Skip to content

Commit

Permalink
Deprecate ConjRowVector/RowVector in favor of Adjoint/Transpose.
Browse files Browse the repository at this point in the history
  • Loading branch information
Sacha0 committed Dec 25, 2017
1 parent a3d6875 commit ebf71e7
Show file tree
Hide file tree
Showing 8 changed files with 283 additions and 573 deletions.
282 changes: 276 additions & 6 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2219,12 +2219,6 @@ end
@deprecate chol!(x::Number, uplo) chol(x) false
end

# deprecate RowVector{T}(shape...) constructors to RowVector{T}(uninitialized, shape...) equivalents
@deprecate RowVector{T}(n::Int) where {T} RowVector{T}(uninitialized, n)
@deprecate RowVector{T}(n1::Int, n2::Int) where {T} RowVector{T}(uninitialized, n1, n2)
@deprecate RowVector{T}(n::Tuple{Int}) where {T} RowVector{T}(uninitialized, n)
@deprecate RowVector{T}(n::Tuple{Int,Int}) where {T} RowVector{T}(uninitialized, n)

@deprecate cumsum(A::AbstractArray) cumsum(A, 1)
@deprecate cumprod(A::AbstractArray) cumprod(A, 1)

Expand Down Expand Up @@ -2309,6 +2303,282 @@ end
export ConjArray
end

# deprecate ConjRowVector/RowVector
# TODO: between 0.7 and 1.0 remove
# 1) the type definitions in base/linalg/rowvector.jl
# 2) the include("base/linalg/rowvector.jl") from base/linalg/linalg.jl
# 3) the file base/linalg/rowvector.jl itself
# 4) the RowVectors in the Unions in base/sparse/sparsevector.jl around lines 995, 1010, 1011, and 1012
@eval Base.LinAlg begin
export RowVector

_RowVector_depstring() = string("`ConjRowVector` and `RowVector` have been deprecated in favor ",
"of `Adjoint` and `Transpose`. Please see 0.7's NEWS.md for a more detailed explanation ",
"of the associated changes.")

@inline check_types(::Type{T1}, ::AbstractVector{T2}) where {T1,T2} = check_types(T1, T2)
@pure check_types(::Type{T1}, ::Type{T2}) where {T1,T2} = T1 === transpose_type(T2) ? nothing :
error("Element type mismatch. Tried to create a `RowVector{$T1}` from an `AbstractVector{$T2}`")

# The element type may be transformed as transpose is recursive
@inline transpose_type(::Type{T}) where {T} = promote_op(transpose, T)

# Constructors that take a vector
function RowVector(vec::AbstractVector{T}) where {T}
Base.depwarn(_RowVector_depstring(), :RowVector)
return RowVector{transpose_type(T),typeof(vec)}(vec)
end
function RowVector{T}(vec::AbstractVector{T}) where {T}
Base.depwarn(_RowVector_depstring(), :RowVector)
return RowVector{T,typeof(vec)}(vec)
end

# Constructors that take a size and default to Array
function RowVector{T}(::Uninitialized, n::Int) where {T}
Base.depwarn(_RowVector_depstring(), :RowVector)
return RowVector{T}(Vector{transpose_type(T)}(uninitialized, n))
end
function RowVector{T}(::Uninitialized, n1::Int, n2::Int) where {T}
Base.depwarn(_RowVector_depstring(), :RowVector)
return n1 == 1 ? RowVector{T}(Vector{transpose_type(T)}(uninitialized, n2)) :
error("RowVector expects 1×N size, got ($n1,$n2)")
end
function RowVector{T}(::Uninitialized, n::Tuple{Int}) where {T}
Base.depwarn(_RowVector_depstring(), :RowVector)
return RowVector{T}(Vector{transpose_type(T)}(uninitialized, n[1]))
end
function RowVector{T}(::Uninitialized, n::Tuple{Int,Int}) where {T}
Base.depwarn(_RowVector_depstring(), :RowVector)
return n[1] == 1 ? RowVector{T}(Vector{transpose_type(T)}(uninitialized, n[2])) :
error("RowVector expects 1×N size, got $n")
end

# Conversion of underlying storage
convert(::Type{RowVector{T,V}}, rowvec::RowVector) where {T,V<:AbstractVector} =
RowVector{T,V}(convert(V,rowvec.vec))

# similar tries to maintain the RowVector wrapper and the parent type
@inline similar(rowvec::RowVector) = RowVector(similar(parent(rowvec)))
@inline similar(rowvec::RowVector, ::Type{T}) where {T} = RowVector(similar(parent(rowvec), transpose_type(T)))

