diff --git a/base/deprecated.jl b/base/deprecated.jl index 76864183f3bff..1a060e63e9fa7 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2990,6 +2990,131 @@ end # re. A_mul_B deprecation, don't forget to: # 1) delete function shims in base/linalg/linalg.jl +# methods involving RowVector from base/linalg/bidiag.jl, to deprecate +@eval Base.LinAlg begin + \(::Diagonal, ::RowVector) = _mat_ldiv_rowvec_error() + \(::Bidiagonal, ::RowVector) = _mat_ldiv_rowvec_error() + \(::Bidiagonal{<:Number}, ::RowVector{<:Number}) = _mat_ldiv_rowvec_error() + \(::Adjoint{<:Any,<:Bidiagonal}, ::RowVector) = _mat_ldiv_rowvec_error() + \(::Transpose{<:Any,<:Bidiagonal}, ::RowVector) = _mat_ldiv_rowvec_error() + \(::Adjoint{<:Number,<:Bidiagonal{<:Number}}, ::RowVector{<:Number}) = _mat_ldiv_rowvec_error() + \(::Transpose{<:Number,<:Bidiagonal{<:Number}}, ::RowVector{<:Number}) = _mat_ldiv_rowvec_error() + _mat_ldiv_rowvec_error() = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) +end + +# methods involving RowVector from base/linalg/diagonal.jl, to deprecate +@eval Base.LinAlg begin + *(rowvec::RowVector, D::Diagonal) = rvtranspose(D * rvtranspose(rowvec)) # seems potentially incorrect without also transposing D? + *(D::Diagonal, transrowvec::Transpose{<:Any,<:RowVector}) = (rowvec = transrowvec.parent; D*rvtranspose(rowvec)) + *(D::Diagonal, adjrowvec::Adjoint{<:Any,<:RowVector}) = (rowvec = adjrowvec.parent; D*rvadjoint(rowvec)) +end + +# methods involving RowVector from base/sparse/linalg.jl, to deprecate +@eval Base.SparseArrays begin + \(::SparseMatrixCSC, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) + \(::Adjoint{<:Any,<:SparseMatrixCSC}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) + \(::Transpose{<:Any,<:SparseMatrixCSC}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) +end + +# methods involving RowVector from base/linalg/qr.jl, to deprecate +@eval Base.LinAlg begin + *(rowvec::RowVector, adjB::Adjoint{<:Any,<:AbstractQ}) = (B = adjB.parent; rvadjoint(B*rvadjoint(rowvec))) +end + +# methods involving RowVector from base/linalg/qr.jl, to deprecate +@eval Base.LinAlg begin + *(A::RowVector, B::Adjoint{<:Any,<:AbstractRotation}) = A * adjoint(B.parent) +end + +# methods involving RowVector from base/linalg/generic.jl, to deprecate +@eval Base.LinAlg begin + """ + norm(A::RowVector, q::Real=2) + + For row vectors, return the ``q``-norm of `A`, which is equivalent to the p-norm with + value `p = q/(q-1)`. They coincide at `p = q = 2`. + + The difference in norm between a vector space and its dual arises to preserve + the relationship between duality and the inner product, and the result is + consistent with the p-norm of `1 × n` matrix. + + # Examples + ```jldoctest + julia> v = [1; im]; + + julia> vc = v'; + + julia> norm(vc, 1) + 1.0 + + julia> norm(v, 1) + 2.0 + + julia> norm(vc, 2) + 1.4142135623730951 + + julia> norm(v, 2) + 1.4142135623730951 + + julia> norm(vc, Inf) + 2.0 + + julia> norm(v, Inf) + 1.0 + ``` + """ + norm(tv::RowVector, q::Real) = q == Inf ? norm(rvtranspose(tv), 1) : norm(rvtranspose(tv), q/(q-1)) + norm(tv::RowVector) = norm(rvtranspose(tv)) +end + +# methods involving RowVector from base/linalg/factorization.jl, to deprecate +@eval Base.LinAlg begin + \(A::Adjoint{<:Any,<:Factorization}, B::RowVector) = adjoint(A.parent) \ B + \(A::Transpose{<:Any,<:Factorization}, B::RowVector) = transpose(A.parent) \ B + \(A::Transpose{<:Any,<:Factorization{<:Real}}, B::RowVector) = transpose(A.parent) \ B +end + +# methods involving RowVector from base/sparse/higherorderfns.jl, to deprecate +@eval Base.SparseArrays.HigherOrderFns begin + BroadcastStyle(::Type{<:Base.RowVector{T,<:Vector}}) where T = Broadcast.MatrixStyle() +end + +# methods involving RowVector from base/linalg/symmetric.jl, to deprecate +@eval Base.LinAlg begin + *(A::RowVector, transB::Transpose{<:Any,<:RealHermSymComplexSym}) = A * transB.parent + *(A::RowVector, adjB::Adjoint{<:Any,<:RealHermSymComplexHerm}) = A * adjB.parent + \(A::HermOrSym{<:Any,<:StridedMatrix}, B::RowVector) = invoke(\, Tuple{AbstractMatrix, RowVector}, A, B) + *(A::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::Adjoint{<:Any,<:RowVector}) = A.parent * B + *(A::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::Transpose{<:Any,<:RowVector}) = A.parent * B + *(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Adjoint{<:Any,<:RowVector}) = A.parent * B + *(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Transpose{<:Any,<:RowVector}) = A.parent * B +end + +# methods involving RowVector from base/linalg/triangular.jl, to deprecate +@eval Base.LinAlg begin + *(rowvec::RowVector, A::AbstractTriangular) = rvtranspose(transpose(A) * rvtranspose(rowvec)) + *(rowvec::RowVector, transA::Transpose{<:Any,<:AbstractTriangular}) = rvtranspose(transA.parent * rvtranspose(rowvec)) + *(A::AbstractTriangular, transrowvec::Transpose{<:Any,<:RowVector}) = A * rvtranspose(transrowvec.parent) + *(transA::Transpose{<:Any,<:AbstractTriangular}, transrowvec::Transpose{<:Any,<:RowVector}) = transA.parent.' * rvtranspose(transrowvec.parent) + *(rowvec::RowVector, adjA::Adjoint{<:Any,<:AbstractTriangular}) = rvadjoint(adjA.parent * rvadjoint(rowvec)) + *(A::AbstractTriangular, adjrowvec::Adjoint{<:Any,<:RowVector}) = A * rvadjoint(adjrowvec.parent) + *(adjA::Adjoint{<:Any,<:AbstractTriangular}, adjrowvec::Adjoint{<:Any,<:RowVector}) = adjA.parent' * rvadjoint(adjrowvec.parent) + \(::Union{UpperTriangular,LowerTriangular}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) + \(::Union{UnitUpperTriangular,UnitLowerTriangular}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) + \(::Adjoint{<:Any,<:Union{UpperTriangular,LowerTriangular}}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) + \(::Adjoint{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) + \(::Transpose{<:Any,<:Union{UpperTriangular,LowerTriangular}}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) + \(::Transpose{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) + /(rowvec::RowVector, A::Union{UpperTriangular,LowerTriangular}) = rvtranspose(transpose(A) \ rvtranspose(rowvec)) + /(rowvec::RowVector, A::Union{UnitUpperTriangular,UnitLowerTriangular}) = rvtranspose(transpose(A) \ rvtranspose(rowvec)) + /(rowvec::RowVector, transA::Transpose{<:Any,<:Union{UpperTriangular,LowerTriangular}}) = rvtranspose(transA.parent \ rvtranspose(rowvec)) + /(rowvec::RowVector, transA::Transpose{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}) = rvtranspose(transA.parent \ rvtranspose(rowvec)) + /(rowvec::RowVector, adjA::Adjoint{<:Any,<:Union{UpperTriangular,LowerTriangular}}) = /(rowvec, adjoint(adjA.parent)) + /(rowvec::RowVector, adjA::Adjoint{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}) = /(rowvec, adjoint(adjA.parent)) + *(A::Adjoint{<:Any,<:AbstractTriangular}, B::Transpose{<:Any,<:RowVector}) = A * rvtranspose(B.parent) + *(A::Transpose{<:Any,<:AbstractTriangular}, B::Adjoint{<:Any,<:RowVector}) = A * rvadjoint(B.parent) +end + # issue #24822 @deprecate_binding Display AbstractDisplay diff --git a/base/exports.jl b/base/exports.jl index 1aa49686a6c03..4071076b23f64 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -95,6 +95,8 @@ export RoundNearestTiesUp, RoundToZero, RoundUp, + Adjoint, + Transpose, RowVector, AbstractSerializer, SerializationState, diff --git a/base/linalg/adjtrans.jl b/base/linalg/adjtrans.jl index 984370318a36e..6d7b56aa89fe8 100644 --- a/base/linalg/adjtrans.jl +++ b/base/linalg/adjtrans.jl @@ -49,12 +49,30 @@ Adjoint(x::Number) = adjoint(x) Transpose(x::Number) = transpose(x) # unwrapping constructors -# perhaps slightly odd, but necessary (at least till adjoint and transpose names are free) Adjoint(A::Adjoint) = A.parent Transpose(A::Transpose) = A.parent +# normalizing unwrapping constructors +# technically suspect, but at least fine for now +Adjoint(A::Transpose) = conj(A.parent) +Transpose(A::Adjoint) = conj(A.parent) + +# eager lowercase quasi-constructors, unwrapping +adjoint(A::Adjoint) = copy(A.parent) +transpose(A::Transpose) = copy(A.parent) +# eager lowercase quasi-constructors, normalizing +# technically suspect, but at least fine for now +adjoint(A::Transpose) = conj!(copy(A.parent)) +transpose(A::Adjoint) = conj!(copy(A.parent)) + +# lowercase quasi-constructors for vectors, TODO: deprecate +adjoint(sv::AbstractVector) = Adjoint(sv) +transpose(sv::AbstractVector) = Transpose(sv) + # some aliases for internal convenience use const AdjOrTrans{T,S} = Union{Adjoint{T,S},Transpose{T,S}} where {T,S} +const AdjointAbsVec{T} = Adjoint{T,<:AbstractVector} +const TransposeAbsVec{T} = Transpose{T,<:AbstractVector} const AdjOrTransAbsVec{T} = AdjOrTrans{T,<:AbstractVector} const AdjOrTransAbsMat{T} = AdjOrTrans{T,<:AbstractMatrix} @@ -99,22 +117,100 @@ parent(A::AdjOrTrans) = A.parent vec(v::AdjOrTransAbsVec) = v.parent +### concatenation +# preserve Adjoint/Transpose wrapper around vectors +# 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)...)) +# 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...) + + +### higher order functions +# preserve Adjoint/Transpose wrapper around vectors +# to retain the associated semantics post-map/broadcast + +# vectorfy takes an Adoint/Transpose-wrapped vector and builds +# an unwrapped vector with the entrywise-same contents +vectorfy(x::Number) = x +vectorfy(adjvec::AdjointAbsVec) = map(Adjoint, adjvec.parent) +vectorfy(transvec::TransposeAbsVec) = map(Transpose, transvec.parent) +vectorfyall(transformedvecs...) = (map(vectorfy, transformedvecs)...,) + +# map over collections of Adjoint/Transpose-wrapped vectors +# note that the caller's operation `f` should be applied to the entries of the wrapped +# vectors, rather than the entires of the wrapped vector's parents. so first we use vectorfy +# to build unwrapped vectors with entrywise-same contents as the wrapped input vectors. +# then we map the caller's operation over that set of unwrapped vectors. but now re-wrapping +# the resulting vector would inappropriately transform the result vector's entries. so +# instead of simply mapping the caller's operation over the set of unwrapped vectors, +# we map Adjoint/Transpose composed with the caller's operationt over the set of unwrapped +# vectors. then re-wrapping the result vector yields a wrapped vector with the correct entries. +map(f, avs::AdjointAbsVec...) = Adjoint(map(Adjoint∘f, vectorfyall(avs...)...)) +map(f, tvs::TransposeAbsVec...) = Transpose(map(Transpose∘f, vectorfyall(tvs...)...)) + +# broadcast over collections of Adjoint/Transpose-wrapped vectors and numbers +# similar explanation for these definitions as for map above +broadcast(f, avs::Union{Number,AdjointAbsVec}...) = Adjoint(broadcast(Adjoint∘f, vectorfyall(avs...)...)) +broadcast(f, tvs::Union{Number,TransposeAbsVec}...) = Transpose(broadcast(Transpose∘f, vectorfyall(tvs...) ...)) + + ### linear algebra -# definitions necessary for test/linalg/rowvector.jl to pass -# should be cleaned up / revised as necessary in the future -/(A::Transpose{<:Any,<:Vector}, B::Matrix) = /(transpose(A.parent), B) -/(A::Transpose{<:Any,<:Vector}, B::Transpose{<:Any,<:Matrix}) = /(transpose(A.parent), B) -*(A::Adjoint{<:Any,<:Matrix}, B::Adjoint{<:Any,<:Vector}) = *(adjoint(A.parent), adjoint(B.parent)) +## multiplication * + +# Adjoint/Transpose-vector * vector +*(u::AdjointAbsVec, v::AbstractVector) = dot(u.parent, v) +*(u::TransposeAbsVec{T}, v::AbstractVector{T}) where {T<:Real} = dot(u.parent, v) +function *(u::TransposeAbsVec, v::AbstractVector) + @boundscheck length(u) == length(v) || throw(DimensionMismatch()) + return sum(@inbounds(return u[k]*v[k]) for k in 1:length(u)) +end +# vector * Adjoint/Transpose-vector +*(u::AbstractVector, v::AdjOrTransAbsVec) = broadcast(*, u, v) +# Adjoint/Transpose-vector * Adjoint/Transpose-vector +# (necessary for disambiguation with fallback methods in linalg/matmul) +*(u::AdjointAbsVec, v::AdjointAbsVec) = throw(MethodError(*, (u, v))) +*(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) +# 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) + + +## pseudoinversion +pinv(v::AdjointAbsVec, tol::Real = 0) = pinv(v.parent, tol).parent +pinv(v::TransposeAbsVec, tol::Real = 0) = pinv(conj(v.parent)).parent + + +## left-division \ +\(u::AdjOrTransAbsVec, v::AdjOrTransAbsVec) = pinv(u) * v + + +## right-division \ +/(u::AdjointAbsVec, A::AbstractMatrix) = Adjoint(Adjoint(A) \ u.parent) +/(u::TransposeAbsVec, A::AbstractMatrix) = Transpose(Transpose(A) \ u.parent) # dismabiguation methods -*(A::Transpose{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:AbstractVector}) = transpose(A.parent) * B -*(A::Transpose{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:AbstractMatrix}) = transpose(A.parent) * B -*(A::Transpose{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractVector}) = A * adjoint(B.parent) +*(A::AdjointAbsVec, B::Transpose{<:Any,<:AbstractMatrix}) = A * transpose(B.parent) +*(A::TransposeAbsVec, B::Adjoint{<:Any,<:AbstractMatrix}) = A * adjoint(B.parent) *(A::Transpose{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractMatrix}) = transpose(A.parent) * B -*(A::Adjoint{<:Any,<:AbstractVector}, B::Transpose{<:Any,<:AbstractVector}) = adjoint(A.parent) * B -*(A::Adjoint{<:Any,<:AbstractVector}, B::Transpose{<:Any,<:AbstractMatrix}) = adjoint(A.parent) * B -*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractVector}) = A * adjoint(B.parent) -*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:AbstractVector}) = A * transpose(B.parent) -*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:AbstractMatrix}) = adjoint(A.parent) * B \ No newline at end of file +*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:AbstractMatrix}) = A * transpose(B.parent) +# Adj/Trans-vector * Trans/Adj-vector, shouldn't exist, here for ambiguity resolution? TODO: test removal +*(A::Adjoint{<:Any,<:AbstractVector}, B::Transpose{<:Any,<:AbstractVector}) = throw(MethodError(*, (A, B))) +*(A::Transpose{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:AbstractVector}) = throw(MethodError(*, (A, B))) +# Adj/Trans-matrix * Trans/Adj-vector, shouldn't exist, here for ambiguity resolution? TODO: test removal +*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractVector}) = throw(MethodError(*, (A, B))) +*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:AbstractVector}) = throw(MethodError(*, (A, B))) +*(A::Transpose{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractVector}) = throw(MethodError(*, (A, B))) diff --git a/base/linalg/bidiag.jl b/base/linalg/bidiag.jl index 4d5635a19727c..eefb6056b210d 100644 --- a/base/linalg/bidiag.jl +++ b/base/linalg/bidiag.jl @@ -348,15 +348,6 @@ mul!(C::AbstractMatrix, A::BiTri, B::Transpose{<:Any,<:AbstractVecOrMat}) = A_mu mul!(C::AbstractMatrix, A::BiTri, B::Adjoint{<:Any,<:AbstractVecOrMat}) = A_mul_B_td!(C, A, B) mul!(C::AbstractVector, A::BiTri, B::Transpose{<:Any,<:AbstractVecOrMat}) = throw(MethodError(mul!, (C, A, B))) -\(::Diagonal, ::RowVector) = _mat_ldiv_rowvec_error() -\(::Bidiagonal, ::RowVector) = _mat_ldiv_rowvec_error() -\(::Bidiagonal{<:Number}, ::RowVector{<:Number}) = _mat_ldiv_rowvec_error() -\(::Adjoint{<:Any,<:Bidiagonal}, ::RowVector) = _mat_ldiv_rowvec_error() -\(::Transpose{<:Any,<:Bidiagonal}, ::RowVector) = _mat_ldiv_rowvec_error() -\(::Adjoint{<:Number,<:Bidiagonal{<:Number}}, ::RowVector{<:Number}) = _mat_ldiv_rowvec_error() -\(::Transpose{<:Number,<:Bidiagonal{<:Number}}, ::RowVector{<:Number}) = _mat_ldiv_rowvec_error() -_mat_ldiv_rowvec_error() = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) - function check_A_mul_B!_sizes(C, A, B) nA, mA = size(A) nB, mB = size(B) diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index a6f70e68dc252..bdf18cb084ce8 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -358,11 +358,6 @@ rdiv!(A::AbstractMatrix{T}, transD::Transpose{<:Any,<:Diagonal{T}}) where {T} = \(adjF::Adjoint{<:Any,<:Factorization}, D::Diagonal) = (F = adjF.parent; ldiv!(Adjoint(F), Matrix{typeof(oneunit(eltype(D))/oneunit(eltype(F)))}(D))) -# Methods to resolve ambiguities with `Diagonal` -@inline *(rowvec::RowVector, D::Diagonal) = transpose(D * transpose(rowvec)) -*(D::Diagonal, transrowvec::Transpose{<:Any,<:RowVector}) = (rowvec = transrowvec.parent; D*transpose(rowvec)) -*(D::Diagonal, adjrowvec::Adjoint{<:Any,<:RowVector}) = (rowvec = adjrowvec.parent; D*adjoint(rowvec)) - conj(D::Diagonal) = Diagonal(conj(D.diag)) transpose(D::Diagonal{<:Number}) = D transpose(D::Diagonal) = Diagonal(transpose.(D.diag)) diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl index d99c071799244..a83a5dcb725b3 100644 --- a/base/linalg/factorization.jl +++ b/base/linalg/factorization.jl @@ -85,8 +85,3 @@ ldiv!(Y::AbstractVecOrMat, transA::Transpose{<:Any,<:Factorization}, B::Abstract # fallback methods for transposed solves \(transF::Transpose{<:Any,<:Factorization{<:Real}}, B::AbstractVecOrMat) = (F = transF.parent; \(Adjoint(F), B)) \(transF::Transpose{<:Any,<:Factorization}, B::AbstractVecOrMat) = (F = transF.parent; conj.(\(Adjoint(F), conj.(B)))) - -# dismabiguation methods -\(A::Adjoint{<:Any,<:Factorization}, B::RowVector) = adjoint(A.parent) \ B -\(A::Transpose{<:Any,<:Factorization}, B::RowVector) = transpose(A.parent) \ B -\(A::Transpose{<:Any,<:Factorization{<:Real}}, B::RowVector) = transpose(A.parent) \ B diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index 40373f13cc36c..d0991145d0dfa 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -576,13 +576,12 @@ This is equivalent to [`vecnorm`](@ref). """ @inline norm(x::Number, p::Real=2) = vecnorm(x, p) -@inline norm(tv::RowVector) = norm(transpose(tv)) - """ - norm(A::RowVector, q::Real=2) + norm(A::Adjoint{<:Any,<:AbstracVector}, q::Real=2) + norm(A::Transpose{<:Any,<:AbstracVector}, q::Real=2) -For row vectors, return the ``q``-norm of `A`, which is equivalent to the p-norm with -value `p = q/(q-1)`. They coincide at `p = q = 2`. +For Adjoint/Transpose-wrapped vectors, return the ``q``-norm of `A`, which is +equivalent to the p-norm with value `p = q/(q-1)`. They coincide at `p = q = 2`. The difference in norm between a vector space and its dual arises to preserve the relationship between duality and the inner product, and the result is @@ -613,7 +612,10 @@ julia> norm(v, Inf) 1.0 ``` """ -@inline norm(tv::RowVector, q::Real) = q == Inf ? norm(transpose(tv), 1) : norm(transpose(tv), q/(q-1)) +norm(v::TransposeAbsVec, q::Real) = q == Inf ? norm(v.parent, 1) : norm(v.parent, q/(q-1)) +norm(v::AdjointAbsVec, q::Real) = q == Inf ? norm(conj(v.parent), 1) : norm(conj(v.parent), q/(q-1)) +norm(v::AdjointAbsVec) = norm(conj(v.parent)) +norm(v::TransposeAbsVec) = norm(v.parent) function vecdot(x::AbstractArray, y::AbstractArray) lx = _length(x) diff --git a/base/linalg/givens.jl b/base/linalg/givens.jl index 27dc2a9979029..c00411603f0c5 100644 --- a/base/linalg/givens.jl +++ b/base/linalg/givens.jl @@ -379,7 +379,6 @@ end *(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Adjoint{<:Any,<:AbstractRotation}) = A.parent * B # dismabiguation methods: *(Diag/RowVec/AbsTri, Adj of AbstractRotation) *(A::Diagonal, B::Adjoint{<:Any,<:AbstractRotation}) = A * adjoint(B.parent) -*(A::RowVector, B::Adjoint{<:Any,<:AbstractRotation}) = A * adjoint(B.parent) *(A::AbstractTriangular, B::Adjoint{<:Any,<:AbstractRotation}) = A * adjoint(B.parent) # moar disambiguation mul!(A::QRPackedQ, B::Adjoint{<:Any,<:Givens}) = throw(MethodError(mul!, (A, B))) diff --git a/base/linalg/linalg.jl b/base/linalg/linalg.jl index c9ad1c6fbe2da..e1099557e492e 100644 --- a/base/linalg/linalg.jl +++ b/base/linalg/linalg.jl @@ -48,6 +48,8 @@ export BLAS, # Types + Adjoint, + Transpose, RowVector, ConjArray, ConjVector, diff --git a/base/linalg/qr.jl b/base/linalg/qr.jl index 0d9027d5ca0d9..916e6a29f30ec 100644 --- a/base/linalg/qr.jl +++ b/base/linalg/qr.jl @@ -720,7 +720,7 @@ function *(A::StridedMatrix, adjB::Adjoint{<:Any,<:AbstractQ}) throw(DimensionMismatch("matrix A has dimensions $(size(A)) but matrix B has dimensions $(size(B))")) end end -@inline *(rowvec::RowVector, adjB::Adjoint{<:Any,<:AbstractQ}) = (B = adjB.parent; adjoint(B*adjoint(rowvec))) +*(u::AdjointAbsVec, A::Adjoint{<:Any,<:AbstractQ}) = Adjoint(A.parent * u.parent) ### AcQ/AcQc diff --git a/base/linalg/rowvector.jl b/base/linalg/rowvector.jl index 6d228c3a7da6c..ff5f932c7c2e8 100644 --- a/base/linalg/rowvector.jl +++ b/base/linalg/rowvector.jl @@ -100,26 +100,38 @@ convert(::Type{RowVector{T,V}}, rowvec::RowVector) where {T,V<:AbstractVector} = @inline similar(rowvec::RowVector, ::Type{T}, dims::Dims{N}) where {T,N} = similar(parent(rowvec), T, dims) # Basic methods -""" - transpose(v::AbstractVector) - -The transposition operator (`.'`). - -# Examples -```jldoctest -julia> v = [1,2,3] -3-element Array{Int64,1}: - 1 - 2 - 3 -julia> transpose(v) -1×3 RowVector{Int64,Array{Int64,1}}: - 1 2 3 -``` -""" -@inline transpose(vec::AbstractVector) = RowVector(vec) -@inline adjoint(vec::AbstractVector) = RowVector(_conj(vec)) +# replaced in the Adjoint/Transpose transition +# """ +# transpose(v::AbstractVector) +# +# The transposition operator (`.'`). +# +# # Examples +# ```jldoctest +# julia> v = [1,2,3] +# 3-element Array{Int64,1}: +# 1 +# 2 +# 3 +# +# julia> transpose(v) +# 1×3 RowVector{Int64,Array{Int64,1}}: +# 1 2 3 +# ``` +# """ +# @inline transpose(vec::AbstractVector) = RowVector(vec) +# @inline adjoint(vec::AbstractVector) = RowVector(_conj(vec)) + +# methods necessary to preserve RowVector's behavior through the Adjoint/Transpose transition +rvadjoint(v::AbstractVector) = RowVector(_conj(v)) +rvtranspose(v::AbstractVector) = RowVector(v) +rvadjoint(v::RowVector) = conj(v.vec) +rvadjoint(v::RowVector{<:Real}) = v.vec +rvtranspose(v::RowVector) = v.vec +rvtranspose(v::ConjRowVector) = copy(v.vec) +rvadjoint(x) = adjoint(x) +rvtranspose(x) = transpose(x) @inline transpose(rowvec::RowVector) = rowvec.vec @inline transpose(rowvec::ConjRowVector) = copy(rowvec.vec) # remove the ConjArray wrapper from any raw vector @@ -157,22 +169,22 @@ julia> conj(v) IndexStyle(::RowVector) = IndexLinear() IndexStyle(::Type{<:RowVector}) = IndexLinear() -@propagate_inbounds getindex(rowvec::RowVector, i::Int) = transpose(rowvec.vec[i]) -@propagate_inbounds setindex!(rowvec::RowVector, v, i::Int) = (setindex!(rowvec.vec, transpose(v), i); rowvec) +@propagate_inbounds getindex(rowvec::RowVector, i::Int) = rvtranspose(rowvec.vec[i]) +@propagate_inbounds setindex!(rowvec::RowVector, v, i::Int) = (setindex!(rowvec.vec, rvtranspose(v), i); rowvec) # Keep a RowVector where appropriate -@propagate_inbounds getindex(rowvec::RowVector, ::Colon, i::Int) = transpose.(rowvec.vec[i:i]) +@propagate_inbounds getindex(rowvec::RowVector, ::Colon, i::Int) = rvtranspose.(rowvec.vec[i:i]) @propagate_inbounds getindex(rowvec::RowVector, ::Colon, inds::AbstractArray{Int}) = RowVector(rowvec.vec[inds]) @propagate_inbounds getindex(rowvec::RowVector, ::Colon, ::Colon) = RowVector(rowvec.vec[:]) # helper function for below -@inline to_vec(rowvec::RowVector) = map(transpose, transpose(rowvec)) +@inline to_vec(rowvec::RowVector) = map(rvtranspose, rvtranspose(rowvec)) @inline to_vec(x::Number) = x @inline to_vecs(rowvecs...) = (map(to_vec, rowvecs)...,) # map: Preserve the RowVector by un-wrapping and re-wrapping, but note that `f` # expects to operate within the transposed domain, so to_vec transposes the elements -@inline map(f, rowvecs::RowVector...) = RowVector(map(transpose∘f, to_vecs(rowvecs...)...)) +@inline map(f, rowvecs::RowVector...) = RowVector(map(rvtranspose∘f, to_vecs(rowvecs...)...)) # broacast (other combinations default to higher-dimensional array) @inline broadcast(f, rowvecs::Union{Number,RowVector}...) = @@ -180,13 +192,13 @@ IndexStyle(::Type{<:RowVector}) = IndexLinear() # Horizontal concatenation # -@inline hcat(X::RowVector...) = transpose(vcat(map(transpose, X)...)) -@inline hcat(X::Union{RowVector,Number}...) = transpose(vcat(map(transpose, X)...)) +@inline hcat(X::RowVector...) = rvtranspose(vcat(map(rvtranspose, X)...)) +@inline hcat(X::Union{RowVector,Number}...) = rvtranspose(vcat(map(rvtranspose, X)...)) @inline typed_hcat(::Type{T}, X::RowVector...) where {T} = - transpose(typed_vcat(T, map(transpose, X)...)) + rvtranspose(typed_vcat(T, map(rvtranspose, X)...)) @inline typed_hcat(::Type{T}, X::Union{RowVector,Number}...) where {T} = - transpose(typed_vcat(T, map(transpose, X)...)) + rvtranspose(typed_vcat(T, map(rvtranspose, X)...)) # Multiplication # @@ -202,7 +214,7 @@ IndexStyle(::Type{<:RowVector}) = IndexLinear() end sum(@inbounds(return rowvec[i]*vec[i]) for i = 1:length(vec)) end -@inline *(rowvec::RowVector, mat::AbstractMatrix) = transpose(mat.' * transpose(rowvec)) +@inline *(rowvec::RowVector, mat::AbstractMatrix) = rvtranspose(mat.' * rvtranspose(rowvec)) *(::RowVector, ::RowVector) = throw(DimensionMismatch("Cannot multiply two transposed vectors")) @inline *(vec::AbstractVector, rowvec::RowVector) = vec .* rowvec *(vec::AbstractVector, rowvec::AbstractVector) = throw(DimensionMismatch("Cannot multiply two vectors")) @@ -211,77 +223,57 @@ end *(::RowVector, ::Transpose{<:Any,<:AbstractVector}) = throw(DimensionMismatch("Cannot multiply two transposed vectors")) *(rowvec::RowVector, transmat::Transpose{<:Any,<:AbstractMatrix}) = - (mat = transmat.parent; transpose(mat * transpose(rowvec))) + (mat = transmat.parent; rvtranspose(mat * rvtranspose(rowvec))) *(rowvec1::RowVector, transrowvec2::Transpose{<:Any,<:RowVector}) = - (rowvec2 = transrowvec2.parent; rowvec1*transpose(rowvec2)) + (rowvec2 = transrowvec2.parent; rowvec1*rvtranspose(rowvec2)) *(::AbstractVector, ::Transpose{<:Any,<:RowVector}) = throw(DimensionMismatch("Cannot multiply two vectors")) -*(vec1::AbstractVector, transvec2::Transpose{<:Any,<:AbstractVector}) = - (vec2 = transvec2.parent; vec1 * transpose(vec2)) *(mat::AbstractMatrix, transrowvec::Transpose{<:Any,<:RowVector}) = - (rowvec = transrowvec.parent; mat * transpose(rowvec)) + (rowvec = transrowvec.parent; mat * rvtranspose(rowvec)) *(transrowvec::Transpose{<:Any,<:RowVector}, transvec::Transpose{<:Any,<:AbstractVector}) = - transpose(transrowvec.parent) * transpose(transvec.parent) -*(transvec::Transpose{<:Any,<:AbstractVector}, transmat::Transpose{<:Any,<:AbstractMatrix}) = - transpose(transmat.parent * transvec.parent) + rvtranspose(transrowvec.parent) * transpose(transvec.parent) *(transrowvec1::Transpose{<:Any,<:RowVector}, transrowvec2::Transpose{<:Any,<:RowVector}) = throw(DimensionMismatch("Cannot multiply two vectors")) *(transvec::Transpose{<:Any,<:AbstractVector}, transrowvec::Transpose{<:Any,<:RowVector}) = - transpose(transvec.parent)*transpose(transrowvec.parent) -*(transvec::Transpose{<:Any,<:AbstractVector}, transrowvec::Transpose{<:Any,<:AbstractVector}) = - throw(DimensionMismatch("Cannot multiply two transposed vectors")) + transpose(transvec.parent)*rvtranspose(transrowvec.parent) *(transmat::Transpose{<:Any,<:AbstractMatrix}, transrowvec::Transpose{<:Any,<:RowVector}) = - (transmat.parent).' * transpose(transrowvec.parent) + (transmat.parent).' * rvtranspose(transrowvec.parent) *(::Transpose{<:Any,<:RowVector}, ::AbstractVector) = throw(DimensionMismatch("Cannot multiply two vectors")) -*(transvec::Transpose{<:Any,<:AbstractVector}, mat::AbstractMatrix) = - transpose(*(Transpose(mat), transvec.parent)) *(transrowvec1::Transpose{<:Any,<:RowVector}, rowvec2::RowVector) = - transpose(transrowvec1.parent) * rowvec2 + rvtranspose(transrowvec1.parent) * rowvec2 *(transvec::Transpose{<:Any,<:AbstractVector}, rowvec::RowVector) = throw(DimensionMismatch("Cannot multiply two transposed vectors")) -*(transvec1::Transpose{<:Any,<:AbstractVector{T}}, vec2::AbstractVector{T}) where {T<:Real} = - reduce(+, map(*, transvec1.parent, vec2)) # Seems to be overloaded... -*(transvec1::Transpose{<:Any,<:AbstractVector}, vec2::AbstractVector) = - transpose(transvec1.parent) * vec2 # Conjugated forms *(::RowVector, ::Adjoint{<:Any,<:AbstractVector}) = throw(DimensionMismatch("Cannot multiply two transposed vectors")) *(rowvec::RowVector, adjmat::Adjoint{<:Any,<:AbstractMatrix}) = - adjoint(adjmat.parent * adjoint(rowvec)) + rvadjoint(adjmat.parent * rvadjoint(rowvec)) *(rowvec1::RowVector, adjrowvec2::Adjoint{<:Any,<:RowVector}) = - rowvec1 * adjoint(adjrowvec2.parent) + rowvec1 * rvadjoint(adjrowvec2.parent) *(vec::AbstractVector, adjrowvec::Adjoint{<:Any,<:RowVector}) = throw(DimensionMismatch("Cannot multiply two vectors")) -*(vec1::AbstractVector, adjvec2::Adjoint{<:Any,<:AbstractVector}) = - vec1 * adjoint(adjvec2.parent) *(mat::AbstractMatrix, adjrowvec::Adjoint{<:Any,<:RowVector}) = - mat * adjoint(adjrowvec.parent) + mat * rvadjoint(adjrowvec.parent) *(adjrowvec::Adjoint{<:Any,<:RowVector}, adjvec::Adjoint{<:Any,<:AbstractVector}) = - adjoint(adjrowvec.parent) * adjoint(adjvec.parent) -*(adjvec::Adjoint{<:Any,<:AbstractVector}, adjmat::Adjoint{<:Any,<:AbstractMatrix}) = - adjoint(adjmat.parent * adjvec.parent) + rvadjoint(adjrowvec.parent) * adjoint(adjvec.parent) *(adjrowvec1::Adjoint{<:Any,<:RowVector}, adjrowvec2::Adjoint{<:Any,<:RowVector}) = throw(DimensionMismatch("Cannot multiply two vectors")) *(adjvec::Adjoint{<:Any,<:AbstractVector}, adjrowvec::Adjoint{<:Any,<:RowVector}) = - adjoint(adjvec.parent)*adjoint(adjrowvec.parent) -*(adjvec::Adjoint{<:Any,<:AbstractVector}, adjrowvec::Adjoint{<:Any,<:AbstractVector}) = - throw(DimensionMismatch("Cannot multiply two transposed vectors")) + adjoint(adjvec.parent)*rvadjoint(adjrowvec.parent) *(adjmat::Adjoint{<:Any,<:AbstractMatrix}, adjrowvec::Adjoint{<:Any,<:RowVector}) = - (adjmat.parent)' * adjoint(adjrowvec.parent) + (adjmat.parent)' * rvadjoint(adjrowvec.parent) *(::Adjoint{<:Any,<:RowVector}, ::AbstractVector) = throw(DimensionMismatch("Cannot multiply two vectors")) -*(adjvec::Adjoint{<:Any,<:AbstractVector}, mat::AbstractMatrix) = adjoint(*(Adjoint(mat), adjvec.parent)) -*(adjrowvec1::Adjoint{<:Any,<:RowVector}, rowvec2::RowVector) = adjoint(adjrowvec1.parent) * rowvec2 +*(adjrowvec1::Adjoint{<:Any,<:RowVector}, rowvec2::RowVector) = rvadjoint(adjrowvec1.parent) * rowvec2 *(adjvec::Adjoint{<:Any,<:AbstractVector}, rowvec::RowVector) = throw(DimensionMismatch("Cannot multiply two transposed vectors")) -*(adjvec1::Adjoint{<:Any,<:AbstractVector}, vec2::AbstractVector) = adjoint(adjvec1.parent)*vec2 # Pseudo-inverse -pinv(v::RowVector, tol::Real=0) = pinv(v', tol)' +pinv(v::RowVector, tol::Real=0) = rvadjoint(pinv(rvadjoint(v), tol)) # Left Division # @@ -294,19 +286,19 @@ pinv(v::RowVector, tol::Real=0) = pinv(v', tol)' # Right Division # -@inline /(rowvec::RowVector, mat::AbstractMatrix) = transpose(transpose(mat) \ transpose(rowvec)) -/(rowvec::RowVector, transmat::Transpose{<:Any,<:AbstractMatrix}) = transpose(transmat.parent \ transpose(rowvec)) -/(rowvec::RowVector, adjmat::Adjoint{<:Any,<:AbstractMatrix}) = adjoint(adjmat.parent \ adjoint(rowvec)) +@inline /(rowvec::RowVector, mat::AbstractMatrix) = rvtranspose(transpose(mat) \ rvtranspose(rowvec)) +/(rowvec::RowVector, transmat::Transpose{<:Any,<:AbstractMatrix}) = rvtranspose(transmat.parent \ rvtranspose(rowvec)) +/(rowvec::RowVector, adjmat::Adjoint{<:Any,<:AbstractMatrix}) = rvadjoint(adjmat.parent \ rvadjoint(rowvec)) # definitions necessary for test/linalg/dense.jl to pass # should be cleaned up / revised as necessary in the future -/(A::Number, B::Adjoint{<:Any,<:RowVector}) = /(A, adjoint(B.parent)) -/(A::Matrix, B::RowVector) = adjoint(adjoint(B) \ adjoint(A)) +/(A::Number, B::Adjoint{<:Any,<:RowVector}) = /(A, rvadjoint(B.parent)) +/(A::Matrix, B::RowVector) = rvadjoint(rvadjoint(B) \ adjoint(A)) # dismabiguation methods *(A::Adjoint{<:Any,<:AbstractVector}, B::Transpose{<:Any,<:RowVector}) = adjoint(A.parent) * B -*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:RowVector}) = A * transpose(B.parent) +*(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:RowVector}) = A * rvtranspose(B.parent) *(A::Transpose{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:RowVector}) = transpose(A.parent) * B -*(A::Transpose{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:RowVector}) = A * adjoint(B.parent) +*(A::Transpose{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:RowVector}) = A * rvadjoint(B.parent) diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index f3f11abfd3e09..d69135729c525 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -339,9 +339,6 @@ mul!(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Hermitian{T,<:StridedMatrix}) *(adjA::Adjoint{<:Any,<:RealHermSymComplexSym}, adjB::Adjoint{<:Any,<:RealHermSymComplexHerm}) = adjA * adjB.parent *(adjA::Adjoint{<:Any,<:RealHermSymComplexHerm}, adjB::Adjoint{<:Any,<:RealHermSymComplexSym}) = adjA.parent * adjB -# ambiguities with RowVector -*(A::RowVector, transB::Transpose{<:Any,<:RealHermSymComplexSym}) = A * transB.parent -*(A::RowVector, adjB::Adjoint{<:Any,<:RealHermSymComplexHerm}) = A * adjB.parent # ambiguities with AbstractTriangular *(transA::Transpose{<:Any,<:RealHermSymComplexSym}, B::AbstractTriangular) = transA.parent * B *(A::AbstractTriangular, transB::Transpose{<:Any,<:RealHermSymComplexSym}) = A * transB.parent @@ -372,8 +369,6 @@ det(A::Symmetric) = det(factorize(A)) # Bunch-Kaufman solves can not utilize BLAS-3 for multiple right hand sides # so using LU is faster for AbstractMatrix right hand side \(A::HermOrSym{<:Any,<:StridedMatrix}, B::AbstractMatrix) = \(lufact(A), B) -# ambiguity with RowVector -\(A::HermOrSym{<:Any,<:StridedMatrix}, B::RowVector) = invoke(\, Tuple{AbstractMatrix, RowVector}, A, B) function _inv(A::HermOrSym) n = checksquare(A) @@ -759,11 +754,6 @@ end *(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Adjoint{<:Any,<:AbstractMatrix}) = A.parent * B *(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Transpose{<:Any,<:AbstractVector}) = A.parent * B *(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Transpose{<:Any,<:AbstractMatrix}) = A.parent * B -# dismabiguation methods: *(Adj/Trans of RealHermSymComplex{Herm|Sym}, Adj/Trans of RowVector) -*(A::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::Adjoint{<:Any,<:RowVector}) = A.parent * B -*(A::Adjoint{<:Any,<:RealHermSymComplexHerm}, B::Transpose{<:Any,<:RowVector}) = A.parent * B -*(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Adjoint{<:Any,<:RowVector}) = A.parent * B -*(A::Transpose{<:Any,<:RealHermSymComplexSym}, B::Transpose{<:Any,<:RowVector}) = A.parent * B # dismabiguation methods: *(Adj/Trans of AbsTri or RealHermSymComplex{Herm|Sym}, Adj/Trans of other) *(A::Adjoint{<:Any,<:AbstractTriangular}, B::Adjoint{<:Any,<:RealHermSymComplexHerm}) = A * B.parent diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index b1472887ca1b9..da121e1862f65 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -1839,10 +1839,10 @@ function *(A::AbstractMatrix, transB::Transpose{<:Any,<:AbstractTriangular}) mul!(AA, Transpose(convert(AbstractArray{TAB}, B))) end # ambiguity resolution with definitions in linalg/rowvector.jl -*(transA::Transpose{<:Any,<:AbstractVector}, B::AbstractTriangular) = *(transpose(transA.parent), B) -*(adjA::Adjoint{<:Any,<:AbstractVector}, B::AbstractTriangular) = *(adjoint(adjA.parent), B) -*(transA::Transpose{<:Any,<:AbstractVector}, transB::Transpose{<:Any,<:AbstractTriangular}) = *(transpose(transA.parent), transB) -*(adjA::Adjoint{<:Any,<:AbstractVector}, adjB::Adjoint{<:Any,<:AbstractTriangular}) = *(adjoint(adjA.parent), adjB) +*(v::AdjointAbsVec, A::AbstractTriangular) = Adjoint(Adjoint(A) * v.parent) +*(v::TransposeAbsVec, A::AbstractTriangular) = Transpose(Transpose(A) * v.parent) +*(v::AdjointAbsVec, A::Adjoint{<:Any,<:AbstractTriangular}) = Adjoint(A.parent * v.parent) +*(v::TransposeAbsVec, A::Transpose{<:Any,<:AbstractTriangular}) = Transpose(A.parent * v.parent) # If these are not defined, they will fallback to the versions in matmul.jl @@ -1861,42 +1861,6 @@ end *(transA::Transpose{<:Any,<:AbstractTriangular}, transB::Transpose{<:Any,<:AbstractMatrix}) = *(transA, transpose(transB.parent)) *(transA::Transpose{<:Any,<:AbstractMatrix}, transB::Transpose{<:Any,<:AbstractTriangular}) = *(transpose(transA.parent), transB) -# Specializations for RowVector -*(rowvec::RowVector, A::AbstractTriangular) = transpose(transpose(A) * transpose(rowvec)) -*(rowvec::RowVector, transA::Transpose{<:Any,<:AbstractTriangular}) = transpose(transA.parent * transpose(rowvec)) -*(A::AbstractTriangular, transrowvec::Transpose{<:Any,<:RowVector}) = A * transpose(transrowvec.parent) -*(transA::Transpose{<:Any,<:AbstractTriangular}, transrowvec::Transpose{<:Any,<:RowVector}) = transA.parent.' * transpose(transrowvec.parent) -*(rowvec::RowVector, adjA::Adjoint{<:Any,<:AbstractTriangular}) = adjoint(adjA.parent * adjoint(rowvec)) -*(A::AbstractTriangular, adjrowvec::Adjoint{<:Any,<:RowVector}) = A * adjoint(adjrowvec.parent) -*(adjA::Adjoint{<:Any,<:AbstractTriangular}, adjrowvec::Adjoint{<:Any,<:RowVector}) = adjA.parent' * adjoint(adjrowvec.parent) - -@inline /(rowvec::RowVector, A::Union{UpperTriangular,LowerTriangular}) = transpose(transpose(A) \ transpose(rowvec)) -@inline /(rowvec::RowVector, A::Union{UnitUpperTriangular,UnitLowerTriangular}) = transpose(transpose(A) \ transpose(rowvec)) - -/(rowvec::RowVector, transA::Transpose{<:Any,<:Union{UpperTriangular,LowerTriangular}}) = - transpose(transA.parent \ transpose(rowvec)) -/(rowvec::RowVector, transA::Transpose{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}) = - transpose(transA.parent \ transpose(rowvec)) -# ambiguity resolution with definitions in linalg/rowvector.jl -/(rowvec::RowVector, adjA::Adjoint{<:Any,<:Union{UpperTriangular,LowerTriangular}}) = - /(rowvec, adjoint(adjA.parent)) -/(rowvec::RowVector, adjA::Adjoint{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}) = - /(rowvec, adjoint(adjA.parent)) - -rdiv(rowvec::RowVector, adjA::Adjoint{<:Any,<:Union{UpperTriangular,LowerTriangular}}) = - adjoint(adjA.parent \ adjoint(rowvec)) -rdiv(rowvec::RowVector, adjA::Adjoint{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}) = - adjoint(adjA.parent \ adjoint(rowvec)) - -\(::Union{UpperTriangular,LowerTriangular}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) -\(::Union{UnitUpperTriangular,UnitLowerTriangular}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) - -\(::Transpose{<:Any,<:Union{UpperTriangular,LowerTriangular}}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) -\(::Transpose{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) - -\(::Adjoint{<:Any,<:Union{UpperTriangular,LowerTriangular}}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) -\(::Adjoint{<:Any,<:Union{UnitUpperTriangular,UnitLowerTriangular}}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) - # Complex matrix power for upper triangular factor, see: # Higham and Lin, "A Schur-Padé algorithm for fractional powers of a Matrix", # SIAM J. Matrix Anal. & Appl., 32 (3), (2011) 1056–1078. @@ -2417,6 +2381,20 @@ factorize(A::AbstractTriangular) = A *(A::Adjoint{<:Any,<:AbstractMatrix}, B::Transpose{<:Any,<:AbstractTriangular}) = adjoint(A.parent) * B *(A::Transpose{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:AbstractTriangular}) = transpose(A.parent) * B *(A::Transpose{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:AbstractTriangular}) = transpose(A.parent) * B -# dismabiguation methods: *(Adj/Trans of AbstractTriangular, Trans/Adj of RowVector) -*(A::Adjoint{<:Any,<:AbstractTriangular}, B::Transpose{<:Any,<:RowVector}) = A * transpose(B.parent) -*(A::Transpose{<:Any,<:AbstractTriangular}, B::Adjoint{<:Any,<:RowVector}) = A * adjoint(B.parent) + +# disambiguation methods: /(Adjoint of AbsVec, <:AbstractTriangular) +/(u::AdjointAbsVec, A::Union{LowerTriangular,UpperTriangular}) = Adjoint(Adjoint(A) \ u.parent) +/(u::AdjointAbsVec, A::Union{UnitLowerTriangular,UnitUpperTriangular}) = Adjoint(Adjoint(A) \ u.parent) +# disambiguation methods: /(Adjoint of AbsVec, Adj/Trans of <:AbstractTriangular) +/(u::AdjointAbsVec, A::Adjoint{<:Any,<:Union{LowerTriangular,UpperTriangular}}) = Adjoint(A.parent \ u.parent) +/(u::AdjointAbsVec, A::Adjoint{<:Any,<:Union{UnitLowerTriangular,UnitUpperTriangular}}) = Adjoint(A.parent \ u.parent) +/(u::AdjointAbsVec, A::Transpose{<:Any,<:Union{LowerTriangular,UpperTriangular}}) = Adjoint(conj(A.parent) \ u.parent) +/(u::AdjointAbsVec, A::Transpose{<:Any,<:Union{UnitLowerTriangular,UnitUpperTriangular}}) = Adjoint(conj(A.parent) \ u.parent) +# disambiguation methods: /(Transpose of AbsVec, <:AbstractTriangular) +/(u::TransposeAbsVec, A::Union{LowerTriangular,UpperTriangular}) = Transpose(Transpose(A) \ u.parent) +/(u::TransposeAbsVec, A::Union{UnitLowerTriangular,UnitUpperTriangular}) = Transpose(Transpose(A) \ u.parent) +# disambiguation methods: /(Transpose of AbsVec, Adj/Trans of <:AbstractTriangular) +/(u::TransposeAbsVec, A::Adjoint{<:Any,<:Union{LowerTriangular,UpperTriangular}}) = Transpose(conj(A.parent) \ u.parent) +/(u::TransposeAbsVec, A::Adjoint{<:Any,<:Union{UnitLowerTriangular,UnitUpperTriangular}}) = Transpose(conj(A.parent) \ u.parent) +/(u::TransposeAbsVec, A::Transpose{<:Any,<:Union{LowerTriangular,UpperTriangular}}) = Transpose(A.parent \ u.parent) +/(u::TransposeAbsVec, A::Transpose{<:Any,<:Union{UnitLowerTriangular,UnitUpperTriangular}}) = Transpose(A.parent \ u.parent) diff --git a/base/sparse/higherorderfns.jl b/base/sparse/higherorderfns.jl index 3b4b3744b60bb..eb58e93cf7e11 100644 --- a/base/sparse/higherorderfns.jl +++ b/base/sparse/higherorderfns.jl @@ -993,7 +993,8 @@ Broadcast.BroadcastStyle(::PromoteToSparse, ::Broadcast.Style{Tuple}) = Broadcas # Broadcast.BroadcastStyle(::SPVM, ::Broadcast.DefaultArrayStyle{0}) = PromoteToSparse() # Broadcast.BroadcastStyle(::SPVM, ::Broadcast.DefaultArrayStyle{1}) = PromoteToSparse() # Broadcast.BroadcastStyle(::SPVM, ::Broadcast.DefaultArrayStyle{2}) = PromoteToSparse() -BroadcastStyle(::Type{<:Base.RowVector{T,<:Vector}}) where T = Broadcast.MatrixStyle() # RowVector not yet defined when broadcast.jl loaded +BroadcastStyle(::Type{<:Base.Adjoint{T,<:Vector}}) where T = Broadcast.MatrixStyle() # Adjoint not yet defined when broadcast.jl loaded +BroadcastStyle(::Type{<:Base.Transpose{T,<:Vector}}) where T = Broadcast.MatrixStyle() # Transpose not yet defined when broadcast.jl loaded Broadcast.BroadcastStyle(::SPVM, ::Broadcast.VectorStyle) = PromoteToSparse() Broadcast.BroadcastStyle(::SPVM, ::Broadcast.MatrixStyle) = PromoteToSparse() Broadcast.BroadcastStyle(::SparseVecStyle, ::Broadcast.DefaultArrayStyle{N}) where N = diff --git a/base/sparse/linalg.jl b/base/sparse/linalg.jl index 59ca7d455ee67..d34d34630214e 100644 --- a/base/sparse/linalg.jl +++ b/base/sparse/linalg.jl @@ -941,7 +941,6 @@ function \(A::SparseMatrixCSC, B::AbstractVecOrMat) return \(qrfact(A), B) end end -\(::SparseMatrixCSC, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) for xform in (:Adjoint, :Transpose) @eval begin function \(xformA::($xform){<:Any,<:SparseMatrixCSC}, B::AbstractVecOrMat) @@ -965,7 +964,6 @@ for xform in (:Adjoint, :Transpose) return \($xform(qrfact(A)), B) end end - \(::($xform){<:Any,<:SparseMatrixCSC}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) end end diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index 110a63c991292..caad68dcc5b53 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -992,7 +992,7 @@ vcat(X::Union{Vector,SparseVector}...) = vcat(map(sparse, X)...) # TODO: A definition similar to the third exists in base/linalg/bidiag.jl. These definitions # should be consolidated in a more appropriate location, e.g. base/linalg/special.jl. -const _SparseArrays = Union{SparseVector, SparseMatrixCSC, RowVector{<:Any, <:SparseVector}} +const _SparseArrays = Union{SparseVector, SparseMatrixCSC, RowVector{<:Any,<:SparseVector}, Adjoint{<:Any,<:SparseVector}, Transpose{<:Any,<:SparseVector}} const _SpecialArrays = Union{Diagonal, Bidiagonal, Tridiagonal, SymTridiagonal} const _SparseConcatArrays = Union{_SpecialArrays, _SparseArrays} @@ -1007,9 +1007,9 @@ const _Triangular_DenseArrays{T,A<:Matrix} = Base.LinAlg.AbstractTriangular{T,A} const _Annotated_DenseArrays = Union{_Triangular_DenseArrays, _Symmetric_DenseArrays, _Hermitian_DenseArrays} const _Annotated_Typed_DenseArrays{T} = Union{_Triangular_DenseArrays{T}, _Symmetric_DenseArrays{T}, _Hermitian_DenseArrays{T}} -const _SparseConcatGroup = Union{Vector, RowVector{<:Any, <:Vector}, Matrix, _SparseConcatArrays, _Annotated_SparseConcatArrays, _Annotated_DenseArrays} -const _DenseConcatGroup = Union{Vector, RowVector{<:Any, <:Vector}, Matrix, _Annotated_DenseArrays} -const _TypedDenseConcatGroup{T} = Union{Vector{T}, RowVector{T,Vector{T}}, Matrix{T}, _Annotated_Typed_DenseArrays{T}} +const _SparseConcatGroup = Union{Vector, Adjoint{<:Any,<:Vector}, Transpose{<:Any,<:Vector}, RowVector{<:Any,<:Vector}, Matrix, _SparseConcatArrays, _Annotated_SparseConcatArrays, _Annotated_DenseArrays} +const _DenseConcatGroup = Union{Vector, Adjoint{<:Any,<:Vector}, Transpose{<:Any,<:Vector}, RowVector{<:Any, <:Vector}, Matrix, _Annotated_DenseArrays} +const _TypedDenseConcatGroup{T} = Union{Vector{T}, Adjoint{T,Vector{T}}, Transpose{T,Vector{T}}, RowVector{T,Vector{T}}, Matrix{T}, _Annotated_Typed_DenseArrays{T}} # Concatenations involving un/annotated sparse/special matrices/vectors should yield sparse arrays function cat(catdims, Xin::_SparseConcatGroup...) @@ -1437,8 +1437,8 @@ vecnorm(x::SparseVectorUnion, p::Real=2) = vecnorm(nonzeros(x), p) # Transpose # (The only sparse matrix structure in base is CSC, so a one-row sparse matrix is worse than dense) -@inline transpose(sv::SparseVector) = RowVector(sv) -@inline adjoint(sv::SparseVector) = RowVector(conj(sv)) +transpose(sv::SparseVector) = Transpose(sv) +adjoint(sv::SparseVector) = Adjoint(sv) ### BLAS Level-1 diff --git a/test/arrayops.jl b/test/arrayops.jl index f26192f2f8bde..e8dabcd11795c 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -2048,9 +2048,9 @@ end # module AutoRetType @test isa(cat((1,2), densearray, densearray), Array) end @test isa([[1,2,3]'; [1,2,3]'], Matrix{Int}) - @test isa([[1,2,3]' [1,2,3]'], RowVector{Int, Vector{Int}}) + @test isa([[1,2,3]' [1,2,3]'], Transpose{Int, Vector{Int}}) @test isa([Any[1.0, 2]'; Any[2.0, 2]'], Matrix{Any}) - @test isa([Any[1.0, 2]' Any[2.0, 2']'], RowVector{Any, Vector{Any}}) + @test isa([Any[1.0, 2]' Any[2.0, 2']'], Adjoint{Any, Vector{Any}}) # Test that concatenations of heterogeneous Matrix-Vector pairs yield dense matrices @test isa(hcat(densemat, densevec), Array) @test isa(hcat(densevec, densemat), Array) diff --git a/test/bitarray.jl b/test/bitarray.jl index 366e37d9f15b7..df21aed3a4445 100644 --- a/test/bitarray.jl +++ b/test/bitarray.jl @@ -4,7 +4,7 @@ using Base: findprevnot, findnextnot tc(r1::NTuple{N,Any}, r2::NTuple{N,Any}) where {N} = all(x->tc(x...), [zip(r1,r2)...]) tc(r1::BitArray{N}, r2::Union{BitArray{N},Array{Bool,N}}) where {N} = true -tc(r1::RowVector{Bool,BitVector}, r2::Union{RowVector{Bool,BitVector},RowVector{Bool,Vector{Bool}}}) = true +tc(r1::Transpose{Bool,BitVector}, r2::Union{Transpose{Bool,BitVector},Transpose{Bool,Vector{Bool}}}) = true tc(r1::T, r2::T) where {T} = true tc(r1,r2) = false @@ -1308,7 +1308,7 @@ end @testset "Transpose" begin b1 = bitrand(v1) - @check_bit_operation transpose(b1) RowVector{Bool,BitVector} + @check_bit_operation transpose(b1) Transpose{Bool,BitVector} for m1 = 0:n1, m2 = 0:n2 b1 = bitrand(m1, m2) diff --git a/test/linalg/adjtrans.jl b/test/linalg/adjtrans.jl index 0439e8a7ecd0a..3aa71e1ca9c8b 100644 --- a/test/linalg/adjtrans.jl +++ b/test/linalg/adjtrans.jl @@ -286,3 +286,147 @@ end @test vec(Adjoint(intvec)) === intvec @test vec(Transpose(intvec)) === intvec end + +@testset "horizontal concatenation of Adjoint/Transpose-wrapped vectors and Numbers" begin + # horizontal concatenation of Adjoint/Transpose-wrapped vectors and Numbers + # should preserve the Adjoint/Transpose-wrapper to preserve semantics downstream + vec, tvec, avec = [1im, 2im], [1im 2im], [-1im -2im] + vecvec = [[1im, 2im], [3im, 4im]] + tvecvec = [[[1im 2im]] [[3im 4im]]] + avecvec = [[[-1im -2im]] [[-3im -4im]]] + # for arrays with concrete scalar eltype + @test hcat(Adjoint(vec), Adjoint(vec))::Adjoint{Complex{Int},Vector{Complex{Int}}} == hcat(avec, avec) + @test hcat(Adjoint(vec), 1, Adjoint(vec))::Adjoint{Complex{Int},Vector{Complex{Int}}} == hcat(avec, 1, avec) + @test hcat(Transpose(vec), Transpose(vec))::Transpose{Complex{Int},Vector{Complex{Int}}} == hcat(tvec, tvec) + @test hcat(Transpose(vec), 1, Transpose(vec))::Transpose{Complex{Int},Vector{Complex{Int}}} == hcat(tvec, 1, tvec) + # for arrays with concrete array eltype + @test hcat(Adjoint(vecvec), Adjoint(vecvec))::Adjoint{Adjoint{Complex{Int},Vector{Complex{Int}}},Vector{Vector{Complex{Int}}}} == hcat(avecvec, avecvec) + @test hcat(Transpose(vecvec), Transpose(vecvec))::Transpose{Transpose{Complex{Int},Vector{Complex{Int}}},Vector{Vector{Complex{Int}}}} == hcat(tvecvec, tvecvec) +end + +@testset "map/broadcast over Adjoint/Transpose-wrapped vectors and Numbers" begin + # map and broadcast over Adjoint/Transpose-wrapped vectors and Numbers + # should preserve the Adjoint/Transpose-wrapper to preserve semantics downstream + vec, tvec, avec = [1im, 2im], [1im 2im], [-1im -2im] + vecvec = [[1im, 2im], [3im, 4im]] + tvecvec = [[[1im 2im]] [[3im 4im]]] + avecvec = [[[-1im -2im]] [[-3im -4im]]] + # unary map over wrapped vectors with concrete scalar eltype + @test map(-, Adjoint(vec))::Adjoint{Complex{Int},Vector{Complex{Int}}} == -avec + @test map(-, Transpose(vec))::Transpose{Complex{Int},Vector{Complex{Int}}} == -tvec + # unary map over wrapped vectors with concrete array eltype + @test map(-, Adjoint(vecvec))::Adjoint{Adjoint{Complex{Int},Vector{Complex{Int}}},Vector{Vector{Complex{Int}}}} == -avecvec + @test map(-, Transpose(vecvec))::Transpose{Transpose{Complex{Int},Vector{Complex{Int}}},Vector{Vector{Complex{Int}}}} == -tvecvec + # binary map over wrapped vectors with concrete scalar eltype + @test map(+, Adjoint(vec), Adjoint(vec))::Adjoint{Complex{Int},Vector{Complex{Int}}} == avec + avec + @test map(+, Transpose(vec), Transpose(vec))::Transpose{Complex{Int},Vector{Complex{Int}}} == tvec + tvec + # binary map over wrapped vectors with concrete array eltype + @test map(+, Adjoint(vecvec), Adjoint(vecvec))::Adjoint{Adjoint{Complex{Int},Vector{Complex{Int}}},Vector{Vector{Complex{Int}}}} == avecvec + avecvec + @test map(+, Transpose(vecvec), Transpose(vecvec))::Transpose{Transpose{Complex{Int},Vector{Complex{Int}}},Vector{Vector{Complex{Int}}}} == tvecvec + tvecvec + # unary broadcast over wrapped vectors with concrete scalar eltype + @test broadcast(-, Adjoint(vec))::Adjoint{Complex{Int},Vector{Complex{Int}}} == -avec + @test broadcast(-, Transpose(vec))::Transpose{Complex{Int},Vector{Complex{Int}}} == -tvec + # unary broadcast over wrapped vectors with concrete array eltype + @test broadcast(-, Adjoint(vecvec))::Adjoint{Adjoint{Complex{Int},Vector{Complex{Int}}},Vector{Vector{Complex{Int}}}} == -avecvec + @test broadcast(-, Transpose(vecvec))::Transpose{Transpose{Complex{Int},Vector{Complex{Int}}},Vector{Vector{Complex{Int}}}} == -tvecvec + # binary broadcast over wrapped vectors with concrete scalar eltype + @test broadcast(+, Adjoint(vec), Adjoint(vec))::Adjoint{Complex{Int},Vector{Complex{Int}}} == avec + avec + @test broadcast(+, Transpose(vec), Transpose(vec))::Transpose{Complex{Int},Vector{Complex{Int}}} == tvec + tvec + # binary broadcast over wrapped vectors with concrete array eltype + @test broadcast(+, Adjoint(vecvec), Adjoint(vecvec))::Adjoint{Adjoint{Complex{Int},Vector{Complex{Int}}},Vector{Vector{Complex{Int}}}} == avecvec + avecvec + @test broadcast(+, Transpose(vecvec), Transpose(vecvec))::Transpose{Transpose{Complex{Int},Vector{Complex{Int}}},Vector{Vector{Complex{Int}}}} == tvecvec + tvecvec + # trinary broadcast over wrapped vectors with concrete scalar eltype and numbers + @test broadcast(+, Adjoint(vec), 1, Adjoint(vec))::Adjoint{Complex{Int},Vector{Complex{Int}}} == avec + avec .+ 1 + @test broadcast(+, Transpose(vec), 1, Transpose(vec))::Transpose{Complex{Int},Vector{Complex{Int}}} == tvec + tvec .+ 1 +end + +@testset "Adjoint/Transpose-wrapped vector multiplication" begin + realvec, realmat = [1, 2, 3], [1 2 3; 4 5 6; 7 8 9] + complexvec, complexmat = [1im, 2, -3im], [1im 2 3; 4 5 -6im; 7im 8 9] + # Adjoint/Transpose-vector * vector + @test Adjoint(realvec) * realvec == dot(realvec, realvec) + @test Transpose(realvec) * realvec == dot(realvec, realvec) + @test Adjoint(complexvec) * complexvec == dot(complexvec, complexvec) + @test Transpose(complexvec) * complexvec == dot(conj(complexvec), complexvec) + # vector * Adjoint/Transpose-vector + @test realvec * Adjoint(realvec) == broadcast(*, realvec, reshape(realvec, (1, 3))) + @test realvec * Transpose(realvec) == broadcast(*, realvec, reshape(realvec, (1, 3))) + @test complexvec * Adjoint(complexvec) == broadcast(*, complexvec, reshape(conj(complexvec), (1, 3))) + @test complexvec * Transpose(complexvec) == broadcast(*, complexvec, reshape(complexvec, (1, 3))) + # Adjoint/Transpose-vector * matrix + @test (Adjoint(realvec) * realmat)::Adjoint{Int,Vector{Int}} == + reshape(adjoint(realmat) * realvec, (1, 3)) + @test (Transpose(realvec) * realmat)::Transpose{Int,Vector{Int}} == + reshape(transpose(realmat) * realvec, (1, 3)) + @test (Adjoint(complexvec) * complexmat)::Adjoint{Complex{Int},Vector{Complex{Int}}} == + reshape(conj(adjoint(complexmat) * complexvec), (1, 3)) + @test (Transpose(complexvec) * complexmat)::Transpose{Complex{Int},Vector{Complex{Int}}} == + reshape(transpose(complexmat) * complexvec, (1, 3)) + # Adjoint/Transpose-vector * Adjoint/Transpose-matrix + @test (Adjoint(realvec) * Adjoint(realmat))::Adjoint{Int,Vector{Int}} == + reshape(realmat * realvec, (1, 3)) + @test (Transpose(realvec) * Transpose(realmat))::Transpose{Int,Vector{Int}} == + reshape(realmat * realvec, (1, 3)) + @test (Adjoint(complexvec) * Adjoint(complexmat))::Adjoint{Complex{Int},Vector{Complex{Int}}} == + reshape(conj(complexmat * complexvec), (1, 3)) + @test (Transpose(complexvec) * Transpose(complexmat))::Transpose{Complex{Int},Vector{Complex{Int}}} == + reshape(complexmat * complexvec, (1, 3)) +end + +@testset "Adjoint/Transpose-wrapped vector pseudoinversion" begin + realvec, complexvec = [1, 2, 3, 4], [1im, 2, 3im, 4] + rowrealvec, rowcomplexvec = reshape(realvec, (1, 4)), reshape(complexvec, (1, 4)) + # pinv(Adjoint/Transpose-vector) should match matrix equivalents + # TODO tighten type asserts once pinv yields Transpose/Adjoint + @test pinv(Adjoint(realvec))::Vector{Float64} ≈ pinv(rowrealvec) + @test pinv(Transpose(realvec))::Vector{Float64} ≈ pinv(rowrealvec) + @test pinv(Adjoint(complexvec))::Vector{Complex{Float64}} ≈ pinv(conj(rowcomplexvec)) + @test pinv(Transpose(complexvec))::Vector{Complex{Float64}} ≈ pinv(rowcomplexvec) +end + +@testset "Adjoint/Transpose-wrapped vector left-division" begin + realvec, complexvec = [1., 2., 3., 4.,], [1.0im, 2., 3.0im, 4.] + rowrealvec, rowcomplexvec = reshape(realvec, (1, 4)), reshape(complexvec, (1, 4)) + # \(Adjoint/Transpose-vector, Adjoint/Transpose-vector) should mat matrix equivalents + @test Adjoint(realvec)\Adjoint(realvec) ≈ rowrealvec\rowrealvec + @test Transpose(realvec)\Transpose(realvec) ≈ rowrealvec\rowrealvec + @test Adjoint(complexvec)\Adjoint(complexvec) ≈ conj(rowcomplexvec)\conj(rowcomplexvec) + @test Transpose(complexvec)\Transpose(complexvec) ≈ rowcomplexvec\rowcomplexvec +end + +@testset "Adjoint/Transpose-wrapped vector right-division" begin + realvec, realmat = [1, 2, 3], [1 0 0; 0 2 0; 0 0 3] + complexvec, complexmat = [1im, 2, -3im], [2im 0 0; 0 3 0; 0 0 -5im] + rowrealvec, rowcomplexvec = reshape(realvec, (1, 3)), reshape(complexvec, (1, 3)) + # /(Adjoint/Transpose-vector, matrix) + @test (Adjoint(realvec) / realmat)::Adjoint ≈ rowrealvec / realmat + @test (Adjoint(complexvec) / complexmat)::Adjoint ≈ conj(rowcomplexvec) / complexmat + @test (Transpose(realvec) / realmat)::Transpose ≈ rowrealvec / realmat + @test (Transpose(complexvec) / complexmat)::Transpose ≈ rowcomplexvec / complexmat + # /(Adjoint/Transpose-vector, Adjoint matrix) + @test (Adjoint(realvec) / Adjoint(realmat))::Adjoint ≈ rowrealvec / adjoint(realmat) + @test (Adjoint(complexvec) / Adjoint(complexmat))::Adjoint ≈ conj(rowcomplexvec) / adjoint(complexmat) + @test (Transpose(realvec) / Adjoint(realmat))::Transpose ≈ rowrealvec / adjoint(realmat) + @test (Transpose(complexvec) / Adjoint(complexmat))::Transpose ≈ rowcomplexvec / adjoint(complexmat) + # /(Adjoint/Transpose-vector, Transpose matrix) + @test (Adjoint(realvec) / Transpose(realmat))::Adjoint ≈ rowrealvec / transpose(realmat) + @test (Adjoint(complexvec) / Transpose(complexmat))::Adjoint ≈ conj(rowcomplexvec) / transpose(complexmat) + @test (Transpose(realvec) / Transpose(realmat))::Transpose ≈ rowrealvec / transpose(realmat) + @test (Transpose(complexvec) / Transpose(complexmat))::Transpose ≈ rowcomplexvec / transpose(complexmat) +end + +@testset "norm of Adjoint/Transpose-wrapped vectors" begin + # definitions are in base/linalg/generic.jl + realvec, complexvec = [3, -4], [3im, -4im] + # one norm result should be maximum(abs.(realvec)) == 4 + # two norm result should be sqrt(sum(abs.(realvec))) == 5 + # inf norm result should be sum(abs.(realvec)) == 7 + for v in (realvec, complexvec) + @test norm(Adjoint(v)) ≈ 5 + @test norm(Adjoint(v), 1) ≈ 4 + @test norm(Adjoint(v), Inf) ≈ 7 + @test norm(Transpose(v)) ≈ 5 + @test norm(Transpose(v), 1) ≈ 4 + @test norm(Transpose(v), Inf) ≈ 7 + end +end diff --git a/test/linalg/bidiag.jl b/test/linalg/bidiag.jl index 5814775fa3986..31f7651c5f093 100644 --- a/test/linalg/bidiag.jl +++ b/test/linalg/bidiag.jl @@ -180,11 +180,6 @@ srand(1) @test_throws DimensionMismatch T.' \ ones(elty,n+1,2) @test_throws DimensionMismatch T' \ ones(elty,n+1,2) - @test_throws DimensionMismatch T \ RowVector(ones(elty,n+1)) - @test_throws DimensionMismatch T.' \ RowVector(ones(elty,n+1)) - @test_throws DimensionMismatch T' \ RowVector(ones(elty,n+1)) - @test_throws DimensionMismatch Transpose(T) \ RowVector(ones(elty,n+1)) - @test_throws DimensionMismatch Adjoint(T) \ RowVector(ones(elty,n+1)) let bb = b, cc = c for atype in ("Array", "SubArray") if atype == "Array" @@ -206,10 +201,6 @@ srand(1) @test T/b' ≈ Tfull/b' end end - # test DimensionMismatch for RowVectors - @test_throws DimensionMismatch T \ b' - @test_throws DimensionMismatch T.' \ b' - @test_throws DimensionMismatch T' \ b' end end diff --git a/test/linalg/conjarray.jl b/test/linalg/conjarray.jl index 4ba4ac90ad5bb..29839ff81bb5b 100644 --- a/test/linalg/conjarray.jl +++ b/test/linalg/conjarray.jl @@ -17,12 +17,24 @@ end @testset "RowVector conjugates" begin + # these definitions are what adjoint(...) and transpose(...) meant + # meant prior to the Adjoint/Transpose transition, and the tests + # below are re-expressed in them to shield them against changes + # to adjoint(...), transpose(...), .', ', and A[ct]_(mul|ldiv|rdiv)_B[ct] + using Base.LinAlg: _conj, ConjRowVector + rvadjoint(v::AbstractVector) = RowVector(_conj(v)) + rvtranspose(v::AbstractVector) = RowVector(v) + rvadjoint(v::RowVector) = conj(v.vec) + rvadjoint(v::RowVector{<:Real}) = v.vec + rvtranspose(v::RowVector) = v.vec + rvtranspose(v::ConjRowVector) = copy(v.vec) + v = [1+im, 1-im] - rv = v' + rv = rvadjoint(v) @test (parent(rv) isa ConjArray) - @test rv' === v + @test rvadjoint(rv) === v # Currently, view behavior defaults to only RowVectors. - @test isa((v').', Vector) - @test isa((v.')', Vector) + @test isa(rvtranspose(rvadjoint(v)), Vector) + @test isa(rvadjoint(rvtranspose(v)), Vector) end diff --git a/test/linalg/diagonal.jl b/test/linalg/diagonal.jl index 014f89bbbf251..6fe0008a00a59 100644 --- a/test/linalg/diagonal.jl +++ b/test/linalg/diagonal.jl @@ -422,6 +422,7 @@ end end end -@testset "Diagonal of a RowVector (#23649)" begin - @test Diagonal([1,2,3].') == Diagonal([1 2 3]) +@testset "Diagonal of Adjoint/Transpose vectors (#23649)" begin + @test Diagonal(Adjoint([1, 2, 3])) == Diagonal([1 2 3]) + @test Diagonal(Transpose([1, 2, 3])) == Diagonal([1 2 3]) end diff --git a/test/linalg/matmul.jl b/test/linalg/matmul.jl index 1a019db76a7af..effb4e93c7e64 100644 --- a/test/linalg/matmul.jl +++ b/test/linalg/matmul.jl @@ -293,9 +293,12 @@ end struct RootInt i::Int end -import Base: *, transpose +import Base: *, adjoint, transpose, Adjoint, Transpose (*)(x::RootInt, y::RootInt) = x.i*y.i +adjoint(x::RootInt) = x +Adjoint(x::RootInt) = x transpose(x::RootInt) = x +Transpose(x::RootInt) = x @test Base.promote_op(*, RootInt, RootInt) === Int @testset "#14293" begin diff --git a/test/linalg/pinv.jl b/test/linalg/pinv.jl index 2c20e9f54bb12..de2d2ef11c6c8 100644 --- a/test/linalg/pinv.jl +++ b/test/linalg/pinv.jl @@ -133,9 +133,9 @@ end a = rand(eltya, m) apinv = @inferred pinv(a) @test pinv(hcat(a)) ≈ apinv - @test apinv isa RowVector{eltya} + @test isa(apinv, eltya <: Complex ? Adjoint{eltya} : Transpose{eltya}) end - @testset "RowVector" begin + @testset "Adjoint/Transpose vector" begin a = rand(eltya, m)' apinv = @inferred pinv(a) @test pinv(vcat(a)) ≈ apinv diff --git a/test/linalg/rowvector.jl b/test/linalg/rowvector.jl index 96a9915a1be49..fc3a4dd2e0bc1 100644 --- a/test/linalg/rowvector.jl +++ b/test/linalg/rowvector.jl @@ -1,5 +1,19 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +using Base.LinAlg: Adjoint, Transpose + +# these definitions are what adjoint(...) and transpose(...) meant +# meant prior to the Adjoint/Transpose transition, and the tests +# below are re-expressed in them to shield them against changes +# to adjoint(...), transpose(...), .', ', and A[ct]_(mul|ldiv|rdiv)_B[ct] +using Base.LinAlg: _conj, ConjRowVector +rvadjoint(v::AbstractVector) = RowVector(_conj(v)) +rvtranspose(v::AbstractVector) = RowVector(v) +rvadjoint(v::RowVector) = conj(v.vec) +rvadjoint(v::RowVector{<:Real}) = v.vec +rvtranspose(v::RowVector) = v.vec +rvtranspose(v::ConjRowVector) = copy(v.vec) + @testset "Core" begin v = [1,2,3] z = [1+im,2,3] @@ -12,18 +26,18 @@ @test size(RowVector{Int}(uninitialized, (1,3))) === (1,3) @test_throws ErrorException RowVector{Float64, Vector{Int}}(v) - @test (v.')::RowVector == [1 2 3] - @test (v')::RowVector == [1 2 3] - @test (z.')::RowVector == [1+im 2 3] - @test (z')::RowVector == [1-im 2 3] + @test rvtranspose(v)::RowVector == [1 2 3] + @test rvadjoint(v)::RowVector == [1 2 3] + @test rvtranspose(z)::RowVector == [1+im 2 3] + @test rvadjoint(z)::RowVector == [1-im 2 3] - rv = v.' - tz = z.' + rv = rvtranspose(v) + tz = rvtranspose(z) - @test (rv.')::Vector == [1, 2, 3] - @test (rv')::Vector == [1, 2, 3] - @test (tz.')::Vector == [1+im, 2, 3] - @test (tz')::Vector == [1-im, 2, 3] + @test rvtranspose(rv)::Vector == [1, 2, 3] + @test rvadjoint(rv)::Vector == [1, 2, 3] + @test rvtranspose(tz)::Vector == [1+im, 2, 3] + @test rvadjoint(tz)::Vector == [1-im, 2, 3] @test conj(rv) === rv @test conj(tz) == [1-im 2 3] @@ -48,7 +62,7 @@ @test (-).(rv,1)::RowVector == [0 1 2] y = rand(Complex{Float64},3) - @test sum(abs2, imag.(diag(y .+ y'))) < 1e-20 + @test sum(abs2, imag.(diag(y .+ rvadjoint(y)))) < 1e-20 @test parent(rv) === v @test vec(rv) === v @@ -57,18 +71,18 @@ end @testset "Diagonal ambiguity methods" begin d = Diagonal([1,2,3]) v = [2,3,4] - rv = v.' + rv = rvtranspose(v) - @test (rv*d)::RowVector == [2,6,12].' + @test (rv*d)::RowVector == rvtranspose([2,6,12]) @test_throws DimensionMismatch d*rv - @test (d*rv.')::Vector == [2,6,12] + @test (d*rvtranspose(rv))::Vector == [2,6,12] - @test_throws DimensionMismatch rv.'*d + @test_throws DimensionMismatch rvtranspose(rv)*d - @test (d*rv')::Vector == [2,6,12] + @test (d*rvadjoint(rv))::Vector == [2,6,12] - @test_throws DimensionMismatch rv'*d + @test_throws DimensionMismatch rvadjoint(rv)*d @test (rv/d)::RowVector ≈ [2/1 3/2 4/3] @@ -78,7 +92,7 @@ end @testset "Bidiagonal ambiguity methods" begin bd = Bidiagonal([1,2,3], [0,0], :U) v = [2,3,4] - rv = v.' + rv = rvtranspose(v) @test (rv/bd)::RowVector ≈ [2/1 3/2 4/3] @@ -86,21 +100,21 @@ end end @testset "hcat" begin - @test isa([([1, 2, 3].') 4], RowVector{Int}) - @test isa([([1, 2, 3].') ([4, 5].')], RowVector{Int}) + @test isa([rvtranspose([1, 2, 3]) 4], RowVector{Int}) + @test isa([rvtranspose([1, 2, 3]) rvtranspose([4, 5])], RowVector{Int}) end @testset "Left Division" begin mat = Matrix(Diagonal([1,2,3])) v = [2,3,4] - rv = v.' + rv = rvtranspose(v) @test_throws DimensionMismatch mat \ rv end @testset "Multiplication" begin v = [1,2,3] - rv = v.' + rv = rvtranspose(v) mat = Matrix(Diagonal([1,2,3])) @test (rv*v) === 14 @@ -111,95 +125,95 @@ end @test_throws DimensionMismatch v*v # Was previously a missing method error, now an error message @test_throws DimensionMismatch mat*rv - @test_throws DimensionMismatch rv*v.' - @test (rv*mat.')::RowVector == [1 4 9] - @test [1]*reshape([1],(1,1)).' == reshape([1], (1,1)) - @test rv*rv.' === 14 - @test_throws DimensionMismatch v*rv.' - @test (v*v.')::Matrix == [1 2 3; 2 4 6; 3 6 9] - @test (mat*rv.')::Vector == [1,4,9] - - @test (rv.'*v.')::Matrix == [1 2 3; 2 4 6; 3 6 9] - @test_throws DimensionMismatch rv.'*mat.' - @test (v.'*mat.')::RowVector == [1 4 9] - @test_throws DimensionMismatch rv.'*rv.' - @test v.'*rv.' === 14 - @test_throws DimensionMismatch v.'*v.' - @test (mat.'*rv.')::Vector == [1,4,9] - - @test_throws DimensionMismatch rv.'*v - @test_throws DimensionMismatch rv.'*mat - @test (v.'*mat)::RowVector == [1 4 9] - @test (rv.'*rv)::Matrix == [1 2 3; 2 4 6; 3 6 9] - @test_throws DimensionMismatch v.'*rv - @test v.'*v === 14 - @test_throws DimensionMismatch mat.'*rv + @test_throws DimensionMismatch rv*rvtranspose(v) + @test (rv*Transpose(mat))::RowVector == [1 4 9] + @test [1]*Transpose(reshape([1],(1,1))) == reshape([1], (1,1)) + @test rv*rvtranspose(rv) === 14 + @test_throws DimensionMismatch v*rvtranspose(rv) + @test (v*rvtranspose(v))::Matrix == [1 2 3; 2 4 6; 3 6 9] + @test (mat*rvtranspose(rv))::Vector == [1,4,9] + + @test (rvtranspose(rv)*rvtranspose(v))::Matrix == [1 2 3; 2 4 6; 3 6 9] + @test_throws DimensionMismatch rvtranspose(rv)*Transpose(mat) + @test (rvtranspose(v)*Transpose(mat))::RowVector == [1 4 9] + @test_throws DimensionMismatch rvtranspose(rv)*rvtranspose(rv) + @test rvtranspose(v)*rvtranspose(rv) === 14 + @test_throws DimensionMismatch rvtranspose(v)*rvtranspose(v) + @test (Transpose(mat)*rvtranspose(rv))::Vector == [1,4,9] + + @test_throws DimensionMismatch rvtranspose(rv)*v + @test_throws DimensionMismatch rvtranspose(rv)*mat + @test (rvtranspose(v)*mat)::RowVector == [1 4 9] + @test (rvtranspose(rv)*rv)::Matrix == [1 2 3; 2 4 6; 3 6 9] + @test_throws DimensionMismatch rvtranspose(v)*rv + @test rvtranspose(v)*v === 14 + @test_throws DimensionMismatch Transpose(mat)*rv z = [1+im,2,3] - cz = z' + cz = rvadjoint(z) mat = Matrix(Diagonal([1+im,2,3])) @test cz*z === 15 + 0im - @test_throws DimensionMismatch cz*z' - @test (cz*mat')::RowVector == [-2im 4 9] - @test [1]*reshape([1],(1,1))' == reshape([1], (1,1)) - @test cz*cz' === 15 + 0im - @test_throws DimensionMismatch z*cz' - @test (z*z')::Matrix == [2 2+2im 3+3im; 2-2im 4 6; 3-3im 6 9] - @test (mat*cz')::Vector == [2im,4,9] - - @test (cz'*z')::Matrix == [2 2+2im 3+3im; 2-2im 4 6; 3-3im 6 9] - @test_throws DimensionMismatch cz'*mat' - @test (z'*mat')::RowVector == [-2im 4 9] - @test_throws DimensionMismatch cz'*cz' - @test z'*cz' === 15 + 0im - @test_throws DimensionMismatch z'*z' - @test (mat'*cz')::Vector == [2,4,9] - - @test_throws DimensionMismatch cz'*z - @test_throws DimensionMismatch cz'*mat - @test (z'*mat)::RowVector == [2 4 9] - @test (cz'*cz)::Matrix == [2 2+2im 3+3im; 2-2im 4 6; 3-3im 6 9] - @test_throws DimensionMismatch z'*cz - @test z'*z === 15 + 0im - @test_throws DimensionMismatch mat'*cz + @test_throws DimensionMismatch cz*rvadjoint(z) + @test (cz*Adjoint(mat))::RowVector == [-2im 4 9] + @test [1]*Adjoint(reshape([1],(1,1))) == reshape([1], (1,1)) + @test cz*rvadjoint(cz) === 15 + 0im + @test_throws DimensionMismatch z*rvadjoint(cz) + @test (z*rvadjoint(z))::Matrix == [2 2+2im 3+3im; 2-2im 4 6; 3-3im 6 9] + @test (mat*rvadjoint(cz))::Vector == [2im,4,9] + + @test (rvadjoint(cz)*rvadjoint(z))::Matrix == [2 2+2im 3+3im; 2-2im 4 6; 3-3im 6 9] + @test_throws DimensionMismatch rvadjoint(cz)*Adjoint(mat) + @test (rvadjoint(z)*Adjoint(mat))::RowVector == [-2im 4 9] + @test_throws DimensionMismatch rvadjoint(cz)*rvadjoint(cz) + @test rvadjoint(z)*rvadjoint(cz) === 15 + 0im + @test_throws DimensionMismatch rvadjoint(z)*rvadjoint(z) + @test (Adjoint(mat)*rvadjoint(cz))::Vector == [2,4,9] + + @test_throws DimensionMismatch rvadjoint(cz)*z + @test_throws DimensionMismatch rvadjoint(cz)*mat + @test (rvadjoint(z)*mat)::RowVector == [2 4 9] + @test (rvadjoint(cz)*cz)::Matrix == [2 2+2im 3+3im; 2-2im 4 6; 3-3im 6 9] + @test_throws DimensionMismatch rvadjoint(z)*cz + @test rvadjoint(z)*z === 15 + 0im + @test_throws DimensionMismatch Adjoint(mat)*cz end @testset "norm" begin - @test norm([3.0,4.0].') ≈ 5.0 - @test norm([3.0,4.0].', 1) ≈ 4.0 - @test norm([3.0,4.0].', Inf) ≈ 7.0 + @test norm(rvtranspose([3.0,4.0])) ≈ 5.0 + @test norm(rvtranspose([3.0,4.0]), 1) ≈ 4.0 + @test norm(rvtranspose([3.0,4.0]), Inf) ≈ 7.0 end @testset "QR ambiguity methods" begin qrmat = Base.LinAlg.getq(qrfact(Matrix(1.0I, 3, 3))) v = [2,3,4] - rv = v.' + rv = rvtranspose(v) - @test (rv*qrmat')::RowVector == [2 3 4] + @test (rv*Adjoint(qrmat))::RowVector == [2 3 4] end @testset "Right Division" begin mat = Matrix(Diagonal([1,2,3])) v = [2,3,4] - rv = v.' + rv = rvtranspose(v) @test (rv/mat)::RowVector ≈ [2/1 3/2 4/3] - @test (v.'/mat)::RowVector ≈ [2/1 3/2 4/3] - @test (v.'/mat.')::RowVector ≈ [2/1 3/2 4/3] - @test (rv/mat.')::RowVector ≈ [2/1 3/2 4/3] + @test (rvtranspose(v)/mat)::RowVector ≈ [2/1 3/2 4/3] + @test (rvtranspose(v)/Transpose(mat))::RowVector ≈ [2/1 3/2 4/3] + @test (rv/Transpose(mat))::RowVector ≈ [2/1 3/2 4/3] - @test (v'/mat)::RowVector ≈ [2/1 3/2 4/3] - @test (v'/mat')::RowVector ≈ [2/1 3/2 4/3] - @test (rv/mat')::RowVector ≈ [2/1 3/2 4/3] + @test (rvadjoint(v)/mat)::RowVector ≈ [2/1 3/2 4/3] + @test (rvadjoint(v)/Adjoint(mat))::RowVector ≈ [2/1 3/2 4/3] + @test (rv/Adjoint(mat))::RowVector ≈ [2/1 3/2 4/3] end @testset "Sparse ambiguity methods" begin mat = sparse(Diagonal([1,2,3])) v = [2,3,4] - rv = v.' + rv = rvtranspose(v) @test (rv/mat)::RowVector ≈ [2/1 3/2 4/3] @@ -209,32 +223,32 @@ end @testset "AbstractTriangular ambiguity methods" begin ut = UpperTriangular([1 0 0; 0 2 0; 0 0 3]) v = [2,3,4] - rv = v.' + rv = rvtranspose(v) @test (rv*ut)::RowVector == [2 6 12] @test_throws DimensionMismatch ut*rv - @test (rv*ut.')::RowVector == [2 6 12] - @test (ut*rv.')::Vector == [2,6,12] + @test (rv*Transpose(ut))::RowVector == [2 6 12] + @test (ut*rvtranspose(rv))::Vector == [2,6,12] - @test (ut.'*rv.')::Vector == [2,6,12] - @test_throws DimensionMismatch rv.'*ut.' + @test (Transpose(ut)*rvtranspose(rv))::Vector == [2,6,12] + @test_throws DimensionMismatch rvtranspose(rv)*Transpose(ut) - @test_throws DimensionMismatch ut.'*rv - @test_throws DimensionMismatch rv.'*ut + @test_throws DimensionMismatch Transpose(ut)*rv + @test_throws DimensionMismatch rvtranspose(rv)*ut - @test (rv*ut')::RowVector == [2 6 12] - @test (ut*rv')::Vector == [2,6,12] + @test (rv*Adjoint(ut))::RowVector == [2 6 12] + @test (ut*rvadjoint(rv))::Vector == [2,6,12] - @test_throws DimensionMismatch rv'*ut' - @test (ut'*rv')::Vector == [2,6,12] + @test_throws DimensionMismatch rvadjoint(rv)*Adjoint(ut) + @test (Adjoint(ut)*rvadjoint(rv))::Vector == [2,6,12] - @test_throws DimensionMismatch ut'*rv - @test_throws DimensionMismatch rv'*ut + @test_throws DimensionMismatch Adjoint(ut)*rv + @test_throws DimensionMismatch rvadjoint(rv)*ut @test (rv/ut)::RowVector ≈ [2/1 3/2 4/3] - @test (rv/ut.')::RowVector ≈ [2/1 3/2 4/3] - @test (rv/ut')::RowVector ≈ [2/1 3/2 4/3] + @test (rv/Transpose(ut))::RowVector ≈ [2/1 3/2 4/3] + @test (rv/Adjoint(ut))::RowVector ≈ [2/1 3/2 4/3] @test_throws DimensionMismatch ut\rv end @@ -242,38 +256,38 @@ end @testset "Symmetric/Hermitian ambiguity methods" begin S = Symmetric(rand(3, 3)) H = Hermitian(rand(3, 3)) - v = (rand(3)')::RowVector + v = (rvadjoint(rand(3)))::RowVector @test_throws DimensionMismatch S\v @test_throws DimensionMismatch H\v end # issue #20389 @testset "1 row/col vec*mat" begin - let x=[1,2,3], A=ones(1,4), y=x', B=A', C=x.*A - @test x*A == y'*A == x*B' == y'*B' == C - @test A'*x' == A'*y == B*x' == B*y == C' + let x=[1,2,3], A=ones(1,4), y=rvadjoint(x), B=adjoint(A), C=x.*A + @test x*A == rvadjoint(y)*A == x*Adjoint(B) == rvadjoint(y)*Adjoint(B) == C + @test Adjoint(A)*rvadjoint(x) == Adjoint(A)*y == B*rvadjoint(x) == B*y == adjoint(C) end end @testset "complex 1 row/col vec*mat" begin - let x=[1,2,3]*im, A=ones(1,4)*im, y=x', B=A', C=x.*A - @test x*A == y'*A == x*B' == y'*B' == C - @test A'*x' == A'*y == B*x' == B*y == C' + let x=[1,2,3]*im, A=ones(1,4)*im, y=rvadjoint(x), B=adjoint(A), C=x.*A + @test x*A == rvadjoint(y)*A == x*Adjoint(B) == rvadjoint(y)*Adjoint(B) == C + @test Adjoint(A)*rvadjoint(x) == Adjoint(A)*y == B*rvadjoint(x) == B*y == adjoint(C) end end @testset "issue #20979" begin f20979(z::Complex) = [z.re -z.im; z.im z.re] - v = [1+2im]' + v = rvadjoint([1+2im]) @test (f20979.(v))[1] == f20979(v[1]) @test f20979.(v) == f20979.(collect(v)) w = rand(ComplexF64, 3) - @test f20979.(v') == f20979.(collect(v')) == (f20979.(v))' + @test f20979.(rvadjoint(v)) == f20979.(collect(rvadjoint(v))) == rvadjoint(f20979.(v)) g20979(x, y) = [x[2,1] x[1,2]; y[1,2] y[2,1]] v = [rand(2,2), rand(2,2), rand(2,2)] - @test g20979.(v', v') == g20979.(collect(v'), collect(v')) == - map(g20979, v', v') == map(g20979, collect(v'), collect(v')) + @test g20979.(rvadjoint(v), rvadjoint(v)) == g20979.(collect(rvadjoint(v)), collect(rvadjoint(v))) == + map(g20979, rvadjoint(v), rvadjoint(v)) == map(g20979, collect(rvadjoint(v)), collect(rvadjoint(v))) end @testset "ambiguity between * methods with RowVectors and ConjRowVectors (#20971)" begin @@ -282,18 +296,18 @@ end @testset "setindex!/getindex" begin v = [2, 3, 4] - rv = v.' + rv = rvtranspose(v) @test_throws BoundsError setindex!(rv, 5, CartesianIndex((5, 4, 3))) rv[CartesianIndex((1, 1, 1))] = 5 @test_throws BoundsError getindex(rv, CartesianIndex((5, 4, 3))) @test rv[1] == 5 @test rv[:, 2]::Vector == [v[2]] - @test rv[:, 2:3]::RowVector == v[2:3].' + @test rv[:, 2:3]::RowVector == rvtranspose(v[2:3]) @test rv[:, :]::RowVector == rv v = [1] - rv = v.' + rv = rvtranspose(v) rv[CartesianIndex()] = 2 @test rv[CartesianIndex()] == 2 rv[CartesianIndex(1)] = 1 diff --git a/test/linalg/symmetric.jl b/test/linalg/symmetric.jl index 4737084f621e7..67b067260c585 100644 --- a/test/linalg/symmetric.jl +++ b/test/linalg/symmetric.jl @@ -289,13 +289,13 @@ end @testset "linalg binary ops" begin @testset "mat * vec" begin @test Symmetric(asym)*x+y ≈ asym*x+y - # testing fallbacks for RowVector * SymHerm.' + # testing fallbacks for Transpose-vector * SymHerm.' xadj = x.' @test xadj * Symmetric(asym).' ≈ xadj * asym @test x' * Symmetric(asym) ≈ x' * asym @test Hermitian(aherm)*x+y ≈ aherm*x+y - # testing fallbacks for RowVector * SymHerm' + # testing fallbacks for Adjoint-vector * SymHerm' xadj = x' @test x' * Hermitian(aherm) ≈ x' * aherm @test xadj * Hermitian(aherm)' ≈ xadj * aherm diff --git a/test/show.jl b/test/show.jl index 18f96eba765df..18cf251f30ff2 100644 --- a/test/show.jl +++ b/test/show.jl @@ -556,7 +556,7 @@ end @test replstr(Matrix(1.0I, 10, 10)) == "10×10 Array{Float64,2}:\n 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0\n 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0\n 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0" # an array too long vertically to fit on screen, and too long horizontally: @test replstr(collect(1.:100.)) == "100-element Array{Float64,1}:\n 1.0\n 2.0\n 3.0\n 4.0\n 5.0\n 6.0\n 7.0\n 8.0\n 9.0\n 10.0\n ⋮ \n 92.0\n 93.0\n 94.0\n 95.0\n 96.0\n 97.0\n 98.0\n 99.0\n 100.0" -@test replstr(collect(1.:100.)') == "1×100 RowVector{Float64,Array{Float64,1}}:\n 1.0 2.0 3.0 4.0 5.0 6.0 7.0 … 95.0 96.0 97.0 98.0 99.0 100.0" +@test replstr(collect(1.:100.)') == "1×100 Transpose{Float64,Array{Float64,1}}:\n 1.0 2.0 3.0 4.0 5.0 6.0 7.0 … 95.0 96.0 97.0 98.0 99.0 100.0" # too big in both directions to fit on screen: @test replstr((1.:100.)*(1:100)') == "100×100 Array{Float64,2}:\n 1.0 2.0 3.0 4.0 5.0 6.0 … 97.0 98.0 99.0 100.0\n 2.0 4.0 6.0 8.0 10.0 12.0 194.0 196.0 198.0 200.0\n 3.0 6.0 9.0 12.0 15.0 18.0 291.0 294.0 297.0 300.0\n 4.0 8.0 12.0 16.0 20.0 24.0 388.0 392.0 396.0 400.0\n 5.0 10.0 15.0 20.0 25.0 30.0 485.0 490.0 495.0 500.0\n 6.0 12.0 18.0 24.0 30.0 36.0 … 582.0 588.0 594.0 600.0\n 7.0 14.0 21.0 28.0 35.0 42.0 679.0 686.0 693.0 700.0\n 8.0 16.0 24.0 32.0 40.0 48.0 776.0 784.0 792.0 800.0\n 9.0 18.0 27.0 36.0 45.0 54.0 873.0 882.0 891.0 900.0\n 10.0 20.0 30.0 40.0 50.0 60.0 970.0 980.0 990.0 1000.0\n ⋮ ⋮ ⋱ \n 92.0 184.0 276.0 368.0 460.0 552.0 8924.0 9016.0 9108.0 9200.0\n 93.0 186.0 279.0 372.0 465.0 558.0 9021.0 9114.0 9207.0 9300.0\n 94.0 188.0 282.0 376.0 470.0 564.0 9118.0 9212.0 9306.0 9400.0\n 95.0 190.0 285.0 380.0 475.0 570.0 9215.0 9310.0 9405.0 9500.0\n 96.0 192.0 288.0 384.0 480.0 576.0 … 9312.0 9408.0 9504.0 9600.0\n 97.0 194.0 291.0 388.0 485.0 582.0 9409.0 9506.0 9603.0 9700.0\n 98.0 196.0 294.0 392.0 490.0 588.0 9506.0 9604.0 9702.0 9800.0\n 99.0 198.0 297.0 396.0 495.0 594.0 9603.0 9702.0 9801.0 9900.0\n 100.0 200.0 300.0 400.0 500.0 600.0 9700.0 9800.0 9900.0 10000.0" diff --git a/test/sparse/higherorderfns.jl b/test/sparse/higherorderfns.jl index e4dd960636ef6..d25b5eabd0ba6 100644 --- a/test/sparse/higherorderfns.jl +++ b/test/sparse/higherorderfns.jl @@ -414,7 +414,7 @@ end @test broadcast!(+, Z, V, A, X) == sparse(broadcast(+, fV, fA, X)) @test broadcast(*, s, V, A, X)::SparseMatrixCSC == sparse(broadcast(*, s, fV, fA, X)) @test broadcast!(*, Z, s, V, A, X) == sparse(broadcast(*, s, fV, fA, X)) - # Issue #20954 combinations of sparse arrays and RowVectors + # Issue #20954 combinations of sparse arrays and Adjoint/Transpose vectors @test broadcast(+, A, X')::SparseMatrixCSC == sparse(broadcast(+, fA, X')) @test broadcast(*, V, X')::SparseMatrixCSC == sparse(broadcast(*, fV, X')) end