9

C 2011 [N1570] 5.2.4.2.2 9 says:

Except for assignment and cast …, the values yielded by operators with floating operands and values subject to the usual arithmetic conversions and of floating constants are evaluated to a format whose range and precision may be greater than required by the type.

Does this mean all floating-point operations in the implementation may be evaluated with one format or each operation may be evaluated with a format with greater range and precision?

The latter would permit A*B == A*B to evaluate as false, if A*B evaluated with extra precision differed from A*B evaluated with nominal precision.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • @old_timer: IEEE 754 floating-point multiplication is commutative. – Eric Postpischil Mar 12 '18 at 23:42
  • 3
    @old_timer You misunderstood OP's question. OP is asking whether 2 AB can be different. – llllllllll Mar 12 '18 at 23:42
  • 3
    @old_timer: IEEE 754 floating-point multiplication is commutative. Please do not distract from the question; it is solely about what the C language requires for evaluation format, not about the properties of floating-point arithmetic. – Eric Postpischil Mar 12 '18 at 23:45
  • @old_timer: Obviously the expressions may have different values if evaluated with different precisions. That is not the question. The question is whether the C standard permits different precisions to be used. – Eric Postpischil Mar 12 '18 at 23:48
  • @liliscent: I wanted to answer [this question](https://stackoverflow.com/questions/49241507/can-it-guarantee-the-double-value-a-b-is-always-equal-to-a-b) but was not sure about the C standard. The question is important for reproducibility (will the same expression have the same value in different compilations) and mathematical properties (will things the programmer expects to have a certain value have that value). – Eric Postpischil Mar 12 '18 at 23:56
  • 6
    @liliscent: It is easy to conceive an implementation that might mix precisions. Consider a compiler that used the x87 FPU for calculation, with its extended precision. The x87 FPU has only eight spaces on its stack, so calculations will easily overflow it. This would force the compiler to store intermediate values to memory, and it might do that using `double` instead of the full x87 FPU expression. (Generally, I would choose to store the entire x87 FPU value to memory in this case, but perhaps there are complicating factors to consider in designing the compiler.) – Eric Postpischil Mar 12 '18 at 23:58
  • @BoPersson: The C standard requires assignment and cast to “remove” extra range and precision. (That”s in the “…” in the question; I elided it since it is not part of this question. The original text where “…” appears is “(which remove all extra range and precision)”.) – Eric Postpischil Mar 13 '18 at 00:33

1 Answers1

6

It is worth reading the interpretation of Joseph S. Myers of the relevant parts of the standard in the case of GCC's C compiler, and the definition of FLT_EVAL_METHOD in C11 5.2.4.2.2:9:

The use of evaluation formats is characterized by the implementation-defined value of FLT_EVAL_METHOD:

-1 indeterminable;

0 evaluate all operations and constants just to the range and precision of the type;

1 evaluate operations and constants of type float and double to the range and precision of the double type, evaluate long double operations and constants to the range and precision of the long double type;

2 evaluate all operations and constants to the range and precision of the long double type.

A C compiler that defines FLT_EVAL_METHOD as -1 does not need to do anything specific regarding the precision of floating-point computations, but according to the above, one that defines it to 1 should only evaluate float expressions in double precision, and one that defines it to 2 should only evaluate float and double expressions in long double precision.

The standard does not explicitly allow other precisions, and neither does it explicitly allow rounding to the nominal precision at the compiler's convenience. (GCC was doing the latter before Joseph S. Myers's patch, and clang -mno-sse2 -std=c99 on x86 was doing the same kind of thing the last time I tried it, while at the same time incorrectly defining FLT_EVAL_METHOD to 0).

According to this strict interpretation of the meaning of FLT_EVAL_METHOD, a * b should only have one value, and if this value is not NaN, a * b == a * b should always hold in a C program compiled with a compiler that defined FLT_EVAL_METHOD to 0, 1 or 2.

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281