@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.}};

    BicubicSplineInterpolator interp = new BicubicSplineInterpolator(new CubicSplineInterpolator());
    interp.interpolate(x0Values, x1Values, yValues);
  }
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void notTwoMethodsTest() {
    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.}};

    BicubicSplineInterpolator interp =
        new BicubicSplineInterpolator(
            new PiecewisePolynomialInterpolator[] {new CubicSplineInterpolator()});
    interp.interpolate(x0Values, x1Values, yValues);
  }
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void notKnotRevoveredTests() {
    double[] x0Values = new double[] {0., 1., 2., 3.};
    double[] x1Values = new double[] {0., 1., 2.};
    double[][] yValues =
        new double[][] {
          {1.e-20, 3.e-120, 5.e-20},
          {2.e-20, 3.e-120, 4.e-120},
          {1.e-20, 1.e-120, 1.e-20},
          {4.e-120, 3.e-20, 2.e-20}
        };

    BicubicSplineInterpolator intp = new BicubicSplineInterpolator(new CubicSplineInterpolator());
    intp.interpolate(x0Values, x1Values, yValues);
  }
  /** Tests below for debugging */
  @Test(enabled = false)
  public void printTest() {
    //    double[] x0Values = new double[] {0., 1., 2., 3. };
    //    double[] x1Values = new double[] {0., 0.000000000001, 2. };
    double[] x0Values = new double[] {0., 1., 2., 3.};
    double[] x1Values = new double[] {0., 1., 2.};
    double[][] yValues =
        new double[][] {
          {1.e-20, 3.e-120, 5.e-20},
          {2.e-20, 3.e-120, 4.e-120},
          {1.e-20, 1.e-120, 1.e-20},
          {4.e-120, 3.e-20, 2.e-20}
        };

    //    double[] x0Values = new double[] {0., 1., 2. };
    //    double[] x1Values = new double[] {0., 1., 2., 3. };
    //    double[][] yValues = new double[][] { {1., 3., 5., 7. }, {2., 3., 4., 5. }, {1., 1., 1.,
    // 1. } };

    BicubicSplineInterpolator intp = new BicubicSplineInterpolator(new CubicSplineInterpolator());
    PiecewisePolynomialResult2D result2D = intp.interpolate(x0Values, x1Values, yValues);
    System.out.println(result2D.getCoefs()[0][0]);
    System.out.println(result2D.getCoefs()[2][1]);

    final int n0Keys = 31;
    final int n1Keys = 21;
    double[] x0Keys = new double[n0Keys];
    double[] x1Keys = new double[n1Keys];
    for (int i = 0; i < n0Keys; ++i) {
      x0Keys[i] = 0. + 3. * i / (n0Keys - 1);
    }
    for (int i = 0; i < n1Keys; ++i) {
      x1Keys[i] = 0. + 2. * i / (n1Keys - 1);
    }

    //    final int n0Keys = 61;
    //    final int n1Keys = 101;
    //    double[] x0Keys = new double[n0Keys];
    //    double[] x1Keys = new double[n1Keys];
    //    for (int i = 0; i < n0Keys; ++i) {
    //      x0Keys[i] = -1. + 4. * i / (n0Keys - 1);
    //    }
    //    for (int i = 0; i < n1Keys; ++i) {
    //      x1Keys[i] = -1. + 5. * i / (n1Keys - 1);
    //    }

    PiecewisePolynomialFunction2D func = new PiecewisePolynomialFunction2D();
    final double[][] values = func.evaluate(result2D, x0Keys, x1Keys).getData();

    for (int i = 0; i < n0Keys; ++i) {
      System.out.print("\t" + x0Keys[i]);
    }
    System.out.print("\n");
    for (int j = 0; j < n1Keys; ++j) {
      System.out.print(x1Keys[j]);
      for (int i = 0; i < n0Keys; ++i) {
        System.out.print("\t" + values[i][j]);
      }
      System.out.print("\n");
    }

    System.out.print("\n");

    for (int i = 0; i < x0Values.length; ++i) {
      System.out.print("\t" + x0Values[i]);
    }
    System.out.print("\n");
    for (int j = 0; j < x1Values.length; ++j) {
      System.out.print(x1Values[j]);
      for (int i = 0; i < x0Values.length; ++i) {
        System.out.print("\t" + yValues[i][j]);
      }
      System.out.print("\n");
    }
    System.out.print("\n");
  }