fastrand/
lib.rs

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([1, 4, 5], 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`](alloc::string::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 subtlety 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")]
113extern crate alloc;
114#[cfg(feature = "std")]
115extern crate std;
116
117use core::convert::{TryFrom, TryInto};
118use core::ops::{Bound, RangeBounds};
119
120#[cfg(feature = "alloc")]
121use alloc::vec::Vec;
122
123#[cfg(feature = "std")]
124mod global_rng;
125
126#[cfg(feature = "std")]
127pub use global_rng::*;
128
129/// A random number generator.
130#[derive(Debug, PartialEq, Eq)]
131pub struct Rng(u64);
132
133impl Clone for Rng {
134    /// Clones the generator by creating a new generator with the same seed.
135    fn clone(&self) -> Rng {
136        Rng::with_seed(self.0)
137    }
138}
139
140impl Rng {
141    /// Generates a random `u32`.
142    #[inline]
143    fn gen_u32(&mut self) -> u32 {
144        self.gen_u64() as u32
145    }
146
147    /// Generates a random `u64`.
148    #[inline]
149    fn gen_u64(&mut self) -> u64 {
150        // Constants for WyRand taken from: https://github.com/wangyi-fudan/wyhash/blob/master/wyhash.h#L151
151        // Updated for the final v4.2 implementation with improved constants for better entropy output.
152        const WY_CONST_0: u64 = 0x2d35_8dcc_aa6c_78a5;
153        const WY_CONST_1: u64 = 0x8bb8_4b93_962e_acc9;
154
155        let s = self.0.wrapping_add(WY_CONST_0);
156        self.0 = s;
157        let t = u128::from(s) * u128::from(s ^ WY_CONST_1);
158        (t as u64) ^ (t >> 64) as u64
159    }
160
161    /// Generates a random `u128`.
162    #[inline]
163    fn gen_u128(&mut self) -> u128 {
164        (u128::from(self.gen_u64()) << 64) | u128::from(self.gen_u64())
165    }
166
167    /// Generates a random `u32` in `0..n`.
168    #[inline]
169    fn gen_mod_u32(&mut self, n: u32) -> u32 {
170        // Adapted from: https://lemire.me/blog/2016/06/30/fast-random-shuffling/
171        let mut r = self.gen_u32();
172        let mut hi = mul_high_u32(r, n);
173        let mut lo = r.wrapping_mul(n);
174        if lo < n {
175            let t = n.wrapping_neg() % n;
176            while lo < t {
177                r = self.gen_u32();
178                hi = mul_high_u32(r, n);
179                lo = r.wrapping_mul(n);
180            }
181        }
182        hi
183    }
184
185    /// Generates a random `u64` in `0..n`.
186    #[inline]
187    fn gen_mod_u64(&mut self, n: u64) -> u64 {
188        // Adapted from: https://lemire.me/blog/2016/06/30/fast-random-shuffling/
189        let mut r = self.gen_u64();
190        let mut hi = mul_high_u64(r, n);
191        let mut lo = r.wrapping_mul(n);
192        if lo < n {
193            let t = n.wrapping_neg() % n;
194            while lo < t {
195                r = self.gen_u64();
196                hi = mul_high_u64(r, n);
197                lo = r.wrapping_mul(n);
198            }
199        }
200        hi
201    }
202
203    /// Generates a random `u128` in `0..n`.
204    #[inline]
205    fn gen_mod_u128(&mut self, n: u128) -> u128 {
206        // Adapted from: https://lemire.me/blog/2016/06/30/fast-random-shuffling/
207        let mut r = self.gen_u128();
208        let mut hi = mul_high_u128(r, n);
209        let mut lo = r.wrapping_mul(n);
210        if lo < n {
211            let t = n.wrapping_neg() % n;
212            while lo < t {
213                r = self.gen_u128();
214                hi = mul_high_u128(r, n);
215                lo = r.wrapping_mul(n);
216            }
217        }
218        hi
219    }
220}
221
222/// Computes `(a * b) >> 32`.
223#[inline]
224fn mul_high_u32(a: u32, b: u32) -> u32 {
225    (((a as u64) * (b as u64)) >> 32) as u32
226}
227
228/// Computes `(a * b) >> 64`.
229#[inline]
230fn mul_high_u64(a: u64, b: u64) -> u64 {
231    (((a as u128) * (b as u128)) >> 64) as u64
232}
233
234/// Computes `(a * b) >> 128`.
235#[inline]
236fn mul_high_u128(a: u128, b: u128) -> u128 {
237    // Adapted from: https://stackoverflow.com/a/28904636
238    let a_lo = a as u64 as u128;
239    let a_hi = (a >> 64) as u64 as u128;
240    let b_lo = b as u64 as u128;
241    let b_hi = (b >> 64) as u64 as u128;
242    let carry = (a_lo * b_lo) >> 64;
243    let carry = ((a_hi * b_lo) as u64 as u128 + (a_lo * b_hi) as u64 as u128 + carry) >> 64;
244    a_hi * b_hi + ((a_hi * b_lo) >> 64) + ((a_lo * b_hi) >> 64) + carry
245}
246
247macro_rules! rng_integer {
248    ($t:tt, $unsigned_t:tt, $gen:tt, $mod:tt, $doc:tt) => {
249        #[doc = $doc]
250        ///
251        /// Panics if the range is empty.
252        #[inline]
253        pub fn $t(&mut self, range: impl RangeBounds<$t>) -> $t {
254            let panic_empty_range = || {
255                panic!(
256                    "empty range: {:?}..{:?}",
257                    range.start_bound(),
258                    range.end_bound()
259                )
260            };
261
262            let low = match range.start_bound() {
263                Bound::Unbounded => $t::MIN,
264                Bound::Included(&x) => x,
265                Bound::Excluded(&x) => x.checked_add(1).unwrap_or_else(panic_empty_range),
266            };
267
268            let high = match range.end_bound() {
269                Bound::Unbounded => $t::MAX,
270                Bound::Included(&x) => x,
271                Bound::Excluded(&x) => x.checked_sub(1).unwrap_or_else(panic_empty_range),
272            };
273
274            if low > high {
275                panic_empty_range();
276            }
277
278            if low == $t::MIN && high == $t::MAX {
279                self.$gen() as $t
280            } else {
281                let len = high.wrapping_sub(low).wrapping_add(1);
282                low.wrapping_add(self.$mod(len as $unsigned_t as _) as $t)
283            }
284        }
285    };
286}
287
288impl Rng {
289    /// Creates a new random number generator with the initial seed.
290    #[inline]
291    #[must_use = "this creates a new instance of `Rng`; if you want to initialize the thread-local generator, use `fastrand::seed()` instead"]
292    pub const fn with_seed(seed: u64) -> Self {
293        Rng(seed)
294    }
295
296    /// Clones the generator by deterministically deriving a new generator based on the initial
297    /// seed.
298    ///
299    /// This function can be used to create a new generator that is a "spinoff" of the old
300    /// generator. The new generator will not produce the same sequence of values as the
301    /// old generator.
302    ///
303    /// # Example
304    ///
305    /// ```
306    /// // Seed two generators equally, and clone both of them.
307    /// let mut base1 = fastrand::Rng::with_seed(0x4d595df4d0f33173);
308    /// base1.bool(); // Use the generator once.
309    ///
310    /// let mut base2 = fastrand::Rng::with_seed(0x4d595df4d0f33173);
311    /// base2.bool(); // Use the generator once.
312    ///
313    /// let mut rng1 = base1.fork();
314    /// let mut rng2 = base2.fork();
315    ///
316    /// println!("rng1 returns {}", rng1.u32(..));
317    /// println!("rng2 returns {}", rng2.u32(..));
318    /// ```
319    #[inline]
320    #[must_use = "this creates a new instance of `Rng`"]
321    pub fn fork(&mut self) -> Self {
322        Rng::with_seed(self.gen_u64())
323    }
324
325    /// Generates a random `char` in ranges a-z and A-Z.
326    #[inline]
327    pub fn alphabetic(&mut self) -> char {
328        const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
329        *self.choice(CHARS).unwrap() as char
330    }
331
332    /// Generates a random `char` in ranges a-z, A-Z and 0-9.
333    #[inline]
334    pub fn alphanumeric(&mut self) -> char {
335        const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
336        *self.choice(CHARS).unwrap() as char
337    }
338
339    /// Generates a random `bool`.
340    #[inline]
341    pub fn bool(&mut self) -> bool {
342        self.u8(..) % 2 == 0
343    }
344
345    /// Generates a random digit in the given `base`.
346    ///
347    /// Digits are represented by `char`s in ranges 0-9 and a-z.
348    ///
349    /// Panics if the base is zero or greater than 36.
350    #[inline]
351    pub fn digit(&mut self, base: u32) -> char {
352        if base == 0 {
353            panic!("base cannot be zero");
354        }
355        if base > 36 {
356            panic!("base cannot be larger than 36");
357        }
358        let num = self.u8(..base as u8);
359        if num < 10 {
360            (b'0' + num) as char
361        } else {
362            (b'a' + num - 10) as char
363        }
364    }
365
366    /// Generates a random `f32` in range `0..=1`.
367    #[inline]
368    pub fn f32_inclusive(&mut self) -> f32 {
369        // Generate a number in 0..2^63 then convert to f32 and multiply by 2^(-63).
370        //
371        // Even though we're returning f32, we still generate u64 internally to make
372        // it possible to return nonzero numbers as small as 2^(-63). If we only
373        // generated u32 internally, the smallest nonzero number we could return
374        // would be 2^(-32).
375        //
376        // The integer we generate is in 0..2^63 rather than 0..2^64 to improve speed
377        // on x86-64, which has efficient i64->float conversion (cvtsi2ss) but for
378        // which u64->float conversion must be implemented in software.
379        //
380        // There is still some remaining bias in the int-to-float conversion, because
381        // nonzero numbers <=2^(-64) are never generated, even though they are
382        // expressible in f32. However, at this point the bias in int-to-float conversion
383        // is no larger than the bias in the underlying WyRand generator: since it only
384        // has a 64-bit state, it necessarily already have biases of at least 2^(-64)
385        // probability.
386        //
387        // See e.g. Section 3.1 of Thomas, David B., et al. "Gaussian random number generators,
388        // https://www.doc.ic.ac.uk/~wl/papers/07/csur07dt.pdf, for background.
389        const MUL: f32 = 1.0 / (1u64 << 63) as f32;
390        (self.gen_u64() >> 1) as f32 * MUL
391    }
392
393    /// Generates a random `f32` in range `0..1`.
394    ///
395    /// Function `f32_inclusive()` is a little simpler and faster, so default
396    /// to that if inclusive range is acceptable.
397    #[inline]
398    pub fn f32(&mut self) -> f32 {
399        loop {
400            let x = self.f32_inclusive();
401            if x < 1.0 {
402                return x;
403            }
404        }
405    }
406
407    /// Generates a random `f64` in range `0..=1`.
408    #[inline]
409    pub fn f64_inclusive(&mut self) -> f64 {
410        // See the comment in f32_inclusive() for more details.
411        const MUL: f64 = 1.0 / (1u64 << 63) as f64;
412        (self.gen_u64() >> 1) as f64 * MUL
413    }
414
415    /// Generates a random `f64` in range `0..1`.
416    ///
417    /// Function `f64_inclusive()` is a little simpler and faster, so default
418    /// to that if inclusive range is acceptable.
419    #[inline]
420    pub fn f64(&mut self) -> f64 {
421        loop {
422            let x = self.f64_inclusive();
423            if x < 1.0 {
424                return x;
425            }
426        }
427    }
428
429    /// Collects `amount` values at random from the iterable into a vector.
430    ///
431    /// The length of the returned vector equals `amount` unless the iterable
432    /// contains insufficient elements, in which case it equals the number of
433    /// elements available.
434    ///
435    /// Complexity is `O(n)` where `n` is the length of the iterable.
436    #[cfg(feature = "alloc")]
437    pub fn choose_multiple<I: IntoIterator>(&mut self, source: I, amount: usize) -> Vec<I::Item> {
438        // Adapted from: https://docs.rs/rand/latest/rand/seq/trait.IteratorRandom.html#method.choose_multiple
439        let mut reservoir = Vec::with_capacity(amount);
440        let mut iter = source.into_iter();
441
442        reservoir.extend(iter.by_ref().take(amount));
443
444        // Continue unless the iterator was exhausted
445        //
446        // note: this prevents iterators that "restart" from causing problems.
447        // If the iterator stops once, then so do we.
448        if reservoir.len() == amount {
449            for (i, elem) in iter.enumerate() {
450                let end = i + 1 + amount;
451                let k = self.usize(0..end);
452                if let Some(slot) = reservoir.get_mut(k) {
453                    *slot = elem;
454                }
455            }
456        } else {
457            // If less than one third of the `Vec` was used, reallocate
458            // so that the unused space is not wasted. There is a corner
459            // case where `amount` was much less than `self.len()`.
460            if reservoir.capacity() > 3 * reservoir.len() {
461                reservoir.shrink_to_fit();
462            }
463        }
464        reservoir
465    }
466
467    rng_integer!(
468        i8,
469        u8,
470        gen_u32,
471        gen_mod_u32,
472        "Generates a random `i8` in the given range."
473    );
474
475    rng_integer!(
476        i16,
477        u16,
478        gen_u32,
479        gen_mod_u32,
480        "Generates a random `i16` in the given range."
481    );
482
483    rng_integer!(
484        i32,
485        u32,
486        gen_u32,
487        gen_mod_u32,
488        "Generates a random `i32` in the given range."
489    );
490
491    rng_integer!(
492        i64,
493        u64,
494        gen_u64,
495        gen_mod_u64,
496        "Generates a random `i64` in the given range."
497    );
498
499    rng_integer!(
500        i128,
501        u128,
502        gen_u128,
503        gen_mod_u128,
504        "Generates a random `i128` in the given range."
505    );
506
507    #[cfg(target_pointer_width = "16")]
508    rng_integer!(
509        isize,
510        usize,
511        gen_u32,
512        gen_mod_u32,
513        "Generates a random `isize` in the given range."
514    );
515    #[cfg(target_pointer_width = "32")]
516    rng_integer!(
517        isize,
518        usize,
519        gen_u32,
520        gen_mod_u32,
521        "Generates a random `isize` in the given range."
522    );
523    #[cfg(target_pointer_width = "64")]
524    rng_integer!(
525        isize,
526        usize,
527        gen_u64,
528        gen_mod_u64,
529        "Generates a random `isize` in the given range."
530    );
531
532    /// Generates a random `char` in range a-z.
533    #[inline]
534    pub fn lowercase(&mut self) -> char {
535        const CHARS: &[u8] = b"abcdefghijklmnopqrstuvwxyz";
536        *self.choice(CHARS).unwrap() as char
537    }
538
539    /// Initializes this generator with the given seed.
540    #[inline]
541    pub fn seed(&mut self, seed: u64) {
542        self.0 = seed;
543    }
544
545    /// Gives back **current** seed that is being held by this generator.
546    #[inline]
547    pub fn get_seed(&self) -> u64 {
548        self.0
549    }
550
551    /// Choose an item from an iterator at random.
552    ///
553    /// This function may have an unexpected result if the `len()` property of the
554    /// iterator does not match the actual number of items in the iterator. If
555    /// the iterator is empty, this returns `None`.
556    #[inline]
557    pub fn choice<I>(&mut self, iter: I) -> Option<I::Item>
558    where
559        I: IntoIterator,
560        I::IntoIter: ExactSizeIterator,
561    {
562        let mut iter = iter.into_iter();
563
564        // Get the item at a random index.
565        let len = iter.len();
566        if len == 0 {
567            return None;
568        }
569        let index = self.usize(0..len);
570
571        iter.nth(index)
572    }
573
574    /// Shuffles a slice randomly.
575    #[inline]
576    pub fn shuffle<T>(&mut self, slice: &mut [T]) {
577        for i in 1..slice.len() {
578            slice.swap(i, self.usize(..=i));
579        }
580    }
581
582    /// Fill a byte slice with random data.
583    #[inline]
584    pub fn fill(&mut self, slice: &mut [u8]) {
585        // We fill the slice by chunks of 8 bytes, or one block of
586        // WyRand output per new state.
587        let mut chunks = slice.chunks_exact_mut(core::mem::size_of::<u64>());
588        for chunk in chunks.by_ref() {
589            let n = self.gen_u64().to_ne_bytes();
590            // Safe because the chunks are always 8 bytes exactly.
591            chunk.copy_from_slice(&n);
592        }
593
594        let remainder = chunks.into_remainder();
595
596        // Any remainder will always be less than 8 bytes.
597        if !remainder.is_empty() {
598            // Generate one last block of 8 bytes of entropy
599            let n = self.gen_u64().to_ne_bytes();
600
601            // Use the remaining length to copy from block
602            remainder.copy_from_slice(&n[..remainder.len()]);
603        }
604    }
605
606    rng_integer!(
607        u8,
608        u8,
609        gen_u32,
610        gen_mod_u32,
611        "Generates a random `u8` in the given range."
612    );
613
614    rng_integer!(
615        u16,
616        u16,
617        gen_u32,
618        gen_mod_u32,
619        "Generates a random `u16` in the given range."
620    );
621
622    rng_integer!(
623        u32,
624        u32,
625        gen_u32,
626        gen_mod_u32,
627        "Generates a random `u32` in the given range."
628    );
629
630    rng_integer!(
631        u64,
632        u64,
633        gen_u64,
634        gen_mod_u64,
635        "Generates a random `u64` in the given range."
636    );
637
638    rng_integer!(
639        u128,
640        u128,
641        gen_u128,
642        gen_mod_u128,
643        "Generates a random `u128` in the given range."
644    );
645
646    #[cfg(target_pointer_width = "16")]
647    rng_integer!(
648        usize,
649        usize,
650        gen_u32,
651        gen_mod_u32,
652        "Generates a random `usize` in the given range."
653    );
654    #[cfg(target_pointer_width = "32")]
655    rng_integer!(
656        usize,
657        usize,
658        gen_u32,
659        gen_mod_u32,
660        "Generates a random `usize` in the given range."
661    );
662    #[cfg(target_pointer_width = "64")]
663    rng_integer!(
664        usize,
665        usize,
666        gen_u64,
667        gen_mod_u64,
668        "Generates a random `usize` in the given range."
669    );
670
671    /// Generates a random `char` in range A-Z.
672    #[inline]
673    pub fn uppercase(&mut self) -> char {
674        const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
675        *self.choice(CHARS).unwrap() as char
676    }
677
678    /// Generates a random `char` in the given range.
679    ///
680    /// Panics if the range is empty.
681    #[inline]
682    pub fn char(&mut self, range: impl RangeBounds<char>) -> char {
683        let panic_empty_range = || {
684            panic!(
685                "empty range: {:?}..{:?}",
686                range.start_bound(),
687                range.end_bound()
688            )
689        };
690
691        let surrogate_start = 0xd800u32;
692        let surrogate_len = 0x800u32;
693
694        let low = match range.start_bound() {
695            Bound::Unbounded => 0u8 as char,
696            Bound::Included(&x) => x,
697            Bound::Excluded(&x) => {
698                let scalar = if x as u32 == surrogate_start - 1 {
699                    surrogate_start + surrogate_len
700                } else {
701                    x as u32 + 1
702                };
703                char::try_from(scalar).unwrap_or_else(|_| panic_empty_range())
704            }
705        };
706
707        let high = match range.end_bound() {
708            Bound::Unbounded => core::char::MAX,
709            Bound::Included(&x) => x,
710            Bound::Excluded(&x) => {
711                let scalar = if x as u32 == surrogate_start + surrogate_len {
712                    surrogate_start - 1
713                } else {
714                    (x as u32).wrapping_sub(1)
715                };
716                char::try_from(scalar).unwrap_or_else(|_| panic_empty_range())
717            }
718        };
719
720        if low > high {
721            panic_empty_range();
722        }
723
724        let gap = if (low as u32) < surrogate_start && (high as u32) >= surrogate_start {
725            surrogate_len
726        } else {
727            0
728        };
729        let range = high as u32 - low as u32 - gap;
730        let mut val = self.u32(0..=range) + low as u32;
731        if val >= surrogate_start {
732            val += gap;
733        }
734        val.try_into().unwrap()
735    }
736}