diff options
Diffstat (limited to 'libjava/classpath/java/lang/Long.java')
-rw-r--r-- | libjava/classpath/java/lang/Long.java | 146 |
1 files changed, 113 insertions, 33 deletions
diff --git a/libjava/classpath/java/lang/Long.java b/libjava/classpath/java/lang/Long.java index 08ac3976ca7..a5ee6c707ad 100644 --- a/libjava/classpath/java/lang/Long.java +++ b/libjava/classpath/java/lang/Long.java @@ -51,6 +51,7 @@ package java.lang; * @author Eric Blake (ebb9@email.byu.edu) * @author Tom Tromey (tromey@redhat.com) * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @author Ian Rogers * @since 1.0 * @status updated to 1.5 */ @@ -86,6 +87,18 @@ public final class Long extends Number implements Comparable<Long> */ public static final int SIZE = 64; + // This caches some Long values, and is used by boxing + // conversions via valueOf(). We cache at least -128..127; + // these constants control how much we actually cache. + private static final int MIN_CACHE = -128; + private static final int MAX_CACHE = 127; + private static final Long[] longCache = new Long[MAX_CACHE - MIN_CACHE + 1]; + static + { + for (int i=MIN_CACHE; i <= MAX_CACHE; i++) + longCache[i - MIN_CACHE] = new Long(i); + } + /** * The immutable value of this Long. * @@ -118,6 +131,45 @@ public final class Long extends Number implements Comparable<Long> } /** + * Return the size of a string large enough to hold the given number + * + * @param num the number we want the string length for (must be positive) + * @param radix the radix (base) that will be used for the string + * @return a size sufficient for a string of num + */ + private static int stringSize(long num, int radix) { + int exp; + if (radix < 4) + { + exp = 1; + } + else if (radix < 8) + { + exp = 2; + } + else if (radix < 16) + { + exp = 3; + } + else if (radix < 32) + { + exp = 4; + } + else + { + exp = 5; + } + int size=0; + do + { + num >>>= exp; + size++; + } + while(num != 0); + return size; + } + + /** * Converts the <code>long</code> to a <code>String</code> using * the specified radix (base). If the radix exceeds * <code>Character.MIN_RADIX</code> or <code>Character.MAX_RADIX</code>, 10 @@ -131,29 +183,43 @@ public final class Long extends Number implements Comparable<Long> */ public static String toString(long num, int radix) { - // Use the Integer toString for efficiency if possible. - if ((int) num == num) - return Integer.toString((int) num, radix); - if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) radix = 10; - // For negative numbers, print out the absolute value w/ a leading '-'. - // Use an array large enough for a binary number. - char[] buffer = new char[65]; - int i = 65; - boolean isNeg = false; - if (num < 0) + // Is the value negative? + boolean isNeg = num < 0; + + // Is the string a single character? + if (!isNeg && num < radix) + return new String(digits, (int)num, 1, true); + + // Compute string size and allocate buffer + // account for a leading '-' if the value is negative + int size; + int i; + char[] buffer; + if (isNeg) { - isNeg = true; num = -num; // When the value is MIN_VALUE, it overflows when made positive if (num < 0) - { - buffer[--i] = digits[(int) (-(num + radix) % radix)]; - num = -(num / radix); - } + { + i = size = stringSize(MAX_VALUE, radix) + 2; + buffer = new char[size]; + buffer[--i] = digits[(int) (-(num + radix) % radix)]; + num = -(num / radix); + } + else + { + i = size = stringSize(num, radix) + 1; + buffer = new char[size]; + } + } + else + { + i = size = stringSize(num, radix); + buffer = new char[size]; } do @@ -167,7 +233,7 @@ public final class Long extends Number implements Comparable<Long> buffer[--i] = '-'; // Package constructor avoids an array copy. - return new String(buffer, i, 65 - i, true); + return new String(buffer, i, size - i, true); } /** @@ -270,7 +336,7 @@ public final class Long extends Number implements Comparable<Long> */ public static Long valueOf(String s, int radix) { - return new Long(parseLong(s, radix, false)); + return valueOf(parseLong(s, radix, false)); } /** @@ -286,7 +352,7 @@ public final class Long extends Number implements Comparable<Long> */ public static Long valueOf(String s) { - return new Long(parseLong(s, 10, false)); + return valueOf(parseLong(s, 10, false)); } /** @@ -298,9 +364,10 @@ public final class Long extends Number implements Comparable<Long> */ public static Long valueOf(long val) { - // We aren't required to cache here. We could, though perhaps we - // ought to consider that as an empirical question. - return new Long(val); + if (val < MIN_CACHE || val > MAX_CACHE) + return new Long(val); + else + return longCache[((int)val) - MIN_CACHE]; } /** @@ -337,7 +404,7 @@ public final class Long extends Number implements Comparable<Long> */ public static Long decode(String str) { - return new Long(parseLong(str, 10, true)); + return valueOf(parseLong(str, 10, true)); } /** @@ -467,7 +534,7 @@ public final class Long extends Number implements Comparable<Long> public static Long getLong(String nm, long val) { Long result = getLong(nm, null); - return result == null ? new Long(val) : result; + return result == null ? valueOf(val) : result; } /** @@ -622,7 +689,14 @@ public final class Long extends Number implements Comparable<Long> */ public static int signum(long x) { - return x < 0 ? -1 : (x > 0 ? 1 : 0); + return (int) ((x >> 63) | (-x >>> 63)); + + // The LHS propagates the sign bit through every bit in the word; + // if X < 0, every bit is set to 1, else 0. if X > 0, the RHS + // negates x and shifts the resulting 1 in the sign bit to the + // LSB, leaving every other bit 0. + + // Hacker's Delight, Section 2-7 } /** @@ -655,16 +729,22 @@ public final class Long extends Number implements Comparable<Long> */ private static String toUnsignedString(long num, int exp) { - // Use the Integer toUnsignedString for efficiency if possible. - // If NUM<0 then this particular optimization doesn't work - // properly. - if (num >= 0 && (int) num == num) - return Integer.toUnsignedString((int) num, exp); + // Compute string length + int size = 1; + long copy = num >>> exp; + while (copy != 0) + { + size++; + copy >>>= exp; + } + // Quick path for single character strings + if (size == 1) + return new String(digits, (int)num, 1, true); - // Use an array large enough for a binary number. + // Encode into buffer int mask = (1 << exp) - 1; - char[] buffer = new char[64]; - int i = 64; + char[] buffer = new char[size]; + int i = size; do { buffer[--i] = digits[(int) num & mask]; @@ -673,7 +753,7 @@ public final class Long extends Number implements Comparable<Long> while (num != 0); // Package constructor avoids an array copy. - return new String(buffer, i, 64 - i, true); + return new String(buffer, i, size - i, true); } /** |