classpath-patches
[Top][All Lists]
Advanced

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

[cp-patches] Patch: FYI: Double.toHexString and Float.toHexString


From: Tom Tromey
Subject: [cp-patches] Patch: FYI: Double.toHexString and Float.toHexString
Date: 07 Dec 2005 13:09:40 -0700
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3.50

I'm checking this in on the trunk.

This adds the new 1.5 methods Double.toHexString and
Float.toHexString.  I wrote Mauve tests for both of these.  (BTW,
adding a new Mauve test file from Eclipse is super easy... I forgot
how easy it is when all the boilerplate is written for you, even
though I added the templates :-)

The code in both classes is pretty much identical, aside from a few
constants.

Tom

2005-12-07  Tom Tromey  <address@hidden>

        * java/lang/Float.java (toHexString): New method.
        * java/lang/Double.java (toHexString): New method.

Index: java/lang/Double.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/lang/Double.java,v
retrieving revision 1.40
diff -u -r1.40 Double.java
--- java/lang/Double.java       18 Sep 2005 23:00:24 -0000      1.40
+++ java/lang/Double.java       7 Dec 2005 20:08:13 -0000
@@ -173,6 +173,81 @@
   }
 
   /**
+   * Convert a double value to a hexadecimal string.  This converts as
+   * follows:
+   * <ul>
+   * <li> A NaN value is converted to the string "NaN".
+   * <li> Positive infinity is converted to the string "Infinity".
+   * <li> Negative infinity is converted to the string "-Infinity".
+   * <li> For all other values, the first character of the result is '-'
+   * if the value is negative.  This is followed by '0x1.' if the
+   * value is normal, and '0x0.' if the value is denormal.  This is
+   * then followed by a (lower-case) hexadecimal representation of the
+   * mantissa, with leading zeros as required for denormal values.
+   * The next character is a 'p', and this is followed by a decimal
+   * representation of the unbiased exponent.
+   * </ul>
+   * @param d the double value
+   * @return the hexadecimal string representation
+   * @since 1.5
+   */
+  public static String toHexString(double d)
+  {
+    if (isNaN(d))
+      return "NaN";
+    if (isInfinite(d))
+      return d < 0 ? "-Infinity" : "Infinity";
+
+    long bits = doubleToLongBits(d);
+    StringBuilder result = new StringBuilder();
+    
+    if (bits < 0)
+      result.append('-');
+    result.append("0x");
+
+    final int mantissaBits = 52;
+    final int exponentBits = 11;
+    long mantMask = (1L << mantissaBits) - 1;
+    long mantissa = bits & mantMask;
+    long expMask = (1L << exponentBits) - 1;
+    long exponent = (bits >>> mantissaBits) & expMask;
+
+    result.append(exponent == 0 ? '0' : '1');
+    result.append('.');
+    result.append(Long.toHexString(mantissa));
+    if (exponent == 0 && mantissa != 0)
+      {
+        // Treat denormal specially by inserting '0's to make
+        // the length come out right.  The constants here are
+        // to account for things like the '0x'.
+        int offset = 4 + ((bits < 0) ? 1 : 0);
+        // The silly +3 is here to keep the code the same between
+        // the Float and Double cases.  In Float the value is
+        // not a multiple of 4.
+        int desiredLength = offset + (mantissaBits + 3) / 4;
+        while (result.length() < desiredLength)
+          result.insert(offset, '0');
+      }
+    result.append('p');
+    if (exponent == 0 && mantissa == 0)
+      {
+        // Zero, so do nothing special.
+      }
+    else
+      {
+        // Apply bias.
+        boolean denormal = exponent == 0;
+        exponent -= (1 << (exponentBits - 1)) - 1;
+        // Handle denormal.
+        if (denormal)
+          ++exponent;
+      }
+
+    result.append(Long.toString(exponent));
+    return result.toString();
+  }
+
+  /**
    * Returns a <code>Double</code> object wrapping the value.
    * In contrast to the <code>Double</code> constructor, this method
    * may cache some values.  It is used by boxing conversion.
Index: java/lang/Float.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/lang/Float.java,v
retrieving revision 1.33
diff -u -r1.33 Float.java
--- java/lang/Float.java        18 Sep 2005 23:00:24 -0000      1.33
+++ java/lang/Float.java        7 Dec 2005 20:08:13 -0000
@@ -183,6 +183,83 @@
   }
 
   /**
+   * Convert a float value to a hexadecimal string.  This converts as
+   * follows:
+   * <ul>
+   * <li> A NaN value is converted to the string "NaN".
+   * <li> Positive infinity is converted to the string "Infinity".
+   * <li> Negative infinity is converted to the string "-Infinity".
+   * <li> For all other values, the first character of the result is '-'
+   * if the value is negative.  This is followed by '0x1.' if the
+   * value is normal, and '0x0.' if the value is denormal.  This is
+   * then followed by a (lower-case) hexadecimal representation of the
+   * mantissa, with leading zeros as required for denormal values.
+   * The next character is a 'p', and this is followed by a decimal
+   * representation of the unbiased exponent.
+   * </ul>
+   * @param f the float value
+   * @return the hexadecimal string representation
+   * @since 1.5
+   */
+  public static String toHexString(float f)
+  {
+    if (isNaN(f))
+      return "NaN";
+    if (isInfinite(f))
+      return f < 0 ? "-Infinity" : "Infinity";
+
+    int bits = floatToIntBits(f);
+    StringBuilder result = new StringBuilder();
+    
+    if (bits < 0)
+      result.append('-');
+    result.append("0x");
+
+    final int mantissaBits = 23;
+    final int exponentBits = 8;
+    int mantMask = (1 << mantissaBits) - 1;
+    int mantissa = bits & mantMask;
+    int expMask = (1 << exponentBits) - 1;
+    int exponent = (bits >>> mantissaBits) & expMask;
+
+    result.append(exponent == 0 ? '0' : '1');
+    result.append('.');
+    // For Float only, we have to adjust the mantissa.
+    mantissa <<= 1;
+    result.append(Integer.toHexString(mantissa));
+    if (exponent == 0 && mantissa != 0)
+      {
+        // Treat denormal specially by inserting '0's to make
+        // the length come out right.  The constants here are
+        // to account for things like the '0x'.
+        int offset = 4 + ((bits < 0) ? 1 : 0);
+        // The silly +3 is here to keep the code the same between
+        // the Float and Double cases.  In Float the value is
+        // not a multiple of 4.
+        int desiredLength = offset + (mantissaBits + 3) / 4;
+        while (result.length() < desiredLength)
+          result.insert(offset, '0');
+      }
+    result.append('p');
+    if (exponent == 0 && mantissa == 0)
+      {
+        // Zero, so do nothing special.
+      }
+    else
+      {
+        // Apply bias.
+        boolean denormal = exponent == 0;
+        exponent -= (1 << (exponentBits - 1)) - 1;
+        // Handle denormal.
+        if (denormal)
+          ++exponent;
+      }
+
+    result.append(Integer.toString(exponent));
+    return result.toString();
+  }
+
+  /**
    * Creates a new <code>Float</code> object using the <code>String</code>.
    *
    * @param s the <code>String</code> to convert




reply via email to

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