1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  package org.apache.commons.math4.legacy.analysis.interpolation;
18  
19  import org.apache.commons.math4.legacy.analysis.BivariateFunction;
20  import org.apache.commons.statistics.distribution.ContinuousDistribution;
21  import org.apache.commons.statistics.distribution.UniformContinuousDistribution;
22  import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
23  import org.apache.commons.math4.legacy.exception.InsufficientDataException;
24  import org.apache.commons.math4.legacy.exception.NonMonotonicSequenceException;
25  import org.apache.commons.math4.legacy.exception.NullArgumentException;
26  import org.apache.commons.rng.UniformRandomProvider;
27  import org.apache.commons.rng.simple.RandomSource;
28  import org.apache.commons.math4.core.jdkmath.JdkMath;
29  import org.apache.commons.numbers.core.Precision;
30  import org.junit.Assert;
31  import org.junit.Test;
32  
33  
34  
35  
36  public final class PiecewiseBicubicSplineInterpolatingFunctionTest {
37      
38  
39  
40      @Test
41      public void testPreconditions() {
42          double[] xval = new double[] { 3, 4, 5, 6.5, 7.5 };
43          double[] yval = new double[] { -4, -3, -1, 2.5, 3.5 };
44          double[][] zval = new double[xval.length][yval.length];
45  
46          @SuppressWarnings("unused")
47          PiecewiseBicubicSplineInterpolatingFunction bcf = new PiecewiseBicubicSplineInterpolatingFunction(xval, yval, zval);
48  
49          try {
50              bcf = new PiecewiseBicubicSplineInterpolatingFunction(null, yval, zval);
51              Assert.fail("Failed to detect x null pointer");
52          } catch (NullArgumentException iae) {
53              
54          }
55  
56          try {
57              bcf = new PiecewiseBicubicSplineInterpolatingFunction(xval, null, zval);
58              Assert.fail("Failed to detect y null pointer");
59          } catch (NullArgumentException iae) {
60              
61          }
62  
63          try {
64              bcf = new PiecewiseBicubicSplineInterpolatingFunction(xval, yval, null);
65              Assert.fail("Failed to detect z null pointer");
66          } catch (NullArgumentException iae) {
67              
68          }
69  
70          try {
71              double xval1[] = { 0.0, 1.0, 2.0, 3.0 };
72              bcf = new PiecewiseBicubicSplineInterpolatingFunction(xval1, yval, zval);
73              Assert.fail("Failed to detect insufficient x data");
74          } catch (InsufficientDataException iae) {
75              
76          }
77  
78          try {
79              double yval1[] = { 0.0, 1.0, 2.0, 3.0 };
80              bcf = new PiecewiseBicubicSplineInterpolatingFunction(xval, yval1, zval);
81              Assert.fail("Failed to detect insufficient y data");
82          } catch (InsufficientDataException iae) {
83              
84          }
85  
86          try {
87              double zval1[][] = new double[4][4];
88              bcf = new PiecewiseBicubicSplineInterpolatingFunction(xval, yval, zval1);
89              Assert.fail("Failed to detect insufficient z data");
90          } catch (InsufficientDataException iae) {
91              
92          }
93  
94          try {
95              double xval1[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
96              bcf = new PiecewiseBicubicSplineInterpolatingFunction(xval1, yval, zval);
97              Assert.fail("Failed to detect data set array with different sizes.");
98          } catch (DimensionMismatchException iae) {
99              
100         }
101 
102         try {
103             double yval1[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
104             bcf = new PiecewiseBicubicSplineInterpolatingFunction(xval, yval1, zval);
105             Assert.fail("Failed to detect data set array with different sizes.");
106         } catch (DimensionMismatchException iae) {
107             
108         }
109 
110         
111         try {
112             double xval1[] = { 0.0, 1.0, 0.5, 7.0, 3.5 };
113             bcf = new PiecewiseBicubicSplineInterpolatingFunction(xval1, yval, zval);
114             Assert.fail("Failed to detect unsorted x arguments.");
115         } catch (NonMonotonicSequenceException iae) {
116             
117         }
118 
119         
120         try {
121             double yval1[] = { 0.0, 1.0, 1.5, 0.0, 3.0 };
122             bcf = new PiecewiseBicubicSplineInterpolatingFunction(xval, yval1, zval);
123             Assert.fail("Failed to detect unsorted y arguments.");
124         } catch (NonMonotonicSequenceException iae) {
125             
126         }
127     }
128 
129     
130 
131 
132 
133 
134     @Test
135     public void testPlane() {
136         final int numberOfElements = 10;
137         final double minimumX = -10;
138         final double maximumX = 10;
139         final double minimumY = -10;
140         final double maximumY = 10;
141         final int numberOfSamples = 100;
142 
143         final double interpolationTolerance = 7e-15;
144         final double maxTolerance = 6e-14;
145 
146         
147         BivariateFunction f = new BivariateFunction() {
148                 @Override
149                 public double value(double x, double y) {
150                     return 2 * x - 3 * y + 5;
151                 }
152             };
153 
154         testInterpolation(minimumX,
155                           maximumX,
156                           minimumY,
157                           maximumY,
158                           numberOfElements,
159                           numberOfSamples,
160                           f,
161                           interpolationTolerance,
162                           maxTolerance);
163     }
164 
165     
166 
167 
168 
169 
170     @Test
171     public void testParabaloid() {
172         final int numberOfElements = 10;
173         final double minimumX = -10;
174         final double maximumX = 10;
175         final double minimumY = -10;
176         final double maximumY = 10;
177         final int numberOfSamples = 100;
178 
179         final double interpolationTolerance = 1e-13;
180         final double maxTolerance = 6e-14;
181 
182         
183         BivariateFunction f = new BivariateFunction() {
184                 @Override
185                 public double value(double x, double y) {
186                     return 2 * x * x - 3 * y * y + 4 * x * y - 5;
187                 }
188             };
189 
190         testInterpolation(minimumX,
191                           maximumX,
192                           minimumY,
193                           maximumY,
194                           numberOfElements,
195                           numberOfSamples,
196                           f,
197                           interpolationTolerance,
198                           maxTolerance);
199     }
200 
201     
202 
203 
204 
205 
206 
207 
208 
209 
210 
211 
212     private void testInterpolation(double minimumX,
213                                    double maximumX,
214                                    double minimumY,
215                                    double maximumY,
216                                    int numberOfElements,
217                                    int numberOfSamples,
218                                    BivariateFunction f,
219                                    double meanTolerance,
220                                    double maxTolerance) {
221         double expected;
222         double actual;
223         double currentX;
224         double currentY;
225         final double deltaX = (maximumX - minimumX) / ((double) numberOfElements);
226         final double deltaY = (maximumY - minimumY) / ((double) numberOfElements);
227         final double[] xValues = new double[numberOfElements];
228         final double[] yValues = new double[numberOfElements];
229         final double[][] zValues = new double[numberOfElements][numberOfElements];
230 
231         for (int i = 0; i < numberOfElements; i++) {
232             xValues[i] = minimumX + deltaX * (double) i;
233             for (int j = 0; j < numberOfElements; j++) {
234                 yValues[j] = minimumY + deltaY * (double) j;
235                 zValues[i][j] = f.value(xValues[i], yValues[j]);
236             }
237         }
238 
239         final BivariateFunction interpolation
240             = new PiecewiseBicubicSplineInterpolatingFunction(xValues,
241                                                               yValues,
242                                                               zValues);
243 
244         for (int i = 0; i < numberOfElements; i++) {
245             currentX = xValues[i];
246             for (int j = 0; j < numberOfElements; j++) {
247                 currentY = yValues[j];
248                 expected = f.value(currentX, currentY);
249                 actual = interpolation.value(currentX, currentY);
250                 Assert.assertTrue(Precision.equals(expected, actual));
251             }
252         }
253 
254         final UniformRandomProvider rng = RandomSource.WELL_19937_C.create(1234567L);
255         final ContinuousDistribution.Sampler distX = UniformContinuousDistribution.of(xValues[0], xValues[xValues.length - 1]).createSampler(rng);
256         final ContinuousDistribution.Sampler distY = UniformContinuousDistribution.of(yValues[0], yValues[yValues.length - 1]).createSampler(rng);
257 
258         double sumError = 0;
259         for (int i = 0; i < numberOfSamples; i++) {
260             currentX = distX.sample();
261             currentY = distY.sample();
262             expected = f.value(currentX, currentY);
263             actual = interpolation.value(currentX, currentY);
264             sumError += JdkMath.abs(actual - expected);
265             Assert.assertEquals(expected, actual, maxTolerance);
266         }
267 
268         final double meanError = sumError / numberOfSamples;
269         Assert.assertEquals(0, meanError, meanTolerance);
270     }
271 }