Skip to content

Commit fad4f2e

Browse files
committed
Don't subtype AbstractQ <: AbstractMatrix
1 parent 0ea2b2d commit fad4f2e

File tree

6 files changed

+136
-170
lines changed

6 files changed

+136
-170
lines changed

stdlib/LinearAlgebra/src/hessenberg.jl

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -570,31 +570,33 @@ function AbstractMatrix(F::Hessenberg)
570570
return A + μ*I # allocate another matrix, e.g. if A is real and μ is complex
571571
end
572572
end
573+
# convert(::Type{AbstractMatrix{T}}, Q::HessenbergQ{T}) where {T} = Q
574+
convert(::Type{AbstractQ{T}}, Q::HessenbergQ{T}) where {T} = Q
573575

574576
# adjoint(Q::HessenbergQ{<:Real})
575577

576578
lmul!(Q::BlasHessenbergQ{T,false}, X::StridedVecOrMat{T}) where {T<:BlasFloat} =
577579
LAPACK.ormhr!('L', 'N', 1, size(Q.factors, 1), Q.factors, Q.τ, X)
578580
rmul!(X::StridedVecOrMat{T}, Q::BlasHessenbergQ{T,false}) where {T<:BlasFloat} =
579581
LAPACK.ormhr!('R', 'N', 1, size(Q.factors, 1), Q.factors, Q.τ, X)
580-
lmul!(adjQ::Adjoint{<:Any,<:BlasHessenbergQ{T,false}}, X::StridedVecOrMat{T}) where {T<:BlasFloat} =
581-
(Q = adjQ.parent; LAPACK.ormhr!('L', ifelse(T<:Real, 'T', 'C'), 1, size(Q.factors, 1), Q.factors, Q.τ, X))
582-
rmul!(X::StridedVecOrMat{T}, adjQ::Adjoint{<:Any,<:BlasHessenbergQ{T,false}}) where {T<:BlasFloat} =
583-
(Q = adjQ.parent; LAPACK.ormhr!('R', ifelse(T<:Real, 'T', 'C'), 1, size(Q.factors, 1), Q.factors, Q.τ, X))
582+
lmul!(adjQ::AdjointQ{<:Any,<:BlasHessenbergQ{T,false}}, X::StridedVecOrMat{T}) where {T<:BlasFloat} =
583+
(Q = adjQ.Q; LAPACK.ormhr!('L', ifelse(T<:Real, 'T', 'C'), 1, size(Q.factors, 1), Q.factors, Q.τ, X))
584+
rmul!(X::StridedVecOrMat{T}, adjQ::AdjointQ{<:Any,<:BlasHessenbergQ{T,false}}) where {T<:BlasFloat} =
585+
(Q = adjQ.Q; LAPACK.ormhr!('R', ifelse(T<:Real, 'T', 'C'), 1, size(Q.factors, 1), Q.factors, Q.τ, X))
584586

585587
lmul!(Q::BlasHessenbergQ{T,true}, X::StridedVecOrMat{T}) where {T<:BlasFloat} =
586588
LAPACK.ormtr!('L', Q.uplo, 'N', Q.factors, Q.τ, X)
587589
rmul!(X::StridedVecOrMat{T}, Q::BlasHessenbergQ{T,true}) where {T<:BlasFloat} =
588590
LAPACK.ormtr!('R', Q.uplo, 'N', Q.factors, Q.τ, X)
589-
lmul!(adjQ::Adjoint{<:Any,<:BlasHessenbergQ{T,true}}, X::StridedVecOrMat{T}) where {T<:BlasFloat} =
590-
(Q = adjQ.parent; LAPACK.ormtr!('L', Q.uplo, ifelse(T<:Real, 'T', 'C'), Q.factors, Q.τ, X))
591-
rmul!(X::StridedVecOrMat{T}, adjQ::Adjoint{<:Any,<:BlasHessenbergQ{T,true}}) where {T<:BlasFloat} =
592-
(Q = adjQ.parent; LAPACK.ormtr!('R', Q.uplo, ifelse(T<:Real, 'T', 'C'), Q.factors, Q.τ, X))
591+
lmul!(adjQ::AdjointQ{<:Any,<:BlasHessenbergQ{T,true}}, X::StridedVecOrMat{T}) where {T<:BlasFloat} =
592+
(Q = adjQ.Q; LAPACK.ormtr!('L', Q.uplo, ifelse(T<:Real, 'T', 'C'), Q.factors, Q.τ, X))
593+
rmul!(X::StridedVecOrMat{T}, adjQ::AdjointQ{<:Any,<:BlasHessenbergQ{T,true}}) where {T<:BlasFloat} =
594+
(Q = adjQ.Q; LAPACK.ormtr!('R', Q.uplo, ifelse(T<:Real, 'T', 'C'), Q.factors, Q.τ, X))
593595

