@Override protected double doFirstDerivative(double xValue) { double resValue = evaluate(xValue, poly.getKnots(), poly.getCoefMatrix(), poly.getDimensions()); int nCoefs = poly.getOrder(); int numberOfIntervals = poly.getNumberOfIntervals(); double resDerivative = differentiate( xValue, poly.getKnots(), poly.getCoefMatrix(), poly.getDimensions(), nCoefs, numberOfIntervals); return Math.exp(resValue) * resDerivative; }
@Override protected DoubleArray doParameterSensitivity(double xValue) { int interval = FunctionUtils.getLowerBoundIndex(poly.getKnots(), xValue); if (interval == poly.getKnots().size() - 1) { interval--; // there is 1 less interval that knots } DoubleMatrix coefficientSensitivity = polySens.get().getCoefficientSensitivity(interval); double[] resSense = nodeSensitivity( xValue, poly.getKnots(), poly.getCoefMatrix(), poly.getDimensions(), interval, coefficientSensitivity).toArray(); double resValue = Math.exp(evaluate(xValue, poly.getKnots(), poly.getCoefMatrix(), poly.getDimensions())); double[] knotValues = getValues(logYValues); final int knotValuesLength = knotValues.length; double[] res = new double[knotValuesLength]; for (int i = 0; i < knotValuesLength; ++i) { res[i] = resSense[i] * resValue / knotValues[i]; } return DoubleArray.ofUnsafe(res); }
Bound(DoubleArray xValues, DoubleArray yValues) { super(xValues, yValues); this.xValues = xValues.toArrayUnsafe(); this.yValues = yValues.toArrayUnsafe(); this.logYValues = getYLogValues(this.yValues); PiecewisePolynomialInterpolator underlying = new MonotonicityPreservingCubicSplineInterpolator(new LogNaturalSplineHelper()); this.poly = underlying.interpolate(xValues.toArray(), logYValues); this.polySens = Suppliers.memoize(() -> underlying.interpolateWithSensitivity(xValues.toArray(), logYValues)); }
private static double differentiate( double xValue, DoubleArray knots, DoubleMatrix coefMatrix, int dimensions, int nCoefs, int numberOfIntervals) { int rowCount = dimensions * numberOfIntervals; int colCount = nCoefs - 1; DoubleMatrix coef = DoubleMatrix.of( rowCount, colCount, (i, j) -> coefMatrix.get(i, j) * (nCoefs - j - 1)); return evaluate(xValue, knots, coef, dimensions); }
@Override protected double doInterpolate(double xValue) { double resValue = evaluate(xValue, poly.getKnots(), poly.getCoefMatrix(), poly.getDimensions()); return Math.exp(resValue); }
@Override public BoundCurveInterpolator bind( BoundCurveExtrapolator extrapolatorLeft, BoundCurveExtrapolator extrapolatorRight) { return new Bound(this, extrapolatorLeft, extrapolatorRight); } }
private static double evaluate( double xValue, DoubleArray knots, DoubleMatrix coefMatrix, int dimensions) { // check for 1 less interval than knots int lowerBound = FunctionUtils.getLowerBoundIndex(knots, xValue); int indicator = lowerBound == knots.size() - 1 ? lowerBound - 1 : lowerBound; DoubleArray coefs = coefMatrix.row(dimensions * indicator); return getValue(coefs.toArrayUnsafe(), xValue, knots.get(indicator)); }
@Override public BoundCurveInterpolator bind(DoubleArray xValues, DoubleArray yValues) { return new Bound(xValues, yValues); }