summaryrefslogtreecommitdiffstats
path: root/lib/msun
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>2008-02-14 13:44:03 +0000
committerbde <bde@FreeBSD.org>2008-02-14 13:44:03 +0000
commitfda3d327bb53def2427bfd1e96bf8bf1fd4b91ac (patch)
tree200bcf0f45e36a9a5f0d825b6771084f7cc46b4e /lib/msun
parent419234714f55d2950c53162eb6f0cf83045c2d3d (diff)
downloadFreeBSD-src-fda3d327bb53def2427bfd1e96bf8bf1fd4b91ac.zip
FreeBSD-src-fda3d327bb53def2427bfd1e96bf8bf1fd4b91ac.tar.gz
Use the expression fabs(x+0.0)+fabs(y+0.0) instad of a+b (where a is
|x| or |y| and b is |y| or |x|) when mixing NaN arg(s). hypot*() had its own foot shooting for mixing NaNs -- it swaps the args so that |x| in bits is largest, but does this before quieting signaling NaNs, so on amd64 (where the result of adding NaNs depends on the order) it gets inconsistent results if setting the quiet bit makes a difference, just like a similar ia64 and i387 hardware comparison. The usual fix (see e_powf.c 1.13 for more details) of mixing using (a+0.0)+-(b+0.0) doesn't work on amd64 if the args are swapped (since the rder makes a difference with SSE). Fortunately, the original args are unchanged and don't need to be swapped when we let the hardware decide the mixing after quieting them, but we need to take their absolute value. hypotf() doesn't seem to have any real bugs masked by this non-bug. On amd64, its maximum error in 2^32 trials on amd64 is now 0.8422 ulps, and on i386 the maximum error is unchanged and about the same, except with certain CFLAGS it magically drops to 0.5 (perfect rounding). Convert to __FBSDID().
Diffstat (limited to 'lib/msun')
-rw-r--r--lib/msun/src/e_hypot.c8
-rw-r--r--lib/msun/src/e_hypotf.c8
2 files changed, 8 insertions, 8 deletions
diff --git a/lib/msun/src/e_hypot.c b/lib/msun/src/e_hypot.c
index e2f82ac..932b5db 100644
--- a/lib/msun/src/e_hypot.c
+++ b/lib/msun/src/e_hypot.c
@@ -11,9 +11,8 @@
* ====================================================
*/
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
/* __ieee754_hypot(x,y)
*
@@ -68,7 +67,8 @@ __ieee754_hypot(double x, double y)
if(ha > 0x5f300000) { /* a>2**500 */
if(ha >= 0x7ff00000) { /* Inf or NaN */
u_int32_t low;
- w = a+b; /* for sNaN */
+ /* Use original arg order iff result is NaN; quieten sNaNs. */
+ w = fabs(x+0.0)+fabs(y+0.0);
GET_LOW_WORD(low,a);
if(((ha&0xfffff)|low)==0) w = a;
GET_LOW_WORD(low,b);
diff --git a/lib/msun/src/e_hypotf.c b/lib/msun/src/e_hypotf.c
index 0624a39..b100b75 100644
--- a/lib/msun/src/e_hypotf.c
+++ b/lib/msun/src/e_hypotf.c
@@ -13,9 +13,8 @@
* ====================================================
*/
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
#include "math.h"
#include "math_private.h"
@@ -37,7 +36,8 @@ __ieee754_hypotf(float x, float y)
k=0;
if(ha > 0x58800000) { /* a>2**50 */
if(ha >= 0x7f800000) { /* Inf or NaN */
- w = a+b; /* for sNaN */
+ /* Use original arg order iff result is NaN; quieten sNaNs. */
+ w = fabsf(x+0.0F)+fabsf(y+0.0F);
if(ha == 0x7f800000) w = a;
if(hb == 0x7f800000) w = b;
return w;
OpenPOWER on IntegriCloud