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}