1661 Commits
Author SHA1 Message Date
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
Adhemerval Zanella 70cc22b19c math: Update tanh from CORE-MATH (revision bb39e4fa)
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.
2026-08-25 14:36:35 -03:00
Adhemerval Zanella fdc90dbb52 math: Fix sinh worst-case results for |x| > 36.736801 [BZ 34441]
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.
2026-07-27 14:13:51 -03:00
Yury Khrustalev 3f3229739e math: test: Fix unsupported check in test-narrowing-trap
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2026-07-21 13:39:42 +01:00
Adhemerval Zanella 6b29e74c73 math: Update tanh from CORE-MATH (revision cf237fa0)
Sync the double-precision tanh implementation with CORE-MATH revision
cf237fa0.

Checked on aarch64-linux-gnu.
2026-07-18 09:36:58 -03:00
Adhemerval Zanella 5c47592adb math: Fix inaccurate sin/cos/tan for large arguments (BZ 34376)
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>
2026-07-17 13:52:58 +00:00
Adhemerval Zanella a767fbcff0 math: Sync acosh with CORE-MATH 887cab6f
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>
2026-06-15 17:41:15 +00:00
Adhemerval Zanella 808035fdff math: Fix non-narrowing test build with arg-format conditions
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.
2026-05-29 13:58:58 -03:00
Adhemerval Zanella 1e7935ae87 math: Fix fma alignment when exponent difference is exactly 64 (BZ 34183)
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>
2026-05-28 10:22:48 -03:00
Pierre Blanchard 2ff2565df7 AArch64: Implement AdvSIMD and SVE powr(f) routines
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.
2026-04-20 13:01:25 -03:00
Xi Ruoyao 7cc1f7683b testsuite: fix test-narrowing-trap failure on platforms where FE_INVALID is not defined
I didn't realize it can be undefined at all instead of simply
unsupported :(.

Signed-off-by: Xi Ruoyao <xry111@xry111.site>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
2026-03-30 14:56:09 -03:00
Xi Ruoyao 5274604915 LoongArch: fix missing trap for enabled exceptions on narrowing operation
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>
2026-03-25 09:15:18 +08:00
Adhemerval Zanella 19781c2221 math: Fix spurious overflow and missing errno for lgammaf
It syncs with CORE-MATH 9a75500ba1831 and 20d51f2ee.

Checked on aarch64-linux-gnu.
2026-03-20 17:47:41 +00:00
Adhemerval Zanella f05c4907a2 math: Consolidated common definition/data for cosh/sinh/tanh
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>
2026-03-16 13:52:20 -03:00
Adhemerval Zanella e658f35935 math: Use tanh from CORE-MATH
The current implementation precision shows the following accuracy, on
three ranges ([-DBL_MAX,-10], [-10,10], [10,DBL_MAX]) with 10e9 uniform
randomly generated numbers for each range (first column is the
accuracy in ULP, with '0' being correctly rounded, second is the
number of samples with the corresponding precision):

* Range [-DBL_MAX, -10]
 * FE_TONEAREST
     0:      10000000000 100.00%
 * FE_UPWARD
     0:      10000000000 100.00%
 * FE_DOWNWARD
     0:      10000000000 100.00%
 * FE_TOWARDZERO
     0:      10000000000 100.00%

* Range [-10, -10]
 * FE_TONEAREST
     0:       4059325526  94.51%
     1:        231023238   5.38%
     2:          4618531   0.11%
 * FE_UPWARD
     0:       2106654900  49.05%
     1:       2145413180  49.95%
     2:         40847554   0.95%
     3:          2051661   0.05%
 * FE_DOWNWARD
     0:       2106618401  49.05%
     1:       2145409958  49.95%
     2:         40880992   0.95%
     3:          2057944   0.05%
 * FE_TOWARDZERO
     0:       4061659952  94.57%
     1:        221006985   5.15%
     2:         12285512   0.29%
     3:            14846   0.00%

* Range [10, DBL_MAX]
 * FE_TONEAREST
     0:      10000000000 100.00%
 * FE_UPWARD
     0:      10000000000 100.00%
 * FE_DOWNWARD
     0:      10000000000 100.00%
 * FE_TOWARDZERO
     0:      10000000000 100.00%

The CORE-MATH implementation is correctly rounded for any rounding mode.
The code was adapted to glibc style and to use the definition of
math_config.h (to handle errno, overflow, and underflow).

Performance-wise, it shows:

latency                      master        patched        improvement
x86_64                     109.7420       184.5950            -68.21%
x86_64v2                   109.1230       187.1890            -71.54%
x86_64v3                    99.4471        49.1104             50.62%
aarch64                     43.0474        32.2933             24.98%
armhf-vpfv4                 41.0954        35.8473             12.77%
powerpc64le                 27.3282        22.7134             16.89%

reciprocal-throughput        master        patched        improvement
x86_64                      42.5562       158.1820           -271.70%
x86_64v2                    42.5734       159.2560           -274.07%
x86_64v3                    35.9899        24.2877             32.52%
aarch64                     24.7660        22.8466              7.75%
armhf-vpfv4                 27.0251        25.8150              4.48%
powerpc64le                 11.7350        11.2504              4.13%

* x86_64:        gcc version 15.2.1 20260112, Ryzen 9 5900X, --disable-multi-arch
* aarch64:       gcc version 15.2.1 20251105, Neoverse-N1
* armv7a-vpfv4:  gcc version 15.2.1 20251105, Neoverse-N1
* powerpc64le:   gcc version 15.2.1 20260128, POWER10

Checked on x86_64-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.

Reviewed-by: DJ Delorie <dj@redhat.com>
2026-03-16 13:51:58 -03:00
Adhemerval Zanella a702a425d0 math: Remove the SVID error handling from sinh
It improves throughput from 8 to 18% and latency from 1 to 10%,
dependending of the ABI.

Reviewed-by: DJ Delorie <dj@redhat.com>
2026-03-16 13:51:58 -03:00
Adhemerval Zanella 106f8c2ed6 math: Use sinh from CORE-MATH
The current implementation precision shows the following accuracy, on
three ranges ([-DBL_MAX,-10], [-10,10], [10,DBL_MAX]) with 10e9 uniform
randomly generated numbers for each range (first column is the
accuracy in ULP, with '0' being correctly rounded, second is the
number of samples with the corresponding precision):

* Range [-DBL_MAX, -10]
 * FE_TONEAREST
     0:      10000000000 100.00%
 * FE_UPWARD
     0:      10000000000 100.00%
 * FE_DOWNWARD
     0:      10000000000 100.00%
 * FE_TOWARDZERO
     0:      10000000000 100.00%

* Range [-10, -10]
 * FE_TONEAREST
     0:       3169388892  73.79%
     1:       1125270674  26.20%
     2:           307729   0.01%
 * FE_UPWARD
     0:       1450068660  33.76%
     1:       2146926394  49.99%
     2:        697404986  16.24%
     3:           567255   0.01%
 * FE_DOWNWARD
     0:       1449727976  33.75%
     1:       2146957381  49.99%
     2:        697719649  16.25%
     3:           562289   0.01%
 * FE_TOWARDZERO
     0:       2519351889  58.66%
     1:       1773434502  41.29%
     2:          2180904   0.05%

* Range [10, DBL_MAX]
 * FE_TONEAREST
     0:      10000000000 100.00%
 * FE_UPWARD
     0:      10000000000 100.00%
 * FE_DOWNWARD
     0:      10000000000 100.00%
 * FE_TOWARDZERO
     0:      10000000000 100.00%

The CORE-MATH implementation is correctly rounded for any rounding mode.
The code was adapted to glibc style and to use the definition of
math_config.h (to handle errno, overflow, and underflow).

Performance-wise, it shows:

latency                      master        patched        improvement
x86_64                     101.0710       129.4710            -28.10%
x86_64v2                   101.1810       127.6370            -26.15%
x86_64v3                    96.0685        48.5911             49.42%
aarch64                     41.4229        22.3971             45.93%
armhf-vpfv4                 42.8620        25.6011             40.27%
powerpc64le                 29.2630        13.1450             55.08%

reciprocal-throughput        master        patched        improvement
x86_64                      42.6895       105.7150           -147.64%
x86_64v2                    42.7255       104.7480           -145.17%
x86_64v3                    39.6949        25.9087             34.73%
aarch64                     26.0104        19.2236             26.09%
armhf-vpfv4                 29.4362        23.6350             19.71%
powerpc64le                 12.9170        8.34582             35.39%

* x86_64:        gcc version 15.2.1 20260112, Ryzen 9 5900X, --disable-multi-arch
* aarch64:       gcc version 15.2.1 20251105, Neoverse-N1
* armv7a-vpfv4:  gcc version 15.2.1 20251105, Neoverse-N1
* powerpc64le:   gcc version 15.2.1 20260128, POWER10

Checked on x86_64-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.

Reviewed-by: DJ Delorie <dj@redhat.com>
2026-03-16 13:51:57 -03:00
Adhemerval Zanella 514129fad2 math: Remove the SVID error handling from cosh
It improves throughout from 3.5% to 9%.

Reviewed-by: DJ Delorie <dj@redhat.com>
2026-03-16 09:34:28 -03:00
Adhemerval Zanella 291fc87155 math: Use cosh from CORE-MATH
The current implementation precision shows the following accuracy, on
three ranges ([-DBL_MAX,-10], [-10,10], [10,DBL_MAX]) with 10e9 uniform
randomly generated numbers for each range (first column is the
accuracy in ULP, with '0' being correctly rounded, second is the
number of samples with the corresponding precision):

* Range [-DBL_MAX, -10]
 * FE_TONEAREST
     0:      10000000000 100.00%
 * FE_UPWARD
     0:      10000000000 100.00%
 * FE_DOWNWARD
     0:      10000000000 100.00%
 * FE_TOWARDZERO
     0:      10000000000 100.00%

* Range [-10, -10]
 * FE_TONEAREST
     0:       3291614060  76.64%
     1:       1003353235  23.36%
 * FE_UPWARD
     0:       2295272497  53.44%
     1:       1999675198  46.56%
     2:            19600   0.00%
 * FE_DOWNWARD
     0:       2294966533  53.43%
     1:       1999981461  46.57%
     2:            19301   0.00%
 * FE_TOWARDZERO
     0:       2306015780  53.69%
     1:       1988942093  46.31%
     2:             9422   0.00%

* Range [10, DBL_MAX]
 * FE_TONEAREST
     0:      10000000000 100.00%
 * FE_UPWARD
     0:      10000000000 100.00%
 * FE_DOWNWARD
     0:      10000000000 100.00%
 * FE_TOWARDZERO
     0:      10000000000 100.00%

The CORE-MATH implementation is correctly rounded for any rounding mode.
The code was adapted to glibc style and to use the definition of
math_config.h (to handle errno, overflow, and underflow).

Performance-wise, it shows:

latency                      master        patched     improvement
x86_64                      52.1066       126.4120        -142.60%
x86_64v2                    49.5781       119.8520        -141.74%
x86_64v3                    45.0811        50.5758         -12.19%
aarch64                     19.9977        21.7814          -8.92%
armhf-vpfv4                 20.5969        27.0479         -31.32%
powerpc64le                 12.6405        13.6768          -8.20%

reciprocal-throughput        master        patched     improvement
x86_64                      18.4833        102.9120       -456.78%
x86_64v2                    17.5409        99.5179        -467.35%
x86_64v3                    18.9187        25.3662         -34.08%
aarch64                     10.9045        18.8217         -72.60%
armhf-vpfv4                 15.7430        24.0822         -52.97%
powerpc64le                  5.4275         8.1269         -49.73%

* x86_64:        gcc version 15.2.1 20260112, Ryzen 9 5900X, --disable-multi-arch
* aarch64:       gcc version 15.2.1 20251105, Neoverse-N1
* armv7a-vpfv4:  gcc version 15.2.1 20251105, Neoverse-N1
* powerpc64le:   gcc version 15.2.1 20260128, POWER10

Checked on x86_64-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.

Reviewed-by: DJ Delorie <dj@redhat.com>
2026-03-16 09:34:23 -03:00
Adhemerval Zanella 236171bb87 math: Sync log2p1f with CORE-MATH
The new code shows better performance overall:

latency                      patched        sync   improvement
x86_64                       48.5909     33.3368        31.39%
x86_64v2                     49.1357     33.9981        30.81%
x86_64v3                     39.2397     28.0957        28.40%
aarch64                      16.5372     12.8133        22.52%
armhf-vpfv4                  18.1434     14.5273        19.93%
powerpc64le                   9.0999     7.49235        17.67%

reciprocal-throughput        patched        sync   improvement
x86_64                       14.5197     10.9726        24.43%
x86_64v2                     14.7640     11.1358        24.57%
x86_64v3                     11.5523     9.83253        14.89%
aarch64                       8.2854      7.8479         5.28%
armhf-vpfv4                   8.8586      8.5245         3.77%
powerpc64le                   3.8995      4.0069        -2.75%

x86_64 / i686      gcc version 15.2.1 20260112. Ryzen 5900X
aarch64:           gcc version 15.2.1 20251105, Neoverse-N1
armv7a-vpfv4:      gcc version 15.2.1 20251105, Neoverse-N1
powerpc64le:       gcc version 14.2.1 20241230, POWER10

The sync also improves the internal table size, the s_log1pf.os
'size' output shows:

size                         master        sync   improvement
x86_64                         3417        2089        38.86%
x86_64v2                       3417        2089        38.86%
x86_64v3                       3228        2001        38.01%
i686                           3490        2151        38.37%
aarch64                        3200        1888        41.00%
armhf-vpfv4                    3080        1804        41.43%
powerpc64le                    3408        2148        36.97%

Checked on aarch64-linux-gnu, arm-linux-gnueabihf,
powerpc64le-linux-gnu, i686-linux-gnu, and x86_64-linux-gnu.

Reviewed-by: Paul Zimmermann <Paul.Zimmermann@inria.fr>
2026-03-02 10:10:05 -03:00
Adhemerval Zanella 3069c7951d math: Sync log1pf with CORE-MATH
The performance is similar, with some minor regression:

latency                      master        sync   improvement
x86_64                      38.2841     38.1375         0.38%
x86_64v2                    37.7338     37.4292         0.81%
x86_64v3                    31.3500     32.3576        -3.21%
aarch64                     13.7384     13.9030        -1.20%
armhf-vpfv4                 15.5730     16.5105        -6.02%
powerpc64le                  7.6038      7.5757         0.37%

reciprocal-throughput        master        sync   improvement
x86_64                      12.4910     11.9683         4.18%
x86_64v2                    12.2935     11.7614         4.33%
x86_64v3                    11.5444     10.6369         7.86%
aarch64                      7.7262      7.8954        -2.19%
armhf-vpfv4                  8.3502      8.8741        -6.27%
powerpc64le                  3.5883      3.5259         1.74%

x86_64 / i686      gcc version 15.2.1 20260112. Ryzen 5900X
aarch64:           gcc version 15.2.1 20251105, Neoverse-N1
armv7a-vpfv4:      gcc version 15.2.1 20251105, Neoverse-N1
powerpc64le:       gcc version 14.2.1 20241230, POWER10

The sync also improves the internal table size, the s_log1pf.os
'size' output shows:

size                         master       sync    improvement
x86_64                         2078       1641         21.03%
x86_64v2                       2078       1641         21.03%
x86_64v3                       1975       1514         23.34%
aarch64                        1808       1336         26.11%
armhf-vpfv4                    1716       1284         25.17%
powerpc64le                    2132       1616         24.20%

Checked on aarch64-linux-gnu, arm-linux-gnueabihf,
powerpc64le-linux-gnu, i686-linux-gnu, and x86_64-linux-gnu.

Reviewed-by: Paul Zimmermann <Paul.Zimmermann@inria.fr>
2026-03-02 10:08:38 -03:00
Adhemerval Zanella 1405c0fe2d math: Optimize f{max,min}imum_mag_num{f,l,f128}
Simplify order signal comparison and reorganize check to reduce
branches and allow targets to use conditional select/move.

With gcc-15 on aarch64 for fmaximum_mag_num:

* master:

0000000000000000 <__fmaximum_mag_num>:
   0:   d503245f        bti     c
   4:   1e60c004        fabs    d4, d0
   8:   1e60c023        fabs    d3, d1
   c:   1e632080        fcmp    d4, d3
  10:   5400008d        b.le    20 <__fmaximum_mag_num+0x20>
  14:   1e60401f        fmov    d31, d0
  18:   1e6043e0        fmov    d0, d31
  1c:   d65f03c0        ret
  20:   54000085        b.pl    30 <__fmaximum_mag_num+0x30>  // b.nfrst
  24:   1e60403f        fmov    d31, d1
  28:   1e6043e0        fmov    d0, d31
  2c:   d65f03c0        ret
  30:   54000161        b.ne    5c <__fmaximum_mag_num+0x5c>  // b.any
  34:   4f000402        movi    v2.4s, #0x0
  38:   1e6e101d        fmov    d29, #1.000000000000000000e+00
  3c:   6ee0f842        fneg    v2.2d, v2.2d
  40:   4ea21c5e        mov     v30.16b, v2.16b
  44:   2e7d1c22        bsl     v2.8b, v1.8b, v29.8b
  48:   2e7d1c1e        bsl     v30.8b, v0.8b, v29.8b
  4c:   1e6223d0        fcmpe   d30, d2
  50:   1e61ac1f        fcsel   d31, d0, d1, ge // ge = tcont
  54:   1e6043e0        fmov    d0, d31
  58:   d65f03c0        ret
  5c:   1e612020        fcmp    d1, d1
  60:   1e60403f        fmov    d31, d1
  64:   54ffff87        b.vc    54 <__fmaximum_mag_num+0x54>
  68:   1e602000        fcmp    d0, d0
  6c:   1e60401f        fmov    d31, d0
  70:   54ffff27        b.vc    54 <__fmaximum_mag_num+0x54>
  74:   1e61281f        fadd    d31, d0, d1
  78:   17fffff7        b       54 <__fmaximum_mag_num+0x54>

* patch:

0000000000000000 <__fminimum_mag_num>:
   0:   d503245f        bti     c
   4:   1e612000        fcmp    d0, d1
   8:   1e60401f        fmov    d31, d0
   c:   540000e6        b.vs    28 <__fminimum_mag_num+0x28>
  10:   1e60c01e        fabs    d30, d0
  14:   1e60c03d        fabs    d29, d1
  18:   1e7d23c0        fcmp    d30, d29
  1c:   54000160        b.eq    48 <__fminimum_mag_num+0x48>  // b.none
  20:   1e605c20        fcsel   d0, d1, d0, pl  // pl = nfrst
  24:   d65f03c0        ret
  28:   1e612020        fcmp    d1, d1
  2c:   1e604020        fmov    d0, d1
  30:   54ffffa7        b.vc    24 <__fminimum_mag_num+0x24>
  34:   1e7f23e0        fcmp    d31, d31
  38:   1e6043e0        fmov    d0, d31
  3c:   54ffff47        b.vc    24 <__fminimum_mag_num+0x24>
  40:   1e612be0        fadd    d0, d31, d1
  44:   d65f03c0        ret
  48:   9e660000        fmov    x0, d0
  4c:   f100001f        cmp     x0, #0x0
  50:   1e61bc00        fcsel   d0, d0, d1, lt  // lt = tstop
  54:   d65f03c0        ret

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>
2026-02-02 14:36:29 -03:00
Adhemerval Zanella 8a7675663e math: Optimize f{max,min}imum_mag{f,l,f128}
Simplify order signal comparison and reorganize check to reduce
branches and allow targets to use conditional select/move.

With gcc-15 on aarch64 for fmaximum_mag:

* master:

0000000000000000 <__fmaximum_mag>:
   0:   d503245f        bti     c
   4:   1e60c004        fabs    d4, d0
   8:   1e60c023        fabs    d3, d1
   c:   1e632080        fcmp    d4, d3
  10:   5400008d        b.le    20 <__fmaximum_mag+0x20>
  14:   1e60401f        fmov    d31, d0
  18:   1e6043e0        fmov    d0, d31
  1c:   d65f03c0        ret
  20:   54000085        b.pl    30 <__fmaximum_mag+0x30>  // b.nfrst
  24:   1e60403f        fmov    d31, d1
  28:   1e6043e0        fmov    d0, d31
  2c:   d65f03c0        ret
  30:   54000161        b.ne    5c <__fmaximum_mag+0x5c>  // b.any
  34:   4f000402        movi    v2.4s, #0x0
  38:   1e6e101d        fmov    d29, #1.000000000000000000e+00
  3c:   6ee0f842        fneg    v2.2d, v2.2d
  40:   4ea21c5e        mov     v30.16b, v2.16b
  44:   2e7d1c22        bsl     v2.8b, v1.8b, v29.8b
  48:   2e7d1c1e        bsl     v30.8b, v0.8b, v29.8b
  4c:   1e6223d0        fcmpe   d30, d2
  50:   1e61ac1f        fcsel   d31, d0, d1, ge // ge = tcont
  54:   1e6043e0        fmov    d0, d31
  58:   d65f03c0        ret
  5c:   1e61281f        fadd    d31, d0, d1
  60:   1e6043e0        fmov    d0, d31
  64:   d65f03c0        ret

* patch:

0000000000000000 <__fmaximum_mag>:
   0:   d503245f        bti     c
   4:   1e612000        fcmp    d0, d1
   8:   540000e6        b.vs    24 <__fmaximum_mag+0x24>
   c:   1e60c01f        fabs    d31, d0
  10:   1e60c03e        fabs    d30, d1
  14:   1e7e23e0        fcmp    d31, d30
  18:   540000a0        b.eq    2c <__fmaximum_mag+0x2c>  // b.none
  1c:   1e60dc20        fcsel   d0, d1, d0, le
  20:   d65f03c0        ret
  24:   1e612800        fadd    d0, d0, d1
  28:   d65f03c0        ret
  2c:   9e660000        fmov    x0, d0
  30:   f100001f        cmp     x0, #0x0
  34:   1e60bc20        fcsel   d0, d1, d0, lt  // lt = tstop
  38:   d65f03c0        ret

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>
2026-02-02 14:36:24 -03:00
Adhemerval Zanella c3ced14f88 math: Optimize f{max,min}imum_num{f,l,f,f128}
Add an isunordered check for fast-path and simplified sign check
and use the fmax/fmin when possible.

With gcc-15 on aarch64 for fmaximum_num:

* master

0000000000000000 <__fmaximum_num>:
   0:   d503245f        bti     c
   4:   1e612000        fcmp    d0, d1
   8:   5400008d        b.le    18 <__fmaximum_num+0x18>
   c:   1e60401f        fmov    d31, d0
  10:   1e6043e0        fmov    d0, d31
  14:   d65f03c0        ret
  18:   54000085        b.pl    28 <__fmaximum_num+0x28>  // b.nfrst
  1c:   1e60403f        fmov    d31, d1
  20:   1e6043e0        fmov    d0, d31
  24:   d65f03c0        ret
  28:   54000161        b.ne    54 <__fmaximum_num+0x54>  // b.any
  2c:   4f000402        movi    v2.4s, #0x0
  30:   1e6e101e        fmov    d30, #1.000000000000000000e+00
  34:   6ee0f842        fneg    v2.2d, v2.2d
  38:   4ea21c5d        mov     v29.16b, v2.16b
  3c:   2e7e1c22        bsl     v2.8b, v1.8b, v30.8b
  40:   2e7e1c1d        bsl     v29.8b, v0.8b, v30.8b
  44:   1e6223b0        fcmpe   d29, d2
  48:   1e61ac1f        fcsel   d31, d0, d1, ge // ge = tcont
  4c:   1e6043e0        fmov    d0, d31
  50:   d65f03c0        ret
  54:   1e612020        fcmp    d1, d1
  58:   1e60403f        fmov    d31, d1
  5c:   54ffff87        b.vc    4c <__fmaximum_num+0x4c>
  60:   1e602000        fcmp    d0, d0
  64:   1e60401f        fmov    d31, d0
  68:   54ffff27        b.vc    4c <__fmaximum_num+0x4c>
  6c:   1e61281f        fadd    d31, d0, d1
  70:   17fffff7        b       4c <__fmaximum_num+0x4c>

* patch:

0000000000000000 <__fmaximum_num>:
   0:   d503245f        bti     c
   4:   1e612000        fcmp    d0, d1
   8:   54000086        b.vs    18 <__fmaximum_num+0x18>
   c:   1e61681f        fmaxnm  d31, d0, d1
  10:   1e6043e0        fmov    d0, d31
  14:   d65f03c0        ret
  18:   1e612020        fcmp    d1, d1
  1c:   1e60403f        fmov    d31, d1
  20:   54ffff87        b.vc    10 <__fmaximum_num+0x10>
  24:   1e602000        fcmp    d0, d0
  28:   1e60401f        fmov    d31, d0
  2c:   54ffff27        b.vc    10 <__fmaximum_num+0x10>
  30:   1e61281f        fadd    d31, d0, d1
  34:   17fffff7        b       10 <__fmaximum_num+0x10>

And with gcc-15 on x86_64:

* master:

0000000000000000 <__fmaximum_num>:
   0:   66 0f 2e c1             ucomisd %xmm1,%xmm0
   4:   66 0f 28 d8             movapd %xmm0,%xmm3
   8:   77 5e                   ja     68 <__fmaximum_num+0x68>
   a:   66 0f 2e c8             ucomisd %xmm0,%xmm1
   e:   77 50                   ja     60 <__fmaximum_num+0x60>
  10:   66 0f 2e c1             ucomisd %xmm1,%xmm0
  14:   7a 5a                   jp     70 <__fmaximum_num+0x70>
  16:   75 58                   jne    70 <__fmaximum_num+0x70>
  18:   f3 0f 7e 05 00 00 00    movq   0x0(%rip),%xmm0        # 20 <__fmaximum_num+0x20>
  1f:   00
  20:   f2 0f 10 15 00 00 00    movsd  0x0(%rip),%xmm2        # 28 <__fmaximum_num+0x28>
  27:   00
  28:   66 0f 28 e0             movapd %xmm0,%xmm4
  2c:   66 0f 54 15 00 00 00    andpd  0x0(%rip),%xmm2        # 34 <__fmaximum_num+0x34>
  33:   00
  34:   66 0f 54 c1             andpd  %xmm1,%xmm0
  38:   66 0f 54 e3             andpd  %xmm3,%xmm4
  3c:   66 0f 56 e2             orpd   %xmm2,%xmm4
  40:   66 0f 56 d0             orpd   %xmm0,%xmm2
  44:   f2 0f c2 d4 02          cmplesd %xmm4,%xmm2
  49:   66 0f 54 da             andpd  %xmm2,%xmm3
  4d:   66 0f 55 d1             andnpd %xmm1,%xmm2
  51:   66 0f 56 d3             orpd   %xmm3,%xmm2
  55:   66 0f 28 c2             movapd %xmm2,%xmm0
  59:   c3                      ret
  5a:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
  60:   66 0f 28 c1             movapd %xmm1,%xmm0
  64:   c3                      ret
  65:   0f 1f 00                nopl   (%rax)
  68:   c3                      ret
  69:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)
  70:   66 0f 2e c9             ucomisd %xmm1,%xmm1
  74:   66 0f 28 c1             movapd %xmm1,%xmm0
  78:   7b ea                   jnp    64 <__fmaximum_num+0x64>
  7a:   66 0f 2e db             ucomisd %xmm3,%xmm3
  7e:   66 0f 28 c3             movapd %xmm3,%xmm0
  82:   7b e0                   jnp    64 <__fmaximum_num+0x64>
  84:   f2 0f 58 c1             addsd  %xmm1,%xmm0
  88:   c3                      ret

