Skip to content

Commit 0830823

Browse files
dkarraschKristofferC
authored andcommitted
Fix multiplication of AbstractQs (#46237)
(cherry picked from commit 947c908)
1 parent bc457f6 commit 0830823

File tree

3 files changed

+29
-16
lines changed

3 files changed

+29
-16
lines changed

stdlib/LinearAlgebra/src/qr.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,9 +380,9 @@ norm solution.
380380
381381
Multiplication with respect to either full/square or non-full/square `Q` is allowed, i.e. both `F.Q*F.R`
382382
and `F.Q*A` are supported. A `Q` matrix can be converted into a regular matrix with
383-
[`Matrix`](@ref). This operation returns the "thin" Q factor, i.e., if `A` is `m`×`n` with `m>=n`, then
383+
[`Matrix`](@ref). This operation returns the "thin" Q factor, i.e., if `A` is `m`×`n` with `m>=n`, then
384384
`Matrix(F.Q)` yields an `m`×`n` matrix with orthonormal columns. To retrieve the "full" Q factor, an
385-
`m`×`m` orthogonal matrix, use `F.Q*Matrix(I,m,m)`. If `m<=n`, then `Matrix(F.Q)` yields an `m`×`m`
385+
`m`×`m` orthogonal matrix, use `F.Q*I`. If `m<=n`, then `Matrix(F.Q)` yields an `m`×`m`
386386
orthogonal matrix.
387387
388388
The block size for QR decomposition can be specified by keyword argument

stdlib/LinearAlgebra/src/special.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -347,10 +347,10 @@ end
347347
*(A::Diagonal, Q::AbstractQ) = _qrmul(A, Q)
348348
*(A::Diagonal, Q::Adjoint{<:Any,<:AbstractQ}) = _qrmul(A, Q)
349349

350-
*(Q::AbstractQ, B::AbstractQ) = _qlmul(Q, B)
351-
*(Q::Adjoint{<:Any,<:AbstractQ}, B::AbstractQ) = _qrmul(Q, B)
352-
*(Q::AbstractQ, B::Adjoint{<:Any,<:AbstractQ}) = _qlmul(Q, B)
353-
*(Q::Adjoint{<:Any,<:AbstractQ}, B::Adjoint{<:Any,<:AbstractQ}) = _qrmul(Q, B)
350+
*(Q::AbstractQ, B::AbstractQ) = Q * (B * I)
351+
*(Q::Adjoint{<:Any,<:AbstractQ}, B::AbstractQ) = Q * (B * I)
352+
*(Q::AbstractQ, B::Adjoint{<:Any,<:AbstractQ}) = Q * (B * I)
353+
*(Q::Adjoint{<:Any,<:AbstractQ}, B::Adjoint{<:Any,<:AbstractQ}) = Q * (B * I)
354354

355355
# fill[stored]! methods
356356
fillstored!(A::Diagonal, x) = (fill!(A.diag, x); A)

stdlib/LinearAlgebra/test/special.jl

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -215,16 +215,29 @@ end
215215
atri = typ(a)
216216
matri = Matrix(atri)
217217
b = rand(n,n)
218-
qrb = qr(b, ColumnNorm())
219-
@test atri * qrb.Q matri * qrb.Q rmul!(copy(atri), qrb.Q)
220-
@test atri * qrb.Q' matri * qrb.Q' rmul!(copy(atri), qrb.Q')
221-
@test qrb.Q * atri qrb.Q * matri lmul!(qrb.Q, copy(atri))
222-
@test qrb.Q' * atri qrb.Q' * matri lmul!(qrb.Q', copy(atri))
223-
qrb = qr(b, NoPivot())
224-
@test atri * qrb.Q matri * qrb.Q rmul!(copy(atri), qrb.Q)
225-
@test atri * qrb.Q' matri * qrb.Q' rmul!(copy(atri), qrb.Q')
226-
@test qrb.Q * atri qrb.Q * matri lmul!(qrb.Q, copy(atri))
227-
@test qrb.Q' * atri qrb.Q' * matri lmul!(qrb.Q', copy(atri))
218+
for pivot in (ColumnNorm(), NoPivot())
219+
qrb = qr(b, pivot)
220+
@test atri * qrb.Q matri * qrb.Q rmul!(copy(atri), qrb.Q)
221+
@test atri * qrb.Q' matri * qrb.Q' rmul!(copy(atri), qrb.Q')
222+
@test qrb.Q * atri qrb.Q * matri lmul!(qrb.Q, copy(atri))
223+
@test qrb.Q' * atri qrb.Q' * matri lmul!(qrb.Q', copy(atri))
224+
end
225+
end
226+
end
227+
228+
@testset "Multiplication of Qs" begin
229+
for pivot in (ColumnNorm(), NoPivot()), A in (rand(5, 3), rand(5, 5), rand(3, 5))
230+
Q = qr(A, pivot).Q
231+
m = size(A, 1)
232+
C = Matrix{Float64}(undef, (m, m))
233+
@test Q*Q (Q*I) * (Q*I) mul!(C, Q, Q)
234+
@test size(Q*Q) == (m, m)
235+
@test Q'Q (Q'*I) * (Q*I) mul!(C, Q', Q)
236+
@test size(Q'Q) == (m, m)
237+
@test Q*Q' (Q*I) * (Q'*I) mul!(C, Q, Q')
238+
@test size(Q*Q') == (m, m)
239+
@test Q'Q' (Q'*I) * (Q'*I) mul!(C, Q', Q')
240+
@test size(Q'Q') == (m, m)
228241
end
229242
end
230243

0 commit comments

Comments
 (0)