diff --git a/NEWS.md b/NEWS.md
index 33b2cebbb2388..23c96f94fc9b8 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -31,6 +31,10 @@ New language features
the module is first loaded, and on process startup if a pre-compiled
version of the module is present ([#1268]).
+ * Multi-line comments ([#69], [#6128]): `#= .... =#`
+
+ * --bounds-check=yes|no compiler option
+
Library improvements
--------------------
diff --git a/base/abstractarray.jl b/base/abstractarray.jl
index e7a0e38ad1a54..c92cda269fcb8 100644
--- a/base/abstractarray.jl
+++ b/base/abstractarray.jl
@@ -331,13 +331,6 @@ imag{T<:Real}(x::AbstractArray{T}) = zero(x)
\(A::Number, B::AbstractArray) = B ./ A
-./(x::Number,y::AbstractArray ) = throw(MethodError(./, (x,y)))
-./(x::AbstractArray, y::Number) = throw(MethodError(./, (x,y)))
-
-.^(x::Number,y::AbstractArray ) = throw(MethodError(.^, (x,y)))
-.^(x::AbstractArray, y::Number) = throw(MethodError(.^, (x,y)))
-
-
## Indexing: getindex ##
getindex(t::AbstractArray, i::Real) = error("indexing not defined for ", typeof(t))
diff --git a/base/array.jl b/base/array.jl
index 42dc231971e16..394f95b6262fa 100644
--- a/base/array.jl
+++ b/base/array.jl
@@ -261,9 +261,11 @@ convert{T,n,S}(::Type{Array{T,n}}, x::Array{S,n}) = copy!(similar(x,T), x)
convert{T,S,N}(::Type{AbstractArray{T,N}}, B::StridedArray{S,N}) = copy!(similar(B,T), B)
-function collect{C}(T::Type, itr::C)
- if method_exists(length,(C,))
- a = Array(T,length(itr))
+function collect(T::Type, itr)
+ if applicable(length, itr)
+ # when length() isn't defined this branch might pollute the
+ # type of the other.
+ a = Array(T,length(itr)::Integer)
i = 0
for x in itr
a[i+=1] = x
@@ -276,9 +278,8 @@ function collect{C}(T::Type, itr::C)
end
return a
end
-function collect{C}(itr::C)
- method_exists(eltype,(C,)) ? collect(eltype(itr),itr) : [x for x in itr]
-end
+
+collect(itr) = collect(eltype(itr), itr)
## Indexing: getindex ##
@@ -786,7 +787,7 @@ for f in (:+, :-, :div, :mod, :&, :|, :$)
end
end
end
-for f in (:.+, :.-, :.*, :./, :.%, :div, :mod, :rem, :&, :|, :$)
+for f in (:.+, :.-, :.*, :./, :.\, :.%, :div, :mod, :rem, :&, :|, :$)
@eval begin
function ($f){T}(A::Number, B::StridedArray{T})
F = similar(B, promote_array_type(typeof(A),T))
diff --git a/base/boot.jl b/base/boot.jl
index 71152e6c116ae..3095da73e6c5d 100644
--- a/base/boot.jl
+++ b/base/boot.jl
@@ -152,7 +152,7 @@ export
#checked_smul, checked_ssub, checked_uadd, checked_umul, checked_usub,
#nan_dom_err, copysign_float, ctlz_int, ctpop_int, cttz_int,
#div_float, eq_float, eq_int, eqfsi64, eqfui64, flipsign_int, select_value,
- #fpext64, fpiseq, fpislt, fpsiround, fpuiround, fptosi, fptoui,
+ #sqrt_llvm, fpext64, fpiseq, fpislt, fpsiround, fpuiround, fptosi, fptoui,
#fptrunc32, le_float, lefsi64, lefui64, lesif64,
#leuif64, lshr_int, lt_float, ltfsi64, ltfui64, ltsif64, ltuif64, mul_float,
#mul_int, ne_float, ne_int, neg_float, neg_int, not_int, or_int, rem_float,
diff --git a/base/broadcast.jl b/base/broadcast.jl
index df840ae2916fa..c52192524b706 100644
--- a/base/broadcast.jl
+++ b/base/broadcast.jl
@@ -2,6 +2,7 @@ module Broadcast
using ..Cartesian
import Base.promote_eltype
+import Base.@get!
import Base.num_bit_chunks, Base.@_msk_end, Base.getindex_unchecked
import Base.(.+), Base.(.-), Base.(.*), Base.(./), Base.(.\)
import Base.(.==), Base.(.<), Base.(.!=), Base.(.<=)
@@ -203,73 +204,31 @@ function gen_broadcast_function_tobitarray(genbody::Function, nd::Int, narrays::
end
end
-let broadcast_cache = Dict()
-global broadcast!
-function broadcast!(f::Function, B, As::Union(Array,BitArray)...)
- nd = ndims(B)
- narrays = length(As)
- key = (f, nd, narrays)
- if !haskey(broadcast_cache, key)
- func = gen_broadcast_function(gen_broadcast_body_iter, nd, narrays, f)
- broadcast_cache[key] = func
- else
- func = broadcast_cache[key]
- end
- func(B, As...)
- B
-end
-end # let broadcast_cache
-
-let broadcast_cache = Dict()
-global broadcast!
-function broadcast!(f::Function, B::BitArray, As::Union(Array,BitArray)...)
- nd = ndims(B)
- narrays = length(As)
- key = (f, nd, narrays)
- if !haskey(broadcast_cache, key)
- func = gen_broadcast_function_tobitarray(gen_broadcast_body_iter_tobitarray, nd, narrays, f)
- broadcast_cache[key] = func
- else
- func = broadcast_cache[key]
- end
- func(B, As...)
- B
-end
-end # let broadcast_cache
-
-let broadcast_cache = Dict()
-global broadcast!
-function broadcast!(f::Function, B, As...)
- nd = ndims(B)
- narrays = length(As)
- key = (f, nd, narrays)
- if !haskey(broadcast_cache, key)
- func = gen_broadcast_function(gen_broadcast_body_cartesian, nd, narrays, f)
- broadcast_cache[key] = func
- else
- func = broadcast_cache[key]
- end
- func(B, As...)
- B
-end
-end # let broadcast_cache
-
-let broadcast_cache = Dict()
-global broadcast!
-function broadcast!(f::Function, B::BitArray, As...)
- nd = ndims(B)
- narrays = length(As)
- key = (f, nd, narrays)
- if !haskey(broadcast_cache, key)
- func = gen_broadcast_function_tobitarray(gen_broadcast_body_cartesian_tobitarray, nd, narrays, f)
- broadcast_cache[key] = func
- else
- func = broadcast_cache[key]
- end
- func(B, As...)
- B
+for (Bsig, Asig, gbf, gbb) in
+ ((BitArray , Union(Array,BitArray) ,
+ :gen_broadcast_function_tobitarray, :gen_broadcast_body_iter_tobitarray ),
+ (Any , Union(Array,BitArray) ,
+ :gen_broadcast_function , :gen_broadcast_body_iter ),
+ (BitArray , Any ,
+ :gen_broadcast_function_tobitarray, :gen_broadcast_body_cartesian_tobitarray),
+ (Any , Any ,
+ :gen_broadcast_function , :gen_broadcast_body_cartesian ))
+
+ @eval let cache = Dict{Function,Dict{Int,Dict{Int,Function}}}()
+ global broadcast!
+ function broadcast!(f::Function, B::$Bsig, As::$Asig...)
+ nd = ndims(B)
+ narrays = length(As)
+
+ cache_f = @get! cache f Dict{Int,Dict{Int,Function}}()
+ cache_f_na = @get! cache_f narrays Dict{Int,Function}()
+ func = @get! cache_f_na nd $gbf($gbb, nd, narrays, f)
+
+ func(B, As...)
+ B
+ end
+ end # let broadcast_cache
end
-end # let broadcast_cache
broadcast(f::Function, As...) = broadcast!(f, Array(promote_eltype(As...), broadcast_shape(As...)), As...)
diff --git a/base/client.jl b/base/client.jl
index 8f5589f887a64..aee03eb75381f 100644
--- a/base/client.jl
+++ b/base/client.jl
@@ -364,14 +364,17 @@ function load_juliarc()
try_include(abspath(homedir(),".juliarc.jl"))
end
-
-function _start()
+function early_init()
Sys.init_sysinfo()
if CPU_CORES > 8 && !("OPENBLAS_NUM_THREADS" in keys(ENV)) && !("OMP_NUM_THREADS" in keys(ENV))
# Prevent openblas from stating to many threads, unless/until specifically requested
ENV["OPENBLAS_NUM_THREADS"] = 8
end
start_gc_msgs_task()
+end
+
+function _start()
+ early_init()
try
any(a->(a=="--worker"), ARGS) || init_head_sched()
diff --git a/base/dict.jl b/base/dict.jl
index 43f9b70592dcc..945a4faa48df2 100644
--- a/base/dict.jl
+++ b/base/dict.jl
@@ -561,6 +561,26 @@ function get!{K,V}(default::Function, h::Dict{K,V}, key0)
return v
end
+# NOTE: this macro is specific to Dict, not Associative, and should
+# therefore not be exported as-is: it's for internal use only.
+macro get!(h, key0, default)
+ quote
+ K, V = eltype($(esc(h)))
+ key = convert(K, $(esc(key0)))
+ isequal(key, $(esc(key0))) || error($(esc(key0)), " is not a valid key for type ", K)
+ idx = ht_keyindex2($(esc(h)), key)
+ if idx < 0
+ idx = -idx
+ v = convert(V, $(esc(default)))
+ _setindex!($(esc(h)), v, key, idx)
+ else
+ @inbounds v = $(esc(h)).vals[idx]
+ end
+ v
+ end
+end
+
+
function getindex{K,V}(h::Dict{K,V}, key)
index = ht_keyindex(h, key)
return (index<0) ? throw(KeyError(key)) : h.vals[index]::V
diff --git a/base/intfuncs.jl b/base/intfuncs.jl
index dbf5007e5c366..43acccb9b7bb2 100644
--- a/base/intfuncs.jl
+++ b/base/intfuncs.jl
@@ -146,7 +146,7 @@ nextpow2(x::Integer) = oftype(x,x < 0 ? -nextpow2(unsigned(-x)) : nextpow2(unsig
prevpow2(x::Unsigned) = (one(x)>>(x==0)) << ((sizeof(x)<<3)-leading_zeros(x)-1)
prevpow2(x::Integer) = oftype(x,x < 0 ? -prevpow2(unsigned(-x)) : prevpow2(unsigned(x)))
-ispow2(x::Integer) = ((x<=0) == (x&(x-1)))
+ispow2(x::Integer) = count_ones(x)==1
# smallest a^n >= x, with integer n
function nextpow(a::Real, x::Real)
diff --git a/base/io.jl b/base/io.jl
index 0faf10ba4988f..d93f9f565a7d0 100644
--- a/base/io.jl
+++ b/base/io.jl
@@ -226,17 +226,9 @@ function done(itr::EachLine, nada)
true
end
next(itr::EachLine, nada) = (readline(itr.stream), nothing)
+eltype(itr::EachLine) = ByteString
-function readlines(s, fx::Function...)
- a = {}
- for l in eachline(s)
- for f in fx
- l = f(l)
- end
- push!(a, l)
- end
- return a
-end
+readlines(s) = collect(eachline(s))
## IOStream
diff --git a/base/math.jl b/base/math.jl
index 8570ec8b3553e..e2f3d19fd0cdd 100644
--- a/base/math.jl
+++ b/base/math.jl
@@ -22,7 +22,7 @@ import Base: log, exp, sin, cos, tan, sinh, cosh, tanh, asin,
acos, atan, asinh, acosh, atanh, sqrt, log2, log10,
max, min, minmax, ceil, floor, trunc, round, ^, exp2, exp10
-import Core.Intrinsics.nan_dom_err
+import Core.Intrinsics: nan_dom_err, sqrt_llvm, box, unbox
# non-type specific math functions
@@ -49,25 +49,22 @@ function sinpi(x::Real)
return nan(x)
end
- rx = float(rem(x,2))
+ rx = copysign(float(rem(x,2)),x)
arx = abs(rx)
- if arx == 0.0
- # return -0.0 iff x == -0.0
- return x == 0.0 ? x : arx
- elseif arx < 0.25
+ if arx < oftype(rx,0.25)
return sin(pi*rx)
- elseif arx <= 0.75
- arx = 0.5 - arx
+ elseif arx <= oftype(rx,0.75)
+ arx = oftype(rx,0.5) - arx
return copysign(cos(pi*arx),rx)
- elseif arx < 1.25
- rx = copysign(1.0,rx) - rx
+ elseif arx < oftype(rx,1.25)
+ rx = (one(rx) - arx)*sign(rx)
return sin(pi*rx)
- elseif arx <= 1.75
- arx = 1.5 - arx
+ elseif arx <= oftype(rx,1.75)
+ arx = oftype(rx,1.5) - arx
return -copysign(cos(pi*arx),rx)
else
- rx = rx - copysign(2.0,rx)
+ rx = rx - copysign(oftype(rx,2.0),rx)
return sin(pi*rx)
end
end
@@ -81,19 +78,19 @@ function cospi(x::Real)
rx = abs(float(rem(x,2)))
- if rx <= 0.25
+ if rx <= oftype(rx,0.25)
return cos(pi*rx)
- elseif rx < 0.75
- rx = 0.5 - rx
+ elseif rx < oftype(rx,0.75)
+ rx = oftype(rx,0.5) - rx
return sin(pi*rx)
- elseif rx <= 1.25
- rx = 1.0 - rx
+ elseif rx <= oftype(rx,1.25)
+ rx = one(rx) - rx
return -cos(pi*rx)
- elseif rx < 1.75
- rx = rx - 1.5
+ elseif rx < oftype(rx,1.75)
+ rx = rx - oftype(rx,1.5)
return sin(pi*rx)
else
- rx = 2.0 - rx
+ rx = oftype(rx,2.0) - rx
return cos(pi*rx)
end
end
@@ -172,25 +169,22 @@ function sind(x::Real)
return nan(x)
end
- rx = rem(x,360.0)
+ rx = copysign(float(rem(x,360)),x)
arx = abs(rx)
- if arx == 0.0
- # return -0.0 iff x == -0.0
- return x == 0.0 ? 0.0 : arx
- elseif arx < 45.0
+ if arx < oftype(rx,45.0)
return sin(deg2rad(rx))
- elseif arx <= 135.0
- arx = 90.0 - arx
+ elseif arx <= oftype(rx,135.0)
+ arx = oftype(rx,90.0) - arx
return copysign(cos(deg2rad(arx)),rx)
- elseif arx < 225.0
- rx = copysign(180.0,rx) - rx
+ elseif arx < oftype(rx,225.0)
+ rx = (oftype(rx,180.0) - arx)*sign(rx)
return sin(deg2rad(rx))
elseif arx <= 315.0
- arx = 270.0 - arx
+ arx = oftype(rx,270.0) - arx
return -copysign(cos(deg2rad(arx)),rx)
else
- rx = rx - copysign(360.0,rx)
+ rx = rx - copysign(oftype(rx,360.0),rx)
return sin(deg2rad(rx))
end
end
@@ -203,21 +197,21 @@ function cosd(x::Real)
return nan(x)
end
- rx = abs(rem(x,360.0))
+ rx = abs(float(rem(x,360)))
- if rx <= 45.0
+ if rx <= oftype(rx,45.0)
return cos(deg2rad(rx))
- elseif rx < 135.0
- rx = 90.0 - rx
+ elseif rx < oftype(rx,135.0)
+ rx = oftype(rx,90.0) - rx
return sin(deg2rad(rx))
- elseif rx <= 225.0
- rx = 180.0 - rx
+ elseif rx <= oftype(rx,225.0)
+ rx = oftype(rx,180.0) - rx
return -cos(deg2rad(rx))
- elseif rx < 315.0
- rx = rx - 270.0
+ elseif rx < oftype(rx,315.0)
+ rx = rx - oftype(rx,270.0)
return sin(deg2rad(rx))
else
- rx = 360.0 - rx
+ rx = oftype(rx,360.0) - rx
return cos(deg2rad(rx))
end
end
@@ -272,7 +266,7 @@ exp10(x::Integer) = exp10(float(x))
# functions that return NaN on non-NaN argument for domain error
for f in (:sin, :cos, :tan, :asin, :acos, :acosh, :atanh, :log, :log2, :log10,
- :lgamma, :sqrt, :log1p)
+ :lgamma, :log1p)
@eval begin
($f)(x::Float64) = nan_dom_err(ccall(($(string(f)),libm), Float64, (Float64,), x), x)
($f)(x::Float32) = nan_dom_err(ccall(($(string(f,"f")),libm), Float32, (Float32,), x), x)
@@ -281,6 +275,11 @@ for f in (:sin, :cos, :tan, :asin, :acos, :acosh, :atanh, :log, :log2, :log10,
end
end
+sqrt(x::Float64) = box(Float64,sqrt_llvm(unbox(Float64,x)))
+sqrt(x::Float32) = box(Float32,sqrt_llvm(unbox(Float32,x)))
+sqrt(x::Real) = sqrt(float(x))
+@vectorize_1arg Number sqrt
+
for f in (:ceil, :trunc, :significand) # :rint, :nearbyint
@eval begin
($f)(x::Float64) = ccall(($(string(f)),libm), Float64, (Float64,), x)
@@ -410,8 +409,8 @@ modf(x) = rem(x,one(x)), trunc(x)
^(x::Float64, y::Float64) = nan_dom_err(ccall((:pow,libm), Float64, (Float64,Float64), x, y), x+y)
^(x::Float32, y::Float32) = nan_dom_err(ccall((:powf,libm), Float32, (Float32,Float32), x, y), x+y)
-^(x::Float64, y::Integer) = x^float64(y)
-^(x::Float32, y::Integer) = x^float32(y)
+^(x::Float64, y::Integer) = ccall((:pow,libm), Float64, (Float64,Float64), x, y)
+^(x::Float32, y::Integer) = ccall((:powf,libm), Float32, (Float32,Float32), x, y)
# special functions
diff --git a/contrib/Julia.tmbundle/Preferences/Comments.tmPreferences b/contrib/Julia.tmbundle/Preferences/Comments.tmPreferences
index 33a7700e3f91b..c7b376902bd32 100644
--- a/contrib/Julia.tmbundle/Preferences/Comments.tmPreferences
+++ b/contrib/Julia.tmbundle/Preferences/Comments.tmPreferences
@@ -20,6 +20,30 @@
value
#
+
+ name
+ TM_COMMENT_START_2
+ value
+ #=
+
+
+ name
+ TM_COMMENT_END_2
+ value
+ =#
+
+
+ name
+ TM_COMMENT_DISABLE_INDENT_2
+ value
+ yes
+
+
+ name
+ TM_COMMENT_MODE_2
+ value
+ block
+
uuid
diff --git a/contrib/Julia.tmbundle/Syntaxes/Julia.tmLanguage b/contrib/Julia.tmbundle/Syntaxes/Julia.tmLanguage
index 437e217a07101..acf61d295307d 100644
--- a/contrib/Julia.tmbundle/Syntaxes/Julia.tmLanguage
+++ b/contrib/Julia.tmbundle/Syntaxes/Julia.tmLanguage
@@ -109,6 +109,30 @@
patterns
+
+ begin
+ #=
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.definition.comment.begin.julia
+
+
+ end
+ =#
+ endCaptures
+
+ 0
+
+ name
+ punctuation.definition.comment.end.julia
+
+
+ name
+ comment.block.number-sign-equals.julia
+
captures
diff --git a/contrib/julia.xml b/contrib/julia.xml
index 5d29bcda648aa..1422b0470ba2d 100644
--- a/contrib/julia.xml
+++ b/contrib/julia.xml
@@ -29,7 +29,7 @@
-
+
@@ -342,6 +342,7 @@
+
@@ -433,6 +434,15 @@
+
+
+
+
+
+
+
+
+
@@ -464,6 +474,7 @@
+
diff --git a/deps/libuv b/deps/libuv
index a37279a161589..6649b84058e82 160000
--- a/deps/libuv
+++ b/deps/libuv
@@ -1 +1 @@
-Subproject commit a37279a16158923480bab1c23fc8430f76a17bed
+Subproject commit 6649b84058e82f52adbc1a98f0b94b8aff8c467d
diff --git a/doc/conf.py b/doc/conf.py
index 1a0799ceffbc9..b38dabd5670ea 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -21,6 +21,7 @@
sys.path.append(juliadoc_dir)
import juliadoc
+import sphinx_rtd_theme
# -- General configuration -----------------------------------------------------
@@ -49,7 +50,7 @@
# General information about the project.
project = u'Julia Language'
AUTHORS = u"Jeff Bezanson, Stefan Karpinski, Viral Shah, Alan Edelman, et al."
-copyright = u'2012-2013, '+AUTHORS
+copyright = u'2012-2014, '+AUTHORS
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -112,7 +113,8 @@
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
-html_theme_path = [juliadoc.get_theme_dir()]
+html_theme_path = [juliadoc.get_theme_dir(),
+ sphinx_rtd_theme.get_html_theme_path()]
# The name for this set of Sphinx documents. If None, it defaults to
# " v documentation".
diff --git a/doc/index.rst b/doc/index.rst
index 0f6e238b18678..50312f42d89fb 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -3,9 +3,65 @@
Julia Documentation
%%%%%%%%%%%%%%%%%%%%%
+* :ref:`manual`
+* :ref:`stdlib`
+
+.. _manual:
+
+########
+ Manual
+########
+
+.. toctree::
+ :maxdepth: 1
+
+ manual/introduction
+ manual/getting-started
+ manual/variables
+ manual/integers-and-floating-point-numbers
+ manual/mathematical-operations
+ manual/complex-and-rational-numbers
+ manual/strings
+ manual/functions
+ manual/control-flow
+ manual/variables-and-scoping
+ manual/types
+ manual/methods
+ manual/constructors
+ manual/conversion-and-promotion
+ manual/modules
+ manual/metaprogramming
+ manual/arrays
+ manual/linear-algebra
+ manual/networking-and-streams
+ manual/parallel-computing
+ manual/running-external-programs
+ manual/calling-c-and-fortran-code
+ manual/embedding
+ manual/packages
+ manual/performance-tips
+ manual/style-guide
+ manual/faq
+ manual/noteworthy-differences
+
+.. _stdlib:
+
+##################
+ Standard Library
+##################
+
.. toctree::
:maxdepth: 1
- manual/index
- stdlib/index
- packages/packagelist
+ stdlib/base
+ stdlib/sparse
+ stdlib/linalg
+ stdlib/constants
+ stdlib/file
+ stdlib/punctuation
+ stdlib/sort
+ stdlib/pkg
+ stdlib/collections
+ stdlib/graphics
+ stdlib/test
+ stdlib/profile
diff --git a/doc/juliadoc b/doc/juliadoc
index 300b72cd13fe9..88cb64ff33f25 160000
--- a/doc/juliadoc
+++ b/doc/juliadoc
@@ -1 +1 @@
-Subproject commit 300b72cd13fe9b54b938a0b49416e4d860181d0f
+Subproject commit 88cb64ff33f25d50244c337cd3c865392a77400a
diff --git a/doc/manual/getting-started.rst b/doc/manual/getting-started.rst
index 2e09d7a46566a..0ed2a6863fa4d 100644
--- a/doc/manual/getting-started.rst
+++ b/doc/manual/getting-started.rst
@@ -98,6 +98,7 @@ those available for the ``perl`` and ``ruby`` programs::
julia [options] [program] [args...]
-v --version Display version information
+ -h --help Print this message
-q --quiet Quiet startup without banner
-H --home= Load files relative to
-T --tab= Set REPL tab width to
@@ -116,7 +117,7 @@ those available for the ``perl`` and ``ruby`` programs::
-F Load ~/.juliarc.jl, then handle remaining inputs
--color=yes|no Enable or disable color text
- -h --help Print this message
+ --check-bounds=yes|no Emit bounds checks always or never (ignoring declarations)
Resources
---------
diff --git a/doc/requirements.txt b/doc/requirements.txt
index 0cfb48ae2a869..6e0416e70da76 100644
--- a/doc/requirements.txt
+++ b/doc/requirements.txt
@@ -1 +1,2 @@
-e git+https://github.com/JuliaLang/JuliaDoc.git#egg=JuliaDoc
+-e git+https://github.com/snide/sphinx_rtd_theme.git#egg=sphinx_rtd_theme
diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst
index bfe4fe1d7b2c9..9af5bfceff3de 100644
--- a/doc/stdlib/base.rst
+++ b/doc/stdlib/base.rst
@@ -1,5 +1,9 @@
.. currentmodule:: Base
+**********************
+ The Standard Library
+**********************
+
Introduction
------------
@@ -624,7 +628,7 @@ Iterable Collections
Determine whether predicate ``p`` returns true for all elements of ``itr``.
- **Example**: ``all((i) -> i>i, [4,5,6]) = true``
+ **Example**: ``all(i->(4<=i<=6), [4,5,6]) = true``
.. function:: map(f, c...) -> collection
diff --git a/doc/stdlib/index.rst b/doc/stdlib/index.rst
index 109e968b21ce5..a45b06ee855b8 100644
--- a/doc/stdlib/index.rst
+++ b/doc/stdlib/index.rst
@@ -5,10 +5,6 @@
The Julia Standard Library
############################
-*********
-Built-ins
-*********
-
.. toctree::
:maxdepth: 1
@@ -19,16 +15,6 @@ Built-ins
file
punctuation
sort
-
-.. _built-in-modules:
-
-****************
-Built-in Modules
-****************
-
-.. toctree::
- :maxdepth: 1
-
pkg
collections
graphics
diff --git a/doc/stdlib/linalg.rst b/doc/stdlib/linalg.rst
index 2ed2edfc1d8cd..c2d72de56b745 100644
--- a/doc/stdlib/linalg.rst
+++ b/doc/stdlib/linalg.rst
@@ -161,7 +161,9 @@ Linear algebra functions in Julia are largely implemented by calling functions f
.. function:: bkfact(A) -> BunchKaufman
- Compute the Bunch-Kaufman factorization of a real symmetric or complex Hermitian matrix ``A`` and return a ``BunchKaufman`` object. The following functions are available for ``BunchKaufman`` objects: ``size``, ``\``, ``inv``, ``issym``, ``ishermitian``.
+ Compute the Bunch-Kaufman [Bunch1977]_ factorization of a real symmetric or complex Hermitian matrix ``A`` and return a ``BunchKaufman`` object. The following functions are available for ``BunchKaufman`` objects: ``size``, ``\``, ``inv``, ``issym``, ``ishermitian``.
+
+ .. [Bunch1977] J R Bunch and L Kaufman, Some stable methods for calculating inertia and solving symmetric linear systems, Mathematics of Computation 31:137 (1977), 163-179. `url`_.
.. function:: bkfact!(A) -> BunchKaufman
@@ -306,9 +308,9 @@ Linear algebra functions in Julia are largely implemented by calling functions f
Scale an array ``A`` by a scalar ``b``, returning a new array.
- If ``A`` is a matrix and ``b`` is a vector, then ``scale!(A,b)``
+ If ``A`` is a matrix and ``b`` is a vector, then ``scale(A,b)``
scales each column ``i`` of ``A`` by ``b[i]`` (similar to
- ``A*diagm(b)``), while ``scale!(b,A)`` scales each row ``i`` of
+ ``A*diagm(b)``), while ``scale(b,A)`` scales each row ``i`` of
``A`` by ``b[i]`` (similar to ``diagm(b)*A``), returning a new array.
Note: for large ``A``, ``scale`` can be much faster than ``A .* b`` or
@@ -316,7 +318,7 @@ Linear algebra functions in Julia are largely implemented by calling functions f
.. function:: scale!(A, b), scale!(b, A)
- Scale an array ``A`` by a scalar ``b``, similar to ``scale`` but
+ Scale an array ``A`` by a scalar ``b``, similar to :func:`scale` but
overwriting ``A`` in-place.
If ``A`` is a matrix and ``b`` is a vector, then ``scale!(A,b)``
diff --git a/doc/stdlib/punctuation.rst b/doc/stdlib/punctuation.rst
index c5422b4285bfe..0cdd88959f423 100644
--- a/doc/stdlib/punctuation.rst
+++ b/doc/stdlib/punctuation.rst
@@ -11,6 +11,8 @@ Extended documentation for mathematical symbols & functions is :ref:`here (int64_t)S32_MAX || i64 < (int64_t)S32_MIN)
- return (jl_value_t*)jl_box_int64(i64);
- return (jl_value_t*)jl_box_int32((int32_t)i64);
+ jl_compileropts.int_literals!=64
#endif
+ ) {
+ if (i64 > (int64_t)S32_MAX || i64 < (int64_t)S32_MIN)
+ return (jl_value_t*)jl_box_int64(i64);
+ return (jl_value_t*)jl_box_int32((int32_t)i64);
+ }
+ else {
+ return (jl_value_t*)jl_box_int64(i64);
+ }
}
if (issymbol(e)) {
if (e == true_sym)
@@ -477,6 +484,8 @@ jl_value_t *jl_parse_next(void)
if (c == FL_EOF)
return NULL;
if (iscons(c)) {
+ if (cdr_(c) == FL_EOF)
+ return NULL;
value_t a = car_(c);
if (isfixnum(a)) {
jl_lineno = numval(a);
diff --git a/src/builtins.c b/src/builtins.c
index 9e1a12018fb23..55edb077936d8 100644
--- a/src/builtins.c
+++ b/src/builtins.c
@@ -648,7 +648,7 @@ DLLEXPORT int jl_substrtod(char *str, size_t offset, int len, double *out)
char *p;
errno = 0;
char *bstr = str+offset;
- *out = strtod(bstr, &p);
+ *out = strtod_c(bstr, &p);
if ((p == bstr) || (p != (bstr+len)) ||
(errno==ERANGE && (*out==0 || *out==HUGE_VAL || *out==-HUGE_VAL)))
return 1;
@@ -659,7 +659,7 @@ DLLEXPORT int jl_strtod(char *str, double *out)
{
char *p;
errno = 0;
- *out = strtod(str, &p);
+ *out = strtod_c(str, &p);
if (p == str ||
(errno==ERANGE && (*out==0 || *out==HUGE_VAL || *out==-HUGE_VAL)))
return 1;
@@ -677,9 +677,9 @@ DLLEXPORT int jl_substrtof(char *str, int offset, int len, float *out)
errno = 0;
char *bstr = str+offset;
#if defined(_OS_WINDOWS_) && !defined(_COMPILER_MINGW_)
- *out = (float)strtod(bstr, &p);
+ *out = (float)strtod_c(bstr, &p);
#else
- *out = strtof(bstr, &p);
+ *out = strtof_c(bstr, &p);
#endif
if ((p == bstr) || (p != (bstr+len)) ||
@@ -693,9 +693,9 @@ DLLEXPORT int jl_strtof(char *str, float *out)
char *p;
errno = 0;
#if defined(_OS_WINDOWS_) && !defined(_COMPILER_MINGW_)
- *out = (float)strtod(str, &p);
+ *out = (float)strtod_c(str, &p);
#else
- *out = strtof(str, &p);
+ *out = strtof_c(str, &p);
#endif
if (p == str ||
(errno==ERANGE && (*out==0 || *out==HUGE_VALF || *out==-HUGE_VALF)))
diff --git a/src/cgutils.cpp b/src/cgutils.cpp
index cf50e5fd40d35..4da8f10c0bce7 100644
--- a/src/cgutils.cpp
+++ b/src/cgutils.cpp
@@ -767,7 +767,9 @@ static Value *emit_bounds_check(Value *i, Value *len, jl_codectx_t *ctx)
{
Value *im1 = builder.CreateSub(i, ConstantInt::get(T_size, 1));
#if CHECK_BOUNDS==1
- if (ctx->boundsCheck.empty() || ctx->boundsCheck.back()==true) {
+ if (((ctx->boundsCheck.empty() || ctx->boundsCheck.back()==true) &&
+ jl_compileropts.check_bounds != JL_COMPILEROPT_CHECK_BOUNDS_OFF) ||
+ jl_compileropts.check_bounds == JL_COMPILEROPT_CHECK_BOUNDS_ON) {
Value *ok = builder.CreateICmpULT(im1, len);
raise_exception_unless(ok, prepare_global(jlboundserr_var), ctx);
}
@@ -1296,8 +1298,10 @@ static Value *emit_array_nd_index(Value *a, jl_value_t *ex, size_t nd, jl_value_
{
Value *i = ConstantInt::get(T_size, 0);
Value *stride = ConstantInt::get(T_size, 1);
- bool bc = ctx->boundsCheck.empty() || ctx->boundsCheck.back()==true;
#if CHECK_BOUNDS==1
+ bool bc = ((ctx->boundsCheck.empty() || ctx->boundsCheck.back()==true) &&
+ jl_compileropts.check_bounds != JL_COMPILEROPT_CHECK_BOUNDS_OFF) ||
+ jl_compileropts.check_bounds == JL_COMPILEROPT_CHECK_BOUNDS_ON;
BasicBlock *failBB=NULL, *endBB=NULL;
if (bc) {
failBB = BasicBlock::Create(getGlobalContext(), "oob");
diff --git a/src/codegen.cpp b/src/codegen.cpp
index ebed2ab9110f4..f5cdaee1e99e1 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -116,8 +116,6 @@ void __attribute__(()) __stack_chk_fail()
}
}
-#define CONDITION_REQUIRES_BOOL
-
#define DISABLE_FLOAT16
// llvm state
@@ -2223,12 +2221,10 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx)
static Value *emit_condition(jl_value_t *cond, const std::string &msg, jl_codectx_t *ctx)
{
Value *condV = emit_unboxed(cond, ctx);
-#ifdef CONDITION_REQUIRES_BOOL
if (expr_type(cond, ctx) != (jl_value_t*)jl_bool_type &&
condV->getType() != T_int1) {
emit_typecheck(condV, (jl_value_t*)jl_bool_type, msg, ctx);
}
-#endif
if (condV->getType() == T_int1) {
return builder.CreateXor(condV, ConstantInt::get(T_int1,1));
}
@@ -2589,7 +2585,8 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed,
builder.SetInsertPoint(tryblk);
}
else if (head == boundscheck_sym) {
- if (jl_array_len(ex->args) > 0) {
+ if (jl_array_len(ex->args) > 0 &&
+ jl_compileropts.check_bounds == JL_COMPILEROPT_CHECK_BOUNDS_DEFAULT) {
jl_value_t *arg = args[0];
if (arg == jl_true) {
ctx->boundsCheck.push_back(true);
diff --git a/src/flisp/read.c b/src/flisp/read.c
index caaa9e64c4e4e..56a639439e56f 100644
--- a/src/flisp/read.c
+++ b/src/flisp/read.c
@@ -39,7 +39,7 @@ int isnumtok_base(char *tok, value_t *pval, int base)
return 0;
if (!((tok[0]=='0' && tok[1]=='x') || (base >= 15)) &&
strpbrk(tok, ".eEpP")) {
- d = strtod(tok, &end);
+ d = strtod_c(tok, &end);
if (*end == '\0') {
if (pval) *pval = mk_double(d);
return 1;
@@ -55,7 +55,7 @@ int isnumtok_base(char *tok, value_t *pval, int base)
// hexadecimal float literals
else if (((tok[0]=='0' && tok[1]=='x') || (base == 16)) &&
strpbrk(tok, "pP")) {
- d = strtod(tok, &end);
+ d = strtod_c(tok, &end);
if (*end == '\0') {
if (pval) *pval = mk_double(d);
return 1;
diff --git a/src/init.c b/src/init.c
index 9a80112e18c0d..9ef8565bd42f6 100644
--- a/src/init.c
+++ b/src/init.c
@@ -62,7 +62,9 @@ extern BOOL (WINAPI *hSymRefreshModuleList)(HANDLE);
char *julia_home = NULL;
jl_compileropts_t jl_compileropts = { NULL, // build_path
- 0 // code_coverage
+ 0, // code_coverage
+ JL_COMPILEROPT_CHECK_BOUNDS_DEFAULT,
+ 0 // int32_literals
};
int jl_boot_file_loaded = 0;
diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp
index 3001dbbdbbd84..6d0729b558b64 100644
--- a/src/intrinsics.cpp
+++ b/src/intrinsics.cpp
@@ -34,6 +34,7 @@ namespace JL_I {
nan_dom_err,
// functions
abs_float, copysign_float, flipsign_int, select_value,
+ sqrt_llvm,
// pointer access
pointerref, pointerset, pointertoref,
// c interface
@@ -1243,6 +1244,14 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs,
HANDLE(jl_alloca,1) {
return builder.CreateAlloca(IntegerType::get(jl_LLVMContext, 8),JL_INT(x));
}
+ HANDLE(sqrt_llvm,1) {
+ x = FP(x);
+ raise_exception_unless(builder.CreateFCmpUGE(x, ConstantFP::get(x->getType(),0.0)),
+ prepare_global(jldomerr_var), ctx);
+ return builder.CreateCall(Intrinsic::getDeclaration(jl_Module, Intrinsic::sqrt,
+ ArrayRef(x->getType())),
+ x);
+ }
default:
assert(false);
}
@@ -1321,7 +1330,7 @@ extern "C" void jl_init_intrinsic_functions(void)
ADD_I(uitofp); ADD_I(sitofp);
ADD_I(fptrunc); ADD_I(fpext);
ADD_I(abs_float); ADD_I(copysign_float);
- ADD_I(flipsign_int); ADD_I(select_value);
+ ADD_I(flipsign_int); ADD_I(select_value); ADD_I(sqrt_llvm);
ADD_I(pointerref); ADD_I(pointerset); ADD_I(pointertoref);
ADD_I(checked_sadd); ADD_I(checked_uadd);
ADD_I(checked_ssub); ADD_I(checked_usub);
diff --git a/src/jlapi.c b/src/jlapi.c
index da9cbc3260b11..b3105bd203642 100644
--- a/src/jlapi.c
+++ b/src/jlapi.c
@@ -51,11 +51,10 @@ DLLEXPORT void jl_init(char *julia_home_dir)
jl_set_const(jl_core_module, jl_symbol("JULIA_HOME"),
jl_cstr_to_string(julia_home));
jl_module_export(jl_core_module, jl_symbol("JULIA_HOME"));
- jl_eval_string("Base.reinit_stdio()");
- jl_eval_string("Base.Random.librandom_init()");
- jl_eval_string("Base.init_sched()");
+ jl_eval_string("Base.early_init()");
jl_eval_string("Base.init_head_sched()");
jl_eval_string("Base.init_load_path()");
+ jl_exception_clear();
}
DLLEXPORT void *jl_eval_string(char *str)
@@ -72,6 +71,7 @@ DLLEXPORT void *jl_eval_string(char *str)
JL_GC_PUSH1(&ast);
r = jl_toplevel_eval(ast);
JL_GC_POP();
+ jl_exception_clear();
}
JL_CATCH {
//jl_show(jl_stderr_obj(), jl_exception_in_transit);
@@ -143,6 +143,7 @@ DLLEXPORT jl_value_t *jl_call(jl_function_t *f, jl_value_t **args, int32_t nargs
argv[i] = args[i-1];
v = jl_apply(f, args, nargs);
JL_GC_POP();
+ jl_exception_clear();
}
JL_CATCH {
v = NULL;
@@ -157,6 +158,7 @@ DLLEXPORT jl_value_t *jl_call0(jl_function_t *f)
JL_GC_PUSH1(&f);
v = jl_apply(f, NULL, 0);
JL_GC_POP();
+ jl_exception_clear();
}
JL_CATCH {
v = NULL;
@@ -171,6 +173,7 @@ DLLEXPORT jl_value_t *jl_call1(jl_function_t *f, jl_value_t *a)
JL_GC_PUSH2(&f,&a);
v = jl_apply(f, &a, 1);
JL_GC_POP();
+ jl_exception_clear();
}
JL_CATCH {
v = NULL;
@@ -186,6 +189,7 @@ DLLEXPORT jl_value_t *jl_call2(jl_function_t *f, jl_value_t *a, jl_value_t *b)
jl_value_t *args[2] = {a,b};
v = jl_apply(f, args, 2);
JL_GC_POP();
+ jl_exception_clear();
}
JL_CATCH {
v = NULL;
@@ -201,6 +205,7 @@ DLLEXPORT jl_value_t *jl_call3(jl_function_t *f, jl_value_t *a, jl_value_t *b, j
jl_value_t *args[3] = {a,b,c};
v = jl_apply(f, args, 3);
JL_GC_POP();
+ jl_exception_clear();
}
JL_CATCH {
v = NULL;
@@ -224,6 +229,7 @@ DLLEXPORT jl_value_t *jl_get_field(jl_value_t *o, char *fld)
jl_value_t *s = (jl_value_t*)jl_symbol(fld);
int i = jl_field_index((jl_datatype_t*)jl_typeof(o), (jl_sym_t*)s, 1);
v = jl_get_nth_field(o, i);
+ jl_exception_clear();
}
JL_CATCH {
v = NULL;
diff --git a/src/jlfrontend.scm b/src/jlfrontend.scm
index 0a02bc0ba3bf1..8d0fb59d63c8f 100644
--- a/src/jlfrontend.scm
+++ b/src/jlfrontend.scm
@@ -181,19 +181,22 @@
(set! *ts-stack* (cdr *ts-stack*)))
(define (jl-parser-next)
- (skip-ws-and-comments (ts:port current-token-stream))
- (let ((lineno (input-port-line (ts:port current-token-stream))))
- (let ((e (parser-wrap (lambda ()
- (julia-parse current-token-stream)))))
- (if (eof-object? e)
- e
- (cons lineno
- (parser-wrap
- (lambda ()
- (if (and (pair? e) (or (eq? (car e) 'error)
- (eq? (car e) 'continue)))
+ (let* ((err (parser-wrap
+ (lambda ()
+ (skip-ws-and-comments (ts:port current-token-stream)))))
+ (lineno (input-port-line (ts:port current-token-stream))))
+ (cons lineno
+ (if (pair? err)
+ err
+ (parser-wrap
+ (lambda ()
+ (let ((e (julia-parse current-token-stream)))
+ (if (eof-object? e)
e
- (expand-toplevel-expr e)))))))))
+ (if (and (pair? e) (or (eq? (car e) 'error)
+ (eq? (car e) 'continue)))
+ e
+ (expand-toplevel-expr e))))))))))
; expand a piece of raw surface syntax to an executable thunk
(define (jl-expand-to-thunk expr)
diff --git a/src/julia-parser.scm b/src/julia-parser.scm
index e276d1a8567d5..4d14a0ec46f0b 100644
--- a/src/julia-parser.scm
+++ b/src/julia-parser.scm
@@ -355,10 +355,34 @@
(eq? (car t) 'macrocall)
(memq (cadr t) '(@int128_str @uint128_str @bigint_str))))
+; skip to end of comment, starting at #: either #... or #= .... =#.
+(define (skip-comment port)
+ (define (skip-multiline-comment port count)
+ (let ((c (read-char port)))
+ (if (eof-object? c)
+ (error "incomplete: unterminated multi-line comment #= ... =#")
+ (begin (if (eqv? c #\=)
+ (let ((c (peek-char port)))
+ (if (eqv? c #\#)
+ (begin
+ (read-char port)
+ (if (> count 1)
+ (skip-multiline-comment port (- count 1))))
+ (skip-multiline-comment port count)))
+ (if (eqv? c #\#)
+ (skip-multiline-comment port
+ (if (eqv? (peek-char port) #\=) (+ count 1) count))
+ (skip-multiline-comment port count)))))))
+
+ (read-char port) ; read # that was already peeked
+ (if (eqv? (peek-char port) #\=)
+ (skip-multiline-comment port 1)
+ (skip-to-eol port)))
+
(define (skip-ws-and-comments port)
(skip-ws port #t)
(if (eqv? (peek-char port) #\#)
- (begin (skip-to-eol port)
+ (begin (skip-comment port)
(skip-ws-and-comments port)))
#t)
@@ -371,7 +395,7 @@
((char-numeric? c) (read-number port #f #f))
- ((eqv? c #\#) (skip-to-eol port) (next-token port s))
+ ((eqv? c #\#) (skip-comment port) (next-token port s))
; . is difficult to handle; it could start a number or operator
((and (eqv? c #\.)
diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm
index 4691dc6811a50..fca5717b4ba73 100644
--- a/src/julia-syntax.scm
+++ b/src/julia-syntax.scm
@@ -2914,13 +2914,28 @@ So far only the second case can actually occur.
(set-car! (cdr end-jump) (make&mark-label)))))
((block) (for-each (lambda (x) (compile x break-labels vi))
(cdr e)))
- ((_while) (let ((topl (make&mark-label))
- (endl (make-label)))
- (compile (cadr e) break-labels vi)
- (emit `(gotoifnot ,(goto-form (caddr e)) ,endl))
- (compile (cadddr e) break-labels vi)
- (emit `(goto ,topl))
- (mark-label endl)))
+ ((_while)
+ (let ((test-blk (cadr e))
+ (endl (make-label)))
+ (if (or (atom? test-blk) (equal? test-blk '(block)))
+ ;; if condition is simple, compile it twice in order
+ ;; to generate a single branch per iteration.
+ (let ((topl (make-label)))
+ (compile test-blk break-labels vi)
+ (emit `(gotoifnot ,(goto-form (caddr e)) ,endl))
+ (mark-label topl)
+ (compile (cadddr e) break-labels vi)
+ (compile test-blk break-labels vi)
+ (emit `(gotoifnot (call (top !) ,(goto-form (caddr e))) ,topl))
+ (mark-label endl))
+
+ (let ((topl (make&mark-label)))
+ (compile test-blk break-labels vi)
+ (emit `(gotoifnot ,(goto-form (caddr e)) ,endl))
+ (compile (cadddr e) break-labels vi)
+ (emit `(goto ,topl))
+ (mark-label endl)))))
+
((break-block) (let ((endl (make-label)))
(compile (caddr e)
(cons (list (cadr e) endl handler-level)
diff --git a/src/julia.h b/src/julia.h
index 83ea753b26d85..dfbf129fa2488 100644
--- a/src/julia.h
+++ b/src/julia.h
@@ -384,7 +384,7 @@ extern DLLEXPORT jl_datatype_t *jl_methtable_type;
extern DLLEXPORT jl_datatype_t *jl_method_type;
extern DLLEXPORT jl_datatype_t *jl_task_type;
-extern jl_tuple_t *jl_null;
+extern DLLEXPORT jl_tuple_t *jl_null;
#define JL_NULL ((void*)jl_null)
extern jl_value_t *jl_true;
extern jl_value_t *jl_false;
@@ -611,7 +611,7 @@ jl_value_t *jl_full_type(jl_value_t *v);
int jl_is_type(jl_value_t *v);
DLLEXPORT int jl_is_leaf_type(jl_value_t *v);
int jl_has_typevars(jl_value_t *v);
-int jl_subtype(jl_value_t *a, jl_value_t *b, int ta);
+DLLEXPORT int jl_subtype(jl_value_t *a, jl_value_t *b, int ta);
int jl_type_morespecific(jl_value_t *a, jl_value_t *b, int ta);
DLLEXPORT int jl_types_equal(jl_value_t *a, jl_value_t *b);
jl_value_t *jl_type_union(jl_tuple_t *types);
@@ -1294,11 +1294,17 @@ void jl_print_gc_stats(JL_STREAM *s);
typedef struct {
char *build_path;
- int code_coverage;
+ int8_t code_coverage;
+ int8_t check_bounds;
+ int int_literals;
} jl_compileropts_t;
extern DLLEXPORT jl_compileropts_t jl_compileropts;
+#define JL_COMPILEROPT_CHECK_BOUNDS_DEFAULT 0
+#define JL_COMPILEROPT_CHECK_BOUNDS_ON 1
+#define JL_COMPILEROPT_CHECK_BOUNDS_OFF 2
+
#ifdef __cplusplus
}
#endif
diff --git a/src/support/Makefile b/src/support/Makefile
index d284a26098b93..6eee27033d084 100644
--- a/src/support/Makefile
+++ b/src/support/Makefile
@@ -6,7 +6,7 @@ override CXXFLAGS += $(JCXXFLAGS)
OBJS = hashing.o timefuncs.o ptrhash.o operators.o \
utf8.o ios.o htable.o bitvector.o \
- int2str.o libsupportinit.o arraylist.o
+ int2str.o libsupportinit.o arraylist.o strtod.o
ifeq ($(OS),WINNT)
OBJS += asprintf.o wcwidth.o
diff --git a/src/support/libsupport.h b/src/support/libsupport.h
index fd4f43ebb360f..6aa8bb9c761a8 100644
--- a/src/support/libsupport.h
+++ b/src/support/libsupport.h
@@ -14,6 +14,7 @@
#include "ptrhash.h"
#include "bitvector.h"
#include "dirpath.h"
+#include "strtod.h"
DLLEXPORT void libsupport_init(void);
diff --git a/src/support/strtod.c b/src/support/strtod.c
new file mode 100644
index 0000000000000..a99a919ddc159
--- /dev/null
+++ b/src/support/strtod.c
@@ -0,0 +1,291 @@
+#include "libsupport.h"
+#define _GNU_SOURCE
+#include
+#include
+
+#if !defined(_OS_WINDOWS_)
+// This code path should be used for systems that support the strtod_l function
+
+#include
+#if defined(_OS_LINUX_)
+extern double strtod_l(const char *nptr, char **endptr, locale_t loc);
+extern float strtof_l(const char *nptr, char **endptr, locale_t loc);
+#endif
+
+// Cache locale object
+static int c_locale_initialized = 0;
+static locale_t c_locale;
+
+locale_t get_c_locale()
+{
+ if(!c_locale_initialized)
+ {
+ c_locale_initialized = 1;
+ c_locale = newlocale(LC_ALL_MASK, "C", NULL);
+ }
+ return c_locale;
+}
+
+double strtod_c(const char *nptr, char **endptr)
+{
+ return strtod_l(nptr, endptr, get_c_locale());
+}
+
+float strtof_c(const char *nptr, char **endptr)
+{
+ return strtof_l(nptr, endptr, get_c_locale());
+}
+
+
+#else
+// This code path should be used for systems that do not support the strtod_l function
+// Currently this is MinGW/Windows
+
+// The following code is derived from the Python function _PyOS_ascii_strtod
+// see http://hg.python.org/cpython/file/default/Python/pystrtod.c
+//
+// Copyright © 2001-2014 Python Software Foundation; All Rights Reserved
+//
+// The following modifications have been made:
+// - Leading spaces are ignored
+// - Parsing of hex floats is supported in the derived version
+// - Python functions for tolower, isdigit and malloc have been replaced by the respective
+// C stdlib functions
+
+#include
+
+int case_insensitive_match(const char *s, const char *t)
+{
+ while(*t && tolower(*s) == *t) {
+ s++;
+ t++;
+ }
+ return *t ? 0 : 1;
+}
+
+double parse_inf_or_nan(const char *p, char **endptr)
+{
+ double retval;
+ const char *s;
+ int negate = 0;
+
+ s = p;
+ if (*s == '-') {
+ negate = 1;
+ s++;
+ }
+ else if (*s == '+') {
+ s++;
+ }
+ if (case_insensitive_match(s, "inf")) {
+ s += 3;
+ if (case_insensitive_match(s, "inity"))
+ s += 5;
+ retval = negate ? -D_PINF : D_PINF;
+ }
+ else if (case_insensitive_match(s, "nan")) {
+ s += 3;
+ retval = negate ? -D_PNAN : D_PNAN;
+ }
+ else {
+ s = p;
+ retval = -1.0;
+ }
+ *endptr = (char *)s;
+ return retval;
+}
+
+
+double strtod_c(const char *nptr, char **endptr)
+{
+ char *fail_pos;
+ double val;
+ struct lconv *locale_data;
+ const char *decimal_point;
+ size_t decimal_point_len;
+ const char *p, *decimal_point_pos;
+ const char *end = NULL; /* Silence gcc */
+ const char *digits_pos = NULL;
+ int negate = 0;
+
+ fail_pos = NULL;
+
+ locale_data = localeconv();
+ decimal_point = locale_data->decimal_point;
+ decimal_point_len = strlen(decimal_point);
+
+ decimal_point_pos = NULL;
+
+ /* Parse infinities and nans */
+ val = parse_inf_or_nan(nptr, endptr);
+ if (*endptr != nptr)
+ return val;
+
+ /* Set errno to zero, so that we can distinguish zero results
+ and underflows */
+ errno = 0;
+
+ /* We process the optional sign manually, then pass the remainder to
+ the system strtod. This ensures that the result of an underflow
+ has the correct sign. */
+ p = nptr;
+
+ /* parse leading spaces */
+ while (isspace(*p)) {
+ p++;
+ }
+
+ /* Process leading sign, if present */
+ if (*p == '-') {
+ negate = 1;
+ p++;
+ }
+ else if (*p == '+') {
+ p++;
+ }
+
+ /* This code path is used for hex floats */
+ if (*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X'))
+ {
+ digits_pos = p;
+ p += 2;
+ /* Check that what's left begins with a digit or decimal point */
+ if (!isxdigit(*p) && *p != '.')
+ goto invalid_string;
+
+
+ if (decimal_point[0] != '.' ||
+ decimal_point[1] != 0)
+ {
+ /* Look for a '.' in the input; if present, it'll need to be
+ swapped for the current locale's decimal point before we
+ call strtod. On the other hand, if we find the current
+ locale's decimal point then the input is invalid. */
+ while (isxdigit(*p))
+ p++;
+
+ if (*p == '.')
+ {
+ decimal_point_pos = p++;
+
+ /* locate end of number */
+ while (isxdigit(*p))
+ p++;
+
+ if (*p == 'p' || *p == 'P')
+ p++;
+ if (*p == '+' || *p == '-')
+ p++;
+ while (isdigit(*p))
+ p++;
+ end = p;
+ }
+ else if (strncmp(p, decimal_point, decimal_point_len) == 0)
+ goto invalid_string;
+ /* For the other cases, we need not convert the decimal
+ point */
+ }
+ } else
+ {
+ /* Check that what's left begins with a digit or decimal point */
+ if (!isdigit(*p) && *p != '.')
+ goto invalid_string;
+
+ digits_pos = p;
+ if (decimal_point[0] != '.' ||
+ decimal_point[1] != 0)
+ {
+ /* Look for a '.' in the input; if present, it'll need to be
+ swapped for the current locale's decimal point before we
+ call strtod. On the other hand, if we find the current
+ locale's decimal point then the input is invalid. */
+ while (isdigit(*p))
+ p++;
+
+ if (*p == '.')
+ {
+ decimal_point_pos = p++;
+
+ /* locate end of number */
+ while (isdigit(*p))
+ p++;
+
+ if (*p == 'e' || *p == 'E')
+ p++;
+ if (*p == '+' || *p == '-')
+ p++;
+ while (isdigit(*p))
+ p++;
+ end = p;
+ }
+ else if (strncmp(p, decimal_point, decimal_point_len) == 0)
+ goto invalid_string;
+ /* For the other cases, we need not convert the decimal
+ point */
+ }
+ }
+
+ if (decimal_point_pos) {
+ char *copy, *c;
+ /* Create a copy of the input, with the '.' converted to the
+ locale-specific decimal point */
+ copy = (char *)malloc(end - digits_pos +
+ 1 + decimal_point_len);
+ if (copy == NULL) {
+ *endptr = (char *)nptr;
+ errno = ENOMEM;
+ return val;
+ }
+
+ c = copy;
+ memcpy(c, digits_pos, decimal_point_pos - digits_pos);
+ c += decimal_point_pos - digits_pos;
+ memcpy(c, decimal_point, decimal_point_len);
+ c += decimal_point_len;
+ memcpy(c, decimal_point_pos + 1,
+ end - (decimal_point_pos + 1));
+ c += end - (decimal_point_pos + 1);
+ *c = 0;
+
+ val = strtod(copy, &fail_pos);
+
+ if (fail_pos)
+ {
+ if (fail_pos > decimal_point_pos)
+ fail_pos = (char *)digits_pos +
+ (fail_pos - copy) -
+ (decimal_point_len - 1);
+ else
+ fail_pos = (char *)digits_pos +
+ (fail_pos - copy);
+ }
+
+ free(copy);
+
+ }
+ else {
+ val = strtod(digits_pos, &fail_pos);
+ }
+
+ if (fail_pos == digits_pos)
+ goto invalid_string;
+
+ if (negate && fail_pos != nptr)
+ val = -val;
+ *endptr = fail_pos;
+
+ return val;
+
+ invalid_string:
+ *endptr = (char*)nptr;
+ errno = EINVAL;
+ return -1.0;
+}
+
+
+float strtof_c(const char *nptr, char **endptr)
+{
+ return (float) strtod_c(nptr, endptr);
+}
+
+#endif
diff --git a/src/support/strtod.h b/src/support/strtod.h
new file mode 100644
index 0000000000000..50dda8ecf8f39
--- /dev/null
+++ b/src/support/strtod.h
@@ -0,0 +1,8 @@
+#ifndef STRTOD_H
+#define STRTOD_H
+
+double strtod_c(const char *nptr, char **endptr);
+float strtof_c(const char *nptr, char **endptr);
+
+#endif
+
diff --git a/test/core.jl b/test/core.jl
index 607fbfc2b19df..54476f617aec5 100644
--- a/test/core.jl
+++ b/test/core.jl
@@ -1454,3 +1454,8 @@ x6074 = 6074
test5536(a::Union(Real, AbstractArray)...) = "Splatting"
test5536(a::Union(Real, AbstractArray)) = "Non-splatting"
@test test5536(5) == "Non-splatting"
+
+# multiline comments (#6139 and others raised in #6128)
+@test 3 == include_string("1 + #=# 2") == include_string("1 + #==# 2") == include_string("1 + #===# 2") == include_string("1 + #= #= blah =# =# 2") == include_string("1 + #= #= #= nested =# =# =# 2")
+@test_throws include_string("#=")
+@test_throws include_string("#= #= #= =# =# =")
diff --git a/test/math.jl b/test/math.jl
index e6c20a5bc463b..d276da7139fd5 100644
--- a/test/math.jl
+++ b/test/math.jl
@@ -5,14 +5,31 @@
@test exponent(12.8) == 3
# degree-based trig functions
-for x = -400:40:400
- @test_approx_eq_eps sind(x) sin(pi/180*x) eps(pi/180*x)
- @test_approx_eq_eps cosd(x) cos(pi/180*x) eps(pi/180*x)
+for T = (Float32,Float64)
+ 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)
+ end
+
+ 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)
+ end
end
-for x = -3:0.3:3
- @test_approx_eq_eps sinpi(x) sin(pi*x) eps(pi*x)
- @test_approx_eq_eps cospi(x) cos(pi*x) eps(pi*x)
+# check type stability
+for T = (Float32,Float64,BigFloat)
+ for f = (sind,cosd,sinpi,cospi)
+ @test Base.return_types(f,(T,)) == [T]
+ end
end
diff --git a/test/numbers.jl b/test/numbers.jl
index 36e077d6950da..ab2cf8a5d00dc 100644
--- a/test/numbers.jl
+++ b/test/numbers.jl
@@ -1751,3 +1751,15 @@ end
# issue #5881
@test bits(true) == "00000001"
@test bits(false) == "00000000"
+
+# edge cases of intrinsics
+let g() = sqrt(-1.0)
+ @test_throws sqrt(-1.0)
+end
+@test sqrt(NaN) === NaN
+let g() = sqrt(NaN)
+ @test g() === NaN
+end
+let g(x) = sqrt(x)
+ @test g(NaN) === NaN
+end
diff --git a/ui/repl.c b/ui/repl.c
index 407b6a82a1898..d3c31272f13b5 100644
--- a/ui/repl.c
+++ b/ui/repl.c
@@ -42,7 +42,9 @@ static const char *opts =
" -F Load ~/.juliarc.jl, then handle remaining inputs\n"
" --color=yes|no Enable or disable color text\n\n"
- " --code-coverage Count executions of source lines\n";
+ " --code-coverage Count executions of source lines\n"
+ " --check-bounds=yes|no Emit bounds checks always or never (ignoring declarations)\n"
+ " --int-literals=32|64 Select integer literal size independent of platform\n";
void parse_opts(int *argcp, char ***argvp)
{
@@ -55,6 +57,8 @@ void parse_opts(int *argcp, char ***argvp)
{ "help", no_argument, 0, 'h' },
{ "sysimage", required_argument, 0, 'J' },
{ "code-coverage", no_argument, &codecov, 1 },
+ { "check-bounds", required_argument, 0, 300 },
+ { "int-literals", required_argument, 0, 301 },
{ 0, 0, 0, 0 }
};
int c;
@@ -90,6 +94,22 @@ void parse_opts(int *argcp, char ***argvp)
case 'h':
printf("%s%s", usage, opts);
exit(0);
+ case 300:
+ if (!strcmp(optarg,"yes"))
+ jl_compileropts.check_bounds = JL_COMPILEROPT_CHECK_BOUNDS_ON;
+ else if (!strcmp(optarg,"no"))
+ jl_compileropts.check_bounds = JL_COMPILEROPT_CHECK_BOUNDS_OFF;
+ break;
+ case 301:
+ if (!strcmp(optarg,"32"))
+ jl_compileropts.int_literals = 32;
+ else if (!strcmp(optarg,"64"))
+ jl_compileropts.int_literals = 64;
+ else {
+ ios_printf(ios_stderr, "julia: invalid integer literal size (%s)\n", optarg);
+ exit(1);
+ }
+ break;
default:
ios_printf(ios_stderr, "julia: unhandled option -- %c\n", c);
ios_printf(ios_stderr, "This is a bug, please report it.\n");