Skip to content

Commit 700c6d2

Browse files
committed
Various improvements (no closures for reducing inner allocations)
1 parent 1c4efb5 commit 700c6d2

File tree

1 file changed

+20
-13
lines changed

1 file changed

+20
-13
lines changed

src/TupleTools.jl

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ else
3030
end
3131

3232
if VERSION >= v"0.7-" # to fix type instability in (f)indmin / (f)indmax
33-
Base.Pair(p::Tuple{Any,Any}) = p[1] => p[2]
34-
Base.pairs(collection) = Base.Generator(=>, zip(keys(collection), values(collection)))
33+
Base.pairs(collection) = (k=>v for (k,v) in zip(keys(collection), values(collection)))
3534
end
3635

3736
@inline argtail2(a, b, c...) = c
@@ -82,12 +81,20 @@ not expanded.
8281
Delete the element at location `i` in `t`; if a list `I` of indices is specified
8382
(again as a tuple), the elements of these different positions are deleted.
8483
"""
85-
@inline deleteat(t::Tuple, I::Tuple{Int}) = deleteat(t, I[1])
86-
@inline deleteat(t::Tuple, I::Tuple{Int, Int, Vararg{Int}}) = deleteat(deleteat(t, I[1]), map(i->(i<I[1] ? i : i-1), tail(I)))
87-
@inline deleteat(t::Tuple, i::Int) = 1 <= i <= length(t) ? _deleteat(t, i) : throw(BoundsError(t, i))
84+
deleteat(t::Tuple, I::Tuple{Int}) = deleteat(t, I[1])
85+
function deleteat(t::Tuple, I::Tuple{Int, Int, Vararg{Int}})
86+
any(i->(1 <= i <= length(t)), I) && throw(BoundsError(t, I))
87+
_deleteat(_deleteat(t, I[1]), ishift(tail(I), I[1], -1))
88+
end
89+
deleteat(t::Tuple, i::Int) = 1 <= i <= length(t) ? _deleteat(t, i) : throw(BoundsError(t, i))
8890
@inline _deleteat(t::Tuple, i::Int) = i == 1 ? tail(t) : (t[1], _deleteat(tail(t), i-1)...)
8991
@inline _deleteat(t::Tuple{}, i::Int) = throw(BoundsError(t, i))
9092

93+
@inline _deleteat(t::Tuple, I::Tuple{Int}) = _deleteat(t, I[1])
94+
@inline _deleteat(t::Tuple, I::Tuple{Int,Int,Vararg{Int}}) = _deleteat(_deleteat(t, I[1]), tail(I)) # assumes sorted from big to small
95+
96+
ishift(t::Tuple{Vararg{Int}}, i::Int, s::Int) = map(n->(n < i ? n : n+s), t)
97+
9198
"""
9299
insertat(t::Tuple, i::Int, t2::Tuple) -> ::Tuple
93100
@@ -100,7 +107,6 @@ look as (t[1:i-1]..., t2..., t[i+1:end]). Note that element `t[i]` is deleted. S
100107
@inline _insertat(t::Tuple, i::Int, t2::Tuple) = i == 1 ? (t2..., tail(t)...) : (t[1], _insertat(tail(t), i-1, t2)...)
101108
@inline _insertat(t::Tuple{}, i::Int, t2::Tuple) = throw(BoundsError(t, i))
102109

103-
104110
"""
105111
sort(t::Tuple; lt=isless, by=identity, rev::Bool=false) -> ::Tuple
106112
@@ -121,7 +127,7 @@ Sorts the tuple `t`.
121127
end
122128
end
123129
end
124-
return (t[i], sort(deleteat(t, i); lt = lt, by = by, rev = rev)...)
130+
return (t[i], sort(_deleteat(t, i); lt = lt, by = by, rev = rev)...)
125131
end
126132
@inline sort(t::Tuple{Any}; lt=isless, by=identity, rev::Bool=false) = t
127133

@@ -131,7 +137,8 @@ end
131137
132138
Computes a tuple that contains the permutation required to sort `t`.
133139
"""
134-
@inline function sortperm(t::Tuple; lt=isless, by=identity, rev::Bool=false)
140+
sortperm(t::Tuple; lt=isless, by=identity, rev::Bool=false) = _sortperm(t, lt, by, rev)
141+
@inline function _sortperm(t::Tuple, lt=isless, by=identity, rev::Bool=false)
135142
i::Int = 1
136143
if rev
137144
for k = 2:length(t)
@@ -146,10 +153,10 @@ Computes a tuple that contains the permutation required to sort `t`.
146153
end
147154
end
148155
end
149-
r = sortperm(deleteat(t, i); lt = lt, by = by, rev = rev)
150-
return (i, map(n->(n < i ? n : n+1), r)...)
156+
r = _sortperm(_deleteat(t, i), lt, by, rev)
157+
return (i, ishift(r, i, +1)...)
151158
end
152-
@inline sortperm(t::Tuple{Any}; lt=isless, by=identity, rev::Bool=false) = (1,)
159+
@inline _sortperm(t::Tuple{Any}, lt=isless, by=identity, rev::Bool=false) = (1,)
153160

154161
"""
155162
getindices(t::Tuple, I::Tuple{Vararg{Int}}) -> ::Tuple
@@ -164,8 +171,8 @@ Get the indices `t[i] for i in I`, again as tuple.
164171
165172
Permute the elements of tuple `t` according to the permutation in `p`.
166173
"""
167-
permute(t::NTuple{N}, p::NTuple{N,Int}) where {N} = isperm(p) ? getindices(t, p) : throw(ArgumentError("not a valid permutation: $p"))
168-
permute(t::NTuple{N}, p) where {N} = isperm(p) && length(p) == N ? ntuple(n->t[p[n]], StaticLength(N)) : throw(ArgumentError("not a valid permutation: $p"))
174+
@inline permute(t::NTuple{N}, p::NTuple{N,Int}) where {N} = isperm(p) ? getindices(t, p) : throw(ArgumentError("not a valid permutation: $p"))
175+
@inline permute(t::NTuple{N}, p) where {N} = isperm(p) && length(p) == N ? ntuple(n->t[p[n]], StaticLength(N)) : throw(ArgumentError("not a valid permutation: $p"))
169176

170177
"""
171178
invperm(p::NTuple{N,Int}) -> ::NTuple{N,Int}

0 commit comments

Comments
 (0)