Skip to contentSkip to conversation

gcc type promotion bug?

Linux-ia64 Richard Hirst 2 participants 4 messages Apr 16, 2002

lore
Share & tools
lore
#0 lore raw

#include <stdio.h>

int
main(int argc, char **argv)

{
        long a = 0x70000037L;
        float f = 0.01;
        long b = a + 1L/f;

        printf("%lx, %lx\n", b, a + 100L);
        return 0;
}

In the above, 1/f = 100, so the two numbers printed out should be the same. For me it prints out "70000080, 7000009b". Same for gcc 2.96 and 3.0.3.

By trying various numbers for 'a', it appears to me that it is demoting 'a' to a float when evaluating 'b', thus truncating it to 24 significant bits. I thought all mixed mode arithmetic was supposed to be promoted to doubles for evaluation. This is breaking parted 1.6 on ia64.

Richard

#1 lore raw

Richard Hirst <[email protected]> writes:

|> #include <stdio.h>
|> 
|> int
|> main(int argc, char **argv)
|> {
|>         long a = 0x70000037L;
|>         float f = 0.01;
|>         long b = a + 1L/f;
|> 
|>         printf("%lx, %lx\n", b, a + 100L);
|>         return 0;
|> }
|> 
|> 
|> 
|> In the above, 1/f = 100, so the two numbers printed out should be the
|> same.  For me it prints out "70000080, 7000009b".  Same for gcc 2.96
|> and 3.0.3.
|> 
|> By trying various numbers for 'a', it appears to me that it is demoting
|> 'a' to a float when evaluating 'b', thus truncating it to 24 significant
|> bits.  I thought all mixed mode arithmetic was supposed to be promoted
|> to doubles for evaluation.

No. There are no operands of type double or long double involved, so the ususal arithmetic conversions (6.3.1.8) choose float as the common type:

Otherwise, if the corresponding real type of either operand is float, the other operand is converted, without change of type domain, to a type whose corresponding real type is float.

Andreas.

Signature · 4 lines
Andreas Schwab, SuSE Labs, [email protected]
SuSE GmbH, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."
#2 lore raw
In reply to Richard Hirst
Quoted 6 lines · Andreas Schwab

No. There are no operands of type double or long double involved, so the ususal arithmetic conversions (6.3.1.8) choose float as the common type:

Otherwise, if the corresponding real type of either operand is float, the other operand is converted, without change of type domain, to a type whose corresponding real type is float.

OK, thanks. I looked at (out of date) K&R, which told me all floating point arithmetic in C was done in double precision, and I tried my program on i386, where it appeared to worked fine.

Cheers,
Richard

#3 lore raw
In reply to Richard Hirst

Richard Hirst <[email protected]> writes:

|> On Tue, Apr 16, 2002 at 10:31:02PM +0200, Andreas Schwab wrote:
|> > No.  There are no operands of type double or long double involved, so the
|> > ususal arithmetic conversions (6.3.1.8) choose float as the common type:
|> > 
|> >     Otherwise, if the corresponding real type of either operand is float,
|> >     the other operand is converted, without change of type domain, to a
|> >     type whose corresponding real type is float.
|> 
|> OK, thanks.  I looked at (out of date) K&R, which told me all floating
|> point arithmetic in C was done in double precision, and I tried my
|> program on i386, where it appeared to worked fine.

The standard explicitly allows for using a higher precision and range for floating point computation than those of the nominal type.

Andreas.

Signature · 4 lines
Andreas Schwab, SuSE Labs, [email protected]
SuSE GmbH, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."