/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.math4.analysis.interpolation; import java.util.Random; import org.apache.commons.math4.analysis.UnivariateFunction; import org.apache.commons.math4.analysis.interpolation.LinearInterpolator; import org.apache.commons.math4.analysis.interpolation.UnivariateInterpolator; import org.apache.commons.math4.analysis.interpolation.UnivariatePeriodicInterpolator; import org.apache.commons.math4.exception.NonMonotonicSequenceException; import org.apache.commons.math4.exception.NumberIsTooSmallException; import org.apache.commons.math4.util.FastMath; import org.junit.Assert; import org.junit.Test; /** * Test for {@link UnivariatePeriodicInterpolator}. */ public class UnivariatePeriodicInterpolatorTest { private final Random rng = new Random(1224465L); @Test public void testSine() { final int n = 30; final double[] xval = new double[n]; final double[] yval = new double[n]; final double period = 12.3; final double offset = 45.67; double delta = 0; for (int i = 0; i < n; i++) { delta += rng.nextDouble() * period / n; xval[i] = offset + delta; yval[i] = FastMath.sin(xval[i]); } final UnivariateInterpolator inter = new LinearInterpolator(); final UnivariateFunction f = inter.interpolate(xval, yval); final UnivariateInterpolator interP = new UnivariatePeriodicInterpolator(new LinearInterpolator(), period, 1); final UnivariateFunction fP = interP.interpolate(xval, yval); // Comparing with original interpolation algorithm. final double xMin = xval[0]; final double xMax = xval[n - 1]; for (int i = 0; i < n; i++) { final double x = xMin + (xMax - xMin) * rng.nextDouble(); final double y = f.value(x); final double yP = fP.value(x); Assert.assertEquals("x=" + x, y, yP, Math.ulp(1d)); } // Test interpolation outside the primary interval. for (int i = 0; i < n; i++) { final double xIn = offset + rng.nextDouble() * period; final double xOut = xIn + rng.nextInt(123456789) * period; final double yIn = fP.value(xIn); final double yOut = fP.value(xOut); Assert.assertEquals(yIn, yOut, 1e-7); } } @Test public void testLessThanOnePeriodCoverage() { final int n = 30; final double[] xval = new double[n]; final double[] yval = new double[n]; final double period = 12.3; final double offset = 45.67; double delta = period / 2; for (int i = 0; i < n; i++) { delta += period / (2 * n) * rng.nextDouble(); xval[i] = offset + delta; yval[i] = FastMath.sin(xval[i]); } final UnivariateInterpolator interP = new UnivariatePeriodicInterpolator(new LinearInterpolator(), period, 1); final UnivariateFunction fP = interP.interpolate(xval, yval); // Test interpolation outside the sample data interval. for (int i = 0; i < n; i++) { final double xIn = offset + rng.nextDouble() * period; final double xOut = xIn + rng.nextInt(123456789) * period; final double yIn = fP.value(xIn); final double yOut = fP.value(xOut); Assert.assertEquals(yIn, yOut, 1e-7); } } @Test public void testMoreThanOnePeriodCoverage() { final int n = 30; final double[] xval = new double[n]; final double[] yval = new double[n]; final double period = 12.3; final double offset = 45.67; double delta = period / 2; for (int i = 0; i < n; i++) { delta += 10 * period / n * rng.nextDouble(); xval[i] = offset + delta; yval[i] = FastMath.sin(xval[i]); } final UnivariateInterpolator interP = new UnivariatePeriodicInterpolator(new LinearInterpolator(), period, 1); final UnivariateFunction fP = interP.interpolate(xval, yval); // Test interpolation outside the sample data interval. for (int i = 0; i < n; i++) { final double xIn = offset + rng.nextDouble() * period; final double xOut = xIn + rng.nextInt(123456789) * period; final double yIn = fP.value(xIn); final double yOut = fP.value(xOut); Assert.assertEquals(yIn, yOut, 1e-6); } } @Test(expected=NumberIsTooSmallException.class) public void testTooFewSamples() { final double[] xval = { 2, 3, 7 }; final double[] yval = { 1, 6, 5 }; final double period = 10; final UnivariateInterpolator interpolator = new UnivariatePeriodicInterpolator(new LinearInterpolator(), period); interpolator.interpolate(xval, yval); } @Test(expected=NonMonotonicSequenceException.class) public void testUnsortedSamples() { final double[] xval = { 2, 3, 7, 4, 6 }; final double[] yval = { 1, 6, 5, -1, -2 }; final double period = 10; final UnivariateInterpolator interpolator = new UnivariatePeriodicInterpolator(new LinearInterpolator(), period); interpolator.interpolate(xval, yval); } }