Skip to content

Commit

Permalink
Merge pull request #13732 from gajomi/structuredmatrixprinting
Browse files Browse the repository at this point in the history
General method for modifying printing of elements in arrays
  • Loading branch information
andreasnoack committed Jan 9, 2016
2 parents 0a1a612 + 3481277 commit dc5c974
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 3 deletions.
3 changes: 3 additions & 0 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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 ##

Expand Down
10 changes: 10 additions & 0 deletions base/linalg/bidiag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
7 changes: 7 additions & 0 deletions base/linalg/diagonal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions base/linalg/triangular.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions base/linalg/tridiag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down
17 changes: 14 additions & 3 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,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.
Expand All @@ -1135,8 +1146,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
Expand All @@ -1149,7 +1159,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
Expand Down
11 changes: 11 additions & 0 deletions test/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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"

0 comments on commit dc5c974

Please sign in to comment.