From owner-freebsd-standards@FreeBSD.ORG Mon Jan 19 13:32:16 2004 Return-Path: Delivered-To: freebsd-standards@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 2E13316A4CE for ; Mon, 19 Jan 2004 13:32:16 -0800 (PST) Received: from VARK.homeunix.com (adsl-68-122-6-70.dsl.pltn13.pacbell.net [68.122.6.70]) by mx1.FreeBSD.org (Postfix) with ESMTP id 650E743D3F for ; Mon, 19 Jan 2004 13:32:11 -0800 (PST) (envelope-from das@FreeBSD.ORG) Received: from VARK.homeunix.com (localhost [127.0.0.1]) by VARK.homeunix.com (8.12.10/8.12.10) with ESMTP id i0JLVhKu073075; Mon, 19 Jan 2004 13:31:43 -0800 (PST) (envelope-from das@FreeBSD.ORG) Received: (from das@localhost) by VARK.homeunix.com (8.12.10/8.12.10/Submit) id i0JLVgID073074; Mon, 19 Jan 2004 13:31:42 -0800 (PST) (envelope-from das@FreeBSD.ORG) Date: Mon, 19 Jan 2004 13:31:42 -0800 From: David Schultz To: Bruce Evans Message-ID: <20040119213142.GA72803@VARK.homeunix.com> Mail-Followup-To: Bruce Evans , Steve Kargl , freebsd-standards@FreeBSD.ORG References: <20031129000133.GA30662@troutmask.apl.washington.edu> <20031129080911.GA25448@VARK.homeunix.com> <20031129163105.GA32651@troutmask.apl.washington.edu> <20031130213951.GA37082@VARK.homeunix.com> <20031201182219.O4431@gamplex.bde.org> <20031201203512.GA95524@troutmask.apl.washington.edu> <20031202091936.I8778@gamplex.bde.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20031202091936.I8778@gamplex.bde.org> cc: freebsd-standards@FreeBSD.ORG cc: Steve Kargl Subject: Re: Implementing C99's roundf(), round(), and roundl() X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Jan 2004 21:32:16 -0000 On Tue, Dec 02, 2003, Bruce Evans wrote: > On Mon, 1 Dec 2003, Steve Kargl wrote: > > > On Mon, Dec 01, 2003 at 07:05:18PM +1100, Bruce Evans wrote: > > > All the other corner cases need to be checked. It's possibly to check > > > all 2^32 cases for floats (once you know the correct results). > > > > Do you have code to do this check? > > > > > Other things to check: setting of exception flags. I'm not sure if the > > > settings by ceil() are the right ones and the only ones. > > I thought of a good way after righting the above: roundf() is supposed to > be equivalent to rintf() with certain rounding, so set the rounding mode > and call rintf() to determine the correct value. Unfortunately there > might not be a correct rounding mode (what does round to nearest do > for integers? I think it rounds to even, but roundf() requires rounding > up half-way cases). You're right on the money. The C99 standard says: The double version of round behaves as though implemented by #include #include #pragma STDC FENV_ACCESS ON double round(double x) { double result; fenv_t save_env; feholdexcept(&save_env); result = rint(x); if (fetestexcept(FE_INEXACT)) { fesetround(FE_TOWARDZERO); result = rint(copysign(0.5 + fabs(x), x)); } feupdateenv(&save_env); return result; } The round functions may, but are not required to, raise the inexact exception for noninteger numeric arguments, as this implementation does. This should be a faster implementation in that it only has one branch. The one with ceil() has a branch for the inf/NaN test, another that I added to avoid spurious inexact exceptions, and a third to test the sign of the input. However, I think we may be able to use floor() instead of fesetround()/rint()/feupdateenv() and do something similar without changing the rounding mode: 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? By the way, the man pages refer to fpresetsticky(3), but not fpsetsticky(3). The MI ieee.h header declares only fpsetsticky(), but some architectures override these with equivalent macros for both. If you have a good idea of how this is supposed to be, it would be great if you could fix it. 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. (By the way, if we did implement fenv.h, does anyone know if there are any legal issues or attribution requirements involved in using the exact round() code proposed by the C standard?)