Skip to content

Commit

Permalink
Deprecate getindex(::Factorization, ::Symbol) in favor of dot overloa…
Browse files Browse the repository at this point in the history
…ding
  • Loading branch information
andreasnoack committed Dec 19, 2017
1 parent c16c0cb commit badc334
Show file tree
Hide file tree
Showing 29 changed files with 609 additions and 610 deletions.
6 changes: 6 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3423,6 +3423,12 @@ workspace() = error("workspace() is discontinued, check out Revise.jl for an alt
# PR #25113
@deprecate_binding CartesianRange CartesianIndices

# Use getproperty instead of getindex for Factorizations
function getindex(F::Factorization, s::Symbol)
depwarn("F[:$s] is deprecated, use F.$s instead.", :getindex)
return getproperty(F, s)
end

# END 0.7 deprecations

# BEGIN 1.0 deprecations
Expand Down
38 changes: 19 additions & 19 deletions base/linalg/bunchkaufman.jl
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ convert(::Type{BunchKaufman{T}}, B::BunchKaufman) where {T} =
convert(::Type{Factorization{T}}, B::BunchKaufman{T}) where {T} = B
convert(::Type{Factorization{T}}, B::BunchKaufman) where {T} = convert(BunchKaufman{T}, B)

size(B::BunchKaufman) = size(B.LD)
size(B::BunchKaufman, d::Integer) = size(B.LD, d)
size(B::BunchKaufman) = size(getfield(B, :LD))
size(B::BunchKaufman, d::Integer) = size(getfield(B, :LD), d)
issymmetric(B::BunchKaufman) = B.symmetric
ishermitian(B::BunchKaufman) = !B.symmetric

Expand Down Expand Up @@ -115,7 +115,7 @@ function _ipiv2perm_bk(v::AbstractVector{T}, maxi::Integer, uplo::Char) where T
end

"""
getindex(B::BunchKaufman, d::Symbol)
getproperty(B::BunchKaufman, d::Symbol)
Extract the factors of the Bunch-Kaufman factorization `B`. The factorization can take the
two forms `L*D*L'` or `U*D*U'` (or `L*D*Transpose(L)` in the complex symmetric case) where `L` is a
Expand Down Expand Up @@ -153,43 +153,43 @@ permutation:
3
2
julia> F[:L]*F[:D]*F[:L]' - A[F[:p], F[:p]]
julia> F.L*F.D*F.L' - A[F.p, F.p]
3×3 Array{Float64,2}:
0.0 0.0 0.0
0.0 0.0 0.0
0.0 0.0 0.0
julia> F = bkfact(Symmetric(A));
julia> F[:U]*F[:D]*F[:U]' - F[:P]*A*F[:P]'
julia> F.U*F.D*F.U' - F.P*A*F.P'
3×3 Array{Float64,2}:
0.0 0.0 0.0
0.0 0.0 0.0
0.0 0.0 0.0
```
"""
function getindex(B::BunchKaufman{T}, d::Symbol) where {T<:BlasFloat}
@inline function getproperty(B::BunchKaufman{T}, d::Symbol) where {T<:BlasFloat}
n = size(B, 1)
if d == :p
return _ipiv2perm_bk(B.ipiv, n, B.uplo)
return _ipiv2perm_bk(getfield(B, :ipiv), n, getfield(B, :uplo))
elseif d == :P
return Matrix{T}(I, n, n)[:,invperm(B[:p])]
return Matrix{T}(I, n, n)[:,invperm(B.p)]
elseif d == :L || d == :U || d == :D
if B.rook
LUD, od = LAPACK.syconvf_rook!(B.uplo, 'C', copy(B.LD), B.ipiv)
if getfield(B, :rook)
LUD, od = LAPACK.syconvf_rook!(getfield(B, :uplo), 'C', copy(getfield(B, :LD)), getfield(B, :ipiv))
else
LUD, od = LAPACK.syconv!(B.uplo, copy(B.LD), B.ipiv)
LUD, od = LAPACK.syconv!(getfield(B, :uplo), copy(getfield(B, :LD)), getfield(B, :ipiv))
end
if d == :D
if B.uplo == 'L'
if getfield(B, :uplo) == 'L'
odl = od[1:n - 1]
return Tridiagonal(odl, diag(LUD), B.symmetric ? odl : conj.(odl))
return Tridiagonal(odl, diag(LUD), getfield(B, :symmetric) ? odl : conj.(odl))
else # 'U'
odu = od[2:n]
return Tridiagonal(B.symmetric ? odu : conj.(odu), diag(LUD), odu)
return Tridiagonal(getfield(B, :symmetric) ? odu : conj.(odu), diag(LUD), odu)
end
elseif d == :L
if B.uplo == 'L'
if getfield(B, :uplo) == 'L'
return UnitLowerTriangular(LUD)
else
throw(ArgumentError("factorization is U*D*Transpose(U) but you requested L"))
Expand All @@ -202,7 +202,7 @@ function getindex(B::BunchKaufman{T}, d::Symbol) where {T<:BlasFloat}
end
end
else
throw(KeyError(d))
getfield(B, d)
end
end

Expand All @@ -212,11 +212,11 @@ function Base.show(io::IO, mime::MIME{Symbol("text/plain")}, B::BunchKaufman)
if issuccess(B)
println(io, summary(B))
println(io, "D factor:")
show(io, mime, B[:D])
show(io, mime, B.D)
println(io, "\n$(B.uplo) factor:")
show(io, mime, B[Symbol(B.uplo)])
show(io, mime, B.uplo == 'L' ? B.L : B.U)
println(io, "\npermutation:")
show(io, mime, B[:p])
show(io, mime, B.p)
else
print(io, "Failed factorization of type $(typeof(B))")
end
Expand Down
77 changes: 45 additions & 32 deletions base/linalg/cholesky.jl
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ end
Compute the Cholesky factorization of a dense symmetric positive definite matrix `A`
and return a `Cholesky` factorization. The matrix `A` can either be a [`Symmetric`](@ref) or [`Hermitian`](@ref)
`StridedMatrix` or a *perfectly* symmetric or Hermitian `StridedMatrix`.
The triangular Cholesky factor can be obtained from the factorization `F` with: `F[:L]` and `F[:U]`.
The triangular Cholesky factor can be obtained from the factorization `F` with: `F.L` and `F.U`.
The following functions are available for `Cholesky` objects: [`size`](@ref), [`\\`](@ref),
[`inv`](@ref), [`det`](@ref), [`logdet`](@ref) and [`isposdef`](@ref).
Expand All @@ -305,19 +305,19 @@ U factor:
⋅ 1.0 5.0
⋅ ⋅ 3.0
julia> C[:U]
julia> C.U
3×3 UpperTriangular{Float64,Array{Float64,2}}:
2.0 6.0 -8.0
⋅ 1.0 5.0
⋅ ⋅ 3.0
julia> C[:L]
julia> C.L
3×3 LowerTriangular{Float64,Array{Float64,2}}:
2.0 ⋅ ⋅
6.0 1.0 ⋅
-8.0 5.0 3.0
julia> C[:L] * C[:U] == A
julia> C.L * C.U == A
true
```
"""
Expand All @@ -332,7 +332,7 @@ cholfact(A::Union{StridedMatrix,RealHermSymComplexHerm{<:Real,<:StridedMatrix}},
Compute the pivoted Cholesky factorization of a dense symmetric positive semi-definite matrix `A`
and return a `CholeskyPivoted` factorization. The matrix `A` can either be a [`Symmetric`](@ref)
or [`Hermitian`](@ref) `StridedMatrix` or a *perfectly* symmetric or Hermitian `StridedMatrix`.
The triangular Cholesky factor can be obtained from the factorization `F` with: `F[:L]` and `F[:U]`.
The triangular Cholesky factor can be obtained from the factorization `F` with: `F.L` and `F.U`.
The following functions are available for `PivotedCholesky` objects:
[`size`](@ref), [`\\`](@ref), [`inv`](@ref), [`det`](@ref), and [`rank`](@ref).
The argument `tol` determines the tolerance for determining the rank.
Expand Down Expand Up @@ -361,14 +361,14 @@ convert(::Type{CholeskyPivoted{T}},C::CholeskyPivoted) where {T} =
convert(::Type{Factorization{T}}, C::CholeskyPivoted{T}) where {T} = C
convert(::Type{Factorization{T}}, C::CholeskyPivoted) where {T} = convert(CholeskyPivoted{T}, C)

convert(::Type{AbstractMatrix}, C::Cholesky) = C.uplo == 'U' ? C[:U]'C[:U] : C[:L]*C[:L]'
convert(::Type{AbstractMatrix}, C::Cholesky) = C.uplo == 'U' ? C.U'C.U : C.L*C.L'
convert(::Type{AbstractArray}, C::Cholesky) = convert(AbstractMatrix, C)
convert(::Type{Matrix}, C::Cholesky) = convert(Array, convert(AbstractArray, C))
convert(::Type{Array}, C::Cholesky) = convert(Matrix, C)

function convert(::Type{AbstractMatrix}, F::CholeskyPivoted)
ip = invperm(F[:p])
(F[:L] * F[:U])[ip,ip]
ip = invperm(F.p)
(F.L * F.U)[ip,ip]
end
convert(::Type{AbstractArray}, F::CholeskyPivoted) = convert(AbstractMatrix, F)
convert(::Type{Matrix}, F::CholeskyPivoted) = convert(Array, convert(AbstractArray, F))
Expand All @@ -380,43 +380,56 @@ copy(C::CholeskyPivoted) = CholeskyPivoted(copy(C.factors), C.uplo, C.piv, C.ran
size(C::Union{Cholesky, CholeskyPivoted}) = size(C.factors)
size(C::Union{Cholesky, CholeskyPivoted}, d::Integer) = size(C.factors, d)

function getindex(C::Cholesky, d::Symbol)
d == :U && return UpperTriangular(Symbol(C.uplo) == d ? C.factors : C.factors')
d == :L && return LowerTriangular(Symbol(C.uplo) == d ? C.factors : C.factors')
d == :UL && return Symbol(C.uplo) == :U ? UpperTriangular(C.factors) : LowerTriangular(C.factors)
throw(KeyError(d))
end
function getindex(C::CholeskyPivoted{T}, d::Symbol) where T<:BlasFloat
d == :U && return UpperTriangular(Symbol(C.uplo) == d ? C.factors : C.factors')
d == :L && return LowerTriangular(Symbol(C.uplo) == d ? C.factors : C.factors')
d == :p && return C.piv
if d == :P
@inline function getproperty(C::Cholesky, d::Symbol)
Cfactors = getfield(C, :factors)
Cuplo = getfield(C, :uplo)
if d == :U
return UpperTriangular(Symbol(Cuplo) == d ? Cfactors : Cfactors')
elseif d == :L
return LowerTriangular(Symbol(Cuplo) == d ? Cfactors : Cfactors')
elseif d == :UL
return Symbol(Cuplo) == :U ? UpperTriangular(Cfactors) : LowerTriangular(Cfactors)
else
return getfield(C, d)
end
end
@inline function getproperty(C::CholeskyPivoted{T}, d::Symbol) where T<:BlasFloat
Cfactors = getfield(C, :factors)
Cuplo = getfield(C, :uplo)
if d == :U
return UpperTriangular(Symbol(Cuplo) == d ? Cfactors : Cfactors')
elseif d == :L
return LowerTriangular(Symbol(Cuplo) == d ? Cfactors : Cfactors')
elseif d == :p
return getfield(C, :piv)
elseif d == :P
n = size(C, 1)
P = zeros(T, n, n)
for i = 1:n
P[C.piv[i],i] = one(T)
P[getfield(C, :piv)[i], i] = one(T)
end
return P
else
return getfield(C, d)
end
throw(KeyError(d))
end

issuccess(C::Cholesky) = C.info == 0

function show(io::IO, mime::MIME{Symbol("text/plain")}, C::Cholesky{<:Any,<:AbstractMatrix})
if issuccess(C)
println(io, summary(C), "\n$(C.uplo) factor:")
show(io, mime, C[:UL])
show(io, mime, C.UL)
else
print(io, "Failed factorization of type $(typeof(C))")
end
end

function show(io::IO, mime::MIME{Symbol("text/plain")}, C::CholeskyPivoted{<:Any,<:AbstractMatrix})
println(io, summary(C), "\n$(C.uplo) factor with rank $(rank(C)):")
show(io, mime, C.uplo == 'U' ? C[:U] : C[:L])
show(io, mime, C.uplo == 'U' ? C.U : C.L)
println(io, "\npermutation:")
show(io, mime, C[:p])
show(io, mime, C.p)
end

ldiv!(C::Cholesky{T,<:AbstractMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} =
Expand Down Expand Up @@ -534,8 +547,8 @@ rank(C::CholeskyPivoted) = C.rank
"""
lowrankupdate!(C::Cholesky, v::StridedVector) -> CC::Cholesky
Update a Cholesky factorization `C` with the vector `v`. If `A = C[:U]'C[:U]` then
`CC = cholfact(C[:U]'C[:U] + v*v')` but the computation of `CC` only uses `O(n^2)`
Update a Cholesky factorization `C` with the vector `v`. If `A = C.U'C.U` then
`CC = cholfact(C.U'C.U + v*v')` but the computation of `CC` only uses `O(n^2)`
operations. The input factorization `C` is updated in place such that on exit `C == CC`.
The vector `v` is destroyed during the computation.
"""
Expand Down Expand Up @@ -580,8 +593,8 @@ end
"""
lowrankdowndate!(C::Cholesky, v::StridedVector) -> CC::Cholesky
Downdate a Cholesky factorization `C` with the vector `v`. If `A = C[:U]'C[:U]` then
`CC = cholfact(C[:U]'C[:U] - v*v')` but the computation of `CC` only uses `O(n^2)`
Downdate a Cholesky factorization `C` with the vector `v`. If `A = C.U'C.U` then
`CC = cholfact(C.U'C.U - v*v')` but the computation of `CC` only uses `O(n^2)`
operations. The input factorization `C` is updated in place such that on exit `C == CC`.
The vector `v` is destroyed during the computation.
"""
Expand Down Expand Up @@ -633,17 +646,17 @@ end
"""
lowrankupdate(C::Cholesky, v::StridedVector) -> CC::Cholesky
Update a Cholesky factorization `C` with the vector `v`. If `A = C[:U]'C[:U]`
then `CC = cholfact(C[:U]'C[:U] + v*v')` but the computation of `CC` only uses
Update a Cholesky factorization `C` with the vector `v`. If `A = C.U'C.U`
then `CC = cholfact(C.U'C.U + v*v')` but the computation of `CC` only uses
`O(n^2)` operations.
"""
lowrankupdate(C::Cholesky, v::StridedVector) = lowrankupdate!(copy(C), copy(v))

"""
lowrankdowndate(C::Cholesky, v::StridedVector) -> CC::Cholesky
Downdate a Cholesky factorization `C` with the vector `v`. If `A = C[:U]'C[:U]`
then `CC = cholfact(C[:U]'C[:U] - v*v')` but the computation of `CC` only uses
Downdate a Cholesky factorization `C` with the vector `v`. If `A = C.U'C.U`
then `CC = cholfact(C.U'C.U - v*v')` but the computation of `CC` only uses
`O(n^2)` operations.
"""
lowrankdowndate(C::Cholesky, v::StridedVector) = lowrankdowndate!(copy(C), copy(v))
8 changes: 4 additions & 4 deletions base/linalg/dense.jl
Original file line number Diff line number Diff line change
Expand Up @@ -709,8 +709,8 @@ function sqrt(A::StridedMatrix{<:Real})
return triu!(parent(sqrt(UpperTriangular(A))))
else
SchurF = schurfact(complex(A))
R = triu!(parent(sqrt(UpperTriangular(SchurF[:T])))) # unwrapping unnecessary?
return SchurF[:vectors] * R * SchurF[:vectors]'
R = triu!(parent(sqrt(UpperTriangular(SchurF.T)))) # unwrapping unnecessary?
return SchurF.vectors * R * SchurF.vectors'
end
end
function sqrt(A::StridedMatrix{<:Complex})
Expand All @@ -723,8 +723,8 @@ function sqrt(A::StridedMatrix{<:Complex})
return triu!(parent(sqrt(UpperTriangular(A))))
else
SchurF = schurfact(A)
R = triu!(parent(sqrt(UpperTriangular(SchurF[:T])))) # unwrapping unnecessary?
return SchurF[:vectors] * R * SchurF[:vectors]'
R = triu!(parent(sqrt(UpperTriangular(SchurF.T)))) # unwrapping unnecessary?
return SchurF.vectors * R * SchurF.vectors'
end
end

Expand Down
27 changes: 10 additions & 17 deletions base/linalg/eigen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,6 @@ end
GeneralizedEigen(values::AbstractVector{V}, vectors::AbstractMatrix{T}) where {T,V} =
GeneralizedEigen{T,V,typeof(vectors),typeof(values)}(values, vectors)


function getindex(A::Union{Eigen,GeneralizedEigen}, d::Symbol)
d == :values && return A.values
d == :vectors && return A.vectors
throw(KeyError(d))
end

isposdef(A::Union{Eigen,GeneralizedEigen}) = isreal(A.values) && all(x -> x > 0, A.values)

"""
Expand Down Expand Up @@ -69,8 +62,8 @@ end
eigfact(A; permute::Bool=true, scale::Bool=true) -> Eigen
Computes the eigenvalue decomposition of `A`, returning an `Eigen` factorization object `F`
which contains the eigenvalues in `F[:values]` and the eigenvectors in the columns of the
matrix `F[:vectors]`. (The `k`th eigenvector can be obtained from the slice `F[:vectors][:, k]`.)
which contains the eigenvalues in `F.values` and the eigenvectors in the columns of the
matrix `F.vectors`. (The `k`th eigenvector can be obtained from the slice `F.vectors[:, k]`.)
The following functions are available for `Eigen` objects: [`inv`](@ref), [`det`](@ref), and [`isposdef`](@ref).
Expand All @@ -84,13 +77,13 @@ make rows and columns more equal in norm. The default is `true` for both options
julia> F = eigfact([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0])
Base.LinAlg.Eigen{Float64,Float64,Array{Float64,2},Array{Float64,1}}([1.0, 3.0, 18.0], [1.0 0.0 0.0; 0.0 1.0 0.0; 0.0 0.0 1.0])
julia> F[:values]
julia> F.values
3-element Array{Float64,1}:
1.0
3.0
18.0
julia> F[:vectors]
julia> F.vectors
3×3 Array{Float64,2}:
1.0 0.0 0.0
0.0 1.0 0.0
Expand Down Expand Up @@ -154,9 +147,9 @@ julia> eigvecs([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0])
"""
eigvecs(A::Union{Number, AbstractMatrix}; permute::Bool=true, scale::Bool=true) =
eigvecs(eigfact(A, permute=permute, scale=scale))
eigvecs(F::Union{Eigen{T,V,S,U}, GeneralizedEigen{T,V,S,U}}) where {T,V,S,U} = F[:vectors]::S
eigvecs(F::Union{Eigen, GeneralizedEigen}) = F.vectors

eigvals(F::Union{Eigen{T,V,S,U}, GeneralizedEigen{T,V,S,U}}) where {T,V,S,U} = F[:values]::U
eigvals(F::Union{Eigen, GeneralizedEigen}) = F.values

"""
eigvals!(A; permute::Bool=true, scale::Bool=true) -> values
Expand Down Expand Up @@ -352,8 +345,8 @@ end
Computes the generalized eigenvalue decomposition of `A` and `B`, returning a
`GeneralizedEigen` factorization object `F` which contains the generalized eigenvalues in
`F[:values]` and the generalized eigenvectors in the columns of the matrix `F[:vectors]`.
(The `k`th generalized eigenvector can be obtained from the slice `F[:vectors][:, k]`.)
`F.values` and the generalized eigenvectors in the columns of the matrix `F.vectors`.
(The `k`th generalized eigenvector can be obtained from the slice `F.vectors[:, k]`.)
# Examples
```jldoctest
Expand All @@ -369,12 +362,12 @@ julia> B = [0 1; 1 0]
julia> F = eigfact(A, B);
julia> F[:values]
julia> F.values
2-element Array{Complex{Float64},1}:
0.0 + 1.0im
0.0 - 1.0im
julia> F[:vectors]
julia> F.vectors
2×2 Array{Complex{Float64},2}:
0.0-1.0im 0.0+1.0im
-1.0-0.0im -1.0+0.0im
Expand Down
Loading

0 comments on commit badc334

Please sign in to comment.