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 static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertTrue;
26
27 import org.hipparchus.CalculusFieldElement;
28 import org.hipparchus.Field;
29 import org.hipparchus.analysis.CalculusFieldUnivariateFunction;
30 import org.hipparchus.analysis.UnivariateFunction;
31 import org.hipparchus.exception.MathIllegalArgumentException;
32 import org.hipparchus.exception.NullArgumentException;
33 import org.hipparchus.random.RandomDataGenerator;
34 import org.hipparchus.util.Binary64;
35 import org.hipparchus.util.FastMath;
36 import org.hipparchus.util.MathArrays;
37 import org.hipparchus.util.Precision;
38 import org.junit.Assert;
39 import org.junit.Test;
40
41 public class AkimaSplineInterpolatorTest {
42
43 @Test
44 public void testIssueModifiedWeights() {
45 double[] x = {1, 2, 3, 4, 5, 6, 7, 8};
46 double[] y = {-1, -1, -1, 0, 1, 1, 1, 1};
47 UnivariateFunction original = new AkimaSplineInterpolator().interpolate(x, y);
48 UnivariateFunction modified = new AkimaSplineInterpolator(true).interpolate(x, y);
49 for (double d = 1.01; d <=8; d += 0.02) {
50 if (d < 2) {
51
52 Assert.assertEquals(-1.0, original.value(d), 1.0e-15);
53 Assert.assertEquals(-1.0, modified.value(d), 1.0e-15);
54 } else if (d < 3) {
55
56 Assert.assertTrue(original.value(d) < -1);
57 Assert.assertEquals(-1.0, modified.value(d), 1.0e-15);
58 } else if (d < 4) {
59
60 Assert.assertTrue(original.value(d) > -1 && original.value(d) < 0);
61 Assert.assertTrue(modified.value(d) > -1 && modified.value(d) < 0);
62 Assert.assertTrue(original.value(d) > modified.value(d));
63 } else if (d < 5) {
64
65 Assert.assertTrue(original.value(d) < +1 && original.value(d) > 0);
66 Assert.assertTrue(modified.value(d) < +1 && modified.value(d) > 0);
67 Assert.assertTrue(original.value(d) < modified.value(d));
68 } else if (d < 6) {
69
70 Assert.assertTrue(original.value(d) > +1);
71 Assert.assertEquals(+1.0, modified.value(d), 1.0e-15);
72 } else {
73
74 Assert.assertEquals(+1.0, original.value(d), 1.0e-15);
75 Assert.assertEquals(+1.0, modified.value(d), 1.0e-15);
76 }
77 }
78 }
79
80 @Test
81 public void testIllegalArguments() {
82
83 UnivariateInterpolator i = new AkimaSplineInterpolator();
84
85 try
86 {
87 double[] yval = { 0.0, 1.0, 2.0, 3.0, 4.0 };
88 i.interpolate( null, yval );
89 Assert.fail( "Failed to detect x null pointer" );
90 }
91 catch ( NullArgumentException iae )
92 {
93
94 }
95
96 try
97 {
98 double[] xval = { 0.0, 1.0, 2.0, 3.0, 4.0 };
99 i.interpolate( xval, null );
100 Assert.fail( "Failed to detect y null pointer" );
101 }
102 catch ( NullArgumentException iae )
103 {
104
105 }
106
107 try
108 {
109 double[] xval = { 0.0, 1.0, 2.0, 3.0 };
110 double[] yval = { 0.0, 1.0, 2.0, 3.0 };
111 i.interpolate( xval, yval );
112 Assert.fail( "Failed to detect insufficient data" );
113 }
114 catch ( MathIllegalArgumentException iae )
115 {
116
117 }
118
119 try
120 {
121 double[] xval = { 0.0, 1.0, 2.0, 3.0, 4.0 };
122 double[] yval = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 };
123 i.interpolate( xval, yval );
124 Assert.fail( "Failed to detect data set array with different sizes." );
125 }
126 catch ( MathIllegalArgumentException iae )
127 {
128
129 }
130
131
132 try
133 {
134 double[] xval = { 0.0, 1.0, 0.5, 7.0, 3.5, 2.2, 8.0 };
135 double[] yval = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
136 i.interpolate( xval, yval );
137 Assert.fail( "Failed to detect unsorted arguments." );
138 }
139 catch ( MathIllegalArgumentException iae )
140 {
141
142 }
143 }
144
145 @Test
146 public void testIllegalArgumentsD64()
147 {
148
149 FieldUnivariateInterpolator i = new AkimaSplineInterpolator();
150
151 try
152 {
153 Binary64[] yval = buildD64(0.0, 1.0, 2.0, 3.0, 4.0);
154 i.interpolate( null, yval );
155 Assert.fail( "Failed to detect x null pointer" );
156 }
157 catch ( NullArgumentException iae )
158 {
159
160 }
161
162 try
163 {
164 Binary64[] xval = buildD64(0.0, 1.0, 2.0, 3.0, 4.0);
165 i.interpolate( xval, null );
166 Assert.fail( "Failed to detect y null pointer" );
167 }
168 catch ( NullArgumentException iae )
169 {
170
171 }
172
173 try
174 {
175 Binary64[] xval = buildD64(0.0, 1.0, 2.0, 3.0);
176 Binary64[] yval = buildD64(0.0, 1.0, 2.0, 3.0);
177 i.interpolate( xval, yval );
178 Assert.fail( "Failed to detect insufficient data" );
179 }
180 catch ( MathIllegalArgumentException iae )
181 {
182
183 }
184
185 try
186 {
187 Binary64[] xval = buildD64(0.0, 1.0, 2.0, 3.0, 4.0);
188 Binary64[] yval = buildD64(0.0, 1.0, 2.0, 3.0, 4.0, 5.0);
189 i.interpolate( xval, yval );
190 Assert.fail( "Failed to detect data set array with different sizes." );
191 }
192 catch ( MathIllegalArgumentException iae )
193 {
194
195 }
196
197
198 try
199 {
200 Binary64[] xval = buildD64(0.0, 1.0, 0.5, 7.0, 3.5, 2.2, 8.0);
201 Binary64[] yval = buildD64(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
202 i.interpolate( xval, yval );
203 Assert.fail( "Failed to detect unsorted arguments." );
204 }
205 catch ( MathIllegalArgumentException iae )
206 {
207
208 }
209 }
210
211
212
213
214
215
216 @Test
217 public void testInterpolateLine()
218 {
219 final int numberOfElements = 10;
220 final double minimumX = -10;
221 final double maximumX = 10;
222 final int numberOfSamples = 100;
223 final double interpolationTolerance = 1e-15;
224 final double maxTolerance = 1e-15;
225
226 UnivariateFunction f = x -> 2 * x - 5;
227
228 testInterpolation( minimumX, maximumX, numberOfElements, numberOfSamples, f, interpolationTolerance,
229 maxTolerance );
230 }
231
232
233
234
235
236
237 @Test
238 public void testInterpolateLineD64()
239 {
240 final int numberOfElements = 10;
241 final Binary64 minimumX = new Binary64(-10);
242 final Binary64 maximumX = new Binary64(10);
243 final int numberOfSamples = 100;
244 final double interpolationTolerance = 1e-15;
245 final double maxTolerance = 1e-15;
246
247 CalculusFieldUnivariateFunction<Binary64> f = x -> x.multiply(2).subtract(5);
248
249 testInterpolation( minimumX, maximumX, numberOfElements, numberOfSamples, f, interpolationTolerance,
250 maxTolerance );
251 }
252
253
254
255
256
257
258
259 @Test
260 public void testInterpolateParabola()
261 {
262 final int numberOfElements = 10;
263 final double minimumX = -10;
264 final double maximumX = 10;
265 final int numberOfSamples = 100;
266 final double interpolationTolerance = 7e-15;
267 final double maxTolerance = 6e-14;
268
269 UnivariateFunction f = x -> ( 3 * x * x ) - ( 5 * x ) + 7;
270
271 testInterpolation( minimumX, maximumX, numberOfElements, numberOfSamples, f, interpolationTolerance,
272 maxTolerance );
273 }
274
275
276
277
278
279
280
281 @Test
282 public void testInterpolateParabolaD64()
283 {
284 final int numberOfElements = 10;
285 final Binary64 minimumX = new Binary64(-10);
286 final Binary64 maximumX = new Binary64(10);
287 final int numberOfSamples = 100;
288 final double interpolationTolerance = 7e-15;
289 final double maxTolerance = 6e-14;
290
291 CalculusFieldUnivariateFunction<Binary64> f = x -> x.square().multiply(3).
292 subtract(x.multiply(5)).
293 add(7);
294
295 testInterpolation( minimumX, maximumX, numberOfElements, numberOfSamples, f, interpolationTolerance,
296 maxTolerance );
297 }
298
299
300
301
302
303
304 @Test
305 public void testInterpolateCubic()
306 {
307 final int numberOfElements = 10;
308 final double minimumX = -3;
309 final double maximumX = 3;
310 final int numberOfSamples = 100;
311 final double interpolationTolerance = 0.37;
312 final double maxTolerance = 3.8;
313
314 UnivariateFunction f = x -> ( 3 * x * x * x ) - ( 0.5 * x * x ) + ( 1 * x ) - 1;
315
316 testInterpolation( minimumX, maximumX, numberOfElements, numberOfSamples, f, interpolationTolerance,
317 maxTolerance );
318 }
319
320
321
322
323
324
325 @Test
326 public void testInterpolateCubic64()
327 {
328 final int numberOfElements = 10;
329 final Binary64 minimumX = new Binary64(-3);
330 final Binary64 maximumX = new Binary64(3);
331 final int numberOfSamples = 100;
332 final double interpolationTolerance = 0.37;
333 final double maxTolerance = 3.8;
334
335 CalculusFieldUnivariateFunction<Binary64> f = x -> x.square().multiply(x).multiply(3).
336 subtract(x.square().multiply(0.5)).
337 add(x).
338 subtract(1);
339
340 testInterpolation( minimumX, maximumX, numberOfElements, numberOfSamples, f, interpolationTolerance,
341 maxTolerance );
342 }
343
344 private void testInterpolation( double minimumX, double maximumX, int numberOfElements, int numberOfSamples,
345 UnivariateFunction f, double tolerance, double maxTolerance )
346 {
347 double expected;
348 double actual;
349 double currentX;
350 final double delta = ( maximumX - minimumX ) / ( (double) numberOfElements );
351 double[] xValues = new double[numberOfElements];
352 double[] yValues = new double[numberOfElements];
353
354 for ( int i = 0; i < numberOfElements; i++ )
355 {
356 xValues[i] = minimumX + delta * (double) i;
357 yValues[i] = f.value( xValues[i] );
358 }
359
360 UnivariateFunction interpolation = new AkimaSplineInterpolator().interpolate( xValues, yValues );
361
362 for ( int i = 0; i < numberOfElements; i++ )
363 {
364 currentX = xValues[i];
365 expected = f.value( currentX );
366 actual = interpolation.value( currentX );
367 assertTrue( Precision.equals( expected, actual ) );
368 }
369
370 final RandomDataGenerator randomDataGenerator = new RandomDataGenerator(1234567L);
371
372 double sumError = 0;
373 for ( int i = 0; i < numberOfSamples; i++ )
374 {
375 currentX = randomDataGenerator.nextUniform(xValues[0], xValues[xValues.length - 1]);
376 expected = f.value( currentX );
377 actual = interpolation.value( currentX );
378 sumError += FastMath.abs( actual - expected );
379 assertEquals( expected, actual, maxTolerance );
380 }
381
382 assertEquals( 0.0, ( sumError / (double) numberOfSamples ), tolerance );
383 }
384
385 private <T extends CalculusFieldElement<T>> void testInterpolation(T minimumX, T maximumX,
386 int numberOfElements, int numberOfSamples,
387 CalculusFieldUnivariateFunction<T> f,
388 double tolerance, double maxTolerance)
389 {
390 final Field<T> field = minimumX.getField();
391 T expected;
392 T actual;
393 T currentX;
394 final T delta = maximumX.subtract(minimumX).divide(numberOfElements);
395 T[] xValues = MathArrays.buildArray(field, numberOfElements);
396 T[] yValues = MathArrays.buildArray(field, numberOfElements);
397
398 for ( int i = 0; i < numberOfElements; i++ )
399 {
400 xValues[i] = minimumX.add(delta.multiply(i));
401 yValues[i] = f.value(xValues[i]);
402 }
403
404 CalculusFieldUnivariateFunction<T> interpolation =
405 new AkimaSplineInterpolator().interpolate( xValues, yValues );
406
407 for ( int i = 0; i < numberOfElements; i++ )
408 {
409 currentX = xValues[i];
410 expected = f.value( currentX );
411 actual = interpolation.value( currentX );
412 assertTrue(Precision.equals(expected.getReal(), actual.getReal()));
413 }
414
415 final RandomDataGenerator randomDataGenerator = new RandomDataGenerator(1234567L);
416
417 double sumError = 0;
418 for ( int i = 0; i < numberOfSamples; i++ )
419 {
420 final double r = randomDataGenerator.nextUniform(xValues[0].getReal(),
421 xValues[xValues.length - 1].getReal());
422 currentX = field.getZero().add(r);
423 expected = f.value( currentX );
424 actual = interpolation.value( currentX );
425 sumError += FastMath.norm(actual.subtract(expected));
426 assertEquals(expected.getReal(), actual.getReal(), maxTolerance);
427 }
428
429 assertEquals(0.0, sumError / numberOfSamples, tolerance);
430 }
431
432 private Binary64[] buildD64(double...c) {
433 Binary64[] array = new Binary64[c.length];
434 for (int i = 0; i < c.length; ++i) {
435 array[i] = new Binary64(c[i]);
436 }
437 return array;
438 }
439
440 }