From owner-freebsd-numerics@FreeBSD.ORG Sun Aug 12 23:01:45 2012 Return-Path: Delivered-To: freebsd-numerics@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DE8131065675 for ; Sun, 12 Aug 2012 23:01:45 +0000 (UTC) (envelope-from peter@rulingia.com) Received: from vps.rulingia.com (host-122-100-2-194.octopus.com.au [122.100.2.194]) by mx1.freebsd.org (Postfix) with ESMTP id 625F28FC12 for ; Sun, 12 Aug 2012 23:01:45 +0000 (UTC) Received: from server.rulingia.com (c220-239-249-137.belrs5.nsw.optusnet.com.au [220.239.249.137]) by vps.rulingia.com (8.14.5/8.14.5) with ESMTP id q7CN1jtK075586 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 13 Aug 2012 09:01:45 +1000 (EST) (envelope-from peter@rulingia.com) X-Bogosity: Ham, spamicity=0.000000 Received: from server.rulingia.com (localhost.rulingia.com [127.0.0.1]) by server.rulingia.com (8.14.5/8.14.5) with ESMTP id q7CN1cxZ021075 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 13 Aug 2012 09:01:39 +1000 (EST) (envelope-from peter@server.rulingia.com) Received: (from peter@localhost) by server.rulingia.com (8.14.5/8.14.5/Submit) id q7CN1cLZ021074 for freebsd-numerics@freebsd.org; Mon, 13 Aug 2012 09:01:38 +1000 (EST) (envelope-from peter) Resent-From: Peter Jeremy Resent-Date: Mon, 13 Aug 2012 09:01:38 +1000 Resent-Message-ID: <20120812230138.GW20453@server.rulingia.com> Resent-To: freebsd-numerics@freebsd.org Received: from vps.rulingia.com (host-122-100-2-194.octopus.com.au [122.100.2.194]) by server.rulingia.com (8.14.5/8.14.5) with ESMTP id q6N59PIu011623 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 23 Jul 2012 15:09:25 +1000 (EST) (envelope-from brde@optusnet.com.au) Received: from mail04.syd.optusnet.com.au (mail04.syd.optusnet.com.au [211.29.132.185]) by vps.rulingia.com (8.14.5/8.14.5) with ESMTP id q6N59OLQ011009 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 23 Jul 2012 15:09:25 +1000 (EST) (envelope-from brde@optusnet.com.au) Received: from c122-106-171-246.carlnfd1.nsw.optusnet.com.au (c122-106-171-246.carlnfd1.nsw.optusnet.com.au [122.106.171.246]) by mail04.syd.optusnet.com.au (8.13.1/8.13.1) with ESMTP id q6N594gK000640 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 23 Jul 2012 15:09:05 +1000 From: Bruce Evans Mail-Followup-To: freebsd-numerics@freebsd.org X-X-Sender: bde@besplex.bde.org To: Peter Jeremy In-Reply-To: <20120722233134.GB8033@server.rulingia.com> Message-ID: <20120723143145.T1353@besplex.bde.org> References: <20120717042125.GF66913@server.rulingia.com> <20120717043848.GB87001@troutmask.apl.washington.edu> <20120717225328.GA86902@server.rulingia.com> <20120717232740.GA95026@troutmask.apl.washington.edu> <20120718001337.GA87817@server.rulingia.com> <20120718123627.D1575@besplex.bde.org> <20120722121219.GC73662@server.rulingia.com> <20120722220031.GA7791@server.rulingia.com> <20120722221614.GB53450@zim.MIT.EDU> <20120722231056.GA84338@troutmask.apl.washington.edu> <20120722233134.GB8033@server.rulingia.com> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed X-Mailman-Approved-At: Sun, 12 Aug 2012 23:55:59 +0000 Cc: Diane Bruce , Steve Kargl , John Baldwin , David Chisnall , Stephen Montgomery-Smith , Bruce Evans , Bruce Evans , David Schultz , Warner Losh Subject: Re: Use of C99 extra long double math functions after r236148 X-BeenThere: freebsd-numerics@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Discussions of high quality implementation of libm functions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Date: Sun, 12 Aug 2012 23:01:46 -0000 X-Original-Date: Mon, 23 Jul 2012 15:09:04 +1000 (EST) X-List-Received-Date: Sun, 12 Aug 2012 23:01:46 -0000 On Mon, 23 Jul 2012, Peter Jeremy wrote: > On 2012-Jul-22 16:10:56 -0700, Steve Kargl wrote: >> The above isn't necessarily true. The Fortran standards from >> 2003 and 2008, very care about NaN. Under certain conditions, >> if one has something like >> >> x = sin(NaN) >> >> in Fortran, then the returned NaN must be the one in the function >> call. > > Even if it was a SNaN? My understanding is that SNaN should be > quietened if they are used in any further floating point operations. This may depend on the language specification, but it can be hard to even pass signaling NaNs without causing an exception. (The following interesting behaviour occurs on x86: - On i387, loading a float or double involves a conversion to long double. This conversion is considered to be an operation and it generates an exception and quietens signalling NaNs. - On i386, the ABI requires FP args to be passed on the stack. Compilers may or may not load float and double args as part of putting them on the stack. If they do, then by the previous point, functions never see float or double signaling NaN args, but functions always see long double signaling NaN args. Then is a buggy function returns x when it should return x+x, the bug is not noticed for the float and double cases but it is noticed (if tested for) in the long double case. - On at least Athlon-xp and Athlon64 before Phenom, compilers should always load at least double args as part of putting them on the stack (or other memory), since copying them through integer registers is very slow (it causes store-to-load mismatches). Compilers don't understand this well, but newer gcc is better and goes through the FPU more (going through SSE is good too). Thus the previous points are affected by CFLAGS and compiler opt/pessimizations. - On SSE, no loads involve an implicit conversion and loads of signaling NaNs never trigger exception handling. - On amd64, SSE is the default for floats and doubles, so passing signaling NaNs never triggers the signal, although the ABI now the first few float and double args to be loaded into SSE registes for passing. - On i386, clang uses SSE too much, and thus triggers signaling NaNs less than gcc. ) >> Having libm, do >> >> if (x == NaN) >> return (x + x); >> >> does/may not return the correct NaN. It usually does return the correct NaN. There is no other reasonably portable way to quieten signaling NaNs. (x + x) works well for NaNs and Infs, but if the value might also be finite, I haven't found anything better than adding 0.0L to trigger the signaling NaNs without corrupting finite values. I changed places like e_hypot.c by adding 0 in the same precision as x (this should be written as plain 0, but I used 0.0 for e_hypot.c and 0.0F or (float)0.0 in e_hypotf.c) to give more consistent NaN mixing (convert before mixing). This still gave inconsistences for long doubles, on x86 due to the above messes and maybe on sparc64 too. Adding 0.0L causes x to be promoted to long double, giving the consistent i387 behaviour for its registers. This is free (makes no difference) on i386, but on amd64 it gives consistently by forcing (das would say) gratuitous use of the i387, and on other arches it gives whatever behaviour long doubles give. > I presume you mean > if (isnan(x)) > return (x + x); Nah, in fdlibm, NaNs are classified using magic bit tests on bits that are kept handy in integer registers for other reasons :-). Using mainly bits is a significant optimization, but it can be better to mix bit operations with FP operations even for test operations, to keep more ALUs streaming. > Do you have a test case that shows that? As far as I can tell, all > the FPUs I have access to will return a quietened variant of the > input NaN in this case (ie, only the signalling bit is altered). I test amd64, i386, ia64 and sparc64 and haven't noticed this failing, though I've noticed a few hundred billion other failures for NaNs. Bruce