Implementing C99's roundf(), round(), and roundl()

David Schultz das at FreeBSD.ORG
Wed Jan 21 01:18:56 PST 2004

On Tue, Jan 20, 2004, Bruce Evans wrote:
> I think getting FE_INEXACT from rint() is the usual case (if the
> implementation actually raises it), so we gain little or negative from
> sometimes avoiding the more complicated rint() call.  Also, if we
> depend on the implemenation to set FE_INEXACT, then we may be able to
> depend on the implementation having FE_UPWARD and FE_DOWNWARD, which
> seems to permit a simple implementation that I had in mind.

If you have something in mind that will work, and you have the
time to code it up, then by all means present or commit it.  You
probably have a better idea than I do about the best way to deal
with the exceptions and whatnot.  (Thanks again for taking the
time to look at all of this, by the way.)

> > Another option is to just implement the relevant parts of fenv.h.
> > They are fairly straightforward, and there's no sense in hiding
> > behind the brokenness of gcc's i386 backend forever.
> Is "hiding" not bothering to implement this because gcc's bugs make
> it moot?  I think fenv.h can't be implemented until there is
> "#pragma STDC FENV_ACCESS ON" or some other mechanism to turn off
> both the bugs and (non-buggy) optimizations.
> BTW, I've been using "#define const volatile const" in lib/msun for
> 10 years to turn off some constant folding.  I'm not sure exactly what
> C99 says about it, but I think most FP constant folding at compile
> time is a valid optimization unless FENV_ACCESS is ON.  To avoid
> depending on implementation details that aren't even implemented, msun
> probably needs large changes to use FENV_ACCESS a lot, and/or to use
> feraisexcept() instead of things like:
> e_exp.c:	    if(x > o_threshold) return huge*huge; /* overflow */
> [This needs to raise FE_OVERFLOW, and depends on huge*huge doing it,
> but huge is just "static const double huge 1.0e+300;" and gcc -O1
> folds huge*huge to +Inf at compile time and doesn't raise FE_OVERFLOW.
> My volatile hack forces this to be done at runtime.]

When FENV_ACCESS is on, C99 requires compiler-optimized code to be
affected by any operative modes in effect at runtime and set any
exception flags at runtime as if no optimizations had been
performed.  gcc is flat out broken in this regard, as I think
you've pointed out in the past.  Even with FENV_ACCESS on (though
likely ignored entirely), the code generated for 'd = 0.0 / 0.0' is:

                movl    $0, %eax
                movl    $2146959360, %edx
                movl    %eax, -8(%ebp)
                movl    %edx, -4(%ebp)

I know about the kludges in the math library to raise various
exceptions, but they should be valid with a C99 compiler and the
appropriate pragma.  Ultimately, it wouldn't hurt to clean them
up, though, and it would be nice to have fenv.h before doing that...

Given that gcc is so broken with respect to exceptions, the fact
that the math libraries don't raise the appropriate exceptions is
not a big concern given that basic arithmetic operations often
don't raise exceptions either.  When gcc is fixed, both of these
problems will go away simultaneously.  Nevertheless, if we
implement fenv.h now, we (a) are able to clean up libm sooner and
(b) are a step ahead when gcc supports exceptions better.  It
doesn't seem like we have much to lose by going ahead and
implementing fenv.h, so at the very least we can use it in our own

More information about the freebsd-standards mailing list