[comp.sys.sgi] HUGE

tjh@bucrf11.bu.edu (Tim Hall) (01/17/91)

The following pertains to PI's and 4D/2xx machines running 3.3.1...

Awhile ago I growled about setting a float value to "HUGE" and then
testing to see if that float value == HUGE and the result would be
not true.  After awhile I thought about it and figured I'd been dumb
in assigning HUGE to a float (I use it as a sort of "NULL" float value)
and I should attenuate HUGE and then life will be good.  No such luck.

The following line is from math.h
#define HUGE            3.40282347e+38  /*max decimal value of a "float" */
                                                                  ^^^^^

The following code demonstrates my problem.....

#include <stdio.h>
#include <math.h>

#define NOVALUE ((float)(HUGE * 0.001))
/* Surely this will produce a  ^^^^^^ valid float value! (Ha) */

main( )
{
        float a;

        a = NOVALUE;
        printf( "%f %f\n", NOVALUE, a ); /* They look exactly the same! */
        if ( a == NOVALUE )              /* But noooooooooooooooooooooo */
                printf( "Equal\n" );
        else
                printf( "Not Equal\n" );

}

So the final question is - is it me?  Shouldn't this work?  It used to.

-- 
-Tim Hall
tjh@bu-pub.bu.edu

GO BU! BEAT BC!

sgf@cs.brown.edu (Sam Fulcomer) (01/18/91)

In article <72495@bu.edu.bu.edu> tjh@bu-pub.bu.edu (Tim Hall) writes:
>The following code demonstrates my problem.....
>
>#define NOVALUE ((float)(HUGE * 0.001))
>        float a;
>
>        a = NOVALUE;
>        printf( "%f %f\n", NOVALUE, a ); /* They look exactly the same! */
>        if ( a == NOVALUE )              /* But noooooooooooooooooooooo */


Ayuh, well, it should work. The bug is in the new optimization code in the 
compiler (even at optimization O0).

It used to be that the NOVALUE macro would be faithfully inserted in the 
code (ie, the resulting program would execute the whole works with each
incidence of the macro). The compiler was changed to pre-calculate NOVALUE
and just insert the value in the code (drops out a lot of instructions).

The problem occurs in the way the compiler handles the if statement.
Instead of doing an li.s followed by a cvt.d.s for the insertion of NOVALUE
it does a li.d, thus doing a double compare between a single and a double.
Of course they're not equal at that point, but they should be...

Of course, this is all sheer speculation, but it sounds like a bug...

_/**/Sam

davea@quasar.wpd.sgi.com (David B.Anderson) (01/19/91)

In article <61848@brunix.UUCP>, sgf@cs.brown.edu (Sam Fulcomer) writes:
> In article <1991Jan17.201925.2264@odin.corp.sgi.com> bruceh@sgi.com (Bruce R. Holloway) writes:
> >In article <72495@bu.edu.bu.edu> tjh@bu-pub.bu.edu (Tim Hall) writes:
> >>
> >The problem isn't that HUGE needs to be attenuated.  It's that the MIPS
> >C compiler didn't respect the cast to float in your constant definition.
> 
> ok, but why doesn't
> 	if( a == (float)NOVALUE)
> work?

bruceh is correct.

Since this has become a hot issue I'll elaborate:
	((float) NOVALUE)
should narrow the constant (when NOVALUE is a double constant) to a float.

However, in 3.3, the constant did not get narrowed. 

Fortunately, this is rarely a problem.  Unfortunately, when it bites
someone it is confusing to look at the code because it is the _constant_
which was not narrowed (the generated code is ok, the constant is bad).  
The .s output of Mr. Hall's compile would be in part (cc -g):

compiled with 3.3 cc:
        li.s    $f4, 3.4028234699999997e+35
        s.s     $f4, 28($sp)
        cvt.d.s $f6, $f4
        li.d    $f8, 3.4028234699999997e+35
        c.eq.d  $f6, $f8
        bc1f    $32

One gets the un-narrowed NOVALUE $6 rather than the double-precision
version of the narrowed one.

Now look at the same compiled under 4.0 cc:

        li.s    $f4, 3.4028234346940236e+35
        s.s     $f4, 28($sp)
        cvt.d.s $f6, $f4
        li.d    $f8, 3.4028234346940236e+35
        c.eq.d  $f6, $f8
        bc1f    $32

Same code, but the constant is  now correct.

In general, narrowing *does* happen correctly in 3.3 C. However in
the above case (constant double narrowed to float) it does not.

This is fixed in the next major release (4.0).

Hope this elaboration helps a little.
[ David B. Anderson  Silicon Graphics  (415)335-1548  davea@sgi.com ]
[``What can go wrong?''                           --Calvin to Hobbes]