Fix for issue 10534. Implement int.pow correctly using exponentiation by squaring.

Note that int.pow is now considerably slower than double.pow.

R=floitsch@google.com

Review URL: https://codereview.chromium.org//14619027

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@22635 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
srdjan@google.com 2013-05-13 17:41:58 +00:00
parent 0b9c15a102
commit d0c639e474
4 changed files with 26 additions and 8 deletions

View file

@ -164,12 +164,17 @@ class _IntegerImplementation {
double toDouble() { return new _Double.fromInteger(this); }
int pow(int exponent) {
double res = this.toDouble().pow(exponent);
if (res.isInfinite) {
// Use Bigint instead.
throw "_IntegerImplementation.pow not implemented for large integers.";
// Exponentiation by squaring.
int base = this;
int result = 1;
while (exponent != 0) {
if ((exponent & 1) == 1) {
result *= base;
}
exponent >>= 1;
base *= base;
}
return res.toInt();
return result;
}
String toStringAsFixed(int fractionDigits) {

View file

@ -5,8 +5,11 @@
import "dart:typed_data";
// A VM patch of the dart:math library.
// If [x] is an [int] and [exponent] is a non-negative [int], the result is
// an [int], otherwise the result is a [double].
patch num pow(num x, num exponent) {
if (exponent is int) {
if ((x is int) && (exponent is int) && (exponent >= 0)) {
return x.pow(exponent);
}
// Double.pow will call exponent.toDouble().

View file

@ -85,14 +85,23 @@ var expectedResults =
void main() {
int exp = 0;
for (int val in expectedResults) {
Expect.equals(val, pow(2, exp++));
Expect.equals(val, pow(2, exp));
Expect.equals(val.toDouble(), pow(2, exp.toDouble()));
exp++;
}
// Optimize it.
for (int i = 0; i < 8888; i++) {
pow(2, 3);
pow(2.0, 3.0);
}
exp = 0;
for (int val in expectedResults) {
Expect.equals(val, pow(2, exp++));
Expect.equals(val, pow(2, exp));
Expect.equals(val.toDouble(), pow(2, exp.toDouble()));
exp++;
}
// Test Bigints.
Expect.equals(5559917313492231481, pow(11, 18));
Expect.equals(672749994932560009201, pow(11, 20));
}

View file

@ -102,6 +102,7 @@ io/process_exit_negative_test: Fail, OK # relies on a static error that is a war
package/package_isolate_test: Skip # spawnUri does not work in dart2js. See issue 3051
debugger/*: Skip # Do not run standalone vm debugger tests with dart2js.
left_shift_bit_and_op_test: Skip # Integers exceed dart2js precision.
pow_test: Skip # Precision > 53 bits.
[ $compiler == dart2js && $jscl ]
assert_test: Fail, OK # Assumes unspecified fields on the AssertionError.