diff options
author | Richard Henderson <rth@twiddle.net> | 2012-06-15 12:17:11 -0700 |
---|---|---|
committer | Richard Henderson <rth@twiddle.net> | 2012-06-15 12:17:11 -0700 |
commit | f56ed78d4ad3fa029df5db1110aee06f1e26f199 (patch) | |
tree | e8f2358d8f16386a757ef7125695e7b98a566b24 | |
parent | 45c8de68d5ffe794665a22cb537c87834e83f726 (diff) | |
download | glibc-f56ed78d4ad3fa029df5db1110aee06f1e26f199.tar glibc-f56ed78d4ad3fa029df5db1110aee06f1e26f199.tar.gz glibc-f56ed78d4ad3fa029df5db1110aee06f1e26f199.tar.bz2 glibc-f56ed78d4ad3fa029df5db1110aee06f1e26f199.zip |
[BZ #13848] alpha: Fix s_nearbyint implementation.
-rw-r--r-- | sysdeps/alpha/fpu/s_nearbyint.c | 31 | ||||
-rw-r--r-- | sysdeps/alpha/fpu/s_nearbyintf.c | 35 |
2 files changed, 37 insertions, 29 deletions
diff --git a/sysdeps/alpha/fpu/s_nearbyint.c b/sysdeps/alpha/fpu/s_nearbyint.c index 1f89260569..4589bfcc3e 100644 --- a/sysdeps/alpha/fpu/s_nearbyint.c +++ b/sysdeps/alpha/fpu/s_nearbyint.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007 Free Software Foundation, Inc. +/* Copyright (C) 2000-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson. @@ -19,22 +19,23 @@ #include <math.h> #include <math_ldbl_opt.h> -#ifdef _IEEE_FP_INEXACT -#error "Don't compile with -mieee-with-inexact" -#endif double __nearbyint (double x) { - double two52 = copysign (0x1.0p52, x); - double r; - - r = x + two52; - r = r - two52; - - /* nearbyint(-0.1) == -0, and in general we'll always have the same sign - as our input. */ - return copysign (r, x); + if (isless (fabs (x), 9007199254740992.0)) /* 1 << DBL_MANT_DIG */ + { + double tmp1, new_x; + __asm ("cvttq/svd %2,%1\n\t" + "cvtqt/d %1,%0\n\t" + : "=f"(new_x), "=&f"(tmp1) + : "f"(x)); + + /* nearbyint(-0.1) == -0, and in general we'll always have the same + sign as our input. */ + x = copysign(new_x, x); + } + return x; } weak_alias (__nearbyint, nearbyint) @@ -42,6 +43,6 @@ weak_alias (__nearbyint, nearbyint) strong_alias (__nearbyint, __nearbyintl) weak_alias (__nearbyint, nearbyintl) #endif -#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_1) -compat_symbol (libm, __nearbyint, nearbyintl, GLIBC_2_1); +#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_0) +compat_symbol (libm, __nearbyint, nearbyintl, GLIBC_2_0); #endif diff --git a/sysdeps/alpha/fpu/s_nearbyintf.c b/sysdeps/alpha/fpu/s_nearbyintf.c index efea95902b..871b9f6a02 100644 --- a/sysdeps/alpha/fpu/s_nearbyintf.c +++ b/sysdeps/alpha/fpu/s_nearbyintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007 Free Software Foundation, Inc. +/* Copyright (C) 2007-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson. @@ -18,22 +18,29 @@ #include <math.h> -#ifdef _IEEE_FP_INEXACT -#error "Don't compile with -mieee-with-inexact" -#endif - float __nearbyintf (float x) { - float two23 = copysignf (0x1.0p23, x); - float r; - - r = x + two23; - r = r - two23; - - /* nearbyint(-0.1) == -0, and in general we'll always have the same sign - as our input. */ - return copysign (r, x); + if (isless (fabsf (x), 16777216.0f)) /* 1 << FLT_MANT_DIG */ + { + /* Note that Alpha S_Floating is stored in registers in a + restricted T_Floating format, so we don't even need to + convert back to S_Floating in the end. The initial + conversion to T_Floating is needed to handle denormals. */ + + float tmp1, tmp2, new_x; + + __asm ("cvtst/s %3,%2\n\t" + "cvttq/svd %2,%1\n\t" + "cvtqt/d %1,%0\n\t" + : "=f"(new_x), "=&f"(tmp1), "=&f"(tmp2) + : "f"(x)); + + /* nearbyintf(-0.1) == -0, and in general we'll always have the same + sign as our input. */ + x = copysignf(new_x, x); + } + return x; } weak_alias (__nearbyintf, nearbyintf) |