Skip to content

Commit 4380d1c

Browse files
committed
update on what C does
1 parent 2f8b973 commit 4380d1c

File tree

1 file changed

+5
-9
lines changed

1 file changed

+5
-9
lines changed

text/0000-float-semantics.md

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -248,20 +248,16 @@ C23 clarifies its stance on signaling NaNs:
248248
It doesn't say anything about the bit patterns inside NaNs.
249249
This means that strictly speaking, any form of NaN boxing has to re-normalize NaNs after every single operation.
250250
To the author's knowledge, this is not actually done in practice; code instead relies on compilers implementing a more strict semantics.
251-
The C standard also does not state explicitly whether signaling NaNs can ever be produced by arithmetic operations, though given that the IEEE 754 semantics do not permit this to happen, presumably C does not permit this, either.
252-
At least [two major C implementations violate this part of the spec](https://godbolt.org/z/6veef68xE) by optimizing `x * 1.0` to `x`.
251+
However, neither GCC nor MSVC document that they actually provide a more strict semantics.
252+
253+
The interpretation of that standard by compilers seems to be that if an operation has a signaling NaN as input, then it may produce a signaling NaN as output.
254+
(It is not clear to the author how that is a valid interpretation of the above sentence, but the standard itself mentions transforming `x * 1.0` to `x` as a valid transformations
255+
when the implementation does not have strict support for signaling NaNs.)
253256

254257
LLVM [recently adopted](https://github.com/llvm/llvm-project/pull/66579) new NaN rules that this RFC copies exactly into Rust.
255258
This means that even though arithmetic operations can produce signaling NaNs, there is a guarantee that signaling NaNs will never appear "out of thin air".
256259
LLVM does not actually document that they are using IEEE float semantics, but de-facto they do on almost all targets (the exception are targets that use x87 instructions, as noted above).
257260

258-
GCC [says](https://gcc.gnu.org/wiki/FloatingPointMath) "Without any explicit options, GCC assumes round to nearest or even and does not care about signalling NaNs".
259-
It is unclear whether "does not care" also means "guarantees to never produce by itself", i.e. whether `0.0 / 0.0` is ever allowed to evaluate to a signaling NaN or not.
260-
While IEEE 754 forbids such behavior, GCC does [return signaling NaNs from some arithmetic operations](https://godbolt.org/z/6veef68xE), so it is fair to ask under which exact conditions such signaling NaNs may occur.
261-
If `0.0 / 0.0` *is* allowed to evaluate to a signaling NaN, that is concerning for cases like `pow(1, 0.0/0.0)`, which should return `1` -- but in practice, `pow(1, sNaN)` returns a NaN.
262-
263-
MSVCs [documentation of FP behavior](https://learn.microsoft.com/en-us/cpp/build/reference/fp-specify-floating-point-behavior?view=msvc-170) is similarly silent on the issue of whether and when exactly signaling NaNs may be generated, and what the bits of a NaN payload may look like.
264-
265261
Java requires exact IEEE 754-2008 compliance and goes through a lot of effort to realize that on 32bit x86 without SSE (see [here](https://open-std.org/jtc1/sc22/jsg/docs/m3/docs/jsgn325.pdf) and [here](https://open-std.org/JTC1/SC22/JSG/docs/m3/docs/jsgn326.pdf)). However, they do not seem to tackle the issue of specifying NaN payload bits, even though those bits [can be observed](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Float.html#floatToRawIntBits(float)).
266262

267263
wasm [guarantees](https://webassembly.github.io/spec/core/exec/numerics.html#nan-propagation) that "if all input NaNs are canonical, then any output NaN is canonical". Here ["canonical"](https://webassembly.github.io/spec/core/syntax/values.html#canonical-nan) is defined as a NaN with a "payload whose most significant bit 1 is while all others are 0", i.e. it matches what we call "preferred" above.

0 commit comments

Comments
 (0)