1use crate::{
2 base::impl_noise,
3 from_fast_noise_2::{masked_add, nmasked_add},
4 math::floor,
5};
6
7#[cfg(feature = "nightly-simd")]
8use core::simd::{f32x2, f32x4};
9
10#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
12pub struct Simplex;
13
14impl_noise!(234 Simplex);
15
16impl Simplex {
17 #[inline]
18 fn gen2(self, [x, y]: [f32; 2], seed: i32) -> f32 {
19 use crate::from_fast_noise_2::{gradient_dot2, hash_primes2, max, mul_add, primes};
21
22 const SQRT3: f32 = 1.7320508075688772935274463415059;
23 const F2: f32 = 0.5 * (SQRT3 - 1.0);
24 const G2: f32 = (3.0 - SQRT3) / 6.0;
25
26 let f = F2 * (x + y);
27 let mut x0 = floor(x + f);
28 let mut y0 = floor(y + f);
29
30 let i = (x0 as i32).wrapping_mul(primes::X);
31 let j = (y0 as i32).wrapping_mul(primes::Y);
32
33 let g = G2 * (x0 + y0);
34 x0 = x - (x0 - g);
35 y0 = y - (y0 - g);
36
37 let i1 = x0 > y0;
38
39 let x1 = if i1 { x0 - 1.0 } else { x0 } + G2;
40 let y1 = if i1 { y0 } else { y0 - 1.0 } + G2;
41
42 let x2 = x0 + (G2 * 2.0 - 1.0);
43 let y2 = y0 + (G2 * 2.0 - 1.0);
44
45 let mut t0 = 0.5 - (x0 * x0) - (y0 * y0);
46 let mut t1 = 0.5 - (x1 * x1) - (y1 * y1);
47 let mut t2 = 0.5 - (x2 * x2) - (y2 * y2);
48
49 t0 = max(t0, 0.0);
50 t1 = max(t1, 0.0);
51 t2 = max(t2, 0.0);
52
53 t0 *= t0;
54 t0 *= t0;
55
56 t1 *= t1;
57 t1 *= t1;
58
59 t2 *= t2;
60 t2 *= t2;
61
62 let n0 = gradient_dot2(hash_primes2(seed, i, j), x0, y0);
63 let n1 = gradient_dot2(hash_primes2(seed, masked_add(i, primes::X, i1), nmasked_add(j, primes::Y, i1)), x1, y1);
64 let n2 = gradient_dot2(hash_primes2(seed, i.wrapping_add(primes::X), j.wrapping_add(primes::Y)), x2, y2);
65
66 38.283687591552734375 * mul_add(n0, t0, mul_add(n1, t1, n2 * t2))
67 }
68
69 #[inline]
70 fn gen3(self, [mut x, mut y, mut z]: [f32; 3], seed: i32) -> f32 {
71 use crate::from_fast_noise_2::{gradient_dot3, hash_primes3, masked_add, masked_sub, max, mul_add, nmasked_add, nmasked_sub, nmul_add, primes};
73
74 const F3: f32 = 1.0 / 3.0;
75 const G3: f32 = 1.0 / 2.0;
76
77 let s = F3 * (x + y + z);
78 x += s;
79 y += s;
80 z += s;
81
82 let mut x0 = floor(x);
83 let mut y0 = floor(y);
84 let mut z0 = floor(z);
85 let xi = x - x0;
86 let yi = y - y0;
87 let zi = z - z0;
88
89 let i = (x0 as i32).wrapping_mul(primes::X);
90 let j = (y0 as i32).wrapping_mul(primes::Y);
91 let k = (z0 as i32).wrapping_mul(primes::Z);
92
93 let x_ge_y = xi >= yi;
94 let y_ge_z = yi >= zi;
95 let x_ge_z = xi >= zi;
96
97 let g = G3 * (xi + yi + zi);
98 x0 = xi - g;
99 y0 = yi - g;
100 z0 = zi - g;
101
102 let i1 = x_ge_y & x_ge_z;
103 let j1 = y_ge_z & !x_ge_y;
104 let k1 = !x_ge_z & !y_ge_z;
105
106 let i2 = x_ge_y | x_ge_z;
107 let j2 = !x_ge_y | y_ge_z;
108 let k2 = x_ge_z & y_ge_z; let x1 = masked_sub(x0, 1.0, i1) + G3;
111 let y1 = masked_sub(y0, 1.0, j1) + G3;
112 let z1 = masked_sub(z0, 1.0, k1) + G3;
113 let x2 = masked_sub(x0, 1.0, i2) + G3 * 2.0;
114 let y2 = masked_sub(y0, 1.0, j2) + G3 * 2.0;
115 let z2 = nmasked_sub(z0, 1.0, k2) + G3 * 2.0;
116 let x3 = x0 + (G3 * 3.0 - 1.0);
117 let y3 = y0 + (G3 * 3.0 - 1.0);
118 let z3 = z0 + (G3 * 3.0 - 1.0);
119
120 let mut t0 = nmul_add(x0, x0, nmul_add(y0, y0, nmul_add(z0, z0, 0.6)));
121 let mut t1 = nmul_add(x1, x1, nmul_add(y1, y1, nmul_add(z1, z1, 0.6)));
122 let mut t2 = nmul_add(x2, x2, nmul_add(y2, y2, nmul_add(z2, z2, 0.6)));
123 let mut t3 = nmul_add(x3, x3, nmul_add(y3, y3, nmul_add(z3, z3, 0.6)));
124
125 t0 = max(t0, 0.0);
126 t1 = max(t1, 0.0);
127 t2 = max(t2, 0.0);
128 t3 = max(t3, 0.0);
129
130 t0 *= t0;
131 t0 *= t0;
132 t1 *= t1;
133 t1 *= t1;
134 t2 *= t2;
135 t2 *= t2;
136 t3 *= t3;
137 t3 *= t3;
138
139 let n0 = gradient_dot3(hash_primes3(seed, i, j, k), x0, y0, z0);
140 let n1 = gradient_dot3(hash_primes3(seed, masked_add(i, primes::X, i1), masked_add(j, primes::Y, j1), masked_add(k, primes::Z, k1)), x1, y1, z1);
141 let n2 = gradient_dot3(
142 hash_primes3(seed, masked_add(i, primes::X, i2), masked_add(j, primes::Y, j2), nmasked_add(k, primes::Z, k2)),
143 x2,
144 y2,
145 z2,
146 );
147 let n3 = gradient_dot3(hash_primes3(seed, i.wrapping_add(primes::X), j.wrapping_add(primes::Y), k.wrapping_add(primes::Z)), x3, y3, z3);
148
149 32.69428253173828125 * mul_add(n0, t0, mul_add(n1, t1, mul_add(n2, t2, n3 * t3)))
150 }
151
152 #[inline]
153 fn gen4(self, [mut x, mut y, mut z, mut w]: [f32; 4], seed: i32) -> f32 {
154 use crate::from_fast_noise_2::{gradient_dot4, hash_primes4, masked_add, masked_inc, masked_sub, max, mul_add, nmul_add, primes};
156
157 const SQRT5: f32 = 2.236067977499;
158 const F4: f32 = (SQRT5 - 1.0) / 4.0;
159 const G4: f32 = (5.0 - SQRT5) / 20.0;
160
161 let s = F4 * (x + y + z + w);
162 x += s;
163 y += s;
164 z += s;
165 w += s;
166
167 let mut x0 = floor(x);
168 let mut y0 = floor(y);
169 let mut z0 = floor(z);
170 let mut w0 = floor(w);
171 let xi = x - x0;
172 let yi = y - y0;
173 let zi = z - z0;
174 let wi = w - w0;
175
176 let i = (x0 as i32).wrapping_mul(primes::X);
177 let j = (y0 as i32).wrapping_mul(primes::Y);
178 let k = (z0 as i32).wrapping_mul(primes::Z);
179 let l = (w0 as i32).wrapping_mul(primes::W);
180
181 let g = G4 * (xi + yi + zi + wi);
182 x0 = xi - g;
183 y0 = yi - g;
184 z0 = zi - g;
185 w0 = wi - g;
186
187 let mut rankx = 0;
188 let mut ranky = 0;
189 let mut rankz = 0;
190 let mut rankw = 0;
191
192 let x_ge_y = x0 >= y0;
193 rankx = masked_inc(rankx, x_ge_y);
194 ranky = masked_inc(ranky, !x_ge_y);
195
196 let x_ge_z = x0 >= z0;
197 rankx = masked_inc(rankx, x_ge_z);
198 rankz = masked_inc(rankz, !x_ge_z);
199
200 let x_ge_w = x0 >= w0;
201 rankx = masked_inc(rankx, x_ge_w);
202 rankw = masked_inc(rankw, !x_ge_w);
203
204 let y_ge_z = y0 >= z0;
205 ranky = masked_inc(ranky, y_ge_z);
206 rankz = masked_inc(rankz, !y_ge_z);
207
208 let y_ge_w = y0 >= w0;
209 ranky = masked_inc(ranky, y_ge_w);
210 rankw = masked_inc(rankw, !y_ge_w);
211
212 let z_ge_w = z0 >= w0;
213 rankz = masked_inc(rankz, z_ge_w);
214 rankw = masked_inc(rankw, !z_ge_w);
215
216 let i1 = rankx > 2;
217 let j1 = ranky > 2;
218 let k1 = rankz > 2;
219 let l1 = rankw > 2;
220
221 let i2 = rankx > 1;
222 let j2 = ranky > 1;
223 let k2 = rankz > 1;
224 let l2 = rankw > 1;
225
226 let i3 = rankx > 0;
227 let j3 = ranky > 0;
228 let k3 = rankz > 0;
229 let l3 = rankw > 0;
230
231 let x1 = masked_sub(x0, 1.0, i1) + G4;
232 let y1 = masked_sub(y0, 1.0, j1) + G4;
233 let z1 = masked_sub(z0, 1.0, k1) + G4;
234 let w1 = masked_sub(w0, 1.0, l1) + G4;
235 let x2 = masked_sub(x0, 1.0, i2) + G4 * 2.0;
236 let y2 = masked_sub(y0, 1.0, j2) + G4 * 2.0;
237 let z2 = masked_sub(z0, 1.0, k2) + G4 * 2.0;
238 let w2 = masked_sub(w0, 1.0, l2) + G4 * 2.0;
239 let x3 = masked_sub(x0, 1.0, i3) + G4 * 3.0;
240 let y3 = masked_sub(y0, 1.0, j3) + G4 * 3.0;
241 let z3 = masked_sub(z0, 1.0, k3) + G4 * 3.0;
242 let w3 = masked_sub(w0, 1.0, l3) + G4 * 3.0;
243 let x4 = x0 + (G4 * 4.0 - 1.0);
244 let y4 = y0 + (G4 * 4.0 - 1.0);
245 let z4 = z0 + (G4 * 4.0 - 1.0);
246 let w4 = w0 + (G4 * 4.0 - 1.0);
247
248 let mut t0 = nmul_add(x0, x0, nmul_add(y0, y0, nmul_add(z0, z0, nmul_add(w0, w0, 0.6))));
249 let mut t1 = nmul_add(x1, x1, nmul_add(y1, y1, nmul_add(z1, z1, nmul_add(w1, w1, 0.6))));
250 let mut t2 = nmul_add(x2, x2, nmul_add(y2, y2, nmul_add(z2, z2, nmul_add(w2, w2, 0.6))));
251 let mut t3 = nmul_add(x3, x3, nmul_add(y3, y3, nmul_add(z3, z3, nmul_add(w3, w3, 0.6))));
252 let mut t4 = nmul_add(x4, x4, nmul_add(y4, y4, nmul_add(z4, z4, nmul_add(w4, w4, 0.6))));
253
254 t0 = max(t0, 0.0);
255 t1 = max(t1, 0.0);
256 t2 = max(t2, 0.0);
257 t3 = max(t3, 0.0);
258 t4 = max(t4, 0.0);
259
260 t0 *= t0;
261 t0 *= t0;
262 t1 *= t1;
263 t1 *= t1;
264 t2 *= t2;
265 t2 *= t2;
266 t3 *= t3;
267 t3 *= t3;
268 t4 *= t4;
269 t4 *= t4;
270
271 let n0 = gradient_dot4(hash_primes4(seed, i, j, k, l), x0, y0, z0, w0);
272 let n1 = gradient_dot4(
273 hash_primes4(
274 seed,
275 masked_add(i, primes::X, i1),
276 masked_add(j, primes::Y, j1),
277 masked_add(k, primes::Z, k1),
278 masked_add(l, primes::W, l1),
279 ),
280 x1,
281 y1,
282 z1,
283 w1,
284 );
285 let n2 = gradient_dot4(
286 hash_primes4(
287 seed,
288 masked_add(i, primes::X, i2),
289 masked_add(j, primes::Y, j2),
290 masked_add(k, primes::Z, k2),
291 masked_add(l, primes::W, l2),
292 ),
293 x2,
294 y2,
295 z2,
296 w2,
297 );
298 let n3 = gradient_dot4(
299 hash_primes4(
300 seed,
301 masked_add(i, primes::X, i3),
302 masked_add(j, primes::Y, j3),
303 masked_add(k, primes::Z, k3),
304 masked_add(l, primes::W, l3),
305 ),
306 x3,
307 y3,
308 z3,
309 w3,
310 );
311 let n4 = gradient_dot4(
312 hash_primes4(seed, i.wrapping_add(primes::X), j.wrapping_add(primes::Y), k.wrapping_add(primes::Z), l.wrapping_add(primes::W)),
313 x4,
314 y4,
315 z4,
316 w4,
317 );
318
319 27.0 * mul_add(n0, t0, mul_add(n1, t1, mul_add(n2, t2, mul_add(n3, t3, n4 * t4))))
320 }
321
322 #[inline]
323 #[cfg(feature = "nightly-simd")]
324 fn gen2a(self, point: f32x2, seed: i32) -> f32 {
325 self.gen2(point.into(), seed)
326 }
327
328 #[inline]
329 #[cfg(feature = "nightly-simd")]
330 fn gen3a(self, point: f32x4, seed: i32) -> f32 {
331 self.gen3(*crate::array_4_take_3(point.as_array()), seed)
332 }
333
334 #[inline]
335 #[cfg(feature = "nightly-simd")]
336 fn gen4a(self, point: f32x4, seed: i32) -> f32 {
337 self.gen4(point.into(), seed)
338 }
339}