mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-08 23:58:31 +08:00
logb (+-0) is a pole error: it returns -Inf and raises the divide-by-zero exception, but it never set errno, even though glibc defines math_errhandling to include MATH_ERRNO. Set errno in the zero branch that already exists in every logb implementation, instead of adding a w_logb wrapper; the USE_LOGB*_BUILTIN paths have no such branch, so add one there. The double and float versions use __math_divzero and __math_divzerof. There is no long double equivalent, so those keep the explicit division and use math_opt_barrier to stop the compiler from folding it away. The i386 fxtract implementations of logb and logbf cannot set errno, and adding the error handling to the assembly is not worthwhile, so they are removed in favour of the generic C ones. s_logbl.c moves to sysdeps/x86/fpu, replacing the x86_64 copy that only included it. The manual described logb (0) as returning +Inf without signalling, which was wrong in both respects. Tested on x86_64-linux-gnu. Signed-off-by: Shamil Abdulaev <ashamil435@gmail.com> Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
72 lines
1.7 KiB
C
72 lines
1.7 KiB
C
/* s_logbl.c -- long double version of s_logb.c.
|
|
*/
|
|
|
|
/*
|
|
* ====================================================
|
|
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
|
*
|
|
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
|
* Permission to use, copy, modify, and distribute this
|
|
* software is freely granted, provided that this notice
|
|
* is preserved.
|
|
* ====================================================
|
|
*/
|
|
|
|
#if defined(LIBM_SCCS) && !defined(lint)
|
|
static char rcsid[] = "$NetBSD: $";
|
|
#endif
|
|
|
|
/*
|
|
* long double logbl(x)
|
|
* IEEE 754 logb. Included to pass IEEE test suite. Not recommend.
|
|
* Use ilogb instead.
|
|
*/
|
|
|
|
#include <math.h>
|
|
#include <errno.h>
|
|
#include <math-barriers.h>
|
|
#include <math_private.h>
|
|
#include <libm-alias-ldouble.h>
|
|
|
|
_Float128
|
|
__logbl (_Float128 x)
|
|
{
|
|
#if USE_LOGBL_BUILTIN
|
|
if (__glibc_unlikely (x == 0))
|
|
{
|
|
/* Pole error: logbl (+-0). */
|
|
__set_errno (ERANGE);
|
|
return math_opt_barrier (-1.0) / fabsl (x);
|
|
}
|
|
return __builtin_logbl (x);
|
|
#else
|
|
/* Use generic implementation. */
|
|
int64_t lx, hx, ex;
|
|
|
|
GET_LDOUBLE_WORDS64 (hx, lx, x);
|
|
hx &= 0x7fffffffffffffffLL; /* high |x| */
|
|
if ((hx | lx) == 0)
|
|
{
|
|
/* Pole error: logbl (+-0). */
|
|
__set_errno (ERANGE);
|
|
return math_opt_barrier (-1.0) / fabsl (x);
|
|
}
|
|
if (hx >= 0x7fff000000000000LL)
|
|
return x * x;
|
|
if ((ex = hx >> 48) == 0) /* IEEE 754 logb */
|
|
{
|
|
/* POSIX specifies that denormal number is treated as
|
|
though it were normalized. */
|
|
int ma;
|
|
if (hx == 0)
|
|
ma = __builtin_clzll (lx) + 64;
|
|
else
|
|
ma = __builtin_clzll (hx);
|
|
ex -= ma - 16;
|
|
}
|
|
return (_Float128) (ex - 16383);
|
|
#endif /* ! USE_LOGBL_BUILTIN */
|
|
}
|
|
|
|
libm_alias_ldouble (__logb, logb)
|