Revision: 7328
Author: [email protected]
Date: Thu Dec 17 14:28:24 2009
Log: Fix NumberFormat to work with BigInteger/BigDecimal (using code/ideas  
from
Dan's implementation), fix bug present in Harmony, more tests.

http://code.google.com/p/google-web-toolkit/source/detail?r=7328

Modified:
   
/changes/jat/bigdecimal/user/src/com/google/gwt/i18n/client/NumberFormat.java
   
/changes/jat/bigdecimal/user/super/com/google/gwt/emul/java/math/BigDecimal.java
   
/changes/jat/bigdecimal/user/super/com/google/gwt/emul/java/math/BigInteger.java
   
/changes/jat/bigdecimal/user/test/com/google/gwt/emultest/java/math/BigDecimalArithmeticTest.java
   
/changes/jat/bigdecimal/user/test/com/google/gwt/emultest/java/math/BigIntegerConvertTest.java
   
/changes/jat/bigdecimal/user/test/com/google/gwt/i18n/client/NumberFormat_en_Test.java

=======================================
---  
/changes/jat/bigdecimal/user/src/com/google/gwt/i18n/client/NumberFormat.java   
 
Sun Dec 13 22:19:25 2009
+++  
/changes/jat/bigdecimal/user/src/com/google/gwt/i18n/client/NumberFormat.java   
 
Thu Dec 17 14:28:24 2009
@@ -15,7 +15,6 @@
   */
  package com.google.gwt.i18n.client;

-import com.google.gwt.core.client.GWT;
  import com.google.gwt.i18n.client.constants.NumberConstants;

  import java.math.BigDecimal;
@@ -610,7 +609,48 @@
      }
      return "\u00A0";
    }
-
+
+  /**
+   * Appends a scaled string representation to a buffer, returning the  
scale
+   * (which is the number of places to the right of the end of the string  
the
+   * decimal point should be moved -- i.e., 3.5 would be added to the  
buffer
+   * as "35" and a returned scale of -1).
+   *
+   * @param buf
+   * @param val
+   * @return scale to apply to the result
+   */
+  // @VisibleForTesting
+  static int toScaledString(StringBuilder buf, double val) {
+    int startLen = buf.length();
+    buf.append(toPrecision(val, 20));
+    int scale = 0;
+
+    // remove exponent if present, adjusting scale
+    int expIdx = buf.indexOf("e", startLen);
+    if (expIdx < 0) {
+      expIdx = buf.indexOf("E", startLen);
+    }
+    if (expIdx >= 0) {
+      int expDigits = expIdx + 1;
+      if (expDigits < buf.length() && buf.charAt(expDigits) == '+') {
+        ++expDigits;
+      }
+      if (expDigits < buf.length()) {
+        scale = Integer.parseInt(buf.substring(expDigits));
+      }
+      buf.delete(expIdx, buf.length());
+    }
+
+    // remove decimal point if present, adjusting scale
+    int dot = buf.indexOf(".", startLen);
+    if (dot >= 0) {
+      buf.deleteCharAt(dot);
+      scale -= buf.length() - dot;
+    }
+    return scale;
+  }
+
    /**
     * Lookup a currency code.
     *
@@ -628,31 +668,48 @@
      return currencyData;
    }

-  private static native String toFixed(double d, int digits) /*-{
-    return d.toFixed(digits);
+  /**
+   * Convert a double to a string with {...@code digits} precision.  The  
resulting
+   * string may still be in exponential notation.
+   *
+   * @param d double value
+   * @param digits number of digits of precision to include
+   * @return non-localized string representation of {...@code d}
+   */
+  private static native String toPrecision(double d, int digits) /*-{
+    return d.toPrecision(digits);
    }-*/;

-  // The currency code.
+  /**
+   * The currency code.
+   */
    private final String currencyCode;

-  // Currency setting.
+  /**
+   * Currency symbol to use.
+   */
    private final String currencySymbol;

-  // Forces the decimal separator to always appear in a formatted number.
+  /**
+   * Forces the decimal separator to always appear in a formatted number.
+   */
    private boolean decimalSeparatorAlwaysShown = false;

-  // The number of digits between grouping separators in the integer
-  // portion of a number.
+  /**
+   * The number of digits between grouping separators in the integer  
portion of
+   * a number.
+   */
    private int groupingSize = 3;
-
+
    private boolean isCurrencyFormat = false;

    private int maximumFractionDigits = 3; // invariant, >=  
minFractionDigits.
+
    private int maximumIntegerDigits = 40;
    private int minExponentDigits;
    private int minimumFractionDigits = 0;
    private int minimumIntegerDigits = 1;
-
+
    // The multiplier for use in percent, per mille, etc.
    private int multiplier = 1;

@@ -673,6 +730,24 @@
    // True to force the use of exponential (i.e. scientific) notation.
    private boolean useExponentialNotation = false;

+  /**
+   * Holds the current exponent during one call to
+   * {...@link #format(boolean, StringBuilder, int)}.
+   */
+  private transient int exponent;
+
+  /**
+   * Holds the current decimal position during one call to
+   * {...@link #format(boolean, StringBuilder, int)}.
+   */
+  private transient int decimalPosition;
+
+  /**
+   * Holds the current digits length during one call to
+   * {...@link #format(boolean, StringBuilder, int)}.
+   */
+  private transient int digitsLength;
+
    /**
     * Constructs a format object based on the specified settings.
     *
@@ -722,33 +797,35 @@
     * @return the formatted number string
     */
    public String format(double number) {
-    StringBuffer result = new StringBuffer();
-
      if (Double.isNaN(number)) {
-      result.append(numberConstants.notANumber());
-      return result.toString();
-    }
-
+      return numberConstants.notANumber();
+    }
      boolean isNegative = ((number < 0.0) || (number == 0.0 && 1 / number <  
0.0));
-
-    result.append(isNegative ? negativePrefix : positivePrefix);
+    if (isNegative) {
+      number = -number;
+    }
+    StringBuilder buf = new StringBuilder();
      if (Double.isInfinite(number)) {
-      result.append(numberConstants.infinity());
-    } else {
-      if (isNegative) {
-        number = -number;
-      }
-      number *= multiplier;
-      if (useExponentialNotation) {
-        subformatExponential(number, result);
-      } else {
-        subformatFixed(number, result, minimumIntegerDigits);
-      }
-    }
-
-    result.append(isNegative ? negativeSuffix : positiveSuffix);
-
-    return result.toString();
+      buf.append(isNegative ? negativePrefix : positivePrefix);
+      buf.append(numberConstants.infinity());
+      buf.append(isNegative ? negativeSuffix : positiveSuffix);
+      return buf.toString();
+    }
+    number *= multiplier;
+    int scale = toScaledString(buf, number);
+
+    // pre-round value to deal with .15 being represented as .149999... etc
+    // check at 3 more digits than will be required in the output
+    int preRound = buf.length() + scale + maximumFractionDigits + 3;
+    if (preRound > 0 && preRound < buf.length()
+        && buf.charAt(preRound) == '9') {
+      propagateCarry(buf, preRound - 1);
+      scale += buf.length() - preRound;
+      buf.delete(preRound, buf.length());
+    }
+
+    format(isNegative, buf, scale);
+    return buf.toString();
    }

    /**
@@ -758,18 +835,41 @@
     * @return the formatted number string
     */
    public String format(Number number) {
-    int scale = 0;
-    BigInteger bigInt = null;
      if (number instanceof BigDecimal) {
        BigDecimal bigDec = (BigDecimal) number;
-      bigInt = bigDec.unscaledValue();
-      scale = bigDec.scale();
+      boolean isNegative = bigDec.signum() < 0;
+      if (isNegative) {
+        bigDec = bigDec.negate();
+      }
+      bigDec = bigDec.multiply(BigDecimal.valueOf(multiplier));
+      StringBuilder buf = new StringBuilder();
+      buf.append(bigDec.unscaledValue().toString());
+      format(isNegative, buf, -bigDec.scale());
+      return buf.toString();
      } else if (number instanceof BigInteger) {
-      bigInt = (BigInteger) number;
+      BigInteger bigInt = (BigInteger) number;
+      boolean isNegative = bigInt.signum() < 0;
+      if (isNegative) {
+        bigInt = bigInt.negate();
+      }
+      bigInt = bigInt.multiply(BigInteger.valueOf(multiplier));
+      StringBuilder buf = new StringBuilder();
+      buf.append(bigInt.toString());
+      format(isNegative, buf, 0);
+      return buf.toString();
+    } else if (number instanceof Long) {
+      long longVal = number.longValue();
+      boolean isNegative = longVal < 0;
+      if (isNegative) {
+        longVal = -longVal;
+      }
+      StringBuilder buf = new StringBuilder();
+      buf.append(String.valueOf(longVal));
+      format(isNegative, buf, 0);
+      return buf.toString();
      } else {
        return format(number.doubleValue());
      }
-    return formatBig(bigInt, scale);
    }

    /**
@@ -898,10 +998,10 @@
     * @throws NumberFormatException if the entire text could not be  
converted
     *           into a number
     */
