1use core::num::Wrapping;
2#[cfg(feature = "nightly-simd")]
3use core::simd::{f32x2, f32x4, num::SimdFloat};
4
5use crate::{
6 from_open_simplex_2::smooth_luts::{GRADIENTS_2D, GRADIENTS_3D, GRADIENTS_4D, LOOKUP_4D_A, LOOKUP_4D_B},
7 open_simplex_2::impl_open_simplex_noise,
8 OpenSimplexNoise,
9};
10
11#[cfg(feature = "nightly-simd")]
12use crate::math::splat;
13
14#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
19pub struct OpenSimplex2s;
20
21impl_open_simplex_noise!(234 OpenSimplex2s);
22
23impl OpenSimplexNoise for OpenSimplex2s {
24 #[inline]
25 fn raw_sample2(&self, [xs, ys]: [f32; 2], seed: i32) -> f32 {
26 let seed = Wrapping(seed as i64);
27
28 let xsb = fast_floor(xs);
30 let ysb = fast_floor(ys);
31 let xi = xs - xsb as f32;
32 let yi = ys - ysb as f32;
33
34 let xsbp = Wrapping(xsb as i64) * Wrapping(PRIME_X);
36 let ysbp = Wrapping(ysb as i64) * Wrapping(PRIME_Y);
37
38 let t = (xi + yi) * UNSKEW_2D;
40 let dx0 = xi + t;
41 let dy0 = yi + t;
42
43 let a0 = RSQUARED_2D - dx0 * dx0 - dy0 * dy0;
45 let mut value = (a0 * a0) * (a0 * a0) * grad2(seed, xsbp, ysbp, dx0, dy0);
46
47 let a1 = (2.0 * (1.0 + 2.0 * UNSKEW_2D) * (1.0 / UNSKEW_2D + 2.0)) * t + ((-2.0 * (1.0 + 2.0 * UNSKEW_2D) * (1.0 + 2.0 * UNSKEW_2D)) + a0);
49 let dx1 = dx0 - (1.0 + 2.0 * UNSKEW_2D);
50 let dy1 = dy0 - (1.0 + 2.0 * UNSKEW_2D);
51 value += (a1 * a1) * (a1 * a1) * grad2(seed, xsbp + Wrapping(PRIME_X), ysbp + Wrapping(PRIME_Y), dx1, dy1);
52
53 let xmyi = xi - yi;
56 if t < UNSKEW_2D {
57 if xi + xmyi > 1.0 {
58 let dx2 = dx0 - (3.0 * UNSKEW_2D + 2.0);
59 let dy2 = dy0 - (3.0 * UNSKEW_2D + 1.0);
60 let a2 = RSQUARED_2D - dx2 * dx2 - dy2 * dy2;
61 if a2 > 0.0 {
62 value += (a2 * a2) * (a2 * a2) * grad2(seed, xsbp + Wrapping(PRIME_X << 1), ysbp + Wrapping(PRIME_Y), dx2, dy2);
63 }
64 } else {
65 let dx2 = dx0 - UNSKEW_2D;
66 let dy2 = dy0 - (UNSKEW_2D + 1.0);
67 let a2 = RSQUARED_2D - dx2 * dx2 - dy2 * dy2;
68 if a2 > 0.0 {
69 value += (a2 * a2) * (a2 * a2) * grad2(seed, xsbp, ysbp + Wrapping(PRIME_Y), dx2, dy2);
70 }
71 }
72
73 if yi - xmyi > 1.0 {
74 let dx3 = dx0 - (3.0 * UNSKEW_2D + 1.0);
75 let dy3 = dy0 - (3.0 * UNSKEW_2D + 2.0);
76 let a3 = RSQUARED_2D - dx3 * dx3 - dy3 * dy3;
77 if a3 > 0.0 {
78 value += (a3 * a3) * (a3 * a3) * grad2(seed, xsbp + Wrapping(PRIME_X), ysbp + Wrapping(PRIME_Y << 1), dx3, dy3);
79 }
80 } else {
81 let dx3 = dx0 - (UNSKEW_2D + 1.0);
82 let dy3 = dy0 - UNSKEW_2D;
83 let a3 = RSQUARED_2D - dx3 * dx3 - dy3 * dy3;
84 if a3 > 0.0 {
85 value += (a3 * a3) * (a3 * a3) * grad2(seed, xsbp + Wrapping(PRIME_X), ysbp, dx3, dy3);
86 }
87 }
88 } else {
89 if xi + xmyi < 0.0 {
90 let dx2 = dx0 + (1.0 + UNSKEW_2D);
91 let dy2 = dy0 + UNSKEW_2D;
92 let a2 = RSQUARED_2D - dx2 * dx2 - dy2 * dy2;
93 if a2 > 0.0 {
94 value += (a2 * a2) * (a2 * a2) * grad2(seed, xsbp - Wrapping(PRIME_X), ysbp, dx2, dy2);
95 }
96 } else {
97 let dx2 = dx0 - (UNSKEW_2D + 1.0);
98 let dy2 = dy0 - UNSKEW_2D;
99 let a2 = RSQUARED_2D - dx2 * dx2 - dy2 * dy2;
100 if a2 > 0.0 {
101 value += (a2 * a2) * (a2 * a2) * grad2(seed, xsbp + Wrapping(PRIME_X), ysbp, dx2, dy2);
102 }
103 }
104
105 if yi < xmyi {
106 let dx2 = dx0 + UNSKEW_2D;
107 let dy2 = dy0 + (UNSKEW_2D + 1.0);
108 let a2 = RSQUARED_2D - dx2 * dx2 - dy2 * dy2;
109 if a2 > 0.0 {
110 value += (a2 * a2) * (a2 * a2) * grad2(seed, xsbp, ysbp - Wrapping(PRIME_Y), dx2, dy2);
111 }
112 } else {
113 let dx2 = dx0 - UNSKEW_2D;
114 let dy2 = dy0 - (UNSKEW_2D + 1.0);
115 let a2 = RSQUARED_2D - dx2 * dx2 - dy2 * dy2;
116 if a2 > 0.0 {
117 value += (a2 * a2) * (a2 * a2) * grad2(seed, xsbp, ysbp + Wrapping(PRIME_Y), dx2, dy2);
118 }
119 }
120 }
121
122 value
123 }
124
125 #[inline]
126 #[cfg(feature = "nightly-simd")]
127 fn raw_sample2a(&self, point: f32x2, seed: i32) -> f32 {
128 self.raw_sample2(point.into(), seed)
129 }
130
131 #[inline]
132 fn raw_sample3(&self, [xr, yr, zr]: [f32; 3], seed: i32) -> f32 {
133 let seed = Wrapping(seed as i64);
134
135 let xrb = fast_floor(xr);
137 let yrb = fast_floor(yr);
138 let zrb = fast_floor(zr);
139 let xi = (xr - xrb as f32) as f32;
140 let yi = (yr - yrb as f32) as f32;
141 let zi = (zr - zrb as f32) as f32;
142
143 let xrbp = Wrapping(xrb as i64) * Wrapping(PRIME_X);
145 let yrbp = Wrapping(yrb as i64) * Wrapping(PRIME_Y);
146 let zrbp = Wrapping(zrb as i64) * Wrapping(PRIME_Z);
147 let seed2 = seed ^ Wrapping(SEED_FLIP_3D);
148
149 let x_nmask = (-0.5 - xi) as i32;
151 let y_nmask = (-0.5 - yi) as i32;
152 let z_nmask = (-0.5 - zi) as i32;
153
154 let x0 = xi + x_nmask as f32;
156 let y0 = yi + y_nmask as f32;
157 let z0 = zi + z_nmask as f32;
158 let a0 = RSQUARED_3D - x0 * x0 - y0 * y0 - z0 * z0;
159 let mut value = (a0 * a0)
160 * (a0 * a0)
161 * grad3(
162 seed,
163 xrbp + (Wrapping(x_nmask as i64) & Wrapping(PRIME_X)),
164 yrbp + (Wrapping(y_nmask as i64) & Wrapping(PRIME_Y)),
165 zrbp + (Wrapping(z_nmask as i64) & Wrapping(PRIME_Z)),
166 x0,
167 y0,
168 z0,
169 );
170
171 let x1 = xi - 0.5;
173 let y1 = yi - 0.5;
174 let z1 = zi - 0.5;
175 let a1 = RSQUARED_3D - x1 * x1 - y1 * y1 - z1 * z1;
176 value += (a1 * a1) * (a1 * a1) * grad3(seed2, xrbp + Wrapping(PRIME_X), yrbp + Wrapping(PRIME_Y), zrbp + Wrapping(PRIME_Z), x1, y1, z1);
177
178 let x_aflip_mask0 = ((x_nmask | 1) << 1) as f32 * x1;
181 let y_aflip_mask0 = ((y_nmask | 1) << 1) as f32 * y1;
182 let z_aflip_mask0 = ((z_nmask | 1) << 1) as f32 * z1;
183 let x_aflip_mask1 = (-2 - (x_nmask << 2)) as f32 * x1 - 1.0;
184 let y_aflip_mask1 = (-2 - (y_nmask << 2)) as f32 * y1 - 1.0;
185 let z_aflip_mask1 = (-2 - (z_nmask << 2)) as f32 * z1 - 1.0;
186
187 let mut skip5 = false;
188 let a2 = x_aflip_mask0 + a0;
189 if a2 > 0.0 {
190 let x2 = x0 - (x_nmask | 1) as f32;
191 let y2 = y0;
192 let z2 = z0;
193 value += (a2 * a2)
194 * (a2 * a2)
195 * grad3(
196 seed,
197 xrbp + (Wrapping(!x_nmask as i64) & Wrapping(PRIME_X)),
198 yrbp + (Wrapping(y_nmask as i64) & Wrapping(PRIME_Y)),
199 zrbp + (Wrapping(z_nmask as i64) & Wrapping(PRIME_Z)),
200 x2,
201 y2,
202 z2,
203 );
204 } else {
205 let a3 = y_aflip_mask0 + z_aflip_mask0 + a0;
206 if a3 > 0.0 {
207 let x3 = x0;
208 let y3 = y0 - (y_nmask | 1) as f32;
209 let z3 = z0 - (z_nmask | 1) as f32;
210 value += (a3 * a3)
211 * (a3 * a3)
212 * grad3(
213 seed,
214 xrbp + (Wrapping(x_nmask as i64) & Wrapping(PRIME_X)),
215 yrbp + (Wrapping(!y_nmask as i64) & Wrapping(PRIME_Y)),
216 zrbp + (Wrapping(!z_nmask as i64) & Wrapping(PRIME_Z)),
217 x3,
218 y3,
219 z3,
220 );
221 }
222
223 let a4 = x_aflip_mask1 + a1;
224 if a4 > 0.0 {
225 let x4 = (x_nmask | 1) as f32 + x1;
226 let y4 = y1;
227 let z4 = z1;
228 value += (a4 * a4)
229 * (a4 * a4)
230 * grad3(
231 seed2,
232 xrbp + (Wrapping(x_nmask as i64) & (Wrapping(PRIME_X) << 1)),
233 yrbp + Wrapping(PRIME_Y),
234 zrbp + Wrapping(PRIME_Z),
235 x4,
236 y4,
237 z4,
238 );
239 skip5 = true;
240 }
241 }
242
243 let mut skip9 = false;
244 let a6 = y_aflip_mask0 + a0;
245 if a6 > 0.0 {
246 let x6 = x0;
247 let y6 = y0 - (y_nmask | 1) as f32;
248 let z6 = z0;
249 value += (a6 * a6)
250 * (a6 * a6)
251 * grad3(
252 seed,
253 xrbp + (Wrapping(x_nmask as i64) & Wrapping(PRIME_X)),
254 yrbp + (Wrapping(!y_nmask as i64) & Wrapping(PRIME_Y)),
255 zrbp + (Wrapping(z_nmask as i64) & Wrapping(PRIME_Z)),
256 x6,
257 y6,
258 z6,
259 );
260 } else {
261 let a7 = x_aflip_mask0 + z_aflip_mask0 + a0;
262 if a7 > 0.0 {
263 let x7 = x0 - (x_nmask | 1) as f32;
264 let y7 = y0;
265 let z7 = z0 - (z_nmask | 1) as f32;
266 value += (a7 * a7)
267 * (a7 * a7)
268 * grad3(
269 seed,
270 xrbp + (Wrapping(!x_nmask as i64) & Wrapping(PRIME_X)),
271 yrbp + (Wrapping(y_nmask as i64) & Wrapping(PRIME_Y)),
272 zrbp + (Wrapping(!z_nmask as i64) & Wrapping(PRIME_Z)),
273 x7,
274 y7,
275 z7,
276 );
277 }
278
279 let a8 = y_aflip_mask1 + a1;
280 if a8 > 0.0 {
281 let x8 = x1;
282 let y8 = (y_nmask | 1) as f32 + y1;
283 let z8 = z1;
284 value += (a8 * a8)
285 * (a8 * a8)
286 * grad3(
287 seed2,
288 xrbp + Wrapping(PRIME_X),
289 yrbp + (Wrapping(y_nmask as i64) & (Wrapping(PRIME_Y) << 1)),
290 zrbp + Wrapping(PRIME_Z),
291 x8,
292 y8,
293 z8,
294 );
295 skip9 = true;
296 }
297 }
298
299 let mut skip_d = false;
300 let a_a = z_aflip_mask0 + a0;
301 if a_a > 0.0 {
302 let x_a = x0;
303 let y_a = y0;
304 let z_a = z0 - (z_nmask | 1) as f32;
305 value += (a_a * a_a)
306 * (a_a * a_a)
307 * grad3(
308 seed,
309 xrbp + (Wrapping(x_nmask as i64) & Wrapping(PRIME_X)),
310 yrbp + (Wrapping(y_nmask as i64) & Wrapping(PRIME_Y)),
311 zrbp + (Wrapping(!z_nmask as i64) & Wrapping(PRIME_Z)),
312 x_a,
313 y_a,
314 z_a,
315 );
316 } else {
317 let a_b = x_aflip_mask0 + y_aflip_mask0 + a0;
318 if a_b > 0.0 {
319 let x_b = x0 - (x_nmask | 1) as f32;
320 let y_b = y0 - (y_nmask | 1) as f32;
321 let z_b = z0;
322 value += (a_b * a_b)
323 * (a_b * a_b)
324 * grad3(
325 seed,
326 xrbp + (Wrapping(!x_nmask as i64) & Wrapping(PRIME_X)),
327 yrbp + (Wrapping(!y_nmask as i64) & Wrapping(PRIME_Y)),
328 zrbp + (Wrapping(z_nmask as i64) & Wrapping(PRIME_Z)),
329 x_b,
330 y_b,
331 z_b,
332 );
333 }
334
335 let a_c = z_aflip_mask1 + a1;
336 if a_c > 0.0 {
337 let x_c = x1;
338 let y_c = y1;
339 let z_c = (z_nmask | 1) as f32 + z1;
340 value += (a_c * a_c)
341 * (a_c * a_c)
342 * grad3(
343 seed2,
344 xrbp + Wrapping(PRIME_X),
345 yrbp + Wrapping(PRIME_Y),
346 zrbp + (Wrapping(z_nmask as i64) & (Wrapping(PRIME_Z) << 1)),
347 x_c,
348 y_c,
349 z_c,
350 );
351 skip_d = true;
352 }
353 }
354
355 if !skip5 {
356 let a5 = y_aflip_mask1 + z_aflip_mask1 + a1;
357 if a5 > 0.0 {
358 let x5 = x1;
359 let y5 = (y_nmask | 1) as f32 + y1;
360 let z5 = (z_nmask | 1) as f32 + z1;
361 value += (a5 * a5)
362 * (a5 * a5)
363 * grad3(
364 seed2,
365 xrbp + Wrapping(PRIME_X),
366 yrbp + (Wrapping(y_nmask as i64) & (Wrapping(PRIME_Y) << 1)),
367 zrbp + (Wrapping(z_nmask as i64) & (Wrapping(PRIME_Z) << 1)),
368 x5,
369 y5,
370 z5,
371 );
372 }
373 }
374
375 if !skip9 {
376 let a9 = x_aflip_mask1 + z_aflip_mask1 + a1;
377 if a9 > 0.0 {
378 let x9 = (x_nmask | 1) as f32 + x1;
379 let y9 = y1;
380 let z9 = (z_nmask | 1) as f32 + z1;
381 value += (a9 * a9)
382 * (a9 * a9)
383 * grad3(
384 seed2,
385 xrbp + (Wrapping(x_nmask as i64) & (Wrapping(PRIME_X) << 1)),
386 yrbp + Wrapping(PRIME_Y),
387 zrbp + (Wrapping(z_nmask as i64) & (Wrapping(PRIME_Z) << 1)),
388 x9,
389 y9,
390 z9,
391 );
392 }
393 }
394
395 if !skip_d {
396 let a_d = x_aflip_mask1 + y_aflip_mask1 + a1;
397 if a_d > 0.0 {
398 let x_d = (x_nmask | 1) as f32 + x1;
399 let y_d = (y_nmask | 1) as f32 + y1;
400 let z_d = z1;
401 value += (a_d * a_d)
402 * (a_d * a_d)
403 * grad3(
404 seed2,
405 xrbp + (Wrapping(x_nmask as i64) & (Wrapping(PRIME_X) << 1)),
406 yrbp + (Wrapping(y_nmask as i64) & (Wrapping(PRIME_Y) << 1)),
407 zrbp + Wrapping(PRIME_Z),
408 x_d,
409 y_d,
410 z_d,
411 );
412 }
413 }
414
415 value
416 }
417
418 #[inline]
419 #[cfg(feature = "nightly-simd")]
420 fn raw_sample3a(&self, point: f32x4, seed: i32) -> f32 {
421 self.raw_sample3(*crate::array_4_take_3(point.as_array()), seed)
422 }
423
424 #[inline]
425 fn raw_sample4(&self, [xs, ys, zs, ws]: [f32; 4], seed: i32) -> f32 {
426 let seed = Wrapping(seed as i64);
427
428 let xsb = fast_floor(xs);
430 let ysb = fast_floor(ys);
431 let zsb = fast_floor(zs);
432 let wsb = fast_floor(ws);
433 let xsi = (xs - xsb as f32) as f32;
434 let ysi = (ys - ysb as f32) as f32;
435 let zsi = (zs - zsb as f32) as f32;
436 let wsi = (ws - wsb as f32) as f32;
437
438 let ssi = (xsi + ysi + zsi + wsi) * UNSKEW_4D;
440 let xi = xsi + ssi;
441 let yi = ysi + ssi;
442 let zi = zsi + ssi;
443 let wi = wsi + ssi;
444
445 let xsvp = Wrapping(xsb as i64) * Wrapping(PRIME_X);
447 let ysvp = Wrapping(ysb as i64) * Wrapping(PRIME_Y);
448 let zsvp = Wrapping(zsb as i64) * Wrapping(PRIME_Z);
449 let wsvp = Wrapping(wsb as i64) * Wrapping(PRIME_W);
450
451 let index = (fast_floor(xs * 4.0) & 3) | ((fast_floor(ys * 4.0) & 3) << 2) | ((fast_floor(zs * 4.0) & 3) << 4) | ((fast_floor(ws * 4.0) & 3) << 6);
453
454 let mut value = 0.0;
456 let [secondary_index_start, secondary_index_stop] = LOOKUP_4D_A[index as usize];
457 for i in secondary_index_start..secondary_index_stop {
458 let c = &LOOKUP_4D_B[usize::from(i)];
459 let dx = xi + c.dx;
460 let dy = yi + c.dy;
461 let dz = zi + c.dz;
462 let dw = wi + c.dw;
463 let mut a = (dx * dx + dy * dy) + (dz * dz + dw * dw);
464 if a < RSQUARED_4D {
465 a -= RSQUARED_4D;
466 a *= a;
467 value += a * a * grad4(seed, xsvp + Wrapping(c.xsvp), ysvp + Wrapping(c.ysvp), zsvp + Wrapping(c.zsvp), wsvp + Wrapping(c.wsvp), dx, dy, dz, dw);
468 }
469 }
470 value
471 }
472
473 #[inline]
474 #[cfg(feature = "nightly-simd")]
475 fn raw_sample4a(&self, point: f32x4, seed: i32) -> f32 {
476 self.raw_sample4(point.into(), seed)
477 }
478
479 #[inline(always)]
480 fn raw_improve2_x(&self, [x, y]: [f32; 2]) -> [f32; 2] {
481 let xx = x * ROOT2OVER2;
483 let yy = y * (ROOT2OVER2 * (1.0 + 2.0 * SKEW_2D));
484
485 [yy + xx, yy - xx]
486 }
487
488 #[inline(always)]
489 #[cfg(feature = "nightly-simd")]
490 fn raw_improve2a_x(&self, point: f32x2) -> f32x2 {
491 self.raw_improve2_x(point.into()).into()
492 }
493
494 #[doc(hidden)]
495 fn raw_improve3_xy(&self, [x, y, z]: [f32; 3]) -> [f32; 3] {
496 let xy = x + y;
500 let s2 = xy * ROTATE3_ORTHOGONALIZER;
501 let zz = z * ROOT3OVER3;
502 let xr = x + s2 + zz;
503 let yr = y + s2 + zz;
504 let zr = xy * -ROOT3OVER3 + zz;
505
506 [xr, yr, zr]
508 }
509
510 #[doc(hidden)]
511 #[cfg(feature = "nightly-simd")]
512 fn raw_improve3a_xy(&self, point: f32x4) -> f32x4 {
513 let &[x, y, z, _] = point.as_array();
514 let [x, y, z] = self.raw_improve3_xy([x, y, z]);
515 f32x4::from_array([x, y, z, z])
516 }
517
518 #[doc(hidden)]
519 fn raw_improve3_xz(&self, [x, y, z]: [f32; 3]) -> [f32; 3] {
520 let xz = x + z;
524 let s2 = xz * -0.211324865405187;
525 let yy = y * ROOT3OVER3;
526 let xr = x + s2 + yy;
527 let zr = z + s2 + yy;
528 let yr = xz * -ROOT3OVER3 + yy;
529
530 [xr, yr, zr]
532 }
533
534 #[doc(hidden)]
535 #[cfg(feature = "nightly-simd")]
536 fn raw_improve3a_xz(&self, point: f32x4) -> f32x4 {
537 let &[x, y, z, _] = point.as_array();
538 let [x, y, z] = self.raw_improve3_xz([x, y, z]);
539 f32x4::from_array([x, y, z, z])
540 }
541
542 #[inline]
543 fn raw_improve4_xyz(&self, [x, y, z, w]: [f32; 4]) -> [f32; 4] {
544 let xyz = x + y + z;
545 let ww = w * 1.118033988749894;
546 let s2 = xyz * -0.16666666666666666 + ww;
547 let xs = x + s2;
548 let ys = y + s2;
549 let zs = z + s2;
550 let ws = -0.5 * xyz + ww;
551 [xs, ys, zs, ws]
552 }
553
554 #[inline]
555 #[cfg(feature = "nightly-simd")]
556 fn raw_improve4a_xyz(&self, point: f32x4) -> f32x4 {
557 self.raw_improve4_xyz(*point.as_array()).into()
558 }
559
560 #[inline]
561 fn raw_improve4_xyz_xy(&self, [x, y, z, w]: [f32; 4]) -> [f32; 4] {
562 let xy = x + y;
563 let s2 = xy * -0.21132486540518699998;
564 let zz = z * 0.28867513459481294226;
565 let ww = w * 1.118033988749894;
566 let xr = x + (zz + ww + s2);
567 let yr = y + (zz + ww + s2);
568 let zr = xy * -0.57735026918962599998 + (zz + ww);
569 let wr = z * -0.866025403784439 + ww;
570 [xr, yr, zr, wr]
571 }
572
573 #[inline]
574 #[cfg(feature = "nightly-simd")]
575 fn raw_improve4a_xyz_xy(&self, point: f32x4) -> f32x4 {
576 self.raw_improve4_xyz_xy(*point.as_array()).into()
577 }
578
579 #[inline]
580 fn raw_improve4_xyz_xz(&self, [x, y, z, w]: [f32; 4]) -> [f32; 4] {
581 let xz = x + z;
582 let s2 = xz * -0.21132486540518699998;
583 let yy = y * 0.28867513459481294226;
584 let ww = w * 1.118033988749894;
585 let xr = x + (yy + ww + s2);
586 let zr = z + (yy + ww + s2);
587 let yr = xz * -0.57735026918962599998 + (yy + ww);
588 let wr = y * -0.866025403784439 + ww;
589 [xr, yr, zr, wr]
590 }
591
592 #[inline]
593 #[cfg(feature = "nightly-simd")]
594 fn raw_improve4a_xyz_xz(&self, point: f32x4) -> f32x4 {
595 self.raw_improve4_xyz_xz(*point.as_array()).into()
596 }
597
598 #[inline]
599 fn raw_improve4_xy_zw(&self, [x, y, z, w]: [f32; 4]) -> [f32; 4] {
600 let s2 = (x + y) * -0.28522513987434876941 + (z + w) * 0.83897065470611435718;
601 let t2 = (z + w) * 0.21939749883706435719 + (x + y) * -0.48214856493302476942;
602 let xs = x + s2;
603 let ys = y + s2;
604 let zs = z + t2;
605 let ws = w + t2;
606 [xs, ys, zs, ws]
607 }
608
609 #[inline]
610 #[cfg(feature = "nightly-simd")]
611 fn raw_improve4a_xy_zw(&self, point: f32x4) -> f32x4 {
612 self.raw_improve4_xy_zw(*point.as_array()).into()
613 }
614}
615
616#[inline]
617pub(crate) fn improve2([x, y]: [f32; 2]) -> [f32; 2] {
618 let s = SKEW_2D * (x + y);
620 let xs = x + s;
621 let ys = y + s;
622 [xs, ys]
623}
624
625#[inline]
626#[cfg(feature = "nightly-simd")]
627pub(crate) fn improve2a(point: f32x2) -> f32x2 {
628 improve2(point.into()).into()
629}
630
631#[inline]
632pub(crate) fn improve3([x, y, z]: [f32; 3]) -> [f32; 3] {
633 let r = FALLBACK_ROTATE3 * (x + y + z);
636 let xr = r - x;
637 let yr = r - y;
638 let zr = r - z;
639
640 [xr, yr, zr]
642}
643
644#[inline]
645#[cfg(feature = "nightly-simd")]
646pub(crate) fn improve3a(point: f32x4) -> f32x4 {
647 const R3: f32 = 2.0 / 3.0;
648 let r: f32 = (point[0] + point[1] + point[2]) * R3; f32x4::splat(r) - point
650}
651
652#[inline]
653pub(crate) fn improve4([mut x, mut y, mut z, mut w]: [f32; 4]) -> [f32; 4] {
654 let s = SKEW_4D * (x + y + z + w);
655 x += s;
656 y += s;
657 z += s;
658 w += s;
659 [x, y, z, w]
660}
661
662#[inline]
663#[cfg(feature = "nightly-simd")]
664pub(crate) fn improve4a(point: f32x4) -> f32x4 {
665 let s = SKEW_4D * point.reduce_sum();
666 point + splat(s)
667}
668
669fn grad2(seed: Wrapping<i64>, xsvp: Wrapping<i64>, ysvp: Wrapping<i64>, dx: f32, dy: f32) -> f32 {
670 let mut hash = seed ^ xsvp ^ ysvp;
671 hash *= HASH_MULTIPLIER;
672 hash ^= hash.0 >> (64 - N_GRADS_2D_EXPONENT + 1);
673 let [grad_x, grad_y] = *GRADIENTS_2D[hash.0].as_array();
674 grad_x * dx + grad_y * dy
675}
676
677fn grad3(seed: Wrapping<i64>, xrvp: Wrapping<i64>, yrvp: Wrapping<i64>, zrvp: Wrapping<i64>, dx: f32, dy: f32, dz: f32) -> f32 {
678 let mut hash = (seed ^ xrvp) ^ (yrvp ^ zrvp);
679 hash *= HASH_MULTIPLIER;
680 hash ^= hash.0 >> (64 - N_GRADS_3D_EXPONENT + 2);
681 let [grad_x, grad_y, grad_z, ..] = *GRADIENTS_3D[hash.0].as_array();
682 grad_x * dx + grad_y * dy + grad_z * dz
683}
684
685fn grad4(seed: Wrapping<i64>, xsvp: Wrapping<i64>, ysvp: Wrapping<i64>, zsvp: Wrapping<i64>, wsvp: Wrapping<i64>, dx: f32, dy: f32, dz: f32, dw: f32) -> f32 {
686 let mut hash = seed ^ (xsvp ^ ysvp) ^ (zsvp ^ wsvp);
687 hash *= HASH_MULTIPLIER;
688 hash ^= hash.0 >> (64 - N_GRADS_4D_EXPONENT + 2);
689 let [grad_x, grad_y, grad_z, grad_w] = *GRADIENTS_4D[hash.0].as_array();
690 grad_x * dx + grad_y * dy + grad_z * dz + grad_w * dw
691}
692
693fn fast_floor(x: f32) -> i32 {
694 let xi = x as i32;
695 if x < xi as f32 {
696 xi.wrapping_sub(1)
697 } else {
698 xi
699 }
700}
701
702const PRIME_X: i64 = 0x5205402B9270C86F;
703const PRIME_Y: i64 = 0x598CD327003817B5;
704const PRIME_Z: i64 = 0x5BCC226E9FA0BACB;
705const PRIME_W: i64 = 0x56CC5227E58F554B;
706const HASH_MULTIPLIER: i64 = 0x53A3F72DEEC546F5;
707const SEED_FLIP_3D: i64 = -0x52D547B2E96ED629;
708
709const ROOT2OVER2: f32 = 0.7071067811865476;
710const SKEW_2D: f32 = 0.366025403784439;
711const UNSKEW_2D: f32 = -0.21132486540518713;
712
713const ROOT3OVER3: f32 = 0.577350269189626;
714const FALLBACK_ROTATE3: f32 = 2.0 / 3.0;
715const ROTATE3_ORTHOGONALIZER: f32 = UNSKEW_2D;
716
717const SKEW_4D: f32 = 0.309016994374947;
718const UNSKEW_4D: f32 = -0.138196601125011;
719
720const N_GRADS_2D_EXPONENT: i32 = 7;
721const N_GRADS_3D_EXPONENT: i32 = 8;
722const N_GRADS_4D_EXPONENT: i32 = 9;
723
724const RSQUARED_2D: f32 = 2.0 / 3.0;
725const RSQUARED_3D: f32 = 3.0 / 4.0;
726const RSQUARED_4D: f32 = 4.0 / 5.0;