Skip to content

Commit

Permalink
feat(stdlib)!: Add optimization for Number.pow(Rational, Int) (grai…
Browse files Browse the repository at this point in the history
…n-lang#1716)

* feat!: Add Optimization for `Rationional^Int`

* Update stdlib/runtime/numbers.gr

---------

Co-authored-by: Oscar Spencer <oscar.spen@gmail.com>
  • Loading branch information
spotandjake and ospencer authored Mar 4, 2023
1 parent 3c86e45 commit 67bee5c
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 3 deletions.
5 changes: 5 additions & 0 deletions compiler/test/stdlib/number.test.gr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 20 additions & 3 deletions stdlib/runtime/numbers.gr
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 67bee5c

Please sign in to comment.