| ... | @@ -7,6 +7,7 @@ | ... | @@ -7,6 +7,7 @@ |
| 7 | const std = @import("std"); | 7 | const std = @import("std"); |
| 8 | const builtin = @import("builtin"); | 8 | const builtin = @import("builtin"); |
| 9 | const maxInt = std.math.maxInt; | 9 | const maxInt = std.math.maxInt; |
| | 10 | const isNan = std.math.isNan; |
| 10 | | 11 | |
| 11 | const is_wasm = switch (builtin.arch) { | 12 | const is_wasm = switch (builtin.arch) { |
| 12 | .wasm32, .wasm64 => true, | 13 | .wasm32, .wasm64 => true, |
| ... | @@ -480,7 +481,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) T { | ... | @@ -480,7 +481,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) T { |
| 480 | const sx = if (T == f32) @intCast(u32, ux & 0x80000000) else @intCast(i32, ux >> bits_minus_1); | 481 | const sx = if (T == f32) @intCast(u32, ux & 0x80000000) else @intCast(i32, ux >> bits_minus_1); |
| 481 | var i: uint = undefined; | 482 | var i: uint = undefined; |
| 482 | | 483 | |
| 483 | if (uy << 1 == 0 or isNan(uint, uy) or ex == mask) | 484 | if (uy << 1 == 0 or isNan(@bitCast(T, uy)) or ex == mask) |
| 484 | return (x * y) / (x * y); | 485 | return (x * y) / (x * y); |
| 485 | | 486 | |
| 486 | if (ux << 1 <= uy << 1) { | 487 | if (ux << 1 <= uy << 1) { |
| ... | @@ -549,18 +550,6 @@ fn generic_fmod(comptime T: type, x: T, y: T) T { | ... | @@ -549,18 +550,6 @@ fn generic_fmod(comptime T: type, x: T, y: T) T { |
| 549 | return @bitCast(T, ux); | 550 | return @bitCast(T, ux); |
| 550 | } | 551 | } |
| 551 | | 552 | |
| 552 | fn isNan(comptime T: type, bits: T) bool { | | |
| 553 | if (T == u16) { | | |
| 554 | return (bits & 0x7fff) > 0x7c00; | | |
| 555 | } else if (T == u32) { | | |
| 556 | return (bits & 0x7fffffff) > 0x7f800000; | | |
| 557 | } else if (T == u64) { | | |
| 558 | return (bits & (maxInt(u64) >> 1)) > (u64(0x7ff) << 52); | | |
| 559 | } else { | | |
| 560 | unreachable; | | |
| 561 | } | | |
| 562 | } | | |
| 563 | | | |
| 564 | // NOTE: The original code is full of implicit signed -> unsigned assumptions and u32 wraparound | 553 | // NOTE: The original code is full of implicit signed -> unsigned assumptions and u32 wraparound |
| 565 | // behaviour. Most intermediate i32 values are changed to u32 where appropriate but there are | 554 | // behaviour. Most intermediate i32 values are changed to u32 where appropriate but there are |
| 566 | // potentially some edge cases remaining that are not handled in the same way. | 555 | // potentially some edge cases remaining that are not handled in the same way. |