View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) 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 ASF 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  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.analysis.interpolation;
23  
24  import org.hipparchus.CalculusFieldElement;
25  import org.hipparchus.UnitTestUtils;
26  import org.hipparchus.analysis.CalculusFieldUnivariateFunction;
27  import org.hipparchus.analysis.UnivariateFunction;
28  import org.hipparchus.analysis.polynomials.FieldPolynomialFunction;
29  import org.hipparchus.analysis.polynomials.FieldPolynomialSplineFunction;
30  import org.hipparchus.analysis.polynomials.PolynomialFunction;
31  import org.hipparchus.analysis.polynomials.PolynomialSplineFunction;
32  import org.hipparchus.exception.MathIllegalArgumentException;
33  import org.hipparchus.exception.NullArgumentException;
34  import org.hipparchus.util.Binary64;
35  import org.junit.jupiter.api.Test;
36  
37  import static org.junit.jupiter.api.Assertions.assertEquals;
38  import static org.junit.jupiter.api.Assertions.fail;
39  
40  /**
41   * Base test for interpolators.
42   */
43  public abstract class UnivariateInterpolatorAbstractTest {
44  
45      /** error tolerance for spline interpolator value at knot points */
46      protected double knotTolerance = 1E-12;
47  
48      /** error tolerance for interpolating polynomial coefficients */
49      protected double coefficientTolerance = 1E-6;
50  
51      /** error tolerance for interpolated values */
52      protected double interpolationTolerance = 1E-12;
53  
54      protected abstract UnivariateInterpolator buildDoubleInterpolator();
55  
56      protected abstract FieldUnivariateInterpolator buildFieldInterpolator();
57  
58      @Test
59      public void testInterpolateLinearDegenerateTwoSegment()
60          {
61          double[] x = { 0.0, 0.5, 1.0 };
62          double[] y = { 0.0, 0.5, 1.0 };
63          UnivariateInterpolator i = buildDoubleInterpolator();
64          UnivariateFunction f = i.interpolate(x, y);
65          verifyInterpolation(f, x, y);
66  
67          // Verify coefficients using analytical values
68          PolynomialFunction[] polynomials = ((PolynomialSplineFunction) f).getPolynomials();
69          double[] target = {y[0], 1d};
70          UnitTestUtils.customAssertEquals(polynomials[0].getCoefficients(), target, coefficientTolerance);
71          target = new double[]{y[1], 1d};
72          UnitTestUtils.customAssertEquals(polynomials[1].getCoefficients(), target, coefficientTolerance);
73  
74          // Check interpolation
75          assertEquals(0.0,f.value(0.0), interpolationTolerance);
76          assertEquals(0.4,f.value(0.4), interpolationTolerance);
77          assertEquals(1.0,f.value(1.0), interpolationTolerance);
78      }
79  
80      @Test
81      public void testInterpolateLinearDegenerateTwoSegmentD64()
82          {
83          Binary64[] x = buildD64(0.0, 0.5, 1.0);
84          Binary64[] y = buildD64(0.0, 0.5, 1.0);
85          FieldUnivariateInterpolator i = buildFieldInterpolator();
86          CalculusFieldUnivariateFunction<Binary64> f = i.interpolate(x, y);
87          verifyInterpolation(f, x, y);
88  
89          // Verify coefficients using analytical values
90          FieldPolynomialFunction<Binary64>[] polynomials = ((FieldPolynomialSplineFunction<Binary64>) f).getPolynomials();
91          checkCoeffs(coefficientTolerance, polynomials[0], y[0].getReal(), 1.0);
92          checkCoeffs(coefficientTolerance, polynomials[1], y[1].getReal(), 1.0);
93  
94          // Check interpolation
95          assertEquals(0.0, f.value(new Binary64(0.0)).getReal(), interpolationTolerance);
96          assertEquals(0.4, f.value(new Binary64(0.4)).getReal(), interpolationTolerance);
97          assertEquals(1.0, f.value(new Binary64(1.0)).getReal(), interpolationTolerance);
98      }
99  
100     @Test
101     public void testInterpolateLinearDegenerateThreeSegment()
102         {
103         double[] x = { 0.0, 0.5, 1.0, 1.5 };
104         double[] y = { 0.0, 0.5, 1.0, 1.5 };
105         UnivariateInterpolator i = buildDoubleInterpolator();
106         UnivariateFunction f = i.interpolate(x, y);
107         verifyInterpolation(f, x, y);
108 
109         // Verify coefficients using analytical values
110         PolynomialFunction[] polynomials = ((PolynomialSplineFunction) f).getPolynomials();
111         double[] target = {y[0], 1d};
112         UnitTestUtils.customAssertEquals(polynomials[0].getCoefficients(), target, coefficientTolerance);
113         target = new double[]{y[1], 1d};
114         UnitTestUtils.customAssertEquals(polynomials[1].getCoefficients(), target, coefficientTolerance);
115         target = new double[]{y[2], 1d};
116         UnitTestUtils.customAssertEquals(polynomials[2].getCoefficients(), target, coefficientTolerance);
117 
118         // Check interpolation
119         assertEquals(0,f.value(0), interpolationTolerance);
120         assertEquals(1.4,f.value(1.4), interpolationTolerance);
121         assertEquals(1.5,f.value(1.5), interpolationTolerance);
122     }
123 
124     @Test
125     public void testInterpolateLinearDegenerateThreeSegmentD64()
126         {
127         Binary64[] x = buildD64(0.0, 0.5, 1.0, 1.5);
128         Binary64[] y = buildD64(0.0, 0.5, 1.0, 1.5);
129         FieldUnivariateInterpolator i = buildFieldInterpolator();
130         CalculusFieldUnivariateFunction<Binary64> f = i.interpolate(x, y);
131         verifyInterpolation(f, x, y);
132 
133         // Verify coefficients using analytical values
134         FieldPolynomialFunction<Binary64>[] polynomials = ((FieldPolynomialSplineFunction<Binary64>) f).getPolynomials();
135         checkCoeffs(coefficientTolerance, polynomials[0], y[0].getReal(), 1.0);
136         checkCoeffs(coefficientTolerance, polynomials[1], y[1].getReal(), 1.0);
137         checkCoeffs(coefficientTolerance, polynomials[2], y[2].getReal(), 1.0);
138 
139         // Check interpolation
140         assertEquals(0,   f.value(new Binary64(0)).getReal(),   interpolationTolerance);
141         assertEquals(1.4, f.value(new Binary64(1.4)).getReal(), interpolationTolerance);
142         assertEquals(1.5, f.value(new Binary64(1.5)).getReal(), interpolationTolerance);
143     }
144 
145     @Test
146     public void testIllegalArguments() {
147         UnivariateInterpolator i = buildDoubleInterpolator();
148         try
149         {
150             double[] yval = { 0.0, 1.0, 2.0, 3.0, 4.0 };
151             i.interpolate( null, yval );
152             fail( "Failed to detect x null pointer" );
153         }
154         catch ( NullArgumentException iae )
155         {
156             // Expected.
157         }
158 
159         try
160         {
161             double[] xval = { 0.0, 1.0, 2.0, 3.0, 4.0 };
162             i.interpolate( xval, null );
163             fail( "Failed to detect y null pointer" );
164         }
165         catch ( NullArgumentException iae )
166         {
167             // Expected.
168         }
169 
170         // Data set arrays of different size.
171         try {
172             double[] xval = { 0.0, 1.0 };
173             double[] yval = { 0.0, 1.0, 2.0 };
174             i.interpolate(xval, yval);
175             fail("Failed to detect data set array with different sizes.");
176         } catch (MathIllegalArgumentException iae) {
177             // Expected.
178         }
179         // X values not sorted.
180         try {
181             double[] xval = { 0.0, 1.0, 0.5 };
182             double[] yval = { 0.0, 1.0, 2.0 };
183             i.interpolate(xval, yval);
184             fail("Failed to detect unsorted arguments.");
185         } catch (MathIllegalArgumentException iae) {
186             // Expected.
187         }
188         // Not enough data to interpolate.
189         try {
190             double[] xval = { 0.0 };
191             double[] yval = { 0.0 };
192             i.interpolate(xval, yval);
193             fail("Failed to detect unsorted arguments.");
194         } catch (MathIllegalArgumentException iae) {
195             // Expected.
196         }
197     }
198 
199     @Test
200     public void testIllegalArgumentsD64() {
201         FieldUnivariateInterpolator i = buildFieldInterpolator();
202         try
203         {
204             Binary64[] yval = buildD64(0.0, 1.0, 2.0, 3.0, 4.0);
205             i.interpolate( null, yval );
206             fail( "Failed to detect x null pointer" );
207         }
208         catch ( NullArgumentException iae )
209         {
210             // Expected.
211         }
212 
213         try
214         {
215             Binary64[] xval = buildD64(0.0, 1.0, 2.0, 3.0, 4.0);
216             i.interpolate( xval, null );
217             fail( "Failed to detect y null pointer" );
218         }
219         catch ( NullArgumentException iae )
220         {
221             // Expected.
222         }
223 
224         // Data set arrays of different size.
225         try {
226             Binary64[] xval = buildD64(0.0, 1.0);
227             Binary64[] yval = buildD64(0.0, 1.0, 2.0);
228             i.interpolate(xval, yval);
229             fail("Failed to detect data set array with different sizes.");
230         } catch (MathIllegalArgumentException iae) {
231             // Expected.
232         }
233         // X values not sorted.
234         try {
235             Binary64[] xval = buildD64(0.0, 1.0, 0.5);
236             Binary64[] yval = buildD64(0.0, 1.0, 2.0);
237             i.interpolate(xval, yval);
238             fail("Failed to detect unsorted arguments.");
239         } catch (MathIllegalArgumentException iae) {
240             // Expected.
241         }
242         // Not enough data to interpolate.
243         try {
244             Binary64[] xval = buildD64(0.0);
245             Binary64[] yval = buildD64(0.0);
246             i.interpolate(xval, yval);
247             fail("Failed to detect unsorted arguments.");
248         } catch (MathIllegalArgumentException iae) {
249             // Expected.
250         }
251     }
252 
253     /**
254      * verifies that f(x[i]) = y[i] for i = 0..n-1 where n is common length.
255      */
256     protected void verifyInterpolation(UnivariateFunction f, double[] x, double[] y) {
257         for (int i = 0; i < x.length; i++) {
258             assertEquals(y[i], f.value(x[i]), knotTolerance);
259         }
260     }
261 
262     /**
263      * verifies that f(x[i]) = y[i] for i = 0..n-1 where n is common length.
264      */
265     protected <T extends CalculusFieldElement<T>> void verifyInterpolation(CalculusFieldUnivariateFunction<T> f,
266                                                                            T[] x, T[] y) {
267         for (int i = 0; i < x.length; i++) {
268             assertEquals( y[i].getReal(), f.value(x[i]).getReal(), knotTolerance);
269         }
270     }
271 
272     protected Binary64[] buildD64(double...c) {
273         Binary64[] array = new Binary64[c.length];
274         for (int i = 0; i < c.length; ++i) {
275             array[i] = new Binary64(c[i]);
276         }
277         return array;
278     }
279 
280     protected <T extends CalculusFieldElement<T>> void checkCoeffs(final double tolerance, final FieldPolynomialFunction<T> p,
281                                                                    final double... ref) {
282         final T[] c = p.getCoefficients();
283         assertEquals(ref.length, c.length);
284         for (int i = 0; i < ref.length; ++i) {
285             assertEquals(ref[i], c[i].getReal(), tolerance);
286         }
287     }
288 
289 }