You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by se...@apache.org on 2011/02/12 19:27:22 UTC

svn commit: r1070122 - in /commons/proper/math/branches/MATH_2_X/src: main/java/org/apache/commons/math/util/MathUtils.java test/java/org/apache/commons/math/util/MathUtilsTest.java

Author: sebb
Date: Sat Feb 12 18:27:22 2011
New Revision: 1070122

URL: http://svn.apache.org/viewvc?rev=1070122&view=rev
Log:
Revert MathUtils to 2.1 behaviour.
Update tests accordingly, and restore missing tests from 2.1 version
Note: removed deprecation from methods that merely change behaviour in 3.0

Modified:
    commons/proper/math/branches/MATH_2_X/src/main/java/org/apache/commons/math/util/MathUtils.java
    commons/proper/math/branches/MATH_2_X/src/test/java/org/apache/commons/math/util/MathUtilsTest.java

Modified: commons/proper/math/branches/MATH_2_X/src/main/java/org/apache/commons/math/util/MathUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/math/branches/MATH_2_X/src/main/java/org/apache/commons/math/util/MathUtils.java?rev=1070122&r1=1070121&r2=1070122&view=diff
==============================================================================
--- commons/proper/math/branches/MATH_2_X/src/main/java/org/apache/commons/math/util/MathUtils.java (original)
+++ commons/proper/math/branches/MATH_2_X/src/main/java/org/apache/commons/math/util/MathUtils.java Sat Feb 12 18:27:22 2011
@@ -530,7 +530,7 @@ public final class MathUtils {
      * @deprecated This method considers that {@code NaN == NaN}. In release
      * 3.0, the semantics will change in order to comply with IEEE754 where it
      * is specified that {@code NaN != NaN}.
-     * New methods have been added for those cases wher the old semantics is
+     * New methods have been added for those cases where the old semantics is
      * useful (see e.g. {@link #equalsIncludingNaN(float[],float[])
      * equalsIncludingNaN}.
      */
@@ -576,21 +576,22 @@ public final class MathUtils {
     }
 
     /**
-     * Returns true iff they are strictly equal.
+     * Returns true iff both arguments are NaN or neither is NaN and they are
+     * equal
      *
-     * @param x first value
-     * @param y second value
-     * @return {@code true} if the values are equal.
-     * @deprecated This method considers that {@code NaN == NaN}. In release
+     * <p>This method considers that {@code NaN == NaN}. In release
      * 3.0, the semantics will change in order to comply with IEEE754 where it
-     * is specified that {@code NaN != NaN}. Also, two adjacent floating point
-     * numbers will be considered equal.
+     * is specified that {@code NaN != NaN}.
      * New methods have been added for those cases where the old semantics
      * (w.r.t. NaN) is useful (see e.g.
-     * {@link #equalsIncludingNaN(double,double) equalsIncludingNaN}.
+     * {@link #equalsIncludingNaN(double,double, double) equalsIncludingNaN}.
+     * </p>
+     * 
+     * @param x first value
+     * @param y second value
+     * @return {@code true} if the values are equal.
      */
-    @Deprecated
-        public static boolean equals(double x, double y) {
+    public static boolean equals(double x, double y) {
         return (Double.isNaN(x) && Double.isNaN(y)) || x == y;
     }
 
@@ -609,14 +610,23 @@ public final class MathUtils {
     /**
      * Returns true if both arguments are equal or within the range of allowed
      * error (inclusive).
-     *
+     * <p>
+     * Two NaNs are considered equals, as are two infinities with same sign.
+     * </p>
+     * <p>This method considers that {@code NaN == NaN}. In release
+     * 3.0, the semantics will change in order to comply with IEEE754 where it
+     * is specified that {@code NaN != NaN}.
+     * New methods have been added for those cases where the old semantics
+     * (w.r.t. NaN) is useful (see e.g.
+     * {@link #equalsIncludingNaN(double,double, double) equalsIncludingNaN}.
+     * </p>
      * @param x first value
      * @param y second value
      * @param eps the amount of absolute error to allow.
      * @return {@code true} if the values are equal or within range of each other.
      */
     public static boolean equals(double x, double y, double eps) {
-        return equals(x, y, 1) || FastMath.abs(y - x) <= eps;
+        return equals(x, y) || FastMath.abs(y - x) <= eps;
     }
 
     /**
@@ -643,6 +653,14 @@ public final class MathUtils {
      * href="http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm">
      * Bruce Dawson</a>
      *
+     * <p>This method considers that {@code NaN == NaN}. In release
+     * 3.0, the semantics will change in order to comply with IEEE754 where it
+     * is specified that {@code NaN != NaN}.
+     * New methods have been added for those cases where the old semantics
+     * (w.r.t. NaN) is useful (see e.g.
+     * {@link #equalsIncludingNaN(double,double, int) equalsIncludingNaN}.
+     * </p>
+     * 
      * @param x first value
      * @param y second value
      * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
@@ -666,9 +684,7 @@ public final class MathUtils {
             yInt = SGN_MASK - yInt;
         }
 
-        final boolean isEqual = FastMath.abs(xInt - yInt) <= maxUlps;
-
-        return isEqual && !Double.isNaN(x) && !Double.isNaN(y);
+        return FastMath.abs(xInt - yInt) <= maxUlps;
     }
 
     /**
@@ -691,18 +707,18 @@ public final class MathUtils {
      * their elements are equal as defined by
      * {@link #equals(double,double)}.
      *
-     * @param x first array
-     * @param y second array
-     * @return true if the values are both null or have same dimension
-     * and equal elements.
-     * @deprecated This method considers that {@code NaN == NaN}. In release
+     * <p>This method considers that {@code NaN == NaN}. In release
      * 3.0, the semantics will change in order to comply with IEEE754 where it
      * is specified that {@code NaN != NaN}.
      * New methods have been added for those cases wher the old semantics is
      * useful (see e.g. {@link #equalsIncludingNaN(double[],double[])
      * equalsIncludingNaN}.
+     * </p>
+     * @param x first array
+     * @param y second array
+     * @return true if the values are both null or have same dimension
+     * and equal elements.
      */
-    @Deprecated
     public static boolean equals(double[] x, double[] y) {
         if ((x == null) || (y == null)) {
             return !((x == null) ^ (y == null));
@@ -1290,10 +1306,46 @@ public final class MathUtils {
      * @return the next machine representable number in the specified direction
      * @since 1.2
      * @deprecated as of 2.2, replaced by {@link FastMath#nextAfter(double, double)}
+     * which handles Infinities differently, and returns direction if d and direction compare equal.
      */
     @Deprecated
     public static double nextAfter(double d, double direction) {
-        return FastMath.nextAfter(d, direction);
+
+        // handling of some important special cases
+        if (Double.isNaN(d) || Double.isInfinite(d)) {
+                return d;
+        } else if (d == 0) {
+                return (direction < 0) ? -Double.MIN_VALUE : Double.MIN_VALUE;
+        }
+        // special cases MAX_VALUE to infinity and  MIN_VALUE to 0
+        // are handled just as normal numbers
+
+        // split the double in raw components
+        long bits     = Double.doubleToLongBits(d);
+        long sign     = bits & 0x8000000000000000L;
+        long exponent = bits & 0x7ff0000000000000L;
+        long mantissa = bits & 0x000fffffffffffffL;
+
+        if (d * (direction - d) >= 0) {
+                // we should increase the mantissa
+                if (mantissa == 0x000fffffffffffffL) {
+                        return Double.longBitsToDouble(sign |
+                                        (exponent + 0x0010000000000000L));
+                } else {
+                        return Double.longBitsToDouble(sign |
+                                        exponent | (mantissa + 1));
+                }
+        } else {
+                // we should decrease the mantissa
+                if (mantissa == 0L) {
+                        return Double.longBitsToDouble(sign |
+                                        (exponent - 0x0010000000000000L) |
+                                        0x000fffffffffffffL);
+                } else {
+                        return Double.longBitsToDouble(sign |
+                                        exponent | (mantissa - 1));
+                }
+        }
     }
 
     /**

Modified: commons/proper/math/branches/MATH_2_X/src/test/java/org/apache/commons/math/util/MathUtilsTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/branches/MATH_2_X/src/test/java/org/apache/commons/math/util/MathUtilsTest.java?rev=1070122&r1=1070121&r2=1070122&view=diff
==============================================================================
--- commons/proper/math/branches/MATH_2_X/src/test/java/org/apache/commons/math/util/MathUtilsTest.java (original)
+++ commons/proper/math/branches/MATH_2_X/src/test/java/org/apache/commons/math/util/MathUtilsTest.java Sat Feb 12 18:27:22 2011
@@ -315,6 +315,26 @@ public final class MathUtilsTest extends
         assertTrue(Double.isNaN(MathUtils.cosh(Double.NaN)));
     }
 
+    public void testEquals() {
+        double[] testArray = {
+            Double.NaN,
+            Double.POSITIVE_INFINITY,
+            Double.NEGATIVE_INFINITY,
+            1d,
+            0d };
+        for (int i = 0; i < testArray.length; i++) {
+            for (int j = 0; j < testArray.length; j++) {
+                if (i == j) {
+                    assertTrue(MathUtils.equals(testArray[i], testArray[j]));
+                    assertTrue(MathUtils.equals(testArray[j], testArray[i]));
+                } else {
+                    assertTrue(!MathUtils.equals(testArray[i], testArray[j]));
+                    assertTrue(!MathUtils.equals(testArray[j], testArray[i]));
+                }
+            }
+        }
+    }
+
     public void testEqualsIncludingNaN() {
         double[] testArray = {
             Double.NaN,
@@ -339,7 +359,7 @@ public final class MathUtilsTest extends
         assertTrue(MathUtils.equals(153.0000, 153.0000, .0625));
         assertTrue(MathUtils.equals(153.0000, 153.0625, .0625));
         assertTrue(MathUtils.equals(152.9375, 153.0000, .0625));
-        assertFalse(MathUtils.equals(Double.NaN, Double.NaN, 1.0));
+        assertTrue(MathUtils.equals(Double.NaN, Double.NaN, 1.0)); // This will change in 3.0
         assertTrue(MathUtils.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
         assertTrue(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1.0));
         assertFalse(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0));
@@ -394,6 +414,31 @@ public final class MathUtilsTest extends
         assertFalse(MathUtils.equals(Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, 100000));
     }
 
+    public void testEqualsWithAllowedUlps21() { // From 2.1
+        assertTrue(MathUtils.equals(153, 153, 1));
+
+        assertTrue(MathUtils.equals(153, 153.00000000000003, 1));
+        assertFalse(MathUtils.equals(153, 153.00000000000006, 1));
+        assertTrue(MathUtils.equals(153, 152.99999999999997, 1));
+        assertFalse(MathUtils.equals(153, 152.99999999999994, 1));
+
+        assertTrue(MathUtils.equals(-128, -127.99999999999999, 1));
+        assertFalse(MathUtils.equals(-128, -127.99999999999997, 1));
+        assertTrue(MathUtils.equals(-128, -128.00000000000003, 1));
+        assertFalse(MathUtils.equals(-128, -128.00000000000006, 1));
+
+        assertTrue(MathUtils.equals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1));
+        assertTrue(MathUtils.equals(Double.MAX_VALUE, Double.POSITIVE_INFINITY, 1));
+
+        assertTrue(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1));
+        assertTrue(MathUtils.equals(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY, 1));
+
+
+        assertTrue(MathUtils.equals(Double.NaN, Double.NaN, 1));
+
+        assertFalse(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 100000));
+    }
+
     public void testEqualsWithAllowedUlps() {
         assertTrue(MathUtils.equals(0.0, -0.0, 1));
 
@@ -427,7 +472,7 @@ public final class MathUtilsTest extends
         assertTrue(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 1));
         assertTrue(MathUtils.equals(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY, 1));
 
-        assertFalse(MathUtils.equals(Double.NaN, Double.NaN, 1));
+        assertTrue(MathUtils.equals(Double.NaN, Double.NaN, 1)); // This will change in 3.0
 
         assertFalse(MathUtils.equals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 100000));
     }
@@ -957,6 +1002,91 @@ public final class MathUtilsTest extends
         }
     }
 
+    public void testNextAfter() { // Test from Math 2.1
+        // 0x402fffffffffffff 0x404123456789abcd -> 4030000000000000
+        assertEquals(16.0, MathUtils.nextAfter(15.999999999999998, 34.27555555555555), 0.0);
+
+        // 0xc02fffffffffffff 0x404123456789abcd -> c02ffffffffffffe
+        assertEquals(-15.999999999999996, MathUtils.nextAfter(-15.999999999999998, 34.27555555555555), 0.0);
+
+        // 0x402fffffffffffff 0x400123456789abcd -> 402ffffffffffffe
+        assertEquals(15.999999999999996, MathUtils.nextAfter(15.999999999999998, 2.142222222222222), 0.0);
+
+        // 0xc02fffffffffffff 0x400123456789abcd -> c02ffffffffffffe
+        assertEquals(-15.999999999999996, MathUtils.nextAfter(-15.999999999999998, 2.142222222222222), 0.0);
+
+        // 0x4020000000000000 0x404123456789abcd -> 4020000000000001
+        assertEquals(8.000000000000002, MathUtils.nextAfter(8.0, 34.27555555555555), 0.0);
+
+        // 0xc020000000000000 0x404123456789abcd -> c01fffffffffffff
+        assertEquals(-7.999999999999999, MathUtils.nextAfter(-8.0, 34.27555555555555), 0.0);
+
+        // 0x4020000000000000 0x400123456789abcd -> 401fffffffffffff
+        assertEquals(7.999999999999999, MathUtils.nextAfter(8.0, 2.142222222222222), 0.0);
+
+        // 0xc020000000000000 0x400123456789abcd -> c01fffffffffffff
+        assertEquals(-7.999999999999999, MathUtils.nextAfter(-8.0, 2.142222222222222), 0.0);
+
+        // 0x3f2e43753d36a223 0x3f2e43753d36a224 -> 3f2e43753d36a224
+        assertEquals(2.308922399667661E-4, MathUtils.nextAfter(2.3089223996676606E-4, 2.308922399667661E-4), 0.0);
+
+        // 0x3f2e43753d36a223 0x3f2e43753d36a223 -> 3f2e43753d36a224
+        assertEquals(2.308922399667661E-4, MathUtils.nextAfter(2.3089223996676606E-4, 2.3089223996676606E-4), 0.0);
+
+        // 0x3f2e43753d36a223 0x3f2e43753d36a222 -> 3f2e43753d36a222
+        assertEquals(2.3089223996676603E-4, MathUtils.nextAfter(2.3089223996676606E-4, 2.3089223996676603E-4), 0.0);
+
+        // 0x3f2e43753d36a223 0xbf2e43753d36a224 -> 3f2e43753d36a222
+        assertEquals(2.3089223996676603E-4, MathUtils.nextAfter(2.3089223996676606E-4, -2.308922399667661E-4), 0.0);
+
+        // 0x3f2e43753d36a223 0xbf2e43753d36a223 -> 3f2e43753d36a222
+        assertEquals(2.3089223996676603E-4, MathUtils.nextAfter(2.3089223996676606E-4, -2.3089223996676606E-4), 0.0);
+
+        // 0x3f2e43753d36a223 0xbf2e43753d36a222 -> 3f2e43753d36a222
+        assertEquals(2.3089223996676603E-4, MathUtils.nextAfter(2.3089223996676606E-4, -2.3089223996676603E-4), 0.0);
+
+        // 0xbf2e43753d36a223 0x3f2e43753d36a224 -> bf2e43753d36a222
+        assertEquals(-2.3089223996676603E-4, MathUtils.nextAfter(-2.3089223996676606E-4, 2.308922399667661E-4), 0.0);
+
+        // 0xbf2e43753d36a223 0x3f2e43753d36a223 -> bf2e43753d36a222
+        assertEquals(-2.3089223996676603E-4, MathUtils.nextAfter(-2.3089223996676606E-4, 2.3089223996676606E-4), 0.0);
+
+        // 0xbf2e43753d36a223 0x3f2e43753d36a222 -> bf2e43753d36a222
+        assertEquals(-2.3089223996676603E-4, MathUtils.nextAfter(-2.3089223996676606E-4, 2.3089223996676603E-4), 0.0);
+
+        // 0xbf2e43753d36a223 0xbf2e43753d36a224 -> bf2e43753d36a224
+        assertEquals(-2.308922399667661E-4, MathUtils.nextAfter(-2.3089223996676606E-4, -2.308922399667661E-4), 0.0);
+
+        // 0xbf2e43753d36a223 0xbf2e43753d36a223 -> bf2e43753d36a224
+        assertEquals(-2.308922399667661E-4, MathUtils.nextAfter(-2.3089223996676606E-4, -2.3089223996676606E-4), 0.0);
+
+        // 0xbf2e43753d36a223 0xbf2e43753d36a222 -> bf2e43753d36a222
+        assertEquals(-2.3089223996676603E-4, MathUtils.nextAfter(-2.3089223996676606E-4, -2.3089223996676603E-4), 0.0);
+
+    }
+
+    public void testNextAfterSpecialCases() {
+        assertTrue(Double.isInfinite(MathUtils.nextAfter(Double.NEGATIVE_INFINITY, 0)));
+        assertTrue(Double.isInfinite(MathUtils.nextAfter(Double.POSITIVE_INFINITY, 0)));
+        assertTrue(Double.isNaN(MathUtils.nextAfter(Double.NaN, 0)));
+        assertTrue(Double.isInfinite(MathUtils.nextAfter(Double.MAX_VALUE, Double.POSITIVE_INFINITY)));
+        assertTrue(Double.isInfinite(MathUtils.nextAfter(-Double.MAX_VALUE, Double.NEGATIVE_INFINITY)));
+        assertEquals(Double.MIN_VALUE, MathUtils.nextAfter(0, 1), 0);
+        assertEquals(-Double.MIN_VALUE, MathUtils.nextAfter(0, -1), 0);
+        assertEquals(0, MathUtils.nextAfter(Double.MIN_VALUE, -1), 0);
+        assertEquals(0, MathUtils.nextAfter(-Double.MIN_VALUE, 1), 0);
+    }
+
+    public void testScalb() { // Math 2.1
+        assertEquals( 0.0, MathUtils.scalb(0.0, 5), 1.0e-15);
+        assertEquals(32.0, MathUtils.scalb(1.0, 5), 1.0e-15);
+        assertEquals(1.0 / 32.0, MathUtils.scalb(1.0,  -5), 1.0e-15);
+        assertEquals(Math.PI, MathUtils.scalb(Math.PI, 0), 1.0e-15);
+        assertTrue(Double.isInfinite(MathUtils.scalb(Double.POSITIVE_INFINITY, 1)));
+        assertTrue(Double.isInfinite(MathUtils.scalb(Double.NEGATIVE_INFINITY, 1)));
+        assertTrue(Double.isNaN(MathUtils.scalb(Double.NaN, 1)));
+    }
+
     public void testNormalizeAngle() {
         for (double a = -15.0; a <= 15.0; a += 0.1) {
             for (double b = -15.0; b <= 15.0; b += 0.2) {
@@ -1436,6 +1566,38 @@ public final class MathUtilsTest extends
         assertEquals(4, MathUtils.distanceInf(p1, p2));
     }
 
+    public void testCheckOrder21() { // Test from 2.1
+        MathUtils.checkOrder(new double[] {-15, -5.5, -1, 2, 15}, 1, true);
+        MathUtils.checkOrder(new double[] {-15, -5.5, -1, 2, 2}, 1, false);
+        MathUtils.checkOrder(new double[] {3, -5.5, -11, -27.5}, -1, true);
+        MathUtils.checkOrder(new double[] {3, 0, 0, -5.5, -11, -27.5}, -1, false);
+
+        try {
+            MathUtils.checkOrder(new double[] {-15, -5.5, -1, -1, 2, 15}, 1, true);
+            fail("an exception should have been thrown");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+        try {
+            MathUtils.checkOrder(new double[] {-15, -5.5, -1, -2, 2}, 1, false);
+            fail("an exception should have been thrown");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+        try {
+            MathUtils.checkOrder(new double[] {3, 3, -5.5, -11, -27.5}, -1, true);
+            fail("an exception should have been thrown");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+        try {
+            MathUtils.checkOrder(new double[] {3, -1, 0, -5.5, -11, -27.5}, -1, false);
+            fail("an exception should have been thrown");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
+
     public void testCheckOrder() {
         MathUtils.checkOrder(new double[] {-15, -5.5, -1, 2, 15},
                              MathUtils.OrderDirection.INCREASING, true);



Re: svn commit: r1070122 - in /commons/proper/math/branches/MATH_2_X/src: main/java/org/apache/commons/math/util/MathUtils.java test/java/org/apache/commons/math/util/MathUtilsTest.java

Posted by sebb AT ASF <se...@apache.org>.
On 12 February 2011 18:27,  <se...@apache.org> wrote:
> Author: sebb
> Date: Sat Feb 12 18:27:22 2011
> New Revision: 1070122
>
> URL: http://svn.apache.org/viewvc?rev=1070122&view=rev
> Log:
> Revert MathUtils to 2.1 behaviour.
> Update tests accordingly, and restore missing tests from 2.1 version
> Note: removed deprecation from methods that merely change behaviour in 3.0

It seemed wrong to deprecate a method that was not going to be
removed, but I won't veto restoring the deprecation if it is felt to
be more useful to do so.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org