/** * Copyright (C) 2013 - 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.function.PiecewisePolynomialFunction1D; import com.opengamma.analytics.math.interpolation.data.ArrayInterpolator1DDataBundle; import com.opengamma.analytics.math.interpolation.data.Interpolator1DDataBundle; import com.opengamma.analytics.math.interpolation.data.Interpolator1DPiecewisePoynomialWithExtraKnotsDataBundle; import com.opengamma.analytics.math.matrix.DoubleMatrix1D; /** * */ public class ShapePreservingCubicSplineInterpolator1D extends PiecewisePolynomialInterpolator1D { /** Serialization version */ private static final long serialVersionUID = 1L; private static final PiecewisePolynomialFunction1D FUNC = new PiecewisePolynomialFunction1D(); private static final PiecewisePolynomialInterpolator BASE_METHOD = new ShapePreservingCubicSplineInterpolator(); /** * Default constructor where the interpolation method is fixed */ public ShapePreservingCubicSplineInterpolator1D() { super(BASE_METHOD); } @Override public Double interpolate(final Interpolator1DDataBundle data, final Double value) { Validate.notNull(value, "value"); Validate.notNull(data, "data bundle"); Validate.isTrue(data instanceof Interpolator1DPiecewisePoynomialWithExtraKnotsDataBundle); final Interpolator1DPiecewisePoynomialWithExtraKnotsDataBundle polyData = (Interpolator1DPiecewisePoynomialWithExtraKnotsDataBundle) data; final DoubleMatrix1D res = FUNC.evaluate(polyData.getPiecewisePolynomialResult(), value); return res.getEntry(0); } @Override public double firstDerivative(final Interpolator1DDataBundle data, final Double value) { Validate.notNull(value, "value"); Validate.notNull(data, "data bundle"); Validate.isTrue(data instanceof Interpolator1DPiecewisePoynomialWithExtraKnotsDataBundle); final Interpolator1DPiecewisePoynomialWithExtraKnotsDataBundle polyData = (Interpolator1DPiecewisePoynomialWithExtraKnotsDataBundle) data; final DoubleMatrix1D res = FUNC.differentiate(polyData.getPiecewisePolynomialResult(), value); return res.getEntry(0); } @Override public double[] getNodeSensitivitiesForValue(final Interpolator1DDataBundle data, final Double value) { Validate.notNull(value, "value"); Validate.notNull(data, "data bundle"); Validate.isTrue(data instanceof Interpolator1DPiecewisePoynomialWithExtraKnotsDataBundle); final Interpolator1DPiecewisePoynomialWithExtraKnotsDataBundle polyData = (Interpolator1DPiecewisePoynomialWithExtraKnotsDataBundle) data; final int nData = polyData.size(); final double[] res = new double[nData]; final double eps = polyData.getEps(); final double small = polyData.getSmall(); for (int i = 0; i < nData; ++i) { final double den = Math.abs(polyData.getValues()[i]) < small ? eps : polyData.getValues()[i] * eps; final double up = FUNC.evaluate(polyData.getPiecewisePolynomialResultUp()[i], value).getData()[0]; final double dw = FUNC.evaluate(polyData.getPiecewisePolynomialResultDw()[i], value).getData()[0]; res[i] = 0.5 * (up - dw) / den; } return res; } @Override public Interpolator1DDataBundle getDataBundle(final double[] x, final double[] y) { return new Interpolator1DPiecewisePoynomialWithExtraKnotsDataBundle(new ArrayInterpolator1DDataBundle(x, y, false), BASE_METHOD); } @Override public Interpolator1DDataBundle getDataBundleFromSortedArrays(final double[] x, final double[] y) { return new Interpolator1DPiecewisePoynomialWithExtraKnotsDataBundle(new ArrayInterpolator1DDataBundle(x, y, true), BASE_METHOD); } }