///
        /// <param name="xDataMatrix">  the x-matrix </param>
        /// <param name="betas"> Optimal coefficients of the polynomial </param>
        /// <param name="yDataVector">  the y-vlaues </param>
        /// <returns> Difference between yData[i] and f(xData[i]), where f() is the polynomial with derived coefficients </returns>
        private double[] residualsSolver(DoubleMatrix xDataMatrix, double[] betas, DoubleArray yDataVector)
        {
            DoubleArray betasVector = DoubleArray.copyOf(betas);

            DoubleArray modelValuesVector = (DoubleArray)OG_ALGEBRA.multiply(xDataMatrix, betasVector);
            DoubleArray res = (DoubleArray)OG_ALGEBRA.subtract(yDataVector, modelValuesVector);

            return(res.toArray());
        }
        /// <summary>
        /// Cubic spline is obtained by solving a linear problem Ax=b where A is a square matrix and x,b are vector
        /// This can be done by LU decomposition </summary>
        /// <param name="doubMat"> Matrix A </param>
        /// <param name="doubVec"> Vector B </param>
        /// <returns> Solution to the linear equation, x </returns>
        protected internal virtual double[] matrixEqnSolver(double[][] doubMat, double[] doubVec)
        {
            LUDecompositionResult result = _luObj.apply(DoubleMatrix.copyOf(doubMat));

            double[][]  lMat       = result.L.toArray();
            double[][]  uMat       = result.U.toArray();
            DoubleArray doubVecMod = ((DoubleArray)OG_ALGEBRA.multiply(result.P, DoubleArray.copyOf(doubVec)));

            return(backSubstitution(uMat, forwardSubstitution(lMat, doubVecMod)));
        }
        /// <summary>
        /// Alternative regression method with different output. </summary>
        /// <param name="xData"> X values of data </param>
        /// <param name="yData"> Y values of data </param>
        /// <param name="degree"> Degree of polynomial which fits the given data </param>
        /// <param name="normalize"> Normalize xData by mean and standard deviation if normalize == true </param>
        /// <returns> PolynomialsLeastSquaresRegressionResult containing coefficients, rMatrix, degrees of freedom, norm of residuals, and mean, standard deviation </returns>
        public virtual PolynomialsLeastSquaresFitterResult regressVerbose(double[] xData, double[] yData, int degree, bool normalize)
        {
            LeastSquaresRegressionResult result = regress(xData, yData, degree, normalize);

            int          nData   = xData.Length;
            DoubleMatrix rMatriX = _qrResult.R;

            DoubleArray resResult = DoubleArray.copyOf(result.Residuals);
            double      resNorm   = OG_ALGEBRA.getNorm2(resResult);

            if (normalize == true)
            {
                return(new PolynomialsLeastSquaresFitterResult(result.Betas, rMatriX, nData - degree - 1, resNorm, _renorm));
            }
            return(new PolynomialsLeastSquaresFitterResult(result.Betas, rMatriX, nData - degree - 1, resNorm));
        }
