Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce AdjointFactorization not subtyping AbstractMatrix #46874

Merged
merged 24 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions stdlib/LinearAlgebra/src/LinearAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ const LAPACKFactorizations{T,S} = Union{
QRCompactWY{T,S},
QRPivoted{T,S},
SVD{T,<:Real,S}}
function (\)(F::Union{<:LAPACKFactorizations,Adjoint{<:Any,<:LAPACKFactorizations}}, B::AbstractVecOrMat)
function (\)(F::Union{<:LAPACKFactorizations,AdjointFactorization{<:Any,<:LAPACKFactorizations}}, B::AbstractVecOrMat)
require_one_based_indexing(B)
m, n = size(F)
if m != size(B, 1)
Expand Down Expand Up @@ -523,7 +523,9 @@ function (\)(F::Union{<:LAPACKFactorizations,Adjoint{<:Any,<:LAPACKFactorization
end
# disambiguate
(\)(F::LAPACKFactorizations{T}, B::VecOrMat{Complex{T}}) where {T<:BlasReal} =
invoke(\, Tuple{Factorization{T}, VecOrMat{Complex{T}}}, F, B)
@invoke \(F::Factorization{T}, B::VecOrMat{Complex{T}})
(\)(F::AdjointFactorization{T,<:LAPACKFactorizations}, B::VecOrMat{Complex{T}}) where {T<:BlasReal} =
@invoke \(F::AdjointFactorization{<:Any,<:LAPACKFactorizations}, B::AbstractVecOrMat)

"""
LinearAlgebra.peakflops(n::Integer=2000; parallel::Bool=false)
Expand Down
12 changes: 6 additions & 6 deletions stdlib/LinearAlgebra/src/adjtrans.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ julia> Adjoint(A)
9-2im 0+0im
```
"""
struct Adjoint{T,S} <: AbstractMatrix{T}
struct Adjoint{T,S<:AbstractVecOrMat} <: AbstractMatrix{T}
parent::S
end
"""
Expand All @@ -59,13 +59,13 @@ julia> Transpose(A)
3 0
```
"""
struct Transpose{T,S} <: AbstractMatrix{T}
struct Transpose{T,S<:AbstractVecOrMat} <: AbstractMatrix{T}
parent::S
end

# basic outer constructors
Adjoint(A) = Adjoint{Base.promote_op(adjoint,eltype(A)),typeof(A)}(A)
Transpose(A) = Transpose{Base.promote_op(transpose,eltype(A)),typeof(A)}(A)
Adjoint(A::AbstractVecOrMat) = Adjoint{Base.promote_op(adjoint,eltype(A)),typeof(A)}(A)
Transpose(A::AbstractVecOrMat) = Transpose{Base.promote_op(transpose,eltype(A)),typeof(A)}(A)

Base.dataids(A::Union{Adjoint, Transpose}) = Base.dataids(A.parent)
Base.unaliascopy(A::Union{Adjoint,Transpose}) = typeof(A)(Base.unaliascopy(A.parent))
Expand Down Expand Up @@ -460,8 +460,8 @@ pinv(v::TransposeAbsVec, tol::Real = 0) = pinv(conj(v.parent)).parent
## right-division /
/(u::AdjointAbsVec, A::AbstractMatrix) = adjoint(adjoint(A) \ u.parent)
/(u::TransposeAbsVec, A::AbstractMatrix) = transpose(transpose(A) \ u.parent)
/(u::AdjointAbsVec, A::Transpose{<:Any,<:AbstractMatrix}) = adjoint(conj(A.parent) \ u.parent) # technically should be adjoint(copy(adjoint(copy(A))) \ u.parent)
/(u::TransposeAbsVec, A::Adjoint{<:Any,<:AbstractMatrix}) = transpose(conj(A.parent) \ u.parent) # technically should be transpose(copy(transpose(copy(A))) \ u.parent)
/(u::AdjointAbsVec, A::TransposeAbsMat) = adjoint(conj(A.parent) \ u.parent) # technically should be adjoint(copy(adjoint(copy(A))) \ u.parent)
/(u::TransposeAbsVec, A::AdjointAbsMat) = transpose(conj(A.parent) \ u.parent) # technically should be transpose(copy(transpose(copy(A))) \ u.parent)

## complex conjugate
conj(A::Transpose) = adjoint(A.parent)
Expand Down
90 changes: 57 additions & 33 deletions stdlib/LinearAlgebra/src/factorization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,32 @@ matrix factorizations.
"""
abstract type Factorization{T} end

struct AdjointFactorization{T,S<:Factorization} <: Factorization{T}
parent::S
end
AdjointFactorization(F::Factorization) =
AdjointFactorization{Base.promote_op(adjoint,eltype(F)),typeof(F)}(F)

struct TransposeFactorization{T,S<:Factorization} <: Factorization{T}
parent::S
end
TransposeFactorization(F::Factorization) =
TransposeFactorization{Base.promote_op(adjoint,eltype(F)),typeof(F)}(F)

eltype(::Type{<:Factorization{T}}) where {T} = T
size(F::Adjoint{<:Any,<:Factorization}) = reverse(size(parent(F)))
size(F::Transpose{<:Any,<:Factorization}) = reverse(size(parent(F)))
size(F::AdjointFactorization) = reverse(size(parent(F)))
size(F::TransposeFactorization) = reverse(size(parent(F)))
size(F::Union{AdjointFactorization,TransposeFactorization}, d::Integer) = d in (1, 2) ? size(F)[d] : 1
parent(F::Union{AdjointFactorization,TransposeFactorization}) = F.parent

adjoint(F::Factorization) = AdjointFactorization(F)
transpose(F::Factorization) = TransposeFactorization(F)
transpose(F::Factorization{<:Real}) = AdjointFactorization(F)
adjoint(F::AdjointFactorization) = F.parent
transpose(F::TransposeFactorization) = F.parent
transpose(F::AdjointFactorization{<:Real}) = F.parent
conj(A::TransposeFactorization) = adjoint(A.parent)
conj(A::AdjointFactorization) = transpose(A.parent)

checkpositivedefinite(info) = info == 0 || throw(PosDefException(info))
checknonsingular(info, ::RowMaximum) = info == 0 || throw(SingularException(info))
Expand Down Expand Up @@ -60,64 +83,76 @@ convert(::Type{T}, f::Factorization) where {T<:AbstractArray} = T(f)::T

### General promotion rules
Factorization{T}(F::Factorization{T}) where {T} = F
# This is a bit odd since the return is not a Factorization but it works well in generic code
Factorization{T}(A::Adjoint{<:Any,<:Factorization}) where {T} =
# This no longer looks odd since the return _is_ a Factorization!
Factorization{T}(A::AdjointFactorization) where {T} =
adjoint(Factorization{T}(parent(A)))
Comment on lines -63 to 114
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😉

inv(F::Factorization{T}) where {T} = (n = size(F, 1); ldiv!(F, Matrix{T}(I, n, n)))

Base.hash(F::Factorization, h::UInt) = mapreduce(f -> hash(getfield(F, f)), hash, 1:nfields(F); init=h)
Base.:(==)( F::T, G::T) where {T<:Factorization} = all(f -> getfield(F, f) == getfield(G, f), 1:nfields(F))
Base.isequal(F::T, G::T) where {T<:Factorization} = all(f -> isequal(getfield(F, f), getfield(G, f)), 1:nfields(F))::Bool

function Base.show(io::IO, x::Adjoint{<:Any,<:Factorization})
print(io, "Adjoint of ")
function Base.show(io::IO, x::AdjointFactorization)
print(io, "adjoint of ")
show(io, parent(x))
end
function Base.show(io::IO, x::Transpose{<:Any,<:Factorization})
print(io, "Transpose of ")
function Base.show(io::IO, x::TransposeFactorization)
print(io, "transpose of ")
show(io, parent(x))
end
function Base.show(io::IO, ::MIME"text/plain", x::Adjoint{<:Any,<:Factorization})
print(io, "Adjoint of ")
function Base.show(io::IO, ::MIME"text/plain", x::AdjointFactorization)
print(io, "adjoint of ")
show(io, MIME"text/plain"(), parent(x))
end
function Base.show(io::IO, ::MIME"text/plain", x::Transpose{<:Any,<:Factorization})
print(io, "Transpose of ")
function Base.show(io::IO, ::MIME"text/plain", x::TransposeFactorization)
print(io, "transpose of ")
show(io, MIME"text/plain"(), parent(x))
end

# With a real lhs and complex rhs with the same precision, we can reinterpret
# the complex rhs as a real rhs with twice the number of columns or rows
function (\)(F::Factorization{T}, B::VecOrMat{Complex{T}}) where T<:BlasReal
function (\)(F::Factorization{T}, B::VecOrMat{Complex{T}}) where {T<:BlasReal}
require_one_based_indexing(B)
c2r = reshape(copy(transpose(reinterpret(T, reshape(B, (1, length(B)))))), size(B, 1), 2*size(B, 2))
x = ldiv!(F, c2r)
return reshape(copy(reinterpret(Complex{T}, copy(transpose(reshape(x, div(length(x), 2), 2))))), _ret_size(F, B))
end
function (/)(B::VecOrMat{Complex{T}}, F::Factorization{T}) where T<:BlasReal
# don't do the reinterpretation for [Adjoint/Transpose]Factorization
(\)(F::TransposeFactorization{T}, B::VecOrMat{Complex{T}}) where {T<:BlasReal} =
conj!(adjoint(parent(F)) \ conj.(B))
(\)(F::AdjointFactorization{T}, B::VecOrMat{Complex{T}}) where {T<:BlasReal} =
@invoke \(F::typeof(F), B::AbstractVecOrMat) # send to meta-function in LinearAlgebra.jl

function (/)(B::VecOrMat{Complex{T}}, F::Factorization{T}) where {T<:BlasReal}
require_one_based_indexing(B)
x = rdiv!(copy(reinterpret(T, B)), F)
return copy(reinterpret(Complex{T}, x))
end
# don't do the reinterpretation for [Adjoint/Transpose]Factorization
(/)(B::VecOrMat{Complex{T}}, F::TransposeFactorization{T}) where {T<:BlasReal} =
conj!(adjoint(parent(F)) \ conj.(B))
(/)(B::VecOrMat{Complex{T}}, F::AdjointFactorization{T}) where {T<:BlasReal} =
invoke(/, Tuple{VecOrMat{Complex{T}}, Factorization{T}}, B, F)

function \(F::Union{Factorization, Adjoint{<:Any,<:Factorization}}, B::AbstractVecOrMat)
function (\)(F::Factorization, B::AbstractVecOrMat)
require_one_based_indexing(B)
TFB = typeof(oneunit(eltype(B)) / oneunit(eltype(F)))
TFB = typeof(oneunit(eltype(F)) / oneunit(eltype(B)))
ldiv!(F, copy_similar(B, TFB))
end
(\)(F::TransposeFactorization{<:Real}, B::AbstractVecOrMat) = adjoint(F.parent) \ B
(\)(F::TransposeFactorization, B::AbstractVecOrMat) = conj!(adjoint(F.parent) \ conj.(B))

function /(B::AbstractMatrix, F::Union{Factorization, Adjoint{<:Any,<:Factorization}})
function (/)(B::AbstractMatrix, F::Factorization)
require_one_based_indexing(B)
TFB = typeof(oneunit(eltype(B)) / oneunit(eltype(F)))
rdiv!(copy_similar(B, TFB), F)
end
/(adjB::AdjointAbsVec, adjF::Adjoint{<:Any,<:Factorization}) = adjoint(adjF.parent \ adjB.parent)
/(B::TransposeAbsVec, adjF::Adjoint{<:Any,<:Factorization}) = adjoint(adjF.parent \ adjoint(B))

(/)(A::AbstractMatrix, F::AdjointFactorization) = adjoint(adjoint(F) \ adjoint(A))
(/)(A::AbstractMatrix, F::TransposeFactorization) = transpose(transpose(F) \ transpose(A))

function ldiv!(Y::AbstractVector, A::Factorization, B::AbstractVector)
require_one_based_indexing(Y, B)
m, n = size(A, 1), size(A, 2)
m, n = size(A)
if m > n
Bc = copy(B)
ldiv!(A, Bc)
Expand All @@ -128,7 +163,7 @@ function ldiv!(Y::AbstractVector, A::Factorization, B::AbstractVector)
end
function ldiv!(Y::AbstractMatrix, A::Factorization, B::AbstractMatrix)
require_one_based_indexing(Y, B)
m, n = size(A, 1), size(A, 2)
m, n = size(A)
if m > n
Bc = copy(B)
ldiv!(A, Bc)
Expand All @@ -138,14 +173,3 @@ function ldiv!(Y::AbstractMatrix, A::Factorization, B::AbstractMatrix)
return ldiv!(A, Y)
end
end

# fallback methods for transposed solves
\(F::Transpose{<:Any,<:Factorization{<:Real}}, B::AbstractVecOrMat) = adjoint(F.parent) \ B
\(F::Transpose{<:Any,<:Factorization}, B::AbstractVecOrMat) = conj.(adjoint(F.parent) \ conj.(B))

/(B::AbstractMatrix, F::Transpose{<:Any,<:Factorization{<:Real}}) = B / adjoint(F.parent)
/(B::AbstractMatrix, F::Transpose{<:Any,<:Factorization}) = conj.(conj.(B) / adjoint(F.parent))
/(B::AdjointAbsVec, F::Transpose{<:Any,<:Factorization{<:Real}}) = B / adjoint(F.parent)
/(B::TransposeAbsVec, F::Transpose{<:Any,<:Factorization{<:Real}}) = B / adjoint(F.parent)
/(B::AdjointAbsVec, F::Transpose{<:Any,<:Factorization}) = conj.(conj.(B) / adjoint(F.parent))
/(B::TransposeAbsVec, F::Transpose{<:Any,<:Factorization}) = conj.(conj.(B) / adjoint(F.parent))
8 changes: 3 additions & 5 deletions stdlib/LinearAlgebra/src/hessenberg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -421,11 +421,9 @@ Hessenberg(F::Hessenberg, μ::Number) = Hessenberg(F.factors, F.τ, F.H, F.uplo;

copy(F::Hessenberg{<:Any,<:UpperHessenberg}) = Hessenberg(copy(F.factors), copy(F.τ); μ=F.μ)
copy(F::Hessenberg{<:Any,<:SymTridiagonal}) = Hessenberg(copy(F.factors), copy(F.τ), copy(F.H), F.uplo; μ=F.μ)
size(F::Hessenberg, d) = size(F.H, d)
size(F::Hessenberg, d::Integer) = size(F.H, d)
size(F::Hessenberg) = size(F.H)

adjoint(F::Hessenberg) = Adjoint(F)

# iteration for destructuring into components
Base.iterate(S::Hessenberg) = (S.Q, Val(:H))
Base.iterate(S::Hessenberg, ::Val{:H}) = (S.H, Val(:μ))
Expand Down Expand Up @@ -686,8 +684,8 @@ function rdiv!(B::AbstractVecOrMat{<:Complex}, F::Hessenberg{<:Complex,<:Any,<:A
return B .= Complex.(Br,Bi)
end

ldiv!(F::Adjoint{<:Any,<:Hessenberg}, B::AbstractVecOrMat) = rdiv!(B', F')'
rdiv!(B::AbstractMatrix, F::Adjoint{<:Any,<:Hessenberg}) = ldiv!(F', B')'
ldiv!(F::AdjointFactorization{<:Any,<:Hessenberg}, B::AbstractVecOrMat) = rdiv!(B', F')'
rdiv!(B::AbstractMatrix, F::AdjointFactorization{<:Any,<:Hessenberg}) = ldiv!(F', B')'

det(F::Hessenberg) = det(F.H; shift=F.μ)
logabsdet(F::Hessenberg) = logabsdet(F.H; shift=F.μ)
Expand Down
5 changes: 2 additions & 3 deletions stdlib/LinearAlgebra/src/lq.jl
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,7 @@ AbstractArray(A::LQ) = AbstractMatrix(A)
Matrix(A::LQ) = Array(AbstractArray(A))
Array(A::LQ) = Matrix(A)

adjoint(A::LQ) = Adjoint(A)
Base.copy(F::Adjoint{T,<:LQ{T}}) where {T} =
Base.copy(F::AdjointFactorization{T,<:LQ{T}}) where {T} =
QR{T,typeof(F.parent.factors),typeof(F.parent.τ)}(copy(adjoint(F.parent.factors)), copy(F.parent.τ))

function getproperty(F::LQ, d::Symbol)
Expand Down Expand Up @@ -343,7 +342,7 @@ function ldiv!(A::LQ, B::StridedVecOrMat)
return lmul!(adjoint(A.Q), B)
end

function ldiv!(Fadj::Adjoint{<:Any,<:LQ}, B::StridedVecOrMat)
function ldiv!(Fadj::AdjointFactorization{<:Any,<:LQ}, B::StridedVecOrMat)
require_one_based_indexing(B)
m, n = size(Fadj)
m >= n || throw(DimensionMismatch("solver does not support underdetermined systems (more columns than rows)"))
Expand Down
49 changes: 16 additions & 33 deletions stdlib/LinearAlgebra/src/lu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,11 @@ Base.iterate(S::LU, ::Val{:U}) = (S.U, Val(:p))
Base.iterate(S::LU, ::Val{:p}) = (S.p, Val(:done))
Base.iterate(S::LU, ::Val{:done}) = nothing

adjoint(F::LU) = Adjoint(F)
transpose(F::LU) = Transpose(F)
# LU prefers transpose over adjoint in the real case
adjoint(F::LU) = AdjointFactorization(F)
transpose(F::LU) = TransposeFactorization(F)
# override the generic fallback
transpose(F::LU{<:Real}) = TransposeFactorization(F)

# StridedMatrix
lu!(A::StridedMatrix{<:BlasFloat}; check::Bool = true) = lu!(A, RowMaximum(); check=check)
Expand Down Expand Up @@ -327,7 +330,7 @@ Factorization{T}(F::LU) where {T} = LU{T}(F)
copy(A::LU{T,S,P}) where {T,S,P} = LU{T,S,P}(copy(A.factors), copy(A.ipiv), A.info)

size(A::LU) = size(getfield(A, :factors))
size(A::LU, i) = size(getfield(A, :factors), i)
size(A::LU, i::Integer) = size(getfield(A, :factors), i)

function ipiv2perm(v::AbstractVector{T}, maxi::Integer) where T
require_one_based_indexing(v)
Expand Down Expand Up @@ -432,49 +435,29 @@ function ldiv!(A::LU{<:Any,<:StridedMatrix}, B::StridedVecOrMat)
ldiv!(UpperTriangular(A.factors), ldiv!(UnitLowerTriangular(A.factors), B))
end

ldiv!(transA::Transpose{T,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:BlasFloat} =
ldiv!(transA::TransposeFactorization{T,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:BlasFloat} =
(A = transA.parent; LAPACK.getrs!('T', A.factors, A.ipiv, B))

function ldiv!(transA::Transpose{<:Any,<:LU{<:Any,<:StridedMatrix}}, B::StridedVecOrMat)
function ldiv!(transA::TransposeFactorization{<:Any,<:LU{<:Any,<:StridedMatrix}}, B::StridedVecOrMat)
A = transA.parent
ldiv!(transpose(UnitLowerTriangular(A.factors)), ldiv!(transpose(UpperTriangular(A.factors)), B))
_apply_inverse_ipiv_rows!(A, B)
end

ldiv!(adjF::Adjoint{T,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:Real} =
(F = adjF.parent; ldiv!(transpose(F), B))
ldiv!(adjA::Adjoint{T,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:BlasComplex} =
ldiv!(adjA::AdjointFactorization{T,<:LU{T,<:StridedMatrix}}, B::StridedVecOrMat{T}) where {T<:BlasComplex} =
(A = adjA.parent; LAPACK.getrs!('C', A.factors, A.ipiv, B))

function ldiv!(adjA::Adjoint{<:Any,<:LU{<:Any,<:StridedMatrix}}, B::StridedVecOrMat)
function ldiv!(adjA::AdjointFactorization{<:Any,<:LU{<:Any,<:StridedMatrix}}, B::StridedVecOrMat)
A = adjA.parent
ldiv!(adjoint(UnitLowerTriangular(A.factors)), ldiv!(adjoint(UpperTriangular(A.factors)), B))
_apply_inverse_ipiv_rows!(A, B)
end

(\)(A::Adjoint{<:Any,<:LU}, B::Adjoint{<:Any,<:StridedVecOrMat}) = A \ copy(B)
(\)(A::Transpose{<:Any,<:LU}, B::Transpose{<:Any,<:StridedVecOrMat}) = A \ copy(B)
(\)(A::Adjoint{T,<:LU{T,<:StridedMatrix}}, B::Adjoint{T,<:StridedVecOrMat{T}}) where {T<:BlasComplex} =
(\)(A::AdjointFactorization{T,<:LU{T,<:StridedMatrix}}, B::Adjoint{T,<:StridedVecOrMat{T}}) where {T<:BlasComplex} =
LAPACK.getrs!('C', A.parent.factors, A.parent.ipiv, copy(B))
(\)(A::Transpose{T,<:LU{T,<:StridedMatrix}}, B::Transpose{T,<:StridedVecOrMat{T}}) where {T<:BlasFloat} =
(\)(A::TransposeFactorization{T,<:LU{T,<:StridedMatrix}}, B::Transpose{T,<:StridedVecOrMat{T}}) where {T<:BlasFloat} =
LAPACK.getrs!('T', A.parent.factors, A.parent.ipiv, copy(B))

function (/)(A::AbstractMatrix, F::Adjoint{<:Any,<:LU})
T = promote_type(eltype(A), eltype(F))
return adjoint(ldiv!(F.parent, copymutable_oftype(adjoint(A), T)))
end
# To avoid ambiguities with definitions in adjtrans.jl and factorizations.jl
(/)(adjA::Adjoint{<:Any,<:AbstractVector}, F::Adjoint{<:Any,<:LU}) = adjoint(F.parent \ adjA.parent)
(/)(adjA::Adjoint{<:Any,<:AbstractMatrix}, F::Adjoint{<:Any,<:LU}) = adjoint(F.parent \ adjA.parent)
function (/)(trA::Transpose{<:Any,<:AbstractVector}, F::Adjoint{<:Any,<:LU})
T = promote_type(eltype(trA), eltype(F))
return adjoint(ldiv!(F.parent, conj!(copymutable_oftype(trA.parent, T))))
end
function (/)(trA::Transpose{<:Any,<:AbstractMatrix}, F::Adjoint{<:Any,<:LU})
T = promote_type(eltype(trA), eltype(F))
return adjoint(ldiv!(F.parent, conj!(copymutable_oftype(trA.parent, T))))
end

function det(F::LU{T}) where T
n = checksquare(F)
issuccess(F) || return zero(T)
Expand Down Expand Up @@ -650,7 +633,7 @@ function ldiv!(A::LU{T,Tridiagonal{T,V}}, B::AbstractVecOrMat) where {T,V}
return B
end

function ldiv!(transA::Transpose{<:Any,<:LU{T,Tridiagonal{T,V}}}, B::AbstractVecOrMat) where {T,V}
function ldiv!(transA::TransposeFactorization{<:Any,<:LU{T,Tridiagonal{T,V}}}, B::AbstractVecOrMat) where {T,V}
require_one_based_indexing(B)
A = transA.parent
n = size(A,1)
Expand Down Expand Up @@ -687,7 +670,7 @@ function ldiv!(transA::Transpose{<:Any,<:LU{T,Tridiagonal{T,V}}}, B::AbstractVec
end

# Ac_ldiv_B!(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) where {T<:Real} = At_ldiv_B!(A,B)
function ldiv!(adjA::Adjoint{<:Any,<:LU{T,Tridiagonal{T,V}}}, B::AbstractVecOrMat) where {T,V}
function ldiv!(adjA::AdjointFactorization{<:Any,<:LU{T,Tridiagonal{T,V}}}, B::AbstractVecOrMat) where {T,V}
require_one_based_indexing(B)
A = adjA.parent
n = size(A,1)
Expand Down Expand Up @@ -724,8 +707,8 @@ function ldiv!(adjA::Adjoint{<:Any,<:LU{T,Tridiagonal{T,V}}}, B::AbstractVecOrMa
end

rdiv!(B::AbstractMatrix, A::LU) = transpose(ldiv!(transpose(A), transpose(B)))
rdiv!(B::AbstractMatrix, A::Transpose{<:Any,<:LU}) = transpose(ldiv!(A.parent, transpose(B)))
rdiv!(B::AbstractMatrix, A::Adjoint{<:Any,<:LU}) = adjoint(ldiv!(A.parent, adjoint(B)))
rdiv!(B::AbstractMatrix, A::TransposeFactorization{<:Any,<:LU}) = transpose(ldiv!(A.parent, transpose(B)))
rdiv!(B::AbstractMatrix, A::AdjointFactorization{<:Any,<:LU}) = adjoint(ldiv!(A.parent, adjoint(B)))

# Conversions
AbstractMatrix(F::LU) = (F.L * F.U)[invperm(F.p),:]
Expand Down
4 changes: 2 additions & 2 deletions stdlib/LinearAlgebra/src/qr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ end
Base.propertynames(F::QRPivoted, private::Bool=false) =
(:R, :Q, :p, :P, (private ? fieldnames(typeof(F)) : ())...)

adjoint(F::Union{QR,QRPivoted,QRCompactWY}) = Adjoint(F)
transpose(F::Union{QR,QRPivoted,QRCompactWY}) = throw(ArgumentError("transpose of QR decomposition is not supported"))

abstract type AbstractQ{T} <: AbstractMatrix{T} end

Expand Down Expand Up @@ -1001,7 +1001,7 @@ function _apply_permutation!(F::QRPivoted, B::AbstractVecOrMat)
end
_apply_permutation!(F::Factorization, B::AbstractVecOrMat) = B

function ldiv!(Fadj::Adjoint{<:Any,<:Union{QR,QRCompactWY,QRPivoted}}, B::AbstractVecOrMat)
function ldiv!(Fadj::AdjointFactorization{<:Any,<:Union{QR,QRCompactWY,QRPivoted}}, B::AbstractVecOrMat)
require_one_based_indexing(B)
m, n = size(Fadj)

Expand Down
8 changes: 4 additions & 4 deletions stdlib/LinearAlgebra/test/adjtrans.jl
Original file line number Diff line number Diff line change
Expand Up @@ -489,13 +489,13 @@ end
@test B == A .* A'
end

@testset "test show methods for $t of Factorizations" for t in (Adjoint, Transpose)
A = randn(4, 4)
@testset "test show methods for $t of Factorizations" for t in (adjoint, transpose)
A = randn(ComplexF64, 4, 4)
F = lu(A)
Fop = t(F)
@test "LinearAlgebra."*sprint(show, Fop) ==
@test sprint(show, Fop) ==
"$t of "*sprint(show, parent(Fop))
@test "LinearAlgebra."*sprint((io, t) -> show(io, MIME"text/plain"(), t), Fop) ==
@test sprint((io, t) -> show(io, MIME"text/plain"(), t), Fop) ==
"$t of "*sprint((io, t) -> show(io, MIME"text/plain"(), t), parent(Fop))
end

Expand Down
Loading