Skip to content

Commit b97d834

Browse files
authored
Merge pull request #453 from JuliaArrays/fe/qr
Fixes to new StaticArrays.QR
2 parents 37b8ba2 + c9e7d1f commit b97d834

File tree

2 files changed

+33
-19
lines changed

2 files changed

+33
-19
lines changed

src/qr.jl

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
# define our own struct since LinearAlgebra.QR are restricted to Matrix
2-
struct QR{Q,R}
2+
struct QR{Q,R,P}
33
Q::Q
44
R::R
5+
p::P
56
end
67

78
# iteration for destructuring into components
89
Base.iterate(S::QR) = (S.Q, Val(:R))
9-
Base.iterate(S::QR, ::Val{:R}) = (S.R, Val(:done))
10+
Base.iterate(S::QR, ::Val{:R}) = (S.R, Val(:p))
11+
Base.iterate(S::QR, ::Val{:p}) = (S.p, Val(:done))
1012
Base.iterate(S::QR, ::Val{:done}) = nothing
1113

1214
"""
@@ -33,8 +35,20 @@ true
3335
```
3436
"""
3537
@inline function qr(A::StaticMatrix, pivot::Union{Val{false}, Val{true}} = Val(false))
36-
Q, R = _qr(Size(A), A, pivot)
37-
return QR(Q, R)
38+
QRp = _qr(Size(A), A, pivot)
39+
if length(QRp) === 2
40+
# create an identity permutation since that is cheap,
41+
# and much safer since, in the case of isbits types, we can't
42+
# safely leave the field undefined.
43+
p = identity_perm(QRp[2])
44+
return QR(QRp[1], QRp[2], p)
45+
else # length(QRp) === 3
46+
return QR(QRp[1], QRp[2], QRp[3])
47+
end
48+
end
49+
50+
function identity_perm(R::StaticMatrix{N,M,T}) where {N,M,T}
51+
return similar_type(R, Int, Size((M,)))(ntuple(x -> x, Val{M}()))
3852
end
3953

4054
_qreltype(::Type{T}) where T = typeof(zero(T)/sqrt(abs2(one(T))))
@@ -45,12 +59,12 @@ _qreltype(::Type{T}) where T = typeof(zero(T)/sqrt(abs2(one(T))))
4559
SizeQ = Size( sA[1], diagsize(Size(A)) )
4660
SizeR = Size( diagsize(Size(A)), sA[2] )
4761

48-
if pivot == Val(true)
62+
if pivot === Val{true}
4963
return quote
5064
@_inline_meta
5165
Q0, R0, p0 = qr(Matrix(A), pivot)
5266
T = _qreltype(TA)
53-
return similar_type(A, T, $(SizeQ))(Q0),
67+
return similar_type(A, T, $(SizeQ))(Matrix(Q0)),
5468
similar_type(A, T, $(SizeR))(R0),
5569
similar_type(A, Int, $(Size(sA[2])))(p0)
5670
end

test/qr.jl

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,20 @@ srand(42)
2727
@test Q'*Q one(Q'*Q)
2828
@test istriu(R)
2929

30-
# # pivot=true cases are not released yet
31-
# pivot = Val(true)
32-
# QRp = @inferred qr(arr, pivot)
33-
# @test QRp isa Tuple
34-
# @test length(QRp) == 3
35-
# Q, R, p = QRp
36-
# @test Q isa StaticMatrix
37-
# @test R isa StaticMatrix
38-
# @test p isa StaticVector
30+
# pivot=true cases has no StaticArrays specific version yet
31+
# but fallbacks to LAPACK
32+
pivot = Val(true)
33+
QRp = @inferred qr(arr, pivot)
34+
@test QRp isa StaticArrays.QR
35+
Q, R, p = QRp
36+
@test Q isa StaticMatrix
37+
@test R isa StaticMatrix
38+
@test p isa StaticVector
3939

40-
# Q_ref,R_ref, p_ref = qr(Matrix(arr), pivot)
41-
# @test Q ≈ Q_ref
42-
# @test R ≈ R_ref
43-
# @test p == p_ref
40+
Q_ref, R_ref, p_ref = qr(Matrix(arr), pivot)
41+
@test Q Matrix(Q_ref)
42+
@test R R_ref
43+
@test p == p_ref
4444
end
4545

4646
for eltya in (Float32, Float64, BigFloat, Int),

0 commit comments

Comments
 (0)