/*
 * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.strata.math.impl.interpolation;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.data.Offset.offset;

import org.junit.jupiter.api.Test;

import com.google.common.base.Function;
import com.opengamma.strata.math.impl.function.PiecewisePolynomialFunction1D;

/**
 * Test {@link ClampedPiecewisePolynomialInterpolator}.
 */
public class ClampedPiecewisePolynomialInterpolatorTest {
  private static final double[] X_VALUES = new double[] {-1.0, -0.04, 0.1, 3.2, 15.0};
  private static final double[] Y_VALUES = new double[] {12.4, -2.03, 11.41, 11.0, 0.2};
  private static final double[] X_CLAMPED = new double[] {-1.5, 3.4, 22.0, 0.0};
  private static final double[] Y_CLAMPED = new double[] {6.0, 2.2, 6.1, 3.2};
  private static final double[] X_VALUES_TOTAL = new double[] {-1.5, -1.0, -0.04, 0.0, 0.1, 3.2, 3.4, 15.0, 22.0};
  private static final double[] Y_VALUES_TOTAL = new double[] {6.0, 12.4, -2.03, 3.2, 11.41, 11.0, 2.2, 0.2, 6.1};
  private static final PiecewisePolynomialInterpolator[] BASE_INTERP = new PiecewisePolynomialInterpolator[] {
      new NaturalSplineInterpolator(), new PiecewiseCubicHermiteSplineInterpolatorWithSensitivity(),
      new MonotonicityPreservingCubicSplineInterpolator(new CubicSplineInterpolator())};
  private static final double TOL = 1.0e-14;

  @Test
  public void testInterpolate() {
    for (PiecewisePolynomialInterpolator baseInterp : BASE_INTERP) {
      ClampedPiecewisePolynomialInterpolator interp =
          new ClampedPiecewisePolynomialInterpolator(baseInterp, X_CLAMPED, Y_CLAMPED);
      PiecewisePolynomialResult computed = interp.interpolate(X_VALUES, Y_VALUES);
      PiecewisePolynomialResult expected = baseInterp.interpolate(X_VALUES_TOTAL, Y_VALUES_TOTAL);
      assertThat(computed).isEqualTo(expected);
      assertThat(interp.getPrimaryMethod()).isEqualTo(baseInterp);
    }
  }

  @Test
  public void testInterpolateWithSensitivity() {
    for (PiecewisePolynomialInterpolator baseInterp : BASE_INTERP) {
      ClampedPiecewisePolynomialInterpolator interp =
          new ClampedPiecewisePolynomialInterpolator(baseInterp, X_CLAMPED, Y_CLAMPED);
      PiecewisePolynomialResultsWithSensitivity computed = interp.interpolateWithSensitivity(X_VALUES, Y_VALUES);
      PiecewisePolynomialResultsWithSensitivity expected =
          baseInterp.interpolateWithSensitivity(X_VALUES_TOTAL, Y_VALUES_TOTAL);
      assertThat(computed).isEqualTo(expected);
    }
  }

  @Test
  public void testInterpolateMultiDim() {
    ClampedPiecewisePolynomialInterpolator interp = new ClampedPiecewisePolynomialInterpolator(
        new NaturalSplineInterpolator(), new double[] {1d}, new double[] {2d});
    assertThatExceptionOfType(UnsupportedOperationException.class)
        .isThrownBy(() -> interp.interpolate(X_VALUES, new double[][] {Y_VALUES, Y_VALUES}));
  }

  @Test
  public void testWrongClampedPoints() {
    assertThatIllegalArgumentException()
        .isThrownBy(() -> new ClampedPiecewisePolynomialInterpolator(
            new NaturalSplineInterpolator(), new double[] {0d}, new double[] {0d, 1d}));
    assertThatIllegalArgumentException()
        .isThrownBy(() -> new ClampedPiecewisePolynomialInterpolator(
            new CubicSplineInterpolator(), new double[] {}, new double[] {}));
  }

  @Test
  public void testFunctionalForm() {
    double[] xValues = new double[] {0.5, 1.0, 3.0, 5.0, 10.0, 30.0};
    double lambda0 = 0.14;
    double[] lambda = new double[] {0.25, 0.05, -0.12, 0.03, -0.15, 0.0};
    double pValueTmp = 0d;
    int nData = xValues.length;
    for (int i = 0; i < nData - 1; ++i) {
      lambda[nData - 1] += lambda[i] * xValues[i];
      pValueTmp += lambda[i];
    }
    lambda[nData - 1] *= -1d / xValues[nData - 1];
    pValueTmp += lambda[nData - 1];
    final double pValue = pValueTmp;
    Function<Double, Double> func = new Function<Double, Double>() {
      @Override
      public Double apply(Double t) {
        int index = 0;
        double res = lambda0 * t - pValue * Math.pow(t, 3) / 6.0;
        while (index < nData && t > xValues[index]) {
          res += lambda[index] * Math.pow(t - xValues[index], 3) / 6.0;
          ++index;
        }
        return res;
      }
    };
    double[] rt = new double[nData];
    for (int i = 0; i < nData; ++i) {
      rt[i] = func.apply(xValues[i]);
    }
    ClampedPiecewisePolynomialInterpolator interp =
        new ClampedPiecewisePolynomialInterpolator(BASE_INTERP[0], new double[] {0d}, new double[] {0d});
    PiecewisePolynomialResult result = interp.interpolate(xValues, rt);
    PiecewisePolynomialFunction1D polyFunc = new PiecewisePolynomialFunction1D();
    for (int i = 0; i < 600; ++i) {
      double tm = 0.05 * i;
      double exp = func.apply(tm);
      assertThat(exp).isCloseTo(polyFunc.evaluate(result, tm).get(0), offset(Math.abs(exp) * TOL));
    }
  }

}

@@ -461,76 +461,73 @@
 ort 
-org.junit.jupiter.api.Test;%0A%0Aimport com.google.common.base.Function;
+java.util.function.Function;%0A%0Aimport org.junit.jupiter.api.Test;%0A
 %0Aimp

Replace accidental use of Guava's Function interface in test case. (#2231)