Skip to content

Commit

Permalink
fix(stdlib): Properly handle extremely large integer bases in `Number…
Browse files Browse the repository at this point in the history
….(**)` (#1950)
  • Loading branch information
spotandjake committed Jan 25, 2024
1 parent 7cdcf95 commit 84c076f
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 11 deletions.
1 change: 1 addition & 0 deletions compiler/test/stdlib/number.test.gr
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ assert 10223372036854775809 ** 10 ==
12472159440978016923768615307032788210916694000775261660538874886865415760948494778813645195039710006678013364969179502650466497057008288260604039903029954443675868581729857084924132550246401
assert 1 ** 9223372036854775809 == 1
assert 2.0 ** 9223372036854775809 == Infinity
assert 2.0 ** 99223372036854775809 == Infinity
assert pow(1/2, 2) == 1/4
assert pow(1/2, 3) == 1/8
assert Number.isRational(pow(1/2, 2))
Expand Down
21 changes: 10 additions & 11 deletions stdlib/runtime/numbers.gr
Original file line number Diff line number Diff line change
Expand Up @@ -2859,19 +2859,20 @@ provide let (**) = (base, power) => {
} else {
// Based on https://git.musl-libc.org/cgit/musl/tree/src/math/pow.c
from WasmF64 use { (==), (!=), (<=), (/), (*), (+) }
// Constants
let infinity = 1.0W / 0.0W
let nan = 0.0W / 0.0W
let x = coerceNumberToWasmF64(base)
let y = coerceNumberToWasmF64(power)
// Fast paths
if (WasmF64.abs(y) <= 2.0W) {
if (y == 2.0W) {
return WasmI32.toGrain(newFloat64(x * x)): Number
} else if (y == 0.5W) {
let output =
if (x != infinity) WasmF64.abs(WasmF64.sqrt(x)) else infinity
return WasmI32.toGrain(newFloat64(output)): Number
if (x != InfinityW) {
return WasmI32.toGrain(
newFloat64(WasmF64.abs(WasmF64.sqrt(x)))
): Number
} else {
return Infinity
}
} else if (y == -1.0W) {
return WasmI32.toGrain(newFloat64(1.0W / x)): Number
} else if (y == 1.0W) {
Expand Down Expand Up @@ -3002,9 +3003,7 @@ provide let (**) = (base, power) => {
let mut s = 1.0W
if (hx < 0n) {
if (yisint == 0n) {
from WasmF64 use { (-) }
let d = x - x
return WasmI32.toGrain(newFloat64(d / d)): Number
return NaN
} else if (yisint == 1n) s = -1.0W
}
let mut t1 = 0.0W
Expand All @@ -3022,10 +3021,10 @@ provide let (**) = (base, power) => {
if (iy > 0x43F00000n) {
if (ix <= 0x3FEFFFFFn) {
let output = if (hy < 0n) huge * huge else tiny * tiny
return WasmI32.toGrain(newFloat64(z)): Number
return WasmI32.toGrain(newFloat64(output)): Number
} else if (ix >= 0x3FF00000n) {
let output = if (hy > 0n) huge * huge else tiny * tiny
return WasmI32.toGrain(newFloat64(z)): Number
return WasmI32.toGrain(newFloat64(output)): Number
}
}
if (ix < 0x3FEFFFFFn) {
Expand Down

0 comments on commit 84c076f

Please sign in to comment.