@@ -27,6 +27,28 @@ Base.@pure Base.:+(::StaticLength{N₁}, ::StaticLength{N₂}) where {N₁,N₂}
2727Base. @pure Base.:- (:: StaticLength{N₁} , :: StaticLength{N₂} ) where {N₁,N₂} = StaticLength (max (0 ,N₁- N₂))
2828
2929@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+
3052@inline argtail2 (a, b, c... ) = c
3153
3254"""
@@ -130,7 +152,7 @@ Returns the sum of the element of a tuple, or `0` for an empty tuple.
130152"""
131153sum (t:: Tuple{} ) = 0
132154sum (t:: Tuple{Any} ) = t[1 ]
133- sum (t:: Tuple ) = t[1 ]+ sum (tail (t))
155+ sum (t:: Tuple ) = t[1 ] + sum (tail (t))
134156
135157"""
136158 cumsum(t::Tuple)
@@ -151,7 +173,7 @@ Returns the product of the elements of a tuple, or `1` for an empty tuple.
151173"""
152174prod (t:: Tuple{} ) = 1
153175prod (t:: Tuple{Any} ) = t[1 ]
154- prod (t:: Tuple ) = t[1 ]* prod (tail (t))
176+ prod (t:: Tuple ) = t[1 ] * prod (tail (t))
155177
156178"""
157179 cumprod(t::Tuple)
@@ -284,16 +306,41 @@ _permute(t::NTuple{N,Any}, p) where {N} = ntuple(n->t[p[n]], StaticLength(N))
284306
285307A non-allocating alternative to Base.isperm(p) that is much faster for small permutations.
286308"""
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
293316 end
294317 end
295318 return true
296319end
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
297344
298345"""
299346 invperm(p::NTuple{N,Int}) -> ::NTuple{N,Int}
0 commit comments