|
10 | 10 | R₁ = UpperTriangular(@view R[SOneTo(Sa[2]), SOneTo(Sa[2])]) |
11 | 11 | return R₁ \ y |
12 | 12 | else |
13 | | - return R' * ((R * R') \ y) |
| 13 | + return _wide_qr_solve(q, b) |
14 | 14 | end |
15 | 15 | end |
16 | 16 |
|
| 17 | +# based on https://github.com/JuliaLang/LinearAlgebra.jl/blob/16f64e78769d788376df0f36447affdb7b1b3df6/src/qr.jl#L652C1-L697C4 |
| 18 | +function _wide_qr_solve(A::QR{T}, B::StaticMatrix{mB,nB,T}) where {mB,nB,T} |
| 19 | + m, n = size(A) |
| 20 | + minmn = min(m, n) |
| 21 | + Bbuffer = similar(B) |
| 22 | + copyto!(Bbuffer, B) |
| 23 | + lmul!(adjoint(A.Q), view(Bbuffer, 1:m, :)) |
| 24 | + Rbuffer = similar(A.R) |
| 25 | + copyto!(Rbuffer, A.R) |
| 26 | + |
| 27 | + @inbounds begin |
| 28 | + if n > m # minimum norm solution |
| 29 | + τ = zeros(T,m) |
| 30 | + for k = m:-1:1 # Trapezoid to triangular by elementary operation |
| 31 | + x = view(Rbuffer, k, [k; m + 1:n]) |
| 32 | + τk = LinearAlgebra.reflector!(x) |
| 33 | + τ[k] = conj(τk) |
| 34 | + for i = 1:k - 1 |
| 35 | + vRi = Rbuffer[i,k] |
| 36 | + for j = m + 1:n |
| 37 | + vRi += Rbuffer[i,j]*x[j - m + 1]' |
| 38 | + end |
| 39 | + vRi *= τk |
| 40 | + Rbuffer[i,k] -= vRi |
| 41 | + for j = m + 1:n |
| 42 | + Rbuffer[i,j] -= vRi*x[j - m + 1] |
| 43 | + end |
| 44 | + end |
| 45 | + end |
| 46 | + end |
| 47 | + ldiv!(UpperTriangular(view(Rbuffer, :, SOneTo(minmn))), view(Bbuffer, SOneTo(minmn), :)) |
| 48 | + if n > m # Apply elementary transformation to solution |
| 49 | + Bbuffer[m + 1:mB,1:nB] .= zero(T) |
| 50 | + for j = 1:nB |
| 51 | + for k = 1:m |
| 52 | + vBj = Bbuffer[k,j]' |
| 53 | + for i = m + 1:n |
| 54 | + vBj += Bbuffer[i,j]'*Rbuffer[k,i]' |
| 55 | + end |
| 56 | + vBj *= τ[k] |
| 57 | + Bbuffer[k,j] -= vBj' |
| 58 | + for i = m + 1:n |
| 59 | + Bbuffer[i,j] -= Rbuffer[k,i]'*vBj' |
| 60 | + end |
| 61 | + end |
| 62 | + end |
| 63 | + end |
| 64 | + end |
| 65 | + return similar_type(B)(Bbuffer) |
| 66 | +end |
| 67 | +function _wide_qr_solve(q::QR, b::StaticVecOrMat) |
| 68 | + Q, R = q.Q, q.R |
| 69 | + y = Q' * b |
| 70 | + return R' * ((R * R') \ y) |
| 71 | +end |
| 72 | + |
17 | 73 | @inline function _solve(::Size{(1,1)}, ::Size{(1,)}, a::StaticMatrix{<:Any, <:Any, Ta}, b::StaticVector{<:Any, Tb}) where {Ta, Tb} |
18 | 74 | @inbounds return similar_type(b, typeof(a[1] \ b[1]))(a[1] \ b[1]) |
19 | 75 | end |
|
80 | 136 | else |
81 | 137 | quote |
82 | 138 | @_inline_meta |
83 | | - q = qr(a) |
| 139 | + q = qr(a, ColumnNorm()) |
84 | 140 | q \ b |
85 | 141 | end |
86 | 142 | end |
|
0 commit comments