Skip to content

Commit

Permalink
Initial work on a framework for having multiple RNGs in the future.
Browse files Browse the repository at this point in the history
Make RNG state available through rand.

julia> r = Rng_MT(uint32(0));

julia> rand(r)
0.030581026769374464

julia> srand(r, uint32(0))

julia> rand(r)
0.030581026769374464

Also, iteration is possible for Rng objects.

julia> r = Rng_MT(uint32(0), 5);

julia> for i = r; println(i); end
0.030581026769374464
0.2131403200670121
0.29900252501600133
0.38113885304462825
0.8634883970635943
  • Loading branch information
Viral B. Shah committed Sep 25, 2012
1 parent 484e2d2 commit 68049d4
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 26 deletions.
24 changes: 10 additions & 14 deletions extras/librandom.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Base.*
import Main
import Main.*

export dsfmt_get_min_array_size, dsfmt_get_idstring,
export DSFMT_state, dsfmt_get_min_array_size, dsfmt_get_idstring,
dsfmt_init_gen_rand, dsfmt_gv_init_gen_rand,
dsfmt_init_by_array, dsfmt_gv_init_by_array,
dsfmt_genrand_close1_open2, dsfmt_gv_genrand_close1_open2,
Expand All @@ -23,12 +23,8 @@ export dsfmt_get_min_array_size, dsfmt_get_idstring,
## DSFMT

type DSFMT_state
state::Array{Int32}
isinit::Bool
function DSFMT_state()
state = Array(Int32, 770)
new(state, false)
end
val::Vector{Int32}
DSFMT_state() = new(Array(Int32, 770))
end

function dsfmt_get_min_array_size()
Expand All @@ -41,28 +37,28 @@ function dsfmt_get_idstring()
idstring = ccall(dlsym(Main.librandom, :dsfmt_get_idstring),
Ptr{Uint8},
())
bytestring(idstring)
return bytestring(idstring)
end

function dsfmt_init_gen_rand(s::DSFMT_state, seed::Uint32)
ccall(dlsym(Main.librandom, :dsfmt_init_gen_rand),
Void,
(Ptr{Void}, Uint32,),
s.state, seed)
s.val, seed)
end

function dsfmt_gv_init_gen_rand(seed::Uint32)
ccall(dlsym(Main.librandom, :dsfmt_gv_init_gen_rand),
Void,
(Uint32,),
(Uint32,),
seed)
end

function dsfmt_init_by_array(s::DSFMT_state, seed::Vector{Uint32})
ccall(dlsym(Main.librandom, :dsfmt_init_by_array),
Void,
(Ptr{Void}, Ptr{Uint32}, Int32),
s.state, seed, length(seed))
s.val, seed, length(seed))
end

function dsfmt_gv_init_by_array(seed::Vector{Uint32})
Expand All @@ -83,7 +79,7 @@ for (genrand, gv_genrand) in
r = ccall(dlsym(Main.librandom, $(string(genrand)) ),
Float64,
(Ptr{Void},),
s.state)
s.val)
end

function ($gv_genrand)()
Expand All @@ -110,7 +106,7 @@ for (genrand_fill, gv_genrand_fill, genrand_fill_name, gv_genrand_fill_name) in
ccall(dlsym(Main.librandom, $(string(genrand_fill)) ),
Void,
(Ptr{Void}, Ptr{Float64}, Int32),
s.state, A, n)
s.val, A, n)
return A
end

Expand All @@ -129,7 +125,7 @@ function dsfmt_genrand_uint32(s::DSFMT_state)
r = ccall(dlsym(Main.librandom, :dsfmt_genrand_uint32),
Uint32,
(Ptr{Void},),
s.state)
s.val)
end

function dsfmt_gv_genrand_uint32()
Expand Down
67 changes: 55 additions & 12 deletions extras/rng.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,50 @@ export librandom_init, srand,
randg, randg!,
randexp, randexp!, exprnd,
randchi2, randchi2!, chi2rnd,
randbeta, randbeta!, betarnd
randbeta, randbeta!, betarnd,
Rng_MT