* patch:

0000000000000000 <__fmaximum_num>:
   0:   66 0f 2e c1             ucomisd %xmm1,%xmm0
   4:   7a 2a                   jp     30 <__fmaximum_num+0x30>
   6:   77 18                   ja     20 <__fmaximum_num+0x20>
   8:   66 0f 2e c8             ucomisd %xmm0,%xmm1
   c:   77 08                   ja     16 <__fmaximum_num+0x16>
   e:   66 0f 50 c0             movmskpd %xmm0,%eax
  12:   a8 01                   test   $0x1,%al
  14:   74 0a                   je     20 <__fmaximum_num+0x20>
  16:   66 0f 28 c1             movapd %xmm1,%xmm0
  1a:   c3                      ret
  1b:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
  20:   66 0f 28 c8             movapd %xmm0,%xmm1
  24:   66 0f 28 c1             movapd %xmm1,%xmm0
  28:   c3                      ret
  29:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)
  30:   66 0f 2e c9             ucomisd %xmm1,%xmm1
  34:   7b e0                   jnp    16 <__fmaximum_num+0x16>
  36:   66 0f 2e c0             ucomisd %xmm0,%xmm0
  3a:   7b e4                   jnp    20 <__fmaximum_num+0x20>
  3c:   f2 0f 58 c8             addsd  %xmm0,%xmm1
  40:   eb d4                   jmp    16 <__fmaximum_num+0x16>

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>
2026-02-02 14:36:11 -03:00
Adhemerval Zanella a95db490b5 math: Optimize f{max,min}imum{f,l,f128}
Add an isunordered check for fast-path and simplified sign check
and use the fmax/fmin when possible.

