ref: 16570e96dac87d60ed54aee8d3ff277923e36b5b
dir: /lib/std/rand.myr/
use "alloc"
use "assert"
use "die"
use "extremum"
use "mk"
use "now"
use "putint"
use "types"
pkg std =
type rng
const mksrng : (seed : uint32 -> rng#)
const freerng : (rng : rng# -> void)
generic rand : (lo : @a::(numeric,integral), hi : @a::(numeric,integral) -> @a::(numeric,integral))
generic randnum : (-> @a::(numeric,integral))
const randbytes : (buf : byte[:] -> void)
generic rngrand : (rng : rng#, lo : @a::(numeric,integral), hi : @a::(numeric,integral) -> @a::(numeric,integral))
generic rngrandnum : (rng : rng# -> @a::(numeric,integral))
const rngrandbytes : (rng : rng#, buf : byte[:] -> void)
;;
type rng = struct
s0 : uint64
s1 : uint64
;;
var _rng
generic rand = {lo, hi; -> rngrand(&_rng, lo, hi)}
generic randnum = {; -> rngrandnum(&_rng)}
const randbytes = {buf; -> rngrandbytes(&_rng, buf)}
const __init__ = {
_rng.s0 = (now() : uint64)
_rng.s1 = (now() : uint64)
}
const mksrng = {seed : uint32 -> rng#
-> std.mk([
.s0=(seed & 0xffff : uint64),
.s1=(seed&0xffff0000>>16 : uint64)
])
}
const freerng = {r
std.free(r)
}
generic rngrand = {rng, lo, hi
var span, lim, val, max
span = abs(hi - lo)
max = ~0
/* if ~0 is negative, we have a signed value with a different max */
if max < 0
max = (1 << (8*sizeof(@a)-1)) - 1
;;
lim = (max/span)*span
val = (rngrandnum(rng) & max)
while val > lim
val = (rngrandnum(rng) & max)
;;
-> val % span + lo
}
const rngrandbytes = {rng, buf
var n, r : uint64
n = 0
for var i = 0; i + 8 < buf.len/8; i++
r = rngrandnum(rng)
putle64(buf[n:n+8], r)
n += 8
;;
r = rngrandnum(rng)
for ; n != buf.len; n++
buf[n] = (r & 0xff : byte)
r >>= 8
;;
}
/*
Generate a number using the xoroshiro algorithm, as
designed by David Blackman and Sebastiano Vigna.
See http://xoroshiro.di.unimi.it/ for details.
*/
generic rngrandnum = {rng -> @a::(numeric,integral)
var s0, s1, r
s0 = rng.s0
s1 = rng.s1
r = s0 + s1
s1 ^= s0
rng.s0 = (s0 << 55 | s0 >> 9) ^ s1 ^ (s1 << 14)
rng.s1 = (s1 << 36 | s1 >> 28)
-> (r : @a::(numeric,integral))
}