forked from JuliaRandom/RandomNumbers.jl
/
xorshift64.jl
55 lines (44 loc) · 1.45 KB
/
xorshift64.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import Base: copy, copyto!, ==
import Random: rand, seed!
import RandomNumbers: AbstractRNG, gen_seed, seed_type
"""
```julia
AbstractXorshift64 <: AbstractRNG{UInt64}
```
The base abstract type for `Xorshift64` and `Xorshift64Star`.
"""
abstract type AbstractXorshift64 <: AbstractRNG{UInt64} end
for star in (false, true)
rng_name = Symbol(string("Xorshift64", star ? "Star" : ""))
@eval begin
mutable struct $rng_name <: AbstractXorshift64
x::UInt64
function $rng_name(seed::UInt64=gen_seed(UInt64))
r = new(0)
seed!(r, seed)
r
end
end
$rng_name(seed::Integer) = $rng_name(seed % UInt64)
@inline function xorshift_next(r::$rng_name)
r.x ⊻= r.x << 18
r.x ⊻= r.x >> 31
r.x ⊻= r.x << 11
$(star ? :(r.x * 2685821657736338717) : :(r.x))
end
end
end
@inline seed_type(::Type{T}) where T <: AbstractXorshift64 = UInt64
function copyto!(dest::T, src::T) where T <: AbstractXorshift64
dest.x = src.x
dest
end
copy(src::T) where T <: AbstractXorshift64 = copyto!(T(), src)
==(r1::T, r2::T) where T <: AbstractXorshift64 = r1.x == r2.x
function seed!(r::AbstractXorshift64, seed::Integer=gen_seed(UInt64))
seed == 0 && error("0 cannot be the seed")
r.x = seed % UInt64
xorshift_next(r)
r
end
@inline rand(r::AbstractXorshift64, ::Type{UInt64}) = xorshift_next(r)