All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.opengamma.strata.math.impl.function.RealPolynomialFunction1D Maven / Gradle / Ivy

There is a newer version: 2.12.46
Show newest version
/*
 * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.strata.math.impl.function;

import java.util.Arrays;

import com.google.common.math.DoubleMath;
import com.opengamma.strata.collect.ArgChecker;

/**
 * Class representing a polynomial that has real coefficients and takes a real
 * argument. The function is defined as:
 * $$
 * \begin{align*}
 * p(x) = a_0 + a_1 x + a_2 x^2 + \ldots + a_{n-1} x^{n-1}
 * \end{align*}
 * $$
 */
public class RealPolynomialFunction1D implements DoubleFunction1D {

  private final double[] _coefficients;
  private final int _n;

  /**
   * Creates an instance.
   * 
   * The array of coefficients for a polynomial
   * $p(x) = a_0 + a_1 x + a_2 x^2 + ... + a_{n-1} x^{n-1}$
   * is $\\{a_0, a_1, a_2, ..., a_{n-1}\\}$.
   * 
   * @param coefficients  the array of coefficients, not null or empty
   */
  public RealPolynomialFunction1D(double... coefficients) {
    ArgChecker.notNull(coefficients, "coefficients");
    ArgChecker.isTrue(coefficients.length > 0, "coefficients length must be greater than zero");
    _coefficients = coefficients;
    _n = _coefficients.length;
  }

  //-------------------------------------------------------------------------
  @Override
  public double applyAsDouble(double x) {
    ArgChecker.notNull(x, "x");
    double y = _coefficients[_n - 1];
    for (int i = _n - 2; i >= 0; i--) {
      y = x * y + _coefficients[i];
    }
    return y;
  }

  /**
   * Gets the coefficients of this polynomial.
   * 
   * @return the coefficients of this polynomial
   */
  public double[] getCoefficients() {
    return _coefficients;
  }

  /**
   * Adds a function to the polynomial.
   * If the function is not a {@link RealPolynomialFunction1D} then the addition takes
   * place as in {@link DoubleFunction1D}, otherwise the result will also be a polynomial.
   * 
   * @param f  the function to add
   * @return $P+f$
   */
  @Override
  public DoubleFunction1D add(DoubleFunction1D f) {
    ArgChecker.notNull(f, "function");
    if (f instanceof RealPolynomialFunction1D) {
      RealPolynomialFunction1D p1 = (RealPolynomialFunction1D) f;
      double[] c1 = p1.getCoefficients();
      double[] c = _coefficients;
      int n = c1.length;
      boolean longestIsNew = n > _n;
      double[] c3 = longestIsNew ? Arrays.copyOf(c1, n) : Arrays.copyOf(c, _n);
      for (int i = 0; i < (longestIsNew ? _n : n); i++) {
        c3[i] += longestIsNew ? c[i] : c1[i];
      }
      return new RealPolynomialFunction1D(c3);
    }
    return DoubleFunction1D.super.add(f);
  }

  /**
   * Adds a constant to the polynomial (equivalent to adding the value to the constant
   * term of the polynomial). The result is also a polynomial.
   * 
   * @param a  the value to add
   * @return $P+a$ 
   */
  @Override
  public RealPolynomialFunction1D add(double a) {
    double[] c = Arrays.copyOf(getCoefficients(), _n);
    c[0] += a;
    return new RealPolynomialFunction1D(c);
  }

  /**
   * Returns the derivative of this polynomial (also a polynomial), where
   * $$
   * \begin{align*}
   * P'(x) = a_1 + 2 a_2 x + 3 a_3 x^2 + 4 a_4 x^3 + \dots + n a_n x^{n-1}
   * \end{align*}
   * $$.
   * 
   * @return the derivative polynomial
   */
  @Override
  public RealPolynomialFunction1D derivative() {
    int n = _coefficients.length - 1;
    double[] coefficients = new double[n];
    for (int i = 1; i <= n; i++) {
      coefficients[i - 1] = i * _coefficients[i];
    }
    return new RealPolynomialFunction1D(coefficients);
  }

  /**
   * Divides the polynomial by a constant value (equivalent to dividing each coefficient by this value).
   * The result is also a polynomial.
   * 
   * @param a  the divisor
   * @return the polynomial 
   */
  @Override
  public RealPolynomialFunction1D divide(double a) {
    double[] c = Arrays.copyOf(getCoefficients(), _n);
    for (int i = 0; i < _n; i++) {
      c[i] /= a;
    }
    return new RealPolynomialFunction1D(c);
  }

