Add: julia-0.6.2
Former-commit-id: ccc667cf67d569f3fb3df39aa57c2134755a7551
This commit is contained in:
91
julia-0.6.2/share/julia/base/linalg/ldlt.jl
Normal file
91
julia-0.6.2/share/julia/base/linalg/ldlt.jl
Normal file
@@ -0,0 +1,91 @@
|
||||
# This file is a part of Julia. License is MIT: https://julialang.org/license
|
||||
|
||||
struct LDLt{T,S<:AbstractMatrix} <: Factorization{T}
|
||||
data::S
|
||||
end
|
||||
|
||||
size(S::LDLt) = size(S.data)
|
||||
size(S::LDLt, i::Integer) = size(S.data, i)
|
||||
|
||||
convert(::Type{LDLt{T,S}}, F::LDLt) where {T,S} = LDLt{T,S}(convert(S, F.data))
|
||||
# NOTE: the annotaion <:AbstractMatrix shouldn't be necessary, it is introduced
|
||||
# to avoid an ambiguity warning (see issue #6383)
|
||||
convert(::Type{LDLt{T}}, F::LDLt{S,U}) where {T,S,U<:AbstractMatrix} = convert(LDLt{T,U}, F)
|
||||
|
||||
convert(::Type{Factorization{T}}, F::LDLt{T}) where {T} = F
|
||||
convert(::Type{Factorization{T}}, F::LDLt{S,U}) where {T,S,U} = convert(LDLt{T,U}, F)
|
||||
|
||||
# SymTridiagonal
|
||||
"""
|
||||
ldltfact!(S::SymTridiagonal) -> LDLt
|
||||
|
||||
Same as [`ldltfact`](@ref), but saves space by overwriting the input `A`, instead of creating a copy.
|
||||
"""
|
||||
function ldltfact!(S::SymTridiagonal{T}) where T<:Real
|
||||
n = size(S,1)
|
||||
d = S.dv
|
||||
e = S.ev
|
||||
@inbounds @simd for i = 1:n-1
|
||||
e[i] /= d[i]
|
||||
d[i+1] -= abs2(e[i])*d[i]
|
||||
end
|
||||
return LDLt{T,SymTridiagonal{T}}(S)
|
||||
end
|
||||
|
||||
"""
|
||||
ldltfact(S::SymTridiagonal) -> LDLt
|
||||
|
||||
Compute an `LDLt` factorization of a real symmetric tridiagonal matrix such that `A = L*Diagonal(d)*L'`
|
||||
where `L` is a unit lower triangular matrix and `d` is a vector. The main use of an `LDLt`
|
||||
factorization `F = ldltfact(A)` is to solve the linear system of equations `Ax = b` with `F\\b`.
|
||||
"""
|
||||
function ldltfact(M::SymTridiagonal{T}) where T
|
||||
S = typeof(zero(T)/one(T))
|
||||
return S == T ? ldltfact!(copy(M)) : ldltfact!(convert(SymTridiagonal{S}, M))
|
||||
end
|
||||
|
||||
factorize(S::SymTridiagonal) = ldltfact(S)
|
||||
|
||||
function A_ldiv_B!(S::LDLt{T,SymTridiagonal{T}}, B::AbstractVecOrMat{T}) where T
|
||||
n, nrhs = size(B, 1), size(B, 2)
|
||||
if size(S,1) != n
|
||||
throw(DimensionMismatch("Matrix has dimensions $(size(S)) but right hand side has first dimension $n"))
|
||||
end
|
||||
d = S.data.dv
|
||||
l = S.data.ev
|
||||
@inbounds begin
|
||||
for i = 2:n
|
||||
li1 = l[i-1]
|
||||
@simd for j = 1:nrhs
|
||||
B[i,j] -= li1*B[i-1,j]
|
||||
end
|
||||
end
|
||||
dn = d[n]
|
||||
@simd for j = 1:nrhs
|
||||
B[n,j] /= dn
|
||||
end
|
||||
for i = n-1:-1:1
|
||||
di = d[i]
|
||||
li = l[i]
|
||||
@simd for j = 1:nrhs
|
||||
B[i,j] /= di
|
||||
B[i,j] -= li*B[i+1,j]
|
||||
end
|
||||
end
|
||||
end
|
||||
return B
|
||||
end
|
||||
|
||||
# Conversion methods
|
||||
function convert(::Type{SymTridiagonal}, F::LDLt)
|
||||
e = copy(F.data.ev)
|
||||
d = copy(F.data.dv)
|
||||
e .*= d[1:end-1]
|
||||
d[2:end] += e .* F.data.ev
|
||||
SymTridiagonal(d, e)
|
||||
end
|
||||
convert(::Type{AbstractMatrix}, F::LDLt) = convert(SymTridiagonal, F)
|
||||
convert(::Type{AbstractArray}, F::LDLt) = convert(AbstractMatrix, F)
|
||||
convert(::Type{Matrix}, F::LDLt) = convert(Array, convert(AbstractArray, F))
|
||||
convert(::Type{Array}, F::LDLt) = convert(Matrix, F)
|
||||
full(F::LDLt) = convert(AbstractArray, F)
|
||||
Reference in New Issue
Block a user