remove embedded math4 src

This commit is contained in:
Jonathan Shook 2023-01-26 22:21:18 -06:00
parent 63721cd0df
commit 53832ec027
596 changed files with 0 additions and 128623 deletions

View File

@ -1,58 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4;
/**
* Interface representing a <a href="http://mathworld.wolfram.com/Field.html">field</a>.
* <p>
* Classes implementing this interface will often be singletons.
* </p>
* @param <T> the type of the field elements
* @see FieldElement
* @since 2.0
*/
public interface Field<T> {
/** Get the additive identity of the field.
* <p>
* The additive identity is the element e<sub>0</sub> of the field such that
* for all elements a of the field, the equalities a + e<sub>0</sub> =
* e<sub>0</sub> + a = a hold.
* </p>
* @return additive identity of the field
*/
T getZero();
/** Get the multiplicative identity of the field.
* <p>
* The multiplicative identity is the element e<sub>1</sub> of the field such that
* for all elements a of the field, the equalities a &times; e<sub>1</sub> =
* e<sub>1</sub> &times; a = a hold.
* </p>
* @return multiplicative identity of the field
*/
T getOne();
/**
* Returns the runtime class of the FieldElement.
*
* @return The {@code Class} object that represents the runtime
* class of this object.
*/
Class<? extends FieldElement<T>> getRuntimeClass();
}

View File

@ -1,85 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4;
import org.apache.commons.math4.exception.MathArithmeticException;
import org.apache.commons.math4.exception.NullArgumentException;
/**
* Interface representing <a href="http://mathworld.wolfram.com/Field.html">field</a> elements.
* @param <T> the type of the field elements
* @see Field
* @since 2.0
*/
public interface FieldElement<T> {
/** Compute this + a.
* @param a element to add
* @return a new element representing this + a
* @throws NullArgumentException if {@code a} is {@code null}.
*/
T add(T a) throws NullArgumentException;
/** Compute this - a.
* @param a element to subtract
* @return a new element representing this - a
* @throws NullArgumentException if {@code a} is {@code null}.
*/
T subtract(T a) throws NullArgumentException;
/**
* Returns the additive inverse of {@code this} element.
* @return the opposite of {@code this}.
*/
T negate();
/** Compute n &times; this. Multiplication by an integer number is defined
* as the following sum
* n &times; this = &sum;<sub>i=1</sub><sup>n</sup> this.
* @param n Number of times {@code this} must be added to itself.
* @return A new element representing n &times; this.
*/
T multiply(int n);
/** Compute this &times; a.
* @param a element to multiply
* @return a new element representing this &times; a
* @throws NullArgumentException if {@code a} is {@code null}.
*/
T multiply(T a) throws NullArgumentException;
/** Compute this &divide; a.
* @param a element to divide by
* @return a new element representing this &divide; a
* @throws NullArgumentException if {@code a} is {@code null}.
* @throws MathArithmeticException if {@code a} is zero
*/
T divide(T a) throws NullArgumentException, MathArithmeticException;
/**
* Returns the multiplicative inverse of {@code this} element.
* @return the inverse of {@code this}.
* @throws MathArithmeticException if {@code this} is zero
*/
T reciprocal() throws MathArithmeticException;
/** Get the {@link Field} to which the instance belongs.
* @return {@link Field} to which the instance belongs
*/
Field<T> getField();
}

View File

@ -1,402 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4;
import org.apache.commons.math4.exception.DimensionMismatchException;
/**
* Interface representing a <a href="http://mathworld.wolfram.com/RealNumber.html">real</a>
* <a href="http://mathworld.wolfram.com/Field.html">field</a>.
* @param <T> the type of the field elements
* @see FieldElement
* @since 3.2
*/
public interface RealFieldElement<T> extends FieldElement<T> {
/** Get the real value of the number.
* @return real value
*/
double getReal();
/** '+' operator.
* @param a right hand side parameter of the operator
* @return this+a
*/
T add(double a);
/** '-' operator.
* @param a right hand side parameter of the operator
* @return this-a
*/
T subtract(double a);
/** '&times;' operator.
* @param a right hand side parameter of the operator
* @return this&times;a
*/
T multiply(double a);
/** '&divide;' operator.
* @param a right hand side parameter of the operator
* @return this&divide;a
*/
T divide(double a);
/** IEEE remainder operator.
* @param a right hand side parameter of the operator
* @return this - n &times; a where n is the closest integer to this/a
* (the even integer is chosen for n if this/a is halfway between two integers)
*/
T remainder(double a);
/** IEEE remainder operator.
* @param a right hand side parameter of the operator
* @return this - n &times; a where n is the closest integer to this/a
* (the even integer is chosen for n if this/a is halfway between two integers)
* @exception DimensionMismatchException if number of free parameters or orders are inconsistent
*/
T remainder(T a)
throws DimensionMismatchException;
/** absolute value.
* @return abs(this)
*/
T abs();
/** Get the smallest whole number larger than instance.
* @return ceil(this)
*/
T ceil();
/** Get the largest whole number smaller than instance.
* @return floor(this)
*/
T floor();
/** Get the whole number that is the nearest to the instance, or the even one if x is exactly half way between two integers.
* @return a double number r such that r is an integer r - 0.5 &le; this &le; r + 0.5
*/
T rint();
/** Get the closest long to instance value.
* @return closest long to {@link #getReal()}
*/
long round();
/** Compute the signum of the instance.
* The signum is -1 for negative numbers, +1 for positive numbers and 0 otherwise
* @return -1.0, -0.0, +0.0, +1.0 or NaN depending on sign of a
*/
T signum();
/**
* Returns the instance with the sign of the argument.
* A NaN {@code sign} argument is treated as positive.
*
* @param sign the sign for the returned value
* @return the instance with the same sign as the {@code sign} argument
*/
T copySign(T sign);
/**
* Returns the instance with the sign of the argument.
* A NaN {@code sign} argument is treated as positive.
*
* @param sign the sign for the returned value
* @return the instance with the same sign as the {@code sign} argument
*/
T copySign(double sign);
/**
* Multiply the instance by a power of 2.
* @param n power of 2
* @return this &times; 2<sup>n</sup>
*/
T scalb(int n);
/**
* Returns the hypotenuse of a triangle with sides {@code this} and {@code y}
* - sqrt(<i>this</i><sup>2</sup>&nbsp;+<i>y</i><sup>2</sup>)
* avoiding intermediate overflow or underflow.
*
* <ul>
* <li> If either argument is infinite, then the result is positive infinity.</li>
* <li> else, if either argument is NaN then the result is NaN.</li>
* </ul>
*
* @param y a value
* @return sqrt(<i>this</i><sup>2</sup>&nbsp;+<i>y</i><sup>2</sup>)
* @exception DimensionMismatchException if number of free parameters or orders are inconsistent
*/
T hypot(T y)
throws DimensionMismatchException;
/** {@inheritDoc} */
@Override
T reciprocal();
/** Square root.
* @return square root of the instance
*/
T sqrt();
/** Cubic root.
* @return cubic root of the instance
*/
T cbrt();
/** N<sup>th</sup> root.
* @param n order of the root
* @return n<sup>th</sup> root of the instance
*/
T rootN(int n);
/** Power operation.
* @param p power to apply
* @return this<sup>p</sup>
*/
T pow(double p);
/** Integer power operation.
* @param n power to apply
* @return this<sup>n</sup>
*/
T pow(int n);
/** Power operation.
* @param e exponent
* @return this<sup>e</sup>
* @exception DimensionMismatchException if number of free parameters or orders are inconsistent
*/
T pow(T e)
throws DimensionMismatchException;
/** Exponential.
* @return exponential of the instance
*/
T exp();
/** Exponential minus 1.
* @return exponential minus one of the instance
*/
T expm1();
/** Natural logarithm.
* @return logarithm of the instance
*/
T log();
/** Shifted natural logarithm.
* @return logarithm of one plus the instance
*/
T log1p();
/** Base 10 logarithm.
* @return base 10 logarithm of the instance
* @since 4.0
*/
T log10();
/** Cosine operation.
* @return cos(this)
*/
T cos();
/** Sine operation.
* @return sin(this)
*/
T sin();
/** Tangent operation.
* @return tan(this)
*/
T tan();
/** Arc cosine operation.
* @return acos(this)
*/
T acos();
/** Arc sine operation.
* @return asin(this)
*/
T asin();
/** Arc tangent operation.
* @return atan(this)
*/
T atan();
/** Two arguments arc tangent operation.
* @param x second argument of the arc tangent
* @return atan2(this, x)
* @exception DimensionMismatchException if number of free parameters or orders are inconsistent
*/
T atan2(T x)
throws DimensionMismatchException;
/** Hyperbolic cosine operation.
* @return cosh(this)
*/
T cosh();
/** Hyperbolic sine operation.
* @return sinh(this)
*/
T sinh();
/** Hyperbolic tangent operation.
* @return tanh(this)
*/
T tanh();
/** Inverse hyperbolic cosine operation.
* @return acosh(this)
*/
T acosh();
/** Inverse hyperbolic sine operation.
* @return asin(this)
*/
T asinh();
/** Inverse hyperbolic tangent operation.
* @return atanh(this)
*/
T atanh();
/**
* Compute a linear combination.
* @param a Factors.
* @param b Factors.
* @return <code>&Sigma;<sub>i</sub> a<sub>i</sub> b<sub>i</sub></code>.
* @throws DimensionMismatchException if arrays dimensions don't match
* @since 3.2
*/
T linearCombination(T[] a, T[] b)
throws DimensionMismatchException;
/**
* Compute a linear combination.
* @param a Factors.
* @param b Factors.
* @return <code>&Sigma;<sub>i</sub> a<sub>i</sub> b<sub>i</sub></code>.
* @throws DimensionMismatchException if arrays dimensions don't match
* @since 3.2
*/
T linearCombination(double[] a, T[] b)
throws DimensionMismatchException;
/**
* Compute a linear combination.
* @param a1 first factor of the first term
* @param b1 second factor of the first term
* @param a2 first factor of the second term
* @param b2 second factor of the second term
* @return a<sub>1</sub>&times;b<sub>1</sub> +
* a<sub>2</sub>&times;b<sub>2</sub>
* @see #linearCombination(Object, Object, Object, Object, Object, Object)
* @see #linearCombination(Object, Object, Object, Object, Object, Object, Object, Object)
* @since 3.2
*/
T linearCombination(T a1, T b1, T a2, T b2);
/**
* Compute a linear combination.
* @param a1 first factor of the first term
* @param b1 second factor of the first term
* @param a2 first factor of the second term
* @param b2 second factor of the second term
* @return a<sub>1</sub>&times;b<sub>1</sub> +
* a<sub>2</sub>&times;b<sub>2</sub>
* @see #linearCombination(double, Object, double, Object, double, Object)
* @see #linearCombination(double, Object, double, Object, double, Object, double, Object)
* @since 3.2
*/
T linearCombination(double a1, T b1, double a2, T b2);
/**
* Compute a linear combination.
* @param a1 first factor of the first term
* @param b1 second factor of the first term
* @param a2 first factor of the second term
* @param b2 second factor of the second term
* @param a3 first factor of the third term
* @param b3 second factor of the third term
* @return a<sub>1</sub>&times;b<sub>1</sub> +
* a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
* @see #linearCombination(Object, Object, Object, Object)
* @see #linearCombination(Object, Object, Object, Object, Object, Object, Object, Object)
* @since 3.2
*/
T linearCombination(T a1, T b1, T a2, T b2, T a3, T b3);
/**
* Compute a linear combination.
* @param a1 first factor of the first term
* @param b1 second factor of the first term
* @param a2 first factor of the second term
* @param b2 second factor of the second term
* @param a3 first factor of the third term
* @param b3 second factor of the third term
* @return a<sub>1</sub>&times;b<sub>1</sub> +
* a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
* @see #linearCombination(double, Object, double, Object)
* @see #linearCombination(double, Object, double, Object, double, Object, double, Object)
* @since 3.2
*/
T linearCombination(double a1, T b1, double a2, T b2, double a3, T b3);
/**
* Compute a linear combination.
* @param a1 first factor of the first term
* @param b1 second factor of the first term
* @param a2 first factor of the second term
* @param b2 second factor of the second term
* @param a3 first factor of the third term
* @param b3 second factor of the third term
* @param a4 first factor of the third term
* @param b4 second factor of the third term
* @return a<sub>1</sub>&times;b<sub>1</sub> +
* a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub> +
* a<sub>4</sub>&times;b<sub>4</sub>
* @see #linearCombination(Object, Object, Object, Object)
* @see #linearCombination(Object, Object, Object, Object, Object, Object)
* @since 3.2
*/
T linearCombination(T a1, T b1, T a2, T b2, T a3, T b3, T a4, T b4);
/**
* Compute a linear combination.
* @param a1 first factor of the first term
* @param b1 second factor of the first term
* @param a2 first factor of the second term
* @param b2 second factor of the second term
* @param a3 first factor of the third term
* @param b3 second factor of the third term
* @param a4 first factor of the third term
* @param b4 second factor of the third term
* @return a<sub>1</sub>&times;b<sub>1</sub> +
* a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub> +
* a<sub>4</sub>&times;b<sub>4</sub>
* @see #linearCombination(double, Object, double, Object)
* @see #linearCombination(double, Object, double, Object, double, Object)
* @since 3.2
*/
T linearCombination(double a1, T b1, double a2, T b2, double a3, T b3, double a4, T b4);
}

View File

@ -1,35 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis;
/**
* An interface representing a bivariate real function.
*
* @since 2.1
*/
public interface BivariateFunction {
/**
* Compute the value for the function.
*
* @param x Abscissa for which the function value should be computed.
* @param y Ordinate for which the function value should be computed.
* @return the value.
*/
double value(double x, double y);
}

View File

@ -1,544 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis;
import org.apache.commons.numbers.arrays.LinearCombination;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.MultivariateDifferentiableFunction;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.analysis.function.Identity;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.NumberIsTooLargeException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
/**
* Utilities for manipulating function objects.
*
* @since 3.0
*/
public class FunctionUtils {
/**
* Class only contains static methods.
*/
private FunctionUtils() {}
/**
* Composes functions.
* <p>
* The functions in the argument list are composed sequentially, in the
* given order. For example, compose(f1,f2,f3) acts like f1(f2(f3(x))).</p>
*
* @param f List of functions.
* @return the composite function.
*/
public static UnivariateFunction compose(final UnivariateFunction ... f) {
return new UnivariateFunction() {
/** {@inheritDoc} */
@Override
public double value(double x) {
double r = x;
for (int i = f.length - 1; i >= 0; i--) {
r = f[i].value(r);
}
return r;
}
};
}
/**
* Composes functions.
* <p>
* The functions in the argument list are composed sequentially, in the
* given order. For example, compose(f1,f2,f3) acts like f1(f2(f3(x))).</p>
*
* @param f List of functions.
* @return the composite function.
* @since 3.1
*/
public static UnivariateDifferentiableFunction compose(final UnivariateDifferentiableFunction ... f) {
return new UnivariateDifferentiableFunction() {
/** {@inheritDoc} */
@Override
public double value(final double t) {
double r = t;
for (int i = f.length - 1; i >= 0; i--) {
r = f[i].value(r);
}
return r;
}
/** {@inheritDoc} */
@Override
public DerivativeStructure value(final DerivativeStructure t) {
DerivativeStructure r = t;
for (int i = f.length - 1; i >= 0; i--) {
r = f[i].value(r);
}
return r;
}
};
}
/**
* Adds functions.
*
* @param f List of functions.
* @return a function that computes the sum of the functions.
*/
public static UnivariateFunction add(final UnivariateFunction ... f) {
return new UnivariateFunction() {
/** {@inheritDoc} */
@Override
public double value(double x) {
double r = f[0].value(x);
for (int i = 1; i < f.length; i++) {
r += f[i].value(x);
}
return r;
}
};
}
/**
* Adds functions.
*
* @param f List of functions.
* @return a function that computes the sum of the functions.
* @since 3.1
*/
public static UnivariateDifferentiableFunction add(final UnivariateDifferentiableFunction ... f) {
return new UnivariateDifferentiableFunction() {
/** {@inheritDoc} */
@Override
public double value(final double t) {
double r = f[0].value(t);
for (int i = 1; i < f.length; i++) {
r += f[i].value(t);
}
return r;
}
/** {@inheritDoc}
* @throws DimensionMismatchException if functions are not consistent with each other
*/
@Override
public DerivativeStructure value(final DerivativeStructure t)
throws DimensionMismatchException {
DerivativeStructure r = f[0].value(t);
for (int i = 1; i < f.length; i++) {
r = r.add(f[i].value(t));
}
return r;
}
};
}
/**
* Multiplies functions.
*
* @param f List of functions.
* @return a function that computes the product of the functions.
*/
public static UnivariateFunction multiply(final UnivariateFunction ... f) {
return new UnivariateFunction() {
/** {@inheritDoc} */
@Override
public double value(double x) {
double r = f[0].value(x);
for (int i = 1; i < f.length; i++) {
r *= f[i].value(x);
}
return r;
}
};
}
/**
* Multiplies functions.
*
* @param f List of functions.
* @return a function that computes the product of the functions.
* @since 3.1
*/
public static UnivariateDifferentiableFunction multiply(final UnivariateDifferentiableFunction ... f) {
return new UnivariateDifferentiableFunction() {
/** {@inheritDoc} */
@Override
public double value(final double t) {
double r = f[0].value(t);
for (int i = 1; i < f.length; i++) {
r *= f[i].value(t);
}
return r;
}
/** {@inheritDoc} */
@Override
public DerivativeStructure value(final DerivativeStructure t) {
DerivativeStructure r = f[0].value(t);
for (int i = 1; i < f.length; i++) {
r = r.multiply(f[i].value(t));
}
return r;
}
};
}
/**
* Returns the univariate function
* {@code h(x) = combiner(f(x), g(x)).}
*
* @param combiner Combiner function.
* @param f Function.
* @param g Function.
* @return the composite function.
*/
public static UnivariateFunction combine(final BivariateFunction combiner,
final UnivariateFunction f,
final UnivariateFunction g) {
return new UnivariateFunction() {
/** {@inheritDoc} */
@Override
public double value(double x) {
return combiner.value(f.value(x), g.value(x));
}
};
}
/**
* Returns a MultivariateFunction h(x[]) defined by <pre> <code>
* h(x[]) = combiner(...combiner(combiner(initialValue,f(x[0])),f(x[1]))...),f(x[x.length-1]))
* </code></pre>
*
* @param combiner Combiner function.
* @param f Function.
* @param initialValue Initial value.
* @return a collector function.
*/
public static MultivariateFunction collector(final BivariateFunction combiner,
final UnivariateFunction f,
final double initialValue) {
return new MultivariateFunction() {
/** {@inheritDoc} */
@Override
public double value(double[] point) {
double result = combiner.value(initialValue, f.value(point[0]));
for (int i = 1; i < point.length; i++) {
result = combiner.value(result, f.value(point[i]));
}
return result;
}
};
}
/**
* Returns a MultivariateFunction h(x[]) defined by <pre> <code>
* h(x[]) = combiner(...combiner(combiner(initialValue,x[0]),x[1])...),x[x.length-1])
* </code></pre>
*
* @param combiner Combiner function.
* @param initialValue Initial value.
* @return a collector function.
*/
public static MultivariateFunction collector(final BivariateFunction combiner,
final double initialValue) {
return collector(combiner, new Identity(), initialValue);
}
/**
* Creates a unary function by fixing the first argument of a binary function.
*
* @param f Binary function.
* @param fixed value to which the first argument of {@code f} is set.
* @return the unary function h(x) = f(fixed, x)
*/
public static UnivariateFunction fix1stArgument(final BivariateFunction f,
final double fixed) {
return new UnivariateFunction() {
/** {@inheritDoc} */
@Override
public double value(double x) {
return f.value(fixed, x);
}
};
}
/**
* Creates a unary function by fixing the second argument of a binary function.
*
* @param f Binary function.
* @param fixed value to which the second argument of {@code f} is set.
* @return the unary function h(x) = f(x, fixed)
*/
public static UnivariateFunction fix2ndArgument(final BivariateFunction f,
final double fixed) {
return new UnivariateFunction() {
/** {@inheritDoc} */
@Override
public double value(double x) {
return f.value(x, fixed);
}
};
}
/**
* Samples the specified univariate real function on the specified interval.
* <p>
* The interval is divided equally into {@code n} sections and sample points
* are taken from {@code min} to {@code max - (max - min) / n}; therefore
* {@code f} is not sampled at the upper bound {@code max}.</p>
*
* @param f Function to be sampled
* @param min Lower bound of the interval (included).
* @param max Upper bound of the interval (excluded).
* @param n Number of sample points.
* @return the array of samples.
* @throws NumberIsTooLargeException if the lower bound {@code min} is
* greater than, or equal to the upper bound {@code max}.
* @throws NotStrictlyPositiveException if the number of sample points
* {@code n} is negative.
*/
public static double[] sample(UnivariateFunction f, double min, double max, int n)
throws NumberIsTooLargeException, NotStrictlyPositiveException {
if (n <= 0) {
throw new NotStrictlyPositiveException(
LocalizedFormats.NOT_POSITIVE_NUMBER_OF_SAMPLES,
Integer.valueOf(n));
}
if (min >= max) {
throw new NumberIsTooLargeException(min, max, false);
}
final double[] s = new double[n];
final double h = (max - min) / n;
for (int i = 0; i < n; i++) {
s[i] = f.value(min + i * h);
}
return s;
}
/** Convert regular functions to {@link UnivariateDifferentiableFunction}.
* <p>
* This method handle the case with one free parameter and several derivatives.
* For the case with several free parameters and only first order derivatives,
* see {@link #toDifferentiable(MultivariateFunction, MultivariateVectorFunction)}.
* There are no direct support for intermediate cases, with several free parameters
* and order 2 or more derivatives, as is would be difficult to specify all the
* cross derivatives.
* </p>
* <p>
* Note that the derivatives are expected to be computed only with respect to the
* raw parameter x of the base function, i.e. they are df/dx, df<sup>2</sup>/dx<sup>2</sup>, ...
* Even if the built function is later used in a composition like f(sin(t)), the provided
* derivatives should <em>not</em> apply the composition with sine and its derivatives by
* themselves. The composition will be done automatically here and the result will properly
* contain f(sin(t)), df(sin(t))/dt, df<sup>2</sup>(sin(t))/dt<sup>2</sup> despite the
* provided derivatives functions know nothing about the sine function.
* </p>
* @param f base function f(x)
* @param derivatives derivatives of the base function, in increasing differentiation order
* @return a differentiable function with value and all specified derivatives
* @see #toDifferentiable(MultivariateFunction, MultivariateVectorFunction)
* @see #derivative(UnivariateDifferentiableFunction, int)
*/
public static UnivariateDifferentiableFunction toDifferentiable(final UnivariateFunction f,
final UnivariateFunction ... derivatives) {
return new UnivariateDifferentiableFunction() {
/** {@inheritDoc} */
@Override
public double value(final double x) {
return f.value(x);
}
/** {@inheritDoc} */
@Override
public DerivativeStructure value(final DerivativeStructure x) {
if (x.getOrder() > derivatives.length) {
throw new NumberIsTooLargeException(x.getOrder(), derivatives.length, true);
}
final double[] packed = new double[x.getOrder() + 1];
packed[0] = f.value(x.getValue());
for (int i = 0; i < x.getOrder(); ++i) {
packed[i + 1] = derivatives[i].value(x.getValue());
}
return x.compose(packed);
}
};
}
/** Convert regular functions to {@link MultivariateDifferentiableFunction}.
* <p>
* This method handle the case with several free parameters and only first order derivatives.
* For the case with one free parameter and several derivatives,
* see {@link #toDifferentiable(UnivariateFunction, UnivariateFunction...)}.
* There are no direct support for intermediate cases, with several free parameters
* and order 2 or more derivatives, as is would be difficult to specify all the
* cross derivatives.
* </p>
* <p>
* Note that the gradient is expected to be computed only with respect to the
* raw parameter x of the base function, i.e. it is df/dx<sub>1</sub>, df/dx<sub>2</sub>, ...
* Even if the built function is later used in a composition like f(sin(t), cos(t)), the provided
* gradient should <em>not</em> apply the composition with sine or cosine and their derivative by
* itself. The composition will be done automatically here and the result will properly
* contain f(sin(t), cos(t)), df(sin(t), cos(t))/dt despite the provided derivatives functions
* know nothing about the sine or cosine functions.
* </p>
* @param f base function f(x)
* @param gradient gradient of the base function
* @return a differentiable function with value and gradient
* @see #toDifferentiable(UnivariateFunction, UnivariateFunction...)
* @see #derivative(MultivariateDifferentiableFunction, int[])
*/
public static MultivariateDifferentiableFunction toDifferentiable(final MultivariateFunction f,
final MultivariateVectorFunction gradient) {
return new MultivariateDifferentiableFunction() {
/** {@inheritDoc} */
@Override
public double value(final double[] point) {
return f.value(point);
}
/** {@inheritDoc} */
@Override
public DerivativeStructure value(final DerivativeStructure[] point) {
// set up the input parameters
final double[] dPoint = new double[point.length];
for (int i = 0; i < point.length; ++i) {
dPoint[i] = point[i].getValue();
if (point[i].getOrder() > 1) {
throw new NumberIsTooLargeException(point[i].getOrder(), 1, true);
}
}
// evaluate regular functions
final double v = f.value(dPoint);
final double[] dv = gradient.value(dPoint);
if (dv.length != point.length) {
// the gradient function is inconsistent
throw new DimensionMismatchException(dv.length, point.length);
}
// build the combined derivative
final int parameters = point[0].getFreeParameters();
final double[] partials = new double[point.length];
final double[] packed = new double[parameters + 1];
packed[0] = v;
final int orders[] = new int[parameters];
for (int i = 0; i < parameters; ++i) {
// we differentiate once with respect to parameter i
orders[i] = 1;
for (int j = 0; j < point.length; ++j) {
partials[j] = point[j].getPartialDerivative(orders);
}
orders[i] = 0;
// compose partial derivatives
packed[i + 1] = LinearCombination.value(dv, partials);
}
return new DerivativeStructure(parameters, 1, packed);
}
};
}
/** Convert an {@link UnivariateDifferentiableFunction} to an
* {@link UnivariateFunction} computing n<sup>th</sup> order derivative.
* <p>
* This converter is only a convenience method. Beware computing only one derivative does
* not save any computation as the original function will really be called under the hood.
* The derivative will be extracted from the full {@link DerivativeStructure} result.
* </p>
* @param f original function, with value and all its derivatives
* @param order of the derivative to extract
* @return function computing the derivative at required order
* @see #derivative(MultivariateDifferentiableFunction, int[])
* @see #toDifferentiable(UnivariateFunction, UnivariateFunction...)
*/
public static UnivariateFunction derivative(final UnivariateDifferentiableFunction f, final int order) {
return new UnivariateFunction() {
/** {@inheritDoc} */
@Override
public double value(final double x) {
final DerivativeStructure dsX = new DerivativeStructure(1, order, 0, x);
return f.value(dsX).getPartialDerivative(order);
}
};
}
/** Convert an {@link MultivariateDifferentiableFunction} to an
* {@link MultivariateFunction} computing n<sup>th</sup> order derivative.
* <p>
* This converter is only a convenience method. Beware computing only one derivative does
* not save any computation as the original function will really be called under the hood.
* The derivative will be extracted from the full {@link DerivativeStructure} result.
* </p>
* @param f original function, with value and all its derivatives
* @param orders of the derivative to extract, for each free parameters
* @return function computing the derivative at required order
* @see #derivative(UnivariateDifferentiableFunction, int)
* @see #toDifferentiable(MultivariateFunction, MultivariateVectorFunction)
*/
public static MultivariateFunction derivative(final MultivariateDifferentiableFunction f, final int[] orders) {
return new MultivariateFunction() {
/** {@inheritDoc} */
@Override
public double value(final double[] point) {
// the maximum differentiation order is the sum of all orders
int sumOrders = 0;
for (final int order : orders) {
sumOrders += order;
}
// set up the input parameters
final DerivativeStructure[] dsPoint = new DerivativeStructure[point.length];
for (int i = 0; i < point.length; ++i) {
dsPoint[i] = new DerivativeStructure(point.length, sumOrders, i, point[i]);
}
return f.value(dsPoint).getPartialDerivative(orders);
}
};
}
}

View File

@ -1,42 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis;
/**
* An interface representing a multivariate real function.
*
* @since 2.0
*/
public interface MultivariateFunction {
/**
* Compute the value for the function at the given point.
*
* @param point Point at which the function must be evaluated.
* @return the function value for the given point.
* @throws org.apache.commons.math4.exception.DimensionMismatchException
* if the parameter's dimension is wrong for the function being evaluated.
* @throws org.apache.commons.math4.exception.MathIllegalArgumentException
* when the activated method itself can ascertain that preconditions,
* specified in the API expressed at the level of the activated method,
* have been violated. In the vast majority of cases where Commons Math
* throws this exception, it is the result of argument checking of actual
* parameters immediately passed to a method.
*/
double value(double[] point);
}

View File

@ -1,35 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis;
/**
* An interface representing a multivariate matrix function.
* @since 2.0
*/
public interface MultivariateMatrixFunction {
/**
* Compute the value for the function at the given point.
* @param point point at which the function must be evaluated
* @return function value for the given point
* @exception IllegalArgumentException if point's dimension is wrong
*/
double[][] value(double[] point)
throws IllegalArgumentException;
}

View File

