discard byte order preservation
parent
878ad17c9b
commit
35e9f229c3
|
|
@ -94,52 +94,29 @@ pub fn (mut rng MT19937RNG) seed(seed_data []u32) {
|
|||
// byte returns a uniformly distributed pseudorandom 8-bit unsigned positive `byte`.
|
||||
[inline]
|
||||
pub fn (mut rng MT19937RNG) byte() byte {
|
||||
// Can we extract a value from the buffer?
|
||||
if rng.bytes_left >= 1 {
|
||||
rng.bytes_left -= 1
|
||||
value := byte(rng.buffer)
|
||||
rng.buffer >>= 8
|
||||
return value
|
||||
}
|
||||
// Add a new value to the buffer
|
||||
rng.buffer = rng.internal_u64()
|
||||
rng.buffer = rng.u64()
|
||||
rng.bytes_left = 7
|
||||
value := byte(rng.buffer)
|
||||
rng.buffer >>= 8
|
||||
return value
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (mut rng MT19937RNG) step_by(amount int) u64 {
|
||||
next_number := rng.internal_u64()
|
||||
|
||||
bits_left := rng.bytes_left * 8
|
||||
bits_needed := amount - bits_left
|
||||
|
||||
old_value := rng.buffer & ((u64(1) << bits_left) - 1)
|
||||
new_value := next_number & ((u64(1) << bits_needed) - 1)
|
||||
value := old_value | (new_value << bits_left)
|
||||
|
||||
rng.buffer = next_number >> bits_needed
|
||||
rng.bytes_left = 8 - (bits_needed / 8)
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// u16 returns a pseudorandom 16bit int in range `[0, 2¹⁶)`.
|
||||
[inline]
|
||||
pub fn (mut rng MT19937RNG) u16() u16 {
|
||||
// Can we take a whole u16 out of the buffer?
|
||||
if rng.bytes_left >= 2 {
|
||||
rng.bytes_left -= 2
|
||||
value := u16(rng.buffer)
|
||||
rng.buffer >>= 16
|
||||
return value
|
||||
}
|
||||
if rng.bytes_left > 0 {
|
||||
return u16(rng.step_by(16))
|
||||
}
|
||||
ans := rng.internal_u64()
|
||||
ans := rng.u64()
|
||||
rng.buffer = ans >> 16
|
||||
rng.bytes_left = 6
|
||||
return u16(ans)
|
||||
|
|
@ -155,11 +132,7 @@ pub fn (mut rng MT19937RNG) u32() u32 {
|
|||
rng.buffer >>= 32
|
||||
return value
|
||||
}
|
||||
if rng.bytes_left > 0 {
|
||||
return u32(rng.step_by(32))
|
||||
}
|
||||
// We're out so we start fresh.
|
||||
ans := rng.internal_u64()
|
||||
ans := rng.u64()
|
||||
rng.buffer = ans >> 32
|
||||
rng.bytes_left = 4
|
||||
return u32(ans)
|
||||
|
|
@ -168,14 +141,6 @@ pub fn (mut rng MT19937RNG) u32() u32 {
|
|||
// u64 returns a pseudorandom 64bit int in range `[0, 2⁶⁴)`.
|
||||
[inline]
|
||||
pub fn (mut rng MT19937RNG) u64() u64 {
|
||||
if rng.bytes_left > 0 {
|
||||
return rng.step_by(64)
|
||||
}
|
||||
return rng.internal_u64()
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (mut rng MT19937RNG) internal_u64() u64 {
|
||||
mag01 := [u64(0), u64(mt19937.matrix_a)]
|
||||
mut x := u64(0)
|
||||
mut i := int(0)
|
||||
|
|
@ -202,6 +167,7 @@ fn (mut rng MT19937RNG) internal_u64() u64 {
|
|||
return x
|
||||
}
|
||||
|
||||
// block_size returns the number of bits that the RNG can produce in a single iteration.
|
||||
[inline]
|
||||
pub fn (mut rng MT19937RNG) block_size() int {
|
||||
return 64
|
||||
|
|
|
|||
|
|
@ -330,43 +330,3 @@ fn test_mt19937_f64_in_range() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_mt19937_buffering() {
|
||||
for seed in seeds {
|
||||
for offset in [0, 2, 3, 5, 19, 47] {
|
||||
count := 5
|
||||
mut rngs := []rand.PRNG{cap: count}
|
||||
|
||||
for i in 0 .. count {
|
||||
rngs << &rand.PRNG(&mt19937.MT19937RNG{})
|
||||
rngs[i].seed(seed)
|
||||
}
|
||||
|
||||
for mut rng in rngs {
|
||||
for _ in 0 .. offset {
|
||||
rng.byte()
|
||||
}
|
||||
}
|
||||
|
||||
for _ in 0 .. 6 {
|
||||
first_64bit := rngs[0].u64()
|
||||
second_64bit := u64(rngs[1].u32()) | (u64(rngs[1].u32()) << 32)
|
||||
mut third_64bit := u64(rngs[2].byte())
|
||||
|
||||
for shift in 1 .. 8 {
|
||||
third_64bit |= u64(rngs[2].byte()) << (shift * 8)
|
||||
}
|
||||
|
||||
fourth_64bit := u64(rngs[3].byte()) | (u64(rngs[3].u32()) << 8) | (u64(rngs[3].u16()) << 40) | (u64(rngs[3].byte()) << 56)
|
||||
|
||||
eight_bytes := rngs[4].bytes(8) or { panic("Couldn't obtain random bytes") }
|
||||
mut fifth_64bit := u64(eight_bytes[0]) | (u64(eight_bytes[1]) << 8) | (u64(eight_bytes[2]) << 16) | (u64(eight_bytes[3]) << 24) | (u64(eight_bytes[4]) << 32) | (u64(eight_bytes[5]) << 40) | (u64(eight_bytes[6]) << 48) | (u64(eight_bytes[7]) << 56)
|
||||
|
||||
assert first_64bit == second_64bit
|
||||
assert first_64bit == third_64bit
|
||||
assert first_64bit == fourth_64bit
|
||||
assert first_64bit == fifth_64bit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,66 +31,34 @@ pub fn (mut rng MuslRNG) seed(seed_data []u32) {
|
|||
// byte returns a uniformly distributed pseudorandom 8-bit unsigned positive `byte`.
|
||||
[inline]
|
||||
fn (mut rng MuslRNG) byte() byte {
|
||||
// Can we extract a value from the buffer?
|
||||
if rng.bytes_left >= 1 {
|
||||
rng.bytes_left -= 1
|
||||
value := byte(rng.buffer)
|
||||
rng.buffer >>= 8
|
||||
return value
|
||||
}
|
||||
// Add a new value to the buffer
|
||||
rng.buffer = rng.internal_u32()
|
||||
rng.buffer = rng.u32()
|
||||
rng.bytes_left = 3
|
||||
value := byte(rng.buffer)
|
||||
rng.buffer >>= 8
|
||||
return value
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (mut rng MuslRNG) step_by(amount int) u32 {
|
||||
next_number := rng.internal_u32()
|
||||
|
||||
bits_left := rng.bytes_left * 8
|
||||
bits_needed := amount - bits_left
|
||||
|
||||
old_value := rng.buffer & ((u32(1) << bits_left) - 1)
|
||||
new_value := next_number & ((u32(1) << bits_needed) - 1)
|
||||
value := old_value | (new_value << bits_left)
|
||||
|
||||
rng.buffer = next_number >> bits_needed
|
||||
rng.bytes_left = 4 - (bits_needed / 8)
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// u16 returns a pseudorandom 16-bit unsigned integer (`u16`).
|
||||
[inline]
|
||||
pub fn (mut rng MuslRNG) u16() u16 {
|
||||
// Can we take a whole u16 out of the buffer?
|
||||
if rng.bytes_left >= 2 {
|
||||
rng.bytes_left -= 2
|
||||
value := u16(rng.buffer)
|
||||
rng.buffer >>= 16
|
||||
return value
|
||||
}
|
||||
if rng.bytes_left > 0 {
|
||||
return u16(rng.step_by(16))
|
||||
}
|
||||
ans := rng.internal_u32()
|
||||
ans := rng.u32()
|
||||
rng.buffer = ans >> 16
|
||||
rng.bytes_left = 2
|
||||
return u16(ans)
|
||||
}
|
||||
|
||||
// u32 returns a pseudorandom 32-bit unsigned integer (`u32`).
|
||||
[inline]
|
||||
pub fn (mut rng MuslRNG) u32() u32 {
|
||||
if rng.bytes_left >= 1 {
|
||||
return rng.step_by(32)
|
||||
}
|
||||
return rng.internal_u32()
|
||||
}
|
||||
|
||||
// temper returns a tempered value based on `prev` value.
|
||||
[inline]
|
||||
fn temper(prev u32) u32 {
|
||||
|
|
@ -102,7 +70,8 @@ fn temper(prev u32) u32 {
|
|||
return x
|
||||
}
|
||||
|
||||
fn (mut rng MuslRNG) internal_u32() u32 {
|
||||
// u32 returns a pseudorandom 32-bit unsigned integer (`u32`).
|
||||
fn (mut rng MuslRNG) u32() u32 {
|
||||
rng.state = rng.state * 1103515245 + 12345
|
||||
// We are not dividing by 2 (or shifting right by 1)
|
||||
// because we want all 32-bits of random data
|
||||
|
|
@ -115,6 +84,7 @@ pub fn (mut rng MuslRNG) u64() u64 {
|
|||
return u64(rng.u32()) | (u64(rng.u32()) << 32)
|
||||
}
|
||||
|
||||
// block_size returns the number of bits that the RNG can produce in a single iteration.
|
||||
[inline]
|
||||
pub fn (mut rng MuslRNG) block_size() int {
|
||||
return 32
|
||||
|
|
|
|||
|
|
@ -319,44 +319,3 @@ fn test_musl_f64_in_range() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_musl_buffering() {
|
||||
for seed in seeds {
|
||||
for offset in [0, 2, 3, 5, 19, 47] {
|
||||
count := 5
|
||||
mut rngs := []rand.PRNG{cap: count}
|
||||
|
||||
for i in 0 .. count {
|
||||
rngs << &rand.PRNG(&musl.MuslRNG{})
|
||||
rngs[i].seed(seed)
|
||||
}
|
||||
|
||||
for mut rng in rngs {
|
||||
for _ in 0 .. offset {
|
||||
rng.byte()
|
||||
}
|
||||
}
|
||||
|
||||
for _ in 0 .. 6 {
|
||||
first_64bit := rngs[0].u64()
|
||||
second_64bit := u64(rngs[1].u32()) | (u64(rngs[1].u32()) << 32)
|
||||
mut third_64bit := u64(rngs[2].byte())
|
||||
|
||||
for shift in 1 .. 8 {
|
||||
third_64bit |= u64(rngs[2].byte()) << (shift * 8)
|
||||
}
|
||||
|
||||
fourth_64bit := u64(rngs[3].byte()) | (u64(rngs[3].u32()) << 8) | (u64(rngs[3].u16()) << 40) | (u64(rngs[3].byte()) << 56)
|
||||
|
||||
eight_bytes := rngs[4].bytes(8) or { panic("Couldn't obtain random bytes") }
|
||||
mut fifth_64bit := u64(eight_bytes[0]) | (u64(eight_bytes[1]) << 8) | (u64(eight_bytes[2]) << 16) | (u64(eight_bytes[3]) << 24) | (u64(eight_bytes[4]) << 32) | (u64(eight_bytes[5]) << 40) | (u64(eight_bytes[6]) << 48) | (u64(eight_bytes[7]) << 56)
|
||||
|
||||
println('${first_64bit:x}, ${fourth_64bit:x}')
|
||||
assert first_64bit == second_64bit
|
||||
assert first_64bit == third_64bit
|
||||
assert first_64bit == fourth_64bit
|
||||
assert first_64bit == fifth_64bit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,52 +40,29 @@ pub fn (mut rng PCG32RNG) seed(seed_data []u32) {
|
|||
// byte returns a uniformly distributed pseudorandom 8-bit unsigned positive `byte`.
|
||||
[inline]
|
||||
fn (mut rng PCG32RNG) byte() byte {
|
||||
// Can we extract a value from the buffer?
|
||||
if rng.bytes_left >= 1 {
|
||||
rng.bytes_left -= 1
|
||||
value := byte(rng.buffer)
|
||||
rng.buffer >>= 8
|
||||
return value
|
||||
}
|
||||
// Add a new value to the buffer
|
||||
rng.buffer = rng.internal_u32()
|
||||
rng.buffer = rng.u32()
|
||||
rng.bytes_left = 3
|
||||
value := byte(rng.buffer)
|
||||
rng.buffer >>= 8
|
||||
return value
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (mut rng PCG32RNG) step_by(amount int) u32 {
|
||||
next_number := rng.internal_u32()
|
||||
|
||||
bits_left := rng.bytes_left * 8
|
||||
bits_needed := amount - bits_left
|
||||
|
||||
old_value := rng.buffer & ((u32(1) << bits_left) - 1)
|
||||
new_value := next_number & ((u32(1) << bits_needed) - 1)
|
||||
value := old_value | (new_value << bits_left)
|
||||
|
||||
rng.buffer = next_number >> bits_needed
|
||||
rng.bytes_left = 4 - (bits_needed / 8)
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// u16 returns a pseudorandom 16-bit unsigned integer (`u16`).
|
||||
[inline]
|
||||
pub fn (mut rng PCG32RNG) u16() u16 {
|
||||
// Can we take a whole u16 out of the buffer?
|
||||
if rng.bytes_left >= 2 {
|
||||
rng.bytes_left -= 2
|
||||
value := u16(rng.buffer)
|
||||
rng.buffer >>= 16
|
||||
return value
|
||||
}
|
||||
if rng.bytes_left > 0 {
|
||||
return u16(rng.step_by(16))
|
||||
}
|
||||
ans := rng.internal_u32()
|
||||
ans := rng.u32()
|
||||
rng.buffer = ans >> 16
|
||||
rng.bytes_left = 2
|
||||
return u16(ans)
|
||||
|
|
@ -93,14 +70,7 @@ pub fn (mut rng PCG32RNG) u16() u16 {
|
|||
|
||||
// u32 returns a pseudorandom unsigned `u32`.
|
||||
[inline]
|
||||
pub fn (mut rng PCG32RNG) u32() u32 {
|
||||
if rng.bytes_left >= 1 {
|
||||
return rng.step_by(32)
|
||||
}
|
||||
return rng.internal_u32()
|
||||
}
|
||||
|
||||
fn (mut rng PCG32RNG) internal_u32() u32 {
|
||||
fn (mut rng PCG32RNG) u32() u32 {
|
||||
oldstate := rng.state
|
||||
rng.state = oldstate * (6364136223846793005) + rng.inc
|
||||
xorshifted := u32(((oldstate >> u64(18)) ^ oldstate) >> u64(27))
|
||||
|
|
@ -114,6 +84,7 @@ pub fn (mut rng PCG32RNG) u64() u64 {
|
|||
return u64(rng.u32()) | (u64(rng.u32()) << 32)
|
||||
}
|
||||
|
||||
// block_size returns the number of bits that the RNG can produce in a single iteration.
|
||||
[inline]
|
||||
pub fn (mut rng PCG32RNG) block_size() int {
|
||||
return 32
|
||||
|
|
|
|||
|
|
@ -326,44 +326,3 @@ fn test_pcg32_f64_in_range() {
|
|||
fn test_change_default_random_generator() {
|
||||
rand.set_rng(&rand.PRNG(&pcg32.PCG32RNG{}))
|
||||
}
|
||||
|
||||
fn test_pcg32_buffering() {
|
||||
for seed in seeds {
|
||||
for offset in [0, 2, 3, 5, 19, 47] {
|
||||
count := 5
|
||||
mut rngs := []rand.PRNG{cap: count}
|
||||
|
||||
for i in 0 .. count {
|
||||
rngs << &rand.PRNG(&pcg32.PCG32RNG{})
|
||||
rngs[i].seed(seed)
|
||||
}
|
||||
|
||||
for mut rng in rngs {
|
||||
for _ in 0 .. offset {
|
||||
rng.byte()
|
||||
}
|
||||
}
|
||||
|
||||
for _ in 0 .. 6 {
|
||||
first_64bit := rngs[0].u64()
|
||||
second_64bit := u64(rngs[1].u32()) | (u64(rngs[1].u32()) << 32)
|
||||
mut third_64bit := u64(rngs[2].byte())
|
||||
|
||||
for shift in 1 .. 8 {
|
||||
third_64bit |= u64(rngs[2].byte()) << (shift * 8)
|
||||
}
|
||||
|
||||
fourth_64bit := u64(rngs[3].byte()) | (u64(rngs[3].u32()) << 8) | (u64(rngs[3].u16()) << 40) | (u64(rngs[3].byte()) << 56)
|
||||
|
||||
eight_bytes := rngs[4].bytes(8) or { panic("Couldn't obtain random bytes") }
|
||||
mut fifth_64bit := u64(eight_bytes[0]) | (u64(eight_bytes[1]) << 8) | (u64(eight_bytes[2]) << 16) | (u64(eight_bytes[3]) << 24) | (u64(eight_bytes[4]) << 32) | (u64(eight_bytes[5]) << 40) | (u64(eight_bytes[6]) << 48) | (u64(eight_bytes[7]) << 56)
|
||||
|
||||
println('${first_64bit:x}, ${fourth_64bit:x}')
|
||||
assert first_64bit == second_64bit
|
||||
assert first_64bit == third_64bit
|
||||
assert first_64bit == fourth_64bit
|
||||
assert first_64bit == fifth_64bit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,52 +30,29 @@ pub fn (mut rng SplitMix64RNG) seed(seed_data []u32) {
|
|||
// byte returns a uniformly distributed pseudorandom 8-bit unsigned positive `byte`.
|
||||
[inline]
|
||||
pub fn (mut rng SplitMix64RNG) byte() byte {
|
||||
// Can we extract a value from the buffer?
|
||||
if rng.bytes_left >= 1 {
|
||||
rng.bytes_left -= 1
|
||||
value := byte(rng.buffer)
|
||||
rng.buffer >>= 8
|
||||
return value
|
||||
}
|
||||
// Add a new value to the buffer
|
||||
rng.buffer = rng.internal_u64()
|
||||
rng.buffer = rng.u64()
|
||||
rng.bytes_left = 7
|
||||
value := byte(rng.buffer)
|
||||
rng.buffer >>= 8
|
||||
return value
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (mut rng SplitMix64RNG) step_by(amount int) u64 {
|
||||
next_number := rng.internal_u64()
|
||||
|
||||
bits_left := rng.bytes_left * 8
|
||||
bits_needed := amount - bits_left
|
||||
|
||||
old_value := rng.buffer & ((u64(1) << bits_left) - 1)
|
||||
new_value := next_number & ((u64(1) << bits_needed) - 1)
|
||||
value := old_value | (new_value << bits_left)
|
||||
|
||||
rng.buffer = next_number >> bits_needed
|
||||
rng.bytes_left = 8 - (bits_needed / 8)
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// u16 returns a pseudorandom 16bit int in range `[0, 2¹⁶)`.
|
||||
[inline]
|
||||
pub fn (mut rng SplitMix64RNG) u16() u16 {
|
||||
// Can we take a whole u16 out of the buffer?
|
||||
if rng.bytes_left >= 2 {
|
||||
rng.bytes_left -= 2
|
||||
value := u16(rng.buffer)
|
||||
rng.buffer >>= 16
|
||||
return value
|
||||
}
|
||||
if rng.bytes_left > 0 {
|
||||
return u16(rng.step_by(16))
|
||||
}
|
||||
ans := rng.internal_u64()
|
||||
ans := rng.u64()
|
||||
rng.buffer = ans >> 16
|
||||
rng.bytes_left = 6
|
||||
return u16(ans)
|
||||
|
|
@ -84,18 +61,13 @@ pub fn (mut rng SplitMix64RNG) u16() u16 {
|
|||
// u32 returns a pseudorandom 32bit int in range `[0, 2³²)`.
|
||||
[inline]
|
||||
pub fn (mut rng SplitMix64RNG) u32() u32 {
|
||||
// Can we take a whole u32 out of the buffer?
|
||||
if rng.bytes_left >= 4 {
|
||||
rng.bytes_left -= 4
|
||||
value := u32(rng.buffer)
|
||||
rng.buffer >>= 32
|
||||
return value
|
||||
}
|
||||
if rng.bytes_left > 0 {
|
||||
return u32(rng.step_by(32))
|
||||
}
|
||||
// We're out so we start fresh.
|
||||
ans := rng.internal_u64()
|
||||
ans := rng.u64()
|
||||
rng.buffer = ans >> 32
|
||||
rng.bytes_left = 4
|
||||
return u32(ans)
|
||||
|
|
@ -104,15 +76,6 @@ pub fn (mut rng SplitMix64RNG) u32() u32 {
|
|||
// u64 returns a pseudorandom 64bit int in range `[0, 2⁶⁴)`.
|
||||
[inline]
|
||||
pub fn (mut rng SplitMix64RNG) u64() u64 {
|
||||
if rng.bytes_left > 0 {
|
||||
return rng.step_by(64)
|
||||
}
|
||||
return rng.internal_u64()
|
||||
}
|
||||
|
||||
// u64 updates the PRNG state and returns the next pseudorandom `u64`.
|
||||
[inline]
|
||||
fn (mut rng SplitMix64RNG) internal_u64() u64 {
|
||||
rng.state += (0x9e3779b97f4a7c15)
|
||||
mut z := rng.state
|
||||
z = (z ^ (z >> u64(30))) * 0xbf58476d1ce4e5b9
|
||||
|
|
@ -120,6 +83,7 @@ fn (mut rng SplitMix64RNG) internal_u64() u64 {
|
|||
return z ^ (z >> (31))
|
||||
}
|
||||
|
||||
// block_size returns the number of bits that the RNG can produce in a single iteration.
|
||||
[inline]
|
||||
pub fn (mut rng SplitMix64RNG) block_size() int {
|
||||
return 64
|
||||
|
|
|
|||
|
|
@ -319,43 +319,3 @@ fn test_splitmix64_f64_in_range() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_splitmix64_buffering() {
|
||||
for seed in seeds {
|
||||
for offset in [0, 2, 3, 5, 19, 47] {
|
||||
count := 5
|
||||
mut rngs := []rand.PRNG{cap: count}
|
||||
|
||||
for i in 0 .. count {
|
||||
rngs << &rand.PRNG(&splitmix64.SplitMix64RNG{})
|
||||
rngs[i].seed(seed)
|
||||
}
|
||||
|
||||
for mut rng in rngs {
|
||||
for _ in 0 .. offset {
|
||||
rng.byte()
|
||||
}
|
||||
}
|
||||
|
||||
for _ in 0 .. 6 {
|
||||
first_64bit := rngs[0].u64()
|
||||
second_64bit := u64(rngs[1].u32()) | (u64(rngs[1].u32()) << 32)
|
||||
mut third_64bit := u64(rngs[2].byte())
|
||||
|
||||
for shift in 1 .. 8 {
|
||||
third_64bit |= u64(rngs[2].byte()) << (shift * 8)
|
||||
}
|
||||
|
||||
fourth_64bit := u64(rngs[3].byte()) | (u64(rngs[3].u32()) << 8) | (u64(rngs[3].u16()) << 40) | (u64(rngs[3].byte()) << 56)
|
||||
|
||||
eight_bytes := rngs[4].bytes(8) or { panic("Couldn't obtain random bytes") }
|
||||
mut fifth_64bit := u64(eight_bytes[0]) | (u64(eight_bytes[1]) << 8) | (u64(eight_bytes[2]) << 16) | (u64(eight_bytes[3]) << 24) | (u64(eight_bytes[4]) << 32) | (u64(eight_bytes[5]) << 40) | (u64(eight_bytes[6]) << 48) | (u64(eight_bytes[7]) << 56)
|
||||
|
||||
assert first_64bit == second_64bit
|
||||
assert first_64bit == third_64bit
|
||||
assert first_64bit == fourth_64bit
|
||||
assert first_64bit == fifth_64bit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,9 @@ fn calculate_iterations_for(bits int) int {
|
|||
// SysRNG is the PRNG provided by default in the libc implementiation that V uses.
|
||||
pub struct SysRNG {
|
||||
mut:
|
||||
seed u32 = seed.time_seed_32()
|
||||
seed u32 = seed.time_seed_32()
|
||||
buffer int
|
||||
bytes_left int
|
||||
}
|
||||
|
||||
// r.seed() sets the seed of the accepting SysRNG to the given data.
|
||||
|
|
@ -62,13 +64,29 @@ pub fn (r SysRNG) default_rand() int {
|
|||
|
||||
// byte returns a uniformly distributed pseudorandom 8-bit unsigned positive `byte`.
|
||||
[inline]
|
||||
pub fn (r SysRNG) byte() byte {
|
||||
return byte(C.rand())
|
||||
pub fn (mut r SysRNG) byte() byte {
|
||||
if r.bytes_left >= 1 {
|
||||
r.bytes_left -= 1
|
||||
value := byte(r.buffer)
|
||||
r.buffer >>= 8
|
||||
return value
|
||||
}
|
||||
r.buffer = r.default_rand()
|
||||
r.bytes_left = sys.rand_bytesize - 1
|
||||
value := byte(r.buffer)
|
||||
r.buffer >>= 8
|
||||
return value
|
||||
}
|
||||
|
||||
// u16 returns a uniformly distributed pseudorandom 16-bit unsigned positive `u16`.
|
||||
[inline]
|
||||
pub fn (r SysRNG) u16() u16 {
|
||||
pub fn (mut r SysRNG) u16() u16 {
|
||||
if r.bytes_left >= 2 {
|
||||
r.bytes_left -= 2
|
||||
value := u16(r.buffer)
|
||||
r.buffer >>= 16
|
||||
return value
|
||||
}
|
||||
mut result := u16(C.rand())
|
||||
for i in 1 .. sys.u16_iter_count {
|
||||
result = result ^ (u16(C.rand()) << (sys.rand_bitsize * i))
|
||||
|
|
@ -96,6 +114,7 @@ pub fn (r SysRNG) u64() u64 {
|
|||
return result
|
||||
}
|
||||
|
||||
// block_size returns the number of bits that the RNG can produce in a single iteration.
|
||||
[inline]
|
||||
pub fn (r SysRNG) block_size() int {
|
||||
return sys.rand_bitsize
|
||||
|
|
|
|||
|
|
@ -42,44 +42,23 @@ pub fn (mut rng WyRandRNG) byte() byte {
|
|||
return value
|
||||
}
|
||||
// Add a new value to the buffer
|
||||
rng.buffer = rng.internal_u64()
|
||||
rng.buffer = rng.u64()
|
||||
rng.bytes_left = 7
|
||||
value := byte(rng.buffer)
|
||||
rng.buffer >>= 8
|
||||
return value
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (mut rng WyRandRNG) step_by(amount int) u64 {
|
||||
next_number := rng.internal_u64()
|
||||
|
||||
bits_left := rng.bytes_left * 8
|
||||
bits_needed := amount - bits_left
|
||||
|
||||
old_value := rng.buffer & ((u64(1) << bits_left) - 1)
|
||||
new_value := next_number & ((u64(1) << bits_needed) - 1)
|
||||
value := old_value | (new_value << bits_left)
|
||||
|
||||
rng.buffer = next_number >> bits_needed
|
||||
rng.bytes_left = 8 - (bits_needed / 8)
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// u16 returns a pseudorandom 16bit int in range `[0, 2¹⁶)`.
|
||||
[inline]
|
||||
pub fn (mut rng WyRandRNG) u16() u16 {
|
||||
// Can we take a whole u16 out of the buffer?
|
||||
if rng.bytes_left >= 2 {
|
||||
rng.bytes_left -= 2
|
||||
value := u16(rng.buffer)
|
||||
rng.buffer >>= 16
|
||||
return value
|
||||
}
|
||||
if rng.bytes_left > 0 {
|
||||
return u16(rng.step_by(16))
|
||||
}
|
||||
ans := rng.internal_u64()
|
||||
ans := rng.u64()
|
||||
rng.buffer = ans >> 16
|
||||
rng.bytes_left = 6
|
||||
return u16(ans)
|
||||
|
|
@ -88,18 +67,13 @@ pub fn (mut rng WyRandRNG) u16() u16 {
|
|||
// u32 returns a pseudorandom 32bit int in range `[0, 2³²)`.
|
||||
[inline]
|
||||
pub fn (mut rng WyRandRNG) u32() u32 {
|
||||
// Can we take a whole u32 out of the buffer?
|
||||
if rng.bytes_left >= 4 {
|
||||
rng.bytes_left -= 4
|
||||
value := u32(rng.buffer)
|
||||
rng.buffer >>= 32
|
||||
return value
|
||||
}
|
||||
if rng.bytes_left > 0 {
|
||||
return u32(rng.step_by(32))
|
||||
}
|
||||
// We're out so we start fresh.
|
||||
ans := rng.internal_u64()
|
||||
ans := rng.u64()
|
||||
rng.buffer = ans >> 32
|
||||
rng.bytes_left = 4
|
||||
return u32(ans)
|
||||
|
|
@ -108,14 +82,6 @@ pub fn (mut rng WyRandRNG) u32() u32 {
|
|||
// u64 returns a pseudorandom 64bit int in range `[0, 2⁶⁴)`.
|
||||
[inline]
|
||||
pub fn (mut rng WyRandRNG) u64() u64 {
|
||||
if rng.bytes_left > 0 {
|
||||
return rng.step_by(64)
|
||||
}
|
||||
return rng.internal_u64()
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (mut rng WyRandRNG) internal_u64() u64 {
|
||||
unsafe {
|
||||
mut seed1 := rng.state
|
||||
seed1 += wyrand.wyp0
|
||||
|
|
@ -125,6 +91,7 @@ fn (mut rng WyRandRNG) internal_u64() u64 {
|
|||
return 0
|
||||
}
|
||||
|
||||
// block_size returns the number of bits that the RNG can produce in a single iteration.
|
||||
[inline]
|
||||
pub fn (mut rng WyRandRNG) block_size() int {
|
||||
return 64
|
||||
|
|
|
|||
|
|
@ -319,43 +319,3 @@ fn test_wyrand_f64_in_range() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test_wyrand_buffering() {
|
||||
for seed in seeds {
|
||||
for offset in [0, 2, 3, 5, 19, 47] {
|
||||
count := 5
|
||||
mut rngs := []rand.PRNG{cap: count}
|
||||
|
||||
for i in 0 .. count {
|
||||
rngs << &rand.PRNG(&wyrand.WyRandRNG{})
|
||||
rngs[i].seed(seed)
|
||||
}
|
||||
|
||||
for mut rng in rngs {
|
||||
for _ in 0 .. offset {
|
||||
rng.byte()
|
||||
}
|
||||
}
|
||||
|
||||
for _ in 0 .. 6 {
|
||||
first_64bit := rngs[0].u64()
|
||||
second_64bit := u64(rngs[1].u32()) | (u64(rngs[1].u32()) << 32)
|
||||
mut third_64bit := u64(rngs[2].byte())
|
||||
|
||||
for shift in 1 .. 8 {
|
||||
third_64bit |= u64(rngs[2].byte()) << (shift * 8)
|
||||
}
|
||||
|
||||
fourth_64bit := u64(rngs[3].byte()) | (u64(rngs[3].u32()) << 8) | (u64(rngs[3].u16()) << 40) | (u64(rngs[3].byte()) << 56)
|
||||
|
||||
eight_bytes := rngs[4].bytes(8) or { panic("Couldn't obtain random bytes") }
|
||||
mut fifth_64bit := u64(eight_bytes[0]) | (u64(eight_bytes[1]) << 8) | (u64(eight_bytes[2]) << 16) | (u64(eight_bytes[3]) << 24) | (u64(eight_bytes[4]) << 32) | (u64(eight_bytes[5]) << 40) | (u64(eight_bytes[6]) << 48) | (u64(eight_bytes[7]) << 56)
|
||||
|
||||
assert first_64bit == second_64bit
|
||||
assert first_64bit == third_64bit
|
||||
assert first_64bit == fourth_64bit
|
||||
assert first_64bit == fifth_64bit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue