Skip to content

Commit 86231ce

Browse files
authored
LinearAlgebra: round-trippable 2-argument show for Tridiagonal/SymTridiagonal (#55415)
This makes the displayed form of a `Tridiaognal` and a `SymTridiagonal` valid constructors. ```julia julia> T = Tridiagonal(1:3, 1:4, 1:3) 4×4 Tridiagonal{Int64, UnitRange{Int64}}: 1 1 ⋅ ⋅ 1 2 2 ⋅ ⋅ 2 3 3 ⋅ ⋅ 3 4 julia> show(T) Tridiagonal(1:3, 1:4, 1:3) julia> S = SymTridiagonal(1:4, 1:3) 4×4 SymTridiagonal{Int64, UnitRange{Int64}}: 1 1 ⋅ ⋅ 1 2 2 ⋅ ⋅ 2 3 3 ⋅ ⋅ 3 4 julia> show(S) SymTridiagonal(1:4, 1:3) ``` Displaying the bands has several advantages: firstly, it's briefer than printing the full array, and secondly, it displays the special structure in the bands, if any. E.g.: ```julia julia> T = Tridiagonal(spzeros(3), spzeros(4), spzeros(3)); julia> show(T) Tridiagonal(sparsevec(Int64[], Float64[], 3), sparsevec(Int64[], Float64[], 4), sparsevec(Int64[], Float64[], 3)) ``` It's clear from the displayed form that `T` has sparse bands. A special handling for `SymTridiagonal` matrices is necessary, as the diagonal band is symmetrized. This means: ```julia julia> using StaticArrays julia> m = SMatrix{2,2}(1:4); julia> S = SymTridiagonal(fill(m,3), fill(m,2)) 3×3 SymTridiagonal{SMatrix{2, 2, Int64, 4}, Vector{SMatrix{2, 2, Int64, 4}}}: [1 3; 3 4] [1 3; 2 4] ⋅ [1 2; 3 4] [1 3; 3 4] [1 3; 2 4] ⋅ [1 2; 3 4] [1 3; 3 4] julia> show(S) SymTridiagonal(SMatrix{2, 2, Int64, 4}[[1 3; 3 4], [1 3; 3 4], [1 3; 3 4]], SMatrix{2, 2, Int64, 4}[[1 3; 2 4], [1 3; 2 4]]) ``` The displayed values correspond to the symmetrized band, and not the actual input arguments. I think displaying the symmetrized elements makes more sense here, as this matches the form in the 3-argument `show`.
1 parent 7ec39e7 commit 86231ce

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

stdlib/LinearAlgebra/src/tridiag.jl

+18
Original file line numberDiff line numberDiff line change
@@ -1045,3 +1045,21 @@ function _copyto_banded!(A::SymTridiagonal, B::Tridiagonal)
10451045
_evview(A) .= B.du
10461046
return A
10471047
end
1048+
1049+
# display
1050+
function show(io::IO, T::Tridiagonal)
1051+
print(io, "Tridiagonal(")
1052+
show(io, T.dl)
1053+
print(io, ", ")
1054+
show(io, T.d)
1055+
print(io, ", ")
1056+
show(io, T.du)
1057+
print(io, ")")
1058+
end
1059+
function show(io::IO, S::SymTridiagonal)
1060+
print(io, "SymTridiagonal(")
1061+
show(io, eltype(S) <: Number ? S.dv : view(S, diagind(S, IndexStyle(S))))
1062+
print(io, ", ")
1063+
show(io, S.ev)
1064+
print(io, ")")
1065+
end

stdlib/LinearAlgebra/test/tridiag.jl

+16
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ using .Main.FillArrays
1818
isdefined(Main, :OffsetArrays) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "OffsetArrays.jl"))
1919
using .Main.OffsetArrays
2020

21+
isdefined(Main, :SizedArrays) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "SizedArrays.jl"))
22+
using .Main.SizedArrays
23+
2124
include("testutils.jl") # test_approx_eq_modphase
2225

2326
#Test equivalence of eigenvectors/singular vectors taking into account possible phase (sign) differences
@@ -914,4 +917,17 @@ end
914917
end
915918
end
916919

920+
@testset "show" begin
921+
T = Tridiagonal(1:3, 1:4, 1:3)
922+
@test sprint(show, T) == "Tridiagonal(1:3, 1:4, 1:3)"
923+
S = SymTridiagonal(1:4, 1:3)
924+
@test sprint(show, S) == "SymTridiagonal(1:4, 1:3)"
925+
926+
m = SizedArrays.SizedArray{(2,2)}(reshape([1:4;],2,2))
927+
T = Tridiagonal(fill(m,2), fill(m,3), fill(m,2))
928+
@test sprint(show, T) == "Tridiagonal($(repr(diag(T,-1))), $(repr(diag(T))), $(repr(diag(T,1))))"
929+
S = SymTridiagonal(fill(m,3), fill(m,2))
930+
@test sprint(show, S) == "SymTridiagonal($(repr(diag(S))), $(repr(diag(S,1))))"
931+
end
932+
917933
end # module TestTridiagonal

0 commit comments

Comments
 (0)