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.BivariateFunction;
25 import org.hipparchus.exception.MathIllegalArgumentException;
26 import org.hipparchus.random.RandomDataGenerator;
27 import org.hipparchus.util.FastMath;
28 import org.hipparchus.util.Precision;
29 import org.junit.jupiter.api.Test;
30
31 import static org.junit.jupiter.api.Assertions.assertEquals;
32 import static org.junit.jupiter.api.Assertions.assertFalse;
33 import static org.junit.jupiter.api.Assertions.assertTrue;
34 import static org.junit.jupiter.api.Assertions.fail;
35
36
37
38
39 final class BicubicInterpolatingFunctionTest {
40
41
42
43 @Test
44 void testPreconditions() {
45 double[] xval = new double[] {3, 4, 5, 6.5};
46 double[] yval = new double[] {-4, -3, -1, 2.5};
47 double[][] zval = new double[xval.length][yval.length];
48
49 @SuppressWarnings("unused")
50 BivariateFunction bcf = new BicubicInterpolatingFunction(xval, yval, zval,
51 zval, zval, zval);
52
53 try {
54 bcf = new BicubicInterpolatingFunction(new double[0], yval,
55 zval, zval, zval, zval);
56 fail("an exception should have been thrown");
57 } catch (MathIllegalArgumentException e) {
58
59 }
60 try {
61 bcf = new BicubicInterpolatingFunction(xval, new double[0],
62 zval, zval, zval, zval);
63 fail("an exception should have been thrown");
64 } catch (MathIllegalArgumentException e) {
65
66 }
67 try {
68 bcf = new BicubicInterpolatingFunction(xval, yval,
69 new double[0][], zval, zval, zval);
70 fail("an exception should have been thrown");
71 } catch (MathIllegalArgumentException e) {
72
73 }
74 try {
75 bcf = new BicubicInterpolatingFunction(xval, yval,
76 new double[1][0], zval, zval, zval);
77 fail("an exception should have been thrown");
78 } catch (MathIllegalArgumentException e) {
79
80 }
81
82 double[] wxval = new double[] {3, 2, 5, 6.5};
83 try {
84 bcf = new BicubicInterpolatingFunction(wxval, yval, zval, zval, zval, zval);
85 fail("an exception should have been thrown");
86 } catch (MathIllegalArgumentException e) {
87
88 }
89 double[] wyval = new double[] {-4, -1, -1, 2.5};
90 try {
91 bcf = new BicubicInterpolatingFunction(xval, wyval, zval, zval, zval, zval);
92 fail("an exception should have been thrown");
93 } catch (MathIllegalArgumentException e) {
94
95 }
96 double[][] wzval = new double[xval.length][yval.length - 1];
97 try {
98 bcf = new BicubicInterpolatingFunction(xval, yval, wzval, zval, zval, zval);
99 fail("an exception should have been thrown");
100 } catch (MathIllegalArgumentException e) {
101
102 }
103 try {
104 bcf = new BicubicInterpolatingFunction(xval, yval, zval, wzval, zval, zval);
105 fail("an exception should have been thrown");
106 } catch (MathIllegalArgumentException e) {
107
108 }
109 try {
110 bcf = new BicubicInterpolatingFunction(xval, yval, zval, zval, wzval, zval);
111 fail("an exception should have been thrown");
112 } catch (MathIllegalArgumentException e) {
113
114 }
115 try {
116 bcf = new BicubicInterpolatingFunction(xval, yval, zval, zval, zval, wzval);
117 fail("an exception should have been thrown");
118 } catch (MathIllegalArgumentException e) {
119
120 }
121
122 wzval = new double[xval.length - 1][yval.length];
123 try {
124 bcf = new BicubicInterpolatingFunction(xval, yval, wzval, zval, zval, zval);
125 fail("an exception should have been thrown");
126 } catch (MathIllegalArgumentException e) {
127
128 }
129 try {
130 bcf = new BicubicInterpolatingFunction(xval, yval, zval, wzval, zval, zval);
131 fail("an exception should have been thrown");
132 } catch (MathIllegalArgumentException e) {
133
134 }
135 try {
136 bcf = new BicubicInterpolatingFunction(xval, yval, zval, zval, wzval, zval);
137 fail("an exception should have been thrown");
138 } catch (MathIllegalArgumentException e) {
139
140 }
141 try {
142 bcf = new BicubicInterpolatingFunction(xval, yval, zval, zval, zval, wzval);
143 fail("an exception should have been thrown");
144 } catch (MathIllegalArgumentException e) {
145
146 }
147 }
148
149 @Test
150 void testIsValidPoint() {
151 final double xMin = -12;
152 final double xMax = 34;
153 final double yMin = 5;
154 final double yMax = 67;
155 final double[] xval = new double[] { xMin, xMax };
156 final double[] yval = new double[] { yMin, yMax };
157 final double[][] f = new double[][] { { 1, 2 },
158 { 3, 4 } };
159 final double[][] dFdX = f;
160 final double[][] dFdY = f;
161 final double[][] dFdXdY = f;
162
163 final BicubicInterpolatingFunction bcf
164 = new BicubicInterpolatingFunction(xval, yval, f,
165 dFdX, dFdY, dFdXdY);
166
167 double x, y;
168
169 x = xMin;
170 y = yMin;
171 assertTrue(bcf.isValidPoint(x, y));
172
173 bcf.value(x, y);
174
175 x = xMax;
176 y = yMax;
177 assertTrue(bcf.isValidPoint(x, y));
178
179 bcf.value(x, y);
180
181 final double xRange = xMax - xMin;
182 final double yRange = yMax - yMin;
183 x = xMin + xRange / 3.4;
184 y = yMin + yRange / 1.2;
185 assertTrue(bcf.isValidPoint(x, y));
186
187 bcf.value(x, y);
188
189 final double small = 1e-8;
190 x = xMin - small;
191 y = yMax;
192 assertFalse(bcf.isValidPoint(x, y));
193
194 try {
195 bcf.value(x, y);
196 fail("MathIllegalArgumentException expected");
197 } catch (MathIllegalArgumentException expected) {}
198
199 x = xMin;
200 y = yMax + small;
201 assertFalse(bcf.isValidPoint(x, y));
202
203 try {
204 bcf.value(x, y);
205 fail("MathIllegalArgumentException expected");
206 } catch (MathIllegalArgumentException expected) {}
207 }
208
209
210
211
212
213
214 @Test
215 void testPlane() {
216 final int numberOfElements = 10;
217 final double minimumX = -10;
218 final double maximumX = 10;
219 final double minimumY = -10;
220 final double maximumY = 10;
221 final int numberOfSamples = 1000;
222
223 final double interpolationTolerance = 1e-15;
224 final double maxTolerance = 1e-14;
225
226
227 BivariateFunction f = new BivariateFunction() {
228 @Override
229 public double value(double x, double y) {
230 return 2 * x - 3 * y + 5;
231 }
232 };
233 BivariateFunction dfdx = new BivariateFunction() {
234 @Override
235 public double value(double x, double y) {
236 return 2;
237 }
238 };
239 BivariateFunction dfdy = new BivariateFunction() {
240 @Override
241 public double value(double x, double y) {
242 return -3;
243 }
244 };
245 BivariateFunction d2fdxdy = new BivariateFunction() {
246 @Override
247 public double value(double x, double y) {
248 return 0;
249 }
250 };
251
252 testInterpolation(minimumX,
253 maximumX,
254 minimumY,
255 maximumY,
256 numberOfElements,
257 numberOfSamples,
258 f,
259 dfdx,
260 dfdy,
261 d2fdxdy,
262 interpolationTolerance,
263 maxTolerance,
264 false);
265 }
266
267
268
269
270
271
272 @Test
273 void testParaboloid() {
274 final int numberOfElements = 10;
275 final double minimumX = -10;
276 final double maximumX = 10;
277 final double minimumY = -10;
278 final double maximumY = 10;
279 final int numberOfSamples = 1000;
280
281 final double interpolationTolerance = 2e-14;
282 final double maxTolerance = 1e-12;
283
284
285 BivariateFunction f = new BivariateFunction() {
286 @Override
287 public double value(double x, double y) {
288 return 2 * x * x - 3 * y * y + 4 * x * y - 5;
289 }
290 };
291 BivariateFunction dfdx = new BivariateFunction() {
292 @Override
293 public double value(double x, double y) {
294 return 4 * (x + y);
295 }
296 };
297 BivariateFunction dfdy = new BivariateFunction() {
298 @Override
299 public double value(double x, double y) {
300 return 4 * x - 6 * y;
301 }
302 };
303 BivariateFunction d2fdxdy = new BivariateFunction() {
304 @Override
305 public double value(double x, double y) {
306 return 4;
307 }
308 };
309
310 testInterpolation(minimumX,
311 maximumX,
312 minimumY,
313 maximumY,
314 numberOfElements,
315 numberOfSamples,
316 f,
317 dfdx,
318 dfdy,
319 d2fdxdy,
320 interpolationTolerance,
321 maxTolerance,
322 false);
323 }
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339 private void testInterpolation(double minimumX,
340 double maximumX,
341 double minimumY,
342 double maximumY,
343 int numberOfElements,
344 int numberOfSamples,
345 BivariateFunction f,
346 BivariateFunction dfdx,
347 BivariateFunction dfdy,
348 BivariateFunction d2fdxdy,
349 double meanTolerance,
350 double maxTolerance,
351 boolean print) {
352 double expected;
353 double actual;
354 double currentX;
355 double currentY;
356 final double deltaX = (maximumX - minimumX) / numberOfElements;
357 final double deltaY = (maximumY - minimumY) / numberOfElements;
358 final double[] xValues = new double[numberOfElements];
359 final double[] yValues = new double[numberOfElements];
360 final double[][] zValues = new double[numberOfElements][numberOfElements];
361 final double[][] dzdx = new double[numberOfElements][numberOfElements];
362 final double[][] dzdy = new double[numberOfElements][numberOfElements];
363 final double[][] d2zdxdy = new double[numberOfElements][numberOfElements];
364
365 for (int i = 0; i < numberOfElements; i++) {
366 xValues[i] = minimumX + deltaX * i;
367 final double x = xValues[i];
368 for (int j = 0; j < numberOfElements; j++) {
369 yValues[j] = minimumY + deltaY * j;
370 final double y = yValues[j];
371 zValues[i][j] = f.value(x, y);
372 dzdx[i][j] = dfdx.value(x, y);
373 dzdy[i][j] = dfdy.value(x, y);
374 d2zdxdy[i][j] = d2fdxdy.value(x, y);
375 }
376 }
377
378 final BivariateFunction interpolation
379 = new BicubicInterpolatingFunction(xValues,
380 yValues,
381 zValues,
382 dzdx,
383 dzdy,
384 d2zdxdy);
385
386 for (int i = 0; i < numberOfElements; i++) {
387 currentX = xValues[i];
388 for (int j = 0; j < numberOfElements; j++) {
389 currentY = yValues[j];
390 expected = f.value(currentX, currentY);
391 actual = interpolation.value(currentX, currentY);
392 assertTrue(Precision.equals(expected, actual),
393 "On data point: " + expected + " != " + actual);
394 }
395 }
396
397 final RandomDataGenerator randomDataGenerator = new RandomDataGenerator(100);
398
399 double sumError = 0;
400 for (int i = 0; i < numberOfSamples; i++) {
401 currentX = randomDataGenerator.nextUniform(xValues[0], xValues[xValues.length - 1]);
402 currentY = randomDataGenerator.nextUniform(yValues[0], yValues[yValues.length - 1]);
403 expected = f.value(currentX, currentY);
404
405 if (print) {
406 System.out.println(currentX + " " + currentY + " -> ");
407 }
408
409 actual = interpolation.value(currentX, currentY);
410 sumError += FastMath.abs(actual - expected);
411
412 if (print) {
413 System.out.println(actual + " (diff=" + (expected - actual) + ")");
414 }
415
416 assertEquals(expected, actual, maxTolerance);
417 }
418
419 final double meanError = sumError / numberOfSamples;
420 assertEquals(0, meanError, meanTolerance);
421 }
422 }