@ -1,35 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis;
/**
* An interface representing a multivariate vectorial function.
* @since 2.0
*/
public interface MultivariateVectorFunction {
/**
* Compute the value for the function at the given point.
* @param point point at which the function must be evaluated
* @return function value for the given point
* @exception IllegalArgumentException if point's dimension is wrong
*/
double[] value(double[] point)
throws IllegalArgumentException;
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis;
/**
* An interface representing a real function that depends on one independent
* variable plus some extra parameters.
*
* @since 3.0
*/
public interface ParametricUnivariateFunction {
/**
* Compute the value of the function.
*
* @param x Point for which the function value should be computed.
* @param parameters Function parameters.
* @return the value.
*/
double value(double x, double... parameters);
/**
* Compute the gradient of the function with respect to its parameters.
*
* @param x Point for which the function value should be computed.
* @param parameters Function parameters.
* @return the value.
*/
double[] gradient(double x, double... parameters);
}

View File

@ -1,86 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis;
import org.apache.commons.math4.RealFieldElement;
/**
* An interface representing a univariate real function.
* <p>
* When a <em>user-defined</em> function encounters an error during
* evaluation, the {@link #value(RealFieldElement) value} method should throw a
* <em>user-defined</em> unchecked exception.</p>
* <p>
* The following code excerpt shows the recommended way to do that using
* a root solver as an example, but the same construct is applicable to
* ODE integrators or optimizers.
*
* <pre>
* private static class LocalException extends RuntimeException {
* // The x value that caused the problem.
* private final SomeFieldType x;
*
* public LocalException(SomeFieldType x) {
* this.x = x;
* }
*
* public double getX() {
* return x;
* }
* }
*
* private static class MyFunction implements FieldUnivariateFunction&lt;SomeFieldType&gt; {
* public SomeFieldType value(SomeFieldType x) {
* SomeFieldType y = hugeFormula(x);
* if (somethingBadHappens) {
* throw new LocalException(x);
* }
* return y;
* }
* }
*
* public void compute() {
* try {
* solver.solve(maxEval, new MyFunction(a, b, c), min, max);
* } catch (LocalException le) {
* // Retrieve the x value.
* }
* }
* </pre>
*<p>
* As shown, the exception is local to the user's code and it is guaranteed
* that Apache Commons Math will not catch it.</p>
*
* @param <T> the type of the field elements
* @since 3.6
* @see UnivariateFunction
*/
public interface RealFieldUnivariateFunction<T extends RealFieldElement<T>> {
/**
* Compute the value of the function.
*
* @param x Point at which the function value should be computed.
* @return the value of the function.
* @throws IllegalArgumentException when the activated method itself can
* ascertain that a precondition, specified in the API expressed at the
* level of the activated method, has been violated.
* When Commons Math throws an {@code IllegalArgumentException}, it is
* usually the consequence of checking the actual parameters passed to
* the method.
*/
T value(T x);
}

View File

@ -1,35 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis;
/**
* An interface representing a trivariate real function.
*
* @since 2.2
*/
public interface TrivariateFunction {
/**
* Compute the value for the function.
*
* @param x x-coordinate for which the function value should be computed.
* @param y y-coordinate for which the function value should be computed.
* @param z z-coordinate for which the function value should be computed.
* @return the value.
*/
double value(double x, double y, double z);
}

View File

@ -1,81 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis;
/**
* An interface representing a univariate real function.
* <p>
* When a <em>user-defined</em> function encounters an error during
* evaluation, the {@link #value(double) value} method should throw a
* <em>user-defined</em> unchecked exception.</p>
* <p>
* The following code excerpt shows the recommended way to do that using
* a root solver as an example, but the same construct is applicable to
* ODE integrators or optimizers.</p>
*
* <pre>
* private static class LocalException extends RuntimeException {
* // The x value that caused the problem.
* private final double x;
*
* public LocalException(double x) {
* this.x = x;
* }
*
* public double getX() {
* return x;
* }
* }
*
* private static class MyFunction implements UnivariateFunction {
* public double value(double x) {
* double y = hugeFormula(x);
* if (somethingBadHappens) {
* throw new LocalException(x);
* }
* return y;
* }
* }
*
* public void compute() {
* try {
* solver.solve(maxEval, new MyFunction(a, b, c), min, max);
* } catch (LocalException le) {
* // Retrieve the x value.
* }
* }
* </pre>
*
* As shown, the exception is local to the user's code and it is guaranteed
* that Apache Commons Math will not catch it.
*
*/
public interface UnivariateFunction {
/**
* Compute the value of the function.
*
* @param x Point at which the function value should be computed.
* @return the value of the function.
* @throws IllegalArgumentException when the activated method itself can
* ascertain that a precondition, specified in the API expressed at the
* level of the activated method, has been violated.
* When Commons Math throws an {@code IllegalArgumentException}, it is
* usually the consequence of checking the actual parameters passed to
* the method.
*/
double value(double x);
}

View File

@ -1,33 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis;
/**
* An interface representing a univariate matrix function.
*
* @since 2.0
*/
public interface UnivariateMatrixFunction {
/**
* Compute the value for the function.
* @param x the point for which the function value should be computed
* @return the value
*/
double[][] value(double x);
}

View File

@ -1,33 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis;
/**
* An interface representing a univariate vectorial function.
*
* @since 2.0
*/
public interface UnivariateVectorFunction {
/**
* Compute the value for the function.
* @param x the point for which the function value should be computed
* @return the value
*/
double[] value(double x);
}

View File

@ -1,393 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.differentiation;
import java.io.Serializable;
import org.apache.commons.math4.analysis.UnivariateFunction;
import org.apache.commons.math4.analysis.UnivariateMatrixFunction;
import org.apache.commons.math4.analysis.UnivariateVectorFunction;
import org.apache.commons.math4.exception.MathIllegalArgumentException;
import org.apache.commons.math4.exception.NotPositiveException;
import org.apache.commons.math4.exception.NumberIsTooLargeException;
import org.apache.commons.math4.exception.NumberIsTooSmallException;
import org.apache.commons.math4.util.FastMath;
/** Univariate functions differentiator using finite differences.
* <p>
* This class creates some wrapper objects around regular
* {@link UnivariateFunction univariate functions} (or {@link
* UnivariateVectorFunction univariate vector functions} or {@link
* UnivariateMatrixFunction univariate matrix functions}). These
* wrapper objects compute derivatives in addition to function
* values.
* </p>
* <p>
* The wrapper objects work by calling the underlying function on
* a sampling grid around the current point and performing polynomial
* interpolation. A finite differences scheme with n points is
* theoretically able to compute derivatives up to order n-1, but
* it is generally better to have a slight margin. The step size must
* also be small enough in order for the polynomial approximation to
* be good in the current point neighborhood, but it should not be too
* small because numerical instability appears quickly (there are several
* differences of close points). Choosing the number of points and
* the step size is highly problem dependent.
* </p>
* <p>
* As an example of good and bad settings, lets consider the quintic
* polynomial function {@code f(x) = (x-1)*(x-0.5)*x*(x+0.5)*(x+1)}.
* Since it is a polynomial, finite differences with at least 6 points
* should theoretically recover the exact same polynomial and hence
* compute accurate derivatives for any order. However, due to numerical
* errors, we get the following results for a 7 points finite differences
* for abscissae in the [-10, 10] range:
* <ul>
* <li>step size = 0.25, second order derivative error about 9.97e-10</li>
* <li>step size = 0.25, fourth order derivative error about 5.43e-8</li>
* <li>step size = 1.0e-6, second order derivative error about 148</li>
* <li>step size = 1.0e-6, fourth order derivative error about 6.35e+14</li>
* </ul>
* <p>
* This example shows that the small step size is really bad, even simply
* for second order derivative!</p>
*
* @since 3.1
*/
public class FiniteDifferencesDifferentiator
implements UnivariateFunctionDifferentiator, UnivariateVectorFunctionDifferentiator,
UnivariateMatrixFunctionDifferentiator, Serializable {
/** Serializable UID. */
private static final long serialVersionUID = 20120917L;
/** Number of points to use. */
private final int nbPoints;
/** Step size. */
private final double stepSize;
/** Half sample span. */
private final double halfSampleSpan;
/** Lower bound for independent variable. */
private final double tMin;
/** Upper bound for independent variable. */
private final double tMax;
/**
* Build a differentiator with number of points and step size when independent variable is unbounded.
* <p>
* Beware that wrong settings for the finite differences differentiator
* can lead to highly unstable and inaccurate results, especially for
* high derivation orders. Using very small step sizes is often a
* <em>bad</em> idea.
* </p>
* @param nbPoints number of points to use
* @param stepSize step size (gap between each point)
* @exception NotPositiveException if {@code stepsize <= 0} (note that
* {@link NotPositiveException} extends {@link NumberIsTooSmallException})
* @exception NumberIsTooSmallException {@code nbPoint <= 1}
*/
public FiniteDifferencesDifferentiator(final int nbPoints, final double stepSize)
throws NotPositiveException, NumberIsTooSmallException {
this(nbPoints, stepSize, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
}
/**
* Build a differentiator with number of points and step size when independent variable is bounded.
* <p>
* When the independent variable is bounded (tLower &lt; t &lt; tUpper), the sampling
* points used for differentiation will be adapted to ensure the constraint holds
* even near the boundaries. This means the sample will not be centered anymore in
* these cases. At an extreme case, computing derivatives exactly at the lower bound
* will lead the sample to be entirely on the right side of the derivation point.
* </p>
* <p>
* Note that the boundaries are considered to be excluded for function evaluation.
* </p>
* <p>
* Beware that wrong settings for the finite differences differentiator
* can lead to highly unstable and inaccurate results, especially for
* high derivation orders. Using very small step sizes is often a
* <em>bad</em> idea.
* </p>
* @param nbPoints number of points to use
* @param stepSize step size (gap between each point)
* @param tLower lower bound for independent variable (may be {@code Double.NEGATIVE_INFINITY}
* if there are no lower bounds)
* @param tUpper upper bound for independent variable (may be {@code Double.POSITIVE_INFINITY}
* if there are no upper bounds)
* @exception NotPositiveException if {@code stepsize <= 0} (note that
* {@link NotPositiveException} extends {@link NumberIsTooSmallException})
* @exception NumberIsTooSmallException {@code nbPoint <= 1}
* @exception NumberIsTooLargeException {@code stepSize * (nbPoints - 1) >= tUpper - tLower}
*/
public FiniteDifferencesDifferentiator(final int nbPoints, final double stepSize,
final double tLower, final double tUpper)
throws NotPositiveException, NumberIsTooSmallException, NumberIsTooLargeException {
if (nbPoints <= 1) {
throw new NumberIsTooSmallException(stepSize, 1, false);
}
this.nbPoints = nbPoints;
if (stepSize <= 0) {
throw new NotPositiveException(stepSize);
}
this.stepSize = stepSize;
halfSampleSpan = 0.5 * stepSize * (nbPoints - 1);
if (2 * halfSampleSpan >= tUpper - tLower) {
throw new NumberIsTooLargeException(2 * halfSampleSpan, tUpper - tLower, false);
}
final double safety = FastMath.ulp(halfSampleSpan);
this.tMin = tLower + halfSampleSpan + safety;
this.tMax = tUpper - halfSampleSpan - safety;
}
/**
* Get the number of points to use.
* @return number of points to use
*/
public int getNbPoints() {
return nbPoints;
}
/**
* Get the step size.
* @return step size
*/
public double getStepSize() {
return stepSize;
}
/**
* Evaluate derivatives from a sample.
* <p>
* Evaluation is done using divided differences.
* </p>
* @param t evaluation abscissa value and derivatives
* @param t0 first sample point abscissa
* @param y function values sample {@code y[i] = f(t[i]) = f(t0 + i * stepSize)}
* @return value and derivatives at {@code t}
* @exception NumberIsTooLargeException if the requested derivation order
* is larger or equal to the number of points
*/
private DerivativeStructure evaluate(final DerivativeStructure t, final double t0,
final double[] y)
throws NumberIsTooLargeException {
// create divided differences diagonal arrays
final double[] top = new double[nbPoints];
final double[] bottom = new double[nbPoints];
for (int i = 0; i < nbPoints; ++i) {
// update the bottom diagonal of the divided differences array
bottom[i] = y[i];
for (int j = 1; j <= i; ++j) {
bottom[i - j] = (bottom[i - j + 1] - bottom[i - j]) / (j * stepSize);
}
// update the top diagonal of the divided differences array
top[i] = bottom[0];
}
// evaluate interpolation polynomial (represented by top diagonal) at t
final int order = t.getOrder();
final int parameters = t.getFreeParameters();
final double[] derivatives = t.getAllDerivatives();
final double dt0 = t.getValue() - t0;
DerivativeStructure interpolation = new DerivativeStructure(parameters, order, 0.0);
DerivativeStructure monomial = null;
for (int i = 0; i < nbPoints; ++i) {
if (i == 0) {
// start with monomial(t) = 1
monomial = new DerivativeStructure(parameters, order, 1.0);
} else {
// monomial(t) = (t - t0) * (t - t1) * ... * (t - t(i-1))
derivatives[0] = dt0 - (i - 1) * stepSize;
final DerivativeStructure deltaX = new DerivativeStructure(parameters, order, derivatives);
monomial = monomial.multiply(deltaX);
}
interpolation = interpolation.add(monomial.multiply(top[i]));
}
return interpolation;
}
/** {@inheritDoc}
* <p>The returned object cannot compute derivatives to arbitrary orders. The
* value function will throw a {@link NumberIsTooLargeException} if the requested
* derivation order is larger or equal to the number of points.
* </p>
*/
@Override
public UnivariateDifferentiableFunction differentiate(final UnivariateFunction function) {
return new UnivariateDifferentiableFunction() {
/** {@inheritDoc} */
@Override
public double value(final double x) throws MathIllegalArgumentException {
return function.value(x);
}
/** {@inheritDoc} */
@Override
public DerivativeStructure value(final DerivativeStructure t)
throws MathIllegalArgumentException {
// check we can achieve the requested derivation order with the sample
if (t.getOrder() >= nbPoints) {
throw new NumberIsTooLargeException(t.getOrder(), nbPoints, false);
}
// compute sample position, trying to be centered if possible
final double t0 = FastMath.max(FastMath.min(t.getValue(), tMax), tMin) - halfSampleSpan;
// compute sample points
final double[] y = new double[nbPoints];
for (int i = 0; i < nbPoints; ++i) {
y[i] = function.value(t0 + i * stepSize);
}
// evaluate derivatives
return evaluate(t, t0, y);
}
};
}
/** {@inheritDoc}
* <p>The returned object cannot compute derivatives to arbitrary orders. The
* value function will throw a {@link NumberIsTooLargeException} if the requested
* derivation order is larger or equal to the number of points.
* </p>
*/
@Override
public UnivariateDifferentiableVectorFunction differentiate(final UnivariateVectorFunction function) {
return new UnivariateDifferentiableVectorFunction() {
/** {@inheritDoc} */
@Override
public double[]value(final double x) throws MathIllegalArgumentException {
return function.value(x);
}
/** {@inheritDoc} */
@Override
public DerivativeStructure[] value(final DerivativeStructure t)
throws MathIllegalArgumentException {
// check we can achieve the requested derivation order with the sample
if (t.getOrder() >= nbPoints) {
throw new NumberIsTooLargeException(t.getOrder(), nbPoints, false);
}
// compute sample position, trying to be centered if possible
final double t0 = FastMath.max(FastMath.min(t.getValue(), tMax), tMin) - halfSampleSpan;
// compute sample points
double[][] y = null;
for (int i = 0; i < nbPoints; ++i) {
final double[] v = function.value(t0 + i * stepSize);
if (i == 0) {
y = new double[v.length][nbPoints];
}
for (int j = 0; j < v.length; ++j) {
y[j][i] = v[j];
}
}
// evaluate derivatives
final DerivativeStructure[] value = new DerivativeStructure[y.length];
for (int j = 0; j < value.length; ++j) {
value[j] = evaluate(t, t0, y[j]);
}
return value;
}
};
}
/** {@inheritDoc}
* <p>The returned object cannot compute derivatives to arbitrary orders. The
* value function will throw a {@link NumberIsTooLargeException} if the requested
* derivation order is larger or equal to the number of points.
* </p>
*/
@Override
public UnivariateDifferentiableMatrixFunction differentiate(final UnivariateMatrixFunction function) {
return new UnivariateDifferentiableMatrixFunction() {
/** {@inheritDoc} */
@Override
public double[][] value(final double x) throws MathIllegalArgumentException {
return function.value(x);
}
/** {@inheritDoc} */
@Override
public DerivativeStructure[][] value(final DerivativeStructure t)
throws MathIllegalArgumentException {
// check we can achieve the requested derivation order with the sample
if (t.getOrder() >= nbPoints) {
throw new NumberIsTooLargeException(t.getOrder(), nbPoints, false);
}
// compute sample position, trying to be centered if possible
final double t0 = FastMath.max(FastMath.min(t.getValue(), tMax), tMin) - halfSampleSpan;
// compute sample points
double[][][] y = null;
for (int i = 0; i < nbPoints; ++i) {
final double[][] v = function.value(t0 + i * stepSize);
if (i == 0) {
y = new double[v.length][v[0].length][nbPoints];
}
for (int j = 0; j < v.length; ++j) {
for (int k = 0; k < v[j].length; ++k) {
y[j][k][i] = v[j][k];
}
}
}
// evaluate derivatives
final DerivativeStructure[][] value = new DerivativeStructure[y.length][y[0].length];
for (int j = 0; j < value.length; ++j) {
for (int k = 0; k < y[j].length; ++k) {
value[j][k] = evaluate(t, t0, y[j][k]);
}
}
return value;
}
};
}
}

View File

@ -1,66 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.differentiation;
import org.apache.commons.math4.analysis.MultivariateVectorFunction;
/** Class representing the gradient of a multivariate function.
* <p>
* The vectorial components of the function represent the derivatives
* with respect to each function parameters.
* </p>
* @since 3.1
*/
public class GradientFunction implements MultivariateVectorFunction {
/** Underlying real-valued function. */
private final MultivariateDifferentiableFunction f;
/** Simple constructor.
* @param f underlying real-valued function
*/
public GradientFunction(final MultivariateDifferentiableFunction f) {
this.f = f;
}
/** {@inheritDoc} */
@Override
public double[] value(double[] point) {
// set up parameters
final DerivativeStructure[] dsX = new DerivativeStructure[point.length];
for (int i = 0; i < point.length; ++i) {
dsX[i] = new DerivativeStructure(point.length, 1, i, point[i]);
}
// compute the derivatives
final DerivativeStructure dsY = f.value(dsX);
// extract the gradient
final double[] y = new double[point.length];
final int[] orders = new int[point.length];
for (int i = 0; i < point.length; ++i) {
orders[i] = 1;
y[i] = dsY.getPartialDerivative(orders);
orders[i] = 0;
}
return y;
}
}

View File

@ -1,70 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.differentiation;
import org.apache.commons.math4.analysis.MultivariateMatrixFunction;
/** Class representing the Jacobian of a multivariate vector function.
* <p>
* The rows iterate on the model functions while the columns iterate on the parameters; thus,
* the numbers of rows is equal to the dimension of the underlying function vector
* value and the number of columns is equal to the number of free parameters of
* the underlying function.
* </p>
* @since 3.1
*/
public class JacobianFunction implements MultivariateMatrixFunction {
/** Underlying vector-valued function. */
private final MultivariateDifferentiableVectorFunction f;
/** Simple constructor.
* @param f underlying vector-valued function
*/
public JacobianFunction(final MultivariateDifferentiableVectorFunction f) {
this.f = f;
}
/** {@inheritDoc} */
@Override
public double[][] value(double[] point) {
// set up parameters
final DerivativeStructure[] dsX = new DerivativeStructure[point.length];
for (int i = 0; i < point.length; ++i) {
dsX[i] = new DerivativeStructure(point.length, 1, i, point[i]);
}
// compute the derivatives
final DerivativeStructure[] dsY = f.value(dsX);
// extract the Jacobian
final double[][] y = new double[dsY.length][point.length];
final int[] orders = new int[point.length];
for (int i = 0; i < dsY.length; ++i) {
for (int j = 0; j < point.length; ++j) {
orders[j] = 1;
y[i][j] = dsY[i].getPartialDerivative(orders);
orders[j] = 0;
}
}
return y;
}
}

View File

@ -1,42 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.differentiation;
import org.apache.commons.math4.analysis.MultivariateFunction;
import org.apache.commons.math4.exception.MathIllegalArgumentException;
/**
* Extension of {@link MultivariateFunction} representing a
* multivariate differentiable real function.
* @since 3.1
*/
public interface MultivariateDifferentiableFunction extends MultivariateFunction {
/**
* Compute the value for the function at the given point.
*
* @param point Point at which the function must be evaluated.
* @return the function value for the given point.
* @exception MathIllegalArgumentException if {@code point} does not
* satisfy the function's constraints (wrong dimension, argument out of bound,
* or unsupported derivative order for example)
*/
DerivativeStructure value(DerivativeStructure[] point)
throws MathIllegalArgumentException;
}

View File

@ -1,43 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.differentiation;
import org.apache.commons.math4.analysis.MultivariateVectorFunction;
import org.apache.commons.math4.exception.MathIllegalArgumentException;
/**
* Extension of {@link MultivariateVectorFunction} representing a
* multivariate differentiable vectorial function.
* @since 3.1
*/
public interface MultivariateDifferentiableVectorFunction
extends MultivariateVectorFunction {
/**
* Compute the value for the function at the given point.
* @param point point at which the function must be evaluated
* @return function value for the given point
* @exception MathIllegalArgumentException if {@code point} does not
* satisfy the function's constraints (wrong dimension, argument out of bound,
* or unsupported derivative order for example)
*/
DerivativeStructure[] value(DerivativeStructure[] point)
throws MathIllegalArgumentException;
}

View File

@ -1,937 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.differentiation;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.numbers.arrays.LinearCombination;
import org.apache.commons.numbers.core.Precision;
import org.apache.commons.math4.Field;
import org.apache.commons.math4.FieldElement;
import org.apache.commons.math4.RealFieldElement;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.util.FastMath;
import org.apache.commons.math4.util.MathUtils;
/**
* First derivative computation with large number of variables.
* <p>
* This class plays a similar role to {@link DerivativeStructure}, with
* a focus on efficiency when dealing with large number of independent variables
* and most computation depend only on a few of them, and when only first derivative
* is desired. When these conditions are met, this class should be much faster than
* {@link DerivativeStructure} and use less memory.
* </p>
*
* @since 3.3
*/
public class SparseGradient implements RealFieldElement<SparseGradient>, Serializable {
/** Serializable UID. */
private static final long serialVersionUID = 20131025L;
/** Value of the calculation. */
private double value;
/** Stored derivative, each key representing a different independent variable. */
private final Map<Integer, Double> derivatives;
/** Internal constructor.
* @param value value of the function
* @param derivatives derivatives map, a deep copy will be performed,
* so the map given here will remain safe from changes in the new instance,
* may be null to create an empty derivatives map, i.e. a constant value
*/
private SparseGradient(final double value, final Map<Integer, Double> derivatives) {
this.value = value;
this.derivatives = new HashMap<>();
if (derivatives != null) {
this.derivatives.putAll(derivatives);
}
}
/** Internal constructor.
* @param value value of the function
* @param scale scaling factor to apply to all derivatives
* @param derivatives derivatives map, a deep copy will be performed,
* so the map given here will remain safe from changes in the new instance,
* may be null to create an empty derivatives map, i.e. a constant value
*/
private SparseGradient(final double value, final double scale,
final Map<Integer, Double> derivatives) {
this.value = value;
this.derivatives = new HashMap<>();
if (derivatives != null) {
for (final Map.Entry<Integer, Double> entry : derivatives.entrySet()) {
this.derivatives.put(entry.getKey(), scale * entry.getValue());
}
}
}
/** Factory method creating a constant.
* @param value value of the constant
* @return a new instance
*/
public static SparseGradient createConstant(final double value) {
return new SparseGradient(value, Collections.<Integer, Double> emptyMap());
}
/** Factory method creating an independent variable.
* @param idx index of the variable
* @param value value of the variable
* @return a new instance
*/
public static SparseGradient createVariable(final int idx, final double value) {
return new SparseGradient(value, Collections.singletonMap(idx, 1.0));
}
/**
* Find the number of variables.
* @return number of variables
*/
public int numVars() {
return derivatives.size();
}
/**
* Get the derivative with respect to a particular index variable.
*
* @param index index to differentiate with.
* @return derivative with respect to a particular index variable
*/
public double getDerivative(final int index) {
final Double out = derivatives.get(index);
return (out == null) ? 0.0 : out;
}
/**
* Get the value of the function.
* @return value of the function.
*/
public double getValue() {
return value;
}
/** {@inheritDoc} */
@Override
public double getReal() {
return value;
}
/** {@inheritDoc} */
@Override
public SparseGradient add(final SparseGradient a) {
final SparseGradient out = new SparseGradient(value + a.value, derivatives);
for (Map.Entry<Integer, Double> entry : a.derivatives.entrySet()) {
final int id = entry.getKey();
final Double old = out.derivatives.get(id);
if (old == null) {
out.derivatives.put(id, entry.getValue());
} else {
out.derivatives.put(id, old + entry.getValue());
}
}
return out;
}
/**
* Add in place.
* <p>
* This method is designed to be faster when used multiple times in a loop.
* </p>
* <p>
* The instance is changed here, in order to not change the
* instance the {@link #add(SparseGradient)} method should
* be used.
* </p>
* @param a instance to add
*/
public void addInPlace(final SparseGradient a) {
value += a.value;
for (final Map.Entry<Integer, Double> entry : a.derivatives.entrySet()) {
final int id = entry.getKey();
final Double old = derivatives.get(id);
if (old == null) {
derivatives.put(id, entry.getValue());
} else {
derivatives.put(id, old + entry.getValue());
}
}
}
/** {@inheritDoc} */
@Override
public SparseGradient add(final double c) {
final SparseGradient out = new SparseGradient(value + c, derivatives);
return out;
}
/** {@inheritDoc} */
@Override
public SparseGradient subtract(final SparseGradient a) {
final SparseGradient out = new SparseGradient(value - a.value, derivatives);
for (Map.Entry<Integer, Double> entry : a.derivatives.entrySet()) {
final int id = entry.getKey();
final Double old = out.derivatives.get(id);
if (old == null) {
out.derivatives.put(id, -entry.getValue());
} else {
out.derivatives.put(id, old - entry.getValue());
}
}
return out;
}
/** {@inheritDoc} */
@Override
public SparseGradient subtract(double c) {
return new SparseGradient(value - c, derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient multiply(final SparseGradient a) {
final SparseGradient out =
new SparseGradient(value * a.value, Collections.<Integer, Double> emptyMap());
// Derivatives.
for (Map.Entry<Integer, Double> entry : derivatives.entrySet()) {
out.derivatives.put(entry.getKey(), a.value * entry.getValue());
}
for (Map.Entry<Integer, Double> entry : a.derivatives.entrySet()) {
final int id = entry.getKey();
final Double old = out.derivatives.get(id);
if (old == null) {
out.derivatives.put(id, value * entry.getValue());
} else {
out.derivatives.put(id, old + value * entry.getValue());
}
}
return out;
}
/**
* Multiply in place.
* <p>
* This method is designed to be faster when used multiple times in a loop.
* </p>
* <p>
* The instance is changed here, in order to not change the
* instance the {@link #add(SparseGradient)} method should
* be used.
* </p>
* @param a instance to multiply
*/
public void multiplyInPlace(final SparseGradient a) {
// Derivatives.
for (Map.Entry<Integer, Double> entry : derivatives.entrySet()) {
derivatives.put(entry.getKey(), a.value * entry.getValue());
}
for (Map.Entry<Integer, Double> entry : a.derivatives.entrySet()) {
final int id = entry.getKey();
final Double old = derivatives.get(id);
if (old == null) {
derivatives.put(id, value * entry.getValue());
} else {
derivatives.put(id, old + value * entry.getValue());
}
}
value *= a.value;
}
/** {@inheritDoc} */
@Override
public SparseGradient multiply(final double c) {
return new SparseGradient(value * c, c, derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient multiply(final int n) {
return new SparseGradient(value * n, n, derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient divide(final SparseGradient a) {
final SparseGradient out = new SparseGradient(value / a.value, Collections.<Integer, Double> emptyMap());
// Derivatives.
for (Map.Entry<Integer, Double> entry : derivatives.entrySet()) {
out.derivatives.put(entry.getKey(), entry.getValue() / a.value);
}
for (Map.Entry<Integer, Double> entry : a.derivatives.entrySet()) {
final int id = entry.getKey();
final Double old = out.derivatives.get(id);
if (old == null) {
out.derivatives.put(id, -out.value / a.value * entry.getValue());
} else {
out.derivatives.put(id, old - out.value / a.value * entry.getValue());
}
}
return out;
}
/** {@inheritDoc} */
@Override
public SparseGradient divide(final double c) {
return new SparseGradient(value / c, 1.0 / c, derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient negate() {
return new SparseGradient(-value, -1.0, derivatives);
}
/** {@inheritDoc} */
@Override
public Field<SparseGradient> getField() {
return new Field<SparseGradient>() {
/** {@inheritDoc} */
@Override
public SparseGradient getZero() {
return createConstant(0);
}
/** {@inheritDoc} */
@Override
public SparseGradient getOne() {
return createConstant(1);
}
/** {@inheritDoc} */
@Override
public Class<? extends FieldElement<SparseGradient>> getRuntimeClass() {
return SparseGradient.class;
}
};
}
/** {@inheritDoc} */
@Override
public SparseGradient remainder(final double a) {
return new SparseGradient(FastMath.IEEEremainder(value, a), derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient remainder(final SparseGradient a) {
// compute k such that lhs % rhs = lhs - k rhs
final double rem = FastMath.IEEEremainder(value, a.value);
final double k = FastMath.rint((value - rem) / a.value);
return subtract(a.multiply(k));
}
/** {@inheritDoc} */
@Override
public SparseGradient abs() {
if (Double.doubleToLongBits(value) < 0) {
// we use the bits representation to also handle -0.0
return negate();
} else {
return this;
}
}
/** {@inheritDoc} */
@Override
public SparseGradient ceil() {
return createConstant(FastMath.ceil(value));
}
/** {@inheritDoc} */
@Override
public SparseGradient floor() {
return createConstant(FastMath.floor(value));
}
/** {@inheritDoc} */
@Override
public SparseGradient rint() {
return createConstant(FastMath.rint(value));
}
/** {@inheritDoc} */
@Override
public long round() {
return FastMath.round(value);
}
/** {@inheritDoc} */
@Override
public SparseGradient signum() {
return createConstant(FastMath.signum(value));
}
/** {@inheritDoc} */
@Override
public SparseGradient copySign(final SparseGradient sign) {
final long m = Double.doubleToLongBits(value);
final long s = Double.doubleToLongBits(sign.value);
if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) { // Sign is currently OK
return this;
}
return negate(); // flip sign
}
/** {@inheritDoc} */
@Override
public SparseGradient copySign(final double sign) {
final long m = Double.doubleToLongBits(value);
final long s = Double.doubleToLongBits(sign);
if ((m >= 0 && s >= 0) || (m < 0 && s < 0)) { // Sign is currently OK
return this;
}
return negate(); // flip sign
}
/** {@inheritDoc} */
@Override
public SparseGradient scalb(final int n) {
final SparseGradient out = new SparseGradient(FastMath.scalb(value, n), Collections.<Integer, Double> emptyMap());
for (Map.Entry<Integer, Double> entry : derivatives.entrySet()) {
out.derivatives.put(entry.getKey(), FastMath.scalb(entry.getValue(), n));
}
return out;
}
/** {@inheritDoc} */
@Override
public SparseGradient hypot(final SparseGradient y) {
if (Double.isInfinite(value) || Double.isInfinite(y.value)) {
return createConstant(Double.POSITIVE_INFINITY);
} else if (Double.isNaN(value) || Double.isNaN(y.value)) {
return createConstant(Double.NaN);
} else {
final int expX = FastMath.getExponent(value);
final int expY = FastMath.getExponent(y.value);
if (expX > expY + 27) {
// y is negligible with respect to x
return abs();
} else if (expY > expX + 27) {
// x is negligible with respect to y
return y.abs();
} else {
// find an intermediate scale to avoid both overflow and underflow
final int middleExp = (expX + expY) / 2;
// scale parameters without losing precision
final SparseGradient scaledX = scalb(-middleExp);
final SparseGradient scaledY = y.scalb(-middleExp);
// compute scaled hypotenuse
final SparseGradient scaledH =
scaledX.multiply(scaledX).add(scaledY.multiply(scaledY)).sqrt();
// remove scaling
return scaledH.scalb(middleExp);
}
}
}
/**
* Returns the hypotenuse of a triangle with sides {@code x} and {@code y}
* - sqrt(<i>x</i><sup>2</sup>&nbsp;+<i>y</i><sup>2</sup>)
* avoiding intermediate overflow or underflow.
*
* <ul>
* <li> If either argument is infinite, then the result is positive infinity.</li>
* <li> else, if either argument is NaN then the result is NaN.</li>
* </ul>
*
* @param x a value
* @param y a value
* @return sqrt(<i>x</i><sup>2</sup>&nbsp;+<i>y</i><sup>2</sup>)
*/
public static SparseGradient hypot(final SparseGradient x, final SparseGradient y) {
return x.hypot(y);
}
/** {@inheritDoc} */
@Override
public SparseGradient reciprocal() {
return new SparseGradient(1.0 / value, -1.0 / (value * value), derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient sqrt() {
final double sqrt = FastMath.sqrt(value);
return new SparseGradient(sqrt, 0.5 / sqrt, derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient cbrt() {
final double cbrt = FastMath.cbrt(value);
return new SparseGradient(cbrt, 1.0 / (3 * cbrt * cbrt), derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient rootN(final int n) {
if (n == 2) {
return sqrt();
} else if (n == 3) {
return cbrt();
} else {
final double root = FastMath.pow(value, 1.0 / n);
return new SparseGradient(root, 1.0 / (n * FastMath.pow(root, n - 1)), derivatives);
}
}
/** {@inheritDoc} */
@Override
public SparseGradient pow(final double p) {
return new SparseGradient(FastMath.pow(value, p), p * FastMath.pow(value, p - 1), derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient pow(final int n) {
if (n == 0) {
return getField().getOne();
} else {
final double valueNm1 = FastMath.pow(value, n - 1);
return new SparseGradient(value * valueNm1, n * valueNm1, derivatives);
}
}
/** {@inheritDoc} */
@Override
public SparseGradient pow(final SparseGradient e) {
return log().multiply(e).exp();
}
/** Compute a<sup>x</sup> where a is a double and x a {@link SparseGradient}
* @param a number to exponentiate
* @param x power to apply
* @return a<sup>x</sup>
*/
public static SparseGradient pow(final double a, final SparseGradient x) {
if (a == 0) {
if (x.value == 0) {
return x.compose(1.0, Double.NEGATIVE_INFINITY);
} else if (x.value < 0) {
return x.compose(Double.NaN, Double.NaN);
} else {
return x.getField().getZero();
}
} else {
final double ax = FastMath.pow(a, x.value);
return new SparseGradient(ax, ax * FastMath.log(a), x.derivatives);
}
}
/** {@inheritDoc} */
@Override
public SparseGradient exp() {
final double e = FastMath.exp(value);
return new SparseGradient(e, e, derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient expm1() {
return new SparseGradient(FastMath.expm1(value), FastMath.exp(value), derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient log() {
return new SparseGradient(FastMath.log(value), 1.0 / value, derivatives);
}
/** Base 10 logarithm.
* @return base 10 logarithm of the instance
*/
@Override
public SparseGradient log10() {
return new SparseGradient(FastMath.log10(value), 1.0 / (FastMath.log(10.0) * value), derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient log1p() {
return new SparseGradient(FastMath.log1p(value), 1.0 / (1.0 + value), derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient cos() {
return new SparseGradient(FastMath.cos(value), -FastMath.sin(value), derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient sin() {
return new SparseGradient(FastMath.sin(value), FastMath.cos(value), derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient tan() {
final double t = FastMath.tan(value);
return new SparseGradient(t, 1 + t * t, derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient acos() {
return new SparseGradient(FastMath.acos(value), -1.0 / FastMath.sqrt(1 - value * value), derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient asin() {
return new SparseGradient(FastMath.asin(value), 1.0 / FastMath.sqrt(1 - value * value), derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient atan() {
return new SparseGradient(FastMath.atan(value), 1.0 / (1 + value * value), derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient atan2(final SparseGradient x) {
// compute r = sqrt(x^2+y^2)
final SparseGradient r = multiply(this).add(x.multiply(x)).sqrt();
final SparseGradient a;
if (x.value >= 0) {
// compute atan2(y, x) = 2 atan(y / (r + x))
a = divide(r.add(x)).atan().multiply(2);
} else {
// compute atan2(y, x) = +/- pi - 2 atan(y / (r - x))
final SparseGradient tmp = divide(r.subtract(x)).atan().multiply(-2);
a = tmp.add(tmp.value <= 0 ? -FastMath.PI : FastMath.PI);
}
// fix value to take special cases (+0/+0, +0/-0, -0/+0, -0/-0, +/-infinity) correctly
a.value = FastMath.atan2(value, x.value);
return a;
}
/** Two arguments arc tangent operation.
* @param y first argument of the arc tangent
* @param x second argument of the arc tangent
* @return atan2(y, x)
*/
public static SparseGradient atan2(final SparseGradient y, final SparseGradient x) {
return y.atan2(x);
}
/** {@inheritDoc} */
@Override
public SparseGradient cosh() {
return new SparseGradient(FastMath.cosh(value), FastMath.sinh(value), derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient sinh() {
return new SparseGradient(FastMath.sinh(value), FastMath.cosh(value), derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient tanh() {
final double t = FastMath.tanh(value);
return new SparseGradient(t, 1 - t * t, derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient acosh() {
return new SparseGradient(FastMath.acosh(value), 1.0 / FastMath.sqrt(value * value - 1.0), derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient asinh() {
return new SparseGradient(FastMath.asinh(value), 1.0 / FastMath.sqrt(value * value + 1.0), derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient atanh() {
return new SparseGradient(FastMath.atanh(value), 1.0 / (1.0 - value * value), derivatives);
}
/** Convert radians to degrees, with error of less than 0.5 ULP
* @return instance converted into degrees
*/
public SparseGradient toDegrees() {
return new SparseGradient(FastMath.toDegrees(value), FastMath.toDegrees(1.0), derivatives);
}
/** Convert degrees to radians, with error of less than 0.5 ULP
* @return instance converted into radians
*/
public SparseGradient toRadians() {
return new SparseGradient(FastMath.toRadians(value), FastMath.toRadians(1.0), derivatives);
}
/** Evaluate Taylor expansion of a sparse gradient.
* @param delta parameters offsets (&Delta;x, &Delta;y, ...)
* @return value of the Taylor expansion at x + &Delta;x, y + &Delta;y, ...
*/
public double taylor(final double ... delta) {
double y = value;
for (int i = 0; i < delta.length; ++i) {
y += delta[i] * getDerivative(i);
}
return y;
}
/** Compute composition of the instance by a univariate function.
* @param f0 value of the function at (i.e. f({@link #getValue()}))
* @param f1 first derivative of the function at
* the current point (i.e. f'({@link #getValue()}))
* @return f(this)
*/
public SparseGradient compose(final double f0, final double f1) {
return new SparseGradient(f0, f1, derivatives);
}
/** {@inheritDoc} */
@Override
public SparseGradient linearCombination(final SparseGradient[] a,
final SparseGradient[] b)
throws DimensionMismatchException {
// compute a simple value, with all partial derivatives
SparseGradient out = a[0].getField().getZero();
for (int i = 0; i < a.length; ++i) {
out = out.add(a[i].multiply(b[i]));
}
// recompute an accurate value, taking care of cancellations
final double[] aDouble = new double[a.length];
for (int i = 0; i < a.length; ++i) {
aDouble[i] = a[i].getValue();
}
final double[] bDouble = new double[b.length];
for (int i = 0; i < b.length; ++i) {
bDouble[i] = b[i].getValue();
}
out.value = LinearCombination.value(aDouble, bDouble);
return out;
}
/** {@inheritDoc} */
@Override
public SparseGradient linearCombination(final double[] a, final SparseGradient[] b) {
// compute a simple value, with all partial derivatives
SparseGradient out = b[0].getField().getZero();
for (int i = 0; i < a.length; ++i) {
out = out.add(b[i].multiply(a[i]));
}
// recompute an accurate value, taking care of cancellations
final double[] bDouble = new double[b.length];
for (int i = 0; i < b.length; ++i) {
bDouble[i] = b[i].getValue();
}
out.value = LinearCombination.value(a, bDouble);
return out;
}
/** {@inheritDoc} */
@Override
public SparseGradient linearCombination(final SparseGradient a1, final SparseGradient b1,
final SparseGradient a2, final SparseGradient b2) {
// compute a simple value, with all partial derivatives
SparseGradient out = a1.multiply(b1).add(a2.multiply(b2));
// recompute an accurate value, taking care of cancellations
out.value = LinearCombination.value(a1.value, b1.value, a2.value, b2.value);
return out;
}
/** {@inheritDoc} */
@Override
public SparseGradient linearCombination(final double a1, final SparseGradient b1,
final double a2, final SparseGradient b2) {
// compute a simple value, with all partial derivatives
SparseGradient out = b1.multiply(a1).add(b2.multiply(a2));
// recompute an accurate value, taking care of cancellations
out.value = LinearCombination.value(a1, b1.value, a2, b2.value);
return out;
}
/** {@inheritDoc} */
@Override
public SparseGradient linearCombination(final SparseGradient a1, final SparseGradient b1,
final SparseGradient a2, final SparseGradient b2,
final SparseGradient a3, final SparseGradient b3) {
// compute a simple value, with all partial derivatives
SparseGradient out = a1.multiply(b1).add(a2.multiply(b2)).add(a3.multiply(b3));
// recompute an accurate value, taking care of cancellations
out.value = LinearCombination.value(a1.value, b1.value,
a2.value, b2.value,
a3.value, b3.value);
return out;
}
/** {@inheritDoc} */
@Override
public SparseGradient linearCombination(final double a1, final SparseGradient b1,
final double a2, final SparseGradient b2,
final double a3, final SparseGradient b3) {
// compute a simple value, with all partial derivatives
SparseGradient out = b1.multiply(a1).add(b2.multiply(a2)).add(b3.multiply(a3));
// recompute an accurate value, taking care of cancellations
out.value = LinearCombination.value(a1, b1.value,
a2, b2.value,
a3, b3.value);
return out;
}
/** {@inheritDoc} */
@Override
public SparseGradient linearCombination(final SparseGradient a1, final SparseGradient b1,
final SparseGradient a2, final SparseGradient b2,
final SparseGradient a3, final SparseGradient b3,
final SparseGradient a4, final SparseGradient b4) {
// compute a simple value, with all partial derivatives
SparseGradient out = a1.multiply(b1).add(a2.multiply(b2)).add(a3.multiply(b3)).add(a4.multiply(b4));
// recompute an accurate value, taking care of cancellations
out.value = LinearCombination.value(a1.value, b1.value,
a2.value, b2.value,
a3.value, b3.value,
a4.value, b4.value);
return out;
}
/** {@inheritDoc} */
@Override
public SparseGradient linearCombination(final double a1, final SparseGradient b1,
final double a2, final SparseGradient b2,
final double a3, final SparseGradient b3,
final double a4, final SparseGradient b4) {
// compute a simple value, with all partial derivatives
SparseGradient out = b1.multiply(a1).add(b2.multiply(a2)).add(b3.multiply(a3)).add(b4.multiply(a4));
// recompute an accurate value, taking care of cancellations
out.value = LinearCombination.value(a1, b1.value,
a2, b2.value,
a3, b3.value,
a4, b4.value);
return out;
}
/**
* Test for the equality of two sparse gradients.
* <p>
* Sparse gradients are considered equal if they have the same value
* and the same derivatives.
* </p>
* @param other Object to test for equality to this
* @return true if two sparse gradients are equal
*/
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (other instanceof SparseGradient) {
final SparseGradient rhs = (SparseGradient)other;
if (!Precision.equals(value, rhs.value, 1)) {
return false;
}
if (derivatives.size() != rhs.derivatives.size()) {
return false;
}
for (final Map.Entry<Integer, Double> entry : derivatives.entrySet()) {
if (!rhs.derivatives.containsKey(entry.getKey())) {
return false;
}
if (!Precision.equals(entry.getValue(), rhs.derivatives.get(entry.getKey()), 1)) {
return false;
}
}
return true;
}
return false;
}
/**
* Get a hashCode for the derivative structure.
* @return a hash code value for this object
* @since 3.2
*/
@Override
public int hashCode() {
return 743 + 809 * MathUtils.hash(value) + 167 * derivatives.hashCode();
}
}

View File

@ -1,43 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.differentiation;
import org.apache.commons.math4.analysis.UnivariateFunction;
import org.apache.commons.math4.exception.DimensionMismatchException;
/** Interface for univariate functions derivatives.
* <p>This interface represents a simple function which computes
* both the value and the first derivative of a mathematical function.
* The derivative is computed with respect to the input variable.</p>
* @see UnivariateDifferentiableFunction
* @see UnivariateFunctionDifferentiator
* @since 3.1
*/
public interface UnivariateDifferentiableFunction extends UnivariateFunction {
/** Simple mathematical function.
* <p>{@link UnivariateDifferentiableFunction} classes compute both the
* value and the first derivative of the function.</p>
* @param t function input value
* @return function result
* @exception DimensionMismatchException if t is inconsistent with the
* function's free parameters or order
*/
DerivativeStructure value(DerivativeStructure t)
throws DimensionMismatchException;
}

View File

@ -1,40 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.differentiation;
import org.apache.commons.math4.analysis.UnivariateMatrixFunction;
import org.apache.commons.math4.exception.MathIllegalArgumentException;
/**
* Extension of {@link UnivariateMatrixFunction} representing a univariate differentiable matrix function.
*
* @since 3.1
*/
public interface UnivariateDifferentiableMatrixFunction
extends UnivariateMatrixFunction {
/**
* Compute the value for the function.
* @param x the point for which the function value should be computed
* @return the value
* @exception MathIllegalArgumentException if {@code x} does not
* satisfy the function's constraints (argument out of bound, or unsupported
* derivative order for example)
*/
DerivativeStructure[][] value(DerivativeStructure x) throws MathIllegalArgumentException;
}

View File

@ -1,40 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.differentiation;
import org.apache.commons.math4.analysis.UnivariateVectorFunction;
import org.apache.commons.math4.exception.MathIllegalArgumentException;
/**
* Extension of {@link UnivariateVectorFunction} representing a univariate differentiable vectorial function.
*
* @since 3.1
*/
public interface UnivariateDifferentiableVectorFunction
extends UnivariateVectorFunction {
/**
* Compute the value for the function.
* @param x the point for which the function value should be computed
* @return the value
* @exception MathIllegalArgumentException if {@code x} does not
* satisfy the function's constraints (argument out of bound, or unsupported
* derivative order for example)
*/
DerivativeStructure[] value(DerivativeStructure x) throws MathIllegalArgumentException;
}

View File

@ -1,33 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.differentiation;
import org.apache.commons.math4.analysis.UnivariateFunction;
/** Interface defining the function differentiation operation.
* @since 3.1
*/
public interface UnivariateFunctionDifferentiator {
/** Create an implementation of a {@link UnivariateDifferentiableFunction
* differential} from a regular {@link UnivariateFunction function}.
* @param function function to differentiate
* @return differential function
*/
UnivariateDifferentiableFunction differentiate(UnivariateFunction function);
}

View File

@ -1,33 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.differentiation;
import org.apache.commons.math4.analysis.UnivariateMatrixFunction;
/** Interface defining the function differentiation operation.
* @since 3.1
*/
public interface UnivariateMatrixFunctionDifferentiator {
/** Create an implementation of a {@link UnivariateDifferentiableMatrixFunction
* differential} from a regular {@link UnivariateMatrixFunction matrix function}.
* @param function function to differentiate
* @return differential function
*/
UnivariateDifferentiableMatrixFunction differentiate(UnivariateMatrixFunction function);
}

View File

@ -1,33 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.differentiation;
import org.apache.commons.math4.analysis.UnivariateVectorFunction;
/** Interface defining the function differentiation operation.
* @since 3.1
*/
public interface UnivariateVectorFunctionDifferentiator {
/** Create an implementation of a {@link UnivariateDifferentiableVectorFunction
* differential} from a regular {@link UnivariateVectorFunction vector function}.
* @param function function to differentiate
* @return differential function
*/
UnivariateDifferentiableVectorFunction differentiate(UnivariateVectorFunction function);
}

View File

@ -1,42 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* <p>
* This package holds the main interfaces and basic building block classes
* dealing with differentiation.
* The core class is {@link org.apache.commons.math4.analysis.differentiation.DerivativeStructure
* DerivativeStructure} which holds the value and the differentials of a function. This class
* handles some arbitrary number of free parameters and arbitrary differentiation order. It is used
* both as the input and the output type for the {@link
* org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction
* UnivariateDifferentiableFunction} interface. Any differentiable function should implement this
* interface.
* </p>
* <p>
* The {@link org.apache.commons.math4.analysis.differentiation.UnivariateFunctionDifferentiator
* UnivariateFunctionDifferentiator} interface defines a way to differentiate a simple {@link
* org.apache.commons.math4.analysis.UnivariateFunction UnivariateFunction} and get a {@link
* org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction
* UnivariateDifferentiableFunction}.
* </p>
* <p>
* Similar interfaces also exist for multivariate functions and for vector or matrix valued functions.
* </p>
*
*/
package org.apache.commons.math4.analysis.differentiation;

View File

@ -1,34 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.UnivariateFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Absolute value function.
*
* @since 3.0
*/
public class Abs implements UnivariateFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.abs(x);
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Arc-cosine function.
*
* @since 3.0
*/
public class Acos implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.acos(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.acos();
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Hyperbolic arc-cosine function.
*
* @since 3.0
*/
public class Acosh implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.acosh(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.acosh();
}
}

View File

@ -1,33 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.BivariateFunction;
/**
* Add the two operands.
*
* @since 3.0
*/
public class Add implements BivariateFunction {
/** {@inheritDoc} */
@Override
public double value(double x, double y) {
return x + y;
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Arc-sine function.
*
* @since 3.0
*/
public class Asin implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.asin(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.asin();
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Hyperbolic arc-sine function.
*
* @since 3.0
*/
public class Asinh implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.asinh(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.asinh();
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Arc-tangent function.
*
* @since 3.0
*/
public class Atan implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.atan(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.atan();
}
}

View File

@ -1,34 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.BivariateFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Arc-tangent function.
*
* @since 3.0
*/
public class Atan2 implements BivariateFunction {
/** {@inheritDoc} */
@Override
public double value(double x, double y) {
return FastMath.atan2(x, y);
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Hyperbolic arc-tangent function.
*
* @since 3.0
*/
public class Atanh implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.atanh(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.atanh();
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Cube root function.
*
* @since 3.0
*/
public class Cbrt implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.cbrt(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.cbrt();
}
}

View File

@ -1,34 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.UnivariateFunction;
import org.apache.commons.math4.util.FastMath;
/**
* {@code ceil} function.
*
* @since 3.0
*/
public class Ceil implements UnivariateFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.ceil(x);
}
}

View File

@ -1,53 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
/**
* Constant function.
*
* @since 3.0
*/
public class Constant implements UnivariateDifferentiableFunction {
/** Constant. */
private final double c;
/**
* @param c Constant.
*/
public Constant(double c) {
this.c = c;
}
/** {@inheritDoc} */
@Override
public double value(double x) {
return c;
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return new DerivativeStructure(t.getFreeParameters(), t.getOrder(), c);
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Cosine function.
*
* @since 3.0
*/
public class Cos implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.cos(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.cos();
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Hyperbolic cosine function.
*
* @since 3.0
*/
public class Cosh implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.cosh(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.cosh();
}
}

View File

@ -1,33 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.BivariateFunction;
/**
* Divide the first operand by the second.
*
* @since 3.0
*/
public class Divide implements BivariateFunction {
/** {@inheritDoc} */
@Override
public double value(double x, double y) {
return x / y;
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Exponential function.
*
* @since 3.0
*/
public class Exp implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.exp(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.exp();
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* <code>e<sup>x</sup>-1</code> function.
*
* @since 3.0
*/
public class Expm1 implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.expm1(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.expm1();
}
}

View File

@ -1,34 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.UnivariateFunction;
import org.apache.commons.math4.util.FastMath;
/**
* {@code floor} function.
*
* @since 3.0
*/
public class Floor implements UnivariateFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.floor(x);
}
}

View File

@ -1,252 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import java.util.Arrays;
import org.apache.commons.math4.analysis.ParametricUnivariateFunction;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.NullArgumentException;
import org.apache.commons.math4.util.FastMath;
import org.apache.commons.numbers.core.Precision;
/**
* <a href="http://en.wikipedia.org/wiki/Gaussian_function">
* Gaussian</a> function.
*
* @since 3.0
*/
public class Gaussian implements UnivariateDifferentiableFunction {
/** Mean. */
private final double mean;
/** Inverse of the standard deviation. */
private final double is;
/** Inverse of twice the square of the standard deviation. */
private final double i2s2;
/** Normalization factor. */
private final double norm;
/**
* Gaussian with given normalization factor, mean and standard deviation.
*
* @param norm Normalization factor.
* @param mean Mean.
* @param sigma Standard deviation.
* @throws NotStrictlyPositiveException if {@code sigma <= 0}.
*/
public Gaussian(double norm,
double mean,
double sigma)
throws NotStrictlyPositiveException {
if (sigma <= 0) {
throw new NotStrictlyPositiveException(sigma);
}
this.norm = norm;
this.mean = mean;
this.is = 1 / sigma;
this.i2s2 = 0.5 * is * is;
}
/**
* Normalized gaussian with given mean and standard deviation.
*
* @param mean Mean.
* @param sigma Standard deviation.
* @throws NotStrictlyPositiveException if {@code sigma <= 0}.
*/
public Gaussian(double mean,
double sigma)
throws NotStrictlyPositiveException {
this(1 / (sigma * FastMath.sqrt(2 * Math.PI)), mean, sigma);
}
/**
* Normalized gaussian with zero mean and unit standard deviation.
*/
public Gaussian() {
this(0, 1);
}
/** {@inheritDoc} */
@Override
public double value(double x) {
return value(x - mean, norm, i2s2);
}
/**
* Parametric function where the input array contains the parameters of
* the Gaussian, ordered as follows:
* <ul>
* <li>Norm</li>
* <li>Mean</li>
* <li>Standard deviation</li>
* </ul>
*/
public static class Parametric implements ParametricUnivariateFunction {
/**
* Computes the value of the Gaussian at {@code x}.
*
* @param x Value for which the function must be computed.
* @param param Values of norm, mean and standard deviation.
* @return the value of the function.
* @throws NullArgumentException if {@code param} is {@code null}.
* @throws DimensionMismatchException if the size of {@code param} is
* not 3.
* @throws NotStrictlyPositiveException if {@code param[2]} is negative.
*/
@Override
public double value(double x, double ... param)
throws NullArgumentException,
DimensionMismatchException,
NotStrictlyPositiveException {
validateParameters(param);
final double diff = x - param[1];
final double i2s2 = 1 / (2 * param[2] * param[2]);
return Gaussian.value(diff, param[0], i2s2);
}
/**
* Computes the value of the gradient at {@code x}.
* The components of the gradient vector are the partial
* derivatives of the function with respect to each of the
* <em>parameters</em> (norm, mean and standard deviation).
*
* @param x Value at which the gradient must be computed.
* @param param Values of norm, mean and standard deviation.
* @return the gradient vector at {@code x}.
* @throws NullArgumentException if {@code param} is {@code null}.
* @throws DimensionMismatchException if the size of {@code param} is
* not 3.
* @throws NotStrictlyPositiveException if {@code param[2]} is negative.
*/
@Override
public double[] gradient(double x, double ... param)
throws NullArgumentException,
DimensionMismatchException,
NotStrictlyPositiveException {
validateParameters(param);
final double norm = param[0];
final double diff = x - param[1];
final double sigma = param[2];
final double i2s2 = 1 / (2 * sigma * sigma);
final double n = Gaussian.value(diff, 1, i2s2);
final double m = norm * n * 2 * i2s2 * diff;
final double s = m * diff / sigma;
return new double[] { n, m, s };
}
/**
* Validates parameters to ensure they are appropriate for the evaluation of
* the {@link #value(double,double[])} and {@link #gradient(double,double[])}
* methods.
*
* @param param Values of norm, mean and standard deviation.
* @throws NullArgumentException if {@code param} is {@code null}.
* @throws DimensionMismatchException if the size of {@code param} is
* not 3.
* @throws NotStrictlyPositiveException if {@code param[2]} is negative.
*/
private void validateParameters(double[] param)
throws NullArgumentException,
DimensionMismatchException,
NotStrictlyPositiveException {
if (param == null) {
throw new NullArgumentException();
}
if (param.length != 3) {
throw new DimensionMismatchException(param.length, 3);
}
if (param[2] <= 0) {
throw new NotStrictlyPositiveException(param[2]);
}
}
}
/**
* @param xMinusMean {@code x - mean}.
* @param norm Normalization factor.
* @param i2s2 Inverse of twice the square of the standard deviation.
* @return the value of the Gaussian at {@code x}.
*/
private static double value(double xMinusMean,
double norm,
double i2s2) {
return norm * FastMath.exp(-xMinusMean * xMinusMean * i2s2);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t)
throws DimensionMismatchException {
final double u = is * (t.getValue() - mean);
double[] f = new double[t.getOrder() + 1];
// the nth order derivative of the Gaussian has the form:
// dn(g(x)/dxn = (norm / s^n) P_n(u) exp(-u^2/2) with u=(x-m)/s
// where P_n(u) is a degree n polynomial with same parity as n
// P_0(u) = 1, P_1(u) = -u, P_2(u) = u^2 - 1, P_3(u) = -u^3 + 3 u...
// the general recurrence relation for P_n is:
// P_n(u) = P_(n-1)'(u) - u P_(n-1)(u)
// as per polynomial parity, we can store coefficients of both P_(n-1) and P_n in the same array
final double[] p = new double[f.length];
p[0] = 1;
final double u2 = u * u;
double coeff = norm * FastMath.exp(-0.5 * u2);
if (coeff <= Precision.SAFE_MIN) {
Arrays.fill(f, 0.0);
} else {
f[0] = coeff;
for (int n = 1; n < f.length; ++n) {
// update and evaluate polynomial P_n(x)
double v = 0;
p[n] = -p[n - 1];
for (int k = n; k >= 0; k -= 2) {
v = v * u2 + p[k];
if (k > 2) {
p[k - 2] = (k - 1) * p[k - 1] - p[k - 3];
} else if (k == 2) {
p[0] = p[1];
}
}
if ((n & 0x1) == 1) {
v *= u;
}
coeff *= is;
f[n] = coeff * v;
}
}
return t.compose(f);
}
}

View File

@ -1,176 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.ParametricUnivariateFunction;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.NullArgumentException;
import org.apache.commons.math4.util.FastMath;
/**
* <a href="http://en.wikipedia.org/wiki/Harmonic_oscillator">
* simple harmonic oscillator</a> function.
*
* @since 3.0
*/
public class HarmonicOscillator implements UnivariateDifferentiableFunction {
/** Amplitude. */
private final double amplitude;
/** Angular frequency. */
private final double omega;
/** Phase. */
private final double phase;
/**
* Harmonic oscillator function.
*
* @param amplitude Amplitude.
* @param omega Angular frequency.
* @param phase Phase.
*/
public HarmonicOscillator(double amplitude,
double omega,
double phase) {
this.amplitude = amplitude;
this.omega = omega;
this.phase = phase;
}
/** {@inheritDoc} */
@Override
public double value(double x) {
return value(omega * x + phase, amplitude);
}
/**
* Parametric function where the input array contains the parameters of
* the harmonic oscillator function, ordered as follows:
* <ul>
* <li>Amplitude</li>
* <li>Angular frequency</li>
* <li>Phase</li>
* </ul>
*/
public static class Parametric implements ParametricUnivariateFunction {
/**
* Computes the value of the harmonic oscillator at {@code x}.
*
* @param x Value for which the function must be computed.
* @param param Values of norm, mean and standard deviation.
* @return the value of the function.
* @throws NullArgumentException if {@code param} is {@code null}.
* @throws DimensionMismatchException if the size of {@code param} is
* not 3.
*/
@Override
public double value(double x, double ... param)
throws NullArgumentException,
DimensionMismatchException {
validateParameters(param);
return HarmonicOscillator.value(x * param[1] + param[2], param[0]);
}
/**
* Computes the value of the gradient at {@code x}.
* The components of the gradient vector are the partial
* derivatives of the function with respect to each of the
* <em>parameters</em> (amplitude, angular frequency and phase).
*
* @param x Value at which the gradient must be computed.
* @param param Values of amplitude, angular frequency and phase.
* @return the gradient vector at {@code x}.
* @throws NullArgumentException if {@code param} is {@code null}.
* @throws DimensionMismatchException if the size of {@code param} is
* not 3.
*/
@Override
public double[] gradient(double x, double ... param)
throws NullArgumentException,
DimensionMismatchException {
validateParameters(param);
final double amplitude = param[0];
final double omega = param[1];
final double phase = param[2];
final double xTimesOmegaPlusPhase = omega * x + phase;
final double a = HarmonicOscillator.value(xTimesOmegaPlusPhase, 1);
final double p = -amplitude * FastMath.sin(xTimesOmegaPlusPhase);
final double w = p * x;
return new double[] { a, w, p };
}
/**
* Validates parameters to ensure they are appropriate for the evaluation of
* the {@link #value(double,double[])} and {@link #gradient(double,double[])}
* methods.
*
* @param param Values of norm, mean and standard deviation.
* @throws NullArgumentException if {@code param} is {@code null}.
* @throws DimensionMismatchException if the size of {@code param} is
* not 3.
*/
private void validateParameters(double[] param)
throws NullArgumentException,
DimensionMismatchException {
if (param == null) {
throw new NullArgumentException();
}
if (param.length != 3) {
throw new DimensionMismatchException(param.length, 3);
}
}
}
/**
* @param xTimesOmegaPlusPhase {@code omega * x + phase}.
* @param amplitude Amplitude.
* @return the value of the harmonic oscillator function at {@code x}.
*/
private static double value(double xTimesOmegaPlusPhase,
double amplitude) {
return amplitude * FastMath.cos(xTimesOmegaPlusPhase);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t)
throws DimensionMismatchException {
final double x = t.getValue();
double[] f = new double[t.getOrder() + 1];
final double alpha = omega * x + phase;
f[0] = amplitude * FastMath.cos(alpha);
if (f.length > 1) {
f[1] = -amplitude * omega * FastMath.sin(alpha);
final double mo2 = - omega * omega;
for (int i = 2; i < f.length; ++i) {
f[i] = mo2 * f[i - 2];
}
}
return t.compose(f);
}
}

View File

@ -1,43 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
/**
* Identity function.
*
* @since 3.0
*/
public class Identity implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return x;
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t;
}
}

View File

@ -1,43 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
/**
* Inverse function.
*
* @since 3.0
*/
public class Inverse implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return 1 / x;
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.reciprocal();
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Natural logarithm function.
*
* @since 3.0
*/
public class Log implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.log(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.log();
}
}

View File

@ -1,45 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Base 10 logarithm function.
*
* @since 3.0
*/
public class Log10 implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.log10(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.log10();
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* <code>log(1 + p)</code> function.
*
* @since 3.0
*/
public class Log1p implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.log1p(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.log1p();
}
}

View File

@ -1,221 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.ParametricUnivariateFunction;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.NullArgumentException;
import org.apache.commons.math4.util.FastMath;
/**
* <a href="http://en.wikipedia.org/wiki/Generalised_logistic_function">
* Generalised logistic</a> function.
*
* @since 3.0
*/
public class Logistic implements UnivariateDifferentiableFunction {
/** Lower asymptote. */
private final double a;
/** Upper asymptote. */
private final double k;
/** Growth rate. */
private final double b;
/** Parameter that affects near which asymptote maximum growth occurs. */
private final double oneOverN;
/** Parameter that affects the position of the curve along the ordinate axis. */
private final double q;
/** Abscissa of maximum growth. */
private final double m;
/**
* @param k If {@code b > 0}, value of the function for x going towards +&infin;.
* If {@code b < 0}, value of the function for x going towards -&infin;.
* @param m Abscissa of maximum growth.
* @param b Growth rate.
* @param q Parameter that affects the position of the curve along the
* ordinate axis.
* @param a If {@code b > 0}, value of the function for x going towards -&infin;.
* If {@code b < 0}, value of the function for x going towards +&infin;.
* @param n Parameter that affects near which asymptote the maximum
* growth occurs.
* @throws NotStrictlyPositiveException if {@code n <= 0}.
*/
public Logistic(double k,
double m,
double b,
double q,
double a,
double n)
throws NotStrictlyPositiveException {
if (n <= 0) {
throw new NotStrictlyPositiveException(n);
}
this.k = k;
this.m = m;
this.b = b;
this.q = q;
this.a = a;
oneOverN = 1 / n;
}
/** {@inheritDoc} */
@Override
public double value(double x) {
return value(m - x, k, b, q, a, oneOverN);
}
/**
* Parametric function where the input array contains the parameters of
* the {@link Logistic#Logistic(double,double,double,double,double,double)
* logistic function}, ordered as follows:
* <ul>
* <li>k</li>
* <li>m</li>
* <li>b</li>
* <li>q</li>
* <li>a</li>
* <li>n</li>
* </ul>
*/
public static class Parametric implements ParametricUnivariateFunction {
/**
* Computes the value of the sigmoid at {@code x}.
*
* @param x Value for which the function must be computed.
* @param param Values for {@code k}, {@code m}, {@code b}, {@code q},
* {@code a} and {@code n}.
* @return the value of the function.
* @throws NullArgumentException if {@code param} is {@code null}.
* @throws DimensionMismatchException if the size of {@code param} is
* not 6.
* @throws NotStrictlyPositiveException if {@code param[5] <= 0}.
*/
@Override
public double value(double x, double ... param)
throws NullArgumentException,
DimensionMismatchException,
NotStrictlyPositiveException {
validateParameters(param);
return Logistic.value(param[1] - x, param[0],
param[2], param[3],
param[4], 1 / param[5]);
}
/**
* Computes the value of the gradient at {@code x}.
* The components of the gradient vector are the partial
* derivatives of the function with respect to each of the
* <em>parameters</em>.
*
* @param x Value at which the gradient must be computed.
* @param param Values for {@code k}, {@code m}, {@code b}, {@code q},
* {@code a} and {@code n}.
* @return the gradient vector at {@code x}.
* @throws NullArgumentException if {@code param} is {@code null}.
* @throws DimensionMismatchException if the size of {@code param} is
* not 6.
* @throws NotStrictlyPositiveException if {@code param[5] <= 0}.
*/
@Override
public double[] gradient(double x, double ... param)
throws NullArgumentException,
DimensionMismatchException,
NotStrictlyPositiveException {
validateParameters(param);
final double b = param[2];
final double q = param[3];
final double mMinusX = param[1] - x;
final double oneOverN = 1 / param[5];
final double exp = FastMath.exp(b * mMinusX);
final double qExp = q * exp;
final double qExp1 = qExp + 1;
final double factor1 = (param[0] - param[4]) * oneOverN / FastMath.pow(qExp1, oneOverN);
final double factor2 = -factor1 / qExp1;
// Components of the gradient.
final double gk = Logistic.value(mMinusX, 1, b, q, 0, oneOverN);
final double gm = factor2 * b * qExp;
final double gb = factor2 * mMinusX * qExp;
final double gq = factor2 * exp;
final double ga = Logistic.value(mMinusX, 0, b, q, 1, oneOverN);
final double gn = factor1 * FastMath.log(qExp1) * oneOverN;
return new double[] { gk, gm, gb, gq, ga, gn };
}
/**
* Validates parameters to ensure they are appropriate for the evaluation of
* the {@link #value(double,double[])} and {@link #gradient(double,double[])}
* methods.
*
* @param param Values for {@code k}, {@code m}, {@code b}, {@code q},
* {@code a} and {@code n}.
* @throws NullArgumentException if {@code param} is {@code null}.
* @throws DimensionMismatchException if the size of {@code param} is
* not 6.
* @throws NotStrictlyPositiveException if {@code param[5] <= 0}.
*/
private void validateParameters(double[] param)
throws NullArgumentException,
DimensionMismatchException,
NotStrictlyPositiveException {
if (param == null) {
throw new NullArgumentException();
}
if (param.length != 6) {
throw new DimensionMismatchException(param.length, 6);
}
if (param[5] <= 0) {
throw new NotStrictlyPositiveException(param[5]);
}
}
}
/**
* @param mMinusX {@code m - x}.
* @param k {@code k}.
* @param b {@code b}.
* @param q {@code q}.
* @param a {@code a}.
* @param oneOverN {@code 1 / n}.
* @return the value of the function.
*/
private static double value(double mMinusX,
double k,
double b,
double q,
double a,
double oneOverN) {
return a + (k - a) / FastMath.pow(1 + q * FastMath.exp(b * mMinusX), oneOverN);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.negate().add(m).multiply(b).exp().multiply(q).add(1).pow(oneOverN).reciprocal().multiply(k - a).add(a);
}
}

View File

@ -1,205 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.ParametricUnivariateFunction;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.NullArgumentException;
import org.apache.commons.math4.exception.OutOfRangeException;
import org.apache.commons.math4.util.FastMath;
/**
* <a href="http://en.wikipedia.org/wiki/Logit">
* Logit</a> function.
* It is the inverse of the {@link Sigmoid sigmoid} function.
*
* @since 3.0
*/
public class Logit implements UnivariateDifferentiableFunction {
/** Lower bound. */
private final double lo;
/** Higher bound. */
private final double hi;
/**
* Usual logit function, where the lower bound is 0 and the higher
* bound is 1.
*/
public Logit() {
this(0, 1);
}
/**
* Logit function.
*
* @param lo Lower bound of the function domain.
* @param hi Higher bound of the function domain.
*/
public Logit(double lo,
double hi) {
this.lo = lo;
this.hi = hi;
}
/** {@inheritDoc} */
@Override
public double value(double x)
throws OutOfRangeException {
return value(x, lo, hi);
}
/**
* Parametric function where the input array contains the parameters of
* the logit function, ordered as follows:
* <ul>
* <li>Lower bound</li>
* <li>Higher bound</li>
* </ul>
*/
public static class Parametric implements ParametricUnivariateFunction {
/**
* Computes the value of the logit at {@code x}.
*
* @param x Value for which the function must be computed.
* @param param Values of lower bound and higher bounds.
* @return the value of the function.
* @throws NullArgumentException if {@code param} is {@code null}.
* @throws DimensionMismatchException if the size of {@code param} is
* not 2.
*/
@Override
public double value(double x, double ... param)
throws NullArgumentException,
DimensionMismatchException {
validateParameters(param);
return Logit.value(x, param[0], param[1]);
}
/**
* Computes the value of the gradient at {@code x}.
* The components of the gradient vector are the partial
* derivatives of the function with respect to each of the
* <em>parameters</em> (lower bound and higher bound).
*
* @param x Value at which the gradient must be computed.
* @param param Values for lower and higher bounds.
* @return the gradient vector at {@code x}.
* @throws NullArgumentException if {@code param} is {@code null}.
* @throws DimensionMismatchException if the size of {@code param} is
* not 2.
*/
@Override
public double[] gradient(double x, double ... param)
throws NullArgumentException,
DimensionMismatchException {
validateParameters(param);
final double lo = param[0];
final double hi = param[1];
return new double[] { 1 / (lo - x), 1 / (hi - x) };
}
/**
* Validates parameters to ensure they are appropriate for the evaluation of
* the {@link #value(double,double[])} and {@link #gradient(double,double[])}
* methods.
*
* @param param Values for lower and higher bounds.
* @throws NullArgumentException if {@code param} is {@code null}.
* @throws DimensionMismatchException if the size of {@code param} is
* not 2.
*/
private void validateParameters(double[] param)
throws NullArgumentException,
DimensionMismatchException {
if (param == null) {
throw new NullArgumentException();
}
if (param.length != 2) {
throw new DimensionMismatchException(param.length, 2);
}
}
}
/**
* @param x Value at which to compute the logit.
* @param lo Lower bound.
* @param hi Higher bound.
* @return the value of the logit function at {@code x}.
* @throws OutOfRangeException if {@code x < lo} or {@code x > hi}.
*/
private static double value(double x,
double lo,
double hi)
throws OutOfRangeException {
if (x < lo || x > hi) {
throw new OutOfRangeException(x, lo, hi);
}
return FastMath.log((x - lo) / (hi - x));
}
/** {@inheritDoc}
* @since 3.1
* @exception OutOfRangeException if parameter is outside of function domain
*/
@Override
public DerivativeStructure value(final DerivativeStructure t)
throws OutOfRangeException {
final double x = t.getValue();
if (x < lo || x > hi) {
throw new OutOfRangeException(x, lo, hi);
}
double[] f = new double[t.getOrder() + 1];
// function value
f[0] = FastMath.log((x - lo) / (hi - x));
if (Double.isInfinite(f[0])) {
if (f.length > 1) {
f[1] = Double.POSITIVE_INFINITY;
}
// fill the array with infinities
// (for x close to lo the signs will flip between -inf and +inf,
// for x close to hi the signs will always be +inf)
// this is probably overkill, since the call to compose at the end
// of the method will transform most infinities into NaN ...
for (int i = 2; i < f.length; ++i) {
f[i] = f[i - 2];
}
} else {
// function derivatives
final double invL = 1.0 / (x - lo);
double xL = invL;
final double invH = 1.0 / (hi - x);
double xH = invH;
for (int i = 1; i < f.length; ++i) {
f[i] = xL + xH;
xL *= -i * invL;
xH *= i * invH;
}
}
return t.compose(f);
}
}

View File

@ -1,34 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.BivariateFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Maximum function.
*
* @since 3.0
*/
public class Max implements BivariateFunction {
/** {@inheritDoc} */
@Override
public double value(double x, double y) {
return FastMath.max(x, y);
}
}

View File

@ -1,34 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.BivariateFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Minimum function.
*
* @since 3.0
*/
public class Min implements BivariateFunction {
/** {@inheritDoc} */
@Override
public double value(double x, double y) {
return FastMath.min(x, y);
}
}

View File

@ -1,43 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
/**
* Minus function.
*
* @since 3.0
*/
public class Minus implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return -x;
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.negate();
}
}

View File

@ -1,33 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.BivariateFunction;
/**
* Multiply the two operands.
*
* @since 3.0
*/
public class Multiply implements BivariateFunction {
/** {@inheritDoc} */
@Override
public double value(double x, double y) {
return x * y;
}
}

View File

@ -1,34 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.BivariateFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Power function.
*
* @since 3.0
*/
public class Pow implements BivariateFunction {
/** {@inheritDoc} */
@Override
public double value(double x, double y) {
return FastMath.pow(x, y);
}
}

View File

@ -1,54 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Power function.
*
* @since 3.0
*/
public class Power implements UnivariateDifferentiableFunction {
/** Power. */
private final double p;
/**
* @param p Power.
*/
public Power(double p) {
this.p = p;
}
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.pow(x, p);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.pow(p);
}
}

View File

@ -1,34 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.UnivariateFunction;
import org.apache.commons.math4.util.FastMath;
/**
* {@code rint} function.
*
* @since 3.0
*/
public class Rint implements UnivariateFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.rint(x);
}
}

View File

@ -1,211 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import java.util.Arrays;
import org.apache.commons.math4.analysis.ParametricUnivariateFunction;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.NullArgumentException;
import org.apache.commons.math4.util.FastMath;
/**
* <a href="http://en.wikipedia.org/wiki/Sigmoid_function">
* Sigmoid</a> function.
* It is the inverse of the {@link Logit logit} function.
* A more flexible version, the generalised logistic, is implemented
* by the {@link Logistic} class.
*
* @since 3.0
*/
public class Sigmoid implements UnivariateDifferentiableFunction {
/** Lower asymptote. */
private final double lo;
/** Higher asymptote. */
private final double hi;
/**
* Usual sigmoid function, where the lower asymptote is 0 and the higher
* asymptote is 1.
*/
public Sigmoid() {
this(0, 1);
}
/**
* Sigmoid function.
*
* @param lo Lower asymptote.
* @param hi Higher asymptote.
*/
public Sigmoid(double lo,
double hi) {
this.lo = lo;
this.hi = hi;
}
/** {@inheritDoc} */
@Override
public double value(double x) {
return value(x, lo, hi);
}
/**
* Parametric function where the input array contains the parameters of
* the {@link Sigmoid#Sigmoid(double,double) sigmoid function}, ordered
* as follows:
* <ul>
* <li>Lower asymptote</li>
* <li>Higher asymptote</li>
* </ul>
*/
public static class Parametric implements ParametricUnivariateFunction {
/**
* Computes the value of the sigmoid at {@code x}.
*
* @param x Value for which the function must be computed.
* @param param Values of lower asymptote and higher asymptote.
* @return the value of the function.
* @throws NullArgumentException if {@code param} is {@code null}.
* @throws DimensionMismatchException if the size of {@code param} is
* not 2.
*/
@Override
public double value(double x, double ... param)
throws NullArgumentException,
DimensionMismatchException {
validateParameters(param);
return Sigmoid.value(x, param[0], param[1]);
}
/**
* Computes the value of the gradient at {@code x}.
* The components of the gradient vector are the partial
* derivatives of the function with respect to each of the
* <em>parameters</em> (lower asymptote and higher asymptote).
*
* @param x Value at which the gradient must be computed.
* @param param Values for lower asymptote and higher asymptote.
* @return the gradient vector at {@code x}.
* @throws NullArgumentException if {@code param} is {@code null}.
* @throws DimensionMismatchException if the size of {@code param} is
* not 2.
*/
@Override
public double[] gradient(double x, double ... param)
throws NullArgumentException,
DimensionMismatchException {
validateParameters(param);
final double invExp1 = 1 / (1 + FastMath.exp(-x));
return new double[] { 1 - invExp1, invExp1 };
}
/**
* Validates parameters to ensure they are appropriate for the evaluation of
* the {@link #value(double,double[])} and {@link #gradient(double,double[])}
* methods.
*
* @param param Values for lower and higher asymptotes.
* @throws NullArgumentException if {@code param} is {@code null}.
* @throws DimensionMismatchException if the size of {@code param} is
* not 2.
*/
private void validateParameters(double[] param)
throws NullArgumentException,
DimensionMismatchException {
if (param == null) {
throw new NullArgumentException();
}
if (param.length != 2) {
throw new DimensionMismatchException(param.length, 2);
}
}
}
/**
* @param x Value at which to compute the sigmoid.
* @param lo Lower asymptote.
* @param hi Higher asymptote.
* @return the value of the sigmoid function at {@code x}.
*/
private static double value(double x,
double lo,
double hi) {
return lo + (hi - lo) / (1 + FastMath.exp(-x));
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t)
throws DimensionMismatchException {
double[] f = new double[t.getOrder() + 1];
final double exp = FastMath.exp(-t.getValue());
if (Double.isInfinite(exp)) {
// special handling near lower boundary, to avoid NaN
f[0] = lo;
Arrays.fill(f, 1, f.length, 0.0);
} else {
// the nth order derivative of sigmoid has the form:
// dn(sigmoid(x)/dxn = P_n(exp(-x)) / (1+exp(-x))^(n+1)
// where P_n(t) is a degree n polynomial with normalized higher term
// P_0(t) = 1, P_1(t) = t, P_2(t) = t^2 - t, P_3(t) = t^3 - 4 t^2 + t...
// the general recurrence relation for P_n is:
// P_n(x) = n t P_(n-1)(t) - t (1 + t) P_(n-1)'(t)
final double[] p = new double[f.length];
final double inv = 1 / (1 + exp);
double coeff = hi - lo;
for (int n = 0; n < f.length; ++n) {
// update and evaluate polynomial P_n(t)
double v = 0;
p[n] = 1;
for (int k = n; k >= 0; --k) {
v = v * exp + p[k];
if (k > 1) {
p[k - 1] = (n - k + 2) * p[k - 2] - (k - 1) * p[k - 1];
} else {
p[0] = 0;
}
}
coeff *= inv;
f[n] = coeff * v;
}
// fix function value
f[0] += lo;
}
return t.compose(f);
}
}

View File

@ -1,34 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.UnivariateFunction;
import org.apache.commons.math4.util.FastMath;
/**
* {@code signum} function.
*
* @since 3.0
*/
public class Signum implements UnivariateFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.signum(x);
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Sine function.
*
* @since 3.0
*/
public class Sin implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.sin(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.sin();
}
}

View File

@ -1,196 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.util.FastMath;
/**
* <a href="http://en.wikipedia.org/wiki/Sinc_function">Sinc</a> function,
* defined by
* <pre><code>
* sinc(x) = 1 if x = 0,
* sin(x) / x otherwise.
* </code></pre>
*
* @since 3.0
*/
public class Sinc implements UnivariateDifferentiableFunction {
/**
* Value below which the computations are done using Taylor series.
* <p>
* The Taylor series for sinc even order derivatives are:
* <pre>
* d^(2n)sinc/dx^(2n) = Sum_(k>=0) (-1)^(n+k) / ((2k)!(2n+2k+1)) x^(2k)
* = (-1)^n [ 1/(2n+1) - x^2/(4n+6) + x^4/(48n+120) - x^6/(1440n+5040) + O(x^8) ]
* </pre>
* </p>
* <p>
* The Taylor series for sinc odd order derivatives are:
* <pre>
* d^(2n+1)sinc/dx^(2n+1) = Sum_(k>=0) (-1)^(n+k+1) / ((2k+1)!(2n+2k+3)) x^(2k+1)
* = (-1)^(n+1) [ x/(2n+3) - x^3/(12n+30) + x^5/(240n+840) - x^7/(10080n+45360) + O(x^9) ]
* </pre>
* </p>
* <p>
* So the ratio of the fourth term with respect to the first term
* is always smaller than x^6/720, for all derivative orders.
* This implies that neglecting this term and using only the first three terms induces
* a relative error bounded by x^6/720. The SHORTCUT value is chosen such that this
* relative error is below double precision accuracy when |x| <= SHORTCUT.
* </p>
*/
private static final double SHORTCUT = 6.0e-3;
/** For normalized sinc function. */
private final boolean normalized;
/**
* The sinc function, {@code sin(x) / x}.
*/
public Sinc() {
this(false);
}
/**
* Instantiates the sinc function.
*
* @param normalized If {@code true}, the function is
* <code> sin(&pi;x) / &pi;x</code>, otherwise {@code sin(x) / x}.
*/
public Sinc(boolean normalized) {
this.normalized = normalized;
}
/** {@inheritDoc} */
@Override
public double value(final double x) {
final double scaledX = normalized ? FastMath.PI * x : x;
if (FastMath.abs(scaledX) <= SHORTCUT) {
// use Taylor series
final double scaledX2 = scaledX * scaledX;
return ((scaledX2 - 20) * scaledX2 + 120) / 120;
} else {
// use definition expression
return FastMath.sin(scaledX) / scaledX;
}
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t)
throws DimensionMismatchException {
final double scaledX = (normalized ? FastMath.PI : 1) * t.getValue();
final double scaledX2 = scaledX * scaledX;
double[] f = new double[t.getOrder() + 1];
if (FastMath.abs(scaledX) <= SHORTCUT) {
for (int i = 0; i < f.length; ++i) {
final int k = i / 2;
if ((i & 0x1) == 0) {
// even derivation order
f[i] = (((k & 0x1) == 0) ? 1 : -1) *
(1.0 / (i + 1) - scaledX2 * (1.0 / (2 * i + 6) - scaledX2 / (24 * i + 120)));
} else {
// odd derivation order
f[i] = (((k & 0x1) == 0) ? -scaledX : scaledX) *
(1.0 / (i + 2) - scaledX2 * (1.0 / (6 * i + 24) - scaledX2 / (120 * i + 720)));
}
}
} else {
final double inv = 1 / scaledX;
final double cos = FastMath.cos(scaledX);
final double sin = FastMath.sin(scaledX);
f[0] = inv * sin;
// the nth order derivative of sinc has the form:
// dn(sinc(x)/dxn = [S_n(x) sin(x) + C_n(x) cos(x)] / x^(n+1)
// where S_n(x) is an even polynomial with degree n-1 or n (depending on parity)
// and C_n(x) is an odd polynomial with degree n-1 or n (depending on parity)
// S_0(x) = 1, S_1(x) = -1, S_2(x) = -x^2 + 2, S_3(x) = 3x^2 - 6...
// C_0(x) = 0, C_1(x) = x, C_2(x) = -2x, C_3(x) = -x^3 + 6x...
// the general recurrence relations for S_n and C_n are:
// S_n(x) = x S_(n-1)'(x) - n S_(n-1)(x) - x C_(n-1)(x)
// C_n(x) = x C_(n-1)'(x) - n C_(n-1)(x) + x S_(n-1)(x)
// as per polynomials parity, we can store both S_n and C_n in the same array
final double[] sc = new double[f.length];
sc[0] = 1;
double coeff = inv;
for (int n = 1; n < f.length; ++n) {
double s = 0;
double c = 0;
// update and evaluate polynomials S_n(x) and C_n(x)
final int kStart;
if ((n & 0x1) == 0) {
// even derivation order, S_n is degree n and C_n is degree n-1
sc[n] = 0;
kStart = n;
} else {
// odd derivation order, S_n is degree n-1 and C_n is degree n
sc[n] = sc[n - 1];
c = sc[n];
kStart = n - 1;
}
// in this loop, k is always even
for (int k = kStart; k > 1; k -= 2) {
// sine part
sc[k] = (k - n) * sc[k] - sc[k - 1];
s = s * scaledX2 + sc[k];
// cosine part
sc[k - 1] = (k - 1 - n) * sc[k - 1] + sc[k -2];
c = c * scaledX2 + sc[k - 1];
}
sc[0] *= -n;
s = s * scaledX2 + sc[0];
coeff *= inv;
f[n] = coeff * (s * sin + c * scaledX * cos);
}
}
if (normalized) {
double scale = FastMath.PI;
for (int i = 1; i < f.length; ++i) {
f[i] *= scale;
scale *= FastMath.PI;
}
}
return t.compose(f);
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Hyperbolic sine function.
*
* @since 3.0
*/
public class Sinh implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.sinh(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.sinh();
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Square-root function.
*
* @since 3.0
*/
public class Sqrt implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.sqrt(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.sqrt();
}
}

View File

@ -1,102 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import java.util.Arrays;
import org.apache.commons.math4.analysis.UnivariateFunction;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.NoDataException;
import org.apache.commons.math4.exception.NonMonotonicSequenceException;
import org.apache.commons.math4.exception.NullArgumentException;
import org.apache.commons.math4.util.MathArrays;
/**
* <a href="http://en.wikipedia.org/wiki/Step_function">
* Step function</a>.
*
* @since 3.0
*/
public class StepFunction implements UnivariateFunction {
/** Abscissae. */
private final double[] abscissa;
/** Ordinates. */
private final double[] ordinate;
/**
* Builds a step function from a list of arguments and the corresponding
* values. Specifically, returns the function h(x) defined by <pre><code>
* h(x) = y[0] for all x &lt; x[1]
* y[1] for x[1] &le; x &lt; x[2]
* ...
* y[y.length - 1] for x &ge; x[x.length - 1]
* </code></pre>
* The value of {@code x[0]} is ignored, but it must be strictly less than
* {@code x[1]}.
*
* @param x Domain values where the function changes value.
* @param y Values of the function.
* @throws NonMonotonicSequenceException
* if the {@code x} array is not sorted in strictly increasing order.
* @throws NullArgumentException if {@code x} or {@code y} are {@code null}.
* @throws NoDataException if {@code x} or {@code y} are zero-length.
* @throws DimensionMismatchException if {@code x} and {@code y} do not
* have the same length.
*/
public StepFunction(double[] x,
double[] y)
throws NullArgumentException, NoDataException,
DimensionMismatchException, NonMonotonicSequenceException {
if (x == null ||
y == null) {
throw new NullArgumentException();
}
if (x.length == 0 ||
y.length == 0) {
throw new NoDataException();
}
if (y.length != x.length) {
throw new DimensionMismatchException(y.length, x.length);
}
MathArrays.checkOrder(x);
abscissa = MathArrays.copyOf(x);
ordinate = MathArrays.copyOf(y);
}
/** {@inheritDoc} */
@Override
public double value(double x) {
int index = Arrays.binarySearch(abscissa, x);
double fx = 0;
if (index < -1) {
// "x" is between "abscissa[-index-2]" and "abscissa[-index-1]".
fx = ordinate[-index-2];
} else if (index >= 0) {
// "x" is exactly "abscissa[index]".
fx = ordinate[index];
} else {
// Otherwise, "x" is smaller than the first value in "abscissa"
// (hence the returned value should be "ordinate[0]").
fx = ordinate[0];
}
return fx;
}
}

View File

@ -1,33 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.BivariateFunction;
/**
* Subtract the second operand from the first.
*
* @since 3.0
*/
public class Subtract implements BivariateFunction {
/** {@inheritDoc} */
@Override
public double value(double x, double y) {
return x - y;
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Tangent function.
*
* @since 3.0
*/
public class Tan implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.tan(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.tan();
}
}

View File

@ -1,44 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math4.util.FastMath;
/**
* Hyperbolic tangent function.
*
* @since 3.0
*/
public class Tanh implements UnivariateDifferentiableFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.tanh(x);
}
/** {@inheritDoc}
* @since 3.1
*/
@Override
public DerivativeStructure value(final DerivativeStructure t) {
return t.tanh();
}
}

View File

@ -1,34 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.function;
import org.apache.commons.math4.analysis.UnivariateFunction;
import org.apache.commons.math4.util.FastMath;
/**
* {@code ulp} function.
*
* @since 3.0
*/
public class Ulp implements UnivariateFunction {
/** {@inheritDoc} */
@Override
public double value(double x) {
return FastMath.ulp(x);
}
}

View File

@ -1,26 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* <p>
* The {@code function} package contains function objects that wrap the
* methods contained in {@link java.lang.Math}, as well as common
* mathematical functions such as the gaussian and sinc functions.
* </p>
*
*/
package org.apache.commons.math4.analysis.function;

View File

@ -1,287 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.integration;
import org.apache.commons.math4.analysis.UnivariateFunction;
import org.apache.commons.math4.analysis.solvers.UnivariateSolverUtils;
import org.apache.commons.math4.exception.MathIllegalArgumentException;
import org.apache.commons.math4.exception.MaxCountExceededException;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.NullArgumentException;
import org.apache.commons.math4.exception.NumberIsTooSmallException;
import org.apache.commons.math4.exception.TooManyEvaluationsException;
import org.apache.commons.math4.util.Incrementor;
import org.apache.commons.math4.util.MathUtils;
/**
* Provide a default implementation for several generic functions.
*
* @since 1.2
*/
public abstract class BaseAbstractUnivariateIntegrator implements UnivariateIntegrator {
/** Default absolute accuracy. */
public static final double DEFAULT_ABSOLUTE_ACCURACY = 1.0e-15;
/** Default relative accuracy. */
public static final double DEFAULT_RELATIVE_ACCURACY = 1.0e-6;
/** Default minimal iteration count. */
public static final int DEFAULT_MIN_ITERATIONS_COUNT = 3;
/** Default maximal iteration count. */
public static final int DEFAULT_MAX_ITERATIONS_COUNT = Integer.MAX_VALUE;
/** The iteration count. */
protected final Incrementor iterations;
/** Maximum absolute error. */
private final double absoluteAccuracy;
/** Maximum relative error. */
private final double relativeAccuracy;
/** minimum number of iterations */
private final int minimalIterationCount;
/** The functions evaluation count. */
private final Incrementor evaluations;
/** Function to integrate. */
private UnivariateFunction function;
/** Lower bound for the interval. */
private double min;
/** Upper bound for the interval. */
private double max;
/**
* Construct an integrator with given accuracies and iteration counts.
* <p>
* The meanings of the various parameters are:
* <ul>
* <li>relative accuracy:
* this is used to stop iterations if the absolute accuracy can't be
* achieved due to large values or short mantissa length. If this
* should be the primary criterion for convergence rather then a
* safety measure, set the absolute accuracy to a ridiculously small value,
* like {@link org.apache.commons.numbers.core.Precision#SAFE_MIN Precision.SAFE_MIN}.</li>
* <li>absolute accuracy:
* The default is usually chosen so that results in the interval
* -10..-0.1 and +0.1..+10 can be found with a reasonable accuracy. If the
* expected absolute value of your results is of much smaller magnitude, set
* this to a smaller value.</li>
* <li>minimum number of iterations:
* minimal iteration is needed to avoid false early convergence, e.g.
* the sample points happen to be zeroes of the function. Users can
* use the default value or choose one that they see as appropriate.</li>
* <li>maximum number of iterations:
* usually a high iteration count indicates convergence problems. However,
* the "reasonable value" varies widely for different algorithms. Users are
* advised to use the default value supplied by the algorithm.</li>
* </ul>
*
* @param relativeAccuracy relative accuracy of the result
* @param absoluteAccuracy absolute accuracy of the result
* @param minimalIterationCount minimum number of iterations
* @param maximalIterationCount maximum number of iterations
* @exception NotStrictlyPositiveException if minimal number of iterations
* is not strictly positive
* @exception NumberIsTooSmallException if maximal number of iterations
* is lesser than or equal to the minimal number of iterations
*/
protected BaseAbstractUnivariateIntegrator(final double relativeAccuracy,
final double absoluteAccuracy,
final int minimalIterationCount,
final int maximalIterationCount)
throws NotStrictlyPositiveException, NumberIsTooSmallException {
// accuracy settings
this.relativeAccuracy = relativeAccuracy;
this.absoluteAccuracy = absoluteAccuracy;
// iterations count settings
if (minimalIterationCount <= 0) {
throw new NotStrictlyPositiveException(minimalIterationCount);
}
if (maximalIterationCount <= minimalIterationCount) {
throw new NumberIsTooSmallException(maximalIterationCount, minimalIterationCount, false);
}
this.minimalIterationCount = minimalIterationCount;
this.iterations = new Incrementor();
iterations.setMaximalCount(maximalIterationCount);
// prepare evaluations counter, but do not set it yet
evaluations = new Incrementor();
}
/**
* Construct an integrator with given accuracies.
* @param relativeAccuracy relative accuracy of the result
* @param absoluteAccuracy absolute accuracy of the result
*/
protected BaseAbstractUnivariateIntegrator(final double relativeAccuracy,
final double absoluteAccuracy) {
this(relativeAccuracy, absoluteAccuracy,
DEFAULT_MIN_ITERATIONS_COUNT, DEFAULT_MAX_ITERATIONS_COUNT);
}
/**
* Construct an integrator with given iteration counts.
* @param minimalIterationCount minimum number of iterations
* @param maximalIterationCount maximum number of iterations
* @exception NotStrictlyPositiveException if minimal number of iterations
* is not strictly positive
* @exception NumberIsTooSmallException if maximal number of iterations
* is lesser than or equal to the minimal number of iterations
*/
protected BaseAbstractUnivariateIntegrator(final int minimalIterationCount,
final int maximalIterationCount)
throws NotStrictlyPositiveException, NumberIsTooSmallException {
this(DEFAULT_RELATIVE_ACCURACY, DEFAULT_ABSOLUTE_ACCURACY,
minimalIterationCount, maximalIterationCount);
}
/** {@inheritDoc} */
@Override
public double getRelativeAccuracy() {
return relativeAccuracy;
}
/** {@inheritDoc} */
@Override
public double getAbsoluteAccuracy() {
return absoluteAccuracy;
}
/** {@inheritDoc} */
@Override
public int getMinimalIterationCount() {
return minimalIterationCount;
}
/** {@inheritDoc} */
@Override
public int getMaximalIterationCount() {
return iterations.getMaximalCount();
}
/** {@inheritDoc} */
@Override
public int getEvaluations() {
return evaluations.getCount();
}
/** {@inheritDoc} */
@Override
public int getIterations() {
return iterations.getCount();
}
/**
* @return the lower bound.
*/
protected double getMin() {
return min;
}
/**
* @return the upper bound.
*/
protected double getMax() {
return max;
}
/**
* Compute the objective function value.
*
* @param point Point at which the objective function must be evaluated.
* @return the objective function value at specified point.
* @throws TooManyEvaluationsException if the maximal number of function
* evaluations is exceeded.
*/
protected double computeObjectiveValue(final double point)
throws TooManyEvaluationsException {
try {
evaluations.incrementCount();
} catch (MaxCountExceededException e) {
throw new TooManyEvaluationsException(e.getMax());
}
return function.value(point);
}
/**
* Prepare for computation.
* Subclasses must call this method if they override any of the
* {@code solve} methods.
*
* @param maxEval Maximum number of evaluations.
* @param f the integrand function
* @param lower the min bound for the interval
* @param upper the upper bound for the interval
* @throws NullArgumentException if {@code f} is {@code null}.
* @throws MathIllegalArgumentException if {@code min >= max}.
*/
protected void setup(final int maxEval,
final UnivariateFunction f,
final double lower, final double upper)
throws NullArgumentException, MathIllegalArgumentException {
// Checks.
MathUtils.checkNotNull(f);
UnivariateSolverUtils.verifyInterval(lower, upper);
// Reset.
min = lower;
max = upper;
function = f;
evaluations.setMaximalCount(maxEval);
evaluations.resetCount();
iterations.resetCount();
}
/** {@inheritDoc} */
@Override
public double integrate(final int maxEval, final UnivariateFunction f,
final double lower, final double upper)
throws TooManyEvaluationsException, MaxCountExceededException,
MathIllegalArgumentException, NullArgumentException {
// Initialization.
setup(maxEval, f, lower, upper);
// Perform computation.
return doIntegrate();
}
/**
* Method for implementing actual integration algorithms in derived
* classes.
*
* @return the root.
* @throws TooManyEvaluationsException if the maximal number of evaluations
* is exceeded.
* @throws MaxCountExceededException if the maximum iteration count is exceeded
* or the integrator detects convergence problems otherwise
*/
protected abstract double doIntegrate()
throws TooManyEvaluationsException, MaxCountExceededException;
}

View File

@ -1,184 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.integration;
import org.apache.commons.math4.analysis.UnivariateFunction;
import org.apache.commons.math4.analysis.integration.gauss.GaussIntegrator;
import org.apache.commons.math4.analysis.integration.gauss.GaussIntegratorFactory;
import org.apache.commons.math4.exception.MathIllegalArgumentException;
import org.apache.commons.math4.exception.MaxCountExceededException;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.NumberIsTooSmallException;
import org.apache.commons.math4.exception.TooManyEvaluationsException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.math4.util.FastMath;
/**
* This algorithm divides the integration interval into equally-sized
* sub-interval and on each of them performs a
* <a href="http://mathworld.wolfram.com/Legendre-GaussQuadrature.html">
* Legendre-Gauss</a> quadrature.
* Because of its <em>non-adaptive</em> nature, this algorithm can
* converge to a wrong value for the integral (for example, if the
* function is significantly different from zero toward the ends of the
* integration interval).
* In particular, a change of variables aimed at estimating integrals
* over infinite intervals as proposed
* <a href="http://en.wikipedia.org/w/index.php?title=Numerical_integration#Integrals_over_infinite_intervals">
* here</a> should be avoided when using this class.
*
* @since 3.1
*/
public class IterativeLegendreGaussIntegrator
extends BaseAbstractUnivariateIntegrator {
/** Factory that computes the points and weights. */
private static final GaussIntegratorFactory FACTORY
= new GaussIntegratorFactory();
/** Number of integration points (per interval). */
private final int numberOfPoints;
/**
* Builds an integrator with given accuracies and iterations counts.
*
* @param n Number of integration points.
* @param relativeAccuracy Relative accuracy of the result.
* @param absoluteAccuracy Absolute accuracy of the result.
* @param minimalIterationCount Minimum number of iterations.
* @param maximalIterationCount Maximum number of iterations.
* @throws NotStrictlyPositiveException if minimal number of iterations
* or number of points are not strictly positive.
* @throws NumberIsTooSmallException if maximal number of iterations
* is smaller than or equal to the minimal number of iterations.
*/
public IterativeLegendreGaussIntegrator(final int n,
final double relativeAccuracy,
final double absoluteAccuracy,
final int minimalIterationCount,
final int maximalIterationCount)
throws NotStrictlyPositiveException, NumberIsTooSmallException {
super(relativeAccuracy, absoluteAccuracy, minimalIterationCount, maximalIterationCount);
if (n <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.NUMBER_OF_POINTS, n);
}
numberOfPoints = n;
}
/**
* Builds an integrator with given accuracies.
*
* @param n Number of integration points.
* @param relativeAccuracy Relative accuracy of the result.
* @param absoluteAccuracy Absolute accuracy of the result.
* @throws NotStrictlyPositiveException if {@code n < 1}.
*/
public IterativeLegendreGaussIntegrator(final int n,
final double relativeAccuracy,
final double absoluteAccuracy)
throws NotStrictlyPositiveException {
this(n, relativeAccuracy, absoluteAccuracy,
DEFAULT_MIN_ITERATIONS_COUNT, DEFAULT_MAX_ITERATIONS_COUNT);
}
/**
* Builds an integrator with given iteration counts.
*
* @param n Number of integration points.
* @param minimalIterationCount Minimum number of iterations.
* @param maximalIterationCount Maximum number of iterations.
* @throws NotStrictlyPositiveException if minimal number of iterations
* is not strictly positive.
* @throws NumberIsTooSmallException if maximal number of iterations
* is smaller than or equal to the minimal number of iterations.
* @throws NotStrictlyPositiveException if {@code n < 1}.
*/
public IterativeLegendreGaussIntegrator(final int n,
final int minimalIterationCount,
final int maximalIterationCount)
throws NotStrictlyPositiveException, NumberIsTooSmallException {
this(n, DEFAULT_RELATIVE_ACCURACY, DEFAULT_ABSOLUTE_ACCURACY,
minimalIterationCount, maximalIterationCount);
}
/** {@inheritDoc} */
@Override
protected double doIntegrate()
throws MathIllegalArgumentException, TooManyEvaluationsException, MaxCountExceededException {
// Compute first estimate with a single step.
double oldt = stage(1);
int n = 2;
while (true) {
// Improve integral with a larger number of steps.
final double t = stage(n);
// Estimate the error.
final double delta = FastMath.abs(t - oldt);
final double limit =
FastMath.max(getAbsoluteAccuracy(),
getRelativeAccuracy() * (FastMath.abs(oldt) + FastMath.abs(t)) * 0.5);
// check convergence
if (iterations.getCount() + 1 >= getMinimalIterationCount() &&
delta <= limit) {
return t;
}
// Prepare next iteration.
final double ratio = FastMath.min(4, FastMath.pow(delta / limit, 0.5 / numberOfPoints));
n = FastMath.max((int) (ratio * n), n + 1);
oldt = t;
iterations.incrementCount();
}
}
/**
* Compute the n-th stage integral.
*
* @param n Number of steps.
* @return the value of n-th stage integral.
* @throws TooManyEvaluationsException if the maximum number of evaluations
* is exceeded.
*/
private double stage(final int n)
throws TooManyEvaluationsException {
// Function to be integrated is stored in the base class.
final UnivariateFunction f = new UnivariateFunction() {
/** {@inheritDoc} */
@Override
public double value(double x)
throws MathIllegalArgumentException, TooManyEvaluationsException {
return computeObjectiveValue(x);
}
};
final double min = getMin();
final double max = getMax();
final double step = (max - min) / n;
double sum = 0;
for (int i = 0; i < n; i++) {
// Integrate over each sub-interval [a, b].
final double a = min + i * step;
final double b = a + step;
final GaussIntegrator g = FACTORY.legendreHighPrecision(numberOfPoints, a, b);
sum += g.integrate(f);
}
return sum;
}
}

View File

@ -1,169 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.integration;
import org.apache.commons.math4.exception.MathIllegalArgumentException;
import org.apache.commons.math4.exception.MaxCountExceededException;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.NumberIsTooLargeException;
import org.apache.commons.math4.exception.NumberIsTooSmallException;
import org.apache.commons.math4.exception.TooManyEvaluationsException;
import org.apache.commons.math4.util.FastMath;
/**
* Implements the <a href="http://en.wikipedia.org/wiki/Midpoint_method">
* Midpoint Rule</a> for integration of real univariate functions. For
* reference, see <b>Numerical Mathematics</b>, ISBN 0387989595,
* chapter 9.2.
* <p>
* The function should be integrable.</p>
*
* @since 3.3
*/
public class MidPointIntegrator extends BaseAbstractUnivariateIntegrator {
/** Maximum number of iterations for midpoint. */
public static final int MIDPOINT_MAX_ITERATIONS_COUNT = 64;
/**
* Build a midpoint integrator with given accuracies and iterations counts.
* @param relativeAccuracy relative accuracy of the result
* @param absoluteAccuracy absolute accuracy of the result
* @param minimalIterationCount minimum number of iterations
* @param maximalIterationCount maximum number of iterations
* (must be less than or equal to {@link #MIDPOINT_MAX_ITERATIONS_COUNT}
* @exception NotStrictlyPositiveException if minimal number of iterations
* is not strictly positive
* @exception NumberIsTooSmallException if maximal number of iterations
* is lesser than or equal to the minimal number of iterations
* @exception NumberIsTooLargeException if maximal number of iterations
* is greater than {@link #MIDPOINT_MAX_ITERATIONS_COUNT}
*/
public MidPointIntegrator(final double relativeAccuracy,
final double absoluteAccuracy,
final int minimalIterationCount,
final int maximalIterationCount)
throws NotStrictlyPositiveException, NumberIsTooSmallException, NumberIsTooLargeException {
super(relativeAccuracy, absoluteAccuracy, minimalIterationCount, maximalIterationCount);
if (maximalIterationCount > MIDPOINT_MAX_ITERATIONS_COUNT) {
throw new NumberIsTooLargeException(maximalIterationCount,
MIDPOINT_MAX_ITERATIONS_COUNT, false);
}
}
/**
* Build a midpoint integrator with given iteration counts.
* @param minimalIterationCount minimum number of iterations
* @param maximalIterationCount maximum number of iterations
* (must be less than or equal to {@link #MIDPOINT_MAX_ITERATIONS_COUNT}
* @exception NotStrictlyPositiveException if minimal number of iterations
* is not strictly positive
* @exception NumberIsTooSmallException if maximal number of iterations
* is lesser than or equal to the minimal number of iterations
* @exception NumberIsTooLargeException if maximal number of iterations
* is greater than {@link #MIDPOINT_MAX_ITERATIONS_COUNT}
*/
public MidPointIntegrator(final int minimalIterationCount,
final int maximalIterationCount)
throws NotStrictlyPositiveException, NumberIsTooSmallException, NumberIsTooLargeException {
super(minimalIterationCount, maximalIterationCount);
if (maximalIterationCount > MIDPOINT_MAX_ITERATIONS_COUNT) {
throw new NumberIsTooLargeException(maximalIterationCount,
MIDPOINT_MAX_ITERATIONS_COUNT, false);
}
}
/**
* Construct a midpoint integrator with default settings.
* (max iteration count set to {@link #MIDPOINT_MAX_ITERATIONS_COUNT})
*/
public MidPointIntegrator() {
super(DEFAULT_MIN_ITERATIONS_COUNT, MIDPOINT_MAX_ITERATIONS_COUNT);
}
/**
* Compute the n-th stage integral of midpoint rule.
* This function should only be called by API <code>integrate()</code> in the package.
* To save time it does not verify arguments - caller does.
* <p>
* The interval is divided equally into 2^n sections rather than an
* arbitrary m sections because this configuration can best utilize the
* already computed values.</p>
*
* @param n the stage of 1/2 refinement. Must be larger than 0.
* @param previousStageResult Result from the previous call to the
* {@code stage} method.
* @param min Lower bound of the integration interval.
* @param diffMaxMin Difference between the lower bound and upper bound
* of the integration interval.
* @return the value of n-th stage integral
* @throws TooManyEvaluationsException if the maximal number of evaluations
* is exceeded.
*/
private double stage(final int n,
double previousStageResult,
double min,
double diffMaxMin)
throws TooManyEvaluationsException {
// number of new points in this stage
final long np = 1L << (n - 1);
double sum = 0;
// spacing between adjacent new points
final double spacing = diffMaxMin / np;
// the first new point
double x = min + 0.5 * spacing;
for (long i = 0; i < np; i++) {
sum += computeObjectiveValue(x);
x += spacing;
}
// add the new sum to previously calculated result
return 0.5 * (previousStageResult + sum * spacing);
}
/** {@inheritDoc} */
@Override
protected double doIntegrate()
throws MathIllegalArgumentException, TooManyEvaluationsException, MaxCountExceededException {
final double min = getMin();
final double diff = getMax() - min;
final double midPoint = min + 0.5 * diff;
double oldt = diff * computeObjectiveValue(midPoint);
while (true) {
iterations.incrementCount();
final int i = iterations.getCount();
final double t = stage(i, oldt, min, diff);
if (i >= getMinimalIterationCount()) {
final double delta = FastMath.abs(t - oldt);
final double rLimit =
getRelativeAccuracy() * (FastMath.abs(oldt) + FastMath.abs(t)) * 0.5;
if ((delta <= rLimit) || (delta <= getAbsoluteAccuracy())) {
return t;
}
}
oldt = t;
}
}
}

View File

@ -1,142 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.integration;
import org.apache.commons.math4.exception.MaxCountExceededException;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.NumberIsTooLargeException;
import org.apache.commons.math4.exception.NumberIsTooSmallException;
import org.apache.commons.math4.exception.TooManyEvaluationsException;
import org.apache.commons.math4.util.FastMath;
/**
* Implements the <a href="http://mathworld.wolfram.com/RombergIntegration.html">
* Romberg Algorithm</a> for integration of real univariate functions. For
* reference, see <b>Introduction to Numerical Analysis</b>, ISBN 038795452X,
* chapter 3.
* <p>
* Romberg integration employs k successive refinements of the trapezoid
* rule to remove error terms less than order O(N^(-2k)). Simpson's rule
* is a special case of k = 2.</p>
*
* @since 1.2
*/
public class RombergIntegrator extends BaseAbstractUnivariateIntegrator {
/** Maximal number of iterations for Romberg. */
public static final int ROMBERG_MAX_ITERATIONS_COUNT = 32;
/**
* Build a Romberg integrator with given accuracies and iterations counts.
* @param relativeAccuracy relative accuracy of the result
* @param absoluteAccuracy absolute accuracy of the result
* @param minimalIterationCount minimum number of iterations
* @param maximalIterationCount maximum number of iterations
* (must be less than or equal to {@link #ROMBERG_MAX_ITERATIONS_COUNT})
* @exception NotStrictlyPositiveException if minimal number of iterations
* is not strictly positive
* @exception NumberIsTooSmallException if maximal number of iterations
* is lesser than or equal to the minimal number of iterations
* @exception NumberIsTooLargeException if maximal number of iterations
* is greater than {@link #ROMBERG_MAX_ITERATIONS_COUNT}
*/
public RombergIntegrator(final double relativeAccuracy,
final double absoluteAccuracy,
final int minimalIterationCount,
final int maximalIterationCount)
throws NotStrictlyPositiveException, NumberIsTooSmallException, NumberIsTooLargeException {
super(relativeAccuracy, absoluteAccuracy, minimalIterationCount, maximalIterationCount);
if (maximalIterationCount > ROMBERG_MAX_ITERATIONS_COUNT) {
throw new NumberIsTooLargeException(maximalIterationCount,
ROMBERG_MAX_ITERATIONS_COUNT, false);
}
}
/**
* Build a Romberg integrator with given iteration counts.
* @param minimalIterationCount minimum number of iterations
* @param maximalIterationCount maximum number of iterations
* (must be less than or equal to {@link #ROMBERG_MAX_ITERATIONS_COUNT})
* @exception NotStrictlyPositiveException if minimal number of iterations
* is not strictly positive
* @exception NumberIsTooSmallException if maximal number of iterations
* is lesser than or equal to the minimal number of iterations
* @exception NumberIsTooLargeException if maximal number of iterations
* is greater than {@link #ROMBERG_MAX_ITERATIONS_COUNT}
*/
public RombergIntegrator(final int minimalIterationCount,
final int maximalIterationCount)
throws NotStrictlyPositiveException, NumberIsTooSmallException, NumberIsTooLargeException {
super(minimalIterationCount, maximalIterationCount);
if (maximalIterationCount > ROMBERG_MAX_ITERATIONS_COUNT) {
throw new NumberIsTooLargeException(maximalIterationCount,
ROMBERG_MAX_ITERATIONS_COUNT, false);
}
}
/**
* Construct a Romberg integrator with default settings
* (max iteration count set to {@link #ROMBERG_MAX_ITERATIONS_COUNT})
*/
public RombergIntegrator() {
super(DEFAULT_MIN_ITERATIONS_COUNT, ROMBERG_MAX_ITERATIONS_COUNT);
}
/** {@inheritDoc} */
@Override
protected double doIntegrate()
throws TooManyEvaluationsException, MaxCountExceededException {
final int m = iterations.getMaximalCount() + 1;
double previousRow[] = new double[m];
double currentRow[] = new double[m];
TrapezoidIntegrator qtrap = new TrapezoidIntegrator();
currentRow[0] = qtrap.stage(this, 0);
iterations.incrementCount();
double olds = currentRow[0];
while (true) {
final int i = iterations.getCount();
// switch rows
final double[] tmpRow = previousRow;
previousRow = currentRow;
currentRow = tmpRow;
currentRow[0] = qtrap.stage(this, i);
iterations.incrementCount();
for (int j = 1; j <= i; j++) {
// Richardson extrapolation coefficient
final double r = (1L << (2 * j)) - 1;
final double tIJm1 = currentRow[j - 1];
currentRow[j] = tIJm1 + (tIJm1 - previousRow[j - 1]) / r;
}
final double s = currentRow[i];
if (i >= getMinimalIterationCount()) {
final double delta = FastMath.abs(s - olds);
final double rLimit = getRelativeAccuracy() * (FastMath.abs(olds) + FastMath.abs(s)) * 0.5;
if ((delta <= rLimit) || (delta <= getAbsoluteAccuracy())) {
return s;
}
}
olds = s;
}
}
}

View File

@ -1,124 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.integration;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.NumberIsTooLargeException;
import org.apache.commons.math4.exception.NumberIsTooSmallException;
import org.apache.commons.math4.util.FastMath;
/**
* Implements <a href="http://mathworld.wolfram.com/SimpsonsRule.html">
* Simpson's Rule</a> for integration of real univariate functions. For
* reference, see <b>Introduction to Numerical Analysis</b>, ISBN 038795452X,
* chapter 3.
* <p>
* This implementation employs the basic trapezoid rule to calculate Simpson's
* rule.</p>
*
* @since 1.2
*/
public class SimpsonIntegrator extends BaseAbstractUnivariateIntegrator {
/** Maximal number of iterations for Simpson. */
public static final int SIMPSON_MAX_ITERATIONS_COUNT = 63;
/**
* Build a Simpson integrator with given accuracies and iterations counts.
* @param relativeAccuracy relative accuracy of the result
* @param absoluteAccuracy absolute accuracy of the result
* @param minimalIterationCount minimum number of iterations
* @param maximalIterationCount maximum number of iterations
* (must be less than or equal to {@link #SIMPSON_MAX_ITERATIONS_COUNT})
* @exception NotStrictlyPositiveException if minimal number of iterations
* is not strictly positive
* @exception NumberIsTooSmallException if maximal number of iterations
* is lesser than or equal to the minimal number of iterations
* @exception NumberIsTooLargeException if maximal number of iterations
* is greater than {@link #SIMPSON_MAX_ITERATIONS_COUNT}
*/
public SimpsonIntegrator(final double relativeAccuracy,
final double absoluteAccuracy,
final int minimalIterationCount,
final int maximalIterationCount)
throws NotStrictlyPositiveException, NumberIsTooSmallException, NumberIsTooLargeException {
super(relativeAccuracy, absoluteAccuracy, minimalIterationCount, maximalIterationCount);
if (maximalIterationCount > SIMPSON_MAX_ITERATIONS_COUNT) {
throw new NumberIsTooLargeException(maximalIterationCount,
SIMPSON_MAX_ITERATIONS_COUNT, false);
}
}
/**
* Build a Simpson integrator with given iteration counts.
* @param minimalIterationCount minimum number of iterations
* @param maximalIterationCount maximum number of iterations
* (must be less than or equal to {@link #SIMPSON_MAX_ITERATIONS_COUNT})
* @exception NotStrictlyPositiveException if minimal number of iterations
* is not strictly positive
* @exception NumberIsTooSmallException if maximal number of iterations
* is lesser than or equal to the minimal number of iterations
* @exception NumberIsTooLargeException if maximal number of iterations
* is greater than {@link #SIMPSON_MAX_ITERATIONS_COUNT}
*/
public SimpsonIntegrator(final int minimalIterationCount,
final int maximalIterationCount)
throws NotStrictlyPositiveException, NumberIsTooSmallException, NumberIsTooLargeException {
super(minimalIterationCount, maximalIterationCount);
if (maximalIterationCount > SIMPSON_MAX_ITERATIONS_COUNT) {
throw new NumberIsTooLargeException(maximalIterationCount,
SIMPSON_MAX_ITERATIONS_COUNT, false);
}
}
/**
* Construct an integrator with default settings.
* (max iteration count set to {@link #SIMPSON_MAX_ITERATIONS_COUNT})
*/
public SimpsonIntegrator() {
super(DEFAULT_MIN_ITERATIONS_COUNT, SIMPSON_MAX_ITERATIONS_COUNT);
}
/** {@inheritDoc} */
@Override
protected double doIntegrate() {
// Simpson's rule requires at least two trapezoid stages.
// So we set the first sum using two trapezoid stages.
final TrapezoidIntegrator qtrap = new TrapezoidIntegrator();
final double s0 = qtrap.stage(this, 0);
double oldt = qtrap.stage(this, 1);
double olds = (4 * oldt - s0) / 3.0;
while (true) {
// The first iteration is the first refinement of the sum.
iterations.incrementCount();
final int i = getIterations();
final double t = qtrap.stage(this, i + 1); // 1-stage ahead of the iteration
final double s = (4 * t - oldt) / 3.0;
if (i >= getMinimalIterationCount()) {
final double delta = FastMath.abs(s - olds);
final double rLimit = getRelativeAccuracy() * (FastMath.abs(olds) + FastMath.abs(s)) * 0.5;
if (delta <= rLimit ||
delta <= getAbsoluteAccuracy()) {
return s;
}
}
olds = s;
oldt = t;
}
}
}

View File

@ -1,168 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.integration;
import org.apache.commons.math4.exception.MathIllegalArgumentException;
import org.apache.commons.math4.exception.MaxCountExceededException;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.NumberIsTooLargeException;
import org.apache.commons.math4.exception.NumberIsTooSmallException;
import org.apache.commons.math4.exception.TooManyEvaluationsException;
import org.apache.commons.math4.util.FastMath;
/**
* Implements the <a href="http://mathworld.wolfram.com/TrapezoidalRule.html">
* Trapezoid Rule</a> for integration of real univariate functions. For
* reference, see <b>Introduction to Numerical Analysis</b>, ISBN 038795452X,
* chapter 3.
* <p>
* The function should be integrable.</p>
*
* @since 1.2
*/
public class TrapezoidIntegrator extends BaseAbstractUnivariateIntegrator {
/** Maximum number of iterations for trapezoid. */
public static final int TRAPEZOID_MAX_ITERATIONS_COUNT = 64;
/** Intermediate result. */
private double s;
/**
* Build a trapezoid integrator with given accuracies and iterations counts.
* @param relativeAccuracy relative accuracy of the result
* @param absoluteAccuracy absolute accuracy of the result
* @param minimalIterationCount minimum number of iterations
* @param maximalIterationCount maximum number of iterations
* (must be less than or equal to {@link #TRAPEZOID_MAX_ITERATIONS_COUNT}
* @exception NotStrictlyPositiveException if minimal number of iterations
* is not strictly positive
* @exception NumberIsTooSmallException if maximal number of iterations
* is lesser than or equal to the minimal number of iterations
* @exception NumberIsTooLargeException if maximal number of iterations
* is greater than {@link #TRAPEZOID_MAX_ITERATIONS_COUNT}
*/
public TrapezoidIntegrator(final double relativeAccuracy,
final double absoluteAccuracy,
final int minimalIterationCount,
final int maximalIterationCount)
throws NotStrictlyPositiveException, NumberIsTooSmallException, NumberIsTooLargeException {
super(relativeAccuracy, absoluteAccuracy, minimalIterationCount, maximalIterationCount);
if (maximalIterationCount > TRAPEZOID_MAX_ITERATIONS_COUNT) {
throw new NumberIsTooLargeException(maximalIterationCount,
TRAPEZOID_MAX_ITERATIONS_COUNT, false);
}
}
/**
* Build a trapezoid integrator with given iteration counts.
* @param minimalIterationCount minimum number of iterations
* @param maximalIterationCount maximum number of iterations
* (must be less than or equal to {@link #TRAPEZOID_MAX_ITERATIONS_COUNT}
* @exception NotStrictlyPositiveException if minimal number of iterations
* is not strictly positive
* @exception NumberIsTooSmallException if maximal number of iterations
* is lesser than or equal to the minimal number of iterations
* @exception NumberIsTooLargeException if maximal number of iterations
* is greater than {@link #TRAPEZOID_MAX_ITERATIONS_COUNT}
*/
public TrapezoidIntegrator(final int minimalIterationCount,
final int maximalIterationCount)
throws NotStrictlyPositiveException, NumberIsTooSmallException, NumberIsTooLargeException {
super(minimalIterationCount, maximalIterationCount);
if (maximalIterationCount > TRAPEZOID_MAX_ITERATIONS_COUNT) {
throw new NumberIsTooLargeException(maximalIterationCount,
TRAPEZOID_MAX_ITERATIONS_COUNT, false);
}
}
/**
* Construct a trapezoid integrator with default settings.
* (max iteration count set to {@link #TRAPEZOID_MAX_ITERATIONS_COUNT})
*/
public TrapezoidIntegrator() {
super(DEFAULT_MIN_ITERATIONS_COUNT, TRAPEZOID_MAX_ITERATIONS_COUNT);
}
/**
* Compute the n-th stage integral of trapezoid rule. This function
* should only be called by API <code>integrate()</code> in the package.
* To save time it does not verify arguments - caller does.
* <p>
* The interval is divided equally into 2^n sections rather than an
* arbitrary m sections because this configuration can best utilize the
* already computed values.</p>
*
* @param baseIntegrator integrator holding integration parameters
* @param n the stage of 1/2 refinement, n = 0 is no refinement
* @return the value of n-th stage integral
* @throws TooManyEvaluationsException if the maximal number of evaluations
* is exceeded.
*/
double stage(final BaseAbstractUnivariateIntegrator baseIntegrator, final int n)
throws TooManyEvaluationsException {
if (n == 0) {
final double max = baseIntegrator.getMax();
final double min = baseIntegrator.getMin();
s = 0.5 * (max - min) *
(baseIntegrator.computeObjectiveValue(min) +
baseIntegrator.computeObjectiveValue(max));
return s;
} else {
final long np = 1L << (n-1); // number of new points in this stage
double sum = 0;
final double max = baseIntegrator.getMax();
final double min = baseIntegrator.getMin();
// spacing between adjacent new points
final double spacing = (max - min) / np;
double x = min + 0.5 * spacing; // the first new point
for (long i = 0; i < np; i++) {
sum += baseIntegrator.computeObjectiveValue(x);
x += spacing;
}
// add the new sum to previously calculated result
s = 0.5 * (s + sum * spacing);
return s;
}
}
/** {@inheritDoc} */
@Override
protected double doIntegrate()
throws MathIllegalArgumentException, TooManyEvaluationsException, MaxCountExceededException {
double oldt = stage(this, 0);
iterations.incrementCount();
while (true) {
final int i = iterations.getCount();
final double t = stage(this, i);
if (i >= getMinimalIterationCount()) {
final double delta = FastMath.abs(t - oldt);
final double rLimit =
getRelativeAccuracy() * (FastMath.abs(oldt) + FastMath.abs(t)) * 0.5;
if ((delta <= rLimit) || (delta <= getAbsoluteAccuracy())) {
return t;
}
}
oldt = t;
iterations.incrementCount();
}
}
}

View File

@ -1,95 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.integration;
import org.apache.commons.math4.analysis.UnivariateFunction;
import org.apache.commons.math4.exception.MathIllegalArgumentException;
import org.apache.commons.math4.exception.MaxCountExceededException;
import org.apache.commons.math4.exception.NullArgumentException;
import org.apache.commons.math4.exception.TooManyEvaluationsException;
/**
* Interface for univariate real integration algorithms.
*
* @since 1.2
*/
public interface UnivariateIntegrator {
/**
* Get the relative accuracy.
*
* @return the accuracy
*/
double getRelativeAccuracy();
/**
* Get the absolute accuracy.
*
* @return the accuracy
*/
double getAbsoluteAccuracy();
/**
* Get the min limit for the number of iterations.
*
* @return the actual min limit
*/
int getMinimalIterationCount();
/**
* Get the upper limit for the number of iterations.
*
* @return the actual upper limit
*/
int getMaximalIterationCount();
/**
* Integrate the function in the given interval.
*
* @param maxEval Maximum number of evaluations.
* @param f the integrand function
* @param min the lower bound for the interval
* @param max the upper bound for the interval
* @return the value of integral
* @throws TooManyEvaluationsException if the maximum number of function
* evaluations is exceeded
* @throws MaxCountExceededException if the maximum iteration count is exceeded
* or the integrator detects convergence problems otherwise
* @throws MathIllegalArgumentException if {@code min > max} or the endpoints do not
* satisfy the requirements specified by the integrator
* @throws NullArgumentException if {@code f} is {@code null}.
*/
double integrate(int maxEval, UnivariateFunction f, double min,
double max)
throws TooManyEvaluationsException, MaxCountExceededException,
MathIllegalArgumentException, NullArgumentException;
/**
* Get the number of function evaluations of the last run of the integrator.
*
* @return number of function evaluations
*/
int getEvaluations();
/**
* Get the number of iterations of the last run of the integrator.
*
* @return number of iterations
*/
int getIterations();
}

View File

@ -1,154 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.integration.gauss;
import java.util.Map;
import java.util.TreeMap;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.math4.util.Pair;
/**
* Base class for rules that determines the integration nodes and their
* weights.
* Subclasses must implement the {@link #computeRule(int) computeRule} method.
*
* @param <T> Type of the number used to represent the points and weights of
* the quadrature rules.
*
* @since 3.1
*/
public abstract class BaseRuleFactory<T extends Number> {
/** List of points and weights, indexed by the order of the rule. */
private final Map<Integer, Pair<T[], T[]>> pointsAndWeights
= new TreeMap<>();
/** Cache for double-precision rules. */
private final Map<Integer, Pair<double[], double[]>> pointsAndWeightsDouble
= new TreeMap<>();
/**
* Gets a copy of the quadrature rule with the given number of integration
* points.
*
* @param numberOfPoints Number of integration points.
* @return a copy of the integration rule.
* @throws NotStrictlyPositiveException if {@code numberOfPoints < 1}.
* @throws DimensionMismatchException if the elements of the rule pair do not
* have the same length.
*/
public Pair<double[], double[]> getRule(int numberOfPoints)
throws NotStrictlyPositiveException, DimensionMismatchException {
if (numberOfPoints <= 0) {
throw new NotStrictlyPositiveException(LocalizedFormats.NUMBER_OF_POINTS,
numberOfPoints);
}
// Try to obtain the rule from the cache.
Pair<double[], double[]> cached = pointsAndWeightsDouble.get(numberOfPoints);
if (cached == null) {
// Rule not computed yet.
// Compute the rule.
final Pair<T[], T[]> rule = getRuleInternal(numberOfPoints);
cached = convertToDouble(rule);
// Cache it.
pointsAndWeightsDouble.put(numberOfPoints, cached);
}
// Return a copy.
return new Pair<>(cached.getFirst().clone(),
cached.getSecond().clone());
}
/**
* Gets a rule.
* Synchronization ensures that rules will be computed and added to the
* cache at most once.
* The returned rule is a reference into the cache.
*
* @param numberOfPoints Order of the rule to be retrieved.
* @return the points and weights corresponding to the given order.
* @throws DimensionMismatchException if the elements of the rule pair do not
* have the same length.
*/
protected synchronized Pair<T[], T[]> getRuleInternal(int numberOfPoints)
throws DimensionMismatchException {
final Pair<T[], T[]> rule = pointsAndWeights.get(numberOfPoints);
if (rule == null) {
addRule(computeRule(numberOfPoints));
// The rule should be available now.
return getRuleInternal(numberOfPoints);
}
return rule;
}
/**
* Stores a rule.
*
* @param rule Rule to be stored.
* @throws DimensionMismatchException if the elements of the pair do not
* have the same length.
*/
protected void addRule(Pair<T[], T[]> rule) throws DimensionMismatchException {
if (rule.getFirst().length != rule.getSecond().length) {
throw new DimensionMismatchException(rule.getFirst().length,
rule.getSecond().length);
}
pointsAndWeights.put(rule.getFirst().length, rule);
}
/**
* Computes the rule for the given order.
*
* @param numberOfPoints Order of the rule to be computed.
* @return the computed rule.
* @throws DimensionMismatchException if the elements of the pair do not
* have the same length.
*/
protected abstract Pair<T[], T[]> computeRule(int numberOfPoints)
throws DimensionMismatchException;
/**
* Converts the from the actual {@code Number} type to {@code double}
*
* @param <T> Type of the number used to represent the points and
* weights of the quadrature rules.
* @param rule Points and weights.
* @return points and weights as {@code double}s.
*/
private static <T extends Number> Pair<double[], double[]> convertToDouble(Pair<T[], T[]> rule) {
final T[] pT = rule.getFirst();
final T[] wT = rule.getSecond();
final int len = pT.length;
final double[] pD = new double[len];
final double[] wD = new double[len];
for (int i = 0; i < len; i++) {
pD[i] = pT[i].doubleValue();
wD[i] = wT[i].doubleValue();
}
return new Pair<>(pD, wD);
}
}

View File

@ -1,129 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.integration.gauss;
import org.apache.commons.math4.analysis.UnivariateFunction;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.NonMonotonicSequenceException;
import org.apache.commons.math4.util.MathArrays;
import org.apache.commons.math4.util.Pair;
/**
* Class that implements the Gaussian rule for
* {@link #integrate(UnivariateFunction) integrating} a weighted
* function.
*
* @since 3.1
*/
public class GaussIntegrator {
/** Nodes. */
private final double[] points;
/** Nodes weights. */
private final double[] weights;
/**
* Creates an integrator from the given {@code points} and {@code weights}.
* The integration interval is defined by the first and last value of
* {@code points} which must be sorted in increasing order.
*
* @param points Integration points.
* @param weights Weights of the corresponding integration nodes.
* @throws NonMonotonicSequenceException if the {@code points} are not
* sorted in increasing order.
* @throws DimensionMismatchException if points and weights don't have the same length
*/
public GaussIntegrator(double[] points,
double[] weights)
throws NonMonotonicSequenceException, DimensionMismatchException {
if (points.length != weights.length) {
throw new DimensionMismatchException(points.length,
weights.length);
}
MathArrays.checkOrder(points, MathArrays.OrderDirection.INCREASING, true, true);
this.points = points.clone();
this.weights = weights.clone();
}
/**
* Creates an integrator from the given pair of points (first element of
* the pair) and weights (second element of the pair.
*
* @param pointsAndWeights Integration points and corresponding weights.
* @throws NonMonotonicSequenceException if the {@code points} are not
* sorted in increasing order.
*
* @see #GaussIntegrator(double[], double[])
*/
public GaussIntegrator(Pair<double[], double[]> pointsAndWeights)
throws NonMonotonicSequenceException {
this(pointsAndWeights.getFirst(), pointsAndWeights.getSecond());
}
/**
* Returns an estimate of the integral of {@code f(x) * w(x)},
* where {@code w} is a weight function that depends on the actual
* flavor of the Gauss integration scheme.
* The algorithm uses the points and associated weights, as passed
* to the {@link #GaussIntegrator(double[],double[]) constructor}.
*
* @param f Function to integrate.
* @return the integral of the weighted function.
*/
public double integrate(UnivariateFunction f) {
double s = 0;
double c = 0;
for (int i = 0; i < points.length; i++) {
final double x = points[i];
final double w = weights[i];
final double y = w * f.value(x) - c;
final double t = s + y;
c = (t - s) - y;
s = t;
}
return s;
}
/**
* @return the order of the integration rule (the number of integration
* points).
*/
public int getNumberOfPoints() {
return points.length;
}
/**
* Gets the integration point at the given index.
* The index must be in the valid range but no check is performed.
* @param index index of the integration point
* @return the integration point.
*/
public double getPoint(int index) {
return points[index];
}
/**
* Gets the weight of the integration point at the given index.
* The index must be in the valid range but no check is performed.
* @param index index of the integration point
* @return the weight.
*/
public double getWeight(int index) {
return weights[index];
}
}

View File

@ -1,188 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.integration.gauss;
import java.math.BigDecimal;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.util.Pair;
/**
* Class that provides different ways to compute the nodes and weights to be
* used by the {@link GaussIntegrator Gaussian integration rule}.
*
* @since 3.1
*/
public class GaussIntegratorFactory {
/** Generator of Gauss-Legendre integrators. */
private final BaseRuleFactory<Double> legendre = new LegendreRuleFactory();
/** Generator of Gauss-Legendre integrators. */
private final BaseRuleFactory<BigDecimal> legendreHighPrecision = new LegendreHighPrecisionRuleFactory();
/** Generator of Gauss-Hermite integrators. */
private final BaseRuleFactory<Double> hermite = new HermiteRuleFactory();
/** Generator of Gauss-Laguerre integrators. */
private final BaseRuleFactory<Double> laguerre = new LaguerreRuleFactory();
/**
* Creates a Gauss-Laguerre integrator of the given order.
* The call to the
* {@link GaussIntegrator#integrate(org.apache.commons.math4.analysis.UnivariateFunction)
* integrate} method will perform an integration on the interval
* \([0, +\infty)\): the computed value is the improper integral of
* \(e^{-x} f(x)\)
* where \(f(x)\) is the function passed to the
* {@link SymmetricGaussIntegrator#integrate(org.apache.commons.math4.analysis.UnivariateFunction)
* integrate} method.
*
* @param numberOfPoints Order of the integration rule.
* @return a Gauss-Legendre integrator.
* @since 4.0
*/
public GaussIntegrator laguerre(int numberOfPoints) {
return new GaussIntegrator(getRule(laguerre, numberOfPoints));
}
/**
* Creates a Gauss-Legendre integrator of the given order.
* The call to the
* {@link GaussIntegrator#integrate(org.apache.commons.math4.analysis.UnivariateFunction)
* integrate} method will perform an integration on the natural interval
* {@code [-1 , 1]}.
*
* @param numberOfPoints Order of the integration rule.
* @return a Gauss-Legendre integrator.
*/
public GaussIntegrator legendre(int numberOfPoints) {
return new GaussIntegrator(getRule(legendre, numberOfPoints));
}
/**
* Creates a Gauss-Legendre integrator of the given order.
* The call to the
* {@link GaussIntegrator#integrate(org.apache.commons.math4.analysis.UnivariateFunction)
* integrate} method will perform an integration on the given interval.
*
* @param numberOfPoints Order of the integration rule.
* @param lowerBound Lower bound of the integration interval.
* @param upperBound Upper bound of the integration interval.
* @return a Gauss-Legendre integrator.
* @throws NotStrictlyPositiveException if number of points is not positive
*/
public GaussIntegrator legendre(int numberOfPoints,
double lowerBound,
double upperBound)
throws NotStrictlyPositiveException {
return new GaussIntegrator(transform(getRule(legendre, numberOfPoints),
lowerBound, upperBound));
}
/**
* Creates a Gauss-Legendre integrator of the given order.
* The call to the
* {@link GaussIntegrator#integrate(org.apache.commons.math4.analysis.UnivariateFunction)
* integrate} method will perform an integration on the natural interval
* {@code [-1 , 1]}.
*
* @param numberOfPoints Order of the integration rule.
* @return a Gauss-Legendre integrator.
* @throws NotStrictlyPositiveException if number of points is not positive
*/
public GaussIntegrator legendreHighPrecision(int numberOfPoints)
throws NotStrictlyPositiveException {
return new GaussIntegrator(getRule(legendreHighPrecision, numberOfPoints));
}
/**
* Creates an integrator of the given order, and whose call to the
* {@link GaussIntegrator#integrate(org.apache.commons.math4.analysis.UnivariateFunction)
* integrate} method will perform an integration on the given interval.
*
* @param numberOfPoints Order of the integration rule.
* @param lowerBound Lower bound of the integration interval.
* @param upperBound Upper bound of the integration interval.
* @return a Gauss-Legendre integrator.
* @throws NotStrictlyPositiveException if number of points is not positive
*/
public GaussIntegrator legendreHighPrecision(int numberOfPoints,
double lowerBound,
double upperBound)
throws NotStrictlyPositiveException {
return new GaussIntegrator(transform(getRule(legendreHighPrecision, numberOfPoints),
lowerBound, upperBound));
}
/**
* Creates a Gauss-Hermite integrator of the given order.
* The call to the
* {@link SymmetricGaussIntegrator#integrate(org.apache.commons.math4.analysis.UnivariateFunction)
* integrate} method will perform a weighted integration on the interval
* \([-\infty, +\infty]\): the computed value is the improper integral of
* \(e^{-x^2}f(x)\)
* where \(f(x)\) is the function passed to the
* {@link SymmetricGaussIntegrator#integrate(org.apache.commons.math4.analysis.UnivariateFunction)
* integrate} method.
*
* @param numberOfPoints Order of the integration rule.
* @return a Gauss-Hermite integrator.
*/
public SymmetricGaussIntegrator hermite(int numberOfPoints) {
return new SymmetricGaussIntegrator(getRule(hermite, numberOfPoints));
}
/**
* @param factory Integration rule factory.
* @param numberOfPoints Order of the integration rule.
* @return the integration nodes and weights.
* @throws NotStrictlyPositiveException if number of points is not positive
* @throws DimensionMismatchException if the elements of the rule pair do not
* have the same length.
*/
private static Pair<double[], double[]> getRule(BaseRuleFactory<? extends Number> factory,
int numberOfPoints)
throws NotStrictlyPositiveException, DimensionMismatchException {
return factory.getRule(numberOfPoints);
}
/**
* Performs a change of variable so that the integration can be performed
* on an arbitrary interval {@code [a, b]}.
* It is assumed that the natural interval is {@code [-1, 1]}.
*
* @param rule Original points and weights.
* @param a Lower bound of the integration interval.
* @param b Lower bound of the integration interval.
* @return the points and weights adapted to the new interval.
*/
private static Pair<double[], double[]> transform(Pair<double[], double[]> rule,
double a,
double b) {
final double[] points = rule.getFirst();
final double[] weights = rule.getSecond();
// Scaling
final double scale = (b - a) / 2;
final double shift = a + scale;
for (int i = 0; i < points.length; i++) {
points[i] = points[i] * scale + shift;
weights[i] *= scale;
}
return new Pair<>(points, weights);
}
}

View File

@ -1,177 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.integration.gauss;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.util.FastMath;
import org.apache.commons.math4.util.Pair;
/**
* Factory that creates a
* <a href="http://en.wikipedia.org/wiki/Gauss-Hermite_quadrature">
* Gauss-type quadrature rule using Hermite polynomials</a>
* of the first kind.
* Such a quadrature rule allows the calculation of improper integrals
* of a function
* <p>
* \(f(x) e^{-x^2}\)
* </p><p>
* Recurrence relation and weights computation follow
* <a href="http://en.wikipedia.org/wiki/Abramowitz_and_Stegun">
* Abramowitz and Stegun, 1964</a>.
* </p><p>
* The coefficients of the standard Hermite polynomials grow very rapidly.
* In order to avoid overflows, each Hermite polynomial is normalized with
* respect to the underlying scalar product.
* The initial interval for the application of the bisection method is
* based on the roots of the previous Hermite polynomial (interlacing).
* Upper and lower bounds of these roots are provided by </p>
* <blockquote>
* I. Krasikov,
* <em>Nonnegative quadratic forms and bounds on orthogonal polynomials</em>,
* Journal of Approximation theory <b>111</b>, 31-49
* </blockquote>
*
* @since 3.3
*/
public class HermiteRuleFactory extends BaseRuleFactory<Double> {
/** &pi;<sup>1/2</sup> */
private static final double SQRT_PI = 1.77245385090551602729;
/** &pi;<sup>-1/4</sup> */
private static final double H0 = 7.5112554446494248286e-1;
/** &pi;<sup>-1/4</sup> &radic;2 */
private static final double H1 = 1.0622519320271969145;
/** {@inheritDoc} */
@Override
protected Pair<Double[], Double[]> computeRule(int numberOfPoints)
throws DimensionMismatchException {
if (numberOfPoints == 1) {
// Break recursion.
return new Pair<>(new Double[] { 0d },
new Double[] { SQRT_PI });
}
// Get previous rule.
// If it has not been computed yet it will trigger a recursive call
// to this method.
final int lastNumPoints = numberOfPoints - 1;
final Double[] previousPoints = getRuleInternal(lastNumPoints).getFirst();
// Compute next rule.
final Double[] points = new Double[numberOfPoints];
final Double[] weights = new Double[numberOfPoints];
final double sqrtTwoTimesLastNumPoints = FastMath.sqrt(2 * lastNumPoints);
final double sqrtTwoTimesNumPoints = FastMath.sqrt(2 * numberOfPoints);
// Find i-th root of H[n+1] by bracketing.
final int iMax = numberOfPoints / 2;
for (int i = 0; i < iMax; i++) {
// Lower-bound of the interval.
double a = (i == 0) ? -sqrtTwoTimesLastNumPoints : previousPoints[i - 1].doubleValue();
// Upper-bound of the interval.
double b = (iMax == 1) ? -0.5 : previousPoints[i].doubleValue();
// H[j-1](a)
double hma = H0;
// H[j](a)
double ha = H1 * a;
// H[j-1](b)
double hmb = H0;
// H[j](b)
double hb = H1 * b;
for (int j = 1; j < numberOfPoints; j++) {
// Compute H[j+1](a) and H[j+1](b)
final double jp1 = j + 1;
final double s = FastMath.sqrt(2 / jp1);
final double sm = FastMath.sqrt(j / jp1);
final double hpa = s * a * ha - sm * hma;
final double hpb = s * b * hb - sm * hmb;
hma = ha;
ha = hpa;
hmb = hb;
hb = hpb;
}
// Now ha = H[n+1](a), and hma = H[n](a) (same holds for b).
// Middle of the interval.
double c = 0.5 * (a + b);
// P[j-1](c)
double hmc = H0;
// P[j](c)
double hc = H1 * c;
boolean done = false;
while (!done) {
done = b - a <= Math.ulp(c);
hmc = H0;
hc = H1 * c;
for (int j = 1; j < numberOfPoints; j++) {
// Compute H[j+1](c)
final double jp1 = j + 1;
final double s = FastMath.sqrt(2 / jp1);
final double sm = FastMath.sqrt(j / jp1);
final double hpc = s * c * hc - sm * hmc;
hmc = hc;
hc = hpc;
}
// Now h = H[n+1](c) and hm = H[n](c).
if (!done) {
if (ha * hc < 0) {
b = c;
hmb = hmc;
hb = hc;
} else {
a = c;
hma = hmc;
ha = hc;
}
c = 0.5 * (a + b);
}
}
final double d = sqrtTwoTimesNumPoints * hmc;
final double w = 2 / (d * d);
points[i] = c;
weights[i] = w;
final int idx = lastNumPoints - i;
points[idx] = -c;
weights[idx] = w;
}
// If "numberOfPoints" is odd, 0 is a root.
// Note: as written, the test for oddness will work for negative
// integers too (although it is not necessary here), preventing
// a FindBugs warning.
if (numberOfPoints % 2 != 0) {
double hm = H0;
for (int j = 1; j < numberOfPoints; j += 2) {
final double jp1 = j + 1;
hm = -FastMath.sqrt(j / jp1) * hm;
}
final double d = sqrtTwoTimesNumPoints * hm;
final double w = 2 / (d * d);
points[iMax] = 0d;
weights[iMax] = w;
}
return new Pair<>(points, weights);
}
}

View File

@ -1,84 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.integration.gauss;
import java.util.Arrays;
import org.apache.commons.math4.analysis.polynomials.PolynomialFunction;
import org.apache.commons.math4.analysis.polynomials.PolynomialsUtils;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.linear.EigenDecomposition;
import org.apache.commons.math4.linear.MatrixUtils;
import org.apache.commons.math4.linear.RealMatrix;
import org.apache.commons.math4.util.Pair;
/**
* Factory that creates Gauss-type quadrature rule using Laguerre polynomials.
*
* @see <a href="http://en.wikipedia.org/wiki/Gauss%E2%80%93Laguerre_quadrature">Gauss-Laguerre quadrature (Wikipedia)</a>
* @since 4.0
*/
public class LaguerreRuleFactory extends BaseRuleFactory<Double> {
/** {@inheritDoc} */
@Override
protected Pair<Double[], Double[]> computeRule(int numberOfPoints)
throws DimensionMismatchException {
final RealMatrix companionMatrix = companionMatrix(numberOfPoints);
final EigenDecomposition eigen = new EigenDecomposition(companionMatrix);
final double[] roots = eigen.getRealEigenvalues();
Arrays.sort(roots);
final Double[] points = new Double[numberOfPoints];
final Double[] weights = new Double[numberOfPoints];
final int n1 = numberOfPoints + 1;
final long n1Squared = n1 * (long) n1;
final PolynomialFunction laguerreN1 = PolynomialsUtils.createLaguerrePolynomial(n1);
for (int i = 0; i < numberOfPoints; i++) {
final double xi = roots[i];
points[i] = xi;
final double val = laguerreN1.value(xi);
weights[i] = xi / n1Squared / (val * val);
}
return new Pair<>(points, weights);
}
/**
* @param degree Matrix dimension.
* @return a square matrix.
*/
private RealMatrix companionMatrix(final int degree) {
final RealMatrix c = MatrixUtils.createRealMatrix(degree, degree);
for (int i = 0; i < degree; i++) {
c.setEntry(i, i, 2 * i + 1);
if (i + 1 < degree) {
// subdiagonal
c.setEntry(i+1, i, -(i + 1));
}
if (i - 1 >= 0) {
// superdiagonal
c.setEntry(i-1, i, -i);
}
}
return c;
}
}

View File

@ -1,215 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.integration.gauss;
import java.math.BigDecimal;
import java.math.MathContext;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.util.Pair;
/**
* Factory that creates Gauss-type quadrature rule using Legendre polynomials.
* In this implementation, the lower and upper bounds of the natural interval
* of integration are -1 and 1, respectively.
* The Legendre polynomials are evaluated using the recurrence relation
* presented in <a href="http://en.wikipedia.org/wiki/Abramowitz_and_Stegun">
* Abramowitz and Stegun, 1964</a>.
*
* @since 3.1
*/
public class LegendreHighPrecisionRuleFactory extends BaseRuleFactory<BigDecimal> {
/** Settings for enhanced precision computations. */
private final MathContext mContext;
/** The number {@code 2}. */
private final BigDecimal two;
/** The number {@code -1}. */
private final BigDecimal minusOne;
/** The number {@code 0.5}. */
private final BigDecimal oneHalf;
/**
* Default precision is {@link MathContext#DECIMAL128 DECIMAL128}.
*/
public LegendreHighPrecisionRuleFactory() {
this(MathContext.DECIMAL128);
}
/**
* @param mContext Precision setting for computing the quadrature rules.
*/
public LegendreHighPrecisionRuleFactory(MathContext mContext) {
this.mContext = mContext;
two = new BigDecimal("2", mContext);
minusOne = new BigDecimal("-1", mContext);
oneHalf = new BigDecimal("0.5", mContext);
}
/** {@inheritDoc} */
@Override
protected Pair<BigDecimal[], BigDecimal[]> computeRule(int numberOfPoints)
throws DimensionMismatchException {
if (numberOfPoints == 1) {
// Break recursion.
return new Pair<>(new BigDecimal[] { BigDecimal.ZERO },
new BigDecimal[] { two });
}
// Get previous rule.
// If it has not been computed yet it will trigger a recursive call
// to this method.
final BigDecimal[] previousPoints = getRuleInternal(numberOfPoints - 1).getFirst();
// Compute next rule.
final BigDecimal[] points = new BigDecimal[numberOfPoints];
final BigDecimal[] weights = new BigDecimal[numberOfPoints];
// Find i-th root of P[n+1] by bracketing.
final int iMax = numberOfPoints / 2;
for (int i = 0; i < iMax; i++) {
// Lower-bound of the interval.
BigDecimal a = (i == 0) ? minusOne : previousPoints[i - 1];
// Upper-bound of the interval.
BigDecimal b = (iMax == 1) ? BigDecimal.ONE : previousPoints[i];
// P[j-1](a)
BigDecimal pma = BigDecimal.ONE;
// P[j](a)
BigDecimal pa = a;
// P[j-1](b)
BigDecimal pmb = BigDecimal.ONE;
// P[j](b)
BigDecimal pb = b;
for (int j = 1; j < numberOfPoints; j++) {
final BigDecimal b_two_j_p_1 = new BigDecimal(2 * j + 1, mContext);
final BigDecimal b_j = new BigDecimal(j, mContext);
final BigDecimal b_j_p_1 = new BigDecimal(j + 1, mContext);
// Compute P[j+1](a)
// ppa = ((2 * j + 1) * a * pa - j * pma) / (j + 1);
BigDecimal tmp1 = a.multiply(b_two_j_p_1, mContext);
tmp1 = pa.multiply(tmp1, mContext);
BigDecimal tmp2 = pma.multiply(b_j, mContext);
// P[j+1](a)
BigDecimal ppa = tmp1.subtract(tmp2, mContext);
ppa = ppa.divide(b_j_p_1, mContext);
// Compute P[j+1](b)
// ppb = ((2 * j + 1) * b * pb - j * pmb) / (j + 1);
tmp1 = b.multiply(b_two_j_p_1, mContext);
tmp1 = pb.multiply(tmp1, mContext);
tmp2 = pmb.multiply(b_j, mContext);
// P[j+1](b)
BigDecimal ppb = tmp1.subtract(tmp2, mContext);
ppb = ppb.divide(b_j_p_1, mContext);
pma = pa;
pa = ppa;
pmb = pb;
pb = ppb;
}
// Now pa = P[n+1](a), and pma = P[n](a). Same holds for b.
// Middle of the interval.
BigDecimal c = a.add(b, mContext).multiply(oneHalf, mContext);
// P[j-1](c)
BigDecimal pmc = BigDecimal.ONE;
// P[j](c)
BigDecimal pc = c;
boolean done = false;
while (!done) {
BigDecimal tmp1 = b.subtract(a, mContext);
BigDecimal tmp2 = c.ulp().multiply(BigDecimal.TEN, mContext);
done = tmp1.compareTo(tmp2) <= 0;
pmc = BigDecimal.ONE;
pc = c;
for (int j = 1; j < numberOfPoints; j++) {
final BigDecimal b_two_j_p_1 = new BigDecimal(2 * j + 1, mContext);
final BigDecimal b_j = new BigDecimal(j, mContext);
final BigDecimal b_j_p_1 = new BigDecimal(j + 1, mContext);
// Compute P[j+1](c)
tmp1 = c.multiply(b_two_j_p_1, mContext);
tmp1 = pc.multiply(tmp1, mContext);
tmp2 = pmc.multiply(b_j, mContext);
// P[j+1](c)
BigDecimal ppc = tmp1.subtract(tmp2, mContext);
ppc = ppc.divide(b_j_p_1, mContext);
pmc = pc;
pc = ppc;
}
// Now pc = P[n+1](c) and pmc = P[n](c).
if (!done) {
if (pa.signum() * pc.signum() <= 0) {
b = c;
pmb = pmc;
pb = pc;
} else {
a = c;
pma = pmc;
pa = pc;
}
c = a.add(b, mContext).multiply(oneHalf, mContext);
}
}
final BigDecimal nP = new BigDecimal(numberOfPoints, mContext);
BigDecimal tmp1 = pmc.subtract(c.multiply(pc, mContext), mContext);
tmp1 = tmp1.multiply(nP);
tmp1 = tmp1.pow(2, mContext);
BigDecimal tmp2 = c.pow(2, mContext);
tmp2 = BigDecimal.ONE.subtract(tmp2, mContext);
tmp2 = tmp2.multiply(two, mContext);
tmp2 = tmp2.divide(tmp1, mContext);
points[i] = c;
weights[i] = tmp2;
final int idx = numberOfPoints - i - 1;
points[idx] = c.negate(mContext);
weights[idx] = tmp2;
}
// If "numberOfPoints" is odd, 0 is a root.
// Note: as written, the test for oddness will work for negative
// integers too (although it is not necessary here), preventing
// a FindBugs warning.
if (numberOfPoints % 2 != 0) {
BigDecimal pmc = BigDecimal.ONE;
for (int j = 1; j < numberOfPoints; j += 2) {
final BigDecimal b_j = new BigDecimal(j, mContext);
final BigDecimal b_j_p_1 = new BigDecimal(j + 1, mContext);
// pmc = -j * pmc / (j + 1);
pmc = pmc.multiply(b_j, mContext);
pmc = pmc.divide(b_j_p_1, mContext);
pmc = pmc.negate(mContext);
}
// 2 / pow(numberOfPoints * pmc, 2);
final BigDecimal nP = new BigDecimal(numberOfPoints, mContext);
BigDecimal tmp1 = pmc.multiply(nP, mContext);
tmp1 = tmp1.pow(2, mContext);
BigDecimal tmp2 = two.divide(tmp1, mContext);
points[iMax] = BigDecimal.ZERO;
weights[iMax] = tmp2;
}
return new Pair<>(points, weights);
}
}

View File

@ -1,140 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.integration.gauss;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.util.Pair;
/**
* Factory that creates Gauss-type quadrature rule using Legendre polynomials.
* In this implementation, the lower and upper bounds of the natural interval
* of integration are -1 and 1, respectively.
* The Legendre polynomials are evaluated using the recurrence relation
* presented in <a href="http://en.wikipedia.org/wiki/Abramowitz_and_Stegun">
* Abramowitz and Stegun, 1964</a>.
*
* @since 3.1
*/
public class LegendreRuleFactory extends BaseRuleFactory<Double> {
/** {@inheritDoc} */
@Override
protected Pair<Double[], Double[]> computeRule(int numberOfPoints)
throws DimensionMismatchException {
if (numberOfPoints == 1) {
// Break recursion.
return new Pair<>(new Double[] { 0d },
new Double[] { 2d });
}
// Get previous rule.
// If it has not been computed yet it will trigger a recursive call
// to this method.
final Double[] previousPoints = getRuleInternal(numberOfPoints - 1).getFirst();
// Compute next rule.
final Double[] points = new Double[numberOfPoints];
final Double[] weights = new Double[numberOfPoints];
// Find i-th root of P[n+1] by bracketing.
final int iMax = numberOfPoints / 2;
for (int i = 0; i < iMax; i++) {
// Lower-bound of the interval.
double a = (i == 0) ? -1 : previousPoints[i - 1].doubleValue();
// Upper-bound of the interval.
double b = (iMax == 1) ? 1 : previousPoints[i].doubleValue();
// P[j-1](a)
double pma = 1;
// P[j](a)
double pa = a;
// P[j-1](b)
double pmb = 1;
// P[j](b)
double pb = b;
for (int j = 1; j < numberOfPoints; j++) {
final int two_j_p_1 = 2 * j + 1;
final int j_p_1 = j + 1;
// P[j+1](a)
final double ppa = (two_j_p_1 * a * pa - j * pma) / j_p_1;
// P[j+1](b)
final double ppb = (two_j_p_1 * b * pb - j * pmb) / j_p_1;
pma = pa;
pa = ppa;
pmb = pb;
pb = ppb;
}
// Now pa = P[n+1](a), and pma = P[n](a) (same holds for b).
// Middle of the interval.
double c = 0.5 * (a + b);
// P[j-1](c)
double pmc = 1;
// P[j](c)
double pc = c;
boolean done = false;
while (!done) {
done = b - a <= Math.ulp(c);
pmc = 1;
pc = c;
for (int j = 1; j < numberOfPoints; j++) {
// P[j+1](c)
final double ppc = ((2 * j + 1) * c * pc - j * pmc) / (j + 1);
pmc = pc;
pc = ppc;
}
// Now pc = P[n+1](c) and pmc = P[n](c).
if (!done) {
if (pa * pc <= 0) {
b = c;
pmb = pmc;
pb = pc;
} else {
a = c;
pma = pmc;
pa = pc;
}
c = 0.5 * (a + b);
}
}
final double d = numberOfPoints * (pmc - c * pc);
final double w = 2 * (1 - c * c) / (d * d);
points[i] = c;
weights[i] = w;
final int idx = numberOfPoints - i - 1;
points[idx] = -c;
weights[idx] = w;
}
// If "numberOfPoints" is odd, 0 is a root.
// Note: as written, the test for oddness will work for negative
// integers too (although it is not necessary here), preventing
// a FindBugs warning.
if (numberOfPoints % 2 != 0) {
double pmc = 1;
for (int j = 1; j < numberOfPoints; j += 2) {
pmc = -j * pmc / (j + 1);
}
final double d = numberOfPoints * pmc;
final double w = 2 / (d * d);
points[iMax] = 0d;
weights[iMax] = w;
}
return new Pair<>(points, weights);
}
}

View File

@ -1,103 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.integration.gauss;
import org.apache.commons.math4.analysis.UnivariateFunction;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.NonMonotonicSequenceException;
import org.apache.commons.math4.util.Pair;
/**
* This class's implements {@link #integrate(UnivariateFunction) integrate}
* method assuming that the integral is symmetric about 0.
* This allows to reduce numerical errors.
*
* @since 3.3
*/
public class SymmetricGaussIntegrator extends GaussIntegrator {
/**
* Creates an integrator from the given {@code points} and {@code weights}.
* The integration interval is defined by the first and last value of
* {@code points} which must be sorted in increasing order.
*
* @param points Integration points.
* @param weights Weights of the corresponding integration nodes.
* @throws NonMonotonicSequenceException if the {@code points} are not
* sorted in increasing order.
* @throws DimensionMismatchException if points and weights don't have the same length
*/
public SymmetricGaussIntegrator(double[] points,
double[] weights)
throws NonMonotonicSequenceException, DimensionMismatchException {
super(points, weights);
}
/**
* Creates an integrator from the given pair of points (first element of
* the pair) and weights (second element of the pair.
*
* @param pointsAndWeights Integration points and corresponding weights.
* @throws NonMonotonicSequenceException if the {@code points} are not
* sorted in increasing order.
*
* @see #SymmetricGaussIntegrator(double[], double[])
*/
public SymmetricGaussIntegrator(Pair<double[], double[]> pointsAndWeights)
throws NonMonotonicSequenceException {
this(pointsAndWeights.getFirst(), pointsAndWeights.getSecond());
}
/**
* {@inheritDoc}
*/
@Override
public double integrate(UnivariateFunction f) {
final int ruleLength = getNumberOfPoints();
if (ruleLength == 1) {
return getWeight(0) * f.value(0d);
}
final int iMax = ruleLength / 2;
double s = 0;
double c = 0;
for (int i = 0; i < iMax; i++) {
final double p = getPoint(i);
final double w = getWeight(i);
final double f1 = f.value(p);
final double f2 = f.value(-p);
final double y = w * (f1 + f2) - c;
final double t = s + y;
c = (t - s) - y;
s = t;
}
if (ruleLength % 2 != 0) {
final double w = getWeight(iMax);
final double y = w * f.value(0d) - c;
final double t = s + y;
s = t;
}
return s;
}
}

View File

@ -1,22 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* Gauss family of quadrature schemes.
*
*/
package org.apache.commons.math4.analysis.integration.gauss;

View File

@ -1,22 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* Numerical integration (quadrature) algorithms for univariate real functions.
*
*/
package org.apache.commons.math4.analysis.integration;

View File

@ -1,216 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.interpolation;
import org.apache.commons.math4.analysis.polynomials.PolynomialFunction;
import org.apache.commons.math4.analysis.polynomials.PolynomialSplineFunction;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.NonMonotonicSequenceException;
import org.apache.commons.math4.exception.NullArgumentException;
import org.apache.commons.math4.exception.NumberIsTooSmallException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.math4.util.FastMath;
import org.apache.commons.math4.util.MathArrays;
import org.apache.commons.numbers.core.Precision;
/**
* Computes a cubic spline interpolation for the data set using the Akima
* algorithm, as originally formulated by Hiroshi Akima in his 1970 paper
* "A New Method of Interpolation and Smooth Curve Fitting Based on Local Procedures."
* J. ACM 17, 4 (October 1970), 589-602. DOI=10.1145/321607.321609
* http://doi.acm.org/10.1145/321607.321609
* <p>
* This implementation is based on the Akima implementation in the CubicSpline
* class in the Math.NET Numerics library. The method referenced is
* CubicSpline.InterpolateAkimaSorted
* </p>
* <p>
* The {@link #interpolate(double[], double[]) interpolate} method returns a
* {@link PolynomialSplineFunction} consisting of n cubic polynomials, defined
* over the subintervals determined by the x values, {@code x[0] < x[i] ... < x[n]}.
* The Akima algorithm requires that {@code n >= 5}.
* </p>
*/
public class AkimaSplineInterpolator
implements UnivariateInterpolator {
/** The minimum number of points that are needed to compute the function. */
private static final int MINIMUM_NUMBER_POINTS = 5;
/**
* Computes an interpolating function for the data set.
*
* @param xvals the arguments for the interpolation points
* @param yvals the values for the interpolation points
* @return a function which interpolates the data set
* @throws DimensionMismatchException if {@code xvals} and {@code yvals} have
* different sizes.
* @throws NonMonotonicSequenceException if {@code xvals} is not sorted in
* strict increasing order.
* @throws NumberIsTooSmallException if the size of {@code xvals} is smaller
* than 5.
*/
@Override
public PolynomialSplineFunction interpolate(double[] xvals,
double[] yvals)
throws DimensionMismatchException,
NumberIsTooSmallException,
NonMonotonicSequenceException {
if (xvals == null ||
yvals == null) {
throw new NullArgumentException();
}
if (xvals.length != yvals.length) {
throw new DimensionMismatchException(xvals.length, yvals.length);
}
if (xvals.length < MINIMUM_NUMBER_POINTS) {
throw new NumberIsTooSmallException(LocalizedFormats.NUMBER_OF_POINTS,
xvals.length,
MINIMUM_NUMBER_POINTS, true);
}
MathArrays.checkOrder(xvals);
final int numberOfDiffAndWeightElements = xvals.length - 1;
final double[] differences = new double[numberOfDiffAndWeightElements];
final double[] weights = new double[numberOfDiffAndWeightElements];
for (int i = 0; i < differences.length; i++) {
differences[i] = (yvals[i + 1] - yvals[i]) / (xvals[i + 1] - xvals[i]);
}
for (int i = 1; i < weights.length; i++) {
weights[i] = FastMath.abs(differences[i] - differences[i - 1]);
}
// Prepare Hermite interpolation scheme.
final double[] firstDerivatives = new double[xvals.length];
for (int i = 2; i < firstDerivatives.length - 2; i++) {
final double wP = weights[i + 1];
final double wM = weights[i - 1];
if (Precision.equals(wP, 0.0) &&
Precision.equals(wM, 0.0)) {
final double xv = xvals[i];
final double xvP = xvals[i + 1];
final double xvM = xvals[i - 1];
firstDerivatives[i] = (((xvP - xv) * differences[i - 1]) + ((xv - xvM) * differences[i])) / (xvP - xvM);
} else {
firstDerivatives[i] = ((wP * differences[i - 1]) + (wM * differences[i])) / (wP + wM);
}
}
firstDerivatives[0] = differentiateThreePoint(xvals, yvals, 0, 0, 1, 2);
firstDerivatives[1] = differentiateThreePoint(xvals, yvals, 1, 0, 1, 2);
firstDerivatives[xvals.length - 2] = differentiateThreePoint(xvals, yvals, xvals.length - 2,
xvals.length - 3, xvals.length - 2,
xvals.length - 1);
firstDerivatives[xvals.length - 1] = differentiateThreePoint(xvals, yvals, xvals.length - 1,
xvals.length - 3, xvals.length - 2,
xvals.length - 1);
return interpolateHermiteSorted(xvals, yvals, firstDerivatives);
}
/**
* Three point differentiation helper, modeled off of the same method in the
* Math.NET CubicSpline class. This is used by both the Apache Math and the
* Math.NET Akima Cubic Spline algorithms
*
* @param xvals x values to calculate the numerical derivative with
* @param yvals y values to calculate the numerical derivative with
* @param indexOfDifferentiation index of the elemnt we are calculating the derivative around
* @param indexOfFirstSample index of the first element to sample for the three point method
* @param indexOfSecondsample index of the second element to sample for the three point method
* @param indexOfThirdSample index of the third element to sample for the three point method
* @return the derivative
*/
private double differentiateThreePoint(double[] xvals, double[] yvals,
int indexOfDifferentiation,
int indexOfFirstSample,
int indexOfSecondsample,
int indexOfThirdSample) {
final double x0 = yvals[indexOfFirstSample];
final double x1 = yvals[indexOfSecondsample];
final double x2 = yvals[indexOfThirdSample];
final double t = xvals[indexOfDifferentiation] - xvals[indexOfFirstSample];
final double t1 = xvals[indexOfSecondsample] - xvals[indexOfFirstSample];
final double t2 = xvals[indexOfThirdSample] - xvals[indexOfFirstSample];
final double a = (x2 - x0 - (t2 / t1 * (x1 - x0))) / (t2 * t2 - t1 * t2);
final double b = (x1 - x0 - a * t1 * t1) / t1;
return (2 * a * t) + b;
}
/**
* Creates a Hermite cubic spline interpolation from the set of (x,y) value
* pairs and their derivatives. This is modeled off of the
* InterpolateHermiteSorted method in the Math.NET CubicSpline class.
*
* @param xvals x values for interpolation
* @param yvals y values for interpolation
* @param firstDerivatives first derivative values of the function
* @return polynomial that fits the function
*/
private PolynomialSplineFunction interpolateHermiteSorted(double[] xvals,
double[] yvals,
double[] firstDerivatives) {
if (xvals.length != yvals.length) {
throw new DimensionMismatchException(xvals.length, yvals.length);
}
if (xvals.length != firstDerivatives.length) {
throw new DimensionMismatchException(xvals.length,
firstDerivatives.length);
}
final int minimumLength = 2;
if (xvals.length < minimumLength) {
throw new NumberIsTooSmallException(LocalizedFormats.NUMBER_OF_POINTS,
xvals.length, minimumLength,
true);
}
final int size = xvals.length - 1;
final PolynomialFunction[] polynomials = new PolynomialFunction[size];
final double[] coefficients = new double[4];
for (int i = 0; i < polynomials.length; i++) {
final double w = xvals[i + 1] - xvals[i];
final double w2 = w * w;
final double yv = yvals[i];
final double yvP = yvals[i + 1];
final double fd = firstDerivatives[i];
final double fdP = firstDerivatives[i + 1];
coefficients[0] = yv;
coefficients[1] = firstDerivatives[i];
coefficients[2] = (3 * (yvP - yv) / w - 2 * fd - fdP) / w;
coefficients[3] = (2 * (yv - yvP) / w + fd + fdP) / w2;
polynomials[i] = new PolynomialFunction(coefficients);
}
return new PolynomialSplineFunction(xvals, polynomials);
}
}

View File

@ -1,329 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.interpolation;
import java.util.Arrays;
import org.apache.commons.numbers.arrays.LinearCombination;
import org.apache.commons.math4.analysis.BivariateFunction;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.NoDataException;
import org.apache.commons.math4.exception.NonMonotonicSequenceException;
import org.apache.commons.math4.exception.OutOfRangeException;
import org.apache.commons.math4.util.MathArrays;
/**
* Function that implements the
* <a href="http://en.wikipedia.org/wiki/Bicubic_interpolation">
* bicubic spline interpolation</a>.
*
* @since 3.4
*/
public class BicubicInterpolatingFunction
implements BivariateFunction {
/** Number of coefficients. */
private static final int NUM_COEFF = 16;
/**
* Matrix to compute the spline coefficients from the function values
* and function derivatives values
*/
private static final double[][] AINV = {
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0 },
{ -3,3,0,0,-2,-1,0,0,0,0,0,0,0,0,0,0 },
{ 2,-2,0,0,1,1,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0 },
{ 0,0,0,0,0,0,0,0,-3,3,0,0,-2,-1,0,0 },
{ 0,0,0,0,0,0,0,0,2,-2,0,0,1,1,0,0 },
{ -3,0,3,0,0,0,0,0,-2,0,-1,0,0,0,0,0 },
{ 0,0,0,0,-3,0,3,0,0,0,0,0,-2,0,-1,0 },
{ 9,-9,-9,9,6,3,-6,-3,6,-6,3,-3,4,2,2,1 },
{ -6,6,6,-6,-3,-3,3,3,-4,4,-2,2,-2,-2,-1,-1 },
{ 2,0,-2,0,0,0,0,0,1,0,1,0,0,0,0,0 },
{ 0,0,0,0,2,0,-2,0,0,0,0,0,1,0,1,0 },
{ -6,6,6,-6,-4,-2,4,2,-3,3,-3,3,-2,-1,-2,-1 },
{ 4,-4,-4,4,2,2,-2,-2,2,-2,2,-2,1,1,1,1 }
};
/** Samples x-coordinates */
private final double[] xval;
/** Samples y-coordinates */
private final double[] yval;
/** Set of cubic splines patching the whole data grid */
private final BicubicFunction[][] splines;
/**
* @param x Sample values of the x-coordinate, in increasing order.
* @param y Sample values of the y-coordinate, in increasing order.
* @param f Values of the function on every grid point.
* @param dFdX Values of the partial derivative of function with respect
* to x on every grid point.
* @param dFdY Values of the partial derivative of function with respect
* to y on every grid point.
* @param d2FdXdY Values of the cross partial derivative of function on
* every grid point.
* @throws DimensionMismatchException if the various arrays do not contain
* the expected number of elements.
* @throws NonMonotonicSequenceException if {@code x} or {@code y} are
* not strictly increasing.
* @throws NoDataException if any of the arrays has zero length.
*/
public BicubicInterpolatingFunction(double[] x,
double[] y,
double[][] f,
double[][] dFdX,
double[][] dFdY,
double[][] d2FdXdY)
throws DimensionMismatchException,
NoDataException,
NonMonotonicSequenceException {
final int xLen = x.length;
final int yLen = y.length;
if (xLen == 0 || yLen == 0 || f.length == 0 || f[0].length == 0) {
throw new NoDataException();
}
if (xLen != f.length) {
throw new DimensionMismatchException(xLen, f.length);
}
if (xLen != dFdX.length) {
throw new DimensionMismatchException(xLen, dFdX.length);
}
if (xLen != dFdY.length) {
throw new DimensionMismatchException(xLen, dFdY.length);
}
if (xLen != d2FdXdY.length) {
throw new DimensionMismatchException(xLen, d2FdXdY.length);
}
MathArrays.checkOrder(x);
MathArrays.checkOrder(y);
xval = x.clone();
yval = y.clone();
final int lastI = xLen - 1;
final int lastJ = yLen - 1;
splines = new BicubicFunction[lastI][lastJ];
for (int i = 0; i < lastI; i++) {
if (f[i].length != yLen) {
throw new DimensionMismatchException(f[i].length, yLen);
}
if (dFdX[i].length != yLen) {
throw new DimensionMismatchException(dFdX[i].length, yLen);
}
if (dFdY[i].length != yLen) {
throw new DimensionMismatchException(dFdY[i].length, yLen);
}
if (d2FdXdY[i].length != yLen) {
throw new DimensionMismatchException(d2FdXdY[i].length, yLen);
}
final int ip1 = i + 1;
final double xR = xval[ip1] - xval[i];
for (int j = 0; j < lastJ; j++) {
final int jp1 = j + 1;
final double yR = yval[jp1] - yval[j];
final double xRyR = xR * yR;
final double[] beta = new double[] {
f[i][j], f[ip1][j], f[i][jp1], f[ip1][jp1],
dFdX[i][j] * xR, dFdX[ip1][j] * xR, dFdX[i][jp1] * xR, dFdX[ip1][jp1] * xR,
dFdY[i][j] * yR, dFdY[ip1][j] * yR, dFdY[i][jp1] * yR, dFdY[ip1][jp1] * yR,
d2FdXdY[i][j] * xRyR, d2FdXdY[ip1][j] * xRyR, d2FdXdY[i][jp1] * xRyR, d2FdXdY[ip1][jp1] * xRyR
};
splines[i][j] = new BicubicFunction(computeSplineCoefficients(beta));
}
}
}
/**
* {@inheritDoc}
*/
@Override
public double value(double x, double y)
throws OutOfRangeException {
final int i = searchIndex(x, xval);
final int j = searchIndex(y, yval);
final double xN = (x - xval[i]) / (xval[i + 1] - xval[i]);
final double yN = (y - yval[j]) / (yval[j + 1] - yval[j]);
return splines[i][j].value(xN, yN);
}
/**
* Indicates whether a point is within the interpolation range.
*
* @param x First coordinate.
* @param y Second coordinate.
* @return {@code true} if (x, y) is a valid point.
*/
public boolean isValidPoint(double x, double y) {
if (x < xval[0] ||
x > xval[xval.length - 1] ||
y < yval[0] ||
y > yval[yval.length - 1]) {
return false;
} else {
return true;
}
}
/**
* @param c Coordinate.
* @param val Coordinate samples.
* @return the index in {@code val} corresponding to the interval
* containing {@code c}.
* @throws OutOfRangeException if {@code c} is out of the
* range defined by the boundary values of {@code val}.
*/
private int searchIndex(double c, double[] val) {
final int r = Arrays.binarySearch(val, c);
if (r == -1 ||
r == -val.length - 1) {
throw new OutOfRangeException(c, val[0], val[val.length - 1]);
}
if (r < 0) {
// "c" in within an interpolation sub-interval: Return the
// index of the sample at the lower end of the sub-interval.
return -r - 2;
}
final int last = val.length - 1;
if (r == last) {
// "c" is the last sample of the range: Return the index
// of the sample at the lower end of the last sub-interval.
return last - 1;
}
// "c" is another sample point.
return r;
}
/**
* Compute the spline coefficients from the list of function values and
* function partial derivatives values at the four corners of a grid
* element. They must be specified in the following order:
* <ul>
* <li>f(0,0)</li>
* <li>f(1,0)</li>
* <li>f(0,1)</li>
* <li>f(1,1)</li>
* <li>f<sub>x</sub>(0,0)</li>
* <li>f<sub>x</sub>(1,0)</li>
* <li>f<sub>x</sub>(0,1)</li>
* <li>f<sub>x</sub>(1,1)</li>
* <li>f<sub>y</sub>(0,0)</li>
* <li>f<sub>y</sub>(1,0)</li>
* <li>f<sub>y</sub>(0,1)</li>
* <li>f<sub>y</sub>(1,1)</li>
* <li>f<sub>xy</sub>(0,0)</li>
* <li>f<sub>xy</sub>(1,0)</li>
* <li>f<sub>xy</sub>(0,1)</li>
* <li>f<sub>xy</sub>(1,1)</li>
* </ul>
* where the subscripts indicate the partial derivative with respect to
* the corresponding variable(s).
*
* @param beta List of function values and function partial derivatives
* values.
* @return the spline coefficients.
*/
private double[] computeSplineCoefficients(double[] beta) {
final double[] a = new double[NUM_COEFF];
for (int i = 0; i < NUM_COEFF; i++) {
double result = 0;
final double[] row = AINV[i];
for (int j = 0; j < NUM_COEFF; j++) {
result += row[j] * beta[j];
}
a[i] = result;
}
return a;
}
}
/**
* Bicubic function.
*/
class BicubicFunction implements BivariateFunction {
/** Number of points. */
private static final short N = 4;
/** Coefficients */
private final double[][] a;
/**
* Simple constructor.
*
* @param coeff Spline coefficients.
*/
BicubicFunction(double[] coeff) {
a = new double[N][N];
for (int j = 0; j < N; j++) {
final double[] aJ = a[j];
for (int i = 0; i < N; i++) {
aJ[i] = coeff[i * N + j];
}
}
}
/**
* {@inheritDoc}
*/
@Override
public double value(double x, double y) {
if (x < 0 || x > 1) {
throw new OutOfRangeException(x, 0, 1);
}
if (y < 0 || y > 1) {
throw new OutOfRangeException(y, 0, 1);
}
final double x2 = x * x;
final double x3 = x2 * x;
final double[] pX = {1, x, x2, x3};
final double y2 = y * y;
final double y3 = y2 * y;
final double[] pY = {1, y, y2, y3};
return apply(pX, pY, a);
}
/**
* Compute the value of the bicubic polynomial.
*
* @param pX Powers of the x-coordinate.
* @param pY Powers of the y-coordinate.
* @param coeff Spline coefficients.
* @return the interpolated value.
*/
private double apply(double[] pX, double[] pY, double[][] coeff) {
double result = 0;
for (int i = 0; i < N; i++) {
final double r = LinearCombination.value(coeff[i], pY);
result += r * pX[i];
}
return result;
}
}

View File

@ -1,114 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.interpolation;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.NoDataException;
import org.apache.commons.math4.exception.NonMonotonicSequenceException;
import org.apache.commons.math4.exception.NumberIsTooSmallException;
import org.apache.commons.math4.util.MathArrays;
/**
* Generates a {@link BicubicInterpolatingFunction bicubic interpolating
* function}.
* <p>
* Caveat: Because the interpolation scheme requires that derivatives be
* specified at the sample points, those are approximated with finite
* differences (using the 2-points symmetric formulae).
* Since their values are undefined at the borders of the provided
* interpolation ranges, the interpolated values will be wrong at the
* edges of the patch.
* The {@code interpolate} method will return a function that overrides
* {@link BicubicInterpolatingFunction#isValidPoint(double,double)} to
* indicate points where the interpolation will be inaccurate.
* </p>
*
* @since 3.4
*/
public class BicubicInterpolator
implements BivariateGridInterpolator {
/**
* {@inheritDoc}
*/
@Override
public BicubicInterpolatingFunction interpolate(final double[] xval,
final double[] yval,
final double[][] fval)
throws NoDataException, DimensionMismatchException,
NonMonotonicSequenceException, NumberIsTooSmallException {
if (xval.length == 0 || yval.length == 0 || fval.length == 0) {
throw new NoDataException();
}
if (xval.length != fval.length) {
throw new DimensionMismatchException(xval.length, fval.length);
}
MathArrays.checkOrder(xval);
MathArrays.checkOrder(yval);
final int xLen = xval.length;
final int yLen = yval.length;
// Approximation to the partial derivatives using finite differences.
final double[][] dFdX = new double[xLen][yLen];
final double[][] dFdY = new double[xLen][yLen];
final double[][] d2FdXdY = new double[xLen][yLen];
for (int i = 1; i < xLen - 1; i++) {
final int nI = i + 1;
final int pI = i - 1;
final double nX = xval[nI];
final double pX = xval[pI];
final double deltaX = nX - pX;
for (int j = 1; j < yLen - 1; j++) {
final int nJ = j + 1;
final int pJ = j - 1;
final double nY = yval[nJ];
final double pY = yval[pJ];
final double deltaY = nY - pY;
dFdX[i][j] = (fval[nI][j] - fval[pI][j]) / deltaX;
dFdY[i][j] = (fval[i][nJ] - fval[i][pJ]) / deltaY;
final double deltaXY = deltaX * deltaY;
d2FdXdY[i][j] = (fval[nI][nJ] - fval[nI][pJ] - fval[pI][nJ] + fval[pI][pJ]) / deltaXY;
}
}
// Create the interpolating function.
return new BicubicInterpolatingFunction(xval, yval, fval,
dFdX, dFdY, d2FdXdY) {
/** {@inheritDoc} */
@Override
public boolean isValidPoint(double x, double y) {
if (x < xval[1] ||
x > xval[xval.length - 2] ||
y < yval[1] ||
y > yval[yval.length - 2]) {
return false;
} else {
return true;
}
}
};
}
}

View File

@ -1,51 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.interpolation;
import org.apache.commons.math4.analysis.BivariateFunction;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.NoDataException;
import org.apache.commons.math4.exception.NonMonotonicSequenceException;
import org.apache.commons.math4.exception.NumberIsTooSmallException;
/**
* Interface representing a bivariate real interpolating function where the
* sample points must be specified on a regular grid.
*
*/
public interface BivariateGridInterpolator {
/**
* Compute an interpolating function for the dataset.
*
* @param xval All the x-coordinates of the interpolation points, sorted
* in increasing order.
* @param yval All the y-coordinates of the interpolation points, sorted
* in increasing order.
* @param fval The values of the interpolation points on all the grid knots:
* {@code fval[i][j] = f(xval[i], yval[j])}.
* @return a function which interpolates the dataset.
* @throws NoDataException if any of the arrays has zero length.
* @throws DimensionMismatchException if the array lengths are inconsistent.
* @throws NonMonotonicSequenceException if the array is not sorted.
* @throws NumberIsTooSmallException if the number of points is too small for
* the order of the interpolation
*/
BivariateFunction interpolate(double[] xval, double[] yval,
double[][] fval)
throws NoDataException, DimensionMismatchException,
NonMonotonicSequenceException, NumberIsTooSmallException;
}

View File

@ -1,122 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.interpolation;
import java.io.Serializable;
import org.apache.commons.math4.analysis.polynomials.PolynomialFunctionLagrangeForm;
import org.apache.commons.math4.analysis.polynomials.PolynomialFunctionNewtonForm;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.NonMonotonicSequenceException;
import org.apache.commons.math4.exception.NumberIsTooSmallException;
/**
* Implements the <a href=
* "http://mathworld.wolfram.com/NewtonsDividedDifferenceInterpolationFormula.html">
* Divided Difference Algorithm</a> for interpolation of real univariate
* functions. For reference, see <b>Introduction to Numerical Analysis</b>,
* ISBN 038795452X, chapter 2.
* <p>
* The actual code of Neville's evaluation is in PolynomialFunctionLagrangeForm,
* this class provides an easy-to-use interface to it.</p>
*
* @since 1.2
*/
public class DividedDifferenceInterpolator
implements UnivariateInterpolator, Serializable {
/** serializable version identifier */
private static final long serialVersionUID = 107049519551235069L;
/**
* Compute an interpolating function for the dataset.
*
* @param x Interpolating points array.
* @param y Interpolating values array.
* @return a function which interpolates the dataset.
* @throws DimensionMismatchException if the array lengths are different.
* @throws NumberIsTooSmallException if the number of points is less than 2.
* @throws NonMonotonicSequenceException if {@code x} is not sorted in
* strictly increasing order.
*/
@Override
public PolynomialFunctionNewtonForm interpolate(double x[], double y[])
throws DimensionMismatchException,
NumberIsTooSmallException,
NonMonotonicSequenceException {
/**
* a[] and c[] are defined in the general formula of Newton form:
* p(x) = a[0] + a[1](x-c[0]) + a[2](x-c[0])(x-c[1]) + ... +
* a[n](x-c[0])(x-c[1])...(x-c[n-1])
*/
PolynomialFunctionLagrangeForm.verifyInterpolationArray(x, y, true);
/**
* When used for interpolation, the Newton form formula becomes
* p(x) = f[x0] + f[x0,x1](x-x0) + f[x0,x1,x2](x-x0)(x-x1) + ... +
* f[x0,x1,...,x[n-1]](x-x0)(x-x1)...(x-x[n-2])
* Therefore, a[k] = f[x0,x1,...,xk], c[k] = x[k].
* <p>
* Note x[], y[], a[] have the same length but c[]'s size is one less.</p>
*/
final double[] c = new double[x.length-1];
System.arraycopy(x, 0, c, 0, c.length);
final double[] a = computeDividedDifference(x, y);
return new PolynomialFunctionNewtonForm(a, c);
}
/**
* Return a copy of the divided difference array.
* <p>
* The divided difference array is defined recursively by <pre>
* f[x0] = f(x0)
* f[x0,x1,...,xk] = (f[x1,...,xk] - f[x0,...,x[k-1]]) / (xk - x0)
* </pre>
* <p>
* The computational complexity is \(O(n^2)\) where \(n\) is the common
* length of {@code x} and {@code y}.</p>
*
* @param x Interpolating points array.
* @param y Interpolating values array.
* @return a fresh copy of the divided difference array.
* @throws DimensionMismatchException if the array lengths are different.
* @throws NumberIsTooSmallException if the number of points is less than 2.
* @throws NonMonotonicSequenceException
* if {@code x} is not sorted in strictly increasing order.
*/
protected static double[] computeDividedDifference(final double x[], final double y[])
throws DimensionMismatchException,
NumberIsTooSmallException,
NonMonotonicSequenceException {
PolynomialFunctionLagrangeForm.verifyInterpolationArray(x, y, true);
final double[] divdiff = y.clone(); // initialization
final int n = x.length;
final double[] a = new double [n];
a[0] = divdiff[0];
for (int i = 1; i < n; i++) {
for (int j = 0; j < n-i; j++) {
final double denominator = x[j+i] - x[j];
divdiff[j] = (divdiff[j+1] - divdiff[j]) / denominator;
}
a[i] = divdiff[0];
}
return a;
}
}

View File

@ -1,210 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.interpolation;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.math4.FieldElement;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.MathArithmeticException;
import org.apache.commons.math4.exception.NoDataException;
import org.apache.commons.math4.exception.NullArgumentException;
import org.apache.commons.math4.exception.ZeroException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.math4.util.MathArrays;
import org.apache.commons.math4.util.MathUtils;
/** Polynomial interpolator using both sample values and sample derivatives.
* <p>
* The interpolation polynomials match all sample points, including both values
* and provided derivatives. There is one polynomial for each component of
* the values vector. All polynomials have the same degree. The degree of the
* polynomials depends on the number of points and number of derivatives at each
* point. For example the interpolation polynomials for n sample points without
* any derivatives all have degree n-1. The interpolation polynomials for n
* sample points with the two extreme points having value and first derivative
* and the remaining points having value only all have degree n+1. The
* interpolation polynomial for n sample points with value, first and second
* derivative for all points all have degree 3n-1.
* </p>
*
* @param <T> Type of the field elements.
*
* @since 3.2
*/
public class FieldHermiteInterpolator<T extends FieldElement<T>> {
/** Sample abscissae. */
private final List<T> abscissae;
/** Top diagonal of the divided differences array. */
private final List<T[]> topDiagonal;
/** Bottom diagonal of the divided differences array. */
private final List<T[]> bottomDiagonal;
/** Create an empty interpolator.
*/
public FieldHermiteInterpolator() {
this.abscissae = new ArrayList<>();
this.topDiagonal = new ArrayList<>();
this.bottomDiagonal = new ArrayList<>();
}
/** Add a sample point.
* <p>
* This method must be called once for each sample point. It is allowed to
* mix some calls with values only with calls with values and first
* derivatives.
* </p>
* <p>
* The point abscissae for all calls <em>must</em> be different.
* </p>
* @param x abscissa of the sample point
* @param value value and derivatives of the sample point
* (if only one row is passed, it is the value, if two rows are
* passed the first one is the value and the second the derivative
* and so on)
* @exception ZeroException if the abscissa difference between added point
* and a previous point is zero (i.e. the two points are at same abscissa)
* @exception MathArithmeticException if the number of derivatives is larger
* than 20, which prevents computation of a factorial
* @throws DimensionMismatchException if derivative structures are inconsistent
* @throws NullArgumentException if x is null
*/
@SafeVarargs
public final void addSamplePoint(final T x, final T[] ... value)
throws ZeroException, MathArithmeticException,
DimensionMismatchException, NullArgumentException {
MathUtils.checkNotNull(x);
T factorial = x.getField().getOne();
for (int i = 0; i < value.length; ++i) {
final T[] y = value[i].clone();
if (i > 1) {
factorial = factorial.multiply(i);
final T inv = factorial.reciprocal();
for (int j = 0; j < y.length; ++j) {
y[j] = y[j].multiply(inv);
}
}
// update the bottom diagonal of the divided differences array
final int n = abscissae.size();
bottomDiagonal.add(n - i, y);
T[] bottom0 = y;
for (int j = i; j < n; ++j) {
final T[] bottom1 = bottomDiagonal.get(n - (j + 1));
if (x.equals(abscissae.get(n - (j + 1)))) {
throw new ZeroException(LocalizedFormats.DUPLICATED_ABSCISSA_DIVISION_BY_ZERO, x);
}
final T inv = x.subtract(abscissae.get(n - (j + 1))).reciprocal();
for (int k = 0; k < y.length; ++k) {
bottom1[k] = inv.multiply(bottom0[k].subtract(bottom1[k]));
}
bottom0 = bottom1;
}
// update the top diagonal of the divided differences array
topDiagonal.add(bottom0.clone());
// update the abscissae array
abscissae.add(x);
}
}
/** Interpolate value at a specified abscissa.
* @param x interpolation abscissa
* @return interpolated value
* @exception NoDataException if sample is empty
* @throws NullArgumentException if x is null
*/
public T[] value(T x) throws NoDataException, NullArgumentException {
// safety check
MathUtils.checkNotNull(x);
if (abscissae.isEmpty()) {
throw new NoDataException(LocalizedFormats.EMPTY_INTERPOLATION_SAMPLE);
}
final T[] value = MathArrays.buildArray(x.getField(), topDiagonal.get(0).length);
T valueCoeff = x.getField().getOne();
for (int i = 0; i < topDiagonal.size(); ++i) {
T[] dividedDifference = topDiagonal.get(i);
for (int k = 0; k < value.length; ++k) {
value[k] = value[k].add(dividedDifference[k].multiply(valueCoeff));
}
final T deltaX = x.subtract(abscissae.get(i));
valueCoeff = valueCoeff.multiply(deltaX);
}
return value;
}
/** Interpolate value and first derivatives at a specified abscissa.
* @param x interpolation abscissa
* @param order maximum derivation order
* @return interpolated value and derivatives (value in row 0,
* 1<sup>st</sup> derivative in row 1, ... n<sup>th</sup> derivative in row n)
* @exception NoDataException if sample is empty
* @throws NullArgumentException if x is null
*/
public T[][] derivatives(T x, int order) throws NoDataException, NullArgumentException {
// safety check
MathUtils.checkNotNull(x);
if (abscissae.isEmpty()) {
throw new NoDataException(LocalizedFormats.EMPTY_INTERPOLATION_SAMPLE);
}
final T zero = x.getField().getZero();
final T one = x.getField().getOne();
final T[] tj = MathArrays.buildArray(x.getField(), order + 1);
tj[0] = zero;
for (int i = 0; i < order; ++i) {
tj[i + 1] = tj[i].add(one);
}
final T[][] derivatives =
MathArrays.buildArray(x.getField(), order + 1, topDiagonal.get(0).length);
final T[] valueCoeff = MathArrays.buildArray(x.getField(), order + 1);
valueCoeff[0] = x.getField().getOne();
for (int i = 0; i < topDiagonal.size(); ++i) {
T[] dividedDifference = topDiagonal.get(i);
final T deltaX = x.subtract(abscissae.get(i));
for (int j = order; j >= 0; --j) {
for (int k = 0; k < derivatives[j].length; ++k) {
derivatives[j][k] =
derivatives[j][k].add(dividedDifference[k].multiply(valueCoeff[j]));
}
valueCoeff[j] = valueCoeff[j].multiply(deltaX);
if (j > 0) {
valueCoeff[j] = valueCoeff[j].add(tj[j].multiply(valueCoeff[j - 1]));
}
}
}
return derivatives;
}
}

View File

@ -1,242 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.interpolation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.math4.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math4.analysis.differentiation.UnivariateDifferentiableVectorFunction;
import org.apache.commons.math4.analysis.polynomials.PolynomialFunction;
import org.apache.commons.math4.exception.MathArithmeticException;
import org.apache.commons.math4.exception.NoDataException;
import org.apache.commons.math4.exception.ZeroException;
import org.apache.commons.math4.exception.util.LocalizedFormats;
import org.apache.commons.numbers.combinatorics.Factorial;
/** Polynomial interpolator using both sample values and sample derivatives.
* <p>
* The interpolation polynomials match all sample points, including both values
* and provided derivatives. There is one polynomial for each component of
* the values vector. All polynomials have the same degree. The degree of the
* polynomials depends on the number of points and number of derivatives at each
* point. For example the interpolation polynomials for n sample points without
* any derivatives all have degree n-1. The interpolation polynomials for n
* sample points with the two extreme points having value and first derivative
* and the remaining points having value only all have degree n+1. The
* interpolation polynomial for n sample points with value, first and second
* derivative for all points all have degree 3n-1.
* </p>
*
* @since 3.1
*/
public class HermiteInterpolator implements UnivariateDifferentiableVectorFunction {
/** Sample abscissae. */
private final List<Double> abscissae;
/** Top diagonal of the divided differences array. */
private final List<double[]> topDiagonal;
/** Bottom diagonal of the divided differences array. */
private final List<double[]> bottomDiagonal;
/** Create an empty interpolator.
*/
public HermiteInterpolator() {
this.abscissae = new ArrayList<>();
this.topDiagonal = new ArrayList<>();
this.bottomDiagonal = new ArrayList<>();
}
/** Add a sample point.
* <p>
* This method must be called once for each sample point. It is allowed to
* mix some calls with values only with calls with values and first
* derivatives.
* </p>
* <p>
* The point abscissae for all calls <em>must</em> be different.
* </p>
* @param x abscissa of the sample point
* @param value value and derivatives of the sample point
* (if only one row is passed, it is the value, if two rows are
* passed the first one is the value and the second the derivative
* and so on)
* @exception ZeroException if the abscissa difference between added point
* and a previous point is zero (i.e. the two points are at same abscissa)
* @exception MathArithmeticException if the number of derivatives is larger
* than 20, which prevents computation of a factorial
*/
public void addSamplePoint(final double x, final double[] ... value)
throws ZeroException, MathArithmeticException {
if (value.length > 20) {
throw new MathArithmeticException(LocalizedFormats.NUMBER_TOO_LARGE, value.length, 20);
}
for (int i = 0; i < value.length; ++i) {
final double[] y = value[i].clone();
if (i > 1) {
double inv = 1.0 / Factorial.value(i);
for (int j = 0; j < y.length; ++j) {
y[j] *= inv;
}
}
// update the bottom diagonal of the divided differences array
final int n = abscissae.size();
bottomDiagonal.add(n - i, y);
double[] bottom0 = y;
for (int j = i; j < n; ++j) {
final double[] bottom1 = bottomDiagonal.get(n - (j + 1));
final double inv = 1.0 / (x - abscissae.get(n - (j + 1)));
if (Double.isInfinite(inv)) {
throw new ZeroException(LocalizedFormats.DUPLICATED_ABSCISSA_DIVISION_BY_ZERO, x);
}
for (int k = 0; k < y.length; ++k) {
bottom1[k] = inv * (bottom0[k] - bottom1[k]);
}
bottom0 = bottom1;
}
// update the top diagonal of the divided differences array
topDiagonal.add(bottom0.clone());
// update the abscissae array
abscissae.add(x);
}
}
/** Compute the interpolation polynomials.
* @return interpolation polynomials array
* @exception NoDataException if sample is empty
*/
public PolynomialFunction[] getPolynomials()
throws NoDataException {
// safety check
checkInterpolation();
// iteration initialization
final PolynomialFunction zero = polynomial(0);
PolynomialFunction[] polynomials = new PolynomialFunction[topDiagonal.get(0).length];
for (int i = 0; i < polynomials.length; ++i) {
polynomials[i] = zero;
}
PolynomialFunction coeff = polynomial(1);
// build the polynomials by iterating on the top diagonal of the divided differences array
for (int i = 0; i < topDiagonal.size(); ++i) {
double[] tdi = topDiagonal.get(i);
for (int k = 0; k < polynomials.length; ++k) {
polynomials[k] = polynomials[k].add(coeff.multiply(polynomial(tdi[k])));
}
coeff = coeff.multiply(polynomial(-abscissae.get(i), 1.0));
}
return polynomials;
}
/** Interpolate value at a specified abscissa.
* <p>
* Calling this method is equivalent to call the {@link PolynomialFunction#value(double)
* value} methods of all polynomials returned by {@link #getPolynomials() getPolynomials},
* except it does not build the intermediate polynomials, so this method is faster and
* numerically more stable.
* </p>
* @param x interpolation abscissa
* @return interpolated value
* @exception NoDataException if sample is empty
*/
@Override
public double[] value(double x) throws NoDataException {
// safety check
checkInterpolation();
final double[] value = new double[topDiagonal.get(0).length];
double valueCoeff = 1;
for (int i = 0; i < topDiagonal.size(); ++i) {
double[] dividedDifference = topDiagonal.get(i);
for (int k = 0; k < value.length; ++k) {
value[k] += dividedDifference[k] * valueCoeff;
}
final double deltaX = x - abscissae.get(i);
valueCoeff *= deltaX;
}
return value;
}
/** Interpolate value at a specified abscissa.
* <p>
* Calling this method is equivalent to call the {@link
* PolynomialFunction#value(DerivativeStructure) value} methods of all polynomials
* returned by {@link #getPolynomials() getPolynomials}, except it does not build the
* intermediate polynomials, so this method is faster and numerically more stable.
* </p>
* @param x interpolation abscissa
* @return interpolated value
* @exception NoDataException if sample is empty
*/
@Override
public DerivativeStructure[] value(final DerivativeStructure x)
throws NoDataException {
// safety check
checkInterpolation();
final DerivativeStructure[] value = new DerivativeStructure[topDiagonal.get(0).length];
Arrays.fill(value, x.getField().getZero());
DerivativeStructure valueCoeff = x.getField().getOne();
for (int i = 0; i < topDiagonal.size(); ++i) {
double[] dividedDifference = topDiagonal.get(i);
for (int k = 0; k < value.length; ++k) {
value[k] = value[k].add(valueCoeff.multiply(dividedDifference[k]));
}
final DerivativeStructure deltaX = x.subtract(abscissae.get(i));
valueCoeff = valueCoeff.multiply(deltaX);
}
return value;
}
/** Check interpolation can be performed.
* @exception NoDataException if interpolation cannot be performed
* because sample is empty
*/
private void checkInterpolation() throws NoDataException {
if (abscissae.isEmpty()) {
throw new NoDataException(LocalizedFormats.EMPTY_INTERPOLATION_SAMPLE);
}
}
/** Create a polynomial from its coefficients.
* @param c polynomials coefficients
* @return polynomial
*/
private PolynomialFunction polynomial(double ... c) {
return new PolynomialFunction(c);
}
}

View File

@ -1,387 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math4.analysis.interpolation;
import java.util.List;
import java.util.ArrayList;
import org.apache.commons.numbers.arrays.CosAngle;
import org.apache.commons.numbers.arrays.SafeNorm;
import org.apache.commons.rng.sampling.UnitSphereSampler;
import org.apache.commons.math4.exception.DimensionMismatchException;
import org.apache.commons.math4.exception.NotPositiveException;
import org.apache.commons.math4.exception.NotStrictlyPositiveException;
import org.apache.commons.math4.exception.MaxCountExceededException;
import org.apache.commons.math4.exception.OutOfRangeException;
import org.apache.commons.math4.util.FastMath;
import org.apache.commons.math4.util.MathArrays;
/**
* Utility class for the {@link MicrosphereProjectionInterpolator} algorithm.
*
* @since 3.6
*/
public class InterpolatingMicrosphere {
/** Microsphere. */
private final List<Facet> microsphere;
/** Microsphere data. */
private final List<FacetData> microsphereData;
/** Space dimension. */
private final int dimension;
/** Number of surface elements. */
private final int size;
/** Maximum fraction of the facets that can be dark. */
private final double maxDarkFraction;
/** Lowest non-zero illumination. */
private final double darkThreshold;
/** Background value. */
private final double background;
/**
* Create an unitialiazed sphere.
* Sub-classes are responsible for calling the {@code add(double[]) add}
* method in order to initialize all the sphere's facets.
*
* @param dimension Dimension of the data space.
* @param size Number of surface elements of the sphere.
* @param maxDarkFraction Maximum fraction of the facets that can be dark.
* If the fraction of "non-illuminated" facets is larger, no estimation
* of the value will be performed, and the {@code background} value will
* be returned instead.
* @param darkThreshold Value of the illumination below which a facet is
* considered dark.
* @param background Value returned when the {@code maxDarkFraction}
* threshold is exceeded.
* @throws NotStrictlyPositiveException if {@code dimension <= 0}
* or {@code size <= 0}.
* @throws NotPositiveException if {@code darkThreshold < 0}.
* @throws OutOfRangeException if {@code maxDarkFraction} does not
* belong to the interval {@code [0, 1]}.
*/
protected InterpolatingMicrosphere(int dimension,
int size,
double maxDarkFraction,
double darkThreshold,
double background) {
if (dimension <= 0) {
throw new NotStrictlyPositiveException(dimension);
}
if (size <= 0) {
throw new NotStrictlyPositiveException(size);
}
if (maxDarkFraction < 0 ||
maxDarkFraction > 1) {
throw new OutOfRangeException(maxDarkFraction, 0, 1);
}
if (darkThreshold < 0) {
throw new NotPositiveException(darkThreshold);
}
this.dimension = dimension;
this.size = size;
this.maxDarkFraction = maxDarkFraction;
this.darkThreshold = darkThreshold;
this.background = background;
microsphere = new ArrayList<>(size);
microsphereData = new ArrayList<>(size);
}
/**
* Create a sphere from randomly sampled vectors.
*
* @param dimension Dimension of the data space.
* @param size Number of surface elements of the sphere.
* @param rand Unit vector generator for creating the microsphere.
* @param maxDarkFraction Maximum fraction of the facets that can be dark.
* If the fraction of "non-illuminated" facets is larger, no estimation
* of the value will be performed, and the {@code background} value will
* be returned instead.
* @param darkThreshold Value of the illumination below which a facet
* is considered dark.
* @param background Value returned when the {@code maxDarkFraction}
* threshold is exceeded.
* @throws DimensionMismatchException if the size of the generated
* vectors does not match the dimension set in the constructor.
* @throws NotStrictlyPositiveException if {@code dimension <= 0}
* or {@code size <= 0}.
* @throws NotPositiveException if {@code darkThreshold < 0}.
* @throws OutOfRangeException if {@code maxDarkFraction} does not
* belong to the interval {@code [0, 1]}.
*/
public InterpolatingMicrosphere(int dimension,
int size,
double maxDarkFraction,
double darkThreshold,
double background,
UnitSphereSampler rand) {
this(dimension, size, maxDarkFraction, darkThreshold, background);
// Generate the microsphere normals, assuming that a number of
// randomly generated normals will represent a sphere.
for (int i = 0; i < size; i++) {
add(rand.nextVector(), false);
}
}
/**
* Copy constructor.
*
* @param other Instance to copy.
*/
protected InterpolatingMicrosphere(InterpolatingMicrosphere other) {
dimension = other.dimension;
size = other.size;
maxDarkFraction = other.maxDarkFraction;
darkThreshold = other.darkThreshold;
background = other.background;
// Field can be shared.
microsphere = other.microsphere;
// Field must be copied.
microsphereData = new ArrayList<>(size);
for (FacetData fd : other.microsphereData) {
microsphereData.add(new FacetData(fd.illumination(), fd.sample()));
}
}
/**
* Perform a copy.
*
* @return a copy of this instance.
*/
public InterpolatingMicrosphere copy() {
return new InterpolatingMicrosphere(this);
}
/**
* Get the space dimensionality.
*
* @return the number of space dimensions.
*/
public int getDimension() {
return dimension;
}
/**
* Get the size of the sphere.
*
* @return the number of surface elements of the microspshere.
*/
public int getSize() {
return size;
}
/**
* Estimate the value at the requested location.
* This microsphere is placed at the given {@code point}, contribution
* of the given {@code samplePoints} to each sphere facet is computed
* (illumination) and the interpolation is performed (integration of
* the illumination).
*
* @param point Interpolation point.
* @param samplePoints Sampling data points.
* @param sampleValues Sampling data values at the corresponding
* {@code samplePoints}.
* @param exponent Exponent used in the power law that computes
* the weights (distance dimming factor) of the sample data.
* @param noInterpolationTolerance When the distance between the
* {@code point} and one of the {@code samplePoints} is less than
* this value, no interpolation will be performed, and the value
* of the sample will just be returned.
* @return the estimated value at the given {@code point}.
* @throws NotPositiveException if {@code exponent < 0}.
*/
public double value(double[] point,
double[][] samplePoints,
double[] sampleValues,
double exponent,
double noInterpolationTolerance) {
if (exponent < 0) {
throw new NotPositiveException(exponent);
}
clear();
// Contribution of each sample point to the illumination of the
// microsphere's facets.
final int numSamples = samplePoints.length;
for (int i = 0; i < numSamples; i++) {
// Vector between interpolation point and current sample point.
final double[] diff = MathArrays.ebeSubtract(samplePoints[i], point);
final double diffNorm = SafeNorm.value(diff);
if (FastMath.abs(diffNorm) < noInterpolationTolerance) {
// No need to interpolate, as the interpolation point is
// actually (very close to) one of the sampled points.
return sampleValues[i];
}
final double weight = FastMath.pow(diffNorm, -exponent);
illuminate(diff, sampleValues[i], weight);
}
return interpolate();
}
/**
* Replace {@code i}-th facet of the microsphere.
* Method for initializing the microsphere facets.
*
* @param normal Facet's normal vector.
* @param copy Whether to copy the given array.
* @throws DimensionMismatchException if the length of {@code n}
* does not match the space dimension.
* @throws MaxCountExceededException if the method has been called
* more times than the size of the sphere.
*/
protected void add(double[] normal,
boolean copy) {
if (microsphere.size() >= size) {
throw new MaxCountExceededException(size);
}
if (normal.length > dimension) {
throw new DimensionMismatchException(normal.length, dimension);
}
microsphere.add(new Facet(copy ? normal.clone() : normal));
microsphereData.add(new FacetData(0d, 0d));
}
/**
* Interpolation.
*
* @return the value estimated from the current illumination of the
* microsphere.
*/
private double interpolate() {
// Number of non-illuminated facets.
int darkCount = 0;
double value = 0;
double totalWeight = 0;
for (FacetData fd : microsphereData) {
final double iV = fd.illumination();
if (iV != 0d) {
value += iV * fd.sample();
totalWeight += iV;
} else {
++darkCount;
}
}
final double darkFraction = darkCount / (double) size;
return darkFraction <= maxDarkFraction ?
value / totalWeight :
background;
}
/**
* Illumination.
*
* @param sampleDirection Vector whose origin is at the interpolation
* point and tail is at the sample location.
* @param sampleValue Data value of the sample.
* @param weight Weight.
*/
private void illuminate(double[] sampleDirection,
double sampleValue,
double weight) {
for (int i = 0; i < size; i++) {
final double[] n = microsphere.get(i).getNormal();
final double cos = CosAngle.value(n, sampleDirection);
if (cos > 0) {
final double illumination = cos * weight;
if (illumination > darkThreshold &&
illumination > microsphereData.get(i).illumination()) {
microsphereData.set(i, new FacetData(illumination, sampleValue));
}
}
}
}
/**
* Reset the all the {@link Facet facets} data to zero.
*/
private void clear() {
for (int i = 0; i < size; i++) {
microsphereData.set(i, new FacetData(0d, 0d));
}
}
/**
* Microsphere "facet" (surface element).
*/
private static class Facet {
/** Normal vector characterizing a surface element. */
private final double[] normal;
/**
* @param n Normal vector characterizing a surface element
* of the microsphere. No copy is made.
*/
Facet(double[] n) {
normal = n;
}
/**
* Return a reference to the vector normal to this facet.
*
* @return the normal vector.
*/
public double[] getNormal() {
return normal;
}
}
/**
* Data associated with each {@link Facet}.
*/
private static class FacetData {
/** Illumination received from the sample. */
private final double illumination;
/** Data value of the sample. */
private final double sample;
/**
* @param illumination Illumination.
* @param sample Data value.
*/
FacetData(double illumination, double sample) {
this.illumination = illumination;
this.sample = sample;
}
/**
* Get the illumination.
* @return the illumination.
*/
public double illumination() {
return illumination;
}
/**
* Get the data value.
* @return the data value.
*/
public double sample() {
return sample;
}
}
}

Some files were not shown because too many files have changed in this diff Show More