From 114cc83f95fa839d40eaca115ac3fd4e787f521c Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Thu, 30 Apr 2015 14:31:40 -0400 Subject: [PATCH 001/181] add vecdot, in analogy with vecnorm, as discussed in #11064 --- NEWS.md | 3 +++ base/exports.jl | 1 + base/linalg.jl | 1 + base/linalg/generic.jl | 44 ++++++++++++++++++++++++++++++++++++++++++ base/linalg/matmul.jl | 18 +++-------------- doc/stdlib/linalg.rst | 14 +++++++++++--- test/linalg3.jl | 15 ++++++++++++++ 7 files changed, 78 insertions(+), 18 deletions(-) diff --git a/NEWS.md b/NEWS.md index 09448e51684b9..a3e776d8251e4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -156,6 +156,8 @@ Library improvements * OpenBLAS 64-bit (ILP64) interface is now compiled with a `64_` suffix ([#8734]) to avoid conflicts with external libraries using a 32-bit BLAS ([#4923]). + * New `vecdot` function, analogous to `vecnorm`, for Euclidean inner products over any iterable container ([#11067]). + * Strings * NUL-terminated strings should now be passed to C via the new `Cstring` type, not `Ptr{UInt8}` or `Ptr{Cchar}`, @@ -1393,3 +1395,4 @@ Too numerous to mention. [#10893]: https://github.com/JuliaLang/julia/issues/10893 [#10914]: https://github.com/JuliaLang/julia/issues/10914 [#10994]: https://github.com/JuliaLang/julia/issues/10994 +[#11067]: https://github.com/JuliaLang/julia/issues/11067 diff --git a/base/exports.jl b/base/exports.jl index eb8d36231253f..64bdfd563a126 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -685,6 +685,7 @@ export tril, triu!, triu, + vecdot, vecnorm, ⋅, ×, diff --git a/base/linalg.jl b/base/linalg.jl index 1648da3630c81..d9e269ce8a6c2 100644 --- a/base/linalg.jl +++ b/base/linalg.jl @@ -115,6 +115,7 @@ export triu, tril!, triu!, + vecdot, vecnorm, # Operators diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index fbb450bcf129b..8989c8888ed0f 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -62,6 +62,9 @@ diag(A::AbstractVector) = error("use diagm instead of diag to construct a diagon #diagm{T}(v::AbstractVecOrMat{T}) +########################################################################################### +# Inner products and norms + # special cases of vecnorm; note that they don't need to handle isempty(x) function generic_vecnormMinusInf(x) s = start(x) @@ -215,6 +218,47 @@ end norm(x::Number, p::Real=2) = p == 0 ? convert(typeof(real(x)), ifelse(x != 0, 1, 0)) : abs(x) +function vecdot(x::AbstractVector, y::AbstractVector) + lx = length(x) + lx==length(y) || throw(DimensionMismatch()) + if lx == 0 + return dot(zero(eltype(x)), zero(eltype(y))) + end + s = dot(x[1], y[1]) + @inbounds for i = 2:lx + s += dot(x[i], y[i]) + end + s +end + +function vecdot(x, y) # arbitrary iterables + ix = start(x) + if done(x, ix) + isempty(y) || throw(DimensionMismatch()) + return dot(zero(eltype(x)), zero(eltype(y))) + end + iy = start(y) + done(y, iy) && throw(DimensionMismatch()) + (vx, ix) = next(x, ix) + (vy, iy) = next(y, iy) + s = dot(vx, vy) + while !done(x, ix) + done(y, iy) && throw(DimensionMismatch()) + (vx, ix) = next(x, ix) + (vy, iy) = next(y, iy) + s += dot(vx, vy) + end + !done(y, iy) && throw(DimensionMismatch()) + return s +end + +vecdot(x::Number, y::Number) = conj(x) * y + +dot(x::Number, y::Number) = vecdot(x, y) +dot(x::AbstractVector, y::AbstractVector) = vecdot(x, y) + +########################################################################################### + rank(A::AbstractMatrix, tol::Real) = sum(svdvals(A) .> tol) function rank(A::AbstractMatrix) m,n = size(A) diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index 90edc3b17156d..bf9134e936131 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -33,8 +33,8 @@ scale(b::Vector, A::Matrix) = scale!(similar(b, promote_type(eltype(A),eltype(b) # Dot products -dot{T<:BlasReal}(x::StridedVector{T}, y::StridedVector{T}) = BLAS.dot(x, y) -dot{T<:BlasComplex}(x::StridedVector{T}, y::StridedVector{T}) = BLAS.dotc(x, y) +vecdot{T<:BlasReal}(x::Union(DenseArray{T},StridedVector{T}), y::Union(DenseArray{T},StridedVector{T})) = BLAS.dot(x, y) +vecdot{T<:BlasComplex}(x::Union(DenseArray{T},StridedVector{T}), y::Union(DenseArray{T},StridedVector{T})) = BLAS.dotc(x, y) function dot{T<:BlasReal, TI<:Integer}(x::Vector{T}, rx::Union(UnitRange{TI},Range{TI}), y::Vector{T}, ry::Union(UnitRange{TI},Range{TI})) length(rx)==length(ry) || throw(DimensionMismatch()) if minimum(rx) < 1 || maximum(rx) > length(x) || minimum(ry) < 1 || maximum(ry) > length(y) @@ -49,19 +49,7 @@ function dot{T<:BlasComplex, TI<:Integer}(x::Vector{T}, rx::Union(UnitRange{TI}, end BLAS.dotc(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx), pointer(y)+(first(ry)-1)*sizeof(T), step(ry)) end -function dot(x::AbstractVector, y::AbstractVector) - lx = length(x) - lx==length(y) || throw(DimensionMismatch()) - if lx == 0 - return zero(eltype(x))*zero(eltype(y)) - end - s = conj(x[1])*y[1] - @inbounds for i = 2:lx - s += conj(x[i])*y[i] - end - s -end -dot(x::Number, y::Number) = conj(x) * y + Ac_mul_B(x::AbstractVector, y::AbstractVector) = [dot(x, y)] At_mul_B{T<:Real}(x::AbstractVector{T}, y::AbstractVector{T}) = [dot(x, y)] At_mul_B{T<:BlasComplex}(x::StridedVector{T}, y::StridedVector{T}) = [BLAS.dotu(x, y)] diff --git a/doc/stdlib/linalg.rst b/doc/stdlib/linalg.rst index 364badd3b5555..67e5112d1069c 100644 --- a/doc/stdlib/linalg.rst +++ b/doc/stdlib/linalg.rst @@ -30,6 +30,13 @@ Linear algebra functions in Julia are largely implemented by calling functions f Compute the dot product. For complex vectors, the first vector is conjugated. +.. function:: vecdot(x, y) + + For any iterable containers ``x`` and ``y`` (including arrays of + any dimension) of numbers (or any element type for which ``dot`` is + defined), compute the Euclidean dot product (the sum of + ``dot(x[i],y[i])``) as if they were vectors. + .. function:: cross(x, y) ×(x,y) @@ -493,9 +500,10 @@ Linear algebra functions in Julia are largely implemented by calling functions f .. function:: vecnorm(A, [p]) - For any iterable container ``A`` (including arrays of any dimension) - of numbers, compute the ``p``-norm (defaulting to ``p=2``) as if ``A`` - were a vector of the corresponding length. + For any iterable container ``A`` (including arrays of any + dimension) of numbers (or any element type for which ``norm`` is + defined), compute the ``p``-norm (defaulting to ``p=2``) as if + ``A`` were a vector of the corresponding length. For example, if ``A`` is a matrix and ``p=2``, then this is equivalent to the Frobenius norm. diff --git a/test/linalg3.jl b/test/linalg3.jl index 8df1aef2cd844..3ba6b610173c7 100644 --- a/test/linalg3.jl +++ b/test/linalg3.jl @@ -275,3 +275,18 @@ A = [ 1 5 9 @test diag(zeros(0,1),1) == [] @test_throws BoundsError diag(zeros(0,1),-1) @test_throws BoundsError diag(zeros(0,1),2) + +vecdot_(x,y) = invoke(vecdot, (Any,Any), x,y) # generic vecdot +let A = [1+2im 3+4im; 5+6im 7+8im], B = [2+7im 4+1im; 3+8im 6+5im] + @test vecdot(A,B) == dot(vec(A),vec(B)) == vecdot_(A,B) == vecdot(float(A),float(B)) + @test vecdot(Int[], Int[]) == 0 == vecdot_(Int[], Int[]) + @test_throws MethodError vecdot(Any[], Any[]) + @test_throws MethodError vecdot_(Any[], Any[]) + for n1 = 0:2, n2 = 0:2, d in (vecdot, vecdot_) + if n1 != n2 + @test_throws DimensionMismatch d(1:n1, 1:n2) + else + @test_approx_eq d(1:n1, 1:n2) vecnorm(1:n1)^2 + end + end +end From 7ba2351d46750d8240bd815cc0ae1389fda448e9 Mon Sep 17 00:00:00 2001 From: Jon Malmaud Date: Wed, 6 May 2015 11:10:39 -0400 Subject: [PATCH 002/181] Remove necessarity of sort 'by' and 'lt' parameters being Function types. --- base/ordering.jl | 10 +++++----- base/sort.jl | 18 +++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/base/ordering.jl b/base/ordering.jl index c3652eda7c55b..a63a7047cc119 100644 --- a/base/ordering.jl +++ b/base/ordering.jl @@ -29,12 +29,12 @@ const Reverse = ReverseOrdering(Forward) immutable LexicographicOrdering <: Ordering end const Lexicographic = LexicographicOrdering() -immutable By <: Ordering - by::Function +immutable By{T} <: Ordering + by::T end -immutable Lt <: Ordering - lt::Function +immutable Lt{T} <: Ordering + lt::T end immutable Perm{O<:Ordering,V<:AbstractVector} <: Ordering @@ -65,7 +65,7 @@ ordtype(o::Perm, vs::AbstractArray) = ordtype(o.order, o.data) ordtype(o::By, vs::AbstractArray) = try typeof(o.by(vs[1])) catch; Any end ordtype(o::Ordering, vs::AbstractArray) = eltype(vs) -function ord(lt::Function, by::Function, rev::Bool, order::Ordering=Forward) +function ord(lt, by, rev::Bool, order::Ordering=Forward) o = (lt===isless) & (by===identity) ? order : (lt===isless) & (by!==identity) ? By(by) : (lt!==isless) & (by===identity) ? Lt(lt) : diff --git a/base/sort.jl b/base/sort.jl index 036d33e4c9e6f..d9386889fe262 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -52,7 +52,7 @@ function issorted(itr, order::Ordering) return true end issorted(itr; - lt::Function=isless, by::Function=identity, rev::Bool=false, order::Ordering=Forward) = + lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) = issorted(itr, ord(lt,by,rev,order)) function select!(v::AbstractVector, k::Int, lo::Int, hi::Int, o::Ordering) @@ -117,7 +117,7 @@ end select!(v::AbstractVector, k::Union(Int,OrdinalRange), o::Ordering) = select!(v,k,1,length(v),o) select!(v::AbstractVector, k::Union(Int,OrdinalRange); - lt::Function=isless, by::Function=identity, rev::Bool=false, order::Ordering=Forward) = + lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) = select!(v, k, ord(lt,by,rev,order)) select(v::AbstractVector, k::Union(Int,OrdinalRange); kws...) = select!(copy(v), k; kws...) @@ -235,7 +235,7 @@ for s in [:searchsortedfirst, :searchsortedlast, :searchsorted] @eval begin $s(v::AbstractVector, x, o::Ordering) = $s(v,x,1,length(v),o) $s(v::AbstractVector, x; - lt::Function=isless, by::Function=identity, rev::Bool=false, order::Ordering=Forward) = + lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) = $s(v,x,ord(lt,by,rev,order)) end end @@ -360,8 +360,8 @@ sort!(v::AbstractVector, alg::Algorithm, order::Ordering) = sort!(v,1,length(v), function sort!(v::AbstractVector; alg::Algorithm=defalg(v), - lt::Function=isless, - by::Function=identity, + lt=isless, + by=identity, rev::Bool=false, order::Ordering=Forward) sort!(v, alg, ord(lt,by,rev,order)) @@ -373,8 +373,8 @@ sort(v::AbstractVector; kws...) = sort!(copy(v); kws...) function sortperm(v::AbstractVector; alg::Algorithm=DEFAULT_UNSTABLE, - lt::Function=isless, - by::Function=identity, + lt=isless, + by=identity, rev::Bool=false, order::Ordering=Forward) sort!(collect(1:length(v)), alg, Perm(ord(lt,by,rev,order),v)) @@ -382,8 +382,8 @@ end function sortperm!{I<:Integer}(x::AbstractVector{I}, v::AbstractVector; alg::Algorithm=DEFAULT_UNSTABLE, - lt::Function=isless, - by::Function=identity, + lt=isless, + by=identity, rev::Bool=false, order::Ordering=Forward, initialized::Bool=false) From 2f9b586a473173bf59ee4b9bb195cc05bf060fb1 Mon Sep 17 00:00:00 2001 From: aiorla Date: Thu, 7 May 2015 19:56:06 +0200 Subject: [PATCH 003/181] Speed up factor(n) + minor tweaks in other "primes.jl" functions --- base/primes.jl | 92 +++++++++++++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 35 deletions(-) diff --git a/base/primes.jl b/base/primes.jl index 7bd6a0a9660d5..77bc2ade33fd9 100644 --- a/base/primes.jl +++ b/base/primes.jl @@ -10,7 +10,7 @@ function primesmask(s::AbstractVector{Bool}) n = length(s) n < 2 && return s; s[2] = true n < 3 && return s; s[3] = true - r = floor(Int,sqrt(n)) + r = isqrt(n) for x = 1:r xx = x*x for y = 1:r @@ -32,16 +32,17 @@ primesmask(n::Integer) = n <= typemax(Int) ? primesmask(Int(n)) : primes(n::Union(Integer,AbstractVector{Bool})) = find(primesmask(n)) -# Miller-Rabin for primality testing: +const PRIMES = primes(2^16) + +# Small precomputed primes + Miller-Rabin for primality testing: # http://en.wikipedia.org/wiki/Miller–Rabin_primality_test # -function isprime(n::Integer) - n == 2 && return true - (n < 2) | iseven(n) && return false +function isprime{T<:Integer}(n::T) + (n < 3 || iseven(n)) && return n == 2 + n <= 2^16 && return length(searchsorted(PRIMES,n)) == 1 s = trailing_zeros(n-1) d = (n-1) >>> s for a in witnesses(n) - a < n || break x = powermod(a,d,n) x == 1 && continue t = s @@ -73,51 +74,72 @@ isprime(n::UInt128) = isprime(n::Int128) = n < 2 ? false : n <= typemax(Int64) ? isprime(Int64(n)) : isprime(BigInt(n)) -# TODO: faster factorization algorithms? - -const PRIMES = primes(10000) +# Trial division of small (< 2^16) precomputed primes + +# Pollard rho's algorithm with Richard P. Brent optimizations +# http://en.wikipedia.org/wiki/Trial_division +# http://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm +# http://maths-people.anu.edu.au/~brent/pub/pub051.html +# function factor{T<:Integer}(n::T) 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) - local s::T, p::T - s = isqrt(n) + isprime(n) && (h[n] = 1; return h) + local p::T for p in PRIMES - if p > s - h[n] = 1 - return h - end if n % p == 0 + h[p] = get(h,p,0)+1 + n = oftype(n, div(n,p)) while n % p == 0 h[p] = get(h,p,0)+1 n = oftype(n, div(n,p)) end n == 1 && return h - if isprime(n) - h[n] = 1 - return h - end - s = isqrt(n) + isprime(n) && (h[n] = 1; return h) end end - p = PRIMES[end]+2 - while p <= s - if n % p == 0 - while n % p == 0 - h[p] = get(h,p,0)+1 - n = oftype(n, div(n,p)) + pollardfactors!(n, h) +end + +function pollardfactors!{T<:Integer}(n::T, h::Dict{T,Int}) + while true + local c::T = rand(1:(n-1)), G::T = 1, r::T = 1, y::T = rand(0:(n-1)), m::T = 1900 + local ys::T, q::T = 1, x::T + while c == n - 2 + c = rand(1:(n-1)) + end + while G == 1 + x = y + for i in 1:r + y = oftype(y, widemul(y,y)%n) + y = oftype(y, (widen(y)+widen(c))%n) end - n == 1 && return h - if isprime(n) - h[n] = 1 - return h + local k::T = 0 + G = 1 + while k < r && G == 1 + for i in 1:(m>(r-k)?(r-k):m) + ys = y + y = oftype(y, widemul(y,y)%n) + y = oftype(y, (widen(y)+widen(c))%n) + q = oftype(y, widemul(q,x>y?x-y:y-x)%n) + end + G = gcd(q,n) + k = k + m end - s = isqrt(n) + r = 2 * r + end + G == n && (G = 1) + while G == 1 + ys = oftype(ys, widemul(ys,ys)%n) + ys = oftype(ys, (widen(ys)+widen(c))%n) + G = gcd(x>ys?x-ys:ys-x,n) + end + if G != n + isprime(G) ? h[G] = get(h,G,0) + 1 : pollardfactors!(G,h) + G2 = oftype(n,div(n,G)) + isprime(G2) ? h[G2] = get(h,G2,0) + 1 : pollardfactors!(G2,h) + return h end - p += 2 end - h[n] = 1 - return h end From 42d1d9bdb186087ac191986fcb30f09f14f2e119 Mon Sep 17 00:00:00 2001 From: aiorla Date: Thu, 7 May 2015 22:38:18 +0200 Subject: [PATCH 004/181] Revert to previous header of primes(n) + 2 tests for big factorizations. --- base/primes.jl | 2 +- test/numbers.jl | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/base/primes.jl b/base/primes.jl index 77bc2ade33fd9..5839fb9f27036 100644 --- a/base/primes.jl +++ b/base/primes.jl @@ -37,7 +37,7 @@ const PRIMES = primes(2^16) # Small precomputed primes + Miller-Rabin for primality testing: # http://en.wikipedia.org/wiki/Miller–Rabin_primality_test # -function isprime{T<:Integer}(n::T) +function isprime(n::Integer) (n < 3 || iseven(n)) && return n == 2 n <= 2^16 && return length(searchsorted(PRIMES,n)) == 1 s = trailing_zeros(n-1) diff --git a/test/numbers.jl b/test/numbers.jl index 95e75fd096728..f04b0247808ec 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -2092,6 +2092,10 @@ end @test 2.0f0^(1//3) == 2.0f0^(1.0f0/3) @test 2^(1//3) == 2^(1/3) +# factorization of factors > 2^16 +@test factor((big(2)^31-1)^2) == Dict(big(2^31-1) => 2) +@test factor((big(2)^31-1)*(big(2)^17-1)) == Dict(big(2^31-1) => 1, big(2^17-1) => 1) + # large shift amounts @test Int32(-1)>>31 == -1 @test Int32(-1)>>32 == -1 From 9be052df88c72980f2891f5112eb392c9439b90a Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Fri, 8 May 2015 21:40:42 -0500 Subject: [PATCH 005/181] Add isassigned for SimpleVector. Fixes #11167. --- base/array.jl | 6 +++++- base/base.jl | 6 ++++++ base/exports.jl | 1 + src/array.c | 7 +++++++ test/core.jl | 12 ++++++++++++ 5 files changed, 31 insertions(+), 1 deletion(-) diff --git a/base/array.jl b/base/array.jl index f8a0500657846..c7506d1233cba 100644 --- a/base/array.jl +++ b/base/array.jl @@ -66,7 +66,11 @@ strides{T}(a::Array{T,1}) = (1,) strides{T}(a::Array{T,2}) = (1, size(a,1)) strides{T}(a::Array{T,3}) = (1, size(a,1), size(a,1)*size(a,2)) -isassigned(a::Array, i::Int...) = isdefined(a, i...) +function isassigned{T}(a::Array{T}, i::Int...) + ii = sub2ind(size(a), i...) + 1 <= ii <= length(a) || return false + ccall(:jl_array_isassigned, Cint, (Any, UInt), a, ii-1) == 1 +end ## copy ## diff --git a/base/base.jl b/base/base.jl index 9a19ef6db1ac7..78ef20779df21 100644 --- a/base/base.jl +++ b/base/base.jl @@ -325,6 +325,12 @@ map(f, v::SimpleVector) = Any[ f(v[i]) for i = 1:length(v) ] getindex(v::SimpleVector, I::AbstractArray) = svec(Any[ v[i] for i in I ]...) +function isassigned(v::SimpleVector, i::Int) + 1 <= i <= length(v) || return false + x = unsafe_load(convert(Ptr{Ptr{Void}},data_pointer_from_objref(v)) + i*sizeof(Ptr)) + return x != C_NULL +end + immutable Nullable{T} isnull::Bool value::T diff --git a/base/exports.jl b/base/exports.jl index ac9c10601da40..ef6c869414a2e 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -523,6 +523,7 @@ export invperm, ipermute!, ipermutedims, + isassigned, isperm, issorted, last, diff --git a/src/array.c b/src/array.c index 7d04711ecca82..dad482df951d3 100644 --- a/src/array.c +++ b/src/array.c @@ -463,6 +463,13 @@ JL_CALLABLE(jl_f_arrayref) return jl_arrayref(a, i); } +DLLEXPORT int jl_array_isassigned(jl_array_t *a, size_t i) +{ + if (a->ptrarray) + return ((jl_value_t**)jl_array_data(a))[i] != NULL; + return 1; +} + int jl_array_isdefined(jl_value_t **args0, int nargs) { assert(jl_is_array(args0[0])); diff --git a/test/core.jl b/test/core.jl index 32b72f12a04ee..233ee3235486f 100644 --- a/test/core.jl +++ b/test/core.jl @@ -453,6 +453,18 @@ begin @test_throws TypeError isdefined(2) end +begin + local a + a = cell(2) + @test !isassigned(a,1) && !isassigned(a,2) + a[1] = 1 + @test isassigned(a,1) && !isassigned(a,2) + a = Array(Float64,1) + @test isassigned(a,1) + @test isassigned(a) + @test !isassigned(a,2) +end + # dispatch begin local foo, bar, baz From fef21965c39bca7bbe14b29c412a7ae4c6116db3 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Fri, 8 May 2015 21:58:05 -0500 Subject: [PATCH 006/181] Add isassigned(::SimpleVector, ::Int) tests --- test/core.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/core.jl b/test/core.jl index 233ee3235486f..fef522a3d01f9 100644 --- a/test/core.jl +++ b/test/core.jl @@ -465,6 +465,16 @@ begin @test !isassigned(a,2) end +# isassigned, issue #11167 +type Type11167{T,N} end +Type11167{Int,2} +@test !isassigned(Type11167.name.cache, 0) +@test isassigned(Type11167.name.cache, 1) +@test !isassigned(Type11167.name.cache, 2) +Type11167{Float32,5} +@test isassigned(Type11167.name.cache, 2) +@test !isassigned(Type11167.name.cache, 3) + # dispatch begin local foo, bar, baz From f7f2cdd9ed5fbbac5bbe6e800d3bdb6eecccec40 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 11 May 2015 16:04:34 -0400 Subject: [PATCH 007/181] Missing operations for LinSpace. Fix #11049 --- base/range.jl | 30 ++++++++++++++++++++++++++++++ test/ranges.jl | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/base/range.jl b/base/range.jl index 924c1ac31ec87..8f40abf8d5876 100644 --- a/base/range.jl +++ b/base/range.jl @@ -393,6 +393,15 @@ function getindex(r::FloatRange, s::OrdinalRange) FloatRange(r.start + (first(s)-1)*r.step, step(s)*r.step, sl, r.divisor) end +function getindex{T}(r::LinSpace{T}, s::OrdinalRange) + sl::T = check_indexingrange(s, r) + ifirst = first(s) + ilast = last(s) + vfirst::T = ((r.len - ifirst) * r.start + (ifirst - 1) * r.stop) / r.divisor + vlast::T = ((r.len - ilast) * r.start + (ilast - 1) * r.stop) / r.divisor + return linspace(vfirst, vlast, sl) +end + function show(io::IO, r::Range) print(io, repr(first(r)), ':', repr(step(r)), ':', repr(last(r))) end @@ -541,27 +550,34 @@ end -(r::OrdinalRange) = range(-r.start, -step(r), length(r)) -(r::FloatRange) = FloatRange(-r.start, -r.step, r.len, r.divisor) +-(r::LinSpace) = LinSpace(-r.start, -r.stop, r.len, r.divisor) .+(x::Real, r::UnitRange) = range(x + r.start, length(r)) .+(x::Real, r::Range) = (x+first(r)):step(r):(x+last(r)) #.+(x::Real, r::StepRange) = range(x + r.start, r.step, length(r)) .+(x::Real, r::FloatRange) = FloatRange(r.divisor*x + r.start, r.step, r.len, r.divisor) +.+(x::Real, r::LinSpace) = LinSpace(x + r.start, x + r.stop, r.len, r.divisor) .+(r::Range, x::Real) = x + r #.+(r::FloatRange, x::Real) = x + r .-(x::Real, r::Range) = (x-first(r)):-step(r):(x-last(r)) .-(x::Real, r::FloatRange) = FloatRange(r.divisor*x - r.start, -r.step, r.len, r.divisor) +.-(x::Real, r::LinSpace) = LinSpace(x - r.start, x - r.stop, r.len, r.divisor) .-(r::UnitRange, x::Real) = range(r.start-x, length(r)) .-(r::StepRange , x::Real) = range(r.start-x, r.step, length(r)) .-(r::FloatRange, x::Real) = FloatRange(r.start - r.divisor*x, r.step, r.len, r.divisor) +.-(r::LinSpace, x::Real) = LinSpace(r.start - x, r.stop - x, r.len, r.divisor) .*(x::Real, r::OrdinalRange) = range(x*r.start, x*step(r), length(r)) .*(x::Real, r::FloatRange) = FloatRange(x*r.start, x*r.step, r.len, r.divisor) +.*(x::Real, r::LinSpace) = LinSpace(x * r.start, x * r.stop, r.len, r.divisor) .*(r::Range, x::Real) = x .* r .*(r::FloatRange, x::Real) = x .* r +.*(r::LinSpace, x::Real) = x .* r ./(r::OrdinalRange, x::Real) = range(r.start/x, step(r)/x, length(r)) ./(r::FloatRange, x::Real) = FloatRange(r.start/x, r.step/x, r.len, r.divisor) +./(r::LinSpace, x::Real) = LinSpace(r.start / x, r.stop / x, r.len, r.divisor) promote_rule{T1,T2}(::Type{UnitRange{T1}},::Type{UnitRange{T2}}) = UnitRange{promote_type(T1,T2)} @@ -592,6 +608,19 @@ convert{T}(::Type{FloatRange{T}}, r::OrdinalRange) = convert{T}(::Type{FloatRange}, r::OrdinalRange{T}) = FloatRange{typeof(float(first(r)))}(first(r), step(r), length(r), one(T)) +promote_rule{T1,T2}(::Type{LinSpace{T1}},::Type{LinSpace{T2}}) = + LinSpace{promote_type(T1,T2)} +convert{T}(::Type{LinSpace{T}}, r::LinSpace{T}) = r +convert{T}(::Type{LinSpace{T}}, r::LinSpace) = + LinSpace{T}(r.start, r.stop, r.len, r.divisor) + +promote_rule{F,OR<:OrdinalRange}(::Type{LinSpace{F}}, ::Type{OR}) = + LinSpace{promote_type(F,eltype(OR))} +convert{T}(::Type{LinSpace{T}}, r::OrdinalRange) = + linspace(convert(T, first(r)), convert(T, last(r)), convert(T, length(r))) +convert{T}(::Type{LinSpace}, r::OrdinalRange{T}) = + convert(LinSpace{typeof(float(first(r)))}, r) + # +/- of ranges is defined in operators.jl (to be able to use @eval etc.) @@ -633,6 +662,7 @@ collect(r::Range) = vcat(r) reverse(r::OrdinalRange) = colon(last(r), -step(r), first(r)) reverse(r::FloatRange) = FloatRange(r.start + (r.len-1)*r.step, -r.step, r.len, r.divisor) +reverse(r::LinSpace) = LinSpace(r.stop, r.start, r.len, r.divisor) ## sorting ## diff --git a/test/ranges.jl b/test/ranges.jl index e4dcb20ddbd40..215b738f16eff 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -541,3 +541,47 @@ for x in r i += 2 end @test i == 7 + +# Issue 11049 and related +@test promote(linspace(0f0, 1f0, 3), linspace(0., 5., 2)) === + (linspace(0., 1., 3), linspace(0., 5., 2)) +@test convert(LinSpace{Float64}, linspace(0., 1., 3)) === linspace(0., 1., 3) +@test convert(LinSpace{Float64}, linspace(0f0, 1f0, 3)) === linspace(0., 1., 3) + +@test promote(linspace(0., 1., 3), 0:5) === (linspace(0., 1., 3), + linspace(0., 5., 6)) +@test convert(LinSpace{Float64}, 0:5) === linspace(0., 5., 6) +@test convert(LinSpace{Float64}, 0:1:5) === linspace(0., 5., 6) +@test convert(LinSpace, 0:5) === linspace(0., 5., 6) +@test convert(LinSpace, 0:1:5) === linspace(0., 5., 6) + +function test_range_index(r, s) + @test typeof(r[s]) == typeof(r) + @test [r;][s] == [r[s];] +end +test_range_index(linspace(0.1, 0.3, 3), 1:2) +test_range_index(linspace(0.1, 0.3, 3), 1:0) +test_range_index(linspace(1.0, 1.0, 1), 1:1) +test_range_index(linspace(1.0, 1.0, 1), 1:0) +test_range_index(linspace(1.0, 2.0, 0), 1:0) + +function test_linspace_identity(r, mr) + @test -r == mr + @test isa(-r, LinSpace) + + @test 1 + r + (-1) == r + @test isa(1 + r + (-1), LinSpace) + @test 1 - r - 1 == mr + @test isa(1 - r - 1, LinSpace) + + @test 1 * r * 1 == r + @test isa(1 * r * 1, LinSpace) + @test r / 1 == r + @test isa(r / 1, LinSpace) +end + +test_linspace_identity(linspace(1.0, 27.0, 1275), linspace(-1.0, -27.0, 1275)) + +@test reverse(linspace(1.0, 27.0, 1275)) == linspace(27.0, 1.0, 1275) +@test [reverse(linspace(1.0, 27.0, 1275));] == + reverse([linspace(1.0, 27.0, 1275);]) From a32628ad227651e1232a88610d8403f69ee77718 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sat, 25 Apr 2015 12:27:36 -0400 Subject: [PATCH 008/181] use jl_gf_invoke_lookup in typeinf to lookup the method to be called --- base/inference.jl | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 8d1b4f294c2e1..e4d8c3b0ce14e 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -709,26 +709,18 @@ function invoke_tfunc(f, types, argtype) if is(argtype,Bottom) return Bottom end - applicable = _methods(f, types, -1) - if isempty(applicable) - return Any - end - for (m::SimpleVector) in applicable - local linfo - try - linfo = func_for_method(m[3],types,m[2]) - catch + try + meth = ccall(:jl_gf_invoke_lookup, Any, (Any, Any), f, types) + if is(meth, nothing) return Any end - if typeseq(m[1],types) - tvars = m[2][1:2:end] - (ti, env) = ccall(:jl_match_method, Any, (Any,Any,Any), - argtype, m[1], tvars)::SimpleVector - (_tree,rt) = typeinf(linfo, ti, env, linfo) - return rt - end + (ti, env) = ccall(:jl_match_method, Any, (Any, Any, Any), + argtype, meth.sig, meth.tvars)::SimpleVector + linfo = func_for_method(meth, types, env) + return typeinf(linfo, ti, env, linfo)[2] + catch + return Any end - return Any end # `types` is an array of inferred types for expressions in `args`. From dec9a761745e2909cfb3b649b3083f27bfcbe80d Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Mon, 18 May 2015 13:48:29 +0100 Subject: [PATCH 009/181] move various factorizations into their own files --- base/linalg.jl | 5 + base/linalg/eigen.jl | 151 +++++++ base/linalg/factorization.jl | 822 ----------------------------------- base/linalg/qr.jl | 465 ++++++++++++++++++++ base/linalg/schur.jl | 75 ++++ base/linalg/svd.jl | 129 ++++++ 6 files changed, 825 insertions(+), 822 deletions(-) create mode 100644 base/linalg/eigen.jl create mode 100644 base/linalg/qr.jl create mode 100644 base/linalg/schur.jl create mode 100644 base/linalg/svd.jl diff --git a/base/linalg.jl b/base/linalg.jl index 1648da3630c81..236c68a677d30 100644 --- a/base/linalg.jl +++ b/base/linalg.jl @@ -209,7 +209,12 @@ include("linalg/lapack.jl") include("linalg/dense.jl") include("linalg/tridiag.jl") include("linalg/triangular.jl") + include("linalg/factorization.jl") +include("linalg/qr.jl") +include("linalg/eigen.jl") +include("linalg/svd.jl") +include("linalg/schur.jl") include("linalg/cholesky.jl") include("linalg/lu.jl") diff --git a/base/linalg/eigen.jl b/base/linalg/eigen.jl new file mode 100644 index 0000000000000..70527b1d5fbb5 --- /dev/null +++ b/base/linalg/eigen.jl @@ -0,0 +1,151 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + +# Eigendecomposition +immutable Eigen{T,V,S<:AbstractMatrix,U<:AbstractVector} <: Factorization{T} + values::U + vectors::S + Eigen(values::AbstractVector{V}, vectors::AbstractMatrix{T}) = new(values, vectors) +end +Eigen{T,V}(values::AbstractVector{V}, vectors::AbstractMatrix{T}) = Eigen{T,V,typeof(vectors),typeof(values)}(values, vectors) + +# Generalized eigenvalue problem. +immutable GeneralizedEigen{T,V,S<:AbstractMatrix,U<:AbstractVector} <: Factorization{T} + values::U + vectors::S + GeneralizedEigen(values::AbstractVector{V}, vectors::AbstractMatrix{T}) = new(values, vectors) +end +GeneralizedEigen{T,V}(values::AbstractVector{V}, vectors::AbstractMatrix{T}) = GeneralizedEigen{T,V,typeof(vectors),typeof(values)}(values, vectors) + + +function getindex(A::Union(Eigen,GeneralizedEigen), d::Symbol) + d == :values && return A.values + d == :vectors && return A.vectors + throw(KeyError(d)) +end + +isposdef(A::Union(Eigen,GeneralizedEigen)) = all(A.values .> 0) + +function eigfact!{T<:BlasReal}(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) + n = size(A, 2) + n==0 && return Eigen(zeros(T, 0), zeros(T, 0, 0)) + issym(A) && return eigfact!(Symmetric(A)) + A, WR, WI, VL, VR, _ = LAPACK.geevx!(permute ? (scale ? 'B' : 'P') : (scale ? 'S' : 'N'), 'N', 'V', 'N', A) + all(WI .== 0.) && return Eigen(WR, VR) + evec = zeros(Complex{T}, n, n) + j = 1 + while j <= n + if WI[j] == 0.0 + evec[:,j] = VR[:,j] + else + evec[:,j] = VR[:,j] + im*VR[:,j+1] + evec[:,j+1] = VR[:,j] - im*VR[:,j+1] + j += 1 + end + j += 1 + end + return Eigen(complex(WR, WI), evec) +end + +function eigfact!{T<:BlasComplex}(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) + n = size(A, 2) + n == 0 && return Eigen(zeros(T, 0), zeros(T, 0, 0)) + ishermitian(A) && return eigfact!(Hermitian(A)) + return Eigen(LAPACK.geevx!(permute ? (scale ? 'B' : 'P') : (scale ? 'S' : 'N'), 'N', 'V', 'N', A)[[2,4]]...) +end +function eigfact{T}(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) + S = promote_type(Float32, typeof(one(T)/norm(one(T)))) + eigfact!(copy_oftype(A, S), permute = permute, scale = scale) +end +eigfact(x::Number) = Eigen([x], fill(one(x), 1, 1)) + +# function eig(A::Union(Number, AbstractMatrix); permute::Bool=true, scale::Bool=true) +# F = eigfact(A, permute=permute, scale=scale) +# F[:values], F[:vectors] +# end +function eig(A::Union(Number, AbstractMatrix), args...; kwargs...) + F = eigfact(A, args...; kwargs...) + F[:values], F[:vectors] +end +#Calculates eigenvectors +eigvecs(A::Union(Number, AbstractMatrix), args...; kwargs...) = eigfact(A, args...; kwargs...)[:vectors] + +function eigvals!{T<:BlasReal}(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) + issym(A) && return eigvals!(Symmetric(A)) + _, valsre, valsim, _ = LAPACK.geevx!(permute ? (scale ? 'B' : 'P') : (scale ? 'S' : 'N'), 'N', 'N', 'N', A) + return all(valsim .== 0) ? valsre : complex(valsre, valsim) +end +function eigvals!{T<:BlasComplex}(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) + ishermitian(A) && return eigvals(Hermitian(A)) + return LAPACK.geevx!(permute ? (scale ? 'B' : 'P') : (scale ? 'S' : 'N'), 'N', 'N', 'N', A)[2] +end +function eigvals{T}(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) + S = promote_type(Float32, typeof(one(T)/norm(one(T)))) + return eigvals!(copy_oftype(A, S), permute = permute, scale = scale) +end +function eigvals{T<:Number}(x::T; kwargs...) + val = convert(promote_type(Float32, typeof(one(T)/norm(one(T)))), x) + return imag(val) == 0 ? [real(val)] : [val] +end + +#Computes maximum and minimum eigenvalue +function eigmax(A::Union(Number, StridedMatrix); permute::Bool=true, scale::Bool=true) + v = eigvals(A, permute = permute, scale = scale) + iseltype(v,Complex) ? error("DomainError: complex eigenvalues cannot be ordered") : maximum(v) +end +function eigmin(A::Union(Number, StridedMatrix); permute::Bool=true, scale::Bool=true) + v = eigvals(A, permute = permute, scale = scale) + iseltype(v,Complex) ? error("DomainError: complex eigenvalues cannot be ordered") : minimum(v) +end + +inv(A::Eigen) = A.vectors/Diagonal(A.values)*A.vectors' +det(A::Eigen) = prod(A.values) + +# Generalized eigenproblem +function eigfact!{T<:BlasReal}(A::StridedMatrix{T}, B::StridedMatrix{T}) + issym(A) && isposdef(B) && return eigfact!(Symmetric(A), Symmetric(B)) + n = size(A, 1) + alphar, alphai, beta, _, vr = LAPACK.ggev!('N', 'V', A, B) + all(alphai .== 0) && return GeneralizedEigen(alphar ./ beta, vr) + + vecs = zeros(Complex{T}, n, n) + j = 1 + while j <= n + if alphai[j] == 0.0 + vecs[:,j] = vr[:,j] + else + vecs[:,j ] = vr[:,j] + im*vr[:,j+1] + vecs[:,j+1] = vr[:,j] - im*vr[:,j+1] + j += 1 + end + j += 1 + end + return GeneralizedEigen(complex(alphar, alphai)./beta, vecs) +end + +function eigfact!{T<:BlasComplex}(A::StridedMatrix{T}, B::StridedMatrix{T}) + ishermitian(A) && isposdef(B) && return eigfact!(Hermitian(A), Hermitian(B)) + alpha, beta, _, vr = LAPACK.ggev!('N', 'V', A, B) + return GeneralizedEigen(alpha./beta, vr) +end +function eigfact{TA,TB}(A::AbstractMatrix{TA}, B::AbstractMatrix{TB}) + S = promote_type(Float32, typeof(one(TA)/norm(one(TA))),TB) + return eigfact!(copy_oftype(A, S), copy_oftype(B, S)) +end + +function eigvals!{T<:BlasReal}(A::StridedMatrix{T}, B::StridedMatrix{T}) + issym(A) && isposdef(B) && return eigvals!(Symmetric(A), Symmetric(B)) + alphar, alphai, beta, vl, vr = LAPACK.ggev!('N', 'N', A, B) + return (all(alphai .== 0) ? alphar : complex(alphar, alphai))./beta +end +function eigvals!{T<:BlasComplex}(A::StridedMatrix{T}, B::StridedMatrix{T}) + ishermitian(A) && isposdef(B) && return eigvals!(Hermitian(A), Hermitian(B)) + alpha, beta, vl, vr = LAPACK.ggev!('N', 'N', A, B) + alpha./beta +end +function eigvals{TA,TB}(A::AbstractMatrix{TA}, B::AbstractMatrix{TB}) + S = promote_type(Float32, typeof(one(TA)/norm(one(TA))),TB) + return eigvals!(copy_oftype(A, S), copy_oftype(B, S)) +end + +## Can we determine the source/result is Real? This is not stored in the type Eigen +full(F::Eigen) = F.vectors * Diagonal(F.values) / F.vectors diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl index 7c88964c0f42e..ac14e8c9cac67 100644 --- a/base/linalg/factorization.jl +++ b/base/linalg/factorization.jl @@ -16,814 +16,6 @@ macro assertnonsingular(A, info) :(($info)==0 ? $A : throw(SingularException($info))) end -#################### -# QR Factorization # -#################### - -immutable QR{T,S<:AbstractMatrix} <: Factorization{T} - factors::S - τ::Vector{T} - QR(factors::AbstractMatrix{T}, τ::Vector{T}) = new(factors, τ) -end -QR{T}(factors::AbstractMatrix{T}, τ::Vector{T}) = QR{T,typeof(factors)}(factors, τ) -# Note. For QRCompactWY factorization without pivoting, the WY representation based method introduced in LAPACK 3.4 -immutable QRCompactWY{S,M<:AbstractMatrix} <: Factorization{S} - factors::M - T::Matrix{S} - QRCompactWY(factors::AbstractMatrix{S}, T::AbstractMatrix{S}) = new(factors, T) -end -QRCompactWY{S}(factors::AbstractMatrix{S}, T::AbstractMatrix{S}) = QRCompactWY{S,typeof(factors)}(factors, T) - -immutable QRPivoted{T,S<:AbstractMatrix} <: Factorization{T} - factors::S - τ::Vector{T} - jpvt::Vector{BlasInt} - QRPivoted(factors::AbstractMatrix{T}, τ::Vector{T}, jpvt::Vector{BlasInt}) = new(factors, τ, jpvt) -end -QRPivoted{T}(factors::AbstractMatrix{T}, τ::Vector{T}, jpvt::Vector{BlasInt}) = QRPivoted{T,typeof(factors)}(factors, τ, jpvt) - -function qrfact!{T}(A::AbstractMatrix{T}, pivot::Union(Type{Val{false}}, Type{Val{true}})=Val{false}) - pivot==Val{true} && warn("pivoting only implemented for Float32, Float64, Complex64 and Complex128") - m, n = size(A) - τ = zeros(T, min(m,n)) - @inbounds begin - for k = 1:min(m-1+!(T<:Real),n) - τk = elementaryLeft!(A, k, k) - τ[k] = τk - for j = k+1:n - vAj = A[k,j] - for i = k+1:m - vAj += conj(A[i,k])*A[i,j] - end - vAj = conj(τk)*vAj - A[k,j] -= vAj - for i = k+1:m - A[i,j] -= A[i,k]*vAj - end - end - end - end - QR(A, τ) -end -qrfact!{T<:BlasFloat}(A::StridedMatrix{T}, pivot::Type{Val{false}} = Val{false}) = QRCompactWY(LAPACK.geqrt!(A, min(minimum(size(A)), 36))...) -qrfact!{T<:BlasFloat}(A::StridedMatrix{T}, pivot::Type{Val{true}}) = QRPivoted(LAPACK.geqp3!(A)...) -qrfact{T<:BlasFloat}(A::StridedMatrix{T}, pivot::Union(Type{Val{false}}, Type{Val{true}})=Val{false}) = qrfact!(copy(A), pivot) -copy_oftype{T}(A::StridedMatrix{T}, ::Type{T}) = copy(A) -copy_oftype{T,S}(A::StridedMatrix{T}, ::Type{S}) = convert(AbstractMatrix{S}, A) -qrfact{T}(A::StridedMatrix{T}, pivot::Union(Type{Val{false}}, Type{Val{true}})=Val{false}) = qrfact!(copy_oftype(A, typeof(one(T)/norm(one(T)))), pivot) -qrfact(x::Number) = qrfact(fill(x,1,1)) - -qr(A::Union(Number, AbstractMatrix), pivot::Union(Type{Val{false}}, Type{Val{true}})=Val{false}; thin::Bool=true) = - _qr(A, pivot, thin=thin) -function _qr(A::Union(Number, AbstractMatrix), ::Type{Val{false}}; thin::Bool=true) - F = qrfact(A, Val{false}) - full(getq(F), thin=thin), F[:R]::Matrix{eltype(F)} -end -function _qr(A::Union(Number, AbstractMatrix), ::Type{Val{true}}; thin::Bool=true) - F = qrfact(A, Val{true}) - full(getq(F), thin=thin), F[:R]::Matrix{eltype(F)}, F[:p]::Vector{BlasInt} -end - -convert{T}(::Type{QR{T}},A::QR) = QR(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ)) -convert{T}(::Type{Factorization{T}}, A::QR) = convert(QR{T}, A) -convert{T}(::Type{QRCompactWY{T}},A::QRCompactWY) = QRCompactWY(convert(AbstractMatrix{T}, A.factors), convert(AbstractMatrix{T}, A.T)) -convert{T}(::Type{Factorization{T}}, A::QRCompactWY) = convert(QRCompactWY{T}, A) -convert{T}(::Type{QRPivoted{T}},A::QRPivoted) = QRPivoted(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ), A.jpvt) -convert{T}(::Type{Factorization{T}}, A::QRPivoted) = convert(QRPivoted{T}, A) - -function getindex(A::QR, d::Symbol) - m, n = size(A) - d == :R && return triu!(A.factors[1:min(m,n), 1:n]) - d == :Q && return getq(A) - throw(KeyError(d)) -end -function getindex(A::QRCompactWY, d::Symbol) - m, n = size(A) - d == :R && return triu!(A.factors[1:min(m,n), 1:n]) - d == :Q && return getq(A) - throw(KeyError(d)) -end -function getindex{T}(A::QRPivoted{T}, d::Symbol) - m, n = size(A) - d == :R && return triu!(A.factors[1:min(m,n), 1:n]) - d == :Q && return getq(A) - d == :p && return A.jpvt - if d == :P - p = A[:p] - n = length(p) - P = zeros(T, n, n) - for i in 1:n - P[p[i],i] = one(T) - end - return P - end - throw(KeyError(d)) -end - -# Type-stable interface to get Q -getq(A::QRCompactWY) = QRCompactWYQ(A.factors,A.T) -getq(A::Union(QR, QRPivoted)) = QRPackedQ(A.factors,A.τ) - -immutable QRPackedQ{T,S<:AbstractMatrix} <: AbstractMatrix{T} - factors::S - τ::Vector{T} - QRPackedQ(factors::AbstractMatrix{T}, τ::Vector{T}) = new(factors, τ) -end -QRPackedQ{T}(factors::AbstractMatrix{T}, τ::Vector{T}) = QRPackedQ{T,typeof(factors)}(factors, τ) - -immutable QRPackedWYQ{S,M<:AbstractMatrix} <: AbstractMatrix{S} - factors::M - T::Matrix{S} - QRPackedWYQ(factors::AbstractMatrix{S}, T::Matrix{S}) = new(factors, T) -end -QRPackedWYQ{S}(factors::AbstractMatrix{S}, T::Matrix{S}) = QRPackedWYQ{S,typeof(factors)}(factors, T) - -immutable QRCompactWYQ{S, M<:AbstractMatrix} <: AbstractMatrix{S} - factors::M - T::Matrix{S} - QRCompactWYQ(factors::AbstractMatrix{S}, T::Matrix{S}) = new(factors, T) -end -QRCompactWYQ{S}(factors::AbstractMatrix{S}, T::Matrix{S}) = QRCompactWYQ{S,typeof(factors)}(factors, T) - -convert{T}(::Type{QRPackedQ{T}}, Q::QRPackedQ) = QRPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(Vector{T}, Q.τ)) -convert{T}(::Type{AbstractMatrix{T}}, Q::QRPackedQ) = convert(QRPackedQ{T}, Q) -convert{S}(::Type{QRCompactWYQ{S}}, Q::QRCompactWYQ) = QRCompactWYQ(convert(AbstractMatrix{S}, Q.factors), convert(AbstractMatrix{S}, Q.T)) -convert{S}(::Type{AbstractMatrix{S}}, Q::QRCompactWYQ) = convert(QRCompactWYQ{S}, Q) - -size(A::Union(QR,QRCompactWY,QRPivoted), dim::Integer) = size(A.factors, dim) -size(A::Union(QR,QRCompactWY,QRPivoted)) = size(A.factors) -size(A::Union(QRPackedQ,QRCompactWYQ), dim::Integer) = 0 < dim ? (dim <= 2 ? size(A.factors, 1) : 1) : throw(BoundsError()) -size(A::Union(QRPackedQ,QRCompactWYQ)) = size(A, 1), size(A, 2) - -full{T}(A::Union(QRPackedQ{T},QRCompactWYQ{T}); thin::Bool=true) = A_mul_B!(A, thin ? eye(T, size(A.factors,1), minimum(size(A.factors))) : eye(T, size(A.factors,1))) - -## Multiplication by Q -### QB -A_mul_B!{T<:BlasFloat}(A::QRCompactWYQ{T}, B::StridedVecOrMat{T}) = LAPACK.gemqrt!('L','N',A.factors,A.T,B) -A_mul_B!{T<:BlasFloat}(A::QRPackedQ{T}, B::StridedVecOrMat{T}) = LAPACK.ormqr!('L','N',A.factors,A.τ,B) -function A_mul_B!{T}(A::QRPackedQ{T}, B::AbstractVecOrMat{T}) - mA, nA = size(A.factors) - mB, nB = size(B,1), size(B,2) - mA == mB || throw(DimensionMismatch()) - Afactors = A.factors - @inbounds begin - for k = min(mA,nA):-1:1 - for j = 1:nB - vBj = B[k,j] - for i = k+1:mB - vBj += conj(Afactors[i,k])*B[i,j] - end - vBj = A.τ[k]*vBj - B[k,j] -= vBj - for i = k+1:mB - B[i,j] -= Afactors[i,k]*vBj - end - end - end - end - B -end - -function (*){TA,Tb}(A::Union(QRPackedQ{TA},QRCompactWYQ{TA}), b::StridedVector{Tb}) - TAb = promote_type(TA, Tb) - Anew = convert(AbstractMatrix{TAb}, A) - if size(A.factors, 1) == length(b) - bnew = copy_oftype(b, TAb) - elseif size(A.factors, 2) == length(b) - bnew = [b; zeros(TAb, size(A.factors, 1) - length(b))] - else - throw(DimensionMismatch("vector must have length either $(size(A.factors, 1)) or $(size(A.factors, 2))")) - end - A_mul_B!(Anew, bnew) -end -function (*){TA,TB}(A::Union(QRPackedQ{TA},QRCompactWYQ{TA}), B::StridedMatrix{TB}) - TAB = promote_type(TA, TB) - Anew = convert(AbstractMatrix{TAB}, A) - if size(A.factors, 1) == size(B, 1) - Bnew = copy_oftype(B, TAB) - elseif size(A.factors, 2) == size(B, 1) - Bnew = [B; zeros(TAB, size(A.factors, 1) - size(B,1), size(B, 2))] - else - throw(DimensionMismatch("first dimension of matrix must have size either $(size(A.factors, 1)) or $(size(A.factors, 2))")) - end - A_mul_B!(Anew, Bnew) -end - -### QcB -Ac_mul_B!{T<:BlasReal}(A::QRCompactWYQ{T}, B::StridedVecOrMat{T}) = LAPACK.gemqrt!('L','T',A.factors,A.T,B) -Ac_mul_B!{T<:BlasComplex}(A::QRCompactWYQ{T}, B::StridedVecOrMat{T}) = LAPACK.gemqrt!('L','C',A.factors,A.T,B) -Ac_mul_B!{T<:BlasReal}(A::QRPackedQ{T}, B::StridedVecOrMat{T}) = LAPACK.ormqr!('L','T',A.factors,A.τ,B) -Ac_mul_B!{T<:BlasComplex}(A::QRPackedQ{T}, B::StridedVecOrMat{T}) = LAPACK.ormqr!('L','C',A.factors,A.τ,B) -function Ac_mul_B!{T}(A::QRPackedQ{T}, B::AbstractVecOrMat{T}) - mA, nA = size(A.factors) - mB, nB = size(B,1), size(B,2) - mA == mB || throw(DimensionMismatch()) - Afactors = A.factors - @inbounds begin - for k = 1:min(mA,nA) - for j = 1:nB - vBj = B[k,j] - for i = k+1:mB - vBj += conj(Afactors[i,k])*B[i,j] - end - vBj = conj(A.τ[k])*vBj - B[k,j] -= vBj - for i = k+1:mB - B[i,j] -= Afactors[i,k]*vBj - end - end - end - end - B -end -function Ac_mul_B{TQ<:Number,TB<:Number,N}(Q::Union(QRPackedQ{TQ},QRCompactWYQ{TQ}), B::StridedArray{TB,N}) - TQB = promote_type(TQ,TB) - return Ac_mul_B!(convert(AbstractMatrix{TQB}, Q), copy_oftype(B, TQB)) -end - -### AQ -A_mul_B!{T<:BlasFloat}(A::StridedVecOrMat{T}, B::QRCompactWYQ{T}) = LAPACK.gemqrt!('R','N', B.factors, B.T, A) -A_mul_B!(A::StridedVecOrMat, B::QRPackedQ) = LAPACK.ormqr!('R', 'N', B.factors, B.τ, A) -function A_mul_B!{T}(A::StridedMatrix{T},Q::QRPackedQ{T}) - mQ, nQ = size(Q.factors) - mA, nA = size(A,1), size(A,2) - nA == mQ || throw(DimensionMismatch()) - Qfactors = Q.factors - @inbounds begin - for k = 1:min(mQ,nQ) - for i = 1:mA - vAi = A[i,k] - for j = k+1:mQ - vAi += A[i,j]*Qfactors[j,k] - end - vAi = vAi*Q.τ[k] - A[i,k] -= vAi - for j = k+1:nA - A[i,j] -= vAi*conj(Qfactors[j,k]) - end - end - end - end - A -end - -function (*){TA,TQ,N}(A::StridedArray{TA,N}, Q::Union(QRPackedQ{TQ},QRCompactWYQ{TQ})) - TAQ = promote_type(TA, TQ) - return A_mul_B!(copy_oftype(A, TAQ), convert(AbstractMatrix{TAQ}, Q)) -end - -### AQc -A_mul_Bc!{T<:BlasReal}(A::StridedVecOrMat{T}, B::QRCompactWYQ{T}) = LAPACK.gemqrt!('R','T',B.factors,B.T,A) -A_mul_Bc!{T<:BlasComplex}(A::StridedVecOrMat{T}, B::QRCompactWYQ{T}) = LAPACK.gemqrt!('R','C',B.factors,B.T,A) -A_mul_Bc!{T<:BlasReal}(A::StridedVecOrMat{T}, B::QRPackedQ{T}) = LAPACK.ormqr!('R','T',B.factors,B.τ,A) -A_mul_Bc!{T<:BlasComplex}(A::StridedVecOrMat{T}, B::QRPackedQ{T}) = LAPACK.ormqr!('R','C',B.factors,B.τ,A) -function A_mul_Bc!{T}(A::AbstractMatrix{T},Q::QRPackedQ{T}) - mQ, nQ = size(Q.factors) - mA, nA = size(A,1), size(A,2) - nA == mQ || throw(DimensionMismatch()) - Qfactors = Q.factors - @inbounds begin - for k = min(mQ,nQ):-1:1 - for i = 1:mA - vAi = A[i,k] - for j = k+1:mQ - vAi += A[i,j]*Qfactors[j,k] - end - vAi = vAi*conj(Q.τ[k]) - A[i,k] -= vAi - for j = k+1:nA - A[i,j] -= vAi*conj(Qfactors[j,k]) - end - end - end - end - A -end -A_mul_Bc(A::AbstractTriangular, B::Union(QRCompactWYQ,QRPackedQ)) = A_mul_Bc(full(A), B) -function A_mul_Bc{TA,TB}(A::AbstractArray{TA}, B::Union(QRCompactWYQ{TB},QRPackedQ{TB})) - TAB = promote_type(TA,TB) - BB = convert(AbstractMatrix{TAB}, B) - if size(A,2) == size(B.factors, 1) - return A_mul_Bc!(copy_oftype(A, TAB), BB) - elseif size(A,2) == size(B.factors,2) - return A_mul_Bc!([A zeros(TAB, size(A, 1), size(B.factors, 1) - size(B.factors, 2))], BB) - else - throw(DimensionMismatch()) - end -end - -A_ldiv_B!{T<:BlasFloat}(A::QRCompactWY{T}, b::StridedVector{T}) = (A_ldiv_B!(UpperTriangular(A[:R]), sub(Ac_mul_B!(A[:Q], b), 1:size(A, 2))); b) -A_ldiv_B!{T<:BlasFloat}(A::QRCompactWY{T}, B::StridedMatrix{T}) = (A_ldiv_B!(UpperTriangular(A[:R]), sub(Ac_mul_B!(A[:Q], B), 1:size(A, 2), 1:size(B, 2))); B) - -# Julia implementation similarly to xgelsy -function A_ldiv_B!{T<:BlasFloat}(A::QRPivoted{T}, B::StridedMatrix{T}, rcond::Real) - mA, nA = size(A.factors) - nr = min(mA,nA) - nrhs = size(B, 2) - if nr == 0 return zeros(T, 0, nrhs), 0 end - ar = abs(A.factors[1]) - if ar == 0 return zeros(T, nr, nrhs), 0 end - rnk = 1 - xmin = ones(T, 1) - xmax = ones(T, 1) - tmin = tmax = ar - while rnk < nr - tmin, smin, cmin = LAPACK.laic1!(2, xmin, tmin, sub(A.factors, 1:rnk, rnk + 1), A.factors[rnk + 1, rnk + 1]) - tmax, smax, cmax = LAPACK.laic1!(1, xmax, tmax, sub(A.factors, 1:rnk, rnk + 1), A.factors[rnk + 1, rnk + 1]) - tmax*rcond > tmin && break - push!(xmin, cmin) - push!(xmax, cmax) - for i = 1:rnk - xmin[i] *= smin - xmax[i] *= smax - end - rnk += 1 - end - C, τ = LAPACK.tzrzf!(A.factors[1:rnk,:]) - A_ldiv_B!(UpperTriangular(C[1:rnk,1:rnk]),sub(Ac_mul_B!(getq(A),sub(B, 1:mA, 1:nrhs)),1:rnk,1:nrhs)) - B[rnk+1:end,:] = zero(T) - LAPACK.ormrz!('L', iseltype(B, Complex) ? 'C' : 'T', C, τ, sub(B,1:nA,1:nrhs)) - B[1:nA,:] = sub(B, 1:nA, :)[invperm(A[:p]::Vector{BlasInt}),:] - return B, rnk -end -A_ldiv_B!{T<:BlasFloat}(A::QRPivoted{T}, B::StridedVector{T}) = vec(A_ldiv_B!(A,reshape(B,length(B),1))) -A_ldiv_B!{T<:BlasFloat}(A::QRPivoted{T}, B::StridedVecOrMat{T}) = A_ldiv_B!(A, B, maximum(size(A))*eps(real(float(one(eltype(B))))))[1] -function A_ldiv_B!{T}(A::QR{T},B::StridedMatrix{T}) - m, n = size(A) - minmn = min(m,n) - mB, nB = size(B) - Ac_mul_B!(A[:Q],sub(B,1:m,1:nB)) # Reconsider when arrayviews are merged. - R = A[:R] - @inbounds begin - if n > m # minimum norm solution - τ = zeros(T,m) - for k = m:-1:1 # Trapezoid to triangular by elementary operation - τ[k] = elementaryRightTrapezoid!(R,k) - for i = 1:k-1 - vRi = R[i,k] - for j = m+1:n - vRi += R[i,j]*R[k,j] - end - vRi *= τ[k] - R[i,k] -= vRi - for j = m+1:n - R[i,j] -= vRi*R[k,j] - end - end - end - end - for k = 1:nB # solve triangular system. When array views are implemented, consider exporting to function. - for i = minmn:-1:1 - for j = i+1:minmn - B[i,k] -= R[i,j]*B[j,k] - end - B[i,k] /= R[i,i] - end - end - if n > m # Apply elementary transformation to solution - B[m+1:mB,1:nB] = zero(T) - for j = 1:nB - for k = 1:m - vBj = B[k,j] - for i = m+1:n - vBj += B[i,j]*conj(R[k,i]) - end - vBj *= τ[k] - B[k,j] -= vBj - for i = m+1:n - B[i,j] -= R[k,i]*vBj - end - end - end - end - end - return B -end -A_ldiv_B!(A::QR, B::StridedVector) = A_ldiv_B!(A, reshape(B, length(B), 1))[:] -function A_ldiv_B!(A::QRPivoted, b::StridedVector) - A_ldiv_B!(QR(A.factors,A.τ), b) - b[1:size(A.factors, 2)] = sub(b, 1:size(A.factors, 2))[invperm(A.jpvt)] - b -end -function A_ldiv_B!(A::QRPivoted, B::StridedMatrix) - A_ldiv_B!(QR(A.factors, A.τ), B) - B[1:size(A.factors, 2),:] = sub(B, 1:size(A.factors, 2), :)[invperm(A.jpvt)] - B -end -function \{TA,Tb}(A::Union(QR{TA},QRCompactWY{TA},QRPivoted{TA}), b::StridedVector{Tb}) - S = promote_type(TA,Tb) - m,n = size(A) - m == length(b) || throw(DimensionMismatch("left hand side has $m rows, but right hand side has length $(length(b))")) - AA = convert(Factorization{S}, A) - if n > m - x = A_ldiv_B!(AA, [b; zeros(S, n - m)]) - else - x = A_ldiv_B!(AA, copy_oftype(b, S)) - end - return length(x) > n ? x[1:n] : x -end -function \{TA,TB}(A::Union(QR{TA},QRCompactWY{TA},QRPivoted{TA}),B::StridedMatrix{TB}) - S = promote_type(TA,TB) - m,n = size(A) - m == size(B,1) || throw(DimensionMismatch("left hand side has $m rows, but right hand side has $(size(B,1)) rows")) - AA = convert(Factorization{S}, A) - if n > m - X = A_ldiv_B!(AA, [B; zeros(S, n - m, size(B, 2))]) - else - X = A_ldiv_B!(AA, copy_oftype(B, S)) - end - return size(X, 1) > n ? X[1:n,:] : X -end - -##TODO: Add methods for rank(A::QRP{T}) and adjust the (\) method accordingly -## Add rcond methods for Cholesky, LU, QR and QRP types -## Lower priority: Add LQ, QL and RQ factorizations - -# FIXME! Should add balancing option through xgebal -immutable Hessenberg{T,S<:AbstractMatrix} <: Factorization{T} - factors::S - τ::Vector{T} - Hessenberg(factors::AbstractMatrix{T}, τ::Vector{T}) = new(factors, τ) -end -Hessenberg{T}(factors::AbstractMatrix{T}, τ::Vector{T}) = Hessenberg{T,typeof(factors)}(factors, τ) - -Hessenberg(A::StridedMatrix) = Hessenberg(LAPACK.gehrd!(A)...) - -hessfact!{T<:BlasFloat}(A::StridedMatrix{T}) = Hessenberg(A) -hessfact{T<:BlasFloat}(A::StridedMatrix{T}) = hessfact!(copy(A)) -function hessfact{T}(A::StridedMatrix{T}) - S = promote_type(Float32, typeof(one(T)/norm(one(T)))) - return hessfact!(copy_oftype(A, S)) -end - -immutable HessenbergQ{T,S<:AbstractMatrix} <: AbstractMatrix{T} - factors::S - τ::Vector{T} - HessenbergQ(factors::AbstractMatrix{T}, τ::Vector{T}) = new(factors, τ) -end -HessenbergQ{T}(factors::AbstractMatrix{T}, τ::Vector{T}) = HessenbergQ{T,typeof(factors)}(factors, τ) -HessenbergQ(A::Hessenberg) = HessenbergQ(A.factors, A.τ) -size(A::HessenbergQ, args...) = size(A.factors, args...) - -function getindex(A::Hessenberg, d::Symbol) - d == :Q && return HessenbergQ(A) - d == :H && return triu(A.factors, -1) - throw(KeyError(d)) -end - -full(A::HessenbergQ) = LAPACK.orghr!(1, size(A.factors, 1), copy(A.factors), A.τ) - -# Also printing of QRQs -getindex(A::Union(QRPackedQ,QRCompactWYQ,HessenbergQ), i::Integer, j::Integer) = (x = zeros(eltype(A), size(A, 1)); x[i] = 1; y = zeros(eltype(A), size(A, 2)); y[j] = 1; dot(x, A*y)) - - -####################### -# Eigendecompositions # -####################### - -# Eigenvalues -immutable Eigen{T,V,S<:AbstractMatrix,U<:AbstractVector} <: Factorization{T} - values::U - vectors::S - Eigen(values::AbstractVector{V}, vectors::AbstractMatrix{T}) = new(values, vectors) -end -Eigen{T,V}(values::AbstractVector{V}, vectors::AbstractMatrix{T}) = Eigen{T,V,typeof(vectors),typeof(values)}(values, vectors) - -# Generalized eigenvalue problem. -immutable GeneralizedEigen{T,V,S<:AbstractMatrix,U<:AbstractVector} <: Factorization{T} - values::U - vectors::S - GeneralizedEigen(values::AbstractVector{V}, vectors::AbstractMatrix{T}) = new(values, vectors) -end -GeneralizedEigen{T,V}(values::AbstractVector{V}, vectors::AbstractMatrix{T}) = GeneralizedEigen{T,V,typeof(vectors),typeof(values)}(values, vectors) - - -function getindex(A::Union(Eigen,GeneralizedEigen), d::Symbol) - d == :values && return A.values - d == :vectors && return A.vectors - throw(KeyError(d)) -end - -isposdef(A::Union(Eigen,GeneralizedEigen)) = all(A.values .> 0) - -function eigfact!{T<:BlasReal}(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) - n = size(A, 2) - n==0 && return Eigen(zeros(T, 0), zeros(T, 0, 0)) - issym(A) && return eigfact!(Symmetric(A)) - A, WR, WI, VL, VR, _ = LAPACK.geevx!(permute ? (scale ? 'B' : 'P') : (scale ? 'S' : 'N'), 'N', 'V', 'N', A) - all(WI .== 0.) && return Eigen(WR, VR) - evec = zeros(Complex{T}, n, n) - j = 1 - while j <= n - if WI[j] == 0.0 - evec[:,j] = VR[:,j] - else - evec[:,j] = VR[:,j] + im*VR[:,j+1] - evec[:,j+1] = VR[:,j] - im*VR[:,j+1] - j += 1 - end - j += 1 - end - return Eigen(complex(WR, WI), evec) -end - -function eigfact!{T<:BlasComplex}(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) - n = size(A, 2) - n == 0 && return Eigen(zeros(T, 0), zeros(T, 0, 0)) - ishermitian(A) && return eigfact!(Hermitian(A)) - return Eigen(LAPACK.geevx!(permute ? (scale ? 'B' : 'P') : (scale ? 'S' : 'N'), 'N', 'V', 'N', A)[[2,4]]...) -end -function eigfact{T}(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) - S = promote_type(Float32, typeof(one(T)/norm(one(T)))) - eigfact!(copy_oftype(A, S), permute = permute, scale = scale) -end -eigfact(x::Number) = Eigen([x], fill(one(x), 1, 1)) - -# function eig(A::Union(Number, AbstractMatrix); permute::Bool=true, scale::Bool=true) -# F = eigfact(A, permute=permute, scale=scale) -# F[:values], F[:vectors] -# end -function eig(A::Union(Number, AbstractMatrix), args...; kwargs...) - F = eigfact(A, args...; kwargs...) - F[:values], F[:vectors] -end -#Calculates eigenvectors -eigvecs(A::Union(Number, AbstractMatrix), args...; kwargs...) = eigfact(A, args...; kwargs...)[:vectors] - -function eigvals!{T<:BlasReal}(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) - issym(A) && return eigvals!(Symmetric(A)) - _, valsre, valsim, _ = LAPACK.geevx!(permute ? (scale ? 'B' : 'P') : (scale ? 'S' : 'N'), 'N', 'N', 'N', A) - return all(valsim .== 0) ? valsre : complex(valsre, valsim) -end -function eigvals!{T<:BlasComplex}(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) - ishermitian(A) && return eigvals(Hermitian(A)) - return LAPACK.geevx!(permute ? (scale ? 'B' : 'P') : (scale ? 'S' : 'N'), 'N', 'N', 'N', A)[2] -end -function eigvals{T}(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) - S = promote_type(Float32, typeof(one(T)/norm(one(T)))) - return eigvals!(copy_oftype(A, S), permute = permute, scale = scale) -end -function eigvals{T<:Number}(x::T; kwargs...) - val = convert(promote_type(Float32, typeof(one(T)/norm(one(T)))), x) - return imag(val) == 0 ? [real(val)] : [val] -end - -#Computes maximum and minimum eigenvalue -function eigmax(A::Union(Number, StridedMatrix); permute::Bool=true, scale::Bool=true) - v = eigvals(A, permute = permute, scale = scale) - iseltype(v,Complex) ? error("DomainError: complex eigenvalues cannot be ordered") : maximum(v) -end -function eigmin(A::Union(Number, StridedMatrix); permute::Bool=true, scale::Bool=true) - v = eigvals(A, permute = permute, scale = scale) - iseltype(v,Complex) ? error("DomainError: complex eigenvalues cannot be ordered") : minimum(v) -end - -inv(A::Eigen) = A.vectors/Diagonal(A.values)*A.vectors' -det(A::Eigen) = prod(A.values) - -# Generalized eigenproblem -function eigfact!{T<:BlasReal}(A::StridedMatrix{T}, B::StridedMatrix{T}) - issym(A) && isposdef(B) && return eigfact!(Symmetric(A), Symmetric(B)) - n = size(A, 1) - alphar, alphai, beta, _, vr = LAPACK.ggev!('N', 'V', A, B) - all(alphai .== 0) && return GeneralizedEigen(alphar ./ beta, vr) - - vecs = zeros(Complex{T}, n, n) - j = 1 - while j <= n - if alphai[j] == 0.0 - vecs[:,j] = vr[:,j] - else - vecs[:,j ] = vr[:,j] + im*vr[:,j+1] - vecs[:,j+1] = vr[:,j] - im*vr[:,j+1] - j += 1 - end - j += 1 - end - return GeneralizedEigen(complex(alphar, alphai)./beta, vecs) -end - -function eigfact!{T<:BlasComplex}(A::StridedMatrix{T}, B::StridedMatrix{T}) - ishermitian(A) && isposdef(B) && return eigfact!(Hermitian(A), Hermitian(B)) - alpha, beta, _, vr = LAPACK.ggev!('N', 'V', A, B) - return GeneralizedEigen(alpha./beta, vr) -end -function eigfact{TA,TB}(A::AbstractMatrix{TA}, B::AbstractMatrix{TB}) - S = promote_type(Float32, typeof(one(TA)/norm(one(TA))),TB) - return eigfact!(copy_oftype(A, S), copy_oftype(B, S)) -end - -function eigvals!{T<:BlasReal}(A::StridedMatrix{T}, B::StridedMatrix{T}) - issym(A) && isposdef(B) && return eigvals!(Symmetric(A), Symmetric(B)) - alphar, alphai, beta, vl, vr = LAPACK.ggev!('N', 'N', A, B) - return (all(alphai .== 0) ? alphar : complex(alphar, alphai))./beta -end -function eigvals!{T<:BlasComplex}(A::StridedMatrix{T}, B::StridedMatrix{T}) - ishermitian(A) && isposdef(B) && return eigvals!(Hermitian(A), Hermitian(B)) - alpha, beta, vl, vr = LAPACK.ggev!('N', 'N', A, B) - alpha./beta -end -function eigvals{TA,TB}(A::AbstractMatrix{TA}, B::AbstractMatrix{TB}) - S = promote_type(Float32, typeof(one(TA)/norm(one(TA))),TB) - return eigvals!(copy_oftype(A, S), copy_oftype(B, S)) -end - -# SVD -immutable SVD{T<:BlasFloat,Tr,M<:AbstractArray} <: Factorization{T} - U::M - S::Vector{Tr} - Vt::M - SVD(U::AbstractArray{T}, S::Vector{Tr}, Vt::AbstractArray{T}) = new(U, S, Vt) -end -SVD{T<:BlasFloat,Tr}(U::AbstractArray{T}, S::Vector{Tr}, Vt::AbstractArray{T}) = SVD{T,Tr,typeof(U)}(U, S, Vt) - -function svdfact!{T<:BlasFloat}(A::StridedMatrix{T}; thin::Bool=true) - m,n = size(A) - if m == 0 || n == 0 - u,s,vt = (eye(T, m, thin ? n : m), real(zeros(T,0)), eye(T,n,n)) - else - u,s,vt = LAPACK.gesdd!(thin ? 'S' : 'A', A) - end - SVD(u,s,vt) -end -function svdfact{T}(A::StridedVecOrMat{T};thin = true) - S = promote_type(Float32, typeof(one(T)/norm(one(T)))) - svdfact!(copy_oftype(A, S), thin = thin) -end -svdfact(x::Number; thin::Bool=true) = SVD(x == 0 ? fill(one(x), 1, 1) : fill(x/abs(x), 1, 1), [abs(x)], fill(one(x), 1, 1)) -svdfact(x::Integer; thin::Bool=true) = svdfact(float(x), thin=thin) - -function svd(A::Union(Number, AbstractArray); thin::Bool=true) - F = svdfact(A, thin=thin) - F.U, F.S, F.Vt' -end - -function getindex(F::SVD, d::Symbol) - d == :U && return F.U - d == :S && return F.S - d == :Vt && return F.Vt - d == :V && return F.Vt' - throw(KeyError(d)) -end - -svdvals!{T<:BlasFloat}(A::StridedMatrix{T}) = any([size(A)...].==0) ? zeros(T, 0) : LAPACK.gesdd!('N', A)[2] -svdvals{T<:BlasFloat}(A::AbstractMatrix{T}) = svdvals!(copy(A)) -function svdvals{T}(A::AbstractMatrix{T}) - S = promote_type(Float32, typeof(one(T)/norm(one(T)))) - svdvals!(copy_oftype(A, S)) -end -svdvals(x::Number) = [abs(x)] - -# SVD least squares -function \{T<:BlasFloat}(A::SVD{T}, B::StridedVecOrMat{T}) - n = length(A.S) - Sinv = zeros(T, n) - k = length(find(A.S .> eps(real(float(one(T))))*maximum(A.S))) - Sinv[1:k] = one(T) ./ A.S[1:k] - A.Vt[1:k,:]' * (Sinv[1:k] .* (A.U[:,1:k]' * B)) -end - -# Generalized svd -immutable GeneralizedSVD{T,S} <: Factorization{T} - U::S - V::S - Q::S - a::Vector - b::Vector - k::Int - l::Int - R::S - GeneralizedSVD(U::AbstractMatrix{T}, V::AbstractMatrix{T}, Q::AbstractMatrix{T}, a::Vector, b::Vector, k::Int, l::Int, R::AbstractMatrix{T}) = new(U, V, Q, a, b, k, l, R) -end -GeneralizedSVD{T}(U::AbstractMatrix{T}, V::AbstractMatrix{T}, Q::AbstractMatrix{T}, a::Vector, b::Vector, k::Int, l::Int, R::AbstractMatrix{T}) = GeneralizedSVD{T,typeof(U)}(U, V, Q, a, b, k, l, R) - -function svdfact!{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) - U, V, Q, a, b, k, l, R = LAPACK.ggsvd!('U', 'V', 'Q', A, B) - GeneralizedSVD(U, V, Q, a, b, Int(k), Int(l), R) -end -svdfact{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) = svdfact!(copy(A),copy(B)) -function svdfact{TA,TB}(A::StridedMatrix{TA}, B::StridedMatrix{TB}) - S = promote_type(Float32, typeof(one(TA)/norm(one(TA))),TB) - return svdfact!(copy_oftype(A, S), copy_oftype(B, S)) -end - -function svd(A::AbstractMatrix, B::AbstractMatrix) - F = svdfact(A, B) - F[:U], F[:V], F[:Q], F[:D1], F[:D2], F[:R0] -end - -function getindex{T}(obj::GeneralizedSVD{T}, d::Symbol) - d == :U && return obj.U - d == :V && return obj.V - d == :Q && return obj.Q - (d == :alpha || d == :a) && return obj.a - (d == :beta || d == :b) && return obj.b - (d == :vals || d == :S) && return obj.a[1:obj.k + obj.l] ./ obj.b[1:obj.k + obj.l] - if d == :D1 - m = size(obj.U, 1) - if m - obj.k - obj.l >= 0 - return [eye(T, obj.k) zeros(T, obj.k, obj.l); zeros(T, obj.l, obj.k) diagm(obj.a[obj.k + 1:obj.k + obj.l]); zeros(T, m - obj.k - obj.l, obj.k + obj.l)] - else - return [eye(T, m, obj.k) [zeros(T, obj.k, m - obj.k); diagm(obj.a[obj.k + 1:m])] zeros(T, m, obj.k + obj.l - m)] - end - end - if d == :D2 - m = size(obj.U, 1) - p = size(obj.V, 1) - if m - obj.k - obj.l >= 0 - return [zeros(T, obj.l, obj.k) diagm(obj.b[obj.k + 1:obj.k + obj.l]); zeros(T, p - obj.l, obj.k + obj.l)] - else - return [zeros(T, p, obj.k) [diagm(obj.b[obj.k + 1:m]); zeros(T, obj.k + p - m, m - obj.k)] [zeros(T, m - obj.k, obj.k + obj.l - m); eye(T, obj.k + p - m, obj.k + obj.l - m)]] - end - end - d == :R && return obj.R - if d == :R0 - n = size(obj.Q, 1) - return [zeros(T, obj.k + obj.l, n - obj.k - obj.l) obj.R] - end - throw(KeyError(d)) -end - -function svdvals!{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) - _, _, _, a, b, k, l, _ = LAPACK.ggsvd!('N', 'N', 'N', A, B) - a[1:k + l] ./ b[1:k + l] -end -svdvals{T<:BlasFloat}(A::StridedMatrix{T},B::StridedMatrix{T}) = svdvals!(copy(A),copy(B)) -function svdvals{TA,TB}(A::StridedMatrix{TA}, B::StridedMatrix{TB}) - S = promote_type(Float32, typeof(one(TA)/norm(one(TA))), TB) - return svdvals!(copy_oftype(A, S), copy_oftype(B, S)) -end - -immutable Schur{Ty<:BlasFloat, S<:AbstractMatrix} <: Factorization{Ty} - T::S - Z::S - values::Vector - Schur(T::AbstractMatrix{Ty}, Z::AbstractMatrix{Ty}, values::Vector) = new(T, Z, values) -end -Schur{Ty}(T::AbstractMatrix{Ty}, Z::AbstractMatrix{Ty}, values::Vector) = Schur{Ty, typeof(T)}(T, Z, values) - -schurfact!{T<:BlasFloat}(A::StridedMatrix{T}) = Schur(LinAlg.LAPACK.gees!('V', A)...) -schurfact{T<:BlasFloat}(A::StridedMatrix{T}) = schurfact!(copy(A)) -function schurfact{T}(A::StridedMatrix{T}) - S = promote_type(Float32, typeof(one(T)/norm(one(T)))) - return schurfact!(copy_oftype(A, S)) -end - -function getindex(F::Schur, d::Symbol) - (d == :T || d == :Schur) && return F.T - (d == :Z || d == :vectors) && return F.Z - d == :values && return F.values - throw(KeyError(d)) -end - -function schur(A::StridedMatrix) - SchurF = schurfact(A) - SchurF[:T], SchurF[:Z], SchurF[:values] -end - -ordschur!{Ty<:BlasFloat}(Q::StridedMatrix{Ty}, T::StridedMatrix{Ty}, select::Union(Vector{Bool},BitVector)) = Schur(LinAlg.LAPACK.trsen!(convert(Vector{BlasInt}, select), T , Q)...) -ordschur{Ty<:BlasFloat}(Q::StridedMatrix{Ty}, T::StridedMatrix{Ty}, select::Union(Vector{Bool},BitVector)) = ordschur!(copy(Q), copy(T), select) -ordschur!{Ty<:BlasFloat}(schur::Schur{Ty}, select::Union(Vector{Bool},BitVector)) = (res=ordschur!(schur.Z, schur.T, select); schur[:values][:]=res[:values]; res) -ordschur{Ty<:BlasFloat}(schur::Schur{Ty}, select::Union(Vector{Bool},BitVector)) = ordschur(schur.Z, schur.T, select) - -immutable GeneralizedSchur{Ty<:BlasFloat, M<:AbstractMatrix} <: Factorization{Ty} - S::M - T::M - alpha::Vector - beta::Vector{Ty} - Q::M - Z::M - GeneralizedSchur(S::AbstractMatrix{Ty}, T::AbstractMatrix{Ty}, alpha::Vector, beta::Vector{Ty}, Q::AbstractMatrix{Ty}, Z::AbstractMatrix{Ty}) = new(S, T, alpha, beta, Q, Z) -end -GeneralizedSchur{Ty}(S::AbstractMatrix{Ty}, T::AbstractMatrix{Ty}, alpha::Vector, beta::Vector{Ty}, Q::AbstractMatrix{Ty}, Z::AbstractMatrix{Ty}) = GeneralizedSchur{Ty, typeof(S)}(S, T, alpha, beta, Q, Z) - -schurfact!{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) = GeneralizedSchur(LinAlg.LAPACK.gges!('V', 'V', A, B)...) -schurfact{T<:BlasFloat}(A::StridedMatrix{T},B::StridedMatrix{T}) = schurfact!(copy(A),copy(B)) -function schurfact{TA,TB}(A::StridedMatrix{TA}, B::StridedMatrix{TB}) - S = promote_type(Float32, typeof(one(TA)/norm(one(TA))), TB) - return schurfact!(copy_oftype(A, S), copy_oftype(B, S)) -end - -ordschur!{Ty<:BlasFloat}(S::StridedMatrix{Ty}, T::StridedMatrix{Ty}, Q::StridedMatrix{Ty}, Z::StridedMatrix{Ty}, select::Union(Vector{Bool},BitVector)) = GeneralizedSchur(LinAlg.LAPACK.tgsen!(convert(Vector{BlasInt}, select), S, T, Q, Z)...) -ordschur{Ty<:BlasFloat}(S::StridedMatrix{Ty}, T::StridedMatrix{Ty}, Q::StridedMatrix{Ty}, Z::StridedMatrix{Ty}, select::Union(Vector{Bool},BitVector)) = ordschur!(copy(S), copy(T), copy(Q), copy(Z), select) -ordschur!{Ty<:BlasFloat}(gschur::GeneralizedSchur{Ty}, select::Union(Vector{Bool},BitVector)) = (res=ordschur!(gschur.S, gschur.T, gschur.Q, gschur.Z, select); gschur[:alpha][:]=res[:alpha]; gschur[:beta][:]=res[:beta]; res) -ordschur{Ty<:BlasFloat}(gschur::GeneralizedSchur{Ty}, select::Union(Vector{Bool},BitVector)) = ordschur(gschur.S, gschur.T, gschur.Q, gschur.Z, select) - -function getindex(F::GeneralizedSchur, d::Symbol) - d == :S && return F.S - d == :T && return F.T - d == :alpha && return F.alpha - d == :beta && return F.beta - d == :values && return F.alpha./F.beta - (d == :Q || d == :left) && return F.Q - (d == :Z || d == :right) && return F.Z - throw(KeyError(d)) -end - -function schur(A::StridedMatrix, B::StridedMatrix) - SchurF = schurfact(A, B) - SchurF[:S], SchurF[:T], SchurF[:Q], SchurF[:Z] -end ### General promotion rules convert{T}(::Type{Factorization{T}}, F::Factorization{T}) = F @@ -842,17 +34,3 @@ function At_ldiv_B{TF<:Number,TB<:Number,N}(F::Factorization{TF}, B::AbstractArr TFB = typeof(one(TF)/one(TB)) At_ldiv_B!(convert(Factorization{TFB}, F), TB == TFB ? copy(B) : convert(AbstractArray{TFB,N}, B)) end - -## reconstruct the original matrix -full(F::QR) = F[:Q] * F[:R] -full(F::QRCompactWY) = F[:Q] * F[:R] -full(F::QRPivoted) = (F[:Q] * F[:R])[:,invperm(F[:p])] - -## Can we determine the source/result is Real? This is not stored in the type Eigen -full(F::Eigen) = F.vectors * Diagonal(F.values) / F.vectors - -full(F::Hessenberg) = (fq = full(F[:Q]); (fq * F[:H]) * fq') - -full(F::Schur) = (F.Z * F.T) * F.Z' - -full(F::SVD) = (F.U * Diagonal(F.S)) * F.Vt diff --git a/base/linalg/qr.jl b/base/linalg/qr.jl new file mode 100644 index 0000000000000..522e70f43bca7 --- /dev/null +++ b/base/linalg/qr.jl @@ -0,0 +1,465 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + +# QR and Hessenberg Factorizations + +immutable QR{T,S<:AbstractMatrix} <: Factorization{T} + factors::S + τ::Vector{T} + QR(factors::AbstractMatrix{T}, τ::Vector{T}) = new(factors, τ) +end +QR{T}(factors::AbstractMatrix{T}, τ::Vector{T}) = QR{T,typeof(factors)}(factors, τ) +# Note. For QRCompactWY factorization without pivoting, the WY representation based method introduced in LAPACK 3.4 +immutable QRCompactWY{S,M<:AbstractMatrix} <: Factorization{S} + factors::M + T::Matrix{S} + QRCompactWY(factors::AbstractMatrix{S}, T::AbstractMatrix{S}) = new(factors, T) +end +QRCompactWY{S}(factors::AbstractMatrix{S}, T::AbstractMatrix{S}) = QRCompactWY{S,typeof(factors)}(factors, T) + +immutable QRPivoted{T,S<:AbstractMatrix} <: Factorization{T} + factors::S + τ::Vector{T} + jpvt::Vector{BlasInt} + QRPivoted(factors::AbstractMatrix{T}, τ::Vector{T}, jpvt::Vector{BlasInt}) = new(factors, τ, jpvt) +end +QRPivoted{T}(factors::AbstractMatrix{T}, τ::Vector{T}, jpvt::Vector{BlasInt}) = QRPivoted{T,typeof(factors)}(factors, τ, jpvt) + +function qrfact!{T}(A::AbstractMatrix{T}, pivot::Union(Type{Val{false}}, Type{Val{true}})=Val{false}) + pivot==Val{true} && warn("pivoting only implemented for Float32, Float64, Complex64 and Complex128") + m, n = size(A) + τ = zeros(T, min(m,n)) + @inbounds begin + for k = 1:min(m-1+!(T<:Real),n) + τk = elementaryLeft!(A, k, k) + τ[k] = τk + for j = k+1:n + vAj = A[k,j] + for i = k+1:m + vAj += conj(A[i,k])*A[i,j] + end + vAj = conj(τk)*vAj + A[k,j] -= vAj + for i = k+1:m + A[i,j] -= A[i,k]*vAj + end + end + end + end + QR(A, τ) +end +qrfact!{T<:BlasFloat}(A::StridedMatrix{T}, pivot::Type{Val{false}} = Val{false}) = QRCompactWY(LAPACK.geqrt!(A, min(minimum(size(A)), 36))...) +qrfact!{T<:BlasFloat}(A::StridedMatrix{T}, pivot::Type{Val{true}}) = QRPivoted(LAPACK.geqp3!(A)...) +qrfact{T<:BlasFloat}(A::StridedMatrix{T}, pivot::Union(Type{Val{false}}, Type{Val{true}})=Val{false}) = qrfact!(copy(A), pivot) +copy_oftype{T}(A::StridedMatrix{T}, ::Type{T}) = copy(A) +copy_oftype{T,S}(A::StridedMatrix{T}, ::Type{S}) = convert(AbstractMatrix{S}, A) +qrfact{T}(A::StridedMatrix{T}, pivot::Union(Type{Val{false}}, Type{Val{true}})=Val{false}) = qrfact!(copy_oftype(A, typeof(one(T)/norm(one(T)))), pivot) +qrfact(x::Number) = qrfact(fill(x,1,1)) + +qr(A::Union(Number, AbstractMatrix), pivot::Union(Type{Val{false}}, Type{Val{true}})=Val{false}; thin::Bool=true) = + _qr(A, pivot, thin=thin) +function _qr(A::Union(Number, AbstractMatrix), ::Type{Val{false}}; thin::Bool=true) + F = qrfact(A, Val{false}) + full(getq(F), thin=thin), F[:R]::Matrix{eltype(F)} +end +function _qr(A::Union(Number, AbstractMatrix), ::Type{Val{true}}; thin::Bool=true) + F = qrfact(A, Val{true}) + full(getq(F), thin=thin), F[:R]::Matrix{eltype(F)}, F[:p]::Vector{BlasInt} +end + +convert{T}(::Type{QR{T}},A::QR) = QR(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ)) +convert{T}(::Type{Factorization{T}}, A::QR) = convert(QR{T}, A) +convert{T}(::Type{QRCompactWY{T}},A::QRCompactWY) = QRCompactWY(convert(AbstractMatrix{T}, A.factors), convert(AbstractMatrix{T}, A.T)) +convert{T}(::Type{Factorization{T}}, A::QRCompactWY) = convert(QRCompactWY{T}, A) +convert{T}(::Type{QRPivoted{T}},A::QRPivoted) = QRPivoted(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ), A.jpvt) +convert{T}(::Type{Factorization{T}}, A::QRPivoted) = convert(QRPivoted{T}, A) + +function getindex(A::QR, d::Symbol) + m, n = size(A) + d == :R && return triu!(A.factors[1:min(m,n), 1:n]) + d == :Q && return getq(A) + throw(KeyError(d)) +end +function getindex(A::QRCompactWY, d::Symbol) + m, n = size(A) + d == :R && return triu!(A.factors[1:min(m,n), 1:n]) + d == :Q && return getq(A) + throw(KeyError(d)) +end +function getindex{T}(A::QRPivoted{T}, d::Symbol) + m, n = size(A) + d == :R && return triu!(A.factors[1:min(m,n), 1:n]) + d == :Q && return getq(A) + d == :p && return A.jpvt + if d == :P + p = A[:p] + n = length(p) + P = zeros(T, n, n) + for i in 1:n + P[p[i],i] = one(T) + end + return P + end + throw(KeyError(d)) +end + +# Type-stable interface to get Q +getq(A::QRCompactWY) = QRCompactWYQ(A.factors,A.T) +getq(A::Union(QR, QRPivoted)) = QRPackedQ(A.factors,A.τ) + +immutable QRPackedQ{T,S<:AbstractMatrix} <: AbstractMatrix{T} + factors::S + τ::Vector{T} + QRPackedQ(factors::AbstractMatrix{T}, τ::Vector{T}) = new(factors, τ) +end +QRPackedQ{T}(factors::AbstractMatrix{T}, τ::Vector{T}) = QRPackedQ{T,typeof(factors)}(factors, τ) + +immutable QRPackedWYQ{S,M<:AbstractMatrix} <: AbstractMatrix{S} + factors::M + T::Matrix{S} + QRPackedWYQ(factors::AbstractMatrix{S}, T::Matrix{S}) = new(factors, T) +end +QRPackedWYQ{S}(factors::AbstractMatrix{S}, T::Matrix{S}) = QRPackedWYQ{S,typeof(factors)}(factors, T) + +immutable QRCompactWYQ{S, M<:AbstractMatrix} <: AbstractMatrix{S} + factors::M + T::Matrix{S} + QRCompactWYQ(factors::AbstractMatrix{S}, T::Matrix{S}) = new(factors, T) +end +QRCompactWYQ{S}(factors::AbstractMatrix{S}, T::Matrix{S}) = QRCompactWYQ{S,typeof(factors)}(factors, T) + +convert{T}(::Type{QRPackedQ{T}}, Q::QRPackedQ) = QRPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(Vector{T}, Q.τ)) +convert{T}(::Type{AbstractMatrix{T}}, Q::QRPackedQ) = convert(QRPackedQ{T}, Q) +convert{S}(::Type{QRCompactWYQ{S}}, Q::QRCompactWYQ) = QRCompactWYQ(convert(AbstractMatrix{S}, Q.factors), convert(AbstractMatrix{S}, Q.T)) +convert{S}(::Type{AbstractMatrix{S}}, Q::QRCompactWYQ) = convert(QRCompactWYQ{S}, Q) + +size(A::Union(QR,QRCompactWY,QRPivoted), dim::Integer) = size(A.factors, dim) +size(A::Union(QR,QRCompactWY,QRPivoted)) = size(A.factors) +size(A::Union(QRPackedQ,QRCompactWYQ), dim::Integer) = 0 < dim ? (dim <= 2 ? size(A.factors, 1) : 1) : throw(BoundsError()) +size(A::Union(QRPackedQ,QRCompactWYQ)) = size(A, 1), size(A, 2) + +full{T}(A::Union(QRPackedQ{T},QRCompactWYQ{T}); thin::Bool=true) = A_mul_B!(A, thin ? eye(T, size(A.factors,1), minimum(size(A.factors))) : eye(T, size(A.factors,1))) + +## Multiplication by Q +### QB +A_mul_B!{T<:BlasFloat}(A::QRCompactWYQ{T}, B::StridedVecOrMat{T}) = LAPACK.gemqrt!('L','N',A.factors,A.T,B) +A_mul_B!{T<:BlasFloat}(A::QRPackedQ{T}, B::StridedVecOrMat{T}) = LAPACK.ormqr!('L','N',A.factors,A.τ,B) +function A_mul_B!{T}(A::QRPackedQ{T}, B::AbstractVecOrMat{T}) + mA, nA = size(A.factors) + mB, nB = size(B,1), size(B,2) + mA == mB || throw(DimensionMismatch()) + Afactors = A.factors + @inbounds begin + for k = min(mA,nA):-1:1 + for j = 1:nB + vBj = B[k,j] + for i = k+1:mB + vBj += conj(Afactors[i,k])*B[i,j] + end + vBj = A.τ[k]*vBj + B[k,j] -= vBj + for i = k+1:mB + B[i,j] -= Afactors[i,k]*vBj + end + end + end + end + B +end + +function (*){TA,Tb}(A::Union(QRPackedQ{TA},QRCompactWYQ{TA}), b::StridedVector{Tb}) + TAb = promote_type(TA, Tb) + Anew = convert(AbstractMatrix{TAb}, A) + if size(A.factors, 1) == length(b) + bnew = copy_oftype(b, TAb) + elseif size(A.factors, 2) == length(b) + bnew = [b; zeros(TAb, size(A.factors, 1) - length(b))] + else + throw(DimensionMismatch("vector must have length either $(size(A.factors, 1)) or $(size(A.factors, 2))")) + end + A_mul_B!(Anew, bnew) +end +function (*){TA,TB}(A::Union(QRPackedQ{TA},QRCompactWYQ{TA}), B::StridedMatrix{TB}) + TAB = promote_type(TA, TB) + Anew = convert(AbstractMatrix{TAB}, A) + if size(A.factors, 1) == size(B, 1) + Bnew = copy_oftype(B, TAB) + elseif size(A.factors, 2) == size(B, 1) + Bnew = [B; zeros(TAB, size(A.factors, 1) - size(B,1), size(B, 2))] + else + throw(DimensionMismatch("first dimension of matrix must have size either $(size(A.factors, 1)) or $(size(A.factors, 2))")) + end + A_mul_B!(Anew, Bnew) +end + +### QcB +Ac_mul_B!{T<:BlasReal}(A::QRCompactWYQ{T}, B::StridedVecOrMat{T}) = LAPACK.gemqrt!('L','T',A.factors,A.T,B) +Ac_mul_B!{T<:BlasComplex}(A::QRCompactWYQ{T}, B::StridedVecOrMat{T}) = LAPACK.gemqrt!('L','C',A.factors,A.T,B) +Ac_mul_B!{T<:BlasReal}(A::QRPackedQ{T}, B::StridedVecOrMat{T}) = LAPACK.ormqr!('L','T',A.factors,A.τ,B) +Ac_mul_B!{T<:BlasComplex}(A::QRPackedQ{T}, B::StridedVecOrMat{T}) = LAPACK.ormqr!('L','C',A.factors,A.τ,B) +function Ac_mul_B!{T}(A::QRPackedQ{T}, B::AbstractVecOrMat{T}) + mA, nA = size(A.factors) + mB, nB = size(B,1), size(B,2) + mA == mB || throw(DimensionMismatch()) + Afactors = A.factors + @inbounds begin + for k = 1:min(mA,nA) + for j = 1:nB + vBj = B[k,j] + for i = k+1:mB + vBj += conj(Afactors[i,k])*B[i,j] + end + vBj = conj(A.τ[k])*vBj + B[k,j] -= vBj + for i = k+1:mB + B[i,j] -= Afactors[i,k]*vBj + end + end + end + end + B +end +function Ac_mul_B{TQ<:Number,TB<:Number,N}(Q::Union(QRPackedQ{TQ},QRCompactWYQ{TQ}), B::StridedArray{TB,N}) + TQB = promote_type(TQ,TB) + return Ac_mul_B!(convert(AbstractMatrix{TQB}, Q), copy_oftype(B, TQB)) +end + +### AQ +A_mul_B!{T<:BlasFloat}(A::StridedVecOrMat{T}, B::QRCompactWYQ{T}) = LAPACK.gemqrt!('R','N', B.factors, B.T, A) +A_mul_B!(A::StridedVecOrMat, B::QRPackedQ) = LAPACK.ormqr!('R', 'N', B.factors, B.τ, A) +function A_mul_B!{T}(A::StridedMatrix{T},Q::QRPackedQ{T}) + mQ, nQ = size(Q.factors) + mA, nA = size(A,1), size(A,2) + nA == mQ || throw(DimensionMismatch()) + Qfactors = Q.factors + @inbounds begin + for k = 1:min(mQ,nQ) + for i = 1:mA + vAi = A[i,k] + for j = k+1:mQ + vAi += A[i,j]*Qfactors[j,k] + end + vAi = vAi*Q.τ[k] + A[i,k] -= vAi + for j = k+1:nA + A[i,j] -= vAi*conj(Qfactors[j,k]) + end + end + end + end + A +end + +function (*){TA,TQ,N}(A::StridedArray{TA,N}, Q::Union(QRPackedQ{TQ},QRCompactWYQ{TQ})) + TAQ = promote_type(TA, TQ) + return A_mul_B!(copy_oftype(A, TAQ), convert(AbstractMatrix{TAQ}, Q)) +end + +### AQc +A_mul_Bc!{T<:BlasReal}(A::StridedVecOrMat{T}, B::QRCompactWYQ{T}) = LAPACK.gemqrt!('R','T',B.factors,B.T,A) +A_mul_Bc!{T<:BlasComplex}(A::StridedVecOrMat{T}, B::QRCompactWYQ{T}) = LAPACK.gemqrt!('R','C',B.factors,B.T,A) +A_mul_Bc!{T<:BlasReal}(A::StridedVecOrMat{T}, B::QRPackedQ{T}) = LAPACK.ormqr!('R','T',B.factors,B.τ,A) +A_mul_Bc!{T<:BlasComplex}(A::StridedVecOrMat{T}, B::QRPackedQ{T}) = LAPACK.ormqr!('R','C',B.factors,B.τ,A) +function A_mul_Bc!{T}(A::AbstractMatrix{T},Q::QRPackedQ{T}) + mQ, nQ = size(Q.factors) + mA, nA = size(A,1), size(A,2) + nA == mQ || throw(DimensionMismatch()) + Qfactors = Q.factors + @inbounds begin + for k = min(mQ,nQ):-1:1 + for i = 1:mA + vAi = A[i,k] + for j = k+1:mQ + vAi += A[i,j]*Qfactors[j,k] + end + vAi = vAi*conj(Q.τ[k]) + A[i,k] -= vAi + for j = k+1:nA + A[i,j] -= vAi*conj(Qfactors[j,k]) + end + end + end + end + A +end +A_mul_Bc(A::AbstractTriangular, B::Union(QRCompactWYQ,QRPackedQ)) = A_mul_Bc(full(A), B) +function A_mul_Bc{TA,TB}(A::AbstractArray{TA}, B::Union(QRCompactWYQ{TB},QRPackedQ{TB})) + TAB = promote_type(TA,TB) + BB = convert(AbstractMatrix{TAB}, B) + if size(A,2) == size(B.factors, 1) + return A_mul_Bc!(copy_oftype(A, TAB), BB) + elseif size(A,2) == size(B.factors,2) + return A_mul_Bc!([A zeros(TAB, size(A, 1), size(B.factors, 1) - size(B.factors, 2))], BB) + else + throw(DimensionMismatch()) + end +end + +A_ldiv_B!{T<:BlasFloat}(A::QRCompactWY{T}, b::StridedVector{T}) = (A_ldiv_B!(UpperTriangular(A[:R]), sub(Ac_mul_B!(A[:Q], b), 1:size(A, 2))); b) +A_ldiv_B!{T<:BlasFloat}(A::QRCompactWY{T}, B::StridedMatrix{T}) = (A_ldiv_B!(UpperTriangular(A[:R]), sub(Ac_mul_B!(A[:Q], B), 1:size(A, 2), 1:size(B, 2))); B) + +# Julia implementation similarly to xgelsy +function A_ldiv_B!{T<:BlasFloat}(A::QRPivoted{T}, B::StridedMatrix{T}, rcond::Real) + mA, nA = size(A.factors) + nr = min(mA,nA) + nrhs = size(B, 2) + if nr == 0 return zeros(T, 0, nrhs), 0 end + ar = abs(A.factors[1]) + if ar == 0 return zeros(T, nr, nrhs), 0 end + rnk = 1 + xmin = ones(T, 1) + xmax = ones(T, 1) + tmin = tmax = ar + while rnk < nr + tmin, smin, cmin = LAPACK.laic1!(2, xmin, tmin, sub(A.factors, 1:rnk, rnk + 1), A.factors[rnk + 1, rnk + 1]) + tmax, smax, cmax = LAPACK.laic1!(1, xmax, tmax, sub(A.factors, 1:rnk, rnk + 1), A.factors[rnk + 1, rnk + 1]) + tmax*rcond > tmin && break + push!(xmin, cmin) + push!(xmax, cmax) + for i = 1:rnk + xmin[i] *= smin + xmax[i] *= smax + end + rnk += 1 + end + C, τ = LAPACK.tzrzf!(A.factors[1:rnk,:]) + A_ldiv_B!(UpperTriangular(C[1:rnk,1:rnk]),sub(Ac_mul_B!(getq(A),sub(B, 1:mA, 1:nrhs)),1:rnk,1:nrhs)) + B[rnk+1:end,:] = zero(T) + LAPACK.ormrz!('L', iseltype(B, Complex) ? 'C' : 'T', C, τ, sub(B,1:nA,1:nrhs)) + B[1:nA,:] = sub(B, 1:nA, :)[invperm(A[:p]::Vector{BlasInt}),:] + return B, rnk +end +A_ldiv_B!{T<:BlasFloat}(A::QRPivoted{T}, B::StridedVector{T}) = vec(A_ldiv_B!(A,reshape(B,length(B),1))) +A_ldiv_B!{T<:BlasFloat}(A::QRPivoted{T}, B::StridedVecOrMat{T}) = A_ldiv_B!(A, B, maximum(size(A))*eps(real(float(one(eltype(B))))))[1] +function A_ldiv_B!{T}(A::QR{T},B::StridedMatrix{T}) + m, n = size(A) + minmn = min(m,n) + mB, nB = size(B) + Ac_mul_B!(A[:Q],sub(B,1:m,1:nB)) # Reconsider when arrayviews are merged. + R = A[:R] + @inbounds begin + if n > m # minimum norm solution + τ = zeros(T,m) + for k = m:-1:1 # Trapezoid to triangular by elementary operation + τ[k] = elementaryRightTrapezoid!(R,k) + for i = 1:k-1 + vRi = R[i,k] + for j = m+1:n + vRi += R[i,j]*R[k,j] + end + vRi *= τ[k] + R[i,k] -= vRi + for j = m+1:n + R[i,j] -= vRi*R[k,j] + end + end + end + end + for k = 1:nB # solve triangular system. When array views are implemented, consider exporting to function. + for i = minmn:-1:1 + for j = i+1:minmn + B[i,k] -= R[i,j]*B[j,k] + end + B[i,k] /= R[i,i] + end + end + if n > m # Apply elementary transformation to solution + B[m+1:mB,1:nB] = zero(T) + for j = 1:nB + for k = 1:m + vBj = B[k,j] + for i = m+1:n + vBj += B[i,j]*conj(R[k,i]) + end + vBj *= τ[k] + B[k,j] -= vBj + for i = m+1:n + B[i,j] -= R[k,i]*vBj + end + end + end + end + end + return B +end +A_ldiv_B!(A::QR, B::StridedVector) = A_ldiv_B!(A, reshape(B, length(B), 1))[:] +function A_ldiv_B!(A::QRPivoted, b::StridedVector) + A_ldiv_B!(QR(A.factors,A.τ), b) + b[1:size(A.factors, 2)] = sub(b, 1:size(A.factors, 2))[invperm(A.jpvt)] + b +end +function A_ldiv_B!(A::QRPivoted, B::StridedMatrix) + A_ldiv_B!(QR(A.factors, A.τ), B) + B[1:size(A.factors, 2),:] = sub(B, 1:size(A.factors, 2), :)[invperm(A.jpvt)] + B +end +function \{TA,Tb}(A::Union(QR{TA},QRCompactWY{TA},QRPivoted{TA}), b::StridedVector{Tb}) + S = promote_type(TA,Tb) + m,n = size(A) + m == length(b) || throw(DimensionMismatch("left hand side has $m rows, but right hand side has length $(length(b))")) + AA = convert(Factorization{S}, A) + if n > m + x = A_ldiv_B!(AA, [b; zeros(S, n - m)]) + else + x = A_ldiv_B!(AA, copy_oftype(b, S)) + end + return length(x) > n ? x[1:n] : x +end +function \{TA,TB}(A::Union(QR{TA},QRCompactWY{TA},QRPivoted{TA}),B::StridedMatrix{TB}) + S = promote_type(TA,TB) + m,n = size(A) + m == size(B,1) || throw(DimensionMismatch("left hand side has $m rows, but right hand side has $(size(B,1)) rows")) + AA = convert(Factorization{S}, A) + if n > m + X = A_ldiv_B!(AA, [B; zeros(S, n - m, size(B, 2))]) + else + X = A_ldiv_B!(AA, copy_oftype(B, S)) + end + return size(X, 1) > n ? X[1:n,:] : X +end + +##TODO: Add methods for rank(A::QRP{T}) and adjust the (\) method accordingly +## Add rcond methods for Cholesky, LU, QR and QRP types +## Lower priority: Add LQ, QL and RQ factorizations + +# FIXME! Should add balancing option through xgebal +immutable Hessenberg{T,S<:AbstractMatrix} <: Factorization{T} + factors::S + τ::Vector{T} + Hessenberg(factors::AbstractMatrix{T}, τ::Vector{T}) = new(factors, τ) +end +Hessenberg{T}(factors::AbstractMatrix{T}, τ::Vector{T}) = Hessenberg{T,typeof(factors)}(factors, τ) + +Hessenberg(A::StridedMatrix) = Hessenberg(LAPACK.gehrd!(A)...) + +hessfact!{T<:BlasFloat}(A::StridedMatrix{T}) = Hessenberg(A) +hessfact{T<:BlasFloat}(A::StridedMatrix{T}) = hessfact!(copy(A)) +function hessfact{T}(A::StridedMatrix{T}) + S = promote_type(Float32, typeof(one(T)/norm(one(T)))) + return hessfact!(copy_oftype(A, S)) +end + +immutable HessenbergQ{T,S<:AbstractMatrix} <: AbstractMatrix{T} + factors::S + τ::Vector{T} + HessenbergQ(factors::AbstractMatrix{T}, τ::Vector{T}) = new(factors, τ) +end +HessenbergQ{T}(factors::AbstractMatrix{T}, τ::Vector{T}) = HessenbergQ{T,typeof(factors)}(factors, τ) +HessenbergQ(A::Hessenberg) = HessenbergQ(A.factors, A.τ) +size(A::HessenbergQ, args...) = size(A.factors, args...) + +function getindex(A::Hessenberg, d::Symbol) + d == :Q && return HessenbergQ(A) + d == :H && return triu(A.factors, -1) + throw(KeyError(d)) +end + +# Also printing of QRQs +getindex(A::Union(QRPackedQ,QRCompactWYQ,HessenbergQ), i::Integer, j::Integer) = (x = zeros(eltype(A), size(A, 1)); x[i] = 1; y = zeros(eltype(A), size(A, 2)); y[j] = 1; dot(x, A*y)) + +## reconstruct the original matrix +full(F::QR) = F[:Q] * F[:R] +full(F::QRCompactWY) = F[:Q] * F[:R] +full(F::QRPivoted) = (F[:Q] * F[:R])[:,invperm(F[:p])] + +full(A::HessenbergQ) = LAPACK.orghr!(1, size(A.factors, 1), copy(A.factors), A.τ) +full(F::Hessenberg) = (fq = full(F[:Q]); (fq * F[:H]) * fq') diff --git a/base/linalg/schur.jl b/base/linalg/schur.jl new file mode 100644 index 0000000000000..c169965a45584 --- /dev/null +++ b/base/linalg/schur.jl @@ -0,0 +1,75 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + +# Schur decomposition +immutable Schur{Ty<:BlasFloat, S<:AbstractMatrix} <: Factorization{Ty} + T::S + Z::S + values::Vector + Schur(T::AbstractMatrix{Ty}, Z::AbstractMatrix{Ty}, values::Vector) = new(T, Z, values) +end +Schur{Ty}(T::AbstractMatrix{Ty}, Z::AbstractMatrix{Ty}, values::Vector) = Schur{Ty, typeof(T)}(T, Z, values) + +schurfact!{T<:BlasFloat}(A::StridedMatrix{T}) = Schur(LinAlg.LAPACK.gees!('V', A)...) +schurfact{T<:BlasFloat}(A::StridedMatrix{T}) = schurfact!(copy(A)) +function schurfact{T}(A::StridedMatrix{T}) + S = promote_type(Float32, typeof(one(T)/norm(one(T)))) + return schurfact!(copy_oftype(A, S)) +end + +function getindex(F::Schur, d::Symbol) + (d == :T || d == :Schur) && return F.T + (d == :Z || d == :vectors) && return F.Z + d == :values && return F.values + throw(KeyError(d)) +end + +function schur(A::StridedMatrix) + SchurF = schurfact(A) + SchurF[:T], SchurF[:Z], SchurF[:values] +end + +ordschur!{Ty<:BlasFloat}(Q::StridedMatrix{Ty}, T::StridedMatrix{Ty}, select::Union(Vector{Bool},BitVector)) = Schur(LinAlg.LAPACK.trsen!(convert(Vector{BlasInt}, select), T , Q)...) +ordschur{Ty<:BlasFloat}(Q::StridedMatrix{Ty}, T::StridedMatrix{Ty}, select::Union(Vector{Bool},BitVector)) = ordschur!(copy(Q), copy(T), select) +ordschur!{Ty<:BlasFloat}(schur::Schur{Ty}, select::Union(Vector{Bool},BitVector)) = (res=ordschur!(schur.Z, schur.T, select); schur[:values][:]=res[:values]; res) +ordschur{Ty<:BlasFloat}(schur::Schur{Ty}, select::Union(Vector{Bool},BitVector)) = ordschur(schur.Z, schur.T, select) + +immutable GeneralizedSchur{Ty<:BlasFloat, M<:AbstractMatrix} <: Factorization{Ty} + S::M + T::M + alpha::Vector + beta::Vector{Ty} + Q::M + Z::M + GeneralizedSchur(S::AbstractMatrix{Ty}, T::AbstractMatrix{Ty}, alpha::Vector, beta::Vector{Ty}, Q::AbstractMatrix{Ty}, Z::AbstractMatrix{Ty}) = new(S, T, alpha, beta, Q, Z) +end +GeneralizedSchur{Ty}(S::AbstractMatrix{Ty}, T::AbstractMatrix{Ty}, alpha::Vector, beta::Vector{Ty}, Q::AbstractMatrix{Ty}, Z::AbstractMatrix{Ty}) = GeneralizedSchur{Ty, typeof(S)}(S, T, alpha, beta, Q, Z) + +schurfact!{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) = GeneralizedSchur(LinAlg.LAPACK.gges!('V', 'V', A, B)...) +schurfact{T<:BlasFloat}(A::StridedMatrix{T},B::StridedMatrix{T}) = schurfact!(copy(A),copy(B)) +function schurfact{TA,TB}(A::StridedMatrix{TA}, B::StridedMatrix{TB}) + S = promote_type(Float32, typeof(one(TA)/norm(one(TA))), TB) + return schurfact!(copy_oftype(A, S), copy_oftype(B, S)) +end + +ordschur!{Ty<:BlasFloat}(S::StridedMatrix{Ty}, T::StridedMatrix{Ty}, Q::StridedMatrix{Ty}, Z::StridedMatrix{Ty}, select::Union(Vector{Bool},BitVector)) = GeneralizedSchur(LinAlg.LAPACK.tgsen!(convert(Vector{BlasInt}, select), S, T, Q, Z)...) +ordschur{Ty<:BlasFloat}(S::StridedMatrix{Ty}, T::StridedMatrix{Ty}, Q::StridedMatrix{Ty}, Z::StridedMatrix{Ty}, select::Union(Vector{Bool},BitVector)) = ordschur!(copy(S), copy(T), copy(Q), copy(Z), select) +ordschur!{Ty<:BlasFloat}(gschur::GeneralizedSchur{Ty}, select::Union(Vector{Bool},BitVector)) = (res=ordschur!(gschur.S, gschur.T, gschur.Q, gschur.Z, select); gschur[:alpha][:]=res[:alpha]; gschur[:beta][:]=res[:beta]; res) +ordschur{Ty<:BlasFloat}(gschur::GeneralizedSchur{Ty}, select::Union(Vector{Bool},BitVector)) = ordschur(gschur.S, gschur.T, gschur.Q, gschur.Z, select) + +function getindex(F::GeneralizedSchur, d::Symbol) + d == :S && return F.S + d == :T && return F.T + d == :alpha && return F.alpha + d == :beta && return F.beta + d == :values && return F.alpha./F.beta + (d == :Q || d == :left) && return F.Q + (d == :Z || d == :right) && return F.Z + throw(KeyError(d)) +end + +function schur(A::StridedMatrix, B::StridedMatrix) + SchurF = schurfact(A, B) + SchurF[:S], SchurF[:T], SchurF[:Q], SchurF[:Z] +end + +full(F::Schur) = (F.Z * F.T) * F.Z' diff --git a/base/linalg/svd.jl b/base/linalg/svd.jl new file mode 100644 index 0000000000000..097b171c6b197 --- /dev/null +++ b/base/linalg/svd.jl @@ -0,0 +1,129 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + +# Singular Value Decomposition +immutable SVD{T<:BlasFloat,Tr,M<:AbstractArray} <: Factorization{T} + U::M + S::Vector{Tr} + Vt::M + SVD(U::AbstractArray{T}, S::Vector{Tr}, Vt::AbstractArray{T}) = new(U, S, Vt) +end +SVD{T<:BlasFloat,Tr}(U::AbstractArray{T}, S::Vector{Tr}, Vt::AbstractArray{T}) = SVD{T,Tr,typeof(U)}(U, S, Vt) + +function svdfact!{T<:BlasFloat}(A::StridedMatrix{T}; thin::Bool=true) + m,n = size(A) + if m == 0 || n == 0 + u,s,vt = (eye(T, m, thin ? n : m), real(zeros(T,0)), eye(T,n,n)) + else + u,s,vt = LAPACK.gesdd!(thin ? 'S' : 'A', A) + end + SVD(u,s,vt) +end +function svdfact{T}(A::StridedVecOrMat{T};thin = true) + S = promote_type(Float32, typeof(one(T)/norm(one(T)))) + svdfact!(copy_oftype(A, S), thin = thin) +end +svdfact(x::Number; thin::Bool=true) = SVD(x == 0 ? fill(one(x), 1, 1) : fill(x/abs(x), 1, 1), [abs(x)], fill(one(x), 1, 1)) +svdfact(x::Integer; thin::Bool=true) = svdfact(float(x), thin=thin) + +function svd(A::Union(Number, AbstractArray); thin::Bool=true) + F = svdfact(A, thin=thin) + F.U, F.S, F.Vt' +end + +function getindex(F::SVD, d::Symbol) + d == :U && return F.U + d == :S && return F.S + d == :Vt && return F.Vt + d == :V && return F.Vt' + throw(KeyError(d)) +end + +svdvals!{T<:BlasFloat}(A::StridedMatrix{T}) = any([size(A)...].==0) ? zeros(T, 0) : LAPACK.gesdd!('N', A)[2] +svdvals{T<:BlasFloat}(A::AbstractMatrix{T}) = svdvals!(copy(A)) +function svdvals{T}(A::AbstractMatrix{T}) + S = promote_type(Float32, typeof(one(T)/norm(one(T)))) + svdvals!(copy_oftype(A, S)) +end +svdvals(x::Number) = [abs(x)] + +# SVD least squares +function \{T<:BlasFloat}(A::SVD{T}, B::StridedVecOrMat{T}) + n = length(A.S) + Sinv = zeros(T, n) + k = length(find(A.S .> eps(real(float(one(T))))*maximum(A.S))) + Sinv[1:k] = one(T) ./ A.S[1:k] + A.Vt[1:k,:]' * (Sinv[1:k] .* (A.U[:,1:k]' * B)) +end + +# Generalized svd +immutable GeneralizedSVD{T,S} <: Factorization{T} + U::S + V::S + Q::S + a::Vector + b::Vector + k::Int + l::Int + R::S + GeneralizedSVD(U::AbstractMatrix{T}, V::AbstractMatrix{T}, Q::AbstractMatrix{T}, a::Vector, b::Vector, k::Int, l::Int, R::AbstractMatrix{T}) = new(U, V, Q, a, b, k, l, R) +end +GeneralizedSVD{T}(U::AbstractMatrix{T}, V::AbstractMatrix{T}, Q::AbstractMatrix{T}, a::Vector, b::Vector, k::Int, l::Int, R::AbstractMatrix{T}) = GeneralizedSVD{T,typeof(U)}(U, V, Q, a, b, k, l, R) + +function svdfact!{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) + U, V, Q, a, b, k, l, R = LAPACK.ggsvd!('U', 'V', 'Q', A, B) + GeneralizedSVD(U, V, Q, a, b, Int(k), Int(l), R) +end +svdfact{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) = svdfact!(copy(A),copy(B)) +function svdfact{TA,TB}(A::StridedMatrix{TA}, B::StridedMatrix{TB}) + S = promote_type(Float32, typeof(one(TA)/norm(one(TA))),TB) + return svdfact!(copy_oftype(A, S), copy_oftype(B, S)) +end + +function svd(A::AbstractMatrix, B::AbstractMatrix) + F = svdfact(A, B) + F[:U], F[:V], F[:Q], F[:D1], F[:D2], F[:R0] +end + +function getindex{T}(obj::GeneralizedSVD{T}, d::Symbol) + d == :U && return obj.U + d == :V && return obj.V + d == :Q && return obj.Q + (d == :alpha || d == :a) && return obj.a + (d == :beta || d == :b) && return obj.b + (d == :vals || d == :S) && return obj.a[1:obj.k + obj.l] ./ obj.b[1:obj.k + obj.l] + if d == :D1 + m = size(obj.U, 1) + if m - obj.k - obj.l >= 0 + return [eye(T, obj.k) zeros(T, obj.k, obj.l); zeros(T, obj.l, obj.k) diagm(obj.a[obj.k + 1:obj.k + obj.l]); zeros(T, m - obj.k - obj.l, obj.k + obj.l)] + else + return [eye(T, m, obj.k) [zeros(T, obj.k, m - obj.k); diagm(obj.a[obj.k + 1:m])] zeros(T, m, obj.k + obj.l - m)] + end + end + if d == :D2 + m = size(obj.U, 1) + p = size(obj.V, 1) + if m - obj.k - obj.l >= 0 + return [zeros(T, obj.l, obj.k) diagm(obj.b[obj.k + 1:obj.k + obj.l]); zeros(T, p - obj.l, obj.k + obj.l)] + else + return [zeros(T, p, obj.k) [diagm(obj.b[obj.k + 1:m]); zeros(T, obj.k + p - m, m - obj.k)] [zeros(T, m - obj.k, obj.k + obj.l - m); eye(T, obj.k + p - m, obj.k + obj.l - m)]] + end + end + d == :R && return obj.R + if d == :R0 + n = size(obj.Q, 1) + return [zeros(T, obj.k + obj.l, n - obj.k - obj.l) obj.R] + end + throw(KeyError(d)) +end + +function svdvals!{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) + _, _, _, a, b, k, l, _ = LAPACK.ggsvd!('N', 'N', 'N', A, B) + a[1:k + l] ./ b[1:k + l] +end +svdvals{T<:BlasFloat}(A::StridedMatrix{T},B::StridedMatrix{T}) = svdvals!(copy(A),copy(B)) +function svdvals{TA,TB}(A::StridedMatrix{TA}, B::StridedMatrix{TB}) + S = promote_type(Float32, typeof(one(TA)/norm(one(TA))), TB) + return svdvals!(copy_oftype(A, S), copy_oftype(B, S)) +end + +full(F::SVD) = (F.U * Diagonal(F.S)) * F.Vt From 49a3f3a2675b275750e160fc8fa30b21241f8f8e Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 18 May 2015 12:48:44 -0400 Subject: [PATCH 010/181] throw OverflowError instead of SegFault/Do sth random later when the field offset/size overflow. Improve #11320 --- src/alloc.c | 4 ++++ src/julia.h | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/alloc.c b/src/alloc.c index 8c0fd24bf4778..913982d236e74 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -534,6 +534,8 @@ void jl_compute_field_offsets(jl_datatype_t *st) size_t fsz, al; if (jl_isbits(ty) && jl_is_leaf_type(ty)) { fsz = jl_datatype_size(ty); + if (__unlikely(fsz > JL_FIELD_MAX_SIZE)) + jl_throw(jl_overflow_exception); al = ((jl_datatype_t*)ty)->alignment; st->fields[i].isptr = 0; } @@ -550,6 +552,8 @@ void jl_compute_field_offsets(jl_datatype_t *st) if (al > alignm) alignm = al; } + if (__unlikely(sz > JL_FIELD_MAX_OFFSET)) + jl_throw(jl_overflow_exception); st->fields[i].offset = sz; st->fields[i].size = fsz; sz += fsz; diff --git a/src/julia.h b/src/julia.h index d55528f51b6bd..220094791f51a 100644 --- a/src/julia.h +++ b/src/julia.h @@ -265,6 +265,9 @@ typedef struct { uint16_t isptr:1; } jl_fielddesc_t; +#define JL_FIELD_MAX_OFFSET ((1ul << 16) - 1ul) +#define JL_FIELD_MAX_SIZE ((1ul << 15) - 1ul) + typedef struct _jl_datatype_t { JL_DATA_TYPE jl_typename_t *name; From d4d70961fa72fb90392f952de027679d5f1352a3 Mon Sep 17 00:00:00 2001 From: pabloferz Date: Mon, 18 May 2015 15:01:25 -0500 Subject: [PATCH 011/181] Printing of BigFloats (fixes #11276) Removes the precision info when printing a `BigFloat`, this leads to cleaner printed `Complex{BigFloat}`s. So before we had ```julia julia> big"1.2" + big"2.1" * im 1.200000000000000000000000000000000000000000000000000000000000000000000000000007e+00 with 256 bits of precision + 2.099999999999999999999999999999999999999999999999999999999999999999999999999986e+00 with 256 bits of precisionim ``` while after this change it would be ```julia julia> big"1.2" + big"2.1" * im 1.200000000000000000000000000000000000000000000000000000000000000000000000000007e+00 + 2.099999999999999999999999999999999999999999999999999999999999999999999999999986e+00im ``` This also removes one extra allocation that was present when returning the `bytestring`. Fixes #11276 --- base/mpfr.jl | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/base/mpfr.jl b/base/mpfr.jl index d585a9d8010c1..22eb843990aeb 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -765,18 +765,21 @@ function with_bigfloat_precision(f::Function, precision::Integer) end function string(x::BigFloat) - lng = 128 - for i = 1:2 - z = Array(UInt8, lng + 1) - lng = ccall((:mpfr_snprintf,:libmpfr), Int32, (Ptr{UInt8}, Culong, Ptr{UInt8}, Ptr{BigFloat}...), z, lng + 1, "%.Re", &x) - if lng < 128 || i == 2 - return bytestring(z[1:lng]) - end + lng::Int32 = 127 + buf = Array(UInt8, lng + 1) + lng = ccall((:mpfr_snprintf,:libmpfr), Int32, (Ptr{UInt8}, Culong, Ptr{UInt8}, Ptr{BigFloat}...), buf, lng + 1, "%.Re", &x) + (84 <= lng <= 127) && return bytestring(pointer(buf), lng) + if lng < 84 # print at least 78 decimal places + lng = ccall((:mpfr_sprintf,:libmpfr), Int32, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BigFloat}...), buf, "%.78Re", &x) + elseif lng > 127 + buf = Array(UInt8, lng + 1) + lng = ccall((:mpfr_snprintf,:libmpfr), Int32, (Ptr{UInt8}, Culong, Ptr{UInt8}, Ptr{BigFloat}...), buf, lng + 1, "%.Re", &x) end + return bytestring(pointer(buf), lng) end print(io::IO, b::BigFloat) = print(io, string(b)) -show(io::IO, b::BigFloat) = print(io, string(b), " with $(precision(b)) bits of precision") +show(io::IO, b::BigFloat) = print(io, string(b)) showcompact(io::IO, b::BigFloat) = print(io, string(b)) # get/set exponent min/max From 5cdf380fa4b6f5eff82e60b23240b00a2774771e Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 18 May 2015 20:52:46 -0400 Subject: [PATCH 012/181] switch to a more general-purpose mechanism for doing post-processing work after deserializing the system image starting with 7ec501d6, object_id required more than just object identity for types to compute their hash. the deserializer may not be in a sufficiently consistent state to allow doing this in-situ, so this switches to a more general mechanism for maintaining a list of reinit functions --- src/dump.c | 129 ++++++++++++++++++++++--------------------- src/julia_internal.h | 1 + 2 files changed, 66 insertions(+), 64 deletions(-) diff --git a/src/dump.c b/src/dump.c index e9f7d13da227d..f3fb9c9cc5d46 100644 --- a/src/dump.c +++ b/src/dump.c @@ -42,11 +42,15 @@ static htable_t backref_table; int backref_table_numel; static arraylist_t backref_list; -// list of (jl_value_t *value, jl_value_t **loc, size_t pos) entries -// for anything that was flagged by the serializer for later rework of -// some sort +// list of (jl_value_t **loc, size_t pos) entries +// for anything that was flagged by the serializer for later +// type-rewriting of some sort static arraylist_t flagref_list; +// list of (size_t pos, (void *f)(jl_value_t*)) entries +// for the serializer to mark values in need of rework by function f +static arraylist_t reinit_list; + // list of any methtable objects that were deserialized in MODE_MODULE // and need to be rehashed after assigning the uid fields to types // (only used in MODE_MODULE and MODE_MODULE_LAMBDAS) @@ -78,14 +82,14 @@ static jl_fptr_t id_to_fptrs[] = { // pointers to non-AST-ish objects in a compressed tree static jl_array_t *tree_literal_values=NULL; // (only used in MODE_AST) -static const ptrint_t LongSymbol_tag = 23; -static const ptrint_t LongSvec_tag = 24; -static const ptrint_t LongExpr_tag = 25; -static const ptrint_t LiteralVal_tag = 26; -static const ptrint_t SmallInt64_tag = 27; -static const ptrint_t IdTable_tag = 28; -static const ptrint_t Int32_tag = 29; -static const ptrint_t Array1d_tag = 30; +static const ptrint_t LongSymbol_tag = 23; +static const ptrint_t LongSvec_tag = 24; +static const ptrint_t LongExpr_tag = 25; +static const ptrint_t LiteralVal_tag = 26; +static const ptrint_t SmallInt64_tag = 27; +static const ptrint_t UNUSED_tag = 28; +static const ptrint_t Int32_tag = 29; +static const ptrint_t Array1d_tag = 30; static const ptrint_t Singleton_tag = 31; static const ptrint_t CommonSym_tag = 32; static const ptrint_t Null_tag = 253; @@ -576,6 +580,10 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v) if (mode == MODE_MODULE || mode == MODE_MODULE_LAMBDAS) pos <<= 1; ptrhash_put(&backref_table, v, (void*)pos); + if (jl_typeof(v) == jl_idtable_type) { + arraylist_push(&reinit_list, (void*)pos); + arraylist_push(&reinit_list, (void*)1); + } } size_t i; @@ -737,10 +745,7 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v) writetag(s, (jl_value_t*)Singleton_tag); return; } - if ((jl_value_t*)t == jl_idtable_type) - writetag(s, (jl_value_t*)IdTable_tag); - else - writetag(s, (jl_value_t*)jl_datatype_type); + writetag(s, (jl_value_t*)jl_datatype_type); jl_serialize_value(s, t); if ((mode == MODE_MODULE || mode == MODE_MODULE_LAMBDAS) && t == jl_typename_type) { if (jl_is_submodule(((jl_typename_t*)v)->module, jl_current_module)) { @@ -767,21 +772,8 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v) } } else { - if ((jl_value_t*)t == jl_idtable_type) { - jl_array_t *data = (jl_array_t*)jl_get_nth_field(v, 0); - jl_value_t **d = (jl_value_t**)data->data; - for(size_t i=0; i < jl_array_len(data); i+=2) { - if (d[i+1] != NULL) { - jl_serialize_value(s, d[i+1]); - jl_serialize_value(s, d[i]); - } - } - jl_serialize_value(s, NULL); - } - else { - for(size_t i=0; i < nf; i++) { - jl_serialize_value(s, jl_get_nth_field(v, i)); - } + for(size_t i=0; i < nf; i++) { + jl_serialize_value(s, jl_get_nth_field(v, i)); } } if (mode == MODE_MODULE) { @@ -948,11 +940,9 @@ static jl_value_t *jl_deserialize_datatype(ios_t *s, int pos, jl_value_t **loc) assert(tree_literal_values==NULL && mode != MODE_AST); backref_list.items[pos] = dt; if (tag == 5) { - arraylist_push(&flagref_list, dt); arraylist_push(&flagref_list, loc); arraylist_push(&flagref_list, (void*)(uptrint_t)pos); if (has_instance) { - arraylist_push(&flagref_list, dt); arraylist_push(&flagref_list, &jl_astaggedvalue(dt->instance)->type); arraylist_push(&flagref_list, (void*)(uptrint_t)-1); } @@ -1020,7 +1010,6 @@ static jl_value_t *jl_deserialize_value(ios_t *s, jl_value_t **loc) jl_value_t *bp = (jl_value_t*)backref_list.items[offs]; assert(bp); if (isdatatype && loc != NULL) { - arraylist_push(&flagref_list, bp); arraylist_push(&flagref_list, loc); arraylist_push(&flagref_list, (void*)(uptrint_t)-1); } @@ -1279,7 +1268,7 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t arraylist_push(&backref_list, v); return v; } - else if (vtag == (jl_value_t*)jl_datatype_type || vtag == (jl_value_t*)IdTable_tag) { + else if (vtag == (jl_value_t*)jl_datatype_type) { int pos = backref_list.len; if (usetable) arraylist_push(&backref_list, NULL); @@ -1331,26 +1320,13 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t v = jl_new_struct_uninit(dt); if (usetable) backref_list.items[pos] = v; - if (vtag == (jl_value_t*)IdTable_tag) { - jl_array_t *a = jl_alloc_cell_1d(32); //todo - while (1) { - jl_value_t *val = jl_deserialize_value(s, NULL); - if (val == NULL) - break; - jl_value_t *key = jl_deserialize_value(s, NULL); - a = jl_eqtable_put(a, key, val); - } - jl_set_nth_field(v, 0, (jl_value_t*)a); - } - else { - char *data = (char*)jl_data_ptr(v); - for(i=0; i < nf; i++) { - jl_set_nth_field(v, i, jl_deserialize_value(s, - (dt->fields[i].isptr) ? (jl_value_t**)(data+jl_field_offset(dt, i)) : NULL)); - } - if ((mode == MODE_MODULE || mode == MODE_MODULE_LAMBDAS) && jl_is_mtable(v)) - arraylist_push(&methtable_list, v); + char *data = (char*)jl_data_ptr(v); + for(i=0; i < nf; i++) { + jl_set_nth_field(v, i, jl_deserialize_value(s, + (dt->fields[i].isptr) ? (jl_value_t**)(data+jl_field_offset(dt, i)) : NULL)); } + if ((mode == MODE_MODULE || mode == MODE_MODULE_LAMBDAS) && jl_is_mtable(v)) + arraylist_push(&methtable_list, v); } // TODO: put WeakRefs on the weak_refs list if (mode == MODE_MODULE) { @@ -1367,7 +1343,6 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t arraylist_push(&backref_list, (void*)v); if (mode == MODE_MODULE) { assert(loc != NULL); - arraylist_push(&flagref_list, v); arraylist_push(&flagref_list, loc); arraylist_push(&flagref_list, (void*)pos); } @@ -1440,6 +1415,7 @@ DLLEXPORT void jl_save_system_image(const char *fname) int en = jl_gc_is_enabled(); jl_gc_disable(); htable_reset(&backref_table, 250000); + arraylist_new(&reinit_list, 0); ios_t f; if (ios_file(&f, fname, 1, 1, 1, 1) == NULL) { jl_errorf("Cannot open system image file \"%s\" for writing.\n", fname); @@ -1473,7 +1449,16 @@ DLLEXPORT void jl_save_system_image(const char *fname) write_int32(&f, jl_get_t_uid_ctr()); write_int32(&f, jl_get_gs_ctr()); + + // record reinitialization functions + for (i = 0; i < reinit_list.len; i += 2) { + write_int32(&f, (int)reinit_list.items[i]); + write_int32(&f, (int)reinit_list.items[i+1]); + } + write_int32(&f, -1); + htable_reset(&backref_table, 0); + arraylist_free(&reinit_list); ios_close(&f); if (en) jl_gc_enable(); @@ -1579,6 +1564,23 @@ void jl_restore_system_image(const char *fname) jl_set_t_uid_ctr(read_int32(&f)); jl_set_gs_ctr(read_int32(&f)); + // run reinitialization functions + int pos = read_int32(&f); + while (pos != -1) { + jl_value_t *v = (jl_value_t*)backref_list.items[pos]; + switch (read_int32(&f)) { + case 1: { + jl_array_t **a = (jl_array_t**)&v->fieldptr[0]; + jl_idtable_rehash(a, jl_array_len(*a)); + gc_wb(v, *a); + break; + } + default: + assert(0); + } + pos = read_int32(&f); + } + //jl_printf(JL_STDERR, "backref_list.len = %d\n", backref_list.len); arraylist_free(&backref_list); ios_close(&f); @@ -1773,7 +1775,8 @@ jl_module_t *jl_restore_new_module(const char *fname) size_t i = 0; while (i < flagref_list.len) { - jl_value_t *v, *o = (jl_value_t*)flagref_list.items[i++]; + jl_value_t **loc = (jl_value_t**)flagref_list.items[i++]; + jl_value_t *v, *o = *loc; jl_datatype_t *dt; if (jl_is_datatype(o)) { dt = (jl_datatype_t*)o; @@ -1784,7 +1787,6 @@ jl_module_t *jl_restore_new_module(const char *fname) v = o; } jl_datatype_t *t = (jl_datatype_t*)jl_cache_type_(dt); - jl_value_t **loc = (jl_value_t**)flagref_list.items[i++]; int offs = (int)(intptr_t)flagref_list.items[i++]; if (t != dt) { jl_set_typeof(dt, (jl_value_t*)(ptrint_t)6); // invalidate the old value to help catch errors @@ -1804,30 +1806,29 @@ jl_module_t *jl_restore_new_module(const char *fname) while (j < flagref_list.len) { if (flagref_list.items[j] == dt) { if (t != dt) { - jl_value_t **loc = (jl_value_t**)flagref_list.items[j+1]; - int offs = (int)(intptr_t)flagref_list.items[j+2]; + jl_value_t **loc = (jl_value_t**)flagref_list.items[j]; + int offs = (int)(intptr_t)flagref_list.items[j+1]; if (loc) *loc = (jl_value_t*)t; if (offs > 0) backref_list.items[offs] = t; } } else if (flagref_list.items[j] == v) { if (t->instance != v) { - jl_value_t **loc = (jl_value_t**)flagref_list.items[j+1]; - int offs = (int)(intptr_t)flagref_list.items[j+2]; + jl_value_t **loc = (jl_value_t**)flagref_list.items[j]; + int offs = (int)(intptr_t)flagref_list.items[j+1]; if (loc) *loc = v; if (offs > 0) backref_list.items[offs] = v; } } else { - j += 3; + j += 2; continue; } - flagref_list.len -= 3; + flagref_list.len -= 2; if (j >= flagref_list.len) break; flagref_list.items[j+0] = flagref_list.items[flagref_list.len+0]; flagref_list.items[j+1] = flagref_list.items[flagref_list.len+1]; - flagref_list.items[j+2] = flagref_list.items[flagref_list.len+2]; } } @@ -1891,7 +1892,7 @@ void jl_init_serializer(void) jl_function_type, jl_simplevector_type, jl_array_type, jl_expr_type, (void*)LongSymbol_tag, (void*)LongSvec_tag, (void*)LongExpr_tag, (void*)LiteralVal_tag, - (void*)SmallInt64_tag, (void*)IdTable_tag, + (void*)SmallInt64_tag, (void*)UNUSED_tag, (void*)Int32_tag, (void*)Array1d_tag, (void*)Singleton_tag, jl_module_type, jl_tvar_type, jl_lambda_info_type, (void*)CommonSym_tag, diff --git a/src/julia_internal.h b/src/julia_internal.h index 4dc90f14b3619..d836bb3442cec 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -119,6 +119,7 @@ extern JL_THREAD void *jl_stackbase; void jl_dump_bitcode(char *fname); void jl_dump_objfile(char *fname, int jit_model); int32_t jl_get_llvm_gv(jl_value_t *p); +void jl_idtable_rehash(jl_array_t **pa, size_t newsz); #ifdef _OS_LINUX_ DLLEXPORT void jl_read_sonames(void); From 028d9dcae43829f0f7604d6b35705ea9405e0f8a Mon Sep 17 00:00:00 2001 From: Jim Garrison Date: Fri, 15 May 2015 23:25:48 -0700 Subject: [PATCH 013/181] Make dlopen return a DLHandle object instead of a raw pointer This allows the memory to be garbage collected if dlclose is never called. For backwards compatibility, methods that accept pointers are still implemented. In particular, BinDeps makes use of this API. --- base/libdl.jl | 68 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/base/libdl.jl b/base/libdl.jl index 5f46ca0432856..c732133618294 100644 --- a/base/libdl.jl +++ b/base/libdl.jl @@ -20,40 +20,67 @@ const RTLD_NOLOAD = 0x00000010 const RTLD_DEEPBIND = 0x00000020 const RTLD_FIRST = 0x00000040 -function dlsym(hnd::Ptr, s::Union(Symbol,AbstractString)) - hnd == C_NULL && error("NULL library handle") - ccall(:jl_dlsym, Ptr{Void}, (Ptr{Void}, Cstring), hnd, s) +type DLHandle + ptr::Ptr{Void} end -function dlsym_e(hnd::Ptr, s::Union(Symbol,AbstractString)) - hnd == C_NULL && error("NULL library handle") - ccall(:jl_dlsym_e, Ptr{Void}, (Ptr{Void}, Cstring), hnd, s) +==(hnd1::DLHandle, hnd2::DLHandle) = hnd1.ptr == hnd2.ptr + +isopen(hnd::DLHandle) = hnd.ptr != C_NULL + +function dlsym(hnd::DLHandle, s::Union(Symbol,AbstractString)) + isopen(hnd) || error("NULL library handle") + ccall(:jl_dlsym, Ptr{Void}, (Ptr{Void}, Cstring), hnd.ptr, s) +end + +function dlsym_e(hnd::DLHandle, s::Union(Symbol,AbstractString)) + isopen(hnd) || error("NULL library handle") + ccall(:jl_dlsym_e, Ptr{Void}, (Ptr{Void}, Cstring), hnd.ptr, s) end dlopen(s::Symbol, flags::Integer = RTLD_LAZY | RTLD_DEEPBIND) = dlopen(string(s), flags) -dlopen(s::AbstractString, flags::Integer = RTLD_LAZY | RTLD_DEEPBIND) = - ccall(:jl_load_dynamic_library, Ptr{Void}, (Cstring,UInt32), s, flags) +function dlopen(s::AbstractString, flags::Integer = RTLD_LAZY | RTLD_DEEPBIND) + hnd = DLHandle(ccall(:jl_load_dynamic_library, Ptr{Void}, (Cstring,UInt32), s, flags)) + finalizer(hnd, finalize_dlhandle) + return hnd +end -dlopen_e(s::AbstractString, flags::Integer = RTLD_LAZY | RTLD_DEEPBIND) = - ccall(:jl_load_dynamic_library_e, Ptr{Void}, (Cstring,UInt32), s, flags) +function dlopen_e(s::AbstractString, flags::Integer = RTLD_LAZY | RTLD_DEEPBIND) + hnd = DLHandle(ccall(:jl_load_dynamic_library_e, Ptr{Void}, (Cstring,UInt32), s, flags)) + finalizer(hnd, finalize_dlhandle) + return hnd +end dlopen_e(s::Symbol, flags::Integer = RTLD_LAZY | RTLD_DEEPBIND) = dlopen_e(string(s), flags) -dlclose(p::Ptr) = if p!=C_NULL; ccall(:uv_dlclose,Void,(Ptr{Void},),p); Libc.free(p); end +function finalize_dlhandle(hnd::DLHandle) + if hnd.ptr != C_NULL + Libc.free(hnd.ptr) + hnd.ptr = C_NULL + end +end + +function dlclose(hnd::DLHandle) + if hnd.ptr != C_NULL + ccall(:uv_dlclose,Void,(Ptr{Void},),hnd.ptr) + Libc.free(hnd.ptr) + hnd.ptr = C_NULL + end +end function find_library{T<:ByteString, S<:ByteString}(libnames::Array{T,1}, extrapaths::Array{S,1}=ASCIIString[]) for lib in libnames for path in extrapaths l = joinpath(path, lib) p = dlopen_e(l, RTLD_LAZY) - if p != C_NULL + if isopen(p) dlclose(p) return l end end p = dlopen_e(lib, RTLD_LAZY) - if p != C_NULL + if isopen(p) dlclose(p) return lib end @@ -61,8 +88,8 @@ function find_library{T<:ByteString, S<:ByteString}(libnames::Array{T,1}, extrap return "" end -function dlpath( handle::Ptr{Void} ) - p = ccall( :jl_pathname_for_handle, Ptr{UInt8}, (Ptr{Void},), handle ) +function dlpath(handle::DLHandle) + p = ccall( :jl_pathname_for_handle, Ptr{UInt8}, (Ptr{Void},), handle.ptr ) s = bytestring(p) @windows_only Libc.free(p) return s @@ -75,6 +102,17 @@ function dlpath(libname::Union(AbstractString, Symbol)) return path end +# For now we support the old API that used a raw uv_lib_t* as the +# handle. In particular, BinDeps currently relies on this API. +# TODO: Deprecate these methods. +dlsym(hnd::Ptr, s::Union(Symbol,AbstractString)) = dlsym(DLHandle(hnd), s) +dlsym_e(hnd::Ptr, s::Union(Symbol,AbstractString)) = dlsym_e(DLHandle(hnd), s) +dlclose(hnd::Ptr) = dlclose(DLHandle(hnd)) +dlpath(hnd::Ptr) = dlpath(DLHandle(hnd)) +# (Typically used for comparison with C_NULL) +==(hnd::DLHandle, ptr::Ptr{Void}) = hnd.ptr == ptr +==(ptr::Ptr{Void}, hnd::DLHandle) = hnd.ptr == ptr + if OS_NAME === :Darwin const dlext = "dylib" elseif OS_NAME === :Windows From 9abcf4fffb73646d4f57b21c3b32e0b969516142 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 19 May 2015 02:35:05 -0400 Subject: [PATCH 014/181] [LLVM37] Adjust to IRBuilder API change --- src/ccall.cpp | 4 ++ src/cgutils.cpp | 82 ++++++++++++++++++++++++++++++++++++----- src/codegen.cpp | 81 +++++++++++++++++++++++++++++++++++++--- src/disasm.cpp | 4 ++ src/intrinsics.cpp | 92 +++++++++++++++++++++++++++++----------------- 5 files changed, 215 insertions(+), 48 deletions(-) diff --git a/src/ccall.cpp b/src/ccall.cpp index 7f61cd52c46c6..9810d6d118204 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -210,7 +210,11 @@ static Value *runtime_sym_lookup(PointerType *funcptype, char *f_lib, char *f_na else { libname = literal_static_pointer_val(f_lib, T_pint8); } +#ifdef LLVM37 + Value *llvmf = builder.CreateCall(prepare_call(jldlsym_func), { libname, builder.CreateGlobalStringPtr(f_name), libptrgv }); +#else Value *llvmf = builder.CreateCall3(prepare_call(jldlsym_func), libname, builder.CreateGlobalStringPtr(f_name), libptrgv); +#endif builder.CreateStore(llvmf, llvmgv); builder.CreateBr(ccall_bb); diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 37c0397edc309..85e659aaf4b1e 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -909,8 +909,13 @@ static void raise_exception_unless(Value *cond, Value *exc, jl_codectx_t *ctx) BasicBlock *passBB = BasicBlock::Create(getGlobalContext(),"pass"); builder.CreateCondBr(cond, passBB, failBB); builder.SetInsertPoint(failBB); +#ifdef LLVM37 + builder.CreateCall(prepare_call(jlthrow_line_func), { exc, + ConstantInt::get(T_int32, ctx->lineno) }); +#else builder.CreateCall2(prepare_call(jlthrow_line_func), exc, ConstantInt::get(T_int32, ctx->lineno)); +#endif builder.CreateUnreachable(); ctx->f->getBasicBlockList().push_back(passBB); builder.SetInsertPoint(passBB); @@ -950,10 +955,17 @@ static void emit_type_error(Value *x, jl_value_t *type, const std::string &msg, ArrayRef(zeros)); Value *msg_val = builder.CreateGEP(stringConst(msg), ArrayRef(zeros)); - builder.CreateCall5(prepare_call(jltypeerror_func), - fname_val, msg_val, +#ifdef LLVM37 + builder.CreateCall(prepare_call(jltypeerror_func), + { fname_val, msg_val, literal_pointer_val(type), boxed(x,ctx), - ConstantInt::get(T_int32, ctx->lineno)); + ConstantInt::get(T_int32, ctx->lineno) }); +#else + builder.CreateCall5(prepare_call(jltypeerror_func), + fname_val, msg_val, + literal_pointer_val(type), boxed(x,ctx), + ConstantInt::get(T_int32, ctx->lineno)); +#endif } static void emit_typecheck(Value *x, jl_value_t *type, const std::string &msg, @@ -962,8 +974,14 @@ static void emit_typecheck(Value *x, jl_value_t *type, const std::string &msg, Value *istype; if (jl_is_type_type(type) || !jl_is_leaf_type(type)) { istype = builder. - CreateICmpNE(builder.CreateCall3(prepare_call(jlsubtype_func), x, literal_pointer_val(type), + CreateICmpNE( +#ifdef LLVM37 + builder.CreateCall(prepare_call(jlsubtype_func), { x, literal_pointer_val(type), + ConstantInt::get(T_int32,1) }), +#else + builder.CreateCall3(prepare_call(jlsubtype_func), x, literal_pointer_val(type), ConstantInt::get(T_int32,1)), +#endif ConstantInt::get(T_int32,0)); } else { @@ -995,7 +1013,11 @@ static Value *emit_bounds_check(Value *a, jl_value_t *ty, Value *i, Value *len, builder.CreateCondBr(ok, passBB, failBB); builder.SetInsertPoint(failBB); if (ty == (jl_value_t*)jl_any_type) { +#ifdef LLVM37 + builder.CreateCall(prepare_call(jlvboundserror_func), { a, len, i }); +#else builder.CreateCall3(prepare_call(jlvboundserror_func), a, len, i); +#endif } else if (ty) { if (!a->getType()->isPtrOrPtrVectorTy()) { @@ -1003,13 +1025,24 @@ static Value *emit_bounds_check(Value *a, jl_value_t *ty, Value *i, Value *len, builder.CreateStore(a, tempSpace); a = tempSpace; } +#ifdef LLVM37 + builder.CreateCall(prepare_call(jluboundserror_func), { + builder.CreatePointerCast(a, T_pint8), + literal_pointer_val(ty), + i }); +#else builder.CreateCall3(prepare_call(jluboundserror_func), builder.CreatePointerCast(a, T_pint8), literal_pointer_val(ty), i); +#endif } else { +#ifdef LLVM37 + builder.CreateCall(prepare_call(jlboundserror_func), { a, i }); +#else builder.CreateCall2(prepare_call(jlboundserror_func), a, i); +#endif } builder.CreateUnreachable(); ctx->f->getBasicBlockList().push_back(passBB); @@ -1196,7 +1229,11 @@ static Value *emit_getfield_unknownidx(Value *strct, Value *idx, jl_datatype_t * } else { idx = builder.CreateSub(idx, ConstantInt::get(T_size, 1)); +#ifdef LLVM37 + Value *fld = builder.CreateCall(prepare_call(jlgetnthfieldchecked_func), { strct, idx }); +#else Value *fld = builder.CreateCall2(prepare_call(jlgetnthfieldchecked_func), strct, idx); +#endif return fld; } } @@ -1450,7 +1487,11 @@ static Value *emit_array_nd_index(Value *a, jl_value_t *ex, size_t nd, jl_value_ for(size_t k=0; k < nidxs; k++) { builder.CreateStore(idxs[k], builder.CreateGEP(tmp, ConstantInt::get(T_size, k))); } +#ifdef LLVM37 + builder.CreateCall(prepare_call(jlboundserrorv_func), { a, tmp, ConstantInt::get(T_size, nidxs) }); +#else builder.CreateCall3(prepare_call(jlboundserrorv_func), a, tmp, ConstantInt::get(T_size, nidxs)); +#endif builder.CreateUnreachable(); ctx->f->getBasicBlockList().push_back(endBB); @@ -1631,9 +1672,17 @@ static Value *boxed(Value *v, jl_codectx_t *ctx, jl_value_t *jt) if (jb == jl_float64_type) { // manually inline alloc & init of Float64 box. cheap, I know. #ifdef _P64 - Value *newv = builder.CreateCall(prepare_call(jlalloc1w_func)); + Value *newv = builder.CreateCall(prepare_call(jlalloc1w_func) +#ifdef LLVM37 + , {} +#endif + ); #else - Value *newv = builder.CreateCall(prepare_call(jlalloc2w_func)); + Value *newv = builder.CreateCall(prepare_call(jlalloc2w_func) +#ifdef LLVM37 + , {} +#endif + ); #endif return init_bits_value(newv, literal_pointer_val(jt), t, v); } @@ -1685,11 +1734,24 @@ static void emit_cpointercheck(Value *x, const std::string &msg, static Value* emit_allocobj(size_t static_size) { if (static_size == sizeof(void*)*1) - return builder.CreateCall(prepare_call(jlalloc1w_func)); + + return builder.CreateCall(prepare_call(jlalloc1w_func) +#ifdef LLVM37 + , {} +#endif + ); else if (static_size == sizeof(void*)*2) - return builder.CreateCall(prepare_call(jlalloc2w_func)); + return builder.CreateCall(prepare_call(jlalloc2w_func) +#ifdef LLVM37 + , {} +#endif + ); else if (static_size == sizeof(void*)*3) - return builder.CreateCall(prepare_call(jlalloc3w_func)); + return builder.CreateCall(prepare_call(jlalloc3w_func) +#ifdef LLVM37 + , {} +#endif + ); else return builder.CreateCall(prepare_call(jlallocobj_func), ConstantInt::get(T_size, static_size)); @@ -1704,7 +1766,7 @@ static void emit_write_barrier(jl_codectx_t* ctx, Value *parent, Value *ptr) Value* parent_mark_bits = builder.CreateAnd(parent_type, 1); // the branch hint does not seem to make it to the generated code - //builder.CreateCall2(expect_func, parent_marked, ConstantInt::get(T_int1, 0)); + //builder.CreateCall(expect_func, {parent_marked, ConstantInt::get(T_int1, 0)}); Value* parent_marked = builder.CreateICmpEQ(parent_mark_bits, ConstantInt::get(T_size, 1)); BasicBlock* cont = BasicBlock::Create(getGlobalContext(), "cont"); diff --git a/src/codegen.cpp b/src/codegen.cpp index 69e875bcdd901..0b05c36afb753 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1172,7 +1172,11 @@ static void mallocVisitLine(std::string filename, int line) } GlobalVariable *v = prepare_global(vec[line]); builder.CreateStore(builder.CreateAdd(builder.CreateLoad(v, true), - builder.CreateCall(prepare_call(diff_gc_total_bytes_func))), + builder.CreateCall(prepare_call(diff_gc_total_bytes_func) +#ifdef LLVM37 + , {} +#endif + )), v, true); } @@ -1724,13 +1728,18 @@ static Value *emit_lambda_closure(jl_value_t *expr, jl_codectx_t *ctx) } Value *env_tuple; env_tuple = builder.CreateCall(prepare_call(jlnsvec_func), - ArrayRef(&captured[0], - 1+clen)); + ArrayRef(&captured[0], 1+clen)); ctx->argDepth = argStart; make_gcroot(env_tuple, ctx); +#ifdef LLVM37 + Value *result = builder.CreateCall(prepare_call(jlclosure_func), + {Constant::getNullValue(T_pint8), + env_tuple, literal_pointer_val(expr)}); +#else Value *result = builder.CreateCall3(prepare_call(jlclosure_func), Constant::getNullValue(T_pint8), env_tuple, literal_pointer_val(expr)); +#endif ctx->argDepth--; return result; } @@ -1796,8 +1805,13 @@ static Value *emit_getfield(jl_value_t *expr, jl_sym_t *name, jl_codectx_t *ctx) make_gcroot(arg2, ctx); Value *myargs = builder.CreateGEP(ctx->argTemp, ConstantInt::get(T_size, argStart+ctx->argSpaceOffs)); +#ifdef LLVM37 + Value *result = builder.CreateCall(prepare_call(jlgetfield_func), {V_null, myargs, + ConstantInt::get(T_int32,2)}); +#else Value *result = builder.CreateCall3(prepare_call(jlgetfield_func), V_null, myargs, ConstantInt::get(T_int32,2)); +#endif ctx->argDepth = argStart; return result; } @@ -1887,8 +1901,13 @@ static Value *emit_f_is(jl_value_t *rt1, jl_value_t *rt2, varg1 = boxed(varg1,ctx); varg2 = boxed(varg2,ctx); if (ptr_comparable) answer = builder.CreateICmpEQ(varg1, varg2); - else + else { +#ifdef LLVM37 + answer = builder.CreateTrunc(builder.CreateCall(prepare_call(jlegal_func), {varg1, varg2}), T_int1); +#else answer = builder.CreateTrunc(builder.CreateCall2(prepare_call(jlegal_func), varg1, varg2), T_int1); +#endif + } done: ctx->argDepth = last_depth; return answer; @@ -1989,7 +2008,11 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, Value *typeassert = jl_Module->getOrInsertFunction("jl_typeassert", ft); int ldepth = ctx->argDepth; Value *arg1 = emit_boxed_rooted(args[1], ctx); +#ifdef LLVM37 + builder.CreateCall(prepare_call(typeassert), {arg1, boxed(emit_expr(args[2], ctx),ctx)}); +#else builder.CreateCall2(prepare_call(typeassert), arg1, boxed(emit_expr(args[2], ctx),ctx)); +#endif ctx->argDepth = ldepth; JL_GC_POP(); return arg1; @@ -2046,10 +2069,17 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, nva = builder.CreateTrunc(nva, T_int32); #endif Value *r = +#ifdef LLVM37 + builder.CreateCall(prepare_call(theFptr), {theF, + builder.CreateGEP(ctx->argArray, + ConstantInt::get(T_size, ctx->nReqArgs)), + nva}); +#else builder.CreateCall3(prepare_call(theFptr), theF, builder.CreateGEP(ctx->argArray, ConstantInt::get(T_size, ctx->nReqArgs)), nva); +#endif JL_GC_POP(); return r; } @@ -2070,8 +2100,13 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, else if (f->fptr == &jl_f_throw && nargs==1) { Value *arg1 = boxed(emit_expr(args[1], ctx), ctx); JL_GC_POP(); +#ifdef LLVM37 + builder.CreateCall(prepare_call(jlthrow_line_func), {arg1, + ConstantInt::get(T_int32, ctx->lineno)}); +#else builder.CreateCall2(prepare_call(jlthrow_line_func), arg1, ConstantInt::get(T_int32, ctx->lineno)); +#endif return V_null; } else if (f->fptr == &jl_f_arraylen && nargs==1) { @@ -2382,8 +2417,13 @@ static Value *emit_jlcall(Value *theFptr, Value *theF, int argStart, myargs = builder.CreateGEP(ctx->argTemp, ConstantInt::get(T_size, argStart+ctx->argSpaceOffs)); } +#ifdef LLVM37 + Value *result = builder.CreateCall(prepare_call(theFptr), {theF, myargs, + ConstantInt::get(T_int32,nargs)}); +#else Value *result = builder.CreateCall3(prepare_call(theFptr), theF, myargs, ConstantInt::get(T_int32,nargs)); +#endif ctx->argDepth = argStart; return result; } @@ -2570,18 +2610,30 @@ static Value *emit_call(jl_value_t **args, size_t arglen, jl_codectx_t *ctx, jl_ ConstantInt::get(T_size, argStart+1+ctx->argSpaceOffs)); } theFptr = emit_nthptr_recast(theFunc, (ssize_t)(offsetof(jl_function_t,fptr)/sizeof(void*)), tbaa_func, jl_pfptr_llvmt); +#ifdef LLVM37 + Value *r1 = builder.CreateCall(prepare_call(theFptr), {theFunc, myargs, + ConstantInt::get(T_int32,nargs)}); +#else Value *r1 = builder.CreateCall3(prepare_call(theFptr), theFunc, myargs, ConstantInt::get(T_int32,nargs)); +#endif builder.CreateBr(mergeBB1); ctx->f->getBasicBlockList().push_back(elseBB1); builder.SetInsertPoint(elseBB1); // not function myargs = builder.CreateGEP(ctx->argTemp, ConstantInt::get(T_size, argStart+ctx->argSpaceOffs)); +#ifdef LLVM37 + Value *r2 = builder.CreateCall(prepare_call(jlapplygeneric_func), + {literal_pointer_val((jl_value_t*)jl_module_call_func(ctx->module)), + myargs, + ConstantInt::get(T_int32,nargs+1)}); +#else Value *r2 = builder.CreateCall3(prepare_call(jlapplygeneric_func), literal_pointer_val((jl_value_t*)jl_module_call_func(ctx->module)), myargs, ConstantInt::get(T_int32,nargs+1)); +#endif builder.CreateBr(mergeBB1); ctx->f->getBasicBlockList().push_back(mergeBB1); builder.SetInsertPoint(mergeBB1); @@ -2842,9 +2894,15 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) Value *bp = var_binding_pointer(s, &bnd, true, ctx); if (bnd) { Value *rval = boxed(emit_expr(r, ctx, true),ctx); +#ifdef LLVM37 + builder.CreateCall(prepare_call(jlcheckassign_func), + {literal_pointer_val(bnd), + rval}); +#else builder.CreateCall2(prepare_call(jlcheckassign_func), - literal_pointer_val(bnd), + literal_pointer_val(bnd), rval); +#endif // Global variable. Does not need debug info because the debugger knows about // its memory location. } @@ -3148,7 +3206,11 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, ConstantInt::get(T_size,0)); builder.CreateCall(prepare_call(jlenter_func), jbuf); #ifndef _OS_WINDOWS_ +#ifdef LLVM37 + CallInst *sj = builder.CreateCall(prepare_call(setjmp_func), { jbuf, ConstantInt::get(T_int32,0) }); +#else CallInst *sj = builder.CreateCall2(prepare_call(setjmp_func), jbuf, ConstantInt::get(T_int32,0)); +#endif #else CallInst *sj = builder.CreateCall(prepare_call(setjmp_func), jbuf); #endif @@ -4453,12 +4515,21 @@ static Function *emit_function(jl_lambda_info_t *lam) // restarg = jl_f_tuple(NULL, &args[nreq], nargs-nreq) Value *lv = vi.memvalue; if (dyn_cast(lv) != NULL || dyn_cast(lv)->getAllocatedType() == jl_pvalue_llvmt) { +#ifdef LLVM37 + Value *restTuple = + builder.CreateCall(prepare_call(jltuple_func), {V_null, + builder.CreateGEP(argArray, + ConstantInt::get(T_size,nreq)), + builder.CreateSub(argCount, + ConstantInt::get(T_int32,nreq))}); +#else Value *restTuple = builder.CreateCall3(prepare_call(jltuple_func), V_null, builder.CreateGEP(argArray, ConstantInt::get(T_size,nreq)), builder.CreateSub(argCount, ConstantInt::get(T_int32,nreq))); +#endif if (isBoxed(argname, &ctx)) builder.CreateStore(builder.CreateCall(prepare_call(jlbox_func), restTuple), lv); else diff --git a/src/disasm.cpp b/src/disasm.cpp index 9dcf80acd788c..d07fdaf3f44f8 100644 --- a/src/disasm.cpp +++ b/src/disasm.cpp @@ -164,7 +164,11 @@ void SymbolTable::createSymbols() uint64_t addr = isymb->first - ip; std::ostringstream name; name << "L" << addr; +#ifdef LLVM37 + MCSymbol *symb = Ctx.getOrCreateSymbol(StringRef(name.str())); +#else MCSymbol *symb = Ctx.GetOrCreateSymbol(StringRef(name.str())); +#endif symb->setVariableValue(MCConstantExpr::Create(addr, Ctx)); isymb->second = symb; } diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 8a83fbc7fbc57..930ba371028c1 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -603,7 +603,11 @@ static Value *emit_runtime_pointerref(jl_value_t *e, jl_value_t *i, jl_codectx_t int ldepth = ctx->argDepth; Value *parg = emit_boxed_rooted(e, ctx); Value *iarg = boxed(emit_expr(i, ctx), ctx); +#ifdef LLVM37 + Value *ret = builder.CreateCall(prepare_call(preffunc), { parg, iarg }); +#else Value *ret = builder.CreateCall2(prepare_call(preffunc), parg, iarg); +#endif ctx->argDepth = ldepth; return ret; } @@ -660,7 +664,11 @@ static Value *emit_runtime_pointerset(jl_value_t *e, jl_value_t *x, jl_value_t * Value *parg = emit_boxed_rooted(e, ctx); Value *iarg = emit_boxed_rooted(i, ctx); Value *xarg = boxed(emit_expr(x, ctx), ctx); +#ifdef LLVM37 + builder.CreateCall(prepare_call(psetfunc), { parg, xarg, iarg }); +#else builder.CreateCall3(prepare_call(psetfunc), parg, xarg, iarg); +#endif ctx->argDepth = ldepth; return parg; } @@ -986,20 +994,23 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, HANDLE(fma_float,3) { assert(y->getType() == x->getType()); assert(z->getType() == y->getType()); - return builder.CreateCall3 - (Intrinsic::getDeclaration(jl_Module, Intrinsic::fma, - ArrayRef(x->getType())), - FP(x), FP(y), FP(z)); + Value *fmaintr = Intrinsic::getDeclaration(jl_Module, Intrinsic::fma, + ArrayRef(x->getType())); +#ifdef LLVM37 + return builder.CreateCall(fmaintr,{ FP(x), FP(y), FP(z) }); +#else + return builder.CreateCall3(fmaintr, FP(x), FP(y), FP(z)); +#endif } HANDLE(muladd_float,3) #ifdef LLVM34 { assert(y->getType() == x->getType()); assert(z->getType() == y->getType()); - return builder.CreateCall3 + return builder.CreateCall (Intrinsic::getDeclaration(jl_Module, Intrinsic::fmuladd, ArrayRef(x->getType())), - FP(x), FP(y), FP(z)); + {FP(x), FP(y), FP(z)}); } #else return math_builder(ctx, true)(). @@ -1014,21 +1025,25 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, HANDLE(checked_umul,2) { Value *ix = JL_INT(x); Value *iy = JL_INT(y); assert(ix->getType() == iy->getType()); - Value *res = builder.CreateCall2 - (Intrinsic::getDeclaration(jl_Module, - f==checked_sadd ? - Intrinsic::sadd_with_overflow : - (f==checked_uadd ? - Intrinsic::uadd_with_overflow : - (f==checked_ssub ? - Intrinsic::ssub_with_overflow : - (f==checked_usub ? - Intrinsic::usub_with_overflow : - (f==checked_smul ? - Intrinsic::smul_with_overflow : - Intrinsic::umul_with_overflow)))), - ArrayRef(ix->getType())), - ix, iy); + Value *intr = + Intrinsic::getDeclaration(jl_Module, + f==checked_sadd ? + Intrinsic::sadd_with_overflow : + (f==checked_uadd ? + Intrinsic::uadd_with_overflow : + (f==checked_ssub ? + Intrinsic::ssub_with_overflow : + (f==checked_usub ? + Intrinsic::usub_with_overflow : + (f==checked_smul ? + Intrinsic::smul_with_overflow : + Intrinsic::umul_with_overflow)))), + ArrayRef(ix->getType())); +#ifdef LLVM37 + Value *res = builder.CreateCall(intr,{ix, iy}); +#else + Value *res = builder.CreateCall2(intr, ix, iy); +#endif Value *obit = builder.CreateExtractValue(res, ArrayRef(1)); raise_exception_if(obit, prepare_global(jlovferr_var), ctx); return builder.CreateExtractValue(res, ArrayRef(0)); @@ -1139,15 +1154,23 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, HANDLE(ctlz_int,1) { x = JL_INT(x); Type *types[1] = {x->getType()}; - return builder.CreateCall2( - Intrinsic::getDeclaration(jl_Module, Intrinsic::ctlz, - ArrayRef(types)), x, ConstantInt::get(T_int1,0)); + Value *ctlz = Intrinsic::getDeclaration(jl_Module, Intrinsic::ctlz, + ArrayRef(types)); +#ifdef LLVM37 + return builder.CreateCall(ctlz, {x, ConstantInt::get(T_int1,0)}); +#else + return builder.CreateCall2(ctlz, x, ConstantInt::get(T_int1,0)); +#endif } HANDLE(cttz_int,1) { x = JL_INT(x); Type *types[1] = {x->getType()}; - return builder.CreateCall2( - Intrinsic::getDeclaration(jl_Module, Intrinsic::cttz, ArrayRef(types)), x, ConstantInt::get(T_int1, 0)); + Value *cttz = Intrinsic::getDeclaration(jl_Module, Intrinsic::cttz, ArrayRef(types)); +#ifdef LLVM37 + return builder.CreateCall(cttz, {x, ConstantInt::get(T_int1, 0)}); +#else + return builder.CreateCall2(cttz, x, ConstantInt::get(T_int1, 0)); +#endif } HANDLE(nan_dom_err,2) { @@ -1254,16 +1277,19 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, Type *tx = x->getType(); #ifdef LLVM36 Type *ts[1] = { tx }; - return builder.CreateCall2(Intrinsic::getDeclaration(jl_Module, Intrinsic::powi, - ArrayRef(ts)), - x, y); + Value *powi = Intrinsic::getDeclaration(jl_Module, Intrinsic::powi, + ArrayRef(ts)); +#ifdef LLVM37 + return builder.CreateCall(powi, {x, y}); +#else + return builder.CreateCall2(powi, x, y); +#endif #else // issue #6506 Type *ts[2] = { tx, tx }; - return builder. - CreateCall2(jl_Module->getOrInsertFunction(tx==T_float64 ? "pow" : "powf", - FunctionType::get(tx, ts, false)), - x, builder.CreateSIToFP(y, tx)); + Value *pow = jl_Module->getOrInsertFunction( + tx==T_float64 ? "pow" : "powf", FunctionType::get(tx, ts, false)); + return builder.CreateCall2(pow, x, builder.CreateSIToFP(y, tx)); #endif } HANDLE(sqrt_llvm_fast,1) { From c777d31727a13707c6fe02856cc8e1ded4c96f72 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 19 May 2015 00:34:40 -0700 Subject: [PATCH 015/181] homebrew bottle caching appears to be broken we're not running on osx travis at the moment so haven't noticed homebrew has switched from sourceforge to bintray which should be more reliable anyway [ci skip] --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6c1154a7fd9bb..48a3d0d35fc08 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,8 +39,6 @@ before_install: brew tap staticfloat/julia; brew rm --force $(brew deps --HEAD julia); brew update; - sed -i '' -e "s@https://downloads.sf.net/project/machomebrew/Bottles@https://cache.e.ip.saba.us/https://downloads.sf.net/project/machomebrew/Bottles@" /usr/local/Library/Homebrew/software_spec.rb; - sed -i '' -e "s@https://homebrew.bintray.com@https://cache.e.ip.saba.us/https://homebrew.bintray.com@" /usr/local/Library/Homebrew/software_spec.rb; brew install -v --only-dependencies --HEAD julia; BUILDOPTS="USECLANG=1 LLVM_CONFIG=$(brew --prefix llvm33-julia)/bin/llvm-config-3.3 VERBOSE=1 USE_BLAS64=0 SUITESPARSE_INC=-I$(brew --prefix suite-sparse-julia)/include"; BUILDOPTS="$BUILDOPTS LIBBLAS=-lopenblas LIBBLASNAME=libopenblas LIBLAPACK=-lopenblas LIBLAPACKNAME=libopenblas"; From 678cd329c30c0d5d24cdf1198bdb7106baf1dd36 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 19 May 2015 00:51:20 -0700 Subject: [PATCH 016/181] Remove .bat files from contrib/windows echo.bat probably never did anything, since libuv can't spawn bat files prepare-julia-env.bat is redundant since we now have contrib/build_sysimg.jl (too weird to live, and too rare to die) --- Makefile | 2 +- contrib/windows/echo.bat | 1 - contrib/windows/prepare-julia-env.bat | 23 ----------------------- ui/Makefile | 3 --- 4 files changed, 1 insertion(+), 28 deletions(-) delete mode 100644 contrib/windows/echo.bat delete mode 100644 contrib/windows/prepare-julia-env.bat diff --git a/Makefile b/Makefile index f87b7a7263dff..c9b4ee7d4c7d4 100644 --- a/Makefile +++ b/Makefile @@ -243,7 +243,7 @@ install: $(build_bindir)/stringreplace doc/_build/html $(INSTALL_M) $(build_bindir)/julia* $(DESTDIR)$(bindir)/ ifeq ($(OS),WINNT) - -$(INSTALL_M) $(build_bindir)/*.dll $(build_bindir)/*.bat $(DESTDIR)$(bindir)/ + -$(INSTALL_M) $(build_bindir)/*.dll $(DESTDIR)$(bindir)/ else -cp -a $(build_libexecdir) $(DESTDIR)$(prefix) diff --git a/contrib/windows/echo.bat b/contrib/windows/echo.bat deleted file mode 100644 index 75ca8e2eaf014..0000000000000 --- a/contrib/windows/echo.bat +++ /dev/null @@ -1 +0,0 @@ -@echo %* diff --git a/contrib/windows/prepare-julia-env.bat b/contrib/windows/prepare-julia-env.bat deleted file mode 100644 index d1383fedfd812..0000000000000 --- a/contrib/windows/prepare-julia-env.bat +++ /dev/null @@ -1,23 +0,0 @@ -@rem -@rem This file attempts to auto detect and configure the environment -@rem for starting julia and julia-web-server -@rem -@rem It sets the path as needed to reference various lib and bin -@rem files, and builds sys.ji if needed. -@rem - -set SYS_PATH=%PATH% -set PATH=%~dp0;%~dp0bin;%~dp0usr\bin;%~dp0..\usr\bin;%~dp0..\..\usr\bin;%SYS_PATH% -set JULIA_EXE=julia.exe -for %%A in (%JULIA_EXE%) do set JULIA_HOME=%%~dp$PATH:A -set JULIA=%JULIA_HOME%%JULIA_EXE% -set PATH=%SYS_PATH% - -set private_libdir=bin -if not exist "%JULIA_HOME%..\lib\julia\sys.ji" ( ^ -echo "Preparing Julia for first launch. This may take a while" && ^ -echo "You may see two git related errors. This is completely normal" && ^ -cd "%JULIA_HOME%..\share\julia\base" && ^ -"%JULIA%" --build "%JULIA_HOME%..\lib\julia\sys0" sysimg.jl && ^ -"%JULIA%" --build "%JULIA_HOME%..\lib\julia\sys" -J sys0.ji sysimg.jl && ^ -popd && pushd "%cd%" ) diff --git a/ui/Makefile b/ui/Makefile index f02b076c9bf05..f5edfd096a149 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -46,9 +46,6 @@ release debug: @$(call PRINT_CC, $(CC) $(CPPFLAGS) $(CFLAGS) $(DEBUGFLAGS) -c $< -o $@) ifeq ($(OS),WINNT) -$(build_bindir)/julia.bat: $(JULIAHOME)/contrib/windows/*.bat - cp $(JULIAHOME)/contrib/windows/*.bat $(build_bindir) -julia-release julia-debug: $(build_bindir)/julia.bat ifneq ($(USEMSVC), 1) julia_res.o: $(JULIAHOME)/contrib/windows/julia.rc JLVER=`cat $(JULIAHOME)/VERSION` && \ From 0fbd90360f89ac6c64085dbd913c02bfa7c7affa Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Tue, 19 May 2015 08:47:07 -0400 Subject: [PATCH 017/181] Allow anonymous typed VarArg. Fix #10985 --- src/julia-syntax.scm | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 42f672e9fc8cf..5b405966ea1a9 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -14,9 +14,12 @@ (if (any vararg? (butlast l)) (error "invalid ... on non-final argument")) (map (lambda (a) - (if (and (pair? a) (eq? (car a) 'kw)) - `(kw ,(fill-missing-argname (cadr a)) ,(caddr a)) - (fill-missing-argname a))) + (cond ((and (pair? a) (eq? (car a) 'kw)) + `(kw ,(fill-missing-argname (cadr a)) ,(caddr a))) + ((and (pair? a) (eq? (car a) '...)) + `(... ,(fill-missing-argname (cadr a)))) + (else + (fill-missing-argname a)))) l)) (define (deparse-arglist l (sep ",")) (string.join (map deparse l) sep)) From aa7bc7b9b9c2e9984c7ff368dd5630b97bece9d4 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Tue, 19 May 2015 08:50:03 -0400 Subject: [PATCH 018/181] Add test for lowering anonymous typed VarArg. --- test/parser.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/parser.jl b/test/parser.jl index 84830eafbaa1b..68f7be5bbb47b 100644 --- a/test/parser.jl +++ b/test/parser.jl @@ -83,3 +83,6 @@ macro test999_str(args...); args; end # issue #10994 @test parse("1 + #= \0 =# 2") == :(1 + 2) + +# issue #10985 +@test expand(:(f(::Int...) = 1)).head == :method From a4ba697038beb9e683de3bce2956b62ba05e3911 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 19 May 2015 10:57:58 -0400 Subject: [PATCH 019/181] fix base64decode to return array of decoded bytes, not a string (see #9157) --- base/base64.jl | 25 +++++++++---------------- doc/stdlib/io-network.rst | 4 ++-- test/base64.jl | 2 +- 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/base/base64.jl b/base/base64.jl index 00398c5635228..72cfffd4e446b 100644 --- a/base/base64.jl +++ b/base/base64.jl @@ -163,10 +163,6 @@ base64encode(x...) = base64encode(write, x...) ############################################################################# -# read(b::Base64Pipe, ::Type{UInt8}) = # TODO: decode base64 - -############################################################################# - type Base64DecodePipe <: IO io::IO # reading works in blocks of 4 characters that are decoded into 3 bytes and 2 of them cached @@ -182,7 +178,7 @@ end function read(b::Base64DecodePipe, t::Type{UInt8}) if length(b.cache) > 0 - val = shift!(b.cache) + return shift!(b.cache) else empty!(b.encvec) while !eof(b.io) && length(b.encvec) < 4 @@ -191,24 +187,21 @@ function read(b::Base64DecodePipe, t::Type{UInt8}) push!(b.encvec, c) end end - val = b64decode!(b.encvec,b.cache) + return b64decode!(b.encvec,b.cache) end - val -end - -function eof(b::Base64DecodePipe) - return length(b.cache) == 0 && eof(b.io) end -function close(b::Base64DecodePipe) -end +eof(b::Base64DecodePipe) = length(b.cache) == 0 && eof(b.io) +close(b::Base64DecodePipe) = nothing # Decodes a base64-encoded string function base64decode(s) b = IOBuffer(s) - decoded = readall(Base64DecodePipe(b)) - close(b) - decoded + try + return readbytes(Base64DecodePipe(b)) + finally + close(b) + end end end # module diff --git a/doc/stdlib/io-network.rst b/doc/stdlib/io-network.rst index a0797b8243889..cd2c4b256770c 100644 --- a/doc/stdlib/io-network.rst +++ b/doc/stdlib/io-network.rst @@ -436,8 +436,8 @@ Text I/O .. function:: base64decode(string) - Decodes the base64-encoded ``string`` and returns the obtained bytes. - + Decodes the base64-encoded ``string`` and returns a ``Vector{UInt8}`` + of the decoded bytes. Multimedia I/O -------------- diff --git a/test/base64.jl b/test/base64.jl index fd003944d0950..76f31dee69881 100644 --- a/test/base64.jl +++ b/test/base64.jl @@ -24,7 +24,7 @@ end rm(fname) # Encode to string and decode -@test base64decode(base64encode(inputText)) == inputText +@test utf8(base64decode(base64encode(inputText))) == inputText # Decode with max line chars = 76 and padding ipipe = Base64DecodePipe(IOBuffer(encodedMaxLine76)) From 77b63834a2b6c040cdd6474d606ab8212a791f1f Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 19 May 2015 11:54:30 -0400 Subject: [PATCH 020/181] make RTLD_LOCAL the default for dlopen on both Mac and Linux (fix #11322) --- src/dlload.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dlload.c b/src/dlload.c index ca9be9b9506be..6e9a945450bb3 100644 --- a/src/dlload.c +++ b/src/dlload.c @@ -50,7 +50,7 @@ DLLEXPORT int jl_uv_dlopen(const char *filename, jl_uv_libhandle lib_, unsigned dlerror(); /* Reset error status. */ lib->handle = dlopen(filename, (flags & JL_RTLD_NOW ? RTLD_NOW : RTLD_LAZY) - | JL_RTLD(flags, GLOBAL) | JL_RTLD(flags, LOCAL) + | (flags & JL_RTLD_GLOBAL ? RTLD_GLOBAL : RTLD_LOCAL) #ifdef RTLD_NODELETE | JL_RTLD(flags, NODELETE) #endif From defb363cd30c692e382dfea074cf2ff7d65d89b9 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Tue, 19 May 2015 17:31:06 -0400 Subject: [PATCH 021/181] speed up repl init --- base/precompile.jl | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/base/precompile.jl b/base/precompile.jl index dda16ae87fd18..ad3a53a65ef62 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -14,6 +14,10 @@ precompile(==, (Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}, Base precompile(==, (Base.LineEdit.Prompt, Base.LineEdit.Prompt)) precompile(==, (Base.Multimedia.TextDisplay, Base.REPL.REPLDisplay{Base.REPL.LineEditREPL})) precompile(==, (Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, Base.Multimedia.TextDisplay)) +precompile(==, (Int32, Int32)) +precompile(==, (Int32, Int64)) +precompile(==, (Int64, Int32)) +precompile(==, (Int64, Int64)) precompile(==, (Bool,Bool)) precompile(==, (Char, ASCIIString)) precompile(==, (IOStream,Void)) @@ -21,6 +25,7 @@ precompile(==, (Type{ASCIIString}, Type{Any})) precompile(==, (Type{Base.LineEdit.Prompt}, Type{Base.LineEdit.Prompt})) precompile(==, (Type{Function}, Int)) precompile(==, (Type{Function}, Type{ASCIIString})) +precompile(Base._atreplinit, (Base.REPL.LineEditREPL,)) precompile(Base.BitArray, (Int,)) precompile(Base.CallStack, (Expr, Module, (Void,), Base.EmptyCallStack)) precompile(Base.Dict, ()) @@ -170,6 +175,8 @@ precompile(Base._uv_hook_readcb, (Base.TTY, Int, Ptr{Void}, UInt)) precompile(Base._uv_hook_writecb_task, (Base.TTY, Ptr{Void}, Int32)) precompile(Base.abs, (Char,)) precompile(Base.abspath, (ASCIIString, ASCIIString)) +precompile(Base.abspath, (UTF8String,)) +precompile(Base.abspath, (UTF8String, UTF8String)) precompile(Base.abstract_eval, (LambdaStaticData, ObjectIdDict, Base.StaticVarInfo)) precompile(Base.abstract_interpret, (Bool, ObjectIdDict, Base.StaticVarInfo)) precompile(Base.alignment, (Float64,)) @@ -204,6 +211,7 @@ precompile(Base.convert, (Type{Char}, Char)) precompile(Base.convert, (Type{Function}, Function)) precompile(Base.convert, (Type{IOBuffer}, IOBuffer)) precompile(Base.convert, (Type{Module}, Module)) +precompile(Base.convert, (Type{AbstractString}, ASCIIString)) precompile(Base.copy!, (Array{Dict{Any, Any}, 1}, Int, Array{Dict{Any, Any}, 1}, Int, Int)) precompile(Base.copy, (Bool,)) precompile(Base.delete_var!, (Expr, Symbol)) @@ -288,6 +296,9 @@ precompile(Base.length, (ASCIIString,)) precompile(Base.length, (Array{UInt8,1},)) precompile(Base.length, (UnitRange{Int},)) precompile(Base.match, (Regex, ASCIIString)) +precompile(Base.match, (Regex, UTF8String)) +precompile(Base.match, (Regex, ASCIIString, Int)) +precompile(Base.match, (Regex, UTF8String, Int)) precompile(Base.min, (Int32, Int32)) precompile(Base.next, (Array{Base.LineEdit.TextInterface, 1}, Int)) precompile(Base.next, (Dict{Any,Any}, Int)) @@ -379,6 +390,7 @@ precompile(Base.setindex!, (Dict{Any, Any}, Base.LineEdit.PromptState, Base.Line precompile(Base.setindex!, (Dict{Any,Any}, Base.LineEdit.SearchState, Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider})) precompile(Base.setindex!, (Dict{Any,Any}, Bool, Cmd)) precompile(Base.setindex!, (Dict{UInt8, Any}, Base.LineEdit.Prompt, UInt8)) +precompile(Base.setindex!, (Base.EnvHash, ASCIIString, ASCIIString)) precompile(Base.setindex!, (Vector{Any}, UInt8, Int)) precompile(Base.setindex!, (Vector{Any}, Vector{Any}, Int)) precompile(Base.show, (Base.Terminals.TTYTerminal, Int)) @@ -425,6 +437,7 @@ precompile(Base.unshift!, (Array{Any,1}, Task)) precompile(Base.utf8, (ASCIIString,)) precompile(Base.utf8, (UTF8String,)) precompile(Base.uv_error, (ASCIIString, Bool)) +precompile(Base.uvfinalize, (Base.TTY,)) precompile(Base.vcat, (Base.LineEdit.Prompt,)) precompile(Base.wait, ()) precompile(Base.wait, (RemoteRef,)) @@ -453,6 +466,43 @@ precompile(Base.setindex!, (Dict{ByteString, VersionNumber}, VersionNumber, ASCI precompile(Base.spawn, (Cmd, (Base.TTY, Base.TTY, Base.TTY), Bool, Bool)) precompile(Base.spawn, (Cmd,)) +# For repl startup +precompile(Base.call, (Type{Task}, Function)) +precompile(Base.yieldto, (Task, Int)) +precompile(Base.open, (UTF8String, Bool, Bool, Bool, Bool, Bool)) +precompile(Base.setindex!, (Base.Dict{Any, Any}, Char, Char)) +precompile(Base.setindex!, (Base.Dict{Any, Any}, Char, UTF8String)) +precompile(Base.in, (UTF8String, Array{Any, 1})) +precompile(Base.getindex, (Base.Dict{Any, Any}, UTF8String)) +precompile(Base.LineEdit.setup_prefix_keymap, (Base.REPL.REPLHistoryProvider, Base.LineEdit.Prompt)) +precompile(Base.convert, (Type{Any}, Base.Dict{Char, Any})) +precompile(Base.REPL.mode_keymap, (Base.LineEdit.Prompt,)) +precompile(Base.promote_type, (Type{Base.LineEdit.Prompt}, Type{Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}}, Type)) +precompile(Base.promote_type, (Type{Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}}, Type{Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}})) +precompile(Base.similar, (Array{Base.LineEdit.Prompt, 1}, Type{Base.LineEdit.TextInterface}, Tuple{Int64})) +precompile(Base.setindex!, (Array{Base.LineEdit.TextInterface, 1}, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}, Base.UnitRange{Int64})) +precompile(Base.LineEdit.init_state, (Base.Terminals.TTYTerminal, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider})) +precompile(Base.setindex!, (Base.Dict{Any, Any}, Base.LineEdit.PrefixSearchState, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider})) +precompile(Base.take_ref, (Tuple{Int64, Int64},)) +precompile(Base.get, (Base.Dict{Any, Any}, Tuple{Int64, Int64}, Bool)) +precompile(Base.setindex!, (Base.Dict{Any, Any}, Base.RemoteValue, Tuple{Int64, Int64})) +precompile(Base.LineEdit.refresh_multi_line, (Array{Any, 1}, Base.Terminals.TerminalBuffer, Base.Terminals.TTYTerminal, Base.IOBuffer, Base.LineEdit.InputAreaState, Base.LineEdit.PromptState)) +precompile(Base.schedule, (Array{Any, 1}, Task, Void)) +precompile(Base.LineEdit.match_input, (Function, Base.LineEdit.MIState, Base.Terminals.TTYTerminal, Array{Char, 1}, Base.Dict{Char, Any})) +precompile(Base.convert, (Type{Union(ASCIIString, UTF8String)}, ASCIIString)) +precompile(Base.LineEdit.keymap_fcn, (Function, Base.LineEdit.MIState, ASCIIString)) +precompile(Base.weak_key_delete!, (Base.Dict{Any, Any}, Base.RemoteRef)) +precompile(==, (Base.RemoteRef, WeakRef)) +precompile(==, (Base.RemoteRef, Base.RemoteRef)) +precompile(Base.send_del_client, (Base.RemoteRef,)) +precompile(!=, (Base.SubString{UTF8String}, ASCIIString)) +precompile(Base.print_joined, (Base.IOBuffer, Array{Base.SubString{UTF8String}, 1}, ASCIIString)) +precompile(Base.call, (Array{Any, 1}, Type{Base.LineEdit.Prompt}, ASCIIString)) +precompile(Base.joinpath, (UTF8String, ASCIIString, ASCIIString, ASCIIString)) +precompile(Base.string, (ASCIIString, UTF8String, Char)) +precompile(Base.string, (ASCIIString, ASCIIString, Int)) +precompile(Base.vect, (Base.LineEdit.Prompt, ASCIIString)) + # Speed up repl help if Base.USE_GPL_LIBS sprint(Markdown.term, @doc fft) From ca885151913c14828e48cb8cca17e42339680674 Mon Sep 17 00:00:00 2001 From: Scott Paul Jones Date: Tue, 12 May 2015 00:10:16 -0400 Subject: [PATCH 022/181] Add isvalid(Type, value) methods, to replace is_valid_* --- NEWS.md | 12 ++++ base/ascii.jl | 2 +- base/deprecated.jl | 14 +++++ base/exports.jl | 5 -- base/io.jl | 2 +- base/string.jl | 4 +- base/utf16.jl | 8 +-- base/utf32.jl | 9 +-- base/utf8.jl | 2 +- base/utf8proc.jl | 12 ++-- doc/manual/strings.rst | 4 +- doc/stdlib/strings.rst | 22 ++++---- test/strings.jl | 124 ++++++++++++++++++++++++++++++----------- 13 files changed, 151 insertions(+), 69 deletions(-) diff --git a/NEWS.md b/NEWS.md index e96eef4fc1e54..683b3c6d4fa58 100644 --- a/NEWS.md +++ b/NEWS.md @@ -367,6 +367,13 @@ Deprecated or removed * Instead of `linrange`, use `linspace` ([#9666]). + * The functions `is_valid_char`, `is_valid_ascii`, `is_valid_utf8`, `is_valid_utf16`, and + `is_valid_utf32` have been replaced by generic `isvalid` methods. + The single argument form `isvalid(value)` can now be used for values of type `Char`, `ASCIIString`, + `UTF8String`, `UTF16String` and `UTF32String`. + The two argument form `isvalid(type, value)` can be used with the above types, with values + of type `Vector{UInt8}`, `Vector{UInt16}`, `Vector{UInt32}`, and `Vector{Char}` ([#11241]). + Julia v0.3.0 Release Notes ========================== @@ -1379,6 +1386,7 @@ Too numerous to mention. [#9779]: https://github.com/JuliaLang/julia/issues/9779 [#9862]: https://github.com/JuliaLang/julia/issues/9862 [#9957]: https://github.com/JuliaLang/julia/issues/9957 +[#10008]: https://github.com/JuliaLang/julia/issues/10008 [#10024]: https://github.com/JuliaLang/julia/issues/10024 [#10031]: https://github.com/JuliaLang/julia/issues/10031 [#10075]: https://github.com/JuliaLang/julia/issues/10075 @@ -1406,5 +1414,9 @@ Too numerous to mention. [#10888]: https://github.com/JuliaLang/julia/issues/10888 [#10893]: https://github.com/JuliaLang/julia/issues/10893 [#10914]: https://github.com/JuliaLang/julia/issues/10914 +[#10955]: https://github.com/JuliaLang/julia/issues/10955 [#10994]: https://github.com/JuliaLang/julia/issues/10994 +[#11105]: https://github.com/JuliaLang/julia/issues/11105 [#11145]: https://github.com/JuliaLang/julia/issues/11145 +[#11171]: https://github.com/JuliaLang/julia/issues/11171 +[#11241]: https://github.com/JuliaLang/julia/issues/11241 diff --git a/base/ascii.jl b/base/ascii.jl index da70742cc61d6..940f957f8e948 100644 --- a/base/ascii.jl +++ b/base/ascii.jl @@ -100,7 +100,7 @@ ascii(x) = convert(ASCIIString, x) convert(::Type{ASCIIString}, s::ASCIIString) = s convert(::Type{ASCIIString}, s::UTF8String) = ascii(s.data) convert(::Type{ASCIIString}, a::Vector{UInt8}) = begin - is_valid_ascii(a) || throw(ArgumentError("invalid ASCII sequence")) + isvalid(ASCIIString,a) || throw(ArgumentError("invalid ASCII sequence")) return ASCIIString(a) end diff --git a/base/deprecated.jl b/base/deprecated.jl index 4d2c645230bb4..4abccc3c98aea 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -443,3 +443,17 @@ export float32_isvalid, float64_isvalid @deprecate (&)(x::Char, y::Char) Char(UInt32(x) & UInt32(y)) @deprecate (|)(x::Char, y::Char) Char(UInt32(x) | UInt32(y)) @deprecate ($)(x::Char, y::Char) Char(UInt32(x) $ UInt32(y)) + +# 11241 + +@deprecate is_valid_char(ch::Char) isvalid(ch) +@deprecate is_valid_ascii(str::ASCIIString) isvalid(str) +@deprecate is_valid_utf8(str::UTF8String) isvalid(str) +@deprecate is_valid_utf16(str::UTF16String) isvalid(str) +@deprecate is_valid_utf32(str::UTF32String) isvalid(str) + +@deprecate is_valid_char(ch) isvalid(Char, ch) +@deprecate is_valid_ascii(str) isvalid(ASCIIString, str) +@deprecate is_valid_utf8(str) isvalid(UTF8String, str) +@deprecate is_valid_utf16(str) isvalid(UTF16String, str) +@deprecate is_valid_utf32(str) isvalid(UTF32String, str) diff --git a/base/exports.jl b/base/exports.jl index c597161bd1d62..3ebf2be2733d2 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -820,11 +820,6 @@ export ind2chr, info, is_assigned_char, - is_valid_ascii, - is_valid_char, - is_valid_utf8, - is_valid_utf16, - is_valid_utf32, isalnum, isalpha, isascii, diff --git a/base/io.jl b/base/io.jl index c8023d7d77df3..7d0eb16d67c75 100644 --- a/base/io.jl +++ b/base/io.jl @@ -246,7 +246,7 @@ end function readall(s::IO) b = readbytes(s) - return is_valid_ascii(b) ? ASCIIString(b) : UTF8String(b) + return isvalid(ASCIIString, b) ? ASCIIString(b) : UTF8String(b) end readall(filename::AbstractString) = open(readall, filename) diff --git a/base/string.jl b/base/string.jl index 8a7e83f4e0cbd..7295a231eea89 100644 --- a/base/string.jl +++ b/base/string.jl @@ -968,8 +968,8 @@ byte_string_classify(s::ByteString) = byte_string_classify(s.data) # 1: valid ASCII # 2: valid UTF-8 -is_valid_ascii(s::Union(Array{UInt8,1},ByteString)) = byte_string_classify(s) == 1 -is_valid_utf8(s::Union(Array{UInt8,1},ByteString)) = byte_string_classify(s) != 0 +isvalid(::Type{ASCIIString}, s::Union(Array{UInt8,1},ByteString)) = byte_string_classify(s) == 1 +isvalid(::Type{UTF8String}, s::Union(Array{UInt8,1},ByteString)) = byte_string_classify(s) != 0 ## multiline strings ## diff --git a/base/utf16.jl b/base/utf16.jl index 2a6ec9b571167..59c1e37cc799a 100644 --- a/base/utf16.jl +++ b/base/utf16.jl @@ -95,7 +95,7 @@ sizeof(s::UTF16String) = sizeof(s.data) - sizeof(UInt16) unsafe_convert{T<:Union(Int16,UInt16)}(::Type{Ptr{T}}, s::UTF16String) = convert(Ptr{T}, pointer(s)) -function is_valid_utf16(data::AbstractArray{UInt16}) +function isvalid(::Type{UTF16String}, data::AbstractArray{UInt16}) i = 1 n = length(data) # this may include NULL termination; that's okay while i < n # check for unpaired surrogates @@ -110,10 +110,8 @@ function is_valid_utf16(data::AbstractArray{UInt16}) return i > n || !utf16_is_surrogate(data[i]) end -is_valid_utf16(s::UTF16String) = is_valid_utf16(s.data) - function convert(::Type{UTF16String}, data::AbstractVector{UInt16}) - !is_valid_utf16(data) && throw(ArgumentError("invalid UTF16 data")) + !isvalid(UTF16String, data) && throw(ArgumentError("invalid UTF16 data")) len = length(data) d = Array(UInt16, len + 1) d[end] = 0 # NULL terminate @@ -144,7 +142,7 @@ function convert(T::Type{UTF16String}, bytes::AbstractArray{UInt8}) copy!(d,1, data,1, length(data)) # assume native byte order end d[end] = 0 # NULL terminate - !is_valid_utf16(d) && throw(ArgumentError("invalid UTF16 data")) + !isvalid(UTF16String, d) && throw(ArgumentError("invalid UTF16 data")) UTF16String(d) end diff --git a/base/utf32.jl b/base/utf32.jl index 5415b222888a7..306abcb24a95d 100644 --- a/base/utf32.jl +++ b/base/utf32.jl @@ -92,13 +92,14 @@ function convert(T::Type{UTF32String}, bytes::AbstractArray{UInt8}) UTF32String(d) end -function is_valid_utf32(s::Union(Vector{Char}, Vector{UInt32})) - for i=1:length(s) - @inbounds if !is_valid_char(reinterpret(UInt32, s[i])) ; return false ; end +function isvalid(::Type{UTF32String}, str::Union(Vector{Char}, Vector{UInt32})) + for i=1:length(str) + @inbounds if !isvalid(Char, reinterpret(UInt32, str[i])) ; return false ; end end return true end -is_valid_utf32(s::UTF32String) = is_valid_utf32(s.data) +isvalid(str::Vector{Char}) = isvalid(UTF32String, str) +isvalid{T<:Union(ASCIIString,UTF8String,UTF16String,UTF32String)}(str::T) = isvalid(T, str.data) utf32(p::Ptr{Char}, len::Integer) = utf32(pointer_to_array(p, len)) utf32(p::Union(Ptr{UInt32}, Ptr{Int32}), len::Integer) = utf32(convert(Ptr{Char}, p), len) diff --git a/base/utf8.jl b/base/utf8.jl index 07859349e1784..f288a1c0fa3dd 100644 --- a/base/utf8.jl +++ b/base/utf8.jl @@ -212,7 +212,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) : throw(ArgumentError("invalid UTF-8 sequence")) +convert(::Type{UTF8String}, a::Array{UInt8,1}) = isvalid(UTF8String, 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 842a79429f059..fc60350f8545a 100644 --- a/base/utf8proc.jl +++ b/base/utf8proc.jl @@ -3,19 +3,21 @@ # Various Unicode functionality from the utf8proc library module UTF8proc -import Base: show, showcompact, ==, hash, string, symbol, isless, length, eltype, start, next, done, convert +import Base: show, showcompact, ==, hash, string, symbol, isless, length, eltype, start, next, done, convert, isvalid export isgraphemebreak # also exported by Base: -export normalize_string, graphemes, is_valid_char, is_assigned_char, charwidth, +export normalize_string, graphemes, is_assigned_char, charwidth, isvalid, islower, isupper, isalpha, isdigit, isnumber, isalnum, iscntrl, ispunct, isspace, isprint, isgraph, isblank # whether codepoints are valid Unicode scalar values, i.e. 0-0xd7ff, 0xe000-0x10ffff -is_valid_char(ch::Unsigned) = !Bool((ch-0xd800<0x800)|(ch>0x10ffff)) -is_valid_char(ch::Integer) = is_valid_char(Unsigned(ch)) -is_valid_char(ch::Char) = is_valid_char(UInt32(ch)) +isvalid(::Type{Char}, ch::Unsigned) = !((ch - 0xd800 < 0x800) | (ch > 0x10ffff)) +isvalid(::Type{Char}, ch::Integer) = isvalid(Char, Unsigned(ch)) +isvalid(::Type{Char}, ch::Char) = isvalid(Char, UInt32(ch)) + +isvalid(ch::Char) = isvalid(Char, ch) # utf8 category constants const UTF8PROC_CATEGORY_CN = 0 diff --git a/doc/manual/strings.rst b/doc/manual/strings.rst index 15fcfe8859e5b..8969095c609ce 100644 --- a/doc/manual/strings.rst +++ b/doc/manual/strings.rst @@ -99,14 +99,14 @@ convert an integer value back to a :obj:`Char` just as easily: Not all integer values are valid Unicode code points, but for performance, the :func:`Char` conversion does not check that every character value is valid. If you want to check that each converted value is a -valid code point, use the :func:`is_valid_char` function: +valid code point, use the :func:`isvalid` function: .. doctest:: julia> Char(0x110000) '\U110000' - julia> is_valid_char(0x110000) + julia> isvalid(Char, 0x110000) false As of this writing, the valid Unicode code points are ``U+00`` through diff --git a/doc/stdlib/strings.rst b/doc/stdlib/strings.rst index 4a88a4fadbf43..b05d50f3fb72f 100644 --- a/doc/stdlib/strings.rst +++ b/doc/stdlib/strings.rst @@ -109,17 +109,19 @@ even though they may contain more than one codepoint; for example a letter combined with an accent mark is a single grapheme.) -.. function:: is_valid_ascii(s) -> Bool +.. function:: isvalid(value) -> Bool - Returns true if the argument (``ASCIIString``, ``UTF8String``, or byte vector) is valid ASCII, false otherwise. + Returns true if the given value is valid for its type, + which currently can be one of ``Char``, ``ASCIIString``, ``UTF8String``, ``UTF16String``, or ``UTF32String`` -.. function:: is_valid_utf8(s) -> Bool +.. function:: isvalid(T, value) -> Bool - Returns true if the argument (``ASCIIString``, ``UTF8String``, or byte vector) is valid UTF-8, false otherwise. - -.. function:: is_valid_char(c) -> Bool - - Returns true if the given char or integer is a valid Unicode code point. + Returns true if the given value is valid for that type. + Types currently can be ``Char``, ``ASCIIString``, ``UTF8String``, ``UTF16String``, or ``UTF32String`` + Values for ``Char`` can be of type ``Char`` or ``UInt32`` + Values for ``ASCIIString`` and ``UTF8String`` can be of that type, or ``Vector{UInt8}`` + Values for ``UTF16String`` can be ``UTF16String`` or ``Vector{UInt16}`` + Values for ``UTF32String`` can be ``UTF32String``, ``Vector{Char}`` or ``Vector{UInt32}`` .. function:: is_assigned_char(c) -> Bool @@ -379,10 +381,6 @@ Create a string from the address of a NUL-terminated UTF-16 string. A copy is made; the pointer can be safely freed. If ``length`` is specified, the string does not have to be NUL-terminated. -.. function:: is_valid_utf16(s) -> Bool - - Returns true if the argument (``UTF16String`` or ``UInt16`` array) is valid UTF-16. - .. function:: utf32(s) Create a UTF-32 string from a byte array, array of ``UInt32``, or diff --git a/test/strings.jl b/test/strings.jl index 9e0ae6a0c5135..1f520aa7d4eaf 100644 --- a/test/strings.jl +++ b/test/strings.jl @@ -1281,44 +1281,106 @@ end @test isxdigit("a") == true @test isxdigit("g") == false -@test is_valid_ascii("is_valid_ascii") == true -@test is_valid_ascii("Σ_not_valid_ascii") == false -@test is_valid_char('a') == true -@test is_valid_char('\x00') == true -@test is_valid_char(0xd800) == false - -@test is_valid_utf16(utf16("a")) == true -@test is_valid_utf16(UInt16[0xd800,0]) == false -# TODO is_valid_utf8 - # Issue #11140 -@test is_valid_utf32(utf32("a")) == true -@test is_valid_utf32(utf32("\x00")) == true -@test is_valid_utf32(UInt32[0xd800,0]) == false +@test isvalid(utf32("a")) == true +@test isvalid(utf32("\x00")) == true +@test isvalid(UTF32String, UInt32[0xd800,0]) == false + +# Issue #11241 + +@test isvalid(ASCIIString, "is_valid_ascii") == true +@test isvalid(ASCIIString, "Σ_not_valid_ascii") == false + +# test all edge conditions +for (val, pass) in ( + (0, true), (0xd7ff, true), + (0xd800, false), (0xdfff, false), + (0xe000, true), (0xffff, true), + (0x10000, true), (0x10ffff, true), + (0x110000, false) + ) + @test isvalid(Char, val) == pass +end +for (val, pass) in ( + (b"\x00", true), + (b"\x7f", true), + (b"\x80", false), + (b"\xbf", false), + (b"\xc0", false), + (b"\xff", false), + (b"\xc0\x80", false), + (b"\xc1\x80", false), + (b"\xc2\x80", true), + (b"\xc2\xc0", false), + (b"\xed\x9f\xbf", true), + (b"\xed\xa0\x80", false), + (b"\xed\xbf\xbf", false), + (b"\xee\x80\x80", true), + (b"\xef\xbf\xbf", true), + (b"\xf0\x90\x80\x80", true), + (b"\xf4\x8f\xbf\xbf", true), + (b"\xf4\x90\x80\x80", false), + (b"\xf5\x80\x80\x80", false), + (b"\ud800\udc00", false), + (b"\udbff\udfff", false), + (b"\ud800\u0100", false), + (b"\udc00\u0100", false), + (b"\udc00\ud800", false) + ) + @test isvalid(UTF8String, val) == pass +end +for (val, pass) in ( + (UInt16[0x0000], true), + (UInt16[0xd7ff,0], true), + (UInt16[0xd800,0], false), + (UInt16[0xdfff,0], false), + (UInt16[0xe000,0], true), + (UInt16[0xffff,0], true), + (UInt16[0xd800,0xdc00,0], true), + (UInt16[0xdbff,0xdfff,0], true), + (UInt16[0xd800,0x0100,0], false), + (UInt16[0xdc00,0x0100,0], false), + (UInt16[0xdc00,0xd800,0], false) + ) + @test isvalid(UTF16String, val) == pass +end +for (val, pass) in ( + (UInt32[0x0000], true), + (UInt32[0xd7ff,0], true), + (UInt32[0xd800,0], false), + (UInt32[0xdfff,0], false), + (UInt32[0xe000,0], true), + (UInt32[0xffff,0], true), + (UInt32[0x100000,0], true), + (UInt32[0x10ffff,0], true), + (UInt32[0x110000,0], false), + ) + @test isvalid(UTF32String, val) == pass +end # Issue #11203 -@test is_valid_ascii(UInt8[]) == true -@test is_valid_utf8(UInt8[]) == true -@test is_valid_utf16(UInt16[]) == true -@test is_valid_utf32(UInt32[]) == true +@test isvalid(ASCIIString,UInt8[]) == true +@test isvalid(UTF8String, UInt8[]) == true +@test isvalid(UTF16String,UInt16[]) == true +@test isvalid(UTF32String,UInt32[]) == true # Check UTF-8 characters # Check ASCII range (true), # then single continuation bytes and lead bytes with no following continuation bytes (false) for (rng,flg) in ((0:0x7f, true), (0x80:0xff, false)) for byt in rng - @test is_valid_utf8(UInt8[byt]) == flg + @test isvalid(UTF8String, UInt8[byt]) == flg end end # Check overlong lead bytes for 2-character sequences (false) for byt = 0xc0:0xc1 - @test is_valid_utf8(UInt8[byt,0x80]) == false + @test isvalid(UTF8String, UInt8[byt,0x80]) == false end # Check valid lead-in to two-byte sequences (true) for byt = 0xc2:0xdf for (rng,flg) in ((0x00:0x7f, false), (0x80:0xbf, true), (0xc0:0xff, false)) for cont in rng - @test is_valid_utf8(UInt8[byt, cont]) == flg + @test isvalid(UTF8String, UInt8[byt, cont]) == flg end end end @@ -1326,11 +1388,11 @@ end for r1 in (0xe0:0xec, 0xee:0xef) for byt = r1 # Check for short sequence - @test is_valid_utf8(UInt8[byt]) == false + @test isvalid(UTF8String, UInt8[byt]) == false for (rng,flg) in ((0x00:0x7f, false), (0x80:0xbf, true), (0xc0:0xff, false)) for cont in rng - @test is_valid_utf8(UInt8[byt, cont]) == false - @test is_valid_utf8(UInt8[byt, cont, 0x80]) == flg + @test isvalid(UTF8String, UInt8[byt, cont]) == false + @test isvalid(UTF8String, UInt8[byt, cont, 0x80]) == flg end end end @@ -1339,8 +1401,8 @@ end # Check for short sequence, or start of surrogate pair for (rng,flg) in ((0x00:0x7f, false), (0x80:0x9f, true), (0xa0:0xff, false)) for cont in rng - @test is_valid_utf8(UInt8[0xed, cont]) == false - @test is_valid_utf8(UInt8[0xed, cont, 0x80]) == flg + @test isvalid(UTF8String, UInt8[0xed, cont]) == false + @test isvalid(UTF8String, UInt8[0xed, cont, 0x80]) == flg end end # Check valid four-byte sequences @@ -1354,22 +1416,22 @@ for byt = 0xf0:0xf4 end for (rng,flg) in r0 for cont in rng - @test is_valid_utf8(UInt8[byt, cont]) == false - @test is_valid_utf8(UInt8[byt, cont, 0x80]) == false - @test is_valid_utf8(UInt8[byt, cont, 0x80, 0x80]) == flg + @test isvalid(UTF8String, UInt8[byt, cont]) == false + @test isvalid(UTF8String, UInt8[byt, cont, 0x80]) == false + @test isvalid(UTF8String, UInt8[byt, cont, 0x80, 0x80]) == flg end end end # Check five-byte sequences, should be invalid for byt = 0xf8:0xfb - @test is_valid_utf8(UInt8[byt, 0x80, 0x80, 0x80, 0x80]) == false + @test isvalid(UTF8String, UInt8[byt, 0x80, 0x80, 0x80, 0x80]) == false end # Check six-byte sequences, should be invalid for byt = 0xfc:0xfd - @test is_valid_utf8(UInt8[byt, 0x80, 0x80, 0x80, 0x80, 0x80]) == false + @test isvalid(UTF8String, UInt8[byt, 0x80, 0x80, 0x80, 0x80, 0x80]) == false end # Check seven-byte sequences, should be invalid -@test is_valid_utf8(UInt8[0xfe, 0x80, 0x80, 0x80, 0x80, 0x80]) == false +@test isvalid(UTF8String, UInt8[0xfe, 0x80, 0x80, 0x80, 0x80, 0x80]) == false # This caused JuliaLang/JSON.jl#82 @test first('\x00':'\x7f') === '\x00' From 18fa555fd8f0c95dc5bf9164e1fd87ca15dcf9e9 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 15 May 2015 22:54:26 -0400 Subject: [PATCH 023/181] remove jl_static_eval special-case for dlsym/dlopen this was a deprecation to support efficient code generation for ccall(dlsym(x,dlopen(y)),...) from pre-0.1 this syntax is not encouraged and has not been in use for several years --- src/codegen.cpp | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 0b05c36afb753..5a0a71c4673da 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1286,27 +1286,7 @@ jl_value_t *jl_static_eval(jl_value_t *ex, void *ctx_, jl_module_t *mod, jl_value_t *f = jl_static_eval(jl_exprarg(e,0),ctx,mod,sp,ast,sparams,allow_alloc); if (f && jl_is_function(f)) { jl_fptr_t fptr = ((jl_function_t*)f)->fptr; - if (fptr == &jl_apply_generic) { - if (f == jl_get_global(jl_base_module, jl_symbol("dlsym")) || - f == jl_get_global(jl_base_module, jl_symbol("dlopen"))) { - size_t i; - size_t n = jl_array_dim0(e->args); - jl_value_t **v; - JL_GC_PUSHARGS(v, n); - v[0] = f; - for (i = 1; i < n; i++) { - v[i] = jl_static_eval(jl_exprarg(e,i),ctx,mod,sp,ast,sparams,allow_alloc); - if (v[i] == NULL) { - JL_GC_POP(); - return NULL; - } - } - jl_value_t *result = jl_apply_generic(f, v+1, (uint32_t)n-1); - JL_GC_POP(); - return result; - } - } - else if (jl_array_dim0(e->args) == 3 && fptr == &jl_f_get_field) { + if (jl_array_dim0(e->args) == 3 && fptr == &jl_f_get_field) { m = (jl_module_t*)jl_static_eval(jl_exprarg(e,1),ctx,mod,sp,ast,sparams,allow_alloc); s = (jl_sym_t*)jl_static_eval(jl_exprarg(e,2),ctx,mod,sp,ast,sparams,allow_alloc); if (m && jl_is_module(m) && s && jl_is_symbol(s)) { From 63849fd1685c65444e5a0cb13c58f20f2e1a5402 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 15 May 2015 23:13:12 -0400 Subject: [PATCH 024/181] redefine TopNode so that there can be multiple independent top modules making inference separate from base required modifying the definition of TopNode to be more general, since Base may not even exist at points and it is desirable for Core.Inference to be wholly separate from Base. rather than special-casing Base, this introduces the concept that any module can indicate that it is valid as a top module and will define appropriate functions, as expected by the julia parser, to make this legal. At the start of the module definition, modules can ccall jl_set_istopmod(isprimary) to indicate this. The primary top module will be used to resolve the top module for any code that is not contained in another top module. Only one module can be the primary top module at a time, typically it will be Base. --- base/boot.jl | 2 + base/inference.jl | 99 +++++++++++++++++++++++++------------------- base/sysimg.jl | 1 + src/dump.c | 16 ++++--- src/gf.c | 2 - src/init.c | 1 + src/julia-syntax.scm | 2 +- src/julia.h | 4 +- src/julia_internal.h | 1 + src/module.c | 14 +++++++ src/toplevel.c | 14 ++++--- 11 files changed, 98 insertions(+), 58 deletions(-) diff --git a/base/boot.jl b/base/boot.jl index d02cba7844871..51b41d4e51a98 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -296,3 +296,5 @@ convert(::Type{Any}, x::ANY) = x convert{T}(::Type{T}, x::T) = x cconvert(T::Type, x) = convert(T, x) unsafe_convert{T}(::Type{T}, x::T) = x + +ccall(:jl_set_istopmod, Void, (Bool,), true) diff --git a/base/inference.jl b/base/inference.jl index 8d1b4f294c2e1..dd49144dcab86 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -82,7 +82,7 @@ function _iisconst(s::Symbol) isdefined(m,s) && (ccall(:jl_is_const, Int32, (Any, Any), m, s) != 0) end _iisconst(s::SymbolNode) = _iisconst(s.name) -_iisconst(s::TopNode) = isconst(_basemod(), s.name) +_iisconst(s::TopNode) = isconst(_topmod(), s.name) _iisconst(x::Expr) = false _iisconst(x::ANY) = true @@ -91,12 +91,18 @@ _ieval(x::ANY) = (inference_stack::CallStack).mod, x, C_NULL, 0) _iisdefined(x::ANY) = isdefined((inference_stack::CallStack).mod, x) -function _basemod() +function _topmod() m = (inference_stack::CallStack).mod - if m === Core || m === Base - return m + return ccall(:jl_base_relative_to, Any, (Any,), m)::Module +end + +function istopfunction(topmod, f, sym) + if isdefined(Main, :Base) && isdefined(Main.Base, sym) && f === getfield(Main.Base, sym) + return true + elseif isdefined(topmod, sym) && f === getfield(topmod, sym) + return true end - return Main.Base + return false end cmp_tfunc = (x,y)->Bool @@ -489,7 +495,7 @@ end function isconstantfunc(f::ANY, sv::StaticVarInfo) if isa(f,TopNode) - m = _basemod() + m = _topmod() return isconst(m, f.name) && isdefined(m, f.name) && f end if isa(f,GlobalRef) @@ -583,22 +589,22 @@ end function abstract_call_gf(f, fargs, argtype, e) argtypes = argtype.parameters + tm = _topmod() if length(argtypes)>1 && (argtypes[1] <: Tuple) && argtypes[2]===Int # allow tuple indexing functions to take advantage of constant # index arguments. - if f === Main.Base.getindex + if istopfunction(tm, f, :getindex) isa(e,Expr) && (e.head = :call1) return getfield_tfunc(fargs, argtypes[1], argtypes[2])[1] - elseif f === Main.Base.next + elseif istopfunction(tm, f, :next) isa(e,Expr) && (e.head = :call1) return Tuple{getfield_tfunc(fargs, argtypes[1], argtypes[2])[1], Int} - elseif f === Main.Base.indexed_next + elseif istopfunction(tm, f, :indexed_next) isa(e,Expr) && (e.head = :call1) return Tuple{getfield_tfunc(fargs, argtypes[1], argtypes[2])[1], Int} end end - if (isdefined(Main.Base,:promote_type) && f === Main.Base.promote_type) || - (isdefined(Main.Base,:typejoin) && f === Main.Base.typejoin) + if istopfunction(tm, f, :promote_type) || istopfunction(tm, f, :typejoin) la = length(argtypes) c = cell(la) for i = 1:la @@ -609,7 +615,7 @@ function abstract_call_gf(f, fargs, argtype, e) return Type end end - if isdefined(Main.Base,:promote_type) && f === Main.Base.promote_type + if istopfunction(tm, f, :promote_type) try RT = Type{f(c...)} isa(e,Expr) && (e.head = :call1) @@ -676,20 +682,22 @@ function abstract_call_gf(f, fargs, argtype, e) sp = sp.prev end ls = length(sig.parameters) - if limit && ls > lsig+1 && !(isdefined(Main.Base,:promote_typeof) && f === Main.Base.promote_typeof) - fst = sig.parameters[lsig+1] - allsame = true - # allow specializing on longer arglists if all the trailing - # arguments are the same, since there is no exponential - # blowup in this case. - for i = lsig+2:ls - if sig.parameters[i] != fst - allsame = false - break + if limit && ls > lsig+1 + if !istopfunction(tm, f, :promote_typeof) + fst = sig.parameters[lsig+1] + allsame = true + # allow specializing on longer arglists if all the trailing + # arguments are the same, since there is no exponential + # blowup in this case. + for i = lsig+2:ls + if sig.parameters[i] != fst + allsame = false + break + end + end + if !allsame + sig = limit_tuple_type_n(sig, lsig+1) end - end - if !allsame - sig = limit_tuple_type_n(sig, lsig+1) end end #print(m,"\n") @@ -899,7 +907,7 @@ function abstract_eval_call(e, vtypes, sv::StaticVarInfo) end return Any end - #print("call ", e.args[1], argtypes, " ") + #print("call ", e.args[1], argtypes, "\n\n") f = _ieval(func) return abstract_call(f, fargs, argtypes, vtypes, sv, e) end @@ -908,7 +916,7 @@ function abstract_eval(e::ANY, vtypes, sv::StaticVarInfo) if isa(e,QuoteNode) return typeof((e::QuoteNode).value) elseif isa(e,TopNode) - return abstract_eval_global(_basemod(), (e::TopNode).name) + return abstract_eval_global(_topmod(), (e::TopNode).name) elseif isa(e,Symbol) return abstract_eval_symbol(e::Symbol, vtypes, sv) elseif isa(e,SymbolNode) @@ -1917,8 +1925,8 @@ function resolve_relative(sym, locals, args, from, to, orig) if const_to && is(eval(from,sym), eval(to,sym)) return orig end - m = _basemod() - if is(from,m) || is(from,Core) + m = _topmod() + if is(from, m) || is(from, Core) return TopNode(sym) end end @@ -2003,7 +2011,7 @@ function exprtype(x::ANY, sv::StaticVarInfo) elseif isa(x,GenSym) return abstract_eval_gensym(x::GenSym, sv) elseif isa(x,TopNode) - return abstract_eval_global(_basemod(), (x::TopNode).name) + return abstract_eval_global(_topmod(), (x::TopNode).name) elseif isa(x,Symbol) sv = inference_stack.sv if is_local(sv, x::Symbol) @@ -2180,16 +2188,16 @@ function inlineable(f::ANY, e::Expr, atype::ANY, sv::StaticVarInfo, enclosing_as # remove redundant unbox return (e.args[3],()) end - if isdefined(Main.Base,:isbits) && is(f,Main.Base.isbits) && - length(atypes)==1 && isType(atypes[1]) && effect_free(argexprs[1],sv,true) && - isleaftype(atypes[1].parameters[1]) + topmod = _topmod() + if istopfunction(topmod, f, :isbits) && length(atypes)==1 && isType(atypes[1]) && + effect_free(argexprs[1],sv,true) && isleaftype(atypes[1].parameters[1]) return (isbits(atypes[1].parameters[1]),()) end # special-case inliners for known pure functions that compute types if isType(e.typ) if (is(f,apply_type) || is(f,fieldtype) || - (isdefined(Main.Base,:typejoin) && is(f,Main.Base.typejoin)) || - (isdefined(Main.Base,:promote_type) && is(f,Main.Base.promote_type))) && + istopfunction(topmod, f, :typejoin) || + istopfunction(topmod, f, :promote_type)) && isleaftype(e.typ.parameters[1]) return (e.typ.parameters[1],()) end @@ -2265,7 +2273,9 @@ function inlineable(f::ANY, e::Expr, atype::ANY, sv::StaticVarInfo, enclosing_as nm = length(methargs) if !(atype <: metharg) incompletematch = true - if !inline_incompletematch_allowed + if !inline_incompletematch_allowed || !isdefined(Main,:Base) + # provide global disable if this optimization is not desirable + # need Main.Base defined for MethodError return NF end else @@ -2439,7 +2449,7 @@ function inlineable(f::ANY, e::Expr, atype::ANY, sv::StaticVarInfo, enclosing_as argexprs2 = t.args icall = LabelNode(label_counter(body.args)+1) partmatch = Expr(:gotoifnot, false, icall.label) - thrw = Expr(:call, :throw, Expr(:call, TopNode(:MethodError), Expr(:call, top_tuple, e.args[1], QuoteNode(:inline)), t)) + thrw = Expr(:call, :throw, Expr(:call, GlobalRef(Main.Base,:MethodError), Expr(:call, top_tuple, e.args[1], QuoteNode(:inline)), t)) thrw.typ = Bottom end @@ -2712,7 +2722,7 @@ function mk_tuplecall(args, sv::StaticVarInfo) e end -const basenumtype = Union(Int32,Int64,Float32,Float64,Complex64,Complex128,Rational) +const corenumtype = Union(Int32,Int64,Float32,Float64) function inlining_pass(e::Expr, sv, ast) if e.head == :method @@ -2814,17 +2824,20 @@ function inlining_pass(e::Expr, sv, ast) e.args = Any[is_global(sv,:call) ? (:call) : GlobalRef((inference_stack::CallStack).mod, :call), e.args...] end - if is(f, ^) || is(f, .^) + if isdefined(Main, :Base) && + ((isdefined(Main.Base, :^) && is(f, Main.Base.(:^))) || + (isdefined(Main.Base, :.^) && is(f, Main.Base.(:.^)))) if length(e.args) == 3 && isa(e.args[3],Union(Int32,Int64)) a1 = e.args[2] + basenumtype = Union(corenumtype, Main.Base.Complex64, Main.Base.Complex128, Main.Base.Rational) if isa(a1,basenumtype) || ((isa(a1,Symbol) || isa(a1,SymbolNode) || isa(a1,GenSym)) && exprtype(a1,sv) <: basenumtype) if e.args[3]==2 - e.args = Any[TopNode(:*), a1, a1] - f = * + e.args = Any[GlobalRef(Main.Base,:*), a1, a1] + f = Main.Base.(:*) elseif e.args[3]==3 - e.args = Any[TopNode(:*), a1, a1, a1] - f = * + e.args = Any[GlobalRef(Main.Base,:*), a1, a1, a1] + f = Main.Base.(:*) end end end diff --git a/base/sysimg.jl b/base/sysimg.jl index 5d16fd0160052..fd8c265be4e16 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -7,6 +7,7 @@ baremodule Base using Core: Intrinsics, arraylen, arrayref, arrayset, arraysize, _expr, kwcall, _apply, typeassert, apply_type, svec +ccall(:jl_set_istopmod, Void, (Bool,), true) include = Core.include diff --git a/src/dump.c b/src/dump.c index f3fb9c9cc5d46..42d9ee702be9c 100644 --- a/src/dump.c +++ b/src/dump.c @@ -502,6 +502,7 @@ static void jl_serialize_module(ios_t *s, jl_module_t *m) } } jl_serialize_value(s, m->constant_table); + write_uint8(s, m->istopmod); write_uint64(s, m->uuid); } @@ -1253,6 +1254,7 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t } m->constant_table = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&m->constant_table); if (m->constant_table != NULL) gc_wb(m, m->constant_table); + m->istopmod = read_uint8(s); m->uuid = read_uint64(s); return (jl_value_t*)m; } @@ -1424,9 +1426,11 @@ DLLEXPORT void jl_save_system_image(const char *fname) // orphan old Base module if present jl_base_module = (jl_module_t*)jl_get_global(jl_main_module, jl_symbol("Base")); - jl_idtable_type = jl_get_global(jl_base_module, jl_symbol("ObjectIdDict")); + jl_idtable_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("ObjectIdDict")) : NULL; jl_serialize_value(&f, jl_main_module); + jl_serialize_value(&f, jl_top_module); + jl_serialize_value(&f, jl_typeinf_func); // ensure everything in deser_tag is reassociated with its GlobalValue ptrint_t i=2; @@ -1527,7 +1531,9 @@ void jl_restore_system_image(const char *fname) datatype_list = jl_alloc_cell_1d(0); jl_main_module = (jl_module_t*)jl_deserialize_value(&f, NULL); + jl_top_module = (jl_module_t*)jl_deserialize_value(&f, NULL); jl_internal_main_module = jl_main_module; + jl_typeinf_func = (jl_function_t*)jl_deserialize_value(&f, NULL); jl_core_module = (jl_module_t*)jl_get_global(jl_main_module, jl_symbol("Core")); jl_base_module = (jl_module_t*)jl_get_global(jl_main_module, @@ -1554,11 +1560,11 @@ void jl_restore_system_image(const char *fname) datatype_list = NULL; jl_get_builtin_hooks(); - jl_get_system_hooks(); - jl_get_uv_hooks(); + if (jl_base_module) { + jl_get_system_hooks(); + jl_get_uv_hooks(); + } jl_boot_file_loaded = 1; - jl_typeinf_func = (jl_function_t*)jl_get_global(jl_base_module, - jl_symbol("typeinf_ext")); jl_init_box_caches(); jl_set_t_uid_ctr(read_int32(&f)); diff --git a/src/gf.c b/src/gf.c index a94bc15a5de2a..794ab97c0c6b8 100644 --- a/src/gf.c +++ b/src/gf.c @@ -399,8 +399,6 @@ jl_function_t *jl_method_cache_insert(jl_methtable_t *mt, jl_tupletype_t *type, return jl_method_list_insert(pml, type, method, jl_emptysvec, 0, 0, cache_array ? cache_array : (jl_value_t*)mt)->func; } -extern jl_function_t *jl_typeinf_func; - /* run type inference on lambda "li" in-place, for given argument types. "def" is the original method definition of which this is an instance; diff --git a/src/init.c b/src/init.c index f494c6cbc5754..335b4773a84ab 100644 --- a/src/init.c +++ b/src/init.c @@ -1029,6 +1029,7 @@ void _julia_init(JL_IMAGE_SEARCH rel) if (!jl_options.image_file) { jl_core_module = jl_new_module(jl_symbol("Core")); + jl_top_module = jl_core_module; jl_init_intrinsic_functions(); jl_init_primitives(); diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 42f672e9fc8cf..2e2b536905d05 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1684,7 +1684,7 @@ (expand-forms (lower-tuple-assignment (list lhs st) - `(call (|.| (top Base) (quote indexed_next)) + `(call (top indexed_next) ,xx ,(+ i 1) ,st)))) (iota (length lhss)) lhss) diff --git a/src/julia.h b/src/julia.h index 220094791f51a..a3311ea98028a 100644 --- a/src/julia.h +++ b/src/julia.h @@ -321,6 +321,7 @@ typedef struct _jl_module_t { arraylist_t usings; // modules with all bindings potentially imported jl_array_t *constant_table; jl_function_t *call_func; // cached lookup of `call` within this module + uint8_t istopmod; uint64_t uuid; } jl_module_t; @@ -1069,6 +1070,7 @@ extern DLLEXPORT jl_module_t *jl_main_module; extern DLLEXPORT jl_module_t *jl_internal_main_module; extern DLLEXPORT jl_module_t *jl_core_module; extern DLLEXPORT jl_module_t *jl_base_module; +extern DLLEXPORT jl_module_t *jl_top_module; extern DLLEXPORT jl_module_t *jl_current_module; DLLEXPORT jl_module_t *jl_new_module(jl_sym_t *name); // get binding for reading @@ -1229,7 +1231,7 @@ DLLEXPORT jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t * jl_value_t *jl_static_eval(jl_value_t *ex, void *ctx_, jl_module_t *mod, jl_value_t *sp, jl_expr_t *ast, int sparams, int allow_alloc); int jl_is_toplevel_only_expr(jl_value_t *e); -jl_module_t *jl_base_relative_to(jl_module_t *m); +DLLEXPORT jl_module_t *jl_base_relative_to(jl_module_t *m); void jl_type_infer(jl_lambda_info_t *li, jl_tupletype_t *argtypes, jl_lambda_info_t *def); jl_function_t *jl_method_lookup_by_type(jl_methtable_t *mt, jl_tupletype_t *types, diff --git a/src/julia_internal.h b/src/julia_internal.h index d836bb3442cec..2474f70bf1017 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -11,6 +11,7 @@ extern "C" { #endif extern size_t jl_page_size; +extern jl_function_t *jl_typeinf_func; STATIC_INLINE jl_value_t *newobj(jl_value_t *type, size_t nfields) { diff --git a/src/module.c b/src/module.c index a1cbbb857f09f..d4e3b50123b1a 100644 --- a/src/module.c +++ b/src/module.c @@ -14,6 +14,7 @@ extern "C" { jl_module_t *jl_main_module=NULL; jl_module_t *jl_core_module=NULL; jl_module_t *jl_base_module=NULL; +jl_module_t *jl_top_module=NULL; jl_module_t *jl_current_module=NULL; jl_module_t *jl_new_module(jl_sym_t *name) @@ -26,6 +27,7 @@ jl_module_t *jl_new_module(jl_sym_t *name) m->parent = NULL; m->constant_table = NULL; m->call_func = NULL; + m->istopmod = 0; m->uuid = uv_now(uv_default_loop()); htable_new(&m->bindings, 0); arraylist_new(&m->usings, 0); @@ -48,6 +50,18 @@ DLLEXPORT jl_value_t *jl_f_new_module(jl_sym_t *name, uint8_t std_imports) return (jl_value_t*)m; } +DLLEXPORT void jl_set_istopmod(uint8_t isprimary) +{ + jl_current_module->istopmod = 1; + if (isprimary) + jl_top_module = jl_current_module; +} + +DLLEXPORT uint8_t jl_istopmod(jl_module_t *mod) +{ + return mod->istopmod; +} + static jl_binding_t *new_binding(jl_sym_t *name) { assert(jl_is_symbol(name)); diff --git a/src/toplevel.c b/src/toplevel.c index 86ff1ffbb0078..622082700c31c 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -205,11 +205,14 @@ static int is_intrinsic(jl_module_t *m, jl_sym_t *s) // this is only needed because of the bootstrapping process: // - initially Base doesn't exist and top === Core // - later, it refers to either old Base or new Base -jl_module_t *jl_base_relative_to(jl_module_t *m) +DLLEXPORT jl_module_t *jl_base_relative_to(jl_module_t *m) { - if (m==jl_core_module || m==jl_old_base_module) - return m; - return (jl_base_module==NULL) ? jl_core_module : jl_base_module; + while (m != jl_main_module) { + if (m->istopmod) + return m; + m = m->parent; + } + return jl_top_module; } int jl_has_intrinsics(jl_expr_t *e, jl_module_t *m) @@ -582,8 +585,7 @@ jl_value_t *jl_parse_eval_all(const char *fname, size_t len) jl_value_t *jl_load(const char *fname) { - if (jl_current_module == jl_base_module) { - //This deliberatly uses ios, because stdio initialization has been moved to Julia + if (jl_current_module->istopmod) { jl_printf(JL_STDOUT, "%s\r\n", fname); #ifdef _OS_WINDOWS_ uv_run(uv_default_loop(), (uv_run_mode)1); From ae6acf4715379e9e97a0e4ee41117622b4380a1f Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 15 May 2015 23:23:00 -0400 Subject: [PATCH 025/181] rearrange base to make several files a bit more stand-alone --- base/abstractarray.jl | 64 ++++++------ base/array.jl | 28 ------ base/base.jl | 220 ----------------------------------------- base/complex.jl | 61 +++++++++++- base/dict.jl | 9 ++ base/error.jl | 18 ++-- base/essentials.jl | 222 ++++++++++++++++++++++++++++++++++++++++++ base/float.jl | 52 ++++++++-- base/hashing.jl | 92 ----------------- base/intset.jl | 13 +++ base/refpointer.jl | 34 +++---- base/set.jl | 9 ++ base/sysimg.jl | 32 +++--- 13 files changed, 433 insertions(+), 421 deletions(-) create mode 100644 base/essentials.jl diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 387832999a29c..8e2af74fb807a 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -390,27 +390,6 @@ convert{T,S,N}(::Type{AbstractArray{T }}, A::AbstractArray{S,N}) = convert(Abst convert{T,N}(::Type{Array}, A::AbstractArray{T,N}) = convert(Array{T,N}, A) -big{T<:FloatingPoint,N}(x::AbstractArray{T,N}) = convert(AbstractArray{BigFloat,N}, x) -big{T<:FloatingPoint,N}(x::AbstractArray{Complex{T},N}) = convert(AbstractArray{Complex{BigFloat},N}, x) -big{T<:Integer,N}(x::AbstractArray{T,N}) = convert(AbstractArray{BigInt,N}, x) - -float{T<:FloatingPoint}(x::AbstractArray{T}) = x -complex{T<:Complex}(x::AbstractArray{T}) = x - -float{T<:Integer64}(x::AbstractArray{T}) = convert(AbstractArray{typeof(float(zero(T)))}, x) -complex{T<:Union(Integer64,Float64,Float32,Float16)}(x::AbstractArray{T}) = - convert(AbstractArray{typeof(complex(zero(T)))}, x) - -function float(A::AbstractArray) - cnv(x) = convert(FloatingPoint,x) - map_promote(cnv, A) -end - -function complex(A::AbstractArray) - cnv(x) = convert(Complex,x) - map_promote(cnv, A) -end - full(x::AbstractArray) = x map(::Type{Integer}, a::Array) = map!(Integer, similar(a,typeof(Integer(one(eltype(a))))), a) @@ -423,14 +402,6 @@ map{T<:Real}(::Type{T}, r::StepRange) = T(r.start):T(r.step):T(last(r)) map{T<:Real}(::Type{T}, r::UnitRange) = T(r.start):T(last(r)) map{T<:FloatingPoint}(::Type{T}, r::FloatRange) = FloatRange(T(r.start), T(r.step), r.len, T(r.divisor)) -for fn in (:float,:big) - @eval begin - $fn(r::StepRange) = $fn(r.start):$fn(r.step):$fn(last(r)) - $fn(r::UnitRange) = $fn(r.start):$fn(last(r)) - $fn(r::FloatRange) = FloatRange($fn(r.start), $fn(r.step), r.len, $fn(r.divisor)) - end -end - ## Unary operators ## conj{T<:Real}(x::AbstractArray{T}) = x @@ -1424,3 +1395,38 @@ push!(A, a, b) = push!(push!(A, a), b) push!(A, a, b, c...) = push!(push!(A, a, b), c...) unshift!(A, a, b) = unshift!(unshift!(A, b), a) unshift!(A, a, b, c...) = unshift!(unshift!(A, c...), a, b) + +## hashing collections ## + +const hashaa_seed = UInt === UInt64 ? 0x7f53e68ceb575e76 : 0xeb575e76 +const hashrle_seed = UInt == UInt64 ? 0x2aab8909bfea414c : 0xbfea414c +function hash(a::AbstractArray, h::UInt) + h += hashaa_seed + h += hash(size(a)) + + state = start(a) + done(a, state) && return h + x2, state = next(a, state) + done(a, state) && return hash(x2, h) + + x1 = x2 + while !done(a, state) + x1 = x2 + x2, state = next(a, state) + if isequal(x2, x1) + # For repeated elements, use run length encoding + # This allows efficient hashing of sparse arrays + runlength = 2 + while !done(a, state) + x2, state = next(a, state) + isequal(x1, x2) || break + runlength += 1 + end + h += hashrle_seed + h = hash(runlength, h) + end + h = hash(x1, h) + end + !isequal(x2, x1) && (h = hash(x2, h)) + return h +end diff --git a/base/array.jl b/base/array.jl index 1c390e43bf216..b65e3eef87584 100644 --- a/base/array.jl +++ b/base/array.jl @@ -749,7 +749,6 @@ end promote_array_type{Scalar, Arry}(::Type{Scalar}, ::Type{Arry}) = promote_type(Scalar, Arry) promote_array_type{S<:Real, A<:FloatingPoint}(::Type{S}, ::Type{A}) = A -promote_array_type{S<:Union(Complex, Real), AT<:FloatingPoint}(::Type{S}, ::Type{Complex{AT}}) = Complex{AT} promote_array_type{S<:Integer, A<:Integer}(::Type{S}, ::Type{A}) = A promote_array_type{S<:Integer}(::Type{S}, ::Type{Bool}) = S @@ -865,33 +864,6 @@ for f in (:+, :-) end end -## promotion to complex ## - -function complex{S<:Real,T<:Real}(A::Array{S}, B::Array{T}) - if size(A) != size(B); throw(DimensionMismatch()); end - F = similar(A, typeof(complex(zero(S),zero(T)))) - for i in eachindex(A) - @inbounds F[i] = complex(A[i], B[i]) - end - return F -end - -function complex{T<:Real}(A::Real, B::Array{T}) - F = similar(B, typeof(complex(A,zero(T)))) - for i in eachindex(B) - @inbounds F[i] = complex(A, B[i]) - end - return F -end - -function complex{T<:Real}(A::Array{T}, B::Real) - F = similar(A, typeof(complex(zero(T),B))) - for i in eachindex(A) - @inbounds F[i] = complex(A[i], B) - end - return F -end - # use memcmp for lexcmp on byte arrays function lexcmp(a::Array{UInt8,1}, b::Array{UInt8,1}) c = ccall(:memcmp, Int32, (Ptr{UInt8}, Ptr{UInt8}, UInt), diff --git a/base/base.jl b/base/base.jl index 9a19ef6db1ac7..d36e9210266a2 100644 --- a/base/base.jl +++ b/base/base.jl @@ -1,105 +1,5 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license -typealias Callable Union(Function,DataType) - -const Bottom = Union() - -# constructors for Core types in boot.jl -call(T::Type{BoundsError}) = Core.call(T) -call(T::Type{BoundsError}, args...) = Core.call(T, args...) -call(T::Type{DivideError}) = Core.call(T) -call(T::Type{DomainError}) = Core.call(T) -call(T::Type{OverflowError}) = Core.call(T) -call(T::Type{InexactError}) = Core.call(T) -call(T::Type{OutOfMemoryError}) = Core.call(T) -call(T::Type{StackOverflowError}) = Core.call(T) -call(T::Type{UndefRefError}) = Core.call(T) -call(T::Type{UndefVarError}, var::Symbol) = Core.call(T, var) -call(T::Type{InterruptException}) = Core.call(T) -call(T::Type{SymbolNode}, name::Symbol, t::ANY) = Core.call(T, name, t) -call(T::Type{GlobalRef}, modu, name::Symbol) = Core.call(T, modu, name) -call(T::Type{ASCIIString}, d::Array{UInt8,1}) = Core.call(T, d) -call(T::Type{UTF8String}, d::Array{UInt8,1}) = Core.call(T, d) -call(T::Type{TypeVar}, args...) = Core.call(T, args...) -call(T::Type{TypeConstructor}, args...) = Core.call(T, args...) -call(T::Type{Expr}, args::ANY...) = _expr(args...) -call(T::Type{LineNumberNode}, n::Int) = Core.call(T, n) -call(T::Type{LabelNode}, n::Int) = Core.call(T, n) -call(T::Type{GotoNode}, n::Int) = Core.call(T, n) -call(T::Type{QuoteNode}, x::ANY) = Core.call(T, x) -call(T::Type{NewvarNode}, s::Symbol) = Core.call(T, s) -call(T::Type{TopNode}, s::Symbol) = Core.call(T, s) -call(T::Type{Module}, args...) = Core.call(T, args...) -call(T::Type{Task}, f::ANY) = Core.call(T, f) -call(T::Type{GenSym}, n::Int) = Core.call(T, n) -call(T::Type{WeakRef}) = Core.call(T) -call(T::Type{WeakRef}, v::ANY) = Core.call(T, v) - -# The specialization for 1 arg is important -# when running with --inline=no, see #11158 -call{T}(::Type{T}, arg) = convert(T, arg)::T -call{T}(::Type{T}, args...) = convert(T, args...)::T - -convert{T}(::Type{T}, x::T) = x - -convert(::Type{Tuple{}}, ::Tuple{}) = () -convert(::Type{Tuple}, x::Tuple) = x -convert{T}(::Type{Tuple{Vararg{T}}}, x::Tuple) = cnvt_all(T, x...) -cnvt_all(T) = () -cnvt_all(T, x, rest...) = tuple(convert(T,x), cnvt_all(T, rest...)...) - -macro generated(f) - isa(f, Expr) || error("invalid syntax; @generated must be used with a function definition") - if is(f.head, :function) || isdefined(:length) && is(f.head, :(=)) && length(f.args) == 2 && f.args[1].head == :call - f.head = :stagedfunction - return Expr(:escape, f) - else - error("invalid syntax; @generated must be used with a function definition") - end -end - -@generated function tuple_type_head{T<:Tuple}(::Type{T}) - T.parameters[1] -end - -isvarargtype(t::ANY) = isa(t,DataType)&&is((t::DataType).name,Vararg.name) -isvatuple(t::DataType) = (n = length(t.parameters); n > 0 && isvarargtype(t.parameters[n])) -unwrapva(t::ANY) = isvarargtype(t) ? t.parameters[1] : t - -@generated function tuple_type_tail{T<:Tuple}(::Type{T}) - if isvatuple(T) && length(T.parameters) == 1 - return T - end - Tuple{argtail(T.parameters...)...} -end - -argtail(x, rest...) = rest -tail(x::Tuple) = argtail(x...) - -convert{T<:Tuple{Any,Vararg{Any}}}(::Type{T}, x::Tuple{Any, Vararg{Any}}) = - tuple(convert(tuple_type_head(T),x[1]), convert(tuple_type_tail(T), tail(x))...) - -oftype(x,c) = convert(typeof(x),c) - -unsigned(x::Int) = reinterpret(UInt, x) -signed(x::UInt) = reinterpret(Int, x) - -# conversions used by ccall -ptr_arg_cconvert{T}(::Type{Ptr{T}}, x) = cconvert(T, x) -ptr_arg_unsafe_convert{T}(::Type{Ptr{T}}, x) = unsafe_convert(T, x) -ptr_arg_unsafe_convert(::Type{Ptr{Void}}, x) = x - -cconvert(T::Type, x) = convert(T, x) # do the conversion eagerly in most cases -cconvert{P<:Ptr}(::Type{P}, x) = x # but defer the conversion to Ptr to unsafe_convert -unsafe_convert{T}(::Type{T}, x::T) = x # unsafe_convert (like convert) defaults to assuming the convert occurred -unsafe_convert{P<:Ptr}(::Type{P}, x::Ptr) = convert(P, x) - -reinterpret{T,S}(::Type{T}, x::S) = box(T,unbox(S,x)) - -sizeof(x) = Core.sizeof(x) - -abstract IO - type ErrorException <: Exception msg::AbstractString end @@ -166,11 +66,6 @@ end ccall(:jl_get_system_hooks, Void, ()) -# index colon -type Colon -end -const (:) = Colon() - ==(w::WeakRef, v::WeakRef) = isequal(w.value, v.value) ==(w::WeakRef, v) = isequal(w.value, v) ==(w, v::WeakRef) = isequal(w, v.value) @@ -192,27 +87,6 @@ bytestring(str::ByteString) = str identity(x) = x -function append_any(xs...) - # used by apply() and quote - # must be a separate function from append(), since apply() needs this - # exact function. - out = Array(Any, 4) - l = 4 - i = 1 - for x in xs - for y in x - if i > l - ccall(:jl_array_grow_end, Void, (Any, UInt), out, 16) - l += 16 - end - arrayset(out, y, i) - i += 1 - end - end - ccall(:jl_array_del_end, Void, (Any, UInt), out, l-i+1) - out -end - # used by { } syntax function cell_1d(xs::ANY...) n = length(xs) @@ -231,100 +105,6 @@ function cell_2d(nr, nc, xs::ANY...) a end -# simple Array{Any} operations needed for bootstrap -setindex!(A::Array{Any}, x::ANY, i::Real) = arrayset(A, x, to_index(i)) - -function length_checked_equal(args...) - n = length(args[1]) - for i=2:length(args) - if length(args[i]) != n - error("argument dimensions must match") - end - end - n -end - -map(f::Function, a::Array{Any,1}) = Any[ f(a[i]) for i=1:length(a) ] - -function precompile(f::ANY, args::Tuple) - if isa(f,DataType) - args = tuple(Type{f}, args...) - f = f.name.module.call - end - if isgeneric(f) - ccall(:jl_compile_hint, Void, (Any, Any), f, Tuple{args...}) - end -end - -esc(e::ANY) = Expr(:escape, e) - -macro boundscheck(yesno,blk) - # hack: use this syntax since it avoids introducing line numbers - :($(Expr(:boundscheck,yesno)); - $(esc(blk)); - $(Expr(:boundscheck,:pop))) -end - -macro inbounds(blk) - :(@boundscheck false $(esc(blk))) -end - -macro label(name::Symbol) - Expr(:symboliclabel, name) -end - -macro goto(name::Symbol) - Expr(:symbolicgoto, name) -end - -call{T,N}(::Type{Array{T}}, d::NTuple{N,Int}) = - ccall(:jl_new_array, Array{T,N}, (Any,Any), Array{T,N}, d) -call{T}(::Type{Array{T}}, d::Integer...) = Array{T}(convert(Tuple{Vararg{Int}}, d)) - -call{T}(::Type{Array{T}}, m::Integer) = - ccall(:jl_alloc_array_1d, Array{T,1}, (Any,Int), Array{T,1}, m) -call{T}(::Type{Array{T}}, m::Integer, n::Integer) = - ccall(:jl_alloc_array_2d, Array{T,2}, (Any,Int,Int), Array{T,2}, m, n) -call{T}(::Type{Array{T}}, m::Integer, n::Integer, o::Integer) = - ccall(:jl_alloc_array_3d, Array{T,3}, (Any,Int,Int,Int), Array{T,3}, m, n, o) - -# TODO: possibly turn these into deprecations -Array{T,N}(::Type{T}, d::NTuple{N,Int}) = Array{T}(d) -Array{T}(::Type{T}, d::Integer...) = Array{T}(convert(Tuple{Vararg{Int}}, d)) -Array{T}(::Type{T}, m::Integer) = Array{T}(m) -Array{T}(::Type{T}, m::Integer,n::Integer) = Array{T}(m,n) -Array{T}(::Type{T}, m::Integer,n::Integer,o::Integer) = Array{T}(m,n,o) - -# SimpleVector - -function getindex(v::SimpleVector, i::Int) - if !(1 <= i <= length(v)) - throw(BoundsError(v,i)) - end - x = unsafe_load(convert(Ptr{Ptr{Void}},data_pointer_from_objref(v)) + i*sizeof(Ptr)) - x == C_NULL && throw(UndefRefError()) - return unsafe_pointer_to_objref(x) -end - -length(v::SimpleVector) = v.length -endof(v::SimpleVector) = v.length -start(v::SimpleVector) = 1 -next(v::SimpleVector,i) = (v[i],i+1) -done(v::SimpleVector,i) = (i > v.length) -isempty(v::SimpleVector) = (v.length == 0) - -function ==(v1::SimpleVector, v2::SimpleVector) - length(v1)==length(v2) || return false - for i = 1:length(v1) - v1[i] == v2[i] || return false - end - return true -end - -map(f, v::SimpleVector) = Any[ f(v[i]) for i = 1:length(v) ] - -getindex(v::SimpleVector, I::AbstractArray) = svec(Any[ v[i] for i in I ]...) - immutable Nullable{T} isnull::Bool value::T diff --git a/base/complex.jl b/base/complex.jl index 11935b101b704..7ecfd8fe604b5 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -76,8 +76,7 @@ function write(s::IO, z::Complex) write(s,imag(z)) end - -## generic functions of complex numbers ## +## equality and hashing of complex numbers ## ==(z::Complex, w::Complex) = (real(z) == real(w)) & (imag(z) == imag(w)) ==(z::Complex, x::Real) = isreal(z) && real(z) == x @@ -85,6 +84,21 @@ end isequal(z::Complex, w::Complex) = isequal(real(z),real(w)) & isequal(imag(z),imag(w)) +if UInt === UInt64 + const h_imag = 0x32a7a07f3e7cd1f9 +else + const h_imag = 0x3e7cd1f9 +end +const hash_0_imag = hash(0, h_imag) + +function hash(z::Complex, h::UInt) + # TODO: with default argument specialization, this would be better: + # hash(real(z), h $ hash(imag(z), h $ h_imag) $ hash(0, h $ h_imag)) + hash(real(z), h $ hash(imag(z), h_imag) $ hash_0_imag) +end + +## generic functions of complex numbers ## + conj(z::Complex) = Complex(real(z),-imag(z)) abs(z::Complex) = hypot(real(z), imag(z)) abs2(z::Complex) = real(z)*real(z) + imag(z)*imag(z) @@ -710,3 +724,46 @@ end float{T<:FloatingPoint}(z::Complex{T}) = z float(z::Complex) = Complex(float(real(z)), float(imag(z))) @vectorize_1arg Complex float + +## Array operations on complex numbers ## + +complex{T<:Complex}(x::AbstractArray{T}) = x + +complex{T<:Union(Integer64,Float64,Float32,Float16)}(x::AbstractArray{T}) = + convert(AbstractArray{typeof(complex(zero(T)))}, x) + +function complex(A::AbstractArray) + cnv(x) = convert(Complex,x) + map_promote(cnv, A) +end + +big{T<:FloatingPoint,N}(x::AbstractArray{Complex{T},N}) = convert(AbstractArray{Complex{BigFloat},N}, x) + +## promotion to complex ## + +promote_array_type{S<:Union(Complex, Real), AT<:FloatingPoint}(::Type{S}, ::Type{Complex{AT}}) = Complex{AT} + +function complex{S<:Real,T<:Real}(A::Array{S}, B::Array{T}) + if size(A) != size(B); throw(DimensionMismatch()); end + F = similar(A, typeof(complex(zero(S),zero(T)))) + for i in eachindex(A) + @inbounds F[i] = complex(A[i], B[i]) + end + return F +end + +function complex{T<:Real}(A::Real, B::Array{T}) + F = similar(B, typeof(complex(A,zero(T)))) + for i in eachindex(B) + @inbounds F[i] = complex(A, B[i]) + end + return F +end + +function complex{T<:Real}(A::Array{T}, B::Real) + F = similar(A, typeof(complex(zero(T),B))) + for i in eachindex(A) + @inbounds F[i] = complex(A[i], B) + end + return F +end diff --git a/base/dict.jl b/base/dict.jl index fdd97c74f28c5..6fa9413fd175e 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -259,6 +259,15 @@ function ==(l::Associative, r::Associative) true end +const hasha_seed = UInt === UInt64 ? 0x6d35bb51952d5539 : 0x952d5539 +function hash(a::Associative, h::UInt) + h += hasha_seed + for (k,v) in a + h $= hash(k, hash(v)) + end + return h +end + # some support functions _tablesz(x::Integer) = x < 16 ? 16 : one(x)<<((sizeof(x)<<3)-leading_zeros(x-1)) diff --git a/base/error.jl b/base/error.jl index 1dd4d0a065c0a..30cd809b5e755 100644 --- a/base/error.jl +++ b/base/error.jl @@ -18,8 +18,8 @@ ## native julia error handling ## -error(s::AbstractString) = throw(ErrorException(s)) -error(s...) = throw(ErrorException(string(s...))) +error(s::AbstractString) = throw(Main.Base.ErrorException(s)) +error(s...) = throw(Main.Base.ErrorException(Main.Base.string(s...))) rethrow() = ccall(:jl_rethrow, Void, ())::Bottom rethrow(e) = ccall(:jl_rethrow_other, Void, (Any,), e)::Bottom @@ -31,21 +31,21 @@ kwerr(kw) = error("unrecognized keyword argument \"", kw, "\"") ## system error handling ## -systemerror(p, b::Bool) = b ? throw(SystemError(string(p))) : nothing +systemerror(p, b::Bool) = b ? throw(Main.Base.SystemError(string(p))) : nothing ## assertion functions and macros ## -assert(x) = x ? nothing : throw(AssertionError()) +assert(x) = x ? nothing : throw(Main.Base.AssertionError()) macro assert(ex, msgs...) msg = isempty(msgs) ? ex : msgs[1] if !isempty(msgs) && isa(msg, Expr) # message is an expression needing evaluating - msg = :(string($(esc(msg)))) - elseif isdefined(Base, :string) - msg = string(msg) + msg = :(Main.Base.string($(esc(msg)))) + elseif isdefined(Main, :Base) && isdefined(Main.Base, :string) + msg = Main.Base.string(msg) else # string() might not be defined during bootstrap - msg = :(string($(Expr(:quote,msg)))) + msg = :(Main.Base.string($(Expr(:quote,msg)))) end - :($(esc(ex)) ? $(nothing) : throw(AssertionError($msg))) + :($(esc(ex)) ? $(nothing) : throw(Main.Base.AssertionError($msg))) end diff --git a/base/essentials.jl b/base/essentials.jl new file mode 100644 index 0000000000000..45b737ba5315e --- /dev/null +++ b/base/essentials.jl @@ -0,0 +1,222 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + +abstract IO + +typealias Callable Union(Function,DataType) + +const Bottom = Union() + +# constructors for Core types in boot.jl +call(T::Type{BoundsError}) = Core.call(T) +call(T::Type{BoundsError}, args...) = Core.call(T, args...) +call(T::Type{DivideError}) = Core.call(T) +call(T::Type{DomainError}) = Core.call(T) +call(T::Type{OverflowError}) = Core.call(T) +call(T::Type{InexactError}) = Core.call(T) +call(T::Type{OutOfMemoryError}) = Core.call(T) +call(T::Type{StackOverflowError}) = Core.call(T) +call(T::Type{UndefRefError}) = Core.call(T) +call(T::Type{UndefVarError}, var::Symbol) = Core.call(T, var) +call(T::Type{InterruptException}) = Core.call(T) +call(T::Type{SymbolNode}, name::Symbol, t::ANY) = Core.call(T, name, t) +call(T::Type{GlobalRef}, modu, name::Symbol) = Core.call(T, modu, name) +call(T::Type{ASCIIString}, d::Array{UInt8,1}) = Core.call(T, d) +call(T::Type{UTF8String}, d::Array{UInt8,1}) = Core.call(T, d) +call(T::Type{TypeVar}, args...) = Core.call(T, args...) +call(T::Type{TypeConstructor}, args...) = Core.call(T, args...) +call(T::Type{Expr}, args::ANY...) = _expr(args...) +call(T::Type{LineNumberNode}, n::Int) = Core.call(T, n) +call(T::Type{LabelNode}, n::Int) = Core.call(T, n) +call(T::Type{GotoNode}, n::Int) = Core.call(T, n) +call(T::Type{QuoteNode}, x::ANY) = Core.call(T, x) +call(T::Type{NewvarNode}, s::Symbol) = Core.call(T, s) +call(T::Type{TopNode}, s::Symbol) = Core.call(T, s) +call(T::Type{Module}, args...) = Core.call(T, args...) +call(T::Type{Task}, f::ANY) = Core.call(T, f) +call(T::Type{GenSym}, n::Int) = Core.call(T, n) +call(T::Type{WeakRef}) = Core.call(T) +call(T::Type{WeakRef}, v::ANY) = Core.call(T, v) + +# The specialization for 1 arg is important +# when running with --inline=no, see #11158 +call{T}(::Type{T}, arg) = convert(T, arg)::T +call{T}(::Type{T}, args...) = convert(T, args...)::T + +convert{T}(::Type{T}, x::T) = x + +convert(::Type{Tuple{}}, ::Tuple{}) = () +convert(::Type{Tuple}, x::Tuple) = x +convert{T}(::Type{Tuple{Vararg{T}}}, x::Tuple) = cnvt_all(T, x...) +cnvt_all(T) = () +cnvt_all(T, x, rest...) = tuple(convert(T,x), cnvt_all(T, rest...)...) + +macro generated(f) + isa(f, Expr) || error("invalid syntax; @generated must be used with a function definition") + if is(f.head, :function) || isdefined(:length) && is(f.head, :(=)) && length(f.args) == 2 && f.args[1].head == :call + f.head = :stagedfunction + return Expr(:escape, f) + else + error("invalid syntax; @generated must be used with a function definition") + end +end + + +@generated function tuple_type_head{T<:Tuple}(::Type{T}) + T.parameters[1] +end + +isvarargtype(t::ANY) = isa(t,DataType)&&is((t::DataType).name,Vararg.name) +isvatuple(t::DataType) = (n = length(t.parameters); n > 0 && isvarargtype(t.parameters[n])) +unwrapva(t::ANY) = isvarargtype(t) ? t.parameters[1] : t + +@generated function tuple_type_tail{T<:Tuple}(::Type{T}) + if isvatuple(T) && length(T.parameters) == 1 + return T + end + Tuple{argtail(T.parameters...)...} +end + +argtail(x, rest...) = rest +tail(x::Tuple) = argtail(x...) + +convert{T<:Tuple{Any,Vararg{Any}}}(::Type{T}, x::Tuple{Any, Vararg{Any}}) = + tuple(convert(tuple_type_head(T),x[1]), convert(tuple_type_tail(T), tail(x))...) + +oftype(x,c) = convert(typeof(x),c) + +unsigned(x::Int) = reinterpret(UInt, x) +signed(x::UInt) = reinterpret(Int, x) + +# conversions used by ccall +ptr_arg_cconvert{T}(::Type{Ptr{T}}, x) = cconvert(T, x) +ptr_arg_unsafe_convert{T}(::Type{Ptr{T}}, x) = unsafe_convert(T, x) +ptr_arg_unsafe_convert(::Type{Ptr{Void}}, x) = x + +cconvert(T::Type, x) = convert(T, x) # do the conversion eagerly in most cases +cconvert{P<:Ptr}(::Type{P}, x) = x # but defer the conversion to Ptr to unsafe_convert +unsafe_convert{T}(::Type{T}, x::T) = x # unsafe_convert (like convert) defaults to assuming the convert occurred +unsafe_convert{P<:Ptr}(::Type{P}, x::Ptr) = convert(P, x) + +reinterpret{T,S}(::Type{T}, x::S) = box(T,unbox(S,x)) + +sizeof(x) = Core.sizeof(x) + +function append_any(xs...) + # used by apply() and quote + # must be a separate function from append(), since apply() needs this + # exact function. + out = Array(Any, 4) + l = 4 + i = 1 + for x in xs + for y in x + if i > l + ccall(:jl_array_grow_end, Void, (Any, UInt), out, 16) + l += 16 + end + arrayset(out, y, i) + i += 1 + end + end + ccall(:jl_array_del_end, Void, (Any, UInt), out, l-i+1) + out +end + +# simple Array{Any} operations needed for bootstrap +setindex!(A::Array{Any}, x::ANY, i::Real) = arrayset(A, x, to_index(i)) + +function length_checked_equal(args...) + n = length(args[1]) + for i=2:length(args) + if length(args[i]) != n + error("argument dimensions must match") + end + end + n +end + +map(f::Function, a::Array{Any,1}) = Any[ f(a[i]) for i=1:length(a) ] + +function precompile(f::ANY, args::Tuple) + if isa(f,DataType) + args = tuple(Type{f}, args...) + f = f.name.module.call + end + if isgeneric(f) + ccall(:jl_compile_hint, Void, (Any, Any), f, Tuple{args...}) + end +end + +esc(e::ANY) = Expr(:escape, e) + +macro boundscheck(yesno,blk) + # hack: use this syntax since it avoids introducing line numbers + :($(Expr(:boundscheck,yesno)); + $(esc(blk)); + $(Expr(:boundscheck,:pop))) +end + +macro inbounds(blk) + :(@boundscheck false $(esc(blk))) +end + +macro label(name::Symbol) + Expr(:symboliclabel, name) +end + +macro goto(name::Symbol) + Expr(:symbolicgoto, name) +end + +call{T,N}(::Type{Array{T}}, d::NTuple{N,Int}) = + ccall(:jl_new_array, Array{T,N}, (Any,Any), Array{T,N}, d) +call{T}(::Type{Array{T}}, d::Integer...) = Array{T}(convert(Tuple{Vararg{Int}}, d)) + +call{T}(::Type{Array{T}}, m::Integer) = + ccall(:jl_alloc_array_1d, Array{T,1}, (Any,Int), Array{T,1}, m) +call{T}(::Type{Array{T}}, m::Integer, n::Integer) = + ccall(:jl_alloc_array_2d, Array{T,2}, (Any,Int,Int), Array{T,2}, m, n) +call{T}(::Type{Array{T}}, m::Integer, n::Integer, o::Integer) = + ccall(:jl_alloc_array_3d, Array{T,3}, (Any,Int,Int,Int), Array{T,3}, m, n, o) + +# TODO: possibly turn these into deprecations +Array{T,N}(::Type{T}, d::NTuple{N,Int}) = Array{T}(d) +Array{T}(::Type{T}, d::Integer...) = Array{T}(convert(Tuple{Vararg{Int}}, d)) +Array{T}(::Type{T}, m::Integer) = Array{T}(m) +Array{T}(::Type{T}, m::Integer,n::Integer) = Array{T}(m,n) +Array{T}(::Type{T}, m::Integer,n::Integer,o::Integer) = Array{T}(m,n,o) + +# SimpleVector + +function getindex(v::SimpleVector, i::Int) + if !(1 <= i <= length(v)) + throw(BoundsError(v,i)) + end + x = unsafe_load(convert(Ptr{Ptr{Void}},data_pointer_from_objref(v)) + i*sizeof(Ptr)) + x == C_NULL && throw(UndefRefError()) + return unsafe_pointer_to_objref(x) +end + +length(v::SimpleVector) = v.length +endof(v::SimpleVector) = v.length +start(v::SimpleVector) = 1 +next(v::SimpleVector,i) = (v[i],i+1) +done(v::SimpleVector,i) = (i > v.length) +isempty(v::SimpleVector) = (v.length == 0) + +function ==(v1::SimpleVector, v2::SimpleVector) + length(v1)==length(v2) || return false + for i = 1:length(v1) + v1[i] == v2[i] || return false + end + return true +end + +map(f, v::SimpleVector) = Any[ f(v[i]) for i = 1:length(v) ] + +getindex(v::SimpleVector, I::AbstractArray) = svec(Any[ v[i] for i in I ]...) + +# index colon +type Colon +end +const (:) = Colon() diff --git a/base/float.jl b/base/float.jl index 3be3402f033f5..215d1944910d1 100644 --- a/base/float.jl +++ b/base/float.jl @@ -1,5 +1,14 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license +## floating point traits ## + +const Inf16 = box(Float16,unbox(UInt16,0x7c00)) +const NaN16 = box(Float16,unbox(UInt16,0x7e00)) +const Inf32 = box(Float32,unbox(UInt32,0x7f800000)) +const NaN32 = box(Float32,unbox(UInt32,0x7fc00000)) +const Inf = box(Float64,unbox(UInt64,0x7ff0000000000000)) +const NaN = box(Float64,unbox(UInt64,0x7ff8000000000000)) + ## conversions to floating-point ## convert(::Type{Float16}, x::Integer) = convert(Float16, convert(Float32,x)) for t in (Int8,Int16,Int32,Int64,Int128,UInt8,UInt16,UInt32,UInt64,UInt128) @@ -89,11 +98,11 @@ end #convert(::Type{Float16}, x::Float32) = box(Float16,fptrunc(Float16,x)) convert(::Type{Float16}, x::Float64) = convert(Float16, convert(Float32,x)) -convert(::Type{Float32}, x::Float64) = box(Float32,fptrunc(Float32,x)) +convert(::Type{Float32}, x::Float64) = box(Float32,fptrunc(Float32,unbox(Float64,x))) #convert(::Type{Float32}, x::Float16) = box(Float32,fpext(Float32,x)) convert(::Type{Float64}, x::Float16) = convert(Float64, convert(Float32,x)) -convert(::Type{Float64}, x::Float32) = box(Float64,fpext(Float64,x)) +convert(::Type{Float64}, x::Float32) = box(Float64,fpext(Float64,unbox(Float32,x))) convert(::Type{FloatingPoint}, x::Bool) = convert(Float64, x) convert(::Type{FloatingPoint}, x::Int8) = convert(Float64, x) @@ -301,14 +310,17 @@ isfinite(x::Integer) = true isinf(x::Real) = !isnan(x) & !isfinite(x) -## floating point traits ## +## hashing small, built-in numeric types ## -const Inf16 = box(Float16,unbox(UInt16,0x7c00)) -const NaN16 = box(Float16,unbox(UInt16,0x7e00)) -const Inf32 = box(Float32,unbox(UInt32,0x7f800000)) -const NaN32 = box(Float32,unbox(UInt32,0x7fc00000)) -const Inf = box(Float64,unbox(UInt64,0x7ff0000000000000)) -const NaN = box(Float64,unbox(UInt64,0x7ff8000000000000)) +hx(a::UInt64, b::Float64, h::UInt) = hash_uint64((3a + reinterpret(UInt64,b)) - h) +const hx_NaN = hx(UInt64(0), NaN, UInt(0 )) + +hash(x::UInt64, h::UInt) = hx(x, Float64(x), h) +hash(x::Int64, h::UInt) = hx(reinterpret(UInt64,abs(x)), Float64(x), h) +hash(x::Float64, h::UInt) = isnan(x) ? (hx_NaN $ h) : hx(box(UInt64,fptoui(unbox(Float64,abs(x)))), x, h) + +hash(x::Union(Bool,Char,Int8,UInt8,Int16,UInt16,Int32,UInt32), h::UInt) = hash(Int64(x), h) +hash(x::Float32, h::UInt) = hash(Float64(x), h) ## precision, as defined by the effective number of bits in the mantissa ## precision(::Type{Float16}) = 11 @@ -438,3 +450,25 @@ significand_mask(::Type{Float32}) = 0x007f_ffff significand_bits{T<:FloatingPoint}(::Type{T}) = trailing_ones(significand_mask(T)) exponent_bits{T<:FloatingPoint}(::Type{T}) = sizeof(T)*8 - significand_bits(T) - 1 exponent_bias{T<:FloatingPoint}(::Type{T}) = Int(exponent_one(T) >> significand_bits(T)) + +## Array operations on floating point numbers ## + +float{T<:FloatingPoint}(x::AbstractArray{T}) = x + +float{T<:Integer64}(x::AbstractArray{T}) = convert(AbstractArray{typeof(float(zero(T)))}, x) + +function float(A::AbstractArray) + cnv(x) = convert(FloatingPoint,x) + map_promote(cnv, A) +end + +for fn in (:float,:big) + @eval begin + $fn(r::StepRange) = $fn(r.start):$fn(r.step):$fn(last(r)) + $fn(r::UnitRange) = $fn(r.start):$fn(last(r)) + $fn(r::FloatRange) = FloatRange($fn(r.start), $fn(r.step), r.len, $fn(r.divisor)) + end +end + +big{T<:FloatingPoint,N}(x::AbstractArray{T,N}) = convert(AbstractArray{BigFloat,N}, x) +big{T<:Integer,N}(x::AbstractArray{T,N}) = convert(AbstractArray{BigInt,N}, x) diff --git a/base/hashing.jl b/base/hashing.jl index 709841dbbeaac..babc03efb4bb6 100644 --- a/base/hashing.jl +++ b/base/hashing.jl @@ -53,33 +53,6 @@ else hash_uint(x::UInt) = hash_32_32(x) end -## hashing small, built-in numeric types ## - -hx(a::UInt64, b::Float64, h::UInt) = hash_uint64((3a + reinterpret(UInt64,b)) - h) -const hx_NaN = hx(UInt64(0), NaN, UInt(0 )) - -hash(x::UInt64, h::UInt) = hx(x, Float64(x), h) -hash(x::Int64, h::UInt) = hx(reinterpret(UInt64,abs(x)), Float64(x), h) -hash(x::Float64, h::UInt) = isnan(x) ? (hx_NaN $ h) : hx(box(UInt64,fptoui(unbox(Float64,abs(x)))), x, h) - -hash(x::Union(Bool,Char,Int8,UInt8,Int16,UInt16,Int32,UInt32), h::UInt) = hash(Int64(x), h) -hash(x::Float32, h::UInt) = hash(Float64(x), h) - -## hashing complex numbers ## - -if UInt === UInt64 - const h_imag = 0x32a7a07f3e7cd1f9 -else - const h_imag = 0x3e7cd1f9 -end -const hash_0_imag = hash(0, h_imag) - -function hash(z::Complex, h::UInt) - # TODO: with default argument specialization, this would be better: - # hash(real(z), h $ hash(imag(z), h $ h_imag) $ hash(0, h $ h_imag)) - hash(real(z), h $ hash(imag(z), h_imag) $ hash_0_imag) -end - ## symbol & expression hashing ## hash(x::Symbol, h::UInt) = 3*object_id(x) - h @@ -89,71 +62,6 @@ else hash(x::Expr, h::UInt) = hash(x.args, hash(x.head, h + 0x96d26dc6)) end -## hashing collections ## - -const hashaa_seed = UInt === UInt64 ? 0x7f53e68ceb575e76 : 0xeb575e76 -const hashrle_seed = UInt == UInt64 ? 0x2aab8909bfea414c : 0xbfea414c -function hash(a::AbstractArray, h::UInt) - h += hashaa_seed - h += hash(size(a)) - - state = start(a) - done(a, state) && return h - x2, state = next(a, state) - done(a, state) && return hash(x2, h) - - x1 = x2 - while !done(a, state) - x1 = x2 - x2, state = next(a, state) - if isequal(x2, x1) - # For repeated elements, use run length encoding - # This allows efficient hashing of sparse arrays - runlength = 2 - while !done(a, state) - x2, state = next(a, state) - isequal(x1, x2) || break - runlength += 1 - end - h += hashrle_seed - h = hash(runlength, h) - end - h = hash(x1, h) - end - !isequal(x2, x1) && (h = hash(x2, h)) - return h -end - -const hasha_seed = UInt === UInt64 ? 0x6d35bb51952d5539 : 0x952d5539 -function hash(a::Associative, h::UInt) - h += hasha_seed - for (k,v) in a - h $= hash(k, hash(v)) - end - return h -end - -const hashs_seed = UInt === UInt64 ? 0x852ada37cfe8e0ce : 0xcfe8e0ce -function hash(s::Set, h::UInt) - h += hashs_seed - for x in s - h $= hash(x) - end - return h -end - -const hashis_seed = UInt === UInt64 ? 0x88989f1fc7dea67d : 0xc7dea67d -function hash(s::IntSet, h::UInt) - h += hashis_seed - h += hash(s.fill1s) - filln = s.fill1s ? ~zero(eltype(s.bits)) : zero(eltype(s.bits)) - for x in s.bits - if x != filln - h = hash(x, h) - end - end - return h -end # hashing ranges by component at worst leads to collisions for very similar ranges const hashr_seed = UInt === UInt64 ? 0x80707b6821b70087 : 0x21b70087 diff --git a/base/intset.jl b/base/intset.jl index 5f44e28e10249..64192c9e6cfcb 100644 --- a/base/intset.jl +++ b/base/intset.jl @@ -291,6 +291,19 @@ function ==(s1::IntSet, s2::IntSet) return true end +const hashis_seed = UInt === UInt64 ? 0x88989f1fc7dea67d : 0xc7dea67d +function hash(s::IntSet, h::UInt) + h += hashis_seed + h += hash(s.fill1s) + filln = s.fill1s ? ~zero(eltype(s.bits)) : zero(eltype(s.bits)) + for x in s.bits + if x != filln + h = hash(x, h) + end + end + return h +end + issubset(a::IntSet, b::IntSet) = isequal(a, intersect(a,b)) <(a::IntSet, b::IntSet) = (a<=b) && !isequal(a,b) <=(a::IntSet, b::IntSet) = issubset(a, b) diff --git a/base/refpointer.jl b/base/refpointer.jl index cddbd7226957b..969a52447396c 100644 --- a/base/refpointer.jl +++ b/base/refpointer.jl @@ -2,11 +2,11 @@ ### General Methods for Ref{T} type -Base.eltype{T}(x::Type{Ref{T}}) = T -Base.convert{T}(::Type{Ref{T}}, x::Ref{T}) = x +eltype{T}(x::Type{Ref{T}}) = T +convert{T}(::Type{Ref{T}}, x::Ref{T}) = x # create Ref objects for general object conversion -Base.unsafe_convert{T}(::Type{Ref{T}}, x) = unsafe_convert(Ptr{T}, x) +unsafe_convert{T}(::Type{Ref{T}}, x) = unsafe_convert(Ptr{T}, x) ### Methods for a Ref object that can store a single value of any type @@ -21,21 +21,21 @@ Ref(x::Ref) = x Ref(x::Any) = RefValue(x) Ref{T}(x::Ptr{T}, i::Integer=1) = x + (i-1)*Core.sizeof(T) Ref(x, i::Integer) = (i != 1 && error("Object only has one element"); Ref(x)) -Base.call{T}(::Type{Ref{T}}) = RefValue{T}() # Ref{T}() -Base.call{T}(::Type{Ref{T}}, x) = RefValue{T}(x) # Ref{T}(x) -Base.convert{T}(::Type{Ref{T}}, x) = RefValue{T}(x) +call{T}(::Type{Ref{T}}) = RefValue{T}() # Ref{T}() +call{T}(::Type{Ref{T}}, x) = RefValue{T}(x) # Ref{T}(x) +convert{T}(::Type{Ref{T}}, x) = RefValue{T}(x) -function Base.unsafe_convert{T}(P::Type{Ptr{T}}, b::RefValue{T}) +function unsafe_convert{T}(P::Type{Ptr{T}}, b::RefValue{T}) if isbits(T) return convert(P, data_pointer_from_objref(b)) else return convert(P, data_pointer_from_objref(b.x)) end end -function Base.unsafe_convert(P::Type{Ptr{Any}}, b::RefValue{Any}) +function unsafe_convert(P::Type{Ptr{Any}}, b::RefValue{Any}) return convert(P, data_pointer_from_objref(b)) end -Base.unsafe_convert{T}(::Type{Ptr{Void}}, b::RefValue{T}) = Base.convert(Ptr{Void}, Base.unsafe_convert(Ptr{T}, b)) +unsafe_convert{T}(::Type{Ptr{Void}}, b::RefValue{T}) = convert(Ptr{Void}, unsafe_convert(Ptr{T}, b)) ### Methods for a Ref object that is backed by an array at index i @@ -53,27 +53,27 @@ immutable RefArray{T, A<:AbstractArray, R} <: Ref{T} end RefArray{T}(x::AbstractArray{T},i::Int,roots::Any) = RefArray{T,typeof(x),Any}(x, i, roots) RefArray{T}(x::AbstractArray{T},i::Int=1,roots::Void=nothing) = RefArray{T,typeof(x),Void}(x, i, nothing) -Base.convert{T}(::Type{Ref{T}}, x::AbstractArray{T}) = RefArray(x, 1) +convert{T}(::Type{Ref{T}}, x::AbstractArray{T}) = RefArray(x, 1) Ref(x::AbstractArray, i::Integer=1) = RefArray(x, i) -function Base.unsafe_convert{T}(P::Type{Ptr{T}}, b::RefArray{T}) +function unsafe_convert{T}(P::Type{Ptr{T}}, b::RefArray{T}) if isbits(T) convert(P, pointer(b.x, b.i)) else convert(P, data_pointer_from_objref(b.x[b.i])) end end -function Base.unsafe_convert(P::Type{Ptr{Any}}, b::RefArray{Any}) +function unsafe_convert(P::Type{Ptr{Any}}, b::RefArray{Any}) return convert(P, pointer(b.x, b.i)) end -Base.unsafe_convert{T}(::Type{Ptr{Void}}, b::RefArray{T}) = Base.convert(Ptr{Void}, Base.unsafe_convert(Ptr{T}, b)) +unsafe_convert{T}(::Type{Ptr{Void}}, b::RefArray{T}) = convert(Ptr{Void}, unsafe_convert(Ptr{T}, b)) ### -Base.getindex(b::RefValue) = b.x -Base.getindex(b::RefArray) = b.x[b.i] +getindex(b::RefValue) = b.x +getindex(b::RefArray) = b.x[b.i] -Base.setindex!(b::RefValue, x) = (b.x = x; b) -Base.setindex!(b::RefArray, x) = (b.x[b.i] = x; b) +setindex!(b::RefValue, x) = (b.x = x; b) +setindex!(b::RefArray, x) = (b.x[b.i] = x; b) ### diff --git a/base/set.jl b/base/set.jl index eda53d33d3192..04b94406a2ec0 100644 --- a/base/set.jl +++ b/base/set.jl @@ -132,3 +132,12 @@ function filter!(f, s::Set) end return s end + +const hashs_seed = UInt === UInt64 ? 0x852ada37cfe8e0ce : 0xcfe8e0ce +function hash(s::Set, h::UInt) + h += hashs_seed + for x in s + h $= hash(x) + end + return h +end diff --git a/base/sysimg.jl b/base/sysimg.jl index fd8c265be4e16..e56faff55bf32 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -28,7 +28,7 @@ end ## Load essential files and libraries - +include("essentials.jl") include("base.jl") include("reflection.jl") include("build_h.jl") @@ -51,33 +51,35 @@ include("operators.jl") include("pointer.jl") include("refpointer.jl") -# rounding utilities +# array structures +include("abstractarray.jl") +include("subarray.jl") +include("array.jl") +include("subarray2.jl") + +# numeric operations +include("hashing.jl") include("rounding.jl") importall .Rounding - include("float.jl") include("complex.jl") include("rational.jl") -# core data structures (used by type inference) -include("abstractarray.jl") -include("subarray.jl") -include("array.jl") -include("subarray2.jl") +# SIMD loops +include("simdloop.jl") +importall .SimdLoop + +# map-reduce operators include("functors.jl") +include("reduce.jl") + +## core structures include("bitarray.jl") include("intset.jl") include("dict.jl") include("set.jl") -include("hashing.jl") include("iterator.jl") -# SIMD loops -include("simdloop.jl") -importall .SimdLoop - -include("reduce.jl") - # compiler include("inference.jl") From 677f5373d3c5d87b99e798edc789ca6bdf58f5d6 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 15 May 2015 23:31:07 -0400 Subject: [PATCH 026/181] switch inlining costs to use scaled integer math. this removes the need for floating point numbers in inference. --- base/inference.jl | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index dd49144dcab86..621d2141cd131 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -2303,12 +2303,12 @@ function inlineable(f::ANY, e::Expr, atype::ANY, sv::StaticVarInfo, enclosing_as body = Expr(:block) body.args = without_linenums(ast.args[3].args)::Array{Any,1} need_mod_annotate = true - cost = 1.0 + cost::Int = 1000 if incompletematch cost *= 4 end if is(f, next) || is(f, done) || is(f, unsafe_convert) || is(f, cconvert) - cost /= 4 + cost ÷= 4 end inline_op = (f===(+) || f===(*) || f===min || f===max) && (3 <= length(argexprs) <= 9) && meth[3].sig == Tuple{Any,Any,Any,Vararg{Any}} @@ -2676,17 +2676,18 @@ end # doesn't work on Tuples of TypeVars const inline_incompletematch_allowed = false -inline_worthy(body, cost::Real) = true -function inline_worthy(body::Expr, cost::Real=1.0) # precondition: 0true, symlim) < symlim return true end From 0e88529c475cb2f8c26f3b8847f34b4d8aaee2f9 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 15 May 2015 23:38:22 -0400 Subject: [PATCH 027/181] split t_func::ObjectIdDict to t_ifunc::Array (for IntrinsicFunctions) and t_ffunc::Array (for builtin functions) this removes the dependence on being able to serialize ObjectIdDict from the inference code --- base/inference.jl | 136 ++++++++++++++++++++++++++-------------------- 1 file changed, 78 insertions(+), 58 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 621d2141cd131..47fe61e657f96 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -109,24 +109,35 @@ cmp_tfunc = (x,y)->Bool isType(t::ANY) = isa(t,DataType) && is((t::DataType).name,Type.name) -const t_func = ObjectIdDict() -t_func[throw] = (1, 1, x->Bottom) -t_func[box] = (2, 2, (t,v)->(isType(t) ? t.parameters[1] : Any)) -t_func[eq_int] = (2, 2, cmp_tfunc) -t_func[ne_int] = (2, 2, cmp_tfunc) -t_func[slt_int] = (2, 2, cmp_tfunc) -t_func[ult_int] = (2, 2, cmp_tfunc) -t_func[sle_int] = (2, 2, cmp_tfunc) -t_func[ule_int] = (2, 2, cmp_tfunc) -t_func[eq_float] = (2, 2, cmp_tfunc) -t_func[ne_float] = (2, 2, cmp_tfunc) -t_func[lt_float] = (2, 2, cmp_tfunc) -t_func[le_float] = (2, 2, cmp_tfunc) -t_func[fpiseq] = (2, 2, cmp_tfunc) -t_func[fpislt] = (2, 2, cmp_tfunc) -t_func[nan_dom_err] = (2, 2, (a, b)->a) -t_func[eval(Core.Intrinsics,:ccall)] = - (3, Inf, function(fptr, rt, at, a...) +const IInf = typemax(Int) # integer infinity +const n_ifunc = reinterpret(Int32,llvmcall)+1 +const t_ifunc = Array{Tuple{Int,Int,Function},1}(n_ifunc) +const t_ffunc_key = Array{Function,1}(0) +const t_ffunc_val = Array{Tuple{Int,Int,Function},1}(0) +function add_tfunc(f::IntrinsicFunction, minarg::Int, maxarg::Int, tfunc::Function) + t_ifunc[reinterpret(Int32,f)+1] = (minarg, maxarg, tfunc) +end +function add_tfunc(f::Function, minarg::Int, maxarg::Int, tfunc::Function) + push!(t_ffunc_key, f) + push!(t_ffunc_val, (minarg, maxarg, tfunc)) +end +add_tfunc(throw, 1, 1, x->Bottom) +add_tfunc(box, 2, 2, (t,v)->(isType(t) ? t.parameters[1] : Any)) +add_tfunc(eq_int, 2, 2, cmp_tfunc) +add_tfunc(ne_int, 2, 2, cmp_tfunc) +add_tfunc(slt_int, 2, 2, cmp_tfunc) +add_tfunc(ult_int, 2, 2, cmp_tfunc) +add_tfunc(sle_int, 2, 2, cmp_tfunc) +add_tfunc(ule_int, 2, 2, cmp_tfunc) +add_tfunc(eq_float, 2, 2, cmp_tfunc) +add_tfunc(ne_float, 2, 2, cmp_tfunc) +add_tfunc(lt_float, 2, 2, cmp_tfunc) +add_tfunc(le_float, 2, 2, cmp_tfunc) +add_tfunc(fpiseq, 2, 2, cmp_tfunc) +add_tfunc(fpislt, 2, 2, cmp_tfunc) +add_tfunc(nan_dom_err, 2, 2, (a, b)->a) +add_tfunc(getfield(Core.Intrinsics,:ccall), 3, IInf, + function(fptr, rt, at, a...) if !isType(rt) return Any end @@ -140,36 +151,36 @@ t_func[eval(Core.Intrinsics,:ccall)] = end return t end) -t_func[eval(Core.Intrinsics,:llvmcall)] = - (3, Inf, (fptr, rt, at, a...)->(isType(rt) ? rt.parameters[1] : Any)) -t_func[eval(Core.Intrinsics,:cglobal)] = - (1, 2, (fptr, t...)->(isempty(t) ? Ptr{Void} : - isType(t[1]) ? Ptr{t[1].parameters[1]} : Ptr)) -t_func[eval(Core.Intrinsics,:select_value)] = +add_tfunc(eval(Core.Intrinsics,:llvmcall), 3, IInf, + (fptr, rt, at, a...)->(isType(rt) ? rt.parameters[1] : Any)) +add_tfunc(eval(Core.Intrinsics,:cglobal), 1, 2, + (fptr, t...)->(isempty(t) ? Ptr{Void} : + isType(t[1]) ? Ptr{t[1].parameters[1]} : Ptr)) +add_tfunc(eval(Core.Intrinsics,:select_value), 3, 3, # TODO: return Bottom if cnd is definitely not a Bool - (3, 3, (cnd, x, y)->Union(x,y)) -t_func[is] = (2, 2, cmp_tfunc) -t_func[issubtype] = (2, 2, cmp_tfunc) -t_func[isa] = (2, 2, cmp_tfunc) -t_func[isdefined] = (1, Inf, (args...)->Bool) -t_func[Core.sizeof] = (1, 1, x->Int) -t_func[nfields] = (1, 1, x->Int) -t_func[Union] = (0, Inf, - (args...)->(if all(isType,args) - Type{Union(map(t->t.parameters[1],args)...)} - else - Type - end)) -t_func[_expr] = (1, Inf, (args...)->Expr) -t_func[method_exists] = (2, 2, cmp_tfunc) -t_func[applicable] = (1, Inf, (f, args...)->Bool) -t_func[arraylen] = (1, 1, x->Int) -#t_func[arrayref] = (2,Inf,(a,i...)->(isa(a,DataType) && a<:Array ? + (cnd, x, y)->Union(x,y)) +add_tfunc(is, 2, 2, cmp_tfunc) +add_tfunc(issubtype, 2, 2, cmp_tfunc) +add_tfunc(isa, 2, 2, cmp_tfunc) +add_tfunc(isdefined, 1, IInf, (args...)->Bool) +add_tfunc(Core.sizeof, 1, 1, x->Int) +add_tfunc(nfields, 1, 1, x->Int) +add_tfunc(Union, 0, IInf, + (args...)->(if all(isType,args) + Type{Union(map(t->t.parameters[1],args)...)} + else + Type + end)) +add_tfunc(_expr, 1, IInf, (args...)->Expr) +add_tfunc(method_exists, 2, 2, cmp_tfunc) +add_tfunc(applicable, 1, IInf, (f, args...)->Bool) +add_tfunc(arraylen, 1, 1, x->Int) +#add_tfunc(arrayref, 2,IInf,(a,i...)->(isa(a,DataType) && a<:Array ? # a.parameters[1] : Any)) -#t_func[arrayset] = (3, Inf, (a,v,i...)->a) -t_func[arraysize] = (2, 2, (a,d)->Int) -t_func[pointerref] = (2,2,(a,i)->(isa(a,DataType) && a<:Ptr ? a.parameters[1] : Any)) -t_func[pointerset] = (3, 3, (a,v,i)->a) +#add_tfunc(arrayset, 3, IInf, (a,v,i...)->a) +add_tfunc(arraysize, 2, 2, (a,d)->Int) +add_tfunc(pointerref, 2, 2, (a,i)->(isa(a,DataType) && a<:Ptr ? a.parameters[1] : Any)) +add_tfunc(pointerset, 3, 3, (a,v,i)->a) const typeof_tfunc = function (t) if isType(t) @@ -193,11 +204,11 @@ const typeof_tfunc = function (t) Type end end -t_func[typeof] = (1, 1, typeof_tfunc) +add_tfunc(typeof, 1, 1, typeof_tfunc) # involving constants: typeassert, getfield, fieldtype, apply_type # therefore they get their arguments unevaluated -t_func[typeassert] = - (2, 2, (A, v, t)->(isType(t) ? typeintersect(v,t.parameters[1]) : Any)) +add_tfunc(typeassert, 2, 2, + (A, v, t)->(isType(t) ? typeintersect(v,t.parameters[1]) : Any)) function limit_type_depth(t::ANY, d::Int, cov::Bool, vars) if isa(t,TypeVar) || isa(t,TypeConstructor) @@ -313,8 +324,8 @@ const getfield_tfunc = function (A, s0, name) return reduce(tmerge, Bottom, map(unwrapva,s.types)) #=Union(s.types...)=#, false end end -t_func[getfield] = (2, 2, (A,s,name)->getfield_tfunc(A,s,name)[1]) -t_func[setfield!] = (3, 3, (o, f, v)->v) +add_tfunc(getfield, 2, 2, (A,s,name)->getfield_tfunc(A,s,name)[1]) +add_tfunc(setfield!, 3, 3, (o, f, v)->v) const fieldtype_tfunc = function (A, s, name) if isType(s) s = s.parameters[1] @@ -327,8 +338,7 @@ const fieldtype_tfunc = function (A, s, name) end Type{exact || isleaftype(t) || isa(t,TypeVar) ? t : TypeVar(:_, t)} end -t_func[fieldtype] = (2, 2, fieldtype_tfunc) -t_func[Box] = (1, 1, (a,)->Box) +add_tfunc(fieldtype, 2, 2, fieldtype_tfunc) function valid_tparam(x::ANY) if isa(x,Tuple) @@ -431,7 +441,7 @@ const apply_type_tfunc = function (A, args...) end uncertain && !isa(appl,TypeVar) ? Type{TypeVar(:_,appl)} : Type{appl} end -t_func[apply_type] = (1, Inf, apply_type_tfunc) +add_tfunc(apply_type, 1, IInf, apply_type_tfunc) function tuple_tfunc(argtype::ANY) if isa(argtype,DataType) && argtype.name === Tuple.name @@ -471,10 +481,20 @@ function builtin_tfunction(f::ANY, args::ANY, argtype::ANY) end return Expr end - tf = get(t_func::ObjectIdDict, f, false) - if is(tf,false) - # unknown/unhandled builtin - return Any + if isa(f, IntrinsicFunction) + iidx = Int(reinterpret(Int32, f::IntrinsicFunction))+1 + if !isdefined(t_ifunc, iidx) + # unknown/unhandled intrinsic (most fall in this category since most return an unboxed value) + return Any + end + tf = t_ifunc[iidx] + else + fidx = findfirst(t_ffunc_key, f::Function) + if fidx == 0 + # unknown/unhandled builtin or anonymous function + return Any + end + tf = t_ffunc_val[fidx] end tf = tf::Tuple{Real, Real, Function} if isva From 978b3f24a4d9b18cb8de8bd47e7bb63052641ae6 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 15 May 2015 23:45:01 -0400 Subject: [PATCH 028/181] run the "economy mode" repl any time Base._start is not defined --- ui/repl.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/ui/repl.c b/ui/repl.c index b85c4e8f30c10..db52d34f0ab2d 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -41,7 +41,6 @@ extern "C" { static int lisp_prompt = 0; static int codecov = JL_LOG_NONE; static int malloclog= JL_LOG_NONE; -static char *program = NULL; static int imagepathspecified = 0; static const char usage[] = "julia [options] [program] [args...]\n"; @@ -345,13 +344,9 @@ void parse_opts(int *argcp, char ***argvp) optind -= skip; *argvp += optind; *argcp -= optind; - if (jl_options.image_file==NULL && *argcp > 0) { - if (strcmp((*argvp)[0], "-")) - program = (*argvp)[0]; - } } -static int exec_program(void) +static int exec_program(char *program) { int err = 0; again: ; @@ -427,13 +422,6 @@ static int true_main(int argc, char *argv[]) } } - // run program if specified, otherwise enter REPL - if (program) { - int ret = exec_program(); - uv_tty_reset_mode(); - return ret; - } - jl_function_t *start_client = jl_base_module ? (jl_function_t*)jl_get_global(jl_base_module, jl_symbol("_start")) : NULL; @@ -442,11 +430,19 @@ static int true_main(int argc, char *argv[]) return 0; } + // run program if specified, otherwise enter REPL + if (argc > 0) { + if (strcmp(argv[0], "-")) { + return exec_program(argv[0]); + } + } + ios_puts("warning: Base._start not defined, falling back to economy mode repl.\n", ios_stdout); if (!jl_errorexception_type) ios_puts("warning: jl_errorexception_type not defined; any errors will be fatal.\n", ios_stdout); + while (!ios_eof(ios_stdin)) { - char *line = NULL; + char *volatile line = NULL; JL_TRY { ios_puts("\njulia> ", ios_stdout); ios_flush(ios_stdout); From f43ff542941498c4bdeb39afc62b36cfcc2fc6d5 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 15 May 2015 23:46:31 -0400 Subject: [PATCH 029/181] also normalize the jl_options.machinefile and jl_options.load paths during init, prior to starting executing julia code which may result in a change to the current working directory --- src/init.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/init.c b/src/init.c index 335b4773a84ab..b8979f1f078fd 100644 --- a/src/init.c +++ b/src/init.c @@ -943,6 +943,10 @@ static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) } if (jl_options.build_path) jl_options.build_path = abspath(jl_options.build_path); + if (jl_options.machinefile) + jl_options.machinefile = abspath(jl_options.machinefile); + if (jl_options.load) + jl_options.load = abspath(jl_options.load); } void _julia_init(JL_IMAGE_SEARCH rel) From 469f69902d873d8d832ae564c1b0b782a0251f3b Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 15 May 2015 23:48:28 -0400 Subject: [PATCH 030/181] move inference out of Base into Core.Inference having inference inside Base made it hard to modify and slow to compile the sysimg since bootstrapping. additionally, it made inference vulnerable to unintentional sabotage by the users program. to combat those issues, this creates a copy of the essential code required for running the inference into Core.Inference. this allows any part of the system (esp. Base) around inference to change, and even be recompiled or monkey-patched, without impacting the core inference algorithms. note that this clarifies and even tightens the restrictions on what functionality is available for the use of inference. the primary available functionality is: "essential" primitives integers arrays dictionary support (limited, and ObjectIdDict will NOT deserialize properly) c-interaction intset limited printing and string support (no interpolation) --- Makefile | 57 +++++++++++++++++++++------ base/coreimg.jl | 86 +++++++++++++++++++++++++++++++++++++++++ base/nofloat_hashing.jl | 10 +++++ base/operators.jl | 8 ++-- base/precompile.jl | 15 ------- base/reflection.jl | 5 +++ base/sysimg.jl | 3 -- contrib/build_sysimg.jl | 64 ++++++++++++++++-------------- src/dump.c | 6 +-- test/core.jl | 6 +-- 10 files changed, 194 insertions(+), 66 deletions(-) create mode 100644 base/coreimg.jl create mode 100644 base/nofloat_hashing.jl diff --git a/Makefile b/Makefile index c9b4ee7d4c7d4..f498c86265f9f 100644 --- a/Makefile +++ b/Makefile @@ -130,13 +130,11 @@ ifeq ($(OS), WINNT) $(build_sysconfdir)/julia/juliarc.jl: contrib/windows/juliarc.jl endif -# use sys.ji if it exists, otherwise run two stages -$(build_private_libdir)/sys%ji: $(build_private_libdir)/sys%o - +.SECONDARY: $(build_private_libdir)/inference0.o +.SECONDARY: $(build_private_libdir)/inference.o .SECONDARY: $(build_private_libdir)/sys.o -.SECONDARY: $(build_private_libdir)/sys0.o -$(build_private_libdir)/sys%$(SHLIB_EXT): $(build_private_libdir)/sys%o +$(build_private_libdir)/%.$(SHLIB_EXT): $(build_private_libdir)/%.o ifneq ($(USEMSVC), 1) @$(call PRINT_LINK, $(CXX) -shared -fPIC -L$(build_private_libdir) -L$(build_libdir) -L$(build_shlibdir) -o $@ $< \ $$([ $(OS) = Darwin ] && echo '' -Wl,-undefined,dynamic_lookup || echo '' -Wl,--unresolved-symbols,ignore-all ) \ @@ -146,17 +144,54 @@ else @true endif -$(build_private_libdir)/sys0.o: | $(build_private_libdir) - @$(call PRINT_JULIA, cd base && \ - $(call spawn,$(JULIA_EXECUTABLE)) -C $(JULIA_CPU_TARGET) --build $(call cygpath_w,$(build_private_libdir)/sys0) sysimg.jl) +CORE_SRCS := base/boot.jl base/coreimg.jl \ + base/abstractarray.jl \ + base/array.jl \ + base/bool.jl \ + base/build_h.jl \ + base/c.jl \ + base/dict.jl \ + base/error.jl \ + base/essentials.jl \ + base/expr.jl \ + base/functors.jl \ + base/hashing.jl \ + base/inference.jl \ + base/int.jl \ + base/intset.jl \ + base/iterator.jl \ + base/nofloat_hashing.jl \ + base/number.jl \ + base/operators.jl \ + base/options.jl \ + base/osutils.jl \ + base/pointer.jl \ + base/promotion.jl \ + base/range.jl \ + base/reduce.jl \ + base/reflection.jl \ + base/refpointer.jl \ + base/subarray.jl \ + base/subarray2.jl \ + base/tuple.jl BASE_SRCS := $(wildcard base/*.jl base/*/*.jl base/*/*/*.jl) +$(build_private_libdir)/inference0.o: $(CORE_SRCS) | $(build_private_libdir) + @$(call PRINT_JULIA, cd base && \ + $(call spawn,$(JULIA_EXECUTABLE)) -C $(JULIA_CPU_TARGET) --build $(call cygpath_w,$(build_private_libdir)/inference0) -f \ + coreimg.jl) + +$(build_private_libdir)/inference.o: $(build_private_libdir)/inference0.$(SHLIB_EXT) + @$(call PRINT_JULIA, cd base && \ + $(call spawn,$(JULIA_EXECUTABLE)) -C $(JULIA_CPU_TARGET) --build $(call cygpath_w,$(build_private_libdir)/inference) -f \ + -J $(call cygpath_w,$(build_private_libdir)/inference0.ji) coreimg.jl) + COMMA:=, -$(build_private_libdir)/sys.o: VERSION $(BASE_SRCS) $(build_docdir)/helpdb.jl $(build_private_libdir)/sys0.$(SHLIB_EXT) +$(build_private_libdir)/sys.o: VERSION $(BASE_SRCS) $(build_docdir)/helpdb.jl $(build_private_libdir)/inference.$(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 \ + $(call spawn,$(JULIA_EXECUTABLE)) -C $(JULIA_CPU_TARGET) --build $(call cygpath_w,$(build_private_libdir)/sys) -f \ + -J $(call cygpath_w,$(build_private_libdir)/inference.ji) sysimg.jl \ || { 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) diff --git a/base/coreimg.jl b/base/coreimg.jl new file mode 100644 index 0000000000000..01b4fd4077e43 --- /dev/null +++ b/base/coreimg.jl @@ -0,0 +1,86 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + +Main.Core.eval(Main.Core, :(baremodule Inference +using Core: Intrinsics, arraylen, arrayref, arrayset, arraysize, _expr, + kwcall, _apply, typeassert, apply_type, svec +ccall(:jl_set_istopmod, Void, (Bool,), false) + +eval(x) = Core.eval(Inference,x) +eval(m,x) = Core.eval(m,x) + +include = Core.include + +# simple print definitions for debugging. +show(x::ANY) = ccall(:jl_static_show, Void, (Ptr{Void}, Any), + Intrinsics.pointerref(Intrinsics.cglobal(:jl_uv_stdout,Ptr{Void}),1), x) +print(x::ANY) = show(x) +println(x::ANY) = ccall(:jl_, Void, (Any,), x) # includes a newline +print(a::ANY...) = for x=a; print(x); end + +## Load essential files and libraries +include("essentials.jl") +include("reflection.jl") +include("build_h.jl") +include("c.jl") +include("options.jl") + +# core operations & types +include("promotion.jl") +include("tuple.jl") +include("range.jl") +include("expr.jl") +include("error.jl") + +# core numeric operations & types +include("bool.jl") +include("number.jl") +include("int.jl") +include("operators.jl") +include("pointer.jl") +include("refpointer.jl") + +# core array operations +include("abstractarray.jl") +include("subarray.jl") +include("array.jl") +include("subarray2.jl") + +#TODO: eliminate Dict from inference +include("hashing.jl") +include("nofloat_hashing.jl") + +# map-reduce operators +macro simd(forloop) + esc(forloop) +end +include("functors.jl") +include("reduce.jl") + +## core structures +include("intset.jl") +include("dict.jl") +include("iterator.jl") + +# compiler +include("inference.jl") + +precompile(CallStack, (Expr, Module, (Void,), EmptyCallStack)) +precompile(_ieval, (Symbol,)) +precompile(abstract_eval, (LambdaStaticData, ObjectIdDict, StaticVarInfo)) +precompile(abstract_interpret, (Bool, ObjectIdDict, StaticVarInfo)) +precompile(delete_var!, (Expr, Symbol)) +precompile(eval_annotate, (LambdaStaticData, ObjectIdDict, StaticVarInfo, ObjectIdDict, Array{Any,1})) +precompile(is_var_assigned, (Expr, Symbol)) +precompile(isconstantfunc, (SymbolNode, StaticVarInfo)) +precompile(occurs_more, (Bool, Function, Int)) +precompile(occurs_more, (UInt8, Function, Int)) +precompile(occurs_undef, (Symbol, Expr)) +precompile(sym_replace, (UInt8, Array{Any,1}, Array{Any,1}, Array{Any,1}, Array{Any,1})) +precompile(symequal, (Symbol, Symbol)) + +# For OS specific stuff in I/O +# to force compile of inference +include("osutils.jl") + +end # baremodule Inference +)) diff --git a/base/nofloat_hashing.jl b/base/nofloat_hashing.jl new file mode 100644 index 0000000000000..17552943b5125 --- /dev/null +++ b/base/nofloat_hashing.jl @@ -0,0 +1,10 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + +## hashing small, built-in numeric types +## for a system image built without floating point support + +hx(a::UInt64, b::UInt64, h::UInt) = hash_uint64(3a + b - h) + +hash(x::UInt64, h::UInt) = hx(x, x, h) +hash(x::Int64, h::UInt) = hx(reinterpret(UInt64,abs(x)), reinterpret(UInt64,x), h) +hash(x::Union(Bool,Char,Int8,UInt8,Int16,UInt16,Int32,UInt32), h::UInt) = hash(Int64(x), h) diff --git a/base/operators.jl b/base/operators.jl index e21b25e86ddb0..fc3e8efa2d284 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -429,12 +429,14 @@ reverse(p::Pair) = Pair(p.second, p.first) # some operators not defined yet global //, >:, <|, hcat, hvcat, ⋅, ×, ∈, ∉, ∋, ∌, ⊆, ⊈, ⊊, ∩, ∪, √, ∛ -module Operators +this_module = current_module() +baremodule Operators export !, !=, !==, + ===, $, %, .%, @@ -504,9 +506,9 @@ export ctranspose, call -import Base: !, !=, $, %, .%, &, *, +, -, .!=, .+, .-, .*, ./, .<, .<=, .==, .>, +import ..this_module: !, !=, $, %, .%, &, *, +, -, .!=, .+, .-, .*, ./, .<, .<=, .==, .>, .>=, .\, .^, /, //, <, <:, <<, <=, ==, >, >=, >>, .>>, .<<, >>>, - <|, |>, \, ^, |, ~, !==, >:, colon, hcat, vcat, hvcat, getindex, setindex!, + <|, |>, \, ^, |, ~, !==, ===, >:, colon, hcat, vcat, hvcat, getindex, setindex!, transpose, ctranspose, call, ≥, ≤, ≠, .≥, .≤, .≠, ÷, ⋅, ×, ∈, ∉, ∋, ∌, ⊆, ⊈, ⊊, ∩, ∪, √, ∛ diff --git a/base/precompile.jl b/base/precompile.jl index ad3a53a65ef62..e5c57f7c1580b 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -27,7 +27,6 @@ precompile(==, (Type{Function}, Int)) precompile(==, (Type{Function}, Type{ASCIIString})) precompile(Base._atreplinit, (Base.REPL.LineEditREPL,)) precompile(Base.BitArray, (Int,)) -precompile(Base.CallStack, (Expr, Module, (Void,), Base.EmptyCallStack)) precompile(Base.Dict, ()) precompile(Base.Dict{Any,Any}, (Int,)) precompile(Base.IOStream, (ASCIIString, Array{UInt8,1})) @@ -163,7 +162,6 @@ precompile(Base._deleteat_beg!, (Array{UInt8, 1}, Int, Int)) precompile(Base._deleteat_end!, (Array{UInt8, 1}, Int, Int)) precompile(Base._growat_beg!, (Array{UInt8, 1}, Int, Int)) precompile(Base._growat_end!, (Array{UInt8, 1}, Int, Int)) -precompile(Base._ieval, (Symbol,)) precompile(Base._require, (ASCIIString,)) precompile(Base._setindex!, (Base.Dict{Symbol, Any}, Base.LineEdit.Prompt, Symbol, Int)) precompile(Base._setindex!, (Dict{Any, Any}, Base.LineEdit.PromptState, Base.LineEdit.Prompt, Int)) @@ -175,10 +173,6 @@ precompile(Base._uv_hook_readcb, (Base.TTY, Int, Ptr{Void}, UInt)) precompile(Base._uv_hook_writecb_task, (Base.TTY, Ptr{Void}, Int32)) precompile(Base.abs, (Char,)) precompile(Base.abspath, (ASCIIString, ASCIIString)) -precompile(Base.abspath, (UTF8String,)) -precompile(Base.abspath, (UTF8String, UTF8String)) -precompile(Base.abstract_eval, (LambdaStaticData, ObjectIdDict, Base.StaticVarInfo)) -precompile(Base.abstract_interpret, (Bool, ObjectIdDict, Base.StaticVarInfo)) precompile(Base.alignment, (Float64,)) precompile(Base.any, (Function, Array{Any,1})) precompile(Base.arg_gen, (ASCIIString,)) @@ -214,7 +208,6 @@ precompile(Base.convert, (Type{Module}, Module)) precompile(Base.convert, (Type{AbstractString}, ASCIIString)) precompile(Base.copy!, (Array{Dict{Any, Any}, 1}, Int, Array{Dict{Any, Any}, 1}, Int, Int)) precompile(Base.copy, (Bool,)) -precompile(Base.delete_var!, (Expr, Symbol)) precompile(Base.deleteat!, (Array{UInt8, 1}, Base.UnitRange{Int})) precompile(Base.done, (Array{Base.LineEdit.TextInterface, 1}, Int)) precompile(Base.done, (Dict{Any,Any}, Int)) @@ -223,7 +216,6 @@ precompile(Base.done, (IntSet, Int)) precompile(Base.done, (UnitRange{Int},Int)) precompile(Base.endof, (Array{Any,1},)) precompile(Base.enq_work, (Task,)) -precompile(Base.eval_annotate, (LambdaStaticData, ObjectIdDict, Base.StaticVarInfo, ObjectIdDict, Array{Any,1})) precompile(Base.eval_user_input, (Expr, Bool)) precompile(Base.fdio, (Int32,)) precompile(Base.fdwatcher_init, ()) @@ -266,9 +258,7 @@ precompile(Base.input_color, ()) precompile(Base.insert!, (Array{Any,1}, Int, Base.GlobalRef)) precompile(Base.int, (Int,)) precompile(Base.int, (UInt,)) -precompile(Base.is_var_assigned, (Expr, Symbol)) precompile(Base.isabspath, (ASCIIString,)) -precompile(Base.isconstantfunc, (SymbolNode, Base.StaticVarInfo)) precompile(Base.isempty, (ASCIIString,)) precompile(Base.isempty, (Array{Any,1},)) precompile(Base.isempty, (Base.LineEdit.MIState,)) @@ -311,9 +301,6 @@ precompile(Base.normpath, (ASCIIString,)) precompile(Base.notify, (Condition, Any)) precompile(Base.notify_empty, (Base.RemoteValue,)) precompile(Base.notify_full, (Base.RemoteValue,)) -precompile(Base.occurs_more, (Bool, Function, Int)) -precompile(Base.occurs_more, (UInt8, Function, Int)) -precompile(Base.occurs_undef, (Symbol, Expr)) precompile(Base.open, (ASCIIString, ASCIIString)) precompile(Base.parse_input_line, (ASCIIString,)) precompile(Base.parse, (Type{Int}, ASCIIString, Int)) @@ -417,9 +404,7 @@ precompile(Libc.strftime, (ASCIIString, Libc.TmStruct)) precompile(Base.string, (Int,)) precompile(Base.strip, (ASCIIString,)) precompile(Base.strwidth, (ASCIIString,)) -precompile(Base.sym_replace, (UInt8, Array{Any,1}, Array{Any,1}, Array{Any,1}, Array{Any,1})) precompile(Base.symbol, (SubString{UTF8String},)) -precompile(Base.symequal, (Symbol, Symbol)) precompile(Base.sync_begin, ()) precompile(Base.sync_end, ()) precompile(Base.systemerror, (Symbol, Bool)) diff --git a/base/reflection.jl b/base/reflection.jl index 21d2d8de66157..1b072797e1bca 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -203,6 +203,11 @@ code_native(f::ANY, types::ANY) = code_native(STDOUT, f, types) code_native(io::IO, f::ANY, t::ANY) = code_native(io, call, tt_cons(isa(f, Type) ? Type{f} : typeof(f), t)) +if isdefined(Core, :Inference) && not_int(is(current_module(), Core.Inference)) + code_typed(args...;kwargs...) = Core.Inference.code_typed(args...;kwargs...) + return_types(args...;kwargs...) = Core.Inference.return_types(args...;kwargs...) +end + which(f::ANY, t::Tuple{Vararg{Type}}) = which(f, Tuple{t...}) function which(f::ANY, t::ANY) if isleaftype(t) diff --git a/base/sysimg.jl b/base/sysimg.jl index e56faff55bf32..73ead07c577f3 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -80,9 +80,6 @@ include("dict.jl") include("set.jl") include("iterator.jl") -# compiler -include("inference.jl") - # For OS specific stuff in I/O include("osutils.jl") diff --git a/contrib/build_sysimg.jl b/contrib/build_sysimg.jl index da97a672eb30c..5d98d58e06e51 100644 --- a/contrib/build_sysimg.jl +++ b/contrib/build_sysimg.jl @@ -25,37 +25,45 @@ function build_sysimg(sysimg_path=default_sysimg_path, cpu_target="native", user # Enter base/ and setup some useful paths base_dir = dirname(Base.find_source_file("sysimg.jl")) cd(base_dir) do + julia = joinpath(JULIA_HOME, "julia") + ld = find_system_linker() + + # Ensure we have write-permissions to wherever we're trying to write to try - julia = joinpath(JULIA_HOME, "julia") - ld = find_system_linker() - - # Ensure we have write-permissions to wherever we're trying to write to - try - touch("$sysimg_path.ji") - catch - err_msg = "Unable to modify $sysimg_path.ji, ensure parent directory exists " - err_msg *= "and is writable. Absolute paths work best. Do you need to run this with sudo?)" - error( err_msg ) - end + touch("$sysimg_path.ji") + catch + err_msg = "Unable to modify $sysimg_path.ji, ensure parent directory exists " + err_msg *= "and is writable. Absolute paths work best.)" + error( err_msg ) + end - # Copy in userimg.jl if it exists... - if userimg_path != nothing - if !isreadable(userimg_path) - error("$userimg_path is not readable, ensure it is an absolute path!") - end - cp(userimg_path, "userimg.jl") + # Copy in userimg.jl if it exists... + if userimg_path != nothing + if !isreadable(userimg_path) + error("$userimg_path is not readable, ensure it is an absolute path!") end - - # Start by building sys0.{ji,o} - sys0_path = joinpath(dirname(sysimg_path), "sys0") - info("Building sys0.o...") - println("$julia -C $cpu_target --build $sys0_path sysimg.jl") - run(`$julia -C $cpu_target --build $sys0_path sysimg.jl`) - - # Bootstrap off of that to create sys.{ji,o} + if isfile("userimg.jl") + error("$base_dir/userimg.jl already exists, delete manually to continue.") + end + cp(userimg_path, "userimg.jl") + end + try + # Start by building inference0.{ji,o} + inference0_path = joinpath(dirname(sysimg_path), "inference0") + info("Building inference0.o...") + println("$julia -C $cpu_target --build $inference0_path coreimg.jl") + run(`$julia -C $cpu_target --build $inference0_path coreimg.jl`) + + # Bootstrap off off that to create inference.{ji,o} + inference_path = joinpath(dirname(sysimg_path), "inference") + info("Building inference.o...") + println("$julia -C $cpu_target --build $inference_path coreimg.jl") + run(`$julia -C $cpu_target --build $inference_path coreimg.jl`) + + # Bootstrap off off that to create sys.{ji,o} info("Building sys.o...") - println("$julia -C $cpu_target --build $sysimg_path -J $sys0_path.ji -f sysimg.jl") - run(`$julia -C $cpu_target --build $sysimg_path -J $sys0_path.ji -f sysimg.jl`) + println("$julia -C $cpu_target --build $sysimg_path -J $inference_path.ji -f sysimg.jl") + run(`$julia -C $cpu_target --build $sysimg_path -J $inference_path.ji -f sysimg.jl`) if ld != nothing link_sysimg(sysimg_path, ld) @@ -70,7 +78,7 @@ function build_sysimg(sysimg_path=default_sysimg_path, cpu_target="native", user end finally # Cleanup userimg.jl - if isfile("userimg.jl") + if userimg_path != nothing && isfile("userimg.jl") rm("userimg.jl") end end diff --git a/src/dump.c b/src/dump.c index 42d9ee702be9c..fed1d7b9edb72 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1511,13 +1511,13 @@ void jl_restore_system_image(const char *fname) if (ios_file(&f, fname, 1, 0, 0, 0) == NULL) { jl_errorf("System image file \"%s\" not found\n", fname); } - int build_mode = 0; + int imaging_mode = jl_options.build_path != NULL; #ifdef _OS_WINDOWS_ //XXX: the windows linker forces our system image to be // linked against only one dll, I picked libjulia-release - if (jl_is_debugbuild()) build_mode = 1; + if (jl_is_debugbuild()) imaging_mode = 1; #endif - if (!build_mode) { + if (!imaging_mode) { jl_load_sysimg_so(); } #ifdef JL_GC_MARKSWEEP diff --git a/test/core.jl b/test/core.jl index 32b72f12a04ee..a729215440949 100644 --- a/test/core.jl +++ b/test/core.jl @@ -1614,9 +1614,9 @@ macro m6031(x); x; end @test (@m6031 [2,4,6])[2] == 4 # issue #6050 -@test Base.getfield_tfunc([nothing, QuoteNode(:vals)], - Dict{Int64,Tuple{UnitRange{Int64},UnitRange{Int64}}}, - :vals) == (Array{Tuple{UnitRange{Int64},UnitRange{Int64}},1},true) +@test Core.Inference.getfield_tfunc([nothing, QuoteNode(:vals)], + Dict{Int64,Tuple{UnitRange{Int64},UnitRange{Int64}}}, + :vals) == (Array{Tuple{UnitRange{Int64},UnitRange{Int64}},1},true) # issue #6068 x6068 = 1 From 7d8d76dc2647a8b511aeb527b00847a9075c17aa Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 16 May 2015 01:03:22 -0400 Subject: [PATCH 031/181] remove all platform-specific code from Core.Inference and further shrink its size --- Makefile | 3 --- base/abstractarray.jl | 8 ++++++++ base/c.jl | 4 ++++ base/coreimg.jl | 8 ++------ base/options.jl | 24 ++++++++++++------------ base/pointer.jl | 2 -- base/refpointer.jl | 7 ------- src/julia.h | 2 +- ui/repl.c | 5 +++-- 9 files changed, 30 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index f498c86265f9f..62d8c506573ce 100644 --- a/Makefile +++ b/Makefile @@ -149,7 +149,6 @@ CORE_SRCS := base/boot.jl base/coreimg.jl \ base/array.jl \ base/bool.jl \ base/build_h.jl \ - base/c.jl \ base/dict.jl \ base/error.jl \ base/essentials.jl \ @@ -164,13 +163,11 @@ CORE_SRCS := base/boot.jl base/coreimg.jl \ base/number.jl \ base/operators.jl \ base/options.jl \ - base/osutils.jl \ base/pointer.jl \ base/promotion.jl \ base/range.jl \ base/reduce.jl \ base/reflection.jl \ - base/refpointer.jl \ base/subarray.jl \ base/subarray2.jl \ base/tuple.jl diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 8e2af74fb807a..6f03ce3521a58 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -402,6 +402,14 @@ map{T<:Real}(::Type{T}, r::StepRange) = T(r.start):T(r.step):T(last(r)) map{T<:Real}(::Type{T}, r::UnitRange) = T(r.start):T(last(r)) map{T<:FloatingPoint}(::Type{T}, r::FloatRange) = FloatRange(T(r.start), T(r.step), r.len, T(r.divisor)) +## unsafe/pointer conversions ## + +# note: the following type definitions don't mean any AbstractArray is convertible to +# a data Ref. they just map the array element type to the pointer type for +# convenience in cases that work. +pointer{T}(x::AbstractArray{T}) = unsafe_convert(Ptr{T}, x) +pointer{T}(x::AbstractArray{T}, i::Integer) = unsafe_convert(Ptr{T},x) + (i-1)*elsize(x) + ## Unary operators ## conj{T<:Real}(x::AbstractArray{T}) = x diff --git a/base/c.jl b/base/c.jl index c02c47b587b77..b79c6a4112387 100644 --- a/base/c.jl +++ b/base/c.jl @@ -59,6 +59,10 @@ end convert{T<:Union(Int8,UInt8)}(::Type{Cstring}, p::Ptr{T}) = box(Cstring, unbox(Ptr{T}, p)) convert(::Type{Cwstring}, p::Ptr{Cwchar_t}) = box(Cwstring, unbox(Ptr{Cwchar_t}, p)) +# convert strings to ByteString etc. to pass as pointers +cconvert(::Type{Cstring}, s::AbstractString) = bytestring(s) +cconvert(::Type{Cwstring}, s::AbstractString) = wstring(s) + containsnul(p::Ptr, len) = C_NULL != ccall(:memchr, Ptr{Cchar}, (Ptr{Cchar}, Cint, Csize_t), p, 0, len) function unsafe_convert(::Type{Cstring}, s::ByteString) p = unsafe_convert(Ptr{Cchar}, s) diff --git a/base/coreimg.jl b/base/coreimg.jl index 01b4fd4077e43..c54633d8e2d71 100644 --- a/base/coreimg.jl +++ b/base/coreimg.jl @@ -21,10 +21,11 @@ print(a::ANY...) = for x=a; print(x); end include("essentials.jl") include("reflection.jl") include("build_h.jl") -include("c.jl") include("options.jl") # core operations & types +typealias Cint Int32 +typealias Csize_t UInt include("promotion.jl") include("tuple.jl") include("range.jl") @@ -37,7 +38,6 @@ include("number.jl") include("int.jl") include("operators.jl") include("pointer.jl") -include("refpointer.jl") # core array operations include("abstractarray.jl") @@ -78,9 +78,5 @@ precompile(occurs_undef, (Symbol, Expr)) precompile(sym_replace, (UInt8, Array{Any,1}, Array{Any,1}, Array{Any,1}, Array{Any,1})) precompile(symequal, (Symbol, Symbol)) -# For OS specific stuff in I/O -# to force compile of inference -include("osutils.jl") - end # baremodule Inference )) diff --git a/base/options.jl b/base/options.jl index 62a861020de2f..3e08a5a8bda49 100644 --- a/base/options.jl +++ b/base/options.jl @@ -3,17 +3,17 @@ # NOTE: This type needs to be kept in sync with jl_options in src/julia.h immutable JLOptions quiet::Int8 - julia_home::Ptr{Cchar} - julia_bin::Ptr{Cchar} - build_path::Ptr{Cchar} - eval::Ptr{Cchar} - print::Ptr{Cchar} - postboot::Ptr{Cchar} - load::Ptr{Cchar} - image_file::Ptr{Cchar} - cpu_target::Ptr{Cchar} - nprocs::Clong - machinefile::Ptr{Cchar} + julia_home::Ptr{UInt8} + julia_bin::Ptr{UInt8} + build_path::Ptr{UInt8} + eval::Ptr{UInt8} + print::Ptr{UInt8} + postboot::Ptr{UInt8} + load::Ptr{UInt8} + image_file::Ptr{UInt8} + cpu_target::Ptr{UInt8} + nprocs::Int32 + machinefile::Ptr{UInt8} isinteractive::Int8 color::Int8 historyfile::Int8 @@ -28,7 +28,7 @@ immutable JLOptions can_inline::Int8 fast_math::Int8 worker::Int8 - bindto::Ptr{Cchar} + bindto::Ptr{UInt8} end JLOptions() = unsafe_load(cglobal(:jl_options, JLOptions)) diff --git a/base/pointer.jl b/base/pointer.jl index 85625d978c8f9..6e10a8323e29d 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -24,8 +24,6 @@ unsafe_convert(::Type{Ptr{Int8}}, s::ByteString) = convert(Ptr{Int8}, unsafe_con # convert strings to ByteString etc. to pass as pointers cconvert(::Type{Ptr{UInt8}}, s::AbstractString) = bytestring(s) cconvert(::Type{Ptr{Int8}}, s::AbstractString) = bytestring(s) -cconvert(::Type{Cstring}, s::AbstractString) = bytestring(s) -cconvert(::Type{Cwstring}, s::AbstractString) = wstring(s) unsafe_convert{T}(::Type{Ptr{T}}, a::Array{T}) = ccall(:jl_array_ptr, Ptr{T}, (Any,), a) unsafe_convert(::Type{Ptr{Void}}, a::Array) = ccall(:jl_array_ptr, Ptr{Void}, (Any,), a) diff --git a/base/refpointer.jl b/base/refpointer.jl index 969a52447396c..67a3b5e052061 100644 --- a/base/refpointer.jl +++ b/base/refpointer.jl @@ -38,13 +38,6 @@ end unsafe_convert{T}(::Type{Ptr{Void}}, b::RefValue{T}) = convert(Ptr{Void}, unsafe_convert(Ptr{T}, b)) ### Methods for a Ref object that is backed by an array at index i - -# note: the following type definitions don't mean any AbstractArray is convertible to -# a data Ref. they just map the array element type to the pointer type for -# convenience in cases that work. -pointer{T}(x::AbstractArray{T}) = unsafe_convert(Ptr{T}, x) -pointer{T}(x::AbstractArray{T}, i::Integer) = unsafe_convert(Ptr{T},x) + (i-1)*elsize(x) - immutable RefArray{T, A<:AbstractArray, R} <: Ref{T} x::A i::Int diff --git a/src/julia.h b/src/julia.h index a3311ea98028a..7d92895e9a9ea 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1533,7 +1533,7 @@ typedef struct { const char *load; const char *image_file; const char *cpu_target; - long nprocs; + int32_t nprocs; const char *machinefile; int8_t isinteractive; int8_t color; diff --git a/ui/repl.c b/ui/repl.c index db52d34f0ab2d..c756ef6c6932f 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -199,9 +199,10 @@ void parse_opts(int *argcp, char ***argvp) jl_options.nprocs = jl_cpu_cores(); } else { - jl_options.nprocs = strtol(optarg, &endptr, 10); - if (errno != 0 || optarg == endptr || *endptr != 0 || jl_options.nprocs < 1) + long nprocs = strtol(optarg, &endptr, 10); + if (errno != 0 || optarg == endptr || *endptr != 0 || nprocs < 1 || nprocs >= INT_MAX) jl_errorf("julia: -p,--procs= must be an integer >= 1\n"); + jl_options.nprocs = (int)nprocs; } break; case opt_machinefile: From b66c1ffac55ce70eb8e1f15bf618f89419eb8f5f Mon Sep 17 00:00:00 2001 From: Isaiah Norton Date: Tue, 19 May 2015 23:05:42 -0400 Subject: [PATCH 032/181] Fixes for LLVM36 build after #11341 --- src/intrinsics.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 930ba371028c1..b4c0eb241a682 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -1007,10 +1007,19 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, { assert(y->getType() == x->getType()); assert(z->getType() == y->getType()); +#ifdef LLVM37 return builder.CreateCall +#else + return builder.CreateCall3 +#endif (Intrinsic::getDeclaration(jl_Module, Intrinsic::fmuladd, ArrayRef(x->getType())), - {FP(x), FP(y), FP(z)}); + #ifdef LLVM37 + {FP(x), FP(y), FP(z)} + #else + FP(x), FP(y), FP(z) + #endif + ); } #else return math_builder(ctx, true)(). From c056d8f4883c454623e3c16c8ccf30c54b2b1e9f Mon Sep 17 00:00:00 2001 From: Tomas Lycken Date: Wed, 20 May 2015 08:09:35 +0200 Subject: [PATCH 033/181] Better suggestion for replacement of [a] --- base/abstractarray.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 387832999a29c..be434f8598b24 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -17,7 +17,7 @@ if _oldstyle_array_vcat_ function oldstyle_vcat_warning(n::Int) if n == 1 before = "a" - after = "a;" + after = "collect(a)" elseif n == 2 before = "a,b" after = "a;b" From 186b33c437c6313c7e7c36338f9b0a3fa9019969 Mon Sep 17 00:00:00 2001 From: Josh Langsfeld Date: Wed, 20 May 2015 12:04:02 -0400 Subject: [PATCH 034/181] Added fallback <= operator Missing from the set of methods that prevent infinite recursion --- base/promotion.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/promotion.jl b/base/promotion.jl index 6aad8934cbad5..1ffcf73a55506 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -217,7 +217,8 @@ muladd{T<:Number}(x::T, y::T, z::T) = x*y+z ($){T<:Integer}(x::T, y::T) = no_op_err("\$", T) =={T<:Number}(x::T, y::T) = x === y -<{T<:Real}(x::T, y::T) = no_op_err("<", T) + <{T<:Real}(x::T, y::T) = no_op_err("<" , T) +<={T<:Real}(x::T, y::T) = no_op_err("<=", T) div{T<:Real}(x::T, y::T) = no_op_err("div", T) fld{T<:Real}(x::T, y::T) = no_op_err("fld", T) From 3a8f83757ad49e12671ed8d7418c3411abe0f0af Mon Sep 17 00:00:00 2001 From: fcard Date: Wed, 20 May 2015 13:22:03 -0300 Subject: [PATCH 035/181] Fix misplaced variable in Docs.docm (fixes #11348) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `isexpr(_, :macrocall)` and `namify` should use `def′` instead of `def`, as otherwise it will, for example, try to test\namify `quote @macro end` instead of `@macro` when `@doc "x" -> @macro` is called. --- base/docs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/docs.jl b/base/docs.jl index 13383d37ba4f7..5a004905b04e7 100644 --- a/base/docs.jl +++ b/base/docs.jl @@ -190,7 +190,7 @@ function docm(meta, 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) - isexpr(def, :macrocall) && (def = namify(def)) + isexpr(def′, :macrocall) && (def = namify(def′)) return objdoc(meta, def) end From 1dc5472b2c2bbc1ed8d853a7279b95afd87f4687 Mon Sep 17 00:00:00 2001 From: fcard Date: Wed, 20 May 2015 14:42:01 -0300 Subject: [PATCH 036/181] Add tests to macro documentation fix --- test/docs.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/docs.jl b/test/docs.jl index 0ef3f3be505f4..ac5e7825c0b0f 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -3,3 +3,8 @@ @doc "Doc abstract type" -> abstract C74685 <: AbstractArray @test stringmime("text/plain", Docs.doc(C74685))=="Doc abstract type\n" + +macro macro_doctest() end +@doc "Helps test if macros can be documented with `@doc \"...\" -> @...`." -> +@macro_doctest +@test (@doc @macro_doctest) != nothing From 81fa52c6c68e1bd8f81b201e27e5b5a9f4fdf55f Mon Sep 17 00:00:00 2001 From: Jake Bolewski Date: Wed, 20 May 2015 17:02:49 -0400 Subject: [PATCH 037/181] fix circ ref detection in show for isbits types closes #11376 --- base/show.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/show.jl b/base/show.jl index 1586276f94b02..01f54e2a4c67b 100644 --- a/base/show.jl +++ b/base/show.jl @@ -155,7 +155,7 @@ function show_delim_array(io::IO, itr::AbstractArray, op, delim, cl, delim_one, x = itr[i] multiline = isa(x,AbstractArray) && ndims(x)>1 && length(x)>0 newline && multiline && println(io) - if is(x, itr) + if !isbits(x) && is(x, itr) print(io, "#= circular reference =#") elseif compact showcompact_lim(io, x) @@ -195,7 +195,7 @@ function show_delim_array(io::IO, itr, op, delim, cl, delim_one, compact=false, x, state = next(itr,state) multiline = isa(x,AbstractArray) && ndims(x)>1 && length(x)>0 newline && multiline && println(io) - if is(x, itr) + if !isbits(x) && is(x, itr) print(io, "#= circular reference =#") else show(io, x) From d6a8167e27653ef23117f446fa1de7d489ebaf51 Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Wed, 20 May 2015 17:43:13 -0400 Subject: [PATCH 038/181] fix test failure on OS X introduced by f43ff542941498c4bdeb39afc62b --- test/cmdlineargs.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index df1db68d4e201..79d796e1860ac 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -75,6 +75,7 @@ let exename = joinpath(JULIA_HOME, Base.julia_exename()) # only that the filename gets correctly passed to the option struct let fname = tempname() touch(fname) + fname = realpath(fname) try @test readchomp(`$exename --machinefile $fname -e "println(bytestring(Base.JLOptions().machinefile))"`) == fname finally From 1b6f9be5fc7c547affa2a91a1852ff17cf7807fa Mon Sep 17 00:00:00 2001 From: Isaiah Norton Date: Wed, 20 May 2015 22:26:08 -0400 Subject: [PATCH 039/181] Hide 'warning: replacing module' in sysimg build --- src/toplevel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/toplevel.c b/src/toplevel.c index 622082700c31c..3abe931dffaea 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -110,7 +110,7 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) jl_module_t *parent_module = jl_current_module; jl_binding_t *b = jl_get_binding_wr(parent_module, name); jl_declare_constant(b); - if (b->value != NULL) { + if (b->value != NULL && jl_options.build_path == NULL) { jl_printf(JL_STDERR, "Warning: replacing module %s\n", name->name); } jl_module_t *newm = jl_new_module(name); From 48d5e5f23f8003188cdb602807d8202a1cd5ba9d Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 21 May 2015 14:11:28 +0200 Subject: [PATCH 040/181] improve performance of issym and ishermitian --- base/functors.jl | 3 +++ base/sparse.jl | 2 +- base/sparse/sparsematrix.jl | 38 ++++++++++++++++++++++++++++++------- test/sparsedir/sparse.jl | 38 +++++++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 8 deletions(-) diff --git a/base/functors.jl b/base/functors.jl index 24c10dfd43f69..646facee9d749 100644 --- a/base/functors.jl +++ b/base/functors.jl @@ -24,6 +24,9 @@ call(::ExpFun, x) = exp(x) immutable LogFun <: Func{1} end call(::LogFun, x) = log(x) +immutable ConjFun <: Func{1} end +call(::ConjFun, x) = conj(x) + immutable AndFun <: Func{2} end call(::AndFun, x, y) = x & y diff --git a/base/sparse.jl b/base/sparse.jl index bf82e81d3f712..d931e43082e4e 100644 --- a/base/sparse.jl +++ b/base/sparse.jl @@ -2,7 +2,7 @@ module SparseMatrix -using Base: Func, AddFun, OrFun +using Base: Func, AddFun, OrFun, ConjFun, IdFun using Base.Sort: Forward using Base.LinAlg: AbstractTriangular diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index 8cc9f676a3525..eb58d423fbf06 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -2376,17 +2376,41 @@ end squeeze(S::SparseMatrixCSC, dims::Dims) = throw(ArgumentError("squeeze is not available for sparse matrices")) ## Structure query functions +issym(A::SparseMatrixCSC) = is_hermsym(A, IdFun()) -function issym(A::SparseMatrixCSC) - m, n = size(A) - if m != n; return false; end - return countnz(A - A.') == 0 -end +ishermitian(A::SparseMatrixCSC) = is_hermsym(A, ConjFun()) -function ishermitian(A::SparseMatrixCSC) +function is_hermsym(A::SparseMatrixCSC, check::Func) m, n = size(A) if m != n; return false; end - return countnz(A - A') == 0 + + colptr = A.colptr + rowval = A.rowval + nzval = A.nzval + tracker = copy(A.colptr) + @inbounds for col = 1:A.n + for p = tracker[col]:colptr[col+1]-1 + val = nzval[p] + if val == 0; continue; end # In case of explicit zeros + row = rowval[p] + if row < col; return false; end + if row == col # Diagonal element + if val != check(val) + return false + end + else + row2 = rowval[tracker[row]] + if row2 > col; return false; end + if row2 == col # A[i,j] and A[j,i] exists + if val != check(nzval[tracker[row]]) + return false + end + tracker[row] += 1 + end + end + end + end + return true end function istriu{Tv}(A::SparseMatrixCSC{Tv}) diff --git a/test/sparsedir/sparse.jl b/test/sparsedir/sparse.jl index 0c2e3d1fb41e2..db22999119389 100644 --- a/test/sparsedir/sparse.jl +++ b/test/sparsedir/sparse.jl @@ -930,3 +930,41 @@ A = sparse([1.0]) @test norm(A) == 1.0 @test_throws ArgumentError norm(sprand(5,5,0.2),3) @test_throws ArgumentError norm(sprand(5,5,0.2),2) + +# test ishermitian and issym real matrices +A = speye(5,5) +@test ishermitian(A) == true +@test issym(A) == true +A[1,3] = 1.0 +@test ishermitian(A) == false +@test issym(A) == false +A[3,1] = 1.0 +@test ishermitian(A) == true +@test issym(A) == true + +# test ishermitian and issym complex matrices +A = speye(5,5) + im*speye(5,5) +@test ishermitian(A) == false +@test issym(A) == true +A[1,4] = 1.0 + im +@test ishermitian(A) == false +@test issym(A) == false + +A = speye(Complex128, 5,5) +A[3,2] = 1.0 + im +@test ishermitian(A) == false +@test issym(A) == false +A[2,3] = 1.0 - im +@test ishermitian(A) == true +@test issym(A) == false + +A = sparse(zeros(5,5)) +@test ishermitian(A) == true +@test issym(A) == true + +# Test with explicit zeros +A = speye(Complex128, 5,5) +A[3,1] = 2 +A.nzval[2] = 0.0 +@test ishermitian(A) == true +@test issym(A) == true From 9f1a5d85889887f7c367543d6b4cb1b26cb3e5dd Mon Sep 17 00:00:00 2001 From: Mike Innes Date: Thu, 21 May 2015 13:47:38 +0100 Subject: [PATCH 041/181] highlight module in META docs --- base/docs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/docs.jl b/base/docs.jl index 5a004905b04e7..6a7c4ef7709bd 100644 --- a/base/docs.jl +++ b/base/docs.jl @@ -17,7 +17,7 @@ macro init () quote if !isdefined(:META) const $META = ObjectIdDict() - doc($META, doc"Documentation metadata for $(string(current_module())).") + doc($META, @doc_str $("Documentation metadata for `$(current_module())`.")) push!(modules, current_module()) nothing end From a03ad8cb0d6223c3d33c129586eaa6d10c8551a8 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 21 May 2015 12:50:03 -0400 Subject: [PATCH 042/181] empty tuple type needs a UID --- src/jltypes.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/jltypes.c b/src/jltypes.c index 88595022511c8..527554b3e6343 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -3182,6 +3182,7 @@ void jl_init_types(void) jl_ntuple_typename = jl_ntuple_type->name; jl_tupletype_t *empty_tuple_type = jl_apply_tuple_type(jl_emptysvec); + empty_tuple_type->uid = jl_assign_type_uid(); jl_emptytuple = ((jl_datatype_t*)empty_tuple_type)->instance; // non-primitive definitions follow From 49d3b6b6218da55cdc6031eda25f728204e912cc Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 21 May 2015 14:02:19 -0400 Subject: [PATCH 043/181] fix #11357, bug in getfield tfunc --- base/inference.jl | 5 +++-- test/core.jl | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 47fe61e657f96..64a2d4998aa29 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -269,7 +269,8 @@ const getfield_tfunc = function (A, s0, name) if s <: Tuple && name === Symbol return Bottom, true end - if isa(A[2],QuoteNode) && isa(A[2].value,Symbol) + haveargs = A !== nothing && length(A)>1 + if haveargs && isa(A[2],QuoteNode) && isa(A[2].value,Symbol) fld = A[2].value A1 = A[1] if isa(A1,Module) && isdefined(A1,fld) && isconst(A1, fld) @@ -307,7 +308,7 @@ const getfield_tfunc = function (A, s0, name) end end return Bottom, true - elseif isa(A[2],Int) + elseif haveargs && isa(A[2],Int) if isa(A[1],Module) || s === Module return Bottom, true end diff --git a/test/core.jl b/test/core.jl index a729215440949..bcea269683f07 100644 --- a/test/core.jl +++ b/test/core.jl @@ -2816,3 +2816,11 @@ g10995((1, 2)) # issue #11149 @noinline f11149(a,b,args...) = (a,b,args...) @test f11149(1,2,3) == invoke(f11149, Tuple{Int,Int,Int}, 1,2,3) + +# issue #11357 +function f11357() + x = (1,2,3) + i = (1,) + x[i...] +end +@test f11357() === 1 From 7c60974da515bda857361dedab0017c36ea56b06 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 21 May 2015 15:15:49 -0400 Subject: [PATCH 044/181] fix #11271 don't use reinterpret on struct types in fill! --- base/array.jl | 9 +++++---- src/intrinsics.cpp | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/base/array.jl b/base/array.jl index b65e3eef87584..638ff33ea1ce7 100644 --- a/base/array.jl +++ b/base/array.jl @@ -206,10 +206,11 @@ end function fill!{T<:Union(Integer,FloatingPoint)}(a::Array{T}, x) # note: checking bit pattern xT = convert(T,x) - if isbits(T) && ((sizeof(T)==1 && reinterpret(UInt8, xT) == 0) || - (sizeof(T)==2 && reinterpret(UInt16, xT) == 0) || - (sizeof(T)==4 && reinterpret(UInt32, xT) == 0) || - (sizeof(T)==8 && reinterpret(UInt64, xT) == 0)) + if isbits(T) && nfields(T)==0 && + ((sizeof(T)==1 && reinterpret(UInt8, xT) == 0) || + (sizeof(T)==2 && reinterpret(UInt16, xT) == 0) || + (sizeof(T)==4 && reinterpret(UInt32, xT) == 0) || + (sizeof(T)==8 && reinterpret(UInt64, xT) == 0)) ccall(:memset, Ptr{Void}, (Ptr{Void}, Cint, Csize_t), a, 0, length(a)*sizeof(T)) else diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index b4c0eb241a682..1f4b47b4e50ed 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -437,7 +437,8 @@ static Value *generic_box(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ctx) if (vxt == T_void) return vx; if (!vxt->isSingleValueType()) { - jl_error("box: argument not of a primitive type"); + emit_error("reinterpret: expected non-struct value as second argument", ctx); + return UndefValue::get(jl_pvalue_llvmt); } if (llvmt == T_int1) { vx = builder.CreateTrunc(vx, llvmt); From b9222cc12c88649bf7df33459fda02399179835c Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Thu, 21 May 2015 15:39:13 -0400 Subject: [PATCH 045/181] Fix #11387 by changing the option argument in symmetry in CHOLMOD --- base/sparse/cholmod.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index e79d5e06877f8..721c3715bedfd 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -1144,7 +1144,7 @@ function issym(A::Sparse) if s.stype != 0 return isreal(A) end - i = symmetry(A, ifelse(version >= v"3.0.5", 0, 1))[1] # 0 is faster, but had a bug before 3.0.5 + i = symmetry(A, 1)[1] # 0 is faster, but had a bug before 3.0.5 return i == MM_SYMMETRIC || i == MM_SYMMETRIC_POSDIAG end @@ -1153,7 +1153,7 @@ function ishermitian(A::Sparse{Float64}) if s.stype != 0 return true else - i = symmetry(A, ifelse(version >= v"3.0.5", 0, 1))[1] # 0 is faster, but had a bug before 3.0.5 + i = symmetry(A, 1)[1] # 0 is faster, but had a bug before 3.0.5 return i == MM_SYMMETRIC || i == MM_SYMMETRIC_POSDIAG end end @@ -1162,7 +1162,7 @@ function ishermitian(A::Sparse{Complex{Float64}}) if s.stype != 0 return true else - i = symmetry(A, ifelse(version >= v"3.0.5", 0, 1))[1] # 0 is faster, but had a bug before 3.0.5 + i = symmetry(A, 1)[1] # 0 is faster, but had a bug before 3.0.5 return i == MM_HERMITIAN || i == MM_HERMITIAN_POSDIAG end end From 85d27602309de060bf5d93ab54e78d7a09498a4c Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Thu, 21 May 2015 16:42:33 -0400 Subject: [PATCH 046/181] Remove obsolete comments about cholmod_symmetry function [ci skip] --- base/sparse/cholmod.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index 721c3715bedfd..f5ea8bc6163c6 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -1144,7 +1144,7 @@ function issym(A::Sparse) if s.stype != 0 return isreal(A) end - i = symmetry(A, 1)[1] # 0 is faster, but had a bug before 3.0.5 + i = symmetry(A, 1)[1] return i == MM_SYMMETRIC || i == MM_SYMMETRIC_POSDIAG end @@ -1153,7 +1153,7 @@ function ishermitian(A::Sparse{Float64}) if s.stype != 0 return true else - i = symmetry(A, 1)[1] # 0 is faster, but had a bug before 3.0.5 + i = symmetry(A, 1)[1] return i == MM_SYMMETRIC || i == MM_SYMMETRIC_POSDIAG end end @@ -1162,7 +1162,7 @@ function ishermitian(A::Sparse{Complex{Float64}}) if s.stype != 0 return true else - i = symmetry(A, 1)[1] # 0 is faster, but had a bug before 3.0.5 + i = symmetry(A, 1)[1] return i == MM_HERMITIAN || i == MM_HERMITIAN_POSDIAG end end From 343797030987286e63139c6212f3c463ca893eba Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Thu, 21 May 2015 17:16:40 -0400 Subject: [PATCH 047/181] fix #11383 --- base/intfuncs.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 019bd217911fb..89ef71f1bd84a 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -70,8 +70,8 @@ end # ^ for any x supporting * to_power_type(x::Number) = oftype(x*x, x) to_power_type(x) = x -function power_by_squaring(x, p::Integer) - x = to_power_type(x) +function power_by_squaring(x_, p::Integer) + x = to_power_type(x_) if p == 1 return copy(x) elseif p == 0 From 88461184a785ab0ea4d07671134f8936dfd880eb Mon Sep 17 00:00:00 2001 From: ScottPJones Date: Thu, 21 May 2015 12:19:12 -0400 Subject: [PATCH 048/181] Fix #11389 Add UTF32String constructor for Vector{UInt32} --- base/utf32.jl | 5 +++-- doc/stdlib/strings.rst | 4 ++-- test/strings.jl | 13 +++++++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/base/utf32.jl b/base/utf32.jl index 306abcb24a95d..3d6390cb21bdd 100644 --- a/base/utf32.jl +++ b/base/utf32.jl @@ -3,15 +3,16 @@ ## UTF-32 in the native byte order, i.e. plain old character arrays ## immutable UTF32String <: DirectIndexString - data::Array{Char,1} # includes 32-bit NULL termination after string chars + data::Vector{Char} # includes 32-bit NULL termination after string chars - function UTF32String(a::Array{Char,1}) + function UTF32String(a::Vector{Char}) if length(a) < 1 || a[end] != Char(0) throw(ArgumentError("UTF32String data must be NULL-terminated")) end new(a) end end +UTF32String(data::Vector{UInt32}) = UTF32String(reinterpret(Char, data)) next(s::UTF32String, i::Int) = (s.data[i], i+1) endof(s::UTF32String) = length(s.data) - 1 diff --git a/doc/stdlib/strings.rst b/doc/stdlib/strings.rst index b05d50f3fb72f..da0bd958fb93d 100644 --- a/doc/stdlib/strings.rst +++ b/doc/stdlib/strings.rst @@ -383,7 +383,7 @@ .. function:: utf32(s) - Create a UTF-32 string from a byte array, array of ``UInt32``, or + Create a UTF-32 string from a byte array, array of ``Char`` or ``UInt32``, or any other string type. (Conversions of byte arrays check for a byte-order marker in the first four bytes, and do not include it in the resulting string.) @@ -393,7 +393,7 @@ string (so that it is mostly invisible in Julia); this allows the string to be passed directly to external functions requiring NUL-terminated data. This NUL is appended automatically by the - `utf32(s)` conversion function. If you have a ``UInt32`` array + `utf32(s)` conversion function. If you have a ``Char`` or ``UInt32`` array ``A`` that is already NUL-terminated UTF-32 data, then you can instead use `UTF32String(A)`` to construct the string without making a copy of the data and treating the NUL as a terminator diff --git a/test/strings.jl b/test/strings.jl index 1f520aa7d4eaf..38793b4b74186 100644 --- a/test/strings.jl +++ b/test/strings.jl @@ -1603,3 +1603,16 @@ let s = "ba\0d" @test_throws ArgumentError Base.unsafe_convert(Cstring, s) @test_throws ArgumentError Base.unsafe_convert(Cwstring, wstring(s)) end + +# issue # 11389: Vector{UInt32} was copied with UTF32String, unlike Vector{Char} +a = UInt32[48,0] +b = UTF32String(a) +@test b=="0" +a[1] = 65 +@test b=="A" +c = Char['0','\0'] +d = UTF32String(c) +@test d=="0" +c[1] = 'A' +@test d=="A" + From d0476f25162075519b0144a3c0e4366dc0f17591 Mon Sep 17 00:00:00 2001 From: ScottPJones Date: Fri, 22 May 2015 08:23:44 -0400 Subject: [PATCH 049/181] Add documentation of differences between @allocated and @time --- base/util.jl | 8 +++++++- doc/stdlib/base.rst | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/base/util.jl b/base/util.jl index 222c1730171f5..4022167baf206 100644 --- a/base/util.jl +++ b/base/util.jl @@ -199,7 +199,13 @@ macro elapsed(ex) end end -# measure bytes allocated without any contamination from compilation +# measure bytes allocated without *most* contamination from compilation +# Note: This reports a different value from the @time macros, because +# it wraps the call in a function, however, this means that things +# like: @allocated y = foo() +# will not work correctly, because it will set y in the context of +# the local function made by the macro, not the current function + macro allocated(ex) quote let diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index ecf09563309f3..ec16b5016822c 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -759,6 +759,9 @@ System .. function:: @allocated A macro to evaluate an expression, discarding the resulting value, instead returning the total number of bytes allocated during evaluation of the expression. + Note: the expression is evaluated inside a local function, instead of the current context, in order to eliminate the effects of compilation, + however, there still may be some allocations due to JIT compilation. This also makes the results inconsistent with the ``@time`` macros, + which do not try to adjust for the effects of compilation. .. function:: EnvHash() -> EnvHash From 675f1566c642ce1568d2a3830155bbbc3374cee1 Mon Sep 17 00:00:00 2001 From: Oscar Blumberg Date: Fri, 22 May 2015 11:19:18 -0400 Subject: [PATCH 050/181] Fix GC not following module parents Also a missing root for new modules. Thanks to @yuyichao for finding those issues. Fix #11395. --- src/gc.c | 3 +++ src/module.c | 2 ++ src/toplevel.c | 3 +-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/gc.c b/src/gc.c index ca18e6f25ebc1..20f62f3808bf6 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1562,6 +1562,9 @@ NOINLINE static int gc_mark_module(jl_module_t *m, int d) verify_parent1("module", m, &m->constant_table, "constant_table"); refyoung |= gc_push_root(m->constant_table, d); } + + refyoung |= gc_push_root(m->parent, d); + return refyoung; } diff --git a/src/module.c b/src/module.c index d4e3b50123b1a..fb8147763b64e 100644 --- a/src/module.c +++ b/src/module.c @@ -44,9 +44,11 @@ jl_module_t *jl_new_module(jl_sym_t *name) DLLEXPORT jl_value_t *jl_f_new_module(jl_sym_t *name, uint8_t std_imports) { jl_module_t *m = jl_new_module(name); + JL_GC_PUSH1(&m); m->parent = jl_main_module; gc_wb(m, m->parent); if (std_imports) jl_add_standard_imports(m); + JL_GC_POP(); return (jl_value_t*)m; } diff --git a/src/toplevel.c b/src/toplevel.c index 3abe931dffaea..453872696c869 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -116,8 +116,7 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) jl_module_t *newm = jl_new_module(name); newm->parent = parent_module; b->value = (jl_value_t*)newm; - - gc_wb(parent_module, newm); + gc_wb_binding(b, newm); if (parent_module == jl_main_module && name == jl_symbol("Base")) { // pick up Base module during bootstrap From e6721ae4773832d9616716df30bd5d90104be656 Mon Sep 17 00:00:00 2001 From: pabloferz Date: Fri, 22 May 2015 12:19:54 -0500 Subject: [PATCH 051/181] Avoid the printing of e+00 --- base/mpfr.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/mpfr.jl b/base/mpfr.jl index 22eb843990aeb..b148f6c8b89ab 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -768,14 +768,14 @@ function string(x::BigFloat) lng::Int32 = 127 buf = Array(UInt8, lng + 1) lng = ccall((:mpfr_snprintf,:libmpfr), Int32, (Ptr{UInt8}, Culong, Ptr{UInt8}, Ptr{BigFloat}...), buf, lng + 1, "%.Re", &x) - (84 <= lng <= 127) && return bytestring(pointer(buf), lng) + (84 <= lng <= 127) && return bytestring(pointer(buf), 1 <= x < 10 ? lng-4 : lng) if lng < 84 # print at least 78 decimal places lng = ccall((:mpfr_sprintf,:libmpfr), Int32, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BigFloat}...), buf, "%.78Re", &x) - elseif lng > 127 + else buf = Array(UInt8, lng + 1) lng = ccall((:mpfr_snprintf,:libmpfr), Int32, (Ptr{UInt8}, Culong, Ptr{UInt8}, Ptr{BigFloat}...), buf, lng + 1, "%.Re", &x) end - return bytestring(pointer(buf), lng) + return bytestring(pointer(buf), 1 <= x < 10 ? lng-4 : lng) end print(io::IO, b::BigFloat) = print(io, string(b)) From 1c74420a91f5870ef1b6b880121257e9d8fd969e Mon Sep 17 00:00:00 2001 From: pabloferz Date: Fri, 22 May 2015 14:00:04 -0500 Subject: [PATCH 052/181] Avoid the printing of e+00 --- test/mpfr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/mpfr.jl b/test/mpfr.jl index 31b6f0058cbec..512008d79979b 100644 --- a/test/mpfr.jl +++ b/test/mpfr.jl @@ -365,7 +365,7 @@ z = parse(BigInt,"9223372036854775809") @test typeof(round(UInt, x)) == UInt && round(UInt, x) == 0x2a # string representation -str = "1.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012e+00" +str = "1.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012" with_bigfloat_precision(406) do @test string(nextfloat(BigFloat(1))) == str end From 682e6b1e8e08fd73a34446df476869025e1fc105 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Thu, 7 May 2015 23:19:57 -0500 Subject: [PATCH 053/181] Add constraint check on b in intersect_typevar Fixes #11136 --- src/jltypes.c | 12 ++++++ test/core.jl | 109 ++++++++++++++++++++++++++++---------------------- 2 files changed, 73 insertions(+), 48 deletions(-) diff --git a/src/jltypes.c b/src/jltypes.c index 527554b3e6343..cf3e2ee2c6ff8 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -739,6 +739,18 @@ static jl_value_t *intersect_typevar(jl_tvar_t *a, jl_value_t *b, break; } } + if (jl_is_typevar(b)) { + for(i=0; i < penv->n; i+=2) { + if (penv->data[i] == b && !jl_is_typevar(penv->data[i+1])) { + jl_value_t *ti = jl_type_intersection((jl_value_t*)a, penv->data[i+1]); + if (ti == (jl_value_t*)jl_bottom_type) { + JL_GC_POP(); + return ti; + } + break; + } + } + } extend((jl_value_t*)a, b, penv); if (jl_is_typevar(b)) { JL_GC_POP(); diff --git a/test/core.jl b/test/core.jl index bcea269683f07..f1da5e3706d1f 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4,6 +4,12 @@ const Bottom = Union() +function testintersect(a, b, result, cmp=is) + @test cmp(typeintersect(a, b), result) + @test cmp(typeintersect(b, a), result) +end +isnot(x,y) = !is(x,y) + # basic type relationships @test Int8 <: Integer @test Int32 <: Integer @@ -23,7 +29,7 @@ const Bottom = Union() @test Array{Int8,1} <: Array{Int8,1} @test !(Type{Bottom} <: Type{Int32}) @test !(Vector{Float64} <: Vector{Union(Float64,Float32)}) -@test is(Bottom, typeintersect(Vector{Float64},Vector{Union(Float64,Float32)})) +testintersect(Vector{Float64}, Vector{Union(Float64,Float32)}, Bottom) @test !isa(Array,Type{Any}) @test Type{Complex} <: DataType @@ -31,88 +37,88 @@ const Bottom = Union() @test !(Type{Ptr{Bottom}} <: Type{Ptr}) @test !(Type{Rational{Int}} <: Type{Rational}) let T = TypeVar(:T,true) - @test !is(Bottom, typeintersect(Array{Bottom},AbstractArray{T})) - @test is(Bottom, typeintersect(Tuple{Type{Ptr{UInt8}},Ptr{Bottom}}, - Tuple{Type{Ptr{T}},Ptr{T}})) + testintersect(Array{Bottom},AbstractArray{T}, Bottom, isnot) + testintersect(Tuple{Type{Ptr{UInt8}},Ptr{Bottom}}, + Tuple{Type{Ptr{T}},Ptr{T}}, Bottom) @test !(Type{T} <: TypeVar) - @test isequal(typeintersect(Tuple{Range{Int},Tuple{Int,Int}},Tuple{AbstractArray{T},Dims}), + testintersect(Tuple{Range{Int},Tuple{Int,Int}},Tuple{AbstractArray{T},Dims}, Tuple{Range{Int},Tuple{Int,Int}}) - @test isequal(typeintersect(Tuple{T, AbstractArray{T}}, Tuple{Number, Array{Int,1}}), + testintersect(Tuple{T, AbstractArray{T}}, Tuple{Number, Array{Int,1}}, Tuple{Int, Array{Int,1}}) - @test isequal(typeintersect(Tuple{T, AbstractArray{T}}, Tuple{Int, Array{Number,1}}), + testintersect(Tuple{T, AbstractArray{T}}, Tuple{Int, Array{Number,1}}, Tuple{Int, Array{Number,1}}) - @test isequal(typeintersect(Tuple{T, AbstractArray{T}},Tuple{Any, Array{Number,1}}), - Tuple{Number, Array{Number,1}}) - @test !is(Bottom, typeintersect(Tuple{Array{T}, Array{T}}, Tuple{Array, Array{Any}})) + testintersect(Tuple{T, AbstractArray{T}},Tuple{Any, Array{Number,1}}, + Tuple{Number, Array{Number,1}}, isequal) + testintersect(Tuple{Array{T}, Array{T}}, Tuple{Array, Array{Any}}, Bottom, isnot) f47{T}(x::Vector{Vector{T}}) = 0 @test_throws MethodError f47(Array(Vector,0)) @test f47(Array(Vector{Int},0)) == 0 - @test typeintersect(Tuple{T,T}, Tuple{Union(Float64,Int64),Int64}) == Tuple{Int64,Int64} - @test typeintersect(Tuple{T,T}, Tuple{Int64,Union(Float64,Int64)}) == Tuple{Int64,Int64} + testintersect(Tuple{T,T}, Tuple{Union(Float64,Int64),Int64}, Tuple{Int64,Int64}) + testintersect(Tuple{T,T}, Tuple{Int64,Union(Float64,Int64)}, Tuple{Int64,Int64}) TT = TypeVar(:T) S = TypeVar(:S,true); N = TypeVar(:N,true); SN = TypeVar(:S,Number,true) - @test typeintersect(Type{TypeVar(:T,Array{TT,1})},Type{Array{SN,N}}) == Type{Array{SN,1}} + testintersect(Type{TypeVar(:T,Array{TT,1})},Type{Array{SN,N}}, Type{Array{SN,1}}) # issue #5359 - @test typeintersect(Tuple{Type{Array{T,1}},Array{T,1}}, - Tuple{Type{AbstractVector},Vector{Int}}) === Bottom + testintersect(Tuple{Type{Array{T,1}},Array{T,1}}, + Tuple{Type{AbstractVector},Vector{Int}}, Bottom) # issue #5559 - @test typeintersect(Tuple{Type{Vector{Complex128}}, AbstractVector}, - Tuple{Type{Array{T,N}}, Array{S,N}}) == Tuple{Type{Vector{Complex128}},Vector} - @test typeintersect(Tuple{Type{Vector{Complex128}}, AbstractArray}, - Tuple{Type{Array{T,N}}, Array{S,N}}) == Tuple{Type{Vector{Complex128}},Vector} + testintersect(Tuple{Type{Vector{Complex128}}, AbstractVector}, + Tuple{Type{Array{T,N}}, Array{S,N}}, Tuple{Type{Vector{Complex128}},Vector}, isequal) + testintersect(Tuple{Type{Vector{Complex128}}, AbstractArray}, + Tuple{Type{Array{T,N}}, Array{S,N}}, Tuple{Type{Vector{Complex128}},Vector}, isequal) - @test typeintersect(Type{Array{T}}, Type{AbstractArray{T}}) === Bottom + testintersect(Type{Array{T}}, Type{AbstractArray{T}}, Bottom) - @test typeintersect(Type{Tuple{Bool,Vararg{Int}}}, Type{Tuple{Vararg{T}}}) === Bottom - @test typeintersect(Type{Tuple{Bool,Vararg{Int}}}, Type{Tuple{T,Vararg{T}}}) === Bottom + testintersect(Type{Tuple{Bool,Vararg{Int}}}, Type{Tuple{Vararg{T}}}, Bottom) + testintersect(Type{Tuple{Bool,Vararg{Int}}}, Type{Tuple{T,Vararg{T}}}, Bottom) - @test typeintersect(Tuple{Rational{T},T}, Tuple{Rational{Integer},Int}) === Tuple{Rational{Integer},Int} + testintersect(Tuple{Rational{T},T}, Tuple{Rational{Integer},Int}, Tuple{Rational{Integer},Int}) - @test typeintersect(Pair{T,Ptr{T}}, Pair{Ptr{S},S}) === Bottom - @test typeintersect(Tuple{T,Ptr{T}}, Tuple{Ptr{S},S}) === Bottom + testintersect(Pair{T,Ptr{T}}, Pair{Ptr{S},S}, Bottom) + testintersect(Tuple{T,Ptr{T}}, Tuple{Ptr{S},S}, Bottom) end let N = TypeVar(:N,true) - @test isequal(typeintersect(Tuple{NTuple{N,Integer},NTuple{N,Integer}}, - Tuple{Tuple{Integer,Integer}, Tuple{Vararg{Integer}}}), + testintersect(Tuple{NTuple{N,Integer},NTuple{N,Integer}}, + Tuple{Tuple{Integer,Integer}, Tuple{Vararg{Integer}}}, Tuple{Tuple{Integer,Integer}, Tuple{Integer,Integer}}) - @test isequal(typeintersect(Tuple{NTuple{N,Integer},NTuple{N,Integer}}, - Tuple{Tuple{Vararg{Integer}}, Tuple{Integer,Integer}}), + testintersect(Tuple{NTuple{N,Integer},NTuple{N,Integer}}, + Tuple{Tuple{Vararg{Integer}}, Tuple{Integer,Integer}}, Tuple{Tuple{Integer,Integer}, Tuple{Integer,Integer}}) local A = typeintersect(Tuple{NTuple{N,Any},Array{Int,N}}, Tuple{Tuple{Int,Vararg{Int}},Array}) local B = Tuple{Tuple{Int,Vararg{Int}},Array{Int,N}} @test A<:B && B<:A - @test isequal(typeintersect(Tuple{NTuple{N,Any},Array{Int,N}}, - Tuple{Tuple{Int,Vararg{Int}},Array{Int,2}}), + testintersect(Tuple{NTuple{N,Any},Array{Int,N}}, + Tuple{Tuple{Int,Vararg{Int}},Array{Int,2}}, Tuple{Tuple{Int,Int}, Array{Int,2}}) end -@test is(Bottom, typeintersect(Type{Any},Type{Complex})) -@test is(Bottom, typeintersect(Type{Any},Type{TypeVar(:T,Real)})) +testintersect(Type{Any},Type{Complex}, Bottom) +testintersect(Type{Any},Type{TypeVar(:T,Real)}, Bottom) @test !(Type{Array{Integer}} <: Type{AbstractArray{Integer}}) @test !(Type{Array{Integer}} <: Type{Array{TypeVar(:T,Integer)}}) -@test is(Bottom, typeintersect(Type{Function},UnionType)) -@test is(Type{Int32}, typeintersect(Type{Int32},DataType)) +testintersect(Type{Function},UnionType,Bottom) +testintersect(Type{Int32}, DataType, Type{Int32}) @test !(Type <: TypeVar) -@test !is(Bottom, typeintersect(DataType, Type)) -@test !is(Bottom, typeintersect(UnionType, Type)) -@test !is(Bottom, typeintersect(DataType, Type{Int})) -@test !is(Bottom, typeintersect(DataType, Type{TypeVar(:T,Int)})) -@test !is(Bottom, typeintersect(DataType, Type{TypeVar(:T,Integer)})) +testintersect(DataType, Type, Bottom, isnot) +testintersect(UnionType, Type, Bottom, isnot) +testintersect(DataType, Type{Int}, Bottom, isnot) +testintersect(DataType, Type{TypeVar(:T,Int)}, Bottom, isnot) +testintersect(DataType, Type{TypeVar(:T,Integer)}, Bottom, isnot) -@test typeintersect(Tuple{Vararg{Int}}, Tuple{Vararg{Bool}}) === Tuple{} -@test typeintersect(Type{Tuple{Vararg{Int}}}, Type{Tuple{Vararg{Bool}}}) === Bottom -@test typeintersect(Tuple{Bool,Vararg{Int}}, Tuple{Vararg{Bool}}) === Tuple{Bool,} +testintersect(Tuple{Vararg{Int}}, Tuple{Vararg{Bool}}, Tuple{}) +testintersect(Type{Tuple{Vararg{Int}}}, Type{Tuple{Vararg{Bool}}}, Bottom) +testintersect(Tuple{Bool,Vararg{Int}}, Tuple{Vararg{Bool}}, Tuple{Bool,}) let T = TypeVar(:T,Union(Float32,Float64)) - @test typeintersect(AbstractArray, Matrix{T}) == Matrix{T} + testintersect(AbstractArray, Matrix{T}, Matrix{T}) end let T = TypeVar(:T,Union(Float32,Float64),true) - @test typeintersect(AbstractArray, Matrix{T}) == Matrix{T} + testintersect(AbstractArray, Matrix{T}, Matrix{T}) end @test isa(Int,Type{TypeVar(:T,Number)}) @@ -146,7 +152,7 @@ end # issue #2997 let T = TypeVar(:T,Union(Float64,Array{Float64,1}),true) - @test typeintersect(T,Real) === Float64 + testintersect(T,Real,Float64) end # join @@ -1361,7 +1367,7 @@ abstract IT4805{N, T} let T = TypeVar(:T,Int,true) N = TypeVar(:N,true) - @test typeintersect(Type{IT4805{1,T}}, Type{TypeVar(:_,IT4805{N,Int})}) != Bottom + testintersect(Type{IT4805{1,T}}, Type{TypeVar(:_,IT4805{N,Int})}, Bottom, isnot) end let @@ -2002,7 +2008,7 @@ abstract AbstractThing{T,N} type ConcreteThing{T<:FloatingPoint,N} <: AbstractThing{T,N} end -@test typeintersect(AbstractThing{TypeVar(:T,true),2}, ConcreteThing) == ConcreteThing{TypeVar(:T,FloatingPoint),2} +testintersect(AbstractThing{TypeVar(:T,true),2}, ConcreteThing, ConcreteThing{TypeVar(:T,FloatingPoint),2}, isequal) # issue #8978 module I8978 @@ -2824,3 +2830,10 @@ function f11357() x[i...] end @test f11357() === 1 + +# issue #11136 +type A11136 end +type B11136 end +let T = TypeVar(:T, true), TB = TypeVar(:T, B11136, true) + testintersect(Tuple{T, T}, Tuple{A11136, TB}, Bottom) +end From bcf5361ec68ba02f4a861b4b7673da438ff0c7b1 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Wed, 13 May 2015 11:42:52 -0500 Subject: [PATCH 054/181] args_morespecific for TypeVars: don't fail due to invariance (fixes #8652) In jl_args_morespecific(a,b), one of the important tests is to call type_match_(b,a), essentially reasoning that if b <: a then a cannot be more specific than b. The problem is that this test can fail for an independent reason, like invariance. This takes the drastic step of keeping invariance=false for the type_match_ check in jl_args_morespecific. Surprisingly, this doesn't appear to break anything. --- src/gf.c | 8 +++++--- src/jltypes.c | 4 ++++ src/julia_internal.h | 1 + test/core.jl | 18 ++++++++++++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/gf.c b/src/gf.c index 794ab97c0c6b8..405caa438b9c1 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1126,10 +1126,12 @@ DLLEXPORT int jl_args_morespecific(jl_value_t *a, jl_value_t *b) return msp; } if (jl_has_typevars(a)) { - //if (jl_type_match_morespecific(b,a) == (jl_value_t*)jl_false) - // return 1; + type_match_invariance_mask = 0; + //int result = jl_type_match_morespecific(b,a) == (jl_value_t*)jl_false); // this rule seems to work better: - if (jl_type_match(b,a) == (jl_value_t*)jl_false) + int result = jl_type_match(b,a) == (jl_value_t*)jl_false; + type_match_invariance_mask = 1; + if (result) return 1; } int nmsp = jl_type_morespecific(b,a); diff --git a/src/jltypes.c b/src/jltypes.c index cf3e2ee2c6ff8..e619f643d1d09 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -2718,6 +2718,8 @@ int jl_type_morespecific(jl_value_t *a, jl_value_t *b) // ---------------------------------------------------------------------------- +int type_match_invariance_mask = 1; + static jl_value_t *type_match_(jl_value_t *child, jl_value_t *parent, cenv_t *env, int morespecific, int invariant); @@ -2728,6 +2730,7 @@ static jl_value_t *tuple_match(jl_datatype_t *child, jl_datatype_t *parent, size_t cl = jl_nparams(child); size_t pl = jl_nparams(parent); int mode = 0; + invariant = invariant & type_match_invariance_mask; while(1) { int cseq = (cibody; if (jl_is_typector(parent)) diff --git a/src/julia_internal.h b/src/julia_internal.h index 2474f70bf1017..a75feae456d1a 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -85,6 +85,7 @@ int jl_tuple_subtype(jl_value_t **child, size_t cl, jl_datatype_t *pdt, int ta); int jl_subtype_invariant(jl_value_t *a, jl_value_t *b, int ta); jl_value_t *jl_type_match(jl_value_t *a, jl_value_t *b); +extern int type_match_invariance_mask; jl_value_t *jl_type_match_morespecific(jl_value_t *a, jl_value_t *b); int jl_types_equal_generic(jl_value_t *a, jl_value_t *b, int useenv); jl_datatype_t *jl_inst_concrete_tupletype_v(jl_value_t **p, size_t np); diff --git a/test/core.jl b/test/core.jl index f1da5e3706d1f..4d42d8c78be36 100644 --- a/test/core.jl +++ b/test/core.jl @@ -155,6 +155,19 @@ let T = TypeVar(:T,Union(Float64,Array{Float64,1}),true) testintersect(T,Real,Float64) end +# issue #8652 +args_morespecific(a, b) = ccall(:jl_args_morespecific, Cint, (Any,Any), a, b) != 0 +let T1 = TypeVar(:T, Integer, true), T2 = TypeVar(:T, Integer, true) + a = Tuple{Type{T1}, T1} + b2 = Tuple{Type{T2}, Integer} + @test args_morespecific(a, b2) + @test !args_morespecific(b2, a) + a = Tuple{Type{T1}, Ptr{T1}} + b2 = Tuple{Type{T2}, Ptr{Integer}} + @test args_morespecific(a, b2) + @test !args_morespecific(b2, a) +end + # join @test typejoin(Int8,Int16) === Signed @test typejoin(Int,AbstractString) === Any @@ -317,6 +330,11 @@ let m = sptest3(:a) @test is(m(0),Symbol) end +sptest4{T}(x::T, y::T) = 42 +sptest4{T}(x::T, y) = 44 +@test sptest4(1,2) == 42 +@test sptest4(1, "cat") == 44 + # closures function clotest() c = 0 From 65cc7f3f8021e7c225a55c04136ae78a825b4729 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Thu, 21 May 2015 17:20:10 -0500 Subject: [PATCH 055/181] Also check eqc in intersect_typevar (fixes #11367) --- src/jltypes.c | 10 ++++++++++ test/core.jl | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/src/jltypes.c b/src/jltypes.c index e619f643d1d09..3a3125e905ee0 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -750,6 +750,16 @@ static jl_value_t *intersect_typevar(jl_tvar_t *a, jl_value_t *b, break; } } + for(i=0; i < eqc->n; i+=2) { + if (eqc->data[i] == b && !jl_is_typevar(eqc->data[i+1])) { + jl_value_t *ti = jl_type_intersection((jl_value_t*)a, eqc->data[i+1]); + if (ti == (jl_value_t*)jl_bottom_type) { + JL_GC_POP(); + return ti; + } + break; + } + } } extend((jl_value_t*)a, b, penv); if (jl_is_typevar(b)) { diff --git a/test/core.jl b/test/core.jl index 4d42d8c78be36..e643eb721ba1a 100644 --- a/test/core.jl +++ b/test/core.jl @@ -2855,3 +2855,9 @@ type B11136 end let T = TypeVar(:T, true), TB = TypeVar(:T, B11136, true) testintersect(Tuple{T, T}, Tuple{A11136, TB}, Bottom) end + +# issue #11367 +abstract Foo11367 +let T1 = TypeVar(:T1, true), T2 = TypeVar(:T2, Foo11367, true) + testintersect(Tuple{T1, T1}, Tuple{Type{BigInt}, T2}, Bottom) +end From bb932646d9c634860c7319861d5359718c740ff5 Mon Sep 17 00:00:00 2001 From: ScottPJones Date: Thu, 21 May 2015 12:06:47 -0400 Subject: [PATCH 056/181] Fix #11379 deprecate utf32(Integer...) --- NEWS.md | 3 +++ base/deprecated.jl | 4 ++++ base/utf32.jl | 9 --------- test/unicode.jl | 4 ++-- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/NEWS.md b/NEWS.md index 683b3c6d4fa58..0381fc6c4dd14 100644 --- a/NEWS.md +++ b/NEWS.md @@ -374,6 +374,8 @@ Deprecated or removed The two argument form `isvalid(type, value)` can be used with the above types, with values of type `Vector{UInt8}`, `Vector{UInt16}`, `Vector{UInt32}`, and `Vector{Char}` ([#11241]). + * Instead of `utf32(64,123,...)` use `utf32(UInt32[64,123,...])` ([#11379]). + Julia v0.3.0 Release Notes ========================== @@ -1420,3 +1422,4 @@ Too numerous to mention. [#11145]: https://github.com/JuliaLang/julia/issues/11145 [#11171]: https://github.com/JuliaLang/julia/issues/11171 [#11241]: https://github.com/JuliaLang/julia/issues/11241 +[#11379]: https://github.com/JuliaLang/julia/issues/11379 diff --git a/base/deprecated.jl b/base/deprecated.jl index 4abccc3c98aea..13be7c4bfbb55 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -457,3 +457,7 @@ export float32_isvalid, float64_isvalid @deprecate is_valid_utf8(str) isvalid(UTF8String, str) @deprecate is_valid_utf16(str) isvalid(UTF16String, str) @deprecate is_valid_utf32(str) isvalid(UTF32String, str) + +# 11379 + +@deprecate utf32(c::Integer...) UTF32String(UInt32[c...,0]) diff --git a/base/utf32.jl b/base/utf32.jl index 3d6390cb21bdd..b183912491de0 100644 --- a/base/utf32.jl +++ b/base/utf32.jl @@ -18,15 +18,6 @@ next(s::UTF32String, i::Int) = (s.data[i], i+1) endof(s::UTF32String) = length(s.data) - 1 length(s::UTF32String) = length(s.data) - 1 -function utf32(c::Integer...) - a = Array(Char, length(c) + 1) - for i = 1:length(c) - a[i] = Char(c[i]) - end - a[end] = Char(0) - UTF32String(a) -end - utf32(x) = convert(UTF32String, x) convert(::Type{UTF32String}, c::Char) = UTF32String(Char[c, Char(0)]) convert(::Type{UTF32String}, s::UTF32String) = s diff --git a/test/unicode.jl b/test/unicode.jl index 6742e86786f53..5d3a64285ca83 100644 --- a/test/unicode.jl +++ b/test/unicode.jl @@ -80,12 +80,12 @@ else end str1 = "∀ ε > 0, ∃ δ > 0: |x-y| < δ ⇒ |f(x)-f(y)| < ε" - str2 = utf32( + str2 = UTF32String(UInt32[ 8704, 32, 949, 32, 62, 32, 48, 44, 32, 8707, 32, 948, 32, 62, 32, 48, 58, 32, 124, 120, 45, 121, 124, 32, 60, 32, 948, 32, 8658, 32, 124, 102, 40, 120, 41, 45, 102, 40, 121, 41, 124, 32, 60, 32, 949 - ) + ,0]) @test str1 == str2 # Cleanup unicode data From 2fedc274232bdf944dcc86eb05265852de7d1262 Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Tue, 19 May 2015 19:10:02 -0400 Subject: [PATCH 057/181] Fix sparse matrix nits, fixes #9917, fixes #11032 --- base/sparse/sparsematrix.jl | 13 ++++++++++--- test/sparsedir/sparse.jl | 4 ++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index 8cc9f676a3525..3c2a57844661b 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -184,7 +184,9 @@ convert{T}(::Type{AbstractMatrix{T}}, A::SparseMatrixCSC) = convert(SparseMatrix convert(::Type{Matrix}, S::SparseMatrixCSC) = full(S) function full{Tv}(S::SparseMatrixCSC{Tv}) - A = zeros(Tv, S.m, S.n) + # Handle cases where zero(Tv) is not defined but the array is dense. + # (Should we really worry about this?) + A = length(S) == nnz(S) ? Array(Tv, S.m, S.n) : zeros(Tv, S.m, S.n) for col = 1 : S.n, k = S.colptr[col] : (S.colptr[col+1]-1) A[S.rowval[k], col] = S.nzval[k] end @@ -1223,7 +1225,7 @@ function rangesearch(haystack::Range, needle) (rem==0 && 1<=i+1<=length(haystack)) ? i+1 : 0 end -getindex(A::SparseMatrixCSC, i::Integer) = getindex(A, ind2sub(size(A),i)) +getindex(A::SparseMatrixCSC, i::Integer) = isempty(A) ? throw(BoundsError()) : getindex(A, ind2sub(size(A),i)) getindex(A::SparseMatrixCSC, I::Tuple{Integer,Integer}) = getindex(A, I[1], I[2]) function getindex{T}(A::SparseMatrixCSC{T}, i0::Integer, i1::Integer) @@ -1636,7 +1638,11 @@ function getindex{Tv}(A::SparseMatrixCSC{Tv}, I::AbstractArray{Bool}) end function getindex{Tv}(A::SparseMatrixCSC{Tv}, I::AbstractArray) - szA = size(A); colptrA = A.colptr; rowvalA = A.rowval; nzvalA = A.nzval + szA = size(A) + nA = szA[1]*szA[2] + colptrA = A.colptr + rowvalA = A.rowval + nzvalA = A.nzval n = length(I) outm = size(I,1) @@ -1652,6 +1658,7 @@ function getindex{Tv}(A::SparseMatrixCSC{Tv}, I::AbstractArray) idxB = 1 for i in 1:n + ((I[i] < 1) | (I[i] > nA)) && throw(BoundsError()) row,col = ind2sub(szA, I[i]) for r in colptrA[col]:(colptrA[col+1]-1) @inbounds if rowvalA[r] == row diff --git a/test/sparsedir/sparse.jl b/test/sparsedir/sparse.jl index 0c2e3d1fb41e2..5eb02cf81e588 100644 --- a/test/sparsedir/sparse.jl +++ b/test/sparsedir/sparse.jl @@ -749,6 +749,10 @@ end # issue #9917 @test sparse([]') == reshape(sparse([]), 1, 0) +@test full(sparse([])) == zeros(0, 1) +@test_throws BoundsError sparse([])[1] +x = speye(100) +@test_throws BoundsError x[-10:10] for T in (Int, Float16, Float32, Float64, BigInt, BigFloat) let R=rand(T[1:100;],2,2), I=rand(T[1:100;],2,2) From 39e83f77ffa7d1f846abaa3be3843d3a3a0ea66e Mon Sep 17 00:00:00 2001 From: Blake Johnson Date: Sun, 17 May 2015 23:23:47 -0400 Subject: [PATCH 058/181] Fix issue #11281. The problem is that `prefix` ought to be "" when the string is just the tilde. --- base/REPLCompletions.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index f2a0156b9583b..f42404173fff9 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -110,10 +110,11 @@ function complete_keyword(s::ByteString) end function complete_path(path::AbstractString, pos) - if ismatch(r"^~(?:/|$)", path) - path = homedir() * path[2:end] + dir, prefix = splitdir(expanduser(path)) + # if the path is just "~", don't consider the expanded username as a prefix + @unix_only if path == "~" + dir, prefix = expanduser(path), "" end - dir, prefix = splitdir(path) local files try if length(dir) == 0 From 09cd655470ea50bb3b6bbf56e6ebacd1e872db7c Mon Sep 17 00:00:00 2001 From: Blake Johnson Date: Sat, 23 May 2015 00:38:56 -0400 Subject: [PATCH 059/181] Avoid the throw() in expanduser(). --- base/REPLCompletions.jl | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index f42404173fff9..31c341d2cd4d5 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -110,10 +110,15 @@ function complete_keyword(s::ByteString) end function complete_path(path::AbstractString, pos) - dir, prefix = splitdir(expanduser(path)) - # if the path is just "~", don't consider the expanded username as a prefix - @unix_only if path == "~" - dir, prefix = expanduser(path), "" + if Base.is_unix(OS_NAME) && ismatch(r"^~(?:/|$)", path) + # if the path is just "~", don't consider the expanded username as a prefix + if path == "~" + dir, prefix = homedir(), "" + else + dir, prefix = splitdir(homedir() * path[2:end]) + end + else + dir, prefix = splitdir(path) end local files try From 49c504e1640f08bfbd7f5dc2ed63e9de606899f3 Mon Sep 17 00:00:00 2001 From: Jim Garrison Date: Fri, 22 May 2015 23:40:00 -0700 Subject: [PATCH 060/181] Add spaces after commas in methodshow This is meant to supercede #4957, where the outcome seemed to be > I like the extra spaces but the color issue is too much of a bikeshed. -- @JeffBezanson I am being fairly conservative in that I added spaces *only* to the method table. Closes #4957. --- base/methodshow.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/methodshow.jl b/base/methodshow.jl index 168e8e6dded75..935c0593d0ebd 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -45,7 +45,7 @@ function show(io::IO, m::Method) end print(io, "(") print_joined(io, [isempty(d[2]) ? d[1] : d[1]*"::"*d[2] for d in decls], - ",", ",") + ", ", ", ") print(io, ")") if line > 0 print(io, " at ", file, ":", line) @@ -119,7 +119,7 @@ function writemime(io::IO, ::MIME"text/html", m::Method) end print(io, "(") print_joined(io, [isempty(d[2]) ? d[1] : d[1]*"::"*d[2]*"" - for d in decls], ",", ",") + for d in decls], ", ", ", ") print(io, ")") if line > 0 u = url(m) From bfd93352818f19a72da6baae45e43b5e822d34f4 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Sat, 23 May 2015 10:03:06 +0100 Subject: [PATCH 061/181] Add documentation about deprecation process Cf. #10612 --- base/deprecated.jl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/base/deprecated.jl b/base/deprecated.jl index 13be7c4bfbb55..b2406918faa1d 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1,4 +1,22 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license +# +# Deprecated functions and objects +# +# Please add new deprecations at the bottom of the file. +# A function deprecated in a release will be removed in the next one. +# Please also add a reference to the pull request which introduced the +# deprecation. +# +# For simple cases where a direct replacement is available, use @deprecate: +# the first argument is the signature of the deprecated method, the second one +# is the call which replaces it. Remove the definition of the deprecated method +# and unexport it, as @deprecate takes care of calling the replacement +# and of exporting the function. +# +# For more complex cases, move the body of the deprecated method in this file, +# and call depwarn() directly from inside it. The symbol depwarn() expects is +# the name of the function, which is used to ensure that the deprecation warning +# is only printed the first time for each call place. macro deprecate(old,new) meta = Expr(:meta, :noinline) From dc684d256a98573f491dfdccbd359fd34952e9eb Mon Sep 17 00:00:00 2001 From: rickhg12hs Date: Sat, 23 May 2015 07:41:13 -0400 Subject: [PATCH 062/181] Fix task macro description in parallel.rst It wraps an expression in a Task _without_ executing it. --- doc/stdlib/parallel.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/stdlib/parallel.rst b/doc/stdlib/parallel.rst index b75e61a21b1ec..c54b77e0233d7 100644 --- a/doc/stdlib/parallel.rst +++ b/doc/stdlib/parallel.rst @@ -90,7 +90,7 @@ Tasks .. function:: @task - Wrap an expression in a Task executing it, and return the Task. This + Wrap an expression in a Task without executing it, and return the Task. This only creates a task, and does not run it. .. function:: sleep(seconds) From 66d6419917301943d53af5085ac2a0a3446c31be Mon Sep 17 00:00:00 2001 From: Mike Nolta Date: Sat, 23 May 2015 12:10:23 -0400 Subject: [PATCH 063/181] doc/devdocs/types.rst: fix typos --- doc/devdocs/types.rst | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/doc/devdocs/types.rst b/doc/devdocs/types.rst index c77feb55fe53b..61b3ce3fec3b0 100644 --- a/doc/devdocs/types.rst +++ b/doc/devdocs/types.rst @@ -111,22 +111,21 @@ parameters: ub: Any::DataType <: Any bound: Bool false -A :obj`TypeVar` is one of Julia's built-in types---it's defined in +A :obj:`TypeVar` is one of Julia's built-in types---it's defined in ``jltypes.c``, although you can find a commented-out version in ``boot.jl``. The ``name`` field is straightforward: it's what's printed when showing the object. ``lb`` and ``ub`` stand for "lower bound" and "upper bound," respectively: these are the sets that constrain what types the TypeVar may represent. In this case, ``T``\ 's lower bound is ``Union()`` (i.e., ``Bottom`` or the empty set); in -other words, this :obj`TypeVar` is not constrained from below. The +other words, this :obj:`TypeVar` is not constrained from below. The upper bound is ``Any``, so neither is it constrained from above. In a method definition like:: g{S<:Integer}(x::S) = 0 -one can extract the underlying :obj`TypeVar`:: - +one can extract the underlying :obj:`TypeVar`:: .. testcode:: s @@ -146,8 +145,8 @@ one can extract the underlying :obj`TypeVar`:: Here ``ub`` is ``Integer``, as specified in the function definition. -The last field of a :obj`TypeVar` is ``bound``. This boolean value -specifies whether the :obj`TypeVar` is defined as one of the function +The last field of a :obj:`TypeVar` is ``bound``. This boolean value +specifies whether the :obj:`TypeVar` is defined as one of the function parameters. For example: .. doctest:: @@ -190,7 +189,7 @@ bounded. This is because in ``h3``, the same type ``T`` is used in both places, whereas for ``h2`` the ``T`` inside the array is simply the default symbol used for the first parameter of :obj:`Array`. -One can construct :obj`TypeVar`\s manually: +One can construct :obj:`TypeVar`\s manually: .. doctest:: @@ -236,7 +235,7 @@ These therefore print identically, but they have very different behavior: To see what's happening, it's helpful to use Julia's internal :c:func:`jl_` function (defined in ``builtins.c``) for display, because it prints -bound :obj`TypeVar` objects with a hash (``#T`` instead of ``T``): +bound :obj:`TypeVar` objects with a hash (``#T`` instead of ``T``): .. doctest:: @@ -254,7 +253,7 @@ Even though both print as ``T``, in ``sneaky`` the second ``T`` is not bound, and hence it isn't constrained to be the same type as the element type of the :obj:`Array`. -Some :obj`TypeVar` interactions depend on the ``bound`` state, even when there are not two or more uses of the same :obj`TypeVar`. For example: +Some :obj:`TypeVar` interactions depend on the ``bound`` state, even when there are not two or more uses of the same :obj:`TypeVar`. For example: .. doctest:: @@ -371,7 +370,7 @@ type: (The error is triggered because the cache is pre-allocated to have length 8, but only the first two entries are populated.) Consequently, when you instantiate a parametric type, each concrete -type gets saved in a type-cache. However, instances with :obj`TypeVar` +type gets saved in a type-cache. However, instances with :obj:`TypeVar` parameters are not cached. Tuple-types @@ -402,8 +401,8 @@ It's worth noting that the parameter is a type, ``Any``, rather than a Unlike other types, tuple-types are covariant in their parameters, so this definition permits ``Tuple`` to match any type of tuple. This is -therefore equivalent to having an unbound :obj`TypeVar` but distinct -from a bound :obj`TypeVar` +therefore equivalent to having an unbound :obj:`TypeVar` but distinct +from a bound :obj:`TypeVar` .. doctest:: @@ -522,7 +521,7 @@ We can make it more interesting by trying a more complex case:: (gdb) call jl_(b) Tuple{Array{Int64, 2}, Int8} -Let's watch how this bound :obj`TypeVar` gets handled. To follow this, +Let's watch how this bound :obj:`TypeVar` gets handled. To follow this, you'll need to examine the variables ``penv`` and ``eqc``, which are defined as: @@ -569,7 +568,7 @@ Armed with this knowledge, you may find yourself surprised by the following: julia> Tuple{Array{Int},Float64} <: Tuple{Array{T},T} true -where ``T`` is a bound :obj`TypeVar`. In other words, ``A <: B`` does +where ``T`` is a bound :obj:`TypeVar`. In other words, ``A <: B`` does not imply that ``typeintersect(A, B) == A``. A little bit of digging reveals the reason why: ``jl_subtype_le`` does not use the ``cenv_t`` constraints that we just saw in ``typeintersect``. From f15d9016663809a496773b57c8a3be595d04c48f Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sat, 23 May 2015 14:43:40 -0400 Subject: [PATCH 064/181] Remove redundant `require`, clean up for 6afe305 --- base/loading.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/base/loading.jl b/base/loading.jl index 7ddb93abd8e5b..1ba13bc7374fa 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -38,7 +38,6 @@ end package_list = Dict{ByteString,Float64}() # to synchronize multiple tasks trying to require something package_locks = Dict{ByteString,Any}() -require(fname::AbstractString) = require(bytestring(fname)) require(f::AbstractString, fs::AbstractString...) = (require(f); for x in fs require(x); end) # only broadcast top-level (not nested) requires and reloads From 14bb4c27dcb6bdb18694e9cb885580f12ffa6d76 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 23 May 2015 15:44:59 -0400 Subject: [PATCH 065/181] fix #11355 --- src/gf.c | 8 ++++++-- test/core.jl | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/gf.c b/src/gf.c index 405caa438b9c1..828b216141138 100644 --- a/src/gf.c +++ b/src/gf.c @@ -641,8 +641,12 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type, // for T..., intersect with T if (jl_is_vararg_type(declt)) declt = jl_tparam0(declt); - jl_svecset(newparams, i, - jl_type_intersection(declt, (jl_value_t*)jl_typetype_type)); + jl_value_t *di = jl_type_intersection(declt, (jl_value_t*)jl_typetype_type); + if (di == (jl_value_t*)jl_datatype_type) + // issue #11355: DataType has a UID and so takes precedence in the cache + jl_svecset(newparams, i, (jl_value_t*)jl_typetype_type); + else + jl_svecset(newparams, i, di); // TODO: recompute static parameter values, so in extreme cases we // can give `T=Type` instead of `T=Type{Type{Type{...`. } diff --git a/test/core.jl b/test/core.jl index e643eb721ba1a..0384530067e0c 100644 --- a/test/core.jl +++ b/test/core.jl @@ -2861,3 +2861,18 @@ abstract Foo11367 let T1 = TypeVar(:T1, true), T2 = TypeVar(:T2, Foo11367, true) testintersect(Tuple{T1, T1}, Tuple{Type{BigInt}, T2}, Bottom) end + +# issue #11355 +function f11355{T<:Tuple}(sig::Type{T}) + f11355(sig.parameters[1]) +end +function f11355(arg::DataType) + if arg <: Tuple + return 200 + end + return 100 +end +let t = Tuple{Type{Dict{TypeVar(:K, true)}}} + @test f11355(t) == 100 + @test f11355(t) == 100 +end From ed992a6cc64bfdb33570d94ac64b67caa436b35a Mon Sep 17 00:00:00 2001 From: fcard Date: Sat, 23 May 2015 12:09:39 -0300 Subject: [PATCH 066/181] Fixes #11413 Moves `:call` exclusive patterns to its own `if` clause. --- base/show.jl | 13 ++++++------- test/show.jl | 5 +++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/base/show.jl b/base/show.jl index 01f54e2a4c67b..a457d87da67c2 100644 --- a/base/show.jl +++ b/base/show.jl @@ -484,13 +484,8 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int) if is(head, :tuple) && nargs == 1; print(io, ','); end head !== :row && print(io, cl) - # function declaration (like :call but always printed with parens) - # (:calldecl is a "fake" expr node created when we find a :function expr) - elseif head == :calldecl && nargs >= 1 - show_call(io, head, args[1], args[2:end], indent) - # function call - elseif haskey(expr_calls, head) && nargs >= 1 # :call/:ref/:curly + elseif head == :call && nargs >= 1 func = args[1] func_prec = operator_precedence(func) func_args = args[2:end] @@ -535,11 +530,15 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int) show_enclosed_list(io, op, func_args, ",", cl, indent) end - # normal function (i.e. "f(x,y)" or "A[x,y]") + # normal function (i.e. "f(x,y)") else show_call(io, head, func, func_args, indent) end + # other call-like expressions ("A[1,2]", "T{X,Y}") + elseif haskey(expr_calls, head) && nargs >= 1 # :ref/:curly/:calldecl + show_call(io, head, ex.args[1], ex.args[2:end], indent) + # comprehensions elseif (head === :typed_comprehension || head === :typed_dict_comprehension) && length(args) == 3 isdict = (head === :typed_dict_comprehension) diff --git a/test/show.jl b/test/show.jl index 1d1d54f7ceac4..e02edd2cd211d 100644 --- a/test/show.jl +++ b/test/show.jl @@ -233,3 +233,8 @@ end # issue #9865 @test ismatch(r"^Set\(\[.+….+\]\)$", replstr(Set(1:100))) + +# issue 11413 +@test string(:(*{1,2})) == "*{1,2}" +@test string(:(*{1,x})) == "*{1,x}" +@test string(:(-{x})) == "-{x}" From 146df73e6a3995c5a9b9d36f49a71f3cf071821a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 23 May 2015 18:51:13 -0400 Subject: [PATCH 067/181] also defer exit_on_sigint to end of sigatomic blocks. might help #11382 --- src/init.c | 15 ++++++++++----- src/julia.h | 3 ++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/init.c b/src/init.c index b8979f1f078fd..60562f05a7fe9 100644 --- a/src/init.c +++ b/src/init.c @@ -159,6 +159,13 @@ static void jl_find_stack_bottom(void) jl_stack_lo = jl_stack_hi - stack_size; } +// what to do on SIGINT +DLLEXPORT void jl_sigint_action(void) +{ + if (exit_on_sigint) jl_exit(0); + jl_throw(jl_interrupt_exception); +} + #ifdef _OS_WINDOWS_ static char *strsignal(int sig) { @@ -195,13 +202,12 @@ void __cdecl crt_sig_handler(int sig, int num) break; case SIGINT: signal(SIGINT, (void (__cdecl *)(int))crt_sig_handler); - if (exit_on_sigint) jl_exit(0); if (jl_defer_signal) { jl_signal_pending = sig; } else { jl_signal_pending = 0; - jl_throw(jl_interrupt_exception); + jl_sigint_action(); } break; default: // SIGSEGV, (SSIGTERM, IGILL) @@ -326,7 +332,6 @@ volatile HANDLE hMainThread = NULL; static BOOL WINAPI sigint_handler(DWORD wsig) //This needs winapi types to guarantee __stdcall { - if (exit_on_sigint) jl_exit(0); int sig; //windows signals use different numbers from unix (raise) switch(wsig) { @@ -340,6 +345,7 @@ static BOOL WINAPI sigint_handler(DWORD wsig) //This needs winapi types to guara } else { jl_signal_pending = 0; + if (exit_on_sigint) jl_exit(0); if ((DWORD)-1 == SuspendThread(hMainThread)) { //error jl_safe_printf("error: SuspendThread failed\n"); @@ -477,7 +483,6 @@ void restore_signals(void) void sigint_handler(int sig, siginfo_t *info, void *context) { - if (exit_on_sigint) jl_exit(0); if (jl_defer_signal) { jl_signal_pending = sig; } @@ -487,7 +492,7 @@ void sigint_handler(int sig, siginfo_t *info, void *context) sigemptyset(&sset); sigaddset(&sset, SIGINT); sigprocmask(SIG_UNBLOCK, &sset, NULL); - jl_throw(jl_interrupt_exception); + jl_sigint_action(); } } #endif diff --git a/src/julia.h b/src/julia.h index 7d92895e9a9ea..e9f8f2e4d6b69 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1317,10 +1317,11 @@ DLLEXPORT extern volatile sig_atomic_t jl_defer_signal; jl_defer_signal--; \ if (jl_defer_signal == 0 && jl_signal_pending != 0) { \ jl_signal_pending = 0; \ - jl_throw(jl_interrupt_exception); \ + jl_sigint_action(); \ } \ } while(0) +DLLEXPORT void jl_sigint_action(void); DLLEXPORT void restore_signals(void); DLLEXPORT void jl_install_sigint_handler(); DLLEXPORT void jl_sigatomic_begin(void); From ebdb7b2f74f1254ad658eb254e2ab55543b4151e Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 23 May 2015 18:55:56 -0400 Subject: [PATCH 068/181] re-add isassigned for SimpleVector --- base/essentials.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/base/essentials.jl b/base/essentials.jl index 45b737ba5315e..702dd82885d74 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -216,6 +216,12 @@ map(f, v::SimpleVector) = Any[ f(v[i]) for i = 1:length(v) ] getindex(v::SimpleVector, I::AbstractArray) = svec(Any[ v[i] for i in I ]...) +function isassigned(v::SimpleVector, i::Int) + 1 <= i <= length(v) || return false + x = unsafe_load(convert(Ptr{Ptr{Void}},data_pointer_from_objref(v)) + i*sizeof(Ptr)) + return x != C_NULL +end + # index colon type Colon end From 5fab9d110dd19cb1481f5fc976c0e32bb51d2c0a Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sat, 23 May 2015 17:41:02 -0700 Subject: [PATCH 069/181] add _IO_stdin_used to julia.expmap fixes #10982 --- src/julia.expmap | 1 + 1 file changed, 1 insertion(+) diff --git a/src/julia.expmap b/src/julia.expmap index f7a703552bdcd..f6c1f587c9a8c 100644 --- a/src/julia.expmap +++ b/src/julia.expmap @@ -35,6 +35,7 @@ gc_queue_root; gc_wb_slow; jlbacktrace; + _IO_stdin_used; /* freebsd */ environ; From c1645883308c1790e83004f7c7b283b01ccf85e7 Mon Sep 17 00:00:00 2001 From: Mike Innes Date: Sun, 24 May 2015 10:25:05 +0100 Subject: [PATCH 070/181] rename doc setter method --- base/docs.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/base/docs.jl b/base/docs.jl index 6a7c4ef7709bd..051f129231c1c 100644 --- a/base/docs.jl +++ b/base/docs.jl @@ -17,14 +17,14 @@ macro init () quote if !isdefined(:META) const $META = ObjectIdDict() - doc($META, @doc_str $("Documentation metadata for `$(current_module())`.")) + doc!($META, @doc_str $("Documentation metadata for `$(current_module())`.")) push!(modules, current_module()) nothing end end end -function doc(obj, data) +function doc!(obj, data) meta()[obj] = data end @@ -78,7 +78,7 @@ FuncDoc() = FuncDoc(Method[], Dict(), Dict()) getset(coll, key, default) = coll[key] = get(coll, key, default) -function doc(f::Function, m::Method, data, source) +function doc!(f::Function, m::Method, data, source) fd = getset(meta(), f, FuncDoc()) isa(fd, FuncDoc) || error("Can't document a method when the function already has metadata") !haskey(fd.meta, m) && push!(fd.order, m) @@ -159,7 +159,7 @@ function namedoc(meta, def, name) quote @init $(esc(def)) - doc($(esc(name)), $(mdify(meta))) + doc!($(esc(name)), $(mdify(meta))) nothing end end @@ -168,7 +168,7 @@ function funcdoc(meta, def) quote @init f, m = $(trackmethod(def)) - doc(f, m, $(mdify(meta)), $(esc(Expr(:quote, def)))) + doc!(f, m, $(mdify(meta)), $(esc(Expr(:quote, def)))) f end end @@ -177,7 +177,7 @@ function objdoc(meta, def) quote @init f = $(esc(def)) - doc(f, $(mdify(meta))) + doc!(f, $(mdify(meta))) f end end From b307f88cfc8f37f8ec25565a2f2a69dacc9e48bf Mon Sep 17 00:00:00 2001 From: Mike Innes Date: Sun, 24 May 2015 10:50:35 +0100 Subject: [PATCH 071/181] hack for callable types --- base/docs.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/base/docs.jl b/base/docs.jl index 051f129231c1c..a8c96a0cf66f5 100644 --- a/base/docs.jl +++ b/base/docs.jl @@ -113,6 +113,10 @@ end catdoc() = nothing catdoc(xs...) = vcat(xs...) +# Generic Callables + +doc(f, ::Method) = doc(f) + # Modules function doc(m::Module) From 33ab0f623bfd44ea45784db263c1d4d7dff94eec Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 18 May 2015 16:15:02 -0400 Subject: [PATCH 072/181] Do not require new line or ";" at the end of import expression. Fix #10910 --- src/julia-parser.scm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 36981c0ea0d50..ce7f96394aaa6 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -1293,9 +1293,9 @@ (from (and (eq? next ':) (not (ts:space? s)))) (done (cond ((or from (eqv? next #\,)) (begin (take-token s) #f)) - ((memv next '(#\newline #\;)) #t) - ((eof-object? next) #t) - (else #f))) + ((or (eq? next '|.|) + (eqv? (string.sub (string next) 0 1) ".")) #f) + (else #t))) (rest (if done '() (parse-comma-separated s (lambda (s) @@ -1341,7 +1341,7 @@ (loop (cons (symbol (string.sub (string nxt) 1)) path))) (else - (error (string "invalid \"" word "\" statement"))))))) + `(,word ,@(reverse path))))))) ; parse comma-separated assignments, like "i=1:n,j=1:m,..." (define (parse-comma-separated s what) From b2c2d42fe928b49532c4480af2902b35cf8b7b10 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 18 May 2015 16:30:14 -0400 Subject: [PATCH 073/181] Add test for parsing import/using --- test/parser.jl | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/parser.jl b/test/parser.jl index 68f7be5bbb47b..9ff3626e1632b 100644 --- a/test/parser.jl +++ b/test/parser.jl @@ -86,3 +86,26 @@ macro test999_str(args...); args; end # issue #10985 @test expand(:(f(::Int...) = 1)).head == :method + +# issue #10910 +@test parse(":(using A)") == Expr(:quote, Expr(:using, :A)) +@test parse(":(using A.b, B)") == Expr(:quote, + Expr(:toplevel, + Expr(:using, :A, :b), + Expr(:using, :B))) +@test parse(":(using A: b, c.d)") == Expr(:quote, + Expr(:toplevel, + Expr(:using, :A, :b), + Expr(:using, :A, :c, :d))) + +@test parse(":(importall A)") == Expr(:quote, Expr(:importall, :A)) + +@test parse(":(import A)") == Expr(:quote, Expr(:import, :A)) +@test parse(":(import A.b, B)") == Expr(:quote, + Expr(:toplevel, + Expr(:import, :A, :b), + Expr(:import, :B))) +@test parse(":(import A: b, c.d)") == Expr(:quote, + Expr(:toplevel, + Expr(:import, :A, :b), + Expr(:import, :A, :c, :d))) From c726d2aca12ee68196a9c393019de89a6fca600e Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sun, 24 May 2015 15:06:28 -0400 Subject: [PATCH 074/181] fully replace show_func_sig with jl_static_show_func_sig too much duplication otherwise --- src/builtins.c | 12 ++++++------ src/gf.c | 38 ++++---------------------------------- 2 files changed, 10 insertions(+), 40 deletions(-) diff --git a/src/builtins.c b/src/builtins.c index 84a81384ccc06..abb7774820135 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -1542,12 +1542,10 @@ DLLEXPORT size_t jl_static_show(JL_STREAM *out, jl_value_t *v) return jl_static_show_x(out, v, 0); } -DLLEXPORT size_t -jl_static_show_func_sig(JL_STREAM *s, jl_value_t *type) +DLLEXPORT size_t jl_static_show_func_sig(JL_STREAM *s, jl_value_t *type) { - if (!jl_is_tuple_type(type)) { + if (!jl_is_tuple_type(type)) return jl_static_show(s, type); - } size_t n = 0; size_t tl = jl_nparams(type); n += jl_printf(s, "("); @@ -1557,11 +1555,13 @@ jl_static_show_func_sig(JL_STREAM *s, jl_value_t *type) if (i != tl - 1) { n += jl_static_show(s, tp); n += jl_printf(s, ", "); - } else { + } + else { if (jl_is_vararg_type(tp)) { n += jl_static_show(s, jl_tparam0(tp)); n += jl_printf(s, "..."); - } else { + } + else { n += jl_static_show(s, tp); } } diff --git a/src/gf.c b/src/gf.c index 828b216141138..e89bd0a5add21 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1156,33 +1156,6 @@ DLLEXPORT int jl_args_morespecific(jl_value_t *a, jl_value_t *b) void print_func_loc(JL_STREAM *s, jl_lambda_info_t *li); -static void -show_func_sig(JL_STREAM *s, jl_value_t *errstream, jl_value_t *type) -{ - if (!jl_is_tuple_type(type)) { - jl_show(errstream, type); - return; - } - size_t tl = jl_nparams(type); - jl_printf(s, "("); - size_t i; - for (i = 0;i < tl;i++) { - jl_value_t *tp = jl_tparam(type, i); - if (i != tl - 1) { - jl_show(errstream, tp); - jl_printf(s, ", "); - } else { - if (jl_is_vararg_type(tp)) { - jl_show(errstream, jl_tparam0(tp)); - jl_printf(s, "..."); - } else { - jl_show(errstream, tp); - } - } - } - jl_printf(s, ")"); -} - /* warn about ambiguous method priorities @@ -1228,7 +1201,6 @@ static void check_ambiguous(jl_methlist_t *ml, jl_tupletype_t *type, } jl_methlist_t *l = ml; char *n; - jl_value_t *errstream; JL_STREAM *s; while (l != (void*)jl_nothing) { if (sigs_eq(isect, (jl_value_t*)l->sig, 0)) @@ -1236,16 +1208,15 @@ static void check_ambiguous(jl_methlist_t *ml, jl_tupletype_t *type, l = l->next; } n = fname->name; - errstream = jl_stderr_obj(); s = JL_STDERR; jl_printf(s, "Warning: New definition \n %s", n); - show_func_sig(s, errstream, (jl_value_t*)type); + jl_static_show_func_sig(s, (jl_value_t*)type); print_func_loc(s, linfo); jl_printf(s, "\nis ambiguous with: \n %s", n); - show_func_sig(s, errstream, (jl_value_t*)sig); + jl_static_show_func_sig(s, (jl_value_t*)sig); print_func_loc(s, oldmeth->func->linfo); jl_printf(s, ".\nTo fix, define \n %s", n); - show_func_sig(s, errstream, isect); + jl_static_show_func_sig(s, isect); jl_printf(s, "\nbefore the new definition.\n"); done_chk_amb: JL_GC_POP(); @@ -1280,10 +1251,9 @@ jl_methlist_t *jl_method_list_insert(jl_methlist_t **pml, jl_tupletype_t *type, if (check_amb && l->func->linfo && method->linfo && (l->func->linfo->module != method->linfo->module)) { jl_module_t *newmod = method->linfo->module; - jl_value_t *errstream = jl_stderr_obj(); JL_STREAM *s = JL_STDERR; jl_printf(s, "Warning: Method definition %s", method->linfo->name->name); - show_func_sig(s, errstream, (jl_value_t*)type); + jl_static_show_func_sig(s, (jl_value_t*)type); jl_printf(s, " in module %s", l->func->linfo->module->name->name); print_func_loc(s, l->func->linfo); jl_printf(s, " overwritten in module %s", newmod->name->name); From 1c938c0bed7f0426c2244d425e22a5c9ee97abe9 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sun, 24 May 2015 15:33:11 -0400 Subject: [PATCH 075/181] fix NULL derefs when printing errors during bootstrap --- src/builtins.c | 2 ++ src/init.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/builtins.c b/src/builtins.c index abb7774820135..ccf1a016d6111 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -890,6 +890,7 @@ void jl_flush_cstdio(void) jl_value_t *jl_stdout_obj(void) { + if (jl_base_module == NULL) return NULL; jl_value_t *stdout_obj = jl_get_global(jl_base_module, jl_symbol("STDOUT")); if (stdout_obj != NULL) return stdout_obj; return jl_get_global(jl_base_module, jl_symbol("OUTPUT_STREAM")); @@ -897,6 +898,7 @@ jl_value_t *jl_stdout_obj(void) jl_value_t *jl_stderr_obj(void) { + if (jl_base_module == NULL) return NULL; jl_value_t *stderr_obj = jl_get_global(jl_base_module, jl_symbol("STDERR")); if (stderr_obj != NULL) return stderr_obj; return jl_get_global(jl_base_module, jl_symbol("OUTPUT_STREAM")); diff --git a/src/init.c b/src/init.c index 60562f05a7fe9..63eded6953b0e 100644 --- a/src/init.c +++ b/src/init.c @@ -543,7 +543,7 @@ DLLEXPORT void jl_atexit_hook() } JL_CATCH { jl_printf(JL_STDERR, "\natexit hook threw an error: "); - jl_show(jl_stderr_obj(),jl_exception_in_transit); + jl_static_show(JL_STDERR, jl_exception_in_transit); } } } @@ -1060,7 +1060,7 @@ void _julia_init(JL_IMAGE_SEARCH rel) } JL_CATCH { jl_printf(JL_STDERR, "error during init:\n"); - jl_show(jl_stderr_obj(), jl_exception_in_transit); + jl_static_show(JL_STDERR, jl_exception_in_transit); jl_printf(JL_STDERR, "\n"); jl_exit(1); } From b142f46178c7057c9444f10fed66763a78d7c6b5 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sun, 24 May 2015 16:36:49 -0400 Subject: [PATCH 076/181] fix #11238, better tuple type checks in reflection --- base/error.jl | 4 ++-- base/inference.jl | 16 ++++------------ base/reflection.jl | 23 ++++++++++++++++++----- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/base/error.jl b/base/error.jl index 30cd809b5e755..ae382a78bdd14 100644 --- a/base/error.jl +++ b/base/error.jl @@ -18,8 +18,8 @@ ## native julia error handling ## -error(s::AbstractString) = throw(Main.Base.ErrorException(s)) -error(s...) = throw(Main.Base.ErrorException(Main.Base.string(s...))) +error(s::AbstractString) = throw(Main.Base.call(Main.Base.ErrorException,s)) +error(s...) = throw(Main.Base.call(Main.Base.ErrorException,Main.Base.string(s...))) rethrow() = ccall(:jl_rethrow, Void, ())::Bottom rethrow(e) = ccall(:jl_rethrow_other, Void, (Any,), e)::Bottom diff --git a/base/inference.jl b/base/inference.jl index 64a2d4998aa29..32575669c9f40 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -3279,15 +3279,11 @@ function replace_getfield!(ast, e::ANY, tupname, vals, sv, i0) end function code_typed(f, types::ANY; optimize=true) - if isa(types,Tuple) - types = Tuple{types...} - end + types = to_tuple_type(types) code_typed(call, Tuple{isa(f,Type)?Type{f}:typeof(f), types.parameters...}, optimize=optimize) end function code_typed(f::Function, types::ANY; optimize=true) - if isa(types,Tuple) - types = Tuple{types...} - end + types = to_tuple_type(types) asts = [] for x in _methods(f,types,-1) linfo = func_for_method(x[3],types,x[2]) @@ -3306,15 +3302,11 @@ function code_typed(f::Function, types::ANY; optimize=true) end function return_types(f, types::ANY) - if isa(types,Tuple) - types = Tuple{types...} - end + types = to_tuple_type(types) return_types(call, Tuple{isa(f,Type)?Type{f}:typeof(f), types.parameters...}) end function return_types(f::Function, types::ANY) - if isa(types,Tuple) - types = Tuple{types...} - end + types = to_tuple_type(types) rt = [] for x in _methods(f,types,-1) linfo = func_for_method(x[3],types,x[2]) diff --git a/base/reflection.jl b/base/reflection.jl index 1b072797e1bca..45b89f039f3ec 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -105,10 +105,24 @@ isgeneric(f::ANY) = (isa(f,Function) && isa(f.env,MethodTable)) function_name(f::Function) = isgeneric(f) ? f.env.name : (:anonymous) +function to_tuple_type(t::ANY) + if isa(t,Tuple) || isa(t,AbstractArray) || isa(t,SimpleVector) + t = Tuple{t...} + end + if isa(t,Type) && t<:Tuple + if !all(p->(isa(p,Type)||isa(p,TypeVar)), t.parameters) + error("argument tuple type must contain only types") + end + else + error("expected tuple type") + end + t +end + tt_cons(t::ANY, tup::ANY) = Tuple{t, (isa(tup, Type) ? tup.parameters : tup)...} code_lowered(f, t::ANY) = map(m->uncompressed_ast(m.func.code), methods(f, t)) -methods(f::Function,t::ANY) = Any[m[3] for m in _methods(f,t,-1)] +methods(f::Function,t::ANY) = (t=to_tuple_type(t); Any[m[3] for m in _methods(f,t,-1)]) methods(f::ANY,t::ANY) = methods(call, tt_cons(isa(f,Type) ? Type{f} : typeof(f), t)) function _methods(f::ANY,t::ANY,lim) if isa(t,Type) @@ -170,9 +184,8 @@ uncompressed_ast(l::LambdaStaticData) = isa(l.ast,Expr) ? l.ast : ccall(:jl_uncompress_ast, Any, (Any,Any), l, l.ast) # Printing code representations in IR and assembly -_dump_function(f, t::Tuple{Vararg{Type}}, native, wrapper, strip_ir_metadata) = - _dump_function(f, Tuple{t...}, native, wrapper, strip_ir_metadata) function _dump_function(f, t::ANY, native, wrapper, strip_ir_metadata) + t = to_tuple_type(t) llvmf = ccall(:jl_get_llvmf, Ptr{Void}, (Any, Any, Bool), f, t, wrapper) if llvmf == C_NULL @@ -183,7 +196,7 @@ function _dump_function(f, t::ANY, native, wrapper, strip_ir_metadata) str = ccall(:jl_dump_function_asm, Any, (Ptr{Void},), llvmf)::ByteString else str = ccall(:jl_dump_function_ir, Any, - (Ptr{Void}, Bool), llvmf, strip_ir_metadata)::ByteString + (Ptr{Void}, Bool), llvmf, strip_ir_metadata)::ByteString end return str @@ -208,8 +221,8 @@ if isdefined(Core, :Inference) && not_int(is(current_module(), Core.Inference)) return_types(args...;kwargs...) = Core.Inference.return_types(args...;kwargs...) end -which(f::ANY, t::Tuple{Vararg{Type}}) = which(f, Tuple{t...}) function which(f::ANY, t::ANY) + t = to_tuple_type(t) if isleaftype(t) ms = methods(f, t) isempty(ms) && error("no method found for the specified argument types") From a2ed42cc65172cd5786b1604571e6f778107d73e Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 25 May 2015 00:25:11 -0400 Subject: [PATCH 077/181] re-fix #11355, fix #11428 --- src/gf.c | 3 ++- test/core.jl | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gf.c b/src/gf.c index e89bd0a5add21..039a9ec325c9c 100644 --- a/src/gf.c +++ b/src/gf.c @@ -642,7 +642,7 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type, if (jl_is_vararg_type(declt)) declt = jl_tparam0(declt); jl_value_t *di = jl_type_intersection(declt, (jl_value_t*)jl_typetype_type); - if (di == (jl_value_t*)jl_datatype_type) + if (is_kind(di)) // issue #11355: DataType has a UID and so takes precedence in the cache jl_svecset(newparams, i, (jl_value_t*)jl_typetype_type); else @@ -653,6 +653,7 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type, else { jl_svecset(newparams, i, (jl_value_t*)jl_typetype_type); } + need_guard_entries = 1; assert(jl_svecref(newparams,i) != (jl_value_t*)jl_bottom_type); } else if (jl_is_type_type(elt) && very_general_type(decl_i) && diff --git a/test/core.jl b/test/core.jl index 0fffb9bec3ab9..dafcfe15cda23 100644 --- a/test/core.jl +++ b/test/core.jl @@ -2894,7 +2894,8 @@ function f11355(arg::DataType) end return 100 end -let t = Tuple{Type{Dict{TypeVar(:K, true)}}} +let t = Tuple{Type{Vector{Int}}} @test f11355(t) == 100 + t = Tuple{Type{Dict{TypeVar(:K, true)}}} @test f11355(t) == 100 end From c6d8ace09a400984788d2b54f41714c805cfd34e Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 25 May 2015 01:02:04 -0400 Subject: [PATCH 078/181] remove extra blank line in DomainError output. fixes #11225 --- base/replutil.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/replutil.jl b/base/replutil.jl index ebcec65f886f3..43dd83ca2990b 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -94,15 +94,15 @@ end showerror(io::IO, ex::LoadError) = showerror(io, ex, []) function showerror(io::IO, ex::DomainError, bt) - println(io, "DomainError:") + print(io, "DomainError:") for b in bt code = ccall(:jl_lookup_code_address, Any, (Ptr{Void}, Cint), b, true) if length(code) == 5 && !code[4] # code[4] == fromC if code[1] in (:log, :log2, :log10, :sqrt) # TODO add :besselj, :besseli, :bessely, :besselk - println(io,"$(code[1]) will only return a complex result if called with a complex argument.") + println(io,"\n$(code[1]) will only return a complex result if called with a complex argument.") print(io, "try $(code[1]) (complex(x))") elseif (code[1] == :^ && code[2] == symbol("intfuncs.jl")) || code[1] == :power_by_squaring - println(io, "Cannot raise an integer x to a negative power -n. Make x a float by adding") + println(io, "\nCannot raise an integer x to a negative power -n. Make x a float by adding") print(io, "a zero decimal (e.g. 2.0^-n instead of 2^-n), or write 1/x^n, float(x)^-n, or (x//1)^-n") end break From e36b46069c6dcf7e17b075484594b69087621b8d Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 25 May 2015 01:06:46 -0400 Subject: [PATCH 079/181] show a few more operators (!=, !==, >=, <=) quoted. fixes #11394 --- base/show.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/show.jl b/base/show.jl index a457d87da67c2..9c5dc1b8ffdc3 100644 --- a/base/show.jl +++ b/base/show.jl @@ -259,7 +259,7 @@ show_unquoted(io::IO, ex, ::Int,::Int) = show(io, ex) ## AST printing constants ## const indent_width = 4 -const quoted_syms = Set{Symbol}([:(:),:(::),:(:=),:(=),:(==),:(===),:(=>)]) +const quoted_syms = Set{Symbol}([:(:),:(::),:(:=),:(=),:(==),:(!=),:(===),:(!==),:(=>),:(>=),:(<=)]) const uni_ops = Set{Symbol}([:(+), :(-), :(!), :(¬), :(~), :(<:), :(>:), :(√), :(∛), :(∜)]) const expr_infix_wide = Set([:(=), :(+=), :(-=), :(*=), :(/=), :(\=), :(&=), :(|=), :($=), :(>>>=), :(>>=), :(<<=), :(&&), :(||), :(<:), :(=>)]) From d777bccb870bf71355ac37299cb2d6bf31d51899 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 25 May 2015 01:48:49 -0400 Subject: [PATCH 080/181] fix #11278, restore check that field types are Types, lost in #10380 --- src/builtins.c | 6 ++++++ src/interpreter.c | 6 +++++- src/julia_internal.h | 1 - src/toplevel.c | 6 ------ 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/builtins.c b/src/builtins.c index ccf1a016d6111..aaec4de02fa66 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -1005,6 +1005,12 @@ JL_CALLABLE(jl_f_union) // generic function reflection ------------------------------------------------ +static void jl_check_type_tuple(jl_value_t *t, jl_sym_t *name, const char *ctx) +{ + if (!jl_is_tuple_type(t)) + jl_type_error_rt(name->name, ctx, (jl_value_t*)jl_type_type, t); +} + JL_CALLABLE(jl_f_methodexists) { JL_NARGS(method_exists, 2, 2); diff --git a/src/interpreter.c b/src/interpreter.c index 2f4494fc7030c..46006808a84d2 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -410,7 +410,11 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl, size_t ng dt->types = (jl_svec_t*)eval(args[4], locals, nl, ngensym); gc_wb(dt, dt->types); inside_typedef = 0; - //jl_check_type_tuple(dt->types, dt->name->name, "type definition"); + for(size_t i=0; i < jl_svec_len(dt->types); i++) { + jl_value_t *elt = jl_svecref(dt->types, i); + if (!jl_is_type(elt) && !jl_is_typevar(elt)) + jl_type_error_rt(dt->name->name->name, "type definition", (jl_value_t*)jl_type_type, elt); + } super = eval(args[3], locals, nl, ngensym); jl_set_datatype_super(dt, super); } diff --git a/src/julia_internal.h b/src/julia_internal.h index a75feae456d1a..0115aa09bad61 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -49,7 +49,6 @@ uint32_t jl_get_gs_ctr(void); void jl_set_gs_ctr(uint32_t ctr); void NORETURN jl_no_method_error(jl_function_t *f, jl_value_t **args, size_t na); -void jl_check_type_tuple(jl_value_t *t, jl_sym_t *name, const char *ctx); #define JL_CALLABLE(name) \ DLLEXPORT jl_value_t *name(jl_value_t *F, jl_value_t **args, uint32_t nargs) diff --git a/src/toplevel.c b/src/toplevel.c index 453872696c869..ff115071e8fa8 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -613,12 +613,6 @@ DLLEXPORT jl_value_t *jl_load_(jl_value_t *str) void jl_reinstantiate_inner_types(jl_datatype_t *t); -void jl_check_type_tuple(jl_value_t *t, jl_sym_t *name, const char *ctx) -{ - if (!jl_is_tuple_type(t)) - jl_type_error_rt(name->name, ctx, (jl_value_t*)jl_type_type, t); -} - void jl_set_datatype_super(jl_datatype_t *tt, jl_value_t *super) { if (!jl_is_datatype(super) || !jl_is_abstracttype(super) || From b610428120aaf9be5b526d866f5be0e2c134fec0 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sun, 24 May 2015 23:34:25 -0700 Subject: [PATCH 081/181] Only test samefile(Libdl.dlpath(dl), dl) for libraries that can be dlopen'ed related to #11268 --- test/backtrace.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/backtrace.jl b/test/backtrace.jl index 94a099239ee55..651ca3d4c4250 100644 --- a/test/backtrace.jl +++ b/test/backtrace.jl @@ -20,7 +20,7 @@ dlls = Libdl.dllist() @test length(dlls) > 3 # at a bare minimum, probably have some version of libstdc, libgcc, libjulia, ... if @unix? true : (Base.windows_version() >= Base.WINDOWS_VISTA_VER) for dl in dlls - if isfile(dl) + if isfile(dl) && (Libdl.dlopen_e(dl) != C_NULL) @test Base.samefile(Libdl.dlpath(dl), dl) end end From d797d569268635b60a952f83cb439102806b4f74 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sun, 24 May 2015 23:30:06 -0700 Subject: [PATCH 082/181] Set default for USE_BLAS64 to 0 when using non MKL system BLAS fixes #10457, fixes #11417 --- Make.inc | 10 +++++++++- contrib/windows/msys_build.sh | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Make.inc b/Make.inc index 7b6725e5fd6b1..5b5ee16fe3b69 100644 --- a/Make.inc +++ b/Make.inc @@ -574,10 +574,18 @@ else PCRE_CONFIG = $(build_bindir)/pcre-config endif -# Use 64-bit libraries by default on 64-bit architectures +# Use ILP64 BLAS interface when building openblas from source on 64-bit architectures ifeq ($(BINARY), 64) +ifeq ($(USE_SYSTEM_BLAS), 1) +ifeq ($(USE_INTEL_MKL), 1) +USE_BLAS64 ?= 1 +else # non MKL system blas is most likely LP64 +USE_BLAS64 ?= 0 +endif +else USE_BLAS64 ?= 1 endif +endif ifeq ($(USE_SYSTEM_BLAS), 1) ifeq ($(OS), Darwin) diff --git a/contrib/windows/msys_build.sh b/contrib/windows/msys_build.sh index 16f6528f8b828..7679ecc891764 100755 --- a/contrib/windows/msys_build.sh +++ b/contrib/windows/msys_build.sh @@ -41,6 +41,7 @@ if [ "$ARCH" = x86_64 ]; then bits=64 archsuffix=64 echo "override MARCH = x86-64" >> Make.user + echo 'USE_BLAS64 = 1' >> Make.user else bits=32 archsuffix=86 From 31299a74332bd20ea0f76116880dd7c93b3273d1 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Mon, 25 May 2015 07:58:24 -0700 Subject: [PATCH 083/181] Change libgit2 to a git-external note that the tarball checksums changed because of switching from /archive/ to /tarball/ url for downloading, which changes the leading folder name inside the tarball --- deps/.gitignore | 3 +- deps/Makefile | 38 +++++++++----------- deps/Versions.make | 1 - deps/checksums/libgit2-0.22.2.tar.gz/md5 | 1 - deps/checksums/libgit2-0.22.2.tar.gz/sha512 | 1 - deps/checksums/libgit2-v0.22.2.tar.gz/md5 | 1 + deps/checksums/libgit2-v0.22.2.tar.gz/sha512 | 1 + deps/libgit2.version | 2 ++ 8 files changed, 23 insertions(+), 25 deletions(-) delete mode 100644 deps/checksums/libgit2-0.22.2.tar.gz/md5 delete mode 100644 deps/checksums/libgit2-0.22.2.tar.gz/sha512 create mode 100644 deps/checksums/libgit2-v0.22.2.tar.gz/md5 create mode 100644 deps/checksums/libgit2-v0.22.2.tar.gz/sha512 create mode 100644 deps/libgit2.version diff --git a/deps/.gitignore b/deps/.gitignore index 9eeac7af247b6..abcca87d2e715 100644 --- a/deps/.gitignore +++ b/deps/.gitignore @@ -16,7 +16,6 @@ /libcxx-* /libcxxabi-* /libffi-* -/libgit* /llvm-* /lldb-* /mpfr-* @@ -33,6 +32,8 @@ /Rmath-julia* # git-externals: +/libgit2 +/libgit2-* /libuv /libuv-* /openblas diff --git a/deps/Makefile b/deps/Makefile index 5a8862b1f3c2f..93534f741877e 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -1869,7 +1869,11 @@ install-virtualenv: $(VIRTUALENV_TARGET) ## libgit2 -LIBGIT2_OBJ_SOURCE = libgit2-$(LIBGIT2_VER)/build/libgit2.$(SHLIB_EXT) +LIBGIT2_GIT_URL = git://github.com/libgit2/libgit2.git +LIBGIT2_TAR_URL = https://api.github.com/repos/libgit2/libgit2/tarball/$1 +$(eval $(call git-external,libgit2,LIBGIT2,CMakeLists.txt,build/libgit2.$(SHLIB_EXT))) + +LIBGIT2_OBJ_SOURCE = $(LIBGIT2_SRC_DIR)/build/libgit2.$(SHLIB_EXT) LIBGIT2_OBJ_TARGET = $(build_shlibdir)/libgit2.$(SHLIB_EXT) LIBGIT2_OPTS = $(CMAKE_COMMON) -DTHREADSAFE=ON @@ -1883,28 +1887,22 @@ LIBGIT2_OPTS += -DCMAKE_FIND_ROOT_PATH=/usr/$(XC_HOST) -DCMAKE_FIND_ROOT_PATH_MO endif endif -libgit2-$(LIBGIT2_VER).tar.gz: - $(JLDOWNLOAD) $@ https://github.com/libgit2/libgit2/archive/v$(LIBGIT2_VER).tar.gz -libgit2-$(LIBGIT2_VER)/CMakeLists.txt: libgit2-$(LIBGIT2_VER).tar.gz - $(JLCHECKSUM) $< - $(TAR) zxf $< - touch -c $@ -libgit2-$(LIBGIT2_VER)/build/Makefile: libgit2-$(LIBGIT2_VER)/CMakeLists.txt - mkdir -p libgit2-$(LIBGIT2_VER)/build - cd libgit2-$(LIBGIT2_VER)/build/ && \ +$(LIBGIT2_SRC_DIR)/build/Makefile: $(LIBGIT2_SRC_DIR)/CMakeLists.txt + mkdir -p $(LIBGIT2_SRC_DIR)/build + cd $(LIBGIT2_SRC_DIR)/build/ && \ $(CMAKE) .. $(LIBGIT2_OPTS) touch -c $@ -$(LIBGIT2_OBJ_SOURCE): libgit2-$(LIBGIT2_VER)/build/Makefile - $(MAKE) -C libgit2-$(LIBGIT2_VER)/build +$(LIBGIT2_OBJ_SOURCE): $(LIBGIT2_SRC_DIR)/build/Makefile + $(MAKE) -C $(LIBGIT2_SRC_DIR)/build touch -c $@ -libgit2-$(LIBGIT2_VER)/build/checked: $(LIBGIT2_OBJ_SOURCE) +$(LIBGIT2_SRC_DIR)/build/checked: $(LIBGIT2_OBJ_SOURCE) ifeq ($(OS),$(BUILD_OS)) - $(MAKE) -C libgit2-$(LIBGIT2_VER)/build test + $(MAKE) -C $(LIBGIT2_SRC_DIR)/build test endif echo 1 > $@ $(LIBGIT2_OBJ_TARGET): $(LIBGIT2_OBJ_SOURCE) | $(build_shlibdir) cp $< $@ - #$$(call make-install,libgit2-$(LIBGIT2_VER)/build,) + #$$(call make-install,$(LIBGIT2_SRC_DIR)/build,) ifeq ($(OS),Linux) # If we're on linux, copy over libssl and libcrypto for libgit2 -LIBGIT_LIBS=$$(ldd "$@" | tail -n +2 | awk '{print $$(NF-1)}'); \ @@ -1917,15 +1915,13 @@ endif touch -c $@ clean-libgit2: - -rm -rf libgit2-$(LIBGIT2_VER)/build/ + -rm -rf $(LIBGIT2_SRC_DIR)/build/ -rm -f $(LIBGIT2_OBJ_TARGET) -distclean-libgit2: - -rm -rf libgit2-$(LIBGIT2_VER).tar.gz libgit2-$(LIBGIT2_VER).zip libgit2-$(LIBGIT2_VER) -get-libgit2: libgit2-$(LIBGIT2_VER).tar.gz -configure-libgit2: libgit2-$(LIBGIT2_VER)/build/Makefile +get-libgit2: $(LIBGIT2_SRC_DIR)/CMakeLists.txt +configure-libgit2: $(LIBGIT2_SRC_DIR)/build/Makefile compile-libgit2: $(LIBGIT2_OBJ_SOURCE) -check-libgit2: libgit2-$(LIBGIT2_VER)/build/checked +check-libgit2: $(LIBGIT2_SRC_DIR)/build/checked install-libgit2: $(LIBGIT2_OBJ_TARGET) ## phony targets ## diff --git a/deps/Versions.make b/deps/Versions.make index 208856d0c84f0..f529654a76f4b 100644 --- a/deps/Versions.make +++ b/deps/Versions.make @@ -13,5 +13,4 @@ MPFR_VER=3.1.2 PATCHELF_VER = 0.8 GIT_VER = 1.8.5.6 VIRTUALENV_VER = 1.11.6 -LIBGIT2_VER = 0.22.2 RMATH_JULIA_VER = 0.1 diff --git a/deps/checksums/libgit2-0.22.2.tar.gz/md5 b/deps/checksums/libgit2-0.22.2.tar.gz/md5 deleted file mode 100644 index c19aef1d41acf..0000000000000 --- a/deps/checksums/libgit2-0.22.2.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -7b21448c471dc76a3ca4801b61ac856a diff --git a/deps/checksums/libgit2-0.22.2.tar.gz/sha512 b/deps/checksums/libgit2-0.22.2.tar.gz/sha512 deleted file mode 100644 index 7c40e5a1ab8da..0000000000000 --- a/deps/checksums/libgit2-0.22.2.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -ab97a2a548fa0e9be113bfe58f6d4e97dda9d7b10b4979b5736c6d410a8f1f3fb6801d691aad246481567eecc99b6f658f7bab639076ffdf21d30561243c8eb9 diff --git a/deps/checksums/libgit2-v0.22.2.tar.gz/md5 b/deps/checksums/libgit2-v0.22.2.tar.gz/md5 new file mode 100644 index 0000000000000..3695cea1c967d --- /dev/null +++ b/deps/checksums/libgit2-v0.22.2.tar.gz/md5 @@ -0,0 +1 @@ +979fc01cad098af9df0d81866f58852c diff --git a/deps/checksums/libgit2-v0.22.2.tar.gz/sha512 b/deps/checksums/libgit2-v0.22.2.tar.gz/sha512 new file mode 100644 index 0000000000000..81b09f443dbf5 --- /dev/null +++ b/deps/checksums/libgit2-v0.22.2.tar.gz/sha512 @@ -0,0 +1 @@ +b931844871739e576f2252d7a4ba20cff3417fb8a439f527d1f0e4da13b92a5b2e3cc0741fb19d531a4c2fcf72d7650d9fc3b8a72d4245cf956bedbd4ad2db31 diff --git a/deps/libgit2.version b/deps/libgit2.version new file mode 100644 index 0000000000000..19d5237b2f6c7 --- /dev/null +++ b/deps/libgit2.version @@ -0,0 +1,2 @@ +LIBGIT2_BRANCH=v0.22.2 +LIBGIT2_SHA1=fb6df50b7f250a4fd8b2fab257f119a5185e9bf5 From 01c871c1b634156340b740df2883798a6266af4b Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 25 May 2015 12:35:24 -0400 Subject: [PATCH 084/181] specialize on all tuple types. fixes #11100 --- src/gf.c | 96 +------------------------------------------------------- 1 file changed, 1 insertion(+), 95 deletions(-) diff --git a/src/gf.c b/src/gf.c index 039a9ec325c9c..12c2bd50db08c 100644 --- a/src/gf.c +++ b/src/gf.c @@ -77,13 +77,7 @@ static int cache_match_by_type(jl_value_t **types, size_t n, jl_tupletype_t *sig } } jl_value_t *a = types[i]; - if (jl_is_tuple_type(decl)) { - // tuples don't have to match exactly, to avoid caching - // signatures for tuples of every length - if (!jl_subtype(a, decl, 0)) - return 0; - } - else if (jl_is_datatype(a) && jl_is_datatype(decl) && + if (jl_is_datatype(a) && jl_is_datatype(decl) && ((jl_datatype_t*)decl)->name == jl_type_type->name && ((jl_datatype_t*)a )->name == jl_type_type->name) { jl_value_t *tp0 = jl_tparam0(decl); @@ -132,15 +126,6 @@ static inline int cache_match(jl_value_t **args, size_t n, jl_tupletype_t *sig, hash-consed, so pointer comparison should work. */ } - else if (jl_is_tuple_type(decl)) { - // tuples don't have to match exactly, to avoid caching - // signatures for tuples of every length - jl_datatype_t *ta = (jl_datatype_t*)jl_typeof(a); - if (!jl_is_tuple_type(ta) || //!jl_subtype(a, decl, 1)) - !jl_tuple_subtype(jl_svec_data(ta->parameters), jl_datatype_nfields(ta), - (jl_datatype_t*)decl, 0)) - return 0; - } else if (jl_is_type_type(decl) && jl_is_type(a)) { jl_value_t *tp0 = jl_tparam0(decl); if (tp0 == (jl_value_t*)jl_typetype_tvar) { @@ -473,19 +458,6 @@ static int is_kind(jl_value_t *v) v==(jl_value_t*)jl_typector_type); } -static int jl_is_specializable_tuple(jl_tupletype_t *t) -{ - if (jl_nparams(t)==0) return 1; - jl_value_t *e0 = jl_tparam(t,0); - if (jl_is_tuple_type(e0) || e0 == (jl_value_t*)jl_datatype_type) return 0; - size_t i, l=jl_nparams(t); - // allow specialization on homogeneous tuples - for(i=1; i < l; i++) { - if (jl_tparam(t,i) != e0) return 0; - } - return 1; -} - static jl_value_t *ml_matches(jl_methlist_t *ml, jl_value_t *type, jl_sym_t *name, int lim); @@ -559,72 +531,6 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type, } if (set_to_any) { } - else if (jl_is_tuple_type(elt) && !jl_is_specializable_tuple((jl_tupletype_t*)elt)) { - /* - don't cache tuple type exactly; just remember that it was - a tuple, unless the declaration asks for something more - specific. determined with a type intersection. - */ - int might_need_guard=0; - if (i < jl_nparams(decl)) { - jl_value_t *declt = jl_tparam(decl,i); - if (jl_is_vararg_type(declt)) - declt = jl_tparam0(declt); - // note: ignore va flag (for T..., intersect with T) - if (!jl_has_typevars(declt)) { - if (declt == (jl_value_t*)jl_anytuple_type || - jl_subtype((jl_value_t*)jl_anytuple_type, declt, 0)) { - // don't specialize args that matched (Any...) or Any - jl_svecset(newparams, i, (jl_value_t*)jl_anytuple_type); - might_need_guard = 1; - } - else { - declt = jl_type_intersection(declt, (jl_value_t*)jl_anytuple_type); - if (jl_nparams(elt) > 3 || - (jl_is_tuple_type(declt) && tuple_all_Any((jl_tupletype_t*)declt))) { - jl_svecset(newparams, i, declt); - might_need_guard = 1; - } - } - } - } - else { - jl_svecset(newparams, i, (jl_value_t*)jl_anytuple_type); - might_need_guard = 1; - } - assert(jl_svecref(newparams,i) != (jl_value_t*)jl_bottom_type); - if (might_need_guard) { - jl_methlist_t *curr = mt->defs; - // can't generalize type if there's an overlapping definition - // with typevars. - // TODO: it seems premature to take these intersections - // before the whole signature has been generalized. - // example ((T...,),S,S,S,S,S,S,S,S,S,S,S,S,S,S,S,S,...) - temp2 = (jl_value_t*)jl_svec_copy(newparams); - temp2 = (jl_value_t*)jl_apply_tuple_type((jl_svec_t*)temp2); - while (curr != (void*)jl_nothing && curr->func!=method) { - if (curr->tvars!=jl_emptysvec && - jl_type_intersection((jl_value_t*)curr->sig, (jl_value_t*)temp2) != - (jl_value_t*)jl_bottom_type) { - jl_svecset(newparams, i, jl_tparam(type, i)); - might_need_guard = 0; - break; - } - curr = curr->next; - } - } - if (might_need_guard) { - jl_methlist_t *curr = mt->defs; - while (curr != (void*)jl_nothing && curr->func!=method) { - jl_tupletype_t *sig = curr->sig; - if (jl_nparams(sig) > i && jl_is_tuple_type(jl_tparam(sig,i))) { - need_guard_entries = 1; - break; - } - curr = curr->next; - } - } - } else if (jl_is_type_type(elt) && jl_is_type_type(jl_tparam0(elt)) && // give up on specializing static parameters for Type{Type{Type{...}}} (jl_is_type_type(jl_tparam0(jl_tparam0(elt))) || From 52e4f3aa930829cd2ca7c49c410fefb469578ef0 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 25 May 2015 12:49:43 -0400 Subject: [PATCH 085/181] remove another bit of dead code from specializing on all tuples --- src/gf.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/gf.c b/src/gf.c index 12c2bd50db08c..b0f670013458d 100644 --- a/src/gf.c +++ b/src/gf.c @@ -442,15 +442,6 @@ static int very_general_type(jl_value_t *t) ((jl_tvar_t*)t)->ub==(jl_value_t*)jl_any_type))); } -static int tuple_all_Any(jl_tupletype_t *t) -{ - for(int i=0; i < jl_nparams(t); i++) { - if (jl_tparam(t,i) != (jl_value_t*)jl_any_type) - return 0; - } - return 1; -} - static int is_kind(jl_value_t *v) { return (v==(jl_value_t*)jl_uniontype_type || From d01ec8aa4a70819c7f4204fcbd3203339abc2c7d Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sat, 25 Apr 2015 14:02:31 -0400 Subject: [PATCH 086/181] Better error message for invoke --- base/replutil.jl | 54 ++++++++++++++++++++++++------------------- src/gf.c | 16 ++++++++++--- src/julia_internal.h | 1 + test/replutil.jl | 55 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 27 deletions(-) diff --git a/base/replutil.jl b/base/replutil.jl index 43dd83ca2990b..3c9f002464881 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -124,6 +124,9 @@ showerror(io::IO, ex::ArgumentError) = print(io, "ArgumentError: $(ex.msg)") showerror(io::IO, ex::AssertionError) = print(io, "AssertionError: $(ex.msg)") function showerror(io::IO, ex::MethodError) + is_arg_types = isa(ex.args, DataType) + arg_types = is_arg_types ? ex.args : typesof(ex.args...) + arg_types_param::SimpleVector = arg_types.parameters print(io, "MethodError: ") if isa(ex.f, Tuple) f = ex.f[1] @@ -137,41 +140,41 @@ function showerror(io::IO, ex::MethodError) else print(io, "`$(name)` has no method matching $(name)(") end - for (i, arg) in enumerate(ex.args) - if isa(arg, Type) && arg != typeof(arg) - print(io, "::Type{$(arg)}") - else - print(io, "::$(typeof(arg))") - end - i == length(ex.args) || print(io, ", ") + for (i, typ) in enumerate(arg_types_param) + print(io, "::$typ") + i == length(arg_types_param) || print(io, ", ") end print(io, ")") # Check for local functions that shadow methods in Base if isdefined(Base, name) basef = eval(Base, name) - if basef !== f && isgeneric(basef) && applicable(basef, ex.args...) + if basef !== ex.f && isgeneric(basef) && method_exists(basef, arg_types) println(io) print(io, "you may have intended to import Base.$(name)") end end - # Check for row vectors used where a column vector is intended. - vec_args = [] - hasrows = false - for arg in ex.args - isrow = isa(arg,Array) && ndims(arg)==2 && size(arg,1)==1 - hasrows |= isrow - push!(vec_args, isrow ? vec(arg) : arg) - end - if hasrows && applicable(f, vec_args...) - print(io, "\n\nYou might have used a 2d row vector where a 1d column vector was required.") - print(io, "\nNote the difference between 1d column vector [1,2,3] and 2d row vector [1 2 3].") - print(io, "\nYou can convert to a column vector with the vec() function.") + if !is_arg_types + # Check for row vectors used where a column vector is intended. + vec_args = [] + hasrows = false + for arg in ex.args + isrow = isa(arg,Array) && ndims(arg)==2 && size(arg,1)==1 + hasrows |= isrow + push!(vec_args, isrow ? vec(arg) : arg) + end + if hasrows && applicable(f, vec_args...) + print(io, "\n\nYou might have used a 2d row vector where a 1d column vector was required.") + print(io, "\nNote the difference between 1d column vector [1,2,3] and 2d row vector [1 2 3].") + print(io, "\nYou can convert to a column vector with the vec() function.") + end end # Give a helpful error message if the user likely called a type constructor # and sees a no method error for convert - if f == Base.convert && !isempty(ex.args) && isa(ex.args[1], Type) + if (f == Base.convert && !isempty(arg_types_param) && + isa(arg_types_param[1], Type)) + construct_type = arg_types_param[1].parameters[1] println(io) - print(io, "This may have arisen from a call to the constructor $(ex.args[1])(...),") + print(io, "This may have arisen from a call to the constructor $construct_type(...),") print(io, "\nsince type constructors fall back to convert methods.") end show_method_candidates(io, ex) @@ -181,6 +184,9 @@ const UNSHOWN_METHODS = ObjectIdDict( which(call, Tuple{Type, Vararg{Any}}) => true ) function show_method_candidates(io::IO, ex::MethodError) + is_arg_types = isa(ex.args, DataType) + arg_types = is_arg_types ? ex.args : typesof(ex.args...) + arg_types_param::SimpleVector = arg_types.parameters # Displays the closest candidates of the given function by looping over the # functions methods and counting the number of matching arguments. if isa(ex.f, Tuple) @@ -217,7 +223,7 @@ function show_method_candidates(io::IO, ex::MethodError) show_delim_array(buf, tv, '{', ',', '}', false) end print(buf, "(") - t_i = Any[Base.REPLCompletions.method_type_of_arg(arg) for arg in ex.args] + t_i = Any[arg_types_param...] right_matches = 0 for i = 1 : min(length(t_i), length(sig)) i > (use_constructor_syntax ? 2 : 1) && print(buf, ", ") @@ -259,7 +265,7 @@ function show_method_candidates(io::IO, ex::MethodError) if length(t_i) > length(sig) && !isempty(sig) && Base.isvarargtype(sig[end]) # It ensures that methods like f(a::AbstractString...) gets the correct # number of right_matches - for t in typeof(ex.args).parameters[length(sig):end] + for t in arg_types_param[length(sig):end] if t <: sig[end].parameters[1] right_matches += 1 end diff --git a/src/gf.c b/src/gf.c index b0f670013458d..b923b12348ba1 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1301,12 +1301,22 @@ jl_methlist_t *jl_method_table_insert(jl_methtable_t *mt, jl_tupletype_t *type, return ml; } +void NORETURN jl_no_method_error_bare(jl_function_t *f, jl_value_t *args) +{ + jl_value_t *fargs[3] = { + (jl_value_t*)jl_methoderror_type, + (jl_value_t*)f, + args + }; + jl_throw(jl_apply(jl_module_call_func(jl_base_module), fargs, 3)); + // not reached +} + void NORETURN jl_no_method_error(jl_function_t *f, jl_value_t **args, size_t na) { jl_value_t *argtup = jl_f_tuple(NULL, args, na); JL_GC_PUSH1(&argtup); - jl_value_t *fargs[3] = { (jl_value_t*)jl_methoderror_type, (jl_value_t*)f, argtup }; - jl_throw(jl_apply(jl_module_call_func(jl_base_module), fargs, 3)); + jl_no_method_error_bare(f, argtup); // not reached } @@ -1683,7 +1693,7 @@ jl_value_t *jl_gf_invoke(jl_function_t *gf, jl_tupletype_t *types, size_t i; if ((jl_value_t*)m == jl_nothing) { - jl_no_method_error(gf, args, nargs); + jl_no_method_error_bare(gf, (jl_value_t*)types); // unreachable } diff --git a/src/julia_internal.h b/src/julia_internal.h index 0115aa09bad61..0d7bac5feb0ef 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -48,6 +48,7 @@ void jl_set_t_uid_ctr(int i); uint32_t jl_get_gs_ctr(void); void jl_set_gs_ctr(uint32_t ctr); +void NORETURN jl_no_method_error_bare(jl_function_t *f, jl_value_t *args); void NORETURN jl_no_method_error(jl_function_t *f, jl_value_t **args, size_t na); #define JL_CALLABLE(name) \ diff --git a/test/replutil.jl b/test/replutil.jl index db0a4bcdd173e..14682173e9a5a 100644 --- a/test/replutil.jl +++ b/test/replutil.jl @@ -68,3 +68,58 @@ for f in [getindex, setindex!] Base.show_method_candidates(buf, MethodError(f,(test_type, 1,1))) test_have_color(buf, "", "") end + + +function _except_str(expr, err_type=Exception) + quote + let + local err::$(esc(err_type)) + try + $(esc(expr)) + catch err + end + err + buff = IOBuffer() + showerror(buff, err) + takebuf_string(buff) + end + end +end + +macro except_str(args...) + _except_str(args...) +end + +# Pull Request 11007 +abstract InvokeType11007 +abstract MethodType11007 <: InvokeType11007 +type InstanceType11007 <: MethodType11007 +end +let + f11007(::MethodType11007) = nothing + err_str = @except_str(invoke(f11007, Tuple{InvokeType11007}, + InstanceType11007()), MethodError) + @test !contains(err_str, "::InstanceType11007") + @test contains(err_str, "::InvokeType11007") +end + +let + +() = nothing + err_str = @except_str 1 + 2 MethodError + @test contains(err_str, "Base.+") +end + +let + g11007(::AbstractVector) = nothing + err_str = @except_str g11007([[1] [1]]) + @test contains(err_str, "row vector") + @test contains(err_str, "column vector") +end + +abstract T11007 +let + err_str = @except_str T11007() + @test contains(err_str, "convert") + @test contains(err_str, "constructor") + @test contains(err_str, "T11007(...)") +end From a973bb6ad838dfd39da52b21e41c9ee3d0cbe5d6 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Mon, 25 May 2015 22:39:00 +0530 Subject: [PATCH 087/181] Move ARM configuration later in the file, after ARCH is detected. --- Make.inc | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/Make.inc b/Make.inc index 7b6725e5fd6b1..e2592bf8c1f1e 100644 --- a/Make.inc +++ b/Make.inc @@ -140,7 +140,6 @@ private_libdir = $(prefix)/lib/$(MULTIARCH)/julia libdir = $(prefix)/lib/$(MULTIARCH)/ endif - # LLVM Options LLVMROOT = $(build_prefix) LLVM_ASSERTIONS = 0 @@ -381,26 +380,6 @@ else build_shlibdir = $(build_libdir) endif -# If we are running on ARM, set certain options automatically -ifneq (,$(findstring arm,$(ARCH))) -LLVM_ASSERTIONS=1 -LLVM_FLAGS+="--with-cpu=cortex-a9 --with-float=hard --with-abi=aapcs-vfp --enable-assertions" - -OPENBLAS_DYNAMIC_ARCH=0 -OPENBLAS_TARGET_ARCH=ARMV7 -USE_BLAS64=0 - -LLVM_VER=3.6.0 - -USE_SYSTEM_LIBM=1 -USE_SYSTEM_FFTW=1 -USE_SYSTEM_GMP=1 -USE_SYSTEM_MPFR=1 - -JCFLAGS += -fsigned-char -endif - - ifeq (exists, $(shell [ -e $(JULIAHOME)/Make.user ] && echo exists )) include $(JULIAHOME)/Make.user endif @@ -436,7 +415,6 @@ endif # if MARCH is set newer than the native processor, be forewarned that the compile might fail # JULIA_CPU_TARGET is the JIT-only complement to MARCH. Setting it explicitly is not generally necessary, # since it is set equal to MARCH by default - BUILD_MACHINE := $(shell $(HOSTCC) -dumpmachine) ifeq ($(ARCH),) override ARCH := $(shell $(CC) -dumpmachine | sed "s/\([^-]*\).*$$/\1/") @@ -524,6 +502,26 @@ else $(error "unknown word-size for arch: $(ARCH)") endif +# If we are running on ARM, set certain options automatically +ifneq (,$(findstring arm,$(ARCH))) +JCFLAGS += -fsigned-char + +LLVM_ASSERTIONS=1 +LLVM_FLAGS+="--with-float=hard --with-abi=aapcs-vfp" +LLVM_VER=3.6.0 + +USE_BLAS64=0 +#OPENBLAS_DYNAMIC_ARCH=0 +#OPENBLAS_TARGET_ARCH=ARMV7 +USE_SYSTEM_BLAS=1 +USE_SYSTEM_LAPACK=1 +USE_SYSTEM_LIBM=1 +USE_SYSTEM_FFTW=1 +USE_SYSTEM_GMP=1 +USE_SYSTEM_MPFR=1 + +endif + # Set some ARCH-specific flags ifneq ($(USEICC),1) ifeq ($(ISX86),1) From 275d404f231a711d621b76f431755198d39f5db3 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 25 May 2015 13:39:37 -0400 Subject: [PATCH 088/181] add syntax `function foo end` for generic function with no methods closes #8283 --- NEWS.md | 8 +++++-- doc/manual/functions.rst | 1 + doc/manual/methods.rst | 12 ++++++++++ src/codegen.cpp | 44 ++++++++++++++++++++++++++---------- src/interpreter.c | 2 ++ src/julia-parser.scm | 49 ++++++++++++++++++++++------------------ src/julia-syntax.scm | 14 ++++++++---- src/julia.h | 2 ++ src/toplevel.c | 24 ++++++++++++++++++++ test/core.jl | 5 ++++ 10 files changed, 120 insertions(+), 41 deletions(-) diff --git a/NEWS.md b/NEWS.md index 0381fc6c4dd14..a3e5d31a9632e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,7 +5,7 @@ New language features --------------------- * Function call overloading: for arbitrary objects `x` (not of type - `Function`), `x(...)` is transformed into `call(x, ...)`, and `Base.call` + `Function`), `x(...)` is transformed into `call(x, ...)`, and `call` can be overloaded as desired. Constructors are now a special case of this mechanism, which allows e.g. constructors for abstract types. `T(...)` falls back to `convert(T, x)`, so all `convert` methods implicitly @@ -23,12 +23,15 @@ New language features it operates at two different stages of evaluation. At compile time, the generated function is called with its arguments bound to the types for which it should specialize. The quoted expression it returns forms the body of the specialized - method which is then called at run time. ([#7311]). + method which is then called at run time ([#7311]). * (Also with syntax todo) Documentation system for functions, methods, types and macros in packages and user code ([#8791]). Type `?@doc` at the repl to see the current syntax and more information. + * The syntax `function foo end` can be used to introduce a generic function without + yet adding any methods ([#8283]). + Language changes ---------------- @@ -1324,6 +1327,7 @@ Too numerous to mention. [#8089]: https://github.com/JuliaLang/julia/issues/8089 [#8152]: https://github.com/JuliaLang/julia/issues/8152 [#8246]: https://github.com/JuliaLang/julia/issues/8246 +[#8283]: https://github.com/JuliaLang/julia/issues/8283 [#8297]: https://github.com/JuliaLang/julia/issues/8297 [#8399]: https://github.com/JuliaLang/julia/issues/8399 [#8423]: https://github.com/JuliaLang/julia/issues/8423 diff --git a/doc/manual/functions.rst b/doc/manual/functions.rst index f6f53652b0975..8c7166edde293 100644 --- a/doc/manual/functions.rst +++ b/doc/manual/functions.rst @@ -183,6 +183,7 @@ Expression Calls ``1:n`` :func:`colon` ``A[i]`` :func:`getindex` ``A[i]=x`` :func:`setindex!` +``A(x)`` :func:`call` =================== ================== These functions are included in the ``Base.Operators`` module even diff --git a/doc/manual/methods.rst b/doc/manual/methods.rst index 91a8eeb0caa9f..43ba174f82dd9 100644 --- a/doc/manual/methods.rst +++ b/doc/manual/methods.rst @@ -610,5 +610,17 @@ to get ``70``. ``call`` overloading is also used extensively for type constructors in Julia, discussed :ref:`later in the manual `. +Empty generic functions +----------------------- + +Occasionally it is useful to introduce a generic function without yet adding +methods. +This can be used to separate interface definitions from implementations. +It might also be done for the purpose of documentation or code readability. +The syntax for this is an empty ``function`` block without a tuple of +arguments:: + + function emptyfunc + end .. [Clarke61] Arthur C. Clarke, *Profiles of the Future* (1961): Clarke's Third Law. diff --git a/src/codegen.cpp b/src/codegen.cpp index 5a0a71c4673da..7ff9bc45d90b1 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -292,6 +292,7 @@ static Function *jlgetfield_func; static Function *jlbox_func; static Function *jlclosure_func; static Function *jlmethod_func; +static Function *jlgenericfunction_func; static Function *jlenter_func; static Function *jlleave_func; static Function *jlegal_func; @@ -1478,8 +1479,10 @@ static void simple_escape_analysis(jl_value_t *expr, bool esc, jl_codectx_t *ctx } else if (e->head == method_sym) { simple_escape_analysis(jl_exprarg(e,0), esc, ctx); - simple_escape_analysis(jl_exprarg(e,1), esc, ctx); - simple_escape_analysis(jl_exprarg(e,2), esc, ctx); + if (jl_expr_nargs(e) > 1) { + simple_escape_analysis(jl_exprarg(e,1), esc, ctx); + simple_escape_analysis(jl_exprarg(e,2), esc, ctx); + } } else if (e->head == assign_sym) { // don't consider assignment LHS as a variable "use" @@ -3121,16 +3124,22 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, } } } - Value *a1 = boxed(emit_expr(args[1], ctx),ctx); - make_gcroot(a1, ctx); - Value *a2 = boxed(emit_expr(args[2], ctx),ctx); - make_gcroot(a2, ctx); - Value *mdargs[9] = - { name, bp, bp_owner, literal_pointer_val(bnd), a1, a2, literal_pointer_val(args[3]), - literal_pointer_val((jl_value_t*)jl_module_call_func(ctx->module)), - ConstantInt::get(T_int32, (int)iskw) }; - ctx->argDepth = last_depth; - return builder.CreateCall(prepare_call(jlmethod_func), ArrayRef(&mdargs[0], 9)); + if (jl_expr_nargs(ex) == 1) { + Value *mdargs[4] = { name, bp, bp_owner, literal_pointer_val(bnd) }; + return builder.CreateCall(prepare_call(jlgenericfunction_func), ArrayRef(&mdargs[0], 4)); + } + else { + Value *a1 = boxed(emit_expr(args[1], ctx),ctx); + make_gcroot(a1, ctx); + Value *a2 = boxed(emit_expr(args[2], ctx),ctx); + make_gcroot(a2, ctx); + Value *mdargs[9] = + { name, bp, bp_owner, literal_pointer_val(bnd), a1, a2, literal_pointer_val(args[3]), + literal_pointer_val((jl_value_t*)jl_module_call_func(ctx->module)), + ConstantInt::get(T_int32, (int)iskw) }; + ctx->argDepth = last_depth; + return builder.CreateCall(prepare_call(jlmethod_func), ArrayRef(&mdargs[0], 9)); + } } else if (head == const_sym) { jl_sym_t *sym = (jl_sym_t*)args[0]; @@ -5200,6 +5209,17 @@ static void init_julia_llvm_env(Module *m) "jl_method_def", m); add_named_global(jlmethod_func, (void*)&jl_method_def); + std::vector funcdefargs(0); + funcdefargs.push_back(jl_pvalue_llvmt); + funcdefargs.push_back(jl_ppvalue_llvmt); + funcdefargs.push_back(jl_pvalue_llvmt); + funcdefargs.push_back(jl_pvalue_llvmt); + jlgenericfunction_func = + Function::Create(FunctionType::get(jl_pvalue_llvmt, funcdefargs, false), + Function::ExternalLinkage, + "jl_generic_function_def", m); + add_named_global(jlgenericfunction_func, (void*)&jl_generic_function_def); + std::vector ehargs(0); ehargs.push_back(T_pint8); jlenter_func = diff --git a/src/interpreter.c b/src/interpreter.c index 46006808a84d2..d04d3a46bf9dc 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -294,6 +294,8 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl, size_t ng bp_owner = (jl_value_t*)jl_current_module; } } + if (jl_expr_nargs(ex) == 1) + return jl_generic_function_def(fname, bp, bp_owner, b); jl_value_t *atypes=NULL, *meth=NULL; JL_GC_PUSH2(&atypes, &meth); atypes = eval(args[1], locals, nl, ngensym); diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 36981c0ea0d50..ad301af65c0d7 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -1123,28 +1123,33 @@ ((stagedfunction function macro) (if (eq? word 'stagedfunction) (syntax-deprecation-warning s "stagedfunction" "@generated function")) (let* ((paren (eqv? (require-token s) #\()) - (sig (parse-call s)) - (def (if (or (symbol? sig) - (and (pair? sig) (eq? (car sig) '|::|) - (symbol? (cadr sig)))) - (if paren - ;; in "function (x)" the (x) is a tuple - `(tuple ,sig) - ;; function foo => syntax error - (error (string "expected \"(\" in \"" word "\" definition"))) - (if (not (and (pair? sig) - (or (eq? (car sig) 'call) - (eq? (car sig) 'tuple)))) - (error (string "expected \"(\" in \"" word "\" definition")) - sig))) - (loc (begin (if (not (eq? (peek-token s) 'end)) - ;; if ends on same line, don't skip the following newline - (skip-ws-and-comments (ts:port s))) - (line-number-filename-node s))) - (body (parse-block s))) - (expect-end s) - (add-filename-to-block! body loc) - (list word def body))) + (sig (parse-call s))) + (if (and (eq? word 'function) (not paren) (symbol? sig)) + (begin (if (not (eq? (require-token s) 'end)) + (error (string "expected \"end\" in definition of function \"" sig "\""))) + (take-token s) + `(function ,sig)) + (let* ((def (if (or (symbol? sig) + (and (pair? sig) (eq? (car sig) '|::|) + (symbol? (cadr sig)))) + (if paren + ;; in "function (x)" the (x) is a tuple + `(tuple ,sig) + ;; function foo => syntax error + (error (string "expected \"(\" in " word " definition"))) + (if (not (and (pair? sig) + (or (eq? (car sig) 'call) + (eq? (car sig) 'tuple)))) + (error (string "expected \"(\" in " word " definition")) + sig))) + (loc (begin (if (not (eq? (peek-token s) 'end)) + ;; if ends on same line, don't skip the following newline + (skip-ws-and-comments (ts:port s))) + (line-number-filename-node s))) + (body (parse-block s))) + (expect-end s) + (add-filename-to-block! body loc) + (list word def body))))) ((abstract) (list 'abstract (parse-subtype-spec s))) ((type immutable) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 5718e656e3ec4..e72ceb05dbb67 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1086,7 +1086,9 @@ (expand-binding-forms `(-> ,name ,(caddr e))) e)) - e))) + (if (and (length= e 2) (symbol? name)) + `(method ,name) + e)))) ((->) (let ((a (cadr e)) @@ -3041,10 +3043,12 @@ So far only the second case can actually occur. (vinfo:set-sa! vi #f) (if (assq (car vi) captvars) (vinfo:set-iasg! vi #t))))) - `(method ,(cadr e) - ,(analyze-vars (caddr e) env captvars) - ,(analyze-vars (cadddr e) env captvars) - ,(caddddr e))) + (if (length= e 2) + `(method ,(cadr e)) + `(method ,(cadr e) + ,(analyze-vars (caddr e) env captvars) + ,(analyze-vars (cadddr e) env captvars) + ,(caddddr e)))) (else (cons (car e) (map (lambda (x) (analyze-vars x env captvars)) (cdr e))))))) diff --git a/src/julia.h b/src/julia.h index e9f8f2e4d6b69..04a633f67ed66 100644 --- a/src/julia.h +++ b/src/julia.h @@ -966,6 +966,8 @@ jl_expr_t *jl_exprn(jl_sym_t *head, size_t n); jl_function_t *jl_new_generic_function(jl_sym_t *name); void jl_add_method(jl_function_t *gf, jl_tupletype_t *types, jl_function_t *meth, jl_svec_t *tvars, int8_t isstaged); +DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name, jl_value_t **bp, jl_value_t *bp_owner, + jl_binding_t *bnd); DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_value_t *bp_owner, jl_binding_t *bnd, jl_svec_t *argtypes, jl_function_t *f, jl_value_t *isstaged, jl_value_t *call_func, int iskw); diff --git a/src/toplevel.c b/src/toplevel.c index ff115071e8fa8..0dbda6a304f4d 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -660,6 +660,30 @@ static int type_contains(jl_value_t *ty, jl_value_t *x) void print_func_loc(JL_STREAM *s, jl_lambda_info_t *li); +// empty generic function def +// TODO: maybe have jl_method_def call this +DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name, jl_value_t **bp, jl_value_t *bp_owner, + jl_binding_t *bnd) +{ + jl_value_t *gf=NULL; + + if (bnd && bnd->value != NULL && !bnd->constp) + jl_errorf("cannot define function %s; it already has a value", bnd->name->name); + if (*bp != NULL) { + gf = *bp; + if (!jl_is_gf(gf)) + jl_errorf("cannot define function %s; it already has a value", name->name); + } + if (bnd) + bnd->constp = 1; + if (*bp == NULL) { + gf = (jl_value_t*)jl_new_generic_function(name); + *bp = gf; + if (bp_owner) gc_wb(bp_owner, gf); + } + return gf; +} + DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_value_t *bp_owner, jl_binding_t *bnd, jl_svec_t *argdata, jl_function_t *f, jl_value_t *isstaged, diff --git a/test/core.jl b/test/core.jl index dafcfe15cda23..b5521e2b3fdef 100644 --- a/test/core.jl +++ b/test/core.jl @@ -2899,3 +2899,8 @@ let t = Tuple{Type{Vector{Int}}} t = Tuple{Type{Dict{TypeVar(:K, true)}}} @test f11355(t) == 100 end + +# issue #8283 +function func8283 end +@test isa(func8283,Function) && isgeneric(func8283) +@test_throws MethodError func8283() From 216d7fec958d429856562ffda1179a3df94f9233 Mon Sep 17 00:00:00 2001 From: Blake Johnson Date: Mon, 25 May 2015 13:21:12 -0400 Subject: [PATCH 089/181] Add a test for user path completion. Also, a fix from actually writing the test: make string closing behavior of homedir path's consistent with other paths. --- base/REPLCompletions.jl | 2 +- test/replcompletions.jl | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index 31c341d2cd4d5..33741029a68ba 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -302,7 +302,7 @@ function completions(string, pos) paths, r, success = complete_path(replace(string[r], r"\\ ", " "), pos) if inc_tag == :string && length(paths) == 1 && # Only close if there's a single choice, - !isdir(replace(string[startpos:start(r)-1] * paths[1], r"\\ ", " ")) && # except if it's a directory + !isdir(expanduser(replace(string[startpos:start(r)-1] * paths[1], r"\\ ", " "))) && # except if it's a directory (length(string) <= pos || string[pos+1] != '"') # or there's already a " at the cursor. paths[1] *= "\"" end diff --git a/test/replcompletions.jl b/test/replcompletions.jl index 9fde5769b1b85..f9fa99607f860 100644 --- a/test/replcompletions.jl +++ b/test/replcompletions.jl @@ -377,6 +377,19 @@ c, r, res = test_scomplete(s) @test "Pkg" in c @test r == 6:7 @test s[r] == "Pk" + + # Tests homedir expansion + let + path = homedir() + dir = joinpath(path, "tmpfoobar") + mkdir(dir) + s = "\"~/tmpfoob" + c,r = test_complete(s) + @test "tmpfoobar/" in c + @test r == 4:10 + @test s[r] == "tmpfoob" + rm(dir) + end end let #test that it can auto complete with spaces in file/path From 7b6de4b9bffb16765dc11d1a8314487fa401ff42 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 25 May 2015 13:46:39 -0400 Subject: [PATCH 090/181] show nested Pairs with parens. part of #11436 --- base/show.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/base/show.jl b/base/show.jl index 9c5dc1b8ffdc3..e0fff18387f2f 100644 --- a/base/show.jl +++ b/base/show.jl @@ -122,9 +122,13 @@ print(io::IO, n::Unsigned) = print(io, dec(n)) show{T}(io::IO, p::Ptr{T}) = print(io, typeof(p), " @0x$(hex(UInt(p), WORD_SIZE>>2))") function show(io::IO, p::Pair) + isa(p.first,Pair) && print(io, "(") show(io, p.first) + isa(p.first,Pair) && print(io, ")") print(io, "=>") + isa(p.second,Pair) && print(io, "(") show(io, p.second) + isa(p.second,Pair) && print(io, ")") end function show(io::IO, m::Module) From f32acc81c3ef11de2d5b220ccea26cd006bbe1e7 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 25 May 2015 16:31:56 -0400 Subject: [PATCH 091/181] remove unnecessary ability for Enum types to have parameters. fixes #11164 --- base/Enums.jl | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/base/Enums.jl b/base/Enums.jl index 6770e6f8a8f10..0e820b803b042 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -7,9 +7,6 @@ export Enum, @enum abstract Enum Base.convert{T<:Integer}(::Type{T},x::Enum) = convert(T, x.val) -Base.convert{T<:Enum}(::Type{T},x::Integer) = T(x) -Base.start{T<:Enum}(::Type{T}) = 1 -# next, done defined per Enum # generate code to test whether expr is in the given set of values function membershiptest(expr, values) @@ -32,8 +29,6 @@ macro enum(T,syms...) end if isa(T,Symbol) typename = T - elseif isa(T,Expr) && T.head === :curly - typename = T.args[1] else throw(ArgumentError("invalid type expression for enum $T")) end @@ -92,26 +87,27 @@ macro enum(T,syms...) # enum definition immutable $(esc(T)) <: Enum val::$enumT - function $(esc(typename))(x::Integer) + function Base.convert(::Type{$(esc(typename))}, x::Integer) $(membershiptest(:x, values)) || enum_argument_error($(Expr(:quote, typename)), x) new(x) end end - Base.typemin{E<:$(esc(typename))}(x::Type{E}) = E($lo) - Base.typemax{E<:$(esc(typename))}(x::Type{E}) = E($hi) - Base.length{E<:$(esc(typename))}(x::Type{E}) = $(length(vals)) - Base.next{E<:$(esc(typename))}(x::Type{E},s) = (E($values[s]),s+1) - Base.done{E<:$(esc(typename))}(x::Type{E},s) = s > $(length(values)) - Base.names{E<:$(esc(typename))}(x::Type{E}) = [$(map(x->Expr(:quote, (x[1])), vals)...)] - Base.isless{E<:$(esc(typename))}(x::E, y::E) = isless(x.val, y.val) - function Base.print{E<:$(esc(typename))}(io::IO,x::E) + Base.typemin(x::Type{$(esc(typename))}) = $(esc(typename))($lo) + Base.typemax(x::Type{$(esc(typename))}) = $(esc(typename))($hi) + Base.length(x::Type{$(esc(typename))}) = $(length(vals)) + Base.start(::Type{$(esc(typename))}) = 1 + Base.next(x::Type{$(esc(typename))},s) = ($(esc(typename))($values[s]),s+1) + Base.done(x::Type{$(esc(typename))},s) = s > $(length(values)) + Base.names(x::Type{$(esc(typename))}) = [$(map(x->Expr(:quote, (x[1])), vals)...)] + Base.isless(x::$(esc(typename)), y::$(esc(typename))) = isless(x.val, y.val) + function Base.print(io::IO,x::$(esc(typename))) for (sym, i) in $vals if i == x.val print(io, sym); break end end end - Base.show{E<:$(esc(typename))}(io::IO,x::E) = print(io, x, "::", E) + Base.show(io::IO,x::$(esc(typename))) = print(io, x, "::", $(esc(typename))) end if isa(T,Symbol) for (sym,i) in vals From 3bc6c75379c72c3a31353a9e3d3884fa6a597d82 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 25 May 2015 16:35:19 -0400 Subject: [PATCH 092/181] switch `int` to `Int` in Enum help. fixes #11227 --- doc/stdlib/base.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index ec16b5016822c..f959f827c1ca8 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -476,7 +476,7 @@ Types julia> @enum FRUIT apple=1 orange=2 kiwi=3 - julia> f(x::FRUIT) = "I'm a FRUIT with value: $(int(x))" + julia> f(x::FRUIT) = "I'm a FRUIT with value: $(Int(x))" f (generic function with 1 method) julia> f(apple) From 11755f1e98f57c6b9eaee41eb985713eb8c2cdbb Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 23 May 2015 18:21:13 -0400 Subject: [PATCH 093/181] make -i option run REPL. fixes #11347 --- base/client.jl | 5 ++++- ui/repl.c | 5 ++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/base/client.jl b/base/client.jl index 88d6f871079e0..093b53fc362ce 100644 --- a/base/client.jl +++ b/base/client.jl @@ -306,7 +306,9 @@ let reqarg = Set(UTF8String["--home", "-H", repl = false # remove filename from ARGS shift!(ARGS) - ccall(:jl_exit_on_sigint, Void, (Cint,), 1) + if !is_interactive + ccall(:jl_exit_on_sigint, Void, (Cint,), 1) + end include(args[1]) else println(STDERR, "julia: unknown option `$(args[1])`") @@ -315,6 +317,7 @@ let reqarg = Set(UTF8String["--home", "-H", end break end + repl |= is_interactive return (quiet,repl,startup,color_set,history_file) end end diff --git a/ui/repl.c b/ui/repl.c index c756ef6c6932f..4b01348a06825 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -61,7 +61,7 @@ static const char opts[] = " 'auto' launches as many workers as the number of local cores\n" " --machinefile Run processes on hosts listed in \n\n" - " -i Force isinteractive() to be true\n" + " -i Interactive mode; REPL runs and isinteractive() is true\n" " --color={yes|no} Enable or disable color text\n\n" " --history-file={yes|no} Load or save history\n" " --no-history-file Don't load history file (deprecated, use --history-file=no)\n" @@ -76,8 +76,7 @@ static const char opts[] = " --track-allocation={none|user|all}, --track-allocation\n" " Count bytes allocated by each source line\n\n" - " -O, --optimize\n" - " Run time-intensive code optimizations\n" + " -O, --optimize Run time-intensive code optimizations\n" " --check-bounds={yes|no} Emit bounds checks always or never (ignoring declarations)\n" " --dump-bitcode={yes|no} Dump bitcode for the system image (used with --build)\n" " --depwarn={yes|no} Enable or disable syntax and method deprecation warnings\n" From 5b9fd0b72fe2bf8c021270a6e7afdab3565a9d05 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 25 May 2015 16:40:35 -0400 Subject: [PATCH 094/181] NEWS update for -i option change --- NEWS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS.md b/NEWS.md index a3e5d31a9632e..6554f1858ae43 100644 --- a/NEWS.md +++ b/NEWS.md @@ -114,6 +114,11 @@ Language changes macro. Instead, the string is first unindented and then `x_str` is invoked, as if the string had been single-quoted ([#10228]). +Command line option changes +--------------------------- + + * The `-i` option now forces the REPL to run after loading the specified script (if any) ([#11347]). + Compiler improvements --------------------- @@ -1426,4 +1431,5 @@ Too numerous to mention. [#11145]: https://github.com/JuliaLang/julia/issues/11145 [#11171]: https://github.com/JuliaLang/julia/issues/11171 [#11241]: https://github.com/JuliaLang/julia/issues/11241 +[#11347]: https://github.com/JuliaLang/julia/issues/11347 [#11379]: https://github.com/JuliaLang/julia/issues/11379 From 0ba9c91fe1f151441ce83352f6f7646f93aa9883 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Mon, 25 May 2015 21:43:20 +0100 Subject: [PATCH 095/181] Disable 'dist' and 'source-dist' make targets Yet another step towards making 'dist' equivalent to 'light-source-dist', as in most projects. Also change mentions of old targets in docs. [av skip] --- DISTRIBUTING.md | 14 +++++++------- Makefile | 10 ++++++++-- README.windows.md | 4 ++-- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/DISTRIBUTING.md b/DISTRIBUTING.md index 4b2fa8e7261e1..5bf9000d3137a 100644 --- a/DISTRIBUTING.md +++ b/DISTRIBUTING.md @@ -29,10 +29,10 @@ pregenerate the `base/version_git.jl` file with: Julia has lots of build dependencies where we use patched versions that has not yet been included by the popular package managers. These dependencies will usually be automatically downloaded when you build, but if you want to be able to build -Julia on a computer without internet access you should create a source-dist archive -with the special make target +Julia on a computer without internet access you should create a full-source-dist +archive with the special make target - make source-dist + make full-source-dist that creates a julia-version-commit.tar.gz archive with all required dependencies. @@ -66,9 +66,9 @@ The full list of CPU targets supported by LLVM can be obtained by running Linux ----- -On Linux, `make dist` creates a tarball that contains a fully functional Julia -installation. If you wish to create a distribution package such as a -`.deb`, or `.rpm`, some extra effort is needed. See the +On Linux, `make binary-dist` creates a tarball that contains a fully +functional Julia installation. If you wish to create a distribution +package such as a `.deb`, or `.rpm`, some extra effort is needed. See the [julia-debian](http://github.com/staticfloat/julia-debian) repository for an example of what metadata is needed for creating `.deb` packages for Debian and Ubuntu-based systems. See the @@ -118,7 +118,7 @@ is to cross-compile from a Linux distribution such as Ubuntu. In-depth compilation instructions [are available](https://github.com/JuliaLang/julia/blob/master/README.windows.md). However the important steps for redistribution are to ensure to `make -win-extras` in between `make` and `make dist`. After that process is +win-extras` in between `make` and `make binary-dist`. After that process is completed, the `.zip` file created in the head Julia directory will hold a completely self-contained Julia. diff --git a/Makefile b/Makefile index 62d8c506573ce..ae87f772edfe9 100644 --- a/Makefile +++ b/Makefile @@ -371,7 +371,10 @@ endif distclean dist-clean: rm -fr julia-*.tar.gz julia*.exe julia-*.7z julia-$(JULIA_COMMIT) -binary-dist dist: distclean +dist: + @echo \'dist\' target is deprecated: use \'binary-dist\' instead. + +binary-dist: distclean ifeq ($(USE_SYSTEM_BLAS),0) ifneq ($(OPENBLAS_DYNAMIC_ARCH),1) @echo OpenBLAS must be rebuilt with OPENBLAS_DYNAMIC_ARCH=1 to use binary-dist target @@ -451,8 +454,11 @@ light-source-dist: light-source-dist.tmp sed -e "s_.*_$$DIRNAME/&_" light-source-dist.tmp > light-source-dist.tmp1; \ cd ../ && tar -cz -T $$DIRNAME/light-source-dist.tmp1 --no-recursion -f $$DIRNAME/julia-$(JULIA_VERSION)_$(JULIA_COMMIT).tar.gz +source-dist: + @echo \'source-dist\' target is deprecated: use \'full-source-dist\' instead. + # Make tarball with Julia code plus all dependencies -full-source-dist source-dist: light-source-dist.tmp +full-source-dist: light-source-dist.tmp # Get all the dependencies downloaded @$(MAKE) -C deps getall NO_GIT=1 diff --git a/README.windows.md b/README.windows.md index 9c83ef4f185b6..e6ea778afc884 100644 --- a/README.windows.md +++ b/README.windows.md @@ -279,8 +279,8 @@ Finally, the build and install process for Julia: 1. `git clone https://github.com/JuliaLang/julia.git julia-win32` 2. `echo override XC_HOST = i686-w64-mingw32 >> Make.user` 3. `make` -4. `make win-extras` (Necessary before running `make dist`p) -5. `make dist` +4. `make win-extras` (Necessary before running `make binary-dist`p) +5. `make binary-dist` 6. move the julia-* directory / zip file to the target machine If you are building for 64-bit windows, the steps are essentially the same. Just replace i686 in XC_HOST with x86_64. (note: on Mac, wine only runs in 32-bit mode) From 969df71d2d66f6fcf06f338d00aad32211cc4cbd Mon Sep 17 00:00:00 2001 From: Jon Malmaud Date: Thu, 14 May 2015 23:25:37 -0400 Subject: [PATCH 096/181] Added ismount function. --- base/exports.jl | 1 + base/stat.jl | 15 +++++++++++++++ doc/stdlib/file.rst | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/base/exports.jl b/base/exports.jl index ec54154e26e0e..2762d68ddff11 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1266,6 +1266,7 @@ export isfifo, isfile, islink, + ismount, ispath, isreadable, issetgid, diff --git a/base/stat.jl b/base/stat.jl index de6f29a25d430..f9b5cc684e090 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -124,3 +124,18 @@ function samefile(a::AbstractString, b::AbstractString) return false end end + +function ismount(path...) + path = joinpath(path...) + isdir(path) || return false + s1 = lstat(path) + # Symbolic links cannot be mount points + islink(s1) && return false + parent_path = joinpath(path, "..") + s2 = lstat(parent_path) + # If a directory and its parent are on different devices, then the + # directory must be a mount point + (s1.device != s2.device) && return true + (s1.inode == s2.inode) && return true + false +end diff --git a/doc/stdlib/file.rst b/doc/stdlib/file.rst index 8969c86c3e715..f53e41b6e3162 100644 --- a/doc/stdlib/file.rst +++ b/doc/stdlib/file.rst @@ -186,6 +186,10 @@ Returns ``true`` if ``path`` is a symbolic link, ``false`` otherwise. +.. function:: ismount(path) -> Bool + + Returns ``true`` if ``path`` is a mount point, ``false`` otherwise. + .. function:: ispath(path) -> Bool Returns ``true`` if ``path`` is a valid filesystem path, ``false`` otherwise. From 769df42927dad2251e4a399a3c286d192b089f2b Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 25 May 2015 22:08:40 -0400 Subject: [PATCH 097/181] fix #11425, performance regression in == on Types --- base/operators.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/operators.jl b/base/operators.jl index fc3e8efa2d284..0f20a088a467c 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -19,7 +19,8 @@ isless(x::FloatingPoint, y::FloatingPoint) = (!isnan(x) & isnan(y)) | (signbit(x isless(x::Real, y::FloatingPoint) = (!isnan(x) & isnan(y)) | (signbit(x) & !signbit(y)) | (x < y) isless(x::FloatingPoint, y::Real ) = (!isnan(x) & isnan(y)) | (signbit(x) & !signbit(y)) | (x < y) -==(T::Type, S::Type) = typeseq(T, S) +=={T}(::Type{T}, ::Type{T}) = true # encourage more specialization on types (see #11425) +==(T::Type, S::Type) = typeseq(T, S) ## comparison fallbacks ## From 63f013bd570652aef702ce18cf8de3c09640c814 Mon Sep 17 00:00:00 2001 From: Mike Nolta Date: Mon, 25 May 2015 21:56:53 -0400 Subject: [PATCH 098/181] Make.inc: remove a couple of unused variables OSXVER and JULIA_TARGET_ARCH --- Make.inc | 2 -- 1 file changed, 2 deletions(-) diff --git a/Make.inc b/Make.inc index e2592bf8c1f1e..5678ceec38020 100644 --- a/Make.inc +++ b/Make.inc @@ -251,7 +251,6 @@ STDLIBCPP_FLAG = ifeq ($(OS), Darwin) DARWINVER := $(shell uname -r | cut -b 1-2) DARWINVER_GTE13 := $(shell expr `uname -r | cut -b 1-2` \>= 13) -OSXVER := $(shell sw_vers -productVersion | cut -b 1-4) ifeq ($(DARWINVER), 10) # Snow Leopard specific configuration USEGCC = 1 USECLANG = 0 @@ -467,7 +466,6 @@ endif endif JULIA_CPU_TARGET ?= native -JCPPFLAGS += -DJULIA_TARGET_ARCH=$(JULIA_CPU_TARGET) # We map amd64 to x86_64 for compatibility with systems that identify 64-bit systems as such ifeq ($(ARCH),amd64) From 116238c4965920c7e8751147124a908e86390b44 Mon Sep 17 00:00:00 2001 From: Mike Nolta Date: Mon, 25 May 2015 22:11:03 -0400 Subject: [PATCH 099/181] '/bin/bash' -> '/usr/bin/env bash' (for FreeBSD) --- contrib/check-whitespace.sh | 2 +- test/perf/micro/java/setup.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/check-whitespace.sh b/contrib/check-whitespace.sh index fb0bc31341b08..ddbd3dda16bc8 100755 --- a/contrib/check-whitespace.sh +++ b/contrib/check-whitespace.sh @@ -1,4 +1,4 @@ -#! /bin/bash +#!/usr/bin/env bash # This file is a part of Julia. License is MIT: http://julialang.org/license # Check for trailing white space in source files; diff --git a/test/perf/micro/java/setup.sh b/test/perf/micro/java/setup.sh index d53c637eddab5..59e83e9f11bae 100755 --- a/test/perf/micro/java/setup.sh +++ b/test/perf/micro/java/setup.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This file is a part of Julia. License is MIT: http://julialang.org/license mvn compile exec:java From 5cf693897e90b5d3c2bc14e46b3e3a5f6fa93a12 Mon Sep 17 00:00:00 2001 From: Jon Malmaud Date: Mon, 25 May 2015 23:08:36 -0400 Subject: [PATCH 100/181] Fix printing of LaTeX markdown to IPython and plain text. --- base/markdown/IPython/IPython.jl | 6 ++++++ base/markdown/render/plain.jl | 2 ++ test/markdown.jl | 17 ++++++++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/base/markdown/IPython/IPython.jl b/base/markdown/IPython/IPython.jl index fead30f770d35..9408421ffaeca 100644 --- a/base/markdown/IPython/IPython.jl +++ b/base/markdown/IPython/IPython.jl @@ -25,5 +25,11 @@ end writemime(io::IO, ::MIME"text/plain", tex::LaTeX) = print(io, '$', tex.formula, '$') +latex(io::IO, tex::LaTeX) = + print(io, "\$\$", tex.formula, "\$\$") + +latexinline(io::IO, tex::LaTeX) = + print(io, '$', tex.formula, '$') + term(io::IO, tex::LaTeX, cols) = println_with_format(:magenta, io, tex.formula) terminline(io::IO, tex::LaTeX) = print_with_format(:magenta, io, tex.formula) diff --git a/base/markdown/render/plain.jl b/base/markdown/render/plain.jl index 6261a9aec3ad6..dffe9048dac59 100644 --- a/base/markdown/render/plain.jl +++ b/base/markdown/render/plain.jl @@ -42,6 +42,8 @@ function plain(io::IO, md::HorizontalRule) println(io, "–" ^ 3) end +plain(io::IO, md) = writemime(io, "text/plain", md) + # Inline elements plaininline(x) = sprint(plaininline, x) diff --git a/test/markdown.jl b/test/markdown.jl index b4a4206c568a9..3605cf8ccdcaf 100644 --- a/test/markdown.jl +++ b/test/markdown.jl @@ -1,7 +1,7 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license using Base.Markdown -import Base.Markdown: MD, Paragraph, Header, Italic, Bold, plain, term, html, Table, Code +import Base.Markdown: MD, Paragraph, Header, Italic, Bold, plain, term, html, Table, Code, LaTeX import Base: writemime # Basics @@ -176,3 +176,18 @@ t = """a | b 1 | 2 """ @test plain(Markdown.parse(t)) == t + + +# LaTeX extension +latex_doc = md""" +We have $x^2 < x$ whenever: + +$|x| < 1$""" + +@test latex_doc == MD(Any[Paragraph(Any["We have ", + LaTeX("x^2 < x"), + " whenever:"]), + LaTeX("|x| < 1")]) + + +@test latex(latex_doc) == "We have \$x^2 < x\$ whenever:\n\$\$|x| < 1\$\$" From a85357a2cad8ac9cd0bc0a5cf2d5e7277fadbe3a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 25 May 2015 23:13:14 -0400 Subject: [PATCH 101/181] fix #11243, strange subtype bug looks like I had tried to add a clause to jl_subtype_le that wasn't present in 0.3. failed experiment I guess. --- src/jltypes.c | 11 +++++------ test/core.jl | 8 ++++++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/jltypes.c b/src/jltypes.c index 3a3125e905ee0..ba50f9ba5c089 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -2432,17 +2432,16 @@ static int jl_subtype_le(jl_value_t *a, jl_value_t *b, int ta, int invariant) if (jl_subtype_le(a, jl_tparam0(b), 0, 1)) return 1; } - if (invariant && ttb == (jl_datatype_t*)ttb->name->primary) - return 0; assert(jl_nparams(tta) == jl_nparams(ttb)); size_t l = jl_nparams(tta); for(i=0; i < l; i++) { jl_value_t *apara = jl_tparam(tta,i); jl_value_t *bpara = jl_tparam(ttb,i); - if (invariant && jl_is_typevar(bpara) && - !((jl_tvar_t*)bpara)->bound) { - if (!jl_is_typevar(apara)) - return 0; + if (invariant) { + if (jl_is_typevar(bpara) && !((jl_tvar_t*)bpara)->bound) { + if (!jl_is_typevar(apara)) + return 0; + } } if (!jl_subtype_le(apara, bpara, 0, 1)) return 0; diff --git a/test/core.jl b/test/core.jl index b5521e2b3fdef..7f05b5ba3c2fa 100644 --- a/test/core.jl +++ b/test/core.jl @@ -133,8 +133,6 @@ end @test !(Type{Tuple{Int,Int}} <: Tuple) @test Tuple{Type{Int}} <: Tuple{DataType} -@test !issubtype(Type{Array{TypeVar(:T,true)}}, Type{Array}) - @test () != Type{Tuple{}} # issue #6561 @@ -2904,3 +2902,9 @@ end function func8283 end @test isa(func8283,Function) && isgeneric(func8283) @test_throws MethodError func8283() + +# issue #11243 +let a = [Pair(1,2), Pair("a","b")] + @test typeof(a) == Vector{Pair} + @test typeof(a) <: Vector{Pair} +end From 08c2d7ad298a7b74a025a2f5069bd0c5e6ae5afe Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Tue, 26 May 2015 11:33:06 +0530 Subject: [PATCH 102/181] Build all the libraries on ARM by default. --- Make.inc | 15 ++++++++------- README.arm.md | 7 ++++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Make.inc b/Make.inc index 5678ceec38020..3366cba927781 100644 --- a/Make.inc +++ b/Make.inc @@ -509,14 +509,15 @@ LLVM_FLAGS+="--with-float=hard --with-abi=aapcs-vfp" LLVM_VER=3.6.0 USE_BLAS64=0 -#OPENBLAS_DYNAMIC_ARCH=0 +OPENBLAS_DYNAMIC_ARCH=0 + #OPENBLAS_TARGET_ARCH=ARMV7 -USE_SYSTEM_BLAS=1 -USE_SYSTEM_LAPACK=1 -USE_SYSTEM_LIBM=1 -USE_SYSTEM_FFTW=1 -USE_SYSTEM_GMP=1 -USE_SYSTEM_MPFR=1 +#USE_SYSTEM_BLAS=1 +#USE_SYSTEM_LAPACK=1 +#USE_SYSTEM_LIBM=1 +#USE_SYSTEM_FFTW=1 +#USE_SYSTEM_GMP=1 +#USE_SYSTEM_MPFR=1 endif diff --git a/README.arm.md b/README.arm.md index 4698b79c270d3..e3acd0ed972c5 100644 --- a/README.arm.md +++ b/README.arm.md @@ -17,11 +17,12 @@ This is the list of known issues on ARM: # Build dependencies In addition to the standard `build-essentials` toolchain the following -libraries must be installed to build on ARM. On Debian/Ubuntu, use the -following command: +libraries may be installed to build on ARM, if you want to avoid +compiling them. We recommend using Ubuntu 14.04 or newer. On +Debian/Ubuntu, use the following command: ```` -sudo apt-get install libblas3gf liblapack3gf libfftw3-dev libgmp3-dev libmpfr-dev libblas-dev liblapack-dev cmake gcc-4.7 g++-4.7 gfortran libgfortran3 +sudo apt-get install libblas3gf liblapack3gf libfftw3-dev libgmp3-dev libmpfr-dev libblas-dev liblapack-dev cmake gcc-4.8 g++-4.8 gfortran libgfortran3 ```` # ARM specific build problems From 86a7d574a95bb2374f86874a859442cfecd214a3 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Tue, 26 May 2015 12:05:15 +0530 Subject: [PATCH 103/181] Better instructions for ARM in the README. --- README.arm.md | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/README.arm.md b/README.arm.md index e3acd0ed972c5..c34626b7f3c87 100644 --- a/README.arm.md +++ b/README.arm.md @@ -16,10 +16,18 @@ This is the list of known issues on ARM: # Build dependencies -In addition to the standard `build-essentials` toolchain the following -libraries may be installed to build on ARM, if you want to avoid -compiling them. We recommend using Ubuntu 14.04 or newer. On -Debian/Ubuntu, use the following command: +We recommend using at least Ubuntu 14.04 and gcc 4.8, which is part of the +standard `build-essentials`. + +Julia on ARM can be built by simply typing `make`, which will download all +the relevant libraries. This is the recommended way, and it will take a +few hours. + +In case the build is troublesome, you can avoid compiling all the +dependencies by commenting out the appropriate `USE_SYSTEM_XYZ` +lines in the `arm` section of `Make.inc`. Install the following +libraries in that case. Also note that this will use the reference +BLAS, which is 10-100x slower. ```` sudo apt-get install libblas3gf liblapack3gf libfftw3-dev libgmp3-dev libmpfr-dev libblas-dev liblapack-dev cmake gcc-4.8 g++-4.8 gfortran libgfortran3 @@ -45,3 +53,7 @@ so by following these tutorials. - [Crouton Tutorial 1](http://www.howtogeek.com/162120/how-to-install-ubuntu-linux-on-your-chromebook-with-crouton/) - [Crouton Tutorial 2](http://lifehacker.com/how-to-install-linux-on-a-chromebook-and-unlock-its-ful-509039343) + +These tutorials will end up installing Ubuntu 12.04, and you have to +upgrade to Ubuntu 14.04, or install Ubuntu 14.04 from scratch by +finding appropriate `crouton` help. From b05a330468cb84448ce13b49833ea98eba1d06df Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Tue, 26 May 2015 12:29:35 +0530 Subject: [PATCH 104/181] Recommend using overrides in Make.user instead of modifying Make.inc. --- Make.inc | 9 --------- README.arm.md | 29 +++++++++++++++++++++++------ 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/Make.inc b/Make.inc index 3366cba927781..cc8d1f34e56f4 100644 --- a/Make.inc +++ b/Make.inc @@ -510,15 +510,6 @@ LLVM_VER=3.6.0 USE_BLAS64=0 OPENBLAS_DYNAMIC_ARCH=0 - -#OPENBLAS_TARGET_ARCH=ARMV7 -#USE_SYSTEM_BLAS=1 -#USE_SYSTEM_LAPACK=1 -#USE_SYSTEM_LIBM=1 -#USE_SYSTEM_FFTW=1 -#USE_SYSTEM_GMP=1 -#USE_SYSTEM_MPFR=1 - endif # Set some ARCH-specific flags diff --git a/README.arm.md b/README.arm.md index c34626b7f3c87..6f852b1e3d642 100644 --- a/README.arm.md +++ b/README.arm.md @@ -20,14 +20,31 @@ We recommend using at least Ubuntu 14.04 and gcc 4.8, which is part of the standard `build-essentials`. Julia on ARM can be built by simply typing `make`, which will download all -the relevant libraries. This is the recommended way, and it will take a +the relevant libraries. This is the *recommended* way, and it will take a few hours. -In case the build is troublesome, you can avoid compiling all the -dependencies by commenting out the appropriate `USE_SYSTEM_XYZ` -lines in the `arm` section of `Make.inc`. Install the following -libraries in that case. Also note that this will use the reference -BLAS, which is 10-100x slower. +OpenBLAS detects the target architecture reasonably well, but in case +it does not, you can force the target architecture should you need to in +`Make.user`. + +```` +override OPENBLAS_TARGET_ARCH=ARMV7 +```` + +Similarly, one can install other system libraries instead of building them, +should the build be troublesome, by adding the following lines in `Make.user`: + +```` +override USE_SYSTEM_BLAS=1 +override USE_SYSTEM_LAPACK=1 +override USE_SYSTEM_LIBM=1 +override USE_SYSTEM_FFTW=1 +override USE_SYSTEM_GMP=1 +override USE_SYSTEM_MPFR=1 +override USE_SYSTEM_ARPACK=1 +```` + +The following command will install all the necessary libraries on Ubuntu. ```` sudo apt-get install libblas3gf liblapack3gf libfftw3-dev libgmp3-dev libmpfr-dev libblas-dev liblapack-dev cmake gcc-4.8 g++-4.8 gfortran libgfortran3 From 54c1eaef012fc9d39150e8e1e5efef4c4a9fe662 Mon Sep 17 00:00:00 2001 From: aiorla Date: Tue, 26 May 2015 11:14:23 +0200 Subject: [PATCH 105/181] Redundant oftypes removes + Use of a more eficient searchsorted. --- base/primes.jl | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/base/primes.jl b/base/primes.jl index 5839fb9f27036..0094b36741ae4 100644 --- a/base/primes.jl +++ b/base/primes.jl @@ -39,7 +39,7 @@ const PRIMES = primes(2^16) # function isprime(n::Integer) (n < 3 || iseven(n)) && return n == 2 - n <= 2^16 && return length(searchsorted(PRIMES,n)) == 1 + n <= 2^16 && return PRIMES[searchsortedlast(PRIMES,n)] == n s = trailing_zeros(n-1) d = (n-1) >>> s for a in witnesses(n) @@ -90,10 +90,10 @@ function factor{T<:Integer}(n::T) for p in PRIMES if n % p == 0 h[p] = get(h,p,0)+1 - n = oftype(n, div(n,p)) + n = div(n,p) while n % p == 0 h[p] = get(h,p,0)+1 - n = oftype(n, div(n,p)) + n = div(n,p) end n == 1 && return h isprime(n) && (h[n] = 1; return h) @@ -112,17 +112,17 @@ function pollardfactors!{T<:Integer}(n::T, h::Dict{T,Int}) while G == 1 x = y for i in 1:r - y = oftype(y, widemul(y,y)%n) - y = oftype(y, (widen(y)+widen(c))%n) + y = widemul(y,y)%n + y = (widen(y)+widen(c))%n end local k::T = 0 G = 1 while k < r && G == 1 for i in 1:(m>(r-k)?(r-k):m) ys = y - y = oftype(y, widemul(y,y)%n) - y = oftype(y, (widen(y)+widen(c))%n) - q = oftype(y, widemul(q,x>y?x-y:y-x)%n) + y = widemul(y,y)%n + y = (widen(y)+widen(c))%n + q = widemul(q,x>y?x-y:y-x)%n end G = gcd(q,n) k = k + m @@ -131,13 +131,13 @@ function pollardfactors!{T<:Integer}(n::T, h::Dict{T,Int}) end G == n && (G = 1) while G == 1 - ys = oftype(ys, widemul(ys,ys)%n) - ys = oftype(ys, (widen(ys)+widen(c))%n) + ys = widemul(ys,ys)%n + ys = (widen(ys)+widen(c))%n G = gcd(x>ys?x-ys:ys-x,n) end if G != n isprime(G) ? h[G] = get(h,G,0) + 1 : pollardfactors!(G,h) - G2 = oftype(n,div(n,G)) + G2 = div(n,G) isprime(G2) ? h[G2] = get(h,G2,0) + 1 : pollardfactors!(G2,h) return h end From 70dd6a849a63e6281d01a7c246a054a096226a9e Mon Sep 17 00:00:00 2001 From: Mike Nolta Date: Tue, 26 May 2015 09:55:43 -0400 Subject: [PATCH 106/181] doc/devdocs/types.rst: fix typo --- doc/devdocs/types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/devdocs/types.rst b/doc/devdocs/types.rst index 61b3ce3fec3b0..87ffba60899ce 100644 --- a/doc/devdocs/types.rst +++ b/doc/devdocs/types.rst @@ -125,7 +125,7 @@ In a method definition like:: g{S<:Integer}(x::S) = 0 -one can extract the underlying :obj:`TypeVar`:: +one can extract the underlying :obj:`TypeVar`: .. testcode:: s From f0712f0dfd96adf468cdfc1268bbf7055d79a36f Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 26 May 2015 14:34:26 -0400 Subject: [PATCH 107/181] refactor sysimg code to allow combining sys.ji and sys.so no functional change yet; to be exposed as a command line option next --- src/cgutils.cpp | 10 +++ src/codegen.cpp | 7 ++- src/dump.c | 145 +++++++++++++++++++++++++++---------------- src/init.c | 52 +++++++++++----- src/julia.h | 2 + src/julia_internal.h | 2 +- 6 files changed, 146 insertions(+), 72 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 85e659aaf4b1e..f48f176033989 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -367,6 +367,16 @@ static void jl_gen_llvm_gv_array(llvm::Module *mod, SmallVector((const unsigned char*)sysimg_data, sysimg_len)); + addComdat(new GlobalVariable(*mod, data->getType(), true, GlobalVariable::ExternalLinkage, + data, "jl_system_image_data")); + Constant *len = ConstantInt::get(T_size, sysimg_len); + addComdat(new GlobalVariable(*mod, len->getType(), true, GlobalVariable::ExternalLinkage, + len, "jl_system_image_size")); +} + static int32_t jl_assign_functionID(Function *functionObject) { // give the function an index in the constant lookup table diff --git a/src/codegen.cpp b/src/codegen.cpp index 7ff9bc45d90b1..82691b7090a08 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -387,6 +387,7 @@ struct jl_varinfo_t { // --- helpers for reloading IR image static void jl_gen_llvm_gv_array(llvm::Module *mod, SmallVector &globalvars); +static void jl_sysimg_to_llvm(llvm::Module *mod, const char *sysimg_data, size_t sysimg_len); extern "C" void jl_dump_bitcode(char *fname) @@ -416,7 +417,7 @@ void jl_dump_bitcode(char *fname) } extern "C" -void jl_dump_objfile(char *fname, int jit_model) +void jl_dump_objfile(char *fname, int jit_model, const char *sysimg_data, size_t sysimg_len) { #ifdef LLVM36 std::error_code err; @@ -487,9 +488,13 @@ void jl_dump_objfile(char *fname, int jit_model) SmallVector globalvars; #ifdef USE_MCJIT + if (sysimg_data) + jl_sysimg_to_llvm(shadow_module, sysimg_data, sysimg_len); jl_gen_llvm_gv_array(shadow_module, globalvars); PM.run(*shadow_module); #else + if (sysimg_data) + jl_sysimg_to_llvm(jl_Module, sysimg_data, sysimg_len); jl_gen_llvm_gv_array(jl_Module, globalvars); PM.run(*jl_Module); #endif diff --git a/src/dump.c b/src/dump.c index fed1d7b9edb72..ed7cd90d6dba2 100644 --- a/src/dump.c +++ b/src/dump.c @@ -216,7 +216,19 @@ static void jl_load_sysimg_so() // attempt to load the pre-compiled sysimage from jl_sysimg_handle // if this succeeds, sysimg_gvars will be a valid array // otherwise, it will be NULL - if (jl_sysimg_handle != 0) { + if (jl_sysimg_handle == 0) { + sysimg_gvars = 0; + return; + } + + int imaging_mode = jl_options.build_path != NULL; +#ifdef _OS_WINDOWS_ + //XXX: the windows linker forces our system image to be + // linked against only one dll, I picked libjulia-release + if (jl_is_debugbuild()) imaging_mode = 1; +#endif + // in --build mode only use sysimg data, not precompiled native code + if (!imaging_mode) { sysimg_gvars = (jl_value_t***)jl_dlsym(jl_sysimg_handle, "jl_sysimg_gvars"); globalUnique = *(size_t*)jl_dlsym(jl_sysimg_handle, "jl_globalUnique"); const char *cpu_target = (const char*)jl_dlsym(jl_sysimg_handle, "jl_sysimg_cpu_target"); @@ -252,8 +264,10 @@ static void jl_load_sysimg_so() } #endif } - else { - sysimg_gvars = 0; + const char *sysimg_data = (const char*)jl_dlsym_e(jl_sysimg_handle, "jl_system_image_data"); + if (sysimg_data) { + size_t len = *(size_t*)jl_dlsym(jl_sysimg_handle, "jl_system_image_size"); + jl_restore_system_image_data(sysimg_data, len); } } @@ -1410,7 +1424,7 @@ int jl_deserialize_verify_mod_list(ios_t *s) extern jl_array_t *jl_module_init_order; -DLLEXPORT void jl_save_system_image(const char *fname) +void jl_save_system_image_to_stream(ios_t *f) { jl_gc_collect(1); jl_gc_collect(0); @@ -1418,28 +1432,24 @@ DLLEXPORT void jl_save_system_image(const char *fname) jl_gc_disable(); htable_reset(&backref_table, 250000); arraylist_new(&reinit_list, 0); - ios_t f; - if (ios_file(&f, fname, 1, 1, 1, 1) == NULL) { - jl_errorf("Cannot open system image file \"%s\" for writing.\n", fname); - } // orphan old Base module if present jl_base_module = (jl_module_t*)jl_get_global(jl_main_module, jl_symbol("Base")); jl_idtable_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("ObjectIdDict")) : NULL; - jl_serialize_value(&f, jl_main_module); - jl_serialize_value(&f, jl_top_module); - jl_serialize_value(&f, jl_typeinf_func); + jl_serialize_value(f, jl_main_module); + jl_serialize_value(f, jl_top_module); + jl_serialize_value(f, jl_typeinf_func); // ensure everything in deser_tag is reassociated with its GlobalValue ptrint_t i=2; for (i=2; i < 255; i++) { - jl_serialize_gv(&f, deser_tag[i]); + jl_serialize_gv(f, deser_tag[i]); } - jl_serialize_globalvals(&f); - jl_serialize_gv_syms(&f, jl_get_root_symbol()); // serialize symbols with GlobalValue references - jl_serialize_value(&f, NULL); // signal the end of the symbols list + jl_serialize_globalvals(f); + jl_serialize_gv_syms(f, jl_get_root_symbol()); // serialize symbols with GlobalValue references + jl_serialize_value(f, NULL); // signal the end of the symbols list // save module initialization order if (jl_module_init_order != NULL) { @@ -1449,34 +1459,50 @@ DLLEXPORT void jl_save_system_image(const char *fname) assert(ptrhash_get(&backref_table, jl_cellref(jl_module_init_order, i)) != HT_NOTFOUND); } } - jl_serialize_value(&f, jl_module_init_order); + jl_serialize_value(f, jl_module_init_order); - write_int32(&f, jl_get_t_uid_ctr()); - write_int32(&f, jl_get_gs_ctr()); + write_int32(f, jl_get_t_uid_ctr()); + write_int32(f, jl_get_gs_ctr()); // record reinitialization functions for (i = 0; i < reinit_list.len; i += 2) { - write_int32(&f, (int)reinit_list.items[i]); - write_int32(&f, (int)reinit_list.items[i+1]); + write_int32(f, (int)reinit_list.items[i]); + write_int32(f, (int)reinit_list.items[i+1]); } - write_int32(&f, -1); + write_int32(f, -1); htable_reset(&backref_table, 0); arraylist_free(&reinit_list); - ios_close(&f); if (en) jl_gc_enable(); } +DLLEXPORT void jl_save_system_image(const char *fname) +{ + ios_t f; + if (ios_file(&f, fname, 1, 1, 1, 1) == NULL) { + jl_errorf("Cannot open system image file \"%s\" for writing.\n", fname); + } + jl_save_system_image_to_stream(&f); + ios_close(&f); +} + +DLLEXPORT ios_t *jl_create_system_image() +{ + ios_t *f; f = (ios_t*)malloc(sizeof(ios_t)); + ios_mem(f, 1000000); + jl_save_system_image_to_stream(f); + return f; +} + extern jl_function_t *jl_typeinf_func; extern int jl_boot_file_loaded; extern void jl_get_builtin_hooks(void); extern void jl_get_system_hooks(void); extern void jl_get_uv_hooks(); -// Takes in a path of the form "usr/lib/julia/sys.ji", such as passed in to jl_restore_system_image() -DLLEXPORT -void jl_preload_sysimg_so(const char *fname) +// Takes in a path of the form "usr/lib/julia/sys.{ji,so}", as passed to jl_restore_system_image() +DLLEXPORT void jl_preload_sysimg_so(const char *fname) { // If passed NULL, don't even bother if (!fname) @@ -1504,22 +1530,8 @@ void jl_preload_sysimg_so(const char *fname) jl_options.cpu_target = (const char *)jl_dlsym(jl_sysimg_handle, "jl_sysimg_cpu_target"); } -DLLEXPORT -void jl_restore_system_image(const char *fname) +void jl_restore_system_image_from_stream(ios_t *f) { - ios_t f; - if (ios_file(&f, fname, 1, 0, 0, 0) == NULL) { - jl_errorf("System image file \"%s\" not found\n", fname); - } - int imaging_mode = jl_options.build_path != NULL; -#ifdef _OS_WINDOWS_ - //XXX: the windows linker forces our system image to be - // linked against only one dll, I picked libjulia-release - if (jl_is_debugbuild()) imaging_mode = 1; -#endif - if (!imaging_mode) { - jl_load_sysimg_so(); - } #ifdef JL_GC_MARKSWEEP int en = jl_gc_is_enabled(); jl_gc_disable(); @@ -1530,10 +1542,10 @@ void jl_restore_system_image(const char *fname) datatype_list = jl_alloc_cell_1d(0); - jl_main_module = (jl_module_t*)jl_deserialize_value(&f, NULL); - jl_top_module = (jl_module_t*)jl_deserialize_value(&f, NULL); + jl_main_module = (jl_module_t*)jl_deserialize_value(f, NULL); + jl_top_module = (jl_module_t*)jl_deserialize_value(f, NULL); jl_internal_main_module = jl_main_module; - jl_typeinf_func = (jl_function_t*)jl_deserialize_value(&f, NULL); + jl_typeinf_func = (jl_function_t*)jl_deserialize_value(f, NULL); jl_core_module = (jl_module_t*)jl_get_global(jl_main_module, jl_symbol("Core")); jl_base_module = (jl_module_t*)jl_get_global(jl_main_module, @@ -1543,12 +1555,12 @@ void jl_restore_system_image(const char *fname) // ensure everything in deser_tag is reassociated with its GlobalValue ptrint_t i; for (i=2; i < 255; i++) { - jl_deserialize_gv(&f, deser_tag[i]); + jl_deserialize_gv(f, deser_tag[i]); } - jl_deserialize_globalvals(&f); - jl_deserialize_gv_syms(&f); + jl_deserialize_globalvals(f); + jl_deserialize_gv_syms(f); - jl_module_init_order = (jl_array_t*)jl_deserialize_value(&f, NULL); + jl_module_init_order = (jl_array_t*)jl_deserialize_value(f, NULL); // cache builtin parametric types for(int i=0; i < jl_array_len(datatype_list); i++) { @@ -1567,14 +1579,14 @@ void jl_restore_system_image(const char *fname) jl_boot_file_loaded = 1; jl_init_box_caches(); - jl_set_t_uid_ctr(read_int32(&f)); - jl_set_gs_ctr(read_int32(&f)); + jl_set_t_uid_ctr(read_int32(f)); + jl_set_gs_ctr(read_int32(f)); // run reinitialization functions - int pos = read_int32(&f); + int pos = read_int32(f); while (pos != -1) { jl_value_t *v = (jl_value_t*)backref_list.items[pos]; - switch (read_int32(&f)) { + switch (read_int32(f)) { case 1: { jl_array_t **a = (jl_array_t**)&v->fieldptr[0]; jl_idtable_rehash(a, jl_array_len(*a)); @@ -1584,12 +1596,11 @@ void jl_restore_system_image(const char *fname) default: assert(0); } - pos = read_int32(&f); + pos = read_int32(f); } //jl_printf(JL_STDERR, "backref_list.len = %d\n", backref_list.len); arraylist_free(&backref_list); - ios_close(&f); #ifdef JL_GC_MARKSWEEP if (en) jl_gc_enable(); @@ -1598,6 +1609,34 @@ void jl_restore_system_image(const char *fname) jl_update_all_fptrs(); } +DLLEXPORT void jl_restore_system_image(const char *fname) +{ + char *dot = strrchr(fname, '.'); + int is_ji = (dot && !strcmp(dot, ".ji")); + + jl_load_sysimg_so(); + if (!is_ji) { + if (sysimg_gvars == 0) + jl_errorf("System image file \"%s\" not found\n", fname); + return; + } + + ios_t f; + if (ios_file(&f, fname, 1, 0, 0, 0) == NULL) { + jl_errorf("System image file \"%s\" not found\n", fname); + } + jl_restore_system_image_from_stream(&f); + ios_close(&f); +} + +DLLEXPORT void jl_restore_system_image_data(const char *buf, size_t len) +{ + ios_t f; + ios_static_buffer(&f, (char*)buf, len); + jl_restore_system_image_from_stream(&f); + ios_close(&f); +} + void jl_init_restored_modules() { if (jl_module_init_order != NULL) { diff --git a/src/init.c b/src/init.c index 63eded6953b0e..ec444bc9c1131 100644 --- a/src/init.c +++ b/src/init.c @@ -1226,30 +1226,48 @@ DLLEXPORT void julia_save() if (jl_options.compile_enabled == JL_OPTIONS_COMPILE_ALL) jl_compile_all(); char *build_ji; - if (asprintf(&build_ji, "%s.ji",build_path) > 0) { + // TODO: these should be replaced by an option to write either a .ji or a .so + int write_ji = 1; // save a .ji file + int separate_so = 1; // save a separate .so file + ios_t *s = NULL; + + if (write_ji) { + if (asprintf(&build_ji, "%s.ji",build_path) <= 0) { + jl_printf(JL_STDERR,"\nFATAL: failed to create string for .ji build path\n"); + return; + } jl_save_system_image(build_ji); free(build_ji); - if (jl_options.dumpbitcode == JL_OPTIONS_DUMPBITCODE_ON) { - char *build_bc; - if (asprintf(&build_bc, "%s.bc",build_path) > 0) { - jl_dump_bitcode(build_bc); - free(build_bc); - } - else { - jl_printf(JL_STDERR,"\nWARNING: failed to create string for .bc build path\n"); - } + } + else { + s = jl_create_system_image(); + } + + if (jl_options.dumpbitcode == JL_OPTIONS_DUMPBITCODE_ON) { + char *build_bc; + if (asprintf(&build_bc, "%s.bc",build_path) > 0) { + jl_dump_bitcode(build_bc); + free(build_bc); + } + else { + jl_printf(JL_STDERR,"\nWARNING: failed to create string for .bc build path\n"); } + } + + if (!write_ji || separate_so) { char *build_o; - if (asprintf(&build_o, "%s.o",build_path) > 0) { - jl_dump_objfile(build_o,0); - free(build_o); + if (asprintf(&build_o, "%s.o",build_path) <= 0) { + jl_printf(JL_STDERR,"\nFATAL: failed to create string for .o build path\n"); + return; + } + if (separate_so) { + jl_dump_objfile(build_o, 0, NULL, 0); } else { - jl_printf(JL_STDERR,"\nFATAL: failed to create string for .o build path\n"); + assert(s != NULL); + jl_dump_objfile(build_o, 0, (const char*)s->buf, s->size); } - } - else { - jl_printf(JL_STDERR,"\nFATAL: failed to create string for .ji build path\n"); + free(build_o); } } } diff --git a/src/julia.h b/src/julia.h index 04a633f67ed66..a8dcba4752fbb 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1173,8 +1173,10 @@ DLLEXPORT void jl_atexit_hook(void); DLLEXPORT void NORETURN jl_exit(int status); DLLEXPORT void jl_preload_sysimg_so(const char *fname); +DLLEXPORT ios_t *jl_create_system_image(); DLLEXPORT void jl_save_system_image(const char *fname); DLLEXPORT void jl_restore_system_image(const char *fname); +DLLEXPORT void jl_restore_system_image_data(const char *buf, size_t len); DLLEXPORT int jl_save_new_module(const char *fname, jl_module_t *mod); DLLEXPORT jl_module_t *jl_restore_new_module(const char *fname); void jl_init_restored_modules(); diff --git a/src/julia_internal.h b/src/julia_internal.h index 0115aa09bad61..ce3a622a60b6f 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -118,7 +118,7 @@ extern JL_THREAD void *jl_stackbase; #endif void jl_dump_bitcode(char *fname); -void jl_dump_objfile(char *fname, int jit_model); +void jl_dump_objfile(char *fname, int jit_model, const char *sysimg_data, size_t sysimg_len); int32_t jl_get_llvm_gv(jl_value_t *p); void jl_idtable_rehash(jl_array_t **pa, size_t newsz); From adf2624ae2025fae8aa7d2e15d0345150b011439 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 26 May 2015 14:47:30 -0400 Subject: [PATCH 108/181] add sysimg data variables to globalvars array --- src/cgutils.cpp | 13 ++++++++----- src/codegen.cpp | 7 ++++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index f48f176033989..a2c931ebe06dd 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -367,14 +367,17 @@ static void jl_gen_llvm_gv_array(llvm::Module *mod, SmallVector &globalvars, + const char *sysimg_data, size_t sysimg_len) { Constant *data = ConstantDataArray::get(jl_LLVMContext, ArrayRef((const unsigned char*)sysimg_data, sysimg_len)); - addComdat(new GlobalVariable(*mod, data->getType(), true, GlobalVariable::ExternalLinkage, - data, "jl_system_image_data")); + globalvars.push_back(addComdat(new GlobalVariable(*mod, data->getType(), true, + GlobalVariable::ExternalLinkage, + data, "jl_system_image_data"))); Constant *len = ConstantInt::get(T_size, sysimg_len); - addComdat(new GlobalVariable(*mod, len->getType(), true, GlobalVariable::ExternalLinkage, - len, "jl_system_image_size")); + globalvars.push_back(addComdat(new GlobalVariable(*mod, len->getType(), true, + GlobalVariable::ExternalLinkage, + len, "jl_system_image_size"))); } static int32_t jl_assign_functionID(Function *functionObject) diff --git a/src/codegen.cpp b/src/codegen.cpp index 82691b7090a08..4575080f37aa7 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -387,7 +387,8 @@ struct jl_varinfo_t { // --- helpers for reloading IR image static void jl_gen_llvm_gv_array(llvm::Module *mod, SmallVector &globalvars); -static void jl_sysimg_to_llvm(llvm::Module *mod, const char *sysimg_data, size_t sysimg_len); +static void jl_sysimg_to_llvm(llvm::Module *mod, SmallVector &globalvars, + const char *sysimg_data, size_t sysimg_len); extern "C" void jl_dump_bitcode(char *fname) @@ -489,12 +490,12 @@ void jl_dump_objfile(char *fname, int jit_model, const char *sysimg_data, size_t SmallVector globalvars; #ifdef USE_MCJIT if (sysimg_data) - jl_sysimg_to_llvm(shadow_module, sysimg_data, sysimg_len); + jl_sysimg_to_llvm(shadow_module, globalvars, sysimg_data, sysimg_len); jl_gen_llvm_gv_array(shadow_module, globalvars); PM.run(*shadow_module); #else if (sysimg_data) - jl_sysimg_to_llvm(jl_Module, sysimg_data, sysimg_len); + jl_sysimg_to_llvm(jl_Module, globalvars, sysimg_data, sysimg_len); jl_gen_llvm_gv_array(jl_Module, globalvars); PM.run(*jl_Module); #endif From 4d9bc85f585ae01ecb469571e0adc9db87d7c9a2 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 26 May 2015 15:13:04 -0400 Subject: [PATCH 109/181] avoid forming Tuple{Union(), ...}, which was confusing codegen. see comment in #11100 ideally, any Tuple containing Union() should collapse to Union(), but I will just put a bandaid on this for now. --- base/inference.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 32575669c9f40..437d664a2c647 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -619,10 +619,12 @@ function abstract_call_gf(f, fargs, argtype, e) return getfield_tfunc(fargs, argtypes[1], argtypes[2])[1] elseif istopfunction(tm, f, :next) isa(e,Expr) && (e.head = :call1) - return Tuple{getfield_tfunc(fargs, argtypes[1], argtypes[2])[1], Int} + t1 = getfield_tfunc(fargs, argtypes[1], argtypes[2])[1] + return t1===Bottom ? Bottom : Tuple{t1, Int} elseif istopfunction(tm, f, :indexed_next) isa(e,Expr) && (e.head = :call1) - return Tuple{getfield_tfunc(fargs, argtypes[1], argtypes[2])[1], Int} + t1 = getfield_tfunc(fargs, argtypes[1], argtypes[2])[1] + return t1===Bottom ? Bottom : Tuple{t1, Int} end end if istopfunction(tm, f, :promote_type) || istopfunction(tm, f, :typejoin) From ca18d28e3e4d095f6a0fb3aa2989a207a67aad0a Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Tue, 26 May 2015 15:51:36 -0400 Subject: [PATCH 110/181] Chenge vecLib to Accelerate [ci skip] --- deps/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/Makefile b/deps/Makefile index 5a8862b1f3c2f..b40ea304c9011 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -1128,7 +1128,7 @@ endif libgfortblas.$(SHLIB_EXT): gfortblas.c gfortblas.alias $(CC) -Wall -O3 $(CPPFLAGS) $(CFLAGS) $(fPIC) -shared $< -o $@ -pipe \ - -Wl,-reexport_framework,vecLib -Wl,-alias_list,gfortblas.alias + -Wl,-reexport_framework,Accelerate -Wl,-alias_list,gfortblas.alias $(build_shlibdir)/libgfortblas.$(SHLIB_EXT): libgfortblas.$(SHLIB_EXT) cp -f $< $@ $(INSTALL_NAME_CMD)libgfortblas.$(SHLIB_EXT) $@ From 539db71f12bdea11146de6365bd5fe822e3fcb41 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 26 May 2015 16:07:41 -0400 Subject: [PATCH 111/181] support all pointer arrays in jl_f_apply, not just Vector{Any} --- src/array.c | 2 +- src/builtins.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/array.c b/src/array.c index c9ceff2797aa5..350cfd76085c0 100644 --- a/src/array.c +++ b/src/array.c @@ -425,9 +425,9 @@ JL_CALLABLE(jl_f_arraysize) jl_value_t *jl_arrayref(jl_array_t *a, size_t i) { assert(i < jl_array_len(a)); - jl_value_t *el_type = (jl_value_t*)jl_tparam0(jl_typeof(a)); jl_value_t *elt; if (!a->ptrarray) { + jl_value_t *el_type = (jl_value_t*)jl_tparam0(jl_typeof(a)); elt = jl_new_bits(el_type, &((char*)a->data)[i*a->elsize]); } else { diff --git a/src/builtins.c b/src/builtins.c index aaec4de02fa66..a59376e728ebe 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -421,7 +421,7 @@ JL_CALLABLE(jl_f_apply) else if (jl_is_tuple(args[i])) { n += jl_nfields(args[i]); } - else if (jl_typeis(args[i], jl_array_any_type)) { + else if (jl_is_array(args[i]) && ((jl_array_t*)args[i])->ptrarray) { n += jl_array_len(args[i]); } else { From 91eb633a16466009a8caf9cb04da50eede72ff92 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 18 May 2015 21:33:01 -0400 Subject: [PATCH 112/181] Allow interpolation in using and export statement. Fix #11332 --- src/julia-parser.scm | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 197699b379887..08c23232dff0f 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -70,6 +70,11 @@ (define syntactic-op? (Set syntactic-operators)) (define syntactic-unary-op? (Set syntactic-unary-operators)) +(define (symbol-or-interpolate? ex) + (or (symbol? ex) + (and (pair? ex) + (eq? '$ (car ex))))) + (define trans-op (string->symbol ".'")) (define ctrans-op (string->symbol "'")) (define vararg-op (string->symbol "...")) @@ -1245,8 +1250,8 @@ body)))) ((export) (let ((es (map macrocall-to-atsym - (parse-comma-separated s parse-atom)))) - (if (not (every symbol? es)) + (parse-comma-separated s parse-unary-prefix)))) + (if (not (every symbol-or-interpolate? es)) (error "invalid \"export\" statement")) `(export ,@es))) ((import using importall) @@ -1327,17 +1332,17 @@ (begin (take-token s) (loop (list* '|.| '|.| '|.| '|.| l) (peek-token s)))) (else - (cons (macrocall-to-atsym (parse-atom s)) l))))) + (cons (macrocall-to-atsym (parse-unary-prefix s)) l))))) (define (parse-import s word) (let loop ((path (parse-import-dots s))) - (if (not (symbol? (car path))) + (if (not (symbol-or-interpolate? (car path))) (error (string "invalid \"" word "\" statement: expected identifier"))) (let ((nxt (peek-token s))) (cond ((eq? nxt '|.|) (take-token s) - (loop (cons (macrocall-to-atsym (parse-atom s)) path))) + (loop (cons (macrocall-to-atsym (parse-unary-prefix s)) path))) ((or (memv nxt '(#\newline #\; #\, :)) (eof-object? nxt)) `(,word ,@(reverse path))) From 1415d5fc50c6966834b91234d552959280c0d946 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 18 May 2015 21:47:55 -0400 Subject: [PATCH 113/181] Add test for parsing using/export with interpolation. --- test/parser.jl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/parser.jl b/test/parser.jl index 9ff3626e1632b..1bc6595937d61 100644 --- a/test/parser.jl +++ b/test/parser.jl @@ -109,3 +109,14 @@ macro test999_str(args...); args; end Expr(:toplevel, Expr(:import, :A, :b), Expr(:import, :A, :c, :d))) + +# issue #11332 +@test parse("export \$(symbol(\"A\"))") == :(export $(Expr(:$, :(symbol("A"))))) +@test parse("export \$A") == :(export $(Expr(:$, :A))) +@test parse("using \$a.\$b") == Expr(:using, Expr(:$, :a), Expr(:$, :b)) +@test parse("using \$a.\$b, \$c") == Expr(:toplevel, Expr(:using, Expr(:$, :a), + Expr(:$, :b)), + Expr(:using, Expr(:$, :c))) +@test parse("using \$a: \$b, \$c.\$d") == + Expr(:toplevel, Expr(:using, Expr(:$, :a), Expr(:$, :b)), + Expr(:using, Expr(:$, :a), Expr(:$, :c), Expr(:$, :d))) From 3316f8f6be3b170f3bc56ecb158c21ed22deea62 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 21 Apr 2015 22:33:51 -0700 Subject: [PATCH 114/181] Explicit casts for MSVC Cast to (char*) for MSVC --- src/builtins.c | 2 +- src/dump.c | 6 +++--- src/gc.c | 2 +- src/jl_uv.c | 2 +- ui/repl.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/builtins.c b/src/builtins.c index a59376e728ebe..cbf85182e9866 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -620,7 +620,7 @@ JL_CALLABLE(jl_f_tuple) if (nargs == 0) return (jl_value_t*)jl_emptytuple; jl_datatype_t *tt; if (nargs < jl_page_size/sizeof(jl_value_t*)) { - jl_value_t **types = alloca(nargs*sizeof(jl_value_t*)); + jl_value_t **types = (jl_value_t**)alloca(nargs*sizeof(jl_value_t*)); for(i=0; i < nargs; i++) types[i] = jl_typeof(args[i]); tt = jl_inst_concrete_tupletype_v(types, nargs); diff --git a/src/dump.c b/src/dump.c index ed7cd90d6dba2..618b59a4c9f5c 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1611,7 +1611,7 @@ void jl_restore_system_image_from_stream(ios_t *f) DLLEXPORT void jl_restore_system_image(const char *fname) { - char *dot = strrchr(fname, '.'); + char *dot = (char*) strrchr(fname, '.'); int is_ji = (dot && !strcmp(dot, ".ji")); jl_load_sysimg_so(); @@ -1886,8 +1886,8 @@ jl_module_t *jl_restore_new_module(const char *fname) jl_methtable_t *mt = (jl_methtable_t*)methtable_list.items[i]; jl_array_t *cache_targ = mt->cache_targ; jl_array_t *cache_arg1 = mt->cache_arg1; - mt->cache_targ = (void*)jl_nothing; - mt->cache_arg1 = (void*)jl_nothing; + mt->cache_targ = (jl_array_t*)jl_nothing; + mt->cache_arg1 = (jl_array_t*)jl_nothing; if (cache_targ != (void*)jl_nothing) { size_t j, l = jl_array_len(cache_targ); for (j = 0; j < l; j++) { diff --git a/src/gc.c b/src/gc.c index 20f62f3808bf6..3481650dd159d 100644 --- a/src/gc.c +++ b/src/gc.c @@ -280,7 +280,7 @@ static region_t *find_region(void *ptr) static gcpage_t *page_metadata(void *data) { region_t *r = find_region(data); - int pg_idx = PAGE_INDEX(r, data); + int pg_idx = PAGE_INDEX(r, (char*)data); return &r->meta[pg_idx]; } diff --git a/src/jl_uv.c b/src/jl_uv.c index ef60e3a830a9b..59883f32e0d52 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -193,7 +193,7 @@ DLLEXPORT void jl_uv_alloc_buf(uv_handle_t *handle, size_t suggested_size, uv_bu JL_GC_PUSH1(&ret); // TODO: jl_fieldref allocates boxes here. should avoid that. assert(jl_is_tuple(ret) && jl_nfields(ret)==2 && jl_is_pointer(jl_fieldref(ret,0))); - buf->base = jl_unbox_voidpointer(jl_fieldref(ret,0)); + buf->base = (char*)jl_unbox_voidpointer(jl_fieldref(ret,0)); #ifdef _P64 assert(jl_is_uint64(jl_fieldref(ret,1))); buf->len = jl_unbox_uint64(jl_fieldref(ret,1)); diff --git a/ui/repl.c b/ui/repl.c index 4b01348a06825..61ece9b3022f4 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -447,7 +447,7 @@ static int true_main(int argc, char *argv[]) ios_puts("\njulia> ", ios_stdout); ios_flush(ios_stdout); line = ios_readline(ios_stdin); - jl_value_t *val = jl_eval_string(line); + jl_value_t *val = (jl_value_t*)jl_eval_string(line); if (jl_exception_occurred()) { jl_printf(JL_STDERR, "error during run:\n"); jl_static_show(JL_STDERR, jl_exception_in_transit); From f9cd8d7da048893b2cd36b5356cb93894a2936d0 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sat, 25 Apr 2015 00:16:43 -0700 Subject: [PATCH 115/181] MSVC does not understand __attribute__((aligned(GC_PAGE_SZ))) --- src/gc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gc.c b/src/gc.c index 3481650dd159d..dc0cba0e5bead 100644 --- a/src/gc.c +++ b/src/gc.c @@ -251,7 +251,11 @@ typedef struct { char pages[REGION_PG_COUNT][GC_PAGE_SZ]; // must be first, to preserve page alignment uint32_t freemap[REGION_PG_COUNT/32]; gcpage_t meta[REGION_PG_COUNT]; -} region_t __attribute__((aligned(GC_PAGE_SZ))); +} region_t +#ifndef _COMPILER_MICROSOFT_ +__attribute__((aligned(GC_PAGE_SZ))) +#endif +; static region_t *regions[REGION_COUNT] = {NULL}; // store a lower bound of the first free page in each region static int regions_lb[REGION_COUNT] = {0}; From 1bd5a89eee166274d639f718cea2c19e9e42d59a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 26 May 2015 22:36:33 -0400 Subject: [PATCH 116/181] organize command line option help --- ui/repl.c | 58 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/ui/repl.c b/ui/repl.c index 4b01348a06825..c400c3a3d8467 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -45,42 +45,54 @@ static int imagepathspecified = 0; static const char usage[] = "julia [options] [program] [args...]\n"; static const char opts[] = - " -v, --version Display version information\n" - " -h, --help Print this message\n" - " -q, --quiet Quiet startup without banner\n" - " -H, --home Set location of julia executable\n\n" + " -v, --version Display version information\n" + " -h, --help Print this message\n\n" + // startup options + " -J, --sysimage Start up with the given system image file\n" + " -H, --home Set location of julia executable\n" + " --startup-file={yes|no} Load ~/.juliarc.jl\n" + " -f, --no-startup Don't load ~/.juliarc (deprecated, use --startup-file=no)\n" + " -F Load ~/.juliarc (deprecated, use --startup-file=yes)\n\n" + + // actions " -e, --eval Evaluate \n" " -E, --print Evaluate and show \n" - " -P, --post-boot Evaluate , but don't disable interactive mode\n" - " -L, --load Load immediately on all processors\n" - " -J, --sysimage Start up with the given system image file\n" - " -C, --cpu-target Limit usage of cpu features up to \n\n" + " -P, --post-boot Evaluate , but don't disable interactive mode (deprecated, use -i -e instead)\n" + " -L, --load Load immediately on all processors\n\n" + // parallel options " -p, --procs {N|auto} Integer value N launches N additional local worker processes\n" " 'auto' launches as many workers as the number of local cores\n" " --machinefile Run processes on hosts listed in \n\n" + // interactive options " -i Interactive mode; REPL runs and isinteractive() is true\n" - " --color={yes|no} Enable or disable color text\n\n" + " -q, --quiet Quiet startup (no banner)\n" + " --color={yes|no} Enable or disable color text\n" " --history-file={yes|no} Load or save history\n" - " --no-history-file Don't load history file (deprecated, use --history-file=no)\n" - " --startup-file={yes|no} Load ~/.juliarc.jl\n" - " -f, --no-startup Don't load ~/.juliarc (deprecated, use --startup-file=no)\n" - " -F Load ~/.juliarc (deprecated, use --startup-file=yes)\n\n" + " --no-history-file Don't load history file (deprecated, use --history-file=no)\n\n" - " --compile={yes|no|all} Enable or disable compiler, or request exhaustive compilation\n\n" + // code generation options + " --compile={yes|no|all} Enable or disable compiler, or request exhaustive compilation\n" + " -C, --cpu-target Limit usage of cpu features up to \n" + " -O, --optimize Run time-intensive code optimizations\n" + " --inline={yes|no} Control whether inlining is permitted (overrides functions declared as @inline)\n" + " --check-bounds={yes|no} Emit bounds checks always or never (ignoring declarations)\n" + " --math-mode={ieee,fast} Disallow or enable unsafe floating point optimizations (overrides @fastmath declaration)\n\n" - " --code-coverage={none|user|all}, --code-coverage\n" - " Count executions of source lines (omitting setting is equivalent to 'user')\n\n" + // error and warning options + " --depwarn={yes|no} Enable or disable syntax and method deprecation warnings\n\n" + // compiler output options + " --build name Generate a system image with the given name (without extension)\n" + " --dump-bitcode={yes|no} Dump bitcode for the system image\n\n" + + // instrumentation options + " --code-coverage={none|user|all}, --code-coverage\n" + " Count executions of source lines (omitting setting is equivalent to 'user')\n" " --track-allocation={none|user|all}, --track-allocation\n" - " Count bytes allocated by each source line\n\n" - " -O, --optimize Run time-intensive code optimizations\n" - " --check-bounds={yes|no} Emit bounds checks always or never (ignoring declarations)\n" - " --dump-bitcode={yes|no} Dump bitcode for the system image (used with --build)\n" - " --depwarn={yes|no} Enable or disable syntax and method deprecation warnings\n" - " --inline={yes|no} Control whether inlining is permitted (overrides functions declared as @inline)\n"; + " Count bytes allocated by each source line\n"; void parse_opts(int *argcp, char ***argvp) { @@ -318,6 +330,8 @@ void parse_opts(int *argcp, char ***argvp) case opt_math_mode: if (!strcmp(optarg,"ieee")) jl_options.fast_math = JL_OPTIONS_FAST_MATH_OFF; + else if (!strcmp(optarg,"fast")) + jl_options.fast_math = JL_OPTIONS_FAST_MATH_ON; else if (!strcmp(optarg,"user")) jl_options.fast_math = JL_OPTIONS_FAST_MATH_DEFAULT; else From 0636aeeda3f53ede6cbb8bd567e858bc59ecb1f8 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 26 May 2015 23:03:34 -0400 Subject: [PATCH 117/181] fix #11431 jl_in_gc was always true when SIGINT was delivered at the end of the GC's sigatomic block, meaning the task-switch-in-finalizer error was always triggered during propagation of the interrupt exception. --- src/gc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gc.c b/src/gc.c index 20f62f3808bf6..4f9dcccebd261 100644 --- a/src/gc.c +++ b/src/gc.c @@ -2171,8 +2171,8 @@ void jl_gc_collect(int full) { if (!is_gc_enabled) return; if (jl_in_gc) return; - jl_in_gc = 1; JL_SIGATOMIC_BEGIN(); + jl_in_gc = 1; uint64_t t0 = jl_hrtime(); int recollect = 0; #if defined(GC_TIME) @@ -2376,8 +2376,8 @@ void jl_gc_collect(int full) #ifdef GC_FINAL_STATS max_pause = max_pause < pause ? pause : max_pause; #endif - JL_SIGATOMIC_END(); jl_in_gc = 0; + JL_SIGATOMIC_END(); #ifdef GC_TIME if (estimate_freed != SAVE2) { // this should not happen but it does From ca893e4423a59160fe03acae2c5d16ad9ff723e5 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 26 May 2015 23:16:15 -0400 Subject: [PATCH 118/181] update test of --math-mode=fast option --- test/cmdlineargs.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 79d796e1860ac..52725fe8f6e77 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -151,13 +151,13 @@ let exename = joinpath(JULIA_HOME, Base.julia_exename()) # --fast-math let JL_OPTIONS_FAST_MATH_DEFAULT = 0, + JL_OPTIONS_FAST_MATH_ON = 1, JL_OPTIONS_FAST_MATH_OFF = 2 @test parse(Int,readchomp(`$exename -E "Int(Base.JLOptions().fast_math)"`)) == JL_OPTIONS_FAST_MATH_DEFAULT @test parse(Int,readchomp(`$exename --math-mode=user -E "Int(Base.JLOptions().fast_math)"`)) == JL_OPTIONS_FAST_MATH_DEFAULT @test parse(Int,readchomp(`$exename --math-mode=ieee -E "Int(Base.JLOptions().fast_math)"`)) == JL_OPTIONS_FAST_MATH_OFF + @test parse(Int,readchomp(`$exename --math-mode=fast -E "Int(Base.JLOptions().fast_math)"`)) == JL_OPTIONS_FAST_MATH_ON end - # --math-mode takes ieee/user as argument - @test !success(`$exename --math-mode=fast`) # --worker takes default / custom as arugment (default/custom arguments tested in test/parallel.jl, test/examples.jl) @test !success(`$exename --worker=true`) From 8c0e81dbc67509b1f238854b7d968b4a639bffbd Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Tue, 26 May 2015 21:48:41 -0700 Subject: [PATCH 119/181] Add checksum note to release checklist --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 62d8c506573ce..c81dab6da8f97 100644 --- a/Makefile +++ b/Makefile @@ -112,8 +112,9 @@ release-candidate: release test @echo 5. Replace github release tarball with tarballs created from make light-source-dist and make full-source-dist @echo 6. Follow packaging instructions in DISTRIBUTING.md to create binary packages for all platforms @echo 7. Upload to AWS, update http://julialang.org/downloads and http://status.julialang.org/stable links - @echo 8. Announce on mailing lists - @echo 9. Change master to release-0.X in base/version.jl and base/version_git.sh as in 4cb1e20 + @echo 8. Update checksums on AWS for tarball and packaged binaries + @echo 9. Announce on mailing lists + @echo 10. Change master to release-0.X in base/version.jl and base/version_git.sh as in 4cb1e20 @echo $(build_docdir)/helpdb.jl: doc/helpdb.jl | $(build_docdir) From c4d37a1cdcfb6a173c75ef0c868d63b6348d7665 Mon Sep 17 00:00:00 2001 From: Jim Garrison Date: Tue, 26 May 2015 22:16:37 -0700 Subject: [PATCH 120/181] Add checksums for LLVM 3.6.1 [av skip] --- deps/checksums/cfe-3.6.1.src.tar.xz/md5 | 1 + deps/checksums/cfe-3.6.1.src.tar.xz/sha512 | 1 + deps/checksums/compiler-rt-3.6.1.src.tar.xz/md5 | 1 + deps/checksums/compiler-rt-3.6.1.src.tar.xz/sha512 | 1 + deps/checksums/llvm-3.6.1.src.tar.xz/md5 | 1 + deps/checksums/llvm-3.6.1.src.tar.xz/sha512 | 1 + 6 files changed, 6 insertions(+) create mode 100644 deps/checksums/cfe-3.6.1.src.tar.xz/md5 create mode 100644 deps/checksums/cfe-3.6.1.src.tar.xz/sha512 create mode 100644 deps/checksums/compiler-rt-3.6.1.src.tar.xz/md5 create mode 100644 deps/checksums/compiler-rt-3.6.1.src.tar.xz/sha512 create mode 100644 deps/checksums/llvm-3.6.1.src.tar.xz/md5 create mode 100644 deps/checksums/llvm-3.6.1.src.tar.xz/sha512 diff --git a/deps/checksums/cfe-3.6.1.src.tar.xz/md5 b/deps/checksums/cfe-3.6.1.src.tar.xz/md5 new file mode 100644 index 0000000000000..b69db72fcd1ee --- /dev/null +++ b/deps/checksums/cfe-3.6.1.src.tar.xz/md5 @@ -0,0 +1 @@ +9ff6811757735051f8651833b22ae014 diff --git a/deps/checksums/cfe-3.6.1.src.tar.xz/sha512 b/deps/checksums/cfe-3.6.1.src.tar.xz/sha512 new file mode 100644 index 0000000000000..d224afab17988 --- /dev/null +++ b/deps/checksums/cfe-3.6.1.src.tar.xz/sha512 @@ -0,0 +1 @@ +a96944bccfd9341be7adafdcc40367d458e85e7e74b0d2f3a7ea18edf1454d04a232c2d0003d6449c52f81d1e235b434acc1bb63eb5f7d16f8f4a43b70826743 diff --git a/deps/checksums/compiler-rt-3.6.1.src.tar.xz/md5 b/deps/checksums/compiler-rt-3.6.1.src.tar.xz/md5 new file mode 100644 index 0000000000000..ab5fe2f6d1998 --- /dev/null +++ b/deps/checksums/compiler-rt-3.6.1.src.tar.xz/md5 @@ -0,0 +1 @@ +6f204b1feb324b1672ac907b32d927c0 diff --git a/deps/checksums/compiler-rt-3.6.1.src.tar.xz/sha512 b/deps/checksums/compiler-rt-3.6.1.src.tar.xz/sha512 new file mode 100644 index 0000000000000..da7c526619e78 --- /dev/null +++ b/deps/checksums/compiler-rt-3.6.1.src.tar.xz/sha512 @@ -0,0 +1 @@ +121c048fe60bccccd4a188a18613c94e1e1d9abd8fbae6405d23418f0c9b3562fff72fe77aea9bc0f8632ec9ad89503b9c67fcab5bf378001f90ad7492a1845a diff --git a/deps/checksums/llvm-3.6.1.src.tar.xz/md5 b/deps/checksums/llvm-3.6.1.src.tar.xz/md5 new file mode 100644 index 0000000000000..1db183f9c50f6 --- /dev/null +++ b/deps/checksums/llvm-3.6.1.src.tar.xz/md5 @@ -0,0 +1 @@ +ebf9e97be405ae126e134d3a357cd58a diff --git a/deps/checksums/llvm-3.6.1.src.tar.xz/sha512 b/deps/checksums/llvm-3.6.1.src.tar.xz/sha512 new file mode 100644 index 0000000000000..76a3280267efe --- /dev/null +++ b/deps/checksums/llvm-3.6.1.src.tar.xz/sha512 @@ -0,0 +1 @@ +fa07d0fe6c527d86c0b91b1b62597f949d777e3609e4e8ca2ea5e07931e1ebc7a363273cc705cf4a13b45e7ab00716b76de26688d077c1b51341d9dd2972de3f From 9abdd9e84695a202282bfc0875d75e634b0a1081 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 26 May 2015 23:31:15 -0700 Subject: [PATCH 121/181] appveyor future-proofing for release branches [ci skip] --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 556d9b669d576..2066b61f37e24 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,7 +11,7 @@ environment: branches: only: - master - - release-0.3 + - /release-.*/ skip_commits: # Add [av skip] to commit messages for docfixes, etc to reduce load on queue From 9362047d79ec85f64cf159b3689979c81b9ab02e Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 27 May 2015 00:24:45 -0700 Subject: [PATCH 122/181] symlink throws a different error type on XP --- test/file.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/file.jl b/test/file.jl index 731f26d55c039..9f9a4223a735b 100644 --- a/test/file.jl +++ b/test/file.jl @@ -935,8 +935,12 @@ for f in (mkdir, cd, Base.FS.unlink, readlink, rm, touch, readdir, mkpath, stat, end @test_throws ArgumentError chmod("ba\0d", 0o222) @test_throws ArgumentError open("ba\0d", "w") -for f in (cp, mv, symlink) - @test_throws ArgumentError f(file, "ba\0d") +@test_throws ArgumentError cp(file, "ba\0d") +@test_throws ArgumentError mv(file, "ba\0d") +if @unix? true : (Base.windows_version() >= Base.WINDOWS_VISTA_VER) + @test_throws ArgumentError symlink(file, "ba\0d") +else + @test_throws ErrorException symlink(file, "ba\0d") end @test_throws ArgumentError download("good", "ba\0d") @test_throws ArgumentError download("ba\0d", "good") From d0b81fdb9b138868808949b793bc8494e158a3d2 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 27 May 2015 00:26:35 -0700 Subject: [PATCH 123/181] Remove sys.dll from win32 nightlies backtraces are still bad with llvm 3.3 --- Makefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Makefile b/Makefile index c81dab6da8f97..17caaac83f353 100644 --- a/Makefile +++ b/Makefile @@ -406,10 +406,8 @@ ifeq ($(JULIA_CPU_TARGET), native) endif ifeq ($(OS), WINNT) -ifeq ($(ARCH),x86_64) - # If we are running on WIN64, also delete sys.dll until we switch to llvm3.5+ + # If we are running on windows, also delete sys.dll until we switch to llvm3.5+ -rm -f $(DESTDIR)$(private_libdir)/sys.$(SHLIB_EXT) -endif [ ! -d dist-extras ] || ( cd dist-extras && \ cp 7z.exe 7z.dll libexpat-1.dll zlib1.dll libgfortran-3.dll libquadmath-0.dll libstdc++-6.dll libgcc_s_s*-1.dll libssp-0.dll $(bindir) && \ From cfbd68c81f8f7e49ec92f5775666ff5bb6b1fe76 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 27 May 2015 01:31:16 -0700 Subject: [PATCH 124/181] update busybox url [ci skip] --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 31345be2e800d..4241d9dacaec3 100644 --- a/Makefile +++ b/Makefile @@ -555,7 +555,7 @@ endif cd dist-extras && \ $(JLDOWNLOAD) http://downloads.sourceforge.net/sevenzip/7z920_extra.7z && \ $(JLDOWNLOAD) https://unsis.googlecode.com/files/nsis-2.46.5-Unicode-setup.exe && \ - $(JLDOWNLOAD) busybox.exe http://intgat.tigress.co.uk/rmy/files/busybox/busybox-w32-TIG-1778-g15efec6.exe && \ + $(JLDOWNLOAD) busybox.exe http://frippery.org/files/busybox/busybox-w32-FRP-1-g9eb16cb.exe && \ chmod a+x 7z.exe && \ chmod a+x 7z.dll && \ $(call spawn,./7z.exe) x -y -onsis nsis-2.46.5-Unicode-setup.exe && \ From dd6102847efd5b2dff9c8f7086de216a9df1cb87 Mon Sep 17 00:00:00 2001 From: Tristan Roussel Date: Sat, 23 May 2015 01:26:48 +0200 Subject: [PATCH 125/181] Fix #11356 --- base/floatfuncs.jl | 21 ++++++++++++++++++++- test/numbers.jl | 23 +++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index f7b528441f711..e2d64579f4235 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -138,7 +138,26 @@ for f in (:round, :ceil, :floor, :trunc) function ($f)(x, digits::Integer, base::Integer=10) x = float(x) og = convert(eltype(x),base)^digits - ($f)(x * og) / og + r = ($f)(x * og) / og + + if !isfinite(r) + if digits > 0 + return x + elseif x > 0 + if ceil == $f + return convert(eltype(x), Inf) + end + return zero(x) + elseif x < 0 + if floor == $f + return -convert(eltype(x), Inf) + end + return -zero(x) + else + return x + end + end + return r end end end diff --git a/test/numbers.jl b/test/numbers.jl index 3346993090d58..7e0daabd098a3 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -1833,6 +1833,29 @@ approx_eq(a, b) = approx_eq(a, b, 1e-6) @test approx_eq(ceil(-123.456,1), -123.4) @test approx_eq(floor(123.456,1), 123.4) @test approx_eq(floor(-123.456,1), -123.5) +# rounding with too much (or too few) precision +for x in (12345.6789, 0, -12345.6789) + y = float(x) + @test y == trunc(x, 1000) + @test y == round(x, 1000) + @test y == floor(x, 1000) + @test y == ceil(x, 1000) +end +x = 12345.6789 +@test 0.0 == trunc(x, -1000) +@test 0.0 == round(x, -1000) +@test 0.0 == floor(x, -1000) +@test Inf == ceil(x, -1000) +x = -12345.6789 +@test -0.0 == trunc(x, -1000) +@test -0.0 == round(x, -1000) +@test -Inf == floor(x, -1000) +@test -0.0 == ceil(x, -1000) +x = 0.0 +@test 0.0 == trunc(x, -1000) +@test 0.0 == round(x, -1000) +@test 0.0 == floor(x, -1000) +@test 0.0 == ceil(x, -1000) # rounding in other bases @test approx_eq(round(pi,2,2), 3.25) @test approx_eq(round(pi,3,2), 3.125) From 22105fbdac8cc3388c8e3e931fd18834f5bca971 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 27 May 2015 04:11:13 -0700 Subject: [PATCH 126/181] clarify cholmod integer size error message [av skip] --- base/sparse/cholmod.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index f5ea8bc6163c6..5382777a85e3b 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -115,10 +115,10 @@ function __init__() working with sparse matrix factorizations, e.g. solving systems of equations with \\. - This problem can be fixed by fixing the Julia build or by - downloading the OS X or generic Linux binary from - www.julialang.org, which ship with the correct versions - of all dependencies. + This problem can be fixed by modifying the Julia build + configuration or by downloading the OS X or generic + Linux binary from www.julialang.org, which include + the correct versions of all dependencies. """) end end From c78161d54c236264c573f7d5c2153e21f4382e7f Mon Sep 17 00:00:00 2001 From: Seth Bromberger Date: Wed, 27 May 2015 08:13:56 -0700 Subject: [PATCH 127/181] Update README.arm.md I needed to `apt-get install m4` as well. --- README.arm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.arm.md b/README.arm.md index 6f852b1e3d642..df0d5feb679d2 100644 --- a/README.arm.md +++ b/README.arm.md @@ -47,7 +47,7 @@ override USE_SYSTEM_ARPACK=1 The following command will install all the necessary libraries on Ubuntu. ```` -sudo apt-get install libblas3gf liblapack3gf libfftw3-dev libgmp3-dev libmpfr-dev libblas-dev liblapack-dev cmake gcc-4.8 g++-4.8 gfortran libgfortran3 +sudo apt-get install libblas3gf liblapack3gf libfftw3-dev libgmp3-dev libmpfr-dev libblas-dev liblapack-dev cmake gcc-4.8 g++-4.8 gfortran libgfortran3 m4 ```` # ARM specific build problems From 4c7bb25a3444a951bb4621ab004a59bdcc87110f Mon Sep 17 00:00:00 2001 From: Oscar Blumberg Date: Wed, 27 May 2015 12:54:06 -0400 Subject: [PATCH 128/181] fix gc_verify another tags-are-now-behind-objects forgotten problem. --- src/gc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gc.c b/src/gc.c index 4f9dcccebd261..e0fdfa337744a 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1961,7 +1961,7 @@ static void clear_mark(int bits) for (int i = 0; i < 2; i++) { bigval_t *v = bigs[i]; while (v != NULL) { - void* gcv = &v->data; + void* gcv = &v->header; if (!verifying) arraylist_push(&bits_save[gc_bits(gcv)], gcv); gc_bits(gcv) = bits; v = v->next; From 9bffc74b0fa6ef0a9188fab0212f25624a6b159f Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 27 May 2015 17:04:37 -0400 Subject: [PATCH 129/181] hopefully fix #11366 a method argument with type Type{Foo{T}} was incorrectly considered a leaf type in apply_type_tfunc --- base/inference.jl | 7 +++++-- src/jltypes.c | 2 +- src/julia.h | 2 +- test/core.jl | 4 ++++ 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 437d664a2c647..7c3300b610f7f 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -371,6 +371,8 @@ function extract_simple_tparam(Ai) return Bottom end +has_typevars(t::ANY) = ccall(:jl_has_typevars, Cint, (Any,), t)!=0 + # TODO: handle e.g. apply_type(T, R::Union(Type{Int32},Type{Float64})) const apply_type_tfunc = function (A, args...) if !isType(args[1]) @@ -387,8 +389,9 @@ const apply_type_tfunc = function (A, args...) for i=2:max(lA,length(args)) ai = args[i] if isType(ai) - uncertain |= (!isleaftype(ai)) - tparams = svec(tparams..., ai.parameters[1]) + aip1 = ai.parameters[1] + uncertain |= has_typevars(aip1) + tparams = svec(tparams..., aip1) else if i<=lA val = extract_simple_tparam(A[i]) diff --git a/src/jltypes.c b/src/jltypes.c index ba50f9ba5c089..106a3efff1b0c 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -136,7 +136,7 @@ static int jl_has_typevars_from(jl_value_t *v, jl_svec_t *p) return jl_has_typevars__(v, 0, p); } -int jl_has_typevars(jl_value_t *v) +DLLEXPORT int jl_has_typevars(jl_value_t *v) { if (jl_is_typevar(v)) return 1; return jl_has_typevars__(v, 0, NULL); diff --git a/src/julia.h b/src/julia.h index a8dcba4752fbb..e1b1088d1d57c 100644 --- a/src/julia.h +++ b/src/julia.h @@ -904,7 +904,7 @@ DLLEXPORT uptrint_t jl_object_id(jl_value_t *v); // type predicates and basic operations int jl_is_type(jl_value_t *v); DLLEXPORT int jl_is_leaf_type(jl_value_t *v); -int jl_has_typevars(jl_value_t *v); +DLLEXPORT int jl_has_typevars(jl_value_t *v); DLLEXPORT int jl_subtype(jl_value_t *a, jl_value_t *b, int ta); int jl_type_morespecific(jl_value_t *a, jl_value_t *b); DLLEXPORT int jl_types_equal(jl_value_t *a, jl_value_t *b); diff --git a/test/core.jl b/test/core.jl index 7f05b5ba3c2fa..2bd1a1ae0922d 100644 --- a/test/core.jl +++ b/test/core.jl @@ -2908,3 +2908,7 @@ let a = [Pair(1,2), Pair("a","b")] @test typeof(a) == Vector{Pair} @test typeof(a) <: Vector{Pair} end + +# issue #11366 +f11366{T}(x::Type{Ref{T}}) = Ref{x} +@test !isleaftype(Base.return_types(f11366, (Any,))[1]) From 556bbe3eb16d23338092bf8d5ca3a760e1c8c99f Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 27 May 2015 18:52:39 -0400 Subject: [PATCH 130/181] don't emit two copies of a definition in `@doc` this would force us to lower the same code twice, which could make loading code with documentation much slower --- base/docs.jl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/base/docs.jl b/base/docs.jl index a8c96a0cf66f5..678dd2ee1260b 100644 --- a/base/docs.jl +++ b/base/docs.jl @@ -53,16 +53,20 @@ function newmethod(funcs, f) return newmethod(applicable) end +def_dict(f) = [def => def.func for def in methods(f)] + function trackmethod(def) name = uncurly(unblock(def).args[1].args[1]) f = esc(name) quote + funcs = nothing if $(isexpr(name, Symbol)) && isdefined($(Expr(:quote, name))) && isgeneric($f) - funcs = [def => def.func for def in methods($f)] - $(esc(def)) + funcs = def_dict($f) + end + $(esc(def)) + if funcs !== nothing $f, newmethod(funcs, $f) else - $(esc(def)) $f, newmethod(methods($f)) end end From dc6b7a2f9b270125c07025e99d976d04ecb88739 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Wed, 27 May 2015 21:03:07 -0400 Subject: [PATCH 131/181] NoFramePointerElim was removed from LLVM It didn't do what it said it would anyway with MCJIT. --- src/codegen.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/codegen.cpp b/src/codegen.cpp index 4575080f37aa7..2e8f75faeb853 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5527,7 +5527,9 @@ extern "C" void jl_init_codegen(void) #if defined(JL_DEBUG_BUILD) && !defined(LLVM37) options.JITEmitDebugInfo = true; #endif +#ifndef LLVM37 options.NoFramePointerElim = true; +#endif #ifndef LLVM34 options.NoFramePointerElimNonLeaf = true; #endif From 44cc8c28d59a69aaa1943231fdd39735fbe92331 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 27 May 2015 20:24:01 -0700 Subject: [PATCH 132/181] one more dist -> binary-dist change [ci skip] --- contrib/mac/app/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/mac/app/Makefile b/contrib/mac/app/Makefile index e86200d4813c6..90ae14e829222 100644 --- a/contrib/mac/app/Makefile +++ b/contrib/mac/app/Makefile @@ -16,7 +16,7 @@ all: clean dmg dmg: make -C ../../../deps install-git - make -C ../../.. dist + make -C ../../.. binary-dist tar zxf ../../../julia-*.tar.gz mv julia-* julia -mkdir -p ./julia/libexec ./julia/share From 9f208f7efb2769a9d6a96122fee814f16919fd8e Mon Sep 17 00:00:00 2001 From: Bob Portmann Date: Wed, 27 May 2015 21:25:55 -0600 Subject: [PATCH 133/181] Correct regex captures documentation Very small change to correct that regex captures return an array instead of a tuple. Perhaps returning a tuple would be better but that is another issue. --- doc/manual/strings.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/manual/strings.rst b/doc/manual/strings.rst index 8969095c609ce..5e24be59235ee 100644 --- a/doc/manual/strings.rst +++ b/doc/manual/strings.rst @@ -640,7 +640,7 @@ which to start the search. For example: You can extract the following info from a :obj:`RegexMatch` object: - the entire substring matched: ``m.match`` -- the captured substrings as a tuple of strings: ``m.captures`` +- the captured substrings as an array of strings: ``m.captures`` - the offset at which the whole match begins: ``m.offset`` - the offsets of the captured substrings as a vector: ``m.offsets`` @@ -691,8 +691,8 @@ a string is invalid). Here's is a pair of somewhat contrived examples:: 0 2 -It is convenient to have captures returned as a tuple so that one can -use tuple destructuring syntax to bind them to local variables:: +It is convenient to have captures returned as an array so that one can +use destructuring syntax to bind them to local variables:: julia> first, second, third = m.captures; first "a" From 94d81646e95d2f563fc4fbe01c3e123f481a557f Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 27 May 2015 23:45:14 -0400 Subject: [PATCH 134/181] fix #11397 the tupocalypse broke serialization of Tuple{} --- base/serialize.jl | 6 +++--- test/serialize.jl | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/base/serialize.jl b/base/serialize.jl index 56d4f90e95124..7e84f4d1d4668 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -40,7 +40,7 @@ let i = 2 :mul_float, :unbox, :box, :eq_int, :slt_int, :sle_int, :ne_int, :arrayset, :arrayref, - :Core, :Base, svec(), :reserved16, + :Core, :Base, svec(), Tuple{}, :reserved17, :reserved18, :reserved19, :reserved20, false, true, nothing, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, @@ -555,11 +555,11 @@ function deserialize(s, ::Type{DataType}) mod = deserialize(s)::Module ty = eval(mod,name) if length(ty.parameters) == 0 - params = svec() + t = ty else params = deserialize(s) + t = ty{params...} end - t = ty{params...} if form == 0 return t end diff --git a/test/serialize.jl b/test/serialize.jl index 1091281d35553..5dd034e6efc34 100644 --- a/test/serialize.jl +++ b/test/serialize.jl @@ -62,9 +62,12 @@ create_serialization_stream() do s lt = ntuple(len, i->0x1) serialize(s, lt) + serialize(s, Tuple{}) + seek(s, 0) @test deserialize(s) === tpl @test deserialize(s) === lt + @test deserialize(s) === Tuple{} end # Symbol From 54bdb48e22787c041264eb21c4e5dac8f21f09d1 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Thu, 28 May 2015 09:36:52 -0400 Subject: [PATCH 135/181] Fix #11469. Scalar inputs to herk! should be real. --- base/linalg/blas.jl | 19 ++++++++++--------- base/linalg/matmul.jl | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/base/linalg/blas.jl b/base/linalg/blas.jl index 5419da0eaf705..c4ff0816d557d 100644 --- a/base/linalg/blas.jl +++ b/base/linalg/blas.jl @@ -687,7 +687,8 @@ function syrk(uplo::Char, trans::Char, alpha::Number, A::StridedVecOrMat) end syrk(uplo::Char, trans::Char, A::StridedVecOrMat) = syrk(uplo, trans, one(eltype(A)), A) -for (fname, elty) in ((:zherk_,:Complex128), (:cherk_,:Complex64)) +for (fname, elty, relty) in ((:zherk_, :Complex128, :Float64), + (:cherk_, :Complex64, :Float32)) @eval begin # SUBROUTINE CHERK(UPLO,TRANS,N,K,ALPHA,A,LDA,BETA,C,LDC) # * .. Scalar Arguments .. @@ -697,25 +698,25 @@ for (fname, elty) in ((:zherk_,:Complex128), (:cherk_,:Complex64)) # * .. # * .. Array Arguments .. # COMPLEX A(LDA,*),C(LDC,*) - function herk!(uplo::Char, trans::Char, alpha::($elty), A::StridedVecOrMat{$elty}, - beta::($elty), C::StridedMatrix{$elty}) + function herk!(uplo::Char, trans::Char, α::$relty, A::StridedVecOrMat{$elty}, + β::$relty, C::StridedMatrix{$elty}) n = chksquare(C) - n == size(A, trans == 'N' ? 1 : 2) || throw(DimensionMismatch("herk!")) + n == size(A, trans == 'N' ? 1 : 2) || throw(DimensionMismatch("the matrix to update has dimension $n but the implied dimension of the update is $(size(A, trans == 'N' ? 1 : 2))")) k = size(A, trans == 'N' ? 2 : 1) ccall(($(blasfunc(fname)), libblas), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, - Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, + Ptr{$relty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$relty}, Ptr{$elty}, Ptr{BlasInt}), &uplo, &trans, &n, &k, - &alpha, A, &max(1,stride(A,2)), &beta, + &α, A, &max(1,stride(A,2)), &β, C, &max(1,stride(C,2))) C end - function herk(uplo::Char, trans::Char, alpha::($elty), A::StridedVecOrMat{$elty}) + function herk(uplo::Char, trans::Char, α::$relty, A::StridedVecOrMat{$elty}) n = size(A, trans == 'N' ? 1 : 2) - herk!(uplo, trans, alpha, A, zero($elty), similar(A, $elty, (n,n))) + herk!(uplo, trans, α, A, zero($relty), similar(A, (n,n))) end - herk(uplo::Char, trans::Char, A::StridedVecOrMat{$elty}) = herk(uplo, trans, one($elty), A) + herk(uplo::Char, trans::Char, A::StridedVecOrMat{$elty}) = herk(uplo, trans, one($relty), A) end end diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index bf9134e936131..600e8002ff336 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -223,7 +223,7 @@ function syrk_wrapper!{T<:BlasFloat}(C::StridedMatrix{T}, tA::Char, A::StridedVe return generic_matmatmul!(C, tA, tAt, A, A) end -function herk_wrapper!{T<:BlasFloat}(C::StridedMatrix{T}, tA::Char, A::StridedVecOrMat{T}) +function herk_wrapper!{T<:BlasReal}(C::Union(StridedMatrix{T}, StridedMatrix{Complex{T}}), tA::Char, A::Union(StridedVecOrMat{T}, StridedVecOrMat{Complex{T}})) nC = chksquare(C) if tA == 'C' (nA, mA) = size(A,1), size(A,2) From fba1d0d07b98d0984e70709e42e0b843df293d36 Mon Sep 17 00:00:00 2001 From: fcard Date: Sun, 24 May 2015 07:33:38 -0300 Subject: [PATCH 136/181] Fixes #11393 --- base/show.jl | 22 +++++++++++++--------- test/show.jl | 20 +++++++++++++++++++- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/base/show.jl b/base/show.jl index a457d87da67c2..e0dd7df1240b8 100644 --- a/base/show.jl +++ b/base/show.jl @@ -250,10 +250,10 @@ show(io::IO, s::Symbol) = show_unquoted_quote_expr(io, s, 0, 0) typealias ExprNode Union(Expr, QuoteNode, SymbolNode, LineNumberNode, LabelNode, GotoNode, TopNode) -print (io::IO, ex::ExprNode) = (show_unquoted(io, ex); nothing) +print (io::IO, ex::ExprNode) = (show_unquoted(io, ex, 0, 0); nothing) show (io::IO, ex::ExprNode) = show_unquoted_quote_expr(io, ex, 0, 0) -show_unquoted(io::IO, ex) = show_unquoted(io, ex, 0, 0) -show_unquoted(io::IO, ex, indent::Int) = show_unquoted(io, ex, indent, 0) +show_unquoted(io::IO, ex) = show_unquoted(io, ex, 0, 1) +show_unquoted(io::IO, ex, indent::Int) = show_unquoted(io, ex, indent, 1) show_unquoted(io::IO, ex, ::Int,::Int) = show(io, ex) ## AST printing constants ## @@ -341,7 +341,7 @@ function show_block(io::IO, head, args::Vector, body, indent::Int) exs = (is_expr(body, :block) || is_expr(body, :body)) ? body.args : Any[body] for ex in exs if !is_linenumber(ex); print(io, '\n', " "^ind); end - show_unquoted(io, ex, ind) + show_unquoted(io, ex, ind, 0) end print(io, '\n', " "^indent) end @@ -355,7 +355,7 @@ function show_block(io::IO, head, arg, block, i::Int) end # show an indented list -function show_list(io::IO, items, sep, indent::Int, prec::Int=0, enclose_operators::Bool=false) +function show_list(io::IO, items, sep, indent::Int, prec::Int=1, enclose_operators::Bool=false) n = length(items) if n == 0; return end indent += indent_width @@ -370,7 +370,7 @@ function show_list(io::IO, items, sep, indent::Int, prec::Int=0, enclose_operato end end # show an indented list inside the parens (op, cl) -function show_enclosed_list(io::IO, op, items, sep, cl, indent, prec=0, encl_ops=false) +function show_enclosed_list(io::IO, op, items, sep, cl, indent, prec=1, encl_ops=false) print(io, op); show_list(io, items, sep, indent, prec, encl_ops); print(io, cl) end @@ -387,9 +387,9 @@ function show_call(io::IO, head, func, func_args, indent) end if !isempty(func_args) && isa(func_args[1], Expr) && func_args[1].head === :parameters print(io, op) - show_list(io, func_args[2:end], ',', indent, 0) + show_list(io, func_args[2:end], ',', indent) print(io, "; ") - show_list(io, func_args[1].args, ',', indent, 0) + show_list(io, func_args[1].args, ',', indent) print(io, cl) else show_enclosed_list(io, op, func_args, ",", cl, indent) @@ -610,7 +610,11 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int) show_list(io, args, ", ", indent) elseif is(head, :macrocall) && nargs >= 1 - show_list(io, args, ' ', indent) + if prec >= 1 # nested in calls + show_call(io, :call, ex.args[1], ex.args[2:end], indent) + else + show_list(io, args, ' ', indent, 1) + end elseif is(head, :typealias) && nargs == 2 print(io, "typealias ") diff --git a/test/show.jl b/test/show.jl index e02edd2cd211d..c8caa684de473 100644 --- a/test/show.jl +++ b/test/show.jl @@ -234,7 +234,25 @@ end # issue #9865 @test ismatch(r"^Set\(\[.+….+\]\)$", replstr(Set(1:100))) -# issue 11413 +# issue #11413 @test string(:(*{1,2})) == "*{1,2}" @test string(:(*{1,x})) == "*{1,x}" @test string(:(-{x})) == "-{x}" + +# issue #11393 +@test_repr "@m(x,y) + z" +@test_repr "(@m(x,y),z)" +@test_repr "[@m(x,y),z]" +@test_repr "A[@m(x,y),z]" +@test_repr "T{@m(x,y),z}" +@test_repr "@m x @n(y) z" +@test_repr "f(@m(x,y);z=@n(a))" +@test_repr "@m(x,y).z" +@test_repr "::@m(x,y)+z" +@test_repr "[@m(x) y z]" +@test_repr "[@m(x) y; z]" +@test_repr "let @m(x), y=z; end" + +@test repr(:(@m x y)) == ":(@m x y)" +@test string(:(@m x y)) == "@m x y" +@test string(:(@m x y;)) == "begin \n @m x y\nend" From eb32204fcb700ffbbba2dd279f05c0cd2be605fd Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Thu, 28 May 2015 12:59:11 -0400 Subject: [PATCH 137/181] Update blas test to new herk signature. --- test/blas.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/blas.jl b/test/blas.jl index a3539e8d3a73a..9664b9fb4f03c 100644 --- a/test/blas.jl +++ b/test/blas.jl @@ -81,7 +81,7 @@ for elty in [Float32, Float64, Complex64, Complex128] @test all(triu(BLAS.herk('U', 'C', L4)) .== triu(BLAS.gemm('T', 'N', L4, L4))) @test all(tril(BLAS.herk('L', 'C', L4)) .== tril(BLAS.gemm('T', 'N', L4, L4))) ans = similar(L4) - @test all(tril(BLAS.herk('L','C', L4)) .== tril(BLAS.herk!('L', 'C', one(elty), L4, zero(elty), ans))) + @test all(tril(BLAS.herk('L','C', L4)) .== tril(BLAS.herk!('L', 'C', real(one(elty)), L4, real(zero(elty)), ans))) @test all(Base.LinAlg.copytri!(ans, 'L') .== LinAlg.BLAS.gemm('T', 'N', L4, L4)) else @test all(triu(BLAS.syrk('U', 'N', U4)) .== triu(BLAS.gemm('N', 'T', U4, U4))) From b3544f29b91b354cdce8beee3d96a9fb5d27abce Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 28 May 2015 14:34:28 -0400 Subject: [PATCH 138/181] add --handle-signals option for disabling signal handling --- base/options.jl | 1 + src/init.c | 28 ++++++++++++++++++---------- src/julia.h | 7 ++++++- ui/repl.c | 15 +++++++++++++-- 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/base/options.jl b/base/options.jl index 3e08a5a8bda49..c4695e88b4693 100644 --- a/base/options.jl +++ b/base/options.jl @@ -29,6 +29,7 @@ immutable JLOptions fast_math::Int8 worker::Int8 bindto::Ptr{UInt8} + handle_signals::Int8 end JLOptions() = unsafe_load(cglobal(:jl_options, JLOptions)) diff --git a/src/init.c b/src/init.c index ec444bc9c1131..afaf6ca1a6069 100644 --- a/src/init.c +++ b/src/init.c @@ -113,6 +113,7 @@ jl_options_t jl_options = { 0, // quiet JL_OPTIONS_FAST_MATH_DEFAULT, 0, // worker NULL, // bindto + JL_OPTIONS_HANDLE_SIGNALS_ON, }; int jl_boot_file_loaded = 0; @@ -1090,6 +1091,22 @@ void _julia_init(JL_IMAGE_SEARCH rel) jl_current_module = jl_main_module; jl_root_task->current_module = jl_current_module; + if (jl_options.handle_signals == JL_OPTIONS_HANDLE_SIGNALS_ON) + jl_install_default_signal_handlers(); + +#ifdef JL_GC_MARKSWEEP + jl_gc_enable(); +#endif + + if (jl_options.image_file) + jl_init_restored_modules(); + + if (jl_options.handle_signals == JL_OPTIONS_HANDLE_SIGNALS_ON) + jl_install_sigint_handler(); +} + +void jl_install_default_signal_handlers(void) +{ #ifndef _OS_WINDOWS_ signal_stack = malloc(sig_stack_size); struct sigaction actf; @@ -1187,18 +1204,9 @@ void _julia_init(JL_IMAGE_SEARCH rel) } SetUnhandledExceptionFilter(exception_handler); #endif - -#ifdef JL_GC_MARKSWEEP - jl_gc_enable(); -#endif - - if (jl_options.image_file) - jl_init_restored_modules(); - - jl_install_sigint_handler(); } -DLLEXPORT void jl_install_sigint_handler() +DLLEXPORT void jl_install_sigint_handler(void) { #ifdef _OS_WINDOWS_ SetConsoleCtrlHandler((PHANDLER_ROUTINE)sigint_handler,1); diff --git a/src/julia.h b/src/julia.h index e1b1088d1d57c..1cd36e22c740c 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1327,9 +1327,10 @@ DLLEXPORT extern volatile sig_atomic_t jl_defer_signal; DLLEXPORT void jl_sigint_action(void); DLLEXPORT void restore_signals(void); -DLLEXPORT void jl_install_sigint_handler(); +DLLEXPORT void jl_install_sigint_handler(void); DLLEXPORT void jl_sigatomic_begin(void); DLLEXPORT void jl_sigatomic_end(void); +void jl_install_default_signal_handlers(void); // tasks and exceptions ------------------------------------------------------- @@ -1555,6 +1556,7 @@ typedef struct { int8_t fast_math; int8_t worker; const char *bindto; + int8_t handle_signals; } jl_options_t; extern DLLEXPORT jl_options_t jl_options; @@ -1590,6 +1592,9 @@ extern DLLEXPORT jl_options_t jl_options; #define JL_OPTIONS_FAST_MATH_OFF 2 #define JL_OPTIONS_FAST_MATH_DEFAULT 0 +#define JL_OPTIONS_HANDLE_SIGNALS_ON 1 +#define JL_OPTIONS_HANDLE_SIGNALS_OFF 0 + // Version information #include "julia_version.h" diff --git a/ui/repl.c b/ui/repl.c index 76de35d46b31b..1f26f251348f4 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -53,7 +53,8 @@ static const char opts[] = " -H, --home Set location of julia executable\n" " --startup-file={yes|no} Load ~/.juliarc.jl\n" " -f, --no-startup Don't load ~/.juliarc (deprecated, use --startup-file=no)\n" - " -F Load ~/.juliarc (deprecated, use --startup-file=yes)\n\n" + " -F Load ~/.juliarc (deprecated, use --startup-file=yes)\n" + " --handle-signals={yes|no} Enable or disable Julia's default signal handlers\n\n" // actions " -e, --eval Evaluate \n" @@ -110,7 +111,8 @@ void parse_opts(int *argcp, char ***argvp) opt_inline, opt_math_mode, opt_worker, - opt_bind_to + opt_bind_to, + opt_handle_signals }; static char* shortopts = "+vhqFfH:e:E:P:L:J:C:ip:Ob:"; static struct option longopts[] = { @@ -143,6 +145,7 @@ void parse_opts(int *argcp, char ***argvp) { "depwarn", required_argument, 0, opt_depwarn }, { "inline", required_argument, 0, opt_inline }, { "math-mode", required_argument, 0, opt_math_mode }, + { "handle-signals", required_argument, 0, opt_handle_signals }, // hidden command line options { "build", required_argument, 0, 'b' }, { "worker", no_argument, 0, opt_worker }, @@ -348,6 +351,14 @@ void parse_opts(int *argcp, char ***argvp) case opt_bind_to: jl_options.bindto = strdup(optarg); break; + case opt_handle_signals: + if (!strcmp(optarg,"yes")) + jl_options.handle_signals = JL_OPTIONS_HANDLE_SIGNALS_ON; + else if (!strcmp(optarg,"no")) + jl_options.handle_signals = JL_OPTIONS_HANDLE_SIGNALS_OFF; + else + jl_errorf("julia: invalid argument to --handle-signals (%s)\n", optarg); + break; default: jl_errorf("julia: unhandled option -- %c\n" "This is a bug, please report it.\n", c); From bb848b873d4a74769793ed5d0822f11ae2a5fd3c Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 28 May 2015 15:34:47 -0400 Subject: [PATCH 139/181] fix test for #3167 (it didn't actually test anything) --- test/core.jl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/core.jl b/test/core.jl index 2bd1a1ae0922d..1681477163c39 100644 --- a/test/core.jl +++ b/test/core.jl @@ -1172,11 +1172,12 @@ function foo(x) end return ret end -x = Array(Union(Dict{Int64,AbstractString},Array{Int64,3},Number,AbstractString,Void), 3) -x[1] = 1.0 -x[2] = 2.0 -x[3] = 3.0 -foo(x) == [1.0, 2.0, 3.0] +let x = Array(Union(Dict{Int64,AbstractString},Array{Int64,3},Number,AbstractString,Void), 3) + x[1] = 1.0 + x[2] = 2.0 + x[3] = 3.0 + @test foo(x) == [1.0, 2.0, 3.0] +end # TODO!! # issue #4115 From 8624c6b01f3691867da509fd8a88126a1419dffd Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Thu, 28 May 2015 16:00:57 -0500 Subject: [PATCH 140/181] Let Pkg.free take an iterable to free multiple packages The call to `resolve` from `Pkg.free` takes quite a long time. If one is freeing a number of packages, it's more efficient to defer the call to `resolve` until all the checkouts have been finished. This also adds a number of tests of Pkg functionality --- base/pkg.jl | 2 +- base/pkg/entry.jl | 24 ++++++++++++++++++++++++ test/pkg.jl | 19 +++++++++++++++++-- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/base/pkg.jl b/base/pkg.jl index 07c078fb0ff29..de95efe3b1681 100644 --- a/base/pkg.jl +++ b/base/pkg.jl @@ -37,7 +37,7 @@ clone(url::AbstractString, pkg::AbstractString) = cd(Entry.clone,url,pkg) checkout(pkg::AbstractString, branch::AbstractString="master"; merge::Bool=true, pull::Bool=true) = cd(Entry.checkout,pkg,branch,merge,pull) -free(pkg::AbstractString) = cd(Entry.free,pkg) +free(pkg) = cd(Entry.free,pkg) pin(pkg::AbstractString) = cd(Entry.pin,pkg) pin(pkg::AbstractString, ver::VersionNumber) = cd(Entry.pin,pkg,ver) diff --git a/base/pkg/entry.jl b/base/pkg/entry.jl index 2c9c52a52a824..0bc51cf602e03 100644 --- a/base/pkg/entry.jl +++ b/base/pkg/entry.jl @@ -217,6 +217,30 @@ function free(pkg::AbstractString) end end +function free(pkgs) + try + for pkg in pkgs + ispath(pkg,".git") || error("$pkg is not a git repo") + Read.isinstalled(pkg) || error("$pkg cannot be freed – not an installed package") + avail = Read.available(pkg) + isempty(avail) && error("$pkg cannot be freed – not a registered package") + Git.dirty(dir=pkg) && error("$pkg cannot be freed – repo is dirty") + info("Freeing $pkg") + vers = sort!(collect(keys(avail)), rev=true) + for ver in vers + sha1 = avail[ver].sha1 + Git.iscommit(sha1, dir=pkg) || continue + Git.run(`checkout -q $sha1`, dir=pkg) + break + end + isempty(Cache.prefetch(pkg, Read.url(pkg), [a.sha1 for (v,a)=avail])) && continue + error("can't find any registered versions of $pkg to checkout") + end + finally + resolve() + end +end + function pin(pkg::AbstractString, head::AbstractString) ispath(pkg,".git") || error("$pkg is not a git repo") branch = "pinned.$(head[1:8]).tmp" diff --git a/test/pkg.jl b/test/pkg.jl index 175243f1da3ab..e37016013670b 100644 --- a/test/pkg.jl +++ b/test/pkg.jl @@ -15,14 +15,29 @@ function temp_pkg_dir(fn::Function) end end -# Test adding or removing a package -#Also test for the existence of REUIRE and META_Branch +# Test basic operations: adding or removing a package, status, free +#Also test for the existence of REQUIRE and META_Branch temp_pkg_dir() do @test isfile(joinpath(Pkg.dir(),"REQUIRE")) @test isfile(joinpath(Pkg.dir(),"META_BRANCH")) @test isempty(Pkg.installed()) Pkg.add("Example") @test [keys(Pkg.installed())...] == ["Example"] + iob = IOBuffer() + Pkg.checkout("Example") + Pkg.status("Example", iob) + str = chomp(takebuf_string(iob)) + @test startswith(str, " - Example") + @test endswith(str, "master") + Pkg.free("Example") + Pkg.status("Example", iob) + str = chomp(takebuf_string(iob)) + @test endswith(str, string(Pkg.installed("Example"))) + Pkg.checkout("Example") + Pkg.free(("Example",)) + Pkg.status("Example", iob) + str = chomp(takebuf_string(iob)) + @test endswith(str, string(Pkg.installed("Example"))) Pkg.rm("Example") @test isempty(Pkg.installed()) end From f04f10d0366be7ff44d99e88ffef3eeeccda34dc Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 28 May 2015 16:19:26 +0100 Subject: [PATCH 141/181] isspace: reduce need for category_code call, and inline --- base/utf8proc.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/base/utf8proc.jl b/base/utf8proc.jl index fc60350f8545a..c75e2147c3d69 100644 --- a/base/utf8proc.jl +++ b/base/utf8proc.jl @@ -155,8 +155,9 @@ iscntrl(c::Char) = (c <= Char(0x1f) || Char(0x7f) <= c <= Char(0x9f)) ispunct(c::Char) = (UTF8PROC_CATEGORY_PC <= category_code(c) <= UTF8PROC_CATEGORY_PO) -# 0x85 is the Unicode Next Line (NEL) character -isspace(c::Char) = c == ' ' || '\t' <= c <='\r' || c == Char(0x85) || category_code(c)==UTF8PROC_CATEGORY_ZS +# \u85 is the Unicode Next Line (NEL) character +# the check for \ufffd allows for branch removal on ASCIIStrings +@inline isspace(c::Char) = c == ' ' || '\t' <= c <='\r' || c == '\u85' || '\ua0' <= c && c != '\ufffd' && category_code(c)==UTF8PROC_CATEGORY_ZS isprint(c::Char) = (UTF8PROC_CATEGORY_LU <= category_code(c) <= UTF8PROC_CATEGORY_ZS) From 62e5942c4d5b280d816e60bf364dc54284bd6e3a Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Fri, 22 May 2015 13:49:49 +0100 Subject: [PATCH 142/181] Use Ref{T} type for BLAS calls --- base/linalg/blas.jl | 254 ++++++++++++++++++++++---------------------- 1 file changed, 127 insertions(+), 127 deletions(-) diff --git a/base/linalg/blas.jl b/base/linalg/blas.jl index c4ff0816d557d..c08cad416cefa 100644 --- a/base/linalg/blas.jl +++ b/base/linalg/blas.jl @@ -70,8 +70,8 @@ for (fname, elty) in ((:dcopy_,:Float64), # SUBROUTINE DCOPY(N,DX,INCX,DY,INCY) function blascopy!(n::Integer, DX::Union(Ptr{$elty},StridedArray{$elty}), incx::Integer, DY::Union(Ptr{$elty},StridedArray{$elty}), incy::Integer) ccall(($(blasfunc(fname)), libblas), Void, - (Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), - &n, DX, &incx, DY, &incy) + (Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}), + n, DX, incx, DY, incy) DY end end @@ -86,8 +86,8 @@ for (fname, elty) in ((:dscal_,:Float64), # SUBROUTINE DSCAL(N,DA,DX,INCX) function scal!(n::Integer, DA::$elty, DX::Union(Ptr{$elty},DenseArray{$elty}), incx::Integer) ccall(($(blasfunc(fname)), libblas), Void, - (Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}), - &n, &DA, DX, &incx) + (Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, Ref{BlasInt}), + n, DA, DX, incx) DX end end @@ -106,8 +106,8 @@ for (fname, elty) in ((:ddot_,:Float64), # DOUBLE PRECISION DX(*),DY(*) function dot(n::Integer, DX::Union(Ptr{$elty},DenseArray{$elty}), incx::Integer, DY::Union(Ptr{$elty},DenseArray{$elty}), incy::Integer) ccall(($(blasfunc(fname)), libblas), $elty, - (Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), - &n, DX, &incx, DY, &incy) + (Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}), + n, DX, incx, DY, incy) end end end @@ -121,11 +121,11 @@ for (fname, elty) in ((:cblas_zdotc_sub,:Complex128), # * .. Array Arguments .. # DOUBLE PRECISION DX(*),DY(*) function dotc(n::Integer, DX::Union(Ptr{$elty},DenseArray{$elty}), incx::Integer, DY::Union(Ptr{$elty},DenseArray{$elty}), incy::Integer) - result = Array($elty, 1) + result = Ref{$elty}() ccall(($(blasfunc(fname)), libblas), Void, - (BlasInt, Ptr{$elty}, BlasInt, Ptr{$elty}, BlasInt, Ptr{$elty}), + (BlasInt, Ptr{$elty}, BlasInt, Ptr{$elty}, BlasInt, Ref{$elty}), n, DX, incx, DY, incy, result) - result[1] + result[] end end end @@ -139,11 +139,11 @@ for (fname, elty) in ((:cblas_zdotu_sub,:Complex128), # * .. Array Arguments .. # DOUBLE PRECISION DX(*),DY(*) function dotu(n::Integer, DX::Union(Ptr{$elty},DenseArray{$elty}), incx::Integer, DY::Union(Ptr{$elty},DenseArray{$elty}), incy::Integer) - result = Array($elty, 1) + result = Ref{$elty}() ccall(($(blasfunc(fname)), libblas), Void, - (BlasInt, Ptr{$elty}, BlasInt, Ptr{$elty}, BlasInt, Ptr{$elty}), + (BlasInt, Ptr{$elty}, BlasInt, Ptr{$elty}, BlasInt, Ref{$elty}), n, DX, incx, DY, incy, result) - result[1] + result[] end end end @@ -172,8 +172,8 @@ for (fname, elty, ret_type) in ((:dnrm2_,:Float64,:Float64), # SUBROUTINE DNRM2(N,X,INCX) function nrm2(n::Integer, X::Union(Ptr{$elty},DenseArray{$elty}), incx::Integer) ccall(($(blasfunc(fname)), libblas), $ret_type, - (Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), - &n, X, &incx) + (Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}), + n, X, incx) end end end @@ -189,8 +189,8 @@ for (fname, elty, ret_type) in ((:dasum_,:Float64,:Float64), # SUBROUTINE ASUM(N, X, INCX) function asum(n::Integer, X::Union(Ptr{$elty},DenseArray{$elty}), incx::Integer) ccall(($(blasfunc(fname)), libblas), $ret_type, - (Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), - &n, X, &incx) + (Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}), + n, X, incx) end end end @@ -212,8 +212,8 @@ for (fname, elty) in ((:daxpy_,:Float64), # DOUBLE PRECISION DX(*),DY(*) function axpy!(n::Integer, alpha::($elty), dx::Union(Ptr{$elty}, DenseArray{$elty}), incx::Integer, dy::Union(Ptr{$elty}, DenseArray{$elty}), incy::Integer) ccall(($(blasfunc(fname)), libblas), Void, - (Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), - &n, &alpha, dx, &incx, dy, &incy) + (Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}), + n, alpha, dx, incx, dy, incy) dy end end @@ -244,8 +244,8 @@ for (fname, elty) in ((:idamax_,:Float64), @eval begin function iamax(n::Integer, dx::Union(Ptr{$elty}, DenseArray{$elty}), incx::Integer) ccall(($(blasfunc(fname)), libblas),BlasInt, - (Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), - &n, dx, &incx) + (Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}), + n, dx, incx) end end end @@ -271,12 +271,12 @@ for (fname, elty) in ((:dgemv_,:Float64), m,n = size(A,1),size(A,2) length(X) == (trans == 'N' ? n : m) && length(Y) == (trans == 'N' ? m : n) || throw(DimensionMismatch()) ccall(($(blasfunc(fname)), libblas), Void, - (Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, - Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, - Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}), - &trans, &size(A,1), &size(A,2), &alpha, - A, &max(1,stride(A,2)), X, &stride(X,1), - &beta, Y, &stride(Y,1)) + (Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, Ref{$elty}, + Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}, + Ref{$elty}, Ptr{$elty}, Ref{BlasInt}), + trans, size(A,1), size(A,2), alpha, + A, max(1,stride(A,2)), X, stride(X,1), + beta, Y, stride(Y,1)) Y end function gemv(trans::Char, alpha::($elty), A::StridedMatrix{$elty}, X::StridedVector{$elty}) @@ -303,13 +303,13 @@ for (fname, elty) in ((:dgbmv_,:Float64), # DOUBLE PRECISION A(LDA,*),X(*),Y(*) function gbmv!(trans::Char, m::Integer, kl::Integer, ku::Integer, alpha::($elty), A::StridedMatrix{$elty}, x::StridedVector{$elty}, beta::($elty), y::StridedVector{$elty}) ccall(($(blasfunc(fname)), libblas), Void, - (Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, - Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, - Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, - Ptr{BlasInt}), - &trans, &m, &size(A,2), &kl, - &ku, &alpha, A, &max(1,stride(A,2)), - x, &stride(x,1), &beta, y, &stride(y,1)) + (Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, Ref{BlasInt}, + Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, Ref{BlasInt}, + Ptr{$elty}, Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, + Ref{BlasInt}), + trans, m, size(A,2), kl, + ku, alpha, A, max(1,stride(A,2)), + x, stride(x,1), beta, y, stride(y,1)) y end function gbmv(trans::Char, m::Integer, kl::Integer, ku::Integer, alpha::($elty), A::StridedMatrix{$elty}, x::StridedVector{$elty}) @@ -342,12 +342,12 @@ for (fname, elty) in ((:dsymv_,:Float64), if m != n throw(DimensionMismatch("Matrix A is $m by $n but must be square")) end if m != length(x) || m != length(y) throw(DimensionMismatch()) end ccall(($(blasfunc(fname)), libblas), Void, - (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, - Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, - Ptr{$elty}, Ptr{BlasInt}), - &uplo, &n, &alpha, A, - &max(1,stride(A,2)), x, &stride(x,1), &beta, - y, &stride(y,1)) + (Ref{UInt8}, Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, + Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}, Ref{$elty}, + Ptr{$elty}, Ref{BlasInt}), + uplo, n, alpha, A, + max(1,stride(A,2)), x, stride(x,1), beta, + y, stride(y,1)) y end function symv(uplo::Char, alpha::($elty), A::StridedMatrix{$elty}, x::StridedVector{$elty}) @@ -371,12 +371,12 @@ for (fname, elty) in ((:zhemv_,:Complex128), incx = stride(x, 1) incy = stride(y, 1) ccall(($(blasfunc(fname)), libblas), Void, - (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, - Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, - Ptr{$elty}, Ptr{BlasInt}), - &uplo, &n, &α, A, - &lda, x, &incx, &β, - y, &incy) + (Ref{UInt8}, Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, + Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}, Ref{$elty}, + Ptr{$elty}, Ref{BlasInt}), + uplo, n, α, A, + lda, x, incx, β, + y, incy) y end function hemv(uplo::Char, α::($elty), A::StridedMatrix{$elty}, x::StridedVector{$elty}) @@ -403,12 +403,12 @@ for (fname, elty) in ((:dsbmv_,:Float64), # DOUBLE PRECISION A(LDA,*),X(*),Y(*) function sbmv!(uplo::Char, k::Integer, alpha::($elty), A::StridedMatrix{$elty}, x::StridedVector{$elty}, beta::($elty), y::StridedVector{$elty}) ccall(($(blasfunc(fname)), libblas), Void, - (Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, - Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, - Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}), - &uplo, &size(A,2), &k, &alpha, - A, &max(1,stride(A,2)), x, &stride(x,1), - &beta, y, &stride(y,1)) + (Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, Ref{$elty}, + Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}, + Ref{$elty}, Ptr{$elty}, Ref{BlasInt}), + uplo, size(A,2), k, alpha, + A, max(1,stride(A,2)), x, stride(x,1), + beta, y, stride(y,1)) y end function sbmv(uplo::Char, k::Integer, alpha::($elty), A::StridedMatrix{$elty}, x::StridedVector{$elty}) @@ -439,10 +439,10 @@ for (fname, elty) in ((:dtrmv_,:Float64), throw(DimensionMismatch("length(x)=$(length(x))does not match size(A)=$(size(A))")) end ccall(($(blasfunc(fname)), libblas), Void, - (Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, - Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), - &uplo, &trans, &diag, &n, - A, &max(1,stride(A,2)), x, &max(1,stride(x, 1))) + (Ref{UInt8}, Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, + Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}), + uplo, trans, diag, n, + A, max(1,stride(A,2)), x, max(1,stride(x, 1))) x end function trmv(uplo::Char, trans::Char, diag::Char, A::StridedMatrix{$elty}, x::StridedVector{$elty}) @@ -466,10 +466,10 @@ for (fname, elty) in ((:dtrsv_,:Float64), n = chksquare(A) n==length(x) || throw(DimensionMismatch("size of A is $n != length(x) = $(length(x))")) ccall(($(blasfunc(fname)), libblas), Void, - (Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, - Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), - &uplo, &trans, &diag, &n, - A, &max(1,stride(A,2)), x, &1) + (Ref{UInt8}, Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, + Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}), + uplo, trans, diag, n, + A, max(1,stride(A,2)), x, 1) x end function trsv(uplo::Char, trans::Char, diag::Char, A::StridedMatrix{$elty}, x::StridedVector{$elty}) @@ -489,12 +489,12 @@ for (fname, elty) in ((:dger_,:Float64), m == length(x) || throw(DimensionMismatch()) n == length(y) || throw(DimensionMismatch()) ccall(($(blasfunc(fname)), libblas), Void, - (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, - Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, - Ptr{BlasInt}), - &m, &n, &α, x, - &1, y, &1, A, - &max(1,stride(A,2))) + (Ref{BlasInt}, Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, + Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, + Ref{BlasInt}), + m, n, α, x, + 1, y, 1, A, + max(1,stride(A,2))) A end end @@ -510,10 +510,10 @@ for (fname, elty) in ((:dsyr_,:Float64), n = chksquare(A) length(x) == n || throw(DimensionMismatch("Length of vector must be the same as the matrix dimensions")) ccall(($(blasfunc(fname)), libblas), Void, - (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, - Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), - &uplo, &n, &α, x, - &1, A, &max(1,stride(A,2))) + (Ref{UInt8}, Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, + Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}), + uplo, n, α, x, + 1, A, max(1,stride(A,2))) A end end @@ -527,10 +527,10 @@ for (fname, elty) in ((:zher_,:Complex128), n = chksquare(A) length(x) == A || throw(DimensionMismatch("Length of vector must be the same as the matrix dimensions")) ccall(($(blasfunc(fname)), libblas), Void, - (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, - Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), - &uplo, &n, &α, x, - &1, A, &max(1,stride(A,2))) + (Ref{UInt8}, Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, + Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}), + uplo, n, α, x, + 1, A, max(1,stride(A,2))) A end end @@ -562,14 +562,14 @@ for (gemm, elty) in throw(DimensionMismatch()) end ccall(($(blasfunc(gemm)), libblas), Void, - (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, - Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, - Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, - Ptr{BlasInt}), - &transA, &transB, &m, &n, - &k, &alpha, A, &max(1,stride(A,2)), - B, &max(1,stride(B,2)), &beta, C, - &max(1,stride(C,2))) + (Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, + Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, Ref{BlasInt}, + Ptr{$elty}, Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, + Ref{BlasInt}), + transA, transB, m, n, + k, alpha, A, max(1,stride(A,2)), + B, max(1,stride(B,2)), beta, C, + max(1,stride(C,2))) C end function gemm(transA::Char, transB::Char, alpha::($elty), A::StridedMatrix{$elty}, B::StridedMatrix{$elty}) @@ -599,12 +599,12 @@ for (mfname, elty) in ((:dsymm_,:Float64), j = chksquare(A) if j != (side == 'L' ? m : n) || size(B,2) != n throw(DimensionMismatch()) end ccall(($(blasfunc(mfname)), libblas), Void, - (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, - Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, - Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}), - &side, &uplo, &m, &n, - &alpha, A, &max(1,stride(A,2)), B, - &max(1,stride(B,2)), &beta, C, &max(1,stride(C,2))) + (Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, + Ref{$elty}, Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, + Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, Ref{BlasInt}), + side, uplo, m, n, + alpha, A, max(1,stride(A,2)), B, + max(1,stride(B,2)), beta, C, max(1,stride(C,2))) C end function symm(side::Char, uplo::Char, alpha::($elty), A::StridedMatrix{$elty}, B::StridedMatrix{$elty}) @@ -632,12 +632,12 @@ for (mfname, elty) in ((:zhemm_,:Complex128), j = chksquare(A) if j != (side == 'L' ? m : n) || size(B,2) != n throw(DimensionMismatch()) end ccall(($(blasfunc(mfname)), libblas), Void, - (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, - Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, - Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}), - &side, &uplo, &m, &n, - &alpha, A, &max(1,stride(A,2)), B, - &max(1,stride(B,2)), &beta, C, &max(1,stride(C,2))) + (Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, + Ref{$elty}, Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, + Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, Ref{BlasInt}), + side, uplo, m, n, + alpha, A, max(1,stride(A,2)), B, + max(1,stride(B,2)), beta, C, max(1,stride(C,2))) C end function hemm(side::Char, uplo::Char, alpha::($elty), A::StridedMatrix{$elty}, B::StridedMatrix{$elty}) @@ -670,12 +670,12 @@ for (fname, elty) in ((:dsyrk_,:Float64), if nn != n throw(DimensionMismatch("syrk!")) end k = size(A, trans == 'N' ? 2 : 1) ccall(($(blasfunc(fname)), libblas), Void, - (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, - Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, - Ptr{$elty}, Ptr{BlasInt}), - &uplo, &trans, &n, &k, - &alpha, A, &max(1,stride(A,2)), &beta, - C, &max(1,stride(C,2))) + (Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, + Ref{$elty}, Ptr{$elty}, Ref{BlasInt}, Ref{$elty}, + Ptr{$elty}, Ref{BlasInt}), + uplo, trans, n, k, + alpha, A, max(1,stride(A,2)), beta, + C, max(1,stride(C,2))) C end end @@ -704,12 +704,12 @@ for (fname, elty, relty) in ((:zherk_, :Complex128, :Float64), n == size(A, trans == 'N' ? 1 : 2) || throw(DimensionMismatch("the matrix to update has dimension $n but the implied dimension of the update is $(size(A, trans == 'N' ? 1 : 2))")) k = size(A, trans == 'N' ? 2 : 1) ccall(($(blasfunc(fname)), libblas), Void, - (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, - Ptr{$relty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$relty}, - Ptr{$elty}, Ptr{BlasInt}), - &uplo, &trans, &n, &k, - &α, A, &max(1,stride(A,2)), &β, - C, &max(1,stride(C,2))) + (Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, + Ref{$elty}, Ptr{$elty}, Ref{BlasInt}, Ref{$elty}, + Ptr{$elty}, Ref{BlasInt}), + uplo, trans, n, k, + α, A, max(1,stride(A,2)), β, + C, max(1,stride(C,2))) C end function herk(uplo::Char, trans::Char, α::$relty, A::StridedVecOrMat{$elty}) @@ -743,12 +743,12 @@ for (fname, elty) in ((:dsyr2k_,:Float64), if nn != n throw(DimensionMismatch("syr2k!")) end k = size(A, trans == 'N' ? 2 : 1) ccall(($(blasfunc(fname)), libblas), Void, - (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, - Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, - Ptr{$elty}, Ptr{BlasInt}), - &uplo, &trans, &n, &k, - &alpha, A, &max(1,stride(A,2)), B, &max(1,stride(B,2)), &beta, - C, &max(1,stride(C,2))) + (Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, + Ref{$elty}, Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}, Ref{$elty}, + Ptr{$elty}, Ref{BlasInt}), + uplo, trans, n, k, + alpha, A, max(1,stride(A,2)), B, max(1,stride(B,2)), beta, + C, max(1,stride(C,2))) C end end @@ -779,12 +779,12 @@ for (fname, elty1, elty2) in ((:zher2k_,:Complex128,:Float64), (:cher2k_,:Comple n == size(A, trans == 'N' ? 1 : 2) || throw(DimensionMismatch("her2k!")) k = size(A, trans == 'N' ? 2 : 1) ccall(($(blasfunc(fname)), libblas), Void, - (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, - Ptr{$elty1}, Ptr{$elty1}, Ptr{BlasInt}, Ptr{$elty1}, Ptr{BlasInt}, - Ptr{$elty2}, Ptr{$elty1}, Ptr{BlasInt}), - &uplo, &trans, &n, &k, - &alpha, A, &max(1,stride(A,2)), B, &max(1,stride(B,2)), - &beta, C, &max(1,stride(C,2))) + (Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, + Ref{$elty1}, Ptr{$elty1}, Ref{BlasInt}, Ptr{$elty1}, Ref{BlasInt}, + Ref{$elty2}, Ptr{$elty1}, Ref{BlasInt}), + uplo, trans, n, k, + alpha, A, max(1,stride(A,2)), B, max(1,stride(B,2)), + beta, C, max(1,stride(C,2))) C end function her2k(uplo::Char, trans::Char, alpha::($elty1), A::StridedVecOrMat{$elty1}, B::StridedVecOrMat{$elty1}) @@ -815,10 +815,10 @@ for (mmname, smname, elty) in nA = chksquare(A) if nA != (side == 'L' ? m : n) throw(DimensionMismatch("trmm!")) end ccall(($(blasfunc(mmname)), libblas), Void, - (Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, - Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), - &side, &uplo, &transa, &diag, &m, &n, - &alpha, A, &max(1,stride(A,2)), B, &max(1,stride(B,2))) + (Ref{UInt8}, Ref{UInt8}, Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, + Ref{$elty}, Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}), + side, uplo, transa, diag, m, n, + alpha, A, max(1,stride(A,2)), B, max(1,stride(B,2))) B end function trmm(side::Char, uplo::Char, transa::Char, diag::Char, @@ -838,12 +838,12 @@ for (mmname, smname, elty) in k = chksquare(A) k==(side == 'L' ? m : n) || throw(DimensionMismatch("size of A is $n, size(B)=($m,$n) and transa='$transa'")) ccall(($(blasfunc(smname)), libblas), Void, - (Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, - Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, - Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), - &side, &uplo, &transa, &diag, - &m, &n, &alpha, A, - &max(1,stride(A,2)), B, &max(1,stride(B,2))) + (Ref{UInt8}, Ref{UInt8}, Ref{UInt8}, Ref{UInt8}, + Ref{BlasInt}, Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, + Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}), + side, uplo, transa, diag, + m, n, alpha, A, + max(1,stride(A,2)), B, max(1,stride(B,2))) B end function trsm(side::Char, uplo::Char, transa::Char, diag::Char, alpha::$elty, A::StridedMatrix{$elty}, B::StridedMatrix{$elty}) From 10476055a548a1da109c1c6c837328830f69bdde Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 28 May 2015 17:31:15 -0400 Subject: [PATCH 143/181] fix #9799, module init order - still wait until outermost module finishes loading before running initializers, but run them innermost-first - allow a non-Main module to be the "outermost" module --- src/toplevel.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/toplevel.c b/src/toplevel.c index 0dbda6a304f4d..07c8d460b6853 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -93,6 +93,7 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) { static arraylist_t module_stack; static int initialized=0; + static jl_module_t *outermost = NULL; if (!initialized) { arraylist_new(&module_stack, 0); initialized = 1; @@ -145,6 +146,10 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) JL_GC_PUSH1(&last_module); jl_module_t *task_last_m = jl_current_task->current_module; jl_current_task->current_module = jl_current_module = newm; + jl_module_t *prev_outermost = outermost; + size_t stackidx = module_stack.len; + if (outermost == NULL) + outermost = newm; jl_array_t *exprs = ((jl_expr_t*)jl_exprarg(ex, 2))->args; JL_TRY { @@ -157,11 +162,14 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) JL_CATCH { jl_current_module = last_module; jl_current_task->current_module = task_last_m; + outermost = prev_outermost; + module_stack.len = stackidx; jl_rethrow(); } JL_GC_POP(); jl_current_module = last_module; jl_current_task->current_module = task_last_m; + outermost = prev_outermost; #if 0 // some optional post-processing steps @@ -185,10 +193,13 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) arraylist_push(&module_stack, newm); - if (jl_current_module == jl_main_module) { - while (module_stack.len > 0) { - jl_module_load_time_initialize((jl_module_t *) arraylist_pop(&module_stack)); + if (outermost == NULL || jl_current_module == jl_main_module) { + size_t i, l=module_stack.len; + for(i = stackidx; i < l; i++) { + jl_module_load_time_initialize((jl_module_t*)module_stack.items[i]); } + assert(module_stack.len == l); + module_stack.len = stackidx; } return jl_nothing; From ec37d6d197f82fb91db2c9235f05bd0854520490 Mon Sep 17 00:00:00 2001 From: Jake Bolewski Date: Thu, 28 May 2015 18:22:31 -0400 Subject: [PATCH 144/181] fix old style vcat warning --- base/abstractarray.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 50d4d25dfdfe9..bf18b1daac852 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -16,16 +16,16 @@ const _oldstyle_array_vcat_ = true if _oldstyle_array_vcat_ function oldstyle_vcat_warning(n::Int) if n == 1 - before = "a" + before = "[a]" after = "collect(a)" elseif n == 2 - before = "a,b" - after = "a;b" + before = "[a,b]" + after = "[a;b]" else - before = "a,b,..." - after = "a;b;..." + before = "[a,b,...]" + after = "[a;b;...]" end - depwarn("[$before] concatenation is deprecated; use [$after] instead", :vect) + depwarn("$before concatenation is deprecated; use $after instead", :vect) end function vect(A::AbstractArray...) oldstyle_vcat_warning(length(A)) From 3872dd632a2ce6285fd914808ea5aceab869c085 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Thu, 28 May 2015 17:27:52 -0500 Subject: [PATCH 145/181] Add help documentation on new Pkg.free [ci skip] --- doc/helpdb.jl | 145 +++++++++++++++++++++++++++++++-------------- doc/stdlib/pkg.rst | 4 +- 2 files changed, 103 insertions(+), 46 deletions(-) diff --git a/doc/helpdb.jl b/doc/helpdb.jl index 30f27d5671728..85d13f3623efe 100644 --- a/doc/helpdb.jl +++ b/doc/helpdb.jl @@ -1904,7 +1904,7 @@ Any[ julia> @enum FRUIT apple=1 orange=2 kiwi=3 - julia> f(x::FRUIT) = \"I'm a FRUIT with value: \$(int(x))\" + julia> f(x::FRUIT) = \"I'm a FRUIT with value: \$(Int(x))\" f (generic function with 1 method) julia> f(apple) @@ -2299,8 +2299,25 @@ Any[ ("Base","@time","@time() A macro to execute an expression, printing the time it took to - execute and the total number of bytes its execution caused to be - allocated, before returning the value of the expression. + execute, the number of allocations, and the total number of bytes + its execution caused to be allocated, before returning the value of + the expression. + +"), + +("Base","@timev","@timev() + + This is a verbose version of the \"@time\" macro, it first prints + the same information as \"@time\", then any non-zero memory + allocation counters, and then returns the value of the expression. + +"), + +("Base","@timed","@timed() + + A macro to execute an expression, and return the value of the + expression, elapsed time, total bytes allocated, garbage collection + time, and an object with various memory allocation counters. "), @@ -2316,7 +2333,12 @@ Any[ A macro to evaluate an expression, discarding the resulting value, instead returning the total number of bytes allocated during - evaluation of the expression. + evaluation of the expression. Note: the expression is evaluated + inside a local function, instead of the current context, in order + to eliminate the effects of compilation, however, there still may + be some allocations due to JIT compilation. This also makes the + results inconsistent with the \"@time\" macros, which do not try to + adjust for the effects of compilation. "), @@ -5261,10 +5283,10 @@ Millisecond(v) "), -("Base","mv","mv(src::AbstractString,dst::AbstractString; remove_destination::Bool=false) +("Base","mv","mv(src::AbstractString, dst::AbstractString; remove_destination::Bool=false) Move the file, link, or directory from *src* to *dest*. - \"remove_destination=true\" will first remove an existing `dst`. + \"remove_destination=true\" will first remove an existing *dst*. "), @@ -5295,16 +5317,18 @@ Millisecond(v) "), -("Base","mktemp","mktemp() +("Base","mktemp","mktemp([parent=tempdir()]) Returns \"(path, io)\", where \"path\" is the path of a new - temporary file and \"io\" is an open file object for this path. + temporary file in \"parent\" and \"io\" is an open file object for + this path. "), -("Base","mktempdir","mktempdir() +("Base","mktempdir","mktempdir([parent=tempdir()]) - Create a temporary directory and return its path. + Create a temporary directory in the \"parent\" directory and return + its path. "), @@ -5355,6 +5379,12 @@ Millisecond(v) "), +("Base","ismount","ismount(path) -> Bool + + Returns \"true\" if \"path\" is a mount point, \"false\" otherwise. + +"), + ("Base","ispath","ispath(path) -> Bool Returns \"true\" if \"path\" is a valid filesystem path, \"false\" @@ -6199,8 +6229,8 @@ base64encode(args...) ("Base","base64decode","base64decode(string) - Decodes the base64-encoded \"string\" and returns the obtained - bytes. + Decodes the base64-encoded \"string\" and returns a + \"Vector{UInt8}\" of the decoded bytes. "), @@ -6901,6 +6931,15 @@ popdisplay(d::Display) "), +("Base","vecdot","vecdot(x, y) + + For any iterable containers \"x\" and \"y\" (including arrays of + any dimension) of numbers (or any element type for which \"dot\" is + defined), compute the Euclidean dot product (the sum of + \"dot(x[i],y[i])\") as if they were vectors. + +"), + ("Base","cross","cross(x, y) ×(x, y) @@ -7715,8 +7754,9 @@ popdisplay(d::Display) ("Base","vecnorm","vecnorm(A[, p]) For any iterable container \"A\" (including arrays of any - dimension) of numbers, compute the \"p\"-norm (defaulting to - \"p=2\") as if \"A\" were a vector of the corresponding length. + dimension) of numbers (or any element type for which \"norm\" is + defined), compute the \"p\"-norm (defaulting to \"p=2\") as if + \"A\" were a vector of the corresponding length. For example, if \"A\" is a matrix and \"p=2\", then this is equivalent to the Frobenius norm. @@ -11539,8 +11579,8 @@ golden ("Base","@task","@task() - Wrap an expression in a Task executing it, and return the Task. - This only creates a task, and does not run it. + Wrap an expression in a Task without executing it, and return the + Task. This only creates a task, and does not run it. "), @@ -12143,6 +12183,10 @@ golden versions after. This is an inverse for both \"Pkg.checkout\" and \"Pkg.pin\". + You can also supply an iterable collection of package names, e.g., + \"Pkg.free((\"Pkg1\", \"Pkg2\"))\" to free multiple packages at + once. + "), ("Base.Pkg","build","build() @@ -12508,12 +12552,30 @@ golden "), +("Base","ascii","ascii(::Ptr{UInt8}[, length]) + + Create an ASCII string from the address of a C (0-terminated) + string encoded in ASCII. A copy is made; the ptr can be safely + freed. If \"length\" is specified, the string does not have to be + 0-terminated. + +"), + ("Base","utf8","utf8(::Array{UInt8, 1}) Create a UTF-8 string from a byte array. "), +("Base","utf8","utf8(::Ptr{UInt8}[, length]) + + Create a UTF-8 string from the address of a C (0-terminated) string + encoded in UTF-8. A copy is made; the ptr can be safely freed. If + \"length\" is specified, the string does not have to be + 0-terminated. + +"), + ("Base","utf8","utf8(s) Convert a string to a contiguous UTF-8 string (all characters must @@ -12584,24 +12646,24 @@ golden "), -("Base","is_valid_ascii","is_valid_ascii(s) -> Bool +("Base","isvalid","isvalid(value) -> Bool - Returns true if the argument (\"ASCIIString\", \"UTF8String\", or - byte vector) is valid ASCII, false otherwise. + Returns true if the given value is valid for its type, which + currently can be one of \"Char\", \"ASCIIString\", \"UTF8String\", + \"UTF16String\", or \"UTF32String\" "), -("Base","is_valid_utf8","is_valid_utf8(s) -> Bool +("Base","isvalid","isvalid(T, value) -> Bool - Returns true if the argument (\"ASCIIString\", \"UTF8String\", or - byte vector) is valid UTF-8, false otherwise. - -"), - -("Base","is_valid_char","is_valid_char(c) -> Bool - - Returns true if the given char or integer is a valid Unicode code - point. + Returns true if the given value is valid for that type. Types + currently can be \"Char\", \"ASCIIString\", \"UTF8String\", + \"UTF16String\", or \"UTF32String\" Values for \"Char\" can be of + type \"Char\" or \"UInt32\" Values for \"ASCIIString\" and + \"UTF8String\" can be of that type, or \"Vector{UInt8}\" Values for + \"UTF16String\" can be \"UTF16String\" or \"Vector{UInt16}\" Values + for \"UTF32String\" can be \"UTF32String\", \"Vector{Char}\" or + \"Vector{UInt32}\" "), @@ -13038,30 +13100,23 @@ golden "), -("Base","is_valid_utf16","is_valid_utf16(s) -> Bool - - Returns true if the argument (\"UTF16String\" or \"UInt16\" array) - is valid UTF-16. - -"), - ("Base","utf32","utf32(s) - Create a UTF-32 string from a byte array, array of \"UInt32\", or - any other string type. (Conversions of byte arrays check for a - byte-order marker in the first four bytes, and do not include it in - the resulting string.) + Create a UTF-32 string from a byte array, array of \"Char\" or + \"UInt32\", or any other string type. (Conversions of byte arrays + check for a byte-order marker in the first four bytes, and do not + include it in the resulting string.) Note that the resulting \"UTF32String\" data is terminated by the NUL codepoint (32-bit zero), which is not treated as a character in the string (so that it is mostly invisible in Julia); this allows the string to be passed directly to external functions requiring NUL-terminated data. This NUL is appended automatically by the - *utf32(s)* conversion function. If you have a \"UInt32\" array - \"A\" that is already NUL-terminated UTF-32 data, then you can - instead use *UTF32String(A)`* to construct the string without - making a copy of the data and treating the NUL as a terminator - rather than as part of the string. + *utf32(s)* conversion function. If you have a \"Char\" or + \"UInt32\" array \"A\" that is already NUL-terminated UTF-32 data, + then you can instead use *UTF32String(A)`* to construct the string + without making a copy of the data and treating the NUL as a + terminator rather than as part of the string. "), diff --git a/doc/stdlib/pkg.rst b/doc/stdlib/pkg.rst index cb3eea98567f0..585ff66ec8796 100644 --- a/doc/stdlib/pkg.rst +++ b/doc/stdlib/pkg.rst @@ -105,6 +105,9 @@ to use them, you'll need to prefix each function call with an explicit ``Pkg.``, It calls ``Pkg.resolve()`` to determine optimal package versions after. This is an inverse for both ``Pkg.checkout`` and ``Pkg.pin``. + You can also supply an iterable collection of package names, e.g., + ``Pkg.free(("Pkg1", "Pkg2"))`` to free multiple packages at once. + .. function:: build() Run the build scripts for all installed packages in depth-first recursive order. @@ -142,4 +145,3 @@ to use them, you'll need to prefix each function call with an explicit ``Pkg.``, .. function:: test(pkgs...) Run the tests for each package in ``pkgs`` ensuring that each package's test dependencies are installed for the duration of the test. A package is tested by running its ``test/runtests.jl`` file and test dependencies are specified in ``test/REQUIRE``. - From ff4706b1886becb374963f979a35c5187935c053 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sun, 4 Jan 2015 01:45:44 -0500 Subject: [PATCH 146/181] add a `dirty` flag to Dict makes `get!` work with default functions that modify the dict. fixes #9573 --- base/dict.jl | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/base/dict.jl b/base/dict.jl index 6fa9413fd175e..5da52114251d4 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -359,10 +359,11 @@ type Dict{K,V} <: Associative{K,V} vals::Array{V,1} ndel::Int count::Int + dirty::Bool function Dict() n = 16 - new(zeros(UInt8,n), Array(K,n), Array(V,n), 0, 0) + new(zeros(UInt8,n), Array(K,n), Array(V,n), 0, 0, false) end function Dict(kv) h = Dict{K,V}() @@ -446,6 +447,7 @@ function rehash!{K,V}(h::Dict{K,V}, newsz = length(h.keys)) oldv = h.vals sz = length(olds) newsz = _tablesz(newsz) + h.dirty = true if h.count == 0 resize!(h.slots, newsz) fill!(h.slots, 0) @@ -512,6 +514,7 @@ function empty!{K,V}(h::Dict{K,V}) resize!(h.vals, sz) h.ndel = 0 h.count = 0 + h.dirty = true return h end @@ -583,6 +586,7 @@ function _setindex!(h::Dict, v, key, index) h.keys[index] = key h.vals[index] = v h.count += 1 + h.dirty = true sz = length(h.keys) # Rehash now if necessary @@ -636,8 +640,17 @@ function get!{K,V}(default::Callable, h::Dict{K,V}, key0) index > 0 && return h.vals[index] + h.dirty = false v = convert(V, default()) - _setindex!(h, v, key, -index) + if h.dirty + index = ht_keyindex2(h, key) + end + if index > 0 + h.keys[index] = key + h.vals[index] = v + else + _setindex!(h, v, key, -index) + end return v end @@ -708,6 +721,7 @@ function _delete!(h::Dict, index) ccall(:jl_arrayunset, Void, (Any, UInt), h.vals, index-1) h.ndel += 1 h.count -= 1 + h.dirty = true h end From bcb0530935bda01f2222c0aa2766818b8ba2228a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 28 May 2015 22:21:52 -0400 Subject: [PATCH 147/181] add test for the dict dirty flag (thanks @garrison) --- test/dict.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/dict.jl b/test/dict.jl index b57d504a42126..53e39b8870638 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -325,3 +325,11 @@ let Base.showdict(IOBuffer(), a) Base.showdict(IOBuffer(), a; limit=true) end + +# Issue #7944 +let d = Dict{Int,Int}() + get!(d, 0) do + d[0] = 1 + end + @test length(d) == 1 +end From faa5263e15786c42ef2b71d0350d2d48cf4cad6d Mon Sep 17 00:00:00 2001 From: Jake Bolewski Date: Fri, 1 May 2015 10:51:33 -0400 Subject: [PATCH 148/181] Improve serialization performance by using a vector of obj ptrs with linear search Tag lookups for serailization have been replaced by linear search with a vector of object pointers instead of using an ObjectIdDict. Lookups that are constant are now computed at compile time. Deserialization tag lookup is now just a direct index. This change maintains backwards compatibility. --- base/serialize.jl | 256 ++++++++++++++++++++++++-------------------- base/sharedarray.jl | 3 +- 2 files changed, 141 insertions(+), 118 deletions(-) diff --git a/base/serialize.jl b/base/serialize.jl index 7e84f4d1d4668..ef6868cd89061 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -14,73 +14,98 @@ abstract LongTuple abstract LongExpr abstract UndefRefTag +const TAGS = Any[ + Symbol, Int8, UInt8, Int16, UInt16, Int32, UInt32, + Int64, UInt64, Int128, UInt128, Float32, Float64, Char, Ptr, + DataType, UnionType, Function, + Tuple, Array, Expr, LongSymbol, LongTuple, LongExpr, + LineNumberNode, SymbolNode, LabelNode, GotoNode, + QuoteNode, TopNode, TypeVar, Box, LambdaStaticData, + Module, UndefRefTag, Task, ASCIIString, UTF8String, + UTF16String, UTF32String, Float16, + SimpleVector, :reserved10, :reserved11, :reserved12, + + (), Bool, Any, :Any, Bottom, :reserved21, :reserved22, Type, + :Array, :TypeVar, :Box, + :lambda, :body, :return, :call, symbol("::"), + :(=), :null, :gotoifnot, :A, :B, :C, :M, :N, :T, :S, :X, :Y, + :a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k, :l, :m, :n, :o, + :p, :q, :r, :s, :t, :u, :v, :w, :x, :y, :z, + :add_int, :sub_int, :mul_int, :add_float, :sub_float, + :mul_float, :unbox, :box, + :eq_int, :slt_int, :sle_int, :ne_int, + :arrayset, :arrayref, + :Core, :Base, svec(), Tuple{}, + :reserved17, :reserved18, :reserved19, :reserved20, + false, true, nothing, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32 +] + const ser_version = 2 # do not make changes without bumping the version #! -const ser_tag = ObjectIdDict() -const deser_tag = ObjectIdDict() +const SER_TAG = ObjectIdDict() +const DESER_TAG = ObjectIdDict() let i = 2 - global ser_tag, deser_tag - for t = Any[ - Symbol, Int8, UInt8, Int16, UInt16, Int32, UInt32, - Int64, UInt64, Int128, UInt128, Float32, Float64, Char, Ptr, - DataType, UnionType, Function, - Tuple, Array, Expr, LongSymbol, LongTuple, LongExpr, - LineNumberNode, SymbolNode, LabelNode, GotoNode, - QuoteNode, TopNode, TypeVar, Box, LambdaStaticData, - Module, UndefRefTag, Task, ASCIIString, UTF8String, - UTF16String, UTF32String, Float16, - SimpleVector, :reserved10, :reserved11, :reserved12, - - (), Bool, Any, :Any, Bottom, :reserved21, :reserved22, Type, - :Array, :TypeVar, :Box, - :lambda, :body, :return, :call, symbol("::"), - :(=), :null, :gotoifnot, :A, :B, :C, :M, :N, :T, :S, :X, :Y, - :a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k, :l, :m, :n, :o, - :p, :q, :r, :s, :t, :u, :v, :w, :x, :y, :z, - :add_int, :sub_int, :mul_int, :add_float, :sub_float, - :mul_float, :unbox, :box, - :eq_int, :slt_int, :sle_int, :ne_int, - :arrayset, :arrayref, - :Core, :Base, svec(), Tuple{}, - :reserved17, :reserved18, :reserved19, :reserved20, - false, true, nothing, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32] - ser_tag[t] = Int32(i) - deser_tag[Int32(i)] = t + for t = TAGS + SER_TAG[t] = Int32(i) + DESER_TAG[Int32(i)] = t i += 1 end end -# tags >= this just represent themselves, their whole representation is 1 byte -const VALUE_TAGS = ser_tag[()] - -const EMPTY_TUPLE_TAG = ser_tag[()] -const ZERO_TAG = ser_tag[0] -const INT_TAG = ser_tag[Int] +const NTAGS = length(TAGS) +const TAG_PTRS = Array(Ptr{Void}, NTAGS) -writetag(s, x) = write(s, UInt8(ser_tag[x])) +function sertag(v::ANY) + idx = 2 + ptr = pointer_from_objref(v) + @inbounds @simd for i = 1:NTAGS + ptr == TAG_PTRS[i] && return Int32(idx) + idx += 1 + end + return Int32(-1) +end +desertag(i::Int32) = TAGS[i-1] -function write_as_tag(s, x) - t = ser_tag[x] - if t < VALUE_TAGS - write(s, UInt8(0)) +function __init__() + for i in 1:NTAGS + TAG_PTRS[i] = pointer_from_objref(TAGS[i]) end - write(s, UInt8(t)) end -serialize(s, x::Bool) = write_as_tag(s, x) +function test_roundtrip(obj) + io = IOBuffer() + serialize(io, obj) + seekstart(io) + dobj = deserialize(io) + return dobj == obj, dobj +end + +# tags >= this just represent themselves, their whole representation is 1 byte +const VALUE_TAGS = SER_TAG[()] +const ZERO_TAG = SER_TAG[0] + +writetag(s, tag) = write(s, UInt8(tag)) + +function write_as_tag(s, tag) + tag < VALUE_TAGS && write(s, UInt8(0)) + write(s, UInt8(tag)) +end + +@eval serialize(s, x::Bool) = x ? writetag(s, $(SER_TAG[true])) : + writetag(s, $(SER_TAG[false])) serialize(s, ::Ptr) = error("cannot serialize a pointer") -serialize(s, ::Tuple{}) = write(s, UInt8(EMPTY_TUPLE_TAG)) # write_as_tag(s, ()) +@eval serialize(s, ::Tuple{}) = writetag(s, $(SER_TAG[()])) -function serialize(s, t::Tuple) +@eval function serialize(s, t::Tuple) l = length(t) if l <= 255 - writetag(s, Tuple) + writetag(s, $(SER_TAG[Tuple])) write(s, UInt8(l)) else - writetag(s, LongTuple) + writetag(s, $(SER_TAG[LongTuple])) write(s, Int32(l)) end for i = 1:l @@ -88,25 +113,26 @@ function serialize(s, t::Tuple) end end -function serialize(s, v::SimpleVector) - writetag(s, SimpleVector) +@eval function serialize(s, v::SimpleVector) + writetag(s, $(SER_TAG[SimpleVector])) write(s, Int32(length(v))) for i = 1:length(v) serialize(s, v[i]) end end -function serialize(s, x::Symbol) - if haskey(ser_tag, x) - return write_as_tag(s, x) +@eval function serialize(s, x::Symbol) + tag = sertag(x) + if tag > 0 + return write_as_tag(s, tag) end pname = unsafe_convert(Ptr{UInt8}, x) ln = Int(ccall(:strlen, Csize_t, (Ptr{UInt8},), pname)) if ln <= 255 - writetag(s, Symbol) + writetag(s, $(SER_TAG[Symbol])) write(s, UInt8(ln)) else - writetag(s, LongSymbol) + writetag(s, $(SER_TAG[LongSymbol])) write(s, Int32(ln)) end write(s, pname, ln) @@ -132,8 +158,8 @@ function serialize_array_data(s, a) end end -function serialize(s, a::Array) - writetag(s, Array) +@eval function serialize(s, a::Array) + writetag(s, $(SER_TAG[Array])) elty = eltype(a) if elty !== UInt8 serialize(s, elty) @@ -150,17 +176,17 @@ function serialize(s, a::Array) if isdefined(a, i) serialize(s, a[i]) else - writetag(s, UndefRefTag) + writetag(s, $(SER_TAG[UndefRefTag])) end end end end -function serialize{T,N,A<:Array}(s, a::SubArray{T,N,A}) +@eval function serialize{T,N,A<:Array}(s, a::SubArray{T,N,A}) if !isbits(T) || stride(a,1)!=1 return serialize(s, copy(a)) end - writetag(s, Array) + writetag(s, $(SER_TAG[Array])) serialize(s, T) serialize(s, size(a)) serialize_array_data(s, a) @@ -173,34 +199,33 @@ end # Don't serialize the pointers function serialize(s, r::Regex) - Serializer.serialize_type(s, typeof(r)) + serialize_type(s, typeof(r)) serialize(s, r.pattern) serialize(s, r.options) end function serialize(s, n::BigInt) - Serializer.serialize_type(s, BigInt) + serialize_type(s, BigInt) serialize(s, base(62,n)) end - function serialize(s, n::BigFloat) - Serializer.serialize_type(s, BigFloat) + serialize_type(s, BigFloat) serialize(s, string(n)) end -function serialize(s, e::Expr) - l = length(e.args) +@eval function serialize(s, ex::Expr) + l = length(ex.args) if l <= 255 - writetag(s, Expr) + writetag(s, $(SER_TAG[Expr])) write(s, UInt8(l)) else - writetag(s, LongExpr) + writetag(s, $(SER_TAG[LongExpr])) write(s, Int32(l)) end - serialize(s, e.head) - serialize(s, e.typ) - for a = e.args + serialize(s, ex.head) + serialize(s, ex.typ) + for a = ex.args serialize(s, a) end end @@ -214,7 +239,6 @@ function serialize(s, t::Dict) end end - function serialize_mod_names(s, m::Module) p = module_parent(m) if m !== p @@ -223,15 +247,14 @@ function serialize_mod_names(s, m::Module) end end -function serialize(s, m::Module) - writetag(s, Module) +@eval function serialize(s, m::Module) + writetag(s, $(SER_TAG[Module])) serialize_mod_names(s, m) - serialize(s, ()) - nothing + writetag(s, $(SER_TAG[()])) end -function serialize(s, f::Function) - writetag(s, Function) +@eval function serialize(s, f::Function) + writetag(s, $(SER_TAG[Function])) name = false if isgeneric(f) name = f.env.name @@ -239,7 +262,7 @@ function serialize(s, f::Function) name = f.env end if isa(name,Symbol) - if isdefined(Base,name) && is(f,eval(Base,name)) + if isdefined(Base,name) && is(f,getfield(Base,name)) write(s, UInt8(0)) serialize(s, name) return @@ -251,7 +274,7 @@ function serialize(s, f::Function) mod = f.env.defs.func.code.module end if mod !== () - if isdefined(mod,name) && is(f,eval(mod,name)) + if isdefined(mod,name) && is(f,getfield(mod,name)) # toplevel named func write(s, UInt8(2)) serialize(s, mod) @@ -285,8 +308,8 @@ function lambda_number(l::LambdaStaticData) return ln end -function serialize(s, linfo::LambdaStaticData) - writetag(s, LambdaStaticData) +@eval function serialize(s, linfo::LambdaStaticData) + writetag(s, $(SER_TAG[LambdaStaticData])) serialize(s, lambda_number(linfo)) serialize(s, uncompressed_ast(linfo)) if isdefined(linfo.def, :roots) @@ -304,11 +327,11 @@ function serialize(s, linfo::LambdaStaticData) end end -function serialize(s, t::Task) +@eval function serialize(s, t::Task) if istaskstarted(t) && !istaskdone(t) error("cannot serialize a running Task") end - writetag(s, Task) + writetag(s, $(SER_TAG[Task])) serialize(s, t.code) serialize(s, t.storage) serialize(s, t.state == :queued || t.state == :waiting ? (:runnable) : t.state) @@ -322,7 +345,7 @@ function serialize_type_data(s, t) mod = t.name.module serialize(s, mod) if length(t.parameters) > 0 - if isdefined(mod,tname) && is(t,eval(mod,tname)) + if isdefined(mod,tname) && is(t,getfield(mod,tname)) serialize(s, svec()) else serialize(s, t.parameters) @@ -330,39 +353,39 @@ function serialize_type_data(s, t) end end -function serialize(s, t::DataType) - if haskey(ser_tag,t) - write_as_tag(s, t) - else - writetag(s, DataType) - write(s, UInt8(0)) - serialize_type_data(s, t) +@eval function serialize(s, t::DataType) + tag = sertag(t) + if tag > 0 + return write_as_tag(s, tag) end + writetag(s, $(SER_TAG[DataType])) + write(s, UInt8(0)) + serialize_type_data(s, t) end -function serialize_type(s, t::DataType) - if haskey(ser_tag,t) - writetag(s, t) - else - writetag(s, DataType) - write(s, UInt8(1)) - serialize_type_data(s, t) +@eval function serialize_type(s, t::DataType) + tag = sertag(t) + if tag > 0 + return writetag(s, tag) end + writetag(s, $(SER_TAG[DataType])) + write(s, UInt8(1)) + serialize_type_data(s, t) end -function serialize(s, n::Int) +@eval function serialize(s, n::Int) if 0 <= n <= 32 write(s, UInt8(ZERO_TAG+n)) return end - write(s, UInt8(INT_TAG)) + writetag(s, $(SER_TAG[Int])) write(s, n) - nothing end -function serialize(s, x) - if haskey(ser_tag,x) - return write_as_tag(s, x) +@eval function serialize(s, x) + tag = sertag(x) + if tag > 0 + return write_as_tag(s, tag) end t = typeof(x) nf = nfields(t) @@ -374,7 +397,7 @@ function serialize(s, x) if isdefined(x, i) serialize(s, getfield(x, i)) else - writetag(s, UndefRefTag) + writetag(s, $(SER_TAG[UndefRefTag])) end end end @@ -382,15 +405,14 @@ end ## deserializing values ## -function deserialize(s) +deserialize(s) = handle_deserialize(s, Int32(read(s, UInt8))) -end function handle_deserialize(s, b) if b == 0 - return deser_tag[Int32(read(s, UInt8))] + return desertag(Int32(read(s, UInt8))) end - tag = deser_tag[b] + tag = desertag(b) if b >= VALUE_TAGS return tag elseif is(tag,Tuple) @@ -422,7 +444,7 @@ function deserialize(s, ::Type{Module}) if !isdefined(m,mname) warn("Module $mname not defined on process $(myid())") # an error seemingly fails end - m = eval(m,mname)::Module + m = getfield(m,mname)::Module end else mname = path @@ -430,7 +452,7 @@ function deserialize(s, ::Type{Module}) if !isdefined(m,mname) warn("Module $mname not defined on process $(myid())") # an error seemingly fails end - m = eval(m,mname)::Module + m = getfield(m,mname)::Module mname = deserialize(s) end end @@ -446,14 +468,14 @@ function deserialize(s, ::Type{Function}) if !isdefined(Base,name) return (args...)->error("function $name not defined on process $(myid())") end - return eval(Base,name)::Function + return getfield(Base,name)::Function elseif b==2 mod = deserialize(s)::Module name = deserialize(s)::Symbol if !isdefined(mod,name) return (args...)->error("function $name not defined on process $(myid())") end - return eval(mod,name)::Function + return getfield(mod,name)::Function elseif b==3 env = deserialize(s) return ccall(:jl_new_gf_internal, Any, (Any,), env)::Function @@ -525,7 +547,7 @@ function deserialize(s, ::Type{Array}) A = Array(elty, dims) for i = 1:length(A) tag = Int32(read(s, UInt8)) - if tag==0 || !is(deser_tag[tag], UndefRefTag) + if tag==0 || !is(desertag(tag), UndefRefTag) A[i] = handle_deserialize(s, tag) end end @@ -553,7 +575,7 @@ function deserialize(s, ::Type{DataType}) form = read(s, UInt8) name = deserialize(s)::Symbol mod = deserialize(s)::Module - ty = eval(mod,name) + ty = getfield(mod,name) if length(ty.parameters) == 0 t = ty else @@ -606,7 +628,7 @@ function deserialize(s, t::DataType) x = ccall(:jl_new_struct_uninit, Any, (Any,), t) for i in 1:nf tag = Int32(read(s, UInt8)) - if tag==0 || !is(deser_tag[tag], UndefRefTag) + if tag==0 || !is(desertag(tag), UndefRefTag) ccall(:jl_set_nth_field, Void, (Any, Csize_t, Any), x, i-1, handle_deserialize(s, tag)) end end diff --git a/base/sharedarray.jl b/base/sharedarray.jl index b4bf2c8405bf6..679ee29b3fe16 100644 --- a/base/sharedarray.jl +++ b/base/sharedarray.jl @@ -193,7 +193,8 @@ function serialize(s, S::SharedArray) Serializer.serialize_type(s, typeof(S)) for n in SharedArray.name.names if n in [:s, :pidx, :loc_subarr_1d] - Serializer.writetag(s, Serializer.UndefRefTag) + Serializer.writetag(s, + Serializer.sertag(Serializer.UndefRefTag)) else serialize(s, getfield(S, n)) end From 06f15bbd1275a68fd1e9d695cf8a6576d533d5c8 Mon Sep 17 00:00:00 2001 From: Jake Bolewski Date: Mon, 4 May 2015 14:41:23 -0400 Subject: [PATCH 149/181] update tests --- test/remote.jl | 6 +++--- test/serialize.jl | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/test/remote.jl b/test/remote.jl index 0dab126c666a7..b359b611c2663 100644 --- a/test/remote.jl +++ b/test/remote.jl @@ -1,9 +1,9 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license # Check that serializer hasn't gone out-of-frame -@test Serializer.ser_tag[Symbol] == 2 -@test Serializer.ser_tag[()] == 47 -@test Serializer.ser_tag[false] == 123 +@test Serializer.sertag(Symbol) == 2 +@test Serializer.sertag(()) == 47 +@test Serializer.sertag(false) == 123 # issue #1770 let diff --git a/test/serialize.jl b/test/serialize.jl index 5dd034e6efc34..18731fb6ddc0f 100644 --- a/test/serialize.jl +++ b/test/serialize.jl @@ -10,20 +10,20 @@ end # Tags create_serialization_stream() do s - Serializer.writetag(s, Bool) - @test takebuf_array(s)[end] == UInt8(Serializer.ser_tag[Bool]) + Serializer.writetag(s, Serializer.sertag(Bool)) + @test takebuf_array(s)[end] == UInt8(Serializer.sertag(Bool)) end create_serialization_stream() do s - Serializer.write_as_tag(s, Bool) - @test takebuf_array(s)[end] == UInt8(Serializer.ser_tag[Bool]) + Serializer.write_as_tag(s, Serializer.sertag(Bool)) + @test takebuf_array(s)[end] == UInt8(Serializer.sertag(Bool)) end create_serialization_stream() do s - Serializer.write_as_tag(s, Symbol) + Serializer.write_as_tag(s, Serializer.sertag(Symbol)) data = takebuf_array(s) @test data[end-1] == 0x00 - @test data[end] == UInt8(Serializer.ser_tag[Symbol]) + @test data[end] == UInt8(Serializer.sertag(Symbol)) end # Boolean & Empty & Nothing From f02c932fd8fed73cdfc7dd0b7fbb28e2c3b2d010 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 28 May 2015 22:43:39 -0400 Subject: [PATCH 150/181] avoid eval and extra pointer array in serializer code tighten up sertag code a bit --- base/serialize.jl | 112 +++++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/base/serialize.jl b/base/serialize.jl index ef6868cd89061..5e53bab755b83 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -44,46 +44,46 @@ const TAGS = Any[ const ser_version = 2 # do not make changes without bumping the version #! const SER_TAG = ObjectIdDict() -const DESER_TAG = ObjectIdDict() let i = 2 for t = TAGS SER_TAG[t] = Int32(i) - DESER_TAG[Int32(i)] = t i += 1 end end const NTAGS = length(TAGS) -const TAG_PTRS = Array(Ptr{Void}, NTAGS) function sertag(v::ANY) - idx = 2 ptr = pointer_from_objref(v) + ptags = convert(Ptr{Ptr{Void}}, pointer(TAGS)) @inbounds @simd for i = 1:NTAGS - ptr == TAG_PTRS[i] && return Int32(idx) - idx += 1 + ptr == unsafe_load(ptags,i) && return (i+1)%Int32 end return Int32(-1) end desertag(i::Int32) = TAGS[i-1] -function __init__() - for i in 1:NTAGS - TAG_PTRS[i] = pointer_from_objref(TAGS[i]) - end -end - -function test_roundtrip(obj) - io = IOBuffer() - serialize(io, obj) - seekstart(io) - dobj = deserialize(io) - return dobj == obj, dobj -end - # tags >= this just represent themselves, their whole representation is 1 byte const VALUE_TAGS = SER_TAG[()] const ZERO_TAG = SER_TAG[0] +const TRUE_TAG = SER_TAG[true] +const FALSE_TAG = SER_TAG[false] +const EMPTYTUPLE_TAG = SER_TAG[()] +const TUPLE_TAG = SER_TAG[Tuple] +const LONGTUPLE_TAG = SER_TAG[LongTuple] +const SIMPLEVECTOR_TAG = SER_TAG[SimpleVector] +const SYMBOL_TAG = SER_TAG[Symbol] +const LONGSYMBOL_TAG = SER_TAG[LongSymbol] +const ARRAY_TAG = SER_TAG[Array] +const UNDEFREF_TAG = SER_TAG[UndefRefTag] +const EXPR_TAG = SER_TAG[Expr] +const LONGEXPR_TAG = SER_TAG[LongExpr] +const MODULE_TAG = SER_TAG[Module] +const FUNCTION_TAG = SER_TAG[Function] +const LAMBDASTATICDATA_TAG = SER_TAG[LambdaStaticData] +const TASK_TAG = SER_TAG[Task] +const DATATYPE_TAG = SER_TAG[DataType] +const INT_TAG = SER_TAG[Int] writetag(s, tag) = write(s, UInt8(tag)) @@ -92,20 +92,20 @@ function write_as_tag(s, tag) write(s, UInt8(tag)) end -@eval serialize(s, x::Bool) = x ? writetag(s, $(SER_TAG[true])) : - writetag(s, $(SER_TAG[false])) +serialize(s, x::Bool) = x ? writetag(s, TRUE_TAG) : + writetag(s, FALSE_TAG) serialize(s, ::Ptr) = error("cannot serialize a pointer") -@eval serialize(s, ::Tuple{}) = writetag(s, $(SER_TAG[()])) +serialize(s, ::Tuple{}) = writetag(s, EMPTYTUPLE_TAG) -@eval function serialize(s, t::Tuple) +function serialize(s, t::Tuple) l = length(t) if l <= 255 - writetag(s, $(SER_TAG[Tuple])) + writetag(s, TUPLE_TAG) write(s, UInt8(l)) else - writetag(s, $(SER_TAG[LongTuple])) + writetag(s, LONGTUPLE_TAG) write(s, Int32(l)) end for i = 1:l @@ -113,15 +113,15 @@ serialize(s, ::Ptr) = error("cannot serialize a pointer") end end -@eval function serialize(s, v::SimpleVector) - writetag(s, $(SER_TAG[SimpleVector])) +function serialize(s, v::SimpleVector) + writetag(s, SIMPLEVECTOR_TAG) write(s, Int32(length(v))) for i = 1:length(v) serialize(s, v[i]) end end -@eval function serialize(s, x::Symbol) +function serialize(s, x::Symbol) tag = sertag(x) if tag > 0 return write_as_tag(s, tag) @@ -129,10 +129,10 @@ end pname = unsafe_convert(Ptr{UInt8}, x) ln = Int(ccall(:strlen, Csize_t, (Ptr{UInt8},), pname)) if ln <= 255 - writetag(s, $(SER_TAG[Symbol])) + writetag(s, SYMBOL_TAG) write(s, UInt8(ln)) else - writetag(s, $(SER_TAG[LongSymbol])) + writetag(s, LONGSYMBOL_TAG) write(s, Int32(ln)) end write(s, pname, ln) @@ -158,8 +158,8 @@ function serialize_array_data(s, a) end end -@eval function serialize(s, a::Array) - writetag(s, $(SER_TAG[Array])) +function serialize(s, a::Array) + writetag(s, ARRAY_TAG) elty = eltype(a) if elty !== UInt8 serialize(s, elty) @@ -176,17 +176,17 @@ end if isdefined(a, i) serialize(s, a[i]) else - writetag(s, $(SER_TAG[UndefRefTag])) + writetag(s, UNDEFREF_TAG) end end end end -@eval function serialize{T,N,A<:Array}(s, a::SubArray{T,N,A}) +function serialize{T,N,A<:Array}(s, a::SubArray{T,N,A}) if !isbits(T) || stride(a,1)!=1 return serialize(s, copy(a)) end - writetag(s, $(SER_TAG[Array])) + writetag(s, ARRAY_TAG) serialize(s, T) serialize(s, size(a)) serialize_array_data(s, a) @@ -214,13 +214,13 @@ function serialize(s, n::BigFloat) serialize(s, string(n)) end -@eval function serialize(s, ex::Expr) +function serialize(s, ex::Expr) l = length(ex.args) if l <= 255 - writetag(s, $(SER_TAG[Expr])) + writetag(s, EXPR_TAG) write(s, UInt8(l)) else - writetag(s, $(SER_TAG[LongExpr])) + writetag(s, LONGEXPR_TAG) write(s, Int32(l)) end serialize(s, ex.head) @@ -247,14 +247,14 @@ function serialize_mod_names(s, m::Module) end end -@eval function serialize(s, m::Module) - writetag(s, $(SER_TAG[Module])) +function serialize(s, m::Module) + writetag(s, MODULE_TAG) serialize_mod_names(s, m) - writetag(s, $(SER_TAG[()])) + writetag(s, EMPTYTUPLE_TAG) end -@eval function serialize(s, f::Function) - writetag(s, $(SER_TAG[Function])) +function serialize(s, f::Function) + writetag(s, FUNCTION_TAG) name = false if isgeneric(f) name = f.env.name @@ -308,8 +308,8 @@ function lambda_number(l::LambdaStaticData) return ln end -@eval function serialize(s, linfo::LambdaStaticData) - writetag(s, $(SER_TAG[LambdaStaticData])) +function serialize(s, linfo::LambdaStaticData) + writetag(s, LAMBDASTATICDATA_TAG) serialize(s, lambda_number(linfo)) serialize(s, uncompressed_ast(linfo)) if isdefined(linfo.def, :roots) @@ -327,11 +327,11 @@ end end end -@eval function serialize(s, t::Task) +function serialize(s, t::Task) if istaskstarted(t) && !istaskdone(t) error("cannot serialize a running Task") end - writetag(s, $(SER_TAG[Task])) + writetag(s, TASK_TAG) serialize(s, t.code) serialize(s, t.storage) serialize(s, t.state == :queued || t.state == :waiting ? (:runnable) : t.state) @@ -353,36 +353,36 @@ function serialize_type_data(s, t) end end -@eval function serialize(s, t::DataType) +function serialize(s, t::DataType) tag = sertag(t) if tag > 0 return write_as_tag(s, tag) end - writetag(s, $(SER_TAG[DataType])) + writetag(s, DATATYPE_TAG) write(s, UInt8(0)) serialize_type_data(s, t) end -@eval function serialize_type(s, t::DataType) +function serialize_type(s, t::DataType) tag = sertag(t) if tag > 0 return writetag(s, tag) end - writetag(s, $(SER_TAG[DataType])) + writetag(s, DATATYPE_TAG) write(s, UInt8(1)) serialize_type_data(s, t) end -@eval function serialize(s, n::Int) +function serialize(s, n::Int) if 0 <= n <= 32 write(s, UInt8(ZERO_TAG+n)) return end - writetag(s, $(SER_TAG[Int])) + writetag(s, INT_TAG) write(s, n) end -@eval function serialize(s, x) +function serialize(s, x) tag = sertag(x) if tag > 0 return write_as_tag(s, tag) @@ -397,7 +397,7 @@ end if isdefined(x, i) serialize(s, getfield(x, i)) else - writetag(s, $(SER_TAG[UndefRefTag])) + writetag(s, UNDEFREF_TAG) end end end From ebfebfdc48919b767124a62958b9b6455552f3c9 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 29 May 2015 01:22:40 -0400 Subject: [PATCH 151/181] always re-initialize variables to undefined at the top of their scope fixes #11065 --- src/julia-syntax.scm | 39 +++++++++++++++++++++++++++++++++------ test/core.jl | 12 ++++++++++++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index e72ceb05dbb67..87536bf7f69f9 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -3232,11 +3232,7 @@ So far only the second case can actually occur. (vinf (var-info-for vname vi))) (if (and vinf (not (and (pair? code) - (equal? (car code) `(newvar ,vname)))) - ;; TODO: remove the following expression to re-null - ;; all variables when they are allocated. see issue #1571 - (vinfo:capt vinf) - ) + (equal? (car code) `(newvar ,vname))))) (emit `(newvar ,vname)) #f))) ((newvar) @@ -3246,10 +3242,41 @@ So far only the second case can actually occur. #f)) (else (emit (goto-form e)))))) (compile e '()) - (cons 'body (reverse! code)))) + (let* ((stmts (reverse! code)) + (di (definitely-initialized-vars stmts vi))) + (cons 'body (filter (lambda (e) + (not (and (pair? e) (eq? (car e) 'newvar) + (has? di (cadr e))))) + stmts))))) (define to-goto-form goto-form) +;; find newvar nodes that are unnecessary because (1) the variable is not +;; captured, and (2) the variable is assigned before any branches. +;; this is used to remove newvar nodes that are not needed for re-initializing +;; variables to undefined (see issue #11065). it doesn't look for variable +;; *uses*, because any variables used-before-def that also pass this test +;; are *always* used undefined, and therefore don't need to be *re*-initialized. +(define (definitely-initialized-vars stmts vi) + (let ((vars (table)) + (di (table))) + (let loop ((stmts stmts)) + (if (null? stmts) + di + (begin + (let ((e (car stmts))) + (cond ((and (pair? e) (eq? (car e) 'newvar)) + (let ((vinf (var-info-for (cadr e) vi))) + (if (not (vinfo:capt vinf)) + (put! vars (cadr e) #t)))) + ((and (pair? e) (eq? (car e) '=)) + (if (has? vars (cadr e)) + (begin (del! vars (cadr e)) + (put! di (cadr e) #t)))) + ((and (pair? e) (memq (car e) '(goto gotoifnot))) + (set! vars (table))))) + (loop (cdr stmts))))))) + ;; macro expander (define (splice-expr? e) diff --git a/test/core.jl b/test/core.jl index 1681477163c39..f2f8f15dcf0a4 100644 --- a/test/core.jl +++ b/test/core.jl @@ -2913,3 +2913,15 @@ end # issue #11366 f11366{T}(x::Type{Ref{T}}) = Ref{x} @test !isleaftype(Base.return_types(f11366, (Any,))[1]) + +# issue #11065, #1571 +function f11065() + for i = 1:2 + if i == 1 + z = "z is defined" + elseif i == 2 + print(z) + end + end +end +@test_throws UndefVarError f11065() From 8b3ba34b5a28f168b5690a73af3c43b4ec0dcccc Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Thu, 28 May 2015 23:12:08 -0700 Subject: [PATCH 152/181] make release-candidate slightly more windows-friendly (cherry picked from commit 869a90b16e254bfd5fb2b1b111df427aee23912d) [av skip] --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 4241d9dacaec3..1754fd90d10f9 100644 --- a/Makefile +++ b/Makefile @@ -76,9 +76,9 @@ endif release-candidate: release test @#Check documentation - @./julia doc/NEWS-update.jl #Add missing cross-references to NEWS.md + @$(JULIA_EXECUTABLE) doc/NEWS-update.jl #Add missing cross-references to NEWS.md @$(MAKE) -C doc unicode #Rebuild Unicode table if necessary - @./julia doc/DocCheck.jl > doc/UNDOCUMENTED.rst 2>&1 #Check for undocumented items + @$(JULIA_EXECUTABLE) doc/DocCheck.jl > doc/UNDOCUMENTED.rst 2>&1 #Check for undocumented items @if [ -z "$(cat doc/UNDOCUMENTED.rst)" ]; then \ rm doc/UNDOCUMENTED.rst; \ else \ From a5357e9fb811486c1de1d8c25e7a503f1f517f42 Mon Sep 17 00:00:00 2001 From: ScottPJones Date: Fri, 29 May 2015 09:58:34 +0200 Subject: [PATCH 153/181] Add 2-argument isvalid(::Type{T},str::T) --- base/utf32.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/base/utf32.jl b/base/utf32.jl index b183912491de0..419e104e33dfb 100644 --- a/base/utf32.jl +++ b/base/utf32.jl @@ -92,6 +92,7 @@ function isvalid(::Type{UTF32String}, str::Union(Vector{Char}, Vector{UInt32})) end isvalid(str::Vector{Char}) = isvalid(UTF32String, str) isvalid{T<:Union(ASCIIString,UTF8String,UTF16String,UTF32String)}(str::T) = isvalid(T, str.data) +isvalid{T<:Union(ASCIIString,UTF8String,UTF16String,UTF32String)}(::Type{T}, str::T) = isvalid(T, str.data) utf32(p::Ptr{Char}, len::Integer) = utf32(pointer_to_array(p, len)) utf32(p::Union(Ptr{UInt32}, Ptr{Int32}), len::Integer) = utf32(convert(Ptr{Char}, p), len) From 527cbc82dc2cd9dbea0fe74c7a634df610a542b8 Mon Sep 17 00:00:00 2001 From: ScottPJones Date: Fri, 29 May 2015 10:25:08 +0200 Subject: [PATCH 154/181] Add unit tests --- test/strings.jl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/strings.jl b/test/strings.jl index 38793b4b74186..10c9b11fe2665 100644 --- a/test/strings.jl +++ b/test/strings.jl @@ -1433,6 +1433,24 @@ end # Check seven-byte sequences, should be invalid @test isvalid(UTF8String, UInt8[0xfe, 0x80, 0x80, 0x80, 0x80, 0x80]) == false +# 11482 + +# isvalid +let s = "abcdef", u8 = "abcdef\uff", u16 = utf16(u8), u32 = utf32(u8), + bad32 = utf32(UInt32[65,0x110000]), badch = Char[0x110000][1] + + @test !isvalid(bad32) + @test !isvalid(badch) + @test isvalid(s) + @test isvalid(u8) + @test isvalid(u16) + @test isvalid(u32) + @test isvalid(ASCIIString, s) + @test isvalid(UTF8String, u8) + @test isvalid(UTF16String, u16) + @test isvalid(UTF32String, u32) +end + # This caused JuliaLang/JSON.jl#82 @test first('\x00':'\x7f') === '\x00' @test last('\x00':'\x7f') === '\x7f' From 32e0d882c70ba3a8f19c4f751575a39cc9242296 Mon Sep 17 00:00:00 2001 From: Isaiah Norton Date: Fri, 29 May 2015 09:55:52 -0400 Subject: [PATCH 155/181] Fix #11457, LLVM37 API change --- src/codegen.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 2e8f75faeb853..76be5e0f4c551 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3226,7 +3226,11 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, builder.CreateLoad(prepare_global(jlexc_var), true)), resetstkoflw_blk, handlr); builder.SetInsertPoint(resetstkoflw_blk); - builder.CreateCall(prepare_call(resetstkoflw_func)); + builder.CreateCall(prepare_call(resetstkoflw_func) +# ifdef LLVM37 + , {} +# endif + ); builder.CreateBr(handlr); #else builder.CreateCondBr(isz, tryblk, handlr); From c7221d916f99a3477e0fc443298ebea506e47df1 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Fri, 29 May 2015 10:19:21 -0500 Subject: [PATCH 156/181] Deprecate ntuple(::Integer, ::Function) Some day we will want to duck-type the Function argument to ntuple, but we need one release cycle with a deprecation warning before we can do that. So let's do the deprecation now. --- base/abstractarray.jl | 6 +- base/array.jl | 4 +- base/base.jl | 4 - base/bitarray.jl | 12 +- base/deepcopy.jl | 2 +- base/deprecated.jl | 2 + base/essentials.jl | 4 + base/inference.jl | 2 +- base/mmap.jl | 2 +- base/multidimensional.jl | 2 +- base/serialize.jl | 2 +- base/subarray.jl | 2 +- base/tuple.jl | 3 +- doc/stdlib/base.rst | 2 +- test/arrayops.jl | 8 +- test/arrayperf.jl | 263 --------------------------------------- test/serialize.jl | 2 +- 17 files changed, 30 insertions(+), 292 deletions(-) delete mode 100644 test/arrayperf.jl diff --git a/base/abstractarray.jl b/base/abstractarray.jl index bf18b1daac852..7014523b88e9d 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -81,7 +81,7 @@ function stride(a::AbstractArray, i::Integer) return s end -strides(a::AbstractArray) = ntuple(ndims(a), i->stride(a,i))::Dims +strides(a::AbstractArray) = ntuple(i->stride(a,i), ndims(a))::Dims function isassigned(a::AbstractArray, i::Int...) # TODO @@ -738,7 +738,7 @@ function hvcat(nbc::Integer, as...) throw(ArgumentError("all rows must have the same number of block columns")) end nbr = div(n,nbc) - hvcat(ntuple(nbr, i->nbc), as...) + hvcat(ntuple(i->nbc, nbr), as...) end function hvcat{T}(rows::Tuple{Vararg{Int}}, as::AbstractMatrix{T}...) @@ -1049,7 +1049,7 @@ end function ind2sub{N,T<:Integer}(dims::NTuple{N,Integer}, ind::AbstractVector{T}) M = length(ind) - t = NTuple{N,Vector{T}}(ntuple(N,n->Array{T}(M))) + t = NTuple{N,Vector{T}}(ntuple(n->Array{T}(M),N)) copy!(t[1],ind) for j = 1:N-1 d = dims[j] diff --git a/base/array.jl b/base/array.jl index 3765af07d19f4..3341ef11b057a 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1278,8 +1278,8 @@ function indcopy(sz::Dims, I::Tuple{Vararg{RangeIndex}}) for i = n+1:length(sz) s *= sz[i] end - dst::typeof(I) = ntuple(n, i-> findin(I[i], i < n ? (1:sz[i]) : (1:s)))::typeof(I) - src::typeof(I) = ntuple(n, i-> I[i][findin(I[i], i < n ? (1:sz[i]) : (1:s))])::typeof(I) + dst::typeof(I) = ntuple(i-> findin(I[i], i < n ? (1:sz[i]) : (1:s)), n)::typeof(I) + src::typeof(I) = ntuple(i-> I[i][findin(I[i], i < n ? (1:sz[i]) : (1:s))], n)::typeof(I) dst, src end diff --git a/base/base.jl b/base/base.jl index d36e9210266a2..419add05c2e8a 100644 --- a/base/base.jl +++ b/base/base.jl @@ -59,10 +59,6 @@ type AssertionError <: Exception AssertionError(msg) = new(msg) end -# For passing constants through type inference -immutable Val{T} -end - ccall(:jl_get_system_hooks, Void, ()) diff --git a/base/bitarray.jl b/base/bitarray.jl index 14cb014aa2cb8..961bb998f5c12 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -280,7 +280,7 @@ function reshape{N}(B::BitArray, dims::NTuple{N,Int}) prod(dims) == length(B) || throw(DimensionMismatch("new dimensions $(dims) must be consistent with array size $(length(B))")) dims == size(B) && return B - Br = BitArray{N}(ntuple(N,i->0)...) + Br = BitArray{N}(ntuple(i->0,N)...) Br.chunks = B.chunks Br.len = prod(dims) N != 1 && (Br.dims = dims) @@ -1710,7 +1710,7 @@ function permutedims(B::Union(BitArray,StridedArray), perm) dimsB = size(B) ndimsB = length(dimsB) (ndimsB == length(perm) && isperm(perm)) || throw(ArgumentError("no valid permutation of dimensions")) - dimsP = ntuple(ndimsB, i->dimsB[perm[i]])::typeof(dimsB) + dimsP = ntuple(i->dimsB[perm[i]], ndimsB)::typeof(dimsB) P = similar(B, dimsP) permutedims!(P, B, perm) end @@ -1831,7 +1831,7 @@ function cat(catdim::Integer, X::Union(BitArray, Integer)...) end end - cat_ranges = ntuple(nargs, i->(catdim <= ndimsX[i] ? dimsX[i][catdim] : 1)) + cat_ranges = ntuple(i->(catdim <= ndimsX[i] ? dimsX[i][catdim] : 1), nargs) function compute_dims(d) if d == catdim @@ -1844,7 +1844,7 @@ function cat(catdim::Integer, X::Union(BitArray, Integer)...) end ndimsC = max(catdim, d_max) - dimsC = ntuple(ndimsC, compute_dims)::Tuple{Vararg{Int}} + dimsC = ntuple(compute_dims, ndimsC)::Tuple{Vararg{Int}} typeC = promote_type(map(x->isa(x,BitArray) ? eltype(x) : typeof(x), X)...) if !has_integer || typeC == Bool C = BitArray(dimsC) @@ -1855,8 +1855,8 @@ function cat(catdim::Integer, X::Union(BitArray, Integer)...) range = 1 for k = 1:nargs nextrange = range + cat_ranges[k] - cat_one = ntuple(ndimsC, i->(i != catdim ? - (1:dimsC[i]) : (range:nextrange-1) )) + cat_one = ntuple(i->(i != catdim ? (1:dimsC[i]) : (range:nextrange-1)), + ndimsC) # note: when C and X are BitArrays, this calls # the special assign with ranges C[cat_one...] = X[k] diff --git a/base/deepcopy.jl b/base/deepcopy.jl index ab866fd4cbee6..0f7fb648773bc 100644 --- a/base/deepcopy.jl +++ b/base/deepcopy.jl @@ -11,7 +11,7 @@ deepcopy_internal(x::Union(Symbol,LambdaStaticData,TopNode,QuoteNode, DataType,UnionType,Task), stackdict::ObjectIdDict) = x deepcopy_internal(x::Tuple, stackdict::ObjectIdDict) = - ntuple(length(x), i->deepcopy_internal(x[i], stackdict)) + ntuple(i->deepcopy_internal(x[i], stackdict), length(x)) deepcopy_internal(x::Module, stackdict::ObjectIdDict) = error("deepcopy of Modules not supported") function deepcopy_internal(x::Function, stackdict::ObjectIdDict) diff --git a/base/deprecated.jl b/base/deprecated.jl index b2406918faa1d..7cac3c4ae9db6 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -368,6 +368,8 @@ end @deprecate with_env(f::Function, key::AbstractString, val) withenv(f, key=>val) +@deprecate ntuple(n::Integer, f::Function) ntuple(f, n) + # 0.4 discontinued functions @noinline function subtypetree(x::DataType, level=-1) diff --git a/base/essentials.jl b/base/essentials.jl index 702dd82885d74..9c01156055522 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -226,3 +226,7 @@ end type Colon end const (:) = Colon() + +# For passing constants through type inference +immutable Val{T} +end diff --git a/base/inference.jl b/base/inference.jl index dd82a9ad67fba..5f5220592c5c2 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1871,7 +1871,7 @@ function type_annotate(ast::Expr, states::Array{Any,1}, sv::ANY, rettype::ANY, a # builtins.c:jl_trampoline. However if jl_trampoline is changed then # this code will need to be restored. #na = length(a.args[1]) - #li.ast, _ = typeinf(li, ntuple(na+1, i->(i>na ? (Tuple)[1] : Any)), + #li.ast, _ = typeinf(li, ntuple(i->(i>na ? (Tuple)[1] : Any), na+1), # li.sparams, li, false) end end diff --git a/base/mmap.jl b/base/mmap.jl index 9ed92112f8325..30705b650732d 100644 --- a/base/mmap.jl +++ b/base/mmap.jl @@ -166,7 +166,7 @@ function mmap_bitarray{N}(dims::NTuple{N,Integer}, s::IOStream, offset::FileOffs 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)...) + B = BitArray{N}(ntuple(i->0,N)...) B.chunks = chunks B.len = n if N != 1 diff --git a/base/multidimensional.jl b/base/multidimensional.jl index fb211e3b29334..d65ab9deb140b 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -856,7 +856,7 @@ end @generated function findn{N}(B::BitArray{N}) quote nnzB = countnz(B) - I = ntuple($N, x->Array(Int, nnzB)) + I = ntuple(x->Array(Int, nnzB), $N) if nnzB > 0 count = 1 @nloops $N i B begin diff --git a/base/serialize.jl b/base/serialize.jl index 7e84f4d1d4668..d9efd5757acd1 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -403,7 +403,7 @@ function handle_deserialize(s, b) return deserialize(s, tag) end -deserialize_tuple(s, len) = ntuple(len, i->deserialize(s)) +deserialize_tuple(s, len) = ntuple(i->deserialize(s), len) deserialize(s, ::Type{Symbol}) = symbol(read(s, UInt8, Int32(read(s, UInt8)))) deserialize(s, ::Type{LongSymbol}) = symbol(read(s, UInt8, read(s, Int32))) diff --git a/base/subarray.jl b/base/subarray.jl index d26ba1eec2e6e..d8bb2870d3296 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -31,7 +31,7 @@ parent(V::SubArray) = V.parent parentindexes(V::SubArray) = V.indexes parent(a::AbstractArray) = a -parentindexes(a::AbstractArray) = ntuple(ndims(a), i->1:size(a,i)) +parentindexes(a::AbstractArray) = ntuple(i->1:size(a,i), ndims(a)) ## SubArray creation # Drops singleton dimensions (those indexed with a scalar) diff --git a/base/tuple.jl b/base/tuple.jl index c7977af2e02ed..06e72b8e58ec2 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -28,7 +28,6 @@ eltype{T,_}(::Type{NTuple{_,T}}) = T ## mapping ## -ntuple(n::Integer, f::Function) = ntuple(f, n) # TODO: deprecate this? ntuple(f::Function, n::Integer) = n<=0 ? () : n==1 ? (f(1),) : @@ -36,7 +35,7 @@ ntuple(f::Function, n::Integer) = n==3 ? (f(1),f(2),f(3),) : n==4 ? (f(1),f(2),f(3),f(4),) : n==5 ? (f(1),f(2),f(3),f(4),f(5),) : - tuple(ntuple(n-2,f)..., f(n-1), f(n)) + tuple(ntuple(f,n-5)..., f(n-4), f(n-3), f(n-2), f(n-1), f(n)) # 0 argument function map(f) = f() diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index f959f827c1ca8..03533e38e138c 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -220,7 +220,7 @@ All Objects Construct a tuple of the given objects. -.. function:: ntuple(n, f::Function) +.. function:: ntuple(f::Function, n) Create a tuple of length ``n``, computing each element as ``f(i)``, where ``i`` is the index of the element. diff --git a/test/arrayops.jl b/test/arrayops.jl index 8985ee265995b..4ec10bcacd1cc 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -882,12 +882,12 @@ A = [NaN]; B = [NaN] Nmax = 3 # TODO: go up to CARTESIAN_DIMS+2 (currently this exposes problems) for N = 1:Nmax #indexing with (UnitRange, UnitRange, UnitRange) - args = ntuple(N, d->UnitRange{Int}) + args = ntuple(d->UnitRange{Int}, N) @test Base.return_types(getindex, Tuple{Array{Float32, N}, args...}) == [Array{Float32, N}] @test Base.return_types(getindex, Tuple{BitArray{N}, args...}) == Any[BitArray{N}] @test Base.return_types(setindex!, Tuple{Array{Float32, N}, Array{Int, 1}, args...}) == [Array{Float32, N}] # Indexing with (UnitRange, UnitRange, Float64) - args = ntuple(N, d->dd 1 && @test Base.return_types(getindex, Tuple{Array{Float32, N}, args...}) == [Array{Float32, N-1}] N > 1 && @test Base.return_types(getindex, Tuple{BitArray{N}, args...}) == [BitArray{N-1}] N > 1 && @test Base.return_types(setindex!, Tuple{Array{Float32, N}, Array{Int, 1}, args...}) == [Array{Float32, N}] @@ -995,7 +995,7 @@ for i = 1:10 @test mdsum(A) == 15 @test mdsum2(A) == 15 AA = reshape(aa, tuple(2, shp...)) - B = sub(AA, 1:1, ntuple(i, i->Colon())...) + B = sub(AA, 1:1, ntuple(i->Colon(), i)...) @test isa(Base.linearindexing(B), Base.IteratorsMD.LinearSlow) @test mdsum(B) == 15 @test mdsum2(B) == 15 @@ -1008,7 +1008,7 @@ for i = 2:10 A = reshape(a, tuple(shp...)) @test mdsum(A) == 55 @test mdsum2(A) == 55 - B = sub(A, ntuple(i, i->Colon())...) + B = sub(A, ntuple(i->Colon(), i)...) @test mdsum(B) == 55 @test mdsum2(B) == 55 insert!(shp, 2, 1) diff --git a/test/arrayperf.jl b/test/arrayperf.jl deleted file mode 100644 index 1d3bc51ea39ae..0000000000000 --- a/test/arrayperf.jl +++ /dev/null @@ -1,263 +0,0 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license - -n_evals = 1e7 -run_ref = true -run_assign = true - -if run_ref - println("#### Ref ####") - println("Whole array operations:") - println("Small arrays:") - lensmall = 4 - for n_dims in 1:10 - sz = ntuple(n_dims,i->lensmall) - A = randn(sz) - n_el = prod(sz) - n_r = ceil(Int,n_evals/n_el) - print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") - print(n_dims, " dimensions (", n_r, " repeats): ") - @time for i = 1:n_r - B = A[:] - end - end - println("Big arrays:") - lenbig = [1000000,1000,100,32,16,10,10] - for n_dims in 1:length(lenbig) - sz = ntuple(n_dims,i->lenbig[n_dims]) - A = randn(sz) - n_el = prod(sz) - n_r = ceil(Int,n_evals/n_el) - print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") - print(n_dims, " dimensions (", n_r, " repeats): ") - @time for i = 1:n_r - B = A[:] - end - end - println("\n") - - println("Slicing with contiguous blocks:") - println("Small arrays:") - for n_dims in 1:10 - sz = ntuple(n_dims,i->lensmall) - A = randn(sz) - ind = ntuple(n_dims,i -> ((i <= ceil(n_dims/2)) ? (1:sz[i]) : (rand(1:sz[i])))) - n_el = prod(map(length,ind)) - n_r = ceil(Int,n_evals/n_el) - print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") - @time for i = 1:n_r - # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) - B = A[ind...] - end - end - println("Big arrays:") - for n_dims in 1:length(lenbig) - sz = ntuple(n_dims,i->lenbig[n_dims]) - A = randn(sz) - ind = ntuple(n_dims,i -> ((i <= ceil(n_dims/2)) ? (1:sz[i]) : (rand(1:sz[i])))) - n_el = prod(map(length,ind)) - n_r = ceil(Int,n_evals/n_el) - print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") - @time for i = 1:n_r - # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) - B = A[ind...] - end - end - println("\n") - - println("Slicing with non-contiguous blocks:") - println("Small arrays:") - for n_dims in 1:10 - sz = ntuple(n_dims,i->lensmall) - A = randn(sz) - ind = ntuple(n_dims,i -> ((i > n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) - n_el = prod(map(length,ind)) - n_r = ceil(Int,n_evals/n_el) - print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") - @time for i = 1:n_r - # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) - B = A[ind...] - end - end - println("Big arrays:") - for n_dims in 1:length(lenbig) - sz = ntuple(n_dims,i->lenbig[n_dims]) - A = randn(sz) - ind = ntuple(n_dims,i -> ((i > n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) - n_el = prod(map(length,ind)) - n_r = ceil(Int,n_evals/n_el) - print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") - @time for i = 1:n_r - # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) - B = A[ind...] - end - end - println("\n") - - - println("Random operations:") - println("Small arrays:") - function randind(len) - i = rand(1:6) - indchoices = [1:len,1:ceil(Int,len/2),1:ceil(Int,3*len/4),2:2:len,1:ceil(Int,len/2):len,len:-1:1] - return indchoices[i] - end - #indsmall = [1:4,1:2,1:3,2:2:4,1:3:4,4:-1:1] - for n_dims in 1:10 - sz = ntuple(n_dims,i->lensmall) - A = randn(sz) - ind = ntuple(n_dims,i->randind(sz[i])) - n_el = prod(map(length,ind)) - n_r = ceil(Int,n_evals/n_el) - print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") - @time for i = 1:n_r - # ind = ntuple(n_dims,i->randind(sz[i])) - B = A[ind...] - end - end - println("Big arrays:") - for n_dims in 1:length(lenbig) - sz = ntuple(n_dims,i->lenbig[n_dims]) - A = randn(sz) - ind = ntuple(n_dims,i->randind(sz[i])) - n_el = prod(map(length,ind)) - n_r = ceil(Int,n_evals/n_el) - print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") - @time for i = 1:n_r - # ind = ntuple(n_dims,i->randind(sz[i])) - B = A[ind...] - end - end -end - -if run_assign - println("\n\n\n#### Assign ####") - println("Whole array operations:") - println("Small arrays:") - for n_dims in 1:10 - sz = ntuple(n_dims,i->lensmall) - B = zeros(sz) - A = randn(sz) - n_r = ceil(Int,n_evals/prod(sz)) - print(n_dims, " dimensions (", n_r, " repeats): ") - @time for i = 1:n_r - B[:] = A - end - end - println("Big arrays:") - for n_dims in 1:length(lenbig) - sz = ntuple(n_dims,i->lenbig[n_dims]) - B = zeros(sz) - A = randn(sz) - n_r = ceil(Int,n_evals/prod(sz)) - print(n_dims, " dimensions (", n_r, " repeats): ") - @time for i = 1:n_r - B[:] = A - end - end - println("\n") - - println("Slicing with contiguous blocks:") - println("Small arrays:") - for n_dims in 1:10 - sz = ntuple(n_dims,i->lensmall) - B = zeros(sz) - ind = ntuple(n_dims,i -> ((i <= ceil(n_dims/2)) ? (1:sz[i]) : (rand(1:sz[i])))) - A = randn(map(length,ind)) - n_el = prod(map(length,ind)) - n_r = ceil(Int,n_evals/n_el) - print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") - @time for i = 1:n_r - # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) - # A = randn(map(length,ind)) - B[ind...] = A - end - end - println("Big arrays:") - for n_dims in 1:length(lenbig) - sz = ntuple(n_dims,i->lenbig[n_dims]) - B = zeros(sz) - ind = ntuple(n_dims,i -> ((i <= ceil(n_dims/2)) ? (1:sz[i]) : (rand(1:sz[i])))) - A = randn(map(length,ind)) - n_el = prod(map(length,ind)) - n_r = ceil(Int,n_evals/n_el) - print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") - @time for i = 1:n_r -# ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) - # A = randn(map(length,ind)) - B[ind...] = A - end - end - println("\n") - - println("Slicing with non-contiguous blocks:") - println("Small arrays:") - for n_dims in 1:10 - sz = ntuple(n_dims,i->lensmall) - B = zeros(sz) - ind = ntuple(n_dims,i -> ((i > n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) - A = randn(map(length,ind)) - n_el = prod(map(length,ind)) - n_r = ceil(Int,n_evals/n_el) - print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") - @time for i = 1:n_r - # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) - # A = randn(map(length,ind)) - B[ind...] = A - end - end - println("Big arrays:") - for n_dims in 1:length(lenbig) - sz = ntuple(n_dims,i->lenbig[n_dims]) - B = zeros(sz) - ind = ntuple(n_dims,i -> ((i > n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) - A = randn(map(length,ind)) - n_el = prod(map(length,ind)) - n_r = ceil(Int,n_evals/n_el) - print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") - @time for i = 1:n_r - # ind = ntuple(n_dims,i -> ((i <= n_dims/2) ? (1:sz[i]) : (rand(1:sz[i])))) - # A = randn(map(length,ind)) - B[ind...] = A - end - end - println("\n") - - - println("Random operations:") - println("Small arrays:") - function randind(len) - i = rand(1:6) - indchoices = [1:len,1:ceil(Int,len/2),1:ceil(Int,3*len/4),2:2:len,1:ceil(Int,len/2):len,len:-1:1] - return indchoices[i] - end - #indsmall = [1:4,1:2,1:3,2:2:4,1:3:4,4:-1:1] - for n_dims in 1:10 - sz = ntuple(n_dims,i->lensmall) - B = zeros(sz) - ind = ntuple(n_dims,i->randind(sz[i])) - A = randn(map(length,ind)) - n_el = prod(map(length,ind)) - n_r = ceil(Int,n_evals/n_el) - print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") - @time for i = 1:n_r - # ind = ntuple(n_dims,i->randind(sz[i])) - # A = randn(map(length,ind)) - B[ind...] = A - end - end - println("Big arrays:") - for n_dims in 1:length(lenbig) - sz = ntuple(n_dims,i->lenbig[n_dims]) - B = zeros(sz) - ind = ntuple(n_dims,i->randind(sz[i])) - A = randn(map(length,ind)) - n_el = prod(map(length,ind)) - n_r = ceil(Int,n_evals/n_el) - print(n_dims, " dimensions (", n_r, " repeats, ", n_r*n_el, " operations): ") - @time for i = 1:n_r - # ind = ntuple(n_dims,i->randind(sz[i])) - # A = randn(map(length,ind)) - B[ind...] = A - end - end -end diff --git a/test/serialize.jl b/test/serialize.jl index 5dd034e6efc34..e2a55f729209d 100644 --- a/test/serialize.jl +++ b/test/serialize.jl @@ -59,7 +59,7 @@ create_serialization_stream() do s serialize(s, tpl) len = 257 - lt = ntuple(len, i->0x1) + lt = ntuple(i->0x1, len) serialize(s, lt) serialize(s, Tuple{}) From ae0ce5f4e5dc97b44c9437d95cdabe9a2de11ffd Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Fri, 29 May 2015 10:21:17 -0500 Subject: [PATCH 157/181] Add an inferrable ntuple function based on Val It's inferrable with Functors and FastAnonymous, but not (currently) generic functions. --- base/tuple.jl | 11 +++++++++++ test/tuple.jl | 3 +++ 2 files changed, 14 insertions(+) diff --git a/base/tuple.jl b/base/tuple.jl index 06e72b8e58ec2..6fe5a67354f9f 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -37,6 +37,17 @@ ntuple(f::Function, n::Integer) = n==5 ? (f(1),f(2),f(3),f(4),f(5),) : tuple(ntuple(f,n-5)..., f(n-4), f(n-3), f(n-2), f(n-1), f(n)) +ntuple(f, ::Type{Val{0}}) = () +ntuple(f, ::Type{Val{1}}) = (f(1),) +ntuple(f, ::Type{Val{2}}) = (f(1),f(2)) +ntuple(f, ::Type{Val{3}}) = (f(1),f(2),f(3)) +ntuple(f, ::Type{Val{4}}) = (f(1),f(2),f(3),f(4)) +ntuple(f, ::Type{Val{5}}) = (f(1),f(2),f(3),f(4),f(5)) +@generated function ntuple{N}(f, ::Type{Val{N}}) + M = N-5 + :(tuple(ntuple(f, Val{$M})..., f($N-4), f($N-3), f($N-2), f($N-1), f($N))) +end + # 0 argument function map(f) = f() # 1 argument function diff --git a/test/tuple.jl b/test/tuple.jl index 90187f6442df6..41e5d1a27c697 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -132,3 +132,6 @@ foo(x, y, z) = x + y + z @test any((true, true)) === true @test any((true, false)) === true @test any((false, false)) === false + +@test @inferred(ntuple(Base.Abs2Fun(), Val{2})) == (1, 4) +@test @inferred(ntuple(Base.Abs2Fun(), Val{6})) == (1, 4, 9, 16, 25, 36) From 6b4c275b339c34ca938f4232c37672c7219d23d0 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 29 May 2015 13:34:37 -0400 Subject: [PATCH 158/181] NEWS item for --handle-signals [ci skip] --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index d426e17a83651..adf5ec02b972a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -119,6 +119,8 @@ Command line option changes * The `-i` option now forces the REPL to run after loading the specified script (if any) ([#11347]). + * New option --handle-signals={yes|no} to disable Julia's signal handlers. + Compiler improvements --------------------- From 45613c247a0016db16b586bff700c7118e3aea30 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Thu, 28 May 2015 12:41:52 -0400 Subject: [PATCH 159/181] Fix #11436: print nested operators with parens Default to prec=0, use prec=-1 to designate a special top-level environment where macros can be space-separated --- base/show.jl | 26 +++++++++++++++----------- test/show.jl | 5 +++++ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/base/show.jl b/base/show.jl index 39ab99da76d67..c9c233414c17b 100644 --- a/base/show.jl +++ b/base/show.jl @@ -254,10 +254,13 @@ show(io::IO, s::Symbol) = show_unquoted_quote_expr(io, s, 0, 0) typealias ExprNode Union(Expr, QuoteNode, SymbolNode, LineNumberNode, LabelNode, GotoNode, TopNode) -print (io::IO, ex::ExprNode) = (show_unquoted(io, ex, 0, 0); nothing) -show (io::IO, ex::ExprNode) = show_unquoted_quote_expr(io, ex, 0, 0) -show_unquoted(io::IO, ex) = show_unquoted(io, ex, 0, 1) -show_unquoted(io::IO, ex, indent::Int) = show_unquoted(io, ex, indent, 1) +# Operators have precedence levels from 1-N, and show_unquoted defaults to a +# precedence level of 0 (the fourth argument). The top-level print and show +# methods use a precedence of -1 to specially allow space-separated macro syntax +print (io::IO, ex::ExprNode) = (show_unquoted(io, ex, 0, -1); nothing) +show (io::IO, ex::ExprNode) = show_unquoted_quote_expr(io, ex, 0, -1) +show_unquoted(io::IO, ex) = show_unquoted(io, ex, 0, 0) +show_unquoted(io::IO, ex, indent::Int) = show_unquoted(io, ex, indent, 0) show_unquoted(io::IO, ex, ::Int,::Int) = show(io, ex) ## AST printing constants ## @@ -345,7 +348,7 @@ function show_block(io::IO, head, args::Vector, body, indent::Int) exs = (is_expr(body, :block) || is_expr(body, :body)) ? body.args : Any[body] for ex in exs if !is_linenumber(ex); print(io, '\n', " "^ind); end - show_unquoted(io, ex, ind, 0) + show_unquoted(io, ex, ind, -1) end print(io, '\n', " "^indent) end @@ -359,7 +362,7 @@ function show_block(io::IO, head, arg, block, i::Int) end # show an indented list -function show_list(io::IO, items, sep, indent::Int, prec::Int=1, enclose_operators::Bool=false) +function show_list(io::IO, items, sep, indent::Int, prec::Int=0, enclose_operators::Bool=false) n = length(items) if n == 0; return end indent += indent_width @@ -374,7 +377,7 @@ function show_list(io::IO, items, sep, indent::Int, prec::Int=1, enclose_operato end end # show an indented list inside the parens (op, cl) -function show_enclosed_list(io::IO, op, items, sep, cl, indent, prec=1, encl_ops=false) +function show_enclosed_list(io::IO, op, items, sep, cl, indent, prec=0, encl_ops=false) print(io, op); show_list(io, items, sep, indent, prec, encl_ops); print(io, cl) end @@ -438,7 +441,7 @@ function show_unquoted_quote_expr(io::IO, value, indent::Int, prec::Int) print(io, "end") else print(io, ":(") - show_unquoted(io, value, indent+indent_width, 0) + show_unquoted(io, value, indent+indent_width, -1) print(io, ")") end end @@ -467,7 +470,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int) elseif (head in expr_infix_any && nargs==2) || (is(head,:(:)) && nargs==3) func_prec = operator_precedence(head) head_ = head in expr_infix_wide ? " $head " : head - if func_prec < prec + if func_prec <= prec show_enclosed_list(io, '(', args, head_, ')', indent, func_prec, true) else show_list(io, args, head_, indent, func_prec, true) @@ -614,10 +617,11 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int) show_list(io, args, ", ", indent) elseif is(head, :macrocall) && nargs >= 1 - if prec >= 1 # nested in calls + # Use the functional syntax unless specifically designated with prec=-1 + if prec >= 0 show_call(io, :call, ex.args[1], ex.args[2:end], indent) else - show_list(io, args, ' ', indent, 1) + show_list(io, args, ' ', indent) end elseif is(head, :typealias) && nargs == 2 diff --git a/test/show.jl b/test/show.jl index c8caa684de473..5a4df943a13e0 100644 --- a/test/show.jl +++ b/test/show.jl @@ -256,3 +256,8 @@ end @test repr(:(@m x y)) == ":(@m x y)" @test string(:(@m x y)) == "@m x y" @test string(:(@m x y;)) == "begin \n @m x y\nend" + +# issue #11436 +@test_repr "1 => 2 => 3" +@test_repr "1 => (2 => 3)" +@test_repr "(1 => 2) => 3" From 817cae25bc088753a2b00e1d8eeca535d03435f7 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 29 May 2015 19:55:30 -0400 Subject: [PATCH 160/181] fix #11492, inference logic for which values are valid type parameters --- base/inference.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/inference.jl b/base/inference.jl index dd82a9ad67fba..366dbd6321114 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -352,7 +352,7 @@ function valid_tparam(x::ANY) end function extract_simple_tparam(Ai) - if isa(Ai,Int) || isa(Ai,Bool) + if !isa(Ai,Symbol) && valid_tparam(Ai) return Ai elseif isa(Ai,QuoteNode) && valid_tparam(Ai.value) return Ai.value From 0dd566942db3d7fb6573597ecededde9ef27be17 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Fri, 29 May 2015 17:48:23 -0400 Subject: [PATCH 161/181] re-add big(z::Complex) method (inadvertently deleted) and related methods --- base/complex.jl | 4 ++++ base/rational.jl | 3 +++ test/numbers.jl | 7 +++++++ 3 files changed, 14 insertions(+) diff --git a/base/complex.jl b/base/complex.jl index 7ecfd8fe604b5..f149e4f3c22bc 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -725,6 +725,9 @@ float{T<:FloatingPoint}(z::Complex{T}) = z float(z::Complex) = Complex(float(real(z)), float(imag(z))) @vectorize_1arg Complex float +big{T<:FloatingPoint}(z::Complex{T}) = Complex{BigFloat}(z) +big{T<:Integer}(z::Complex{T}) = Complex{BigInt}(z) + ## Array operations on complex numbers ## complex{T<:Complex}(x::AbstractArray{T}) = x @@ -737,6 +740,7 @@ function complex(A::AbstractArray) map_promote(cnv, A) end +big{T<:Integer,N}(x::AbstractArray{Complex{T},N}) = convert(AbstractArray{Complex{BigInt},N}, x) big{T<:FloatingPoint,N}(x::AbstractArray{Complex{T},N}) = convert(AbstractArray{Complex{BigFloat},N}, x) ## promotion to complex ## diff --git a/base/rational.jl b/base/rational.jl index 4bda53ec0069c..e66bab63ad624 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -80,6 +80,9 @@ end convert(::Type{Rational}, x::Float64) = convert(Rational{Int64}, x) convert(::Type{Rational}, x::Float32) = convert(Rational{Int}, x) +big{T<:Integer}(z::Complex{Rational{T}}) = Complex{Rational{BigInt}}(z) +big{T<:Integer,N}(x::AbstractArray{Complex{Rational{T}},N}) = convert(AbstractArray{Complex{Rational{BigInt}},N}, x) + promote_rule{T<:Integer,S<:Integer}(::Type{Rational{T}}, ::Type{S}) = Rational{promote_type(T,S)} promote_rule{T<:Integer,S<:Integer}(::Type{Rational{T}}, ::Type{Rational{S}}) = Rational{promote_type(T,S)} promote_rule{T<:Integer,S<:FloatingPoint}(::Type{Rational{T}}, ::Type{S}) = promote_type(T,S) diff --git a/test/numbers.jl b/test/numbers.jl index c8355448b14de..f5deef2a04774 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -2481,3 +2481,10 @@ for T in (Int8,Int16,Int32,Int64,Int128,UInt8,UInt16,UInt32,UInt64,UInt128) @test_throws InexactError T(big(typemax(T))+1) @test_throws InexactError T(big(typemin(T))-1) end + +for (d,B) in ((4//2+1im,Rational{BigInt}),(3.0+1im,BigFloat),(2+1im,BigInt)) + @test typeof(big(d)) == Complex{B} + @test big(d) == d + @test typeof(big([d])) == Vector{Complex{B}} + @test big([d]) == [d] +end From 11310e6be88bd97ff973a0b9027b21a3c4a04852 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Sat, 30 May 2015 22:52:03 +0530 Subject: [PATCH 162/181] Get rid of all LLVM_FLAGS for ARM, and let LLVM autodetect. Move to LLVM 3.6.1 on arm. --- Make.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Make.inc b/Make.inc index ed24bb7202fc9..09379149b9fa2 100644 --- a/Make.inc +++ b/Make.inc @@ -505,8 +505,8 @@ ifneq (,$(findstring arm,$(ARCH))) JCFLAGS += -fsigned-char LLVM_ASSERTIONS=1 -LLVM_FLAGS+="--with-float=hard --with-abi=aapcs-vfp" -LLVM_VER=3.6.0 +#LLVM_FLAGS+="--with-float=hard --with-abi=aapcs-vfp" +LLVM_VER=3.6.1 USE_BLAS64=0 OPENBLAS_DYNAMIC_ARCH=0 From e3bdd0a4700d8124e44feb3b7030e3c59cc6356d Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Sat, 30 May 2015 20:55:34 -0400 Subject: [PATCH 163/181] Fix use of one deprecation in another deprecation --- base/deprecated.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index b2406918faa1d..a2fa838da1743 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -330,12 +330,12 @@ for (f,t) in ((:int, Int), (:int8, Int8), (:int16, Int16), (:int32, Int32 (:int64, Int64), (:int128, Int128), (:uint, UInt), (:uint8, UInt8), (:uint16, UInt16), (:uint32, UInt32), (:uint64, UInt64), (:uint128,UInt128)) @eval begin - @deprecate ($f){S<:AbstractString}(a::AbstractArray{S}) [parseint($t,s) for s in a] + @deprecate ($f){S<:AbstractString}(a::AbstractArray{S}) [parse($t,s) for s in a] end end for (f,t) in ((:float32, Float32), (:float64, Float64)) @eval begin - @deprecate ($f){S<:AbstractString}(a::AbstractArray{S}) [parsefloat($t,s) for s in a] + @deprecate ($f){S<:AbstractString}(a::AbstractArray{S}) [parse($t,s) for s in a] end end From 64a8e025465a46f2508a5fa11cb3aa03d8826aea Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Sun, 31 May 2015 00:40:56 -0400 Subject: [PATCH 164/181] Fix Profiler segfault on Darwin We frequently find ourselves in the presence of invalid unwind information, which can cause the profiler to try to access invalid memory. It is possible to probe before whether the memory is accessible, but the easier solution is just to catch the SEGV and recover. This used to work originally, but in 12d363a1c678fabec61b215b8ecc5e6b7a17cc65, I switched exception handling to be thread-local to be able to debug the exception handler. Unfortunately, since the profiler runs on a different thread, it was no longer covered by this protection. Rectify that. --- src/init.c | 12 ++++++++++-- src/julia_internal.h | 3 +++ src/profile.c | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/init.c b/src/init.c index ec444bc9c1131..18791319e1bee 100644 --- a/src/init.c +++ b/src/init.c @@ -954,6 +954,15 @@ static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) jl_options.load = abspath(jl_options.load); } +#ifdef _OS_DARWIN_ +void attach_exception_port() +{ + kern_return_t ret; + ret = thread_set_exception_ports(mach_thread_self(),EXC_MASK_BAD_ACCESS,segv_port,EXCEPTION_DEFAULT,MACHINE_THREAD_STATE); + HANDLE_MACH_ERROR("thread_set_exception_ports",ret); +} +#endif + void _julia_init(JL_IMAGE_SEARCH rel) { libsupport_init(); @@ -1123,8 +1132,7 @@ void _julia_init(JL_IMAGE_SEARCH rel) } pthread_attr_destroy(&attr); - ret = thread_set_exception_ports(mach_thread_self(),EXC_MASK_BAD_ACCESS,segv_port,EXCEPTION_DEFAULT,MACHINE_THREAD_STATE); - HANDLE_MACH_ERROR("thread_set_exception_ports",ret); + attach_exception_port(); #else // defined(_OS_DARWIN_) stack_t ss; ss.ss_flags = 0; diff --git a/src/julia_internal.h b/src/julia_internal.h index ce3a622a60b6f..f4634079af4ab 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -154,6 +154,9 @@ DLLEXPORT size_t rec_backtrace_ctx(ptrint_t *data, size_t maxsize, bt_context_t size_t rec_backtrace_ctx_dwarf(ptrint_t *data, size_t maxsize, bt_context_t ctx); #endif DLLEXPORT void jl_raise_debugger(void); +#ifdef _OS_DARWIN_ +DLLEXPORT void attach_exception_port(void); +#endif // timers // Returns time in nanosec diff --git a/src/profile.c b/src/profile.c index 946e3463399d3..f47dd19d210d8 100644 --- a/src/profile.c +++ b/src/profile.c @@ -169,6 +169,7 @@ void *mach_profile_listener(void *arg) { (void)arg; int max_size = 512; + attach_exception_port(); mach_profiler_thread = mach_thread_self(); mig_reply_error_t *bufRequest = (mig_reply_error_t *) malloc(max_size); while (1) { From bfa86480b8a3a7de91da8ac2ead59995d95850d1 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 31 May 2015 06:53:36 -0500 Subject: [PATCH 165/181] Support ndims(::CartesianRange) --- base/multidimensional.jl | 4 +++- test/arrayops.jl | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index d65ab9deb140b..cb93c225865a9 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -3,7 +3,7 @@ ### Multidimensional iterators module IteratorsMD -import Base: eltype, length, start, done, next, last, getindex, setindex!, linearindexing, min, max, eachindex +import Base: eltype, length, start, done, next, last, getindex, setindex!, linearindexing, min, max, eachindex, ndims import Base: simd_outer_range, simd_inner_length, simd_index, @generated import Base: @nref, @ncall, @nif, @nexprs, LinearFast, LinearSlow, to_index @@ -144,6 +144,8 @@ end end CartesianRange{N}(sz::NTuple{N,Int}) = CartesianRange(CartesianIndex(sz)) +ndims(R::CartesianRange) = length(R.start) + @generated function eachindex{T,N}(::LinearSlow, A::AbstractArray{T,N}) startargs = fill(1, N) stopargs = [:(size(A,$i)) for i=1:N] diff --git a/test/arrayops.jl b/test/arrayops.jl index 4ec10bcacd1cc..dcda66cfc9967 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -1076,6 +1076,7 @@ indexes = collect(R) @test indexes[12] == CartesianIndex{2}(5,5) @test length(indexes) == 12 @test length(R) == 12 +@test ndims(R) == 2 r = 2:3 itr = eachindex(r) From d1b34516b88bb96b356bb9b8d61f8241d15a348e Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Sun, 31 May 2015 20:23:53 -0400 Subject: [PATCH 166/181] Fix round(::AbstractArray, digits::Int) etc. cc @sbromberger --- base/floatfuncs.jl | 11 ++++++++++- test/numbers.jl | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index e2d64579f4235..61e7e8a839a97 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -77,6 +77,15 @@ for f in (:trunc,:floor,:ceil,:round) function ($f){T}(::Type{T}, x::AbstractArray) reshape([ ($f)(T, x[i])::T for i in eachindex(x) ], size(x)) end + function ($f){R}(x::AbstractArray{R,1}, digits::Integer, base::Integer=10) + [ ($f)(x[i], digits, base) for i = 1:length(x) ] + end + function ($f){R}(x::AbstractArray{R,2}, digits::Integer, base::Integer=10) + [ ($f)(x[i,j], digits, base) for i = 1:size(x,1), j = 1:size(x,2) ] + end + function ($f)(x::AbstractArray, digits::Integer, base::Integer=10) + reshape([ ($f)(x[i], digits, base) for i in eachindex(x) ], size(x)) + end end end @@ -135,7 +144,7 @@ end for f in (:round, :ceil, :floor, :trunc) @eval begin - function ($f)(x, digits::Integer, base::Integer=10) + function ($f)(x::Real, digits::Integer, base::Integer=10) x = float(x) og = convert(eltype(x),base)^digits r = ($f)(x * og) / og diff --git a/test/numbers.jl b/test/numbers.jl index c8355448b14de..43455a8eb6f59 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -1860,6 +1860,16 @@ x = 0.0 @test approx_eq(round(pi,2,2), 3.25) @test approx_eq(round(pi,3,2), 3.125) @test approx_eq(round(pi,3,5), 3.144) +# vectorized trunc/round/floor/ceil with digits/base argument +a = rand(2, 2, 2) +for f in (trunc, round, floor, ceil) + @test f(a[:, 1, 1], 2) == map(x->f(x, 2), a[:, 1, 1]) + @test f(a[:, :, 1], 2) == map(x->f(x, 2), a[:, :, 1]) + @test f(a, 9, 2) == map(x->f(x, 9, 2), a) + @test f(a[:, 1, 1], 9, 2) == map(x->f(x, 9, 2), a[:, 1, 1]) + @test f(a[:, :, 1], 9, 2) == map(x->f(x, 9, 2), a[:, :, 1]) + @test f(a, 9, 2) == map(x->f(x, 9, 2), a) + end # significant digits (would be nice to have a smart vectorized # version of signif) @test approx_eq(signif(123.456,1), 100.) From 848dfc51df259e3146a685d071e7892291759f06 Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Sun, 31 May 2015 20:26:31 -0400 Subject: [PATCH 167/181] Avoid checking which rounding function is called at runtime --- base/floatfuncs.jl | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index 61e7e8a839a97..6b307ae678335 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -153,15 +153,9 @@ for f in (:round, :ceil, :floor, :trunc) if digits > 0 return x elseif x > 0 - if ceil == $f - return convert(eltype(x), Inf) - end - return zero(x) + return $(:ceil == f ? :(convert(eltype(x), Inf)) : :(zero(x))) elseif x < 0 - if floor == $f - return -convert(eltype(x), Inf) - end - return -zero(x) + return $(:floor == f ? :(-convert(eltype(x), Inf)) : :(-zero(x))) else return x end From 8d8638726473b97b2ca4b9e13a54e897fe06843a Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Sun, 31 May 2015 20:59:23 -0400 Subject: [PATCH 168/181] Use new LLVM 3.7 APIs for backtraces Fixes #7910. --- base/replutil.jl | 4 ++-- src/debuginfo.cpp | 38 +++++++++++++++++++++++--------------- src/disasm.cpp | 3 ++- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/base/replutil.jl b/base/replutil.jl index 3c9f002464881..4cca6d5372d40 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -96,7 +96,7 @@ showerror(io::IO, ex::LoadError) = showerror(io, ex, []) function showerror(io::IO, ex::DomainError, bt) print(io, "DomainError:") for b in bt - code = ccall(:jl_lookup_code_address, Any, (Ptr{Void}, Cint), b, true) + code = ccall(:jl_lookup_code_address, Any, (Ptr{Void}, Cint), b-1, true) if length(code) == 5 && !code[4] # code[4] == fromC if code[1] in (:log, :log2, :log10, :sqrt) # TODO add :besselj, :besseli, :bessely, :besselk println(io,"\n$(code[1]) will only return a complex result if called with a complex argument.") @@ -350,7 +350,7 @@ function show_backtrace(io::IO, top_function::Symbol, t, set) local fname, file, line count = 0 for i = 1:length(t) - lkup = ccall(:jl_lookup_code_address, Any, (Ptr{Void}, Cint), t[i], true) + lkup = ccall(:jl_lookup_code_address, Any, (Ptr{Void}, Cint), t[i]-1, true) if lkup === nothing continue end diff --git a/src/debuginfo.cpp b/src/debuginfo.cpp index eb7f745ee6260..d8acadf431a21 100644 --- a/src/debuginfo.cpp +++ b/src/debuginfo.cpp @@ -69,7 +69,9 @@ struct FuncInfo { struct ObjectInfo { const object::ObjectFile* object; size_t size; -#ifdef LLVM36 +#ifdef LLVM37 + const llvm::LoadedObjectInfo *L; +#elif defined(LLVM36) size_t slide; #endif #ifdef _OS_DARWIN_ @@ -306,12 +308,15 @@ class JuliaJITEventListener: public JITEventListener if (Section->isText(isText) || !isText) continue; #endif #ifdef _OS_DARWIN_ -#if defined(LLVM36) +# if defined(LLVM37) + Size = Section->getSize(); +# endif +# if defined(LLVM36) sym_iter.getName(sName); if (sName[0] == '_') { sName = sName.substr(1); } -#else +# else sym_iter.getName(sName); Addr = ((MCJIT*)jl_ExecutionEngine)->getSymbolAddress(sName, true); if (!Addr && sName[0] == '_') { @@ -319,18 +324,18 @@ class JuliaJITEventListener: public JITEventListener Addr = ((MCJIT*)jl_ExecutionEngine)->getSymbolAddress(sName, true); } if (!Addr) continue; -#endif +# endif #elif defined(_OS_WINDOWS_) -#if defined(LLVM36) +# if defined(LLVM36) SectionSize = Section->getSize(); -#else +# else Section->getAddress(SectionAddr); Section->getSize(SectionSize); -#endif +# endif sym_iter.getName(sName); -#ifdef _CPU_X86_ +# ifdef _CPU_X86_ if (sName[0] == '_') sName = sName.substr(1); -#endif +# endif if (SectionAddrCheck) assert(SectionAddrCheck == SectionAddr); else @@ -346,7 +351,9 @@ class JuliaJITEventListener: public JITEventListener obj.getObjectFile(); #endif ObjectInfo tmp = {objfile, (size_t)Size -#ifdef LLVM36 +#ifdef LLVM37 + ,L.clone() +#elif defined(LLVM36) ,(size_t)SectionAddr #endif #ifdef _OS_DARWIN_ @@ -708,19 +715,20 @@ void jl_getFunctionInfo(const char **name, size_t *line, const char **filename, std::map::iterator it = objmap.lower_bound(pointer); if (it != objmap.end() && (intptr_t)(*it).first + (*it).second.size > pointer) { -#if defined(_OS_DARWIN_) +#if defined(_OS_DARWIN_) && !defined(LLVM37) *name = jl_demangle((*it).second.name); - DIContext *context = NULL; // current versions of MCJIT can't handle MachO relocations + DIContext *context = NULL; // versions of MCJIT < 3.7 can't handle MachO relocations #else #ifdef LLVM36 #ifdef LLVM37 - DIContext *context = new DWARFContextInMemory(*it->second.object); + DIContext *context = new DWARFContextInMemory(*it->second.object, it->second.L); #else DIContext *context = DIContext::getDWARFContext(*it->second.object); -#endif pointer -= (*it).second.slide; +#endif #else DIContext *context = DIContext::getDWARFContext(const_cast(it->second.object)); + pointer -= (*it).second.slide; #endif #endif lookup_pointer(context, name, line, filename, pointer, 1, fromC); @@ -811,7 +819,7 @@ int jl_get_llvmf_info(uint64_t fptr, uint64_t *symsize, uint64_t *slide, if (fit != objmap.end()) { *symsize = fit->second.size; *object = fit->second.object; -#ifdef LLVM36 +#if defined(LLVM36) && !defined(LLVM37) *slide = fit->second.slide; #else *slide = 0; diff --git a/src/disasm.cpp b/src/disasm.cpp index d07fdaf3f44f8..5028e10b6d009 100644 --- a/src/disasm.cpp +++ b/src/disasm.cpp @@ -166,10 +166,11 @@ void SymbolTable::createSymbols() name << "L" << addr; #ifdef LLVM37 MCSymbol *symb = Ctx.getOrCreateSymbol(StringRef(name.str())); + symb->setVariableValue(MCConstantExpr::create(addr, Ctx)); #else MCSymbol *symb = Ctx.GetOrCreateSymbol(StringRef(name.str())); -#endif symb->setVariableValue(MCConstantExpr::Create(addr, Ctx)); +#endif isymb->second = symb; } } From ccab0298fdfe6b48a574a5da1a5d2ecb3a9145b5 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Sun, 31 May 2015 22:01:44 -0400 Subject: [PATCH 169/181] Add an option to turn segfaults into julia errors This is quite handy when developing against C or C++ libraries that like to segfault on invalid parameters. --- base/boot.jl | 3 ++- base/essentials.jl | 1 + src/alloc.c | 3 +++ src/init.c | 32 ++++++++++++++++++++++++++++++++ src/julia_internal.h | 4 ++++ src/options.h | 5 +++++ 6 files changed, 47 insertions(+), 1 deletion(-) diff --git a/base/boot.jl b/base/boot.jl index 51b41d4e51a98..bacea5b210c02 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -136,7 +136,7 @@ export # errors BoundsError, DivideError, DomainError, Exception, InexactError, InterruptException, OutOfMemoryError, OverflowError, - StackOverflowError, UndefRefError, UndefVarError, + StackOverflowError, SegmentationFault, UndefRefError, UndefVarError, # AST representation Expr, GotoNode, LabelNode, LineNumberNode, QuoteNode, SymbolNode, TopNode, GlobalRef, NewvarNode, GenSym, @@ -218,6 +218,7 @@ immutable DomainError <: Exception end immutable OverflowError <: Exception end immutable InexactError <: Exception end immutable OutOfMemoryError <: Exception end +immutable SegmentationFault <: Exception end immutable StackOverflowError <: Exception end immutable UndefRefError <: Exception end immutable UndefVarError <: Exception diff --git a/base/essentials.jl b/base/essentials.jl index 702dd82885d74..bd7eb10ae78eb 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -15,6 +15,7 @@ call(T::Type{OverflowError}) = Core.call(T) call(T::Type{InexactError}) = Core.call(T) call(T::Type{OutOfMemoryError}) = Core.call(T) call(T::Type{StackOverflowError}) = Core.call(T) +call(T::Type{SegmentationFault}) = Core.call(T) call(T::Type{UndefRefError}) = Core.call(T) call(T::Type{UndefVarError}, var::Symbol) = Core.call(T, var) call(T::Type{InterruptException}) = Core.call(T) diff --git a/src/alloc.c b/src/alloc.c index 913982d236e74..2a1cdcb9189d4 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -62,6 +62,9 @@ jl_datatype_t *jl_void_type; jl_datatype_t *jl_voidpointer_type; jl_value_t *jl_an_empty_cell=NULL; jl_value_t *jl_stackovf_exception; +#ifdef SEGV_EXCEPTION +jl_value_t *jl_segv_exception; +#endif jl_value_t *jl_diverror_exception; jl_value_t *jl_domain_exception; jl_value_t *jl_overflow_exception; diff --git a/src/init.c b/src/init.c index ec444bc9c1131..910a716909587 100644 --- a/src/init.c +++ b/src/init.c @@ -289,9 +289,18 @@ void segv_handler(int sig, siginfo_t *info, void *context) sigprocmask(SIG_UNBLOCK, &sset, NULL); jl_throw(jl_memory_exception); } +#ifdef SEGV_EXCEPTION + else { + sigemptyset(&sset); + sigaddset(&sset, SIGSEGV); + sigprocmask(SIG_UNBLOCK, &sset, NULL); + jl_throw(jl_segv_exception); + } +#else else { sigdie_handler(sig, info, context); } +#endif } #endif @@ -746,6 +755,17 @@ void *mach_segv_listener(void *arg) } } +#ifdef SEGV_EXCEPTION + +void darwin_segv_handler(unw_context_t *uc) +{ + bt_size = rec_backtrace_ctx(bt_data, MAX_BT_SIZE, uc); + jl_exception_in_transit = jl_segv_exception; + jl_rethrow(); +} + +#endif + void darwin_stack_overflow_handler(unw_context_t *uc) { bt_size = rec_backtrace_ctx(bt_data, MAX_BT_SIZE, uc); @@ -798,8 +818,12 @@ kern_return_t catch_exception_raise(mach_port_t exception_port, ret = thread_get_state(thread,x86_EXCEPTION_STATE64,(thread_state_t)&exc_state,&exc_count); HANDLE_MACH_ERROR("thread_get_state(1)",ret); uint64_t fault_addr = exc_state.__faultvaddr; +#ifdef SEGV_EXCEPTION + if (1) { +#else if (is_addr_on_stack((void*)fault_addr) || ((exc_state.__err & PAGE_PRESENT) == PAGE_PRESENT)) { +#endif ret = thread_get_state(thread,x86_THREAD_STATE64,(thread_state_t)&state,&count); HANDLE_MACH_ERROR("thread_get_state(2)",ret); old_state = state; @@ -822,6 +846,10 @@ kern_return_t catch_exception_raise(mach_port_t exception_port, state.__rdi = (uint64_t)uc; if ((exc_state.__err & PAGE_PRESENT) == PAGE_PRESENT) state.__rip = (uint64_t)darwin_accerr_handler; +#ifdef SEGV_EXCEPTION + else if (!is_addr_on_stack((void*)fault_addr)) + state.__rip = (uint64_t)darwin_segv_handler; +#endif else state.__rip = (uint64_t)darwin_stack_overflow_handler; @@ -1325,6 +1353,10 @@ void jl_get_builtin_hooks(void) jl_boundserror_type = (jl_datatype_t*)core("BoundsError"); jl_memory_exception = jl_new_struct_uninit((jl_datatype_t*)core("OutOfMemoryError")); +#ifdef SEGV_EXCEPTION + jl_segv_exception = jl_new_struct_uninit((jl_datatype_t*)core("SegmentationFault")); +#endif + jl_ascii_string_type = (jl_datatype_t*)core("ASCIIString"); jl_utf8_string_type = (jl_datatype_t*)core("UTF8String"); jl_symbolnode_type = (jl_datatype_t*)core("SymbolNode"); diff --git a/src/julia_internal.h b/src/julia_internal.h index ce3a622a60b6f..70061fa2d2fcf 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -176,6 +176,10 @@ DLLEXPORT void jl_atexit_hook(); #define HAVE_CPUID #endif +#ifdef SEGV_EXCEPTION +extern DLLEXPORT jl_value_t *jl_segv_exception; +#endif + #ifdef __cplusplus } #endif diff --git a/src/options.h b/src/options.h index 91015f0860192..43aba33de8103 100644 --- a/src/options.h +++ b/src/options.h @@ -49,6 +49,11 @@ // reachable memory is freed //#define GC_VERIFY +// SEGV_EXCEPTION turns segmentation faults into catchable julia exceptions. +// This is not recommended, as the memory state after such an exception should +// be considered untrusted, but can be helpful during development +// #define SEGV_EXCEPTION + // profiling options // GC_FINAL_STATS prints total GC stats at exit From 7d202b782ebe7f02f02c3adcaa529fc73b1ff74e Mon Sep 17 00:00:00 2001 From: kshyatt Date: Fri, 15 May 2015 17:33:44 -0700 Subject: [PATCH 170/181] Initial work on blas and bidiag --- base/linalg/bidiag.jl | 17 +++++--- base/linalg/blas.jl | 94 +++++++++++++++++++++++++++++++------------ 2 files changed, 79 insertions(+), 32 deletions(-) diff --git a/base/linalg/bidiag.jl b/base/linalg/bidiag.jl index 6e4a5d9795948..6c29d7e65b6f9 100644 --- a/base/linalg/bidiag.jl +++ b/base/linalg/bidiag.jl @@ -6,7 +6,11 @@ type Bidiagonal{T} <: AbstractMatrix{T} ev::Vector{T} # sub/super diagonal isupper::Bool # is upper bidiagonal (true) or lower (false) function Bidiagonal{T}(dv::Vector{T}, ev::Vector{T}, isupper::Bool) - length(ev)==length(dv)-1 ? new(dv, ev, isupper) : throw(DimensionMismatch()) + if length(ev)==length(dv)-1 + new(dv, ev, isupper) + else + throw(DimensionMismatch("Length of diagonal vector is $(length(dv)), length of off-diagonal vector is $(length(ev))")) + end end end Bidiagonal{T}(dv::AbstractVector{T}, ev::AbstractVector{T}, isupper::Bool)=Bidiagonal{T}(copy(dv), copy(ev), isupper) @@ -103,7 +107,7 @@ function diag{T}(M::Bidiagonal{T}, n::Integer=0) elseif -size(M,1) length(x) || minimum(ry) < 1 || maximum(ry) > length(y) - throw(BoundsError()) + if length(rx) != length(ry) + throw(DimensionMismatch("Ranges of differing lengths")) + end + if minimum(rx) < 1 || maximum(rx) > length(x) + throw(BoundsError("Range out of bounds for x, of length $(length(x))")) + end + if minimum(ry) < 1 || maximum(ry) > length(y) + throw(BoundsError("Range out of bounds for y, of length $(length(y))")) end axpy!(length(rx), convert(T, alpha), pointer(x)+(first(rx)-1)*sizeof(T), step(rx), pointer(y)+(first(ry)-1)*sizeof(T), step(ry)) y @@ -269,7 +281,13 @@ for (fname, elty) in ((:dgemv_,:Float64), # DOUBLE PRECISION A(LDA,*),X(*),Y(*) function gemv!(trans::Char, alpha::($elty), A::StridedVecOrMat{$elty}, X::StridedVector{$elty}, beta::($elty), Y::StridedVector{$elty}) m,n = size(A,1),size(A,2) - length(X) == (trans == 'N' ? n : m) && length(Y) == (trans == 'N' ? m : n) || throw(DimensionMismatch()) + if trans == 'N' && (length(X) != n || length(Y) != m) + throw(DimensionMismatch("A has dimensions $(size(A)), X has length $(length(X)) and Y has length $(length(Y))")) + elseif trans == 'C' && (length(X) != m || length(Y) != n) + throw(DimensionMismatch("A' has dimensions $n, $m, X has length $(length(X)) and Y has length $(length(Y))")) + elseif trans == 'T' && (length(X) != m || length(Y) != n) + throw(DimensionMismatch("A.' has dimensions $n, $m, X has length $(length(X)) and Y has length $(length(Y))")) + end ccall(($(blasfunc(fname)), libblas), Void, (Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}, @@ -340,7 +358,9 @@ for (fname, elty) in ((:dsymv_,:Float64), function symv!(uplo::Char, alpha::($elty), A::StridedMatrix{$elty}, x::StridedVector{$elty},beta::($elty), y::StridedVector{$elty}) m, n = size(A) if m != n throw(DimensionMismatch("Matrix A is $m by $n but must be square")) end - if m != length(x) || m != length(y) throw(DimensionMismatch()) end + if m != length(x) || m != length(y) + throw(DimensionMismatch("A has size ($m,$n), x has length $(length(x)), y has length $(length(y))")) + end ccall(($(blasfunc(fname)), libblas), Void, (Ref{UInt8}, Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}, Ref{$elty}, @@ -365,8 +385,12 @@ for (fname, elty) in ((:zhemv_,:Complex128), @eval begin function hemv!(uplo::Char, α::$elty, A::StridedMatrix{$elty}, x::StridedVector{$elty}, β::$elty, y::StridedVector{$elty}) n = size(A, 2) - n == length(x) || throw(DimensionMismatch()) - size(A, 1) == length(y) || throw(DimensionMismatch()) + if n != length(x) + throw(DimensionMismatch("A has size $(size(A)), and x has length $(length(x))")) + end + if size(A, 1) != length(y) + throw(DimensionMismatch("A has size $(size(A)), and y has length $(length(x))")) + end lda = max(1, stride(A, 2)) incx = stride(x, 1) incy = stride(y, 1) @@ -464,7 +488,9 @@ for (fname, elty) in ((:dtrsv_,:Float64), # DOUBLE PRECISION A(LDA,*),X(*) function trsv!(uplo::Char, trans::Char, diag::Char, A::StridedMatrix{$elty}, x::StridedVector{$elty}) n = chksquare(A) - n==length(x) || throw(DimensionMismatch("size of A is $n != length(x) = $(length(x))")) + if n != length(x) + throw(DimensionMismatch("size of A is $n != length(x) = $(length(x))")) + end ccall(($(blasfunc(fname)), libblas), Void, (Ref{UInt8}, Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}), @@ -486,8 +512,9 @@ for (fname, elty) in ((:dger_,:Float64), @eval begin function ger!(α::$elty, x::StridedVector{$elty}, y::StridedVector{$elty}, A::StridedMatrix{$elty}) m, n = size(A) - m == length(x) || throw(DimensionMismatch()) - n == length(y) || throw(DimensionMismatch()) + if m != length(x) || n != length(y) + throw(DimensionMismatch("A has size ($m,$n), x has length $(length(x)), y has length $(length(y))")) + end ccall(($(blasfunc(fname)), libblas), Void, (Ref{BlasInt}, Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, @@ -508,7 +535,9 @@ for (fname, elty) in ((:dsyr_,:Float64), @eval begin function syr!(uplo::Char, α::$elty, x::StridedVector{$elty}, A::StridedMatrix{$elty}) n = chksquare(A) - length(x) == n || throw(DimensionMismatch("Length of vector must be the same as the matrix dimensions")) + if length(x) != n + throw(DimensionMismatch("A has size ($n,$n), x has length $(length(x))")) + end ccall(($(blasfunc(fname)), libblas), Void, (Ref{UInt8}, Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}), @@ -525,7 +554,9 @@ for (fname, elty) in ((:zher_,:Complex128), @eval begin function her!(uplo::Char, α::$elty, x::StridedVector{$elty}, A::StridedMatrix{$elty}) n = chksquare(A) - length(x) == A || throw(DimensionMismatch("Length of vector must be the same as the matrix dimensions")) + if length(x) != A + throw(DimensionMismatch("A has size ($n,$n), x has length $(length(x))")) + end ccall(($(blasfunc(fname)), libblas), Void, (Ref{UInt8}, Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}), @@ -559,7 +590,7 @@ for (gemm, elty) in k = size(A, transA == 'N' ? 2 : 1) n = size(B, transB == 'N' ? 2 : 1) if m != size(C,1) || n != size(C,2) - throw(DimensionMismatch()) + throw(DimensionMismatch("A has size ($m,$k), B has size ($k,$n), C has size $(size(C))")) end ccall(($(blasfunc(gemm)), libblas), Void, (Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, @@ -667,7 +698,7 @@ for (fname, elty) in ((:dsyrk_,:Float64), beta::($elty), C::StridedMatrix{$elty}) n = chksquare(C) nn = size(A, trans == 'N' ? 1 : 2) - if nn != n throw(DimensionMismatch("syrk!")) end + if nn != n throw(DimensionMismatch("C has size ($n,$n), corresponding dimension of A is $nn")) end k = size(A, trans == 'N' ? 2 : 1) ccall(($(blasfunc(fname)), libblas), Void, (Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, @@ -701,7 +732,10 @@ for (fname, elty, relty) in ((:zherk_, :Complex128, :Float64), function herk!(uplo::Char, trans::Char, α::$relty, A::StridedVecOrMat{$elty}, β::$relty, C::StridedMatrix{$elty}) n = chksquare(C) - n == size(A, trans == 'N' ? 1 : 2) || throw(DimensionMismatch("the matrix to update has dimension $n but the implied dimension of the update is $(size(A, trans == 'N' ? 1 : 2))")) + nn = size(A, trans == 'N' ? 1 : 2) + if nn != n + throw(DimensionMismatch("the matrix to update has dimension $n but the implied dimension of the update is $(size(A, trans == 'N' ? 1 : 2))")) + end k = size(A, trans == 'N' ? 2 : 1) ccall(($(blasfunc(fname)), libblas), Void, (Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, @@ -740,7 +774,7 @@ for (fname, elty) in ((:dsyr2k_,:Float64), beta::($elty), C::StridedMatrix{$elty}) n = chksquare(C) nn = size(A, trans == 'N' ? 1 : 2) - if nn != n throw(DimensionMismatch("syr2k!")) end + if nn != n throw(DimensionMismatch("C has size ($n,$n), corresponding dimension of A is $nn")) end k = size(A, trans == 'N' ? 2 : 1) ccall(($(blasfunc(fname)), libblas), Void, (Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, @@ -776,7 +810,8 @@ for (fname, elty1, elty2) in ((:zher2k_,:Complex128,:Float64), (:cher2k_,:Comple A::StridedVecOrMat{$elty1}, B::StridedVecOrMat{$elty1}, beta::($elty2), C::StridedMatrix{$elty1}) n = chksquare(C) - n == size(A, trans == 'N' ? 1 : 2) || throw(DimensionMismatch("her2k!")) + nn = size(A, trans == 'N' ? 1 : 2) + if nn != n throw(DimensionMismatch("C has size ($n,$n), corresponding dimension of A is $nn")) end k = size(A, trans == 'N' ? 2 : 1) ccall(($(blasfunc(fname)), libblas), Void, (Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, @@ -836,7 +871,9 @@ for (mmname, smname, elty) in alpha::$elty, A::StridedMatrix{$elty}, B::StridedMatrix{$elty}) m, n = size(B) k = chksquare(A) - k==(side == 'L' ? m : n) || throw(DimensionMismatch("size of A is $n, size(B)=($m,$n) and transa='$transa'")) + if k != (side == 'L' ? m : n) + throw(DimensionMismatch("size of A is $n, size(B)=($m,$n) and transa='$transa'")) + end ccall(($(blasfunc(smname)), libblas), Void, (Ref{UInt8}, Ref{UInt8}, Ref{UInt8}, Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, Ref{$elty}, Ptr{$elty}, @@ -856,10 +893,15 @@ end # module function copy!{T<:BlasFloat,Ti<:Integer}(dest::Array{T}, rdest::Union(UnitRange{Ti},Range{Ti}), src::Array{T}, rsrc::Union(UnitRange{Ti},Range{Ti})) - if minimum(rdest) < 1 || maximum(rdest) > length(dest) || minimum(rsrc) < 1 || maximum(rsrc) > length(src) - throw(BoundsError()) + if minimum(rdest) < 1 || maximum(rdest) > length(dest) + throw(BoundsError("Range out of bounds for dest, of length $(length(dest))")) + end + if minimum(rsrc) < 1 || maximum(rsrc) > length(src) + throw(BoundsError("Range out of bounds for src, of length $(length(src))")) + end + if length(rdest) != length(rsrc) + throw(DimensionMismatch("Ranges must be of the same length")) end - length(rdest)==length(rsrc) || throw(DimensionMismatch("Ranges must be of the same length")) BLAS.blascopy!(length(rsrc), pointer(src)+(first(rsrc)-1)*sizeof(T), step(rsrc), pointer(dest)+(first(rdest)-1)*sizeof(T), step(rdest)) dest From e7de8d89951fec9035148ff62a0104f429ea5392 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Sat, 30 May 2015 19:11:23 -0700 Subject: [PATCH 171/181] Prettified bunchkaufman and diagonal --- base/linalg/bunchkaufman.jl | 4 +++- base/linalg/diagonal.jl | 40 ++++++++++++++++++++++++++++--------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/base/linalg/bunchkaufman.jl b/base/linalg/bunchkaufman.jl index c72abbfbbdabb..86468ff961b60 100644 --- a/base/linalg/bunchkaufman.jl +++ b/base/linalg/bunchkaufman.jl @@ -14,7 +14,9 @@ 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 || throw(ArgumentError("Bunch-Kaufman decomposition is only valid for symmetric matrices")) + if !symmetric + throw(ArgumentError("Bunch-Kaufman decomposition is only valid for symmetric matrices")) + end LD, ipiv = LAPACK.sytrf!(char_uplo(uplo) , A) BunchKaufman(LD, ipiv, char_uplo(uplo), symmetric) end diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index 89b1675cc0f17..e8e88b94a96f2 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -14,14 +14,22 @@ convert{T}(::Type{UpperTriangular}, A::Diagonal{T}) = UpperTriangular(A) convert{T}(::Type{LowerTriangular}, A::Diagonal{T}) = LowerTriangular(A) function similar{T}(D::Diagonal, ::Type{T}, d::Tuple{Int,Int}) - d[1] == d[2] || throw(ArgumentError("Diagonal matrix must be square")) + if d[1] != d[2] + throw(ArgumentError("Diagonal matrix must be square")) + end return Diagonal{T}(Array(T,d[1])) 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 ? throw(ArgumentError("dimension must be ≥ 1, got $d")) : (d<=2 ? length(D.diag) : 1) + +function size(D::Diagonal,d::Integer) + if d<1 + throw(ArgumentError("dimension must be ≥ 1, got $d")) + end + return d<=2 ? length(D.diag) : 1 +end fill!(D::Diagonal, x) = (fill!(D.diag, x); D) @@ -64,19 +72,27 @@ Ac_mul_B!(A::Diagonal,B::AbstractMatrix)= scale!(conj(A.diag),B) /(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag ./ Db.diag ) function A_ldiv_B!{T}(D::Diagonal{T}, v::AbstractVector{T}) - length(v)==length(D.diag) || throw(DimensionMismatch()) + if length(v) != length(D.diag) + throw(DimensionMismatch("diagonal matrix is $(length(D.diag)) by $(length(D.diag)) but right hand side has $(length(v)) rows")) + end for i=1:length(D.diag) d = D.diag[i] - d==zero(T) && throw(SingularException(i)) + if d == zero(T) + throw(SingularException(i)) + end v[i] *= inv(d) end v end function A_ldiv_B!{T}(D::Diagonal{T}, V::AbstractMatrix{T}) - size(V,1)==length(D.diag) || throw(DimensionMismatch()) + if size(V,1) != length(D.diag) + throw(DimensionMismatch("diagonal matrix is $(length(D.diag)) by $(length(D.diag)) but right hand side has $(size(V,1)) rows")) + end for i=1:length(D.diag) d = D.diag[i] - d==zero(T) && throw(SingularException(i)) + if d == zero(T) + throw(SingularException(i)) + end V[i,:] *= inv(d) end V @@ -103,12 +119,16 @@ sqrtm(D::Diagonal) = Diagonal(sqrt(D.diag)) #Linear solver function A_ldiv_B!(D::Diagonal, B::StridedVecOrMat) m, n = size(B, 1), size(B, 2) - m == length(D.diag) || throw(DimensionMismatch("diagonal matrix is $(length(D.diag)) by $(length(D.diag)) but right hand side has $m rows")) + if m != length(D.diag) + throw(DimensionMismatch("diagonal matrix is $(length(D.diag)) by $(length(D.diag)) but right hand side has $m rows")) + end (m == 0 || n == 0) && return B for j = 1:n for i = 1:m di = D.diag[i] - di == 0 && throw(SingularException(i)) + if di == 0 + throw(SingularException(i)) + end B[i,j] /= di end end @@ -121,7 +141,9 @@ end function inv{T}(D::Diagonal{T}) Di = similar(D.diag) for i = 1:length(D.diag) - D.diag[i] == zero(T) && throw(SingularException(i)) + if D.diag[i] == zero(T) + throw(SingularException(i)) + end Di[i] = inv(D.diag[i]) end Diagonal(Di) From a8bf83ec551c91c07c964c224c0dd4af77285e5f Mon Sep 17 00:00:00 2001 From: kshyatt Date: Sun, 31 May 2015 16:00:50 -0700 Subject: [PATCH 172/181] Prettified arnoldi, chol, dense --- base/linalg/arnoldi.jl | 36 ++++++++++++++++++++++++++++-------- base/linalg/cholesky.jl | 4 +++- base/linalg/dense.jl | 17 ++++++++++++----- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/base/linalg/arnoldi.jl b/base/linalg/arnoldi.jl index baa981d3fbc81..f782a56f25a87 100644 --- a/base/linalg/arnoldi.jl +++ b/base/linalg/arnoldi.jl @@ -18,19 +18,25 @@ function eigs(A, B; isgeneral = B !== I sym = issym(A) && !iscmplx nevmax=sym ? n-1 : n-2 - nevmax > 0 || throw(ArgumentError("Input matrix A is too small. Use eigfact instead.")) + if nevmax <= 0 + throw(ArgumentError("Input matrix A is too small. Use eigfact instead.")) + end if nev > nevmax warn("Adjusting nev from $nev to $nevmax") nev = nevmax end - nev > 0 || throw(ArgumentError("requested number of eigenvalues (nev) must be ≥ 1, got $nev")) + if nev <= 0 + throw(ArgumentError("requested number of eigenvalues (nev) must be ≥ 1, got $nev")) + end ncvmin = nev + (sym ? 1 : 2) if ncv < ncvmin warn("Adjusting ncv from $ncv to $ncvmin") ncv = ncvmin end ncv = blas_int(min(ncv, n)) - isgeneral && !isposdef(B) && throw(PosDefException(0)) + if isgeneral && !isposdef(B) + throw(PosDefException(0)) + end bmat = isgeneral ? "G" : "I" isshift = sigma !== nothing @@ -42,7 +48,9 @@ function eigs(A, B; 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")) + if which == :BE && !sym + throw(ArgumentError("which=:BE only possible for real symmetric problem")) + end 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 @@ -57,8 +65,12 @@ function eigs(A, B; sigma = isshift ? convert(T,sigma) : zero(T) if !isempty(v0) - length(v0)==n || throw(DimensionMismatch()) - eltype(v0)==T || throw(ArgumentError("starting vector must have element type $T, got $(eltype(v0))")) + if length(v0) != n + throw(DimensionMismatch()) + end + if eltype(v0) != T + throw(ArgumentError("starting vector must have element type $T, got $(eltype(v0))")) + end end whichstr = "LM" @@ -72,10 +84,18 @@ function eigs(A, B; whichstr = (!sym ? "SR" : "SA") end if which == :LI - whichstr = (!sym ? "LI" : throw(ArgumentError("largest imaginary is meaningless for symmetric eigenvalue problems"))) + if !sym + whichstr = "LI" + else + throw(ArgumentError("largest imaginary is meaningless for symmetric eigenvalue problems")) + end end if which == :SI - whichstr = (!sym ? "SI" : throw(ArgumentError("smallest imaginary is meaningless for symmetric eigenvalue problems"))) + if !sym + whichstr = "SI" + else + throw(ArgumentError("smallest imaginary is meaningless for symmetric eigenvalue problems")) + end end # Refer to ex-*.doc files in ARPACK/DOCUMENTS for calling sequence diff --git a/base/linalg/cholesky.jl b/base/linalg/cholesky.jl index 539d87de11d5d..e4b40d8a64294 100644 --- a/base/linalg/cholesky.jl +++ b/base/linalg/cholesky.jl @@ -85,7 +85,9 @@ function chol{T}(A::AbstractMatrix{T}, uplo::Union(Type{Val{:L}}, Type{Val{:U}}) end function chol!(x::Number, uplo) rx = real(x) - rx == abs(x) || throw(DomainError()) + if rx != abs(x) + throw(DomainError("x must be positive semidefinite")) + end rxr = sqrt(rx) convert(promote_type(typeof(x), typeof(rxr)), rxr) end diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index 7e597223cda2e..b50e12f82f230 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -56,7 +56,9 @@ function mapreduce_seq_impl{T<:BlasComplex}(::Abs2Fun, ::AddFun, a::Union(Array{ end function norm{T<:BlasFloat, TI<:Integer}(x::StridedVector{T}, rx::Union(UnitRange{TI},Range{TI})) - (minimum(rx) < 1 || maximum(rx) > length(x)) && throw(BoundsError()) + if minimum(rx) < 1 || maximum(rx) > length(x) + throw(BoundsError()) + end BLAS.nrm2(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx)) end @@ -168,8 +170,9 @@ kron(a::Vector, b::Matrix)=kron(reshape(a,length(a),1),b) ^(A::Matrix, p::Integer) = p < 0 ? inv(A^-p) : Base.power_by_squaring(A,p) function ^(A::Matrix, p::Number) - isinteger(p) && return A^Integer(real(p)) - + if isinteger(p) + return A^Integer(real(p)) + end chksquare(A) v, X = eig(A) any(v.<0) && (v = complex(v)) @@ -276,7 +279,9 @@ function rcswap!{T<:Number}(i::Integer, j::Integer, X::StridedMatrix{T}) end function sqrtm{T<:Real}(A::StridedMatrix{T}) - issym(A) && return sqrtm(Symmetric(A)) + if issym(A) + return sqrtm(Symmetric(A)) + end n = chksquare(A) SchurF = schurfact(complex(A)) R = full(sqrtm(UpperTriangular(SchurF[:T]))) @@ -284,7 +289,9 @@ function sqrtm{T<:Real}(A::StridedMatrix{T}) all(imag(retmat) .== 0) ? real(retmat) : retmat end function sqrtm{T<:Complex}(A::StridedMatrix{T}) - ishermitian(A) && return sqrtm(Hermitian(A)) + if ishermitian(A) + return sqrtm(Hermitian(A)) + end n = chksquare(A) SchurF = schurfact(A) R = full(sqrtm(UpperTriangular(SchurF[:T]))) From ae49e06b92299391d451a5eb022058e853426e7a Mon Sep 17 00:00:00 2001 From: kshyatt Date: Sun, 31 May 2015 16:43:10 -0700 Subject: [PATCH 173/181] Prettied lu and ldlt --- base/linalg/ldlt.jl | 4 +++- base/linalg/lu.jl | 28 +++++++++++++++++++--------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/base/linalg/ldlt.jl b/base/linalg/ldlt.jl index b38ea161b183c..99392d33823f9 100644 --- a/base/linalg/ldlt.jl +++ b/base/linalg/ldlt.jl @@ -34,7 +34,9 @@ factorize(S::SymTridiagonal) = ldltfact(S) function A_ldiv_B!{T}(S::LDLt{T,SymTridiagonal{T}}, B::AbstractVecOrMat{T}) n, nrhs = size(B, 1), size(B, 2) - size(S,1) == n || throw(DimensionMismatch()) + if size(S,1) != n + throw(DimensionMismatch("Matrix has dimensions $(size(S)) but right hand side has first dimension $n")) + end d = S.data.dv l = S.data.ev @inbounds begin diff --git a/base/linalg/lu.jl b/base/linalg/lu.jl index 31f0995ecab94..a7c73f20e7325 100644 --- a/base/linalg/lu.jl +++ b/base/linalg/lu.jl @@ -119,18 +119,20 @@ function getindex{T,S<:StridedMatrix}(A::LU{T,S}, d::Symbol) L = tril!(A.factors[1:m, 1:min(m,n)]) for i = 1:min(m,n); L[i,i] = one(T); end return L - end - d == :U && return triu!(A.factors[1:min(m,n), 1:n]) - d == :p && return ipiv2perm(A.ipiv, m) - if d == :P + elseif d == :U + return triu!(A.factors[1:min(m,n), 1:n]) + elseif d == :p + return ipiv2perm(A.ipiv, m) + elseif d == :P p = A[:p] P = zeros(T, m, m) for i in 1:m P[i,p[i]] = one(T) end return P + else + throw(KeyError(d)) end - throw(KeyError(d)) end A_ldiv_B!{T<:BlasFloat, S<:StridedMatrix}(A::LU{T, S}, B::StridedVecOrMat{T}) = @assertnonsingular LAPACK.getrs!('N', A.factors, A.ipiv, B) A.info @@ -167,7 +169,9 @@ end function logdet{T<:Real,S}(A::LU{T,S}) d,s = logdet2(A) - s>=0 || error("DomainError: determinant is negative") + if s < 0 + throw(DomainError("Determinant is negative")) + end d end @@ -260,7 +264,9 @@ factorize(A::Tridiagonal) = lufact(A) # See dgtts2.f function A_ldiv_B!{T}(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) n = size(A,1) - n == size(B,1) || throw(DimensionMismatch()) + if n != size(B,1) + throw(DimensionMismatch("Matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows")) + end nrhs = size(B,2) dl = A.factors.dl d = A.factors.d @@ -289,7 +295,9 @@ end function At_ldiv_B!{T}(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) n = size(A,1) - n == size(B,1) || throw(DimensionMismatch("")) + if n != size(B,1) + throw(DimensionMismatch("Matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows")) + end nrhs = size(B,2) dl = A.factors.dl d = A.factors.d @@ -322,7 +330,9 @@ end # Ac_ldiv_B!{T<:Real}(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) = At_ldiv_B!(A,B) function Ac_ldiv_B!{T}(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) n = size(A,1) - n == size(B,1) || throw(DimensionMismatch("")) + if n != size(B,1) + throw(DimensionMismatch("Matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows")) + end nrhs = size(B,2) dl = A.factors.dl d = A.factors.d From 8473f4aaa50dfe641ddba18e48b422fa4bffce39 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Sun, 31 May 2015 16:43:21 -0700 Subject: [PATCH 174/181] Prettied generic and givens --- base/linalg/generic.jl | 98 ++++++++++++++++++++++++++++++------------ base/linalg/givens.jl | 16 +++++-- 2 files changed, 83 insertions(+), 31 deletions(-) diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index 8989c8888ed0f..7b0e828a18d35 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -158,13 +158,20 @@ vecnormp(x, p) = generic_vecnormp(x, p) function vecnorm(itr, p::Real=2) isempty(itr) && return float(real(zero(eltype(itr)))) - p == 2 && return vecnorm2(itr) - p == 1 && return vecnorm1(itr) - p == Inf && return vecnormInf(itr) - p == 0 && return convert(typeof(float(real(zero(eltype(itr))))), - countnz(itr)) - p == -Inf && return vecnormMinusInf(itr) - vecnormp(itr,p) + if p == 2 + return vecnorm2(itr) + elseif p == 1 + return vecnorm1(itr) + elseif p == Inf + return vecnormInf(itr) + elseif p == 0 + return convert(typeof(float(real(zero(eltype(itr))))), + countnz(itr)) + elseif p == -Inf + return vecnormMinusInf(itr) + else + vecnormp(itr,p) + end end vecnorm(x::Number, p::Real=2) = p == 0 ? real(x==0 ? zero(x) : one(x)) : abs(x) @@ -209,10 +216,15 @@ function normInf{T}(A::AbstractMatrix{T}) return convert(Tnorm, nrm) end function norm{T}(A::AbstractMatrix{T}, p::Real=2) - p == 2 && return norm2(A) - p == 1 && return norm1(A) - p == Inf && return normInf(A) - throw(ArgumentError("invalid p-norm p=$p. Valid: 1, 2, Inf")) + if p == 2 + return norm2(A) + elseif p == 1 + return norm1(A) + elseif p == Inf + return normInf(A) + else + throw(ArgumentError("invalid p-norm p=$p. Valid: 1, 2, Inf")) + end end norm(x::Number, p::Real=2) = @@ -220,7 +232,9 @@ norm(x::Number, p::Real=2) = function vecdot(x::AbstractVector, y::AbstractVector) lx = length(x) - lx==length(y) || throw(DimensionMismatch()) + if lx != length(y) + throw(DimensionMismatch("Vector x has length $lx, but vector y has length $(length(y))")) + end if lx == 0 return dot(zero(eltype(x)), zero(eltype(y))) end @@ -234,21 +248,29 @@ end function vecdot(x, y) # arbitrary iterables ix = start(x) if done(x, ix) - isempty(y) || throw(DimensionMismatch()) + if !isempty(y) + throw(DimensionMismatch("x and y are of different lengths!")) + end return dot(zero(eltype(x)), zero(eltype(y))) end iy = start(y) - done(y, iy) && throw(DimensionMismatch()) + if done(y, iy) + throw(DimensionMismatch("x and y are of different lengths!")) + end (vx, ix) = next(x, ix) (vy, iy) = next(y, iy) s = dot(vx, vy) while !done(x, ix) - done(y, iy) && throw(DimensionMismatch()) + if done(y, iy) + throw(DimensionMismatch("x and y are of different lengths!")) + end (vx, ix) = next(x, ix) (vy, iy) = next(y, iy) s += dot(vx, vy) end - !done(y, iy) && throw(DimensionMismatch()) + if !done(y, iy) + throw(DimensionMismatch("x and y are of different lengths!")) + end return s end @@ -286,7 +308,9 @@ function inv{T}(A::AbstractMatrix{T}) end function \{T}(A::AbstractMatrix{T}, B::AbstractVecOrMat{T}) - size(A,1) == size(B,1) || throw(DimensionMismatch("LHS and RHS should have the same number of rows. LHS has $(size(A,1)) rows, but RHS has $(size(B,1)) rows.")) + if size(A,1) != size(B,1) + throw(DimensionMismatch("LHS and RHS should have the same number of rows. LHS has $(size(A,1)) rows, but RHS has $(size(B,1)) rows.")) + end factorize(A)\B end function \{TA,TB}(A::AbstractMatrix{TA}, B::AbstractVecOrMat{TB}) @@ -310,7 +334,9 @@ condskeel{T<:Integer}(A::AbstractMatrix{T}, x::AbstractVector, p::Real=Inf) = no function issym(A::AbstractMatrix) m, n = size(A) - m==n || return false + if m != n + return false + end for i = 1:(n-1), j = (i+1):n if A[i,j] != transpose(A[j,i]) return false @@ -323,7 +349,9 @@ issym(x::Number) = true function ishermitian(A::AbstractMatrix) m, n = size(A) - m==n || return false + if m != n + return false + end for i = 1:n, j = i:n if A[i,j] != ctranspose(A[j,i]) return false @@ -397,14 +425,18 @@ end # for BlasFloat Arrays) function axpy!(alpha, x::AbstractArray, y::AbstractArray) n = length(x) - n==length(y) || throw(DimensionMismatch()) + if n != length(y) + throw(DimensionMismatch("x has length $n, but y has length $(length(y))")) + end for i = 1:n @inbounds y[i] += alpha * x[i] end y end function axpy!{Ti<:Integer,Tj<:Integer}(alpha, x::AbstractArray, rx::AbstractArray{Ti}, y::AbstractArray, ry::AbstractArray{Tj}) - length(x)==length(y) || throw(DimensionMismatch()) + if length(x) != length(y) + throw(DimensionMismatch("x has length $(length(x)), but y has length $(length(y))")) + end if minimum(rx) < 1 || maximum(rx) > length(x) || minimum(ry) < 1 || maximum(ry) > length(y) || length(rx) != length(ry) throw(BoundsError()) end @@ -417,8 +449,12 @@ end # Elementary reflection similar to LAPACK. The reflector is not Hermitian but ensures that tridiagonalization of Hermitian matrices become real. See lawn72 function elementaryLeft!(A::AbstractMatrix, row::Integer, col::Integer) m, n = size(A) - 1 <= row <= m || throw(BoundsError("row cannot be less than one or larger than $(size(A,1))")) - 1 <= col <= n || throw(BoundsError("col cannot be less than one or larger than $(size(A,2))")) + if !(1 <= row <= m) + throw(BoundsError("row cannot be less than one or larger than $(size(A,1))")) + end + if !(1 <= col <= n) + throw(BoundsError("col cannot be less than one or larger than $(size(A,2))")) + end @inbounds begin ξ1 = A[row,col] normu = abs2(ξ1) @@ -438,9 +474,15 @@ function elementaryLeft!(A::AbstractMatrix, row::Integer, col::Integer) end function elementaryRight!(A::AbstractMatrix, row::Integer, col::Integer) m, n = size(A) - 1 <= row <= m || throw(BoundsError("row cannot be less than one or larger than $(size(A,1))")) - 1 <= col <= n || throw(BoundsError("col cannot be less than one or larger than $(size(A,2))")) - row <= col || error("col cannot be larger than row") + if !(1 <= row <= m) + throw(BoundsError("row cannot be less than one or larger than $(size(A,1))")) + end + if !(1 <= col <= n) + throw(BoundsError("col cannot be less than one or larger than $(size(A,2))")) + end + if row > col + throw(ArgumentError("row cannot be larger than col")) + end @inbounds begin ξ1 = A[row,col] normu = abs2(ξ1) @@ -460,7 +502,9 @@ function elementaryRight!(A::AbstractMatrix, row::Integer, col::Integer) end function elementaryRightTrapezoid!(A::AbstractMatrix, row::Integer) m, n = size(A) - 1 <= row <= m || throw(BoundsError("row cannot be less than one or larger than $(size(A,1))")) + if !(1 <= row <= m) + throw(BoundsError("row cannot be less than one or larger than $(size(A,1))")) + end @inbounds begin ξ1 = A[row,row] normu = abs2(A[row,row]) diff --git a/base/linalg/givens.jl b/base/linalg/givens.jl index 06ff7c8a91967..7e1f9cc3fcea4 100644 --- a/base/linalg/givens.jl +++ b/base/linalg/givens.jl @@ -221,13 +221,17 @@ function givensAlgorithm{T<:FloatingPoint}(f::Complex{T}, g::Complex{T}) end function givens{T}(f::T, g::T, i1::Integer, i2::Integer) - i1 < i2 || throw(ArgumentError("second index must be larger than the first")) + if i1 >= i2 + throw(ArgumentError("second index must be larger than the first")) + end 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 || throw(ArgumentError("second index must be larger than the first")) + if i1 >= i2 + throw(ArgumentError("second index must be larger than the first")) + end c, s, r = givensAlgorithm(A[i1,col], A[i2,col]) Givens(i1, i2, convert(T, c), convert(T, s)), r end @@ -237,7 +241,9 @@ getindex(G::Givens, i::Integer, j::Integer) = i == j ? (i == G.i1 || i == G.i2 ? A_mul_B!(G1::Givens, G2::Givens) = error("Operation not supported. Consider *") function A_mul_B!(G::Givens, A::AbstractMatrix) m, n = size(A) - G.i2 <= m || throw(DimensionMismatch("column indices for rotation are outside the matrix")) + if G.i2 > m + throw(DimensionMismatch("column indices for rotation are outside the matrix")) + end @inbounds @simd for i = 1:n tmp = G.c*A[G.i1,i] + G.s*A[G.i2,i] A[G.i2,i] = G.c*A[G.i2,i] - conj(G.s)*A[G.i1,i] @@ -247,7 +253,9 @@ function A_mul_B!(G::Givens, A::AbstractMatrix) end function A_mul_Bc!(A::AbstractMatrix, G::Givens) m, n = size(A) - G.i2 <= n || throw(DimensionMismatch("column indices for rotation are outside the matrix")) + if G.i2 > n + throw(DimensionMismatch("column indices for rotation are outside the matrix")) + end @inbounds @simd for i = 1:m tmp = G.c*A[i,G.i1] + conj(G.s)*A[i,G.i2] A[i,G.i2] = G.c*A[i,G.i2] - G.s*A[i,G.i1] From 155f80fae66da3f40713ebb707aa11cf5096b8b7 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Sun, 31 May 2015 16:59:34 -0700 Subject: [PATCH 175/181] Prettified matmul --- base/linalg/matmul.jl | 108 +++++++++++++++++++++++++++++++----------- 1 file changed, 81 insertions(+), 27 deletions(-) diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index 600e8002ff336..d4f304bab23fa 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -9,7 +9,9 @@ arithtype(::Type{Bool}) = Int function scale!(C::AbstractMatrix, A::AbstractMatrix, b::AbstractVector) m, n = size(A) p, q = size(C) - n == length(b) && p == m && q == n || throw(DimensionMismatch()) + if n != length(b) || p != m || q != n + throw(DimensionMismatch()) + end @inbounds for j = 1:n bj = b[j] for i = 1:m @@ -22,7 +24,9 @@ end function scale!(C::AbstractMatrix, b::AbstractVector, A::AbstractMatrix) m, n = size(A) p, q = size(C) - m == length(b) && p == m && q == n || throw(DimensionMismatch()) + if m != length(b) || p != m || q != n + throw(DimensionMismatch()) + end @inbounds for j = 1:n, i = 1:m C[i,j] = A[i,j]*b[i] end @@ -197,10 +201,18 @@ end function gemv!{T<:BlasFloat}(y::StridedVector{T}, tA::Char, A::StridedVecOrMat{T}, x::StridedVector{T}) mA, nA = lapack_size(tA, A) - nA == length(x) || throw(DimensionMismatch()) - mA == length(y) || throw(DimensionMismatch()) - mA == 0 && return y - nA == 0 && return fill!(y,0) + if nA != length(x) + throw(DimensionMismatch()) + end + if mA != length(y) + throw(DimensionMismatch()) + end + if mA == 0 + return y + end + if nA == 0 + return fill!(y,0) + end stride(A, 1) == 1 && stride(A, 2) >= size(A, 1) && return BLAS.gemv!(tA, one(T), A, x, zero(T), y) return generic_matvecmul!(y, tA, A, x) end @@ -214,12 +226,22 @@ function syrk_wrapper!{T<:BlasFloat}(C::StridedMatrix{T}, tA::Char, A::StridedVe (mA, nA) = size(A,1), size(A,2) tAt = 'T' end - nC == mA || throw(DimensionMismatch("output matrix has size: $(nC), but should have size $(mA)")) - if mA == 0 || nA == 0; return fill!(C,0); end - if mA == 2 && nA == 2; return matmul2x2!(C,tA,tAt,A,A); end - if mA == 3 && nA == 3; return matmul3x3!(C,tA,tAt,A,A); end + if nC != mA + throw(DimensionMismatch("output matrix has size: $(nC), but should have size $(mA)")) + end + if mA == 0 || nA == 0 + return fill!(C,0) + end + if mA == 2 && nA == 2 + return matmul2x2!(C,tA,tAt,A,A) + end + if mA == 3 && nA == 3 + return matmul3x3!(C,tA,tAt,A,A) + end - stride(A, 1) == 1 && stride(A, 2) >= size(A, 1) && return copytri!(BLAS.syrk!('U', tA, one(T), A, zero(T), C), 'U') + if stride(A, 1) == 1 && stride(A, 2) >= size(A, 1) + return copytri!(BLAS.syrk!('U', tA, one(T), A, zero(T), C), 'U') + end return generic_matmatmul!(C, tA, tAt, A, A) end @@ -232,15 +254,25 @@ function herk_wrapper!{T<:BlasReal}(C::Union(StridedMatrix{T}, StridedMatrix{Com (mA, nA) = size(A,1), size(A,2) tAt = 'C' end - nC == mA || throw(DimensionMismatch("output matrix has size: $(nC), but should have size $(mA)")) - if mA == 0 || nA == 0; return fill!(C,0); end - if mA == 2 && nA == 2; return matmul2x2!(C,tA,tAt,A,A); end - if mA == 3 && nA == 3; return matmul3x3!(C,tA,tAt,A,A); end + if nC != mA + throw(DimensionMismatch("output matrix has size: $(nC), but should have size $(mA)")) + end + if mA == 0 || nA == 0 + return fill!(C,0) + end + if mA == 2 && nA == 2 + return matmul2x2!(C,tA,tAt,A,A) + end + if mA == 3 && nA == 3 + return matmul3x3!(C,tA,tAt,A,A) + end # Result array does not need to be initialized as long as beta==0 # C = Array(T, mA, mA) - stride(A, 1) == 1 && stride(A, 2) >= size(A, 1) && return copytri!(BLAS.herk!('U', tA, one(T), A, zero(T), C), 'U', true) + if stride(A, 1) == 1 && stride(A, 2) >= size(A, 1) + return copytri!(BLAS.herk!('U', tA, one(T), A, zero(T), C), 'U', true) + end return generic_matmatmul!(C,tA, tAt, A, A) end @@ -259,16 +291,26 @@ function gemm_wrapper!{T<:BlasFloat}(C::StridedVecOrMat{T}, tA::Char, tB::Char, mA, nA = lapack_size(tA, A) mB, nB = lapack_size(tB, B) - nA==mB || throw(DimensionMismatch("*")) + if nA != mB + throw(DimensionMismatch("A has dimensions ($mA,$nA) but B has dimensions ($mB, $nB)")) + end if mA == 0 || nA == 0 || nB == 0 - size(C) == (mA, nB) || throw(DimensionMismatch()) + if size(C) != (mA, nB) + throw(DimensionMismatch("C has dimensions $(size(C)), should have ($mA,$nB)")) + end return fill!(C,0) end - if mA == 2 && nA == 2 && nB == 2; return matmul2x2!(C,tA,tB,A,B); end - if mA == 3 && nA == 3 && nB == 3; return matmul3x3!(C,tA,tB,A,B); end + if mA == 2 && nA == 2 && nB == 2 + return matmul2x2!(C,tA,tB,A,B) + end + if mA == 3 && nA == 3 && nB == 3 + return matmul3x3!(C,tA,tB,A,B) + end - stride(A, 1) == stride(B, 1) == 1 && stride(A, 2) >= size(A, 1) && stride(B, 2) >= size(B, 1) && return BLAS.gemm!(tA, tB, one(T), A, B, zero(T), C) + if stride(A, 1) == stride(B, 1) == 1 && stride(A, 2) >= size(A, 1) && stride(B, 2) >= size(B, 1) + return BLAS.gemm!(tA, tB, one(T), A, B, zero(T), C) + end generic_matmatmul!(C, tA, tB, A, B) end @@ -305,8 +347,12 @@ end function generic_matvecmul!{T,S,R}(C::AbstractVector{R}, tA, A::AbstractVecOrMat{T}, B::AbstractVector{S}) mB = length(B) mA, nA = lapack_size(tA, A) - mB==nA || throw(DimensionMismatch("*")) - mA==length(C) || throw(DimensionMismatch("*")) + if mB != nA + throw(DimensionMismatch("Matrix A has dimensions ($mA,$nA), vector B has length $mB")) + end + if mA != length(C) + throw(DimensionMismatch("Result C has length $(length(C)), needs length $mA")) + end z = zero(R) Astride = size(A, 1) @@ -357,11 +403,19 @@ const Cbuf = Array(UInt8, tilebufsize) function generic_matmatmul!{T,S,R}(C::AbstractVecOrMat{R}, tA, tB, A::AbstractVecOrMat{T}, B::AbstractVecOrMat{S}) mA, nA = lapack_size(tA, A) mB, nB = lapack_size(tB, B) - mB==nA || throw(DimensionMismatch("*")) - if size(C,1) != mA || size(C,2) != nB; throw(DimensionMismatch("*")); end + if mB != nA + throw(DimensionMismatch("Matrix A has dimensions ($mA, $nB), matrix B has dimensions ($mB, $nB)")) + end + if size(C,1) != mA || size(C,2) != nB + throw(DimensionMismatch("Result C has dimensions $(size(C)), needs ($mA, $nB)")) + end - if mA == nA == nB == 2; return matmul2x2!(C, tA, tB, A, B); end - if mA == nA == nB == 3; return matmul3x3!(C, tA, tB, A, B); end + if mA == nA == nB == 2 + return matmul2x2!(C, tA, tB, A, B) + end + if mA == nA == nB == 3 + return matmul3x3!(C, tA, tB, A, B) + end @inbounds begin if isbits(R) From fd09a9f1ef427629a6d01d91d42ebce290555369 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Sun, 31 May 2015 17:09:25 -0700 Subject: [PATCH 176/181] prettied up qr --- base/linalg/qr.jl | 52 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/base/linalg/qr.jl b/base/linalg/qr.jl index 522e70f43bca7..83fe4e35ecd12 100644 --- a/base/linalg/qr.jl +++ b/base/linalg/qr.jl @@ -75,22 +75,33 @@ convert{T}(::Type{Factorization{T}}, A::QRPivoted) = convert(QRPivoted{T}, A) function getindex(A::QR, d::Symbol) m, n = size(A) - d == :R && return triu!(A.factors[1:min(m,n), 1:n]) - d == :Q && return getq(A) - throw(KeyError(d)) + if d == :R + return triu!(A.factors[1:min(m,n), 1:n]) + elseif d == :Q + return getq(A) + else + throw(KeyError(d)) + end end function getindex(A::QRCompactWY, d::Symbol) m, n = size(A) - d == :R && return triu!(A.factors[1:min(m,n), 1:n]) - d == :Q && return getq(A) - throw(KeyError(d)) + if d == :R + return triu!(A.factors[1:min(m,n), 1:n]) + elseif d == :Q + return getq(A) + else + throw(KeyError(d)) + end end function getindex{T}(A::QRPivoted{T}, d::Symbol) m, n = size(A) - d == :R && return triu!(A.factors[1:min(m,n), 1:n]) - d == :Q && return getq(A) - d == :p && return A.jpvt - if d == :P + if d == :R + return triu!(A.factors[1:min(m,n), 1:n]) + elseif d == :Q + return getq(A) + elseif d == :p + return A.jpvt + elseif d == :P p = A[:p] n = length(p) P = zeros(T, n, n) @@ -98,8 +109,9 @@ function getindex{T}(A::QRPivoted{T}, d::Symbol) P[p[i],i] = one(T) end return P + else + throw(KeyError(d)) end - throw(KeyError(d)) end # Type-stable interface to get Q @@ -146,7 +158,9 @@ A_mul_B!{T<:BlasFloat}(A::QRPackedQ{T}, B::StridedVecOrMat{T}) = LAPACK.ormqr!(' function A_mul_B!{T}(A::QRPackedQ{T}, B::AbstractVecOrMat{T}) mA, nA = size(A.factors) mB, nB = size(B,1), size(B,2) - mA == mB || throw(DimensionMismatch()) + if mA != mB + throw(DimensionMismatch("Matrix A has dimensions ($mA,$nA) but B has dimensions ($mB, $nB)")) + end Afactors = A.factors @inbounds begin for k = min(mA,nA):-1:1 @@ -199,7 +213,9 @@ Ac_mul_B!{T<:BlasComplex}(A::QRPackedQ{T}, B::StridedVecOrMat{T}) = LAPACK.ormqr function Ac_mul_B!{T}(A::QRPackedQ{T}, B::AbstractVecOrMat{T}) mA, nA = size(A.factors) mB, nB = size(B,1), size(B,2) - mA == mB || throw(DimensionMismatch()) + if mA != mB + throw(DimensionMismatch("Matrix A has dimensions ($mA,$nA) but B has dimensions ($mB, $nB)")) + end Afactors = A.factors @inbounds begin for k = 1:min(mA,nA) @@ -229,7 +245,9 @@ A_mul_B!(A::StridedVecOrMat, B::QRPackedQ) = LAPACK.ormqr!('R', 'N', B.factors, function A_mul_B!{T}(A::StridedMatrix{T},Q::QRPackedQ{T}) mQ, nQ = size(Q.factors) mA, nA = size(A,1), size(A,2) - nA == mQ || throw(DimensionMismatch()) + if nA != mQ + throw(DimensionMismatch("Matrix A has dimensions ($mA,$nA) but matrix Q has dimensions ($mQ, $nQ)")) + end Qfactors = Q.factors @inbounds begin for k = 1:min(mQ,nQ) @@ -262,7 +280,9 @@ A_mul_Bc!{T<:BlasComplex}(A::StridedVecOrMat{T}, B::QRPackedQ{T}) = LAPACK.ormqr function A_mul_Bc!{T}(A::AbstractMatrix{T},Q::QRPackedQ{T}) mQ, nQ = size(Q.factors) mA, nA = size(A,1), size(A,2) - nA == mQ || throw(DimensionMismatch()) + if nA != mQ + throw(DimensionMismatch("Matrix A has dimensions ($mA,$nA) but matrix Q has dimensions ($mQ, $nQ)")) + end Qfactors = Q.factors @inbounds begin for k = min(mQ,nQ):-1:1 @@ -290,7 +310,7 @@ function A_mul_Bc{TA,TB}(A::AbstractArray{TA}, B::Union(QRCompactWYQ{TB},QRPacke elseif size(A,2) == size(B.factors,2) return A_mul_Bc!([A zeros(TAB, size(A, 1), size(B.factors, 1) - size(B.factors, 2))], BB) else - throw(DimensionMismatch()) + throw(DimensionMismatch("Matrix A has dimensions $(size(A)) but matrix B has dimensions $(size(B))")) end end From 2f682c638016f384d84e601604597645e5b836fd Mon Sep 17 00:00:00 2001 From: kshyatt Date: Sun, 31 May 2015 17:20:26 -0700 Subject: [PATCH 177/181] Prettied svd and schur --- base/linalg/schur.jl | 38 ++++++++++++++++++++++++----------- base/linalg/svd.jl | 48 +++++++++++++++++++++++++++----------------- 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/base/linalg/schur.jl b/base/linalg/schur.jl index c169965a45584..5c7204ee1ff96 100644 --- a/base/linalg/schur.jl +++ b/base/linalg/schur.jl @@ -17,10 +17,15 @@ function schurfact{T}(A::StridedMatrix{T}) end function getindex(F::Schur, d::Symbol) - (d == :T || d == :Schur) && return F.T - (d == :Z || d == :vectors) && return F.Z - d == :values && return F.values - throw(KeyError(d)) + if d == :T || d == :Schur + return F.T + elseif d == :Z || d == :vectors + return F.Z + elseif d == :values + return F.values + else + throw(KeyError(d)) + end end function schur(A::StridedMatrix) @@ -57,14 +62,23 @@ ordschur!{Ty<:BlasFloat}(gschur::GeneralizedSchur{Ty}, select::Union(Vector{Bool ordschur{Ty<:BlasFloat}(gschur::GeneralizedSchur{Ty}, select::Union(Vector{Bool},BitVector)) = ordschur(gschur.S, gschur.T, gschur.Q, gschur.Z, select) function getindex(F::GeneralizedSchur, d::Symbol) - d == :S && return F.S - d == :T && return F.T - d == :alpha && return F.alpha - d == :beta && return F.beta - d == :values && return F.alpha./F.beta - (d == :Q || d == :left) && return F.Q - (d == :Z || d == :right) && return F.Z - throw(KeyError(d)) + if d == :S + return F.S + elseif d == :T + return F.T + elseif d == :alpha + return F.alpha + elseif d == :beta + return F.beta + elseif d == :values + return F.alpha./F.beta + elseif d == :Q || d == :left + return F.Q + elseif d == :Z || d == :right + return F.Z + else + throw(KeyError(d)) + end end function schur(A::StridedMatrix, B::StridedMatrix) diff --git a/base/linalg/svd.jl b/base/linalg/svd.jl index 097b171c6b197..0afc9c9d599eb 100644 --- a/base/linalg/svd.jl +++ b/base/linalg/svd.jl @@ -31,11 +31,17 @@ function svd(A::Union(Number, AbstractArray); thin::Bool=true) end function getindex(F::SVD, d::Symbol) - d == :U && return F.U - d == :S && return F.S - d == :Vt && return F.Vt - d == :V && return F.Vt' - throw(KeyError(d)) + if d == :U + return F.U + elseif d == :S + return F.S + elseif d == :Vt + return F.Vt + elseif d == :V + return F.Vt' + else + throw(KeyError(d)) + end end svdvals!{T<:BlasFloat}(A::StridedMatrix{T}) = any([size(A)...].==0) ? zeros(T, 0) : LAPACK.gesdd!('N', A)[2] @@ -85,21 +91,26 @@ function svd(A::AbstractMatrix, B::AbstractMatrix) end function getindex{T}(obj::GeneralizedSVD{T}, d::Symbol) - d == :U && return obj.U - d == :V && return obj.V - d == :Q && return obj.Q - (d == :alpha || d == :a) && return obj.a - (d == :beta || d == :b) && return obj.b - (d == :vals || d == :S) && return obj.a[1:obj.k + obj.l] ./ obj.b[1:obj.k + obj.l] - if d == :D1 + if d == :U + return obj.U + elseif d == :V + return obj.V + elseif d == :Q + return obj.Q + elseif d == :alpha || d == :a + return obj.a + elseif d == :beta || d == :b + return obj.b + elseif d == :vals || d == :S + return obj.a[1:obj.k + obj.l] ./ obj.b[1:obj.k + obj.l] + elseif d == :D1 m = size(obj.U, 1) if m - obj.k - obj.l >= 0 return [eye(T, obj.k) zeros(T, obj.k, obj.l); zeros(T, obj.l, obj.k) diagm(obj.a[obj.k + 1:obj.k + obj.l]); zeros(T, m - obj.k - obj.l, obj.k + obj.l)] else return [eye(T, m, obj.k) [zeros(T, obj.k, m - obj.k); diagm(obj.a[obj.k + 1:m])] zeros(T, m, obj.k + obj.l - m)] end - end - if d == :D2 + elseif d == :D2 m = size(obj.U, 1) p = size(obj.V, 1) if m - obj.k - obj.l >= 0 @@ -107,13 +118,14 @@ function getindex{T}(obj::GeneralizedSVD{T}, d::Symbol) else return [zeros(T, p, obj.k) [diagm(obj.b[obj.k + 1:m]); zeros(T, obj.k + p - m, m - obj.k)] [zeros(T, m - obj.k, obj.k + obj.l - m); eye(T, obj.k + p - m, obj.k + obj.l - m)]] end - end - d == :R && return obj.R - if d == :R0 + elseif d == :R + return obj.R + elseif d == :R0 n = size(obj.Q, 1) return [zeros(T, obj.k + obj.l, n - obj.k - obj.l) obj.R] + else + throw(KeyError(d)) end - throw(KeyError(d)) end function svdvals!{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) From 7cec3cdd9397994c88ae128135516973d7274913 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Sun, 31 May 2015 18:56:19 -0700 Subject: [PATCH 178/181] Prettied triangular --- base/linalg/triangular.jl | 132 ++++++++++++++++++++++++++++---------- 1 file changed, 97 insertions(+), 35 deletions(-) diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index 81a97c01dbdbc..ea984dd5717cc 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -23,8 +23,12 @@ 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("Triangular matrix must be square")) - length(dims) == 2 || throw(ArgumentError("Triangular matrix must have two dimensions")) + if dims[1] != dims[2] + throw(ArgumentError("Triangular matrix must be square")) + end + if length(dims) != 2 + throw(ArgumentError("Triangular matrix must have two dimensions")) + end B = similar(A.data, Tnew, dims) return $t(B) end @@ -226,9 +230,9 @@ for (t, uploc, isunitc) in ((:LowerTriangular, 'L', 'N'), # Condition numbers function cond{T<:BlasFloat,S}(A::$t{T,S}, p::Real=2) chksquare(A) - if p==1 + if p == 1 return inv(LAPACK.trcon!('O', $uploc, $isunitc, A.data)) - elseif p==Inf + elseif p == Inf return inv(LAPACK.trcon!('I', $uploc, $isunitc, A.data)) else #use fallback return cond(full(A), p) @@ -315,7 +319,9 @@ 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 does not fit")) + if m != size(A, 1) + throw(DimensionMismatch("left and right hand side does not fit")) + end for j = 1:n for i = 1:m Bij = A.data[i,i]*B[i,j] @@ -329,7 +335,9 @@ 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 does not fit")) + if m != size(A, 1) + throw(DimensionMismatch("left and right hand side does not fit")) + end for j = 1:n for i = 1:m Bij = B[i,j] @@ -344,7 +352,9 @@ 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 does not fit")) + if m != size(A, 1) + throw(DimensionMismatch("left and right hand side does not fit")) + end for j = 1:n for i = m:-1:1 Bij = A.data[i,i]*B[i,j] @@ -358,7 +368,9 @@ 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 does not fit")) + if m != size(A, 1) + throw(DimensionMismatch("left and right hand side does not fit")) + end for j = 1:n for i = m:-1:1 Bij = B[i,j] @@ -373,7 +385,9 @@ 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 does not fit")) + if m != size(A, 1) + throw(DimensionMismatch("left and right hand side does not fit")) + end for j = 1:n for i = m:-1:1 Bij = A.data[i,i]*B[i,j] @@ -387,7 +401,9 @@ 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 does not fit")) + if m != size(A, 1) + throw(DimensionMismatch("left and right hand side does not fit")) + end for j = 1:n for i = m:-1:1 Bij = B[i,j] @@ -402,7 +418,9 @@ 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 does not fit")) + if m != size(A, 1) + throw(DimensionMismatch("left and right hand side does not fit")) + end for j = 1:n for i = 1:m Bij = A.data[i,i]*B[i,j] @@ -416,7 +434,9 @@ 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 does not fit")) + if m != size(A, 1) + throw(DimensionMismatch("left and right hand side does not fit")) + end for j = 1:n for i = 1:m Bij = B[i,j] @@ -431,7 +451,9 @@ end function A_mul_B!(A::StridedMatrix, B::UpperTriangular) m, n = size(A) - size(B, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) + if size(B, 1) != n + throw(DimensionMismatch("left and right hand side does not fit")) + end for i = 1:m for j = n:-1:1 Aij = A[i,j]*B[j,j] @@ -445,7 +467,9 @@ 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 does not fit")) + if size(B, 1) != n + throw(DimensionMismatch("left and right hand side does not fit")) + end for i = 1:m for j = n:-1:1 Aij = A[i,j] @@ -460,7 +484,9 @@ end function A_mul_B!(A::StridedMatrix, B::LowerTriangular) m, n = size(A) - size(B, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) + if size(B, 1) != n + throw(DimensionMismatch("left and right hand side does not fit")) + end for i = 1:m for j = 1:n Aij = A[i,j]*B[j,j] @@ -474,7 +500,9 @@ 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 does not fit")) + if size(B, 1) != n + throw(DimensionMismatch("left and right hand side does not fit")) + end for i = 1:m for j = 1:n Aij = A[i,j] @@ -489,7 +517,9 @@ end function A_mul_Bc!(A::StridedMatrix, B::UpperTriangular) m, n = size(A) - size(B, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) + if size(B, 1) != n + throw(DimensionMismatch("left and right hand side does not fit")) + end for i = 1:m for j = 1:n Aij = A[i,j]*B[j,j] @@ -503,7 +533,9 @@ 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 does not fit")) + if size(B, 1) != n + throw(DimensionMismatch("left and right hand side does not fit")) + end for i = 1:m for j = 1:n Aij = A[i,j] @@ -518,7 +550,9 @@ end function A_mul_Bc!(A::StridedMatrix, B::LowerTriangular) m, n = size(A) - size(B, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) + if size(B, 1) != n + throw(DimensionMismatch("left and right hand side does not fit")) + end for i = 1:m for j = n:-1:1 Aij = A[i,j]*B[j,j] @@ -532,7 +566,9 @@ 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 does not fit")) + if size(B, 1) != n + throw(DimensionMismatch("left and right hand side does not fit")) + end for i = 1:m for j = n:-1:1 Aij = A[i,j] @@ -548,7 +584,9 @@ end #Generic solver using naive substitution function naivesub!(A::UpperTriangular, b::AbstractVector, x::AbstractVector=b) n = size(A, 2) - n == length(b) == length(x) || throw(DimensionMismatch()) + if !(n == length(b) == length(x)) + throw(DimensionMismatch("Second dimension of A, $n, length of x, $(length(x)), and length of b, $(length(b)) must be equal")) + end for j = n:-1:1 xj = b[j] for k = j+1:1:n @@ -565,7 +603,9 @@ function naivesub!(A::UpperTriangular, b::AbstractVector, x::AbstractVector=b) end function naivesub!(A::UnitUpperTriangular, b::AbstractVector, x::AbstractVector=b) n = size(A, 2) - n == length(b) == length(x) || throw(DimensionMismatch()) + if !(n == length(b) == length(x)) + throw(DimensionMismatch("Second dimension of A, $n, length of x, $(length(x)), and length of b, $(length(b)) must be equal")) + end for j = n:-1:1 xj = b[j] for k = j+1:1:n @@ -577,7 +617,9 @@ function naivesub!(A::UnitUpperTriangular, b::AbstractVector, x::AbstractVector= end function naivesub!(A::LowerTriangular, b::AbstractVector, x::AbstractVector=b) n = size(A, 2) - n == length(b) == length(x) || throw(DimensionMismatch()) + if !(n == length(b) == length(x)) + throw(DimensionMismatch("Second dimension of A, $n, length of x, $(length(x)), and length of b, $(length(b)) must be equal")) + end for j = 1:n xj = b[j] for k = 1:j-1 @@ -594,7 +636,9 @@ function naivesub!(A::LowerTriangular, b::AbstractVector, x::AbstractVector=b) end function naivesub!(A::UnitLowerTriangular, b::AbstractVector, x::AbstractVector=b) n = size(A, 2) - n == length(b) == length(x) || throw(DimensionMismatch()) + if !(n == length(b) == length(x)) + throw(DimensionMismatch("Second dimension of A, $n, length of x, $(length(x)), and length of b, $(length(b)) must be equal")) + end for j = 1:n xj = b[j] for k = 1:j-1 @@ -607,7 +651,9 @@ end function A_rdiv_B!(A::StridedMatrix, B::UpperTriangular) m, n = size(A) - size(A, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) + if size(A, 1) != n + throw(DimensionMismatch("left and right hand side does not fit")) + end for i = 1:m for j = 1:n Aij = A[i,j] @@ -621,7 +667,9 @@ 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 does not fit")) + if size(A, 1) != n + throw(DimensionMismatch("left and right hand side does not fit")) + end for i = 1:m for j = 1:n Aij = A[i,j] @@ -636,7 +684,9 @@ end function A_rdiv_B!(A::StridedMatrix, B::LowerTriangular) m, n = size(A) - size(A, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) + if size(A, 1) != n + throw(DimensionMismatch("left and right hand side does not fit")) + end for i = 1:m for j = n:-1:1 Aij = A[i,j] @@ -650,7 +700,9 @@ 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 does not fit")) + if size(A, 1) != n + throw(DimensionMismatch("left and right hand side does not fit")) + end for i = 1:m for j = n:-1:1 Aij = A[i,j] @@ -665,7 +717,9 @@ end function A_rdiv_Bc!(A::StridedMatrix, B::UpperTriangular) m, n = size(A) - size(A, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) + if size(A, 1) != n + throw(DimensionMismatch("left and right hand side does not fit")) + end for i = 1:m for j = n:-1:1 Aij = A[i,j] @@ -679,7 +733,9 @@ 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 does not fit")) + if size(A, 1) != n + throw(DimensionMismatch("left and right hand side does not fit")) + end for i = 1:m for j = n:-1:1 Aij = A[i,j] @@ -694,7 +750,9 @@ end function A_rdiv_Bc!(A::StridedMatrix, B::LowerTriangular) m, n = size(A) - size(A, 1) == n || throw(DimensionMismatch("left and right hand side does not fit")) + if size(A, 1) != n + throw(DimensionMismatch("left and right hand side does not fit")) + end for i = 1:m for j = 1:n Aij = A[i,j] @@ -708,7 +766,9 @@ 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 does not fit")) + if size(A, 1) != n + throw(DimensionMismatch("left and right hand side does not fit")) + end for i = 1:m for j = 1:n Aij = A[i,j] @@ -869,8 +929,11 @@ sqrtm(A::UnitLowerTriangular) = sqrtm(A.').' eigvals(A::AbstractTriangular) = diag(A) function eigvecs{T}(A::AbstractTriangular{T}) TT = promote_type(T, Float32) - TT <: BlasFloat && return eigvecs(convert(AbstractMatrix{TT}, A)) - throw(ArgumentError("eigvecs type $(typeof(A)) not supported. Please submit a pull request.")) + if TT <: BlasFloat + return eigvecs(convert(AbstractMatrix{TT}, A)) + else + throw(ArgumentError("eigvecs type $(typeof(A)) not supported. Please submit a pull request.")) + end end det{T}(A::UnitUpperTriangular{T}) = one(T)*one(T) det{T}(A::UnitLowerTriangular{T}) = one(T)*one(T) @@ -887,4 +950,3 @@ for func in (:svd, :svdfact, :svdfact!, :svdvals) end factorize(A::AbstractTriangular) = A - From bbc47a84fa2f5359cd078e820ae53dd9ec68c870 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Sun, 31 May 2015 19:15:29 -0700 Subject: [PATCH 179/181] Prettied up tridiag --- base/linalg/tridiag.jl | 70 +++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 11 deletions(-) diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index 6d530b0dbd843..48da9f8d15b97 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -53,7 +53,15 @@ ctranspose(M::SymTridiagonal) = conj(M) function diag{T}(M::SymTridiagonal{T}, n::Integer=0) absn = abs(n) - absn==0 ? M.dv : absn==1 ? M.ev : absn Date: Mon, 1 Jun 2015 11:52:01 +0500 Subject: [PATCH 180/181] Unbreak LLVM_SVN build. Function simplifed in LLVM master source tree. See https://github.com/llvm-mirror/llvm/commit/481f35f113c3fdd04ffb537fcbfaa1b187849cf4 --- src/debuginfo.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/debuginfo.cpp b/src/debuginfo.cpp index d8acadf431a21..1523cc1be0df3 100644 --- a/src/debuginfo.cpp +++ b/src/debuginfo.cpp @@ -295,7 +295,11 @@ class JuliaJITEventListener: public JITEventListener for (const object::SymbolRef &sym_iter : obj.symbols()) { sym_iter.getType(SymbolType); if (SymbolType != object::SymbolRef::ST_Function) continue; +#if defined(LLVM37) + Size = sym_iter.getSize(); +#else sym_iter.getSize(Size); +#endif sym_iter.getAddress(Addr); sym_iter.getSection(Section); if (Section == EndSection) continue; From 2945c8461ee2c86f736f580d5b1c5d1da1793579 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Fri, 29 May 2015 23:50:02 -0400 Subject: [PATCH 181/181] switch to utf8proc's portable, up-to-date, upper/lowercase functions (fixes #11471) --- base/string.jl | 4 ---- base/utf8proc.jl | 8 +++++++- deps/Makefile | 2 +- deps/checksums/utf8proc-1.3-dev1.tar.gz/md5 | 1 + deps/checksums/utf8proc-1.3-dev1.tar.gz/sha512 | 1 + deps/checksums/utf8proc-v1.2.tar.gz/md5 | 1 - deps/checksums/utf8proc-v1.2.tar.gz/sha512 | 1 - deps/utf8proc.version | 4 ++-- test/strings.jl | 4 ++++ 9 files changed, 16 insertions(+), 10 deletions(-) create mode 100644 deps/checksums/utf8proc-1.3-dev1.tar.gz/md5 create mode 100644 deps/checksums/utf8proc-1.3-dev1.tar.gz/sha512 delete mode 100644 deps/checksums/utf8proc-v1.2.tar.gz/md5 delete mode 100644 deps/checksums/utf8proc-v1.2.tar.gz/sha512 diff --git a/base/string.jl b/base/string.jl index 7295a231eea89..ebe3c8db8fe1e 100644 --- a/base/string.jl +++ b/base/string.jl @@ -793,10 +793,6 @@ write(io::IO, s::RopeString) = (write(io, s.head); write(io, s.tail)) sizeof(s::RopeString) = sizeof(s.head) + sizeof(s.tail) ## uppercase and lowercase transformations ## - -uppercase(c::Char) = convert(Char, ccall(:towupper, Cwchar_t, (Cwchar_t,), c)) -lowercase(c::Char) = convert(Char, ccall(:towlower, Cwchar_t, (Cwchar_t,), c)) - uppercase(s::AbstractString) = map(uppercase, s) lowercase(s::AbstractString) = map(lowercase, s) diff --git a/base/utf8proc.jl b/base/utf8proc.jl index c75e2147c3d69..9b299136626ca 100644 --- a/base/utf8proc.jl +++ b/base/utf8proc.jl @@ -3,7 +3,7 @@ # Various Unicode functionality from the utf8proc library module UTF8proc -import Base: show, showcompact, ==, hash, string, symbol, isless, length, eltype, start, next, done, convert, isvalid +import Base: show, showcompact, ==, hash, string, symbol, isless, length, eltype, start, next, done, convert, isvalid, lowercase, uppercase export isgraphemebreak @@ -121,6 +121,12 @@ end charwidth(c::Char) = Int(ccall(:utf8proc_charwidth, Cint, (UInt32,), c)) +# faster x+y that does no overflow checking +fastplus(x::Char, y::UInt32) = reinterpret(Char, reinterpret(UInt32, x) + y) + +lowercase(c::Char) = isascii(c) ? ('A' <= c <= 'Z' ? fastplus(c,0x00000020) : c) : ccall(:utf8proc_tolower, Char, (UInt32,), c) +uppercase(c::Char) = isascii(c) ? ('a' <= c <= 'z' ? fastplus(c,0xffffffe0) : c) : ccall(:utf8proc_toupper, Char, (UInt32,), c) + ############################################################################ # returns UTF8PROC_CATEGORY code in 0:30 giving Unicode category diff --git a/deps/Makefile b/deps/Makefile index 9f4cac6459269..85aa830fc1888 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -1436,7 +1436,7 @@ UTF8PROC_OBJ_HEADER = $(build_includedir)/utf8proc.h UTF8PROC_OBJ_TARGET = $(UTF8PROC_OBJ_LIB) $(UTF8PROC_OBJ_HEADER) $(UTF8PROC_SRC_TARGET): $(UTF8PROC_SRC_DIR)/Makefile - $(MAKE) -C $(UTF8PROC_SRC_DIR) cc="$(CC) -O2 -std=c99 $(fPIC) -DUTF8PROC_EXPORTS $(DEPS_CFLAGS)" AR="$(AR)" libutf8proc.a + $(MAKE) -C $(UTF8PROC_SRC_DIR) CC="$(CC)" CFLAGS="-O2 -std=c99 $(fPIC) -DUTF8PROC_EXPORTS $(DEPS_CFLAGS)" AR="$(AR)" libutf8proc.a touch -c $@ $(UTF8PROC_SRC_DIR)/checked: $(UTF8PROC_SRC_TARGET) ifeq ($(OS),$(BUILD_OS)) diff --git a/deps/checksums/utf8proc-1.3-dev1.tar.gz/md5 b/deps/checksums/utf8proc-1.3-dev1.tar.gz/md5 new file mode 100644 index 0000000000000..664eecce05b6b --- /dev/null +++ b/deps/checksums/utf8proc-1.3-dev1.tar.gz/md5 @@ -0,0 +1 @@ +e61de478d2a858586671dfd56477281e diff --git a/deps/checksums/utf8proc-1.3-dev1.tar.gz/sha512 b/deps/checksums/utf8proc-1.3-dev1.tar.gz/sha512 new file mode 100644 index 0000000000000..7128872214524 --- /dev/null +++ b/deps/checksums/utf8proc-1.3-dev1.tar.gz/sha512 @@ -0,0 +1 @@ +167d3a7779335d7ac0103431c4e7b1d9dc4f31836a7704524ea6c1c29d447012ec49f122247f9bf5d445500d7ddd7af5403ca260da05ffac9dba114e32afac07 diff --git a/deps/checksums/utf8proc-v1.2.tar.gz/md5 b/deps/checksums/utf8proc-v1.2.tar.gz/md5 deleted file mode 100644 index 02d6089a6222a..0000000000000 --- a/deps/checksums/utf8proc-v1.2.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -c9517c6d8e3f17f76fe5e171f7132ef5 diff --git a/deps/checksums/utf8proc-v1.2.tar.gz/sha512 b/deps/checksums/utf8proc-v1.2.tar.gz/sha512 deleted file mode 100644 index 0bd9d433cc6b0..0000000000000 --- a/deps/checksums/utf8proc-v1.2.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -e0f6f17730ab5063fc76de6065ded3eafa64f9ff673004bde41fb42e7a4a28a2861d46b1bd085438f667a5aef4489a009ddfad2faf791a52196499a484067c29 diff --git a/deps/utf8proc.version b/deps/utf8proc.version index 7cbb562416585..c69c593c8d135 100644 --- a/deps/utf8proc.version +++ b/deps/utf8proc.version @@ -1,2 +1,2 @@ -UTF8PROC_BRANCH=v1.2 -UTF8PROC_SHA1=e1fdad0ca9dc518b429439b6f4eac546a1bdd0de +UTF8PROC_BRANCH=1.3-dev1 +UTF8PROC_SHA1=f7219d516efe7496737d041f22b0ba567174fb16 diff --git a/test/strings.jl b/test/strings.jl index 10c9b11fe2665..b8f1a42f76983 100644 --- a/test/strings.jl +++ b/test/strings.jl @@ -673,6 +673,10 @@ end @test lowercase("AbC") == "abc" @test lowercase('A') == 'a' @test lowercase('a') == 'a' +@test uppercase('α') == '\u0391' +@test lowercase('Δ') == 'δ' +@test lowercase('\U118bf') == '\U118df' +@test uppercase('\U1044d') == '\U10425' @test ucfirst("Abc") == "Abc" @test ucfirst("abc") == "Abc" @test lcfirst("ABC") == "aBC"