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>
The bug only exists in the non-FMA-contracted compilation of that
branch. On x86_64 it can be triggered with:
GLIBC_TUNABLES=glibc.cpu.hwcaps=-AVX2 math/test-double-tanh
Or by building without ifunc support.
Checked on aarch64-linux-gnu and x86_64-linux-gnu with
--disable-multi-arch.
The CORE-MATH import mistranslated the accurate path result scaling
'th *= sp.f' as 'th *= asuint64 (sp)' (commit 106f8c2ed6), and two of
the 51 exceptional-case table entries were dropped when the table was
moved to e_sinh_data.c (commit f05c4907a2).
Checked on x86_64-linux-gnu and aarch64-linux-gnu.
The Payne-Hanek range reducer __branred delivers the reduced argument
as a double-double with only about 93 significant bits. For arguments
extremely close to a multiple of pi/2 the true reduced argument can be
as small as 2^-61, so most of those bits cancel and sin/cos/tan can be
wrong by up to ~143000 ulp. This inaccuracy used to be handled by the
multiple-precision slow paths, which was removed by commit
649095838b ("sin/cos slow paths: remove slow paths from huge range
reduction") and commit 476d692e8a ("math: Remove slow paths in tan
[BZ #15267]").
Restore the e_rem_pio2.c (removed as unused by commit ca3aac57ef
"Remove unused math files") and use __ieee754_rem_pio2 for
the huge-argument reduction instead of __branred, which is removed.
It also does not depend on precise IEEE double rounding, so the nofma
and vector-width workarounds for branred.c are no longer needed.
The file is restored trimmed to its huge-argument path, the callers
reduce smaller arguments themselves and handle non-finite inputs, so
only 1e8 < |x| < 2^1024 reaches __ieee754_rem_pio2.
Checked on x86_64-linux-gnu, aarch64-linux-gnu, armv7a-linux-gnueabihf,
and i686-linux-gnu.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
It syncs with CORE-MATH commit 887cab6f. The new tests are from
the CORE-MATH acosh worst-cases inputs that trigger the FE_TOWARDZERO
issue with the previous implementation, along with the hard-to-round
cases from CORE-MATH commits 72febed6 and ce9e99f6.
Checked on x86_64-linux-gnu, x86_64-linux-gnu with --disable-multi-arch
(so soft FMA implementation is used), i686-linux-gnu (which uses its
own acosh implementation), aarch64-linux-gnu, and
armv7a-linux-gnueabihf.
Reviewed-by: Paul Zimmermann <Paul.Zimmermann@inria.fr>
auto-libm-test-in shares inputs between narrowing and non-narrowing
functions, and some carry arg-format conditions (e.g. "arg-ibm128").
When auto-libm-test-out-fma is regenerated, gen-libm-test.py turns these
into TEST_COND_arg_ibm128, which expands via ARG_MANT_DIG to ARG_PREFIX.
ARG_PREFIX is only defined for TEST_NARROW, so the non-narrowing fma test
failed to build with "ARG_PREFIX_MANT_DIG undeclared".
Define TEST_COND_arg_ibm128 to 0 when ARG_FLOAT is not defined, mirroring
the existing guard for TEST_COND_ibm128_libgcc; in the non-narrowing case
there is no separate argument format, so the condition is always false.
Regenerate auto-libm-test-out-fma accordingly.
When d (the exponent difference between z and x*y) is exactly 64,
the alignment path shifts z left by 64 bits via (zhi = nz.m, zlo = 0)
and decrements d to 0, then takes the inner 'if (d < 64)' branch
which evaluates 'rhi << (64 - d)' with d == 0. A shift by 64 of a
64-bit value is UB in C.
Add the explicit 'if (d == 0)' empty branch (present in the
original musl implementation).
Checked on x86_64-linux-gnu with --disable-multi-arch and
arm-linux-gnueabihf.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Vector variants of the new C23 powr routines.
These provide same maximum error error as pow by virtue of
relying on shared approximation techniques and sources.
Note: Benchmark inputs for powr(f) are identical to pow(f).
Performance gain over pow on V1 with GCC@15:
- SVE powr: 10-12% on subnormal x, 12-13% on x < 0.
- SVE powrf: 15% on all x < 0.
- AdvSIMD powr: for x < 0, 40% if x subnormal, 60% otherwise.
- AdvSIMD powrf: 4% on x subnormals or x < 0.
The libc_feupdateenv_test macro is supposed to trap when the trap for a
previously held exception is enabled. But
libc_feupdateenv_test_loongarch wasn't doing it properly: the comment
claims "setting of the cause bits" would cause "the hardware to generate
the exception" but that's simply not true for the LoongArch movgr2fcsr
instruction.
To fix the issue, we need to call __feraiseexcept in case a held exception
is enabled to trap.
Reviewed-by: caiyinyu <caiyinyu@loongson.cn>
Signed-off-by: Xi Ruoyao <xry111@xry111.site>
Common data definitions are moved to e_coshsinh_data, cosh only
data is moved to e_cosh_data, sinh to e_sinh_data, and tanh to
e_tanh_data.
Reviewed-by: DJ Delorie <dj@redhat.com>
The functions are documented to behave like fmax/fmin when the
arguments have the same absolute value.
Checked on x86_64-linux-gnu, aarch64-linux-gnu, i686-linux-gnu,
arm-linux-gnueabihf, powerpc64le-linux-gnu,
riscv64-linux-gnu-rv64imafdc-lp64d, and loongarch64-linux-gnuf64.
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
The C standard (at least from C99 until C23) does not require
fmin/fmax to order zeros by their sign, so glibc's previous behavior
was entirely standards-conforming. However, the standard does
recommend that zeros be ordered in a footnote, saying:
"If possible, fmax is sensitive to the sign of zero, for example
fmax(−0.0, +0.0) ideally returns +0."
As this is indeed possible (and not too complicated), implement it as
a quality-of-implementation improvement. It also remove possible
deviations between architectures, where for some architectures that
has direct mapping instruction (USE_FMA*_BUILTIN) they already do
the ordering.
Checked on x86_64-linux-gnu, aarch64-linux-gnu, i686-linux-gnu,
arm-linux-gnueabihf, powerpc64le-linux-gnu,
riscv64-linux-gnu-rv64imafdc-lp64d, and loongarch64-linux-gnuf64.
Co-authored-by: James Y Knight <jyknight@google.com>
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
On x86_64, it allows the fast path (normal/subnormal inputs) to use maxsd.
With gcc-15 targetting x86_64 for fmax:
* master:
ucomisd xmm0, xmm1
jnb .L1
ucomisd xmm1, xmm0
ja .L13
[...]
.L13:
movapd xmm0, xmm1
.L1:
ret
* patch;
ucomisd xmm0, xmm1
jp .L2
maxsd xmm0, xmm1
ret
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
When the result of ceill, floorl, roundl and truncl is zero, the sign of
the result must match the sign of the input. For the IBM 128-bit long
double format, the sign is determined by the high part.
Ensure the correct sign when the high part is the result of
computations, by copying the sign from the input high part to the output
high part. On POWER, this conveniently maps to the fcpsgn instruction.
In addition add test for the values provided in BZ #33623, and for the
opposite value when the result is 0.
Fixes: BZ #33623
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
The CORE-MATH c423b9a3 commit made atanh to use a slight different
muldd_acc and polydd (which uses muldd_acc internally) compared
to previous version.
The new tests were suggested by Paul Zimmermann (although I did
not see any regression).
Checked on x86_64-linux-gnu, x86_64-linux-gnu-v3, aarch64-linux-gnu,
and i686-linux-gnu.
Reviewed-by: Paul Zimmermann <Paul.Zimmermann@inria.fr>
The CORE-MATH c423b9a3 commit made atanh to use a slight different
muldd_acc, mulddd, and polydd (which uses muldd_acc internally)
compare to asinh and acosh.
The new tests were suggested by Paul Zimmermann (although I did
not see any regression).
Checked on x86_64-linux-gnu, x86_64-linux-gnu-v3, aarch64-linux-gnu,
and i686-linux-gnu.
Reviewed-by: Paul Zimmermann <Paul.Zimmermann@inria.fr>
Neither gcc [1] nor clang [2] handles pseudo-normal numbers correctly
with the __builtin_isinf_sign, so disable its usage for _Float64x and
long double types.
This only affects x86, so add a new define __FP_BUILTIN_ISINF_SIGN_DENORMAL
to gate long double and related types to the libc function instead.
It fixes the regression on test-ldouble-isinf when built with clang:
Failure: isinf (pseudo_zero): Exception "Invalid operation" set
Failure: isinf (pseudo_inf): Exception "Invalid operation" set
Failure: isinf (pseudo_qnan): Exception "Invalid operation" set
Failure: isinf (pseudo_snan): Exception "Invalid operation" set
Failure: isinf (pseudo_unnormal): Exception "Invalid operation" set
Failure: isinf_downward (pseudo_zero): Exception "Invalid operation" set
Failure: isinf_downward (pseudo_inf): Exception "Invalid operation" set
Failure: isinf_downward (pseudo_qnan): Exception "Invalid operation" set
Failure: isinf_downward (pseudo_snan): Exception "Invalid operation" set
Failure: isinf_downward (pseudo_unnormal): Exception "Invalid operation" set
Failure: isinf_towardzero (pseudo_zero): Exception "Invalid operation" set
Failure: isinf_towardzero (pseudo_inf): Exception "Invalid operation" set
Failure: isinf_towardzero (pseudo_qnan): Exception "Invalid operation" set
Failure: isinf_towardzero (pseudo_snan): Exception "Invalid operation" set
Failure: isinf_towardzero (pseudo_unnormal): Exception "Invalid operation" set
Failure: isinf_upward (pseudo_zero): Exception "Invalid operation" set
Failure: isinf_upward (pseudo_inf): Exception "Invalid operation" set
Failure: isinf_upward (pseudo_qnan): Exception "Invalid operation" set
Failure: isinf_upward (pseudo_snan): Exception "Invalid operation" set
Failure: isinf_upward (pseudo_unnormal): Exception "Invalid operation" set
Checked on x86_64-linux-gnu with gcc-15 and clang-18.
[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123173
[2] https://github.com/llvm/llvm-project/issues/172651
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Neither gcc [1] nor clang [2] handles pseudo-normal numbers correctly
with the __builtin_fpclassify, so disable its usage for _Float64x and
long double types.
This only affects x86, so add a new header, fp-builtin-denormal.h, that
defines whether the architecture requires disabling the optimization
through a new glibc define (__FP_BUILTIN_FPCLASSIFY_DENORMAL).
It fixes the regression on test-ldouble-fpclassify and
test-float64x-fpclassify when built with clang:
Failure: fpclassify (pseudo_zero): Exception "Invalid operation" set
Failure: fpclassify (pseudo_inf): Exception "Invalid operation" set
Failure: fpclassify (pseudo_qnan): Exception "Invalid operation" set
Failure: fpclassify (pseudo_snan): Exception "Invalid operation" set
Failure: fpclassify (pseudo_unnormal): Exception "Invalid operation" set
Failure: fpclassify_downward (pseudo_zero): Exception "Invalid operation" set
Failure: fpclassify_downward (pseudo_inf): Exception "Invalid operation" set
Failure: fpclassify_downward (pseudo_qnan): Exception "Invalid operation" set
Failure: fpclassify_downward (pseudo_snan): Exception "Invalid operation" set
Failure: fpclassify_downward (pseudo_unnormal): Exception "Invalid operation" set
Failure: fpclassify_towardzero (pseudo_zero): Exception "Invalid operation" set
Failure: fpclassify_towardzero (pseudo_inf): Exception "Invalid operation" set
Failure: fpclassify_towardzero (pseudo_qnan): Exception "Invalid operation" set
Failure: fpclassify_towardzero (pseudo_snan): Exception "Invalid operation" set
Failure: fpclassify_towardzero (pseudo_unnormal): Exception "Invalid operation" set
Failure: fpclassify_upward (pseudo_zero): Exception "Invalid operation" set
Failure: fpclassify_upward (pseudo_inf): Exception "Invalid operation" set
Failure: fpclassify_upward (pseudo_qnan): Exception "Invalid operation" set
Failure: fpclassify_upward (pseudo_snan): Exception "Invalid operation" set
Failure: fpclassify_upward (pseudo_unnormal): Exception "Invalid operation" set
Checked on x86_64-linux-gnu with gcc-15 and clang-18.
[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123161
[2] https://github.com/llvm/llvm-project/issues/172533
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
clang does not check for unordered numbers with builtins for 128-bit
float types (both _Float128 on x86_64 or long double on aarch64) [1].
For instance, the code:
#ifdef __x86_64__
typedef __float128 FLOAT128_TYPE;
#elif defined (__aarch64__)
typedef long double FLOAT128_TYPE;
#endif
int foo (FLOAT128_TYPE x, FLOAT128_TYPE y)
{
return __builtin_isgreater (x, y);
}
Will issue a __gttf2 call instead of a __unordtf2 followed by the
comparison.
Using the generic implementation fixes multiple issues with math tests,
such as:
Failure: fmax (0, qNaN): Exception "Invalid operation" set
Failure: fmax (0, -qNaN): Exception "Invalid operation" set
Failure: fmax (-0, qNaN): Exception "Invalid operation" set
Failure: fmax (-0, -qNaN): Exception "Invalid operation" set
Failure: fmax (9, qNaN): Exception "Invalid operation" set
Failure: fmax (9, -qNaN): Exception "Invalid operation" set
Failure: fmax (-9, qNaN): Exception "Invalid operation" set
Failure: fmax (-9, -qNaN): Exception "Invalid operation" set
It has a small performance overhead due to the extra isunordered (which
could be omitted for float and double types). Using _Generic (similar to
how __MATH_TG) on a bivariadic function requires a lot of boilerplate
macros.
[1] https://github.com/llvm/llvm-project/issues/172499
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Vector variants of the new C23 rsqrt routines for both AdvSIMD and
SVE, as well as in both single and double precision.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
C23 defines library macros __STDC_VERSION_<header>_H__ to indicate
that a header has support for new / changed features from C23. Now
that all the required library features are implemented in glibc,
define these macros. I'm not sure this is sufficiently much of a
user-visible feature to be worth a mention in NEWS.
Tested for x86_64.
There are various optional C23 features we don't yet have, of which I
might look at the Annex H ones (floating-point encoding conversion
functions and _Float16 functions) next.
* Optional time bases TIME_MONOTONIC, TIME_ACTIVE, TIME_THREAD_ACTIVE.
See
<https://sourceware.org/pipermail/libc-alpha/2023-June/149264.html>
- we need to review / update that patch. (I think patch 2/2,
inventing new names for all the nonstandard CLOCK_* supported by the
Linux kernel, is rather more dubious.)
* Updating conform/ tests for C23.
* Defining the rounding mode macro FE_TONEARESTFROMZERO for RISC-V (as
far as I know, the only architecture supported by glibc that has
hardware support for this rounding mode for binary floating point)
and supporting it throughout glibc and its tests (especially the
string/numeric conversions in both directions that explicitly handle
each possible rounding mode, and various tests that do likewise).
* Annex H floating-point encoding conversion functions. (It's not
entirely clear which are optional even given support for Annex H;
there's some wording applied inconsistently about only being
required when non-arithmetic interchange formats are supported; see
the comments I raised on the WG14 reflector on 23 Oct 2025.)
* _Float16 functions (and other header and testcase support for this
type).
* Decimal floating-point support.
* Fully supporting __int128 and unsigned __int128 as integer types
wider than intmax_t, as permitted by C23. Would need doing in
coordination with GCC, see GCC bug 113887 for more discussion of
what's involved.
The CORE-MATH commit 6736002f fixes some issues for RNDZ:
Failure: Test: acosh_towardzero (0x1.08000c1e79fp+0)
Result:
is: 2.4935636091994373e-01 0x1.feae8c399b18cp-3
should be: 2.4935636091994370e-01 0x1.feae8c399b18bp-3
difference: 2.7755575615628913e-17 0x1.0000000000000p-55
ulp : 1.0000
max.ulp : 0.0000
Failure: Test: acosh_towardzero (0x1.080016353964ep+0)
Result:
is: 2.4935874767710369e-01 0x1.feafcc91f518ep-3
should be: 2.4935874767710367e-01 0x1.feafcc91f518dp-3
difference: 2.7755575615628913e-17 0x1.0000000000000p-55
ulp : 1.0000
max.ulp : 0.0000
Maximal error of `acosh_towardzero'
is : 1 ulp
accepted: 0 ulp
This only happens when the ISA supports fma, such as x86_64-v3, aarch64,
or powerpc.
Checked on x86_64-linux-gnu, x86_64-linux-gnu-v3, aarch64-linux-gnu,
and i686-linux-gnu.
When we want to inline builtin math functions, like truncf, for
extern float truncf (float __x) __attribute__ ((__nothrow__ )) __attribute__ ((__const__));
extern float __truncf (float __x) __attribute__ ((__nothrow__ )) __attribute__ ((__const__));
float (truncf) (float) asm ("__truncf");
compiler may redirect truncf calls to __truncf, instead of inlining it
(for instance, clang). The USE_TRUNCF_BUILTIN is 1 to indicate that
truncf should be inlined. In this case, we don't want the truncf
redirection:
1. For each math function which may be inlined, we define
#if USE_TRUNCF_BUILTIN
# define NO_truncf_BUILTIN inline_truncf
#else
# define NO_truncf_BUILTIN truncf
#endif
in <math-use-builtins.h>.
2. Include <math-use-builtins.h> in include/math.h.
3. Change MATH_REDIRECT to
#define MATH_REDIRECT(FUNC, PREFIX, ARGS) \
float (NO_ ## FUNC ## f ## _BUILTIN) (ARGS (float)) \
asm (PREFIX #FUNC "f");
With this change If USE_TRUNCF_BUILTIN is 0, we get
float (truncf) (float) asm ("__truncf");
truncf will be redirected to __truncf.
And for USE_TRUNCF_BUILTIN 1, we get:
float (inline_truncf) (float) asm ("__truncf");
In both cases either truncf will be inlined or the internal alias
(__truncf) will be called.
It is not required for all math-use-builtin symbol, only the one
defined in math.h. It also allows to remove all the math-use-builtin
inclusion, since it is now implicitly included by math.h.
For MIPS, some math-use-builtin headers include sysdep.h and this
in turn includes a lot of extra headers that do not allow ldbl-128
code to override alias definition (math.h will include
some stdlib.h definition). The math-use-builtin only requires
the __mips_isa_rev, so move the defintion to sgidefs.h.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Co-authored-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
As discussed in bug 28327, C23 changed the fromfp functions to return
floating types instead of intmax_t / uintmax_t. (Although the
motivation in N2548 was reducing the use of intmax_t in library
interfaces, the new version does have the advantage of being able to
specify arbitrary integer widths for e.g. assigning the result to a
_BitInt, as well as being able to indicate an error case in-band with
a NaN return.)
As with other such changes from interfaces introduced in TS 18661,
implement the new types as a replacement for the old ones, with the
old functions remaining as compat symbols but not supported as an API.
The test generator used for many of the tests is updated to handle
both versions of the functions.
Tested for x86_64 and x86, and with build-many-glibcs.py.
Also tested tgmath tests for x86_64 with GCC 7 to make sure that the
modified case for older compilers in <tgmath.h> does work.
Also tested for powerpc64le to cover the ldbl-128ibm implementation
and the other things that are handled differently for that
configuration. The new tests fail for ibm128, but all the failures
relate to incorrect signs of zero results and turn out to arise from
bugs in the underlying roundl, ceill, truncl and floorl
implementations that I've reported in bug 33623, rather than
indicating any bug in the actual new implementation of the functions
for that format. So given fixes for those functions (which shouldn't
be hard, and of course should add to the tests for those functions
rather than relying only on indirect testing via fromfp), the fromfp
tests should start passing for ibm128 as well.
It improves latency for about 1.5% and throughput for about 2-4%.
Tested on x86_64-linux-gnu and i686-linux-gnu.
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>