private static DECIMAL GradCoord3D(int seed, int x, int y, int z, DECIMAL xd, DECIMAL yd, DECIMAL zd)
        {
            int hash = seed;

            hash ^= PrimeX * x;
            hash ^= PrimeY * y;
            hash ^= PrimeZ * z;

            hash = hash * hash * hash * 60493;
            hash = (hash >> 13) ^ hash;

            Decimal3 g = Grad3D[hash & 15];

            return(xd * g.x + yd * g.y + zd * g.z);
        }
        private DECIMAL SingleCellular2Edge(DECIMAL x, DECIMAL y, DECIMAL z)
        {
            int xr = FastRound(x);
            int yr = FastRound(y);
            int zr = FastRound(z);

            DECIMAL[] distance = { 999999, 999999, 999999, 999999 };

            switch (CellularDistanceFunction)
            {
            case CellularDistanceFunctions.Euclidean:
                for (int xi = xr - 1; xi <= xr + 1; xi++)
                {
                    for (int yi = yr - 1; yi <= yr + 1; yi++)
                    {
                        for (int zi = zr - 1; zi <= zr + 1; zi++)
                        {
                            Decimal3 vec = Cell3D[Hash3D(Seed, xi, yi, zi) & 255];

                            DECIMAL vecX = xi - x + vec.x * CellularJitter;
                            DECIMAL vecY = yi - y + vec.y * CellularJitter;
                            DECIMAL vecZ = zi - z + vec.z * CellularJitter;

                            DECIMAL newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ;

                            for (int i = cellularDistanceIndex1; i > 0; i--)
                            {
                                distance[i] = Math.Max(Math.Min(distance[i], newDistance), distance[i - 1]);
                            }
                            distance[0] = Math.Min(distance[0], newDistance);
                        }
                    }
                }
                break;

            case CellularDistanceFunctions.Manhattan:
                for (int xi = xr - 1; xi <= xr + 1; xi++)
                {
                    for (int yi = yr - 1; yi <= yr + 1; yi++)
                    {
                        for (int zi = zr - 1; zi <= zr + 1; zi++)
                        {
                            Decimal3 vec = Cell3D[Hash3D(Seed, xi, yi, zi) & 255];

                            DECIMAL vecX = xi - x + vec.x * CellularJitter;
                            DECIMAL vecY = yi - y + vec.y * CellularJitter;
                            DECIMAL vecZ = zi - z + vec.z * CellularJitter;

                            DECIMAL newDistance = Math.Abs(vecX) + Math.Abs(vecY) + Math.Abs(vecZ);

                            for (int i = cellularDistanceIndex1; i > 0; i--)
                            {
                                distance[i] = Math.Max(Math.Min(distance[i], newDistance), distance[i - 1]);
                            }
                            distance[0] = Math.Min(distance[0], newDistance);
                        }
                    }
                }
                break;

            case CellularDistanceFunctions.Natural:
                for (int xi = xr - 1; xi <= xr + 1; xi++)
                {
                    for (int yi = yr - 1; yi <= yr + 1; yi++)
                    {
                        for (int zi = zr - 1; zi <= zr + 1; zi++)
                        {
                            Decimal3 vec = Cell3D[Hash3D(Seed, xi, yi, zi) & 255];

                            DECIMAL vecX = xi - x + vec.x * CellularJitter;
                            DECIMAL vecY = yi - y + vec.y * CellularJitter;
                            DECIMAL vecZ = zi - z + vec.z * CellularJitter;

                            DECIMAL newDistance = (Math.Abs(vecX) + Math.Abs(vecY) + Math.Abs(vecZ)) + (vecX * vecX + vecY * vecY + vecZ * vecZ);

                            for (int i = cellularDistanceIndex1; i > 0; i--)
                            {
                                distance[i] = Math.Max(Math.Min(distance[i], newDistance), distance[i - 1]);
                            }
                            distance[0] = Math.Min(distance[0], newDistance);
                        }
                    }
                }
                break;

            default:
                break;
            }

            switch (CellularReturnType)
            {
            case CellularReturnTypes.Distance2:
                return(distance[cellularDistanceIndex1]);

            case CellularReturnTypes.Distance2Add:
                return(distance[cellularDistanceIndex1] + distance[cellularDistanceIndex0]);

            case CellularReturnTypes.Distance2Sub:
                return(distance[cellularDistanceIndex1] - distance[cellularDistanceIndex0]);

            case CellularReturnTypes.Distance2Mul:
                return(distance[cellularDistanceIndex1] * distance[cellularDistanceIndex0]);

            case CellularReturnTypes.Distance2Div:
                return(distance[cellularDistanceIndex0] / distance[cellularDistanceIndex1]);

            default:
                return(0);
            }
            ;
        }
        private void SingleGradientPerturb(int seed, DECIMAL perturbAmp, DECIMAL frequency, ref DECIMAL x, ref DECIMAL y, ref DECIMAL z)
        {
            DECIMAL xf = x * frequency;
            DECIMAL yf = y * frequency;
            DECIMAL zf = z * frequency;

            int x0 = FastFloor(xf);
            int y0 = FastFloor(yf);
            int z0 = FastFloor(zf);
            int x1 = x0 + 1;
            int y1 = y0 + 1;
            int z1 = z0 + 1;

            DECIMAL xs, ys, zs;

            switch (InterpolationMethod)
            {
            default:
            case Interp.Linear:
                xs = xf - x0;
                ys = yf - y0;
                zs = zf - z0;
                break;

            case Interp.Hermite:
                xs = InterpHermiteFunc(xf - x0);
                ys = InterpHermiteFunc(yf - y0);
                zs = InterpHermiteFunc(zf - z0);
                break;

            case Interp.Quintic:
                xs = InterpQuinticFunc(xf - x0);
                ys = InterpQuinticFunc(yf - y0);
                zs = InterpQuinticFunc(zf - z0);
                break;
            }

            Decimal3 vec0 = Cell3D[Hash3D(seed, x0, y0, z0) & 255];
            Decimal3 vec1 = Cell3D[Hash3D(seed, x1, y0, z0) & 255];

            DECIMAL lx0x = Lerp(vec0.x, vec1.x, xs);
            DECIMAL ly0x = Lerp(vec0.y, vec1.y, xs);
            DECIMAL lz0x = Lerp(vec0.z, vec1.z, xs);

            vec0 = Cell3D[Hash3D(seed, x0, y1, z0) & 255];
            vec1 = Cell3D[Hash3D(seed, x1, y1, z0) & 255];

            DECIMAL lx1x = Lerp(vec0.x, vec1.x, xs);
            DECIMAL ly1x = Lerp(vec0.y, vec1.y, xs);
            DECIMAL lz1x = Lerp(vec0.z, vec1.z, xs);

            DECIMAL lx0y = Lerp(lx0x, lx1x, ys);
            DECIMAL ly0y = Lerp(ly0x, ly1x, ys);
            DECIMAL lz0y = Lerp(lz0x, lz1x, ys);

            vec0 = Cell3D[Hash3D(seed, x0, y0, z1) & 255];
            vec1 = Cell3D[Hash3D(seed, x1, y0, z1) & 255];

            lx0x = Lerp(vec0.x, vec1.x, xs);
            ly0x = Lerp(vec0.y, vec1.y, xs);
            lz0x = Lerp(vec0.z, vec1.z, xs);

            vec0 = Cell3D[Hash3D(seed, x0, y1, z1) & 255];
            vec1 = Cell3D[Hash3D(seed, x1, y1, z1) & 255];

            lx1x = Lerp(vec0.x, vec1.x, xs);
            ly1x = Lerp(vec0.y, vec1.y, xs);
            lz1x = Lerp(vec0.z, vec1.z, xs);

            x += Lerp(lx0y, Lerp(lx0x, lx1x, ys), zs) * perturbAmp;
            y += Lerp(ly0y, Lerp(ly0x, ly1x, ys), zs) * perturbAmp;
            z += Lerp(lz0y, Lerp(lz0x, lz1x, ys), zs) * perturbAmp;
        }
        private DECIMAL SingleCellular(DECIMAL x, DECIMAL y, DECIMAL z)
        {
            int xr = FastRound(x);
            int yr = FastRound(y);
            int zr = FastRound(z);

            DECIMAL distance = 999999;
            int     xc = 0, yc = 0, zc = 0;

            switch (CellularDistanceFunction)
            {
            case CellularDistanceFunctions.Euclidean:
                for (int xi = xr - 1; xi <= xr + 1; xi++)
                {
                    for (int yi = yr - 1; yi <= yr + 1; yi++)
                    {
                        for (int zi = zr - 1; zi <= zr + 1; zi++)
                        {
                            Decimal3 vec = Cell3D[Hash3D(Seed, xi, yi, zi) & 255];

                            DECIMAL vecX = xi - x + vec.x * CellularJitter;
                            DECIMAL vecY = yi - y + vec.y * CellularJitter;
                            DECIMAL vecZ = zi - z + vec.z * CellularJitter;

                            DECIMAL newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ;

                            if (newDistance < distance)
                            {
                                distance = newDistance;
                                xc       = xi;
                                yc       = yi;
                                zc       = zi;
                            }
                        }
                    }
                }
                break;

            case CellularDistanceFunctions.Manhattan:
                for (int xi = xr - 1; xi <= xr + 1; xi++)
                {
                    for (int yi = yr - 1; yi <= yr + 1; yi++)
                    {
                        for (int zi = zr - 1; zi <= zr + 1; zi++)
                        {
                            Decimal3 vec = Cell3D[Hash3D(Seed, xi, yi, zi) & 255];

                            DECIMAL vecX = xi - x + vec.x * CellularJitter;
                            DECIMAL vecY = yi - y + vec.y * CellularJitter;
                            DECIMAL vecZ = zi - z + vec.z * CellularJitter;

                            DECIMAL newDistance = Math.Abs(vecX) + Math.Abs(vecY) + Math.Abs(vecZ);

                            if (newDistance < distance)
                            {
                                distance = newDistance;
                                xc       = xi;
                                yc       = yi;
                                zc       = zi;
                            }
                        }
                    }
                }
                break;

            case CellularDistanceFunctions.Natural:
                for (int xi = xr - 1; xi <= xr + 1; xi++)
                {
                    for (int yi = yr - 1; yi <= yr + 1; yi++)
                    {
                        for (int zi = zr - 1; zi <= zr + 1; zi++)
                        {
                            Decimal3 vec = Cell3D[Hash3D(Seed, xi, yi, zi) & 255];

                            DECIMAL vecX = xi - x + vec.x * CellularJitter;
                            DECIMAL vecY = yi - y + vec.y * CellularJitter;
                            DECIMAL vecZ = zi - z + vec.z * CellularJitter;

                            DECIMAL newDistance = (Math.Abs(vecX) + Math.Abs(vecY) + Math.Abs(vecZ)) + (vecX * vecX + vecY * vecY + vecZ * vecZ);

                            if (newDistance < distance)
                            {
                                distance = newDistance;
                                xc       = xi;
                                yc       = yi;
                                zc       = zi;
                            }
                        }
                    }
                }
                break;
            }

            switch (CellularReturnType)
            {
            case CellularReturnTypes.CellValue:
                return(ValCoord3D(Seed, xc, yc, zc));

            case CellularReturnTypes.NoiseLookup:
                Decimal3 vec = Cell3D[Hash3D(Seed, xc, yc, zc) & 255];
                return(CellularNoiseLookup.GetNoise(xc + vec.x * CellularJitter, yc + vec.y * CellularJitter, zc + vec.z * CellularJitter));

            case CellularReturnTypes.Distance:
                return(distance);

            default:
                return(0);
            }
        }