Skip to content

Commit c271362

Browse files
committed
add rand(::Tuple)
1 parent 80820ac commit c271362

File tree

4 files changed

+66
-4
lines changed

4 files changed

+66
-4
lines changed

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ Standard library changes
5252
* `Base.tail` now works on named tuples ([#29595]).
5353
* `randperm` and `randcycle` now use the type of their argument to determine the element type of
5454
the returned array ([#29670]).
55+
* A new method `rand(::Tuple)` implements sampling from the values of a tuple ([#25278]).
5556

5657
Compiler/Runtime improvements
5758
-----------------------------

stdlib/Random/src/Random.jl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ rand(rng::AbstractRNG, ::UniformT{T}) where {T} = rand(rng, T)
217217
#### scalars
218218

219219
rand(rng::AbstractRNG, X) = rand(rng, Sampler(rng, X, Val(1)))
220+
# this is needed to disambiguate
221+
rand(rng::AbstractRNG, X::Dims) = rand(rng, Sampler(rng, X, Val(1)))
220222
rand(rng::AbstractRNG=GLOBAL_RNG, ::Type{X}=Float64) where {X} = rand(rng, Sampler(rng, X, Val(1)))
221223

222224
rand(X) = rand(GLOBAL_RNG, X)
@@ -249,9 +251,6 @@ rand( X, d::Integer, dims::Integer...) = rand(X, Dims((d, dims...
249251
# rand(r, ()) would match both this method and rand(r, dims::Dims)
250252
# moreover, a call like rand(r, NotImplementedType()) would be an infinite loop
251253

252-
# this is needed to disambiguate
253-
rand(r::AbstractRNG, dims::Dims) = error("rand(rng, dims) is discontinued; try rand(rng, Float64, dims)")
254-
255254
rand(r::AbstractRNG, ::Type{X}, dims::Dims) where {X} = rand!(r, Array{X}(undef, dims), X)
256255
rand( ::Type{X}, dims::Dims) where {X} = rand(GLOBAL_RNG, X, dims)
257256

@@ -283,7 +282,7 @@ include("misc.jl")
283282
Pick a random element or array of random elements from the set of values specified by `S`;
284283
`S` can be
285284
286-
* an indexable collection (for example `1:n` or `['x','y','z']`),
285+
* an indexable collection (for example `1:9` or `('x', "y", :z)`),
287286
* an `AbstractDict` or `AbstractSet` object,
288287
* a string (considered as a collection of characters), or
289288
* a type: the set of values to pick from is then equivalent to `typemin(S):typemax(S)` for

stdlib/Random/src/generation.jl

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,3 +430,54 @@ function rand(rng::AbstractRNG, sp::SamplerSimple{<:AbstractString,<:Sampler})::
430430
isvalid_unsafe(str, pos) && return str[pos]
431431
end
432432
end
433+
434+
435+
## random elements from tuples
436+
437+
### 1
438+
439+
Sampler(::Type{<:AbstractRNG}, t::Tuple{A}, ::Repetition) where {A} =
440+
SamplerTrivial(t)
441+
442+
rand(rng::AbstractRNG, sp::SamplerTrivial{Tuple{A}}) where {A} =
443+
@inbounds return sp[][1]
444+
445+
### 2
446+
447+
Sampler(RNG::Type{<:AbstractRNG}, t::Tuple{A,B}, n::Repetition) where {A,B} =
448+
SamplerSimple(t, Sampler(RNG, Bool, n))
449+
450+
rand(rng::AbstractRNG, sp::SamplerSimple{Tuple{A,B}}) where {A,B} =
451+
@inbounds return sp[][1 + rand(rng, sp.data)]
452+
453+
### 3
454+
455+
Sampler(RNG::Type{<:AbstractRNG}, t::Tuple{A,B,C}, n::Repetition) where {A,B,C} =
456+
SamplerSimple(t, Sampler(RNG, UInt52(), n))
457+
458+
function rand(rng::AbstractRNG, sp::SamplerSimple{Tuple{A,B,C}}) where {A,B,C}
459+
local r
460+
while true
461+
r = rand(rng, sp.data)
462+
r != 0x000fffffffffffff && break # _very_ likely
463+
end
464+
@inbounds return sp[][1 + r ÷ 0x0005555555555555]
465+
end
466+
467+
### 4
468+
469+
Sampler(RNG::Type{<:AbstractRNG}, t::Tuple{A,B,C,D}, n::Repetition) where {A,B,C,D} =
470+
SamplerSimple(t, Sampler(RNG, UInt52Raw(Int), n))
471+
472+
function rand(rng::AbstractRNG, sp::SamplerSimple{Tuple{A,B,C,D}}) where {A,B,C,D}
473+
r = rand(rng, sp.data) & 3
474+
@inbounds return sp[][1 + r]
475+
end
476+
477+
### n
478+
479+
Sampler(RNG::Type{<:AbstractRNG}, t::Tuple, n::Repetition) =
480+
SamplerSimple(t, Sampler(RNG, Base.OneTo(length(t)), n))
481+
482+
rand(rng::AbstractRNG, sp::SamplerSimple{<:Tuple}) =
483+
@inbounds return sp[][rand(rng, sp.data)]

stdlib/Random/test/runtests.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,3 +702,14 @@ end
702702
a = rand(Int, 1)
703703
@test shuffle(a) == a
704704
end
705+
706+
@testset "rand(::Tuple)" begin
707+
for x in (0x1, 1)
708+
@test rand((x,)) == 0x1
709+
@test rand((x, 2)) 1:2
710+
@test rand((x, 2, 3)) 1:3
711+
@test rand((x, 2, 3, 4)) 1:4
712+
@test rand((x, 2, 3, 4, 5)) 1:5
713+
@test rand((x, 2, 3, 4, 6)) 1:6
714+
end
715+
end

0 commit comments

Comments
 (0)