With gcc-15 on aarch64:

* master:

0000000000000000 <__fmaximum>:
   0:   d503245f        bti     c
   4:   1e612000        fcmp    d0, d1
   8:   5400008d        b.le    18 <__fmaximum+0x18>
   c:   1e60401f        fmov    d31, d0
  10:   1e6043e0        fmov    d0, d31
  14:   d65f03c0        ret
  18:   54000085        b.pl    28 <__fmaximum+0x28>  // b.nfrst
  1c:   1e60403f        fmov    d31, d1
  20:   1e6043e0        fmov    d0, d31
  24:   d65f03c0        ret
  28:   54000161        b.ne    54 <__fmaximum+0x54>  // b.any
  2c:   4f000402        movi    v2.4s, #0x0
  30:   1e6e101e        fmov    d30, #1.000000000000000000e+00
  34:   6ee0f842        fneg    v2.2d, v2.2d
  38:   4ea21c5d        mov     v29.16b, v2.16b
  3c:   2e7e1c22        bsl     v2.8b, v1.8b, v30.8b
  40:   2e7e1c1d        bsl     v29.8b, v0.8b, v30.8b
  44:   1e6223b0        fcmpe   d29, d2
  48:   1e61ac1f        fcsel   d31, d0, d1, ge // ge = tcont
  4c:   1e6043e0        fmov    d0, d31
  50:   d65f03c0        ret
  54:   1e61281f        fadd    d31, d0, d1
  58:   1e6043e0        fmov    d0, d31
  5c:   d65f03c0        ret

