1#![cfg_attr(docsrs, feature(doc_cfg))]
2
3#[macro_use]
4extern crate log;
5
6
7#[cfg(feature = "bag")]
8#[cfg_attr(docsrs, doc(cfg(feature = "bag")))]
9pub mod weighted_bag;
10
11#[cfg(feature = "bag")]
12#[cfg_attr(docsrs, doc(cfg(feature = "bag")))]
13pub use weighted_bag::WeightedBag;
14
15struct Storage {
16 seed: u64,
17 rng: rand::rngs::SmallRng,
18}
19
20std::thread_local! {
21 static STORAGE: std::cell::RefCell<Storage> = std::cell::RefCell::new({
22 use {
23 rand::{rngs::SmallRng, Rng, SeedableRng as _},
24 };
25
26 let seed = SmallRng::from_entropy().gen::<u64>();
28
29 trace!("Initializing with seed: {seed}");
30
31 Storage {
32 seed,
33 rng: SmallRng::seed_from_u64(seed),
35 }
36
37
38 })
39}
40
41pub fn set_seed(seed: u64) {
44 use rand::{rngs::SmallRng, SeedableRng};
45 STORAGE.with_borrow_mut(|storage| {
46 storage.seed = seed;
47
48 storage.rng = SmallRng::seed_from_u64(seed);
49 });
50}
51
52pub fn seed() -> u64 {
54 STORAGE.with_borrow(|storage| storage.seed)
55}
56
57pub fn get<T>(x: T, y: T) -> T
61where
62 T: rand::distributions::uniform::SampleUniform
63 + std::cmp::PartialEq
64 + std::cmp::PartialOrd
65 + std::fmt::Debug,
66{
67 use rand::Rng as _;
68
69 if x == y {
70 return x;
72 };
73
74 STORAGE.with_borrow_mut(|storage| storage.rng.gen_range(x..y))
75}
76
77pub fn get_inc<T>(x: T, y: T) -> T
81where
82 T: rand::distributions::uniform::SampleUniform
84 + std::cmp::PartialEq
85 + std::fmt::Debug
86 + std::cmp::PartialOrd,
87{
88 use rand::Rng as _;
89
90 if x == y {
91 return x;
93 };
94
95 STORAGE.with_borrow_mut(|storage| storage.rng.gen_range(x..=y))
96}
97
98pub fn conflip() -> bool {
102 use rand::Rng as _;
103
104 STORAGE.with_borrow_mut(|storage| storage.rng.gen_bool(0.5))
105}
106
107pub fn str(len: usize) -> String {
109 use rand::distributions::{Alphanumeric, DistString};
110
111 STORAGE.with_borrow_mut(|storage| Alphanumeric.sample_string(&mut storage.rng, len))
112}
113
114pub fn pick<T: std::fmt::Debug>(input: &[T]) -> &T {
118 use rand::seq::SliceRandom;
119
120 if input.is_empty() {
121 panic!("Can't sample empty slice ")
122 }
123
124 STORAGE.with_borrow_mut(|storage| input.choose(&mut storage.rng).unwrap())
125}