also looking at this
fix(interpreter): keep 2^63 as a float in floor, ceil and round
#932
2 files
+22
-3
Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.
| @@ -3464,8 +3464,10 @@ pub const Interpreter = struct { | ||
| 3464 | 3464 | if (val == .Float) { |
| 3465 | 3465 | const floored = @floor(val.Float); |
| 3466 | 3466 | // If the result fits in i64, return Int; otherwise Float. |
| 3467 | // maxInt(i64) rounds up to 2^63 as an f64, which does not fit, | |
| 3468 | // so the upper bound is exclusive. | |
| 3467 | 3469 | if (floored >= @as(f64, @floatFromInt(std.math.minInt(i64))) and |
| 3468 | floored <= @as(f64, @floatFromInt(std.math.maxInt(i64)))) | |
| 3470 | floored < @as(f64, @floatFromInt(std.math.maxInt(i64)))) | |
| 3469 | 3471 | { |
| 3470 | 3472 | return Value{ .Int = @intFromFloat(floored) }; |
| 3471 | 3473 | } |
| @@ -3481,7 +3483,7 @@ pub const Interpreter = struct { | ||
| 3481 | 3483 | if (val == .Float) { |
| 3482 | 3484 | const ceiled = @ceil(val.Float); |
| 3483 | 3485 | if (ceiled >= @as(f64, @floatFromInt(std.math.minInt(i64))) and |
| 3484 | ceiled <= @as(f64, @floatFromInt(std.math.maxInt(i64)))) | |
| 3486 | ceiled < @as(f64, @floatFromInt(std.math.maxInt(i64)))) | |
| 3485 | 3487 | { |
| 3486 | 3488 | return Value{ .Int = @intFromFloat(ceiled) }; |
| 3487 | 3489 | } |
| @@ -3497,7 +3499,7 @@ pub const Interpreter = struct { | ||
| 3497 | 3499 | if (val == .Float) { |
| 3498 | 3500 | const rounded = @round(val.Float); |
| 3499 | 3501 | if (rounded >= @as(f64, @floatFromInt(std.math.minInt(i64))) and |
| 3500 | rounded <= @as(f64, @floatFromInt(std.math.maxInt(i64)))) | |
| 3502 | rounded < @as(f64, @floatFromInt(std.math.maxInt(i64)))) | |
| 3501 | 3503 | { |
| 3502 | 3504 | return Value{ .Int = @intFromFloat(rounded) }; |
| 3503 | 3505 | } |
| @@ -46,6 +46,23 @@ test "eval: print a string literal (hello world)" { | ||
| 46 | 46 | ); |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | test "eval: floor, ceil and round keep 2^63 as a float" { | |
| 50 | try runProgram( | |
| 51 | \\fn main() { | |
| 52 | \\ let max = 9223372036854775807.0 | |
| 53 | \\ assert(is_float(floor(max))) | |
| 54 | \\ assert(is_float(ceil(max))) | |
| 55 | \\ assert(is_float(round(max))) | |
| 56 | \\ assert(is_int(floor(9223372036854774784.0))) | |
| 57 | \\ assert(floor(9223372036854774784.0) == 9223372036854774784) | |
| 58 | \\ assert(is_int(ceil(-9223372036854775808.0))) | |
| 59 | \\ assert(ceil(-9223372036854775808.0) == -9223372036854775807 - 1) | |
| 60 | \\ assert(is_int(round(2.5))) | |
| 61 | \\ assert(round(2.5) == 3) | |
| 62 | \\} | |
| 63 | ); | |
| 64 | } | |
| 65 | ||
| 49 | 66 | test "eval: let-binding then use" { |
| 50 | 67 | try runProgram( |
| 51 | 68 | \\fn main() { |