* patch:

0000000000000000 <__fmaximum>:
   0:   d503245f        bti     c
   4:   1e612000        fcmp    d0, d1
   8:   54000086        b.vs    18 <__fmaximum+0x18>
   c:   1e61681f        fmaxnm  d31, d0, d1
  10:   1e6043e0        fmov    d0, d31
  14:   d65f03c0        ret
  18:   1e61281f        fadd    d31, d0, d1
  1c:   1e6043e0        fmov    d0, d31
  20:   d65f03c0        ret

And with gcc-15 on x86_64:

* master:

0000000000000000 <__fmaximum>:
   0:   66 0f 2e c1             ucomisd %xmm1,%xmm0
   4:   77 56                   ja     5c <__fmaximum+0x5c>
   6:   66 0f 2e c8             ucomisd %xmm0,%xmm1
   a:   77 4c                   ja     58 <__fmaximum+0x58>
   c:   66 0f 2e c1             ucomisd %xmm1,%xmm0
  10:   7a 4e                   jp     60 <__fmaximum+0x60>
  12:   75 4c                   jne    60 <__fmaximum+0x60>
  14:   f3 0f 7e 1d 00 00 00    movq   0x0(%rip),%xmm3        # 1c <__fmaximum+0x1c>
  1b:   00
  1c:   f2 0f 10 15 00 00 00    movsd  0x0(%rip),%xmm2        # 24 <__fmaximum+0x24>
  23:   00
  24:   66 0f 28 e3             movapd %xmm3,%xmm4
  28:   66 0f 54 15 00 00 00    andpd  0x0(%rip),%xmm2        # 30 <__fmaximum+0x30>
  2f:   00
  30:   66 0f 54 e0             andpd  %xmm0,%xmm4
  34:   66 0f 54 d9             andpd  %xmm1,%xmm3
  38:   66 0f 56 e2             orpd   %xmm2,%xmm4
  3c:   66 0f 56 d3             orpd   %xmm3,%xmm2
  40:   f2 0f c2 d4 02          cmplesd %xmm4,%xmm2
  45:   66 0f 54 c2             andpd  %xmm2,%xmm0
  49:   66 0f 55 d1             andnpd %xmm1,%xmm2
  4d:   66 0f 56 c2             orpd   %xmm2,%xmm0
  51:   c3                      ret
  52:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
  58:   66 0f 28 c1             movapd %xmm1,%xmm0
  5c:   c3                      ret
  5d:   0f 1f 00                nopl   (%rax)
  60:   f2 0f 58 c1             addsd  %xmm1,%xmm0
  64:   c3                      ret

