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