public static Double NewSimplexNoise4D(Double x, Double y, Double z, Double w, Int32 seed, InterpolationDelegate interp)
{
var f4 = (Math.Sqrt(5.0) - 1.0)/4.0;
var sideLength = 2.0/(4.0*f4 + 1.0);
var a = Math.Sqrt((sideLength*sideLength) - ((sideLength/2.0)*(sideLength/2.0)));
var cornerToFace = Math.Sqrt((a*a + (a/2.0)*(a/2.0)));
var cornerToFaceSquared = cornerToFace*cornerToFace;
var valueScaler = Math.Pow(3.0, -0.5);
var g4 = f4/(1.0 + 4.0*f4);
valueScaler *= Math.Pow(3.0, -3.5)*100.0 + 13.0;
Double[] loc = {x, y, z, w};
Double s = 0;
for (var c = 0; c < 4; ++c)
s += loc[c];
s *= f4;
var skewLoc = new[] {FastFloor(x + s), FastFloor(y + s), FastFloor(z + s), FastFloor(w + s)};
var intLoc = new[] {FastFloor(x + s), FastFloor(y + s), FastFloor(z + s), FastFloor(w + s)};
var unskew = 0.00;
for (var c = 0; c < 4; ++c)
unskew += skewLoc[c];
unskew *= g4;
var cellDist = new[]
{
loc[0] - skewLoc[0] + unskew, loc[1] - skewLoc[1] + unskew,
loc[2] - skewLoc[2] + unskew, loc[3] - skewLoc[3] + unskew
};
var distOrder = new[] {0, 1, 2, 3};
SortBy4(cellDist, distOrder);
var newDistOrder = new[] {-1, distOrder[0], distOrder[1], distOrder[2], distOrder[3]};
var n = 0.00;
var skewOffset = 0.00;
for (var c = 0; c < 5; ++c)
{
var i = newDistOrder[c];
if (i != -1)
intLoc[i] += 1;
var u = new Double[4];
for (var d = 0; d < 4; ++d)
{
u[d] = cellDist[d] - (intLoc[d] - skewLoc[d]) + skewOffset;
}
var t = cornerToFaceSquared;
for (var d = 0; d < 4; ++d)
{
t -= u[d]*u[d];
}
if (t > 0.0)
{
var h = HashCoordinates(intLoc[0], intLoc[1], intLoc[2], intLoc[3], seed);
var gr = 0.00;
for (var d = 0; d < 4; ++d)
{
gr += NoiseLookupTable.Gradient4D[h, d]*u[d];
}
n += gr*t*t*t*t;
}
skewOffset += g4;
}
n *= valueScaler;
return n;
}