classpath
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Math.min


From: Eric Blake
Subject: Re: Math.min
Date: Fri, 10 Aug 2001 10:44:16 +0100

Here is a patch for the bugs in java.lang.Math.{max,min}, along with some
speed optimizations for abs.

--
Eric Blake, Elixent, Castlemead, Lwr Castle St., Bristol BS1 3AG, UK
address@hidden   tel:+44(0)117 917 5611

2001-08-10  Eric Blake  <address@hidden>

        * java/lang/Math.java (abs): optimize
        (min, max): fix bugs

Index: java/lang/Math.java
===================================================================
RCS file: /cvs/classpath/java/lang/Math.java,v
retrieving revision 1.6
diff -u -r1.6 Math.java
--- java/lang/Math.java 2000/03/16 23:31:30     1.6
+++ java/lang/Math.java 2001/08/10 09:41:27
@@ -1,5 +1,5 @@
 /* java.lang.Math
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 1998, 2001 Free Software Foundation, Inc.

 This file is part of GNU Classpath.

@@ -38,6 +38,7 @@
  *
  * @author Paul Fisher
  * @author John Keiser
+ * @author Eric Blake <address@hidden>
  * @since JDK1.1
  */
 public final class Math {
@@ -105,7 +106,9 @@
    * @return the absolute value.
    */
   public static float abs(float a) {
-    return Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a));
+    // avoid method call overhead, but treat -0.0 correctly
+    // return Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a));
+    return (a == 0) ? 0 : (a < 0) ? -a : a;
   }

   /**
@@ -115,7 +118,9 @@
    * @return the absolute value.
    */
   public static double abs(double a) {
-    return Double.longBitsToDouble((Double.doubleToLongBits(a) << 1) >>>
1);
+    // avoid method call overhead, but treat -0.0 correctly
+    // return Double.longBitsToDouble((Double.doubleToLongBits(a) << 1) >>>
1);
+    return (a == 0) ? 0 : (a < 0) ? -a : a;
   }

   /**
@@ -139,26 +144,38 @@
   }

   /**
-   * Return whichever argument is smaller.
+   * Return whichever argument is smaller. If either argument is NaN, the
+   * result is NaN, and when comparing 0 and -0, -0 is always smaller.
    * @param a the first number
    * @param b a second number
    * @return the smaller of the two numbers.
    */
   public static float min(float a, float b) {
-    if (a == 0.0f && b == 0.0f)        // return -0.0f, if a or b is -0.0f
-      return ((Float.floatToIntBits(a) >> 31) == 1) ? a : b;
+    if (Float.isNaN(a))
+      return a;
+    if (Float.isNaN(b))
+      return b;
+    // recall that -0.0 == 0.0, -0.0*0.0 is -0.0, 1/[+-]0 is [+-]Infinity
+    if (a == 0 && b == 0)
+      return (1 / (a * b) == Float.POSITIVE_INFINITY) ? a : -0.0f;
     return (a < b) ? a : b;
   }

   /**
-   * Return whichever argument is smaller.
+   * Return whichever argument is smaller. If either argument is NaN, the
+   * result is NaN, and when comparing 0 and -0, -0 is always smaller.
    * @param a the first number
    * @param b a second number
    * @return the smaller of the two numbers.
    */
   public static double min(double a, double b) {
-    if (a == 0.0d && b == 0.0d)        // return -0.0d, if a or b is -0.0d
-      return ((Double.doubleToLongBits(a) >> 63) == 1) ? a : b;
+    if (Double.isNaN(a))
+      return a;
+    if (Double.isNaN(b))
+      return b;
+    // recall that -0.0 == 0.0, -0.0*0.0 is -0.0, 1/[+-]0 is [+-]Infinity
+    if (a == 0 && b == 0)
+      return (1 / (a * b) == Double.POSITIVE_INFINITY) ? a : -0.0;
     return (a < b) ? a : b;
   }

@@ -183,26 +200,38 @@
   }

   /**
-   * Return whichever argument is larger.
+   * Return whichever argument is larger. If either argument is NaN, the
+   * result is NaN, and when comparing 0 and -0, 0 is always larger.
    * @param a the first number
    * @param b a second number
    * @return the larger of the two numbers.
    */
   public static float max(float a, float b) {
-    if (a == 0.0f && b == 0.0f)        // return +0.0f, if a or b is +0.0f
-      return ((Float.floatToIntBits(a) >> 31) == 0) ? a : b;
+    if (Float.isNaN(a))
+      return a;
+    if (Float.isNaN(b))
+      return b;
+    // recall that -0.0 == 0.0, -0.0*0.0 is -0.0, 1/[+-]0 is [+-]Infinity
+    if (a == 0 && b == 0)
+      return (1 / (a * b) == Float.POSITIVE_INFINITY) ? a : 0.0f;
     return (a > b) ? a : b;
   }

   /**
-   * Return whichever argument is larger.
+   * Return whichever argument is larger. If either argument is NaN, the
+   * result is NaN, and when comparing 0 and -0, 0 is always larger.
    * @param a the first number
    * @param b a second number
    * @return the larger of the two numbers.
    */
   public static double max(double a, double b) {
-    if (a == 0.0d && b == 0.0d)        // return +0.0d, if a or b is +0.0d
-      return ((Double.doubleToLongBits(a) >> 63) == 0) ? a : b;
+    if (Double.isNaN(a))
+      return a;
+    if (Double.isNaN(b))
+      return b;
+    // recall that -0.0 == 0.0, -0.0*0.0 is -0.0, 1/[+-]0 is [+-]Infinity
+    if (a == 0 && b == 0)
+      return (1 / (a * b) == Double.POSITIVE_INFINITY) ? a : 0.0;
     return (a > b) ? a : b;
   }





reply via email to

[Prev in Thread] Current Thread [Next in Thread]