com.opengamma.strata.math.impl.function.DoubleFunction1D Maven / Gradle / Ivy
Show all versions of strata-math Show documentation
/*
* 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.function.DoubleUnaryOperator;
import java.util.function.Function;
import com.opengamma.strata.collect.ArgChecker;
import com.opengamma.strata.math.impl.differentiation.FiniteDifferenceType;
/**
* Defines a family of functions that take real arguments and return real values.
* The functionality of {@link Function} is extended; this class allows arithmetic
* operations on functions and defines a derivative function.
*/
public interface DoubleFunction1D extends DoubleUnaryOperator {
/**
* Returns a function that calculates the first derivative.
*
* The method used is central finite difference, with $\epsilon = 10^{-5}$.
* Implementing classes can override this method to return a function that
* is the exact functional representation of the first derivative.
*
* @return a function that calculates the first derivative of this function
*/
public default DoubleFunction1D derivative() {
return derivative(FiniteDifferenceType.CENTRAL, 1e-5);
}
/**
* Returns a function that calculates the first derivative. The method used
* is finite difference, with the differencing type and $\epsilon$ as arguments.
*
* @param differenceType the differencing type to use
* @param eps the $\epsilon$ to use
* @return a function that calculates the first derivative of this function
*/
public default DoubleFunction1D derivative(FiniteDifferenceType differenceType, double eps) {
ArgChecker.notNull(differenceType, "difference type");
switch (differenceType) {
case CENTRAL:
return new DoubleFunction1D() {
@Override
public double applyAsDouble(double x) {
return (DoubleFunction1D.this.applyAsDouble(x + eps) - DoubleFunction1D.this.applyAsDouble(x - eps)) / 2 / eps;
}
};
case BACKWARD:
return new DoubleFunction1D() {
@Override
public double applyAsDouble(double x) {
return (DoubleFunction1D.this.applyAsDouble(x) - DoubleFunction1D.this.applyAsDouble(x - eps)) / eps;
}
};
case FORWARD:
return new DoubleFunction1D() {
@Override
public double applyAsDouble(double x) {
return (DoubleFunction1D.this.applyAsDouble(x + eps) - DoubleFunction1D.this.applyAsDouble(x)) / eps;
}
};
default:
throw new IllegalArgumentException("Unhandled FiniteDifferenceType " + differenceType);
}
}
/**
* For a DoubleFunction1D $g(x)$, adding a function $f(x)$ returns the
* function $h(x) = f(x) + g(x)$.
*
* @param f the function to add
* @return a function $h(x) = f(x) + g(x)$
*/
public default DoubleFunction1D add(DoubleFunction1D f) {
ArgChecker.notNull(f, "f");
return new DoubleFunction1D() {
@Override
public double applyAsDouble(double x) {
return DoubleFunction1D.this.applyAsDouble(x) + f.applyAsDouble(x);
}
};
}
/**
* For a DoubleFunction1D $g(x)$, adding a constant $a$ returns the function
* $h(x) = g(x) + a$.
*
* @param a the constant to add
* @return a function $h(x) = g(x) + a$
*/
public default DoubleFunction1D add(double a) {
return new DoubleFunction1D() {
@Override
public double applyAsDouble(double x) {
return DoubleFunction1D.this.applyAsDouble(x) + a;
}
};
}
/**
* For a DoubleFunction1D $g(x)$, dividing by a function $f(x)$ returns the
* function $h(x) = \frac{g(x)}{f(x)}$.
*
* @param f the function to divide by
* @return a function $h(x) = \frac{f(x)}{g(x)}$
*/
public default DoubleFunction1D divide(DoubleFunction1D f) {
ArgChecker.notNull(f, "f");
return new DoubleFunction1D() {
@Override
public double applyAsDouble(double x) {
return DoubleFunction1D.this.applyAsDouble(x) / f.applyAsDouble(x);
}
};
}
/**
* For a DoubleFunction1D $g(x)$, dividing by a constant $a$ returns the
* function $h(x) = \frac{g(x)}{a}$.
*
* @param a the constant to add
* @return a function $h(x) = \frac{g(x)}{a}$
*/
public default DoubleFunction1D divide(double a) {
return new DoubleFunction1D() {
@Override
public double applyAsDouble(double x) {
return DoubleFunction1D.this.applyAsDouble(x) / a;
}
};
}
/**
* For a DoubleFunction1D $g(x)$, multiplying by a function $f(x)$ returns
* the function $h(x) = f(x) g(x)$.
*
* @param f the function to multiply by
* @return a function $h(x) = f(x) g(x)$
*/
public default DoubleFunction1D multiply(DoubleFunction1D f) {
ArgChecker.notNull(f, "f");
return new DoubleFunction1D() {
@Override
public double applyAsDouble(double x) {
return DoubleFunction1D.this.applyAsDouble(x) * f.applyAsDouble(x);
}
};
}
/**
* For a DoubleFunction1D $g(x)$, multiplying by a constant $a$ returns the
* function $h(x) = a g(x)$.
*
* @param a the constant to add
* @return a function $h(x) = a g(x)$
*/
public default DoubleFunction1D multiply(double a) {
return new DoubleFunction1D() {
@Override
public double applyAsDouble(double x) {
return DoubleFunction1D.this.applyAsDouble(x) * a;
}
};
}
/**
* For a DoubleFunction1D $g(x)$, subtracting a function $f(x)$ returns the
* function $h(x) = f(x) - g(x)$.
*
* @param f the function to subtract
* @return a function $h(x) = g(x) - f(x)$
*/
public default DoubleFunction1D subtract(DoubleFunction1D f) {
ArgChecker.notNull(f, "f");
return new DoubleFunction1D() {
@Override
public double applyAsDouble(double x) {
return DoubleFunction1D.this.applyAsDouble(x) - f.applyAsDouble(x);
}
};
}
/**
* For a DoubleFunction1D $g(x)$, subtracting a constant $a$ returns the
* function $h(x) = g(x) - a$.
*
* @param a the constant to add
* @return a function $h(x) = g(x) - a$
*/
public default DoubleFunction1D subtract(double a) {
return new DoubleFunction1D() {
@Override
public double applyAsDouble(double x) {
return DoubleFunction1D.this.applyAsDouble(x) - a;
}
};
}
//-------------------------------------------------------------------------
/**
* Converts a Function<Double, Double> into a DoubleFunction1D.
*
* @param f the function to convert
* @return the converted function
*/
public static DoubleFunction1D from(Function f) {
ArgChecker.notNull(f, "f");
return new DoubleFunction1D() {
@Override
public double applyAsDouble(double x) {
return f.apply(x);
}
};
}
}