Skip to content

Commit aaa8f3a

Browse files
committed
faster randn!(::MersenneTwister, ::Array{Float64})
And `randexp!`.
1 parent 8e76b12 commit aaa8f3a

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

NEWS.md

+2
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ Standard library changes
154154

155155
#### Random
156156

157+
* `randn!(::MersenneTwister, ::Array{Float64})` is faster, and as a result, for a given state of the RNG,
158+
the corresponding generated numbers have changed ([#35078]).
157159

158160
#### REPL
159161

stdlib/Random/src/normal.jl

+24-4
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ julia> randn(rng, ComplexF32, (2, 3))
3535
0.611224+1.56403im 0.355204-0.365563im 0.0905552+1.31012im
3636
```
3737
"""
38-
@inline function randn(rng::AbstractRNG=default_rng())
38+
@inline randn(rng::AbstractRNG=default_rng()) = _randn(rng, rand(rng, UInt52Raw()))
39+
40+
@inline function _randn(rng::AbstractRNG, r::UInt64)
3941
@inbounds begin
40-
r = rand(rng, UInt52())
42+
r &= 0x000fffffffffffff
4143
rabs = Int64(r>>1) # One bit for the sign
4244
idx = rabs & 0xFF
4345
x = ifelse(r % Bool, -rabs, rabs)*wi[idx+1]
@@ -95,9 +97,11 @@ julia> randexp(rng, 3, 3)
9597
0.695867 0.693292 0.643644
9698
```
9799
"""
98-
function randexp(rng::AbstractRNG=default_rng())
100+
randexp(rng::AbstractRNG=default_rng()) = _randexp(rng, rand(rng, UInt52Raw()))
101+
102+
function _randexp(rng::AbstractRNG, ri::UInt64)
99103
@inbounds begin
100-
ri = rand(rng, UInt52())
104+
ri &= 0x000fffffffffffff
101105
idx = ri & 0xFF
102106
x = ri*we[idx+1]
103107
ri < ke[idx+1] && return x # 98.9% of the time we return here 1st try
@@ -162,6 +166,7 @@ function randexp! end
162166

163167
for randfun in [:randn, :randexp]
164168
randfun! = Symbol(randfun, :!)
169+
_randfun = Symbol(:_, randfun)
165170
@eval begin
166171
# scalars
167172
$randfun(rng::AbstractRNG, T::BitFloatType) = convert(T, $randfun(rng))
@@ -175,6 +180,21 @@ for randfun in [:randn, :randexp]
175180
A
176181
end
177182

183+
# optimization for MersenneTwister, which randomizes natively Array{Float64}
184+
function $randfun!(rng::MersenneTwister, A::Array{Float64})
185+
if length(A) < 13
186+
for i in eachindex(A)
187+
@inbounds A[i] = $randfun(rng, Float64)
188+
end
189+
else
190+
rand!(rng, A, CloseOpen12())
191+
for i in eachindex(A)
192+
@inbounds A[i] = $_randfun(rng, reinterpret(UInt64, A[i]))
193+
end
194+
end
195+
A
196+
end
197+
178198
$randfun!(A::AbstractArray) = $randfun!(default_rng(), A)
179199

180200
# generating arrays

0 commit comments

Comments
 (0)