/**
     * Computes the polynomial coefficients for the Hermite cubic spline interpolation
     * for a set of (x,y) value pairs and their derivatives. This is modeled off of
     * the InterpolateHermiteSorted method in the Math.NET CubicSpline class.
     *
     * @param xVals
     *    x values for interpolation.
     * @param yVals
     *    y values for interpolation.
     * @param firstDerivatives
     *    First derivative values of the function.
     * @returns
     *    Polynomial coefficients of the segments.
     */
    static List <float>[] computeHermitePolyCoefficients(float[] xVals, float[] yVals, float[] firstDerivatives)
    {
        if (xVals.Length != yVals.Length || xVals.Length != firstDerivatives.Length)
        {
            Debug.Log("[LogLabel.Easing] Dimension mismatch");
        }
        if (xVals.Length < 2)
        {
            Debug.Log("[LogLabel.Easing] Not enough points.");
        }
        int n = xVals.Length - 1; // number of segments

        List <float>[] segmentCoeffs = new List <float> [n];
        for (int i = 0; i < n; i++)
        {
            float w  = xVals[i + 1] - xVals[i];
            float w2 = w * w;

            float yv  = yVals[i];
            float yvP = yVals[i + 1];

            float fd  = firstDerivatives[i];
            float fdP = firstDerivatives[i + 1];

            float[] coeffs = new float[4];
            coeffs[0]        = yv;
            coeffs[1]        = firstDerivatives[i];
            coeffs[2]        = (3 * (yvP - yv) / w - 2 * fd - fdP) / w;
            coeffs[3]        = (2 * (yv - yvP) / w + fd + fdP) / w2;
            segmentCoeffs[i] = PolynomialRoutines.trimPoly(coeffs).ToList();
        }
        return(segmentCoeffs);
    }
    /**
     * An univariate numeric function.
     */
    //static System.Func<float, float> UniFunction;

    /// <summary>
    /// Returns a function that computes a cubic spline interpolation for the data
    /// set using the Akima algorithm, as originally formulated by Hiroshi Akima in
    /// his 1970 paper "A New Method of Interpolation and Smooth Curve Fitting Based
    /// on Local Procedures."
    /// J. ACM 17, 4 (October 1970), 589-602. DOI=10.1145/321607.321609
    /// http://doi.acm.org/10.1145/321607.321609
    ///
    /// This implementation is based on the Akima implementation in the CubicSpline
    /// class in the Math.NET Numerics library. The method referenced is
    /// CubicSpline.InterpolateAkimaSorted.
    ///
    /// Returns a polynomial spline function consisting of n cubic polynomials,
    /// defined over the subintervals determined by the x values,
    /// x[0] < x[1] < ... < x[n-1].
    /// The Akima algorithm requires that n >= 5.
    ///
    /// @param xVals
    ///    The arguments of the interpolation points.
    /// @param yVals
    ///    The values of the interpolation points.
    /// @returns
    ///    A function which interpolates the dataset.
    /// </summary>
    public static System.Func <float, float> createAkimaSplineInterpolator(float[] xVals, float[] yVals)
    {
        List <float>[] segmentCoeffs = computeAkimaPolyCoefficients(xVals, yVals);
        float[]        xValsCopy     = new float[xVals.Length];
        xVals.CopyTo(xValsCopy, 0); // clone to break dependency on passed values
        return((float x) => {
            return PolynomialRoutines.evaluatePolySegment(xValsCopy, segmentCoeffs, x);
        });
    }