Files
glibc/sysdeps/ieee754/ldbl-128/s_logbl.c
T
Shamil Abdulaev 9e1a0b152b math: Set errno to ERANGE for logb (+-0) [BZ #6793]
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>
2026-09-07 11:38:48 -03:00

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)