zig
zig copied to clipboard
Managing floating point rounding mode
A discussion with @Rhodiumtoad brought up how FPU rounding modes are handled with zig.
e.g. what rounding mode state does zig expect the FPU to be in when an extern
function is called? If zig doesn't specify or check this, then it means that comptime
evaluations may not be correct (as they could be computed with the wrong rounding mode).
Do we need a @setFloatingPointRoundingMode
?
Could we have the rounding mode be .Unknown
on entrance to a extern
or export
function, and ban most comptime floating point operations when in the unknown mode?
Reading docs on LLVM Constrained Floating-Point Intrinsics I spotted:
By default, LLVM optimization passes assume that the rounding mode is round-to-nearest and that floating-point exceptions will not be monitored.
I haven't looked at what IR zig emits: does it use constrained FP intrinsics?
What is the default behavior of zig currently? The language documentation has @setFloatMode() which by default is on 'Strict', but does this also imply a rounding mode? This is currently a breaking point for me to migrate a few (numeric-computing related) personal projects to zig, because any floating point operations done in zig are currently underspecified (or essentially undefined behavior) because the rounding behavior is not specified. I would also be willing to help contribute these features to the zig compiler, but for that a direction first needs to be decided by the core team.
At least, with SSE2 for f32 and f64: Zig's default rounding mode seems to be Round to Nearest, halfway-ties round to even. Which is also the default IEEE-754-2008 rounding mode[1].
Zig provides @round
which seems to be: Round to Nearest, halfway-tires away from zero.
So Zig seems to be missing @roundeven
[2].
@nearbyint
could be needed, if the rounding mode can change.
Also note: std.math.isNan
seems to be missing cases that _mm_cmpunord_ps
would catch. I don't know what compatibility concerns come into play there.