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.analysis.UnivariateFunction;
25  import org.hipparchus.exception.MathIllegalArgumentException;
26  import org.hipparchus.util.FastMath;
27  import org.junit.jupiter.api.Test;
28  
29  import java.util.Random;
30  
31  import static org.junit.jupiter.api.Assertions.assertEquals;
32  import static org.junit.jupiter.api.Assertions.assertThrows;
33  
34  
35  /**
36   * Test for {@link UnivariatePeriodicInterpolator}.
37   */
38  class UnivariatePeriodicInterpolatorTest {
39      private final Random rng = new Random(1224465L);
40  
41      @Test
42      void testSine() {
43          final int n = 30;
44          final double[] xval = new double[n];
45          final double[] yval = new double[n];
46          final double period = 12.3;
47          final double offset = 45.67;
48  
49          double delta = 0;
50          for (int i = 0; i < n; i++) {
51              delta += rng.nextDouble() * period / n;
52              xval[i] = offset + delta;
53              yval[i] = FastMath.sin(xval[i]);
54          }
55  
56          final UnivariateInterpolator inter = new LinearInterpolator();
57          final UnivariateFunction f = inter.interpolate(xval, yval);
58  
59          final UnivariateInterpolator interP
60              = new UnivariatePeriodicInterpolator(new LinearInterpolator(),
61                                                       period, 1);
62          final UnivariateFunction fP = interP.interpolate(xval, yval);
63  
64          // Comparing with original interpolation algorithm.
65          final double xMin = xval[0];
66          final double xMax = xval[n - 1];
67          for (int i = 0; i < n; i++) {
68              final double x = xMin + (xMax - xMin) * rng.nextDouble();
69              final double y = f.value(x);
70              final double yP = fP.value(x);
71  
72              assertEquals(y, yP, Math.ulp(1d), "x=" + x);
73          }
74  
75          // Test interpolation outside the primary interval.
76          for (int i = 0; i < n; i++) {
77              final double xIn = offset + rng.nextDouble() * period;
78              final double xOut = xIn + rng.nextInt(123456789) * period;
79              final double yIn = fP.value(xIn);
80              final double yOut = fP.value(xOut);
81  
82              assertEquals(yIn, yOut, 1e-7);
83          }
84      }
85  
86      @Test
87      void testLessThanOnePeriodCoverage() {
88          final int n = 30;
89          final double[] xval = new double[n];
90          final double[] yval = new double[n];
91          final double period = 12.3;
92          final double offset = 45.67;
93  
94          double delta = period / 2;
95          for (int i = 0; i < n; i++) {
96              delta += period / (2 * n) * rng.nextDouble();
97              xval[i] = offset + delta;
98              yval[i] = FastMath.sin(xval[i]);
99          }
100 
101         final UnivariateInterpolator interP
102             = new UnivariatePeriodicInterpolator(new LinearInterpolator(),
103                                                      period, 1);
104         final UnivariateFunction fP = interP.interpolate(xval, yval);
105 
106         // Test interpolation outside the sample data interval.
107         for (int i = 0; i < n; i++) {
108             final double xIn = offset + rng.nextDouble() * period;
109             final double xOut = xIn + rng.nextInt(123456789) * period;
110             final double yIn = fP.value(xIn);
111             final double yOut = fP.value(xOut);
112 
113             assertEquals(yIn, yOut, 1e-7);
114         }
115     }
116 
117     @Test
118     void testMoreThanOnePeriodCoverage() {
119         final int n = 30;
120         final double[] xval = new double[n];
121         final double[] yval = new double[n];
122         final double period = 12.3;
123         final double offset = 45.67;
124 
125         double delta = period / 2;
126         for (int i = 0; i < n; i++) {
127             delta += 10 * period / n * rng.nextDouble();
128             xval[i] = offset + delta;
129             yval[i] = FastMath.sin(xval[i]);
130         }
131 
132         final UnivariateInterpolator interP
133             = new UnivariatePeriodicInterpolator(new LinearInterpolator(),
134                                                      period, 1);
135         final UnivariateFunction fP = interP.interpolate(xval, yval);
136 
137         // Test interpolation outside the sample data interval.
138         for (int i = 0; i < n; i++) {
139             final double xIn = offset + rng.nextDouble() * period;
140             final double xOut = xIn + rng.nextInt(123456789) * period;
141             final double yIn = fP.value(xIn);
142             final double yOut = fP.value(xOut);
143 
144             assertEquals(yIn, yOut, 1e-6);
145         }
146     }
147 
148     @Test
149     void testTooFewSamples() {
150         assertThrows(MathIllegalArgumentException.class, () -> {
151             final double[] xval = {2, 3, 7};
152             final double[] yval = {1, 6, 5};
153             final double period = 10;
154 
155             final UnivariateInterpolator interpolator
156                 = new UnivariatePeriodicInterpolator(new LinearInterpolator(), period);
157             interpolator.interpolate(xval, yval);
158         });
159     }
160 
161     @Test
162     void testUnsortedSamples() {
163         assertThrows(MathIllegalArgumentException.class, () -> {
164             final double[] xval = {2, 3, 7, 4, 6};
165             final double[] yval = {1, 6, 5, -1, -2};
166             final double period = 10;
167 
168             final UnivariateInterpolator interpolator
169                 = new UnivariatePeriodicInterpolator(new LinearInterpolator(), period);
170             interpolator.interpolate(xval, yval);
171         });
172     }
173 }