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