Skip to content

Commit 78fd05a

Browse files
authored
Minor AbstractQ audit (#49363)
1 parent 3ce7a9b commit 78fd05a

File tree

2 files changed

+18
-12
lines changed

2 files changed

+18
-12
lines changed

stdlib/LinearAlgebra/src/abstractq.jl

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,14 @@ promote_rule(::Type{<:AbstractMatrix{T}}, ::Type{<:AbstractQ{T}}) where {T} =
2222
(@inline; Union{AbstractMatrix{T},AbstractQ{T}})
2323

2424
# conversion
25-
AbstractQ{S}(Q::AbstractQ{S}) where {S} = Q
26-
# the following eltype promotion needs to be defined for each subtype
25+
# the following eltype promotion should be defined for each subtype `QType`
2726
# convert(::Type{AbstractQ{T}}, Q::QType) where {T} = QType{T}(Q)
27+
# and then care has to be taken that
28+
# QType{T}(Q::QType{T}) where T = ...
29+
# is implemented as a no-op
30+
31+
# the following conversion method ensures functionality when the above method is not defined
32+
# (as for HessenbergQ), but no eltype conversion is required either (say, in multiplication)
2833
convert(::Type{AbstractQ{T}}, Q::AbstractQ{T}) where {T} = Q
2934
convert(::Type{AbstractQ{T}}, adjQ::AdjointQ{T}) where {T} = adjQ
3035
convert(::Type{AbstractQ{T}}, adjQ::AdjointQ) where {T} = convert(AbstractQ{T}, adjQ.Q)'
@@ -36,7 +41,6 @@ Matrix(Q::AbstractQ{T}) where {T} = Matrix{T}(Q)
3641
Array{T}(Q::AbstractQ) where {T} = Matrix{T}(Q)
3742
Array(Q::AbstractQ) = Matrix(Q)
3843
convert(::Type{T}, Q::AbstractQ) where {T<:Array} = T(Q)
39-
convert(::Type{T}, Q::AbstractQ) where {T<:Matrix} = T(Q)
4044
# legacy
4145
@deprecate(convert(::Type{AbstractMatrix{T}}, Q::AbstractQ) where {T},
4246
convert(LinearAlgebra.AbstractQ{T}, Q))
@@ -227,11 +231,9 @@ QRCompactWYQ{S}(factors::AbstractMatrix, T::AbstractMatrix) where {S} =
227231
@deprecate(QRCompactWYQ{S,M}(factors::AbstractMatrix{S}, T::AbstractMatrix{S}) where {S,M},
228232
QRCompactWYQ{S,M,typeof(T)}(factors, T), false)
229233

230-
QRPackedQ{T}(Q::QRPackedQ) where {T} = QRPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(Vector{T}, Q.τ))
234+
QRPackedQ{T}(Q::QRPackedQ) where {T} = QRPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(AbstractVector{T}, Q.τ))
231235
QRCompactWYQ{S}(Q::QRCompactWYQ) where {S} = QRCompactWYQ(convert(AbstractMatrix{S}, Q.factors), convert(AbstractMatrix{S}, Q.T))
232236

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

508-
LQPackedQ{T}(Q::LQPackedQ) where {T} = LQPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(Vector{T}, Q.τ))
510+
LQPackedQ{T}(Q::LQPackedQ) where {T} = LQPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(AbstractVector{T}, Q.τ))
509511
@deprecate(AbstractMatrix{T}(Q::LQPackedQ) where {T},
510512
convert(AbstractQ{T}, Q),
511513
false)

stdlib/LinearAlgebra/test/abstractq.jl

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ n = 5
2929
A = rand(T, n, n)
3030
F = qr(A)
3131
Q = MyQ(F.Q)
32+
@test ndims(Q) == 2
33+
T <: Real && @test transpose(Q) == adjoint(Q)
34+
T <: Complex && @test_throws ErrorException transpose(Q)
3235
@test convert(AbstractQ{complex(T)}, Q) isa MyQ{complex(T)}
3336
@test convert(AbstractQ{complex(T)}, Q') isa AdjointQ{<:complex(T),<:MyQ{complex(T)}}
3437
@test Q*I Q.Q*I rtol=2eps(real(T))
@@ -50,14 +53,15 @@ n = 5
5053
@test mul!(X, transQ(Q), transY(Y)) transQ(Q) * transY(Y) transQ(Q.Q) * transY(Y)
5154
@test mul!(X, transY(Y), transQ(Q)) transY(Y) * transQ(Q) transY(Y) * transQ(Q.Q)
5255
end
53-
@test Matrix(Q) Q[:,:] copyto!(zeros(T, size(Q)), Q) Q.Q*I
54-
@test Matrix(Q') (Q')[:,:] copyto!(zeros(T, size(Q)), Q') Q.Q'*I
55-
@test Q[1,:] == Q.Q[1,:]
56-
@test Q[:,1] == Q.Q[:,1]
56+
@test convert(Matrix, Q) Matrix(Q) Q[:,:] copyto!(zeros(T, size(Q)), Q) Q.Q*I
57+
@test convert(Matrix, Q') Matrix(Q') (Q')[:,:] copyto!(zeros(T, size(Q)), Q') Q.Q'*I
58+
@test Q[1,:] == Q.Q[1,:] == view(Q, 1, :)
59+
@test Q[:,1] == Q.Q[:,1] == view(Q, :, 1)
5760
@test Q[1,1] == Q.Q[1,1]
5861
@test Q[:] == Q.Q[:]
59-
@test Q[:,1:3] == Q.Q[:,1:3]
62+
@test Q[:,1:3] == Q.Q[:,1:3] == view(Q, :, 1:3)
6063
@test Q[:,1:3] Matrix(Q)[:,1:3]
64+
@test Q[2:3,2:3] == view(Q, 2:3, 2:3) Matrix(Q)[2:3,2:3]
6165
@test_throws BoundsError Q[0,1]
6266
@test_throws BoundsError Q[n+1,1]
6367
@test_throws BoundsError Q[1,0]

0 commit comments

Comments
 (0)