-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement proper f128 float printing #1181
Comments
negative zero is also printed as positive zero:
|
I would like to propose that the default float printing and default float parsing in Zig should have roundtrip bit-for-bit value preservation for all values for all float types. So that means that this fuzz test should never fail: const std = @import("std");
test "fuzz test float printing and parsing" {
const seed = 0x1234;
var prng = std.rand.DefaultPrng.init(seed);
var buf: [1024]u8 = undefined; // i don't know how big this should be
while (true) {
inline for ([]type{ f16, f32, f64, f128 }) |F| {
const I = @IntType(false, F.bit_count);
const rand_int = prng.random.int(I);
const rand_float = @bitCast(F, rand_int);
const serialized = std.fmt.bufPrint(&buf, "{}", rand_float) catch unreachable;
const deserialized = std.fmt.parseFloat(F, serialized) catch unreachable;
std.testing.expect(rand_int == @bitCast(I, deserialized));
}
}
} Right now this test is a bug report generator :-) Maybe an exception should be made for negative NaN? I'm not sure exactly what the rules are about that particular case right now. |
There are more than 2 representations of NaN, and ALL must be normalized to a single representation. |
Just a note (perhaps stating the obvious) - it's not just the extra precision of |
I was studying the issue, but I had to change the bug-report-generator code to comply with latest zig compiler (at the time of writing 0.12.0-dev.1396+f6de3ec96). const std = @import("std");
test "fuzz test float printing and parsing" {
const seed = 0x1234;
var prng = std.rand.DefaultPrng.init(seed);
var buf: [1024]u8 = undefined; // i don't know how big this should be
while (true) {
inline for ([4]type{ f16, f32, f64, f128 }) |F| {
const I = std.meta.Int(std.builtin.Signedness.unsigned, @bitSizeOf(F));
const rand_int = prng.random().int(I);
const rand_float = @as(F, @bitCast(rand_int));
const serialized = std.fmt.bufPrint(&buf, "{}", .{rand_float}) catch unreachable;
const deserialized = std.fmt.parseFloat(F, serialized) catch unreachable;
try std.testing.expect(rand_int == @as(I, @bitCast(deserialized)));
}
}
} |
This replaces the errol backend with one based on ryu. The 128-bit backend only is implemented. This supports all floating-point types and does not use fp logic to print. Closes ziglang#1181. Closes ziglang#1299. Closes ziglang#3612.
This replaces the errol backend with one based on ryu. The 128-bit backend only is implemented. This supports all floating-point types and does not use fp logic to print. Closes ziglang#1181. Closes ziglang#1299. Closes ziglang#3612.
Right now we cast f128 to a f64 and simply lose any excess precision we otherwise had. This may be fairly involved as errol3 (the current float printing algorithm used) is specified using f64 digits only. Will have to check the algorithm and see the appropriate modifications needed for the wider range.
The text was updated successfully, but these errors were encountered: