Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 16 Jan 2012 14:51:13 -0500
From:      David Schultz <das@freebsd.org>
To:        Ian Lepore <freebsd@damnhippie.dyndns.org>
Cc:        freebsd-arm <freebsd-arm@freebsd.org>
Subject:   Re: fenv.h fixes for softfloat
Message-ID:  <20120116195113.GA87187@zim.MIT.EDU>
In-Reply-To: <1326730552.1669.29.camel@revolution.hippie.lan>
References:  <20120111175516.GA99475@zim.MIT.EDU> <1326509894.48691.100.camel@revolution.hippie.lan> <20120114081214.GA14925@zim.MIT.EDU> <1326563626.1678.34.camel@revolution.hippie.lan> <20120114182933.GA17739@zim.MIT.EDU> <1326568038.1678.43.camel@revolution.hippie.lan> <20120114211039.GA18310@zim.MIT.EDU> <1326591214.1678.85.camel@revolution.hippie.lan> <20120116022647.GA36657@zim.MIT.EDU> <1326730552.1669.29.camel@revolution.hippie.lan>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, Jan 16, 2012, Ian Lepore wrote:
> So, on theory that there's probably nothing wrong with rint() but maybe
> something wrong with casting, I tried a test that does what the guts of
> llrint() does, but breaking the casting into a separate step and looking
> at the flags after each operation.  I also tried casting to (long)
> versus (long long) and the results are different.  Here's the broken
> down test code:
> 
>         fenv_t env;
>         volatile long long llr;
>         volatile double dr;
>         volatile double _d = 1.0;
>         
>         feclearexcept(FE_ALL_EXCEPT);
>         feholdexcept(&env);
>         printf("except 1: %#x\n", fetestexcept(FE_ALL_EXCEPT));
>         
>         dr = rint(_d);
>         printf("except 2: %#x\n", fetestexcept(FE_ALL_EXCEPT));
>         
>         if (fetestexcept(FE_INVALID))
>             feclearexcept(FE_INEXACT);
>         printf("except 3: %#x\n", fetestexcept(FE_ALL_EXCEPT));
>         
>         llr = (long)dr;
>         printf("except 4: %#x\n", fetestexcept(FE_ALL_EXCEPT));
>         
>         llr = (long long)dr;
>         printf("except 5: %#x\n", fetestexcept(FE_ALL_EXCEPT));
>         
>         feupdateenv(&env);
>         printf("except 6: %#x _d=%f dr=%f llr=%lld\n", fetestexcept(FE_ALL_EXCEPT), _d, dr, llr);
> 
> And here's the output from running it:
> 
>         except 1: 0
>         except 2: 0
>         except 3: 0
>         except 4: 0
>         except 5: 0x10
>         except 6: 0x10 _d=1.000000 dr=1.000000 llr=1
> 
> It's interesting that a cast to 32 bits is fine but a cast directly to
> 64 bits raises FE_INEXACT for the same value.

The problem is that double->long conversions use the __fixdfsi
function in softfloat, but there's no equivalent double->longlong.
Instead, a semi-bogus __fixdfdi function is provided in libc/quad.
It'll take a little while to come up with a good fix.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120116195113.GA87187>