From 1b35e95401dd13f2813e82c261ddfb67d2349da6 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Fri, 11 Jun 2021 13:20:55 -0400 Subject: [PATCH 01/26] Better handling of 0- and 1-length dims/shape args --- base/abstractarray.jl | 44 +++++++++++++++++++++++++----------- test/abstractarray.jl | 52 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 82 insertions(+), 14 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 96b1b834e7d43..444832491093d 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2140,8 +2140,6 @@ _hvncat(dimsshape::Union{Tuple, Int}, row_first::Bool, xs::AbstractArray...) = _ _hvncat(dimsshape::Union{Tuple, Int}, row_first::Bool, xs::AbstractArray{T}...) where T = _typed_hvncat(T, dimsshape, row_first, xs...) typed_hvncat(::Type{T}, ::Tuple{}, ::Bool) where T = Vector{T}() -typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, xs...) where T = Vector{T}() -typed_hvncat(T::Type, ::Tuple{Vararg{Any, 1}}, ::Bool, xs...) = typed_vcat(T, xs...) # methods assume 2+ dimensions typed_hvncat(T::Type, dimsshape::Tuple, row_first::Bool, xs...) = _typed_hvncat(T, dimsshape, row_first, xs...) typed_hvncat(T::Type, dim::Int, xs...) = _typed_hvncat(T, Val(dim), xs...) @@ -2151,17 +2149,19 @@ _typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, xs::Number...) where T = Vector{T}() function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool, xs::Number...) where {T, N} A = Array{T, N}(undef, dims...) lengtha = length(A) # Necessary to store result because throw blocks are being deoptimized right now, which leads to excessive allocations - lengthx = length(xs) # Cuts from 3 allocations to 1. +# 1-dimensional hvncat methods if lengtha != lengthx throw(ArgumentError("argument count does not match specified shape (expected $lengtha, got $lengthx)")) - end - hvncat_fill!(A, row_first, xs) - return A -end - -function hvncat_fill!(A::Array, row_first::Bool, xs::Tuple) - # putting these in separate functions leads to unnecessary allocations - if row_first +_typed_hvncat(::Type{T}, ::Val{0}, x) where T = fill(T(x)) +_typed_hvncat(::Type{T}, ::Val{0}, x::AbstractArray) where T = T.(x) +_typed_hvncat(::Type, ::Val{0}, ::AbstractArray...) = + throw(ArgumentError("a 0-dimensional array may not have more than one element")) +_typed_hvncat(::Type, ::Val{0}, ::Any...) = + throw(ArgumentError("a 0-dimensional array may not have more than one element")) + +_typed_hvncat(::Type{T}, ::Val{N}) where {T, N} = + (N < 0 && throw(ArgumentError("concatenation dimension must be nonnegative"))) || + Vector{T}() nr, nc = size(A, 1), size(A, 2) nrc = nr * nc na = prod(size(A)[3:end]) @@ -2246,7 +2246,17 @@ function _typed_hvncat(::Type{T}, ::Val{N}, as...) where {T, N} return A end -function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool, as...) where {T, N} + +# 0-dimensional cases for balanced and unbalanced hvncat methods + +_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x) where T = fill(T(x)) +_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::Number) where T = fill(T(x)) +_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::AbstractArray) where T = T.(x) +_typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Number...) = + throw(ArgumentError("a 0-dimensional array may not have more than one element")) +_typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Any...) = + throw(ArgumentError("a 0-dimensional array may not have more than one element")) + d1 = row_first ? 2 : 1 d2 = row_first ? 1 : 2 @@ -2308,7 +2318,15 @@ function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool, return A end -function _typed_hvncat(::Type{T}, shape::Tuple{Vararg{Tuple, N}}, row_first::Bool, as...) where {T, N} + +# unbalanced dimensions hvncat methods + +_typed_hvncat(T::Type, shape::Tuple{Tuple}, row_first::Bool, xs...) = + (length(shape[1]) == 0 && + throw(ArgumentError("each level of `shape` argument must have at least one value"))) || + _typed_hvncat_1d(T, shape[1][1], Val(row_first), xs...) + +function _typed_hvncat(T::Type, shape::NTuple{N, Tuple}, row_first::Bool, as...) where {N} d1 = row_first ? 2 : 1 d2 = row_first ? 1 : 2 shape = collect(shape) # saves allocations later diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 65f9f4efa2cd3..49f75a38049dc 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1342,6 +1342,7 @@ end end end +import Base.typed_hvncat @testset "hvncat" begin a = fill(1, (2,3,2,4,5)) b = fill(2, (1,1,2,4,5)) @@ -1389,7 +1390,56 @@ end @test [v v;;; fill(v, 1, 2)] == fill(v, 1, 2, 2) end - @test_throws BoundsError hvncat(((1, 2), (3,)), false, zeros(Int, 0, 0, 0), 7, 8) + # 0-dimension behaviors + @test hvncat(0) == [] + @test hvncat(0, 1) == fill(1) + @test hvncat(0, [1]) == [1] + @test_throws ArgumentError hvncat(0, 1, 1) + @test typed_hvncat(Float64, 0) == Float64[] + @test typed_hvncat(Float64, 0, 1) == fill(1.0) + @test typed_hvncat(Float64, 0, [1]) == Float64[1.0] + @test_throws ArgumentError typed_hvncat(Float64, 0, 1, 1) + @test hvncat((), true) == [] + @test hvncat((), true, 1) == fill(1) + @test hvncat((), true, [1]) == [1] + @test_throws ArgumentError hvncat((), true, 1, 1) + @test typed_hvncat(Float64, (), true) == Float64[] + @test typed_hvncat(Float64, (), true, 1) == fill(1.0) + @test typed_hvncat(Float64, (), true, [1]) == [1.0] + @test_throws ArgumentError typed_hvncat(Float64, (), true, 1, 1) + + # 1-dimension behaviors + # int form + @test hvncat(1) == [] + @test hvncat(1, 1) == [1] + @test hvncat(1, [1]) == [1] + @test hvncat(1, 1, 1) == [1 ; 1] + @test typed_hvncat(Float64, 1) == Float64[] + @test typed_hvncat(Float64, 1, 1) == Float64[1.0] + @test typed_hvncat(Float64, 1, [1]) == Float64[1.0] + @test typed_hvncat(Float64, 1, 1, 1) == Float64[1.0 ; 1.0] + # dims form + @test_throws ArgumentError hvncat((1,), true) + @test hvncat((2,), true, 1, 1) == [1; 1] + @test hvncat((2,), true, [1], [1]) == [1; 1] + @test_throws ArgumentError hvncat((2,), true, 1) + @test typed_hvncat(Float64, (2,), true, 1, 1) == Float64[1.0; 1.0] + @test typed_hvncat(Float64, (2,), true, [1], [1]) == Float64[1.0; 1.0] + @test_throws ArgumentError typed_hvncat(Float64, (2,), true, 1) + # row_first has no effect with just one dimension of the dims form + @test hvncat((2,), false, 1, 1) == [1; 1] + @test typed_hvncat(Float64, (2,), false, 1, 1) == Float64[1.0; 1.0] + # shape form + @test hvncat(((2,),), true, 1, 1) == [1 1] + @test hvncat(((2,),), true, [1], [1]) == [1 1] + @test_throws ArgumentError hvncat(((2,),), true, 1) + @test hvncat(((2,),), false, 1, 1) == [1; 1] + @test hvncat(((2,),), false, [1], [1]) == [1; 1] + @test typed_hvncat(Float64, ((2,),), true, 1, 1) == Float64[1.0 1.0] + @test typed_hvncat(Float64, ((2,),), true, [1], [1]) == Float64[1.0 1.0] + @test_throws ArgumentError typed_hvncat(Float64, ((2,),), true, 1) + @test typed_hvncat(Float64, ((2,),), false, 1, 1) == Float64[1.0; 1.0] + @test typed_hvncat(Float64, ((2,),), false, [1], [1]) == Float64[1.0; 1.0] end @testset "keepat!" begin From b25b530575e8728d8886333a83e97bc30f60a42c Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Fri, 11 Jun 2021 13:29:29 -0400 Subject: [PATCH 02/26] Fixed git lines screwup --- base/abstractarray.jl | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 444832491093d..20884b1470cb0 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2143,15 +2143,8 @@ typed_hvncat(::Type{T}, ::Tuple{}, ::Bool) where T = Vector{T}() typed_hvncat(T::Type, dimsshape::Tuple, row_first::Bool, xs...) = _typed_hvncat(T, dimsshape, row_first, xs...) typed_hvncat(T::Type, dim::Int, xs...) = _typed_hvncat(T, Val(dim), xs...) -_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool) where T = Vector{T}() -_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, xs...) where T = Vector{T}() -_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, xs::Number...) where T = Vector{T}() -function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool, xs::Number...) where {T, N} - A = Array{T, N}(undef, dims...) - lengtha = length(A) # Necessary to store result because throw blocks are being deoptimized right now, which leads to excessive allocations # 1-dimensional hvncat methods - if lengtha != lengthx - throw(ArgumentError("argument count does not match specified shape (expected $lengtha, got $lengthx)")) + _typed_hvncat(::Type{T}, ::Val{0}, x) where T = fill(T(x)) _typed_hvncat(::Type{T}, ::Val{0}, x::AbstractArray) where T = T.(x) _typed_hvncat(::Type, ::Val{0}, ::AbstractArray...) = @@ -2162,6 +2155,25 @@ _typed_hvncat(::Type, ::Val{0}, ::Any...) = _typed_hvncat(::Type{T}, ::Val{N}) where {T, N} = (N < 0 && throw(ArgumentError("concatenation dimension must be nonnegative"))) || Vector{T}() + +_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool) where T = Vector{T}() +_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, xs...) where T = Vector{T}() +_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, xs::Number...) where T = Vector{T}() + +function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool, xs::Number...) where {T, N} + A = Array{T, N}(undef, dims...) + lengtha = length(A) # Necessary to store result because throw blocks are being deoptimized right now, which leads to excessive allocations + lengthx = length(xs) # Cuts from 3 allocations to 1. + if lengtha != lengthx + throw(ArgumentError("argument count does not match specified shape (expected $lengtha, got $lengthx)")) + end + hvncat_fill!(A, row_first, xs) + return A +end + +function hvncat_fill!(A::Array, row_first::Bool, xs::Tuple) + # putting these in separate functions leads to unnecessary allocations + if row_first nr, nc = size(A, 1), size(A, 2) nrc = nr * nc na = prod(size(A)[3:end]) @@ -2257,6 +2269,7 @@ _typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Number...) = _typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Any...) = throw(ArgumentError("a 0-dimensional array may not have more than one element")) +function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool, as...) where {T, N} d1 = row_first ? 2 : 1 d2 = row_first ? 1 : 2 From ec59c12ab0b33206b239216442c010cf057f1d9d Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Fri, 11 Jun 2021 16:03:11 -0400 Subject: [PATCH 03/26] Restored missing bits --- base/abstractarray.jl | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 20884b1470cb0..af730e1da6c7c 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2146,6 +2146,7 @@ typed_hvncat(T::Type, dim::Int, xs...) = _typed_hvncat(T, Val(dim), xs...) # 1-dimensional hvncat methods _typed_hvncat(::Type{T}, ::Val{0}, x) where T = fill(T(x)) +_typed_hvncat(::Type{T}, ::Val{0}, x::Number) where T = fill(T(x)) _typed_hvncat(::Type{T}, ::Val{0}, x::AbstractArray) where T = T.(x) _typed_hvncat(::Type, ::Val{0}, ::AbstractArray...) = throw(ArgumentError("a 0-dimensional array may not have more than one element")) @@ -2156,9 +2157,16 @@ _typed_hvncat(::Type{T}, ::Val{N}) where {T, N} = (N < 0 && throw(ArgumentError("concatenation dimension must be nonnegative"))) || Vector{T}() +# 0-dimensional cases for balanced and unbalanced hvncat methods + _typed_hvncat(::Type{T}, ::Tuple{}, ::Bool) where T = Vector{T}() -_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, xs...) where T = Vector{T}() -_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, xs::Number...) where T = Vector{T}() +_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x) where T = fill(T(x)) +_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::Number) where T = fill(T(x)) +_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::AbstractArray) where T = T.(x) +_typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Number...) = + throw(ArgumentError("a 0-dimensional array may not have more than one element")) +_typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Any...) = + throw(ArgumentError("a 0-dimensional array may not have more than one element")) function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool, xs::Number...) where {T, N} A = Array{T, N}(undef, dims...) @@ -2269,6 +2277,22 @@ _typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Number...) = _typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Any...) = throw(ArgumentError("a 0-dimensional array may not have more than one element")) +# balanced dimensions hvncat methods + +_typed_hvncat(T::Type, dims::Tuple{Int}, ::Bool, as...) = _typed_hvncat_1d(T, dims[1], Val(false), as...) +_typed_hvncat(T::Type, dims::Tuple{Int}, ::Bool, as::Number...) = _typed_hvncat_1d(T, dims[1], Val(false), as...) + +function _typed_hvncat_1d(::Type{T}, ds::Int, ::Val{row_first}, as...) where {T, row_first} + lengthas = length(as) + ds > 0 || + throw(ArgumentError("`dimsshape` argument must consist of positive integers")) + lengthas == ds || + throw(ArgumentError("number of elements does not match `dimshape` argument; expected $ds, got $lengthas")) + return row_first ? + _typed_hvncat(T, Val(2), as...) : + _typed_hvncat(T, Val(1), as...) +end + function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool, as...) where {T, N} d1 = row_first ? 2 : 1 d2 = row_first ? 1 : 2 From a80a5222b3657fc4e302a58f8c58197502c40316 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Fri, 11 Jun 2021 18:44:52 -0400 Subject: [PATCH 04/26] T.() => convert.() --- base/abstractarray.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index af730e1da6c7c..27a77c74b6c56 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2162,7 +2162,7 @@ _typed_hvncat(::Type{T}, ::Val{N}) where {T, N} = _typed_hvncat(::Type{T}, ::Tuple{}, ::Bool) where T = Vector{T}() _typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x) where T = fill(T(x)) _typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::Number) where T = fill(T(x)) -_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::AbstractArray) where T = T.(x) +_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::AbstractArray) where T = convert.(T, x) _typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Number...) = throw(ArgumentError("a 0-dimensional array may not have more than one element")) _typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Any...) = @@ -2271,7 +2271,7 @@ end _typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x) where T = fill(T(x)) _typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::Number) where T = fill(T(x)) -_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::AbstractArray) where T = T.(x) +_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::AbstractArray) where T = convert.(T, x) _typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Number...) = throw(ArgumentError("a 0-dimensional array may not have more than one element")) _typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Any...) = From e73244c96516f3443a6024b8555a4510c01a14f4 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Fri, 11 Jun 2021 18:47:53 -0400 Subject: [PATCH 05/26] error suggestion --- base/abstractarray.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 27a77c74b6c56..9f5698979dca3 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2149,9 +2149,9 @@ _typed_hvncat(::Type{T}, ::Val{0}, x) where T = fill(T(x)) _typed_hvncat(::Type{T}, ::Val{0}, x::Number) where T = fill(T(x)) _typed_hvncat(::Type{T}, ::Val{0}, x::AbstractArray) where T = T.(x) _typed_hvncat(::Type, ::Val{0}, ::AbstractArray...) = - throw(ArgumentError("a 0-dimensional array may not have more than one element")) + throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) _typed_hvncat(::Type, ::Val{0}, ::Any...) = - throw(ArgumentError("a 0-dimensional array may not have more than one element")) + throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) _typed_hvncat(::Type{T}, ::Val{N}) where {T, N} = (N < 0 && throw(ArgumentError("concatenation dimension must be nonnegative"))) || @@ -2164,9 +2164,9 @@ _typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x) where T = fill(T(x)) _typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::Number) where T = fill(T(x)) _typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::AbstractArray) where T = convert.(T, x) _typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Number...) = - throw(ArgumentError("a 0-dimensional array may not have more than one element")) + throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) _typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Any...) = - throw(ArgumentError("a 0-dimensional array may not have more than one element")) + throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool, xs::Number...) where {T, N} A = Array{T, N}(undef, dims...) @@ -2273,9 +2273,9 @@ _typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x) where T = fill(T(x)) _typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::Number) where T = fill(T(x)) _typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::AbstractArray) where T = convert.(T, x) _typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Number...) = - throw(ArgumentError("a 0-dimensional array may not have more than one element")) + throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) _typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Any...) = - throw(ArgumentError("a 0-dimensional array may not have more than one element")) + throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) # balanced dimensions hvncat methods From c5f3497b59b1d5fb8aa247b75ed16be4ccfdbd89 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Fri, 11 Jun 2021 18:48:05 -0400 Subject: [PATCH 06/26] style suggestion --- base/abstractarray.jl | 17 ++++++++++------- test/abstractarray.jl | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 9f5698979dca3..9e5dcecc05208 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2288,9 +2288,11 @@ function _typed_hvncat_1d(::Type{T}, ds::Int, ::Val{row_first}, as...) where {T, throw(ArgumentError("`dimsshape` argument must consist of positive integers")) lengthas == ds || throw(ArgumentError("number of elements does not match `dimshape` argument; expected $ds, got $lengthas")) - return row_first ? - _typed_hvncat(T, Val(2), as...) : - _typed_hvncat(T, Val(1), as...) + if row_first + return _typed_hvncat(T, Val(2), as...) + else + return _typed_hvncat(T, Val(1), as...) + end end function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool, as...) where {T, N} @@ -2358,10 +2360,11 @@ end # unbalanced dimensions hvncat methods -_typed_hvncat(T::Type, shape::Tuple{Tuple}, row_first::Bool, xs...) = - (length(shape[1]) == 0 && - throw(ArgumentError("each level of `shape` argument must have at least one value"))) || - _typed_hvncat_1d(T, shape[1][1], Val(row_first), xs...) +function _typed_hvncat(T::Type, shape::Tuple{Tuple}, row_first::Bool, xs...) + if (length(shape[1]) == 0 + throw(ArgumentError("each level of `shape` argument must have at least one value"))) + return _typed_hvncat_1d(T, shape[1][1], Val(row_first), xs...) +end function _typed_hvncat(T::Type, shape::NTuple{N, Tuple}, row_first::Bool, as...) where {N} d1 = row_first ? 2 : 1 diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 49f75a38049dc..96699d43f9c02 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1342,7 +1342,7 @@ end end end -import Base.typed_hvncat +using Base.typed_hvncat @testset "hvncat" begin a = fill(1, (2,3,2,4,5)) b = fill(2, (1,1,2,4,5)) From c724b9306d298297b2a44855a2f5ec886b028aea Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Fri, 11 Jun 2021 21:00:52 -0400 Subject: [PATCH 07/26] Removed duplicated methods --- base/abstractarray.jl | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 9e5dcecc05208..40cdb8cf389ed 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2157,17 +2157,6 @@ _typed_hvncat(::Type{T}, ::Val{N}) where {T, N} = (N < 0 && throw(ArgumentError("concatenation dimension must be nonnegative"))) || Vector{T}() -# 0-dimensional cases for balanced and unbalanced hvncat methods - -_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool) where T = Vector{T}() -_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x) where T = fill(T(x)) -_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::Number) where T = fill(T(x)) -_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::AbstractArray) where T = convert.(T, x) -_typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Number...) = - throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) -_typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Any...) = - throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) - function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool, xs::Number...) where {T, N} A = Array{T, N}(undef, dims...) lengtha = length(A) # Necessary to store result because throw blocks are being deoptimized right now, which leads to excessive allocations @@ -2205,7 +2194,6 @@ function hvncat_fill!(A::Array, row_first::Bool, xs::Tuple) end _typed_hvncat(T::Type, dim::Int, ::Bool, xs...) = _typed_hvncat(T, Val(dim), xs...) # catches from _hvncat type promoters -_typed_hvncat(::Type{T}, ::Val) where T = Vector{T}() _typed_hvncat(T::Type, ::Val{N}, xs::Number...) where N = _typed_hvncat(T, (ntuple(x -> 1, N - 1)..., length(xs)), false, xs...) function _typed_hvncat(::Type{T}, ::Val{N}, as::AbstractArray...) where {T, N} # optimization for arrays that can be concatenated by copying them linearly into the destination @@ -2277,6 +2265,7 @@ _typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Number...) = _typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Any...) = throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) + # balanced dimensions hvncat methods _typed_hvncat(T::Type, dims::Tuple{Int}, ::Bool, as...) = _typed_hvncat_1d(T, dims[1], Val(false), as...) From cc6cd7ef379a282082fab277d285fedff676f0d1 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Fri, 11 Jun 2021 21:01:12 -0400 Subject: [PATCH 08/26] T => convert --- base/abstractarray.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 40cdb8cf389ed..9756349e7ce5c 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2257,8 +2257,8 @@ end # 0-dimensional cases for balanced and unbalanced hvncat methods -_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x) where T = fill(T(x)) -_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::Number) where T = fill(T(x)) +_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x) where T = fill(convert(T, x)) +_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::Number) where T = fill(convert(T, x)) _typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::AbstractArray) where T = convert.(T, x) _typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Number...) = throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) From af6b44ce2fcc31a9a6c7ec024a44be3f5da2901d Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Fri, 11 Jun 2021 21:06:10 -0400 Subject: [PATCH 09/26] Fix parentheses --- base/abstractarray.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 9756349e7ce5c..554d267bf733f 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2350,8 +2350,8 @@ end # unbalanced dimensions hvncat methods function _typed_hvncat(T::Type, shape::Tuple{Tuple}, row_first::Bool, xs...) - if (length(shape[1]) == 0 - throw(ArgumentError("each level of `shape` argument must have at least one value"))) + if length(shape[1]) == 0 + throw(ArgumentError("each level of `shape` argument must have at least one value")) return _typed_hvncat_1d(T, shape[1][1], Val(row_first), xs...) end From a8d71bc1149f60e6c1c1f5fa0c3b90b1e576dce5 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Fri, 11 Jun 2021 21:12:26 -0400 Subject: [PATCH 10/26] fix function --- base/abstractarray.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 554d267bf733f..dd6b18b30ff3a 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2350,7 +2350,7 @@ end # unbalanced dimensions hvncat methods function _typed_hvncat(T::Type, shape::Tuple{Tuple}, row_first::Bool, xs...) - if length(shape[1]) == 0 + length(shape[1]) > 0 || throw(ArgumentError("each level of `shape` argument must have at least one value")) return _typed_hvncat_1d(T, shape[1][1], Val(row_first), xs...) end From b4cfd435b62eef8e48b912ce90b14d90657834c1 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Fri, 11 Jun 2021 22:40:53 -0400 Subject: [PATCH 11/26] Fix ambiguity --- base/abstractarray.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index dd6b18b30ff3a..747e86efc2c9f 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2148,9 +2148,11 @@ typed_hvncat(T::Type, dim::Int, xs...) = _typed_hvncat(T, Val(dim), xs...) _typed_hvncat(::Type{T}, ::Val{0}, x) where T = fill(T(x)) _typed_hvncat(::Type{T}, ::Val{0}, x::Number) where T = fill(T(x)) _typed_hvncat(::Type{T}, ::Val{0}, x::AbstractArray) where T = T.(x) -_typed_hvncat(::Type, ::Val{0}, ::AbstractArray...) = - throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) -_typed_hvncat(::Type, ::Val{0}, ::Any...) = +_typed_hvncat(::Type, ::Val{0}, ::Number...) = _typed_hvncat_0d_too_many() +_typed_hvncat(::Type, ::Val{0}, ::AbstractArray...) = _typed_hvncat_0d_too_many() +_typed_hvncat(::Type, ::Val{0}, ::Any...) = _typed_hvncat_0d_too_many() + +_typed_hvncat_0d_too_many() = throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) _typed_hvncat(::Type{T}, ::Val{N}) where {T, N} = From 632ef9b1564d46d49d4a4b63b56106495088dd61 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Fri, 11 Jun 2021 22:45:05 -0400 Subject: [PATCH 12/26] whitespace fix --- base/abstractarray.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 747e86efc2c9f..f4d117aa680b4 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2151,7 +2151,7 @@ _typed_hvncat(::Type{T}, ::Val{0}, x::AbstractArray) where T = T.(x) _typed_hvncat(::Type, ::Val{0}, ::Number...) = _typed_hvncat_0d_too_many() _typed_hvncat(::Type, ::Val{0}, ::AbstractArray...) = _typed_hvncat_0d_too_many() _typed_hvncat(::Type, ::Val{0}, ::Any...) = _typed_hvncat_0d_too_many() - + _typed_hvncat_0d_too_many() = throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) From a8c5d6ee26ac4384157f57b46a3aaf2efedb1f44 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Fri, 11 Jun 2021 23:55:55 -0400 Subject: [PATCH 13/26] Ambiguity and more T => convert --- base/abstractarray.jl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index f4d117aa680b4..e8ad8354c917b 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2145,12 +2145,13 @@ typed_hvncat(T::Type, dim::Int, xs...) = _typed_hvncat(T, Val(dim), xs...) # 1-dimensional hvncat methods -_typed_hvncat(::Type{T}, ::Val{0}, x) where T = fill(T(x)) -_typed_hvncat(::Type{T}, ::Val{0}, x::Number) where T = fill(T(x)) -_typed_hvncat(::Type{T}, ::Val{0}, x::AbstractArray) where T = T.(x) +_typed_hvncat(::Type{T}, ::Val{0}) = Vector{T}() +_typed_hvncat(::Type{T}, ::Val{0}, x) where T = fill(convert(T, x)) +_typed_hvncat(::Type{T}, ::Val{0}, x::Number) where T = fill(convert(T, x)) +_typed_hvncat(::Type{T}, ::Val{0}, x::AbstractArray) where T = convert.(T, x) +_typed_hvncat(::Type, ::Val{0}, ::Any...) = _typed_hvncat_0d_too_many() _typed_hvncat(::Type, ::Val{0}, ::Number...) = _typed_hvncat_0d_too_many() _typed_hvncat(::Type, ::Val{0}, ::AbstractArray...) = _typed_hvncat_0d_too_many() -_typed_hvncat(::Type, ::Val{0}, ::Any...) = _typed_hvncat_0d_too_many() _typed_hvncat_0d_too_many() = throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) From cd55f21214a4847fde7a15a3ab868beb7dd2cb34 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 12 Jun 2021 00:06:56 -0400 Subject: [PATCH 14/26] fix type parameter --- base/abstractarray.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index e8ad8354c917b..326f96da044bb 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2145,7 +2145,7 @@ typed_hvncat(T::Type, dim::Int, xs...) = _typed_hvncat(T, Val(dim), xs...) # 1-dimensional hvncat methods -_typed_hvncat(::Type{T}, ::Val{0}) = Vector{T}() +_typed_hvncat(::Type{T}, ::Val{0}) where T = Vector{T}() _typed_hvncat(::Type{T}, ::Val{0}, x) where T = fill(convert(T, x)) _typed_hvncat(::Type{T}, ::Val{0}, x::Number) where T = fill(convert(T, x)) _typed_hvncat(::Type{T}, ::Val{0}, x::AbstractArray) where T = convert.(T, x) From 415fe8406a359a1bb806fd6542fc1bcdbe54c745 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 12 Jun 2021 08:12:32 -0400 Subject: [PATCH 15/26] fix using --- test/abstractarray.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 96699d43f9c02..b733b40ec66e5 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1342,7 +1342,7 @@ end end end -using Base.typed_hvncat +using Base: typed_hvncat @testset "hvncat" begin a = fill(1, (2,3,2,4,5)) b = fill(2, (1,1,2,4,5)) From be7d439865fc33658250c61670a7204f79aa6165 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 12 Jun 2021 08:26:38 -0400 Subject: [PATCH 16/26] Belonged in other PR --- base/abstractarray.jl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 326f96da044bb..d19bd3480950c 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2156,9 +2156,7 @@ _typed_hvncat(::Type, ::Val{0}, ::AbstractArray...) = _typed_hvncat_0d_too_many( _typed_hvncat_0d_too_many() = throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) -_typed_hvncat(::Type{T}, ::Val{N}) where {T, N} = - (N < 0 && throw(ArgumentError("concatenation dimension must be nonnegative"))) || - Vector{T}() +_typed_hvncat(::Type{T}, ::Val{N}) where {T, N} = Vector{T}() function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool, xs::Number...) where {T, N} A = Array{T, N}(undef, dims...) From e114402a2bb8632d2b2718487161d7f8b8675b60 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 12 Jun 2021 09:33:35 -0400 Subject: [PATCH 17/26] Removed method leading to unintended recurssion. --- base/abstractarray.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index d19bd3480950c..fb51bb31dac42 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2195,7 +2195,6 @@ function hvncat_fill!(A::Array, row_first::Bool, xs::Tuple) end _typed_hvncat(T::Type, dim::Int, ::Bool, xs...) = _typed_hvncat(T, Val(dim), xs...) # catches from _hvncat type promoters -_typed_hvncat(T::Type, ::Val{N}, xs::Number...) where N = _typed_hvncat(T, (ntuple(x -> 1, N - 1)..., length(xs)), false, xs...) function _typed_hvncat(::Type{T}, ::Val{N}, as::AbstractArray...) where {T, N} # optimization for arrays that can be concatenated by copying them linearly into the destination # conditions: the elements must all have 1- or 0-length dimensions above N From aa80b4077eaac159437be04e1fc82c65b29f74d3 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 12 Jun 2021 10:31:15 -0400 Subject: [PATCH 18/26] Pass through to later checks --- base/abstractarray.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index fb51bb31dac42..454426214e176 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2128,11 +2128,10 @@ julia> hvncat(((3, 3), (3, 3), (6,)), true, a, b, c, d, e, f) """ hvncat(::Tuple{}, ::Bool) = [] hvncat(::Tuple{}, ::Bool, xs...) = [] -hvncat(::Tuple{Vararg{Any, 1}}, ::Bool, xs...) = vcat(xs...) # methods assume 2+ dimensions hvncat(dimsshape::Tuple, row_first::Bool, xs...) = _hvncat(dimsshape, row_first, xs...) hvncat(dim::Int, xs...) = _hvncat(dim, true, xs...) -_hvncat(::Union{Tuple, Int}, ::Bool) = [] +_hvncat(dimsshape::Union{Tuple, Int}, row_first::Bool) = _typed_hvncat(Any, dimsshape, row_first) _hvncat(dimsshape::Union{Tuple, Int}, row_first::Bool, xs...) = _typed_hvncat(promote_eltypeof(xs...), dimsshape, row_first, xs...) _hvncat(dimsshape::Union{Tuple, Int}, row_first::Bool, xs::T...) where T<:Number = _typed_hvncat(T, dimsshape, row_first, xs...) _hvncat(dimsshape::Union{Tuple, Int}, row_first::Bool, xs::Number...) = _typed_hvncat(promote_typeof(xs...), dimsshape, row_first, xs...) From 77c078d93a626348811a671449a47564fcb31747 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 12 Jun 2021 16:29:44 -0400 Subject: [PATCH 19/26] pass through first function --- base/abstractarray.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 454426214e176..37391106ac09f 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2127,7 +2127,6 @@ julia> hvncat(((3, 3), (3, 3), (6,)), true, a, b, c, d, e, f) => shape = ((2, 1, 1), (3, 1), (4,), (4,)) with `rowfirst` = true """ hvncat(::Tuple{}, ::Bool) = [] -hvncat(::Tuple{}, ::Bool, xs...) = [] hvncat(dimsshape::Tuple, row_first::Bool, xs...) = _hvncat(dimsshape, row_first, xs...) hvncat(dim::Int, xs...) = _hvncat(dim, true, xs...) From 19530bec936c6bd087ed8cf99f01a36dd56967a2 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 12 Jun 2021 19:50:34 -0400 Subject: [PATCH 20/26] Modify behavior of 0-argument int-form to return N-dim array or error --- base/abstractarray.jl | 14 ++++++-------- test/abstractarray.jl | 20 ++++++++++++++++---- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 37391106ac09f..ea67461370471 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2126,7 +2126,6 @@ julia> hvncat(((3, 3), (3, 3), (6,)), true, a, b, c, d, e, f) 4 = elements in each 4d slice (4,) => shape = ((2, 1, 1), (3, 1), (4,), (4,)) with `rowfirst` = true """ -hvncat(::Tuple{}, ::Bool) = [] hvncat(dimsshape::Tuple, row_first::Bool, xs...) = _hvncat(dimsshape, row_first, xs...) hvncat(dim::Int, xs...) = _hvncat(dim, true, xs...) @@ -2137,24 +2136,23 @@ _hvncat(dimsshape::Union{Tuple, Int}, row_first::Bool, xs::Number...) = _typed_h _hvncat(dimsshape::Union{Tuple, Int}, row_first::Bool, xs::AbstractArray...) = _typed_hvncat(promote_eltype(xs...), dimsshape, row_first, xs...) _hvncat(dimsshape::Union{Tuple, Int}, row_first::Bool, xs::AbstractArray{T}...) where T = _typed_hvncat(T, dimsshape, row_first, xs...) -typed_hvncat(::Type{T}, ::Tuple{}, ::Bool) where T = Vector{T}() typed_hvncat(T::Type, dimsshape::Tuple, row_first::Bool, xs...) = _typed_hvncat(T, dimsshape, row_first, xs...) typed_hvncat(T::Type, dim::Int, xs...) = _typed_hvncat(T, Val(dim), xs...) # 1-dimensional hvncat methods -_typed_hvncat(::Type{T}, ::Val{0}) where T = Vector{T}() +_typed_hvncat(::Type, ::Val{0}) = _typed_hvncat_0d_only_one() _typed_hvncat(::Type{T}, ::Val{0}, x) where T = fill(convert(T, x)) _typed_hvncat(::Type{T}, ::Val{0}, x::Number) where T = fill(convert(T, x)) _typed_hvncat(::Type{T}, ::Val{0}, x::AbstractArray) where T = convert.(T, x) -_typed_hvncat(::Type, ::Val{0}, ::Any...) = _typed_hvncat_0d_too_many() -_typed_hvncat(::Type, ::Val{0}, ::Number...) = _typed_hvncat_0d_too_many() -_typed_hvncat(::Type, ::Val{0}, ::AbstractArray...) = _typed_hvncat_0d_too_many() +_typed_hvncat(::Type, ::Val{0}, ::Any...) = _typed_hvncat_0d_only_one() +_typed_hvncat(::Type, ::Val{0}, ::Number...) = _typed_hvncat_0d_only_one() +_typed_hvncat(::Type, ::Val{0}, ::AbstractArray...) = _typed_hvncat_0d_only_one() -_typed_hvncat_0d_too_many() = +_typed_hvncat_0d_only_one() = throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) -_typed_hvncat(::Type{T}, ::Val{N}) where {T, N} = Vector{T}() +_typed_hvncat(::Type{T}, ::Val{N}) where {T, N} = Array{T, N}(undef, ntuple(x -> 0, Val(N))) function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool, xs::Number...) where {T, N} A = Array{T, N}(undef, dims...) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index b733b40ec66e5..94c28c9a66ab0 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1,3 +1,4 @@ +using Core: Argument # This file is a part of Julia. License is MIT: https://julialang.org/license using Random, LinearAlgebra, SparseArrays @@ -1391,19 +1392,21 @@ using Base: typed_hvncat end # 0-dimension behaviors - @test hvncat(0) == [] + # exactly one argument, placed in an array + # if already an array, copy, with type conversion as necessary + @test_throws ArgumentError hvncat(0) @test hvncat(0, 1) == fill(1) @test hvncat(0, [1]) == [1] @test_throws ArgumentError hvncat(0, 1, 1) - @test typed_hvncat(Float64, 0) == Float64[] + @test_throws ArgumentError typed_hvncat(Float64, 0) @test typed_hvncat(Float64, 0, 1) == fill(1.0) @test typed_hvncat(Float64, 0, [1]) == Float64[1.0] @test_throws ArgumentError typed_hvncat(Float64, 0, 1, 1) - @test hvncat((), true) == [] + @test_throws ArgumentError hvncat((), true) == [] @test hvncat((), true, 1) == fill(1) @test hvncat((), true, [1]) == [1] @test_throws ArgumentError hvncat((), true, 1, 1) - @test typed_hvncat(Float64, (), true) == Float64[] + @test_throws ArgumentError typed_hvncat(Float64, (), true) == Float64[] @test typed_hvncat(Float64, (), true, 1) == fill(1.0) @test typed_hvncat(Float64, (), true, [1]) == [1.0] @test_throws ArgumentError typed_hvncat(Float64, (), true, 1, 1) @@ -1440,6 +1443,15 @@ using Base: typed_hvncat @test_throws ArgumentError typed_hvncat(Float64, ((2,),), true, 1) @test typed_hvncat(Float64, ((2,),), false, 1, 1) == Float64[1.0; 1.0] @test typed_hvncat(Float64, ((2,),), false, [1], [1]) == Float64[1.0; 1.0] + + # zero-value behaviors for int form above dimension zero + # e.g. [;;], [;;;], though that isn't valid syntax + @test hvncat(1) == [] + @test hvncat(2) == Array{Int, 2}(undef, 0, 0) + @test hvncat(3) == Array{Int, 3}(undef, 0, 0, 0) + @test typed_hvncat(Int, 1) == [] + @test typed_hvncat(Int, 2) == Array{Int, 2}(undef, 0, 0) + @test typed_hvncat(Int, 3) == Array{Int, 3}(undef, 0, 0, 0) end @testset "keepat!" begin From 52166b3256dc6eda09c3ac4da1bdefae70f65f2b Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Mon, 14 Jun 2021 20:33:36 -0400 Subject: [PATCH 21/26] Remove stray using --- test/abstractarray.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 94c28c9a66ab0..f5755e49eab22 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1,4 +1,3 @@ -using Core: Argument # This file is a part of Julia. License is MIT: https://julialang.org/license using Random, LinearAlgebra, SparseArrays From 046752cc5629b904db62c6f5432be7eccd2c1637 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Thu, 1 Jul 2021 12:39:21 -0400 Subject: [PATCH 22/26] Consolidate 0-dimension case --- base/abstractarray.jl | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index ea67461370471..2426a1502f06a 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2142,9 +2142,9 @@ typed_hvncat(T::Type, dim::Int, xs...) = _typed_hvncat(T, Val(dim), xs...) # 1-dimensional hvncat methods _typed_hvncat(::Type, ::Val{0}) = _typed_hvncat_0d_only_one() -_typed_hvncat(::Type{T}, ::Val{0}, x) where T = fill(convert(T, x)) -_typed_hvncat(::Type{T}, ::Val{0}, x::Number) where T = fill(convert(T, x)) -_typed_hvncat(::Type{T}, ::Val{0}, x::AbstractArray) where T = convert.(T, x) +_typed_hvncat(T::Type, ::Val{0}, x) = fill(convert(T, x)) +_typed_hvncat(T::Type, ::Val{0}, x::Number) = fill(convert(T, x)) +_typed_hvncat(T::Type, ::Val{0}, x::AbstractArray) = convert.(T, x) _typed_hvncat(::Type, ::Val{0}, ::Any...) = _typed_hvncat_0d_only_one() _typed_hvncat(::Type, ::Val{0}, ::Number...) = _typed_hvncat_0d_only_one() _typed_hvncat(::Type, ::Val{0}, ::AbstractArray...) = _typed_hvncat_0d_only_one() @@ -2251,15 +2251,10 @@ function _typed_hvncat(::Type{T}, ::Val{N}, as...) where {T, N} end -# 0-dimensional cases for balanced and unbalanced hvncat methods +# 0-dimensional cases for balanced and unbalanced hvncat method -_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x) where T = fill(convert(T, x)) -_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::Number) where T = fill(convert(T, x)) -_typed_hvncat(::Type{T}, ::Tuple{}, ::Bool, x::AbstractArray) where T = convert.(T, x) -_typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Number...) = - throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) -_typed_hvncat(::Type, ::Tuple{}, ::Bool, ::Any...) = - throw(ArgumentError("a 0-dimensional array may only contain exactly one element")) +_typed_hvncat(T::Type, ::Tuple{}, ::Bool, x...) = _typed_hvncat(T, Val(0), x...) +_typed_hvncat(T::Type, ::Tuple{}, ::Bool, x::Number...) = _typed_hvncat(T, Val(0), x...) # balanced dimensions hvncat methods From f730a60a888ec8ec61362440ec1a1d1ae0d3fa15 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Thu, 1 Jul 2021 12:40:29 -0400 Subject: [PATCH 23/26] Update test/abstractarray.jl Co-authored-by: Jameson Nash --- test/abstractarray.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index f5755e49eab22..e0eefacea91d5 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1447,7 +1447,7 @@ using Base: typed_hvncat # e.g. [;;], [;;;], though that isn't valid syntax @test hvncat(1) == [] @test hvncat(2) == Array{Int, 2}(undef, 0, 0) - @test hvncat(3) == Array{Int, 3}(undef, 0, 0, 0) + @test Array{Int, 3}(undef, 0, 0, 0) == hvncat(3) isa Array{Int, 3} @test typed_hvncat(Int, 1) == [] @test typed_hvncat(Int, 2) == Array{Int, 2}(undef, 0, 0) @test typed_hvncat(Int, 3) == Array{Int, 3}(undef, 0, 0, 0) From bc53fc7fc33b8d4ee889224253ad30850ceb3afd Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Thu, 1 Jul 2021 12:57:45 -0400 Subject: [PATCH 24/26] Test eltype and size --- test/abstractarray.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index e0eefacea91d5..733a709ee0454 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1445,12 +1445,12 @@ using Base: typed_hvncat # zero-value behaviors for int form above dimension zero # e.g. [;;], [;;;], though that isn't valid syntax - @test hvncat(1) == [] - @test hvncat(2) == Array{Int, 2}(undef, 0, 0) - @test Array{Int, 3}(undef, 0, 0, 0) == hvncat(3) isa Array{Int, 3} - @test typed_hvncat(Int, 1) == [] - @test typed_hvncat(Int, 2) == Array{Int, 2}(undef, 0, 0) - @test typed_hvncat(Int, 3) == Array{Int, 3}(undef, 0, 0, 0) + @test [] == hvncat(1) isa Array{Any, 1} + @test Array{Any, 2}(undef, 0, 0, 0) == hvncat(2) isa Array{Any, 2} + @test Array{Any, 3}(undef, 0, 0, 0) == hvncat(3) isa Array{Any, 3} + @test Int[] == typed_hvncat(Int, 1) isa Array{Int, 1} + @test Array{Int, 2}(undef, 0, 0) == typed_hvncat(Int, 2) isa Array{Int, 2} + @test Array{Int, 3}(undef, 0, 0, 0) == typed_hvncat(Int, 3) isa Array{Int, 3} end @testset "keepat!" begin From 264f3bc1772a6fcd231a6528db98ff33ffdfeb26 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Thu, 1 Jul 2021 13:21:11 -0400 Subject: [PATCH 25/26] Fix stack overflow when dim < ndims --- base/abstractarray.jl | 3 ++- test/abstractarray.jl | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 2426a1502f06a..db9096e67e20c 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2196,7 +2196,8 @@ function _typed_hvncat(::Type{T}, ::Val{N}, as::AbstractArray...) where {T, N} # conditions: the elements must all have 1- or 0-length dimensions above N for a ∈ as ndims(a) <= N || all(x -> size(a, x) == 1, (N + 1):ndims(a)) || - return _typed_hvncat(T, (ntuple(x -> 1, N - 1)..., length(as)), false, as...) + return _typed_hvncat(T, (ntuple(x -> 1, N - 1)..., length(as), 1), false, as...) + # the extra 1 is to avoid an infinite cycle end nd = max(N, ndims(as[1])) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 733a709ee0454..cefccbac9bd14 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1415,6 +1415,7 @@ using Base: typed_hvncat @test hvncat(1) == [] @test hvncat(1, 1) == [1] @test hvncat(1, [1]) == [1] + @test hvncat(1, [1 2; 3 4]) == [1 2; 3 4] @test hvncat(1, 1, 1) == [1 ; 1] @test typed_hvncat(Float64, 1) == Float64[] @test typed_hvncat(Float64, 1, 1) == Float64[1.0] From b565092f7e10c35564cefa2f10b179ac1dc02601 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Thu, 1 Jul 2021 20:21:20 -0400 Subject: [PATCH 26/26] Test fix --- test/abstractarray.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index cefccbac9bd14..a1c6dd1b22ce7 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1447,7 +1447,7 @@ using Base: typed_hvncat # zero-value behaviors for int form above dimension zero # e.g. [;;], [;;;], though that isn't valid syntax @test [] == hvncat(1) isa Array{Any, 1} - @test Array{Any, 2}(undef, 0, 0, 0) == hvncat(2) isa Array{Any, 2} + @test Array{Any, 2}(undef, 0, 0) == hvncat(2) isa Array{Any, 2} @test Array{Any, 3}(undef, 0, 0, 0) == hvncat(3) isa Array{Any, 3} @test Int[] == typed_hvncat(Int, 1) isa Array{Int, 1} @test Array{Int, 2}(undef, 0, 0) == typed_hvncat(Int, 2) isa Array{Int, 2}