1#![forbid(unsafe_code)]
69#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
70
71use std::cell::Cell;
72use std::collections::hash_map::DefaultHasher;
73use std::convert::TryInto;
74use std::hash::{Hash, Hasher};
75use std::ops::{Bound, RangeBounds};
76use std::thread;
77
78#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
79use instant::Instant;
80#[cfg(not(all(target_arch = "wasm32", not(target_os = "wasi"))))]
81use std::time::Instant;
82
83#[derive(Debug, PartialEq, Eq)]
85pub struct Rng(Cell<u64>);
86
87impl Default for Rng {
88 #[inline]
89 fn default() -> Rng {
90 Rng::new()
91 }
92}
93
94impl Clone for Rng {
95 fn clone(&self) -> Rng {
116 Rng::with_seed(self.gen_u64())
117 }
118}
119
120impl Rng {
121 #[inline]
123 fn gen_u32(&self) -> u32 {
124 self.gen_u64() as u32
125 }
126
127 #[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 #[inline]
138 fn gen_u128(&self) -> u128 {
139 (u128::from(self.gen_u64()) << 64) | u128::from(self.gen_u64())
140 }
141
142 #[inline]
144 fn gen_mod_u32(&self, n: u32) -> u32 {
145 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 #[inline]
162 fn gen_mod_u64(&self, n: u64) -> u64 {
163 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 #[inline]
180 fn gen_mod_u128(&self, n: u128) -> u128 {
181 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
197thread_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#[inline]
209fn mul_high_u32(a: u32, b: u32) -> u32 {
210 (((a as u64) * (b as u64)) >> 32) as u32
211}
212
213#[inline]
215fn mul_high_u64(a: u64, b: u64) -> u64 {
216 (((a as u128) * (b as u128)) >> 64) as u64
217}
218
219#[inline]
221fn mul_high_u128(a: u128, b: u128) -> u128 {
222 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
232macro_rules! rng_integer {
233 ($t:tt, $unsigned_t:tt, $gen:tt, $mod:tt, $doc:tt) => {
234 #[doc = $doc]
235 #[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
273impl Rng {
274 #[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 #[inline]
285 #[must_use = "this creates a new instance of `Rng`; if you want to initialize the thread-local generator, use `fastrand::seed()` instead"]
286 pub fn with_seed(seed: u64) -> Self {
287 let rng = Rng(Cell::new(0));
288
289 rng.seed(seed);
290 rng
291 }
292
293 #[inline]
295 pub fn alphabetic(&self) -> char {
296 const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
297 let len = CHARS.len() as u8;
298 let i = self.u8(..len);
299 CHARS[i as usize] as char
300 }
301
302 #[inline]
304 pub fn alphanumeric(&self) -> char {
305 const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
306 let len = CHARS.len() as u8;
307 let i = self.u8(..len);
308 CHARS[i as usize] as char
309 }
310
311 #[inline]
313 pub fn bool(&self) -> bool {
314 self.u8(..) % 2 == 0
315 }
316
317 #[inline]
323 pub fn digit(&self, base: u32) -> char {
324 if base == 0 {
325 panic!("base cannot be zero");
326 }
327 if base > 36 {
328 panic!("base cannot be larger than 36");
329 }
330 let num = self.u8(..base as u8);
331 if num < 10 {
332 (b'0' + num) as char
333 } else {
334 (b'a' + num - 10) as char
335 }
336 }
337
338 pub fn f32(&self) -> f32 {
340 let b = 32;
341 let f = std::f32::MANTISSA_DIGITS - 1;
342 f32::from_bits((1 << (b - 2)) - (1 << f) + (self.u32(..) >> (b - f))) - 1.0
343 }
344
345 pub fn f64(&self) -> f64 {
347 let b = 64;
348 let f = std::f64::MANTISSA_DIGITS - 1;
349 f64::from_bits((1 << (b - 2)) - (1 << f) + (self.u64(..) >> (b - f))) - 1.0
350 }
351
352 rng_integer!(
353 i8,
354 u8,
355 gen_u32,
356 gen_mod_u32,
357 "Generates a random `i8` in the given range."
358 );
359
360 rng_integer!(
361 i16,
362 u16,
363 gen_u32,
364 gen_mod_u32,
365 "Generates a random `i16` in the given range."
366 );
367
368 rng_integer!(
369 i32,
370 u32,
371 gen_u32,
372 gen_mod_u32,
373 "Generates a random `i32` in the given range."
374 );
375
376 rng_integer!(
377 i64,
378 u64,
379 gen_u64,
380 gen_mod_u64,
381 "Generates a random `i64` in the given range."
382 );
383
384 rng_integer!(
385 i128,
386 u128,
387 gen_u128,
388 gen_mod_u128,
389 "Generates a random `i128` in the given range."
390 );
391
392 #[cfg(target_pointer_width = "16")]
393 rng_integer!(
394 isize,
395 usize,
396 gen_u32,
397 gen_mod_u32,
398 "Generates a random `isize` in the given range."
399 );
400 #[cfg(target_pointer_width = "32")]
401 rng_integer!(
402 isize,
403 usize,
404 gen_u32,
405 gen_mod_u32,
406 "Generates a random `isize` in the given range."
407 );
408 #[cfg(target_pointer_width = "64")]
409 rng_integer!(
410 isize,
411 usize,
412 gen_u64,
413 gen_mod_u64,
414 "Generates a random `isize` in the given range."
415 );
416
417 #[inline]
419 pub fn lowercase(&self) -> char {
420 const CHARS: &[u8] = b"abcdefghijklmnopqrstuvwxyz";
421 let len = CHARS.len() as u8;
422 let i = self.u8(..len);
423 CHARS[i as usize] as char
424 }
425
426 #[inline]
428 pub fn seed(&self, seed: u64) {
429 self.0.set(seed);
430 }
431
432 #[inline]
434 pub fn get_seed(&self) -> u64 {
435 self.0.get()
436 }
437
438 #[inline]
440 pub fn shuffle<T>(&self, slice: &mut [T]) {
441 for i in 1..slice.len() {
442 slice.swap(i, self.usize(..=i));
443 }
444 }
445
446 #[inline]
448 pub fn fill(&self, slice: &mut [u8]) {
449 let mut chunks = slice.chunks_exact_mut(core::mem::size_of::<u64>());
452 for chunk in chunks.by_ref() {
453 let n = self.gen_u64().to_ne_bytes();
454 chunk.copy_from_slice(&n);
456 }
457
458 let remainder = chunks.into_remainder();
459
460 if !remainder.is_empty() {
462 let n = self.gen_u64().to_ne_bytes();
464
465 remainder.copy_from_slice(&n[..remainder.len()]);
467 }
468 }
469
470 rng_integer!(
471 u8,
472 u8,
473 gen_u32,
474 gen_mod_u32,
475 "Generates a random `u8` in the given range."
476 );
477
478 rng_integer!(
479 u16,
480 u16,
481 gen_u32,
482 gen_mod_u32,
483 "Generates a random `u16` in the given range."
484 );
485
486 rng_integer!(
487 u32,
488 u32,
489 gen_u32,
490 gen_mod_u32,
491 "Generates a random `u32` in the given range."
492 );
493
494 rng_integer!(
495 u64,
496 u64,
497 gen_u64,
498 gen_mod_u64,
499 "Generates a random `u64` in the given range."
500 );
501
502 rng_integer!(
503 u128,
504 u128,
505 gen_u128,
506 gen_mod_u128,
507 "Generates a random `u128` in the given range."
508 );
509
510 #[cfg(target_pointer_width = "16")]
511 rng_integer!(
512 usize,
513 usize,
514 gen_u32,
515 gen_mod_u32,
516 "Generates a random `usize` in the given range."
517 );
518 #[cfg(target_pointer_width = "32")]
519 rng_integer!(
520 usize,
521 usize,
522 gen_u32,
523 gen_mod_u32,
524 "Generates a random `usize` in the given range."
525 );
526 #[cfg(target_pointer_width = "64")]
527 rng_integer!(
528 usize,
529 usize,
530 gen_u64,
531 gen_mod_u64,
532 "Generates a random `usize` in the given range."
533 );
534 #[cfg(target_pointer_width = "128")]
535 rng_integer!(
536 usize,
537 usize,
538 gen_u128,
539 gen_mod_u128,
540 "Generates a random `usize` in the given range."
541 );
542
543 #[inline]
545 pub fn uppercase(&self) -> char {
546 const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
547 let len = CHARS.len() as u8;
548 let i = self.u8(..len);
549 CHARS[i as usize] as char
550 }
551
552 #[inline]
556 pub fn char(&self, range: impl RangeBounds<char>) -> char {
557 use std::convert::TryFrom;
558
559 let panic_empty_range = || {
560 panic!(
561 "empty range: {:?}..{:?}",
562 range.start_bound(),
563 range.end_bound()
564 )
565 };
566
567 let surrogate_start = 0xd800u32;
568 let surrogate_len = 0x800u32;
569
570 let low = match range.start_bound() {
571 Bound::Unbounded => 0u8 as char,
572 Bound::Included(&x) => x,
573 Bound::Excluded(&x) => {
574 let scalar = if x as u32 == surrogate_start - 1 {
575 surrogate_start + surrogate_len
576 } else {
577 x as u32 + 1
578 };
579 char::try_from(scalar).unwrap_or_else(|_| panic_empty_range())
580 }
581 };
582
583 let high = match range.end_bound() {
584 Bound::Unbounded => std::char::MAX,
585 Bound::Included(&x) => x,
586 Bound::Excluded(&x) => {
587 let scalar = if x as u32 == surrogate_start + surrogate_len {
588 surrogate_start - 1
589 } else {
590 (x as u32).wrapping_sub(1)
591 };
592 char::try_from(scalar).unwrap_or_else(|_| panic_empty_range())
593 }
594 };
595
596 if low > high {
597 panic_empty_range();
598 }
599
600 let gap = if (low as u32) < surrogate_start && (high as u32) >= surrogate_start {
601 surrogate_len
602 } else {
603 0
604 };
605 let range = high as u32 - low as u32 - gap;
606 let mut val = self.u32(0..=range) + low as u32;
607 if val >= surrogate_start {
608 val += gap;
609 }
610 val.try_into().unwrap()
611 }
612}
613
614#[inline]
616pub fn seed(seed: u64) {
617 RNG.with(|rng| rng.seed(seed))
618}
619
620#[inline]
622pub fn get_seed() -> u64 {
623 RNG.with(|rng| rng.get_seed())
624}
625
626#[inline]
628pub fn bool() -> bool {
629 RNG.with(|rng| rng.bool())
630}
631
632#[inline]
634pub fn alphabetic() -> char {
635 RNG.with(|rng| rng.alphabetic())
636}
637
638#[inline]
640pub fn alphanumeric() -> char {
641 RNG.with(|rng| rng.alphanumeric())
642}
643
644#[inline]
646pub fn lowercase() -> char {
647 RNG.with(|rng| rng.lowercase())
648}
649
650#[inline]
652pub fn uppercase() -> char {
653 RNG.with(|rng| rng.uppercase())
654}
655
656#[inline]
662pub fn digit(base: u32) -> char {
663 RNG.with(|rng| rng.digit(base))
664}
665
666#[inline]
668pub fn shuffle<T>(slice: &mut [T]) {
669 RNG.with(|rng| rng.shuffle(slice))
670}
671
672macro_rules! integer {
673 ($t:tt, $doc:tt) => {
674 #[doc = $doc]
675 #[inline]
678 pub fn $t(range: impl RangeBounds<$t>) -> $t {
679 RNG.with(|rng| rng.$t(range))
680 }
681 };
682}
683
684integer!(u8, "Generates a random `u8` in the given range.");
685integer!(i8, "Generates a random `i8` in the given range.");
686integer!(u16, "Generates a random `u16` in the given range.");
687integer!(i16, "Generates a random `i16` in the given range.");
688integer!(u32, "Generates a random `u32` in the given range.");
689integer!(i32, "Generates a random `i32` in the given range.");
690integer!(u64, "Generates a random `u64` in the given range.");
691integer!(i64, "Generates a random `i64` in the given range.");
692integer!(u128, "Generates a random `u128` in the given range.");
693integer!(i128, "Generates a random `i128` in the given range.");
694integer!(usize, "Generates a random `usize` in the given range.");
695integer!(isize, "Generates a random `isize` in the given range.");
696integer!(char, "Generates a random `char` in the given range.");
697
698pub fn f32() -> f32 {
700 RNG.with(|rng| rng.f32())
701}
702
703pub fn f64() -> f64 {
705 RNG.with(|rng| rng.f64())
706}