com.opengamma.analytics.math.function.PiecewisePolynomialWithSensitivityFunction1D.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.analytics.math.function.PiecewisePolynomialWithSensitivityFunction1D.java

Source

/**
 * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
 * 
 * Please see distribution for license.
 */
package com.opengamma.analytics.math.function;

import org.apache.commons.lang.NotImplementedException;

import com.opengamma.analytics.math.FunctionUtils;
import com.opengamma.analytics.math.interpolation.PiecewisePolynomialResultsWithSensitivity;
import com.opengamma.analytics.math.matrix.DoubleMatrix1D;
import com.opengamma.analytics.math.matrix.DoubleMatrix2D;
import com.opengamma.analytics.math.matrix.MatrixAlgebra;
import com.opengamma.analytics.math.matrix.OGMatrixAlgebra;
import com.opengamma.util.ArgumentChecker;

/**
 * Give a class {@link PiecewisePolynomialResultsWithSensitivity}, Compute node sensitivity of function value, first derivative value and second derivative value
 */
public class PiecewisePolynomialWithSensitivityFunction1D extends PiecewisePolynomialFunction1D {

    private static final MatrixAlgebra MA = new OGMatrixAlgebra();

    /** 
     * @param pp {@link PiecewisePolynomialResultsWithSensitivity}
     * @param xKey 
     * @return Node sensitivity value at x=xKey
     */
    public DoubleMatrix1D nodeSensitivity(final PiecewisePolynomialResultsWithSensitivity pp, final double xKey) {
        ArgumentChecker.notNull(pp, "null pp");
        ArgumentChecker.isFalse(Double.isNaN(xKey), "xKey containing NaN");
        ArgumentChecker.isFalse(Double.isInfinite(xKey), "xKey containing Infinity");

        if (pp.getDimensions() > 1) {
            throw new NotImplementedException();
        }

        final double[] knots = pp.getKnots().getData();
        final int nKnots = knots.length;
        int interval = FunctionUtils.getLowerBoundIndex(knots, xKey);
        if (interval == nKnots - 1) {
            interval--; // there is 1 less interval that knots
        }

        final double s = xKey - knots[interval];
        final DoubleMatrix2D a = pp.getCoefficientSensitivity(interval);
        final int nCoefs = a.getNumberOfRows();

        DoubleMatrix1D res = a.getRowVector(0);
        for (int i = 1; i < nCoefs; i++) {
            res = (DoubleMatrix1D) MA.scale(res, s);
            res = (DoubleMatrix1D) MA.add(res, a.getRowVector(i));
        }

        return res;
    }

    /** 
     * @param pp {@link PiecewisePolynomialResultsWithSensitivity}
     * @param xKeys 
     * @return Node sensitivity value at x=xKeys
     */
    public DoubleMatrix1D[] nodeSensitivity(final PiecewisePolynomialResultsWithSensitivity pp,
            final double[] xKeys) {
        ArgumentChecker.notNull(pp, "null pp");
        ArgumentChecker.notNull(xKeys, "null xKeys");
        final int nKeys = xKeys.length;
        final DoubleMatrix1D[] res = new DoubleMatrix1D[nKeys];

        for (int i = 0; i < nKeys; ++i) {
            ArgumentChecker.isFalse(Double.isNaN(xKeys[i]), "xKey containing NaN");
            ArgumentChecker.isFalse(Double.isInfinite(xKeys[i]), "xKey containing Infinity");
        }
        if (pp.getDimensions() > 1) {
            throw new NotImplementedException();
        }

        final double[] knots = pp.getKnots().getData();
        final int nKnots = knots.length;

        for (int j = 0; j < nKeys; ++j) {
            final double xKey = xKeys[j];
            int interval = FunctionUtils.getLowerBoundIndex(knots, xKey);
            if (interval == nKnots - 1) {
                interval--; // there is 1 less interval that knots
            }

            final double s = xKey - knots[interval];
            final DoubleMatrix2D a = pp.getCoefficientSensitivity(interval);
            final int nCoefs = a.getNumberOfRows();

            res[j] = a.getRowVector(0);
            for (int i = 1; i < nCoefs; i++) {
                res[j] = (DoubleMatrix1D) MA.scale(res[j], s);
                res[j] = (DoubleMatrix1D) MA.add(res[j], a.getRowVector(i));
            }
        }

        return res;
    }

    /** 
     * @param pp {@link PiecewisePolynomialResultsWithSensitivity}
     * @param xKey 
     * @return Node sensitivity of derivative value at x=xKey
     */
    public DoubleMatrix1D differentiateNodeSensitivity(final PiecewisePolynomialResultsWithSensitivity pp,
            final double xKey) {
        ArgumentChecker.notNull(pp, "null pp");
        ArgumentChecker.isFalse(Double.isNaN(xKey), "xKey containing NaN");
        ArgumentChecker.isFalse(Double.isInfinite(xKey), "xKey containing Infinity");

        if (pp.getDimensions() > 1) {
            throw new NotImplementedException();
        }
        final int nCoefs = pp.getOrder();
        ArgumentChecker.isFalse(nCoefs < 2, "Polynomial degree is too low");

        final double[] knots = pp.getKnots().getData();
        final int nKnots = knots.length;
        int interval = FunctionUtils.getLowerBoundIndex(knots, xKey);
        if (interval == nKnots - 1) {
            interval--; // there is 1 less interval that knots
        }

        final double s = xKey - knots[interval];
        final DoubleMatrix2D a = pp.getCoefficientSensitivity(interval);

        DoubleMatrix1D res = (DoubleMatrix1D) MA.scale(a.getRowVector(0), nCoefs - 1);
        for (int i = 1; i < nCoefs - 1; i++) {
            res = (DoubleMatrix1D) MA.scale(res, s);
            res = (DoubleMatrix1D) MA.add(res, MA.scale(a.getRowVector(i), nCoefs - 1 - i));
        }

        return res;
    }