abstract Rng

start(r::Rng) = 1
done(r::Rng, count) = r.len == count ? true : false
next(r::Rng, count) = (rand(r), count + 1)

type Rng_MT <: Rng
state::DSFMT_state
seed::Union(Uint32,Vector{Uint32})
len::Int # Use for iteration. Set to -1 otherwise.

function Rng_MT()
seed = uint32(0)
state = DSFMT_state()
dsfmt_init_gen_rand(state, seed)
return new(state, seed, -1)
end

Rng_MT(seed) = Rng_MT(seed, -1)

function Rng_MT(seed::Uint32, len::Int)
state = DSFMT_state()
dsfmt_init_gen_rand(state, seed)
return new(state, seed, len)
end

function Rng_MT(seed::Vector{Uint32}, len::Int)
state = DSFMT_state()
dsfmt_init_by_array(state, seed)
return new(state, seed, len)
end
end

rand(r::Rng_MT) = dsfmt_genrand_close_open(r.state)
rand(r::Rng_MT, args) = rand(r, args...)

function srand(r::Rng_MT, seed)
r.seed = seed
dsfmt_init_gen_rand(r.state, seed)
return r
end

## initialization

Expand All @@ -39,11 +82,11 @@ end

@windows_only begin
a = zeros(Uint32, 2)
LibRandom.win32_SystemFunction036!(a)
win32_SystemFunction036!(a)
srand(a)
end

LibRandom.randmtzig_create_ziggurat_tables()
randmtzig_create_ziggurat_tables()
end

# macros to generate random arrays
Expand Down Expand Up @@ -82,12 +125,12 @@ end

function srand(seed::Uint32)
global RANDOM_SEED = seed
LibRandom.dsfmt_gv_init_gen_rand(seed)
dsfmt_gv_init_gen_rand(seed)
end

function srand(seed::Vector{Uint32})
global RANDOM_SEED = seed
LibRandom.dsfmt_gv_init_by_array(seed)
dsfmt_gv_init_by_array(seed)
end

srand(seed::Uint64) = srand([uint32(seed),uint32(seed>>32)])
Expand All @@ -105,9 +148,9 @@ srand(filename::String) = srand(filename, 4)

## rand()

rand() = LibRandom.dsfmt_gv_genrand_close_open()
rand() = dsfmt_gv_genrand_close_open()

const dsfmt_min_array_size = LibRandom.dsfmt_get_min_array_size()
const dsfmt_min_array_size = dsfmt_get_min_array_size()

function rand!(A::Array{Float64})
n = numel(A)
Expand All @@ -116,7 +159,7 @@ function rand!(A::Array{Float64})
A[i] = rand()
end
else
A = LibRandom.dsfmt_gv_fill_array_close_open!(A, n & 0xfffffffe)
A = dsfmt_gv_fill_array_close_open!(A, n & 0xfffffffe)
if isodd(n)
A[n] = rand()
end
Expand Down Expand Up @@ -200,15 +243,15 @@ randbool() = randbit() == 1
# The Ziggurat Method for generating random variables - Marsaglia and Tsang
# Paper and reference code: http:https://www.jstatsoft.org/v05/i08/

randn() = LibRandom.randmtzig_randn()
randn!(A::Array{Float64}) = LibRandom.randmtzig_fill_randn!(A)
randn() = randmtzig_randn()
randn!(A::Array{Float64}) = randmtzig_fill_randn!(A)
randn(dims::Dims) = randn!(Array(Float64, dims))
randn(dims::Int...) = randn(dims)

## randexp() - Exponentially distributed random numbers using Ziggurat algorithm

randexp() = LibRandom.randmtzig_exprnd()
randexp!(A::Array{Float64}) = LibRandom.randmtzig_fill_exprnd!(A)
randexp() = randmtzig_exprnd()
randexp!(A::Array{Float64}) = randmtzig_fill_exprnd!(A)
randexp(dims::Dims) = randexp!(Array(Float64, dims))
randexp(dims::Int...) = randexp(dims)

Expand Down

0 comments on commit 68049d4

Please sign in to comment.