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 //! Shuffle an array: 33 //! 34 //! ``` 35 //! let mut v = vec![1, 2, 3, 4, 5]; 36 //! fastrand::shuffle(&mut v); 37 //! ``` 38 //! 39 //! Generate a random [`Vec`] or [`String`]: 40 //! 41 //! ``` 42 //! use std::iter::repeat_with; 43 //! 44 //! let v: Vec<i32> = repeat_with(|| fastrand::i32(..)).take(10).collect(); 45 //! let s: String = repeat_with(fastrand::alphanumeric).take(10).collect(); 46 //! ``` 47 //! 48 //! To get reproducible results on every run, initialize the generator with a seed: 49 //! 50 //! ``` 51 //! // Pick an arbitrary number as seed. 52 //! fastrand::seed(7); 53 //! 54 //! // Now this prints the same number on every run: 55 //! println!("{}", fastrand::u32(..)); 56 //! ``` 57 //! 58 //! To be more efficient, create a new [`Rng`] instance instead of using the thread-local 59 //! generator: 60 //! 61 //! ``` 62 //! use std::iter::repeat_with; 63 //! 64 //! let rng = fastrand::Rng::new(); 65 //! let mut bytes: Vec<u8> = repeat_with(|| rng.u8(..)).take(10_000).collect(); 66 //! ``` 67 68 #![forbid(unsafe_code)] 69 #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)] 70 71 use std::cell::Cell; 72 use std::collections::hash_map::DefaultHasher; 73 use std::convert::TryInto; 74 use std::hash::{Hash, Hasher}; 75 use std::ops::{Bound, RangeBounds}; 76 use std::thread; 77 78 #[cfg(target_arch = "wasm32")] 79 use instant::Instant; 80 #[cfg(not(target_arch = "wasm32"))] 81 use std::time::Instant; 82 83 /// A random number generator. 84 #[derive(Debug, PartialEq, Eq)] 85 pub struct Rng(Cell<u64>); 86 87 impl Default for Rng { 88 #[inline] 89 fn default() -> Rng { 90 Rng::new() 91 } 92 } 93 94 impl Clone for Rng { 95 /// Clones the generator by deterministically deriving a new generator based on the initial 96 /// seed. 97 /// 98 /// # Example 99 /// 100 /// ``` 101 /// // Seed two generators equally, and clone both of them. 102 /// let base1 = fastrand::Rng::new(); 103 /// base1.seed(0x4d595df4d0f33173); 104 /// base1.bool(); // Use the generator once. 105 /// 106 /// let base2 = fastrand::Rng::new(); 107 /// base2.seed(0x4d595df4d0f33173); 108 /// base2.bool(); // Use the generator once. 109 /// 110 /// let rng1 = base1.clone(); 111 /// let rng2 = base2.clone(); 112 /// 113 /// assert_eq!(rng1.u64(..), rng2.u64(..), "the cloned generators are identical"); 114 /// ``` 115 fn clone(&self) -> Rng { 116 Rng::with_seed(self.gen_u64()) 117 } 118 } 119 120 impl Rng { 121 /// Generates a random `u32`. 122 #[inline] 123 fn gen_u32(&self) -> u32 { 124 self.gen_u64() as u32 125 } 126 127 /// Generates a random `u64`. 128 #[inline] 129 fn gen_u64(&self) -> u64 { 130 let s = self.0.get().wrapping_add(0xA0761D6478BD642F); 131 self.0.set(s); 132 let t = u128::from(s) * u128::from(s ^ 0xE7037ED1A0B428DB); 133 (t as u64) ^ (t >> 64) as u64 134 } 135 136 /// Generates a random `u128`. 137 #[inline] 138 fn gen_u128(&self) -> u128 { 139 (u128::from(self.gen_u64()) << 64) | u128::from(self.gen_u64()) 140 } 141 142 /// Generates a random `u32` in `0..n`. 143 #[inline] 144 fn gen_mod_u32(&self, n: u32) -> u32 { 145 // Adapted from: https://lemire.me/blog/2016/06/30/fast-random-shuffling/ 146 let mut r = self.gen_u32(); 147 let mut hi = mul_high_u32(r, n); 148 let mut lo = r.wrapping_mul(n); 149 if lo < n { 150 let t = n.wrapping_neg() % n; 151 while lo < t { 152 r = self.gen_u32(); 153 hi = mul_high_u32(r, n); 154 lo = r.wrapping_mul(n); 155 } 156 } 157 hi 158 } 159 160 /// Generates a random `u64` in `0..n`. 161 #[inline] 162 fn gen_mod_u64(&self, n: u64) -> u64 { 163 // Adapted from: https://lemire.me/blog/2016/06/30/fast-random-shuffling/ 164 let mut r = self.gen_u64(); 165 let mut hi = mul_high_u64(r, n); 166 let mut lo = r.wrapping_mul(n); 167 if lo < n { 168 let t = n.wrapping_neg() % n; 169 while lo < t { 170 r = self.gen_u64(); 171 hi = mul_high_u64(r, n); 172 lo = r.wrapping_mul(n); 173 } 174 } 175 hi 176 } 177 178 /// Generates a random `u128` in `0..n`. 179 #[inline] 180 fn gen_mod_u128(&self, n: u128) -> u128 { 181 // Adapted from: https://lemire.me/blog/2016/06/30/fast-random-shuffling/ 182 let mut r = self.gen_u128(); 183 let mut hi = mul_high_u128(r, n); 184 let mut lo = r.wrapping_mul(n); 185 if lo < n { 186 let t = n.wrapping_neg() % n; 187 while lo < t { 188 r = self.gen_u128(); 189 hi = mul_high_u128(r, n); 190 lo = r.wrapping_mul(n); 191 } 192 } 193 hi 194 } 195 } 196 197 thread_local! { 198 static RNG: Rng = Rng(Cell::new({ 199 let mut hasher = DefaultHasher::new(); 200 Instant::now().hash(&mut hasher); 201 thread::current().id().hash(&mut hasher); 202 let hash = hasher.finish(); 203 (hash << 1) | 1 204 })); 205 } 206 207 /// Computes `(a * b) >> 32`. 208 #[inline] 209 fn mul_high_u32(a: u32, b: u32) -> u32 { 210 (((a as u64) * (b as u64)) >> 32) as u32 211 } 212 213 /// Computes `(a * b) >> 64`. 214 #[inline] 215 fn mul_high_u64(a: u64, b: u64) -> u64 { 216 (((a as u128) * (b as u128)) >> 64) as u64 217 } 218 219 /// Computes `(a * b) >> 128`. 220 #[inline] 221 fn mul_high_u128(a: u128, b: u128) -> u128 { 222 // Adapted from: https://stackoverflow.com/a/28904636 223 let a_lo = a as u64 as u128; 224 let a_hi = (a >> 64) as u64 as u128; 225 let b_lo = b as u64 as u128; 226 let b_hi = (b >> 64) as u64 as u128; 227 let carry = (a_lo * b_lo) >> 64; 228 let carry = ((a_hi * b_lo) as u64 as u128 + (a_lo * b_hi) as u64 as u128 + carry) >> 64; 229 a_hi * b_hi + ((a_hi * b_lo) >> 64) + ((a_lo * b_hi) >> 64) + carry 230 } 231 232 macro_rules! rng_integer { 233 ($t:tt, $unsigned_t:tt, $gen:tt, $mod:tt, $doc:tt) => { 234 #[doc = $doc] 235 /// 236 /// Panics if the range is empty. 237 #[inline] 238 pub fn $t(&self, range: impl RangeBounds<$t>) -> $t { 239 let panic_empty_range = || { 240 panic!( 241 "empty range: {:?}..{:?}", 242 range.start_bound(), 243 range.end_bound() 244 ) 245 }; 246 247 let low = match range.start_bound() { 248 Bound::Unbounded => std::$t::MIN, 249 Bound::Included(&x) => x, 250 Bound::Excluded(&x) => x.checked_add(1).unwrap_or_else(panic_empty_range), 251 }; 252 253 let high = match range.end_bound() { 254 Bound::Unbounded => std::$t::MAX, 255 Bound::Included(&x) => x, 256 Bound::Excluded(&x) => x.checked_sub(1).unwrap_or_else(panic_empty_range), 257 }; 258 259 if low > high { 260 panic_empty_range(); 261 } 262 263 if low == std::$t::MIN && high == std::$t::MAX { 264 self.$gen() as $t 265 } else { 266 let len = high.wrapping_sub(low).wrapping_add(1); 267 low.wrapping_add(self.$mod(len as $unsigned_t as _) as $t) 268 } 269 } 270 }; 271 } 272 273 impl Rng { 274 /// Creates a new random number generator. 275 #[inline] 276 pub fn new() -> Rng { 277 Rng::with_seed( 278 RNG.try_with(|rng| rng.u64(..)) 279 .unwrap_or(0x4d595df4d0f33173), 280 ) 281 } 282 283 /// Creates a new random number generator with the initial seed. 284 #[inline] 285 pub fn with_seed(seed: u64) -> Self { 286 let rng = Rng(Cell::new(0)); 287 288 rng.seed(seed); 289 rng 290 } 291 292 /// Generates a random `char` in ranges a-z and A-Z. 293 #[inline] 294 pub fn alphabetic(&self) -> char { 295 const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 296 let len = CHARS.len() as u8; 297 let i = self.u8(..len); 298 CHARS[i as usize] as char 299 } 300 301 /// Generates a random `char` in ranges a-z, A-Z and 0-9. 302 #[inline] 303 pub fn alphanumeric(&self) -> char { 304 const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 305 let len = CHARS.len() as u8; 306 let i = self.u8(..len); 307 CHARS[i as usize] as char 308 } 309 310 /// Generates a random `bool`. 311 #[inline] 312 pub fn bool(&self) -> bool { 313 self.u8(..) % 2 == 0 314 } 315 316 /// Generates a random digit in the given `base`. 317 /// 318 /// Digits are represented by `char`s in ranges 0-9 and a-z. 319 /// 320 /// Panics if the base is zero or greater than 36. 321 #[inline] 322 pub fn digit(&self, base: u32) -> char { 323 if base == 0 { 324 panic!("base cannot be zero"); 325 } 326 if base > 36 { 327 panic!("base cannot be larger than 36"); 328 } 329 let num = self.u8(..base as u8); 330 if num < 10 { 331 (b'0' + num) as char 332 } else { 333 (b'a' + num - 10) as char 334 } 335 } 336 337 /// Generates a random `f32` in range `0..1`. 338 pub fn f32(&self) -> f32 { 339 let b = 32; 340 let f = std::f32::MANTISSA_DIGITS - 1; 341 f32::from_bits((1 << (b - 2)) - (1 << f) + (self.u32(..) >> (b - f))) - 1.0 342 } 343 344 /// Generates a random `f64` in range `0..1`. 345 pub fn f64(&self) -> f64 { 346 let b = 64; 347 let f = std::f64::MANTISSA_DIGITS - 1; 348 f64::from_bits((1 << (b - 2)) - (1 << f) + (self.u64(..) >> (b - f))) - 1.0 349 } 350 351 rng_integer!( 352 i8, 353 u8, 354 gen_u32, 355 gen_mod_u32, 356 "Generates a random `i8` in the given range." 357 ); 358 359 rng_integer!( 360 i16, 361 u16, 362 gen_u32, 363 gen_mod_u32, 364 "Generates a random `i16` in the given range." 365 ); 366 367 rng_integer!( 368 i32, 369 u32, 370 gen_u32, 371 gen_mod_u32, 372 "Generates a random `i32` in the given range." 373 ); 374 375 rng_integer!( 376 i64, 377 u64, 378 gen_u64, 379 gen_mod_u64, 380 "Generates a random `i64` in the given range." 381 ); 382 383 rng_integer!( 384 i128, 385 u128, 386 gen_u128, 387 gen_mod_u128, 388 "Generates a random `i128` in the given range." 389 ); 390 391 #[cfg(target_pointer_width = "16")] 392 rng_integer!( 393 isize, 394 usize, 395 gen_u32, 396 gen_mod_u32, 397 "Generates a random `isize` in the given range." 398 ); 399 #[cfg(target_pointer_width = "32")] 400 rng_integer!( 401 isize, 402 usize, 403 gen_u32, 404 gen_mod_u32, 405 "Generates a random `isize` in the given range." 406 ); 407 #[cfg(target_pointer_width = "64")] 408 rng_integer!( 409 isize, 410 usize, 411 gen_u64, 412 gen_mod_u64, 413 "Generates a random `isize` in the given range." 414 ); 415 416 /// Generates a random `char` in range a-z. 417 #[inline] 418 pub fn lowercase(&self) -> char { 419 const CHARS: &[u8] = b"abcdefghijklmnopqrstuvwxyz"; 420 let len = CHARS.len() as u8; 421 let i = self.u8(..len); 422 CHARS[i as usize] as char 423 } 424 425 /// Initializes this generator with the given seed. 426 #[inline] 427 pub fn seed(&self, seed: u64) { 428 self.0.set(seed); 429 } 430 431 /// Gives back **current** seed that is being held by this generator. 432 #[inline] 433 pub fn get_seed(&self) -> u64 { 434 self.0.get() 435 } 436 437 /// Shuffles a slice randomly. 438 #[inline] 439 pub fn shuffle<T>(&self, slice: &mut [T]) { 440 for i in 1..slice.len() { 441 slice.swap(i, self.usize(..=i)); 442 } 443 } 444 445 /// Fill a byte slice with random data. 446 pub fn fill(&self, slice: &mut [u8]) { 447 // Filling the buffer in chunks of 8 is much faster. 448 let mut chunks = slice.chunks_exact_mut(8); 449 for chunk in chunks.by_ref() { 450 let n = self.gen_u64(); 451 // Safe because the chunks are always 8 bytes exactly. 452 let bytes: &mut [u8; 8] = chunk.try_into().unwrap(); 453 *bytes = n.to_ne_bytes(); 454 } 455 456 for item in chunks.into_remainder() { 457 *item = self.u8(..); 458 } 459 } 460 461 rng_integer!( 462 u8, 463 u8, 464 gen_u32, 465 gen_mod_u32, 466 "Generates a random `u8` in the given range." 467 ); 468 469 rng_integer!( 470 u16, 471 u16, 472 gen_u32, 473 gen_mod_u32, 474 "Generates a random `u16` in the given range." 475 ); 476 477 rng_integer!( 478 u32, 479 u32, 480 gen_u32, 481 gen_mod_u32, 482 "Generates a random `u32` in the given range." 483 ); 484 485 rng_integer!( 486 u64, 487 u64, 488 gen_u64, 489 gen_mod_u64, 490 "Generates a random `u64` in the given range." 491 ); 492 493 rng_integer!( 494 u128, 495 u128, 496 gen_u128, 497 gen_mod_u128, 498 "Generates a random `u128` in the given range." 499 ); 500 501 #[cfg(target_pointer_width = "16")] 502 rng_integer!( 503 usize, 504 usize, 505 gen_u32, 506 gen_mod_u32, 507 "Generates a random `usize` in the given range." 508 ); 509 #[cfg(target_pointer_width = "32")] 510 rng_integer!( 511 usize, 512 usize, 513 gen_u32, 514 gen_mod_u32, 515 "Generates a random `usize` in the given range." 516 ); 517 #[cfg(target_pointer_width = "64")] 518 rng_integer!( 519 usize, 520 usize, 521 gen_u64, 522 gen_mod_u64, 523 "Generates a random `usize` in the given range." 524 ); 525 #[cfg(target_pointer_width = "128")] 526 rng_integer!( 527 usize, 528 usize, 529 gen_u128, 530 gen_mod_u128, 531 "Generates a random `usize` in the given range." 532 ); 533 534 /// Generates a random `char` in range A-Z. 535 #[inline] 536 pub fn uppercase(&self) -> char { 537 const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 538 let len = CHARS.len() as u8; 539 let i = self.u8(..len); 540 CHARS[i as usize] as char 541 } 542 543 /// Generates a random `char` in the given range. 544 /// 545 /// Panics if the range is empty. 546 #[inline] 547 pub fn char(&self, range: impl RangeBounds<char>) -> char { 548 use std::convert::TryFrom; 549 550 let panic_empty_range = || { 551 panic!( 552 "empty range: {:?}..{:?}", 553 range.start_bound(), 554 range.end_bound() 555 ) 556 }; 557 558 let surrogate_start = 0xd800u32; 559 let surrogate_len = 0x800u32; 560 561 let low = match range.start_bound() { 562 Bound::Unbounded => 0u8 as char, 563 Bound::Included(&x) => x, 564 Bound::Excluded(&x) => { 565 let scalar = if x as u32 == surrogate_start - 1 { 566 surrogate_start + surrogate_len 567 } else { 568 x as u32 + 1 569 }; 570 char::try_from(scalar).unwrap_or_else(|_| panic_empty_range()) 571 } 572 }; 573 574 let high = match range.end_bound() { 575 Bound::Unbounded => std::char::MAX, 576 Bound::Included(&x) => x, 577 Bound::Excluded(&x) => { 578 let scalar = if x as u32 == surrogate_start + surrogate_len { 579 surrogate_start - 1 580 } else { 581 (x as u32).wrapping_sub(1) 582 }; 583 char::try_from(scalar).unwrap_or_else(|_| panic_empty_range()) 584 } 585 }; 586 587 if low > high { 588 panic_empty_range(); 589 } 590 591 let gap = if (low as u32) < surrogate_start && (high as u32) >= surrogate_start { 592 surrogate_len 593 } else { 594 0 595 }; 596 let range = high as u32 - low as u32 - gap; 597 let mut val = self.u32(0..=range) + low as u32; 598 if val >= surrogate_start { 599 val += gap; 600 } 601 val.try_into().unwrap() 602 } 603 } 604 605 /// Initializes the thread-local generator with the given seed. 606 #[inline] 607 pub fn seed(seed: u64) { 608 RNG.with(|rng| rng.seed(seed)) 609 } 610 611 /// Gives back **current** seed that is being held by the thread-local generator. 612 #[inline] 613 pub fn get_seed() -> u64 { 614 RNG.with(|rng| rng.get_seed()) 615 } 616 617 /// Generates a random `bool`. 618 #[inline] 619 pub fn bool() -> bool { 620 RNG.with(|rng| rng.bool()) 621 } 622 623 /// Generates a random `char` in ranges a-z and A-Z. 624 #[inline] 625 pub fn alphabetic() -> char { 626 RNG.with(|rng| rng.alphabetic()) 627 } 628 629 /// Generates a random `char` in ranges a-z, A-Z and 0-9. 630 #[inline] 631 pub fn alphanumeric() -> char { 632 RNG.with(|rng| rng.alphanumeric()) 633 } 634 635 /// Generates a random `char` in range a-z. 636 #[inline] 637 pub fn lowercase() -> char { 638 RNG.with(|rng| rng.lowercase()) 639 } 640 641 /// Generates a random `char` in range A-Z. 642 #[inline] 643 pub fn uppercase() -> char { 644 RNG.with(|rng| rng.uppercase()) 645 } 646 647 /// Generates a random digit in the given `base`. 648 /// 649 /// Digits are represented by `char`s in ranges 0-9 and a-z. 650 /// 651 /// Panics if the base is zero or greater than 36. 652 #[inline] 653 pub fn digit(base: u32) -> char { 654 RNG.with(|rng| rng.digit(base)) 655 } 656 657 /// Shuffles a slice randomly. 658 #[inline] 659 pub fn shuffle<T>(slice: &mut [T]) { 660 RNG.with(|rng| rng.shuffle(slice)) 661 } 662 663 macro_rules! integer { 664 ($t:tt, $doc:tt) => { 665 #[doc = $doc] 666 /// 667 /// Panics if the range is empty. 668 #[inline] 669 pub fn $t(range: impl RangeBounds<$t>) -> $t { 670 RNG.with(|rng| rng.$t(range)) 671 } 672 }; 673 } 674 675 integer!(u8, "Generates a random `u8` in the given range."); 676 integer!(i8, "Generates a random `i8` in the given range."); 677 integer!(u16, "Generates a random `u16` in the given range."); 678 integer!(i16, "Generates a random `i16` in the given range."); 679 integer!(u32, "Generates a random `u32` in the given range."); 680 integer!(i32, "Generates a random `i32` in the given range."); 681 integer!(u64, "Generates a random `u64` in the given range."); 682 integer!(i64, "Generates a random `i64` in the given range."); 683 integer!(u128, "Generates a random `u128` in the given range."); 684 integer!(i128, "Generates a random `i128` in the given range."); 685 integer!(usize, "Generates a random `usize` in the given range."); 686 integer!(isize, "Generates a random `isize` in the given range."); 687 integer!(char, "Generates a random `char` in the given range."); 688 689 /// Generates a random `f32` in range `0..1`. 690 pub fn f32() -> f32 { 691 RNG.with(|rng| rng.f32()) 692 } 693 694 /// Generates a random `f64` in range `0..1`. 695 pub fn f64() -> f64 { 696 RNG.with(|rng| rng.f64()) 697 }