    /** 
     * @param pp {@link PiecewisePolynomialResultsWithSensitivity}
     * @param xKeys 
     * @return Node sensitivity of derivative value at x=xKeys
     */
    public DoubleMatrix1D[] differentiateNodeSensitivity(final PiecewisePolynomialResultsWithSensitivity pp,
            final double[] xKeys) {
        ArgumentChecker.notNull(pp, "null pp");

        if (pp.getDimensions() > 1) {
            throw new NotImplementedException();
        }
        final int nCoefs = pp.getOrder();
        ArgumentChecker.isFalse(nCoefs < 2, "Polynomial degree is too low");
        final int nIntervals = pp.getNumberOfIntervals();

        final DoubleMatrix2D[] diffSense = new DoubleMatrix2D[nIntervals];
        final DoubleMatrix2D[] senseMat = pp.getCoefficientSensitivityAll();
        final int nData = senseMat[0].getNumberOfColumns();
        for (int i = 0; i < nIntervals; ++i) {
            final double[][] tmp = new double[nCoefs - 1][nData];
            for (int j = 0; j < nCoefs - 1; ++j) {
                for (int k = 0; k < nData; ++k) {
                    tmp[j][k] = (nCoefs - 1 - j) * senseMat[i].getData()[j][k];
                }
            }
            diffSense[i] = new DoubleMatrix2D(tmp);
        }

        PiecewisePolynomialResultsWithSensitivity ppDiff = new PiecewisePolynomialResultsWithSensitivity(
                pp.getKnots(), pp.getCoefMatrix(), nCoefs - 1, pp.getDimensions(), diffSense);
        return nodeSensitivity(ppDiff, xKeys);
    }

    /** 
     * @param pp {@link PiecewisePolynomialResultsWithSensitivity}
     * @param xKey 
     * @return Node sensitivity of second derivative value at x=xKey
     */
    public DoubleMatrix1D differentiateTwiceNodeSensitivity(final PiecewisePolynomialResultsWithSensitivity pp,
            final double xKey) {
        ArgumentChecker.notNull(pp, "null pp");
        ArgumentChecker.isFalse(Double.isNaN(xKey), "xKey containing NaN");
        ArgumentChecker.isFalse(Double.isInfinite(xKey), "xKey containing Infinity");

        if (pp.getDimensions() > 1) {
            throw new NotImplementedException();
        }
        final int nCoefs = pp.getOrder();
        ArgumentChecker.isFalse(nCoefs < 3, "Polynomial degree is too low");

        final double[] knots = pp.getKnots().getData();
        final int nKnots = knots.length;
        int interval = FunctionUtils.getLowerBoundIndex(knots, xKey);
        if (interval == nKnots - 1) {
            interval--; // there is 1 less interval that knots
        }

        final double s = xKey - knots[interval];
        final DoubleMatrix2D a = pp.getCoefficientSensitivity(interval);

        DoubleMatrix1D res = (DoubleMatrix1D) MA.scale(a.getRowVector(0), (nCoefs - 1) * (nCoefs - 2));
        for (int i = 1; i < nCoefs - 2; i++) {
            res = (DoubleMatrix1D) MA.scale(res, s);
            res = (DoubleMatrix1D) MA.add(res, MA.scale(a.getRowVector(i), (nCoefs - 1 - i) * (nCoefs - 2 - i)));
        }

        return res;
    }

    /** 
     * @param pp {@link PiecewisePolynomialResultsWithSensitivity}
     * @param xKeys 
     * @return Node sensitivity of second derivative value at x=xKeys
     */
    public DoubleMatrix1D[] differentiateTwiceNodeSensitivity(final PiecewisePolynomialResultsWithSensitivity pp,
            final double[] xKeys) {
        ArgumentChecker.notNull(pp, "null pp");

        if (pp.getDimensions() > 1) {
            throw new NotImplementedException();
        }
        final int nCoefs = pp.getOrder();
        ArgumentChecker.isFalse(nCoefs < 3, "Polynomial degree is too low");
        final int nIntervals = pp.getNumberOfIntervals();

        final DoubleMatrix2D[] diffSense = new DoubleMatrix2D[nIntervals];
        final DoubleMatrix2D[] senseMat = pp.getCoefficientSensitivityAll();
        final int nData = senseMat[0].getNumberOfColumns();
        for (int i = 0; i < nIntervals; ++i) {
            final double[][] tmp = new double[nCoefs - 2][nData];
            for (int j = 0; j < nCoefs - 2; ++j) {
                for (int k = 0; k < nData; ++k) {
                    tmp[j][k] = (nCoefs - 1 - j) * (nCoefs - 2 - j) * senseMat[i].getData()[j][k];
                }
            }
            diffSense[i] = new DoubleMatrix2D(tmp);
        }

        PiecewisePolynomialResultsWithSensitivity ppDiff = new PiecewisePolynomialResultsWithSensitivity(
                pp.getKnots(), pp.getCoefMatrix(), nCoefs - 2, pp.getDimensions(), diffSense);
        return nodeSensitivity(ppDiff, xKeys);
    }
}