Most hardware architectures (x86, ARM fall into this category) pick the rule that the payload is the Nth operand (usually first, sometimes second) when multiple inputs are NaN. I believe there's some hardware where the lesser of the payloads (converted to an integer) is picked instead. RISC-V dispenses with NaN payload propagation entirely. There is theoretically the ability for hardware to generate a new unique NaN with the hardware address of the instruction into the payload, but I don't believe any hardware actually does it.
Most programming languages do not generally model NaN with greater fidelity than "there is a NaN value" or maybe "there is a distinction between qNaN and sNaN."
Sign bit is NOT the signalling/quiet bit. Bit 51 (edit or bit 50 - damn ***** IEEE for not publishing important standards for free public access) is according to the first result I looked at: https://craftinginterpreters.com/optimization.html
Edit 2 from IEEE 754 (2008 version):
6.2.1 NaN encodings in binary formats
This subclause further specifies the encodings of NaNs as bit strings when they are the results of operations. When encoded, all NaNs have a sign bit and a pattern of bits necessary to identify the encoding as a NaN and which determines its kind (sNaN vs. qNaN). The remaining bits, which are in the trailing significand field, encode the payload, which might be diagnostic information (see above).
All binary NaN bit strings have all the bits of the biased exponent field E set to 1 (see 3.4). A quiet NaN bit string should be encoded with the first bit (d1) of the trailing significand field T being 1. A signaling NaN bit string should be encoded with the first bit of the trailing significand field being 0. If the first bit of the trailing significand field is 0, some other bit of the trailing significand field must be non-zero to distinguish the NaN from infinity. In the preferred encoding just described, a signaling NaN shall be quieted by setting d1 to 1, leaving the remaining bits of T unchanged.
6.3 The sign bit
When either an input or result is NaN, this standard does not interpret the sign of a NaN. Note, however, that operations on bit strings—copy, negate, abs, copySign—specify the sign bit of a NaN result, sometimes based upon the sign bit of a NaN operand. The logical predicate totalOrder is also affected by the sign bit of a NaN operand. For all other operations, this standard does not specify the sign bit of a NaN result, even when there is only one input NaN, or when the NaN is produced from an invalid operation.
When neither the inputs nor result are NaN, the sign of a product or quotient is the exclusive OR of the operands’ signs; the sign of a sum, or of a difference x−y regarded as a sum x+(−y), differs from at most one of the addends’ signs; and the sign of the result of conversions, the quantize operation, the roundTo- Integral operations, and the roundToIntegralExact (see 5.3.1) is the sign of the first or only operand. These rules shall apply even when operands or results are zero or infinite.
When the sum of two operands with opposite signs (or the difference of two operands with like signs) is exactly zero, the sign of that sum (or difference) shall be +0 in all rounding-direction attributes except roundTowardNegative; under that attribute, the sign of an exact zero sum (or difference) shall be −0. However, x + x = x − (−x) retains the same sign as x even when x is zero.
When (a×b)+c is exactly zero, the sign of fusedMultiplyAdd(a, b, c) shall be determined by the rules above for a sum of operands. When the exact result of (a × b) + c is non-zero yet the result of fusedMultiplyAdd is zero because of rounding, the zero result takes the sign of the exact result.
Except that squareRoot(−0) shall be −0, every numeric squareRoot result shall have a positive sign.
I.e. you are definitely wrong. The sign bit can be + or - for NaN (presumably a side-effect of the encoding for +/-Infinity ). And then that leads to a bunch of arse (section 6.3) because the spec needs to decide what happens to the sign bit in a bunch of different situations. PS: fucking infinity. Infinity should have been NaN. Infinity ≠ Infinity, except in in the egghead-land IEEE (side note: egghead is a compliment IMHO). Mind you, easy to see mistakes in retrospect, but corner cases are shit in programming. I do like NaN, although reading comments here, and the IEEE spec, forces me to learn how little I now about NaN encodings. Oh, and any NaN should equal any other NaN. Mathematically obviously not, but logically yes and IEEE is for programming. NaN is already defined as a nonsense, so at least keep the nonsense consistent. Changing if = to if ≠ should not introduce subtle logic bugs.Ranting edit #755: and while we are at it, -0 is an abomination in the eyes of the Great Architect in the Matrix - it should never have been allowed - perhaps -0 should have been NaN with signalling bits in the exponent (even though that would prevent some language virtual machine optimisations where 53 bits of NaN get used to pack other information, but the win would be compelling because reducing bugs due special cases is huge IMHO). How many developers understand IEEE corner cases: fuck all in my long experience.
A random stackoverflow answer without sources seems to confirm your pov. Now I don't know what to believe. How is the sign bit used in NaNs? Would they really waste that bit?
“A quiet NaN bit string should be encoded with the first bit (d1) of the trailing significand field T being 1. A signaling NaN bit string should be encoded with the first bit of the trailing significand field being 0.“
Or is it that some implementations before 2008 used other bits?PS: I might be complaining, but I do sincerely thank you for your hard work. I certainly would not want to be on a standards committee, so I sincerely appreciate the efforts of the committed whom fight so hard to make things better. Your comment just goes to show how many corner cases there are to the corner cases!!
Citing the person who came up with posits for anything related to IEEE 754 is a pretty poor decision, he is prone to a lot of misunderstanding here. There's a lot of decent explanations of IEEE 754 (including Wikipedia), so you shouldn't need to resort the explanations of someone whose major shtick is telling people IEEE 754 sucks.
> How is the sign bit used in NaNs? Would they really waste that bit?
Sign bits have no meaning for NaNs, although some C libraries (e.g., glibc) will distinguish between a NaN with the sign bit set and not set when printing floating-point numbers, which gives the illusion that it matters more than any other bit. Using the sign bit for qNaN-versus-sNaN is a bad idea from a design perspective, since there are a few FP operations explicitly specified to modify only the sign bit (fneg, fabs), and this would mean that you get regular operations that could generate sNaNs, which defeats the design goal of sNaN.
"we gave you enough different NaNs to uniquely represent every grain of sand on the planet uniquely"
how does math work on them?
"we have no idea"
how do we tell what type of nan we have?
"we have no idea"
what should these bajillion values represent?
"I don't know, probably something"
the fact that they didn't just make there be a single NaN and make it equal to itself (and while you're at it make it so the real numbers have a total ordering)
For almost all operations, if any input is a NaN, the result is a NaN. It's pretty well-specified by IEEE 754, the only thing that isn't is what the payload is, but there's no general expectation that the payload is preserved through computation.
> how do we tell what type of nan we have?
`getpayload()`
> what should these bajillion values represent?
Diagnostic information that tells you which operation caused the NaN in the first place. (This is Kahan's standard argument for why having many NaNs can be useful.)
> the fact that they didn't just make there be a single NaN
What's the alternative? You'd either have to have lots of illegal floating point values, or you'd have to make the number of finite floating-point numbers with the highest exponent value slightly smaller than for all other exponent values, which complicates a good deal of numerical analysis.
> make it equal to itself
Yeah, this is the big, nasty mistake of IEEE 754.
> and while you're at it make it so the real numbers have a total ordering
There is a totalOrder predicate specified by IEEE 754. Representing floating-point comparisons as a partial order is arguably better than giving it a total order, but the lack of reflexivity of equals makes the existing predicates not a partial order.