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