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