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