I am designing a new microprocessor instruction set (www.forwardcom.info) and I want to use NAN propagation for tracing errors. However, there are a number of oddities in the IEEE 754 floating point standard that prevent this.
First, the reason why I want to use NAN propagation rather than error trapping is that I have vector registers with variable length. If, for example, I have a float vector with 8 elements and I have 1/0 in the first element and 0/0 in the sixth element, then I get only one trap, but if I run the same program on a computer with half the vector length then I get two traps: one for infinity and one for NAN. I want the result to be independent of the vector length so I need to rely on the propagation of NAN and INF rather than trapping. The NAN and INF values will propagate through the calculations so that they can be checked in the final result. The NAN representation contains some bits called payload that can be used for information about the source of error.
However, there are two problems in the IEEE 754 floating point standard that prevent reliable propagation of NAN values.
The first problem is that the combination of two NANs with different payloads is just one of the two values. For example NAN1 + NAN2 gives NAN1. This violates the fundamental principle that a+b = b+a. The compiler can swap the operands so that you get different results on different compilers or with different optimization options. I prefer to get the bitwise OR combination of the two payloads. This will work if you have one bit for each error condition, but of course not if the payload contains more complex information (such as NAN boxing in languages with dynamic types). The standards committee actually discussed the OR'ing solution (see http://grouper.ieee.org/groups/754/email/msg01094.html). I don't know why they rejected this proposal.
The second problem is that the min and max functions do not propagate the NAN if only one of the inputs is a NAN. In other words, min(1,NAN) = 1. Reliable NAN propagation would of course require that min(1,NAN) = NAN. I have no idea why the standard says this.
In the new microprocessor system, named ForwardCom, I want to avoid these unfortunate quirks and specify that NAN1 + NAN2 = NAN1 | NAN2, and min(1,NAN) = NAN.
And now to my questions: First, do I need an option switch to change between strict IEEE conformance and the reliable NAN propagation? Quoting the standard:
Quiet NaNs should, by means left to the implementer’s discretion, afford retrospective diagnostic information inherited from invalid or unavailable data and results. To facilitate propagation of diagnostic information contained in NaNs, as much of that information as possible should be preserved in NaN results of operations.
Note that the standard says "should" here, where it has "shall" elsewhere. Does that mean that my deviation from the recommendation is permissible?
And the second question: I cannot find any examples where NAN propagation is actually used for tracing errors. Maybe this is because of the weaknesses in the standard. I want to define different payload bits for different error conditions, for example:
0/0, 0*∞, ∞/∞, modulo(1,0), modulo(∞,1), ∞-∞, and other errors involving infinity and division by zero.
sqrt(-1), log(-1), pow(-1,0.1), and other errors deriving from logarithms and powers.
asin(2) and other mathematical functions.
explicit assignment. This can be useful when a variable is initialized to a NAN.
There are plenty of vacant bits for user-defined error codes.
Has this been done before, or do I have to invent everything from scratch? Are there any problems that I have to consider (other than NAN boxing in certain languages)