private DoubleArray[] fdSenseCal(double[] xValues, double[] yValues, double[] xx)
        {
            int    nData = yValues.Length;
            double eps   = 1e-6;
            double scale = 0.5 / eps;

            DoubleArray[]             res  = new DoubleArray[nData];
            double[]                  temp = new double[nData];
            PiecewisePolynomialResult pp;

            for (int i = 0; i < nData; i++)
            {
                Array.Copy(yValues, 0, temp, 0, nData);
                temp[i] += eps;
                pp       = PCHIP.interpolate(xValues, temp);
                DoubleArray yUp = PPVAL.evaluate(pp, xx).row(0);
                temp[i] -= 2 * eps;
                pp       = PCHIP.interpolate(xValues, temp);
                DoubleArray yDown = PPVAL.evaluate(pp, xx).row(0);
                res[i] = (DoubleArray)MA.scale(MA.subtract(yUp, yDown), scale);
            }
            return(res);
        }