Skip to content

Commit

Permalink
add rand(::Tuple)
Browse files Browse the repository at this point in the history
  • Loading branch information
rfourquet committed Aug 13, 2018
1 parent 0846eb5 commit bb0d78a
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 3 deletions.
5 changes: 2 additions & 3 deletions stdlib/Random/src/Random.jl
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ rand(rng::AbstractRNG, ::UniformT{T}) where {T} = rand(rng, T)
#### scalars

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

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

# this is needed to disambiguate
rand(r::AbstractRNG, dims::Dims) = error("rand(rng, dims) is discontinued; try rand(rng, Float64, dims)")

rand(r::AbstractRNG, ::Type{X}, dims::Dims) where {X} = rand!(r, Array{X}(undef, dims), X)
rand( ::Type{X}, dims::Dims) where {X} = rand(GLOBAL_RNG, X, dims)

Expand Down
51 changes: 51 additions & 0 deletions stdlib/Random/src/generation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -430,3 +430,54 @@ function rand(rng::AbstractRNG, sp::SamplerSimple{<:AbstractString,<:Sampler})::
isvalid_unsafe(str, pos) && return str[pos]
end
end


## random elements from tuples

### 1

Sampler(::Type{<:AbstractRNG}, t::Tuple{A}, ::Repetition) where {A} =
SamplerTrivial(t)

rand(rng::AbstractRNG, sp::SamplerTrivial{Tuple{A}}) where {A} =
@inbounds return sp[][1]

### 2

Sampler(RNG::Type{<:AbstractRNG}, t::Tuple{A,B}, n::Repetition) where {A,B} =
SamplerSimple(t, Sampler(RNG, Bool, n))

rand(rng::AbstractRNG, sp::SamplerSimple{Tuple{A,B}}) where {A,B} =
@inbounds return sp[][1 + rand(rng, sp.data)]

### 3

Sampler(RNG::Type{<:AbstractRNG}, t::Tuple{A,B,C}, n::Repetition) where {A,B,C} =
SamplerSimple(t, Sampler(RNG, UInt52(), n))

function rand(rng::AbstractRNG, sp::SamplerSimple{Tuple{A,B,C}}) where {A,B,C}
local r
while true
r = rand(rng, sp.data)
r != 0x000fffffffffffff && break # _very_ likely
end
@inbounds return sp[][1 + r ÷ 0x0005555555555555]
end

### 4

Sampler(RNG::Type{<:AbstractRNG}, t::Tuple{A,B,C,D}, n::Repetition) where {A,B,C,D} =
SamplerSimple(t, Sampler(RNG, UInt52Raw(Int), n))

function rand(rng::AbstractRNG, sp::SamplerSimple{Tuple{A,B,C,D}}) where {A,B,C,D}
r = rand(rng, sp.data) & 3
@inbounds return sp[][1 + r]
end

### n

Sampler(RNG::Type{<:AbstractRNG}, t::Tuple, n::Repetition) =
SamplerSimple(t, Sampler(RNG, Base.OneTo(length(t)), n))

rand(rng::AbstractRNG, sp::SamplerSimple{<:Tuple}) =
@inbounds return sp[][rand(rng, sp.data)]
11 changes: 11 additions & 0 deletions stdlib/Random/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -686,3 +686,14 @@ end
@test Random.gentype(Random.UInt52(UInt128)) == UInt128
@test Random.gentype(Random.UInt104()) == UInt128
end

@testset "rand(::Tuple)" begin
for x in (0x1, 1)
@test rand((x,)) == 0x1
@test rand((x, 2)) 1:2
@test rand((x, 2, 3)) 1:3
@test rand((x, 2, 3, 4)) 1:4
@test rand((x, 2, 3, 4, 5)) 1:5
@test rand((x, 2, 3, 4, 6)) 1:6
end
end

0 comments on commit bb0d78a

Please sign in to comment.