PR ada/18099: Rounding floating-point to integer

Geert Bosch bosch@gnat.com
Fri Oct 22 05:45:00 GMT 2004


Quoting from the PR:
> Ada requires conversion of floating-point to integer to round,
> with halfway cases rounded away from  zero. This is implemented
> by adding 0.5 to the floating-point value and then truncating,
> as in regular C  float to int conversion. However, this gives
> wrong semantics for the predecessor of 0.5, and odd  floating-point
> integers in the range 2.0**(mantissa - 1)+1.0 .. 2.0**(mantissa)-1.0
> and the negative  versions of these.
>
> The reason is that adding 0.5 in the above cases, yields a value
> exactly between two  representable floating-point numbers. So the
> predecessor of 0.5 is then rounded to one, and the  floating-point
> integers mentioned before get rounded to the next higher integer.

At first, the obvious solution seemed to be to implement FIX_ROUND_EXPR
in expr.c, however that would logically round halfway cases to even,
while here they should be rounded away from zero.

Even though this could be implemented in the Ada front end and run time
library, the semantics are common enough to warrant a more unified
approach. The C99 round, lround, llround family of functions have
the same semantics, as does the Fortran NINT function.
Note here that F95 has the exact same bug as GNAT, see
fortran/trans-intrinsic.c.

Directly calling the C functions isn't ideal, since they do not always
exist, they should be expandable inline where appropriate, and also
the compiler should be able to do its various folding and constant
propagation tricks with these.

So, I'd propose to implement GCC builtins for round,lround,llround,
roundf, lroundf, llroundf, roundl, lroundl, llroundl, and have the
front ends interface to these. Does this sound like a good idea, or
should we use an FIX_*_EXPR for this?

   -Geert

PS. This bug was found by ACATS C460007, after fixing the 'Pred and 
'Succ
   attributes.



More information about the Gcc mailing list