001package squidpony.squidmath;
002
003/**
004 * A container class for various interfaces and implementing classes that affect continuous noise, such as that produced
005 * by {@link WhirlingNoise} or {@link SeededNoise}, as well as static utility methods used throughout noise code.
006 * <br>
007 * Created by Tommy Ettinger on 3/17/2017.
008 */
009public class Noise {
010    public static final SeededNoise alternate = new SeededNoise(0xFEEDCAFE);
011    /**
012     * Like {@link Math#floor}, but returns a long.
013     * Doesn't consider weird doubles like INFINITY and NaN.
014     *
015     * @param t the double to find the floor for
016     * @return the floor of t, as a long
017     */
018    public static long longFloor(double t) {
019        return t >= 0.0 ? (long) t : (long) t - 1L;
020    }
021    /**
022     * Like {@link Math#floor(double)}, but takes a float and returns a long.
023     * Doesn't consider weird floats like INFINITY and NaN.
024     *
025     * @param t the double to find the floor for
026     * @return the floor of t, as a long
027     */
028    public static long longFloor(float t) {
029        return t >= 0f ? (long) t : (long) t - 1L;
030    }
031    /**
032     * Like {@link Math#floor(double)} , but returns an int.
033     * Doesn't consider weird doubles like INFINITY and NaN.
034     * @param t the float to find the floor for
035     * @return the floor of t, as an int
036     */
037    public static int fastFloor(double t) {
038        return t >= 0.0 ? (int) t : (int) t - 1;
039    }
040    /**
041     * Like {@link Math#floor(double)}, but takes a float and returns an int.
042     * Doesn't consider weird floats like INFINITY and NaN.
043     * @param t the float to find the floor for
044     * @return the floor of t, as an int
045     */
046    public static int fastFloor(float t) {
047        return t >= 0f ? (int) t : (int) t - 1;
048    }
049    /**
050     * Like {@link Math#ceil(double)}, but returns an int.
051     * Doesn't consider weird doubles like INFINITY and NaN.
052     * @param t the float to find the ceiling for
053     * @return the ceiling of t, as an int
054     */
055    public static int fastCeil(double t) {
056        return t >= 0.0 ? -(int) -t + 1: -(int)-t;
057    }
058    /**
059     * Like {@link Math#ceil(double)}, but takes a float and returns an int.
060     * Doesn't consider weird floats like INFINITY and NaN.
061     * @param t the float to find the ceiling for
062     * @return the ceiling of t, as an int
063     */
064    public static int fastCeil(float t) {
065        return t >= 0f ? -(int) -t + 1: -(int)-t;
066    }
067
068    /**
069     * Cubic-interpolates between start and end (valid doubles), with a between 0 (yields start) and 1 (yields end).
070     * Will smoothly transition toward start or end as a approaches 0 or 1, respectively. Somewhat faster than
071     * quintic interpolation ({@link #querp(double, double, double)}), but slower (and smoother) than
072     * {@link  #lerp(double, double, double)}.
073     * @param start a valid double
074     * @param end a valid double
075     * @param a a double between 0 and 1 inclusive
076     * @return a double between start and end inclusive
077     */
078    public static double cerp(final double start, final double end, double a) {
079        return (1.0 - (a *= a * (3.0 - 2.0 * a))) * start + a * end;
080    }
081
082    /**
083     * Cubic-interpolates between start and end (valid floats), with a between 0 (yields start) and 1 (yields end).
084     * Will smoothly transition toward start or end as a approaches 0 or 1, respectively. Somewhat faster than
085     * quintic interpolation ({@link #querp(float, float, float)}), but slower (and smoother) than
086     * {@link #lerp(float, float, float)}.
087     * @param start a valid float
088     * @param end a valid float
089     * @param a a float between 0 and 1 inclusive
090     * @return a float between start and end inclusive
091     */
092    public static float cerp(final float start, final float end, float a) {
093        return (1f - (a *= a * (3f - 2f * a))) * start + a * end;
094    }
095    /*
096     * Quintic-interpolates between start and end (valid doubles), with a between 0 (yields start) and 1 (yields end).
097     * Will smoothly transition toward start or end as a approaches 0 or 1, respectively.
098     * @param start a valid double, as in, not infinite or NaN
099     * @param end a valid double, as in, not infinite or NaN
100     * @param a a double between 0 and 1 inclusive
101     * @return a double between x and y inclusive
102     */
103    public static double querp(final double start, final double end, double a){
104        return (1.0 - (a *= a * a * (a * (a * 6.0 - 15.0) + 10.0))) * start + a * end;
105    }
106    /*
107     * Quintic-interpolates between start and end (valid floats), with a between 0 (yields start) and 1 (yields end).
108     * Will smoothly transition toward start or end as a approaches 0 or 1, respectively.
109     * @param start a valid float, as in, not infinite or NaN
110     * @param end a valid float, as in, not infinite or NaN
111     * @param a a float between 0 and 1 inclusive
112     * @return a float between x and y inclusive
113     */
114    public static float querp(final float start, final float end, float a){
115        return (1f - (a *= a * a * (a * (a * 6f - 15f) + 10f))) * start + a * end;
116    }
117
118
119    /**
120     * Linear-interpolates between start and end (valid doubles), with a between 0 (yields start) and 1 (yields end).
121     * @param start a valid double, as in, not infinite or NaN
122     * @param end a valid double, as in, not infinite or NaN
123     * @param a a double between 0 and 1 inclusive
124     * @return a double between x and y inclusive
125     */
126    public static double lerp(final double start, final double end, final double a) {
127        return (1.0 - a) * start + a * end;
128    }
129
130    /**
131     * Linear-interpolates between start and end (valid floats), with a between 0 (yields start) and 1 (yields end).
132     * @param start a valid float, as in, not infinite or NaN
133     * @param end a valid float, as in, not infinite or NaN
134     * @param a a float between 0 and 1 inclusive
135     * @return a float between x and y inclusive
136     */
137    public static float lerp(final float start, final float end, final float a) {
138        return (1f - a) * start + a * end;
139    }
140
141    /**
142     * Given a float {@code a} from 0.0 to 1.0 (both inclusive), this gets a float that adjusts a to be closer to the
143     * end points of that range (if less than 0.5, it gets closer to 0.0, otherwise it gets closer to 1.0).
144     * @param a a float between 0.0f and 1.0f inclusive
145     * @return a float between 0.0f and 1.0f inclusive that is more likely to be near the extremes
146     */
147    public static double emphasize(final double a)
148    {
149        return a * a * (3.0 - 2.0 * a);
150    }
151    /**
152     * Given a float {@code a} from -1.0 to 1.0 (both inclusive), this gets a float that adjusts a to be closer to the
153     * end points of that range (if less than 0, it gets closer to -1.0, otherwise it gets closer to 1.0).
154     * <br>
155     * Used by {@link ClassicNoise} and {@link  JitterNoise} to increase the frequency of high and low results, which
156     * improves the behavior of {@link Ridged2D} and other Ridged noise when it uses those noise algorithms.
157     * @param a a float between -1.0f and 1.0f inclusive
158     * @return a float between -1.0f and 1.0f inclusive that is more likely to be near the extremes
159     */
160    public static double emphasizeSigned(double a)
161    {         
162        a = a * 0.5 + 0.5;
163        return a * a * (6.0 - 4.0 * a) - 1.0;
164    }
165
166    /**
167     * Given a double {@code a} from 0.0 to 1.0 (both inclusive), this gets a double that adjusts a to be much closer to
168     * the end points of that range (if less than 0.5, it gets closer to 0.0, otherwise it gets closer to 1.0).
169     * @param a a double between 0.0 and 1.0 inclusive
170     * @return a double between 0.0 and 1.0 inclusive that is more likely to be near the extremes
171     */
172    public static double extreme(final double a)
173    {
174        return a * a * a * (a * (a * 6 - 15) + 10);
175    }
176
177    /**
178     * Given a double {@code a} from -1.0 to 1.0 (both inclusive), this gets a double that adjusts a to be much closer
179     * to the end points of that range (if less than 0, it gets closer to -1.0, otherwise it gets closer to 1.0).
180     * @param a a double between -1.0 and 1.0 inclusive
181     * @return a double between -1.0 and 1.0 inclusive that is more likely to be near the extremes
182     */
183    public static double extremeSigned(double a)
184    {
185        a = a * 0.5 + 0.5;
186        return a * a * a * (a * (a * 12 - 30) + 20) - 1.0;
187    }
188
189    public interface Noise1D {
190        double getNoise(double x);
191        double getNoiseWithSeed(double x, long seed);
192    }
193
194    public interface Noise2D {
195        double getNoise(double x, double y);
196        double getNoiseWithSeed(double x, double y, long seed);
197    }
198
199    public interface Noise3D {
200        double getNoise(double x, double y, double z);
201        double getNoiseWithSeed(double x, double y, double z, long seed);
202    }
203
204    public interface Noise4D {
205        double getNoise(double x, double y, double z, double w);
206        double getNoiseWithSeed(double x, double y, double z, double w, long seed);
207    }
208
209    public interface Noise6D {
210        double getNoise(double x, double y, double z, double w, double u, double v);
211        double getNoiseWithSeed(double x, double y, double z, double w, double u, double v, long seed);
212    }
213
214    public static class Layered1D implements Noise1D {
215        protected int octaves;
216        protected Noise1D basis;
217        public double frequency;
218        public double lacunarity;
219        public Layered1D() {
220            this(Basic1D.instance);
221        }
222
223        public Layered1D(Noise1D basis) {
224            this(basis, 2);
225        }
226
227        public Layered1D(Noise1D basis, final int octaves) {
228            this(basis, octaves, 1.0);
229        }
230        public Layered1D(Noise1D basis, final int octaves, double frequency) {
231            this(basis, octaves, frequency, 0.5);
232        }
233        public Layered1D(Noise1D basis, final int octaves, double frequency, double lacunarity) {
234            this.basis = basis;
235            this.frequency = frequency;
236            this.octaves = Math.max(1, Math.min(63, octaves));
237            this.lacunarity = lacunarity;
238        }
239
240
241        @Override
242        public double getNoise(double x) {
243            x *= frequency;
244            int s = 1;
245            double n = 0.0, i_s = 2.0;
246            for (int o = 0; o < octaves; o++, s <<= 1) {
247                n += basis.getNoise(x * (i_s *= lacunarity) + (o << 6)) * s;
248            }
249            return n / ((1 << octaves) - 1.0);
250        }
251
252        @Override
253        public double getNoiseWithSeed(double x, long seed) {
254            x *= frequency;
255            int s = 1;
256            double n = 0.0, i_s = 2.0;
257            for (int o = 0; o < octaves; o++, s <<= 1) {
258                n += basis.getNoiseWithSeed(x * (i_s *= lacunarity), (seed += 0x9E3779B97F4A7C15L)) * s;
259            }
260            return n / ((1 << octaves) - 1.0);
261        }
262    }
263
264    public static class Layered2D implements Noise2D {
265        protected int octaves;
266        protected Noise2D basis;
267        public double frequency;
268        public double lacunarity;
269        public Layered2D() {
270            this(SeededNoise.instance);
271        }
272
273        public Layered2D(Noise2D basis) {
274            this(basis, 2);
275        }
276
277        public Layered2D(Noise2D basis, final int octaves) {
278            this(basis, octaves, 1.0);
279        }
280        public Layered2D(Noise2D basis, final int octaves, double frequency) {
281            this(basis, octaves, frequency, 0.5);
282        }
283        public Layered2D(Noise2D basis, final int octaves, double frequency, double lacunarity) {
284            this.basis = basis;
285            this.frequency = frequency;
286            this.octaves = Math.max(1, Math.min(63, octaves));
287            this.lacunarity = lacunarity;
288        }
289
290        @Override
291        public double getNoise(double x, double y) {
292            x *= frequency;
293            y *= frequency;
294            int s = 1;
295            double n = 0.0, i_s = 2.0;
296            for (int o = 0; o < octaves; o++, s <<= 1) {
297                n += basis.getNoise(x * (i_s *= lacunarity) + (o << 6), y * i_s + (o << 7)) * s;
298            }
299            return n / ((1 << octaves) - 1.0);
300        }
301
302        @Override
303        public double getNoiseWithSeed(double x, double y, long seed) {
304            x *= frequency;
305            y *= frequency;
306            int s = 1;
307            double n = 0.0, i_s = 2.0;
308            for (int o = 0; o < octaves; o++, s <<= 1) {
309                n += basis.getNoiseWithSeed(x * (i_s *= lacunarity), y * i_s, (seed += 0x9E3779B97F4A7C15L)) * s;
310            }
311            return n / ((1 << octaves) - 1.0);
312        }
313    }
314    public static class Layered3D implements Noise3D {
315        protected int octaves;
316        protected Noise3D basis;
317        public double frequency;
318        public double lacunarity;
319        public Layered3D() {
320            this(SeededNoise.instance);
321        }
322
323        public Layered3D(Noise3D basis) {
324            this(basis, 2);
325        }
326
327        public Layered3D(Noise3D basis, final int octaves) {
328            this(basis, octaves, 1.0);
329        }
330        public Layered3D(Noise3D basis, final int octaves, double frequency) {
331            this(basis, octaves, frequency, 0.5);
332        }
333        public Layered3D(Noise3D basis, final int octaves, double frequency, double lacunarity) {
334            this.basis = basis;
335            this.frequency = frequency;
336            this.octaves = Math.max(1, Math.min(63, octaves));
337            this.lacunarity = lacunarity;
338        }
339
340        @Override
341        public double getNoise(double x, double y, double z) {
342            x *= frequency;
343            y *= frequency;
344            z *= frequency;
345            int s = 1;
346            double n = 0.0, i_s = 2.0;
347            for (int o = 0; o < octaves; o++, s <<= 1) {
348                n += basis.getNoise(x * (i_s *= lacunarity) + (o << 6), y * i_s + (o << 7), z * i_s + (o << 8)) * s;
349            }
350            return n / ((1 << octaves) - 1.0);
351        }
352
353        @Override
354        public double getNoiseWithSeed(double x, double y, double z, long seed) {
355            x *= frequency;
356            y *= frequency;
357            z *= frequency;
358            int s = 1;
359            double n = 0.0, i_s = 2.0;
360            for (int o = 0; o < octaves; o++, s <<= 1) {
361                n += basis.getNoiseWithSeed(x * (i_s *= lacunarity), y * i_s, z * i_s, (seed += 0x9E3779B97F4A7C15L)) * s;
362            }
363            return n / ((1 << octaves) - 1.0);
364        }
365    }
366    public static class Layered4D implements Noise4D {
367        protected int octaves;
368        protected Noise4D basis;
369        public double frequency;
370        public double lacunarity;
371        public Layered4D() {
372            this(SeededNoise.instance);
373        }
374
375        public Layered4D(Noise4D basis) {
376            this(basis, 2);
377        }
378
379        public Layered4D(Noise4D basis, final int octaves) {
380            this(basis, octaves, 1.0);
381        }
382        public Layered4D(Noise4D basis, final int octaves, double frequency) {
383            this(basis, octaves, frequency, 0.5);
384        }
385        public Layered4D(Noise4D basis, final int octaves, double frequency, double lacunarity) {
386            this.basis = basis;
387            this.frequency = frequency;
388            this.octaves = Math.max(1, Math.min(63, octaves));
389            this.lacunarity = lacunarity;
390        }
391
392        @Override
393        public double getNoise(double x, double y, double z, double w) {
394            x *= frequency;
395            y *= frequency;
396            z *= frequency;
397            w *= frequency;
398            int s = 1;
399            double n = 0.0, i_s = 2.0;
400            for (int o = 0; o < octaves; o++, s <<= 1) {
401                n += basis.getNoise(x * (i_s *= lacunarity) + (o << 6), y * i_s + (o << 7), z * i_s + (o << 8), w * i_s + (o << 9)) * s;
402            }
403            return n / ((1 << octaves) - 1.0);
404        }
405
406        @Override
407        public double getNoiseWithSeed(double x, double y, double z, double w, long seed) {
408            x *= frequency;
409            y *= frequency;
410            z *= frequency;
411            w *= frequency;
412            int s = 1;
413            double n = 0.0, i_s = 2.0;
414            for (int o = 0; o < octaves; o++, s <<= 1) {
415                n += basis.getNoiseWithSeed(x * (i_s *= lacunarity), y * i_s, z * i_s, w * i_s, (seed += 0x9E3779B97F4A7C15L)) * s;
416            }
417            return n / ((1 << octaves) - 1.0);
418        }
419    }
420    public static class Layered6D implements Noise6D {
421        protected int octaves;
422        protected Noise6D basis;
423        public double frequency;
424        public double lacunarity;
425        public Layered6D() {
426            this(SeededNoise.instance);
427        }
428
429        public Layered6D(Noise6D basis) {
430            this(basis, 2);
431        }
432
433        public Layered6D(Noise6D basis, final int octaves) {
434            this(basis, octaves, 1.0);
435        }
436        public Layered6D(Noise6D basis, final int octaves, double frequency) {
437            this(basis, octaves, frequency, 0.5);
438        }
439        public Layered6D(Noise6D basis, final int octaves, double frequency, double lacunarity) {
440            this.basis = basis;
441            this.frequency = frequency;
442            this.octaves = Math.max(1, Math.min(63, octaves));
443            this.lacunarity = lacunarity;
444        }
445
446        @Override
447        public double getNoise(double x, double y, double z, double w, double u, double v) {
448            x *= frequency;
449            y *= frequency;
450            z *= frequency;
451            w *= frequency;
452            u *= frequency;
453            v *= frequency;
454            int s = 1;
455            double n = 0.0, i_s = 2.0;
456            for (int o = 0; o < octaves; o++, s <<= 1) {
457                n += basis.getNoise(x * (i_s *= lacunarity) + (o << 6), y * i_s + (o << 7), z * i_s + (o << 8)
458                        , w * i_s + (o << 9), u * i_s + (o << 10), v * i_s + (o << 11)) * s;
459            }
460            return n / ((1 << octaves) - 1.0);
461        }
462
463        @Override
464        public double getNoiseWithSeed(double x, double y, double z, double w, double u, double v, long seed) {
465            x *= frequency;
466            y *= frequency;
467            z *= frequency;
468            w *= frequency;
469            u *= frequency;
470            v *= frequency;
471            int s = 1;
472            double n = 0.0, i_s = 2.0;
473            for (int o = 0; o < octaves; o++, s <<= 1) {
474                n += basis.getNoiseWithSeed(x * (i_s *= lacunarity), y * i_s, z * i_s
475                        , w * i_s, u * i_s, v * i_s, (seed += 0x9E3779B97F4A7C15L)) * s;
476            }
477            return n / ((1 << octaves) - 1.0);
478        }
479    }
480    
481    public static class InverseLayered1D implements Noise1D {
482        protected int octaves;
483        protected Noise1D basis;
484        public double frequency;
485        /**
486         * A multiplier that affects how much the frequency changes with each layer; the default is 0.5 .
487         */
488        public double lacunarity = 0.5;
489        public InverseLayered1D() {
490            this(Basic1D.instance);
491        }
492
493        public InverseLayered1D(Noise1D basis) {
494            this(basis, 2);
495        }
496
497        public InverseLayered1D(Noise1D basis, final int octaves) {
498            this(basis, octaves, 1.0);
499        }
500        public InverseLayered1D(Noise1D basis, final int octaves, double frequency) {
501            this.basis = basis;
502            this.frequency = frequency;
503            this.octaves = Math.max(1, Math.min(63, octaves));
504        }
505        public InverseLayered1D(Noise1D basis, final int octaves, double frequency, double lacunarity){
506            this(basis, octaves, frequency);
507            this.lacunarity = lacunarity;
508        }
509
510        @Override
511        public double getNoise(double x) {
512            x *= frequency;
513            int s = 1 << (octaves - 1);
514            double n = 0.0, i_s = 2.0;
515            for (int o = 0; o < octaves; o++, s >>= 1) {
516                n += basis.getNoise(x * (i_s *= lacunarity) + (o << 6)) * s;
517            }
518            return n / ((1 << octaves) - 1.0);
519        }
520
521        @Override
522        public double getNoiseWithSeed(double x, long seed) {
523            x *= frequency;
524            int s = 1 << (octaves - 1);
525            double n = 0.0, i_s = 2.0;
526            for (int o = 0; o < octaves; o++, s >>= 1) {
527                n += basis.getNoiseWithSeed(x * (i_s *= lacunarity), (seed += 0x9E3779B97F4A7C15L)) * s;
528            }
529            return n / ((1 << octaves) - 1.0);
530        }
531    }
532
533    public static class InverseLayered2D implements Noise2D {
534        protected int octaves;
535        protected Noise2D basis;
536        public double frequency;
537        /**
538         * A multiplier that affects how much the frequency changes with each layer; the default is 0.5 .
539         */
540        public double lacunarity = 0.5;
541        public InverseLayered2D() {
542            this(SeededNoise.instance, 2);
543        }
544
545        public InverseLayered2D(Noise2D basis) {
546            this(basis, 2);
547        }
548
549        public InverseLayered2D(Noise2D basis, final int octaves) {
550            this(basis, octaves, 1.0);
551        }
552        public InverseLayered2D(Noise2D basis, final int octaves, double frequency) {
553            this.basis = basis;
554            this.frequency = frequency;
555            this.octaves = Math.max(1, Math.min(63, octaves));
556        }
557        public InverseLayered2D(Noise2D basis, final int octaves, double frequency, double lacunarity){
558            this(basis, octaves, frequency);
559            this.lacunarity = lacunarity;
560        }
561
562        @Override
563        public double getNoise(double x, double y) {
564            x *= frequency;
565            y *= frequency;
566            int s = 1 << (octaves - 1);
567            double n = 0.0, i_s = 2.0;
568            for (int o = 0; o < octaves; o++, s >>= 1) {
569                n += basis.getNoise(x * (i_s *= lacunarity) + (o << 6), y * i_s + (o << 7)) * s;
570            }
571            return n / ((1 << octaves) - 1.0);
572        }
573
574        @Override
575        public double getNoiseWithSeed(double x, double y, long seed) {
576            x *= frequency;
577            y *= frequency;
578            int s = 1 << (octaves - 1);
579            double n = 0.0, i_s = 2.0;
580            for (int o = 0; o < octaves; o++, s >>= 1) {
581                n += basis.getNoiseWithSeed(x * (i_s *= lacunarity), y * i_s, (seed += 0x9E3779B97F4A7C15L)) * s;
582            }
583            return n / ((1 << octaves) - 1.0);
584        }
585    }
586    public static class InverseLayered3D implements Noise3D {
587        protected int octaves;
588        protected Noise3D basis;
589        public double frequency;
590        /**
591         * A multiplier that affects how much the frequency changes with each layer; the default is 0.5 .
592         */
593        public double lacunarity = 0.5;
594        public InverseLayered3D() {
595            this(SeededNoise.instance, 2);
596        }
597
598        public InverseLayered3D(Noise3D basis) {
599            this(basis, 2);
600        }
601
602        public InverseLayered3D(Noise3D basis, final int octaves) {
603            this(basis, octaves, 1.0);
604        }
605        public InverseLayered3D(Noise3D basis, final int octaves, double frequency) {
606            this.basis = basis;
607            this.frequency = frequency;
608            this.octaves = Math.max(1, Math.min(63, octaves));
609        }
610        public InverseLayered3D(Noise3D basis, final int octaves, double frequency, double lacunarity){
611            this(basis, octaves, frequency);
612            this.lacunarity = lacunarity;
613        }
614
615        @Override
616        public double getNoise(double x, double y, double z) {
617            x *= frequency;
618            y *= frequency;
619            z *= frequency;
620            int s = 1 << (octaves - 1);
621            double n = 0.0, i_s = 2.0;
622            for (int o = 0; o < octaves; o++, s >>= 1) {
623                n += basis.getNoise(x * (i_s *= lacunarity) + (o << 6), y * i_s + (o << 7), z * i_s + (o << 8)) * s;
624            }
625            return n / ((1 << octaves) - 1.0);
626        }
627
628        @Override
629        public double getNoiseWithSeed(double x, double y, double z, long seed) {
630            x *= frequency;
631            y *= frequency;
632            z *= frequency;
633            int s = 1 << (octaves - 1);
634            double n = 0.0, i_s = 2.0;
635            for (int o = 0; o < octaves; o++, s >>= 1) {
636                n += basis.getNoiseWithSeed(x * (i_s *= lacunarity), y * i_s, z * i_s, (seed += 0x9E3779B97F4A7C15L)) * s;
637            }
638            return n / ((1 << octaves) - 1.0);
639        }
640    }
641    public static class InverseLayered4D implements Noise4D {
642        protected int octaves;
643        protected Noise4D basis;
644        public double frequency;
645        /**
646         * A multiplier that affects how much the frequency changes with each layer; the default is 0.5 .
647         */
648        public double lacunarity = 0.5;
649        public InverseLayered4D() {
650            this(SeededNoise.instance, 2);
651        }
652
653        public InverseLayered4D(Noise4D basis) {
654            this(basis, 2);
655        }
656
657        public InverseLayered4D(Noise4D basis, final int octaves) {
658            this(basis, octaves, 1.0);
659        }
660        public InverseLayered4D(Noise4D basis, final int octaves, double frequency) {
661            this.basis = basis;
662            this.frequency = frequency;
663            this.octaves = Math.max(1, Math.min(63, octaves));
664        }
665        public InverseLayered4D(Noise4D basis, final int octaves, double frequency, double lacunarity){
666            this(basis, octaves, frequency);
667            this.lacunarity = lacunarity;
668        }
669
670        @Override
671        public double getNoise(double x, double y, double z, double w) {
672            x *= frequency;
673            y *= frequency;
674            z *= frequency;
675            w *= frequency;
676            int s = 1 << (octaves - 1);
677            double n = 0.0, i_s = 2.0;
678            for (int o = 0; o < octaves; o++, s >>= 1) {
679                n += basis.getNoise(x * (i_s *= lacunarity) + (o << 6), y * i_s + (o << 7), z * i_s + (o << 8), w * i_s + (o << 9)) * s;
680            }
681            return n / ((1 << octaves) - 1.0);
682        }
683
684        @Override
685        public double getNoiseWithSeed(double x, double y, double z, double w, long seed) {
686            x *= frequency;
687            y *= frequency;
688            z *= frequency;
689            w *= frequency;
690            int s = 1 << (octaves - 1);
691            double n = 0.0, i_s = 2.0;
692            for (int o = 0; o < octaves; o++, s >>= 1) {
693                n += basis.getNoiseWithSeed(x * (i_s *= lacunarity), y * i_s, z * i_s, w * i_s, (seed += 0x9E3779B97F4A7C15L)) * s;
694            }
695            return n / ((1 << octaves) - 1.0);
696        }
697    }
698    public static class InverseLayered6D implements Noise6D {
699        protected int octaves;
700        protected Noise6D basis;
701        public double frequency;
702        /**
703         * A multiplier that affects how much the frequency changes with each layer; the default is 0.5 .
704         */
705        public double lacunarity = 0.5;
706        public InverseLayered6D() {
707            this(SeededNoise.instance, 2);
708        }
709
710        public InverseLayered6D(Noise6D basis) {
711            this(basis, 2);
712        }
713
714        public InverseLayered6D(Noise6D basis, final int octaves) {
715            this(basis, octaves, 1.0);
716        }
717        public InverseLayered6D(Noise6D basis, final int octaves, double frequency) {
718            this.basis = basis;
719            this.frequency = frequency;
720            this.octaves = Math.max(1, Math.min(63, octaves));
721        }
722        public InverseLayered6D(Noise6D basis, final int octaves, double frequency, double lacunarity){
723            this(basis, octaves, frequency);
724            this.lacunarity = lacunarity;
725        }
726
727        @Override
728        public double getNoise(double x, double y, double z, double w, double u, double v) {
729            x *= frequency;
730            y *= frequency;
731            z *= frequency;
732            w *= frequency;
733            u *= frequency;
734            v *= frequency;
735            int s = 1 << (octaves - 1);
736            double n = 0.0, i_s = 2.0;
737            for (int o = 0; o < octaves; o++, s >>= 1) {
738                n += basis.getNoise(x * (i_s *= lacunarity) + (o << 6), y * i_s + (o << 7), z * i_s + (o << 8)
739                        , w * i_s + (o << 9), u * i_s + (o << 10), v * i_s + (o << 11)) * s;
740            }
741            return n / ((1 << octaves) - 1.0);
742        }
743
744        @Override
745        public double getNoiseWithSeed(double x, double y, double z, double w, double u, double v, long seed) {
746            x *= frequency;
747            y *= frequency;
748            z *= frequency;
749            w *= frequency;
750            u *= frequency;
751            v *= frequency;
752            int s = 1 << (octaves - 1);
753            double n = 0.0, i_s = 2.0;
754            for (int o = 0; o < octaves; o++, s >>= 1) {
755                n += basis.getNoiseWithSeed(x * (i_s *= lacunarity), y * i_s, z * i_s
756                        , w * i_s, u * i_s, v * i_s, (seed += 0x9E3779B97F4A7C15L)) * s;
757            }
758            return n / ((1 << octaves) - 1.0);
759        }
760    }
761
762
763    public static class Scaled1D implements Noise1D {
764        protected double scaleX;
765        protected Noise1D basis;
766
767        public Scaled1D() {
768            this(Basic1D.instance);
769        }
770
771        public Scaled1D(Noise1D basis) {
772            this(basis, 2.0);
773        }
774
775        public Scaled1D(Noise1D basis, final double scaleX) {
776            this.basis = basis;
777            this.scaleX = scaleX;
778        }
779
780        @Override
781        public double getNoise(final double x) {
782            return basis.getNoise(x * scaleX);
783        }
784
785        @Override
786        public double getNoiseWithSeed(final double x, long seed) {
787            return basis.getNoiseWithSeed(x * scaleX, seed);
788        }
789    }
790
791    public static class Scaled2D implements Noise2D {
792        protected double scaleX, scaleY;
793        protected Noise2D basis;
794
795        public Scaled2D() {
796            this(SeededNoise.instance);
797        }
798
799        public Scaled2D(Noise2D basis) {
800            this(basis, 2.0, 2.0);
801        }
802
803        public Scaled2D(Noise2D basis, double scale) {
804            this(basis, scale, scale);
805        }
806
807        public Scaled2D(Noise2D basis, final double scaleX, final double scaleY) {
808            this.basis = basis;
809            this.scaleX = scaleX;
810            this.scaleY = scaleY;
811        }
812
813        @Override
814        public double getNoise(final double x, final double y) {
815            return basis.getNoise(x * scaleX, y * scaleY);
816        }
817
818        @Override
819        public double getNoiseWithSeed(final double x, final double y, long seed) {
820            return basis.getNoiseWithSeed(x * scaleX, y * scaleY, seed);
821        }
822    }
823    public static class Scaled3D implements Noise3D {
824        protected double scaleX, scaleY, scaleZ;
825        protected Noise3D basis;
826
827        public Scaled3D() {
828            this(SeededNoise.instance);
829        }
830
831        public Scaled3D(Noise3D basis) {
832            this(basis, 2.0, 2.0, 2.0);
833        }
834
835        public Scaled3D(Noise3D basis, double scale) {
836            this(basis, scale, scale, scale);
837        }
838
839        public Scaled3D(Noise3D basis, final double scaleX, final double scaleY, final double scaleZ) {
840            this.basis = basis;
841            this.scaleX = scaleX;
842            this.scaleY = scaleY;
843            this.scaleZ = scaleZ;
844        }
845
846        @Override
847        public double getNoise(final double x, final double y, final double z) {
848            return basis.getNoise(x * scaleX, y * scaleY, z * scaleZ);
849        }
850
851        @Override
852        public double getNoiseWithSeed(final double x, final double y, final double z, long seed) {
853            return basis.getNoiseWithSeed(x * scaleX, y * scaleY, z * scaleZ, seed);
854        }
855    }
856    public static class Scaled4D implements Noise4D {
857        protected double scaleX, scaleY, scaleZ, scaleW;
858        protected Noise4D basis;
859
860        public Scaled4D() {
861            this(SeededNoise.instance);
862        }
863
864        public Scaled4D(Noise4D basis) {
865            this(basis, 2.0, 2.0, 2.0, 2.0);
866        }
867
868        public Scaled4D(Noise4D basis, double scale) {
869            this(basis, scale, scale, scale, scale);
870        }
871
872        public Scaled4D(Noise4D basis, final double scaleX, final double scaleY, final double scaleZ, final double scaleW) {
873            this.basis = basis;
874            this.scaleX = scaleX;
875            this.scaleY = scaleY;
876            this.scaleZ = scaleZ;
877            this.scaleW = scaleW;
878        }
879
880        @Override
881        public double getNoise(final double x, final double y, final double z, final double w) {
882            return basis.getNoise(x * scaleX, y * scaleY, z * scaleZ, w * scaleW);
883        }
884
885        @Override
886        public double getNoiseWithSeed(final double x, final double y, final double z, final double w, long seed) {
887            return basis.getNoiseWithSeed(x * scaleX, y * scaleY, z * scaleZ, w * scaleW, seed);
888        }
889    }
890    public static class Scaled6D implements Noise6D {
891        protected double scaleX, scaleY, scaleZ, scaleW, scaleU, scaleV;
892        protected Noise6D basis;
893
894        public Scaled6D() {
895            this(SeededNoise.instance);
896        }
897
898        public Scaled6D(Noise6D basis) {
899            this(basis, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0);
900        }
901
902        public Scaled6D(Noise6D basis, double scale) {
903            this(basis, scale, scale, scale, scale, scale, scale);
904        }
905
906        public Scaled6D(Noise6D basis, final double scaleX, final double scaleY, final double scaleZ,
907                        final double scaleW, final double scaleU, final double scaleV) {
908            this.basis = basis;
909            this.scaleX = scaleX;
910            this.scaleY = scaleY;
911            this.scaleZ = scaleZ;
912            this.scaleW = scaleW;
913            this.scaleU = scaleU;
914            this.scaleV = scaleV;
915        }
916
917        @Override
918        public double getNoise(final double x, final double y, final double z, final double w,
919                               final double u, final double v) {
920            return basis.getNoise(x * scaleX, y * scaleY, z * scaleZ, w * scaleW, u * scaleU, v * scaleV);
921        }
922
923        @Override
924        public double getNoiseWithSeed(final double x, final double y, final double z, final double w,
925                                       final double u, final double v, long seed) {
926            return basis.getNoiseWithSeed(x * scaleX, y * scaleY, z * scaleZ, w * scaleW, u * scaleU,
927                    v * scaleV, seed);
928        }
929    }
930
931    public static class Ridged2D implements Noise2D {
932        protected int octaves;
933        public double frequency;
934        protected double correct;
935        protected Noise2D basis;
936
937        public Ridged2D() {
938            this(SeededNoise.instance, 2, 1.25);
939        }
940
941        public Ridged2D(Noise2D basis) {
942            this(basis, 2, 1.25);
943        }
944
945        public Ridged2D(Noise2D basis, int octaves, double frequency) {
946            this.basis = basis;
947            this.frequency = frequency;
948            setOctaves(octaves);
949        }
950
951        public void setOctaves(int octaves)
952        {
953            this.octaves = (octaves = Math.max(1, Math.min(63, octaves)));
954            correct = 1.0;
955            for (int o = 1; o < octaves; o++) {
956                correct += Math.pow(2.0, -o);
957            }
958            correct = 2.0 / correct;
959        }
960
961
962        @Override
963        public double getNoise(double x, double y) {
964            double sum = 0, amp = 1.0;
965            x *= frequency;
966            y *= frequency;
967            for (int i = 0; i < octaves; ++i) {
968                double n = basis.getNoise(x + (i << 6), y + (i << 7));
969                n = 1.0 - Math.abs(n);
970                sum += amp * n;
971                amp *= 0.5;
972                x *= 2.0;
973                y *= 2.0;
974            }
975            return sum * correct - 1.0;
976        }
977
978        @Override
979        public double getNoiseWithSeed(double x, double y, long seed) {
980            double sum = 0, amp = 1.0;
981            x *= frequency;
982            y *= frequency;
983            for (int i = 0; i < octaves; ++i) {
984                double n = basis.getNoiseWithSeed(x, y, (seed += 0x9E3779B97F4A7C15L));
985                n = 1.0 - Math.abs(n);
986                sum += amp * n;
987                amp *= 0.5;
988                x *= 2.0;
989                y *= 2.0;
990            }
991            return sum * correct - 1.0;
992        }
993    }
994
995    public static class Ridged3D implements Noise3D {
996        protected int octaves;
997        public double frequency;
998        protected double correct;
999        protected Noise3D basis;
1000        public Ridged3D() {
1001            this(SeededNoise.instance, 2, 1.25);
1002        }
1003
1004        public Ridged3D(Noise3D basis) {
1005            this(basis, 2, 1.25);
1006        }
1007
1008        public Ridged3D(Noise3D basis, int octaves) {
1009            this(basis, octaves, 1.25);
1010        }
1011        public Ridged3D(Noise3D basis, int octaves, double frequency) {
1012            this.basis = basis;
1013            this.frequency = frequency;
1014            setOctaves(octaves);
1015        }
1016        public void setOctaves(int octaves)
1017        {
1018            this.octaves = (octaves = Math.max(1, Math.min(63, octaves)));
1019            correct = 1.0;
1020            for (int o = 1; o < octaves; o++) {
1021                correct += Math.pow(2.0, -o);
1022            }
1023            correct = 2.0 / correct;
1024        }
1025
1026        @Override
1027        public double getNoise(double x, double y, double z) {
1028            double sum = 0, amp = 1.0;
1029            x *= frequency;
1030            y *= frequency;
1031            z *= frequency;
1032            for (int i = 0; i < octaves; ++i) {
1033                double n = basis.getNoise(x + (i << 6), y + (i << 7), z + (i << 8));
1034                n = 1.0 - Math.abs(n);
1035                sum += amp * n;
1036                amp *= 0.5;
1037                x *= 2.0;
1038                y *= 2.0;
1039                z *= 2.0;
1040            }
1041            return sum * correct - 1.0;
1042        }
1043
1044        @Override
1045        public double getNoiseWithSeed(double x, double y, double z, long seed) {
1046            double sum = 0, amp = 1.0;
1047            x *= frequency;
1048            y *= frequency;
1049            z *= frequency;
1050            for (int i = 0; i < octaves; ++i) {
1051                double n = basis.getNoiseWithSeed(x, y, z, (seed += 0x9E3779B97F4A7C15L));
1052                n = 1.0 - Math.abs(n);
1053                sum += amp * n;
1054                amp *= 0.5;
1055                x *= 2.0;
1056                y *= 2.0;
1057                z *= 2.0;
1058            }
1059            return sum * correct - 1.0;
1060        }
1061    }
1062
1063
1064    public static class Ridged4D implements Noise4D {
1065        public double[] exp;
1066        protected int octaves;
1067        public double frequency, correct;
1068        public Noise4D basis;
1069
1070        public Ridged4D() {
1071            this(SeededNoise.instance, 2, 1.25);
1072        }
1073
1074        public Ridged4D(Noise4D basis) {
1075            this(basis, 2, 1.25);
1076        }
1077
1078        public Ridged4D(Noise4D basis, int octaves, double frequency) {
1079            this.basis = basis;
1080            this.frequency = frequency;
1081            setOctaves(octaves);
1082        }
1083        public void setOctaves(int octaves)
1084        {
1085            this.octaves = (octaves = Math.max(1, Math.min(63, octaves)));
1086            exp = new double[octaves];
1087            double maxvalue = 0.0;
1088            for (int i = 0; i < octaves; ++i) {
1089                maxvalue += (exp[i] = Math.pow(2.0, -i));
1090            }
1091            correct = 2.0 / maxvalue;
1092        }
1093
1094        @Override
1095        public double getNoise(double x, double y, double z, double w) {
1096            double sum = 0.0, n;
1097            x *= frequency;
1098            y *= frequency;
1099            z *= frequency;
1100            w *= frequency;
1101            for (int i = 0; i < octaves; ++i) {
1102                n = basis.getNoise(x + (i << 6), y + (i << 7), z + (i << 8), w + (i << 9));
1103                n = 1.0 - Math.abs(n);
1104                sum += n * n * exp[i];
1105                x *= 2.0;
1106                y *= 2.0;
1107                z *= 2.0;
1108                w *= 2.0;
1109            }
1110            return sum * correct - 1.0;
1111        }
1112
1113        @Override
1114        public double getNoiseWithSeed(double x, double y, double z, double w, long seed) {
1115            double sum = 0, n;
1116            x *= frequency;
1117            y *= frequency;
1118            z *= frequency;
1119            w *= frequency;
1120            for (int i = 0; i < octaves; ++i) {
1121                n = basis.getNoiseWithSeed(x, y, z, w, (seed += 0x9E3779B97F4A7C15L));
1122                n = 1.0 - Math.abs(n);
1123                sum += n * n * exp[i];
1124                x *= 2.0;
1125                y *= 2.0;
1126                z *= 2.0;
1127                w *= 2.0;
1128            }
1129            return sum * correct - 1.0;
1130        }
1131    }
1132
1133
1134    public static class Ridged6D implements Noise6D
1135    {
1136        protected double[] exp;
1137        protected int octaves;
1138        public double frequency, correct;
1139        public Noise6D basis;
1140        public Ridged6D()
1141        {
1142            this(SeededNoise.instance, 2, 1.25);
1143        }
1144        public Ridged6D(Noise6D basis)
1145        {
1146            this(basis, 2, 1.25);
1147        }
1148        public Ridged6D(Noise6D basis, int octaves, double frequency)
1149        {
1150            this.basis = basis;
1151            this.frequency = frequency;
1152            setOctaves(octaves);
1153        }
1154        public void setOctaves(int octaves)
1155        {
1156            this.octaves = (octaves = Math.max(1, Math.min(63, octaves)));
1157            exp = new double[octaves];
1158            double maxvalue = 0.0;
1159            for (int i = 0; i < octaves; ++i) {
1160                maxvalue += (exp[i] = Math.pow(2.0, -i));
1161            }
1162            correct = 2.0 / maxvalue;
1163        }
1164
1165        @Override
1166        public double getNoise(double x, double y, double z, double w, double u, double v) {
1167            double sum = 0.0, n;
1168            x *= frequency;
1169            y *= frequency;
1170            z *= frequency;
1171            w *= frequency;
1172            u *= frequency;
1173            v *= frequency;
1174
1175            for (int i = 0; i < octaves; ++i) {
1176                n = basis.getNoise(x + (i << 6), y + (i << 7), z + (i << 8), w + (i << 9), u + (i << 10), v + (i << 11));
1177                n = 1.0 - Math.abs(n);
1178                sum += n * n * exp[i];
1179                x *= 2.0;
1180                y *= 2.0;
1181                z *= 2.0;
1182                w *= 2.0;
1183                u *= 2.0;
1184                v *= 2.0;
1185            }
1186            return sum * correct - 1.0;
1187        }
1188
1189        @Override
1190        public double getNoiseWithSeed(double x, double y, double z, double w, double u, double v, long seed) {
1191            double sum = 0, n;
1192            x *= frequency;
1193            y *= frequency;
1194            z *= frequency;
1195            w *= frequency;
1196            u *= frequency;
1197            v *= frequency;
1198            for (int i = 0; i < octaves; ++i) {
1199                n = basis.getNoiseWithSeed(x, y, z,
1200                        w, u, v, (seed += 0x9E3779B97F4A7C15L));
1201                n = 1.0 - Math.abs(n);
1202                sum += n * n * exp[i];
1203                x *= 2.0;
1204                y *= 2.0;
1205                z *= 2.0;
1206                w *= 2.0;
1207                u *= 2.0;
1208                v *= 2.0;
1209            }
1210            return sum * correct - 1.0;
1211        }
1212    }
1213
1214    public static class Turbulent2D implements Noise2D {
1215        protected int octaves;
1216        protected Noise2D basis, disturbance;
1217        public double frequency;
1218        public final double correct;
1219
1220        public Turbulent2D() {
1221            this(SeededNoise.instance, alternate, 1);
1222        }
1223
1224        public Turbulent2D(Noise2D basis, Noise2D disturb) {
1225            this(basis, disturb, 1);
1226        }
1227
1228        public Turbulent2D(Noise2D basis, Noise2D disturb, final int octaves) {
1229            this(basis, disturb, octaves, 1.0);
1230        }
1231        public Turbulent2D(Noise2D basis, Noise2D disturb, final int octaves, final double frequency) {
1232            this.basis = basis;
1233            this.frequency = frequency;
1234            disturbance = disturb;
1235            this.octaves = Math.max(1, Math.min(63, octaves));
1236            correct = 1.0 / ((1 << this.octaves) - 1.0);
1237        }
1238
1239        @Override
1240        public double getNoise(double x, double y) {
1241            x *= frequency;
1242            y *= frequency;
1243            x += disturbance.getNoise(x, y);
1244            int s = 1;
1245            double n = 0.0, i_s = 2.0;
1246            for (int o = 0; o < octaves; o++, s <<= 1) {
1247                i_s *= 0.5;
1248                n += basis.getNoise(x * i_s + (o << 6), y * i_s + (o << 7)) * s;
1249            }
1250            return n * correct;
1251        }
1252
1253        @Override
1254        public double getNoiseWithSeed(double x, double y, long seed) {
1255            x *= frequency;
1256            y *= frequency;
1257            x += disturbance.getNoiseWithSeed(x, y, seed);
1258            int s = 1;
1259            double n = 0.0, i_s = 2.0;
1260            for (int o = 0; o < octaves; o++, s <<= 1) {
1261                i_s *= 0.5;
1262                n += basis.getNoiseWithSeed(x * i_s, y * i_s, seed += 0x9E3779B97F4A7C15L) * s;
1263            }
1264            return n * correct;
1265        }
1266    }
1267    public static class Turbulent3D implements Noise3D {
1268        protected int octaves;
1269        protected Noise3D basis, disturbance;
1270        public double frequency;
1271        public final double correct;
1272
1273        public Turbulent3D() {
1274            this(SeededNoise.instance, alternate, 1);
1275        }
1276
1277        public Turbulent3D(Noise3D basis, Noise3D disturb) {
1278            this(basis, disturb, 1);
1279        }
1280
1281        public Turbulent3D(Noise3D basis, Noise3D disturb, final int octaves) {
1282            this(basis, disturb, octaves, 1.0);
1283        }
1284        public Turbulent3D(Noise3D basis, Noise3D disturb, final int octaves, final double frequency) {
1285            this.basis = basis;
1286            this.frequency = frequency;
1287            disturbance = disturb;
1288            this.octaves = Math.max(1, Math.min(63, octaves));
1289            correct = 1.0 / ((1 << this.octaves) - 1.0);
1290        }
1291
1292        @Override
1293        public double getNoise(double x, double y, double z) {
1294            x *= frequency;
1295            y *= frequency;
1296            z *= frequency;
1297            x += disturbance.getNoise(x, y, z);
1298            int s = 1;
1299            double n = 0.0, i_s = 2.0;
1300            for (int o = 0; o < octaves; o++, s <<= 1) {
1301                i_s *= 0.5;
1302                n += basis.getNoise(x * i_s + (o << 6), y * i_s + (o << 7), z * i_s + (o << 8)) * s;
1303            }
1304            return n * correct;
1305        }
1306
1307        @Override
1308        public double getNoiseWithSeed(double x, double y, double z, long seed) {
1309            x *= frequency;
1310            y *= frequency;
1311            z *= frequency;
1312            x += disturbance.getNoiseWithSeed(x, y, z, seed);
1313            int s = 1;
1314            double n = 0.0, i_s = 2.0;
1315            for (int o = 0; o < octaves; o++, s <<= 1) {
1316                i_s *= 0.5;
1317                n += basis.getNoiseWithSeed(x * i_s, y * i_s, z * i_s, seed += 0x9E3779B97F4A7C15L) * s;
1318            }
1319            return n * correct;
1320        }
1321    }
1322
1323    public static class Turbulent4D implements Noise4D {
1324        protected int octaves;
1325        protected Noise4D basis, disturbance;
1326        public double frequency;
1327        public final double correct;
1328        public Turbulent4D() {
1329            this(SeededNoise.instance, alternate, 1);
1330        }
1331
1332        public Turbulent4D(Noise4D basis, Noise4D disturb) {
1333            this(basis, disturb, 1);
1334        }
1335
1336
1337        public Turbulent4D(Noise4D basis, Noise4D disturb, final int octaves) {
1338            this(basis, disturb, octaves, 1.0);
1339        }
1340        public Turbulent4D(Noise4D basis, Noise4D disturb, final int octaves, final double frequency) {
1341            this.basis = basis;
1342            this.frequency = frequency;
1343            disturbance = disturb;
1344            this.octaves = Math.max(1, Math.min(63, octaves));
1345            correct = 1.0 / ((1 << this.octaves) - 1.0);
1346        }
1347
1348        @Override
1349        public double getNoise(double x, double y, double z, double w) {
1350            x *= frequency;
1351            y *= frequency;
1352            z *= frequency;
1353            w *= frequency;
1354            x += disturbance.getNoise(x, y, z, w);
1355            int s = 1;
1356            double n = 0.0, i_s = 2.0;
1357            for (int o = 0; o < octaves; o++, s <<= 1) {
1358                i_s *= 0.5;
1359                n += basis.getNoise(x * i_s + (o << 6), y * i_s + (o << 7), z * i_s + (o << 8), w * i_s + (o << 9)) * s;
1360            }
1361            return n * correct;
1362        }
1363
1364        @Override
1365        public double getNoiseWithSeed(double x, double y, double z, double w, long seed) {
1366            x *= frequency;
1367            y *= frequency;
1368            z *= frequency;
1369            w *= frequency;
1370            x += disturbance.getNoiseWithSeed(x, y, z, w, seed);
1371            int s = 1;
1372            double n = 0.0, i_s = 2.0;
1373            for (int o = 0; o < octaves; o++, s <<= 1) {
1374                i_s *= 0.5;
1375                n += basis.getNoiseWithSeed(x * i_s, y * i_s, z * i_s, w * i_s, seed += 0x9E3779B97F4A7C15L) * s;
1376            }
1377            return n * correct;
1378        }
1379    }
1380    public static class Turbulent6D implements Noise6D {
1381        protected int octaves;
1382        protected Noise6D basis, disturbance;
1383        public double frequency;
1384        public final double correct;
1385        public Turbulent6D() {
1386            this(SeededNoise.instance, alternate, 1);
1387        }
1388
1389        public Turbulent6D(Noise6D basis, Noise6D disturb) {
1390            this(basis, disturb, 1);
1391        }
1392
1393        public Turbulent6D(Noise6D basis, Noise6D disturb, final int octaves) {
1394            this(basis, disturb, octaves, 1.0);
1395        }
1396        public Turbulent6D(Noise6D basis, Noise6D disturb, final int octaves, final double frequency) {
1397            this.basis = basis;
1398            this.frequency = frequency;
1399            disturbance = disturb;
1400            this.octaves = Math.max(1, Math.min(63, octaves));
1401            correct = 1.0 / ((1 << this.octaves) - 1.0);
1402        }
1403        @Override
1404        public double getNoise(double x, double y, double z, double w, double u, double v) {
1405            x *= frequency;
1406            y *= frequency;
1407            z *= frequency;
1408            w *= frequency;
1409            u *= frequency;
1410            v *= frequency;
1411            x += disturbance.getNoise(x, y, z, w, u, v);
1412            int s = 1;
1413            double n = 0.0, i_s = 2.0;
1414            for (int o = 0; o < octaves; o++, s <<= 1) {
1415                i_s *= 0.5;
1416                n += basis.getNoise(x * i_s + (o << 6), y * i_s + (o << 7), z * i_s + (o << 8), w * i_s + (o << 9), u * i_s + (o << 10), v * i_s + (o << 11)) * s;
1417            }
1418            return n * correct;
1419        }
1420
1421        @Override
1422        public double getNoiseWithSeed(double x, double y, double z, double w, double u, double v, long seed) {
1423            x *= frequency;
1424            y *= frequency;
1425            z *= frequency;
1426            w *= frequency;
1427            u *= frequency;
1428            v *= frequency;
1429            x += disturbance.getNoiseWithSeed(x, y, z, w, u, v, seed);
1430            int s = 1;
1431            double n = 0.0, i_s = 2.0;
1432            for (int o = 0; o < octaves; o++, s <<= 1) {
1433                i_s *= 0.5;
1434                n += basis.getNoiseWithSeed(x * i_s, y * i_s, z * i_s, w * i_s, u * i_s, v * i_s, seed += 0x9E3779B97F4A7C15L) * s;
1435            }
1436            return n * correct;
1437        }
1438    }
1439
1440    public static class Viny2D implements Noise2D {
1441        protected int octaves;
1442        protected Noise2D basis, disturbance;
1443        public double frequency;
1444
1445        public Viny2D() {
1446            this(SeededNoise.instance, alternate, 1);
1447        }
1448
1449        public Viny2D(Noise2D basis, Noise2D disturb) {
1450            this(basis, disturb, 1);
1451        }
1452
1453        public Viny2D(Noise2D basis, Noise2D disturb, final int octaves) {
1454            this(basis, disturb, octaves, 1.0);
1455        }
1456        public Viny2D(Noise2D basis, Noise2D disturb, final int octaves, final double frequency) {
1457            this.basis = basis;
1458            this.frequency = frequency;
1459            disturbance = disturb;
1460            this.octaves = Math.max(1, Math.min(63, octaves));
1461        }
1462
1463        @Override
1464        public double getNoise(double x, double y) {
1465            x *= frequency;
1466            y *= frequency;
1467            int s = 2 << (octaves - 1);
1468            double n = 0.0, i_s = 1.0 / s, xx, yy;
1469            for (int o = 0; o < octaves; o++) {
1470                xx = x * (i_s *= 2.0) + (o << 6);
1471                yy = y * i_s + (o << 7);
1472                n += basis.getNoise(xx, yy) * s + disturbance.getNoise(xx, yy) * (s >>= 1);
1473            }
1474            return n / ((3 << octaves) - 3.0);
1475        }
1476
1477        @Override
1478        public double getNoiseWithSeed(double x, double y, long seed) {
1479            x *= frequency;
1480            y *= frequency;
1481            int s = 2 << (octaves - 1);
1482            double n = 0.0, i_s = 1.0 / s, xx, yy;
1483            for (int o = 0; o < octaves; o++) {
1484                xx = x * (i_s *= 2.0) + (o << 6);
1485                yy = y * i_s + (o << 7);
1486                n += basis.getNoiseWithSeed(xx, yy, seed) * s + disturbance.getNoiseWithSeed(xx, yy, seed) * (s >>= 1);
1487            }
1488            return n / ((3 << octaves) - 3.0);
1489        }
1490    }
1491    public static class Viny3D implements Noise3D {
1492        protected int octaves;
1493        protected Noise3D basis, disturbance;
1494        public double frequency;
1495
1496        public Viny3D() {
1497            this(SeededNoise.instance, alternate, 1);
1498        }
1499
1500        public Viny3D(Noise3D basis, Noise3D disturb) {
1501            this(basis, disturb, 1);
1502        }
1503
1504        public Viny3D(Noise3D basis, Noise3D disturb, final int octaves) {
1505            this(basis, disturb, octaves, 1.0);
1506        }
1507        public Viny3D(Noise3D basis, Noise3D disturb, final int octaves, final double frequency) {
1508            this.basis = basis;
1509            this.frequency = frequency;
1510            disturbance = disturb;
1511            this.octaves = Math.max(1, Math.min(63, octaves));
1512        }
1513
1514        @Override
1515        public double getNoise(double x, double y, double z) {
1516            x *= frequency;
1517            y *= frequency;
1518            z *= frequency;
1519            int s = 2 << (octaves - 1);
1520            double n = 0.0, i_s = 1.0 / s, xx, yy, zz;
1521            for (int o = 0; o < octaves; o++) {
1522                xx = x * (i_s *= 2.0) + (o << 6);
1523                yy = y * i_s + (o << 7);
1524                zz = z * i_s + (o << 8);
1525                n += basis.getNoise(xx, yy, zz) * s + disturbance.getNoise(xx, yy, zz) * (s >>= 1);
1526            }
1527            return n / ((3 << octaves) - 3.0);
1528        }
1529
1530        @Override
1531        public double getNoiseWithSeed(double x, double y, double z, long seed) {
1532            x *= frequency;
1533            y *= frequency;
1534            z *= frequency;
1535            int s = 2 << (octaves - 1);
1536            double n = 0.0, i_s = 1.0 / s, xx, yy, zz;
1537            for (int o = 0; o < octaves; o++) {
1538                seed += 0x9E3779B97F4A7C15L;
1539                xx = x * (i_s *= 2.0) + (o << 6);
1540                yy = y * i_s + (o << 7);
1541                zz = z * i_s + (o << 8);
1542                n += basis.getNoiseWithSeed(xx, yy, zz, seed) * s + disturbance.getNoiseWithSeed(xx, yy, zz, seed) * (s >>= 1);
1543            }
1544            return n / ((3 << octaves) - 3.0);
1545        }
1546    }
1547
1548    public static class Viny4D implements Noise4D {
1549        protected int octaves;
1550        protected Noise4D basis, disturbance;
1551        public double frequency;
1552
1553        public Viny4D() {
1554            this(SeededNoise.instance, alternate, 1);
1555        }
1556
1557        public Viny4D(Noise4D basis, Noise4D disturb) {
1558            this(basis, disturb, 1);
1559        }
1560
1561
1562        public Viny4D(Noise4D basis, Noise4D disturb, final int octaves) {
1563            this(basis, disturb, octaves, 1.0);
1564        }
1565        public Viny4D(Noise4D basis, Noise4D disturb, final int octaves, final double frequency) {
1566            this.basis = basis;
1567            this.frequency = frequency;
1568            disturbance = disturb;
1569            this.octaves = Math.max(1, Math.min(63, octaves));
1570        }
1571        @Override
1572        public double getNoise(double x, double y, double z, double w) {
1573            x *= frequency;
1574            y *= frequency;
1575            z *= frequency;
1576            w *= frequency;
1577            int s = 2 << (octaves - 1);
1578            double n = 0.0, i_s = 1.0 / s, xx, yy, zz, ww;
1579            for (int o = 0; o < octaves; o++) {
1580                xx = x * (i_s *= 2.0) + (o << 6);
1581                yy = y * i_s + (o << 7);
1582                zz = z * i_s + (o << 8);
1583                ww = w * i_s + (o << 9);
1584                n += basis.getNoise(xx, yy, zz, ww) * s + disturbance.getNoise(xx, yy, zz, ww) * (s >>= 1);
1585            }
1586            return n / ((3 << octaves) - 3.0);
1587        }
1588
1589        @Override
1590        public double getNoiseWithSeed(double x, double y, double z, double w, long seed) {
1591            x *= frequency;
1592            y *= frequency;
1593            z *= frequency;
1594            w *= frequency;
1595            int s = 2 << (octaves - 1);
1596            double n = 0.0, i_s = 1.0 / s, xx, yy, zz, ww;
1597            for (int o = 0; o < octaves; o++) {
1598                seed += 0x9E3779B97F4A7C15L;
1599                xx = x * (i_s *= 2.0) + (o << 6);
1600                yy = y * i_s + (o << 7);
1601                zz = z * i_s + (o << 8);
1602                ww = w * i_s + (o << 9);
1603                n += basis.getNoiseWithSeed(xx, yy, zz, ww, seed) * s + disturbance.getNoiseWithSeed(xx, yy, zz, ww, seed) * (s >>= 1);
1604            }
1605            return n / ((3 << octaves) - 3.0);
1606        }
1607    }
1608    public static class Viny6D implements Noise6D {
1609        protected int octaves;
1610        protected Noise6D basis, disturbance;
1611        public double frequency;
1612        public Viny6D() {
1613            this(SeededNoise.instance, alternate, 1);
1614        }
1615
1616        public Viny6D(Noise6D basis, Noise6D disturb) {
1617            this(basis, disturb, 1);
1618        }
1619
1620        public Viny6D(Noise6D basis, Noise6D disturb, final int octaves) {
1621            this(basis, disturb, octaves, 1.0);
1622        }
1623        public Viny6D(Noise6D basis, Noise6D disturb, final int octaves, final double frequency) {
1624            this.basis = basis;
1625            this.frequency = frequency;
1626            disturbance = disturb;
1627            this.octaves = Math.max(1, Math.min(63, octaves));
1628        }
1629        @Override
1630        public double getNoise(double x, double y, double z, double w, double u, double v) {
1631            x *= frequency;
1632            y *= frequency;
1633            z *= frequency;
1634            w *= frequency;
1635            u *= frequency;
1636            v *= frequency;
1637            int s = 2 << (octaves - 1);
1638            double n = 0.0, i_s = 1.0 / s, xx, yy, zz, ww, uu, vv;
1639            for (int o = 0; o < octaves; o++) {
1640                xx = x * (i_s *= 2.0) + (o << 6);
1641                yy = y * i_s + (o << 7);
1642                zz = z * i_s + (o << 8);
1643                ww = w * i_s + (o << 9);
1644                uu = u * i_s + (o << 10);
1645                vv = v * i_s + (o << 11);
1646                n += basis.getNoise(xx, yy, zz, ww, uu, vv) * s + disturbance.getNoise(xx, yy, zz, ww, uu, vv) * (s >>= 1);
1647            }
1648            return n / ((3 << octaves) - 3.0);
1649        }
1650
1651        @Override
1652        public double getNoiseWithSeed(double x, double y, double z, double w, double u, double v, long seed) {
1653            x *= frequency;
1654            y *= frequency;
1655            z *= frequency;
1656            w *= frequency;
1657            u *= frequency;
1658            v *= frequency;
1659            int s = 2 << (octaves - 1);
1660            double n = 0.0, i_s = 1.0 / s, xx, yy, zz, ww, uu, vv;
1661            for (int o = 0; o < octaves; o++) {
1662                seed += 0x9E3779B97F4A7C15L;
1663                xx = x * (i_s *= 2.0) + (o << 6);
1664                yy = y * i_s + (o << 7);
1665                zz = z * i_s + (o << 8);
1666                ww = w * i_s + (o << 9);
1667                uu = u * i_s + (o << 10);
1668                vv = v * i_s + (o << 11);
1669                n += basis.getNoiseWithSeed(xx, yy, zz, ww, uu, vv, seed) * s + disturbance.getNoiseWithSeed(xx, yy, zz, ww, uu, vv, seed) * (s >>= 1);
1670            }
1671            return n / ((3 << octaves) - 3.0);
1672        }
1673    }
1674
1675
1676    public static class Slick2D implements Noise2D {
1677        protected int octaves;
1678        protected Noise2D basis, disturbance;
1679
1680        public Slick2D() {
1681            this(SeededNoise.instance, alternate, 1);
1682        }
1683
1684        public Slick2D(Noise2D basis, Noise2D disturb) {
1685            this(basis, disturb, 1);
1686        }
1687
1688        public Slick2D(Noise2D basis, Noise2D disturb, final int octaves) {
1689            this.basis = basis;
1690            disturbance = disturb;
1691            this.octaves = Math.max(1, Math.min(63, octaves));
1692        }
1693
1694        @Override
1695        public double getNoise(final double x, final double y) {
1696            double n = 0.0, i_s = 1.0, xx, yy;
1697            int s = 1 << (octaves - 1);
1698            for (int o = 0; o < octaves; o++, s >>= 1) {
1699                xx = x * (i_s *= 0.5) + (o << 6);
1700                yy = y * i_s + (o << 7);
1701                n += basis.getNoise(xx + disturbance.getNoise(x, y), yy) * s;
1702            }
1703            return n / ((1 << octaves) - 1.0);
1704        }
1705
1706        @Override
1707        public double getNoiseWithSeed(final double x, final double y, long seed) {
1708            double n = 0.0, i_s = 1.0, xx, yy;
1709
1710            int s = 1 << (octaves - 1);
1711            for (int o = 0; o < octaves; o++, s >>= 1) {
1712                seed += 0x9E3779B97F4A7C15L;
1713                xx = x * (i_s *= 0.5) + (o << 6);
1714                yy = y * i_s + (o << 7);
1715                n += basis.getNoiseWithSeed(xx + disturbance.getNoiseWithSeed(x, y, seed), yy, seed) * s;
1716            }
1717            return n / ((1 << octaves) - 1.0);
1718        }
1719    }
1720    public static class Slick3D implements Noise3D {
1721        protected int octaves;
1722        protected Noise3D basis, disturbance;
1723
1724        public Slick3D() {
1725            this(SeededNoise.instance, alternate, 1);
1726        }
1727
1728        public Slick3D(Noise3D basis, Noise3D disturb) {
1729            this(basis, disturb, 1);
1730        }
1731
1732        public Slick3D(Noise3D basis, Noise3D disturb, final int octaves) {
1733            this.basis = basis;
1734            disturbance = disturb;
1735            this.octaves = Math.max(1, Math.min(63, octaves));
1736        }
1737
1738        @Override
1739        public double getNoise(final double x, final double y, final double z) {
1740            double n = 0.0, i_s = 1.0, xx, yy, zz;
1741            int s = 1 << (octaves - 1);
1742            for (int o = 0; o < octaves; o++, s >>= 1) {
1743                xx = x * (i_s *= 0.5) + (o << 6);
1744                yy = y * i_s + (o << 7);
1745                zz = z * i_s + (o << 8);
1746                n += basis.getNoise(xx + disturbance.getNoise(x, y, z), yy, zz) * s;
1747            }
1748            return n / ((1 << octaves) - 1.0);
1749        }
1750
1751        @Override
1752        public double getNoiseWithSeed(final double x, final double y, final double z, long seed) {
1753            double n = 0.0, i_s = 1.0, xx, yy, zz;
1754            int s = 1 << (octaves - 1);
1755            for (int o = 0; o < octaves; o++, s >>= 1) {
1756                seed += 0x9E3779B97F4A7C15L;
1757                xx = x * (i_s *= 0.5) + (o << 6);
1758                yy = y * i_s + (o << 7);
1759                zz = z * i_s + (o << 8);
1760                n += basis.getNoiseWithSeed(xx + disturbance.getNoiseWithSeed(x, y, z, seed), yy, zz, seed) * s;
1761            }
1762            return n / ((1 << octaves) - 1.0);
1763        }
1764    }
1765    public static class Slick4D implements Noise4D {
1766        protected int octaves;
1767        protected Noise4D basis, disturbance;
1768
1769        public Slick4D() {
1770            this(SeededNoise.instance, alternate, 1);
1771        }
1772
1773        public Slick4D(Noise4D basis, Noise4D disturb) {
1774            this(basis, disturb, 1);
1775        }
1776
1777        public Slick4D(Noise4D basis, Noise4D disturb, final int octaves) {
1778            this.basis = basis;
1779            disturbance = disturb;
1780            this.octaves = Math.max(1, Math.min(63, octaves));
1781        }
1782
1783        @Override
1784        public double getNoise(final double x, final double y, final double z, final double w) {
1785            double n = 0.0, i_s = 1.0, xx, yy, zz, ww;
1786            int s = 1 << (octaves - 1);
1787            for (int o = 0; o < octaves; o++, s >>= 1) {
1788                xx = x * (i_s *= 0.5) + (o << 6);
1789                yy = y * i_s + (o << 7);
1790                zz = z * i_s + (o << 8);
1791                ww = w * i_s + (o << 9);
1792                n += basis.getNoise(xx + disturbance.getNoise(x, y, z, w), yy, zz, ww) * s;
1793            }
1794            return n / ((1 << octaves) - 1.0);
1795        }
1796
1797        @Override
1798        public double getNoiseWithSeed(final double x, final double y, final double z, final double w, long seed) {
1799            double n = 0.0, i_s = 1.0, xx, yy, zz, ww;
1800            int s = 1 << (octaves - 1);
1801            for (int o = 0; o < octaves; o++, s >>= 1) {
1802                seed += 0x9E3779B97F4A7C15L;
1803                xx = x * (i_s *= 0.5) + (o << 6);
1804                yy = y * i_s + (o << 7);
1805                zz = z * i_s + (o << 8);
1806                ww = w * i_s + (o << 9);
1807                n += basis.getNoiseWithSeed(xx + disturbance.getNoiseWithSeed(x, y, z, w, seed), yy, zz, ww, seed) * s;
1808            }
1809            return n / ((1 << octaves) - 1.0);
1810        }
1811    }
1812    public static class Slick6D implements Noise6D {
1813        protected int octaves;
1814        protected Noise6D basis, disturbance;
1815
1816        public Slick6D() {
1817            this(SeededNoise.instance, alternate, 1);
1818        }
1819
1820        public Slick6D(Noise6D basis, Noise6D disturb) {
1821            this(basis, disturb, 1);
1822        }
1823
1824        public Slick6D(Noise6D basis, Noise6D disturb, final int octaves) {
1825            this.basis = basis;
1826            disturbance = disturb;
1827            this.octaves = Math.max(1, Math.min(63, octaves));
1828        }
1829
1830        @Override
1831        public double getNoise(final double x, final double y, final double z, final double w, final double u, final double v) {
1832            double n = 0.0, i_s = 1.0, xx, yy, zz, ww, uu, vv;
1833            int s = 1 << (octaves - 1);
1834            for (int o = 0; o < octaves; o++, s >>= 1) {
1835                xx = x * (i_s *= 0.5) + (o << 6);
1836                yy = y * i_s + (o << 7);
1837                zz = z * i_s + (o << 8);
1838                ww = w * i_s + (o << 9);
1839                uu = u * i_s + (o << 10);
1840                vv = v * i_s + (o << 11);
1841                n += basis.getNoise(xx + disturbance.getNoise(x, y, z, w, u, v), yy, zz, ww, uu, vv) * s;
1842            }
1843            return n / ((1 << octaves) - 1.0);
1844        }
1845
1846        @Override
1847        public double getNoiseWithSeed(final double x, final double y, final double z, final double w, final double u, final double v, long seed) {
1848            double n = 0.0, i_s = 1.0, xx, yy, zz, ww, uu, vv;
1849            int s = 1 << (octaves - 1);
1850            for (int o = 0; o < octaves; o++, s >>= 1) {
1851                seed += 0x9E3779B97F4A7C15L;
1852                xx = x * (i_s *= 0.5) + (o << 6);
1853                yy = y * i_s + (o << 7);
1854                zz = z * i_s + (o << 8);
1855                ww = w * i_s + (o << 9);
1856                uu = u * i_s + (o << 10);
1857                vv = v * i_s + (o << 11);
1858                n += basis.getNoiseWithSeed(xx + disturbance.getNoiseWithSeed(x, y, z, w, u, v, seed), yy, zz, ww, uu, vv, seed) * s;
1859            }
1860            return n / ((1 << octaves) - 1.0);
1861        }
1862    }
1863
1864
1865    public static class Exponential1D implements Noise1D {
1866        protected Noise1D basis;
1867        protected double sharpness, adjustment;
1868        public Exponential1D() {
1869            this(Basic1D.instance);
1870        }
1871
1872        public Exponential1D(Noise1D basis) {
1873            this(basis, 0.125);
1874        }
1875        public Exponential1D(Noise1D basis, double sharpness) {
1876            this.basis = basis;
1877            this.sharpness = sharpness - fastFloor(sharpness) - 1.0;
1878            this.adjustment = 2.0 / Math.log1p(this.sharpness * 0.9999999999999999);
1879            this.sharpness *= 0.5;
1880        }
1881
1882
1883        @Override
1884        public double getNoise(double x) {
1885            return Math.log(1.0 + sharpness * (basis.getNoise(x) + 1.0)) * adjustment - 1.0;
1886        }
1887
1888        @Override
1889        public double getNoiseWithSeed(double x, long seed) {
1890            return Math.log(1.0 + sharpness * (basis.getNoiseWithSeed(x, seed) + 1.0)) * adjustment - 1.0;
1891        }
1892    }
1893
1894    public static class Exponential2D implements Noise2D {
1895        protected Noise2D basis;
1896        protected double sharpness, adjustment;
1897        public Exponential2D() {
1898            this(SeededNoise.instance);
1899        }
1900
1901        public Exponential2D(Noise2D basis) {
1902            this(basis, 0.125);
1903        }
1904        public Exponential2D(Noise2D basis, double sharpness) {
1905            this.basis = basis;
1906            this.sharpness = sharpness - fastFloor(sharpness) - 1.0;
1907            this.adjustment = 2.0 / Math.log1p(this.sharpness * 0.9999999999999999);
1908            this.sharpness *= 0.5;
1909        }
1910
1911        @Override
1912        public double getNoise(double x, double y) {
1913            return Math.log(1.0 + sharpness * (basis.getNoise(x, y) + 1.0)) * adjustment - 1.0;
1914        }
1915
1916        @Override
1917        public double getNoiseWithSeed(double x, double y, long seed) {
1918            return Math.log(1.0 + sharpness * (basis.getNoiseWithSeed(x, y, seed) + 1.0)) * adjustment - 1.0;
1919        }
1920    }
1921    public static class Exponential3D implements Noise3D {
1922        protected Noise3D basis;
1923        protected double sharpness, adjustment;
1924        public Exponential3D() {
1925            this(SeededNoise.instance);
1926        }
1927
1928        public Exponential3D(Noise3D basis) {
1929            this(basis, 0.125);
1930        }
1931        public Exponential3D(Noise3D basis, double sharpness) {
1932            this.basis = basis;
1933            this.sharpness = sharpness - fastFloor(sharpness) - 1.0;
1934            this.adjustment = 2.0 / Math.log1p(this.sharpness * 0.9999999999999999);
1935            this.sharpness *= 0.5;
1936        }
1937
1938        @Override
1939        public double getNoise(double x, double y, double z) {
1940            return Math.log(1.0 + sharpness * (basis.getNoise(x, y, z) + 1.0)) * adjustment - 1.0;
1941        }
1942
1943        @Override
1944        public double getNoiseWithSeed(double x, double y, double z, long seed) {
1945            return Math.log(1.0 + sharpness * (basis.getNoiseWithSeed(x, y, z, seed) + 1.0)) * adjustment - 1.0;
1946        }
1947    }
1948    public static class Exponential4D implements Noise4D {
1949        protected Noise4D basis;
1950        protected double sharpness, adjustment;
1951        public Exponential4D() {
1952            this(SeededNoise.instance);
1953        }
1954
1955        public Exponential4D(Noise4D basis) {
1956            this(basis, 0.125);
1957        }
1958        public Exponential4D(Noise4D basis, double sharpness) {
1959            this.basis = basis;
1960            this.sharpness = sharpness - fastFloor(sharpness) - 1.0;
1961            this.adjustment = 2.0 / Math.log1p(this.sharpness * 0.9999999999999999);
1962            this.sharpness *= 0.5;
1963        }
1964
1965        @Override
1966        public double getNoise(double x, double y, double z, double w) {
1967            return Math.log(1.0 + sharpness * (basis.getNoise(x, y, z, w) + 1.0)) * adjustment - 1.0;
1968        }
1969
1970        @Override
1971        public double getNoiseWithSeed(double x, double y, double z, double w, long seed) {
1972            return Math.log(1.0 + sharpness * (basis.getNoiseWithSeed(x, y, z, w, seed) + 1.0)) * adjustment - 1.0;
1973        }
1974    }
1975    public static class Exponential6D implements Noise6D {
1976        protected Noise6D basis;
1977        protected double sharpness, adjustment;
1978        public Exponential6D() {
1979            this(SeededNoise.instance);
1980        }
1981
1982        public Exponential6D(Noise6D basis) {
1983            this(basis, 0.125);
1984        }
1985        public Exponential6D(Noise6D basis, double sharpness) {
1986            this.basis = basis;
1987            this.sharpness = sharpness - fastFloor(sharpness) - 1.0;
1988            this.adjustment = 2.0 / Math.log1p(this.sharpness * 0.9999999999999999);
1989            this.sharpness *= 0.5;
1990        }
1991
1992        @Override
1993        public double getNoise(double x, double y, double z, double w, double u, double v) {
1994            return Math.log(1.0 + sharpness * (basis.getNoise(x, y, z, w, u, v) + 1.0)) * adjustment - 1.0;
1995        }
1996
1997        @Override
1998        public double getNoiseWithSeed(double x, double y, double z, double w, double u, double v, long seed) {
1999            return Math.log(1.0 + sharpness * (basis.getNoiseWithSeed(x, y, z, w, u, v, seed) + 1.0)) * adjustment - 1.0;
2000        }
2001    }
2002    
2003    
2004    /**
2005     * Produces a 2D array of noise with values from -1.0 to 1.0 that is seamless on all boundaries.
2006     * Uses (x,y) order. Allows a seed to change the generated noise.
2007     * If you need to call this very often, consider {@link #seamless2D(double[][], int, int)}, which re-uses the array.
2008     * @param width the width of the array to produce (the length of the outer layer of arrays)
2009     * @param height the height of the array to produce (the length of the inner arrays)
2010     * @param seed an int seed that affects the noise produced, with different seeds producing very different noise
2011     * @param octaves how many runs of differently sized and weighted noise generations to apply to the same area
2012     * @return a freshly-allocated seamless-bounded array, a {@code double[width][height]}.
2013     */
2014    public static double[][] seamless2D(final int width, final int height, final int seed, final int octaves) {
2015        return seamless2D(new double[width][height], seed, octaves);
2016    }
2017
2018    /**
2019     * Fills the given 2D array (modifying it) with noise, using values from -1.0 to 1.0, that is seamless on all
2020     * boundaries. This overload doesn't care what you use for x or y axes, it uses the exact size of fill fully.
2021     * Allows a seed to change the generated noise.
2022     * @param fill a 2D array of double; must be rectangular, so it's a good idea to create with {@code new double[width][height]} or something similar
2023     * @param seed an int seed that affects the noise produced, with different seeds producing very different noise
2024     * @param octaves how many runs of differently sized and weighted noise generations to apply to the same area
2025     * @return {@code fill}, after assigning it with seamless-bounded noise
2026     */
2027    public static double[][] seamless2D(final double[][] fill, final int seed, final int octaves) {
2028        return seamless2D(fill, seed, octaves, SeededNoise.instance);
2029    }
2030
2031    public static double total;
2032    /**
2033     * Fills the given 2D array (modifying it) with noise, using values from -1.0 to 1.0, that is seamless on all
2034     * boundaries. This overload doesn't care what you use for x or y axes, it uses the exact size of fill fully.
2035     * Allows a seed to change the generated noise. DOES NOT clear the values in fill, so if it already has non-zero
2036     * elements, the result will be different than if it had been cleared beforehand. That does allow you to utilize
2037     * this method to add multiple seamless noise values on top of each other, though that allows values to go above or
2038     * below the normal minimum and maximum (-1.0 to 1.0).
2039     * @param fill a 2D array of double; must be rectangular, so it's a good idea to create with {@code new double[width][height]} or something similar
2040     * @param seed an int seed that affects the noise produced, with different seeds producing very different noise
2041     * @param octaves how many runs of differently sized and weighted noise generations to apply to the same area
2042     * @return {@code fill}, after assigning it with seamless-bounded noise
2043     */
2044    public static double[][] seamless2D(final double[][] fill, long seed, final int octaves, final Noise.Noise4D generator) {
2045        final int height, width;
2046        if (fill == null || (width = fill.length) <= 0 || (height = fill[0].length) <= 0
2047                || octaves <= 0 || octaves >= 63)
2048            return fill;
2049        final double i_w = 6.283185307179586 / width, i_h = 6.283185307179586 / height;
2050        int s = 1 << (octaves - 1);
2051        total = 0.0;
2052        double p, q,
2053                ps, pc,
2054                qs, qc,
2055                i_s = 0.5 / s;
2056        for (int o = 0; o < octaves; o++, s >>= 1) {
2057            seed += 0x9E3779B97F4A7C15L;
2058            i_s *= 2.0;
2059            for (int x = 0; x < width; x++) {
2060                p = x * i_w;
2061                ps = NumberTools.sin(p) * i_s;
2062                pc = NumberTools.cos(p) * i_s;
2063                for (int y = 0; y < height; y++) {
2064                    q = y * i_h;
2065                    qs = NumberTools.sin(q) * i_s;
2066                    qc = NumberTools.cos(q) * i_s;
2067                    fill[x][y] += generator.getNoiseWithSeed(pc, ps, qc, qs, seed) * s;
2068                }
2069            }
2070        }
2071        i_s = 1.0 / ((1 << octaves) - 1.0);
2072        for (int x = 0; x < width; x++) {
2073            for (int y = 0; y < height; y++) {
2074                total += (fill[x][y] *= i_s);
2075            }
2076        }
2077        return fill;
2078    }
2079
2080    /**
2081     * Produces a 3D array of noise with values from -1.0 to 1.0 that is seamless on all boundaries.
2082     * Allows a seed to change the generated noise.
2083     * Because most games that would use this would use it for maps, and maps are often top-down, the returned 3D array
2084     * uses the order (z,x,y), which allows a 2D slice of x and y to be taken as an element from the top-level array.
2085     * If you need to call this very often, consider {@link #seamless3D(double[][][], long, int)}, which re-uses the
2086     * array instead of re-generating it.
2087     * @param width the width of the array to produce (the length of the middle layer of arrays)
2088     * @param height the height of the array to produce (the length of the innermost arrays)
2089     * @param depth the depth of the array to produce (the length of the outermost layer of arrays)
2090     * @param seed an int seed that affects the noise produced, with different seeds producing very different noise
2091     * @param octaves how many runs of differently sized and weighted noise generations to apply to the same area
2092     * @return a freshly-allocated seamless-bounded array, a {@code double[depth][width][height]}.
2093     */
2094    public static double[][][] seamless3D(final int depth, final int width, final int height, final long seed, final int octaves) {
2095        return seamless3D(new double[depth][width][height], seed, octaves);
2096    }
2097
2098    /**
2099     * Fills the given 3D array (modifying it) with noise, using values from -1.0 to 1.0, that is seamless on all
2100     * boundaries. This overload doesn't care what you use for x, y, or z axes, it uses the exact size of fill fully.
2101     * Allows a seed to change the generated noise.
2102     * @param fill a 3D array of double; must be rectangular, so it's a good idea to create with {@code new double[depth][width][height]} or something similar
2103     * @param seed an int seed that affects the noise produced, with different seeds producing very different noise
2104     * @param octaves how many runs of differently sized and weighted noise generations to apply to the same area
2105     * @return {@code fill}, after assigning it with seamless-bounded noise
2106     */
2107    public static double[][][] seamless3D(final double[][][] fill, final long seed, final int octaves) {
2108        return seamless3D(fill, seed, octaves, SeededNoise.instance);
2109    }
2110
2111    /**
2112     * Fills the given 3D array (modifying it) with noise, using values from -1.0 to 1.0, that is seamless on all
2113     * boundaries. This overload doesn't care what you use for x, y, or z axes, it uses the exact size of fill fully.
2114     * Allows a seed to change the generated noise.
2115     * @param fill a 3D array of double; must be rectangular, so it's a good idea to create with {@code new double[depth][width][height]} or something similar
2116     * @param seed an int seed that affects the noise produced, with different seeds producing very different noise
2117     * @param octaves how many runs of differently sized and weighted noise generations to apply to the same area
2118     * @return {@code fill}, after assigning it with seamless-bounded noise
2119     */
2120    public static double[][][] seamless3D(final double[][][] fill, long seed, final int octaves, final Noise.Noise6D generator) {
2121        final int depth, height, width;
2122        if(fill == null || (depth = fill.length) <= 0 || (width = fill[0].length) <= 0 || (height = fill[0][0].length) <= 0
2123                || octaves <= 0 || octaves >= 63)
2124            return fill;
2125        final double i_w = 6.283185307179586 / width, i_h = 6.283185307179586 / height, i_d = 6.283185307179586 / depth;
2126        int s = 1<<(octaves-1);
2127        total = 0.0;
2128        double p, q, r,
2129                ps, pc,
2130                qs, qc,
2131                rs, rc, i_s = 0.5 / s;
2132        for (int o = 0; o < octaves; o++, s>>=1) {
2133            seed += 0x9E3779B97F4A7C15L;
2134            i_s *= 2.0;
2135            for (int x = 0; x < width; x++) {
2136                p = x * i_w;
2137                ps = NumberTools.sin(p) * i_s;
2138                pc = NumberTools.cos(p) * i_s;
2139                for (int y = 0; y < height; y++) {
2140                    q = y * i_h;
2141                    qs = NumberTools.sin(q) * i_s;
2142                    qc = NumberTools.cos(q) * i_s;
2143                    for (int z = 0; z < depth; z++) {
2144                        r = z * i_d;
2145                        rs = NumberTools.sin(r) * i_s;
2146                        rc = NumberTools.cos(r) * i_s;
2147                        fill[z][x][y] += generator.getNoiseWithSeed(pc, ps, qc, qs, rc, rs, seed) * s;
2148                    }
2149                }
2150            }
2151        }
2152        i_s = 1.0 / ((1<<octaves) - 1.0);
2153        for (int x = 0; x < width; x++) {
2154            for (int y = 0; y < height; y++) {
2155                for (int z = 0; z < depth; z++) {
2156                    total += (fill[z][x][y] *= i_s);
2157                }
2158            }
2159        }
2160        return fill;
2161    }
2162
2163    /**
2164     * Fills the given 3D array (modifying it) with noise, using values from -1.0 to 1.0, that is seamless on all
2165     * boundaries. This overload doesn't care what you use for x, y, or z axes, it uses the exact size of fill fully.
2166     * Allows a seed to change the generated noise.
2167     * @param fill a 3D array of double; must be rectangular, so it's a good idea to create with {@code new double[depth][width][height]} or something similar
2168     * @param seed an int seed that affects the noise produced, with different seeds producing very different noise
2169     * @param octaves how many runs of differently sized and weighted noise generations to apply to the same area
2170     * @return {@code fill}, after assigning it with seamless-bounded noise
2171     */
2172    public static float[][][] seamless3D(final float[][][] fill, long seed, final int octaves) {
2173        final int depth, height, width;
2174        if(fill == null || (depth = fill.length) <= 0 || (width = fill[0].length) <= 0 || (height = fill[0][0].length) <= 0
2175                || octaves <= 0 || octaves >= 63)
2176            return fill;
2177        final double i_w = 6.283185307179586 / width, i_h = 6.283185307179586 / height, i_d = 6.283185307179586 / depth;
2178        int s = 1<<(octaves-1);
2179        double p, q, r,
2180                ps, pc,
2181                qs, qc,
2182                rs, rc, i_s = 0.5 / s;
2183        for (int o = 0; o < octaves; o++, s>>=1) {
2184            seed += 0x9E3779B97F4A7C15L;
2185            i_s *= 2.0;
2186            for (int x = 0; x < width; x++) {
2187                p = x * i_w;
2188                ps = NumberTools.sin(p) * i_s;
2189                pc = NumberTools.cos(p) * i_s;
2190                for (int y = 0; y < height; y++) {
2191                    q = y * i_h;
2192                    qs = NumberTools.sin(q) * i_s;
2193                    qc = NumberTools.cos(q) * i_s;
2194                    for (int z = 0; z < depth; z++) {
2195                        r = z * i_d;
2196                        rs = NumberTools.sin(r) * i_s;
2197                        rc = NumberTools.cos(r) * i_s;
2198                        fill[z][x][y] += SeededNoise.noise(pc, ps, qc, qs, rc, rs, seed) * s;
2199                    }
2200                }
2201            }
2202        }
2203        i_s = 1.0 / ((1<<octaves) - 1.0);
2204        for (int x = 0; x < width; x++) {
2205            for (int y = 0; y < height; y++) {
2206                for (int z = 0; z < depth; z++) {
2207                    fill[z][x][y] *= i_s;
2208                }
2209            }
2210        }
2211        return fill;
2212    }
2213
2214    /**
2215     * Like {@link #seamless2D(double[][], long, int, Noise4D)}, but this produces 1D noise that "tiles" by repeating
2216     * its output every {@code sizeX} units that {@code x} increases or decreases by. This doesn't precalculate an
2217     * array, instead calculating just one value so that later calls with different x will tile seamlessly.
2218     * <br>
2219     * Internally, this just samples out of a circle from a source of 2D noise.
2220     * @param noise a Noise2D implementation such as a {@link SeededNoise} or {@link FastNoise}
2221     * @param x the x-coordinate to sample
2222     * @param sizeX the range of x to generate before repeating; must be greater than 0
2223     * @param seed the noise seed, as a long
2224     * @return continuous noise from -1.0 to 1.0, inclusive 
2225     */
2226    public static double seamless1D(Noise2D noise, double x, double sizeX, long seed)
2227    {
2228        x *= 6.283185307179586 / sizeX;
2229        return noise.getNoiseWithSeed(NumberTools.cos(x), NumberTools.sin(x), seed);
2230    }
2231
2232    /**
2233     * Like {@link #seamless2D(double[][], long, int, Noise4D)}, but this doesn't precalculate noise into an array,
2234     * instead calculating just one 2D point so that later calls with different x or y will tile seamlessly.
2235     * @param noise a Noise4D implementation such as a {@link SeededNoise} or {@link FastNoise}
2236     * @param x the x-coordinate to sample
2237     * @param y the y-coordinate to sample
2238     * @param sizeX the range of x to generate before repeating; must be greater than 0
2239     * @param sizeY the range of y to generate before repeating; must be greater than 0
2240     * @param seed the noise seed, as a long
2241     * @return continuous noise from -1.0 to 1.0, inclusive 
2242     */
2243    public static double seamless2D(Noise4D noise, double x, double y, double sizeX, double sizeY, long seed)
2244    {
2245        x *= 6.283185307179586 / sizeX;
2246        y *= 6.283185307179586 / sizeY;
2247        return noise.getNoiseWithSeed(NumberTools.cos(x), NumberTools.sin(x), NumberTools.cos(y), NumberTools.sin(y),
2248                seed);
2249    }
2250
2251
2252    /**
2253     * Like {@link #seamless3D(double[][][], long, int, Noise6D)}, but this doesn't precalculate noise into an array,
2254     * instead calculating just one 3D point so that later calls with different x, y, or z will tile seamlessly.
2255     * @param noise a Noise6D implementation such as a {@link SeededNoise} or {@link FastNoise}
2256     * @param x the x-coordinate to sample
2257     * @param y the y-coordinate to sample
2258     * @param z the z-coordinate to sample
2259     * @param sizeX the range of x to generate before repeating; must be greater than 0
2260     * @param sizeY the range of y to generate before repeating; must be greater than 0
2261     * @param sizeZ the range of z to generate before repeating; must be greater than 0
2262     * @param seed the noise seed, as a long
2263     * @return continuous noise from -1.0 to 1.0, inclusive 
2264     */
2265    public static double seamless3D(Noise6D noise, double x, double y, double z, double sizeX, double sizeY, double sizeZ, long seed)
2266    {
2267        x *= 6.283185307179586 / sizeX;
2268        y *= 6.283185307179586 / sizeY;
2269        z *= 6.283185307179586 / sizeZ;
2270        return noise.getNoiseWithSeed(NumberTools.cos(x), NumberTools.sin(x), NumberTools.cos(y), NumberTools.sin(y),
2271                NumberTools.cos(z), NumberTools.sin(z), seed);
2272    }
2273
2274    /**
2275     * A very simple 1D noise implementation, because a full-blown Perlin or Simplex noise implementation is probably
2276     * overkill for 1D noise. This does produce smoothly sloping lines, like Simplex noise does for higher dimensions.
2277     * The shape of the line varies over time, but <a href="https://i.imgur.com/83R3WLN.png">can look like this</a>.
2278     * If you give this a seed with {@link #getNoiseWithSeed(double, long)} instead of using {@link #getNoise(double)},
2279     * it will use a small extra step to adjust the spacing of peaks and valleys based on the seed, so getNoiseWithSeed
2280     * is slower than getNoise. If you use any Noise classes like {@link Noise.Layered1D}, they should use a seed anyway
2281     * because different octaves won't have different enough shapes otherwise.
2282     */
2283    public static class Basic1D implements Noise1D
2284    {
2285        public static final Basic1D instance = new Basic1D();
2286        public double alter1, alter2, alter3, alter4;
2287        public long lastSeed;
2288        public Basic1D()
2289        {
2290            this(1L);
2291        }
2292        public Basic1D(long seed)
2293        {
2294            lastSeed = seed;
2295            alter1 = (DiverRNG.determine(seed) >> 11) * 0x1.8p-54;
2296            alter2 = (DiverRNG.determine(seed + 11111) >> 11) * 0x1p-53;
2297            alter3 = (DiverRNG.determine(seed + 22222) >> 11) * 0x1.8p-53;
2298            alter4 = (DiverRNG.determine(seed + 33333) >> 11) * 0x1p-52;
2299        }
2300        @Override
2301        public double getNoise(double x) {
2302            return (cubicSway(x * alter1) * 0.4375f +
2303                    cubicSway(x * alter2) * 0.3125f +
2304                    cubicSway(x * alter3) * 0.1875f +
2305                    cubicSway(x * alter4) * 0.0625f);
2306        }
2307
2308        @Override
2309        public double getNoiseWithSeed(double x, long seed) {
2310            if(lastSeed != seed)
2311            {
2312                lastSeed = seed;
2313                alter1 = (DiverRNG.determine(seed) >> 11) * 0x1.8p-54;
2314                alter2 = (DiverRNG.determine(seed + 11111) >> 11) * 0x1p-53;
2315                alter3 = (DiverRNG.determine(seed + 22222) >> 11) * 0x1.8p-53;
2316                alter4 = (DiverRNG.determine(seed + 33333) >> 11) * 0x1p-52;
2317            }
2318            return (cubicSway(x * alter1) * 0.4375f +
2319                    cubicSway(x * alter2) * 0.3125f +
2320                    cubicSway(x * alter3) * 0.1875f +
2321                    cubicSway(x * alter4) * 0.0625f);
2322        }
2323        public static double cubicSway(double value)
2324        {
2325            long floor = (value >= 0.0 ? (long) value : (long) value - 1L);
2326            value -= floor;
2327            floor = (-(floor & 1L) | 1L);
2328            return value * value * (3.0 - 2.0 * value) * (floor << 1) - floor;
2329        }
2330
2331        public static double noise(double x, long seed) {
2332            final double
2333                    alter1 = (DiverRNG.determine(seed) >> 11) * 0x1.8p-54, 
2334                    alter2 = (DiverRNG.determine(seed + 11111) >> 11) * 0x1p-53, 
2335                    alter3 = (DiverRNG.determine(seed + 22222) >> 11) * 0x1.8p-53, 
2336                    alter4 = (DiverRNG.determine(seed + 33333) >> 11) * 0x1p-52;
2337            return (cubicSway(x * alter1) * 0.4375f +
2338                    cubicSway(x * alter2) * 0.3125f +
2339                    cubicSway(x * alter3) * 0.1875f +
2340                    cubicSway(x * alter4) * 0.0625f);
2341        }
2342    }
2343    public static class Sway1D implements Noise1D
2344    {
2345        public static final Sway1D instance = new Sway1D();
2346        public long seed;
2347        public Sway1D()
2348        {
2349            seed = 0L;
2350        }
2351        public Sway1D(long seed)
2352        {
2353            this.seed = seed;
2354        }
2355
2356        @Override
2357        public double getNoise(double x) {
2358            return NumberTools.swayRandomized(seed, x);
2359        }
2360
2361        @Override
2362        public double getNoiseWithSeed(double x, long seed) {
2363            return NumberTools.swayRandomized(seed, x);
2364        }
2365    }
2366    public static class Sway2D implements Noise2D
2367    {
2368        public static final Sway2D instance = new Sway2D();
2369        public long seed;
2370        public Sway2D()
2371        {
2372            seed = 12345L;
2373        }
2374        public Sway2D(long seed)
2375        {
2376            this.seed = seed;
2377        }
2378
2379        @Override
2380        public double getNoise(double x, double y) {
2381            return getNoiseWithSeed(x, y, seed);
2382        }
2383
2384        @Override
2385        public double getNoiseWithSeed(double x, double y, long seed) {
2386//            double xx = NumberTools.swayRandomized(seed - 0xC13FA9A902A6328FL, x + y) * 0.75,
2387//                    yy = NumberTools.swayRandomized(seed - 0xABC98388FB8FAC03L, y - x) * 0.75;
2388//            return NumberTools.sway((NumberTools.swayRandomized(seed, x + yy) +
2389//                    NumberTools.swayRandomized(0x8CB92BA72F3D8DD7L - seed, y + xx)) * 1.25 + 0.5);
2390
2391//            return NumberTools.swayRandomized(seed,
2392//                    (NumberTools.swayRandomized(seed + 0x8CB92BA72F3D8DD7L, (x + y))
2393//                    + NumberTools.swayRandomized(seed + 0xC13FA9A902A6328FL, x * 0.5 - y * 1.5)
2394//                    + NumberTools.swayRandomized(seed + 0xABC98388FB8FAC03L, x * 1.5 - y * 0.5)) * 4.0);
2395
2396//            double adjust0 = NumberTools.swayRandomized(seed + 0xC13FA9A902A6328FL, x * 1.75 + y * -0.25) + 1.,
2397//                    adjust1 = NumberTools.swayRandomized(seed + 0x8CB92BA72F3D8DD7L, x * 0.25 + y * -1.75) + 1.,
2398//                    adjust2 = NumberTools.swayRandomized(seed - 0x8CB92BA72F3D8DD7L, x + y) + 1.;
2399//            return NumberTools.sway(
2400//                    (NumberTools.swayRandomized(seed + 0xC13FA9A902A6328FL, x * 1.5 + y * 0.5) * adjust0
2401//                    + NumberTools.swayRandomized(seed + 0xABC98388FB8FAC03L, x * 0.5 + y * 1.5) * adjust1
2402//                    + NumberTools.swayRandomized(seed + 0x8CB92BA72F3D8DD7L, x - y) * adjust2 
2403//                    ) * 0.75 + 0.5);
2404            final long floorX = x >= 0.0 ? (long) x : (long) x - 1L,
2405                    floorY = y >= 0.0 ? (long) y : (long) y - 1L;
2406//            long seedX = seed * 0xC13FA9A902A6328FL + floorX * 0x91E10DA5C79E7B1DL,
2407//                    seedY = seed * 0x91E10DA5C79E7B1DL + floorY * 0xC13FA9A902A6328FL;
2408//            final long startX = ((seedX ^ (seedX >>> 25)) * (seedX | 0xA529L)),
2409//                    endX = (((seedX += 0x91E10DA5C79E7B1DL) ^ (seedX >>> 25)) * (seedX | 0xA529L));
2410//            final long startY = ((seedY ^ (seedY >>> 25)) * (seedY | 0xA529L)),
2411//                    endY = (((seedY += 0xC13FA9A902A6328FL) ^ (seedY >>> 25)) * (seedY | 0xA529L));
2412//            final int x0y0 = (int) (startX + startY >>> 56),
2413//                    x1y0 = (int) (endX + startY >>> 56),
2414//                    x0y1 = (int) (startX + endY >>> 56),
2415//                    x1y1 = (int) (endX + endY >>> 56);
2416            final int x0y0 = HastyPointHash.hash256(floorX, floorY, seed),
2417                    x1y0 = HastyPointHash.hash256(floorX+1, floorY, seed),
2418                    x0y1 = HastyPointHash.hash256(floorX, floorY+1, seed),
2419                    x1y1 = HastyPointHash.hash256(floorX+1, floorY+1, seed);
2420            x -= floorX;
2421            y -= floorY;
2422//            x *= x * (3.0 - 2.0 * x);
2423//            y *= y * (3.0 - 2.0 * y);
2424//            x *= x;
2425//            y *= y;
2426            final double ix = 1.0 - x, iy = 1.0 - y;
2427//            final double ix = (1 - x) * (1 - x), iy = (1 - y) * (1 - y);
2428//            final double ix = x, iy = y;
2429//            x = 1.0 - x;
2430//            y = 1.0 - y;
2431            //            double ret = ((ix * SeededNoise.phiGrad2[x0y0][0] + iy * SeededNoise.phiGrad2[x0y0][1])
2432//                    + (x * SeededNoise.phiGrad2[x1y0][0] + iy * SeededNoise.phiGrad2[x1y0][1])
2433//                    + (ix * SeededNoise.phiGrad2[x0y1][0] + y * SeededNoise.phiGrad2[x0y1][1])
2434//                    + (x * SeededNoise.phiGrad2[x1y1][0] + y * SeededNoise.phiGrad2[x1y1][1])
2435//            );
2436            return ((SeededNoise.phiGrad2[x0y0][0] + SeededNoise.phiGrad2[x0y0][1]) * (ix * iy)
2437                    + (SeededNoise.phiGrad2[x1y0][0] + SeededNoise.phiGrad2[x1y0][1]) * (x * iy)
2438                    + (SeededNoise.phiGrad2[x0y1][0] + SeededNoise.phiGrad2[x0y1][1]) * (ix * y)
2439                    + (SeededNoise.phiGrad2[x1y1][0] + SeededNoise.phiGrad2[x1y1][1]) * (x * y)
2440            ) * 0.7071067811865475;
2441//            long xf = x >= 0.0 ? (long) x : (long) x - 1L;
2442//            long yf = y >= 0.0 ? (long) y : (long) y - 1L;
2443//            long s = ((0x91E10DA5C79E7B1DL ^ seed ^ yf)) * 0xC13FA9A902A6328FL, s2 = ((0x91E10DA5C79E7B1DL ^ seed ^ yf + 1L)) * 0xC13FA9A902A6328FL;
2444//            double xSmall = x - xf;
2445//            //, 0xABC98388FB8FAC03L, 0x8CB92BA72F3D8DD7L
2446//            double start = (((s += xf * 0x6C8E9CF570932BD5L) ^ (s >>> 25)) * (s | 0xA529L)) * 0x0.fffffffffffffbp-63,
2447//                    start2 = (((s2 += xf * 0x6C8E9CF570932BD5L) ^ (s2 >>> 25)) * (s2 | 0xA529L)) * 0x0.fffffffffffffbp-63,
2448//                    end = (((s += 0x6C8E9CF570932BD5L) ^ (s >>> 25)) * (s | 0xA529L)) * 0x0.fffffffffffffbp-63,
2449//                    end2 = (((s2 += 0x6C8E9CF570932BD5L) ^ (s2 >>> 25)) * (s2 | 0xA529L)) * 0x0.fffffffffffffbp-63;
2450////            double x0y0 = HastyPointHash.hashAll(xf, yf, seed) * 0x0.fffffffffffffbp-63,
2451////                    x1y0 = HastyPointHash.hashAll(xf+1L, yf, seed) * 0x0.fffffffffffffbp-63,
2452////                    x0y1 = HastyPointHash.hashAll(xf, yf+1L, seed) * 0x0.fffffffffffffbp-63,
2453////                    x1y1 = HastyPointHash.hashAll(xf+1L, yf+1L, seed) * 0x0.fffffffffffffbp-63, y0, y1;
2454//            xSmall = xSmall * xSmall * (3.0 - 2.0 * xSmall);
2455////            double a2 = xSmall * xSmall, a4 = a2 * a2, a6 = a4 * a2;
2456////            xSmall = 0x1.c71c71c71c71cp-2 * a6 + -0x1.e38e38e38e38ep0 * a4 + 0x1.38e38e38e38e4p1 * a2;
2457////            y0 = (1.0 - xSmall) * x0y0 + xSmall * x1y0;
2458////            y1 = (1.0 - xSmall) * x0y1 + xSmall * x1y1;
2459//            double ySmall = y - yf;
2460//            ySmall = ySmall * ySmall * (3.0 - 2.0 * ySmall);
2461////            a2 = ySmall * ySmall;
2462////            a4 = a2 * a2;
2463////            a6 = a4 * a2;
2464////            ySmall = 0x1.c71c71c71c71cp-2 * a6 + -0x1.e38e38e38e38ep0 * a4 + 0x1.38e38e38e38e4p1 * a2;
2465//            return (1.0 - ySmall) * ((1.0 - xSmall) * start + xSmall * end) + ySmall * ((1.0 - xSmall) * start2 + xSmall * end2);
2466////            x1 = (1.0 - xSmall) * start2 + xSmall * end2;
2467////            s = HastyPointHash.hashAll(xf, yf, seed);//((0xC13FA9A902A6328FL ^ seed)) * 0x91E10DA5C79E7B1DL;
2468////            start = (((s += yf * 0x6C8E9CF570932BD5L) ^ (s >>> 25)) * (s | 0xA529L)) * 0x0.fffffffffffffbp-63;
2469//////            start2 = (((s2 = s * 0xD1B54A32D192ED03L) ^ (s2 >>> 25)) * (s2 | 0xA529L)) * 0x0.fffffffffffffbp-63;
2470////            end = (((s += 0x6C8E9CF570932BD5L) ^ (s >>> 25)) * (s | 0xA529L)) * 0x0.fffffffffffffbp-63;
2471//////            end2 = (((s2 = s * 0xD1B54A32D192ED03L) ^ (s2 >>> 25)) * (s2 | 0xA529L)) * 0x0.fffffffffffffbp-63;
2472////            y0 = (1.0 - ySmall) * start + ySmall * end;
2473//////            y1 = (1.0 - ySmall) * start2 + ySmall * end2;
2474////            return NumberTools.sway(x0 + y0 + 0.5);
2475        }
2476    }
2477
2478    /**
2479     * A hybrid between value and gradient noise that may be faster for 1D noise. Every integer value of x given to this
2480     * will produce a result of 0. This only hashes one coordinate per noise call, unlike most value noise that needs 2
2481     * hashes in 1D and many more in higher dimensions. Based on <a href="https://www.shadertoy.com/view/3sd3Rs">Inigo
2482     * Quilez' "Basic Noise"</a>.
2483     */
2484    public static class QuilezNoise implements Noise1D, Noise2D {
2485
2486        public long seed;
2487        public QuilezNoise() {
2488            this(0xB0BAFE77L);
2489        }
2490
2491        public QuilezNoise(long seed) {
2492            this.seed = seed;
2493        }
2494        @Override
2495        public double getNoise(double x) { 
2496            return getNoiseWithSeed(x, seed);
2497        }
2498//            xFloor = (xFloor ^ xFloor << 7 ^ 0x9E3779B97F4A7C15L) * 0xD1B54A32D192ED03L;
2499//            xFloor = (xFloor ^ xFloor >>> 41 ^ xFloor >>> 23) * (xFloor ^ xFloor >> 25 | 1) >>> 32;
2500//            final double h = xFloor * 0x1p-28 - 4.0;
2501//            seed = (seed ^ xFloor ^ 0x9E3779B97F4A7C15L) * 0xD1B54A32D192ED03L; // XLCG, helps randomize upper bits
2502//            // this next 'h' part finishes randomizing (not amazing quality, but fast), uses only the upper bits,
2503//            // and reduces it to a double between -8.0 and almost 8.0.
2504//            final double h = ((seed ^ seed >>> 26) * (seed | 0xA529) >>> 32) * 0x1p-28 - 8.0;
2505
2506        @Override
2507        public double getNoiseWithSeed(double x, final long seed) {
2508            x += ((seed & 0xFFFFFFFFL) ^ (seed >>> 32)) * 0x1p-24; // offset x by between 0.0 and almost 256.0
2509            final long xFloor = x >= 0.0 ? (long) x : (long) x - 1, // floor of x as a long
2510                    rise = 1L - ((x >= 0.0 ? (long) (x * 2.0) : (long) (x * 2.0) - 1) & 2L); // either 1 or -1
2511            x -= xFloor;
2512            // and now we flip the switch from "magic" to "more magic..."
2513            // this directly sets the bits that describe a double. this might seem like it should be slow; it is not.
2514            // seed and xFloor are XORed to roughly mix them together; adding would work too probably.
2515            // the two huge longs don't really matter except for their last digits:
2516            // the one that uses ^ must end in 5 or D (both hex) 
2517            // the one that uses * must end in 3 or B (both hex)
2518            // and that makes this a valid "XLCG," a cousin of the commonly used LCG random number generator.
2519            // it improves the randomness in the upper bits more than the lower ones, where the upper bits will become
2520            // more significant decimal places in the resulting double.
2521            // we unsigned-right-shift by 12, which puts the random bits all in the double's mantissa (which is how far
2522            // it is between the previous power of two and next power of two, roughly).
2523            // we bitwise OR with 0x4030000000000000L, which is the exponent section for a double between 16.0 and 32.0.
2524            // we work our magic and convert the bits to double.
2525            // subtracting 24.0 takes the range to -4.0 to 12.0, where we want it (Quilez used this).
2526            final double h = NumberTools.longBitsToDouble((seed ^ xFloor ^ 0x9E3779B97F4A7C15L) * 0xD1B54A32D192ED03L >>> 12 | 
2527                      0x4040000000000000L) - 52.0;
2528//                    0x4030000000000000L) - 20.0;
2529            // Quilez' quartic curve; uses the "rise" calculated earlier to determine if this is on the rising or
2530            // the falling side. Uses that complicated "h" as the height of the peak or valley in the middle.
2531            return rise * x * (x - 1.0) * (h * x * (x - 1.0) - 1.0);
2532        }
2533
2534        @Override
2535        public double getNoise(double x, double y) {
2536            return getNoiseWithSeed(x, y, seed);
2537        }
2538
2539        @Override
2540        public double getNoiseWithSeed(double x, double y, long seed) {
2541            double n = 0.0;
2542            for (int i = 0; i < 4; i++) {
2543                seed += 0x9E3779B97F4A7C15L;
2544                double xEdit = x += (((seed & 0x55555555L) | (seed >>> 32 & 0xAAAAAAAAL))) * 0x1p-29 + 0.5698402909980532;
2545                double yEdit = y += (((seed & 0xAAAAAAAAL) | (seed >>> 32 & 0x55555555L))) * 0x1p-29 + 0.7548776662466927;
2546                final long
2547                        xFloor = xEdit >= 0.0 ? (long) xEdit : (long) xEdit - 1,
2548                        yFloor = yEdit >= 0.0 ? (long) yEdit : (long) yEdit - 1;
2549                xEdit -= xFloor;
2550                yEdit -= yFloor;
2551                xEdit *= (xEdit - 1.0);
2552                yEdit *= (yEdit - 1.0);
2553                final double m = (xEdit + yEdit) * 0.5;
2554                final double h = NumberTools.longBitsToDouble(HastyPointHash.hashAll(xFloor, yFloor, seed) >>> 12 | 0x4040000000000000L) - 52.0;
2555//            final double i = NumberTools.longBitsToDouble((~seed + yFloor ^ 0x9E3779B97F4A7C15L) * 0xD1B54A32D192ED03L >>> 12 | 0x4030000000000000L) - 24.0;
2556                n += (m * (h * m - 1.0));
2557            }
2558            return n * 0.25;
2559////                    cerp(
2560//                    0.5 * (
2561//                            (xRise * m * (h * m - 1.0)) +
2562//                            (yRise * m * (i * m - 1.0))
2563//                    );
2564//                            //, 0.5 + (y - x) * 0.5);
2565        }
2566
2567    }
2568}