Skip to content

Commit

Permalink
Builtin pow function support for large arguments
Browse files Browse the repository at this point in the history
This helps with beeware#47, as I am a
first-timer!

There are still some issues with very large arguments, but
I can file a separate bug for that, assuming it is not already known.
  • Loading branch information
swenson committed Aug 15, 2016
1 parent 6cb06ce commit 5bdacc8
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 1 deletion.
29 changes: 28 additions & 1 deletion batavia/core/builtins.js
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,34 @@ batavia.builtins.pow = function(args) {
x = args[0];
y = args[1];
z = args[2];
return Math.pow(x, y) % z;

if (!batavia.isinstance(x, batavia.types.Int) ||
!batavia.isinstance(y, batavia.types.Int) ||
!batavia.isinstance(y, batavia.types.Int)) {
throw new batavia.builtins.TypeError("pow() requires all arguments be integers when 3 arguments are present");
}
if (y < 0) {
throw new batavia.builtins.TypeError("Builtin Batavia does not support negative exponents")
}
if (y == 0) {
return 1;
}
if (z == 1) {
return 0;
}

// right-to-left exponentiation to reduce memory and time
// See https://en.wikipedia.org/wiki/Modular_exponentiation#Right-to-left_binary_method
var result = 1;
var base = x % z;
while (y > 0) {
if ((y & 1) == 1) {
result = (result * base) % z;
}
y >>= 1;
base = (base * base) % z;
}
return result;
} else {
throw new batavia.builtins.TypeError("pow expected at least 2 arguments, got " + args.length);
}
Expand Down
31 changes: 31 additions & 0 deletions tests/builtins/test_pow.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,37 @@ def test_float_neg_y_with_z(self):
print(pow(x, y, z))
""")

def test_huge_y(self):
self.assertCodeExecution("""
x = 2
y = 1000000000
z = 3
print(pow(x, y, z))
""")

def test_lots_of_pows(self):
self.assertCodeExecution("""
print(pow(967, 441, 8))
print(pow(911, 940, 583))
print(pow(672, 84, 767))
print(pow(237, 30, 789))
print(pow(346, 623, 616))
print(pow(148, 183, 115))
print(pow(14, 487, 965))
print(pow(64, 541, 466))
print(pow(602, 89, 580))
print(pow(269, 556, 645))
print(pow(481, 355, 250))
print(pow(934, 453, 531))
print(pow(19, 508, 6))
print(pow(143, 473, 378))
print(pow(54, 588, 165))
print(pow(557, 144, 938))
print(pow(771, 957, 142))
print(pow(305, 39, 277))
print(pow(807, 177, 155))
print(pow(955, 154, 834))
""")

class BuiltinPowFunctionTests(BuiltinFunctionTestCase, TranspileTestCase):
functions = ["pow"]
Expand Down

0 comments on commit 5bdacc8

Please sign in to comment.