594596
lmul!(Q::HessenbergQ{T}, X::Adjoint{T,<:StridedVecOrMat{T}}) where {T} = rmul!(X', Q')'
595597
rmul!(X::Adjoint{T,<:StridedVecOrMat{T}}, Q::HessenbergQ{T}) where {T} = lmul!(Q', X')'
596-
lmul!(adjQ::Adjoint{<:Any,<:HessenbergQ{T}}, X::Adjoint{T,<:StridedVecOrMat{T}}) where {T} = rmul!(X', adjQ')'
597-
rmul!(X::Adjoint{T,<:StridedVecOrMat{T}}, adjQ::Adjoint{<:Any,<:HessenbergQ{T}}) where {T} = lmul!(adjQ', X')'
598+
lmul!(adjQ::AdjointQ{<:Any,<:HessenbergQ{T}}, X::Adjoint{T,<:StridedVecOrMat{T}}) where {T} = rmul!(X', adjQ')'
599+
rmul!(X::Adjoint{T,<:StridedVecOrMat{T}}, adjQ::AdjointQ{<:Any,<:HessenbergQ{T}}) where {T} = lmul!(adjQ', X')'
598600

599601
# multiply x by the entries of M in the upper-k triangle, which contains
600602
# the entries of the upper-Hessenberg matrix H for k=-1

stdlib/LinearAlgebra/src/qr.jl

Lines changed: 103 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -516,12 +516,18 @@ Base.propertynames(F::QRPivoted, private::Bool=false) =
516516

517517
adjoint(F::Union{QR,QRPivoted,QRCompactWY}) = Adjoint(F)
518518

519-
abstract type AbstractQ{T} <: AbstractMatrix{T} end
519+
abstract type AbstractQ{T} end
520+
struct AdjointQ{T,S<:AbstractQ{T}} <: AbstractQ{T}
521+
Q::S
522+
end
520523

521524
inv(Q::AbstractQ) = Q'
525+
adjoint(Q::AbstractQ) = AdjointQ(Q)
526+
adjoint(adjQ::AdjointQ) = adjQ.Q
527+
eltype(::AbstractQ{T}) where {T} = T
522528

523529
"""
524-
QRPackedQ <: AbstractMatrix
530+
QRPackedQ <: LinearAlgebra.AbstractQ
525531
526532
The orthogonal/unitary ``Q`` matrix of a QR factorization stored in [`QR`](@ref) or
527533
[`QRPivoted`](@ref) format.
@@ -544,7 +550,7 @@ QRPackedQ{T}(factors::AbstractMatrix, τ::AbstractVector) where {T} =
544550
QRPackedQ{T,S,typeof(τ)}(factors, τ), false)
545551

546552
"""
547-
QRCompactWYQ <: AbstractMatrix
553+
QRCompactWYQ <: LinearAlgebra.AbstractQ
548554
549555
The orthogonal/unitary ``Q`` matrix of a QR factorization stored in [`QRCompactWY`](@ref)
550556
format.
@@ -572,16 +578,25 @@ AbstractMatrix{T}(Q::QRPackedQ) where {T} = QRPackedQ{T}(Q)
572578
QRCompactWYQ{S}(Q::QRCompactWYQ) where {S} = QRCompactWYQ(convert(AbstractMatrix{S}, Q.factors), convert(AbstractMatrix{S}, Q.T))
573579
AbstractMatrix{S}(Q::QRCompactWYQ{S}) where {S} = Q
574580
AbstractMatrix{S}(Q::QRCompactWYQ) where {S} = QRCompactWYQ{S}(Q)
575-
Matrix{T}(Q::AbstractQ{S}) where {T,S} = Matrix{T}(lmul!(Q, Matrix{S}(I, size(Q, 1), min(size(Q.factors)...))))
581+
Matrix{T}(Q::AbstractQ{S}) where {T,S} = convert(Matrix{T}, lmul!(Q, Matrix{S}(I, size(Q, 1), min(size(Q.factors)...))))
576582
Matrix(Q::AbstractQ{T}) where {T} = Matrix{T}(Q)
577583
Array{T}(Q::AbstractQ) where {T} = Matrix{T}(Q)
578584
Array(Q::AbstractQ) = Matrix(Q)
585+
convert(::Type{Array}, Q::AbstractQ) = Matrix(Q)
586+
convert(::Type{Matrix}, Q::AbstractQ) = Matrix(Q)
587+
# legacy
588+
@deprecate(convert(::Type{AbstractMatrix{T}}, Q::AbstractQ) where {T},
589+
convert(LinearAlgebra.AbstractQ{T}, Q))
590+
convert(::Type{AbstractQ{T}}, Q::QRPackedQ) where {T} = QRPackedQ{T}(Q)
591+
convert(::Type{AbstractQ{T}}, Q::QRCompactWYQ) where {T} = QRCompactWYQ{T}(Q)
592+
convert(::Type{AbstractQ{T}}, adjQ::AdjointQ) where {T} = adjoint(convert(AbstractQ{T}, adjQ.Q))
579593

