|
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