1use crate::prelude::*;
10use parking_lot::Mutex;
11use rand::distributions::uniform::{SampleRange, SampleUniform};
12use rand::distributions::{self, Distribution};
13use rand::seq::SliceRandom;
14use rand::{Rng as _, SeedableRng as _};
15use rand_xoshiro::Xoshiro256StarStar;
16use std::cell::RefCell;
17
18pub fn chance(probability: f64) -> bool {
23 THREAD_RNG.with(|rng| rng.borrow_mut().gen_chance(probability))
24}
25
26pub fn fill_bytes(bytes: &mut [u8]) {
28 THREAD_RNG.with(|rng| rng.borrow_mut().fill_bytes(bytes))
29}
30
31pub fn random<T: Random>() -> T {
33 THREAD_RNG.with(|rng| T::random_with(&mut rng.borrow_mut()))
34}
35
36pub fn range<T: SampleUniform>(range: impl SampleRange<T>) -> T {
38 THREAD_RNG.with(|rng| rng.borrow_mut().gen_range(range))
39}
40
41pub fn ratio<T: Number + SampleUniform>(numerator: T, denominator: T) -> bool {
44 THREAD_RNG.with(|rng| rng.borrow_mut().gen_ratio(numerator, denominator))
45}
46
47pub fn shuffle<T>(slice: &mut [T]) {
49 THREAD_RNG.with(|rng| rng.borrow_mut().shuffle(slice))
50}
51
52pub trait Random: Sized {
54 fn random_with(rng: &mut Rng) -> Self;
56
57 fn random() -> Self {
59 random()
60 }
61}
62
63impl<T> Random for T
66where
67 distributions::Standard: Distribution<T>,
68{
69 fn random_with(rng: &mut Rng) -> Self {
70 rng.inner.gen()
71 }
72}
73
74#[derive(Clone)]
76pub struct Rng {
77 inner: Xoshiro256StarStar,
78}
79
80static GLOBAL_RNG: Lazy<Mutex<Rng>> =
82 Lazy::new(|| Mutex::new(Rng { inner: Xoshiro256StarStar::from_entropy() }));
83
84thread_local! {
85 static THREAD_RNG: RefCell<Rng> = {
87 let mut global_rng = GLOBAL_RNG.lock();
88 let thread_rng = global_rng.clone();
89
90 global_rng.inner.long_jump();
91
92 RefCell::new(thread_rng)
93 };
94}
95
96impl Rng {
97 pub fn new() -> Rng {
99 THREAD_RNG.with(|rng| {
100 let mut thread_rng = rng.borrow_mut();
101 let local_rng = thread_rng.clone();
102
103 thread_rng.inner.jump();
104
105 local_rng
106 })
107 }
108
109 pub fn fill_bytes(&mut self, bytes: &mut [u8]) {
111 self.inner.fill(bytes);
112 }
113
114 pub fn gen<T: Random>(&mut self) -> T {
116 T::random_with(self)
117 }
118
119 pub fn gen_chance(&mut self, probability: f64) -> bool {
124 probability > self.gen()
125 }
126
127 pub fn gen_range<T: SampleUniform>(&mut self, range: impl SampleRange<T>) -> T {
129 self.inner.gen_range(range)
130 }
131
132 pub fn gen_ratio<T: Number + SampleUniform>(&mut self, numerator: T, denominator: T) -> bool {
135 debug_assert!(denominator > T::zero(), "The denominator of a ratio must be greater than zero.");
136
137 numerator > self.gen_range(T::zero()..denominator)
138 }
139
140 pub fn shuffle<T>(&mut self, slice: &mut [T]) {
142 slice.shuffle(&mut self.inner);
143 }
144}
145
146impl Default for Rng {
147 fn default() -> Self {
148 Self::new()
149 }
150}