580594
size(F::Union{QR,QRCompactWY,QRPivoted}, dim::Integer) = size(getfield(F, :factors), dim)
581595
size(F::Union{QR,QRCompactWY,QRPivoted}) = size(getfield(F, :factors))
582596
size(Q::Union{QRCompactWYQ,QRPackedQ}, dim::Integer) =
583597
size(getfield(Q, :factors), dim == 2 ? 1 : dim)
584598
size(Q::Union{QRCompactWYQ,QRPackedQ}) = size(Q, 1), size(Q, 2)
599+
size(adjQ::AdjointQ) = size(adjQ.Q, 2), size(adjQ.Q, 1)
585600

586601
copymutable(Q::AbstractQ{T}) where {T} = lmul!(Q, Matrix{T}(I, size(Q)))
587602
copy(Q::AbstractQ) = copymutable(Q)
@@ -596,6 +611,9 @@ end
596611

597612
getindex(Q::AbstractQ, i::Int, j::Int) = Q[:, j][i]
598613

614+
# needed because AbstractQ does not subtype AbstractMatrix
615+
qr(Q::AbstractQ, arg...; kwargs...) = qr!(Matrix(Q), arg...; kwargs...)
616+
599617
# specialization avoiding the fallback using slow `getindex`
600618
function copyto!(dest::AbstractMatrix, src::AbstractQ)
601619
copyto!(dest, I)
@@ -653,50 +671,49 @@ function lmul!(A::QRPackedQ, B::AbstractVecOrMat)
653671
B
654672
end
655673

