squirrel_noise5/
lib.rs

1#![cfg_attr(not(test), no_std)]
2const SQ5_BIT_NOISE1: u32 = 0xd2a80a3f; // 11010010101010000000101000111111
3const SQ5_BIT_NOISE2: u32 = 0xa884f197; // 10101000100001001111000110010111
4const SQ5_BIT_NOISE3: u32 = 0x6C736F4B; // 01101100011100110110111101001011
5const SQ5_BIT_NOISE4: u32 = 0xB79F3ABB; // 10110111100111110011101010111011
6const SQ5_BIT_NOISE5: u32 = 0x1b56c4f5; // 00011011010101101100010011110101
7
8const PRIME1: i32 = 198491317; // Large prime number with non-boring bits
9const PRIME2: i32 = 6542989; // Large prime number with distinct and non-boring bits
10const PRIME3: i32 = 357239; // Large prime number with distinct and non-boring bits
11
12#[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//-------------------------------
47//      u32
48//-------------------------------
49#[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//-------------------------------
67//      u32_range
68//-------------------------------
69#[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//-------------------------------
87//      u32_cap
88//-------------------------------
89#[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//-------------------------------
107//      u64
108//-------------------------------
109#[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//-------------------------------
129//      i32
130//-------------------------------
131#[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//-------------------------------
149//      i32_range
150//-------------------------------
151#[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//-------------------------------
169//      i32_cap
170//-------------------------------
171#[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//-------------------------------
189//      i64
190//-------------------------------
191#[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//-------------------------------
209//      f32_range
210//-------------------------------
211#[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//-------------------------------
229//      f32_01
230//-------------------------------
231#[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//-------------------------------
249//      f32_-11
250//-------------------------------
251#[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}