From 7084d3858be78547db6424e7bdfce6197f252a21 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 10 Jan 2021 22:19:39 -0500 Subject: [PATCH 1/3] Improve (no)specialization in print_matrix It makes sense to extract the axes before we lose inferrability of the vector or matrix being printed. Hence this delays application of `@nospecialize`. However, it also standardizes the row/column indices and reduces specialization in `alignment`. --- base/arrayshow.jl | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/base/arrayshow.jl b/base/arrayshow.jl index 37adaf13f669e..7bf01333e7eb9 100644 --- a/base/arrayshow.jl +++ b/base/arrayshow.jl @@ -57,7 +57,7 @@ Parameter `sep::Integer` is number of spaces to put between elements. Alignment is reported as a vector of (left,right) tuples, one for each column going across the screen. """ -function alignment(io::IO, X::AbstractVecOrMat, +function alignment(io::IO, @nospecialize(X::AbstractVecOrMat), rows::AbstractVector{T}, cols::AbstractVector{V}, cols_if_complete::Integer, cols_otherwise::Integer, sep::Integer) where {T,V} a = Tuple{T, V}[] @@ -94,7 +94,7 @@ is specified as string sep. `print_matrix_row` will also respect compact output for elements. """ function print_matrix_row(io::IO, - X::AbstractVecOrMat, A::Vector, + @nospecialize(X::AbstractVecOrMat), A::Vector, i::Integer, cols::AbstractVector, sep::AbstractString) for (k, j) = enumerate(cols) k > length(A) && break @@ -158,7 +158,7 @@ string post (printed at the end of the last row of the matrix). Also options to use different ellipsis characters hdots, vdots, ddots. These are repeated every hmod or vmod elements. """ -function print_matrix(io::IO, @nospecialize(X::AbstractVecOrMat), +function print_matrix(io::IO, X::AbstractVecOrMat, pre::AbstractString = " ", # pre-matrix string sep::AbstractString = " ", # separator between elements post::AbstractString = "", # post-matrix string @@ -191,12 +191,16 @@ function _print_matrix(io, @nospecialize(X::AbstractVecOrMat), pre, sep, post, h halfheight = div(screenheight,2) if m > screenheight rowsA = [rowsA[(0:halfheight-1) .+ firstindex(rowsA)]; rowsA[(end-div(screenheight-1,2)+1):end]] + else + rowsA = [rowsA;] end # Similarly for columns, only necessary to get alignments for as many # columns as could conceivably fit across the screen maxpossiblecols = div(screenwidth, 1+sepsize) if n > maxpossiblecols colsA = [colsA[(0:maxpossiblecols-1) .+ firstindex(colsA)]; colsA[(end-maxpossiblecols+1):end]] + else + colsA = [colsA;] end A = alignment(io, X, rowsA, colsA, screenwidth, screenwidth, sepsize) # Nine-slicing is accomplished using print_matrix_row repeatedly @@ -268,12 +272,15 @@ end # typeinfo agnostic # n-dimensional arrays -function show_nd(io::IO, a::AbstractArray, print_matrix::Function, label_slices::Bool) +show_nd(io::IO, a::AbstractArray, print_matrix::Function, label_slices::Bool) = + invokelatest(_show_nd, io, a, print_matrix, label_slices, map(unitrange, axes(a))) + +function _show_nd(io::IO, @nospecialize(a::AbstractArray), print_matrix::Function, label_slices::Bool, axs::Tuple{Vararg{AbstractUnitRange}}) limit::Bool = get(io, :limit, false) if isempty(a) return end - tailinds = tail(tail(axes(a))) + tailinds = tail(tail(axs)) nd = ndims(a)-2 for I in CartesianIndices(tailinds) idxs = I.I @@ -284,7 +291,7 @@ function show_nd(io::IO, a::AbstractArray, print_matrix::Function, label_slices: if length(ind) > 10 if ii == ind[firstindex(ind)+3] && all(d->idxs[d]==first(tailinds[d]),1:i-1) for j=i+1:nd - szj = length(axes(a, j+2)) + szj = length(axs[j+2]) indj = tailinds[j] if szj>10 && first(indj)+2 < idxs[j] <= last(indj)-3 @goto skip @@ -302,7 +309,7 @@ function show_nd(io::IO, a::AbstractArray, print_matrix::Function, label_slices: if label_slices _show_nd_label(io, a, idxs) end - slice = view(a, axes(a,1), axes(a,2), idxs...) + slice = view(a, axs[1], axs[2], idxs...) print_matrix(io, slice) print(io, idxs == map(last,tailinds) ? "" : "\n\n") @label skip @@ -379,10 +386,13 @@ end `_show_nonempty(io, X::AbstractMatrix, prefix)` prints matrix X with opening and closing square brackets, preceded by `prefix`, supposed to encode the type of the elements. """ -function _show_nonempty(io::IO, X::AbstractMatrix, prefix::String) +_show_nonempty(io::IO, X::AbstractMatrix, prefix::String) = + _show_nonempty(io, inferencebarrier(X), prefix, axes(X)) + +function _show_nonempty(io::IO, @nospecialize(X::AbstractMatrix), prefix::String, axs::Tuple{AbstractUnitRange,AbstractUnitRange}) @assert !isempty(X) limit = get(io, :limit, false)::Bool - indr, indc = axes(X,1), axes(X,2) + indr, indc = axs nr, nc = length(indr), length(indc) rdots, cdots = false, false rr1, rr2 = UnitRange{Int}(indr), 1:0 From bcb6fd57ea0a8843cec929b605272bb739ded1b5 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 12 Jan 2021 08:43:27 -0600 Subject: [PATCH 2/3] Update base/arrayshow.jl Co-authored-by: Kristoffer Carlsson --- base/arrayshow.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/arrayshow.jl b/base/arrayshow.jl index 7bf01333e7eb9..36421cbbfb981 100644 --- a/base/arrayshow.jl +++ b/base/arrayshow.jl @@ -200,7 +200,7 @@ function _print_matrix(io, @nospecialize(X::AbstractVecOrMat), pre, sep, post, h if n > maxpossiblecols colsA = [colsA[(0:maxpossiblecols-1) .+ firstindex(colsA)]; colsA[(end-maxpossiblecols+1):end]] else - colsA = [colsA;] + colsA = [colsA;] end A = alignment(io, X, rowsA, colsA, screenwidth, screenwidth, sepsize) # Nine-slicing is accomplished using print_matrix_row repeatedly From 9f484b6f534eb803a251a00a09323c2049614268 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 16 Feb 2021 09:09:59 -0500 Subject: [PATCH 3/3] remove objectionable invokelatest --- base/arrayshow.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/base/arrayshow.jl b/base/arrayshow.jl index 36421cbbfb981..94d2ed85225a1 100644 --- a/base/arrayshow.jl +++ b/base/arrayshow.jl @@ -166,8 +166,7 @@ function print_matrix(io::IO, X::AbstractVecOrMat, vdots::AbstractString = "\u22ee", ddots::AbstractString = " \u22f1 ", hmod::Integer = 5, vmod::Integer = 5) - # use invokelatest to avoid backtracing in type invalidation, ref #37741 - invokelatest(_print_matrix, io, X, pre, sep, post, hdots, vdots, ddots, hmod, vmod, unitrange(axes(X,1)), unitrange(axes(X,2))) + _print_matrix(io, inferencebarrier(X), pre, sep, post, hdots, vdots, ddots, hmod, vmod, unitrange(axes(X,1)), unitrange(axes(X,2))) end function _print_matrix(io, @nospecialize(X::AbstractVecOrMat), pre, sep, post, hdots, vdots, ddots, hmod, vmod, rowsA, colsA) @@ -273,7 +272,7 @@ end # typeinfo agnostic # n-dimensional arrays show_nd(io::IO, a::AbstractArray, print_matrix::Function, label_slices::Bool) = - invokelatest(_show_nd, io, a, print_matrix, label_slices, map(unitrange, axes(a))) + _show_nd(io, inferencebarrier(a), print_matrix, label_slices, map(unitrange, axes(a))) function _show_nd(io::IO, @nospecialize(a::AbstractArray), print_matrix::Function, label_slices::Bool, axs::Tuple{Vararg{AbstractUnitRange}}) limit::Bool = get(io, :limit, false)