656-
function (*)(A::AbstractQ, b::StridedVector)
657-
TAb = promote_type(eltype(A), eltype(b))
658-
Anew = convert(AbstractMatrix{TAb}, A)
659-
if size(A.factors, 1) == length(b)
660-
bnew = copymutable_oftype(b, TAb)
661-
elseif size(A.factors, 2) == length(b)
662-
bnew = [b; zeros(TAb, size(A.factors, 1) - length(b))]
674+
function (*)(Q::AbstractQ, b::AbstractVector)
675+
TQb = promote_type(eltype(Q), eltype(b))
676+
QQ = convert(AbstractQ{TQb}, Q)
677+
if size(Q.factors, 1) == length(b)
678+
bnew = copy_similar(b, TQb)
679+
elseif size(Q.factors, 2) == length(b)
680+
bnew = [b; zeros(TQb, size(Q.factors, 1) - length(b))]
663681
else
664-
throw(DimensionMismatch("vector must have length either $(size(A.factors, 1)) or $(size(A.factors, 2))"))
682+
throw(DimensionMismatch("vector must have length either $(size(Q.factors, 1)) or $(size(Q.factors, 2))"))
665683
end
666-
lmul!(Anew, bnew)
684+
lmul!(QQ, bnew)
667685
end
668-
function (*)(A::AbstractQ, B::StridedMatrix)
669-
TAB = promote_type(eltype(A), eltype(B))
670-
Anew = convert(AbstractMatrix{TAB}, A)
671-
if size(A.factors, 1) == size(B, 1)
672-
Bnew = copymutable_oftype(B, TAB)
673-
elseif size(A.factors, 2) == size(B, 1)
674-
Bnew = [B; zeros(TAB, size(A.factors, 1) - size(B,1), size(B, 2))]
686+
function (*)(Q::AbstractQ, B::AbstractMatrix)
687+
TQB = promote_type(eltype(Q), eltype(B))
688+
QQ = convert(AbstractQ{TQB}, Q)
689+
if size(Q.factors, 1) == size(B, 1)
690+
Bnew = copy_similar(B, TQB)
691+
elseif size(Q.factors, 2) == size(B, 1)
692+
Bnew = [B; zeros(TQB, size(Q.factors, 1) - size(B,1), size(B, 2))]
675693
else
676-
throw(DimensionMismatch("first dimension of matrix must have size either $(size(A.factors, 1)) or $(size(A.factors, 2))"))
694+
throw(DimensionMismatch("first dimension of matrix must have size either $(size(Q.factors, 1)) or $(size(Q.factors, 2))"))
677695
end
678-
lmul!(Anew, Bnew)
696+
lmul!(QQ, Bnew)
679697
end
680698

681-
function (*)(A::AbstractQ, b::Number)
682-
TAb = promote_type(eltype(A), typeof(b))
683-
dest = similar(A, TAb)
684-
copyto!(dest, b*I)
685-
lmul!(A, dest)
699+
function (*)(Q::AbstractQ, b::Number)
700+
TQb = promote_type(eltype(Q), typeof(b))
701+
dest = Matrix{TQb}(b*I, size(Q))
702+
lmul!(convert(AbstractQ{TQb}, Q), dest)
686703
end
687704

688705
### QcB
689-
lmul!(adjA::Adjoint{<:Any,<:QRCompactWYQ{T,S}}, B::StridedVecOrMat{T}) where {T<:BlasReal,S<:StridedMatrix} =
690-
(A = adjA.parent; LAPACK.gemqrt!('L', 'T', A.factors, A.T, B))
691-
lmul!(adjA::Adjoint{<:Any,<:QRCompactWYQ{T,S}}, B::StridedVecOrMat{T}) where {T<:BlasComplex,S<:StridedMatrix} =
692-
(A = adjA.parent; LAPACK.gemqrt!('L', 'C', A.factors, A.T, B))
693-
lmul!(adjA::Adjoint{<:Any,<:QRPackedQ{T,S}}, B::StridedVecOrMat{T}) where {T<:BlasReal,S<:StridedMatrix} =
694-
(A = adjA.parent; LAPACK.ormqr!('L', 'T', A.factors, A.τ, B))
695-
lmul!(adjA::Adjoint{<:Any,<:QRPackedQ{T,S}}, B::StridedVecOrMat{T}) where {T<:BlasComplex,S<:StridedMatrix} =
696-
(A = adjA.parent; LAPACK.ormqr!('L', 'C', A.factors, A.τ, B))
697-
function lmul!(adjA::Adjoint{<:Any,<:QRPackedQ}, B::AbstractVecOrMat)
706+
lmul!(adjQ::AdjointQ{<:Any,<:QRCompactWYQ{T,S}}, B::StridedVecOrMat{T}) where {T<:BlasReal,S<:StridedMatrix} =
707+
(Q = adjQ.Q; LAPACK.gemqrt!('L', 'T', Q.factors, Q.T, B))
708+
lmul!(adjQ::AdjointQ{<:Any,<:QRCompactWYQ{T,S}}, B::StridedVecOrMat{T}) where {T<:BlasComplex,S<:StridedMatrix} =
709+
(Q = adjQ.Q; LAPACK.gemqrt!('L', 'C', Q.factors, Q.T, B))
710+
lmul!(adjQ::AdjointQ{<:Any,<:QRPackedQ{T,S}}, B::StridedVecOrMat{T}) where {T<:BlasReal,S<:StridedMatrix} =
711+
(Q = adjQ.Q; LAPACK.ormqr!('L', 'T', Q.factors, Q.τ, B))
712+
lmul!(adjQ::AdjointQ{<:Any,<:QRPackedQ{T,S}}, B::StridedVecOrMat{T}) where {T<:BlasComplex,S<:StridedMatrix} =
713+
(Q = adjQ.Q; LAPACK.ormqr!('L', 'C', Q.factors, Q.τ, B))
714+
function lmul!(adjA::AdjointQ{<:Any,<:QRPackedQ}, B::AbstractVecOrMat)
698715
require_one_based_indexing(B)
699-
A = adjA.parent
716+
A = adjA.Q
700717
mA, nA = size(A.factors)
701718
mB, nB = size(B,1), size(B,2)
702719
if mA != mB
@@ -720,26 +737,26 @@ function lmul!(adjA::Adjoint{<:Any,<:QRPackedQ}, B::AbstractVecOrMat)
720737
end
721738
B
722739
end
723-
function *(adjQ::Adjoint{<:Any,<:AbstractQ}, B::StridedVecOrMat)
724-
Q = adjQ.parent
725-
TQB = promote_type(eltype(Q), eltype(B))
726-
return lmul!(adjoint(convert(AbstractMatrix{TQB}, Q)), copymutable_oftype(B, TQB))
740+
function *(adjQ::AdjointQ, B::AbstractMatrix)
741+
TQB = promote_type(eltype(adjQ), eltype(B))
742+
return lmul!(convert(AbstractQ{TQB}, adjQ), copy_similar(B, TQB))
727743
end
728744

