Int64(int value) should not be sensitive to rounding errors (#26)
* Int64(int value) should not be sensitive to rounding errors
* fix error in test
* fix constructor
* new package version number
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9ec23ff..228c997 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+## 0.10.6
+
+* Fix `Int64([int value])` constructor to avoid rounding error on intermediate
+ results for large negative inputs when compiled to JavaScript. `new
+ Int64(-1000000000000000000)` used to produce the same value as
+ `Int64.parseInt("-1000000000000000001")`
+
## 0.10.5
* Fix strong mode warning in overridden `compareTo()` methods.
diff --git a/lib/src/int64.dart b/lib/src/int64.dart
index cc78ab6..c25b8fa 100644
--- a/lib/src/int64.dart
+++ b/lib/src/int64.dart
@@ -128,7 +128,7 @@
bool negative = false;
if (value < 0) {
negative = true;
- value = -value - 1;
+ value = -value;
}
// Avoid using bitwise operations that in JavaScript coerce their input to
// 32 bits.
@@ -138,12 +138,9 @@
value -= v1 * 4194304;
v0 = value;
- if (negative) {
- v0 = ~v0;
- v1 = ~v1;
- v2 = ~v2;
- }
- return Int64._masked(v0, v1, v2);
+ return negative
+ ? Int64._negate(_MASK & v0, _MASK & v1, _MASK2 & v2)
+ : Int64._masked(v0, v1, v2);
}
factory Int64.fromBytes(List<int> bytes) {
diff --git a/pubspec.yaml b/pubspec.yaml
index 185275f..a80a13e 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,9 +1,9 @@
name: fixnum
-version: 0.10.5
+version: 0.10.6
author: Dart Team <misc@dartlang.org>
description: Library for 32- and 64-bit signed fixed-width integers.
homepage: https://github.com/dart-lang/fixnum
dev_dependencies:
test: ^0.12.0
environment:
- sdk: ">=0.8.10+6 <2.0.0"
+ sdk: ">=1.8.3 <2.0.0-dev.infinity"
diff --git a/test/int64_test.dart b/test/int64_test.dart
index 4ae7aea..fbd008d 100644
--- a/test/int64_test.dart
+++ b/test/int64_test.dart
@@ -747,6 +747,20 @@
expect(-(Int64.MIN_VALUE + new Int64(1)), Int64.MAX_VALUE);
});
+ test("", () {
+ check(int n) {
+ // Sign change should commute with conversion.
+ expect(-new Int64(-n), new Int64(n));
+ expect(new Int64(-n), -new Int64(n));
+ }
+
+ check(10);
+ check(1000000000000000000);
+ check(9223372000000000000); // near Int64.MAX_VALUE, has exact double value
+ check(9223372036854775807); // Int64.MAX_VALUE, rounds up to -MIN_VALUE
+ check(-9223372036854775808); // Int64.MIN_VALUE
+ });
+
group("parse", () {
test("parseRadix10", () {
checkInt(int x) {