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.io.Serializable;
25 import java.util.Arrays;
26
27 import org.hipparchus.CalculusFieldElement;
28 import org.hipparchus.analysis.FieldUnivariateFunction;
29 import org.hipparchus.analysis.ParametricUnivariateFunction;
30 import org.hipparchus.analysis.differentiation.Derivative;
31 import org.hipparchus.analysis.differentiation.UnivariateDifferentiableFunction;
32 import org.hipparchus.exception.LocalizedCoreFormats;
33 import org.hipparchus.exception.MathIllegalArgumentException;
34 import org.hipparchus.exception.NullArgumentException;
35 import org.hipparchus.util.FastMath;
36 import org.hipparchus.util.MathUtils;
37
38
39
40
41
42
43
44
45 public class PolynomialFunction implements UnivariateDifferentiableFunction, FieldUnivariateFunction, Serializable {
46
47
48
49 private static final long serialVersionUID = -7726511984200295583L;
50
51
52
53
54
55 private final double[] coefficients;
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 public PolynomialFunction(double... c)
72 throws MathIllegalArgumentException, NullArgumentException {
73 super();
74 MathUtils.checkNotNull(c);
75 int n = c.length;
76 if (n == 0) {
77 throw new MathIllegalArgumentException(LocalizedCoreFormats.EMPTY_POLYNOMIALS_COEFFICIENTS_ARRAY);
78 }
79 while ((n > 1) && (c[n - 1] == 0)) {
80 --n;
81 }
82 this.coefficients = new double[n];
83 System.arraycopy(c, 0, this.coefficients, 0, n);
84 }
85
86
87
88
89
90
91
92
93
94
95
96
97
98 @Override
99 public double value(double x) {
100 return evaluate(coefficients, x);
101 }
102
103
104
105
106
107
108 public int degree() {
109 return coefficients.length - 1;
110 }
111
112
113
114
115
116
117
118
119
120 public double[] getCoefficients() {
121 return coefficients.clone();
122 }
123
124
125
126
127
128
129
130
131
132
133
134 protected static double evaluate(double[] coefficients, double argument)
135 throws MathIllegalArgumentException, NullArgumentException {
136 MathUtils.checkNotNull(coefficients);
137 int n = coefficients.length;
138 if (n == 0) {
139 throw new MathIllegalArgumentException(LocalizedCoreFormats.EMPTY_POLYNOMIALS_COEFFICIENTS_ARRAY);
140 }
141 double result = coefficients[n - 1];
142 for (int j = n - 2; j >= 0; j--) {
143 result = argument * result + coefficients[j];
144 }
145 return result;
146 }
147
148
149
150
151
152
153 @Override
154 public <T extends Derivative<T>> T value(final T t)
155 throws MathIllegalArgumentException, NullArgumentException {
156 MathUtils.checkNotNull(coefficients);
157 int n = coefficients.length;
158 if (n == 0) {
159 throw new MathIllegalArgumentException(LocalizedCoreFormats.EMPTY_POLYNOMIALS_COEFFICIENTS_ARRAY);
160 }
161 T result = t.getField().getZero().add(coefficients[n - 1]);
162 for (int j = n - 2; j >= 0; j--) {
163 result = result.multiply(t).add(coefficients[j]);
164 }
165 return result;
166 }
167
168
169
170
171
172
173 @Override
174 public <T extends CalculusFieldElement<T>> T value(final T t)
175 throws MathIllegalArgumentException, NullArgumentException {
176 MathUtils.checkNotNull(coefficients);
177 int n = coefficients.length;
178 if (n == 0) {
179 throw new MathIllegalArgumentException(LocalizedCoreFormats.EMPTY_POLYNOMIALS_COEFFICIENTS_ARRAY);
180 }
181 T result = t.getField().getZero().add(coefficients[n - 1]);
182 for (int j = n - 2; j >= 0; j--) {
183 result = result.multiply(t).add(coefficients[j]);
184 }
185 return result;
186 }
187
188
189
190
191
192
193
194 public PolynomialFunction add(final PolynomialFunction p) {
195
196 final int lowLength = FastMath.min(coefficients.length, p.coefficients.length);
197 final int highLength = FastMath.max(coefficients.length, p.coefficients.length);
198
199
200 double[] newCoefficients = new double[highLength];
201 for (int i = 0; i < lowLength; ++i) {
202 newCoefficients[i] = coefficients[i] + p.coefficients[i];
203 }
204 System.arraycopy((coefficients.length < p.coefficients.length) ?
205 p.coefficients : coefficients,
206 lowLength,
207 newCoefficients, lowLength,
208 highLength - lowLength);
209
210 return new PolynomialFunction(newCoefficients);
211 }
212
213
214
215
216
217
218
219 public PolynomialFunction subtract(final PolynomialFunction p) {
220
221 int lowLength = FastMath.min(coefficients.length, p.coefficients.length);
222 int highLength = FastMath.max(coefficients.length, p.coefficients.length);
223
224
225 double[] newCoefficients = new double[highLength];
226 for (int i = 0; i < lowLength; ++i) {
227 newCoefficients[i] = coefficients[i] - p.coefficients[i];
228 }
229 if (coefficients.length < p.coefficients.length) {
230 for (int i = lowLength; i < highLength; ++i) {
231 newCoefficients[i] = -p.coefficients[i];
232 }
233 } else {
234 System.arraycopy(coefficients, lowLength, newCoefficients, lowLength,
235 highLength - lowLength);
236 }
237
238 return new PolynomialFunction(newCoefficients);
239 }
240
241
242
243
244
245
246 public PolynomialFunction negate() {
247 double[] newCoefficients = new double[coefficients.length];
248 for (int i = 0; i < coefficients.length; ++i) {
249 newCoefficients[i] = -coefficients[i];
250 }
251 return new PolynomialFunction(newCoefficients);
252 }
253
254
255
256
257
258
259
260 public PolynomialFunction multiply(final PolynomialFunction p) {
261 double[] newCoefficients = new double[coefficients.length + p.coefficients.length - 1];
262
263 for (int i = 0; i < newCoefficients.length; ++i) {
264 newCoefficients[i] = 0.0;
265 for (int j = FastMath.max(0, i + 1 - p.coefficients.length);
266 j < FastMath.min(coefficients.length, i + 1);
267 ++j) {
268 newCoefficients[i] += coefficients[j] * p.coefficients[i-j];
269 }
270 }
271
272 return new PolynomialFunction(newCoefficients);
273 }
274
275
276
277
278
279
280
281
282
283 protected static double[] differentiate(double[] coefficients)
284 throws MathIllegalArgumentException, NullArgumentException {
285 MathUtils.checkNotNull(coefficients);
286 int n = coefficients.length;
287 if (n == 0) {
288 throw new MathIllegalArgumentException(LocalizedCoreFormats.EMPTY_POLYNOMIALS_COEFFICIENTS_ARRAY);
289 }
290 if (n == 1) {
291 return new double[]{0};
292 }
293 double[] result = new double[n - 1];
294 for (int i = n - 1; i > 0; i--) {
295 result[i - 1] = i * coefficients[i];
296 }
297 return result;
298 }
299
300
301
302
303
304
305 public PolynomialFunction antiDerivative() {
306 final int d = degree();
307 final double[] anti = new double[d + 2];
308 anti[0] = 0d;
309 for (int i = 1; i <= d + 1; i++) {
310 anti[i] = coefficients[i - 1] / i;
311 }
312 return new PolynomialFunction(anti);
313 }
314
315
316
317
318
319
320
321
322
323
324
325
326 public double integrate(final double lower, final double upper) {
327 if (Double.isInfinite(lower) || Double.isInfinite(upper)) {
328 throw new MathIllegalArgumentException(LocalizedCoreFormats.INFINITE_BOUND);
329 }
330 if (lower > upper) {
331 throw new MathIllegalArgumentException(LocalizedCoreFormats.LOWER_BOUND_NOT_BELOW_UPPER_BOUND);
332 }
333 final PolynomialFunction anti = antiDerivative();
334 return anti.value(upper) - anti.value(lower);
335 }
336
337
338
339
340
341
342 public PolynomialFunction polynomialDerivative() {
343 return new PolynomialFunction(differentiate(coefficients));
344 }
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361 @Override
362 public String toString() {
363 StringBuilder s = new StringBuilder();
364 if (coefficients[0] == 0.0) {
365 if (coefficients.length == 1) {
366 return "0";
367 }
368 } else {
369 s.append(toString(coefficients[0]));
370 }
371
372 for (int i = 1; i < coefficients.length; ++i) {
373 if (coefficients[i] != 0) {
374 if (s.length() > 0) {
375 if (coefficients[i] < 0) {
376 s.append(" - ");
377 } else {
378 s.append(" + ");
379 }
380 } else {
381 if (coefficients[i] < 0) {
382 s.append('-');
383 }
384 }
385
386 double absAi = FastMath.abs(coefficients[i]);
387 if ((absAi - 1) != 0) {
388 s.append(toString(absAi));
389 s.append(' ');
390 }
391
392 s.append('x');
393 if (i > 1) {
394 s.append('^');
395 s.append(i);
396 }
397 }
398 }
399
400 return s.toString();
401 }
402
403
404
405
406
407
408
409 private static String toString(double coeff) {
410 final String c = Double.toString(coeff);
411 if (c.endsWith(".0")) {
412 return c.substring(0, c.length() - 2);
413 } else {
414 return c;
415 }
416 }
417
418
419 @Override
420 public int hashCode() {
421 final int prime = 31;
422 int result = 1;
423 result = prime * result + Arrays.hashCode(coefficients);
424 return result;
425 }
426
427
428 @Override
429 public boolean equals(Object obj) {
430 if (this == obj) {
431 return true;
432 }
433 if (!(obj instanceof PolynomialFunction)) {
434 return false;
435 }
436 PolynomialFunction other = (PolynomialFunction) obj;
437 return Arrays.equals(coefficients, other.coefficients);
438 }
439
440
441
442
443
444 public static class Parametric implements ParametricUnivariateFunction {
445
446
447
448
449
450
451
452
453 public Parametric() {
454
455 }
456
457
458 @Override
459 public double[] gradient(double x, double ... parameters) {
460 final double[] gradient = new double[parameters.length];
461 double xn = 1.0;
462 for (int i = 0; i < parameters.length; ++i) {
463 gradient[i] = xn;
464 xn *= x;
465 }
466 return gradient;
467 }
468
469
470 @Override
471 public double value(final double x, final double ... parameters)
472 throws MathIllegalArgumentException {
473 return PolynomialFunction.evaluate(parameters, x);
474 }
475 }
476 }