UnivariatePeriodicInterpolator implements UnivariateInterpolator { public UnivariateFunction interpolate(double[] xval, double[] yval) throws NumberIsTooSmallException, NonMonotonicSequenceException { if (xval.length < extend) { throw new NumberIsTooSmallException(xval.length, extend, true); } MathArrays.checkOrder(xval); final double offset = xval[0]; final int len = xval.length + extend * 2; final double[] x = new double[len]; final double[] y = new double[len]; for (int i = 0; i < xval.length; i++) { final int index = i + extend; x[index] = MathUtils.reduce(xval[i], period, offset); y[index] = yval[i]; } for (int i = 0; i < extend; i++) { int index = xval.length - extend + i; x[i] = MathUtils.reduce(xval[index], period, offset) - period; y[i] = yval[index]; index = len - extend + i; x[index] = MathUtils.reduce(xval[i], period, offset) + period; y[index] = yval[i]; } MathArrays.sortInPlace(x, y); final UnivariateFunction f = interpolator.interpolate(x, y); return new UnivariateFunction() { public double value(final double x) throws MathIllegalArgumentException { return f.value(MathUtils.reduce(x, period, offset)); } }; } UnivariatePeriodicInterpolator(UnivariateInterpolator interpolator,
                                          double period,
                                          int extend);  UnivariatePeriodicInterpolator(UnivariateInterpolator interpolator,
                                          double period); UnivariateFunction interpolate(double[] xval,
                                          double[] yval); static final int DEFAULT_EXTEND; }
@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); 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)); } 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); 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); 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); }