summaryrefslogtreecommitdiff
path: root/sysdeps/ieee754
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2025-10-31 13:08:51 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2025-11-04 04:14:01 -0300
commit0e1a1178ee22a25ff4568f51a2fec85451b17b04 (patch)
tree4f500bd6e226c7621c2c557a585f85c8f5070663 /sysdeps/ieee754
parentc4c6c79d70888702dcabfb208fbb664d9d9e6667 (diff)
math: Remove the SVID error handling from remainder
The optimized i386 version is faster than the generic one, and gcc implements it through the builtin. This optimization enables us to migrate the implementation to a C version. The performance on a Zen3 chip is similar to the SVID one. The m68k provided an optimized version through __m81_u(remainderf) (mathimpl.h), and gcc does not implement it through a builtin (different than i386). Performance improves a bit on x86_64 (Zen3, gcc 15.2.1): reciprocal-throughput input master NO-SVID improvement x86_64 subnormals 18.8522 16.2506 13.80% x86_64 normal 421.8260 403.9270 4.24% x86_64 close-exponent 21.0579 18.7642 10.89% i686 subnormals 21.3443 21.4229 -0.37% i686 normal 525.8380 538.807 -2.47% i686 close-exponent 21.6589 21.7983 -0.64% Tested on x86_64-linux-gnu and i686-linux-gnu. Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
Diffstat (limited to 'sysdeps/ieee754')
-rw-r--r--sysdeps/ieee754/dbl-64/e_remainder.c30
-rw-r--r--sysdeps/ieee754/dbl-64/w_remainder.c1
-rw-r--r--sysdeps/ieee754/ldbl-opt/w_remainder_compat.c2
3 files changed, 21 insertions, 12 deletions
diff --git a/sysdeps/ieee754/dbl-64/e_remainder.c b/sysdeps/ieee754/dbl-64/e_remainder.c
index dbae3aab81..99c6a754f0 100644
--- a/sysdeps/ieee754/dbl-64/e_remainder.c
+++ b/sysdeps/ieee754/dbl-64/e_remainder.c
@@ -18,10 +18,12 @@
#include <math.h>
#include <libm-alias-finite.h>
+#include <libm-alias-double.h>
+#include <math-svid-compat.h>
#include "math_config.h"
double
-__ieee754_remainder (double x, double y)
+__remainder (double x, double y)
{
uint64_t hx = asuint64 (x);
uint64_t hy = asuint64 (y);
@@ -34,12 +36,8 @@ __ieee754_remainder (double x, double y)
y = fabs (y);
if (__glibc_likely (hy < UINT64_C (0x7fe0000000000000)))
{
- /* |x| not finite, |y| equal 0 is handled by fmod. */
- if (__glibc_unlikely (hx >= EXPONENT_MASK))
- return (x * y) / (x * y);
-
- x = fabs (__ieee754_fmod (x, y + y));
- if (x + x > y)
+ x = fabs (__fmod (x, y + y));
+ if (isgreater (x + x, y))
{
x -= y;
if (x + x >= y)
@@ -52,9 +50,9 @@ __ieee754_remainder (double x, double y)
}
else
{
- /* |x| not finite or |y| is NaN or 0 */
- if ((hx >= EXPONENT_MASK || (hy - 1) >= EXPONENT_MASK))
- return (x * y) / (x * y);
+ /* |x| not finite or |y| is NaN */
+ if (__glibc_unlikely (hx >= EXPONENT_MASK || hy > EXPONENT_MASK))
+ return __math_invalid (x * y);
x = fabs (x);
double y_half = y * 0.5;
@@ -70,4 +68,14 @@ __ieee754_remainder (double x, double y)
return sx ? -x : x;
}
-libm_alias_finite (__ieee754_remainder, __remainder)
+libm_alias_finite (__remainder, __remainder)
+#if LIBM_SVID_COMPAT
+versioned_symbol (libm, __remainder, remainder, GLIBC_2_43);
+libm_alias_double_other (__remainder, remainder)
+#else
+libm_alias_double (__remainder, remainder)
+weak_alias (__remainder, drem)
+# ifdef NO_LONG_DOUBLE
+weak_alias (__remainder, dreml)
+# endif
+#endif
diff --git a/sysdeps/ieee754/dbl-64/w_remainder.c b/sysdeps/ieee754/dbl-64/w_remainder.c
new file mode 100644
index 0000000000..db3355f598
--- /dev/null
+++ b/sysdeps/ieee754/dbl-64/w_remainder.c
@@ -0,0 +1 @@
+/* Not needed */
diff --git a/sysdeps/ieee754/ldbl-opt/w_remainder_compat.c b/sysdeps/ieee754/ldbl-opt/w_remainder_compat.c
index 8bdea32c02..ed87fbf7ec 100644
--- a/sysdeps/ieee754/ldbl-opt/w_remainder_compat.c
+++ b/sysdeps/ieee754/ldbl-opt/w_remainder_compat.c
@@ -1,6 +1,6 @@
#include <math_ldbl_opt.h>
#include <math/w_remainder_compat.c>
#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_0)
-strong_alias (__remainder, __drem)
+strong_alias (__remainder_compat, __drem)
compat_symbol (libm, __drem, dreml, GLIBC_2_0);
#endif