/// <summary>
        ///   Get the noise function at a given position specified by f
        /// </summary>
        /// <param name="f">A position in space (dimension 1-4)</param>
        /// <returns>Amplitude of noise from this pass at the given location.</returns>
        public float GetNoise(float[] f)
        {
            int[]   n = new int[MaxDimensions];                 // Indexes to pass to lattice function
            float[] r = new float[MaxDimensions];               // Remainders to pass to lattice function
            float[] w = new float[MaxDimensions];               // Cubic values to pass to interpolation function

            for (int i = 0; i < m_nDimensions; i++)
            {
                n[i] = (int)Math.Floor(f[i]);
                r[i] = f[i] - n[i];
                w[i] = NoiseHelper.Cubic(r[i]);
            }

            float fValue;

            switch (m_nDimensions)
            {
            case 1:
                fValue = Lerp(Lattice(n[0], r[0]),
                              Lattice(n[0] + 1, r[0] - 1),
                              w[0]);
                break;

            case 2:
                fValue = Lerp(Lerp(Lattice(n[0], r[0], n[1], r[1]),
                                   Lattice(n[0] + 1, r[0] - 1, n[1], r[1]),
                                   w[0]),
                              Lerp(Lattice(n[0], r[0], n[1] + 1, r[1] - 1),
                                   Lattice(n[0] + 1, r[0] - 1, n[1] + 1, r[1] - 1),
                                   w[0]),
                              w[1]);
                break;

            case 3:
                fValue = Lerp(Lerp(Lerp(Lattice(n[0], r[0], n[1], r[1], n[2], r[2]),
                                        Lattice(n[0] + 1, r[0] - 1, n[1], r[1], n[2], r[2]),
                                        w[0]),
                                   Lerp(Lattice(n[0], r[0], n[1] + 1, r[1] - 1, n[2], r[2]),
                                        Lattice(n[0] + 1, r[0] - 1, n[1] + 1, r[1] - 1, n[2], r[2]),
                                        w[0]),
                                   w[1]),
                              Lerp(Lerp(Lattice(n[0], r[0], n[1], r[1], n[2] + 1, r[2] - 1),
                                        Lattice(n[0] + 1, r[0] - 1, n[1], r[1], n[2] + 1, r[2] - 1),
                                        w[0]),
                                   Lerp(Lattice(n[0], r[0], n[1] + 1, r[1] - 1, n[2] + 1, r[2] - 1),
                                        Lattice(n[0] + 1, r[0] - 1, n[1] + 1, r[1] - 1, n[2] + 1, r[2] - 1),
                                        w[0]),
                                   w[1]),
                              w[2]);
                break;

            case 4:
                fValue = Lerp(Lerp(Lerp(Lerp(Lattice(n[0], r[0], n[1], r[1], n[2], r[2], n[3], r[3]),
                                             Lattice(n[0] + 1, r[0] - 1, n[1], r[1], n[2], r[2], n[3], r[3]),
                                             w[0]),
                                        Lerp(Lattice(n[0], r[0], n[1] + 1, r[1] - 1, n[2], r[2], n[3], r[3]),
                                             Lattice(n[0] + 1, r[0] - 1, n[1] + 1, r[1] - 1, n[2], r[2], n[3], r[3]),
                                             w[0]),
                                        w[1]),
                                   Lerp(Lerp(Lattice(n[0], r[0], n[1], r[1], n[2] + 1, r[2] - 1, n[3], r[3]),
                                             Lattice(n[0] + 1, r[0] - 1, n[1], r[1], n[2] + 1, r[2] - 1, n[3], r[3]),
                                             w[0]),
                                        Lerp(Lattice(n[0], r[0], n[1] + 1, r[1] - 1, n[2] + 1, r[2] - 1),
                                             Lattice(n[0] + 1, r[0] - 1, n[1] + 1, r[1] - 1, n[2] + 1, r[2] - 1, n[3], r[3]),
                                             w[0]),
                                        w[1]),
                                   w[2]),
                              Lerp(Lerp(Lerp(Lattice(n[0], r[0], n[1], r[1], n[2], r[2], n[3] + 1, r[3] - 1),
                                             Lattice(n[0] + 1, r[0] - 1, n[1], r[1], n[2], r[2], n[3] + 1, r[3] - 1),
                                             w[0]),
                                        Lerp(Lattice(n[0], r[0], n[1] + 1, r[1] - 1, n[2], r[2], n[3] + 1, r[3] - 1),
                                             Lattice(n[0] + 1, r[0] - 1, n[1] + 1, r[1] - 1, n[2], r[2], n[3] + 1, r[3] - 1),
                                             w[0]),
                                        w[1]),
                                   Lerp(Lerp(Lattice(n[0], r[0], n[1], r[1], n[2] + 1, r[2] - 1, n[3] + 1, r[3] - 1),
                                             Lattice(n[0] + 1, r[0] - 1, n[1], r[1], n[2] + 1, r[2] - 1, n[3] + 1, r[3] - 1),
                                             w[0]),
                                        Lerp(Lattice(n[0], r[0], n[1] + 1, r[1] - 1, n[2] + 1, r[2] - 1),
                                             Lattice(n[0] + 1, r[0] - 1, n[1] + 1, r[1] - 1, n[2] + 1, r[2] - 1, n[3] + 1, r[3] - 1),
                                             w[0]),
                                        w[1]),
                                   w[2]),
                              w[3]);
                break;

            default:
                throw new Exception("Invalid value for dimension");
            }
            return(NoiseHelper.Clamp(-0.99999f, 0.99999f, fValue));
        }
 private static float Lerp(float a, float b, float x)
 {
     return(NoiseHelper.Lerp(a, b, x));
 }