From 3481277770da70d1a7cbc740e2b41ac53476ece1 Mon Sep 17 00:00:00 2001 From: Gabriel Joel Mitchell Date: Tue, 1 Dec 2015 00:35:04 -0800 Subject: [PATCH] added methods to allow for overriding of element printing in arrays --- base/abstractarray.jl | 3 +++ base/linalg/bidiag.jl | 10 ++++++++++ base/linalg/diagonal.jl | 7 +++++++ base/linalg/triangular.jl | 10 ++++++++++ base/linalg/tridiag.jl | 12 ++++++++++++ base/show.jl | 17 ++++++++++++++--- test/show.jl | 11 +++++++++++ 7 files changed, 67 insertions(+), 3 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 506da175ebb33..286d56279a2ed 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -706,6 +706,9 @@ end get(A::AbstractArray, I::RangeVecIntList, default) = get!(similar(A, typeof(default), map(length, I)...), A, I, default) +## structured matrix methods ## +replace_in_print_matrix(A::AbstractMatrix,i::Integer,j::Integer,s::AbstractString) = s +replace_in_print_matrix(A::AbstractVector,i::Integer,j::Integer,s::AbstractString) = s ## Concatenation ## diff --git a/base/linalg/bidiag.jl b/base/linalg/bidiag.jl index 7ae75eae513fb..c9544e041b59f 100644 --- a/base/linalg/bidiag.jl +++ b/base/linalg/bidiag.jl @@ -40,6 +40,16 @@ function getindex{T}(A::Bidiagonal{T}, i::Integer, j::Integer) i == j ? A.dv[i] : (A.isupper && (i == j-1)) || (!A.isupper && (i == j+1)) ? A.ev[min(i,j)] : zero(T) end + +## structured matrix methods ## +function Base.replace_in_print_matrix(A::Bidiagonal,i::Integer,j::Integer,s::AbstractString) + if A.isupper + i==j || i==j-1 ? s : Base.replace_with_centered_mark(s) + else + i==j || i==j+1 ? s : Base.replace_with_centered_mark(s) + end +end + #Converting from Bidiagonal to dense Matrix full{T}(M::Bidiagonal{T}) = convert(Matrix{T}, M) function convert{T}(::Type{Matrix{T}}, A::Bidiagonal) diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index 9ac67743a64ac..62ab64724d38a 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -51,6 +51,13 @@ function unsafe_setindex!(D::Diagonal, v, i::Int, j::Int) D end + +## structured matrix methods ## +function Base.replace_in_print_matrix(A::Diagonal,i::Integer,j::Integer,s::AbstractString) + i==j ? s : Base.replace_with_centered_mark(s) +end + + ishermitian{T<:Real}(D::Diagonal{T}) = true ishermitian(D::Diagonal) = all(D.diag .== real(D.diag)) issym(D::Diagonal) = true diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index d9961704fd26e..c9d2cc1e3b90e 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -159,6 +159,16 @@ function setindex!(A::UnitLowerTriangular, x, i::Integer, j::Integer) return A end + +## structured matrix methods ## +function Base.replace_in_print_matrix(A::UpperTriangular,i::Integer,j::Integer,s::AbstractString) + i<=j ? s : Base.replace_with_centered_mark(s) +end +function Base.replace_in_print_matrix(A::LowerTriangular,i::Integer,j::Integer,s::AbstractString) + i>=j ? s : Base.replace_with_centered_mark(s) +end + + istril(A::LowerTriangular) = true istril(A::UnitLowerTriangular) = true istriu(A::UpperTriangular) = true diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index b03a85bb02f1f..63a5098940f08 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -196,6 +196,12 @@ end getindex( a::ZeroOffsetVector, i) = a.data[i+1] setindex!(a::ZeroOffsetVector, x, i) = a.data[i+1]=x + +## structured matrix methods ## +function Base.replace_in_print_matrix(A::SymTridiagonal,i::Integer,j::Integer,s::AbstractString) + i==j-1||i==j||i==j+1 ? s : Base.replace_with_centered_mark(s) +end + #Implements the inverse using the recurrence relation between principal minors # a, b, c are assumed to be the subdiagonal, diagonal, and superdiagonal of # a tridiagonal matrix. @@ -375,6 +381,12 @@ function getindex{T}(A::Tridiagonal{T}, i::Integer, j::Integer) end end + +## structured matrix methods ## +function Base.replace_in_print_matrix(A::Tridiagonal,i::Integer,j::Integer,s::AbstractString) + i==j-1||i==j||i==j+1 ? s : Base.replace_with_centered_mark(s) +end + #tril and triu istriu(M::Tridiagonal) = all(M.dl .== 0) diff --git a/base/show.jl b/base/show.jl index 8a7596f87b08b..005aa28409075 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1125,6 +1125,17 @@ function alignment( return a end +""" +Unexported convenience function used in body of `replace_in_print_matrix` +methods. By default returns a string of the same width as original with a +centered cdot, used in printing of structural zeros of structured matrices. +Accept keyword args `c` for alternate single character marker. +""" +function replace_with_centered_mark(s::AbstractString;c::Char = '⋅') + N = length(s) + return join(setindex!([utf8(" ") for i=1:N],string(c),ceil(Int,N/2))) +end + """ `print_matrix_row(io, X, A, i, cols, sep)` produces the aligned output for a single matrix row X[i, cols] where the desired list of columns is given. @@ -1134,8 +1145,7 @@ is specified as string sep. """ function print_matrix_row(io::IO, X::AbstractVecOrMat, A::Vector, - i::Integer, cols::AbstractVector, sep::AbstractString -) + i::Integer, cols::AbstractVector, sep::AbstractString) for k = 1:length(A) j = cols[k] if isassigned(X,Int(i),Int(j)) # isassigned accepts only `Int` indices @@ -1148,7 +1158,8 @@ function print_matrix_row(io::IO, end l = repeat(" ", A[k][1]-a[1]) # pad on left and right as needed r = repeat(" ", A[k][2]-a[2]) - print(io, l, sx, r) + prettysx = replace_in_print_matrix(X,i,j,sx) + print(io, l, prettysx, r) if k < length(A); print(io, sep); end end end diff --git a/test/show.jl b/test/show.jl index 9bad23bdef002..4130943a57d64 100644 --- a/test/show.jl +++ b/test/show.jl @@ -339,9 +339,20 @@ end # Issue 14121 @test_repr "(A'x)'" + # issue #14481 @test_repr "in(1,2,3)" @test_repr "<(1,2,3)" @test_repr "+(1,2,3)" @test_repr "-(1,2,3)" @test_repr "*(1,2,3)" + +# test structured zero matrix printing for select structured types +A = reshape(1:16,4,4) +@test replstr(Diagonal(A)) == "4x4 Diagonal{$Int}:\n 1 ⋅ ⋅ ⋅\n ⋅ 6 ⋅ ⋅\n ⋅ ⋅ 11 ⋅\n ⋅ ⋅ ⋅ 16" +@test replstr(Bidiagonal(A,true)) == "4x4 Bidiagonal{$Int}:\n 1 5 ⋅ ⋅\n ⋅ 6 10 ⋅\n ⋅ ⋅ 11 15\n ⋅ ⋅ ⋅ 16" +@test replstr(Bidiagonal(A,false)) == "4x4 Bidiagonal{$Int}:\n 1 ⋅ ⋅ ⋅\n 2 6 ⋅ ⋅\n ⋅ 7 11 ⋅\n ⋅ ⋅ 12 16" +@test replstr(SymTridiagonal(A+A')) == "4x4 SymTridiagonal{$Int}:\n 2 7 ⋅ ⋅\n 7 12 17 ⋅\n ⋅ 17 22 27\n ⋅ ⋅ 27 32" +@test replstr(Tridiagonal(diag(A,-1),diag(A),diag(A,+1))) == "4x4 Tridiagonal{$Int}:\n 1 5 ⋅ ⋅\n 2 6 10 ⋅\n ⋅ 7 11 15\n ⋅ ⋅ 12 16" +@test replstr(UpperTriangular(A)) == "4x4 UpperTriangular{$Int,Array{$Int,2}}:\n 1 5 9 13\n ⋅ 6 10 14\n ⋅ ⋅ 11 15\n ⋅ ⋅ ⋅ 16" +@test replstr(LowerTriangular(A)) == "4x4 LowerTriangular{$Int,Array{$Int,2}}:\n 1 ⋅ ⋅ ⋅\n 2 6 ⋅ ⋅\n 3 7 11 ⋅\n 4 8 12 16"