Skip to content

Commit

Permalink
Allow use of 32 element tuples without dynamic allocation
Browse files Browse the repository at this point in the history
  • Loading branch information
kshyatt authored and ElOceanografo committed May 4, 2021
1 parent bdef033 commit bc42920
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 19 deletions.
4 changes: 2 additions & 2 deletions base/combinatorics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ function isperm(P::Tuple)
end
end

isperm(P::Any16) = _isperm(P)
isperm(P::Any32) = _isperm(P)

# swap columns i and j of a, in-place
function swapcols!(a::AbstractMatrix, i, j)
Expand Down Expand Up @@ -286,7 +286,7 @@ function invperm(P::Tuple)
end
end

invperm(P::Any16) = Tuple(invperm(collect(P)))
invperm(P::Any32) = Tuple(invperm(collect(P)))

#XXX This function should be moved to Combinatorics.jl but is currently used by Base.DSP.
"""
Expand Down
20 changes: 18 additions & 2 deletions base/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ afoldl(op, a) = a
function afoldl(op, a, bs...)
l = length(bs)
i = 0; y = a; l == i && return y
#@nexprs 15 i -> (y = op(y, bs[i]); l == i && return y)
#@nexprs 31 i -> (y = op(y, bs[i]); l == i && return y)
i = 1; y = op(y, bs[i]); l == i && return y
i = 2; y = op(y, bs[i]); l == i && return y
i = 3; y = op(y, bs[i]); l == i && return y
Expand All @@ -606,12 +606,28 @@ function afoldl(op, a, bs...)
i = 13; y = op(y, bs[i]); l == i && return y
i = 14; y = op(y, bs[i]); l == i && return y
i = 15; y = op(y, bs[i]); l == i && return y
i = 16; y = op(y, bs[i]); l == i && return y
i = 17; y = op(y, bs[i]); l == i && return y
i = 18; y = op(y, bs[i]); l == i && return y
i = 19; y = op(y, bs[i]); l == i && return y
i = 20; y = op(y, bs[i]); l == i && return y
i = 21; y = op(y, bs[i]); l == i && return y
i = 22; y = op(y, bs[i]); l == i && return y
i = 23; y = op(y, bs[i]); l == i && return y
i = 24; y = op(y, bs[i]); l == i && return y
i = 25; y = op(y, bs[i]); l == i && return y
i = 26; y = op(y, bs[i]); l == i && return y
i = 27; y = op(y, bs[i]); l == i && return y
i = 28; y = op(y, bs[i]); l == i && return y
i = 29; y = op(y, bs[i]); l == i && return y
i = 30; y = op(y, bs[i]); l == i && return y
i = 31; y = op(y, bs[i]); l == i && return y
for i in (i + 1):l
y = op(y, bs[i])
end
return y
end
typeof(afoldl).name.mt.max_args = 18
typeof(afoldl).name.mt.max_args = 34

for op in (:+, :*, :&, :|, :xor, :min, :max, :kron)
@eval begin
Expand Down
36 changes: 21 additions & 15 deletions base/tuple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,17 @@ map(f, t::Tuple{Any, Any}) = (@_inline_meta; (f(t[1]), f(t[2])))
map(f, t::Tuple{Any, Any, Any}) = (@_inline_meta; (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)
const Any32{N} = Tuple{Any,Any,Any,Any,Any,Any,Any,Any,
Any,Any,Any,Any,Any,Any,Any,Any,
Any,Any,Any,Any,Any,Any,Any,Any,
Any,Any,Any,Any,Any,Any,Any,Any,
Vararg{Any,N}}
const All32{T,N} = Tuple{T,T,T,T,T,T,T,T,
T,T,T,T,T,T,T,T,
T,T,T,T,T,T,T,T,
T,T,T,T,T,T,T,T,
Vararg{T,N}}
function map(f, t::Any32)
n = length(t)
A = Vector{Any}(undef, n)
for i=1:n
Expand All @@ -235,7 +241,7 @@ 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)
function map(f, t::Any32, s::Any32)
n = length(t)
A = Vector{Any}(undef, n)
for i = 1:n
Expand All @@ -251,7 +257,7 @@ 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...)
function map(f, t1::Any32, t2::Any32, ts::Any32...)
n = length(t1)
A = Vector{Any}(undef, n)
for i = 1:n
Expand Down Expand Up @@ -317,8 +323,8 @@ function _totuple(T, itr, s...)
end

# use iterative algorithm for long tuples
function _totuple(T::Type{All16{E,N}}, itr) where {E,N}
len = N+16
function _totuple(T::Type{All32{E,N}}, itr) where {E,N}
len = N+32
elts = collect(E, Iterators.take(itr,len))
if length(elts) != len
_totuple_err(T)
Expand All @@ -342,15 +348,15 @@ end
filter(f, xs::Tuple) = afoldl((ys, x) -> f(x) ? (ys..., x) : ys, (), xs...)

# use Array for long tuples
filter(f, t::Any16) = Tuple(filter(f, collect(t)))
filter(f, t::Any32) = Tuple(filter(f, collect(t)))

## comparison ##

isequal(t1::Tuple, t2::Tuple) = (length(t1) == length(t2)) && _isequal(t1, t2)
_isequal(t1::Tuple{}, t2::Tuple{}) = true
_isequal(t1::Tuple{Any}, t2::Tuple{Any}) = isequal(t1[1], t2[1])
_isequal(t1::Tuple, t2::Tuple) = isequal(t1[1], t2[1]) && _isequal(tail(t1), tail(t2))
function _isequal(t1::Any16, t2::Any16)
function _isequal(t1::Any32, t2::Any32)
for i = 1:length(t1)
if !isequal(t1[i], t2[i])
return false
Expand Down Expand Up @@ -380,7 +386,7 @@ function _eq_missing(t1::Tuple, t2::Tuple)
return _eq_missing(tail(t1), tail(t2))
end
end
function _eq(t1::Any16, t2::Any16)
function _eq(t1::Any32, t2::Any32)
anymissing = false
for i = 1:length(t1)
eq = (t1[i] == t2[i])
Expand All @@ -396,7 +402,7 @@ end
const tuplehash_seed = UInt === UInt64 ? 0x77cfa1eef01bca90 : 0xf01bca90
hash(::Tuple{}, h::UInt) = h + tuplehash_seed
hash(t::Tuple, h::UInt) = hash(t[1], hash(tail(t), h))
function hash(t::Any16, h::UInt)
function hash(t::Any32, h::UInt)
out = h + tuplehash_seed
for i = length(t):-1:1
out = hash(t[i], out)
Expand All @@ -417,7 +423,7 @@ function <(t1::Tuple, t2::Tuple)
end
return tail(t1) < tail(t2)
end
function <(t1::Any16, t2::Any16)
function <(t1::Any32, t2::Any32)
n1, n2 = length(t1), length(t2)
for i = 1:min(n1, n2)
a, b = t1[i], t2[i]
Expand All @@ -444,7 +450,7 @@ function isless(t1::Tuple, t2::Tuple)
a, b = t1[1], t2[1]
isless(a, b) || (isequal(a, b) && isless(tail(t1), tail(t2)))
end
function isless(t1::Any16, t2::Any16)
function isless(t1::Any32, t2::Any32)
n1, n2 = length(t1), length(t2)
for i = 1:min(n1, n2)
a, b = t1[i], t2[i]
Expand Down

0 comments on commit bc42920

Please sign in to comment.