Skip to content

Commit

Permalink
add rand(::Type{<:Pair}) (#28705)
Browse files Browse the repository at this point in the history
This adds e.g. `rand(Pair{Int,Int})` producing a random pair of `Int`.
  • Loading branch information
rfourquet authored Oct 7, 2023
1 parent 0296599 commit e4c9031
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 4 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ Standard library changes

* When seeding RNGs provided by `Random`, negative integer seeds can now be used ([#51416]).

* `rand` now supports sampling over `Pair` types ([#28705]).

#### REPL

* Tab complete hints now show in lighter text while typing in the repl. To disable
Expand Down
7 changes: 5 additions & 2 deletions stdlib/Random/src/Random.jl
Original file line number Diff line number Diff line change
Expand Up @@ -330,8 +330,11 @@ Pick a random element or array of random elements from the set of values specifi
+ a user-defined type and set of values; for implementation guidance please see [Hooking into the `Random` API](@ref rand-api-hook)
+ `S` can also be a tuple type of known size and where each parameter of `S` is itself a sampleable type; return a value of type `S`.
Note that tuple types such as `Tuple{Vararg{T}}` (unknown size) and `Tuple{1:2}` (parameterized with a value) are not supported.
+ a tuple type of known size and where each parameter of `S` is itself a sampleable type; return a value of type `S`.
Note that tuple types such as `Tuple{Vararg{T}}` (unknown size) and `Tuple{1:2}` (parameterized with a value) are not supported
+ a `Pair` type, e.g. `Pair{X, Y}` such that `rand` is defined for `X` and `Y`,
in which case random pairs are produced.
`S` defaults to [`Float64`](@ref).
Expand Down
13 changes: 13 additions & 0 deletions stdlib/Random/src/generation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,19 @@ function rand(rng::AbstractRNG, sp::SamplerTag{T}) where T<:Tuple
ntuple(i -> rand(rng, sp.data[min(i, length(sp.data))]), Val{fieldcount(T)}())::T
end

### random pairs

function Sampler(::Type{RNG}, ::Type{Pair{A, B}}, n::Repetition) where {RNG<:AbstractRNG, A, B}
sp1 = Sampler(RNG, A, n)
sp2 = A === B ? sp1 : Sampler(RNG, B, n)
SamplerTag{Ref{Pair{A,B}}}(sp1 => sp2) # Ref so that the gentype is Pair{A, B}
# in SamplerTag's constructor
end

rand(rng::AbstractRNG, sp::SamplerTag{<:Ref{<:Pair}}) =
rand(rng, sp.data.first) => rand(rng, sp.data.second)


## Generate random integer within a range

### BitInteger
Expand Down
18 changes: 16 additions & 2 deletions stdlib/Random/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,8 @@ end
for rng in ([], [MersenneTwister(0)], [RandomDevice()], [Xoshiro()])
ftypes = [Float16, Float32, Float64, FakeFloat64, BigFloat]
cftypes = [ComplexF16, ComplexF32, ComplexF64, ftypes...]
types = [Bool, Char, BigFloat, Tuple{Bool, Tuple{Int, Char}}, Base.BitInteger_types..., cftypes...]
types = [Bool, Char, BigFloat, Tuple{Bool, Tuple{Int, Char}}, Pair{Int8, UInt32},
Base.BitInteger_types..., cftypes...]
randset = Set(rand(Int, 20))
randdict = Dict(zip(rand(Int,10), rand(Int, 10)))

Expand Down Expand Up @@ -365,7 +366,7 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()], [Xoshiro()])
end
for f! in [rand!, randn!, randexp!]
for T in functypes[f!]
(T <: Tuple) && continue
(T <: Tuple || T <: Pair) && continue
X = T == Bool ? T[0,1] : T[0,1,2]
for A in (Vector{T}(undef, 5),
Matrix{T}(undef, 2, 3),
Expand Down Expand Up @@ -1180,3 +1181,16 @@ end
@test Random.hash_seed(map(UInt64, seed32)) == hash32
@test hash32 keys(vseeds)
end

@testset "rand(::Type{<:Pair})" begin
@test rand(Pair{Int, Int}) isa Pair{Int, Int}
@test rand(Pair{Int, Float64}) isa Pair{Int, Float64}
@test rand(Pair{Int, Float64}, 3) isa Array{Pair{Int, Float64}}

# test that making an array out of a sampler works
# (i.e. that gentype(sp) is correct)
sp = Random.Sampler(AbstractRNG, Pair{Bool, Char})
xs = rand(sp, 3)
@test xs isa Vector{Pair{Bool, Char}}
@test length(xs) == 3
end

0 comments on commit e4c9031

Please sign in to comment.