1pub mod sq3 {
2 use std::time::Instant;
3 use std::cell::Cell;
4 use std::collections::hash_map::DefaultHasher;
5 use std::hash::{Hash, Hasher};
6 use std::thread;
7
8 thread_local! {
9 static RNG: Rng = Rng::new({
10 let mut hasher = DefaultHasher::new();
11 Instant::now().hash(&mut hasher);
12 thread::current().id().hash(&mut hasher);
13 let hash = hasher.finish();
14 ((hash << 1) | 1) as u32
15 });
16 }
17
18 pub struct Rng {
19 position: Cell<u32>,
20 _seed: Cell<u32>
21 }
22
23 impl Rng {
24 pub fn new(seed: u32) -> Self {
25 Self{
26 position: Cell::new(0),
27 _seed: Cell::new(seed)
28 }
29 }
30
31 #[inline]
32 pub fn seed(&self, value: u32) {
33 self._seed.set(value);
34 }
35
36 #[inline]
37 pub fn rand(&self) -> f32 {
38 let new_pos = self.position.get() + 1;
39 self.position.set(new_pos);
40 normalized(new_pos, self._seed.get())
41 }
42
43 #[inline]
44 pub fn bool(&self) -> bool {
45 self.rand() < 0.5
46 }
47
48 #[inline]
49 pub fn range_i32(&self, min: i32, max: i32) -> i32 {
50 (self.rand() * (max as f32 - min as f32)) as i32 + min
51 }
52
53 #[inline]
54 pub fn range_f32(&self, min: f32, max: f32) -> f32 {
55 (self.rand() * (max - min)) + min
56 }
57
58 #[inline]
59 pub fn range_u8(&self, min: u8, max: u8) -> u8 {
60 (self.rand() * (max as f32 - min as f32)) as u8 + min
61 }
62
63 #[inline]
64 pub fn range_usize(&self, min: usize, max: usize) -> usize {
65 (self.rand() * (max as f32 - min as f32)) as usize + min
66 }
67
68 #[inline]
69 pub fn range_u32(&self, min: u32, max: u32) -> u32 {
70 (self.rand() * (max as f32 - min as f32)) as u32 + min
71 }
72
73 #[inline]
74 pub fn u8(&self, max: u8) -> u8 {
75 (self.rand() * max as f32) as u8
76 }
77
78 #[inline]
79 pub fn usize(&self, max: usize) -> usize {
80 (self.rand() * max as f32) as usize
81 }
82
83 #[inline]
84 pub fn u32(&self, max: u32) -> u32 {
85 (self.rand() * max as f32) as u32
86 }
87
88 #[inline]
89 pub fn shuffle<T>(&self, slice: &mut [T]) {
90 for n in 1..slice.len() {
91 slice.swap(n, self.usize(n + 1));
92 }
93 }
94 }
95
96 #[inline]
98 pub fn rand() -> f32 {
99 RNG.with(|rng| rng.rand())
100 }
101
102 #[inline]
103 pub fn bool() -> bool {
104 RNG.with(|rng| rng.bool())
105 }
106
107 #[inline]
108 pub fn range_i32(min: i32, max: i32) -> i32 {
109 RNG.with(|rng| rng.range_i32(min, max))
110 }
111
112 #[inline]
113 pub fn range_f32(min: f32, max: f32) -> f32 {
114 RNG.with(|rng| rng.range_f32(min, max))
115 }
116
117 #[inline]
118 pub fn range_u8(min: u8, max: u8) -> u8 {
119 RNG.with(|rng| rng.range_u8(min, max))
120 }
121
122 #[inline]
123 pub fn range_usize(min: usize, max: usize) -> usize {
124 RNG.with(|rng| rng.range_usize(min, max))
125 }
126
127 #[inline]
128 pub fn range_u32(min: u32, max: u32) -> u32 {
129 RNG.with(|rng| rng.range_u32(min, max))
130 }
131
132 #[inline]
133 pub fn u8(max: u8) -> u8 {
134 RNG.with(|rng| rng.u8(max))
135 }
136
137 #[inline]
138 pub fn usize(max: usize) -> usize {
139 RNG.with(|rng| rng.usize(max))
140 }
141
142 #[inline]
143 pub fn u32(max: u32) -> u32 {
144 RNG.with(|rng| rng.u32(max))
145 }
146
147 #[inline]
148 pub fn seed(seed: u32) {
149 RNG.with(|rng| rng.seed(seed))
150 }
151
152 #[inline]
153 pub fn shuffle<T>(slice: &mut [T]) {
154 RNG.with(|rng| rng.shuffle(slice))
155 }
156
157 pub fn squirrel3(position: u32, seed: u32) -> u32 {
161 let mut mangled = position.wrapping_mul(0xB5297A4D);
162 mangled = mangled.wrapping_add(seed);
163 mangled = mangled ^ (mangled >> 8);
164 mangled = mangled.wrapping_add(0x68E31DA4);
165 mangled = mangled ^ (mangled << 8);
166 mangled = mangled.wrapping_mul(0x1B56C4E9);
167 mangled = mangled ^ (mangled >> 8);
168 mangled
169 }
170
171 #[inline]
172 pub fn normalized(position: u32, seed: u32) -> f32 {
173 squirrel3(position, seed) as f32 / u32::MAX as f32
174 }
175
176 #[inline]
177 pub fn noise1d(position: u32) -> f32 {
178 normalized(position, 0)
179 }
180
181 #[inline]
182 pub fn noise2d(x: u32, y: u32) -> f32 {
183 normalized(x.wrapping_add(y.wrapping_mul(198491317)), 0)
184 }
185
186 #[inline]
187 pub fn noise3d(x: u32, y: u32, z: u32) -> f32 {
188 normalized(x.wrapping_add(y.wrapping_mul(198491317)).wrapping_add(z.wrapping_mul(6542989)), 0)
189 }
190}