use super::rand::prelude::*;
use super::serde::{Deserialize, Serialize};
use rand_core::impls::fill_bytes_via_next;
use rand_core::le::read_u64_into;
use rand_core::{RngCore, SeedableRng};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Xoroshiro128StarStar {
s0: u64,
s1: u64,
}
impl Default for Xoroshiro128StarStar {
fn default() -> Self {
Self::new()
}
}
impl Xoroshiro128StarStar {
#[inline]
pub fn next_f64(&mut self) -> f64 {
f64::from_bits(0x3FF << 52 | self.next_u64() >> 12) - 1.
}
#[allow(dead_code)]
pub fn get_s0_i64(&self) -> i64 {
i64::from_le_bytes(self.s0.to_le_bytes())
}
#[allow(dead_code)]
pub fn get_s1_i64(&self) -> i64 {
i64::from_le_bytes(self.s1.to_le_bytes())
}
pub fn new() -> Self {
let mut rng = thread_rng();
Self::seed_from_u64(rng.gen::<u64>())
}
}
impl RngCore for Xoroshiro128StarStar {
#[inline]
fn next_u32(&mut self) -> u32 {
self.next_u64() as u32
}
#[inline]
fn next_u64(&mut self) -> u64 {
let r = self.s0.wrapping_mul(5).rotate_left(7).wrapping_mul(9);
self.s1 ^= self.s0;
self.s0 = self.s0.rotate_left(24) ^ self.s1 ^ (self.s1 << 16);
self.s1 = self.s1.rotate_left(37);
r
}
#[inline]
fn fill_bytes(&mut self, dest: &mut [u8]) {
fill_bytes_via_next(self, dest);
}
#[inline]
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
self.fill_bytes(dest);
Ok(())
}
}
impl SeedableRng for Xoroshiro128StarStar {
type Seed = [u8; 16];
fn from_seed(seed: [u8; 16]) -> Xoroshiro128StarStar {
if seed.iter().all(|&x| x == 0) {
return Self::seed_from_u64(0);
}
let mut s = [0; 2];
read_u64_into(&seed, &mut s);
Self { s0: s[0], s1: s[1] }
}
fn seed_from_u64(seed: u64) -> Xoroshiro128StarStar {
let mut rng = SplitMix64::seed_from_u64(seed);
let s0 = rng.next_u64();
let s1 = rng.next_u64();
Self { s0, s1 }
}
}
pub struct SplitMix64 {
x: u64,
}
impl SplitMix64 {
#[allow(dead_code)]
pub fn get_x_i64(&self) -> i64 {
i64::from_le_bytes(self.x.to_le_bytes())
}
}
const PHI: u64 = 0x9e3779b97f4a7c15;
impl SeedableRng for SplitMix64 {
type Seed = [u8; 8];
fn from_seed(seed: [u8; 8]) -> SplitMix64 {
let mut state = [0; 1];
read_u64_into(&seed, &mut state);
SplitMix64 { x: state[0] }
}
fn seed_from_u64(seed: u64) -> SplitMix64 {
SplitMix64::from_seed(seed.to_le_bytes())
}
}
impl RngCore for SplitMix64 {
#[inline]
fn next_u32(&mut self) -> u32 {
self.x = self.x.wrapping_add(PHI);
let mut z = self.x;
z = (z ^ (z >> 33)).wrapping_mul(0x62A9D9ED799705F5);
z = (z ^ (z >> 28)).wrapping_mul(0xCB24D0A5C88C35B3);
(z >> 32) as u32
}
#[inline]
fn next_u64(&mut self) -> u64 {
self.x = self.x.wrapping_add(PHI);
let mut z = self.x;
z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
z ^ (z >> 31)
}
#[inline]
fn fill_bytes(&mut self, dest: &mut [u8]) {
fill_bytes_via_next(self, dest);
}
#[inline]
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
self.fill_bytes(dest);
Ok(())
}
}
impl SplitMix64 {
#[inline]
#[allow(dead_code)]
pub fn next_f64(&mut self) -> f64 {
f64::from_bits(0x3FF << 52 | self.next_u64() >> 12) - 1.
}
}