doryen_extra/noise/algorithms/
simplex.rs

1/* BSD 3-Clause License
2 *
3 * Copyright © 2019, Alexander Krivács Schrøder <alexschrod@gmail.com>.
4 * Copyright © 2008-2019, Jice and the libtcod contributors.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 *    this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 *    this list of conditions and the following disclaimer in the documentation
15 *    and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 *    contributors may be used to endorse or promote products derived from
19 *    this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34use crate::noise::algorithms::AlgorithmInitializer;
35use crate::noise::Algorithm;
36use crate::random::algorithms::Algorithm as RandomAlgorithm;
37use crate::util::FloorRem;
38
39use derivative::Derivative;
40
41/// Simplex noise algorithm.
42#[derive(Clone, Copy, Derivative)]
43#[derivative(Debug)]
44pub struct Simplex {
45    dimensions: usize,
46    #[derivative(Debug = "ignore")]
47    map: [u8; 256],
48}
49
50impl Algorithm for Simplex {
51    fn new<R: RandomAlgorithm>(
52        dimensions: usize,
53        mut initializer: AlgorithmInitializer<R>,
54    ) -> Self {
55        Self {
56            dimensions,
57            map: initializer.map(),
58        }
59    }
60
61    fn generate(&self, f: &[f32]) -> f32 {
62        assert!(f.len() >= self.dimensions);
63
64        match self.dimensions {
65            1 => self.simplex_1d(f[0]),
66            2 => self.simplex_2d(f[0], f[1]),
67            3 => self.simplex_3d(f[0], f[1], f[2]),
68            4 => self.simplex_4d(f[0], f[1], f[2], f[3]),
69            _ => unreachable!(),
70        }
71    }
72}
73
74impl Simplex {
75    const SIMPLEX_SCALE: f32 = 0.5;
76    const SIMPLEX: [[f32; 4]; 64] = [
77        [0.0, 1.0, 2.0, 3.0],
78        [0.0, 1.0, 3.0, 2.0],
79        [0.0, 0.0, 0.0, 0.0],
80        [0.0, 2.0, 3.0, 1.0],
81        [0.0, 0.0, 0.0, 0.0],
82        [0.0, 0.0, 0.0, 0.0],
83        [0.0, 0.0, 0.0, 0.0],
84        [1.0, 2.0, 3.0, 0.0],
85        [0.0, 2.0, 1.0, 3.0],
86        [0.0, 0.0, 0.0, 0.0],
87        [0.0, 3.0, 1.0, 2.0],
88        [0.0, 3.0, 2.0, 1.0],
89        [0.0, 0.0, 0.0, 0.0],
90        [0.0, 0.0, 0.0, 0.0],
91        [0.0, 0.0, 0.0, 0.0],
92        [1.0, 3.0, 2.0, 0.0],
93        [0.0, 0.0, 0.0, 0.0],
94        [0.0, 0.0, 0.0, 0.0],
95        [0.0, 0.0, 0.0, 0.0],
96        [0.0, 0.0, 0.0, 0.0],
97        [0.0, 0.0, 0.0, 0.0],
98        [0.0, 0.0, 0.0, 0.0],
99        [0.0, 0.0, 0.0, 0.0],
100        [0.0, 0.0, 0.0, 0.0],
101        [1.0, 2.0, 0.0, 3.0],
102        [0.0, 0.0, 0.0, 0.0],
103        [1.0, 3.0, 0.0, 2.0],
104        [0.0, 0.0, 0.0, 0.0],
105        [0.0, 0.0, 0.0, 0.0],
106        [0.0, 0.0, 0.0, 0.0],
107        [2.0, 3.0, 0.0, 1.0],
108        [2.0, 3.0, 1.0, 0.0],
109        [1.0, 0.0, 2.0, 3.0],
110        [1.0, 0.0, 3.0, 2.0],
111        [0.0, 0.0, 0.0, 0.0],
112        [0.0, 0.0, 0.0, 0.0],
113        [0.0, 0.0, 0.0, 0.0],
114        [2.0, 0.0, 3.0, 1.0],
115        [0.0, 0.0, 0.0, 0.0],
116        [2.0, 1.0, 3.0, 0.0],
117        [0.0, 0.0, 0.0, 0.0],
118        [0.0, 0.0, 0.0, 0.0],
119        [0.0, 0.0, 0.0, 0.0],
120        [0.0, 0.0, 0.0, 0.0],
121        [0.0, 0.0, 0.0, 0.0],
122        [0.0, 0.0, 0.0, 0.0],
123        [0.0, 0.0, 0.0, 0.0],
124        [0.0, 0.0, 0.0, 0.0],
125        [2.0, 0.0, 1.0, 3.0],
126        [0.0, 0.0, 0.0, 0.0],
127        [0.0, 0.0, 0.0, 0.0],
128        [0.0, 0.0, 0.0, 0.0],
129        [3.0, 0.0, 1.0, 2.0],
130        [3.0, 0.0, 2.0, 1.0],
131        [0.0, 0.0, 0.0, 0.0],
132        [3.0, 1.0, 2.0, 0.0],
133        [2.0, 1.0, 0.0, 3.0],
134        [0.0, 0.0, 0.0, 0.0],
135        [0.0, 0.0, 0.0, 0.0],
136        [0.0, 0.0, 0.0, 0.0],
137        [3.0, 1.0, 0.0, 2.0],
138        [0.0, 0.0, 0.0, 0.0],
139        [3.0, 2.0, 0.0, 1.0],
140        [3.0, 2.0, 1.0, 0.0],
141    ];
142
143    fn simplex_1d(&self, f0: f32) -> f32 {
144        let i0 = (f0 * Self::SIMPLEX_SCALE).floor() as i32;
145        let i1 = i0 + 1;
146        let x0 = f0 * Self::SIMPLEX_SCALE - i0 as f32;
147        let x1 = x0 - 1.0;
148        let t0 = 1.0 - x0 * x0;
149        let t1 = 1.0 - x1 * x1;
150        let t0 = t0 * t0;
151        let t1 = t1 * t1;
152        let i0 = i32::from(self.map[(i0 & 0xFF) as usize]);
153        let mut n0 = Self::simplex_gradient_1d(i0, x0);
154        n0 *= t0 * t0;
155        let i1 = i32::from(self.map[(i1 & 0xFF) as usize]);
156        let mut n1 = Self::simplex_gradient_1d(i1, x1);
157        n1 *= t1 * t1;
158
159        0.25 * (n0 + n1)
160    }
161
162    #[allow(clippy::many_single_char_names)]
163    fn simplex_2d(&self, f0: f32, f1: f32) -> f32 {
164        const F2: f64 = 0.366_025_403;
165        const G2: f64 = 0.211_324_865;
166
167        let s = f64::from(f0 + f1) * F2 * f64::from(Self::SIMPLEX_SCALE);
168        let xs = f0 * Self::SIMPLEX_SCALE + s as f32;
169        let ys = f1 * Self::SIMPLEX_SCALE + s as f32;
170        let i = xs.floor() as i32;
171        let j = ys.floor() as i32;
172        let t = (f64::from(i) + f64::from(j)) * G2;
173        let xo = f64::from(i) - t;
174        let yo = f64::from(j) - t;
175        let x0 = f0 * Self::SIMPLEX_SCALE - xo as f32;
176        let y0 = f1 * Self::SIMPLEX_SCALE - yo as f32;
177        let ii = i.floor_modulo(256);
178        let jj = j.floor_modulo(256);
179        let (i1, j1) = if x0 > y0 { (1, 0) } else { (0, 1) };
180        let x1 = x0 - i1 as f32 + G2 as f32;
181        let y1 = y0 - j1 as f32 + G2 as f32;
182        let x2 = x0 - 1.0 + (2.0 * G2) as f32;
183        let y2 = y0 - 1.0 + (2.0 * G2) as f32;
184        let mut t0 = 0.5 - x0 * x0 - y0 * y0;
185
186        let n0 = if t0 < 0.0 {
187            0.0
188        } else {
189            let mut idx = (ii + i32::from(self.map[jj as usize])) & 0xFF;
190            t0 *= t0;
191            idx = i32::from(self.map[idx as usize]);
192            Self::simplex_gradient_2d(idx, x0, y0) * t0 * t0
193        };
194        let mut t1 = 0.5 - x1 * x1 - y1 * y1;
195        let n1 = if t1 < 0.0 {
196            0.0
197        } else {
198            let mut idx = (ii + i1 + i32::from(self.map[((jj + j1) & 0xFF) as usize])) & 0xFF;
199            t1 *= t1;
200            idx = i32::from(self.map[idx as usize]);
201            Self::simplex_gradient_2d(idx, x1, y1) * t1 * t1
202        };
203        let mut t2 = 0.5 - x2 * x2 - y2 * y2;
204        let n2 = if t2 < 0.0 {
205            0.0
206        } else {
207            let mut idx = (ii + 1 + i32::from(self.map[((jj + 1) & 0xFF) as usize])) & 0xFF;
208            t2 *= t2;
209            idx = i32::from(self.map[idx as usize]);
210            Self::simplex_gradient_2d(idx, x2, y2) * t2 * t2
211        };
212
213        40.0 * (n0 + n1 + n2)
214    }
215
216    #[allow(clippy::too_many_lines)]
217    #[allow(clippy::many_single_char_names)]
218    fn simplex_3d(&self, f0: f32, f1: f32, f2: f32) -> f32 {
219        const F3: f64 = 0.333_333_333;
220        const G3: f64 = 0.166_666_667;
221
222        let s = f64::from(f0 + f1 + f2) * F3 * f64::from(Self::SIMPLEX_SCALE);
223        let xs = f0 * Self::SIMPLEX_SCALE + s as f32;
224        let ys = f1 * Self::SIMPLEX_SCALE + s as f32;
225        let zs = f2 * Self::SIMPLEX_SCALE + s as f32;
226        let i = xs.floor() as i32;
227        let j = ys.floor() as i32;
228        let k = zs.floor() as i32;
229        let t = (f64::from(i) + f64::from(j) + f64::from(k)) * G3;
230        let xo = f64::from(i) - t;
231        let yo = f64::from(j) - t;
232        let zo = f64::from(k) - t;
233        let x0 = f0 * Self::SIMPLEX_SCALE - xo as f32;
234        let y0 = f1 * Self::SIMPLEX_SCALE - yo as f32;
235        let z0 = f2 * Self::SIMPLEX_SCALE - zo as f32;
236
237        let (i1, j1, k1, i2, j2, k2) = if x0 >= y0 {
238            if y0 >= z0 {
239                (1, 0, 0, 1, 1, 0)
240            } else if x0 >= z0 {
241                (1, 0, 0, 1, 0, 1)
242            } else {
243                (0, 0, 1, 1, 0, 1)
244            }
245        } else if y0 < z0 {
246            (0, 0, 1, 0, 1, 1)
247        } else if x0 < z0 {
248            (0, 1, 0, 0, 1, 1)
249        } else {
250            (0, 1, 0, 1, 1, 0)
251        };
252
253        let x1 = x0 - i1 as f32 + G3 as f32;
254        let y1 = y0 - j1 as f32 + G3 as f32;
255        let z1 = z0 - k1 as f32 + G3 as f32;
256        let x2 = x0 - i2 as f32 + 2.0 * G3 as f32;
257        let y2 = y0 - j2 as f32 + 2.0 * G3 as f32;
258        let z2 = z0 - k2 as f32 + 2.0 * G3 as f32;
259        let x3 = x0 - 1.0 + (3.0 * G3) as f32;
260        let y3 = y0 - 1.0 + (3.0 * G3) as f32;
261        let z3 = z0 - 1.0 + (3.0 * G3) as f32;
262        let ii = i.floor_modulo(256);
263        let jj = j.floor_modulo(256);
264        let kk = k.floor_modulo(256);
265
266        let mut t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
267        let n0 = if t0 < 0.0 {
268            0.0
269        } else {
270            let idx = i32::from(
271                self.map[((ii
272                    + i32::from(
273                        self.map[((jj + i32::from(self.map[kk as usize])) & 0xFF) as usize],
274                    ))
275                    & 0xFF) as usize],
276            );
277            t0 *= t0;
278            Self::simplex_gradient_3d(idx, x0, y0, z0) * t0 * t0
279        };
280
281        let mut t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;
282        let n1 = if t1 < 0.0 {
283            0.0
284        } else {
285            let idx = i32::from(
286                self.map[((ii
287                    + i1
288                    + i32::from(
289                        self.map[((jj + j1 + i32::from(self.map[((kk + k1) & 0xFF) as usize]))
290                            & 0xFF) as usize],
291                    ))
292                    & 0xFF) as usize],
293            );
294            t1 *= t1;
295            Self::simplex_gradient_3d(idx, x1, y1, z1) * t1 * t1
296        };
297
298        let mut t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;
299        let n2 = if t2 < 0.0 {
300            0.0
301        } else {
302            let idx = i32::from(
303                self.map[((ii
304                    + i2
305                    + i32::from(
306                        self.map[((jj + j2 + i32::from(self.map[((kk + k2) & 0xFF) as usize]))
307                            & 0xFF) as usize],
308                    ))
309                    & 0xFF) as usize],
310            );
311            t2 *= t2;
312            Self::simplex_gradient_3d(idx, x2, y2, z2) * t2 * t2
313        };
314
315        let mut t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;
316        let n3 = if t3 < 0.0 {
317            0.0
318        } else {
319            let idx = i32::from(
320                self.map[((ii
321                    + 1
322                    + i32::from(
323                        self.map[((jj + 1 + i32::from(self.map[((kk + 1) & 0xFF) as usize])) & 0xFF)
324                            as usize],
325                    ))
326                    & 0xFF) as usize],
327            );
328            t3 *= t3;
329            Self::simplex_gradient_3d(idx, x3, y3, z3) * t3 * t3
330        };
331
332        32.0 * (n0 + n1 + n2 + n3)
333    }
334
335    #[allow(clippy::too_many_lines)]
336    #[allow(clippy::many_single_char_names)]
337    fn simplex_4d(&self, f0: f32, f1: f32, f2: f32, f3: f32) -> f32 {
338        const F4: f64 = 0.309_016_994;
339        const G4: f64 = 0.138_196_601;
340
341        let s = f64::from(f0 + f1 + f2 + f3) * F4 * f64::from(Self::SIMPLEX_SCALE);
342        let xs = f0 * Self::SIMPLEX_SCALE + s as f32;
343        let ys = f1 * Self::SIMPLEX_SCALE + s as f32;
344        let zs = f2 * Self::SIMPLEX_SCALE + s as f32;
345        let ws = f3 * Self::SIMPLEX_SCALE + s as f32;
346
347        let i = xs.floor() as i32;
348        let j = ys.floor() as i32;
349        let k = zs.floor() as i32;
350        let l = ws.floor() as i32;
351
352        let t = (f64::from(i) + f64::from(j) + f64::from(k) + f64::from(l)) * G4;
353        let xo = f64::from(i) - t;
354        let yo = f64::from(j) - t;
355        let zo = f64::from(k) - t;
356        let wo = f64::from(l) - t;
357
358        let x0 = f0 * Self::SIMPLEX_SCALE - xo as f32;
359        let y0 = f1 * Self::SIMPLEX_SCALE - yo as f32;
360        let z0 = f2 * Self::SIMPLEX_SCALE - zo as f32;
361        let w0 = f3 * Self::SIMPLEX_SCALE - wo as f32;
362
363        let c1 = if x0 > y0 { 32 } else { 0 };
364        let c2 = if x0 > z0 { 16 } else { 0 };
365        let c3 = if y0 > z0 { 8 } else { 0 };
366        let c4 = if x0 > w0 { 4 } else { 0 };
367        let c5 = if y0 > w0 { 2 } else { 0 };
368        let c6 = if z0 > w0 { 1 } else { 0 };
369        let c = c1 + c2 + c3 + c4 + c5 + c6;
370
371        let i1 = if Self::SIMPLEX[c][0] >= 3.0 { 1 } else { 0 };
372        let j1 = if Self::SIMPLEX[c][1] >= 3.0 { 1 } else { 0 };
373        let k1 = if Self::SIMPLEX[c][2] >= 3.0 { 1 } else { 0 };
374        let l1 = if Self::SIMPLEX[c][3] >= 3.0 { 1 } else { 0 };
375
376        let i2 = if Self::SIMPLEX[c][0] >= 2.0 { 1 } else { 0 };
377        let j2 = if Self::SIMPLEX[c][1] >= 2.0 { 1 } else { 0 };
378        let k2 = if Self::SIMPLEX[c][2] >= 2.0 { 1 } else { 0 };
379        let l2 = if Self::SIMPLEX[c][3] >= 2.0 { 1 } else { 0 };
380
381        let i3 = if Self::SIMPLEX[c][0] >= 1.0 { 1 } else { 0 };
382        let j3 = if Self::SIMPLEX[c][1] >= 1.0 { 1 } else { 0 };
383        let k3 = if Self::SIMPLEX[c][2] >= 1.0 { 1 } else { 0 };
384        let l3 = if Self::SIMPLEX[c][3] >= 1.0 { 1 } else { 0 };
385
386        let x1 = x0 - i1 as f32 + (G4) as f32;
387        let y1 = y0 - j1 as f32 + (G4) as f32;
388        let z1 = z0 - k1 as f32 + (G4) as f32;
389        let w1 = w0 - l1 as f32 + (G4) as f32;
390        let x2 = x0 - i2 as f32 + (2.0 * G4) as f32;
391        let y2 = y0 - j2 as f32 + (2.0 * G4) as f32;
392        let z2 = z0 - k2 as f32 + (2.0 * G4) as f32;
393        let w2 = w0 - l2 as f32 + (2.0 * G4) as f32;
394        let x3 = x0 - i3 as f32 + (3.0 * G4) as f32;
395        let y3 = y0 - j3 as f32 + (3.0 * G4) as f32;
396        let z3 = z0 - k3 as f32 + (3.0 * G4) as f32;
397        let w3 = w0 - l3 as f32 + (3.0 * G4) as f32;
398        let x4 = x0 - 1.0 + (4.0 * G4) as f32;
399        let y4 = y0 - 1.0 + (4.0 * G4) as f32;
400        let z4 = z0 - 1.0 + (4.0 * G4) as f32;
401        let w4 = w0 - 1.0 + (4.0 * G4) as f32;
402
403        let ii = i.floor_modulo(256);
404        let jj = j.floor_modulo(256);
405        let kk = k.floor_modulo(256);
406        let ll = l.floor_modulo(256);
407
408        let mut t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
409        let n0 = if t0 < 0.0 {
410            0.0
411        } else {
412            let idx = i32::from(
413                self.map[((ii
414                    + i32::from(
415                        self.map[((jj
416                            + i32::from(
417                                self.map[((kk + i32::from(self.map[ll as usize])) & 0xFF) as usize],
418                            ))
419                            & 0xFF) as usize],
420                    ))
421                    & 0xFF) as usize],
422            );
423            t0 *= t0;
424            Self::simplex_gradient_4d(idx, x0, y0, z0, w0) * t0 * t0
425        };
426
427        let mut t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;
428        let n1 = if t1 < 0.0 {
429            0.0
430        } else {
431            let idx = i32::from(
432                self.map[((ii
433                    + i1
434                    + i32::from(
435                        self.map[((jj
436                            + j1
437                            + i32::from(
438                                self.map[((kk
439                                    + k1
440                                    + i32::from(self.map[((ll + l1) & 0xFF) as usize]))
441                                    & 0xFF) as usize],
442                            ))
443                            & 0xFF) as usize],
444                    ))
445                    & 0xFF) as usize],
446            );
447            t1 *= t1;
448            Self::simplex_gradient_4d(idx, x1, y1, z1, w1) * t1 * t1
449        };
450
451        let mut t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;
452        let n2 = if t2 < 0.0 {
453            0.0
454        } else {
455            let idx = i32::from(
456                self.map[((ii
457                    + i2
458                    + i32::from(
459                        self.map[((jj
460                            + j2
461                            + i32::from(
462                                self.map[((kk
463                                    + k2
464                                    + i32::from(self.map[((ll + l2) & 0xFF) as usize]))
465                                    & 0xFF) as usize],
466                            ))
467                            & 0xFF) as usize],
468                    ))
469                    & 0xFF) as usize],
470            );
471            t2 *= t2;
472            Self::simplex_gradient_4d(idx, x2, y2, z2, w2) * t2 * t2
473        };
474
475        let mut t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;
476        let n3 = if t3 < 0.0 {
477            0.0
478        } else {
479            let idx = i32::from(
480                self.map[((ii
481                    + i3
482                    + i32::from(
483                        self.map[((jj
484                            + j3
485                            + i32::from(
486                                self.map[((kk
487                                    + k3
488                                    + i32::from(self.map[((ll + l3) & 0xFF) as usize]))
489                                    & 0xFF) as usize],
490                            ))
491                            & 0xFF) as usize],
492                    ))
493                    & 0xFF) as usize],
494            );
495            t3 *= t3;
496            Self::simplex_gradient_4d(idx, x3, y3, z3, w3) * t3 * t3
497        };
498
499        let mut t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;
500        let n4 = if t4 < 0.0 {
501            0.0
502        } else {
503            let idx = i32::from(
504                self.map[((ii
505                    + 1
506                    + i32::from(
507                        self.map[((jj
508                            + 1
509                            + i32::from(
510                                self.map[((kk
511                                    + 1
512                                    + i32::from(self.map[((ll + 1) & 0xFF) as usize]))
513                                    & 0xFF) as usize],
514                            ))
515                            & 0xFF) as usize],
516                    ))
517                    & 0xFF) as usize],
518            );
519            t4 *= t4;
520            Self::simplex_gradient_4d(idx, x4, y4, z4, w4) * t4 * t4
521        };
522
523        27.0 * (n0 + n1 + n2 + n3 + n4)
524    }
525
526    fn simplex_gradient_1d(mut h: i32, x: f32) -> f32 {
527        h &= 0xF;
528        let mut grad = 1.0 + (h & 7) as f32;
529        if h & 8 == 8 {
530            grad = -grad;
531        }
532        grad * x
533    }
534
535    #[allow(clippy::many_single_char_names)]
536    fn simplex_gradient_2d(mut h: i32, x: f32, y: f32) -> f32 {
537        h &= 0x7;
538        let (u, v) = if h < 4 { (x, 2.0 * y) } else { (y, 2.0 * x) };
539        (if h & 1 == 1 { -u } else { u }) + (if h & 2 == 2 { -v } else { v })
540    }
541
542    #[allow(clippy::many_single_char_names)]
543    #[allow(unused_parens)] // Bug in stable/nightly at the time of writing.
544    fn simplex_gradient_3d(mut h: i32, x: f32, y: f32, z: f32) -> f32 {
545        h &= 0xF;
546        let u = if h < 8 { x } else { y };
547        let v = if h < 4 {
548            y
549        } else if h == 12 || h == 14 {
550            x
551        } else {
552            z
553        };
554
555        (if h & 1 == 1 { -u } else { u } + if h & 2 == 2 { -v } else { v })
556    }
557
558    #[allow(clippy::many_single_char_names)]
559    #[allow(unused_parens)] // Bug in stable/nightly at the time of writing.
560    fn simplex_gradient_4d(mut h: i32, x: f32, y: f32, z: f32, t: f32) -> f32 {
561        h &= 0x1F;
562        let u = if h < 24 { x } else { y };
563        let v = if h < 16 { y } else { z };
564        let w = if h < 8 { z } else { t };
565
566        (if h & 1 == 1 { -u } else { u }
567            + if h & 2 == 2 { -v } else { v }
568            + if h & 4 == 4 { -w } else { w })
569    }
570}