From 4b028cc7d9b7049a3f81c7d6e0ed141134d42efb Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sat, 10 Oct 2026 21:51:24 +0100 Subject: [PATCH] Concatenate scalars with layout arrays via ArrayLayouts.typed_vcat/typed_hcat [2; v] with v a layout array previously fell back to Base's generic cat, which for infinite lazy arrays hangs trying to copy v. Route one or two scalar prefixes through ArrayLayouts.typed_vcat/typed_hcat so packages like InfiniteArrays can return a lazy Vcat/Hcat. Co-Authored-By: Claude Opus 5.5 --- src/ArrayLayouts.jl | 14 ++++++++++++-- test/test_layoutarray.jl | 8 ++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/ArrayLayouts.jl b/src/ArrayLayouts.jl index 931037e..beda3d3 100644 --- a/src/ArrayLayouts.jl +++ b/src/ArrayLayouts.jl @@ -428,17 +428,27 @@ include("hash.jl") -typed_hcat(::Type{T}, ::Tuple, A...) where T = Base._typed_hcat(T, A) -typed_vcat(::Type{T}, ::Tuple, A...) where T = Base._typed_vcat(T, A) +typed_hcat(::Type{T}, ::Tuple, A...) where T = _default_typed_hcat(T, A) +typed_vcat(::Type{T}, ::Tuple, A...) where T = _default_typed_vcat(T, A) typed_hcat(::Type{T}, A...) where T = typed_hcat(T, (size(A[1],1), sum(size.(A,2))), A...) typed_vcat(::Type{T}, A...) where T = typed_vcat(T, (sum(size.(A,1)),size(A[1],2)), A...) +# Base._typed_hcat/_typed_vcat only support arrays so fall back to generic concatenation when scalars are present +_default_typed_hcat(::Type{T}, A::Tuple{Vararg{AbstractVecOrMat}}) where T = Base._typed_hcat(T, A) +_default_typed_vcat(::Type{T}, A::Tuple{Vararg{AbstractVecOrMat}}) where T = Base._typed_vcat(T, A) +_default_typed_hcat(::Type{T}, A::Tuple) where T = Base._cat_t(Val(2), T, A...) +_default_typed_vcat(::Type{T}, A::Tuple) where T = Base._cat_t(Val(1), T, A...) + Base.typed_vcat(::Type{T}, A::LayoutVecOrMats, B::AbstractVecOrMat...) where T = typed_vcat(T, A, B...) Base.typed_hcat(::Type{T}, A::LayoutVecOrMats, B::AbstractVecOrMat...) where T = typed_hcat(T, A, B...) Base.typed_vcat(::Type{T}, A::LayoutVecOrMats, B::LayoutVecOrMats, C::AbstractVecOrMat...) where T = typed_vcat(T, A, B, C...) Base.typed_hcat(::Type{T}, A::LayoutVecOrMats, B::LayoutVecOrMats, C::AbstractVecOrMat...) where T = typed_hcat(T, A, B, C...) Base.typed_vcat(::Type{T}, A::AbstractVecOrMat, B::LayoutVecOrMats, C::AbstractVecOrMat...) where T = typed_vcat(T, A, B, C...) Base.typed_hcat(::Type{T}, A::AbstractVecOrMat, B::LayoutVecOrMats, C::AbstractVecOrMat...) where T = typed_hcat(T, A, B, C...) +Base.typed_vcat(::Type{T}, A::Number, B::LayoutVecOrMats, C::AbstractVecOrMat...) where T = typed_vcat(T, A, B, C...) +Base.typed_hcat(::Type{T}, A::Number, B::LayoutVecOrMats, C::AbstractVecOrMat...) where T = typed_hcat(T, A, B, C...) +Base.typed_vcat(::Type{T}, A::Number, B::Number, C::LayoutVecOrMats, D::AbstractVecOrMat...) where T = typed_vcat(T, A, B, C, D...) +Base.typed_hcat(::Type{T}, A::Number, B::Number, C::LayoutVecOrMats, D::AbstractVecOrMat...) where T = typed_hcat(T, A, B, C, D...) ### # reshapedarray for layoutarrays diff --git a/test/test_layoutarray.jl b/test/test_layoutarray.jl index 047e365..0d7d8ca 100644 --- a/test/test_layoutarray.jl +++ b/test/test_layoutarray.jl @@ -452,6 +452,14 @@ BroadcastStyle(::Type{<:MyVector2{T}}) where {T} = MyBroadcastStyle{1}() @test [Array(a) A A] == [Array(a) Array(A) Array(A)] @test [a A A] == [Array(a) Array(A) Array(A)] @test [a Array(A) A] == [Array(a) Array(A) Array(A)] + + @test [2; a] == [2; Array(a)] + @test [2; 3; a] == [2; 3; Array(a)] + @test [2; a; a] == [2; Array(a); Array(a)] + @test [2.0; view(A,:,1)] == [2.0; A[:,1]] + r = MyMatrix(randn(1,5)) + @test [2 r] == [2 Array(r)] + @test [2 3 r] == [2 3 Array(r)] end @testset "dot" begin