GaussIntegratorFactory.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      https://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. /*
  18.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */
  21. package org.hipparchus.analysis.integration.gauss;

  22. import org.hipparchus.dfp.DfpField;
  23. import org.hipparchus.exception.MathIllegalArgumentException;
  24. import org.hipparchus.util.Pair;

  25. /**
  26.  * Class that provides different ways to compute the nodes and weights to be
  27.  * used by the {@link GaussIntegrator Gaussian integration rule}.
  28.  */
  29. public class GaussIntegratorFactory {

  30.     /** Number of digits for Legendre high precision. */
  31.     public static final int DEFAULT_DECIMAL_DIGITS = 40;

  32.     /** Generator of Gauss-Legendre integrators. */
  33.     private final RuleFactory legendre;
  34.     /** Generator of Gauss-Legendre integrators. */
  35.     private final RuleFactory legendreHighPrecision;
  36.     /** Generator of Gauss-Hermite integrators. */
  37.     private final RuleFactory hermite;
  38.     /** Generator of Gauss-Laguerre integrators. */
  39.     private final RuleFactory laguerre;

  40.     /** Simple constructor.
  41.      */
  42.     public GaussIntegratorFactory() {
  43.         this(DEFAULT_DECIMAL_DIGITS);
  44.     }

  45.     /** Simple constructor.
  46.      * @param decimalDigits minimum number of decimal digits for {@link #legendreHighPrecision(int)}
  47.      */
  48.     public GaussIntegratorFactory(final int decimalDigits) {
  49.         legendre              = new LegendreRuleFactory();
  50.         legendreHighPrecision = new ConvertingRuleFactory<>(new FieldLegendreRuleFactory<>(new DfpField(decimalDigits)));
  51.         hermite               = new HermiteRuleFactory();
  52.         laguerre              = new LaguerreRuleFactory();
  53.     }

  54.     /**
  55.      * Creates a Gauss-Laguerre integrator of the given order.
  56.      * The call to the
  57.      * {@link GaussIntegrator#integrate(org.hipparchus.analysis.UnivariateFunction)
  58.      * integrate} method will perform an integration on the interval
  59.      * \([0, +\infty)\): the computed value is the improper integral of
  60.      * \(e^{-x} f(x)\)
  61.      * where \(f(x)\) is the function passed to the
  62.      * {@link SymmetricGaussIntegrator#integrate(org.hipparchus.analysis.UnivariateFunction)
  63.      * integrate} method.
  64.      *
  65.      * @param numberOfPoints Order of the integration rule.
  66.      * @return a Gauss-Legendre integrator.
  67.      */
  68.     public GaussIntegrator laguerre(int numberOfPoints) {
  69.         return new GaussIntegrator(laguerre.getRule(numberOfPoints));
  70.     }

  71.     /**
  72.      * Creates a Gauss-Legendre integrator of the given order.
  73.      * The call to the
  74.      * {@link GaussIntegrator#integrate(org.hipparchus.analysis.UnivariateFunction)
  75.      * integrate} method will perform an integration on the natural interval
  76.      * {@code [-1 , 1]}.
  77.      *
  78.      * @param numberOfPoints Order of the integration rule.
  79.      * @return a Gauss-Legendre integrator.
  80.      */
  81.     public GaussIntegrator legendre(int numberOfPoints) {
  82.         return new GaussIntegrator(legendre.getRule(numberOfPoints));
  83.     }

  84.     /**
  85.      * Creates a Gauss-Legendre integrator of the given order.
  86.      * The call to the
  87.      * {@link GaussIntegrator#integrate(org.hipparchus.analysis.UnivariateFunction)
  88.      * integrate} method will perform an integration on the given interval.
  89.      *
  90.      * @param numberOfPoints Order of the integration rule.
  91.      * @param lowerBound Lower bound of the integration interval.
  92.      * @param upperBound Upper bound of the integration interval.
  93.      * @return a Gauss-Legendre integrator.
  94.      * @throws MathIllegalArgumentException if number of points is not positive
  95.      */
  96.     public GaussIntegrator legendre(int numberOfPoints,
  97.                                     double lowerBound,
  98.                                     double upperBound)
  99.         throws MathIllegalArgumentException {
  100.         return new GaussIntegrator(transform(legendre.getRule(numberOfPoints),
  101.                                              lowerBound, upperBound));
  102.     }

  103.     /**
  104.      * Creates a Gauss-Legendre integrator of the given order.
  105.      * The call to the
  106.      * {@link GaussIntegrator#integrate(org.hipparchus.analysis.UnivariateFunction)
  107.      * integrate} method will perform an integration on the natural interval
  108.      * {@code [-1 , 1]}.
  109.      *
  110.      * @param numberOfPoints Order of the integration rule.
  111.      * @return a Gauss-Legendre integrator.
  112.      * @throws MathIllegalArgumentException if number of points is not positive
  113.      */
  114.     public GaussIntegrator legendreHighPrecision(int numberOfPoints)
  115.         throws MathIllegalArgumentException {
  116.         return new GaussIntegrator(legendreHighPrecision.getRule(numberOfPoints));
  117.     }

  118.     /**
  119.      * Creates an integrator of the given order, and whose call to the
  120.      * {@link GaussIntegrator#integrate(org.hipparchus.analysis.UnivariateFunction)
  121.      * integrate} method will perform an integration on the given interval.
  122.      *
  123.      * @param numberOfPoints Order of the integration rule.
  124.      * @param lowerBound Lower bound of the integration interval.
  125.      * @param upperBound Upper bound of the integration interval.
  126.      * @return a Gauss-Legendre integrator.
  127.      * @throws MathIllegalArgumentException if number of points is not positive
  128.      */
  129.     public GaussIntegrator legendreHighPrecision(int numberOfPoints,
  130.                                                  double lowerBound,
  131.                                                  double upperBound)
  132.         throws MathIllegalArgumentException {
  133.         return new GaussIntegrator(transform(legendreHighPrecision.getRule(numberOfPoints),
  134.                                              lowerBound, upperBound));
  135.     }

  136.     /**
  137.      * Creates a Gauss-Hermite integrator of the given order.
  138.      * The call to the
  139.      * {@link SymmetricGaussIntegrator#integrate(org.hipparchus.analysis.UnivariateFunction)
  140.      * integrate} method will perform a weighted integration on the interval
  141.      * \([-\infty, +\infty]\): the computed value is the improper integral of
  142.      * \(e^{-x^2}f(x)\)
  143.      * where \(f(x)\) is the function passed to the
  144.      * {@link SymmetricGaussIntegrator#integrate(org.hipparchus.analysis.UnivariateFunction)
  145.      * integrate} method.
  146.      *
  147.      * @param numberOfPoints Order of the integration rule.
  148.      * @return a Gauss-Hermite integrator.
  149.      */
  150.     public SymmetricGaussIntegrator hermite(int numberOfPoints) {
  151.         return new SymmetricGaussIntegrator(hermite.getRule(numberOfPoints));
  152.     }

  153.     /**
  154.      * Performs a change of variable so that the integration can be performed
  155.      * on an arbitrary interval {@code [a, b]}.
  156.      * It is assumed that the natural interval is {@code [-1, 1]}.
  157.      *
  158.      * @param rule Original points and weights.
  159.      * @param a Lower bound of the integration interval.
  160.      * @param b Lower bound of the integration interval.
  161.      * @return the points and weights adapted to the new interval.
  162.      */
  163.     private Pair<double[], double[]> transform(Pair<double[], double[]> rule, double a, double b) {
  164.         final double[] points = rule.getFirst();
  165.         final double[] weights = rule.getSecond();

  166.         // Scaling
  167.         final double scale = (b - a) / 2;
  168.         final double shift = a + scale;

  169.         for (int i = 0; i < points.length; i++) {
  170.             points[i] = points[i] * scale + shift;
  171.             weights[i] *= scale;
  172.         }

  173.         return new Pair<>(points, weights);
  174.     }

  175. }