729745
### QBc/QcBc
730-
function *(Q::AbstractQ, adjB::Adjoint{<:Any,<:StridedVecOrMat})
746+
function *(Q::AbstractQ, adjB::Adjoint{<:Any,<:AbstractVecOrMat})
731747
B = adjB.parent
732748
TQB = promote_type(eltype(Q), eltype(B))
733749
Bc = similar(B, TQB, (size(B, 2), size(B, 1)))
734750
adjoint!(Bc, B)
735-
return lmul!(convert(AbstractMatrix{TQB}, Q), Bc)
751+
return lmul!(convert(AbstractQ{TQB}, Q), Bc)
736752
end
737-
function *(adjQ::Adjoint{<:Any,<:AbstractQ}, adjB::Adjoint{<:Any,<:StridedVecOrMat})
738-
Q, B = adjQ.parent, adjB.parent
739-
TQB = promote_type(eltype(Q), eltype(B))
753+
# disambiguation
754+
function *(adjQ::AdjointQ, adjB::Adjoint{<:Any,<:AbstractVecOrMat})
755+
B = adjB.parent
756+
TQB = promote_type(eltype(adjQ), eltype(B))
740757
Bc = similar(B, TQB, (size(B, 2), size(B, 1)))
741758
adjoint!(Bc, B)
742-
return lmul!(adjoint(convert(AbstractMatrix{TQB}, Q)), Bc)
759+
return lmul!(convert(AbstractQ{TQB}, adjQ), Bc)
743760
end
744761

745762
### AQ
@@ -772,30 +789,27 @@ function rmul!(A::StridedMatrix,Q::QRPackedQ)
772789
A
773790
end
774791

775-
function (*)(A::StridedMatrix, Q::AbstractQ)
792+
function (*)(A::AbstractMatrix, Q::AbstractQ)
776793
TAQ = promote_type(eltype(A), eltype(Q))
777-
778-
return rmul!(copymutable_oftype(A, TAQ), convert(AbstractMatrix{TAQ}, Q))
794+
return rmul!(copy_similar(A, TAQ), convert(AbstractQ{TAQ}, Q))
779795
end
780-
781-
function (*)(a::Number, B::AbstractQ)
782-
TaB = promote_type(typeof(a), eltype(B))
783-
dest = similar(B, TaB)
784-
copyto!(dest, a*I)
785-
rmul!(dest, B)
796+
function (*)(a::Number, Q::AbstractQ)
797+
TaQ = promote_type(typeof(a), eltype(Q))
798+
dest = Matrix{TaQ}(a*I, size(Q))
799+
rmul!(dest, convert(AbstractQ{TaQ}, Q))
786800
end
787801

