1use crate::*;
2
3use std::sync::atomic::{AtomicU64, Ordering};
4
5const DEFAULT_INC: u64 = 1442695040888963407;
8const MULTIPLIER: u64 = 6364136223846793005;
9
10static STATE: AtomicU64 = AtomicU64::new(0);
11
12pub fn srand(seed: u64) {
15 STATE.store(0, Ordering::Relaxed);
16 rand();
17 let oldstate = STATE.load(Ordering::Relaxed);
18 STATE.store(oldstate.wrapping_add(seed), Ordering::Relaxed);
19 rand();
20}
21
22pub fn rand() -> u32 {
24 let oldstate: u64 = STATE.load(Ordering::Relaxed);
25 STATE.store(
26 oldstate.wrapping_mul(MULTIPLIER).wrapping_add(DEFAULT_INC),
27 Ordering::Relaxed,
28 );
29 let xorshifted: u32 = (((oldstate >> 18) ^ oldstate) >> 27) as u32;
30 let rot: u32 = (oldstate >> 59) as u32;
31 xorshifted.rotate_right(rot)
32}
33
34pub trait RandomRange {
35 fn gen_range(low: Self, high: Self) -> Self;
36}
37
38macro_rules! impl_random_range{
39 ($($ty:ty),*,)=>{
40 $(
41 impl RandomRange for $ty{
42 #[inline]
43 fn gen_range(low: Self, high: Self) -> Self {
44 let r = rand() as f64 / (u32::MAX as f64 + 1.0);
45 let r = low as f64 + (high as f64 - low as f64) * r;
46 r as Self
47 }
48 }
49 )*
50 }
51 }
52impl_random_range!(
53 f32, f64, u8, u16, u32, u64, usize, i8, i16, i32, i64, isize,
54);
55
56pub fn gen_range<T>(low: T, high: T) -> T
57where T: RandomRange {
58 T::gen_range(low, high)
59}
60
61pub struct VecChooseIter<'a, T> {
62 source: &'a Vec<T>,
63 indices: std::vec::IntoIter<usize>,
64}
65
66impl<'a, T> Iterator for VecChooseIter<'a, T> {
67 type Item = &'a T;
68
69 fn next(&mut self) -> Option<&'a T> {
70 self.indices.next().map(|ix| &self.source[ix])
71 }
72}
73
74pub trait ChooseRandom<T> {
75 fn shuffle(&mut self);
76 fn choose(&self) -> Option<&T>;
77 fn choose_mut(&mut self) -> Option<&mut T>;
78 fn choose_multiple(&self, _amount: usize) -> VecChooseIter<T>;
79}
80
81impl<T> ChooseRandom<T> for Vec<T> {
82 fn shuffle(&mut self) {
83 let mut fy = FisherYates::default();
84
85 fy.shuffle(self);
86 }
87
88 fn choose(&self) -> Option<&T> {
89 let ix = gen_range(0, self.len());
90 self.get(ix)
91 }
92
93 fn choose_mut(&mut self) -> Option<&mut T> {
94 let ix = gen_range(0, self.len());
95 self.get_mut(ix)
96 }
97
98 fn choose_multiple(&self, amount: usize) -> VecChooseIter<T> {
99 let mut indices =
100 (0..self.len()).enumerate().map(|(i, _)| i).collect::<Vec<usize>>();
101
102 indices.shuffle();
103 indices.resize(amount, 0);
104
105 VecChooseIter { source: self, indices: indices.into_iter() }
106 }
107}
108
109#[derive(Debug, Default)]
112pub struct FisherYates {
113 buffer: [u8; std::mem::size_of::<usize>()],
114}
115
116impl FisherYates {
117 pub fn shuffle<T>(&mut self, data: &mut [T]) {
118 for i in 1..data.len() {
119 let j = self.gen_range(i);
120 data.swap(i, j);
121 }
122 }
123}
124
125impl FisherYates {
126 fn gen_range(&mut self, top: usize) -> usize {
127 const USIZE_BYTES: usize = std::mem::size_of::<usize>();
128 let bit_width = USIZE_BYTES * 8 - top.leading_zeros() as usize;
129 let byte_count = (bit_width - 1) / 8 + 1;
130 loop {
131 for i in 0..byte_count {
132 self.buffer[i] = gen_range(0, 255);
133 }
134 let result = usize::from_le_bytes(self.buffer);
135 let result = result & ((1 << bit_width) - 1);
136 if result < top {
137 break result;
138 }
139 }
140 }
141}
142
143pub fn random_i32(min: i32, max: i32) -> i32 {
149 gen_range(min, max)
151}
152
153pub fn random_usize(min: usize, max: usize) -> usize {
154 gen_range(min, max)
156}
157
158pub fn flip_coin(p: f32) -> bool {
159 toss_coin(p)
160}
161
162pub fn coin_toss(p: f32) -> bool {
163 toss_coin(p)
164}
165
166pub fn toss_coin(p: f32) -> bool {
167 gen_range(0.0, 1.0) < p
168}
169
170pub fn random_angle() -> f32 {
171 gen_range(0.0, 2.0 * PI)
172}
173
174pub fn random_range(min: f32, max: f32) -> f32 {
175 gen_range(min, max)
176}
177
178pub fn random_dir() -> Vec2 {
179 let angle = gen_range(0.0, std::f32::consts::PI * 2.0);
180
181 Vec2::new(angle.cos(), angle.sin())
182}
183
184pub fn random_vec(min: f32, max: f32) -> Vec2 {
185 random_dir() * gen_range(min, max)
186}
187
188pub fn random_offset(radius: f32) -> Vec2 {
189 random_dir() * gen_range(0.0, radius)
190}
191
192pub fn random_circle(radius: f32) -> Vec2 {
193 random_offset(radius)
194}
195
196pub fn random_box(center: Vec2, size: Vec2) -> Vec2 {
197 center +
198 vec2(
199 gen_range(-size.x, size.x) / 2.0,
200 gen_range(-size.y, size.y) / 2.0,
201 )
202}
203
204pub fn random_around(position: Vec2, min: f32, max: f32) -> Vec2 {
205 position + random_vec(min, max)
206}
207
208pub fn random() -> f32 {
209 gen_range(0.0, 1.0)
210}
211
212#[test]
213fn crash_poop_gen_range() {
214 let things = vec![1, 2, 3];
215
216 let mut i: usize = 0;
217
218 for _ in 0..1000000000usize {
219 i += 1;
220 if things.choose().is_none() {
221 panic!("EXITING AFTER {} ITERATIONS", i);
222 }
223 }
224}