* patched:

0000000000000000 <__fmaximum>:
   0:   66 0f 2e c1             ucomisd %xmm1,%xmm0
   4:   7a 2a                   jp     30 <__fmaximum+0x30>
   6:   77 18                   ja     20 <__fmaximum+0x20>
   8:   66 0f 2e c8             ucomisd %xmm0,%xmm1
   c:   77 08                   ja     16 <__fmaximum+0x16>
   e:   66 0f 50 c0             movmskpd %xmm0,%eax
  12:   a8 01                   test   $0x1,%al
  14:   74 0a                   je     20 <__fmaximum+0x20>
  16:   66 0f 28 c1             movapd %xmm1,%xmm0
  1a:   c3                      ret
  1b:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
  20:   66 0f 28 c8             movapd %xmm0,%xmm1
  24:   66 0f 28 c1             movapd %xmm1,%xmm0
  28:   c3                      ret
  29:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)
  30:   f2 0f 58 c8             addsd  %xmm0,%xmm1
  34:   66 0f 28 c1             movapd %xmm1,%xmm0
  38:   c3                      ret

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>
2026-02-02 14:35:51 -03:00
Adhemerval Zanella 822bb11278 math: Order signed zeros in f{max,min}mag{f,l,f128}
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>
2026-02-02 14:35:44 -03:00
Adhemerval ZanellaandJames Y Knight bdb07a03fb math: Order signed zeros in f{max,min}{f,l,f128}
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>
2026-02-02 14:35:19 -03:00
Adhemerval Zanella 6bbe7ae5f3 math: Simplify f{max,min}mag template
On aarch64 with gcc-15 it optimizes the fast-path slightly, for fmaxmag:

