diff --git a/NEWS.md b/NEWS.md index 75a5cc9246855..8adc4a08e24ae 100644 --- a/NEWS.md +++ b/NEWS.md @@ -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 ========================== diff --git a/base/deprecated.jl b/base/deprecated.jl index 687ff736c9316..555bcc2197013 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -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) @@ -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) diff --git a/base/docs/bootstrap.jl b/base/docs/bootstrap.jl index 9fbe4b4bfafe9..62f6e7cfc01d0 100644 --- a/base/docs/bootstrap.jl +++ b/base/docs/bootstrap.jl @@ -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 @@ -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 diff --git a/base/range.jl b/base/range.jl index 52db2504d032b..af2f4dab0be4d 100644 --- a/base/range.jl +++ b/base/range.jl @@ -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 diff --git a/base/replutil.jl b/base/replutil.jl index 6e4412aaa5256..f666512c5d8a8 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -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 diff --git a/base/sharedarray.jl b/base/sharedarray.jl index 24b1679bbe855..b4a1d2b7b1b48 100644 --- a/base/sharedarray.jl +++ b/base/sharedarray.jl @@ -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) diff --git a/base/show.jl b/base/show.jl index 68279acb7756d..c76e6c6c4b0e6 100644 --- a/base/show.jl +++ b/base/show.jl @@ -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) : @@ -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( 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 @@ -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 @@ -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 ) @@ -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 = " ", @@ -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) @@ -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) @@ -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) @@ -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 @@ -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 *= "[" @@ -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 diff --git a/base/sparse/linalg.jl b/base/sparse/linalg.jl index 9475575073df7..526365ab55b0f 100644 --- a/base/sparse/linalg.jl +++ b/base/sparse/linalg.jl @@ -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) diff --git a/test/parallel.jl b/test/parallel.jl index dc4a01a8e58c8..7c4e523b14fcf 100644 --- a/test/parallel.jl +++ b/test/parallel.jl @@ -179,6 +179,20 @@ end ### Utility functions +# construct PR #13514 +S = SharedArray{Int}((1,2,3)) +@test size(S) == (1,2,3) +@test typeof(S) <: SharedArray{Int} +S = SharedArray{Int}(2) +@test size(S) == (2,) +@test typeof(S) <: SharedArray{Int} +S = SharedArray{Int}(1,2) +@test size(S) == (1,2) +@test typeof(S) <: SharedArray{Int} +S = SharedArray{Int}(1,2,3) +@test size(S) == (1,2,3) +@test typeof(S) <: SharedArray{Int} + # reshape d = Base.shmem_fill(1.0, (10,10,10)) diff --git a/test/ranges.jl b/test/ranges.jl index a4a53ed49cc02..a88f6c02ede77 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -544,6 +544,17 @@ for x in r end @test i == 7 +# stringmime/writemime should display the range or linspace nicely +# to test print_range in range.jl +replstr(x) = stringmime("text/plain", x) +@test replstr(1:4) == "4-element UnitRange{$Int}:\n 1,2,3,4" +@test replstr(linspace(1,5,7)) == "7-element LinSpace{Float64}:\n 1.0,1.66667,2.33333,3.0,3.66667,4.33333,5.0" +@test replstr(0:100.) == "101-element FloatRange{Float64}:\n 0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,…,94.0,95.0,96.0,97.0,98.0,99.0,100.0" +# next is to test a very large range, which should be fast because print_range +# only examines spacing of the left and right edges of the range, sufficient +# to cover the designated screen size. +@test replstr(0:10^9) == "1000000001-element UnitRange{$Int}:\n 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,…,999999998,999999999,1000000000" + # Issue 11049 and related @test promote(linspace(0f0, 1f0, 3), linspace(0., 5., 2)) === (linspace(0., 1., 3), linspace(0., 5., 2)) diff --git a/test/sparsedir/sparse.jl b/test/sparsedir/sparse.jl index 27e363354888b..1fa66634cec7a 100644 --- a/test/sparsedir/sparse.jl +++ b/test/sparsedir/sparse.jl @@ -126,7 +126,6 @@ for i = 1:5 @test (maximum(abs(a\b - full(a)\b)) < 1000*eps()) @test (maximum(abs(a'\b - full(a')\b)) < 1000*eps()) @test (maximum(abs(a.'\b - full(a.')\b)) < 1000*eps()) - @test (maximum(abs(A_ldiv_B!(a,copy(b)) - full(a)\b)) < 1000*eps()) a = speye(5) + tril(0.1*sprandn(5, 5, 0.2) + 0.1*im*sprandn(5, 5, 0.2)) b = randn(5,3) @@ -145,7 +144,6 @@ for i = 1:5 @test (maximum(abs(a\b - full(a)\b)) < 1000*eps()) @test (maximum(abs(a'\b - full(a')\b)) < 1000*eps()) @test (maximum(abs(a.'\b - full(a.')\b)) < 1000*eps()) - @test (maximum(abs(A_ldiv_B!(a,copy(b)) - full(a)\b)) < 1000*eps()) a = speye(5) + triu(0.1*sprandn(5, 5, 0.2) + 0.1*im*sprandn(5, 5, 0.2)) b = randn(5,3) @@ -164,7 +162,6 @@ for i = 1:5 @test (maximum(abs(a\b - full(a)\b)) < 1000*eps()) @test (maximum(abs(a'\b - full(a')\b)) < 1000*eps()) @test (maximum(abs(a.'\b - full(a.')\b)) < 1000*eps()) - @test (maximum(abs(A_ldiv_B!(a,copy(b)) - full(a)\b)) < 1000*eps()) a = spdiagm(randn(5)) + im*spdiagm(randn(5)) b = randn(5,3)