commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From l..@apache.org
Subject svn commit: r1090820 - in /commons/proper/math/trunk/src: main/java/org/apache/commons/math/util/MathUtils.java site/xdoc/changes.xml test/java/org/apache/commons/math/util/MathUtilsTest.java
Date Sun, 10 Apr 2011 15:56:52 GMT
Author: luc
Date: Sun Apr 10 15:56:51 2011
New Revision: 1090820

URL: http://svn.apache.org/viewvc?rev=1090820&view=rev
Log:
Added a compareTo method to MathUtils that uses a number of ulps as a tolerance error, and
works well on all numbers, including normals, subnormals, signed zeroes, infinities and NaNs

Jira: MATH-557

Modified:
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/util/MathUtils.java
    commons/proper/math/trunk/src/site/xdoc/changes.xml
    commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/MathUtilsTest.java

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/util/MathUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/util/MathUtils.java?rev=1090820&r1=1090819&r2=1090820&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/util/MathUtils.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/util/MathUtils.java Sun
Apr 10 15:56:51 2011
@@ -400,7 +400,33 @@ public final class MathUtils {
         if (equals(x, y, eps)) {
             return 0;
         } else if (x < y) {
-          return -1;
+            return -1;
+        }
+        return 1;
+    }
+
+    /**
+     * Compares two numbers given some amount of allowed error.
+     * Two float numbers are considered equal if there are {@code (maxUlps - 1)}
+     * (or fewer) floating point numbers between them, i.e. two adjacent floating
+     * point numbers are considered equal.
+     * Adapted from <a
+     * href="http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm">
+     * Bruce Dawson</a>
+     *
+     * @param x first value
+     * @param y second value
+     * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
+     * values between {@code x} and {@code y}.
+     * @return <ul><li>0 if  {@link #equals(double, double, int) equals(x, y,
maxUlps)}</li>
+     *       <li>&lt; 0 if !{@link #equals(double, double, int) equals(x, y, maxUlps)}
&amp;&amp; x &lt; y</li>
+     *       <li>> 0 if !{@link #equals(double, double, int) equals(x, y, maxUlps)}
&amp;&amp; x > y</li></ul>
+     */
+    public static int compareTo(final double x, final double y, final int maxUlps) {
+        if (equals(x, y, maxUlps)) {
+            return 0;
+        } else if (x < y) {
+            return -1;
         }
         return 1;
     }

Modified: commons/proper/math/trunk/src/site/xdoc/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/site/xdoc/changes.xml?rev=1090820&r1=1090819&r2=1090820&view=diff
==============================================================================
--- commons/proper/math/trunk/src/site/xdoc/changes.xml (original)
+++ commons/proper/math/trunk/src/site/xdoc/changes.xml Sun Apr 10 15:56:51 2011
@@ -52,6 +52,11 @@ The <action> type attribute can be add,u
     If the output is not quite correct, check for invisible trailing spaces!
      -->
     <release version="3.0" date="TBD" description="TBD">
