3 ms·
I find the argument unconvincing. While IEEE 758 does not specify what `/` (or `+`) operator in particular does (that falls under C standard), it does specify t
by zokier 5y ago
I find the argument unconvincing. While IEEE 758 does not specify what `/` (or `+`) operator in particular does (that falls under C standard), it does specify that:
> Implementations shall provide the following formatOf general-computational operations, for destinations of
> all supported arithmetic formats, and, for each destination format, for operands of all supported arithmetic
> formats with the same radix as the destination format
Which to my interpretation sounds like providing a `division(double, double) -> double` operation is required. I suppose the argument could be that in C the way of invoking that specific operation would be to add an explicit cast, i.e.
(double)(a op b)
But I do think that this is more a quirk on how operators are done specifically in C and not a general matter; the actual IEEE 758 operations are consistent and don't have such surprises.
So I guess you were technically correct that IEEE 758 does not guarantee `a + b == a + b`, because IEEE 758 does not specify `+` (or `==` for that matter) operators at all. What IEEE 758 does guarantee is that you get the same result for the same operation.
In terms of C language, it is maybe interesting question if `FP_CONTRACT` pragma influences the result here at all:
> A floating expression may be contracted, that is, evaluated as though it were a single opera-
> tion, thereby omitting rounding errors implied by the source code and the expression evalua-
> tion method. The FP_CONTRACT pragma in <math.h> provides a way to disallow contracted
> expressions. Otherwise, whether and how expressions are contracted is implementation-defined.
Are the comparison and arithmetic operations considered to be contracted in these sort of situations?
- ReleaseCandidat 5y ago> But I do think that this is more a quirk on how operators are done specifically in C and not a general matte That has nothing to do with C, but with the CPU and its registers. x86 has 80bit floating point registers (too), so if the compiler/CPU (doesn't matter which language) saves a value in a 80 bit floating point register and moves it from there to memory where it is stored in 64 bits, the number gets rounded (not truncated, it's actually converted). See also the GCC page: For instance, in the following code segment, depending on the compilation flags and numbers and calculations used to find tmp, the following code may print out that the values are different: double tmp, X[2]; tmp = .... tmp += .... ... X[0] = tmp; if (X[0] == tmp) printf("Values are the same, as expected!\n"); else printf("Values are different!\n"); This is because tmp will typically be moved to a register during register assignment, which means tmp may hold a full 80 bits of accuracy, some of which are lost in the store to X[0], and thus the numbers are no longer equal. You may workaround this problem by always explicitly storing to memory to force the round-down. https://gcc.gnu.org/wiki/x87note https://gcc.gnu.org/wiki/x87note > Are the comparison and arithmetic operations considered to be contracted in these sort of situations? No. Or well, maybe. 'Contracted' means using e.g. FMA (fused multiply and add), so addition and multiplication like `ab + c` is done in a single step instead of two. Which means that the result is only rounded once (`ab + c` is rounded), whereas without this fusing/contracting `ab` would be rounded and `ab + c` would be rounded again (actually depending on the optimization/compiler flags). So the results (may) differ.