1#![forbid(unsafe_code)]
71#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
72
73use std::cell::Cell;
74use std::collections::hash_map::DefaultHasher;
75use std::hash::{Hash, Hasher};
76use std::ops::{Bound, RangeBounds};
77use std::thread;
78
79#[cfg(not(target_arch = "wasm32"))]
80use std::time::Instant;
81#[cfg(target_arch = "wasm32")]
82use instant::Instant;
83
84#[derive(Debug)]
86pub struct Rng(Cell<u64>);
87
88impl Default for Rng {
89 #[inline]
90 fn default() -> Rng {
91 Rng::new()
92 }
93}
94
95impl Clone for Rng {
96 fn clone(&self) -> Rng {
117 Rng::with_seed(self.gen_u64())
118 }
119}
120
121impl Rng {
122 #[inline]
124 fn gen_u32(&self) -> u32 {
125 let s = self.0.get();
127 self.0.set(
128 s.wrapping_mul(6364136223846793005)
129 .wrapping_add(1442695040888963407),
130 );
131 (((s ^ (s >> 18)) >> 27) as u32).rotate_right((s >> 59) as u32)
132 }
133
134 #[inline]
136 fn gen_u64(&self) -> u64 {
137 ((self.gen_u32() as u64) << 32) | (self.gen_u32() as u64)
138 }
139
140 #[inline]
142 fn gen_u128(&self) -> u128 {
143 ((self.gen_u64() as u128) << 64) | (self.gen_u64() as u128)
144 }
145
146 #[inline]
148 fn gen_mod_u32(&self, n: u32) -> u32 {
149 let mut r = self.gen_u32();
151 let mut hi = mul_high_u32(r, n);
152 let mut lo = r.wrapping_mul(n);
153 if lo < n {
154 let t = n.wrapping_neg() % n;
155 while lo < t {
156 r = self.gen_u32();
157 hi = mul_high_u32(r, n);
158 lo = r.wrapping_mul(n);
159 }
160 }
161 hi
162 }
163
164 #[inline]
166 fn gen_mod_u64(&self, n: u64) -> u64 {
167 let mut r = self.gen_u64();
169 let mut hi = mul_high_u64(r, n);
170 let mut lo = r.wrapping_mul(n);
171 if lo < n {
172 let t = n.wrapping_neg() % n;
173 while lo < t {
174 r = self.gen_u64();
175 hi = mul_high_u64(r, n);
176 lo = r.wrapping_mul(n);
177 }
178 }
179 hi
180 }
181
182 #[inline]
184 fn gen_mod_u128(&self, n: u128) -> u128 {
185 let mut r = self.gen_u128();
187 let mut hi = mul_high_u128(r, n);
188 let mut lo = r.wrapping_mul(n);
189 if lo < n {
190 let t = n.wrapping_neg() % n;
191 while lo < t {
192 r = self.gen_u128();
193 hi = mul_high_u128(r, n);
194 lo = r.wrapping_mul(n);
195 }
196 }
197 hi
198 }
199}
200
201thread_local! {
202 static RNG: Rng = Rng(Cell::new({
203 let mut hasher = DefaultHasher::new();
204 Instant::now().hash(&mut hasher);
205 thread::current().id().hash(&mut hasher);
206 let hash = hasher.finish();
207 (hash << 1) | 1
208 }));
209}
210
211#[inline]
213fn mul_high_u32(a: u32, b: u32) -> u32 {
214 (((a as u64) * (b as u64)) >> 32) as u32
215}
216
217#[inline]
219fn mul_high_u64(a: u64, b: u64) -> u64 {
220 (((a as u128) * (b as u128)) >> 64) as u64
221}
222
223#[inline]
225fn mul_high_u128(a: u128, b: u128) -> u128 {
226 let a_lo = a as u64 as u128;
228 let a_hi = (a >> 64) as u64 as u128;
229 let b_lo = b as u64 as u128;
230 let b_hi = (b >> 64) as u64 as u128;
231 let carry = (a_lo * b_lo) >> 64;
232 let carry = ((a_hi * b_lo) as u64 as u128 + (a_lo * b_hi) as u64 as u128 + carry) >> 64;
233 a_hi * b_hi + ((a_hi * b_lo) >> 64) + ((a_lo * b_hi) >> 64) + carry
234}
235
236macro_rules! rng_integer {
237 ($t:tt, $gen:tt, $mod:tt, $doc:tt) => {
238 #[doc = $doc]
239 #[inline]
242 pub fn $t(&self, range: impl RangeBounds<$t>) -> $t {
243 let panic_empty_range = || {
244 panic!(
245 "empty range: {:?}..{:?}",
246 range.start_bound(),
247 range.end_bound()
248 )
249 };
250
251 let low = match range.start_bound() {
252 Bound::Unbounded => std::$t::MIN,
253 Bound::Included(&x) => x,
254 Bound::Excluded(&x) => x.checked_add(1).unwrap_or_else(panic_empty_range),
255 };
256
257 let high = match range.end_bound() {
258 Bound::Unbounded => std::$t::MAX,
259 Bound::Included(&x) => x,
260 Bound::Excluded(&x) => x.checked_sub(1).unwrap_or_else(panic_empty_range),
261 };
262
263 if low > high {
264 panic_empty_range();
265 }
266
267 if low == std::$t::MIN && high == std::$t::MAX {
268 self.$gen() as $t
269 } else {
270 let len = high.wrapping_sub(low).wrapping_add(1);
271 low.wrapping_add(self.$mod(len as _) as $t)
272 }
273 }
274 };
275}
276
277impl Rng {
278 #[inline]
280 pub fn new() -> Rng {
281 Rng::with_seed(
282 RNG.try_with(|rng| rng.u64(..))
283 .unwrap_or(0x4d595df4d0f33173),
284 )
285 }
286
287 #[inline]
289 pub fn with_seed(seed: u64) -> Self {
290 let rng = Rng(Cell::new(0));
291
292 rng.seed(seed);
293 rng
294 }
295
296 #[inline]
298 pub fn alphabetic(&self) -> char {
299 const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
300 let len = CHARS.len() as u8;
301 let i = self.u8(..len);
302 CHARS[i as usize] as char
303 }
304
305 #[inline]
307 pub fn alphanumeric(&self) -> char {
308 const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
309 let len = CHARS.len() as u8;
310 let i = self.u8(..len);
311 CHARS[i as usize] as char
312 }
313
314 #[inline]
316 pub fn bool(&self) -> bool {
317 self.u8(..) % 2 == 0
318 }
319
320 #[inline]
326 pub fn digit(&self, base: u32) -> char {
327 if base == 0 {
328 panic!("base cannot be zero");
329 }
330 if base > 36 {
331 panic!("base cannot be larger than 36");
332 }
333 let num = self.u8(..base as u8);
334 if num < 10 {
335 (b'0' + num) as char
336 } else {
337 (b'a' + num - 10) as char
338 }
339 }
340
341 pub fn f32(&self) -> f32 {
343 let b = 32;
344 let f = std::f32::MANTISSA_DIGITS - 1;
345 f32::from_bits((1 << (b - 2)) - (1 << f) + (self.u32(..) >> (b - f))) - 1.0
346 }
347
348 pub fn f64(&self) -> f64 {
350 let b = 64;
351 let f = std::f64::MANTISSA_DIGITS - 1;
352 f64::from_bits((1 << (b - 2)) - (1 << f) + (self.u64(..) >> (b - f))) - 1.0
353 }
354
355 rng_integer!(
356 i8,
357 gen_u32,
358 gen_mod_u32,
359 "Generates a random `i8` in the given range."
360 );
361
362 rng_integer!(
363 i16,
364 gen_u32,
365 gen_mod_u32,
366 "Generates a random `i16` in the given range."
367 );
368
369 rng_integer!(
370 i32,
371 gen_u32,
372 gen_mod_u32,
373 "Generates a random `i32` in the given range."
374 );
375
376 rng_integer!(
377 i64,
378 gen_u64,
379 gen_mod_u64,
380 "Generates a random `i64` in the given range."
381 );
382
383 rng_integer!(
384 i128,
385 gen_u128,
386 gen_mod_u128,
387 "Generates a random `i128` in the given range."
388 );
389
390 #[cfg(target_pointer_width = "16")]
391 rng_integer!(
392 isize,
393 gen_u32,
394 gen_mod_u32,
395 "Generates a random `isize` in the given range."
396 );
397 #[cfg(target_pointer_width = "32")]
398 rng_integer!(
399 isize,
400 gen_u32,
401 gen_mod_u32,
402 "Generates a random `isize` in the given range."
403 );
404 #[cfg(target_pointer_width = "64")]
405 rng_integer!(
406 isize,
407 gen_u64,
408 gen_mod_u64,
409 "Generates a random `isize` in the given range."
410 );
411
412 #[inline]
414 pub fn lowercase(&self) -> char {
415 const CHARS: &[u8] = b"abcdefghijklmnopqrstuvwxyz";
416 let len = CHARS.len() as u8;
417 let i = self.u8(..len);
418 CHARS[i as usize] as char
419 }
420
421 #[inline]
423 pub fn seed(&self, seed: u64) {
424 self.0.set(seed.wrapping_add(1442695040888963407));
425 self.gen_u32();
426 }
427
428 #[inline]
430 pub fn shuffle<T>(&self, slice: &mut [T]) {
431 for i in 1..slice.len() {
432 slice.swap(i, self.usize(..=i));
433 }
434 }
435
436 rng_integer!(
437 u8,
438 gen_u32,
439 gen_mod_u32,
440 "Generates a random `u8` in the given range."
441 );
442
443 rng_integer!(
444 u16,
445 gen_u32,
446 gen_mod_u32,
447 "Generates a random `u16` in the given range."
448 );
449
450 rng_integer!(
451 u32,
452 gen_u32,
453 gen_mod_u32,
454 "Generates a random `u32` in the given range."
455 );
456
457 rng_integer!(
458 u64,
459 gen_u64,
460 gen_mod_u64,
461 "Generates a random `u64` in the given range."
462 );
463
464 rng_integer!(
465 u128,
466 gen_u128,
467 gen_mod_u128,
468 "Generates a random `u128` in the given range."
469 );
470
471 #[cfg(target_pointer_width = "16")]
472 rng_integer!(
473 usize,
474 gen_u32,
475 gen_mod_u32,
476 "Generates a random `usize` in the given range."
477 );
478 #[cfg(target_pointer_width = "32")]
479 rng_integer!(
480 usize,
481 gen_u32,
482 gen_mod_u32,
483 "Generates a random `usize` in the given range."
484 );
485 #[cfg(target_pointer_width = "64")]
486 rng_integer!(
487 usize,
488 gen_u64,
489 gen_mod_u64,
490 "Generates a random `usize` in the given range."
491 );
492 #[cfg(target_pointer_width = "128")]
493 rng_integer!(
494 usize,
495 gen_u128,
496 gen_mod_u128,
497 "Generates a random `usize` in the given range."
498 );
499
500 #[inline]
502 pub fn uppercase(&self) -> char {
503 const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
504 let len = CHARS.len() as u8;
505 let i = self.u8(..len);
506 CHARS[i as usize] as char
507 }
508}
509
510#[inline]
512pub fn seed(seed: u64) {
513 RNG.with(|rng| rng.seed(seed))
514}
515
516#[inline]
518pub fn bool() -> bool {
519 RNG.with(|rng| rng.bool())
520}
521
522#[inline]
524pub fn alphabetic() -> char {
525 RNG.with(|rng| rng.alphabetic())
526}
527
528#[inline]
530pub fn alphanumeric() -> char {
531 RNG.with(|rng| rng.alphanumeric())
532}
533
534#[inline]
536pub fn lowercase() -> char {
537 RNG.with(|rng| rng.lowercase())
538}
539
540#[inline]
542pub fn uppercase() -> char {
543 RNG.with(|rng| rng.uppercase())
544}
545
546#[inline]
552pub fn digit(base: u32) -> char {
553 RNG.with(|rng| rng.digit(base))
554}
555
556#[inline]
558pub fn shuffle<T>(slice: &mut [T]) {
559 RNG.with(|rng| rng.shuffle(slice))
560}
561
562macro_rules! integer {
563 ($t:tt, $doc:tt) => {
564 #[doc = $doc]
565 #[inline]
568 pub fn $t(range: impl RangeBounds<$t>) -> $t {
569 RNG.with(|rng| rng.$t(range))
570 }
571 };
572}
573
574integer!(u8, "Generates a random `u8` in the given range.");
575integer!(i8, "Generates a random `i8` in the given range.");
576integer!(u16, "Generates a random `u16` in the given range.");
577integer!(i16, "Generates a random `i16` in the given range.");
578integer!(u32, "Generates a random `u32` in the given range.");
579integer!(i32, "Generates a random `i32` in the given range.");
580integer!(u64, "Generates a random `u64` in the given range.");
581integer!(i64, "Generates a random `i64` in the given range.");
582integer!(u128, "Generates a random `u128` in the given range.");
583integer!(i128, "Generates a random `i128` in the given range.");
584integer!(usize, "Generates a random `usize` in the given range.");
585integer!(isize, "Generates a random `isize` in the given range.");
586
587pub fn f32() -> f32 {
589 RNG.with(|rng| rng.f32())
590}
591
592pub fn f64() -> f64 {
594 RNG.with(|rng| rng.f64())
595}