Skip to content

Commit a3bca35

Browse files
authored
Move concatenation into abstractarray.jl (#689)
Also return a throw expression for size mismatches rather than throwing from function generators.
1 parent 82b65f4 commit a3bca35

File tree

4 files changed

+112
-109
lines changed

4 files changed

+112
-109
lines changed

src/abstractarray.jl

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,53 @@ reshape(a::Array, ::Size{S}) where {S} = SizedArray{Tuple{S...}}(a)
169169

170170
# TODO permutedims?
171171

172+
#--------------------------------------------------
173+
# Concatenation
174+
@inline vcat(a::StaticVecOrMatLike) = a
175+
@inline vcat(a::StaticVecOrMatLike, b::StaticVecOrMatLike) = _vcat(Size(a), Size(b), a, b)
176+
@inline vcat(a::StaticVecOrMatLike, b::StaticVecOrMatLike, c::StaticVecOrMatLike...) = vcat(vcat(a,b), vcat(c...))
177+
178+
@generated function _vcat(::Size{Sa}, ::Size{Sb}, a::StaticVecOrMatLike, b::StaticVecOrMatLike) where {Sa, Sb}
179+
if Size(Sa)[2] != Size(Sb)[2]
180+
return :(throw(DimensionMismatch("Tried to vcat arrays of size $Sa and $Sb")))
181+
end
182+
183+
# TODO cleanup?
184+
if a <: StaticVector && b <: StaticVector
185+
Snew = (Sa[1] + Sb[1],)
186+
exprs = vcat([:(a[$i]) for i = 1:Sa[1]],
187+
[:(b[$i]) for i = 1:Sb[1]])
188+
else
189+
Snew = (Sa[1] + Sb[1], Size(Sa)[2])
190+
exprs = [((i <= size(a,1)) ? ((a <: StaticVector) ? :(a[$i]) : :(a[$i,$j]))
191+
: ((b <: StaticVector) ? :(b[$(i-size(a,1))]) : :(b[$(i-size(a,1)),$j])))
192+
for i = 1:(Sa[1]+Sb[1]), j = 1:Size(Sa)[2]]
193+
end
194+
195+
return quote
196+
@_inline_meta
197+
@inbounds return similar_type(a, promote_type(eltype(a), eltype(b)), Size($Snew))(tuple($(exprs...)))
198+
end
199+
end
200+
201+
@inline hcat(a::StaticVector) = similar_type(a, Size(Size(a)[1],1))(a)
202+
@inline hcat(a::StaticMatrixLike) = a
203+
@inline hcat(a::StaticVecOrMatLike, b::StaticVecOrMatLike) = _hcat(Size(a), Size(b), a, b)
204+
@inline hcat(a::StaticVecOrMatLike, b::StaticVecOrMatLike, c::StaticVecOrMatLike...) = hcat(hcat(a,b), hcat(c...))
205+
206+
@generated function _hcat(::Size{Sa}, ::Size{Sb}, a::StaticVecOrMatLike, b::StaticVecOrMatLike) where {Sa, Sb}
207+
if Sa[1] != Sb[1]
208+
return :(throw(DimensionMismatch("Tried to hcat arrays of size $Sa and $Sb")))
209+
end
210+
211+
exprs = vcat([:(a[$i]) for i = 1:prod(Sa)],
212+
[:(b[$i]) for i = 1:prod(Sb)])
213+
214+
Snew = (Sa[1], Size(Sa)[2] + Size(Sb)[2])
215+
216+
return quote
217+
@_inline_meta
218+
@inbounds return similar_type(a, promote_type(eltype(a), eltype(b)), Size($Snew))(tuple($(exprs...)))
219+
end
220+
end
221+

src/linalg.jl

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -82,54 +82,6 @@ end
8282
end
8383
end
8484

85-
@inline vcat(a::StaticVecOrMatLike) = a
86-
@inline vcat(a::StaticVecOrMatLike, b::StaticVecOrMatLike) = _vcat(Size(a), Size(b), a, b)
87-
@inline vcat(a::StaticVecOrMatLike, b::StaticVecOrMatLike, c::StaticVecOrMatLike...) = vcat(vcat(a,b), vcat(c...))
88-
89-
@generated function _vcat(::Size{Sa}, ::Size{Sb}, a::StaticVecOrMatLike, b::StaticVecOrMatLike) where {Sa, Sb}
90-
if Size(Sa)[2] != Size(Sb)[2]
91-
throw(DimensionMismatch("Tried to vcat arrays of size $Sa and $Sb"))
92-
end
93-
94-
# TODO cleanup?
95-
if a <: StaticVector && b <: StaticVector
96-
Snew = (Sa[1] + Sb[1],)
97-
exprs = vcat([:(a[$i]) for i = 1:Sa[1]],
98-
[:(b[$i]) for i = 1:Sb[1]])
99-
else
100-
Snew = (Sa[1] + Sb[1], Size(Sa)[2])
101-
exprs = [((i <= size(a,1)) ? ((a <: StaticVector) ? :(a[$i]) : :(a[$i,$j]))
102-
: ((b <: StaticVector) ? :(b[$(i-size(a,1))]) : :(b[$(i-size(a,1)),$j])))
103-
for i = 1:(Sa[1]+Sb[1]), j = 1:Size(Sa)[2]]
104-
end
105-
106-
return quote
107-
@_inline_meta
108-
@inbounds return similar_type(a, promote_type(eltype(a), eltype(b)), Size($Snew))(tuple($(exprs...)))
109-
end
110-
end
111-
112-
@inline hcat(a::StaticVector) = similar_type(a, Size(Size(a)[1],1))(a)
113-
@inline hcat(a::StaticMatrixLike) = a
114-
@inline hcat(a::StaticVecOrMatLike, b::StaticVecOrMatLike) = _hcat(Size(a), Size(b), a, b)
115-
@inline hcat(a::StaticVecOrMatLike, b::StaticVecOrMatLike, c::StaticVecOrMatLike...) = hcat(hcat(a,b), hcat(c...))
116-
117-
@generated function _hcat(::Size{Sa}, ::Size{Sb}, a::StaticVecOrMatLike, b::StaticVecOrMatLike) where {Sa, Sb}
118-
if Sa[1] != Sb[1]
119-
throw(DimensionMismatch("Tried to hcat arrays of size $Sa and $Sb"))
120-
end
121-
122-
exprs = vcat([:(a[$i]) for i = 1:prod(Sa)],
123-
[:(b[$i]) for i = 1:prod(Sb)])
124-
125-
Snew = (Sa[1], Size(Sa)[2] + Size(Sb)[2])
126-
127-
return quote
128-
@_inline_meta
129-
@inbounds return similar_type(a, promote_type(eltype(a), eltype(b)), Size($Snew))(tuple($(exprs...)))
130-
end
131-
end
132-
13385
@inline Base.zero(a::SA) where {SA <: StaticArray} = zeros(SA)
13486
@inline Base.zero(a::Type{SA}) where {SA <: StaticArray} = zeros(SA)
13587

test/abstractarray.jl

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,65 @@ using StaticArrays, Test, LinearAlgebra
130130
@test @inferred(reverse(m))::typeof(m) == MVector(3, 2, 1)
131131
end
132132
end
133+
134+
@testset "vcat() and hcat()" begin
135+
@test @inferred(vcat(SVector(1,2,3))) === SVector(1,2,3)
136+
@test @inferred(hcat(SVector(1,2,3))) === SMatrix{3,1}(1,2,3)
137+
@test @inferred(hcat(SMatrix{3,1}(1,2,3))) === SMatrix{3,1}(1,2,3)
138+
139+
@test @inferred(vcat(SVector(1,2,3), SVector(4,5,6))) === SVector(1,2,3,4,5,6)
140+
@test @inferred(hcat(SVector(1,2,3), SVector(4,5,6))) === @SMatrix [1 4; 2 5; 3 6]
141+
@test_throws DimensionMismatch vcat(SVector(1,2,3), @SMatrix [1 4; 2 5])
142+
@test_throws DimensionMismatch hcat(SVector(1,2,3), SVector(4,5))
143+
144+
@test @inferred(vcat(@SMatrix([1;2;3]), SVector(4,5,6))) === @SMatrix([1;2;3;4;5;6])
145+
@test @inferred(vcat(SVector(1,2,3), @SMatrix([4;5;6]))) === @SMatrix([1;2;3;4;5;6])
146+
@test @inferred(hcat(@SMatrix([1;2;3]), SVector(4,5,6))) === @SMatrix [1 4; 2 5; 3 6]
147+
@test @inferred(hcat(SVector(1,2,3), @SMatrix([4;5;6]))) === @SMatrix [1 4; 2 5; 3 6]
148+
149+
@test @inferred(vcat(@SMatrix([1;2;3]), @SMatrix([4;5;6]))) === @SMatrix([1;2;3;4;5;6])
150+
@test @inferred(hcat(@SMatrix([1;2;3]), @SMatrix([4;5;6]))) === @SMatrix [1 4; 2 5; 3 6]
151+
152+
@test @inferred(vcat(SVector(1),SVector(2),SVector(3),SVector(4))) === SVector(1,2,3,4)
153+
@test @inferred(hcat(SVector(1),SVector(2),SVector(3),SVector(4))) === SMatrix{1,4}(1,2,3,4)
154+
155+
vcat(SVector(1.0f0), SVector(1.0)) === SVector(1.0, 1.0)
156+
hcat(SVector(1.0f0), SVector(1.0)) === SMatrix{1,2}(1.0, 1.0)
157+
158+
# issue #388
159+
let x = SVector(1, 2, 3)
160+
# current limit: 34 arguments
161+
hcat(
162+
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
163+
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x)
164+
allocs = @allocated hcat(
165+
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
166+
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x)
167+
@test allocs == 0
168+
vcat(
169+
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
170+
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x)
171+
allocs = @allocated vcat(
172+
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
173+
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x)
174+
@test allocs == 0
175+
end
176+
177+
# issue #561
178+
let A = Diagonal(SVector(1, 2)), B = @SMatrix [3 4; 5 6]
179+
@test @inferred(hcat(A, B)) === SMatrix{2, 4}([Matrix(A) Matrix(B)])
180+
end
181+
182+
let A = Transpose(@SMatrix [1 2; 3 4]), B = Adjoint(@SMatrix [5 6; 7 8])
183+
@test @inferred(hcat(A, B)) === SMatrix{2, 4}([Matrix(A) Matrix(B)])
184+
end
185+
186+
let A = Diagonal(SVector(1, 2)), B = @SMatrix [3 4; 5 6]
187+
@test @inferred(vcat(A, B)) === SMatrix{4, 2}([Matrix(A); Matrix(B)])
188+
end
189+
190+
let A = Transpose(@SMatrix [1 2; 3 4]), B = Adjoint(@SMatrix [5 6; 7 8])
191+
@test @inferred(vcat(A, B)) === SMatrix{4, 2}([Matrix(A); Matrix(B)])
192+
end
193+
end
194+

test/linalg.jl

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -147,67 +147,6 @@ using StaticArrays, Test, LinearAlgebra
147147

148148
end
149149

150-
@testset "vcat() and hcat()" begin
151-
@test @inferred(vcat(SVector(1,2,3))) === SVector(1,2,3)
152-
@test @inferred(hcat(SVector(1,2,3))) === SMatrix{3,1}(1,2,3)
153-
@test @inferred(hcat(SMatrix{3,1}(1,2,3))) === SMatrix{3,1}(1,2,3)
154-
155-
@test @inferred(vcat(SVector(1,2,3), SVector(4,5,6))) === SVector(1,2,3,4,5,6)
156-
@test @inferred(hcat(SVector(1,2,3), SVector(4,5,6))) === @SMatrix [1 4; 2 5; 3 6]
157-
@test_throws DimensionMismatch vcat(SVector(1,2,3), @SMatrix [1 4; 2 5])
158-
@test_throws DimensionMismatch hcat(SVector(1,2,3), SVector(4,5))
159-
160-
@test @inferred(vcat(@SMatrix([1;2;3]), SVector(4,5,6))) === @SMatrix([1;2;3;4;5;6])
161-
@test @inferred(vcat(SVector(1,2,3), @SMatrix([4;5;6]))) === @SMatrix([1;2;3;4;5;6])
162-
@test @inferred(hcat(@SMatrix([1;2;3]), SVector(4,5,6))) === @SMatrix [1 4; 2 5; 3 6]
163-
@test @inferred(hcat(SVector(1,2,3), @SMatrix([4;5;6]))) === @SMatrix [1 4; 2 5; 3 6]
164-
165-
@test @inferred(vcat(@SMatrix([1;2;3]), @SMatrix([4;5;6]))) === @SMatrix([1;2;3;4;5;6])
166-
@test @inferred(hcat(@SMatrix([1;2;3]), @SMatrix([4;5;6]))) === @SMatrix [1 4; 2 5; 3 6]
167-
168-
@test @inferred(vcat(SVector(1),SVector(2),SVector(3),SVector(4))) === SVector(1,2,3,4)
169-
@test @inferred(hcat(SVector(1),SVector(2),SVector(3),SVector(4))) === SMatrix{1,4}(1,2,3,4)
170-
171-
vcat(SVector(1.0f0), SVector(1.0)) === SVector(1.0, 1.0)
172-
hcat(SVector(1.0f0), SVector(1.0)) === SMatrix{1,2}(1.0, 1.0)
173-
174-
# issue #388
175-
let x = SVector(1, 2, 3)
176-
# current limit: 34 arguments
177-
hcat(
178-
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
179-
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x)
180-
allocs = @allocated hcat(
181-
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
182-
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x)
183-
@test allocs == 0
184-
vcat(
185-
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
186-
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x)
187-
allocs = @allocated vcat(
188-
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,
189-
x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x)
190-
@test allocs == 0
191-
end
192-
193-
# issue #561
194-
let A = Diagonal(SVector(1, 2)), B = @SMatrix [3 4; 5 6]
195-
@test @inferred(hcat(A, B)) === SMatrix{2, 4}([Matrix(A) Matrix(B)])
196-
end
197-
198-
let A = Transpose(@SMatrix [1 2; 3 4]), B = Adjoint(@SMatrix [5 6; 7 8])
199-
@test @inferred(hcat(A, B)) === SMatrix{2, 4}([Matrix(A) Matrix(B)])
200-
end
201-
202-
let A = Diagonal(SVector(1, 2)), B = @SMatrix [3 4; 5 6]
203-
@test @inferred(vcat(A, B)) === SMatrix{4, 2}([Matrix(A); Matrix(B)])
204-
end
205-
206-
let A = Transpose(@SMatrix [1 2; 3 4]), B = Adjoint(@SMatrix [5 6; 7 8])
207-
@test @inferred(vcat(A, B)) === SMatrix{4, 2}([Matrix(A); Matrix(B)])
208-
end
209-
end
210-
211150
@testset "normalization" begin
212151
@test norm(SVector(1.0,2.0,2.0)) 3.0
213152
@test norm(SVector(1.0,2.0,2.0),2) 3.0

0 commit comments

Comments
 (0)