Overhaul BigInteger implementation.

This provides a faster code path for #valueOf(long) and some other
operations, cleans up constructors and also removes the JavaScript
specific native code.

PiperOrigin-RevId: 361980135
Change-Id: Ib72cc15e798ab2eb0a5c83a636278ff936440a8e
diff --git a/user/super/com/google/gwt/emul/java/math/BigDecimal.java b/user/super/com/google/gwt/emul/java/math/BigDecimal.java
index 0802895..9f310cd 100644
--- a/user/super/com/google/gwt/emul/java/math/BigDecimal.java
+++ b/user/super/com/google/gwt/emul/java/math/BigDecimal.java
@@ -2572,7 +2572,7 @@
 
   private BigInteger getUnscaledValue() {
     if (intVal == null) {
-      intVal = BigInteger.valueOf(smallValue);
+      intVal = BigInteger.valueOf((long) smallValue);
     }
     return intVal;
   }
diff --git a/user/super/com/google/gwt/emul/java/math/BigInteger.java b/user/super/com/google/gwt/emul/java/math/BigInteger.java
index 4f27600..8fe9f77 100644
--- a/user/super/com/google/gwt/emul/java/math/BigInteger.java
+++ b/user/super/com/google/gwt/emul/java/math/BigInteger.java
@@ -34,6 +34,7 @@
  */
 package java.math;
 
+import static javaemul.internal.Coercions.ensureInt;
 import static javaemul.internal.InternalPreconditions.checkCriticalArgument;
 import static javaemul.internal.InternalPreconditions.checkNotNull;
 
@@ -96,11 +97,6 @@
   static final BigInteger MINUS_ONE = new BigInteger(-1, 1);
 
   /**
-   * 2^32.
-   */
-  static final double POW32 = 4294967296d;
-
-  /**
    * All the {@code BigInteger} numbers in the range [0,10] are cached.
    */
   static final BigInteger[] SMALL_VALUES = {
@@ -139,17 +135,19 @@
   }
 
   public static BigInteger valueOf(long val) {
-    if (val < 0) {
-      if (val != -1) {
-        return new BigInteger(-1, -val);
-      }
-      return MINUS_ONE;
-    } else if (val <= 10) {
-      return SMALL_VALUES[(int) val];
-    } else {
-      // (val > 10)
-      return new BigInteger(1, val);
+    return val >= 0 ? BigInteger.fromBits(val) : BigInteger.fromBits(-val).negate();
+  }
+
+  private static BigInteger fromBits(long bits) {
+    int lowBits = (int) bits;
+    int highBits = LongUtils.getHighBits(bits);
+    if (highBits != 0) {
+      return new BigInteger(1, lowBits, highBits);
     }
+    if (lowBits > 10 || lowBits < 0) {
+      return new BigInteger(1, lowBits);
+    }
+    return SMALL_VALUES[lowBits];
   }
 
   static BigInteger getPowerOfTwo(int exp) {
@@ -163,20 +161,6 @@
     return new BigInteger(1, intCount + 1, resDigits);
   }
 
-  public static BigInteger valueOf(double val) {
-    if (val < 0) {
-      if (val != -1) {
-        return new BigInteger(-1, -val);
-      }
-      return MINUS_ONE;
-    } else if (val <= 10) {
-      return SMALL_VALUES[(int) val];
-    } else {
-      // (val > 10)
-      return new BigInteger(1, val);
-    }
-  }
-
   /**
    * @see BigInteger#BigInteger(String, int)
    */
@@ -235,18 +219,6 @@
   }
 
   /**
-   * Converts an integral double to an unsigned integer; ie 2^31 will be
-   * returned as 0x80000000.
-   *
-   * @param val
-   * @return val as an unsigned int
-   */
-  @SuppressWarnings("unusable-by-js")
-  private static native int toUnsignedInt(double val) /*-{
-    return val | 0;
-  }-*/;
-
-  /**
    * The magnitude of this big integer. This array is in little endian order and
    * each "digit" is a 32-bit unsigned integer. For example: {@code 13} is
    * represented as [ 13 ] {@code -13} is represented as [ 13 ] {@code 2^32 +
@@ -438,16 +410,17 @@
    * @param sign the sign of the number
    * @param value the only one digit of array
    */
