[PATCH v2] math: Set errno to ERANGE for logb (+-0) [BZ #6793]
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Fri Sep 4 18:32:21 GMT 2026
On 04/09/26 15:13, Shamil Abdulaev wrote:
> 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>
LGTM, thanks.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> ---
> Changes since v1:
>
> - Use __math_divzero / __math_divzerof in the double and float
> implementations instead of open-coding the errno setting.
> - Use math_opt_barrier on the numerator in the long double and
> powerpc implementations, where no such helper exists, so that the
> division by zero is not folded at compile time.
> - Move sysdeps/i386/fpu/s_logbl.c to sysdeps/x86/fpu and drop
> sysdeps/x86_64/fpu/s_logbl.c, which only included it.
> - Drop the claim that the i386 assembly is removed for the same
> reason as ilogb in commit 7c00a20397; that removal was a
> performance change.
>
> manual/math.texi | 3 ++-
> math/libm-test-logb.inc | 6 ++----
> sysdeps/i386/fpu/s_logb.S | 16 ----------------
> sysdeps/i386/fpu/s_logbf.S | 16 ----------------
> sysdeps/ieee754/dbl-64/s_logb.c | 7 ++++++-
> sysdeps/ieee754/flt-32/s_logbf.c | 7 ++++++-
> sysdeps/ieee754/ldbl-128/s_logbl.c | 14 +++++++++++++-
> sysdeps/ieee754/ldbl-128ibm/s_logbl.c | 8 +++++++-
> sysdeps/m68k/m680x0/fpu/s_logbl.c | 8 +++++++-
> sysdeps/powerpc/fpu/s_logb.c | 9 +++++++--
> sysdeps/powerpc/fpu/s_logbf.c | 9 +++++++--
> sysdeps/powerpc/fpu/s_logbl.c | 9 +++++++--
> sysdeps/{i386 => x86}/fpu/s_logbl.c | 10 ++++++++++
> sysdeps/x86_64/fpu/s_logbl.c | 1 -
> 14 files changed, 74 insertions(+), 49 deletions(-)
> delete mode 100644 sysdeps/i386/fpu/s_logb.S
> delete mode 100644 sysdeps/i386/fpu/s_logbf.S
> rename sysdeps/{i386 => x86}/fpu/s_logbl.c (50%)
> delete mode 100644 sysdeps/x86_64/fpu/s_logbl.c
>
> diff --git a/manual/math.texi b/manual/math.texi
> index cf57937943..945b48d9fc 100644
> --- a/manual/math.texi
> +++ b/manual/math.texi
> @@ -669,7 +669,8 @@ due to intermediate rounding.
> If @var{x} is de-normalized, @code{logb} returns the exponent @var{x}
> would have if it were normalized. If @var{x} is infinity (positive or
> negative), @code{logb} returns @math{@infinity{}}. If @var{x} is zero,
> -@code{logb} returns @math{@infinity{}}. It does not signal.
> +a pole error occurs: @code{logb} raises the divide-by-zero exception,
> +sets @code{errno} to @code{ERANGE} and returns @math{-@infinity{}}.
> @end deftypefun
>
> @deftypefun int ilogb (double @var{x})
> diff --git a/math/libm-test-logb.inc b/math/libm-test-logb.inc
> index 8399f52031..df8642bf21 100644
> --- a/math/libm-test-logb.inc
> +++ b/math/libm-test-logb.inc
> @@ -23,10 +23,8 @@ static const struct test_f_f_data logb_test_data[] =
> TEST_f_f (logb, plus_infty, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
> TEST_f_f (logb, minus_infty, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
>
> - /* Bug 6793: errno setting may be missing. */
> - TEST_f_f (logb, 0, minus_infty, NO_INEXACT_EXCEPTION|DIVIDE_BY_ZERO_EXCEPTION),
> -
> - TEST_f_f (logb, minus_zero, minus_infty, NO_INEXACT_EXCEPTION|DIVIDE_BY_ZERO_EXCEPTION),
> + TEST_f_f (logb, 0, minus_infty, NO_INEXACT_EXCEPTION|DIVIDE_BY_ZERO_EXCEPTION|ERRNO_ERANGE),
> + TEST_f_f (logb, minus_zero, minus_infty, NO_INEXACT_EXCEPTION|DIVIDE_BY_ZERO_EXCEPTION|ERRNO_ERANGE),
> TEST_f_f (logb, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
> TEST_f_f (logb, -qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
> TEST_f_f (logb, snan_value, qnan_value, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION),
> diff --git a/sysdeps/i386/fpu/s_logb.S b/sysdeps/i386/fpu/s_logb.S
> deleted file mode 100644
> index d1c7129248..0000000000
> --- a/sysdeps/i386/fpu/s_logb.S
> +++ /dev/null
> @@ -1,16 +0,0 @@
> -/*
> - * Public domain.
> - */
> -
> -#include <machine/asm.h>
> -#include <libm-alias-double.h>
> -
> -RCSID("$NetBSD: s_logb.S,v 1.4 1995/05/09 00:14:30 jtc Exp $")
> -
> -ENTRY(__logb)
> - fldl 4(%esp)
> - fxtract
> - fstp %st
> - ret
> -END (__logb)
> -libm_alias_double (__logb, logb)
> diff --git a/sysdeps/i386/fpu/s_logbf.S b/sysdeps/i386/fpu/s_logbf.S
> deleted file mode 100644
> index 0d5e55d34f..0000000000
> --- a/sysdeps/i386/fpu/s_logbf.S
> +++ /dev/null
> @@ -1,16 +0,0 @@
> -/*
> - * Public domain.
> - */
> -
> -#include <machine/asm.h>
> -#include <libm-alias-float.h>
> -
> -RCSID("$NetBSD: s_logbf.S,v 1.3 1995/05/09 00:15:12 jtc Exp $")
> -
> -ENTRY(__logbf)
> - flds 4(%esp)
> - fxtract
> - fstp %st
> - ret
> -END (__logbf)
> -libm_alias_float (__logb, logb)
> diff --git a/sysdeps/ieee754/dbl-64/s_logb.c b/sysdeps/ieee754/dbl-64/s_logb.c
> index 49b88d2c8d..af4d56a2e7 100644
> --- a/sysdeps/ieee754/dbl-64/s_logb.c
> +++ b/sysdeps/ieee754/dbl-64/s_logb.c
> @@ -20,11 +20,15 @@
> #include <math_private.h>
> #include <libm-alias-double.h>
> #include <fix-int-fp-convert-zero.h>
> +#include "math_config.h"
>
> double
> __logb (double x)
> {
> #if USE_LOGB_BUILTIN
> + if (__glibc_unlikely (x == 0))
> + /* Pole error: logb (+-0). */
> + return __math_divzero (1);
> return __builtin_logb (x);
> #else
> int64_t ix, ex;
> @@ -32,7 +36,8 @@ __logb (double x)
> EXTRACT_WORDS64 (ix, x);
> ix &= UINT64_C(0x7fffffffffffffff);
> if (ix == 0)
> - return -1.0 / fabs (x);
> + /* Pole error: logb (+-0). */
> + return __math_divzero (1);
> ex = ix >> 52;
> if (ex == 0x7ff)
> return x * x;
> diff --git a/sysdeps/ieee754/flt-32/s_logbf.c b/sysdeps/ieee754/flt-32/s_logbf.c
> index 29316e5787..f21a5b4123 100644
> --- a/sysdeps/ieee754/flt-32/s_logbf.c
> +++ b/sysdeps/ieee754/flt-32/s_logbf.c
> @@ -16,11 +16,15 @@
> #include <math_private.h>
> #include <libm-alias-float.h>
> #include <fix-int-fp-convert-zero.h>
> +#include "math_config.h"
>
> float
> __logbf (float x)
> {
> #if USE_LOGBF_BUILTIN
> + if (__glibc_unlikely (x == 0))
> + /* Pole error: logbf (+-0). */
> + return __math_divzerof (1);
> return __builtin_logbf (x);
> #else
> int32_t ix, rix;
> @@ -28,7 +32,8 @@ __logbf (float x)
> GET_FLOAT_WORD (ix, x);
> ix &= 0x7fffffff; /* high |x| */
> if (ix == 0)
> - return (float) -1.0 / fabsf (x);
> + /* Pole error: logbf (+-0). */
> + return __math_divzerof (1);
> if (ix >= 0x7f800000)
> return x * x;
> if (__glibc_unlikely ((rix = ix >> 23) == 0))
> diff --git a/sysdeps/ieee754/ldbl-128/s_logbl.c b/sysdeps/ieee754/ldbl-128/s_logbl.c
> index 7927155cac..2151a04117 100644
> --- a/sysdeps/ieee754/ldbl-128/s_logbl.c
> +++ b/sysdeps/ieee754/ldbl-128/s_logbl.c
> @@ -23,6 +23,8 @@ static char rcsid[] = "$NetBSD: $";
> */
>
> #include <math.h>
> +#include <errno.h>
> +#include <math-barriers.h>
> #include <math_private.h>
> #include <libm-alias-ldouble.h>
>
> @@ -30,6 +32,12 @@ _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. */
> @@ -38,7 +46,11 @@ __logbl (_Float128 x)
> GET_LDOUBLE_WORDS64 (hx, lx, x);
> hx &= 0x7fffffffffffffffLL; /* high |x| */
> if ((hx | lx) == 0)
> - return -1.0 / fabsl (x);
> + {
> + /* 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 */
> diff --git a/sysdeps/ieee754/ldbl-128ibm/s_logbl.c b/sysdeps/ieee754/ldbl-128ibm/s_logbl.c
> index 37ef47b6a4..cea7c14d8b 100644
> --- a/sysdeps/ieee754/ldbl-128ibm/s_logbl.c
> +++ b/sysdeps/ieee754/ldbl-128ibm/s_logbl.c
> @@ -19,6 +19,8 @@
> */
>
> #include <math.h>
> +#include <errno.h>
> +#include <math-barriers.h>
> #include <math_private.h>
> #include <math_ldbl_opt.h>
> #include <fix-int-fp-convert-zero.h>
> @@ -34,7 +36,11 @@ __logbl (long double x)
> hxs = hx;
> hx &= 0x7fffffffffffffffLL; /* high |x| */
> if (hx == 0)
> - return -1.0 / fabs (x);
> + {
> + /* Pole error: logbl (+-0). */
> + __set_errno (ERANGE);
> + return math_opt_barrier (-1.0) / fabs (x);
> + }
> if (hx >= 0x7ff0000000000000LL)
> return x * x;
> if (__glibc_unlikely ((rhx = hx >> 52) == 0))
> diff --git a/sysdeps/m68k/m680x0/fpu/s_logbl.c b/sysdeps/m68k/m680x0/fpu/s_logbl.c
> index 8cd2326bf8..ec2448aebe 100644
> --- a/sysdeps/m68k/m680x0/fpu/s_logbl.c
> +++ b/sysdeps/m68k/m680x0/fpu/s_logbl.c
> @@ -19,6 +19,8 @@
> */
>
> #include <math.h>
> +#include <errno.h>
> +#include <math-barriers.h>
> #include <math_private.h>
>
> long double
> @@ -29,7 +31,11 @@ __logbl (long double x)
> GET_LDOUBLE_WORDS (es, ix, lx, x);
> es &= 0x7fff; /* exponent */
> if ((es | ix | lx) == 0)
> - return -1.0 / fabsl (x);
> + {
> + /* Pole error: logbl (+-0). */
> + __set_errno (ERANGE);
> + return math_opt_barrier (-1.0) / fabsl (x);
> + }
> if (es == 0x7fff)
> return x * x;
> if (es == 0) /* IEEE 754 logb */
> diff --git a/sysdeps/powerpc/fpu/s_logb.c b/sysdeps/powerpc/fpu/s_logb.c
> index 880e48e0f5..bcda752bed 100644
> --- a/sysdeps/powerpc/fpu/s_logb.c
> +++ b/sysdeps/powerpc/fpu/s_logb.c
> @@ -22,6 +22,8 @@
> # include <sysdeps/ieee754/dbl-64/s_logb.c>
> #else
> # include <math.h>
> +# include <errno.h>
> +# include <math-barriers.h>
> # include <math_private.h>
> # include <math_ldbl_opt.h>
> # include <libm-alias-double.h>
> @@ -34,8 +36,11 @@ __logb (double x)
> double ret;
>
> if (__glibc_unlikely (x == 0.0))
> - /* Raise FE_DIVBYZERO and return -HUGE_VAL[LF]. */
> - return -1.0 / fabs (x);
> + {
> + /* Pole error: raise FE_DIVBYZERO, set errno and return -HUGE_VAL. */
> + __set_errno (ERANGE);
> + return math_opt_barrier (-1.0) / fabs (x);
> + }
>
> /* Mask to extract the exponent. */
> asm ("xxland %x0,%x1,%x2\n"
> diff --git a/sysdeps/powerpc/fpu/s_logbf.c b/sysdeps/powerpc/fpu/s_logbf.c
> index c640aa88bc..beeecf9c20 100644
> --- a/sysdeps/powerpc/fpu/s_logbf.c
> +++ b/sysdeps/powerpc/fpu/s_logbf.c
> @@ -22,6 +22,8 @@
> # include <sysdeps/ieee754/flt-32/s_logbf.c>
> #else
> # include <math.h>
> +# include <errno.h>
> +# include <math-barriers.h>
> # include <libm-alias-float.h>
> /* This implementation avoids FP to INT conversions by using VSX
> bitwise instructions over FP values. */
> @@ -32,8 +34,11 @@ __logbf (float x)
> double ret;
>
> if (__glibc_unlikely (x == 0.0))
> - /* Raise FE_DIVBYZERO and return -HUGE_VAL[LF]. */
> - return -1.0 / fabs (x);
> + {
> + /* Pole error: raise FE_DIVBYZERO, set errno and return -HUGE_VALF. */
> + __set_errno (ERANGE);
> + return math_opt_barrier (-1.0) / fabs (x);
> + }
>
> /* mask to extract the exponent. */
> asm ("xxland %x0,%x1,%x2\n"
> diff --git a/sysdeps/powerpc/fpu/s_logbl.c b/sysdeps/powerpc/fpu/s_logbl.c
> index 51edd8ebde..4111fb221c 100644
> --- a/sysdeps/powerpc/fpu/s_logbl.c
> +++ b/sysdeps/powerpc/fpu/s_logbl.c
> @@ -22,6 +22,8 @@
> # include <./sysdeps/ieee754/ldbl-128ibm/s_logbl.c>
> #else
> # include <math.h>
> +# include <errno.h>
> +# include <math-barriers.h>
> # include <math_private.h>
> # include <math_ldbl_opt.h>
>
> @@ -35,8 +37,11 @@ __logbl (long double x)
> int64_t hx;
>
> if (__glibc_unlikely (x == 0.0))
> - /* Raise FE_DIVBYZERO and return -HUGE_VAL[LF]. */
> - return -1.0L / __builtin_fabsl (x);
> + {
> + /* Pole error: raise FE_DIVBYZERO, set errno and return -HUGE_VALL. */
> + __set_errno (ERANGE);
> + return math_opt_barrier (-1.0L) / __builtin_fabsl (x);
> + }
>
> ldbl_unpack (x, &xh, &xl);
> EXTRACT_WORDS64 (hx, xh);
> diff --git a/sysdeps/i386/fpu/s_logbl.c b/sysdeps/x86/fpu/s_logbl.c
> similarity index 50%
> rename from sysdeps/i386/fpu/s_logbl.c
> rename to sysdeps/x86/fpu/s_logbl.c
> index ec867de010..91056e1b06 100644
> --- a/sysdeps/i386/fpu/s_logbl.c
> +++ b/sysdeps/x86/fpu/s_logbl.c
> @@ -2,6 +2,9 @@
> * Public domain.
> */
>
> +#include <math.h>
> +#include <errno.h>
> +#include <math-barriers.h>
> #include <libm-alias-ldouble.h>
>
> long double
> @@ -9,6 +12,13 @@ __logbl (long double x)
> {
> long double res;
>
> + if (__glibc_unlikely (x == 0))
> + {
> + /* Pole error: logbl (+-0). */
> + __set_errno (ERANGE);
> + return math_opt_barrier (-1.0L) / 0.0L;
> + }
> +
> asm ("fxtract\n"
> "fstp %%st" : "=t" (res) : "0" (x));
> return res;
> diff --git a/sysdeps/x86_64/fpu/s_logbl.c b/sysdeps/x86_64/fpu/s_logbl.c
> deleted file mode 100644
> index 4791ba64e8..0000000000
> --- a/sysdeps/x86_64/fpu/s_logbl.c
> +++ /dev/null
> @@ -1 +0,0 @@
> -#include <sysdeps/i386/fpu/s_logbl.c>
More information about the Libc-alpha
mailing list