/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.math.interpolation; import com.opengamma.analytics.math.FunctionUtils; import com.opengamma.analytics.math.function.PiecewisePolynomialFunction1D; import com.opengamma.analytics.math.interpolation.data.Interpolator1DDataBundle; import com.opengamma.analytics.math.matrix.DoubleMatrix1D; import com.opengamma.analytics.math.matrix.DoubleMatrix2D; import com.opengamma.util.ArgumentChecker; /** * Given a data set {x[i], y[i]}, extrapolate {x[i], x[i] * y[i]} by a linear function by using polynomial coefficients * obtained in ProductPiecewisePolynomialInterpolator1D. * * Even if the interpolator is clamped at (0,0), this extrapolator does not ensure the resulting extrapolation curve goes through the origin. * Thus a reference value is returned for Math.abs(value) < SMALL, where SMALL is defined in the super class. * Use {@link ZeroClampedProductExtrapolator1D} if one needs extrapolation such that the resulting curve go through the origin. */ public class ReciprocalExtrapolator1D extends ProductPolynomialExtrapolator1D { private static final long serialVersionUID = 1L; private static final PiecewisePolynomialFunction1D FUNC = new LinearlFunction1D(); /** * Construct the extrapolator * @param interpolator The interpolator */ public ReciprocalExtrapolator1D(Interpolator1D interpolator) { super(interpolator, FUNC); } /** * {@inheritDoc} * For small Math.abs(value), the resulting value diverges in general. * In such a case this method returns a reference value */ @Override public Double interpolate(final Interpolator1DDataBundle data, final Double value) { return super.interpolate(data, value); } /** * {@inheritDoc} * For small Math.abs(value), the resulting value diverges in general. * In such a case this method returns a reference value */ @Override public double firstDerivative(final Interpolator1DDataBundle data, final Double value) { return super.firstDerivative(data, value); } /** * {@inheritDoc} * For small Math.abs(value), the resulting value diverges in general. * In such a case this method returns a reference value */ @Override public double[] getNodeSensitivitiesForValue(final Interpolator1DDataBundle data, final Double value) { return super.getNodeSensitivitiesForValue(data, value); } private static class LinearlFunction1D extends PiecewisePolynomialFunction1D { @Override public DoubleMatrix1D evaluate(final PiecewisePolynomialResult pp, final double xKey) { ArgumentChecker.notNull(pp, "pp"); double[] knots = pp.getKnots().getData(); int nKnots = knots.length; DoubleMatrix2D coefMatrix = pp.getCoefMatrix(); int dim = pp.getDimensions(); double[] res = new double[dim]; int indicator = FunctionUtils.getLowerBoundIndex(knots, xKey); if (indicator == nKnots - 1) { indicator--; //there is 1 less interval that knots } for (int j = 0; j < dim; ++j) { double[] coefs = coefMatrix.getRowVector(dim * indicator + j).getData(); res[j] = getValue(coefs, xKey, knots[indicator]); } return new DoubleMatrix1D(res); } @Override public DoubleMatrix1D differentiate(final PiecewisePolynomialResult pp, final double xKey) { ArgumentChecker.notNull(pp, "pp"); double[] knots = pp.getKnots().getData(); int nKnots = pp.getNumberOfIntervals() + 1; int nCoefs = pp.getOrder(); int dim = pp.getDimensions(); double[] res = new double[dim]; int indicator = FunctionUtils.getLowerBoundIndex(knots, xKey); if (indicator == nKnots - 1) { indicator--; //there is 1 less interval that knots } DoubleMatrix2D coefMatrix = pp.getCoefMatrix(); for (int j = 0; j < dim; ++j) { final double[] coefs = coefMatrix.getRowVector(dim * indicator + j).getData(); res[j] = coefs[nCoefs - 2]; } return new DoubleMatrix1D(res); } @Override public DoubleMatrix1D differentiateTwice(final PiecewisePolynomialResult pp, final double xKey) { ArgumentChecker.notNull(pp, "pp"); int dim = pp.getDimensions(); double[] result = new double[dim]; return new DoubleMatrix1D(result); } @Override protected double getValue(final double[] coefs, final double x, final double leftknot) { int nCoefs = coefs.length; double res = coefs[nCoefs - 2] * (x - leftknot) + coefs[nCoefs - 1]; return res; } } }