@@ -27,6 +27,28 @@ Base.@pure Base.:+(::StaticLength{N₁}, ::StaticLength{N₂}) where {N₁,N₂}
27
27
Base. @pure Base.:- (:: StaticLength{N₁} , :: StaticLength{N₂} ) where {N₁,N₂} = StaticLength (max (0 ,N₁- N₂))
28
28
29
29
@inline Base. ntuple (f, :: StaticLength{N} ) where {N} = ntuple (f, Val {N} ())
30
+
31
+ mutable struct MutableNTuple{N,T}
32
+ data:: NTuple{N,T}
33
+ function MutableNTuple (data:: NTuple{N,T} ) where {N,T}
34
+ @assert isbitstype (T)
35
+ return new {N,T} (data)
36
+ end
37
+ end
38
+
39
+ Base. @propagate_inbounds function Base. getindex (t:: MutableNTuple{N,T} , i:: Int ) where {N,T}
40
+ @boundscheck checkbounds (Base. OneTo (N),i)
41
+ GC. @preserve t unsafe_load (Base. unsafe_convert (Ptr{T}, pointer_from_objref (t)), i)
42
+ end
43
+
44
+ Base. @propagate_inbounds function Base. setindex! (t:: MutableNTuple{N,T} , val, i:: Int ) where {N,T}
45
+ @boundscheck checkbounds (Base. OneTo (N),i)
46
+ GC. @preserve t unsafe_store! (Base. unsafe_convert (Ptr{T}, pointer_from_objref (t)), convert (T, val), i)
47
+ return t
48
+ end
49
+
50
+ @inline Base. Tuple (t:: MutableNTuple ) = t. data
51
+
30
52
@inline argtail2 (a, b, c... ) = c
31
53
32
54
"""
@@ -130,7 +152,7 @@ Returns the sum of the element of a tuple, or `0` for an empty tuple.
130
152
"""
131
153
sum (t:: Tuple{} ) = 0
132
154
sum (t:: Tuple{Any} ) = t[1 ]
133
- sum (t:: Tuple ) = t[1 ]+ sum (tail (t))
155
+ sum (t:: Tuple ) = t[1 ] + sum (tail (t))
134
156
135
157
"""
136
158
cumsum(t::Tuple)
@@ -151,7 +173,7 @@ Returns the product of the elements of a tuple, or `1` for an empty tuple.
151
173
"""
152
174
prod (t:: Tuple{} ) = 1
153
175
prod (t:: Tuple{Any} ) = t[1 ]
154
- prod (t:: Tuple ) = t[1 ]* prod (tail (t))
176
+ prod (t:: Tuple ) = t[1 ] * prod (tail (t))
155
177
156
178
"""
157
179
cumprod(t::Tuple)
@@ -284,16 +306,41 @@ _permute(t::NTuple{N,Any}, p) where {N} = ntuple(n->t[p[n]], StaticLength(N))
284
306
285
307
A non-allocating alternative to Base.isperm(p) that is much faster for small permutations.
286
308
"""
287
- function isperm (p)
288
- N = length (p)
289
- @inbounds for i = 1 : N
290
- 1 <= p[i] <= N || return false
291
- for j = i+ 1 : N
292
- p[i] == p[j] && return false
309
+ function isperm (p:: NTuple{N,Integer} ) where N
310
+ used = MutableNTuple (ntuple (n-> false , Val (N)))
311
+ @inbounds for i in p
312
+ if 0 < i <= N && used[i] == false
313
+ used[i] = true
314
+ else
315
+ return false
293
316
end
294
317
end
295
318
return true
296
319
end
320
+ isperm (p:: Tuple{} ) = true
321
+ isperm (p:: Tuple{Int} ) = p[1 ] == 1
322
+ isperm (p:: Tuple{Int,Int} ) = ((p[1 ] == 1 ) & (p[2 ] == 2 )) | ((p[1 ] == 2 ) & (p[2 ] == 1 ))
323
+ function isperm (p:: Tuple{Int,Int,Int} )
324
+ return ! (p[1 ] < 1 || p[1 ] > 3 || p[2 ] < 1 || p[2 ] > 3 || p[3 ] < 1 || p[3 ] > 3 ||
325
+ p[1 ] == p[2 ] || p[1 ] == p[3 ] || p[2 ] == p[3 ])
326
+ end
327
+ function isperm (p:: Tuple{Int,Int,Int,Int} )
328
+ return ! (p[1 ] < 1 || p[1 ] > 4 || p[2 ] < 1 || p[2 ] > 4 ||
329
+ p[3 ] < 1 || p[3 ] > 4 || p[4 ] < 1 || p[4 ] > 4 ||
330
+ p[1 ] == p[2 ] || p[1 ] == p[3 ] || p[1 ] == p[4 ] ||
331
+ p[2 ] == p[3 ] || p[2 ] == p[4 ] || p[3 ] == p[4 ])
332
+ end
333
+
334
+ # function isperm(p)
335
+ # N = length(p)
336
+ # @inbounds for i = 1:N
337
+ # 1 <= p[i] <= N || return false
338
+ # for j = i+1:N
339
+ # p[i] == p[j] && return false
340
+ # end
341
+ # end
342
+ # return true
343
+ # end
297
344
298
345
"""
299
346
invperm(p::NTuple{N,Int}) -> ::NTuple{N,Int}
0 commit comments