/** * Copyright (C) 2016 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.market.curve.interpolator; import java.io.Serializable; import com.opengamma.strata.collect.array.DoubleArray; /** * Interpolator implementation that uses upper step interpolation. * <p> * The interpolated value at <i>x</i> s.t. <i>x<sub>1</sub> < x =< x<sub>2</sub></i> is the value at <i>x<sub>2</sub></i>. * The flat extrapolation is implemented outside the data range. */ final class StepUpperCurveInterpolator implements CurveInterpolator, Serializable { /** * The serialization version id. */ private static final long serialVersionUID = 1L; /** * The small parameter. * <p> * A value will be treated as 0 if its magnitude is smaller than this parameter. */ private static final double EPS = 1.0e-12; /** * The interpolator name. */ public static final String NAME = "StepUpper"; /** * The interpolator instance. */ public static final CurveInterpolator INSTANCE = new StepUpperCurveInterpolator(); /** * Restricted constructor. */ private StepUpperCurveInterpolator() { } // resolve instance private Object readResolve() { return INSTANCE; } //------------------------------------------------------------------------- @Override public String getName() { return NAME; } @Override public BoundCurveInterpolator bind(DoubleArray xValues, DoubleArray yValues) { return new Bound(xValues, yValues); } //------------------------------------------------------------------------- @Override public String toString() { return NAME; } //------------------------------------------------------------------------- /** * Bound interpolator. */ static class Bound extends AbstractBoundCurveInterpolator { private final double[] xValues; private final double[] yValues; private final int maxIndex; Bound(DoubleArray xValues, DoubleArray yValues) { super(xValues, yValues); this.xValues = xValues.toArrayUnsafe(); this.yValues = yValues.toArrayUnsafe(); this.maxIndex = xValues.size() - 1; } Bound(Bound base, BoundCurveExtrapolator extrapolatorLeft, BoundCurveExtrapolator extrapolatorRight) { super(base, extrapolatorLeft, extrapolatorRight); this.xValues = base.xValues; this.yValues = base.yValues; this.maxIndex = base.maxIndex; } //------------------------------------------------------------------------- @Override protected double doInterpolate(double xValue) { int upperIndex = getUpperBoundIndex(xValue); return yValues[upperIndex]; } @Override protected double doFirstDerivative(double xValue) { return 0d; } @Override protected DoubleArray doParameterSensitivity(double xValue) { double[] result = new double[yValues.length]; int upperIndex = getUpperBoundIndex(xValue); result[upperIndex] = 1d; return DoubleArray.ofUnsafe(result); } @Override public BoundCurveInterpolator bind( BoundCurveExtrapolator extrapolatorLeft, BoundCurveExtrapolator extrapolatorRight) { return new Bound(this, extrapolatorLeft, extrapolatorRight); } private int getUpperBoundIndex(double xValue) { if (xValue <= xValues[0] + EPS) { return 0; } if (xValue >= xValues[maxIndex - 1] + EPS) { return maxIndex; } int lowerIndex = lowerBoundIndex(xValue, xValues); if (Math.abs(xValues[lowerIndex] - xValue) < EPS) { return lowerIndex; } return lowerIndex + 1; } } }