# Resizing similar currently loses its RowVector property.
@inline similar(rowvec::RowVector, ::Type{T}, dims::Dims{N}) where {T,N} = similar(parent(rowvec), T, dims)

# Basic methods

# 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
@inline adjoint(rowvec::RowVector) = conj(rowvec.vec)
@inline adjoint(rowvec::RowVector{<:Real}) = rowvec.vec

parent(rowvec::RowVector) = rowvec.vec
vec(rowvec::RowVector) = rowvec.vec

"""
conj(v::RowVector)
Return a [`ConjArray`](@ref) lazy view of the input, where each element is conjugated.
# Examples
```jldoctest
julia> v = RowVector([1+im, 1-im])
1×2 RowVector{Complex{Int64},Array{Complex{Int64},1}}:
1+1im 1-1im
julia> conj(v)
1×2 RowVector{Complex{Int64},ConjArray{Complex{Int64},1,Array{Complex{Int64},1}}}:
1-1im 1+1im
```
"""
@inline conj(rowvec::RowVector) = RowVector(_conj(rowvec.vec))
@inline conj(rowvec::RowVector{<:Real}) = rowvec

# AbstractArray interface
@inline length(rowvec::RowVector) = length(rowvec.vec)
@inline size(rowvec::RowVector) = (1, length(rowvec.vec))
@inline size(rowvec::RowVector, d) = ifelse(d==2, length(rowvec.vec), 1)
@inline axes(rowvec::RowVector) = (Base.OneTo(1), axes(rowvec.vec)[1])
@inline axes(rowvec::RowVector, d) = ifelse(d == 2, axes(rowvec.vec)[1], Base.OneTo(1))
IndexStyle(::RowVector) = IndexLinear()
IndexStyle(::Type{<:RowVector}) = IndexLinear()

@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) = 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(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(rvtransposef, to_vecs(rowvecs...)...))

# broacast (other combinations default to higher-dimensional array)
@inline broadcast(f, rowvecs::Union{Number,RowVector}...) =
RowVector(broadcast(transposef, to_vecs(rowvecs...)...))

# Horizontal concatenation #

@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} =
rvtranspose(typed_vcat(T, map(rvtranspose, X)...))
@inline typed_hcat(::Type{T}, X::Union{RowVector,Number}...) where {T} =
rvtranspose(typed_vcat(T, map(rvtranspose, X)...))

# Multiplication #

# inner product -> dot product specializations
@inline *(rowvec::RowVector{T}, vec::AbstractVector{T}) where {T<:Real} = dot(parent(rowvec), vec)
@inline *(rowvec::ConjRowVector{T}, vec::AbstractVector{T}) where {T<:Real} = dot(rvadjoint(rowvec), vec)
@inline *(rowvec::ConjRowVector, vec::AbstractVector) = dot(rvadjoint(rowvec), vec)

# Generic behavior
@inline function *(rowvec::RowVector, vec::AbstractVector)
if length(rowvec) != length(vec)
throw(DimensionMismatch("A has dimensions $(size(rowvec)) but B has dimensions $(size(vec))"))
end
sum(@inbounds(return rowvec[i]*vec[i]) for i = 1:length(vec))
end
@inline *(rowvec::RowVector, mat::AbstractMatrix) = rvtranspose(Transpose(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"))

# Transposed forms
*(::RowVector, ::Transpose{<:Any,<:AbstractVector}) =
throw(DimensionMismatch("Cannot multiply two transposed vectors"))
*(rowvec::RowVector, transmat::Transpose{<:Any,<:AbstractMatrix}) =
(mat = transmat.parent; rvtranspose(mat * rvtranspose(rowvec)))
*(rowvec1::RowVector, transrowvec2::Transpose{<:Any,<:RowVector}) =
(rowvec2 = transrowvec2.parent; rowvec1*rvtranspose(rowvec2))
*(::AbstractVector, ::Transpose{<:Any,<:RowVector}) =
throw(DimensionMismatch("Cannot multiply two vectors"))
*(mat::AbstractMatrix, transrowvec::Transpose{<:Any,<:RowVector}) =
(rowvec = transrowvec.parent; mat * rvtranspose(rowvec))

*(transrowvec::Transpose{<:Any,<:RowVector}, transvec::Transpose{<:Any,<:AbstractVector}) =
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)*rvtranspose(transrowvec.parent)
*(transmat::Transpose{<:Any,<:AbstractMatrix}, transrowvec::Transpose{<:Any,<:RowVector}) =
transmat * rvtranspose(transrowvec.parent)

*(::Transpose{<:Any,<:RowVector}, ::AbstractVector) =
throw(DimensionMismatch("Cannot multiply two vectors"))
*(transrowvec1::Transpose{<:Any,<:RowVector}, rowvec2::RowVector) =
rvtranspose(transrowvec1.parent) * rowvec2
*(transvec::Transpose{<:Any,<:AbstractVector}, rowvec::RowVector) =
throw(DimensionMismatch("Cannot multiply two transposed vectors"))

# Conjugated forms
*(::RowVector, ::Adjoint{<:Any,<:AbstractVector}) =
throw(DimensionMismatch("Cannot multiply two transposed vectors"))
*(rowvec::RowVector, adjmat::Adjoint{<:Any,<:AbstractMatrix}) =
rvadjoint(adjmat.parent * rvadjoint(rowvec))
*(rowvec1::RowVector, adjrowvec2::Adjoint{<:Any,<:RowVector}) =
rowvec1 * rvadjoint(adjrowvec2.parent)
*(vec::AbstractVector, adjrowvec::Adjoint{<:Any,<:RowVector}) =
throw(DimensionMismatch("Cannot multiply two vectors"))
*(mat::AbstractMatrix, adjrowvec::Adjoint{<:Any,<:RowVector}) =
mat * rvadjoint(adjrowvec.parent)

*(adjrowvec::Adjoint{<:Any,<:RowVector}, adjvec::Adjoint{<:Any,<:AbstractVector}) =
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)*rvadjoint(adjrowvec.parent)
*(adjmat::Adjoint{<:Any,<:AbstractMatrix}, adjrowvec::Adjoint{<:Any,<:RowVector}) =
adjoint(adjmat.parent) * rvadjoint(adjrowvec.parent)

