1
- _thin_must_hold (thin) =
2
- thin || throw (ArgumentError (" For the sake of type stability, `thin = true` must hold." ))
1
+ # define our own struct since LinearAlgebra.QR are restricted to Matrix
2
+ struct QR{Q,R}
3
+ Q:: Q
4
+ R:: R
5
+ end
3
6
4
- """
5
- qr(A::StaticMatrix, pivot=Val{false}; thin=true) -> Q, R, [p]
7
+ # iteration for destructuring into components
8
+ 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{:done} ) = nothing
6
11
7
- Compute the QR factorization of `A` such that `A = Q*R` or `A[:,p] = Q*R`, see [`qr`](@ref).
8
- This function does not support `thin=false` keyword option due to type inference instability.
9
- To use this option call `qr(A, pivot, Val{false})` instead.
10
12
"""
11
- @inline function qr (A:: StaticMatrix , pivot:: Union{Val{false}, Val{true}} = Val (false ); thin:: Bool = true )
12
- _thin_must_hold (thin)
13
- return _qr (Size (A), A, pivot, Val (true ))
14
- end
13
+ qr(A::StaticMatrix, pivot=Val(false))
15
14
15
+ Compute the QR factorization of `A`. The factors can be obtain by iteration:
16
16
17
- @inline qr (A:: StaticMatrix , pivot:: Union{Val{false}, Val{true}} , thin:: Union{Val{false}, Val{true}} ) = _qr (Size (A), A, pivot, thin)
17
+ ```julia
18
+ julia> A = @SMatrix rand(3,4);
18
19
20
+ julia> Q, R = qr(A);
19
21
20
- _qreltype (:: Type{T} ) where T = typeof (zero (T)/ sqrt (abs2 (one (T))))
22
+ julia> Q * R ≈ A
23
+ true
24
+ ```
21
25
26
+ or by using `getfield`:
22
27
23
- @generated function _qr (:: Size{sA} , A:: StaticMatrix{<:Any, <:Any, TA} , pivot:: Union{Val{false}, Val{true}} = Val (false ), thin:: Union{Val{false}, Val{true}} = Val (true )) where {sA, TA}
28
+ ```julia
29
+ julia> F = qr(A);
24
30
25
- isthin = thin == Val (true )
31
+ julia> F.Q * F.R ≈ A
32
+ true
33
+ ```
34
+ """
35
+ @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
+ end
26
39
27
- SizeQ = Size ( sA[1 ], isthin ? diagsize (Size (A)) : sA[1 ] )
40
+ _qreltype (:: Type{T} ) where T = typeof (zero (T)/ sqrt (abs2 (one (T))))
41
+
42
+
43
+ @generated function _qr (:: Size{sA} , A:: StaticMatrix{<:Any, <:Any, TA} , pivot:: Union{Val{false}, Val{true}} = Val (false )) where {sA, TA}
44
+
45
+ SizeQ = Size ( sA[1 ], diagsize (Size (A)) )
28
46
SizeR = Size ( diagsize (Size (A)), sA[2 ] )
29
47
30
48
if pivot == Val (true )
31
49
return quote
32
50
@_inline_meta
33
- Q0, R0, p0 = qr (Matrix (A), pivot, thin = $ isthin )
51
+ Q0, R0, p0 = qr (Matrix (A), pivot)
34
52
T = _qreltype (TA)
35
53
return similar_type (A, T, $ (SizeQ))(Q0),
36
54
similar_type (A, T, $ (SizeR))(R0),
@@ -40,14 +58,13 @@ _qreltype(::Type{T}) where T = typeof(zero(T)/sqrt(abs2(one(T))))
40
58
if (sA[1 ]* sA[1 ] + sA[1 ]* sA[2 ])÷ 2 * diagsize (Size (A)) < 17 * 17 * 17
41
59
return quote
42
60
@_inline_meta
43
- return qr_unrolled (Size (A), A, pivot, thin )
61
+ return qr_unrolled (Size (A), A, pivot)
44
62
end
45
63
else
46
64
return quote
47
65
@_inline_meta
48
66
Q0R0 = qr (Matrix (A), pivot)
49
- Q0 = Q0R0. Q
50
- R0 = Q0R0. R
67
+ Q0, R0 = Matrix (Q0R0. Q), Q0R0. R
51
68
T = _qreltype (TA)
52
69
return similar_type (A, T, $ (SizeQ))(Q0),
53
70
similar_type (A, T, $ (SizeR))(R0)
60
77
# Compute the QR decomposition of `A` such that `A = Q*R`
61
78
# by Householder reflections without pivoting.
62
79
#
63
- # `thin=true` (reduced) method will produce `Q` and `R` in truncated form,
64
- # in the case of `thin=false` Q is full, but R is still reduced, see [`qr`](@ref).
65
- #
66
80
# For original source code see below.
67
- @generated function qr_unrolled (:: Size{sA} , A:: StaticMatrix{<:Any, <:Any, TA} , pivot:: Val{false} , thin :: Union{Val{false}, Val{true}} = Val ( true ) ) where {sA, TA}
81
+ @generated function qr_unrolled (:: Size{sA} , A:: StaticMatrix{<:Any, <:Any, TA} , pivot:: Val{false} ) where {sA, TA}
68
82
m, n = sA[1 ], sA[2 ]
69
83
70
84
Q = [Symbol (" Q_$(i) _$(j) " ) for i = 1 : m, j = 1 : m]
124
138
end
125
139
126
140
# truncate Q and R sizes in LAPACK consilient way
127
- if thin == Val (true )
128
- mQ, nQ = m, min (m, n)
129
- else
130
- mQ, nQ = m, m
131
- end
141
+ mQ, nQ = m, min (m, n)
132
142
mR, nR = min (m, n), n
133
143
134
144
return quote
0 commit comments