Skip to content

Instantly share code, notes, and snippets.

@maxbennedich
Last active January 16, 2019 14:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maxbennedich/5d32bf7fa94f1763f5362618067aef01 to your computer and use it in GitHub Desktop.
Save maxbennedich/5d32bf7fa94f1763f5362618067aef01 to your computer and use it in GitHub Desktop.
Braille plot sparse show
const BRAILLE = split("⠀⠁⠂⠄⡀⠈⠐⠠⢀", "") .|> s -> Int(s[1])
function show_any_nonzero(S::SparseMatrixCSC; maxw = displaysize(stdout)[2], maxh = displaysize(stdout)[1]-3)
h,w = size(S)
h > 4maxh && (w = max(1, (w*4maxh+h÷2)÷h); h = 4maxh)
w > 2maxw && (h = max(1, (h*2maxw+w÷2)÷w); w = 2maxw)
P = fill(BRAILLE[1], (w+3)÷2, (h+3)÷4)
P[end, :].=10
@inbounds for c = 0:w-1, r = 0:h-1
_anynz(S, r*S.m÷h+1, c*S.n÷w+1, (r+1)*S.m÷h, (c+1)*S.n÷w) &&
(P[c÷2+1, r÷4+1] |= BRAILLE[4c&4+r&3+2])
end
print(join(Char.(P)) * "nz = $(nnz(S))")
end
function show_any_nonzero_loop_nz(S::SparseMatrixCSC; maxw = displaysize(stdout)[2], maxh = displaysize(stdout)[1]-3)
h,w = size(S)
h > 4maxh && (w = max(1, (w*4maxh+h÷2)÷h); h = 4maxh)
w > 2maxw && (h = max(1, (h*2maxw+w÷2)÷w); w = 2maxw)
P = fill(BRAILLE[1], (w+3)÷2, (h+3)÷4)
P[end, :].=10
@inbounds for c = 1:S.n
for k in nzrange(S, c)
x = (c-1)*w÷S.n
y = (S.rowval[k]-1)*h÷S.m
P[1+x÷2,1+y÷4] |= BRAILLE[4x&4+y&3+2]
end
end
print(join(Char.(P)) * "nz = $(nnz(S))")
end
function show_above_median_nonzero(S::SparseMatrixCSC; maxw = displaysize(stdout)[2], maxh = displaysize(stdout)[1]-3)
h,w = size(S)
h > 4maxh && (w = max(1, (w*4maxh+h÷2)÷h); h = 4maxh)
w > 2maxw && (h = max(1, (h*2maxw+w÷2)÷w); w = 2maxw)
P = fill(BRAILLE[1], (w+3)÷2, (h+3)÷4)
P[end, :].=10
med = mediancount(S, h, w)
@inbounds for c = 0:w-1, r = 0:h-1
_gtnz(S, r*S.m÷h+1, c*S.n÷w+1, (r+1)*S.m÷h, (c+1)*S.n÷w, med) &&
(P[c÷2+1, r÷4+1] |= BRAILLE[4c&4+r&3+2])
end
print(join(Char.(P)) * "nz = $(nnz(S))")
end
function mediancount(S::SparseMatrixCSC, h, w)
counts = Vector{Int}(undef, w*h)
@inbounds for c = 0:w-1, r = 0:h-1
counts[r*w+c+1] = _count(S, r*S.m÷h+1, c*S.n÷w+1, (r+1)*S.m÷h, (c+1)*S.n÷w)
end
trunc(Int, median!(counts))
end
function _anynz(S::SparseMatrixCSC, r1, c1, r2, c2)
@inbounds for c = c1:c2
k = searchsortedfirst(S.rowval, r1, S.colptr[c], S.colptr[c+1]-1, Base.Order.Forward)
k != S.colptr[c+1] && S.rowval[k] ≤ r2 && return true
end
false
end
function _gtnz(S::SparseMatrixCSC, r1, c1, r2, c2, m)
count = 0
@inbounds for c = c1:c2
for k = searchsortedfirst(S.rowval, r1, S.colptr[c], S.colptr[c+1]-1, Base.Order.Forward):S.colptr[c+1]-1
S.rowval[k] > r2 && break
(count += 1) > m && return true
end
end
false
end
function _count(S::SparseMatrixCSC, r1, c1, r2, c2)
count = 0
@inbounds for c = c1:c2
for k = searchsortedfirst(S.rowval, r1, S.colptr[c], S.colptr[c+1]-1, Base.Order.Forward):S.colptr[c+1]-1
S.rowval[k] > r2 && break
count += 1
end
end
count
end
@stev47
Copy link

stev47 commented Jan 16, 2019

For the loop_nz variant you may put x = outside the inner loop.
Also counting non-zeros into a preallocated bucket = zeros(Int, h, w) and writing the characters separately shaves of a bit (trading a small amount of memory though).
That is especially performant in the median variant, where the median can now be calculated using the bucket counts instead of the whole matrix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment