/** * 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 com.opengamma.strata.collect.TestHelper.assertThrowsIllegalArg; import static org.testng.Assert.assertEquals; import org.testng.annotations.Test; import com.google.common.base.Function; import com.opengamma.strata.math.impl.function.PiecewisePolynomialFunction1D; /** * Test {@link ClampedPiecewisePolynomialInterpolator}. */ @Test 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; 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); assertEquals(computed, expected); assertEquals(interp.getPrimaryMethod(), baseInterp); } } 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); assertEquals(computed, expected); } } @Test(expectedExceptions = UnsupportedOperationException.class) public void testInterpolateMultiDim() { ClampedPiecewisePolynomialInterpolator interp = new ClampedPiecewisePolynomialInterpolator( new NaturalSplineInterpolator(), new double[] {1d }, new double[] {2d }); interp.interpolate(X_VALUES, new double[][] {Y_VALUES, Y_VALUES }); } public void testWrongClampedPoints() { assertThrowsIllegalArg(() -> new ClampedPiecewisePolynomialInterpolator( new NaturalSplineInterpolator(), new double[] {0d }, new double[] {0d, 1d })); assertThrowsIllegalArg(() -> new ClampedPiecewisePolynomialInterpolator( new CubicSplineInterpolator(), new double[] {}, new double[] {})); } 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); assertEquals(exp, polyFunc.evaluate(result, tm).get(0), Math.abs(exp) * TOL); } } }