Class PhantomNoise

java.lang.Object
squidpony.squidmath.PhantomNoise

@Beta
public class PhantomNoise
extends Object
Arbitrary-dimensional continuous noise that maintains most of the same style even as the dimensionality gets fairly high. If you know what dimension of noise you need, and it's covered by FoamNoise (meaning it's 2D, 3D, 4D, or 6D noise), then using FoamNoise will give you a significantly faster version of approximately the same algorithm. If your noise has an unknown dimension count, this won't really work either, since PhantomNoise needs to do some preparation and allocation for a specific dimension in its constructor. But, if you know what the range of dimensions is, and the lowest is at least 2D, you can make one PhantomNoise per dimension easily enough.
The algorithm this uses is surprisingly simple. To produce N-D noise, it makes N+1 calls to N-D value noise, with each call using a different rotation of the same size of grid. It "domain warps" value noise calls after the first, adding the previous value noise result to one coordinate of the next value noise call. To get a PhantomNoise result, it averages all the value noise calls and curves the output range so it doesn't get more biased toward 0 with higher dimensions (which would happen with a pure average of a rising number of variables). The curving here uses adapted code from libGDX's Interpolation.Pow class; it looks like this for 2D, like this for 3D, and like this for 4D. There's some preparation this does in the constructor, which eliminates the need for allocations during noise generation. For N-D PhantomNoise, this makes N+1 double arrays, one for each rotation for a value noise call, and each rotation array has N items. The rotations match the vertices of an N-simplex, so a triangle in 2D, a tetrahedron in 3D, etc. It also stores two working-room arrays, each with N+1 double items, two frequently-edited int arrays of the floors of doubles it's using, and of modified versions of those floors to be hashed (each with N+1 items), and interestingly, a CrossHash.Yolk hash functor, seeded in the PhantomNoise constructor.
At higher dimensions, Simplex noise (what SeededNoise produces) starts to change how it looks compared to lower dimensions. PhantomNoise, on the other hand, maintains a fairly consistent blob-like organic look, such as this 6D PhantomNoise sample. Red and purple mark the highest and lowest possible values, respectively, and while they appear plenty in PhantomNoise, they are absent in this 6D SeededNoise sample. There may be differences in how the inputs are handled between the two samples, but 6D Simplex generally suffers from "the curse of dimensionality" more-so than PhantomNoise (or Perlin noise like ClassicNoise, somewhat surprisingly), with the "curse" affecting the density of information in higher-dimensional space.
This is marked Beta because it's still pretty slow at higher dimensions, and if some optimization becomes available here, I'll take it and the output will change from this version.