* master

0000000000000000 <__fmaxmag>:
   0:   d503245f        bti     c
   4:   1e60c01e        fabs    d30, d0
   8:   1e60c03f        fabs    d31, d1
   c:   1e7f23c0        fcmp    d30, d31
  10:   5400004d        b.le    18 <__fmaxmag+0x18>
  14:   d65f03c0        ret
  18:   54000065        b.pl    24 <__fmaxmag+0x24>  // b.nfrst
  1c:   1e604020        fmov    d0, d1
  20:   d65f03c0        ret
  24:   540001e0        b.eq    60 <__fmaxmag+0x60>  // b.none
  [...]
  60:   1e612010        fcmpe   d0, d1
  64:   1e61cc00        fcsel   d0, d0, d1, gt
  68:   d65f03c0        ret

* patch:

0000000000000000 <__fmaxmag>:
   0:   d503245f        bti     c
   4:   1e612000        fcmp    d0, d1
   8:   540000e6        b.vs    24 <__fmaxmag+0x24>
   c:   1e60c01f        fabs    d31, d0
  10:   1e60c03e        fabs    d30, d1
  14:   1e7e23e0        fcmp    d31, d30
  18:   540001c0        b.eq    50 <__fmaxmag+0x50>  // b.none
  1c:   1e60dc20        fcsel   d0, d1, d0, le
  20:   d65f03c0        ret
  [...]
  50:   1e612010        fcmpe   d0, d1
  54:   1e61cc00        fcsel   d0, d0, d1, gt
  58:   d65f03c0        ret
  [...]

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>
2026-02-02 14:34:33 -03:00
Adhemerval Zanella 92ff5e9d91 math: Simplify f{max,min} template
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>
2026-02-02 14:34:29 -03:00
Aurelien Jarno 6f4b28b20a Fix ldbl-128ibm ceill, floorl, roundl and truncl zero-sign handling
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>
2026-01-24 11:38:10 +01:00
Adhemerval Zanella ae62786747 Revert "x86: Do not use __builtin_fpclassify for _Float64x/long double"
This reverts commit 5011210399. It
breaks libstdc++ and other languages bootstrap.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2026-01-14 14:33:20 -03:00
Adhemerval Zanella 9e822788e5 Revert "x86: Do not use __builtin_isinf_sign for _Float64x/long double"
This reverts commit 999cd617cb.  It
breaks libstdc++ and other languages bootstrap.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
2026-01-14 14:33:16 -03:00
Adhemerval Zanella 8efe2b03db math: Sync acosh from CORE-MATH
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>
2026-01-12 10:34:38 -03:00
Adhemerval Zanella 05b46df987 math: Sync atanh from CORE-MATH
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>
2026-01-12 10:34:35 -03:00
Adhemerval Zanella eafea63c11 math: Sync asinh from CORE-MATH
The CORE-MATH commit cd653cf7 fixes some issues for RNDZ (below).

