|
3 | 3 | #### Specialized matrix types ####
|
4 | 4 |
|
5 | 5 | ## (complex) symmetric tridiagonal matrices
|
6 |
| -struct SymTridiagonal{T} <: AbstractMatrix{T} |
7 |
| - dv::Vector{T} # diagonal |
8 |
| - ev::Vector{T} # subdiagonal |
9 |
| - function SymTridiagonal{T}(dv::Vector{T}, ev::Vector{T}) where T |
| 6 | +struct SymTridiagonal{T,V<:AbstractVector{T}} <: AbstractMatrix{T} |
| 7 | + dv::V # diagonal |
| 8 | + ev::V # subdiagonal |
| 9 | + function SymTridiagonal{T}(dv::V, ev::V) where {T,V<:AbstractVector{T}} |
10 | 10 | if !(length(dv) - 1 <= length(ev) <= length(dv))
|
11 | 11 | throw(DimensionMismatch("subdiagonal has wrong length. Has length $(length(ev)), but should be either $(length(dv) - 1) or $(length(dv))."))
|
12 | 12 | end
|
13 |
| - new(dv,ev) |
| 13 | + new{T,V}(dv,ev) |
14 | 14 | end
|
15 | 15 | end
|
16 | 16 |
|
17 | 17 | """
|
18 |
| - SymTridiagonal(dv, ev) |
| 18 | + SymTridiagonal(dv::V, ev::V) where V <: AbstractVector |
19 | 19 |
|
20 |
| -Construct a symmetric tridiagonal matrix from the diagonal and first sub/super-diagonal, |
21 |
| -respectively. The result is of type `SymTridiagonal` and provides efficient specialized |
22 |
| -eigensolvers, but may be converted into a regular matrix with |
23 |
| -[`convert(Array, _)`](@ref) (or `Array(_)` for short). |
| 20 | +Construct a symmetric tridiagonal matrix from the diagonal (`dv`) and first |
| 21 | +sub/super-diagonal (`ev`), respectively. The result is of type `SymTridiagonal` |
| 22 | +and provides efficient specialized eigensolvers, but may be converted into a |
| 23 | +regular matrix with [`convert(Array, _)`](@ref) (or `Array(_)` for short). |
24 | 24 |
|
25 | 25 | # Examples
|
26 | 26 | ```jldoctest
|
27 |
| -julia> dv = [1; 2; 3; 4] |
| 27 | +julia> dv = [1, 2, 3, 4] |
28 | 28 | 4-element Array{Int64,1}:
|
29 | 29 | 1
|
30 | 30 | 2
|
31 | 31 | 3
|
32 | 32 | 4
|
33 | 33 |
|
34 |
| -julia> ev = [7; 8; 9] |
| 34 | +julia> ev = [7, 8, 9] |
35 | 35 | 3-element Array{Int64,1}:
|
36 | 36 | 7
|
37 | 37 | 8
|
38 | 38 | 9
|
39 | 39 |
|
40 | 40 | julia> SymTridiagonal(dv, ev)
|
41 |
| -4×4 SymTridiagonal{Int64}: |
| 41 | +4×4 SymTridiagonal{Int64,Array{Int64,1}}: |
42 | 42 | 1 7 ⋅ ⋅
|
43 | 43 | 7 2 8 ⋅
|
44 | 44 | ⋅ 8 3 9
|
45 | 45 | ⋅ ⋅ 9 4
|
46 | 46 | ```
|
47 | 47 | """
|
48 |
| -SymTridiagonal(dv::Vector{T}, ev::Vector{T}) where {T} = SymTridiagonal{T}(dv, ev) |
| 48 | +SymTridiagonal(dv::V, ev::V) where {T,V<:AbstractVector{T}} = SymTridiagonal{T}(dv, ev) |
49 | 49 |
|
50 |
| -function SymTridiagonal(dv::AbstractVector{Td}, ev::AbstractVector{Te}) where {Td,Te} |
51 |
| - T = promote_type(Td,Te) |
52 |
| - SymTridiagonal(convert(Vector{T}, dv), convert(Vector{T}, ev)) |
53 |
| -end |
| 50 | +""" |
| 51 | + SymTridiagonal(A::AbstractMatrix) |
| 52 | +
|
| 53 | +Construct a symmetric tridiagonal matrix from the diagonal and |
| 54 | +first sub/super-diagonal, of the symmetric matrix `A`. |
54 | 55 |
|
| 56 | +# Examples |
| 57 | +```jldoctest |
| 58 | +julia> A = [1 2 3; 2 4 5; 3 5 6] |
| 59 | +3×3 Array{Int64,2}: |
| 60 | + 1 2 3 |
| 61 | + 2 4 5 |
| 62 | + 3 5 6 |
| 63 | +
|
| 64 | +julia> SymTridiagonal(A) |
| 65 | +3×3 SymTridiagonal{Int64,Array{Int64,1}}: |
| 66 | + 1 2 ⋅ |
| 67 | + 2 4 5 |
| 68 | + ⋅ 5 6 |
| 69 | +``` |
| 70 | +""" |
55 | 71 | function SymTridiagonal(A::AbstractMatrix)
|
56 | 72 | if diag(A,1) == diag(A,-1)
|
57 |
| - SymTridiagonal(diag(A), diag(A,1)) |
| 73 | + SymTridiagonal(diag(A,0), diag(A,1)) |
58 | 74 | else
|
59 | 75 | throw(ArgumentError("matrix is not symmetric; cannot convert to SymTridiagonal"))
|
60 | 76 | end
|
61 | 77 | end
|
62 | 78 |
|
63 | 79 | convert(::Type{SymTridiagonal{T}}, S::SymTridiagonal) where {T} =
|
64 |
| - SymTridiagonal(convert(Vector{T}, S.dv), convert(Vector{T}, S.ev)) |
| 80 | + SymTridiagonal(convert(AbstractVector{T}, S.dv), convert(AbstractVector{T}, S.ev)) |
65 | 81 | convert(::Type{AbstractMatrix{T}}, S::SymTridiagonal) where {T} =
|
66 |
| - SymTridiagonal(convert(Vector{T}, S.dv), convert(Vector{T}, S.ev)) |
67 |
| -function convert(::Type{Matrix{T}}, M::SymTridiagonal{T}) where T |
| 82 | + SymTridiagonal(convert(AbstractVector{T}, S.dv), convert(AbstractVector{T}, S.ev)) |
| 83 | +function convert(::Type{Matrix{T}}, M::SymTridiagonal) where T |
68 | 84 | n = size(M, 1)
|
69 | 85 | Mf = zeros(T, n, n)
|
70 | 86 | @inbounds begin
|
|
311 | 327 | # R. Usmani, "Inversion of a tridiagonal Jacobi matrix",
|
312 | 328 | # Linear Algebra and its Applications 212-213 (1994), pp.413-414
|
313 | 329 | # doi:10.1016/0024-3795(94)90414-6
|
314 |
| -function inv_usmani(a::Vector{T}, b::Vector{T}, c::Vector{T}) where T |
| 330 | +function inv_usmani(a::V, b::V, c::V) where {T,V<:AbstractVector{T}} |
315 | 331 | n = length(b)
|
316 | 332 | θ = ZeroOffsetVector(zeros(T, n+1)) #principal minors of A
|
317 | 333 | θ[0] = 1
|
|
341 | 357 |
|
342 | 358 | #Implements the determinant using principal minors
|
343 | 359 | #Inputs and reference are as above for inv_usmani()
|
344 |
| -function det_usmani(a::Vector{T}, b::Vector{T}, c::Vector{T}) where T |
| 360 | +function det_usmani(a::V, b::V, c::V) where {T,V<:AbstractVector{T}} |
345 | 361 | n = length(b)
|
346 | 362 | θa = one(T)
|
347 | 363 | if n == 0
|
@@ -635,7 +651,7 @@ convert(::Type{AbstractMatrix{T}},M::Tridiagonal) where {T} = convert(Tridiagona
|
635 | 651 | convert(::Type{Tridiagonal{T}}, M::SymTridiagonal{T}) where {T} = Tridiagonal(M)
|
636 | 652 | function convert(::Type{SymTridiagonal{T}}, M::Tridiagonal) where T
|
637 | 653 | if M.dl == M.du
|
638 |
| - return SymTridiagonal(convert(Vector{T},M.d), convert(Vector{T},M.dl)) |
| 654 | + return SymTridiagonal{T}(convert(AbstractVector{T},M.d), convert(AbstractVector{T},M.dl)) |
639 | 655 | else
|
640 | 656 | throw(ArgumentError("Tridiagonal is not symmetric, cannot convert to SymTridiagonal"))
|
641 | 657 | end
|
|
0 commit comments