Skip to main content

fish_oxide/
custom_rand.rs

1use rand::{seq::SliceRandom, thread_rng, Rng};
2use std::{
3    f64::consts::PI,
4    sync::{
5        atomic::{AtomicU64, Ordering},
6        LazyLock,
7    },
8};
9
10static JSR: AtomicU64 = AtomicU64::new(0x5EED);
11
12pub fn str_to_seed(str: String) -> u32 {
13    let mut n = 1;
14    for (i, c) in str.chars().enumerate() {
15        let x = (c as u32) + 1;
16        n ^= x << (7 + (i % 5));
17        // if (i % 2){
18        n ^= n << 17;
19        n ^= n >> 13;
20        n ^= n << 5;
21        // }
22        n = (n >> 0) % 4294967295;
23    }
24    return n;
25}
26
27pub fn rand() -> f64 {
28    return thread_rng().gen();
29    // let mut reg = JSR.load(Ordering::Acquire);
30    // reg ^= reg << 17;
31    // reg ^= reg >> 13;
32    // reg ^= reg << 5;
33    // JSR.store(reg, Ordering::Release);
34    // return (reg >> 0) as f64 / 4294967295.;
35}
36
37pub fn seed_rand(seed: u64) {
38    JSR.store(seed, Ordering::SeqCst);
39}
40
41const PERLIN_YWRAPB: u64 = 4;
42const PERLIN_YWRAP: u64 = 1 << PERLIN_YWRAPB;
43const PERLIN_ZWRAPB: u64 = 8;
44const PERLIN_ZWRAP: u64 = 1 << PERLIN_ZWRAPB;
45const PERLIN_SIZE: u64 = 4095;
46const PERLIN_OCTAVES: u64 = 4;
47const PERLIN_AMP_FALLOFF: f64 = 0.5;
48pub fn scaled_cosine(i: f64) -> f64 {
49    return 0.5 * (1.0 - f64::cos(i * PI));
50}
51
52static PERLIN: LazyLock<Vec<f64>> = LazyLock::new(|| (0..=PERLIN_SIZE).map(|_| rand()).collect());
53
54pub fn noise(mut x: f64, y_opt: Option<f64>, z_opt: Option<f64>) -> f64 {
55    x = x.abs();
56    let y = y_opt.unwrap_or(0.).abs();
57    let z = z_opt.unwrap_or(0.).abs();
58
59    let mut xi = x.floor() as u64;
60    let mut yi = y.floor() as u64;
61    let mut zi = z.floor() as u64;
62
63    let mut xf = x - (xi as f64);
64    let mut yf = y - (yi as f64);
65    let mut zf = z - (zi as f64);
66
67    let mut rxf;
68    let mut ryf;
69
70    let mut r = 0.;
71    let mut ampl = 0.5;
72
73    let mut n1;
74    let mut n2;
75    let mut n3;
76    for _ in 0..PERLIN_OCTAVES {
77        let mut of = xi + ((yi) << PERLIN_YWRAPB) + ((zi) << PERLIN_ZWRAPB);
78        rxf = scaled_cosine(xf);
79        ryf = scaled_cosine(yf);
80        n1 = PERLIN[(of & PERLIN_SIZE) as usize];
81        n1 += rxf * (PERLIN[((of + 1) & PERLIN_SIZE) as usize] - n1);
82        n2 = PERLIN[((of + PERLIN_YWRAP) & PERLIN_SIZE) as usize];
83        n2 += rxf * (PERLIN[((of + PERLIN_YWRAP + 1) & PERLIN_SIZE) as usize] - n2);
84        n1 += ryf * (n2 - n1);
85        of += PERLIN_ZWRAP;
86        n2 = PERLIN[(of & PERLIN_SIZE) as usize];
87        n2 += rxf * (PERLIN[((of + 1) & PERLIN_SIZE) as usize] - n2);
88        n3 = PERLIN[((of + PERLIN_YWRAP) & PERLIN_SIZE) as usize];
89        n3 += rxf * (PERLIN[((of + PERLIN_YWRAP + 1) & PERLIN_SIZE) as usize] - n3);
90        n2 += ryf * (n3 - n2);
91        n1 += scaled_cosine(zf) * (n2 - n1);
92        r += n1 * ampl;
93        ampl *= PERLIN_AMP_FALLOFF;
94        xi <<= 1;
95        xf *= 2.;
96        yi <<= 1;
97        yf *= 2.;
98        zi <<= 1;
99        zf *= 2.;
100
101        if xf >= 1.0 {
102            xi += 1;
103            xf -= 1.;
104        }
105        if yf >= 1.0 {
106            yi += 1;
107            yf -= 1.;
108        }
109        if zf >= 1.0 {
110            zi += 1;
111            zf -= 1.;
112        }
113    }
114    return r;
115}
116
117pub fn choice<'a, T>(opts: &'a [T], percs_opt: Option<&[f64]>) -> &'a T {
118    return opts.choose(&mut thread_rng()).unwrap();
119    let default_percs = opts.iter().map(|_| 1.).collect::<Vec<_>>();
120    let percs = percs_opt.unwrap_or(&default_percs);
121    let mut s = percs.iter().sum();
122    let mut r = rand() * s;
123    s = 0.;
124    for i in 0..percs.len() {
125        s += percs[i];
126        if r <= s {
127            return &opts[i];
128        }
129    }
130    unreachable!();
131}
132
133pub fn rndtri(a: i64, b: i64, c: i64) -> i64 {
134    let s0 = (b - a) / 2;
135    let s1 = (c - b) / 2;
136    let s = s0 + s1;
137    let r = rand() as i64 * s;
138    if r < s0 {
139        //d * d/(b-a) / 2 = r;
140        let d = ((2 * r * (b - a)) as f32).sqrt();
141        return a + d as i64;
142    }
143    //d * d/(c-b) / 2 = s-r;
144    let d = ((2 * (s - r) * (c - b)) as f32).sqrt();
145    return c - d as i64;
146}
147pub fn rndtri_f(a: f64, b: f64, c: f64) -> f64 {
148    let s0 = (b - a) / 2.;
149    let s1 = (c - b) / 2.;
150    let s = s0 + s1;
151    let r = rand() as f64 * s;
152    if r < s0 {
153        //d * d/(b-a) / 2 = r;
154        let d = (2. * r * (b - a)).sqrt();
155        return a + d;
156    }
157    //d * d/(c-b) / 2 = s-r;
158    let d = (2. * (s - r) * (c - b)).sqrt();
159    return c - d;
160}
161
162pub fn deviate(n: f64) -> f64 {
163    return (rand() as f64 * 2. * n) - n;
164}