src/share/classes/java/lang/Long.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -23,10 +23,12 @@
  * questions.
  */
 
 package java.lang;
 
+import java.math.*;
+
 /**
  * The {@code Long} class wraps a value of the primitive type {@code
  * long} in an object. An object of type {@code Long} contains a
  * single field whose type is {@code long}.
  *

@@ -138,23 +140,106 @@
 
         return new String(buf, charPos, (65 - charPos));
     }
 
     /**
+     * Returns an unsigned string representation of the first argument
+     * in the radix specified by the second argument.
+     *
+     * <p>If the radix is smaller than {@code Character.MIN_RADIX}
+     * or larger than {@code Character.MAX_RADIX}, then the radix
+     * {@code 10} is used instead.
+     *
+     * <p>Note that since the first argument is treated as an unsigned
+     * value, no leading sign character is printed.
+     *
+     * <p>If the magnitude is zero, it is represented by a single zero
+     * character {@code '0'} (<code>'&#92;u0030'</code>); otherwise,
+     * the first character of the representation of the magnitude will
+     * not be the zero character.
+     *
+     * <p>The characters used as digits and the behavior of radixes
+     * is the same as {@link #toString(long, int) toString}.
+     *
+     * @param   i       an integer to be converted to an unsigned string.
+     * @param   radix   the radix to use in the string representation.
+     * @return  an unsigned string representation of the argument in the specified radix.
+     * @see     #toString(long, int)
+     * @since 1.8
+     */
+    public static String toUnsignedString(long i, int radix) {
+        if (i >= 0)
+            return toString(i, radix);
+        else {
+            switch (radix) {
+            case 2:
+                return toBinaryString(i);
+
+            case 4:
+                return toUnsignedString0(i, 2);
+
+            case 8:
+                return toOctalString(i);
+
+            case 10:
+                /*
+                 * We can get the effect of an unsigned division by 10
+                 * on a long value by first shifting right, yielding a
+                 * positive value, and then dividing by 5.  This
+                 * allows the last digit and preceding digits to be
+                 * isolated more quickly than by an initial conversion
+                 * to BigInteger.
+                 */
+                long quot = (i >>> 1) / 5;
+                long rem = i - quot * 10;
+                return toString(quot) + rem;
+
+            case 16:
+                return toHexString(i);
+
+            case 32:
+                return toUnsignedString0(i, 5);
+
+            default:
+                return toUnsignedBigInteger(i).toString(radix);
+            }
+        }
+    }
+
+    /**
+     * Return a BigInteger equal to the unsigned value of the
+     * argument.
+     */
+    private static BigInteger toUnsignedBigInteger(long i) {
+        int upper = (int) ((i >> 32) & 0xffffffff);
+        int lower = (int) i;
+
+         // return (upper << 32) + lower
+        return (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft(32).
+            add(BigInteger.valueOf(Integer.toUnsignedLong(lower)));
+    }
+
+    /**
      * Returns a string representation of the {@code long}
      * argument as an unsigned integer in base&nbsp;16.
      *
      * <p>The unsigned {@code long} value is the argument plus
      * 2<sup>64</sup> if the argument is negative; otherwise, it is
      * equal to the argument.  This value is converted to a string of
      * ASCII digits in hexadecimal (base&nbsp;16) with no extra
-     * leading {@code 0}s.  If the unsigned magnitude is zero, it
-     * is represented by a single zero character {@code '0'}
-     * (<code>'&#92;u0030'</code>); otherwise, the first character of
-     * the representation of the unsigned magnitude will not be the
-     * zero character. The following characters are used as
-     * hexadecimal digits:
+     * leading {@code 0}s.
+     *
+     * <p>The value of the argument can be recovered from the returned
+     * string {@code s} by calling {@link
+     * Long#parseUnsignedLong(String, int) Long.parseUnsignedLong(s,
+     * 16)}.
+     *
+     * <p>If the unsigned magnitude is zero, it is represented by a
+     * single zero character {@code '0'} (<code>'&#92;u0030'</code>);
+     * otherwise, the first character of the representation of the
+     * unsigned magnitude will not be the zero character. The
+     * following characters are used as hexadecimal digits:
      *
      * <blockquote>
      *  {@code 0123456789abcdef}
      * </blockquote>
      *

@@ -170,14 +255,16 @@
      *
      * @param   i   a {@code long} to be converted to a string.
      * @return  the string representation of the unsigned {@code long}
      *          value represented by the argument in hexadecimal
      *          (base&nbsp;16).
+     * @see #parseUnsignedLong(String, int)
+     * @see #toUnsignedString(long, int)
      * @since   JDK 1.0.2
      */
     public static String toHexString(long i) {
-        return toUnsignedString(i, 4);
+        return toUnsignedString0(i, 4);
     }
 
     /**
      * Returns a string representation of the {@code long}
      * argument as an unsigned integer in base&nbsp;8.

@@ -186,16 +273,20 @@
      * 2<sup>64</sup> if the argument is negative; otherwise, it is
      * equal to the argument.  This value is converted to a string of
      * ASCII digits in octal (base&nbsp;8) with no extra leading
      * {@code 0}s.
      *
+     * <p>The value of the argument can be recovered from the returned
+     * string {@code s} by calling {@link
+     * Long#parseUnsignedLong(String, int) Long.parseUnsignedLong(s,
+     * 8)}.
+     *
      * <p>If the unsigned magnitude is zero, it is represented by a
-     * single zero character {@code '0'}
-     * (<code>'&#92;u0030'</code>); otherwise, the first character of
-     * the representation of the unsigned magnitude will not be the
-     * zero character. The following characters are used as octal
-     * digits:
+     * single zero character {@code '0'} (<code>'&#92;u0030'</code>);
+     * otherwise, the first character of the representation of the
+     * unsigned magnitude will not be the zero character. The
+     * following characters are used as octal digits:
      *
      * <blockquote>
      *  {@code 01234567}
      * </blockquote>
      *

@@ -203,45 +294,55 @@
      * <code>'&#92;u0037'</code>.
      *
      * @param   i   a {@code long} to be converted to a string.
      * @return  the string representation of the unsigned {@code long}
      *          value represented by the argument in octal (base&nbsp;8).
+     * @see #parseUnsignedLong(String, int)
+     * @see #toUnsignedString(long, int)
      * @since   JDK 1.0.2
      */
     public static String toOctalString(long i) {
-        return toUnsignedString(i, 3);
+        return toUnsignedString0(i, 3);
     }
 
     /**
      * Returns a string representation of the {@code long}
      * argument as an unsigned integer in base&nbsp;2.
      *
      * <p>The unsigned {@code long} value is the argument plus
      * 2<sup>64</sup> if the argument is negative; otherwise, it is
      * equal to the argument.  This value is converted to a string of
      * ASCII digits in binary (base&nbsp;2) with no extra leading
-     * {@code 0}s.  If the unsigned magnitude is zero, it is
-     * represented by a single zero character {@code '0'}
-     * (<code>'&#92;u0030'</code>); otherwise, the first character of
-     * the representation of the unsigned magnitude will not be the
-     * zero character. The characters {@code '0'}
-     * (<code>'&#92;u0030'</code>) and {@code '1'}
-     * (<code>'&#92;u0031'</code>) are used as binary digits.
+     * {@code 0}s.
+     *
+     * <p>The value of the argument can be recovered from the returned
+     * string {@code s} by calling {@link
+     * Long#parseUnsignedLong(String, int) Long.parseUnsignedLong(s,
+     * 2)}.
+     *
+     * <p>If the unsigned magnitude is zero, it is represented by a
+     * single zero character {@code '0'} (<code>'&#92;u0030'</code>);
+     * otherwise, the first character of the representation of the
+     * unsigned magnitude will not be the zero character. The
+     * characters {@code '0'} (<code>'&#92;u0030'</code>) and {@code
+     * '1'} (<code>'&#92;u0031'</code>) are used as binary digits.
      *
      * @param   i   a {@code long} to be converted to a string.
      * @return  the string representation of the unsigned {@code long}
      *          value represented by the argument in binary (base&nbsp;2).
+     * @see #parseUnsignedLong(String, int)
+     * @see #toUnsignedString(long, int)
      * @since   JDK 1.0.2
      */
     public static String toBinaryString(long i) {
-        return toUnsignedString(i, 1);
+        return toUnsignedString0(i, 1);
     }
 
     /**
      * Convert the integer to an unsigned number.
      */
-    private static String toUnsignedString(long i, int shift) {
+    private static String toUnsignedString0(long i, int shift) {
         char[] buf = new char[64];
         int charPos = 64;
         int radix = 1 << shift;
         long mask = radix - 1;
         do {

@@ -269,10 +370,27 @@
         getChars(i, size, buf);
         return new String(0, size, buf);
     }
 
     /**
+     * Returns an unsigned string representation of the argument.
+     *
+     * The argument is converted to unsigned decimal representation
+     * and returned as a string exactly as if the argument and radix
+     * 10 were given as arguments to the {@link #toUnsignedString(long,
+     * int)} method.
+     *
+     * @param   i  an integer to be converted to an unsigned string.
+     * @return  an unsigned string representation of the argument.
+     * @see     #toUnsignedString(long, int)
+     * @since 1.8
+     */
+    public static String toUnsignedString(long i) {
+        return toUnsignedString(i, 10);
+    }
+
+    /**
      * Places characters representing the integer i into the
      * character array buf. The characters are placed into
      * the buffer backwards starting with the least significant
      * digit at the specified index (exclusive), and working
      * backwards from there.

@@ -483,10 +601,109 @@
     public static long parseLong(String s) throws NumberFormatException {
         return parseLong(s, 10);
     }
 
     /**
+     * Parses the string argument as an unsigned integer in the radix
+     * specified by the second argument.
+     *
+     * The characters in the string must all be digits of the
+     * specified radix (as determined by whether {@link
+     * java.lang.Character#digit(char, int)} returns a nonnegative
+     * value), except that the first character may be an ASCII plus
+     * sign {@code '+'} (<code>'&#92;u002B'</code>). The resulting
+     * integer value is returned.
+     *
+     * <p>An exception of type {@code NumberFormatException} is
+     * thrown if any of the following situations occurs:
+     * <ul>
+     * <li>The first argument is {@code null} or is a string of
+     * length zero.
+     *
+     * <li>The radix is either smaller than
+     * {@link java.lang.Character#MIN_RADIX} or
+     * larger than {@link java.lang.Character#MAX_RADIX}.
+     *
+     * <li>Any character of the string is not a digit of the specified
+     * radix, except that the first character may be a plus sign
+     * {@code '+'} (<code>'&#92;u002B'</code>) provided that the
+     * string is longer than length 1.
+     *
+     * <li>The value represented by the string is larger than the
+     * largest unsigned {@code long}, 2<sup>64</sup>-1.
+     *
+     * </ul>
+     *
+     *
+     * @param      s   the {@code String} containing the unsigned integer
+     *                  representation to be parsed
+     * @param      radix   the radix to be used while parsing {@code s}.
+     * @return     the integer represented by the string argument in the
+     *             specified radix.
+     * @throws     NumberFormatException if the {@code String}
+     *             does not contain a parsable {@code long}.
+     * @since 1.8
+     */
+    public static long parseUnsignedLong(String s, int radix)
+                throws NumberFormatException {
+        if (s == null)  {
+            throw new NumberFormatException("null");
+        }
+
+        int len = s.length();
+        if (len > 0) {
+            char firstChar = s.charAt(0);
+            if (firstChar == '-') {
+                throw new 
+                    NumberFormatException(String.format("Illegal leading minus sign " +
+                                                       "on unsigned string %s.", s));
+            } else {
+                if (len <= 12 || // Long.MAX_VALUE in Character.MAX_RADIX is 13 digits
+                    (radix == 10 && len <= 18) ) { // Long.MAX_VALUE in base 10 is 19 digits
+                    return parseLong(s, radix); 
+                }
+
+                // For simplicty, use BigInteger for parsing
+                BigInteger bi = new BigInteger(s, radix);
+
+                // Largest *unsigned* value is all ones in binary
+                BigInteger limit = toUnsignedBigInteger(-1L);
+                
+                if (bi.compareTo(limit) <= 0) {
+                    return bi.longValue();
+                } else {
+                    throw new
+                    NumberFormatException(String.format("String value %s exceeds " + 
+                                                        "range of unsigned long.", s));
+                }
+            }
+        } else {
+            throw NumberFormatException.forInputString(s);
+        }
+    }
+
+    /**
+     * Parses the string argument as an unsigned decimal integer. The
+     * characters in the string must all be decimal digits, except
+     * that the first character may be an an ASCII plus sign {@code
+     * '+'} (<code>'&#92;u002B'</code>). The resulting integer value
+     * is returned, exactly as if the argument and the radix 10 were
+     * given as arguments to the {@link
+     * #parseUnsignedLong(java.lang.String, int)} method.
+     *
+     * @param s   a {@code String} containing the unsigned {@code long}
+     *            representation to be parsed
+     * @return    the unsigned integer value represented by the argument in decimal.
+     * @throws    NumberFormatException  if the string does not contain a
+     *            parsable unsigned integer.
+     * @since 1.8
+     */
+    public static long parseUnsignedLong(String s) throws NumberFormatException {
+        return parseUnsignedLong(s, 10);
+    }
+
+    /**
      * Returns a {@code Long} object holding the value
      * extracted from the specified {@code String} when parsed
      * with the radix given by the second argument.  The first
      * argument is interpreted as representing a signed
      * {@code long} in the radix specified by the second

@@ -975,10 +1192,76 @@
      */
     public static int compare(long x, long y) {
         return (x < y) ? -1 : ((x == y) ? 0 : 1);
     }
 
+    /**
+     * Compares two {@code long} values numerically treating the values
+     * as unsigned.
+     *
+     * @param  x the first {@code long} to compare
+     * @param  y the second {@code long} to compare
+     * @return the value {@code 0} if {@code x == y}; a value less
+     *         than {@code 0} if {@code x < y} as unsigned values; and
+     *         a value greater than {@code 0} if {@code x > y} as
+     *         unsigned values
+     * @since 1.8
+     */
+    public static int compareUnsigned(long x, long y) {
+        return compare(x + MIN_VALUE, y + MIN_VALUE);
+    }
+
+
+    /**
+     * Returns the unsigned quotient of dividing the first argument by
+     * the second where each argument is interpreted as an unsigned
+     * value.
+     *
+     * In other words, return the unsigned value of {@code
+     * (dividend / divisor)}.
+     *
+     * @return the unsigned quotient of the first argument divided by
+     * the second argument
+     * @param dividend the value to be divided
+     * @param divisor the value doing the dividing
+     * @since 1.8
+     */
+    public static long divideUnsigned(long dividend, long divisor) {
+        if (divisor < 0L) { // signed comparison
+            // Answer must be 0 or 1 depending on relative magnitude
+            // of dividiend and divisor.
+            return (compareUnsigned(dividend, divisor)) < 0 ? 0L :1L;
+        }
+
+        /*
+         * For simple code, leveraging BigInteger.  Longer and faster
+         * code written directly in terms of operations on longs is
+         * possible; see "Hacker's Delight" for divide and remainder
+         * algorithms.
+         */
+        return toUnsignedBigInteger(dividend).
+            divide(toUnsignedBigInteger(divisor)).longValue();
+    }
+
+    /**
+     * Returns the unsigned remainder from dividing the first argument by
+     * the second where each argument is interpreted as an unsigned
+     * value.
+     *
+     * In other words, return the unsigned value of {@code
+     * (dividend % divisor)}.
+     *
+     * @return the unsigned remainder of the first argument divided by
+     * the second argument
+     * @param dividend the value to be divided
+     * @param divisor the value doing the dividing
+     * @since 1.8
+     */
+    public static long remainderUnsigned(long dividend, long divisor) {
+        return toUnsignedBigInteger(dividend).
+            remainder(toUnsignedBigInteger(divisor)).longValue();
+    }
 
     // Bit Twiddling
 
     /**
      * The number of bits used to represent a {@code long} value in two's