Skip to content

Commit 7792727

Browse files
committed
use normal entrypoints into base's display pipeline
Base and SparseArrays had some funky interactions going on with replace_in_print_matrix, this fully disentangles the print funcs. it also makes SparseArrays smarter about swaping to braille, fixes aliasing, and generally makes printing more robust.
1 parent 751387e commit 7792727

1 file changed

Lines changed: 67 additions & 10 deletions

File tree

src/sparsematrix.jl

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -334,10 +334,7 @@ function Base.isstored(A::AdjOrTrans{<:Any,<:AbstractSparseMatrixCSC}, i::Intege
334334
return false
335335
end
336336

337-
Base.replace_in_print_matrix(A::AbstractSparseMatrixCSCInclAdjointAndTranspose, i::Integer, j::Integer, s::AbstractString) =
338-
Base.isstored(A, i, j) ? s : Base.replace_with_centered_mark(s)
339-
340-
function Base.array_summary(io::IO, S::AbstractSparseMatrixCSCInclAdjointAndTranspose, dims::Tuple{Vararg{Base.OneTo}})
337+
function Base.summary(io::IO, S::AbstractSparseMatrixCSCInclAdjointAndTranspose)
341338
_checkbuffers(S)
342339

343340
xnnz = nnz(S)
@@ -347,12 +344,23 @@ function Base.array_summary(io::IO, S::AbstractSparseMatrixCSCInclAdjointAndTran
347344
nothing
348345
end
349346

350-
# called by `show(io, MIME("text/plain"), ::AbstractSparseMatrixCSCInclAdjointAndTranspose)`
351-
function Base.print_array(io::IO, S::AbstractSparseMatrixCSCInclAdjointAndTranspose)
352-
if max(size(S)...) < 16
353-
Base.print_matrix(io, S)
354-
else
347+
using Base: show_circular
348+
function Base.show(io::IO, ::MIME"text/plain", S::AbstractSparseMatrixCSCInclAdjointAndTranspose)
349+
isempty(S) && get(io, :compact, false) && return show(io, S)
350+
summary(io, S)
351+
isempty(S) && return
352+
353+
screen = displaysize(io)
354+
get(io, :limit, false) && screen[1] <= 4 && return print(io, ": …")
355+
println(io, ":")
356+
357+
show_circular(io, S) && return
358+
io = IOContext(io, :compact=>true, :typeinfo=>eltype(S), :SHOWN_SET=>S)
359+
360+
if (screen[1] < size(S, 1) + 4) | (screen[2] < 3size(S, 2))
355361
_show_with_braille_patterns(io, S)
362+
else
363+
_show_with_dotted_zeros(io, S)
356364
end
357365
end
358366

@@ -405,7 +413,15 @@ function _show_with_braille_patterns(io::IO, S::AbstractSparseMatrixCSCInclAdjoi
405413
# The maximal number of characters we allow to display the matrix
406414
local maxHeight::Int, maxWidth::Int
407415
maxHeight = displaysize(io)[1] - 4 # -4 from [Prompt, header, newline after elements, new prompt]
408-
maxWidth = displaysize(io)[2] ÷ 2
416+
maxWidth = displaysize(io)[2] - 2 # -2 from brackets
417+
418+
warn = false
419+
try
420+
zero(eltype(S))
421+
catch
422+
warn = true
423+
maxHeight -= 1
424+
end
409425

410426
# In the process of generating the braille pattern to display the nonzero
411427
# structure of `S`, we need to be able to scale the matrix `S` to a
@@ -450,6 +466,13 @@ function _show_with_braille_patterns(io::IO, S::AbstractSparseMatrixCSCInclAdjoi
450466
rvals = rowvals(parent(S))
451467
rowscale = max(1, scaleHeight - 1) / max(1, m - 1)
452468
colscale = max(1, scaleWidth - 1) / max(1, n - 1)
469+
470+
if rowscale != 1 || colscale != 1
471+
print(io, " (downscaled to fit on screen)")
472+
end
473+
println(io, ":")
474+
warn && printstyled(stderr, "WARNING: could not find generic zero for given elements. expect errors and wrong results\n", color=:red)
475+
453476
if isa(S, AbstractSparseMatrixCSC)
454477
@inbounds for j in axes(S,2)
455478
# Scale the column index `j` to the best matching column index
@@ -489,6 +512,40 @@ function _show_with_braille_patterns(io::IO, S::AbstractSparseMatrixCSCInclAdjoi
489512
foreach(c -> print(io, Char(c)), @view brailleGrid[1:end-1])
490513
end
491514

515+
using Base: alignment
516+
function _show_with_dotted_zeros(io::IO, S::AbstractSparseMatrixCSCInclAdjointAndTranspose)
517+
rows, cols, vals = rowvals(parent(S)), ColumnIndices(parent(S)), nonzeros(parent(S))
518+
(S isa Adjoint) | (S isa Transpose) && ((rows, cols) = (cols, rows))
519+
520+
align = [isassigned(vals, ind) ? alignment(io, vals[ind]) : (3, 3) for ind in eachindex(vals)]
521+
colwidths = [max.((0, 0), align[findall(==(col), cols)]...) for col in axes(S,2)]
522+
displaysize(io)[2] < sum(sum.(colwidths) .+ 2) && return _show_with_braille_patterns(io, S)
523+
524+
try
525+
zero(eltype(S))
526+
catch
527+
printstyled(stderr, "WARNING: could not find generic zero for given elements. expect errors and wrong results\n", color=:red)
528+
end
529+
530+
for row in axes(S,1)
531+
for col in axes(S,2)
532+
index = findall(==(col), cols)
533+
index = index[findall(==(row), rows[index])]
534+
l, r = colwidths[col]
535+
if isempty(index) # no value here, print an aligned dot
536+
l, r = cld(l+r-1, 2) + 1, div(l+r-1, 2) + 1
537+
print(io, " "^l * "" * (col==axes(S,2)[end] ? "" : " "^r))
538+
else
539+
l, r = (l+1, r+1) .- align[index[]]
540+
print(io, " "^l)
541+
isassigned(vals, index[]) ? show(io, vals[index[]]) : print(io, "#undef")
542+
col == axes(S,2)[end] || print(io, " "^r)
543+
end
544+
end
545+
row == axes(S,1)[end] || println(io)
546+
end
547+
end
548+
492549
for QT in (:LinAlgLeftQs, :LQPackedQ)
493550
@eval (*)(Q::$QT, B::AbstractSparseMatrixCSC) = Q * Matrix(B)
494551
@eval (*)(Q::$QT, B::AdjOrTrans{<:Any,<:AbstractSparseMatrixCSC}) = Q * copy(B)

0 commit comments

Comments
 (0)