@@ -406,106 +406,46 @@ end
406406
407407const brailleBlocks = UInt16[' ⠁' , ' ⠂' , ' ⠄' , ' ⡀' , ' ⠈' , ' ⠐' , ' ⠠' , ' ⢀' ]
408408function _show_with_braille_patterns (io:: IO , S:: AbstractSparseMatrixCSCInclAdjointAndTranspose )
409+ # The maximum number of characters we allow to display the matrix
410+ h, w = get (io, :limit , false ) ? displaysize (io) .- (4 , 2 ) : (typemax (Int)÷ 4 , typemax (Int)÷ 2 )
409411 m, n = size (S)
410- (m == 0 || n == 0 ) && return show (io, MIME (" text/plain" ), S)
411-
412- # The maximal number of characters we allow to display the matrix
413- local maxHeight:: Int , maxWidth:: Int
414- maxHeight = displaysize (io)[1 ] - 4 # -4 from [Prompt, header, newline after elements, new prompt]
415- maxWidth = displaysize (io)[2 ] - 2 # -2 from brackets
416412
417413 warn = false
418414 try
419415 zero (eltype (S))
420416 catch
421417 warn = true
422- maxHeight -= 1
423- end
424-
425- # In the process of generating the braille pattern to display the nonzero
426- # structure of `S`, we need to be able to scale the matrix `S` to a
427- # smaller matrix with the same aspect ratio as `S`, but fits on the
428- # available screen space. The size of that smaller matrix is stored
429- # in the variables `scaleHeight` and `scaleWidth`. If no scaling is needed,
430- # we can use the size `m × n` of `S` directly.
431- # We determine if scaling is needed and set the scaling factors
432- # `scaleHeight` and `scaleWidth` accordingly. Note that each available
433- # character can contain up to 4 braille dots in its height (⡇) and up to
434- # 2 braille dots in its width (⠉).
435- if get (io, :limit , false ) && (m > 4 maxHeight || n > 2 maxWidth)
436- s = min (2 maxWidth / n, 4 maxHeight / m)
437- scaleHeight = floor (Int, s * m)
438- scaleWidth = floor (Int, s * n)
439- else
440- scaleHeight = m
441- scaleWidth = n
442- end
443-
444- # Make sure that the matrix size is big enough to be able to display all
445- # the corner border characters
446- if scaleHeight < 8
447- scaleHeight = 8
448- end
449- if scaleWidth < 4
450- scaleWidth = 4
418+ h -= 1
451419 end
452420
453- # `brailleGrid` is used to store the needed braille characters for
454- # the matrix `S`. Each row of the braille pattern to print is stored
455- # in a column of `brailleGrid`.
456- brailleGrid = fill (UInt16 (10240 ), (scaleWidth - 1 ) ÷ 2 + 4 , (scaleHeight - 1 ) ÷ 4 + 1 )
457- brailleGrid[1 ,:] .= ' ⎢'
458- brailleGrid[end - 1 ,:] .= ' ⎥'
459- brailleGrid[1 ,1 ] = ' ⎡'
460- brailleGrid[1 ,end ] = ' ⎣'
461- brailleGrid[end - 1 ,1 ] = ' ⎤'
462- brailleGrid[end - 1 ,end ] = ' ⎦'
463- brailleGrid[end , :] .= ' \n '
464-
465- rvals = rowvals (parent (S))
466- rowscale = max (1 , scaleHeight - 1 ) / max (1 , m - 1 )
467- colscale = max (1 , scaleWidth - 1 ) / max (1 , n - 1 )
421+ # In order to prevent aliasing, we only scale down by full integers.
422+ # While 1 to 1/2 is a big jump, it's less noticeable as you get bigger.
423+ # Note each character has 4 dots of height and 2 dots of width.
424+ scale = max (n÷ 2 w, m÷ 4 h) + 1
425+ char_h, char_w = fld1 (m, 4 scale), fld1 (n, 2 scale)
468426
469- if rowscale != 1 || colscale != 1
470- print (io, " (downscaled to fit on screen)" )
471- end
427+ scale != 1 && print (io, " (displaying at 1/$scale scale)" )
472428 println (io, " :" )
473429 warn && printstyled (stderr , " WARNING: could not find generic zero for given elements. expect errors and wrong results\n " , color= :red )
474430
475- if isa (S, AbstractSparseMatrixCSC)
476- @inbounds for j in axes (S,2 )
477- # Scale the column index `j` to the best matching column index
478- # of a matrix of size `scaleHeight × scaleWidth`
479- sj = round (Int, (j - 1 ) * colscale + 1 )
480- for x in nzrange (S, j)
481- # Scale the row index `i` to the best matching row index
482- # of a matrix of size `scaleHeight × scaleWidth`
483- si = round (Int, (rvals[x] - 1 ) * rowscale + 1 )
484-
485- # Given the index pair `(si, sj)` of the scaled matrix,
486- # calculate the corresponding triple `(k, l, p)` such that the
487- # element at `(si, sj)` can be found at position `(k, l)` in the
488- # braille grid `brailleGrid` and corresponds to the 1-dot braille
489- # character `brailleBlocks[p]`
490- k = (sj - 1 ) ÷ 2 + 2
491- l = (si - 1 ) ÷ 4 + 1
492- p = ((sj - 1 ) % 2 ) * 4 + ((si - 1 ) % 4 + 1 )
493-
494- brailleGrid[k, l] |= brailleBlocks[p]
495- end
431+ # Rows of output are cols of `brailleGrid` since julia is column-major
432+ brailleGrid = fill (UInt16 (10240 ), char_w + 3 , char_h)
433+ brailleGrid[[1 ,end - 1 ,end ],:] .= [' ⎢' , ' ⎥' , ' \n ' ]
434+ brailleGrid[[1 ,end - 1 ],[1 ,end ]] .= [' ⎡' ' ⎣' ;' ⎤' ' ⎦' ]
435+ char_h == 1 && (brailleGrid[[1 ,end - 1 ],1 ] .= [' [' , ' ]' ])
436+
437+ rinds = rowvals (parent (S))
438+ cinds = ColumnIndices (parent (S))
439+
440+ if S isa AbstractSparseMatrixCSC
441+ for cords in zip (rinds, cinds)
442+ row, col = fld1 .(cords, scale) |> x-> fldmod1 .(x, (4 , 2 ))
443+ brailleGrid[col[1 ]+ 1 , row[1 ]] |= brailleBlocks[row[2 ] + 4 (col[2 ]- 1 )]
496444 end
497- else
498- # If `S` is a adjoint or transpose of a sparse matrix we invert the
499- # roles of the indices `i` and `j`
500- @inbounds for i = 1 : m
501- si = round (Int, (i - 1 ) * rowscale + 1 )
502- for x in nzrange (parent (S), i)
503- sj = round (Int, (rvals[x] - 1 ) * colscale + 1 )
504- k = (sj - 1 ) ÷ 2 + 2
505- l = (si - 1 ) ÷ 4 + 1
506- p = ((sj - 1 ) % 2 ) * 4 + ((si - 1 ) % 4 + 1 )
507- brailleGrid[k, l] |= brailleBlocks[p]
508- end
445+ else # swap rows / cols for adj and transpose
446+ for cords in zip (rinds, cinds)
447+ col, row = fld1 .(cords, scale) |> x-> fldmod1 .(x, (2 , 4 ))
448+ brailleGrid[col[1 ]+ 1 , row[1 ]] |= brailleBlocks[row[2 ] + 4 (col[2 ]- 1 )]
509449 end
510450 end
511451 foreach (c -> print (io, Char (c)), @view brailleGrid[1 : end - 1 ])
0 commit comments