testing double (without inline functions)
Failure: Test: asinh_towardzero (0x1.07888cc76eb3cp-4)
Result:
 is:          6.4294901954893124e-02   0x1.075a175321f74p-4
 should be:   6.4294901954893110e-02   0x1.075a175321f73p-4
 difference:  1.3877787807814456e-17   0x1.0000000000000p-56
 ulp       :  1.0000
 max.ulp   :  0.0000
Failure: Test: asinh_towardzero (0x1.07888e17d0fep-4)
Result:
 is:          6.4294906839823556e-02   0x1.075a18a2d2922p-4
 should be:   6.4294906839823542e-02   0x1.075a18a2d2921p-4
 difference:  1.3877787807814456e-17   0x1.0000000000000p-56
 ulp       :  1.0000
 max.ulp   :  0.0000
Failure: Test: asinh_towardzero (0x1.07888e344d64ep-4)
Result:
 is:          6.4294907253493294e-02   0x1.075a18bf3fed0p-4
 should be:   6.4294907253493280e-02   0x1.075a18bf3fecfp-4
 difference:  1.3877787807814456e-17   0x1.0000000000000p-56
 ulp       :  1.0000
 max.ulp   :  0.0000
Failure: Test: asinh_towardzero (0x1.07888e45219adp-4)
Result:
 is:          6.4294907497881415e-02   0x1.075a18d00b3f4p-4
 should be:   6.4294907497881401e-02   0x1.075a18d00b3f3p-4
 difference:  1.3877787807814456e-17   0x1.0000000000000p-56
 ulp       :  1.0000
 max.ulp   :  0.0000
Failure: Test: asinh_towardzero (0x1.0788946685afp-4)
Result:
 is:          6.4294930288402857e-02   0x1.075a1eee32572p-4
 should be:   6.4294930288402843e-02   0x1.075a1eee32571p-4
 difference:  1.3877787807814456e-17   0x1.0000000000000p-56
 ulp       :  1.0000
 max.ulp   :  0.0000
Failure: Test: asinh_towardzero (0x1.07889a0cffe1fp-4)
Result:
 is:          6.4294951293986671e-02   0x1.075a2491b07a9p-4
 should be:   6.4294951293986657e-02   0x1.075a2491b07a8p-4
 difference:  1.3877787807814456e-17   0x1.0000000000000p-56
 ulp       :  1.0000
 max.ulp   :  0.0000
