diff --git a/compiler/test/stdlib/number.test.gr b/compiler/test/stdlib/number.test.gr index 2d6cd929a0..8bcb4a20d2 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 1cb22ea063..e1c5caa339 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 {