diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2f52514a3d59e..5193cda28f5c2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -95,14 +95,17 @@ Build as usual, and do `make clean testall` to test your contribution. If your c ##### General Formatting Guidelines For Julia code contributions - - 4 space indent + - 4 spaces per indentation level, no tabs - use whitespace to make the code more readable - - no whitespace at the end of a line + - no whitespace at the end of a line (trailing whitespace) - comments are good, especially when they explain the algorithm + - try to adhere to a 92 character line length limit + - use upper camel case convention for modules, type names + - use lower case with underscores for method names ##### General Formatting Guidelines For C code contributions - - 4 space indent + - 4 spaces per indentation level, no tabs - space between if and ( (if (x) ...) - newline before opening { in function definitions - f(void) for 0-argument function declarations diff --git a/Makefile b/Makefile index 337f7fc13a5f2..64e0865c9bb94 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,7 @@ $(build_docdir): @mkdir -p $@/examples @cp -R doc/devdocs doc/manual doc/stdlib $@ @cp -R examples/*.jl $@/examples/ + @cp -R examples/clustermanager $@/examples/ git-submodules: ifneq ($(NO_GIT), 1) @@ -152,12 +153,12 @@ $(build_private_libdir)/sys0.o: BASE_SRCS := $(wildcard base/*.jl base/*/*.jl base/*/*/*.jl) -,:=, +COMMA:=, $(build_private_libdir)/sys.o: VERSION $(BASE_SRCS) $(build_docdir)/helpdb.jl $(build_private_libdir)/sys0.$(SHLIB_EXT) @$(call PRINT_JULIA, cd base && \ $(call spawn,$(JULIA_EXECUTABLE)) -C $(JULIA_CPU_TARGET) --build $(call cygpath_w,$(build_private_libdir)/sys) \ -J$(call cygpath_w,$(build_private_libdir))/$$([ -e $(build_private_libdir)/sys.ji ] && echo sys.ji || echo sys0.ji) -f sysimg.jl \ - || { echo '*** This error is usually fixed by running `make clean`. If the error persists$(,) try `make cleanall`. ***' && false; } ) + || { echo '*** This error is usually fixed by running `make clean`. If the error persists$(COMMA) try `make cleanall`. ***' && false; } ) $(build_bindir)/stringreplace: contrib/stringreplace.c | $(build_bindir) @$(call PRINT_CC, $(CC) -o $(build_bindir)/stringreplace contrib/stringreplace.c) @@ -448,17 +449,17 @@ distcleanall: cleanall run-julia run-julia-debug run-julia-release run \ install dist source-dist git-submodules -test: release +test: check-whitespace release @$(MAKE) $(QUIET_MAKE) -C test default -testall: release +testall: check-whitespace release cp $(build_prefix)/lib/julia/sys.ji local.ji && $(JULIA_EXECUTABLE) -J local.ji -e 'true' && rm local.ji @$(MAKE) $(QUIET_MAKE) -C test all -testall1: release +testall1: check-whitespace release @env JULIA_CPU_CORES=1 $(MAKE) $(QUIET_MAKE) -C test all -test-%: release +test-%: check-whitespace release @$(MAKE) $(QUIET_MAKE) -C test $* perf: release diff --git a/NEWS.md b/NEWS.md index 3e4a15ceaf01b..4a72139a7f81b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -156,6 +156,8 @@ Library improvements * Split `Triangular` type into `UpperTriangular`, `LowerTriangular`, `UnitUpperTriagular` and `UnitLowerTriangular` ([#9779]) + * ClusterManager - Performance improvements([#9309]) and support for changing transports([#9434]) + Deprecated or removed --------------------- diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 2b8a6a36f3bb9..5cb33ef0ddb77 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -24,7 +24,7 @@ ndims{T<:AbstractArray}(::Type{T}) = ndims(super(T)) length(t::AbstractArray) = prod(size(t))::Int endof(a::AbstractArray) = length(a) first(a::AbstractArray) = a[1] -first(a) = (s = start(a); done(a, s) ? error("collection is empty") : next(a, s)[1]) +first(a) = (s = start(a); done(a, s) ? throw(ArgumentError("collection must be non-empty")) : next(a, s)[1]) last(a) = a[end] ctranspose(a::AbstractArray) = error("ctranspose not implemented for $(typeof(a)). Consider adding parentheses, e.g. A*(B*C') instead of A*B*C' to avoid explicit calculation of the transposed matrix.") transpose(a::AbstractArray) = error("transpose not implemented for $(typeof(a)). Consider adding parentheses, e.g. A*(B*C.') instead of A*B*C' to avoid explicit calculation of the transposed matrix.") diff --git a/base/array.jl b/base/array.jl index 1eac1848c9768..b694c75262882 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1046,7 +1046,9 @@ end function hcat{T}(V::Vector{T}...) height = length(V[1]) for j = 2:length(V) - if length(V[j]) != height; throw(ArgumentError("vector must have same lengths")); end + if length(V[j]) != height + throw(DimensionMismatch("vectors must have same lengths")) + end end [ V[j][i]::T for i=1:length(V[1]), j=1:length(V) ] end diff --git a/base/ascii.jl b/base/ascii.jl index c9c0035aa2c3c..3c3a2d8a5266c 100644 --- a/base/ascii.jl +++ b/base/ascii.jl @@ -98,7 +98,11 @@ write(io::IO, s::ASCIIString) = write(io, s.data) ascii(x) = convert(ASCIIString, x) convert(::Type{ASCIIString}, s::ASCIIString) = s convert(::Type{ASCIIString}, s::UTF8String) = ascii(s.data) -convert(::Type{ASCIIString}, a::Array{UInt8,1}) = is_valid_ascii(a) ? ASCIIString(a) : error("invalid ASCII sequence") +convert(::Type{ASCIIString}, a::Vector{UInt8}) = begin + is_valid_ascii(a) || throw(ArgumentError("invalid ASCII sequence")) + return ASCIIString(a) +end + function convert(::Type{ASCIIString}, a::Array{UInt8,1}, invalids_as::ASCIIString) l = length(a) idx = 1 diff --git a/base/base64.jl b/base/base64.jl index a736b9e9a1b1e..0a1cf481153cd 100644 --- a/base/base64.jl +++ b/base/base64.jl @@ -63,7 +63,7 @@ end #Returns the first decoded byte and stores up to two more in cache function b64decode!(encvec::Vector{UInt8}, cache::Vector{UInt8}) if length(encvec) < 2 - error("Incorrect base64 format") + throw(ArgumentError("incorrect base64 format, block must be at least 2 and at most 4 bytes")) end @inbounds u = revb64chars[encvec[1]] @inbounds v = revb64chars[encvec[2]] diff --git a/base/bitarray.jl b/base/bitarray.jl index 011c9814be62c..1c4dde9f703fe 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -7,11 +7,13 @@ type BitArray{N} <: DenseArray{Bool, N} len::Int dims::NTuple{N,Int} function BitArray(dims::Int...) - length(dims) == N || error("number of dimensions must be $N (got $(length(dims)))") + length(dims) == N || throw(ArgumentError("number of dimensions must be $N, got $(length(dims))")) n = 1 + i = 1 for d in dims - d >= 0 || error("dimension size must be nonnegative (got $d)") + d >= 0 || throw(ArgumentError("dimension size must be ≥ 0, got $d for dimension $i")) n *= d + i += 1 end nc = num_bit_chunks(n) chunks = Array(UInt64, nc) @@ -34,7 +36,14 @@ length(B::BitArray) = B.len size(B::BitVector) = (B.len,) size(B::BitArray) = B.dims -size(B::BitVector, d) = (d==1 ? B.len : d>1 ? 1 : error("dimensions should be positive (got $d)")) +size(B::BitVector, d) = begin + if d == 1 + return B.len + elseif d > 1 + return 1 + end + throw(ArgumentError("dimension must be ≥ 1, got $d")) +end size{N}(B::BitArray{N}, d) = (d>N ? 1 : B.dims[d]) isassigned{N}(B::BitArray{N}, i::Int) = 1 <= i <= length(B) @@ -592,7 +601,7 @@ function resize!(B::BitVector, n::Integer) end function pop!(B::BitVector) - isempty(B) && error("argument must not be empty") + isempty(B) && throw(ArgumentError("argument must not be empty")) item = B[end] B[end] = false @@ -626,7 +635,7 @@ function unshift!(B::BitVector, item) end function shift!(B::BitVector) - isempty(B) && error("argument must not be empty") + isempty(B) && throw(ArgumentError("argument must not be empty")) @inbounds begin item = B[1] @@ -753,7 +762,7 @@ function deleteat!(B::BitVector, inds) while !done(inds, s) (i,s) = next(inds, s) if !(q <= i <= n) - i < q && error("indices must be unique and sorted") + i < q && throw(ArgumentError("indices must be unique and sorted")) throw(BoundsError(B, i)) end new_l -= 1 @@ -1540,8 +1549,8 @@ function any(B::BitArray) return false end -minimum(B::BitArray) = isempty(B) ? error("argument must be non-empty") : all(B) -maximum(B::BitArray) = isempty(B) ? error("argument must be non-empty") : any(B) +minimum(B::BitArray) = isempty(B) ? throw(ArgumentError("argument must be non-empty")) : all(B) +maximum(B::BitArray) = isempty(B) ? throw(ArgumentError("argument must be non-empty")) : any(B) ## map over bitarrays ## @@ -1682,7 +1691,7 @@ ctranspose(B::BitArray) = transpose(B) function permutedims(B::Union(BitArray,StridedArray), perm) dimsB = size(B) ndimsB = length(dimsB) - (ndimsB == length(perm) && isperm(perm)) || error("no valid permutation of dimensions") + (ndimsB == length(perm) && isperm(perm)) || throw(ArgumentError("no valid permutation of dimensions")) dimsP = ntuple(ndimsB, i->dimsB[perm[i]])::typeof(dimsB) P = similar(B, dimsP) permutedims!(P, B, perm) @@ -1694,7 +1703,9 @@ end function hcat(B::BitVector...) height = length(B[1]) for j = 2:length(B) - length(B[j]) == height || error("dimensions must match") + if length(B[j]) != height + throw(DimensionMismatch("dimensions must match")) + end end M = BitArray(height, length(B)) for j = 1:length(B) @@ -1726,7 +1737,9 @@ function hcat(A::Union(BitMatrix,BitVector)...) Aj = A[j] nd = ndims(Aj) ncols += (nd==2 ? size(Aj,2) : 1) - if size(Aj, 1) != nrows; error("rows must match"); end + if size(Aj, 1) != nrows + throw(DimensionMismatch("row lengths must match")) + end end B = BitArray(nrows, ncols) @@ -1746,7 +1759,9 @@ function vcat(A::BitMatrix...) nrows = sum(a->size(a, 1), A)::Int ncols = size(A[1], 2) for j = 2:nargs - size(A[j], 2) == ncols || error("columns must match") + if size(A[j], 2) != ncols + throw(DimensionMismatch("column lengths must match")) + end end B = BitArray(nrows, ncols) Bc = B.chunks @@ -1784,14 +1799,16 @@ function cat(catdim::Integer, X::Union(BitArray, Integer)...) if catdim > d_max + 1 for i = 1:nargs - dimsX[1] == dimsX[i] || error("all inputs must have same dimensions when concatenating along a higher dimension"); + if dimsX[1] != dimsX[i] + throw(DimensionMismatch("all inputs must have same dimensions when concatenating along a higher dimension")) + end end elseif nargs >= 2 for d = 1:d_max d == catdim && continue len = d <= ndimsX[1] ? dimsX[1][d] : 1 for i = 2:nargs - len == (d <= ndimsX[i] ? dimsX[i][d] : 1) || error("mismatch in dimension ", d) + len == (d <= ndimsX[i] ? dimsX[i][d] : 1) || throw(DimensionMismatch("mismatch in dimension $d")) end end end diff --git a/base/broadcast.jl b/base/broadcast.jl index a414efeba2fcb..8e29f437c4c28 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -37,7 +37,7 @@ function broadcast_shape(As::Union(AbstractArray,Number)...) if bshape[d] == 1 bshape[d] = n elseif bshape[d] != n - error("arrays could not be broadcast to a common size") + throw(DimensionMismatch("arrays could not be broadcast to a common size")) end end end @@ -49,12 +49,12 @@ end function check_broadcast_shape(shape::Dims, As::Union(AbstractArray,Number)...) for A in As if ndims(A) > length(shape) - error("cannot broadcast array to have fewer dimensions") + throw(DimensionMismatch("cannot broadcast array to have fewer dimensions")) end for k in 1:ndims(A) n, nA = shape[k], size(A, k) if n != nA != 1 - error("array could not be broadcast to match destination") + throw(DimensionMismatch("array could not be broadcast to match destination")) end end end diff --git a/base/cartesian.jl b/base/cartesian.jl index 39e293929cb77..1517ed5f8c368 100644 --- a/base/cartesian.jl +++ b/base/cartesian.jl @@ -33,7 +33,7 @@ macro ngenerate(itersym, returntypeexpr, funcexpr) if isa(funcexpr, Expr) && funcexpr.head == :macrocall && funcexpr.args[1] == symbol("@inline") funcexpr = Base._inline(funcexpr.args[2]) end - isfuncexpr(funcexpr) || error("Requires a function expression") + isfuncexpr(funcexpr) || throw(ArgumentError("requires a function expression")) esc(ngenerate(itersym, returntypeexpr, funcexpr.args[1], N->sreplace!(copy(funcexpr.args[2]), itersym, N))) end @@ -54,20 +54,20 @@ macro nsplat(itersym, args...) rangeexpr = args[1] funcexpr = args[2] if !isa(rangeexpr, Expr) || rangeexpr.head != :(:) || length(rangeexpr.args) != 2 - error("First argument must be a from:to expression") + throw(ArgumentError("first argument must be a from:to expression")) end rng = rangeexpr.args[1]:rangeexpr.args[2] else - error("Wrong number of arguments") + throw(ArgumentError("wrong number of arguments")) end if isa(funcexpr, Expr) && funcexpr.head == :macrocall && funcexpr.args[1] == symbol("@inline") funcexpr = Base._inline(funcexpr.args[2]) end - isfuncexpr(funcexpr) || error("Second argument must be a function expression") + isfuncexpr(funcexpr) || throw(ArgumentError("second argument must be a function expression")) prototype = funcexpr.args[1] body = funcexpr.args[2] varname, T = get_splatinfo(prototype, itersym) - isempty(varname) && error("Last argument must be a splat") + isempty(varname) && throw(ArgumentError("last argument must be a splat")) explicit = [Expr(:function, resolvesplat!(copy(prototype), varname, T, N), resolvesplats!(copy(body), varname, N)) for N in rng] protosplat = resolvesplat!(copy(prototype), varname, T, 0) @@ -96,7 +96,7 @@ function ngenerate(itersym, returntypeexpr, prototype, bodyfunc, dims=1:CARTESIA extractvarargs = N -> Expr(:block, map(popescape, _nextract(N, s, s).args)...) end fsym = funcsym(prototype) - dictname = symbol(string(fsym)*"_cache") + dictname = symbol(fsym,"_cache") fargs = funcargs(prototype) if !isempty(varname) fargs[end] = Expr(:..., fargs[end].args[1]) @@ -158,10 +158,10 @@ end # Replace splatted with desplatted for a specific number of arguments function resolvesplat!(prototype, varname, T::Union(Type,Symbol,Expr), N::Int) if !isempty(varname) - prototype.args[end] = N > 0 ? Expr(:(::), symbol(string(varname, "_1")), T) : + prototype.args[end] = N > 0 ? Expr(:(::), symbol(varname, "_1"), T) : Expr(:(::), symbol(varname), T) for i = 2:N - push!(prototype.args, Expr(:(::), symbol(string(varname, "_", i)), T)) + push!(prototype.args, Expr(:(::), symbol(varname, "_", i), T)) end end prototype @@ -186,9 +186,9 @@ function resolvesplats!(ex::Expr, varname, N::Int) end a = ex.args[end] if isa(a, Expr) && a.head == :... && a.args[1] == symbol(varname) - ex.args[end] = symbol(string(varname, "_1")) + ex.args[end] = symbol(varname, "_1") for i = 2:N - push!(ex.args, symbol(string(varname, "_", i))) + push!(ex.args, symbol(varname, "_", i)) end else resolvesplats!(a, varname, N) @@ -206,7 +206,7 @@ function spliceint!(ex::Expr) if ex.head == :escape return esc(spliceint!(ex.args[1])) end - ex.head == :call || error(string(ex, " must be a call")) + ex.head == :call || throw(ArgumentError("$ex must be a call")) if isa(ex.args[1], Expr) && ex.args[1].head == :curly args = ex.args[1].args for i = length(args):-1:1 @@ -228,7 +228,7 @@ end # Extract the "function name" function funcsym(prototype::Expr) prototype = popescape(prototype) - prototype.head == :call || error(string(prototype, " must be a call")) + prototype.head == :call || throw(ArgumentError("$prototype must be a call")) tmp = prototype.args[1] if isa(tmp, Expr) && tmp.head == :curly tmp = tmp.args[1] @@ -238,7 +238,7 @@ end function funcrename(prototype::Expr, name::Symbol) prototype = popescape(prototype) - prototype.head == :call || error(string(prototype, " must be a call")) + prototype.head == :call || throw(ArgumentError("$prototype must be a call")) tmp = prototype.args[1] if isa(tmp, Expr) && tmp.head == :curly tmp.args[1] = name @@ -250,7 +250,7 @@ end function hasparameter(prototype::Expr, sym::Symbol) prototype = popescape(prototype) - prototype.head == :call || error(string(prototype, " must be a call")) + prototype.head == :call || throw(ArgumentError("$prototype must be a call")) tmp = prototype.args[1] if isa(tmp, Expr) && tmp.head == :curly for i = 2:length(tmp.args) @@ -267,7 +267,7 @@ funcarg(s::Symbol) = s funcarg(ex::Expr) = ex.args[1] function funcargs(prototype::Expr) prototype = popescape(prototype) - prototype.head == :call || error(string(prototype, " must be a call")) + prototype.head == :call || throw(ArgumentError("$prototype must be a call")) map(a->funcarg(a), prototype.args[2:end]) end @@ -282,10 +282,10 @@ _nloops(N::Int, itersym::Symbol, arraysym::Symbol, args::Expr...) = _nloops(N, i function _nloops(N::Int, itersym::Symbol, rangeexpr::Expr, args::Expr...) if rangeexpr.head != :-> - error("Second argument must be an anonymous function expression to compute the range") + throw(ArgumentError("second argument must be an anonymous function expression to compute the range")) end if !(1 <= length(args) <= 3) - error("Too many arguments") + throw(ArgumentError("number of arguments must be 1 ≤ length(args) ≤ 3, got $nargs")) end body = args[end] ex = Expr(:escape, body) @@ -359,7 +359,7 @@ end function _nall(N::Int, criterion::Expr) if criterion.head != :-> - error("Second argument must be an anonymous function expression yielding the criterion") + throw(ArgumentError("second argument must be an anonymous function expression yielding the criterion")) end conds = [Expr(:escape, inlineanonymous(criterion, i)) for i = 1:N] Expr(:&&, conds...) @@ -391,10 +391,10 @@ end # Simplify expressions like :(d->3:size(A,d)-3) given an explicit value for d function inlineanonymous(ex::Expr, val) if ex.head != :-> - error("Not an anonymous function") + throw(ArgumentError("not an anonymous function")) end if !isa(ex.args[1], Symbol) - error("Not a single-argument anonymous function") + throw(ArgumentError("not a single-argument anonymous function")) end sym = ex.args[1] ex = ex.args[2] @@ -404,7 +404,7 @@ function inlineanonymous(ex::Expr, val) end # Given :i and 3, this generates :i_3 -inlineanonymous(base::Symbol, ext) = symbol(string(base)*"_"*string(ext)) +inlineanonymous(base::Symbol, ext) = symbol(base,"_",string(ext)) # Replace a symbol by a value or a "coded" symbol # E.g., for d = 3, @@ -425,7 +425,7 @@ function lreplace!(ex::Expr, sym::Symbol, val, r) if ex.head == :curly && length(ex.args) == 2 && isa(ex.args[1], Symbol) && endswith(string(ex.args[1]), "_") excurly = exprresolve(lreplace!(ex.args[2], sym, val, r)) if isa(excurly, Number) - return symbol(string(ex.args[1])*string(excurly)) + return symbol(ex.args[1],excurly) else ex.args[2] = excurly return ex diff --git a/base/client.jl b/base/client.jl index 3faa2640f647f..5e2da9f39fad6 100644 --- a/base/client.jl +++ b/base/client.jl @@ -48,11 +48,11 @@ function repl_cmd(cmd, out) end if isempty(cmd.exec) - error("no cmd to execute") + throw(ArgumentError("no cmd to execute")) elseif cmd.exec[1] == "cd" new_oldpwd = pwd() if length(cmd.exec) > 2 - error("cd method only takes one argument") + throw(ArgumentError("cd method only takes one argument")) elseif length(cmd.exec) == 2 dir = cmd.exec[2] if dir == "-" @@ -222,8 +222,15 @@ function process_options(args::Vector{UTF8String}) if args[i]=="-q" || args[i]=="--quiet" quiet = true elseif args[i]=="--worker" - start_worker() - # doesn't return + worker_arg = (i == length(args)) ? "" : args[i+1] + + if worker_arg == "custom" + i += 1 + else + start_worker() + # doesn't return + end + elseif args[i]=="--bind-to" i+=1 # has already been processed elseif args[i]=="-e" || args[i]=="--eval" diff --git a/base/collections.jl b/base/collections.jl index 43e37f820c209..419456d9cd6d1 100644 --- a/base/collections.jl +++ b/base/collections.jl @@ -126,7 +126,7 @@ type PriorityQueue{K,V,O<:Ordering} <: Associative{K,V} o::O) # TODO: maybe deprecate if length(ks) != length(vs) - error("key and value arrays must have equal lengths") + throw(ArgumentError("key and value arrays must have equal lengths")) end PriorityQueue{K,V,O}(zip(ks, vs), o) end @@ -137,7 +137,7 @@ type PriorityQueue{K,V,O<:Ordering} <: Associative{K,V} for (i, (k, v)) in enumerate(itr) xs[i] = Pair{K,V}(k, v) if haskey(index, k) - error("PriorityQueue keys must be unique") + throw(ArgumentError("PriorityQueue keys must be unique")) end index[k] = i end @@ -247,9 +247,8 @@ end function enqueue!{K,V}(pq::PriorityQueue{K,V}, key, value) if haskey(pq, key) - error("PriorityQueue keys must be unique") + throw(ArgumentError("PriorityQueue keys must be unique")) end - push!(pq.xs, Pair{K,V}(key, value)) pq.index[key] = length(pq) percolate_up!(pq, length(pq)) diff --git a/base/combinatorics.jl b/base/combinatorics.jl index a86df2a9cc795..fc8184fd5457e 100644 --- a/base/combinatorics.jl +++ b/base/combinatorics.jl @@ -138,7 +138,7 @@ end function nthperm!(a::AbstractVector, k::Integer) k -= 1 # make k 1-indexed - k < 0 && error("permutation must be a positive number") + k < 0 && throw(ArgumentError("permutation k must be ≥ 0, got $k")) n = length(a) n == 0 && return a f = factorial(oftype(k, n-1)) @@ -159,7 +159,7 @@ end nthperm(a::AbstractVector, k::Integer) = nthperm!(copy(a),k) function nthperm{T<:Integer}(p::AbstractVector{T}) - isperm(p) || error("argument is not a permutation") + isperm(p) || throw(ArgumentError("argument is not a permutation")) k, n = 1, length(p) for i = 1:n-1 f = factorial(n-i) @@ -176,7 +176,7 @@ function invperm(a::AbstractVector) for i = 1:n j = a[i] ((1 <= j <= n) && b[j] == 0) || - error("argument is not a permutation") + throw(ArgumentError("argument is not a permutation")) b[j] = i end b @@ -596,7 +596,7 @@ end # for integer n1, n2, n3 function nextprod(a::Vector{Int}, x) if x > typemax(Int) - error("unsafe for x bigger than typemax(Int)") + throw(ArgumentError("unsafe for x > typemax(Int), got $x")) end k = length(a) v = ones(Int, k) # current value of each counter @@ -637,7 +637,7 @@ end # for integer n1, n2, n3 function prevprod(a::Vector{Int}, x) if x > typemax(Int) - error("unsafe for x bigger than typemax(Int)") + throw(ArgumentError("unsafe for x > typemax(Int), got $x")) end k = length(a) v = ones(Int, k) # current value of each counter diff --git a/base/darray.jl b/base/darray.jl index ec2dcd162f1cd..454801dc937a3 100644 --- a/base/darray.jl +++ b/base/darray.jl @@ -198,7 +198,7 @@ end function reshape{T,S<:Array}(A::DArray{T,1,S}, d::Dims) if prod(d) != length(A) - error("dimensions must be consistent with array size") + throw(DimensionMismatch("dimensions must be consistent with array size")) end DArray(d) do I sz = map(length,I) @@ -246,7 +246,7 @@ getindex(d::DArray) = d[1] getindex(d::DArray, I::Union(Int,UnitRange{Int})...) = sub(d,I...) function copy!(dest::SubOrDArray, src::SubOrDArray) - dest.dims == src.dims && dest.pmap == src.pmap && dest.indexes == src.indexes && dest.cuts == src.cuts || throw(ArgumentError("destination array doesn't fit to source array")) + dest.dims == src.dims && dest.pmap == src.pmap && dest.indexes == src.indexes && dest.cuts == src.cuts || throw(DimensionMismatch("destination array doesn't fit to source array")) for p in dest.pmap @spawnat p copy!(localpart(dest), localpart(src)) end diff --git a/base/datafmt.jl b/base/datafmt.jl index 161cb6f231324..7b4f42e21edec 100644 --- a/base/datafmt.jl +++ b/base/datafmt.jl @@ -19,7 +19,7 @@ function countlines(filename::AbstractString, eol::Char) end function countlines(io::IO, eol::Char) if !isascii(eol) - error("only ASCII line terminators are supported") + throw(ArgumentError("only ASCII line terminators are supported")) end a = Array(UInt8, 8192) nl = 0 @@ -142,8 +142,8 @@ end function DLMStore{T,S<:AbstractString}(::Type{T}, dims::NTuple{2,Integer}, has_header::Bool, sbuff::S, auto::Bool, eol::Char) (nrows,ncols) = dims - ((nrows == 0) || (ncols == 0)) && error("Empty input") - ((nrows < 0) || (ncols < 0)) && error("Invalid dimensions") + nrows <= 0 && throw(ArgumentError("number of rows in dims must be > 0, got $nrows")) + ncols <= 0 && throw(ArgumentError("number of columns in dims must be > 0, got $ncols")) hdr_offset = has_header ? 1 : 0 DLMStore{T,S}(fill(SubString(sbuff,1,0), 1, ncols), Array(T, nrows-hdr_offset, ncols), nrows, ncols, 0, 0, hdr_offset, sbuff, auto, eol, Array(Float64,1)) end @@ -239,10 +239,10 @@ function readdlm_string(sbuff::AbstractString, dlm::Char, T::Type, eol::Char, au dims = get(optsd, :dims, nothing) has_header = get(optsd, :header, get(optsd, :has_header, false)) - haskey(optsd, :has_header) && (optsd[:has_header] != has_header) && error("conflicting values for header and has_header") + haskey(optsd, :has_header) && (optsd[:has_header] != has_header) && throw(ArgumentError("conflicting values for header and has_header")) skipstart = get(optsd, :skipstart, 0) - (skipstart >= 0) || error("invalid value for skipstart") + (skipstart >= 0) || throw(ArgumentError("skipstart must be ≥ 0, got $skipstart")) skipblanks = get(optsd, :skipblanks, true) @@ -279,9 +279,9 @@ const deprecated_opts = Dict(:has_header => :header) function val_opts(opts) d = Dict{Symbol,Union(Bool,NTuple{2,Integer},Char,Integer)}() for (opt_name, opt_val) in opts - !in(opt_name, valid_opts) && error("unknown option $opt_name") + !in(opt_name, valid_opts) && throw(ArgumentError("unknown option $opt_name")) opt_typ = valid_opt_types[findfirst(valid_opts, opt_name)] - !isa(opt_val, opt_typ) && error("$opt_name should be of type $opt_typ") + !isa(opt_val, opt_typ) && throw(ArgumentError("$opt_name should be of type $opt_typ, got $(typeof(opt_val))")) d[opt_name] = opt_val haskey(deprecated_opts, opt_name) && warn("$opt_name is deprecated, use $(deprecated_opts[opt_name]) instead") end diff --git a/base/dict.jl b/base/dict.jl index a5135652694dd..e2f907514dea1 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -573,7 +573,7 @@ end function setindex!{K,V}(h::Dict{K,V}, v0, key0) key = convert(K,key0) if !isequal(key,key0) - error(key0, " is not a valid key for type ", K) + throw(ArgumentError("$key0 is not a valid key for type $K")) end v = convert(V, v0) @@ -592,7 +592,7 @@ end function get!{K,V}(h::Dict{K,V}, key0, default) key = convert(K,key0) if !isequal(key,key0) - error(key0, " is not a valid key for type ", K) + throw(ArgumentError("$key0 is not a valid key for type $K")) end index = ht_keyindex2(h, key) @@ -607,7 +607,7 @@ end function get!{K,V}(default::Callable, h::Dict{K,V}, key0) key = convert(K,key0) if !isequal(key,key0) - error(key0, " is not a valid key for type ", K) + throw(ArgumentError("$key0 is not a valid key for type $K")) end index = ht_keyindex2(h, key) @@ -625,7 +625,9 @@ macro get!(h, key0, default) quote K, V = eltype($(esc(h))) key = convert(K, $(esc(key0))) - isequal(key, $(esc(key0))) || error($(esc(key0)), " is not a valid key for type ", K) + if !isequal(key, $(esc(key0))) + throw(ArgumentError(string($(esc(key0)), " is not a valid key for type ", K))) + end idx = ht_keyindex2($(esc(h)), key) if idx < 0 idx = -idx diff --git a/base/docs.jl b/base/docs.jl index 23df4d04d1031..b1df32c368977 100644 --- a/base/docs.jl +++ b/base/docs.jl @@ -173,8 +173,7 @@ fexpr(ex) = isexpr(ex, :function) || (isexpr(ex, :(=)) && isexpr(ex.args[1], :ca function docm(meta, def) def′ = unblock(def) - isexpr(def′, :macro) && return namedoc(meta, def, - symbol(string("@", namify(def′)))) + isexpr(def′, :macro) && return namedoc(meta, def, symbol("@", namify(def′))) isexpr(def′, :type) && return namedoc(meta, def, namify(def′.args[2])) isexpr(def′, :abstract) && return namedoc(meta, def, namify(def′)) fexpr(def′) && return funcdoc(meta, def) diff --git a/base/dsp.jl b/base/dsp.jl index e8e611bff323e..cf65e18c2b865 100644 --- a/base/dsp.jl +++ b/base/dsp.jl @@ -22,10 +22,12 @@ end # (and does so by default) function filt!{T,S,N}(out::AbstractArray, b::Union(AbstractVector, Number), a::Union(AbstractVector, Number), x::AbstractArray{T}, si::AbstractArray{S,N}=_zerosi(b,a,T)) - isempty(b) && error("b must be non-empty") - isempty(a) && error("a must be non-empty") - a[1] == 0 && error("a[1] must be nonzero") - size(x) != size(out) && error("out size must match x") + isempty(b) && throw(ArgumentError("filter vector b must be non-empty")) + isempty(a) && throw(ArgumentError("filter vector a must be non-empty")) + a[1] == 0 && throw(ArgumentError("filter vector a[1] must be nonzero")) + if size(x) != size(out) + thow(ArgumentError("output size $(size(out)) must match input size $(size(x))")) + end as = length(a) bs = length(b) @@ -33,8 +35,12 @@ function filt!{T,S,N}(out::AbstractArray, b::Union(AbstractVector, Number), a::U silen = sz - 1 ncols = trailingsize(x,2) - size(si, 1) != silen && error("si must have max(length(a),length(b))-1 rows") - N > 1 && trailingsize(si,2) != ncols && error("si must either be a vector or have the same number of columns as x") + if size(si, 1) != silen + throw(ArgumentError("initial state vector si must have max(length(a),length(b))-1 rows")) + end + if N > 1 && trailingsize(si,2) != ncols + throw(ArgumentError("initial state vector si must be a vector or have the same number of columns as x")) + end size(x,1) == 0 && return out sz == 1 && return scale!(out, x, b[1]/a[1]) # Simple scaling without memory @@ -187,10 +193,10 @@ fftwcopy{T<:Complex}(X::StridedArray{T}) = complex128(X) for (f, fr2r, Y, Tx) in ((:dct, :r2r, :Y, :Number), (:dct!, :r2r!, :X, :fftwNumber)) - plan_f = symbol(string("plan_",f)) - plan_fr2r = symbol(string("plan_",fr2r)) - fi = symbol(string("i",f)) - plan_fi = symbol(string("plan_",fi)) + plan_f = symbol("plan_",f) + plan_fr2r = symbol("plan_",fr2r) + fi = symbol("i",f) + plan_fi = symbol("plan_",fi) Ycopy = Y == :X ? 0 : :(Y = fftwcopy(X)) @eval begin function $f{T<:$Tx}(X::StridedArray{T}, region) diff --git a/base/env.jl b/base/env.jl index ebc40a10fa137..edc226571d45f 100644 --- a/base/env.jl +++ b/base/env.jl @@ -33,7 +33,7 @@ function _jl_win_getenv(s::UTF16String,len::UInt32) val=zeros(UInt16,len) ret=ccall(:GetEnvironmentVariableW,stdcall,UInt32,(Ptr{UInt16},Ptr{UInt16},UInt32),s,val,len) if ret==0 || ret != len-1 || val[end] != 0 - error(string("system error getenv: ", s, ' ', len, "-1 != ", ret, ": ", FormatMessage())) + error(string("getenv: ", s, ' ', len, "-1 != ", ret, ": ", FormatMessage())) end val end @@ -120,7 +120,7 @@ done(::EnvHash, i) = (ccall(:jl_environ, Any, (Int32,), i) == nothing) function next(::EnvHash, i) env = ccall(:jl_environ, Any, (Int32,), i) if env == nothing - error(BoundsError) + throw(BoundsError()) end env::ByteString m = match(r"^(.*?)=(.*)$"s, env) diff --git a/base/exports.jl b/base/exports.jl index df72a4e05f70a..46014fc6b11c0 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -30,6 +30,7 @@ export BitArray, BitMatrix, BitVector, + BufferStream, CartesianIndex, CartesianRange, CFILE, @@ -408,6 +409,7 @@ export mod1, modf, mod2pi, + muladd, nextfloat, nextpow, nextpow2, @@ -1218,6 +1220,7 @@ export nprocs, nworkers, pmap, + process_messages, procs, put!, remotecall, diff --git a/base/expr.jl b/base/expr.jl index 14cc00222dc05..10554f9bdcd2a 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -5,7 +5,7 @@ symbol(s::ASCIIString) = symbol(s.data) symbol(s::UTF8String) = symbol(s.data) symbol(a::Array{UInt8,1}) = ccall(:jl_symbol_n, Any, (Ptr{UInt8}, Int32), a, length(a))::Symbol -symbol(x::Char) = symbol(string(x)) +symbol(x...) = symbol(string(x...)) gensym() = ccall(:jl_gensym, Any, ())::Symbol diff --git a/base/fftw.jl b/base/fftw.jl index 3022566dc40c6..f728ce80a6a77 100644 --- a/base/fftw.jl +++ b/base/fftw.jl @@ -417,9 +417,9 @@ complexfloat{T<:Complex}(X::StridedArray{T}) = complex128(X) # along with in-place variants fft! and plan_fft! if feasible. for (f,direction) in ((:fft,:FORWARD), (:bfft,:BACKWARD)) - f! = symbol(string(f,"!")) - plan_f = symbol(string("plan_",f)) - plan_f! = symbol(string("plan_",f,"!")) + f! = symbol(f,"!") + plan_f = symbol("plan_",f) + plan_f! = symbol("plan_",f,"!") @eval begin function $f{T<:fftwComplex}(X::StridedArray{T}, region) Y = similar(X, T) @@ -503,8 +503,8 @@ normalization(X::StridedArray) = 1 / length(X) # Normalized ifft inverse transforms: for (f,fb) in ((:ifft,:bfft), (:ifft!,:bfft!)) - pf = symbol(string("plan_", f)) - pfb = symbol(string("plan_", fb)) + pf = symbol("plan_", f) + pfb = symbol("plan_", fb) @eval begin $f(X, region) = scale!($fb(X, region), normalization(X, region)) $f(X) = scale!($fb(X), normalization(X)) diff --git a/base/file.jl b/base/file.jl index ed162486806e8..02e1a9382cea6 100644 --- a/base/file.jl +++ b/base/file.jl @@ -48,8 +48,8 @@ function mkpath(path::AbstractString, mode::Unsigned=0o777) mkdir(path, mode) end -mkdir(path::AbstractString, mode::Signed) = error("mode must be an unsigned integer; try 0o$mode") -mkpath(path::AbstractString, mode::Signed) = error("mode must be an unsigned integer; try 0o$mode") +mkdir(path::AbstractString, mode::Signed) = throw(ArgumentError("mode must be an unsigned integer; try 0o$mode")) +mkpath(path::AbstractString, mode::Signed) = throw(ArgumentError("mode must be an unsigned integer; try 0o$mode")) function rm(path::AbstractString; recursive::Bool=false) if islink(path) || !isdir(path) diff --git a/base/float.jl b/base/float.jl index 15097c53a7f80..89ca9c9e404c0 100644 --- a/base/float.jl +++ b/base/float.jl @@ -200,6 +200,8 @@ widen(::Type{Float32}) = Float64 fma(x::Float32, y::Float32, z::Float32) = box(Float32,fma_float(unbox(Float32,x),unbox(Float32,y),unbox(Float32,z))) fma(x::Float64, y::Float64, z::Float64) = box(Float64,fma_float(unbox(Float64,x),unbox(Float64,y),unbox(Float64,z))) +muladd(x::Float32, y::Float32, z::Float32) = box(Float32,muladd_float(unbox(Float32,x),unbox(Float32,y),unbox(Float32,z))) +muladd(x::Float64, y::Float64, z::Float64) = box(Float64,muladd_float(unbox(Float64,x),unbox(Float64,y),unbox(Float64,z))) # TODO: faster floating point div? # TODO: faster floating point fld? diff --git a/base/float16.jl b/base/float16.jl index 62dee7f60da50..9427812a3c995 100644 --- a/base/float16.jl +++ b/base/float16.jl @@ -136,6 +136,9 @@ end function fma(a::Float16, b::Float16, c::Float16) float16(fma(float32(a), float32(b), float32(c))) end +function muladd(a::Float16, b::Float16, c::Float16) + float16(muladd(float32(a), float32(b), float32(c))) +end for op in (:<,:<=,:isless) @eval ($op)(a::Float16, b::Float16) = ($op)(float32(a), float32(b)) end diff --git a/base/fs.jl b/base/fs.jl index 1e9cb80b9734d..0bb62a7fa9c18 100644 --- a/base/fs.jl +++ b/base/fs.jl @@ -84,7 +84,7 @@ open(f::AbstractString,flags) = open(f,flags,0) function close(f::File) if !f.open - error("file is already closed") + throw(ArgumentError("file \"$(f.path)\" is already closed")) end err = ccall(:jl_fs_close, Int32, (Int32,), f.handle) uv_error("close",err) @@ -99,7 +99,7 @@ function unlink(p::AbstractString) end function unlink(f::File) if isempty(f.path) - error("no path associated with this file") + throw(ArgumentError("no path associated with this file")) end if f.open close(f) @@ -127,13 +127,13 @@ end function sendfile(src::AbstractString, dst::AbstractString) src_file = open(src, JL_O_RDONLY) if !src_file.open - error("Src file is not open") + throw(ArgumentError("source file \"$(src.path)\" is not open")) end dst_file = open(dst, JL_O_CREAT | JL_O_TRUNC | JL_O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH | S_IWOTH) if !dst_file.open - error("Dst file is not open") + throw(ArgumentError("destination file \"$(dst.path)\" is not open")) end src_stat = stat(src_file) @@ -169,7 +169,7 @@ end function write(f::File, buf::Ptr{UInt8}, len::Integer, offset::Integer=-1) if !f.open - error("file is not open") + throw(ArgumentError("file \"$(f.path)\" is not open")) end err = ccall(:jl_fs_write, Int32, (Int32, Ptr{UInt8}, Csize_t, Int64), f.handle, buf, len, offset) @@ -179,7 +179,7 @@ end function write(f::File, c::UInt8) if !f.open - error("file is not open") + throw(ArgumentError("file \"$(f.path)\" is not open")) end err = ccall(:jl_fs_write_byte, Int32, (Int32, Cchar), f.handle, c) uv_error("write",err) @@ -214,7 +214,7 @@ end function read(f::File, ::Type{UInt8}) if !f.open - error("file is not open") + throw(ArgumentError("file \"$(f.path)\" is not open")) end ret = ccall(:jl_fs_read_byte, Int32, (Int32,), f.handle) uv_error("read", ret) diff --git a/base/gmp.jl b/base/gmp.jl index 80d6055ca955f..f879f519c5610 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -81,7 +81,7 @@ function Base.parseint_nocheck(::Type{BigInt}, s::AbstractString, base::Int) err = ccall((:__gmpz_set_str, :libgmp), Int32, (Ptr{BigInt}, Ptr{UInt8}, Int32), &z, convert(Ptr{UInt8},SubString(s,i)), base) - err == 0 || error("invalid big integer: $(repr(s))") + err == 0 || throw(ArgumentError("invalid BigInt: $(repr(s))")) return sgn < 0 ? -z : z end @@ -477,7 +477,7 @@ dec(n::BigInt) = base(10, n) hex(n::BigInt) = base(16, n) function base(b::Integer, n::BigInt) - 2 <= b <= 62 || error("invalid base: $b") + 2 <= b <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $b")) p = ccall((:__gmpz_get_str,:libgmp), Ptr{UInt8}, (Ptr{UInt8}, Cint, Ptr{BigInt}), C_NULL, b, &n) len = int(ccall(:strlen, Csize_t, (Ptr{UInt8},), p)) ASCIIString(pointer_to_array(p,len,true)) diff --git a/base/help.jl b/base/help.jl index 414460e5fb61d..8535529870331 100644 --- a/base/help.jl +++ b/base/help.jl @@ -179,7 +179,7 @@ function help(io::IO, x) end help(args...) = help(STDOUT, args...) -help(::IO, args...) = error("too many arguments to help()") +help(::IO, args...) = throw(ArgumentError("too many arguments to help()")) # check whether an expression is a qualified name, e.g. Base.FFTW.FORWARD isname(n::Symbol) = true diff --git a/base/intfuncs.jl b/base/intfuncs.jl index e312ff251c401..20befe5187573 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -275,7 +275,7 @@ const base36digits = ['0':'9','a':'z'] const base62digits = ['0':'9','A':'Z','a':'z'] function base(b::Int, x::Unsigned, pad::Int, neg::Bool) - if !(2 <= b <= 62) error("invalid base: $b") end + 2 <= b <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $b")) digits = b <= 36 ? base36digits : base62digits i = neg + max(pad,ndigits0z(x,b)) a = Array(UInt8,i) @@ -307,7 +307,7 @@ bits(x::Union(Int64,UInt64,Float64)) = bin(reinterpret(UInt64,x),64) bits(x::Union(Int128,UInt128)) = bin(reinterpret(UInt128,x),128) function digits{T<:Integer}(n::Integer, base::T=10, pad::Integer=1) - 2 <= base || error("invalid base: $base") + 2 <= base || throw(ArgumentError("base must be ≥ 2, got $base")) m = max(pad,ndigits0z(n,base)) a = zeros(T,m) digits!(a, n, base) @@ -315,7 +315,7 @@ function digits{T<:Integer}(n::Integer, base::T=10, pad::Integer=1) end function digits!{T<:Integer}(a::AbstractArray{T,1}, n::Integer, base::T=10) - 2 <= base || error("invalid base: $base") + 2 <= base || throw(ArgumentError("base must be ≥ 2, got $base")) for i = 1:length(a) a[i] = rem(n, base) n = div(n, base) diff --git a/base/intset.jl b/base/intset.jl index b9a7df2d016eb..c8f7c64e94434 100644 --- a/base/intset.jl +++ b/base/intset.jl @@ -168,7 +168,7 @@ isempty(s::IntSet) = function first(s::IntSet) n = next(s,0)[1] if n >= s.limit - error("set must be non-empty") + throw(ArgumentError("set must be non-empty")) end return n end @@ -184,7 +184,7 @@ function last(s::IntSet) end end end - error("set has no last element") + throw(ArgumentError("set has no last element")) end length(s::IntSet) = int(ccall(:bitvector_count, UInt64, (Ptr{UInt32}, UInt64, UInt64), s.bits, 0, s.limit)) + diff --git a/base/io.jl b/base/io.jl index 2edd4265d3ed3..62fb504e9e784 100644 --- a/base/io.jl +++ b/base/io.jl @@ -288,8 +288,8 @@ function unmark(io::IO) return true end -function reset(io::IO) - !ismarked(io) && error(io, " not marked") +function reset{T<:IO}(io::T) + ismarked(io) || throw(ArgumentError("$(T) not marked")) m = io.mark seek(io, m) io.mark = -1 # must be after seek, or seek may fail diff --git a/base/iobuffer.jl b/base/iobuffer.jl index e86f2c214553b..6490251916f18 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -59,7 +59,7 @@ function read_sub{T}(from::IOBuffer, a::Array{T}, offs, nel) throw(BoundsError()) end if !isbits(T) - error("read from IOBuffer only supports bits types or arrays of bits types; got "*string(T)) + throw(ArgumentError("read from IOBuffer only supports bits types or arrays of bits types; got "*string(T))) end read!(from, pointer(a, offs), nel*sizeof(T)) return a @@ -67,7 +67,7 @@ end read!(from::IOBuffer, p::Ptr, nb::Integer) = read!(from, p, int(nb)) function read!(from::IOBuffer, p::Ptr, nb::Int) - if !from.readable error("read failed") end + from.readable || throw(ArgumentError("read failed, IOBuffer is not readable")) avail = nb_available(from) adv = min(avail,nb) ccall(:memcpy, Ptr{Void}, (Ptr{Void}, Ptr{Void}, UInt), p, pointer(from.data,from.ptr), adv) @@ -79,7 +79,7 @@ function read!(from::IOBuffer, p::Ptr, nb::Int) end function read(from::IOBuffer, ::Type{UInt8}) - if !from.readable error("read failed") end + from.readable || throw(ArgumentError("read failed, IOBuffer is not readable")) if from.ptr > from.size throw(EOFError()) end @@ -89,7 +89,7 @@ function read(from::IOBuffer, ::Type{UInt8}) end function peek(from::IOBuffer) - if !from.readable error("read failed") end + from.readable || throw(ArgumentError("read failed, IOBuffer is not readable")) if from.ptr > from.size throw(EOFError()) end @@ -113,7 +113,10 @@ function skip(io::IOBuffer, n::Integer) end function seek(io::IOBuffer, n::Integer) - !io.seekable && (!ismarked(io) || n!=io.mark) && error("seek failed") + if !io.seekable + ismarked(io) || throw(ArgumentError("seek failed, IOBuffer is not seekable and is not marked")) + n == io.mark || throw(ArgumentError("seek failed, IOBuffer is not seekable and n != mark")) + end io.ptr = min(n+1, io.size+1) return io end @@ -124,9 +127,10 @@ function seekend(io::IOBuffer) end function truncate(io::IOBuffer, n::Integer) - if !io.writable error("truncate failed") end - if !io.seekable error("truncate failed") end #because absolute offsets are meaningless - if n > io.maxsize || n < 0 error("truncate failed") end + io.writable || throw(ArgumentError("truncate failed, IOBuffer is not writeable")) + io.seekable || throw(ArgumentError("truncate failed, IOBuffer is not seekable")) + n < 0 && throw(ArgumentError("truncate failed, n bytes must be ≥ 0, got $n")) + n > io.maxsize && throw(ArgumentError("truncate failed, $(n) bytes is exceeds IOBuffer maxsize $(io.maxsize)")) if n > length(io.data) resize!(io.data, n) end @@ -138,8 +142,8 @@ function truncate(io::IOBuffer, n::Integer) end function compact(io::IOBuffer) - if !io.writable error("compact failed") end - if io.seekable error("compact failed") end + io.writable || throw(ArgumentError("compact failed, IOBuffer is not writeable")) + io.seekable && throw(ArgumentError("compact failed, IOBuffer is seekable")) local ptr::Int, bytes_to_move::Int if ismarked(io) && io.mark < io.ptr if io.mark == 0 return end @@ -158,9 +162,9 @@ function compact(io::IOBuffer) end function ensureroom(io::IOBuffer, nshort::Int) - if !io.writable error("ensureroom failed") end + io.writable || throw(ArgumentError("ensureroom failed, IOBuffer is not writeable")) if !io.seekable - if nshort < 0 error("ensureroom failed") end + nshort >= 0 || throw(ArgumentError("ensureroom failed, requested number of bytes must be ≥ 0, got $nshort")) if !ismarked(io) && io.ptr > 1 && io.size <= io.ptr - 1 io.ptr = 1 io.size = 0 @@ -199,8 +203,8 @@ function close(io::IOBuffer) end isopen(io::IOBuffer) = io.readable || io.writable || io.seekable || nb_available(io) > 0 function bytestring(io::IOBuffer) - if !io.readable error("bytestring read failed") end - if !io.seekable error("bytestring read failed") end + io.readable || throw(ArgumentError("bytestring read failed, IOBuffer is not readable")) + io.seekable || throw(ArgumentError("bytestring read failed, IOBuffer is not seekable")) bytestring(pointer(io.data), io.size) end function takebuf_array(io::IOBuffer) @@ -234,7 +238,7 @@ end write(to::IOBuffer, p::Ptr, nb::Integer) = write(to, p, int(nb)) function write(to::IOBuffer, p::Ptr, nb::Int) - !to.writable && error("write failed") + to.writable || throw(ArgumentError("write failed, IOBuffer is not writeable")) ensureroom(to, nb) ptr = (to.append ? to.size+1 : to.ptr) nb = min(nb, length(to.data) - ptr + 1) @@ -262,7 +266,7 @@ end write(to::IOBuffer, a::Array) = write_sub(to, a, 1, length(a)) function write(to::IOBuffer, a::UInt8) - if !to.writable error("write failed") end + to.writable || throw(ArgumentError("write failed, IOBuffer is not writeable")) ensureroom(to, 1) ptr = (to.append ? to.size+1 : to.ptr) if ptr > to.maxsize diff --git a/base/iostream.jl b/base/iostream.jl index fe77084f35967..b6f7820559fa9 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -37,7 +37,7 @@ end iswritable(s::IOStream) = bool(ccall(:ios_get_writable, Cint, (Ptr{Void},), s.ios)) isreadable(s::IOStream) = bool(ccall(:ios_get_readable, Cint, (Ptr{Void},), s.ios)) modestr(s::IO) = modestr(isreadable(s), iswritable(s)) -modestr(r::Bool, w::Bool) = r ? (w ? "r+" : "r") : (w ? "w" : error("Neither readable nor writable")) +modestr(r::Bool, w::Bool) = r ? (w ? "r+" : "r") : (w ? "w" : throw(ArgumentError("neither readable nor writable"))) function truncate(s::IOStream, n::Integer) systemerror("truncate", ccall(:ios_trunc, Int32, (Ptr{Void}, UInt), s.ios, n) != 0) @@ -128,7 +128,7 @@ function open(fname::AbstractString, mode::AbstractString) mode == "w+" ? open(fname, true , true , true , true , false) : mode == "a" ? open(fname, false, true , true , false, true ) : mode == "a+" ? open(fname, true , true , true , false, true ) : - error("invalid open mode: ", mode) + throw(ArgumentError("invalid open mode: $mode")) end function open(f::Function, args...) @@ -147,7 +147,7 @@ write(s::IOStream, b::UInt8) = int(ccall(:ios_putc, Int32, (UInt8, Ptr{Void}), b function write{T}(s::IOStream, a::Array{T}) if isbits(T) if !iswritable(s) - error("attempt to write to a read-only IOStream") + throw(ArgumentError("write failed, IOStream is not writeable")) end int(ccall(:ios_write, UInt, (Ptr{Void}, Ptr{Void}, UInt), s.ios, a, length(a)*sizeof(T))) @@ -158,7 +158,7 @@ end function write(s::IOStream, p::Ptr, nb::Integer) if !iswritable(s) - error("attempt to write to a read-only IOStream") + throw(ArgumentError("write failed, IOStream is not writeable")) end int(ccall(:ios_write, UInt, (Ptr{Void}, Ptr{Void}, UInt), s.ios, p, nb)) end @@ -205,7 +205,7 @@ end function write(s::IOStream, c::Char) if !iswritable(s) - error("attempt to write to a read-only IOStream") + throw(ArgumentError("write failed, IOStream is not writeable")) end int(ccall(:ios_pututf8, Int32, (Ptr{Void}, Char), s.ios, c)) end diff --git a/base/libc.jl b/base/libc.jl index 29bf59aa3ce4e..23e5d1e4af076 100644 --- a/base/libc.jl +++ b/base/libc.jl @@ -55,7 +55,8 @@ function strptime(fmt::AbstractString, timestr::AbstractString) # exposed in the API. # tm.isdst = -1 if r == C_NULL - error("invalid arguments") + #TODO: better error message + throw(ArgumentError("invalid arguments")) end @osx_only begin # if we didn't explicitly parse the weekday or year day, use mktime diff --git a/base/linalg/arnoldi.jl b/base/linalg/arnoldi.jl index e79746ab3afc2..708acea8d657f 100644 --- a/base/linalg/arnoldi.jl +++ b/base/linalg/arnoldi.jl @@ -20,7 +20,7 @@ function eigs(A, B; nev = nevmax warn("nev should be at most $nevmax") end - nev > 0 || throw(ArgumentError("nev must be at least one")) + nev > 0 || throw(ArgumentError("requested number of eigen values (nev) must be ≥ 1, got $nev")) ncvmin = nev + (sym ? 1 : 2) if ncv < ncvmin warn("ncv should be at least $ncvmin") @@ -35,8 +35,11 @@ function eigs(A, B; warn("Use symbols instead of strings for specifying which eigenvalues to compute") which=symbol(which) end - which == :LM || which == :SM || which == :LR || which == :SR || which == :LI || which == :SI || which == :BE || error("invalid value for which") - which != :BE || sym || error("which = :BE only possible for real symmetric problem") + if (which != :LM && which != :SM && which != :LR && which != :SR && + which != :LI && which != :SI && which != :BE) + throw(ArgumentError("which must be :LM, :SM, :LR, :SR, :LI, :SI, or :BE, got $(repr(which))")) + end + which != :BE || sym || throw(ArgumentError("which=:BE only possible for real symmetric problem")) isshift && which == :SM && warn("use of :SM in shift-and-invert mode is not recommended, use :LM to find eigenvalues closest to sigma") if which==:SM && !isshift # transform into shift-and-invert method with sigma = 0 @@ -46,13 +49,13 @@ function eigs(A, B; end if sigma != nothing && !iscmplx && isa(sigma,Complex) - error("complex shifts for real problems are not yet supported") + throw(ArgumentError("complex shifts for real problems are not yet supported")) end sigma = isshift ? convert(T,sigma) : zero(T) if !isempty(v0) length(v0)==n || throw(DimensionMismatch()) - eltype(v0)==T || error("Starting vector must have eltype $T") + eltype(v0)==T || throw(ArgumentError("starting vector must have element type $T, got $(eltype(v0))")) end whichstr = "LM" @@ -66,10 +69,10 @@ function eigs(A, B; whichstr = (!sym ? "SR" : "SA") end if which == :LI - whichstr = (!sym ? "LI" : error("largest imaginary is meaningless for symmetric eigenvalue problems")) + whichstr = (!sym ? "LI" : throw(ArgumentError("largest imaginary is meaningless for symmetric eigenvalue problems"))) end if which == :SI - whichstr = (!sym ? "SI" : error("smallest imaginary is meaningless for symmetric eigenvalue problems")) + whichstr = (!sym ? "SI" : throw(ArgumentError("smallest imaginary is meaningless for symmetric eigenvalue problems"))) end # Refer to ex-*.doc files in ARPACK/DOCUMENTS for calling sequence @@ -123,19 +126,21 @@ size(s::SVDOperator) = s.m + s.n, s.m + s.n issym(s::SVDOperator) = true function svds{S}(X::S; nsv::Int = 6, ritzvec::Bool = true, tol::Float64 = 0.0, maxiter::Int = 1000) - if nsv > minimum(size(X)); error("nsv($nsv) should be at most $(minimum(size(X)))"); end - - otype = eltype(X) - ex = eigs(SVDOperator{otype,S}(X), I; ritzvec = ritzvec, nev = 2*nsv, tol = tol, maxiter = maxiter) - ind = [1:2:nsv*2] - sval = abs(ex[1][ind]) + if nsv < 1 + throw(ArgumentError("number of singular values (nsv) must be ≥ 1, got $nsv")) + end + if nsv > minimum(size(X)) + throw(ArgumentError("number of singular values (nsv) must be ≤ $(minimum(size(X))), got $nsv")) + end + otype = eltype(X) + ex = eigs(SVDOperator{otype,S}(X), I; ritzvec = ritzvec, nev = 2*nsv, tol = tol, maxiter = maxiter) + ind = [1:2:nsv*2] + sval = abs(ex[1][ind]) - if ! ritzvec - return sval, ex[2], ex[3], ex[4], ex[5] - end + ritzvec || return (sval, ex[2], ex[3], ex[4], ex[5]) - ## calculating singular vectors - left_sv = sqrt(2) * ex[2][ 1:size(X,1), ind ] .* sign(ex[1][ind]') - right_sv = sqrt(2) * ex[2][ size(X,1)+1:end, ind ] - return left_sv, sval, right_sv, ex[3], ex[4], ex[5], ex[6] + # calculating singular vectors + left_sv = sqrt(2) * ex[2][ 1:size(X,1), ind ] .* sign(ex[1][ind]') + right_sv = sqrt(2) * ex[2][ size(X,1)+1:end, ind ] + return (left_sv, sval, right_sv, ex[3], ex[4], ex[5], ex[6]) end diff --git a/base/linalg/arpack.jl b/base/linalg/arpack.jl index f3111866601cd..be4a1dd9725be 100644 --- a/base/linalg/arpack.jl +++ b/base/linalg/arpack.jl @@ -94,7 +94,7 @@ function aupd_wrapper(T, matvecA::Function, matvecB::Function, solveSI::Function error("Internal ARPACK error") end else - error("ARPACK mode not yet supported") + throw(ArgumentError("ARPACK mode ($mode) not yet supported")) end end @@ -179,7 +179,7 @@ function eupd_wrapper(T, n::Integer, sym::Bool, cmplx::Bool, bmat::ASCIIString, evec[:,j] = v[:,j] j += 1 else - error("Arpack unexpected behavior") + error("ARPACK unexpected behavior") end end diff --git a/base/linalg/bidiag.jl b/base/linalg/bidiag.jl index bf8fd97418af7..af6b3ccde19e4 100644 --- a/base/linalg/bidiag.jl +++ b/base/linalg/bidiag.jl @@ -7,13 +7,20 @@ type Bidiagonal{T} <: AbstractMatrix{T} length(ev)==length(dv)-1 ? new(dv, ev, isupper) : throw(DimensionMismatch()) end end - Bidiagonal{T}(dv::AbstractVector{T}, ev::AbstractVector{T}, isupper::Bool)=Bidiagonal{T}(copy(dv), copy(ev), isupper) Bidiagonal{T}(dv::AbstractVector{T}, ev::AbstractVector{T}) = error("Did you want an upper or lower Bidiagonal? Try again with an additional true (upper) or false (lower) argument.") #Convert from BLAS uplo flag to boolean internal -Bidiagonal(dv::AbstractVector, ev::AbstractVector, uplo::BlasChar) = Bidiagonal(copy(dv), copy(ev), uplo=='U' ? true : uplo=='L' ? false : error("Bidiagonal can only be upper 'U' or lower 'L' but you said '$uplo''")) - +Bidiagonal(dv::AbstractVector, ev::AbstractVector, uplo::BlasChar) = begin + if uplo === 'U' + isupper = true + elseif uplo === 'L' + isupper = false + else + throw(ArgumentError("Bidiagonal uplo argument must be upper 'U' or lower 'L', got $(repr(uplo))")) + end + Bidiagonal(copy(dv), copy(ev), isupper) +end function Bidiagonal{Td,Te}(dv::AbstractVector{Td}, ev::AbstractVector{Te}, isupper::Bool) T = promote_type(Td,Te) Bidiagonal(convert(Vector{T}, dv), convert(Vector{T}, ev), isupper) @@ -61,7 +68,7 @@ function show(io::IO, M::Bidiagonal) end size(M::Bidiagonal) = (length(M.dv), length(M.dv)) -size(M::Bidiagonal, d::Integer) = d<1 ? error("dimension out of range") : (d<=2 ? length(M.dv) : 1) +size(M::Bidiagonal, d::Integer) = d<1 ? throw(ArgumentError("dimension must be ≥ 1, got $d")) : (d<=2 ? length(M.dv) : 1) #Elementary operations for func in (:conj, :copy, :round, :trunc, :floor, :ceil) @@ -119,18 +126,15 @@ SpecialMatrix = Union(Diagonal, Bidiagonal, SymTridiagonal, Tridiagonal, Abstrac #Generic multiplication for func in (:*, :Ac_mul_B, :A_mul_Bc, :/, :A_rdiv_Bc) - @eval begin - ($func){T}(A::Bidiagonal{T}, B::AbstractVector{T}) = ($func)(full(A), B) - end + @eval ($func){T}(A::Bidiagonal{T}, B::AbstractVector{T}) = ($func)(full(A), B) end - #Linear solvers A_ldiv_B!(A::Union(Bidiagonal, AbstractTriangular), b::AbstractVector) = naivesub!(A, b) At_ldiv_B!(A::Union(Bidiagonal, AbstractTriangular), b::AbstractVector) = naivesub!(transpose(A), b) Ac_ldiv_B!(A::Union(Bidiagonal, AbstractTriangular), b::AbstractVector) = naivesub!(ctranspose(A), b) -for func in (:A_ldiv_B!, :Ac_ldiv_B!, :At_ldiv_B!) @eval begin - function ($func)(A::Union(Bidiagonal, AbstractTriangular), B::AbstractMatrix) +for func in (:A_ldiv_B!, :Ac_ldiv_B!, :At_ldiv_B!) + @eval function ($func)(A::Union(Bidiagonal, AbstractTriangular), B::AbstractMatrix) tmp = similar(B[:,1]) n = size(B, 1) for i = 1:size(B,2) @@ -140,9 +144,9 @@ for func in (:A_ldiv_B!, :Ac_ldiv_B!, :At_ldiv_B!) @eval begin end B end -end end -for func in (:A_ldiv_Bt!, :Ac_ldiv_Bt!, :At_ldiv_Bt!) @eval begin - function ($func)(A::Union(Bidiagonal, AbstractTriangular), B::AbstractMatrix) +end +for func in (:A_ldiv_Bt!, :Ac_ldiv_Bt!, :At_ldiv_Bt!) + @eval function ($func)(A::Union(Bidiagonal, AbstractTriangular), B::AbstractMatrix) tmp = similar(B[:, 2]) m, n = size(B) nm = n*m @@ -153,7 +157,7 @@ for func in (:A_ldiv_Bt!, :Ac_ldiv_Bt!, :At_ldiv_Bt!) @eval begin end B end -end end +end #Generic solver using naive substitution function naivesub!{T}(A::Bidiagonal{T}, b::AbstractVector, x::AbstractVector = b) diff --git a/base/linalg/bitarray.jl b/base/linalg/bitarray.jl index 37229c087236b..2b4d15d1585fc 100644 --- a/base/linalg/bitarray.jl +++ b/base/linalg/bitarray.jl @@ -181,7 +181,7 @@ function istril(A::BitMatrix) end function findmax(a::BitArray) - length(a)==0 && error("findmax: array is empty") + isempty(a) && throw(ArgumentError("BitArray must be non-empty")) m, mi = false, 1 ti = 1 ac = a.chunks @@ -194,7 +194,7 @@ function findmax(a::BitArray) end function findmin(a::BitArray) - length(a)==0 && error("findmin: array is empty") + isempty(a) && throw(ArgumentError("BitArray must be non-empty")) m, mi = true, 1 ti = 1 ac = a.chunks diff --git a/base/linalg/bunchkaufman.jl b/base/linalg/bunchkaufman.jl index b5fecfd3fd9db..2752c4785945d 100644 --- a/base/linalg/bunchkaufman.jl +++ b/base/linalg/bunchkaufman.jl @@ -12,7 +12,7 @@ end BunchKaufman{T}(LD::AbstractMatrix{T}, ipiv::Vector{BlasInt}, uplo::Char, symmetric::Bool) = BunchKaufman{T,typeof(LD)}(LD, ipiv, uplo, symmetric) function bkfact!{T<:BlasReal}(A::StridedMatrix{T}, uplo::Symbol=:U, symmetric::Bool=issym(A)) - symmetric || error("The Bunch-Kaufman decomposition is only valid for symmetric matrices") + symmetric || throw(ArgumentError("Bunch-Kaufman decomposition is only valid for symmetric matrices")) LD, ipiv = LAPACK.sytrf!(char_uplo(uplo) , A) BunchKaufman(LD, ipiv, char_uplo(uplo), symmetric) end diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index dae4ca8cd332b..4a08996913068 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -437,7 +437,7 @@ function cond(A::StridedMatrix, p::Real=2) chksquare(A) return cond(lufact(A), p) end - throw(ArgumentError("invalid p-norm p=$p. Valid: 1, 2 or Inf")) + throw(ArgumentError("p-norm must be 1, 2 or Inf, got $p")) end ## Lyapunov and Sylvester equation diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index d2c52e328271b..bf214066e3c96 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -19,7 +19,7 @@ end copy!(D1::Diagonal, D2::Diagonal) = (copy!(D1.diag, D2.diag); D1) size(D::Diagonal) = (length(D.diag),length(D.diag)) -size(D::Diagonal,d::Integer) = d<1 ? error("dimension out of range") : (d<=2 ? length(D.diag) : 1) +size(D::Diagonal,d::Integer) = d<1 ? throw(ArgumentError("dimension must be ≥ 1, got $d")) : (d<=2 ? length(D.diag) : 1) fill!(D::Diagonal, x) = (fill!(D.diag, x); D) diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index d4c3507449a2e..d695f61fb6ac7 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -21,7 +21,7 @@ function generic_scale!(X::AbstractArray, s::Number) end function generic_scale!(C::AbstractArray, X::AbstractArray, s::Number) - length(C) == length(X) || error("C must be the same length as X") + length(C) == length(X) | throw(DimensionMismatch("first array argument must be the same length as the second array argument")) for i = 1:length(X) @inbounds C[i] = X[i]*s end diff --git a/base/linalg/givens.jl b/base/linalg/givens.jl index 969d2898f9e05..718947a50a226 100644 --- a/base/linalg/givens.jl +++ b/base/linalg/givens.jl @@ -206,13 +206,13 @@ function givensAlgorithm{T<:FloatingPoint}(f::Complex{T}, g::Complex{T}) end function givens{T}(f::T, g::T, i1::Integer, i2::Integer) - i1 < i2 || error("second index must be larger than the first") + i1 < i2 || throw(ArgumentError("second index must be larger than the first")) c, s, r = givensAlgorithm(f, g) Givens(i1, i2, convert(T, c), convert(T, s)), r end function givens{T}(A::AbstractMatrix{T}, i1::Integer, i2::Integer, col::Integer) - i1 < i2 || error("second index must be larger than the first") + i1 < i2 || throw(ArgumentError("second index must be larger than the first")) c, s, r = givensAlgorithm(A[i1,col], A[i2,col]) Givens(i1, i2, convert(T, c), convert(T, s)), r end diff --git a/base/linalg/lapack.jl b/base/linalg/lapack.jl index 014bff044545b..64a17439c04b1 100644 --- a/base/linalg/lapack.jl +++ b/base/linalg/lapack.jl @@ -25,9 +25,8 @@ end #Check that upper/lower (for special matrices) is correctly specified macro chkuplo() - :((uplo=='U' || uplo=='L') || throw(ArgumentError("""invalid uplo = $uplo - -Valid choices are 'U' (upper) or 'L' (lower)."""))) + :((uplo=='U' || uplo=='L') || + throw(ArgumentError(string("uplo argument must be 'U' (upper) or 'L' (lower), got ", repr(uplo))))) end subsetrows(X::AbstractVector, Y::AbstractArray, k) = Y[1:k] @@ -3193,7 +3192,7 @@ for (bdsdc, elty) in ldvt=ldu=max(1, n) lwork=3*n^2 + 4n else - error(string("COMPQ argument must be 'N', 'P' or 'I' but you said '",compq,"'")) + throw(ArgumentError("COMPQ argument must be 'N', 'P' or 'I', got $(repr(compq))")) end u = similar(d, $elty, (ldu, n)) vt= similar(d, $elty, (ldvt, n)) diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index 086dacc1da353..6332dda7ce5e4 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -21,8 +21,8 @@ for t in (:LowerTriangular, :UnitLowerTriangular, :UpperTriangular, :UnitUpperTr convert{T,S}(::Type{Matrix}, A::$t{T,S}) = convert(Matrix{T}, A) function similar{T,S,Tnew}(A::$t{T,S}, ::Type{Tnew}, dims::Dims) - dims[1] == dims[2] || throw(ArgumentError("a Triangular matrix must be square")) - length(dims) == 2 || throw(ArgumentError("a Triangular matrix must have two dimensions")) + dims[1] == dims[2] || throw(ArgumentError("Triangular matrix must be square")) + length(dims) == 2 || throw(ArgumentError("Triangular matrix must have two dimensions")) B = similar(A.data, Tnew, dims) return $t(B) end @@ -328,7 +328,7 @@ end ## Generic triangular multiplication function A_mul_B!(A::UpperTriangular, B::StridedVecOrMat) m, n = size(B, 1), size(B, 2) - m == size(A, 1) || throw(DimensionMismatch("left and right hand side doesn't fit")) + m == size(A, 1) || throw(DimensionMismatch("left and right hand side does not fit")) for j = 1:n for i = 1:m Bij = A.data[i,i]*B[i,j] @@ -342,7 +342,7 @@ function A_mul_B!(A::UpperTriangular, B::StridedVecOrMat) end function A_mul_B!(A::UnitUpperTriangular, B::StridedVecOrMat) m, n = size(B, 1), size(B, 2) - m == size(A, 1) || throw(DimensionMismatch("left and right hand side doesn't fit")) + m == size(A, 1) || throw(DimensionMismatch("left and right hand side does not fit")) for j = 1:n for i = 1:m Bij = B[i,j] @@ -357,7 +357,7 @@ end function A_mul_B!(A::LowerTriangular, B::StridedVecOrMat) m, n = size(B, 1), size(B, 2) - m == size(A, 1) || throw(DimensionMismatch("left and right hand side doesn't fit")) + m == size(A, 1) || throw(DimensionMismatch("left and right hand side does not fit")) for j = 1:n for i = m:-1:1 Bij = A.data[i,i]*B[i,j] @@ -371,7 +371,7 @@ function A_mul_B!(A::LowerTriangular, B::StridedVecOrMat) end function A_mul_B!(A::UnitLowerTriangular, B::StridedVecOrMat) m, n = size(B, 1), size(B, 2) - m == size(A, 1) || throw(DimensionMismatch("left and right hand side doesn't fit")) + m == size(A, 1) || throw(DimensionMismatch("left and right hand side does not fit")) for j = 1:n for i = m:-1:1 Bij = B[i,j] @@ -386,7 +386,7 @@ end function Ac_mul_B!(A::UpperTriangular, B::StridedVecOrMat) m, n = size(B, 1), size(B, 2) - m == size(A, 1) || throw(DimensionMismatch("left and right hand side doesn't fit")) + m == size(A, 1) || throw(DimensionMismatch("left and right hand side does not fit")) for j = 1:n for i = m:-1:1 Bij = A.data[i,i]*B[i,j] @@ -400,7 +400,7 @@ function Ac_mul_B!(A::UpperTriangular, B::StridedVecOrMat) end function Ac_mul_B!(A::UnitUpperTriangular, B::StridedVecOrMat) m, n = size(B, 1), size(B, 2) - m == size(A, 1) || throw(DimensionMismatch("left and right hand side doesn't fit")) + m == size(A, 1) || throw(DimensionMismatch("left and right hand side does not fit")) for j = 1:n for i = m:-1:1 Bij = B[i,j] @@ -415,7 +415,7 @@ end function Ac_mul_B!(A::LowerTriangular, B::StridedVecOrMat) m, n = size(B, 1), size(B, 2) - m == size(A, 1) || throw(DimensionMismatch("left and right hand side doesn't fit")) + m == size(A, 1) || throw(DimensionMismatch("left and right hand side does not fit")) for j = 1:n for i = 1:m Bij = A.data[i,i]*B[i,j] @@ -429,7 +429,7 @@ function Ac_mul_B!(A::LowerTriangular, B::StridedVecOrMat) end function Ac_mul_B!(A::UnitLowerTriangular, B::StridedVecOrMat) m, n = size(B, 1), size(B, 2) - m == size(A, 1) || throw(DimensionMismatch("left and right hand side doesn't fit")) + m == size(A, 1) || throw(DimensionMismatch("left and right hand side does not fit")) for j = 1:n for i = 1:m Bij = B[i,j] @@ -444,7 +444,7 @@ end function A_mul_B!(A::StridedMatrix, B::UpperTriangular) m, n = size(A) - size(B, 1) == n || throw(DimensionMismatch("left and right hand side doesn't fit")) + size(B, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) for i = 1:m for j = n:-1:1 Aij = A[i,j]*B[j,j] @@ -458,7 +458,7 @@ function A_mul_B!(A::StridedMatrix, B::UpperTriangular) end function A_mul_B!(A::StridedMatrix, B::UnitUpperTriangular) m, n = size(A) - size(B, 1) == n || throw(DimensionMismatch("left and right hand side doesn't fit")) + size(B, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) for i = 1:m for j = n:-1:1 Aij = A[i,j] @@ -473,7 +473,7 @@ end function A_mul_B!(A::StridedMatrix, B::LowerTriangular) m, n = size(A) - size(B, 1) == n || throw(DimensionMismatch("left and right hand side doesn't fit")) + size(B, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) for i = 1:m for j = 1:n Aij = A[i,j]*B[j,j] @@ -487,7 +487,7 @@ function A_mul_B!(A::StridedMatrix, B::LowerTriangular) end function A_mul_B!(A::StridedMatrix, B::UnitLowerTriangular) m, n = size(A) - size(B, 1) == n || throw(DimensionMismatch("left and right hand side doesn't fit")) + size(B, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) for i = 1:m for j = 1:n Aij = A[i,j] @@ -502,7 +502,7 @@ end function A_mul_Bc!(A::StridedMatrix, B::UpperTriangular) m, n = size(A) - size(B, 1) == n || throw(DimensionMismatch("left and right hand side doesn't fit")) + size(B, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) for i = 1:m for j = 1:n Aij = A[i,j]*B[j,j] @@ -516,7 +516,7 @@ function A_mul_Bc!(A::StridedMatrix, B::UpperTriangular) end function A_mul_Bc!(A::StridedMatrix, B::UnitUpperTriangular) m, n = size(A) - size(B, 1) == n || throw(DimensionMismatch("left and right hand side doesn't fit")) + size(B, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) for i = 1:m for j = 1:n Aij = A[i,j] @@ -531,7 +531,7 @@ end function A_mul_Bc!(A::StridedMatrix, B::LowerTriangular) m, n = size(A) - size(B, 1) == n || throw(DimensionMismatch("left and right hand side doesn't fit")) + size(B, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) for i = 1:m for j = n:-1:1 Aij = A[i,j]*B[j,j] @@ -545,7 +545,7 @@ function A_mul_Bc!(A::StridedMatrix, B::LowerTriangular) end function A_mul_Bc!(A::StridedMatrix, B::UnitLowerTriangular) m, n = size(A) - size(B, 1) == n || throw(DimensionMismatch("left and right hand side doesn't fit")) + size(B, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) for i = 1:m for j = n:-1:1 Aij = A[i,j] @@ -608,7 +608,7 @@ end function A_rdiv_B!(A::StridedMatrix, B::UpperTriangular) m, n = size(A) - size(A, 1) == n || throw(DimensionMismatch("left and right hand side doesn't fit")) + size(A, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) for i = 1:m for j = 1:n Aij = A[i,j] @@ -622,7 +622,7 @@ function A_rdiv_B!(A::StridedMatrix, B::UpperTriangular) end function A_rdiv_B!(A::StridedMatrix, B::UnitUpperTriangular) m, n = size(A) - size(A, 1) == n || throw(DimensionMismatch("left and right hand side doesn't fit")) + size(A, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) for i = 1:m for j = 1:n Aij = A[i,j] @@ -637,7 +637,7 @@ end function A_rdiv_B!(A::StridedMatrix, B::LowerTriangular) m, n = size(A) - size(A, 1) == n || throw(DimensionMismatch("left and right hand side doesn't fit")) + size(A, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) for i = 1:m for j = n:-1:1 Aij = A[i,j] @@ -651,7 +651,7 @@ function A_rdiv_B!(A::StridedMatrix, B::LowerTriangular) end function A_rdiv_B!(A::StridedMatrix, B::UnitLowerTriangular) m, n = size(A) - size(A, 1) == n || throw(DimensionMismatch("left and right hand side doesn't fit")) + size(A, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) for i = 1:m for j = n:-1:1 Aij = A[i,j] @@ -666,7 +666,7 @@ end function A_rdiv_Bc!(A::StridedMatrix, B::UpperTriangular) m, n = size(A) - size(A, 1) == n || throw(DimensionMismatch("left and right hand side doesn't fit")) + size(A, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) for i = 1:m for j = n:-1:1 Aij = A[i,j] @@ -680,7 +680,7 @@ function A_rdiv_Bc!(A::StridedMatrix, B::UpperTriangular) end function A_rdiv_Bc!(A::StridedMatrix, B::UnitUpperTriangular) m, n = size(A) - size(A, 1) == n || throw(DimensionMismatch("left and right hand side doesn't fit")) + size(A, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) for i = 1:m for j = n:-1:1 Aij = A[i,j] @@ -695,7 +695,7 @@ end function A_rdiv_Bc!(A::StridedMatrix, B::LowerTriangular) m, n = size(A) - size(A, 1) == n || throw(DimensionMismatch("left and right hand side doesn't fit")) + size(A, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) for i = 1:m for j = 1:n Aij = A[i,j] @@ -709,7 +709,7 @@ function A_rdiv_Bc!(A::StridedMatrix, B::LowerTriangular) end function A_rdiv_Bc!(A::StridedMatrix, B::UnitLowerTriangular) m, n = size(A) - size(A, 1) == n || throw(DimensionMismatch("left and right hand side doesn't fit")) + size(A, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) for i = 1:m for j = 1:n Aij = A[i,j] @@ -871,7 +871,7 @@ eigvals(A::AbstractTriangular) = diag(A) function eigvecs{T}(A::AbstractTriangular{T}) TT = promote_type(T, Float32) TT <: BlasFloat && return eigvecs(convert(AbstractMatrix{TT}, A)) - error("type not handled yet. Please submit a pull request.") + throw(ArgumentError("eigvecs type $(typeof(A)) not supported. Please submit a pull request.")) end det{T}(A::UnitUpperTriangular{T}) = one(T)*one(T) det{T}(A::UnitLowerTriangular{T}) = one(T)*one(T) diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index 5d77aff4db8d3..29b3d276fec84 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -37,7 +37,7 @@ end convert{T}(::Type{Matrix}, M::SymTridiagonal{T}) = convert(Matrix{T}, M) size(A::SymTridiagonal) = (length(A.dv), length(A.dv)) -size(A::SymTridiagonal, d::Integer) = d<1 ? error("dimension out of range") : (d<=2 ? length(A.dv) : 1) +size(A::SymTridiagonal, d::Integer) = d<1 ? throw(ArgumentError("dimension must be ≥ 1, got $d")) : (d<=2 ? length(A.dv) : 1) #Elementary operations for func in (:conj, :copy, :round, :trunc, :floor, :ceil) @@ -190,7 +190,7 @@ end function Tridiagonal{T}(dl::Vector{T}, d::Vector{T}, du::Vector{T}) n = length(d) if (length(dl) != n-1 || length(du) != n-1) - error(string("Cannot make Tridiagonal from incompatible lengths of subdiagonal, diagonal and superdiagonal: (", length(dl), ", ", length(d), ", ", length(du),")")) + throw(ArgumentError("Cannot make Tridiagonal from incompatible lengths of subdiagonal, diagonal and superdiagonal: ($(length(dl)), $(length(d)), $(length(du))")) end Tridiagonal(dl, d, du, zeros(T,n-2)) end @@ -199,7 +199,7 @@ function Tridiagonal{Tl, Td, Tu}(dl::Vector{Tl}, d::Vector{Td}, du::Vector{Tu}) end size(M::Tridiagonal) = (length(M.d), length(M.d)) -size(M::Tridiagonal, d::Integer) = d<1 ? error("dimension out of range") : (d<=2 ? length(M.d) : 1) +size(M::Tridiagonal, d::Integer) = d<1 ? throw(ArgumentError("dimension d must be ≥ 1, got $d")) : (d<=2 ? length(M.d) : 1) full{T}(M::Tridiagonal{T}) = convert(Matrix{T}, M) function convert{T}(::Type{Matrix{T}}, M::Tridiagonal{T}) @@ -273,7 +273,7 @@ convert{T}(::Type{Tridiagonal{T}},M::Tridiagonal) = Tridiagonal(convert(Vector{T convert{T}(::Type{AbstractMatrix{T}},M::Tridiagonal) = convert(Tridiagonal{T}, M) convert{T}(::Type{Tridiagonal{T}}, M::SymTridiagonal{T}) = Tridiagonal(M) convert{T}(::Type{SymTridiagonal{T}}, M::Tridiagonal) = M.dl==M.du ? (SymTridiagonal(M.dl, M.d)) : - error("Tridiagonal is not symmetric, cannot convert to SymTridiagonal") + throw(ArgumentError("Tridiagonal is not symmetric, cannot convert to SymTridiagonal")) convert{T}(::Type{SymTridiagonal{T}},M::SymTridiagonal) = SymTridiagonal(convert(Vector{T}, M.dv), convert(Vector{T}, M.ev)) function A_mul_B!(C::AbstractVecOrMat, A::Tridiagonal, B::AbstractVecOrMat) diff --git a/base/loading.jl b/base/loading.jl index a16024b38ec90..44702305ee14d 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -44,7 +44,7 @@ toplevel_load = true function require(name::AbstractString) path = find_in_node1_path(name) - path == nothing && error("$name not found") + path == nothing && throw(ArgumentError("$name not found in path")) if myid() == 1 && toplevel_load refs = Any[ @spawnat p _require(path) for p in filter(x->x!=1, procs()) ] @@ -74,7 +74,7 @@ end function reload(name::AbstractString) global toplevel_load path = find_in_node1_path(name) - path == nothing && error("$name not found") + path == nothing && throw(ArgumentError("$name not found in path")) refs = nothing if myid() == 1 && toplevel_load refs = Any[ @spawnat p reload_path(path) for p in filter(x->x!=1, procs()) ] diff --git a/base/math.jl b/base/math.jl index 2fa20782fa2f3..1b7a1b15ae2a8 100644 --- a/base/math.jl +++ b/base/math.jl @@ -59,7 +59,7 @@ macro evalpoly(z, p...) b = :($(esc(p[end-1]))) as = [] for i = length(p)-2:-1:1 - ai = symbol(string("a", i)) + ai = symbol("a", i) push!(as, :($ai = $a)) a = :($b + r*$ai) b = :($(esc(p[i])) - s * $ai) @@ -358,7 +358,7 @@ mod2pi(x::Float32) = float32(mod2pi(float64(x))) mod2pi(x::Int32) = mod2pi(float64(x)) function mod2pi(x::Int64) fx = float64(x) - fx == x || error("Integer argument to mod2pi is too large: $x") + fx == x || throw(ArgumentError("Int64 argument to mod2pi is too large: $x")) mod2pi(fx) end diff --git a/base/mmap.jl b/base/mmap.jl index f2f5ad6568b58..5c61a9d93a8c5 100644 --- a/base/mmap.jl +++ b/base/mmap.jl @@ -22,10 +22,10 @@ function mmap(len::Integer, prot::Integer, flags::Integer, fd, offset::Integer) const pagesize::Int = ccall(:jl_getpagesize, Clong, ()) # Check that none of the computations will overflow if len < 0 - error("requested size is negative") + throw(ArgumentError("requested size must be ≥ 0, got $len")) end if len > typemax(Int)-pagesize - error("requested size is too large") + throw(ArgumentError("requested size must be ≤ $(typemax(Int)-pagesize), got $len")) end # Set the offset to a page boundary offset_page::FileOffset = floor(Integer,offset/pagesize)*pagesize @@ -91,7 +91,7 @@ function mmap_stream_settings(s::IO) prot = PROT_READ | PROT_WRITE end if prot & PROT_READ == 0 - error("mmap requires read permissions on the file (choose r+)") + throw(ArgumentError("mmap requires read permissions on the file (choose r+)")) end flags = MAP_SHARED return prot, flags, (prot & PROT_WRITE) > 0 @@ -102,7 +102,7 @@ function mmap_array{T,N}(::Type{T}, dims::NTuple{N,Integer}, s::IO, offset::File prot, flags, iswrite = mmap_stream_settings(s) len = prod(dims)*sizeof(T) if len > typemax(Int) - error("file is too large to memory-map on this platform") + throw(ArgumentError("file is too large to memory-map on this platform")) end if iswrite && grow pmap, delta = mmap_grow(len, prot, flags, fd(s), offset) @@ -145,10 +145,10 @@ function mmap_array{T,N}(::Type{T}, dims::NTuple{N,Integer}, s::Union(IO,SharedM len = prod(dims)*sizeof(T) const granularity::Int = ccall(:jl_getallocationgranularity, Clong, ()) if len < 0 - error("requested size is negative") + throw(ArgumentError("requested size must be ≥ 0, got $len")) end if len > typemax(Int)-granularity - error("file is too large to memory-map on this platform") + throw(ArgumentError("file is too large ot memory-map on this platform")) end # Set the offset to a page boundary offset_page::FileOffset = div(offset, granularity)*granularity @@ -197,22 +197,22 @@ end function mmap_bitarray{N}(dims::NTuple{N,Integer}, s::IOStream, offset::FileOffset) iswrite = !isreadonly(s) n = 1 - for d in dims + for (i, d) in enumerate(dims) if d < 0 - error("invalid dimension size") + throw(ArgumentError("dimension size must be ≥ 0, got $d size for dimension $i")) end n *= d end nc = num_bit_chunks(n) if nc > typemax(Int) - error("file is too large to memory-map on this platform") + throw(ArgumentError("file is too large to memory-map on this platform")) end chunks = mmap_array(UInt64, (nc,), s, offset) if iswrite chunks[end] &= _msk_end(n) else if chunks[end] != chunks[end] & _msk_end(n) - error("the given file does not contain a valid BitArray of size ", join(dims, 'x'), " (open with \"r+\" mode to override)") + throw(ArgumentError("the given file does not contain a valid BitArray of size $(join(dims, 'x')) (open with \"r+\" mode to override)")) end end B = BitArray{N}(ntuple(N,i->0)...) diff --git a/base/mpfr.jl b/base/mpfr.jl index 607e6d4294174..2e71f5412b18b 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -80,7 +80,7 @@ end function BigFloat(x::AbstractString, base::Int) z = BigFloat() err = ccall((:mpfr_set_str, :libmpfr), Int32, (Ptr{BigFloat}, Ptr{UInt8}, Int32, Int32), &z, x, base, ROUNDING_MODE[end]) - if err != 0; error("incorrectly formatted number"); end + err == 0 || throw("incorrectly formatted number \"$x\"") return z end BigFloat(x::AbstractString) = BigFloat(x, 10) @@ -174,11 +174,16 @@ convert(::Type{Float64}, x::BigFloat) = ccall((:mpfr_get_d,:libmpfr), Float64, (Ptr{BigFloat},Int32), &x, ROUNDING_MODE[end]) convert(::Type{Float32}, x::BigFloat) = ccall((:mpfr_get_flt,:libmpfr), Float32, (Ptr{BigFloat},Int32), &x, ROUNDING_MODE[end]) +# TODO: avoid double rounding +convert(::Type{Float16}, x::BigFloat) = convert(Float16, convert(Float32, x)) call(::Type{Float64}, x::BigFloat, r::RoundingMode) = ccall((:mpfr_get_d,:libmpfr), Float64, (Ptr{BigFloat},Int32), &x, to_mpfr(r)) call(::Type{Float32}, x::BigFloat, r::RoundingMode) = ccall((:mpfr_get_flt,:libmpfr), Float32, (Ptr{BigFloat},Int32), &x, to_mpfr(r)) +# TODO: avoid double rounding +call(::Type{Float16}, x::BigFloat, r::RoundingMode) = + convert(Float16, call(Float32, x, r)) promote_rule{T<:Real}(::Type{BigFloat}, ::Type{T}) = BigFloat promote_rule{T<:FloatingPoint}(::Type{BigInt},::Type{T}) = BigFloat @@ -658,7 +663,7 @@ function from_mpfr(c::Integer) elseif c == 4 return RoundFromZero else - error("invalid MPFR rounding mode code") + throw(ArgumentError("invalid MPFR rounding mode code: $c")) end RoundingMode(c) end diff --git a/base/multi.jl b/base/multi.jl index adca59f51de42..b0c3d53959d29 100644 --- a/base/multi.jl +++ b/base/multi.jl @@ -303,7 +303,8 @@ function rmprocs(args...; waitfor = 0.0) else if haskey(map_pid_wrkr, i) push!(rmprocset, i) - remote_do(i, exit) + w = map_pid_wrkr[i] + kill(w.manager, i, w.config) end end end @@ -1286,6 +1287,12 @@ function connect(manager::ClusterManager, pid::Int, config::WorkerConfig) (s, s) end +function kill(manager::ClusterManager, pid::Int, config::WorkerConfig) + remote_do(pid, exit) # For TCP based transports this will result in a close of the socket + # at our end, which will result in a cleanup of the worker. + nothing +end + function connect_w2w(pid::Int, config::WorkerConfig) (rhost, rport) = get(config.connect_at) config.host = rhost diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 5b0505fe70de5..c4022ebaa5875 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1,7 +1,8 @@ ### Multidimensional iterators module IteratorsMD -import Base: eltype, length, start, _start, done, next, getindex, setindex!, linearindexing, min, max +import Base: eltype, length, start, _start, done, next, last, getindex, setindex!, linearindexing, min, max +import Base: simd_outer_range, simd_inner_length, simd_index import Base: @nref, @ncall, @nif, @nexprs, LinearFast, LinearSlow, to_index export CartesianIndex, CartesianRange, eachindex @@ -148,10 +149,31 @@ done{I<:CartesianIndex}(iter::CartesianRange{I}, state::(Bool, I)) = state[1] stagedfunction length{I<:CartesianIndex}(iter::CartesianRange{I}) N = length(I) + N == 0 && return 1 args = [:(iter.stop[$i]-iter.start[$i]+1) for i=1:N] Expr(:call,:*,args...) end +last(iter::CartesianRange) = iter.stop + +stagedfunction simd_outer_range{I}(iter::CartesianRange{I}) + N = length(I) + N == 0 && return :(CartesianRange(CartesianIndex{0}(),CartesianIndex{0}())) + startargs = [:(iter.start[$i]) for i=2:N] + stopargs = [:(iter.stop[$i]) for i=2:N] + :(CartesianRange(CartesianIndex{$(N-1)}($(startargs...)), CartesianIndex{$(N-1)}($(stopargs...)))) +end + +simd_inner_length{I<:CartesianIndex{0}}(iter::CartesianRange{I}, ::CartesianIndex) = 1 +simd_inner_length(iter::CartesianRange, I::CartesianIndex) = iter.stop[1]-iter.start[1]+1 + +simd_index{I<:CartesianIndex{0}}(iter::CartesianRange{I}, ::CartesianIndex, I1::Int) = iter.start +stagedfunction simd_index{N}(iter::CartesianRange, Ilast::CartesianIndex{N}, I1::Int) + args = [d == 1 ? :(I1+iter.start[1]) : :(Ilast[$(d-1)]) for d = 1:N+1] + meta = Expr(:meta, :inline) + :($meta; CartesianIndex{$(N+1)}($(args...))) +end + end # IteratorsMD using .IteratorsMD @@ -299,7 +321,7 @@ end # is desired, in which case we fall back to the div-based algorithm. stagedfunction merge_indexes(V, indexes::NTuple, dims::Dims, linindex::UnitRange{Int}) N = length(indexes) - N > 0 || error("Cannot merge empty indexes") + N > 0 || throw(ArgumentError("cannot merge empty indexes")) quote n = length(linindex) Base.Cartesian.@nexprs $N d->(I_d = indexes[d]) @@ -332,7 +354,7 @@ merge_indexes(V, indexes::NTuple, dims::Dims, linindex) = merge_indexes_div(V, i # an extra loop. stagedfunction merge_indexes_div(V, indexes::NTuple, dims::Dims, linindex) N = length(indexes) - N > 0 || error("Cannot merge empty indexes") + N > 0 || throw(ArgumentError("cannot merge empty indexes")) Istride_N = symbol("Istride_$N") quote Base.Cartesian.@nexprs $N d->(I_d = indexes[d]) @@ -373,7 +395,7 @@ for (f, op) in ((:cumsum!, :+), if size(B, axis) < 1 return B end - size(B) == size(A) || throw(DimensionMismatch("Size of B must match A")) + size(B) == size(A) || throw(DimensionMismatch("size of B must match A")) if axis == 1 # We can accumulate to a temporary variable, which allows register usage and will be slightly faster @inbounds @nloops N i d->(d > 1 ? (1:size(A,d)) : (1:1)) begin @@ -708,8 +730,8 @@ end for (V, PT, BT) in [((:N,), BitArray, BitArray), ((:T,:N), Array, StridedArray)] @eval @ngenerate N typeof(P) function permutedims!{$(V...)}(P::$PT{$(V...)}, B::$BT{$(V...)}, perm) dimsB = size(B) - length(perm) == N || error("expected permutation of size $N, but length(perm)=$(length(perm))") - isperm(perm) || error("input is not a permutation") + length(perm) == N || throw(ArgumentError("expected permutation of size $N, but length(perm)=$(length(perm))")) + isperm(perm) || throw(ArgumentError("input is not a permutation")) dimsP = size(P) for i = 1:length(perm) dimsP[i] == dimsB[perm[i]] || throw(DimensionMismatch("destination tensor of incorrect size")) diff --git a/base/operators.jl b/base/operators.jl index 19855fe48fa48..779982e7a6e47 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -181,14 +181,14 @@ copy(x::Union(Symbol,Number,AbstractString,Function,Tuple,LambdaStaticData, function promote_shape(a::(Int,), b::(Int,)) if a[1] != b[1] - error("dimensions must match") + throw(DimensionMismatch("dimensions must match")) end return a end function promote_shape(a::(Int,Int), b::(Int,)) if a[1] != b[1] || a[2] != 1 - error("dimensions must match") + throw(DimensionMismatch("dimensions must match")) end return a end @@ -197,7 +197,7 @@ promote_shape(a::(Int,), b::(Int,Int)) = promote_shape(b, a) function promote_shape(a::(Int, Int), b::(Int, Int)) if a[1] != b[1] || a[2] != b[2] - error("dimensions must match") + throw(DimensionMismatch("dimensions must match")) end return a end @@ -208,12 +208,12 @@ function promote_shape(a::Dims, b::Dims) end for i=1:length(b) if a[i] != b[i] - error("dimensions must match") + throw(DimensionMismatch("dimensions must match")) end end for i=length(b)+1:length(a) if a[i] != 1 - error("dimensions must match") + throw(DimensionMismatch("dimensions must match")) end end return a @@ -226,11 +226,10 @@ index_shape(i, I...) = tuple(length(i), index_shape(I...)...) function throw_setindex_mismatch(X, I) if length(I) == 1 - e = DimensionMismatch("tried to assign $(length(X)) elements to $(length(I[1])) destinations") + throw(DimensionMismatch("tried to assign $(length(X)) elements to $(length(I[1])) destinations")) else - e = DimensionMismatch("tried to assign $(dims2string(size(X))) array to $(dims2string(map(length,I))) destination") + throw(DimensionMismatch("tried to assign $(dims2string(size(X))) array to $(dims2string(map(length,I))) destination")) end - throw(e) end # check for valid sizes in A[I...] = X where X <: AbstractArray diff --git a/base/osutils.jl b/base/osutils.jl index 4f0fc795376d1..c58115719a0a8 100644 --- a/base/osutils.jl +++ b/base/osutils.jl @@ -3,7 +3,7 @@ function is_unix(os::Symbol) elseif (os==:Linux) return true; elseif (os==:FreeBSD) return true; elseif (os==:Darwin) return true; - else error("unknown operating system") + else throw(ArgumentError("unknown operating system, $(repr(os))")) end end diff --git a/base/path.jl b/base/path.jl index 932f602734a60..19f6fb772a349 100644 --- a/base/path.jl +++ b/base/path.jl @@ -61,7 +61,7 @@ function joinpath(a::AbstractString, b::AbstractString) isabspath(b) && return b A, a = splitdrive(a) B, b = splitdrive(b) - !isempty(B) && A != B && error("drive mismatch: $A$a $B$b") + !isempty(B) && A != B && throw(ArgumentError("drive mismatch: $A$a $B$b")) C = isempty(B) ? A : B isempty(a) ? string(C,b) : ismatch(path_separator_re, a[end:end]) ? string(C,a,b) : @@ -139,5 +139,5 @@ end if done(path,i) return homedir() end c, j = next(path,i) if c == '/' return homedir()*path[i:end] end - error("~user tilde expansion not yet implemented") + throw(ArgumentError("~user tilde expansion not yet implemented")) end diff --git a/base/pcre.jl b/base/pcre.jl index ddb7283ce8ff3..55935b98e895e 100644 --- a/base/pcre.jl +++ b/base/pcre.jl @@ -77,7 +77,7 @@ function config{T}(what::Integer, ::Type{T}) what, buf) if ret != 0 - error("error $n") + error("PCRE.config error code $n") end reinterpret(T,buf)[1] end diff --git a/base/pointer.jl b/base/pointer.jl index 722f2c9840e93..f2227b1cf15b7 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -7,8 +7,8 @@ convert{T<:Union(Int,UInt)}(::Type{T}, x::Ptr) = box(T, unbox(Ptr,x)) convert{T<:Integer}(::Type{T}, x::Ptr) = convert(T,unsigned(x)) # integer to pointer -convert{T}(::Type{Ptr{T}}, x::Integer) = box(Ptr{T},unbox(UInt,uint(x))) -convert{T}(::Type{Ptr{T}}, x::Signed) = box(Ptr{T},unbox(Int,int(x))) +convert{T}(::Type{Ptr{T}}, x::Integer) = box(Ptr{T},unbox(UInt,UInt(x))) +convert{T}(::Type{Ptr{T}}, x::Signed) = box(Ptr{T},unbox(Int,Int(x))) # pointer to pointer convert{T}(::Type{Ptr{T}}, p::Ptr{T}) = p @@ -36,17 +36,19 @@ function pointer_to_array{T,N}(p::Ptr{T}, dims::NTuple{N,Int}, own::Bool=false) Array{T,N}, p, dims, own) end function pointer_to_array{T,N}(p::Ptr{T}, dims::NTuple{N,Integer}, own::Bool=false) + i = 1 for d in dims if !(0 <= d <= typemax(Int)) - error("invalid Array dimensions") + throw(ArgumentError("Array dimension must be 0 ≤ dim ≤ $(typemax(Int)), got $d for dimension $i")) end + i += 1 end pointer_to_array(p, convert((Int...), dims), own) end -unsafe_load(p::Ptr,i::Integer) = pointerref(p, int(i)) +unsafe_load(p::Ptr,i::Integer) = pointerref(p, Int(i)) unsafe_load(p::Ptr) = unsafe_load(p, 1) -unsafe_store!(p::Ptr{Any}, x::ANY, i::Integer) = pointerset(p, x, int(i)) -unsafe_store!{T}(p::Ptr{T}, x, i::Integer) = pointerset(p, convert(T,x), int(i)) +unsafe_store!(p::Ptr{Any}, x::ANY, i::Integer) = pointerset(p, x, Int(i)) +unsafe_store!{T}(p::Ptr{T}, x, i::Integer) = pointerset(p, convert(T,x), Int(i)) unsafe_store!{T}(p::Ptr{T}, x) = pointerset(p, convert(T,x), 1) # convert a raw Ptr to an object reference, and vice-versa diff --git a/base/poll.jl b/base/poll.jl index d758bb7b9ff3d..b47f96d7130b6 100644 --- a/base/poll.jl +++ b/base/poll.jl @@ -107,7 +107,7 @@ function FDWatcher(fd::RawFD) handle = c_malloc(_sizeof_uv_poll) @unix_only if ccall(:jl_uv_unix_fd_is_watched,Int32,(Int32,Ptr{Void},Ptr{Void}),fd.fd,handle,eventloop()) == 1 c_free(handle) - error("file descriptor $(fd.fd) is already being watched by another watcher") + throw(ArgumentError("file descriptor $(fd.fd) is already being watched by another watcher")) end err = ccall(:uv_poll_init,Int32,(Ptr{Void},Ptr{Void},Int32),eventloop(),handle,fd.fd) if err < 0 @@ -143,7 +143,7 @@ end function _wait(fdw::FDWatcher,readable,writable) if !readable && !writable - error("must watch for at least one event") + throw(ArgumentError("must watch for at least one read or write FD event")) end events = FDEvent(readable | fdw.events.readable, writable | fdw.events.writable, @@ -240,7 +240,7 @@ close(t::UVPollingWatcher) = ccall(:jl_close_uv,Void,(Ptr{Void},),t.handle) function start_watching(t::FDWatcher, events::FDEvent) associate_julia_struct(t.handle, t) @unix_only if ccall(:jl_uv_unix_fd_is_watched,Int32,(Int32,Ptr{Void},Ptr{Void}),t.fd,t.handle,eventloop()) == 1 - error("cannot watch an FD more than once on Unix") + throw(ArgumentError("cannot watch an FD more than once on Unix")) end uv_error("start_watching (FD)", ccall(:jl_poll_start, Int32, (Ptr{Void},Int32), t.handle, diff --git a/base/primes.jl b/base/primes.jl index f043f4315dca9..f7c6d32c54205 100644 --- a/base/primes.jl +++ b/base/primes.jl @@ -26,7 +26,7 @@ function primesmask(s::AbstractVector{Bool}) end primesmask(n::Int) = primesmask(falses(n)) primesmask(n::Integer) = n <= typemax(Int) ? primesmask(int(n)) : - error("you want WAY too many primes ($n)") + throw(ArgumentError("requested number of primes must be ≤ $(typemax(Int)), got $n")) primes(n::Union(Integer,AbstractVector{Bool})) = find(primesmask(n)) @@ -76,7 +76,7 @@ isprime(n::Int128) = n < 2 ? false : const PRIMES = primes(10000) function factor{T<:Integer}(n::T) - 0 < n || error("number to be factored must be positive") + 0 < n || throw(ArgumentError("number to be factored must be ≥ 0, got $n")) h = Dict{T,Int}() n == 1 && return h n <= 3 && (h[n] = 1; return h) diff --git a/base/printf.jl b/base/printf.jl index f25c6a5939b46..33f9b84e23f50 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -81,7 +81,7 @@ end # [diouxXeEfFgGaAcCsSp%] # conversion next_or_die(s::AbstractString, k) = !done(s,k) ? next(s,k) : - error("invalid printf format string: ", repr(s)) + throw(ArgumentError("invalid printf format string: $(repr(s))")) function parse1(s::AbstractString, k::Integer) j = k @@ -125,7 +125,7 @@ function parse1(s::AbstractString, k::Integer) end # validate conversion if !(c in "diouxXDOUeEfFgGaAcCsSpn") - error("invalid printf format string: ", repr(s)) + throw(ArgumentError("invalid printf format string: $(repr(s))")) end # TODO: warn about silly flag/conversion combinations flags, width, precision, c, k @@ -995,7 +995,7 @@ is_str_expr(ex) = endswith(string(ex.args[1]),"str"))) function _printf(macroname, io, fmt, args) - isa(fmt, AbstractString) || error("$macroname: format must be a plain static string (no interpolation or prefix)") + isa(fmt, AbstractString) || throw(ArgumentError("$macroname: format must be a plain static string (no interpolation or prefix)")) sym_args, blk = gen(fmt) has_splatting = false @@ -1032,7 +1032,7 @@ function _printf(macroname, io, fmt, args) quote G = $(esc(x)) if length(G) != $(length(sym_args)) - error($macroname,": wrong number of arguments (",length(G),") should be (",$(length(sym_args)),")") + throw(ArgumentError($macroname,": wrong number of arguments (",length(G),") should be (",$(length(sym_args)),")")) end end ) @@ -1043,20 +1043,20 @@ function _printf(macroname, io, fmt, args) end macro printf(args...) - !isempty(args) || error("@printf: called with zero arguments") + !isempty(args) || throw(ArgumentError("@printf: called with no arguments")) if isa(args[1], AbstractString) || is_str_expr(args[1]) _printf("@printf", :STDOUT, args[1], args[2:end]) else (length(args) >= 2 && (isa(args[2], AbstractString) || is_str_expr(args[2]))) || - error("@printf: first or second argument must be a format string") + throw(ArgumentError("@printf: first or second argument must be a format string")) _printf("@printf", esc(args[1]), args[2], args[3:end]) end end macro sprintf(args...) - !isempty(args) || error("@sprintf: called with zero arguments") + !isempty(args) || throw(ArgumentError("@sprintf: called with zero arguments")) isa(args[1], AbstractString) || is_str_expr(args[1]) || - error("@sprintf: first argument must be a format string") + throw(ArgumentError("@sprintf: first argument must be a format string")) blk = _printf("@sprintf", :(IOBuffer()), args[1], args[2:end]) push!(blk.args, :(takebuf_string(out))) blk diff --git a/base/process.jl b/base/process.jl index 53af3dc913217..6b9ed3d451858 100644 --- a/base/process.jl +++ b/base/process.jl @@ -565,9 +565,7 @@ end # spawn function below so that we can exec more efficiently. # function _jl_pre_exec(args::Vector{ByteString}) - if length(args) < 1 - error("too few arguments to exec") - end + isempty(args) && throw(ArgumentError("exec called with no arguments")) ptrs = Array(Ptr{UInt8}, length(args)+1) for i = 1:length(args) ptrs[i] = args[i].data diff --git a/base/profile.jl b/base/profile.jl index 851456ab48aed..1c5e800f4ec77 100644 --- a/base/profile.jl +++ b/base/profile.jl @@ -51,7 +51,7 @@ function print{T<:Unsigned}(io::IO, data::Vector{T} = fetch(), lidict::Dict = ge elseif format == :flat flat(io, data, lidict, C, combine, cols) else - error("output format ", format, " not recognized") + throw(ArgumentError("output format $(repr(format)) not recognized")) end end print{T<:Unsigned}(data::Vector{T} = fetch(), lidict::Dict = getdict(data); kwargs...) = print(STDOUT, data, lidict; kwargs...) @@ -70,7 +70,7 @@ function callers(funcname::ByteString, bt::Vector{UInt}, lidict; filename = noth if filename == nothing && linerange == nothing return callersf(li -> li.func == funcname, bt, lidict) end - filename == nothing && error("If supplying linerange, you must also supply the filename") + filename == nothing && throw(ArgumentError("if supplying linerange, you must also supply the filename")) if linerange == nothing return callersf(li -> li.func == funcname && li.file == filename, bt, lidict) else diff --git a/base/promotion.jl b/base/promotion.jl index e48df7b58a089..0603b578db4e8 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -161,6 +161,7 @@ promote_to_super{T<:Number,S<:Number}(::Type{T}, ::Type{S}, ::Type) = ^(x::Number, y::Number) = ^(promote(x,y)...) fma(x::Number, y::Number, z::Number) = fma(promote(x,y,z)...) +muladd(x::Number, y::Number, z::Number) = muladd(promote(x,y,z)...) (&)(x::Integer, y::Integer) = (&)(promote(x,y)...) (|)(x::Integer, y::Integer) = (|)(promote(x,y)...) @@ -195,6 +196,7 @@ no_op_err(name, T) = error(name," not defined for ",T) fma{T<:Number}(x::T, y::T, z::T) = no_op_err("fma", T) fma(x::Integer, y::Integer, z::Integer) = x*y+z +muladd{T<:Number}(x::T, y::T, z::T) = x*y+z (&){T<:Integer}(x::T, y::T) = no_op_err("&", T) (|){T<:Integer}(x::T, y::T) = no_op_err("|", T) diff --git a/base/random.jl b/base/random.jl index c128e17bf50e1..c3a0cafe85c68 100644 --- a/base/random.jl +++ b/base/random.jl @@ -420,17 +420,25 @@ end RangeGeneratorInt{T, U<:Union(UInt32, UInt128)}(a::T, k::U) = RangeGeneratorInt{T, U}(a, k, maxmultiple(k)) # mixed 32/64 bits entropy generator RangeGeneratorInt{T}(a::T, k::UInt64) = RangeGeneratorInt{T,UInt64}(a, k, maxmultiplemix(k)) - - # generator for ranges -RangeGenerator{T<:Unsigned}(r::UnitRange{T}) = isempty(r) ? error("range must be non-empty") : RangeGeneratorInt(first(r), last(r) - first(r) + one(T)) +RangeGenerator{T<:Unsigned}(r::UnitRange{T}) = begin + if isempty(r) + throw(ArgumentError("range must be non-empty")) + end + RangeGeneratorInt(first(r), last(r) - first(r) + one(T)) +end # specialized versions for (T, U) in [(UInt8, UInt32), (UInt16, UInt32), (Int8, UInt32), (Int16, UInt32), (Int32, UInt32), (Int64, UInt64), (Int128, UInt128), (Bool, UInt32)] - @eval RangeGenerator(r::UnitRange{$T}) = isempty(r) ? error("range must be non-empty") : RangeGeneratorInt(first(r), convert($U, unsigned(last(r) - first(r)) + one($U))) # overflow ok + @eval RangeGenerator(r::UnitRange{$T}) = begin + if isempty(r) + throw(ArgumentError("range must be non-empty")) + end + RangeGeneratorInt(first(r), convert($U, unsigned(last(r) - first(r)) + one($U))) # overflow ok + end end if GMP_VERSION.major >= 6 @@ -456,7 +464,7 @@ end function RangeGenerator(r::UnitRange{BigInt}) m = last(r) - first(r) - m < 0 && error("range must be non-empty") + m < 0 && throw(ArgumentError("range must be non-empty")) nd = ndigits(m, 2) nlimbs, highbits = divrem(nd, 8*sizeof(Limb)) highbits > 0 && (nlimbs += 1) diff --git a/base/range.jl b/base/range.jl index 13b5710166bde..b613952d13cb6 100644 --- a/base/range.jl +++ b/base/range.jl @@ -15,11 +15,11 @@ immutable StepRange{T,S} <: OrdinalRange{T,S} function StepRange(start::T, step::S, stop::T) if T<:FloatingPoint || S<:FloatingPoint - error("StepRange should not be used with floating point") + throw(ArgumentError("StepRange should not be used with floating point")) end z = zero(S) - step == z && error("step cannot be zero") - step != step && error("step cannot be NaN") + step == z && throw(ArgumentError("step cannot be zero")) + step != step && throw(ArgumentError("step cannot be NaN")) if stop == start last = stop @@ -118,8 +118,8 @@ function rat(x) end function colon{T<:FloatingPoint}(start::T, step::T, stop::T) - step == 0 && error("range step cannot be zero") - start == stop && return FloatRange{T}(start,step,1,1) + step == 0 && throw(ArgumentError("range step cannot be zero")) + start == stop && return FloatRange{T}(start,step,1,1) (0 < step) != (start < stop) && return FloatRange{T}(start,step,0,1) # float range "lifting" @@ -161,7 +161,7 @@ range(a::FloatingPoint, st::Real, len::Integer) = FloatRange(a, float(st), len, linrange(a::Real, b::Real, len::Integer) = len >= 2 ? range(a, (b-a)/(len-1), len) : len == 1 && a == b ? range(a, zero((b-a)/(len-1)), 1) : - error("invalid range length") + throw(ArgumentError("invalid range length")) ## interface implementations @@ -221,10 +221,10 @@ last{T}(r::StepRange{T}) = r.stop last(r::UnitRange) = r.stop last{T}(r::FloatRange{T}) = convert(T, (r.start + (r.len-1)*r.step)/r.divisor) -minimum(r::UnitRange) = isempty(r) ? error("range must be non-empty") : first(r) -maximum(r::UnitRange) = isempty(r) ? error("range must be non-empty") : last(r) -minimum(r::Range) = isempty(r) ? error("range must be non-empty") : min(first(r), last(r)) -maximum(r::Range) = isempty(r) ? error("range must be non-empty") : max(first(r), last(r)) +minimum(r::UnitRange) = isempty(r) ? throw(ArgumentError("range must be non-empty")) : first(r) +maximum(r::UnitRange) = isempty(r) ? throw(ArgumentError("range must be non-empty")) : last(r) +minimum(r::Range) = isempty(r) ? throw(ArgumentError("range must be non-empty")) : min(first(r), last(r)) +maximum(r::Range) = isempty(r) ? throw(ArgumentError("range must be non-empty")) : max(first(r), last(r)) ctranspose(r::Range) = [x for _=1, x=r] transpose(r::Range) = r' @@ -545,7 +545,7 @@ function sum{T<:Real}(r::Range{T}) end function mean{T<:Real}(r::Range{T}) - isempty(r) && error("mean of an empty range is undefined") + isempty(r) && throw(ArgumentError("mean of an empty range is undefined")) (first(r) + last(r)) / 2 end diff --git a/base/rational.jl b/base/rational.jl index 3963315af5404..10ed93373b9ef 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -3,7 +3,7 @@ immutable Rational{T<:Integer} <: Real den::T function Rational(num::T, den::T) - num == den == 0 && error("invalid rational: 0//0") + num == den == zero(T) && throw(ArgumentError("invalid rational: zero($T)//zero($T)")) g = den < 0 ? -gcd(den, num) : gcd(den, num) new(div(num, g), div(den, g)) end diff --git a/base/reduce.jl b/base/reduce.jl index 457e5097a4229..7c62b2cd718ff 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -114,7 +114,7 @@ mapreduce_impl(f, op, A::AbstractArray, ifirst::Int, ilast::Int) = mapreduce_seq_impl(f, op, A, ifirst, ilast) # handling empty arrays -mr_empty(f, op, T) = error("Reducing over an empty array is not allowed.") +mr_empty(f, op, T) = throw(ArgumentError("reducing over an empty collection is not allowed")) # use zero(T)::T to improve type information when zero(T) is not defined mr_empty(::IdFun, op::AddFun, T) = r_promote(op, zero(T)::T) mr_empty(::AbsFun, op::AddFun, T) = r_promote(op, abs(zero(T)::T)) @@ -271,7 +271,7 @@ extrema(x::Real) = (x, x) function extrema(itr) s = start(itr) - done(itr, s) && error("argument is empty") + done(itr, s) && throw(ArgumentError("collection must be non-empty")) (v, s) = next(itr, s) while v != v && !done(itr, s) (x, s) = next(itr, s) diff --git a/base/reducedim.jl b/base/reducedim.jl index 92507d3004e60..351e574458d61 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -219,7 +219,7 @@ for (fname, Op) in [(:sum, :AddFun), (:prod, :MulFun), (:maximum, :MaxFun), (:minimum, :MinFun), (:all, :AndFun), (:any, :OrFun)] - fname! = symbol(string(fname, '!')) + fname! = symbol(fname, '!') @eval begin $(fname!)(f::Union(Function,Func{1}), r::AbstractArray, A::AbstractArray; init::Bool=true) = mapreducedim!(f, $(Op)(), initarray!(r, $(Op)(), init), A) @@ -235,8 +235,8 @@ for (fname, fbase, Fun) in [(:sumabs, :sum, :AbsFun), (:sumabs2, :sum, :Abs2Fun), (:maxabs, :maximum, :AbsFun), (:minabs, :minimum, :AbsFun)] - fname! = symbol(string(fname, '!')) - fbase! = symbol(string(fbase, '!')) + fname! = symbol(fname, '!') + fbase! = symbol(fbase, '!') @eval begin $(fname!)(r::AbstractArray, A::AbstractArray; init::Bool=true) = $(fbase!)($(Fun)(), r, A; init=init) diff --git a/base/reflection.jl b/base/reflection.jl index 8d66e905eedc8..83ee8442576bc 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -34,7 +34,7 @@ function names(v) if isa(t,DataType) return names(t) else - error("cannot call names() on a non-composite type") + throw(ArgumentError("cannot call names() on a non-composite type")) end end @@ -122,7 +122,7 @@ end function methods(f::Function) if !isgeneric(f) - error("not a generic function") + throw(ArgumentError("argument is not a generic function")) end f.env end @@ -171,7 +171,7 @@ function which(f::ANY, t::(Type...)) t = tuple(isa(f,Type) ? Type{f} : typeof(f), t...) f = call elseif !isgeneric(f) - error("argument is not a generic function") + throw(ArgumentError("argument is not a generic function")) end m = ccall(:jl_gf_invoke_lookup, Any, (Any, Any), f, t) if m === nothing diff --git a/base/regex.jl b/base/regex.jl index 485ac4d54ecfa..b014fa9001e64 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -16,7 +16,7 @@ type Regex pattern = bytestring(pattern) options = int32(options) if (options & ~PCRE.OPTIONS_MASK) != 0 - error("invalid regex options: $options") + throw(ArgumentError("invalid regex options: $options")) end re = compile(new(pattern, options, C_NULL, C_NULL, Array(Int32, 0))) finalizer(re, @@ -35,7 +35,7 @@ function Regex(pattern::AbstractString, flags::AbstractString) f=='m' ? PCRE.MULTILINE : f=='s' ? PCRE.DOTALL : f=='x' ? PCRE.EXTENDED : - error("unknown regex flag: $f") + throw(ArgumentError("unknown regex flag: $f")) end Regex(pattern, options) end diff --git a/base/rounding.jl b/base/rounding.jl index df054de8e1c0a..73dfa3d228d02 100644 --- a/base/rounding.jl +++ b/base/rounding.jl @@ -34,7 +34,7 @@ function from_fenv(r::Integer) elseif r == JL_FE_TOWARDZERO return RoundToZero else - error("invalid rounding mode code") + throw(ArgumentError("invalid rounding mode code: $r")) end end diff --git a/base/sharedarray.jl b/base/sharedarray.jl index b1c2dee3b05f9..aa0f4db28ba95 100644 --- a/base/sharedarray.jl +++ b/base/sharedarray.jl @@ -25,7 +25,7 @@ end function SharedArray(T::Type, dims::NTuple; init=false, pids=Int[]) N = length(dims) - isbits(T) || error("Type of Shared Array elements must be bits types") + isbits(T) || throw(ArgumentError("type of SharedArray elements must be bits types, got $(T)")) if isempty(pids) # only use workers on the current host @@ -37,7 +37,7 @@ function SharedArray(T::Type, dims::NTuple; init=false, pids=Int[]) onlocalhost = true else if !check_same_host(pids) - error("SharedArray requires all requested processes to be on the same machine.") + throw(ArgumentError("SharedArray requires all requested processes to be on the same machine.")) end onlocalhost = myid() in procs(pids[1]) @@ -119,7 +119,7 @@ length(S::SharedArray) = prod(S.dims) size(S::SharedArray) = S.dims function reshape{T,N}(a::SharedArray{T}, dims::NTuple{N,Int}) - (length(a) != prod(dims)) && error("dimensions must be consistent with array size") + (length(a) != prod(dims)) && throw(DimensionMismatch("dimensions must be consistent with array size")) refs = Array(RemoteRef, length(a.pids)) for (i, p) in enumerate(a.pids) refs[i] = remotecall(p, (r,d)->reshape(fetch(r),d), a.refs[i], dims) @@ -294,7 +294,7 @@ copy!(S::SharedArray, A::Array) = (copy!(S.s, A); S) function copy!(S::SharedArray, R::SharedArray) length(S) == length(R) || throw(BoundsError()) ps = intersect(procs(S), procs(R)) - isempty(ps) && error("source and destination arrays don't share any process") + isempty(ps) && throw(ArgumentError("source and destination arrays don't share any process")) l = length(S) length(ps) > l && (ps = ps[1:l]) nw = length(ps) diff --git a/base/show.jl b/base/show.jl index 63cca0df4c954..2a5123d99980c 100644 --- a/base/show.jl +++ b/base/show.jl @@ -851,7 +851,7 @@ xdump(fn::Function, io::IO, x::DataType, n::Int) = x.abstract ? dumptype(io, x, # defaults: xdump(fn::Function, io::IO, x) = xdump(xdump, io, x, 5, "") # default is 5 levels xdump(fn::Function, io::IO, x, n::Int) = xdump(xdump, io, x, n, "") -xdump(fn::Function, io::IO, args...) = error("invalid arguments to xdump") +xdump(fn::Function, io::IO, args...) = throw(ArgumentError("invalid arguments to xdump")) xdump(fn::Function, args...) = xdump(fn, STDOUT::IO, args...) xdump(io::IO, args...) = xdump(xdump, io, args...) xdump(args...) = with_output_limit(()->xdump(xdump, STDOUT::IO, args...), true) @@ -863,7 +863,7 @@ dump(io::IO, x::AbstractString, n::Int, indent) = (print(io, typeof(x), " "); show(io, x); println(io)) dump(io::IO, x, n::Int, indent) = xdump(dump, io, x, n, indent) -dump(io::IO, args...) = error("invalid arguments to dump") +dump(io::IO, args...) = throw(ArgumentError("invalid arguments to dump")) dump(args...) = with_output_limit(()->dump(STDOUT::IO, args...), true) function dump(io::IO, x::Dict, n::Int, indent) diff --git a/base/simdloop.jl b/base/simdloop.jl index e73c85e8fa921..16a1b572b4957 100644 --- a/base/simdloop.jl +++ b/base/simdloop.jl @@ -2,7 +2,7 @@ module SimdLoop -export @simd +export @simd, simd_outer_range, simd_inner_length, simd_index # Error thrown from ill-formed uses of @simd type SimdError <: Exception @@ -34,6 +34,19 @@ end check_body!(x::QuoteNode) = check_body!(x.value) check_body!(x) = true +# @simd splits a for loop into two loops: an outer scalar loop and +# an inner loop marked with :simdloop. The simd_... functions define +# the splitting. + +# Get range for outer loop. +simd_outer_range(r) = 0:0 + +# Get trip count for inner loop. +simd_inner_length(r,j::Int) = length(r) + +# Construct user-level index from original range, outer loop index j, and inner loop index i. +simd_index(r,j::Int,i) = first(r)+i*step(r) + # Compile Expr x in context of @simd. function compile(x) (isa(x, Expr) && x.head == :for) || throw(SimdError("for loop expected")) @@ -42,23 +55,28 @@ function compile(x) var,range = parse_iteration_space(x.args[1]) r = gensym("r") # Range value - n = gensym("n") # Trip count - i = gensym("i") # Trip index + j = gensym("i") # Iteration variable for outer loop + n = gensym("n") # Trip count for inner loop + i = gensym("i") # Trip index for inner loop quote # Evaluate range value once, to enhance type and data flow analysis by optimizers. - let $r = $range, $n = length($r) - if zero($n) < $n - # Lower loop in way that seems to work best for LLVM 3.3 vectorizer. - let $i = zero($n) - while $i < $n - local $var = first($r) + $i*step($r) - $(x.args[2]) # Body of loop - $i += 1 - $(Expr(:simdloop)) # Mark loop as SIMD loop + let $r = $range + for $j in Base.simd_outer_range($r) + let $n = Base.simd_inner_length($r,$j) + if zero($n) < $n + # Lower loop in way that seems to work best for LLVM 3.3 vectorizer. + let $i = zero($n) + while $i < $n + local $var = Base.simd_index($r,$j,$i) + $(x.args[2]) # Body of loop + $i += 1 + $(Expr(:simdloop)) # Mark loop as SIMD loop + end + end + # Set index to last value just like a regular for loop would + $var = last($r) end end - # Set index to last value just like a regular for loop would - $var = last($r) end end nothing diff --git a/base/socket.jl b/base/socket.jl index 8e25778dc7959..70029bfae28e8 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -21,9 +21,9 @@ end function IPv4(host::Integer) if host < 0 - error("IP address must not be negative") + throw(ArgumentError("IPv4 address must be positive")) elseif typemax(typeof(host)) > typemax(UInt32) && host > typemax(UInt32) - error("IPv4 address must fit within 32 bits") + throw(ArgumentError("IPv4 address must fit within 32 bits")) else return IPv4(uint32(host)) end @@ -63,11 +63,11 @@ end function IPv6(host::Integer) if host < 0 - error("IP address must not be negative") + throw(ArgumentError("IPv6 address must be positive")) # We allow passing bigger integer types, but need to be careful to avoid overflow # Let's hope promotion rules are sensible elseif typemax(typeof(host)) > typemax(UInt128) && host > typemax(UInt128) - error("IPv6 address must fit within 128 bits") + throw(ArgumentError("IPv6 address must fit within 128 bits")) else return IPv6(uint128(host)) end @@ -142,17 +142,17 @@ function parseipv4(str) ret = 0 for f in fields if length(f) == 0 - error("empty field in IPv4 address") + throw(ArgumentError("empty field in IPv4 address")) end if f[1] == '0' if length(f) >= 2 && f[2] == 'x' if length(f) > 8 # 2+(3*2) - prevent parseint from overflowing on 32bit - error("IPv4 field too large") + throw(ArgumentError("IPv4 field too large")) end r = parseint(f[3:end],16) else if length(f) > 9 # 1+8 - prevent parseint from overflowing on 32bit - error("IPv4 field too large") + throw(ArgumentError("IPv4 field too large")) end r = parseint(f,8) end @@ -161,12 +161,12 @@ function parseipv4(str) end if i != length(fields) if r < 0 || r > 255 - error("IPv4 field out of range (must be 0-255)") + throw(ArgumentError("IPv4 field out of range (must be 0-255)")) end ret |= uint32(r) << ((4-i)*8) else if r > ((uint64(1)<<((5-length(fields))*8))-1) - error("IPv4 field too large") + throw(ArgumentError("IPv4 field too large")) end ret |= r end @@ -177,7 +177,7 @@ end function parseipv6fields(fields,num_fields) if length(fields) > num_fields - error("too many fields in IPv6 address") + throw(ArgumentError("too many fields in IPv6 address")) end cf = 7 ret = uint128(0) @@ -200,7 +200,7 @@ parseipv6fields(fields) = parseipv6fields(fields,8) function parseipv6(str) fields = split(str,':') if length(fields) > 8 - error("too many fields in IPv6 address") + throw(ArgumentError("too many fields in IPv6 address")) elseif length(fields) == 8 return IPv6(parseipv6fields(fields)) elseif in('.',fields[end]) diff --git a/base/sort.jl b/base/sort.jl index 4015816555aa4..e8f8b7480e2bc 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -54,7 +54,7 @@ issorted(itr; issorted(itr, ord(lt,by,rev,order)) function select!(v::AbstractVector, k::Int, lo::Int, hi::Int, o::Ordering) - lo <= k <= hi || error("select index $k is out of range $lo:$hi") + lo <= k <= hi || throw(ArgumentError("select index $k is out of range $lo:$hi")) @inbounds while lo < hi if hi-lo == 1 if lt(o, v[hi], v[lo]) @@ -85,7 +85,7 @@ end function select!(v::AbstractVector, r::OrdinalRange, lo::Int, hi::Int, o::Ordering) isempty(r) && (return v[r]) a, b = extrema(r) - lo <= a <= b <= hi || error("selection $r is out of range $lo:$hi") + lo <= a <= b <= hi || throw(ArgumentError("selection $r is out of range $lo:$hi")) @inbounds while true if lo == a && hi == b sort!(v, lo, hi, DEFAULT_UNSTABLE, o) diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index bee53c8f02085..836c463f667a6 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -895,7 +895,6 @@ function getindex_cols{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, J::AbstractVector) # for indexing whole columns (m, n) = size(A) nJ = length(J) - nJ == 0 || maximum(J) <= n || throw(BoundsError()) colptrA = A.colptr; rowvalA = A.rowval; nzvalA = A.nzval @@ -905,6 +904,7 @@ function getindex_cols{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, J::AbstractVector) @inbounds for j = 1:nJ col = J[j] + 1 <= col <= n || throw(BoundsError()) nnzS += colptrA[col+1] - colptrA[col] colptrS[j+1] = nnzS + 1 end @@ -933,6 +933,7 @@ function getindex{Tv,Ti<:Integer}(A::SparseMatrixCSC{Tv,Ti}, I::Range, J::Abstra end nI = length(I) + nI == 0 || (minimum(I) >= 1 && maximum(I) <= m) || throw(BoundsError()) nJ = length(J) colptrA = A.colptr; rowvalA = A.rowval; nzvalA = A.nzval colptrS = Array(Ti, nJ+1) @@ -940,12 +941,13 @@ function getindex{Tv,Ti<:Integer}(A::SparseMatrixCSC{Tv,Ti}, I::Range, J::Abstra nnzS = 0 # Form the structure of the result and compute space - for j = 1:nJ - @inbounds col = J[j] + @inbounds for j = 1:nJ + col = J[j] + 1 <= col <= n || throw(BoundsError()) @simd for k in colptrA[col]:colptrA[col+1]-1 - if rowvalA[k] in I; nnzS += 1 end # `in` is fast for ranges + nnzS += rowvalA[k] in I # `in` is fast for ranges end - @inbounds colptrS[j+1] = nnzS+1 + colptrS[j+1] = nnzS+1 end # Populate the values in the result diff --git a/base/special/bessel.jl b/base/special/bessel.jl index c32b8c9b34de1..dfda2c8fcee80 100644 --- a/base/special/bessel.jl +++ b/base/special/bessel.jl @@ -1,7 +1,7 @@ for jy in ("j","y"), nu in (0,1) - jynu = Expr(:quote, symbol(string(jy,nu))) - jynuf = Expr(:quote, symbol(string(jy,nu,"f"))) - bjynu = symbol(string("bessel",jy,nu)) + jynu = Expr(:quote, symbol(jy,nu)) + jynuf = Expr(:quote, symbol(jy,nu,"f")) + bjynu = symbol("bessel",jy,nu) if jy == "y" @eval begin $bjynu(x::Float64) = nan_dom_err(ccall(($jynu,libm), Float64, (Float64,), x), x) @@ -15,7 +15,7 @@ for jy in ("j","y"), nu in (0,1) end @eval begin $bjynu(x::Real) = $bjynu(float(x)) - $bjynu(x::Complex) = $(symbol(string("bessel",jy)))($nu,x) + $bjynu(x::Complex) = $(symbol("bessel",jy))($nu,x) @vectorize_1arg Number $bjynu end end @@ -365,7 +365,7 @@ function besselyx(nu::Real, x::FloatingPoint) end for f in ("i", "ix", "j", "jx", "k", "kx", "y", "yx") - bfn = symbol(string("bessel", f)) + bfn = symbol("bessel", f) @eval begin $bfn(nu::Real, z::Complex64) = complex64($bfn(float64(nu), complex128(z))) $bfn(nu::Real, z::Complex) = $bfn(float64(nu), complex128(z)) diff --git a/base/statistics.jl b/base/statistics.jl index 8eeec2fa63ea8..20f0183794b98 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -3,7 +3,7 @@ function mean(iterable) state = start(iterable) if done(iterable, state) - error("mean of empty collection undefined: $(repr(iterable))") + throw(ArgumentError("mean of empty collection undefined: $(repr(iterable))")) end count = 1 total, state = next(iterable, state) @@ -41,7 +41,7 @@ mean{T}(A::AbstractArray{T}, region) = function var(iterable; corrected::Bool=true, mean=nothing) state = start(iterable) if done(iterable, state) - error("variance of empty collection undefined: $(repr(iterable))") + throw(ArgumentError("variance of empty collection undefined: $(repr(iterable))")) end count = 1 value, state = next(iterable, state) @@ -72,7 +72,7 @@ function var(iterable; corrected::Bool=true, mean=nothing) end return sum2 / (count - int(corrected)) else - error("invalid value of mean") + throw(ArgumentError("invalid value of mean, $(mean)::$(typeof(mean))")) end end @@ -162,14 +162,14 @@ function var{T}(A::AbstractArray{T}; corrected::Bool=true, mean=nothing) convert(momenttype(T), mean == 0 ? varzm(A; corrected=corrected) : mean == nothing ? varm(A, Base.mean(A); corrected=corrected) : isa(mean, Number) ? varm(A, mean::Number; corrected=corrected) : - error("invalid value of mean"))::momenttype(T) + throw(ArgumentError("invalid value of mean, $(mean)::$(typeof(mean))")))::momenttype(T) end function var(A::AbstractArray, region; corrected::Bool=true, mean=nothing) mean == 0 ? varzm(A, region; corrected=corrected) : mean == nothing ? varm(A, Base.mean(A, region), region; corrected=corrected) : isa(mean, AbstractArray) ? varm(A, mean::AbstractArray, region; corrected=corrected) : - error("invalid value of mean") + throw(ArgumentError("invalid value of mean, $(mean)::$(typeof(mean))")) end varm(iterable, m::Number; corrected::Bool=true) = @@ -226,7 +226,7 @@ _getnobs(x::AbstractMatrix, vardim::Int) = size(x, vardim) function _getnobs(x::AbstractVecOrMat, y::AbstractVecOrMat, vardim::Int) n = _getnobs(x, vardim) - _getnobs(y, vardim) == n || throw(DimensionMismatch("Dimensions of x and y mismatch.")) + _getnobs(y, vardim) == n || throw(DimensionMismatch("dimensions of x and y mismatch")) return n end @@ -279,21 +279,21 @@ function cov(x::AbstractVector; corrected::Bool=true, mean=nothing) mean == 0 ? covzm(x; corrected=corrected) : mean == nothing ? covm(x, Base.mean(x); corrected=corrected) : isa(mean, Number) ? covm(x, mean; corrected=corrected) : - error("Invalid value of mean.") + throw(ArgumentError("invalid value of mean, $(mean)::$(typeof(mean))")) end function cov(x::AbstractMatrix; vardim::Int=1, corrected::Bool=true, mean=nothing) mean == 0 ? covzm(x; vardim=vardim, corrected=corrected) : mean == nothing ? covm(x, _vmean(x, vardim); vardim=vardim, corrected=corrected) : isa(mean, AbstractArray) ? covm(x, mean; vardim=vardim, corrected=corrected) : - error("Invalid value of mean.") + throw(ArgumentError("invalid value of mean, $(mean)::$(typeof(mean))")) end function cov(x::AbstractVector, y::AbstractVector; corrected::Bool=true, mean=nothing) mean == 0 ? covzm(x, y; corrected=corrected) : mean == nothing ? covm(x, Base.mean(x), y, Base.mean(y); corrected=corrected) : isa(mean, (Number,Number)) ? covm(x, mean[1], y, mean[2]; corrected=corrected) : - error("Invalid value of mean.") + throw(ArgumentError("invalid value of mean, $(mean)::$(typeof(mean))")) end function cov(x::AbstractVecOrMat, y::AbstractVecOrMat; vardim::Int=1, corrected::Bool=true, mean=nothing) @@ -304,7 +304,7 @@ function cov(x::AbstractVecOrMat, y::AbstractVecOrMat; vardim::Int=1, corrected: elseif isa(mean, (Any,Any)) covm(x, mean[1], y, mean[2]; vardim=vardim, corrected=corrected) else - error("Invalid value of mean.") + throw(ArgumentError("invalid value of mean, $(mean)::$(typeof(mean))")) end end @@ -315,7 +315,7 @@ end function cov2cor!{T}(C::AbstractMatrix{T}, xsd::AbstractArray) nx = length(xsd) - size(C) == (nx, nx) || throw(DimensionMismatch("Inconsistent dimensions.")) + size(C) == (nx, nx) || throw(DimensionMismatch("inconsistent dimensions")) for j = 1:nx for i = 1:j-1 C[i,j] = C[j,i] @@ -330,7 +330,7 @@ end function cov2cor!(C::AbstractMatrix, xsd::Number, ysd::AbstractArray) nx, ny = size(C) - length(ysd) == ny || throw(DimensionMismatch("Inconsistent dimensions.")) + length(ysd) == ny || throw(DimensionMismatch("inconsistent dimensions")) for j = 1:ny for i = 1:nx C[i,j] /= (xsd * ysd[j]) @@ -341,7 +341,7 @@ end function cov2cor!(C::AbstractMatrix, xsd::AbstractArray, ysd::Number) nx, ny = size(C) - length(xsd) == nx || throw(DimensionMismatch("Inconsistent dimensions.")) + length(xsd) == nx || throw(DimensionMismatch("inconsistent dimensions")) for j = 1:ny for i = 1:nx C[i,j] /= (xsd[i] * ysd) @@ -353,7 +353,7 @@ end function cov2cor!(C::AbstractMatrix, xsd::AbstractArray, ysd::AbstractArray) nx, ny = size(C) (length(xsd) == nx && length(ysd) == ny) || - throw(DimensionMismatch("Inconsistent dimensions.")) + throw(DimensionMismatch("inconsistent dimensions")) for j = 1:ny for i = 1:nx C[i,j] /= (xsd[i] * ysd[j]) @@ -371,7 +371,7 @@ corzm(x::AbstractMatrix; vardim::Int=1) = function corzm(x::AbstractVector, y::AbstractVector) n = length(x) - length(y) == n || throw(DimensionMismatch("Inconsistent lengths.")) + length(y) == n || throw(DimensionMismatch("inconsistent lengths")) x1 = x[1] y1 = y[1] xx = abs2(x1) @@ -415,21 +415,21 @@ function cor(x::AbstractVector; mean=nothing) mean == 0 ? corzm(x) : mean == nothing ? corm(x, Base.mean(x)) : isa(mean, Number) ? corm(x, mean) : - error("Invalid value of mean.") + throw(ArgumentError("invalid value of mean, $(mean)::$(typeof(mean))")) end function cor(x::AbstractMatrix; vardim::Int=1, mean=nothing) mean == 0 ? corzm(x; vardim=vardim) : mean == nothing ? corm(x, _vmean(x, vardim); vardim=vardim) : isa(mean, AbstractArray) ? corm(x, mean; vardim=vardim) : - error("Invalid value of mean.") + throw(ArgumentError("invalid value of mean, $(mean)::$(typeof(mean))")) end function cor(x::AbstractVector, y::AbstractVector; mean=nothing) mean == 0 ? corzm(x, y) : mean == nothing ? corm(x, Base.mean(x), y, Base.mean(y)) : isa(mean, (Number,Number)) ? corm(x, mean[1], y, mean[2]) : - error("Invalid value of mean.") + throw(ArgumentError("invalid value of mean, $(mean)::$(typeof(mean))")) end function cor(x::AbstractVecOrMat, y::AbstractVecOrMat; vardim::Int=1, mean=nothing) @@ -440,7 +440,7 @@ function cor(x::AbstractVecOrMat, y::AbstractVecOrMat; vardim::Int=1, mean=nothi elseif isa(mean, (Any,Any)) corm(x, mean[1], y, mean[2]; vardim=vardim) else - error("Invalid value of mean.") + throw(ArgumentError("invalid value of mean, $(mean)::$(typeof(mean))")) end end @@ -457,7 +457,7 @@ middle(a::Range) = middle(a[1], a[end]) middle(a::AbstractArray) = ((v1, v2) = extrema(a); middle(v1, v2)) function median!{T}(v::AbstractVector{T}) - isempty(v) && error("median of an empty array is undefined") + isempty(v) && throw(ArgumentError("median of an empty array is undefined, $(repr(v))")) if T<:FloatingPoint @inbounds for x in v isnan(x) && return x @@ -480,8 +480,8 @@ median{T}(v::AbstractArray{T}, region) = mapslices(median, v, region) # TODO: need faster implementation (use select!?) # function quantile!(v::AbstractVector, q::AbstractVector) - isempty(v) && error("empty data array") - isempty(q) && error("empty quantile array") + isempty(v) && throw(ArgumentError("empty data array")) + isempty(q) && throw(ArgumentError("empty quantile array")) # make sure the quantiles are in [0,1] q = bound_quantiles(q) @@ -493,7 +493,7 @@ function quantile!(v::AbstractVector, q::AbstractVector) lo = floor(Int,index) hi = ceil(Int,index) sort!(v) - isnan(v[end]) && error("quantiles are undefined in presence of NaNs") + isnan(v[end]) && throw(ArgumentError("quantiles are undefined in presence of NaNs")) i = find(index .> lo) r = float(v[lo]) h = (index.-lo)[i] @@ -506,7 +506,7 @@ quantile(v::AbstractVector, q::Number) = quantile(v,[q])[1] function bound_quantiles(qs::AbstractVector) epsilon = 100*eps() if (any(qs .< -epsilon) || any(qs .> 1+epsilon)) - error("quantiles out of [0,1] range") + throw(ArgumentError("quantiles out of [0,1] range")) end [min(1,max(0,q)) for q = qs] end @@ -579,7 +579,7 @@ end function hist!{HT}(h::AbstractArray{HT}, v::AbstractVector, edg::AbstractVector; init::Bool=true) n = length(edg) - 1 - length(h) == n || error("length(h) must equal length(edg) - 1.") + length(h) == n || throw(DimensionMismatch("length(histogram) must equal length(edges) - 1")) if init fill!(h, zero(HT)) end @@ -598,7 +598,9 @@ hist(v::AbstractVector) = hist(v,sturges(length(v))) function hist!{HT}(H::AbstractArray{HT,2}, A::AbstractMatrix, edg::AbstractVector; init::Bool=true) m, n = size(A) - size(H) == (length(edg)-1, n) || error("Incorrect size of H.") + sH = size(H) + sE = (length(edg)-1,n) + sH == sE || throw(DimensionMismatch("incorrect size of histogram")) if init fill!(H, zero(HT)) end @@ -616,10 +618,10 @@ hist(A::AbstractMatrix) = hist(A,sturges(size(A,1))) ## hist2d function hist2d!{HT}(H::AbstractArray{HT,2}, v::AbstractMatrix, edg1::AbstractVector, edg2::AbstractVector; init::Bool=true) - size(v,2) == 2 || error("hist2d requires an Nx2 matrix.") + size(v,2) == 2 || throw(DimensionMismatch("hist2d requires an Nx2 matrix")) n = length(edg1) - 1 m = length(edg2) - 1 - size(H) == (n, m) || error("Incorrect size of H.") + size(H) == (n, m) || throw(DimensionMismatch("incorrect size of histogram")) if init fill!(H, zero(HT)) end diff --git a/base/stream.jl b/base/stream.jl index cb8e02ebc9eac..57b403a89e135 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -247,7 +247,7 @@ function init_stdio(handle) elseif t == UV_NAMED_PIPE ret = Pipe(handle) else - error("FATAL: stdio type ($t) invalid") + throw(ArgumentError("invalid stdio type: $t")) end ret.status = StatusOpen ret.line_buffered = false @@ -282,16 +282,16 @@ end flush(::AsyncStream) = nothing -function isopen(x::Union(AsyncStream,UVServer)) +function isopen{T<:Union(AsyncStream,UVServer)}(x::T) if !(x.status != StatusUninit && x.status != StatusInit) - error("I/O object not initialized") + throw(ArgumentError("$T object not initialized")) end x.status != StatusClosed && x.status != StatusEOF end function check_open(x) if !isopen(x) || x.status == StatusClosing - error("stream is closed or unusable") + throw(ArgumentError("stream is closed or unusable")) end end @@ -655,7 +655,7 @@ function readall(stream::AsyncStream) end function read!{T}(s::AsyncStream, a::Array{T}) - isbits(T) || error("read from buffer only supports bits types or arrays of bits types") + isbits(T) || throw(ArgumentError("read from AsyncStream only supports bits types or arrays of bits types")) nb = length(a) * sizeof(T) read!(s, reshape(reinterpret(UInt8, a), nb)) return a @@ -687,7 +687,7 @@ function read!(s::AsyncStream, a::Vector{UInt8}) end function read{T}(s::AsyncStream, ::Type{T}, dims::Dims) - isbits(T) || error("read from buffer only supports bits types or arrays of bits types") + isbits(T) || throw(ArgumentError("read from AsyncStream only supports bits types or arrays of bits types")) nb = prod(dims)*sizeof(T) a = read!(s, Array(UInt8, nb)) reshape(reinterpret(T, a), dims) @@ -853,7 +853,7 @@ end function accept(server::UVServer, client::AsyncStream) if server.status != StatusActive - throw(ArgumentError("server not connected; make sure \"listen\" has been called")) + throw(ArgumentError("server not connected, make sure \"listen\" has been called")) end while isopen(server) err = accept_nonblock(server,client) @@ -896,7 +896,7 @@ end function listen(path::AbstractString) sock = PipeServer() - bind(sock, path) || error("could not listen on path $path") + bind(sock, path) || throw(ArgumentError("could not listen on path $path")) uv_error("listen", _listen(sock)) sock end @@ -930,7 +930,7 @@ _fd(x::IOStream) = RawFD(fd(x)) for (x,writable,unix_fd,c_symbol) in ((:STDIN,false,0,:jl_uv_stdin),(:STDOUT,true,1,:jl_uv_stdout),(:STDERR,true,2,:jl_uv_stderr)) f = symbol("redirect_"*lowercase(string(x))) - _f = symbol(string("_",f)) + _f = symbol("_",f) @eval begin function ($_f)(stream) global $x @@ -960,3 +960,47 @@ mark(x::AsyncStream) = mark(x.buffer) unmark(x::AsyncStream) = unmark(x.buffer) reset(x::AsyncStream) = reset(x.buffer) ismarked(x::AsyncStream) = ismarked(x.buffer) + +# BufferStream's are non-OS streams, backed by a regular IOBuffer +type BufferStream <: AsyncStream + buffer::IOBuffer + r_c::Condition + close_c::Condition + is_open::Bool + + BufferStream() = new(PipeBuffer(), Condition(), Condition(), true) +end + +isopen(s::BufferStream) = s.is_open +close(s::BufferStream) = (s.is_open = false; notify(s.r_c; all=true); notify(s.close_c; all=true); nothing) + +function wait_readnb(s::BufferStream, nb::Int) + while isopen(s) && nb_available(s.buffer) < nb + wait(s.r_c) + end + + (nb_available(s.buffer) < nb) && error("closed BufferStream") +end + +function eof(s::BufferStream) + wait_readnb(s,1) + !isopen(s) && nb_available(s.buffer)<=0 +end + +show(io::IO, s::BufferStream) = print(io,"BufferStream() bytes waiting:",nb_available(s.buffer),", isopen:", s.is_open) + +nb_available(s::BufferStream) = nb_available(s.buffer) + +function wait_readbyte(s::BufferStream, c::UInt8) + while isopen(s) && search(s.buffer,c) <= 0 + wait(s.r_c) + end +end + +wait_close(s::BufferStream) = if isopen(s) wait(s.close_c); end +start_reading(s::BufferStream) = nothing + +write(s::BufferStream, b::UInt8) = (rv=write(s.buffer, b); notify(s.r_c; all=true);rv) +write{T}(s::BufferStream, a::Array{T}) = (rv=write(s.buffer, a); notify(s.r_c; all=true);rv) +write(s::BufferStream, p::Ptr, nb::Integer) = (rv=write(s.buffer, p, nb); notify(s.r_c; all=true);rv) + diff --git a/base/string.jl b/base/string.jl index 50fe2d82d3b52..3bc65c06c29bf 100644 --- a/base/string.jl +++ b/base/string.jl @@ -829,7 +829,7 @@ function map(f::Function, s::AbstractString) for c in s c2 = f(c) if !isa(c2,Char) - error("map(f,s::AbstractString) requires f to return Char; try map(f,collect(s)) or a comprehension instead") + throw(ArgumentError("map(f,s::AbstractString) requires f to return Char; try map(f,collect(s)) or a comprehension instead")) end write(out, c2::Char) end diff --git a/base/subarray.jl b/base/subarray.jl index 7095d096f8354..a3417a1191b08 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -287,7 +287,7 @@ first(::Colon) = 1 ## Strides stagedfunction strides{T,N,P,I}(V::SubArray{T,N,P,I}) - all(map(x->x<:Union(RangeIndex,Colon), I)) || error("strides valid only for RangeIndex indexing") + all(map(x->x<:Union(RangeIndex,Colon), I)) || throw(ArgumentError("strides valid only for RangeIndex indexing")) strideexprs = Array(Any, N+1) strideexprs[1] = 1 i = 1 diff --git a/base/tuple.jl b/base/tuple.jl index 30ce5cbdfe1fb..d95fec6b14f39 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -2,7 +2,7 @@ length(t::Tuple) = tuplelen(t) endof(t::Tuple) = tuplelen(t) -size(t::Tuple, d) = d==1 ? tuplelen(t) : error("invalid tuple dimension $(d)") +size(t::Tuple, d) = d==1 ? tuplelen(t) : throw(ArgumentError("invalid tuple dimension $d")) getindex(t::Tuple, i::Int) = tupleref(t, i) getindex(t::Tuple, i::Real) = tupleref(t, convert(Int, i)) getindex(t::Tuple, r::AbstractArray) = tuple([t[ri] for ri in r]...) diff --git a/base/utf16.jl b/base/utf16.jl index b8154a61b179f..c38ecbf1c735e 100644 --- a/base/utf16.jl +++ b/base/utf16.jl @@ -25,7 +25,7 @@ function next(s::UTF16String, i::Int) elseif length(s.data)-1 > i && utf16_is_lead(s.data[i]) && utf16_is_trail(s.data[i+1]) return utf16_get_supplementary(s.data[i], s.data[i+1]), i+2 end - error("invalid UTF-16 character index") + throw(ArgumentError("invalid UTF-16 character index")) end function reverseind(s::UTF16String, i::Integer) diff --git a/base/utf32.jl b/base/utf32.jl index ca030e45c6310..336ee7243ae54 100644 --- a/base/utf32.jl +++ b/base/utf32.jl @@ -106,7 +106,7 @@ function map(f::Function, s::UTF32String) for i = 1:(length(d)-1) c2 = f(d[i]) if !isa(c2, Char) - error("map(f,s::AbstractString) requires f to return Char; try map(f,collect(s)) or a comprehension instead") + throw(ArgumentError("map(f,s::AbstractString) requires f to return Char; try map(f,collect(s)) or a comprehension instead")) end out[i] = (c2::Char) end diff --git a/base/utf8.jl b/base/utf8.jl index 73c08cc4c0ff6..477c0c699c3c9 100644 --- a/base/utf8.jl +++ b/base/utf8.jl @@ -60,7 +60,7 @@ function next(s::UTF8String, i::Int) end if 0 < j && i <= j+utf8_trailing[d[j]+1] <= length(d) # b is a continuation byte of a valid UTF-8 character - error("invalid UTF-8 character index") + throw(ArgumentError("invalid UTF-8 character index")) end # move past 1 byte in case the data is actually Latin-1 return '\ufffd', i+1 @@ -156,7 +156,7 @@ function reverse(s::UTF8String) out = similar(s.data) if ccall(:u8_reverse, Cint, (Ptr{UInt8}, Ptr{UInt8}, Csize_t), out, s.data, length(out)) == 1 - error("invalid UTF-8 data") + throw(ArgumentError("invalid UTF-8 data")) end UTF8String(out) end @@ -171,7 +171,7 @@ write(io::IO, s::UTF8String) = write(io, s.data) utf8(x) = convert(UTF8String, x) convert(::Type{UTF8String}, s::UTF8String) = s convert(::Type{UTF8String}, s::ASCIIString) = UTF8String(s.data) -convert(::Type{UTF8String}, a::Array{UInt8,1}) = is_valid_utf8(a) ? UTF8String(a) : error("invalid UTF-8 sequence") +convert(::Type{UTF8String}, a::Array{UInt8,1}) = is_valid_utf8(a) ? UTF8String(a) : throw(ArgumentError("invalid UTF-8 sequence")) function convert(::Type{UTF8String}, a::Array{UInt8,1}, invalids_as::AbstractString) l = length(a) idx = 1 diff --git a/base/utf8proc.jl b/base/utf8proc.jl index 1a80b7b6896c0..feacc40d04a2a 100644 --- a/base/utf8proc.jl +++ b/base/utf8proc.jl @@ -159,7 +159,7 @@ isgraph(c::Char) = (UTF8PROC_CATEGORY_LU <= category_code(c) <= UTF8PROC_CATEGOR for name = ("alnum", "alpha", "cntrl", "digit", "number", "graph", "lower", "print", "punct", "space", "upper") - f = symbol(string("is",name)) + f = symbol("is",name) @eval begin function $f(s::AbstractString) for c in s diff --git a/base/version.jl b/base/version.jl index 29712c7d92dfa..eea8bf9013009 100644 --- a/base/version.jl +++ b/base/version.jl @@ -8,26 +8,26 @@ immutable VersionNumber build::(Union(Int,ASCIIString)...) function VersionNumber(major::Integer, minor::Integer, patch::Integer, pre::(Union(Int,ASCIIString)...), bld::(Union(Int,ASCIIString)...)) - major >= 0 || error("invalid negative major version: $major") - minor >= 0 || error("invalid negative minor version: $minor") - patch >= 0 || error("invalid negative patch version: $patch") + major >= 0 || throw(ArgumentError("invalid negative major version: $major")) + minor >= 0 || throw(ArgumentError("invalid negative minor version: $minor")) + patch >= 0 || throw(ArgumentError("invalid negative patch version: $patch")) for ident in pre if isa(ident,Int) - ident >= 0 || error("invalid negative pre-release identifier: $ident") + ident >= 0 || throw(ArgumentError("invalid negative pre-release identifier: $ident")) else if !ismatch(r"^(?:|[0-9a-z-]*[a-z-][0-9a-z-]*)$"i, ident) || isempty(ident) && !(length(pre)==1 && isempty(bld)) - error("invalid pre-release identifier: ", repr(ident)) + throw(ArgumentError("invalid pre-release identifier: $(repr(ident))")) end end end for ident in bld if isa(ident,Int) - ident >= 0 || error("invalid negative build identifier: $ident") + ident >= 0 || throw(ArgumentError("invalid negative build identifier: $ident")) else if !ismatch(r"^(?:|[0-9a-z-]*[a-z-][0-9a-z-]*)$"i, ident) || isempty(ident) && length(bld)!=1 - error("invalid build identifier: ", repr(ident)) + throw(ArgumentError("invalid build identifier: $(repr(ident))")) end end end @@ -81,7 +81,7 @@ end VersionNumber(v::AbstractString) = begin m = match(VERSION_REGEX, v) - if m == nothing error("invalid version string: $v") end + m == nothing && throw(ArgumentError("invalid version string: $v")) major, minor, patch, minus, prerl, plus, build = m.captures major = int(major) minor = minor != nothing ? int(minor) : 0 diff --git a/doc/manual/metaprogramming.rst b/doc/manual/metaprogramming.rst index 5d75de73ecfd0..03c9d4e404980 100644 --- a/doc/manual/metaprogramming.rst +++ b/doc/manual/metaprogramming.rst @@ -138,16 +138,20 @@ used as one building-block of expressions: julia> typeof(ans) Symbol -:obj:`Symbol`\ s can also be created using :func:`symbol`, which takes -a character or string as its argument: +:obj:`Symbol`\ s can also be created using :func:`symbol`, which takes any +number of arguments and creates a new symbol by concatenating their string +representations together: .. doctest:: julia> :foo == symbol("foo") true - julia> symbol("'") - :' + julia> symbol("func",10) + :func10 + + julia> symbol(:var,'_',"sym") + :var_sym In the context of an expression, symbols are used to indicate access to variables; when an expression is evaluated, a symbol is replaced with diff --git a/doc/manual/parallel-computing.rst b/doc/manual/parallel-computing.rst index 522d71f78abbb..bd36495753414 100644 --- a/doc/manual/parallel-computing.rst +++ b/doc/manual/parallel-computing.rst @@ -674,21 +674,46 @@ retained. ClusterManagers --------------- -Julia worker processes can also be spawned on arbitrary machines, -enabling Julia's natural parallelism to function quite transparently -in a cluster environment. The :class:`ClusterManager` interface provides a -way to specify a means to launch and manage worker processes. +The launching, management and networking of julia processes into a logical +cluster is done via cluster managers. A ``ClusterManager`` is responsible for -Thus, a custom cluster manager would need to: +- launching worker processes in a cluster environment +- managing events during the lifetime of each worker +- optionally, a cluster manager can also provide data transport -- be a subtype of the abstract :class:`ClusterManager` -- implement :func:`launch`, a method responsible for launching new workers -- implement :func:`manage`, which is called at various events during a worker's lifetime +A julia cluster has the following characteristics: +- The initial julia process, also called the ``master`` is special and has a julia id of 1. +- Only the ``master`` process can add or remove worker processes. +- All processes can directly communicate with each other. + +Connections between workers (using the in-built TCP/IP transport) is established in the following manner: +- ``addprocs`` is called on the master process with a ``ClusterManager`` object +- ``addprocs`` calls the appropriate ``launch`` method which spawns required + number of worker processes on appropriate machines +- Each worker starts listening on a free port and writes out its host, port information to STDOUT +- The cluster manager captures the stdout's of each worker and makes it available to the master process +- The master process parses this information and sets up TCP/IP connections to each worker +- Every worker is also notified of other workers in the cluster +- Each worker connects to all workers whose julia id is less than its own id +- In this way a mesh network is established, wherein every worker is directly connected with every other worker + + +While the default transport layer uses plain TCP sockets, it is possible for a julia cluster to provide +its own transport. Julia provides two in-built cluster managers: -- :class:`LocalManager`, used when :func:`addprocs` or :func:`addprocs(::Integer) ` are called -- :class:`SSHManager`, used when :func:`addprocs(::Array) ` is called with a list of hostnames +- ``LocalManager``, used when :func:`addprocs` or :func:`addprocs(np::Integer) ` are called +- ``SSHManager``, used when :func:`addprocs(hostnames::Array) ` is called with a list of hostnames + +:class:`LocalManager` is used to launch additional workers on the same host, thereby leveraging multi-core +and multi-processor hardware. + +Thus, a minimal cluster manager would need to: + +- be a subtype of the abstract :class:`ClusterManager` +- implement :func:`launch`, a method responsible for launching new workers +- implement :func:`manage`, which is called at various events during a worker's lifetime :func:`addprocs(manager::FooManager) ` requires ``FooManager`` to implement:: @@ -730,8 +755,8 @@ argument. Optionally ``--bind-to bind_addr[:port]`` may also be specified to ena to connect to it at the specified ``bind_addr`` and ``port``. Useful for multi-homed hosts. -For every worker launched, the :func:`launch` method must add a :clas`WorkerConfig` -object with appropriate fields initialized to ``launched`` :: +For every worker launched, the :func:`launch` method must add a :class:`WorkerConfig` +object (with appropriate fields initialized) to ``launched`` :: type WorkerConfig # Common fields relevant to all cluster managers @@ -753,6 +778,8 @@ object with appropriate fields initialized to ``launched`` :: sshflags::Nullable{Cmd} max_parallel::Nullable{Integer} + connect_at::Nullable{Any} + ..... end @@ -778,7 +805,6 @@ required to connect to the workers from the master process. ``userdata`` is provided for custom cluster managers to store their own worker specific information. - :func:`manage(manager::FooManager, id::Integer, config::WorkerConfig, op::Symbol) ` is called at different times during the worker's lifetime with different ``op`` values: @@ -789,6 +815,59 @@ times during the worker's lifetime with different ``op`` values: interrupt signal. - with ``:finalize`` for cleanup purposes. + +Cluster Managers with custom transports +--------------------------------------- + +Replacing the default TCP/IP all-to-all socket connections with a custom transport layer is a little more involved. +Each julia process has as many communication tasks as the workers it is connected to. For example, consider a julia cluster of +32 processes in a all-to-all mesh network: + + - Each julia process thus has 31 communication tasks + - Each task handles all incoming messages from a single remote worker in a message processing loop + - The message processing loop waits on an ``AsyncStream`` object - for example, a TCP socket in the default implementation, reads an entire + message, processes it and waits for the next one + - Sending messages to a process is done directly from any julia task - not just communication tasks - again, via the appropriate + ``AsyncStream`` object + +Replacing the default transport involves the new implementation to setup connections to remote workers, and to provide appropriate +``AsyncStream`` objects that the message processing loops can wait on. The manager specific callbacks to be implemented are:: + + connect(manager::FooManager, pid::Integer, config::WorkerConfig) + kill(manager::FooManager, pid::Int, config::WorkerConfig) + +The default implementation (which uses TCP/IP sockets) is implemented as ``connect(manager::ClusterManager, pid::Integer, config::WorkerConfig)``. + +``connect`` should return a pair of ``AsyncStream`` objects, one for reading data sent from worker ``pid``, +and the other to write data that needs to be sent to worker ``pid``. Custom cluster managers can use an in-memory ``BufferStream`` +as the plumbing to proxy data between the custom, possibly non-AsyncStream transport and julia's in-built parallel infrastructure. + +A ``BufferStream`` is an in-memory ``IOBuffer`` which behaves like an ``AsyncStream``. + +Folder ``examples/clustermanager/0mq`` is an example of using ZeroMQ is connect julia workers in a star network with a 0MQ broker in the middle. +Note: The julia processes are still all *logically* connected to each other - any worker can message any other worker directly without any +awareness of 0MQ being used as the transport layer. + +When using custom transports: + - julia workers must be started with arguments ``--worker custom``. Just ``--worker`` will result in the newly launched + workers defaulting to the socket transport implementation + - For every logical connection with a worker, :func:`process_messages(rd::AsyncStream, wr::AsyncStream)` must be called + This launches a new task that handles reading and writing of messages from/to the worker represented by the ``AsyncStream`` objects + - :func:`init_worker(manager::FooManager)` must be called as part of worker process initializaton + - Field ``connect_at::Any`` in :class:`WorkerConfig` can be set by the cluster manager when ``launch`` is called. The value of + this field is passed in in all ``connect`` callbacks. Typically, it carries information on *how to connect* to a worker. For example, + the TCP/IP socket transport uses this field to specify the ``(host, port)`` tuple at which to connect to a worker + + +``kill(manager, pid, config)`` is called to remove a worker from the cluster. +On the master process, the corresponding ``AsyncStream`` objects must be closed by the implementation to ensure proper cleanup. The default +implementation simply executes an ``exit()`` call on the specified remote worker. + +``examples/clustermanager/simple`` is an example that shows a simple implementation using unix domain sockets for cluster setup + + + + .. rubric:: Footnotes .. [#mpi2rma] In this context, MPI refers to the MPI-1 standard. Beginning with MPI-2, the MPI standards committee introduced a new set of communication mechanisms, collectively referred to as Remote Memory Access (RMA). The motivation for adding RMA to the MPI standard was to facilitate one-sided communication patterns. For additional information on the latest MPI standard, see http://www.mpi-forum.org/docs. diff --git a/doc/stdlib/math.rst b/doc/stdlib/math.rst index aea02def55f79..c4d3f8d45f94d 100644 --- a/doc/stdlib/math.rst +++ b/doc/stdlib/math.rst @@ -81,7 +81,15 @@ Mathematical Operators Computes ``x*y+z`` without rounding the intermediate result ``x*y``. On some systems this is significantly more expensive than - ``x*y+z``. + ``x*y+z``. ``fma`` is used to improve accuracy in certain + algorithms. See ``muladd``. + +.. function:: muladd(x, y, z) + + Combined multiply-add, computes ``x*y+z`` in an efficient manner. + This may on some systems be equivalent to ``x*y+z``, or to + ``fma(x,y,z)``. ``muladd`` is used to improve performance. See + ``fma``. .. function:: div(x, y) ÷(x, y) diff --git a/doc/stdlib/parallel.rst b/doc/stdlib/parallel.rst index f5dc7320a4f37..8cf74a793b93a 100644 --- a/doc/stdlib/parallel.rst +++ b/doc/stdlib/parallel.rst @@ -101,7 +101,7 @@ General Parallel Computing Support .. function:: addprocs(n::Integer; exeflags=``) -> List of process identifiers Launches workers using the in-built ``LocalManager`` which only launches workers on the local host. - This can be used to take advantage of multiple cores. `addprocs(4)`` will add 4 processes on the local machine. + This can be used to take advantage of multiple cores. ``addprocs(4)`` will add 4 processes on the local machine. .. function:: addprocs() -> List of process identifiers diff --git a/doc/stdlib/strings.rst b/doc/stdlib/strings.rst index 07e449fe72050..c13f7084049ea 100644 --- a/doc/stdlib/strings.rst +++ b/doc/stdlib/strings.rst @@ -335,9 +335,9 @@ Tests whether a character is a valid hexadecimal digit, or whether this is true for all elements of a string. -.. function:: symbol(str) -> Symbol +.. function:: symbol(x...) -> Symbol - Convert a string to a ``Symbol``. + Create a ``Symbol`` by concatenating the string representations of the arguments together. .. function:: escape_string(str::AbstractString) -> AbstractString diff --git a/examples/clustermanager/0mq/README b/examples/clustermanager/0mq/README new file mode 100644 index 0000000000000..c6bb2cfcfb7ff --- /dev/null +++ b/examples/clustermanager/0mq/README @@ -0,0 +1,27 @@ +This is a proof-of-concept that uses ZeroMQ as transport. +It uses a star topology as opposed to the native mesh network. + +Package ZMQ must be installed. All workers only run on localhost. + +All Julia nodes only connect to a "broker" process that listens on known ports +8100 and 8101 via ZMQ sockets. + + +All commands must be run from `examples/clustermanager/0mq` directory + +First, start the broker. In a new console type: + julia broker.jl + +This does not return. + +Next, start a Julia REPL and type: + include("ZMQCM.jl") + ZMQCM.start_master(4) # start with four workers + + +Alternatively, head.jl, a test script could be run. It just launches the requested number of workers, +executes a simple command on all of them and exits. + julia head.jl 4 + +NOTE: As stated this is a proof-of-concept. A real Julia cluster using ZMQ will probably use +different ZMQ socket types and optimize the transport. diff --git a/examples/clustermanager/0mq/ZMQCM.jl b/examples/clustermanager/0mq/ZMQCM.jl new file mode 100644 index 0000000000000..f7db7ca649d75 --- /dev/null +++ b/examples/clustermanager/0mq/ZMQCM.jl @@ -0,0 +1,276 @@ +using ZMQ + +import Base: launch, manage, connect, kill + +const BROKER_SUB_PORT = 8100 +const BROKER_PUB_PORT = 8101 + +const SELF_INITIATED = 0 +const REMOTE_INITIATED = 1 + +const PAYLOAD_MSG = "J" +const CONTROL_MSG = "Z" + +const REQUEST_ACK = "R" +const ACK_MSG = "A" +const KILL_MSG = "K" + +type ZMQCMan <: ClusterManager + map_zmq_julia::Dict{Int, Tuple} + c::Condition + isfree::Bool + ctx + pub + sub + zid_self + ZMQCMan() = new(Dict{Int, Tuple}(), Condition(), true) +end + +const manager = ZMQCMan() + +function lock_for_send() + if manager.isfree == true + manager.isfree = false + else + while manager.isfree == false + wait(manager.c) + if manager.isfree == true + manager.isfree = false + return + end + end + end +end + +function release_lock_for_send() + manager.isfree = true + notify(manager.c, all=true) +end + +function init_node(zid=0) + manager.ctx = Context(1) + pub=Socket(manager.ctx, PUB) # Outbound + connect(pub, "tcp://127.0.0.1:$BROKER_SUB_PORT") + + sub=Socket(manager.ctx, SUB) # In bound + connect(sub, "tcp://127.0.0.1:$BROKER_PUB_PORT") + ZMQ.set_subscribe(sub, string(zid)) + + manager.pub = pub + manager.sub = sub + manager.zid_self = zid + + (pub, sub) +end + +function send_data(zid, mtype, data) + lock_for_send() + ZMQ.send(manager.pub, Message(string(zid)), SNDMORE) + ZMQ.send(manager.pub, Message(string(manager.zid_self)), SNDMORE) + #println("Sending message of type $mtype to $zid") + ZMQ.send(manager.pub, Message(mtype), SNDMORE) + ZMQ.send(manager.pub, Message(data)) + release_lock_for_send() +end + +function setup_connection(zid, initiated_by) + try + read_stream=BufferStream() + write_stream=BufferStream() + + if initiated_by == REMOTE_INITIATED + test_remote = false + else + test_remote = true + end + + manager.map_zmq_julia[zid] = (read_stream, write_stream, test_remote) + + @schedule begin + while true + (r_s, w_s, do_test_remote) = manager.map_zmq_julia[zid] + if do_test_remote + send_data(zid, CONTROL_MSG, REQUEST_ACK) + sleep(0.5) + else + break + end + end + (r_s, w_s, do_test_remote) = manager.map_zmq_julia[zid] + + while true + data = readavailable(w_s) + send_data(zid, PAYLOAD_MSG, data) + end + end + (read_stream, write_stream) + catch e + Base.show_backtrace(STDOUT,catch_backtrace()) + println(e) + rethrow(e) + end +end + +# BROKER +function start_broker() + ctx=Context(1) + xpub=Socket(ctx, XPUB) + xsub=Socket(ctx, XSUB) + + ZMQ.bind(xsub, "tcp://127.0.0.1:$(BROKER_SUB_PORT)") + ZMQ.bind(xpub, "tcp://127.0.0.1:$(BROKER_PUB_PORT)") + + ccall((:zmq_proxy, :libzmq), Cint, (Ptr{Void}, Ptr{Void}, Ptr{Void}), xsub.data, xpub.data, C_NULL) +# proxy(xsub, xpub) + + # control never comes here + ZMQ.close(xpub) + ZMQ.close(xsub) + ZMQ.close(ctx) +end + +function recv_data() + try + #println("On $(manager.zid_self) waiting to recv message") + zid = int(bytestring(ZMQ.recv(manager.sub))) + assert(zid == manager.zid_self) + + from_zid = int(bytestring(ZMQ.recv(manager.sub))) + mtype = bytestring(ZMQ.recv(manager.sub)) + + #println("$zid received message of type $mtype from $from_zid") + + data = ZMQ.recv(manager.sub) + if mtype == CONTROL_MSG + cmsg = bytestring(data) + if cmsg == REQUEST_ACK + #println("$from_zid REQUESTED_ACK from $zid") + # send back a control_msg + send_data(from_zid, CONTROL_MSG, ACK_MSG) + elseif cmsg == ACK_MSG + #println("$zid got ACK_MSG from $from_zid") + (r_s, w_s, test_remote) = manager.map_zmq_julia[from_zid] + manager.map_zmq_julia[from_zid] = (r_s, w_s, false) + elseif cmsg == KILL_MSG + exit(0) + else + error("Unknown control message : ", cmsg) + end + data = "" + end + + (from_zid, data) + catch e + Base.show_backtrace(STDOUT,catch_backtrace()) + println(e) + rethrow(e) + end + +end + +# MASTER +function start_master(np) + init_node() + @schedule begin + try + while true + (from_zid, data) = recv_data() + + #println("master recv data from $from_zid") + + (r_s, w_s, t_r) = manager.map_zmq_julia[from_zid] + write(r_s, convert(Ptr{Uint8}, data), length(data)) + end + catch e + Base.show_backtrace(STDOUT,catch_backtrace()) + println(e) + rethrow(e) + end + end + + addprocs(manager; np=np) +end + + +function launch(manager::ZMQCMan, params::Dict, launched::Array, c::Condition) + #println("launch $(params[:np])") + for i in 1:params[:np] + io, pobj = open (`julia --worker custom worker.jl $i`, "r") + + wconfig = WorkerConfig() + wconfig.userdata = Dict(:zid=>i, :io=>io) + push!(launched, wconfig) + notify(c) + end +end + +function connect(manager::ZMQCMan, pid::Int, config::WorkerConfig) + #println("connect_m2w") + if myid() == 1 + zid = get(config.userdata)[:zid] + config.connect_at = zid # This will be useful in the worker-to-worker connection setup. + + print_worker_stdout(get(config.userdata)[:io], pid) + else + #println("connect_w2w") + zid = get(config.connect_at) + config.userdata = Dict{Symbol, Any}(:zid=>zid) + end + + streams = setup_connection(zid, SELF_INITIATED) + + udata = get(config.userdata) + udata[:streams] = streams + + streams +end + +# WORKER +function start_worker(zid) + #println("start_worker") + Base.init_worker(ZMQCMan()) + init_node(zid) + + while true + (from_zid, data) = recv_data() + + #println("worker recv data from $from_zid") + + streams = get(manager.map_zmq_julia, from_zid, nothing) + if streams == nothing + # First time.. + (r_s, w_s) = setup_connection(from_zid, REMOTE_INITIATED) + process_messages(r_s, w_s) + else + (r_s, w_s, t_r) = streams + end + + write(r_s, convert(Ptr{Uint8}, data), length(data)) + end +end + +function manage(manager::ZMQCMan, id::Int, config::WorkerConfig, op) + nothing +end + +function kill(manager::ZMQCMan, pid::Int, config::WorkerConfig) + send_data(get(config.userdata)[:zid], CONTROL_MSG, KILL_MSG) + (r_s, w_s) = get(config.userdata)[:streams] + close(r_s) + close(w_s) + + # remove from our map + delete!(manager.map_zmq_julia, get(config.userdata)[:zid]) + + nothing +end + + + +function print_worker_stdout(io, pid) + @schedule while !eof(io) + line = readline(io) + print("\tFrom worker $(pid):\t$line") + end +end + diff --git a/examples/clustermanager/0mq/broker.jl b/examples/clustermanager/0mq/broker.jl new file mode 100644 index 0000000000000..527090c606e66 --- /dev/null +++ b/examples/clustermanager/0mq/broker.jl @@ -0,0 +1,2 @@ +include("ZMQCM.jl") +start_broker() diff --git a/examples/clustermanager/0mq/head.jl b/examples/clustermanager/0mq/head.jl new file mode 100644 index 0000000000000..a3eb9c755cf8a --- /dev/null +++ b/examples/clustermanager/0mq/head.jl @@ -0,0 +1,9 @@ +include("ZMQCM.jl") + +# @spawn run(`julia broker.jl`) + +start_master(int(ARGS[1])) + +resp = pmap(x -> myid() *2, [1:nworkers()]) + +println(resp) diff --git a/examples/clustermanager/0mq/worker.jl b/examples/clustermanager/0mq/worker.jl new file mode 100644 index 0000000000000..abb7712751a83 --- /dev/null +++ b/examples/clustermanager/0mq/worker.jl @@ -0,0 +1,3 @@ +include("ZMQCM.jl") + +start_worker(int(ARGS[1])) diff --git a/examples/clustermanager/simple/README b/examples/clustermanager/simple/README new file mode 100644 index 0000000000000..86906ada08b7b --- /dev/null +++ b/examples/clustermanager/simple/README @@ -0,0 +1,12 @@ +This is a simple proof-of-concept that uses Unix Domain Sockets as transport. + +All commands must be run from `examples/clustermanager/simple` directory + +Start a Julia REPL and type: + include("UnixDomainCM.jl") + addprocs(UnixDomainCM(4)) # start with four workers + +Alternatively, head.jl, a test script could be run. It just launches the requested number of workers, +executes a simple command on all of them and exits. + julia head.jl 4 + diff --git a/examples/clustermanager/simple/UnixDomainCM.jl b/examples/clustermanager/simple/UnixDomainCM.jl new file mode 100644 index 0000000000000..114d70bdaf479 --- /dev/null +++ b/examples/clustermanager/simple/UnixDomainCM.jl @@ -0,0 +1,87 @@ +import Base: launch, manage, connect, exit + +type UnixDomainCM <: ClusterManager + np::Integer +end + +function launch(manager::UnixDomainCM, params::Dict, launched::Array, c::Condition) +# println("launch $(manager.np)") + for i in 1:manager.np + sockname = tempname() + try + cmd = `$(params[:exename]) --worker custom $(@__FILE__) worker $sockname` + io, pobj = open (cmd, "r") + + wconfig = WorkerConfig() + wconfig.userdata = Dict(:sockname=>sockname, :io=>io, :process=>pobj) + push!(launched, wconfig) + notify(c) + catch e + println(e) + end + end +end + +function connect(manager::UnixDomainCM, pid::Int, config::WorkerConfig) + if myid() == 1 +# println("connect_m2w") + config.connect_at = get(config.userdata)[:sockname] # This will be useful in the worker-to-worker connection setup. + + print_worker_stdout(get(config.userdata)[:io], pid) + else +# println("connect_w2w") + sockname = get(config.connect_at) + config.userdata = Dict{Symbol, Any}(:sockname=>sockname) + end + + t = time() + while true + try + address = get(config.userdata)[:sockname] + if isa(address, Tuple) + sock = connect(address...) + else + sock = connect(ascii(address)) + end + return (sock, sock) + catch e + if (time() - t) > 10.0 + rethrow(e) + else + gc() + sleep(0.1) + end + end + end + +end + +# WORKER +function start_worker(sockname) + Base.init_worker(UnixDomainCM(0)) + + srvr = listen(ascii(sockname)) + while true + sock = accept(srvr) + process_messages(sock, sock) + end +end + +function manage(manager::UnixDomainCM, id::Int, config::WorkerConfig, op) + if op == :deregister + rm(get(config.userdata)[:sockname]) + end + nothing +end + +function print_worker_stdout(io, pid) + @schedule while !eof(io) + line = readline(io) + print("\tFrom worker $(pid):\t$line") + end +end + +if (length(ARGS) > 0) && (ARGS[1] == "worker") + # script has been launched as a worker + start_worker(ARGS[2]) +end diff --git a/examples/clustermanager/simple/head.jl b/examples/clustermanager/simple/head.jl new file mode 100644 index 0000000000000..6f1297e6d6050 --- /dev/null +++ b/examples/clustermanager/simple/head.jl @@ -0,0 +1,5 @@ +include("UnixDomainCM.jl") + +addprocs(UnixDomainCM(int(ARGS[1]))) +resp = pmap(x -> myid() *2, [1:nworkers()]) +println(resp) diff --git a/examples/clustermanager/simple/test_simple.jl b/examples/clustermanager/simple/test_simple.jl new file mode 100644 index 0000000000000..bfe159519c947 --- /dev/null +++ b/examples/clustermanager/simple/test_simple.jl @@ -0,0 +1,10 @@ +cmanpath = joinpath(dirname(@__FILE__), "UnixDomainCM.jl") +include(cmanpath) + +npids = addprocs(UnixDomainCM(2)) +assert(length(npids) == 2) +test_pids = [remotecall_fetch(x, myid) for x in npids] +assert(npids == test_pids) +rmprocs(npids; waitfor=1.0) + +exit(0) diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index a7e0b62ddad3f..6aec85e4ae388 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -6,7 +6,7 @@ namespace JL_I { neg_int, add_int, sub_int, mul_int, sdiv_int, udiv_int, srem_int, urem_int, smod_int, neg_float, add_float, sub_float, mul_float, div_float, rem_float, - fma_float, + fma_float, muladd_float, // fast arithmetic neg_float_fast, add_float_fast, sub_float_fast, mul_float_fast, div_float_fast, rem_float_fast, @@ -986,6 +986,20 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, ArrayRef(x->getType())), FP(x), FP(y), FP(z)); } + HANDLE(muladd_float,3) +#ifdef LLVM34 + { + assert(y->getType() == x->getType()); + assert(z->getType() == y->getType()); + return builder.CreateCall3 + (Intrinsic::getDeclaration(jl_Module, Intrinsic::fmuladd, + ArrayRef(x->getType())), + FP(x), FP(y), FP(z)); + } +#else + return math_builder(ctx, true)(). + CreateFAdd(builder.CreateFMul(FP(x), FP(y)), FP(z)); +#endif HANDLE(checked_sadd,2) HANDLE(checked_uadd,2) @@ -1323,7 +1337,7 @@ extern "C" void jl_init_intrinsic_functions(void) ADD_I(sdiv_int); ADD_I(udiv_int); ADD_I(srem_int); ADD_I(urem_int); ADD_I(smod_int); ADD_I(neg_float); ADD_I(add_float); ADD_I(sub_float); ADD_I(mul_float); - ADD_I(div_float); ADD_I(rem_float); ADD_I(fma_float); + ADD_I(div_float); ADD_I(rem_float); ADD_I(fma_float); ADD_I(muladd_float); ADD_I(neg_float_fast); ADD_I(add_float_fast); ADD_I(sub_float_fast); ADD_I(mul_float_fast); ADD_I(div_float_fast); ADD_I(rem_float_fast); ADD_I(eq_int); ADD_I(ne_int); diff --git a/test/base64.jl b/test/base64.jl index 0ec6ac960ced0..eb7bb3bb4f508 100644 --- a/test/base64.jl +++ b/test/base64.jl @@ -39,4 +39,4 @@ ipipe = Base64DecodePipe(IOBuffer(string(encodedMaxLine76[1:end-2],"=="))) # Test incorrect format ipipe = Base64DecodePipe(IOBuffer(encodedMaxLine76[1:end-3])) -@test_throws ErrorException readall(ipipe) +@test_throws ArgumentError readall(ipipe) diff --git a/test/broadcast.jl b/test/broadcast.jl index c2aad5991de4c..2959d63f79525 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -50,7 +50,7 @@ for arr in (identity, as_sub) A = arr(eye(2)); @test broadcast!(+, A, A, arr([1, 4])) == arr([2 1; 4 5]) A = arr(eye(2)); @test broadcast!(+, A, A, arr([1 4])) == arr([2 4; 1 5]) - A = arr([1 0]); @test_throws ErrorException broadcast!(+, A, A, arr([1, 4])) + A = arr([1 0]); @test_throws DimensionMismatch broadcast!(+, A, A, arr([1, 4])) A = arr([1 0]); @test broadcast!(+, A, A, arr([1 4])) == arr([2 4]) A = arr([1 0]); @test broadcast!(+, A, A, 2) == arr([3 2]) diff --git a/test/dates/ranges.jl b/test/dates/ranges.jl index 3923cc1063448..d153ba2abd442 100644 --- a/test/dates/ranges.jl +++ b/test/dates/ranges.jl @@ -14,8 +14,8 @@ function test_all_combos() @test first(dr) == f1 @test last(dr) == f1-one(l1 - f1) @test length([i for i in dr]) == 0 - @test_throws ErrorException minimum(dr) - @test_throws ErrorException maximum(dr) + @test_throws ArgumentError minimum(dr) + @test_throws ArgumentError maximum(dr) @test_throws BoundsError dr[1] @test findin(dr,dr) == Int64[] @test [dr] == T[] @@ -66,8 +66,8 @@ function test_all_combos() @test first(dr) == l1 @test last(dr) == l1+one(l1 - f1) @test length([i for i in dr]) == 0 - @test_throws ErrorException minimum(dr) - @test_throws ErrorException maximum(dr) + @test_throws ArgumentError minimum(dr) + @test_throws ArgumentError maximum(dr) @test_throws BoundsError dr[1] @test findin(dr,dr) == Int64[] @test [dr] == T[] @@ -119,8 +119,8 @@ function test_all_combos() @test first(dr) == f1 @test last(dr) == f1-one(l1 - f1) @test length([i for i in dr]) == 0 - @test_throws ErrorException minimum(dr) - @test_throws ErrorException maximum(dr) + @test_throws ArgumentError minimum(dr) + @test_throws ArgumentError maximum(dr) @test_throws BoundsError dr[1] @test findin(dr,dr) == Int64[] @test [dr] == T[] @@ -171,8 +171,8 @@ function test_all_combos() @test first(dr) == l1 @test last(dr) == l1+one(l1 - f1) @test length([i for i in dr]) == 0 - @test_throws ErrorException minimum(dr) - @test_throws ErrorException maximum(dr) + @test_throws ArgumentError minimum(dr) + @test_throws ArgumentError maximum(dr) @test_throws BoundsError dr[1] @test findin(dr,dr) == Int64[] @test [dr] == T[] diff --git a/test/dict.jl b/test/dict.jl index 3c3bb11c1b9c0..9d93c9337ab4c 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -90,7 +90,7 @@ let @test typeof(d) == typeof(d2) == typeof(d3) == Dict{Any,Any} end -@test_throws ErrorException first(Dict()) +@test_throws ArgumentError first(Dict()) @test first(Dict(:f=>2)) == (:f,2) # issue #1821 @@ -268,4 +268,4 @@ let a = Dict("foo" => 0.0, "bar" => 42.0) b = Dict("フー" => 17, "バー" => 4711) @test is(typeof(merge(a, b)), Dict{UTF8String,Float64}) -end \ No newline at end of file +end diff --git a/test/examples.jl b/test/examples.jl index cf0b9fe2b8723..bd12472027504 100644 --- a/test/examples.jl +++ b/test/examples.jl @@ -35,9 +35,36 @@ include(joinpath(dir, "queens.jl")) @test solve(8, 8, 1) == Array{Int,1}[[1,1]] @test solve(8, 8, 7) == Array{Int,1}[[1,1],[2,3],[3,5],[4,2],[5,8],[7,4],[8,7]] +# Different cluster managers do not play well together. Since +# the test infrastructure already uses LocalManager, we will test the simple +# cluster manager example through a new Julia session. +@unix_only begin + script = joinpath(dir, "clustermanager/simple/test_simple.jl") + cmd = `$(joinpath(JULIA_HOME,Base.julia_exename())) $script` + if !success(cmd) + error("UnixDomainCM failed test, cmd : $cmd") + end +end + # At least make sure code loads include(joinpath(dir, "plife.jl")) include(joinpath(dir, "preduce.jl")) include(joinpath(dir, "wordcount.jl")) + +# the 0mq clustermanager depends on package ZMQ. Just making sure the +# code loads using a stub module definition for ZMQ. +zmq_found=true +try + using ZMQ +catch + zmq_found=false +end + +if !zmq_found + eval(parse("module ZMQ end")) +end + +include(joinpath(dir, "clustermanager/0mq/ZMQCM.jl")) + diff --git a/test/file.jl b/test/file.jl index 313fa510df612..4aefe5f81d6e2 100644 --- a/test/file.jl +++ b/test/file.jl @@ -187,8 +187,8 @@ c = mmap_array(UInt8, (11,), s) @test c == "Hello World".data c = mmap_array(UInt8, (uint16(11),), s) @test c == "Hello World".data -@test_throws ErrorException mmap_array(UInt8, (int16(-11),), s) -@test_throws ErrorException mmap_array(UInt8, (typemax(UInt),), s) +@test_throws ArgumentError mmap_array(UInt8, (int16(-11),), s) +@test_throws ArgumentError mmap_array(UInt8, (typemax(UInt),), s) close(s) s = open(file, "r+") @test isreadonly(s) == false @@ -212,7 +212,7 @@ s = open(file, "r") @test isreadonly(s) b = mmap_bitarray((17,13), s) @test b == trues(17,13) -@test_throws ErrorException mmap_bitarray((7,3), s) +@test_throws ArgumentError mmap_bitarray((7,3), s) close(s) s = open(file, "r+") b = mmap_bitarray((17,19), s) @@ -272,7 +272,7 @@ mark(s) @test ismarked(s) unmark(s) @test !ismarked(s) -@test_throws ErrorException reset(s) +@test_throws ArgumentError reset(s) @test !unmark(s) @test !ismarked(s) close(s) diff --git a/test/iobuffer.jl b/test/iobuffer.jl index 6bb32ba1c1cbe..0531ad9077c06 100644 --- a/test/iobuffer.jl +++ b/test/iobuffer.jl @@ -29,14 +29,14 @@ seek(io, 2) truncate(io, 10) @test ioslength(io) == 10 io.readable = false -@test_throws ErrorException read!(io,UInt8[0]) +@test_throws ArgumentError read!(io,UInt8[0]) truncate(io, 0) @test write(io,"boston\ncambridge\n") > 0 @test takebuf_string(io) == "boston\ncambridge\n" @test takebuf_string(io) == "" close(io) -@test_throws ErrorException write(io,UInt8[0]) -@test_throws ErrorException seek(io,0) +@test_throws ArgumentError write(io,UInt8[0]) +@test_throws ArgumentError seek(io,0) @test eof(io) end @@ -47,9 +47,9 @@ let io = IOBuffer("hamster\nguinea pig\nturtle") @test_throws EOFError read(io,UInt8) seek(io,0) @test read(io,UInt8) == convert(UInt8, 'h') -@test_throws ErrorException truncate(io,0) -@test_throws ErrorException write(io,uint8(0)) -@test_throws ErrorException write(io,UInt8[0]) +@test_throws ArgumentError truncate(io,0) +@test_throws ArgumentError write(io,uint8(0)) +@test_throws ArgumentError write(io,UInt8[0]) @test takebuf_string(io) == "hamster\nguinea pig\nturtle" @test takebuf_string(io) == "hamster\nguinea pig\nturtle" #should be unchanged close(io) @@ -64,8 +64,8 @@ Base.compact(io) @test readline(io) == "waffles\n" @test write(io,"whipped cream\n") > 0 @test readline(io) == "blueberries\n" -@test_throws ErrorException seek(io,0) -@test_throws ErrorException truncate(io,0) +@test_throws ArgumentError seek(io,0) +@test_throws ArgumentError truncate(io,0) @test readline(io) == "whipped cream\n" Base.compact(io) @test position(io) == 0 diff --git a/test/mod2pi.jl b/test/mod2pi.jl index 255cdea3594ca..712f659721a33 100644 --- a/test/mod2pi.jl +++ b/test/mod2pi.jl @@ -191,4 +191,4 @@ testModPi() @test_approx_eq mod2pi(355.0) 3.1416227979431572 @test_approx_eq mod2pi(355.0f0) 3.1416228f0 @test mod2pi(int64(2)^60) == mod2pi(2.0^60) -@test_throws ErrorException mod2pi(int64(2)^60-1) +@test_throws ArgumentError mod2pi(int64(2)^60-1) diff --git a/test/mpfr.jl b/test/mpfr.jl index 613e5a90044c9..4ed130a5abf32 100644 --- a/test/mpfr.jl +++ b/test/mpfr.jl @@ -149,6 +149,7 @@ y = BigFloat(1) # convert from @test convert(Float64, BigFloat(0.5)) == 0.5 @test convert(Float32, BigFloat(0.5)) == float32(0.5) +@test convert(Float16, BigFloat(0.5)) == float16(0.5) # exponent x = BigFloat(0) diff --git a/test/numbers.jl b/test/numbers.jl index 89ec4e44ad8b9..3f907b2ff4819 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -105,6 +105,43 @@ let eps = 1//BigInt(2)^200, one_eps = 1+eps, @test fma(one_eps256, one_eps256, -1) == BigFloat(one_eps * one_eps - 1) end +# muladd + +let eps = 1//BigInt(2)^30, one_eps = 1+eps, + eps64 = float64(eps), one_eps64 = float64(one_eps) + @test eps64 == float64(eps) + @test one_eps64 == float64(one_eps) + @test one_eps64 * one_eps64 - 1 != float64(one_eps * one_eps - 1) + @test isapprox(muladd(one_eps64, one_eps64, -1), + float64(one_eps * one_eps - 1)) +end + +let eps = 1//BigInt(2)^15, one_eps = 1+eps, + eps32 = float32(eps), one_eps32 = float32(one_eps) + @test eps32 == float32(eps) + @test one_eps32 == float32(one_eps) + @test one_eps32 * one_eps32 - 1 != float32(one_eps * one_eps - 1) + @test isapprox(muladd(one_eps32, one_eps32, -1), + float32(one_eps * one_eps - 1)) +end + +let eps = 1//BigInt(2)^7, one_eps = 1+eps, + eps16 = float16(float32(eps)), one_eps16 = float16(float32(one_eps)) + @test eps16 == float16(float32(eps)) + @test one_eps16 == float16(float32(one_eps)) + @test one_eps16 * one_eps16 - 1 != float16(float32(one_eps * one_eps - 1)) + @test isapprox(muladd(one_eps16, one_eps16, -1), + float16(float32(one_eps * one_eps - 1))) +end + +@test muladd(1,2,3) == 1*2+3 +@test muladd(big(1),2,3) == big(1)*2+3 +@test muladd(uint(1),2,3) == uint(1)*2+3 +@test muladd(1//1,2,3) == (1//1)*2+3 +@test muladd(big(1//1),2,3) == big(1//1)*2+3 +@test muladd(1.0,2,3) == 1.0*2+3 +@test muladd(big(1.0),2,3) == big(1.0)*2+3 + # lexing typemin(Int64) @test (-9223372036854775808)^1 == -9223372036854775808 @test [1 -1 -9223372036854775808] == [1 -1 typemin(Int64)] diff --git a/test/reduce.jl b/test/reduce.jl index 56bd615912ba3..bf25bedafccf6 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -48,7 +48,7 @@ fz = float(z) @test sum(z) === 136 @test sum(fz) === 136.0 -@test_throws ErrorException sum(sin, Int[]) +@test_throws ArgumentError sum(sin, Int[]) @test sum(sin, 3) == sin(3.0) @test sum(sin, [3]) == sin(3.0) a = sum(sin, z) @@ -92,7 +92,7 @@ for f in (sum2, sum5, sum6, sum9, sum10) end for f in (sum3, sum4, sum7, sum8) @test sum(z) == f(z) - @test_throws ErrorException f(Int[]) + @test_throws ArgumentError f(Int[]) @test sum(Int[7]) == f(Int[7]) == 7 end @test typeof(sum(Int8[])) == typeof(sum(Int8[1])) == typeof(sum(Int8[1 7])) @@ -125,8 +125,8 @@ prod2(itr) = invoke(prod, (Any,), itr) # maximum & minimum & extrema -@test_throws ErrorException maximum(Int[]) -@test_throws ErrorException minimum(Int[]) +@test_throws ArgumentError maximum(Int[]) +@test_throws ArgumentError minimum(Int[]) @test maximum(5) == 5 @test minimum(5) == 5 @@ -149,7 +149,7 @@ prod2(itr) = invoke(prod, (Any,), itr) @test extrema([4., 3., NaN, 5., 2.]) == (2., 5.) @test maxabs(Int[]) == 0 -@test_throws ErrorException Base.minabs(Int[]) +@test_throws ArgumentError Base.minabs(Int[]) @test maxabs(-2) == 2 @test minabs(-2) == 2 diff --git a/test/sets.jl b/test/sets.jl index b40060b391925..077c62bc5f95f 100644 --- a/test/sets.jl +++ b/test/sets.jl @@ -189,7 +189,7 @@ filter!(isodd, s) @test isequal(s, Set([1,3])) # first -@test_throws ErrorException first(Set()) +@test_throws ArgumentError first(Set()) @test first(Set(2)) == 2 # ########## end of set tests ########## @@ -224,8 +224,8 @@ s = IntSet([0,1,10,20,200,300,1000,10000,10002]) @test !in(0,s) @test !in(10002,s) @test in(10000,s) -@test_throws ErrorException first(IntSet()) -@test_throws ErrorException last(IntSet()) +@test_throws ArgumentError first(IntSet()) +@test_throws ArgumentError last(IntSet()) t = copy(s) sizehint!(t, 20000) #check that hash does not depend on size of internal Array{UInt32, 1} @test hash(s) == hash(t) diff --git a/test/simdloop.jl b/test/simdloop.jl index bc06140bb65df..618bb37ffa1d0 100644 --- a/test/simdloop.jl +++ b/test/simdloop.jl @@ -90,3 +90,36 @@ end)) end @label exit_loop end)) + +# @simd with cartesian iteration +function simd_cartesian_range!(indexes, crng) + @simd for I in crng + push!(indexes, I) + end + indexes +end + +crng = CartesianRange(CartesianIndex{4}(2,0,1,3), + CartesianIndex{4}(4,1,1,5)) +indexes = simd_cartesian_range!(Array(eltype(crng), 0), crng) +@test indexes == collect(crng) + +crng = CartesianRange(CartesianIndex{2}(-1,1), + CartesianIndex{2}(1,3)) +indexes = simd_cartesian_range!(Array(eltype(crng), 0), crng) +@test indexes == collect(crng) + +crng = CartesianRange(CartesianIndex{2}(-1,1), + CartesianIndex{2}(-1,3)) +indexes = simd_cartesian_range!(Array(eltype(crng), 0), crng) +@test indexes == collect(crng) + +crng = CartesianRange(CartesianIndex{1}(2), + CartesianIndex{1}(4)) +indexes = simd_cartesian_range!(Array(eltype(crng), 0), crng) +@test indexes == collect(crng) + +crng = CartesianRange(CartesianIndex{0}(), + CartesianIndex{0}()) +indexes = simd_cartesian_range!(Array(eltype(crng), 0), crng) +@test indexes == collect(crng) diff --git a/test/socket.jl b/test/socket.jl index 14139cd43fe74..27b086aa01fef 100644 --- a/test/socket.jl +++ b/test/socket.jl @@ -4,11 +4,11 @@ @test ip"192.0xFFFF" == IPv4(192,0,255,255) @test ip"192.0xFFFFF" == IPv4(192,15,255,255) @test ip"192.0xFFFFFF" == IPv4(192,255,255,255) -@test_throws ErrorException Base.parseipv4("192.0xFFFFFFF") +@test_throws ArgumentError Base.parseipv4("192.0xFFFFFFF") @test ip"022.0.0.1" == IPv4(18,0,0,1) -@test_throws ErrorException Base.parseipv4("192.0xFFFFFFFFF") -@test_throws ErrorException Base.parseipv4("192.") +@test_throws ArgumentError Base.parseipv4("192.0xFFFFFFFFF") +@test_throws ArgumentError Base.parseipv4("192.") @test ip"::1" == IPv6(1) @test ip"2605:2700:0:3::4713:93e3" == IPv6(parseint(UInt128,"260527000000000300000000471393e3",16)) diff --git a/test/sparse.jl b/test/sparse.jl index 0be54c86833b7..efb2dd0727872 100644 --- a/test/sparse.jl +++ b/test/sparse.jl @@ -323,6 +323,24 @@ for (aa116, ss116) in [(a116, s116), (ad116, sd116)] @test full(ss116[li,empty]) == aa116[li,empty] @test full(ss116[empty,empty]) == aa116[empty,empty] end + + # out of bounds indexing + @test_throws BoundsError ss116[0, 1] + @test_throws BoundsError ss116[end+1, 1] + @test_throws BoundsError ss116[1, 0] + @test_throws BoundsError ss116[1, end+1] + for j in (1, 1:size(s116,2), 1:1, Int[1], trues(size(s116, 2)), 1:0, Int[]) + @test_throws BoundsError ss116[0:1, j] + @test_throws BoundsError ss116[[0, 1], j] + @test_throws BoundsError ss116[end:end+1, j] + @test_throws BoundsError ss116[[end, end+1], j] + end + for i in (1, 1:size(s116,1), 1:1, Int[1], trues(size(s116, 1)), 1:0, Int[]) + @test_throws BoundsError ss116[i, 0:1] + @test_throws BoundsError ss116[i, [0, 1]] + @test_throws BoundsError ss116[i, end:end+1] + @test_throws BoundsError ss116[i, [end, end+1]] + end end # workaround issue #7197: comment out let-block diff --git a/test/spawn.jl b/test/spawn.jl index 622fe629c81d7..43a15ec662e58 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -146,7 +146,7 @@ mark(sock) @test readline(sock) == "Hello, world!\n" unmark(sock) @test !ismarked(sock) -@test_throws ErrorException reset(sock) +@test_throws ArgumentError reset(sock) @test !unmark(sock) @test readline(sock) == "Goodbye, world...\n" #@test eof(sock) ## doesn't work... diff --git a/test/statistics.jl b/test/statistics.jl index b233b639a1463..85b586ffcdf72 100644 --- a/test/statistics.jl +++ b/test/statistics.jl @@ -31,8 +31,7 @@ end @test all(median([2 3 1 -1; 7 4 5 -4], 2) .== [1.5, 4.5]) @test all(median([2 3 1 -1; 7 4 5 -4], 1) .== [4.5 3.5 3.0 -2.5]) - -@test_throws ErrorException median([]) +@test_throws ArgumentError median([]) @test isnan(median([NaN])) @test isnan(median([0.0,NaN])) @test isnan(median([NaN,0.0])) @@ -46,10 +45,10 @@ end # edge case: empty vector # iterable; this has to throw for type stability -@test_throws ErrorException var(()) -@test_throws ErrorException var((); corrected=false) -@test_throws ErrorException var((); mean=2) -@test_throws ErrorException var((); mean=2, corrected=false) +@test_throws ArgumentError var(()) +@test_throws ArgumentError var((); corrected=false) +@test_throws ArgumentError var((); mean=2) +@test_throws ArgumentError var((); mean=2, corrected=false) # reduction @test isnan(var(Int[])) @test isnan(var(Int[]; corrected=false)) diff --git a/test/strings.jl b/test/strings.jl index 804e14f8ab56f..4c563f1a1c4c1 100644 --- a/test/strings.jl +++ b/test/strings.jl @@ -1019,6 +1019,7 @@ let end @test symbol("asdf") === :asdf +@test symbol(:abc,"def",'g',"hi",0) === :abcdefghi0 @test startswith(string(gensym("asdf")),"##asdf#") @test gensym("asdf") != gensym("asdf") @test gensym() != gensym()