Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ New library features
Standard library changes
------------------------

* The `length` function on certain ranges of certain specific element types no longer checks for integer
overflow in most cases. The new function `checked_length` is now available, which will try to use checked
arithmetic to error if the result may be wrapping. Or use a package such as SaferIntegers.jl when
constructing the range. ([#40382])

#### Package Manager

#### LinearAlgebra
Expand Down
25 changes: 9 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,16 @@
Documentation:
[![version 1][docs-img]](https://docs.julialang.org)

Code coverage:
[![coveralls][coveralls-img]](https://coveralls.io/r/JuliaLang/julia?branch=master)
[![codecov][codecov-img]](https://codecov.io/github/JuliaLang/julia?branch=master)

Continuous integration: [![Build status](https://badge.buildkite.com/f28e0d28b345f9fad5856ce6a8d64fffc7c70df8f4f2685cd8.svg?branch=master)](https://buildkite.com/julialang/julia)

[docs-img]: https://img.shields.io/badge/docs-v1-blue.svg
[coveralls-img]: https://img.shields.io/coveralls/github/JuliaLang/julia/master.svg?label=coveralls
[codecov-img]: https://img.shields.io/codecov/c/github/JuliaLang/julia/master.svg?label=codecov


## The Julia Language

Expand Down Expand Up @@ -141,19 +150,3 @@ Supported IDEs include: [julia-vscode](https://github.com/JuliaEditorSupport/jul
Code plugin), [Juno](http://junolab.org/) (Atom plugin). [Jupyter](https://jupyter.org/)
notebooks are available through the [IJulia](https://github.com/JuliaLang/IJulia.jl) package, and
[Pluto](https://github.com/fonsp/Pluto.jl) notebooks through the Pluto.jl package.

## Continuous Integration (CI) Builders

Code coverage:
[![coveralls][coveralls-img]](https://coveralls.io/r/JuliaLang/julia?branch=master)
[![codecov][codecov-img]](https://codecov.io/github/JuliaLang/julia?branch=master)

| Builder | Status |
| ---------- | ------ |
| Overall | [![Build status](https://badge.buildkite.com/f28e0d28b345f9fad5856ce6a8d64fffc7c70df8f4f2685cd8.svg?branch=master)](https://buildkite.com/julialang/julia) |
| analyzegc | [![Build status](https://badge.buildkite.com/f28e0d28b345f9fad5856ce6a8d64fffc7c70df8f4f2685cd8.svg?branch=master&step=analyzegc)](https://buildkite.com/julialang/julia) |
| llvmpasses | [![Build status](https://badge.buildkite.com/f28e0d28b345f9fad5856ce6a8d64fffc7c70df8f4f2685cd8.svg?branch=master&step=llvmpasses)](https://buildkite.com/julialang/julia) |
| coverage | [![Build status](https://badge.buildkite.com/d5ae34dbbf6fefe615300c4f3118bf63cb4a5ae7fd962263c1.svg?branch=master)](https://buildkite.com/julialang/julia-coverage-linux64) |

[coveralls-img]: https://img.shields.io/coveralls/github/JuliaLang/julia/master.svg?label=coveralls
[codecov-img]: https://img.shields.io/codecov/c/github/JuliaLang/julia/master.svg?label=codecov
13 changes: 8 additions & 5 deletions base/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,6 @@ include("refpointer.jl")
include("checked.jl")
using .Checked

# SIMD loops
@pure sizeof(s::String) = Core.sizeof(s) # needed by gensym as called from simdloop
include("simdloop.jl")
using .SimdLoop

# array structures
include("indices.jl")
include("array.jl")
Expand Down Expand Up @@ -177,6 +172,14 @@ using .MultiplicativeInverses
include("abstractarraymath.jl")
include("arraymath.jl")

# SIMD loops
@pure sizeof(s::String) = Core.sizeof(s) # needed by gensym as called from simdloop
include("simdloop.jl")
using .SimdLoop

# functions for AbstractArray with @simd
include("abstractarraypatch.jl")

# map-reduce operators
include("reduce.jl")

Expand Down
124 changes: 34 additions & 90 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,6 @@ axes1(A::AbstractArray{<:Any,0}) = OneTo(1)
axes1(A::AbstractArray) = (@_inline_meta; axes(A)[1])
axes1(iter) = oneto(length(iter))

unsafe_indices(A) = axes(A)
unsafe_indices(r::AbstractRange) = (oneto(unsafe_length(r)),) # Ranges use checked_sub for size

"""
keys(a::AbstractArray)

Expand Down Expand Up @@ -580,14 +577,14 @@ end
function trailingsize(inds::Indices, n)
s = 1
for i=n:length(inds)
s *= unsafe_length(inds[i])
s *= length(inds[i])
end
return s
end
# This version is type-stable even if inds is heterogeneous
function trailingsize(inds::Indices)
@_inline_meta
prod(map(unsafe_length, inds))
prod(map(length, inds))
end

## Bounds checking ##
Expand Down Expand Up @@ -688,7 +685,7 @@ function checkbounds_indices(::Type{Bool}, ::Tuple{}, I::Tuple)
@_inline_meta
checkindex(Bool, OneTo(1), I[1])::Bool & checkbounds_indices(Bool, (), tail(I))
end
checkbounds_indices(::Type{Bool}, IA::Tuple, ::Tuple{}) = (@_inline_meta; all(x->unsafe_length(x)==1, IA))
checkbounds_indices(::Type{Bool}, IA::Tuple, ::Tuple{}) = (@_inline_meta; all(x->length(x)==1, IA))
checkbounds_indices(::Type{Bool}, ::Tuple{}, ::Tuple{}) = true

throw_boundserror(A, I) = (@_noinline_meta; throw(BoundsError(A, I)))
Expand Down Expand Up @@ -886,7 +883,35 @@ function copy!(dst::AbstractArray, src::AbstractArray)
end

## from general iterable to any array

"""
copyto!(dest::AbstractArray, src) -> dest

Copy all elements from collection `src` to array `dest`, whose length must be greater than
or equal to the length `n` of `src`. The first `n` elements of `dest` are overwritten,
the other elements are left untouched.

See also [`copy!`](@ref Base.copy!), [`copy`](@ref).

# Examples
```jldoctest
julia> x = [1., 0., 3., 0., 5.];

julia> y = zeros(7);

julia> copyto!(y, x);

julia> y
7-element Vector{Float64}:
1.0
0.0
3.0
0.0
5.0
0.0
0.0
```
"""
function copyto!(dest::AbstractArray, src)
destiter = eachindex(dest)
y = iterate(destiter)
Expand Down Expand Up @@ -964,87 +989,6 @@ function copyto!(dest::AbstractArray, dstart::Integer, src, sstart::Integer, n::
return dest
end

## copy between abstract arrays - generally more efficient
## since a single index variable can be used.

"""
copyto!(dest::AbstractArray, src) -> dest

Copy all elements from collection `src` to array `dest`, whose length must be greater than
or equal to the length `n` of `src`. The first `n` elements of `dest` are overwritten,
the other elements are left untouched.

See also [`copy!`](@ref Base.copy!), [`copy`](@ref).

# Examples
```jldoctest
julia> x = [1., 0., 3., 0., 5.];

julia> y = zeros(7);

julia> copyto!(y, x);

julia> y
7-element Vector{Float64}:
1.0
0.0
3.0
0.0
5.0
0.0
0.0
```
"""
function copyto!(dest::AbstractArray, src::AbstractArray)
isempty(src) && return dest
src′ = unalias(dest, src)
copyto_unaliased!(IndexStyle(dest), dest, IndexStyle(src′), src′)
end

function copyto!(deststyle::IndexStyle, dest::AbstractArray, srcstyle::IndexStyle, src::AbstractArray)
isempty(src) && return dest
src′ = unalias(dest, src)
copyto_unaliased!(deststyle, dest, srcstyle, src′)
end

function copyto_unaliased!(deststyle::IndexStyle, dest::AbstractArray, srcstyle::IndexStyle, src::AbstractArray)
isempty(src) && return dest
length(dest) >= length(src) || throw(BoundsError(dest, LinearIndices(src)))
if deststyle isa IndexLinear
if srcstyle isa IndexLinear
Δi = firstindex(dest) - firstindex(src)
for i in eachindex(src)
@inbounds dest[i + Δi] = src[i]
end
else
j = firstindex(dest) - 1
@inbounds @simd for I in eachindex(src)
dest[j+=1] = src[I]
end
end
else
if srcstyle isa IndexLinear
i = firstindex(src) - 1
@inbounds @simd for J in eachindex(dest)
dest[J] = src[i+=1]
end
else
iterdest, itersrc = eachindex(dest), eachindex(src)
if iterdest == itersrc
# Shared-iterator implementation
@inbounds @simd for I in itersrc
dest[I] = src[I]
end
else
for (I,J) in zip(itersrc, iterdest)
@inbounds dest[J] = src[I]
end
end
end
end
return dest
end

function copyto!(dest::AbstractArray, dstart::Integer, src::AbstractArray)
copyto!(dest, dstart, src, first(LinearIndices(src)), length(src))
end
Expand Down Expand Up @@ -2497,8 +2441,8 @@ function _sub2ind_recurse(inds, L, ind, i::Integer, I::Integer...)
end

nextL(L, l::Integer) = L*l
nextL(L, r::AbstractUnitRange) = L*unsafe_length(r)
nextL(L, r::Slice) = L*unsafe_length(r.indices)
nextL(L, r::AbstractUnitRange) = L*length(r)
nextL(L, r::Slice) = L*length(r.indices)
offsetin(i, l::Integer) = i-1
offsetin(i, r::AbstractUnitRange) = i-first(r)

Expand All @@ -2524,7 +2468,7 @@ end
_lookup(ind, d::Integer) = ind+1
_lookup(ind, r::AbstractUnitRange) = ind+first(r)
_div(ind, d::Integer) = div(ind, d), 1, d
_div(ind, r::AbstractUnitRange) = (d = unsafe_length(r); (div(ind, d), first(r), d))
_div(ind, r::AbstractUnitRange) = (d = length(r); (div(ind, d), first(r), d))

# Vectorized forms
function _sub2ind(inds::Indices{1}, I1::AbstractVector{T}, I::AbstractVector{T}...) where T<:Integer
Expand Down
55 changes: 55 additions & 0 deletions base/abstractarraypatch.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

## copy between abstract arrays - generally more efficient
## since a single index variable can be used.
## copyto_unaliased! use @simd to speed up, so these definition is seperated from abstractarray.jl

function copyto!(dest::AbstractArray, src::AbstractArray)
isempty(src) && return dest
src′ = unalias(dest, src)
copyto_unaliased!(IndexStyle(dest), dest, IndexStyle(src′), src′)
end

function copyto!(deststyle::IndexStyle, dest::AbstractArray, srcstyle::IndexStyle, src::AbstractArray)
isempty(src) && return dest
src′ = unalias(dest, src)
copyto_unaliased!(deststyle, dest, srcstyle, src′)
end

function copyto_unaliased!(deststyle::IndexStyle, dest::AbstractArray, srcstyle::IndexStyle, src::AbstractArray)
isempty(src) && return dest
length(dest) >= length(src) || throw(BoundsError(dest, LinearIndices(src)))
if deststyle isa IndexLinear
if srcstyle isa IndexLinear
Δi = firstindex(dest) - firstindex(src)
for i in eachindex(src)
@inbounds dest[i + Δi] = src[i]
end
else
j = firstindex(dest) - 1
@inbounds @simd for I in eachindex(src)
dest[j+=1] = src[I]
end
end
else
if srcstyle isa IndexLinear
i = firstindex(src) - 1
@inbounds @simd for J in eachindex(dest)
dest[J] = src[i+=1]
end
else
iterdest, itersrc = eachindex(dest), eachindex(src)
if iterdest == itersrc
# Shared-iterator implementation
@inbounds @simd for I in itersrc
dest[I] = src[I]
end
else
for (I,J) in zip(itersrc, iterdest)
@inbounds dest[J] = src[I]
end
end
end
end
return dest
end
2 changes: 1 addition & 1 deletion base/broadcast.jl
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ an `Int`.
"""
Base.@propagate_inbounds newindex(arg, I::CartesianIndex) = CartesianIndex(_newindex(axes(arg), I.I))
Base.@propagate_inbounds newindex(arg, I::Integer) = CartesianIndex(_newindex(axes(arg), (I,)))
Base.@propagate_inbounds _newindex(ax::Tuple, I::Tuple) = (ifelse(Base.unsafe_length(ax[1])==1, ax[1][1], I[1]), _newindex(tail(ax), tail(I))...)
Base.@propagate_inbounds _newindex(ax::Tuple, I::Tuple) = (ifelse(length(ax[1]) == 1, ax[1][1], I[1]), _newindex(tail(ax), tail(I))...)
Base.@propagate_inbounds _newindex(ax::Tuple{}, I::Tuple) = ()
Base.@propagate_inbounds _newindex(ax::Tuple, I::Tuple{}) = (ax[1][1], _newindex(tail(ax), ())...)
Base.@propagate_inbounds _newindex(ax::Tuple{}, I::Tuple{}) = ()
Expand Down
12 changes: 10 additions & 2 deletions base/checked.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ module Checked

export checked_neg, checked_abs, checked_add, checked_sub, checked_mul,
checked_div, checked_rem, checked_fld, checked_mod, checked_cld,
add_with_overflow, sub_with_overflow, mul_with_overflow
checked_length, add_with_overflow, sub_with_overflow, mul_with_overflow

import Core.Intrinsics:
checked_sadd_int, checked_ssub_int, checked_smul_int, checked_sdiv_int,
checked_srem_int,
checked_uadd_int, checked_usub_int, checked_umul_int, checked_udiv_int,
checked_urem_int
import ..no_op_err, ..@_inline_meta, ..@_noinline_meta
import ..no_op_err, ..@_inline_meta, ..@_noinline_meta, ..checked_length

# define promotion behavior for checked operations
checked_add(x::Integer, y::Integer) = checked_add(promote(x,y)...)
Expand Down Expand Up @@ -349,4 +349,12 @@ The overflow protection may impose a perceptible performance penalty.
"""
checked_cld(x::T, y::T) where {T<:Integer} = cld(x, y) # Base.cld already checks

"""
Base.checked_length(r)

Calculates `length(r)`, but may check for overflow errors where applicable when
the result doesn't fit into `Union{Integer(eltype(r)),Int}`.
"""
checked_length(r) = length(r) # for most things, length doesn't error

end
5 changes: 0 additions & 5 deletions base/compiler/compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,6 @@ add_with_overflow(x::T, y::T) where {T<:SignedInt} = checked_sadd_int(x, y)
add_with_overflow(x::T, y::T) where {T<:UnsignedInt} = checked_uadd_int(x, y)
add_with_overflow(x::Bool, y::Bool) = (x+y, false)

# SIMD loops (The new copyto_unalias! use @simd)
@pure sizeof(s::String) = Core.sizeof(s) # needed by gensym as called from simdloop
include("simdloop.jl")
using .SimdLoop

# core array operations
include("indices.jl")
include("array.jl")
Expand Down
3 changes: 3 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,9 @@ end
@deprecate cat_shape(dims, shape::Tuple{}, shapes::Tuple...) cat_shape(dims, shapes) false
cat_shape(dims, shape::Tuple{}) = () # make sure `cat_shape(dims, ())` do not recursively calls itself

@deprecate unsafe_indices(A) axes(A) false
@deprecate unsafe_length(r) length(r) false

# END 1.6 deprecations

# BEGIN 1.7 deprecations
Expand Down
Loading