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 /*
19 * This is not the original file distributed by the Apache Software Foundation
20 * It has been modified by the Hipparchus project
21 */
22 package org.hipparchus.analysis.integration.gauss;
23
24 import org.hipparchus.dfp.DfpField;
25 import org.hipparchus.exception.MathIllegalArgumentException;
26 import org.hipparchus.util.Pair;
27
28 /**
29 * Class that provides different ways to compute the nodes and weights to be
30 * used by the {@link GaussIntegrator Gaussian integration rule}.
31 */
32 public class GaussIntegratorFactory {
33
34 /** Number of digits for Legendre high precision. */
35 public static final int DEFAULT_DECIMAL_DIGITS = 40;
36
37 /** Generator of Gauss-Legendre integrators. */
38 private final RuleFactory legendre;
39 /** Generator of Gauss-Legendre integrators. */
40 private final RuleFactory legendreHighPrecision;
41 /** Generator of Gauss-Hermite integrators. */
42 private final RuleFactory hermite;
43 /** Generator of Gauss-Laguerre integrators. */
44 private final RuleFactory laguerre;
45
46 /** Simple constructor.
47 */
48 public GaussIntegratorFactory() {
49 this(DEFAULT_DECIMAL_DIGITS);
50 }
51
52 /** Simple constructor.
53 * @param decimalDigits minimum number of decimal digits for {@link #legendreHighPrecision(int)}
54 */
55 public GaussIntegratorFactory(final int decimalDigits) {
56 legendre = new LegendreRuleFactory();
57 legendreHighPrecision = new ConvertingRuleFactory<>(new FieldLegendreRuleFactory<>(new DfpField(decimalDigits)));
58 hermite = new HermiteRuleFactory();
59 laguerre = new LaguerreRuleFactory();
60 }
61
62 /**
63 * Creates a Gauss-Laguerre integrator of the given order.
64 * The call to the
65 * {@link GaussIntegrator#integrate(org.hipparchus.analysis.UnivariateFunction)
66 * integrate} method will perform an integration on the interval
67 * \([0, +\infty)\): the computed value is the improper integral of
68 * \(e^{-x} f(x)\)
69 * where \(f(x)\) is the function passed to the
70 * {@link SymmetricGaussIntegrator#integrate(org.hipparchus.analysis.UnivariateFunction)
71 * integrate} method.
72 *
73 * @param numberOfPoints Order of the integration rule.
74 * @return a Gauss-Legendre integrator.
75 */
76 public GaussIntegrator laguerre(int numberOfPoints) {
77 return new GaussIntegrator(laguerre.getRule(numberOfPoints));
78 }
79
80 /**
81 * Creates a Gauss-Legendre integrator of the given order.
82 * The call to the
83 * {@link GaussIntegrator#integrate(org.hipparchus.analysis.UnivariateFunction)
84 * integrate} method will perform an integration on the natural interval
85 * {@code [-1 , 1]}.
86 *
87 * @param numberOfPoints Order of the integration rule.
88 * @return a Gauss-Legendre integrator.
89 */
90 public GaussIntegrator legendre(int numberOfPoints) {
91 return new GaussIntegrator(legendre.getRule(numberOfPoints));
92 }
93
94 /**
95 * Creates a Gauss-Legendre integrator of the given order.
96 * The call to the
97 * {@link GaussIntegrator#integrate(org.hipparchus.analysis.UnivariateFunction)
98 * integrate} method will perform an integration on the given interval.
99 *
100 * @param numberOfPoints Order of the integration rule.
101 * @param lowerBound Lower bound of the integration interval.
102 * @param upperBound Upper bound of the integration interval.
103 * @return a Gauss-Legendre integrator.
104 * @throws MathIllegalArgumentException if number of points is not positive
105 */
106 public GaussIntegrator legendre(int numberOfPoints,
107 double lowerBound,
108 double upperBound)
109 throws MathIllegalArgumentException {
110 return new GaussIntegrator(transform(legendre.getRule(numberOfPoints),
111 lowerBound, upperBound));
112 }
113
114 /**
115 * Creates a Gauss-Legendre integrator of the given order.
116 * The call to the
117 * {@link GaussIntegrator#integrate(org.hipparchus.analysis.UnivariateFunction)
118 * integrate} method will perform an integration on the natural interval
119 * {@code [-1 , 1]}.
120 *
121 * @param numberOfPoints Order of the integration rule.
122 * @return a Gauss-Legendre integrator.
123 * @throws MathIllegalArgumentException if number of points is not positive
124 */
125 public GaussIntegrator legendreHighPrecision(int numberOfPoints)
126 throws MathIllegalArgumentException {
127 return new GaussIntegrator(legendreHighPrecision.getRule(numberOfPoints));
128 }
129
130 /**
131 * Creates an integrator of the given order, and whose call to the
132 * {@link GaussIntegrator#integrate(org.hipparchus.analysis.UnivariateFunction)
133 * integrate} method will perform an integration on the given interval.
134 *
135 * @param numberOfPoints Order of the integration rule.
136 * @param lowerBound Lower bound of the integration interval.
137 * @param upperBound Upper bound of the integration interval.
138 * @return a Gauss-Legendre integrator.
139 * @throws MathIllegalArgumentException if number of points is not positive
140 */
141 public GaussIntegrator legendreHighPrecision(int numberOfPoints,
142 double lowerBound,
143 double upperBound)
144 throws MathIllegalArgumentException {
145 return new GaussIntegrator(transform(legendreHighPrecision.getRule(numberOfPoints),
146 lowerBound, upperBound));
147 }
148
149 /**
150 * Creates a Gauss-Hermite integrator of the given order.
151 * The call to the
152 * {@link SymmetricGaussIntegrator#integrate(org.hipparchus.analysis.UnivariateFunction)
153 * integrate} method will perform a weighted integration on the interval
154 * \([-\infty, +\infty]\): the computed value is the improper integral of
155 * \(e^{-x^2}f(x)\)
156 * where \(f(x)\) is the function passed to the
157 * {@link SymmetricGaussIntegrator#integrate(org.hipparchus.analysis.UnivariateFunction)
158 * integrate} method.
159 *
160 * @param numberOfPoints Order of the integration rule.
161 * @return a Gauss-Hermite integrator.
162 */
163 public SymmetricGaussIntegrator hermite(int numberOfPoints) {
164 return new SymmetricGaussIntegrator(hermite.getRule(numberOfPoints));
165 }
166
167 /**
168 * Performs a change of variable so that the integration can be performed
169 * on an arbitrary interval {@code [a, b]}.
170 * It is assumed that the natural interval is {@code [-1, 1]}.
171 *
172 * @param rule Original points and weights.
173 * @param a Lower bound of the integration interval.
174 * @param b Lower bound of the integration interval.
175 * @return the points and weights adapted to the new interval.
176 */
177 private Pair<double[], double[]> transform(Pair<double[], double[]> rule, double a, double b) {
178 final double[] points = rule.getFirst();
179 final double[] weights = rule.getSecond();
180
181 // Scaling
182 final double scale = (b - a) / 2;
183 final double shift = a + scale;
184
185 for (int i = 0; i < points.length; i++) {
186 points[i] = points[i] * scale + shift;
187 weights[i] *= scale;
188 }
189
190 return new Pair<>(points, weights);
191 }
192
193 }