This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-math.git


The following commit(s) were added to refs/heads/master by this push:
     new 75e62ead4 Fix sine test
75e62ead4 is described below

commit 75e62ead434abd5a6d2376d5774fbe33da8de925
Author: Alex Herbert <[email protected]>
AuthorDate: Wed Oct 28 09:56:10 2026 +0000

    Fix sine test
    
    The points were only sampled on average within half the period. Updated
    to sample uniformly within the period.
    
    Updated the interpolation test to ensure the round-trip from xOut to xIn
    to xOut is exact. The periodic interpolation should then be exact.
    
    Add note about flaky less-than-one-period test.
---
 .../UnivariatePeriodicInterpolatorTest.java        | 46 ++++++++++++++++------
 1 file changed, 34 insertions(+), 12 deletions(-)

diff --git 
a/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/analysis/interpolation/UnivariatePeriodicInterpolatorTest.java
 
b/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/analysis/interpolation/UnivariatePeriodicInterpolatorTest.java
index 32f123ccc..258c57836 100644
--- 
a/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/analysis/interpolation/UnivariatePeriodicInterpolatorTest.java
+++ 
b/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/analysis/interpolation/UnivariatePeriodicInterpolatorTest.java
@@ -25,6 +25,7 @@ import org.apache.commons.rng.simple.RandomSource;
 import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
 import org.apache.commons.math4.legacy.exception.NonMonotonicSequenceException;
 import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
+import java.util.Arrays;
 import org.apache.commons.math4.core.jdkmath.JdkMath;
 
 
@@ -37,17 +38,12 @@ public class UnivariatePeriodicInterpolatorTest {
     @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] = JdkMath.sin(xval[i]);
-        }
+        // Sample within the period
+        final double[] xval = rng.doubles(n).map(x -> offset + x * 
period).sorted().toArray();
+        final double[] yval = Arrays.stream(xval).map(JdkMath::sin).toArray();
 
         final UnivariateInterpolator inter = new LinearInterpolator();
         final UnivariateFunction f = inter.interpolate(xval, yval);
@@ -65,20 +61,46 @@ public class UnivariatePeriodicInterpolatorTest {
             final double y = f.value(x);
             final double yP = fP.value(x);
 
-            Assert.assertEquals("(Delta: ulp(1)) x=" + x, y, yP, Math.ulp(1d));
+            Assert.assertEquals("Original interpolation", y, yP, 0);
         }
 
         // Test interpolation outside the primary interval.
+        // Ensure the point outside the period is exactly mapped:
+        //   xIn = offset + x * period
+        //   xOut = xIn + j * period
+        // Known offset of the period is the first value
+        final double off = xval[0];
         for (int i = 0; i < n; i++) {
-            final double xIn = offset + rng.nextDouble() * period;
-            final double xOut = xIn + rng.nextInt(123456789) * period;
+            final int j = rng.nextInt(123456789);
+            final double x = rng.nextDouble();
+            double xOut = off + (j + x) * period;
+            // xIn = off + x * period
+            // Performed from xOut so the mapping is exact
+            double xIn = (xOut - off) - j * period + off;
+            // Verify xIn
+            double expected = off + x * period;
+            // This is inexact and relative error depends on the magnitude of j
+            // which is at most a 27 bit integer. Relative tolerance ~ 26 bits
+            // for the effective round-trip x' = x + j - j.
+            Assert.assertEquals("Approximate xIn", expected, xIn, 
Math.abs(expected * 0x1p-26));
+            Assert.assertEquals("xOut remapped", xOut, xIn + j * period, 0);
             final double yIn = fP.value(xIn);
             final double yOut = fP.value(xOut);
 
-            Assert.assertEquals("Delta: 1e-7", yIn, yOut, 1e-7);
+            Assert.assertEquals("Interpolation", yIn, yOut, 0);
         }
     }
 
+    /**
+     * Note: This test is flaky.
+     *
+     * <p>The test only works since the period chosen 12.3 = 3.92 pi and 
sampling uses
+     * approximately half of the period 12.3 so covers the period of sine most 
of the
+     * time. If the function was not periodic within half the specific period 
the test
+     * would fail. The aim is to assert interpolation within the provided 
period using
+     * points that do not cover that period does work even if doing this is not
+     * recommended.
+     */
     @Test
     public void testLessThanOnePeriodCoverage() {
         final int n = 30;

Reply via email to