Explicit cast to same floating-point type?

queueing-rmail uunet!lupine!segfault!rfg
Tue Dec 29 13:20:24 PST 1992


I've just come across an interesting little "feature" of the native C
compiler which happens to reside on the i486 box I have here (which
just happens to be running SVR4).

This little feature seem quite useful, but (unfortunately) it is not
shared (currently) by the GNU C compiler (for the same platform).

In a nutshell, the "feature" I'm talking about is that a floating-point
expression may be computed into an x86 floating-point register (which
happens to be 80-bits long, even though type `double' for this machine
is 64-bits long) and if you then explicitly cast the expression value
to type `double' the effect is that the expression value gets truncated
to a 64-bit real before being used any further.  (This truncation happens
to be achieved by storing the upper 64-bits of the FP register in question
to memory and then reloading that 64-bit value from memory, but that's all
rather irrelevant to this discussion.)

Anyway, for machines on which it might be reasonable for the C compiler
to evaluate expression is "extended" mode, this "truncation by explicit
cast" feature seems really quite useful (as illustrated by the example
given below).  So naturally, I wondered if there was anything explicit
in either the ANSI C standard or in the "Floating Point C Extensions"
document developed by the NCEG which would mandate this feature in C
compilers.

Well, I've looked a bit at both documents and I can't seem to find any-
thing which explicitly covers the semantics of a floating point expression,
evaluated in "extended" mode, and then explicitly casted to any given
floating-point type (and perhaps even to the same type as the "nominal"
static type which the compiler must believe the expression has).

So my question for the NCEG members is just this... Does either the ANSI
C standard or the "Floating Point C Extensions" document specify and/or
require any specific semantics for such cases?  If so, what are those
semantics?  If no particular semantics are required in such instances
(by either document) then would the specification of some required
semantics for such cases be something that the NCEG might be interested
in working on?

// rfg


======================================================================
Here is the test case file I've just cooked up on the basis of my recent
findings.  Note that as far as I'm concerned, I prefer to view the
absence of the "truncation by explicit cast" feature from GCC as a
"bug" (rather than simply a non-feature) but I must confess that in
strict terms, this might only be a "quality of implementation" issue
(and not really a "bug" per se).

cut here
--------------------------------------------------------------------
/* (C) 1992 Ronald F. Guilmette; all rights reserved.  */

/* g921119_01+.c */

/* Check that if a type `double' value is computed (perhaps into a
   register which has greater precision than type `double') and 
   if that value is then explicitly casted to a type `double'
   value, its precision will be forced to that of a double.

   This is a bug in the GCC 2.3.3 compiler when compiling for an x86
   target (and perhaps also for m680x0 targets, as these also provide
   80-bit "extended" floating-point registers).

   Note that this test passes (i.e. returns a zero exit status) when
   compiled with the "native" C compiler on SVR4 (for an x86 system),
   but only when the explicit cast to double is present.

   Also note that the act of returing a computed floating-point value
   from a function which is explicitly declared to return a type `double'
   result is *NOT* sufficient (with either GCC 2.3.3 or the native C
   compiler on SVR4/x86) to force the significance of the return value
   down to that of a double, however an explicit cast will do the trick
   (for the SVR4 C compiler at least).
*/

#include <stdio.h>

int err_count;

double point_four = 0.4;
double point_one_six;

int
test ()
{
  point_one_six = (point_four * point_four);
  if ((double)(point_four * point_four) != point_one_six)
    {
      printf ("ERROR: casting to double is ineffective\n");
      err_count++;
    }
  return err_count;
}

int main () { return test (); }



More information about the Numeric-interest mailing list