├── REQUIRE ├── .gitignore ├── .travis.yml ├── LICENSE.md ├── src ├── nullable.jl ├── timer.jl ├── ngenerate.jl ├── linspace.jl └── Compat.jl ├── appveyor.yml ├── README.md └── test └── runtests.jl /REQUIRE: -------------------------------------------------------------------------------- 1 | julia 0.4 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.jl.cov 2 | *.jl.mem 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: julia 2 | os: 3 | - linux 4 | - osx 5 | julia: 6 | - 0.4 7 | - 0.5 8 | - nightly 9 | notifications: 10 | email: false 11 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The Compatibility.jl package is licensed under the MIT "Expat" License: 2 | 3 | > Copyright (c) 2014: Stefan Karpinski. 4 | > 5 | > Permission is hereby granted, free of charge, to any person obtaining 6 | > a copy of this software and associated documentation files (the 7 | > "Software"), to deal in the Software without restriction, including 8 | > without limitation the rights to use, copy, modify, merge, publish, 9 | > distribute, sublicense, and/or sell copies of the Software, and to 10 | > permit persons to whom the Software is furnished to do so, subject to 11 | > the following conditions: 12 | > 13 | > The above copyright notice and this permission notice shall be 14 | > included in all copies or substantial portions of the Software. 15 | > 16 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | > EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | > MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | > IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | > CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | > TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | > SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /src/nullable.jl: -------------------------------------------------------------------------------- 1 | import Base: eltype, convert, get, isequal, ==, hash, show 2 | export Nullable, NullException, isnull 3 | 4 | immutable Nullable{T} 5 | isnull::Bool 6 | value::T 7 | 8 | Nullable() = new(true) 9 | Nullable(value::T) = new(false, value) 10 | end 11 | 12 | immutable NullException <: Exception 13 | end 14 | 15 | Nullable{T}(value::T) = Nullable{T}(value) 16 | Nullable() = Nullable{Union()}() 17 | 18 | eltype{T}(::Type{Nullable{T}}) = T 19 | 20 | function convert{T}(::Type{Nullable{T}}, x::Nullable) 21 | return isnull(x) ? Nullable{T}() : Nullable{T}(convert(T, get(x))) 22 | end 23 | 24 | convert{T}(::Type{Nullable{T}}, x::T) = Nullable{T}(x) 25 | 26 | @compat convert{T}(::Type{Nullable{T}}, ::Void) = Nullable{T}() 27 | @compat convert( ::Type{Nullable }, ::Void) = Nullable{Union()}() 28 | 29 | function show{T}(io::IO, x::Nullable{T}) 30 | if x.isnull 31 | @printf(io, "Nullable{%s}()", repr(T)) 32 | else 33 | @printf(io, "Nullable(%s)", repr(x.value)) 34 | end 35 | end 36 | 37 | get(x::Nullable) = x.isnull ? throw(NullException()) : x.value 38 | 39 | get{T}(x::Nullable{T}, y) = x.isnull ? convert(T, y) : x.value 40 | 41 | isnull(x::Nullable) = x.isnull 42 | 43 | function isequal(x::Nullable, y::Nullable) 44 | if x.isnull && y.isnull 45 | return true 46 | elseif x.isnull || y.isnull 47 | return false 48 | else 49 | return isequal(x.value, y.value) 50 | end 51 | end 52 | 53 | ==(x::Nullable, y::Nullable) = throw(NullException()) 54 | 55 | const nullablehash_seed = UInt === UInt64 ? 0x932e0143e51d0171 : 0xe51d0171 56 | 57 | function hash(x::Nullable, h::UInt) 58 | if x.isnull 59 | return h + nullablehash_seed 60 | else 61 | return hash(x.value, h + nullablehash_seed) 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - JULIAVERSION: "julialang/bin/winnt/x86/0.4/julia-0.4-latest-win32.exe" 4 | - JULIAVERSION: "julialang/bin/winnt/x64/0.4/julia-0.4-latest-win64.exe" 5 | - JULIAVERSION: "julialang/bin/winnt/x86/0.5/julia-0.5-latest-win32.exe" 6 | - JULIAVERSION: "julialang/bin/winnt/x64/0.5/julia-0.5-latest-win64.exe" 7 | - JULIAVERSION: "julianightlies/bin/winnt/x86/julia-latest-win32.exe" 8 | - JULIAVERSION: "julianightlies/bin/winnt/x64/julia-latest-win64.exe" 9 | 10 | branches: 11 | only: 12 | - master 13 | - /release-.*/ 14 | 15 | notifications: 16 | - provider: Email 17 | on_build_success: false 18 | on_build_failure: false 19 | on_build_status_changed: false 20 | 21 | install: 22 | # if there's a newer build queued for the same PR, cancel this one 23 | - ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod ` 24 | https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | ` 25 | Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { ` 26 | throw "There are newer queued builds for this pull request, failing early." } 27 | # Download most recent Julia Windows binary 28 | - ps: (new-object net.webclient).DownloadFile( 29 | $("http://s3.amazonaws.com/"+$env:JULIAVERSION), 30 | "C:\projects\julia-binary.exe") 31 | # Run installer silently, output to C:\projects\julia 32 | - C:\projects\julia-binary.exe /S /D=C:\projects\julia 33 | 34 | build_script: 35 | # Need to convert from shallow to complete for Pkg.clone to work 36 | - IF EXIST .git\shallow (git fetch --unshallow) 37 | - C:\projects\julia\bin\julia -F -e "versioninfo(); 38 | Pkg.clone(pwd(), \"Compat\"); Pkg.build(\"Compat\")" 39 | 40 | test_script: 41 | - C:\projects\julia\bin\julia --check-bounds=yes -e "Pkg.test(\"Compat\")" 42 | -------------------------------------------------------------------------------- /src/timer.jl: -------------------------------------------------------------------------------- 1 | # This file is a part of Julia. License is MIT: http://julialang.org/license 2 | 3 | ########################################## 4 | # Timer2 5 | ########################################## 6 | # 7 | # This is a backported replacement for the new Timer code introduced in v0.4 8 | # 9 | 10 | type Timer2 11 | handle::Ptr{Void} 12 | cond::Condition 13 | isopen::Bool 14 | 15 | function Timer2(timeout::Real, repeat::Real=0.0) 16 | timeout ≥ 0 || throw(ArgumentError("timer cannot have negative timeout of $timeout seconds")) 17 | repeat ≥ 0 || throw(ArgumentError("timer cannot repeat $repeat times")) 18 | 19 | this = new(Libc.malloc(Base._sizeof_uv_timer), Condition(), true) 20 | err = ccall(:uv_timer_init,Cint,(Ptr{Void},Ptr{Void}),Base.eventloop(),this.handle) 21 | if err != 0 22 | #TODO: this codepath is currently not tested 23 | Libc.free(this.handle) 24 | this.handle = C_NULL 25 | throw(UVError("uv_make_timer",err)) 26 | end 27 | 28 | Base.associate_julia_struct(this.handle, this) 29 | Base.preserve_handle(this) 30 | 31 | ccall(:uv_update_time, Void, (Ptr{Void},), Base.eventloop()) 32 | @compat ccall(:uv_timer_start, Cint, (Ptr{Void},Ptr{Void},UInt64,UInt64), 33 | this.handle, Base.uv_jl_asynccb::Ptr{Void}, 34 | UInt64(round(timeout*1000))+1, UInt64(round(repeat*1000))) 35 | this 36 | end 37 | end 38 | 39 | Base.wait(t::Timer2) = wait(t.cond) 40 | 41 | Base.isopen(t::Timer2) = t.isopen 42 | 43 | function Base.close(t::Timer2) 44 | if t.handle != C_NULL 45 | t.isopen = false 46 | ccall(:uv_timer_stop, Cint, (Ptr{Void},), t.handle) 47 | ccall(:jl_close_uv, Void, (Ptr{Void},), t.handle) 48 | end 49 | end 50 | 51 | function Base._uv_hook_close(t::Timer2) 52 | Base.unpreserve_handle(t) 53 | Base.disassociate_julia_struct(t) 54 | t.handle = C_NULL 55 | nothing 56 | end 57 | 58 | function Base._uv_hook_asynccb(t::Timer2) 59 | @compat if ccall(:uv_timer_get_repeat, UInt64, (Ptr{Void},), t.handle) == 0 60 | # timer is stopped now 61 | close(t) 62 | end 63 | notify(t.cond) 64 | nothing 65 | end 66 | 67 | # timer with repeated callback 68 | function Base.Timer(cb::Function, timeout::Real, repeat::Real=0.0) 69 | t = Timer2(timeout, repeat) 70 | @schedule begin 71 | while isopen(t) 72 | wait(t) 73 | cb(t) 74 | end 75 | end 76 | t 77 | end 78 | 79 | Base.Timer(timeout::Real, repeat::Real=0.0) = Timer2(timeout, repeat) 80 | -------------------------------------------------------------------------------- /src/ngenerate.jl: -------------------------------------------------------------------------------- 1 | module CompatCartesian 2 | 3 | export @ngenerate, @nsplat 4 | 5 | macro ngenerate(itersym, returntypeexpr, funcexpr) 6 | if isa(funcexpr, Expr) && funcexpr.head == :macrocall && funcexpr.args[1] == Symbol("@inline") 7 | funcexpr = Base._inline(funcexpr.args[2]) 8 | end 9 | isfuncexpr(funcexpr) || error("Requires a function expression") 10 | esc(_ngenerate(itersym, funcexpr)) 11 | end 12 | 13 | function _ngenerate(itersym::Symbol, funcexpr::Expr) 14 | prototype = funcexpr.args[1] 15 | body = funcexpr.args[2] 16 | varname, T = get_splatinfo(prototype, itersym) 17 | ex = Expr(:$, itersym) 18 | sreplace!(body, itersym, ex) 19 | if !isempty(varname) 20 | prototype, body = _nsplat(prototype, body, varname, T, itersym) 21 | else 22 | body = Expr(:quote, body) 23 | end 24 | Expr(:stagedfunction, prototype, body) 25 | end 26 | 27 | macro nsplat(itersym, args...) 28 | if length(args) == 1 29 | funcexpr = args[1] 30 | elseif length(args) == 2 31 | funcexpr = args[2] 32 | else 33 | error("Wrong number of arguments") 34 | end 35 | if isa(funcexpr, Expr) && funcexpr.head == :macrocall && funcexpr.args[1] == Symbol("@inline") 36 | funcexpr = Base._inline(funcexpr.args[2]) 37 | end 38 | isfuncexpr(funcexpr) || error("Second argument must be a function expression") 39 | prototype = funcexpr.args[1] 40 | body = funcexpr.args[2] 41 | varname, T = get_splatinfo(prototype, itersym) 42 | isempty(varname) && error("Last argument must be a splat") 43 | prototype, body = _nsplat(prototype, body, varname, T, itersym) 44 | esc(Expr(:stagedfunction, prototype, body)) 45 | end 46 | 47 | function _nsplat(prototype, body, varname, T, itersym) 48 | varsym = Symbol(varname) 49 | prototype.args[end] = Expr(:..., Expr(:(::), varsym, T)) # :($varsym::$T...) 50 | varquot = Expr(:quote, varsym) 51 | bodyquot = Expr(:quote, body) 52 | newbody = quote 53 | $itersym = length($varsym) 54 | quote 55 | Base.Cartesian.@nexprs $($itersym) (d->$($(Expr(:quote, Symbol(varsym, "_d")))) = $($varquot)[d]) 56 | $(Compat.CompatCartesian.resolvesplats!($bodyquot, $varquot, $itersym)) 57 | end 58 | end 59 | prototype, newbody 60 | end 61 | 62 | # If using the syntax that will need "desplatting", 63 | # myfunction(A::AbstractArray, I::NTuple{N, Int}...) 64 | # return the variable name (as a string) and type 65 | function get_splatinfo(ex::Expr, itersym::Symbol) 66 | if ex.head == :call 67 | a = ex.args[end] 68 | if isa(a, Expr) && a.head == :... && length(a.args) == 1 69 | b = a.args[1] 70 | if isa(b, Expr) && b.head == :(::) 71 | varname = string(b.args[1]) 72 | c = b.args[2] 73 | if isa(c, Expr) && c.head == :curly && c.args[1] == :NTuple && c.args[2] == itersym 74 | T = c.args[3] 75 | return varname, T 76 | end 77 | end 78 | end 79 | end 80 | "", Void 81 | end 82 | 83 | resolvesplats!(arg, varname, N) = arg 84 | function resolvesplats!(ex::Expr, varname, N::Int) 85 | if ex.head == :call 86 | for i = 2:length(ex.args)-1 87 | resolvesplats!(ex.args[i], varname, N) 88 | end 89 | a = ex.args[end] 90 | if isa(a, Expr) && a.head == :... && a.args[1] == Symbol(varname) 91 | ex.args[end] = :($varname[1]) # Expr(:ref, varname, 1) 92 | for i = 2:N 93 | push!(ex.args, :($varname[$i])) # Expr(:ref, varname, i)) 94 | end 95 | else 96 | resolvesplats!(a, varname, N) 97 | end 98 | else 99 | for i = 1:length(ex.args) 100 | resolvesplats!(ex.args[i], varname, N) 101 | end 102 | end 103 | ex 104 | end 105 | 106 | isfuncexpr(ex::Expr) = 107 | ex.head == :function || (ex.head == :(=) && typeof(ex.args[1]) == Expr && ex.args[1].head == :call) 108 | isfuncexpr(arg) = false 109 | 110 | sreplace!(arg, sym, val) = arg 111 | function sreplace!(ex::Expr, sym, val) 112 | for i = 1:length(ex.args) 113 | ex.args[i] = sreplace!(ex.args[i], sym, val) 114 | end 115 | ex 116 | end 117 | sreplace!(s::Symbol, sym, val) = s == sym ? val : s 118 | 119 | end 120 | -------------------------------------------------------------------------------- /src/linspace.jl: -------------------------------------------------------------------------------- 1 | module LazyLinSpace 2 | 3 | export linspace 4 | import Base: map, float, big, show, isempty, step, length, first, last, start, next, done, 5 | getindex, unsafe_getindex, promote_rule, convert, reverse, eltype 6 | import Base.Operators: +, -, .+, .-, *, .*, ==, ./ 7 | 8 | import ..AbstractFloat 9 | import ..@compat 10 | 11 | ## linspace and logspace 12 | 13 | immutable LinSpace{T<:AbstractFloat} <: Range{T} 14 | start::T 15 | stop::T 16 | len::T 17 | divisor::T 18 | end 19 | 20 | # float rationalization helper 21 | function rat(x) 22 | y = x 23 | a = d = 1 24 | b = c = 0 25 | m = maxintfloat(Float32) 26 | while abs(y) <= m 27 | f = trunc(Int,y) 28 | y -= f 29 | a, c = f*a + c, a 30 | b, d = f*b + d, b 31 | max(abs(a),abs(b)) <= convert(Int,m) || return c, d 32 | oftype(x,a)/oftype(x,b) == x && break 33 | y = inv(y) 34 | end 35 | return a, b 36 | end 37 | 38 | function linspace{T<:AbstractFloat}(start::T, stop::T, len::T) 39 | len == round(len) || throw(InexactError()) 40 | 0 <= len || error("linspace($start, $stop, $len): negative length") 41 | if len == 0 42 | n = convert(T, 2) 43 | if isinf(n*start) || isinf(n*stop) 44 | start /= n; stop /= n; n = one(T) 45 | end 46 | return LinSpace(-start, -stop, -one(T), n) 47 | end 48 | if len == 1 49 | start == stop || error("linspace($start, $stop, $len): endpoints differ") 50 | return LinSpace(-start, -start, zero(T), one(T)) 51 | end 52 | n = convert(T, len - 1) 53 | len - n == 1 || error("linspace($start, $stop, $len): too long for $T") 54 | a0, b = rat(start) 55 | a = convert(T,a0) 56 | if a/convert(T,b) == start 57 | c0, d = rat(stop) 58 | c = convert(T,c0) 59 | if c/convert(T,d) == stop 60 | e = lcm(b,d) 61 | a *= div(e,b) 62 | c *= div(e,d) 63 | s = convert(T,n*e) 64 | if isinf(a*n) || isinf(c*n) 65 | s, p = frexp(s) 66 | p2 = oftype(s,2)^p 67 | a /= p2; c /= p2 68 | end 69 | if a*n/s == start && c*n/s == stop 70 | return LinSpace(a, c, len, s) 71 | end 72 | end 73 | end 74 | a, c, s = start, stop, n 75 | if isinf(a*n) || isinf(c*n) 76 | s, p = frexp(s) 77 | p2 = oftype(s,2)^p 78 | a /= p2; c /= p2 79 | end 80 | if a*n/s == start && c*n/s == stop 81 | return LinSpace(a, c, len, s) 82 | end 83 | return LinSpace(start, stop, len, n) 84 | end 85 | function linspace{T<:AbstractFloat}(start::T, stop::T, len::Real) 86 | T_len = convert(T, len) 87 | T_len == len || throw(InexactError()) 88 | linspace(start, stop, T_len) 89 | end 90 | linspace(start::Real, stop::Real, len::Real=50) = 91 | linspace(promote(AbstractFloat(start), AbstractFloat(stop))..., len) 92 | 93 | function show(io::IO, r::LinSpace) 94 | print(io, "linspace(") 95 | show(io, first(r)) 96 | print(io, ',') 97 | show(io, last(r)) 98 | print(io, ',') 99 | show(io, length(r)) 100 | print(io, ')') 101 | end 102 | 103 | logspace(start::Real, stop::Real, n::Integer=50) = 10.^linspace(start, stop, n) 104 | 105 | eltype{T}(r::LinSpace{T}) = T 106 | isempty(r::LinSpace) = length(r) == 0 107 | step{T}(r::LinSpace{T}) = ifelse(r.len <= 0, convert(T,NaN), (r.stop-r.start)/r.divisor) 108 | length(r::LinSpace) = convert(Integer,r.len + signbit(r.len - 1)) 109 | first{T}(r::LinSpace{T}) = convert(T, (r.len-1)*r.start/r.divisor) 110 | last{T}(r::LinSpace{T}) = convert(T, (r.len-1)*r.stop/r.divisor) 111 | start(r::LinSpace) = 1 112 | done(r::LinSpace, i::Int) = length(r) < i 113 | next{T}(r::LinSpace{T}, i::Int) = 114 | (convert(T, ((r.len-i)*r.start + (i-1)*r.stop)/r.divisor), i+1) 115 | 116 | getindex{T}(r::LinSpace{T}, i::Int) = (checkbounds(r, i); unsafe_getindex(r, i)) 117 | getindex{T}(r::LinSpace{T}, i::Integer) = (checkbounds(r, i); unsafe_getindex(r, convert(Int,i))) 118 | unsafe_getindex{T}(r::LinSpace{T}, i::Int) = convert(T, ((r.len-i)*r.start + (i-1)*r.stop)/r.divisor) 119 | 120 | getindex(r::LinSpace, s::OrdinalRange) = (checkbounds(r, s); unsafe_getindex(r, s)) 121 | function unsafe_getindex{T}(r::LinSpace{T}, s::OrdinalRange) 122 | sl::T = length(s) 123 | ifirst = first(s) 124 | ilast = last(s) 125 | vfirst::T = ((r.len - ifirst) * r.start + (ifirst - 1) * r.stop) / r.divisor 126 | vlast::T = ((r.len - ilast) * r.start + (ilast - 1) * r.stop) / r.divisor 127 | return linspace(vfirst, vlast, sl) 128 | end 129 | 130 | function map{T<:AbstractFloat}(::Type{T}, r::LinSpace) 131 | new_len = T(r.len) 132 | new_len == r.len || error("$r: too long for $T") 133 | LinSpace(T(r.start), T(r.stop), new_len, T(r.divisor)) 134 | end 135 | 136 | for fn in (:float,:big) 137 | @eval function $fn(r::LinSpace) 138 | new_len = $fn(r.len) 139 | new_len == r.len || error(string(r, ": too long for ", $fn)) 140 | LinSpace($fn(r.start), $fn(r.stop), new_len, $fn(r.divisor)) 141 | end 142 | end 143 | 144 | for fn in (:+, :-) 145 | @eval function $fn{T<:AbstractFloat}(r1::LinSpace{T}, r2::LinSpace{T}) 146 | len = r1.len 147 | (len == r2.len || 148 | throw(DimensionMismatch("argument dimensions must match"))) 149 | divisor1, divisor2 = r1.divisor, r2.divisor 150 | if divisor1 == divisor2 151 | LinSpace{T}($fn(r1.start, r2.start), $fn(r1.stop, r2.stop), 152 | len, divisor1) 153 | else 154 | linspace(convert(T, $fn(first(r1), first(r2))), 155 | convert(T, $fn(last(r1), last(r2))), len) 156 | end 157 | end 158 | 159 | @eval $fn(r1::(@compat Union{FloatRange, OrdinalRange, LinSpace}), 160 | r2::(@compat Union{FloatRange, OrdinalRange, LinSpace})) = 161 | $fn(promote(r1, r2)...) 162 | end 163 | 164 | (==){T<:LinSpace}(r::T, s::T) = (first(r) == first(s)) & (length(r) == length(s)) & (last(r) == last(s)) 165 | -(r::LinSpace) = LinSpace(-r.start, -r.stop, r.len, r.divisor) 166 | 167 | function .+{T}(x::Real, r::LinSpace{T}) 168 | x2 = x * r.divisor / (r.len - 1) 169 | LinSpace(x2 + r.start, x2 + r.stop, r.len, r.divisor) 170 | end 171 | 172 | function .-(x::Real, r::LinSpace) 173 | x2 = x * r.divisor / (r.len - 1) 174 | LinSpace(x2 - r.start, x2 - r.stop, r.len, r.divisor) 175 | end 176 | 177 | function .-(r::LinSpace, x::Real) 178 | x2 = x * r.divisor / (r.len - 1) 179 | LinSpace(r.start - x2, r.stop - x2, r.len, r.divisor) 180 | end 181 | 182 | .*(x::Real, r::LinSpace) = LinSpace(x * r.start, x * r.stop, r.len, r.divisor) 183 | .*(r::LinSpace, x::Real) = x .* r 184 | ./(r::LinSpace, x::Real) = LinSpace(r.start / x, r.stop / x, r.len, r.divisor) 185 | 186 | promote_rule{T1,T2}(::Type{LinSpace{T1}},::Type{LinSpace{T2}}) = 187 | LinSpace{promote_type(T1,T2)} 188 | convert{T}(::Type{LinSpace{T}}, r::LinSpace{T}) = r 189 | convert{T}(::Type{LinSpace{T}}, r::LinSpace) = 190 | LinSpace{T}(r.start, r.stop, r.len, r.divisor) 191 | 192 | promote_rule{F,OR<:OrdinalRange}(::Type{LinSpace{F}}, ::Type{OR}) = 193 | LinSpace{promote_type(F,eltype(OR))} 194 | convert{T}(::Type{LinSpace{T}}, r::OrdinalRange) = 195 | linspace(convert(T, first(r)), convert(T, last(r)), convert(T, length(r))) 196 | convert{T}(::Type{LinSpace}, r::OrdinalRange{T}) = 197 | convert(LinSpace{typeof(float(first(r)))}, r) 198 | 199 | # Promote FloatRange to LinSpace 200 | promote_rule{F,OR<:FloatRange}(::Type{LinSpace{F}}, ::Type{OR}) = 201 | LinSpace{promote_type(F,eltype(OR))} 202 | convert{T}(::Type{LinSpace{T}}, r::FloatRange) = 203 | linspace(convert(T, first(r)), convert(T, last(r)), convert(T, length(r))) 204 | convert{T}(::Type{LinSpace}, r::FloatRange{T}) = 205 | convert(LinSpace{T}, r) 206 | 207 | reverse(r::LinSpace) = LinSpace(r.stop, r.start, r.len, r.divisor) 208 | 209 | end 210 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Compat Package for Julia 2 | 3 | [![Build Status](https://travis-ci.org/JuliaLang/Compat.jl.svg?branch=master)](https://travis-ci.org/JuliaLang/Compat.jl) 4 | [![Build status](https://ci.appveyor.com/api/projects/status/github/JuliaLang/Compat.jl?branch=master)](https://ci.appveyor.com/project/quinnj/compat-jl/branch/master) 5 | 6 | [![Compat](http://pkg.julialang.org/badges/Compat_0.3.svg)](http://pkg.julialang.org/?pkg=Compat&ver=0.3) 7 | [![Compat](http://pkg.julialang.org/badges/Compat_0.4.svg)](http://pkg.julialang.org/?pkg=Compat&ver=0.4) 8 | [![Compat](http://pkg.julialang.org/badges/Compat_0.5.svg)](http://pkg.julialang.org/?pkg=Compat&ver=0.5) 9 | [![Compat](http://pkg.julialang.org/badges/Compat_0.6.svg)](http://pkg.julialang.org/?pkg=Compat&ver=0.6) 10 | 11 | The **Compat** package is designed to ease interoperability between 12 | older and newer versions of the [Julia 13 | language](http://julialang.org/). In particular, in cases where it is 14 | impossible to write code that works with both the latest Julia 15 | `master` branch and older Julia versions, or impossible to write code 16 | that doesn't generate a deprecation warning in some Julia version, the 17 | Compat package provides a macro that lets you use the *latest syntax* 18 | in a backwards-compatible way. 19 | 20 | This is primarily intended for use by other [Julia 21 | packages](http://docs.julialang.org/en/latest/manual/packages/), where 22 | it is important to maintain cross-version compatibility. 23 | 24 | ## Usage 25 | 26 | To use Compat in your Julia package, add a line `Compat` to the 27 | `REQUIRE` file in your package directory. Then, in your package, 28 | shortly after the `module` statement include lines like these: 29 | 30 | ``` 31 | using Compat 32 | import Compat.String 33 | ``` 34 | 35 | and then as needed add 36 | 37 | ``` 38 | @compat ...compat syntax... 39 | ``` 40 | 41 | wherever you want to use syntax that differs in the latest Julia 42 | `master` (the development version of Julia). The `compat syntax` is usually 43 | the syntax on Julia `master`. However, in a few cases where this is not possible, 44 | a slightly different syntax might be used. 45 | Please check the list below for the specific syntax you need. 46 | 47 | ## Supported syntax 48 | 49 | Currently, the `@compat` macro supports the following syntaxes: 50 | 51 | * `@compat foo.:bar` — `foo.(:bar)` in 0.4 ([#15032]) 52 | 53 | * `@compat f.(args...)` — `broadcast(f, args...)` in 0.4 ([#15032]) 54 | 55 | * `@compat (a::B{T}){T}(c) = d` — the Julia 0.5-style call overload 56 | 57 | * `@compat(get(io, s, false))`, with `s` equal to `:limit`, `:compact` or `:multiline`, to detect the corresponding print settings (performs useful work only on Julia 0.5, defaults to `false` otherwise) 58 | 59 | * `@compat import Base.show` and `@compat function show(args...)` for handling the deprecation of `writemime` in Julia 0.5 ([#16563]). See https://github.com/JuliaLang/Compat.jl/pull/219. 60 | 61 | * `@compat @boundscheck checkbounds(...)` rewrites to unconditionally call `checkbounds(...)` in 0.4. The 0.4-style two-argument form of `@boundscheck` is left unchanged. 62 | 63 | * `@compat Nullable(value, hasvalue)` to handle the switch from the `Nullable` `:isnull` field to `:hasvalue` field ([#18510]) 64 | 65 | * `@compat x .= y` converts to an in-place assignment to `x` (via `broadcast!`) ([#17510]). 66 | However, beware that `.=` in Julia 0.4 has the precedence of `==`, not of assignment `=`, so if the right-hand-side `y` 67 | includes expressions with lower precedence than `==` you should enclose it in parentheses `x .= (y)` to ensure the 68 | correct order of evaluation. 69 | 70 | ## Type Aliases 71 | 72 | * In 0.5, `ASCIIString` and `ByteString` were deprecated, and `UTF8String` was renamed to the (now concrete) type `String`. 73 | 74 | Compat provides unexported `Compat.UTF8String` and `Compat.ASCIIString` type aliases which are equivalent to the same types from Base on Julia 0.4, but to `String` on Julia 0.5. In most cases, using these types by calling `import Compat: UTF8String, ASCIIString` should be enough. Note that `Compat.ASCIIString` does **not** guarantee that the string only contains ASCII characters on Julia 0.5: call `isascii` to check if the string is pure ASCII if needed. 75 | 76 | Compat also provides an unexported `Compat.String` type which is equivalent to `ByteString` on Julia 0.4, and to `String` on Julia 0.5. This type should be used only in places where `ByteString` was used on Julia 0.4, i.e. where either `ASCIIString` or `UTF8String` should be accepted. It should **not** be used as the default type for variables or fields holding strings, as it introduces type-instability in Julia 0.4: use `Compat.UTF8String` or `Compat.ASCIIString` instead. 77 | 78 | * `bytestring` has been replaced in most cases with additional `String` construction methods; for 0.4 compatibility, the usage involves replacing `bytestring(args...)` with `Compat.String(args...)`. However, for converting a `Ptr{UInt8}` to a string, use the new `unsafe_string(...)` method to make a copy or `unsafe_wrap(String, ...)` to avoid a copy. 79 | 80 | ## New functions and methods 81 | 82 | * `foreach`, similar to `map` but when the return value is not needed ([#13744]) 83 | 84 | * `walkdir`, returns an iterator that walks the directory tree of a directory ([#13707]) 85 | 86 | * `allunique`, checks whether all elements in an iterable appear only once ([#15914]) 87 | 88 | * `Base.promote_eltype_op` is available as `Compat.promote_eltype_op` 89 | 90 | * [`normalize`](http://docs.julialang.org/en/latest/stdlib/linalg/?highlight=normalize#Base.normalize) and [`normalize!`](http://docs.julialang.org/en/latest/stdlib/linalg/?highlight=normalize#Base.normalize!), normalizes a vector with respect to the p-norm ([#13681]) 91 | 92 | * `redirect_stdout`, `redirect_stderr`, and `redirect_stdin` take an optional function as a first argument, `redirect_std*(f, stream)`, so that one may use `do` block syntax (as first available for Julia 0.6) 93 | 94 | * `unsafe_get` returns the `:value` field of a `Nullable` object without any null-check and has a generic fallback for non-`Nullable` argument ([#18484]) 95 | 96 | * `isnull` has a generic fallback for non-`Nullable` argument 97 | 98 | * `transcode` converts between UTF-xx string encodings in Julia 0.5 (as a lightweight 99 | alternative to the LegacyStrings package) ([#17323]) 100 | 101 | * `∘` (typically used infix as `f ∘ g`) for function composition can be used in 0.5 and earlier ([#17155]) 102 | 103 | * The method of `!` to negate functions (typically used as a unary operator, as in `!isinteger`) can be used in 0.5 and earlier ([#17155]). 104 | 105 | * `iszero(x)` efficiently checks whether `x == zero(x)` (including arrays) can be used in 0.5 and earlier ([#19950]). 106 | 107 | * `.&` and `.|` are short syntax for `broadcast(&, xs...)` and `broadcast(|, xs...)` (respectively) in Julia 0.6 (only supported on Julia 0.5 and above) [#17623](https://github.com/JuliaLang/julia/pull/17623) 108 | 109 | * `Compat.isapprox` with `nans` keyword argument [#20022](https://github.com/JuliaLang/julia/pull/20022) 110 | 111 | ## Renamed functions 112 | 113 | * `pointer_to_array` and `pointer_to_string` have been replaced with `unsafe_wrap(Array, ...)` and `unsafe_wrap(String, ...)` respectively 114 | 115 | * `bytestring(::Ptr, ...)` has been replaced with `unsafe_string` 116 | 117 | * `super` is now `supertype` ([#14338]) 118 | 119 | * `qr(A, pivot=b)` is now `qr(A, Val{b})`, likewise for `qrfact` and `qrfact!` 120 | 121 | * `readall` and `readbytes` are now `readstring` and `read` ([#14660]) 122 | 123 | * `get_bigfloat_precision` is now `precision(BigFloat)`, `set_precision` is `setprecision` and `with_bigfloat_precision` is now also `setprecision` 124 | ([#13232]) 125 | 126 | * `get_rounding` is now `rounding`. `set_rounding` and `with_rounding` are now `setrounding` ([#13232]) 127 | 128 | * `Base.tty_size` (which was not exported) is now `displaysize` in Julia 0.5 129 | 130 | * `Compat.LinAlg.checksquare` ([#14601]) 131 | 132 | * `issym` is now `issymmetric` ([#15192]) 133 | 134 | * `istext` is now `istextmime` ([#15708]) 135 | 136 | * `symbol` is now `Symbol` ([#16154]) 137 | 138 | * `write(::IO, ::Ptr, len)` is now `unsafe_write` ([#14766]) 139 | 140 | * `slice` is now `view` ([#16972]); do `import Compat.view` and then use `view` normally without the `@compat` macro 141 | 142 | * `fieldoffsets` has been deprecated in favor of `fieldoffset` ([#14777]) 143 | 144 | * `print_escaped` is now another method of `escape_string`, `print_unescaped` a method of `unescape_string`, and `print_joined` a method of `join` ([#16603]) 145 | 146 | * `writemime` has been merged into `show` ([#16563]). Note that to extend this function requires `@compat`; see the [Supported Syntax](#supported-syntax) section for more information 147 | 148 | * `$` is now `xor` or `⊻` ([#18977]) 149 | 150 | * `num` and `den` are now `numerator` and `denominator` ([#19246]) 151 | 152 | * `takebuf_array` is now a method of `take!`. `takebuf_string(io)` becomes `String(take!(io))` ([#19088]) 153 | 154 | ## New macros 155 | 156 | * `@static` has been added ([#16219]) 157 | 158 | * `@functorize` (not present in any Julia version) takes a function (or operator) and turns it into a functor object if one is available in the used Julia version. E.g. something like `mapreduce(Base.AbsFun(), Base.MulFun(), x)` can now be written as `mapreduce(@functorize(abs), @functorize(*), x)`, and `f(::Base.AbsFun())` as `f(::typeof(@functorize(abs)))`, to work across different Julia versions. `Func{1}` can be written as `supertype(typeof(@functorize(abs)))` (and so on for `Func{2}`), which will fall back to `Function` on Julia 0.5. 159 | 160 | * `Compat.@blasfunc` makes functionality of `Base.LinAlg.BLAS.@blasfunc` available on older Julia versions 161 | 162 | * `@__DIR__` has been added ([#18380]) 163 | 164 | * `@vectorize_1arg` and `@vectorize_2arg` are deprecated on Julia 0.6 in favor 165 | of the broadcast syntax ([#17302]). `Compat.@dep_vectorize_1arg` and 166 | `Compat.@dep_vectorize_2arg` are provided so that packages can still provide 167 | the deprecated definitions without causing a depwarn in the package itself 168 | before all the users are upgraded. 169 | 170 | Packages are expected to use this until all users of the deprecated 171 | vectorized function have migrated. These macros will be dropped when the 172 | support for `0.6` is dropped from `Compat`. 173 | 174 | ## Other changes 175 | 176 | * `remotecall`, `remotecall_fetch`, `remotecall_wait`, and `remote_do` have the function to be executed remotely as the first argument in Julia 0.5. Loading `Compat` defines the same methods in older versions of Julia ([#13338]) 177 | 178 | * `Base.FS` is now `Base.Filesystem` ([#12819]) 179 | Compat provides an unexported `Compat.Filesystem` module that is aliased to 180 | `Base.FS` on Julia 0.4 and `Base.Filesystem` on Julia 0.5. 181 | 182 | * `cov` and `cor` don't allow keyword arguments anymore. Loading Compat defines compatibility methods for the new API ([#13465]) 183 | 184 | * On versions of Julia that do not contain a Base.Threads module, Compat defines a Threads module containing a no-op `@threads` macro. 185 | 186 | * `Base.SingleAsyncWork` is now `Base.AsyncCondition` 187 | Compat provides an unexported `Compat.AsyncCondition` type that is aliased to 188 | `Base.SingleAsyncWork` on Julia 0.4 and `Base.AsyncCondition` on Julia 0.5. 189 | 190 | * `repeat` now accepts any `AbstractArray` [#14082](https://github.com/JuliaLang/julia/pull/14082): `Compat.repeat` supports this new API on Julia 0.4, and calls `Base.repeat` on 0.5. 191 | 192 | * `OS_NAME` is now `Sys.KERNEL`. OS information available as `is_apple`, `is_bsd`, `is_linux`, `is_unix`, and `is_windows` ([#16219]) 193 | 194 | * `cholfact`, `cholfact!`, and `chol` require that input is either `Hermitian`, `Symmetric` 195 | or that the elements are perfectly symmetric or Hermitian on 0.5. Compat now defines methods 196 | for `HermOrSym` such that using the new methods are backward compatible. 197 | 198 | * `Diagonal` and `*` methods support `SubArray`s even on 0.4. 199 | 200 | ## New types 201 | 202 | Currently, no new exported types are introduced by Compat. 203 | 204 | ## Developer tips 205 | 206 | One of the most important rules for `Compat.jl` is to avoid breaking user code 207 | whenever possible, especially on a released version. 208 | 209 | Although the syntax used in the most recent Julia version 210 | is the preferred compat syntax, there are cases where this shouldn't be used. 211 | Examples include when the new syntax already has a different meaning 212 | on previous versions of Julia, or when functions are removed from `Base` 213 | Julia and the alternative cannot be easily implemented on previous versions. 214 | In such cases, possible solutions are forcing the new feature to be used with 215 | qualified name in `Compat.jl` (e.g. use `Compat.`) or 216 | reimplementing the old features on a later Julia version. 217 | 218 | If you're adding additional compatibility code to this package, the [`contrib/commit-name.sh`](https://github.com/JuliaLang/julia/blob/master/contrib/commit-name.sh) script in the base Julia repository is useful for extracting the version number from a git commit SHA. For example, from the git repository of `julia`, run something like this: 219 | 220 | ```sh 221 | bash $ contrib/commit-name.sh a378b60fe483130d0d30206deb8ba662e93944da 222 | 0.5.0-dev+2023 223 | ``` 224 | 225 | This prints a version number corresponding to the specified commit of the form 226 | `X.Y.Z-aaa+NNNN`, and you can then test whether Julia 227 | is at least this version by `VERSION >= v"X.Y.Z-aaa+NNNN"`. 228 | 229 | ### Tagging the correct minimum version of Compat 230 | 231 | One of the most frequent problems package developers encounter is finding the right 232 | version of `Compat` to add to their REQUIRE. This is meant to be a guide on how to 233 | specify the right lower bound. 234 | 235 | * Find the appropriate fix needed for your package from the `Compat` README. Every 236 | function or feature added to `Compat` is documented in its README, so you are 237 | guaranteed to find it. 238 | 239 | * Navigate to the [blame page of the README](https://github.com/JuliaLang/Compat.jl/blame/master/README.md) 240 | by clicking on the README file on GitHub, and then clicking on the `blame` button 241 | which can be found in the top-right corner. 242 | 243 | * Now find your fix, and then find the corresponding commit ID of that fix on the 244 | left-hand side. Click on the commit ID. This navigates to a page which recorded 245 | that particular commit. 246 | 247 | * On the top pane, you should find the list of the tagged versions of Compat that 248 | includes this fix. Find the minimum version from there. 249 | 250 | * Now specify the correct minimum version for Compat in your REQUIRE file by 251 | `Compat ` 252 | 253 | [#12819]: https://github.com/JuliaLang/julia/issues/12819 254 | [#13232]: https://github.com/JuliaLang/julia/issues/13232 255 | [#13338]: https://github.com/JuliaLang/julia/issues/13338 256 | [#13465]: https://github.com/JuliaLang/julia/issues/13465 257 | [#13681]: https://github.com/JuliaLang/julia/issues/13681 258 | [#13707]: https://github.com/JuliaLang/julia/issues/13707 259 | [#13744]: https://github.com/JuliaLang/julia/issues/13744 260 | [#14082]: https://github.com/JuliaLang/julia/issues/14082 261 | [#14338]: https://github.com/JuliaLang/julia/issues/14338 262 | [#14601]: https://github.com/JuliaLang/julia/issues/14601 263 | [#14660]: https://github.com/JuliaLang/julia/issues/14660 264 | [#14766]: https://github.com/JuliaLang/julia/issues/14766 265 | [#14777]: https://github.com/JuliaLang/julia/issues/14777 266 | [#15032]: https://github.com/JuliaLang/julia/issues/15032 267 | [#15192]: https://github.com/JuliaLang/julia/issues/15192 268 | [#15708]: https://github.com/JuliaLang/julia/issues/15708 269 | [#15914]: https://github.com/JuliaLang/julia/issues/15914 270 | [#16154]: https://github.com/JuliaLang/julia/issues/16154 271 | [#16219]: https://github.com/JuliaLang/julia/issues/16219 272 | [#16563]: https://github.com/JuliaLang/julia/issues/16563 273 | [#16603]: https://github.com/JuliaLang/julia/issues/16603 274 | [#16972]: https://github.com/JuliaLang/julia/issues/16972 275 | [#17155]: https://github.com/JuliaLang/julia/issues/17155 276 | [#17302]: https://github.com/JuliaLang/julia/issues/17302 277 | [#17323]: https://github.com/JuliaLang/julia/issues/17323 278 | [#17510]: https://github.com/JuliaLang/julia/issues/17510 279 | [#18380]: https://github.com/JuliaLang/julia/issues/18380 280 | [#18484]: https://github.com/JuliaLang/julia/issues/18484 281 | [#18510]: https://github.com/JuliaLang/julia/issues/18510 282 | [#18977]: https://github.com/JuliaLang/julia/issues/18977 283 | [#19088]: https://github.com/JuliaLang/julia/issues/19088 284 | [#19246]: https://github.com/JuliaLang/julia/issues/19246 285 | [#19950]: https://github.com/JuliaLang/julia/issues/19950 286 | -------------------------------------------------------------------------------- /test/runtests.jl: -------------------------------------------------------------------------------- 1 | using Compat 2 | import Compat.String 3 | import Compat.view 4 | @compat import Base.show 5 | using Base.Test 6 | 7 | v = 1 8 | @test_throws AssertionError @assert(v < 1) 9 | 10 | type TestCustomShowType end 11 | @compat function show(io::IO, ::MIME"text/plain", ::TestCustomShowType) 12 | print(io, "MyTestCustomShowType") 13 | end 14 | myio = IOBuffer() 15 | display(TextDisplay(myio), MIME"text/plain"(), TestCustomShowType()) 16 | @test @compat String(myio) == "MyTestCustomShowType" 17 | 18 | type TestCustomShowType2 end 19 | @compat Base.show(io::IO, ::MIME"text/plain", ::TestCustomShowType2) = print(io, "MyTestCustomShowType2") 20 | myio = IOBuffer() 21 | display(TextDisplay(myio), MIME"text/plain"(), TestCustomShowType2()) 22 | @test @compat String(myio) == "MyTestCustomShowType2" 23 | 24 | type TestCustomShowType3 end 25 | @compat show(io::IO, ::TestCustomShowType3) = print(io, "2-Argument-show") 26 | myio = IOBuffer() 27 | display(TextDisplay(myio), TestCustomShowType3()) 28 | @test @compat String(myio) == "2-Argument-show" 29 | 30 | immutable ParameterizedShowType{T} 31 | _::T 32 | end 33 | myio = IOBuffer() 34 | @compat show{T}(io::IO, ::MIME"text/html", ::ParameterizedShowType{T}) = 35 | print(io, "::", T, "") 36 | @compat show(myio, MIME("text/html"), ParameterizedShowType(0.0)) 37 | @test @compat String(myio) == "::Float64" 38 | 39 | d = Dict{Int,Int}() 40 | d[1] = 1 41 | @test Compat.@Dict(1 => 1) == d 42 | @test Compat.@Dict(1 => v) == d 43 | 44 | @test typeof(@compat(Dict(1 => 1))) == Dict{Int,Int} 45 | @test @compat(Dict(1 => 1)) == d 46 | @test @compat(Dict(1 => v)) == d 47 | 48 | ad = Dict{Any,Any}() 49 | ad[1] = 1 50 | @test Compat.@AnyDict(1 => 1) == ad 51 | @test Compat.@AnyDict(1 => v) == ad 52 | 53 | @test typeof(@compat(Dict{Any,Any}(1 => 1))) == Dict{Any,Any} 54 | @test @compat(Dict{Any,Any}(1 => 1)) == ad 55 | @test @compat(Dict{Any,Any}(1 => v)) == ad 56 | 57 | td = Dict{Int,Float64}() 58 | td[1] = 1.0 59 | 60 | @test typeof(@compat(Dict{Int,Float64}(1 => 1))) == Dict{Int,Float64} 61 | @test @compat(Dict{Int,Float64}(1 => 1)) == td 62 | @test @compat(Dict{Int,Float64}(1 => v)) == td 63 | 64 | @test @compat(Dict()) == Dict() 65 | @test @compat(Dict{Any,Any}()) == Dict{Any,Any}() 66 | @test @compat(Dict([(1, 1)])) == d 67 | @test @compat(Dict(:Void => :Nothing)) == Dict([(:Void, :Nothing)]) 68 | 69 | d2 = Dict{Symbol,Dict{Symbol,Int}}() 70 | d2[:a] = Dict{Symbol,Int}() 71 | d2[:a][:b] = 1 72 | @test @compat(Dict(:a => Dict(:b => 1))) == d2 73 | 74 | d = Dict(zip([1, 2], [3, 4])) 75 | @test d == @compat Dict(1=>3, 2=>4) 76 | 77 | @compat function f() 78 | a = :a 79 | b = Dict(:b => 1) 80 | Dict(a => b) 81 | end 82 | @test f() == d2 83 | 84 | ns = length(d.slots) 85 | @test length(sizehint!(d, ns + 1).slots) > ns 86 | 87 | @test @compat split("a,b,,c", ',', limit=2) == ["a", "b,,c"] 88 | @test @compat split("a,b,,c", ',', limit=2,keep=true) == ["a", "b,,c"] 89 | @test @compat split("a,b,,c", ',', keep=false) == ["a", "b", "c"] 90 | @test @compat split("a,b,,c", ',', keep=true) == ["a", "b", "", "c"] 91 | 92 | @test @compat rsplit("a,b,,c", ',', limit=2) == ["a,b,", "c"] 93 | @test @compat rsplit("a,b,,c", ',', limit=2,keep=true) == ["a,b,", "c"] 94 | @test @compat rsplit("a,b,,c", ',', keep=false) == ["a", "b", "c"] 95 | @test @compat rsplit("a,b,,c", ',', keep=true) == ["a", "b", "", "c"] 96 | 97 | if VERSION < v"0.4.0-dev+1387" 98 | @test isdefined(Main, :AbstractString) 99 | end 100 | 101 | @test round(Int, 3//4) == 1 102 | @test round(Int, 1) == 1 103 | @test round(Int, 1.1) == 1 104 | @test round(Int, [1, 1]) == [1, 1] 105 | @test round(Int, [1.1, 1.1]) == [1, 1] 106 | @test round(Int, [1 1]) == [1 1] 107 | @test round(Int, [1.1 1.1]) == [1 1] 108 | @test round(Int, fill(1.1, 2, 3, 4)) == fill(1, 2, 3, 4) 109 | @test ceil(Int, 1) == 1 110 | @test ceil(Int, 1.1) == 2 111 | @test ceil(Int, [1, 1]) == [1, 1] 112 | @test ceil(Int, [1.1, 1.1]) == [2, 2] 113 | @test ceil(Int, [1 1]) == [1 1] 114 | @test ceil(Int, [1.1 1.1]) == [2 2] 115 | @test ceil(Int, fill(1.1, 2, 3, 4)) == fill(2, 2, 3, 4) 116 | @test floor(Int, 1) == 1 117 | @test floor(Int, 1.1) == 1 118 | @test floor(Int, [1, 1]) == [1, 1] 119 | @test floor(Int, [1.1, 1.1]) == [1, 1] 120 | @test floor(Int, [1 1]) == [1 1] 121 | @test floor(Int, [1.1 1.1]) == [1 1] 122 | @test floor(Int, fill(1.1, 2, 3, 4)) == fill(1, 2, 3, 4) 123 | @test trunc(Int, 1) == 1 124 | @test trunc(Int, 1.1) == 1 125 | @test trunc(Int, [1, 1]) == [1, 1] 126 | @test trunc(Int, [1.1, 1.1]) == [1, 1] 127 | @test trunc(Int, [1 1]) == [1 1] 128 | @test trunc(Int, [1.1 1.1]) == [1 1] 129 | @test trunc(Int, fill(1.1, 2, 3, 4)) == fill(1, 2, 3, 4) 130 | 131 | # n % Type 132 | for T in Any[Int16, Int32, UInt32, Int64, UInt64] 133 | if !(T <: Unsigned) 134 | @test convert(T, -200) % Int8 === @compat Int8(56) 135 | @test convert(T, -200) % UInt8 === 0x38 136 | @test convert(T, -300) % Int8 === @compat Int8(-44) 137 | @test convert(T, -300) % UInt8 === 0xd4 138 | @test convert(T, -128) % Int8 === @compat Int8(-128) 139 | @test convert(T, -128) % UInt8 === 0x80 140 | end 141 | @test convert(T, 127) % Int8 === @compat Int8(127) 142 | @test convert(T, 127) % UInt8 === 0x7f 143 | @test convert(T, 128) % Int8 === @compat Int8(-128) 144 | @test convert(T, 128) % UInt8 === 0x80 145 | @test convert(T, 200) % Int8 === @compat Int8(-56) 146 | @test convert(T, 300) % UInt8 === 0x2c 147 | end 148 | 149 | @test IPv4("1.2.3.4") == ip"1.2.3.4" 150 | @test IPv6("2001:1:2:3::1") == ip"2001:1:2:3::1" 151 | @test isless(ip"1.2.3.4", ip"1.2.3.5") 152 | 153 | @test startswith("abcdef","abc") == true 154 | @test startswith("abcdef","def") == false 155 | 156 | @test size(bitrand(3, 4)) == (3, 4) 157 | @test size(bitrand((3, 4))) == (3, 4) 158 | @test size(bitrand(MersenneTwister(), 3, 4)) == (3, 4) 159 | @test size(bitrand(MersenneTwister(), (3, 4))) == (3, 4) 160 | @test rand(Bool) in [false, true] 161 | 162 | rng = MersenneTwister() 163 | srand() 164 | srand(rng, UInt32[0,0]) 165 | srand(rng) 166 | for Tr in (Int8,UInt8,Int32,UInt32,Int64,UInt64,Int128,UInt128,Float16,Float32,Float64) 167 | for T in (Tr, Complex{Tr}) 168 | @test isa(rand(rng, T), T) 169 | let x = rand(rng, T, 3,4) 170 | @test isa(x, Array{T,2}) 171 | @test size(x) == (3,4) 172 | rand!(rng, x) 173 | end 174 | end 175 | end 176 | srand(rng, 0) 177 | let x = rand(rng, Int64, 3,4) 178 | srand(rng, 0) 179 | @test x == rand(rng, Int64, (3,4)) 180 | end 181 | 182 | module CartesianTest 183 | using Base.Cartesian, Compat 184 | @ngenerate N NTuple{N,Int} function f(X::NTuple{N,Int}...) 185 | @ncall N tuple X 186 | end 187 | end 188 | 189 | @test CartesianTest.f(1) == (1,) 190 | @test CartesianTest.f(1,2) == (1,2) 191 | @test CartesianTest.f(1,2,3) == (1,2,3) 192 | @test CartesianTest.f(1,2,3,4) == (1,2,3,4) 193 | @test CartesianTest.f(1,2,3,4,5) == (1,2,3,4,5) 194 | 195 | extrapath = is_windows() ? joinpath(JULIA_HOME,"..","Git","usr","bin")*";" : "" 196 | @compat withenv("PATH" => extrapath * ENV["PATH"]) do 197 | cmd1 = pipeline(`echo hello`, `sort`) 198 | cmd2 = pipeline(`true`, `true`) 199 | if is_windows() 200 | try # use busybox-w32 201 | success(`busybox`) 202 | cmd1 = pipeline(`busybox echo hello`, `busybox sort`) 203 | cmd2 = pipeline(`busybox true`, `busybox true`) 204 | end 205 | end 206 | @test readstring(cmd1) == "hello\n" 207 | @test success(cmd2) 208 | end 209 | 210 | let convert_funcs_and_types = 211 | ((:integer, :Integer), (:signed, :Signed), (:unsigned, :Unsigned), 212 | (:int, :Int), (:int8, :Int8), (:int16, :Int16), (:int32, :Int32), 213 | (:int64, :Int64), (:int128, :Int128), (:uint, :UInt), 214 | (:uint8, :UInt8), (:uint16, :UInt16), (:uint32, :UInt32), 215 | (:uint64, :UInt64), (:uint128, :UInt128), 216 | (:float16, :Float16), (:float32, :Float32), (:float64, :Float64), 217 | (:complex32,:Complex32), (:complex64,:Complex64),(:complex128,:Complex128), 218 | (:char,:Char)) 219 | 220 | for (df,t) in convert_funcs_and_types 221 | x = @compat UInt8(10) 222 | r1 = eval(:(@compat($t($x)))) 223 | ty = eval(t) 224 | if ty.abstract 225 | @test issubtype(typeof(r1),ty) 226 | else 227 | @test typeof(r1) === ty 228 | end 229 | if VERSION < v"0.4.0-dev+3732" 230 | r2 = eval(df)(x) 231 | @test r1 === r2 232 | if t === :Signed || t === :Complex32 233 | continue 234 | end 235 | x = fill(x, 10) 236 | r1 = eval(:(@compat map($t, $x))) 237 | r2 = eval(df)(x) 238 | @test r1 == r2 239 | @test typeof(r1) === typeof(r2) 240 | end 241 | end 242 | @test (@compat Bool(1)) 243 | @test !(@compat Bool(0)) 244 | 245 | # issue #54 246 | c = @compat Complex128(1) 247 | @test c.re == 1 248 | @test c.im == 0 249 | 250 | c = @compat Complex128(1,2) 251 | @test c.re == 1 252 | @test c.im == 2 253 | 254 | c = @compat Complex128(1+2im) 255 | @test c.re == 1 256 | @test c.im == 2 257 | end 258 | 259 | type Test3609 260 | a 261 | b 262 | end 263 | 264 | if VERSION < v"0.4.0-dev+3609" 265 | let v = Test3609(1,2) 266 | @test fieldnames(Test3609) == fieldnames(v) == Symbol[:a, :b] 267 | end 268 | end 269 | 270 | @test fieldoffset(Complex{Float32}, 2) === @compat UInt(4) 271 | 272 | @test parse(Int8, '9') == convert(Int8, 9) 273 | @test parse(Int, 'a', 16) == 10 274 | @test parse(Int, "200") == 200 275 | @test parse(Int16, "1101", 2) == convert(Int16, 13) 276 | @test parse(Float64, "222") == 222.0 277 | @test parse(Float32, "1.1") == convert(Float32, 1.1) 278 | @test parse(BigFloat, "1.125") == convert(BigFloat, 1.125) 279 | @test isa(tryparse(Float32, "1.1"), Nullable) 280 | @test get(tryparse(Float32, "1.1")) == 1.1f0 281 | @test isa(tryparse(Float32, "a"), Nullable{Float32}) 282 | @test isa(tryparse(Float64, "1.1"), Nullable) 283 | @test get(tryparse(Float64, "1.1")) == 1.1 284 | @test isa(tryparse(Float64, "a"), Nullable{Float64}) 285 | @test get(tryparse(Int32, "1")) == 1 286 | @test isa(tryparse(Int32, "a"), Nullable{Int32}) 287 | @test get(tryparse(Int64, "1")) == 1 288 | @test isa(tryparse(Int64, "a"), Nullable{Int64}) 289 | 290 | @test_throws ArgumentError tryparse(Int32, "0", 1) 291 | @test tryparse(Int32, "12345", 16) === Nullable{Int32}(@compat Int32(74565)) 292 | @test tryparse(Int64, "12345", 10) === Nullable{Int64}(@compat Int64(12345)) 293 | @test tryparse(Int64, "12345", 6) === Nullable{Int64}(@compat Int64(1865)) 294 | @test isnull(tryparse(Int64, "nonsense", 10)) 295 | @test tryparse(Int64, "nonsense", 36) === Nullable{Int64}(@compat Int64(1856056985582)) 296 | 297 | # Make sure exports from Libc and Libdl are defined 298 | for x in [:strftime,:systemsleep,:getpid,:FILE,:malloc,:flush_cstdio,:realloc,:strptime,:Libc,:errno,:TmStruct,:calloc,:time,:strerror,:gethostname,:free] 299 | getfield(Libc, x) 300 | end 301 | for x in [:RTLD_LOCAL,:RTLD_GLOBAL,:find_library,:dlsym,:RTLD_LAZY,:RTLD_NODELETE,:DL_LOAD_PATH,:RTLD_NOW,:Libdl,:dlext,:dlsym_e,:RTLD_FIRST,:dlopen,:dllist,:dlpath,:RTLD_NOLOAD,:dlclose,:dlopen_e,:RTLD_DEEPBIND] 302 | getfield(Libdl, x) 303 | end 304 | 305 | # Test unsafe_convert 306 | type Au_c; end 307 | x = "abc" 308 | @test @compat String(unsafe_string(Compat.unsafe_convert(Ptr{UInt8}, x))) == x 309 | Compat.unsafe_convert(::Ptr{Au_c}, x) = x 310 | @test Compat.unsafe_convert(pointer([Au_c()]), 1) == 1 311 | 312 | # Test Ptr{T}(0) 313 | @test @compat(Ptr{Int}(0)) == C_NULL 314 | 315 | # Test Tuple{} syntax 316 | if VERSION < v"0.4.0-dev+4319" 317 | @test @compat Tuple{1} == (1,) 318 | @test @compat Tuple{:a, :b} == (:a, :b) 319 | @test @compat Tuple{:a, Tuple{:b}} == (:a, (:b,)) 320 | @test @compat Tuple{:a, Tuple{:b, :c}} == (:a, (:b, :c)) 321 | @test @compat Tuple{Int} == (Int,) 322 | @test @compat Tuple{Int, Float64} == (Int, Float64) 323 | @test @compat Tuple{Int, Tuple{Float64}} == (Int, (Float64,)) 324 | @test @compat Tuple{Int, Tuple{Float64, Char}} == (Int, (Float64, Char)) 325 | @test @compat Tuple{Int, Vararg{Float64}} == (Int, Float64...) 326 | # Issue 81 327 | a81 = [Int, Int] 328 | b81 = (Int, Int) 329 | @test @compat Tuple{a81..., Vararg{Float64}} == (Int, Int, Float64...) 330 | @test @compat Tuple{b81..., Vararg{Float64}} == (Int, Int, Float64...) 331 | end 332 | 333 | # Ensure eachindex iterates over the whole array 334 | let A, B, s 335 | A = reshape(1:20,4,5) 336 | s = 0 337 | for i in eachindex(A) 338 | s += A[i] 339 | end 340 | @test s == 210 341 | B = sparse(A) 342 | s = 0 343 | for i in eachindex(B) 344 | s += B[i] 345 | end 346 | @test s == 210 347 | end 348 | 349 | let 350 | d = @compat Dict(1=>2, 3=>4) 351 | d[5] = 6 352 | val = 0 353 | for I in eachindex(d) 354 | val += d[I] 355 | end 356 | @test val == 12 357 | empty!(d) 358 | for I in eachindex(d) 359 | val += d[I] 360 | end 361 | @test val == 12 362 | end 363 | 364 | # findlast, findprev 365 | let a = [0,1,2,3,0,1,2,3] 366 | @test findlast(a) == 8 367 | @test findlast(a.==0) == 5 368 | @test findlast(a.==5) == 0 369 | @test findlast([1,2,4,1,2,3,4], 3) == 6 370 | @test findlast(isodd, [2,4,6,3,9,2,0]) == 5 371 | @test findlast(isodd, [2,4,6,2,0]) == 0 372 | @test findprev(a,4) == 4 373 | @test findprev(a,5) == 4 374 | @test findprev(a,1) == 0 375 | @test findprev(a,1,4) == 2 376 | @test findprev(a,1,8) == 6 377 | @test findprev(isodd, [2,4,5,3,9,2,0], 7) == 5 378 | @test findprev(isodd, [2,4,5,3,9,2,0], 2) == 0 379 | end 380 | 381 | # isdiag 382 | @test isdiag(diagm([1,2,3,4])) 383 | @test !isdiag([1 2; 3 4]) 384 | @test isdiag(5) 385 | 386 | # keytype & valtype 387 | if VERSION < v"0.4.0-dev+4502" 388 | @test keytype(@compat(Dict(1 => 1.))) == Int 389 | @test valtype(@compat(Dict(1 => 1.))) == Float64 390 | end 391 | 392 | # Val 393 | begin 394 | local firstlast 395 | firstlast(::Type{Val{true}}) = "First" 396 | firstlast(::Type{Val{false}}) = "Last" 397 | 398 | @test firstlast(Val{true}) == "First" 399 | @test firstlast(Val{false}) == "Last" 400 | end 401 | 402 | # qr, qrfact, qrfact! 403 | let A = [1.0 2.0; 3.0 4.0] 404 | Q, R = qr(A, Val{false}) 405 | @test Q*R ≈ A 406 | Q, R, p = qr(A, Val{true}) 407 | @test Q*R ≈ A[:,p] 408 | F = qrfact(A, Val{false}) 409 | @test F[:Q]*F[:R] ≈ A 410 | F = qrfact(A, Val{true}) 411 | @test F[:Q]*F[:R] ≈ A[:,F[:p]] 412 | A_copy = copy(A) 413 | F = qrfact!(A_copy, Val{false}) 414 | @test F[:Q]*F[:R] ≈ A 415 | A_copy = copy(A) 416 | F = qrfact!(A_copy, Val{true}) 417 | @test F[:Q]*F[:R] ≈ A[:,F[:p]] 418 | end 419 | 420 | # Cstring 421 | let s = "foo" 422 | # note: need cconvert in 0.5 because of JuliaLang/julia#16893 423 | @test reinterpret(Ptr{Cchar}, Compat.unsafe_convert(Cstring, VERSION < v"0.4" ? s : Base.cconvert(Cstring, s))) == pointer(s) 424 | if VERSION < v"0.5.0-dev+4859" 425 | let w = wstring("foo") 426 | @test reinterpret(Ptr{Cwchar_t}, Compat.unsafe_convert(Cwstring, w)) == pointer(w) 427 | end 428 | end 429 | end 430 | 431 | # fma and muladd 432 | @test fma(3,4,5) == 3*4+5 == muladd(3,4,5) 433 | 434 | if VERSION < v"0.5.0-dev+5271" 435 | # is_valid_utf32 436 | s = utf32("abc") 437 | @test isvalid(s) 438 | s = utf32(UInt32[65,0x110000]) 439 | @test !isvalid(s) 440 | 441 | # isvalid 442 | let s = "abcdef", u8 = "abcdef\uff", u16 = utf16(u8), u32 = utf32(u8), 443 | bad32 = utf32(UInt32[65,0x110000]), badch = Char[0x110000][1] 444 | 445 | @test !isvalid(bad32) 446 | @test !isvalid(badch) 447 | @test isvalid(s) 448 | @test isvalid(u8) 449 | @test isvalid(u16) 450 | @test isvalid(u32) 451 | @test isvalid(Compat.ASCIIString, s) 452 | @test isvalid(Compat.UTF8String, u8) 453 | @test isvalid(UTF16String, u16) 454 | @test isvalid(UTF32String, u32) 455 | end 456 | end 457 | 458 | if VERSION < v"0.5.0-dev+907" 459 | # chol 460 | let A = rand(2,2) 461 | B = A'*A 462 | U = @compat chol(B, Val{:U}) 463 | @test U'*U ≈ B 464 | end 465 | end 466 | 467 | # @generated 468 | if VERSION > v"0.3.99" 469 | let 470 | @compat @generated function foo(x) 471 | T = x 472 | :(return $T) 473 | end 474 | @test foo(5) == Int 475 | end 476 | end 477 | 478 | # Timer 479 | let c = 0, f, g, t 480 | @compat f(t::Timer) = (c += 1) 481 | @compat g(t::Base.Timer) = (c += 1) 482 | t = Timer(f, 0.0, 0.05) 483 | sleep(0.05) 484 | @test c >= 1 485 | sleep(0.1) 486 | @test c >= 3 487 | close(t) 488 | sleep(0.1) 489 | val = c 490 | sleep(0.1) 491 | @test val == c 492 | t = Timer(g, 0.0, 0.05) 493 | sleep(0.05) 494 | @test c >= 2 495 | close(t) 496 | end 497 | 498 | # MathConst -> Irrational 499 | f(::Irrational) = true 500 | @test f(π) 501 | Compat.@irrational mathconst_one 1.0 big(1.) 502 | @test f(mathconst_one) 503 | 504 | # gc_enable(::Bool) 505 | @test gc_enable(false) 506 | @test !gc_enable(true) 507 | 508 | # Vector{Int}(), Array{Int} 509 | 510 | @test @compat typeof(Vector{Int}()) == Array{Int,1} 511 | @test @compat length(Vector{Int}()) == 0 512 | 513 | @test @compat typeof(Vector{Int8}(10)) == Array{Int8,1} 514 | @test @compat length(Vector{Int8}(10)) == 10 515 | 516 | @test @compat typeof(Array{UInt16}()) == Array{UInt16,0} 517 | @test @compat length(Array{UInt16}()) == 1 518 | 519 | @test @compat typeof(Array{UInt16}(0)) == Array{UInt16,1} 520 | @test @compat length(Array{UInt16}(0)) == 0 521 | 522 | @test @compat typeof(Array{Float16}(5)) == Array{Float16,1} 523 | @test @compat length(Array{Float16}(5)) == 5 524 | 525 | @test @compat typeof(Array{AbstractString}(2,2)) == Array{AbstractString,2} 526 | @test @compat size(Array{AbstractString}(2,2)) == (2,2) 527 | 528 | @test @compat typeof(Array{Rational{Int}}(2,2,2,2,2)) == Array{Rational{Int},5} 529 | @test @compat size(Array{Rational{Int}}(2,2,2,2,2)) == (2,2,2,2,2) 530 | 531 | @compat String(Mmap.mmap(@__FILE__(),Vector{UInt8},11,1)) == "sing Compat" 532 | 533 | @test base64encode("hello world") == "aGVsbG8gd29ybGQ=" 534 | 535 | @test nothing === __precompile__(false) # tests should never be precompiled 536 | @test nothing === __precompile__() 537 | @test nothing === include_dependency("foo") 538 | 539 | @test real(Int) == real(Complex{Int}) == Int 540 | 541 | @test isa(1.2, AbstractFloat) 542 | 543 | @test [1,2,3] ≈ [1,2,3+1e-9] 544 | @test [0,1] ≈ [1e-9, 1] 545 | @test [0,1] ≉ [1e-3, 1] 546 | 547 | # linspace (some of the julia 0.4 tests) 548 | @test [Compat.linspace(0.1,0.3,3);] == [1:3;]./10 549 | @test [Compat.linspace(0.0,0.3,4);] == [0:3;]./10 550 | @test [Compat.linspace(0.3,-0.1,5);] == [3:-1:-1;]./10 551 | @test [Compat.linspace(0.1,-0.3,5);] == [1:-1:-3;]./10 552 | @test [Compat.linspace(0.0,1.0,11);] == [0:10;]./10 553 | @test [Compat.linspace(0.0,1.0,0);] == [] 554 | @test [Compat.linspace(0.0,-1.0,0);] == [] 555 | @test [Compat.linspace(0.0,-1.0,11);] == [0:-1:-10;]./10 556 | @test [Compat.linspace(1.0,27.0,1275);] == [49:1323;]./49 557 | @test [Compat.linspace(0.0,2.1,4);] == [0:7:21;]./10 558 | @test [Compat.linspace(0.0,3.3,4);] == [0:11:33;]./10 559 | @test [Compat.linspace(0.1,3.4,4);] == [1:11:34;]./10 560 | @test [Compat.linspace(0.0,3.9,4);] == [0:13:39;]./10 561 | @test [Compat.linspace(0.1,4.0,4);] == [1:13:40;]./10 562 | @test [Compat.linspace(1.1,3.3,3);] == [11:11:33;]./10 563 | @test [Compat.linspace(0.3,1.1,9);] == [3:1:11;]./10 564 | @test [Compat.linspace(0.0,0.0,1);] == [0.0] 565 | @test [Compat.linspace(0.0,0.0,1);] == [0.0] 566 | 567 | for T = (Float32, Float64) 568 | z = zero(T) 569 | u = eps(z) 570 | @test first(Compat.linspace(u,u,0)) == u 571 | @test last(Compat.linspace(u,u,0)) == u 572 | @test first(Compat.linspace(-u,u,0)) == -u 573 | @test last(Compat.linspace(-u,u,0)) == u 574 | @test [Compat.linspace(-u,u,0);] == [] 575 | @test [Compat.linspace(-u,-u,1);] == [-u] 576 | @test [Compat.linspace(-u,u,2);] == [-u,u] 577 | @test [Compat.linspace(-u,u,3);] == [-u,0,u] 578 | @test [Compat.linspace(-u,u,4);] == [-u,0,0,u] 579 | @test [Compat.linspace(-u,u,4);][2] === -z 580 | @test [Compat.linspace(-u,u,4);][3] === z 581 | @test first(Compat.linspace(-u,-u,0)) == -u 582 | @test last(Compat.linspace(-u,-u,0)) == -u 583 | @test first(Compat.linspace(u,-u,0)) == u 584 | @test last(Compat.linspace(u,-u,0)) == -u 585 | @test [Compat.linspace(u,-u,0);] == [] 586 | @test [Compat.linspace(u,u,1);] == [u] 587 | @test [Compat.linspace(u,-u,2);] == [u,-u] 588 | @test [Compat.linspace(u,-u,3);] == [u,0,-u] 589 | @test [Compat.linspace(u,-u,4);] == [u,0,0,-u] 590 | @test [Compat.linspace(u,-u,4);][2] === z 591 | @test [Compat.linspace(u,-u,4);][3] === -z 592 | v = [Compat.linspace(-u,u,12);] 593 | @test length(v) == 12 594 | @test issorted(v) && unique(v) == [-u,0,0,u] 595 | @test [-3u:u:3u;] == [Compat.linspace(-3u,3u,7);] == [-3:3;].*u 596 | @test [3u:-u:-3u;] == [Compat.linspace(3u,-3u,7);] == [3:-1:-3;].*u 597 | end 598 | 599 | if VERSION < v"0.4.0-dev+768" 600 | @test @compat(Void) === Nothing 601 | else 602 | @test @compat(Void) === Void 603 | end 604 | @test Ptr{Void} == @compat(Ptr{Void}) 605 | 606 | # MemoryError -> OutOfMemoryError 607 | # Base64Pipe -> Base64EncodePipe 608 | # UdpSocket -> UDPSocket 609 | f141(::Type{OutOfMemoryError}) = true 610 | f141(::Type{Base64EncodePipe}) = true 611 | f141(::Type{UDPSocket}) = true 612 | f141(::Type{TCPSocket}) = true 613 | 614 | @test f141(OutOfMemoryError) 615 | @test f141(Base64EncodePipe) 616 | @test f141(UDPSocket) 617 | @test f141(TCPSocket) 618 | 619 | # Union syntax 620 | if VERSION < v"0.4.0-dev+5379" 621 | @test @compat(Union{}) == None 622 | @test @compat(Union{Int,Float64}) == Union(Int,Float64) 623 | @test @compat(:(Union{})) == :(Union()) 624 | end 625 | 626 | @test fetch(remotecall(() -> true, 1)) 627 | @test remotecall_fetch(() -> true, 1) 628 | @test fetch(remotecall_wait(() -> true, 1)) 629 | Base.remote_do(() -> true, 1) # Doesn't return anything so cannot be `@test`ed but should print some output if it fails 630 | 631 | # JuliaLang/julia#13440 632 | @test isa(SparseArrays, Module) 633 | 634 | # JuliaLang/julia#12819 635 | @test Compat.Filesystem.JL_O_RDWR == Compat.Filesystem.JL_O_RDWR 636 | 637 | # JuliaLang/julia#14338 638 | @test supertype(Int) == Signed 639 | 640 | # withenv 641 | @test "1234" == @compat withenv(() -> ENV["_TESTVAR"], "_TESTVAR" => 1234) 642 | @test "1234" == @compat withenv("_TESTVAR" => 1234) do 643 | return ENV["_TESTVAR"] 644 | end 645 | 646 | # Test functional form of mktemp and mktempdir 647 | let 648 | tmp_path = mktemp() do p, io 649 | @test isfile(p) 650 | print(io, "鴨かも?") 651 | p 652 | end 653 | @test tmp_path != "" 654 | @test !isfile(tmp_path) 655 | end 656 | 657 | let 658 | tmpdir = mktempdir() do d 659 | @test isdir(d) 660 | d 661 | end 662 | @test tmpdir != "" 663 | @test !isdir(tmpdir) 664 | end 665 | 666 | # https://github.com/JuliaLang/julia/pull/14660 667 | mktempdir() do dir 668 | 669 | verbose = false 670 | 671 | # Create test file... 672 | filename = joinpath(dir, "file.txt") 673 | text = "C1,C2\n1,2\na,b\n" 674 | 675 | # List of IO producers... 676 | l = [ 677 | ("IOStream", (text) -> begin 678 | write(filename, text) 679 | open(filename) 680 | end), 681 | ("IOBuffer", (text)->IOBuffer(text)) 682 | ] 683 | 684 | open_streams = Any[] 685 | function cleanup() 686 | for s in open_streams 687 | try close(s) end 688 | end 689 | end 690 | 691 | for (name, f) in l 692 | 693 | io = ()->(s=f(text); push!(open_streams, s); s) 694 | 695 | write(filename, text) 696 | 697 | verbose && println("$name read...") 698 | @test read(io(), UInt8) == read(IOBuffer(text), UInt8) 699 | @test read(io(), UInt8) == read(filename, UInt8) 700 | @test read(io(), Int) == read(IOBuffer(text), Int) 701 | @test read(io(), Int) == read(filename,Int) 702 | s1 = io() 703 | s2 = IOBuffer(text) 704 | @test read(s1, UInt32, 2) == read(s2, UInt32, 2) 705 | @test !eof(s1) 706 | @test read(s1, UInt8, 5) == read(s2, UInt8, 5) 707 | @test !eof(s1) 708 | @test read(s1, UInt8, 1) == read(s2, UInt8, 1) 709 | @test eof(s1) 710 | @test_throws EOFError read(s1, UInt8) 711 | @test eof(s1) 712 | close(s1) 713 | close(s2) 714 | 715 | verbose && println("$name eof...") 716 | n = length(text) - 1 717 | @test @compat read!(io(), Vector{UInt8}(n)) == 718 | read!(IOBuffer(text), Vector{UInt8}(n)) 719 | @test @compat (s = io(); read!(s, Vector{UInt8}(n)); !eof(s)) 720 | n = length(text) 721 | @test @compat read!(io(), Vector{UInt8}(n)) == 722 | read!(IOBuffer(text), Vector{UInt8}(n)) 723 | @test @compat (s = io(); read!(s, Vector{UInt8}(n)); eof(s)) 724 | n = length(text) + 1 725 | @test_throws EOFError @compat read!(io(), Vector{UInt8}(n)) 726 | @test_throws EOFError @compat read!(io(), Vector{UInt8}(n)) 727 | 728 | old_text = text 729 | cleanup() 730 | const SZ_UNBUFFERED_IO = 65536 731 | 732 | for text in [ 733 | old_text, 734 | convert(Compat.UTF8String, Char['A' + i % 52 for i in 1:(div(SZ_UNBUFFERED_IO,2))]), 735 | convert(Compat.UTF8String, Char['A' + i % 52 for i in 1:( SZ_UNBUFFERED_IO -1)]), 736 | convert(Compat.UTF8String, Char['A' + i % 52 for i in 1:( SZ_UNBUFFERED_IO )]), 737 | convert(Compat.UTF8String, Char['A' + i % 52 for i in 1:( SZ_UNBUFFERED_IO +1)]) 738 | ] 739 | 740 | write(filename, text) 741 | 742 | verbose && println("$name readstring...") 743 | @test readstring(io()) == text 744 | 745 | @test readstring(io()) == readstring(filename) 746 | 747 | 748 | verbose && println("$name read...") 749 | @test @compat read(io()) == UInt8[convert(UInt8, _) for _ in text] 750 | 751 | @test read(io()) == read(filename) 752 | 753 | cleanup() 754 | 755 | 756 | verbose && println("$name readbytes!...") 757 | l = length(text) 758 | for n = [1, 2, l-2, l-1, l, l+1, l+2] 759 | @compat a1 = Vector{UInt8}(n); 760 | @compat a2 = Vector{UInt8}(n) 761 | s1 = io() 762 | s2 = IOBuffer(text) 763 | n1 = readbytes!(s1, a1) 764 | n2 = readbytes!(s2, a2) 765 | @test n1 == n2 766 | @test length(a1) == length(a2) 767 | @test a1[1:n1] == a2[1:n2] 768 | @test n <= length(text) || eof(s1) 769 | @test n <= length(text) || eof(s2) 770 | 771 | cleanup() 772 | end 773 | 774 | verbose && println("$name read!...") 775 | l = length(text) 776 | for n = [1, 2, l-2, l-1, l] 777 | @test @compat read!(io(), Vector{UInt8}(n)) == 778 | read!(IOBuffer(text), Vector{UInt8}(n)) 779 | @test @compat read!(io(), Vector{UInt8}(n)) == 780 | read!(filename, Vector{UInt8}(n)) 781 | 782 | cleanup() 783 | end 784 | @test_throws EOFError @compat read!(io(), Vector{UInt8}(length(text)+1)) 785 | 786 | 787 | verbose && println("$name readuntil...") 788 | @test readuntil(io(), '\n') == readuntil(IOBuffer(text),'\n') 789 | @test readuntil(io(), '\n') == readuntil(filename,'\n') 790 | @test readuntil(io(), "\n") == readuntil(IOBuffer(text),"\n") 791 | @test readuntil(io(), "\n") == readuntil(filename,"\n") 792 | @test readuntil(io(), ',') == readuntil(IOBuffer(text),',') 793 | @test readuntil(io(), ',') == readuntil(filename,',') 794 | 795 | cleanup() 796 | 797 | verbose && println("$name readline...") 798 | @test readline(io()) == readline(IOBuffer(text)) 799 | @test readline(io()) == readline(filename) 800 | 801 | verbose && println("$name readlines...") 802 | @test readlines(io()) == readlines(IOBuffer(text)) 803 | @test readlines(io()) == readlines(filename) 804 | @test collect(eachline(io())) == collect(eachline(IOBuffer(text))) 805 | @test collect(eachline(io())) == collect(eachline(filename)) 806 | 807 | cleanup() 808 | 809 | verbose && println("$name countlines...") 810 | @test countlines(io()) == countlines(IOBuffer(text)) 811 | 812 | # verbose && println("$name readcsv...") 813 | # @test readcsv(io()) == readcsv(IOBuffer(text)) 814 | # @test readcsv(io()) == readcsv(filename) 815 | 816 | cleanup() 817 | end 818 | 819 | text = old_text 820 | write(filename, text) 821 | 822 | verbose && println("$name position...") 823 | @test @compat (s = io(); read!(s, Vector{UInt8}(4)); position(s)) == 4 824 | 825 | verbose && println("$name seek...") 826 | for n = 0:length(text)-1 827 | @test readlines(seek(io(), n)) == readlines(seek(IOBuffer(text), n)) 828 | cleanup() 829 | end 830 | verbose && println("$name skip...") 831 | for n = 0:length(text)-1 832 | @test readlines(seek(io(), n)) == readlines(seek(IOBuffer(text), n)) 833 | @test readlines(skip(io(), n)) == readlines(skip(IOBuffer(text), n)) 834 | cleanup() 835 | end 836 | verbose && println("$name seekend...") 837 | @test readstring(seekend(io())) == "" 838 | 839 | verbose && println("$name write(::IOStream, ...)") 840 | to = open("$filename.to", "w") 841 | write(to, io()) 842 | close(to) 843 | @test readstring("$filename.to") == text 844 | 845 | verbose && println("$name write(filename, ...)") 846 | write("$filename.to", io()) 847 | @test readstring("$filename.to") == text 848 | 849 | verbose && println("$name write(::IOBuffer, ...)") 850 | @compat to = IOBuffer(UInt8[convert(UInt8, _) for _ in text], false, true) 851 | write(to, io()) 852 | @test String(take!(to)) == text 853 | 854 | cleanup() 855 | end 856 | 857 | 858 | # https://github.com/JuliaLang/julia/pull/13232 859 | 860 | setprecision(BigFloat, 100) 861 | @test precision(BigFloat) == 100 862 | setprecision(256) 863 | @test precision(BigFloat) == 256 864 | 865 | setprecision(BigFloat, 100) do 866 | a = big(pi) 867 | @test precision(a) == 100 868 | end 869 | 870 | setprecision(130) do 871 | a = big(pi) 872 | @test precision(a) == 130 873 | end 874 | 875 | for T in (BigFloat, Float64) 876 | setrounding(T, RoundDown) 877 | @test rounding(T) == RoundDown 878 | setrounding(T, RoundNearest) 879 | 880 | setrounding(T, RoundUp) do 881 | @test rounding(T) == RoundUp 882 | end 883 | end 884 | 885 | end 886 | 887 | @test typeof(displaysize()) == @compat(Tuple{Int, Int}) 888 | 889 | @test Compat.LinAlg.checksquare(randn(4,4)) == 4 890 | @test Compat.LinAlg.checksquare(randn(4,4), randn(3,3)) == [4,3] 891 | @test_throws DimensionMismatch Compat.LinAlg.checksquare(randn(4,3)) 892 | 893 | @test issymmetric([1 2 3; 2 2 3; 3 3 2]) 894 | @test !issymmetric([1 3 3; 2 2 3; 3 3 2]) 895 | 896 | let X = randn(10,2), Y = randn(10,2), x = randn(10), y = randn(10) 897 | for b in (true, false) 898 | if VERSION < v"0.5.0-dev+679" 899 | @test cov(x, b) == cov(x, corrected=b) 900 | end 901 | for d in (1, 2) 902 | @test size(cov(X, d), 1) == 8*d - 6 903 | @test size(cov(X, d, b), 1) == 8*d - 6 904 | @test size(cov(X, Y, d), 1) == 8*d - 6 905 | @test size(cov(X, Y, d, b), 1) == 8*d - 6 906 | 907 | @test size(cor(X, d), 1) == 8*d - 6 908 | @test size(cor(X, Y, d), 1) == 8*d - 6 909 | end 910 | end 911 | end 912 | 913 | # foreach 914 | let 915 | a = Any[] 916 | foreach(()->push!(a,0)) 917 | @test a == [0] 918 | a = Any[] 919 | foreach(x->push!(a,x), [1,5,10]) 920 | @test a == [1,5,10] 921 | a = Any[] 922 | foreach((args...)->push!(a,args), [2,4,6], [10,20,30]) 923 | @test a == [(2,10),(4,20),(6,30)] 924 | end 925 | 926 | @test istextmime("text/html") && !istextmime("image/png") 927 | 928 | module CallTest 929 | 930 | using Base.Test, Compat 931 | 932 | immutable A 933 | a 934 | end 935 | 936 | immutable B{T} 937 | b::T 938 | end 939 | 940 | if VERSION >= v"0.4" 941 | @compat (::Type{A})() = A(1) 942 | @compat (::Type{B})() = B{Int}() 943 | @compat (::Type{B{T}}){T}() = B{T}(zero(T)) 944 | 945 | @compat (a::A)() = a.a 946 | @compat (a::A)(b) = (a.a, b) 947 | @compat (a::A)(b, c; d=2) = (a.a, b, c, d) 948 | @compat (b::B{T}){T}() = b.b, T 949 | @compat (b::B{T}){T}(c::T) = 1 950 | @compat (b::B{T}){T,T2}(c::T2) = 0 951 | @compat (b::B{T}){T}(c::T, d; f=1) = (c, d, f) 952 | 953 | @test A() === A(1) 954 | @test B() === B(0) 955 | @test B{Float64}() === B(0.0) 956 | 957 | @test A(1)() === 1 958 | @test A(1)(2) === (1, 2) 959 | @test A(1)(2, 3; d=10) === (1, 2, 3, 10) 960 | @test B(0)() === (0, Int) 961 | @test B(0)(1) === 1 962 | @test B(0)(1, 2; f=100) === (1, 2, 100) 963 | @test B(0)(1.0) === 0 964 | end 965 | 966 | end 967 | 968 | # walkdir 969 | 970 | dirwalk = mktempdir() 971 | cd(dirwalk) do 972 | for i=1:2 973 | mkdir("sub_dir$i") 974 | open("file$i", "w") do f end 975 | 976 | mkdir(joinpath("sub_dir1", "subsub_dir$i")) 977 | touch(joinpath("sub_dir1", "file$i")) 978 | end 979 | touch(joinpath("sub_dir2", "file_dir2")) 980 | has_symlinks = is_unix() ? true : (isdefined(Base, :WINDOWS_VISTA_VER) && Base.windows_version() >= Base.WINDOWS_VISTA_VER) 981 | follow_symlink_vec = has_symlinks ? [true, false] : [false] 982 | has_symlinks && symlink(abspath("sub_dir2"), joinpath("sub_dir1", "link")) 983 | for follow_symlinks in follow_symlink_vec 984 | task = walkdir(".", follow_symlinks=follow_symlinks) 985 | root, dirs, files = consume(task) 986 | @test root == "." 987 | @test dirs == ["sub_dir1", "sub_dir2"] 988 | @test files == ["file1", "file2"] 989 | 990 | root, dirs, files = consume(task) 991 | @test root == joinpath(".", "sub_dir1") 992 | @test dirs == (has_symlinks ? ["link", "subsub_dir1", "subsub_dir2"] : ["subsub_dir1", "subsub_dir2"]) 993 | @test files == ["file1", "file2"] 994 | 995 | root, dirs, files = consume(task) 996 | if follow_symlinks 997 | @test root == joinpath(".", "sub_dir1", "link") 998 | @test dirs == [] 999 | @test files == ["file_dir2"] 1000 | root, dirs, files = consume(task) 1001 | end 1002 | for i=1:2 1003 | @test root == joinpath(".", "sub_dir1", "subsub_dir$i") 1004 | @test dirs == [] 1005 | @test files == [] 1006 | root, dirs, files = consume(task) 1007 | end 1008 | 1009 | @test root == joinpath(".", "sub_dir2") 1010 | @test dirs == [] 1011 | @test files == ["file_dir2"] 1012 | end 1013 | 1014 | for follow_symlinks in follow_symlink_vec 1015 | task = walkdir(".", follow_symlinks=follow_symlinks, topdown=false) 1016 | root, dirs, files = consume(task) 1017 | if follow_symlinks 1018 | @test root == joinpath(".", "sub_dir1", "link") 1019 | @test dirs == [] 1020 | @test files == ["file_dir2"] 1021 | root, dirs, files = consume(task) 1022 | end 1023 | for i=1:2 1024 | @test root == joinpath(".", "sub_dir1", "subsub_dir$i") 1025 | @test dirs == [] 1026 | @test files == [] 1027 | root, dirs, files = consume(task) 1028 | end 1029 | @test root == joinpath(".", "sub_dir1") 1030 | @test dirs == (has_symlinks ? ["link", "subsub_dir1", "subsub_dir2"] : ["subsub_dir1", "subsub_dir2"]) 1031 | @test files == ["file1", "file2"] 1032 | 1033 | root, dirs, files = consume(task) 1034 | @test root == joinpath(".", "sub_dir2") 1035 | @test dirs == [] 1036 | @test files == ["file_dir2"] 1037 | 1038 | root, dirs, files = consume(task) 1039 | @test root == "." 1040 | @test dirs == ["sub_dir1", "sub_dir2"] 1041 | @test files == ["file1", "file2"] 1042 | end 1043 | #test of error handling 1044 | task_error = walkdir(".") 1045 | task_noerror = walkdir(".", onerror=x->x) 1046 | root, dirs, files = consume(task_error) 1047 | @test root == "." 1048 | @test dirs == ["sub_dir1", "sub_dir2"] 1049 | @test files == ["file1", "file2"] 1050 | 1051 | rm(joinpath("sub_dir1"), recursive=true) 1052 | @test_throws SystemError consume(task_error) # throws an error because sub_dir1 do not exist 1053 | 1054 | root, dirs, files = consume(task_noerror) 1055 | @test root == "." 1056 | @test dirs == ["sub_dir1", "sub_dir2"] 1057 | @test files == ["file1", "file2"] 1058 | 1059 | root, dirs, files = consume(task_noerror) # skips sub_dir1 as it no longer exist 1060 | @test root == joinpath(".", "sub_dir2") 1061 | @test dirs == [] 1062 | @test files == ["file_dir2"] 1063 | 1064 | end 1065 | rm(dirwalk, recursive=true) 1066 | 1067 | # RemoteChannel/Future 1068 | r = remotecall(sin, 1, pi/3) 1069 | @compat foo(r::Future) = 7 1070 | @test foo(r) == 7 1071 | 1072 | @compat rc = RemoteChannel() 1073 | @compat rc = RemoteChannel(myid()) 1074 | 1075 | @compat rc = Future() 1076 | @compat rc = Future(myid()) 1077 | 1078 | # @functorize 1079 | function checkfunc(Fun, func) 1080 | if VERSION >= v"0.5.0-dev+3701" 1081 | @eval @test @functorize($(func)) === Base.$(func) 1082 | else 1083 | if isdefined(Base, Fun) 1084 | @eval @test isa(@functorize($(func)), Base.$(Fun)) 1085 | else 1086 | @eval @test isa(@functorize($(func)), Function) 1087 | @eval @test @functorize($(func)) === Base.$(func) 1088 | end 1089 | end 1090 | end 1091 | 1092 | for (Fun, func) in [(:IdFun, :identity), 1093 | (:AbsFun, :abs), 1094 | (:Abs2Fun, :abs2), 1095 | (:ExpFun, :exp), 1096 | (:LogFun, :log), 1097 | (:ConjFun, :conj)] 1098 | begin 1099 | if isdefined(Base, func) 1100 | checkfunc(Fun, func) 1101 | a = rand(1:10, 10) 1102 | @eval @test mapreduce($(func), +, $(a)) == mapreduce(@functorize($(func)), +, $(a)) 1103 | end 1104 | end 1105 | end 1106 | 1107 | dotfunctors = [(:DotAddFun, :.+), 1108 | (:DotSubFun, :.-), 1109 | (:DotMulFun, :.*), 1110 | (:DotRDivFun, :./), 1111 | (:DotIDivFun, @compat(Symbol(".÷"))), 1112 | (:DotRemFun, :.%), 1113 | (:DotLSFun, :.<<), 1114 | (:DotRSFun, :.>>)] 1115 | 1116 | functors = [(:AndFun, :&), 1117 | (:OrFun, :|), 1118 | (:XorFun, :⊻), 1119 | (:AddFun, :+), 1120 | (:SubFun, :-), 1121 | (:MulFun, :*), 1122 | (:RDivFun, :/), 1123 | (:LDivFun, :\ ), 1124 | (:IDivFun, :div), 1125 | (:ModFun, :mod), 1126 | (:RemFun, :rem), 1127 | (:PowFun, :^), 1128 | (:MaxFun, :scalarmax), 1129 | (:MinFun, :scalarmin), 1130 | (:LessFun, :<), 1131 | (:MoreFun, :>), 1132 | (:ElementwiseMaxFun, :max), 1133 | (:ElementwiseMinFun, :min)] 1134 | 1135 | # since #17623, dot functions are no longer function objects 1136 | if VERSION < v"0.6.0-dev.1614" 1137 | append!(functors, dotfunctors) 1138 | end 1139 | 1140 | for (Fun, func) in functors 1141 | begin 1142 | if isdefined(Base, func) && (func !== :.>> || VERSION >= v"0.4.0-dev+553") && (func !== :.% || VERSION >= v"0.5.0-dev+1472") 1143 | checkfunc(Fun, func) 1144 | a = rand(1:10, 10) 1145 | @eval @test mapreduce(identity, Base.$(func), $(a)) == mapreduce(identity, @functorize($(func)), $(a)) 1146 | end 1147 | end 1148 | end 1149 | 1150 | if VERSION >= v"0.5.0-dev+3701" 1151 | @test @functorize(complex) === complex 1152 | @test @functorize(dot) === dot 1153 | else 1154 | if isdefined(Base, :SparseArrays) && isdefined(Base.SparseArrays, :ComplexFun) 1155 | @test isa(@functorize(complex), Base.SparseArrays.ComplexFun) 1156 | @test isa(@functorize(dot), Base.SparseArrays.DotFun) 1157 | else 1158 | @test isa(@functorize(complex), Function) 1159 | @test isa(@functorize(dot), Function) 1160 | @test @functorize(complex) === complex 1161 | @test @functorize(dot) === dot 1162 | end 1163 | end 1164 | let a = rand(1:10, 10) 1165 | @test mapreduce(identity, dot, a) == mapreduce(identity, @functorize(dot), a) 1166 | end 1167 | @test isa(@functorize(centralizedabs2fun)(1), @functorize(centralizedabs2fun)) 1168 | @test isa(@functorize(centralizedabs2fun)(1.0), @functorize(centralizedabs2fun)) 1169 | let a = rand(1:10, 10) 1170 | @eval @test mapreduce(x -> abs2(x - 1), +, $(a)) == mapreduce(@functorize(centralizedabs2fun)(1), +, $(a)) 1171 | end 1172 | 1173 | # Threads.@threads 1174 | using Compat.Threads 1175 | @threads for i=1:10 1176 | @test true 1177 | end 1178 | 1179 | # Issue #223 1180 | @test 1 == threadid() <= nthreads() 1181 | 1182 | @test @compat(Symbol("foo")) === :foo 1183 | @test @compat(Symbol("foo", "bar")) === :foobar 1184 | @test @compat(Symbol("a_", 2)) === :a_2 1185 | @test @compat(Symbol('c')) === :c 1186 | @test @compat(Symbol(1)) === @compat(Symbol("1")) 1187 | 1188 | @test @compat(Base.:+) == + 1189 | let x = rand(3), y = rand(3) 1190 | @test @compat(sin.(cos.(x))) == map(x -> sin(cos(x)), x) 1191 | @test @compat(atan2.(sin.(y),x)) == broadcast(atan2,map(sin,y),x) 1192 | end 1193 | let x0 = Array(Float64), v, v0 1194 | x0[1] = rand() 1195 | v0 = @compat sin.(x0) 1196 | @test isa(v0, Array{Float64,0}) 1197 | v = @compat sin.(x0[1]) 1198 | @test isa(v, Float64) 1199 | @test v == v0[1] == sin(x0[1]) 1200 | end 1201 | let x = rand(2, 2), v 1202 | v = @compat sin.(x) 1203 | @test isa(v, Array{Float64,2}) 1204 | @test v == [sin(x[1, 1]) sin(x[1, 2]); 1205 | sin(x[2, 1]) sin(x[2, 2])] 1206 | end 1207 | let x1 = [1, 2, 3], x2 = ([3, 4, 5],), v 1208 | v = @compat atan2.(x1, x2...) 1209 | @test isa(v, Vector{Float64}) 1210 | @test v == [atan2(1, 3), atan2(2, 4), atan2(3, 5)] 1211 | end 1212 | # Do the following in global scope to make sure inference is able to handle it 1213 | @test @compat(sin.([1, 2])) == [sin(1), sin(2)] 1214 | @test isa(@compat(sin.([1, 2])), Vector{Float64}) 1215 | @test @compat(atan2.(1, [2, 3])) == [atan2(1, 2), atan2(1, 3)] 1216 | @test isa(@compat(atan2.(1, [2, 3])), Vector{Float64}) 1217 | @test @compat(atan2.([1, 2], [2, 3])) == [atan2(1, 2), atan2(2, 3)] 1218 | @test isa(@compat(atan2.([1, 2], [2, 3])), Vector{Float64}) 1219 | # And make sure it is actually inferrable 1220 | f15032(a) = @compat sin.(a) 1221 | @inferred f15032([1, 2, 3]) 1222 | @inferred f15032([1.0, 2.0, 3.0]) 1223 | 1224 | if VERSION ≥ v"0.4.0-dev+3732" 1225 | @test Symbol("foo") === :foo 1226 | @test Symbol("foo", "bar") === :foobar 1227 | @test Symbol("a_", 2) === :a_2 1228 | @test Symbol('c') === :c 1229 | @test Symbol(1) === Symbol("1") 1230 | end 1231 | 1232 | foostring(::String) = 1 1233 | @test foostring("hello") == 1 1234 | @test foostring("λ") == 1 1235 | @test isa("hello", Compat.ASCIIString) 1236 | @test isa("λ", Compat.UTF8String) 1237 | 1238 | let async, c = false 1239 | run = Condition() 1240 | async = Compat.AsyncCondition(x->(c = true; notify(run))) 1241 | ccall(:uv_async_send, Void, (Ptr{Void},), async.handle) 1242 | wait(run) 1243 | @test c 1244 | end 1245 | 1246 | let async, c = false 1247 | async = Compat.AsyncCondition() 1248 | started = Condition() 1249 | task = @schedule begin 1250 | notify(started) 1251 | wait(async) 1252 | true 1253 | end 1254 | wait(started) 1255 | ccall(:uv_async_send, Void, (Ptr{Void},), async.handle) 1256 | @test wait(task) 1257 | end 1258 | 1259 | let io = IOBuffer(), s = "hello" 1260 | unsafe_write(io, pointer(s), length(s)) 1261 | @test String(take!(io)) == s 1262 | end 1263 | 1264 | @static if VERSION ≥ v"0.4" 1265 | @test VERSION ≥ v"0.4" 1266 | else 1267 | @test VERSION < v"0.4" 1268 | end 1269 | 1270 | let io = IOBuffer(), s = "hello" 1271 | @test @compat String(Vector{UInt8}(s)) == s 1272 | write(io, s) 1273 | @test @compat String(io) == s 1274 | @test unsafe_string(pointer(s)) == s 1275 | @test unsafe_string(pointer(s),sizeof(s)) == s 1276 | @test string(s, s, s) == "hellohellohello" 1277 | @test @compat(String(s)) == s 1278 | @test String == @compat(Union{Compat.UTF8String,Compat.ASCIIString}) 1279 | end 1280 | 1281 | @test Compat.repeat(1:2, inner=2) == [1, 1, 2, 2] 1282 | @test Compat.repeat(1:2, outer=[2]) == [1, 2, 1, 2] 1283 | @test Compat.repeat([1,2], inner=(2,)) == [1, 1, 2, 2] 1284 | 1285 | if VERSION < v"0.5.0-dev+4267" 1286 | if OS_NAME == :Windows 1287 | @test is_windows() 1288 | elseif OS_NAME == :Darwin 1289 | @test is_apple() && is_bsd() && is_unix() 1290 | elseif OS_NAME == :FreeBSD 1291 | @test is_bsd() && is_unix() 1292 | elseif OS_NAME == :Linux 1293 | @test is_linux() && is_unix() 1294 | end 1295 | else 1296 | @test Compat.KERNEL == Sys.KERNEL 1297 | end 1298 | 1299 | io = IOBuffer() 1300 | @test @compat(get(io, :limit, false)) == false 1301 | @test @compat(get(io, :compact, false)) == false 1302 | @test @compat(get(io, :multiline, false)) == false 1303 | @test @compat(get(Nullable(1))) == 1 1304 | 1305 | let 1306 | test_str = "test" 1307 | ptr = pointer(test_str) 1308 | wrapped_str = if VERSION < v"0.6.0-dev.1988" 1309 | unsafe_wrap(Compat.String, ptr) 1310 | else 1311 | unsafe_string(ptr) 1312 | end 1313 | new_str = unsafe_string(ptr) 1314 | cstr = convert(Cstring, ptr) 1315 | new_str2 = unsafe_string(cstr) 1316 | @test wrapped_str == "test" 1317 | @test new_str == "test" 1318 | @test new_str2 == "test" 1319 | if VERSION < v"0.6.0-dev.1988" 1320 | # Test proper pointer aliasing behavior, which is not possible in 0.6 1321 | # with the new String representation 1322 | @test ptr == pointer(wrapped_str) 1323 | end 1324 | @test ptr ≠ pointer(new_str) 1325 | @test ptr ≠ pointer(new_str2) 1326 | @test unsafe_string(convert(Ptr{Int8}, ptr)) == "test" 1327 | if VERSION < v"0.6.0-dev.1988" 1328 | @test unsafe_wrap(Compat.String, convert(Ptr{Int8}, ptr)) == "test" 1329 | end 1330 | x = [1, 2] 1331 | @test unsafe_wrap(Array, pointer(x), 2) == [1, 2] 1332 | end 1333 | 1334 | @test allunique([1, 2, 3]) 1335 | @test !allunique([1, 2, 1]) 1336 | @test allunique(1:3) 1337 | @test allunique(FloatRange(0.0, 0.0, 0.0, 1.0)) 1338 | @test !allunique(FloatRange(0.0, 0.0, 2.0, 1.0)) 1339 | 1340 | # Add test for Base.view 1341 | let a = rand(10,10) 1342 | @test view(a, :, 1) == a[:,1] 1343 | end 1344 | 1345 | 1346 | # 0.5 style single argument `@boundscheck` 1347 | @inline function do_boundscheck() 1348 | # A bit ugly since `@boundscheck` returns `nothing`. 1349 | checked = false 1350 | @compat @boundscheck (checked = true;) 1351 | checked 1352 | end 1353 | @test do_boundscheck() == true 1354 | 1355 | @test Compat.promote_eltype_op(@functorize(+), ones(2,2), 1) === Float64 1356 | @test Compat.promote_eltype_op(@functorize(*), ones(Int, 2), zeros(Int16,2)) === Int 1357 | 1358 | #Add test for Base.normalize and Base.normalize! 1359 | let 1360 | vr = [3.0, 4.0] 1361 | for Tr in (Float32, Float64) 1362 | for T in (Tr, Complex{Tr}) 1363 | v = convert(Vector{T}, vr) 1364 | @test norm(v) == 5.0 1365 | w = normalize(v) 1366 | @test norm(w - [0.6, 0.8], Inf) < eps(Tr) 1367 | @test isapprox(norm(w), 1.0) 1368 | @test norm(normalize!(copy(v)) - w, Inf) < eps(Tr) 1369 | @test isempty(normalize!(T[])) 1370 | end 1371 | end 1372 | end 1373 | 1374 | #Test potential overflow in normalize! 1375 | let 1376 | δ = inv(prevfloat(typemax(Float64))) 1377 | v = [δ, -δ] 1378 | if VERSION > v"0.4.0-pre+7164" 1379 | @test norm(v) === 7.866824069956793e-309 1380 | end 1381 | w = normalize(v) 1382 | if VERSION > v"0.4.0-pre+7164" 1383 | @test w ≈ [1/√2, -1/√2] 1384 | @test isapprox(norm(w), 1.0) 1385 | end 1386 | @test norm(normalize!(v) - w, Inf) < eps() 1387 | end 1388 | 1389 | # JuliaLang/julia#16603 1390 | @test sprint(join, [1, 2, 3]) == "123" 1391 | @test sprint(join, [1, 2, 3], ',') == "1,2,3" 1392 | @test sprint(join, [1, 2, 3], ", ", ", and ") == "1, 2, and 3" 1393 | @test sprint(escape_string, "xyz\n", "z") == "xy\\z\\n" 1394 | @test sprint(unescape_string, "xyz\\n") == "xyz\n" 1395 | 1396 | # three-argument show from JuliaLang/julia#16563 1397 | @test sprint(show, "text/plain", 1) == stringmime("text/plain", 1) 1398 | 1399 | let n=5, a=rand(n), incx=1, b=rand(n), incy=1 1400 | ccall((Compat.@blasfunc(dcopy_), Base.LinAlg.BLAS.libblas), Void, 1401 | (Ptr{Base.LinAlg.BLAS.BlasInt}, Ptr{Float64}, Ptr{Base.LinAlg.BLAS.BlasInt}, Ptr{Float64}, Ptr{Base.LinAlg.BLAS.BlasInt}), 1402 | &n, a, &incx, b, &incy) 1403 | @test a == b 1404 | end 1405 | 1406 | # do-block redirect_std* 1407 | let filename = tempname() 1408 | ret = open(filename, "w") do f 1409 | redirect_stdout(f) do 1410 | println("hello") 1411 | [1,3] 1412 | end 1413 | end 1414 | @test ret == [1,3] 1415 | @test chomp(readstring(filename)) == "hello" 1416 | ret = open(filename, "w") do f 1417 | redirect_stderr(f) do 1418 | println(STDERR, "WARNING: hello") 1419 | [2] 1420 | end 1421 | end 1422 | @test ret == [2] 1423 | @test contains(readstring(filename), "WARNING: hello") 1424 | ret = open(filename) do f 1425 | redirect_stdin(f) do 1426 | readline() 1427 | end 1428 | end 1429 | @test contains(ret, "WARNING: hello") 1430 | rm(filename) 1431 | end 1432 | 1433 | @test @__DIR__() == dirname(@__FILE__) 1434 | 1435 | # PR #17302 1436 | # To be removed when 0.5/0.6 support is dropped. 1437 | f17302(a::Number) = a 1438 | f17302(a::Number, b::Number) = a + b 1439 | Compat.@dep_vectorize_1arg Real f17302 1440 | Compat.@dep_vectorize_2arg Real f17302 1441 | @test_throws MethodError f17302([1im]) 1442 | @test_throws MethodError f17302([1im], [1im]) 1443 | mktemp() do fname, f 1444 | redirect_stderr(f) do 1445 | @test f17302([1.0]) == [1.0] 1446 | @test f17302(1.0, [1]) == [2.0] 1447 | @test f17302([1.0], 1) == [2.0] 1448 | @test f17302([1.0], [1]) == [2.0] 1449 | end 1450 | end 1451 | 1452 | # 0.5.0-dev+4677 1453 | for A in (Hermitian(randn(5,5) + 10I), 1454 | Symmetric(randn(5,5) + 10I), 1455 | Symmetric(randn(5,5) + 10I, :L)) 1456 | F = cholfact(A) 1457 | @test F[:U]'F[:U] ≈ A 1458 | @test F[:L]*F[:L]' ≈ A 1459 | 1460 | Ac = copy(A) 1461 | F = cholfact!(Ac) 1462 | @test F[:U]'F[:U] ≈ A 1463 | @test F[:L]*F[:L]' ≈ A 1464 | 1465 | @test istriu(chol(A)) 1466 | @test chol(A) ≈ F[:U] 1467 | 1468 | F = cholfact(A, Val{true}) 1469 | @test F[:U]'F[:U] ≈ A[F[:p], F[:p]] 1470 | @test F[:L]*F[:L]' ≈ A[F[:p], F[:p]] 1471 | Ac = copy(A) 1472 | F = cholfact!(Ac, Val{true}) 1473 | @test F[:U]'F[:U] ≈ A[F[:p], F[:p]] 1474 | @test F[:L]*F[:L]' ≈ A[F[:p], F[:p]] 1475 | end 1476 | 1477 | types = [ 1478 | Bool, 1479 | Float16, 1480 | Float32, 1481 | Float64, 1482 | Int128, 1483 | Int16, 1484 | Int32, 1485 | Int64, 1486 | Int8, 1487 | UInt16, 1488 | UInt32, 1489 | UInt64, 1490 | UInt8, 1491 | ] 1492 | for T in types 1493 | # julia#18510, Nullable constructors 1494 | x = @compat Nullable(one(T), true) 1495 | @test isnull(x) === false 1496 | @test isa(x.value, T) 1497 | @test eltype(x) === T 1498 | 1499 | x = @compat Nullable{T}(one(T), true) 1500 | y = @compat Nullable{Any}(one(T), true) 1501 | @test isnull(x) === false 1502 | @test isnull(y) === false 1503 | @test isa(x.value, T) 1504 | @test eltype(x) === T 1505 | @test eltype(y) === Any 1506 | 1507 | x = @compat Nullable{T}(one(T), false) 1508 | y = @compat Nullable{Any}(one(T), false) 1509 | @test isnull(x) === true 1510 | @test isnull(y) === true 1511 | @test eltype(x) === T 1512 | @test eltype(y) === Any 1513 | 1514 | x = @compat Nullable(one(T), false) 1515 | @test isnull(x) === true 1516 | @test eltype(x) === T 1517 | 1518 | x = @compat Nullable{T}() 1519 | @test isnull(x) === true 1520 | @test eltype(x) === T 1521 | 1522 | # julia#18484, generic isnull, unsafe_get 1523 | a = one(T) 1524 | x = @compat Nullable(a, true) 1525 | @test isequal(unsafe_get(x), a) 1526 | 1527 | x = @compat Nullable{Array{T}}() 1528 | @test_throws UndefRefError unsafe_get(x) 1529 | end 1530 | 1531 | @test xor(1,5) == 4 1532 | @test 1 ⊻ 5 == 4 1533 | 1534 | # julia#19246 1535 | @test numerator(1//2) === 1 1536 | @test denominator(1//2) === 2 1537 | 1538 | # julia#19088 1539 | let io = IOBuffer() 1540 | write(io, "aaa") 1541 | @test take!(io) == UInt8['a', 'a', 'a'] 1542 | write(io, "bbb") 1543 | @test String(take!(io)) == "bbb" 1544 | end 1545 | 1546 | # julia#17510 1547 | let x = [1,2,3] 1548 | @compat x .= [3,4,5] 1549 | @test x == [3,4,5] 1550 | @compat x .= x .== 4 1551 | @test x == [0,1,0] 1552 | @compat x .= 7 1553 | @test x == [7,7,7] 1554 | end 1555 | 1556 | let s = "Koala test: 🐨" 1557 | @test transcode(UInt16, s) == UInt16[75,111,97,108,97,32,116,101,115,116,58,32,55357,56360] 1558 | @test transcode(UInt32, s) == UInt32[75,111,97,108,97,32,116,101,115,116,58,32,128040] 1559 | for T in (UInt8,UInt16,UInt32,Cwchar_t) 1560 | @test transcode(Compat.String, transcode(T, s)) == s 1561 | @test transcode(UInt8, transcode(T, s)) == Vector{UInt8}(s) 1562 | @test transcode(T, s) == transcode(T, Vector{UInt8}(s)) == transcode(T, transcode(T, s)) 1563 | end 1564 | end 1565 | 1566 | # julia#17155, tests from Base Julia 1567 | @test (uppercase∘hex)(239487) == "3A77F" 1568 | let str = randstring(20) 1569 | @test filter(!isupper, str) == replace(str, r"[A-Z]", "") 1570 | @test filter(!islower, str) == replace(str, r"[a-z]", "") 1571 | end 1572 | 1573 | # julia#19950, tests from Base (#20028) 1574 | for T in (Float16, Float32, Float64, BigFloat, Int8, Int16, Int32, Int64, Int128, 1575 | BigInt, UInt8, UInt16, UInt32, UInt64, UInt128) 1576 | @test iszero(T(0)) 1577 | @test iszero(Complex{T}(0)) 1578 | if T<:Integer 1579 | @test iszero(Rational{T}(0)) 1580 | end 1581 | if T<:AbstractFloat 1582 | @test iszero(T(-0.0)) 1583 | @test iszero(Complex{T}(-0.0)) 1584 | end 1585 | end 1586 | @test !iszero([0, 1, 2, 3]) 1587 | @test iszero([0, 0, 0, 0]) 1588 | 1589 | x = view(1:10, 2:4) 1590 | D = Diagonal(x) 1591 | @test D[1,1] == 2 1592 | @test D[3,3] == 4 1593 | A = view(rand(5,5), 1:3, 1:3) 1594 | @test D*A == Diagonal(copy(x)) * copy(A) 1595 | @test A*D == copy(A) * Diagonal(copy(x)) 1596 | 1597 | # julia#17623 1598 | @static if VERSION >= v"0.5.0-dev+5509" # To work around unsupported syntax on Julia 0.4 1599 | @test [true, false] .& [true, true] == [true, false] 1600 | @test [true, false] .| [true, true] == [true, true] 1601 | end 1602 | 1603 | # julia#20022 1604 | @test !Compat.isapprox(NaN, NaN) 1605 | @test Compat.isapprox(NaN, NaN, nans=true) 1606 | -------------------------------------------------------------------------------- /src/Compat.jl: -------------------------------------------------------------------------------- 1 | VERSION >= v"0.4.0-dev+6521" && __precompile__() 2 | 3 | module Compat 4 | 5 | using Base.Meta 6 | 7 | """Get just the function part of a function declaration.""" 8 | withincurly(ex) = isexpr(ex, :curly) ? ex.args[1] : ex 9 | 10 | if VERSION < v"0.4.0-dev+2254" 11 | immutable Val{T} end 12 | export Val 13 | end 14 | 15 | if VERSION < v"0.4.0-dev+1419" 16 | export UInt, UInt8, UInt16, UInt32, UInt64, UInt128 17 | const UInt = Uint 18 | const UInt8 = Uint8 19 | const UInt16 = Uint16 20 | const UInt32 = Uint32 21 | const UInt64 = Uint64 22 | const UInt128 = Uint128 23 | end 24 | 25 | if VERSION < v"0.4.0-dev+4603" 26 | # used for C string arguments to ccall 27 | # (in Julia 0.4, these types also check for embedded NUL chars) 28 | const Cstring = Ptr{UInt8} 29 | const Cwstring = Ptr{Cwchar_t} 30 | export Cstring, Cwstring 31 | end 32 | 33 | if VERSION < v"0.4.0-dev+2340" 34 | const base64encode = base64 35 | export base64encode 36 | end 37 | 38 | if VERSION >= v"0.4.0-dev+3184" 39 | include("ngenerate.jl") 40 | using .CompatCartesian 41 | export @ngenerate, @nsplat 42 | end 43 | 44 | if VERSION < v"0.4.0-dev+1624" 45 | eachindex(A::AbstractArray) = 1:length(A) 46 | eachindex(a::Associative) = Base.KeyIterator(a) 47 | export eachindex 48 | end 49 | 50 | if VERSION < v"0.4.0-dev+1387" 51 | typealias AbstractString Base.String 52 | export AbstractString 53 | end 54 | 55 | if VERSION < v"0.4.0-dev+3324" 56 | typealias AssertionError ErrorException 57 | export AssertionError 58 | end 59 | 60 | if VERSION < v"0.4.0-dev+412" 61 | eval(Base, :(const IPAddr = IpAddr)) 62 | end 63 | 64 | if VERSION < v"0.4.0-dev+2197" 65 | Base.IPv4(ipstr::AbstractString) = Base.parseipv4(ipstr) 66 | Base.IPv6(ipstr::AbstractString) = Base.parseipv6(ipstr) 67 | end 68 | 69 | if VERSION < v"0.4.0-dev+2200" 70 | function Base.isless{T<:Base.IPAddr}(a::T, b::T) 71 | return isless(a.host, b.host) 72 | end 73 | end 74 | 75 | if VERSION < v"0.4.0-dev+980" 76 | macro Dict(pairs...) 77 | esc(Expr(:dict, pairs...)) 78 | end 79 | macro AnyDict(pairs...) 80 | esc(Expr(:typed_dict, :(Any=>Any), pairs...)) 81 | end 82 | 83 | Base.Dict(kv) = dict_with_eltype(kv, eltype(kv)) 84 | dict_with_eltype{K,V}(kv, ::Type{(K,V)}) = Dict{K,V}(kv) 85 | dict_with_eltype(kv, t) = Dict{Any,Any}(kv) 86 | else 87 | macro Dict(pairs...) 88 | esc(Expr(:call, :Dict, pairs...)) 89 | end 90 | macro AnyDict(pairs...) 91 | esc(Expr(:call, :(Base.AnyDict), pairs...)) 92 | end 93 | end 94 | 95 | import Base: round, ceil, floor, trunc 96 | if VERSION < v"0.4.0-dev+1827" 97 | for (fnew,fold) in ((:round, :iround), (:ceil, :iceil), (:floor, :ifloor), (:trunc, :itrunc)) 98 | @eval begin 99 | ($fnew){T<:Integer}(::Type{T}, x::Integer) = convert(T, x) # ambiguity resolution with digits/base version, not all old methods defined 100 | ($fnew){T<:Integer}(::Type{T}, x::Real) = ($fold)(T, x) 101 | ($fnew){T<:Integer}(::Type{T}, x::Rational) = convert(T, ($fold)(x)) # no e.g. iround(::Type{T}, x::Rational) is defined in 0.3 102 | function ($fnew){T,R}(::Type{T}, x::AbstractArray{R,1}) 103 | [ ($fnew)(T, x[i])::T for i = 1:length(x) ] 104 | end 105 | function ($fnew){T,R}(::Type{T}, x::AbstractArray{R,2}) 106 | [ ($fnew)(T, x[i,j])::T for i = 1:size(x,1), j = 1:size(x,2) ] 107 | end 108 | function ($fnew){T}(::Type{T}, x::AbstractArray) 109 | reshape([ ($fnew)(T, x[i])::T for i = 1:length(x) ], size(x)) 110 | end 111 | end 112 | end 113 | end 114 | 115 | if VERSION < v"0.4.0-dev+838" 116 | Base.rem{T<:Integer}(n::Integer, ::Type{T}) = convert(T, n) 117 | elseif VERSION < v"0.4.0-dev+1037" 118 | Base.rem{T<:Integer}(n::Integer, ::Type{T}) = itrunc(T, n) 119 | elseif VERSION < v"0.4.0-dev+1039" 120 | Base.rem{T<:Integer}(n::Integer, ::Type{T}) = mod(n, T) 121 | end 122 | 123 | if VERSION < v"0.4.0-dev+2014" 124 | sizehint! = Base.sizehint 125 | export sizehint! 126 | end 127 | 128 | if VERSION < v"0.4.0-dev+3413" 129 | # based on pipe in base/process.jl: 130 | import Base: AbstractCmd, Redirectable 131 | function pipeline(cmd::AbstractCmd; stdin=nothing, stdout=nothing, stderr=nothing, append::Bool=false) 132 | if append && stdout === nothing && stderr === nothing 133 | error("append set to true, but no output redirections specified") 134 | end 135 | if stdin !== nothing 136 | cmd = stdin |> cmd 137 | end 138 | if stdout !== nothing 139 | cmd = append ? cmd >> stdout : cmd |> stdout 140 | end 141 | if stderr !== nothing 142 | cmd = append ? cmd .>> stderr : cmd .> stderr 143 | end 144 | return cmd 145 | end 146 | pipeline(cmd::AbstractCmd, dest) = pipeline(cmd, stdout=dest) 147 | pipeline(src::Union(Redirectable,AbstractString), cmd::AbstractCmd) = pipeline(cmd, stdin=src) 148 | pipeline(a, b, c, d...) = pipeline(pipeline(a,b), c, d...) 149 | export pipeline 150 | elseif VERSION < v"0.4.0-dev+6987" 151 | const pipeline = Base.pipe 152 | export pipeline 153 | end 154 | 155 | if VERSION < v"0.5.0-dev+961" 156 | export walkdir 157 | 158 | function walkdir(root; topdown=true, follow_symlinks=false, onerror=throw) 159 | content = nothing 160 | try 161 | content = readdir(root) 162 | catch err 163 | isa(err, SystemError) || throw(err) 164 | onerror(err) 165 | #Need to return an empty task to skip the current root folder 166 | return Task(()->()) 167 | end 168 | dirs = Array(eltype(content), 0) 169 | files = Array(eltype(content), 0) 170 | for name in content 171 | if isdir(joinpath(root, name)) 172 | push!(dirs, name) 173 | else 174 | push!(files, name) 175 | end 176 | end 177 | 178 | function _it() 179 | if topdown 180 | produce(root, dirs, files) 181 | end 182 | for dir in dirs 183 | path = joinpath(root,dir) 184 | if follow_symlinks || !islink(path) 185 | for (root_l, dirs_l, files_l) in walkdir(path, topdown=topdown, follow_symlinks=follow_symlinks, onerror=onerror) 186 | produce(root_l, dirs_l, files_l) 187 | end 188 | end 189 | end 190 | if !topdown 191 | produce(root, dirs, files) 192 | end 193 | end 194 | Task(_it) 195 | end 196 | end 197 | 198 | function rewrite_show(ex) 199 | if isexpr(ex, :call) 200 | Expr(:call, rewrite_show(ex.args[1]), ex.args[2:end]...) 201 | elseif isexpr(ex, :curly) 202 | Expr(:curly, rewrite_show(ex.args[1]), ex.args[2:end]...) 203 | else 204 | :(Base.writemime) 205 | end 206 | end 207 | 208 | function rewrite_dict(ex) 209 | length(ex.args) == 1 && return ex 210 | 211 | f = ex.args[1] 212 | if isexpr(f, :curly) 213 | newex = Expr(:typed_dict, :($(f.args[2])=>$(f.args[3]))) 214 | else 215 | newex = Expr(:dict) 216 | end 217 | 218 | for i = 2:length(ex.args) 219 | pair = ex.args[i] 220 | !isexpr(pair, :(=>)) && return ex 221 | push!(newex.args, pair) 222 | end 223 | newex 224 | end 225 | 226 | function rewrite_ordereddict(ex) 227 | length(ex.args) == 1 && return ex 228 | 229 | f = ex.args[1] 230 | newex = Expr(:call, f, :[]) 231 | 232 | for i = 2:length(ex.args) 233 | pair = ex.args[i] 234 | !isexpr(pair, :(=>)) && return ex 235 | push!(newex.args[2].args, Expr(:tuple, pair.args...)) 236 | end 237 | 238 | newex 239 | end 240 | 241 | # rewrite Julia 0.4-style split or rsplit (str, splitter; kws...) 242 | # into 0.2/0.3-style positional arguments 243 | function rewrite_split(ex, f) 244 | limit = nothing 245 | keep = nothing 246 | for i in 4:length(ex.args) 247 | if isexpr(ex.args[i], :kw) 248 | kw = ex.args[i].args 249 | if kw[1] == :limit 250 | limit = kw[2] 251 | elseif kw[1] == :keep 252 | keep = kw[2] 253 | end 254 | end 255 | end 256 | if limit == nothing 257 | if keep == nothing 258 | return Expr(:call, f, ex.args[2], ex.args[3]) 259 | else 260 | return Expr(:call, f, ex.args[2], ex.args[3], keep) 261 | end 262 | else 263 | if keep == nothing 264 | return Expr(:call, f, ex.args[2], ex.args[3], limit) 265 | else 266 | return Expr(:call, f, ex.args[2], ex.args[3], limit, keep) 267 | end 268 | end 269 | end 270 | 271 | # rewrites all subexpressions of the form `a => b` to `(a, b)` 272 | function rewrite_pairs_to_tuples!(expr::Expr) 273 | if expr.head == :(=>) 274 | expr.head = :tuple 275 | end 276 | for subexpr in expr.args 277 | isa(subexpr, Expr) && rewrite_pairs_to_tuples!(subexpr) 278 | end 279 | return expr 280 | end 281 | 282 | function is_quote_symbol(ex::ANY, val::Symbol) 283 | if isa(ex, QuoteNode) 284 | return (ex::QuoteNode).value === val 285 | elseif isa(ex, Expr) 286 | ex = ex::Expr 287 | return ex.head === :quote && length(ex.args) == 1 && ex.args[1] === val 288 | end 289 | return false 290 | end 291 | 292 | # rewrites accesses to IOContext dicts 293 | function rewrite_iocontext!(expr::Expr) 294 | args = expr.args 295 | nargs = length(args) 296 | if nargs == 4 && expr.head === :call && args[1] === :get && args[4] === false 297 | key = args[3] 298 | if is_quote_symbol(key, :limit) || is_quote_symbol(key, :compact) 299 | if VERSION >= v"0.5.0-dev+1936" && VERSION < v"0.5.0-dev+4305" 300 | args[1] = :(Base.limit_output) 301 | deleteat!(args, 3:4) 302 | elseif VERSION < v"0.5.0-dev+1936" 303 | expr.head = :quote 304 | args[1] = false 305 | deleteat!(args, 3:4) 306 | end 307 | elseif is_quote_symbol(key, :multiline) 308 | if VERSION < v"0.5.0-dev+4305" 309 | expr.head = :quote 310 | args[1] = false 311 | deleteat!(args, 3:4) 312 | end 313 | end 314 | end 315 | end 316 | 317 | if VERSION < v"0.4.0-dev+707" 318 | macro inline(ex) 319 | esc(ex) 320 | end 321 | end 322 | 323 | if VERSION < v"0.4.0-dev+2056" 324 | macro noinline(ex) 325 | esc(ex) 326 | end 327 | end 328 | 329 | if VERSION < v"0.4.0-dev+2440" 330 | bitrand(r::AbstractRNG, dims::Dims) = rand!(r, BitArray(dims)) 331 | bitrand(r::AbstractRNG, dims::Int...) = rand!(r, BitArray(dims)) 332 | bitrand(dims::Dims) = rand!(BitArray(dims)) 333 | bitrand(dims::Int...) = rand!(BitArray(dims)) 334 | export bitrand 335 | Base.rand(::Type{Bool}) = randbool() 336 | end 337 | 338 | if VERSION < v"0.4.0-dev+2485" 339 | startswith = Base.beginswith 340 | export startswith 341 | end 342 | 343 | if VERSION < v"0.4.0-dev+3609" 344 | fieldnames(x::DataType) = collect(x.names) 345 | function fieldnames(v) 346 | t = typeof(v) 347 | if !isa(t, DataType) 348 | throw(ArgumentError("cannot call fieldnames() on a non-composite type")) 349 | end 350 | return fieldnames(t) 351 | end 352 | export fieldnames 353 | end 354 | 355 | if VERSION < v"0.4.0-dev+3874" 356 | Base.parse{T<:Integer}(::Type{T}, c::Char) = parseint(T, c) 357 | Base.parse{T<:Integer}(::Type{T}, c::Char, base::Integer) = parseint(T, c, base) 358 | Base.parse{T<:Integer}(::Type{T}, s::AbstractString) = parseint(T, s) 359 | Base.parse{T<:Integer}(::Type{T}, s::AbstractString, base::Integer) = parseint(T, s, base) 360 | Base.parse{T<:Union(Float32,Float64)}(::Type{T}, s::AbstractString) = parsefloat(T, s) 361 | end 362 | 363 | if VERSION < v"0.4.0-dev+4539" 364 | Base.parse(::Type{BigFloat}, s::AbstractString) = BigFloat(s) 365 | end 366 | 367 | # JuliaLang/julia#10543 368 | if !isdefined(Base, :tryparse) 369 | function tryparse{T}(::Type{T}, args...) 370 | try 371 | Nullable(Base.parse(T, args...)) 372 | catch 373 | Nullable{T}() 374 | end 375 | end 376 | end 377 | 378 | if VERSION < v"0.4.0-dev+3710" 379 | const unsafe_convert = Base.convert 380 | else 381 | import Base.unsafe_convert 382 | end 383 | 384 | if VERSION < v"0.4.0-dev+3732" 385 | const calltypes = Dict{Symbol,Symbol}() 386 | for (k,v) in [(:Integer,:integer), 387 | (:Signed,:signed), 388 | (:Unsigned,:unsigned), 389 | (:Int,:int), 390 | (:Int8,:int8), 391 | (:Int16,:int16), 392 | (:Int32,:int32), 393 | (:Int64,:int64), 394 | (:Int128,:int128), 395 | (:UInt,:uint), 396 | (:UInt8,:uint8), 397 | (:UInt16,:uint16), 398 | (:UInt32,:uint32), 399 | (:UInt64,:uint64), 400 | (:UInt128,:uint128), 401 | (:Float16,:float16), 402 | (:Float32,:float32), 403 | (:Float64,:float64), 404 | (:Complex32,:complex32), 405 | (:Complex64,:complex64), 406 | (:Complex128,:complex128), 407 | (:Char,:char), 408 | (:Bool,:bool), 409 | (:Symbol,:symbol)] 410 | calltypes[k] = v 411 | end 412 | elseif VERSION < v"0.5.0-dev+3831" 413 | Base.Symbol(args...) = symbol(args...)::Symbol 414 | end 415 | 416 | if VERSION < v"0.5.0-dev+2396" 417 | function new_style_call_overload(ex::Expr) 418 | # Not a function call 419 | ((ex.head === :(=) || ex.head === :function) && 420 | length(ex.args) == 2 && isexpr(ex.args[1], :call)) || return false 421 | callee = (ex.args[1]::Expr).args[1] 422 | # Only Expr function name can be call overload 423 | isa(callee, Expr) || return false 424 | callee = callee::Expr 425 | # (a::A)() = ... 426 | callee.head === :(::) && return true 427 | # The other case is with type parameter. 428 | # Filter out everything without one. 429 | (callee.head === :curly && length(callee.args) >= 1) || return false 430 | # Check what the type parameter applies to is a Expr(:(::)) 431 | return isexpr(callee.args[1], :(::)) 432 | end 433 | else 434 | new_style_call_overload(ex::Expr) = false 435 | end 436 | 437 | istopsymbol(ex, mod, sym) = ex in (sym, Expr(:(.), mod, Expr(:quote, sym))) 438 | 439 | if VERSION < v"0.5.0-dev+4002" 440 | typealias Array0D{T} Array{T,0} 441 | @inline broadcast_getindex(arg, idx) = arg[(idx - 1) % length(arg) + 1] 442 | # Optimize for single element 443 | @inline broadcast_getindex(arg::Number, idx) = arg 444 | @inline broadcast_getindex(arg::Array0D, idx) = arg[1] 445 | 446 | # If we know from syntax level that we don't need wrapping 447 | @inline broadcast_getindex_naive(arg, idx) = arg[idx] 448 | @inline broadcast_getindex_naive(arg::Number, idx) = arg 449 | @inline broadcast_getindex_naive(arg::Array0D, idx) = arg[1] 450 | 451 | # For vararg support 452 | @inline getindex_vararg(idx) = () 453 | @inline getindex_vararg(idx, arg1) = (broadcast_getindex(arg1, idx),) 454 | @inline getindex_vararg(idx, arg1, arg2) = 455 | (broadcast_getindex(arg1, idx), broadcast_getindex(arg2, idx)) 456 | @inline getindex_vararg(idx, arg1, arg2, arg3, args...) = 457 | (broadcast_getindex(arg1, idx), broadcast_getindex(arg2, idx), 458 | broadcast_getindex(arg3, idx), getindex_vararg(idx, args...)...) 459 | 460 | @inline getindex_naive_vararg(idx) = () 461 | @inline getindex_naive_vararg(idx, arg1) = 462 | (broadcast_getindex_naive(arg1, idx),) 463 | @inline getindex_naive_vararg(idx, arg1, arg2) = 464 | (broadcast_getindex_naive(arg1, idx), 465 | broadcast_getindex_naive(arg2, idx)) 466 | @inline getindex_naive_vararg(idx, arg1, arg2, arg3, args...) = 467 | (broadcast_getindex_naive(arg1, idx), 468 | broadcast_getindex_naive(arg2, idx), 469 | broadcast_getindex_naive(arg3, idx), 470 | getindex_naive_vararg(idx, args...)...) 471 | 472 | # Decide if the result should be scalar or array 473 | # `size() === ()` is not good enough since broadcasting on 474 | # a scalar should return a scalar where as broadcasting on a 0-dim 475 | # array should return a 0-dim array. 476 | @inline should_return_array(::Val{true}, args...) = Val{true}() 477 | @inline should_return_array(::Val{false}) = Val{false}() 478 | @inline should_return_array(::Val{false}, arg1) = Val{false}() 479 | @inline should_return_array(::Val{false}, arg1::AbstractArray) = Val{true}() 480 | @inline should_return_array(::Val{false}, arg1::AbstractArray, 481 | arg2::AbstractArray) = Val{true}() 482 | @inline should_return_array(::Val{false}, arg1, 483 | arg2::AbstractArray) = Val{true}() 484 | @inline should_return_array(::Val{false}, arg1::AbstractArray, 485 | arg2) = Val{true}() 486 | @inline should_return_array(::Val{false}, arg1, arg2) = Val{false}() 487 | @inline should_return_array(::Val{false}, arg1, arg2, args...) = 488 | should_return_array(should_return_array(Val{false}(), arg1, arg2), 489 | args...) 490 | 491 | @inline broadcast_return(res1d, shp, ret_ary::Val{false}) = res1d[1] 492 | @inline broadcast_return(res1d, shp, ret_ary::Val{true}) = reshape(res1d, shp) 493 | 494 | @inline need_full_getindex(shp) = false 495 | @inline need_full_getindex(shp, arg1::Number) = false 496 | @inline need_full_getindex(shp, arg1::Array0D) = false 497 | @inline need_full_getindex(shp, arg1) = shp != size(arg1) 498 | @inline need_full_getindex(shp, arg1, arg2) = 499 | need_full_getindex(shp, arg1) || need_full_getindex(shp, arg2) 500 | @inline need_full_getindex(shp, arg1, arg2, arg3, args...) = 501 | need_full_getindex(shp, arg1, arg2) || need_full_getindex(shp, arg3) || 502 | need_full_getindex(shp, args...) 503 | 504 | function rewrite_broadcast(f, args) 505 | nargs = length(args) 506 | # This actually allows multiple splatting..., 507 | # which is now allowed on master. 508 | # The previous version that simply calls broadcast so removing that 509 | # will be breaking. Oh, well.... 510 | is_vararg = Bool[isexpr(args[i], :...) for i in 1:nargs] 511 | names = [gensym("broadcast") for i in 1:nargs] 512 | new_args = [is_vararg[i] ? Expr(:..., names[i]) : names[i] 513 | for i in 1:nargs] 514 | # Optimize for common case where we know the index doesn't need 515 | # any wrapping 516 | naive_getidx_for = function (i, idxvar) 517 | if is_vararg[i] 518 | Expr(:..., :($Compat.getindex_naive_vararg($idxvar, 519 | $(names[i])...))) 520 | else 521 | :($Compat.broadcast_getindex_naive($(names[i]), $idxvar)) 522 | end 523 | end 524 | always_naive = nargs == 1 && !is_vararg[1] 525 | getidx_for = if always_naive 526 | naive_getidx_for 527 | else 528 | function (i, idxvar) 529 | if is_vararg[i] 530 | Expr(:..., :($Compat.getindex_vararg($idxvar, 531 | $(names[i])...))) 532 | else 533 | :($Compat.broadcast_getindex($(names[i]), $idxvar)) 534 | end 535 | end 536 | end 537 | @gensym allidx 538 | @gensym newshape 539 | @gensym res1d 540 | @gensym idx 541 | @gensym ret_ary 542 | 543 | res1d_expr = quote 544 | $res1d = [$f($([naive_getidx_for(i, idx) for i in 1:nargs]...)) 545 | for $idx in $allidx] 546 | end 547 | if !always_naive 548 | res1d_expr = quote 549 | if $Compat.need_full_getindex($newshape, $(new_args...)) 550 | $res1d = [$f($([getidx_for(i, idx) for i in 1:nargs]...)) 551 | for $idx in $allidx] 552 | else 553 | $res1d_expr 554 | end 555 | end 556 | end 557 | 558 | return quote 559 | # The `local` makes sure type inference can infer the type even 560 | # in global scope as long as the input is type stable 561 | local $(names...) 562 | $([:($(names[i]) = $(is_vararg[i] ? args[i].args[1] : args[i])) 563 | for i in 1:nargs]...) 564 | local $newshape = $(Base.Broadcast).broadcast_shape($(new_args...)) 565 | # `eachindex` is not generic enough 566 | local $allidx = 1:prod($newshape) 567 | local $ret_ary = $Compat.should_return_array(Val{false}(), 568 | $(new_args...)) 569 | local $res1d 570 | $res1d_expr 571 | $Compat.broadcast_return($res1d, $newshape, $ret_ary) 572 | end 573 | end 574 | end 575 | 576 | function _compat(ex::Expr) 577 | if ex.head === :call 578 | f = ex.args[1] 579 | if VERSION < v"0.4.0-dev+980" && (f === :Dict || (isexpr(f, :curly) && length(f.args) == 3 && f.args[1] === :Dict)) 580 | ex = rewrite_dict(ex) 581 | elseif VERSION < v"0.4.0-dev+980" && (f === :OrderedDict || (isexpr(f, :curly) && length(f.args) == 3 && f.args[1] === :OrderedDict)) 582 | ex = rewrite_ordereddict(ex) 583 | elseif VERSION < v"0.4.0-dev+129" && (f === :split || f === :rsplit) && length(ex.args) >= 4 && isexpr(ex.args[4], :kw) 584 | ex = rewrite_split(ex, f) 585 | elseif VERSION < v"0.4.0-dev+3732" && haskey(calltypes, f) && length(ex.args) > 1 586 | T = ex.args[1] 587 | if T in (:Complex32, :Complex64, :Complex128) 588 | ex = Expr(:call, calltypes[T], ex.args[2:end]...) 589 | elseif T == :Symbol 590 | ex = Expr(:call, calltypes[T], Expr(:call, :string, ex.args[2:end]...)) 591 | else 592 | ex = Expr(:(::), Expr(:call, :convert, T, ex.args[2:end]...), T) 593 | end 594 | elseif VERSION < v"0.4.0-dev+3732" && (f === :map && haskey(calltypes, ex.args[2]) && length(ex.args) > 2) 595 | ex = Expr(:call, calltypes[ex.args[2]], ex.args[3:end]...) 596 | elseif VERSION < v"0.4.0-dev+1419" && isexpr(f, :curly) && f.args[1] === :Ptr && length(ex.args) == 2 && ex.args[2] == 0 597 | ex = Expr(:call, :zero, f) 598 | elseif VERSION < v"0.4.0-dev+4356" && f === :chol 599 | s = ex.args[3] 600 | if isexpr(s, :curly) && s.args[1] === :Val 601 | ex = Expr(:call, :chol, ex.args[2], s.args[2]) 602 | end 603 | elseif VERSION < v"0.4.0-dev+4739" && isexpr(f, :curly) && (f.args[1] === :Vector || f.args[1] === :Array) 604 | if f.args[1] === :Vector && length(ex.args) == 1 605 | ex = Expr(:call, :Array, f.args[2], 0) 606 | else 607 | ex = Expr(:call, :Array, f.args[2], ex.args[2:end]...) 608 | end 609 | elseif VERSION < v"0.4.0-dev+4389" && f === :withenv 610 | rewrite_pairs_to_tuples!(ex) 611 | elseif VERSION < v"0.4.0-dev+1246" && f == :String 612 | ex = Expr(:call, :bytestring, ex.args[2:end]...) 613 | elseif VERSION < v"0.5.0-dev+4340" && length(ex.args) > 3 && 614 | istopsymbol(withincurly(ex.args[1]), :Base, :show) 615 | ex = rewrite_show(ex) 616 | elseif VERSION < v"0.6.0-dev.826" && length(ex.args) == 3 && # julia#18510 617 | istopsymbol(withincurly(ex.args[1]), :Base, :Nullable) 618 | ex = Expr(:call, f, ex.args[2], Expr(:call, :(Compat._Nullable_field2), ex.args[3])) 619 | end 620 | if VERSION < v"0.5.0-dev+4305" 621 | rewrite_iocontext!(ex) 622 | end 623 | elseif ex.head === :curly 624 | f = ex.args[1] 625 | if VERSION < v"0.4.0-dev+4319" && f === :Tuple 626 | args = ex.args[2:end] 627 | has_ellipsis = any(args) do arg 628 | isa(arg, Expr) && (arg.head === :...) 629 | end 630 | ex = if has_ellipsis 631 | Expr(:call, TopNode(:tuple), args...) 632 | else 633 | Expr(:tuple, args...) 634 | end 635 | elseif VERSION < v"0.4.0-dev+5379" && f === :Union 636 | ex = Expr(:call,:Union,ex.args[2:end]...) 637 | elseif ex == :(Ptr{Void}) 638 | # Do no change Ptr{Void} to Ptr{Nothing}: 0.4.0-dev+768 639 | return ex 640 | end 641 | elseif ex.head === :macrocall 642 | f = ex.args[1] 643 | if VERSION < v"0.4.0-dev+4387" && f === symbol("@generated") 644 | f = ex.args[2] 645 | if isexpr(f, :function) 646 | ex = Expr(:stagedfunction, f.args...) 647 | end 648 | end 649 | if VERSION < v"0.5.0-dev+2129" && f === symbol("@boundscheck") && length(ex.args) == 2 650 | # Handle 0.5 single argument @boundscheck syntax. (0.4 has a two 651 | # arguments and a very diffferent meaning). `nothing` is included 652 | # so we have a consistent return type. 653 | ex = :($(ex.args[2]); nothing) 654 | end 655 | elseif VERSION < v"0.4.0-dev+5322" && ex.head === :(::) && isa(ex.args[end], Symbol) 656 | # Replace Base.Timer with Compat.Timer2 in type declarations 657 | if istopsymbol(ex.args[end], :Base, :Timer) 658 | ex.args[end] = :(Compat.Timer2) 659 | end 660 | elseif ex.head === :quote && isa(ex.args[1], Symbol) 661 | # Passthrough 662 | return ex 663 | elseif new_style_call_overload(ex) 664 | callexpr = ex.args[1]::Expr 665 | callee = callexpr.args[1]::Expr 666 | is_kw = (length(callexpr.args) >= 2 && 667 | isexpr(callexpr.args[2], :parameters)) 668 | if callee.head === :(::) 669 | # (:function, (:call, :(:(::), <1>), <2>), ) -> 670 | # (:function, (:call, :(Base.call), :(:(::), <1>), <2>), ) 671 | unshift!(callexpr.args, :(Base.call)) 672 | else 673 | # (:function, (:call, :(curly, :(:(::), <1>), <3>), <2>), ) -> 674 | # (:function, (:call, :(curly, :(Base.call), <3>), :(:(::), <1>), <2>), ) 675 | obj = callee.args[1]::Expr 676 | callee.args[1] = :(Base.call) 677 | insert!(callexpr.args, 2, obj) 678 | end 679 | if is_kw 680 | # Expr(:parameters) is moved to the 3rd argument 681 | params = callexpr.args[3] 682 | @assert isexpr(params, :parameters) 683 | obj = callexpr.args[2] 684 | callexpr.args[2] = params 685 | callexpr.args[3] = obj 686 | end 687 | elseif VERSION < v"0.5.0-dev+4002" && ex.head == :. && length(ex.args) == 2 # 15032 688 | if isexpr(ex.args[2], :quote) && isa(ex.args[2].args[1], QuoteNode) 689 | # foo.:bar -> foo.(:bar) in older Julia 690 | return Expr(ex.head, _compat(ex.args[1]), ex.args[2].args[1]) 691 | elseif isexpr(ex.args[2], :quote) && isexpr(ex.args[2].args[1], :quote) && 692 | isa(ex.args[2].args[1].args[1], Symbol) 693 | # foo.:bar -> foo.(:bar) in older Julia 694 | return Expr(ex.head, _compat(ex.args[1]), QuoteNode(ex.args[2].args[1].args[1])) 695 | elseif isexpr(ex.args[2], :tuple) 696 | # f.(arg1, arg2...) -> broadcast(f, arg1, arg2...) 697 | return rewrite_broadcast(_compat(ex.args[1]), 698 | map(_compat, ex.args[2].args)) 699 | elseif !isa(ex.args[2], QuoteNode) && 700 | !(isexpr(ex.args[2], :quote) && isa(ex.args[2].args[1], Symbol)) 701 | # f.(arg) -> broadcast(f, arg) 702 | return rewrite_broadcast(_compat(ex.args[1]), [_compat(ex.args[2])]) 703 | end 704 | elseif ex.head === :import 705 | if VERSION < v"0.5.0-dev+4340" && length(ex.args) == 2 && ex.args[1] === :Base && ex.args[2] === :show 706 | return quote 707 | import Base.show 708 | import Base.writemime 709 | end 710 | end 711 | elseif VERSION < v"0.5.0-dev+5575" && isexpr(ex, :comparison) #17510 712 | if length(ex.args) == 3 && ex.args[2] == :.= 713 | return :(Base.broadcast!(Base.identity, $(_compat(ex.args[1])), $(_compat(ex.args[3])))) 714 | elseif length(ex.args) > 3 && ex.args[2] == :.= 715 | return :(Base.broadcast!(Base.identity, $(_compat(ex.args[1])), $(_compat(Expr(:comparison, ex.args[3:end]...))))) 716 | end 717 | end 718 | return Expr(ex.head, map(_compat, ex.args)...) 719 | end 720 | function _compat(ex::Symbol) 721 | if VERSION < v"0.4.0-dev+768" && ex === :Void 722 | return :Nothing 723 | end 724 | if VERSION < v"0.5.0-dev+1343" && (ex == :Future || ex == :RemoteChannel) 725 | return :RemoteRef 726 | end 727 | return ex 728 | end 729 | _compat(ex) = ex 730 | 731 | macro compat(ex) 732 | esc(_compat(ex)) 733 | end 734 | 735 | export @compat, @inline, @noinline 736 | 737 | if VERSION < v"0.4.0-dev+656" 738 | include("nullable.jl") 739 | end 740 | 741 | if VERSION < v"0.4.0-dev+3864" 742 | function tryparse(T::Type{Float32}, s) 743 | r = Array(T,1) 744 | float32_isvalid(s, r) ? Nullable(r[1]) : Nullable{Float32}() 745 | end 746 | 747 | function tryparse(T::Type{Float64}, s) 748 | r = Array(T,1) 749 | float64_isvalid(s, r) ? Nullable(r[1]) : Nullable{Float64}() 750 | end 751 | 752 | function tryparse{T<:Integer}(::Type{T}, s, base=10) 753 | (2 <= base <= 62) || throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $base")) 754 | try 755 | Nullable(parse(T, s, base)) 756 | catch 757 | Nullable{T}() 758 | end 759 | end 760 | export tryparse 761 | end 762 | 763 | if VERSION < v"0.4.0-dev+3844" 764 | @eval module Libc 765 | const FILE = Base.CFILE 766 | const calloc = Base.c_calloc 767 | const free = Base.c_free 768 | const malloc = Base.c_malloc 769 | const realloc = Base.c_realloc 770 | using Base: munmap, systemsleep 771 | export FILE, TmStruct, calloc, errno, flush_cstdio, free, 772 | gethostname, getpid, malloc, msync, realloc, strerror, 773 | strftime, strptime, systemsleep, time 774 | end 775 | @eval module Libdl 776 | using Base.Sys: dlext, dllist, dlpath 777 | export DL_LOAD_PATH, RTLD_DEEPBIND, RTLD_FIRST, RTLD_GLOBAL, RTLD_LAZY, 778 | RTLD_LOCAL, RTLD_NODELETE, RTLD_NOLOAD, RTLD_NOW, dlclose, dlext, 779 | dllist, dlopen, dlopen_e, dlpath, dlsym, dlsym_e, find_library 780 | end 781 | export Libc, Libdl 782 | else 783 | import Base: Libc, Libdl 784 | end 785 | 786 | if VERSION < v"0.4.0-dev+2418" 787 | function findprev(A, start) 788 | for i = start:-1:1 789 | A[i] != 0 && return i 790 | end 791 | 0 792 | end 793 | findlast(A) = findprev(A, length(A)) 794 | function findprev(A, v, start) 795 | for i = start:-1:1 796 | A[i] == v && return i 797 | end 798 | 0 799 | end 800 | findlast(A, v) = findprev(A, v, length(A)) 801 | function findprev(testf::Function, A, start) 802 | for i = start:-1:1 803 | testf(A[i]) && return i 804 | end 805 | 0 806 | end 807 | findlast(testf::Function, A) = findprev(testf, A, length(A)) 808 | export findprev, findlast 809 | end 810 | 811 | if VERSION < v"0.4.0-dev+4524" 812 | isdiag(A::AbstractMatrix) = istril(A) && istriu(A) 813 | isdiag(x::Number) = true 814 | export isdiag 815 | end 816 | 817 | if VERSION < v"0.4.0-dev+4502" 818 | keytype{K,V}(::Associative{K,V}) = K 819 | valtype{K,V}(::Associative{K,V}) = V 820 | export keytype, valtype 821 | end 822 | 823 | if VERSION < v"0.4.0-dev+2840" 824 | Base.qr(A, ::Type{Val{true}}; thin::Bool=true) = 825 | Base.qr(A, pivot=true, thin=thin) 826 | Base.qr(A, ::Type{Val{false}}; thin::Bool=true) = 827 | Base.qr(A, pivot=false, thin=thin) 828 | Base.qrfact(A, ::Type{Val{true}}) = Base.qrfact(A, pivot=true) 829 | Base.qrfact(A, ::Type{Val{false}}) = Base.qrfact(A, pivot=false) 830 | Base.qrfact!(A, ::Type{Val{true}}) = Base.qrfact!(A, pivot=true) 831 | Base.qrfact!(A, ::Type{Val{false}}) = Base.qrfact!(A, pivot=false) 832 | end 833 | 834 | if VERSION < v"0.4.0-dev+2823" 835 | fma(x::Number,y::Number,z::Number) = x*y + z 836 | export fma 837 | end 838 | 839 | if VERSION < v"0.4.0-dev+2861" 840 | muladd(x::Number,y::Number,z::Number) = x*y + z 841 | export muladd 842 | end 843 | 844 | if VERSION < v"0.4.0-dev+4734" 845 | function is_valid_utf32(str::Union(Vector{Char}, Vector{UInt32})) 846 | for i=1:length(str) 847 | @inbounds if !is_valid_char(reinterpret(UInt32, str[i])) ; return false ; end 848 | end 849 | return true 850 | end 851 | is_valid_utf32(str::UTF32String) = is_valid_utf32(str.data) 852 | export is_valid_utf32 853 | end 854 | 855 | if VERSION < v"0.4.0-dev+4939" 856 | import Base.isvalid 857 | isvalid(ch::Char) = is_valid_char(ch) 858 | isvalid(str::ASCIIString) = is_valid_ascii(str) 859 | isvalid(str::UTF8String) = is_valid_utf8(str) 860 | isvalid(str::UTF16String) = is_valid_utf16(str) 861 | isvalid(str::UTF32String) = is_valid_utf32(str) 862 | isvalid(::Type{Char}, ch) = is_valid_char(ch) 863 | isvalid(::Type{ASCIIString}, str) = is_valid_ascii(str) 864 | isvalid(::Type{UTF8String}, str) = is_valid_utf8(str) 865 | isvalid(::Type{UTF16String}, str) = is_valid_utf16(str) 866 | isvalid(::Type{UTF32String}, str) = is_valid_utf32(str) 867 | export isvalid 868 | end 869 | 870 | if VERSION < v"0.4.0-dev+5322" 871 | include("timer.jl") 872 | end 873 | 874 | if VERSION < v"0.4.0-dev+5688" 875 | typealias Irrational MathConst 876 | @eval const $(symbol("@irrational")) = getfield(Base, symbol("@math_const")) 877 | export Irrational 878 | else 879 | import Base.@irrational 880 | end 881 | 882 | if VERSION < v"0.4.0-dev+5305" 883 | function Base.gc_enable(on::Bool) 884 | state = ccall(:jl_gc_is_enabled, Cint, ()) != 0 885 | on ? gc_enable() : gc_disable() 886 | state 887 | end 888 | end 889 | 890 | if VERSION < v"0.4.0-dev+5697" 891 | @eval module Mmap 892 | function mmap{T,N}(io::IO, 893 | ::Type{Array{T,N}}=Vector{UInt8}, 894 | dims::NTuple{N,Integer}=(div(filesize(io)-position(io),sizeof(T)),), 895 | offset::Integer=position(io); grow::Bool=true, shared::Bool=true) 896 | mmap_array(T,dims,io::IO,convert(FileOffset,offset)) 897 | end 898 | 899 | mmap{T<:Array,N}(file::String, 900 | ::Type{T}=Vector{UInt8}, 901 | dims::NTuple{N,Integer}=(div(filesize(file),sizeof(eltype(T))),), 902 | offset::Integer=0; grow::Bool=true, shared::Bool=true) = 903 | open(io->mmap(io, T, dims, offset; grow=grow, shared=shared), file, isfile(file) ? "r+" : "w+")::Array{eltype(T),N} 904 | 905 | # using a length argument instead of dims 906 | mmap{T<:Array}(io::IO, ::Type{T}, len::Integer, offset::Integer=position(io); grow::Bool=true, shared::Bool=true) = 907 | mmap(io, T, (len,), offset; grow=grow, shared=shared) 908 | mmap{T<:Array}(file::String, ::Type{T}, len::Integer, offset::Integer=0; grow::Bool=true, shared::Bool=true) = 909 | open(io->mmap(io, T, (len,), offset; grow=grow, shared=shared), file, isfile(file) ? "r+" : "w+")::Vector{eltype(T)} 910 | 911 | # constructors for non-file-backed (anonymous) mmaps 912 | mmap{T<:Array,N}(::Type{T}, dims::NTuple{N,Integer}; shared::Bool=true) = mmap(Anonymous(), T, dims, 0; shared=shared) 913 | mmap{T<:Array}(::Type{T}, i::Integer...; shared::Bool=true) = mmap(Anonymous(), T, convert(Tuple{Vararg{Int}},i), 0; shared=shared) 914 | end 915 | export Mmap 916 | end 917 | 918 | if VERSION < v"0.4.0-dev+6521" 919 | __precompile__(isprecompilable::Bool = true) = nothing 920 | export __precompile__ 921 | end 922 | 923 | if VERSION < v"0.4.0-dev+6506" 924 | include_dependency(::AbstractString) = nothing 925 | export include_dependency 926 | end 927 | 928 | if VERSION < v"0.4.0-dev+6425" 929 | typealias AbstractFloat FloatingPoint 930 | export AbstractFloat 931 | end 932 | 933 | if VERSION < v"0.4.0-dev+6068" 934 | Base.real{T<:Real}(::Type{T}) = T 935 | Base.real{T<:Real}(::Type{Complex{T}}) = T 936 | end 937 | 938 | # Use as Compat.Linspace to get improved linspace in both 0.3 and 0.4 939 | if VERSION < v"0.4.0-dev+6110" 940 | include("linspace.jl") 941 | const linspace = LazyLinSpace.linspace 942 | else 943 | const linspace = Base.linspace 944 | end 945 | 946 | if VERSION < v"0.4.0-dev+436" 947 | export UDPSocket 948 | const UDPSocket = UdpSocket 949 | export TCPSocket 950 | const TCPSocket = Base.TcpSocket 951 | end 952 | 953 | if VERSION < v"0.4.0-dev+2340" 954 | export Base64EncodePipe 955 | const Base64EncodePipe = Base64Pipe 956 | end 957 | 958 | if VERSION < v"0.4.0-dev+3837" 959 | export OutOfMemoryError 960 | const OutOfMemoryError = MemoryError 961 | end 962 | 963 | 964 | if VERSION < v"0.4.0-dev+4389" 965 | export withenv 966 | # temporarily set and then restore an environment value 967 | function withenv(f::Function, keyvals...) 968 | old = Dict{typeof(first(first(keyvals))),Any}() 969 | for (key,val) in keyvals 970 | old[key] = get(ENV, key, nothing) 971 | val !== nothing ? (ENV[key]=val) : Base._unsetenv(key) 972 | end 973 | try f() 974 | finally 975 | for (key,val) in old 976 | val !== nothing ? (ENV[key]=val) : Base._unsetenv(key) 977 | end 978 | end 979 | end 980 | withenv(f::Function) = f() # handle empty keyvals case; see #10853 981 | end 982 | 983 | import Base: remotecall, remotecall_fetch, remotecall_wait, remote_do 984 | if VERSION < v"0.5.0-dev+431" 985 | for f in (:remotecall, :remotecall_fetch, :remotecall_wait, :remote_do) 986 | @eval begin 987 | ($f)(f::Function, w::Base.LocalProcess, args...) = ($f)(w, f, args...) 988 | ($f)(f::Function, w::Base.Worker, args...) = ($f)(w, f, args...) 989 | ($f)(f::Function, id::Integer, args...) = ($f)(id, f, args...) 990 | end 991 | end 992 | end 993 | 994 | if VERSION < v"0.5.0-dev+763" 995 | export SparseArrays 996 | const SparseArrays = Base.SparseMatrix 997 | end 998 | 999 | if VERSION < v"0.5.0-dev+1229" 1000 | const Filesystem = Base.FS 1001 | else 1002 | import Base.Filesystem 1003 | end 1004 | 1005 | if VERSION < v"0.5.0-dev+1946" 1006 | const supertype = super 1007 | export supertype 1008 | end 1009 | 1010 | if VERSION < v"0.4.0-dev+1653" 1011 | function rm_recursive(path) 1012 | if islink(path) || !isdir(path) 1013 | rm(path) 1014 | else 1015 | for p in readdir(path) 1016 | rm_recursive(joinpath(path, p)) 1017 | end 1018 | rm(path) 1019 | end 1020 | end 1021 | 1022 | function Base.mktemp(fn::Function) 1023 | (tmp_path, tmp_io) = mktemp() 1024 | try 1025 | fn(tmp_path, tmp_io) 1026 | finally 1027 | close(tmp_io) 1028 | rm(tmp_path) 1029 | end 1030 | end 1031 | 1032 | function Base.mktempdir(fn::Function) 1033 | tmpdir = mktempdir() 1034 | try 1035 | fn(tmpdir) 1036 | finally 1037 | rm_recursive(tmpdir) 1038 | end 1039 | end 1040 | end 1041 | 1042 | if VERSION < v"0.5.0-dev+679" 1043 | import Base: cov, cor 1044 | 1045 | cov(x::AbstractVector, corrected::Bool) = cov(x, corrected=corrected) 1046 | cov(X::AbstractMatrix, vardim::Integer) = cov(X, vardim=vardim) 1047 | cov(X::AbstractMatrix, vardim::Integer, corrected::Bool) = cov(X, vardim=vardim, corrected=corrected) 1048 | cov(x::AbstractVector, y::AbstractVector, corrected::Bool) = cov(x, y, corrected=corrected) 1049 | cov(X::AbstractMatrix, Y::AbstractMatrix, vardim::Integer) = cov(X, Y, vardim=vardim) 1050 | cov(X::AbstractMatrix, Y::AbstractMatrix, vardim::Integer, corrected::Bool) = cov(X, Y, vardim=vardim, corrected=corrected) 1051 | 1052 | cor(X::AbstractMatrix, vardim::Integer) = cor(X, vardim=vardim) 1053 | cor(X::AbstractMatrix, Y::AbstractMatrix, vardim::Integer) = cor(X, Y, vardim=vardim) 1054 | end 1055 | 1056 | if VERSION < v"0.5.0-dev+2228" 1057 | const readstring = readall 1058 | export readstring 1059 | 1060 | Base.read(s::IO) = readbytes(s) 1061 | Base.read(s::IO, nb) = readbytes(s, nb) 1062 | 1063 | Base.write(filename::AbstractString, args...) = open(io->write(io, args...), filename, "w") 1064 | 1065 | Base.read(filename::AbstractString, args...) = open(io->read(io, args...), filename) 1066 | Base.read!(filename::AbstractString, a) = open(io->read!(io, a), filename) 1067 | Base.readuntil(filename::AbstractString, args...) = open(io->readuntil(io, args...), filename) 1068 | Base.readline(filename::AbstractString) = open(readline, filename) 1069 | Base.readlines(filename::AbstractString) = open(readlines, filename) 1070 | Base.readavailable(s::IOStream) = read!(s, @compat Vector{UInt8}(nb_available(s))) 1071 | Base.readavailable(s::IOBuffer) = read(s) 1072 | 1073 | function Base.write(to::IO, from::IO) 1074 | while !eof(from) 1075 | write(to, readavailable(from)) 1076 | end 1077 | end 1078 | 1079 | function Base.eachline(filename::AbstractString) 1080 | s = open(filename) 1081 | EachLine(s, ()->close(s)) 1082 | end 1083 | end 1084 | 1085 | if VERSION < v"0.5.0-dev+2023" 1086 | const displaysize = Base.tty_size 1087 | export displaysize 1088 | end 1089 | 1090 | 1091 | # Pull Request https://github.com/JuliaLang/julia/pull/13232 1092 | # Rounding and precision functions: 1093 | 1094 | if VERSION >= v"0.5.0-dev+1182" 1095 | import Base: 1096 | setprecision, setrounding, rounding 1097 | 1098 | else # if VERSION < v"0.5.0-dev+1182" 1099 | 1100 | export setprecision 1101 | export setrounding 1102 | export rounding 1103 | 1104 | setprecision(f, ::Type{BigFloat}, prec) = with_bigfloat_precision(f, prec) 1105 | setprecision(::Type{BigFloat}, prec) = set_bigfloat_precision(prec) 1106 | 1107 | # assume BigFloat if type not explicit: 1108 | setprecision(prec) = setprecision(BigFloat, prec) 1109 | setprecision(f, prec) = setprecision(f, BigFloat, prec) 1110 | 1111 | Base.precision(::Type{BigFloat}) = get_bigfloat_precision() 1112 | 1113 | setrounding(f, T, rounding_mode) = 1114 | with_rounding(f, T, rounding_mode) 1115 | 1116 | setrounding(T, rounding_mode) = set_rounding(T, rounding_mode) 1117 | 1118 | rounding(T) = get_rounding(T) 1119 | 1120 | end 1121 | 1122 | module LinAlg 1123 | if VERSION < v"0.5.0-dev+2022" 1124 | const checksquare = Base.LinAlg.chksquare 1125 | else 1126 | import Base.LinAlg.checksquare 1127 | end 1128 | end 1129 | 1130 | if VERSION < v"0.5.0-dev+2915" 1131 | const issymmetric = issym 1132 | export issymmetric 1133 | end 1134 | 1135 | if VERSION < v"0.5.0-dev+977" 1136 | export foreach 1137 | 1138 | foreach(f) = (f(); nothing) 1139 | foreach(f, itr) = (for x in itr; f(x); end; nothing) 1140 | foreach(f, itrs...) = (for z in zip(itrs...); f(z...); end; nothing) 1141 | end 1142 | 1143 | if !isdefined(Base, :istextmime) 1144 | export istextmime 1145 | istextmime(m::@compat(Union{MIME,AbstractString})) = istext(m) 1146 | end 1147 | 1148 | function primarytype(t::ANY) 1149 | tn = t.name 1150 | if isdefined(tn, :primary) 1151 | return tn.primary 1152 | else 1153 | return tn.wrapper 1154 | end 1155 | end 1156 | 1157 | export @functorize 1158 | macro functorize(f) 1159 | if VERSION >= v"0.5.0-dev+3701" 1160 | f === :scalarmax ? :(Base.scalarmax) : 1161 | f === :scalarmin ? :(Base.scalarmin) : 1162 | f === :centralizedabs2fun ? :(primarytype(typeof(Base.centralizedabs2fun(0)))) : 1163 | f 1164 | else 1165 | f = f === :identity ? :(Base.IdFun()) : 1166 | f === :abs ? :(Base.AbsFun()) : 1167 | f === :abs2 ? :(Base.Abs2Fun()) : 1168 | f === :exp ? :(Base.ExpFun()) : 1169 | f === :log ? :(Base.LogFun()) : 1170 | f === :& ? :(Base.AndFun()) : 1171 | f === :| ? :(Base.OrFun()) : 1172 | f === :+ ? :(Base.AddFun()) : 1173 | f === :* ? :(Base.MulFun()) : 1174 | f === :scalarmax ? :(Base.MaxFun()) : 1175 | f === :scalarmin ? :(Base.MinFun()) : 1176 | f === :centralizedabs2fun ? :(Base.CentralizedAbs2Fun) : 1177 | f 1178 | if VERSION >= v"0.4.0-dev+4902" 1179 | f = f === :< ? :(Base.LessFun()) : 1180 | f === :> ? :(Base.MoreFun()) : 1181 | f 1182 | end 1183 | if VERSION >= v"0.4.0-dev+4902" 1184 | f = f === :conj ? :(Base.ConjFun()) : 1185 | f 1186 | end 1187 | if VERSION >= v"0.4.0-dev+6254" 1188 | f = f === :- ? :(Base.SubFun()) : 1189 | f === :^ ? :(Base.PowFun()) : 1190 | f 1191 | end 1192 | if VERSION >= v"0.4.0-dev+6256" 1193 | f = f === :/ ? :(Base.RDivFun()) : 1194 | f === :\ ? :(Base.LDivFun()) : 1195 | f === :div ? :(Base.IDivFun()) : 1196 | f 1197 | end 1198 | if VERSION >= v"0.4.0-dev+6353" 1199 | f = f === :$ ? :(Base.XorFun()) : 1200 | f === :.+ ? :(Base.DotAddFun()) : 1201 | f === :.- ? :(Base.DotSubFun()) : 1202 | f === :.* ? :(Base.DotMulFun()) : 1203 | f === :mod ? :(Base.ModFun()) : 1204 | f === :rem ? :(Base.RemFun()) : 1205 | # DotRemFun is defined, but ::call(::DotRemFun, ...) is not until later 1206 | #f === :.% ? :(Base.DotRemFun()) : 1207 | f === :.<< ? :(Base.DotLSFun()) : 1208 | f === :.>> ? :(Base.DotRSFun()) : 1209 | f 1210 | end 1211 | if VERSION >= v"0.4.0-dev+6359" 1212 | f = f === :./ ? :(Base.DotRDivFun()) : 1213 | f 1214 | end 1215 | if VERSION >= v"0.4.0-rc1+59" 1216 | f = f === :max ? :(Base.ElementwiseMaxFun()) : 1217 | f === :min ? :(Base.ElementwiseMinFun()) : 1218 | f 1219 | end 1220 | if VERSION >= v"0.5.0-dev+741" 1221 | f = f === :complex ? :(Base.SparseArrays.ComplexFun()) : 1222 | f === :dot ? :(Base.SparseArrays.DotFun()) : 1223 | f 1224 | end 1225 | if VERSION >= v"0.5.0-dev+1472" 1226 | f = f === Symbol(".÷") ? :(Base.DotIDivFun()) : 1227 | f === :.% ? :(Base.DotRemFun()) : 1228 | f 1229 | end 1230 | f 1231 | end 1232 | end 1233 | 1234 | if !isdefined(Base, :Threads) 1235 | @eval module Threads 1236 | macro threads(expr) 1237 | return esc(expr) 1238 | end 1239 | threadid() = 1 1240 | nthreads() = 1 1241 | export @threads, threadid, nthreads 1242 | end 1243 | export Threads 1244 | end 1245 | 1246 | if !isdefined(Base, :normalize) 1247 | function normalize!(v::AbstractVector, p::Real=2) 1248 | nrm = norm(v, p) 1249 | __normalize!(v, nrm) 1250 | end 1251 | 1252 | @inline function __normalize!(v::AbstractVector, nrm::AbstractFloat) 1253 | #The largest positive floating point number whose inverse is less than 1254 | #infinity 1255 | δ = inv(prevfloat(typemax(nrm))) 1256 | if nrm ≥ δ #Safe to multiply with inverse 1257 | invnrm = inv(nrm) 1258 | scale!(v, invnrm) 1259 | else # scale elements to avoid overflow 1260 | εδ = eps(one(nrm))/δ 1261 | scale!(v, εδ) 1262 | scale!(v, inv(nrm*εδ)) 1263 | end 1264 | v 1265 | end 1266 | 1267 | copy_oftype{T,N}(A::AbstractArray{T,N}, ::Type{T}) = copy(A) 1268 | copy_oftype{T,N,S}(A::AbstractArray{T,N}, ::Type{S}) = convert(AbstractArray{S,N}, A) 1269 | 1270 | function normalize(v::AbstractVector, p::Real = 2) 1271 | nrm = norm(v, p) 1272 | if !isempty(v) 1273 | vv = copy_oftype(v, typeof(v[1]/nrm)) 1274 | return __normalize!(vv, nrm) 1275 | else 1276 | T = typeof(zero(eltype(v))/nrm) 1277 | return T[] 1278 | end 1279 | end 1280 | 1281 | export normalize, normalize! 1282 | end 1283 | 1284 | if !isdefined(Base, :AsyncCondition) 1285 | type AsyncCondition 1286 | cond::Condition 1287 | handle::Ptr{Void} 1288 | 1289 | function AsyncCondition(func=nothing) 1290 | this = new(Condition()) 1291 | # the callback is supposed to be called with this AsyncCondition 1292 | # as the argument, so we need to create a wrapper callback 1293 | if func == nothing 1294 | function wrapfunc(data) 1295 | notify(this.cond) 1296 | 1297 | nothing 1298 | end 1299 | else 1300 | function wrapfunc(data) 1301 | notify(this.cond) 1302 | func(this) 1303 | 1304 | nothing 1305 | end 1306 | end 1307 | work = Base.SingleAsyncWork(wrapfunc) 1308 | this.handle = work.handle 1309 | 1310 | this 1311 | end 1312 | end 1313 | 1314 | Base.wait(c::AsyncCondition) = wait(c.cond) 1315 | else 1316 | import Base.AsyncCondition 1317 | end 1318 | 1319 | # 0.5.0-dev+2301, JuliaLang/julia#14766 1320 | if !isdefined(Base, :unsafe_write) 1321 | const unsafe_write = write 1322 | export unsafe_write 1323 | end 1324 | 1325 | # JuliaLang/julia#16219 1326 | if !isdefined(Base, @compat Symbol("@static")) 1327 | macro static(ex) 1328 | if isa(ex, Expr) 1329 | if ex.head === :if 1330 | cond = eval(current_module(), ex.args[1]) 1331 | if cond 1332 | return esc(ex.args[2]) 1333 | elseif length(ex.args) == 3 1334 | return esc(ex.args[3]) 1335 | else 1336 | return nothing 1337 | end 1338 | end 1339 | end 1340 | throw(ArgumentError("invalid @static macro")) 1341 | end 1342 | export @static 1343 | end 1344 | 1345 | # JuliaLang/julia#14082 1346 | if VERSION < v"0.5.0-dev+4295" 1347 | function repeat(A::AbstractArray; 1348 | inner=ntuple(x->1, ndims(A)), 1349 | outer=ntuple(x->1, ndims(A))) 1350 | ndims_in = ndims(A) 1351 | length_inner = length(inner) 1352 | length_outer = length(outer) 1353 | 1354 | length_inner >= ndims_in || throw(ArgumentError("number of inner repetitions ($(length(inner))) cannot be less than number of dimensions of input ($(ndims(A)))")) 1355 | length_outer >= ndims_in || throw(ArgumentError("number of outer repetitions ($(length(outer))) cannot be less than number of dimensions of input ($(ndims(A)))")) 1356 | 1357 | ndims_out = max(ndims_in, length_inner, length_outer) 1358 | 1359 | inner = vcat(collect(inner), ones(Int,ndims_out-length_inner)) 1360 | outer = vcat(collect(outer), ones(Int,ndims_out-length_outer)) 1361 | 1362 | size_in = size(A) 1363 | size_out = ntuple(i->inner[i]*size(A,i)*outer[i],ndims_out)::Dims 1364 | inner_size_out = ntuple(i->inner[i]*size(A,i),ndims_out)::Dims 1365 | 1366 | indices_in = Array(Int, ndims_in) 1367 | indices_out = Array(Int, ndims_out) 1368 | 1369 | length_out = prod(size_out) 1370 | R = similar(A, size_out) 1371 | 1372 | for index_out in 1:length_out 1373 | indices_out = ind2sub(size_out, index_out) 1374 | for t in 1:ndims_in 1375 | # "Project" outer repetitions into inner repetitions 1376 | indices_in[t] = mod1(indices_out[t], inner_size_out[t]) 1377 | # Find inner repetitions using flooring division 1378 | indices_in[t] = Base.fld1(indices_in[t], inner[t]) 1379 | end 1380 | index_in = sub2ind(size_in, indices_in...) 1381 | R[index_out] = A[index_in] 1382 | end 1383 | 1384 | return R 1385 | end 1386 | else 1387 | const repeat = Base.repeat 1388 | end 1389 | 1390 | if VERSION < v"0.5.0-dev+4267" 1391 | if OS_NAME == :Windows 1392 | const KERNEL = :NT 1393 | else 1394 | const KERNEL = OS_NAME 1395 | end 1396 | 1397 | @eval is_apple() = $(KERNEL == :Darwin) 1398 | @eval is_linux() = $(KERNEL == :Linux) 1399 | @eval is_bsd() = $(KERNEL in (:FreeBSD, :OpenBSD, :NetBSD, :Darwin, :Apple)) 1400 | @eval is_unix() = $(is_linux() || is_bsd()) 1401 | @eval is_windows() = $(KERNEL == :NT) 1402 | export is_apple, is_linux, is_bsd, is_unix, is_windows 1403 | else 1404 | const KERNEL = Sys.KERNEL 1405 | end 1406 | 1407 | import Base: srand, rand, rand! 1408 | if VERSION < v"0.4.0-dev+1373" # PR #8854 1409 | function make_seed() 1410 | try 1411 | @static if is_unix() 1412 | seed = open("/dev/urandom") do io 1413 | a = Array(UInt32, 4) 1414 | read!(io, a) 1415 | a 1416 | end 1417 | elseif is_windows() 1418 | seed = let a = zeros(UInt32, 2) 1419 | Base.dSFMT.win32_SystemFunction036!(a) 1420 | a 1421 | end 1422 | end 1423 | return seed 1424 | catch 1425 | println(STDERR, "Entropy pool not available to seed RNG; using ad-hoc entropy sources.") 1426 | seed = reinterpret(UInt64, time()) 1427 | seed = hash(seed, convert(UInt64, getpid())) 1428 | try 1429 | seed = hash(seed, parse(UInt64, readall(`ifconfig` |> `sha1sum`)[1:40], 16)) 1430 | end 1431 | return seed 1432 | end 1433 | end 1434 | if VERSION < v"0.4.0-dev+1352" # PR #8832 1435 | function srand(r::MersenneTwister, seed::Vector{UInt32}) 1436 | r.seed = seed 1437 | Base.dSFMT.dsfmt_init_by_array(r.state, seed) 1438 | return r 1439 | end 1440 | else 1441 | function srand(r::MersenneTwister, seed::Vector{UInt32}) 1442 | r.seed = seed 1443 | Base.dSFMT.dsfmt_init_by_array(r.state, seed) 1444 | r.idx = Base.dSFMT.dsfmt_get_min_array_size() 1445 | return r 1446 | end 1447 | rand(r::MersenneTwister, ::Type{UInt32}) = reinterpret(UInt64, Base.Random.rand_close1_open2(r)) % UInt32 1448 | end 1449 | srand(r::MersenneTwister, seed::Union(UInt32,Int32)) = srand(r, UInt32[seed]) 1450 | srand(r::MersenneTwister, seed::Union(UInt64,Int64)) = 1451 | srand(r, UInt32[seed & 0xffffffff, seed >> 32]) 1452 | srand(r::MersenneTwister) = srand(r, make_seed()) 1453 | 1454 | rand(r::MersenneTwister, ::Type{UInt8}) = rand(r, UInt32) % UInt8 1455 | rand(r::MersenneTwister, ::Type{UInt16}) = rand(r, UInt32) % UInt16 1456 | rand(r::MersenneTwister, ::Type{UInt32}) = reinterpret(UInt64, rand(r)) % UInt32 1457 | rand(r::MersenneTwister, ::Type{UInt64}) = convert(UInt64,rand(r, UInt32)) <<32 | rand(r, UInt32) 1458 | rand(r::MersenneTwister, ::Type{UInt128}) = convert(UInt128,rand(r, UInt64))<<64 | rand(r, UInt64) 1459 | 1460 | for (T,Tu) in ((Int8,UInt8),(Int16,UInt16),(Int32,UInt32),(Int64,UInt64),(Int128,UInt128)) 1461 | @eval rand(r::MersenneTwister, ::Type{$T}) = reinterpret($T, rand(r, $Tu)) 1462 | end 1463 | rand(r::MersenneTwister, ::Type{Float64}) = rand(r) 1464 | rand(r::MersenneTwister, ::Type{Float64}) = rand(r) 1465 | rand{T<:Union(Float16,Float32)}(r::MersenneTwister, ::Type{T}) = convert(T, rand(r)) 1466 | rand{T<:Real}(r::AbstractRNG, ::Type{Complex{T}}) = complex(rand(r, T), rand(r, T)) 1467 | if VERSION < v"0.4.0-dev+1296" # commit 89befafa7deded0119d0186ef116e03ec91b9680 1468 | function rand!{T<:Number}(r::AbstractRNG, A::AbstractArray{T}) 1469 | for i=1:length(A) 1470 | @inbounds A[i] = rand(r, T) 1471 | end 1472 | A 1473 | end 1474 | end 1475 | rand(r::AbstractRNG, T::Type, dims::Dims) = rand!(r, Array(T, dims)) 1476 | rand(r::AbstractRNG, T::Type, d1::Int, dims::Int...) = rand!(r, Array(T, d1, dims...)) 1477 | rand(r::MersenneTwister, ::Type{Bool}) = ((rand(r, UInt32) & 1) == 1) 1478 | end 1479 | 1480 | if VERSION < v"0.4.0-dev+551" # PR #8320 1481 | srand() = srand(make_seed()) 1482 | end 1483 | 1484 | if VERSION < v"0.4.0-dev+1884" 1485 | randexp(rng::MersenneTwister) = Base.Random.randmtzig_exprnd(rng) 1486 | randexp() = Base.Random.randmtzig_exprnd() 1487 | export randexp 1488 | end 1489 | 1490 | if isdefined(Core, :String) && isdefined(Core, :AbstractString) 1491 | # Not exported in order to not break code on 0.5 1492 | typealias UTF8String Core.String 1493 | typealias ASCIIString Core.String 1494 | else 1495 | typealias String Base.ByteString 1496 | if VERSION >= v"0.4.0-dev+5243" 1497 | @compat (::Type{Base.ByteString})(io::Base.AbstractIOBuffer) = bytestring(io) 1498 | elseif VERSION >= v"0.4.0-dev+1246" 1499 | @compat (::Type{Base.ByteString})(io::IOBuffer) = bytestring(io) 1500 | end 1501 | if VERSION >= v"0.4.0-dev+1246" 1502 | @compat (::Type{Base.ByteString})(s::Cstring) = bytestring(s) 1503 | @compat (::Type{Base.ByteString})(v::Vector{UInt8}) = bytestring(v) 1504 | @compat (::Type{Base.ByteString})(p::Union{Ptr{Int8},Ptr{UInt8}}) = bytestring(p) 1505 | @compat (::Type{Base.ByteString})(p::Union{Ptr{Int8},Ptr{UInt8}}, len::Integer) = bytestring(p, len) 1506 | @compat (::Type{Base.ByteString})(s::AbstractString) = bytestring(s) 1507 | end 1508 | end 1509 | 1510 | if VERSION < v"0.5.0-dev+2285" 1511 | fieldoffset(T, i) = @compat UInt(fieldoffsets(T)[i]) 1512 | export fieldoffset 1513 | end 1514 | 1515 | if !isdefined(Base, :view) 1516 | const view = slice 1517 | end 1518 | 1519 | if !isdefined(Base, :pointer_to_string) 1520 | 1521 | function pointer_to_string(p::Ptr{UInt8}, len::Integer, own::Bool=false) 1522 | a = ccall(:jl_ptr_to_array_1d, Vector{UInt8}, 1523 | (Any, Ptr{UInt8}, Csize_t, Cint), Vector{UInt8}, p, len, own) 1524 | ccall(:jl_array_to_string, String, (Any,), a) 1525 | end 1526 | 1527 | pointer_to_string(p::Ptr{UInt8}, own::Bool=false) = 1528 | pointer_to_string(p, ccall(:strlen, Csize_t, (Cstring,), p), own) 1529 | 1530 | end 1531 | 1532 | if VERSION < v"0.5.0-dev+4612" 1533 | export unsafe_string, unsafe_wrap 1534 | unsafe_wrap(::Type{Compat.String}, p::@compat(Union{Ptr{Int8},Ptr{UInt8}}), own::Bool=false) = pointer_to_string(convert(Ptr{UInt8}, p), own) 1535 | unsafe_wrap(::Type{Compat.String}, p::@compat(Union{Ptr{Int8},Ptr{UInt8}}), len, own::Bool=false) = pointer_to_string(convert(Ptr{UInt8}, p), len, own) 1536 | unsafe_wrap(::Type{Array}, p::Ptr, dims, own::Bool=false) = pointer_to_array(p, dims, own) 1537 | unsafe_string(p::@compat(Union{Ptr{Int8},Ptr{UInt8}})) = bytestring(p) 1538 | unsafe_string(p::@compat(Union{Ptr{Int8},Ptr{UInt8}}), len) = bytestring(p, len) 1539 | if Cstring != Ptr{UInt8} 1540 | unsafe_string(p::Cstring) = unsafe_string(Ptr{UInt8}(p)) 1541 | end 1542 | end 1543 | 1544 | if !isdefined(Base, :allunique) 1545 | allunique(itr) = length(itr) == length(unique(itr)) 1546 | export allunique 1547 | end 1548 | 1549 | if !isdefined(Base, :promote_eltype_op) 1550 | if isdefined(Base, :promote_op) 1551 | promote_eltype_op(::Any) = Union{} 1552 | promote_eltype_op{T}(op, ::AbstractArray{T}) = Base.promote_op(op, T) 1553 | promote_eltype_op{T}(op, ::T ) = Base.promote_op(op, T) 1554 | promote_eltype_op{R,S}(op, ::AbstractArray{R}, ::AbstractArray{S}) = Base.promote_op(op, R, S) 1555 | promote_eltype_op{R,S}(op, ::AbstractArray{R}, ::S) = Base.promote_op(op, R, S) 1556 | promote_eltype_op{R,S}(op, ::R, ::AbstractArray{S}) = Base.promote_op(op, R, S) 1557 | promote_eltype_op(op, A, B, C, D...) = Base.promote_op(op, eltype(A), promote_eltype_op(op, B, C, D...)) 1558 | else 1559 | promote_eltype_op(::Any) = Union{} 1560 | promote_eltype_op{T}(op, ::AbstractArray{T}) = T 1561 | promote_eltype_op{T}(op, ::T ) = T 1562 | promote_eltype_op{R,S}(op, ::AbstractArray{R}, ::AbstractArray{S}) = Base.promote_type(R, S) 1563 | promote_eltype_op{R,S}(op, ::AbstractArray{R}, ::S) = Base.promote_type(R, S) 1564 | promote_eltype_op{R,S}(op, ::R, ::AbstractArray{S}) = Base.promote_type(R, S) 1565 | promote_eltype_op(op, A, B, C, D...) = Base.promote_type(eltype(A), promote_eltype_op(op, B, C, D...)) 1566 | end 1567 | else 1568 | import Base.promote_eltype_op 1569 | end 1570 | 1571 | if VERSION < v"0.5.0-dev+4351" 1572 | Base.join(io::IO, items) = 1573 | print_joined(io, items) 1574 | Base.join(io::IO, items, delim) = 1575 | print_joined(io, items, delim) 1576 | Base.join(io::IO, items, delim, last) = 1577 | print_joined(io, items, delim, last) 1578 | Base.unescape_string(io, s::AbstractString) = 1579 | print_unescaped(io, s) 1580 | Base.escape_string(io, str::AbstractString, esc::AbstractString) = 1581 | print_escaped(io, str, esc) 1582 | end 1583 | 1584 | if VERSION < v"0.5.0-dev+4340" 1585 | Base.show(io::IO, mime, x) = writemime(io, mime, x) 1586 | end 1587 | 1588 | if VERSION >= v"0.5.0-dev+4338" 1589 | import Base.LinAlg.BLAS.@blasfunc 1590 | elseif VERSION >= v"0.5.0-dev+1871" 1591 | import Base.@blasfunc 1592 | else 1593 | macro blasfunc(x) 1594 | Expr(:quote, Base.blasfunc(x)) 1595 | end 1596 | end 1597 | 1598 | import Base: redirect_stdin, redirect_stdout, redirect_stderr 1599 | if VERSION < v"0.6.0-dev.374" 1600 | for (F,S) in ((:redirect_stdin, :STDIN), (:redirect_stdout, :STDOUT), (:redirect_stderr, :STDERR)) 1601 | @eval function $F(f::Function, stream) 1602 | STDOLD = $S 1603 | $F(stream) 1604 | try f() finally $F(STDOLD) end 1605 | end 1606 | end 1607 | end 1608 | 1609 | if VERSION < v"0.6.0-dev.528" 1610 | macro __DIR__() 1611 | Base.source_dir() 1612 | end 1613 | export @__DIR__ 1614 | end 1615 | 1616 | # PR #17302 1617 | # Provide a non-deprecated version of `@vectorize_(1|2)arg` macro which defines 1618 | # deprecated version of the function so that the depwarns can be fixed without 1619 | # breaking users. 1620 | # Packages are expected to use this to maintain the old API until all users 1621 | # of the deprecated vectorized function have migrated. 1622 | # These macros should raise a depwarn when the `0.5` support is dropped from 1623 | # `Compat` and be dropped when the support for `0.6` is dropped from `Compat`. 1624 | # Modified based on the version copied from 0.6 Base. 1625 | macro dep_vectorize_1arg(S, f) 1626 | S = esc(S) 1627 | f = esc(f) 1628 | T = esc(:T) 1629 | x = esc(:x) 1630 | AbsArr = esc(:AbstractArray) 1631 | ## Depwarn to be enabled when 0.5 support is dropped. 1632 | # depwarn("Implicit vectorized function is deprecated in favor of compact broadcast syntax.", 1633 | # Symbol("@dep_vectorize_1arg")) 1634 | :(@deprecate $f{$T<:$S}($x::$AbsArr{$T}) @compat($f.($x))) 1635 | end 1636 | 1637 | macro dep_vectorize_2arg(S, f) 1638 | S = esc(S) 1639 | f = esc(f) 1640 | T1 = esc(:T1) 1641 | T2 = esc(:T2) 1642 | x = esc(:x) 1643 | y = esc(:y) 1644 | AbsArr = esc(:AbstractArray) 1645 | ## Depwarn to be enabled when 0.5 support is dropped. 1646 | # depwarn("Implicit vectorized function is deprecated in favor of compact broadcast syntax.", 1647 | # Symbol("@dep_vectorize_2arg")) 1648 | quote 1649 | @deprecate $f{$T1<:$S}($x::$S, $y::$AbsArr{$T1}) @compat($f.($x,$y)) 1650 | @deprecate $f{$T1<:$S}($x::$AbsArr{$T1}, $y::$S) @compat($f.($x,$y)) 1651 | @deprecate $f{$T1<:$S,$T2<:$S}($x::$AbsArr{$T1}, $y::$AbsArr{$T2}) @compat($f.($x,$y)) 1652 | end 1653 | end 1654 | 1655 | if VERSION < v"0.5.0-dev+4677" 1656 | using Base.LinAlg: HermOrSym 1657 | Base.chol(A::HermOrSym) = Base.LinAlg.chol!(A.uplo == 'U' ? copy(A.data) : A.data') 1658 | Base.cholfact(A::HermOrSym) = cholfact(A.data, Symbol(A.uplo)) 1659 | Base.cholfact!(A::HermOrSym) = cholfact!(A.data, Symbol(A.uplo)) 1660 | 1661 | Base.cholfact(A::HermOrSym, T::Type) = cholfact(A.data, Symbol(A.uplo), T) 1662 | Base.cholfact!(A::HermOrSym, T::Type) = cholfact!(A.data, Symbol(A.uplo), T) 1663 | end 1664 | 1665 | # julia#18510 1666 | if VERSION < v"0.6.0-dev.826" 1667 | _Nullable_field2(x) = !x 1668 | else 1669 | _Nullable_field2(x) = x 1670 | end 1671 | 1672 | # julia#18484 1673 | if VERSION < v"0.6.0-dev.848" 1674 | unsafe_get(x::Nullable) = x.value 1675 | unsafe_get(x) = x 1676 | export unsafe_get 1677 | if VERSION < v"0.4.0-dev+656" # so "nullable.jl" is included 1678 | isnull(x) = false 1679 | else 1680 | Base.isnull(x) = false 1681 | end 1682 | end 1683 | 1684 | # julia#18977 1685 | if !isdefined(Base, :xor) 1686 | const xor = $ 1687 | const ⊻ = xor 1688 | export xor, ⊻ 1689 | end 1690 | 1691 | # julia#19246 1692 | if !isdefined(Base, :numerator) 1693 | const numerator = num 1694 | const denominator = den 1695 | export numerator, denominator 1696 | end 1697 | 1698 | # julia #19950 1699 | if !isdefined(Base, :iszero) 1700 | iszero(x) = x == zero(x) 1701 | iszero(x::Number) = x == 0 1702 | iszero(x::AbstractArray) = all(iszero, x) 1703 | export iszero 1704 | end 1705 | 1706 | # julia#19088 1707 | if VERSION < v"0.6.0-dev.1256" 1708 | Base.take!(io::Base.AbstractIOBuffer) = takebuf_array(io) 1709 | end 1710 | 1711 | # julia #17323 1712 | if VERSION < v"0.5.0-dev+5380" 1713 | export transcode 1714 | transcode{T<:Compat.String}(::Type{T}, src::Union{Compat.String,Vector{UInt8}}) = utf8(src) 1715 | transcode{T<:Compat.String}(::Type{T}, src::Vector{UInt16}) = utf8(utf16(src)) 1716 | transcode{T<:Compat.String}(::Type{T}, src::Vector{UInt32}) = utf8(utf32(src)) 1717 | transcode(::Type{UInt8}, src::Vector{UInt8}) = src 1718 | transcode(::Type{UInt8}, src) = transcode(Compat.String, src).data 1719 | function transcode(::Type{UInt16}, src::Union{Compat.String,Vector{UInt8}}) 1720 | d = utf16(utf8(src)).data 1721 | return resize!(d, length(d)-1) # strip off trailing NUL codeunit 1722 | end 1723 | function transcode(::Type{UInt32}, src::Union{Compat.String,Vector{UInt8}}) 1724 | d = utf32(utf8(src)).data 1725 | return resize!(d, length(d)-1) # strip off trailing NUL codeunit 1726 | end 1727 | transcode(::Type{UInt16}, src::Vector{UInt16}) = src 1728 | transcode(::Type{UInt32}, src::Vector{UInt32}) = src 1729 | if Cwchar_t == Int32 1730 | transcode(::Type{Cwchar_t}, src::Vector{Cwchar_t}) = src 1731 | transcode(::Type{Cwchar_t}, src) = reinterpret(Cwchar_t, transcode(UInt32, src)) 1732 | transcode(::Type{UInt8}, src::Vector{Cwchar_t}) = transcode(UInt8, reinterpret(UInt32, src)) 1733 | transcode(T, src::Vector{Cwchar_t}) = transcode(T, reinterpret(UInt32, src)) 1734 | end 1735 | end 1736 | 1737 | # julia #17155 function composition and negation 1738 | if VERSION < v"0.6.0-dev.1883" 1739 | export ∘ 1740 | ∘(f, g) = (x...)->f(g(x...)) 1741 | @compat Base.:!(f::Function) = (x...)->!f(x...) 1742 | end 1743 | 1744 | if VERSION < v"0.5.0-dev+1450" 1745 | Base.Diagonal(v::AbstractVector) = Diagonal(collect(v)) 1746 | end 1747 | if VERSION < v"0.5.0-dev+3669" 1748 | using Base: promote_op 1749 | import Base: * 1750 | typealias SubMatrix{T} SubArray{T,2} 1751 | (*)(A::SubMatrix, D::Diagonal) = 1752 | scale!(similar(A, promote_op(*, eltype(A), eltype(D.diag))), A, D.diag) 1753 | (*)(D::Diagonal, A::SubMatrix) = 1754 | scale!(similar(A, promote_op(*, eltype(A), eltype(D.diag))), D.diag, A) 1755 | end 1756 | 1757 | if VERSION >= v"0.5.0-dev+5509" && VERSION < v"0.6.0-dev.1614" 1758 | # To work around unsupported syntax on Julia 0.4 1759 | include_string("export .&, .|") 1760 | include_string(".&(xs...) = broadcast(&, xs...)") 1761 | include_string(".|(xs...) = broadcast(|, xs...)") 1762 | end 1763 | 1764 | if VERSION < v"0.6.0-dev.2093" # Compat.isapprox to allow for NaNs 1765 | using Base.rtoldefault 1766 | function isapprox(x::Number, y::Number; rtol::Real=rtoldefault(x,y), atol::Real=0, nans::Bool=false) 1767 | x == y || (isfinite(x) && isfinite(y) && abs(x-y) <= atol + rtol*max(abs(x), abs(y))) || (nans && isnan(x) && isnan(y)) 1768 | end 1769 | else 1770 | import Base.isapprox 1771 | end 1772 | 1773 | end # module 1774 | --------------------------------------------------------------------------------