fish_oxide/
custom_rand.rs1use 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 n ^= n << 17;
19 n ^= n >> 13;
20 n ^= n << 5;
21 n = (n >> 0) % 4294967295;
23 }
24 return n;
25}
26
27pub fn rand() -> f64 {
28 return thread_rng().gen();
29 }
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 let d = ((2 * r * (b - a)) as f32).sqrt();
141 return a + d as i64;
142 }
143 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 let d = (2. * r * (b - a)).sqrt();
155 return a + d;
156 }
157 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}