changeset 9885:15b5ea29bab8

8032016: Optimizations of Math.next{After,Up}({float,double}) Summary: Rearrange code to handle the more common and costly case first. Reviewed-by: darcy Contributed-by: Jeff Hain <jeffhain@rocketmail.com>
author bpb
date Fri, 02 May 2014 11:25:07 -0700
parents 94776e898d0e
children 0619a50c0e2b d062f1046081
files src/share/classes/java/lang/Math.java
diffstat 1 files changed, 68 insertions(+), 96 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/lang/Math.java	Fri May 02 10:05:57 2014 -0400
+++ b/src/share/classes/java/lang/Math.java	Fri May 02 11:25:07 2014 -0700
@@ -1904,51 +1904,36 @@
          * are naturally handled without any additional testing
          */
 
-        // First check for NaN values
-        if (Double.isNaN(start) || Double.isNaN(direction)) {
-            // return a NaN derived from the input NaN(s)
-            return start + direction;
+        /*
+         * IEEE 754 floating-point numbers are lexicographically
+         * ordered if treated as signed-magnitude integers.
+         * Since Java's integers are two's complement,
+         * incrementing the two's complement representation of a
+         * logically negative floating-point value *decrements*
+         * the signed-magnitude representation. Therefore, when
+         * the integer representation of a floating-point value
+         * is negative, the adjustment to the representation is in
+         * the opposite direction from what would initially be expected.
+         */
+
+        // Branch to descending case first as it is more costly than ascending
+        // case due to start != 0.0d conditional.
+        if (start > direction) { // descending
+            if (start != 0.0d) {
+                final long transducer = Double.doubleToRawLongBits(start);
+                return Double.longBitsToDouble(transducer + ((transducer > 0L) ? -1L : 1L));
+            } else { // start == 0.0d && direction < 0.0d
+                return -Double.MIN_VALUE;
+            }
+        } else if (start < direction) { // ascending
+            // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0)
+            // then bitwise convert start to integer.
+            final long transducer = Double.doubleToRawLongBits(start + 0.0d);
+            return Double.longBitsToDouble(transducer + ((transducer >= 0L) ? 1L : -1L));
         } else if (start == direction) {
             return direction;
-        } else {        // start > direction or start < direction
-            // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0)
-            // then bitwise convert start to integer.
-            long transducer = Double.doubleToRawLongBits(start + 0.0d);
-
-            /*
-             * IEEE 754 floating-point numbers are lexicographically
-             * ordered if treated as signed- magnitude integers .
-             * Since Java's integers are two's complement,
-             * incrementing" the two's complement representation of a
-             * logically negative floating-point value *decrements*
-             * the signed-magnitude representation. Therefore, when
-             * the integer representation of a floating-point values
-             * is less than zero, the adjustment to the representation
-             * is in the opposite direction than would be expected at
-             * first .
-             */
-            if (direction > start) { // Calculate next greater value
-                transducer = transducer + (transducer >= 0L ? 1L:-1L);
-            } else  { // Calculate next lesser value
-                assert direction < start;
-                if (transducer > 0L)
-                    --transducer;
-                else
-                    if (transducer < 0L )
-                        ++transducer;
-                    /*
-                     * transducer==0, the result is -MIN_VALUE
-                     *
-                     * The transition from zero (implicitly
-                     * positive) to the smallest negative
-                     * signed magnitude value must be done
-                     * explicitly.
-                     */
-                    else
-                        transducer = DoubleConsts.SIGN_BIT_MASK | 1L;
-            }
-
-            return Double.longBitsToDouble(transducer);
+        } else { // isNaN(start) || isNaN(direction)
+            return start + direction;
         }
     }
 
@@ -2003,51 +1988,36 @@
          * are naturally handled without any additional testing
          */
 
