swh:1:snp:a72e953ecd624a7df6e6196bbdd05851996c5e40
Tip revision: e8cb96bc6d6e74b0e9fdfd80171c0e284d19eea7 authored by Jiahao Chen on 09 August 2014, 03:21:53 UTC
Merge pull request #7928 from wlbksy/patch-1
Merge pull request #7928 from wlbksy/patch-1
Tip revision: e8cb96b
random.jl
module Random
using Base.LibRandom
export srand,
rand, rand!,
randn, randn!,
randbool, randbool!,
AbstractRNG, RNG, MersenneTwister
abstract AbstractRNG
type MersenneTwister <: AbstractRNG
state::DSFMT_state
seed::Union(Uint32,Vector{Uint32})
function MersenneTwister()
seed = uint32(0)
state = DSFMT_state()
dsfmt_init_gen_rand(state, seed)
return new(state, seed)
end
function MersenneTwister(seed::Uint32)
state = DSFMT_state()
dsfmt_init_gen_rand(state, seed)
return new(state, seed)
end
function MersenneTwister(seed::Vector{Uint32})
state = DSFMT_state()
dsfmt_init_by_array(state, seed)
return new(state, seed)
end
MersenneTwister(seed) = MersenneTwister(reinterpret(Uint32, [seed]))
end
function srand(r::MersenneTwister, seed)
r.seed = seed
dsfmt_init_gen_rand(r.state, seed)
return r
end
## initialization
function librandom_init()
@unix_only begin
try
srand("/dev/urandom")
catch
println(STDERR, "Entropy pool not available to seed RNG, using ad-hoc entropy sources.")
seed = reinterpret(Uint64, time())
seed = bitmix(seed, uint64(getpid()))
try
seed = bitmix(seed, parseint(Uint64, readall(`ifconfig` |> `sha1sum`)[1:40], 16))
catch
# ignore
end
srand(seed)
end
end
@windows_only begin
a = zeros(Uint32, 2)
win32_SystemFunction036!(a)
srand(a)
end
randmtzig_create_ziggurat_tables()
end
## srand()
function srand(seed::Vector{Uint32})
global RANDOM_SEED = seed
dsfmt_gv_init_by_array(seed)
end
srand(n::Integer) = srand(make_seed(n))
function make_seed(n::Integer)
n < 0 && throw(DomainError())
seed = Uint32[]
while true
push!(seed, n & 0xffffffff)
n2 = n >> 32
if n2 == 0 || n2 == n
return seed
end
n = n2
end
end
function srand(filename::String, n::Integer)
open(filename) do io
a = Array(Uint32, int(n))
read(io, a)
srand(a)
end
end
srand(filename::String) = srand(filename, 4)
## random floating point values
rand(::Type{Float64}) = dsfmt_gv_genrand_close_open()
rand() = dsfmt_gv_genrand_close_open()
rand(::Type{Float32}) = float32(rand())
rand(::Type{Float16}) = float16(rand())
rand{T<:Real}(::Type{Complex{T}}) = complex(rand(T),rand(T))
rand(r::MersenneTwister) = dsfmt_genrand_close_open(r.state)
## random integers
dsfmt_randui32() = dsfmt_gv_genrand_uint32()
dsfmt_randui64() = uint64(dsfmt_randui32()) | (uint64(dsfmt_randui32())<<32)
rand(::Type{Uint8}) = uint8(rand(Uint32))
rand(::Type{Uint16}) = uint16(rand(Uint32))
rand(::Type{Uint32}) = dsfmt_randui32()
rand(::Type{Uint64}) = dsfmt_randui64()
rand(::Type{Uint128}) = uint128(rand(Uint64))<<64 | rand(Uint64)
rand(::Type{Int8}) = int8(rand(Uint8))
rand(::Type{Int16}) = int16(rand(Uint16))
rand(::Type{Int32}) = int32(rand(Uint32))
rand(::Type{Int64}) = int64(rand(Uint64))
rand(::Type{Int128}) = int128(rand(Uint128))
# Arrays of random numbers
rand!(A::Array{Float64}) = dsfmt_gv_fill_array_close_open!(A)
rand(::Type{Float64}, dims::Dims) = rand!(Array(Float64, dims))
rand(::Type{Float64}, dims::Int...) = rand(Float64, dims)
rand(dims::Dims) = rand(Float64, dims)
rand(dims::Int...) = rand(Float64, dims)
rand!(r::MersenneTwister, A::Array{Float64}) = dsfmt_fill_array_close_open!(r.state, A)
rand(r::AbstractRNG, dims::Dims) = rand!(r, Array(Float64, dims))
rand(r::AbstractRNG, dims::Int...) = rand(r, dims)
function rand!{T}(A::Array{T})
for i=1:length(A)
A[i] = rand(T)
end
A
end
rand(T::Type, dims::Dims) = rand!(Array(T, dims))
rand{T<:Number}(::Type{T}) = error("No random number generator for type $T. Try a more specific type.")
rand{T<:Number}(::Type{T}, dims::Int...) = rand(T, dims)
function randu{T<:Union(Uint32,Uint64,Uint128)}(k::T)
# generate an unsigned integer in 0:k-1
# largest multiple of k that can be represented in T
u = convert(T, div(typemax(T),k)*k)
x = rand(T)
while x >= u
x = rand(T)
end
rem(x, k)
end
# random integer from lo to hi inclusive
function rand{T<:Union(Uint32,Uint64,Uint128)}(r::Range1{T})
ulen = convert(T, length(r))
convert(T, first(r) + randu(ulen))
end
function rand(r::Range1{Int32})
ulen = convert(Uint32, length(r))
convert(Int32, first(r) + randu(ulen))
end
function rand(r::Range1{Int64})
ulen = convert(Uint64, length(r))
convert(Int64, first(r) + randu(ulen))
end
function rand(r::Range1{Int128})
ulen = convert(Uint128, length(r))
convert(Int128, first(r) + randu(ulen))
end
# fallback for other integer types
rand{T<:Integer}(r::Range1{T}) = convert(T, rand(int(r)))
function rand!{T<:Integer}(r::Range1{T}, A::Array{T})
for i=1:length(A)
A[i] = rand(r)
end
return A
end
rand{T<:Integer}(r::Range1{T}, dims::Dims) = rand!(r, Array(T, dims))
rand{T<:Integer}(r::Range1{T}, dims::Int...) = rand(r, dims)
## random Bools
rand!(B::BitArray) = Base.bitarray_rand_fill!(B)
randbool(dims::Dims) = rand!(BitArray(dims))
randbool(dims::Int...) = rand!(BitArray(dims))
randbool() = ((dsfmt_randui32() & 1) == 1)
randbool!(B::BitArray) = rand!(B)
## randn() - Normally distributed random numbers using Ziggurat algorithm
# The Ziggurat Method for generating random variables - Marsaglia and Tsang
# Paper and reference code: http://www.jstatsoft.org/v05/i08/
randn() = randmtzig_randn()
randn!(A::Array{Float64}) = randmtzig_fill_randn!(A)
randn(dims::Dims) = randn!(Array(Float64, dims))
randn(dims::Int...) = randn!(Array(Float64, dims...))
immutable UUID
value::Uint128
end
@eval function uuid4()
u = rand(Uint128)
u &= $(parseint(Uint128,"ffffffffffff0fff3fffffffffffffff",16))
u |= $(parseint(Uint128,"00000000000040008000000000000000",16))
UUID(u)
end
function Base.convert(::Type{Vector{Uint8}}, u::UUID)
u = u.value
a = Array(Uint8,36)
for i = [36:-1:25; 23:-1:20; 18:-1:15; 13:-1:10; 8:-1:1]
a[i] = Base.digit(u & 0xf)
u >>= 4
end
a[[24,19,14,9]] = '-'
return a
end
Base.show(io::IO, u::UUID) = write(io,convert(Vector{Uint8},u))
Base.repr(u::UUID) = ASCIIString(convert(Vector{Uint8},u))
end # module