Skip to content

Commit

Permalink
Minor AbstractQ audit (JuliaLang#49363)
Browse files Browse the repository at this point in the history
  • Loading branch information
dkarrasch committed Apr 17, 2023
1 parent 3ce7a9b commit 78fd05a
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 12 deletions.
16 changes: 9 additions & 7 deletions stdlib/LinearAlgebra/src/abstractq.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@ promote_rule(::Type{<:AbstractMatrix{T}}, ::Type{<:AbstractQ{T}}) where {T} =
(@inline; Union{AbstractMatrix{T},AbstractQ{T}})

# conversion
AbstractQ{S}(Q::AbstractQ{S}) where {S} = Q
# the following eltype promotion needs to be defined for each subtype
# the following eltype promotion should be defined for each subtype `QType`
# convert(::Type{AbstractQ{T}}, Q::QType) where {T} = QType{T}(Q)
# and then care has to be taken that
# QType{T}(Q::QType{T}) where T = ...
# is implemented as a no-op

# the following conversion method ensures functionality when the above method is not defined
# (as for HessenbergQ), but no eltype conversion is required either (say, in multiplication)
convert(::Type{AbstractQ{T}}, Q::AbstractQ{T}) where {T} = Q
convert(::Type{AbstractQ{T}}, adjQ::AdjointQ{T}) where {T} = adjQ
convert(::Type{AbstractQ{T}}, adjQ::AdjointQ) where {T} = convert(AbstractQ{T}, adjQ.Q)'
Expand All @@ -36,7 +41,6 @@ Matrix(Q::AbstractQ{T}) where {T} = Matrix{T}(Q)
Array{T}(Q::AbstractQ) where {T} = Matrix{T}(Q)
Array(Q::AbstractQ) = Matrix(Q)
convert(::Type{T}, Q::AbstractQ) where {T<:Array} = T(Q)
convert(::Type{T}, Q::AbstractQ) where {T<:Matrix} = T(Q)
# legacy
@deprecate(convert(::Type{AbstractMatrix{T}}, Q::AbstractQ) where {T},
convert(LinearAlgebra.AbstractQ{T}, Q))
Expand Down Expand Up @@ -227,11 +231,9 @@ QRCompactWYQ{S}(factors::AbstractMatrix, T::AbstractMatrix) where {S} =
@deprecate(QRCompactWYQ{S,M}(factors::AbstractMatrix{S}, T::AbstractMatrix{S}) where {S,M},
QRCompactWYQ{S,M,typeof(T)}(factors, T), false)

QRPackedQ{T}(Q::QRPackedQ) where {T} = QRPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(Vector{T}, Q.τ))
QRPackedQ{T}(Q::QRPackedQ) where {T} = QRPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(AbstractVector{T}, Q.τ))
QRCompactWYQ{S}(Q::QRCompactWYQ) where {S} = QRCompactWYQ(convert(AbstractMatrix{S}, Q.factors), convert(AbstractMatrix{S}, Q.T))

AbstractQ{S}(Q::QRPackedQ) where {S} = QRPackedQ{S}(Q)
AbstractQ{S}(Q::QRCompactWYQ) where {S} = QRCompactWYQ{S}(Q)
# override generic square fallback
Matrix{T}(Q::Union{QRCompactWYQ{S},QRPackedQ{S}}) where {T,S} =
convert(Matrix{T}, lmul!(Q, Matrix{S}(I, size(Q, 1), min(size(Q.factors)...))))
Expand Down Expand Up @@ -505,7 +507,7 @@ struct LQPackedQ{T,S<:AbstractMatrix{T},C<:AbstractVector{T}} <: AbstractQ{T}
τ::C
end

LQPackedQ{T}(Q::LQPackedQ) where {T} = LQPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(Vector{T}, Q.τ))
LQPackedQ{T}(Q::LQPackedQ) where {T} = LQPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(AbstractVector{T}, Q.τ))
@deprecate(AbstractMatrix{T}(Q::LQPackedQ) where {T},
convert(AbstractQ{T}, Q),
false)
Expand Down
14 changes: 9 additions & 5 deletions stdlib/LinearAlgebra/test/abstractq.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ n = 5
A = rand(T, n, n)
F = qr(A)
Q = MyQ(F.Q)
@test ndims(Q) == 2
T <: Real && @test transpose(Q) == adjoint(Q)
T <: Complex && @test_throws ErrorException transpose(Q)
@test convert(AbstractQ{complex(T)}, Q) isa MyQ{complex(T)}
@test convert(AbstractQ{complex(T)}, Q') isa AdjointQ{<:complex(T),<:MyQ{complex(T)}}
@test Q*I Q.Q*I rtol=2eps(real(T))
Expand All @@ -50,14 +53,15 @@ n = 5
@test mul!(X, transQ(Q), transY(Y)) transQ(Q) * transY(Y) transQ(Q.Q) * transY(Y)
@test mul!(X, transY(Y), transQ(Q)) transY(Y) * transQ(Q) transY(Y) * transQ(Q.Q)
end
@test Matrix(Q) Q[:,:] copyto!(zeros(T, size(Q)), Q) Q.Q*I
@test Matrix(Q') (Q')[:,:] copyto!(zeros(T, size(Q)), Q') Q.Q'*I
@test Q[1,:] == Q.Q[1,:]
@test Q[:,1] == Q.Q[:,1]
@test convert(Matrix, Q) Matrix(Q) Q[:,:] copyto!(zeros(T, size(Q)), Q) Q.Q*I
@test convert(Matrix, Q') Matrix(Q') (Q')[:,:] copyto!(zeros(T, size(Q)), Q') Q.Q'*I
@test Q[1,:] == Q.Q[1,:] == view(Q, 1, :)
@test Q[:,1] == Q.Q[:,1] == view(Q, :, 1)
@test Q[1,1] == Q.Q[1,1]
@test Q[:] == Q.Q[:]
@test Q[:,1:3] == Q.Q[:,1:3]
@test Q[:,1:3] == Q.Q[:,1:3] == view(Q, :, 1:3)
@test Q[:,1:3] Matrix(Q)[:,1:3]
@test Q[2:3,2:3] == view(Q, 2:3, 2:3) Matrix(Q)[2:3,2:3]
@test_throws BoundsError Q[0,1]
@test_throws BoundsError Q[n+1,1]
@test_throws BoundsError Q[1,0]
Expand Down

0 comments on commit 78fd05a

Please sign in to comment.