Skip to content

Commit f6d7d4a

Browse files
committed
remove some harmful @inline s, update docs, add tests
1 parent 995b11d commit f6d7d4a

File tree

3 files changed

+13
-29
lines changed

3 files changed

+13
-29
lines changed

docs/src/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# TupleTools.jl
22

3-
TupleTools contains a bunch of tools for using tuples (mostly homogeneous tuples `NTuple{N}`) as a collection and performing a number of operations with an inferrable result, typically also an `NTuple{M}` with inferable length `M`. ~~Type inference breaks down if some of the final or intermediate tuples exceed `MAX_TUPLETYPE_LEN`, meaning inference typically works up to output tuples of length `13` or `14`.~~ Chosen implementations are typically faster than the corresponding functions in base for those small tuple lengths, but can be slower for larger tuples. Inference breaks down for most functions in case of inhomogeneous tuples.
3+
TupleTools contains a bunch of tools for using tuples (mostly homogeneous tuples `NTuple{N}`) as a collection and performing a number of operations with an inferrable result, typically also an `NTuple{M}` with inferable length `M`. Chosen implementations are typically faster than the corresponding functions in base for those small tuple lengths, but can be slower for larger tuples. Inference breaks down for most functions in case of inhomogeneous tuples.
44

5-
Note that none of the following functions are exported, since their name often collides with the equivalent functions (with different implementations) in `Base`. Some functions here provided just have an equivalent in `Base` that doesn't work for tuples at all, like `sort`. Some functions also provide reasonable defaults assuming that they are used for tuples of `Int`s, i.e. `TupleTools.sum(()) = 0` or `TupleTools.prod(()) = 1` (whereas the corresponding `Base` functions would error). This originates from the assumption that these methods are used to operate on tuples of e.g. sizes, indices or strides of multidimensional arrays.
5+
Note that none of the following functions are exported, since their name often collides with the equivalent functions (with different implementations) in `Base`. Some functions here provided just have an equivalent in `Base` that doesn't work for tuples at all, like `sort` or `cumsum` and `cumprod`. Some functions also provide reasonable defaults assuming that they are used for tuples of `Int`s, i.e. `TupleTools.sum(()) = 0` or `TupleTools.prod(()) = 1` (whereas the corresponding `Base` functions would error). This originates from the assumption that these methods are used to operate on tuples of e.g. sizes, indices or strides of multidimensional arrays.
66

77
## Types
88

src/TupleTools.jl

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ end
9595
deleteat(t::Tuple, i::Int) =
9696
1 <= i <= length(t) ? _deleteat(t, i) : throw(BoundsError(t, i))
9797
@inline _deleteat(t::Tuple, i::Int) = i == 1 ? tail(t) : (t[1], _deleteat(tail(t), i-1)...)
98-
# @inline _deleteat(t::Tuple{}, i::Int) = throw(BoundsError(t, i))
9998

10099
@inline _deleteat(t::Tuple, I::Tuple{Int}) = _deleteat(t, I[1])
101100
@inline _deleteat(t::Tuple, I::Tuple{Int,Int,Vararg{Int}}) =
@@ -113,7 +112,6 @@ insertat(t::Tuple, i::Int, t2::Tuple) =
113112
1 <= i <= length(t) ? _insertat(t, i, t2) : throw(BoundsError(t, i))
114113
@inline _insertat(t::Tuple, i::Int, t2::Tuple) =
115114
i == 1 ? (t2..., tail(t)...) : (t[1], _insertat(tail(t), i-1, t2)...)
116-
@inline _insertat(t::Tuple{}, i::Int, t2::Tuple) = throw(BoundsError(t, i))
117115

118116
"""
119117
insertafter(t::Tuple, i::Int, t2::Tuple) -> ::Tuple
@@ -126,8 +124,6 @@ insertafter(t::Tuple, i::Int, t2::Tuple) =
126124
0 <= i <= length(t) ? _insertafter(t, i, t2) : throw(BoundsError(t, i))
127125
@inline _insertafter(t::Tuple, i::Int, t2::Tuple) =
128126
i == 0 ? (t2..., t...) : (t[1], _insertafter(tail(t), i-1, t2)...)
129-
@inline _insertafter(t::Tuple{}, i::Int, t2::Tuple) =
130-
i == 0 ? t2 : throw(BoundsError(t, i))
131127

132128
"""
133129
sum(t::Tuple)
@@ -145,7 +141,7 @@ Returns the cumulative sum of the elements of a tuple, or `()` for an empty tupl
145141
"""
146142
function cumsum(t::Tuple)
147143
t_1, t_tail = first(t), tail(t)
148-
return (t_1,cumsum((t_1+first(t_tail),tail(t_tail)...))...)
144+
return (t_1, cumsum((t_1 + first(t_tail), tail(t_tail)...))...)
149145
end
150146
cumsum(t::Tuple{Any}) = t
151147
cumsum(t::Tuple{}) = t
@@ -209,33 +205,15 @@ argmax(t::Tuple) = findmax(t)[2]
209205
Returns the value and index of the minimum element in a tuple. If there are multiple
210206
minimal elements, then the first one will be returned.
211207
"""
212-
findmin(t::Tuple{Any}) = (t[1], 1)
213-
findmin(t::Tuple) = _findmin(tail(t),2,t[1],1)
214-
_findmin(t::Tuple{}, s, v, i) = (v, i)
215-
@inline function _findmin(t::Tuple, s, v, i)
216-
if t[1] < v
217-
_findmin(tail(t), s+1, t[1], s)
218-
else
219-
_findmin(tail(t), s+1, v, i)
220-
end
221-
end
208+
findmin(t::Tuple) = Base.findmin(t)
222209

