summaryrefslogtreecommitdiff
path: root/libjava/classpath/java/lang/Long.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/java/lang/Long.java')
-rw-r--r--libjava/classpath/java/lang/Long.java146
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);
}
/**