1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 }