blob: 3b1c2eb9955734b71c112c972f72dddf2f68e80c [file] [log] [blame]
/*
* 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) {
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) {
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) {
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) {
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);
}
}