Skip to content

Commit e809d34

Browse files
authored
Overload lmul!, rmul! for AbstractQ (#264)
1 parent 255e4ce commit e809d34

File tree

4 files changed

+63
-10
lines changed

4 files changed

+63
-10
lines changed

src/ArrayLayouts.jl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import Base.Broadcast: BroadcastStyle, broadcastable, instantiate, materialize,
1717

1818
using LinearAlgebra: AbstractQ, AbstractTriangular, AdjOrTrans, AdjointAbsVec, HermOrSym, HessenbergQ, QRCompactWYQ,
1919
QRPackedQ, RealHermSymComplexHerm, TransposeAbsVec, _apply_ipiv_rows!, checknonsingular,
20-
checksquare, chkfullrank, cholcopy, ipiv2perm
20+
checksquare, chkfullrank, cholcopy, ipiv2perm, QRCompactWYQ, AdjointQ, QRPackedQ
2121

2222
using LinearAlgebra.BLAS: BlasComplex, BlasFloat, BlasReal
2323

@@ -81,6 +81,10 @@ end
8181
abstract type LayoutArray{T,N} <: AbstractArray{T,N} end
8282
const LayoutMatrix{T} = LayoutArray{T,2}
8383
const LayoutVector{T} = LayoutArray{T,1}
84+
const LayoutVecOrMat{T} = Union{LayoutVector{T},LayoutMatrix{T}}
85+
const LayoutMatrices{T} = Union{LayoutMatrix{T}, SubArray{T,2,<:LayoutMatrix}}
86+
const LayoutVecOrMats{T} = Union{LayoutVecOrMat{T}, SubArray{T,1,<:LayoutVecOrMat}, SubArray{T,2,<:LayoutMatrix}}
87+
8488

8589
## TODO: Following are type piracy which may be removed in Julia v1.5
8690
## No, it can't, because strides(::AdjointAbsMat) is defined only for real eltype!
@@ -374,9 +378,6 @@ end
374378
# printing
375379
###
376380

377-
const LayoutVecOrMat{T} = Union{LayoutVector{T},LayoutMatrix{T}}
378-
const LayoutVecOrMats{T} = Union{LayoutVecOrMat{T},SubArray{T,1,<:LayoutVecOrMat},SubArray{T,2,<:LayoutVecOrMat}}
379-
380381
layout_replace_in_print_matrix(_, A, i, j, s) =
381382
i in colsupport(A,j) ? s : Base.replace_with_centered_mark(s)
382383

src/factorizations.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ mulreduce(M::Mul{<:AbstractQLayout}) = Lmul(M)
134134
mulreduce(M::Mul{<:Any,<:AbstractQLayout}) = Rmul(M)
135135
mulreduce(M::Mul{<:TriangularLayout,<:AbstractQLayout}) = Rmul(M)
136136
mulreduce(M::Mul{<:AbstractQLayout,<:TriangularLayout}) = Lmul(M)
137+
mulreduce(M::Mul{<:DiagonalLayout, <:AbstractQLayout}) = Lmul(M)
138+
mulreduce(M::Mul{<:AbstractQLayout, <:DiagonalLayout}) = Rmul(M)
137139

138140
function copyto!(dest::AbstractArray{T}, M::Lmul{<:AbstractQLayout}) where T
139141
A,B = M.A,M.B
@@ -152,8 +154,8 @@ function copyto!(dest::AbstractArray, M::Ldiv{<:AbstractQLayout})
152154
ldiv!(A,dest)
153155
end
154156

155-
materialize!(M::Lmul{LAY}) where LAY<:AbstractQLayout = error(LazyString("Overload materialize!(::Lmul{", LAY, "})"))
156-
materialize!(M::Rmul{LAY}) where LAY<:AbstractQLayout = error(LazyString("Overload materialize!(::Rmul{", LAY, "})"))
157+
materialize!(M::Lmul{LAY, LAY2}) where {LAY<:AbstractQLayout,LAY2} = error(LazyString("Overload materialize!(::Lmul{", LAY, ", ", LAY2, "})"))
158+
materialize!(M::Rmul{LAY1, LAY}) where {LAY<:AbstractQLayout,LAY1} = error(LazyString("Overload materialize!(::Rmul{", LAY1, ", ", LAY, "})"))
157159

158160
materialize!(M::Ldiv{<:AbstractQLayout}) = materialize!(Lmul(M.A',M.B))
159161

src/lmul.jl

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ end
2828

2929

3030
const MatLmulVec{StyleA,StyleB} = Lmul{StyleA,StyleB,<:Union{AbstractMatrix,AbstractQ},<:AbstractVector}
31-
const MatLmulMat{StyleA,StyleB} = Lmul{StyleA,StyleB,<:AbstractMatrix,<:AbstractMatrix}
31+
const MatLmulMat{StyleA,StyleB} = Lmul{StyleA,StyleB,<:Union{AbstractMatrix,AbstractQ},<:Union{AbstractMatrix,AbstractQ}}
3232

3333
const BlasMatLmulVec{StyleA,StyleB,T<:BlasFloat} = Lmul{StyleA,StyleB,<:Union{AbstractMatrix{T},AbstractQ{T}},<:AbstractVector{T}}
34-
const BlasMatLmulMat{StyleA,StyleB,T<:BlasFloat} = Lmul{StyleA,StyleB,<:AbstractMatrix{T},<:AbstractMatrix{T}}
34+
const BlasMatLmulMat{StyleA,StyleB,T<:BlasFloat} = Lmul{StyleA,StyleB,<:Union{AbstractMatrix{T},AbstractQ{T}},<:Union{AbstractMatrix{T},AbstractQ{T}}}
3535

36-
const MatRmulMat{StyleA,StyleB} = Rmul{StyleA,StyleB,<:AbstractMatrix,<:AbstractMatrix}
37-
const BlasMatRmulMat{StyleA,StyleB,T<:BlasFloat} = Rmul{StyleA,StyleB,<:AbstractMatrix{T},<:AbstractMatrix{T}}
36+
const MatRmulMat{StyleA,StyleB} = Rmul{StyleA,StyleB,<:Union{AbstractMatrix,AbstractQ},<:Union{AbstractMatrix,AbstractQ}}
37+
const BlasMatRmulMat{StyleA,StyleB,T<:BlasFloat} = Rmul{StyleA,StyleB,<:Union{AbstractMatrix{T},AbstractQ{T}},<:Union{AbstractMatrix{T},AbstractQ{T}}}
3838

3939

4040
####
@@ -153,3 +153,22 @@ macro layoutrmul(Typ)
153153
ArrayLayouts.@_layoutrmul UnitLowerTriangular{T, <:Transpose{T,<:$Typ{T}}} where T
154154
end)
155155
end
156+
157+
158+
# TODO: uncomment out. commented for now due to ambiguities
159+
# LinearAlgebra.lmul!(Q::AbstractQ, v::LayoutVecOrMats) = lmul!(Q, v)
160+
# LinearAlgebra.rmul!(A::LayoutMatrices, Q::AbstractQ) = rmul!(A, Q)
161+
162+
for Typ in (:QRCompactWYQ, :QRPackedQ)
163+
@eval begin
164+
LinearAlgebra.lmul!(Q::$Typ{<:Any,<:LayoutMatrix}, v::LayoutVecOrMats) = lmul!(Q, v)
165+
LinearAlgebra.lmul!(Q::$Typ{<:Any,<:LayoutMatrix}, v::AbstractVecOrMat) = lmul!(Q, v)
166+
LinearAlgebra.lmul!(Q::AdjointQ{<:Any,<:$Typ{<:Any,<:LayoutMatrix}}, v::LayoutVecOrMats) = lmul!(Q, v)
167+
LinearAlgebra.lmul!(Q::AdjointQ{<:Any,<:$Typ{<:Any,<:LayoutMatrix}}, v::AbstractVecOrMat) = lmul!(Q, v)
168+
LinearAlgebra.rmul!(V::LayoutMatrices, Q::$Typ{<:Any,<:LayoutMatrix}) = rmul!(V, Q)
169+
LinearAlgebra.rmul!(V::AbstractMatrix, Q::$Typ{<:Any,<:LayoutMatrix}) = rmul!(V, Q)
170+
LinearAlgebra.rmul!(V::LayoutMatrices, Q::AdjointQ{<:Any,<:$Typ{<:Any,<:LayoutMatrix}}) = rmul!(V, Q)
171+
LinearAlgebra.rmul!(V::AbstractMatrix, Q::AdjointQ{<:Any,<:$Typ{<:Any,<:LayoutMatrix}}) = rmul!(V, Q)
172+
LinearAlgebra.rmul!(V::StridedVecOrMat{T}, Q::AdjointQ{<:Any,<:$Typ{T,<:LayoutMatrix}}) where T<:BlasReal = rmul!(V, Q)
173+
end
174+
end

test/test_layoutarray.jl

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,37 @@ Base.copy(A::MyVector) = MyVector(copy(A.A))
602602
@test mul!(copy(B), D, A, 2.0, 3.0) mul!(copy(B), D, V, 2.0, 3.0) 2D * A + 3B
603603
@test mul!(copy(B), A, D, 2.0, 3.0) mul!(copy(B), V, D, 2.0, 3.0) 2A * D + 3B
604604
end
605+
606+
@testset "Diagonal * Q" begin
607+
A = randn(10,5)
608+
= qr(A).Q
609+
Q = LinearAlgebra.QRCompactWYQ(MyMatrix(Q̃.factors), Q̃.T)
610+
D = Diagonal(1:10)
611+
@test ArrayLayouts.mul(D, Q) ArrayLayouts.mul(D, Q̃) D*Q
612+
@test ArrayLayouts.mul(Q, D) ArrayLayouts.mul(Q̃, D) Q*D
613+
end
614+
615+
@testset "QR" begin
616+
A = randn(10,5)
617+
= qr(A).Q
618+
Q = LinearAlgebra.QRCompactWYQ(MyMatrix(Q̃.factors), Q̃.T)
619+
b = randn(10)
620+
B = randn(10,3)
621+
@test Q*b *b lmul!(Q, copy(b)) lmul!(Q, MyVector(copy(b)))
622+
@test Q'b 'b lmul!(Q', copy(b)) lmul!(Q', MyVector(copy(b)))
623+
@test Q*B *B lmul!(Q, copy(B)) lmul!(Q, MyMatrix(copy(B)))
624+
@test Q'B 'B lmul!(Q', copy(B)) lmul!(Q', MyMatrix(copy(B)))
625+
626+
@test B'Q B' rmul!(copy(B'),Q) rmul!(MyMatrix(copy(B')), Q)
627+
@test B'Q' B'' rmul!(copy(B'),Q') rmul!(MyMatrix(copy(B')), Q')
628+
629+
@test_throws ErrorException lmul!(Q, big.(B))
630+
@test_throws ErrorException lmul!(Q', big.(B))
631+
@test_throws ErrorException rmul!(big.(B'),Q')
632+
@test_throws ErrorException rmul!(big.(B'),Q)
633+
634+
@test_broken Q*b lmul!(Q̃, MyVector(copy(b))) # broken due to commented out code for ambiguity with MatrixFactorizations.jl
635+
end
605636
end
606637

607638
struct MyUpperTriangular{T} <: AbstractMatrix{T}

0 commit comments

Comments
 (0)