Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backports for 1.7-beta2 #41254

Merged
merged 15 commits into from
Jun 18, 2021
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
77 changes: 52 additions & 25 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1635,11 +1635,21 @@ cat_size(A::AbstractArray) = size(A)
cat_size(A, d) = 1
cat_size(A::AbstractArray, d) = size(A, d)

cat_length(::Any) = 1
cat_length(a::AbstractArray) = length(a)

cat_ndims(a) = 0
cat_ndims(a::AbstractArray) = ndims(a)

cat_indices(A, d) = OneTo(1)
cat_indices(A::AbstractArray, d) = axes(A, d)

cat_similar(A, ::Type{T}, shape) where T = Array{T}(undef, shape)
cat_similar(A::AbstractArray, ::Type{T}, shape) where T = similar(A, T, shape)
cat_similar(A, ::Type{T}, shape::Tuple) where T = Array{T}(undef, shape)
cat_similar(A, ::Type{T}, shape::Vector) where T = Array{T}(undef, shape...)
cat_similar(A::Array, ::Type{T}, shape::Tuple) where T = Array{T}(undef, shape)
cat_similar(A::Array, ::Type{T}, shape::Vector) where T = Array{T}(undef, shape...)
cat_similar(A::AbstractArray, T::Type, shape::Tuple) = similar(A, T, shape)
cat_similar(A::AbstractArray, T::Type, shape::Vector) = similar(A, T, shape...)

# These are for backwards compatibility (even though internal)
cat_shape(dims, shape::Tuple{Vararg{Int}}) = shape
Expand Down Expand Up @@ -2034,22 +2044,25 @@ function typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as...) where T
T[rs...;]
end

# nd concatenation
## N-dimensional concatenation ##

"""
hvncat(dim::Int, row_first, values...)
hvncat(dims::Tuple{Vararg{Int}}, row_first, values...)
hvncat(shape::Tuple{Vararg{Tuple}}, row_first, values...)

Horizontal, vertical, and n-dimensional concatenation of many `values` in one call.

This function is called
for block matrix syntax. The first argument either specifies the shape of the concatenation,
similar to `hvcat`, as a tuple of tuples, or the dimensions that specify the key number of
elements along each axis, and is used to determine the output dimensions. The `dims` form
is more performant, and is used by default when the concatenation operation has the same
number of elements along each axis (e.g., [a b; c d;;; e f ; g h]). The `shape` form is used
when the number of elements along each axis is unbalanced (e.g., [a b ; c]). Unbalanced
syntax needs additional validation overhead.
This function is called for block matrix syntax. The first argument either specifies the
shape of the concatenation, similar to `hvcat`, as a tuple of tuples, or the dimensions that
specify the key number of elements along each axis, and is used to determine the output
dimensions. The `dims` form is more performant, and is used by default when the concatenation
operation has the same number of elements along each axis (e.g., [a b; c d;;; e f ; g h]).
The `shape` form is used when the number of elements along each axis is unbalanced
(e.g., [a b ; c]). Unbalanced syntax needs additional validation overhead. The `dim` form
is an optimization for concatenation along just one dimension. `row_first` indicates how
`values` are ordered. The meaning of the first and second elements of `shape` are also
swapped based on `row_first`.

# Examples
```jldoctest
Expand Down Expand Up @@ -2097,6 +2110,24 @@ julia> hvncat(((3, 3), (3, 3), (6,)), true, a, b, c, d, e, f)
[:, :, 2] =
4 5 6
```

# Examples for construction of the arguments:
[a b c ; d e f ;;;
g h i ; j k l ;;;
m n o ; p q r ;;;
s t u ; v w x]
=> dims = (2, 3, 4)

[a b ; c ;;; d ;;;;]
___ _ _
2 1 1 = elements in each row (2, 1, 1)
_______ _
3 1 = elements in each column (3, 1)
_____________
4 = elements in each 3d slice (4,)
_____________
4 = elements in each 4d slice (4,)
=> shape = ((2, 1, 1), (3, 1), (4,), (4,)) with `rowfirst` = true
"""
hvncat(::Tuple{}, ::Bool) = []
hvncat(::Tuple{}, ::Bool, xs...) = []
Expand Down Expand Up @@ -2177,7 +2208,7 @@ function _typed_hvncat(::Type{T}, ::Val{N}, as::AbstractArray...) where {T, N}
end
end

A = Array{T, nd}(undef, ntuple(d -> cat_size(as[1], d), N - 1)..., Ndim, ntuple(x -> 1, nd - N)...)
A = cat_similar(as[1], T, (ntuple(d -> size(as[1], d), N - 1)..., Ndim, ntuple(x -> 1, nd - N)...))
k = 1
for a ∈ as
for i ∈ eachindex(a)
Expand All @@ -2188,9 +2219,6 @@ function _typed_hvncat(::Type{T}, ::Val{N}, as::AbstractArray...) where {T, N}
return A
end

