mollusk 0e4acfb8f2 fix incorrect folder name for julia-0.6.x
Former-commit-id: ef2c7401e0876f22d2f7762d182cfbcd5a7d9c70
2018-06-11 03:28:36 -07:00

339 lines
11 KiB
Julia
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# This file is a part of Julia. License is MIT: https://julialang.org/license
# Document NTuple here where we have everything needed for the doc system
"""
NTuple{N, T}
A compact way of representing the type for a tuple of length `N` where all elements are of type `T`.
```jldoctest
julia> isa((1, 2, 3, 4, 5, 6), NTuple{6, Int})
true
```
"""
NTuple
## indexing ##
length(t::Tuple) = nfields(t)
endof(t::Tuple) = length(t)
size(t::Tuple, d) = d==1 ? length(t) : throw(ArgumentError("invalid tuple dimension $d"))
getindex(t::Tuple, i::Int) = getfield(t, i)
getindex(t::Tuple, i::Real) = getfield(t, convert(Int, i))
getindex(t::Tuple, r::AbstractArray{<:Any,1}) = ([t[ri] for ri in r]...)
getindex(t::Tuple, b::AbstractArray{Bool,1}) = length(b) == length(t) ? getindex(t,find(b)) : throw(BoundsError(t, b))
# returns new tuple; N.B.: becomes no-op if i is out-of-bounds
setindex(x::Tuple, v, i::Integer) = _setindex((), x, v, i::Integer)
function _setindex(y::Tuple, r::Tuple, v, i::Integer)
@_inline_meta
_setindex((y..., ifelse(length(y) + 1 == i, v, first(r))), tail(r), v, i)
end
_setindex(y::Tuple, r::Tuple{}, v, i::Integer) = y
## iterating ##
start(t::Tuple) = 1
done(t::Tuple, i::Int) = (length(t) < i)
next(t::Tuple, i::Int) = (t[i], i+1)
eachindex(t::Tuple) = 1:length(t)
function eachindex(t::Tuple, t2::Tuple...)
@_inline_meta
1:_maxlength(t, t2...)
end
_maxlength(t::Tuple) = length(t)
function _maxlength(t::Tuple, t2::Tuple, t3::Tuple...)
@_inline_meta
max(length(t), _maxlength(t2, t3...))
end
# this allows partial evaluation of bounded sequences of next() calls on tuples,
# while reducing to plain next() for arbitrary iterables.
indexed_next(t::Tuple, i::Int, state) = (t[i], i+1)
indexed_next(a::Array, i::Int, state) = (a[i], i+1)
indexed_next(I, i, state) = done(I,state) ? throw(BoundsError()) : next(I, state)
# Use dispatch to avoid a branch in first
first(::Tuple{}) = throw(ArgumentError("tuple must be non-empty"))
first(t::Tuple) = t[1]
# eltype
eltype(::Type{Tuple{}}) = Bottom
eltype(::Type{<:Tuple{Vararg{E}}}) where {E} = E
function eltype(t::Type{<:Tuple})
@_pure_meta
t isa Union && return typejoin(eltype(t.a), eltype(t.b))
t´ = unwrap_unionall(t)
r = Union{}
for ti in t´.parameters
r = typejoin(r, rewrap_unionall(unwrapva(ti), t))
end
return r
end
# version of tail that doesn't throw on empty tuples (used in array indexing)
safe_tail(t::Tuple) = tail(t)
safe_tail(t::Tuple{}) = ()
# front (the converse of tail: it skips the last entry)
function front(t::Tuple)
@_inline_meta
_front((), t...)
end
front(::Tuple{}) = throw(ArgumentError("Cannot call front on an empty tuple"))
_front(out, v) = out
function _front(out, v, t...)
@_inline_meta
_front((out..., v), t...)
end
## mapping ##
"""
ntuple(f::Function, n::Integer)
Create a tuple of length `n`, computing each element as `f(i)`,
where `i` is the index of the element.
```jldoctest
julia> ntuple(i -> 2*i, 4)
(2, 4, 6, 8)
```
"""
function ntuple(f::F, n::Integer) where F
t = n <= 0 ? () :
n == 1 ? (f(1),) :
n == 2 ? (f(1), f(2)) :
n == 3 ? (f(1), f(2), f(3)) :
n == 4 ? (f(1), f(2), f(3), f(4)) :
n == 5 ? (f(1), f(2), f(3), f(4), f(5)) :
n == 6 ? (f(1), f(2), f(3), f(4), f(5), f(6)) :
n == 7 ? (f(1), f(2), f(3), f(4), f(5), f(6), f(7)) :
n == 8 ? (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8)) :
n == 9 ? (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9)) :
n == 10 ? (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10)) :
_ntuple(f, n)
return t
end
_ntuple(f, n) = (@_noinline_meta; ([f(i) for i = 1:n]...))
# inferrable ntuple
ntuple(f, ::Type{Val{0}}) = (@_inline_meta; ())
ntuple(f, ::Type{Val{1}}) = (@_inline_meta; (f(1),))
ntuple(f, ::Type{Val{2}}) = (@_inline_meta; (f(1), f(2)))
ntuple(f, ::Type{Val{3}}) = (@_inline_meta; (f(1), f(2), f(3)))
ntuple(f, ::Type{Val{4}}) = (@_inline_meta; (f(1), f(2), f(3), f(4)))
ntuple(f, ::Type{Val{5}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5)))
ntuple(f, ::Type{Val{6}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6)))
ntuple(f, ::Type{Val{7}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7)))
ntuple(f, ::Type{Val{8}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8)))
ntuple(f, ::Type{Val{9}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9)))
ntuple(f, ::Type{Val{10}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10)))
ntuple(f, ::Type{Val{11}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11)))
ntuple(f, ::Type{Val{12}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12)))
ntuple(f, ::Type{Val{13}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13)))
ntuple(f, ::Type{Val{14}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13), f(14)))
ntuple(f, ::Type{Val{15}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13), f(14), f(15)))
function ntuple(f::F, ::Type{Val{N}}) where {F,N}
Core.typeassert(N, Int)
(N >= 0) || throw(ArgumentError(string("tuple length should be ≥0, got ", N)))
_ntuple((), f, Val{N})
end
# Build up the output until it has length N
_ntuple(out::NTuple{N,Any}, f::F, ::Type{Val{N}}) where {F,N} = out
function _ntuple(out::NTuple{M,Any}, f::F, ::Type{Val{N}}) where {F,N,M}
@_inline_meta
_ntuple((out..., f(M+1)), f, Val{N})
end
# 1 argument function
map(f, t::Tuple{}) = ()
map(f, t::Tuple{Any,}) = (f(t[1]),)
map(f, t::Tuple{Any, Any}) = (f(t[1]), f(t[2]))
map(f, t::Tuple{Any, Any, Any}) = (f(t[1]), f(t[2]), f(t[3]))
map(f, t::Tuple) = (@_inline_meta; (f(t[1]), map(f,tail(t))...))
# stop inlining after some number of arguments to avoid code blowup
const Any16{N} = Tuple{Any,Any,Any,Any,Any,Any,Any,Any,
Any,Any,Any,Any,Any,Any,Any,Any,Vararg{Any,N}}
const All16{T,N} = Tuple{T,T,T,T,T,T,T,T,
T,T,T,T,T,T,T,T,Vararg{T,N}}
function map(f, t::Any16)
n = length(t)
A = Array{Any,1}(n)
for i=1:n
A[i] = f(t[i])
end
(A...)
end
# 2 argument function
map(f, t::Tuple{}, s::Tuple{}) = ()
map(f, t::Tuple{Any,}, s::Tuple{Any,}) = (f(t[1],s[1]),)
map(f, t::Tuple{Any,Any}, s::Tuple{Any,Any}) = (f(t[1],s[1]), f(t[2],s[2]))
function map(f, t::Tuple, s::Tuple)
@_inline_meta
(f(t[1],s[1]), map(f, tail(t), tail(s))...)
end
function map(f, t::Any16, s::Any16)
n = length(t)
A = Array{Any,1}(n)
for i = 1:n
A[i] = f(t[i], s[i])
end
(A...)
end
# n argument function
heads(ts::Tuple...) = map(t -> t[1], ts)
tails(ts::Tuple...) = map(tail, ts)
map(f, ::Tuple{}...) = ()
function map(f, t1::Tuple, t2::Tuple, ts::Tuple...)
@_inline_meta
(f(heads(t1, t2, ts...)...), map(f, tails(t1, t2, ts...)...)...)
end
function map(f, t1::Any16, t2::Any16, ts::Any16...)
n = length(t1)
A = Array{Any,1}(n)
for i = 1:n
A[i] = f(t1[i], t2[i], map(t -> t[i], ts)...)
end
(A...)
end
# type-stable padding
fill_to_length(t::Tuple, val, ::Type{Val{N}}) where {N} = _ftl((), val, Val{N}, t...)
_ftl(out::NTuple{N,Any}, val, ::Type{Val{N}}) where {N} = out
function _ftl(out::NTuple{N,Any}, val, ::Type{Val{N}}, t...) where N
@_inline_meta
throw(ArgumentError("input tuple of length $(N+length(t)), requested $N"))
end
function _ftl(out, val, ::Type{Val{N}}, t1, t...) where N
@_inline_meta
_ftl((out..., t1), val, Val{N}, t...)
end
function _ftl(out, val, ::Type{Val{N}}) where N
@_inline_meta
_ftl((out..., val), val, Val{N})
end
# constructing from an iterator
# only define these in Base, to avoid overwriting the constructors
if isdefined(Main, :Base)
(::Type{T})(x::Tuple) where {T<:Tuple} = convert(T, x) # still use `convert` for tuples
# resolve ambiguity between preceding and following methods
All16{E,N}(x::Tuple) where {E,N} = convert(All16{E,N}, x)
function (T::All16{E,N})(itr) where {E,N}
len = N+16
elts = collect(E, Iterators.take(itr,len))
if length(elts) != len
_totuple_err(T)
end
(elts...,)
end
(::Type{T})(itr) where {T<:Tuple} = _totuple(T, itr, start(itr))
_totuple(::Type{Tuple{}}, itr, s) = ()
function _totuple_err(T::ANY)
@_noinline_meta
throw(ArgumentError("too few elements for tuple type $T"))
end
function _totuple(T, itr, s)
@_inline_meta
done(itr, s) && _totuple_err(T)
v, s = next(itr, s)
(convert(tuple_type_head(T), v), _totuple(tuple_type_tail(T), itr, s)...)
end
_totuple(::Type{Tuple{Vararg{E}}}, itr, s) where {E} = (collect(E, Iterators.rest(itr,s))...,)
_totuple(::Type{Tuple}, itr, s) = (collect(Iterators.rest(itr,s))...,)
end
## comparison ##
function isequal(t1::Tuple, t2::Tuple)
if length(t1) != length(t2)
return false
end
for i = 1:length(t1)
if !isequal(t1[i], t2[i])
return false
end
end
return true
end
function ==(t1::Tuple, t2::Tuple)
if length(t1) != length(t2)
return false
end
for i = 1:length(t1)
if !(t1[i] == t2[i])
return false
end
end
return true
end
const tuplehash_seed = UInt === UInt64 ? 0x77cfa1eef01bca90 : 0xf01bca90
hash( ::Tuple{}, h::UInt) = h + tuplehash_seed
hash(x::Tuple{Any,}, h::UInt) = hash(x[1], hash((), h))
hash(x::Tuple{Any,Any}, h::UInt) = hash(x[1], hash(x[2], hash((), h)))
hash(x::Tuple, h::UInt) = hash(x[1], hash(x[2], hash(tail(tail(x)), h)))
function isless(t1::Tuple, t2::Tuple)
n1, n2 = length(t1), length(t2)
for i = 1:min(n1, n2)
a, b = t1[i], t2[i]
if !isequal(a, b)
return isless(a, b)
end
end
return n1 < n2
end
## functions ##
isempty(x::Tuple{}) = true
isempty(x::Tuple) = false
revargs() = ()
revargs(x, r...) = (revargs(r...)..., x)
reverse(t::Tuple) = revargs(t...)
## specialized reduction ##
# TODO: these definitions cannot yet be combined, since +(x...)
# where x might be any tuple matches too many methods.
sum(x::Tuple{Any, Vararg{Any}}) = +(x...)
# NOTE: should remove, but often used on array sizes
prod(x::Tuple{}) = 1
prod(x::Tuple{Any, Vararg{Any}}) = *(x...)
all(x::Tuple{}) = true
all(x::Tuple{Bool}) = x[1]
all(x::Tuple{Bool, Bool}) = x[1]&x[2]
all(x::Tuple{Bool, Bool, Bool}) = x[1]&x[2]&x[3]
# use generic reductions for the rest
any(x::Tuple{}) = false
any(x::Tuple{Bool}) = x[1]
any(x::Tuple{Bool, Bool}) = x[1]|x[2]
any(x::Tuple{Bool, Bool, Bool}) = x[1]|x[2]|x[3]