ya_rand/
rng.rs

1const F64_MANT: u32 = f64::MANTISSA_DIGITS;
2const F32_MANT: u32 = f32::MANTISSA_DIGITS;
3const F64_MAX_PRECISE: u64 = 1 << F64_MANT;
4const F32_MAX_PRECISE: u64 = 1 << F32_MANT;
5const F64_DIVISOR: f64 = F64_MAX_PRECISE as f64;
6const F32_DIVISOR: f32 = F32_MAX_PRECISE as f32;
7pub const ALPHANUMERIC: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
8
9/// Trait for RNGs that are known to provide streams of cryptographically secure data.
10#[cfg(feature = "secure")]
11pub trait SecureYARandGenerator: YARandGenerator {
12    /// Generates a random `String` with length `len`, using the provided
13    /// `Encoder` to determine character set and minimum secure length.
14    /// Returns `None` only when `len` is less than what the encoder
15    /// declares to be secure.
16    ///
17    /// All provided encoders are accessible through [`crate::ya_rand_encoding`].
18    /// Users wishing to implement their own encoding must do so through
19    /// [`Encoder`](crate::ya_rand_encoding::Encoder).
20    ///
21    /// Originally inspired by golang's addition of [`rand.Text`] in release 1.24,
22    /// but altered to be encoding/length generic and unbiased for non-trivial bases.
23    ///
24    /// [`rand.Text`]:
25    /// https://cs.opensource.google/go/go/+/refs/tags/go1.24.0:src/crypto/rand/text.go
26    #[cfg(feature = "std")]
27    #[inline(never)]
28    fn text<E>(&mut self, len: usize) -> Option<std::string::String>
29    where
30        E: crate::ya_rand_encoding::Encoder,
31    {
32        match len >= E::MIN_LEN {
33            true => Some({
34                const BYTE_VALUES: usize = 1 << u8::BITS;
35                // SAFETY: u8's are a trivial type and we pwomise to
36                // always overwrite all of them UwU.
37                let mut data = unsafe {
38                    std::boxed::Box::new_uninit_slice(len)
39                        .assume_init()
40                        .into_vec()
41                };
42                // This branch is evaluated at compile time, so concrete
43                // implementations in final binaries will only have the
44                // contents of the branch suitable for the encoder used.
45                if BYTE_VALUES % E::CHARSET.len() == 0 {
46                    // Fill vec with random data.
47                    self.fill_bytes(&mut data);
48                    // Directly map each random u8 to a character in the set.
49                    // Since this branch is only reachable when length is a power
50                    // of two, the modulo gets optimized out and the whole thing
51                    // gets vectorized. The assembly for this branch is
52                    // absolutely beautiful.
53                    // This approach is extremely efficient, but only produces
54                    // unbiased random sequences when the length of the current
55                    // `CHARSET` is divisible by the amount of possible u8 values,
56                    // which is why we need a fallback approach.
57                    for d in &mut data {
58                        let random_value = *d as usize;
59                        *d = E::CHARSET[random_value % E::CHARSET.len()];
60                    }
61                } else {
62                    // Alternative approach that's potentially much slower,
63                    // but always produces unbiased results.
64                    data.fill_with(|| *self.choose(E::CHARSET).unwrap());
65                }
66                // SAFETY: All provided encoders only use ascii values, and custom
67                // encoder implementations agree to do the same when implementing
68                // the `YARandEncoder` trait.
69                unsafe { std::string::String::from_utf8_unchecked(data) }
70            }),
71            false => None,
72        }
73    }
74
75    /// Fills `dest` with random data, which is safe to be used
76    /// in cryptographic contexts.
77    ///
78    /// # Examples
79    ///
80    /// ```
81    /// use ya_rand::*;
82    ///
83    /// let mut rng = new_rng_secure();
84    /// let mut data = [0; 1738];
85    /// rng.fill_bytes(&mut data);
86    /// assert!(data.into_iter().any(|v| v != 0));
87    /// ```
88    fn fill_bytes(&mut self, dest: &mut [u8]);
89}
90
91/// Trait for RNGs that can be created from a user-provided seed.
92pub trait SeedableYARandGenerator: YARandGenerator + Default {
93    /// Creates a generator from the output of an internal PRNG,
94    /// which is itself seeded from `seed`.
95    ///
96    /// As a rule: unless you are **absolutely certain** that you need to manually
97    /// seed a generator, you don't.
98    /// Instead, use [`crate::new_rng`] when you need to create a new instance.
99    ///
100    /// If you have a scenario where you really do need a set seed, prefer to use the
101    /// `Default` implementation of the desired generator.
102    ///
103    /// # Examples
104    ///
105    /// ```
106    /// use ya_rand::*;
107    ///
108    /// // In actual use these would be declared `mut`.
109    /// let rng1 = ShiroRng::new_with_seed(0);
110    /// let rng2 = ShiroRng::default();
111    /// // Default is just a shortcut for manually seeding with 0.
112    /// assert!(rng1 == rng2);
113    /// ```
114    fn new_with_seed(seed: u64) -> Self;
115}
116
117/// Base trait that all RNGs must implement.
118pub trait YARandGenerator: Sized {
119    /// Creates a generator using randomness provided by the OS.
120    ///
121    /// Unlike [`YARandGenerator::new`], which will panic on failure, `try_new`
122    /// propagates the error-handling responsibility to the user. But the probability
123    /// of your operating systems RNG failing is absurdly low, and in the rare case that it
124    /// does fail, that's not really an issue most users are going to be able to address.
125    ///
126    /// Stick to using [`crate::new_rng`], unless you really need a generator of a
127    /// different type (you probably don't), then use `new` on your desired type.
128    fn try_new() -> Result<Self, getrandom::Error>;
129
130    /// Creates a generator using randomness provided by the OS.
131    ///
132    /// It is recommended to use the top-level [`crate::new_rng`] instead
133    /// of calling this function on a specific generator type.
134    ///
135    /// # Safety
136    ///
137    /// This function will panic if your OS rng fails to provide enough entropy.
138    /// But this is extremely unlikely, and unless you're working at the kernel level it's
139    /// not something you should ever be concerned with.
140    ///
141    /// Since Windows 10 this function is infallible, thanks to modern Windows versions adopting
142    /// a user-space cryptographic architecture that can't fail during runtime.
143    ///
144    /// # Examples
145    ///
146    /// ```
147    /// use ya_rand::*;
148    ///
149    /// // Recommended usage
150    /// let mut rng1 = new_rng();
151    /// // More explicit
152    /// let mut rng2 = ShiroRng::new();
153    /// // Even more explicit
154    /// let mut rng3 = Xoshiro256pp::new();
155    /// // Since these are all created using OS entropy, the odds of
156    /// // their initial states colliding is vanishingly small.
157    /// assert!(rng1 != rng2);
158    /// assert!(rng1 != rng3);
159    /// assert!(rng2 != rng3);
160    /// ```
161    fn new() -> Self {
162        Self::try_new().expect(
163            "WARNING: retrieving random data from the operating system should never fail; \
164            something has gone terribly wrong",
165        )
166    }
167
168    /// Returns a uniformly distributed u64 in the interval [0, 2<sup>64</sup>).
169    fn u64(&mut self) -> u64;
170
171    /// Returns a uniformly distributed u32 in the interval [0, 2<sup>32</sup>).
172    #[inline]
173    fn u32(&mut self) -> u32 {
174        self.bits(u32::BITS) as u32
175    }
176
177    /// Returns a uniformly distributed u16 in the interval [0, 2<sup>16</sup>).
178    #[inline]
179    fn u16(&mut self) -> u16 {
180        self.bits(u16::BITS) as u16
181    }
182
183    /// Returns a uniformly distributed u8 in the interval [0, 2<sup>8</sup>).
184    #[inline]
185    fn u8(&mut self) -> u8 {
186        self.bits(u8::BITS) as u8
187    }
188
189    /// Returns a uniformly distributed u64 in the interval [0, 2<sup>`bit_count`</sup>).
190    ///
191    /// The value of `bit_count` is clamped to 64.
192    #[inline]
193    fn bits(&mut self, bit_count: u32) -> u64 {
194        self.u64() >> (u64::BITS - bit_count.min(u64::BITS))
195    }
196
197    /// A simple coinflip, returning a bool that has a 50% chance of being true.
198    ///
199    /// # Examples
200    ///
201    /// ```
202    /// use ya_rand::*;
203    ///
204    /// const ITERATIONS: u64 = 1 << 24;
205    /// let mut rng = new_rng();
206    /// let mut yes: u64 = 0;
207    /// let mut no: u64 = 0;
208    /// for _ in 0..ITERATIONS {
209    ///     if rng.bool() {
210    ///         yes += 1;
211    ///     } else {
212    ///         no += 1;
213    ///     }
214    /// }
215    /// // We expect the difference to be within ~5%.
216    /// let THRESHOLD: u64 = ITERATIONS / 20;
217    /// assert!(yes.abs_diff(no) <= THRESHOLD);
218    /// ```
219    #[inline]
220    fn bool(&mut self) -> bool {
221        // Compiles to a single "shr 63" instruction.
222        self.bits(1) == 1
223    }
224
225    /// Returns a uniformly distributed u64 in the interval [0, `max`).
226    ///
227    /// Using [`YARandGenerator::bits`] when `max` happens to be a power of 2
228    /// is faster and generates better assembly.
229    ///
230    /// # Examples
231    ///
232    /// ```
233    /// use ya_rand::*;
234    ///
235    /// let mut rng = new_rng();
236    /// // Special case: bound of 0 always returns 0.
237    /// assert!(rng.bound(0) == 0);
238    /// for i in 1..=2000 {
239    ///     for _ in 0..(i * 2) {
240    ///         assert!(rng.bound(i) < i);
241    ///     }
242    /// }
243    /// ```
244    #[inline]
245    fn bound(&mut self, max: u64) -> u64 {
246        // Lemire's method: https://arxiv.org/abs/1805.10941.
247        let mut mul = || crate::util::wide_mul(self.u64(), max);
248        let (mut high, mut low) = mul();
249        match low < max {
250            false => {}
251            true => {
252                let threshold = max.wrapping_neg() % max;
253                while low < threshold {
254                    (high, low) = mul();
255                }
256            }
257        }
258        debug_assert!((max != 0 && high < max) || high == 0);
259        high
260    }
261
262    /// Returns a uniformly distributed u64 in the interval \[0, `max`\].
263    ///
264    /// # Examples
265    ///
266    /// ```
267    /// use ya_rand::*;
268    ///
269    /// let mut rng = new_rng();
270    /// for i in 0..=2000 {
271    ///     for _ in 0..(i * 2) {
272    ///         assert!(rng.bound_inclusive(i) <= i);
273    ///     }
274    /// }
275    /// ```
276    #[inline]
277    fn bound_inclusive(&mut self, max: u64) -> u64 {
278        self.bound(max + 1)
279    }
280
281    /// Returns a uniformly distributed i64 in the interval [`min`, `max`)
282    #[inline]
283    fn range(&mut self, min: i64, max: i64) -> i64 {
284        let delta = max - min;
285        debug_assert!(delta > 0);
286        (self.bound(delta as u64) as i64) + min
287    }
288
289    /// Returns a uniformly distributed i64 in the interval \[`min`, `max`\]
290    #[inline]
291    fn range_inclusive(&mut self, min: i64, max: i64) -> i64 {
292        self.range(min, max + 1)
293    }
294
295    /// Returns a uniformly distributed f64 in the interval [0.0, 1.0).
296    #[inline]
297    fn f64(&mut self) -> f64 {
298        (self.bits(F64_MANT) as f64) / F64_DIVISOR
299    }
300
301    /// Returns a uniformly distributed f32 in the interval [0.0, 1.0).
302    #[inline]
303    fn f32(&mut self) -> f32 {
304        (self.bits(F32_MANT) as f32) / F32_DIVISOR
305    }
306
307    /// Returns a uniformly distributed f64 in the interval (0.0, 1.0].
308    #[inline]
309    fn f64_nonzero(&mut self) -> f64 {
310        // Interval of (0, 2^53]
311        let nonzero = self.bits(F64_MANT) + 1;
312        (nonzero as f64) / F64_DIVISOR
313    }
314
315    /// Returns a uniformly distributed f32 in the interval (0.0, 1.0].
316    #[inline]
317    fn f32_nonzero(&mut self) -> f32 {
318        // Interval of (0, 2^24]
319        let nonzero = self.bits(F32_MANT) + 1;
320        (nonzero as f32) / F32_DIVISOR
321    }
322
323    /// Returns a uniformly distributed f64 in the interval (-1.0, 1.0).
324    #[inline]
325    fn f64_wide(&mut self) -> f64 {
326        // This approach is faster than using Generator::range.
327        const BITS: u32 = F64_MANT + 1;
328        const OFFSET: i64 = F64_MAX_PRECISE as i64;
329        let mut x: i64;
330        loop {
331            // Start with an interval of [0, 2^54)
332            x = self.bits(BITS) as i64;
333            // Interval is now (0, 2^54)
334            match x != 0 {
335                true => break,
336                false => {}
337            }
338        }
339        // Shift interval to (-2^53, 2^53)
340        x -= OFFSET;
341        (x as f64) / F64_DIVISOR
342    }
343
344    /// Returns a uniformly distributed f32 in the interval (-1.0, 1.0).
345    #[inline]
346    fn f32_wide(&mut self) -> f32 {
347        // This approach is faster than using Generator::range.
348        const BITS: u32 = F32_MANT + 1;
349        const OFFSET: i64 = F32_MAX_PRECISE as i64;
350        let mut x: i64;
351        loop {
352            // Start with an interval of [0, 2^25)
353            x = self.bits(BITS) as i64;
354            // Interval is now (0, 2^25)
355            match x != 0 {
356                true => break,
357                false => {}
358            }
359        }
360        // Shift interval to (-2^24, 2^24)
361        x -= OFFSET;
362        (x as f32) / F32_DIVISOR
363    }
364
365    /// Returns two indepedent and normally distributed f64 values with
366    /// `mean` = 0.0 and `stddev` = 1.0.
367    #[cfg(feature = "std")]
368    fn f64_normal(&mut self) -> (f64, f64) {
369        // Marsaglia polar method.
370        // TLDR: It projects a point **within** the unit
371        // circle onto the unit radius.
372        let mut x: f64;
373        let mut y: f64;
374        let mut s: f64;
375        loop {
376            x = self.f64_wide();
377            y = self.f64_wide();
378            s = (x * x) + (y * y);
379            // Reroll if s does not lie **within** the unit circle.
380            match s < 1.0 && s != 0.0 {
381                true => break,
382                false => {}
383            }
384        }
385        let t = (2.0 * s.ln().abs() / s).sqrt();
386        (x * t, y * t)
387    }
388
389    /// Returns two indepedent and normally distributed f64 values with
390    /// user-defined `mean` and `stddev`.
391    #[cfg(feature = "std")]
392    #[inline]
393    fn f64_normal_distribution(&mut self, mean: f64, stddev: f64) -> (f64, f64) {
394        debug_assert!(stddev != 0.0);
395        let (x, y) = self.f64_normal();
396        ((x * stddev) + mean, (y * stddev) + mean)
397    }
398
399    /// Returns an exponentially distributed f64 with `lambda` = 1.0.
400    #[cfg(feature = "std")]
401    #[inline]
402    fn f64_exponential(&mut self) -> f64 {
403        // Using abs() instead of negating the result of ln()
404        // to avoid outputs of -0.0.
405        self.f64_nonzero().ln().abs()
406    }
407
408    /// Returns an exponentially distributed f64 with user-defined `lambda`.
409    #[cfg(feature = "std")]
410    #[inline]
411    fn f64_exponential_lambda(&mut self, lambda: f64) -> f64 {
412        debug_assert!(lambda != 0.0);
413        self.f64_exponential() / lambda
414    }
415
416    /// Returns a randomly chosen item from the iterator of `collection`.
417    ///
418    /// Only returns `None` when the length of the iterator is zero.
419    ///
420    /// # Examples
421    ///
422    /// ```
423    /// use ya_rand::*;
424    ///
425    /// const SIZE: usize = 1738;
426    /// const HALF: usize = SIZE / 2;
427    /// let mut rng = new_rng();
428    /// let mut v = [0; SIZE];
429    /// for i in 0..SIZE {
430    ///     v[i] = i;
431    /// }
432    ///
433    /// let random_choice = rng.choose(&v).expect("Vector 'v' is not empty.");
434    /// assert!(v.contains(random_choice));
435    ///
436    /// let random_choice = rng.choose(&v[HALF..]).expect("Still not empty.");
437    /// assert!(v[HALF..].contains(random_choice) == true);
438    ///
439    /// // We randomly selected from the top half so we won't find
440    /// // our value in the bottom half.
441    /// assert!(v[..HALF].contains(random_choice) == false);
442    /// ```
443    #[inline]
444    fn choose<C>(&mut self, collection: C) -> Option<C::Item>
445    where
446        C: IntoIterator,
447        C::IntoIter: ExactSizeIterator,
448    {
449        let mut iter = collection.into_iter();
450        let len = iter.len();
451        match len != 0 {
452            true => Some({
453                let idx = self.bound(len as u64) as usize;
454                // SAFETY: Since `bound` always returns a value less than
455                // it's input, `nth` will never return `None`.
456                unsafe { iter.nth(idx).unwrap_unchecked() }
457            }),
458            false => None,
459        }
460    }
461
462    /// Returns a randomly selected ASCII alphabetic character.
463    #[inline]
464    fn ascii_alphabetic(&mut self) -> char {
465        *self.choose(&ALPHANUMERIC[..52]).unwrap() as char
466    }
467
468    /// Returns a randomly selected ASCII uppercase character.
469    #[inline]
470    fn ascii_uppercase(&mut self) -> char {
471        *self.choose(&ALPHANUMERIC[..26]).unwrap() as char
472    }
473
474    /// Returns a randomly selected ASCII lowercase character.
475    #[inline]
476    fn ascii_lowercase(&mut self) -> char {
477        *self.choose(&ALPHANUMERIC[26..52]).unwrap() as char
478    }
479
480    /// Returns a randomly selected ASCII alphanumeric character.
481    #[inline]
482    fn ascii_alphanumeric(&mut self) -> char {
483        *self.choose(&ALPHANUMERIC[..]).unwrap() as char
484    }
485
486    /// Returns a randomly selected ASCII digit character.
487    #[inline]
488    fn ascii_digit(&mut self) -> char {
489        *self.choose(&ALPHANUMERIC[52..]).unwrap() as char
490    }
491
492    /// Performs a Fisher-Yates shuffle on the contents of `slice`.
493    ///
494    /// This implementation is the modern variant introduced by
495    /// Richard Durstenfeld. It is in-place and O(n).
496    ///
497    /// # Examples
498    ///
499    /// ```
500    /// use ya_rand::*;
501    ///
502    /// let mut rng = new_rng();
503    /// let mut data = [0; 1738];
504    /// for i in 0..data.len() {
505    ///     data[i] = i;
506    /// }
507    /// assert!(data.is_sorted() == true);
508    ///
509    /// rng.shuffle(&mut data);
510    /// assert!(data.is_sorted() == false);
511    /// ```
512    #[inline(never)]
513    fn shuffle<T>(&mut self, slice: &mut [T]) {
514        let slice_ptr = slice.as_mut_ptr();
515        for i in (1..slice.len()).rev() {
516            let j = self.bound_inclusive(i as u64) as usize;
517            // SAFETY: Index 'i' will always be in bounds because it's
518            // bounded by slice length; index 'j' will always be
519            // in bounds because it's bounded by 'i'.
520            unsafe {
521                core::ptr::swap(slice_ptr.add(i), slice_ptr.add(j));
522            }
523        }
524    }
525}