Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 14 Jan 2012 18:33:34 -0700
From:      Ian Lepore <freebsd@damnhippie.dyndns.org>
To:        David Schultz <das@freebsd.org>
Cc:        freebsd-arm <freebsd-arm@freebsd.org>
Subject:   Re: fenv.h fixes for softfloat
Message-ID:  <1326591214.1678.85.camel@revolution.hippie.lan>
In-Reply-To: <20120114211039.GA18310@zim.MIT.EDU>
References:  <1326144525.2199.32.camel@revolution.hippie.lan> <20120111052634.GA96534@zim.MIT.EDU> <20120111101833.GA88428@ci0.org> <1326291254.2419.55.camel@revolution.hippie.lan> <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>

next in thread | previous in thread | raw e-mail | index | archive | help
Here are some intermediate results from the llrint() problem before I
call it a night...

The totally degenerate case to get FE_INVALID set is (long long)1.0;

That is, llrint() calls rint() then casts the result to long long.
rint() doesn't even break a sweat converting 1.0 to 1.0 and returns with
no exception flags set, then the cast from 1.0 to 1LL raises FE_INVALID.

With the original value 1.1 instead of 1.0, rint() itself raises
FE_INVALID, in the path that falls out the bottom.  I added printfs:

        printf("rint 7a: except %#x\n", fetestexcept(FE_ALL_EXCEPT));
        INSERT_WORDS(x,i0,i1);
        printf("rint 7b: except %#x\n", fetestexcept(FE_ALL_EXCEPT));
        STRICT_ASSIGN(double,w,TWO52[sx]+x);
        printf("rint 7c: except %#x\n", fetestexcept(FE_ALL_EXCEPT));
        result = w-TWO52[sx];
        printf("rint 8: except %#x i0=%#x i1=%#x x=%g w=%g result=%g\n", fetestexcept(FE_ALL_EXCEPT), i0, i1, x, w, result);
        return result;

And a run using rint(1.1) gave this output:

        rint 7a: except 0
        rint 7b: except 0
        rint 7c: except 0x10
        rint 8: except 0x10 i0=0x3ff20000 i1=0x9999999a x=1.125 w=4.5036e+15 result=1

I think this may be overall bad news.  It seems to imply that certain
normal operations on doubles can raise FE_INVALID as a side effect while
generating valid results, and because of those words in the spec about
how the rounding routines have to behave as if they're a single
operation, I think that means that each rounding routine has to check
for invalid inputs explicitly and raise FE_INVALID, and otherwise don't
let FE_INVALID from rounding or casting leak out to the caller.  Ick.

Or, maybe the fact that (long long)1.0 raises FE_INVALID is the real
problem, like it's not a normal or expected side effect.  Hmmm, for that
matter, what does the spec say about things like casting raising
exceptions?  I think I'll go fix dinner and leave you to ponder that. :)

-- Ian







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