*(::Adjoint{<:Any,<:RowVector}, ::AbstractVector) = throw(DimensionMismatch("Cannot multiply two vectors"))
*(adjrowvec1::Adjoint{<:Any,<:RowVector}, rowvec2::RowVector) = rvadjoint(adjrowvec1.parent) * rowvec2
*(adjvec::Adjoint{<:Any,<:AbstractVector}, rowvec::RowVector) = throw(DimensionMismatch("Cannot multiply two transposed vectors"))

# Pseudo-inverse
pinv(v::RowVector, tol::Real=0) = rvadjoint(pinv(rvadjoint(v), tol))

# Left Division #

\(rowvec1::RowVector, rowvec2::RowVector) = pinv(rowvec1) * rowvec2
\(mat::AbstractMatrix, rowvec::RowVector) = throw(DimensionMismatch("Cannot left-divide transposed vector by matrix"))
\(transmat::Transpose{<:Any,<:AbstractMatrix}, rowvec::RowVector) =
throw(DimensionMismatch("Cannot left-divide transposed vector by matrix"))
\(adjmat::Adjoint{<:Any,<:AbstractMatrix}, rowvec::RowVector) =
throw(DimensionMismatch("Cannot left-divide transposed vector by matrix"))

# Right Division #

@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, 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 * rvtranspose(B.parent)
*(A::Transpose{<:Any,<:AbstractVector}, B::Adjoint{<:Any,<:RowVector}) = transpose(A.parent) * B
*(A::Transpose{<:Any,<:AbstractMatrix}, B::Adjoint{<:Any,<:RowVector}) = A * rvadjoint(B.parent)
end
@eval Base begin
export RowVector
end
@eval Base.LinAlg begin
# deprecate RowVector{T}(shape...) constructors to RowVector{T}(uninitialized, shape...) equivalents
@deprecate RowVector{T}(n::Int) where {T} RowVector{T}(uninitialized, n)
@deprecate RowVector{T}(n1::Int, n2::Int) where {T} RowVector{T}(uninitialized, n1, n2)
@deprecate RowVector{T}(n::Tuple{Int}) where {T} RowVector{T}(uninitialized, n)
@deprecate RowVector{T}(n::Tuple{Int,Int}) where {T} RowVector{T}(uninitialized, n)
end

# A[ct]_(mul|ldiv|rdiv)_B[ct][!] methods from base/operators.jl, to deprecate
@deprecate Ac_ldiv_Bt(a,b) (\)(Adjoint(a), Transpose(b))
@deprecate At_ldiv_Bt(a,b) (\)(Transpose(a), Transpose(b))
Expand Down
1 change: 0 additions & 1 deletion base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ export
RoundUp,
Adjoint,
Transpose,
RowVector,
AbstractSerializer,
SerializationState,
Set,
Expand Down
1 change: 0 additions & 1 deletion base/linalg/linalg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export
# Types
Adjoint,
Transpose,
RowVector,
SymTridiagonal,
Tridiagonal,
Bidiagonal,
Expand Down
Loading

0 comments on commit ebf71e7

Please sign in to comment.