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