788802
### AQc
789-
rmul!(A::StridedVecOrMat{T}, adjB::Adjoint{<:Any,<:QRCompactWYQ{T}}) where {T<:BlasReal} =
790-
(B = adjB.parent; LAPACK.gemqrt!('R', 'T', B.factors, B.T, A))
791-
rmul!(A::StridedVecOrMat{T}, adjB::Adjoint{<:Any,<:QRCompactWYQ{T}}) where {T<:BlasComplex} =
792-
(B = adjB.parent; LAPACK.gemqrt!('R', 'C', B.factors, B.T, A))
793-
rmul!(A::StridedVecOrMat{T}, adjB::Adjoint{<:Any,<:QRPackedQ{T}}) where {T<:BlasReal} =
794-
(B = adjB.parent; LAPACK.ormqr!('R', 'T', B.factors, B.τ, A))
795-
rmul!(A::StridedVecOrMat{T}, adjB::Adjoint{<:Any,<:QRPackedQ{T}}) where {T<:BlasComplex} =
796-
(B = adjB.parent; LAPACK.ormqr!('R', 'C', B.factors, B.τ, A))
797-
function rmul!(A::StridedMatrix, adjQ::Adjoint{<:Any,<:QRPackedQ})
798-
Q = adjQ.parent
803+
rmul!(A::StridedVecOrMat{T}, adjQ::AdjointQ{<:Any,<:QRCompactWYQ{T}}) where {T<:BlasReal} =
804+
(Q = adjQ.Q; LAPACK.gemqrt!('R', 'T', Q.factors, Q.T, A))
805+
rmul!(A::StridedVecOrMat{T}, adjQ::AdjointQ{<:Any,<:QRCompactWYQ{T}}) where {T<:BlasComplex} =
806+
(Q = adjQ.Q; LAPACK.gemqrt!('R', 'C', Q.factors, Q.T, A))
807+
rmul!(A::StridedVecOrMat{T}, adjQ::AdjointQ{<:Any,<:QRPackedQ{T}}) where {T<:BlasReal} =
808+
(Q = adjQ.Q; LAPACK.ormqr!('R', 'T', Q.factors, Q.τ, A))
809+
rmul!(A::StridedVecOrMat{T}, adjQ::AdjointQ{<:Any,<:QRPackedQ{T}}) where {T<:BlasComplex} =
810+
(Q = adjQ.Q; LAPACK.ormqr!('R', 'C', Q.factors, Q.τ, A))
811+
function rmul!(A::StridedMatrix, adjQ::AdjointQ{<:Any,<:QRPackedQ})
812+
Q = adjQ.Q
799813
mQ, nQ = size(Q.factors)
800814
mA, nA = size(A,1), size(A,2)
801815
if nA != mQ
@@ -819,40 +833,41 @@ function rmul!(A::StridedMatrix, adjQ::Adjoint{<:Any,<:QRPackedQ})
819833
end
820834
A
821835
end
822-
function *(A::StridedMatrix, adjB::Adjoint{<:Any,<:AbstractQ})
823-
B = adjB.parent
824-
TAB = promote_type(eltype(A),eltype(B))
825-
BB = convert(AbstractMatrix{TAB}, B)
826-
if size(A,2) == size(B.factors, 1)
827-
AA = copy_similar(A, TAB)
828-
return rmul!(AA, adjoint(BB))
829-
elseif size(A,2) == size(B.factors,2)
830-
return rmul!([A zeros(TAB, size(A, 1), size(B.factors, 1) - size(B.factors, 2))], adjoint(BB))
836+
function *(A::AbstractMatrix, adjQ::AdjointQ)
837+
Q = adjQ.Q
838+
TAQ = promote_type(eltype(A),eltype(Q))
839+
QQ = convert(AbstractQ{TAQ}, Q)
840+
if size(A,2) == size(Q.factors, 1)
841+
AA = copy_similar(A, TAQ)
842+
return rmul!(AA, adjoint(QQ))
843+
elseif size(A,2) == size(Q.factors,2)
844+
return rmul!([A zeros(TAQ, size(A, 1), size(Q.factors, 1) - size(Q.factors, 2))], adjoint(QQ))
831845
else
832-
throw(DimensionMismatch("matrix A has dimensions $(size(A)) but matrix B has dimensions $(size(B))"))
846+
throw(DimensionMismatch("matrix A has dimensions $(size(A)) but matrix B has dimensions $(size(Q))"))
833847
end
834848
end
835-
*(u::AdjointAbsVec, A::Adjoint{<:Any,<:AbstractQ}) = adjoint(A.parent * u.parent)
836-
849+
*(u::AdjointAbsVec, adjQ::AdjointQ) = adjoint(adjQ.Q * u.parent)
850+
*(a::AbstractVector, adjQ::AdjointQ) = reshape(a, length(a), 1) * adjQ
837851