-  BigInteger(int sign, int value) {
-    this.sign = sign;
-    numberLength = 1;
-    digits = new int[] {value};
+  BigInteger(int sign, int bits) {
+    this(sign, 1, new int[] {bits});
+  }
+
+  BigInteger(int sign, int lowBits, int highBits) {
+    this(sign, 2, new int[] {lowBits, highBits});
   }
 
   /**
-   * Creates a new {@code BigInteger} with the given sign and magnitude. This
-   * constructor does not create a copy, so any changes to the reference will
-   * affect the new number.
+   * Creates a new {@code BigInteger} with the given sign and magnitude. This constructor does not
+   * create a copy, so any changes to the reference will affect the new number.
    *
    * @param signum The sign of the number represented by {@code digits}
    * @param digits The magnitude of the number
@@ -466,8 +439,8 @@
   }
 
   /**
-   * Constructs a number without to create new space. This construct should be
-   * used only if the three fields of representation are known.
+   * Constructs a number without to create new space. This construct should be used only if the
+   * three fields of representation are known.
    *
    * @param sign the sign of the number
    * @param numberLength the length of the internal array
@@ -480,53 +453,13 @@
   }
 
   /**
-   * Creates a new {@code BigInteger} whose value is equal to the specified
-   * {@code long}.
-   *
-   * @param sign the sign of the number
-   * @param val the value of the new {@code BigInteger}.
-   */
-  BigInteger(int sign, long val) {
-    // PRE: (val >= 0) && (sign >= -1) && (sign <= 1)
-    this.sign = sign;
-    if (LongUtils.getHighBits(val) == 0) {
-      // It fits in one 'int'
-      numberLength = 1;
-      digits = new int[] {(int) val};
-    } else {
-      numberLength = 2;
-      digits = new int[] {(int) val, (int) (val >> 32)};
-    }
-  }
-
-  /**
-   * Creates a new {@code BigInteger} whose value is equal to the specified
-   * {@code double} (which must be an integral value).
-   *
-   * @param sign the sign of the number
-   * @param val the value of the new {@code BigInteger}.
-   */
-  private BigInteger(int sign, double val) {
-    // PRE: (val >= 0) && (sign >= -1) && (sign <= 1)
-    this.sign = sign;
-    if (val < POW32) {
-      // It fits in one 'int'
-      numberLength = 1;
-      digits = new int[] { toUnsignedInt(val) };
-    } else {
-      numberLength = 2;
-      digits = new int[] { toUnsignedInt(val % POW32), toUnsignedInt(val / POW32) };
-    }
-  }
-
-  /**
    * Returns a (new) {@code BigInteger} whose value is the absolute value of
    * {@code this}.
    *
    * @return {@code abs(this)}.
    */
   public BigInteger abs() {
-    return ((sign < 0) ? new BigInteger(1, numberLength, digits) : this);
+    return sign < 0 ? negate() : this;
   }
 
   /**
@@ -913,7 +846,7 @@
   public int intValue() {
     int i = digits[0];
     // i is always positive except for Integer.MIN_VALUE because of int overflow
-    return (sign > 0 || i == Integer.MIN_VALUE) ? i : -i;
+    return sign > 0 ? i : ensureInt(-i);
   }
 
   /**
@@ -1113,10 +1046,7 @@
    */
   public BigInteger multiply(BigInteger val) {
     // This let us to throw NullPointerException when val == null
-    if (val.sign == 0) {
-      return ZERO;
-    }
-    if (sign == 0) {
+    if (val.sign == 0 || sign == 0) {
       return ZERO;
     }
     return Multiplication.multiply(this, val);
@@ -1128,7 +1058,7 @@
    * @return {@code -this}.
    */
   public BigInteger negate() {
-    return ((sign == 0) ? this : new BigInteger(-sign, numberLength, digits));
+    return sign == 0 ? this : new BigInteger(-sign, numberLength, digits);
   }
 
   /**
diff --git a/user/test/com/google/gwt/emultest/java/math/BigIntegerConstructorsTest.java b/user/test/com/google/gwt/emultest/java/math/BigIntegerConstructorsTest.java
index 3229ee3..c3992e5 100644
--- a/user/test/com/google/gwt/emultest/java/math/BigIntegerConstructorsTest.java
+++ b/user/test/com/google/gwt/emultest/java/math/BigIntegerConstructorsTest.java
@@ -38,9 +38,6 @@
 package com.google.gwt.emultest.java.math;
 
 import com.google.gwt.emultest.java.util.EmulTestBase;
-import com.google.gwt.testing.TestUtils;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
 import java.math.BigInteger;
 import java.util.Random;
 
@@ -778,48 +775,4 @@
     }
     assertEquals("incorrect sign", 1, aNumber.signum());
   }
-
-  /**
-   * Test internal static factory method.
-   */
-  public void testValueOfDouble() {
-    if (TestUtils.isJvm()) {
-      // JRE implementation doesn't have the method tested here
-      return;
-    }
-    BigInteger val = BigInteger.valueOf(noopToCompileForJvm(1.0));
-    assertEquals("1", val.toString());
-    val = BigInteger.valueOf(noopToCompileForJvm(100.0));
-    assertEquals("100", val.toString());
-    val = BigInteger.valueOf(noopToCompileForJvm(2147483647.0));
-    assertEquals("2147483647", val.toString());
-    val = BigInteger.valueOf(noopToCompileForJvm(-2147483647.0));
-    assertEquals("-2147483647", val.toString());
-    val = BigInteger.valueOf(noopToCompileForJvm(2147483648.0));
-    assertEquals("2147483648", val.toString());
-    val = BigInteger.valueOf(noopToCompileForJvm(-2147483648.0));
-    assertEquals("-2147483648", val.toString());
-    val = BigInteger.valueOf(noopToCompileForJvm(4294967295.0));
-    assertEquals("4294967295", val.toString());
-    val = BigInteger.valueOf(noopToCompileForJvm(-4294967295.0));
-    assertEquals("-4294967295", val.toString());
-    val = BigInteger.valueOf(noopToCompileForJvm(4294967296.0));
-    assertEquals("4294967296", val.toString());
-    val = BigInteger.valueOf(noopToCompileForJvm(-4294967296.0));
-    assertEquals("-4294967296", val.toString());
-  }
-
-  @Target({ElementType.METHOD})
-  private @interface GwtIncompatible {}
-
-  @GwtIncompatible
-  private static long noopToCompileForJvm(double d) {
-    // The BigInteger.valueOf(double) doesn't exist on JVM. This methods exists to so that this test
-    // can be compiled with the standard JRE.
-    throw new AssertionError();
-  }
-
-  private static double noopToCompileForJvm(Double d) {
-    return d;
-  }
 }