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.interpolation;
23
24 import org.hipparchus.analysis.polynomials.PolynomialFunction;
25 import org.hipparchus.dfp.Dfp;
26 import org.hipparchus.dfp.DfpField;
27 import org.hipparchus.exception.MathIllegalArgumentException;
28 import org.hipparchus.fraction.BigFraction;
29 import org.hipparchus.util.FastMath;
30 import org.junit.jupiter.api.Test;
31
32 import java.util.Random;
33
34 import static org.junit.jupiter.api.Assertions.assertEquals;
35 import static org.junit.jupiter.api.Assertions.assertThrows;
36
37 class FieldHermiteInterpolatorTest {
38
39 @Test
40 void testZero() {
41 FieldHermiteInterpolator<BigFraction> interpolator = new FieldHermiteInterpolator<BigFraction>();
42 interpolator.addSamplePoint(new BigFraction(0), new BigFraction[] { new BigFraction(0) });
43 for (int x = -10; x < 10; x++) {
44 BigFraction y = interpolator.value(new BigFraction(x))[0];
45 assertEquals(BigFraction.ZERO, y);
46 BigFraction[][] derivatives = interpolator.derivatives(new BigFraction(x), 1);
47 assertEquals(BigFraction.ZERO, derivatives[0][0]);
48 assertEquals(BigFraction.ZERO, derivatives[1][0]);
49 }
50 }
51
52 @Test
53 void testQuadratic() {
54 FieldHermiteInterpolator<BigFraction> interpolator = new FieldHermiteInterpolator<BigFraction>();
55 interpolator.addSamplePoint(new BigFraction(0), new BigFraction[] { new BigFraction(2) });
56 interpolator.addSamplePoint(new BigFraction(1), new BigFraction[] { new BigFraction(0) });
57 interpolator.addSamplePoint(new BigFraction(2), new BigFraction[] { new BigFraction(0) });
58 for (double x = -10; x < 10; x += 1.0) {
59 BigFraction y = interpolator.value(new BigFraction(x))[0];
60 assertEquals((x - 1) * (x - 2), y.doubleValue(), 1.0e-15);
61 BigFraction[][] derivatives = interpolator.derivatives(new BigFraction(x), 3);
62 assertEquals((x - 1) * (x - 2), derivatives[0][0].doubleValue(), 1.0e-15);
63 assertEquals(2 * x - 3, derivatives[1][0].doubleValue(), 1.0e-15);
64 assertEquals(2, derivatives[2][0].doubleValue(), 1.0e-15);
65 assertEquals(0, derivatives[3][0].doubleValue(), 1.0e-15);
66 }
67 }
68
69 @Test
70 void testMixedDerivatives() {
71 FieldHermiteInterpolator<BigFraction> interpolator = new FieldHermiteInterpolator<BigFraction>();
72 interpolator.addSamplePoint(new BigFraction(0), new BigFraction[] { new BigFraction(1) }, new BigFraction[] { new BigFraction(2) });
73 interpolator.addSamplePoint(new BigFraction(1), new BigFraction[] { new BigFraction(4) });
74 interpolator.addSamplePoint(new BigFraction(2), new BigFraction[] { new BigFraction(5) }, new BigFraction[] { new BigFraction(2) });
75 BigFraction[][] derivatives = interpolator.derivatives(new BigFraction(0), 5);
76 assertEquals(new BigFraction( 1), derivatives[0][0]);
77 assertEquals(new BigFraction( 2), derivatives[1][0]);
78 assertEquals(new BigFraction( 8), derivatives[2][0]);
79 assertEquals(new BigFraction(-24), derivatives[3][0]);
80 assertEquals(new BigFraction( 24), derivatives[4][0]);
81 assertEquals(new BigFraction( 0), derivatives[5][0]);
82 derivatives = interpolator.derivatives(new BigFraction(1), 5);
83 assertEquals(new BigFraction( 4), derivatives[0][0]);
84 assertEquals(new BigFraction( 2), derivatives[1][0]);
85 assertEquals(new BigFraction( -4), derivatives[2][0]);
86 assertEquals(new BigFraction( 0), derivatives[3][0]);
87 assertEquals(new BigFraction( 24), derivatives[4][0]);
88 assertEquals(new BigFraction( 0), derivatives[5][0]);
89 derivatives = interpolator.derivatives(new BigFraction(2), 5);
90 assertEquals(new BigFraction( 5), derivatives[0][0]);
91 assertEquals(new BigFraction( 2), derivatives[1][0]);
92 assertEquals(new BigFraction( 8), derivatives[2][0]);
93 assertEquals(new BigFraction( 24), derivatives[3][0]);
94 assertEquals(new BigFraction( 24), derivatives[4][0]);
95 assertEquals(new BigFraction( 0), derivatives[5][0]);
96 }
97
98 @Test
99 void testRandomPolynomialsValuesOnly() {
100
101 Random random = new Random(0x42b1e7dbd361a932l);
102
103 for (int i = 0; i < 100; ++i) {
104
105 int maxDegree = 0;
106 PolynomialFunction[] p = new PolynomialFunction[5];
107 for (int k = 0; k < p.length; ++k) {
108 int degree = random.nextInt(7);
109 p[k] = randomPolynomial(degree, random);
110 maxDegree = FastMath.max(maxDegree, degree);
111 }
112
113 DfpField field = new DfpField(30);
114 Dfp step = field.getOne().divide(field.newDfp(10));
115 FieldHermiteInterpolator<Dfp> interpolator = new FieldHermiteInterpolator<Dfp>();
116 for (int j = 0; j < 1 + maxDegree; ++j) {
117 Dfp x = field.newDfp(j).multiply(step);
118 Dfp[] values = new Dfp[p.length];
119 for (int k = 0; k < p.length; ++k) {
120 values[k] = field.newDfp(p[k].value(x.getReal()));
121 }
122 interpolator.addSamplePoint(x, values);
123 }
124
125 for (int j = 0; j < 20; ++j) {
126 Dfp x = field.newDfp(j).multiply(step);
127 Dfp[] values = interpolator.value(x);
128 assertEquals(p.length, values.length);
129 for (int k = 0; k < p.length; ++k) {
130 assertEquals(p[k].value(x.getReal()),
131 values[k].getReal(),
132 1.0e-8 * FastMath.abs(p[k].value(x.getReal())));
133 }
134 }
135
136 }
137
138 }
139
140 @Test
141 void testRandomPolynomialsFirstDerivative() {
142
143 Random random = new Random(0x570803c982ca5d3bl);
144
145 for (int i = 0; i < 100; ++i) {
146
147 int maxDegree = 0;
148 PolynomialFunction[] p = new PolynomialFunction[5];
149 PolynomialFunction[] pPrime = new PolynomialFunction[5];
150 for (int k = 0; k < p.length; ++k) {
151 int degree = random.nextInt(7);
152 p[k] = randomPolynomial(degree, random);
153 pPrime[k] = p[k].polynomialDerivative();
154 maxDegree = FastMath.max(maxDegree, degree);
155 }
156
157 DfpField field = new DfpField(30);
158 Dfp step = field.getOne().divide(field.newDfp(10));
159 FieldHermiteInterpolator<Dfp> interpolator = new FieldHermiteInterpolator<Dfp>();
160 for (int j = 0; j < 1 + maxDegree / 2; ++j) {
161 Dfp x = field.newDfp(j).multiply(step);
162 Dfp[] values = new Dfp[p.length];
163 Dfp[] derivatives = new Dfp[p.length];
164 for (int k = 0; k < p.length; ++k) {
165 values[k] = field.newDfp(p[k].value(x.getReal()));
166 derivatives[k] = field.newDfp(pPrime[k].value(x.getReal()));
167 }
168 interpolator.addSamplePoint(x, values, derivatives);
169 }
170
171 Dfp h = step.divide(field.newDfp(100000));
172 for (int j = 0; j < 20; ++j) {
173 Dfp x = field.newDfp(j).multiply(step);
174 Dfp[] y = interpolator.value(x);
175 Dfp[] yP = interpolator.value(x.add(h));
176 Dfp[] yM = interpolator.value(x.subtract(h));
177 assertEquals(p.length, y.length);
178 for (int k = 0; k < p.length; ++k) {
179 assertEquals(p[k].value(x.getReal()),
180 y[k].getReal(),
181 1.0e-8 * FastMath.abs(p[k].value(x.getReal())));
182 assertEquals(pPrime[k].value(x.getReal()),
183 yP[k].subtract(yM[k]).divide(h.multiply(2)).getReal(),
184 4.0e-8 * FastMath.abs(p[k].value(x.getReal())));
185 }
186 }
187
188 }
189 }
190
191 @Test
192 void testSine() {
193 DfpField field = new DfpField(30);
194 FieldHermiteInterpolator<Dfp> interpolator = new FieldHermiteInterpolator<Dfp>();
195 for (Dfp x = field.getZero(); x.getReal() < FastMath.PI; x = x.add(0.5)) {
196 interpolator.addSamplePoint(x, new Dfp[] { x.sin() });
197 }
198 for (Dfp x = field.newDfp(0.1); x.getReal() < 2.9; x = x.add(0.01)) {
199 Dfp y = interpolator.value(x)[0];
200 assertEquals( x.sin().getReal(), y.getReal(), 3.5e-5);
201 }
202 }
203
204 @Test
205 void testSquareRoot() {
206 DfpField field = new DfpField(30);
207 FieldHermiteInterpolator<Dfp> interpolator = new FieldHermiteInterpolator<Dfp>();
208 for (Dfp x = field.getOne(); x.getReal() < 3.6; x = x.add(0.5)) {
209 interpolator.addSamplePoint(x, new Dfp[] { x.sqrt() });
210 }
211 for (Dfp x = field.newDfp(1.1); x.getReal() < 3.5; x = x.add(0.01)) {
212 Dfp y = interpolator.value(x)[0];
213 assertEquals(x.sqrt().getReal(), y.getReal(), 1.5e-4);
214 }
215 }
216
217 @Test
218 void testWikipedia() {
219
220
221 FieldHermiteInterpolator<BigFraction> interpolator = new FieldHermiteInterpolator<BigFraction>();
222 interpolator.addSamplePoint(new BigFraction(-1),
223 new BigFraction[] { new BigFraction( 2) },
224 new BigFraction[] { new BigFraction(-8) },
225 new BigFraction[] { new BigFraction(56) });
226 interpolator.addSamplePoint(new BigFraction( 0),
227 new BigFraction[] { new BigFraction( 1) },
228 new BigFraction[] { new BigFraction( 0) },
229 new BigFraction[] { new BigFraction( 0) });
230 interpolator.addSamplePoint(new BigFraction( 1),
231 new BigFraction[] { new BigFraction( 2) },
232 new BigFraction[] { new BigFraction( 8) },
233 new BigFraction[] { new BigFraction(56) });
234 for (BigFraction x = new BigFraction(-1); x.doubleValue() <= 1.0; x = x.add(new BigFraction(1, 8))) {
235 BigFraction y = interpolator.value(x)[0];
236 BigFraction x2 = x.multiply(x);
237 BigFraction x4 = x2.multiply(x2);
238 BigFraction x8 = x4.multiply(x4);
239 assertEquals(x8.add(new BigFraction(1)), y);
240 }
241 }
242
243 @Test
244 void testOnePointParabola() {
245 FieldHermiteInterpolator<BigFraction> interpolator = new FieldHermiteInterpolator<BigFraction>();
246 interpolator.addSamplePoint(new BigFraction(0),
247 new BigFraction[] { new BigFraction(1) },
248 new BigFraction[] { new BigFraction(1) },
249 new BigFraction[] { new BigFraction(2) });
250 for (BigFraction x = new BigFraction(-1); x.doubleValue() <= 1.0; x = x.add(new BigFraction(1, 8))) {
251 BigFraction y = interpolator.value(x)[0];
252 assertEquals(BigFraction.ONE.add(x.multiply(BigFraction.ONE.add(x))), y);
253 }
254 }
255
256 private PolynomialFunction randomPolynomial(int degree, Random random) {
257 double[] coeff = new double[ 1 + degree];
258 for (int j = 0; j < degree; ++j) {
259 coeff[j] = random.nextDouble();
260 }
261 return new PolynomialFunction(coeff);
262 }
263
264 @Test
265 void testEmptySampleValue() {
266 assertThrows(MathIllegalArgumentException.class, () -> {
267 new FieldHermiteInterpolator<BigFraction>().value(BigFraction.ZERO);
268 });
269 }
270
271 @Test
272 void testEmptySampleDerivative() {
273 assertThrows(MathIllegalArgumentException.class, () -> {
274 new FieldHermiteInterpolator<BigFraction>().derivatives(BigFraction.ZERO, 1);
275 });
276 }
277
278 @Test
279 void testDuplicatedAbscissa() {
280 assertThrows(MathIllegalArgumentException.class, () -> {
281 FieldHermiteInterpolator<BigFraction> interpolator = new FieldHermiteInterpolator<BigFraction>();
282 interpolator.addSamplePoint(new BigFraction(1), new BigFraction[]{new BigFraction(0)});
283 interpolator.addSamplePoint(new BigFraction(1), new BigFraction[]{new BigFraction(1)});
284 });
285 }
286
287 }
288