You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2021/08/18 22:03:08 UTC

[commons-math] 01/02: Update atan2 special cases test

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

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

commit f06bb2aa3ffa87be738f557e91d62b0ef2085271
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Wed Aug 18 22:55:30 2021 +0100

    Update atan2 special cases test
    
    Enumerate all combinations of 0, infinity and another value (0.1) with
    +/- for each. Results are the same with java.lang.Math.
---
 .../legacy/core/jdkmath/AccurateMathTest.java      | 90 +++++++++++++++-------
 1 file changed, 64 insertions(+), 26 deletions(-)

diff --git a/commons-math-legacy-core/src/test/java/org/apache/commons/math4/legacy/core/jdkmath/AccurateMathTest.java b/commons-math-legacy-core/src/test/java/org/apache/commons/math4/legacy/core/jdkmath/AccurateMathTest.java
index 6cddff2..8592600 100644
--- a/commons-math-legacy-core/src/test/java/org/apache/commons/math4/legacy/core/jdkmath/AccurateMathTest.java
+++ b/commons-math-legacy-core/src/test/java/org/apache/commons/math4/legacy/core/jdkmath/AccurateMathTest.java
@@ -622,32 +622,70 @@ public class AccurateMathTest {
 
         assertTrue("atan2(NaN, 0.0) should be NaN", Double.isNaN(AccurateMath.atan2(Double.NaN, 0.0)));
         assertTrue("atan2(0.0, NaN) should be NaN", Double.isNaN(AccurateMath.atan2(0.0, Double.NaN)));
-        assertEquals("atan2(0.0, 0.0) should be 0.0", 0.0, AccurateMath.atan2(0.0, 0.0), Precision.EPSILON);
-        assertEquals("atan2(0.0, 0.001) should be 0.0", 0.0, AccurateMath.atan2(0.0, 0.001), Precision.EPSILON);
-        assertEquals("atan2(0.1, +Inf) should be 0.0", 0.0, AccurateMath.atan2(0.1, Double.POSITIVE_INFINITY), Precision.EPSILON);
-        assertEquals("atan2(-0.0, 0.0) should be -0.0", -0.0, AccurateMath.atan2(-0.0, 0.0), Precision.EPSILON);
-        assertEquals("atan2(-0.0, 0.001) should be -0.0", -0.0, AccurateMath.atan2(-0.0, 0.001), Precision.EPSILON);
-        assertEquals("atan2(-0.0, +Inf) should be -0.0", -0.0, AccurateMath.atan2(-0.1, Double.POSITIVE_INFINITY), Precision.EPSILON);
-        assertEquals("atan2(0.0, -0.0) should be PI", AccurateMath.PI, AccurateMath.atan2(0.0, -0.0), Precision.EPSILON);
-        assertEquals("atan2(0.1, -Inf) should be PI", AccurateMath.PI, AccurateMath.atan2(0.1, Double.NEGATIVE_INFINITY), Precision.EPSILON);
-        assertEquals("atan2(-0.0, -0.0) should be -PI", -AccurateMath.PI, AccurateMath.atan2(-0.0, -0.0), Precision.EPSILON);
-        assertEquals("atan2(0.1, -Inf) should be -PI", -AccurateMath.PI, AccurateMath.atan2(-0.1, Double.NEGATIVE_INFINITY), Precision.EPSILON);
-        assertEquals("atan2(0.1, 0.0) should be PI/2", AccurateMath.PI / 2.0, AccurateMath.atan2(0.1, 0.0), Precision.EPSILON);
-        assertEquals("atan2(0.1, -0.0) should be PI/2", AccurateMath.PI / 2.0, AccurateMath.atan2(0.1, -0.0), Precision.EPSILON);
-        assertEquals("atan2(Inf, 0.1) should be PI/2", AccurateMath.PI / 2.0, AccurateMath.atan2(Double.POSITIVE_INFINITY, 0.1), Precision.EPSILON);
-        assertEquals("atan2(Inf, -0.1) should be PI/2", AccurateMath.PI / 2.0, AccurateMath.atan2(Double.POSITIVE_INFINITY, -0.1), Precision.EPSILON);
-        assertEquals("atan2(-0.1, 0.0) should be -PI/2", -AccurateMath.PI / 2.0, AccurateMath.atan2(-0.1, 0.0), Precision.EPSILON);
-        assertEquals("atan2(-0.1, -0.0) should be -PI/2", -AccurateMath.PI / 2.0, AccurateMath.atan2(-0.1, -0.0), Precision.EPSILON);
-        assertEquals("atan2(-Inf, 0.1) should be -PI/2", -AccurateMath.PI / 2.0, AccurateMath.atan2(Double.NEGATIVE_INFINITY, 0.1), Precision.EPSILON);
-        assertEquals("atan2(-Inf, -0.1) should be -PI/2", -AccurateMath.PI / 2.0, AccurateMath.atan2(Double.NEGATIVE_INFINITY, -0.1), Precision.EPSILON);
-        assertEquals("atan2(Inf, Inf) should be PI/4", AccurateMath.PI / 4.0, AccurateMath.atan2(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY),
-                     Precision.EPSILON);
-        assertEquals("atan2(Inf, -Inf) should be PI * 3/4", AccurateMath.PI * 3.0 / 4.0,
-                     AccurateMath.atan2(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY), Precision.EPSILON);
-        assertEquals("atan2(-Inf, Inf) should be -PI/4", -AccurateMath.PI / 4.0, AccurateMath.atan2(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY),
-                     Precision.EPSILON);
-        assertEquals("atan2(-Inf, -Inf) should be -PI * 3/4", -AccurateMath.PI * 3.0 / 4.0,
-                     AccurateMath.atan2(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY), Precision.EPSILON);
+
+        final double pinf = Double.POSITIVE_INFINITY;
+        final double ninf = Double.NEGATIVE_INFINITY;
+        // Test using fractions of pi
+        assertAtan2( 0.0,  0.0,  0.0, 1.0);
+        assertAtan2( 0.0, -0.0,  1.0, 1.0);
+        assertAtan2( 0.0,  0.1,  0.0, 1.0);
+        assertAtan2( 0.0, -0.1,  1.0, 1.0);
+        assertAtan2( 0.0, pinf,  0.0, 1.0);
+        assertAtan2( 0.0, ninf,  1.0, 1.0);
+        assertAtan2(-0.0,  0.0, -0.0, 1.0);
+        assertAtan2(-0.0, -0.0, -1.0, 1.0);
+        assertAtan2(-0.0,  0.1, -0.0, 1.0);
+        assertAtan2(-0.0, -0.1, -1.0, 1.0);
+        assertAtan2(-0.0, pinf, -0.0, 1.0);
+        assertAtan2(-0.0, ninf, -1.0, 1.0);
+        assertAtan2( 0.1,  0.0,  1.0, 2.0);
+        assertAtan2( 0.1, -0.0,  1.0, 2.0);
+        assertAtan2( 0.1,  0.1,  1.0, 4.0);
+        assertAtan2( 0.1, -0.1,  3.0, 4.0);
+        assertAtan2( 0.1, pinf,  0.0, 1.0);
+        assertAtan2( 0.1, ninf,  1.0, 1.0);
+        assertAtan2(-0.1,  0.0, -1.0, 2.0);
+        assertAtan2(-0.1, -0.0, -1.0, 2.0);
+        assertAtan2(-0.1,  0.1, -1.0, 4.0);
+        assertAtan2(-0.1, -0.1, -3.0, 4.0);
+        assertAtan2(-0.1, pinf, -0.0, 1.0);
+        assertAtan2(-0.1, ninf, -1.0, 1.0);
+        assertAtan2(pinf,  0.0,  1.0, 2.0);
+        assertAtan2(pinf, -0.0,  1.0, 2.0);
+        assertAtan2(pinf,  0.1,  1.0, 2.0);
+        assertAtan2(pinf, -0.1,  1.0, 2.0);
+        assertAtan2(pinf, pinf,  1.0, 4.0);
+        assertAtan2(pinf, ninf,  3.0, 4.0);
+        assertAtan2(ninf,  0.0, -1.0, 2.0);
+        assertAtan2(ninf, -0.0, -1.0, 2.0);
+        assertAtan2(ninf,  0.1, -1.0, 2.0);
+        assertAtan2(ninf, -0.1, -1.0, 2.0);
+        assertAtan2(ninf, pinf, -1.0, 4.0);
+        assertAtan2(ninf, ninf, -3.0, 4.0);
+    }
+
+    /**
+     * Assert the atan2(y, x) value is a fraction of pi.
+     *
+     * @param y ordinate
+     * @param x abscissa
+     * @param numerator numerator of the fraction of pi (including the sign)
+     * @param denominator denominator of the fraction of pi
+     */
+    private static void assertAtan2(double y, double x, double numerator, double denominator) {
+        final double v = AccurateMath.atan2(y, x);
+        if (numerator == 0) {
+            // Exact including the sign.
+            // Not available in JUnit 4 so use the long bits.
+            final long l = Double.doubleToLongBits(v);
+            if (l != Double.doubleToLongBits(numerator)) {
+                Assert.fail(String.format("atan2(%s, %s) should be %s but was %s", y, x, numerator, v));
+            }
+        } else {
+            final String msg = String.format("atan2(%s, %s) should be pi * %s / %s", y, x, numerator, denominator);
+            final double expected = AccurateMath.PI * numerator / denominator;
+            assertEquals(msg, expected, v, Precision.EPSILON);
+        }
     }
 
     @Test