BilinearSplineInterpolator extends PiecewisePolynomialInterpolator2D { @Override public PiecewisePolynomialResult2D interpolate(final double[] x0Values, final double[] x1Values, final double[][] yValues) { ArgumentChecker.notNull(x0Values, "x0Values"); ArgumentChecker.notNull(x1Values, "x1Values"); ArgumentChecker.notNull(yValues, "yValues"); final int nData0 = x0Values.length; final int nData1 = x1Values.length; ArgumentChecker.isTrue(nData0 == yValues.length, "x0Values length = yValues number of rows"); ArgumentChecker.isTrue(nData1 == yValues[0].length, "x1Values length = yValues number of columns"); ArgumentChecker.isTrue(nData0 > 1, "Data points along x0 direction should be more than 1"); ArgumentChecker.isTrue(nData1 > 1, "Data points along x1 direction should be more than 1"); for (int i = 0; i < nData0; ++i) { ArgumentChecker.isFalse(Double.isNaN(x0Values[i]), "x0Values containing NaN"); ArgumentChecker.isFalse(Double.isInfinite(x0Values[i]), "x0Values containing Infinity"); } for (int i = 0; i < nData1; ++i) { ArgumentChecker.isFalse(Double.isNaN(x1Values[i]), "x1Values containing NaN"); ArgumentChecker.isFalse(Double.isInfinite(x1Values[i]), "x1Values containing Infinity"); } for (int i = 0; i < nData0; ++i) { for (int j = 0; j < nData1; ++j) { ArgumentChecker.isFalse(Double.isNaN(yValues[i][j]), "yValues containing NaN"); ArgumentChecker.isFalse(Double.isInfinite(yValues[i][j]), "yValues containing Infinity"); } } for (int i = 0; i < nData0; ++i) { for (int j = i + 1; j < nData0; ++j) { ArgumentChecker.isFalse(x0Values[i] == x0Values[j], "x0Values should be distinct"); } } for (int i = 0; i < nData1; ++i) { for (int j = i + 1; j < nData1; ++j) { ArgumentChecker.isFalse(x1Values[i] == x1Values[j], "x1Values should be distinct"); } } final int order = 2; DoubleMatrix2D[][] coefMat = new DoubleMatrix2D[nData0 - 1][nData1 - 1]; for (int i = 0; i < nData0 - 1; ++i) { for (int j = 0; j < nData1 - 1; ++j) { final double interval0 = x0Values[i + 1] - x0Values[i]; final double interval1 = x1Values[j + 1] - x1Values[j]; double ref = 0.; double[][] coefMatTmp = new double[order][order]; coefMatTmp[1][1] = yValues[i][j]; coefMatTmp[0][1] = (-yValues[i][j] + yValues[i + 1][j]) / interval0; coefMatTmp[1][0] = (-yValues[i][j] + yValues[i][j + 1]) / interval1; coefMatTmp[0][0] = (yValues[i][j] - yValues[i + 1][j] - yValues[i][j + 1] + yValues[i + 1][j + 1]) / interval0 / interval1; for (int k = 0; k < order; ++k) { for (int l = 0; l < order; ++l) { ArgumentChecker.isFalse(Double.isNaN(coefMatTmp[k][l]), "Too large/small input"); ArgumentChecker.isFalse(Double.isInfinite(coefMatTmp[k][l]), "Too large/small input"); ref += coefMatTmp[k][l] * Math.pow(interval0, 1 - k) * Math.pow(interval1, 1 - l); } } final double bound = Math.max(Math.abs(ref) + Math.abs(yValues[i + 1][j + 1]), 0.1); ArgumentChecker.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] = new DoubleMatrix2D(coefMatTmp); coefMat[i][j] = new DoubleMatrix2D(coefMatTmp); } } return new PiecewisePolynomialResult2D(new DoubleMatrix1D(x0Values), new DoubleMatrix1D(x1Values), coefMat, new int[] {order, order }); }  @Override PiecewisePolynomialResult2D interpolate(final double[] x0Values, final double[] x1Values, final double[][] yValues);  }
@Test public void constFunctionTest() { double[] x0Values = new double[] {0., 1., 2., 3. }; double[] x1Values = new double[] {0., 1., 2. }; final int n0Data = x0Values.length; final int n1Data = x1Values.length; double[][] yValues = new double[n0Data][n1Data]; for (int i = 0; i < n0Data; ++i) { for (int j = 0; j < n1Data; ++j) { yValues[i][j] = 3.; } } DoubleMatrix2D[][] coefsExp = new DoubleMatrix2D[n0Data - 1][n1Data - 1]; for (int i = 0; i < n0Data - 1; ++i) { for (int j = 0; j < n1Data - 1; ++j) { coefsExp[i][j] = new DoubleMatrix2D(new double[][] { {0., 0. }, {0., 3. } }); } } final int orderExp = 2; final int n0KnotsExp = x0Values.length; final int n1KnotsExp = x1Values.length; BilinearSplineInterpolator interp = new BilinearSplineInterpolator(); final int n0Keys = 51; final int n1Keys = 41; double[] x0Keys = new double[n0Keys]; double[] x1Keys = new double[n1Keys]; for (int i = 0; i < n0Keys; ++i) { x0Keys[i] = -1. + 5. * i / (n0Keys - 1); } for (int i = 0; i < n1Keys; ++i) { x1Keys[i] = -1. + 4. * i / (n1Keys - 1); } PiecewisePolynomialResult2D result = interp.interpolate(x0Values, x1Values, yValues); assertEquals(result.getNumberOfIntervals()[0], n0KnotsExp - 1); assertEquals(result.getNumberOfIntervals()[1], n1KnotsExp - 1); assertEquals(result.getOrder()[0], orderExp); assertEquals(result.getOrder()[1], orderExp); for (int i = 0; i < n0Data; ++i) { final double ref = Math.abs(x0Values[i]) == 0. ? 1. : Math.abs(x0Values[i]); assertEquals(result.getKnots0().getData()[i], x0Values[i], ref * EPS); } for (int i = 0; i < n1Data; ++i) { final double ref = Math.abs(x1Values[i]) == 0. ? 1. : Math.abs(x1Values[i]); assertEquals(result.getKnots1().getData()[i], x1Values[i], ref * EPS); } for (int i = 0; i < n0Data - 1; ++i) { for (int j = 0; j < n1Data - 1; ++j) { for (int k = 0; k < orderExp; ++k) { for (int l = 0; l < orderExp; ++l) { final double ref = Math.abs(coefsExp[i][j].getData()[k][l]) == 0. ? 1. : Math.abs(coefsExp[i][j].getData()[k][l]); assertEquals(result.getCoefs()[i][j].getData()[k][l], coefsExp[i][j].getData()[k][l], ref * EPS); } } } } double[][] resValues = interp.interpolate(x0Values, x1Values, yValues, x0Keys, x1Keys).getData(); for (int i = 0; i < n0Keys; ++i) { for (int j = 0; j < n1Keys; ++j) { final double ref = 3.; assertEquals(resValues[i][j], ref, ref * EPS); } } { final double ref = 3.; assertEquals(interp.interpolate(x0Values, x1Values, yValues, x0Keys[2], x1Keys[1]), ref, ref * EPS); } }
@Test public void bilinearFunctionTest() { double[] x0Values = new double[] {0., 1., 2., 3. }; double[] x1Values = new double[] {0., 1., 2. }; final int n0Data = x0Values.length; final int n1Data = x1Values.length; double[][] yValues = new double[n0Data][n1Data]; for (int i = 0; i < n0Data; ++i) { for (int j = 0; j < n1Data; ++j) { yValues[i][j] = (x0Values[i] - 1.5) * (x1Values[j] - 0.5); } } DoubleMatrix2D[][] coefsExp = new DoubleMatrix2D[n0Data - 1][n1Data - 1]; for (int i = 0; i < n0Data - 1; ++i) { for (int j = 0; j < n1Data - 1; ++j) { coefsExp[i][j] = new DoubleMatrix2D(new double[][] { {1., (-0.5 + x1Values[j]) }, {(-1.5 + x0Values[i]), (-1.5 + x0Values[i]) * (-0.5 + x1Values[j]) } }); } } final int orderExp = 2; final int n0KnotsExp = x0Values.length; final int n1KnotsExp = x1Values.length; BilinearSplineInterpolator interp = new BilinearSplineInterpolator(); final int n0Keys = 51; final int n1Keys = 41; double[] x0Keys = new double[n0Keys]; double[] x1Keys = new double[n1Keys]; for (int i = 0; i < n0Keys; ++i) { x0Keys[i] = -1. + 5. * i / (n0Keys - 1); } for (int i = 0; i < n1Keys; ++i) { x1Keys[i] = -1. + 4. * i / (n1Keys - 1); } PiecewisePolynomialResult2D result = interp.interpolate(x0Values, x1Values, yValues); assertEquals(result.getNumberOfIntervals()[0], n0KnotsExp - 1); assertEquals(result.getNumberOfIntervals()[1], n1KnotsExp - 1); assertEquals(result.getOrder()[0], orderExp); assertEquals(result.getOrder()[1], orderExp); for (int i = 0; i < n0Data; ++i) { final double ref = Math.abs(x0Values[i]) == 0. ? 1. : Math.abs(x0Values[i]); assertEquals(result.getKnots0().getData()[i], x0Values[i], ref * EPS); assertEquals(result.getKnots2D().get(0).getData()[i], x0Values[i], ref * EPS); } for (int i = 0; i < n1Data; ++i) { final double ref = Math.abs(x1Values[i]) == 0. ? 1. : Math.abs(x1Values[i]); assertEquals(result.getKnots1().getData()[i], x1Values[i], ref * EPS); assertEquals(result.getKnots2D().get(1).getData()[i], x1Values[i], ref * EPS); } for (int i = 0; i < n0Data - 1; ++i) { for (int j = 0; j < n1Data - 1; ++j) { for (int k = 0; k < orderExp; ++k) { for (int l = 0; l < orderExp; ++l) { final double ref = Math.abs(coefsExp[i][j].getData()[k][l]) == 0. ? 1. : Math.abs(coefsExp[i][j].getData()[k][l]); assertEquals(result.getCoefs()[i][j].getData()[k][l], coefsExp[i][j].getData()[k][l], ref * EPS); } } } } double[][] resValues = interp.interpolate(x0Values, x1Values, yValues, x0Keys, x1Keys).getData(); for (int i = 0; i < n0Keys; ++i) { for (int j = 0; j < n1Keys; ++j) { final double expVal = (x0Keys[i] - 1.5) * (x1Keys[j] - 0.5); final double ref = Math.abs(expVal) == 0. ? 1. : Math.abs(expVal); assertEquals(resValues[i][j], expVal, ref * EPS); } } for (int i = 0; i < n0Keys; ++i) { for (int j = 0; j < n1Keys; ++j) { final double expVal = (x0Keys[i] - 1.5) * (x1Keys[j] - 0.5); final double ref = Math.abs(expVal) == 0. ? 1. : Math.abs(expVal); assertEquals(resValues[i][j], expVal, ref * EPS); } } { final double expVal = (x0Keys[1] - 1.5) * (x1Keys[2] - 0.5); final double ref = Math.abs(expVal) == 0. ? 1. : Math.abs(expVal); assertEquals(interp.interpolate(x0Values, x1Values, yValues, x0Keys[1], x1Keys[2]), expVal, ref * EPS); } { final double expVal = (x0Keys[23] - 1.5) * (x1Keys[20] - 0.5); final double ref = Math.abs(expVal) == 0. ? 1. : Math.abs(expVal); assertEquals(interp.interpolate(x0Values, x1Values, yValues, x0Keys[23], x1Keys[20]), expVal, ref * EPS); } }
@Test(expectedExceptions = IllegalArgumentException.class) public void nullx0Test() { double[] x0Values = new double[] {0., 1., 2., 3. }; double[] x1Values = new double[] {0., 1., 2. }; double[][] yValues = new double[][] { {1., 2., 4. }, {-1., 2., -4. }, {2., 3., 4. }, {5., 2., 1. } }; x0Values = null; BilinearSplineInterpolator interp = new BilinearSplineInterpolator(); interp.interpolate(x0Values, x1Values, yValues); }
@Test(expectedExceptions = IllegalArgumentException.class) public void nullx1Test() { double[] x0Values = new double[] {0., 1., 2., 3. }; double[] x1Values = new double[] {0., 1., 2. }; double[][] yValues = new double[][] { {1., 2., 4. }, {-1., 2., -4. }, {2., 3., 4. }, {5., 2., 1. } }; x1Values = null; BilinearSplineInterpolator interp = new BilinearSplineInterpolator(); interp.interpolate(x0Values, x1Values, yValues); }
@Test(expectedExceptions = IllegalArgumentException.class) public void nullyTest() { double[] x0Values = new double[] {0., 1., 2., 3. }; double[] x1Values = new double[] {0., 1., 2. }; double[][] yValues = new double[][] { {1., 2., 4. }, {-1., 2., -4. }, {2., 3., 4. }, {5., 2., 1. } }; yValues = null; BilinearSplineInterpolator interp = new BilinearSplineInterpolator(); interp.interpolate(x0Values, x1Values, yValues); }
@Test(expectedExceptions = IllegalArgumentException.class) public void wrongLengthx0Test() { double[] x0Values = new double[] {0., 1., 2. }; double[] x1Values = new double[] {0., 1., 2. }; double[][] yValues = new double[][] { {1., 2., 4. }, {-1., 2., -4. }, {2., 3., 4. }, {5., 2., 1. } }; BilinearSplineInterpolator interp = new BilinearSplineInterpolator(); interp.interpolate(x0Values, x1Values, yValues); }
@Test(expectedExceptions = IllegalArgumentException.class) public void wrongLengthx1Test() { double[] x0Values = new double[] {0., 1., 2., 3. }; double[] x1Values = new double[] {0., 1., 2., 3. }; double[][] yValues = new double[][] { {1., 2., 4. }, {-1., 2., -4. }, {2., 3., 4. }, {5., 2., 1. } }; BilinearSplineInterpolator interp = new BilinearSplineInterpolator(); interp.interpolate(x0Values, x1Values, yValues); }
@Test(expectedExceptions = IllegalArgumentException.class) public void shortx0Test() { double[] x0Values = new double[] {1. }; double[] x1Values = new double[] {0., 1., 2. }; double[][] yValues = new double[][] {{1., 2., 4. } }; BilinearSplineInterpolator interp = new BilinearSplineInterpolator(); interp.interpolate(x0Values, x1Values, yValues); }
@Test(expectedExceptions = IllegalArgumentException.class) public void shortx1Test() { double[] x0Values = new double[] {0., 1., 2., 3. }; double[] x1Values = new double[] {0. }; double[][] yValues = new double[][] { {1. }, {-1. }, {2. }, {5. } }; BilinearSplineInterpolator interp = new BilinearSplineInterpolator(); interp.interpolate(x0Values, x1Values, yValues); }
@Test(expectedExceptions = IllegalArgumentException.class) public void infX0Test() { double[] x0Values = new double[] {0., 1., 2., INF }; double[] x1Values = new double[] {0., 1., 2. }; double[][] yValues = new double[][] { {1., 2., 4. }, {-1., 2., -4. }, {2., 3., 4. }, {5., 2., 1. } }; BilinearSplineInterpolator interp = new BilinearSplineInterpolator(); interp.interpolate(x0Values, x1Values, yValues); }
@Test(expectedExceptions = IllegalArgumentException.class) public void nanX0Test() { double[] x0Values = new double[] {0., 1., 2., Double.NaN }; double[] x1Values = new double[] {0., 1., 2. }; double[][] yValues = new double[][] { {1., 2., 4. }, {-1., 2., -4. }, {2., 3., 4. }, {5., 2., 1. } }; BilinearSplineInterpolator interp = new BilinearSplineInterpolator(); interp.interpolate(x0Values, x1Values, yValues); }
@Test(expectedExceptions = IllegalArgumentException.class) public void infX1Test() { double[] x0Values = new double[] {0., 1., 2., 3. }; double[] x1Values = new double[] {0., 1., INF }; double[][] yValues = new double[][] { {1., 2., 4. }, {-1., 2., -4. }, {2., 3., 4. }, {5., 2., 1. } }; BilinearSplineInterpolator interp = new BilinearSplineInterpolator(); interp.interpolate(x0Values, x1Values, yValues); }
@Test(expectedExceptions = IllegalArgumentException.class) public void nanX1Test() { double[] x0Values = new double[] {0., 1., 2., 3. }; double[] x1Values = new double[] {0., 1., Double.NaN }; double[][] yValues = new double[][] { {1., 2., 4. }, {-1., 2., -4. }, {2., 3., 4. }, {5., 2., 1. } }; BilinearSplineInterpolator interp = new BilinearSplineInterpolator(); interp.interpolate(x0Values, x1Values, yValues); }
@Test(expectedExceptions = IllegalArgumentException.class) public void infYTest() { double[] x0Values = new double[] {0., 1., 2., 3. }; double[] x1Values = new double[] {0., 1., 2. }; double[][] yValues = new double[][] { {1., 2., 4. }, {-1., 2., INF }, {2., 3., 4. }, {5., 2., 1. } }; BilinearSplineInterpolator interp = new BilinearSplineInterpolator(); interp.interpolate(x0Values, x1Values, yValues); }
@Test(expectedExceptions = IllegalArgumentException.class) public void nanYTest() { double[] x0Values = new double[] {0., 1., 2., 3. }; double[] x1Values = new double[] {0., 1., 2. }; double[][] yValues = new double[][] { {1., 2., 4. }, {-1., 2., -4. }, {2., 3., 4. }, {5., 2., Double.NaN } }; BilinearSplineInterpolator interp = new BilinearSplineInterpolator(); interp.interpolate(x0Values, x1Values, yValues); }
@Test(expectedExceptions = IllegalArgumentException.class) public void coincideX0Test() { double[] x0Values = new double[] {0., 1., 1., 3. }; double[] x1Values = new double[] {0., 1., 2. }; double[][] yValues = new double[][] { {1., 2., 4. }, {-1., 2., -4. }, {2., 3., 4. }, {5., 2., 1. } }; BilinearSplineInterpolator interp = new BilinearSplineInterpolator(); interp.interpolate(x0Values, x1Values, yValues); }
@Test(expectedExceptions = IllegalArgumentException.class) public void coincideX1Test() { double[] x0Values = new double[] {0., 1., 2., 3. }; double[] x1Values = new double[] {0., 1., 1. }; double[][] yValues = new double[][] { {1., 2., 4. }, {-1., 2., -4. }, {2., 3., 4. }, {5., 2., 1. } }; BilinearSplineInterpolator interp = new BilinearSplineInterpolator(); interp.interpolate(x0Values, x1Values, yValues); }
@Test(expectedExceptions = IllegalArgumentException.class) public void notKnotRevoveredTests() { double[] x0Values = new double[] {0., 1., 1.0000001, 3. }; double[] x1Values = new double[] {1., 1.0000000001, 3. }; double[][] yValues = new double[][] { {1., 3., 5. }, {2., 3.e13, 4. }, {1., 1.e-2, 1. }, {4., 3., 2. } }; BilinearSplineInterpolator intp = new BilinearSplineInterpolator(); intp.interpolate(x0Values, x1Values, yValues); }