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 java.util.Random;
25  
26  import org.hipparchus.analysis.polynomials.PolynomialFunction;
27  import org.hipparchus.dfp.Dfp;
28  import org.hipparchus.dfp.DfpField;
29  import org.hipparchus.exception.MathIllegalArgumentException;
30  import org.hipparchus.fraction.BigFraction;
31  import org.hipparchus.util.FastMath;
32  import org.junit.Assert;
33  import org.junit.Test;
34  
35  public class FieldHermiteInterpolatorTest {
36  
37      @Test
38      public void testZero() {
39          FieldHermiteInterpolator<BigFraction> interpolator = new FieldHermiteInterpolator<BigFraction>();
40          interpolator.addSamplePoint(new BigFraction(0), new BigFraction[] { new BigFraction(0) });
41          for (int x = -10; x < 10; x++) {
42              BigFraction y = interpolator.value(new BigFraction(x))[0];
43              Assert.assertEquals(BigFraction.ZERO, y);
44              BigFraction[][] derivatives = interpolator.derivatives(new BigFraction(x), 1);
45              Assert.assertEquals(BigFraction.ZERO, derivatives[0][0]);
46              Assert.assertEquals(BigFraction.ZERO, derivatives[1][0]);
47          }
48      }
49  
50      @Test
51      public void testQuadratic() {
52          FieldHermiteInterpolator<BigFraction> interpolator = new FieldHermiteInterpolator<BigFraction>();
53          interpolator.addSamplePoint(new BigFraction(0), new BigFraction[] { new BigFraction(2) });
54          interpolator.addSamplePoint(new BigFraction(1), new BigFraction[] { new BigFraction(0) });
55          interpolator.addSamplePoint(new BigFraction(2), new BigFraction[] { new BigFraction(0) });
56          for (double x = -10; x < 10; x += 1.0) {
57              BigFraction y = interpolator.value(new BigFraction(x))[0];
58              Assert.assertEquals((x - 1) * (x - 2), y.doubleValue(), 1.0e-15);
59              BigFraction[][] derivatives = interpolator.derivatives(new BigFraction(x), 3);
60              Assert.assertEquals((x - 1) * (x - 2), derivatives[0][0].doubleValue(), 1.0e-15);
61              Assert.assertEquals(2 * x - 3, derivatives[1][0].doubleValue(), 1.0e-15);
62              Assert.assertEquals(2, derivatives[2][0].doubleValue(), 1.0e-15);
63              Assert.assertEquals(0, derivatives[3][0].doubleValue(), 1.0e-15);
64          }
65      }
66  
67      @Test
68      public void testMixedDerivatives() {
69          FieldHermiteInterpolator<BigFraction> interpolator = new FieldHermiteInterpolator<BigFraction>();
70          interpolator.addSamplePoint(new BigFraction(0), new BigFraction[] { new BigFraction(1) }, new BigFraction[] { new BigFraction(2) });
71          interpolator.addSamplePoint(new BigFraction(1), new BigFraction[] { new BigFraction(4) });
72          interpolator.addSamplePoint(new BigFraction(2), new BigFraction[] { new BigFraction(5) }, new BigFraction[] { new BigFraction(2) });
73          BigFraction[][] derivatives = interpolator.derivatives(new BigFraction(0), 5);
74          Assert.assertEquals(new BigFraction(  1), derivatives[0][0]);
75          Assert.assertEquals(new BigFraction(  2), derivatives[1][0]);
76          Assert.assertEquals(new BigFraction(  8), derivatives[2][0]);
77          Assert.assertEquals(new BigFraction(-24), derivatives[3][0]);
78          Assert.assertEquals(new BigFraction( 24), derivatives[4][0]);
79          Assert.assertEquals(new BigFraction(  0), derivatives[5][0]);
80          derivatives = interpolator.derivatives(new BigFraction(1), 5);
81          Assert.assertEquals(new BigFraction(  4), derivatives[0][0]);
82          Assert.assertEquals(new BigFraction(  2), derivatives[1][0]);
83          Assert.assertEquals(new BigFraction( -4), derivatives[2][0]);
84          Assert.assertEquals(new BigFraction(  0), derivatives[3][0]);
85          Assert.assertEquals(new BigFraction( 24), derivatives[4][0]);
86          Assert.assertEquals(new BigFraction(  0), derivatives[5][0]);
87          derivatives = interpolator.derivatives(new BigFraction(2), 5);
88          Assert.assertEquals(new BigFraction(  5), derivatives[0][0]);
89          Assert.assertEquals(new BigFraction(  2), derivatives[1][0]);
90          Assert.assertEquals(new BigFraction(  8), derivatives[2][0]);
91          Assert.assertEquals(new BigFraction( 24), derivatives[3][0]);
92          Assert.assertEquals(new BigFraction( 24), derivatives[4][0]);
93          Assert.assertEquals(new BigFraction(  0), derivatives[5][0]);
94      }
95  
96      @Test
97      public void testRandomPolynomialsValuesOnly() {
98  
99          Random random = new Random(0x42b1e7dbd361a932l);
100 
101         for (int i = 0; i < 100; ++i) {
102 
103             int maxDegree = 0;
104             PolynomialFunction[] p = new PolynomialFunction[5];
105             for (int k = 0; k < p.length; ++k) {
106                 int degree = random.nextInt(7);
107                 p[k] = randomPolynomial(degree, random);
108                 maxDegree = FastMath.max(maxDegree, degree);
109             }
110 
111             DfpField field = new DfpField(30);
112             Dfp step = field.getOne().divide(field.newDfp(10));
113             FieldHermiteInterpolator<Dfp> interpolator = new FieldHermiteInterpolator<Dfp>();
114             for (int j = 0; j < 1 + maxDegree; ++j) {
115                 Dfp x = field.newDfp(j).multiply(step);
116                 Dfp[] values = new Dfp[p.length];
117                 for (int k = 0; k < p.length; ++k) {
118                     values[k] = field.newDfp(p[k].value(x.getReal()));
119                 }
120                 interpolator.addSamplePoint(x, values);
121             }
122 
123             for (int j = 0; j < 20; ++j) {
124                 Dfp x = field.newDfp(j).multiply(step);
125                 Dfp[] values = interpolator.value(x);
126                 Assert.assertEquals(p.length, values.length);
127                 for (int k = 0; k < p.length; ++k) {
128                     Assert.assertEquals(p[k].value(x.getReal()),
129                                         values[k].getReal(),
130                                         1.0e-8 * FastMath.abs(p[k].value(x.getReal())));
131                 }
132             }
133 
134         }
135 
136     }
137 
138     @Test
139     public void testRandomPolynomialsFirstDerivative() {
140 
141         Random random = new Random(0x570803c982ca5d3bl);
142 
143         for (int i = 0; i < 100; ++i) {
144 
145             int maxDegree = 0;
146             PolynomialFunction[] p      = new PolynomialFunction[5];
147             PolynomialFunction[] pPrime = new PolynomialFunction[5];
148             for (int k = 0; k < p.length; ++k) {
149                 int degree = random.nextInt(7);
150                 p[k]      = randomPolynomial(degree, random);
151                 pPrime[k] = p[k].polynomialDerivative();
152                 maxDegree = FastMath.max(maxDegree, degree);
153             }
154 
155             DfpField field = new DfpField(30);
156             Dfp step = field.getOne().divide(field.newDfp(10));
157             FieldHermiteInterpolator<Dfp> interpolator = new FieldHermiteInterpolator<Dfp>();
158             for (int j = 0; j < 1 + maxDegree / 2; ++j) {
159                 Dfp x = field.newDfp(j).multiply(step);
160                 Dfp[] values      = new Dfp[p.length];
161                 Dfp[] derivatives = new Dfp[p.length];
162                 for (int k = 0; k < p.length; ++k) {
163                     values[k]      = field.newDfp(p[k].value(x.getReal()));
164                     derivatives[k] = field.newDfp(pPrime[k].value(x.getReal()));
165                 }
166                 interpolator.addSamplePoint(x, values, derivatives);
167             }
168 
169             Dfp h = step.divide(field.newDfp(100000));
170             for (int j = 0; j < 20; ++j) {
171                 Dfp x = field.newDfp(j).multiply(step);
172                 Dfp[] y  = interpolator.value(x);
173                 Dfp[] yP = interpolator.value(x.add(h));
174                 Dfp[] yM = interpolator.value(x.subtract(h));
175                 Assert.assertEquals(p.length, y.length);
176                 for (int k = 0; k < p.length; ++k) {
177                     Assert.assertEquals(p[k].value(x.getReal()),
178                                         y[k].getReal(),
179                                         1.0e-8 * FastMath.abs(p[k].value(x.getReal())));
180                     Assert.assertEquals(pPrime[k].value(x.getReal()),
181                                         yP[k].subtract(yM[k]).divide(h.multiply(2)).getReal(),
182                                         4.0e-8 * FastMath.abs(p[k].value(x.getReal())));
183                 }
184             }
185 
186         }
187     }
188 
189     @Test
190     public void testSine() {
191         DfpField field = new DfpField(30);
192         FieldHermiteInterpolator<Dfp> interpolator = new FieldHermiteInterpolator<Dfp>();
193         for (Dfp x = field.getZero(); x.getReal() < FastMath.PI; x = x.add(0.5)) {
194             interpolator.addSamplePoint(x, new Dfp[] { x.sin() });
195         }
196         for (Dfp x = field.newDfp(0.1); x.getReal() < 2.9; x = x.add(0.01)) {
197             Dfp y = interpolator.value(x)[0];
198             Assert.assertEquals( x.sin().getReal(), y.getReal(), 3.5e-5);
199         }
200     }
201 
202     @Test
203     public void testSquareRoot() {
204         DfpField field = new DfpField(30);
205         FieldHermiteInterpolator<Dfp> interpolator = new FieldHermiteInterpolator<Dfp>();
206         for (Dfp x = field.getOne(); x.getReal() < 3.6; x = x.add(0.5)) {
207             interpolator.addSamplePoint(x, new Dfp[] { x.sqrt() });
208         }
209         for (Dfp x = field.newDfp(1.1); x.getReal() < 3.5; x = x.add(0.01)) {
210             Dfp y = interpolator.value(x)[0];
211             Assert.assertEquals(x.sqrt().getReal(), y.getReal(), 1.5e-4);
212         }
213     }
214 
215     @Test
216     public void testWikipedia() {
217         // this test corresponds to the example from Wikipedia page:
218         // http://en.wikipedia.org/wiki/Hermite_interpolation
219         FieldHermiteInterpolator<BigFraction> interpolator = new FieldHermiteInterpolator<BigFraction>();
220         interpolator.addSamplePoint(new BigFraction(-1),
221                                     new BigFraction[] { new BigFraction( 2) },
222                                     new BigFraction[] { new BigFraction(-8) },
223                                     new BigFraction[] { new BigFraction(56) });
224         interpolator.addSamplePoint(new BigFraction( 0),
225                                     new BigFraction[] { new BigFraction( 1) },
226                                     new BigFraction[] { new BigFraction( 0) },
227                                     new BigFraction[] { new BigFraction( 0) });
228         interpolator.addSamplePoint(new BigFraction( 1),
229                                     new BigFraction[] { new BigFraction( 2) },
230                                     new BigFraction[] { new BigFraction( 8) },
231                                     new BigFraction[] { new BigFraction(56) });
232         for (BigFraction x = new BigFraction(-1); x.doubleValue() <= 1.0; x = x.add(new BigFraction(1, 8))) {
233             BigFraction y = interpolator.value(x)[0];
234             BigFraction x2 = x.multiply(x);
235             BigFraction x4 = x2.multiply(x2);
236             BigFraction x8 = x4.multiply(x4);
237             Assert.assertEquals(x8.add(new BigFraction(1)), y);
238         }
239     }
240 
241     @Test
242     public void testOnePointParabola() {
243         FieldHermiteInterpolator<BigFraction> interpolator = new FieldHermiteInterpolator<BigFraction>();
244         interpolator.addSamplePoint(new BigFraction(0),
245                                     new BigFraction[] { new BigFraction(1) },
246                                     new BigFraction[] { new BigFraction(1) },
247                                     new BigFraction[] { new BigFraction(2) });
248         for (BigFraction x = new BigFraction(-1); x.doubleValue() <= 1.0; x = x.add(new BigFraction(1, 8))) {
249             BigFraction y = interpolator.value(x)[0];
250             Assert.assertEquals(BigFraction.ONE.add(x.multiply(BigFraction.ONE.add(x))), y);
251         }
252     }
253 
254     private PolynomialFunction randomPolynomial(int degree, Random random) {
255         double[] coeff = new double[ 1 + degree];
256         for (int j = 0; j < degree; ++j) {
257             coeff[j] = random.nextDouble();
258         }
259         return new PolynomialFunction(coeff);
260     }
261 
262     @Test(expected=MathIllegalArgumentException.class)
263     public void testEmptySampleValue() {
264         new FieldHermiteInterpolator<BigFraction>().value(BigFraction.ZERO);
265     }
266 
267     @Test(expected=MathIllegalArgumentException.class)
268     public void testEmptySampleDerivative() {
269         new FieldHermiteInterpolator<BigFraction>().derivatives(BigFraction.ZERO, 1);
270     }
271 
272     @Test(expected=MathIllegalArgumentException.class)
273     public void testDuplicatedAbscissa() {
274         FieldHermiteInterpolator<BigFraction> interpolator = new FieldHermiteInterpolator<BigFraction>();
275         interpolator.addSamplePoint(new BigFraction(1), new BigFraction[] { new BigFraction(0) });
276         interpolator.addSamplePoint(new BigFraction(1), new BigFraction[] { new BigFraction(1) });
277     }
278 
279 }
280