1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.hipparchus.analysis.polynomials;
23
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28
29 import org.hipparchus.fraction.BigFraction;
30 import org.hipparchus.util.CombinatoricsUtils;
31 import org.hipparchus.util.FastMath;
32
33
34
35
36
37 public class PolynomialsUtils {
38
39
40 private static final List<BigFraction> CHEBYSHEV_COEFFICIENTS;
41
42
43 private static final List<BigFraction> HERMITE_COEFFICIENTS;
44
45
46 private static final List<BigFraction> LAGUERRE_COEFFICIENTS;
47
48
49 private static final List<BigFraction> LEGENDRE_COEFFICIENTS;
50
51
52 private static final Map<JacobiKey, List<BigFraction>> JACOBI_COEFFICIENTS;
53
54 static {
55
56
57
58 CHEBYSHEV_COEFFICIENTS = new ArrayList<>();
59 CHEBYSHEV_COEFFICIENTS.add(BigFraction.ONE);
60 CHEBYSHEV_COEFFICIENTS.add(BigFraction.ZERO);
61 CHEBYSHEV_COEFFICIENTS.add(BigFraction.ONE);
62
63
64
65 HERMITE_COEFFICIENTS = new ArrayList<>();
66 HERMITE_COEFFICIENTS.add(BigFraction.ONE);
67 HERMITE_COEFFICIENTS.add(BigFraction.ZERO);
68 HERMITE_COEFFICIENTS.add(BigFraction.TWO);
69
70
71
72 LAGUERRE_COEFFICIENTS = new ArrayList<>();
73 LAGUERRE_COEFFICIENTS.add(BigFraction.ONE);
74 LAGUERRE_COEFFICIENTS.add(BigFraction.ONE);
75 LAGUERRE_COEFFICIENTS.add(BigFraction.MINUS_ONE);
76
77
78
79 LEGENDRE_COEFFICIENTS = new ArrayList<>();
80 LEGENDRE_COEFFICIENTS.add(BigFraction.ONE);
81 LEGENDRE_COEFFICIENTS.add(BigFraction.ZERO);
82 LEGENDRE_COEFFICIENTS.add(BigFraction.ONE);
83
84
85 JACOBI_COEFFICIENTS = new HashMap<>();
86
87 }
88
89
90
91
92 private PolynomialsUtils() {
93 }
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 public static PolynomialFunction createChebyshevPolynomial(final int degree) {
110 return buildPolynomial(degree, CHEBYSHEV_COEFFICIENTS,
111 new RecurrenceCoefficientsGenerator() {
112
113 private final BigFraction[] coeffs = { BigFraction.ZERO, BigFraction.TWO, BigFraction.ONE };
114
115 @Override
116 public BigFraction[] generate(int k) {
117 return coeffs;
118 }
119 });
120 }
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137 public static PolynomialFunction createHermitePolynomial(final int degree) {
138 return buildPolynomial(degree, HERMITE_COEFFICIENTS,
139 new RecurrenceCoefficientsGenerator() {
140
141 @Override
142 public BigFraction[] generate(int k) {
143 return new BigFraction[] {
144 BigFraction.ZERO,
145 BigFraction.TWO,
146 new BigFraction(2 * k)};
147 }
148 });
149 }
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165 public static PolynomialFunction createLaguerrePolynomial(final int degree) {
166 return buildPolynomial(degree, LAGUERRE_COEFFICIENTS,
167 new RecurrenceCoefficientsGenerator() {
168
169 @Override
170 public BigFraction[] generate(int k) {
171 final int kP1 = k + 1;
172 return new BigFraction[] {
173 new BigFraction(2 * k + 1, kP1),
174 new BigFraction(-1, kP1),
175 new BigFraction(k, kP1)};
176 }
177 });
178 }
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194 public static PolynomialFunction createLegendrePolynomial(final int degree) {
195 return buildPolynomial(degree, LEGENDRE_COEFFICIENTS,
196 new RecurrenceCoefficientsGenerator() {
197
198 @Override
199 public BigFraction[] generate(int k) {
200 final int kP1 = k + 1;
201 return new BigFraction[] {
202 BigFraction.ZERO,
203 new BigFraction(k + kP1, kP1),
204 new BigFraction(k, kP1)};
205 }
206 });
207 }
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227 public static PolynomialFunction createJacobiPolynomial(final int degree, final int v, final int w) {
228
229
230 final JacobiKey key = new JacobiKey(v, w);
231
232 if (!JACOBI_COEFFICIENTS.containsKey(key)) {
233
234
235 final List<BigFraction> list = new ArrayList<>();
236 JACOBI_COEFFICIENTS.put(key, list);
237
238
239 list.add(BigFraction.ONE);
240
241
242 list.add(new BigFraction(v - w, 2));
243 list.add(new BigFraction(2 + v + w, 2));
244
245 }
246
247 return buildPolynomial(degree, JACOBI_COEFFICIENTS.get(key),
248 new RecurrenceCoefficientsGenerator() {
249
250 @Override
251 public BigFraction[] generate(int k) {
252 k++;
253 final int kvw = k + v + w;
254 final int twoKvw = kvw + k;
255 final int twoKvwM1 = twoKvw - 1;
256 final int twoKvwM2 = twoKvw - 2;
257 final int den = 2 * k * kvw * twoKvwM2;
258
259 return new BigFraction[] {
260 new BigFraction(twoKvwM1 * (v * v - w * w), den),
261 new BigFraction(twoKvwM1 * twoKvw * twoKvwM2, den),
262 new BigFraction(2 * (k + v - 1) * (k + w - 1) * twoKvw, den)
263 };
264 }
265 });
266
267 }
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286 public static double[] shift(final double[] coefficients,
287 final double shift) {
288 final int dp1 = coefficients.length;
289 final double[] newCoefficients = new double[dp1];
290
291
292 final int[][] coeff = new int[dp1][dp1];
293 for (int i = 0; i < dp1; i++){
294 for(int j = 0; j <= i; j++){
295 coeff[i][j] = (int) CombinatoricsUtils.binomialCoefficient(i, j);
296 }
297 }
298
299
300 for (int i = 0; i < dp1; i++){
301 newCoefficients[0] += coefficients[i] * FastMath.pow(shift, i);
302 }
303
304
305 final int d = dp1 - 1;
306 for (int i = 0; i < d; i++) {
307 for (int j = i; j < d; j++){
308 newCoefficients[i + 1] += coeff[j + 1][j - i] *
309 coefficients[j + 1] * FastMath.pow(shift, j - i);
310 }
311 }
312
313 return newCoefficients;
314 }
315
316
317
318
319
320
321
322
323 private static PolynomialFunction buildPolynomial(final int degree,
324 final List<BigFraction> coefficients,
325 final RecurrenceCoefficientsGenerator generator) {
326
327 synchronized (coefficients) {
328 final int maxDegree = (int) FastMath.floor(FastMath.sqrt(2 * coefficients.size())) - 1;
329 if (degree > maxDegree) {
330 computeUpToDegree(degree, maxDegree, generator, coefficients);
331 }
332 }
333
334
335
336
337
338
339
340
341
342 final int start = degree * (degree + 1) / 2;
343
344 final double[] a = new double[degree + 1];
345 for (int i = 0; i <= degree; ++i) {
346 a[i] = coefficients.get(start + i).doubleValue();
347 }
348
349
350 return new PolynomialFunction(a);
351
352 }
353
354
355
356
357
358
359
360 private static void computeUpToDegree(final int degree, final int maxDegree,
361 final RecurrenceCoefficientsGenerator generator,
362 final List<BigFraction> coefficients) {
363
364 int startK = (maxDegree - 1) * maxDegree / 2;
365 for (int k = maxDegree; k < degree; ++k) {
366
367
368 int startKm1 = startK;
369 startK += k;
370
371
372 BigFraction[] ai = generator.generate(k);
373
374 BigFraction ck = coefficients.get(startK);
375 BigFraction ckm1 = coefficients.get(startKm1);
376
377
378 coefficients.add(ck.multiply(ai[0]).subtract(ckm1.multiply(ai[2])));
379
380
381 for (int i = 1; i < k; ++i) {
382 final BigFraction ckPrev = ck;
383 ck = coefficients.get(startK + i);
384 ckm1 = coefficients.get(startKm1 + i);
385 coefficients.add(ck.multiply(ai[0]).add(ckPrev.multiply(ai[1])).subtract(ckm1.multiply(ai[2])));
386 }
387
388
389 final BigFraction ckPrev = ck;
390 ck = coefficients.get(startK + k);
391 coefficients.add(ck.multiply(ai[0]).add(ckPrev.multiply(ai[1])));
392
393
394 coefficients.add(ck.multiply(ai[1]));
395
396 }
397
398 }
399
400
401 private interface RecurrenceCoefficientsGenerator {
402
403
404
405
406
407
408 BigFraction[] generate(int k);
409 }
410
411 }