1 //! A simple and fast random number generator.
2 //!
3 //! The implementation uses [Wyrand](https://github.com/wangyi-fudan/wyhash), a simple and fast
4 //! generator but **not** cryptographically secure.
5 //!
6 //! # Examples
7 //!
8 //! Flip a coin:
9 //!
10 //! ```
11 //! if fastrand::bool() {
12 //!     println!("heads");
13 //! } else {
14 //!     println!("tails");
15 //! }
16 //! ```
17 //!
18 //! Generate a random `i32`:
19 //!
20 //! ```
21 //! let num = fastrand::i32(..);
22 //! ```
23 //!
24 //! Choose a random element in an array:
25 //!
26 //! ```
27 //! let v = vec![1, 2, 3, 4, 5];
28 //! let i = fastrand::usize(..v.len());
29 //! let elem = v[i];
30 //! ```
31 //!
32 //! Sample values from an array with `O(n)` complexity (`n` is the length of array):
33 //!
34 //! ```
35 //! fastrand::choose_multiple(vec![1, 4, 5].iter(), 2);
36 //! fastrand::choose_multiple(0..20, 12);
37 //! ```
38 //!
39 //!
40 //! Shuffle an array:
41 //!
42 //! ```
43 //! let mut v = vec![1, 2, 3, 4, 5];
44 //! fastrand::shuffle(&mut v);
45 //! ```
46 //!
47 //! Generate a random [`Vec`] or [`String`]:
48 //!
49 //! ```
50 //! use std::iter::repeat_with;
51 //!
52 //! let v: Vec<i32> = repeat_with(|| fastrand::i32(..)).take(10).collect();
53 //! let s: String = repeat_with(fastrand::alphanumeric).take(10).collect();
54 //! ```
55 //!
56 //! To get reproducible results on every run, initialize the generator with a seed:
57 //!
58 //! ```
59 //! // Pick an arbitrary number as seed.
60 //! fastrand::seed(7);
61 //!
62 //! // Now this prints the same number on every run:
63 //! println!("{}", fastrand::u32(..));
64 //! ```
65 //!
66 //! To be more efficient, create a new [`Rng`] instance instead of using the thread-local
67 //! generator:
68 //!
69 //! ```
70 //! use std::iter::repeat_with;
71 //!
72 //! let mut rng = fastrand::Rng::new();
73 //! let mut bytes: Vec<u8> = repeat_with(|| rng.u8(..)).take(10_000).collect();
74 //! ```
75 //!
76 //! This crate aims to expose a core set of useful randomness primitives. For more niche algorithms,
77 //! consider using the [`fastrand-contrib`] crate alongside this one.
78 //!
79 //! # Features
80 //!
81 //! - `std` (enabled by default): Enables the `std` library. This is required for the global
82 //!   generator and global entropy. Without this feature, [`Rng`] can only be instantiated using
83 //!   the [`with_seed`](Rng::with_seed) method.
84 //! - `js`: Assumes that WebAssembly targets are being run in a JavaScript environment. See the
85 //!   [WebAssembly Notes](#webassembly-notes) section for more information.
86 //!
87 //! # WebAssembly Notes
88 //!
89 //! For non-WASI WASM targets, there is additional sublety to consider when utilizing the global RNG.
90 //! By default, `std` targets will use entropy sources in the standard library to seed the global RNG.
91 //! However, these sources are not available by default on WASM targets outside of WASI.
92 //!
93 //! If the `js` feature is enabled, this crate will assume that it is running in a JavaScript
94 //! environment. At this point, the [`getrandom`] crate will be used in order to access the available
95 //! entropy sources and seed the global RNG. If the `js` feature is not enabled, the global RNG will
96 //! use a predefined seed.
97 //!
98 //! [`fastrand-contrib`]: https://crates.io/crates/fastrand-contrib
99 //! [`getrandom`]: https://crates.io/crates/getrandom
100 
101 #![no_std]
102 #![cfg_attr(docsrs, feature(doc_cfg))]
103 #![forbid(unsafe_code)]
104 #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
105 #![doc(
106     html_favicon_url = "https://raw.githubusercontent.com/smol-rs/smol/master/assets/images/logo_fullsize_transparent.png"
107 )]
108 #![doc(
109     html_logo_url = "https://raw.githubusercontent.com/smol-rs/smol/master/assets/images/logo_fullsize_transparent.png"
110 )]
111 
112 #[cfg(feature = "alloc")]
113 extern crate alloc;
114 #[cfg(feature = "std")]
115 extern crate std;
116 
117 use core::convert::{TryFrom, TryInto};
118 use core::ops::{Bound, RangeBounds};
119 
120 #[cfg(feature = "alloc")]
121 use alloc::vec::Vec;
122 
123 #[cfg(feature = "std")]
124 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
125 mod global_rng;
126 
127 #[cfg(feature = "std")]
128 pub use global_rng::*;
129 
130 /// A random number generator.
131 #[derive(Debug, PartialEq, Eq)]
132 pub struct Rng(u64);
133 
134 impl Clone for Rng {
135     /// Clones the generator by creating a new generator with the same seed.
clone(&self) -> Rng136     fn clone(&self) -> Rng {
137         Rng::with_seed(self.0)
138     }
139 }
140 
141 impl Rng {
142     /// Generates a random `u32`.
143     #[inline]
gen_u32(&mut self) -> u32144     fn gen_u32(&mut self) -> u32 {
145         self.gen_u64() as u32
146     }
147 
148     /// Generates a random `u64`.
149     #[inline]
gen_u64(&mut self) -> u64150     fn gen_u64(&mut self) -> u64 {
151         let s = self.0.wrapping_add(0xA0761D6478BD642F);
152         self.0 = s;
153         let t = u128::from(s) * u128::from(s ^ 0xE7037ED1A0B428DB);
154         (t as u64) ^ (t >> 64) as u64
155     }
156 
157     /// Generates a random `u128`.
158     #[inline]
gen_u128(&mut self) -> u128159     fn gen_u128(&mut self) -> u128 {
160         (u128::from(self.gen_u64()) << 64) | u128::from(self.gen_u64())
161     }
162 
163     /// Generates a random `u32` in `0..n`.
164     #[inline]
gen_mod_u32(&mut self, n: u32) -> u32165     fn gen_mod_u32(&mut self, n: u32) -> u32 {
166         // Adapted from: https://lemire.me/blog/2016/06/30/fast-random-shuffling/
167         let mut r = self.gen_u32();
168         let mut hi = mul_high_u32(r, n);
169         let mut lo = r.wrapping_mul(n);
170         if lo < n {
171             let t = n.wrapping_neg() % n;
172             while lo < t {
173                 r = self.gen_u32();
174                 hi = mul_high_u32(r, n);
175                 lo = r.wrapping_mul(n);
176             }
177         }
178         hi
179     }
180 
181     /// Generates a random `u64` in `0..n`.
182     #[inline]
gen_mod_u64(&mut self, n: u64) -> u64183     fn gen_mod_u64(&mut self, n: u64) -> u64 {
184         // Adapted from: https://lemire.me/blog/2016/06/30/fast-random-shuffling/
185         let mut r = self.gen_u64();
186         let mut hi = mul_high_u64(r, n);
187         let mut lo = r.wrapping_mul(n);
188         if lo < n {
189             let t = n.wrapping_neg() % n;
190             while lo < t {
191                 r = self.gen_u64();
192                 hi = mul_high_u64(r, n);
193                 lo = r.wrapping_mul(n);
194             }
195         }
196         hi
197     }
198 
199     /// Generates a random `u128` in `0..n`.
200     #[inline]
gen_mod_u128(&mut self, n: u128) -> u128201     fn gen_mod_u128(&mut self, n: u128) -> u128 {
202         // Adapted from: https://lemire.me/blog/2016/06/30/fast-random-shuffling/
203         let mut r = self.gen_u128();
204         let mut hi = mul_high_u128(r, n);
205         let mut lo = r.wrapping_mul(n);
206         if lo < n {
207             let t = n.wrapping_neg() % n;
208             while lo < t {
209                 r = self.gen_u128();
210                 hi = mul_high_u128(r, n);
211                 lo = r.wrapping_mul(n);
212             }
213         }
214         hi
215     }
216 }
217 
218 /// Computes `(a * b) >> 32`.
219 #[inline]
mul_high_u32(a: u32, b: u32) -> u32220 fn mul_high_u32(a: u32, b: u32) -> u32 {
221     (((a as u64) * (b as u64)) >> 32) as u32
222 }
223 
224 /// Computes `(a * b) >> 64`.
225 #[inline]
mul_high_u64(a: u64, b: u64) -> u64226 fn mul_high_u64(a: u64, b: u64) -> u64 {
227     (((a as u128) * (b as u128)) >> 64) as u64
228 }
229 
230 /// Computes `(a * b) >> 128`.
231 #[inline]
mul_high_u128(a: u128, b: u128) -> u128232 fn mul_high_u128(a: u128, b: u128) -> u128 {
233     // Adapted from: https://stackoverflow.com/a/28904636
234     let a_lo = a as u64 as u128;
235     let a_hi = (a >> 64) as u64 as u128;
236     let b_lo = b as u64 as u128;
237     let b_hi = (b >> 64) as u64 as u128;
238     let carry = (a_lo * b_lo) >> 64;
239     let carry = ((a_hi * b_lo) as u64 as u128 + (a_lo * b_hi) as u64 as u128 + carry) >> 64;
240     a_hi * b_hi + ((a_hi * b_lo) >> 64) + ((a_lo * b_hi) >> 64) + carry
241 }
242 
243 macro_rules! rng_integer {
244     ($t:tt, $unsigned_t:tt, $gen:tt, $mod:tt, $doc:tt) => {
245         #[doc = $doc]
246         ///
247         /// Panics if the range is empty.
248         #[inline]
249         pub fn $t(&mut self, range: impl RangeBounds<$t>) -> $t {
250             let panic_empty_range = || {
251                 panic!(
252                     "empty range: {:?}..{:?}",
253                     range.start_bound(),
254                     range.end_bound()
255                 )
256             };
257 
258             let low = match range.start_bound() {
259                 Bound::Unbounded => core::$t::MIN,
260                 Bound::Included(&x) => x,
261                 Bound::Excluded(&x) => x.checked_add(1).unwrap_or_else(panic_empty_range),
262             };
263 
264             let high = match range.end_bound() {
265                 Bound::Unbounded => core::$t::MAX,
266                 Bound::Included(&x) => x,
267                 Bound::Excluded(&x) => x.checked_sub(1).unwrap_or_else(panic_empty_range),
268             };
269 
270             if low > high {
271                 panic_empty_range();
272             }
273 
274             if low == core::$t::MIN && high == core::$t::MAX {
275                 self.$gen() as $t
276             } else {
277                 let len = high.wrapping_sub(low).wrapping_add(1);
278                 low.wrapping_add(self.$mod(len as $unsigned_t as _) as $t)
279             }
280         }
281     };
282 }
283 
284 impl Rng {
285     /// Creates a new random number generator with the initial seed.
286     #[inline]
287     #[must_use = "this creates a new instance of `Rng`; if you want to initialize the thread-local generator, use `fastrand::seed()` instead"]
with_seed(seed: u64) -> Self288     pub fn with_seed(seed: u64) -> Self {
289         Rng(seed)
290     }
291 
292     /// Clones the generator by deterministically deriving a new generator based on the initial
293     /// seed.
294     ///
295     /// This function can be used to create a new generator that is a "spinoff" of the old
296     /// generator. The new generator will not produce the same sequence of values as the
297     /// old generator.
298     ///
299     /// # Example
300     ///
301     /// ```
302     /// // Seed two generators equally, and clone both of them.
303     /// let mut base1 = fastrand::Rng::with_seed(0x4d595df4d0f33173);
304     /// base1.bool(); // Use the generator once.
305     ///
306     /// let mut base2 = fastrand::Rng::with_seed(0x4d595df4d0f33173);
307     /// base2.bool(); // Use the generator once.
308     ///
309     /// let mut rng1 = base1.fork();
310     /// let mut rng2 = base2.fork();
311     ///
312     /// println!("rng1 returns {}", rng1.u32(..));
313     /// println!("rng2 returns {}", rng2.u32(..));
314     /// ```
315     #[inline]
316     #[must_use = "this creates a new instance of `Rng`"]
fork(&mut self) -> Self317     pub fn fork(&mut self) -> Self {
318         Rng::with_seed(self.gen_u64())
319     }
320 
321     /// Generates a random `char` in ranges a-z and A-Z.
322     #[inline]
alphabetic(&mut self) -> char323     pub fn alphabetic(&mut self) -> char {
324         const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
325         *self.choice(CHARS).unwrap() as char
326     }
327 
328     /// Generates a random `char` in ranges a-z, A-Z and 0-9.
329     #[inline]
alphanumeric(&mut self) -> char330     pub fn alphanumeric(&mut self) -> char {
331         const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
332         *self.choice(CHARS).unwrap() as char
333     }
334 
335     /// Generates a random `bool`.
336     #[inline]
bool(&mut self) -> bool337     pub fn bool(&mut self) -> bool {
338         self.u8(..) % 2 == 0
339     }
340 
341     /// Generates a random digit in the given `base`.
342     ///
343     /// Digits are represented by `char`s in ranges 0-9 and a-z.
344     ///
345     /// Panics if the base is zero or greater than 36.
346     #[inline]
digit(&mut self, base: u32) -> char347     pub fn digit(&mut self, base: u32) -> char {
348         if base == 0 {
349             panic!("base cannot be zero");
350         }
351         if base > 36 {
352             panic!("base cannot be larger than 36");
353         }
354         let num = self.u8(..base as u8);
355         if num < 10 {
356             (b'0' + num) as char
357         } else {
358             (b'a' + num - 10) as char
359         }
360     }
361 
362     /// Generates a random `f32` in range `0..1`.
f32(&mut self) -> f32363     pub fn f32(&mut self) -> f32 {
364         let b = 32;
365         let f = core::f32::MANTISSA_DIGITS - 1;
366         f32::from_bits((1 << (b - 2)) - (1 << f) + (self.u32(..) >> (b - f))) - 1.0
367     }
368 
369     /// Generates a random `f64` in range `0..1`.
f64(&mut self) -> f64370     pub fn f64(&mut self) -> f64 {
371         let b = 64;
372         let f = core::f64::MANTISSA_DIGITS - 1;
373         f64::from_bits((1 << (b - 2)) - (1 << f) + (self.u64(..) >> (b - f))) - 1.0
374     }
375 
376     /// Collects `amount` values at random from the iterator into a vector.
377     ///
378     /// The length of the returned vector equals `amount` unless the iterator
379     /// contains insufficient elements, in which case it equals the number of
380     /// elements available.
381     ///
382     /// Complexity is `O(n)` where `n` is the length of the iterator.
383     #[cfg(feature = "alloc")]
384     #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
choose_multiple<T: Iterator>(&mut self, mut source: T, amount: usize) -> Vec<T::Item>385     pub fn choose_multiple<T: Iterator>(&mut self, mut source: T, amount: usize) -> Vec<T::Item> {
386         // Adapted from: https://docs.rs/rand/latest/rand/seq/trait.IteratorRandom.html#method.choose_multiple
387         let mut reservoir = Vec::with_capacity(amount);
388 
389         reservoir.extend(source.by_ref().take(amount));
390 
391         // Continue unless the iterator was exhausted
392         //
393         // note: this prevents iterators that "restart" from causing problems.
394         // If the iterator stops once, then so do we.
395         if reservoir.len() == amount {
396             for (i, elem) in source.enumerate() {
397                 let end = i + 1 + amount;
398                 let k = self.usize(0..end);
399                 if let Some(slot) = reservoir.get_mut(k) {
400                     *slot = elem;
401                 }
402             }
403         } else {
404             // If less than one third of the `Vec` was used, reallocate
405             // so that the unused space is not wasted. There is a corner
406             // case where `amount` was much less than `self.len()`.
407             if reservoir.capacity() > 3 * reservoir.len() {
408                 reservoir.shrink_to_fit();
409             }
410         }
411         reservoir
412     }
413 
414     rng_integer!(
415         i8,
416         u8,
417         gen_u32,
418         gen_mod_u32,
419         "Generates a random `i8` in the given range."
420     );
421 
422     rng_integer!(
423         i16,
424         u16,
425         gen_u32,
426         gen_mod_u32,
427         "Generates a random `i16` in the given range."
428     );
429 
430     rng_integer!(
431         i32,
432         u32,
433         gen_u32,
434         gen_mod_u32,
435         "Generates a random `i32` in the given range."
436     );
437 
438     rng_integer!(
439         i64,
440         u64,
441         gen_u64,
442         gen_mod_u64,
443         "Generates a random `i64` in the given range."
444     );
445 
446     rng_integer!(
447         i128,
448         u128,
449         gen_u128,
450         gen_mod_u128,
451         "Generates a random `i128` in the given range."
452     );
453 
454     #[cfg(target_pointer_width = "16")]
455     rng_integer!(
456         isize,
457         usize,
458         gen_u32,
459         gen_mod_u32,
460         "Generates a random `isize` in the given range."
461     );
462     #[cfg(target_pointer_width = "32")]
463     rng_integer!(
464         isize,
465         usize,
466         gen_u32,
467         gen_mod_u32,
468         "Generates a random `isize` in the given range."
469     );
470     #[cfg(target_pointer_width = "64")]
471     rng_integer!(
472         isize,
473         usize,
474         gen_u64,
475         gen_mod_u64,
476         "Generates a random `isize` in the given range."
477     );
478 
479     /// Generates a random `char` in range a-z.
480     #[inline]
lowercase(&mut self) -> char481     pub fn lowercase(&mut self) -> char {
482         const CHARS: &[u8] = b"abcdefghijklmnopqrstuvwxyz";
483         *self.choice(CHARS).unwrap() as char
484     }
485 
486     /// Initializes this generator with the given seed.
487     #[inline]
seed(&mut self, seed: u64)488     pub fn seed(&mut self, seed: u64) {
489         self.0 = seed;
490     }
491 
492     /// Gives back **current** seed that is being held by this generator.
493     #[inline]
get_seed(&self) -> u64494     pub fn get_seed(&self) -> u64 {
495         self.0
496     }
497 
498     /// Choose an item from an iterator at random.
499     ///
500     /// This function may have an unexpected result if the `len()` property of the
501     /// iterator does not match the actual number of items in the iterator. If
502     /// the iterator is empty, this returns `None`.
503     #[inline]
choice<I>(&mut self, iter: I) -> Option<I::Item> where I: IntoIterator, I::IntoIter: ExactSizeIterator,504     pub fn choice<I>(&mut self, iter: I) -> Option<I::Item>
505     where
506         I: IntoIterator,
507         I::IntoIter: ExactSizeIterator,
508     {
509         let mut iter = iter.into_iter();
510 
511         // Get the item at a random index.
512         let len = iter.len();
513         if len == 0 {
514             return None;
515         }
516         let index = self.usize(0..len);
517 
518         iter.nth(index)
519     }
520 
521     /// Shuffles a slice randomly.
522     #[inline]
shuffle<T>(&mut self, slice: &mut [T])523     pub fn shuffle<T>(&mut self, slice: &mut [T]) {
524         for i in 1..slice.len() {
525             slice.swap(i, self.usize(..=i));
526         }
527     }
528 
529     /// Fill a byte slice with random data.
530     #[inline]
fill(&mut self, slice: &mut [u8])531     pub fn fill(&mut self, slice: &mut [u8]) {
532         // We fill the slice by chunks of 8 bytes, or one block of
533         // WyRand output per new state.
534         let mut chunks = slice.chunks_exact_mut(core::mem::size_of::<u64>());
535         for chunk in chunks.by_ref() {
536             let n = self.gen_u64().to_ne_bytes();
537             // Safe because the chunks are always 8 bytes exactly.
538             chunk.copy_from_slice(&n);
539         }
540 
541         let remainder = chunks.into_remainder();
542 
543         // Any remainder will always be less than 8 bytes.
544         if !remainder.is_empty() {
545             // Generate one last block of 8 bytes of entropy
546             let n = self.gen_u64().to_ne_bytes();
547 
548             // Use the remaining length to copy from block
549             remainder.copy_from_slice(&n[..remainder.len()]);
550         }
551     }
552 
553     rng_integer!(
554         u8,
555         u8,
556         gen_u32,
557         gen_mod_u32,
558         "Generates a random `u8` in the given range."
559     );
560 
561     rng_integer!(
562         u16,
563         u16,
564         gen_u32,
565         gen_mod_u32,
566         "Generates a random `u16` in the given range."
567     );
568 
569     rng_integer!(
570         u32,
571         u32,
572         gen_u32,
573         gen_mod_u32,
574         "Generates a random `u32` in the given range."
575     );
576 
577     rng_integer!(
578         u64,
579         u64,
580         gen_u64,
581         gen_mod_u64,
582         "Generates a random `u64` in the given range."
583     );
584 
585     rng_integer!(
586         u128,
587         u128,
588         gen_u128,
589         gen_mod_u128,
590         "Generates a random `u128` in the given range."
591     );
592 
593     #[cfg(target_pointer_width = "16")]
594     rng_integer!(
595         usize,
596         usize,
597         gen_u32,
598         gen_mod_u32,
599         "Generates a random `usize` in the given range."
600     );
601     #[cfg(target_pointer_width = "32")]
602     rng_integer!(
603         usize,
604         usize,
605         gen_u32,
606         gen_mod_u32,
607         "Generates a random `usize` in the given range."
608     );
609     #[cfg(target_pointer_width = "64")]
610     rng_integer!(
611         usize,
612         usize,
613         gen_u64,
614         gen_mod_u64,
615         "Generates a random `usize` in the given range."
616     );
617     #[cfg(target_pointer_width = "128")]
618     rng_integer!(
619         usize,
620         usize,
621         gen_u128,
622         gen_mod_u128,
623         "Generates a random `usize` in the given range."
624     );
625 
626     /// Generates a random `char` in range A-Z.
627     #[inline]
uppercase(&mut self) -> char628     pub fn uppercase(&mut self) -> char {
629         const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
630         *self.choice(CHARS).unwrap() as char
631     }
632 
633     /// Generates a random `char` in the given range.
634     ///
635     /// Panics if the range is empty.
636     #[inline]
char(&mut self, range: impl RangeBounds<char>) -> char637     pub fn char(&mut self, range: impl RangeBounds<char>) -> char {
638         let panic_empty_range = || {
639             panic!(
640                 "empty range: {:?}..{:?}",
641                 range.start_bound(),
642                 range.end_bound()
643             )
644         };
645 
646         let surrogate_start = 0xd800u32;
647         let surrogate_len = 0x800u32;
648 
649         let low = match range.start_bound() {
650             Bound::Unbounded => 0u8 as char,
651             Bound::Included(&x) => x,
652             Bound::Excluded(&x) => {
653                 let scalar = if x as u32 == surrogate_start - 1 {
654                     surrogate_start + surrogate_len
655                 } else {
656                     x as u32 + 1
657                 };
658                 char::try_from(scalar).unwrap_or_else(|_| panic_empty_range())
659             }
660         };
661 
662         let high = match range.end_bound() {
663             Bound::Unbounded => core::char::MAX,
664             Bound::Included(&x) => x,
665             Bound::Excluded(&x) => {
666                 let scalar = if x as u32 == surrogate_start + surrogate_len {
667                     surrogate_start - 1
668                 } else {
669                     (x as u32).wrapping_sub(1)
670                 };
671                 char::try_from(scalar).unwrap_or_else(|_| panic_empty_range())
672             }
673         };
674 
675         if low > high {
676             panic_empty_range();
677         }
678 
679         let gap = if (low as u32) < surrogate_start && (high as u32) >= surrogate_start {
680             surrogate_len
681         } else {
682             0
683         };
684         let range = high as u32 - low as u32 - gap;
685         let mut val = self.u32(0..=range) + low as u32;
686         if val >= surrogate_start {
687             val += gap;
688         }
689         val.try_into().unwrap()
690     }
691 }
692