Skip to content

Commit 953e4e3

Browse files
committed
Add solve methods for rectangular A
1 parent e7c5e01 commit 953e4e3

File tree

3 files changed

+31
-9
lines changed

3 files changed

+31
-9
lines changed

src/StaticArrays.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ include("matrix_multiply.jl")
120120
include("lu.jl")
121121
include("det.jl")
122122
include("inv.jl")
123+
include("qr.jl")
123124
include("solve.jl")
124125
include("eigen.jl")
125126
include("expm.jl")
@@ -128,7 +129,6 @@ include("lyap.jl")
128129
include("triangular.jl")
129130
include("cholesky.jl")
130131
include("svd.jl")
131-
include("qr.jl")
132132
include("deque.jl")
133133
include("flatten.jl")
134134
include("io.jl")

src/solve.jl

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
@inline (\)(a::StaticMatrix, b::StaticVecOrMat) = _solve(Size(a), Size(b), a, b)
2+
@inline (\)(Q::QR, b::StaticVecOrMat) = Q.R \ (Q.Q' * b)
23

34
@inline function _solve(::Size{(1,1)}, ::Size{(1,)}, a::StaticMatrix{<:Any, <:Any, Ta}, b::StaticVector{<:Any, Tb}) where {Ta, Tb}
45
@inbounds return similar_type(b, typeof(a[1] \ b[1]))(a[1] \ b[1])
@@ -55,15 +56,30 @@ end
5556
throw(DimensionMismatch("Left and right hand side first dimensions do not match in backdivide (got sizes $Sa and $Sb)"))
5657
end
5758
end
58-
if prod(Sa) 14*14 && Sa[1] == Sa[2]
59+
if prod(Sa) 14*14
5960
# TODO: Consider triangular special cases as in Base?
60-
quote
61-
@_inline_meta
62-
LUp = lu(a)
63-
LUp.U \ (LUp.L \ $(length(Sb) > 1 ? :(b[LUp.p,:]) : :(b[LUp.p])))
61+
if Sa[1] == Sa[2]
62+
quote
63+
@_inline_meta
64+
LUp = lu(a)
65+
LUp.U \ (LUp.L \ $(length(Sb) > 1 ? :(b[LUp.p,:]) : :(b[LUp.p])))
66+
end
67+
else
68+
69+
quote
70+
@_inline_meta
71+
q = qr(a)
72+
y = q.Q' * b
73+
if Sa[1] > Sa[2]
74+
R₁ = SMatrix{Sa[2], Sa[2]}(q.R[SOneTo(Sa[2]), SOneTo(Sa[2])])
75+
# return inv(R₁) * y
76+
return R₁ \ y
77+
else
78+
return q.R' * ((q.R * q.R') \ y)
79+
# return pinv(q.R) * y
80+
end
81+
end
6482
end
65-
# TODO: Could also use static QR here if `a` is nonsquare.
66-
# Requires that we implement \(::StaticArrays.QR,::StaticVecOrMat)
6783
else
6884
# Fall back to LinearAlgebra, but carry across the statically known size.
6985
outsize = length(Sb) == 1 ? Size(Sa[2]) : Size(Sa[2],Sb[end])

test/solve.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,17 @@ using StaticArrays, Test, LinearAlgebra
2121
# So try all of these
2222
@testset "Mixed static/dynamic" begin
2323
v = @SVector([0.2,0.3])
24+
# Square matrices
2425
for m in (@SMatrix([1.0 0; 0 1.0]), @SMatrix([1.0 0; 1.0 1.0]),
2526
@SMatrix([1.0 1.0; 0 1.0]), @SMatrix([1.0 0.5; 0.25 1.0]))
26-
# TODO: include @SMatrix([1.0 0.0 0.0; 1.0 2.0 0.5]), need qr methods
2727
@test m \ v Array(m) \ v m \ Array(v) Array(m) \ Array(v)
2828
end
29+
# Rectangular matrices
30+
for m in (@SMatrix([1.0 0.0 0.0; 1.0 2.0 0.5]), @SMatrix([1.0 2.0 0.5; 0.0 0.0 1.0]),
31+
@SMatrix([0.0 0.0 1.0; 1.0 2.0 0.5]), @SMatrix([1.0 2.0 0.5; 1.0 0.0 0.0]))
32+
@test m \ v Array(m) \ v Array(m) \ Array(v)
33+
@test_throws MethodError m \ Array(v) # TODO: requires adjoint(::QR) method
34+
end
2935
end
3036
end
3137

0 commit comments

Comments
 (0)