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}