-        // First check for NaN values
-        if (Float.isNaN(start) || Double.isNaN(direction)) {
-            // return a NaN derived from the input NaN(s)
-            return start + (float)direction;
+        /*
+         * IEEE 754 floating-point numbers are lexicographically
+         * ordered if treated as signed-magnitude integers.
+         * Since Java's integers are two's complement,
+         * incrementing the two's complement representation of a
+         * logically negative floating-point value *decrements*
+         * the signed-magnitude representation. Therefore, when
+         * the integer representation of a floating-point value
+         * is negative, the adjustment to the representation is in
+         * the opposite direction from what would initially be expected.
+         */
+
+        // Branch to descending case first as it is more costly than ascending
+        // case due to start != 0.0f conditional.
+        if (start > direction) { // descending
+            if (start != 0.0f) {
+                final int transducer = Float.floatToRawIntBits(start);
+                return Float.intBitsToFloat(transducer + ((transducer > 0) ? -1 : 1));
+            } else { // start == 0.0f && direction < 0.0f
+                return -Float.MIN_VALUE;
+            }
+        } else if (start < direction) { // ascending
+            // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0)
+            // then bitwise convert start to integer.
+            final int transducer = Float.floatToRawIntBits(start + 0.0f);
+            return Float.intBitsToFloat(transducer + ((transducer >= 0) ? 1 : -1));
         } else if (start == direction) {
             return (float)direction;
-        } else {        // start > direction or start < direction
-            // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0)
-            // then bitwise convert start to integer.
-            int transducer = Float.floatToRawIntBits(start + 0.0f);
-
-            /*
-             * IEEE 754 floating-point numbers are lexicographically
-             * ordered if treated as signed- magnitude integers .
-             * Since Java's integers are two's complement,
-             * incrementing" the two's complement representation of a
-             * logically negative floating-point value *decrements*
-             * the signed-magnitude representation. Therefore, when
-             * the integer representation of a floating-point values
-             * is less than zero, the adjustment to the representation
-             * is in the opposite direction than would be expected at
-             * first.
-             */
-            if (direction > start) {// Calculate next greater value
-                transducer = transducer + (transducer >= 0 ? 1:-1);
-            } else  { // Calculate next lesser value
-                assert direction < start;
-                if (transducer > 0)
-                    --transducer;
-                else
-                    if (transducer < 0 )
-                        ++transducer;
-                    /*
-                     * transducer==0, the result is -MIN_VALUE
-                     *
-                     * The transition from zero (implicitly
-                     * positive) to the smallest negative
-                     * signed magnitude value must be done
-                     * explicitly.
-                     */
-                    else
-                        transducer = FloatConsts.SIGN_BIT_MASK | 1;
-            }
-
-            return Float.intBitsToFloat(transducer);
+        } else { // isNaN(start) || isNaN(direction)
+            return start + (float)direction;
         }
     }
 
@@ -2077,12 +2047,13 @@
      * @since 1.6
      */
     public static double nextUp(double d) {
-        if( Double.isNaN(d) || d == Double.POSITIVE_INFINITY)
+        // Use a single conditional and handle the likely cases first.
+        if (d < Double.POSITIVE_INFINITY) {
+            // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0).
+            final long transducer = Double.doubleToRawLongBits(d + 0.0D);
+            return Double.longBitsToDouble(transducer + ((transducer >= 0L) ? 1L : -1L));
+        } else { // d is NaN or +Infinity
             return d;
-        else {
-            d += 0.0d;
-            return Double.longBitsToDouble(Double.doubleToRawLongBits(d) +
-                                           ((d >= 0.0d)?+1L:-1L));
         }
     }
 
@@ -2112,12 +2083,13 @@
      * @since 1.6
      */
     public static float nextUp(float f) {
-        if( Float.isNaN(f) || f == FloatConsts.POSITIVE_INFINITY)
+        // Use a single conditional and handle the likely cases first.
+        if (f < Float.POSITIVE_INFINITY) {
+            // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0).
+            final int transducer = Float.floatToRawIntBits(f + 0.0F);
+            return Float.intBitsToFloat(transducer + ((transducer >= 0) ? 1 : -1));
+        } else { // f is NaN or +Infinity
             return f;
-        else {
-            f += 0.0f;
-            return Float.intBitsToFloat(Float.floatToRawIntBits(f) +
-                                        ((f >= 0.0f)?+1:-1));
         }
     }