On 2004-04-27, at 12:32:29 +0100, Nicholas Clark wrote:
> On Mon, Apr 26, 2004 at 07:33:09AM +0200, Marcus Holland-Moritz wrote:
>
> > Looking at the generated assembly code revealed that casting 'double'
> > to 'unsigned long long' calls __fixunsdfdi(). GCC implements this
> > function, as does OpenBSD's libc (!). Now, the cool thing is that
> > casting works as long as you do _not_ link libc to your executable.
> > I you do (and Perl does), you start getting wrong results for values
> > larger 2**32:
>
> This rings bells. I'm sure we had the same issue with linking (not linking)
> libc with tracking down a modf bug on Linux once. But I can't find it in
> the archives.
>
> How garbage is the output?
When casting floating point values > 2**31-1 (double or float)
to an unsigned long long, the result will be 1 too large.
> Can it be detected by Configure...
$ uname -a
OpenBSD openbsd34.mhxnet 3.4 GENERIC#18 i386
$ cat test.c
typedef unsigned long long U64;
int main(void)
{
double f = 4294967295.5;
U64 u = (U64) f;
return u != 4294967295ULL;
}
$ cc -o test test.c && ./test || echo bug
$ cc -o test -lc test.c && ./test || echo bug
bug
> ...and worked around?
I think so.
> Is it worth it?
Depends on how we want to work around. I see these options:
1) Forbid building with -Duse64bitint.
2) Look through the source for all code that casts floating point
values to U64, and - if possible - work around the bug for
values larger than 2**32-1.
3) Implement our own conversion routines... :-)
I'd vote for 1).
Marcus
> Nicholas Clark
--
Established technology tends to persist in the face of new technology.
-- G. Blaauw, one of the designers of System 360