1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.hipparchus.analysis.integration.gauss;
18
19 import java.util.Arrays;
20 import java.util.SortedMap;
21 import java.util.TreeMap;
22
23 import org.hipparchus.analysis.UnivariateFunction;
24 import org.hipparchus.exception.LocalizedCoreFormats;
25 import org.hipparchus.exception.MathIllegalArgumentException;
26 import org.hipparchus.util.FastMath;
27 import org.hipparchus.util.Incrementor;
28 import org.hipparchus.util.Pair;
29
30
31
32
33
34
35
36
37 public abstract class AbstractRuleFactory implements RuleFactory {
38
39
40 private final SortedMap<Integer, Pair<double[], double[]>> pointsAndWeights = new TreeMap<>();
41
42
43
44
45
46
47
48
49 public AbstractRuleFactory() {
50
51 }
52
53
54 @Override
55 public Pair<double[], double[]> getRule(int numberOfPoints)
56 throws MathIllegalArgumentException {
57
58 if (numberOfPoints <= 0) {
59 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_OF_POINTS,
60 numberOfPoints);
61 }
62 if (numberOfPoints > 1000) {
63 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE,
64 numberOfPoints, 1000);
65 }
66
67 Pair<double[], double[]> rule;
68 synchronized (pointsAndWeights) {
69
70 rule = pointsAndWeights.get(numberOfPoints);
71
72 if (rule == null) {
73
74
75
76 rule = computeRule(numberOfPoints);
77
78
79 pointsAndWeights.put(numberOfPoints, rule);
80 }
81 }
82
83
84 return new Pair<>(rule.getFirst().clone(), rule.getSecond().clone());
85
86 }
87
88
89
90
91
92
93
94
95
96 protected abstract Pair<double[], double[]> computeRule(int numberOfPoints)
97 throws MathIllegalArgumentException;
98
99
100
101
102
103
104
105
106
107
108
109
110 protected double[] findRoots(final int n, final UnivariateFunction ratioEvaluator) {
111
112 final double[] roots = new double[n];
113
114
115 if (n == 1) {
116
117 roots[0] = 0;
118 } else if (n == 2) {
119
120 roots[0] = -1;
121 roots[1] = +1;
122 } else {
123
124
125
126 final double[] previousPoints = getRule(n - 1).getFirst();
127
128
129 roots[0] = previousPoints[0];
130
131
132 for (int i = 1; i < n - 1; ++i) {
133 roots[i] = (previousPoints[i - 1] + previousPoints[i]) * 0.5;
134 }
135
136
137 roots[n - 1] = previousPoints[n - 2];
138
139 }
140
141
142 final double[] ratio = new double[n];
143 final Incrementor incrementor = new Incrementor(1000);
144 double tol;
145 double maxOffset;
146 do {
147
148
149 incrementor.increment();
150
151
152 for (int i = 0; i < n; ++i) {
153 ratio[i] = ratioEvaluator.value(roots[i]);
154 }
155
156
157 maxOffset = 0;
158 for (int i = 0; i < n; ++i) {
159 double sum = 0;
160 for (int j = 0; j < n; ++j) {
161 if (j != i) {
162 sum += 1 / (roots[i] - roots[j]);
163 }
164 }
165 final double offset = ratio[i] / (1 - ratio[i] * sum);
166 maxOffset = FastMath.max(maxOffset, FastMath.abs(offset));
167 roots[i] -= offset;
168 }
169
170
171 tol = 0;
172 for (final double r : roots) {
173 tol = FastMath.max(tol, FastMath.ulp(r));
174 }
175
176 } while (maxOffset > tol);
177
178
179 Arrays.sort(roots);
180
181 return roots;
182
183 }
184
185
186
187
188 protected void enforceSymmetry(final double[] roots) {
189
190 final int n = roots.length;
191
192
193 for (int i = 0; i < n / 2; ++i) {
194 final int idx = n - i - 1;
195 final double c = (roots[i] - roots[idx]) * 0.5;
196 roots[i] = +c;
197 roots[idx] = -c;
198 }
199
200
201
202
203
204 if (n % 2 != 0) {
205 roots[n / 2] = 0;
206 }
207
208 }
209
210 }