-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
implement rand(::BigFloat) (close #13948) #22720
Conversation
base/random.jl
Outdated
function rand!(r::AbstractRNG, A::AbstractArray, s::Union{Dict,Set,IntSet}) | ||
rand!(r::AbstractRNG, A::AbstractArray, ::Type{T}) where {T<:AbstractFloat} = | ||
rand!(r, A, CloseOpen{T}()) | ||
rand!(A::AbstractArray, ::Type{T}) where {T<:AbstractFloat} = rand!(GLOBAL_RNG, A, T) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't this completely redundant with the more general version just above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes thanks
Isn't the branch optimized away if you do |
Excellent, not directly (at least I don't see it) but appartently yes with For |
cc02754
to
261f323
Compare
I decided to implement the full precision |
doc/src/stdlib/numbers.md
Outdated
(or complex numbers of those types). Random floating point numbers are generated uniformly | ||
in ``[0, 1)``. As `BigInt` represents unbounded integers, the interval must be specified | ||
(e.g. `rand(big(1:6))`). | ||
[`Float16`](@ref), [`Float32`](@ref), [`Float64`](@ref), [`Float64`](@ref),[`Bool`](@ref), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the Float64 you added here supposed to be BigFloat?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oups yes! (rebase mistake)
261f323
to
844277a
Compare
844277a
to
c3c9507
Compare
The Travis and circleci failures have to do |
This uses a similar method as for
Float64
: generate uniformly sufficiently many random bits to get a numberx
in[1, 2)
.Then there are two simple possibilities (cf. this nice write-up):
x-1.0
: then one bit of precision is lostrand(Bool) ? x/2 : x/2-0.5
For
Float64
, we do option 1) as dSFMT generates only 52 random bits per iteration, whenFloat64
has 53 bits of precision, and this is way faster (the cost of the branch of option 2 is non-negligible).For
BigFloat
, the two options have similar performances (within few percents, and option 2) even is slightly faster than 1) for higher precisions), so I would favor this one. On the other hand, option 1) has the advantage that it would behave similarly to other floats when their precision is set to match (e.g.rand(BigFloat)
would behave likerand(Float64)
whenprecision(BigFloat) == 53
). "RFC" until this is decided (option 1 is commented out here, if someone wants to play with it).One possibility would be to have something along the lines of having
rand(CloseOpen{T})
generate 1 random a float of typeT
with 1 bit less than the precision,rand(CloseOpenFull{T})
generate at full precision number, andrand(T)
generate the best of the 2 options (1 forFloat64
and 2 forBigFloat
). This would incidentaly solve #16344, by allowing to get randomFloat64
at full precision (opt-in), which is not terribly slow after all: on my machine, this takes 14ns for full precision vs 5ns for 52 bits precision.