/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.math.interpolation.data; import java.io.Serializable; import org.apache.commons.lang.ObjectUtils; import com.opengamma.analytics.math.function.RealPolynomialFunction1D; import com.opengamma.util.ArgumentChecker; /** * */ public class Interpolator1DDoubleQuadraticDataBundle implements Interpolator1DDataBundle, Serializable { private final Interpolator1DDataBundle _underlyingData; private RealPolynomialFunction1D[] _quadratics; private RealPolynomialFunction1D[] _quadraticsFirstDerivative; public Interpolator1DDoubleQuadraticDataBundle(final Interpolator1DDataBundle underlyingData) { ArgumentChecker.notNull(underlyingData, "underlying data"); _underlyingData = underlyingData; } private RealPolynomialFunction1D[] getQuadratics() { final double[] xData = getKeys(); final double[] yData = getValues(); final int n = xData.length - 1; if (n == 0) { final double a = yData[0]; return new RealPolynomialFunction1D[] {new RealPolynomialFunction1D(a) }; } else if (n == 1) { final double a = yData[1]; final double b = (yData[1] - yData[0]) / (xData[1] - xData[0]); return new RealPolynomialFunction1D[] {new RealPolynomialFunction1D(a, b) }; } else { final RealPolynomialFunction1D[] quadratic = new RealPolynomialFunction1D[n - 1]; for (int i = 1; i < n; i++) { quadratic[i - 1] = getQuadratic(xData, yData, i); } return quadratic; } } private RealPolynomialFunction1D[] getQuadraticsFirstDerivative() { final double[] xData = getKeys(); final double[] yData = getValues(); final int n = xData.length - 1; if (n == 0) { return new RealPolynomialFunction1D[] {new RealPolynomialFunction1D(0.) }; } else if (n == 1) { final double b = (yData[1] - yData[0]) / (xData[1] - xData[0]); return new RealPolynomialFunction1D[] {new RealPolynomialFunction1D(b) }; } else { final RealPolynomialFunction1D[] quadraticFirstDerivative = new RealPolynomialFunction1D[n - 1]; for (int i = 1; i < n; i++) { quadraticFirstDerivative[i - 1] = getQuadraticFirstDerivative(xData, yData, i); } return quadraticFirstDerivative; } } private RealPolynomialFunction1D getQuadratic(final double[] x, final double[] y, final int index) { final double a = y[index]; final double dx1 = x[index] - x[index - 1]; final double dx2 = x[index + 1] - x[index]; final double dy1 = y[index] - y[index - 1]; final double dy2 = y[index + 1] - y[index]; final double b = (dx1 * dy2 / dx2 + dx2 * dy1 / dx1) / (dx1 + dx2); final double c = (dy2 / dx2 - dy1 / dx1) / (dx1 + dx2); return new RealPolynomialFunction1D(new double[] {a, b, c }); } private RealPolynomialFunction1D getQuadraticFirstDerivative(final double[] x, final double[] y, final int index) { final double dx1 = x[index] - x[index - 1]; final double dx2 = x[index + 1] - x[index]; final double dy1 = y[index] - y[index - 1]; final double dy2 = y[index + 1] - y[index]; final double b = (dx1 * dy2 / dx2 + dx2 * dy1 / dx1) / (dx1 + dx2); final double c = (dy2 / dx2 - dy1 / dx1) / (dx1 + dx2); return new RealPolynomialFunction1D(new double[] {b, 2. * c }); } public RealPolynomialFunction1D getQuadratic(final int index) { if (_quadratics == null) { _quadratics = getQuadratics(); } return _quadratics[index]; } /** * @param index The index of the interval * @return First derivative of the quadratic function at the index */ public RealPolynomialFunction1D getQuadraticFirstDerivative(final int index) { if (_quadraticsFirstDerivative == null) { _quadraticsFirstDerivative = getQuadraticsFirstDerivative(); } return _quadraticsFirstDerivative[index]; } @Override public boolean containsKey(final Double key) { return _underlyingData.containsKey(key); } @Override public Double firstKey() { return _underlyingData.firstKey(); } @Override public Double firstValue() { return _underlyingData.firstValue(); } @Override public Double get(final Double key) { return _underlyingData.get(key); } @Override public InterpolationBoundedValues getBoundedValues(final Double key) { return _underlyingData.getBoundedValues(key); } @Override public double[] getKeys() { return _underlyingData.getKeys(); } @Override public int getLowerBoundIndex(final Double value) { return _underlyingData.getLowerBoundIndex(value); } @Override public Double getLowerBoundKey(final Double value) { return _underlyingData.getLowerBoundKey(value); } @Override public double[] getValues() { return _underlyingData.getValues(); } @Override public Double higherKey(final Double key) { return _underlyingData.higherKey(key); } @Override public Double higherValue(final Double key) { return _underlyingData.higherValue(key); } @Override public Double lastKey() { return _underlyingData.lastKey(); } @Override public Double lastValue() { return _underlyingData.lastValue(); } @Override public int size() { return _underlyingData.size(); } @Override public void setYValueAtIndex(final int index, final double y) { ArgumentChecker.notNegative(index, "index"); if (index >= size()) { throw new IllegalArgumentException("Index was greater than number of data points"); } _underlyingData.setYValueAtIndex(index, y); if (_quadratics == null) { _quadratics = getQuadratics(); } final double[] keys = getKeys(); final double[] values = getValues(); final int n = size() - 1; if (index == 0) { _quadratics[0] = getQuadratic(keys, values, 1); return; } else if (index == 1) { _quadratics[0] = getQuadratic(keys, values, 1); _quadratics[1] = getQuadratic(keys, values, 2); return; } else if (index == n) { _quadratics[n - 2] = getQuadratic(keys, values, n - 1); } else if (index == n - 1) { _quadratics[n - 3] = getQuadratic(keys, values, n - 2); _quadratics[n - 2] = getQuadratic(keys, values, n - 1); return; } else { _quadratics[index - 2] = getQuadratic(keys, values, index - 1); _quadratics[index - 1] = getQuadratic(keys, values, index); _quadratics[index] = getQuadratic(keys, values, index + 1); return; } } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((_underlyingData == null) ? 0 : _underlyingData.hashCode()); return result; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Interpolator1DDoubleQuadraticDataBundle other = (Interpolator1DDoubleQuadraticDataBundle) obj; return ObjectUtils.equals(_underlyingData, other._underlyingData); } }