Failure: Test: asinh_towardzero (0x1.07889cddeccf9p-4)
Result:
 is:          6.4294961763186983e-02   0x1.075a276120993p-4
 should be:   6.4294961763186969e-02   0x1.075a276120992p-4
 difference:  1.3877787807814456e-17   0x1.0000000000000p-56
 ulp       :  1.0000
 max.ulp   :  0.0000
Failure: Test: asinh_towardzero (0x1.07889efd3a82bp-4)
Result:
 is:          6.4294969652980468e-02   0x1.075a297f4f503p-4
 should be:   6.4294969652980454e-02   0x1.075a297f4f502p-4
 difference:  1.3877787807814456e-17   0x1.0000000000000p-56
 ulp       :  1.0000
 max.ulp   :  0.0000
Maximal error of `asinh_towardzero'
 is      : 1 ulp
 accepted: 0 ulp

The muldd was renamed to muldd_acc to avoid deviate from CORE-MATH
(the symbol and logic in replicated on multiple implementation,
different than glibc we consolidate it on ddcoremath.h).

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>
2026-01-12 10:34:32 -03:00
Paul Eggert 66f3e9219d Update copyright dates with scripts/update-copyrights 2026-01-01 13:42:29 -08:00
Adhemerval Zanella 999cd617cb x86: Do not use __builtin_isinf_sign for _Float64x/long double
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>
2025-12-22 15:55:20 -03:00
Adhemerval Zanella 5011210399 x86: Do not use __builtin_fpclassify for _Float64x/long double
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>
2025-12-22 15:55:16 -03:00
Adhemerval Zanella 42b4589f28 math: Do not use __builtin_isgreater* and __builtin_isless* on clang
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>
2025-12-19 13:23:06 -03:00
James Chesterman e2b00d59eb aarch64: Implement AdvSIMD and SVE rsqrt(f) routines
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>
2025-12-05 15:05:54 -03:00
Joseph Myers e535fb910c Define C23 header version macros
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.
2025-11-27 19:32:49 +00:00
Adhemerval Zanella a61f7fd59d math: Sync atanh from CORE-MATH
The CORE-MATH commit dc9465e7 fixes some issues:

Failure: Test: atanh_towardzero (0x8.3f79103b3c64p-4)
Result:
 is:          5.7018661316561103e-01   0x1.23ef7ff0539c6p-1
 should be:   5.7018661316561092e-01   0x1.23ef7ff0539c5p-1
 difference:  1.1102230246251565e-16   0x1.0000000000000p-53
 ulp       :  1.0000
 max.ulp   :  0.0000
Failure: Test: atanh_towardzero (0x8.3f7d95aabaf7p-4)
Result:
 is:          5.7019248543911060e-01   0x1.23f044fac5997p-1
 should be:   5.7019248543911049e-01   0x1.23f044fac5996p-1
 difference:  1.1102230246251565e-16   0x1.0000000000000p-53
 ulp       :  1.0000
 max.ulp   :  0.0000
Failure: Test: atanh_towardzero (0x8.3f805380d6728p-4)
Result:
 is:          5.7019604623795527e-01   0x1.23f0bc75cd113p-1
 should be:   5.7019604623795516e-01   0x1.23f0bc75cd112p-1
 difference:  1.1102230246251565e-16   0x1.0000000000000p-53
 ulp       :  1.0000
 max.ulp   :  0.0000
Maximal error of `atanh_towardzero'
 is      : 1 ulp
 accepted: 0 ulp

Checked on x86_64-linux-gnu, x86_64-linux-gnu-v3, aarch64-linux-gnu,
and i686-linux-gnu.
2025-11-26 14:10:07 -03:00
Adhemerval Zanella 25de0771ec configure: Only use -fno-fp-int-builtin-inexact if compiler supports it
Checked on x86_64-linux-gnu.

Reviewed-by: Sam James <sam@gentoo.org>
2025-11-21 13:13:10 -03:00
Adhemerval Zanella 92186652d8 math: Sync atanh from CORE-MATH
The CORE-MATH commit 703d7487 fixes some issues for RNDZ:

Failure: Test: atanh_towardzero (0x5.96200b978b69cp-4)
Result:
 is:          3.6447730550366463e-01   0x1.753989ed16faap-2
 should be:   3.6447730550366458e-01   0x1.753989ed16fa9p-2
 difference:  5.5511151231257827e-17   0x1.0000000000000p-54
 ulp       :  1.0000
 max.ulp   :  0.0000
Maximal error of `atanh_towardzero'
 is      : 1 ulp
 accepted: 0 ulp

Checked on x86_64-linux-gnu, x86_64-linux-gnu-v3, aarch64-linux-gnu,
and i686-linux-gnu.
2025-11-19 15:21:44 -03:00
Adhemerval Zanella 4567204feb math: Sync acosh from CORE-MATH
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.
2025-11-19 12:58:56 -03:00
Adhemerval Zanella 13cfd77bf5 math: Don't redirect inlined builtin math functions
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>
2025-11-17 11:17:07 -03:00
Joseph Myers 1f79bc4838 Change fromfp functions to return floating types following C23 (bug 28327)
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.
2025-11-13 00:04:21 +00:00
Adhemerval Zanella b983c854e6 math: Sync acosh from CORE-MATH
The c9abdf80 fix handle some cases for RNDZ.

Checked on x86_64-linux-gnu.
2025-11-10 08:58:14 -03:00
Adhemerval Zanella 3078358ac6 math: Remove the SVID error handling from tgammaf
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>
2025-11-05 10:19:37 -03:00
Adhemerval Zanella de0e623434 math: Remove the SVID error handling from lgammaf/lgammaf_r
It improves latency throughput for about 2%.

Tested on x86_64-linux-gnu and i686-linux-gnu.
Reviewed-by: Wilco Dijkstra  <Wilco.Dijkstra@arm.com>
2025-11-05 09:27:07 -03:00