9899:1999 5.1.2.3 Example 4 reads:

"EXAMPLE 4 Implementations employing wide registers have to take care

to honor appropriate semantics. Values are independent of whether they

are represented in a register or in memory. For example, an implicit

spilling of a register is not permitted to alter the value. Also, an

explicit store and load is required to round to the precision of the

storage type. In particular, casts and assignments are required to

perform their specified conversion. For the fragment

double d1, d2;

float f;

d1 = f = expression;

d2 = (float) expression;

the values assigned to d1 and d2 are required to have been converted to

float."

The output of the following program is:

d3 != d1 * d2

d3 != (double) (d1 * d2)

fdim == 0

I expected an output of

d3 != d1 * d2

d3 == (double) (d1 * d2)

fdim == 0

Here is the program:

#include <math.h>

#include <stdio.h>

int main (void) {

double d1, d2, d3;

d1 = 0.1;

d2 = 10.0;

d3 = d1 * d2;

/* First part */

if (d3 == d1 * d2)

puts("d3 == d1 * d2");

else

puts("d3 != d1 * d2");

/* Second part */

if (d3 == (double) (d1 * d2))

puts("d3 == (double) (d1 * d2)");

else

puts("d3 != (double) (d1 * d2)");

/* Third part */

if (fdim(d3, d1 * d2) == 0)

puts("fdim == 0");

else

puts("fdim != 0");

return 0;

}

It was compiled with gcc using -Wall -W -std=c99 -pedantic

I understand the pitfalls of floating point arithmetic and I understand

what is going on here. On my machine (x86) floating point arithmetic

is performed in 80-bit registers and doubles are 64-bits. In the first

example the compiler is computing the result of the multiplication in

an 80-bit register and comparing the result to the double with less

precision. The result is not unexpected because d3 lost some precision

when it was stored into a 64-bit object but the result of the

multiplication did not undergo this loss. I don't have a problem with

this, it is AFAICT Standard conforming.

The part that is unexpected, to me, is the second part where the result

of the multiplication is explicitly cast to double which, according to

my interpretation of the above-quoted Standard verse, requires that the

result is converted to the narrower type of double before the test for

equality if performed. This does not appear to be happening. If I use

the gcc option -ffloat-store the result is as expected but this

shouldn't be required in a Standard-conforming mode.

The result of the last part of the program shows that when the results

of "d1 * d2" is actually converted to a double, it compares equal to

d3.

So my question is: Is my interpretation correct and are the results of

the second two parts guaranteed? If not, where did I go wrong?

Robert Gamble