+      <action dev="luc" type="add" issue="MATH-557" >
+        Added a compareTo method to MathUtils that uses a number of ulps as a
+        tolerance error, and works well on all numbers, including normals, subnormals,
+        signed zeroes, infinities and NaNs.
+      </action>
       <action dev="luc" type="fix" issue="MATH-434" due-to="Thomas Neidhart">
         Fixed two errors in simplex solver when entries are close together or
         when variables are not restricted to non-negative.

Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/MathUtilsTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/MathUtilsTest.java?rev=1090820&r1=1090819&r2=1090820&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/MathUtilsTest.java
(original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/MathUtilsTest.java
Sun Apr 10 15:56:51 2011
@@ -25,7 +25,6 @@ import org.apache.commons.math.TestUtils
 import org.apache.commons.math.exception.NonMonotonousSequenceException;
 import org.apache.commons.math.exception.MathIllegalArgumentException;
 import org.apache.commons.math.exception.MathArithmeticException;
-import org.apache.commons.math.exception.MathRuntimeException;
 import org.apache.commons.math.exception.NotFiniteNumberException;
 import org.apache.commons.math.exception.NullArgumentException;
 import org.apache.commons.math.exception.util.LocalizedFormats;
@@ -308,10 +307,50 @@ public final class MathUtilsTest {
     }
 
     @Test
-    public void testCompareTo() {
-      Assert.assertEquals(0, MathUtils.compareTo(152.33, 152.32, .011));
-      Assert.assertTrue(MathUtils.compareTo(152.308, 152.32, .011) < 0);
-      Assert.assertTrue(MathUtils.compareTo(152.33, 152.318, .011) > 0);
+    public void testCompareToEpsilon() {
+        Assert.assertEquals(0, MathUtils.compareTo(152.33, 152.32, .011));
+        Assert.assertTrue(MathUtils.compareTo(152.308, 152.32, .011) < 0);
+        Assert.assertTrue(MathUtils.compareTo(152.33, 152.318, .011) > 0);
+        Assert.assertEquals(0, MathUtils.compareTo(Double.MIN_VALUE, +0.0, Double.MIN_VALUE));
+        Assert.assertEquals(0, MathUtils.compareTo(Double.MIN_VALUE, -0.0, Double.MIN_VALUE));
+    }
+
+    @Test
+    public void testCompareToMaxUlps() {
+        double a     = 152.32;
+        double delta = FastMath.ulp(a);
+        for (int i = 0; i <= 10; ++i) {
+            if (i <= 5) {
+                Assert.assertEquals( 0, MathUtils.compareTo(a, a + i * delta, 5));
+                Assert.assertEquals( 0, MathUtils.compareTo(a, a - i * delta, 5));
+            } else {
+                Assert.assertEquals(-1, MathUtils.compareTo(a, a + i * delta, 5));
+                Assert.assertEquals(+1, MathUtils.compareTo(a, a - i * delta, 5));
+            }
+        }
+
+        Assert.assertEquals( 0, MathUtils.compareTo(-0.0, 0.0, 0));
+
+        Assert.assertEquals(-1, MathUtils.compareTo(-Double.MIN_VALUE, -0.0, 0));
+        Assert.assertEquals( 0, MathUtils.compareTo(-Double.MIN_VALUE, -0.0, 1));
+        Assert.assertEquals(-1, MathUtils.compareTo(-Double.MIN_VALUE, +0.0, 0));
+        Assert.assertEquals( 0, MathUtils.compareTo(-Double.MIN_VALUE, +0.0, 1));
+
+        Assert.assertEquals(+1, MathUtils.compareTo( Double.MIN_VALUE, -0.0, 0));
+        Assert.assertEquals( 0, MathUtils.compareTo( Double.MIN_VALUE, -0.0, 1));
+        Assert.assertEquals(+1, MathUtils.compareTo( Double.MIN_VALUE, +0.0, 0));
+        Assert.assertEquals( 0, MathUtils.compareTo( Double.MIN_VALUE, +0.0, 1));
+
+        Assert.assertEquals(-1, MathUtils.compareTo(-Double.MIN_VALUE, Double.MIN_VALUE,
0));
+        Assert.assertEquals(-1, MathUtils.compareTo(-Double.MIN_VALUE, Double.MIN_VALUE,
1));
+        Assert.assertEquals( 0, MathUtils.compareTo(-Double.MIN_VALUE, Double.MIN_VALUE,
2));
+
+        Assert.assertEquals( 0, MathUtils.compareTo(Double.MAX_VALUE, Double.POSITIVE_INFINITY,
1));
+        Assert.assertEquals(-1, MathUtils.compareTo(Double.MAX_VALUE, Double.POSITIVE_INFINITY,
0));
+
+        Assert.assertEquals(+1, MathUtils.compareTo(Double.MAX_VALUE, Double.NaN, Integer.MAX_VALUE));
+        Assert.assertEquals(+1, MathUtils.compareTo(Double.NaN, Double.MAX_VALUE, Integer.MAX_VALUE));
+
     }
 
     @Test



Mime
View raw message