@@ -183,6 +183,34 @@ ltm52(n::Int, mask::Int=nextpow(2, n)-1) = LessThan(n-1, Masked(mask, UInt52Raw(
183
183
184
184
# # shuffle & shuffle!
185
185
186
+ function shuffle (rng:: AbstractRNG , tup:: NTuple{N} ) where {N}
187
+ # `@inline` and `@inbounds` are here to help escape analysis eliminate the `Memory` allocation
188
+ #
189
+ # * `@inline` might be necessary because escape analysis relies on everything
190
+ # touching the `Memory` being inlined because there's no interprocedural escape
191
+ # analysis yet, relevant WIP PR: https://github.com/JuliaLang/julia/pull/56849
192
+ #
193
+ # * `@inbounds` might be necessary because escape analysis requires any throws of
194
+ # `BoundsError` to be eliminated as dead code, because `BoundsError` stores the
195
+ # array itself, making the throw escape the array from the function, relevant
196
+ # WIP PR: https://github.com/JuliaLang/julia/pull/56167
197
+ @inline let
198
+ # use a narrow integer type to save stack space and prevent heap allocation
199
+ Ind = if N ≤ typemax (UInt8)
200
+ UInt8
201
+ elseif N ≤ typemax (UInt16)
202
+ UInt16
203
+ else
204
+ UInt
205
+ end
206
+ mem = @inbounds randperm! (rng, Memory {Ind} (undef, N))
207
+ function closure (i:: Int )
208
+ @inbounds tup[mem[i]]
209
+ end
210
+ ntuple (closure, Val {N} ())
211
+ end
212
+ end
213
+
186
214
"""
187
215
shuffle!([rng=default_rng(),] v::AbstractArray)
188
216
@@ -238,13 +266,16 @@ end
238
266
shuffle! (a:: AbstractArray ) = shuffle! (default_rng (), a)
239
267
240
268
"""
241
- shuffle([rng=default_rng(),] v::AbstractArray)
269
+ shuffle([rng=default_rng(),] v::Union{NTuple, AbstractArray} )
242
270
243
271
Return a randomly permuted copy of `v`. The optional `rng` argument specifies a random
244
272
number generator (see [Random Numbers](@ref)).
245
273
To permute `v` in-place, see [`shuffle!`](@ref). To obtain randomly permuted
246
274
indices, see [`randperm`](@ref).
247
275
276
+ !!! compat "Julia 1.13"
277
+ Shuffling an `NTuple` value requires Julia v1.13 or above.
278
+
248
279
# Examples
249
280
```jldoctest
250
281
julia> shuffle(Xoshiro(123), Vector(1:10))
@@ -261,8 +292,10 @@ julia> shuffle(Xoshiro(123), Vector(1:10))
261
292
7
262
293
```
263
294
"""
295
+ function shuffle end
296
+
264
297
shuffle (r:: AbstractRNG , a:: AbstractArray ) = shuffle! (r, copymutable (a))
265
- shuffle (a:: AbstractArray ) = shuffle (default_rng (), a)
298
+ shuffle (a:: Union{NTuple, AbstractArray} ) = shuffle (default_rng (), a)
266
299
267
300
shuffle (r:: AbstractRNG , a:: Base.OneTo ) = randperm (r, last (a))
268
301
0 commit comments