@@ -3,51 +3,49 @@ _thin_must_hold(thin) =
3
3
import Base. qr
4
4
5
5
6
- @inline function qr (A:: StaticMatrix , pivot:: Type{Val{true}} ; thin:: Bool = true )
6
+ @inline function qr (A:: StaticMatrix , pivot:: Union{ Type{Val{false}}, Type{Val{ true}}} = Val{ false }; thin:: Bool = true )
7
7
_thin_must_hold (thin)
8
8
return qr (Size (A), A, pivot, Val{true })
9
9
end
10
10
11
- @generated function qr (SA:: Size{sA} , A:: StaticMatrix{<:Any, <:Any, TA} , pivot:: Type{Val{true}} , thin:: Union{Type{Val{false}}, Type{Val{true}}} ) where {sA, TA}
12
- mQ = nQ = mR = sA[1 ]
13
- nR = sA[2 ]
14
- sA[1 ] > sA[2 ] && (mR = sA[2 ])
15
- sA[1 ] > sA[2 ] && thin <: Type{Val{true}} && (nQ = sA[2 ])
16
- T = arithmetic_closure (TA)
17
- QT = similar_type (A, T, Size (mQ, nQ))
18
- RT = similar_type (A, T, Size (mR, nR))
19
- PT = similar_type (A, Int, Size (sA[2 ]))
20
- return quote
21
- @_inline_meta
22
- Q0, R0, p0 = Base. qr (Matrix (A), pivot)
23
- return $ QT (Q0), $ RT (R0), $ PT (p0)
24
- end
25
- end
26
11
12
+ """
13
+ qr(Size(A), A::StaticMatrix, pivot=Val{false}, thin=Val{true}) -> Q, R, [p]
27
14
28
- @inline function qr (A:: StaticMatrix , pivot:: Type{Val{false}} ; thin:: Bool = true )
29
- _thin_must_hold (thin)
30
- return qr (Size (A), A, pivot, Val{true })
31
- end
15
+ Compute the QR factorization of `A` such that `A = Q*R` or `A[:,p] = Q*R`, see [`qr`](@ref).
16
+ This function is exported to allow bypass the type instability problem in base `qr` function
17
+ with keyword `thin` parameter in the interface.
18
+ """
19
+ @generated function qr (:: Size{sA} , A:: StaticMatrix{<:Any, <:Any, TA} , pivot:: Union{Type{Val{false}}, Type{Val{true}}} = Val{false }, thin:: Union{Type{Val{false}}, Type{Val{true}}} = Val{true }) where {sA, TA}
20
+
21
+ isthin = thin <: Type{Val{true}}
22
+
23
+ SizeQ = Size ( sA[1 ], isthin ? diagsize (Size (A)) : sA[1 ] )
24
+ SizeR = Size ( diagsize (Size (A)), sA[2 ] )
32
25
33
- @generated function qr (SA:: Size{sA} , A:: StaticMatrix{<:Any, <:Any, TA} , pivot:: Type{Val{false}} , thin:: Union{Type{Val{false}}, Type{Val{true}}} ) where {sA, TA}
34
- if sA[1 ] < 17 && sA[2 ] < 17
26
+ if pivot <: Type{Val{true}}
35
27
return quote
36
28
@_inline_meta
37
- return qr_householder_unrolled (SA, A, thin)
29
+ Q0, R0, p0 = Base. qr (Matrix (A), pivot, thin= $ isthin)
30
+ T = arithmetic_closure (TA)
31
+ return similar_type (A, T, $ (SizeQ))(Q0),
32
+ similar_type (A, T, $ (SizeR))(R0),
33
+ similar_type (A, Int, $ (Size (sA[2 ])))(p0)
38
34
end
39
35
else
40
- mQ = nQ = mR = sA[1 ]
41
- nR = sA[2 ]
42
- sA[1 ] > sA[2 ] && (mR = sA[2 ])
43
- sA[1 ] > sA[2 ] && thin <: Type{Val{true}} && (nQ = sA[2 ])
44
- T = arithmetic_closure (TA)
45
- QT = similar_type (A, T, Size (mQ, nQ))
46
- RT = similar_type (A, T, Size (mR, nR))
47
- return quote
48
- @_inline_meta
49
- Q0, R0 = Base. qr (Matrix (A), pivot)
50
- return $ QT (Q0), $ RT (R0)
36
+ if (sA[1 ]* sA[1 ] + sA[1 ]* sA[2 ])÷ 2 * diagsize (Size (A)) < 17 * 17 * 17
37
+ return quote
38
+ @_inline_meta
39
+ return qr_unrolled (Size (A), A, thin)
40
+ end
41
+ else
42
+ return quote
43
+ @_inline_meta
44
+ Q0, R0 = Base. qr (Matrix (A), pivot, thin= $ isthin)
45
+ T = arithmetic_closure (TA)
46
+ return similar_type (A, T, $ (SizeQ))(Q0),
47
+ similar_type (A, T, $ (SizeR))(R0)
48
+ end
51
49
end
52
50
end
53
51
end
60
58
# in the case of `thin=false` Q is full, but R is still reduced, see [`qr`](@ref).
61
59
#
62
60
# For original source code see below.
63
- @generated function qr_householder_unrolled (:: Size{sA} , A:: StaticMatrix{<:Any, <:Any, TA} , thin:: Union{Type{Val{false}},Type{Val{true}}} ) where {sA, TA}
64
- mQ = nQ = mR = m = sA[1 ]
65
- nR = n = sA[2 ]
66
- # truncate Q and R for thin case
67
- m > n && (mR = n)
68
- m > n && thin <: Type{Val{true}} && (nQ = n)
61
+ @generated function qr_unrolled (:: Size{sA} , A:: StaticMatrix{<:Any, <:Any, TA} , thin:: Union{Type{Val{false}},Type{Val{true}}} = Val{true }) where {sA, TA}
62
+ m, n = sA[1 ], sA[2 ]
69
63
70
64
Q = [Symbol (" Q_$(i) _$(j) " ) for i = 1 : m, j = 1 : m]
71
65
R = [Symbol (" R_$(i) _$(j) " ) for i = 1 : m, j = 1 : n]
@@ -123,22 +117,31 @@ end
123
117
end
124
118
end
125
119
120
+ # truncate Q and R sizes in LAPACK consilient way
121
+ if thin <: Type{Val{true}}
122
+ mQ, nQ = m, min (m, n)
123
+ else
124
+ mQ, nQ = m, m
125
+ end
126
+ mR, nR = min (m, n), n
127
+
126
128
return quote
127
129
@_inline_meta
128
130
T = arithmetic_closure (TA)
129
131
@inbounds $ (Expr (:block , initQ... ))
130
132
@inbounds $ (Expr (:block , initR... ))
131
133
@inbounds $ code
132
- @inbounds return similar_type (A, T, $ (Size (mQ,nQ)))(tuple ($ (Q[1 : mQ,1 : nQ]. .. ))),
133
- similar_type (A, T, $ (Size (mR,nR)))(tuple ($ (R[1 : mR,1 : nR]. .. )))
134
+ @inbounds return similar_type (A, T, $ (Size (mQ, nQ)))( tuple ($ (Q[1 : mQ, 1 : nQ]. .. )) ),
135
+ similar_type (A, T, $ (Size (mR, nR)))( tuple ($ (R[1 : mR, 1 : nR]. .. )) )
134
136
end
135
137
136
138
end
137
139
138
- # # source for @generated function above
139
- # # derived from base/linalg/qr.jl
140
- # # thin version of QR
141
- # function qr_householder_unrolled(A::StaticMatrix{<:Any, <:Any, TA}) where {TA}
140
+
141
+ # # Source for @generated qr_unrolled() function above.
142
+ # # Derived from base/linalg/qr.jl
143
+ # # thin=true version of QR
144
+ # function qr_unrolled(A::StaticMatrix{<:Any, <:Any, TA}) where {TA}
142
145
# m, n = size(A)
143
146
# T = arithmetic_closure(TA)
144
147
# Q = eye(MMatrix{m,m,T,m*m})
0 commit comments