223210
"""
224211
findmax(t::Tuple)
225212
226213
Returns the value and index of the maximum element in a tuple. If there are multiple
227214
maximal elements, then the first one will be returned.
228215
"""
229-
findmax(t::Tuple{Any}) = (t[1], 1)
230-
findmax(t::Tuple) = _findmax(tail(t),2,t[1],1)
231-
_findmax(t::Tuple{}, s, v, i) = (v, i)
232-
@inline function _findmax(t::Tuple, s, v, i)
233-
if t[1] > v
234-
_findmax(tail(t), s+1, t[1], s)
235-
else
236-
_findmax(tail(t), s+1, v, i)
237-
end
238-
end
216+
findmax(t::Tuple) = Base.findmax(t)
239217

240218
"""
241219
sort(t::Tuple; lt=isless, by=identity, rev::Bool=false) -> ::Tuple
@@ -257,7 +235,7 @@ function _split(t::NTuple{N}) where N
257235
ntuple(i->t[i], M), ntuple(i->t[i+M], N-M)
258236
end
259237

260-
@inline function _merge(t1::Tuple, t2::Tuple, lt, by, rev)
238+
function _merge(t1::Tuple, t2::Tuple, lt, by, rev)
261239
if lt(by(first(t1)), by(first(t2))) != rev
262240
return (first(t1), _merge(tail(t1), t2, lt, by, rev)...)
263241
else
@@ -275,7 +253,7 @@ _merge(t1::Tuple, t2::Tuple{}, lt, by, rev) = t1
275253
Computes a tuple that contains the permutation required to sort `t`.
276254
"""
277255
sortperm(t::Tuple; lt=isless, by=identity, rev::Bool=false) = _sortperm(t, lt, by, rev)
278-
@inline function _sortperm(t::Tuple, lt=isless, by=identity, rev::Bool=false)
256+
function _sortperm(t::Tuple, lt=isless, by=identity, rev::Bool=false)
279257
_sort(ntuple(identity, length(t)), lt, i->by(getindex(t, i)), rev)
280258
end
281259

test/runtests.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,15 @@ for i = 1:n
2727
@test @inferred(TupleTools.insertat(t, i, (1,2,3))) == (vcat(p[1:i-1], [1,2,3], p[i+1:n])...,)
2828
end
2929
@test @inferred(TupleTools.deleteat((1,2,3,4,5,6), (3,1,5))) == (2,4,6)
30+
@test_throws BoundsError TupleTools.deleteat(t, 0)
31+
@test_throws BoundsError TupleTools.deleteat(t, n+1)
32+
@test_throws BoundsError TupleTools.insertat(t, 0, (1,2,3))
33+
@test_throws BoundsError TupleTools.insertat(t, n+1, (1,2,3))
3034
for i = 0:n
3135
@test @inferred(TupleTools.insertafter(t, i, (1,2,3))) == (vcat(p[1:i], [1,2,3], p[i+1:n])...,)
3236
end
37+
@test_throws BoundsError TupleTools.insertafter(t, -1, (1,2,3))
38+
@test_throws BoundsError TupleTools.insertafter(t, n+1, (1,2,3))
3339
@test @inferred(TupleTools.vcat((1,2,3),4,(5,),(),(6,7,8))) == (1,2,3,4,5,6,7,8)
3440
@test @inferred(TupleTools.flatten((1,2,3),4,(5,),(),(6,7,8))) == (1,2,3,4,5,6,7,8)
3541
@test @inferred(TupleTools.flatten((1,(2,3)),4,(5,),(),((6,),(7,(8,))))) == (1,2,3,4,5,6,7,8)

0 commit comments

Comments
 (0)