From c7a73a2e61c1c0c67478b66bd1cf86bc0e753805 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 5 Jun 2021 19:13:14 -0400 Subject: [PATCH 1/8] Rebased changes --- base/abstractarray.jl | 72 +++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 8571cc8ee90a5..49f09210a5b69 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2055,10 +2055,30 @@ julia> hvcat((2,2,2), a,b,c,d,e,f) == hvcat(2, a,b,c,d,e,f) true ``` """ -hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractArray...) = typed_hvcat(promote_eltype(xs...), rows, xs...) -hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractArray{T}...) where {T} = typed_hvcat(T, rows, xs...) - -function typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as::AbstractVecOrMat...) where T +hvcat(::Tuple{}) = [] +hvcat(::Tuple{}, xs...) = [] +hvcat(::Tuple{Vararg{Int, 1}}, xs...) = vcat(xs...) # methods assume 2+ dimensions +hvcat(rows::Tuple{Vararg{Int}}, xs...) = _hvcat(rows, xs...) + +_hvcat(::Tuple{Vararg{Int}}) = [] +_hvcat(rows::Tuple{Vararg{Int}}, xs...) = _typed_hvncat(promote_eltypeof(xs...), (length(rows), rows[1]), true, xs...) +_hvcat(rows::Tuple{Vararg{Int}}, xs::T...) where T<:Number = _typed_hvcat(T, rows, xs...) +_hvcat(rows::Tuple{Vararg{Int}}, xs::Number...) = _typed_hvcat(promote_typeof(xs...), rows, xs...) +_hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractVecOrMat...) = _typed_hvcat(promote_eltype(xs...), rows, xs...) +_hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractVecOrMat{T}...) where T = _typed_hvcat(T, rows, xs...) +_hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractArray...) = _typed_hvncat(promote_eltype(xs...), (length(rows), rows[1]), true, xs...) +_hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractArray{T}...) where T = _typed_hvncat(T, (length(rows), rows[1]), true, xs...) + +typed_hvcat(::Type{T}, ::Tuple{}) where T = Vector{T}() +typed_hvcat(::Type{T}, ::Tuple{}, xs...) where T = Vector{T}() +typed_hvcat(T::Type, ::Tuple{Vararg{Any, 1}}, ::Bool, xs...) = typed_vcat(T, xs...) +typed_hvcat(T::Type, rows::Tuple{Vararg{Int}}, xs...) = _typed_hvcat(T, rows, xs...) + +_typed_hvcat(::Type{T}, ::Tuple{}) where T = Vector{T}() +_typed_hvcat(::Type{T}, ::Tuple{}, xs...) where T = Vector{T}() +_typed_hvcat(::Type{T}, ::Tuple{}, xs::Number...) where T = Vector{T}() + +function _typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as::AbstractVecOrMat...) where T nbr = length(rows) # number of block rows nc = 0 @@ -2101,28 +2121,15 @@ function typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as::AbstractVecOrMat.. out end -hvcat(rows::Tuple{Vararg{Int}}) = [] -typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}) where {T} = Vector{T}() - -function hvcat(rows::Tuple{Vararg{Int}}, xs::T...) where T<:Number +function _typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, xs::Number...) where T nr = length(rows) nc = rows[1] - - a = Matrix{T}(undef, nr, nc) - if length(a) != length(xs) - throw(ArgumentError("argument count does not match specified shape (expected $(length(a)), got $(length(xs)))")) - end - k = 1 - @inbounds for i=1:nr + for i = 2:nr if nc != rows[i] throw(DimensionMismatch("row $(i) has mismatched number of columns (expected $nc, got $(rows[i]))")) end - for j=1:nc - a[i,j] = xs[k] - k += 1 - end end - a + hvcat_fill!(Matrix{T}(undef, nr, nc), xs) end function hvcat_fill!(a::Array, xs::Tuple) @@ -2141,23 +2148,11 @@ function hvcat_fill!(a::Array, xs::Tuple) a end -hvcat(rows::Tuple{Vararg{Int}}, xs::Number...) = typed_hvcat(promote_typeof(xs...), rows, xs...) -hvcat(rows::Tuple{Vararg{Int}}, xs...) = typed_hvcat(promote_eltypeof(xs...), rows, xs...) -# the following method is needed to provide a more specific one compared to LinearAlgebra/uniformscaling.jl -hvcat(rows::Tuple{Vararg{Int}}, xs::Union{AbstractArray,Number}...) = typed_hvcat(promote_eltypeof(xs...), rows, xs...) - -function typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, xs::Number...) where T - nr = length(rows) - nc = rows[1] - for i = 2:nr - if nc != rows[i] - throw(DimensionMismatch("row $(i) has mismatched number of columns (expected $nc, got $(rows[i]))")) - end - end - hvcat_fill!(Matrix{T}(undef, nr, nc), xs) -end +_typed_hvcat(T::Type, rows::Tuple{Vararg{Int}}, xs...) = _typed_hvncat(T, (length(rows), rows[1]), true, xs...) +_typed_hvcat(T::Type, rows::Tuple{Vararg{Int}}, xs::AbstractArray...) = _typed_hvncat(T, (length(rows), rows[1]), true, xs...) +_typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, xs::AbstractArray{T}...) where T = _typed_hvncat(T, (length(rows), rows[1]), true, xs...) -function typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as...) where T +function _typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as...) where T nbr = length(rows) # number of block rows rs = Vector{Any}(undef, nbr) a = 1 @@ -2893,6 +2888,11 @@ _ensure_array(x) = 1:0 # passed to similar, makes stack's output an Array _empty_stack(_...) = throw(ArgumentError("`stack` on an empty collection is not allowed")) +cat_ndims(a) = 0 +cat_ndims(a::AbstractArray) = ndims(a) +cat_length(::Any) = 1 +cat_length(a::AbstractArray) = length(a) + ## Reductions and accumulates ## function isequal(A::AbstractArray, B::AbstractArray) From bf028bb7470061de08cb5581f66d3894c1c6ad00 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sun, 6 Jun 2021 11:29:36 -0400 Subject: [PATCH 2/8] Reorganized --- base/abstractarray.jl | 84 +++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 47 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 49f09210a5b69..03451528b29fa 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2057,28 +2057,47 @@ true """ hvcat(::Tuple{}) = [] hvcat(::Tuple{}, xs...) = [] -hvcat(::Tuple{Vararg{Int, 1}}, xs...) = vcat(xs...) # methods assume 2+ dimensions -hvcat(rows::Tuple{Vararg{Int}}, xs...) = _hvcat(rows, xs...) - -_hvcat(::Tuple{Vararg{Int}}) = [] -_hvcat(rows::Tuple{Vararg{Int}}, xs...) = _typed_hvncat(promote_eltypeof(xs...), (length(rows), rows[1]), true, xs...) -_hvcat(rows::Tuple{Vararg{Int}}, xs::T...) where T<:Number = _typed_hvcat(T, rows, xs...) -_hvcat(rows::Tuple{Vararg{Int}}, xs::Number...) = _typed_hvcat(promote_typeof(xs...), rows, xs...) -_hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractVecOrMat...) = _typed_hvcat(promote_eltype(xs...), rows, xs...) -_hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractVecOrMat{T}...) where T = _typed_hvcat(T, rows, xs...) -_hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractArray...) = _typed_hvncat(promote_eltype(xs...), (length(rows), rows[1]), true, xs...) -_hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractArray{T}...) where T = _typed_hvncat(T, (length(rows), rows[1]), true, xs...) + +hvcat(rows::Tuple{Vararg{Int}}, xs::T...) where T<:Number = typed_hvcat(T, rows, xs...) +hvcat(rows::Tuple{Vararg{Int}}, xs::Number...) = typed_hvcat(promote_typeof(xs...), rows, xs...) +hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractVector...) = typed_hvcat(promote_eltype(xs...), rows, xs...) +hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractVecOrMat{T}...) where T = typed_hvcat(T, rows, xs...) + +# dispatch to hvncat methods when it performs better +rows_to_dimshape(rows::Tuple{Vararg{Int}}) = all(==(rows[1]), rows) ? (length(rows), rows[1]) : (rows, (sum(rows),)) +hvcat(rows::Tuple{Vararg{Int}}, xs...) = _hvncat(rows_to_dimshape(rows), true, xs...) typed_hvcat(::Type{T}, ::Tuple{}) where T = Vector{T}() typed_hvcat(::Type{T}, ::Tuple{}, xs...) where T = Vector{T}() -typed_hvcat(T::Type, ::Tuple{Vararg{Any, 1}}, ::Bool, xs...) = typed_vcat(T, xs...) -typed_hvcat(T::Type, rows::Tuple{Vararg{Int}}, xs...) = _typed_hvcat(T, rows, xs...) -_typed_hvcat(::Type{T}, ::Tuple{}) where T = Vector{T}() -_typed_hvcat(::Type{T}, ::Tuple{}, xs...) where T = Vector{T}() -_typed_hvcat(::Type{T}, ::Tuple{}, xs::Number...) where T = Vector{T}() +function typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, xs::Number...) where T + nr = length(rows) + nc = rows[1] + for i = 2:nr + if nc != rows[i] + throw(ArgumentError("row $(i) has mismatched number of columns (expected $nc, got $(rows[i]))")) + end + end + hvcat_fill!(Matrix{T}(undef, nr, nc), xs) +end + +function hvcat_fill!(a::Array, xs::Tuple) + nr, nc = size(a,1), size(a,2) + len = length(xs) + if nr*nc != len + throw(ArgumentError("argument count $(len) does not match specified shape $((nr,nc))")) + end + k = 1 + for i=1:nr + @inbounds for j=1:nc + a[i,j] = xs[k] + k += 1 + end + end + a +end -function _typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as::AbstractVecOrMat...) where T +function typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as::AbstractVector...) where T nbr = length(rows) # number of block rows nc = 0 @@ -2121,36 +2140,7 @@ function _typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as::AbstractVecOrMat. out end -function _typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, xs::Number...) where T - nr = length(rows) - nc = rows[1] - for i = 2:nr - if nc != rows[i] - throw(DimensionMismatch("row $(i) has mismatched number of columns (expected $nc, got $(rows[i]))")) - end - end - hvcat_fill!(Matrix{T}(undef, nr, nc), xs) -end - -function hvcat_fill!(a::Array, xs::Tuple) - nr, nc = size(a,1), size(a,2) - len = length(xs) - if nr*nc != len - throw(ArgumentError("argument count $(len) does not match specified shape $((nr,nc))")) - end - k = 1 - for i=1:nr - @inbounds for j=1:nc - a[i,j] = xs[k] - k += 1 - end - end - a -end - -_typed_hvcat(T::Type, rows::Tuple{Vararg{Int}}, xs...) = _typed_hvncat(T, (length(rows), rows[1]), true, xs...) -_typed_hvcat(T::Type, rows::Tuple{Vararg{Int}}, xs::AbstractArray...) = _typed_hvncat(T, (length(rows), rows[1]), true, xs...) -_typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, xs::AbstractArray{T}...) where T = _typed_hvncat(T, (length(rows), rows[1]), true, xs...) +typed_hvcat(T::Type, rows::Tuple{Vararg{Int}}, xs...) = _typed_hvncat(T, rows_to_dimshape(rows), true, xs...) function _typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as...) where T nbr = length(rows) # number of block rows From 78146d6422f08ef1ff8e3f98a3a3347f5203b490 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Thu, 19 May 2022 03:24:30 -0400 Subject: [PATCH 3/8] Type stability improvement --- base/abstractarray.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 03451528b29fa..6efc9d5f22632 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1730,9 +1730,9 @@ cat_indices(A::AbstractArray, d) = axes(A, d) 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::Array, ::Type{T}, shape::Vector, ::Val{N}) where {T, N} = Array{T, N}(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...) +cat_similar(A::AbstractArray, T::Type, shape::Vector, ::Val{N}) = similar(A, T, shape...) # These are for backwards compatibility (even though internal) cat_shape(dims, shape::Tuple{Vararg{Int}}) = shape @@ -2499,7 +2499,7 @@ function _typed_hvncat_dims(::Type{T}, dims::NTuple{N, Int}, row_first::Bool, as throw(DimensionMismatch("mismatched number of elements; expected $(outlen), got $(elementcount)")) # copy into final array - A = cat_similar(as[1], T, outdims) + A = cat_similar(as[1], T, outdims, Val(N)) # @assert all(==(0), currentdims) outdims .= 0 hvncat_fill!(A, currentdims, outdims, d1, d2, as) @@ -2593,7 +2593,7 @@ function _typed_hvncat_shape(::Type{T}, shape::NTuple{N, Tuple}, row_first, as:: # @assert all(==(0), blockcounts) # copy into final array - A = cat_similar(as[1], T, outdims) + A = cat_similar(as[1], T, outdims, Val(length(outdims))) hvncat_fill!(A, currentdims, blockcounts, d1, d2, as) return A end From b0845345da53f3398bde88bb6e28a81da5a9abbf Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Thu, 19 May 2022 07:21:34 -0400 Subject: [PATCH 4/8] Fix type param --- base/abstractarray.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 6efc9d5f22632..fcea42e369317 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1732,7 +1732,7 @@ 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, ::Val{N}) where {T, N} = Array{T, N}(undef, shape...) cat_similar(A::AbstractArray, T::Type, shape::Tuple) = similar(A, T, shape) -cat_similar(A::AbstractArray, T::Type, shape::Vector, ::Val{N}) = similar(A, T, shape...) +cat_similar(A::AbstractArray, T::Type, shape::Vector, ::Val{N}) where N = similar(A, T, shape...) # These are for backwards compatibility (even though internal) cat_shape(dims, shape::Tuple{Vararg{Int}}) = shape From 34872cdd89f5ffcf106e1faacb60c12e752f79d6 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sun, 13 Aug 2023 17:03:00 -0400 Subject: [PATCH 5/8] Merge issue --- base/abstractarray.jl | 5 ----- 1 file changed, 5 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index fcea42e369317..936eb41b2f41e 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2878,11 +2878,6 @@ _ensure_array(x) = 1:0 # passed to similar, makes stack's output an Array _empty_stack(_...) = throw(ArgumentError("`stack` on an empty collection is not allowed")) -cat_ndims(a) = 0 -cat_ndims(a::AbstractArray) = ndims(a) -cat_length(::Any) = 1 -cat_length(a::AbstractArray) = length(a) - ## Reductions and accumulates ## function isequal(A::AbstractArray, B::AbstractArray) From 67dc65e7c11677041631f8e577eec79bdb307143 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sun, 11 Feb 2024 15:17:08 -0500 Subject: [PATCH 6/8] Simplifying for now --- base/abstractarray.jl | 96 ++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 60 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 2ac11664c3208..8593482104a9d 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1759,8 +1759,10 @@ cat_indices(A::AbstractArray, d) = axes(A, d) 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::Array, ::Type{T}, shape::Vector, ::Val{N}) where {T, N} = Array{T, N}(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...) cat_similar(A::AbstractArray, T::Type, shape::Vector, ::Val{N}) where N = similar(A, T, shape...) # These are for backwards compatibility (even though internal) @@ -2083,30 +2085,33 @@ julia> hvcat((2,2,2), a,b,c,d,e,f) == hvcat(2, a,b,c,d,e,f) true ``` """ -hvcat(::Tuple{}) = [] -hvcat(::Tuple{}, xs...) = [] +hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractArray...) = typed_hvcat(promote_eltype(xs...), rows, xs...) +hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractArray{T}...) where {T} = typed_hvcat(T, rows, xs...) -hvcat(rows::Tuple{Vararg{Int}}, xs::T...) where T<:Number = typed_hvcat(T, rows, xs...) -hvcat(rows::Tuple{Vararg{Int}}, xs::Number...) = typed_hvcat(promote_typeof(xs...), rows, xs...) -hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractVector...) = typed_hvcat(promote_eltype(xs...), rows, xs...) -hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractVecOrMat{T}...) where T = typed_hvcat(T, rows, xs...) - -# dispatch to hvncat methods when it performs better -rows_to_dimshape(rows::Tuple{Vararg{Int}}) = all(==(rows[1]), rows) ? (length(rows), rows[1]) : (rows, (sum(rows),)) -hvcat(rows::Tuple{Vararg{Int}}, xs...) = _hvncat(rows_to_dimshape(rows), true, xs...) +typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as::AbstractVecOrMat...) where T = typed_hvncat(T, (rows, (sum(rows),)), true, as...) -typed_hvcat(::Type{T}, ::Tuple{}) where T = Vector{T}() -typed_hvcat(::Type{T}, ::Tuple{}, xs...) where T = Vector{T}() +hvcat(rows::Tuple{Vararg{Int}}) = [] +typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}) where {T} = Vector{T}() -function typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, xs::Number...) where T +function hvcat(rows::Tuple{Vararg{Int}}, xs::T...) where T<:Number nr = length(rows) nc = rows[1] - for i = 2:nr + + a = Matrix{T}(undef, nr, nc) + if length(a) != length(xs) + throw(ArgumentError("argument count does not match specified shape (expected $(length(a)), got $(length(xs)))")) + end + k = 1 + @inbounds for i=1:nr if nc != rows[i] - throw(ArgumentError("row $(i) has mismatched number of columns (expected $nc, got $(rows[i]))")) + throw(DimensionMismatch("row $(i) has mismatched number of columns (expected $nc, got $(rows[i]))")) + end + for j=1:nc + a[i,j] = xs[k] + k += 1 end end - hvcat_fill!(Matrix{T}(undef, nr, nc), xs) + a end function hvcat_fill!(a::Array, xs::Tuple) @@ -2125,52 +2130,23 @@ function hvcat_fill!(a::Array, xs::Tuple) a end -function typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as::AbstractVector...) where T - nbr = length(rows) # number of block rows - - nc = 0 - for i=1:rows[1] - nc += size(as[i],2) - end - - nr = 0 - a = 1 - for i = 1:nbr - nr += size(as[a],1) - a += rows[i] - end - - out = similar(as[1], T, nr, nc) +hvcat(rows::Tuple{Vararg{Int}}, xs::Number...) = typed_hvcat(promote_typeof(xs...), rows, xs...) +hvcat(rows::Tuple{Vararg{Int}}, xs...) = typed_hvcat(promote_eltypeof(xs...), rows, xs...) +# the following method is needed to provide a more specific one compared to LinearAlgebra/uniformscaling.jl +hvcat(rows::Tuple{Vararg{Int}}, xs::Union{AbstractArray,Number}...) = typed_hvcat(promote_eltypeof(xs...), rows, xs...) - a = 1 - r = 1 - for i = 1:nbr - c = 1 - szi = size(as[a],1) - for j = 1:rows[i] - Aj = as[a+j-1] - szj = size(Aj,2) - if size(Aj,1) != szi - throw(DimensionMismatch("mismatched height in block row $(i) (expected $szi, got $(size(Aj,1)))")) - end - if c-1+szj > nc - throw(DimensionMismatch("block row $(i) has mismatched number of columns (expected $nc, got $(c-1+szj))")) - end - out[r:r-1+szi, c:c-1+szj] = Aj - c += szj - end - if c != nc+1 - throw(DimensionMismatch("block row $(i) has mismatched number of columns (expected $nc, got $(c-1))")) +function typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, xs::Number...) where T + nr = length(rows) + nc = rows[1] + for i = 2:nr + if nc != rows[i] + throw(DimensionMismatch("row $(i) has mismatched number of columns (expected $nc, got $(rows[i]))")) end - r += szi - a += rows[i] end - out + hvcat_fill!(Matrix{T}(undef, nr, nc), xs) end -typed_hvcat(T::Type, rows::Tuple{Vararg{Int}}, xs...) = _typed_hvncat(T, rows_to_dimshape(rows), true, xs...) - -function _typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as...) where T +function typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as...) where T nbr = length(rows) # number of block rows rs = Vector{Any}(undef, nbr) a = 1 @@ -2307,7 +2283,7 @@ end function _typed_hvncat(T::Type, ::Val{N}, xs::Number...) where N N < 0 && throw(ArgumentError("concatenation dimension must be non-negative")) - A = cat_similar(xs[1], T, (ntuple(x -> 1, Val(N - 1))..., length(xs))) + A = cat_similar(xs[1], T, (ntuple(x -> 1, Val(N - 1))..., length(xs)), Val(N)) hvncat_fill!(A, false, xs) return A end @@ -2336,7 +2312,7 @@ function _typed_hvncat(::Type{T}, ::Val{N}, as::AbstractArray...) where {T, N} end end - A = cat_similar(as[1], T, (ntuple(d -> 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)...), Val(nd)) k = 1 for a ∈ as for i ∈ eachindex(a) @@ -2621,7 +2597,7 @@ function _typed_hvncat_shape(::Type{T}, shape::NTuple{N, Tuple}, row_first, as:: # @assert all(==(0), blockcounts) # copy into final array - A = cat_similar(as[1], T, outdims, Val(length(outdims))) + A = cat_similar(as[1], T, outdims, Val(nd)) hvncat_fill!(A, currentdims, blockcounts, d1, d2, as) return A end From 16e3e80e3522c2339c1074ac189123af5c52865c Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Mon, 12 Feb 2024 02:08:27 -0500 Subject: [PATCH 7/8] Remove new cat_similar, rely on type assertions instead --- base/abstractarray.jl | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 8593482104a9d..e6f6ff9fc4566 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1760,10 +1760,8 @@ 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::Array, ::Type{T}, shape::Vector, ::Val{N}) where {T, N} = Array{T, N}(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...) -cat_similar(A::AbstractArray, T::Type, shape::Vector, ::Val{N}) where N = similar(A, T, shape...) # These are for backwards compatibility (even though internal) cat_shape(dims, shape::Tuple{Vararg{Int}}) = shape @@ -2283,7 +2281,7 @@ end function _typed_hvncat(T::Type, ::Val{N}, xs::Number...) where N N < 0 && throw(ArgumentError("concatenation dimension must be non-negative")) - A = cat_similar(xs[1], T, (ntuple(x -> 1, Val(N - 1))..., length(xs)), Val(N)) + A = cat_similar(xs[1], T, (ntuple(x -> 1, Val(N - 1))..., length(xs))) hvncat_fill!(A, false, xs) return A end @@ -2312,7 +2310,7 @@ function _typed_hvncat(::Type{T}, ::Val{N}, as::AbstractArray...) where {T, N} end end - A = cat_similar(as[1], T, (ntuple(d -> size(as[1], d), N - 1)..., Ndim, ntuple(x -> 1, nd - N)...), Val(nd)) + 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) @@ -2503,7 +2501,7 @@ function _typed_hvncat_dims(::Type{T}, dims::NTuple{N, Int}, row_first::Bool, as throw(DimensionMismatch("mismatched number of elements; expected $(outlen), got $(elementcount)")) # copy into final array - A = cat_similar(as[1], T, outdims, Val(N)) + A = cat_similar(as[1], T, ntuple(i -> outdims[i], N)) # @assert all(==(0), currentdims) outdims .= 0 hvncat_fill!(A, currentdims, outdims, d1, d2, as) @@ -2597,7 +2595,7 @@ function _typed_hvncat_shape(::Type{T}, shape::NTuple{N, Tuple}, row_first, as:: # @assert all(==(0), blockcounts) # copy into final array - A = cat_similar(as[1], T, outdims, Val(nd)) + A = cat_similar(as[1], T, ntuple(i -> outdims[i], nd)) hvncat_fill!(A, currentdims, blockcounts, d1, d2, as) return A end From b7f6f2d372a994e0f5e54f6497ea6471ada5df86 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Mon, 12 Feb 2024 03:24:34 -0500 Subject: [PATCH 8/8] Switch hvcat fallback to hvncat, allow dims argument form --- base/abstractarray.jl | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index e6f6ff9fc4566..a7545d04a8d1f 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2086,7 +2086,8 @@ true hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractArray...) = typed_hvcat(promote_eltype(xs...), rows, xs...) hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractArray{T}...) where {T} = typed_hvcat(T, rows, xs...) -typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as::AbstractVecOrMat...) where T = typed_hvncat(T, (rows, (sum(rows),)), true, as...) +rows_to_dimshape(rows::Tuple{Vararg{Int}}) = all(==(rows[1]), rows) ? (length(rows), rows[1]) : (rows, (sum(rows),)) +typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as::AbstractVecOrMat...) where T = typed_hvncat(T, rows_to_dimshape(rows), true, as...) hvcat(rows::Tuple{Vararg{Int}}) = [] typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}) where {T} = Vector{T}() @@ -2144,16 +2145,7 @@ function typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, xs::Number...) where T hvcat_fill!(Matrix{T}(undef, nr, nc), xs) end -function typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as...) where T - nbr = length(rows) # number of block rows - rs = Vector{Any}(undef, nbr) - a = 1 - for i = 1:nbr - rs[i] = typed_hcat(T, as[a:a-1+rows[i]]...) - a += rows[i] - end - T[rs...;] -end +typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as...) where T = typed_hvncat(T, rows_to_dimshape(rows), true, as...) ## N-dimensional concatenation ##