/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.math.interpolation; import org.apache.commons.lang.Validate; import com.opengamma.analytics.math.MathException; import com.opengamma.analytics.math.interpolation.data.ArrayInterpolator1DDataBundle; import com.opengamma.analytics.math.interpolation.data.InterpolationBoundedValues; import com.opengamma.analytics.math.interpolation.data.Interpolator1DDataBundle; /** * A one-dimensional linear interpolator. The interpolated value of the function * <i>y</i> at <i>x</i> between two data points <i>(x<sub>1</sub>, * y<sub>1</sub>)</i> and <i>(x<sub>2</sub>, y<sub>2</sub>)</i> is given by:<br> * <i>y = y<sub>1</sub> + (x - x<sub>1</sub>) * (y<sub>2</sub> - y<sub>1</sub>) * / (x<sub>2</sub> - x<sub>1</sub>)</i> */ public class LinearInterpolator1D extends Interpolator1D { private static final long serialVersionUID = 1L; @Override public Double interpolate(final Interpolator1DDataBundle model, final Double value) { Validate.notNull(value, "Value to be interpolated must not be null"); Validate.notNull(model, "Data bundle must not be null"); final InterpolationBoundedValues boundedValues = model.getBoundedValues(value); final double x1 = boundedValues.getLowerBoundKey(); final double y1 = boundedValues.getLowerBoundValue(); if (model.getLowerBoundIndex(value) == model.size() - 1) { return y1; } final double x2 = boundedValues.getHigherBoundKey(); final double y2 = boundedValues.getHigherBoundValue(); return y1 + (value - x1) / (x2 - x1) * (y2 - y1); } @Override public double firstDerivative(final Interpolator1DDataBundle model, final Double value) { Validate.notNull(value, "Value to be interpolated must not be null"); Validate.notNull(model, "Data bundle must not be null"); final InterpolationBoundedValues boundedValues = model.getBoundedValues(value); final double x1 = boundedValues.getLowerBoundKey(); final double y1 = boundedValues.getLowerBoundValue(); if (model.getLowerBoundIndex(value) == model.size() - 1) { if (value > model.lastKey()) { throw new MathException("Value of " + value + " after last key. Use exstrapolator"); } final double[] x = model.getKeys(); final double[] y = model.getValues(); final int n = x.length; return n == 1 ? 0.0 : (y[n - 1] - y[n - 2]) / (x[n - 1] - x[n - 2]); } final double x2 = boundedValues.getHigherBoundKey(); final double y2 = boundedValues.getHigherBoundValue(); return (y2 - y1) / (x2 - x1); } @Override public double[] getNodeSensitivitiesForValue(final Interpolator1DDataBundle data, final Double value) { Validate.notNull(data, "data"); final int n = data.size(); final double[] result = new double[n]; final InterpolationBoundedValues boundedValues = data.getBoundedValues(value); if (boundedValues.getHigherBoundKey() == null) { result[n - 1] = 1.0; return result; } final int index = data.getLowerBoundIndex(value); final double x1 = boundedValues.getLowerBoundKey(); final double x2 = boundedValues.getHigherBoundKey(); final double dx = x2 - x1; final double a = (x2 - value) / dx; final double b = 1 - a; result[index] = a; result[index + 1] = b; return result; } @Override public Interpolator1DDataBundle getDataBundle(final double[] x, final double[] y) { return new ArrayInterpolator1DDataBundle(x, y); } @Override public Interpolator1DDataBundle getDataBundleFromSortedArrays(final double[] x, final double[] y) { return new ArrayInterpolator1DDataBundle(x, y, true); } }