From 3ca06a50ee47b476fb44aedc69293609023e1bc5 Mon Sep 17 00:00:00 2001 From: "A. R. Shajii" Date: Sat, 25 Mar 2023 09:35:43 -0400 Subject: [PATCH] Add builtin pow() (fix #294) --- stdlib/internal/builtin.codon | 23 +++++++++++++++++++++++ test/core/bltin.codon | 29 +++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/stdlib/internal/builtin.codon b/stdlib/internal/builtin.codon index 7567ce65..46854ecf 100644 --- a/stdlib/internal/builtin.codon +++ b/stdlib/internal/builtin.codon @@ -323,6 +323,29 @@ def oct(n): def hex(n): return _int_format(n.__index__(), 16, "0x") +def pow(base: float, exp: float): + return base ** exp + +@overload +def pow(base: int, exp: int, mod: Optional[int] = None): + if exp < 0: + raise ValueError("pow() negative int exponent not supported") + + if mod is not None: + if mod == 0: + raise ValueError("pow() 3rd argument cannot be 0") + base %= mod + + result = 1 + while exp > 0: + if exp & 1: + x = result * base + result = x % mod if mod is not None else x + y = base * base + base = y % mod if mod is not None else y + exp >>= 1 + return result % mod if mod is not None else result + @extend class int: def _from_str(s: str, base: int): diff --git a/test/core/bltin.codon b/test/core/bltin.codon index ec334bf4..3e1b723d 100644 --- a/test/core/bltin.codon +++ b/test/core/bltin.codon @@ -258,6 +258,34 @@ def test_divmod(): assert math.isclose(result[0], exp_result[0]) assert math.isclose(result[1], exp_result[1]) +@test +def test_pow(): + assert pow(3, 4) == 81 + assert pow(-3, 3) == -27 + assert pow(1, 0) == 1 + assert pow(-1, 0) == 1 + assert pow(0, 0) == 1 + assert pow(12, 12, 42) == 36 + assert pow(1234, 4321, 99) == 46 + assert pow(9999, 9999, 2) == 1 + assert pow(0, 0, 1) == 0 + + try: + pow(1, -1, 2) + assert False + except ValueError as e: + assert 'negative' in str(e) + + try: + pow(1, 1, 0) + assert False + except ValueError as e: + assert 'cannot be 0' in str(e) + + assert pow(1.5, 2) == 2.25 + assert pow(9, 0.5) == 3.0 + assert pow(2.0, -1.0) == 0.5 + @test def test_num_from_str(): assert int('0') == 0 @@ -337,6 +365,7 @@ test_gen_builtins() test_int_format() test_reversed() test_divmod() +test_pow() test_num_from_str() test_files(open) import gzip