use std::io::Write;
use rand::{Rng, SeedableRng, Rand};
use byteorder::{LittleEndian, ByteOrder};
#[allow(missing_copy_implementations)]
#[derive(Debug, Clone)]
pub struct SplitMix64 {
x: u64,
}
impl SplitMix64 {
pub fn new_unseeded() -> SplitMix64 {
SplitMix64 {
x: 0,
}
}
}
impl Rng for SplitMix64 {
#[inline]
fn next_u32(&mut self) -> u32 {
self.next_u64() as u32
}
#[inline]
fn next_u64(&mut self) -> u64 {
self.x = self.x.wrapping_add(0x9e3779b97f4a7c15);
let mut z = self.x;
z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
return z ^ (z >> 31);
}
#[inline]
fn fill_bytes(&mut self, mut dest: &mut [u8]) {
let mut to_write = dest.len();
let mut buf = [0; 64 / 8];
while to_write > 0 {
LittleEndian::write_u64(&mut buf, self.next_u64());
match dest.write(&buf) {
Ok(n) => to_write -= n,
Err(e) => panic!("SplitMix64::fill_bytes failed: {}", e),
}
}
}
}
impl SeedableRng<u64> for SplitMix64 {
fn reseed(&mut self, seed: u64) {
self.x = seed;
}
fn from_seed(seed: u64) -> SplitMix64 {
SplitMix64 {
x: seed,
}
}
}
impl Rand for SplitMix64 {
fn rand<R: Rng>(rng: &mut R) -> SplitMix64 {
SplitMix64 {
x: rng.gen(),
}
}
}