1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 package org.apache.commons.math3.analysis.interpolation;
18 
19 import org.apache.commons.math3.exception.DimensionMismatchException;
20 import org.apache.commons.math3.exception.MathIllegalArgumentException;
21 import org.apache.commons.math3.util.FastMath;
22 import org.apache.commons.math3.analysis.TrivariateFunction;
23 import org.junit.Assert;
24 import org.junit.Test;
25 
26 /**
27  * Test case for the bicubic function.
28  *
29  * @deprecated To be removed in 4.0 (see MATH-1166).
30  */
31 @Deprecated
32 public final class TricubicSplineInterpolatingFunctionTest {
33     /**
34      * Test preconditions.
35      */
36     @Test
testPreconditions()37     public void testPreconditions() {
38         double[] xval = new double[] {3, 4, 5, 6.5};
39         double[] yval = new double[] {-4, -3, -1, 2.5};
40         double[] zval = new double[] {-12, -8, -5.5, -3, 0, 2.5};
41         double[][][] fval = new double[xval.length][yval.length][zval.length];
42 
43         @SuppressWarnings("unused")
44         TrivariateFunction tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
45                                                                              fval, fval, fval, fval,
46                                                                              fval, fval, fval, fval);
47 
48         double[] wxval = new double[] {3, 2, 5, 6.5};
49         try {
50             tcf = new TricubicSplineInterpolatingFunction(wxval, yval, zval,
51                                                           fval, fval, fval, fval,
52                                                           fval, fval, fval, fval);
53             Assert.fail("an exception should have been thrown");
54         } catch (MathIllegalArgumentException e) {
55             // Expected
56         }
57         double[] wyval = new double[] {-4, -1, -1, 2.5};
58         try {
59             tcf = new TricubicSplineInterpolatingFunction(xval, wyval, zval,
60                                                           fval, fval, fval, fval,
61                                                           fval, fval, fval, fval);
62             Assert.fail("an exception should have been thrown");
63         } catch (MathIllegalArgumentException e) {
64             // Expected
65         }
66         double[] wzval = new double[] {-12, -8, -9, -3, 0, 2.5};
67         try {
68             tcf = new TricubicSplineInterpolatingFunction(xval, yval, wzval,
69                                                           fval, fval, fval, fval,
70                                                           fval, fval, fval, fval);
71             Assert.fail("an exception should have been thrown");
72         } catch (MathIllegalArgumentException e) {
73             // Expected
74         }
75         double[][][] wfval = new double[xval.length - 1][yval.length - 1][zval.length];
76         try {
77             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
78                                                           wfval, fval, fval, fval,
79                                                           fval, fval, fval, fval);
80             Assert.fail("an exception should have been thrown");
81         } catch (DimensionMismatchException e) {
82             // Expected
83         }
84         try {
85             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
86                                                           fval, wfval, fval, fval,
87                                                           fval, fval, fval, fval);
88             Assert.fail("an exception should have been thrown");
89         } catch (DimensionMismatchException e) {
90             // Expected
91         }
92         try {
93             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
94                                                           fval, fval, wfval, fval,
95                                                           fval, fval, fval, fval);
96             Assert.fail("an exception should have been thrown");
97         } catch (DimensionMismatchException e) {
98             // Expected
99         }
100         try {
101             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
102                                                           fval, fval, fval, wfval,
103                                                           fval, fval, fval, fval);
104             Assert.fail("an exception should have been thrown");
105         } catch (DimensionMismatchException e) {
106             // Expected
107         }
108         try {
109             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
110                                                           fval, fval, fval, fval,
111                                                           wfval, fval, fval, fval);
112             Assert.fail("an exception should have been thrown");
113         } catch (DimensionMismatchException e) {
114             // Expected
115         }
116         try {
117             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
118                                                           fval, fval, fval, fval,
119                                                           fval, wfval, fval, fval);
120             Assert.fail("an exception should have been thrown");
121         } catch (DimensionMismatchException e) {
122             // Expected
123         }
124         try {
125             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
126                                                           fval, fval, fval, fval,
127                                                           fval, fval, wfval, fval);
128             Assert.fail("an exception should have been thrown");
129         } catch (DimensionMismatchException e) {
130             // Expected
131         }
132         try {
133             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
134                                                           fval, fval, fval, fval,
135                                                           fval, fval, fval, wfval);
136             Assert.fail("an exception should have been thrown");
137         } catch (DimensionMismatchException e) {
138             // Expected
139         }
140         wfval = new double[xval.length][yval.length - 1][zval.length];
141         try {
142             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
143                                                           wfval, fval, fval, fval,
144                                                           fval, fval, fval, fval);
145             Assert.fail("an exception should have been thrown");
146         } catch (DimensionMismatchException e) {
147             // Expected
148         }
149         try {
150             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
151                                                           fval, wfval, fval, fval,
152                                                           fval, fval, fval, fval);
153             Assert.fail("an exception should have been thrown");
154         } catch (DimensionMismatchException e) {
155             // Expected
156         }
157         try {
158             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
159                                                           fval, fval, wfval, fval,
160                                                           fval, fval, fval, fval);
161             Assert.fail("an exception should have been thrown");
162         } catch (DimensionMismatchException e) {
163             // Expected
164         }
165         try {
166             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
167                                                           fval, fval, fval, wfval,
168                                                           fval, fval, fval, fval);
169             Assert.fail("an exception should have been thrown");
170         } catch (DimensionMismatchException e) {
171             // Expected
172         }
173         try {
174             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
175                                                           fval, fval, fval, fval,
176                                                           wfval, fval, fval, fval);
177             Assert.fail("an exception should have been thrown");
178         } catch (DimensionMismatchException e) {
179             // Expected
180         }
181         try {
182             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
183                                                           fval, fval, fval, fval,
184                                                           fval, wfval, fval, fval);
185             Assert.fail("an exception should have been thrown");
186         } catch (DimensionMismatchException e) {
187             // Expected
188         }
189         try {
190             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
191                                                           fval, fval, fval, fval,
192                                                           fval, fval, wfval, fval);
193             Assert.fail("an exception should have been thrown");
194         } catch (DimensionMismatchException e) {
195             // Expected
196         }
197         try {
198             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
199                                                           fval, fval, fval, fval,
200                                                           fval, fval, fval, wfval);
201             Assert.fail("an exception should have been thrown");
202         } catch (DimensionMismatchException e) {
203             // Expected
204         }
205         wfval = new double[xval.length][yval.length][zval.length - 1];
206         try {
207             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
208                                                           wfval, fval, fval, fval,
209                                                           fval, fval, fval, fval);
210             Assert.fail("an exception should have been thrown");
211         } catch (DimensionMismatchException e) {
212             // Expected
213         }
214         try {
215             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
216                                                           fval, wfval, fval, fval,
217                                                           fval, fval, fval, fval);
218             Assert.fail("an exception should have been thrown");
219         } catch (DimensionMismatchException e) {
220             // Expected
221         }
222         try {
223             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
224                                                           fval, fval, wfval, fval,
225                                                           fval, fval, fval, fval);
226             Assert.fail("an exception should have been thrown");
227         } catch (DimensionMismatchException e) {
228             // Expected
229         }
230         try {
231             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
232                                                           fval, fval, fval, wfval,
233                                                           fval, fval, fval, fval);
234             Assert.fail("an exception should have been thrown");
235         } catch (DimensionMismatchException e) {
236             // Expected
237         }
238         try {
239             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
240                                                           fval, fval, fval, fval,
241                                                           wfval, fval, fval, fval);
242             Assert.fail("an exception should have been thrown");
243         } catch (DimensionMismatchException e) {
244             // Expected
245         }
246         try {
247             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
248                                                           fval, fval, fval, fval,
249                                                           fval, wfval, fval, fval);
250             Assert.fail("an exception should have been thrown");
251         } catch (DimensionMismatchException e) {
252             // Expected
253         }
254         try {
255             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
256                                                           fval, fval, fval, fval,
257                                                           fval, fval, wfval, fval);
258             Assert.fail("an exception should have been thrown");
259         } catch (DimensionMismatchException e) {
260             // Expected
261         }
262         try {
263             tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
264                                                           fval, fval, fval, fval,
265                                                           fval, fval, fval, wfval);
266             Assert.fail("an exception should have been thrown");
267         } catch (DimensionMismatchException e) {
268             // Expected
269         }
270     }
271 
272     /**
273      * Test for a plane.
274      * <p>
275      *  f(x, y, z) = 2 x - 3 y - 4 z + 5
276      * </p>
277      */
278     @Test
testPlane()279     public void testPlane() {
280         double[] xval = new double[] {3, 4, 5, 6.5};
281         double[] yval = new double[] {-4, -3, -1, 2, 2.5};
282         double[] zval = new double[] {-12, -8, -5.5, -3, 0, 2.5};
283 
284         // Function values
285         TrivariateFunction f = new TrivariateFunction() {
286                 public double value(double x, double y, double z) {
287                     return 2 * x - 3 * y - 4 * z + 5;
288                 }
289             };
290 
291         double[][][] fval = new double[xval.length][yval.length][zval.length];
292 
293         for (int i = 0; i < xval.length; i++) {
294             for (int j = 0; j < yval.length; j++) {
295                 for (int k = 0; k < zval.length; k++) {
296                     fval[i][j][k] = f.value(xval[i], yval[j], zval[k]);
297                 }
298             }
299         }
300         // Partial derivatives with respect to x
301         double[][][] dFdX = new double[xval.length][yval.length][zval.length];
302         for (int i = 0; i < xval.length; i++) {
303             for (int j = 0; j < yval.length; j++) {
304                 for (int k = 0; k < zval.length; k++) {
305                     dFdX[i][j][k] = 2;
306                 }
307             }
308         }
309         // Partial derivatives with respect to y
310         double[][][] dFdY = new double[xval.length][yval.length][zval.length];
311         for (int i = 0; i < xval.length; i++) {
312             for (int j = 0; j < yval.length; j++) {
313                 for (int k = 0; k < zval.length; k++) {
314                     dFdY[i][j][k] = -3;
315                 }
316             }
317         }
318 
319         // Partial derivatives with respect to z
320         double[][][] dFdZ = new double[xval.length][yval.length][zval.length];
321         for (int i = 0; i < xval.length; i++) {
322             for (int j = 0; j < yval.length; j++) {
323                 for (int k = 0; k < zval.length; k++) {
324                     dFdZ[i][j][k] = -4;
325                 }
326             }
327         }
328         // Partial cross-derivatives
329         double[][][] d2FdXdY = new double[xval.length][yval.length][zval.length];
330         double[][][] d2FdXdZ = new double[xval.length][yval.length][zval.length];
331         double[][][] d2FdYdZ = new double[xval.length][yval.length][zval.length];
332         double[][][] d3FdXdYdZ = new double[xval.length][yval.length][zval.length];
333         for (int i = 0; i < xval.length; i++) {
334             for (int j = 0; j < yval.length; j++) {
335                 for (int k = 0; k < zval.length; k++) {
336                     d2FdXdY[i][j][k] = 0;
337                     d2FdXdZ[i][j][k] = 0;
338                     d2FdYdZ[i][j][k] = 0;
339                     d3FdXdYdZ[i][j][k] = 0;
340                 }
341             }
342         }
343 
344         TrivariateFunction tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
345                                                                              fval, dFdX, dFdY, dFdZ,
346                                                                              d2FdXdY, d2FdXdZ, d2FdYdZ,
347                                                                              d3FdXdYdZ);
348         double x, y, z;
349         double expected, result;
350 
351         x = 4;
352         y = -3;
353         z = 0;
354         expected = f.value(x, y, z);
355         result = tcf.value(x, y, z);
356         Assert.assertEquals("On sample point",
357                             expected, result, 1e-15);
358 
359         x = 4.5;
360         y = -1.5;
361         z = -4.25;
362         expected = f.value(x, y, z);
363         result = tcf.value(x, y, z);
364         Assert.assertEquals("Half-way between sample points (middle of the patch)",
365                             expected, result, 0.3);
366 
367         x = 3.5;
368         y = -3.5;
369         z = -10;
370         expected = f.value(x, y, z);
371         result = tcf.value(x, y, z);
372         Assert.assertEquals("Half-way between sample points (border of the patch)",
373                             expected, result, 0.3);
374     }
375 
376     /**
377      * Sine wave.
378      * <p>
379      *  f(x, y, z) = a cos [&omega; z - k<sub>y</sub> x - k<sub>y</sub> y]
380      * </p>
381      * with A = 0.2, &omega; = 0.5, k<sub>x</sub> = 2, k<sub>y</sub> = 1.
382      */
383     @Test
testWave()384     public void testWave() {
385         double[] xval = new double[] {3, 4, 5, 6.5};
386         double[] yval = new double[] {-4, -3, -1, 2, 2.5};
387         double[] zval = new double[] {-12, -8, -5.5, -3, 0, 4};
388 
389         final double a = 0.2;
390         final double omega = 0.5;
391         final double kx = 2;
392         final double ky = 1;
393 
394         // Function values
395         TrivariateFunction f = new TrivariateFunction() {
396                 public double value(double x, double y, double z) {
397                     return a * FastMath.cos(omega * z - kx * x - ky * y);
398                 }
399             };
400 
401         double[][][] fval = new double[xval.length][yval.length][zval.length];
402         for (int i = 0; i < xval.length; i++) {
403             for (int j = 0; j < yval.length; j++) {
404                 for (int k = 0; k < zval.length; k++) {
405                     fval[i][j][k] = f.value(xval[i], yval[j], zval[k]);
406                 }
407             }
408         }
409 
410         // Partial derivatives with respect to x
411         double[][][] dFdX = new double[xval.length][yval.length][zval.length];
412         TrivariateFunction dFdX_f = new TrivariateFunction() {
413                 public double value(double x, double y, double z) {
414                     return a * FastMath.sin(omega * z - kx * x - ky * y) * kx;
415                 }
416             };
417         for (int i = 0; i < xval.length; i++) {
418             for (int j = 0; j < yval.length; j++) {
419                 for (int k = 0; k < zval.length; k++) {
420                     dFdX[i][j][k] = dFdX_f.value(xval[i], yval[j], zval[k]);
421                 }
422             }
423         }
424 
425         // Partial derivatives with respect to y
426         double[][][] dFdY = new double[xval.length][yval.length][zval.length];
427         TrivariateFunction dFdY_f = new TrivariateFunction() {
428                 public double value(double x, double y, double z) {
429                     return a * FastMath.sin(omega * z - kx * x - ky * y) * ky;
430                 }
431             };
432         for (int i = 0; i < xval.length; i++) {
433             for (int j = 0; j < yval.length; j++) {
434                 for (int k = 0; k < zval.length; k++) {
435                     dFdY[i][j][k] = dFdY_f.value(xval[i], yval[j], zval[k]);
436                 }
437             }
438         }
439 
440         // Partial derivatives with respect to z
441         double[][][] dFdZ = new double[xval.length][yval.length][zval.length];
442         TrivariateFunction dFdZ_f = new TrivariateFunction() {
443                 public double value(double x, double y, double z) {
444                     return -a * FastMath.sin(omega * z - kx * x - ky * y) * omega;
445                 }
446             };
447         for (int i = 0; i < xval.length; i++) {
448             for (int j = 0; j < yval.length; j++) {
449                 for (int k = 0; k < zval.length; k++) {
450                     dFdZ[i][j][k] = dFdZ_f.value(xval[i], yval[j], zval[k]);
451                 }
452             }
453         }
454 
455         // Partial second derivatives w.r.t. (x, y)
456         double[][][] d2FdXdY = new double[xval.length][yval.length][zval.length];
457         TrivariateFunction d2FdXdY_f = new TrivariateFunction() {
458                 public double value(double x, double y, double z) {
459                     return -a * FastMath.cos(omega * z - kx * x - ky * y) * kx * ky;
460                 }
461             };
462         for (int i = 0; i < xval.length; i++) {
463             for (int j = 0; j < yval.length; j++) {
464                 for (int k = 0; k < zval.length; k++) {
465                     d2FdXdY[i][j][k] = d2FdXdY_f.value(xval[i], yval[j], zval[k]);
466                 }
467             }
468         }
469 
470         // Partial second derivatives w.r.t. (x, z)
471         double[][][] d2FdXdZ = new double[xval.length][yval.length][zval.length];
472         TrivariateFunction d2FdXdZ_f = new TrivariateFunction() {
473                 public double value(double x, double y, double z) {
474                     return a * FastMath.cos(omega * z - kx * x - ky * y) * kx * omega;
475                 }
476             };
477         for (int i = 0; i < xval.length; i++) {
478             for (int j = 0; j < yval.length; j++) {
479                 for (int k = 0; k < zval.length; k++) {
480                     d2FdXdZ[i][j][k] = d2FdXdZ_f.value(xval[i], yval[j], zval[k]);
481                 }
482             }
483         }
484 
485         // Partial second derivatives w.r.t. (y, z)
486         double[][][] d2FdYdZ = new double[xval.length][yval.length][zval.length];
487         TrivariateFunction d2FdYdZ_f = new TrivariateFunction() {
488                 public double value(double x, double y, double z) {
489                     return a * FastMath.cos(omega * z - kx * x - ky * y) * ky * omega;
490                 }
491             };
492         for (int i = 0; i < xval.length; i++) {
493             for (int j = 0; j < yval.length; j++) {
494                 for (int k = 0; k < zval.length; k++) {
495                     d2FdYdZ[i][j][k] = d2FdYdZ_f.value(xval[i], yval[j], zval[k]);
496                 }
497             }
498         }
499 
500         // Partial third derivatives
501         double[][][] d3FdXdYdZ = new double[xval.length][yval.length][zval.length];
502         TrivariateFunction d3FdXdYdZ_f = new TrivariateFunction() {
503                 public double value(double x, double y, double z) {
504                     return a * FastMath.sin(omega * z - kx * x - ky * y) * kx * ky * omega;
505                 }
506             };
507         for (int i = 0; i < xval.length; i++) {
508             for (int j = 0; j < yval.length; j++) {
509                 for (int k = 0; k < zval.length; k++) {
510                     d3FdXdYdZ[i][j][k] = d3FdXdYdZ_f.value(xval[i], yval[j], zval[k]);
511                 }
512             }
513         }
514 
515         TrivariateFunction tcf = new TricubicSplineInterpolatingFunction(xval, yval, zval,
516                                                                              fval, dFdX, dFdY, dFdZ,
517                                                                              d2FdXdY, d2FdXdZ, d2FdYdZ,
518                                                                              d3FdXdYdZ);
519         double x, y, z;
520         double expected, result;
521 
522         x = 4;
523         y = -3;
524         z = 0;
525         expected = f.value(x, y, z);
526         result = tcf.value(x, y, z);
527         Assert.assertEquals("On sample point",
528                             expected, result, 1e-14);
529 
530         x = 4.5;
531         y = -1.5;
532         z = -4.25;
533         expected = f.value(x, y, z);
534         result = tcf.value(x, y, z);
535         Assert.assertEquals("Half-way between sample points (middle of the patch)",
536                             expected, result, 0.1);
537 
538         x = 3.5;
539         y = -3.5;
540         z = -10;
541         expected = f.value(x, y, z);
542         result = tcf.value(x, y, z);
543         Assert.assertEquals("Half-way between sample points (border of the patch)",
544                             expected, result, 0.1);
545     }
546 }
547