From ba21f20de11f134a7d48455955b4382554fcfe4a Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 8 Jan 2018 13:15:51 -0800 Subject: [PATCH 1/2] Replace Adjoint/Transpose with adjoint/transpose (instances missed in #25364). --- base/deprecated.jl | 16 ++++----- base/linalg/bidiag.jl | 4 +-- base/linalg/diagonal.jl | 24 ++++++------- base/linalg/generic.jl | 6 ++-- base/linalg/lu.jl | 2 +- base/linalg/triangular.jl | 68 ++++++++++++++++++------------------- base/linalg/tridiag.jl | 8 ++--- base/sparse/linalg.jl | 16 ++++----- base/sparse/sparsevector.jl | 32 ++++++++--------- test/bitarray.jl | 2 +- test/linalg/dense.jl | 2 +- 11 files changed, 90 insertions(+), 90 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 3b828b81ecaad..68f6ed1b85a4c 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2224,10 +2224,10 @@ end @deprecate A_mul_Bt(A::AbstractMatrix, B::AbstractTriangular) (*)(A, transpose(B)) end for (f, op, transform) in ( - (:A_mul_Bc, :*, :Adjoint), - (:A_mul_Bt, :*, :Transpose), - (:A_rdiv_Bc, :/, :Adjoint), - (:A_rdiv_Bt, :/, :Transpose)) + (:A_mul_Bc, :*, :adjoint), + (:A_mul_Bt, :*, :transpose), + (:A_rdiv_Bc, :/, :adjoint), + (:A_rdiv_Bt, :/, :transpose)) @eval Base.LinAlg begin @deprecate $f(A::LowerTriangular, B::UpperTriangular) ($op)(A, ($transform)(B)) @deprecate $f(A::LowerTriangular, B::UnitUpperTriangular) ($op)(A, ($transform)(B)) @@ -2236,10 +2236,10 @@ for (f, op, transform) in ( end end for (f, op, transform) in ( - (:Ac_mul_B, :*, :Adjoint), - (:At_mul_B, :*, :Transpose), - (:Ac_ldiv_B, :\, :Adjoint), - (:At_ldiv_B, :\, :Transpose)) + (:Ac_mul_B, :*, :adjoint), + (:At_mul_B, :*, :transpose), + (:Ac_ldiv_B, :\, :adjoint), + (:At_ldiv_B, :\, :transpose)) @eval Base.LinAlg begin @deprecate ($f)(A::UpperTriangular, B::LowerTriangular) ($op)(($transform)(A), B) @deprecate ($f)(A::UnitUpperTriangular, B::LowerTriangular) ($op)(($transform)(A), B) diff --git a/base/linalg/bidiag.jl b/base/linalg/bidiag.jl index 34860fefde098..811eec31815d0 100644 --- a/base/linalg/bidiag.jl +++ b/base/linalg/bidiag.jl @@ -252,9 +252,9 @@ transpose(B::Bidiagonal) = Transpose(B) adjoint(B::Bidiagonal{<:Real}) = Bidiagonal(B.dv, B.ev, B.uplo == 'U' ? :L : :U) transpose(B::Bidiagonal{<:Number}) = Bidiagonal(B.dv, B.ev, B.uplo == 'U' ? :L : :U) Base.copy(aB::Adjoint{<:Any,<:Bidiagonal}) = - (B = aB.parent; Bidiagonal(map(x -> copy.(Adjoint.(x)), (B.dv, B.ev))..., B.uplo == 'U' ? :L : :U)) + (B = aB.parent; Bidiagonal(map(x -> copy.(adjoint.(x)), (B.dv, B.ev))..., B.uplo == 'U' ? :L : :U)) Base.copy(tB::Transpose{<:Any,<:Bidiagonal}) = - (B = tB.parent; Bidiagonal(map(x -> copy.(Transpose.(x)), (B.dv, B.ev))..., B.uplo == 'U' ? :L : :U)) + (B = tB.parent; Bidiagonal(map(x -> copy.(transpose.(x)), (B.dv, B.ev))..., B.uplo == 'U' ? :L : :U)) istriu(M::Bidiagonal) = M.uplo == 'U' || iszero(M.ev) istril(M::Bidiagonal) = M.uplo == 'L' || iszero(M.ev) diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index c33b00076f7d1..5acf9e1016ba5 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -188,7 +188,7 @@ function mul!(D::Diagonal, B::UnitUpperTriangular) UpperTriangular(B.data) end -*(D::Adjoint{<:Any,<:Diagonal}, B::Diagonal) = Diagonal(Adjoint.(D.parent.diag) .* B.diag) +*(D::Adjoint{<:Any,<:Diagonal}, B::Diagonal) = Diagonal(adjoint.(D.parent.diag) .* B.diag) *(A::Adjoint{<:Any,<:AbstractTriangular}, D::Diagonal) = mul!(copy(A), D) function *(adjA::Adjoint{<:Any,<:AbstractMatrix}, D::Diagonal) A = adjA.parent @@ -197,7 +197,7 @@ function *(adjA::Adjoint{<:Any,<:AbstractMatrix}, D::Diagonal) mul!(Ac, D) end -*(D::Transpose{<:Any,<:Diagonal}, B::Diagonal) = Diagonal(Transpose.(D.parent.diag) .* B.diag) +*(D::Transpose{<:Any,<:Diagonal}, B::Diagonal) = Diagonal(transpose.(D.parent.diag) .* B.diag) *(A::Transpose{<:Any,<:AbstractTriangular}, D::Diagonal) = mul!(copy(A), D) function *(transA::Transpose{<:Any,<:AbstractMatrix}, D::Diagonal) A = transA.parent @@ -206,7 +206,7 @@ function *(transA::Transpose{<:Any,<:AbstractMatrix}, D::Diagonal) mul!(At, D) end -*(D::Diagonal, B::Adjoint{<:Any,<:Diagonal}) = Diagonal(D.diag .* Adjoint.(B.parent.diag)) +*(D::Diagonal, B::Adjoint{<:Any,<:Diagonal}) = Diagonal(D.diag .* adjoint.(B.parent.diag)) *(D::Diagonal, B::Adjoint{<:Any,<:AbstractTriangular}) = mul!(D, collect(B)) *(D::Diagonal, adjQ::Adjoint{<:Any,<:Union{QRCompactWYQ,QRPackedQ}}) = (Q = adjQ.parent; mul!(Array(D), adjoint(Q))) function *(D::Diagonal, adjA::Adjoint{<:Any,<:AbstractMatrix}) @@ -216,7 +216,7 @@ function *(D::Diagonal, adjA::Adjoint{<:Any,<:AbstractMatrix}) mul!(D, Ac) end -*(D::Diagonal, B::Transpose{<:Any,<:Diagonal}) = Diagonal(D.diag .* Transpose.(B.parent.diag)) +*(D::Diagonal, B::Transpose{<:Any,<:Diagonal}) = Diagonal(D.diag .* transpose.(B.parent.diag)) *(D::Diagonal, B::Transpose{<:Any,<:AbstractTriangular}) = mul!(D, copy(B)) function *(D::Diagonal, transA::Transpose{<:Any,<:AbstractMatrix}) A = transA.parent @@ -226,9 +226,9 @@ function *(D::Diagonal, transA::Transpose{<:Any,<:AbstractMatrix}) end *(D::Adjoint{<:Any,<:Diagonal}, B::Adjoint{<:Any,<:Diagonal}) = - Diagonal(Adjoint.(D.parent.diag) .* Adjoint.(B.parent.diag)) + Diagonal(adjoint.(D.parent.diag) .* adjoint.(B.parent.diag)) *(D::Transpose{<:Any,<:Diagonal}, B::Transpose{<:Any,<:Diagonal}) = - Diagonal(Transpose.(D.parent.diag) .* Transpose.(B.parent.diag)) + Diagonal(transpose.(D.parent.diag) .* transpose.(B.parent.diag)) mul!(A::Diagonal, B::Diagonal) = throw(MethodError(mul!, (A, B))) mul!(A::QRPackedQ, D::Diagonal) = throw(MethodError(mul!, (A, D))) @@ -254,12 +254,12 @@ mul!(A::AbstractMatrix, transB::Transpose{<:Any,<:Diagonal}) = (B = transB.paren # Get ambiguous method if try to unify AbstractVector/AbstractMatrix here using AbstractVecOrMat mul!(out::AbstractVector, A::Diagonal, in::AbstractVector) = out .= A.diag .* in -mul!(out::AbstractVector, A::Adjoint{<:Any,<:Diagonal}, in::AbstractVector) = out .= Adjoint.(A.parent.diag) .* in -mul!(out::AbstractVector, A::Transpose{<:Any,<:Diagonal}, in::AbstractVector) = out .= Transpose.(A.parent.diag) .* in +mul!(out::AbstractVector, A::Adjoint{<:Any,<:Diagonal}, in::AbstractVector) = out .= adjoint.(A.parent.diag) .* in +mul!(out::AbstractVector, A::Transpose{<:Any,<:Diagonal}, in::AbstractVector) = out .= transpose.(A.parent.diag) .* in mul!(out::AbstractMatrix, A::Diagonal, in::AbstractMatrix) = out .= A.diag .* in -mul!(out::AbstractMatrix, A::Adjoint{<:Any,<:Diagonal}, in::AbstractMatrix) = out .= Adjoint.(A.parent.diag) .* in -mul!(out::AbstractMatrix, A::Transpose{<:Any,<:Diagonal}, in::AbstractMatrix) = out .= Transpose.(A.parent.diag) .* in +mul!(out::AbstractMatrix, A::Adjoint{<:Any,<:Diagonal}, in::AbstractMatrix) = out .= adjoint.(A.parent.diag) .* in +mul!(out::AbstractMatrix, A::Transpose{<:Any,<:Diagonal}, in::AbstractMatrix) = out .= transpose.(A.parent.diag) .* in mul!(C::AbstractMatrix, A::Diagonal, B::Adjoint{<:Any,<:AbstractVecOrMat}) = mul!(C, A, copy(B)) mul!(C::AbstractMatrix, A::Diagonal, B::Transpose{<:Any,<:AbstractVecOrMat}) = mul!(C, A, copy(B)) @@ -281,8 +281,8 @@ mul!(C::AbstractMatrix, A::Transpose{<:Any,<:Diagonal}, B::Transpose{<:Any,<:Abs *(adjD::Adjoint{<:Any,<:Diagonal}, adjA::Adjoint{<:Any,<:RealHermSymComplexHerm}) = adjD * adjA.parent mul!(C::AbstractMatrix, A::Adjoint{<:Any,<:Diagonal}, B::Adjoint{<:Any,<:RealHermSymComplexHerm}) = mul!(C, A, B.parent) mul!(C::AbstractMatrix, A::Transpose{<:Any,<:Diagonal}, B::Transpose{<:Any,<:RealHermSymComplexSym}) = mul!(C, A, B.parent) -mul!(C::AbstractMatrix, A::Adjoint{<:Any,<:Diagonal}, B::Adjoint{<:Any,<:RealHermSymComplexSym}) = C .= Adjoint.(A.parent.diag) .* B -mul!(C::AbstractMatrix, A::Transpose{<:Any,<:Diagonal}, B::Transpose{<:Any,<:RealHermSymComplexHerm}) = C .= Transpose.(A.parent.diag) .* B +mul!(C::AbstractMatrix, A::Adjoint{<:Any,<:Diagonal}, B::Adjoint{<:Any,<:RealHermSymComplexSym}) = C .= adjoint.(A.parent.diag) .* B +mul!(C::AbstractMatrix, A::Transpose{<:Any,<:Diagonal}, B::Transpose{<:Any,<:RealHermSymComplexHerm}) = C .= transpose.(A.parent.diag) .* B (/)(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag ./ Db.diag) diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index 017b751a5e05a..215d8b21d189a 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -823,9 +823,9 @@ function inv(A::AbstractMatrix{T}) where T ldiv!(factorize(convert(AbstractMatrix{S}, A)), dest) end -pinv(v::AbstractVector{T}, tol::Real = real(zero(T))) where {T<:Real} = _vectorpinv(Transpose, v, tol) -pinv(v::AbstractVector{T}, tol::Real = real(zero(T))) where {T<:Complex} = _vectorpinv(Adjoint, v, tol) -pinv(v::AbstractVector{T}, tol::Real = real(zero(T))) where {T} = _vectorpinv(Adjoint, v, tol) +pinv(v::AbstractVector{T}, tol::Real = real(zero(T))) where {T<:Real} = _vectorpinv(transpose, v, tol) +pinv(v::AbstractVector{T}, tol::Real = real(zero(T))) where {T<:Complex} = _vectorpinv(adjoint, v, tol) +pinv(v::AbstractVector{T}, tol::Real = real(zero(T))) where {T} = _vectorpinv(adjoint, v, tol) function _vectorpinv(dualfn::Tf, v::AbstractVector{Tv}, tol) where {Tv,Tf} res = dualfn(similar(v, typeof(zero(Tv) / (abs2(one(Tv)) + abs2(one(Tv)))))) den = sum(abs2, v) diff --git a/base/linalg/lu.jl b/base/linalg/lu.jl index d440570f24a36..c38340afe5066 100644 --- a/base/linalg/lu.jl +++ b/base/linalg/lu.jl @@ -584,7 +584,7 @@ function ldiv!(adjA::Adjoint{<:Any,LU{T,Tridiagonal{T,V}}}, B::AbstractVecOrMat) return B end -/(B::AbstractMatrix, A::LU) = copy(Transpose(transpose(A) \ transpose(B))) +/(B::AbstractMatrix, A::LU) = copy(transpose(transpose(A) \ transpose(B))) # Conversions AbstractMatrix(F::LU) = (F.L * F.U)[invperm(F.p),:] diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index 44f836c835280..bfb25b5f14e9e 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -1553,46 +1553,46 @@ for (f1, f2) in ((:*, :mul!), (:\, :ldiv!)) end end -for (ipop, op, xform) in ( - (:mul!, :*, :Adjoint), - (:mul!, :*, :Transpose), - (:ldiv!, :\, :Adjoint), - (:ldiv!, :\, :Transpose)) +for (ipop, op, xformtype, xformop) in ( + (:mul!, :*, :Adjoint, :adjoint), + (:mul!, :*, :Transpose, :transpose), + (:ldiv!, :\, :Adjoint, :adjoint), + (:ldiv!, :\, :Transpose, :transpose)) @eval begin - function ($op)(xformA::($xform){<:Any,<:UpperTriangular}, B::LowerTriangular) + function ($op)(xformA::($xformtype){<:Any,<:UpperTriangular}, B::LowerTriangular) A = xformA.parent - TAB = typeof(($op)($xform(zero(eltype(A))), zero(eltype(B))) + - ($op)($xform(zero(eltype(A))), zero(eltype(B)))) + TAB = typeof(($op)($xformop(zero(eltype(A))), zero(eltype(B))) + + ($op)($xformop(zero(eltype(A))), zero(eltype(B)))) BB = similar(B, TAB, size(B)) copyto!(BB, B) - return LowerTriangular(($ipop)($xform(convert(AbstractMatrix{TAB}, A)), BB)) + return LowerTriangular(($ipop)($xformop(convert(AbstractMatrix{TAB}, A)), BB)) end - function ($op)(xformA::($xform){<:Any,<:UnitUpperTriangular}, B::LowerTriangular) + function ($op)(xformA::($xformtype){<:Any,<:UnitUpperTriangular}, B::LowerTriangular) A = xformA.parent TAB = typeof((*)(zero(eltype(A)), zero(eltype(B))) + (*)(zero(eltype(A)), zero(eltype(B)))) BB = similar(B, TAB, size(B)) copyto!(BB, B) - return LowerTriangular($ipop($xform(convert(AbstractMatrix{TAB}, A)), BB)) + return LowerTriangular($ipop($xformop(convert(AbstractMatrix{TAB}, A)), BB)) end - function ($op)(xformA::($xform){<:Any,<:LowerTriangular}, B::UpperTriangular) + function ($op)(xformA::($xformtype){<:Any,<:LowerTriangular}, B::UpperTriangular) A = xformA.parent - TAB = typeof(($op)($xform(zero(eltype(A))), zero(eltype(B))) + - ($op)($xform(zero(eltype(A))), zero(eltype(B)))) + TAB = typeof(($op)($xformop(zero(eltype(A))), zero(eltype(B))) + + ($op)($xformop(zero(eltype(A))), zero(eltype(B)))) BB = similar(B, TAB, size(B)) copyto!(BB, B) - return UpperTriangular($ipop($xform(convert(AbstractMatrix{TAB}, A)), BB)) + return UpperTriangular($ipop($xformop(convert(AbstractMatrix{TAB}, A)), BB)) end - function ($op)(xformA::($xform){<:Any,<:UnitLowerTriangular}, B::UpperTriangular) + function ($op)(xformA::($xformtype){<:Any,<:UnitLowerTriangular}, B::UpperTriangular) A = xformA.parent TAB = typeof((*)(zero(eltype(A)), zero(eltype(B))) + (*)(zero(eltype(A)), zero(eltype(B)))) BB = similar(B, TAB, size(B)) copyto!(BB, B) - return UpperTriangular($ipop($xform(convert(AbstractMatrix{TAB}, A)), BB)) + return UpperTriangular($ipop($xformop(convert(AbstractMatrix{TAB}, A)), BB)) end end end @@ -1626,46 +1626,46 @@ function (/)(A::UpperTriangular, B::UnitUpperTriangular) return UpperTriangular(rdiv!(AA, convert(AbstractMatrix{TAB}, B))) end -for (ipop, op, xform) in ( - (:mul!, :*, :Adjoint), - (:mul!, :*, :Transpose), - (:rdiv!, :/, :Adjoint), - (:rdiv!, :/, :Transpose)) +for (ipop, op, xformtype, xformop) in ( + (:mul!, :*, :Adjoint, :adjoint), + (:mul!, :*, :Transpose, :transpose), + (:rdiv!, :/, :Adjoint, :adjoint), + (:rdiv!, :/, :Transpose, :transpose)) @eval begin - function ($op)(A::LowerTriangular, xformB::($xform){<:Any,<:UpperTriangular}) + function ($op)(A::LowerTriangular, xformB::($xformtype){<:Any,<:UpperTriangular}) B = xformB.parent - TAB = typeof(($op)(zero(eltype(A)), $xform(zero(eltype(B)))) + - ($op)(zero(eltype(A)), $xform(zero(eltype(B))))) + TAB = typeof(($op)(zero(eltype(A)), $xformop(zero(eltype(B)))) + + ($op)(zero(eltype(A)), $xformop(zero(eltype(B))))) AA = similar(A, TAB, size(A)) copyto!(AA, A) - return LowerTriangular($ipop(AA, $xform(convert(AbstractMatrix{TAB}, B)))) + return LowerTriangular($ipop(AA, $xformop(convert(AbstractMatrix{TAB}, B)))) end - function ($op)(A::LowerTriangular, xformB::($xform){<:Any,<:UnitUpperTriangular}) + function ($op)(A::LowerTriangular, xformB::($xformtype){<:Any,<:UnitUpperTriangular}) B = xformB.parent TAB = typeof((*)(zero(eltype(A)), zero(eltype(B))) + (*)(zero(eltype(A)), zero(eltype(B)))) AA = similar(A, TAB, size(A)) copyto!(AA, A) - return LowerTriangular($ipop(AA, $xform(convert(AbstractMatrix{TAB}, B)))) + return LowerTriangular($ipop(AA, $xformop(convert(AbstractMatrix{TAB}, B)))) end - function ($op)(A::UpperTriangular, xformB::($xform){<:Any,<:LowerTriangular}) + function ($op)(A::UpperTriangular, xformB::($xformtype){<:Any,<:LowerTriangular}) B = xformB.parent - TAB = typeof(($op)(zero(eltype(A)), $xform(zero(eltype(B)))) + - ($op)(zero(eltype(A)), $xform(zero(eltype(B))))) + TAB = typeof(($op)(zero(eltype(A)), $xformop(zero(eltype(B)))) + + ($op)(zero(eltype(A)), $xformop(zero(eltype(B))))) AA = similar(A, TAB, size(A)) copyto!(AA, A) - return UpperTriangular($ipop(AA, $xform(convert(AbstractMatrix{TAB}, B)))) + return UpperTriangular($ipop(AA, $xformop(convert(AbstractMatrix{TAB}, B)))) end - function ($op)(A::UpperTriangular, xformB::($xform){<:Any,<:UnitLowerTriangular}) + function ($op)(A::UpperTriangular, xformB::($xformtype){<:Any,<:UnitLowerTriangular}) B = xformB.parent TAB = typeof((*)(zero(eltype(A)), zero(eltype(B))) + (*)(zero(eltype(A)), zero(eltype(B)))) AA = similar(A, TAB, size(A)) copyto!(AA, A) - return UpperTriangular($ipop(AA, $xform(convert(AbstractMatrix{TAB}, B)))) + return UpperTriangular($ipop(AA, $xformop(convert(AbstractMatrix{TAB}, B)))) end end end diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index 383abe2c22001..6d16c8ba3df0f 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -130,8 +130,8 @@ broadcast(::typeof(ceil), ::Type{T}, M::SymTridiagonal) where {T<:Integer} = Sym transpose(S::SymTridiagonal) = S adjoint(S::SymTridiagonal{<:Real}) = S adjoint(S::SymTridiagonal) = Adjoint(S) -Base.copy(S::Adjoint{<:Any,<:SymTridiagonal}) = SymTridiagonal(map(x -> copy.(Adjoint.(x)), (S.parent.dv, S.parent.ev))...) -Base.copy(S::Transpose{<:Any,<:SymTridiagonal}) = SymTridiagonal(map(x -> copy.(Transpose.(x)), (S.parent.dv, S.parent.ev))...) +Base.copy(S::Adjoint{<:Any,<:SymTridiagonal}) = SymTridiagonal(map(x -> copy.(adjoint.(x)), (S.parent.dv, S.parent.ev))...) +Base.copy(S::Transpose{<:Any,<:SymTridiagonal}) = SymTridiagonal(map(x -> copy.(transpose.(x)), (S.parent.dv, S.parent.ev))...) function diag(M::SymTridiagonal, n::Integer=0) # every branch call similar(..., ::Int) to make sure the @@ -526,8 +526,8 @@ adjoint(S::Tridiagonal) = Adjoint(S) transpose(S::Tridiagonal) = Transpose(S) adjoint(S::Tridiagonal{<:Real}) = Tridiagonal(S.du, S.d, S.dl) transpose(S::Tridiagonal{<:Number}) = Tridiagonal(S.du, S.d, S.dl) -Base.copy(aS::Adjoint{<:Any,<:Tridiagonal}) = (S = aS.parent; Tridiagonal(map(x -> copy.(Adjoint.(x)), (S.du, S.d, S.dl))...)) -Base.copy(tS::Transpose{<:Any,<:Tridiagonal}) = (S = tS.parent; Tridiagonal(map(x -> copy.(Transpose.(x)), (S.du, S.d, S.dl))...)) +Base.copy(aS::Adjoint{<:Any,<:Tridiagonal}) = (S = aS.parent; Tridiagonal(map(x -> copy.(adjoint.(x)), (S.du, S.d, S.dl))...)) +Base.copy(tS::Transpose{<:Any,<:Tridiagonal}) = (S = tS.parent; Tridiagonal(map(x -> copy.(transpose.(x)), (S.du, S.d, S.dl))...)) \(A::Adjoint{<:Any,<:Tridiagonal}, B::Adjoint{<:Any,<:StridedVecOrMat}) = copy(A) \ copy(B) diff --git a/base/sparse/linalg.jl b/base/sparse/linalg.jl index acc9005e50a88..f3b65b5dd5bdb 100644 --- a/base/sparse/linalg.jl +++ b/base/sparse/linalg.jl @@ -934,27 +934,27 @@ function \(A::SparseMatrixCSC, B::AbstractVecOrMat) return \(qrfact(A), B) end end -for xform in (:Adjoint, :Transpose) +for (xformtype, xformop) in ((:Adjoint, :adjoint), (:Transpose, :transpose)) @eval begin - function \(xformA::($xform){<:Any,<:SparseMatrixCSC}, B::AbstractVecOrMat) + function \(xformA::($xformtype){<:Any,<:SparseMatrixCSC}, B::AbstractVecOrMat) A = xformA.parent m, n = size(A) if m == n if istril(A) if istriu(A) - return \($xform(Diagonal(Vector(diag(A)))), B) + return \($xformop(Diagonal(Vector(diag(A)))), B) else - return \($xform(LowerTriangular(A)), B) + return \($xformop(LowerTriangular(A)), B) end elseif istriu(A) - return \($xform(UpperTriangular(A)), B) + return \($xformop(UpperTriangular(A)), B) end if ishermitian(A) - return \($xform(Hermitian(A)), B) + return \($xformop(Hermitian(A)), B) end - return \($xform(lufact(A)), B) + return \($xformop(lufact(A)), B) else - return \($xform(qrfact(A)), B) + return \($xformop(qrfact(A)), B) end end end diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index 26c3288bef47e..e842e9173a63a 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -1812,25 +1812,25 @@ for isunittri in (true, false), islowertri in (true, false) tritype = :(Base.LinAlg.$(Symbol(unitstr, halfstr, "Triangular"))) # build out-of-place left-division operations - for (istrans, applyxform, xform) in ( - (false, false, :identity), - (true, true, :Transpose), - (true, true, :Adjoint) ) + for (istrans, applyxform, xformtype, xformop) in ( + (false, false, :identity, :identity), + (true, true, :Transpose, :transpose), + (true, true, :Adjoint, :adjoint) ) # broad method where elements are Numbers - xformtritype = applyxform ? :($xform{<:TA,<:$tritype{<:Any,<:AbstractMatrix}}) : + xformtritype = applyxform ? :($xformtype{<:TA,<:$tritype{<:Any,<:AbstractMatrix}}) : :($tritype{<:TA,<:AbstractMatrix}) @eval function \(xformA::$xformtritype, b::SparseVector{Tb}) where {TA<:Number,Tb<:Number} A = $(applyxform ? :(xformA.parent) : :(xformA) ) TAb = $(isunittri ? :(typeof(zero(TA)*zero(Tb) + zero(TA)*zero(Tb))) : :(typeof((zero(TA)*zero(Tb) + zero(TA)*zero(Tb))/one(TA))) ) - Base.LinAlg.ldiv!($xform(convert(AbstractArray{TAb}, A)), convert(Array{TAb}, b)) + Base.LinAlg.ldiv!($xformop(convert(AbstractArray{TAb}, A)), convert(Array{TAb}, b)) end # faster method requiring good view support of the # triangular matrix type. hence the StridedMatrix restriction. - xformtritype = applyxform ? :($xform{<:TA,<:$tritype{<:Any,<:StridedMatrix}}) : + xformtritype = applyxform ? :($xformtype{<:TA,<:$tritype{<:Any,<:StridedMatrix}}) : :($tritype{<:TA,<:StridedMatrix}) @eval function \(xformA::$xformtritype, b::SparseVector{Tb}) where {TA<:Number,Tb<:Number} A = $(applyxform ? :(xformA.parent) : :(xformA) ) @@ -1847,25 +1847,25 @@ for isunittri in (true, false), islowertri in (true, false) :(1:b.nzind[end]) ) nzrangeviewr = view(r, nzrange) nzrangeviewA = $tritype(view(A.data, nzrange, nzrange)) - Base.LinAlg.ldiv!($xform(convert(AbstractArray{TAb}, nzrangeviewA)), nzrangeviewr) + Base.LinAlg.ldiv!($xformop(convert(AbstractArray{TAb}, nzrangeviewA)), nzrangeviewr) end r end # fallback where elements are not Numbers - xformtritype = applyxform ? :($xform{<:Any,<:$tritype}) : :($tritype) + xformtritype = applyxform ? :($xformtype{<:Any,<:$tritype}) : :($tritype) @eval function \(xformA::$xformtritype, b::SparseVector) A = $(applyxform ? :(xformA.parent) : :(xformA) ) - Base.LinAlg.ldiv!($xform(A), copy(b)) + Base.LinAlg.ldiv!($xformop(A), copy(b)) end end # build in-place left-division operations - for (istrans, applyxform, xform) in ( - (false, false, :identity), - (true, true, :Transpose), - (true, true, :Adjoint) ) - xformtritype = applyxform ? :($xform{<:Any,<:$tritype{<:Any,<:StridedMatrix}}) : + for (istrans, applyxform, xformtype, xformop) in ( + (false, false, :identity, :identity), + (true, true, :Transpose, :transpose), + (true, true, :Adjoint, :adjoint) ) + xformtritype = applyxform ? :($xformtype{<:Any,<:$tritype{<:Any,<:StridedMatrix}}) : :($tritype{<:Any,<:StridedMatrix}) # the generic in-place left-division methods handle these cases, but @@ -1890,7 +1890,7 @@ for isunittri in (true, false), islowertri in (true, false) :(1:b.nzind[end]) ) nzrangeviewbnz = view(b.nzval, nzrange .- (b.nzind[1] - 1)) nzrangeviewA = $tritype(view(A.data, nzrange, nzrange)) - Base.LinAlg.ldiv!($xform(nzrangeviewA), nzrangeviewbnz) + Base.LinAlg.ldiv!($xformop(nzrangeviewA), nzrangeviewbnz) end b end diff --git a/test/bitarray.jl b/test/bitarray.jl index 38b6b38794a16..214484dcebc7f 100644 --- a/test/bitarray.jl +++ b/test/bitarray.jl @@ -1306,7 +1306,7 @@ end # TODO -@testset "Transpose" begin +@testset "transpose" begin b1 = bitrand(v1) @check_bit_operation transpose(b1) Transpose{Bool,BitVector} diff --git a/test/linalg/dense.jl b/test/linalg/dense.jl index 85676a8c0e002..84db0500926e8 100644 --- a/test/linalg/dense.jl +++ b/test/linalg/dense.jl @@ -790,7 +790,7 @@ end @testset "/ and \\ consistency with pinv for vectors" begin @testset "Tests for type $elty" for elty in (Float32, Float64, ComplexF32, ComplexF64) c = rand(elty, 5) - r = (elty <: Complex ? Adjoint : Transpose)(rand(elty, 5)) + r = (elty <: Complex ? adjoint : transpose)(rand(elty, 5)) cm = rand(elty, 5, 1) rm = rand(elty, 1, 5) @testset "inner prodcuts" begin From 3c28b79ca761fa48b60a9ffb829b21009332bfde Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 8 Jan 2018 13:17:17 -0800 Subject: [PATCH 2/2] Make Adjoint/Transpose behave like typical constructors. --- base/linalg/adjtrans.jl | 102 ++++++++++++++++++---------------------- test/linalg/adjtrans.jl | 32 ++++++------- 2 files changed, 63 insertions(+), 71 deletions(-) diff --git a/base/linalg/adjtrans.jl b/base/linalg/adjtrans.jl index 2aa57766b47e2..7f462700e5601 100644 --- a/base/linalg/adjtrans.jl +++ b/base/linalg/adjtrans.jl @@ -11,46 +11,38 @@ import Base: length, size, axes, IndexStyle, getindex, setindex!, parent, vec, c struct Adjoint{T,S} <: AbstractMatrix{T} parent::S function Adjoint{T,S}(A::S) where {T,S} - checkeltype(Adjoint, T, eltype(A)) + checkeltype_adjoint(T, eltype(A)) new(A) end end struct Transpose{T,S} <: AbstractMatrix{T} parent::S function Transpose{T,S}(A::S) where {T,S} - checkeltype(Transpose, T, eltype(A)) + checkeltype_transpose(T, eltype(A)) new(A) end end -function checkeltype(::Type{Transform}, ::Type{ResultEltype}, ::Type{ParentEltype}) where {Transform, ResultEltype, ParentEltype} - if ResultEltype !== transformtype(Transform, ParentEltype) - error(string("Element type mismatch. Tried to create an `$Transform{$ResultEltype}` ", - "from an object with eltype `$ParentEltype`, but the element type of the ", - "`$Transform` of an object with eltype `$ParentEltype` must be ", - "`$(transformtype(Transform, ParentEltype))`")) - end +function checkeltype_adjoint(::Type{ResultEltype}, ::Type{ParentEltype}) where {ResultEltype,ParentEltype} + ResultEltype === Base.promote_op(adjoint, ParentEltype) || error(string( + "Element type mismatch. Tried to create an `Adjoint{$ResultEltype}` ", + "from an object with eltype `$ParentEltype`, but the element type of ", + "the adjoint of an object with eltype `$ParentEltype` must be ", + "`$(Base.promote_op(adjoint, ParentEltype))`.")) return nothing end -function transformtype(::Type{O}, ::Type{S}) where {O,S} - # similar to promote_op(::Any, ::Type) - @_inline_meta - T = _return_type(O, Tuple{_default_type(S)}) - _isleaftype(S) && return _isleaftype(T) ? T : Any - return typejoin(S, T) +function checkeltype_transpose(::Type{ResultEltype}, ::Type{ParentEltype}) where {ResultEltype,ParentEltype} + ResultEltype === Base.promote_op(transpose, ParentEltype) || error(string( + "Element type mismatch. Tried to create a `Transpose{$ResultEltype}` ", + "from an object with eltype `$ParentEltype`, but the element type of ", + "the transpose of an object with eltype `$ParentEltype` must be ", + "`$(Base.promote_op(transpose, ParentEltype))`.")) + return nothing end # basic outer constructors -Adjoint(A) = Adjoint{transformtype(Adjoint,eltype(A)),typeof(A)}(A) -Transpose(A) = Transpose{transformtype(Transpose,eltype(A)),typeof(A)}(A) - -# numbers are the end of the line -Adjoint(x::Number) = adjoint(x) -Transpose(x::Number) = transpose(x) - -# unwrapping constructors -Adjoint(A::Adjoint) = A.parent -Transpose(A::Transpose) = A.parent +Adjoint(A) = Adjoint{Base.promote_op(adjoint,eltype(A)),typeof(A)}(A) +Transpose(A) = Transpose{Base.promote_op(transpose,eltype(A)),typeof(A)}(A) # wrapping lowercase quasi-constructors adjoint(A::AbstractVecOrMat) = Adjoint(A) @@ -80,6 +72,7 @@ julia> transpose(A) ``` """ transpose(A::AbstractVecOrMat) = Transpose(A) + # unwrapping lowercase quasi-constructors adjoint(A::Adjoint) = A.parent transpose(A::Transpose) = A.parent @@ -95,10 +88,8 @@ const AdjOrTransAbsVec{T} = AdjOrTrans{T,<:AbstractVector} const AdjOrTransAbsMat{T} = AdjOrTrans{T,<:AbstractMatrix} # for internal use below -wrappertype(A::Adjoint) = Adjoint -wrappertype(A::Transpose) = Transpose -wrappertype(::Type{<:Adjoint}) = Adjoint -wrappertype(::Type{<:Transpose}) = Transpose +wrapperop(A::Adjoint) = adjoint +wrapperop(A::Transpose) = transpose # AbstractArray interface, basic definitions length(A::AdjOrTrans) = length(A.parent) @@ -108,13 +99,13 @@ axes(v::AdjOrTransAbsVec) = (Base.OneTo(1), axes(v.parent)...) axes(A::AdjOrTransAbsMat) = reverse(axes(A.parent)) IndexStyle(::Type{<:AdjOrTransAbsVec}) = IndexLinear() IndexStyle(::Type{<:AdjOrTransAbsMat}) = IndexCartesian() -@propagate_inbounds getindex(v::AdjOrTransAbsVec, i::Int) = wrappertype(v)(v.parent[i]) -@propagate_inbounds getindex(A::AdjOrTransAbsMat, i::Int, j::Int) = wrappertype(A)(A.parent[j, i]) -@propagate_inbounds setindex!(v::AdjOrTransAbsVec, x, i::Int) = (setindex!(v.parent, wrappertype(v)(x), i); v) -@propagate_inbounds setindex!(A::AdjOrTransAbsMat, x, i::Int, j::Int) = (setindex!(A.parent, wrappertype(A)(x), j, i); A) +@propagate_inbounds getindex(v::AdjOrTransAbsVec, i::Int) = wrapperop(v)(v.parent[i]) +@propagate_inbounds getindex(A::AdjOrTransAbsMat, i::Int, j::Int) = wrapperop(A)(A.parent[j, i]) +@propagate_inbounds setindex!(v::AdjOrTransAbsVec, x, i::Int) = (setindex!(v.parent, wrapperop(v)(x), i); v) +@propagate_inbounds setindex!(A::AdjOrTransAbsMat, x, i::Int, j::Int) = (setindex!(A.parent, wrapperop(A)(x), j, i); A) # AbstractArray interface, additional definitions to retain wrapper over vectors where appropriate -@propagate_inbounds getindex(v::AdjOrTransAbsVec, ::Colon, is::AbstractArray{Int}) = wrappertype(v)(v.parent[is]) -@propagate_inbounds getindex(v::AdjOrTransAbsVec, ::Colon, ::Colon) = wrappertype(v)(v.parent[:]) +@propagate_inbounds getindex(v::AdjOrTransAbsVec, ::Colon, is::AbstractArray{Int}) = wrapperop(v)(v.parent[is]) +@propagate_inbounds getindex(v::AdjOrTransAbsVec, ::Colon, ::Colon) = wrapperop(v)(v.parent[:]) # conversion of underlying storage convert(::Type{Adjoint{T,S}}, A::Adjoint) where {T,S} = Adjoint{T,S}(convert(S, A.parent)) @@ -122,8 +113,8 @@ convert(::Type{Transpose{T,S}}, A::Transpose) where {T,S} = Transpose{T,S}(conve # for vectors, the semantics of the wrapped and unwrapped types differ # so attempt to maintain both the parent and wrapper type insofar as possible -similar(A::AdjOrTransAbsVec) = wrappertype(A)(similar(A.parent)) -similar(A::AdjOrTransAbsVec, ::Type{T}) where {T} = wrappertype(A)(similar(A.parent, transformtype(wrappertype(A), T))) +similar(A::AdjOrTransAbsVec) = wrapperop(A)(similar(A.parent)) +similar(A::AdjOrTransAbsVec, ::Type{T}) where {T} = wrapperop(A)(similar(A.parent, Base.promote_op(wrapperop(A), T))) # for matrices, the semantics of the wrapped and unwrapped types are generally the same # and as you are allocating with similar anyway, you might as well get something unwrapped similar(A::AdjOrTrans) = similar(A.parent, eltype(A), size(A)) @@ -142,15 +133,16 @@ isless(A::AdjOrTransAbsVec, B::AdjOrTransAbsVec) = isless(parent(A), parent(B)) # to retain the associated semantics post-concatenation hcat(avs::Union{Number,AdjointAbsVec}...) = _adjoint_hcat(avs...) hcat(tvs::Union{Number,TransposeAbsVec}...) = _transpose_hcat(tvs...) -_adjoint_hcat(avs::Union{Number,AdjointAbsVec}...) = Adjoint(vcat(map(Adjoint, avs)...)) -_transpose_hcat(tvs::Union{Number,TransposeAbsVec}...) = Transpose(vcat(map(Transpose, tvs)...)) -typed_hcat(::Type{T}, avs::Union{Number,AdjointAbsVec}...) where {T} = Adjoint(typed_vcat(T, map(Adjoint, avs)...)) -typed_hcat(::Type{T}, tvs::Union{Number,TransposeAbsVec}...) where {T} = Transpose(typed_vcat(T, map(Transpose, tvs)...)) +_adjoint_hcat(avs::Union{Number,AdjointAbsVec}...) = adjoint(vcat(map(adjoint, avs)...)) +_transpose_hcat(tvs::Union{Number,TransposeAbsVec}...) = transpose(vcat(map(transpose, tvs)...)) +typed_hcat(::Type{T}, avs::Union{Number,AdjointAbsVec}...) where {T} = adjoint(typed_vcat(T, map(adjoint, avs)...)) +typed_hcat(::Type{T}, tvs::Union{Number,TransposeAbsVec}...) where {T} = transpose(typed_vcat(T, map(transpose, tvs)...)) # otherwise-redundant definitions necessary to prevent hitting the concat methods in sparse/sparsevector.jl hcat(avs::Adjoint{<:Any,<:Vector}...) = _adjoint_hcat(avs...) hcat(tvs::Transpose{<:Any,<:Vector}...) = _transpose_hcat(tvs...) hcat(avs::Adjoint{T,Vector{T}}...) where {T} = _adjoint_hcat(avs...) hcat(tvs::Transpose{T,Vector{T}}...) where {T} = _transpose_hcat(tvs...) +# TODO unify and allow mixed combinations ### higher order functions @@ -158,14 +150,14 @@ hcat(tvs::Transpose{T,Vector{T}}...) where {T} = _transpose_hcat(tvs...) # to retain the associated semantics post-map/broadcast # # note that the caller's operation f operates in the domain of the wrapped vectors' entries. -# hence the Adjoint->f->Adjoint shenanigans applied to the parent vectors' entries. -map(f, avs::AdjointAbsVec...) = Adjoint(map((xs...) -> Adjoint(f(Adjoint.(xs)...)), parent.(avs)...)) -map(f, tvs::TransposeAbsVec...) = Transpose(map((xs...) -> Transpose(f(Transpose.(xs)...)), parent.(tvs)...)) +# hence the adjoint->f->adjoint shenanigans applied to the parent vectors' entries. +map(f, avs::AdjointAbsVec...) = adjoint(map((xs...) -> adjoint(f(adjoint.(xs)...)), parent.(avs)...)) +map(f, tvs::TransposeAbsVec...) = transpose(map((xs...) -> transpose(f(transpose.(xs)...)), parent.(tvs)...)) quasiparentt(x) = parent(x); quasiparentt(x::Number) = x # to handle numbers in the defs below quasiparenta(x) = parent(x); quasiparenta(x::Number) = conj(x) # to handle numbers in the defs below -broadcast(f, avs::Union{Number,AdjointAbsVec}...) = Adjoint(broadcast((xs...) -> Adjoint(f(Adjoint.(xs)...)), quasiparenta.(avs)...)) -broadcast(f, tvs::Union{Number,TransposeAbsVec}...) = Transpose(broadcast((xs...) -> Transpose(f(Transpose.(xs)...)), quasiparentt.(tvs)...)) - +broadcast(f, avs::Union{Number,AdjointAbsVec}...) = adjoint(broadcast((xs...) -> adjoint(f(adjoint.(xs)...)), quasiparenta.(avs)...)) +broadcast(f, tvs::Union{Number,TransposeAbsVec}...) = transpose(broadcast((xs...) -> transpose(f(transpose.(xs)...)), quasiparentt.(tvs)...)) +# TODO unify and allow mixed combinations ### linear algebra @@ -186,11 +178,11 @@ end *(u::TransposeAbsVec, v::TransposeAbsVec) = throw(MethodError(*, (u, v))) # Adjoint/Transpose-vector * matrix -*(u::AdjointAbsVec, A::AbstractMatrix) = Adjoint(Adjoint(A) * u.parent) -*(u::TransposeAbsVec, A::AbstractMatrix) = Transpose(Transpose(A) * u.parent) +*(u::AdjointAbsVec, A::AbstractMatrix) = adjoint(adjoint(A) * u.parent) +*(u::TransposeAbsVec, A::AbstractMatrix) = transpose(transpose(A) * u.parent) # Adjoint/Transpose-vector * Adjoint/Transpose-matrix -*(u::AdjointAbsVec, A::Adjoint{<:Any,<:AbstractMatrix}) = Adjoint(A.parent * u.parent) -*(u::TransposeAbsVec, A::Transpose{<:Any,<:AbstractMatrix}) = Transpose(A.parent * u.parent) +*(u::AdjointAbsVec, A::Adjoint{<:Any,<:AbstractMatrix}) = adjoint(A.parent * u.parent) +*(u::TransposeAbsVec, A::Transpose{<:Any,<:AbstractMatrix}) = transpose(A.parent * u.parent) ## pseudoinversion @@ -203,10 +195,10 @@ 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::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) # dismabiguation methods *(A::AdjointAbsVec, B::Transpose{<:Any,<:AbstractMatrix}) = A * copy(B) diff --git a/test/linalg/adjtrans.jl b/test/linalg/adjtrans.jl index c84a551a84c33..9abdfa3f880fb 100644 --- a/test/linalg/adjtrans.jl +++ b/test/linalg/adjtrans.jl @@ -62,23 +62,12 @@ end # the tests for the inner constructors exercise abstract scalar and concrete array eltype, forgoing here end -@testset "Adjoint and Transpose of Numbers" begin - @test Adjoint(1) == 1 - @test Adjoint(1.0) == 1.0 - @test Adjoint(1im) == -1im - @test Adjoint(1.0im) == -1.0im - @test Transpose(1) == 1 - @test Transpose(1.0) == 1.0 - @test Transpose(1im) == 1im - @test Transpose(1.0im) == 1.0im -end - -@testset "Adjoint and Transpose unwrapping" begin +@testset "Adjoint and Transpose add additional layers to already-wrapped objects" begin intvec, intmat = [1, 2], [1 2; 3 4] - @test Adjoint(Adjoint(intvec)) === intvec - @test Adjoint(Adjoint(intmat)) === intmat - @test Transpose(Transpose(intvec)) === intvec - @test Transpose(Transpose(intmat)) === intmat + @test (A = Adjoint(Adjoint(intvec))::Adjoint{Int,Adjoint{Int,Vector{Int}}}; A.parent.parent === intvec) + @test (A = Adjoint(Adjoint(intmat))::Adjoint{Int,Adjoint{Int,Matrix{Int}}}; A.parent.parent === intmat) + @test (A = Transpose(Transpose(intvec))::Transpose{Int,Transpose{Int,Vector{Int}}}; A.parent.parent === intvec) + @test (A = Transpose(Transpose(intmat))::Transpose{Int,Transpose{Int,Matrix{Int}}}; A.parent.parent === intmat) end @testset "Adjoint and Transpose basic AbstractArray functionality" begin @@ -441,6 +430,17 @@ end end end +@testset "adjoint and transpose of Numbers" begin + @test adjoint(1) == 1 + @test adjoint(1.0) == 1.0 + @test adjoint(1im) == -1im + @test adjoint(1.0im) == -1.0im + @test transpose(1) == 1 + @test transpose(1.0) == 1.0 + @test transpose(1im) == 1im + @test transpose(1.0im) == 1.0im +end + @testset "adjoint!(a, b) return a" begin a = fill(1.0+im, 5) b = fill(1.0+im, 1, 5)