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