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

Bruce Evans bde at zeta.org.au
Mon Jan 19 20:34:13 PST 2004


On Mon, 19 Jan 2004, Steve Kargl wrote:

> On Mon, Jan 19, 2004 at 01:31:42PM -0800, David Schultz wrote:
> >
> > 	double
> > 	round(double x)
> > 	{
> > 		double result;
> > 		fp_except_t fe;
> >
> > 		fe = fpresetsticky(0);
> > 		result = rint(x);
> > 		if (fpgetsticky() & FP_X_IMP) {
> > 			result = copysign(floor(fabs(x) + 0.5), x);
> > 			fe |= FP_X_IMP;
> > 		}
> > 		fpresetsticky(fe);
> > 		return (result);
> > 	}
> >
> > Does this seem reasonable?
>
> Don't you need
>
>         rnd = fpsetround(FP_RN); /* Set to known rounding mode */
> 		result = rint(x);
>         fpsetround(rnd);         /* Reset to whatever the user had */
>
> to ensure that rint() rounds to an expected value.

rint() may (and apparently does in at least our i386 implementation)
raise the inexact exception when it does any rounding.  So if rounding
is needed then it is needed only in the inexact exception case, and
David's point is to avoid it there.

> int main(void) {
>     double u, v, x;
>     x = 0.5;
>     fpsetround(FP_RM);
>     u = round(x);
>     fpsetround(FP_RP);
>     v = round(x);
>     /* Does u equal v ? */
> }

Testing on i386's shows that it does :-).

Bruce


More information about the freebsd-standards mailing list