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