[PATCH 7/8] math: Sync pow with Arm Optimized Routines

Adhemerval Zanella adhemerval.zanella@linaro.org
Thu Feb 26 20:01:53 GMT 2026


Sync with commit 712aa21 for pow.c and 189dfef for pow_log_data.c.
No functional change.

Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
---
 sysdeps/ieee754/dbl-64/e_pow.c          | 24 +++++++++++++++++++-----
 sysdeps/ieee754/dbl-64/e_pow_log_data.c |  2 +-
 sysdeps/ieee754/dbl-64/math_config.h    |  2 +-
 3 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/sysdeps/ieee754/dbl-64/e_pow.c b/sysdeps/ieee754/dbl-64/e_pow.c
index 56c393e917..d0f9936ae2 100644
--- a/sysdeps/ieee754/dbl-64/e_pow.c
+++ b/sysdeps/ieee754/dbl-64/e_pow.c
@@ -73,7 +73,7 @@ log_inline (uint64_t ix, double *tail)
   /* Note: 1/c is j/N or j/N/2 where j is an integer in [N,2N) and
      |z/c - 1| < 1/N, so r = z/c - 1 is exactly representible.  */
 #ifdef __FP_FAST_FMA
-  r = __builtin_fma (z, invc, -1.0);
+  r = fma (z, invc, -1.0);
 #else
   /* Split z such that rhi, rlo and rhi*rhi are exact and |rlo| <= |r|.  */
   double zhi = asdouble ((iz + (1ULL << 31)) & (-1ULL << 32));
@@ -97,7 +97,7 @@ log_inline (uint64_t ix, double *tail)
   /* k*Ln2 + log(c) + r + A[0]*r*r.  */
 #ifdef __FP_FAST_FMA
   hi = t2 + ar2;
-  lo3 = __builtin_fma (ar, r, -ar2);
+  lo3 = fma (ar, r, -ar2);
   lo4 = t2 - hi + ar2;
 #else
   double arhi = A[0] * rhi;
@@ -107,8 +107,10 @@ log_inline (uint64_t ix, double *tail)
   lo4 = t2 - hi + arhi2;
 #endif
   /* p = log1p(r) - r - A[0]*r*r.  */
+#if POW_LOG_POLY_ORDER == 8
   p = (ar3
        * (A[1] + r * A[2] + ar2 * (A[3] + r * A[4] + ar2 * (A[5] + r * A[6]))));
+#endif
   lo = lo1 + lo2 + lo3 + lo4 + p;
   y = hi + lo;
   *tail = hi - y + lo;
@@ -221,9 +223,13 @@ exp_inline (double x, double xtail, uint32_t sign_bias)
   /* x = ln2/N*k + r, with int k and r in [-ln2/2N, ln2/2N].  */
   z = InvLn2N * x;
 #if TOINT_INTRINSICS
-  /* z - kd is in [-0.5, 0.5] in all rounding modes.  */
   kd = roundtoint (z);
   ki = converttoint (z);
+#elif EXP_USE_TOINT_NARROW
+  /* z - kd is in [-0.5-2^-16, 0.5] in all rounding modes.  */
+  kd = eval_as_double (z + Shift);
+  ki = asuint64 (kd) >> 16;
+  kd = (double) (int32_t) ki;
 #else
   /* z - kd is in [-1, 1] in non-nearest rounding modes.  */
   kd = math_narrow_eval (z + Shift);
@@ -244,7 +250,13 @@ exp_inline (double x, double xtail, uint32_t sign_bias)
   r2 = r * r;
   /* Without fma the worst case error is 0.25/N ulp larger.  */
   /* Worst case error is less than 0.5+1.11/N+(abs poly error * 2^53) ulp.  */
+#if EXP_POLY_ORDER == 4
+  tmp = tail + r + r2 * C2 + r * r2 * (C3 + r * C4);
+#elif EXP_POLY_ORDER == 5
   tmp = tail + r + r2 * (C2 + r * C3) + r2 * r2 * (C4 + r * C5);
+#elif EXP_POLY_ORDER == 6
+  tmp = tail + r + r2 * (0.5 + r * C3) + r2 * r2 * (C4 + r * C5 + r2 * C6);
+#endif
   if (__glibc_unlikely (abstop == 0))
     return specialcase (tmp, sbits, ki);
   scale = asdouble (sbits);
@@ -360,7 +372,9 @@ __pow (double x, double y)
       if (topx == 0)
 	{
 	  /* Normalize subnormal x so exponent becomes negative.  */
-	  ix = asuint64 (x * 0x1p52);
+	  /* Without the barrier some versions of clang evalutate the mul
+	     unconditionally causing spurious overflow exceptions.  */
+	  ix = asuint64 (math_opt_barrier (x) * 0x1p52);
 	  ix &= 0x7fffffffffffffff;
 	  ix -= 52ULL << 52;
 	}
@@ -371,7 +385,7 @@ __pow (double x, double y)
   double ehi, elo;
 #ifdef __FP_FAST_FMA
   ehi = y * hi;
-  elo = y * lo + __builtin_fma (y, hi, -ehi);
+  elo = y * lo + fma (y, hi, -ehi);
 #else
   double yhi = asdouble (iy & -1ULL << 27);
   double ylo = y - yhi;
diff --git a/sysdeps/ieee754/dbl-64/e_pow_log_data.c b/sysdeps/ieee754/dbl-64/e_pow_log_data.c
index b9fa605ccc..3f651518cf 100644
--- a/sysdeps/ieee754/dbl-64/e_pow_log_data.c
+++ b/sysdeps/ieee754/dbl-64/e_pow_log_data.c
@@ -61,7 +61,7 @@ error and the interval for z is selected such that near x == 1, where log(x)
 is tiny, large cancellation error is avoided in logc + poly(z/c - 1).  */
 .tab = {
 #if N == 128
-#define A(a,b,c) {a,0,b,c},
+#define A(a, b, c) {a, 0, b, c},
 A(0x1.6a00000000000p+0, -0x1.62c82f2b9c800p-2, 0x1.ab42428375680p-48)
 A(0x1.6800000000000p+0, -0x1.5d1bdbf580800p-2, -0x1.ca508d8e0f720p-46)
 A(0x1.6600000000000p+0, -0x1.5767717455800p-2, -0x1.362a4d5b6506dp-45)
diff --git a/sysdeps/ieee754/dbl-64/math_config.h b/sysdeps/ieee754/dbl-64/math_config.h
index a3506d77eb..8bdd0c3349 100644
--- a/sysdeps/ieee754/dbl-64/math_config.h
+++ b/sysdeps/ieee754/dbl-64/math_config.h
@@ -303,6 +303,6 @@ extern const struct pow_log_data
   /* Note: the pad field is unused, but allows slightly faster indexing.  */
   /* See e_pow_log_data.c for details.  */
   struct {double invc, pad, logc, logctail;} tab[1 << POW_LOG_TABLE_BITS];
-} __pow_log_data attribute_hidden;
+} __pow_log_data __attribute__ ((__aligned__ (16))) attribute_hidden;
 
 #endif
-- 
2.43.0



More information about the Libc-alpha mailing list