-  public Number parseBig(String text) throws NumberFormatException {
-    // TODO(jat): implement
-    return Double.valueOf(parse(text));
-  }
+//  public Number parseBig(String text) throws NumberFormatException {
+//    // TODO(jat): implement
+//    return Double.valueOf(parse(text));
+//  }

    /**
     * Parses text to produce a numeric value.
@@ -922,11 +1022,11 @@
     *     BigDecimal, or {...@code Double(0.0)} if the parse fails.
     * @throws NumberFormatException if the text segment could not be  
converted into a number
     */
-  public Number parseBig(String text, int[] inOutPos)
-      throws NumberFormatException {
-    // TODO(jat): implement
-    return Double.valueOf(parse(text, inOutPos));
-  }
+//  public Number parseBig(String text, int[] inOutPos)
+//      throws NumberFormatException {
+//    // TODO(jat): implement
+//    return Double.valueOf(parse(text, inOutPos));
+//  }

    protected int getGroupingSize() {
      return groupingSize;
@@ -957,41 +1057,178 @@
    }

    /**
-   * This method formats the exponent part of a double.
+   * Add exponent suffix.
     *
-   * @param exponent exponential value
-   * @param result formatted exponential part will be append to it
+   * @param digits
     */
-  private void addExponentPart(int exponent, StringBuffer result) {
-    result.append(numberConstants.exponentialSymbol());
-
+  private void addExponent(StringBuilder digits) {
+    digits.append(numberConstants.exponentialSymbol());
      if (exponent < 0) {
        exponent = -exponent;
-      result.append(numberConstants.minusSign());
-    }
-
+      digits.append(numberConstants.minusSign());
+    }
      String exponentDigits = String.valueOf(exponent);
-    int len = exponentDigits.length();
-    for (int i = len; i < minExponentDigits; ++i) {
-      result.append(numberConstants.zeroDigit());
-    }
-    int zeroDelta = numberConstants.zeroDigit().charAt(0) - '0';
-    for (int i = 0; i < len; ++i) {
-      result.append((char) (exponentDigits.charAt(i) + zeroDelta));
+    for (int i = exponentDigits.length(); i < minExponentDigits; ++i) {
+      digits.append('0');
+    }
+    digits.append(exponentDigits);
+  }
+
+  /**
+   * @param digits
+   * @param decimalSeparator
+   */
+  private void addZeroAndDecimal(StringBuilder digits, char  
decimalSeparator) {
+    // add zero and decimal point if required
+    if (digitsLength == 0) {
+      digits.insert(0, '0');
+      ++decimalPosition;
+    }
+    if (decimalPosition < digitsLength || decimalSeparatorAlwaysShown) {
+      digits.insert(decimalPosition, decimalSeparator);
      }
    }

    /**
-   * Format a scaled BigInteger.
+   * Adjust the fraction digits, adding trailing zeroes if necessary or  
removing
+   * excess trailing zeroes.
     *
-   * @param bigInt value to format
-   * @param scale number of places to move the decimal point to the left;
-   *    i.e., multiply by 10^-scale for the value to format.
-   * @return formatted value
+   * @param digits
     */
-  private String formatBig(BigInteger bigInt, int scale) {
-    // TODO(jat): implement
-    return format(bigInt.doubleValue() * Math.pow(10, -scale));
+  private void adjustFractionDigits(StringBuilder digits) {
+    // adjust fraction digits as required
+    int requiredDigits = decimalPosition + minimumFractionDigits;
+    if (digitsLength < requiredDigits) {
+      // add trailing zeros
+      while (digitsLength < requiredDigits) {
+        digits.append('0');
+        ++digitsLength;
+      }
+    } else {
+      // remove excess trailing zeros
+      int toRemove = decimalPosition + maximumFractionDigits;
+      if (toRemove > digitsLength) {
+        toRemove = digitsLength;
+      }
+      while (toRemove > requiredDigits
+          && digits.charAt(toRemove - 1) == '0') {
+        --toRemove;
+      }
+      if (toRemove < digitsLength) {
+        digits.delete(toRemove, digitsLength);
+        digitsLength = toRemove;
+      }
+    }
+  }
+
+  /**
+   * Compute the exponent to use and adjust decimal position if we are  
using
+   * exponential notation.
+   *
+   * @param digits
+   */
+  private void computeExponent(StringBuilder digits) {
+    // always trim leading zeros
+    int strip = 0;
+    while (strip < digitsLength - 1 && digits.charAt(strip) == '0') {
+      ++strip;
+    }
+    if (strip > 0) {
+      digits.delete(0, strip);
+      digitsLength -= strip;
+      exponent -= strip;
+    }
+
+    // decimal should wind up between minimum & maximumIntegerDigits
+    if (maximumIntegerDigits > minimumIntegerDigits
+        && maximumIntegerDigits > 0) {
+      // in this case, the exponent should be a multiple of
+      // maximumIntegerDigits and 1 <= decimal <= maximumIntegerDigits
+      exponent += decimalPosition - 1;
+      int remainder = exponent % maximumIntegerDigits;
+      if (remainder < 0) {
+        remainder += maximumIntegerDigits;
+      }
+      decimalPosition = remainder + 1;
+      exponent -= remainder;
+    } else {
+      exponent += decimalPosition - minimumIntegerDigits;
+      decimalPosition = minimumIntegerDigits;
+    }
+
+    // special-case 0 to have an exponent of 0
+    if (digitsLength == 1 && digits.charAt(0) == '0') {
+      exponent = 0;
+      decimalPosition = minimumIntegerDigits;
+    }
+  }
+
+  /**
+   * Format a number with its significant digits already represented in  
string
+   * form.  This is done so both double and BigInteger/Decimal formatting  
can
+   * share code without requiring all users to pay the code size penalty  
for
+   * BigDecimal/etc.
+   * <p>
+   * Example values passed in:
+   * <ul>
+   * <li>-13e2
+   * <br>{...@code isNegative=true, digits="13", scale=2}
+   * <li>3.14158
+   * <br>{...@code isNegative=false, digits="314158", scale=-5}
+   * <li>.0001
+   * <br>{...@code isNegative=false, digits="1" ("0001" would be ok),  
scale=-4}
+   * </ul>
+   *
+   * @param isNegative true if the value to be formatted is negative
+   * @param digits a StringBuilder containing just the significant digits  
in
+   *     the value to be formatted, the formatted result will be left here
+   * @param scale the number of places to the right the decimal point  
should
+   *     be moved in the digit string -- negative means the value contains
+   *     fractional digits
+   */
+  private void format(boolean isNegative, StringBuilder digits, int scale)  
{
+    char decimalSeparator;
+    char groupingSeparator;
+    if (isCurrencyFormat) {
+      decimalSeparator = numberConstants.monetarySeparator().charAt(0);
+      groupingSeparator =  
numberConstants.monetaryGroupingSeparator().charAt(0);
+    } else {
+      decimalSeparator = numberConstants.decimalSeparator().charAt(0);
+      groupingSeparator = numberConstants.groupingSeparator().charAt(0);
+    }
+
+    // Set these transient fields, which will be adjusted/used by the  
routines
+    // called in this method.
+    exponent = 0;
+    digitsLength = digits.length();
+    decimalPosition = digitsLength + scale;
+
+    boolean useExponent = this.useExponentialNotation;
+    int currentGroupingSize = this.groupingSize;
+    if (decimalPosition > 1024) {
+      // force really large numbers to be in exponential form
+      useExponent = true;
+    }
+
+    if (useExponent) {
+      computeExponent(digits);
+    }
+    processLeadingZeros(digits);
+    roundValue(digits);
+    insertGroupingSeparators(digits, groupingSeparator,  
currentGroupingSize);
+    adjustFractionDigits(digits);
+    addZeroAndDecimal(digits, decimalSeparator);
+    if (useExponent) {
+      addExponent(digits);
+    }
+    char zeroChar = numberConstants.zeroDigit().charAt(0);
+    if (zeroChar != '0') {
+      localizeDigits(digits, zeroChar);
+    }
+
+    // add prefix/suffix
+    digits.insert(0, isNegative ? negativePrefix : positivePrefix);
+    digits.append(isNegative ? negativeSuffix : positiveSuffix);
    }

    /**
@@ -1011,47 +1248,39 @@
    }

    /**
-   * This does the work of String.valueOf(long), but given a double as  
input
-   * and avoiding our emulated longs.  Contrasted with  
String.valueOf(double),
-   * it ensures (a) there will be no trailing .0, and (b) unwinds  
E-notation.
-   *
-   * @param number the integral value to convert
-   * @return the string representing that integer
+   * Insert grouping separators if needed.
+   *
+   * @param digits
+   * @param groupingSeparator
+   * @param g
     */
-  private String makeIntString(double number) {
-    String intPart = String.valueOf(number);
-    if (GWT.isScript()) {
-      return intPart; // JavaScript does the right thing for integral  
doubles
-    }
-    // ...but bytecode (hosted mode) does not... String.valueOf(double)  
will
-    // either end in .0 (non internationalized) which we don't want but is
-    // easy, or, for large numbers, it will be E-notation, which is  
annoying.
-    int digitLen = intPart.length();
-
-    if (intPart.charAt(digitLen - 2) == '.') {
-      return intPart.substring(0, digitLen - 2);
-    }
-
-    // if we have E notation, (1) the exponent will be positive (else
-    // intValue is 0, which doesn't need E notation), and (2) there will
-    // be a radix dot (String.valueOf() isn't interationalized)
-    int radix = intPart.indexOf('.');
-    int exp = intPart.indexOf('E');
-    int digits = 0;
-    for (int i = exp + 1; i < intPart.length(); i++) {
-      digits = digits * 10 + (intPart.charAt(i) - '0');
-    }
-    digits++;  // exp of zero is one int digit...
-    StringBuffer newIntPart = new StringBuffer();
-    newIntPart.append(intPart.substring(0, radix));
-    newIntPart.append(intPart.substring(radix + 1, exp));
-    while (newIntPart.length() < digits) {
-      newIntPart.append('0');
-    }
-    newIntPart.setLength(digits);
-    return newIntPart.toString();
-  }
-
+  private void insertGroupingSeparators(StringBuilder digits,
+      char groupingSeparator, int g) {
+    if (g > 0) {
+      for (int i = g; i < decimalPosition; i += g + 1) {
+        digits.insert(decimalPosition - i, groupingSeparator);
+        ++decimalPosition;
+        ++digitsLength;
+      }
+    }
+  }
+
+  /**
+   * Replace locale-independent digits with locale-specific ones.
+   *
+   * @param digits StringBuilder containing formatted number
+   * @param zero locale-specific zero character -- the rest of the digits  
must
+   *     be consecutive
+   */
+  private void localizeDigits(StringBuilder digits, char zero) {
+    for (int i = 0; i < digitsLength; ++i) {
+      char ch = digits.charAt(i);
+      if (ch >= '0' && ch <= '9') {
+        digits.setCharAt(i, (char) (ch - '0' + zero));
+      }
+    }
+  }
+
    /**
     * This method parses affix part of pattern.
     *
@@ -1212,7 +1441,7 @@
      ret = ret / scale;
      return ret;
    }
-
+
    /**
     * Method parses provided pattern, result is stored in member variables.
     *
@@ -1379,141 +1608,88 @@

      return pos - start;
    }
-
+
    /**
-   * This method formats a <code>double</code> in exponential format.
+   * Remove excess leading zeros or add some if we don't have enough.
     *
-   * @param number value need to be formated
-   * @param result where the formatted string goes
+   * @param digits
+   * @param zero
     */
-  private void subformatExponential(double number, StringBuffer result) {
-    if (number == 0.0) {
-      subformatFixed(number, result, minimumIntegerDigits);
-      addExponentPart(0, result);
-      return;
+  private void processLeadingZeros(StringBuilder digits) {
+    // make sure we have enough trailing zeros
+    if (decimalPosition > digitsLength) {
+      while (digitsLength < decimalPosition) {
+        digits.append('0');
+        ++digitsLength;
+      }
      }

-    int exponent = (int) Math.floor(Math.log(number) / Math.log(10));
-    number /= Math.pow(10, exponent);
-
-    int minIntDigits = minimumIntegerDigits;
-    if (maximumIntegerDigits > 1 && maximumIntegerDigits >  
minimumIntegerDigits) {
-      // A repeating range is defined; adjust to it as follows.
-      // If repeat == 3, we have 6,5,4=>3; 3,2,1=>0; 0,-1,-2=>-3;
-      // -3,-4,-5=>-6, etc. This takes into account that the
-      // exponent we have here is off by one from what we expect;
-      // it is for the format 0.MMMMMx10^n.
-      while ((exponent % maximumIntegerDigits) != 0) {
-        number *= 10;
-        exponent--;
-      }
-      minIntDigits = 1;
-    } else {
-      // No repeating range is defined; use minimum integer digits.
-      if (minimumIntegerDigits < 1) {
-        exponent++;
-        number /= 10;
-      } else {
-        for (int i = 1; i < minimumIntegerDigits; i++) {
-          exponent--;
-          number *= 10;
+    if (!useExponentialNotation) {
+      // make sure we have the right number of leading zeros
+      if (decimalPosition < minimumIntegerDigits) {
+        // add leading zeros
+        StringBuilder prefix = new StringBuilder();
+        while (decimalPosition < minimumIntegerDigits) {
+          prefix.append('0');
+          ++decimalPosition;
+          ++digitsLength;
+        }
+        digits.insert(0, prefix);
+      } else if (decimalPosition > minimumIntegerDigits) {
+        // trim excess leading zeros
+        int strip = decimalPosition - minimumIntegerDigits;
+        for (int i = 0; i < strip; ++i) {
+          if (digits.charAt(i) != '0') {
+            strip = i;
+            break;
+          }
+        }
+        if (strip > 0) {
+          digits.delete(0, strip);
+          digitsLength -= strip;
+          decimalPosition -= strip;
          }
        }
      }
-
-    subformatFixed(number, result, minIntDigits);
-    addExponentPart(exponent, result);
    }

    /**
-   * This method formats a <code>double</code> into a fractional
-   * representation.
+   * Propagate a carry from incrementing the {...@code i+1}'th digit.
     *
-   * @param number value need to be formated
-   * @param result result will be written here
-   * @param minIntDigits minimum integer digits
+   * @param digits
+   * @param i digit to start incrementing
     */
-  private void subformatFixed(double number, StringBuffer result,
-      int minIntDigits) {
-    double power = Math.pow(10, maximumFractionDigits);
-    // Use 3 extra digits to allow us to do our own rounding since
-    // Java rounds up on .5 whereas some browsers might use 'round to even'
-    // or other rules.
-
-    // There are cases where more digits would be required to get
-    // guaranteed results, but this at least makes such cases rarer.
-    String fixedString = toFixed(number, maximumFractionDigits + 3);
-
-    double intValue = 0, fracValue = 0;
-    int exponentIndex = fixedString.indexOf('e');
-    if (exponentIndex != -1) {
-      // Large numbers may be returned in exponential notation: such  
numbers
-      // are integers anyway
-      intValue = Math.floor(number);
-    } else {
-      int decimalIndex = fixedString.indexOf('.');
-      int len = fixedString.length();
-      if (decimalIndex == -1) {
-        decimalIndex = len;
-      }
-      if (decimalIndex > 0) {
-        intValue = Double.parseDouble(fixedString.substring(0,  
decimalIndex));
-      }
-      if (decimalIndex < len - 1) {
-        fracValue = Double.parseDouble(fixedString.substring(decimalIndex  
+ 1));
-        fracValue = (((int) fracValue) + 500) / 1000;
-        if (fracValue >= power) {
-          fracValue -= power;
-          intValue++;
-        }
+  private void propagateCarry(StringBuilder digits, int i) {
+    boolean carry = true;
+    while (carry && i >= 0) {
+      char digit = digits.charAt(i);
+      if (digit == '9') {
+        // set this to zero and keep going
+        digits.setCharAt(i--, '0');
+      } else {
+        digits.setCharAt(i, (char) (digit + 1));
+        carry = false;
        }
      }
-
-    boolean fractionPresent = (minimumFractionDigits > 0) || (fracValue >  
0);
-
-    String intPart = makeIntString(intValue);
-    String grouping = isCurrencyFormat
-        ? numberConstants.monetaryGroupingSeparator()
-        : numberConstants.groupingSeparator();
-    String decimal = isCurrencyFormat ? numberConstants.monetarySeparator()
-        : numberConstants.decimalSeparator();
-
-    int zeroDelta = numberConstants.zeroDigit().charAt(0) - '0';
-    int digitLen = intPart.length();
-
-    if (intValue > 0 || minIntDigits > 0) {
-      for (int i = digitLen; i < minIntDigits; i++) {
-        result.append(numberConstants.zeroDigit());
-      }
-
-      for (int i = 0; i < digitLen; i++) {
-        result.append((char) (intPart.charAt(i) + zeroDelta));
-
-        if (digitLen - i > 1 && groupingSize > 0
-            && ((digitLen - i) % groupingSize == 1)) {
-          result.append(grouping);
-        }
-      }
-    } else if (!fractionPresent) {
-      // If there is no fraction present, and we haven't printed any
-      // integer digits, then print a zero.
-      result.append(numberConstants.zeroDigit());
-    }
-
-    // Output the decimal separator if we always do so.
-    if (decimalSeparatorAlwaysShown || fractionPresent) {
-      result.append(decimal);
-    }
-
-    // To make sure it lead zero will be kept.
-    String fracPart = makeIntString(Math.floor(fracValue + power + 0.5d));
-    int fracLen = fracPart.length();
-    while (fracPart.charAt(fracLen - 1) == '0' && fracLen >  
minimumFractionDigits + 1) {
-      fracLen--;
-    }
-
-    for (int i = 1; i < fracLen; i++) {
-      result.append((char) (fracPart.charAt(i) + zeroDelta));
+    if (carry) {
+      // ran off the front, prepend a 1
+      digits.insert(0, '1');
+      ++decimalPosition;
+      ++digitsLength;
+    }
+  }
+
+  /**
+   * Round the value at the requested place, propagating any carry  
backward.
+   *
+   * @param digits
+   */
+  private void roundValue(StringBuilder digits) {
+    // TODO(jat): other rounding modes?
+    if (digitsLength > decimalPosition + maximumFractionDigits
+        && digits.charAt(decimalPosition + maximumFractionDigits) >= '5') {
+      int i = decimalPosition + maximumFractionDigits - 1;
+      propagateCarry(digits, i);
      }
    }
  }
=======================================
---  
/changes/jat/bigdecimal/user/super/com/google/gwt/emul/java/math/BigDecimal.java
         
Fri Dec 11 21:30:01 2009
+++  
/changes/jat/bigdecimal/user/super/com/google/gwt/emul/java/math/BigDecimal.java
         
Thu Dec 17 14:28:24 2009
@@ -962,17 +962,17 @@
        return add(augend).round(mc);
      }
      // Cases where there is room for optimizations
-    if (this.aproxPrecision() < diffScale - 1) {
+    if (this.approxPrecision() < diffScale - 1) {
        larger = augend;
        smaller = this;
-    } else if (augend.aproxPrecision() < -diffScale - 1) {
+    } else if (augend.approxPrecision() < -diffScale - 1) {
        larger = this;
        smaller = augend;
      } else {
        // No optimization is done
        return add(augend).round(mc);
      }
-    if (mc.getPrecision() >= larger.aproxPrecision()) {
+    if (mc.getPrecision() >= larger.approxPrecision()) {
        // No optimization is done
        return add(augend).round(mc);
      }
@@ -1030,7 +1030,7 @@
              : (smallValue > val.smallValue) ? 1 : 0;
        }
        double diffScale = this.scale - val.scale;
-      double diffPrecision = this.aproxPrecision() - val.aproxPrecision();
+      double diffPrecision = this.approxPrecision() -  
val.approxPrecision();
        if (diffPrecision > diffScale + 1) {
          return thisSign;
        } else if (diffPrecision < diffScale - 1) {
@@ -1258,8 +1258,8 @@
       * Calculating how many zeros must be append to 'dividend' to obtain a
       * quotient with at least 'mc.precision()' digits
       */
-    double traillingZeros = mc.getPrecision() + 2L +  
divisor.aproxPrecision()
-        - aproxPrecision();
+    double traillingZeros = mc.getPrecision() + 2L +  
divisor.approxPrecision()
+        - approxPrecision();
      double diffScale = scale - divisor.scale;
      double newScale = diffScale; // scale of the final quotient
      int compRem; // to compare the remainder
@@ -1401,7 +1401,7 @@
        // math.04=Division by zero
        throw new ArithmeticException("Division by zero"); //$NON-NLS-1$
      }
-    if ((divisor.aproxPrecision() + newScale > this.aproxPrecision() + 1L)
+    if ((divisor.approxPrecision() + newScale > this.approxPrecision() +  
1L)
          || (this.isZero())) {
        /*
         * If the divisor's integer part is greater than this's integer  
part, the
@@ -1780,7 +1780,7 @@
       * If scale <= -32 there are at least 32 trailing bits zero in  
10^(-scale).
       * If the scale is positive and very large the long value could be  
zero.
       */
-    return ((scale <= -32) || (scale > aproxPrecision()) ? 0
+    return ((scale <= -32) || (scale > approxPrecision()) ? 0
          : toBigInteger().intValue());
    }

@@ -1810,7 +1810,7 @@
       * If scale <= -64 there are at least 64 trailing bits zero in  
10^(-scale).
       * If the scale is positive and very large the long value could be  
zero.
       */
-    return ((scale <= -64) || (scale > aproxPrecision()) ? 0L
+    return ((scale <= -64) || (scale > approxPrecision()) ? 0L
          : toBigInteger().longValue());
    }

@@ -2427,10 +2427,10 @@
        return subtract(subtrahend).round(mc);
      }
      // Now: this != 0 and subtrahend != 0
-    if (subtrahend.aproxPrecision() < diffScale - 1) {
+    if (subtrahend.approxPrecision() < diffScale - 1) {
        // Cases where it is unnecessary to subtract two numbers with very
        // different scales
-      if (mc.getPrecision() < this.aproxPrecision()) {
+      if (mc.getPrecision() < this.approxPrecision()) {
          thisSignum = this.signum();
          if (thisSignum != subtrahend.signum()) {
            tempBI = Multiplication.multiplyByPositiveInt(
@@ -2484,7 +2484,7 @@
        // (scale > 0)
        BigInteger[] integerAndFraction;
        // An optimization before do a heavy division
-      if ((scale > aproxPrecision())
+      if ((scale > approxPrecision())
            || (scale > getUnscaledValue().getLowestSetBit())) {
          // math.08=Rounding necessary
          throw new ArithmeticException("Rounding necessary"); //$NON-NLS-1$
@@ -2717,9 +2717,9 @@
     *
     * @return an approximation of {...@code precision()} value
     */
-  private double aproxPrecision() {
-    return Math.floor(((precision > 0) ? precision
-        : ((this.bitLength - 1) * LOG10_2)) + 1);
+  private double approxPrecision() {
+    return (precision > 0) ? precision
+        : Math.floor((this.bitLength - 1) * LOG10_2) + 1;
    }

    private BigInteger getUnscaledValue() {
@@ -2826,7 +2826,7 @@
     */
    private void inplaceRound(MathContext mc) {
      int mcPrecision = mc.getPrecision();
-    if (aproxPrecision() - mcPrecision <= 0 || mcPrecision == 0) {
+    if (approxPrecision() - mcPrecision <= 0 || mcPrecision == 0) {
        return;
      }
      int discardedPrecision = precision() - mcPrecision;
=======================================
---  
/changes/jat/bigdecimal/user/super/com/google/gwt/emul/java/math/BigInteger.java
         
Fri Dec 11 22:46:18 2009
+++  
/changes/jat/bigdecimal/user/super/com/google/gwt/emul/java/math/BigInteger.java
         
Thu Dec 17 14:28:24 2009
@@ -703,6 +703,7 @@
     *
     * @return this {...@code BigInteger} as a double value
     */
+  @Override
    public double doubleValue() {
      return Double.parseDouble(this.toString());
    }
@@ -1334,10 +1335,10 @@

    /**
     * Returns a string containing a string representation of this {...@code
-   * BigInteger} with base radix. If {...@code radix < Character.MIN_RADIX} or
-   * {...@code radix > Character.MAX_RADIX} then a decimal representation is
-   * returned. The characters of the string representation are generated  
with
-   * method {...@code Character.forDigit}.
+   * BigInteger} with base radix. If {...@code radix} is less than
+   * {...@link Character#MIN_RADIX} or greater than {...@link  
Character#MAX_RADIX}
+   * then a decimal representation is returned. The characters of the  
string
+   * representation are generated with method {...@link Character#forDigit}.
     *
     * @param radix base to be used for the string representation.
     * @return a string representation of this with radix 10.
=======================================
---  
/changes/jat/bigdecimal/user/test/com/google/gwt/emultest/java/math/BigDecimalArithmeticTest.java
        
Tue Dec 15 23:07:53 2009
+++  
/changes/jat/bigdecimal/user/test/com/google/gwt/emultest/java/math/BigDecimalArithmeticTest.java
        
Thu Dec 17 14:28:24 2009
@@ -210,9 +210,21 @@
      sum = val.add(BigDecimal.ZERO);
      assertEquals(val, sum);
    }
+

    /**
-   * divideAndRemainder(BigDecimal)
+   * Test the the approximate scale is computed correctly.
+   *
+   * @see https://issues.apache.org/jira/browse/HARMONY-6406
+   */
+  public void testApproxScale() {
+    BigDecimal decVal = BigDecimal.TEN.multiply(new BigDecimal("0.1"));
+    int compare = decVal.compareTo(new BigDecimal("1.00"));
+    assertEquals(0, compare);
+  }
+
+  /**
+   * divideAndRemainder(BigDecimal).
     */
    public void testDivideAndRemainder1() {
      String a  
= "3736186567876876578956958765675671119238118911893939591735";
@@ -233,7 +245,7 @@
    }

    /**
-   * divideAndRemainder(BigDecimal)
+   * divideAndRemainder(BigDecimal).
     */
    public void testDivideAndRemainder2() {
      String a  
= "3736186567876876578956958765675671119238118911893939591735";
@@ -255,7 +267,7 @@
    }

    /**
-   * divideAndRemainder(BigDecimal, MathContext)
+   * divideAndRemainder(BigDecimal, MathContext).
     */
    public void testDivideAndRemainderMathContextDOWN() {
      String a  
= "3736186567876876578956958765675671119238118911893939591735";
@@ -279,7 +291,7 @@
    }

    /**
-   * divideAndRemainder(BigDecimal, MathContext)
+   * divideAndRemainder(BigDecimal, MathContext).
     */
    public void testDivideAndRemainderMathContextUP() {
      String a  
= "3736186567876876578956958765675671119238118911893939591735";
@@ -303,7 +315,7 @@
    }

    /**
-   * Divide to BigDecimal
+   * Divide to BigDecimal.
     */
    public void testDivideBigDecimal1() {
      String a = "-37361671119238118911893939591735";
@@ -320,7 +332,7 @@
    }

    /**
-   * Divide to BigDecimal
+   * Divide to BigDecimal.
     */
    public void testDivideBigDecimal2() {
      String a = "-37361671119238118911893939591735";
@@ -337,7 +349,7 @@
    }

    /**
-   * divide(BigDecimal, MathContext)
+   * divide(BigDecimal, MathContext).
     */
    public void testDivideBigDecimalScaleMathContextCEILING() {
      String a  
= "3736186567876876578956958765675671119238118911893939591735";
@@ -357,7 +369,7 @@
    }

    /**
-   * divide(BigDecimal, MathContext)
+   * divide(BigDecimal, MathContext).
     */
    public void testDivideBigDecimalScaleMathContextDOWN() {
      String a  
= "3736186567876876578956958765675671119238118911893939591735";
@@ -377,7 +389,7 @@
    }

    /**
-   * divide(BigDecimal, MathContext)
+   * divide(BigDecimal, MathContext).
     */
    public void testDivideBigDecimalScaleMathContextFLOOR() {
      String a  
= "3736186567876876578956958765675671119238118911893939591735";
@@ -397,7 +409,7 @@
    }

    /**
-   * divide(BigDecimal, MathContext)
+   * divide(BigDecimal, MathContext).
     */
    public void testDivideBigDecimalScaleMathContextHALF_DOWN() {
      String a  
= "3736186567876876578956958765675671119238118911893939591735";
@@ -417,7 +429,7 @@
    }

    /**
-   * divide(BigDecimal, MathContext)
+   * divide(BigDecimal, MathContext).
     */
    public void testDivideBigDecimalScaleMathContextHALF_EVEN() {
      String a  
= "3736186567876876578956958765675671119238118911893939591735";
@@ -437,7 +449,7 @@
    }

    /**
-   * divide(BigDecimal, MathContext)
+   * divide(BigDecimal, MathContext).
     */
    public void testDivideBigDecimalScaleMathContextHALF_UP() {
      String a  
= "3736186567876876578956958765675671119238118911893939591735";
@@ -457,7 +469,7 @@
    }

    /**
-   * divide(BigDecimal, MathContext)
+   * divide(BigDecimal, MathContext).
     */
    public void testDivideBigDecimalScaleMathContextUP() {
      String a  
= "3736186567876876578956958765675671119238118911893939591735";
@@ -477,7 +489,7 @@
    }

    /**
-   * divide(BigDecimal, scale, RoundingMode)
+   * divide(BigDecimal, scale, RoundingMode).
     */
    public void testDivideBigDecimalScaleRoundingModeCEILING() {
      String a  
= "3736186567876876578956958765675671119238118911893939591735";
@@ -495,7 +507,7 @@
    }

    /**
-   * divide(BigDecimal, scale, RoundingMode)
+   * divide(BigDecimal, scale, RoundingMode).
     */
    public void testDivideBigDecimalScaleRoundingModeDOWN() {
      String a = "-37361671119238118911893939591735";
@@ -513,7 +525,7 @@
    }

    /**
-   * divide(BigDecimal, scale, RoundingMode)
+   * divide(BigDecimal, scale, RoundingMode).
     */
    public void testDivideBigDecimalScaleRoundingModeFLOOR() {
      String a  
= "3736186567876876578956958765675671119238118911893939591735";
@@ -531,7 +543,7 @@
    }

    /**
-   * divide(BigDecimal, scale, RoundingMode)
+   * divide(BigDecimal, scale, RoundingMode).
     */
    public void testDivideBigDecimalScaleRoundingModeHALF_DOWN() {
      String a  
= "3736186567876876578956958765675671119238118911893939591735";
@@ -549,7 +561,7 @@
    }

    /**
-   * divide(BigDecimal, scale, RoundingMode)
+   * divide(BigDecimal, scale, RoundingMode).
     */
    public void testDivideBigDecimalScaleRoundingModeHALF_EVEN() {
      String a  
= "3736186567876876578956958765675671119238118911893939591735";
@@ -567,7 +579,7 @@
    }

    /**
-   * divide(BigDecimal, scale, RoundingMode)
+   * divide(BigDecimal, scale, RoundingMode).
     */
    public void testDivideBigDecimalScaleRoundingModeHALF_UP() {
      String a  
= "3736186567876876578956958765675671119238118911893939591735";
@@ -587,7 +599,7 @@
    }

    /**
-   * divide(BigDecimal, scale, RoundingMode)
+   * divide(BigDecimal, scale, RoundingMode).
     */
    public void testDivideBigDecimalScaleRoundingModeUP() {
      String a = "-37361671119238118911893939591735";
@@ -605,7 +617,7 @@
    }

    /**
-   * Divide by zero
+   * Divide by zero.
     */
    public void testDivideByZero() {
      String a = "1231212478987482988429808779810457634781384756794987";
@@ -622,7 +634,7 @@
    }

    /**
-   * Divide with invalid rounding mode
+   * Divide with invalid rounding mode.
     */
    public void testDivideExceptionInvalidRM() {
      String a = "1231212478987482988429808779810457634781384756794987";
@@ -641,7 +653,7 @@
    }

    /**
-   * Divide with ROUND_UNNECESSARY
+   * Divide with ROUND_UNNECESSARY.
     */
    public void testDivideExceptionRM() {
      String a = "1231212478987482988429808779810457634781384756794987";
@@ -660,7 +672,7 @@
    }

    /**
-   * Divide: local variable exponent is equal to zero
+   * Divide: local variable exponent is equal to zero.
     */
    public void testDivideExpEqualsZero() {
      String a = "1231212478987482988429808779810457634781384756794987";
@@ -678,7 +690,7 @@
    }

    /**
-   * Divide: local variable exponent is greater than zero
+   * Divide: local variable exponent is greater than zero.
     */
    public void testDivideExpGreaterZero() {
      String a = "1231212478987482988429808779810457634781384756794987";
@@ -696,7 +708,7 @@
    }

    /**
-   * Divide: local variable exponent is less than zero
+   * Divide: local variable exponent is less than zero.
     */
    public void testDivideExpLessZero() {
      String a = "1231212478987482988429808779810457634781384756794987";
@@ -714,7 +726,7 @@
    }

    /**
-   * BigDecimal.divide with a scale that's too large
+   * BigDecimal.divide with a scale that's too large.
     *
     * Regression test for HARMONY-6271
     */
@@ -730,7 +742,7 @@
    }

    /**
-   * Divide: remainder is zero
+   * Divide: remainder is zero.
     */
    public void testDivideRemainderIsZero() {
      String a = "8311389578904553209874735431110";
@@ -748,7 +760,7 @@
    }

    /**
-   * Divide: rounding mode is ROUND_CEILING, result is negative
+   * Divide: rounding mode is ROUND_CEILING, result is negative.
     */
    public void testDivideRoundCeilingNeg() {
      String a  
= "-92948782094488478231212478987482988429808779810457634781384756794987";
@@ -766,7 +778,7 @@
    }

    /**
-   * Divide: rounding mode is ROUND_CEILING, result is positive
+   * Divide: rounding mode is ROUND_CEILING, result is positive.
     */
    public void testDivideRoundCeilingPos() {
      String a  
= "92948782094488478231212478987482988429808779810457634781384756794987";
@@ -784,7 +796,7 @@
    }

    /**
-   * Divide: rounding mode is ROUND_DOWN, result is negative
+   * Divide: rounding mode is ROUND_DOWN, result is negative.
     */
    public void testDivideRoundDownNeg() {
      String a  
= "-92948782094488478231212478987482988429808779810457634781384756794987";
@@ -801,7 +813,7 @@
    }

    /**
-   * Divide: rounding mode is ROUND_DOWN, result is positive
+   * Divide: rounding mode is ROUND_DOWN, result is positive.
     */
    public void testDivideRoundDownPos() {
      String a  
= "92948782094488478231212478987482988429808779810457634781384756794987";
@@ -818,7 +830,7 @@
    }

    /**
-   * Divide: rounding mode is ROUND_FLOOR, result is negative
+   * Divide: rounding mode is ROUND_FLOOR, result is negative.
     */
    public void testDivideRoundFloorNeg() {
      String a  
= "-92948782094488478231212478987482988429808779810457634781384756794987";
@@ -836,7 +848,7 @@
    }

    /**
-   * Divide: rounding mode is ROUND_FLOOR, result is positive
+   * Divide: rounding mode is ROUND_FLOOR, result is positive.
     */
    public void testDivideRoundFloorPos() {
      String a  
= "92948782094488478231212478987482988429808779810457634781384756794987";
@@ -854,7 +866,8 @@
    }

    /**
-   * Divide: rounding mode is ROUND_HALF_DOWN, result is negative;  
distance = -1
+   * Divide: rounding mode is ROUND_HALF_DOWN, result is negative;
+   * distance = -1.
     */
    public void testDivideRoundHalfDownNeg() {
      String a  
= "-92948782094488478231212478987482988429808779810457634781384756794987";
@@ -872,7 +885,7 @@
    }

    /**
-   * Divide: rounding mode is ROUND_HALF_DOWN, result is negative;  
distance = 1
+   * Divide: rounding mode is ROUND_HALF_DOWN, result is negative;  
distance = 1.
     */
    public void testDivideRoundHalfDownNeg1() {
      String a  
= 
"-92948782094488478231212478987482988798104576347813847567949855464535634534563456";
@@ -890,7 +903,7 @@
    }

    /**
-   * Divide: rounding mode is ROUND_HALF_UP, result is negative;  
equidistant
+   * Divide: rounding mode is ROUND_HALF_UP, result is negative;  
equidistant.
     */
    public void testDivideRoundHalfDownNeg2() {
      String a = "-37361671119238118911893939591735";
@@ -908,7 +921,8 @@
    }

    /**
-   * Divide: rounding mode is ROUND_HALF_DOWN, result is positive;  
distance = -1
+   * Divide: rounding mode is ROUND_HALF_DOWN, result is positive;
+   * distance = -1.
     */
    public void testDivideRoundHalfDownPos() {
      String a  
= "92948782094488478231212478987482988429808779810457634781384756794987";
@@ -926,7 +940,7 @@
    }

    /**
-   * Divide: rounding mode is ROUND_HALF_DOWN, result is positive;  
distance = 1
+   * Divide: rounding mode is ROUND_HALF_DOWN, result is positive;  
distance = 1.
     */
    public void testDivideRoundHalfDownPos1() {
      String a  
= 
"92948782094488478231212478987482988798104576347813847567949855464535634534563456";
@@ -944,7 +958,8 @@
    }

    /**
-   * Divide: rounding mode is ROUND_HALF_EVEN, result is negative;  
distance = -1
+   * Divide: rounding mode is ROUND_HALF_EVEN, result is negative;
+   * distance = -1.
     */
    public void testDivideRoundHalfEvenNeg() {
      String a  
= "-92948782094488478231212478987482988429808779810457634781384756794987";
=======================================
---  
/changes/jat/bigdecimal/user/test/com/google/gwt/emultest/java/math/BigIntegerConvertTest.java
   
Fri Dec 11 22:46:18 2009
+++  
/changes/jat/bigdecimal/user/test/com/google/gwt/emultest/java/math/BigIntegerConvertTest.java
   
Thu Dec 17 14:28:24 2009
@@ -309,6 +309,34 @@
      float aNumber = new BigInteger(a).floatValue();
      assertEquals("incorrect value", aNumber, result, 1);
    }
+
+  /**
+   * Convert a negative number to a float value. The value is near
+   * Float.MAX_VALUE, but since all calculation in JS is done in double
+   * precision, it can't be completely accurate about passing that value
+   * through.
+   */
+  public void testFloatValueNearNegMaxValue() {
+    byte[] a = {
+        0, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    int aSign = -1;
+    float aNumber = new BigInteger(aSign, a).floatValue();
+    assertEquals(-3.4028235e38, aNumber, 1e31);
+  }
+
+  /**
+   * Convert a positive number to a float value. The value is near
+   * Float.MAX_VALUE, but since all calculation in JS is done in double
+   * precision, it can't be completely accurate about passing that value
+   * through.
+   */
+  public void testFloatValueNearPosMaxValue() {
+    byte[] a = {
+        0, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    int aSign = 1;
+    float aNumber = new BigInteger(aSign, a).floatValue();
+    assertEquals(3.4028235e38, aNumber, 1e31);
+  }

    /**
     * Convert a negative number to a float value. The number's bit length  
is less
@@ -365,18 +393,6 @@
      float aNumber = new BigInteger(aSign, a).floatValue();
      assertEquals(Float.NEGATIVE_INFINITY, aNumber);
    }
-
-  /**
-   * Convert a negative number to a float value. The exponent is 1023 and  
the
-   * mantissa is all 1s. The rounding bit is 0. The result is  
-Float.MAX_VALUE.
-   */
-  public void testFloatValueNegMaxValue() {
-    byte[] a = {
-        0, -1, -1, -1, 0, -1, -1, -8, -1, -1, -1, -1, -1, -1, -1, -1, -1};
-    int aSign = -1;
-    float aNumber = new BigInteger(aSign, a).floatValue();
-    assertEquals(-Float.MAX_VALUE, aNumber, 1e30);
-  }

    /**
     * Convert a positive number to a float value. Rounding is NOT needed.
@@ -412,6 +428,30 @@
      float aNumber = new BigInteger(aSign, a).floatValue();
      assertEquals(result, aNumber, 1e19);
    }
+
+  /**
+   * Convert a negative number beyond Float.MAX_VALUE, ensuring that it is
+   * converted to Float.NEGATIVE_INFINITY.
+   */
+  public void testFloatValuePastNegMaxValue() {
+    byte[] a = {
+        0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+    int aSign = -1;
+    float aNumber = new BigInteger(aSign, a).floatValue();
+    assertEquals(Float.NEGATIVE_INFINITY, aNumber);
+  }
+
+  /**
+   * Convert a positive number beyond Float.MAX_VALUE, ensuring that it is
+   * converted to Float.POSITIVE_INFINITY.
+   */
+  public void testFloatValuePastPosMaxValue() {
+    byte[] a = {
+        0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+    int aSign = 1;
+    float aNumber = new BigInteger(aSign, a).floatValue();
+    assertEquals(Float.POSITIVE_INFINITY, aNumber);
+  }

    /**
     * Convert a positive number to a float value. The number's length is  
less
@@ -473,18 +513,6 @@
      float aNumber = new BigInteger(aSign, a).floatValue();
      assertEquals(result, aNumber, 1e31);
    }
-
-  /**
-   * Convert a positive number to a float value. The exponent is 1023 and  
the
-   * mantissa is all 1s. The rounding bit is 0. The result is  
Float.MAX_VALUE.
-   */
-  public void testFloatValuePosMaxValue() {
-    byte[] a = {
-        0, -1, -1, -1, 0, -1, -1, -8, -1, -1, -1, -1, -1, -1, -1, -1, -1};
-    int aSign = 1;
-    float aNumber = new BigInteger(aSign, a).floatValue();
-    assertEquals(Float.MAX_VALUE, aNumber, 1e30);
-  }

    /**
     * Convert a positive number to a float value. Rounding is NOT needed.
=======================================
---  
/changes/jat/bigdecimal/user/test/com/google/gwt/i18n/client/NumberFormat_en_Test.java
   
Mon Dec 14 08:34:56 2009
+++  
/changes/jat/bigdecimal/user/test/com/google/gwt/i18n/client/NumberFormat_en_Test.java
   
Thu Dec 17 14:28:24 2009
@@ -13,7 +13,6 @@
   * License for the specific language governing permissions and limitations  
under
   * the License.
   */
-
  package com.google.gwt.i18n.client;

  import com.google.gwt.junit.client.GWTTestCase;
@@ -22,7 +21,7 @@
  import java.math.BigInteger;

  /**
- * GWT JUnit tests must extend GWTTestCase.
+ * Test {...@link NumberFormat} in the {...@code en} locale.
   */
  public class NumberFormat_en_Test extends GWTTestCase {

@@ -55,9 +54,6 @@
      assertEquals("R$123,456.79", str);
    }

-  /**
-   * Add as many tests as you like.
-   */
    public void testBasicFormat() {
      String str =  
NumberFormat.getFormat("0.0000").format(123.45789179565757f);
      assertEquals("123.4579", str);
@@ -72,21 +68,23 @@
      String str = NumberFormat.getFormat("0.000").format(decVal);
      assertEquals("1000000000000000000000000.000", str);

-    // TODO(jat): enable when actually supported
-//    decVal = decVal.add(new BigDecimal(".1"));
-//    str = NumberFormat.getFormat("#,##0.000").format(decVal);
-//    assertEquals("1,000,000,000,000,000,000,000,000.100", str);
-  }
+    decVal = decVal.add(new BigDecimal(".1"));
+    str = NumberFormat.getFormat("#,##0.000").format(decVal);
+    assertEquals("1,000,000,000,000,000,000,000,000.100", str);
+
+    decVal = new BigDecimal(".1499999999999999999999");
+    str = NumberFormat.getFormat(".0").format(decVal);
+    assertEquals(".1", str);
+}

    public void testBigInteger() {
      BigInteger intVal = new BigInteger("1000000000000000000000000");
      String str = NumberFormat.getFormat("#,##0").format(intVal);
      assertEquals("1,000,000,000,000,000,000,000,000", str);

-    // TODO(jat): enable when actually supported
-//    intVal = intVal.add(BigInteger.ONE);
-//    str = NumberFormat.getFormat("#,##0").format(intVal);
-//    assertEquals("1,000,000,000,000,000,000,000,001", str);
+    intVal = intVal.add(BigInteger.ONE);
+    str = NumberFormat.getFormat("#,##0").format(intVal);
+    assertEquals("1,000,000,000,000,000,000,000,001", str);
    }

    public void testCurrency() {
@@ -262,18 +260,6 @@
      value = NumberFormat.getFormat("0E0").parse("1.2345E+4");
      assertTrue(value == 12345.0);
    }
-
-  public void testGrouping() {
-    String str;
-
-    str = NumberFormat.getFormat("#,###").format(1234567890);
-    assertEquals("1,234,567,890", str);
-    str = NumberFormat.getFormat("#,####").format(1234567890);
-    assertEquals("12,3456,7890", str);
-
-    str = NumberFormat.getFormat("#").format(1234567890);
-    assertEquals("1234567890", str);
-  }

    public void testForceLatin() {
      assertFalse(NumberFormat.forcedLatinDigits());
@@ -289,6 +275,47 @@
      assertEquals("3.14", unforced.format(3.14));
    }

+  public void testGrouping() {
+    String str;
+
+    str = NumberFormat.getFormat("#,###").format(1234567890);
+    assertEquals("1,234,567,890", str);
+    str = NumberFormat.getFormat("#,####").format(1234567890);
+    assertEquals("12,3456,7890", str);
+
+    str = NumberFormat.getFormat("#").format(1234567890);
+    assertEquals("1234567890", str);
+  }
+
+  // See external issue 3140
+  public void testLeadingZeros() {
+    String str;
+
+    str =  
NumberFormat.getFormat("0,000,000,000.#").format(123456789.489123);
+    assertEquals("0,123,456,789.5", str);
+
+    str = NumberFormat.getFormat("#,###.####").format(0.414014);
+    assertEquals("0.414", str); // why leading 0?
+
+    str = NumberFormat.getFormat("#.####").format(0.414014);
+    assertEquals("0.414", str); // why leading 0?
+
+    str = NumberFormat.getFormat("#.0###").format(0.414014);
+    assertEquals(".414", str);
+
+    str = NumberFormat.getFormat("0.0###").format(0.414014);
+    assertEquals("0.414", str);
+
+    str = NumberFormat.getFormat("0.####").format(0.414014);
+    assertEquals("0.414", str);
+
+    str = NumberFormat.getFormat("0.0000").format(0.414014);
+    assertEquals("0.4140", str);
+
+    str = NumberFormat.getFormat("#.0000").format(0.414014);
+    assertEquals(".4140", str);
+  }
+
    public void testNegative() {
      String str;

@@ -347,41 +374,6 @@
      str = NumberFormat.getFormat("a''b#").format(123);
      assertEquals("a'b123", str);
    }
-
-  public void testStandardFormat() {
-    String str;
-
-    str = NumberFormat.getCurrencyFormat().format(1234.579);
-    assertEquals("$1,234.58", str);
-    str = NumberFormat.getDecimalFormat().format(1234.579);
-    assertEquals("1,234.579", str);
-    str = NumberFormat.getPercentFormat().format(1234.579);
-    assertEquals("123,458%", str);
-    str = NumberFormat.getScientificFormat().format(1234.579);
-    assertEquals("1E3", str);
-  }
-
-  public void testZeros() {
-    String str;
-
-    str = NumberFormat.getFormat("#.#").format(0);
-    assertEquals("0", str);
-    str = NumberFormat.getFormat("#.").format(0);
-    assertEquals("0.", str);
-    str = NumberFormat.getFormat(".#").format(0);
-    assertEquals(".0", str);
-    str = NumberFormat.getFormat("#").format(0);
-    assertEquals("0", str);
-
-    str = NumberFormat.getFormat("#0.#").format(0);
-    assertEquals("0", str);
-    str = NumberFormat.getFormat("#0.").format(0);
-    assertEquals("0.", str);
-    str = NumberFormat.getFormat("#.0").format(0);
-    assertEquals(".0", str);
-    str = NumberFormat.getFormat("#").format(0);
-    assertEquals("0", str);
-  }

    public void testRounding() {
      String str;
@@ -439,5 +431,69 @@

      str = NumberFormat.getFormat("#0.0000000").format(1.23756789E-05);
      assertEquals("0.0000124", str);
+
+    str =  
NumberFormat.getFormat("#,##,###,##0.00000000000").format(111.18);
+    assertEquals("111.18000000000", str);
+  }
+
+  public void testStandardFormat() {
+    String str;
+
+    str = NumberFormat.getCurrencyFormat().format(1234.579);
+    assertEquals("$1,234.58", str);
+    str = NumberFormat.getDecimalFormat().format(1234.579);
+    assertEquals("1,234.579", str);
+    str = NumberFormat.getPercentFormat().format(1234.579);
+    assertEquals("123,458%", str);
+    str = NumberFormat.getScientificFormat().format(1234.579);
+    assertEquals("1E3", str);
+  }
+
+  public void testToScaledString() {
+    StringBuilder buf = new StringBuilder();
+    int scale = NumberFormat.toScaledString(buf, .1);
+    String str = buf.toString();
+    assertStartsWith("100", str.substring(str.length() + scale));
+    assertAllZeros(str, str.length() + scale);
+    buf = new StringBuilder();
+    scale = NumberFormat.toScaledString(buf, 12345e38);
+    str = buf.toString();
+    assertStartsWith("12345", str);
+    assertEquals(43, scale + str.length());
+  }
+
+  public void testZeros() {
+    String str;
+
+    str = NumberFormat.getFormat("#.#").format(0);
+    assertEquals("0", str);
+    str = NumberFormat.getFormat("#.").format(0);
+    assertEquals("0.", str);
+    str = NumberFormat.getFormat(".#").format(0);
+    assertEquals(".0", str);
+    str = NumberFormat.getFormat("#").format(0);
+    assertEquals("0", str);
+
+    str = NumberFormat.getFormat("#0.#").format(0);
+    assertEquals("0", str);
+    str = NumberFormat.getFormat("#0.").format(0);
+    assertEquals("0.", str);
+    str = NumberFormat.getFormat("#.0").format(0);
+    assertEquals(".0", str);
+    str = NumberFormat.getFormat("#").format(0);
+    assertEquals("0", str);
+  }
+
+  private void assertAllZeros(String str, int prefixLen) {
+    if (prefixLen > str.length()) {
+      prefixLen = str.length();
+    }
+    for (int i = 0; i < prefixLen; ++i) {
+      assertEquals('0', str.charAt(i));
+    }
+  }
+
+  private void assertStartsWith(String prefix, String str) {
+    assertTrue(str + " does not start with " + prefix,  
str.startsWith(prefix));
    }
  }

-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to