Skip to content

New range display2 #13534

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ Library improvements
Deprecated or removed
---------------------

* The method `A_ldiv_B!(SparseMatrixCSC, StrideVecOrMat)` has been deprecated in favor
of versions that require the matrix to in factored form ([#13496]).

Julia v0.4.0 Release Notes
==========================

Expand Down
4 changes: 4 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,7 @@ for f in (:remotecall, :remotecall_fetch, :remotecall_wait)
end
end

#13465
@deprecate cov(x::AbstractVector; corrected=true, mean=Base.mean(x)) covm(x, mean, corrected)
@deprecate cov(X::AbstractMatrix; vardim=1, corrected=true, mean=Base.mean(X, vardim)) covm(X, mean, vardim, corrected)
@deprecate cov(x::AbstractVector, y::AbstractVector; corrected=true, mean=(Base.mean(x), Base.mean(y))) covm(x, mean[1], y, mean[2], corrected)
Expand All @@ -854,3 +855,6 @@ end
@deprecate cor(X::AbstractVecOrMat, Y::AbstractVecOrMat; vardim=1, mean=(Base.mean(X, vardim), Base.mean(Y, vardim))) corm(X, mean[1], Y, mean[2], vardim)

@deprecate_binding SparseMatrix SparseArrays

#13496
@deprecate A_ldiv_B!(A::SparseMatrixCSC, B::StridedVecOrMat) A_ldiv_B!(factorize(A), B)
9 changes: 7 additions & 2 deletions base/docs/bootstrap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ setexpand!(f) = global _expand_ = f

function __bootexpand(str, obj)
global docs = List((ccall(:jl_get_current_module, Any, ()), str, obj), docs)
(isa(obj, Expr) && obj.head == :call) && return nothing
(isa(obj, Expr) && obj.head == :module) && return esc(Expr(:toplevel, obj))
(isa(obj, Expr) && obj.head === :call) && return nothing
(isa(obj, Expr) && obj.head === :module) && return esc(Expr(:toplevel, obj))
esc(obj)
end

Expand All @@ -45,6 +45,11 @@ that were stored in `DocBootstrap.docs` are migrated to their correct modules us
"""
DocBootstrap

"""
loaddocs()

Move all docstrings from `DocBootstrap.docs` to their module's `__META__` dict.
"""
function loaddocs()
node = docs
while node ≠ nothing
Expand Down
53 changes: 53 additions & 0 deletions base/range.jl
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,59 @@ function show(io::IO, r::LinSpace)
print(io, ')')
end

"""
`print_range(io, r)` prints out a nice looking range r in terms of its elements
as if it were `collect(r)`, dependent on the size of the
terminal, and taking into account whether compact numbers should be shown.
It figures out the width in characters of each element, and if they
end up too wide, it shows the first and last elements separated by a
horizontal elipsis. Typical output will look like `1.0,2.0,3.0,…,4.0,5.0,6.0`.

`print_range(io, r, sz, pre, sep, post, hdots)` uses optional
parameters `sz` for the (rows,cols) of the screen,
`pre` and `post` characters for each printed row, `sep` separator string between
printed elements, `hdots` string for the horizontal ellipsis.
"""
function print_range(io::IO, r::Range,
sz::Tuple{Integer, Integer} = (s = tty_size(); (s[1]-4, s[2])),
pre::AbstractString = " ",
sep::AbstractString = ",",
post::AbstractString = "",
hdots::AbstractString = ",\u2026,") # horiz ellipsis
# This function borrows from print_matrix() in show.jl
# and should be called by writemime (replutil.jl) and by display()
screenheight, screenwidth = sz
screenwidth -= length(pre) + length(post)
postsp = ""
sepsize = length(sep)
m = 1 # treat the range as a one-row matrix
n = length(r)
# Figure out spacing alignments for r, but only need to examine the
# left and right edge columns, as many as could conceivably fit on the
# screen, with the middle columns summarized by horz, vert, or diag ellipsis
maxpossiblecols = div(screenwidth, 1+sepsize) # assume each element is at least 1 char + 1 separator
colsr = n <= maxpossiblecols ? (1:n) : [1:div(maxpossiblecols,2)+1; (n-div(maxpossiblecols,2)):n]
rowmatrix = r[colsr]' # treat the range as a one-row matrix for print_matrix_row
A = alignment(rowmatrix,1:m,1:length(rowmatrix),screenwidth,screenwidth,sepsize) # how much space range takes
if n <= length(A) # cols fit screen, so print out all elements
print(io, pre) # put in pre chars
print_matrix_row(io,rowmatrix,A,1,1:n,sep) # the entire range
print(io, post) # add the post characters
else # cols don't fit so put horiz ellipsis in the middle
# how many chars left after dividing width of screen in half
# and accounting for the horiz ellipsis
c = div(screenwidth-length(hdots)+1,2)+1 # chars remaining for each side of rowmatrix
alignR = reverse(alignment(rowmatrix,1:m,length(rowmatrix):-1:1,c,c,sepsize)) # which cols of rowmatrix to put on the right
c = screenwidth - sum(map(sum,alignR)) - (length(alignR)-1)*sepsize - length(hdots)
alignL = alignment(rowmatrix,1:m,1:length(rowmatrix),c,c,sepsize) # which cols of rowmatrix to put on the left
print(io, pre) # put in pre chars
print_matrix_row(io, rowmatrix,alignL,1,1:length(alignL),sep) # left part of range
print(io, hdots) # horizontal ellipsis
print_matrix_row(io, rowmatrix,alignR,1,length(rowmatrix)-length(alignR)+1:length(rowmatrix),sep) # right part of range
print(io, post) # post chars
end
end

logspace(start::Real, stop::Real, n::Integer=50) = 10.^linspace(start, stop, n)

## interface implementations
Expand Down
25 changes: 17 additions & 8 deletions base/replutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,24 @@ function writemime(io::IO, ::MIME"text/plain", f::Function)
end
end

# writemime for ranges, e.g.
# 3-element UnitRange{Int64,Int}
# 1,2,3
# or for more elements than fit on screen:
# 1.0,2.0,3.0,…,6.0,7.0,8.0
function writemime(io::IO, ::MIME"text/plain", r::Range)
print(io, summary(r))
if !isempty(r)
println(io, ":")
with_output_limit(()->print_range(io, r))
end
end

function writemime(io::IO, ::MIME"text/plain", v::AbstractVector)
if isa(v, Range)
show(io, v)
else
print(io, summary(v))
if !isempty(v)
println(io, ":")
with_output_limit(()->print_matrix(io, v))
end
print(io, summary(v))
if !isempty(v)
println(io, ":")
with_output_limit(()->print_matrix(io, v))
end
end

Expand Down
11 changes: 11 additions & 0 deletions base/sharedarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ type SharedArray{T,N} <: DenseArray{T,N}
SharedArray(d,p,r,sn) = new(d,p,r,sn)
end

call{T,N}(::Type{SharedArray{T}}, d::NTuple{N,Int}; kwargs...) =
SharedArray(T, d; kwargs...)
call{T}(::Type{SharedArray{T}}, d::Integer...; kwargs...) =
SharedArray(T, d; kwargs...)
call{T}(::Type{SharedArray{T}}, m::Integer; kwargs...) =
SharedArray(T, m; kwargs...)
call{T}(::Type{SharedArray{T}}, m::Integer, n::Integer; kwargs...) =
SharedArray(T, m, n; kwargs...)
call{T}(::Type{SharedArray{T}}, m::Integer, n::Integer, o::Integer; kwargs...) =
SharedArray(T, m, n, o; kwargs...)

function SharedArray(T::Type, dims::NTuple; init=false, pids=Int[])
N = length(dims)

Expand Down
85 changes: 67 additions & 18 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -972,14 +972,21 @@ dump(io::IO, x::DataType) = dump(io, x, 5, "")
dump(io::IO, x::TypeVar, n::Int, indent) = println(io, x.name)


"""
`alignment(X)` returns a tuple (left,right) showing how many characters are
needed on either side of an alignment feature such as a decimal point.
"""
alignment(x::Any) = (0, length(sprint(showcompact_lim, x)))
alignment(x::Number) = (length(sprint(showcompact_lim, x)), 0)
"`alignment(42)` yields (2,0)"
alignment(x::Integer) = (length(sprint(showcompact_lim, x)), 0)
"`alignment(4.23)` yields (1,3) for `4` and `.23`"
function alignment(x::Real)
m = match(r"^(.*?)((?:[\.eE].*)?)$", sprint(showcompact_lim, x))
m === nothing ? (length(sprint(showcompact_lim, x)), 0) :
(length(m.captures[1]), length(m.captures[2]))
end
"`alignment(1 + 10im)` yields (3,5) for `1 +` and `_10im` (plus sign on left, space on right)"
function alignment(x::Complex)
m = match(r"^(.*[\+\-])(.*)$", sprint(showcompact_lim, x))
m === nothing ? (length(sprint(showcompact_lim, x)), 0) :
Expand All @@ -994,26 +1001,37 @@ end
const undef_ref_str = "#undef"
const undef_ref_alignment = (3,3)

"""
`alignment(X, rows, cols, cols_if_complete, cols_otherwise, sep)` returns the
alignment for specified parts of array `X`, returning the (left,right) info.
It will look in X's `rows`, `cols` (both lists of indices)
and figure out what's needed to be fully aligned, for example looking all
the way down a column and finding out the maximum size of each element.
Parameter `sep::Integer` is number of spaces to put between elements.
`cols_if_complete` and `cols_otherwise` indicate screen width to use.
Alignment is reported as a vector of (left,right) tuples, one for each
column going across the screen.
"""
function alignment(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The additional documentation is great, but you might as well put it in the form of a docstring:

"""
    alignment(X, rows, cols, cols_if_complete, cols_otherwise, sep)

Returns the alignment for the specified parts of array `X`, returning ....
...
"""
function alignment( ...

X::AbstractVecOrMat,
rows::AbstractVector, cols::AbstractVector,
cols_if_complete::Integer, cols_otherwise::Integer, sep::Integer
)
a = Tuple{Int, Int}[]
for j in cols
for j in cols # need to go down each column one at a time
l = r = 0
for i in rows
for i in rows # plumb down and see what largest element sizes are
if isassigned(X,i,j)
aij = alignment(X[i,j])
else
aij = undef_ref_alignment
end
l = max(l, aij[1])
r = max(r, aij[2])
l = max(l, aij[1]) # left characters
r = max(r, aij[2]) # right characters
end
push!(a, (l, r))
push!(a, (l, r)) # one tuple per column of X, pruned to screen width
if length(a) > 1 && sum(map(sum,a)) + sep*length(a) >= cols_if_complete
pop!(a)
pop!(a) # remove this latest tuple if we're already beyond screen width
break
end
end
Expand All @@ -1025,6 +1043,13 @@ function alignment(
return a
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.
The corresponding alignment A is used, and the separation between elements
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,
i::Integer, cols::AbstractVector, sep::AbstractString
Expand All @@ -1039,13 +1064,18 @@ function print_matrix_row(io::IO,
a = undef_ref_alignment
sx = undef_ref_str
end
l = repeat(" ", A[k][1]-a[1])
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)
if k < length(A); print(io, sep); end
end
end

"""
`print_matrix_vdots` is used to show a series of vertical ellipsis instead
of a bunch of rows for long matrices. Not only is the string vdots shown
but it also repeated every M elements if desired.
"""
function print_matrix_vdots(io::IO,
vdots::AbstractString, A::Vector, sep::AbstractString, M::Integer, m::Integer
)
Expand All @@ -1062,6 +1092,16 @@ function print_matrix_vdots(io::IO,
end
end

"""
`print_matrix(io, X)` composes an entire matrix X, taking into account the screen size
to determine when vertical, horizontal, or diagonal ellipsis are desired.
`print_matrix(io, X, sz, pre, sep, post, vdots, ddots, hmod)` has optional
parameters: screen size tuple `sz` such as (24,80),
string `pre` prior to the matrix, with same-size indent on following rows,
and string `post` on the end of the last row of the matrix.
Also options to use different ellipsis characters `hdots`,
`vdots`, `ddots`. The ellipsis are separated every `hmod` or `vmod` apart.
"""
function print_matrix(io::IO, X::AbstractVecOrMat,
sz::Tuple{Integer, Integer} = (s = tty_size(); (s[1]-4, s[2])),
pre::AbstractString = " ",
Expand All @@ -1078,20 +1118,23 @@ function print_matrix(io::IO, X::AbstractVecOrMat,
@assert strwidth(hdots) == strwidth(ddots)
ss = length(sep)
m, n = size(X,1), size(X,2)
if m <= rows # rows fit
if m <= rows # rows fit vertically on screen
# is there a reasonable chance of fitting all columns across screen?
# evaluate by assuming minimum width of 1 char and separator per element

A = alignment(X,1:m,1:n,cols,cols,ss)
if n <= length(A) # rows and cols fit
if n <= length(A) # rows and cols fit so just print whole matrix in one piece
for i = 1:m
print(io, i == 1 ? pre : presp)
print_matrix_row(io, X,A,i,1:n,sep)
print(io, i == m ? post : postsp)
if i != m; println(io, ); end
end
else # rows fit, cols don't
c = div(cols-length(hdots)+1,2)+1
R = reverse(alignment(X,1:m,n:-1:1,c,c,ss))
else # rows fit on screen but cols don't, so need horizontal ellipsis
c = div(cols-length(hdots)+1,2)+1 # what goes to right of ellipsis
R = reverse(alignment(X,1:m,n:-1:1,c,c,ss)) # alignments for right
c = cols - sum(map(sum,R)) - (length(R)-1)*ss - length(hdots)
L = alignment(X,1:m,1:n,c,c,ss)
L = alignment(X,1:m,1:n,c,c,ss) # alignments for left of ellipsis
for i = 1:m
print(io, i == 1 ? pre : presp)
print_matrix_row(io, X,L,i,1:length(L),sep)
Expand All @@ -1101,11 +1144,11 @@ function print_matrix(io::IO, X::AbstractVecOrMat,
if i != m; println(io, ); end
end
end
else # rows don't fit
else # rows don't fit so will need vertical ellipsis
t = div(rows,2)
I = [1:t; m-div(rows-1,2)+1:m]
A = alignment(X,I,1:n,cols,cols,ss)
if n <= length(A) # rows don't fit, cols do
if n <= length(A) # rows don't fit, cols do, so only vertical ellipsis
for i in I
print(io, i == 1 ? pre : presp)
print_matrix_row(io, X,A,i,1:n,sep)
Expand All @@ -1117,7 +1160,7 @@ function print_matrix(io::IO, X::AbstractVecOrMat,
println(io, i == m ? post : postsp)
end
end
else # neither rows nor cols fit
else # neither rows nor cols fit, so use all 3 kinds of ellipsis
c = div(cols-length(hdots)+1,2)+1
R = reverse(alignment(X,I,n:-1:1,c,c,ss))
c = cols - sum(map(sum,R)) - (length(R)-1)*ss - length(hdots)
Expand All @@ -1142,15 +1185,20 @@ function print_matrix(io::IO, X::AbstractVecOrMat,
end
end

summary(x) = string(typeof(x))
"`summary(x)` a string of type information, e.g. `Int64`"
summary(x) = string(typeof(x)) # e.g. Int64

# sizes such as 0-dimensional, 4-dimensional, 2x3
dims2string(d) = length(d) == 0 ? "0-dimensional" :
length(d) == 1 ? "$(d[1])-element" :
join(map(string,d), 'x')

# anything array-like gets summarized e.g. 10-element Array{Int64,1}
"`summary(A)` for array is a string of size and type info, e.g. `10-element Array{Int64,1}`"
summary(a::AbstractArray) =
string(dims2string(size(a)), " ", typeof(a))

# n-dimensional arrays
function show_nd(io::IO, a::AbstractArray, limit, print_matrix, label_slices)
if isempty(a)
return
Expand Down Expand Up @@ -1197,6 +1245,7 @@ end
# for internal use in showing arrays.
_limit_output = false

# print matrix with opening and closing square brackets
function print_matrix_repr(io, X::AbstractArray)
compact, prefix = array_eltype_show_how(X)
prefix *= "["
Expand Down Expand Up @@ -1263,7 +1312,7 @@ end

show(io::IO, X::AbstractArray) = showarray(io, X, header=_limit_output, repr=!_limit_output)

function with_output_limit(thk, lim=true)
function with_output_limit(thk, lim=true) # thk is usually show()
global _limit_output
last = _limit_output
_limit_output = lim
Expand Down
14 changes: 0 additions & 14 deletions base/sparse/linalg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -165,20 +165,6 @@ function spmatmul{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti};
end

## solvers
function A_ldiv_B!(A::SparseMatrixCSC, b::AbstractVecOrMat)
if eltype(b)<:Complex; A = complex(A); end

if istril(A)
# TODO: Fix diagonal case. Diagonal(A.nzval) needs to handle
# the case where there are zeros on the diagonal and error out.
# It also does not work in the complex case. VBS.
#if istriu(A); return A_ldiv_B!(Diagonal(A.nzval), b); end
return fwdTriSolve!(A, b)
end
if istriu(A); return bwdTriSolve!(A, b); end
return A_ldiv_B!(lufact(A),b)
end

function fwdTriSolve!(A::SparseMatrixCSC, B::AbstractVecOrMat)
# forward substitution for CSC matrices
n = length(B)
Expand Down
Loading