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