diff --git a/compiler/builtins/bitcode/src/dec.zig b/compiler/builtins/bitcode/src/dec.zig index ca24c12641..2523519bfa 100644 --- a/compiler/builtins/bitcode/src/dec.zig +++ b/compiler/builtins/bitcode/src/dec.zig @@ -26,21 +26,20 @@ pub const RocDec = extern struct { return .{ .num = num * one_point_zero_i128 }; } - // TODO: There's got to be a better way to do this other than converting to Str pub fn fromF64(num: f64) ?RocDec { - var digit_bytes: [19]u8 = undefined; // 19 = max f64 digits + '.' + '-' - var fbs = std.io.fixedBufferStream(digit_bytes[0..]); - std.fmt.formatFloatDecimal(num, .{}, fbs.writer()) catch - return null; + var result: f64 = num * comptime @intToFloat(f64, one_point_zero_i128); - var dec = RocDec.fromStr(RocStr.init(&digit_bytes, fbs.pos)); - - if (dec) |d| { - return d; - } else { + if (result > comptime @intToFloat(f64, math.maxInt(i128))) { return null; } + + if (result < comptime @intToFloat(f64, math.minInt(i128))) { + return null; + } + + var ret: RocDec = .{ .num = @floatToInt(i128, result) }; + return ret; } pub fn fromStr(roc_str: RocStr) ?RocDec { @@ -729,6 +728,11 @@ test "fromF64" { try expectEqual(RocDec{ .num = 25500000000000000000 }, dec.?); } +test "fromF64 overflow" { + var dec = RocDec.fromF64(1e308); + try expectEqual(dec, null); +} + test "fromStr: empty" { var roc_str = RocStr.init("", 0); var dec = RocDec.fromStr(roc_str);