--- old/src/share/classes/java/lang/Long.java 2010-01-21 16:57:26.000000000 -0800 +++ new/src/share/classes/java/lang/Long.java 2010-01-21 16:57:26.000000000 -0800 @@ -25,6 +25,8 @@ 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 @@ -139,6 +141,52 @@ } /** + * Returns an unsigned string representation of the first argument + * in the radix specified by the second argument. + * + *

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. + * + *

Note that since the first argument is treated as an unsigned + * value, no leading sign character is printed. + * + *

If the magnitude is zero, it is represented by a single zero + * character {@code '0'} ('\u0030'); otherwise, + * the first character of the representation of the magnitude will + * not be the zero character. + * + *

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.7 + */ + public static String toUnsignedString(long i, int radix) { + if (i >= 0) + return toString(i, radix); + else { + 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 16. * @@ -174,7 +222,7 @@ * @since JDK 1.0.2 */ public static String toHexString(long i) { - return toUnsignedString(i, 4); + return toUnsignedString0(i, 4); } /** @@ -207,7 +255,7 @@ * @since JDK 1.0.2 */ public static String toOctalString(long i) { - return toUnsignedString(i, 3); + return toUnsignedString0(i, 3); } /** @@ -232,13 +280,13 @@ * @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; @@ -270,6 +318,23 @@ } /** + * 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.7 + */ + 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 @@ -484,6 +549,99 @@ } /** + * 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 '+'} ('\u002B'). The resulting + * integer value is returned. + * + *

An exception of type {@code NumberFormatException} is + * thrown if any of the following situations occurs: + *

+ * + * + * @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.7 + */ + 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 { + 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 + * '+'} ('\u002B'). 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.7 + */ + 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 @@ -971,6 +1129,71 @@ 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.7 + */ + public static int compareUnsigned(long x, long y) { + long sign_x = x & Long.MIN_VALUE; + long sign_y = y & Long.MIN_VALUE; + + if (sign_x == sign_y) { + return Long.compare(x & (~Long.MIN_VALUE), y & (~Long.MIN_VALUE)); + } + else { + if (sign_x == 0L) + return -1; // sign(x) is 0, sign(y) is 1 => (x < y) + else + return 1; // sign(x) is 1, sign(y) is 0 => (x > y) + } + } + + + /** + * 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.7 + */ + public static long divideUnsigned(long dividend, long divisor) { + 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.7 + */ + public static long remainderUnsigned(long dividend, long divisor) { + return toUnsignedBigInteger(dividend). + remainder(toUnsignedBigInteger(divisor)).longValue(); + } // Bit Twiddling