Skip to content

Commit cb75579

Browse files
committedNov 30, 2014
Merge pull request #9144 from JuliaLang/rf/randexp
faster randmtzig_exprnd (separate unlikely branch + inline) and rename it "randexp"
2 parents d26ab46 + ccb1166 commit cb75579

File tree

4 files changed

+52
-15
lines changed

4 files changed

+52
-15
lines changed
 

‎base/exports.jl

+2
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,8 @@ export
905905
randbool,
906906
randn!,
907907
randn,
908+
randexp!,
909+
randexp,
908910
srand,
909911

910912
# bigfloat & precision

‎base/random.jl

+33-15
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ using Base.dSFMT
55
export srand,
66
rand, rand!,
77
randn, randn!,
8+
randexp, randexp!,
89
randbool,
9-
AbstractRNG, RNG, MersenneTwister,
10-
randmtzig_exprnd
10+
AbstractRNG, RNG, MersenneTwister
11+
1112

1213
abstract AbstractRNG
1314

@@ -984,23 +985,40 @@ randn(dims::Int...) = randn!(Array(Float64, dims...))
984985
randn(rng::MersenneTwister, dims::Dims) = randn!(rng, Array(Float64, dims))
985986
randn(rng::MersenneTwister, dims::Int...) = randn!(rng, Array(Float64, dims...))
986987

987-
function randmtzig_exprnd(rng::MersenneTwister=GLOBAL_RNG)
988+
@inline function randexp(rng::MersenneTwister=GLOBAL_RNG)
988989
@inbounds begin
989-
while true
990-
ri = rand_ui52(rng)
991-
idx = ri & 0xFF
992-
x = ri*we[idx+1]
993-
if ri < ke[idx+1]
994-
return x # 98.9% of the time we return here 1st try
995-
elseif idx == 0
996-
return ziggurat_exp_r - log(rand(rng))
997-
elseif (fe[idx] - fe[idx+1])*rand(rng) + fe[idx+1] < exp(-x)
998-
return x # return from the triangular area
999-
end
1000-
end
990+
ri = rand_ui52(rng)
991+
idx = ri & 0xFF
992+
x = ri*we[idx+1]
993+
ri < ke[idx+1] && return x # 98.9% of the time we return here 1st try
994+
return randexp_unlikely(rng, idx, x)
995+
end
996+
end
997+
998+
function randexp_unlikely(rng, idx, x)
999+
@inbounds if idx == 0
1000+
return ziggurat_exp_r - log(rand(rng))
1001+
elseif (fe[idx] - fe[idx+1])*rand(rng) + fe[idx+1] < exp(-x)
1002+
return x # return from the triangular area
1003+
else
1004+
return randexp(rng)
1005+
end
1006+
end
1007+
1008+
function randexp!(rng::MersenneTwister, A::Array{Float64})
1009+
for i = 1:length(A)
1010+
@inbounds A[i] = randexp(rng)
10011011
end
1012+
A
10021013
end
10031014

1015+
randexp!(A::Array{Float64}) = randexp!(GLOBAL_RNG, A)
1016+
randexp(dims::Dims) = randexp!(Array(Float64, dims))
1017+
randexp(dims::Int...) = randexp!(Array(Float64, dims))
1018+
randexp(rng::MersenneTwister, dims::Dims) = randexp!(rng, Array(Float64, dims))
1019+
randexp(rng::MersenneTwister, dims::Int...) = randexp!(rng, Array(Float64, dims))
1020+
1021+
10041022
## random UUID generation
10051023

10061024
immutable UUID

‎doc/stdlib/base.rst

+8
Original file line numberDiff line numberDiff line change
@@ -4119,6 +4119,14 @@ A ``MersenneTwister`` RNG can generate random numbers of the following types: ``
41194119

41204120
Fill the array A with normally-distributed (mean 0, standard deviation 1) random numbers. Also see the rand function.
41214121

4122+
.. function:: randexp([rng], [dims...])
4123+
4124+
Generate a random number according to the exponential distribution with scale 1. Optionally generate an array of such random numbers.
4125+
4126+
.. function:: randexp!([rng], A::Array{Float64,N})
4127+
4128+
Fill the array A with random numbers following the exponential distribution (with scale 1).
4129+
41224130
Arrays
41234131
------
41244132

‎test/random.jl

+9
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,20 @@ if sizeof(Int32) < sizeof(Int)
8080

8181
end
8282

83+
randn()
8384
randn(100000)
8485
randn!(Array(Float64, 100000))
86+
randn(MersenneTwister(10))
8587
randn(MersenneTwister(10), 100000)
8688
randn!(MersenneTwister(10), Array(Float64, 100000))
8789

90+
randexp()
91+
randexp(100000)
92+
randexp!(Array(Float64, 100000))
93+
randexp(MersenneTwister(10))
94+
randexp(MersenneTwister(10), 100000)
95+
randexp!(MersenneTwister(10), Array(Float64, 100000))
96+
8897
# Test ziggurat tables
8998
ziggurat_table_size = 256
9099
nmantissa = int64(2)^51 # one bit for the sign

0 commit comments

Comments
 (0)
Please sign in to comment.