Esempio n. 4
0
        public virtual DoubleMatrix getUpdatedMatrix(System.Func <DoubleArray, DoubleMatrix> j, DoubleArray x, DoubleArray deltaX, DoubleArray deltaY, DoubleMatrix matrix)
        {
            ArgChecker.notNull(deltaX, "deltaX");
            ArgChecker.notNull(deltaY, "deltaY");
            ArgChecker.notNull(matrix, "matrix");
            double length2 = OG_ALGEBRA.getInnerProduct(deltaX, deltaX);

            if (length2 == 0.0)
            {
                return(matrix);
            }
            Matrix temp = OG_ALGEBRA.subtract(deltaY, OG_ALGEBRA.multiply(matrix, deltaX));

            temp = OG_ALGEBRA.scale(temp, 1.0 / length2);
            return((DoubleMatrix)OG_ALGEBRA.add(matrix, OG_ALGEBRA.getOuterProduct(temp, deltaX)));
        }
            //-------------------------------------------------------------------------
            internal static double[] calculateSecondDerivative(double[] xValues, double[] yValues, int dataSize, double leftFirstDev, double rightFirstDev, bool leftNatural, bool rightNatural)
            {
                double[] deltaX           = new double[dataSize - 1];
                double[] deltaYOverDeltaX = new double[dataSize - 1];
                double[] oneOverDeltaX    = new double[dataSize - 1];

                for (int i = 0; i < dataSize - 1; i++)
                {
                    deltaX[i]           = xValues[i + 1] - xValues[i];
                    oneOverDeltaX[i]    = 1.0 / deltaX[i];
                    deltaYOverDeltaX[i] = (yValues[i + 1] - yValues[i]) * oneOverDeltaX[i];
                }
                DoubleMatrix inverseTriDiag = getInverseTridiagonalMatrix(deltaX, leftNatural, rightNatural);
                DoubleArray  rhsVector      = getRightVector(deltaYOverDeltaX, leftFirstDev, rightFirstDev, leftNatural, rightNatural);

                return(((DoubleArray)OG_ALGEBRA.multiply(inverseTriDiag, rhsVector)).toArray());
            }
            internal static double[][] getSecondDerivativesSensitivities(double[] xValues, double[] yValues, int dataSize, bool leftNatural, bool rightNatural)
            {
                double[] deltaX           = new double[dataSize - 1];
                double[] deltaYOverDeltaX = new double[dataSize - 1];
                double[] oneOverDeltaX    = new double[dataSize - 1];

                for (int i = 0; i < dataSize - 1; i++)
                {
                    deltaX[i]           = xValues[i + 1] - xValues[i];
                    oneOverDeltaX[i]    = 1.0 / deltaX[i];
                    deltaYOverDeltaX[i] = (yValues[i + 1] - yValues[i]) * oneOverDeltaX[i];
                }

                DoubleMatrix inverseTriDiag = getInverseTridiagonalMatrix(deltaX, leftNatural, rightNatural);
                DoubleMatrix rhsMatrix      = getRightMatrix(oneOverDeltaX, leftNatural, rightNatural);

                return(((DoubleMatrix)OG_ALGEBRA.multiply(inverseTriDiag, rhsMatrix)).toArray());
            }
        /// <summary>
        /// Under the QR decomposition, xDataMatrix = qMatrix * rMatrix, optimal coefficients of the
        /// polynomial are computed by back substitution </summary>
        /// <param name="qMatrix">  the q-matrix </param>
        /// <param name="rMatrix">  the r-matrix </param>
        /// <param name="yDataVector">  the y-values </param>
        /// <param name="degree">  the degree </param>
        /// <returns> Coefficients of the polynomial which minimize least square </returns>
        private double[] backSubstitution(DoubleMatrix qMatrix, DoubleMatrix rMatrix, DoubleArray yDataVector, int degree)
        {
            double[] res = new double[degree + 1];
            Arrays.fill(res, 0.0);

            DoubleMatrix tpMatrix     = OG_ALGEBRA.getTranspose(qMatrix);
            DoubleArray  yDataVecConv = (DoubleArray)OG_ALGEBRA.multiply(tpMatrix, yDataVector);

            for (int i = 0; i < degree + 1; ++i)
            {
                double tmp = 0.0;
                for (int j = 0; j < i; ++j)
                {
                    tmp -= rMatrix.get(degree - i, degree - j) * res[degree - j] / rMatrix.get(degree - i, degree - i);
                }
                res[degree - i] = yDataVecConv.get(degree - i) / rMatrix.get(degree - i, degree - i) + tmp;
            }

            return(res);
        }
        /// <summary>
        /// Cubic spline and its node sensitivity are respectively obtained by solving a linear problem Ax=b where A is a square matrix and x,b are vector and AN=L where N,L are matrices </summary>
        /// <param name="doubMat1"> The matrix A </param>
        /// <param name="doubVec"> The vector b </param>
        /// <param name="doubMat2"> The matrix L </param>
        /// <returns> The solutions to the linear systems, x,N </returns>
        protected internal virtual DoubleArray[] combinedMatrixEqnSolver(double[][] doubMat1, double[] doubVec, double[][] doubMat2)
        {
            int nDataPts = doubVec.Length;
            LUDecompositionResult result = _luObj.apply(DoubleMatrix.copyOf(doubMat1));

            double[][]   lMat       = result.L.toArray();
            double[][]   uMat       = result.U.toArray();
            DoubleMatrix pMat       = result.P;
            DoubleArray  doubVecMod = ((DoubleArray)OG_ALGEBRA.multiply(pMat, DoubleArray.copyOf(doubVec)));

            DoubleMatrix doubMat2Matrix = DoubleMatrix.copyOf(doubMat2);

            DoubleArray[] res = new DoubleArray[nDataPts + 1];
            res[0] = DoubleArray.copyOf(backSubstitution(uMat, forwardSubstitution(lMat, doubVecMod)));
            for (int i = 0; i < nDataPts; ++i)
            {
                DoubleArray doubMat2Colum = doubMat2Matrix.column(i);
                DoubleArray doubVecMod2   = ((DoubleArray)OG_ALGEBRA.multiply(pMat, doubMat2Colum));
                res[i + 1] = DoubleArray.copyOf(backSubstitution(uMat, forwardSubstitution(lMat, doubVecMod2)));
            }
            return(res);
        }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void testInvert()
        public virtual void testInvert()
        {
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final com.opengamma.strata.collect.array.DoubleMatrix res = CALCULATOR.apply(MATRIX);
            DoubleMatrix res = CALCULATOR.apply(MATRIX);
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final com.opengamma.strata.collect.array.DoubleMatrix idet = (com.opengamma.strata.collect.array.DoubleMatrix) OG_ALGEBRA.multiply(TRI, res);
            DoubleMatrix idet = (DoubleMatrix)OG_ALGEBRA.multiply(TRI, res);

//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final int n = idet.rowCount();
            int n = idet.rowCount();
            int i, j;

            for (i = 0; i < n; i++)
            {
                for (j = 0; j < n; j++)
                {
                    assertEquals((i == j ? 1.0 : 0.0), idet.get(i, j), EPS);
                }
            }
        }
