Package com.opengamma.analytics.math.function

Source Code of com.opengamma.analytics.math.function.PiecewisePolynomialWithSensitivityFunction1D

/**
* 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);
  }
}
TOP

Related Classes of com.opengamma.analytics.math.function.PiecewisePolynomialWithSensitivityFunction1D

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.