Emulating the FMAdd Instruction, Part 1: 32-bit Floats
1–10 of 10 posts
Re: Emulating the FMAdd Instruction, Part 1: 32-bit Floats
#2Re: Emulating the FMAdd Instruction, Part 1: 32-bit Floats
#3Re: Emulating the FMAdd Instruction, Part 1: 32-bit Floats
#4Re: Emulating the FMAdd Instruction, Part 1: 32-bit Floats
#5I would love to know how the author tested/verified that the code is correct.
Re: Emulating the FMAdd Instruction, Part 1: 32-bit Floats
#6I would love to know how the author tested/verified that the code is correct.
Whether or not the code presented is a faithful translation of that algorithm is more subtle and somewhat dependent on the environment; the AddWithError operation requires that no excess precision is used (FLT_EVAL_METHOD == 0), which is the norm for compilers today but not quite universal, especially for compilers that target 32b x86. The `LowestBitOfMantissa`, `AddOneBitToMantissa` and `SubtractOneBitFromMantissa` operations are not implemented in the post--those aren't hard to implement, but doing it without invoking undefined behavior can be subtle (and what's actually permitted is a critical distinction between C and C++).
It also may not handle some non-finite cases correctly--when the result is infinite or NaN, the error term as computed will be NaN, which will pass `errorTerm != 0.0 && LowestBitOfMantissa(value) == 0`, which will cause a bit to be subtracted from the result, rounding infinity back to a finite value. That will overflow back to infinity on the final conversion in default rounding, but in directed rounding modes will give the wrong answer. It also will get the FP flags wrong in some cases, which doesn't matter much for most use, but means you couldn't use it as a C standard library implementation.
A fully correct implementation that handles all these small details isn't really any more complicated, and can be written in ~20 lines of C without any code golfing (I wrote Apple's libm fma[f] for targets that do not have hardware support). The "hard" part is writing the thousands and thousands of tests that allow you to have some confidence in the implementation details—this can largely be automated, but it’s definitely the harder side of the task.
Re: Emulating the FMAdd Instruction, Part 1: 32-bit Floats
#7I would love to know how the author tested/verified that the code is correct.
The _algorithm_ is certainly correct (this is a relatively straightforward and well-known theorem of floating-point arithmetic, see e.g. "Handbook of Floating-Point Arithmetic" by JM Muller et al). Whether or not the code presented is a faithful translation of that algorithm is more subtle and somewhat dependent on the environment; the AddWithError operation requires that no excess precision is used (FLT_EVAL_METHOD…
Indeed that is what I was getting at -- and I wouldn't know where to start. I'd like to know more about this.
Thanks for the Muller book reference, will have to acquire. I have their "Elementary Functions" book.
Re: Emulating the FMAdd Instruction, Part 1: 32-bit Floats
#8Earlier quoted context omitted.
The _algorithm_ is certainly correct (this is a relatively straightforward and well-known theorem of floating-point arithmetic, see e.g. "Handbook of Floating-Point Arithmetic" by JM Muller et al). Whether or not the code presented is a faithful translation of that algorithm is more subtle and somewhat dependent on the environment; the AddWithError operation requires that no excess precision is used (FLT_EVAL_METHOD…
> The "hard" part is writing the thousands and thousands of tests Indeed that is what I was getting at -- and I wouldn't know where to start. I'd like to know more about this. Thanks for the Muller book reference, will have to acquire. I have their "Elementary Functions" book.
fma is also interesting because it can produce results very close to the underflow boundary (add/subtract/divide/sqrt cannot do this, so one sometimes unearths bugs specific to fma, occasionally even hardware bugs), so those are well worth exercising. For subnormal results, double-rounding happens in a different bit position, so it's important to exercise those cases. One also wants to exercise cases where the product underflows by a huge amount, but the final result does not, because people sometimes write implementations based on integer arithmetic that will incur out-of-range shift counts that may not be correctly handled and invoke UB in C or C++.
Re: Emulating the FMAdd Instruction, Part 1: 32-bit Floats
#9I would love to know how the author tested/verified that the code is correct.