NaN means either an unknown number or that no number can satisfy the condition of being the result of the computed function.
When you compare unknown numbers, you cannot know if they are equal and you cannot know if they are not equal.
That is why both the equality operator and the non-equality operator must be false when comparing a NaN with itself.
When you see a binary FP number, the encoding no longer has any memory about where the number has been generated.
For deciding that a NaN is equal to itself, it is not enough to examine the encoding, you must know the history of the 2 instances of the same NaN value, where they had been generated. Only if the 2 instances are duplicates of a single value, i.e. they had been generated by the same operation, then you could say that they are equal.
If you would want such a facility in a program, then it is not enough to propagate just a floating-point value. You would have to define a custom data type and accompany the FP value by another value that encodes its provenance.
Then you could make custom equality and non-equality operators, which when comparing identical NaNs also compare their provenances, and they decide whether the NaNs are equal or non-equal based on the provenances.
Such a use case is extremely rare. In decades of experience I have never seen a situation when such a feature would be desirable. Nevertheless, if someone wants it, it would be easy to implement it, but it will add considerable overhead.
For example, the provenance could be encoded as a pointer to strings of the form "File ... Line ...", produced using the normal compiler facility for this, which will refer to the source line where the result of a function is tested for being a NaN, and if so the provenance pointer is stored, instead of a null pointer.
Even this encoding of the provenance may not be foolproof, because some functions may generate NaNs with different meanings. For a complete provenance encoding, one would need not only a pointer identifying the function that had generated the NaN, but also the value of a static counter that is incremented at each function invocation.
The provenance could be encoded compactly by storing the string pointers in an array and storing in the provenance an index into that array together with the value of the invocation counter.
So it can be done, but I am pretty sure that this would never be worthwhile.
> If you would want such a facility in a program, then it is not enough to propagate just a floating-point value. You would have to define a custom data type and accompany the FP value by another value that encodes its provenance.
IEEE 754 was way ahead of you. The entire rationale for the existing of NaN payloads was to be able to encode the diagnostic details about operation failure. And this suggests that you really want is the rule that NaNs are equal only to other NaNs with the same payload but are unordered with respect to everything else.
From the research I've done, it seems that the main reason that x != x for NaNs isn't some deep theoretical aspect about the properties of NaNs, but rather because IEEE 754 wanted a cheap way to test for NaN without having to call a function.