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.MultivariateFunction;
25 import org.hipparchus.exception.LocalizedCoreFormats;
26 import org.hipparchus.exception.MathIllegalArgumentException;
27 import org.hipparchus.exception.MathIllegalStateException;
28 import org.hipparchus.random.RandomGenerator;
29 import org.hipparchus.random.UnitSphereRandomVectorGenerator;
30 import org.hipparchus.random.Well1024a;
31 import org.hipparchus.random.Well19937a;
32 import org.hipparchus.util.FastMath;
33 import org.junit.jupiter.api.Test;
34
35 import java.lang.reflect.InvocationTargetException;
36 import java.lang.reflect.Method;
37
38 import static org.junit.jupiter.api.Assertions.assertEquals;
39 import static org.junit.jupiter.api.Assertions.assertFalse;
40 import static org.junit.jupiter.api.Assertions.assertTrue;
41 import static org.junit.jupiter.api.Assertions.fail;
42
43
44
45
46
47 final class MicrosphereProjectionInterpolatorTest {
48
49
50
51
52
53 @Test
54 void testLinearFunction2D() {
55 MultivariateFunction f = new MultivariateFunction() {
56 @Override
57 public double value(double[] x) {
58 if (x.length != 2) {
59 throw new IllegalArgumentException();
60 }
61 return 2 * x[0] - 3 * x[1] + 5;
62 }
63 };
64
65 final double darkFraction = 0.5;
66 final double darkThreshold = 1e-2;
67 final double background = Double.NaN;
68 final double exponent = 1.1;
69 final boolean shareSphere = true;
70 final double noInterpolationTolerance = Math.ulp(1d);
71 final RandomGenerator random = new Well1024a(0x1c7a150c83a6d9dal);
72
73
74 final MultivariateInterpolator interpolator
75 = new MicrosphereProjectionInterpolator(new InterpolatingMicrosphere(2, 500,
76 darkFraction,
77 darkThreshold,
78 background,
79 new UnitSphereRandomVectorGenerator(2, random)),
80 exponent,
81 shareSphere,
82 noInterpolationTolerance);
83
84
85 final MultivariateInterpolator interpolator2D
86 = new MicrosphereProjectionInterpolator(new InterpolatingMicrosphere2D(16,
87 darkFraction,
88 darkThreshold,
89 background),
90 exponent,
91 shareSphere,
92 noInterpolationTolerance);
93
94 final double min = -1;
95 final double max = 1;
96 final double range = max - min;
97 final int res = 5;
98 final int n = res * res;
99 final int dim = 2;
100 double[][] x = new double[n][dim];
101 double[] y = new double[n];
102 int index = 0;
103 for (int i = 0; i < res; i++) {
104 final double x1Val = toCoordinate(min, range, res, i);
105 for (int j = 0; j < res; j++) {
106 final double x2Val = toCoordinate(min, range, res, j);
107 x[index][0] = x1Val;
108 x[index][1] = x2Val;
109 y[index] = f.value(x[index]);
110 ++index;
111 }
112 }
113
114 final MultivariateFunction p = interpolator.interpolate(x, y);
115 final MultivariateFunction p2D = interpolator2D.interpolate(x, y);
116
117 double[] c = new double[dim];
118 double expected, result, result2D;
119
120 final int sampleIndex = 2;
121 c[0] = x[sampleIndex][0];
122 c[1] = x[sampleIndex][1];
123 expected = f.value(c);
124 result = p.value(c);
125 result2D = p2D.value(c);
126 assertEquals(expected, result2D, FastMath.ulp(1d), "on sample point (exact)");
127 assertEquals(result2D, result, FastMath.ulp(1d), "on sample point (ND vs 2D)");
128
129
130 c[0] = 0.654321;
131 c[1] = -0.345678;
132 expected = f.value(c);
133 result = p.value(c);
134 result2D = p2D.value(c);
135 assertEquals(expected, result2D, 1e-1, "interpolation (exact)");
136 assertEquals(result2D, result, 1e-1, "interpolation (ND vs 2D)");
137
138
139 c[0] = 0 - 1e-2;
140 c[1] = 1 + 1e-2;
141 expected = f.value(c);
142 result = p.value(c);
143 result2D = p2D.value(c);
144 assertFalse(Double.isNaN(result));
145 assertFalse(Double.isNaN(result2D));
146 assertEquals(expected, result2D, 1e-1, "extrapolation (exact)");
147 assertEquals(result2D, result, 1e-2, "extrapolation (ND vs 2D)");
148
149
150 c[0] = 20;
151 c[1] = -30;
152 result = p.value(c);
153 assertTrue(Double.isNaN(result), result + " should be NaN");
154 result2D = p2D.value(c);
155 assertTrue(Double.isNaN(result2D), result2D + " should be NaN");
156 }
157
158 @Test
159 void testWrongDimensions() {
160 checkWrongArguments(0, 1, 0.5, 0.0, 0.0,
161 LocalizedCoreFormats.NUMBER_TOO_SMALL_BOUND_EXCLUDED);
162 checkWrongArguments(1, 0, 0.5, 0.0, 0.0,
163 LocalizedCoreFormats.NUMBER_TOO_SMALL_BOUND_EXCLUDED);
164 checkWrongArguments(1, 1, 0.5, -1.0, 0.0,
165 LocalizedCoreFormats.NUMBER_TOO_SMALL);
166 }
167
168 private void checkWrongArguments(int dimension,
169 int size,
170 double maxDarkFraction,
171 double darkThreshold,
172 double background,
173 LocalizedCoreFormats expected) {
174 try {
175 new InterpolatingMicrosphere(dimension, size, maxDarkFraction, darkThreshold, background, null);
176 fail("an exception should have been thrown");
177 } catch (MathIllegalArgumentException miae) {
178 assertEquals(expected, miae.getSpecifier());
179 }
180 }
181
182 @Test
183 void testCopy() {
184 UnitSphereRandomVectorGenerator random =
185 new UnitSphereRandomVectorGenerator(3, new Well19937a(0x265318ael));
186 InterpolatingMicrosphere original = new InterpolatingMicrosphere(3, 30, 0.5, 0.2, 0.0, random);
187 InterpolatingMicrosphere copy = original.copy();
188 assertFalse(original == copy);
189 assertEquals(original.getDimension(), copy.getDimension());
190 assertEquals(original.getSize(), copy.getSize());
191 }
192
193 @Test
194 void testSizeLimit() {
195 UnitSphereRandomVectorGenerator random =
196 new UnitSphereRandomVectorGenerator(3, new Well19937a(0x453l));
197 InterpolatingMicrosphere ims = new InterpolatingMicrosphere(3, 30, 0.5, 0.2, 0.0, random);
198 try {
199 Method add = InterpolatingMicrosphere.class.getDeclaredMethod("add", double[].class, Boolean.TYPE);
200 add.setAccessible(true);
201 try {
202 add.invoke(ims, random.nextVector(), true);
203 fail("an exception should have been thrown");
204 } catch (InvocationTargetException ite) {
205 MathIllegalStateException miae = (MathIllegalStateException) ite.getCause();
206 assertEquals(LocalizedCoreFormats.MAX_COUNT_EXCEEDED, miae.getSpecifier());
207 }
208 } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException e) {
209 fail(e.getLocalizedMessage());
210 }
211 }
212
213 @Test
214 void testInconsistentDimensions() {
215 final int d1 = 5;
216 final int d2 = 3;
217 try {
218 UnitSphereRandomVectorGenerator random =
219 new UnitSphereRandomVectorGenerator(d1, new Well19937a(0x1l));
220 new InterpolatingMicrosphere(d2, 30, 0.5, 0.2, 0.0, random);
221 fail("an exception should have been thrown");
222 } catch (MathIllegalArgumentException miae) {
223 assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
224 assertEquals(d1, ((Integer) miae.getParts()[0]).intValue());
225 assertEquals(d2, ((Integer) miae.getParts()[1]).intValue());
226 }
227 }
228
229
230
231
232
233
234
235 private static double toCoordinate(double min,
236 double range,
237 int res,
238 int pixel) {
239 return pixel * range / (res - 1) + min;
240 }
241 }