[PATCH][4.3] Expand lround inline for x86_64/i?86 SSE math
Brooks Moses
bmoses@stanford.edu
Thu Oct 19 21:57:00 GMT 2006
(Added a cc: to fortran@, so as to increase the population of people who
will complain if I say something that's incorrect!)
Richard Guenther wrote:
> On 10/19/06, Brooks Moses <bmoses@stanford.edu> wrote:
>>Toon Moene wrote:
>>>Richard Guenther wrote:
>>>>I wonder if fortran specifies round differently, as the frontend
>>>>explicitly converts NINT(x) = INT(x + ((x > 0) ? 0.5 : -0.5)).
>>>
>>>Yep - sorry, don't have the reference handy.
>>
>>For what it's worth, since I do have the reference handy, that's
>>essentially a direct translation of how the Fortran 95 standard defines
>>the NINT intrinsic.
>
> So, does it define how the x + 0.5 is carried out with respect to
> intermediate rounding before converting to INT? Literaly writing
> the above yields 1.0 for NINT ( 0.5 - epsilon ) assuming the hardware
> rounds to nearest even for the addition.
It doesn't define this, so far as I am aware -- and, really, I'm not at
all sure whether the standard authors intended the description to be
interpreted as exact math, or as numerically-approximate math.
On the other hand, I just checked the Fortran 2003 standard to see if it
was any clearer, and it looks like they decided to sidestep the issue
entirely -- the result of NINT(A) is now defined as "the integer nearest
A, or if there are two integers equally near A, the result is whichever
such integer has the greater magnitude." Since this isn't listed as an
incompatibility between F2003 and F95, it's presumably fair to consider
this a clarification of the intent of the F95 standard as well.
Thus, this is probably a bug in Gfortran; the following program should
demonstrate it:
program nint_bug
real :: x
x = 0.5 - epsilon(x)/4.0
write(*,*) x - 0.5, nint(x)
if (nint(x) /= 0) call abort
end program
Interestingly, on i686 machines, this program fails to show the bug;
even int(x+0.5) in this example produces 0. This is presumably due to
the use of extra-precision registers; if one stores x+0.5 in another
variable (thereby pulling it out of the registers) and then calls int()
on it, one does get an "erroneous" value of 1.
Unfortunately, I don't have a non-Intel machine handy to test this on;
perhaps someone who has one could test it and (if appropriate) file a PR?
- Brooks
More information about the Fortran
mailing list