From 67bee5c0982d35f0d6a1350e002b7062a498afe7 Mon Sep 17 00:00:00 2001 From: Spotandjake <40705786+spotandjake@users.noreply.github.com> Date: Sat, 4 Mar 2023 18:40:45 -0500 Subject: [PATCH] feat(stdlib)!: Add optimization for `Number.pow(Rational, Int)` (#1716) * feat!: Add Optimization for `Rationional^Int` * Update stdlib/runtime/numbers.gr --------- Co-authored-by: Oscar Spencer --- compiler/test/stdlib/number.test.gr | 5 +++++ stdlib/runtime/numbers.gr | 23 ++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/compiler/test/stdlib/number.test.gr b/compiler/test/stdlib/number.test.gr index 2d6cd929a..8bcb4a20d 100644 --- a/compiler/test/stdlib/number.test.gr +++ b/compiler/test/stdlib/number.test.gr @@ -217,6 +217,11 @@ assert Number.pow(10223372036854775809, 10) == 12472159440978016923768615307032788210916694000775261660538874886865415760948494778813645195039710006678013364969179502650466497057008288260604039903029954443675868581729857084924132550246401 assert Number.pow(1, 9223372036854775809) == 1 assert Number.pow(2.0, 9223372036854775809) == Infinity +assert Number.pow(1/2, 2) == 1/4 +assert Number.pow(1/2, 3) == 1/8 +assert Number.isRational(Number.pow(1/2, 2)) +assert Number.isRational(Number.pow(1/2, 3)) +assert Number.pow(1/2, -2) == 4 // exp assert Number.exp(1) == 2.718281828459045 assert Number.exp(10) == 22026.465794806703 diff --git a/stdlib/runtime/numbers.gr b/stdlib/runtime/numbers.gr index 1cb22ea06..e1c5caa33 100644 --- a/stdlib/runtime/numbers.gr +++ b/stdlib/runtime/numbers.gr @@ -2803,13 +2803,30 @@ let rec expBySquaring = (y, x, n) => { provide let (**) = (base, power) => { let (==) = numberEq let (!=) = (x, y) => !numberEq(x, y) + let basePtr = WasmI32.fromGrain(base) + let powerPtr = WasmI32.fromGrain(power) if (base == 1 && power != 0) { return 1 - } else if ( - isInteger(WasmI32.fromGrain(base)) && isInteger(WasmI32.fromGrain(power)) - ) { + } else if (isInteger(basePtr) && isInteger(powerPtr)) { if (power < 0) return expBySquaring(1, 1 / base, power * -1) else return expBySquaring(1, base, power) + } else if (isRational(basePtr) && isInteger(powerPtr)) { + // Apply expBySquaring to numerator and denominator + let numerator = WasmI32.fromGrain(base) + Memory.incRef(numerator) + let numerator = WasmI32.toGrain(numerator): Rational + let numerator = rationalNumerator(numerator) + let denominator = WasmI32.fromGrain(base) + Memory.incRef(denominator) + let denominator = WasmI32.toGrain(denominator): Rational + let denominator = rationalDenominator(denominator) + let numerator = + if (power < 0) expBySquaring(1, 1 / numerator, power * -1) + else expBySquaring(1, numerator, power) + let denominator = + if (power < 0) expBySquaring(1, 1 / denominator, power * -1) + else expBySquaring(1, denominator, power) + return numerator / denominator } else { // Based on https://git.musl-libc.org/cgit/musl/tree/src/math/pow.c from WasmF64 use {