Update Intl to support fixed-size VM integers
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=181368376
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f71821a..d9d78ba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
* Add a customPattern parameter to the currency constructor. This can be used
to provide a custom pattern if you have one, e.g. for accounting formats.
* Update data to CLDR 32.0.1
+ * Update for Dart 2.0 fixed-size integers.
## 0.15.2
* Group the padding digits to the left of the number, if present. e.g. 00,001.
diff --git a/lib/src/intl/number_format.dart b/lib/src/intl/number_format.dart
index 4ca2d22..b4dce92 100644
--- a/lib/src/intl/number_format.dart
+++ b/lib/src/intl/number_format.dart
@@ -640,8 +640,10 @@
_pad(minimumExponentDigits, exponent.toString());
}
- /// Used to test if we have exceeded Javascript integer limits.
- final _maxInt = pow(2, 52);
+ /// Used to test if we have exceeded integer limits.
+ // TODO(alanknight): Do we have a MaxInt constant we could use instead?
+ static final _maxInt = 1 is double ? pow(2, 52) : 1.0e300.floor();
+ static final _maxDigits = (log(_maxInt)/log(10)).floor();
/// Helpers to check numbers that don't conform to the [num] interface,
/// e.g. Int64
@@ -673,7 +675,8 @@
// Not a normal number, but int-like, e.g. Int64
return number;
} else {
- // TODO(alanknight): Do this more efficiently. If IntX had floor and round we could avoid this.
+ // TODO(alanknight): Do this more efficiently. If IntX had floor and
+ // round we could avoid this.
var basic = _floor(number);
var fraction = (number - basic).toDouble().round();
return fraction == 0 ? number : number + fraction;
@@ -732,6 +735,13 @@
// integer pieces.
integerPart = _floor(number);
var fraction = number - integerPart;
+ if (fraction.toInt() != 0) {
+ // If the fractional part leftover is > 1, presumbly the number
+ // was too big for a fixed-size integer, so leave it as whatever
+ // it was - the obvious thing is a double.
+ integerPart = number;
+ fraction = 0;
+ }
/// If we have significant digits, recalculate the number of fraction
/// digits based on that.
@@ -789,13 +799,16 @@
/// Compute the raw integer digits which will then be printed with
/// grouping and translated to localized digits.
String _integerDigits(integerPart, extraIntegerDigits) {
- // If the int part is larger than 2^52 and we're on Javascript (so it's
- // really a float) it will lose precision, so pad out the rest of it
- // with zeros. Check for Javascript by seeing if an integer is double.
+ // If the integer part is larger than the maximum integer size
+ // (2^52 on Javascript, 2^63 on the VM) it will lose precision,
+ // so pad out the rest of it with zeros.
var paddingDigits = '';
- if (1 is double && integerPart is num && integerPart > _maxInt) {
- var howManyDigitsTooBig = (log(integerPart) / LN10).ceil() - 16;
- var divisor = pow(10, howManyDigitsTooBig).round();
+ if (integerPart is num && integerPart > _maxInt) {
+ var howManyDigitsTooBig = (log(integerPart) / LN10).ceil() - _maxDigits;
+ num divisor = pow(10, howManyDigitsTooBig).round();
+ // pow() produces 0 if the result is too large for a 64-bit int.
+ // If that happens, use a floating point divisor instead.
+ if (divisor == 0) divisor = pow(10.0, howManyDigitsTooBig);
paddingDigits = '0' * howManyDigitsTooBig.toInt();
integerPart = (integerPart / divisor).truncate();
}
diff --git a/test/number_format_test.dart b/test/number_format_test.dart
index 77ddb8c..b9e4627 100644
--- a/test/number_format_test.dart
+++ b/test/number_format_test.dart
@@ -47,6 +47,9 @@
var testNumbersOnlyForTheVM = {
"9,000,000,000,000,000,000":
9000000000000000000,
+ "9,223,372,036,854,775,807":
+ 9223372036854775807
+
};
get allTestNumbers => new Map.from(testNumbersWeCanReadBack)