cat_ndims(a) = 0
cat_ndims(a::AbstractArray) = ndims(a)

function _typed_hvncat(::Type{T}, ::Val{N}, as...) where {T, N}
# optimization for scalars and 1-length arrays that can be concatenated by copying them linearly
# into the destination
Expand Down Expand Up @@ -2257,12 +2285,12 @@ function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool,
elseif currentdims[d] < outdims[d] # dimension in progress
break
else # exceeded dimension
ArgumentError("argument $i has too many elements along axis $d") |> throw
throw(ArgumentError("argument $i has too many elements along axis $d"))
end
end
end
elseif currentdims[d1] > outdims[d1] # exceeded dimension
ArgumentError("argument $i has too many elements along axis $d1") |> throw
throw(ArgumentError("argument $i has too many elements along axis $d1"))
end
end

Expand All @@ -2276,7 +2304,7 @@ function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool,
len == outlen || ArgumentError("too many elements in arguments; expected $(outlen), got $(len)") |> throw

# copy into final array
A = Array{T, nd}(undef, outdims...)
A = cat_similar(as[1], T, outdims)
# @assert all(==(0), currentdims)
outdims .= 0
hvncat_fill!(A, currentdims, outdims, d1, d2, as)
Expand Down Expand Up @@ -2308,7 +2336,8 @@ function _typed_hvncat(::Type{T}, shape::Tuple{Vararg{Tuple, N}}, row_first::Boo
if d == 1 || i == 1 || wasstartblock
currentdims[d] += dsize
elseif dsize != cat_size(as[i - 1], ad)
ArgumentError("argument $i has a mismatched number of elements along axis $ad; expected $(cat_size(as[i - 1], ad)), got $dsize") |> throw
throw(ArgumentError("""argument $i has a mismatched number of elements along axis $ad; \
expected $(cat_size(as[i - 1], ad)), got $dsize"""))
end

wasstartblock = blockcounts[d] == 1 # remember for next dimension
Expand All @@ -2318,7 +2347,8 @@ function _typed_hvncat(::Type{T}, shape::Tuple{Vararg{Tuple, N}}, row_first::Boo
if outdims[d] == 0
outdims[d] = currentdims[d]
elseif outdims[d] != currentdims[d]
ArgumentError("argument $i has a mismatched number of elements along axis $ad; expected $(abs(outdims[d] - (currentdims[d] - dsize))), got $dsize") |> throw
throw(ArgumentError("""argument $i has a mismatched number of elements along axis $ad; \
expected $(abs(outdims[d] - (currentdims[d] - dsize))), got $dsize"""))
end
currentdims[d] = 0
blockcounts[d] = 0
Expand All @@ -2335,12 +2365,12 @@ function _typed_hvncat(::Type{T}, shape::Tuple{Vararg{Tuple, N}}, row_first::Boo
# @assert all(==(0), blockcounts)

# copy into final array
A = Array{T, nd}(undef, outdims...)
A = cat_similar(as[1], T, outdims)
hvncat_fill!(A, currentdims, blockcounts, d1, d2, as)
return A
end

function hvncat_fill!(A::Array{T, N}, scratch1::Vector{Int}, scratch2::Vector{Int}, d1::Int, d2::Int, as::Tuple{Vararg}) where {T, N}
function hvncat_fill!(A::AbstractArray{T, N}, scratch1::Vector{Int}, scratch2::Vector{Int}, d1::Int, d2::Int, as::Tuple{Vararg}) where {T, N}
outdims = size(A)
offsets = scratch1
inneroffsets = scratch2
Expand Down Expand Up @@ -2382,9 +2412,6 @@ end
Ai
end

cat_length(a::AbstractArray) = length(a)
cat_length(::Any) = 1

## Reductions and accumulates ##

function isequal(A::AbstractArray, B::AbstractArray)
Expand Down
9 changes: 6 additions & 3 deletions base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1568,6 +1568,10 @@ end

# Query whether the given intrinsic is nothrow

_iszero(x) = x === Intrinsics.xor_int(x, x)
_isneg1(x) = _iszero(Intrinsics.not_int(x))
_istypemin(x) = !_iszero(x) && Intrinsics.neg_int(x) === x

function intrinsic_nothrow(f::IntrinsicFunction, argtypes::Array{Any, 1})
# First check that we have the correct number of arguments
iidx = Int(reinterpret(Int32, f::IntrinsicFunction)) + 1
Expand All @@ -1594,11 +1598,10 @@ function intrinsic_nothrow(f::IntrinsicFunction, argtypes::Array{Any, 1})
return false
end
den_val = argtypes[2].val
den_val !== zero(typeof(den_val)) || return false
_iszero(den_val) && return false
f !== Intrinsics.checked_sdiv_int && return true
# Nothrow as long as we additionally don't do typemin(T)/-1
return den_val !== -1 || (isa(argtypes[1], Const) &&
argtypes[1].val !== typemin(typeof(den_val)))
return !_isneg1(den_val) || (isa(argtypes[1], Const) && !_istypemin(argtypes[1].val))
end
if f === Intrinsics.pointerref
# Nothrow as long as the types are ok. N.B.: dereferencability is not
Expand Down
12 changes: 9 additions & 3 deletions base/experimental.jl
Original file line number Diff line number Diff line change
Expand Up @@ -268,15 +268,21 @@ method tables (e.g., using [`Core.Compiler.OverlayMethodTable`](@ref)).
"""
macro overlay(mt, def)
def = macroexpand(__module__, def) # to expand @inline, @generated, etc
if !isexpr(def, [:function, :(=)]) || !isexpr(def.args[1], :call)
if !isexpr(def, [:function, :(=)])
error("@overlay requires a function Expr")
end
if isexpr(def.args[1], :call)
def.args[1].args[1] = Expr(:overlay, mt, def.args[1].args[1])
elseif isexpr(def.args[1], :where)
def.args[1].args[1].args[1] = Expr(:overlay, mt, def.args[1].args[1].args[1])
else
error("@overlay requires a function Expr")
end
def.args[1].args[1] = Expr(:overlay, mt, def.args[1].args[1])
esc(def)
end

let new_mt(name::Symbol, mod::Module) = begin
ccall(:jl_check_top_level_effect, Cvoid, (Any, Cstring), mod, name)
ccall(:jl_check_top_level_effect, Cvoid, (Any, Cstring), mod, "@MethodTable")
ccall(:jl_new_method_table, Any, (Any, Any), name, mod)
end
@eval macro MethodTable(name::Symbol)
Expand Down
2 changes: 1 addition & 1 deletion base/expr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ function make_atomic(order, ex)
elseif isexpr(ex, :call, 3)
return make_atomic(order, ex.args[2], ex.args[1], ex.args[3])
elseif ex.head === :(=)
l, r = ex.args[1], ex.args[2]
l, r = ex.args[1], esc(ex.args[2])
if is_expr(l, :., 2)
ll, lr = esc(l.args[1]), esc(l.args[2])
return :(setproperty!($ll, $lr, $r, $order))
Expand Down
4 changes: 3 additions & 1 deletion base/range.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1217,7 +1217,9 @@ function sum(r::AbstractRange{<:Real})
end

function _in_range(x, r::AbstractRange)
if step(r) == 0
if !isfinite(x)
return false
elseif iszero(step(r))
return !isempty(r) && first(r) == x
else
n = round(Integer, (x - first(r)) / step(r)) + 1
Expand Down
7 changes: 4 additions & 3 deletions base/rational.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,22 @@ unsafe_rational(num::T, den::T) where {T<:Integer} = unsafe_rational(T, num, den
unsafe_rational(num::Integer, den::Integer) = unsafe_rational(promote(num, den)...)

@noinline __throw_rational_argerror_typemin(T) = throw(ArgumentError("invalid rational: denominator can't be typemin($T)"))
function checked_den(num::T, den::T) where T<:Integer
function checked_den(::Type{T}, num::T, den::T) where T<:Integer
if signbit(den)
den = -den
signbit(den) && __throw_rational_argerror_typemin(T)
signbit(den) && __throw_rational_argerror_typemin(typeof(den))
num = -num
end
return unsafe_rational(T, num, den)
end
checked_den(num::T, den::T) where T<:Integer = checked_den(T, num, den)
checked_den(num::Integer, den::Integer) = checked_den(promote(num, den)...)

@noinline __throw_rational_argerror_zero(T) = throw(ArgumentError("invalid rational: zero($T)//zero($T)"))
function Rational{T}(num::Integer, den::Integer) where T<:Integer
iszero(den) && iszero(num) && __throw_rational_argerror_zero(T)
num, den = divgcd(num, den)
return checked_den(T(num), T(den))
return checked_den(T, T(num), T(den))
end

Rational(n::T, d::T) where {T<:Integer} = Rational{T}(n, d)
Expand Down
2 changes: 1 addition & 1 deletion base/strings/search.jl
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ function _rsearchindex(s::AbstractVector{<:Union{Int8,UInt8}}, t::AbstractVector
n = length(t)
m = length(s)
k = Int(_k) - sentinel
k < 1 && throw(BoundsError(s, _k))
k < 0 && throw(BoundsError(s, _k))

if n == 0
return 0 <= k <= m ? max(k, 1) : sentinel
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
77b9bf19937476f9b2120dfbafc3322b
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c9079f0c2b4d6ad34eca479f4db14041ac04f0780feaa1b16de552e55ca862f0d56c9a50437304639b96777a2c941c4b7a5eb0ce23071a456126a5c2da23c2e1

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
4c09536f4f769b23e88fee769f5a09bd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
e409fa943a9683a129b80c78ef74572df316ed414dfc8c208f1500d0f07d4d41870d44654446e2c20d1b9ed11e62c4fc6107b6e5789939edbd049fc2aaf22f63
Loading