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.analysis.CalculusFieldBivariateFunction;
26 import org.hipparchus.exception.MathIllegalArgumentException;
27 import org.hipparchus.exception.NullArgumentException;
28 import org.hipparchus.random.RandomDataGenerator;
29 import org.hipparchus.util.Binary64;
30 import org.hipparchus.util.FastMath;
31 import org.hipparchus.util.Precision;
32 import org.junit.jupiter.api.Test;
33
34 import static org.junit.jupiter.api.Assertions.assertEquals;
35 import static org.junit.jupiter.api.Assertions.assertFalse;
36 import static org.junit.jupiter.api.Assertions.assertTrue;
37 import static org.junit.jupiter.api.Assertions.fail;
38
39
40
41
42 final class PiecewiseBicubicSplineInterpolatingFunctionTest {
43
44
45
46 @Test
47 void testPreconditions() {
48 double[] xval = new double[] { 3, 4, 5, 6.5, 7.5 };
49 double[] yval = new double[] { -4, -3, -1, 2.5, 3.5 };
50 double[][] zval = new double[xval.length][yval.length];
51
52 @SuppressWarnings("unused")
53 PiecewiseBicubicSplineInterpolatingFunction bcf = new PiecewiseBicubicSplineInterpolatingFunction(xval, yval, zval);
54
55 try {
56 new PiecewiseBicubicSplineInterpolatingFunction(null, yval, zval);
57 fail("Failed to detect x null pointer");
58 } catch (NullArgumentException iae) {
59
60 }
61
62 try {
63 new PiecewiseBicubicSplineInterpolatingFunction(xval, null, zval);
64 fail("Failed to detect y null pointer");
65 } catch (NullArgumentException iae) {
66
67 }
68
69 try {
70 new PiecewiseBicubicSplineInterpolatingFunction(xval, yval, null);
71 fail("Failed to detect z null pointer");
72 } catch (NullArgumentException iae) {
73
74 }
75
76 try {
77 final double[][] fnull = new double[1][];
78 new PiecewiseBicubicSplineInterpolatingFunction(xval, yval, fnull);
79 fail("Failed to detect z[0] null pointer");
80 } catch (NullArgumentException iae) {
81
82 }
83
84 try {
85 final double[][] f = new double[1][1];
86 new PiecewiseBicubicSplineInterpolatingFunction(new double[0], yval, f);
87 fail("Failed to detect empty x pointer");
88 } catch (MathIllegalArgumentException iae) {
89
90 }
91
92 try {
93 final double[][] f = new double[1][1];
94 new PiecewiseBicubicSplineInterpolatingFunction(xval, new double[0], f);
95 fail("Failed to detect empty y pointer");
96 } catch (MathIllegalArgumentException iae) {
97
98 }
99
100
101 try {
102 final double[][] f = new double[1][0];
103 new PiecewiseBicubicSplineInterpolatingFunction(xval, yval, f);
104 fail("Failed to detect empty z[0] pointer");
105 } catch (MathIllegalArgumentException iae) {
106
107 }
108
109 try {
110 final double[] xval1 = { 0.0, 1.0, 2.0, 3.0 };
111 new PiecewiseBicubicSplineInterpolatingFunction(xval1, yval, zval);
112 fail("Failed to detect insufficient x data");
113 } catch (MathIllegalArgumentException iae) {
114
115 }
116
117 try {
118 final double[] yval1 = { 0.0, 1.0, 2.0, 3.0 };
119 new PiecewiseBicubicSplineInterpolatingFunction(xval, yval1, zval);
120 fail("Failed to detect insufficient y data");
121 } catch (MathIllegalArgumentException iae) {
122
123 }
124
125 try {
126 final double[][] zval1 = new double[4][4];
127 new PiecewiseBicubicSplineInterpolatingFunction(xval, yval, zval1);
128 fail("Failed to detect insufficient z data");
129 } catch (MathIllegalArgumentException iae) {
130
131 }
132
133 try {
134 final double[][] zval1 = new double[5][4];
135 new PiecewiseBicubicSplineInterpolatingFunction(xval, yval, zval1);
136 fail("Failed to detect insufficient z data");
137 } catch (MathIllegalArgumentException iae) {
138
139 }
140
141 try {
142 final double[] xval1 = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
143 new PiecewiseBicubicSplineInterpolatingFunction(xval1, yval, zval);
144 fail("Failed to detect data set array with different sizes.");
145 } catch (MathIllegalArgumentException iae) {
146
147 }
148
149 try {
150 final double[] yval1 = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
151 new PiecewiseBicubicSplineInterpolatingFunction(xval, yval1, zval);
152 fail("Failed to detect data set array with different sizes.");
153 } catch (MathIllegalArgumentException iae) {
154
155 }
156
157
158 try {
159 final double[] xval1 = { 0.0, 1.0, 0.5, 7.0, 3.5 };
160 new PiecewiseBicubicSplineInterpolatingFunction(xval1, yval, zval);
161 fail("Failed to detect unsorted x arguments.");
162 } catch (MathIllegalArgumentException iae) {
163
164 }
165
166
167 try {
168 final double[] yval1 = { 0.0, 1.0, 1.5, 0.0, 3.0 };
169 new PiecewiseBicubicSplineInterpolatingFunction(xval, yval1, zval);
170 fail("Failed to detect unsorted y arguments.");
171 } catch (MathIllegalArgumentException iae) {
172
173 }
174 }
175
176
177
178
179
180
181 @Test
182 void testPlane() {
183 final int numberOfElements = 10;
184 final double minimumX = -10;
185 final double maximumX = 10;
186 final double minimumY = -10;
187 final double maximumY = 10;
188 final int numberOfSamples = 100;
189
190 final double interpolationTolerance = 7e-15;
191 final double maxTolerance = 6e-14;
192
193
194 BivariateFunction f = (x, y) -> 2 * x - 3 * y + 5;
195 CalculusFieldBivariateFunction<Binary64> fT = (x, y) -> x.multiply(2).subtract(y.multiply(3)).add(5);
196
197 testInterpolation(minimumX,
198 maximumX,
199 minimumY,
200 maximumY,
201 numberOfElements,
202 numberOfSamples,
203 f, fT,
204 interpolationTolerance,
205 maxTolerance);
206 }
207
208
209
210
211
212
213 @Test
214 void testParabaloid() {
215 final int numberOfElements = 10;
216 final double minimumX = -10;
217 final double maximumX = 10;
218 final double minimumY = -10;
219 final double maximumY = 10;
220 final int numberOfSamples = 100;
221
222 final double interpolationTolerance = 2e-14;
223 final double maxTolerance = 6e-14;
224
225
226 BivariateFunction f = (x, y) -> 2 * x * x - 3 * y * y + 4 * x * y - 5;
227 CalculusFieldBivariateFunction<Binary64> fT = (x, y) -> x.square().multiply(2).
228 subtract(y.square().multiply(3)).
229 add(x.multiply(y).multiply(4)).
230 subtract(5);
231
232 testInterpolation(minimumX,
233 maximumX,
234 minimumY,
235 maximumY,
236 numberOfElements,
237 numberOfSamples,
238 f, fT,
239 interpolationTolerance,
240 maxTolerance);
241 }
242
243
244
245
246
247
248
249
250
251
252
253
254
255 private void testInterpolation(double minimumX,
256 double maximumX,
257 double minimumY,
258 double maximumY,
259 int numberOfElements,
260 int numberOfSamples,
261 BivariateFunction f,
262 final CalculusFieldBivariateFunction<Binary64> fT,
263 double meanTolerance,
264 double maxTolerance) {
265 double expected;
266 double actual;
267 Binary64 expected64;
268 Binary64 actual64;
269 double currentX;
270 double currentY;
271 Binary64 currentX64;
272 Binary64 currentY64;
273 final double deltaX = (maximumX - minimumX) / ((double) numberOfElements);
274 final double deltaY = (maximumY - minimumY) / ((double) numberOfElements);
275 final double[] xValues = new double[numberOfElements];
276 final double[] yValues = new double[numberOfElements];
277 final double[][] zValues = new double[numberOfElements][numberOfElements];
278
279 for (int i = 0; i < numberOfElements; i++) {
280 xValues[i] = minimumX + deltaX * (double) i;
281 for (int j = 0; j < numberOfElements; j++) {
282 yValues[j] = minimumY + deltaY * (double) j;
283 zValues[i][j] = f.value(xValues[i], yValues[j]);
284 }
285 }
286
287 final PiecewiseBicubicSplineInterpolatingFunction interpolation
288 = new PiecewiseBicubicSplineInterpolatingFunction(xValues,
289 yValues,
290 zValues);
291
292 for (int i = 0; i < numberOfElements; i++) {
293 currentX = xValues[i];
294 currentX64 = new Binary64(currentX);
295 for (int j = 0; j < numberOfElements; j++) {
296 currentY = yValues[j];
297 currentY64 = new Binary64(currentY);
298 assertTrue(Precision.equals(f.value(currentX, currentY),
299 interpolation.value(currentX, currentY)));
300 assertTrue(Precision.equals(fT.value(currentX64, currentY64).getReal(),
301 interpolation.value(currentX64, currentY64).getReal()));
302 }
303 }
304
305 final RandomDataGenerator gen = new RandomDataGenerator(1234567L);
306
307 double sumError = 0;
308 double sumError64 = 0;
309 for (int i = 0; i < numberOfSamples; i++) {
310 currentX = gen.nextUniform(xValues[0], xValues[xValues.length - 1]);
311 currentY = gen.nextUniform(yValues[0], yValues[yValues.length - 1]);
312 currentX64 = new Binary64(currentX);
313 currentY64 = new Binary64(currentY);
314 expected = f.value(currentX, currentY);
315 actual = interpolation.value(currentX, currentY);
316 expected64 = fT.value(currentX64, currentY64);
317 actual64 = interpolation.value(currentX64, currentY64);
318 sumError += FastMath.abs(actual - expected);
319 sumError64 += FastMath.abs(actual64.subtract(expected64)).getReal();
320 assertEquals(expected, actual, maxTolerance);
321 assertEquals(expected64.getReal(), actual64.getReal(), maxTolerance);
322 }
323
324 final double meanError = sumError / numberOfSamples;
325 assertEquals(0, meanError, meanTolerance);
326 final double meanError64 = sumError64 / numberOfSamples;
327 assertEquals(0, meanError64, meanTolerance);
328
329 }
330
331 @Test
332 void testIsValidPoint() {
333
334 final double[] x = new double[] { 0., 1., 2., 3., 4. };
335 final double[] y = x.clone();
336 final PiecewiseBicubicSplineInterpolatingFunction interpolatingFunction =
337 new PiecewiseBicubicSplineInterpolatingFunction(x, y, new double[x.length][y.length]);
338
339 assertFalse(interpolatingFunction.isValidPoint(x[0] - 1, y[0]));
340 assertFalse(interpolatingFunction.isValidPoint(x[x.length - 1] + 1, y[0]));
341 assertFalse(interpolatingFunction.isValidPoint(x[0], y[0] - 1));
342 assertFalse(interpolatingFunction.isValidPoint(x[0], y[y.length - 1] + 1));
343 }
344
345 }