/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.math.interpolation;
import static org.testng.AssertJUnit.assertEquals;
import org.apache.commons.lang.NotImplementedException;
import org.testng.annotations.Test;
import com.opengamma.analytics.math.interpolation.data.Interpolator1DDataBundle;
import com.opengamma.util.test.TestGroup;
/**
* Tests related to the "time/square of value" interpolator.
*/
@Test(groups = TestGroup.UNIT)
public class TimeSquareInterpolator1DTest {
private static final Interpolator1D INTERPOLATOR = new TimeSquareInterpolator1D();
private static final double[] X = new double[] {1, 2, 3};
private static final double[] Y = new double[] {4, 5, 6};
private static final Interpolator1DDataBundle DATA = INTERPOLATOR.getDataBundle(X, Y);
private static final double TOLERANCE_Y = 1.0E-10;
private static final double TOLERANCE_SENSI = 1.0E-6;
@Test(expectedExceptions = IllegalArgumentException.class)
public void nullDataBundle() {
INTERPOLATOR.interpolate(null, 2.3);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void nullValue() {
INTERPOLATOR.interpolate(DATA, null);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void lowValue() {
INTERPOLATOR.interpolate(DATA, -4.);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void highValue() {
INTERPOLATOR.interpolate(DATA, 10.0);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void lowValueFirstDerivative() {
INTERPOLATOR.firstDerivative(DATA, -4.);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void lowValueSensitivity() {
INTERPOLATOR.getNodeSensitivitiesForValue(DATA, -4.);
}
@Test
/**
* Tests the sensitivity of the interpolated value to the Y values.
*/
public void interpolation() {
final Interpolator1D interpolatorFromFactory = Interpolator1DFactory.TIME_SQUARE_INSTANCE;
double[] x = new double[] {1.0, 1.5, 2, 2.75};
for (int loopx = 0; loopx < x.length; loopx++) {
double yCalculated = INTERPOLATOR.interpolate(DATA, x[loopx]);
double yCalculatedFactory = interpolatorFromFactory.interpolate(DATA, x[loopx]);
final int index = DATA.getLowerBoundIndex(x[loopx]);
final double weight = (DATA.getKeys()[index + 1] - x[loopx]) / (DATA.getKeys()[index + 1] - DATA.getKeys()[index]);
final double val1 = DATA.getKeys()[index] * DATA.getValues()[index] * DATA.getValues()[index];
final double val2 = DATA.getKeys()[index + 1] * DATA.getValues()[index + 1] * DATA.getValues()[index + 1];
final double yExpected = Math.sqrt((weight * val1 + (1.0 - weight) * val2) / x[loopx]);
assertEquals("TimeSquare interpolator: data point " + loopx, yExpected, yCalculated, TOLERANCE_Y);
assertEquals("TimeSquare interpolator: data point " + loopx, yCalculated, yCalculatedFactory, TOLERANCE_Y);
}
int lenghtx = DATA.getKeys().length;
double lastx = DATA.getKeys()[lenghtx - 1];
double yCalculated = INTERPOLATOR.interpolate(DATA, lastx);
final double yExpected = DATA.getValues()[lenghtx - 1];
assertEquals("TimeSquare interpolator: last point", yExpected, yCalculated, TOLERANCE_Y);
}
@Test
/**
* Tests the sensitivity of the interpolated value to the Y values.
*/
public void interpolationSensitivity() {
double shift = 1.0E-6;
double[] x = new double[] {1.0, 1.5, 2, 2.75};
for (int loopx = 0; loopx < x.length; loopx++) {
double yInit = INTERPOLATOR.interpolate(DATA, x[loopx]);
double[] ySensiCalculated = INTERPOLATOR.getNodeSensitivitiesForValue(DATA, x[loopx]);
for (int loopsens = 0; loopsens < X.length; loopsens++) {
double[] yVectorBumped = Y.clone();
yVectorBumped[loopsens] += shift;
Interpolator1DDataBundle dataBumped = INTERPOLATOR.getDataBundle(X, yVectorBumped);
double yBumped = INTERPOLATOR.interpolate(dataBumped, x[loopx]);
double ySensiExpected = (yBumped - yInit) / shift;
assertEquals("TimeSquare interpolator: test " + loopx + " node " + loopsens, ySensiExpected, ySensiCalculated[loopsens], TOLERANCE_SENSI);
}
}
int lenghtx = DATA.getKeys().length;
double lastx = DATA.getKeys()[lenghtx - 1];
double yInitLast = INTERPOLATOR.interpolate(DATA, lastx);
double[] ySensiCalculated = INTERPOLATOR.getNodeSensitivitiesForValue(DATA, lastx);
for (int loopsens = 0; loopsens < X.length; loopsens++) {
double[] yVectorBumped = Y.clone();
yVectorBumped[loopsens] += shift;
Interpolator1DDataBundle dataBumped = INTERPOLATOR.getDataBundle(X, yVectorBumped);
double yBumped = INTERPOLATOR.interpolate(dataBumped, lastx);
double ySensiExpected = (yBumped - yInitLast) / shift;
assertEquals("TimeSquare interpolator: test last node " + loopsens, ySensiExpected, ySensiCalculated[loopsens], TOLERANCE_SENSI);
}
}
/**
* Test first derivative values at end points
*/
@Test
public void firstDerivativeEndpointsTest() {
double eps = 1.0e-5;
double[][] xValues = new double[][] { {1., 2., 3., 4., 5., 6. }, {2., 3.6, 5., 5.1, 7.12, 8.8 } };
double[][] yValues = new double[][] { {1., 1.1, 3., 4., 6.9, 9. }, {1., 1.6, 4., 1.1, 5.32, 7.8 } };
int dim = xValues.length;
Interpolator1D interp = new TimeSquareInterpolator1D();
for (int j = 0; j < dim; ++j) {
int nData = xValues[j].length;
Interpolator1DDataBundle data = interp.getDataBundleFromSortedArrays(xValues[j], yValues[j]);
double xMin = xValues[j][0];
double xMax = xValues[j][nData - 1];
double minFirst = (interp.interpolate(data, xMin + eps) - interp.interpolate(data, xMin)) / eps;
double maxFirst = (interp.interpolate(data, xMax) - interp.interpolate(data, xMax - eps)) / eps;
assertEquals("firstDerivativeInterpolatorsTest", minFirst, interp.firstDerivative(data, xMin), eps);
assertEquals("firstDerivativeInterpolatorsTest", maxFirst, interp.firstDerivative(data, xMax), eps);
}
}
/** Tests interpolation when all values are 0. */
@Test
public void interpolationAll0() {
double[] xData = new double[] {1.0, 2.0, 3.0, 4.0 };
double[] yData = new double[] {0.0, 0.0, 0.0, 0.0 };
Interpolator1DDataBundle bundle = INTERPOLATOR.getDataBundle(xData, yData);
double[] xTest = new double[] {1.0, 2.5, 3.0, 3.5, 4.0 };
int nbTest = xTest.length;
for(int i=0; i<nbTest; i++) {
assertEquals("SquareLinearInterpolator - 0 values", 0, INTERPOLATOR.interpolate(bundle, xTest[i]), TOLERANCE_Y);
}
}
/** Tests first derivative at node when value is 0. */
@Test(expectedExceptions = NotImplementedException.class)
public void firstDerivativeNodeOne0Exception1() {
double[] xData = new double[] {1.0, 2.0, 3.0};
double[] yData = new double[] {1.0, 0.0, 1.0 };
Interpolator1DDataBundle bundle = INTERPOLATOR.getDataBundle(xData, yData);
INTERPOLATOR.firstDerivative(bundle, 2.1);
}
/** Tests first derivative at node when value is 0. */
@Test(expectedExceptions = NotImplementedException.class)
public void firstDerivativeNodeOne0Exception2() {
double[] xData = new double[] {1.0, 2.0, 3.0};
double[] yData = new double[] {1.0, 0.0, 1.0 };
Interpolator1DDataBundle bundle = INTERPOLATOR.getDataBundle(xData, yData);
INTERPOLATOR.firstDerivative(bundle, 1.9);
}
/** Tests sensitivity at node when all values are 0. */
@Test(expectedExceptions = NotImplementedException.class)
public void sensitivityNodeOne0Exception1() {
double[] xData = new double[] {1.0, 2.0, 3.0};
double[] yData = new double[] {1.0, 0.0, 1.0 };
Interpolator1DDataBundle bundle = INTERPOLATOR.getDataBundle(xData, yData);
INTERPOLATOR.getNodeSensitivitiesForValue(bundle, 2.1);
}
/** Tests sensitivity at node when all values are 0. */
@Test(expectedExceptions = NotImplementedException.class)
public void sensitivityNodeOne0Exception2() {
double[] xData = new double[] {1.0, 2.0, 3.0};
double[] yData = new double[] {1.0, 0.0, 1.0 };
Interpolator1DDataBundle bundle = INTERPOLATOR.getDataBundle(xData, yData);
INTERPOLATOR.getNodeSensitivitiesForValue(bundle, 1.9);
}
/** Tests data with a negative value. */
@Test(expectedExceptions = IllegalArgumentException.class)
public void negativeValueException() {
double[] xData = new double[] {1.0, 2.0, 3.0};
double[] yData = new double[] {1.0, -0.1, 1.0 };
INTERPOLATOR.getDataBundle(xData, yData);
}
/** Tests data with a negative value. */
@Test(expectedExceptions = IllegalArgumentException.class)
public void negativeValueException2() {
double[] xData = new double[] {1.0, 2.0, 3.0};
double[] yData = new double[] {1.0, -0.1, 1.0 };
INTERPOLATOR.getDataBundleFromSortedArrays(xData, yData);
}
}