View Javadoc
1   /*
2    * Licensed to the Hipparchus project 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 Hipparchus project 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    *      https://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.hipparchus.analysis.interpolation;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.analysis.BivariateFunction;
21  import org.hipparchus.analysis.CalculusFieldBivariateFunction;
22  import org.hipparchus.analysis.FieldBivariateFunction;
23  import org.hipparchus.random.RandomVectorGenerator;
24  import org.hipparchus.random.SobolSequenceGenerator;
25  import org.hipparchus.util.Binary64;
26  import org.hipparchus.util.Binary64Field;
27  import org.hipparchus.util.FastMath;
28  import org.junit.jupiter.api.Test;
29  
30  import static org.junit.jupiter.api.Assertions.assertEquals;
31  
32  class BilinearInterpolatorTest {
33  
34      @Test
35      void testConstant() {
36  
37          double xMin = 0.0;
38          double xMax = 7.0;
39          int    nx   = 15;
40          double[] xVal = createLinearGrid(xMin, xMax, nx);
41  
42          double yMin = -5.0;
43          double yMax = +5.0;
44          int    ny   = 11;
45          double[] yVal = createLinearGrid(yMin, yMax, ny);
46  
47          BivariateFunction f = (x, y) -> 3.5;
48          CalculusFieldBivariateFunction<Binary64> fT = (x, y) -> new Binary64(3.5);
49          BilinearInterpolatingFunction bif = createInterpolatingFunction(xVal, yVal, f);
50  
51          assertEquals(xMin, bif.getXInf(), 1.0e-15);
52          assertEquals(xMax, bif.getXSup(), 1.0e-15);
53          assertEquals(yMin, bif.getYInf(), 1.0e-15);
54          assertEquals(yMax, bif.getYSup(), 1.0e-15);
55  
56          checkInterpolationAtNodes(xVal, yVal, bif, f, fT, 1.0e-15);
57          checkInterpolationRandom(new SobolSequenceGenerator(2), xMin, xMax, yMin, yMax, bif, f, fT, 1.0e-15);
58  
59      }
60  
61      @Test
62      void testLinear() {
63  
64          double xMin = -5.0;
65          double xMax = +5.0;
66          int    nx   = 11;
67          double[] xVal = createLinearGrid(xMin, xMax, nx);
68  
69          double yMin = 0.0;
70          double yMax = 7.0;
71          int    ny   = 15;
72          double[] yVal = createLinearGrid(yMin, yMax, ny);
73  
74          BivariateFunction f = (x, y) -> 2 * x - y;
75          CalculusFieldBivariateFunction<Binary64> fT = new FieldBivariateFunction() {
76              @Override
77              public <T extends CalculusFieldElement<T>> T value(T x, T y) {
78                  return x.multiply(2).subtract(y);
79              }
80          }.toCalculusFieldBivariateFunction(Binary64Field.getInstance());
81          BilinearInterpolatingFunction bif = createInterpolatingFunction(xVal, yVal, f);
82  
83          assertEquals(xMin, bif.getXInf(), 1.0e-15);
84          assertEquals(xMax, bif.getXSup(), 1.0e-15);
85          assertEquals(yMin, bif.getYInf(), 1.0e-15);
86          assertEquals(yMax, bif.getYSup(), 1.0e-15);
87  
88          checkInterpolationAtNodes(xVal, yVal, bif, f, fT, 1.0e-15);
89          checkInterpolationRandom(new SobolSequenceGenerator(2), xMin, xMax, yMin, yMax, bif, f, fT, 1.0e-15);
90  
91      }
92  
93      @Test
94      void testQuadratic() {
95  
96          double xMin = -5.0;
97          double xMax = +5.0;
98          int    nx   = 11;
99          double[] xVal = createLinearGrid(xMin, xMax, nx);
100 
101         double yMin = 0.0;
102         double yMax = 7.0;
103         int    ny   = 15;
104         double[] yVal = createLinearGrid(yMin, yMax, ny);
105 
106         BivariateFunction f = (x, y) -> (3 * x - 2) * (6 - 0.5 * y);
107         CalculusFieldBivariateFunction<Binary64> fT = (x, y) -> x.multiply(3).subtract(2).multiply(y.multiply(-0.5).add(6));
108         BilinearInterpolatingFunction bif = createInterpolatingFunction(xVal, yVal, f);
109 
110         assertEquals(xMin, bif.getXInf(), 1.0e-15);
111         assertEquals(xMax, bif.getXSup(), 1.0e-15);
112         assertEquals(yMin, bif.getYInf(), 1.0e-15);
113         assertEquals(yMax, bif.getYSup(), 1.0e-15);
114 
115         checkInterpolationAtNodes(xVal, yVal, bif, f, fT, 1.0e-15);
116         checkInterpolationRandom(new SobolSequenceGenerator(2), xMin, xMax, yMin, yMax, bif, f, fT, 1.0e-15);
117 
118     }
119 
120     @Test
121     void testSinCos() {
122         doTestSinCos(  10,   10, 1.8e-2);
123         doTestSinCos( 100,  100, 1.5e-4);
124         doTestSinCos(1000, 1000, 1.4e-6);
125     }
126 
127     private void doTestSinCos(final int nx, final int ny, final double tol) {
128         double xMin = -1.0;
129         double xMax = +2.0;
130         double[] xVal = createLinearGrid(xMin, xMax, nx);
131 
132         double yMin = 0.0;
133         double yMax = 1.5;
134         double[] yVal = createLinearGrid(yMin, yMax, ny);
135 
136         BivariateFunction f = (x, y) -> FastMath.sin(x) * FastMath.cos(y);
137         CalculusFieldBivariateFunction<Binary64> fT = (x, y) -> FastMath.sin(x).multiply(FastMath.cos(y));
138         BilinearInterpolatingFunction bif = createInterpolatingFunction(xVal, yVal, f);
139 
140         assertEquals(xMin, bif.getXInf(), 1.0e-15);
141         assertEquals(xMax, bif.getXSup(), 1.0e-15);
142         assertEquals(yMin, bif.getYInf(), 1.0e-15);
143         assertEquals(yMax, bif.getYSup(), 1.0e-15);
144 
145         checkInterpolationAtNodes(xVal, yVal, bif, f, fT, 1.0e-15);
146         checkInterpolationRandom(new SobolSequenceGenerator(2), xMin, xMax, yMin, yMax, bif, f, fT, tol);
147 
148     }
149 
150     private double[] createLinearGrid(final double min, final double max, final int n) {
151         final double[] grid = new double[n];
152         for (int i = 0; i < n; ++i) {
153             grid[i] = ((n - 1 - i) * min + i * max) / (n - 1);
154         }
155         return grid;
156     }
157 
158     private BilinearInterpolatingFunction createInterpolatingFunction(double[] xVal, double[] yVal,
159                                                                       BivariateFunction f) {
160         final double[][] fVal = new double[xVal.length][yVal.length];
161         for (int i = 0; i < xVal.length; ++i) {
162             for (int j = 0; j < yVal.length; ++j) {
163                 fVal[i][j] = f.value(xVal[i], yVal[j]);
164             }
165         }
166         return new BilinearInterpolator().interpolate(xVal, yVal, fVal);
167     }
168 
169     private void checkInterpolationAtNodes(final double[] xVal,
170                                            final double[] yVal,
171                                            final BilinearInterpolatingFunction bif,
172                                            final BivariateFunction f,
173                                            final CalculusFieldBivariateFunction<Binary64> fT,
174                                            final double tol) {
175 
176         for (int i = 0; i < xVal.length; ++i) {
177             for (int j = 0; j < yVal.length; ++j) {
178 
179                 final double x = xVal[i];
180                 final double y = yVal[j];
181                 assertEquals(f.value(x, y), bif.value(x, y), tol);
182 
183                 final Binary64 x64 = new Binary64(x);
184                 final Binary64 y64 = new Binary64(y);
185                 assertEquals(fT.value(x64, y64).getReal(), bif.value(x64, y64).getReal(), tol);
186 
187             }
188         }
189     }
190 
191     private void checkInterpolationRandom(final RandomVectorGenerator random,
192                                           final double xMin, final double xMax,
193                                           final double yMin, final double yMax,
194                                           final BilinearInterpolatingFunction bif,
195                                           final BivariateFunction f,
196                                           final CalculusFieldBivariateFunction<Binary64> fT,
197                                           final double tol) {
198         double maxError = 0.0;
199         for (int i = 0; i < 10000; ++i) {
200 
201             final double[] v = random.nextVector();
202 
203             final double x = xMin + v[0] * (xMax - xMin);
204             final double y = yMin + v[1] * (yMax - yMin);
205             maxError = FastMath.max(maxError, FastMath.abs(f.value(x, y) - bif.value(x, y)));
206 
207             final Binary64 x64 = new Binary64(x);
208             final Binary64 y64 = new Binary64(y);
209             maxError = FastMath.max(maxError, FastMath.abs(fT.value(x64, y64).getReal()- bif.value(x64, y64).getReal()));
210         }
211 
212         assertEquals(0.0, maxError, tol);
213 
214     }
215 
216 }