1#![cfg_attr(not(test), no_std)]
2const SQ5_BIT_NOISE1: u32 = 0xd2a80a3f; const SQ5_BIT_NOISE2: u32 = 0xa884f197; const SQ5_BIT_NOISE3: u32 = 0x6C736F4B; const SQ5_BIT_NOISE4: u32 = 0xB79F3ABB; const SQ5_BIT_NOISE5: u32 = 0x1b56c4f5; const PRIME1: i32 = 198491317; const PRIME2: i32 = 6542989; const PRIME3: i32 = 357239; #[inline]
13pub fn squirrel_noise5(index: u32, seed: u32) -> u32 {
14 let mut mangled_bits = index;
15
16 mangled_bits = mangled_bits.wrapping_mul(SQ5_BIT_NOISE1);
17 mangled_bits = mangled_bits.wrapping_add(seed);
18 mangled_bits ^= mangled_bits >> 9;
19 mangled_bits = mangled_bits.wrapping_add(SQ5_BIT_NOISE2);
20 mangled_bits ^= mangled_bits >> 11;
21 mangled_bits = mangled_bits.wrapping_mul(SQ5_BIT_NOISE3);
22 mangled_bits ^= mangled_bits >> 13;
23 mangled_bits = mangled_bits.wrapping_add(SQ5_BIT_NOISE4);
24 mangled_bits ^= mangled_bits >> 15;
25 mangled_bits = mangled_bits.wrapping_mul(SQ5_BIT_NOISE5);
26 mangled_bits ^= mangled_bits >> 17;
27
28 mangled_bits
29}
30
31#[inline]
32fn linearize_2d(x: i32, y: i32) -> i32 {
33 x.wrapping_add(y.wrapping_mul(PRIME1))
34}
35#[inline]
36fn linearize_3d(x: i32, y: i32, z: i32) -> i32 {
37 x.wrapping_add(y.wrapping_mul(PRIME1))
38 .wrapping_add(z.wrapping_mul(PRIME2))
39}
40#[inline]
41fn linearize_4d(x: i32, y: i32, z: i32, w: i32) -> i32 {
42 x.wrapping_add(y.wrapping_mul(PRIME1))
43 .wrapping_add(z.wrapping_mul(PRIME2))
44 .wrapping_add(w.wrapping_mul(PRIME3))
45}
46#[inline]
50pub fn u32_1d(index: i32, seed: i32) -> u32 {
51 squirrel_noise5(index as u32, seed as u32)
52}
53#[inline]
54pub fn u32_2d(x: i32, y: i32, seed: i32) -> u32 {
55 squirrel_noise5(linearize_2d(x, y) as u32, seed as u32)
56}
57#[inline]
58pub fn u32_3d(x: i32, y: i32, z: i32, seed: i32) -> u32 {
59 squirrel_noise5(linearize_3d(x, y, z) as u32, seed as u32)
60}
61#[inline]
62pub fn u32_4d(x: i32, y: i32, z: i32, w: i32, seed: i32) -> u32 {
63 squirrel_noise5(linearize_4d(x, y, z, w) as u32, seed as u32)
64}
65
66#[inline]
70pub fn u32_range_1d(min: u32, max: u32, index: i32, seed: i32) -> u32 {
71 min + ((max - min) as f32 * f32_zero_to_one_1d(index, seed)) as u32
72}
73#[inline]
74pub fn u32_range_2d(min: u32, max: u32, x: i32, y: i32, seed: i32) -> u32 {
75 min + ((max - min) as f32 * f32_zero_to_one_2d(x, y, seed)) as u32
76}
77#[inline]
78pub fn u32_range_3d(min: u32, max: u32, x: i32, y: i32, z: i32, seed: i32) -> u32 {
79 min + ((max - min) as f32 * f32_zero_to_one_3d(x, y, z, seed)) as u32
80}
81#[inline]
82pub fn u32_range_4d(min: u32, max: u32, x: i32, y: i32, z: i32, w: i32, seed: i32) -> u32 {
83 min + ((max - min) as f32 * f32_zero_to_one_4d(x, y, z, w, seed)) as u32
84}
85
86#[inline]
90pub fn u32_cap_1d(max: u32, index: i32, seed: i32) -> u32 {
91 (max as f32 * f32_zero_to_one_1d(index, seed)) as u32
92}
93#[inline]
94pub fn u32_cap_2d(max: u32, x: i32, y: i32, seed: i32) -> u32 {
95 (max as f32 * f32_zero_to_one_2d(x, y, seed)) as u32
96}
97#[inline]
98pub fn u32_cap_3d(max: u32, x: i32, y: i32, z: i32, seed: i32) -> u32 {
99 (max as f32 * f32_zero_to_one_3d(x, y, z, seed)) as u32
100}
101#[inline]
102pub fn u32_cap_4d(max: u32, x: i32, y: i32, z: i32, w: i32, seed: i32) -> u32 {
103 (max as f32 * f32_zero_to_one_4d(x, y, z, w, seed)) as u32
104}
105
106#[inline]
110pub fn u64_1d(index: i32, seed: i32) -> u64 {
111 let fst = u32_1d(index, seed);
112 let snd = u32_1d(index, fst as i32);
113 ((fst as u64) << 32) | snd as u64
114}
115#[inline]
116pub fn u64_2d(x: i32, y: i32, seed: i32) -> u64 {
117 u64_1d(linearize_2d(x, y), seed)
118}
119#[inline]
120pub fn u64_3d(x: i32, y: i32, z: i32, seed: i32) -> u64 {
121 u64_1d(linearize_3d(x, y, z), seed)
122}
123#[inline]
124pub fn u64_4d(x: i32, y: i32, z: i32, w: i32, seed: i32) -> u64 {
125 u64_1d(linearize_4d(x, y, z, w), seed)
126}
127
128#[inline]
132pub fn i32_1d(index: i32, seed: i32) -> i32 {
133 u32_1d(index, seed) as i32
134}
135#[inline]
136pub fn i32_2d(x: i32, y: i32, seed: i32) -> i32 {
137 u32_2d(x, y, seed) as i32
138}
139#[inline]
140pub fn i32_3d(x: i32, y: i32, z: i32, seed: i32) -> i32 {
141 u32_3d(x, y, z, seed) as i32
142}
143#[inline]
144pub fn i32_4d(x: i32, y: i32, z: i32, w: i32, seed: i32) -> i32 {
145 u32_4d(x, y, z, w, seed) as i32
146}
147
148#[inline]
152pub fn i32_range_1d(min: i32, max: i32, index: i32, seed: i32) -> i32 {
153 min + ((max - min) as f32 * f32_zero_to_one_1d(index, seed)) as i32
154}
155#[inline]
156pub fn i32_range_2d(min: i32, max: i32, x: i32, y: i32, seed: i32) -> i32 {
157 min + ((max - min) as f32 * f32_zero_to_one_2d(x, y, seed)) as i32
158}
159#[inline]
160pub fn i32_range_3d(min: i32, max: i32, x: i32, y: i32, z: i32, seed: i32) -> i32 {
161 min + ((max - min) as f32 * f32_zero_to_one_3d(x, y, z, seed)) as i32
162}
163#[inline]
164pub fn i32_range_4d(min: i32, max: i32, x: i32, y: i32, z: i32, w: i32, seed: i32) -> i32 {
165 min + ((max - min) as f32 * f32_zero_to_one_4d(x, y, z, w, seed)) as i32
166}
167
168#[inline]
172pub fn i32_cap_1d(max: i32, index: i32, seed: i32) -> i32 {
173 (max as f32 * f32_zero_to_one_1d(index, seed)) as i32
174}
175#[inline]
176pub fn i32_cap_2d(max: i32, x: i32, y: i32, seed: i32) -> i32 {
177 (max as f32 * f32_zero_to_one_2d(x, y, seed)) as i32
178}
179#[inline]
180pub fn i32_cap_3d(max: i32, x: i32, y: i32, z: i32, seed: i32) -> i32 {
181 (max as f32 * f32_zero_to_one_3d(x, y, z, seed)) as i32
182}
183#[inline]
184pub fn i32_cap_4d(max: i32, x: i32, y: i32, z: i32, w: i32, seed: i32) -> i32 {
185 (max as f32 * f32_zero_to_one_4d(x, y, z, w, seed)) as i32
186}
187
188#[inline]
192pub fn i64_1d(index: i32, seed: i32) -> i64 {
193 u64_1d(index, seed) as i64
194}
195#[inline]
196pub fn i64_2d(x: i32, y: i32, seed: i32) -> i64 {
197 u64_2d(x, y, seed) as i64
198}
199#[inline]
200pub fn i64_3d(x: i32, y: i32, z: i32, seed: i32) -> i64 {
201 u64_3d(x, y, z, seed) as i64
202}
203#[inline]
204pub fn i64_4d(x: i32, y: i32, z: i32, w: i32, seed: i32) -> i64 {
205 u64_4d(x, y, z, w, seed) as i64
206}
207
208#[inline]
212pub fn f32_range_1d(min: f32, max: f32, index: i32, seed: i32) -> f32 {
213 min + (max - min) * f32_zero_to_one_1d(index, seed)
214}
215#[inline]
216pub fn f32_range_2d(min: f32, max: f32, x: i32, y: i32, seed: i32) -> f32 {
217 min + (max - min) * f32_zero_to_one_2d(x, y, seed)
218}
219#[inline]
220pub fn f32_range_3d(min: f32, max: f32, x: i32, y: i32, z: i32, seed: i32) -> f32 {
221 min + (max - min) * f32_zero_to_one_3d(x, y, z, seed)
222}
223#[inline]
224pub fn f32_range_4d(min: f32, max: f32, x: i32, y: i32, z: i32, w: i32, seed: i32) -> f32 {
225 min + (max - min) * f32_zero_to_one_4d(x, y, z, w, seed)
226}
227
228#[inline]
232pub fn f32_zero_to_one_1d(index: i32, seed: i32) -> f32 {
233 (u32_1d(index, seed) as f64 / u32::MAX as f64) as f32
234}
235#[inline]
236pub fn f32_zero_to_one_2d(x: i32, y: i32, seed: i32) -> f32 {
237 (u32_2d(x, y, seed) as f64 / u32::MAX as f64) as f32
238}
239#[inline]
240pub fn f32_zero_to_one_3d(x: i32, y: i32, z: i32, seed: i32) -> f32 {
241 (u32_3d(x, y, z, seed) as f64 / u32::MAX as f64) as f32
242}
243#[inline]
244pub fn f32_zero_to_one_4d(x: i32, y: i32, z: i32, w: i32, seed: i32) -> f32 {
245 (u32_4d(x, y, z, w, seed) as f64 / u32::MAX as f64) as f32
246}
247
248#[inline]
252pub fn f32_neg_one_to_one_1d(index: i32, seed: i32) -> f32 {
253 (i32_1d(index, seed) as f64 / i32::MAX as f64) as f32
254}
255#[inline]
256pub fn f32_neg_one_to_one_2d(x: i32, y: i32, seed: i32) -> f32 {
257 (i32_2d(x, y, seed) as f64 / i32::MAX as f64) as f32
258}
259#[inline]
260pub fn f32_neg_one_to_one_3d(x: i32, y: i32, z: i32, seed: i32) -> f32 {
261 (i32_3d(x, y, z, seed) as f64 / i32::MAX as f64) as f32
262}
263#[inline]
264pub fn f32_neg_one_to_one_4d(x: i32, y: i32, z: i32, w: i32, seed: i32) -> f32 {
265 (i32_4d(x, y, z, w, seed) as f64 / i32::MAX as f64) as f32
266}
267
268use core::cell::Cell;
269
270#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
271pub struct SquirrelRng {
272 pub seed: Cell<i32>,
273 pub index: Cell<i32>,
274}
275
276impl Default for SquirrelRng {
277 fn default() -> Self {
278 SquirrelRng::from_pos_and_seed(0, 0)
279 }
280}
281
282#[cfg(feature = "rand")]
283pub use rand::{Rng, RngCore, SeedableRng};
284
285#[cfg(feature = "rand")]
286impl SquirrelRng {
287 pub fn new() -> Self {
288 SquirrelRng {
289 seed: Cell::from(rand::rng().random::<i32>()),
290 index: Cell::default(),
291 }
292 }
293
294 pub fn with_seed(seed: i32) -> Self {
295 Self {
296 index: Cell::from(0),
297 seed: Cell::from(seed),
298 }
299 }
300
301 pub fn with_position(self, index: i32) -> Self {
302 Self {
303 index: Cell::from(index),
304 ..self
305 }
306 }
307}
308
309#[cfg(feature = "rand")]
310impl RngCore for SquirrelRng {
311 #[inline]
312 fn next_u32(&mut self) -> u32 {
313 self.u32()
314 }
315
316 #[inline]
317 fn next_u64(&mut self) -> u64 {
318 self.u64()
319 }
320
321 #[inline]
322 fn fill_bytes(&mut self, dest: &mut [u8]) {
323 fill_bytes_via_next(self, dest);
324 }
325}
326
327#[cfg(feature = "rand")]
328fn fill_bytes_via_next<R: RngCore + ?Sized>(rng: &mut R, dest: &mut [u8]) {
329 let mut left = dest;
330 while left.len() >= 8 {
331 let (l, r) = { left }.split_at_mut(8);
332 left = r;
333 let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
334 l.copy_from_slice(&chunk);
335 }
336 let n = left.len();
337 if n > 4 {
338 let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
339 left.copy_from_slice(&chunk[..n]);
340 } else if n > 0 {
341 let chunk: [u8; 4] = rng.next_u32().to_le_bytes();
342 left.copy_from_slice(&chunk[..n]);
343 }
344}
345
346#[cfg(feature = "rand")]
347impl SeedableRng for SquirrelRng {
348 type Seed = [u8; 4];
349
350 fn from_seed(seed: Self::Seed) -> Self {
351 Self::with_seed(i32::from_le_bytes(seed))
352 }
353}
354
355impl SquirrelRng {
356 #[inline]
357 pub fn from_pos_and_seed(seed: i32, index: i32) -> Self {
358 SquirrelRng {
359 seed: Cell::from(seed),
360 index: Cell::from(index),
361 }
362 }
363 #[inline]
364 pub fn u32(&self) -> u32 {
365 let res = u32_1d(self.index.get(), self.seed.get());
366 self.index.update(|x| x.wrapping_add(1));
367 res
368 }
369 #[inline]
370 pub fn u32_range(&self, min: u32, max: u32) -> u32 {
371 let res = u32_range_1d(min, max, self.index.get(), self.seed.get());
372 self.index.update(|x| x.wrapping_add(1));
373 res
374 }
375 #[inline]
376 pub fn u32_cap(&self, max: u32) -> u32 {
377 let res = u32_cap_1d(max, self.index.get(), self.seed.get());
378 self.index.update(|x| x.wrapping_add(1));
379 res
380 }
381 #[inline]
382 pub fn u64(&self) -> u64 {
383 let res = u64_1d(self.index.get(), self.seed.get());
384 self.index.update(|x| x.wrapping_add(1));
385 res
386 }
387
388 #[inline]
389 pub fn i32(&self) -> i32 {
390 let res = i32_1d(self.index.get(), self.seed.get());
391 self.index.update(|x| x.wrapping_add(1));
392 res
393 }
394 #[inline]
395 pub fn i32_range(&self, min: i32, max: i32) -> i32 {
396 let res = i32_range_1d(min, max, self.index.get(), self.seed.get());
397 self.index.update(|x| x.wrapping_add(1));
398 res
399 }
400 #[inline]
401 pub fn i32_cap(&self, max: i32) -> i32 {
402 let res = i32_cap_1d(max, self.index.get(), self.seed.get());
403 self.index.update(|x| x.wrapping_add(1));
404 res
405 }
406 #[inline]
407 pub fn i64(&self) -> i64 {
408 let res = i64_1d(self.index.get(), self.seed.get());
409 self.index.update(|x| x.wrapping_add(1));
410 res
411 }
412
413 #[inline]
414 pub fn usize(&self, max: usize) -> usize {
415 (self.f32_zero_to_one() * max as f32) as usize
416 }
417 #[inline]
418 pub fn usize_range(&self, min: usize, max: usize) -> usize {
419 min + self.usize(max - min)
420 }
421
422 #[inline]
423 pub fn u8(&self) -> u8 {
424 (self.f32_zero_to_one() * 256_f32) as u8
425 }
426 #[inline]
427 pub fn u8_cap(&self, max: u8) -> u8 {
428 (self.f32_zero_to_one() * max as f32) as u8
429 }
430 #[inline]
431 pub fn u8_range(&self, min: u8, max: u8) -> u8 {
432 min + self.u8_cap(max - min)
433 }
434
435 #[inline]
436 pub fn bool(&self) -> bool {
437 self.i32() < 0
438 }
439
440 #[inline]
441 pub fn f32_range(&self, min: f32, max: f32) -> f32 {
442 min + (max - min) * self.f32_zero_to_one()
443 }
444 #[inline]
445 pub fn f32_zero_to_one(&self) -> f32 {
446 let res = f32_zero_to_one_1d(self.index.get(), self.seed.get());
447 self.index.update(|x| x.wrapping_add(1));
448 res
449 }
450 #[inline]
451 pub fn f32_neg_one_to_one(&self) -> f32 {
452 let res = f32_neg_one_to_one_1d(self.index.get(), self.seed.get());
453 self.index.update(|x| x.wrapping_add(1));
454 res
455 }
456
457 #[inline]
458 pub fn shuffle<T>(&self, slice: &mut [T]) {
459 for n in 1..slice.len() {
460 slice.swap(n, self.usize(n + 1));
461 }
462 }
463
464 #[inline]
465 pub fn jump(&self, amount: i32) {
466 self.index.update(|x| x.wrapping_add(amount));
467 }
468 #[inline]
469 pub fn goto(&self, index: i32) {
470 self.index.set(index);
471 }
472 #[inline]
473 pub fn seed(&self, seed: i32) {
474 self.seed.set(seed);
475 }
476}
477
478#[cfg(test)]
479mod tests {
480 use crate::u32_1d;
481
482 const TEST_CASES: &[(i32, i32, u32)] = &[
483 (0, 0, 0x16791E00),
484 (1, 0, 0xC895CB1D),
485 (-1, 0, 0xFAF16D54),
486 (123, 456, 0x0771723F),
487 (-123, 456, 0x09B50E33),
488 (2147483647, -1, 0x1697A56A),
489 (-2147483648, 0, 0x679CCD13),
490 (42, 1337, 0x968DE4C9),
491 (9999, 9999, 0x173A5069),
492 (314159, 271828, 0xEFA3B8DC),
493 ];
494 #[test]
495 fn known_values() {
496 for &(index, seed, expected) in TEST_CASES {
497 let result = u32_1d(index, seed);
498 assert_eq!(
499 result, expected,
500 "Failed for index: {index}, seed: {seed}. Expected: {expected:#010X}, Got: {result:#010X}",
501 );
502 }
503 }
504}