838852
### AcQ/AcQc
839-
function *(adjA::Adjoint{<:Any,<:StridedVecOrMat}, Q::AbstractQ)
853+
function *(adjA::Adjoint{<:Any,<:AbstractVecOrMat}, Q::AbstractQ)
840854
A = adjA.parent
841855
TAQ = promote_type(eltype(A), eltype(Q))
842856
Ac = similar(A, TAQ, (size(A, 2), size(A, 1)))
843857
adjoint!(Ac, A)
844-
return rmul!(Ac, convert(AbstractMatrix{TAQ}, Q))
858+
return rmul!(Ac, convert(AbstractQ{TAQ}, Q))
845859
end
846-
function *(adjA::Adjoint{<:Any,<:StridedVecOrMat}, adjQ::Adjoint{<:Any,<:AbstractQ})
847-
A, Q = adjA.parent, adjQ.parent
848-
TAQ = promote_type(eltype(A), eltype(Q))
860+
# disambiguation
861+
function *(adjA::Adjoint{<:Any,<:AbstractVecOrMat}, adjQ::AdjointQ)
862+
A = adjA.parent
863+
TAQ = promote_type(eltype(A), eltype(adjQ))
849864
Ac = similar(A, TAQ, (size(A, 2), size(A, 1)))
850865
adjoint!(Ac, A)
851-
return rmul!(Ac, adjoint(convert(AbstractMatrix{TAQ}, Q)))
866+
return rmul!(Ac, convert(AbstractQ{TAQ}, adjQ))
852867
end
853868

854869
### mul!
855-
function mul!(C::StridedVecOrMat{T}, Q::AbstractQ{T}, B::StridedVecOrMat{T}) where {T}
870+
function mul!(C::StridedVecOrMat{T}, Q::AbstractQ{T}, B::AbstractVecOrMat{T}) where {T}
856871
require_one_based_indexing(C, B)
857872
mB = size(B, 1)
858873
mC = size(C, 1)
@@ -865,9 +880,9 @@ function mul!(C::StridedVecOrMat{T}, Q::AbstractQ{T}, B::StridedVecOrMat{T}) whe
865880
return lmul!(Q, copyto!(C, B))
866881
end
867882
end
868-
mul!(C::StridedVecOrMat{T}, A::StridedVecOrMat{T}, Q::AbstractQ{T}) where {T} = rmul!(copyto!(C, A), Q)
869-
mul!(C::StridedVecOrMat{T}, adjQ::Adjoint{<:Any,<:AbstractQ{T}}, B::StridedVecOrMat{T}) where {T} = lmul!(adjQ, copyto!(C, B))
870-
mul!(C::StridedVecOrMat{T}, A::StridedVecOrMat{T}, adjQ::Adjoint{<:Any,<:AbstractQ{T}}) where {T} = rmul!(copyto!(C, A), adjQ)
883+
mul!(C::StridedVecOrMat{T}, A::AbstractVecOrMat{T}, Q::AbstractQ{T}) where {T} = rmul!(copyto!(C, A), Q)
884+
mul!(C::StridedVecOrMat{T}, adjQ::AdjointQ{<:Any,<:AbstractQ{T}}, B::AbstractVecOrMat{T}) where {T} = lmul!(adjQ, copyto!(C, B))
885+
mul!(C::StridedVecOrMat{T}, A::AbstractVecOrMat{T}, adjQ::AdjointQ{<:Any,<:AbstractQ{T}}) where {T} = rmul!(copyto!(C, A), adjQ)
871886

872887
function ldiv!(A::QRCompactWY{T}, b::StridedVector{T}) where {T<:BlasFloat}
873888
m,n = size(A)

0 commit comments

Comments
 (0)