  /**
   * Multiplies the polynomial by a function.
   * If the function is not a {@link RealPolynomialFunction1D} then the multiplication takes
   * place as in {@link DoubleFunction1D}, otherwise the result will also be a polynomial.
   * 
   * @param f  the function by which to multiply
   * @return $P \dot f$
   */
  @Override
  public DoubleFunction1D multiply(DoubleFunction1D f) {
    ArgChecker.notNull(f, "function");
    if (f instanceof RealPolynomialFunction1D) {
      RealPolynomialFunction1D p1 = (RealPolynomialFunction1D) f;
      double[] c = _coefficients;
      double[] c1 = p1.getCoefficients();
      int m = c1.length;
      double[] newC = new double[_n + m - 1];
      for (int i = 0; i < newC.length; i++) {
        newC[i] = 0;
        for (int j = Math.max(0, i + 1 - m); j < Math.min(_n, i + 1); j++) {
          newC[i] += c[j] * c1[i - j];
        }
      }
      return new RealPolynomialFunction1D(newC);
    }
    return DoubleFunction1D.super.multiply(f);
  }

  /**
   * Multiplies the polynomial by a constant value (equivalent to multiplying each
   * coefficient by this value). The result is also a polynomial.
   * 
   * @param a  the multiplicator
   * @return the polynomial 
   */
  @Override
  public RealPolynomialFunction1D multiply(double a) {
    double[] c = Arrays.copyOf(getCoefficients(), _n);
    for (int i = 0; i < _n; i++) {
      c[i] *= a;
    }
    return new RealPolynomialFunction1D(c);
  }

  /**
   * Subtracts a function from the polynomial.
   * 

* If the function is not a {@link RealPolynomialFunction1D} then the subtract takes place * as in {@link DoubleFunction1D}, otherwise the result will also be a polynomial. * * @param f the function to subtract * @return $P-f$ */ @Override public DoubleFunction1D subtract(DoubleFunction1D f) { ArgChecker.notNull(f, "function"); if (f instanceof RealPolynomialFunction1D) { RealPolynomialFunction1D p1 = (RealPolynomialFunction1D) f; double[] c = _coefficients; double[] c1 = p1.getCoefficients(); int m = c.length; int n = c1.length; int min = Math.min(m, n); int max = Math.max(m, n); double[] c3 = new double[max]; for (int i = 0; i < min; i++) { c3[i] = c[i] - c1[i]; } for (int i = min; i < max; i++) { if (m == max) { c3[i] = c[i]; } else { c3[i] = -c1[i]; } } return new RealPolynomialFunction1D(c3); } return DoubleFunction1D.super.subtract(f); } /** * Subtracts a constant from the polynomial (equivalent to subtracting the value from the * constant term of the polynomial). The result is also a polynomial. * * @param a the value to add * @return $P-a$ */ @Override public RealPolynomialFunction1D subtract(double a) { double[] c = Arrays.copyOf(getCoefficients(), _n); c[0] -= a; return new RealPolynomialFunction1D(c); } /** * Converts the polynomial to its monic form. If * $$ * \begin{align*} * P(x) = a_0 + a_1 x + a_2 x^2 + a_3 x^3 \dots + a_n x^n * \end{align*} * $$ * then the monic form is * $$ * \begin{align*} * P(x) = \lambda_0 + \lambda_1 x + \lambda_2 x^2 + \lambda_3 x^3 \dots + x^n * \end{align*} * $$ * where * $$ * \begin{align*} * \lambda_i = \frac{a_i}{a_n} * \end{align*} * $$ * * @return the polynomial in monic form */ public RealPolynomialFunction1D toMonic() { double an = _coefficients[_n - 1]; if (DoubleMath.fuzzyEquals(an, (double) 1, 1e-15)) { return new RealPolynomialFunction1D(Arrays.copyOf(_coefficients, _n)); } double[] rescaled = new double[_n]; for (int i = 0; i < _n; i++) { rescaled[i] = _coefficients[i] / an; } return new RealPolynomialFunction1D(rescaled); } //------------------------------------------------------------------------- @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } RealPolynomialFunction1D other = (RealPolynomialFunction1D) obj; if (!Arrays.equals(_coefficients, other._coefficients)) { return false; } return true; } @Override public int hashCode() { int prime = 31; int result = 1; result = prime * result + Arrays.hashCode(_coefficients); return result; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy