mod private
{
use crate :: *;
use rand :: { RngCore, SeedableRng };
#[ cfg(not(feature = "no_std")) ]
use std ::sync :: { Arc, Mutex, RwLock };
use rand_chacha ::ChaCha8Rng;
pub type SharedGenerator = Arc< Mutex<ChaCha8Rng >>;
#[ derive(Debug, Clone) ]
pub struct Hrng
{
children: Arc< RwLock<Vec<Hrng >>>,
generator: SharedGenerator,
children_generator: SharedGenerator,
}
impl Hrng
{
#[ must_use ] pub fn master() -> Self {
Self ::master_with_seed(Seed ::default())
}
#[ must_use ]
#[ allow(clippy ::used_underscore_binding) ]
pub fn master_with_seed(seed: Seed) -> Self
{
let mut _generator: ChaCha8Rng = rand_seeder ::Seeder ::from(seed.into_inner()).make_rng();
let _children_generator = ChaCha8Rng ::seed_from_u64(_generator.next_u64());
let generator = Arc ::new(Mutex ::new(_generator));
#[ allow(clippy ::used_underscore_binding) ]
let children_generator = Arc ::new(Mutex ::new(_children_generator));
Self {
#[ allow(clippy ::default_trait_access) ]
children: Default ::default(),
generator,
children_generator,
}
}
fn _with_short_seed(seed: u64) -> Self
{
let rng = ChaCha8Rng ::seed_from_u64(seed);
Self ::_with_generator(rng)
}
fn _with_generator(mut rng: ChaCha8Rng) -> Self
{
rng.set_stream(1);
let _children_generator = ChaCha8Rng ::seed_from_u64(rng.next_u64());
rng.set_stream(0);
let generator = Arc ::new(Mutex ::new(rng));
#[ allow(clippy ::used_underscore_binding) ]
let children_generator = Arc ::new(Mutex ::new(_children_generator));
Self {
#[ allow(clippy ::default_trait_access) ]
children: Default ::default(),
generator,
children_generator,
}
}
#[ inline(always) ]
#[ must_use ] pub fn rng_ref( &self ) -> SharedGenerator {
self.generator.clone()
}
#[ must_use ] #[ allow(clippy ::missing_panics_doc) ]
pub fn child(&self, index: usize) -> Self
{
let children = self.children.read().unwrap();
if children.len() > index
{
return children[index].clone();
}
drop(children);
let mut rng = self.children_generator.lock().unwrap();
let mut children = self.children.write().unwrap();
let len = children.len();
if len > index
{
return children[index].clone();
}
children.reserve(index + 1 - len);
for _ in len..=index
{
children.push(Self ::_with_short_seed(rng.next_u64()));
}
children[index].clone()
}
#[ must_use ]
#[ allow(clippy ::missing_panics_doc) ]
pub fn _children_len( &self ) -> usize
{
self.children.read().unwrap().len()
}
}
impl Default for Hrng
{
fn default() -> Self
{
Hrng ::master()
}
}
}
crate ::mod_interface! {
orphan use Hrng;
}