From fe20da5e2d1cedd560fc950d9b2a902e9a60966a Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Sun, 7 Sep 2014 13:49:35 -0500 Subject: [PATCH 01/79] Fix hang/incorrect result for ndigits with b < 0. --- base/intfuncs.jl | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 077b363eed90b..691cd8bf95ffb 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -158,6 +158,23 @@ ndigits0z(x::Integer) = ndigits0z(unsigned(abs(x))) const ndigits_max_mul = WORD_SIZE==32 ? 69000000 : 290000000000000000 +function ndigits0zpos(n::Unsigned, b::Int) + +end + +function ndigitsnb(n::Int, b::Int) + if n == 0 + return 1 + end + + d = 0 + while n != 0 + n = iceil(n/b) + d += 1 + end + return d +end + function ndigits0z(n::Unsigned, b::Int) b == 2 && return (sizeof(n)<<3-leading_zeros(n)) b == 8 && return div((sizeof(n)<<3)-leading_zeros(n)+2,3) @@ -180,7 +197,7 @@ ndigits0z(x::Integer, b::Integer) = ndigits0z(unsigned(abs(x)),int(b)) ndigits(x::Unsigned, b::Integer) = x==0 ? 1 : ndigits0z(x,int(b)) ndigits(x::Unsigned) = x==0 ? 1 : ndigits0z(x) -ndigits(x::Integer, b::Integer) = ndigits(unsigned(abs(x)),int(b)) +ndigits(x::Integer, b::Integer) = b >= 0 ? ndigits(unsigned(abs(x)),int(b)) : ndigitsnb(x, b) ndigits(x::Integer) = ndigits(unsigned(abs(x))) ## integer to string functions ## From 4d75555a77f2a7e30db7006749ea3ef152d7d6ca Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Sun, 7 Sep 2014 13:54:05 -0500 Subject: [PATCH 02/79] Remove debug junk --- base/intfuncs.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 691cd8bf95ffb..810744108b533 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -158,10 +158,6 @@ ndigits0z(x::Integer) = ndigits0z(unsigned(abs(x))) const ndigits_max_mul = WORD_SIZE==32 ? 69000000 : 290000000000000000 -function ndigits0zpos(n::Unsigned, b::Int) - -end - function ndigitsnb(n::Int, b::Int) if n == 0 return 1 From 907fb9d5353126df1f34f9d3480f561df7becce8 Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Sun, 7 Sep 2014 14:02:46 -0500 Subject: [PATCH 03/79] Add tests for ndigits (issue #8266). --- test/Makefile | 2 +- test/intfuncs.jl | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 test/intfuncs.jl diff --git a/test/Makefile b/test/Makefile index ab9d903506cdb..0ac94bcde6041 100644 --- a/test/Makefile +++ b/test/Makefile @@ -2,7 +2,7 @@ JULIAHOME = $(abspath ..) include ../Make.inc TESTS = all core keywordargs numbers strings unicode collections hashing \ - remote iobuffer arrayops reduce reducedim \ + remote iobuffer arrayops reduce reducedim intfuncs \ simdloop linalg blas fft dsp sparse bitarray random \ math functional bigint sorting statistics spawn parallel arpack file \ git pkg resolve suitesparse complex version pollfd mpfr broadcast \ diff --git a/test/intfuncs.jl b/test/intfuncs.jl new file mode 100644 index 0000000000000..a13dbe6a1eeab --- /dev/null +++ b/test/intfuncs.jl @@ -0,0 +1,15 @@ +# issue #8266 + +@test ndigits(-15, 10) == 2 +@test ndigits(-15, -10) == 2 +@test ndigits(-1, 10) == 1 +@test ndigits(-1, -10) == 2 +@test ndigits(2, 10) == 1 +@test ndigits(2, -10) == 1 +@test ndigits(10, 10) == 2 +@test ndigits(10, -10) == 3 +@test ndigits(17, 10) == 2 +@test ndigits(17, -10) == 3 + +@test ndigits(146, -3) == 5 + From 0af80c7a7514159ca2a39ad707097f7403494cf9 Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Sun, 7 Sep 2014 17:24:55 -0500 Subject: [PATCH 04/79] Move negative base check inside ndigits0z and add a test for (unsigned, signed) case. --- base/intfuncs.jl | 33 +++++++++++++++++++-------------- test/intfuncs.jl | 1 + 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 810744108b533..6e2815696cdee 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -165,26 +165,31 @@ function ndigitsnb(n::Int, b::Int) d = 0 while n != 0 - n = iceil(n/b) + # cld, while #8111 is waiting to be merged. + n = div(n,b)+(!signbit(n$b)&(rem(n,b)!=0)) d += 1 end return d end function ndigits0z(n::Unsigned, b::Int) - b == 2 && return (sizeof(n)<<3-leading_zeros(n)) - b == 8 && return div((sizeof(n)<<3)-leading_zeros(n)+2,3) - b == 16 && return (sizeof(n)<<1)-(leading_zeros(n)>>2) - b == 10 && return ndigits0z(n) d = 0 - while ndigits_max_mul < n - n = div(n,b) - d += 1 - end - m = 1 - while m <= n - m *= b - d += 1 + if b < 0 + d = ndigitsnb(signed(n), b) + else + b == 2 && return (sizeof(n)<<3-leading_zeros(n)) + b == 8 && return div((sizeof(n)<<3)-leading_zeros(n)+2,3) + b == 16 && return (sizeof(n)<<1)-(leading_zeros(n)>>2) + b == 10 && return ndigits0z(n) + while ndigits_max_mul < n + n = div(n,b) + d += 1 + end + m = 1 + while m <= n + m *= b + d += 1 + end end return d end @@ -193,7 +198,7 @@ ndigits0z(x::Integer, b::Integer) = ndigits0z(unsigned(abs(x)),int(b)) ndigits(x::Unsigned, b::Integer) = x==0 ? 1 : ndigits0z(x,int(b)) ndigits(x::Unsigned) = x==0 ? 1 : ndigits0z(x) -ndigits(x::Integer, b::Integer) = b >= 0 ? ndigits(unsigned(abs(x)),int(b)) : ndigitsnb(x, b) +ndigits(x::Integer, b::Integer) = ndigits(unsigned(abs(x)),int(b)) ndigits(x::Integer) = ndigits(unsigned(abs(x))) ## integer to string functions ## diff --git a/test/intfuncs.jl b/test/intfuncs.jl index a13dbe6a1eeab..8700b6088aa7f 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -10,6 +10,7 @@ @test ndigits(10, -10) == 3 @test ndigits(17, 10) == 2 @test ndigits(17, -10) == 3 +@test ndigits(unsigned(17), -10) == 3 @test ndigits(146, -3) == 5 From dec10587db0e8b76fc5ed3040e911e67704a1432 Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Sun, 7 Sep 2014 17:33:15 -0500 Subject: [PATCH 05/79] ndigits: don't take abs(n) if b < 0. --- base/intfuncs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 6e2815696cdee..db3695c1b5c1b 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -198,7 +198,7 @@ ndigits0z(x::Integer, b::Integer) = ndigits0z(unsigned(abs(x)),int(b)) ndigits(x::Unsigned, b::Integer) = x==0 ? 1 : ndigits0z(x,int(b)) ndigits(x::Unsigned) = x==0 ? 1 : ndigits0z(x) -ndigits(x::Integer, b::Integer) = ndigits(unsigned(abs(x)),int(b)) +ndigits(x::Integer, b::Integer) = b >= 0 ? ndigits(unsigned(abs(x)),int(b)) : ndigitsnb(x, b) ndigits(x::Integer) = ndigits(unsigned(abs(x))) ## integer to string functions ## From f64acabf704490d9b6ba917dcdc030a8d4f71601 Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Sun, 7 Sep 2014 17:38:19 -0500 Subject: [PATCH 06/79] Throw error when bigint ndigits has a negative base. --- base/gmp.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/base/gmp.jl b/base/gmp.jl index a09803eb0da74..2d260b7c153ba 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -429,6 +429,7 @@ function base(b::Integer, n::BigInt) end function ndigits0z(x::BigInt, b::Integer=10) + b < 0 && throw(DomainError()) # TODO: make this work correctly. # mpz_sizeinbase might return an answer 1 too big n = int(ccall((:__gmpz_sizeinbase,:libgmp), Culong, (Ptr{BigInt}, Int32), &x, b)) abs(x) < big(b)^(n-1) ? n-1 : n From 1e52f448e2892abe19af9fbfea4443b5a166869e Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Sun, 7 Sep 2014 18:13:47 -0500 Subject: [PATCH 07/79] Replace 'manual' cld with cld function now that #8111 has been merged. --- base/intfuncs.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index db3695c1b5c1b..e48db4052d085 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -165,8 +165,7 @@ function ndigitsnb(n::Int, b::Int) d = 0 while n != 0 - # cld, while #8111 is waiting to be merged. - n = div(n,b)+(!signbit(n$b)&(rem(n,b)!=0)) + n = cld(n,b) d += 1 end return d From 4156fab06b975506861357966a2dd0be11e53b37 Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Sun, 7 Sep 2014 20:35:44 -0500 Subject: [PATCH 08/79] Match previous ndigits0z interface. --- base/intfuncs.jl | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index e48db4052d085..5dd5bdd584eb4 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -158,11 +158,7 @@ ndigits0z(x::Integer) = ndigits0z(unsigned(abs(x))) const ndigits_max_mul = WORD_SIZE==32 ? 69000000 : 290000000000000000 -function ndigitsnb(n::Int, b::Int) - if n == 0 - return 1 - end - +function ndigits0znb(n::Int, b::Int) d = 0 while n != 0 n = cld(n,b) @@ -194,6 +190,8 @@ function ndigits0z(n::Unsigned, b::Int) end ndigits0z(x::Integer, b::Integer) = ndigits0z(unsigned(abs(x)),int(b)) +ndigitsnb(x::Integer, b::Integer) = x==0 ? 1 : ndigits0znb(x, b) + ndigits(x::Unsigned, b::Integer) = x==0 ? 1 : ndigits0z(x,int(b)) ndigits(x::Unsigned) = x==0 ? 1 : ndigits0z(x) From 43241031615e0beba7c4d8d28d95979b8af0ceaf Mon Sep 17 00:00:00 2001 From: Dan Luu Date: Sun, 14 Sep 2014 12:13:33 -0500 Subject: [PATCH 09/79] Call 0z version of ndigitsnb, which avoids an extra branch. --- base/intfuncs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 5dd5bdd584eb4..9c11e2798935c 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -170,7 +170,7 @@ end function ndigits0z(n::Unsigned, b::Int) d = 0 if b < 0 - d = ndigitsnb(signed(n), b) + d = ndigits0znb(signed(n), b) else b == 2 && return (sizeof(n)<<3-leading_zeros(n)) b == 8 && return div((sizeof(n)<<3)-leading_zeros(n)+2,3) From 141da937e585d404906c69505bfe8fcf8af3d65d Mon Sep 17 00:00:00 2001 From: Peter Simon Date: Mon, 15 Sep 2014 10:03:20 -0700 Subject: [PATCH 10/79] Complete the description of Pkg.init() Provides guidance for those wishing to implement a custom METADATA setup --- doc/stdlib/pkg.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/stdlib/pkg.rst b/doc/stdlib/pkg.rst index d784d192b808a..13ebb6266852e 100644 --- a/doc/stdlib/pkg.rst +++ b/doc/stdlib/pkg.rst @@ -18,10 +18,12 @@ to use them, you'll need to prefix each function call with an explicit ``Pkg.``, Equivalent to ``normpath(Pkg.dir(),names...)`` – i.e. it appends path components to the package directory and normalizes the resulting path. In particular, ``Pkg.dir(pkg)`` returns the path to the package ``pkg``. -.. function:: init() +.. function:: init(meta::String=DEFAULT_META, branch::String=META_BRANCH) - Initialize ``Pkg.dir()`` as a package directory. + Initialize ``Pkg.dir()`` as a package directory. This will be done automatically when the ``JULIA_PKGDIR`` is not set and ``Pkg.dir()`` uses its default value. + As part of this process, clones a local METADATA git repository from the site and branch specified by its arguments, which + are typically not provided. Explicit (non-default) arguments can be used to support a custom METADATA setup. .. function:: resolve() From 10d32f77747fa57d534fdb471dccd5c4227ab534 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Tue, 19 Aug 2014 16:55:59 +0100 Subject: [PATCH 11/79] use double-double precision for sinpi --- base/special/trig.jl | 81 +++++++++++++++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 19 deletions(-) diff --git a/base/special/trig.jl b/base/special/trig.jl index 0ca23285c70ce..6cb73e76e382a 100644 --- a/base/special/trig.jl +++ b/base/special/trig.jl @@ -1,3 +1,41 @@ +immutable Double64 + hi::Float64 + lo::Float64 +end +immutable Double32 + hi::Float64 +end + +# kernel functions are only valid for |x| < pi/4 = 0.7854 +sin_kernel(x::Double64) = ccall((:__kernel_sin,Base.Math.libm),Float64,(Float64,Float64,Cint),x.hi,x.lo,1) +cos_kernel(x::Double64) = ccall((:__kernel_cos,Base.Math.libm),Float64,(Float64,Float64),x.hi,x.lo) +sin_kernel(x::Float64) = ccall((:__kernel_sin,Base.Math.libm),Float64,(Float64,Float64,Cint),x,0.0,0) +cos_kernel(x::Float64) = ccall((:__kernel_cos,Base.Math.libm),Float64,(Float64,Float64),x,0.0) + +sin_kernel(x::Double32) = ccall((:__kernel_sindf,Base.Math.libm),Float32,(Float64,),x.hi) +cos_kernel(x::Double32) = ccall((:__kernel_cosdf,Base.Math.libm),Float32,(Float64,),x.hi) + +sin_kernel(x::Real) = sin(x) +cos_kernel(x::Real) = cos(x) + +# multiply in extended precision +function mulpi_ext(x::Float64) + m = 3.141592653589793 + m_hi = 3.1415926218032837 + m_lo = 3.178650954705639e-8 + + u = 134217729.0*x # 0x1p27 + 1 + x_hi = u-(u-x) + x_lo = x-x_hi + + y_hi = m*x + y_lo = x_hi * m_lo + (x_lo* m_hi + ((x_hi*m_hi-y_hi) + x_lo*m_lo)) + + Double64(y_hi,y_lo) +end +mulpi_ext(x::Float32) = Double32(pi*float64(x)) +mulpi_ext(x::Real) = pi*x # Fallback + function sinpi(x::Real) if isinf(x) return throw(DomainError()) @@ -8,20 +46,24 @@ function sinpi(x::Real) rx = copysign(float(rem(x,2)),x) arx = abs(rx) - if arx < oftype(rx,0.25) - return sin(pi*rx) + if rx == zero(rx) + return rx + elseif arx < oftype(rx,0.25) + return sin_kernel(mulpi_ext(rx)) elseif arx <= oftype(rx,0.75) - arx = oftype(rx,0.5) - arx - return copysign(cos(pi*arx),rx) + y = mulpi_ext(oftype(rx,0.5) - arx) + return copysign(cos_kernel(y),rx) + elseif arx == one(x) + return copysign(zero(rx),rx) elseif arx < oftype(rx,1.25) - rx = (one(rx) - arx)*sign(rx) - return sin(pi*rx) + y = mulpi_ext((one(rx) - arx)*sign(rx)) + return sin_kernel(y) elseif arx <= oftype(rx,1.75) - arx = oftype(rx,1.5) - arx - return -copysign(cos(pi*arx),rx) + y = mulpi_ext(oftype(rx,1.5) - arx) + return -copysign(cos_kernel(y),rx) else - rx = rx - copysign(oftype(rx,2.0),rx) - return sin(pi*rx) + y = mulpi_ext(rx - copysign(oftype(rx,2.0),rx)) + return sin_kernel(y) end end @@ -35,22 +77,23 @@ function cospi(x::Real) rx = abs(float(rem(x,2))) if rx <= oftype(rx,0.25) - return cos(pi*rx) + return cos_kernel(mulpi_ext(rx)) elseif rx < oftype(rx,0.75) - rx = oftype(rx,0.5) - rx - return sin(pi*rx) + y = mulpi_ext(oftype(rx,0.5) - rx) + return sin_kernel(y) elseif rx <= oftype(rx,1.25) - rx = one(rx) - rx - return -cos(pi*rx) + y = mulpi_ext(one(rx) - rx) + return -cos_kernel(y) elseif rx < oftype(rx,1.75) - rx = rx - oftype(rx,1.5) - return sin(pi*rx) + y = mulpi_ext(rx - oftype(rx,1.5)) + return sin_kernel(y) else - rx = oftype(rx,2.0) - rx - return cos(pi*rx) + y = mulpi_ext(oftype(rx,2.0) - rx) + return cos_kernel(y) end end + sinpi(x::Integer) = zero(x) cospi(x::Integer) = isodd(x) ? -one(x) : one(x) From 4f0014dc9a3f89a382223c0416d4750cc9de9110 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Tue, 19 Aug 2014 18:27:04 +0100 Subject: [PATCH 12/79] sind/cosd using double-double --- base/special/trig.jl | 75 +++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 26 deletions(-) diff --git a/base/special/trig.jl b/base/special/trig.jl index 6cb73e76e382a..e801974bff89d 100644 --- a/base/special/trig.jl +++ b/base/special/trig.jl @@ -154,6 +154,25 @@ for (fa, fainv) in ((:asec, :acos), (:acsc, :asin), (:acot, :atan), end end + +# multiply in extended precision +function deg2rad_ext(x::Float64) + m = 0.017453292519943295 + m_hi = 0.01745329238474369 + m_lo = 1.3519960527851425e-10 + + u = 134217729.0*x # 0x1p27 + 1 + x_hi = u-(u-x) + x_lo = x-x_hi + + y_hi = m*x + y_lo = x_hi * m_lo + (x_lo* m_hi + ((x_hi*m_hi-y_hi) + x_lo*m_lo)) + + Double64(y_hi,y_lo) +end +deg2rad_ext(x::Float32) = Double32(deg2rad(float64(x))) +deg2rad_ext(x::Real) = deg2rad(x) # Fallback + function sind(x::Real) if isinf(x) return throw(DomainError()) @@ -164,20 +183,24 @@ function sind(x::Real) rx = copysign(float(rem(x,360)),x) arx = abs(rx) - if arx < oftype(rx,45.0) - return sin(deg2rad(rx)) - elseif arx <= oftype(rx,135.0) - arx = oftype(rx,90.0) - arx - return copysign(cos(deg2rad(arx)),rx) - elseif arx < oftype(rx,225.0) - rx = (oftype(rx,180.0) - arx)*sign(rx) - return sin(deg2rad(rx)) - elseif arx <= 315.0 - arx = oftype(rx,270.0) - arx - return -copysign(cos(deg2rad(arx)),rx) + if rx == zero(rx) + return rx + elseif arx < oftype(rx,45) + return sin_kernel(deg2rad_ext(rx)) + elseif arx <= oftype(rx,135) + y = deg2rad_ext(oftype(rx,90) - arx) + return copysign(cos_kernel(y),rx) + elseif arx == oftype(rx,180) + return copysign(zero(rx),rx) + elseif arx < oftype(rx,225) + y = deg2rad_ext((oftype(rx,180) - arx)*sign(rx)) + return sin_kernel(y) + elseif arx <= oftype(rx,315) + y = deg2rad_ext(oftype(rx,270) - arx) + return -copysign(cos_kernel(y),rx) else - rx = rx - copysign(oftype(rx,360.0),rx) - return sin(deg2rad(rx)) + y = deg2rad_ext(rx - copysign(oftype(rx,360),rx)) + return sin_kernel(y) end end @vectorize_1arg Real sind @@ -191,20 +214,20 @@ function cosd(x::Real) rx = abs(float(rem(x,360))) - if rx <= oftype(rx,45.0) - return cos(deg2rad(rx)) - elseif rx < oftype(rx,135.0) - rx = oftype(rx,90.0) - rx - return sin(deg2rad(rx)) - elseif rx <= oftype(rx,225.0) - rx = oftype(rx,180.0) - rx - return -cos(deg2rad(rx)) - elseif rx < oftype(rx,315.0) - rx = rx - oftype(rx,270.0) - return sin(deg2rad(rx)) + if rx <= oftype(rx,45) + return cos_kernel(deg2rad_ext(rx)) + elseif rx < oftype(rx,135) + y = deg2rad_ext(oftype(rx,90) - rx) + return sin_kernel(y) + elseif rx <= oftype(rx,225) + y = deg2rad_ext(oftype(rx,180) - rx) + return -cos_kernel(y) + elseif rx < oftype(rx,315) + y = deg2rad_ext(rx - oftype(rx,270)) + return sin_kernel(y) else - rx = oftype(rx,360.0) - rx - return cos(deg2rad(rx)) + y = deg2rad_ext(oftype(rx,360) - rx) + return cos_kernel(y) end end @vectorize_1arg Real cosd From 1ffbca6a43856d57e28c3a56c246ffe7900d54c2 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Tue, 19 Aug 2014 18:54:38 +0100 Subject: [PATCH 13/79] translate trig kernel functions to julia --- base/special/trig.jl | 73 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 7 deletions(-) diff --git a/base/special/trig.jl b/base/special/trig.jl index e801974bff89d..16a5f7b526f9e 100644 --- a/base/special/trig.jl +++ b/base/special/trig.jl @@ -6,15 +6,74 @@ immutable Double32 hi::Float64 end -# kernel functions are only valid for |x| < pi/4 = 0.7854 -sin_kernel(x::Double64) = ccall((:__kernel_sin,Base.Math.libm),Float64,(Float64,Float64,Cint),x.hi,x.lo,1) -cos_kernel(x::Double64) = ccall((:__kernel_cos,Base.Math.libm),Float64,(Float64,Float64),x.hi,x.lo) -sin_kernel(x::Float64) = ccall((:__kernel_sin,Base.Math.libm),Float64,(Float64,Float64,Cint),x,0.0,0) -cos_kernel(x::Float64) = ccall((:__kernel_cos,Base.Math.libm),Float64,(Float64,Float64),x,0.0) +# kernel_* functions are only valid for |x| < pi/4 = 0.7854 +# translated from openlibm code: k_sin.c, k_cos.c, k_sinf.c, k_cosf.c +# which are made available under following licence: + +## Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +## +## Developed at SunPro, a Sun Microsystems, Inc. business. +## Permission to use, copy, modify, and distribute this +## software is freely granted, provided that this notice +## is preserved. + +function sin_kernel(x::Double64) + S1 = -1.66666666666666324348e-01 + S2 = 8.33333333332248946124e-03 + S3 = -1.98412698298579493134e-04 + S4 = 2.75573137070700676789e-06 + S5 = -2.50507602534068634195e-08 + S6 = 1.58969099521155010221e-10 + + z = x.hi*x.hi + w = z*z + r = S2+z*(S3+z*S4) + z*w*(S5+z*S6) + v = z*x.hi + x.hi-((z*(0.5*x.lo-v*r)-x.lo)-v*S1) +end + +function cos_kernel(x::Double64) + C1 = 4.16666666666666019037e-02 + C2 = -1.38888888888741095749e-03 + C3 = 2.48015872894767294178e-05 + C4 = -2.75573143513906633035e-07 + C5 = 2.08757232129817482790e-09 + C6 = -1.13596475577881948265e-11 + + z = x.hi*x.hi + w = z*z + r = z*(C1+z*(C2+z*C3)) + w*w*(C4+z*(C5+z*C6)) + hz = 0.5*z + w = 1.0-hz + w + (((1.0-w)-hz) + (z*r-x.hi*x.lo)) +end + +function sin_kernel(x::Double32) + S1 = -0x15555554cbac77.0p-55 + S2 = 0x111110896efbb2.0p-59 + S3 = -0x1a00f9e2cae774.0p-65 + S4 = 0x16cd878c3b46a7.0p-71 + + z = x.hi*x.hi + w = z*z + r = S3+z*S4 + s = z*x.hi + float32((x.hi + s*(S1+z*S2)) + s*w*r) +end -sin_kernel(x::Double32) = ccall((:__kernel_sindf,Base.Math.libm),Float32,(Float64,),x.hi) -cos_kernel(x::Double32) = ccall((:__kernel_cosdf,Base.Math.libm),Float32,(Float64,),x.hi) +function cos_kernel(x::Double32) + C0 = -0x1ffffffd0c5e81.0p-54 + C1 = 0x155553e1053a42.0p-57 + C2 = -0x16c087e80f1e27.0p-62 + C3 = 0x199342e0ee5069.0p-68 + + z = x.hi*x.hi + w = z*z + r = C2+z*C3 + float32(((1.0+z*C0) + w*C1) + (w*z)*r) +end +# fallback methods sin_kernel(x::Real) = sin(x) cos_kernel(x::Real) = cos(x) From 1ecfe451dd30e4c46a357f65de6ba545bec59617 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Wed, 20 Aug 2014 17:16:05 +0100 Subject: [PATCH 14/79] improve sinpi rationals, add tests for exact values --- base/special/trig.jl | 14 ++++++------ test/math.jl | 53 +++++++++++++++++++++++++++++++++----------- 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/base/special/trig.jl b/base/special/trig.jl index 16a5f7b526f9e..01e0ce38396de 100644 --- a/base/special/trig.jl +++ b/base/special/trig.jl @@ -8,7 +8,7 @@ end # kernel_* functions are only valid for |x| < pi/4 = 0.7854 # translated from openlibm code: k_sin.c, k_cos.c, k_sinf.c, k_cosf.c -# which are made available under following licence: +# which are made available under the following licence: ## Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. ## @@ -93,6 +93,7 @@ function mulpi_ext(x::Float64) Double64(y_hi,y_lo) end mulpi_ext(x::Float32) = Double32(pi*float64(x)) +mulpi_ext(x::Rational) = mulpi_ext(float(x)) mulpi_ext(x::Real) = pi*x # Fallback function sinpi(x::Real) @@ -102,18 +103,18 @@ function sinpi(x::Real) return nan(x) end - rx = copysign(float(rem(x,2)),x) + rx = copysign(rem(x,2),x) arx = abs(rx) if rx == zero(rx) - return rx + return copysign(float(zero(rx)),x) elseif arx < oftype(rx,0.25) return sin_kernel(mulpi_ext(rx)) elseif arx <= oftype(rx,0.75) y = mulpi_ext(oftype(rx,0.5) - arx) return copysign(cos_kernel(y),rx) elseif arx == one(x) - return copysign(zero(rx),rx) + return copysign(float(zero(rx)),rx) elseif arx < oftype(rx,1.25) y = mulpi_ext((one(rx) - arx)*sign(rx)) return sin_kernel(y) @@ -152,9 +153,8 @@ function cospi(x::Real) end end - -sinpi(x::Integer) = zero(x) -cospi(x::Integer) = isodd(x) ? -one(x) : one(x) +sinpi(x::Integer) = x >= 0 ? zero(float(x)) : -zero(float(x)) +cospi(x::Integer) = isodd(x) ? -one(float(x)) : one(float(x)) function sinpi(z::Complex) zr, zi = reim(z) diff --git a/test/math.jl b/test/math.jl index bcb187ad43713..b9ac1ff5404c8 100644 --- a/test/math.jl +++ b/test/math.jl @@ -5,26 +5,53 @@ @test exponent(12.8) == 3 # degree-based trig functions -for T = (Float32,Float64) +for T = (Float32,Float64,Rational{Int}) + fT = typeof(float(one(T))) for x = -400:40:400 - @test_approx_eq_eps sind(convert(T,x))::T convert(T,sin(pi/180*x)) eps(deg2rad(convert(T,x))) - @test_approx_eq_eps cosd(convert(T,x))::T convert(T,cos(pi/180*x)) eps(deg2rad(convert(T,x))) - end - for x = 0.0:180:720 - @test sind(convert(T,x)) === zero(T) - @test sind(-convert(T,x)) === -zero(T) + @test_approx_eq_eps sind(convert(T,x))::fT convert(fT,sin(pi/180*x)) eps(deg2rad(convert(fT,x))) + @test_approx_eq_eps cosd(convert(T,x))::fT convert(fT,cos(pi/180*x)) eps(deg2rad(convert(fT,x))) end + + @test sind(convert(T,0.0))::fT === zero(fT) + @test sind(convert(T,180.0))::fT === zero(fT) + @test sind(convert(T,360.0))::fT === zero(fT) + T != Rational{Int} && @test sind(convert(T,-0.0))::fT === -zero(fT) + @test sind(convert(T,-180.0))::fT === -zero(fT) + @test sind(convert(T,-360.0))::fT === -zero(fT) + + @test cosd(convert(T,90))::fT === zero(fT) + @test cosd(convert(T,270))::fT === zero(fT) + @test cosd(convert(T,-90))::fT === zero(fT) + @test cosd(convert(T,-270))::fT === zero(fT) + for x = -3:0.3:3 - @test_approx_eq_eps sinpi(convert(T,x))::T convert(T,sin(pi*x)) eps(pi*convert(T,x)) - @test_approx_eq_eps cospi(convert(T,x))::T convert(T,cos(pi*x)) eps(pi*convert(T,x)) - end - for x = 0.0:1.0:4.0 - @test sinpi(convert(T,x)) === zero(T) - @test sinpi(-convert(T,x)) === -zero(T) + @test_approx_eq_eps sinpi(convert(T,x))::fT convert(fT,sin(pi*x)) eps(pi*convert(fT,x)) + @test_approx_eq_eps cospi(convert(T,x))::fT convert(fT,cos(pi*x)) eps(pi*convert(fT,x)) end + + @test sinpi(convert(T,0.0))::fT === zero(fT) + @test sinpi(convert(T,1.0))::fT === zero(fT) + @test sinpi(convert(T,2.0))::fT === zero(fT) + T != Rational{Int} && @test sinpi(convert(T,-0.0))::fT === -zero(fT) + @test sinpi(convert(T,-1.0))::fT === -zero(fT) + @test sinpi(convert(T,-2.0))::fT === -zero(fT) + + @test cospi(convert(T,0.5))::fT === zero(fT) + @test cospi(convert(T,1.5))::fT === zero(fT) + @test cospi(convert(T,-0.5))::fT === zero(fT) + @test cospi(convert(T,-1.5))::fT === zero(fT) + + # check exact values + @test sind(convert(T,30)) == 0.5 + @test cosd(convert(T,60)) == 0.5 + @test sind(convert(T,150)) == 0.5 + @test sinpi(one(T)/convert(T,6)) == 0.5 + T != Float32 && @test cospi(one(T)/convert(T,3)) == 0.5 + T == Rational{Int} && @test sinpi(5//6) == 0.5 end + # check type stability for T = (Float32,Float64,BigFloat) for f = (sind,cosd,sinpi,cospi) From 07a88e60c6f9d7af36f5132bb575fccb63cb2e39 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Tue, 16 Sep 2014 13:16:20 +0100 Subject: [PATCH 15/79] rename DoubleFloat types --- base/special/trig.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/base/special/trig.jl b/base/special/trig.jl index 01e0ce38396de..7fc56ddd20ba0 100644 --- a/base/special/trig.jl +++ b/base/special/trig.jl @@ -1,8 +1,8 @@ -immutable Double64 +immutable DoubleFloat64 hi::Float64 lo::Float64 end -immutable Double32 +immutable DoubleFloat32 hi::Float64 end @@ -17,7 +17,7 @@ end ## software is freely granted, provided that this notice ## is preserved. -function sin_kernel(x::Double64) +function sin_kernel(x::DoubleFloat64) S1 = -1.66666666666666324348e-01 S2 = 8.33333333332248946124e-03 S3 = -1.98412698298579493134e-04 @@ -32,7 +32,7 @@ function sin_kernel(x::Double64) x.hi-((z*(0.5*x.lo-v*r)-x.lo)-v*S1) end -function cos_kernel(x::Double64) +function cos_kernel(x::DoubleFloat64) C1 = 4.16666666666666019037e-02 C2 = -1.38888888888741095749e-03 C3 = 2.48015872894767294178e-05 @@ -48,7 +48,7 @@ function cos_kernel(x::Double64) w + (((1.0-w)-hz) + (z*r-x.hi*x.lo)) end -function sin_kernel(x::Double32) +function sin_kernel(x::DoubleFloat32) S1 = -0x15555554cbac77.0p-55 S2 = 0x111110896efbb2.0p-59 S3 = -0x1a00f9e2cae774.0p-65 @@ -61,7 +61,7 @@ function sin_kernel(x::Double32) float32((x.hi + s*(S1+z*S2)) + s*w*r) end -function cos_kernel(x::Double32) +function cos_kernel(x::DoubleFloat32) C0 = -0x1ffffffd0c5e81.0p-54 C1 = 0x155553e1053a42.0p-57 C2 = -0x16c087e80f1e27.0p-62 @@ -90,9 +90,9 @@ function mulpi_ext(x::Float64) y_hi = m*x y_lo = x_hi * m_lo + (x_lo* m_hi + ((x_hi*m_hi-y_hi) + x_lo*m_lo)) - Double64(y_hi,y_lo) + DoubleFloat64(y_hi,y_lo) end -mulpi_ext(x::Float32) = Double32(pi*float64(x)) +mulpi_ext(x::Float32) = DoubleFloat32(pi*float64(x)) mulpi_ext(x::Rational) = mulpi_ext(float(x)) mulpi_ext(x::Real) = pi*x # Fallback @@ -227,9 +227,9 @@ function deg2rad_ext(x::Float64) y_hi = m*x y_lo = x_hi * m_lo + (x_lo* m_hi + ((x_hi*m_hi-y_hi) + x_lo*m_lo)) - Double64(y_hi,y_lo) + DoubleFloat64(y_hi,y_lo) end -deg2rad_ext(x::Float32) = Double32(deg2rad(float64(x))) +deg2rad_ext(x::Float32) = DoubleFloat32(deg2rad(float64(x))) deg2rad_ext(x::Real) = deg2rad(x) # Fallback function sind(x::Real) From 2eee58701052caf6b6927604732e197b1054ac7b Mon Sep 17 00:00:00 2001 From: Blake Johnson Date: Thu, 21 Aug 2014 22:34:09 -0400 Subject: [PATCH 16/79] expressions -> functions in LineEdit.jl Un-macrofied keymap function. Update value function signatures. Pass thru returned symbols in keyamp_fcn. history_keymap can now be const. --- base/LineEdit.jl | 376 ++++++++++++++++++++--------------------------- base/REPL.jl | 18 +-- 2 files changed, 172 insertions(+), 222 deletions(-) diff --git a/base/LineEdit.jl b/base/LineEdit.jl index be777b487e24e..4f2d278e0fb53 100644 --- a/base/LineEdit.jl +++ b/base/LineEdit.jl @@ -9,7 +9,7 @@ import Base: ensureroom, peek, show abstract TextInterface -export run_interface, Prompt, ModalInterface, transition, reset_state, edit_insert +export run_interface, Prompt, ModalInterface, transition, reset_state, edit_insert, keymap immutable ModalInterface <: TextInterface modes @@ -82,7 +82,7 @@ end reset_state(::EmptyHistoryProvider) = nothing -complete_line(c::EmptyCompletionProvider, s) = [] +complete_line(c::EmptyCompletionProvider, s) = [], true, true terminal(s::IO) = s terminal(s::PromptState) = s.terminal @@ -684,90 +684,67 @@ function normalize_key(key::String) return takebuf_string(buf) end +function normalize_keys(keymap::Dict) + return [normalize_key(k) => v for (k,v) in keymap] +end + +function add_nested_key!(keymap::Dict, key, value) + i = start(key) + while !done(key, i) + c, i = next(key, i) + if c in keys(keymap) + if !isa(keymap[c], Dict) + error("Conflicting Definitions for keyseq " * escape_string(key) * " within one keymap") + end + elseif done(key, i) + keymap[c] = value + break + else + keymap[c] = Dict{Char,Any}() + end + keymap = keymap[c] + end +end + # Turn a Dict{Any,Any} into a Dict{Char,Any} # For now we use \0 to represent unknown chars so that they are sorted before everything else # If we ever actually want to match \0 in input, this will have to be reworked function normalize_keymap(keymap::Dict) ret = Dict{Char,Any}() - for key in keys(keymap) - newkey = normalize_key(key) - current = ret - i = start(newkey) - while !done(newkey, i) - c, i = next(newkey, i) - if haskey(current, c) - if !isa(current[c], Dict) - println(ret) - error("Conflicting Definitions for keyseq " * escape_string(newkey) * " within one keymap") - end - elseif done(newkey, i) - if isa(keymap[key], String) - current[c] = normalize_key(keymap[key]) - else - current[c] = keymap[key] - end - break - else - current[c] = Dict{Char,Any}() - end - current = current[c] - end + direct_keys = filter((k,v) -> isa(v, Union(Function, Nothing)), keymap) + # first direct entries + for key in keys(direct_keys) + add_nested_key!(ret, key, keymap[key]) + end + # then redirected entries + for key in setdiff(keys(keymap), keys(direct_keys)) + value = normalize_key(keymap[key]) + haskey(keymap, value) || error("Could not find redirected value " * escape_string(keymap[key])) + add_nested_key!(ret, key, keymap[value]) end ret end -keymap_gen_body(keymaps, body::Expr, level) = body -keymap_gen_body(keymaps, body::Function, level) = keymap_gen_body(keymaps, :($(body)(s))) -keymap_gen_body(keymaps, body::Char, level) = keymap_gen_body(keymaps, keymaps[body]) -keymap_gen_body(keymaps, body::Nothing, level) = nothing -function keymap_gen_body(keymaps, body::String, level) - if length(body) == 1 - return keymap_gen_body(keymaps, body[1], level) - end - current = keymaps - for c in body - if haskey(current, c) - if isa(current[c], Dict) - current = current[c] - else - return keymap_gen_body(keymaps, current[c], level) - end - elseif haskey(current, '\0') - return keymap_gen_body(keymaps, current['\0'], level) +match_input(k::Function, s, cs) = (update_key_repeats(s, cs); return keymap_fcn(k, s, last(cs))) +match_input(k::Nothing, s, cs) = (s,p) -> return :ok +function match_input(keymap::Dict, s, cs=Char[]) + c = read(terminal(s), Char) + push!(cs, c) + k = haskey(keymap, c) ? c : '\0' + return match_input(keymap[k], s, cs) + # perhaps better would be: match_input(get(keymap, k, nothing), s, cs) ? +end + +keymap_fcn(f::Nothing, s, c) = (s, p) -> return :ok +function keymap_fcn(f::Function, s, c::Char) + return (s, p) -> begin + r = f(s, p, c) + if isa(r, Symbol) + return r else - error("No match for redirected key $body") - end - end - error("No exact match for redirected key $body") -end - -keymap_gen_body(a, b) = keymap_gen_body(a, b, 1) -function keymap_gen_body(dict, subdict::Dict, level) - block = Expr(:block) - bc = symbol("c" * string(level)) - push!(block.args, :($bc = read(LineEdit.terminal(s), Char))) - - last_if = Expr(:block) - haskey(subdict, '\0') && push!(last_if.args, keymap_gen_body(dict, subdict['\0'], level+1)) - level == 1 && push!(last_if.args, :(LineEdit.update_key_repeats(s, [$bc]))) - - for c in keys(subdict) - c == '\0' && continue - cblock = Expr(:if, :($bc == $c)) - cthen = Expr(:block) - if !isa(subdict[c], Dict) - cs = [symbol("c" * string(i)) for i=1:level] - push!(cthen.args, :(LineEdit.update_key_repeats(s, [$(cs...)]))) + return :ok end - push!(cthen.args, keymap_gen_body(dict, subdict[c], level+1)) - - push!(cblock.args, cthen) - push!(cblock.args, last_if) - last_if = cblock end - - push!(block.args, last_if) - return block end update_key_repeats(s, keystroke) = nothing @@ -777,8 +754,6 @@ function update_key_repeats(s::MIState, keystroke) return end -export @keymap - # deep merge where target has higher precedence function keymap_merge!(target::Dict, source::Dict) for k in keys(source) @@ -795,8 +770,8 @@ end fixup_keymaps!(d, l, s, sk) = nothing function fixup_keymaps!(dict::Dict, level, s, subkeymap) if level > 1 - for d in dict - fixup_keymaps!(d[2], level-1, s, subkeymap) + for d in values(dict) + fixup_keymaps!(d, level-1, s, subkeymap) end else if haskey(dict, s) @@ -826,19 +801,19 @@ function fix_conflicts!(dict::Dict, level) if haskey(dict, '\0') add_specialisations(dict, dict, level) end - for d in dict - d[1] == '\0' && continue - fix_conflicts!(d[2], level+1) + for (k,v) in dict + k == '\0' && continue + fix_conflicts!(v, level+1) end end -keymap_prepare(keymaps::Expr) = keymap_prepare(eval(keymaps)) -keymap_prepare(keymaps::Dict) = keymap_prepare([keymaps]) -function keymap_prepare{D<:Dict}(keymaps::Array{D}) - push!(keymaps, {"*"=>:(error("Unrecognized input"))}) - keymaps = map(normalize_keymap, keymaps) - map(fix_conflicts!, keymaps) - keymaps +function keymap_prepare(keymap::Dict) + if !haskey(keymap, "\0") + keymap["\0"] = (o...)->error("Unrecognized input") + end + keymap = normalize_keymap(keymap) + fix_conflicts!(keymap) + keymap end function keymap_unify(keymaps) @@ -851,19 +826,15 @@ function keymap_unify(keymaps) return ret end -macro keymap(keymaps) - dict = keymap_unify(keymap_prepare(keymaps)) - body = keymap_gen_body(dict, dict) - esc(quote - (s, data) -> begin - $body - return :ok - end - end) +function keymap{D<:Dict}(keymaps::Array{D}) + # keymaps is a vector of prioritized keymaps, with highest priority first + dict = map(normalize_keys, keymaps) + dict = keymap_prepare(merge(reverse(dict)...)) + return (s,p)->match_input(dict, s)(s,p) end const escape_defaults = merge!( - {i => nothing for i=1:31}, # Ignore control characters by default + {char(i) => nothing for i=[1:26, 28:31]}, # Ignore control characters by default { # And ignore other escape sequences by default "\e*" => nothing, "\e[*" => nothing, @@ -1027,88 +998,81 @@ end function setup_search_keymap(hp) p = HistoryPrompt(hp) pkeymap = { - "^R" => :(LineEdit.history_set_backward(data, true); LineEdit.history_next_result(s, data)), - "^S" => :(LineEdit.history_set_backward(data, false); LineEdit.history_next_result(s, data)), - '\r' => s->accept_result(s, p), + "^R" => (s,data,c)->(history_set_backward(data, true); history_next_result(s, data)), + "^S" => (s,data,c)->(history_set_backward(data, false); history_next_result(s, data)), + '\r' => (s,o...)->accept_result(s, p), '\n' => '\r', # Limited form of tab completions - '\t' => :(LineEdit.complete_line(s); LineEdit.update_display_buffer(s, data)), - "^L" => :(Terminals.clear(LineEdit.terminal(s)); LineEdit.update_display_buffer(s, data)), + '\t' => (s,data,c)->(complete_line(s); update_display_buffer(s, data)), + "^L" => (s,data,c)->(Terminals.clear(terminal(s)); update_display_buffer(s, data)), # Backspace/^H - '\b' => :(LineEdit.edit_backspace(data.query_buffer) ? - LineEdit.update_display_buffer(s, data) : beep(LineEdit.terminal(s))), + '\b' => (s,data,c)->(edit_backspace(data.query_buffer) ? + update_display_buffer(s, data) : beep(terminal(s))), 127 => '\b', # Meta Backspace - "\e\b" => :(LineEdit.edit_delete_prev_word(data.query_buffer) ? - LineEdit.update_display_buffer(s, data) : beep(LineEdit.terminal(s))), + "\e\b" => (s,data,c)->(edit_delete_prev_word(data.query_buffer) ? + update_display_buffer(s, data) : beep(terminal(s))), "\e\x7f" => "\e\b", # Word erase to whitespace - "^W" => :(LineEdit.edit_werase(data.query_buffer) ? - LineEdit.update_display_buffer(s, data) : beep(LineEdit.terminal(s))), + "^W" => (s,data,c)->(edit_werase(data.query_buffer) ? + update_display_buffer(s, data) : beep(terminal(s))), # ^C and ^D - "^C" => :(LineEdit.edit_clear(data.query_buffer); - LineEdit.edit_clear(data.response_buffer); - LineEdit.update_display_buffer(s, data); - LineEdit.reset_state(data.histprompt.hp); - LineEdit.transition(s, data.parent)), + "^C" => (s,data,c)->(edit_clear(data.query_buffer); + edit_clear(data.response_buffer); + update_display_buffer(s, data); + reset_state(data.histprompt.hp); + transition(s, data.parent)), "^D" => "^C", # Other ways to cancel search mode (it's difficult to bind \e itself) "^G" => "^C", "\e\e" => "^C", - # ^K - 11 => s->transition(s, state(s, p).parent), - # ^Y - 25 => :(LineEdit.edit_yank(s); LineEdit.update_display_buffer(s, data)), - # ^U - 21 => :(LineEdit.edit_clear(data.query_buffer); - LineEdit.edit_clear(data.response_buffer); - LineEdit.update_display_buffer(s, data)), + "^K" => (s,o...)->transition(s, state(s, p).parent), + "^Y" => (s,data,c)->(edit_yank(s); update_display_buffer(s, data)), + "^U" => (s,data,c)->(edit_clear(data.query_buffer); + edit_clear(data.response_buffer); + update_display_buffer(s, data)), # Right Arrow - "\e[C" => s->(accept_result(s, p); edit_move_right(s)), + "\e[C" => (s,o...)->(accept_result(s, p); edit_move_right(s)), # Left Arrow - "\e[D" => s->(accept_result(s, p); edit_move_left(s)), + "\e[D" => (s,o...)->(accept_result(s, p); edit_move_left(s)), # Up Arrow - "\e[A" => s->(accept_result(s, p); edit_move_up(s)), + "\e[A" => (s,o...)->(accept_result(s, p); edit_move_up(s)), # Down Arrow - "\e[B" => s->(accept_result(s, p); edit_move_down(s)), - # ^B - 2 => s->(accept_result(s, p); edit_move_left(s)), - # ^F - 6 => s->(accept_result(s, p); edit_move_right(s)), + "\e[B" => (s,o...)->(accept_result(s, p); edit_move_down(s)), + "^B" => (s,o...)->(accept_result(s, p); edit_move_left(s)), + "^F" => (s,o...)->(accept_result(s, p); edit_move_right(s)), # Meta B - "\eb" => s->(accept_result(s, p); edit_move_word_left(s)), + "\eb" => (s,o...)->(accept_result(s, p); edit_move_word_left(s)), # Meta F - "\ef" => s->(accept_result(s, p); edit_move_word_right(s)), + "\ef" => (s,o...)->(accept_result(s, p); edit_move_word_right(s)), # Ctrl-Left Arrow "\e[1;5D" => "\eb", # Ctrl-Right Arrow "\e[1;5C" => "\ef", - # ^A - 1 => s->(accept_result(s, p); move_line_start(s); refresh_line(s)), - # ^E - 5 => s->(accept_result(s, p); move_line_end(s); refresh_line(s)), - "^Z" => :(return :suspend), + "^A" => (s,o...)->(accept_result(s, p); move_line_start(s); refresh_line(s)), + "^E" => (s,o...)->(accept_result(s, p); move_line_end(s); refresh_line(s)), + "^Z" => (s,o...)->(return :suspend), # Try to catch all Home/End keys - "\e[H" => s->(accept_result(s, p); move_input_start(s); refresh_line(s)), - "\e[F" => s->(accept_result(s, p); move_input_end(s); refresh_line(s)), + "\e[H" => (s,o...)->(accept_result(s, p); move_input_start(s); refresh_line(s)), + "\e[F" => (s,o...)->(accept_result(s, p); move_input_end(s); refresh_line(s)), # Use ^N and ^P to change search directions and iterate through results - "^N" => :(LineEdit.history_set_backward(data, false); LineEdit.history_next_result(s, data)), - "^P" => :(LineEdit.history_set_backward(data, true); LineEdit.history_next_result(s, data)), + "^N" => (s,data,c)->(history_set_backward(data, false); history_next_result(s, data)), + "^P" => (s,data,c)->(history_set_backward(data, true); history_next_result(s, data)), # Bracketed paste mode - "\e[200~" => quote - ps = LineEdit.state(s, LineEdit.mode(s)) + "\e[200~" => (s,data,c)-> begin + ps = state(s, mode(s)) input = readuntil(ps.terminal, "\e[201~")[1:(end-6)] - LineEdit.edit_insert(data.query_buffer, input); LineEdit.update_display_buffer(s, data) + edit_insert(data.query_buffer, input); update_display_buffer(s, data) end, - "*" => :(LineEdit.edit_insert(data.query_buffer, c1); LineEdit.update_display_buffer(s, data)) + "*" => (s,data,c)->(edit_insert(data.query_buffer, c); update_display_buffer(s, data)) } - p.keymap_func = @eval @LineEdit.keymap $([pkeymap, escape_defaults]) - keymap = { - "^R" => s->(enter_search(s, p, true)), - "^S" => s->(enter_search(s, p, false)), + p.keymap_func = keymap([pkeymap, escape_defaults]) + skeymap = { + "^R" => (s,o...)->(enter_search(s, p, true)), + "^S" => (s,o...)->(enter_search(s, p, false)), } - (p, keymap) + (p, skeymap) end keymap(state, p::HistoryPrompt) = p.keymap_func @@ -1156,7 +1120,7 @@ end const default_keymap = { # Tab - '\t' => s->begin + '\t' => (s,o...)->begin buf = buffer(s) # Yes, we are ignoring the possiblity # the we could be in the middle of a multi-byte @@ -1178,68 +1142,58 @@ const default_keymap = refresh_line(s) end, # Enter - '\r' => quote - if LineEdit.on_enter(s) || (eof(LineEdit.buffer(s)) && s.key_repeats > 1) - LineEdit.commit_line(s) + '\r' => (s,o...)->begin + if on_enter(s) || (eof(buffer(s)) && s.key_repeats > 1) + commit_line(s) return :done else - LineEdit.edit_insert(s, '\n') + edit_insert(s, '\n') end end, '\n' => '\r', # Backspace/^H - '\b' => edit_backspace, + '\b' => (s,o...)->edit_backspace(s), 127 => '\b', # Meta Backspace - "\e\b" => edit_delete_prev_word, + "\e\b" => (s,o...)->edit_delete_prev_word(s), "\e\x7f" => "\e\b", # ^D - 4 => quote - if LineEdit.buffer(s).size > 0 - LineEdit.edit_delete(s) + "^D" => (s,o...)->begin + if buffer(s).size > 0 + edit_delete(s) else - println(LineEdit.terminal(s)) + println(terminal(s)) return :abort end end, - # ^B - 2 => edit_move_left, - # ^F - 6 => edit_move_right, + "^B" => (s,o...)->edit_move_left(s), + "^F" => (s,o...)->edit_move_right(s), # Meta B - "\eb" => edit_move_word_left, + "\eb" => (s,o...)->edit_move_word_left(s), # Meta F - "\ef" => edit_move_word_right, + "\ef" => (s,o...)->edit_move_word_right(s), # Ctrl-Left Arrow "\e[1;5D" => "\eb", # Ctrl-Right Arrow "\e[1;5C" => "\ef", # Meta Enter - "\e\r" => :(LineEdit.edit_insert(s, '\n')), + "\e\r" => (s,o...)->(edit_insert(s, '\n')), "\e\n" => "\e\r", # Simply insert it into the buffer by default - "*" => :(LineEdit.edit_insert(s, c1)), - # ^U - 21 => edit_clear, - # ^K - 11 => edit_kill_line, - # ^Y - 25 => edit_yank, - # ^A - 1 => :(LineEdit.move_line_start(s); LineEdit.refresh_line(s)), - # ^E - 5 => :(LineEdit.move_line_end(s); LineEdit.refresh_line(s)), + "*" => (s,data,c)->(edit_insert(s, c)), + "^U" => (s,o...)->edit_clear(s), + "^K" => (s,o...)->edit_kill_line(s), + "^Y" => (s,o...)->edit_yank(s), + "^A" => (s,o...)->(move_line_start(s); refresh_line(s)), + "^E" => (s,o...)->(move_line_end(s); refresh_line(s)), # Try to catch all Home/End keys - "\e[H" => :(LineEdit.move_input_start(s); LineEdit.refresh_line(s)), - "\e[F" => :(LineEdit.move_input_end(s); LineEdit.refresh_line(s)), - # ^L - 12 => :(Terminals.clear(LineEdit.terminal(s)); LineEdit.refresh_line(s)), - # ^W - 23 => edit_werase, + "\e[H" => (s,o...)->(move_input_start(s); refresh_line(s)), + "\e[F" => (s,o...)->(move_input_end(s); refresh_line(s)), + "^L" => (s,o...)->(Terminals.clear(terminal(s)); refresh_line(s)), + "^W" => (s,o...)->edit_werase(s), # Meta D - "\ed" => edit_delete_next_word, - # ^C - "^C" => s->begin + "\ed" => (s,o...)->edit_delete_next_word(s), + "^C" => (s,o...)->begin try # raise the debugger if present ccall(:jl_raise_debugger, Int, ()) end @@ -1249,19 +1203,19 @@ const default_keymap = transition(s, :reset) refresh_line(s) end, - "^Z" => :(return :suspend), + "^Z" => (s,o...)->(return :suspend), # Right Arrow - "\e[C" => edit_move_right, + "\e[C" => (s,o...)->edit_move_right(s), # Left Arrow - "\e[D" => edit_move_left, + "\e[D" => (s,o...)->edit_move_left(s), # Up Arrow - "\e[A" => edit_move_up, + "\e[A" => (s,o...)->edit_move_up(s), # Down Arrow - "\e[B" => edit_move_down, + "\e[B" => (s,o...)->edit_move_down(s), # Delete - "\e[3~" => edit_delete, + "\e[3~" => (s,o...)->edit_delete(s), # Bracketed Paste Mode - "\e[200~" => s->begin + "\e[200~" => (s,o...)->begin ps = state(s, mode(s)) input = readuntil(ps.terminal, "\e[201~")[1:(end-6)] input = replace(input, '\r', '\n') @@ -1271,25 +1225,21 @@ const default_keymap = end edit_insert(s, input) end, - "^T" => edit_transpose, + "^T" => edit_transpose, } -function history_keymap(hist) - return { - # ^P - 16 => :(LineEdit.history_prev(s, $hist)), - # ^N - 14 => :(LineEdit.history_next(s, $hist)), - # Up Arrow - "\e[A" => :(LineEdit.edit_move_up(s) || LineEdit.history_prev(s, $hist)), - # Down Arrow - "\e[B" => :(LineEdit.edit_move_down(s) || LineEdit.history_next(s, $hist)), - # Page Up - "\e[5~" => :(LineEdit.history_prev_prefix(s, $hist)), - # Page Down - "\e[6~" => :(LineEdit.history_next_prefix(s, $hist)) - } -end +const history_keymap = { + "^P" => (s,o...)->(history_prev(s, mode(s).hist)), + "^N" => (s,o...)->(history_next(s, mode(s).hist)), + # Up Arrow + "\e[A" => (s,o...)->(edit_move_up(s) || history_prev(s, mode(s).hist)), + # Down Arrow + "\e[B" => (s,o...)->(edit_move_down(s) || history_next(s, mode(s).hist)), + # Page Up + "\e[5~" => (s,o...)->(history_prev_prefix(s, mode(s).hist)), + # Page Down + "\e[6~" => (s,o...)->(history_next_prefix(s, mode(s).hist)) +} function deactivate(p::Union(Prompt,HistoryPrompt), s::Union(SearchState,PromptState), termbuf) clear_input_area(termbuf, s) @@ -1337,7 +1287,7 @@ function reset_state(s::MIState) end end -const default_keymap_func = @LineEdit.keymap [LineEdit.default_keymap, LineEdit.escape_defaults] +const default_keymap_func = keymap([default_keymap, escape_defaults]) function Prompt(prompt; first_prompt = prompt, diff --git a/base/REPL.jl b/base/REPL.jl index 4a4f7a9085a98..5c08b7650af36 100644 --- a/base/REPL.jl +++ b/base/REPL.jl @@ -700,7 +700,7 @@ function setup_interface(repl::LineEditREPL; hascolor = repl.hascolor, extra_rep end const repl_keymap = { - ';' => function (s) + ';' => function (s,o...) if isempty(s) || position(LineEdit.buffer(s)) == 0 buf = copy(LineEdit.buffer(s)) transition(s, shell_mode) @@ -710,7 +710,7 @@ function setup_interface(repl::LineEditREPL; hascolor = repl.hascolor, extra_rep edit_insert(s, ';') end end, - '?' => function (s) + '?' => function (s,o...) if isempty(s) || position(LineEdit.buffer(s)) == 0 buf = copy(LineEdit.buffer(s)) transition(s, help_mode) @@ -722,7 +722,7 @@ function setup_interface(repl::LineEditREPL; hascolor = repl.hascolor, extra_rep end, # Bracketed Paste Mode - "\e[200~" => s->begin + "\e[200~" => (s,o...)->begin ps = LineEdit.state(s, LineEdit.mode(s)) input = readuntil(ps.terminal, "\e[201~")[1:(end-6)] input = replace(input, '\r', '\n') @@ -772,13 +772,13 @@ function setup_interface(repl::LineEditREPL; hascolor = repl.hascolor, extra_rep end, } - a = Dict{Any,Any}[hkeymap, repl_keymap, LineEdit.history_keymap(hp), LineEdit.default_keymap, LineEdit.escape_defaults] + a = Dict{Any,Any}[hkeymap, repl_keymap, LineEdit.history_keymap, LineEdit.default_keymap, LineEdit.escape_defaults] prepend!(a, extra_repl_keymap) - julia_prompt.keymap_func = @eval @LineEdit.keymap $(a) + julia_prompt.keymap_func = LineEdit.keymap(a) const mode_keymap = { - '\b' => function (s) + '\b' => function (s,o...) if isempty(s) || position(LineEdit.buffer(s)) == 0 buf = copy(LineEdit.buffer(s)) transition(s, julia_prompt) @@ -788,7 +788,7 @@ function setup_interface(repl::LineEditREPL; hascolor = repl.hascolor, extra_rep LineEdit.edit_backspace(s) end end, - "^C" => function (s) + "^C" => function (s,o...) LineEdit.move_input_end(s) LineEdit.refresh_line(s) print(LineEdit.terminal(s), "^C\n\n") @@ -798,9 +798,9 @@ function setup_interface(repl::LineEditREPL; hascolor = repl.hascolor, extra_rep end } - b = Dict{Any,Any}[hkeymap, mode_keymap, LineEdit.history_keymap(hp), LineEdit.default_keymap, LineEdit.escape_defaults] + b = Dict{Any,Any}[hkeymap, mode_keymap, LineEdit.history_keymap, LineEdit.default_keymap, LineEdit.escape_defaults] - shell_mode.keymap_func = help_mode.keymap_func = @eval @LineEdit.keymap $(b) + shell_mode.keymap_func = help_mode.keymap_func = LineEdit.keymap(b) ModalInterface([julia_prompt, shell_mode, help_mode,hkp]) end From b31bc05e27dee8f8b9b36de9a184ca5ccc5226f0 Mon Sep 17 00:00:00 2001 From: Blake Johnson Date: Sun, 7 Sep 2014 23:20:25 -0400 Subject: [PATCH 17/79] Update LineEdit test. --- test/lineedit.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/lineedit.jl b/test/lineedit.jl index 01a7241198abc..60efd42db265f 100644 --- a/test/lineedit.jl +++ b/test/lineedit.jl @@ -4,24 +4,24 @@ using TestHelpers a_foo = 0 const foo_keymap = { - 'a' => :( global a_foo; a_foo += 1) + 'a' => (o...)->(global a_foo; a_foo += 1) } b_foo = 0 const foo2_keymap = { - 'b' => :( global b_foo; b_foo += 1) + 'b' => (o...)->(global b_foo; b_foo += 1) } a_bar = 0 b_bar = 0 const bar_keymap = { - 'a' => :( global a_bar; a_bar += 1), - 'b' => :( global b_bar; b_bar += 1) + 'a' => (o...)->(global a_bar; a_bar += 1), + 'b' => (o...)->(global b_bar; b_bar += 1) } -test1_func = @eval @LineEdit.keymap $foo_keymap +test1_func = LineEdit.keymap([foo_keymap]) function run_test(f,buf) global a_foo, a_bar, b_bar @@ -34,13 +34,13 @@ end run_test(test1_func,IOBuffer("aa")) @test a_foo == 2 -test2_func = @eval @LineEdit.keymap $([foo2_keymap, foo_keymap]) +test2_func = LineEdit.keymap([foo2_keymap, foo_keymap]) run_test(test2_func,IOBuffer("aaabb")) @test a_foo == 3 @test b_foo == 2 -test3_func = @eval @LineEdit.keymap $([bar_keymap, foo_keymap]) +test3_func = LineEdit.keymap([bar_keymap, foo_keymap]) run_test(test3_func,IOBuffer("aab")) @test a_bar == 2 @@ -186,7 +186,7 @@ end let term = TestHelpers.FakeTerminal(IOBuffer(), IOBuffer(), IOBuffer()) - s = LineEdit.init_state(term, Base.REPL.ModalInterface([Base.REPL.Prompt("test> ")])) + s = LineEdit.init_state(term, ModalInterface([Prompt("test> ")])) buf = LineEdit.buffer(s) LineEdit.edit_insert(s,"first line\nsecond line\nthird line") From b8830db591a9d4699d0a056a120a607e4026a554 Mon Sep 17 00:00:00 2001 From: Blake Johnson Date: Wed, 17 Sep 2014 22:49:07 -0400 Subject: [PATCH 18/79] =?UTF-8?q?Institute=20One=20True=20Behavior?= =?UTF-8?q?=E2=84=A2=20for=20up/down=20arrows.=20Fixes=20#6377.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those that prefer the old behavior can put this in their .juliarc.jl: ```julia import Base: LineEdit, REPL const mykeys = { # Up Arrow "\e[A" => (s,o...)->(LineEdit.edit_move_up(s) || LineEdit.history_prev(s, LineEdit.mode(s).hist)), # Down Arrow "\e[B" => (s,o...)->(LineEdit.edit_move_up(s) || LineEdit.history_next(s, LineEdit.mode(s).hist)), # Page Up "\e[5~" => (s,o...)->(LineEdit.history_prev_prefix(s, LineEdit.mode(s).hist)), # Page Down "\e[B" => (s,o...)->(LineEdit.history_next_prefix(s, LineEdit.mode(s).hist)) } Base.active_repl.interface = REPL.setup_interface(Base.active_repl; extra_repl_keymap = mykeys) ``` --- base/LineEdit.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/LineEdit.jl b/base/LineEdit.jl index 4f2d278e0fb53..f9b18e6445eed 100644 --- a/base/LineEdit.jl +++ b/base/LineEdit.jl @@ -1232,13 +1232,13 @@ const history_keymap = { "^P" => (s,o...)->(history_prev(s, mode(s).hist)), "^N" => (s,o...)->(history_next(s, mode(s).hist)), # Up Arrow - "\e[A" => (s,o...)->(edit_move_up(s) || history_prev(s, mode(s).hist)), + "\e[A" => (s,o...)->(edit_move_up(s) || history_prev_prefix(s, mode(s).hist)), # Down Arrow - "\e[B" => (s,o...)->(edit_move_down(s) || history_next(s, mode(s).hist)), + "\e[B" => (s,o...)->(edit_move_down(s) || history_next_prefix(s, mode(s).hist)), # Page Up - "\e[5~" => (s,o...)->(history_prev_prefix(s, mode(s).hist)), + "\e[5~" => (s,o...)->(history_prev(s, mode(s).hist)), # Page Down - "\e[6~" => (s,o...)->(history_next_prefix(s, mode(s).hist)) + "\e[6~" => (s,o...)->(history_next(s, mode(s).hist)) } function deactivate(p::Union(Prompt,HistoryPrompt), s::Union(SearchState,PromptState), termbuf) From b32a48f5c4e09245f5985034c28908ac152c8da1 Mon Sep 17 00:00:00 2001 From: Erik Schnetter Date: Fri, 19 Sep 2014 11:13:52 -0400 Subject: [PATCH 19/79] signbit returns bool, not int --- base/complex.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/complex.jl b/base/complex.jl index 1253a721814d7..50957e4d5fc56 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -61,7 +61,7 @@ end function complex_show(io::IO, z::Complex, compact::Bool) r, i = reim(z) compact ? showcompact(io,r) : show(io,r) - if signbit(i)==1 && !isnan(i) + if signbit(i) && !isnan(i) i = -i print(io, compact ? "-" : " - ") else From 495015e1f991ae9e69fa5e6b20047f6bbbe29400 Mon Sep 17 00:00:00 2001 From: jake bolewski Date: Fri, 19 Sep 2014 11:34:27 -0400 Subject: [PATCH 20/79] properly show transpose exprs --- base/show.jl | 5 +++++ test/show.jl | 2 ++ 2 files changed, 7 insertions(+) diff --git a/base/show.jl b/base/show.jl index 6138d6d864a37..c2963a4dfd905 100644 --- a/base/show.jl +++ b/base/show.jl @@ -618,6 +618,11 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int) print(io, '&') show_unquoted(io, args[1]) + # transpose + elseif is(head, symbol('\'')) && length(args) == 1 + show_unquoted(io, args[1]) + print(io, '\'') + # print anything else as "Expr(head, args...)" else print(io, "\$(Expr(") diff --git a/test/show.jl b/test/show.jl index 499c85cf2ec6a..5ad5ad63c101f 100644 --- a/test/show.jl +++ b/test/show.jl @@ -171,3 +171,5 @@ end""" @test_repr "Int[i for i=1:10]" @test_repr "Int[(i, j) for (i, j) in zip(1:10,1:0)]" + +@test_repr "[1 2 3; 4 5 6; 7 8 9]'" From 8806a2d5548442c959528a62e6fe2910ed1b507e Mon Sep 17 00:00:00 2001 From: Erik Schnetter Date: Fri, 19 Sep 2014 13:52:45 -0400 Subject: [PATCH 21/79] Avoid more cases where signbit is treated as int --- base/hashing2.jl | 4 ++-- base/printf.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/base/hashing2.jl b/base/hashing2.jl index 342e2dc6c8a93..af0ae10189b53 100644 --- a/base/hashing2.jl +++ b/base/hashing2.jl @@ -101,7 +101,7 @@ function decompose(x::Float32) s = int32(n & 0x007fffff) e = int32(n & 0x7f800000 >> 23) s |= int32(e != 0) << 23 - d = ifelse(signbit(n) == 1, -1, 1) + d = ifelse(signbit(n), -1, 1) int(s), int(e - 150 + (e == 0)), d end @@ -112,7 +112,7 @@ function decompose(x::Float64) s = int64(n & 0x000fffffffffffff) e = int64(n & 0x7ff0000000000000 >> 52) s |= int64(e != 0) << 52 - d = ifelse(signbit(n) == 1, -1, 1) + d = ifelse(signbit(n), -1, 1) int(s), int(e - 1075 + (e == 0)), d end diff --git a/base/printf.jl b/base/printf.jl index 44783afa62f1f..9d717deeb9238 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -749,7 +749,7 @@ end function ini_dec(x::SmallFloatingPoint, n::Int) if x == 0.0 ccall(:memset, Ptr{Void}, (Ptr{Void}, Cint, Csize_t), DIGITS, '0', n) - return int32(1), int32(1), bool(signbit(x)) + return int32(1), int32(1), signbit(x) else len,pt,neg,buffer = grisu(x,Grisu.PRECISION,n) end From 9fa2c991a11768166b5dec7b2e7e11f375db4301 Mon Sep 17 00:00:00 2001 From: Erik Schnetter Date: Fri, 19 Sep 2014 14:24:47 -0400 Subject: [PATCH 22/79] Correct signbit documentation --- doc/helpdb.jl | 4 ++-- doc/manual/mathematical-operations.rst | 2 +- doc/stdlib/base.rst | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/helpdb.jl b/doc/helpdb.jl index 5df537f887e7b..24427da072139 100644 --- a/doc/helpdb.jl +++ b/doc/helpdb.jl @@ -4516,8 +4516,8 @@ popdisplay(d::Display) ("Base","signbit","signbit(x) - Returns \"1\" if the value of the sign of \"x\" is negative, - otherwise \"0\". + Returns \"true\" if the value of the sign of \"x\" is negative, + otherwise \"false\". "), diff --git a/doc/manual/mathematical-operations.rst b/doc/manual/mathematical-operations.rst index 987f813dc412f..c6ce1c6446653 100644 --- a/doc/manual/mathematical-operations.rst +++ b/doc/manual/mathematical-operations.rst @@ -377,7 +377,7 @@ Function Description ``abs(x)`` a positive value with the magnitude of ``x`` ``abs2(x)`` the squared magnitude of ``x`` ``sign(x)`` indicates the sign of ``x``, returning -1, 0, or +1 -``signbit(x)`` indicates whether the sign bit is on (1) or off (0) +``signbit(x)`` indicates whether the sign bit is on (true) or off (false) ``copysign(x,y)`` a value with the magnitude of ``x`` and the sign of ``y`` ``flipsign(x,y)`` a value with the magnitude of ``x`` and the sign of ``x*y`` ================= =========================================================== diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index 3eb5681956ca1..306a75c4830b4 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -3145,7 +3145,7 @@ Mathematical Functions .. function:: signbit(x) - Returns ``1`` if the value of the sign of ``x`` is negative, otherwise ``0``. + Returns ``true`` if the value of the sign of ``x`` is negative, otherwise ``false``. .. function:: flipsign(x, y) From 8ac035be3a6ca12d0164acd02571f09d5835aea8 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Fri, 19 Sep 2014 11:49:04 -0700 Subject: [PATCH 23/79] use https download url for gmp this was the only dependency url using ftp:// --- deps/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/Makefile b/deps/Makefile index 4eecda4ccd2c7..ef877293b6626 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -1466,7 +1466,7 @@ GMP_SRC_TARGET = gmp-$(GMP_VER)/.libs/libgmp.$(SHLIB_EXT) GMP_OBJ_TARGET = $(build_shlibdir)/libgmp.$(SHLIB_EXT) gmp-$(GMP_VER).tar.bz2: - $(JLDOWNLOAD) $@ ftp://ftp.gmplib.org/pub/gmp-$(GMP_VER)/$@ + $(JLDOWNLOAD) $@ https://gmplib.org/download/gmp/$@ gmp-$(GMP_VER)/configure: gmp-$(GMP_VER).tar.bz2 $(JLCHECKSUM) $< $(TAR) jxf $< From 892e746dc536c6cef9cb4d225d2ed5f61800d9fc Mon Sep 17 00:00:00 2001 From: John Myles White Date: Tue, 26 Aug 2014 18:46:44 -0700 Subject: [PATCH 24/79] Add a parametric Nullable{T} type --- base/exports.jl | 13 +- base/nullable.jl | 50 ++++++++ base/sysimg.jl | 3 + doc/manual/index.rst | 1 + doc/manual/nullable-types.rst | 87 +++++++++++++ test/nullable.jl | 230 ++++++++++++++++++++++++++++++++++ test/runtests.jl | 4 +- 7 files changed, 382 insertions(+), 6 deletions(-) create mode 100644 base/nullable.jl create mode 100644 doc/manual/nullable-types.rst create mode 100644 test/nullable.jl diff --git a/base/exports.jl b/base/exports.jl index 093583b5620c3..a1e193288e0de 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -61,6 +61,7 @@ export MathConst, Matrix, MergeSort, + Nullable, ObjectIdDict, OrdinalRange, PollingFileWatcher, @@ -145,6 +146,7 @@ export KeyError, LoadError, MethodError, + NullException, ParseError, ProcessExitedException, SystemError, @@ -197,7 +199,7 @@ export ≠, !==, ≡, - ≢, + ≢, $, %, &, @@ -964,7 +966,7 @@ export rfft, xcorr, -# numerical integration +# numerical integration quadgk, # iteration @@ -1010,7 +1012,7 @@ export toc, toq, -#dates +# dates Date, DateTime, now, @@ -1229,7 +1231,7 @@ export # shared arrays sdata, indexpids, - + # paths and file names abspath, basename, @@ -1323,6 +1325,9 @@ export unsafe_pointer_to_objref, unsafe_store!, +# nullable types + isnull, + # Macros @__FILE__, @b_str, diff --git a/base/nullable.jl b/base/nullable.jl new file mode 100644 index 0000000000000..40e38f20fb545 --- /dev/null +++ b/base/nullable.jl @@ -0,0 +1,50 @@ +immutable Nullable{T} + isnull::Bool + value::T + + Nullable() = new(true) + Nullable(value::T) = new(false, value) +end + +immutable NullException <: Exception +end + +Nullable{T}(value::T) = Nullable{T}(value) + +function convert{S, T}(::Type{Nullable{T}}, x::Nullable{S}) + return isnull(x) ? Nullable{T}() : Nullable(convert(T, get(x))) +end + +function show{T}(io::IO, x::Nullable{T}) + if x.isnull + @printf(io, "Nullable{%s}()", repr(T)) + else + @printf(io, "Nullable(%s)", repr(x.value)) + end +end + +get(x::Nullable) = x.isnull ? throw(NullException()) : x.value + +get{S, T}(x::Nullable{S}, y::T) = x.isnull ? convert(S, y) : x.value + +isnull(x::Nullable) = x.isnull + +function isequal{S, T}(x::Nullable{S}, y::Nullable{T}) + if x.isnull && y.isnull + return true + elseif x.isnull || y.isnull + return false + else + return isequal(x.value, y.value) + end +end + +=={S, T}(x::Nullable{S}, y::Nullable{T}) = throw(NullException()) + +function hash(x::Nullable, h::Uint) + if x.isnull + return h + uint(0x932e0143e51d0171) + else + return hash(x.value, h + uint(0x932e0143e51d0171)) + end +end diff --git a/base/sysimg.jl b/base/sysimg.jl index 3c69dbc01fea1..2c96e8ac5d835 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -270,6 +270,9 @@ importall .Profile include("Dates.jl") import .Dates: Date, DateTime, now +# nullable types +include("nullable.jl") + function __init__() # Base library init reinit_stdio() diff --git a/doc/manual/index.rst b/doc/manual/index.rst index 389b8b8eea3ba..7143b505296ad 100644 --- a/doc/manual/index.rst +++ b/doc/manual/index.rst @@ -28,6 +28,7 @@ linear-algebra networking-and-streams parallel-computing + nullable-types interacting-with-julia running-external-programs calling-c-and-fortran-code diff --git a/doc/manual/nullable-types.rst b/doc/manual/nullable-types.rst new file mode 100644 index 0000000000000..fb8efcab97401 --- /dev/null +++ b/doc/manual/nullable-types.rst @@ -0,0 +1,87 @@ +.. _man-nullable-types: + +******************************************* +Nullable Types: Representing Missing Values +******************************************* + +In many settings, you need to interact with a value of type ``T`` that may or +may not exist. To handle these settings, Julia provides a parametric type +called ``Nullable{T}``, which can be thought of as a specialized container +type that can contain either zero or one values. ``Nullable{T}`` provides a +minimal interface designed to ensure that interactions with missing values +are safe. At present, the interface consists of four possible interactions: + +- Construct a ``Nullable`` object. +- Check if an ``Nullable`` object has a missing value. +- Access the value of a ``Nullable`` object with a guarantee that a + ``NullException`` will be thrown if the object's value is missing. +- Access the value of a ``Nullable`` object with a guarantee that a default + value of type ``T`` will be returned if the object's value is missing. + +Constructing ``Nullable`` objects +--------------------------------- + +To construct an object representing a missing value of type ``T``, use the +``Nullable{T}()`` function: + +.. doctest:: + + x1 = Nullable{Int}() + x2 = Nullable{Float64}() + x3 = Nullable{Vector{Int}}() + +To construct an object representing a non-missing value of type ``T``, use the +``Nullable(x::T)`` function: + +.. doctest:: + + x1 = Nullable(1) + x2 = Nullable(1.0) + x3 = Nullable([1, 2, 3]) + +Note the core distinction between these two ways of constructing a ``Nullable`` +object: in one style, you provide a type, ``T``, as a function parameter; in +the other style, you provide a single value of type ``T`` as an argument. + +Checking if an ``Nullable`` object has a value +---------------------------------------------- + +You can check if a ``Nullable`` object has any value using the ``isnull`` +function: + +.. doctest:: + + isnull(Nullable{Float64}()) + isnull(Nullable(0.0)) + +Safely accessing the value of an ``Nullable`` object +---------------------------------------------------- + +You can safely access the value of an ``Nullable`` object using the ``get`` +function: + +.. doctest:: + + get(Nullable{Float64}()) + get(Nullable(1.0)) + +If the value is not present, as it would be for ``Nullable{Float64}``, a +``NullException`` error will be thrown. The error-throwing nature of the +``get`` function ensures that any attempt to access a missing value immediately +fails. + +In cases for which a reasonable default value exists that could be used +when a ``Nullable`` object's value turns out to be missing, you can provide this +default value as a second argument to ``get``: + +.. doctest:: + + get(Nullable{Float64}(), 0) + get(Nullable(1.0), 0) + +Note that this default value will automatically be converted to the type of +the ``Nullable`` object that you attempt to access using the ``get`` function. +For example, in the code shown above the value ``0`` would be automatically +converted to a ``Float64`` value before being returned. The presence of default +replacement values makes it easy to use the ``get`` function to write +type-stable code that interacts with sources of potentially missing values. diff --git a/test/nullable.jl b/test/nullable.jl new file mode 100644 index 0000000000000..b46a26c339c5d --- /dev/null +++ b/test/nullable.jl @@ -0,0 +1,230 @@ +types = [ + Bool, + Char, + Float16, + Float32, + Float64, + Int128, + Int16, + Int32, + Int64, + Int8, + Uint16, + Uint32, + Uint64, + Uint8, +] + +# Nullable{T}() = new(true) +for T in types + x = Nullable{T}() + @test x.isnull === true + @test isa(x.value, T) +end + +# Nullable{T}(value::T) = new(false, value) +for T in types + x = Nullable{T}(zero(T)) + @test x.isnull === false + @test isa(x.value, T) + @test x.value === zero(T) + + x = Nullable{T}(one(T)) + @test x.isnull === false + @test isa(x.value, T) + @test x.value === one(T) +end + +# immutable NullException <: Exception +@test isa(NullException(), NullException) +@test_throws NullException throw(NullException()) + +# Nullable{T}(value::T) = Nullable{T}(value) +for T in types + v = zero(T) + x = Nullable(v) + @test x.isnull === false + @test isa(x.value, T) + @test x.value === v + + v = one(T) + x = Nullable(v) + @test x.isnull === false + @test isa(x.value, T) + @test x.value === v +end + +p1s = [ + "Nullable{Bool}()", + "Nullable{Char}()", + "Nullable{Float16}()", + "Nullable{Float32}()", + "Nullable{Float64}()", + "Nullable{Int128}()", + "Nullable{Int16}()", + "Nullable{Int32}()", + "Nullable{Int64}()", + "Nullable{Int8}()", + "Nullable{Uint16}()", + "Nullable{Uint32}()", + "Nullable{Uint64}()", + "Nullable{Uint8}()", +] + +p2s = [ + "Nullable(false)", + "Nullable('\0')", + "Nullable(float16(0.0))", + "Nullable(0.0f0)", + "Nullable(0.0)", + "Nullable(0)", + "Nullable(0)", + "Nullable(0)", + "Nullable(0)", + "Nullable(0)", + "Nullable(0x0000)", + "Nullable(0x00000000)", + "Nullable(0x0000000000000000)", + "Nullable(0x00)", +] + +p3s = [ + "Nullable(true)", + "Nullable('\x01')", + "Nullable(float16(1.0))", + "Nullable(1.0f0)", + "Nullable(1.0)", + "Nullable(1)", + "Nullable(1)", + "Nullable(1)", + "Nullable(1)", + "Nullable(1)", + "Nullable(0x0001)", + "Nullable(0x00000001)", + "Nullable(0x0000000000000001)", + "Nullable(0x01)", +] + +# show{T}(io::IO, x::Nullable{T}) +io = IOBuffer() +for (i, T) in enumerate(types) + x1 = Nullable{T}() + x2 = Nullable(zero(T)) + x3 = Nullable(one(T)) + show(io, x1) + takebuf_string(io) == p1s[i] + show(io, x2) + takebuf_string(io) == p2s[i] + show(io, x3) + takebuf_string(io) == p3s[i] +end + +# get(x::Nullable) +for T in types + x1 = Nullable{T}() + x2 = Nullable(zero(T)) + x3 = Nullable(one(T)) + + @test_throws NullException get(x1) + @test get(x2) === zero(T) + @test get(x3) === one(T) +end + +# get{S, T}(x::Nullable{S}, y::T) +for T in types + x1 = Nullable{T}() + x2 = Nullable(zero(T)) + x3 = Nullable(one(T)) + + @test get(x1, zero(T)) === zero(T) + @test get(x1, one(T)) === one(T) + @test get(x2, one(T)) === zero(T) + @test get(x3, zero(T)) === one(T) +end + +# isnull(x::Nullable) +for T in types + x1 = Nullable{T}() + x2 = Nullable(zero(T)) + x3 = Nullable(one(T)) + + @test isnull(x1) === true + @test isnull(x2) === false + @test isnull(x3) === false +end + +# function isequal{S, T}(x::Nullable{S}, y::Nullable{T}) +for T in types + x1 = Nullable{T}() + x2 = Nullable{T}() + x3 = Nullable(zero(T)) + x4 = Nullable(one(T)) + + @test isequal(x1, x1) === true + @test isequal(x1, x2) === true + @test isequal(x1, x3) === false + @test isequal(x1, x4) === false + + @test isequal(x2, x1) === true + @test isequal(x2, x2) === true + @test isequal(x2, x3) === false + @test isequal(x2, x4) === false + + @test isequal(x3, x1) === false + @test isequal(x3, x2) === false + @test isequal(x3, x3) === true + @test isequal(x3, x4) === false + + @test isequal(x4, x1) === false + @test isequal(x4, x2) === false + @test isequal(x4, x3) === false + @test isequal(x4, x4) === true +end + +# function =={S, T}(x::Nullable{S}, y::Nullable{T}) +for T in types + x1 = Nullable{T}() + x2 = Nullable{T}() + x3 = Nullable(zero(T)) + x4 = Nullable(one(T)) + + @test_throws NullException (x1 == x1) + @test_throws NullException (x1 == x2) + @test_throws NullException (x1 == x3) + @test_throws NullException (x1 == x4) + + @test_throws NullException (x2 == x1) + @test_throws NullException (x2 == x2) + @test_throws NullException (x2 == x3) + @test_throws NullException (x2 == x4) + + @test_throws NullException (x3 == x1) + @test_throws NullException (x3 == x2) + @test_throws NullException (x3 == x3) + @test_throws NullException (x3 == x4) + + @test_throws NullException (x4 == x1) + @test_throws NullException (x4 == x2) + @test_throws NullException (x4 == x3) + @test_throws NullException (x4 == x4) +end + +# function hash(x::Nullable, h::Uint) +for T in types + x1 = Nullable{T}() + x2 = Nullable{T}() + x3 = Nullable(zero(T)) + x4 = Nullable(one(T)) + + @test isa(hash(x1), Uint) + @test isa(hash(x2), Uint) + @test isa(hash(x3), Uint) + @test isa(hash(x4), Uint) + + @test hash(x1) == hash(x2) + @test hash(x1) != hash(x3) + @test hash(x1) != hash(x4) + @test hash(x2) != hash(x3) + @test hash(x2) != hash(x4) + @test hash(x3) != hash(x4) +end diff --git a/test/runtests.jl b/test/runtests.jl index 49798ce055db7..b4a901af28861 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -9,7 +9,7 @@ testnames = [ "floatapprox", "readdlm", "reflection", "regex", "float16", "combinatorics", "sysinfo", "rounding", "ranges", "mod2pi", "euler", "show", "lineedit", "replcompletions", "repl", "test", "examples", "goto", - "llvmcall", "grisu" + "llvmcall", "grisu", "nullable" ] @unix_only push!(testnames, "unicode") @@ -35,7 +35,7 @@ end cd(dirname(@__FILE__)) do n = 1 - if net_on + if net_on n = min(8, CPU_CORES, length(tests)) n > 1 && addprocs(n; exeflags=`--check-bounds=yes`) blas_set_num_threads(1) From af423242c9e635b463af29cc197c16729897144e Mon Sep 17 00:00:00 2001 From: Simon Hoke Date: Fri, 19 Sep 2014 15:30:21 -0700 Subject: [PATCH 25/79] fix typo in faq forward port of 457165ed from release-0.3 branch ref: #8421 --- doc/manual/faq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/faq.rst b/doc/manual/faq.rst index 4cf8927c40458..f69bf40a07737 100644 --- a/doc/manual/faq.rst +++ b/doc/manual/faq.rst @@ -721,7 +721,7 @@ Do I want to use a release, beta, or nightly version of Julia? You may prefer the release version of Julia if you are looking for a stable code base. Releases generally occur every 6 months, giving you a stable platform for writing code. -You may prefer the beta version of Julia if you don't mind being slightly behind the latest bugfixes and changes, but find the slightly slower rate of changes more appealing. Additionally, these binaries are tested before they are published to ensure they are fully functional. +You may prefer the beta version of Julia if you don't mind being slightly behind the latest bugfixes and changes, but find the slightly faster rate of changes more appealing. Additionally, these binaries are tested before they are published to ensure they are fully functional. You may prefer the nightly version of Julia if you want to take advantage of the latest updates to the language, and don't mind if the version available today occasionally doesn't actually work. From 62fe48bef37129f91a8c474359b24073ce275e73 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Sat, 20 Sep 2014 15:58:48 +0200 Subject: [PATCH 26/79] Improve DISTRIBUTING.md, fix a detail in README.md In README.md, i486 does not work (issue #7185), better take a correct example. --- DISTRIBUTING.md | 55 +++++++++++++++++++++++++++++++++++++++++++------ README.md | 2 +- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/DISTRIBUTING.md b/DISTRIBUTING.md index dbbb6fc57c765..9322f2db23fcf 100644 --- a/DISTRIBUTING.md +++ b/DISTRIBUTING.md @@ -10,7 +10,7 @@ order to create a portable, working Julia distribution, we have separated most of the notes by OS. Note that while the code for Julia is -[MIT-licensed](https://github.com/JuliaLang/julia/blob/master/LICENSE.md), +[MIT-licensed, with a few exceptions](https://github.com/JuliaLang/julia/blob/master/LICENSE.md), the distribution created by the techniques described herein will be GPL licensed, as various dependent libraries such as `FFTW`, `Rmath`, `SuiteSparse`, and `git` are GPL licensed. We do hope to have a @@ -26,7 +26,7 @@ pregenerate the `base/version_git.jl` file with: make -C base version_git.jl.phony -Juila has lots of build dependencies where we use patched versions that has not +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 @@ -43,6 +43,25 @@ to create a Make.user file containing: override TAGGED_RELEASE_BANNER = "my-package-repository build" +Target Architectures +-------------------- + +By default, Julia optimizes its system image to the native architecture of +the build machine. This is usually not what you want when building packages, +as it will make Julia fail at startup on any machine with incompatible CPUs +(in particular older ones with more restricted instruction sets). + +We therefore recommend that you pass the `MARCH` variable when calling `make`, +setting it to the baseline target you intend to support. This will determine +the target CPU for both the Julia executable and libraries, and the system +image (the latter can also be set using `JULIA_CPU_TARGET`). Typically useful +values for x86 CPUs are `x86-64` and `core2` (for 64-bit builds) and +`pentium4` (for 32-bit builds). Unfortunately, CPUs older than Pentium 4 +are currently not supported (see +[this issue](https://github.com/JuliaLang/julia/issues/7185)). + +The full list of CPU targets supported by LLVM can be obtained by running +`llc -mattr=help`. Linux ----- @@ -52,10 +71,17 @@ 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. Although we have not yet experimented +for Debian and Ubuntu-based systems. See the +[Fedora package](https://admin.fedoraproject.org/pkgdb/package/julia/) +for RPM-based distributions. Although we have not yet experimented with it, [Alien](https://wiki.debian.org/Alien) could be used to generate Julia packages for various Linux distributions. +Julia supports overriding standard installation directories via `prefix` +and other environment variables you can pass when calling `make` and +`make install`. See Make.inc for their list. `DESTDIR` can also be used +to force the installation into a temporary directory. + By default, Julia loads `$prefix/etc/julia/juliarc.jl` as an installation-wide initialization file. This file can be used by distribution managers to provide paths to various binaries such as a @@ -102,8 +128,8 @@ Notes on BLAS and LAPACK Julia builds OpenBLAS by default, which includes the BLAS and LAPACK libraries. On 32-bit architectures, Julia builds OpenBLAS to use 32-bit integers, while on 64-bit architectuers, Julia builds OpenBLAS -to use 64-bit integers. It is essential that all Julia functions that -call BLAS and LAPACK API routines use integers of the correct width. +to use 64-bit integers (ILP64). It is essential that all Julia functions +that call BLAS and LAPACK API routines use integers of the correct width. Most BLAS and LAPACK distributions provided on linux distributions, and even commercial implementations ship libraries that use 32-bit @@ -120,6 +146,22 @@ all libraries that depend on BLAS and LAPACK. The Julia build process will build all these libraries correctly, but when overriding defaults and using system provided libraries, this consistency must be ensured. +Also note that Linux distributions sometimes ship several versions of +OpenBLAS, some of which enable multithreading, and others only working +in a serial fashion. For example, in Fedora, `libopenblasp.so` is threaded, +but `libopenblas.so` is not. We recommend using the former for optimal +performance. To choose an OpenBLAS library whose name is different from +the default `libopenblas.so`, pass `LIBBLAS=-l$(YOURBLAS)` and +`LIBBLASNAME=lib$(YOURBLAS)` to `make`, replacing `$(YOURBLAS)` with the +name of your library. You can also add `.so.0` to the name of the library +if you want your package to work without requiring the unversioned `.so` +symlink. + +Finally, OpenBLAS includes its own optimized version of LAPACK. If you +set `USE_SYSTEM_BLAS=1` and `USE_SYSTEM_LAPACK=1`, you should also set +`LIBLAPACK=-l$(YOURBLAS)` and `LIBLAPACKNAME=lib$(YOURBLAS)`. Else, the +reference LAPACK will be used and performance will typically be much lower. + Notes on Rmath ============== @@ -136,7 +178,8 @@ used. Compilation scripts =================== -The [julia-nightly-packaging](https://github.com/staticfloat/julia-nightly-packaging) repository contains multiple example scripts to ease the creation of +The [julia-nightly-packaging](https://github.com/staticfloat/julia-nightly-packaging) +repository contains multiple example scripts to ease the creation of binary packages. It also includes miscellaneous tools to do things such as fetching the last good commit that passed the [Travis](https://travis-ci.org/JuliaLang/julia/builds) tests. diff --git a/README.md b/README.md index ccec6c8f3a39b..0332c4e7849d0 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ Julia does not install anything outside the directory it was cloned into. Julia Julia can be built for a non-generic architecture by configuring the `ARCH` Makefile variable. See the appropriate section of `Make.inc` for additional customization options, such as `MARCH` and `JULIA_CPU_TARGET`. -For example, to build for i486, set `ARCH=i486` and install the necessary system libraries for linking. On Ubuntu, these may include lib32gfortran3 (also manually call `ln -s /usr/lib32/libgfortran3.so.0 /usr/lib32/libgfortran3.so`) and lib32gcc1, lib32stdc++6, among others. +For example, to build for Pentium 4, set `MARCH=pentium4` and install the necessary system libraries for linking. On Ubuntu, these may include lib32gfortran3 (also manually call `ln -s /usr/lib32/libgfortran3.so.0 /usr/lib32/libgfortran3.so`) and lib32gcc1, lib32stdc++6, among others. You can also set `MARCH=native` for a maximum-performance build customized for the current machine CPU. From 542cf9d93eaa95e4a768560c61be35ed79028a48 Mon Sep 17 00:00:00 2001 From: Jiahao Chen Date: Sat, 20 Sep 2014 10:45:17 -0400 Subject: [PATCH 27/79] Document eigenvector format. Closes #8383 - Documentation for eigvecs and eigfact now explain that eigenvectors are stored in columns of F[:vectors]. - Also added output type annotations for eigvecs and eigfact. - Minor language cleanup - Add line breaks --- doc/stdlib/linalg.rst | 65 +++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/doc/stdlib/linalg.rst b/doc/stdlib/linalg.rst index 974901ec65e7c..2ececc2f53b39 100644 --- a/doc/stdlib/linalg.rst +++ b/doc/stdlib/linalg.rst @@ -183,7 +183,8 @@ Linear algebra functions in Julia are largely implemented by calling functions f .. function:: eig(A,[irange,][vl,][vu,][permute=true,][scale=true]) -> D, V - Compute eigenvalues and eigenvectors of ``A``. See :func:`eigfact` for details on the ``balance`` keyword argument. + Computes eigenvalues and eigenvectors of ``A``. See :func:`eigfact` for + details on the ``balance`` keyword argument. .. doctest:: @@ -194,19 +195,31 @@ Linear algebra functions in Julia are largely implemented by calling functions f 0.0 1.0 0.0 0.0 0.0 1.0) - ``eig`` is a wrapper around :func:`eigfact`, extracting all parts of the factorization to a tuple; where possible, using :func:`eigfact` is recommended. + ``eig`` is a wrapper around :func:`eigfact`, extracting all parts of the + factorization to a tuple; where possible, using :func:`eigfact` is + recommended. .. function:: eig(A, B) -> D, V Computes generalized eigenvalues and vectors of ``A`` with respect to ``B``. - ``eig`` is a wrapper around :func:`eigfact`, extracting all parts of the factorization to a tuple; where possible, using :func:`eigfact` is recommended. + ``eig`` is a wrapper around :func:`eigfact`, extracting all parts of the + factorization to a tuple; where possible, using :func:`eigfact` is + recommended. .. function:: eigvals(A,[irange,][vl,][vu]) - Returns the eigenvalues of ``A``. If ``A`` is :func:`Symmetric`, :func:`Hermitian` or :func:`SymTridiagonal`, it is possible to calculate only a subset of the eigenvalues by specifying either a :func:`UnitRange` ``irange`` covering indices of the sorted eigenvalues, or a pair ``vl`` and ``vu`` for the lower and upper boundaries of the eigenvalues. + Returns the eigenvalues of ``A``. If ``A`` is :func:`Symmetric`, + :func:`Hermitian` or :func:`SymTridiagonal`, it is possible to calculate + only a subset of the eigenvalues by specifying either a :func:`UnitRange` + ``irange`` covering indices of the sorted eigenvalues, or a pair ``vl`` and + ``vu`` for the lower and upper boundaries of the eigenvalues. - For general non-symmetric matrices it is possible to specify how the matrix is balanced before the eigenvector calculation. The option ``permute=true`` permutes the matrix to become closer to upper triangular, and ``scale=true`` scales the matrix by its diagonal elements to make rows and columns more equal in norm. The default is ``true`` for both options. + For general non-symmetric matrices it is possible to specify how the matrix + is balanced before the eigenvector calculation. The option ``permute=true`` + permutes the matrix to become closer to upper triangular, and ``scale=true`` + scales the matrix by its diagonal elements to make rows and columns more + equal in norm. The default is ``true`` for both options. .. function:: eigmax(A) @@ -216,28 +229,50 @@ Linear algebra functions in Julia are largely implemented by calling functions f Returns the smallest eigenvalue of ``A``. -.. function:: eigvecs(A, [eigvals,][permute=true,][scale=true]) +.. function:: eigvecs(A, [eigvals,][permute=true,][scale=true]) -> Matrix - Returns the eigenvectors of ``A``. + Returns a matrix ``M`` whose columns are the eigenvectors of ``A``. + (The ``k``th eigenvector can be obtained from the slice ``M[:, k]``.) The ``permute`` and ``scale`` keywords are the same as for :func:`eigfact`. - For :func:`SymTridiagonal` matrices, if the optional vector of eigenvalues ``eigvals`` is specified, returns the specific corresponding eigenvectors. + For :func:`SymTridiagonal` matrices, if the optional vector of eigenvalues + ``eigvals`` is specified, returns the specific corresponding eigenvectors. -.. function:: eigfact(A,[irange,][vl,][vu,][permute=true,][scale=true]) +.. function:: eigfact(A,[irange,][vl,][vu,][permute=true,][scale=true]) -> Eigen - Compute the eigenvalue decomposition of ``A`` and return an ``Eigen`` object. If ``F`` is the factorization object, the eigenvalues can be accessed with ``F[:values]`` and the eigenvectors with ``F[:vectors]``. The following functions are available for ``Eigen`` objects: ``inv``, ``det``. + Computes the eigenvalue decomposition of ``A``, returning an ``Eigen`` + factorization object ``F`` which contains the eigenvalues in ``F[:values]`` + and the eigenvectors in the columns of the matrix ``F[:vectors]``. (The + ``k``th eigenvector can be obtained from the slice ``F[:vectors][:, k]``.) + + The following functions are available for ``Eigen`` objects: ``inv``, + ``det``. - If ``A`` is :func:`Symmetric`, :func:`Hermitian` or :func:`SymTridiagonal`, it is possible to calculate only a subset of the eigenvalues by specifying either a :func:`UnitRange` ``irange`` covering indices of the sorted eigenvalues or a pair ``vl`` and ``vu`` for the lower and upper boundaries of the eigenvalues. + If ``A`` is :func:`Symmetric`, :func:`Hermitian` or :func:`SymTridiagonal`, + it is possible to calculate only a subset of the eigenvalues by specifying + either a :func:`UnitRange` ``irange`` covering indices of the sorted + eigenvalues or a pair ``vl`` and ``vu`` for the lower and upper boundaries + of the eigenvalues. - For general non-symmetric matrices it is possible to specify how the matrix is balanced before the eigenvector calculation. The option ``permute=true`` permutes the matrix to become closer to upper triangular, and ``scale=true`` scales the matrix by its diagonal elements to make rows and columns more equal in norm. The default is ``true`` for both options. + For general nonsymmetric matrices it is possible to specify how the matrix + is balanced before the eigenvector calculation. The option ``permute=true`` + permutes the matrix to become closer to upper triangular, and ``scale=true`` + scales the matrix by its diagonal elements to make rows and columns more + equal in norm. The default is ``true`` for both options. -.. function:: eigfact(A, B) +.. function:: eigfact(A, B) -> GeneralizedEigen - Compute the generalized eigenvalue decomposition of ``A`` and ``B`` and return an ``GeneralizedEigen`` object. If ``F`` is the factorization object, the eigenvalues can be accessed with ``F[:values]`` and the eigenvectors with ``F[:vectors]``. + Computes the generalized eigenvalue decomposition of ``A`` and ``B``, + returning a ``GeneralizedEigen`` factorization object ``F`` which contains + the generalized eigenvalues in ``F[:values]`` and the generalized + eigenvectors in the columns of the matrix ``F[:vectors]``. (The ``k``th + generalized eigenvector can be obtained from the slice ``F[:vectors][:, + k]``.) .. function:: eigfact!(A, [B]) - ``eigfact!`` is the same as :func:`eigfact`, but saves space by overwriting the input A (and B), instead of creating a copy. + Same as :func:`eigfact`, but saves space by overwriting the input ``A`` (and + ``B``), instead of creating a copy. .. function:: hessfact(A) From b382a743e6e7b00e8a375b9b722b27cd9f5e7168 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Sat, 20 Sep 2014 16:38:45 +0200 Subject: [PATCH 28/79] Install icon and .desktop file during make install Makes packagers' lives easier, looks better and ensures Julia will show up in software centers like GNOME Software. --- Makefile | 7 +++++ contrib/julia.desktop | 8 ++++++ contrib/julia.svg | 62 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 contrib/julia.desktop create mode 100644 contrib/julia.svg diff --git a/Makefile b/Makefile index 9d5da7f18db27..9b03c1e54d5ae 100644 --- a/Makefile +++ b/Makefile @@ -256,6 +256,13 @@ endif -rm -f $(DESTDIR)$(datarootdir)/julia/doc/juliadoc/.gitignore # Copy in beautiful new man page! $(INSTALL_F) $(build_datarootdir)/man/man1/julia.1 $(DESTDIR)$(datarootdir)/man/man1/ + # Copy icon and .desktop file + mkdir -p $(DESTDIR)$(datarootdir)/icons/hicolor/scalable/apps/ + $(INSTALL_F) contrib/julia.svg $(DESTDIR)$(datarootdir)/icons/hicolor/scalable/apps/ + -touch --no-create $(DESTDIR)$(datarootdir)/icons/hicolor/ + -gtk-update-icon-cache $(DESTDIR)$(datarootdir)/icons/hicolor/ + mkdir -p $(DESTDIR)$(datarootdir)/applications/ + $(INSTALL_F) contrib/julia.desktop $(DESTDIR)$(datarootdir)/applications/ # Update RPATH entries of Julia if $(private_libdir_rel) != $(build_private_libdir_rel) ifneq ($(private_libdir_rel),$(build_private_libdir_rel)) diff --git a/contrib/julia.desktop b/contrib/julia.desktop new file mode 100644 index 0000000000000..6b41981354769 --- /dev/null +++ b/contrib/julia.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=Julia +Comment=High-level, high-performance dynamic language for technical computing +Exec=julia +Icon=julia +Terminal=true +Type=Application +Categories=Development;ComputerScience;Building;Science;Math;NumericalAnalysis;ParallelComputing;DataVisualization;ConsoleOnly; diff --git a/contrib/julia.svg b/contrib/julia.svg new file mode 100644 index 0000000000000..b0b03de8a1f09 --- /dev/null +++ b/contrib/julia.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 87fc1db8b3f2c7051e2d037624c28da18013768c Mon Sep 17 00:00:00 2001 From: Jiahao Chen Date: Sat, 20 Sep 2014 12:25:20 -0400 Subject: [PATCH 29/79] Fix typo in lufact docs. Ref #8416 --- doc/stdlib/linalg.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/stdlib/linalg.rst b/doc/stdlib/linalg.rst index 2ececc2f53b39..20a50f1f7b339 100644 --- a/doc/stdlib/linalg.rst +++ b/doc/stdlib/linalg.rst @@ -54,7 +54,7 @@ Linear algebra functions in Julia are largely implemented by calling functions f ----------------------- ------------------------- ---------------------------------------- :func:`Matrix` ``LU`` ``F[:L]*F[:U] == A[F[:p], :]`` :func:`Tridiagonal` ``LU{T,Tridiagonal{T}}`` N/A - :func:`SparseMatrixCSC` ``UmfpackLU`` ``F[:L]*F[:U] == Rs .* A[F[:p], F[:q]]`` + :func:`SparseMatrixCSC` ``UmfpackLU`` ``F[:L]*F[:U] == F[:Rs] .* A[F[:p], F[:q]]`` ======================= ========================= ======================================== The individual components of the factorization ``F`` can be accessed by indexing: From ce42b3e2916d45ed27364f804bb47ddc61022e62 Mon Sep 17 00:00:00 2001 From: Jiahao Chen Date: Sat, 20 Sep 2014 14:13:04 -0400 Subject: [PATCH 30/79] Docs: remove nonexistent Ccomplex_float, Ccomplex_double --- doc/manual/calling-c-and-fortran-code.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/manual/calling-c-and-fortran-code.rst b/doc/manual/calling-c-and-fortran-code.rst index 76ba33df4a540..597c518bd55f8 100644 --- a/doc/manual/calling-c-and-fortran-code.rst +++ b/doc/manual/calling-c-and-fortran-code.rst @@ -245,10 +245,6 @@ Julia type with the same name, prefixed by C. This can help for writing portable +------------------------+-------------------+--------------------------------+ | ``size_t`` | ``Csize_t`` | ``Uint`` | +------------------------+-------------------+--------------------------------+ -| ``complex float`` | ``Ccomplex_float`` (future addition) | -+------------------------+-------------------+--------------------------------+ -| ``complex double`` | ``Ccomplex_double`` (future addition) | -+------------------------+-------------------+--------------------------------+ | ``void`` | | ``Void`` | +------------------------+-------------------+--------------------------------+ | ``void*`` | | ``Ptr{Void}`` | From 87f0ae37796af992c0e71acd57680f6a53218d9c Mon Sep 17 00:00:00 2001 From: Jiahao Chen Date: Sat, 20 Sep 2014 11:28:03 -0400 Subject: [PATCH 31/79] Describe commands useful for updating source trees Closes #7184, #8369 --- README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0332c4e7849d0..9b5bfa7a91d9f 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Once it is built, you can run the `julia` executable using its full path in the - add a soft link to the `julia` executable in the `julia` directory to `/usr/local/bin` (or any suitable directory already in your path), or -- add the `julia` directory to your executable path for this shell session (in bash: `export PATH="$(pwd):$PATH"` ; in csh or tcsh: +- add the `julia` directory to your executable path for this shell session (in `bash`: `export PATH="$(pwd):$PATH"` ; in `csh` or `tcsh`: `set path= ( $path $cwd )` ), or - add the `julia` directory to your executable path permanently (e.g. in `.bash_profile`), or @@ -91,7 +91,7 @@ If everything works correctly, you will see a Julia banner and an interactive pr Your first test of Julia should be to determine whether your build is working properly. From the UNIX/Windows command prompt inside -the julia source directory, type `make testall`. You should see output +the `julia` source directory, type `make testall`. You should see output that lists a series of tests being run; if they complete without error, you should be in good shape to start using Julia. @@ -101,6 +101,52 @@ If you are building a Julia package for distribution on Linux, OS X, or Windows, take a look at the detailed notes in [DISTRIBUTING.md](https://github.com/JuliaLang/julia/blob/master/DISTRIBUTING.md). +### Updating an existing source tree + +If you have previously downloaded `julia` using `git clone`, you can update the +existing source tree using `git pull` rather than starting anew: + + cd julia + git pull && make + +Assuming that you had made no changes to the source tree that will conflict +with upstream updates, these commands will trigger a build to update to the +latest version. + +#### General troubleshooting + +1. Over time, the base library may accumulate enough changes such that the + bootstrapping process in building the system image will fail. If this + happens, the build may fail with an error like + + ```sh + *** This error is usually fixed by running 'make clean'. If the error persists, try 'make cleanall' *** + ``` + + As described, running `make clean && make` is usually sufficient. + Occasionally, the stronger cleanup done by `make cleanall` is needed. + +2. New versions of external dependencies may be introduced which may + occasionally cause conflicts with existing builds of older versions. + + a. Special `make` targets exist to help wipe the existing build of a + dependency. For example, `make -C deps clean-llvm` will clean out the + existing build of `llvm`. + + b. To delete existing binaries of `julia` and all its dependencies, + delete the `./usr` directory _in the source tree_. + +3. In extreme cases, you may wish to reset the source tree to a pristine state. + The following git commands may be helpful: + + ```sh + git reset --hard #Forcibly remove any changes to any files under version control + git clean -x -f -d #Forcibly remove any file or directory not under version control + ``` + + _To avoid losing work, make sure you know what these commands do before you + run them. `git` will not be able to undo these changes!_ + ## Uninstalling Julia From fb032123a89e3105a932f3cabfedab71d137edd4 Mon Sep 17 00:00:00 2001 From: Jiahao Chen Date: Sat, 20 Sep 2014 15:53:02 -0400 Subject: [PATCH 32/79] Remove commented-out references to Ccomplex_* in Base --- base/c.jl | 2 -- base/exports.jl | 2 -- 2 files changed, 4 deletions(-) diff --git a/base/c.jl b/base/c.jl index fee4a98d61a28..c07e3526340a5 100644 --- a/base/c.jl +++ b/base/c.jl @@ -67,8 +67,6 @@ typealias Clonglong Int64 typealias Culonglong Uint64 typealias Cfloat Float32 typealias Cdouble Float64 -#typealias Ccomplex_float Complex64 -#typealias Ccomplex_double Complex128 const sizeof_off_t = ccall(:jl_sizeof_off_t, Cint, ()) diff --git a/base/exports.jl b/base/exports.jl index a1e193288e0de..d6bfb42a36596 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -135,8 +135,6 @@ export Culonglong, Cushort, Cwchar_t, - #Ccomplex_float, - #Ccomplex_double, # Exceptions ArgumentError, From 2eaf48d2662ae124e9f76f33dc74059c4c9a38e8 Mon Sep 17 00:00:00 2001 From: timholy Date: Wed, 10 Sep 2014 09:14:00 -0500 Subject: [PATCH 33/79] Add inline macro via :meta expressions --- base/cartesian.jl | 6 ++++++ base/exports.jl | 3 ++- base/expr.jl | 41 +++++++++++++++++++++++++++++++++++++++++ base/inference.jl | 7 +++---- src/alloc.c | 2 +- src/interpreter.c | 3 +++ src/jltypes.c | 1 + src/julia.h | 2 +- 8 files changed, 58 insertions(+), 7 deletions(-) diff --git a/base/cartesian.jl b/base/cartesian.jl index 9fd9abd0ef382..4c4f6d9bc9b12 100644 --- a/base/cartesian.jl +++ b/base/cartesian.jl @@ -30,6 +30,9 @@ const CARTESIAN_DIMS = 4 # myfunction(A::AbstractArray, I::Int...N) # where N can be an integer or symbol. Currently T...N generates a parser error. macro ngenerate(itersym, returntypeexpr, funcexpr) + if isa(funcexpr, Expr) && funcexpr.head == :macrocall && funcexpr.args[1] == symbol("@inline") + funcexpr = Base._inline(funcexpr.args[2]) + end isfuncexpr(funcexpr) || error("Requires a function expression") esc(ngenerate(itersym, returntypeexpr, funcexpr.args[1], N->sreplace!(copy(funcexpr.args[2]), itersym, N))) end @@ -57,6 +60,9 @@ macro nsplat(itersym, args...) else error("Wrong number of arguments") end + if isa(funcexpr, Expr) && funcexpr.head == :macrocall && funcexpr.args[1] == symbol("@inline") + funcexpr = Base._inline(funcexpr.args[2]) + end isfuncexpr(funcexpr) || error("Second argument must be a function expression") prototype = funcexpr.args[1] body = funcexpr.args[2] diff --git a/base/exports.jl b/base/exports.jl index d6bfb42a36596..d46ceecaba98c 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1384,4 +1384,5 @@ export @inbounds, @simd, @label, - @goto + @goto, + @inline diff --git a/base/expr.jl b/base/expr.jl index f5c297ab9f468..66db044c240aa 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -63,6 +63,13 @@ macro eval(x) :($(esc(:eval))($(Expr(:quote,x)))) end +macro inline(ex) + esc(_inline(ex)) +end + +_inline(ex::Expr) = pushmeta!(ex, :inline) +_inline(arg) = arg + ## some macro utilities ## find_vars(e) = find_vars(e, {}) @@ -95,3 +102,37 @@ function localize_vars(expr, esca) end Expr(:localize, :(()->($expr)), v...) end + +function pushmeta!(ex::Expr, sym::Symbol) + if ex.head == :function + body::Expr = ex.args[2] + if !isempty(body.args) && isa(body.args[1], Expr) && (body.args[1]::Expr).head == :meta + push!((body.args[1]::Expr).args, sym) + else + unshift!(body.args, Expr(:meta, sym)) + end + elseif (ex.head == :(=) && typeof(ex.args[1]) == Expr && ex.args[1].head == :call) + ex = Expr(:function, ex.args[1], Expr(:block, Expr(:meta, sym), ex.args[2])) +# else +# ex = Expr(:withmeta, ex, sym) + end + ex +end + +function popmeta!(body::Expr, sym::Symbol) + if isa(body.args[1],Expr) && (body.args[1]::Expr).head === :meta + metaargs = (body.args[1]::Expr).args + for i = 1:length(metaargs) + if metaargs[i] == sym + if length(metaargs) == 1 + shift!(body.args) # get rid of :meta Expr + else + deleteat!(metaargs, i) # delete this portion of the metadata + end + return true + end + end + end + false +end +popmeta!(arg, sym) = false diff --git a/base/inference.jl b/base/inference.jl index b589538e8c976..834d9d0d94799 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -2496,10 +2496,9 @@ const inline_incompletematch_allowed = false inline_worthy(body, cost::Real) = true function inline_worthy(body::Expr, cost::Real=1.0) # precondition: 0head == simdloop_sym) { return (jl_value_t*)jl_nothing; } + else if (ex->head == meta_sym) { + return (jl_value_t*)jl_nothing; + } jl_errorf("unsupported or misplaced expression %s", ex->head->name); return (jl_value_t*)jl_nothing; } diff --git a/src/jltypes.c b/src/jltypes.c index 26d6226d811aa..70875ea48a72d 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -3261,6 +3261,7 @@ void jl_init_types(void) newvar_sym = jl_symbol("newvar"); copyast_sym = jl_symbol("copyast"); simdloop_sym = jl_symbol("simdloop"); + meta_sym = jl_symbol("meta"); } #ifdef __cplusplus diff --git a/src/julia.h b/src/julia.h index b95c9e91d2c1a..13a04464728a5 100644 --- a/src/julia.h +++ b/src/julia.h @@ -421,7 +421,7 @@ extern jl_sym_t *abstracttype_sym; extern jl_sym_t *bitstype_sym; extern jl_sym_t *compositetype_sym; extern jl_sym_t *type_goto_sym; extern jl_sym_t *global_sym; extern jl_sym_t *tuple_sym; extern jl_sym_t *boundscheck_sym; extern jl_sym_t *copyast_sym; -extern jl_sym_t *simdloop_sym; +extern jl_sym_t *simdloop_sym; extern jl_sym_t *meta_sym; // object accessors ----------------------------------------------------------- From 67b58f259962e28b6c59d1fea816f9af8a19f289 Mon Sep 17 00:00:00 2001 From: timholy Date: Thu, 11 Sep 2014 04:29:18 -0500 Subject: [PATCH 34/79] Add missing check for meta_sym in codegen.cpp --- src/codegen.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/codegen.cpp b/src/codegen.cpp index 01712675e995c..a5d15be94308a 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3006,6 +3006,9 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, "Warning: could not attach metadata for @simd loop.\n"); return NULL; } + else if (head == meta_sym) { + return literal_pointer_val((jl_value_t*)jl_nothing); // will change as new metadata gets added + } else { if (!strcmp(head->name, "$")) jl_error("syntax: prefix $ in non-quoted expression"); From 106e4f71847df094b1463fd0d86ad827083942d4 Mon Sep 17 00:00:00 2001 From: timholy Date: Thu, 11 Sep 2014 12:56:38 -0500 Subject: [PATCH 35/79] Add tests --- test/Makefile | 2 +- test/meta.jl | 27 +++++++++++++++++++++++++++ test/runtests.jl | 2 +- 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 test/meta.jl diff --git a/test/Makefile b/test/Makefile index f29d46ee09829..50b06f512c40e 100644 --- a/test/Makefile +++ b/test/Makefile @@ -8,7 +8,7 @@ TESTS = all core keywordargs numbers strings unicode collections hashing \ suitesparse complex version pollfd mpfr broadcast socket floatapprox \ priorityqueue readdlm reflection regex float16 combinatorics dates \ sysinfo rounding ranges mod2pi euler show lineedit replcompletions \ - backtrace repl test examples goto llvmcall grisu + backtrace repl test examples goto llvmcall grisu meta default: all diff --git a/test/meta.jl b/test/meta.jl new file mode 100644 index 0000000000000..0958567bea071 --- /dev/null +++ b/test/meta.jl @@ -0,0 +1,27 @@ +# test meta-expressions that annotate blocks of code + +module MetaTest + +using Base.Test + +function f(x) + y = x+5 + z = y*y + q = z/y + m = q-3 +end + +@inline function f_inlined(x) + y = x+5 + z = y*y + q = z/y + m = q-3 +end + +g(x) = f(2x) +g_inlined(x) = f_inlined(2x) + +@test g(3) == g_inlined(3) +@test f(3) == f_inlined(3) + +end diff --git a/test/runtests.jl b/test/runtests.jl index b4a901af28861..379f89e99a78e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -9,7 +9,7 @@ testnames = [ "floatapprox", "readdlm", "reflection", "regex", "float16", "combinatorics", "sysinfo", "rounding", "ranges", "mod2pi", "euler", "show", "lineedit", "replcompletions", "repl", "test", "examples", "goto", - "llvmcall", "grisu", "nullable" + "llvmcall", "grisu", "nullable", "meta" ] @unix_only push!(testnames, "unicode") From d7c4bf3ba1b013e7b939f2c8725bdadf8ad4ac37 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Sat, 20 Sep 2014 20:16:56 -0400 Subject: [PATCH 36/79] Add multiplication for SymTridiagonal and some tests. Tiny efficiency improvement for Tridiagonal multiplication. Generalize some promotion methods for matrix multiplication to work for AbstractMatrix. Factor out tridiagonal tests. --- base/linalg/matmul.jl | 44 +++++++-------- base/linalg/tridiag.jl | 35 ++++++++++-- test/linalg/tridiag.jl | 124 +++++++++++++++++++++++++++++++++++++++++ test/linalg4.jl | 92 ------------------------------ test/runtests.jl | 2 +- 5 files changed, 177 insertions(+), 120 deletions(-) create mode 100644 test/linalg/tridiag.jl diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index 7de0ffad84423..021c59cd3d43e 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -112,50 +112,50 @@ Ac_mul_B!(y::StridedVector, A::StridedMatrix, x::StridedVector) = generic_matvec # Matrix-matrix multiplication -function (*){T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) - TS = promote_type(arithtype(T),arithtype(S)) - A_mul_B!(similar(B,TS,(size(A,1),size(B,2))),A,B) +function (*){T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) + TS = promote_type(arithtype(T), arithtype(S)) + A_mul_B!(similar(B, TS, (size(A,1), size(B,2))), A, B) end A_mul_B!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper!(C, 'N', 'N', A, B) for elty in (Float32,Float64) @eval begin function A_mul_B!(C::StridedMatrix{Complex{$elty}}, A::StridedMatrix{Complex{$elty}}, B::StridedMatrix{$elty}) - Afl = reinterpret($elty,A,(2size(A,1),size(A,2))) - Cfl = reinterpret($elty,C,(2size(C,1),size(C,2))) - gemm_wrapper!(Cfl,'N','N',Afl,B) + Afl = reinterpret($elty, A, (2size(A,1), size(A,2))) + Cfl = reinterpret($elty, C, (2size(C,1), size(C,2))) + gemm_wrapper!(Cfl, 'N', 'N', Afl, B) return C end end end A_mul_B!(C::StridedMatrix, A::StridedMatrix, B::StridedMatrix) = generic_matmatmul!(C, 'N', 'N', A, B) -function At_mul_B{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) - TS = promote_type(arithtype(T),arithtype(S)) - At_mul_B!(similar(B,TS,(size(A,2),size(B,2))),A,B) +function At_mul_B{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) + TS = promote_type(arithtype(T), arithtype(S)) + At_mul_B!(similar(B, TS, (size(A,2), size(B,2))), A, B) end At_mul_B!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = is(A,B) ? syrk_wrapper!(C, 'T', A) : gemm_wrapper!(C, 'T', 'N', A, B) At_mul_B!(C::StridedMatrix, A::StridedMatrix, B::StridedMatrix) = generic_matmatmul!(C, 'T', 'N', A, B) -function A_mul_Bt{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) - TS = promote_type(arithtype(T),arithtype(S)) - A_mul_Bt!(similar(B,TS,(size(A,1),size(B,1))),A,B) +function A_mul_Bt{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) + TS = promote_type(arithtype(T), arithtype(S)) + A_mul_Bt!(similar(B, TS, (size(A,1), size(B,1))), A, B) end A_mul_Bt!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = is(A,B) ? syrk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'T', A, B) for elty in (Float32,Float64) @eval begin function A_mul_Bt!(C::StridedMatrix{Complex{$elty}}, A::StridedMatrix{Complex{$elty}}, B::StridedMatrix{$elty}) - Afl = reinterpret($elty,A,(2size(A,1),size(A,2))) - Cfl = reinterpret($elty,C,(2size(C,1),size(C,2))) - gemm_wrapper!(Cfl,'N','T',Afl,B) + Afl = reinterpret($elty, A, (2size(A,1), size(A,2))) + Cfl = reinterpret($elty, C, (2size(C,1), size(C,2))) + gemm_wrapper!(Cfl, 'N', 'T', Afl, B) return C end end end A_mul_Bt!(C::StridedVecOrMat, A::StridedMatrix, B::StridedMatrix) = generic_matmatmul!(C, 'N', 'T', A, B) -function At_mul_Bt{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) - TS = promote_type(arithtype(T),arithtype(S)) - At_mul_Bt!(similar(B,TS,(size(A,2),size(B,1))),A,B) +function At_mul_Bt{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) + TS = promote_type(arithtype(T), arithtype(S)) + At_mul_Bt!(similar(B, TS, (size(A,2), size(B,1))), A, B) end At_mul_Bt!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper!(C, 'T', 'T', A, B) At_mul_Bt!(C::StridedMatrix, A::StridedMatrix, B::StridedMatrix) = generic_matmatmul!(C, 'T', 'T', A, B) @@ -163,8 +163,8 @@ At_mul_Bt!(C::StridedMatrix, A::StridedMatrix, B::StridedMatrix) = generic_matma Ac_mul_B{T<:BlasReal}(A::StridedMatrix{T}, B::StridedMatrix{T}) = At_mul_B(A, B) Ac_mul_B!{T<:BlasReal}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = At_mul_B!(C, A, B) function Ac_mul_B{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) - TS = promote_type(arithtype(T),arithtype(S)) - Ac_mul_B!(similar(B,TS,(size(A,2),size(B,2))),A,B) + TS = promote_type(arithtype(T), arithtype(S)) + Ac_mul_B!(similar(B, TS, (size(A,2), size(B,2))), A, B) end Ac_mul_B!{T<:BlasComplex}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = is(A,B) ? herk_wrapper!(C,'C',A) : gemm_wrapper!(C,'C', 'N', A, B) Ac_mul_B!(C::StridedMatrix, A::StridedMatrix, B::StridedMatrix) = generic_matmatmul!(C, 'C', 'N', A, B) @@ -178,10 +178,10 @@ end A_mul_Bc!{T<:BlasComplex}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = is(A,B) ? herk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'C', A, B) A_mul_Bc!(C::StridedMatrix, A::StridedMatrix, B::StridedMatrix) = generic_matmatmul!(C, 'N', 'C', A, B) -Ac_mul_Bc{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) = Ac_mul_Bc!(similar(B,promote_type(arithtype(T),arithtype(S)), (size(A,2), size(B,1))), A, B) +Ac_mul_Bc{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) = Ac_mul_Bc!(similar(B, promote_type(arithtype(T), arithtype(S)), (size(A,2), size(B,1))), A, B) Ac_mul_Bc!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::StridedMatrix{T}) = gemm_wrapper!(C, 'C', 'C', A, B) Ac_mul_Bc!(C::StridedMatrix, A::StridedMatrix, B::StridedMatrix) = generic_matmatmul!(C, 'C', 'C', A, B) -Ac_mul_Bt{T,S}(A::StridedMatrix{T}, B::StridedMatrix{S}) = Ac_mul_Bt(similar(B, promote_type(arithtype(A),arithtype(B)), (size(A,2), size(B,1))), A, B) +Ac_mul_Bt{T,S}(A::AbstractMatrix{T}, B::StridedMatrix{S}) = Ac_mul_Bt(similar(B, promote_type(arithtype(A), arithtype(B)), (size(A,2), size(B,1))), A, B) Ac_mul_Bt!(C::StridedMatrix, A::StridedMatrix, B::StridedMatrix) = generic_matmatmul!(C, 'C', 'T', A, B) # Supporting functions for matrix multiplication diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index 02f6fe7221a3c..4c9fe6b58261b 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -49,6 +49,30 @@ end /(A::SymTridiagonal, B::Number) = SymTridiagonal(A.dv/B, A.ev/B) ==(A::SymTridiagonal, B::SymTridiagonal) = (A.dv==B.dv) && (A.ev==B.ev) +function A_mul_B!(C::StridedVecOrMat, S::SymTridiagonal, B::StridedVecOrMat) + m, n = size(B, 1), size(B, 2) + m == size(S, 1) == size(C, 1) || throw(DimensionMismatch("")) + n == size(C, 2) || throw(DimensionMismatch("")) + + α = S.dv + β = S.ev + @inbounds begin + for j = 1:n + x₀, x₊ = B[1, j], B[2, j] + β₀ = β[1] + C[1, j] = α[1]*x₀ + x₊*β₀ + for i = 2:m - 1 + x₋, x₀, x₊ = x₀, x₊, B[i + 1, j] + β₋, β₀ = β₀, β[i] + C[i, j] = β₋*x₋ + α[i]*x₀ + β₀*x₊ + end + C[m, j] = β₀*x₀ + α[m]*x₊ + end + end + + return C +end + ## Solver function \{T<:BlasFloat}(M::SymTridiagonal{T}, rhs::StridedVecOrMat{T}) if stride(rhs, 1) == 1 @@ -239,16 +263,17 @@ function A_mul_B!(C::AbstractVecOrMat, A::Tridiagonal, B::AbstractVecOrMat) u = A.du @inbounds begin for j = 1:nB - C[1,j] = d[1]*B[1,j] + u[1]*B[2,j] - for i = 2:nA-1 - C[i,j] = l[i-1]*B[i-1,j] + d[i]*B[i,j] + u[i]*B[i+1,j] + b₀, b₊ = B[1, j], B[2, j] + C[1, j] = d[1]*b₀ + u[1]*b₊ + for i = 2:nA - 1 + b₋, b₀, b₊ = b₀, b₊, B[i + 1, j] + C[i, j] = l[i - 1]*b₋ + d[i]*b₀ + u[i]*b₊ end - C[nA,j] = l[nA-1]*B[nA-1,j] + d[nA]*B[nA,j] + C[nA, j] = l[nA - 1]*b₀ + d[nA]*b₊ end end C end -*(A::Tridiagonal, B::AbstractVecOrMat) = A_mul_B!(similar(B), A, B) A_ldiv_B!(A::Tridiagonal,B::AbstractVecOrMat) = A_ldiv_B!(lufact!(A), B) At_ldiv_B!(A::Tridiagonal,B::AbstractVecOrMat) = At_ldiv_B!(lufact!(A), B) diff --git a/test/linalg/tridiag.jl b/test/linalg/tridiag.jl new file mode 100644 index 0000000000000..45445546606f7 --- /dev/null +++ b/test/linalg/tridiag.jl @@ -0,0 +1,124 @@ +debug = false + +using Base.Test + +#Test equivalence of eigenvectors/singular vectors taking into account possible phase (sign) differences +function test_approx_eq_vecs{S<:Real,T<:Real}(a::StridedVecOrMat{S}, b::StridedVecOrMat{T}, error=nothing) + n = size(a, 1) + @test n==size(b,1) && size(a,2)==size(b,2) + error==nothing && (error=n^3*(eps(S)+eps(T))) + for i=1:n + ev1, ev2 = a[:,i], b[:,i] + deviation = min(abs(norm(ev1-ev2)),abs(norm(ev1+ev2))) + if !isnan(deviation) + @test_approx_eq_eps deviation 0.0 error + end + end +end + +n = 12 #Size of matrix problem to test + +debug && println("SymTridiagonal (symmetric tridiagonal) matrices") +for relty in (Float32, Float64), elty in (relty, )#XXX Complex{relty}) doesn't work + debug && println("elty is $(elty), relty is $(relty)") + a = convert(Vector{elty}, randn(n)) + b = convert(Vector{elty}, randn(n-1)) + if elty <: Complex + a += im*convert(Vector{elty}, randn(n)) + b += im*convert(Vector{elty}, randn(n-1)) + end + + A = SymTridiagonal(a, b) + fA = (elty <: Complex ? complex128:float64)(full(A)) + + debug && println("Idempotent tests") + for func in (conj, transpose, ctranspose) + @test func(func(A)) == A + end + + debug && println("Simple unary functions") + for func in (det, inv) + @test_approx_eq_eps func(A) func(fA) n^2*sqrt(eps(relty)) + end + + debug && println("Multiplication with strided vector") + @test_approx_eq A*ones(n) full(A)*ones(n) + + debug && println("Multiplication with strided matrix") + @test_approx_eq A*ones(n, 2) full(A)*ones(n, 2) + + debug && println("Eigensystems") + zero, infinity = convert(elty, 0), convert(elty, Inf) + debug && println("This tests eigenvalue and eigenvector computations using stebz! and stein!") + w, iblock, isplit = LAPACK.stebz!('V', 'B', -infinity, infinity, 0, 0, zero, a, b) + evecs = LAPACK.stein!(a, b, w) + + (e, v) = eig(SymTridiagonal(a, b)) + @test_approx_eq e w + test_approx_eq_vecs(v, evecs) + + debug && println("stein! call using iblock and isplit") + w, iblock, isplit = LAPACK.stebz!('V', 'B', -infinity, infinity, 0, 0, zero, a, b) + evecs = LAPACK.stein!(a, b, w, iblock, isplit) + test_approx_eq_vecs(v, evecs) + + debug && println("Binary operations") + a = convert(Vector{elty}, randn(n)) + b = convert(Vector{elty}, randn(n - 1)) + if elty <: Complex + a += im*convert(Vector{elty}, randn(n - 1)) + b += im*convert(Vector{elty}, randn(n)) + end + + B = SymTridiagonal(a, b) + fB = (elty <: Complex ? complex128:float64)(full(B)) + + for op in (+, -, *) + @test_approx_eq full(op(A, B)) op(fA, fB) + end +end + +debug && println("Tridiagonal matrices") +for relty in (Float32, Float64), elty in (relty, Complex{relty}) + debug && println("relty is $(relty), elty is $(elty)") + a = convert(Vector{elty}, randn(n - 1)) + b = convert(Vector{elty}, randn(n)) + c = convert(Vector{elty}, randn(n - 1)) + if elty <: Complex + a += im*convert(Vector{elty}, randn(n - 1)) + b += im*convert(Vector{elty}, randn(n)) + c += im*convert(Vector{elty}, randn(n - 1)) + end + + A = Tridiagonal(a, b, c) + fA = (elty <: Complex ? complex128:float64)(full(A)) + + debug && println("Simple unary functions") + for func in (det, inv) + @test_approx_eq_eps func(A) func(fA) n^2*sqrt(eps(relty)) + end + + debug && println("Binary operations") + a = convert(Vector{elty}, randn(n - 1)) + b = convert(Vector{elty}, randn(n)) + c = convert(Vector{elty}, randn(n - 1)) + if elty <: Complex + a += im*convert(Vector{elty}, randn(n - 1)) + b += im*convert(Vector{elty}, randn(n)) + c += im*convert(Vector{elty}, randn(n - 1)) + end + + debug && println("Multiplication with strided vector") + @test_approx_eq A*ones(n) full(A)*ones(n) + + debug && println("Multiplication with strided matrix") + @test_approx_eq A*ones(n, 2) full(A)*ones(n, 2) + + + B = Tridiagonal(a, b, c) + fB = (elty <: Complex ? complex128:float64)(full(B)) + + for op in (+, -, *) + @test_approx_eq full(op(A, B)) op(fA, fB) + end +end \ No newline at end of file diff --git a/test/linalg4.jl b/test/linalg4.jl index fe1928298ce9d..8580b715cad05 100644 --- a/test/linalg4.jl +++ b/test/linalg4.jl @@ -25,98 +25,6 @@ end n=12 #Size of matrix problem to test -debug && println("Tridiagonal matrices") -for relty in (Float32, Float64), elty in (relty, Complex{relty}) - debug && println("relty is $(relty), elty is $(elty)") - a = convert(Vector{elty}, randn(n-1)) - b = convert(Vector{elty}, randn(n)) - c = convert(Vector{elty}, randn(n-1)) - if elty <: Complex - a += im*convert(Vector{elty}, randn(n-1)) - b += im*convert(Vector{elty}, randn(n)) - c += im*convert(Vector{elty}, randn(n-1)) - end - - A=Tridiagonal(a, b, c) - fA=(elty<:Complex?complex128:float64)(full(A)) - - debug && println("Simple unary functions") - for func in (det, inv) - @test_approx_eq_eps func(A) func(fA) n^2*sqrt(eps(relty)) - end - - debug && println("Binary operations") - a = convert(Vector{elty}, randn(n-1)) - b = convert(Vector{elty}, randn(n)) - c = convert(Vector{elty}, randn(n-1)) - if elty <: Complex - a += im*convert(Vector{elty}, randn(n-1)) - b += im*convert(Vector{elty}, randn(n)) - c += im*convert(Vector{elty}, randn(n-1)) - end - - B=Tridiagonal(a, b, c) - fB=(elty<:Complex?complex128:float64)(full(B)) - - for op in (+, -, *) - @test_approx_eq full(op(A, B)) op(fA, fB) - end -end - -debug && println("SymTridiagonal (symmetric tridiagonal) matrices") -for relty in (Float32, Float64), elty in (relty, )#XXX Complex{relty}) doesn't work - debug && println("elty is $(elty), relty is $(relty)") - a = convert(Vector{elty}, randn(n)) - b = convert(Vector{elty}, randn(n-1)) - if elty <: Complex - a += im*convert(Vector{elty}, randn(n)) - b += im*convert(Vector{elty}, randn(n-1)) - end - - A=SymTridiagonal(a, b) - fA=(elty<:Complex?complex128:float64)(full(A)) - - debug && println("Idempotent tests") - for func in (conj, transpose, ctranspose) - @test func(func(A)) == A - end - - debug && println("Simple unary functions") - for func in (det, inv) - @test_approx_eq_eps func(A) func(fA) n^2*sqrt(eps(relty)) - end - - debug && println("Eigensystems") - zero, infinity = convert(elty, 0), convert(elty, Inf) - debug && println("This tests eigenvalue and eigenvector computations using stebz! and stein!") - w, iblock, isplit = LinAlg.LAPACK.stebz!('V','B',-infinity,infinity,0,0,zero,a,b) - evecs = LinAlg.LAPACK.stein!(a,b,w) - - (e, v)=eig(SymTridiagonal(a,b)) - @test_approx_eq e w - test_approx_eq_vecs(v, evecs) - - debug && println("stein! call using iblock and isplit") - w, iblock, isplit = LinAlg.LAPACK.stebz!('V','B',-infinity,infinity,0,0,zero,a,b) - evecs = LinAlg.LAPACK.stein!(a,b,w,iblock,isplit) - test_approx_eq_vecs(v, evecs) - - debug && println("Binary operations") - a = convert(Vector{elty}, randn(n)) - b = convert(Vector{elty}, randn(n-1)) - if elty <: Complex - a += im*convert(Vector{elty}, randn(n-1)) - b += im*convert(Vector{elty}, randn(n)) - end - - B=SymTridiagonal(a, b) - fB=(elty<:Complex?complex128:float64)(full(B)) - - for op in (+, -, *) - @test_approx_eq full(op(A, B)) op(fA, fB) - end -end - #Issue #7647: test xsyevr, xheevr, xstevr drivers for Mi7647 in {Symmetric(diagm([1.0:3.0])), Hermitian(diagm([1.0:3.0])), Hermitian(diagm(complex([1.0:3.0]))), SymTridiagonal([1.0:3.0], zeros(2))} diff --git a/test/runtests.jl b/test/runtests.jl index 49798ce055db7..31645cecc20a4 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -21,7 +21,7 @@ tests = (ARGS==["all"] || isempty(ARGS)) ? testnames : ARGS if "linalg" in tests # specifically selected case filter!(x -> x != "linalg", tests) - prepend!(tests, ["linalg1", "linalg2", "linalg3", "linalg4", "linalg/triangular"]) + prepend!(tests, ["linalg1", "linalg2", "linalg3", "linalg4", "linalg/triangular", "linalg/tridiag"]) end net_required_for = ["socket", "parallel"] From 1b4424d71200d190c3a5e350a1a280289362ead4 Mon Sep 17 00:00:00 2001 From: Mike Nolta Date: Sat, 20 Sep 2014 20:38:30 -0400 Subject: [PATCH 37/79] README: tweak MKL instructions Closes #6367, closes #6550. --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9b5bfa7a91d9f..dcafe3fe00ac8 100644 --- a/README.md +++ b/README.md @@ -311,12 +311,15 @@ SuiteSparse is a special case, since it is typically only installed as a static ### Intel compilers and Math Kernel Libraries -To use the Intel [MKL] BLAS and LAPACK libraries, make sure that MKL version 10.3.6 or higher is installed. For a 64-bit architecture, the MKL environment should be set up as follows: +To use the Intel [MKL] BLAS and LAPACK libraries, make sure that MKL version 10.3.6 or higher is installed. +For a 64-bit architecture, the environment should be set up as follows: + # bash source /path/to/mkl/bin/mklvars.sh intel64 ilp64 export MKL_INTERFACE_LAYER=ILP64 -Julia can be built with the Intel compilers and MKL using the following flags. +It is recommended that Intel compilers be used to build julia when using MKL. +Add the following to the `Make.user` file: USEICC = 1 USEIFC = 1 @@ -324,7 +327,7 @@ Julia can be built with the Intel compilers and MKL using the following flags. USE_INTEL_MKL_FFT = 1 USE_INTEL_LIBM = 1 -It is highly recommended to use a fresh clone of the Julia repository. Also, it is recommended that Intel compilers be used to build julia when using MKL. +It is highly recommended to start with a fresh clone of the Julia repository. ## Source Code Organization From 4eb631eef596ca66ca557596b50bea81aeae2916 Mon Sep 17 00:00:00 2001 From: Mike Nolta Date: Sun, 21 Sep 2014 00:29:10 -0400 Subject: [PATCH 38/79] auto-gen 'make test-*' targets --- test/Makefile | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/test/Makefile b/test/Makefile index 50b06f512c40e..173d2055cccf8 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,14 +1,7 @@ JULIAHOME = $(abspath ..) include ../Make.inc -TESTS = all core keywordargs numbers strings unicode collections hashing \ - remote iobuffer arrayops reduce reducedim intfuncs \ - simdloop linalg blas fft dsp sparse bitarray random math functional \ - bigint sorting statistics spawn parallel arpack file git pkg resolve \ - suitesparse complex version pollfd mpfr broadcast socket floatapprox \ - priorityqueue readdlm reflection regex float16 combinatorics dates \ - sysinfo rounding ranges mod2pi euler show lineedit replcompletions \ - backtrace repl test examples goto llvmcall grisu meta +TESTS = all $(filter-out TestHelpers runtests testdefs,$(subst .jl,,$(wildcard *.jl))) default: all From 9775a316ec702c7dd47509cfb31821b9f0fe64c1 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Sun, 21 Sep 2014 19:36:52 +0530 Subject: [PATCH 39/79] Slight refactor of the sparse transpose code. --- base/sparse/csparse.jl | 67 +++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/base/sparse/csparse.jl b/base/sparse/csparse.jl index e59f988b8b00b..d3eb38c95c5d1 100644 --- a/base/sparse/csparse.jl +++ b/base/sparse/csparse.jl @@ -123,22 +123,27 @@ end # Based on Direct Methods for Sparse Linear Systems, T. A. Davis, SIAM, Philadelphia, Sept. 2006. # Section 2.5: Transpose # http://www.cise.ufl.edu/research/sparse/CSparse/ - -# NOTE: When calling transpose!(S,T), the colptr in the result matrix T must be set up -# by counting the nonzeros in every row of S. function transpose!{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, T::SparseMatrixCSC{Tv,Ti}) + (mS, nS) = size(S) + nnzS = nnz(S) + colptr_S = S.colptr + rowval_S = S.rowval + nzval_S = S.nzval + (mT, nT) = size(T) colptr_T = T.colptr rowval_T = T.rowval nzval_T = T.nzval - nnzS = nnz(S) - colptr_S = S.colptr - rowval_S = S.rowval - nzval_S = S.nzval + fill!(colptr_T, 0) + colptr_T[1] = 1 + for i=1:nnzS + @inbounds colptr_T[rowval_S[i]+1] += 1 + end + cumsum!(colptr_T, colptr_T) w = copy(colptr_T) - @inbounds for j = 1:mT, p = colptr_S[j]:(colptr_S[j+1]-1) + @inbounds for j = 1:nS, p = colptr_S[j]:(colptr_S[j+1]-1) ind = rowval_S[p] q = w[ind] w[ind] += 1 @@ -146,43 +151,41 @@ function transpose!{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, T::SparseMatrixCSC{Tv,Ti}) nzval_T[q] = nzval_S[p] end - return SparseMatrixCSC(mT, nT, colptr_T, rowval_T, nzval_T) + return T end function transpose{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) (nT, mT) = size(S) - nnzS = nnz(S) - rowval_S = S.rowval - + nnzS = nnz(S) + colptr_T = Array(Ti, nT+1) rowval_T = Array(Ti, nnzS) nzval_T = Array(Tv, nnzS) - colptr_T = zeros(Ti, nT+1) - colptr_T[1] = 1 - @simd for i=1:nnz(S) - @inbounds colptr_T[rowval_S[i]+1] += 1 - end - colptr_T = cumsum(colptr_T) - T = SparseMatrixCSC(mT, nT, colptr_T, rowval_T, nzval_T) return transpose!(S, T) end -# NOTE: When calling ctranspose!(S,T), the colptr in the result matrix T must be set up -# by counting the nonzeros in every row of S. function ctranspose!{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, T::SparseMatrixCSC{Tv,Ti}) + (mS, nS) = size(S) + nnzS = nnz(S) + colptr_S = S.colptr + rowval_S = S.rowval + nzval_S = S.nzval + (mT, nT) = size(T) colptr_T = T.colptr rowval_T = T.rowval nzval_T = T.nzval - nnzS = nnz(S) - colptr_S = S.colptr - rowval_S = S.rowval - nzval_S = S.nzval + fill!(colptr_T, 0) + colptr_T[1] = 1 + for i=1:nnzS + @inbounds colptr_T[rowval_S[i]+1] += 1 + end + cumsum!(colptr_T, colptr_T) w = copy(colptr_T) - @inbounds for j = 1:mT, p = colptr_S[j]:(colptr_S[j+1]-1) + @inbounds for j = 1:nS, p = colptr_S[j]:(colptr_S[j+1]-1) ind = rowval_S[p] q = w[ind] w[ind] += 1 @@ -190,24 +193,16 @@ function ctranspose!{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, T::SparseMatrixCSC{Tv,Ti} nzval_T[q] = conj(nzval_S[p]) end - return SparseMatrixCSC(mT, nT, colptr_T, rowval_T, nzval_T) + return T end function ctranspose{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) (nT, mT) = size(S) nnzS = nnz(S) - rowval_S = S.rowval - + colptr_T = Array(Ti, nT+1) rowval_T = Array(Ti, nnzS) nzval_T = Array(Tv, nnzS) - colptr_T = zeros(Ti, nT+1) - colptr_T[1] = 1 - @inbounds for i=1:nnz(S) - colptr_T[rowval_S[i]+1] += 1 - end - colptr_T = cumsum(colptr_T) - T = SparseMatrixCSC(mT, nT, colptr_T, rowval_T, nzval_T) return ctranspose!(S, T) end From e3526748f362b0d309ea7d190d6b15792a0b7d3c Mon Sep 17 00:00:00 2001 From: Jiahao Chen Date: Sun, 21 Sep 2014 13:19:07 -0400 Subject: [PATCH 40/79] README: add distclean-$deps description (HT @tkelman) --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dcafe3fe00ac8..843309b0943fc 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,12 @@ latest version. a. Special `make` targets exist to help wipe the existing build of a dependency. For example, `make -C deps clean-llvm` will clean out the - existing build of `llvm`. + existing build of `llvm` so that `llvm` will be rebuilt from the + downloaded source distribution the next time `make` is called. + `make -C deps distclean-llvm` is a stronger wipe which will also delete + the downloaded source distribution, ensuring that a fresh copy of the + source distribution will be downloaded and that any new patches will be + applied the next time `make` is called. b. To delete existing binaries of `julia` and all its dependencies, delete the `./usr` directory _in the source tree_. From 792f0c354519ef1db37210ecdd3e9ce7a7d029b5 Mon Sep 17 00:00:00 2001 From: Jiahao Chen Date: Sun, 21 Sep 2014 13:25:30 -0400 Subject: [PATCH 41/79] README: Fix formatting in IDE paragraph Also references @quinnj's Sublime-IJulia plugin --- README.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 843309b0943fc..3176dd0533c66 100644 --- a/README.md +++ b/README.md @@ -386,6 +386,14 @@ The following distributions include julia, but the versions may be out of date d ## Editor and Terminal Setup -Currently, Julia editing mode support is available for Emacs, Vim, Textmate, Sublime Text, Notepad++, and Kate, in `contrib/`. There is early support for IDEs such as [Lighttable](https://github.com/one-more-minute/Jewel), [QTCreator based JuliaStudio](http://forio.com/labs/julia-studio/), and [Eclipse (LiClipse)](http://brainwy.github.io/liclipse/). A notebook interface is available through [IJulia](https://github.com/JuliaLang/IJulia.jl), which adds Julia support to the iPython notebook. - -In the terminal, Julia makes great use of both control-key and meta-key bindings. To make the meta-key bindings more accessible, many terminal emulator programs (e.g., `Terminal`, `iTerm`, `xterm`, etc) allow you to use the alt or option key as meta. See the section in the manual on [interacting with Julia](http://docs.julialang.org/en/latest/manual/interacting-with-julia/) for more details. +Currently, Julia editing mode support is available for Emacs, Vim, Textmate, +Sublime Text, Notepad++, and Kate, in `contrib/`. There is early support for +IDEs such as [Light Table](https://github.com/one-more-minute/Julia-LT), +[QTCreator based Julia Studio](http://forio.com/labs/julia-studio), and +[Eclipse (LiClipse)](http://brainwy.github.io/liclipse/). A notebook interface +is available through [IJulia](https://github.com/JuliaLang/IJulia.jl), which +adds Julia support to [IPython](http://ipython.org). The +[Sublime-IJulia](https://github.com/quinnj/Sublime-IJulia) plugin enables +interaction between IJulia and Sublime Text. + +In the terminal, Julia makes great use of both control-key and meta-key bindings. To make the meta-key bindings more accessible, many terminal emulator programs (e.g., `Terminal`, `iTerm`, `xterm`, etc.) allow you to use the alt or option key as meta. See the section in the manual on [interacting with Julia](http://docs.julialang.org/en/latest/manual/interacting-with-julia/) for more details. From cf760e2dabcee9f2ea594fffa3ab1ab252f699de Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sun, 21 Sep 2014 11:38:50 -0700 Subject: [PATCH 42/79] add back test-linalg target to run linalg1-4, as well as test/linalg/*.jl --- test/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Makefile b/test/Makefile index 173d2055cccf8..2fe67f6e0ca40 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,7 +1,7 @@ JULIAHOME = $(abspath ..) include ../Make.inc -TESTS = all $(filter-out TestHelpers runtests testdefs,$(subst .jl,,$(wildcard *.jl))) +TESTS = all linalg $(filter-out TestHelpers runtests testdefs,$(subst .jl,,$(wildcard *.jl))) default: all From 4e533dd02dfdc950a34bef0e93da7012783ceb55 Mon Sep 17 00:00:00 2001 From: Mike Nolta Date: Sun, 21 Sep 2014 17:15:17 -0400 Subject: [PATCH 43/79] don't use '-ggdb3' for intel debug builds --- Make.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Make.inc b/Make.inc index 600b4f24639c8..60a9be3938c68 100644 --- a/Make.inc +++ b/Make.inc @@ -294,7 +294,7 @@ CXX = icpc JCFLAGS = -std=gnu99 -pipe $(fPIC) -fno-strict-aliasing -D_FILE_OFFSET_BITS=64 -fp-model precise -fp-model except -no-ftz JCPPFLAGS = JCXXFLAGS = -pipe $(fPIC) -fno-rtti -DEBUGFLAGS = -O0 -ggdb3 -DJL_DEBUG_BUILD -fstack-protector-all +DEBUGFLAGS = -O0 -g -DJL_DEBUG_BUILD -fstack-protector-all SHIPFLAGS = -O3 -g -falign-functions endif From 07bc2c60dd6f3b3570efb6649d1db0312c9deaad Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sun, 21 Sep 2014 18:14:55 -0700 Subject: [PATCH 44/79] add tar.xz filenames for clang, compiler-rt 3.5.0 --- deps/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/deps/Makefile b/deps/Makefile index ef877293b6626..84bbd40e15fbf 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -194,6 +194,9 @@ LLVM_COMPILER_RT_TAR= else ifeq ($(LLVM_VER), 3.3) LLVM_CLANG_TAR=cfe-$(LLVM_VER).src.tar.gz LLVM_COMPILER_RT_TAR=compiler-rt-$(LLVM_VER).src.tar.gz +else ifeq ($(LLVM_VER), 3.5.0) +LLVM_CLANG_TAR=cfe-$(LLVM_VER).src.tar.xz +LLVM_COMPILER_RT_TAR=compiler-rt-$(LLVM_VER).src.tar.xz else LLVM_CLANG_TAR=clang-$(LLVM_VER).src.tar.gz LLVM_COMPILER_RT_TAR=compiler-rt-$(LLVM_VER).src.tar.gz From addf51803f41108871cdf1d2b5573db0f8bd9ce7 Mon Sep 17 00:00:00 2001 From: Carlo Baldassi Date: Mon, 22 Sep 2014 04:45:49 +0200 Subject: [PATCH 45/79] Generalize splice! replacement for BitArrays Follow up to e048f2bf1b8da56b07738c0a4d142cd29e140e98 Also further generalizes the Array version by allowing any iterable (provided it implements length()). --- base/array.jl | 12 ++++++++---- base/bitarray.jl | 22 +++++++++++++++++----- test/bitarray.jl | 28 ++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/base/array.jl b/base/array.jl index 8fe621e97ee6e..80d6cd5100326 100644 --- a/base/array.jl +++ b/base/array.jl @@ -600,8 +600,10 @@ function splice!(a::Vector, i::Integer, ins=_default_splice) a[i] = ins[1] else _growat!(a, i, m-1) - for k = 1:m - a[i+k-1] = ins[k] + k = 1 + for x in ins + a[i+k-1] = x + k += 1 end end return v @@ -636,8 +638,10 @@ function splice!{T<:Integer}(a::Vector, r::UnitRange{T}, ins=_default_splice) end end - for k = 1:m - a[f+k-1] = ins[k] + k = 1 + for x in ins + a[f+k-1] = x + k += 1 end return v end diff --git a/base/bitarray.jl b/base/bitarray.jl index 0c5dfbf6e6198..5a70c49605ca4 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -731,7 +731,7 @@ end const _default_bit_splice = BitVector(0) -function splice!(B::BitVector, r::Union(UnitRange{Int}, Integer), ins::BitVector = _default_bit_splice) +function splice!(B::BitVector, r::Union(UnitRange{Int}, Integer), ins::AbstractArray = _default_bit_splice) n = length(B) i_f = first(r) i_l = last(r) @@ -739,8 +739,10 @@ function splice!(B::BitVector, r::Union(UnitRange{Int}, Integer), ins::BitVector 1 <= i_f <= n+1 || throw(BoundsError()) i_l <= n || throw(BoundsError()) + Bins = convert(BitArray, ins) + if (i_f > n) - append!(B, ins) + append!(B, Bins) return BitVector(0) end @@ -748,7 +750,7 @@ function splice!(B::BitVector, r::Union(UnitRange{Int}, Integer), ins::BitVector Bc = B.chunks - lins = length(ins) + lins = length(Bins) ldel = length(r) new_l = length(B) + lins - ldel @@ -757,7 +759,7 @@ function splice!(B::BitVector, r::Union(UnitRange{Int}, Integer), ins::BitVector delta_k > 0 && ccall(:jl_array_grow_end, Void, (Any, Uint), Bc, delta_k) copy_chunks!(Bc, i_f+lins, Bc, i_l+1, n-i_l) - copy_chunks!(Bc, i_f, ins.chunks, 1, lins) + copy_chunks!(Bc, i_f, Bins.chunks, 1, lins) delta_k < 0 && ccall(:jl_array_del_end, Void, (Any, Uint), Bc, -delta_k) @@ -769,7 +771,17 @@ function splice!(B::BitVector, r::Union(UnitRange{Int}, Integer), ins::BitVector return v end -splice!(B::BitVector, r::Union(UnitRange{Int}, Integer), ins::AbstractVector{Bool}) = splice!(B, r, bitpack(ins)) + +function splice!(B::BitVector, r::Union(UnitRange{Int}, Integer), ins) + Bins = BitArray(length(ins)) + i = 1 + for x in ins + Bins[i] = bool(x) + i += 1 + end + return splice!(B, r, Bins) +end + function empty!(B::BitVector) ccall(:jl_array_del_end, Void, (Any, Uint), B.chunks, length(B.chunks)) diff --git a/test/bitarray.jl b/test/bitarray.jl index 9d28d1718f4c3..6795a0b031b9c 100644 --- a/test/bitarray.jl +++ b/test/bitarray.jl @@ -478,6 +478,20 @@ for m1 = 1 : v1 + 1 i = splice!(i2, m1:m2, i3) @test isequal(bitunpack(b2), i2) @test b == i + b2 = copy(b1) + i2 = copy(i1) + i3 = int(randbool(v2)) + b = splice!(b2, m1:m2, i3) + i = splice!(i2, m1:m2, i3) + @test isequal(bitunpack(b2), i2) + @test b == i + b2 = copy(b1) + i2 = copy(i1) + i3 = [j => rand(0:3) for j = 1:v2] + b = splice!(b2, m1:m2, values(i3)) + i = splice!(i2, m1:m2, values(i3)) + @test isequal(bitunpack(b2), i2) + @test b == i end end end @@ -494,6 +508,20 @@ for m1 = 1 : v1 i = splice!(i2, m1, i3) @test isequal(bitunpack(b2), i2) @test b == i + b2 = copy(b1) + i2 = copy(i1) + i3 = int(randbool(v2)) + b = splice!(b2, m1:m2, i3) + i = splice!(i2, m1:m2, i3) + @test isequal(bitunpack(b2), i2) + @test b == i + b2 = copy(b1) + i2 = copy(i1) + i3 = [j => rand(0:3) for j = 1:v2] + b = splice!(b2, m1:m2, values(i3)) + i = splice!(i2, m1:m2, values(i3)) + @test isequal(bitunpack(b2), i2) + @test b == i end end From e44100fe8ee7d9a862db11f1d31302d8788afa59 Mon Sep 17 00:00:00 2001 From: Carlo Baldassi Date: Mon, 22 Sep 2014 05:13:20 +0200 Subject: [PATCH 46/79] Use inbounds in randperm/randcycle --- base/combinatorics.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/combinatorics.jl b/base/combinatorics.jl index 146a46c151349..dba483b35393e 100644 --- a/base/combinatorics.jl +++ b/base/combinatorics.jl @@ -115,7 +115,7 @@ shuffle(a::AbstractVector) = shuffle!(copy(a)) function randperm(n::Integer) a = Array(typeof(n), n) a[1] = 1 - for i = 2:n + @inbounds for i = 2:n j = rand(1:i) a[i] = a[j] a[j] = i @@ -126,7 +126,7 @@ end function randcycle(n::Integer) a = Array(typeof(n), n) a[1] = 1 - for i = 2:n + @inbounds for i = 2:n j = rand(1:i-1) a[i] = a[j] a[j] = i From b012c1c23f35fe882036baedddcd15e36fae4e9d Mon Sep 17 00:00:00 2001 From: Don MacMillen Date: Mon, 22 Sep 2014 00:28:32 -0700 Subject: [PATCH 47/79] Fixed typos in splice! examples --- doc/stdlib/base.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index 306a75c4830b4..c91f3e327f8b2 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -1158,7 +1158,7 @@ Dequeues are shifted down to fill the resulting gap. If specified, replacement values from an ordered collection will be spliced in place of the removed item. - To insert ``replacement`` before an index ``n`` without removing any items, use ``splice(collection, n-1:n, replacement)``. + To insert ``replacement`` before an index ``n`` without removing any items, use ``splice!(collection, n:n-1, replacement)``. .. function:: splice!(collection, range, [replacement]) -> items @@ -1167,7 +1167,7 @@ Dequeues If specified, replacement values from an ordered collection will be spliced in place of the removed items. - To insert ``replacement`` before an index ``n`` without removing any items, use ``splice(collection, n-1:n, replacement)``. + To insert ``replacement`` before an index ``n`` without removing any items, use ``splice!(collection, n:n-1, replacement)``. .. function:: resize!(collection, n) -> collection From 4c9f628de5bde5f6f2e7b4a31f96f52b8036f5e8 Mon Sep 17 00:00:00 2001 From: ivarne Date: Mon, 22 Sep 2014 10:16:01 +0200 Subject: [PATCH 48/79] Updated helpdb.jl --- doc/helpdb.jl | 140 ++++++++++++++++++++++++++++---------------------- 1 file changed, 80 insertions(+), 60 deletions(-) diff --git a/doc/helpdb.jl b/doc/helpdb.jl index 24427da072139..26b22e64b31ca 100644 --- a/doc/helpdb.jl +++ b/doc/helpdb.jl @@ -30,8 +30,8 @@ ("Base","whos","whos([Module,] [pattern::Regex]) - Print information about exported global variables in a module, optionally - restricted to those matching \"pattern\". + Print information about exported global variables in a module, + optionally restricted to those matching \"pattern\". "), @@ -1611,7 +1611,7 @@ spliced in place of the removed item. To insert \"replacement\" before an index \"n\" without removing - any items, use \"splice(collection, n-1:n, replacement)\". + any items, use \"splice!(collection, n:n-1, replacement)\". "), @@ -1623,7 +1623,7 @@ ordered collection will be spliced in place of the removed items. To insert \"replacement\" before an index \"n\" without removing - any items, use \"splice(collection, n-1:n, replacement)\". + any items, use \"splice!(collection, n:n-1, replacement)\". "), @@ -5715,17 +5715,17 @@ popdisplay(d::Display) "), -("Base","rand","rand(Int32|Uint32|Int64|Uint64|Int128|Uint128[, dims...]) +("Base","rand","rand(t::Type[, dims...]) - Generate a random integer of the given type. Optionally, generate - an array of random integers of the given type by specifying dims. + Generate a random number or array of random numbes of the given + type. "), ("Base","rand","rand(r[, dims...]) - Generate a random integer in the range \"r\" (for example, \"1:n\" - or \"0:2:10\"). Optionally, generate a random integer array. + Pick a random element or array of random elements from range \"r\" + (for example, \"1:n\" or \"0:2:10\"). "), @@ -5736,13 +5736,6 @@ popdisplay(d::Display) "), -("Base","randbool!","randbool!(A) - - Fill an array with random boolean values. A may be an \"Array\" or - a \"BitArray\". - -"), - ("Base","randn","randn([rng], dims or [dims...]) Generate a normally-distributed random number with mean 0 and @@ -5851,13 +5844,29 @@ popdisplay(d::Display) ("Base","zeros","zeros(type, dims) - Create an array of all zeros of specified type + Create an array of all zeros of specified type. The type defaults + to Float64 if not specified. + +"), + +("Base","zeros","zeros(A) + + Create an array of all zeros with the same element type and shape + as A. "), ("Base","ones","ones(type, dims) - Create an array of all ones of specified type + Create an array of all ones of specified type. The type defaults to + Float64 if not specified. + +"), + +("Base","ones","ones(A) + + Create an array of all ones with the same element type and shape as + A. "), @@ -5873,15 +5882,15 @@ popdisplay(d::Display) "), -("Base","fill","fill(v, dims) +("Base","fill","fill(x, dims) - Create an array filled with \"v\" + Create an array filled with the value \"x\" "), ("Base","fill!","fill!(A, x) - Fill array \"A\" with value \"x\" + Fill the array \"A\" with the value \"x\" "), @@ -9812,15 +9821,15 @@ Millisecond(v) \"Complex{Float64}\" the return type is \"UmfpackLU\". Some examples are shown in the table below. - +-------------------------+---------------------------+------------------------------------------+ - | Type of input \\\"A\\\" | Type of output \\\"F\\\" | Relationship between \\\"F\\\" and \\\"A\\\" | - +-------------------------+---------------------------+------------------------------------------+ - | \\\"Matrix()\\\" | \\\"LU\\\" | \\\"F[:L]*F[:U] == A[F[:p], :]\\\" | - +-------------------------+---------------------------+------------------------------------------+ - | \\\"Tridiagonal()\\\" | \\\"LU{T,Tridiagonal{T}}\\\" | N/A | - +-------------------------+---------------------------+------------------------------------------+ - | \\\"SparseMatrixCSC()\\\" | \\\"UmfpackLU\\\" | \\\"F[:L]*F[:U] == Rs .* A[F[:p], F[:q]]\\\" | - +-------------------------+---------------------------+------------------------------------------+ + +-------------------------+---------------------------+----------------------------------------------+ + | Type of input \\\"A\\\" | Type of output \\\"F\\\" | Relationship between \\\"F\\\" and \\\"A\\\" | + +-------------------------+---------------------------+----------------------------------------------+ + | \\\"Matrix()\\\" | \\\"LU\\\" | \\\"F[:L]*F[:U] == A[F[:p], :]\\\" | + +-------------------------+---------------------------+----------------------------------------------+ + | \\\"Tridiagonal()\\\" | \\\"LU{T,Tridiagonal{T}}\\\" | N/A | + +-------------------------+---------------------------+----------------------------------------------+ + | \\\"SparseMatrixCSC()\\\" | \\\"UmfpackLU\\\" | \\\"F[:L]*F[:U] == F[:Rs] .* A[F[:p], F[:q]]\\\" | + +-------------------------+---------------------------+----------------------------------------------+ The individual components of the factorization \"F\" can be accessed by indexing: @@ -10044,7 +10053,7 @@ Millisecond(v) ("Base","eig","eig(A,[irange,][vl,][vu,][permute=true,][scale=true]) -> D, V - Compute eigenvalues and eigenvectors of \"A\". See \"eigfact()\" + Computes eigenvalues and eigenvectors of \"A\". See \"eigfact()\" for details on the \"balance\" keyword argument. julia> eig([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0]) @@ -10101,10 +10110,12 @@ Millisecond(v) "), -("Base","eigvecs","eigvecs(A, [eigvals,][permute=true,][scale=true]) +("Base","eigvecs","eigvecs(A, [eigvals,][permute=true,][scale=true]) -> Matrix - Returns the eigenvectors of \"A\". The \"permute\" and \"scale\" - keywords are the same as for \"eigfact()\". + Returns a matrix \"M\" whose columns are the eigenvectors of \"A\". + (The \"k``th eigenvector can be obtained from the slice ``M[:, + k]\".) The \"permute\" and \"scale\" keywords are the same as for + \"eigfact()\". For \"SymTridiagonal()\" matrices, if the optional vector of eigenvalues \"eigvals\" is specified, returns the specific @@ -10112,42 +10123,47 @@ Millisecond(v) "), -("Base","eigfact","eigfact(A,[il,][iu,][vl,][vu,][permute=true,][scale=true]) +("Base","eigfact","eigfact(A,[irange,][vl,][vu,][permute=true,][scale=true]) -> Eigen - Compute the eigenvalue decomposition of \"A\" and return an - \"Eigen\" object. If \"F\" is the factorization object, the - eigenvalues can be accessed with \"F[:values]\" and the - eigenvectors with \"F[:vectors]\". The following functions are - available for \"Eigen\" objects: \"inv\", \"det\". + Computes the eigenvalue decomposition of \"A\", returning an + \"Eigen\" factorization object \"F\" which contains the eigenvalues + in \"F[:values]\" and the eigenvectors in the columns of the matrix + \"F[:vectors]\". (The \"k``th eigenvector can be obtained from the + slice ``F[:vectors][:, k]\".) - If \"A\" is \"Symmetric\", \"Hermitian\" or \"SymTridiagonal\", it - is possible to calculate only a subset of the eigenvalues by - specifying either a *UnitRange`* \"irange\" covering indices of the - sorted eigenvalues or a pair \"vl\" and \"vu\" for the lower and - upper boundaries of the eigenvalues. + The following functions are available for \"Eigen\" objects: + \"inv\", \"det\". - For general non-symmetric matrices it is possible to specify how - the matrix is balanced before the eigenvector calculation. The - option \"permute=true\" permutes the matrix to become closer to - upper triangular, and \"scale=true\" scales the matrix by its - diagonal elements to make rows and columns more equal in norm. The - default is \"true\" for both options. + If \"A\" is \"Symmetric()\", \"Hermitian()\" or + \"SymTridiagonal()\", it is possible to calculate only a subset of + the eigenvalues by specifying either a \"UnitRange()\" \"irange\" + covering indices of the sorted eigenvalues or a pair \"vl\" and + \"vu\" for the lower and upper boundaries of the eigenvalues. + + For general nonsymmetric matrices it is possible to specify how the + matrix is balanced before the eigenvector calculation. The option + \"permute=true\" permutes the matrix to become closer to upper + triangular, and \"scale=true\" scales the matrix by its diagonal + elements to make rows and columns more equal in norm. The default + is \"true\" for both options. "), -("Base","eigfact","eigfact(A, B) +("Base","eigfact","eigfact(A, B) -> GeneralizedEigen - Compute the generalized eigenvalue decomposition of \"A\" and \"B\" - and return an \"GeneralizedEigen\" object. If \"F\" is the - factorization object, the eigenvalues can be accessed with - \"F[:values]\" and the eigenvectors with \"F[:vectors]\". + Computes the generalized eigenvalue decomposition of \"A\" and + \"B\", returning a \"GeneralizedEigen\" factorization object \"F\" + which contains the generalized eigenvalues in \"F[:values]\" and + the generalized eigenvectors in the columns of the matrix + \"F[:vectors]\". (The \"k``th generalized eigenvector can be + obtained from the slice ``F[:vectors][:, k]\".) "), ("Base","eigfact!","eigfact!(A[, B]) - \"eigfact!\" is the same as \"eigfact()\", but saves space by - overwriting the input A (and B), instead of creating a copy. + Same as \"eigfact()\", but saves space by overwriting the input + \"A\" (and \"B\"), instead of creating a copy. "), @@ -11052,11 +11068,15 @@ Millisecond(v) "), -("Base.Pkg","init","init() +("Base.Pkg","init","init(meta::String=DEFAULT_META, branch::String=META_BRANCH) Initialize \"Pkg.dir()\" as a package directory. This will be done automatically when the \"JULIA_PKGDIR\" is not set and - \"Pkg.dir()\" uses its default value. + \"Pkg.dir()\" uses its default value. As part of this process, + clones a local METADATA git repository from the site and branch + specified by its arguments, which are typically not provided. + Explicit (non-default) arguments can be used to support a custom + METADATA setup. "), From 2f88a24355c7df525062fd94d1cc927d1318d9bf Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Tue, 23 Sep 2014 11:18:39 +0530 Subject: [PATCH 49/79] fix call to edit_transpose ("^T") --- base/LineEdit.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/LineEdit.jl b/base/LineEdit.jl index f9b18e6445eed..91fdea40e71e6 100644 --- a/base/LineEdit.jl +++ b/base/LineEdit.jl @@ -1225,7 +1225,7 @@ const default_keymap = end edit_insert(s, input) end, - "^T" => edit_transpose, + "^T" => (s,o...)->edit_transpose(s), } const history_keymap = { From dafbc59de468dedd1430b236945a0f6d81c59ea4 Mon Sep 17 00:00:00 2001 From: Kevin Squire Date: Tue, 23 Sep 2014 06:46:50 -0700 Subject: [PATCH 50/79] Formatting: use spaces instead of tabs for indentation --- base/abstractarray.jl | 2 +- base/inference.jl | 2 +- base/linalg/arpack.jl | 8 ++--- base/linalg/dense.jl | 2 +- base/linalg/ldlt.jl | 72 +++++++++++++++++++++---------------------- base/pkg.jl | 4 +-- base/pkg/cache.jl | 6 ++-- base/socket.jl | 2 +- 8 files changed, 49 insertions(+), 49 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index fbf860299bee9..a663a5eab9d03 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -941,7 +941,7 @@ end function ipermutedims(A::AbstractArray,perm) iperm = Array(Int,length(perm)) for i = 1:length(perm) - iperm[perm[i]] = i + iperm[perm[i]] = i end return permutedims(A,iperm) end diff --git a/base/inference.jl b/base/inference.jl index 834d9d0d94799..c2f25b7ad78fb 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1346,7 +1346,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) if la > 0 lastarg = ast.args[1][la] if is_rest_arg(lastarg) - if atypes === Tuple + if atypes === Tuple if la > 1 atypes = tuple(NTuple{la-1,Any}..., Tuple[1]) end diff --git a/base/linalg/arpack.jl b/base/linalg/arpack.jl index 6bdfd1dcfa947..1e60e4274a6a0 100644 --- a/base/linalg/arpack.jl +++ b/base/linalg/arpack.jl @@ -20,11 +20,11 @@ function aupd_wrapper(T, matvecA::Function, matvecB::Function, solveSI::Function rwork = cmplx ? Array(TR, ncv) : Array(TR, 0) if isempty(v0) - resid = Array(T, n) - info = zeros(BlasInt, 1) + resid = Array(T, n) + info = zeros(BlasInt, 1) else - resid = deepcopy(v0) - info = ones(BlasInt, 1) + resid = deepcopy(v0) + info = ones(BlasInt, 1) end iparam = zeros(BlasInt, 11) ipntr = zeros(BlasInt, (sym && !cmplx) ? 11 : 14) diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index c8ef8f11860c0..0960c65468f3a 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -269,7 +269,7 @@ function expm!{T<:BlasFloat}(A::StridedMatrix{T}) end end - # Undo the balancing + # Undo the balancing for j = ilo:ihi scj = scale[j] for i = 1:n diff --git a/base/linalg/ldlt.jl b/base/linalg/ldlt.jl index 117f4a034bee2..2d5016c82bd2f 100644 --- a/base/linalg/ldlt.jl +++ b/base/linalg/ldlt.jl @@ -14,44 +14,44 @@ convert{T,S,U}(::Type{Factorization{T}}, F::LDLt{S,U}) = convert(LDLt{T,U}, F) # SymTridiagonal function ldltfact!{T<:Real}(S::SymTridiagonal{T}) - n = size(S,1) - d = S.dv - e = S.ev - @inbounds for i = 1:n-1 - e[i] /= d[i] - d[i+1] -= abs2(e[i])*d[i] - d[i+1] > 0 || throw(PosDefException(i+1)) - end - return LDLt{T,SymTridiagonal{T}}(S) + n = size(S,1) + d = S.dv + e = S.ev + @inbounds for i = 1:n-1 + e[i] /= d[i] + d[i+1] -= abs2(e[i])*d[i] + d[i+1] > 0 || throw(PosDefException(i+1)) + end + return LDLt{T,SymTridiagonal{T}}(S) end function ldltfact{T}(M::SymTridiagonal{T}) - S = typeof(zero(T)/one(T)) - return S == T ? ldltfact!(copy(M)) : ldltfact!(convert(SymTridiagonal{S}, M)) + S = typeof(zero(T)/one(T)) + return S == T ? ldltfact!(copy(M)) : ldltfact!(convert(SymTridiagonal{S}, M)) end 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("")) - d = S.data.dv - l = S.data.ev - @inbounds begin - for i = 2:n - li1 = l[i-1] - for j = 1:nrhs - B[i,j] -= li1*B[i-1,j] - end - end - dn = d[n] - for j = 1:nrhs - B[n,j] /= dn - end - for i = n-1:-1:1 - di = d[i] - li = l[i] - for j = 1:nrhs - B[i,j] /= di - B[i,j] -= li*B[i+1,j] - end - end - end - return B + n, nrhs = size(B, 1), size(B, 2) + size(S,1) == n || throw(DimensionMismatch("")) + d = S.data.dv + l = S.data.ev + @inbounds begin + for i = 2:n + li1 = l[i-1] + for j = 1:nrhs + B[i,j] -= li1*B[i-1,j] + end + end + dn = d[n] + for j = 1:nrhs + B[n,j] /= dn + end + for i = n-1:-1:1 + di = d[i] + li = l[i] + for j = 1:nrhs + B[i,j] /= di + B[i,j] -= li*B[i+1,j] + end + end + end + return B end diff --git a/base/pkg.jl b/base/pkg.jl index e53c0aff261ca..7bef424bbbb07 100644 --- a/base/pkg.jl +++ b/base/pkg.jl @@ -50,7 +50,7 @@ tag(pkg::String, sym::Symbol, commit::String) = cd(Entry.tag,pkg,sym,false,commi tag(pkg::String, ver::VersionNumber; force::Bool=false) = cd(Entry.tag,pkg,ver,force) tag(pkg::String, ver::VersionNumber, commit::String; force::Bool=false) = - cd(Entry.tag,pkg,ver,force,commit) + cd(Entry.tag,pkg,ver,force,commit) submit(pkg::String) = cd(Entry.submit,pkg) submit(pkg::String, commit::String) = cd(Entry.submit,pkg,commit) @@ -61,7 +61,7 @@ build() = cd(Entry.build) build(pkgs::String...) = cd(Entry.build,[pkgs...]) generate(pkg::String, license::String; force::Bool=false, authors::Union(String,Array) = [], config::Dict=Dict()) = - cd(Generate.package,pkg,license,force=force,authors=authors,config=config) + cd(Generate.package,pkg,license,force=force,authors=authors,config=config) test(;coverage::Bool=false) = cd(Entry.test; coverage=coverage) diff --git a/base/pkg/cache.jl b/base/pkg/cache.jl index b0d7bc4d4e9c1..23d0c44a9a327 100644 --- a/base/pkg/cache.jl +++ b/base/pkg/cache.jl @@ -40,9 +40,9 @@ function prefetch{S<:String}(pkg::String, url::String, sha1s::Vector{S}) Git.set_remote_url(url, dir=cache) if !all(sha1->Git.iscommit(sha1, dir=cache), sha1s) info("Updating cache of $pkg...") - Git.success(`remote update`, dir=cache) || - error("couldn't update $cache using `git remote update`") - end + Git.success(`remote update`, dir=cache) || + error("couldn't update $cache using `git remote update`") + end filter(sha1->!Git.iscommit(sha1, dir=cache), sha1s) end prefetch(pkg::String, url::String, sha1::String...) = prefetch(pkg, url, String[sha1...]) diff --git a/base/socket.jl b/base/socket.jl index 18059a5f5429b..515e057b9e2eb 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -666,7 +666,7 @@ function listenany(default_port) return (addr.port,sock) end close(sock) - addr.port += 1 + addr.port += 1 if addr.port==default_port error("no ports available") end From abcd556a11ab6d345db0478677084ba1373c36d5 Mon Sep 17 00:00:00 2001 From: Iain Dunning Date: Tue, 23 Sep 2014 11:07:06 -0400 Subject: [PATCH 51/79] Add a `versioninfo()` to default Travis --- base/pkg/generate.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/pkg/generate.jl b/base/pkg/generate.jl index 5cae4130b8d2d..56f1047755894 100644 --- a/base/pkg/generate.jl +++ b/base/pkg/generate.jl @@ -152,7 +152,7 @@ function travis(pkg::String; force::Bool=false) - sudo apt-get install libpcre3-dev julia -y - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi script: - - julia -e 'Pkg.init(); Pkg.clone(pwd()); Pkg.test("$pkg")' + - julia -e 'versioninfo(); Pkg.init(); Pkg.clone(pwd()); Pkg.test("$pkg")' """) end end From dc2bca9419a634c985c37259f5e1f802a7d81d3f Mon Sep 17 00:00:00 2001 From: "Arch D. Robison" Date: Tue, 23 Sep 2014 12:38:53 -0500 Subject: [PATCH 52/79] Render array objects more accurately. Enables vectorization of 64-bit arithmetic. --- src/cgutils.cpp | 6 ++++-- src/codegen.cpp | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 68979c5393081..2cc42fa855c28 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1289,7 +1289,8 @@ static Value *emit_arraylen_prim(Value *t, jl_value_t *ty) { #ifdef STORE_ARRAY_LEN (void)ty; - return emit_nthptr_recast(t, 2, tbaa_arraylen, T_psize); + Value* addr = builder.CreateStructGEP(builder.CreateBitCast(t,jl_parray_llvmt), 2); + return tbaa_decorate(tbaa_arraylen, builder.CreateLoad(addr, false)); #else jl_value_t *p1 = jl_tparam1(ty); if (jl_is_long(p1)) { @@ -1320,7 +1321,8 @@ static Value *emit_arraylen(Value *t, jl_value_t *ex, jl_codectx_t *ctx) static Value *emit_arrayptr(Value *t) { - return emit_nthptr(t, 1, tbaa_arrayptr); + Value* addr = builder.CreateStructGEP(builder.CreateBitCast(t,jl_parray_llvmt), 1); + return tbaa_decorate(tbaa_arrayptr, builder.CreateLoad(addr, false)); } static Value *emit_arrayptr(Value *t, jl_value_t *ex, jl_codectx_t *ctx) diff --git a/src/codegen.cpp b/src/codegen.cpp index a5d15be94308a..61b7b8520aea3 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -211,6 +211,7 @@ static bool imaging_mode = false; static Type *jl_value_llvmt; static Type *jl_pvalue_llvmt; static Type *jl_ppvalue_llvmt; +static Type* jl_parray_llvmt; static FunctionType *jl_func_sig; static Type *jl_pfptr_llvmt; static Type *T_int1; @@ -4155,6 +4156,17 @@ static void init_julia_llvm_env(Module *m) assert(jl_func_sig != NULL); jl_pfptr_llvmt = PointerType::get(PointerType::get(jl_func_sig, 0), 0); + Type* vaelts[] = {valueStructElts[0], T_pint8 +#ifdef STORE_ARRAY_LEN + , T_size +#endif + }; + Type* jl_array_llvmt = + StructType::create(getGlobalContext(), + ArrayRef(vaelts,sizeof(vaelts)/sizeof(vaelts[0])), + "jl_array_t"); + jl_parray_llvmt = PointerType::get(jl_array_llvmt,0); + #ifdef JL_GC_MARKSWEEP jlpgcstack_var = new GlobalVariable(*m, jl_ppvalue_llvmt, From 48b89d6f4ecd2c09c71133ae9aaa16fa2a8f90fc Mon Sep 17 00:00:00 2001 From: Jacob Quinn Date: Tue, 23 Sep 2014 14:10:23 -0400 Subject: [PATCH 53/79] Add back non-typed print methods for Float32/Float16. Fixes #8445 --- base/grisu.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/base/grisu.jl b/base/grisu.jl index 1bd1ce03cc1aa..9e1b61d078c1a 100644 --- a/base/grisu.jl +++ b/base/grisu.jl @@ -109,6 +109,9 @@ end Base.show(io::IO, x::FloatingPoint) = _show(io, x, SHORTEST, 0, true) +Base.print(io::IO, x::Float32) = _show(io, x, SHORTEST, 0, false) +Base.print(io::IO, x::Float16) = _show(io, x, SHORTEST, 0, false) + Base.showcompact(io::IO, x::Float64) = _show(io, x, PRECISION, 6, false) Base.showcompact(io::IO, x::Float32) = _show(io, x, PRECISION, 6, false) Base.showcompact(io::IO, x::Float16) = _show(io, x, PRECISION, 5, false) From cfc0b8e8f998981a0f9ea8709a08e971b26a45f6 Mon Sep 17 00:00:00 2001 From: Jacob Quinn Date: Tue, 23 Sep 2014 16:03:28 -0400 Subject: [PATCH 54/79] Fix failing travis. Ref #8451 --- test/float16.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/float16.jl b/test/float16.jl index c6cdd3a08581b..76897b685d88e 100644 --- a/test/float16.jl +++ b/test/float16.jl @@ -94,4 +94,4 @@ let end # issue #5948 -@test string(reinterpret(Float16, 0x7bff)) == "float16(65500.0)" +@test string(reinterpret(Float16, 0x7bff)) == "65500.0" From 4039a800b3de0d7e631bb41b8677076f0715889d Mon Sep 17 00:00:00 2001 From: "Arch D. Robison" Date: Tue, 23 Sep 2014 15:41:31 -0500 Subject: [PATCH 55/79] Change getGlobalContext() to jl_LLVMContext --- src/codegen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 61b7b8520aea3..4a5e5cfb65580 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4162,7 +4162,7 @@ static void init_julia_llvm_env(Module *m) #endif }; Type* jl_array_llvmt = - StructType::create(getGlobalContext(), + StructType::create(jl_LLVMContext, ArrayRef(vaelts,sizeof(vaelts)/sizeof(vaelts[0])), "jl_array_t"); jl_parray_llvmt = PointerType::get(jl_array_llvmt,0); From c344abd3d14caa2c3d278875926299747bcf0da2 Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Tue, 23 Sep 2014 20:31:32 -0400 Subject: [PATCH 56/79] Specialize generic_scale! when input and output are the same array Ref #8145 --- base/linalg/generic.jl | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index 0102bd743e7e1..2a13b311a1add 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -11,7 +11,15 @@ end scale{R<:Real}(s::Complex, X::AbstractArray{R}) = scale(X, s) -generic_scale!(X::AbstractArray, s::Number) = generic_scale!(X, X, s) +# For better performance when input and output are the same array +# See https://github.com/JuliaLang/julia/issues/8415#issuecomment-56608729 +function generic_scale!(X::AbstractArray, s::Number) + for i = 1:length(X) + @inbounds X[i] *= s + end + X +end + function generic_scale!(C::AbstractArray, X::AbstractArray, s::Number) length(C) == length(X) || error("C must be the same length as X") for i = 1:length(X) @@ -21,8 +29,8 @@ function generic_scale!(C::AbstractArray, X::AbstractArray, s::Number) end scale!(C::AbstractArray, s::Number, X::AbstractArray) = generic_scale!(C, X, s) scale!(C::AbstractArray, X::AbstractArray, s::Number) = generic_scale!(C, X, s) -scale!(X::AbstractArray, s::Number) = generic_scale!(X, X, s) -scale!(s::Number, X::AbstractArray) = generic_scale!(X, X, s) +scale!(X::AbstractArray, s::Number) = generic_scale!(X, s) +scale!(s::Number, X::AbstractArray) = generic_scale!(X, s) cross(a::AbstractVector, b::AbstractVector) = [a[2]*b[3]-a[3]*b[2], a[3]*b[1]-a[1]*b[3], a[1]*b[2]-a[2]*b[1]] From ea4473f1a1fe9211b81baf9dff854843cf33788c Mon Sep 17 00:00:00 2001 From: timholy Date: Tue, 23 Sep 2014 20:24:25 -0500 Subject: [PATCH 57/79] Add developer documentation for :meta expressions --- doc/devdocs/index.rst | 1 + doc/devdocs/meta.rst | 55 +++++++++++++++++++++++++++++++++++++++++++ doc/index.rst | 1 + 3 files changed, 57 insertions(+) create mode 100644 doc/devdocs/meta.rst diff --git a/doc/devdocs/index.rst b/doc/devdocs/index.rst index eb8a544b061d5..7e35f83c195d9 100644 --- a/doc/devdocs/index.rst +++ b/doc/devdocs/index.rst @@ -10,3 +10,4 @@ :maxdepth: 1 cartesian + meta diff --git a/doc/devdocs/meta.rst b/doc/devdocs/meta.rst new file mode 100644 index 0000000000000..279b5d51f5e19 --- /dev/null +++ b/doc/devdocs/meta.rst @@ -0,0 +1,55 @@ +.. currentmodule:: Base + +.. _devdocs-meta: + +Talking to the compiler (the ``:meta`` mechanism) +================================================= + +In some circumstances, one might wish to provide hints or instructions +that a given block of code has special properties: you might always +want to inline it, or you might want to turn on special compiler +optimization passes. Starting with version 0.4, julia has a +convention that these instructions can be placed inside a ``:meta`` +expression, which must be the first expression in the body of a +function. + +``:meta`` expressions are created with macros. As an example, consider +the implementation of the ``@inline`` macro:: + + macro inline(ex) + esc(_inline(ex)) + end + + _inline(ex::Expr) = pushmeta!(ex, :inline) + _inline(arg) = arg + +Here, ``ex`` is expected to be an expression defining a function. +A statement like this:: + + @inline function myfunction(x) + x*(x+3) + end + +gets turned into an expression like this:: + + quote + function myfunction(x) + Expr(:meta, :inline) + x*(x+3) + end + end + +``pushmeta!(ex, :symbol)`` appends ``:symbol`` to the end of the +``:meta`` expression, creating a new ``:meta`` expression if +necessary. + +To use the metadata, you have to parse these ``:meta`` expressions. +If your implementation can be performed within Julia, ``popmeta!`` is +very handy: ``popmeta!(body, :symbol)`` will scan a function *body* +expression (one without the function signature) for a ``:meta`` +expression; if ``:symbol`` is present, it will return ``true`` and +remove ``:symbol`` from the arguments of the ``:meta`` expression +(deleting the expression altogether if there are no more arguments). + +Not yet provided is a convenient infrastructure for parsing ``:meta`` +expressions from C++. diff --git a/doc/index.rst b/doc/index.rst index 27b3a23ab0bf9..be43ea4f9f90a 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -80,3 +80,4 @@ Developer Documentation :maxdepth: 1 devdocs/cartesian + devdocs/meta From 79f6c92c3fed76b830342fb69896601c93f67c0c Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Sat, 28 Jun 2014 15:54:03 -0500 Subject: [PATCH 58/79] First draft --- src/flisp/system.lsp | 1 + src/gf.c | 48 +++++++++++++++++++++++++++++++++----------- src/interpreter.c | 2 +- src/jltypes.c | 4 ++-- src/julia-parser.scm | 4 ++-- src/julia-syntax.scm | 48 ++++++++++++++++++++++++++------------------ src/julia.h | 5 +++-- src/toplevel.c | 4 ++-- 8 files changed, 76 insertions(+), 40 deletions(-) diff --git a/src/flisp/system.lsp b/src/flisp/system.lsp index 667d0c03ff11b..465296ac4bf69 100644 --- a/src/flisp/system.lsp +++ b/src/flisp/system.lsp @@ -173,6 +173,7 @@ (define (cddadr x) (cdr (cdr (car (cdr x))))) (define (cdddar x) (cdr (cdr (cdr (car x))))) (define (cddddr x) (cdr (cdr (cdr (cdr x))))) +(define (caddddr x) (car (cdr (cdr (cdr (cdr x)))))) (let ((*values* (list '*values*))) (set! values diff --git a/src/gf.c b/src/gf.c index 38c3b95acf780..b30ef0d42e1af 100644 --- a/src/gf.c +++ b/src/gf.c @@ -323,7 +323,7 @@ jl_function_t *jl_reinstantiate_method(jl_function_t *f, jl_lambda_info_t *li) static jl_methlist_t *jl_method_list_insert(jl_methlist_t **pml, jl_tuple_t *type, jl_function_t *method, jl_tuple_t *tvars, - int check_amb); + int check_amb, int8_t isstaged); static jl_function_t *jl_method_cache_insert(jl_methtable_t *mt, jl_tuple_t *type, @@ -356,7 +356,7 @@ jl_function_t *jl_method_cache_insert(jl_methtable_t *mt, jl_tuple_t *type, } } ml_do_insert: - return jl_method_list_insert(pml, type, method, jl_null, 0)->func; + return jl_method_list_insert(pml, type, method, jl_null, 0, 0)->func; } extern jl_function_t *jl_typeinf_func; @@ -972,17 +972,38 @@ static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, in m = m->next; } + jl_function_t *func = NULL; if (ti == (jl_value_t*)jl_bottom_type) { JL_GC_POP(); if (m != JL_NULL) { + func = m->func; + jl_lambda_info_t *newlinfo = NULL; + jl_value_t *code = NULL; + JL_GC_PUSH3(&code, &func, &newlinfo) + if (m->isstaged) + { + code = jl_apply(m->func, tt->data, jl_tuple_len(tt)); + newlinfo = jl_new_lambda_info(code, jl_null); + func = jl_new_closure(NULL, (jl_value_t*)jl_null, newlinfo); + } + JL_GC_POP(); if (!cache) - return m->func; - return cache_method(mt, tt, m->func, (jl_tuple_t*)m->sig, jl_null); + return func; + return cache_method(mt, tt, func, (jl_tuple_t*)m->sig, jl_null); } return jl_bottom_func; } assert(jl_is_tuple(env)); + func = m->func; + + if (m->isstaged) + { + jl_value_t *code = jl_apply(m->func, tt->data, jl_tuple_len(tt)); + jl_lambda_info_t *newlinfo = jl_new_lambda_info(code, env); + func = jl_new_closure(NULL, (jl_value_t*)jl_null, newlinfo); + } + // don't bother computing this if no arguments are tuples for(i=0; i < jl_tuple_len(tt); i++) { if (jl_is_tuple(jl_tupleref(tt,i))) @@ -999,9 +1020,9 @@ static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, in assert(jl_is_tuple(newsig)); jl_function_t *nf; if (!cache) - nf = m->func; + nf = func; else - nf = cache_method(mt, tt, m->func, newsig, env); + nf = cache_method(mt, tt, func, newsig, env); JL_GC_POP(); return nf; } @@ -1138,7 +1159,7 @@ static int has_unions(jl_tuple_t *type) static jl_methlist_t *jl_method_list_insert(jl_methlist_t **pml, jl_tuple_t *type, jl_function_t *method, jl_tuple_t *tvars, - int check_amb) + int check_amb, int8_t isstaged) { jl_methlist_t *l, **pl; @@ -1170,6 +1191,7 @@ jl_methlist_t *jl_method_list_insert(jl_methlist_t **pml, jl_tuple_t *type, l->va = (jl_tuple_len(type) > 0 && jl_is_vararg_type(jl_tupleref(type,jl_tuple_len(type)-1))) ? 1 : 0; + l->isstaged = isstaged; l->invokes = (struct _jl_methtable_t *)JL_NULL; l->func = method; JL_SIGATOMIC_END(); @@ -1197,6 +1219,7 @@ jl_methlist_t *jl_method_list_insert(jl_methlist_t **pml, jl_tuple_t *type, newrec->va = (jl_tuple_len(type) > 0 && jl_is_vararg_type(jl_tupleref(type,jl_tuple_len(type)-1))) ? 1 : 0; + newrec->isstaged = isstaged; newrec->func = method; newrec->invokes = (struct _jl_methtable_t*)JL_NULL; newrec->next = l; @@ -1249,12 +1272,13 @@ static void remove_conflicting(jl_methlist_t **pl, jl_value_t *type) } jl_methlist_t *jl_method_table_insert(jl_methtable_t *mt, jl_tuple_t *type, - jl_function_t *method, jl_tuple_t *tvars) + jl_function_t *method, jl_tuple_t *tvars, + int8_t isstaged) { if (jl_tuple_len(tvars) == 1) tvars = (jl_tuple_t*)jl_t0(tvars); JL_SIGATOMIC_BEGIN(); - jl_methlist_t *ml = jl_method_list_insert(&mt->defs,type,method,tvars,1); + jl_methlist_t *ml = jl_method_list_insert(&mt->defs,type,method,tvars,1,isstaged); // invalidate cached methods that overlap this definition remove_conflicting(&mt->cache, (jl_value_t*)type); if (mt->cache_arg1 != JL_NULL) { @@ -1660,7 +1684,7 @@ jl_value_t *jl_gf_invoke(jl_function_t *gf, jl_tuple_t *types, if (m->invokes == JL_NULL) { m->invokes = new_method_table(mt->name); // this private method table has just this one definition - jl_method_list_insert(&m->invokes->defs,m->sig,m->func,m->tvars,0); + jl_method_list_insert(&m->invokes->defs,m->sig,m->func,m->tvars,0,0); } tt = arg_type_tuple(args, nargs); @@ -1721,7 +1745,7 @@ DLLEXPORT jl_function_t *jl_new_gf_internal(jl_value_t *env) } void jl_add_method(jl_function_t *gf, jl_tuple_t *types, jl_function_t *meth, - jl_tuple_t *tvars) + jl_tuple_t *tvars, int8_t isstaged) { assert(jl_is_function(gf)); assert(jl_is_tuple(types)); @@ -1729,7 +1753,7 @@ void jl_add_method(jl_function_t *gf, jl_tuple_t *types, jl_function_t *meth, assert(jl_is_mtable(jl_gf_mtable(gf))); if (meth->linfo != NULL) meth->linfo->name = jl_gf_name(gf); - (void)jl_method_table_insert(jl_gf_mtable(gf), types, meth, tvars); + (void)jl_method_table_insert(jl_gf_mtable(gf), types, meth, tvars, isstaged); } DLLEXPORT jl_tuple_t *jl_match_method(jl_value_t *type, jl_value_t *sig, diff --git a/src/interpreter.c b/src/interpreter.c index f62446357e589..a555740cee61b 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -285,7 +285,7 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) jl_check_static_parameter_conflicts((jl_lambda_info_t*)args[2], (jl_tuple_t*)jl_t1(atypes), fname); } meth = eval(args[2], locals, nl); - jl_method_def(fname, bp, b, (jl_tuple_t*)atypes, (jl_function_t*)meth); + jl_method_def(fname, bp, b, (jl_tuple_t*)atypes, (jl_function_t*)meth, args[3] == jl_true); JL_GC_POP(); return *bp; } diff --git a/src/jltypes.c b/src/jltypes.c index 70875ea48a72d..a8f485f7010b5 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -3001,10 +3001,10 @@ void jl_init_types(void) jl_method_type = jl_new_datatype(jl_symbol("Method"), jl_any_type, jl_null, - jl_tuple(6, jl_symbol("sig"), jl_symbol("va"), + jl_tuple(7, jl_symbol("sig"), jl_symbol("va"), jl_symbol("isstaged"), jl_symbol("tvars"), jl_symbol("func"), jl_symbol("invokes"), jl_symbol("next")), - jl_tuple(6, jl_tuple_type, jl_bool_type, + jl_tuple(7, jl_tuple_type, jl_bool_type, jl_bool_type, jl_tuple_type, jl_any_type, jl_any_type, jl_any_type), 0, 1); diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 32999aacc3d91..5b9459aef8edf 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -90,7 +90,7 @@ (define operator? (Set operators)) (define reserved-words '(begin while if for try return break continue - function macro quote let local global const + stagedfunction function macro quote let local global const abstract typealias type bitstype immutable ccall do module baremodule using import export importall)) @@ -1074,7 +1074,7 @@ (if const `(const ,expr) expr))) - ((function macro) + ((stagedfunction function macro) (let* ((paren (eqv? (require-token s) #\()) (sig (parse-call s)) (def (if (or (symbol? sig) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 44201134d8228..35e8c351fa34e 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -437,7 +437,7 @@ (pair? (caddr e)) (eq? (car (caddr e)) 'quote) (symbol? (cadr (caddr e)))))) -(define (method-def-expr- name sparams argl body) +(define (method-def-expr- name sparams argl body isstaged) (receive (names bounds) (sparam-name-bounds sparams '() '()) (begin @@ -455,12 +455,12 @@ (let* ((types (llist-types argl)) (body (method-lambda-expr argl body))) (if (null? sparams) - `(method ,name (tuple (tuple ,@types) (tuple)) ,body) + `(method ,name (tuple (tuple ,@types) (tuple)) ,body ,isstaged) `(method ,name (call (lambda ,names (tuple (tuple ,@types) (tuple ,@names))) ,@(symbols->typevars names bounds #t)) - ,body)))))) + ,body ,isstaged)))))) (define (vararg? x) (and (pair? x) (eq? (car x) '...))) (define (trans? x) (and (pair? x) (eq? (car x) '|.'|))) @@ -469,7 +469,7 @@ (define (const-default? x) (or (number? x) (string? x) (char? x) (and (pair? x) (eq? (car x) 'quote)))) -(define (keywords-method-def-expr name sparams argl body) +(define (keywords-method-def-expr name sparams argl body isstaged) (let* ((kargl (cdar argl)) ;; keyword expressions (= k v) (pargl (cdr argl)) ;; positional args (body (if (and (pair? body) (eq? (car body) 'block)) @@ -533,7 +533,7 @@ `(block ,@(if (null? lno) '() (list (append (car lno) (list (undot-name name))))) - ,@stmts)) + ,@stmts) isstaged) ;; call with no keyword args ,(method-def-expr- @@ -551,7 +551,7 @@ ,@(if (null? restkw) '() '((cell1d))) ,@(map arg-name pargl) ,@(if (null? vararg) '() - (list `(... ,(arg-name (car vararg))))))))) + (list `(... ,(arg-name (car vararg)))))))) isstaged) ;; call with unsorted keyword args. this sorts and re-dispatches. ,(method-def-expr- @@ -628,11 +628,12 @@ ,@(if (null? restkw) '() (list rkw)) ,@(map arg-name pargl) ,@(if (null? vararg) '() - (list `(... ,(arg-name (car vararg))))))))) + (list `(... ,(arg-name (car vararg)))))))) + isstaged) ;; return primary function ,name)))) -(define (optional-positional-defs name sparams req opt dfl body overall-argl . kw) +(define (optional-positional-defs name sparams req opt dfl body isstaged overall-argl . kw) (let ((lno (if (and (pair? body) (pair? (cdr body)) (pair? (cadr body)) (eq? (caadr body) 'line)) (list (cadr body)) @@ -668,11 +669,11 @@ `(block ,@lno (call ,name ,@kw ,@(map arg-name passed) ,@vals))))) - (method-def-expr name sp (append kw passed) body))) + (method-def-expr name sp (append kw passed) body isstaged))) (iota (length opt))) - ,(method-def-expr name sparams overall-argl body)))) + ,(method-def-expr name sparams overall-argl body isstaged)))) -(define (method-def-expr name sparams argl body) +(define (method-def-expr name sparams argl body isstaged) (if (any kwarg? argl) ;; has optional positional args (begin @@ -697,20 +698,20 @@ (check-kw-args (cdr kw)) (receive (vararg req) (separate vararg? argl) - (optional-positional-defs name sparams req opt dfl body + (optional-positional-defs name sparams req opt dfl body isstaged (cons kw (append req opt vararg)) `(parameters (... ,(gensy)))))) ;; optional positional only (receive (vararg req) (separate vararg? argl) - (optional-positional-defs name sparams req opt dfl body + (optional-positional-defs name sparams req opt dfl body isstaged (append req opt vararg))))))) (if (has-parameters? argl) ;; keywords only (begin (check-kw-args (cdar argl)) - (keywords-method-def-expr name sparams argl body)) + (keywords-method-def-expr name sparams argl body isstaged)) ;; neither - (method-def-expr- name sparams argl body)))) + (method-def-expr- name sparams argl body isstaged)))) (define (struct-def-expr name params super fields mut) (receive @@ -796,9 +797,15 @@ (pattern-lambda (function (call (curly name . p) . sig) body) `(function (call (curly ,(if (eq? name Tname) iname name) ,@p) ,@sig) ,(ctor-body body))) + (pattern-lambda (stagedfunction (call (curly name . p) . sig) body) + `(stagedfunction (call (curly ,(if (eq? name Tname) iname name) ,@p) ,@sig) + ,(ctor-body body))) (pattern-lambda (function (call name . sig) body) `(function (call ,(if (eq? name Tname) iname name) ,@sig) ,(ctor-body body))) + (pattern-lambda (stagedfunction (call name . sig) body) + `(stagedfunction (call ,(if (eq? name Tname) iname name) ,@sig) + ,(ctor-body body))) (pattern-lambda (= (call (curly name . p) . sig) body) `(= (call (curly ,(if (eq? name Tname) iname name) ,@p) ,@sig) ,(ctor-body body))) @@ -985,6 +992,7 @@ (cond ((or (atom? e) (quoted? e)) e) ((or (eq? (car e) 'lambda) (eq? (car e) 'function) + (eq? (car e) 'stagedfunction) (eq? (car e) '->)) e) ((eq? (car e) 'return) `(block ,@(if ret `((= ,ret true)) '()) @@ -998,7 +1006,7 @@ ((quoted? e) e) (else (case (car e) - ((function) + ((function stagedfunction) (let ((name (cadr e))) (if (pair? name) (if (eq? (car name) 'call) @@ -1008,11 +1016,11 @@ (method-def-expr (cadr (cadr name)) (cddr (cadr name)) (fix-arglist (cddr name)) - (caddr e)) + (caddr e) (eq? (car e) 'stagedfunction)) (method-def-expr (cadr name) '() (fix-arglist (cddr name)) - (caddr e)))) + (caddr e) (eq? (car e) 'stagedfunction)))) (if (eq? (car name) 'tuple) (expand-binding-forms `(-> ,name ,(caddr e))) @@ -2848,6 +2856,7 @@ So far only the second case can actually occur. (define (free-vars e) (table.keys (free-vars- e (table) *free-vars-secret-value*))) +(define (caddddr x) (car (cdr (cdr (cdr (cdr x)))))) ; convert each lambda's (locals ...) to ; ((localvars...) var-info-lst captured-var-infos) ; where var-info-lst is a list of var-info records @@ -2951,7 +2960,8 @@ So far only the second case can actually occur. (vinfo:set-iasg! vi #t))))) `(method ,(cadr e) ,(analyze-vars (caddr e) env captvars) - ,(analyze-vars (cadddr 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 13a04464728a5..91bbfaee77c3e 100644 --- a/src/julia.h +++ b/src/julia.h @@ -261,6 +261,7 @@ typedef struct _jl_methlist_t { JL_DATA_TYPE jl_tuple_t *sig; int8_t va; + int8_t isstaged; jl_tuple_t *tvars; jl_function_t *func; // cache of specializations of this method for invoke(), i.e. @@ -672,9 +673,9 @@ DLLEXPORT jl_sym_t *jl_get_root_symbol(void); 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_tuple_t *types, jl_function_t *meth, - jl_tuple_t *tvars); + jl_tuple_t *tvars, int8_t isstaged); DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_t *bnd, - jl_tuple_t *argtypes, jl_function_t *f); + jl_tuple_t *argtypes, jl_function_t *f, int8_t isstaged); DLLEXPORT jl_value_t *jl_box_bool(int8_t x); DLLEXPORT jl_value_t *jl_box_int8(int32_t x); DLLEXPORT jl_value_t *jl_box_uint8(uint32_t x); diff --git a/src/toplevel.c b/src/toplevel.c index 4662a78837fba..2702eae851b67 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -642,7 +642,7 @@ static int type_contains(jl_value_t *ty, jl_value_t *x) void print_func_loc(JL_STREAM *s, jl_lambda_info_t *li); DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_t *bnd, - jl_tuple_t *argtypes, jl_function_t *f) + jl_tuple_t *argtypes, jl_function_t *f, int8_t isstaged) { // argtypes is a tuple ((types...), (typevars...)) jl_tuple_t *t = (jl_tuple_t*)jl_t1(argtypes); @@ -702,7 +702,7 @@ DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_ assert(jl_is_tuple(argtypes)); assert(jl_is_tuple(t)); - jl_add_method((jl_function_t*)gf, argtypes, f, t); + jl_add_method((jl_function_t*)gf, argtypes, f, t, isstaged); if (jl_boot_file_loaded && f->linfo && f->linfo->ast && jl_is_expr(f->linfo->ast)) { jl_lambda_info_t *li = f->linfo; From 6af45c1058fb52bfe2739c38431615148d8e0fa8 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Sun, 29 Jun 2014 20:36:43 -0500 Subject: [PATCH 59/79] WIP --- src/alloc.c | 1 + src/gf.c | 25 +++++++++++++++++++++---- src/jltypes.c | 1 + src/julia.h | 1 + 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/alloc.c b/src/alloc.c index 6a747e9a247f2..947ccd7a7026c 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -92,6 +92,7 @@ jl_sym_t *global_sym; jl_sym_t *tuple_sym; jl_sym_t *dot_sym; jl_sym_t *newvar_sym; jl_sym_t *boundscheck_sym; jl_sym_t *copyast_sym; jl_sym_t *simdloop_sym; jl_sym_t *meta_sym; +jl_sym_t *arrow_sym; typedef struct { int64_t a; diff --git a/src/gf.c b/src/gf.c index b30ef0d42e1af..6b9bbadd05bed 100644 --- a/src/gf.c +++ b/src/gf.c @@ -974,35 +974,52 @@ static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, in jl_function_t *func = NULL; if (ti == (jl_value_t*)jl_bottom_type) { - JL_GC_POP(); if (m != JL_NULL) { func = m->func; jl_lambda_info_t *newlinfo = NULL; jl_value_t *code = NULL; - JL_GC_PUSH3(&code, &func, &newlinfo) + jl_expr_t *ex = NULL; + jl_expr_t *oldast = NULL; + JL_GC_PUSH4(&code, &newlinfo, &ex, &oldast); if (m->isstaged) { - code = jl_apply(m->func, tt->data, jl_tuple_len(tt)); + if (jl_is_expr(m->func->linfo->ast)) + oldast = (jl_expr_t*)m->func->linfo; + else + oldast = (jl_expr_t*)jl_uncompress_ast(m->func->linfo, m->func->linfo->ast); + assert(oldast->head == lambda_sym); + ex = jl_exprn(arrow_sym, 2); + jl_expr_t *argnames = jl_exprn(tuple_sym, jl_tuple_len(tt)); + jl_cellset(ex->args, 0, argnames); + jl_array_t *oldargnames = (jl_array_t*)jl_cellref(oldast->args,0); + for (size_t i = 0; i < jl_tuple_len(tt); ++i) { + jl_cellset(argnames->args,i,jl_cellref(oldargnames,i)); + } + jl_cellset(ex->args, 1, jl_apply(m->func, tt->data, jl_tuple_len(tt))); + code = jl_expand((jl_value_t*)ex); newlinfo = jl_new_lambda_info(code, jl_null); func = jl_new_closure(NULL, (jl_value_t*)jl_null, newlinfo); } JL_GC_POP(); + JL_GC_POP(); if (!cache) return func; return cache_method(mt, tt, func, (jl_tuple_t*)m->sig, jl_null); } + JL_GC_POP(); return jl_bottom_func; } assert(jl_is_tuple(env)); func = m->func; + /* if (m->isstaged) { jl_value_t *code = jl_apply(m->func, tt->data, jl_tuple_len(tt)); jl_lambda_info_t *newlinfo = jl_new_lambda_info(code, env); func = jl_new_closure(NULL, (jl_value_t*)jl_null, newlinfo); - } + }*/ // don't bother computing this if no arguments are tuples for(i=0; i < jl_tuple_len(tt); i++) { diff --git a/src/jltypes.c b/src/jltypes.c index a8f485f7010b5..dc5db2683f82b 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -3262,6 +3262,7 @@ void jl_init_types(void) copyast_sym = jl_symbol("copyast"); simdloop_sym = jl_symbol("simdloop"); meta_sym = jl_symbol("meta"); + arrow_sym = jl_symbol("->"); } #ifdef __cplusplus diff --git a/src/julia.h b/src/julia.h index 91bbfaee77c3e..883d0dc6a46b6 100644 --- a/src/julia.h +++ b/src/julia.h @@ -423,6 +423,7 @@ extern jl_sym_t *compositetype_sym; extern jl_sym_t *type_goto_sym; extern jl_sym_t *global_sym; extern jl_sym_t *tuple_sym; extern jl_sym_t *boundscheck_sym; extern jl_sym_t *copyast_sym; extern jl_sym_t *simdloop_sym; extern jl_sym_t *meta_sym; +extern jl_sym_t *arrow_sym; // object accessors ----------------------------------------------------------- From c409db7583fc753afc2a3fc4413a58c18c7c9487 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Mon, 30 Jun 2014 14:40:16 -0400 Subject: [PATCH 60/79] Type inference works correctly --- base/inference.jl | 18 +++++++++++---- src/codegen.cpp | 5 ++-- src/gf.c | 58 +++++++++++++++++++++++------------------------ src/interpreter.c | 2 +- src/julia.h | 2 +- src/toplevel.c | 4 ++-- test/runtests.jl | 2 +- test/staged.jl | 16 +++++++++++++ 8 files changed, 65 insertions(+), 42 deletions(-) create mode 100644 test/staged.jl diff --git a/base/inference.jl b/base/inference.jl index c2f25b7ad78fb..3ac6fbb138bcf 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -633,6 +633,13 @@ const limit_tuple_type_n = function (t::Tuple, lim::Int) return t end +function func_for_method(m::Method, tt) + if !m.isstaged + return m.func.code + end + (ccall(:jl_instantiate_staged,Any,(Any,Any),m,tt)).code +end + function abstract_call_gf(f, fargs, argtypes, e) if length(argtypes)>1 && (argtypes[1] <: Tuple) && argtypes[2]===Int # allow tuple indexing functions to take advantage of constant @@ -704,7 +711,7 @@ function abstract_call_gf(f, fargs, argtypes, e) end end for (m::Tuple) in x - linfo = m[3].func.code + linfo = func_for_method(m[3],argtypes) sig = m[1] lsig = length(m[3].sig) # limit argument type tuple based on size of definition signature. @@ -749,7 +756,7 @@ function invoke_tfunc(f, types, argtypes) return Any end for (m::Tuple) in applicable - linfo = m[3].func.code + linfo = func_for_method(m[3],types) if typeseq(m[1],types) tvars = m[2][1:2:end] (ti, env) = ccall(:jl_match_method, Any, (Any,Any,Any), @@ -2072,7 +2079,8 @@ function inlineable(f, e::Expr, atypes, sv, enclosing_ast) return NF end meth = meth[1]::Tuple - linfo = meth[3].func.code + + linfo = func_for_method(meth[3],atypes) ## This code tries to limit the argument list length only when it is ## growing due to recursion. @@ -3036,7 +3044,7 @@ end function code_typed(f::Callable, types::(Type...)) asts = {} for x in _methods(f,types,-1) - linfo = x[3].func.code + linfo = func_for_method(x[3],types) (tree, ty) = typeinf(linfo, x[1], x[2]) if !isa(tree,Expr) push!(asts, ccall(:jl_uncompress_ast, Any, (Any,Any), linfo, tree)) @@ -3050,7 +3058,7 @@ end function return_types(f::Callable, types) rt = {} for x in _methods(f,types,-1) - linfo = x[3].func.code + linfo = func_for_method(x[3],types) (tree, ty) = typeinf(linfo, x[1], x[2]) push!(rt, ty) end diff --git a/src/codegen.cpp b/src/codegen.cpp index 4a5e5cfb65580..f3a035a388eaa 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2800,9 +2800,9 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, make_gcroot(a1, ctx); Value *a2 = boxed(emit_expr(args[2], ctx),ctx); make_gcroot(a2, ctx); - Value *mdargs[5] = { name, bp, literal_pointer_val(bnd), a1, a2 }; + Value *mdargs[6] = { name, bp, literal_pointer_val(bnd), a1, a2, literal_pointer_val(args[3]) }; ctx->argDepth = last_depth; - return builder.CreateCall(prepare_call(jlmethod_func), ArrayRef(&mdargs[0], 5)); + return builder.CreateCall(prepare_call(jlmethod_func), ArrayRef(&mdargs[0], 6)); } else if (head == const_sym) { jl_sym_t *sym = (jl_sym_t*)args[0]; @@ -4368,6 +4368,7 @@ static void init_julia_llvm_env(Module *m) mdargs.push_back(jl_pvalue_llvmt); mdargs.push_back(jl_pvalue_llvmt); mdargs.push_back(jl_pvalue_llvmt); + mdargs.push_back(jl_pvalue_llvmt); jlmethod_func = Function::Create(FunctionType::get(jl_pvalue_llvmt, mdargs, false), Function::ExternalLinkage, diff --git a/src/gf.c b/src/gf.c index 6b9bbadd05bed..3a5495ab11003 100644 --- a/src/gf.c +++ b/src/gf.c @@ -930,6 +930,32 @@ static jl_value_t *lookup_match(jl_value_t *a, jl_value_t *b, jl_tuple_t **penv, return ti; } +DLLEXPORT jl_function_t *jl_instantiate_staged(jl_methlist_t *m, jl_tuple_t *tt) +{ + jl_lambda_info_t *newlinfo = NULL; + jl_value_t *code = NULL; + jl_expr_t *ex = NULL; + jl_expr_t *oldast = NULL; + jl_function_t *func = NULL; + JL_GC_PUSH4(&code, &newlinfo, &ex, &oldast); + if (jl_is_expr(m->func->linfo->ast)) + oldast = (jl_expr_t*)m->func->linfo; + else + oldast = (jl_expr_t*)jl_uncompress_ast(m->func->linfo, m->func->linfo->ast); + assert(oldast->head == lambda_sym); + ex = jl_exprn(arrow_sym, 2); + jl_expr_t *argnames = jl_exprn(tuple_sym, jl_tuple_len(tt)); + jl_cellset(ex->args, 0, argnames); + jl_array_t *oldargnames = (jl_array_t*)jl_cellref(oldast->args,0); + for (size_t i = 0; i < jl_tuple_len(tt); ++i) { + jl_cellset(argnames->args,i,jl_cellref(oldargnames,i)); + } + jl_cellset(ex->args, 1, jl_apply(m->func, tt->data, jl_tuple_len(tt))); + func = (jl_function_t*)jl_toplevel_eval(jl_expand((jl_value_t*)ex)); + JL_GC_POP(); + return func; +} + static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, int cache, int inexact) { jl_methlist_t *m = mt->defs; @@ -976,31 +1002,8 @@ static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, in if (ti == (jl_value_t*)jl_bottom_type) { if (m != JL_NULL) { func = m->func; - jl_lambda_info_t *newlinfo = NULL; - jl_value_t *code = NULL; - jl_expr_t *ex = NULL; - jl_expr_t *oldast = NULL; - JL_GC_PUSH4(&code, &newlinfo, &ex, &oldast); if (m->isstaged) - { - if (jl_is_expr(m->func->linfo->ast)) - oldast = (jl_expr_t*)m->func->linfo; - else - oldast = (jl_expr_t*)jl_uncompress_ast(m->func->linfo, m->func->linfo->ast); - assert(oldast->head == lambda_sym); - ex = jl_exprn(arrow_sym, 2); - jl_expr_t *argnames = jl_exprn(tuple_sym, jl_tuple_len(tt)); - jl_cellset(ex->args, 0, argnames); - jl_array_t *oldargnames = (jl_array_t*)jl_cellref(oldast->args,0); - for (size_t i = 0; i < jl_tuple_len(tt); ++i) { - jl_cellset(argnames->args,i,jl_cellref(oldargnames,i)); - } - jl_cellset(ex->args, 1, jl_apply(m->func, tt->data, jl_tuple_len(tt))); - code = jl_expand((jl_value_t*)ex); - newlinfo = jl_new_lambda_info(code, jl_null); - func = jl_new_closure(NULL, (jl_value_t*)jl_null, newlinfo); - } - JL_GC_POP(); + func = jl_instantiate_staged(m,tt); JL_GC_POP(); if (!cache) return func; @@ -1013,13 +1016,8 @@ static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, in assert(jl_is_tuple(env)); func = m->func; - /* if (m->isstaged) - { - jl_value_t *code = jl_apply(m->func, tt->data, jl_tuple_len(tt)); - jl_lambda_info_t *newlinfo = jl_new_lambda_info(code, env); - func = jl_new_closure(NULL, (jl_value_t*)jl_null, newlinfo); - }*/ + func = jl_instantiate_staged(m,tt); // don't bother computing this if no arguments are tuples for(i=0; i < jl_tuple_len(tt); i++) { diff --git a/src/interpreter.c b/src/interpreter.c index a555740cee61b..0f412890e27e9 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -285,7 +285,7 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) jl_check_static_parameter_conflicts((jl_lambda_info_t*)args[2], (jl_tuple_t*)jl_t1(atypes), fname); } meth = eval(args[2], locals, nl); - jl_method_def(fname, bp, b, (jl_tuple_t*)atypes, (jl_function_t*)meth, args[3] == jl_true); + jl_method_def(fname, bp, b, (jl_tuple_t*)atypes, (jl_function_t*)meth, args[3]); JL_GC_POP(); return *bp; } diff --git a/src/julia.h b/src/julia.h index 883d0dc6a46b6..60288838de627 100644 --- a/src/julia.h +++ b/src/julia.h @@ -676,7 +676,7 @@ jl_function_t *jl_new_generic_function(jl_sym_t *name); void jl_add_method(jl_function_t *gf, jl_tuple_t *types, jl_function_t *meth, jl_tuple_t *tvars, int8_t isstaged); DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_t *bnd, - jl_tuple_t *argtypes, jl_function_t *f, int8_t isstaged); + jl_tuple_t *argtypes, jl_function_t *f, jl_value_t *isstaged); DLLEXPORT jl_value_t *jl_box_bool(int8_t x); DLLEXPORT jl_value_t *jl_box_int8(int32_t x); DLLEXPORT jl_value_t *jl_box_uint8(uint32_t x); diff --git a/src/toplevel.c b/src/toplevel.c index 2702eae851b67..600609d2b1a39 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -642,7 +642,7 @@ static int type_contains(jl_value_t *ty, jl_value_t *x) void print_func_loc(JL_STREAM *s, jl_lambda_info_t *li); DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_t *bnd, - jl_tuple_t *argtypes, jl_function_t *f, int8_t isstaged) + jl_tuple_t *argtypes, jl_function_t *f, jl_value_t *isstaged) { // argtypes is a tuple ((types...), (typevars...)) jl_tuple_t *t = (jl_tuple_t*)jl_t1(argtypes); @@ -702,7 +702,7 @@ DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_ assert(jl_is_tuple(argtypes)); assert(jl_is_tuple(t)); - jl_add_method((jl_function_t*)gf, argtypes, f, t, isstaged); + jl_add_method((jl_function_t*)gf, argtypes, f, t, isstaged == jl_true); if (jl_boot_file_loaded && f->linfo && f->linfo->ast && jl_is_expr(f->linfo->ast)) { jl_lambda_info_t *li = f->linfo; diff --git a/test/runtests.jl b/test/runtests.jl index 960232a961fed..dc4d747e6ed0c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -9,7 +9,7 @@ testnames = [ "floatapprox", "readdlm", "reflection", "regex", "float16", "combinatorics", "sysinfo", "rounding", "ranges", "mod2pi", "euler", "show", "lineedit", "replcompletions", "repl", "test", "examples", "goto", - "llvmcall", "grisu", "nullable", "meta" + "llvmcall", "grisu", "nullable", "meta", "staged" ] @unix_only push!(testnames, "unicode") diff --git a/test/staged.jl b/test/staged.jl new file mode 100644 index 0000000000000..6b509b1a7676f --- /dev/null +++ b/test/staged.jl @@ -0,0 +1,16 @@ +stagedfunction t1(a,b) + if a == Int64 + return :(a+b) + else + return :(a*b) + end +end + +@test t1(1,2) == 3 +@test t1(1.0,0.5) == 0.5 +@test t1(1,0.5) == 1.5 + +tinline(a,b) = t1(a,b) + +@test !isa(tinline(1,2),Expr) +@test tinline(1,0.5) == 1.5 \ No newline at end of file From 983b80903894de3eb5b75e0d7d35fbd267395fb3 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Mon, 30 Jun 2014 15:43:43 -0400 Subject: [PATCH 61/79] Remove left over caddddr --- src/flisp/system.lsp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/flisp/system.lsp b/src/flisp/system.lsp index 465296ac4bf69..667d0c03ff11b 100644 --- a/src/flisp/system.lsp +++ b/src/flisp/system.lsp @@ -173,7 +173,6 @@ (define (cddadr x) (cdr (cdr (car (cdr x))))) (define (cdddar x) (cdr (cdr (cdr (car x))))) (define (cddddr x) (cdr (cdr (cdr (cdr x))))) -(define (caddddr x) (car (cdr (cdr (cdr (cdr x)))))) (let ((*values* (list '*values*))) (set! values From 8d039275fc40a9022db1f248d003603dcdf99071 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 1 Jul 2014 23:20:05 -0400 Subject: [PATCH 62/79] Fix Splatting --- src/alloc.c | 2 +- src/gf.c | 19 +++++++++++++++---- src/jltypes.c | 1 + src/julia.h | 3 +-- test/staged.jl | 31 ++++++++++++++++++++++++++++++- 5 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/alloc.c b/src/alloc.c index 947ccd7a7026c..4db66e169ffde 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -92,7 +92,7 @@ jl_sym_t *global_sym; jl_sym_t *tuple_sym; jl_sym_t *dot_sym; jl_sym_t *newvar_sym; jl_sym_t *boundscheck_sym; jl_sym_t *copyast_sym; jl_sym_t *simdloop_sym; jl_sym_t *meta_sym; -jl_sym_t *arrow_sym; +jl_sym_t *arrow_sym; jl_sym_t *ldots_sym; typedef struct { int64_t a; diff --git a/src/gf.c b/src/gf.c index 3a5495ab11003..ef772c061c4d2 100644 --- a/src/gf.c +++ b/src/gf.c @@ -944,11 +944,22 @@ DLLEXPORT jl_function_t *jl_instantiate_staged(jl_methlist_t *m, jl_tuple_t *tt) oldast = (jl_expr_t*)jl_uncompress_ast(m->func->linfo, m->func->linfo->ast); assert(oldast->head == lambda_sym); ex = jl_exprn(arrow_sym, 2); - jl_expr_t *argnames = jl_exprn(tuple_sym, jl_tuple_len(tt)); - jl_cellset(ex->args, 0, argnames); jl_array_t *oldargnames = (jl_array_t*)jl_cellref(oldast->args,0); - for (size_t i = 0; i < jl_tuple_len(tt); ++i) { - jl_cellset(argnames->args,i,jl_cellref(oldargnames,i)); + jl_expr_t *argnames = jl_exprn(tuple_sym, jl_array_len(oldargnames)); + jl_cellset(ex->args, 0, argnames); + for (size_t i = 0; i < jl_array_len(oldargnames); ++i) { + jl_value_t *arg = jl_cellref(oldargnames,i); + if (jl_is_expr(arg)) { + assert(((jl_expr_t*)arg)->head == colons_sym); + arg = jl_cellref(((jl_expr_t*)arg)->args,0); + assert(jl_is_symbol(arg)); + jl_expr_t *dd_expr = jl_exprn(ldots_sym,1); + jl_cellset(dd_expr->args,0,arg); + jl_cellset(argnames->args,i,dd_expr); + } else { + assert(jl_is_symbol(arg)); + jl_cellset(argnames->args,i,arg); + } } jl_cellset(ex->args, 1, jl_apply(m->func, tt->data, jl_tuple_len(tt))); func = (jl_function_t*)jl_toplevel_eval(jl_expand((jl_value_t*)ex)); diff --git a/src/jltypes.c b/src/jltypes.c index dc5db2683f82b..3f8b72f245263 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -3263,6 +3263,7 @@ void jl_init_types(void) simdloop_sym = jl_symbol("simdloop"); meta_sym = jl_symbol("meta"); arrow_sym = jl_symbol("->"); + ldots_sym = jl_symbol("..."); } #ifdef __cplusplus diff --git a/src/julia.h b/src/julia.h index 60288838de627..32c603c5f9623 100644 --- a/src/julia.h +++ b/src/julia.h @@ -423,8 +423,7 @@ extern jl_sym_t *compositetype_sym; extern jl_sym_t *type_goto_sym; extern jl_sym_t *global_sym; extern jl_sym_t *tuple_sym; extern jl_sym_t *boundscheck_sym; extern jl_sym_t *copyast_sym; extern jl_sym_t *simdloop_sym; extern jl_sym_t *meta_sym; -extern jl_sym_t *arrow_sym; - +extern jl_sym_t *arrow_sym; extern jl_sym_t *ldots_sym; // object accessors ----------------------------------------------------------- diff --git a/test/staged.jl b/test/staged.jl index 6b509b1a7676f..3d375ed902fef 100644 --- a/test/staged.jl +++ b/test/staged.jl @@ -13,4 +13,33 @@ end tinline(a,b) = t1(a,b) @test !isa(tinline(1,2),Expr) -@test tinline(1,0.5) == 1.5 \ No newline at end of file +@test tinline(1,0.5) == 1.5 + +stagedfunction splat(a,b...) + :( ($a,$b,a,b) ) +end + +@test splat(1,2,3) == (Int64,(Int64,Int64),1,(2,3)) + +A = rand(5,5,3); +B = slice(A, 1:3, 2, 1:3); +stagedfunction mygetindex(S::SubArray, indexes::Real...) + T, N, A, I = S.parameters + if N != length(indexes) + error("Wrong number of indexes supplied") + end + NP = length(I) + indexexprs = Array(Expr, NP) + j = 1 + for i = 1:NP + if I[i] == Int + indexexprs[i] = :(S.indexes[$i]) + else + indexexprs[i] = :(S.indexes[$i][indexes[$j]]) + j += 1 + end + end + ex = :(S.parent[$(indexexprs...)]) + ex +end +@test mygetindex(B,2,2) == A[2,2,2] \ No newline at end of file From 251a0143f9f3f9bb1974869f5eb498c502fe2a77 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 1 Jul 2014 23:45:27 -0400 Subject: [PATCH 63/79] Ugly version of error handling This will have to be changed once we switch the way we do func_for_method, but I will await @JeffBezanson's judgement on how to do that best, so I'll use this to go head first. --- base/inference.jl | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 3ac6fbb138bcf..c02a7a713a854 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -711,7 +711,13 @@ function abstract_call_gf(f, fargs, argtypes, e) end end for (m::Tuple) in x - linfo = func_for_method(m[3],argtypes) + local linfo + try + linfo = func_for_method(m[3],argtypes) + catch + rettype = Any + break + end sig = m[1] lsig = length(m[3].sig) # limit argument type tuple based on size of definition signature. @@ -756,7 +762,12 @@ function invoke_tfunc(f, types, argtypes) return Any end for (m::Tuple) in applicable - linfo = func_for_method(m[3],types) + local linfo + try + linfo = func_for_method(m[3],types) + catch + return Any + end if typeseq(m[1],types) tvars = m[2][1:2:end] (ti, env) = ccall(:jl_match_method, Any, (Any,Any,Any), @@ -2080,7 +2091,12 @@ function inlineable(f, e::Expr, atypes, sv, enclosing_ast) end meth = meth[1]::Tuple - linfo = func_for_method(meth[3],atypes) + local linfo + try + linfo = func_for_method(meth[3],atypes) + catch + return NF + end ## This code tries to limit the argument list length only when it is ## growing due to recursion. From 93a3c3a3f06fe5193c80312b276f10a3cd6efed7 Mon Sep 17 00:00:00 2001 From: timholy Date: Sat, 9 Aug 2014 08:40:25 -0500 Subject: [PATCH 64/79] For caching staged methods, don't restrict the number of varargs to match Also adds `stagedfunction` as a keyword to Kate's julia.xml file --- contrib/julia.xml | 1 + src/gf.c | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/contrib/julia.xml b/contrib/julia.xml index 78286dcd70110..4f97dfa2199c5 100644 --- a/contrib/julia.xml +++ b/contrib/julia.xml @@ -37,6 +37,7 @@ do for function + stagedfunction if immutable let diff --git a/src/gf.c b/src/gf.c index ef772c061c4d2..61a0c0cf1d273 100644 --- a/src/gf.c +++ b/src/gf.c @@ -454,7 +454,7 @@ static jl_value_t *ml_matches(jl_methlist_t *ml, jl_value_t *type, static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type, jl_function_t *method, jl_tuple_t *decl, - jl_tuple_t *sparams) + jl_tuple_t *sparams, int isstaged) { size_t i; int need_guard_entries = 0; @@ -707,7 +707,7 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type, // and the types we find should be bigger. if (jl_tuple_len(type) > mt->max_args && jl_is_vararg_type(jl_tupleref(decl,jl_tuple_len(decl)-1))) { - size_t nspec = mt->max_args + 2; + size_t nspec = isstaged ? jl_tuple_len(type) : mt->max_args + 2; jl_tuple_t *limited = jl_alloc_tuple(nspec); for(i=0; i < nspec-1; i++) { jl_tupleset(limited, i, jl_tupleref(type, i)); @@ -1018,7 +1018,7 @@ static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, in JL_GC_POP(); if (!cache) return func; - return cache_method(mt, tt, func, (jl_tuple_t*)m->sig, jl_null); + return cache_method(mt, tt, func, (jl_tuple_t*)m->sig, jl_null, m->isstaged); } JL_GC_POP(); return jl_bottom_func; @@ -1048,7 +1048,7 @@ static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, in if (!cache) nf = func; else - nf = cache_method(mt, tt, func, newsig, env); + nf = cache_method(mt, tt, func, newsig, env, 0); JL_GC_POP(); return nf; } @@ -1734,7 +1734,7 @@ jl_value_t *jl_gf_invoke(jl_function_t *gf, jl_tuple_t *types, jl_tuple_len(tpenv)/2); } } - mfunc = cache_method(m->invokes, tt, m->func, newsig, tpenv); + mfunc = cache_method(m->invokes, tt, m->func, newsig, tpenv, 0); JL_GC_POP(); } From f2d9bdc39634ff28d148a917f7e9fe59977b63b6 Mon Sep 17 00:00:00 2001 From: timholy Date: Sat, 9 Aug 2014 17:30:35 -0500 Subject: [PATCH 65/79] Simplify conditional in jl_method_table_assoc_exact --- src/gf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gf.c b/src/gf.c index 61a0c0cf1d273..df1624b867087 100644 --- a/src/gf.c +++ b/src/gf.c @@ -274,8 +274,7 @@ static jl_function_t *jl_method_table_assoc_exact(jl_methtable_t *mt, mt_assoc_lkup: while (ml != JL_NULL) { size_t lensig = jl_tuple_len(ml->sig); - if ((lensig == n || ml->va) && - !(lensig > n && n != lensig-1)) { + if (lensig == n || (ml->va && lensig <= n+1)) { if (cache_match(args, n, (jl_tuple_t*)ml->sig, ml->va, lensig)) { return ml->func; } From d8dae6ba986b64eadb03fbbfd0727415c0473d11 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Tue, 23 Sep 2014 18:34:57 -0500 Subject: [PATCH 66/79] stagedfunctions: specialize for all input types --- src/gf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gf.c b/src/gf.c index df1624b867087..1a264f45b41da 100644 --- a/src/gf.c +++ b/src/gf.c @@ -704,9 +704,9 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type, // in general, here we want to find the biggest type that's not a // supertype of any other method signatures. so far we are conservative // and the types we find should be bigger. - if (jl_tuple_len(type) > mt->max_args && + if (!isstaged && jl_tuple_len(type) > mt->max_args && jl_is_vararg_type(jl_tupleref(decl,jl_tuple_len(decl)-1))) { - size_t nspec = isstaged ? jl_tuple_len(type) : mt->max_args + 2; + size_t nspec = mt->max_args + 2; jl_tuple_t *limited = jl_alloc_tuple(nspec); for(i=0; i < nspec-1; i++) { jl_tupleset(limited, i, jl_tupleref(type, i)); From e56ba99e6b7faa3aa1718bc5b5576439995aaa53 Mon Sep 17 00:00:00 2001 From: timholy Date: Tue, 23 Sep 2014 18:38:13 -0500 Subject: [PATCH 67/79] Expand stagedfunction tests --- test/staged.jl | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/test/staged.jl b/test/staged.jl index 3d375ed902fef..b6c0cb4bad665 100644 --- a/test/staged.jl +++ b/test/staged.jl @@ -1,5 +1,5 @@ stagedfunction t1(a,b) - if a == Int64 + if a == Int return :(a+b) else return :(a*b) @@ -19,7 +19,40 @@ stagedfunction splat(a,b...) :( ($a,$b,a,b) ) end -@test splat(1,2,3) == (Int64,(Int64,Int64),1,(2,3)) +@test splat(1,2,3) == (Int,(Int,Int),1,(2,3)) + +stagediobuf = IOBuffer() +stagedfunction splat2(a...) + print(stagediobuf, a) + :(nothing) +end + +const intstr = @sprintf("%s", Int) +splat2(1) +@test takebuf_string(stagediobuf) == "($intstr,)" +splat2(1,3) +@test takebuf_string(stagediobuf) == "($intstr,$intstr)" +splat2(5,2) +@test takebuf_string(stagediobuf) == "" +splat2(1:3,5.2) +@test takebuf_string(stagediobuf) == "(UnitRange{$intstr},Float64)" +splat2(3,5:2:7) +@test takebuf_string(stagediobuf) == "($intstr,StepRange{$intstr,$intstr})" +splat2(1,2,3,4) +@test takebuf_string(stagediobuf) == "($intstr,$intstr,$intstr,$intstr)" +splat2(1,2,3) +@test takebuf_string(stagediobuf) == "($intstr,$intstr,$intstr)" +splat2(1:5, 3, 3:3) +@test takebuf_string(stagediobuf) == "(UnitRange{$intstr},$intstr,UnitRange{$intstr})" +splat2(1:5, 3, 3:3) +@test takebuf_string(stagediobuf) == "" +splat2(1:5, 3:3, 3) +@test takebuf_string(stagediobuf) == "(UnitRange{$intstr},UnitRange{$intstr},$intstr)" +splat2(1:5, 3:3) +@test takebuf_string(stagediobuf) == "(UnitRange{$intstr},UnitRange{$intstr})" +splat2(3, 3:5) +@test takebuf_string(stagediobuf) == "($intstr,UnitRange{$intstr})" + A = rand(5,5,3); B = slice(A, 1:3, 2, 1:3); @@ -42,4 +75,4 @@ stagedfunction mygetindex(S::SubArray, indexes::Real...) ex = :(S.parent[$(indexexprs...)]) ex end -@test mygetindex(B,2,2) == A[2,2,2] \ No newline at end of file +@test mygetindex(B,2,2) == A[2,2,2] From dbfd60353327148766e080ee9e9b336313ab8f2b Mon Sep 17 00:00:00 2001 From: timholy Date: Tue, 23 Sep 2014 21:49:19 -0500 Subject: [PATCH 68/79] Resolve many arithmetic and conditional operations without eval --- base/cartesian.jl | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/base/cartesian.jl b/base/cartesian.jl index 4c4f6d9bc9b12..9a8f42e166c21 100644 --- a/base/cartesian.jl +++ b/base/cartesian.jl @@ -449,14 +449,37 @@ function poplinenum(ex::Expr) ex end +## Resolve expressions at parsing time ## + +const exprresolve_arith_dict = (Symbol=>Function)[:+ => +, + :- => -, :* => *, :/ => /, :^ => ^] +const exprresolve_cond_dict = (Symbol=>Function)[:(==) => ==, + :(<) => <, :(>) => >, :(<=) => <=, :(>=) => >=] + +function exprresolve_arith(ex::Expr) + if ex.head == :call && haskey(exprresolve_arith_dict, ex.args[1]) && all([isa(ex.args[i], Number) for i = 2:length(ex.args)]) + return true, exprresolve_arith_dict[ex.args[1]](ex.args[2:end]...) + end + false, 0 +end + +exprresolve_conditional(b::Bool) = true, b +function exprresolve_conditional(ex::Expr) + if ex.head == :conditional && isa(ex.args[1], Number) && isa(ex.args[3], Number) + return true, exprresolve_cond_dict[ex.args[2]](ex.args[1], ex.args[3]) + end + false, false +end + exprresolve(arg) = arg function exprresolve(ex::Expr) for i = 1:length(ex.args) ex.args[i] = exprresolve(ex.args[i]) end # Handle simple arithmetic - if ex.head == :call && in(ex.args[1], (:+, :-, :*, :/)) && all([isa(ex.args[i], Number) for i = 2:length(ex.args)]) - return eval(ex) + can_eval, result = exprresolve_arith(ex) + if can_eval + return result elseif ex.head == :call && (ex.args[1] == :+ || ex.args[1] == :-) && length(ex.args) == 3 && ex.args[3] == 0 # simplify x+0 and x-0 return ex.args[2] @@ -472,10 +495,15 @@ function exprresolve(ex::Expr) end # Resolve conditionals if ex.head == :if - try - tf = eval(ex.args[1]) + can_eval, tf = exprresolve_conditional(ex.args[1]) + if can_eval ex = tf?ex.args[2]:ex.args[3] - catch + else + try + tf = eval(ex.args[1]) + ex = tf?ex.args[2]:ex.args[3] + catch + end end end ex From 914ab70465fbc66c6638b7928e1013cecae00eae Mon Sep 17 00:00:00 2001 From: Blake Johnson Date: Tue, 23 Sep 2014 23:03:03 -0400 Subject: [PATCH 69/79] Fix #8446. Provides a universal default action (ignore) when a key cannot be found in the keymap. --- base/LineEdit.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/LineEdit.jl b/base/LineEdit.jl index 91fdea40e71e6..3f15c4a8a5990 100644 --- a/base/LineEdit.jl +++ b/base/LineEdit.jl @@ -731,8 +731,8 @@ function match_input(keymap::Dict, s, cs=Char[]) c = read(terminal(s), Char) push!(cs, c) k = haskey(keymap, c) ? c : '\0' - return match_input(keymap[k], s, cs) - # perhaps better would be: match_input(get(keymap, k, nothing), s, cs) ? + # if we don't match on the key, look for a default action then fallback on 'nothing' to ignore + return match_input(get(keymap, k, nothing), s, cs) end keymap_fcn(f::Nothing, s, c) = (s, p) -> return :ok From 58a1f48d7eba14f4b38fd326e4c9e4c07d7c86c8 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Wed, 24 Sep 2014 12:56:15 +0530 Subject: [PATCH 70/79] Add documentation on FFTW threads (relevant to #8455). --- doc/stdlib/base.rst | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index c91f3e327f8b2..872e07fb2a01a 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -4676,8 +4676,11 @@ Statistics Signal Processing ----------------- -Fast Fourier transform (FFT) functions in Julia are largely implemented by -calling functions from `FFTW `_. +Fast Fourier transform (FFT) functions in Julia are largely +implemented by calling functions from `FFTW +`_. By default, Julia does not use multi-threaded +FFTW. Higher performance may be obtained by experimenting with +multi-threading. Use `FFTW.set_num_threads(np)` to use `np` threads. .. function:: fft(A [, dims]) @@ -4700,6 +4703,10 @@ calling functions from `FFTW `_. A multidimensional FFT simply performs this operation along each transformed dimension of ``A``. + Higher performance is usually possible with multi-threading. Use + `FFTW.set_num_threads(np)` to use `np` threads, if you have `np` + processors. + .. function:: fft!(A [, dims]) Same as :func:`fft`, but operates in-place on ``A``, From 06371f0c857a812da3734b1564c82ba5c6ef7288 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Wed, 24 Sep 2014 11:52:05 -0400 Subject: [PATCH 71/79] Rename t1 to avoid collision with bitarray tests --- test/staged.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/staged.jl b/test/staged.jl index b6c0cb4bad665..85e8c4c049f7d 100644 --- a/test/staged.jl +++ b/test/staged.jl @@ -1,4 +1,4 @@ -stagedfunction t1(a,b) +stagedfunction staged_t1(a,b) if a == Int return :(a+b) else @@ -6,11 +6,11 @@ stagedfunction t1(a,b) end end -@test t1(1,2) == 3 -@test t1(1.0,0.5) == 0.5 -@test t1(1,0.5) == 1.5 +@test staged_t1(1,2) == 3 +@test staged_t1(1.0,0.5) == 0.5 +@test staged_t1(1,0.5) == 1.5 -tinline(a,b) = t1(a,b) +tinline(a,b) = staged_t1(a,b) @test !isa(tinline(1,2),Expr) @test tinline(1,0.5) == 1.5 From 48bb1fac8ad33be30f38f50398a0fd5226bcdf7c Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Wed, 24 Sep 2014 13:46:28 -0400 Subject: [PATCH 72/79] Make sure the value returned from instantiate_staged is rooted --- src/gf.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gf.c b/src/gf.c index 1a264f45b41da..a2ae90d84a055 100644 --- a/src/gf.c +++ b/src/gf.c @@ -972,8 +972,8 @@ static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, in size_t nargs = jl_tuple_len(tt); size_t i; jl_value_t *ti=(jl_value_t*)jl_bottom_type; - jl_tuple_t *newsig=NULL, *env = jl_null; - JL_GC_PUSH2(&env, &newsig); + jl_tuple_t *newsig=NULL, *env = jl_null, *func = NULL; + JL_GC_PUSH3(&env, &newsig, &func); while (m != JL_NULL) { if (m->tvars!=jl_null) { @@ -1008,7 +1008,6 @@ static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, in m = m->next; } - jl_function_t *func = NULL; if (ti == (jl_value_t*)jl_bottom_type) { if (m != JL_NULL) { func = m->func; From ed1f136c6898c29d65ae6286ee7a4e0d449eae4a Mon Sep 17 00:00:00 2001 From: timholy Date: Wed, 24 Sep 2014 14:11:26 -0500 Subject: [PATCH 73/79] Cartesian: eliminate any parse-time usage of eval Once a bug was fixed, in base it really wasn't catching anything new. However, it's possible this could affect user-code. --- base/cartesian.jl | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/base/cartesian.jl b/base/cartesian.jl index 9a8f42e166c21..f8d39f78af59d 100644 --- a/base/cartesian.jl +++ b/base/cartesian.jl @@ -452,7 +452,7 @@ end ## Resolve expressions at parsing time ## const exprresolve_arith_dict = (Symbol=>Function)[:+ => +, - :- => -, :* => *, :/ => /, :^ => ^] + :- => -, :* => *, :/ => /, :^ => ^, :div => div] const exprresolve_cond_dict = (Symbol=>Function)[:(==) => ==, :(<) => <, :(>) => >, :(<=) => <=, :(>=) => >=] @@ -465,7 +465,7 @@ end exprresolve_conditional(b::Bool) = true, b function exprresolve_conditional(ex::Expr) - if ex.head == :conditional && isa(ex.args[1], Number) && isa(ex.args[3], Number) + if ex.head == :comparison && isa(ex.args[1], Number) && isa(ex.args[3], Number) return true, exprresolve_cond_dict[ex.args[2]](ex.args[1], ex.args[3]) end false, false @@ -498,12 +498,6 @@ function exprresolve(ex::Expr) can_eval, tf = exprresolve_conditional(ex.args[1]) if can_eval ex = tf?ex.args[2]:ex.args[3] - else - try - tf = eval(ex.args[1]) - ex = tf?ex.args[2]:ex.args[3] - catch - end end end ex From 872d36349e5a2a7721d7dec96ba2f0429ba02e16 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Wed, 24 Sep 2014 12:46:43 -0700 Subject: [PATCH 74/79] Let's only run test/examples.jl if we can actually access the examples --- test/runtests.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index dc4d747e6ed0c..6d51abeaf638c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -8,9 +8,13 @@ testnames = [ "resolve", "pollfd", "mpfr", "broadcast", "complex", "socket", "floatapprox", "readdlm", "reflection", "regex", "float16", "combinatorics", "sysinfo", "rounding", "ranges", "mod2pi", "euler", "show", - "lineedit", "replcompletions", "repl", "test", "examples", "goto", + "lineedit", "replcompletions", "repl", "test", "goto", "llvmcall", "grisu", "nullable", "meta", "staged" ] + +if isdir(joinpath(dirname(@__FILE__), "..", "examples")) + push!(testnames, "examples") +end @unix_only push!(testnames, "unicode") # parallel tests depend on other workers - do them last From 4cf419db00ec4f374bef36b1ac0b43eb5aeaec27 Mon Sep 17 00:00:00 2001 From: Baurzhan Muftakhidinov Date: Thu, 25 Sep 2014 11:46:58 +0600 Subject: [PATCH 75/79] JITMemoryManager header file removed from llvm-svn. Fix https://github.com/JuliaLang/julia/issues/8460 --- src/codegen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index f3a035a388eaa..923aeb505ed4a 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -24,7 +24,6 @@ #endif #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/JITEventListener.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" #include "llvm/PassManager.h" #include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Support/TargetRegistry.h" @@ -38,6 +37,8 @@ #endif #if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 6 #define LLVM36 1 +#else +#include "llvm/ExecutionEngine/JITMemoryManager.h" #endif #if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5 #define LLVM35 1 From be5d78835de52a28db3dca6209039aa0f8deee69 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Thu, 25 Sep 2014 10:06:14 -0400 Subject: [PATCH 76/79] Correct documentation for least squres \ and make documentation for elementwise operations more precise. --- doc/manual/arrays.rst | 4 ++-- doc/stdlib/linalg.rst | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/manual/arrays.rst b/doc/manual/arrays.rst index cbcc3c67e71bb..ed4bae108ae71 100644 --- a/doc/manual/arrays.rst +++ b/doc/manual/arrays.rst @@ -330,8 +330,8 @@ operator should be used for elementwise operations. 5. Binary Boolean or bitwise — ``&``, ``|``, ``$`` Some operators without dots operate elementwise anyway when one argument is a -scalar. These operators are ``*``, ``/``, ``\``, and the bitwise -operators. +scalar. These operators are ``*``, ``+``, ``-``, and the bitwise operators. The +operators ``/`` and ``\`` operate elementwise when the denominator is a scalar. Note that comparisons such as ``==`` operate on whole arrays, giving a single boolean answer. Use dot operators for elementwise comparisons. diff --git a/doc/stdlib/linalg.rst b/doc/stdlib/linalg.rst index 20a50f1f7b339..372784952b6a7 100644 --- a/doc/stdlib/linalg.rst +++ b/doc/stdlib/linalg.rst @@ -17,7 +17,7 @@ Linear algebra functions in Julia are largely implemented by calling functions f .. function:: \\(A, B) :noindex: - Matrix division using a polyalgorithm. For input matrices ``A`` and ``B``, the result ``X`` is such that ``A*X == B`` when ``A`` is square. The solver that is used depends upon the structure of ``A``. A direct solver is used for upper- or lower triangular ``A``. For Hermitian ``A`` (equivalent to symmetric ``A`` for non-complex ``A``) the ``BunchKaufman`` factorization is used. Otherwise an LU factorization is used. For rectangular ``A`` the result is the minimum-norm least squares solution computed by reducing ``A`` to bidiagonal form and solving the bidiagonal least squares problem. For sparse, square ``A`` the LU factorization (from UMFPACK) is used. + Matrix division using a polyalgorithm. For input matrices ``A`` and ``B``, the result ``X`` is such that ``A*X == B`` when ``A`` is square. The solver that is used depends upon the structure of ``A``. A direct solver is used for upper- or lower triangular ``A``. For Hermitian ``A`` (equivalent to symmetric ``A`` for non-complex ``A``) the ``BunchKaufman`` factorization is used. Otherwise an LU factorization is used. For rectangular ``A`` the result is the minimum-norm least squares solution computed by a pivoted QR factorization of ``A`` and a rank estimate of A based on the R factor. For sparse, square ``A`` the LU factorization (from UMFPACK) is used. .. function:: dot(x, y) ⋅(x,y) From 2ef8d31b6b05ed0a8934c7a13f6490939a30b24b Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 25 Sep 2014 12:09:00 -0400 Subject: [PATCH 77/79] rename None to Union(), and Nothing to Void. fixes #8423 I also use Bottom === Union() some places in Base. remove a couple redundant show methods that snuck in somehow. remove some missed 0.3 deprecations in cconvert. --- base/LineEdit.jl | 6 +-- base/REPLCompletions.jl | 2 +- base/abstractarray.jl | 15 +++---- base/array.jl | 8 ++-- base/base.jl | 9 +--- base/boot.jl | 13 +++--- base/cartesian.jl | 2 +- base/deprecated.jl | 8 +++- base/error.jl | 4 +- base/expr.jl | 2 +- base/inference.jl | 90 ++++++++++++++++++------------------- base/loading.jl | 2 +- base/methodshow.jl | 2 +- base/multidimensional.jl | 2 +- base/pkg/github.jl | 2 +- base/pkg/query.jl | 2 +- base/pointer.jl | 2 +- base/precompile.jl | 8 ++-- base/process.jl | 2 +- base/profile.jl | 2 +- base/promotion.jl | 28 ++++++------ base/reflection.jl | 2 +- base/regex.jl | 4 +- base/serialize.jl | 2 +- base/set.jl | 8 ++-- base/show.jl | 15 ++----- base/sparse/csparse.jl | 6 +-- base/sparse/sparsematrix.jl | 28 ++++++------ base/subarray.jl | 2 +- contrib/Julia_Notepad++.xml | 2 +- contrib/julia-mode.el | 2 +- contrib/julia.lang | 2 +- contrib/julia.xml | 2 - src/alloc.c | 1 + src/builtins.c | 10 ++--- src/ccall.cpp | 8 ++-- src/cgutils.cpp | 10 +++-- src/codegen.cpp | 12 +++-- src/dump.c | 10 ++--- src/gf.c | 6 +-- src/init.c | 1 - src/jltypes.c | 22 +++++---- src/julia.h | 9 ++-- test/arrayops.jl | 2 +- test/core.jl | 85 ++++++++++++++++++----------------- test/functional.jl | 4 +- 46 files changed, 229 insertions(+), 237 deletions(-) diff --git a/base/LineEdit.jl b/base/LineEdit.jl index 3f15c4a8a5990..8b3ae98afcb0a 100644 --- a/base/LineEdit.jl +++ b/base/LineEdit.jl @@ -711,7 +711,7 @@ end # If we ever actually want to match \0 in input, this will have to be reworked function normalize_keymap(keymap::Dict) ret = Dict{Char,Any}() - direct_keys = filter((k,v) -> isa(v, Union(Function, Nothing)), keymap) + direct_keys = filter((k,v) -> isa(v, Union(Function, Void)), keymap) # first direct entries for key in keys(direct_keys) add_nested_key!(ret, key, keymap[key]) @@ -726,7 +726,7 @@ function normalize_keymap(keymap::Dict) end match_input(k::Function, s, cs) = (update_key_repeats(s, cs); return keymap_fcn(k, s, last(cs))) -match_input(k::Nothing, s, cs) = (s,p) -> return :ok +match_input(k::Void, s, cs) = (s,p) -> return :ok function match_input(keymap::Dict, s, cs=Char[]) c = read(terminal(s), Char) push!(cs, c) @@ -735,7 +735,7 @@ function match_input(keymap::Dict, s, cs=Char[]) return match_input(get(keymap, k, nothing), s, cs) end -keymap_fcn(f::Nothing, s, c) = (s, p) -> return :ok +keymap_fcn(f::Void, s, c) = (s, p) -> return :ok function keymap_fcn(f::Function, s, c::Char) return (s, p) -> begin r = f(s, p, c) diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index 360dad860063d..af2d146049afd 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -24,7 +24,7 @@ function complete_symbol(sym, ffunc) mod = context_module lookup_module = true - t = None + t = Union() for name in strs[1:(end-1)] s = symbol(name) if lookup_module diff --git a/base/abstractarray.jl b/base/abstractarray.jl index a663a5eab9d03..dc6f37a6ec8ab 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -200,7 +200,6 @@ function copy!(dest::AbstractArray, doffs::Integer, src::AbstractArray, soffs::I end copy(a::AbstractArray) = copy!(similar(a), a) -copy(a::AbstractArray{None}) = a # cannot be assigned into so is immutable function copy!{R,S}(B::AbstractMatrix{R}, ir_dest::Range{Int}, jr_dest::Range{Int}, A::AbstractMatrix{S}, ir_src::Range{Int}, jr_src::Range{Int}) if length(ir_dest) != length(ir_src) || length(jr_dest) != length(jr_src) @@ -502,14 +501,14 @@ get(A::AbstractArray, I::RangeVecIntList, default) = get!(similar(A, typeof(defa ## Concatenation ## -promote_eltype() = None +promote_eltype() = Bottom promote_eltype(v1, vs...) = promote_type(eltype(v1), promote_eltype(vs...)) #TODO: ERROR CHECK -cat(catdim::Integer) = Array(None, 0) +cat(catdim::Integer) = Array(Bottom, 0) -vcat() = Array(None, 0) -hcat() = Array(None, 0) +vcat() = Array(Bottom, 0) +hcat() = Array(Bottom, 0) ## cat: special cases hcat{T}(X::T...) = T[ X[j] for i=1, j=1:length(X) ] @@ -518,7 +517,7 @@ vcat{T}(X::T...) = T[ X[i] for i=1:length(X) ] vcat{T<:Number}(X::T...) = T[ X[i] for i=1:length(X) ] function vcat(X::Number...) - T = None + T = Bottom for x in X T = promote_type(T,typeof(x)) end @@ -526,7 +525,7 @@ function vcat(X::Number...) end function hcat(X::Number...) - T = None + T = Bottom for x in X T = promote_type(T,typeof(x)) end @@ -1287,7 +1286,7 @@ function promote_to!{T}(f::Callable, offs, dest::AbstractArray{T}, A::AbstractAr end function map_promote(f::Callable, A::AbstractArray) - if isempty(A); return similar(A, None); end + if isempty(A); return similar(A, Bottom); end first = f(A[1]) dest = similar(A, typeof(first)) dest[1] = first diff --git a/base/array.jl b/base/array.jl index 80d6cd5100326..e4adfea0efa49 100644 --- a/base/array.jl +++ b/base/array.jl @@ -450,7 +450,7 @@ const _grow_none_errmsg = "[] cannot grow. Instead, initialize the array with \"T[]\", where T is the desired element type." function push!{T}(a::Array{T,1}, item) - if is(T,None) + if is(T,Bottom) error(_grow_none_errmsg) end # convert first so we don't grow the array if the assignment won't work @@ -467,7 +467,7 @@ function push!(a::Array{Any,1}, item::ANY) end function append!{T}(a::Array{T,1}, items::AbstractVector) - if is(T,None) + if is(T,Bottom) error(_grow_none_errmsg) end n = length(items) @@ -477,7 +477,7 @@ function append!{T}(a::Array{T,1}, items::AbstractVector) end function prepend!{T}(a::Array{T,1}, items::AbstractVector) - if is(T,None) + if is(T,Bottom) error(_grow_none_errmsg) end n = length(items) @@ -518,7 +518,7 @@ function pop!(a::Vector) end function unshift!{T}(a::Array{T,1}, item) - if is(T,None) + if is(T,Bottom) error(_grow_none_errmsg) end item = convert(T, item) diff --git a/base/base.jl b/base/base.jl index 05b8c2a9e20ed..d9c3f498bf1d0 100644 --- a/base/base.jl +++ b/base/base.jl @@ -10,6 +10,8 @@ const NonTupleType = Union(DataType,UnionType,TypeConstructor) typealias Callable Union(Function,DataType) +const Bottom = Union() + convert(T, x) = convert_default(T, x, convert) convert(::(), ::()) = () @@ -31,13 +33,6 @@ ptr_arg_convert(::Type{Ptr{Void}}, x) = x # conversion used by ccall cconvert(T, x) = convert(T, x) -# the following 3 definitions implement a 0.3 deprecation -cconvert{T}(::Type{Ptr{T}}, x::Array{T}) = convert(Ptr{T}, x) -cconvert(::Type{Ptr{None}}, x::Array) = convert(Ptr{None}, x) -function cconvert{T}(::Type{Ptr{T}}, x::Array) - depwarn("ccall Ptr argument types must now match exactly, or be Ptr{Void}.", :cconvert) - convert(Ptr{T}, pointer(x)) -end # use the code in ccall.cpp to safely allocate temporary pointer arrays cconvert{T}(::Type{Ptr{Ptr{T}}}, a::Array) = a # convert strings to ByteString to pass as pointers diff --git a/base/boot.jl b/base/boot.jl index d054fad583e06..8a39c61e0d481 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -32,8 +32,6 @@ # types::Tuple #end -#None = Union() - #type TypeVar # name::Symbol # lb::Type @@ -45,6 +43,10 @@ # body #end +#immutable Void +#end +#const nothing = Void() + #abstract AbstractArray{T,N} #abstract DenseArray{T,N} <: AbstractArray{T,N} @@ -115,12 +117,12 @@ import Core.Intrinsics.ccall export # key types - Any, DataType, Vararg, ANY, NTuple, None, Top, + Any, DataType, Vararg, ANY, NTuple, Top, Tuple, Type, TypeConstructor, TypeName, TypeVar, Union, UnionType, Void, AbstractArray, DenseArray, # special objects Box, Function, IntrinsicFunction, LambdaStaticData, Method, MethodTable, - Module, Nothing, Symbol, Task, Array, + Module, Symbol, Task, Array, # numeric types Bool, FloatingPoint, Float16, Float32, Float64, Number, Integer, Int, Int8, Int16, Int32, Int64, Int128, Ptr, Real, Signed, Uint, Uint8, Uint16, Uint32, @@ -164,9 +166,6 @@ export #ule_int, ult_int, unbox, urem_int, xor_int, sext_int, zext_int -immutable Nothing; end -const nothing = Nothing() - const (===) = is abstract Number diff --git a/base/cartesian.jl b/base/cartesian.jl index f8d39f78af59d..b376365678387 100644 --- a/base/cartesian.jl +++ b/base/cartesian.jl @@ -152,7 +152,7 @@ function get_splatinfo(ex::Expr, itersym::Symbol) end end end - "", Nothing + "", Void end # Replace splatted with desplatted for a specific number of arguments diff --git a/base/deprecated.jl b/base/deprecated.jl index 357b6dbe3737c..466e270d5b389 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -38,7 +38,7 @@ function depwarn(msg, funcsym) warn(msg, once=(caller!=C_NULL), key=caller, bt=bt) end -function firstcaller(bt::Array{Ptr{None},1}, funcsym::Symbol) +function firstcaller(bt::Array{Ptr{Void},1}, funcsym::Symbol) # Identify the calling line i = 1 while i <= length(bt) @@ -179,3 +179,9 @@ const IpAddr = IPAddr @deprecate isblank(s::String) all(c -> c == ' ' || c == '\t', s) @deprecate randbool! rand! + +export Nothing +const Nothing = Void + +export None +const None = Union() diff --git a/base/error.jl b/base/error.jl index d5007eb558757..8f502e03b68ca 100644 --- a/base/error.jl +++ b/base/error.jl @@ -25,8 +25,8 @@ macro unexpected() :(error("unexpected branch reached")) end -rethrow() = ccall(:jl_rethrow, Void, ())::None -rethrow(e) = ccall(:jl_rethrow_other, Void, (Any,), e)::None +rethrow() = ccall(:jl_rethrow, Void, ())::Bottom +rethrow(e) = ccall(:jl_rethrow_other, Void, (Any,), e)::Bottom backtrace() = ccall(:jl_backtrace_from_here, Array{Ptr{Void},1}, ()) catch_backtrace() = ccall(:jl_get_backtrace, Array{Ptr{Void},1}, ()) diff --git a/base/expr.jl b/base/expr.jl index 66db044c240aa..0f716b7d928e1 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -43,7 +43,7 @@ astcopy(x) = x ==(x::QuoteNode, y::QuoteNode) = x.value == y.value function show(io::IO, tv::TypeVar) - if !is(tv.lb, None) + if !is(tv.lb, Bottom) show(io, tv.lb) print(io, "<:") end diff --git a/base/inference.jl b/base/inference.jl index c02a7a713a854..0ecb096029962 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -29,7 +29,7 @@ type CallStack prev::Union(EmptyCallStack,CallStack) sv::StaticVarInfo - CallStack(ast, mod, types, prev) = new(ast, mod, types, false, 0, None, prev) + CallStack(ast, mod, types, prev) = new(ast, mod, types, false, 0, Bottom, prev) end inference_stack = EmptyCallStack() @@ -89,7 +89,7 @@ isvarargtype(t::ANY) = isa(t,DataType)&&is((t::DataType).name,Vararg.name) const t_func = ObjectIdDict() #t_func[tuple] = (0, Inf, (args...)->limit_tuple_depth(args)) -t_func[throw] = (1, 1, x->None) +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) @@ -115,17 +115,15 @@ 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, (fptr, rt, at, a...)->(is(rt,Type{Void}) ? Nothing : - isType(rt) ? rt.parameters[1] : Any)) + (3, Inf, (fptr, rt, at, a...)->(isType(rt) ? rt.parameters[1] : Any)) t_func[eval(Core.Intrinsics,:llvmcall)] = - (3, Inf, (fptr, rt, at, a...)->(is(rt,Type{Void}) ? Nothing : - isType(rt) ? rt.parameters[1] : + (3, Inf, (fptr, rt, at, a...)->(isType(rt) ? rt.parameters[1] : isa(rt,Tuple) ? map(x->x.parameters[1],rt) : 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)] = - # TODO: return None if cnd is definitely not a Bool + # 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) @@ -225,7 +223,7 @@ const tupleref_tfunc = function (A, t, i) return Any end if is(t,()) - return None + return Bottom end n = length(t) last = tupleref(t,n) @@ -237,12 +235,12 @@ const tupleref_tfunc = function (A, t, i) if vararg T = last.parameters[1] else - return None + return Bottom end elseif i == n && vararg T = last.parameters[1] elseif i <= 0 - return None + return Bottom else T = tupleref(t,i) end @@ -256,7 +254,7 @@ const tupleref_tfunc = function (A, t, i) if !isa(types, Type) return Any end - T = reduce(tmerge, None, types) + T = reduce(tmerge, Bottom, types) if wrapType return isleaftype(T) || isa(T,TypeVar) ? Type{T} : Type{TypeVar(:_,T)} else @@ -288,7 +286,7 @@ function limit_type_depth(t::ANY, d::Int, cov::Bool, vars) end end elseif isa(t,UnionType) - t === None && return t + t === Bottom && return t if d > MAX_TYPE_DEPTH R = Any else @@ -334,7 +332,7 @@ const getfield_tfunc = function (A, s0, name) end end if isa(s,UnionType) - return reduce(tmerge, None, map(t->getfield_tfunc(A, t, name), s.types)) + return reduce(tmerge, Bottom, map(t->getfield_tfunc(A, t, name), s.types)) end if !isa(s,DataType) || s.abstract return Any @@ -373,18 +371,18 @@ const getfield_tfunc = function (A, s0, name) end end end - return None + return Bottom elseif isa(A[2],Int) if isa(A[1],Module) || s === Module - return None + return Bottom end i::Int = A[2] if i < 1 || i > length(s.names) - return None + return Bottom end return s.types[i] else - return reduce(tmerge, None, s.types)#Union(s.types...) + return reduce(tmerge, Bottom, s.types)#Union(s.types...) end end t_func[getfield] = (2, 2, getfield_tfunc) @@ -400,7 +398,7 @@ const fieldtype_tfunc = function (A, s, name) return Type end t = getfield_tfunc(A, s, name) - if is(t,None) + if is(t,Bottom) return t end Type{isleaftype(t) || isa(t,TypeVar) ? t : TypeVar(:_, t)} @@ -455,7 +453,7 @@ const apply_type_tfunc = function (A, args...) end if i-1 > length(headtype.parameters) # too many parameters for type - return None + return Bottom end uncertain = true tparams = tuple(tparams..., headtype.parameters[i-1]) @@ -498,7 +496,7 @@ function builtin_tfunction(f::ANY, args::ANY, argtypes::ANY) return tuple_tfunc(argtypes, true) elseif is(f,arrayset) if length(argtypes) < 3 && !isva - return None + return Bottom end a1 = argtypes[1] if isvarargtype(a1) @@ -507,14 +505,14 @@ function builtin_tfunction(f::ANY, args::ANY, argtypes::ANY) return a1 elseif is(f,arrayref) if length(argtypes) < 2 && !isva - return None + return Bottom end a = argtypes[1] return (isa(a,DataType) && a<:Array ? a.parameters[1] : Any) elseif is(f,Expr) if length(argtypes) < 1 && !isva - return None + return Bottom end return Expr end @@ -536,7 +534,7 @@ function builtin_tfunction(f::ANY, args::ANY, argtypes::ANY) end elseif !(tf[1] <= length(argtypes) <= tf[2]) # wrong # of args - return None + return Bottom end if is(f,typeassert) || is(f,tupleref) || is(f,getfield) || is(f,apply_type) || is(f,fieldtype) @@ -627,7 +625,7 @@ const limit_tuple_type_n = function (t::Tuple, lim::Int) last = last.parameters[1] end tail = tuple(t[lim:(n-1)]..., last) - tail = typeintersect(reduce(tmerge, None, tail), Any) + tail = typeintersect(reduce(tmerge, Bottom, tail), Any) return tuple(t[1:(lim-1)]..., Vararg{tail}) end return t @@ -684,11 +682,11 @@ function abstract_call_gf(f, fargs, argtypes, e) # typically, considering many methods means spending lots of time # obtaining poor type information. # It is important for N to be >= the number of methods in the error() - # function, so we can still know that error() is always None. + # function, so we can still know that error() is always Bottom. # here I picked 4. argtypes = limit_tuple_type(argtypes) applicable = _methods(f, argtypes, 4) - rettype = None + rettype = Bottom if is(applicable,false) # this means too many methods matched isa(e,Expr) && (e.head = :call) @@ -697,7 +695,7 @@ function abstract_call_gf(f, fargs, argtypes, e) x::Array{Any,1} = applicable if isempty(x) # no methods match - # TODO: it would be nice to return None here, but during bootstrap we + # TODO: it would be nice to return Bottom here, but during bootstrap we # often compile code that calls methods not defined yet, so it is much # safer just to fall back on dynamic dispatch. return Any @@ -747,15 +745,15 @@ function abstract_call_gf(f, fargs, argtypes, e) break end end - # if rettype is None we've found a method not found error + # if rettype is Bottom we've found a method not found error #print("=> ", rettype, "\n") return rettype end function invoke_tfunc(f, types, argtypes) argtypes = typeintersect(types,limit_tuple_type(argtypes)) - if is(argtypes,None) - return None + if is(argtypes,Bottom) + return Bottom end applicable = _methods(f, types, -1) if isempty(applicable) @@ -862,7 +860,7 @@ function abstract_call(f, fargs, argtypes, vtypes, sv::StaticVarInfo, e) end if is(f,kwcall) if length(argtypes) < 3 - return None + return Bottom end if length(fargs) < 2 return Any @@ -890,7 +888,7 @@ function abstract_eval_arg(a::ANY, vtypes::ANY, sv::StaticVarInfo) if isa(a,Symbol) || isa(a,SymbolNode) t = typeintersect(t,Any) # remove Undef end - if isa(t,TypeVar) && t.lb == None && isleaftype(t.ub) + if isa(t,TypeVar) && t.lb == Bottom && isleaftype(t.ub) t = t.ub end return t @@ -899,8 +897,8 @@ end function abstract_eval_call(e, vtypes, sv::StaticVarInfo) fargs = e.args[2:end] argtypes = tuple([abstract_eval_arg(a, vtypes, sv) for a in fargs]...) - if any(x->is(x,None), argtypes) - return None + if any(x->is(x,Bottom), argtypes) + return Bottom end called = e.args[1] func = isconstantfunc(called, sv) @@ -957,7 +955,7 @@ function abstract_eval(e::ANY, vtypes, sv::StaticVarInfo) if is(e.head,:call) || is(e.head,:call1) t = abstract_eval_call(e, vtypes, sv) elseif is(e.head,:null) - t = Nothing + t = Void elseif is(e.head,:new) t = abstract_eval(e.args[1], vtypes, sv) if isType(t) @@ -979,12 +977,12 @@ function abstract_eval(e::ANY, vtypes, sv::StaticVarInfo) # remove unnecessary typevars t = t.name.primary end - if is(t,None) && Undef<:t0 + if is(t,Bottom) && Undef<:t0 # the first time we see this statement the variable will probably - # be Undef; return None so this doesn't contribute to the type + # be Undef; return Bottom so this doesn't contribute to the type # we eventually pick. - elseif is(t,None) - t = Type{None} + elseif is(t,Bottom) + t = Type{Bottom} elseif isleaftype(t) t = Type{t} elseif isleaftype(inference_stack.types) @@ -1013,7 +1011,7 @@ function abstract_eval(e::ANY, vtypes, sv::StaticVarInfo) else t = Any end - if isa(t,TypeVar) && t.lb === None + if isa(t,TypeVar) && t.lb === Bottom # no need to use a typevar as the type of an expression t = t.ub end @@ -1037,9 +1035,9 @@ function abstract_eval_constant(x::ANY) end # Undef is the static type of a value location (e.g. variable) that is -# undefined. The corresponding run-time type is None, since accessing an +# undefined. The corresponding run-time type is Bottom, since accessing an # undefined location is an error. A non-lvalue expression cannot have -# type Undef, only None. +# type Undef, only Bottom. # typealias Top Union(Any,Undef) abstract_eval_global(s::Symbol) = @@ -1255,7 +1253,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) #dbg = #dotrace = true local ast::Expr, tfunc_idx - curtype = None + curtype = Bottom redo = false # check cached t-functions tf = def.tfunc @@ -1669,7 +1667,7 @@ function eval_annotate(e::ANY, vtypes::ANY, sv::StaticVarInfo, decls, clo) e.args[2] = eval_annotate(e.args[2], vtypes, sv, decls, clo) # TODO: if this def does not reach any uses, maybe don't do this rhstype = exprtype(e.args[2]) - if !is(rhstype,None) + if !is(rhstype,Bottom) record_var_type(s, rhstype, decls) end return e @@ -2309,7 +2307,7 @@ function inlineable(f, e::Expr, atypes, sv, enclosing_ast) icall = LabelNode(label_counter(body.args)+1) partmatch = Expr(:gotoifnot, false, icall.label) thrw = Expr(:call, :throw, Expr(:call, Main.Base.MethodError, (f, :inline), t)) - thrw.typ = None + thrw.typ = Bottom end for i=na:-1:1 # stmts_free needs to be calculated in reverse-argument order @@ -2413,7 +2411,7 @@ function inlineable(f, e::Expr, atypes, sv, enclosing_ast) end end free = effect_free(aei,sv,true) - if ((occ==0 && is(aeitype,None)) || islocal || (occ > 1 && !inline_worthy(aei, occ*2)) || + if ((occ==0 && is(aeitype,Bottom)) || islocal || (occ > 1 && !inline_worthy(aei, occ*2)) || (affect_free && !free) || (!affect_free && !effect_free(aei,sv,false))) if occ != 0 # islocal=true is implied by occ!=0 vnew = unique_name(enclosing_ast, ast) diff --git a/base/loading.jl b/base/loading.jl index f45b1ae4171bc..760370c512e5a 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -99,7 +99,7 @@ include_string(txt::String, fname::String) = include_string(txt::String) = include_string(txt, "string") -function source_path(default::Union(String,Nothing)="") +function source_path(default::Union(String,Void)="") t = current_task() while true s = t.storage diff --git a/base/methodshow.jl b/base/methodshow.jl index 6ba1e201d5ea1..e591b24a2d4a9 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -12,7 +12,7 @@ function argtype_decl(n, t) # -> (argname, argtype) if t === Any && !isempty(s) return s, "" end - if t <: Vararg && t !== None && t.parameters[1] === Any + if t <: Vararg && t !== Union() && t.parameters[1] === Any return string(s, "..."), "" end return s, string(t) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 3c1f0238fd638..4a6f6c22276cf 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1,6 +1,6 @@ ### From array.jl -@ngenerate N Nothing function checksize(A::AbstractArray, I::NTuple{N, Any}...) +@ngenerate N Void function checksize(A::AbstractArray, I::NTuple{N, Any}...) @nexprs N d->(size(A, d) == length(I_d) || throw(DimensionMismatch("index $d has length $(length(I_d)), but size(A, $d) = $(size(A,d))"))) nothing end diff --git a/base/pkg/github.jl b/base/pkg/github.jl index 8b6bcef435a23..cc32239a366f2 100644 --- a/base/pkg/github.jl +++ b/base/pkg/github.jl @@ -47,7 +47,7 @@ function curl(url::String, opts::Cmd=``) end error("strangely formatted HTTP response") end -curl(url::String, data::Nothing, opts::Cmd=``) = curl(url,opts) +curl(url::String, data::Void, opts::Cmd=``) = curl(url,opts) curl(url::String, data, opts::Cmd=``) = curl(url,`--data $(sprint(io->json().print(io,data))) $opts`) diff --git a/base/pkg/query.jl b/base/pkg/query.jl index b908e365b0cef..ad0cfe8e119c8 100644 --- a/base/pkg/query.jl +++ b/base/pkg/query.jl @@ -64,7 +64,7 @@ function dependencies(avail::Dict, fix::Dict = (ByteString=>Fixed)["julia"=>Fixe avail, conflicts end -typealias PackageState Union(Nothing,VersionNumber) +typealias PackageState Union(Void,VersionNumber) function diff(have::Dict, want::Dict, avail::Dict, fixed::Dict) change = Array((ByteString,(PackageState,PackageState)),0) diff --git a/base/pointer.jl b/base/pointer.jl index 654a896e004a6..78a8370938ffd 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -20,7 +20,7 @@ convert(::Type{Ptr{Uint8}}, s::ByteString) = convert(Ptr{Uint8}, s.data) convert(::Type{Ptr{Int8}}, s::ByteString) = convert(Ptr{Int8}, s.data) convert{T}(::Type{Ptr{T}}, a::Array{T}) = ccall(:jl_array_ptr, Ptr{T}, (Any,), a) -convert(::Type{Ptr{None}}, a::Array) = ccall(:jl_array_ptr, Ptr{None}, (Any,), a) +convert(::Type{Ptr{Void}}, a::Array) = ccall(:jl_array_ptr, Ptr{Void}, (Any,), a) # note: these definitions don't mean any AbstractArray is convertible to # pointer. they just map the array element type to the pointer type for diff --git a/base/precompile.jl b/base/precompile.jl index 4dd248140a678..2166388c89f71 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -87,7 +87,7 @@ precompile(abstract_interpret, (Bool, ObjectIdDict, StaticVarInfo)) precompile(eval_annotate, (LambdaStaticData, ObjectIdDict, StaticVarInfo, ObjectIdDict, Array{Any,1})) precompile(occurs_more, (Bool, Function, Int)) precompile(isconstantfunc, (SymbolNode, StaticVarInfo)) -precompile(CallStack, (Expr, Module, (Nothing,), EmptyCallStack)) +precompile(CallStack, (Expr, Module, (Void,), EmptyCallStack)) precompile(convert, (Type{Module}, Module)) precompile(effect_free, (Expr,)) precompile(effect_free, (TopNode,)) @@ -125,7 +125,7 @@ precompile(==, (Bool,Bool)) precompile(try_include, (ASCIIString,)) precompile(isfile, (ASCIIString,)) precompile(include_from_node1, (ASCIIString,)) -precompile(source_path, (Nothing,)) +precompile(source_path, (Void,)) precompile(task_local_storage, ()) precompile(atexit, (Function,)) precompile(print, (TTY, ASCIIString)) @@ -156,7 +156,7 @@ precompile(!=, (SubString{ASCIIString}, ASCIIString)) precompile(print_joined, (IOBuffer, Array{SubString{ASCIIString}, 1}, ASCIIString)) precompile(push!, (Array{Union(ASCIIString, UTF8String), 1}, ASCIIString)) precompile(Terminals.TTYTerminal, (ASCIIString, TTY, TTY, TTY)) -precompile(isequal, (Nothing, Nothing)) +precompile(isequal, (Void, Void)) precompile(banner, (Terminals.TTYTerminal, Terminals.TTYTerminal)) precompile(banner, (Terminals.TTYTerminal,)) precompile(print, (IOBuffer, VersionNumber)) @@ -220,7 +220,7 @@ precompile(keys, (Dict{Uint8, Any},)) precompile(in, (Uint8, KeyIterator{Dict{Uint8, Any}})) precompile(ht_keyindex, (Dict{Uint8, Any}, Uint8)) precompile(push!, (Array{String, 1}, ASCIIString)) -precompile(LineEdit.fix_conflicts!, (Nothing, Int)) +precompile(LineEdit.fix_conflicts!, (Void, Int)) precompile(convert, (Type{Function}, Function)) precompile(convert, (Type{Any}, Function)) precompile(similar, (Array{LineEdit.Prompt, 1}, Type{LineEdit.TextInterface}, (Int,))) diff --git a/base/process.jl b/base/process.jl index 261074142a2d7..28cb13e1ceb6a 100644 --- a/base/process.jl +++ b/base/process.jl @@ -4,7 +4,7 @@ type Cmd <: AbstractCmd exec::Vector{ByteString} ignorestatus::Bool detach::Bool - env::Union(Array{ByteString},Nothing) + env::Union(Array{ByteString},Void) dir::UTF8String Cmd(exec::Vector{ByteString}) = new(exec, false, false, nothing, "") end diff --git a/base/profile.jl b/base/profile.jl index b3676606526d0..9f2a5a8bfd8ec 100644 --- a/base/profile.jl +++ b/base/profile.jl @@ -21,7 +21,7 @@ end #### #### User-level functions #### -function init(; n::Union(Nothing,Integer) = nothing, delay::Union(Nothing,Float64) = nothing) +function init(; n::Union(Void,Integer) = nothing, delay::Union(Void,Float64) = nothing) n_cur = ccall(:jl_profile_maxlen_data, Csize_t, ()) delay_cur = ccall(:jl_profile_delay_nsec, Uint64, ())/10^9 if n == nothing && delay == nothing diff --git a/base/promotion.jl b/base/promotion.jl index a3879cd1cb311..5e5395402ba1e 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -1,6 +1,6 @@ ## type join (closest common ancestor, or least upper bound) ## -typejoin() = None +typejoin() = Bottom typejoin(t::ANY) = t typejoin(t::ANY, ts...) = typejoin(t, typejoin(ts...)) function typejoin(a::ANY, b::ANY) @@ -22,7 +22,7 @@ function typejoin(a::ANY, b::ANY) if !isa(u,UnionType) return u end - return reduce(typejoin, None, u.types) + return reduce(typejoin, Bottom, u.types) end if isa(a,Tuple) if !isa(b,Tuple) @@ -82,7 +82,7 @@ end # reduce typejoin over tup[i:end] function tailjoin(tup, i) - t = None + t = Bottom for j = i:length(tup) tj = tup[j] t = typejoin(t, isvarargtype(tj)?tj.parameters[1]:tj) @@ -92,30 +92,30 @@ end ## promotion mechanism ## -promote_type() = None +promote_type() = Bottom promote_type(T) = T promote_type(T, S ) = typejoin(T, S) promote_type(T, S...) = promote_type(T, promote_type(S...)) -promote_type(::Type{None}, ::Type{None}) = None +promote_type(::Type{Bottom}, ::Type{Bottom}) = Bottom promote_type{T}(::Type{T}, ::Type{T}) = T -promote_type{T}(::Type{T}, ::Type{None}) = T -promote_type{T}(::Type{None}, ::Type{T}) = T +promote_type{T}(::Type{T}, ::Type{Bottom}) = T +promote_type{T}(::Type{Bottom}, ::Type{T}) = T # Try promote_rule in both orders. Typically only one is defined, -# and there is a fallback returning None below, so the common case is +# and there is a fallback returning Bottom below, so the common case is # promote_type(T, S) => -# promote_result(T, S, result, None) => -# typejoin(result, None) => result +# promote_result(T, S, result, Bottom) => +# typejoin(result, Bottom) => result promote_type{T,S}(::Type{T}, ::Type{S}) = promote_result(T, S, promote_rule(T,S), promote_rule(S,T)) -promote_rule(T, S) = None +promote_rule(T, S) = Bottom promote_result(t,s,T,S) = promote_type(T,S) -# If no promote_rule is defined, both directions give None. In that +# If no promote_rule is defined, both directions give Bottom. In that # case use typejoin on the original types instead. -promote_result{T,S}(::Type{T},::Type{S},::Type{None},::Type{None}) = typejoin(T, S) +promote_result{T,S}(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) = typejoin(T, S) promote() = () promote(x) = (x,) @@ -143,7 +143,7 @@ end # Otherwise, typejoin(T,S) is called (returning Number) so no conversion # happens, and +(promote(x,y)...) is called again, causing a stack # overflow. -promote_result{T<:Number,S<:Number}(::Type{T},::Type{S},::Type{None},::Type{None}) = +promote_result{T<:Number,S<:Number}(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) = promote_to_super(T, S, typejoin(T,S)) # promote numeric types T and S to typejoin(T,S) if T<:S or S<:T diff --git a/base/reflection.jl b/base/reflection.jl index 5ce427b9f87b9..2317722a480ed 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -73,7 +73,7 @@ function _subtypes(m::Module, x::DataType, sts=Set(), visited=Set()) t = eval(m,s) if isa(t, DataType) && t.name.name == s && super(t).name == x.name ti = typeintersect(t, x) - ti != None && push!(sts, ti) + ti != Bottom && push!(sts, ti) elseif isa(t, Module) && !in(t, visited) _subtypes(t, x, sts, visited) end diff --git a/base/regex.jl b/base/regex.jl index 04d108fc77b4a..a71c07632b938 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -80,7 +80,7 @@ end immutable RegexMatch match::SubString{UTF8String} - captures::Vector{Union(Nothing,SubString{UTF8String})} + captures::Vector{Union(Void,SubString{UTF8String})} offset::Int offsets::Vector{Int} end @@ -121,7 +121,7 @@ function match(re::Regex, str::UTF8String, idx::Integer, add_opts::Uint32=uint32 end n = length(re.ovec)/3 - 1 mat = SubString(str, re.ovec[1]+1, re.ovec[2]) - cap = Union(Nothing,SubString{UTF8String})[ + cap = Union(Void,SubString{UTF8String})[ re.ovec[2i+1] < 0 ? nothing : SubString(str, re.ovec[2i+1]+1, re.ovec[2i+2]) for i=1:n ] off = Int[ re.ovec[2i+1]::Int32+1 for i=1:n ] RegexMatch(mat, cap, re.ovec[1]+1, off) diff --git a/base/serialize.jl b/base/serialize.jl index 48962ae7a38f5..5345cea80ab11 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -21,7 +21,7 @@ let i = 2 UTF16String, UTF32String, Float16, :reserved9, :reserved10, :reserved11, :reserved12, - (), Bool, Any, :Any, None, Top, Undef, Type, + (), Bool, Any, :Any, Bottom, Top, Undef, Type, :Array, :TypeVar, :Box, :lambda, :body, :return, :call, symbol("::"), :(=), :null, :gotoifnot, :A, :B, :C, :M, :N, :T, :S, :X, :Y, diff --git a/base/set.jl b/base/set.jl index b7a9a474707a2..abc2a9a7cef74 100644 --- a/base/set.jl +++ b/base/set.jl @@ -1,8 +1,8 @@ type Set{T} - dict::Dict{T,Nothing} + dict::Dict{T,Void} - Set() = new(Dict{T,Nothing}()) - Set(itr) = union!(new(Dict{T,Nothing}()), itr) + Set() = new(Dict{T,Void}()) + Set(itr) = union!(new(Dict{T,Void}()), itr) end Set() = Set{Any}() Set(itr) = Set{eltype(itr)}(itr) @@ -37,7 +37,7 @@ next(s::Set, i) = (s.dict.keys[i], skip_deleted(s.dict,i+1)) # TODO: simplify me? pop!(s::Set) = (val = s.dict.keys[start(s.dict)]; delete!(s.dict, val); val) -join_eltype() = None +join_eltype() = Bottom join_eltype(v1, vs...) = typejoin(eltype(v1), join_eltype(vs...)) union() = Set() diff --git a/base/show.jl b/base/show.jl index c2963a4dfd905..cd2f426491eab 100644 --- a/base/show.jl +++ b/base/show.jl @@ -68,9 +68,7 @@ function show(io::IO, x::IntrinsicFunction) end function show(io::IO, x::UnionType) - if is(x,None) - print(io, "None") - elseif is(x,Top) + if is(x,Top) print(io, "Top") else print(io, "Union", x.types) @@ -107,14 +105,13 @@ macro show(exs...) end show(io::IO, tn::TypeName) = print(io, tn.name) -show(io::IO, ::Nothing) = print(io, "nothing") +show(io::IO, ::Void) = print(io, "nothing") show(io::IO, b::Bool) = print(io, b ? "true" : "false") show(io::IO, n::Signed) = (write(io, dec(n)); nothing) show(io::IO, n::Unsigned) = print(io, "0x", hex(n,sizeof(n)<<1)) print(io::IO, n::Unsigned) = print(io, dec(n)) -show{T}(io::IO, p::Ptr{T}) = - print(io, is(T,None) ? "Ptr{Void}" : typeof(p), " @0x$(hex(unsigned(p), WORD_SIZE>>2))") +show{T}(io::IO, p::Ptr{T}) = print(io, typeof(p), " @0x$(hex(unsigned(p), WORD_SIZE>>2))") function show(io::IO, m::Module) if is(m,Main) @@ -197,12 +194,6 @@ show_comma_array(io::IO, itr, o, c) = show_delim_array(io, itr, o, ',', c, false show(io::IO, t::Tuple) = show_delim_array(io, t, '(', ',', ')', true) show(io::IO, s::Symbol) = show_unquoted(io, QuoteNode(s)) -show(io::IO, tn::TypeName) = print(io, tn.name) -show(io::IO, ::Nothing) = print(io, "nothing") -show(io::IO, b::Bool) = print(io, b ? "true" : "false") -show(io::IO, n::Signed) = (write(io, dec(n)); nothing) -show(io::IO, n::Unsigned) = print(io, "0x", hex(n,sizeof(n)<<1)) -print(io::IO, n::Unsigned) = print(io, dec(n)) ## Abstract Syntax Tree (AST) printing ## diff --git a/base/sparse/csparse.jl b/base/sparse/csparse.jl index d3eb38c95c5d1..a22a3f9b98364 100644 --- a/base/sparse/csparse.jl +++ b/base/sparse/csparse.jl @@ -358,8 +358,8 @@ function fkeep!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, f, other) end droptol!(A::SparseMatrixCSC, tol) = fkeep!(A, (i,j,x,other)->abs(x)>other, tol) -dropzeros!(A::SparseMatrixCSC) = fkeep!(A, (i,j,x,other)->x!=0, None) -triu!(A::SparseMatrixCSC) = fkeep!(A, (i,j,x,other)->(j>=i), None) +dropzeros!(A::SparseMatrixCSC) = fkeep!(A, (i,j,x,other)->x!=0, nothing) +triu!(A::SparseMatrixCSC) = fkeep!(A, (i,j,x,other)->(j>=i), nothing) triu(A::SparseMatrixCSC) = triu!(copy(A)) -tril!(A::SparseMatrixCSC) = fkeep!(A, (i,j,x,other)->(i>=j), None) +tril!(A::SparseMatrixCSC) = fkeep!(A, (i,j,x,other)->(i>=j), nothing) tril(A::SparseMatrixCSC) = tril!(copy(A)) diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index b3e40799aef4a..e65a4353addf2 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -431,24 +431,24 @@ end # Operations that may map nonzeros to zero, and zero to zero # Result is sparse -for (op, restype) in ((:iceil, Int), (:ceil, Nothing), - (:ifloor, Int), (:floor, Nothing), - (:itrunc, Int), (:trunc, Nothing), - (:iround, Int), (:round, Nothing), - (:sin, Nothing), (:tan, Nothing), - (:sinh, Nothing), (:tanh, Nothing), - (:asin, Nothing), (:atan, Nothing), - (:asinh, Nothing), (:atanh, Nothing), - (:sinpi, Nothing), (:cosc, Nothing), - (:sind, Nothing), (:tand, Nothing), - (:asind, Nothing), (:atand, Nothing) ) +for (op, restype) in ((:iceil, Int), (:ceil, Void), + (:ifloor, Int), (:floor, Void), + (:itrunc, Int), (:trunc, Void), + (:iround, Int), (:round, Void), + (:sin, Void), (:tan, Void), + (:sinh, Void), (:tanh, Void), + (:asin, Void), (:atan, Void), + (:asinh, Void), (:atanh, Void), + (:sinpi, Void), (:cosc, Void), + (:sind, Void), (:tand, Void), + (:asind, Void), (:atand, Void) ) @eval begin function ($op){Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}) nfilledA = nnz(A) colptrB = Array(Ti, A.n+1) rowvalB = Array(Ti, nfilledA) - nzvalB = Array($(restype==Nothing ? (:Tv) : restype), nfilledA) + nzvalB = Array($(restype==Void ? (:Tv) : restype), nfilledA) k = 0 # number of additional zeros introduced by op(A) @inbounds for i = 1 : A.n @@ -515,7 +515,7 @@ end ## Binary arithmetic and boolean operators -for (op, restype) in ( (:+, Nothing), (:-, Nothing), (:.*, Nothing), +for (op, restype) in ( (:+, Void), (:-, Void), (:.*, Void), (:(.<), Bool) ) @eval begin @@ -538,7 +538,7 @@ for (op, restype) in ( (:+, Nothing), (:-, Nothing), (:.*, Nothing), nnzS = nnz(A) + nnz(B) colptrS = Array(Ti, A.n+1) rowvalS = Array(Ti, nnzS) - nzvalS = Array($(restype==Nothing ? (:Tv) : restype), nnzS) + nzvalS = Array($(restype==Void ? (:Tv) : restype), nnzS) z = zero(Tv) diff --git a/base/subarray.jl b/base/subarray.jl index 9eaf962fa11a2..139ffb18850b7 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -400,7 +400,7 @@ stride(s::SubArray, i::Integer) = i <= length(s.strides) ? s.strides[i] : s.stri convert{T}(::Type{Ptr{T}}, x::SubArray{T}) = pointer(x.parent) + (x.first_index-1)*sizeof(T) -convert{T}(::Type{Ptr{None}}, x::SubArray{T}) = convert(Ptr{None}, convert(Ptr{T},x)) +convert{T}(::Type{Ptr{Void}}, x::SubArray{T}) = convert(Ptr{Void}, convert(Ptr{T},x)) convert{T,S,N}(::Type{Array{T,N}},A::SubArray{S,N}) = copy!(Array(T,size(A)), A) pointer(s::SubArray, i::Int) = pointer(s, ind2sub(size(s), i)) diff --git a/contrib/Julia_Notepad++.xml b/contrib/Julia_Notepad++.xml index 990e86ad50af8..7dbb125adb3b0 100644 --- a/contrib/Julia_Notepad++.xml +++ b/contrib/Julia_Notepad++.xml @@ -12,7 +12,7 @@ end "00"00 abstract bitstype break ccall const continue export global import importall in local macro module baremodule return typealias using - AbstractArray AbstractMatrix AbstractSparseMatrix AbstractVector Any Array ASCIIString Associative AsyncStream BitArray BigFloat BigInt BitMatrix BitVector Bool ByteString Char CharString Colon Complex Complex64 Complex128 ComplexPair DArray Dict Dims EachLine EnvHash Exception Expr FileOffset Filter Float Float32 Float64 Function ObjectIdDict Int Int8 Int16 Int32 Int64 Int128 Integer IntSet ImaginaryUnit IO IOBuffer IOStream LocalProcess Matrix Nothing None NTuple Number ObjectIdDict OrdinalRange PipeBuffer ProcessGroup Ptr Range Range1 RangeIndex Ranges Rational Real Regex RegexMatch RegexMatchIterator RemoteRef RepString RevString Reverse RopeString Set Signed SparseMatrixCSC SpawnNullStream StridedArray StridedMatrix StridedVecOrMat StridedVector String SubArray SubDArray SubOrDArray SubString Symbol SymTridiagonal Task TcpSocket Tridiagonal Tuple Type Uint Uint8 Uint16 Uint32 Uint64 Uint128 Union Unsigned UTF8String UVError VecOrMat Vector VersionNumber Void WeakKeyDict WeakRef Woodbury Zip Stat Factorization BunchKaufman CholeskyDense CholeskyPivotedDense LUDense LUTridiagonal LDLTTridiagonal QRDense QRPivotedDense SVDDense GSVDDense InsertionSort QuickSort MergeSort TimSort Cchar Cuchar Cshort Cushort Cint Cuint Clong Culong Cptrdiff_t Csize_t Clonglong Culonglong Cintmax_t Cuintmax_t Cfloat Cdouble ArgumentError DisconnectException EOFError ErrorException KeyError LoadError MethodError ParseError SystemError TypeError + AbstractArray AbstractMatrix AbstractSparseMatrix AbstractVector Any Array ASCIIString Associative AsyncStream BitArray BigFloat BigInt BitMatrix BitVector Bool ByteString Char CharString Colon Complex Complex64 Complex128 ComplexPair DArray Dict Dims EachLine EnvHash Exception Expr FileOffset Filter Float Float32 Float64 Function ObjectIdDict Int Int8 Int16 Int32 Int64 Int128 Integer IntSet ImaginaryUnit IO IOBuffer IOStream LocalProcess Matrix NTuple Number ObjectIdDict OrdinalRange PipeBuffer ProcessGroup Ptr Range Range1 RangeIndex Ranges Rational Real Regex RegexMatch RegexMatchIterator RemoteRef RepString RevString Reverse RopeString Set Signed SparseMatrixCSC SpawnNullStream StridedArray StridedMatrix StridedVecOrMat StridedVector String SubArray SubDArray SubOrDArray SubString Symbol SymTridiagonal Task TcpSocket Tridiagonal Tuple Type Uint Uint8 Uint16 Uint32 Uint64 Uint128 Union Unsigned UTF8String UVError VecOrMat Vector VersionNumber Void WeakKeyDict WeakRef Woodbury Zip Stat Factorization BunchKaufman CholeskyDense CholeskyPivotedDense LUDense LUTridiagonal LDLTTridiagonal QRDense QRPivotedDense SVDDense GSVDDense InsertionSort QuickSort MergeSort TimSort Cchar Cuchar Cshort Cushort Cint Cuint Clong Culong Cptrdiff_t Csize_t Clonglong Culonglong Cintmax_t Cuintmax_t Cfloat Cdouble ArgumentError DisconnectException EOFError ErrorException KeyError LoadError MethodError ParseError SystemError TypeError diff --git a/contrib/julia-mode.el b/contrib/julia-mode.el index 1ba68006108ed..59c14e040660e 100644 --- a/contrib/julia-mode.el +++ b/contrib/julia-mode.el @@ -145,7 +145,7 @@ (defconst julia-font-lock-keywords (list - '("\\<\\(\\|Uint\\(8\\|16\\|32\\|64\\|128\\)\\|Int\\(8\\|16\\|32\\|64\\|128\\)\\|BigInt\\|Integer\\|BigFloat\\|FloatingPoint\\|Float16\\|Float32\\|Float64\\|Complex128\\|Complex64\\|ComplexPair\\|Bool\\|Char\\|DataType\\|Number\\|Real\\|Int\\|Uint\\|Array\\|DArray\\|AbstractArray\\|AbstractVector\\|AbstractMatrix\\|AbstractSparseMatrix\\|SubArray\\|StridedArray\\|StridedVector\\|StridedMatrix\\|VecOrMat\\|StridedVecOrMat\\|DenseArray\\|Range\\|OrdinalRange\\|StepRange\\|UnitRange\\|FloatRange\\|SparseMatrixCSC\\|Tuple\\|NTuple\\|Symbol\\|Function\\|Vector\\|Matrix\\|Union\\|Type\\|Any\\|Complex\\|None\\|String\\|Ptr\\|Void\\|Exception\\|Task\\|Signed\\|Unsigned\\|Associative\\|Dict\\|IO\\|IOStream\\|Rational\\|Regex\\|RegexMatch\\|Set\\|IntSet\\|ASCIIString\\|UTF8String\\|ByteString\\|Expr\\|WeakRef\\|Nothing\\|ObjectIdDict\\|SubString\\)\\>" . + '("\\<\\(\\|Uint\\(8\\|16\\|32\\|64\\|128\\)\\|Int\\(8\\|16\\|32\\|64\\|128\\)\\|BigInt\\|Integer\\|BigFloat\\|FloatingPoint\\|Float16\\|Float32\\|Float64\\|Complex128\\|Complex64\\|ComplexPair\\|Bool\\|Char\\|DataType\\|Number\\|Real\\|Int\\|Uint\\|Array\\|DArray\\|AbstractArray\\|AbstractVector\\|AbstractMatrix\\|AbstractSparseMatrix\\|SubArray\\|StridedArray\\|StridedVector\\|StridedMatrix\\|VecOrMat\\|StridedVecOrMat\\|DenseArray\\|Range\\|OrdinalRange\\|StepRange\\|UnitRange\\|FloatRange\\|SparseMatrixCSC\\|Tuple\\|NTuple\\|Symbol\\|Function\\|Vector\\|Matrix\\|Union\\|Type\\|Any\\|Complex\\|String\\|Ptr\\|Void\\|Exception\\|Task\\|Signed\\|Unsigned\\|Associative\\|Dict\\|IO\\|IOStream\\|Rational\\|Regex\\|RegexMatch\\|Set\\|IntSet\\|ASCIIString\\|UTF8String\\|ByteString\\|Expr\\|WeakRef\\|ObjectIdDict\\|SubString\\)\\>" . font-lock-type-face) (cons julia-keyword-regex 'font-lock-keyword-face) (cons julia-macro-regex 'font-lock-keyword-face) diff --git a/contrib/julia.lang b/contrib/julia.lang index cd0730d86a281..56eb971640cd9 100644 --- a/contrib/julia.lang +++ b/contrib/julia.lang @@ -232,7 +232,7 @@ - Any|None|Nothing|Void + Any|Void Type(Constructor|Name|Var|_Array)?|(Union|Data|NonTuple)Type (Abstract|Strided|Bit)?(Array|Matrix|Vector) Abstract(Cmd|RNG|SparseMatrix) diff --git a/contrib/julia.xml b/contrib/julia.xml index 4f97dfa2199c5..4d538c2aa3376 100644 --- a/contrib/julia.xml +++ b/contrib/julia.xml @@ -142,8 +142,6 @@ LU MathConst Matrix - Nothing - None NTuple Number ObjectIdDict diff --git a/src/alloc.c b/src/alloc.c index 4db66e169ffde..df9392a775520 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -55,6 +55,7 @@ jl_datatype_t *jl_methoderror_type; jl_datatype_t *jl_loaderror_type; jl_datatype_t *jl_undefvarerror_type; jl_datatype_t *jl_pointer_type; +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; diff --git a/src/builtins.c b/src/builtins.c index a2b9fa767f331..03de05f1ff3a3 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -1058,9 +1058,9 @@ void jl_init_primitives(void) // builtin types add_builtin("Any", (jl_value_t*)jl_any_type); - add_builtin("None", (jl_value_t*)jl_bottom_type); - add_builtin("Void", (jl_value_t*)jl_bottom_type); add_builtin("Top", (jl_value_t*)jl_top_type); + add_builtin("Void", (jl_value_t*)jl_void_type); + add_builtin("nothing", (jl_value_t*)jl_nothing); add_builtin("TypeVar", (jl_value_t*)jl_tvar_type); add_builtin("TypeName", (jl_value_t*)jl_typename_type); add_builtin("TypeConstructor", (jl_value_t*)jl_typector_type); @@ -1223,12 +1223,12 @@ DLLEXPORT size_t jl_static_show(JL_STREAM *out, jl_value_t *v) else if (v == jl_false) { n += JL_PRINTF(out, "false"); } + else if (v == jl_nothing) { + n += JL_PRINTF(out, "nothing"); + } else if (jl_is_byte_string(v)) { n += JL_PRINTF(out, "\"%s\"", jl_iostr_data(v)); } - else if (v == jl_bottom_type) { - n += JL_PRINTF(out, "Void"); - } else if (jl_is_uniontype(v)) { n += JL_PRINTF(out, "Union"); n += jl_static_show(out, (jl_value_t*)((jl_uniontype_t*)v)->types); diff --git a/src/ccall.cpp b/src/ccall.cpp index c3543132a5fb2..ea32513241323 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -302,8 +302,10 @@ extern "C" DLLEXPORT void *jl_value_to_pointer(jl_value_t *jt, jl_value_t *v, in return jl_string_data(v); } if (jl_is_array_type(jvt)) { - if (jl_tparam0(jl_typeof(v)) == jt || jt==(jl_value_t*)jl_bottom_type) + if (jl_tparam0(jl_typeof(v)) == jt || jt == (jl_value_t*)jl_bottom_type || + jt == (jl_value_t*)jl_void_type) { return ((jl_array_t*)v)->data; + } if (jl_is_cpointer_type(jt)) { jl_array_t *ar = (jl_array_t*)v; void **temp=(void**)alloc_temp_arg_space((1+jl_array_len(ar))*sizeof(void*)); @@ -375,8 +377,8 @@ static Value *julia_to_native(Type *ty, jl_value_t *jt, Value *jv, assert(ty->isPointerTy()); jl_value_t *aty = expr_type(argex, ctx); if (jl_is_array_type(aty) && - (jl_tparam0(jt) == jl_tparam0(aty) || - jl_tparam0(jt) == (jl_value_t*)jl_bottom_type)) { + (jl_tparam0(jt) == jl_tparam0(aty) || jl_tparam0(jt) == (jl_value_t*)jl_bottom_type || + jl_tparam0(jt) == (jl_value_t*)jl_void_type)) { // array to pointer return builder.CreateBitCast(emit_arrayptr(jv), ty); } diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 2cc42fa855c28..62a887481741e 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -529,8 +529,8 @@ static jl_value_t *llvm_type_to_julia(Type *t, bool throw_error) if (t == T_int64) return (jl_value_t*)jl_int64_type; if (t == T_float32) return (jl_value_t*)jl_float32_type; if (t == T_float64) return (jl_value_t*)jl_float64_type; - if (t == T_void) return (jl_value_t*)jl_bottom_type; - if (t->isEmptyTy()) return (jl_value_t*)jl_nothing->type; + if (t == T_void) return (jl_value_t*)jl_void_type; + if (t->isEmptyTy()) return (jl_value_t*)jl_void_type; if (t == jl_pvalue_llvmt) return (jl_value_t*)jl_any_type; if (t->isPointerTy()) { @@ -1457,7 +1457,7 @@ static jl_value_t *static_void_instance(jl_value_t *jt) //assert(jb->instance != NULL); return (jl_value_t*)jb->instance; } - else if (jt == jl_typeof(jl_nothing) || jt == jl_bottom_type) { + else if (jt == (jl_value_t*)jl_void_type) { return (jl_value_t*)jl_nothing; } assert(jl_is_tuple(jt)); @@ -1541,8 +1541,10 @@ static Value *boxed(Value *v, jl_codectx_t *ctx, jl_value_t *jt) if (jl_subtype(jt2, jt, 0)) jt = jt2; } + if (jt == jl_bottom_type) + return UndefValue::get(jl_pvalue_llvmt); UndefValue *uv = NULL; - if (jt == jl_bottom_type || v == NULL || (uv = dyn_cast(v)) != 0 || t == NoopType) { + if (v == NULL || (uv = dyn_cast(v)) != 0 || t == NoopType) { if (uv != NULL && jl_is_datatype(jt)) { jl_datatype_t *jb = (jl_datatype_t*)jt; // We have an undef value on a hopefully dead branch diff --git a/src/codegen.cpp b/src/codegen.cpp index 923aeb505ed4a..5c06649be6839 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -718,8 +718,7 @@ static Function *jl_cfunction_object(jl_function_t *f, jl_value_t *rt, jl_value_ } JL_TYPECHK(jl_function_ptr, tuple, argt); JL_TYPECHK(jl_function_ptr, type, argt); - if (jl_is_gf(f) && (rt == NULL || jl_is_leaf_type(rt) || rt == (jl_value_t*)jl_bottom_type) && - jl_is_leaf_type(argt)) { + if (jl_is_gf(f) && (rt == NULL || jl_is_leaf_type(rt)) && jl_is_leaf_type(argt)) { jl_function_t *ff = jl_get_specialization(f, (jl_tuple_t*)argt); if (ff != NULL && ff->env==(jl_value_t*)jl_null && ff->linfo != NULL) { if (ff->linfo->cFunctionObject == NULL) { @@ -733,8 +732,7 @@ static Function *jl_cfunction_object(jl_function_t *f, jl_value_t *rt, jl_value_ } if (rt != NULL) { jl_value_t *astrt = jl_ast_rettype(li, li->ast); - if (!jl_types_equal(astrt, rt) && - !(astrt==(jl_value_t*)jl_nothing->type && rt==(jl_value_t*)jl_bottom_type)) { + if (!jl_types_equal(astrt, rt)) { if (astrt == (jl_value_t*)jl_bottom_type) { jl_errorf("cfunction: %s does not return", li->name->name); } @@ -2551,7 +2549,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) jl_varinfo_t &vi = ctx->vars[s]; jl_value_t *rt = expr_type(r,ctx); if ((jl_is_symbol(r) || jl_is_symbolnode(r)) && rt == jl_bottom_type) { - // sometimes x = y::None occurs + // sometimes x = y::Union() occurs if (builder.GetInsertBlock()->getTerminator() != NULL) return; } @@ -3462,7 +3460,7 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) fsig.push_back(ty); } } - Type *rt = (jlrettype == (jl_value_t*)jl_nothing->type ? T_void : julia_type_to_llvm(jlrettype)); + Type *rt = (jlrettype == (jl_value_t*)jl_void_type ? T_void : julia_type_to_llvm(jlrettype)); f = Function::Create(FunctionType::get(rt, fsig, false), Function::ExternalLinkage, funcName.str(), m); if (lam->cFunctionObject == NULL) { @@ -4044,7 +4042,7 @@ extern "C" void jl_fptr_to_llvm(void *fptr, jl_lambda_info_t *lam, int specsig) if (ty != T_void && !ty->isEmptyTy()) fsig.push_back(ty); } - Type *rt = (jlrettype == (jl_value_t*)jl_nothing->type ? T_void : julia_type_to_llvm(jlrettype)); + Type *rt = (jlrettype == (jl_value_t*)jl_void_type ? T_void : julia_type_to_llvm(jlrettype)); Function *f = Function::Create(FunctionType::get(rt, fsig, false), #ifdef USE_MCJIT Function::ExternalLinkage, funcName, shadow_module); diff --git a/src/dump.c b/src/dump.c index ecd33116b607e..d79b35f15f93c 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1201,8 +1201,8 @@ void jl_init_serializer(void) (void*)Int32_tag, (void*)Array1d_tag, (void*)Singleton_tag, jl_module_type, jl_tvar_type, jl_lambda_info_type, - jl_null, jl_false, jl_true, jl_any_type, jl_symbol("Any"), - jl_symbol("Array"), jl_symbol("TypeVar"), + jl_null, jl_false, jl_true, jl_nothing, jl_any_type, + jl_symbol("Any"), jl_symbol("Array"), jl_symbol("TypeVar"), jl_symbol("Box"), jl_symbol("apply"), lambda_sym, body_sym, return_sym, call_sym, colons_sym, null_sym, goto_ifnot_sym, assign_sym, @@ -1255,7 +1255,6 @@ void jl_init_serializer(void) jl_box_int32(51), jl_box_int32(52), jl_box_int32(53), jl_box_int32(54), jl_box_int32(55), jl_box_int32(56), jl_box_int32(57), jl_box_int32(58), jl_box_int32(59), - jl_box_int32(60), jl_box_int32(61), #endif jl_box_int64(0), jl_box_int64(1), jl_box_int64(2), jl_box_int64(3), jl_box_int64(4), jl_box_int64(5), @@ -1278,13 +1277,12 @@ void jl_init_serializer(void) jl_box_int64(51), jl_box_int64(52), jl_box_int64(53), jl_box_int64(54), jl_box_int64(55), jl_box_int64(56), jl_box_int64(57), jl_box_int64(58), jl_box_int64(59), - jl_box_int64(60), jl_box_int64(61), #endif jl_labelnode_type, jl_linenumbernode_type, jl_gotonode_type, jl_quotenode_type, jl_topnode_type, jl_type_type, jl_bottom_type, jl_pointer_type, jl_vararg_type, jl_ntuple_type, jl_abstractarray_type, - jl_densearray_type, jl_box_type, + jl_densearray_type, jl_box_type, jl_void_type, jl_typector_type, jl_undef_type, jl_top_type, jl_typename_type, jl_task_type, jl_uniontype_type, jl_typetype_type, jl_typetype_tvar, jl_ANY_flag, jl_array_any_type, jl_intrinsic_type, jl_method_type, @@ -1296,7 +1294,7 @@ void jl_init_serializer(void) jl_typename_type->name, jl_type_type->name, jl_methtable_type->name, jl_method_type->name, jl_tvar_type->name, jl_vararg_type->name, jl_ntuple_type->name, jl_abstractarray_type->name, - jl_densearray_type->name, + jl_densearray_type->name, jl_void_type->name, jl_lambda_info_type->name, jl_module_type->name, jl_box_type->name, jl_function_type->name, jl_typector_type->name, jl_intrinsic_type->name, jl_undef_type->name, jl_task_type->name, diff --git a/src/gf.c b/src/gf.c index a2ae90d84a055..e3d24764040a7 100644 --- a/src/gf.c +++ b/src/gf.c @@ -905,10 +905,10 @@ static jl_value_t *lookup_match(jl_value_t *a, jl_value_t *b, jl_tuple_t **penv, ee[n++] = val; /* since "a" is a concrete type, we assume that - (a∩b != None) => a<:b. However if a static parameter is - forced to equal None, then part of "b" might become None, + (a∩b != Union()) => a<:b. However if a static parameter is + forced to equal Union(), then part of "b" might become Union(), and therefore a subtype of "a". For example - (Type{None},Int) ∩ (Type{T},T) + (Type{Union()},Int) ∩ (Type{T},T) issue #5254 */ if (val == (jl_value_t*)jl_bottom_type) { diff --git a/src/init.c b/src/init.c index e91cff2ad2de0..2b943f70e59a3 100644 --- a/src/init.c +++ b/src/init.c @@ -1068,7 +1068,6 @@ static jl_value_t *basemod(char *name) // fetch references to things defined in boot.jl void jl_get_builtin_hooks(void) { - jl_nothing = core("nothing"); jl_root_task->tls = jl_nothing; jl_root_task->consumers = jl_nothing; jl_root_task->donenotify = jl_nothing; diff --git a/src/jltypes.c b/src/jltypes.c index 3f8b72f245263..745d18e865098 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -395,7 +395,7 @@ static jl_value_t *intersect_union(jl_uniontype_t *a, jl_value_t *b, return tu; } -// if returns with *bot!=0, then intersection is None +// if returns with *bot!=0, then intersection is Union() static size_t tuple_intersect_size(jl_tuple_t *a, jl_tuple_t *b, int *bot) { size_t al = jl_tuple_len(a); @@ -524,7 +524,7 @@ static jl_value_t *intersect_tag(jl_datatype_t *a, jl_datatype_t *b, ti = jl_type_intersect(ap,bp,penv,eqc,invariant); if (bp == (jl_value_t*)jl_bottom_type && !((jl_tvar_t*)ap)->bound) { - // "None" as a type parameter + // "Union()" as a type parameter jl_tupleset(p, i, ti); continue; } @@ -533,7 +533,7 @@ static jl_value_t *intersect_tag(jl_datatype_t *a, jl_datatype_t *b, ti = jl_type_intersect(ap,bp,penv,eqc,invariant); if (ap == (jl_value_t*)jl_bottom_type && !((jl_tvar_t*)bp)->bound) { - // "None" as a type parameter + // "Union()" as a type parameter jl_tupleset(p, i, ti); continue; } @@ -553,7 +553,7 @@ static jl_value_t *intersect_tag(jl_datatype_t *a, jl_datatype_t *b, else if (type_eqv_(ap,bp)) { ti = ap; if (ti == (jl_value_t*)jl_bottom_type) { - // "None" as a type parameter + // "Union()" as a type parameter jl_tupleset(p, i, ti); continue; } @@ -1017,7 +1017,7 @@ static jl_value_t *jl_type_intersect(jl_value_t *a, jl_value_t *b, // uses to instantiate its supertype. this tells us what subtype parameter // values are implied by the intersected supertype, or that the // intersected supertype cannot come from this subtype (in which case - // our final answer is None). + // our final answer is Union()). size_t i; // hack: we need type_match to find assignments for all typevars int prev_mim = match_intersection_mode; @@ -1064,7 +1064,7 @@ static jl_value_t *jl_type_intersect(jl_value_t *a, jl_value_t *b, if (jl_tupleref(env, e) == tp) { elt = jl_type_intersect(elt, jl_tupleref(env, e+1), penv, eqc, invariant); - // note: elt might be None if "None" was the type parameter + // note: elt might be Union() if "Union()" was the type parameter break; } } @@ -2086,7 +2086,7 @@ static int jl_subtype_le(jl_value_t *a, jl_value_t *b, int ta, int invariant) } } else if (a == b) { - // None <: None + // Union() <: Union() return 1; } size_t i; @@ -2857,7 +2857,6 @@ void jl_init_types(void) jl_null = (jl_tuple_t*)newobj((jl_value_t*)jl_tuple_type, 1); jl_tuple_set_len_unsafe(jl_null, 0); - jl_nothing = (jl_value_t*)jl_null; // for bootstrapping jl_any_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Any"), NULL, jl_null); jl_any_type->super = jl_any_type; @@ -2937,6 +2936,11 @@ void jl_init_types(void) jl_sym_type->mutabl = 1; // now they can be used to create the remaining base kinds and types + jl_void_type = jl_new_datatype(jl_symbol("Void"), jl_any_type, jl_null, + jl_null, jl_null, 0, 0); + jl_nothing = newstruct(jl_void_type); + jl_void_type->instance = jl_nothing; + jl_uniontype_type = jl_new_datatype(jl_symbol("UnionType"), jl_type_type, jl_null, jl_tuple(1, jl_symbol("types")), @@ -3187,7 +3191,7 @@ void jl_init_types(void) // complete builtin type metadata jl_value_t *pointer_void = jl_apply_type((jl_value_t*)jl_pointer_type, - jl_tuple(1,jl_bottom_type)); + jl_tuple(1,jl_void_type)); jl_voidpointer_type = (jl_datatype_t*)pointer_void; jl_tupleset(jl_datatype_type->types, 0, pointer_void); jl_tupleset(jl_datatype_type->types, 9, jl_int32_type); diff --git a/src/julia.h b/src/julia.h index 32c603c5f9623..826b0c9798451 100644 --- a/src/julia.h +++ b/src/julia.h @@ -359,6 +359,7 @@ extern DLLEXPORT jl_datatype_t *jl_float32_type; extern DLLEXPORT jl_datatype_t *jl_float64_type; extern DLLEXPORT jl_datatype_t *jl_floatingpoint_type; extern DLLEXPORT jl_datatype_t *jl_number_type; +extern DLLEXPORT jl_datatype_t *jl_void_type; extern DLLEXPORT jl_datatype_t *jl_voidpointer_type; extern DLLEXPORT jl_datatype_t *jl_pointer_type; @@ -640,11 +641,11 @@ jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_datatype_t *super, jl_tuple_t *parameters); DLLEXPORT jl_datatype_t *jl_new_uninitialized_datatype(size_t nfields); DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super, - jl_tuple_t *parameters, - jl_tuple_t *fnames, jl_tuple_t *ftypes, - int abstract, int mutabl); + jl_tuple_t *parameters, + jl_tuple_t *fnames, jl_tuple_t *ftypes, + int abstract, int mutabl); DLLEXPORT jl_datatype_t *jl_new_bitstype(jl_value_t *name, jl_datatype_t *super, - jl_tuple_t *parameters, size_t nbits); + jl_tuple_t *parameters, size_t nbits); jl_datatype_t *jl_wrap_Type(jl_value_t *t); // x -> Type{x} jl_datatype_t *jl_wrap_vararg(jl_value_t *t); // x -> x... diff --git a/test/arrayops.jl b/test/arrayops.jl index abf073de17f05..2c16074ad6c0b 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -881,7 +881,7 @@ let end # issue #6977 -@test []' == Array(None,1,0) +@test size([]') == (1,0) # issue #6996 @test { 1 2; 3 4 }' == { 1 2; 3 4 }.' diff --git a/test/core.jl b/test/core.jl index cc5c712be1f31..9f75bc75e9c1d 100644 --- a/test/core.jl +++ b/test/core.jl @@ -1,5 +1,7 @@ # test core language features +const Bottom = Union() + # basic type relationships @test Int8 <: Integer @test Int32 <: Integer @@ -17,18 +19,18 @@ @test !(Array{Int8,1} <: Array{Any,1}) @test !(Array{Any,1} <: Array{Int8,1}) @test Array{Int8,1} <: Array{Int8,1} -@test !(Type{None} <: Type{Int32}) +@test !(Type{Bottom} <: Type{Int32}) @test !(Vector{Float64} <: Vector{Union(Float64,Float32)}) -@test is(None, typeintersect(Vector{Float64},Vector{Union(Float64,Float32)})) +@test is(Bottom, typeintersect(Vector{Float64},Vector{Union(Float64,Float32)})) @test !isa(Array,Type{Any}) @test Type{Complex} <: DataType @test isa(Complex,Type{Complex}) -@test !(Type{Ptr{None}} <: Type{Ptr}) +@test !(Type{Ptr{Bottom}} <: Type{Ptr}) @test !(Type{Rational{Int}} <: Type{Rational}) let T = TypeVar(:T,true) - @test !is(None, typeintersect(Array{None},AbstractArray{T})) - @test is(None, typeintersect((Type{Ptr{Uint8}},Ptr{None}), + @test !is(Bottom, typeintersect(Array{Bottom},AbstractArray{T})) + @test is(Bottom, typeintersect((Type{Ptr{Uint8}},Ptr{Bottom}), (Type{Ptr{T}},Ptr{T}))) @test !(Type{T} <: TypeVar) @@ -39,11 +41,11 @@ let T = TypeVar(:T,true) (Int, Array{Int,1})) @test isequal(typeintersect((T, AbstractArray{T}),(Int, Array{Number,1})), - None) + Bottom) @test isequal(typeintersect((T, AbstractArray{T}),(Any, Array{Number,1})), (Number, Array{Number,1})) - @test !is(None, typeintersect((Array{T}, Array{T}), (Array, Array{Any}))) + @test !is(Bottom, typeintersect((Array{T}, Array{T}), (Array, Array{Any}))) f47{T}(x::Vector{Vector{T}}) = 0 @test_throws MethodError f47(Array(Vector,0)) @test f47(Array(Vector{Int},0)) == 0 @@ -55,17 +57,17 @@ let T = TypeVar(:T,true) @test typeintersect(Type{TypeVar(:T,Array{TT,1})},Type{Array{S,N}}) == Type{Array{S,1}} # issue #5359 @test typeintersect((Type{Array{T,1}},Array{T,1}), - (Type{AbstractVector},Vector{Int})) === None + (Type{AbstractVector},Vector{Int})) === Bottom # issue #5559 @test typeintersect((Type{Vector{Complex128}}, AbstractVector), (Type{Array{T,N}}, Array{S,N})) == (Type{Vector{Complex128}},Vector) @test typeintersect((Type{Vector{Complex128}}, AbstractArray), (Type{Array{T,N}}, Array{S,N})) == (Type{Vector{Complex128}},Vector) - @test typeintersect(Type{Array{T}}, Type{AbstractArray{T}}) === None + @test typeintersect(Type{Array{T}}, Type{AbstractArray{T}}) === Bottom - @test typeintersect(Type{(Bool,Int...)}, Type{(T...)}) === None - @test typeintersect(Type{(Bool,Int...)}, Type{(T,T...)}) === None + @test typeintersect(Type{(Bool,Int...)}, Type{(T...)}) === Bottom + @test typeintersect(Type{(Bool,Int...)}, Type{(T,T...)}) === Bottom end let N = TypeVar(:N,true) @test isequal(typeintersect((NTuple{N,Integer},NTuple{N,Integer}), @@ -82,24 +84,24 @@ let N = TypeVar(:N,true) ((Int,Int...),Array{Int,2})), ((Int,Int), Array{Int,2})) - @test isequal(typeintersect((Type{Nothing},Type{Nothing}), Type{NTuple{N,Nothing}}), - Type{(Nothing,Nothing)}) + @test isequal(typeintersect((Type{Void},Type{Void}), Type{NTuple{N,Void}}), + Type{(Void,Void)}) end -@test is(None, typeintersect(Type{Any},Type{Complex})) -@test is(None, typeintersect(Type{Any},Type{TypeVar(:T,Real)})) +@test is(Bottom, typeintersect(Type{Any},Type{Complex})) +@test is(Bottom, typeintersect(Type{Any},Type{TypeVar(:T,Real)})) @test !(Type{Array{Integer}} <: Type{AbstractArray{Integer}}) @test !(Type{Array{Integer}} <: Type{Array{TypeVar(:T,Integer)}}) -@test is(None, typeintersect(Type{Function},UnionType)) +@test is(Bottom, typeintersect(Type{Function},UnionType)) @test is(Type{Int32}, typeintersect(Type{Int32},DataType)) @test !(Type <: TypeVar) -@test !is(None, typeintersect(DataType, Type)) -@test !is(None, typeintersect(UnionType, Type)) -@test !is(None, typeintersect(DataType, Type{Int})) -@test !is(None, typeintersect(DataType, Type{TypeVar(:T,Int)})) -@test !is(None, typeintersect(DataType, Type{TypeVar(:T,Integer)})) +@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)})) @test typeintersect((Int...), (Bool...)) === () -@test typeintersect(Type{(Int...)}, Type{(Bool...)}) === None +@test typeintersect(Type{(Int...)}, Type{(Bool...)}) === Bottom @test typeintersect((Bool,Int...), (Bool...)) === (Bool,) let T = TypeVar(:T,Union(Float32,Float64)) @@ -129,8 +131,8 @@ end @test issubtype(Array{(Any...)}, Array{NTuple}) @test !issubtype(Array{(Int...)}, Array{NTuple}) @test !issubtype(Array{(Int,Int)}, Array{NTuple}) -@test issubtype(Type{(Nothing,)}, (Type{Nothing},)) -@test issubtype((Type{Nothing},),Type{(Nothing,)}) +@test issubtype(Type{(Void,)}, (Type{Void},)) +@test issubtype((Type{Void},),Type{(Void,)}) # this is fancy: know that any type T<:Number must be either a DataType or a UnionType @test Type{TypeVar(:T,Number)} <: Union(DataType,UnionType) @@ -138,8 +140,8 @@ end @test Type{TypeVar(:T,Tuple)} <: Union(Tuple,UnionType) @test !(Type{TypeVar(:T,Tuple)} <: Union(DataType,UnionType)) -@test !is(None, typeintersect((DataType,DataType),Type{TypeVar(:T,(Number,Number))})) -@test !is(None, typeintersect((DataType,UnionType),Type{(Number,None)})) +@test !is(Bottom, typeintersect((DataType,DataType),Type{TypeVar(:T,(Number,Number))})) +@test !is(Bottom, typeintersect((DataType,UnionType),Type{(Number,Bottom)})) # issue #2997 let T = TypeVar(:T,Union(Float64,Array{Float64,1}),true) @@ -164,7 +166,7 @@ end @test Base.typeseq(typejoin(Union(Int,String),Int), Union(Int,String)) @test Base.typeseq(typejoin(Union(Int,String),Int8), Any) -@test promote_type(Bool,None) === Bool +@test promote_type(Bool,Bottom) === Bool # ntuples nttest1{n}(x::NTuple{n,Int}) = n @@ -613,12 +615,11 @@ end # sufficient information # issue #814 begin - local MatOrNothing, my_func, M - typealias MatOrNothing{T} Union(AbstractMatrix{T}, Vector{None}) - my_func{T<:Real}(A::MatOrNothing{T}, B::MatOrNothing{T}, - C::MatOrNothing{T}) = 0 + local MatOrNot, my_func, M + typealias MatOrNot{T} Union(AbstractMatrix{T}, Vector{Union()}) + my_func{T<:Real}(A::MatOrNot{T}, B::MatOrNot{T}, C::MatOrNot{T}) = 0 M = [ 2. 1. ; 1. 1. ] - @test my_func([], M, M) == 0 + @test my_func(Union()[], M, M) == 0 end begin @@ -866,7 +867,7 @@ end # issue #2365 type B2365{T} - v::Union(T, Nothing) + v::Union(T, Void) end @test B2365{Int}(nothing).v === nothing @test B2365{Int}(0).v === 0 @@ -1036,7 +1037,7 @@ function foo(x) end return ret end -x = Array(Union(Dict{Int64,String},Array{Int64,3},Number,String,Nothing), 3) +x = Array(Union(Dict{Int64,String},Array{Int64,3},Number,String,Void), 3) x[1] = 1.0 x[2] = 2.0 x[3] = 3.0 @@ -1153,7 +1154,7 @@ try end # issue #4526 -f4526(x) = isa(x.a, Nothing) +f4526(x) = isa(x.a, Void) @test_throws ErrorException f4526(1) @test_throws ErrorException f4526(im) @test_throws ErrorException f4526(1+2im) @@ -1261,7 +1262,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})}) != None + @test typeintersect(Type{IT4805{1,T}}, Type{TypeVar(:_,IT4805{N,Int})}) != Bottom end let @@ -1301,7 +1302,7 @@ f5150(T) = Array(Rational{T},1) # issue #5165 bitstype 64 T5165{S} -make_t(x::Int64) = Base.box(T5165{Nothing}, Base.unbox(Int64, x)) +make_t(x::Int64) = Base.box(T5165{Void}, Base.unbox(Int64, x)) xs5165 = T5165[make_t(int64(1))] b5165 = IOBuffer() for x in xs5165 @@ -1334,7 +1335,7 @@ end # issue #5254 f5254{T}(::Type{T}, b::T) = 0 f5254(a, b) = 1 -@test f5254(None, 1) == 1 +@test f5254(Bottom, 1) == 1 # evaluate arguments left-to-right, including assignments. issue #4990 let @@ -1360,7 +1361,7 @@ cnvt(T, x) = convert_default(T, x, cnvt) cnvt{S, T, N}(::Type{Array{S, N}}, x::Array{T, N}) = convert(Array{S}, x) function tighttypes!(adf) - T = None + T = Bottom tt = {Int} for t in tt T = typejoin(T, t) @@ -1737,7 +1738,7 @@ f6980(::Union(Int, Float64), ::B6980) = true @test f6980(1, B6980()) # issue #7049 -typealias Maybe7049{T} Union(T,Nothing) +typealias Maybe7049{T} Union(T,Void) function ttt7049(;init::Maybe7049{Union(String,(Int,Char))} = nothing) string("init=", init) end @@ -1842,8 +1843,8 @@ end # issue #8184 immutable Foo8184 - x::Nothing - y::Nothing + x::Void + y::Void z::Float64 end let f = Foo8184(nothing,nothing,1.0) diff --git a/test/functional.jl b/test/functional.jl index 0c222b45666d5..4afe89609bce9 100644 --- a/test/functional.jl +++ b/test/functional.jl @@ -13,9 +13,9 @@ let io=IOBuffer(3) @test takebuf_string(io)=="12" end -# map over [] should return [] +# map over Bottom[] should return Bottom[] # issue #6719 -@test isequal(typeof(map(x -> x, [])), Array{None,1}) +@test isequal(typeof(map(x -> x, Array(Union(),0))), Array{Union(),1}) # maps of tuples (formerly in test/core.jl) -- tuple.jl @test map((x,y)->x+y,(1,2,3),(4,5,6)) == (5,7,9) From b29cb918c8c8ade5d59d4c06fc04538434209dd0 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 25 Sep 2014 12:17:38 -0400 Subject: [PATCH 78/79] Slight cleanup of staged function code --- src/gf.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gf.c b/src/gf.c index a2ae90d84a055..5e22b4b821312 100644 --- a/src/gf.c +++ b/src/gf.c @@ -961,7 +961,8 @@ DLLEXPORT jl_function_t *jl_instantiate_staged(jl_methlist_t *m, jl_tuple_t *tt) } } jl_cellset(ex->args, 1, jl_apply(m->func, tt->data, jl_tuple_len(tt))); - func = (jl_function_t*)jl_toplevel_eval(jl_expand((jl_value_t*)ex)); + code = jl_expand((jl_value_t*)ex); + func = (jl_function_t*)jl_toplevel_eval(code); JL_GC_POP(); return func; } @@ -972,7 +973,8 @@ static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, in size_t nargs = jl_tuple_len(tt); size_t i; jl_value_t *ti=(jl_value_t*)jl_bottom_type; - jl_tuple_t *newsig=NULL, *env = jl_null, *func = NULL; + jl_tuple_t *newsig=NULL, *env = jl_null; + jl_function_t *func = NULL; JL_GC_PUSH3(&env, &newsig, &func); while (m != JL_NULL) { From 94093ce161dd662f93659028c8dce69f30a69333 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 25 Sep 2014 12:45:11 -0400 Subject: [PATCH 79/79] fix #8464 --- src/cgutils.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 62a887481741e..e24ac239884de 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1498,6 +1498,14 @@ static jl_value_t *static_constant_instance(Constant *constant, jl_value_t *jt) return jl_new_bits(jt,&val); } + // issue #8464 + ConstantExpr *ce = dyn_cast(constant); + if (ce != NULL) { + if (ce->isCast()) { + return static_constant_instance(dyn_cast(ce->getOperand(0)), jt); + } + } + assert(jl_is_tuple(jt)); size_t nargs = 0;