ya_rand/
rng.rs

1use crate::util;
2use core::ptr;
3
4#[cfg(all(feature = "alloc", feature = "secure"))]
5use {
6    crate::encoding::Encoder,
7    alloc::{string::String, vec, vec::Vec},
8};
9
10const F64_MANT: u32 = f64::MANTISSA_DIGITS;
11const F32_MANT: u32 = f32::MANTISSA_DIGITS;
12const F64_MAX_PRECISE: u64 = 1 << F64_MANT;
13const F32_MAX_PRECISE: u64 = 1 << F32_MANT;
14const F64_DIVISOR: f64 = F64_MAX_PRECISE as f64;
15const F32_DIVISOR: f32 = F32_MAX_PRECISE as f32;
16pub const ALPHANUMERIC: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
17
18/// Trait for RNGs that provide cryptographically secure data.
19pub trait SecureGenerator: Generator {
20    /// Fills `dst` with random data, which is safe to be used in cryptographic contexts.
21    ///
22    /// # Examples
23    ///
24    /// ```
25    /// use ya_rand::*;
26    ///
27    /// let mut rng = new_rng_secure();
28    /// let mut data = [0; 1738];
29    /// rng.fill_bytes(&mut data);
30    /// assert!(data.into_iter().any(|v| v != 0));
31    /// ```
32    fn fill_bytes(&mut self, dst: &mut [u8]);
33
34    /// Fills `dst` with random data, which is safe to be used in cryptographic contexts.
35    ///
36    /// Differs from [`SecureGenerator::fill_bytes`] in that the underlying type of `dst`
37    /// doesn't need to be a specific type (see safety comment).
38    ///
39    /// # Examples
40    ///
41    /// ```
42    /// use ya_rand::*;
43    ///
44    /// #[repr(C)]
45    /// #[derive(Clone, Copy, Default, PartialEq, Eq)]
46    /// struct NotAByte {
47    ///     x: u16,
48    ///     y: u32,
49    ///     z: u64,
50    /// }
51    ///
52    /// let mut rng = new_rng_secure();
53    /// let zero_value = NotAByte::default();
54    /// let mut data = [zero_value; 69];
55    /// unsafe {
56    ///     rng.fill_raw(&mut data);
57    /// }
58    /// assert!(data.into_iter().any(|v| v != zero_value));
59    /// ```
60    ///
61    /// # Safety
62    ///
63    /// `T` must be valid as nothing more than a collection of bytes.
64    /// Integer types are the simplest example of this, but structs of integer
65    /// types generally should fall under the same umbrella.
66    #[inline]
67    unsafe fn fill_raw<T>(&mut self, dst: &mut [T]) {
68        // SAFETY: The caller has promised not to be a fucking dumbass.
69        let dst_as_bytes = unsafe { util::as_raw_bytes_mut(dst) };
70        self.fill_bytes(dst_as_bytes);
71    }
72
73    /// Generates a random `String` with length `len`, using the provided
74    /// `Encoder` to determine character set and minimum secure length. Because
75    /// character sets can only contain valid ascii values, the length of the created
76    /// `String` reprensents both the size of the `String` in bytes, and the
77    /// amount of characters it contains.
78    ///
79    /// Values of `len` which are less than what would be considered secure for the
80    /// `Encoder` being used will be silently promoted to the minimum secure length.
81    ///
82    /// All provided encoders are accessible via [`crate::encoding`].
83    /// Users wishing to implement their own encoding scheme must do so
84    /// through the [`Encoder`] trait.
85    ///
86    /// Originally inspired by golang's addition of [`rand.Text`] in release 1.24,
87    /// but altered to be encoding/length generic and unbiased for non-trivial bases.
88    ///
89    /// [`rand.Text`]:
90    /// https://cs.opensource.google/go/go/+/refs/tags/go1.24.0:src/crypto/rand/text.go
91    ///
92    /// # Examples
93    ///
94    /// ```
95    /// use ya_rand::*;
96    /// use ya_rand::encoding::Base16;
97    ///
98    /// const LEN: usize = 420;
99    /// let mut rng = new_rng_secure();
100    /// let hex_string = rng.text::<Base16>(LEN);
101    /// assert!(hex_string.len() == LEN);
102    /// assert!(hex_string.bytes().count() == LEN);
103    /// assert!(hex_string.chars().count() == LEN);
104    /// for c in hex_string.bytes() {
105    ///     assert!(
106    ///         (b'0' <= c && c <= b'9') ||
107    ///         (b'A' <= c && c <= b'F')
108    ///     );
109    /// }
110    /// ```
111    #[cfg(all(feature = "alloc", feature = "secure"))]
112    #[inline(never)]
113    fn text<E: Encoder>(&mut self, len: usize) -> String {
114        const BYTE_VALUES: usize = 1 << u8::BITS;
115        // Force all values of the vector to be initialized to a
116        // non-zero value. This guarantees all the allocated memory
117        // will be page-faulted and can massively improve performance
118        // when encoding long strings.
119        let mut bytes = vec![u8::MAX; len.max(E::MIN_LEN)];
120        if BYTE_VALUES % E::CHARSET.len() == 0 {
121            self.fill_bytes(&mut bytes);
122            // Directly map each random u8 to a character in the set.
123            // This approach is extremely efficient, but only produces
124            // unbiased random sequences when the length of the current
125            // `CHARSET` is divisible by the amount of possible u8 values,
126            // which is why we need a fallback approach.
127            for cur in &mut bytes {
128                let random_index = *cur as usize;
129                *cur = E::CHARSET[random_index % E::CHARSET.len()];
130            }
131        } else {
132            // Alternative approach that's potentially much slower,
133            // but always produces unbiased results.
134            // The unwrap gets optimized out since rust can see that
135            // `E::CHARSET` has a non-zero length.
136            bytes.fill_with(|| *self.choose(E::CHARSET).unwrap());
137        }
138        // SAFETY: All provided encoders only use ascii values, and
139        // custom `Encoder` implementations agree to do the same when
140        // implementing the trait.
141        unsafe { String::from_utf8_unchecked(bytes) }
142    }
143}
144
145/// Trait for RNGs that can be created from a user-provided seed.
146pub trait SeedableGenerator: Generator + Default {
147    /// Creates a generator from the output of an internal PRNG,
148    /// which is itself seeded from `seed`.
149    ///
150    /// As a rule: unless you are **absolutely certain** that you need to manually
151    /// seed a generator, you don't.
152    /// Instead, use [`crate::new_rng`] when you need to create a new instance.
153    ///
154    /// If you have a scenario where you really do need a set seed, prefer using the
155    /// `Default` implementation of the desired generator.
156    ///
157    /// # Examples
158    ///
159    /// ```
160    /// use ya_rand::*;
161    ///
162    /// let mut rng1 = ShiroRng::new_with_seed(0);
163    /// // Default initialization is just a shortcut for explicitly seeding with 0.
164    /// let mut rng2 = ShiroRng::default();
165    /// assert!(rng1 == rng2);
166    ///
167    /// let result1 = rng1.u64();
168    /// let result2 = rng2.u64();
169    /// assert!(result1 == result2);
170    /// ```
171    fn new_with_seed(seed: u64) -> Self;
172}
173
174/// Base trait that all RNGs must implement.
175pub trait Generator: Sized {
176    /// Creates a generator using randomness provided by the OS.
177    ///
178    /// Unlike [`Generator::new`], which will panic on failure, `try_new`
179    /// propagates the error-handling responsibility to the user. But the probability
180    /// of your operating systems RNG failing is absurdly low, and in the rare case that it
181    /// does fail, that's not really an issue most users are going to be able to address.
182    ///
183    /// Stick to using [`crate::new_rng`], unless you really need a generator of a
184    /// different type (you probably don't), then use `new` on your desired type.
185    fn try_new() -> Result<Self, getrandom::Error>;
186
187    /// Returns a uniformly distributed `u64` in the interval [0, 2<sup>64</sup>).
188    fn u64(&mut self) -> u64;
189
190    /// Creates a generator using randomness provided by the OS.
191    ///
192    /// It is recommended to use the top-level [`crate::new_rng`] instead
193    /// of calling this function on a specific generator type.
194    ///
195    /// # Examples
196    ///
197    /// ```
198    /// use ya_rand::*;
199    ///
200    /// // Recommended usage
201    /// let mut rng1 = new_rng();
202    /// // More explicit
203    /// let mut rng2 = ShiroRng::new();
204    /// // Even more explicit
205    /// let mut rng3 = Xoshiro256pp::new();
206    /// // Since these are all created using OS entropy, the odds of
207    /// // their initial states colliding is vanishingly small.
208    /// assert!(rng1 != rng2);
209    /// assert!(rng1 != rng3);
210    /// assert!(rng2 != rng3);
211    /// ```
212    ///
213    /// # Safety
214    ///
215    /// This function will panic if your OS rng fails to provide enough entropy.
216    /// But this is extremely unlikely, and unless you're working at the kernel level it's
217    /// not something you should ever be concerned with.
218    ///
219    /// Since Windows 10 this function is infallible, thanks to modern Windows versions adopting
220    /// a user-space cryptographic architecture that can't fail during runtime.
221    #[inline]
222    fn new() -> Self {
223        Self::try_new().expect("retrieving random data from the operating system should never fail")
224    }
225
226    /// Returns a uniformly distributed `usize` in the interval \[0, `usize::MAX`\].
227    #[inline]
228    fn usize(&mut self) -> usize {
229        self.bits(usize::BITS) as usize
230    }
231
232    /// Returns a uniformly distributed `u32` in the interval [0, 2<sup>32</sup>).
233    #[inline]
234    fn u32(&mut self) -> u32 {
235        self.bits(u32::BITS) as u32
236    }
237
238    /// Returns a uniformly distributed `u16` in the interval [0, 2<sup>16</sup>).
239    #[inline]
240    fn u16(&mut self) -> u16 {
241        self.bits(u16::BITS) as u16
242    }
243
244    /// Returns a uniformly distributed `u8` in the interval [0, 2<sup>8</sup>).
245    #[inline]
246    fn u8(&mut self) -> u8 {
247        self.bits(u8::BITS) as u8
248    }
249
250    /// Returns a uniformly distributed `u64` in the interval [0, 2<sup>`bit_count`</sup>).
251    ///
252    /// The value of `bit_count` is clamped to 64.
253    #[inline]
254    fn bits(&mut self, bit_count: u32) -> u64 {
255        self.u64() >> (u64::BITS - bit_count.min(u64::BITS))
256    }
257
258    /// A simple coinflip, returning a `bool` that has a 50% chance of being true.
259    ///
260    /// # Examples
261    ///
262    /// ```
263    /// use ya_rand::*;
264    ///
265    /// const ITERATIONS: u64 = 1 << 24;
266    /// let mut rng = new_rng();
267    /// let mut yes: u64 = 0;
268    /// let mut no: u64 = 0;
269    /// for _ in 0..ITERATIONS {
270    ///     if rng.bool() {
271    ///         yes += 1;
272    ///     } else {
273    ///         no += 1;
274    ///     }
275    /// }
276    /// // We expect the difference to be within ~5%.
277    /// let THRESHOLD: u64 = ITERATIONS / 20;
278    /// assert!(yes.abs_diff(no) <= THRESHOLD);
279    /// ```
280    #[inline]
281    fn bool(&mut self) -> bool {
282        // Compiles to a single "shr 63" instruction.
283        self.bits(1) == 1
284    }
285
286    /// Returns a uniformly distributed `u64` in the interval [0, `max`).
287    ///
288    /// Using [`Generator::bits`] when `max` happens to be a power of 2
289    /// will be significantly faster.
290    ///
291    /// # Examples
292    ///
293    /// ```
294    /// use ya_rand::*;
295    ///
296    /// let mut rng = new_rng();
297    /// // Special case: bound of 0 always returns 0.
298    /// assert!(rng.bound(0) == 0);
299    /// for i in 1..=2000 {
300    ///     for _ in 0..(i * 2) {
301    ///         assert!(rng.bound(i) < i);
302    ///     }
303    /// }
304    /// ```
305    #[inline]
306    fn bound(&mut self, max: u64) -> u64 {
307        // Lemire's nearly divisionless method: https://arxiv.org/abs/1805.10941.
308        let (mut high, mut low) = util::wide_mul(self.u64(), max);
309        match low < max {
310            false => {
311                // TODO: Use the `unlikely` hint when it get stabilized
312                // to indicate this branch is unlikely.
313            }
314            true => {
315                // The dreaded division.
316                let threshold = max.wrapping_neg() % max;
317                while low < threshold {
318                    (high, low) = util::wide_mul(self.u64(), max);
319                }
320            }
321        }
322        debug_assert!(
323            (max != 0 && high < max) || high == 0,
324            "BUG: assertion should be unreachable"
325        );
326        high
327    }
328
329    /// Returns a uniformly distributed `u64` in the interval \[0, `max`\].
330    ///
331    /// It is expected that `max` != `u64::MAX`.
332    ///
333    /// # Examples
334    ///
335    /// ```
336    /// use ya_rand::*;
337    ///
338    /// let mut rng = new_rng();
339    /// for i in 0..=2000 {
340    ///     for _ in 0..(i * 2) {
341    ///         assert!(rng.bound_inclusive(i) <= i);
342    ///     }
343    /// }
344    /// ```
345    #[inline]
346    fn bound_inclusive(&mut self, max: u64) -> u64 {
347        self.bound(max + 1)
348    }
349
350    /// Returns a uniformly distributed `i64` in the interval [`min`, `max`)
351    ///
352    /// It is expected that `min` < `max`.
353    #[inline]
354    fn range(&mut self, min: i64, max: i64) -> i64 {
355        let delta = max.abs_diff(min);
356        (self.bound(delta) as i64) + min
357    }
358
359    /// Returns a uniformly distributed `i64` in the interval \[`min`, `max`\]
360    ///
361    /// It is expected that `min` <= `max` and `max` != `i64::MAX`.
362    #[inline]
363    fn range_inclusive(&mut self, min: i64, max: i64) -> i64 {
364        self.range(min, max + 1)
365    }
366
367    /// Returns a uniformly distributed `f64` in the interval [0.0, 1.0).
368    #[inline]
369    fn f64(&mut self) -> f64 {
370        self.bits(F64_MANT) as f64 / F64_DIVISOR
371    }
372
373    /// Returns a uniformly distributed `f32` in the interval [0.0, 1.0).
374    #[inline]
375    fn f32(&mut self) -> f32 {
376        self.bits(F32_MANT) as f32 / F32_DIVISOR
377    }
378
379    /// Returns a uniformly distributed `f64` in the interval (0.0, 1.0].
380    #[inline]
381    fn f64_nonzero(&mut self) -> f64 {
382        // Interval of (0, 2^53]
383        let nonzero = self.bits(F64_MANT) + 1;
384        nonzero as f64 / F64_DIVISOR
385    }
386
387    /// Returns a uniformly distributed `f32` in the interval (0.0, 1.0].
388    #[inline]
389    fn f32_nonzero(&mut self) -> f32 {
390        // Interval of (0, 2^24]
391        let nonzero = self.bits(F32_MANT) + 1;
392        nonzero as f32 / F32_DIVISOR
393    }
394
395    /// Returns a uniformly distributed `f64` in the interval (-1.0, 1.0).
396    #[inline]
397    fn f64_wide(&mut self) -> f64 {
398        // This approach is faster than using Generator::range.
399        const BITS: u32 = F64_MANT + 1;
400        const OFFSET: i64 = F64_MAX_PRECISE as i64;
401        let mut x: i64;
402        loop {
403            // Start with an interval of [0, 2^54)
404            x = self.bits(BITS) as i64;
405            // Interval is now (0, 2^54)
406            if x != 0 {
407                break;
408            }
409        }
410        // Shift interval to (-2^53, 2^53)
411        x -= OFFSET;
412        x as f64 / F64_DIVISOR
413    }
414
415    /// Returns a uniformly distributed `f32` in the interval (-1.0, 1.0).
416    #[inline]
417    fn f32_wide(&mut self) -> f32 {
418        // This approach is faster than using Generator::range.
419        const BITS: u32 = F32_MANT + 1;
420        const OFFSET: i64 = F32_MAX_PRECISE as i64;
421        let mut x: i64;
422        loop {
423            // Start with an interval of [0, 2^25)
424            x = self.bits(BITS) as i64;
425            // Interval is now (0, 2^25)
426            if x != 0 {
427                break;
428            }
429        }
430        // Shift interval to (-2^24, 2^24)
431        x -= OFFSET;
432        x as f32 / F32_DIVISOR
433    }
434
435    /// Returns two indepedent and normally distributed `f64` values with
436    /// a `mean` of `0.0` and a `stddev` of `1.0`.
437    #[cfg(feature = "std")]
438    fn f64_normal(&mut self) -> (f64, f64) {
439        // Marsaglia polar method.
440        // TLDR: It projects a point within the unit
441        // circle onto the unit radius.
442        let mut x: f64;
443        let mut y: f64;
444        let mut s: f64;
445        loop {
446            x = self.f64_wide();
447            y = self.f64_wide();
448            s = (x * x) + (y * y);
449            // Reroll if `s` does not lie **within** the unit circle.
450            if s < 1.0 && s != 0.0 {
451                break;
452            }
453        }
454        let t = (2.0 * s.ln().abs() / s).sqrt();
455        (x * t, y * t)
456    }
457
458    /// Returns two indepedent and normally distributed `f64` values with
459    /// user-defined `mean` and `stddev`.
460    ///
461    /// It is expected that `stddev.abs()` != `0.0`.
462    #[cfg(feature = "std")]
463    #[inline]
464    fn f64_normal_distribution(&mut self, mean: f64, stddev: f64) -> (f64, f64) {
465        let (x, y) = self.f64_normal();
466        let x_adjusted = x.mul_add(stddev, mean);
467        let y_adjusted = y.mul_add(stddev, mean);
468        (x_adjusted, y_adjusted)
469    }
470
471    /// Returns an exponentially distributed `f64` with a `lambda` of `1.0`.
472    #[cfg(feature = "std")]
473    #[inline]
474    fn f64_exponential(&mut self) -> f64 {
475        // Using abs() instead of negating the result of ln() to
476        // eliminate the possibility of ever returning -0.0.
477        self.f64_nonzero().ln().abs()
478    }
479
480    /// Returns an exponentially distributed `f64` with user-defined `lambda`.
481    ///
482    /// It is expected that `lambda.abs()` != `0.0`.
483    #[cfg(feature = "std")]
484    #[inline]
485    fn f64_exponential_lambda(&mut self, lambda: f64) -> f64 {
486        self.f64_exponential() / lambda
487    }
488
489    /// Returns a randomly chosen item from the iterator of `collection`.
490    ///
491    /// Returns `None` when the length of the iterator is zero.
492    ///
493    /// # Examples
494    ///
495    /// ```
496    /// use ya_rand::*;
497    ///
498    /// const SIZE: usize = 1738;
499    /// let mut rng = new_rng();
500    /// let mut v = [0; SIZE];
501    /// for i in 0..SIZE {
502    ///     v[i] = i;
503    /// }
504    /// let (top, bottom) = v.split_at(v.len() / 2);
505    ///
506    /// // Sanity check.
507    /// let random_item = rng.choose(&v).expect("vector `v` is not empty");
508    /// assert!(v.contains(random_item) == true);
509    ///
510    /// // Choose `random_item` from the top half of the array.
511    /// let random_item = rng.choose(top).expect("still not empty");
512    /// assert!(top.contains(random_item) == true);
513    ///
514    /// // We're looking in the bottom half so we won't find the
515    /// // `random_item` from the top half.
516    /// assert!(bottom.contains(random_item) == false);
517    /// ```
518    #[inline]
519    fn choose<C>(&mut self, collection: C) -> Option<C::Item>
520    where
521        C: IntoIterator,
522        C::IntoIter: ExactSizeIterator,
523    {
524        let mut iter = collection.into_iter();
525        let len = iter.len();
526        match len != 0 {
527            true => Some({
528                let idx = self.bound(len as u64) as usize;
529                // SAFETY: Since `bound` always returns a value less than
530                // it's input, `nth` will never return `None`.
531                unsafe { iter.nth(idx).unwrap_unchecked() }
532            }),
533            false => None,
534        }
535    }
536
537    /// Returns a randomly selected ASCII character from the pool of:
538    ///
539    /// `'A'..='Z'`, and`'a'..='z'`
540    #[inline]
541    fn ascii_alphabetic(&mut self) -> char {
542        *self.choose(&ALPHANUMERIC[..52]).unwrap() as char
543    }
544
545    /// Returns a randomly selected ASCII character from the pool of:
546    ///
547    /// `'A'..='Z'`
548    #[inline]
549    fn ascii_uppercase(&mut self) -> char {
550        *self.choose(&ALPHANUMERIC[..26]).unwrap() as char
551    }
552
553    /// Returns a randomly selected ASCII character from the pool of:
554    ///
555    /// `'a'..='z'`
556    #[inline]
557    fn ascii_lowercase(&mut self) -> char {
558        *self.choose(&ALPHANUMERIC[26..52]).unwrap() as char
559    }
560
561    /// Returns a randomly selected ASCII character from the pool of:
562    ///
563    /// `'A'..='Z'`, `'a'..='z'`, and `'0'..='9'`
564    #[inline]
565    fn ascii_alphanumeric(&mut self) -> char {
566        *self.choose(&ALPHANUMERIC[..]).unwrap() as char
567    }
568
569    /// Returns a randomly selected ASCII character from the pool of:
570    ///
571    /// `'0'..='9'`
572    #[inline]
573    fn ascii_digit(&mut self) -> char {
574        *self.choose(&ALPHANUMERIC[52..]).unwrap() as char
575    }
576
577    /// Performs a Fisher-Yates shuffle on the contents of `slice`.
578    ///
579    /// This implementation is the modern variant introduced by
580    /// Richard Durstenfeld. It is in-place and O(n).
581    ///
582    /// # Examples
583    ///
584    /// ```
585    /// use ya_rand::*;
586    ///
587    /// let mut rng = new_rng();
588    /// let mut data = [0; 1738];
589    /// for i in 0..data.len() {
590    ///     data[i] = i;
591    /// }
592    /// assert!(data.is_sorted() == true);
593    ///
594    /// rng.shuffle(&mut data);
595    /// assert!(data.is_sorted() == false);
596    /// ```
597    #[inline(never)]
598    fn shuffle<T>(&mut self, slice: &mut [T]) {
599        let slice_ptr = slice.as_mut_ptr();
600        for i in (1..slice.len()).rev() {
601            let j = self.bound_inclusive(i as u64) as usize;
602            // SAFETY: Index 'i' will always be in bounds because it's
603            // bounded by slice length; index 'j' will always be
604            // in bounds because it's bounded by 'i'.
605            unsafe {
606                ptr::swap(slice_ptr.add(i), slice_ptr.add(j));
607            }
608        }
609    }
610
611    /// Clones `slice` into a new `Vec`, calls [`Generator::shuffle`]
612    /// on it, and returns the result.
613    #[cfg(all(feature = "alloc", feature = "secure"))]
614    #[inline]
615    fn shuffle_cloned<T: Clone>(&mut self, slice: &[T]) -> Vec<T> {
616        let mut v = slice.to_vec();
617        self.shuffle(&mut v);
618        v
619    }
620}