diff options
| author | hdert <40216616+hdert@users.noreply.github.com> | 2024-01-20 03:25:03 +1300 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2024-01-19 22:00:04 -0800 |
| commit | 314533c28bdb57f4cdc159fe376a10037e72d5f3 (patch) | |
| tree | 34c1992a436da19576e3ad71fedc4a7c60f30ad1 /lib/std/math | |
| parent | 480a2f7f02f9dcb2e53f4515fc26fb72ad78ffd9 (diff) | |
| download | zig-314533c28bdb57f4cdc159fe376a10037e72d5f3.tar.gz zig-314533c28bdb57f4cdc159fe376a10037e72d5f3.zip | |
std/math/pow: Fix #18553, isOddInteger: Return false if float value is greater than 1 << 53 (see comment), add test cases
Diffstat (limited to 'lib/std/math')
| -rw-r--r-- | lib/std/math/pow.zig | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/lib/std/math/pow.zig b/lib/std/math/pow.zig index b095ff1df7..a69fccc907 100644 --- a/lib/std/math/pow.zig +++ b/lib/std/math/pow.zig @@ -178,10 +178,26 @@ pub fn pow(comptime T: type, x: T, y: T) T { } fn isOddInteger(x: f64) bool { + if (@abs(x) >= 1 << 53) { + // From https://golang.org/src/math/pow.go + // 1 << 53 is the largest exact integer in the float64 format. + // Any number outside this range will be truncated before the decimal point and therefore will always be + // an even integer. + // Without this check and if x overflows i64 the @intFromFloat(r.ipart) conversion below will panic + return false; + } const r = math.modf(x); return r.fpart == 0.0 and @as(i64, @intFromFloat(r.ipart)) & 1 == 1; } +test "math.pow.isOddInteger" { + try expect(isOddInteger(math.maxInt(i64) * 2) == false); + try expect(isOddInteger(math.maxInt(i64) * 2 + 1) == false); + try expect(isOddInteger(1 << 53) == false); + try expect(isOddInteger(12.0) == false); + try expect(isOddInteger(15.0) == true); +} + test "math.pow" { const epsilon = 0.000001; |
