Simplifies Long.toString.

It should slightly improve the performance as well.
Adapted from the algorithm in android-sdk.

Change-Id: I10a896c52c625be4a147b0dc0e6ecad3ab8353a9
Review-Link: https://gwt-review.googlesource.com/#/c/13443/
diff --git a/user/super/com/google/gwt/emul/java/lang/Long.java b/user/super/com/google/gwt/emul/java/lang/Long.java
index ec8c799..e6313d5 100644
--- a/user/super/com/google/gwt/emul/java/lang/Long.java
+++ b/user/super/com/google/gwt/emul/java/lang/Long.java
@@ -162,36 +162,42 @@
   }
 
   public static String toString(long value, int intRadix) {
-    if (intRadix == 10 || intRadix < Character.MIN_RADIX
-        || intRadix > Character.MAX_RADIX) {
+    if (intRadix == 10 || intRadix < Character.MIN_RADIX || intRadix > Character.MAX_RADIX) {
       return String.valueOf(value);
     }
 
-    if (Integer.MIN_VALUE <= value && value <= Integer.MAX_VALUE) {
-      return Integer.toString((int) value, intRadix);
+    int intValue = (int) value;
+    if (intValue == value) {
+      return Integer.toString(intValue, intRadix);
     }
 
-    final int bufSize = 65;
-    char[] buf = new char[bufSize];
-    int pos = bufSize - 1;
-    // Cache a converted version for performance (pure long ops are faster).
-    long radix = intRadix;
-    if (value >= 0) {
-      while (value >= radix) {
-        buf[pos--] = Character.forDigit((int) (value % radix));
-        value /= radix;
-      }
-      buf[pos] = Character.forDigit((int) value);
-    } else {
-      long negRadix = -radix;
-      while (value <= negRadix) {
-        buf[pos--] = Character.forDigit(-((int) (value % radix)));
-        value /= radix;
-      }
-      buf[pos--] = Character.forDigit(-((int) value));
-      buf[pos] = '-';
+    /*
+     * If v is positive, negate it. This is the opposite of what one might expect. It is necessary
+     * because the range of the negative values is strictly larger than that of the positive values:
+     * there is no positive value corresponding to Long.MIN_VALUE.
+     */
+    boolean negative = value < 0;
+    if (!negative) {
+      value = -value;
     }
-    return String.valueOf(buf, pos, bufSize - pos);
+
+    int bufLen = intRadix < 8 ? 65 : 23; // Max chars in result (conservative)
+    char[] buf = new char[bufLen];
+    int cursor = bufLen;
+
+    // Convert radix to long before hand to avoid costly conversion on each iteration.
+    long radix = intRadix;
+    do {
+      long q = value / radix;
+      buf[--cursor] = Character.forDigit((int) (radix * q - value));
+      value = q;
+    } while (value != 0);
+
+    if (negative) {
+      buf[--cursor] = '-';
+    }
+
+    return String.valueOf(buf, cursor, bufLen - cursor);
   }
 
   public static Long valueOf(long i) {
diff --git a/user/test/com/google/gwt/emultest/java/lang/LongTest.java b/user/test/com/google/gwt/emultest/java/lang/LongTest.java
index 2710139..df38a56 100644
--- a/user/test/com/google/gwt/emultest/java/lang/LongTest.java
+++ b/user/test/com/google/gwt/emultest/java/lang/LongTest.java
@@ -281,6 +281,7 @@
     assertEquals("9223372036854775807", Long.toString(Long.MAX_VALUE));
 
     assertEquals("100000000", Long.toString(100000000L, 10));
+    assertEquals("575360400", Long.toString(100000000L, 8));
     assertEquals("77777777777", Long.toString(8589934591L, 8));
     assertEquals("fffffffff", Long.toString(68719476735L, 16));
     assertEquals("1111111111111111111111111111111111111111111", Long.toString(8796093022207L, 2));