Skip to content

Commit d5ad85a

Browse files
authored
rand(BigFloat): create BigFloat with precision according to the sampler (#38169)
If the global precision for BigFloat changed between creating the sampler and generating a random BigFloat, bad things would happen, in particular if the precision was decreasing (we would write into arrays out-of-bounds). So create a fresh BigFloat without consideration for the current precision, only for the precision stored in the sampler.
1 parent 6d49bc9 commit d5ad85a

File tree

2 files changed

+17
-1
lines changed

2 files changed

+17
-1
lines changed

stdlib/Random/src/generation.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ Sampler(::Type{<:AbstractRNG}, I::FloatInterval{BigFloat}, ::Repetition) =
5757
SamplerBigFloat{typeof(I)}(precision(BigFloat))
5858

5959
function _rand!(rng::AbstractRNG, z::BigFloat, sp::SamplerBigFloat)
60+
precision(z) == sp.prec || throw(ArgumentError("incompatible BigFloat precision"))
6061
limbs = sp.limbs
6162
rand!(rng, limbs)
6263
@inbounds begin
@@ -100,7 +101,7 @@ rand!(rng::AbstractRNG, z::BigFloat, sp::SamplerBigFloat{T}
100101
_rand!(rng, z, sp, T())
101102

102103
rand(rng::AbstractRNG, sp::SamplerBigFloat{T}) where {T<:FloatInterval{BigFloat}} =
103-
rand!(rng, BigFloat(), sp)
104+
rand!(rng, BigFloat(; precision=sp.prec), sp)
104105

105106

106107
### random integers

stdlib/Random/test/runtests.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,4 +882,19 @@ end
882882
y = rand!(rng, x, s)
883883
@test y === x
884884
@test 1 <= x < 2
885+
886+
old_prec = precision(BigFloat)
887+
setprecision(100) do
888+
x = rand(s) # should use precision of s
889+
@test precision(x) == old_prec
890+
x = BigFloat()
891+
@test_throws ArgumentError rand!(rng, x, s) # incompatible precision
892+
end
893+
s = setprecision(100) do
894+
Random.Sampler(MersenneTwister, Random.CloseOpen01(BigFloat))
895+
end
896+
x = rand(s) # should use precision of s
897+
@test precision(x) == 100
898+
x = BigFloat()
899+
@test_throws ArgumentError rand!(rng, x, s) # incompatible precision
885900
end

0 commit comments

Comments
 (0)