You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by lu...@apache.org on 2011/01/20 23:33:56 UTC

svn commit: r1061551 - in /commons/proper/math/trunk/src: main/java/org/apache/commons/math/util/FastMath.java test/java/org/apache/commons/math/util/FastMathTest.java

Author: luc
Date: Thu Jan 20 22:33:56 2011
New Revision: 1061551

URL: http://svn.apache.org/viewvc?rev=1061551&view=rev
Log:
fixed behavior of nextAfter(double, double) for infinity,
added nextAfter(float, float) and nextUp(float)
JIRA: MATH-478

Modified:
    commons/proper/math/trunk/src/main/java/org/apache/commons/math/util/FastMath.java
    commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/FastMathTest.java

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/util/FastMath.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/util/FastMath.java?rev=1061551&r1=1061550&r2=1061551&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/util/FastMath.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/util/FastMath.java Thu Jan 20 22:33:56 2011
@@ -599,6 +599,14 @@ public class FastMath {
         return nextAfter(a, Double.POSITIVE_INFINITY);
     }
 
+    /** Compute next number towards positive infinity.
+     * @param a number to which neighbor should be computed
+     * @return neighbor of a towards positive infinity
+     */
+    public static float nextUp(final float a) {
+        return nextAfter(a, Float.POSITIVE_INFINITY);
+    }
+
     /** Returns a pseudo-random number between 0.0 and 1.0.
      * @return a random number between 0.0 and 1.0
      */
@@ -3356,8 +3364,16 @@ public class FastMath {
     public static double nextAfter(double d, double direction) {
 
         // handling of some important special cases
-        if (Double.isNaN(d) || Double.isInfinite(d)) {
+        if (Double.isNaN(d)) {
             return d;
+        } else if (Double.isInfinite(d)) {
+            if (d < direction) {
+                return -Double.MAX_VALUE;
+            } else if (direction < d) {
+                return Double.MAX_VALUE;
+            } else {
+                return d;
+            }
         } else if (d == 0) {
             return (direction < 0) ? -Double.MIN_VALUE : Double.MIN_VALUE;
         }
@@ -3393,6 +3409,65 @@ public class FastMath {
 
     }
 
+    /**
+     * Get the next machine representable number after a number, moving
+     * in the direction of another number.
+     * <p>
+     * If <code>direction</code> is greater than or equal to<code>d</code>,
+     * the smallest machine representable number strictly greater than
+     * <code>d</code> is returned; otherwise the largest representable number
+     * strictly less than <code>d</code> is returned.</p>
+     * <p>
+     * If <code>d</code> is NaN or Infinite, it is returned unchanged.</p>
+     *
+     * @param f base number
+     * @param direction (the only important thing is whether
+     * direction is greater or smaller than f)
+     * @return the next machine representable number in the specified direction
+     */
+    public static float nextAfter(float f, float direction) {
+
+        // handling of some important special cases
+        if (Float.isNaN(f)) {
+            return f;
+        } else if (Float.isInfinite(f)) {
+            if (f < direction) {
+                return -Float.MAX_VALUE;
+            } else if (direction < f) {
+                return Float.MAX_VALUE;
+            } else {
+                return f;
+            }
+        } else if (f == 0f) {
+            return (direction < 0f) ? -Float.MIN_VALUE : Float.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
+        int bits     = Float.floatToIntBits(f);
+        int sign     = bits & 0x80000000;
+        int exponent = bits & 0x7f800000;
+        int mantissa = bits & 0x007fffff;
+
+        if (f * (direction - f) >= 0f) {
+            // we should increase the mantissa
+            if (mantissa == 0x000fffff) {
+                return Float.intBitsToFloat(sign | (exponent + 0x00800000));
+            } else {
+                return Float.intBitsToFloat(sign | exponent | (mantissa + 1));
+            }
+        } else {
+            // we should decrease the mantissa
+            if (mantissa == 0) {
+                return Float.intBitsToFloat(sign | (exponent - 0x00800000) | 0x007fffff);
+            } else {
+                return Float.intBitsToFloat(sign | exponent | (mantissa - 1));
+            }
+        }
+
+    }
+
     /** Get the largest whole number smaller than x.
      * @param x number from which floor is requested
      * @return a double number f such that f is an integer f <= x < f + 1.0

Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/FastMathTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/FastMathTest.java?rev=1061551&r1=1061550&r2=1061551&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/FastMathTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/util/FastMathTest.java Thu Jan 20 22:33:56 2011
@@ -991,7 +991,7 @@ public class FastMathTest {
         }
         void check(Method mathMethod, double d, Object expected, Object actual, int entry){
             if (!expected.equals(actual)){
-                reportError(mathMethod.getName()+"(float "+d+") expected "+expected+" actual "+actual+ " entry "+entry);
+                reportError(mathMethod.getName()+"(double "+d+") expected "+expected+" actual "+actual+ " entry "+entry);
             }            
         }
     }