Esempio n. 10
0
//JAVA TO C# CONVERTER WARNING: 'final' parameters are not available in .NET:
//ORIGINAL LINE: @Override public PiecewisePolynomialResult2D interpolate(final double[] x0Values, final double[] x1Values, final double[][] yValues)
        public override PiecewisePolynomialResult2D interpolate(double[] x0Values, double[] x1Values, double[][] yValues)
        {
            ArgChecker.notNull(x0Values, "x0Values");
            ArgChecker.notNull(x1Values, "x1Values");
            ArgChecker.notNull(yValues, "yValues");

//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final int nData0 = x0Values.length;
            int nData0 = x0Values.Length;
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final int nData1 = x1Values.length;
            int nData1 = x1Values.Length;

            DoubleMatrix yValuesMatrix = DoubleMatrix.copyOf(yValues);
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final com.opengamma.strata.math.impl.function.PiecewisePolynomialFunction1D func = new com.opengamma.strata.math.impl.function.PiecewisePolynomialFunction1D();
            PiecewisePolynomialFunction1D func = new PiecewisePolynomialFunction1D();

//JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java:
//ORIGINAL LINE: double[][] diff0 = new double[nData1][nData0];
            double[][] diff0 = RectangularArrays.ReturnRectangularDoubleArray(nData1, nData0);
//JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java:
//ORIGINAL LINE: double[][] diff1 = new double[nData0][nData1];
            double[][] diff1 = RectangularArrays.ReturnRectangularDoubleArray(nData0, nData1);
//JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java:
//ORIGINAL LINE: double[][] cross = new double[nData0][nData1];
            double[][] cross = RectangularArrays.ReturnRectangularDoubleArray(nData0, nData1);

            PiecewisePolynomialResult result0 = _method[0].interpolate(x0Values, OG_ALGEBRA.getTranspose(yValuesMatrix).toArray());

            diff0 = func.differentiate(result0, x0Values).toArray();

            PiecewisePolynomialResult result1 = _method[1].interpolate(x1Values, yValuesMatrix.toArray());

            diff1 = func.differentiate(result1, x1Values).toArray();

            const int order = 4;

            for (int i = 0; i < nData0; ++i)
            {
                for (int j = 0; j < nData1; ++j)
                {
                    if (yValues[i][j] == 0.0)
                    {
                        if (diff0[j][i] == 0.0)
                        {
                            cross[i][j] = diff1[i][j];
                        }
                        else
                        {
                            if (diff1[i][j] == 0.0)
                            {
                                cross[i][j] = diff0[j][i];
                            }
                            else
                            {
                                cross[i][j] = Math.Sign(diff0[j][i] * diff1[i][j]) * Math.Sqrt(Math.Abs(diff0[j][i] * diff1[i][j]));
                            }
                        }
                    }
                    else
                    {
                        cross[i][j] = diff0[j][i] * diff1[i][j] / yValues[i][j];
                    }
                }
            }

//JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java:
//ORIGINAL LINE: DoubleMatrix[][] coefMat = new DoubleMatrix[nData0 - 1][nData1 - 1];
            DoubleMatrix[][] coefMat = RectangularArrays.ReturnRectangularDoubleMatrixArray(nData0 - 1, nData1 - 1);
            for (int i = 0; i < nData0 - 1; ++i)
            {
                for (int j = 0; j < nData1 - 1; ++j)
                {
                    double[] diffsVec = new double[16];
                    for (int l = 0; l < 2; ++l)
                    {
                        for (int m = 0; m < 2; ++m)
                        {
                            diffsVec[l + 2 * m] = yValues[i + l][j + m];
                        }
                    }
                    for (int l = 0; l < 2; ++l)
                    {
                        for (int m = 0; m < 2; ++m)
                        {
                            diffsVec[4 + l + 2 * m] = diff0[j + m][i + l];
                        }
                    }
                    for (int l = 0; l < 2; ++l)
                    {
                        for (int m = 0; m < 2; ++m)
                        {
                            diffsVec[8 + l + 2 * m] = diff1[i + l][j + m];
                        }
                    }
                    for (int l = 0; l < 2; ++l)
                    {
                        for (int m = 0; m < 2; ++m)
                        {
                            diffsVec[12 + l + 2 * m] = cross[i + l][j + m];
                        }
                    }
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final com.opengamma.strata.collect.array.DoubleArray diffs = com.opengamma.strata.collect.array.DoubleArray.copyOf(diffsVec);
                    DoubleArray diffs = DoubleArray.copyOf(diffsVec);
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final com.opengamma.strata.collect.array.DoubleArray ansVec = ((com.opengamma.strata.collect.array.DoubleArray) OG_ALGEBRA.multiply(INV_MAT, diffs));
                    DoubleArray ansVec = ((DoubleArray)OG_ALGEBRA.multiply(INV_MAT, diffs));

                    double @ref = 0.0;
//JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java:
//ORIGINAL LINE: double[][] coefMatTmp = new double[order][order];
                    double[][] coefMatTmp = RectangularArrays.ReturnRectangularDoubleArray(order, order);
                    for (int l = 0; l < order; ++l)
                    {
                        for (int m = 0; m < order; ++m)
                        {
                            coefMatTmp[order - l - 1][order - m - 1] = ansVec.get(l + m * (order)) / Math.Pow((x0Values[i + 1] - x0Values[i]), l) / Math.Pow((x1Values[j + 1] - x1Values[j]), m);
                            ArgChecker.isFalse(double.IsNaN(coefMatTmp[order - l - 1][order - m - 1]), "Too large/small input");
                            ArgChecker.isFalse(double.IsInfinity(coefMatTmp[order - l - 1][order - m - 1]), "Too large/small input");
                            @ref += coefMatTmp[order - l - 1][order - m - 1] * Math.Pow((x0Values[i + 1] - x0Values[i]), l) * Math.Pow((x1Values[j + 1] - x1Values[j]), m);
                        }
                    }
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final double bound = Math.max(Math.abs(ref) + Math.abs(yValues[i + 1][j + 1]), 0.1);
                    double bound = Math.Max(Math.Abs(@ref) + Math.Abs(yValues[i + 1][j + 1]), 0.1);
                    ArgChecker.isTrue(Math.Abs(@ref - yValues[i + 1][j + 1]) < ERROR * bound, "Input is too large/small or data points are too close");
                    coefMat[i][j] = DoubleMatrix.copyOf(coefMatTmp);
                }
            }

            return(new PiecewisePolynomialResult2D(DoubleArray.copyOf(x0Values), DoubleArray.copyOf(x1Values), coefMat, new int[] { order, order }));
        }
        ///
        public virtual void crossDerivativeTest()
        {
            double[] x0Values = new double[] { 1.0, 2.0, 3.0, 4.0 };
            double[] x1Values = new double[] { -1.0, 0.0, 1.0, 2.0, 3.0 };
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final int n0Data = x0Values.length;
            int n0Data = x0Values.Length;
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final int n1Data = x1Values.length;
            int n1Data = x1Values.Length;

            double[][] yValues = new double[][]
            {
                new double[] { 1.0, -1.0, 0.0, 1.0, 0.0 },
                new double[] { 1.0, -1.0, 0.0, 1.0, -2.0 },
                new double[] { 1.0, -2.0, 0.0, -2.0, -2.0 },
                new double[] { -1.0, -1.0, -2.0, -2.0, -1.0 }
            };

            NaturalSplineInterpolator         method = new NaturalSplineInterpolator();
            PiecewisePolynomialInterpolator2D interp = new BicubicSplineInterpolator(method);
            PiecewisePolynomialResult2D       result = interp.interpolate(x0Values, x1Values, yValues);

//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final int n0IntExp = n0Data - 1;
            int n0IntExp = n0Data - 1;
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final int n1IntExp = n1Data - 1;
            int       n1IntExp = n1Data - 1;
            const int orderExp = 4;

            const int n0Keys = 51;
            const int n1Keys = 61;

            double[] x0Keys = new double[n0Keys];
            double[] x1Keys = new double[n1Keys];
            for (int i = 0; i < n0Keys; ++i)
            {
                x0Keys[i] = 0.0 + 5.0 * i / (n0Keys - 1);
            }
            for (int i = 0; i < n1Keys; ++i)
            {
                x1Keys[i] = -2.0 + 6.0 * i / (n1Keys - 1);
            }

            assertEquals(result.NumberOfIntervals[0], n0IntExp);
            assertEquals(result.NumberOfIntervals[1], n1IntExp);
            assertEquals(result.Order[0], orderExp);
            assertEquals(result.Order[1], orderExp);

            for (int i = 0; i < n0Data; ++i)
            {
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final double ref = Math.abs(x0Values[i]) == 0.0 ? 1.0 : Math.abs(x0Values[i]);
                double @ref = Math.Abs(x0Values[i]) == 0.0 ? 1.0 : Math.Abs(x0Values[i]);
                assertEquals(result.Knots0.get(i), x0Values[i], @ref * EPS);
                assertEquals(result.Knots2D[0].get(i), x0Values[i], @ref * EPS);
            }
            for (int i = 0; i < n1Data; ++i)
            {
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final double ref = Math.abs(x1Values[i]) == 0.0 ? 1.0 : Math.abs(x1Values[i]);
                double @ref = Math.Abs(x1Values[i]) == 0.0 ? 1.0 : Math.Abs(x1Values[i]);
                assertEquals(result.Knots1.get(i), x1Values[i], @ref * EPS);
                assertEquals(result.Knots2D[1].get(i), x1Values[i], @ref * EPS);
            }

            for (int i = 0; i < n0Data - 1; ++i)
            {
                for (int j = 0; j < n1Data - 1; ++j)
                {
                    double @ref = Math.Abs(yValues[i][j]) == 0.0 ? 1.0 : Math.Abs(yValues[i][j]);
                    assertEquals(result.Coefs[i][j].get(orderExp - 1, orderExp - 1), yValues[i][j], @ref * EPS);
                }
            }

            DoubleMatrix resValues = interp.interpolate(x0Values, x1Values, yValues, x0Values, x1Values);
            PiecewisePolynomialFunction2D func2D = new PiecewisePolynomialFunction2D();
            DoubleMatrix resDiffX0 = func2D.differentiateX0(result, x0Values, x1Values);
            DoubleMatrix resDiffX1 = func2D.differentiateX1(result, x0Values, x1Values);

            PiecewisePolynomialFunction1D func1D = new PiecewisePolynomialFunction1D();
            DoubleMatrix expDiffX0 = func1D.differentiate(method.interpolate(x0Values, OG_ALGEBRA.getTranspose(DoubleMatrix.copyOf(yValues)).toArray()), x0Values);
            DoubleMatrix expDiffX1 = func1D.differentiate(method.interpolate(x1Values, yValues), x1Values);

            for (int i = 0; i < n0Data; ++i)
            {
                for (int j = 0; j < n1Data; ++j)
                {
                    double expVal = expDiffX1.get(i, j);
                    double @ref   = Math.Abs(expVal) == 0.0 ? 1.0 : Math.Abs(expVal);
                    assertEquals(resDiffX1.get(i, j), expVal, @ref * EPS);
                }
            }

            for (int i = 0; i < n0Data; ++i)
            {
                for (int j = 0; j < n1Data; ++j)
                {
                    double expVal = expDiffX0.get(j, i);
                    double @ref   = Math.Abs(expVal) == 0.0 ? 1.0 : Math.Abs(expVal);
                    assertEquals(resDiffX0.get(i, j), expVal, @ref * EPS);
                }
            }

            for (int i = 0; i < n0Data; ++i)
            {
                for (int j = 0; j < n1Data; ++j)
                {
                    double expVal = yValues[i][j];
                    double @ref   = Math.Abs(expVal) == 0.0 ? 1.0 : Math.Abs(expVal);
                    assertEquals(resValues.get(i, j), expVal, @ref * EPS);
                }
            }
        }
        /// <summary>
        /// f(x0,x1) = ( x0 - 1.)^3 * (x1  + 14./13.)^3
        /// </summary>
        public virtual void cubicTest()
        {
            double[] x0Values = new double[] { 1.0, 2.0, 3.0, 4.0 };
            double[] x1Values = new double[] { -1.0, 0.0, 1.0, 2.0, 3.0 };
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final int n0Data = x0Values.length;
            int n0Data = x0Values.Length;
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final int n1Data = x1Values.length;
            int n1Data = x1Values.Length;

//JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java:
//ORIGINAL LINE: double[][] yValues = new double[n0Data][n1Data];
            double[][] yValues = RectangularArrays.ReturnRectangularDoubleArray(n0Data, n1Data);

            for (int i = 0; i < n0Data; ++i)
            {
                for (int j = 0; j < n1Data; ++j)
                {
                    yValues[i][j] = (x0Values[i] - 1.0) * (x0Values[i] - 1.0) * (x0Values[i] - 1.0) * (x1Values[j] + 14.0 / 13.0) * (x1Values[j] + 14.0 / 13.0) * (x1Values[j] + 14.0 / 13.0);
                }
            }

            CubicSplineInterpolator           method = new CubicSplineInterpolator();
            PiecewisePolynomialInterpolator2D interp = new BicubicSplineInterpolator(method);
            PiecewisePolynomialResult2D       result = interp.interpolate(x0Values, x1Values, yValues);

//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final int n0IntExp = n0Data - 1;
            int n0IntExp = n0Data - 1;
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final int n1IntExp = n1Data - 1;
            int       n1IntExp = n1Data - 1;
            const int orderExp = 4;

            const int n0Keys = 51;
            const int n1Keys = 61;

            double[] x0Keys = new double[n0Keys];
            double[] x1Keys = new double[n1Keys];
            for (int i = 0; i < n0Keys; ++i)
            {
                x0Keys[i] = 0.0 + 5.0 * i / (n0Keys - 1);
            }
            for (int i = 0; i < n1Keys; ++i)
            {
                x1Keys[i] = -2.0 + 6.0 * i / (n1Keys - 1);
            }

            assertEquals(result.NumberOfIntervals[0], n0IntExp);
            assertEquals(result.NumberOfIntervals[1], n1IntExp);
            assertEquals(result.Order[0], orderExp);
            assertEquals(result.Order[1], orderExp);

            for (int i = 0; i < n0Data; ++i)
            {
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final double ref = Math.abs(x0Values[i]) == 0.0 ? 1.0 : Math.abs(x0Values[i]);
                double @ref = Math.Abs(x0Values[i]) == 0.0 ? 1.0 : Math.Abs(x0Values[i]);
                assertEquals(result.Knots0.get(i), x0Values[i], @ref * EPS);
                assertEquals(result.Knots2D[0].get(i), x0Values[i], @ref * EPS);
            }
            for (int i = 0; i < n1Data; ++i)
            {
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final double ref = Math.abs(x1Values[i]) == 0.0 ? 1.0 : Math.abs(x1Values[i]);
                double @ref = Math.Abs(x1Values[i]) == 0.0 ? 1.0 : Math.Abs(x1Values[i]);
                assertEquals(result.Knots1.get(i), x1Values[i], @ref * EPS);
                assertEquals(result.Knots2D[1].get(i), x1Values[i], @ref * EPS);
            }

            for (int i = 0; i < n0Data - 1; ++i)
            {
                for (int j = 0; j < n1Data - 1; ++j)
                {
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final double ref = Math.abs(yValues[i][j]) == 0.0 ? 1.0 : Math.abs(yValues[i][j]);
                    double @ref = Math.Abs(yValues[i][j]) == 0.0 ? 1.0 : Math.Abs(yValues[i][j]);
                    assertEquals(result.Coefs[i][j].get(orderExp - 1, orderExp - 1), yValues[i][j], @ref * EPS);
                }
            }

            DoubleMatrix resValues = interp.interpolate(x0Values, x1Values, yValues, x0Values, x1Values);
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final com.opengamma.strata.math.impl.function.PiecewisePolynomialFunction2D func2D = new com.opengamma.strata.math.impl.function.PiecewisePolynomialFunction2D();
            PiecewisePolynomialFunction2D func2D = new PiecewisePolynomialFunction2D();
            DoubleMatrix resDiffX0 = func2D.differentiateX0(result, x0Values, x1Values);
            DoubleMatrix resDiffX1 = func2D.differentiateX1(result, x0Values, x1Values);

//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final com.opengamma.strata.math.impl.function.PiecewisePolynomialFunction1D func1D = new com.opengamma.strata.math.impl.function.PiecewisePolynomialFunction1D();
            PiecewisePolynomialFunction1D func1D = new PiecewisePolynomialFunction1D();
            DoubleMatrix expDiffX0 = func1D.differentiate(method.interpolate(x0Values, OG_ALGEBRA.getTranspose(DoubleMatrix.copyOf(yValues)).toArray()), x0Values);
            DoubleMatrix expDiffX1 = func1D.differentiate(method.interpolate(x1Values, yValues), x1Values);

            for (int i = 0; i < n0Data; ++i)
            {
                for (int j = 0; j < n1Data; ++j)
                {
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final double expVal = expDiffX1.get(i, j);
                    double expVal = expDiffX1.get(i, j);
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final double ref = Math.abs(expVal) == 0.0 ? 1.0 : Math.abs(expVal);
                    double @ref = Math.Abs(expVal) == 0.0 ? 1.0 : Math.Abs(expVal);
                    assertEquals(resDiffX1.get(i, j), expVal, @ref * EPS);
                }
            }

            for (int i = 0; i < n0Data; ++i)
            {
                for (int j = 0; j < n1Data; ++j)
                {
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final double expVal = expDiffX0.get(j, i);
                    double expVal = expDiffX0.get(j, i);
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final double ref = Math.abs(expVal) == 0.0 ? 1.0 : Math.abs(expVal);
                    double @ref = Math.Abs(expVal) == 0.0 ? 1.0 : Math.Abs(expVal);
                    assertEquals(resDiffX0.get(i, j), expVal, @ref * EPS);
                }
            }

            for (int i = 0; i < n0Data; ++i)
            {
                for (int j = 0; j < n1Data; ++j)
                {
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final double expVal = yValues[i][j];
                    double expVal = yValues[i][j];
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final double ref = Math.abs(expVal) == 0.0 ? 1.0 : Math.abs(expVal);
                    double @ref = Math.Abs(expVal) == 0.0 ? 1.0 : Math.Abs(expVal);
                    assertEquals(resValues.get(i, j), expVal, @ref * EPS);
                }
            }
        }