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 static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertTrue;
21
22 import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
23 import org.apache.commons.statistics.distribution.ContinuousDistribution;
24 import org.apache.commons.statistics.distribution.UniformContinuousDistribution;
25 import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
26 import org.apache.commons.math4.legacy.exception.NonMonotonicSequenceException;
27 import org.apache.commons.math4.legacy.exception.NullArgumentException;
28 import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
29 import org.apache.commons.math4.legacy.analysis.polynomials.PolynomialSplineFunction;
30 import org.apache.commons.rng.UniformRandomProvider;
31 import org.apache.commons.rng.simple.RandomSource;
32 import org.apache.commons.math4.core.jdkmath.JdkMath;
33 import org.apache.commons.numbers.core.Precision;
34 import org.junit.Assert;
35 import org.junit.Test;
36 import org.junit.Ignore;
37
38 public class AkimaSplineInterpolatorTest {
39 @Test
40 public void testIllegalArguments() {
41
42 UnivariateInterpolator i = new AkimaSplineInterpolator();
43
44 try {
45 double yval[] = {0.0, 1.0, 2.0, 3.0, 4.0};
46 i.interpolate(null, yval);
47 Assert.fail("Failed to detect x null pointer");
48 } catch (NullArgumentException iae) {
49
50 }
51
52 try {
53 double xval[] = {0.0, 1.0, 2.0, 3.0, 4.0};
54 i.interpolate(xval, null);
55 Assert.fail("Failed to detect y null pointer");
56 } catch (NullArgumentException iae) {
57
58 }
59
60 try {
61 double xval[] = {0.0, 1.0, 2.0, 3.0};
62 double yval[] = {0.0, 1.0, 2.0, 3.0};
63 i.interpolate(xval, yval);
64 Assert.fail("Failed to detect insufficient data");
65 } catch (NumberIsTooSmallException iae) {
66
67 }
68
69 try {
70 double xval[] = {0.0, 1.0, 2.0, 3.0, 4.0};
71 double yval[] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0};
72 i.interpolate(xval, yval);
73 Assert.fail("Failed to detect data set array with different sizes.");
74 } catch (DimensionMismatchException iae) {
75
76 }
77
78
79 try {
80 double xval[] = {0.0, 1.0, 0.5, 7.0, 3.5, 2.2, 8.0};
81 double yval[] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
82 i.interpolate(xval, yval);
83 Assert.fail("Failed to detect unsorted arguments.");
84 } catch (NonMonotonicSequenceException iae) {
85
86 }
87 }
88
89
90
91
92
93
94 @Test
95 public void testInterpolateLine() {
96 final int numberOfElements = 10;
97 final double minimumX = -10;
98 final double maximumX = 10;
99 final int numberOfSamples = 100;
100 final double interpolationTolerance = 1e-15;
101 final double maxTolerance = 1e-15;
102
103 UnivariateFunction f = new UnivariateFunction() {
104 @Override
105 public double value(double x) {
106 return 2 * x - 5;
107 }
108 };
109
110 testInterpolation( minimumX, maximumX, numberOfElements, numberOfSamples, f, interpolationTolerance,
111 maxTolerance );
112 }
113
114
115
116
117
118
119
120 @Test
121 public void testInterpolateParabola() {
122 final int numberOfElements = 10;
123 final double minimumX = -10;
124 final double maximumX = 10;
125 final int numberOfSamples = 100;
126 final double interpolationTolerance = 7e-15;
127 final double maxTolerance = 6e-14;
128
129 UnivariateFunction f = new UnivariateFunction() {
130 @Override
131 public double value(double x) {
132 return (3 * x * x) - (5 * x) + 7;
133 }
134 };
135
136 testInterpolation( minimumX, maximumX, numberOfElements, numberOfSamples, f, interpolationTolerance,
137 maxTolerance );
138 }
139
140
141
142
143
144
145 @Test
146 public void testInterpolateCubic() {
147 final int numberOfElements = 10;
148 final double minimumX = -3;
149 final double maximumX = 3;
150 final int numberOfSamples = 100;
151 final double interpolationTolerance = 0.37;
152 final double maxTolerance = 3.8;
153
154 UnivariateFunction f = new UnivariateFunction() {
155 @Override
156 public double value(double x) {
157 return (3 * x * x * x) - (0.5 * x * x) + (1 * x) - 1;
158 }
159 };
160
161 testInterpolation( minimumX, maximumX, numberOfElements, numberOfSamples, f, interpolationTolerance,
162 maxTolerance );
163 }
164
165
166
167
168 @Ignore
169 @Test
170 public void testMath1635() {
171 final double[] x = {
172 5994, 6005, 6555, 6588, 6663,
173 6760, 6770, 6792, 6856, 6964,
174 7028, 7233, 7426, 7469, 7619,
175 7910, 8038, 8178, 8414, 8747,
176 8983, 9316, 9864, 9875
177 };
178
179 final double[] y = {
180 3.0, 2.0, 2.0, 2.0, 2.0,
181 2.0, 2.0, 2.0, 2.0, 2.0,
182 2.0, 2.0, 2.0, 2.0, 2.0,
183 2.0, 2.0, 2.0, 2.0, 2.0,
184 2.0, 2.0, 2.0, 3.0
185 };
186
187 final AkimaSplineInterpolator interpolator = new AkimaSplineInterpolator(true);
188 final PolynomialSplineFunction interpolate = interpolator.interpolate(x, y);
189 final double value = interpolate.value(9584);
190 final double expected = 2;
191 Assert.assertEquals(expected, value, 1e-4);
192 }
193
194 @Test
195 public void testOriginalVsModified() {
196 final UnivariateFunction f = new UnivariateFunction() {
197 @Override
198 public double value(double x) {
199 return x < -1 ? -1 :
200 x < 1 ? x : 1;
201 }
202 };
203
204 final double[] xS = new double[] {-1, 0, 1, 2, 3 };
205 final double[] yS = new double[xS.length];
206
207 for (int i = 0; i < xS.length; i++) {
208 yS[i] = f.value(xS[i]);
209 }
210
211 final UnivariateFunction iOriginal = new AkimaSplineInterpolator(false).interpolate(xS, yS);
212 final UnivariateFunction iModified = new AkimaSplineInterpolator(true).interpolate(xS, yS);
213
214 final int n = 100;
215 final double delta = 1d / n;
216 for (int i = 1; i < n - 1; i++) {
217 final double x = 2 - i * delta;
218
219 final double value = f.value(x);
220 final double diffOriginal = Math.abs(iOriginal.value(x) - value);
221 final double diffModified = Math.abs(iModified.value(x) - value);
222
223
224 Assert.assertTrue(diffOriginal > 0);
225 Assert.assertEquals(0d, diffModified, 0d);
226 }
227 }
228
229 private void testInterpolation( double minimumX, double maximumX, int numberOfElements, int numberOfSamples,
230 UnivariateFunction f, double tolerance, double maxTolerance ) {
231 double expected;
232 double actual;
233 double currentX;
234 final double delta = ( maximumX - minimumX ) / ( (double) numberOfElements );
235 double xValues[] = new double[numberOfElements];
236 double yValues[] = new double[numberOfElements];
237
238 for (int i = 0; i < numberOfElements; i++) {
239 xValues[i] = minimumX + delta * (double) i;
240 yValues[i] = f.value(xValues[i]);
241 }
242
243 UnivariateFunction interpolation = new AkimaSplineInterpolator().interpolate( xValues, yValues );
244
245 for (int i = 0; i < numberOfElements; i++) {
246 currentX = xValues[i];
247 expected = f.value(currentX);
248 actual = interpolation.value( currentX );
249 assertTrue( Precision.equals( expected, actual ) );
250 }
251
252 final UniformRandomProvider rng = RandomSource.WELL_19937_C.create(1234567L);
253 final ContinuousDistribution.Sampler distX =
254 UniformContinuousDistribution.of(xValues[0], xValues[xValues.length - 1]).createSampler(rng);
255
256 double sumError = 0;
257 for (int i = 0; i < numberOfSamples; i++) {
258 currentX = distX.sample();
259 expected = f.value(currentX);
260 actual = interpolation.value( currentX );
261 sumError += JdkMath.abs( actual - expected );
262 assertEquals( expected, actual, maxTolerance );
263 }
264
265 assertEquals( 0.0, sumError / (double) numberOfSamples, tolerance );
266 }
267 }