|
| 1 | +module XORShift |
| 2 | + |
| 3 | +import Base: rand, rand! |
| 4 | + |
| 5 | +type XORShiftStar1024 <: AbstractRNG |
| 6 | + x00::UInt64 |
| 7 | + x01::UInt64 |
| 8 | + x02::UInt64 |
| 9 | + x03::UInt64 |
| 10 | + x04::UInt64 |
| 11 | + x05::UInt64 |
| 12 | + x06::UInt64 |
| 13 | + x07::UInt64 |
| 14 | + x08::UInt64 |
| 15 | + x09::UInt64 |
| 16 | + x10::UInt64 |
| 17 | + x11::UInt64 |
| 18 | + x12::UInt64 |
| 19 | + x13::UInt64 |
| 20 | + x14::UInt64 |
| 21 | + x15::UInt64 |
| 22 | + p::UInt64 |
| 23 | +end |
| 24 | +XORShiftStar() = XORShiftStar1024(rand(UInt64, 16)..., 0) |
| 25 | + |
| 26 | +const globalXORShiftStar1024 = XORShiftStar() |
| 27 | + |
| 28 | +fromUInt64(::Type{UInt64}, u::UInt64) = u |
| 29 | +fromUInt64(::Type{Float64}, u::UInt64) = 5.421010862427522e-20 * u |
| 30 | + |
| 31 | +function rand(rng::XORShiftStar1024, ::Type{UInt64}) |
| 32 | + @inbounds begin |
| 33 | + p = rng.p |
| 34 | + s0 = getfield(rng, reinterpret(Int, p)+1) |
| 35 | + p = (p + 1) % 16 |
| 36 | + s1 = getfield(rng, reinterpret(Int, p)+1) |
| 37 | + s1 $= s1 << 31 |
| 38 | + s1 $= s1 >> 11 |
| 39 | + s0 $= s0 >> 30 |
| 40 | + s0 $= s1 |
| 41 | + unsafe_store!(convert(Ptr{UInt64}, pointer_from_objref(rng))+8, |
| 42 | + s0, reinterpret(Int, p)+1) |
| 43 | + rng.p = p |
| 44 | + end |
| 45 | + return s0 * 1181783497276652981 |
| 46 | +end |
| 47 | + |
| 48 | +rand{T<:Number}(rng::XORShiftStar1024, ::Type{T}) = fromUInt64(T, rand(rng, UInt64)) |
| 49 | + |
| 50 | +@eval function rand!{T}(rng::XORShiftStar1024, a::AbstractArray{T}) |
| 51 | + p = rng.p |
| 52 | + n = length(a) |
| 53 | + q = min((16 - p) % 16, n) |
| 54 | + r = (n - q) % 16 |
| 55 | + @inbounds for i = 1:q |
| 56 | + a[i] = rand(rng, T) |
| 57 | + end |
| 58 | + $(Expr(:block, [ |
| 59 | + let x = symbol(@sprintf("x%02d", k % 16)) |
| 60 | + :($x = rng.$x) |
| 61 | + end |
| 62 | + for k = 0:15 ]...)) |
| 63 | + r = q + (n-q) >> 4 << 4 |
| 64 | + @inbounds for i = q+1:16:r |
| 65 | + $(Expr(:block, [ |
| 66 | + let x0 = symbol(@sprintf("x%02d", k % 16)), |
| 67 | + x1 = symbol(@sprintf("x%02d", (k + 1) % 16)) |
| 68 | + quote |
| 69 | + s0 = $x0 |
| 70 | + s1 = $x1 |
| 71 | + s1 $= s1 << 31 |
| 72 | + s1 $= s1 >> 11 |
| 73 | + s0 $= s0 >> 30 |
| 74 | + s0 $= s1 |
| 75 | + $x1 = s0 |
| 76 | + a[i + $k] = fromUInt64(T, s0 * 1181783497276652981) |
| 77 | + end |
| 78 | + end |
| 79 | + for k = 0:15 ]...)) |
| 80 | + end |
| 81 | + $(Expr(:block, [ |
| 82 | + let x = symbol(@sprintf("x%02d", k % 16)) |
| 83 | + :(rng.$x = $x) |
| 84 | + end |
| 85 | + for k = 0:15 ]...)) |
| 86 | + rng.p = 0 |
| 87 | + @inbounds for i = r+1:n |
| 88 | + a[i] = rand(rng, T) |
| 89 | + end |
| 90 | + return a |
| 91 | +end |
| 92 | + |
| 93 | +end # module |
0 commit comments