about summary refs log tree commit diff
path: root/sysdeps/ieee754/flt-32
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/ieee754/flt-32')
-rw-r--r--sysdeps/ieee754/flt-32/e_gammaf_r.c331
-rw-r--r--sysdeps/ieee754/flt-32/e_log10f.c195
-rw-r--r--sysdeps/ieee754/flt-32/math_config.h2
-rw-r--r--sysdeps/ieee754/flt-32/s_exp10m1f.c227
-rw-r--r--sysdeps/ieee754/flt-32/s_exp2m1f.c194
-rw-r--r--sysdeps/ieee754/flt-32/s_expm1f.c232
-rw-r--r--sysdeps/ieee754/flt-32/s_log10p1f.c182
-rw-r--r--sysdeps/ieee754/flt-32/s_log1pf.c271
-rw-r--r--sysdeps/ieee754/flt-32/s_log2p1f.c248
-rw-r--r--sysdeps/ieee754/flt-32/w_log1pf.c1
10 files changed, 1430 insertions, 453 deletions
diff --git a/sysdeps/ieee754/flt-32/e_gammaf_r.c b/sysdeps/ieee754/flt-32/e_gammaf_r.c
index a9730d61c1..6b1f95d50f 100644
--- a/sysdeps/ieee754/flt-32/e_gammaf_r.c
+++ b/sysdeps/ieee754/flt-32/e_gammaf_r.c
@@ -1,215 +1,176 @@
-/* Implementation of gamma function according to ISO C.
-   Copyright (C) 1997-2024 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
+/* Implementation of the gamma function for binary32.
 
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
+Copyright (c) 2023-2024 Alexei Sibidanov.
 
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
+The original version of this file was copied from the CORE-MATH
+project (file src/binary32/tgamma/tgammaf.c, revision a48e352).
 
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+ */
+
+/* Changes with respect to the original CORE-MATH code:
+   - removed the dealing with errno
+     (this is done in the wrapper math/w_tgammaf_compat.c)
+   - usage of math_narrow_eval to deal with underflow/overflow
+   - deal with signgamp
+ */
 
 #include <math.h>
-#include <math-narrow-eval.h>
-#include <math_private.h>
-#include <fenv_private.h>
-#include <math-underflow.h>
 #include <float.h>
+#include <stdint.h>
+#include <stddef.h>
 #include <libm-alias-finite.h>
+#include <math-narrow-eval.h>
+#include "math_config.h"
 
-/* Coefficients B_2k / 2k(2k-1) of x^-(2k-1) inside exp in Stirling's
-   approximation to gamma function.  */
+float
+__ieee754_gammaf_r (float x, int *signgamp)
+{
+  /* The wrapper in math/w_tgamma_template.c expects *signgamp to be set to a
+     non-negative value if the returned value is gamma(x), and to a negative
+     value if it is -gamma(x).
+     Since the code here directly computes gamma(x), we set it to 1.
+  */
+  if (signgamp != NULL)
+    *signgamp = 1;
 
-static const float gamma_coeff[] =
+  /* List of exceptional cases. Each entry contains the 32-bit encoding u of x,
+     a binary32 approximation f of gamma(x), and a correction term df.  */
+  static const struct
   {
-    0x1.555556p-4f,
-    -0xb.60b61p-12f,
-    0x3.403404p-12f,
+    uint32_t u;
+    float f, df;
+  } tb[] = {
+    { 0x27de86a9u,  0x1.268266p+47f,  0x1p22f },  /* x = 0x1.bd0d52p-48 */
+    { 0x27e05475u,  0x1.242422p+47f,  0x1p22f },  /* x = 0x1.c0a8eap-48 */
+    { 0xb63befb3u, -0x1.5cb6e4p+18f,  0x1p-7f },  /* x = -0x1.77df66p-19 */
+    { 0x3c7bb570u,  0x1.021d9p+6f,    0x1p-19f }, /* x = 0x1.f76aep-7 */
+    { 0x41e886d1u,  0x1.33136ap+98f,  0x1p73f },  /* x = 0x1.d10da2p+4 */
+    { 0xc067d177u,  0x1.f6850cp-3f,   0x1p-28f }, /* x = -0x1.cfa2eep+1 */
+    { 0xbd99da31u, -0x1.befe66p+3,   -0x1p-22f }, /* x = -0x1.33b462p-4 */
+    { 0xbf54c45au, -0x1.a6b4ecp+2,    0x1p-23f }, /* x = -0x1.a988b4p-1 */
+    { 0x41ee77feu,  0x1.d3631cp+101, -0x1p-76f }, /* x = 0x1.dceffcp+4 */
+    { 0x3f843a64u,  0x1.f6c638p-1,    0x1p-26f }, /* x = 0x1.0874c8p+0 */
   };
 
-#define NCOEFF (sizeof (gamma_coeff) / sizeof (gamma_coeff[0]))
-
-/* Return gamma (X), for positive X less than 42, in the form R *
-   2^(*EXP2_ADJ), where R is the return value and *EXP2_ADJ is set to
-   avoid overflow or underflow in intermediate calculations.  */
-
-static float
-gammaf_positive (float x, int *exp2_adj)
-{
-  int local_signgam;
-  if (x < 0.5f)
-    {
-      *exp2_adj = 0;
-      return __ieee754_expf (__ieee754_lgammaf_r (x + 1, &local_signgam)) / x;
-    }
-  else if (x <= 1.5f)
-    {
-      *exp2_adj = 0;
-      return __ieee754_expf (__ieee754_lgammaf_r (x, &local_signgam));
-    }
-  else if (x < 2.5f)
-    {
-      *exp2_adj = 0;
-      float x_adj = x - 1;
-      return (__ieee754_expf (__ieee754_lgammaf_r (x_adj, &local_signgam))
-	      * x_adj);
-    }
-  else
-    {
-      float eps = 0;
-      float x_eps = 0;
-      float x_adj = x;
-      float prod = 1;
-      if (x < 4.0f)
-	{
-	  /* Adjust into the range for applying Stirling's
-	     approximation.  */
-	  float n = ceilf (4.0f - x);
-	  x_adj = math_narrow_eval (x + n);
-	  x_eps = (x - (x_adj - n));
-	  prod = __gamma_productf (x_adj - n, x_eps, n, &eps);
+  uint32_t t = asuint (x);
+  uint32_t ax = t << 1;
+  if (__glibc_unlikely (ax >= (0xffu << 24)))
+    { /* x=NaN or +/-Inf */
+      if (ax == (0xffu << 24))
+	{ /* x=+/-Inf */
+	  if (t >> 31) /* x=-Inf */
+	    return __math_invalidf (x);
+	  return x; /* x=+Inf */
 	}
-      /* The result is now gamma (X_ADJ + X_EPS) / (PROD * (1 + EPS)).
-	 Compute gamma (X_ADJ + X_EPS) using Stirling's approximation,
-	 starting by computing pow (X_ADJ, X_ADJ) with a power of 2
-	 factored out.  */
-      float exp_adj = -eps;
-      float x_adj_int = roundf (x_adj);
-      float x_adj_frac = x_adj - x_adj_int;
-      int x_adj_log2;
-      float x_adj_mant = __frexpf (x_adj, &x_adj_log2);
-      if (x_adj_mant < M_SQRT1_2f)
+      return x + x; /* x=NaN, where x+x ensures the "Invalid operation"
+		       exception is set if x is sNaN */
+    }
+  double z = x;
+  if (__glibc_unlikely (ax < 0x6d000000u))
+    { /* |x| < 0x1p-18 */
+      volatile double d = (0x1.fa658c23b1578p-1 - 0x1.d0a118f324b63p-1 * z)
+	* z - 0x1.2788cfc6fb619p-1;
+      double f = 1.0 / z + d;
+      float r = f;
+      uint64_t rt = asuint64 (f);
+      if (((rt + 2) & 0xfffffff) < 4)
 	{
-	  x_adj_log2--;
-	  x_adj_mant *= 2.0f;
+	  for (unsigned i = 0; i < sizeof (tb) / sizeof (tb[0]); i++)
+	    if (t == tb[i].u)
+	      return tb[i].f + tb[i].df;
 	}
-      *exp2_adj = x_adj_log2 * (int) x_adj_int;
-      float ret = (__ieee754_powf (x_adj_mant, x_adj)
-		   * __ieee754_exp2f (x_adj_log2 * x_adj_frac)
-		   * __ieee754_expf (-x_adj)
-		   * sqrtf (2 * M_PIf / x_adj)
-		   / prod);
-      exp_adj += x_eps * __ieee754_logf (x_adj);
-      float bsum = gamma_coeff[NCOEFF - 1];
-      float x_adj2 = x_adj * x_adj;
-      for (size_t i = 1; i <= NCOEFF - 1; i++)
-	bsum = bsum / x_adj2 + gamma_coeff[NCOEFF - 1 - i];
-      exp_adj += bsum / x_adj;
-      return ret + ret * __expm1f (exp_adj);
+      return r;
     }
-}
-
-float
-__ieee754_gammaf_r (float x, int *signgamp)
-{
-  int32_t hx;
-  float ret;
-
-  GET_FLOAT_WORD (hx, x);
-
-  if (__glibc_unlikely ((hx & 0x7fffffff) == 0))
+  float fx = floorf (x);
+  if (__glibc_unlikely (x >= 0x1.18522p+5f))
     {
-      /* Return value for x == 0 is Inf with divide by zero exception.  */
-      *signgamp = 0;
-      return 1.0 / x;
+      /* Overflow case.  The original CORE-MATH code returns
+	 0x1p127f * 0x1p127f, but apparently some compilers replace this
+	 by +Inf.  */
+      return math_narrow_eval (x * 0x1p127f);
     }
-  if (__builtin_expect (hx < 0, 0)
-      && (uint32_t) hx < 0xff800000 && rintf (x) == x)
-    {
-      /* Return value for integer x < 0 is NaN with invalid exception.  */
-      *signgamp = 0;
-      return (x - x) / (x - x);
+  /* compute k only after the overflow check, otherwise the case to integer
+     might overflow */
+  int k = fx;
+  if (__glibc_unlikely (fx == x))
+    { /* x is integer */
+      if (x == 0.0f)
+	return 1.0f / x;
+      if (x < 0.0f)
+	return __math_invalidf (0.0f);
+      double t0 = 1, x0 = 1;
+      for (int i = 1; i < k; i++, x0 += 1.0)
+	t0 *= x0;
+      return t0;
     }
-  if (__glibc_unlikely (hx == 0xff800000))
-    {
-      /* x == -Inf.  According to ISO this is NaN.  */
-      *signgamp = 0;
-      return x - x;
+  if (__glibc_unlikely (x < -42.0f))
+    { /* negative non-integer */
+      /* For x < -42, x non-integer, |gamma(x)| < 2^-151.  */
+      static const float sgn[2] = { 0x1p-127f, -0x1p-127f };
+      /* Underflows always happens */
+      return math_narrow_eval (0x1p-127f * sgn[k & 1]);
     }
-  if (__glibc_unlikely ((hx & 0x7f800000) == 0x7f800000))
+  /* The array c[] stores a degree-15 polynomial approximation for
+     gamma(x).  */
+  static const double c[] =
     {
-      /* Positive infinity (return positive infinity) or NaN (return
-	 NaN).  */
-      *signgamp = 0;
-      return x + x;
-    }
+       0x1.c9a76be577123p+0,   0x1.8f2754ddcf90dp+0,  0x1.0d1191949419bp+0,
+       0x1.e1f42cf0ae4a1p-2,   0x1.82b358a3ab638p-3,  0x1.e1f2b30cd907bp-5,
+       0x1.240f6d4071bd8p-6,   0x1.1522c9f3cd012p-8,  0x1.1fd0051a0525bp-10,
+       0x1.9808a8b96c37ep-13,  0x1.b3f78e01152b5p-15, 0x1.49c85a7e1fd04p-18,
+       0x1.471ca49184475p-19, -0x1.368f0b7ed9e36p-23, 0x1.882222f9049efp-23,
+      -0x1.a69ed2042842cp-25
+   };
 
-  if (x >= 36.0f)
-    {
-      /* Overflow.  */
-      *signgamp = 0;
-      ret = math_narrow_eval (FLT_MAX * FLT_MAX);
-      return ret;
-    }
-  else
+  double m = z - 0x1.7p+1;
+  double i = roundeven (m);
+  double step = copysign (1.0, i);
+  double d = m - i, d2 = d * d, d4 = d2 * d2, d8 = d4 * d4;
+  double f = (c[0] + d * c[1]) + d2 * (c[2] + d * c[3])
+	     + d4 * ((c[4] + d * c[5]) + d2 * (c[6] + d * c[7]))
+	     + d8 * ((c[8] + d * c[9]) + d2 * (c[10] + d * c[11])
+		     + d4 * ((c[12] + d * c[13]) + d2 * (c[14] + d * c[15])));
+  int jm = fabs (i);
+  double w = 1;
+  if (jm)
     {
-      SET_RESTORE_ROUNDF (FE_TONEAREST);
-      if (x > 0.0f)
+      z -= 0.5 + step * 0.5;
+      w = z;
+      for (int j = jm - 1; j; j--)
 	{
-	  *signgamp = 0;
-	  int exp2_adj;
-	  float tret = gammaf_positive (x, &exp2_adj);
-	  ret = __scalbnf (tret, exp2_adj);
+	  z -= step;
+	  w *= z;
 	}
-      else if (x >= -FLT_EPSILON / 4.0f)
-	{
-	  *signgamp = 0;
-	  ret = 1.0f / x;
-	}
-      else
-	{
-	  float tx = truncf (x);
-	  *signgamp = (tx == 2.0f * truncf (tx / 2.0f)) ? -1 : 1;
-	  if (x <= -42.0f)
-	    /* Underflow.  */
-	    ret = FLT_MIN * FLT_MIN;
-	  else
-	    {
-	      float frac = tx - x;
-	      if (frac > 0.5f)
-		frac = 1.0f - frac;
-	      float sinpix = (frac <= 0.25f
-			      ? __sinf (M_PIf * frac)
-			      : __cosf (M_PIf * (0.5f - frac)));
-	      int exp2_adj;
-	      float tret = M_PIf / (-x * sinpix
-				    * gammaf_positive (-x, &exp2_adj));
-	      ret = __scalbnf (tret, -exp2_adj);
-	      math_check_force_underflow_nonneg (ret);
-	    }
-	}
-      ret = math_narrow_eval (ret);
-    }
-  if (isinf (ret) && x != 0)
-    {
-      if (*signgamp < 0)
-	{
-	  ret = math_narrow_eval (-copysignf (FLT_MAX, ret) * FLT_MAX);
-	  ret = -ret;
-	}
-      else
-	ret = math_narrow_eval (copysignf (FLT_MAX, ret) * FLT_MAX);
-      return ret;
     }
-  else if (ret == 0)
+  if (i <= -0.5)
+    w = 1 / w;
+  f *= w;
+  uint64_t rt = asuint64 (f);
+  float r = f;
+  /* Deal with exceptional cases.  */
+  if (__glibc_unlikely (((rt + 2) & 0xfffffff) < 8))
     {
-      if (*signgamp < 0)
-	{
-	  ret = math_narrow_eval (-copysignf (FLT_MIN, ret) * FLT_MIN);
-	  ret = -ret;
-	}
-      else
-	ret = math_narrow_eval (copysignf (FLT_MIN, ret) * FLT_MIN);
-      return ret;
+      for (unsigned j = 0; j < sizeof (tb) / sizeof (tb[0]); j++)
+	if (t == tb[j].u)
+	  return tb[j].f + tb[j].df;
     }
-  else
-    return ret;
+  return r;
 }
 libm_alias_finite (__ieee754_gammaf_r, __gammaf_r)
diff --git a/sysdeps/ieee754/flt-32/e_log10f.c b/sysdeps/ieee754/flt-32/e_log10f.c
index 791895e042..03d9e281f3 100644
--- a/sysdeps/ieee754/flt-32/e_log10f.c
+++ b/sysdeps/ieee754/flt-32/e_log10f.c
@@ -1,54 +1,161 @@
-/* e_log10f.c -- float version of e_log10.c.
- */
-
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
+/* Correctly-rounded radix-10 logarithm function for binary32 value.
+
+Copyright (c) 2022-2023 Alexei Sibidanov.
+
+This file is part of the CORE-MATH project
+project (file src/binary32/log10/log10f.c, revision bc385c2).
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
 
 #include <math.h>
-#include <math_private.h>
-#include <fix-int-fp-convert-zero.h>
+#include <stdint.h>
 #include <libm-alias-finite.h>
+#include "math_config.h"
 
-static const float
-two25      =  3.3554432000e+07, /* 0x4c000000 */
-ivln10     =  4.3429449201e-01, /* 0x3ede5bd9 */
-log10_2hi  =  3.0102920532e-01, /* 0x3e9a2080 */
-log10_2lo  =  7.9034151668e-07; /* 0x355427db */
+static __attribute__ ((noinline)) float
+as_special (float x)
+{
+  uint32_t ux = asuint (x);
+  if (ux == 0x7f800000u)
+    return x; /* +inf */
+  uint32_t ax = ux << 1;
+  if (ax == 0u)
+    /* -0.0 */
+    return  __math_divzerof (1);
+  if (ax > 0xff000000u)
+    return x + x; /* nan */
+  return __math_invalidf (x);
+}
 
 float
-__ieee754_log10f(float x)
+__ieee754_log10f (float x)
 {
-	float y,z;
-	int32_t i,k,hx;
-
-	GET_FLOAT_WORD(hx,x);
-
-	k=0;
-	if (hx < 0x00800000) {			/* x < 2**-126  */
-	    if (__builtin_expect((hx&0x7fffffff)==0, 0))
-	      return -two25/fabsf (x);	/* log(+-0)=-inf  */
-	    if (__builtin_expect(hx<0, 0))
-		return (x-x)/(x-x);	/* log(-#) = NaN */
-	    k -= 25; x *= two25; /* subnormal number, scale up x */
-	    GET_FLOAT_WORD(hx,x);
+  static const double tr[] =
+    {
+      0x1p+0,         0x1.f81f82p-1,  0x1.f07c1fp-1,  0x1.e9131acp-1,
+      0x1.e1e1e1ep-1, 0x1.dae6077p-1, 0x1.d41d41dp-1, 0x1.cd85689p-1,
+      0x1.c71c71cp-1, 0x1.c0e0704p-1, 0x1.bacf915p-1, 0x1.b4e81b5p-1,
+      0x1.af286bdp-1, 0x1.a98ef6p-1,  0x1.a41a41ap-1, 0x1.9ec8e95p-1,
+      0x1.999999ap-1, 0x1.948b0fdp-1, 0x1.8f9c19p-1,  0x1.8acb90fp-1,
+      0x1.8618618p-1, 0x1.8181818p-1, 0x1.7d05f41p-1, 0x1.78a4c81p-1,
+      0x1.745d174p-1, 0x1.702e05cp-1, 0x1.6c16c17p-1, 0x1.6816817p-1,
+      0x1.642c859p-1, 0x1.605816p-1,  0x1.5c9882cp-1, 0x1.58ed231p-1,
+      0x1.5555555p-1, 0x1.51d07ebp-1, 0x1.4e5e0a7p-1, 0x1.4afd6ap-1,
+      0x1.47ae148p-1, 0x1.446f865p-1, 0x1.4141414p-1, 0x1.3e22cbdp-1,
+      0x1.3b13b14p-1, 0x1.3813814p-1, 0x1.3521cfbp-1, 0x1.323e34ap-1,
+      0x1.2f684bep-1, 0x1.2c9fb4ep-1, 0x1.29e412ap-1, 0x1.27350b9p-1,
+      0x1.2492492p-1, 0x1.21fb781p-1, 0x1.1f7047ep-1, 0x1.1cf06aep-1,
+      0x1.1a7b961p-1, 0x1.1811812p-1, 0x1.15b1e5fp-1, 0x1.135c811p-1,
+      0x1.1111111p-1, 0x1.0ecf56cp-1, 0x1.0c9715p-1,  0x1.0a6810ap-1,
+      0x1.0842108p-1, 0x1.0624dd3p-1, 0x1.041041p-1,  0x1.0204081p-1,
+      0.5
+    };
+  static const double tl[] =
+    {
+      -0x1.d45fd6237ebe3p-47, 0x1.b947689311b6ep-8, 0x1.b5e909c96d7d5p-7,
+      0x1.45f4f59ed2165p-6,   0x1.af5f92cbd8f1ep-6, 0x1.0ba01a606de8cp-5,
+      0x1.3ed119b9a2b7bp-5,   0x1.714834298eec2p-5, 0x1.a30a9d98357fbp-5,
+      0x1.d41d512670813p-5,   0x1.02428c0f65519p-4, 0x1.1a23444eecc3ep-4,
+      0x1.31b30543f4cb4p-4,   0x1.48f3ed39bfd04p-4, 0x1.5fe8049a0e423p-4,
+      0x1.769140a6aa008p-4,   0x1.8cf1836c98cb3p-4, 0x1.a30a9d55541a1p-4,
+      0x1.b8de4d1ee823ep-4,   0x1.ce6e4202ca2e6p-4, 0x1.e3bc1accace07p-4,
+      0x1.f8c9683b5abd4p-4,   0x1.06cbd68ca9a6ep-3, 0x1.11142f19df73p-3,
+      0x1.1b3e71fa7a97fp-3,   0x1.254b4d37a46e3p-3, 0x1.2f3b6912cbf07p-3,
+      0x1.390f683115886p-3,   0x1.42c7e7fffc5a8p-3, 0x1.4c65808c78d3cp-3,
+      0x1.55e8c50751c55p-3,   0x1.5f52445dec3d8p-3, 0x1.68a288c3f12p-3,
+      0x1.71da17bdf0d19p-3,   0x1.7af973608afd9p-3, 0x1.84011952a2579p-3,
+      0x1.8cf1837a7ea6p-3,    0x1.95cb2891e43d6p-3, 0x1.9e8e7b0f869ep-3,
+      0x1.a73beaa5db18dp-3,   0x1.afd3e394558d3p-3, 0x1.b856cf060d9f1p-3,
+      0x1.c0c5134de1ffcp-3,   0x1.c91f1371bc99fp-3, 0x1.d1652ffcd3f53p-3,
+      0x1.d997c6f635e75p-3,   0x1.e1b733ab90f3bp-3, 0x1.e9c3ceadac856p-3,
+      0x1.f1bdeec43a305p-3,   0x1.f9a5e7a5fa3fep-3, 0x1.00be05ac02f2bp-2,
+      0x1.04a054d81a2d4p-2,   0x1.087a0835957fbp-2, 0x1.0c4b457099517p-2,
+      0x1.101431aa1fe51p-2,   0x1.13d4f08b98dd8p-2, 0x1.178da53edb892p-2,
+      0x1.1b3e71e9f9d58p-2,   0x1.1ee777defdeedp-2, 0x1.2288d7b48e23bp-2,
+      0x1.2622b0f52e49fp-2,   0x1.29b522a4c6314p-2, 0x1.2d404b0e30f8p-2,
+      0x1.30c4478f3fbe5p-2,   0x1.34413509f7915p-2
+    };
+  static const union
+  {
+    float f;
+    uint32_t u;
+  } st[] =
+  {
+    { 0x1p+0 },        { 0x1.4p+3 },      { 0x1.9p+6 },       { 0x1.f4p+9 },
+    { 0x1.388p+13 },   { 0x1.86ap+16 },   { 0x1.e848p+19 },   { 0x1.312dp+23 },
+    { 0x1.7d784p+26 }, { 0x1.dcd65p+29 }, { 0x1.2a05f2p+33 }, { 0 },
+    { 0 },             { 0 },             { 0 },              { 0 }
+  };
+  static const double b[] =
+    {
+      0x1.bcb7b15c5a2f8p-2, -0x1.bcbb1dbb88ebap-3, 0x1.2871c39d521c6p-3
+    };
+  static const double c[] =
+    {
+      0x1.bcb7b1526e50ep-2,  -0x1.bcb7b1526e53dp-3, 0x1.287a7636f3fa2p-3,
+      -0x1.bcb7b146a14b3p-4, 0x1.63c627d5219cbp-4,  -0x1.2880736c8762dp-4,
+      0x1.fc1ecf913961ap-5
+    };
+  uint32_t ux = asuint (x);
+  if (__glibc_unlikely (ux < (1 << 23) || ux >= 0x7f800000u))
+    {
+      if (ux == 0 || ux >= 0x7f800000u)
+	return as_special (x);
+      /* subnormal */
+      int n = __builtin_clz (ux) - 8;
+      ux <<= n;
+      ux -= n << 23;
+    }
+  unsigned m = ux & ((1 << 23) - 1), j = (m + (1 << (23 - 7))) >> (23 - 6);
+  double ix = tr[j], l = tl[j];
+  int e = ((int) ux >> 23) - 127;
+  unsigned je = e + 1;
+  je = (je * 0x4d104d4) >> 28;
+  if (__glibc_unlikely (ux == st[je].u))
+    return je;
+
+  double tz = asdouble (((int64_t) m | ((int64_t) 1023 << 23)) << (52 - 23));
+  double z = tz * ix - 1, z2 = z * z;
+  double r
+      = ((e * 0x1.34413509f79ffp-2 + l) + z * b[0]) + z2 * (b[1] + z * b[2]);
+  float ub = r, lb = r + 0x1.b008p-34;
+  if (__glibc_unlikely (ub != lb))
+    {
+      double f = z
+		 * ((c[0] + z * c[1])
+		    + z2
+			  * ((c[2] + z * c[3])
+			     + z2 * (c[4] + z * c[5] + z2 * c[6])));
+      f -= 0x1.0cee0ed4ca7e9p-54 * e;
+      f += l - tl[0];
+      double el = e * 0x1.34413509f7ap-2;
+      r = el + f;
+      ub = r;
+      tz = r;
+      if (__glibc_unlikely (!((asuint64 (tz) & ((1 << 28) - 1)))))
+	{
+	  double dr = (el - r) + f;
+	  r += dr * 32;
+	  ub = r;
 	}
-	if (__builtin_expect(hx >= 0x7f800000, 0)) return x+x;
-	k += (hx>>23)-127;
-	i  = ((uint32_t)k&0x80000000)>>31;
-	hx = (hx&0x007fffff)|((0x7f-i)<<23);
-	y  = (float)(k+i);
-	if (FIX_INT_FP_CONVERT_ZERO && y == 0.0f)
-	  y = 0.0f;
-	SET_FLOAT_WORD(x,hx);
-	z  = y*log10_2lo + ivln10*__ieee754_logf(x);
-	return  z+y*log10_2hi;
+    }
+  return ub;
 }
 libm_alias_finite (__ieee754_log10f, __log10f)
diff --git a/sysdeps/ieee754/flt-32/math_config.h b/sysdeps/ieee754/flt-32/math_config.h
index 729f22cd4f..dc07ebd459 100644
--- a/sysdeps/ieee754/flt-32/math_config.h
+++ b/sysdeps/ieee754/flt-32/math_config.h
@@ -166,9 +166,9 @@ extern const struct exp2f_data
   uint64_t tab[1 << EXP2F_TABLE_BITS];
   double shift_scaled;
   double poly[EXP2F_POLY_ORDER];
-  double shift;
   double invln2_scaled;
   double poly_scaled[EXP2F_POLY_ORDER];
+  double shift;
 } __exp2f_data attribute_hidden;
 
 #define LOGF_TABLE_BITS 4
diff --git a/sysdeps/ieee754/flt-32/s_exp10m1f.c b/sysdeps/ieee754/flt-32/s_exp10m1f.c
new file mode 100644
index 0000000000..ea3173a174
--- /dev/null
+++ b/sysdeps/ieee754/flt-32/s_exp10m1f.c
@@ -0,0 +1,227 @@
+/* Implementation of the exp10m1 function for binary32.
+
+Copyright (c) 2022-2024 Alexei Sibidanov. Paul Zimmermann.
+
+The original version of this file was copied from the CORE-MATH
+project (file src/binary32/exp10m1/exp10m1f.c, revision c46b85b).
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+ */
+
+#include <math.h>
+#include "math_config.h"
+#include <libm-alias-float.h>
+
+float
+__exp10m1f (float x)
+{
+  const double iln10h = 0x1.a934f09p+1 * 16;
+  const double iln10l = 0x1.e68dc57f2496p-29 * 16;
+  double z = x;
+  uint32_t ux = asuint (x);
+  uint32_t ax = ux & (~0u >> 1);
+  if (__glibc_unlikely (ux > 0xc0f0d2f1u))
+    { /* x < -7.52575 */
+      if (ax > (0xffu << 23))
+	return x + x; /* nan */
+      return (ux == 0xff800000) ? -0x1p+0f : -0x1p+0f + 0x1p-26f;
+    }
+  else if (__glibc_unlikely (ax > 0x421a209au))
+    { /* x > 38.5318 */
+      if (ax >= asuint (INFINITY))
+	return x + x; /* +Inf or NaN */
+      return __math_oflowf (0);
+    }
+  else if (__glibc_unlikely (ax < 0x3d89c604u))
+    { /* |x| < 0.1549/log(10) */
+      double z2 = z * z, r;
+      if (__glibc_unlikely (ax < 0x3d1622fbu))
+	{ /* |x| < 8.44e-2/log(10)  */
+	  if (__glibc_unlikely (ax < 0x3c8b76a3u))
+	    { /* |x| < 3.92e-2/log(10)  */
+	      if (__glibc_unlikely (ax < 0x3bcced04u))
+		{ /* |x| < 1.44e-2/log(10) */
+		  if (__glibc_unlikely (ax < 0x3acf33ebu))
+		    { /* |x| < 3.64e-3/log(10 */
+		      if (__glibc_unlikely (ax < 0x395a966bu))
+			{ /* |x| < 4.8e-4/log(10 */
+			  if (__glibc_unlikely (ax < 0x36fe4a4bu))
+			    { /* |x| < 1.745e-5/log(10) */
+			      if (__glibc_unlikely (ax < 0x32407f39u))
+				{ /* |x| < 2.58e-8/log(10) */
+				  if (__glibc_unlikely (ax < 0x245e5bd9u))
+				    { /* |x| < 4.82164e-17 */
+				      r = 0x1.26bb1bbb55516p+1;
+				    }
+				  else
+				    {
+				      if (__glibc_unlikely (ux == 0x2c994b7bu))
+					return 0x1.60f974p-37f - 0x1p-90f;
+				      r = 0x1.26bb1bbb55516p+1
+					  + z * 0x1.53524c73cea69p+1;
+				    }
+				}
+			      else
+				{
+				  if (__glibc_unlikely (ux == 0xb6fa215bu))
+				    return -0x1.1ff87ep-16 + 0x1p-68;
+				  r = 0x1.26bb1bbb55516p+1
+				      + z * (0x1.53524c73ea62fp+1
+					     + z * 0x1.0470591de2c75p+1);
+				}
+			    }
+			  else
+			    {
+			      static const double cp[] =
+				{
+				  0x1.26bb1bbb55515p+1, 0x1.53524c73cea69p+1,
+				  0x1.0470595038cc2p+1, 0x1.2bd7609fe1561p+0
+			        };
+			      r = (cp[0] + z * cp[1])
+				  + z2 * (cp[2] + z * cp[3]);
+			    }
+			}
+		      else
+			{
+			  static const double cp[] =
+			    {
+			      0x1.26bb1bbb55516p+1, 0x1.53524c73ce6dbp+1,
+			      0x1.0470591de3024p+1, 0x1.2bd76b79060e6p+0,
+			      0x1.1429ffd3a963dp-1
+			    };
+			  r = (cp[0] + z * cp[1])
+			      + z2 * (cp[2] + z * (cp[3] + z * cp[4]));
+			}
+		    }
+		  else
+		    {
+		      static const double cp[] =
+			{
+			  0x1.26bb1bbb55516p+1, 0x1.53524c73cea67p+1,
+			  0x1.0470591dc2953p+1, 0x1.2bd760a004d64p+0,
+			  0x1.142a85da6f072p-1, 0x1.a7ed70725b00ep-3
+			};
+		      r = (cp[0] + z * cp[1]) + z2
+			    * ((cp[2] + z * cp[3])
+			       + z2 * (cp[4] + z * cp[5]));
+		    }
+		}
+	      else
+		{
+		  static const double cp[] =
+		    {
+		      0x1.26bb1bbb55516p+1, 0x1.53524c73ceadep+1,
+		      0x1.0470591de2bb4p+1, 0x1.2bd76099a9d33p+0,
+		      0x1.1429ffd829b0bp-1, 0x1.a7f2a6a0f7dc8p-3,
+		      0x1.16e4dfbce0f56p-4
+		    };
+		  r = (cp[0] + z * cp[1])
+		      + z2 * ((cp[2] + z * cp[3])
+			      + z2 * (cp[4] + z * (cp[5] + z * cp[6])));
+		}
+	    }
+	  else
+	    {
+	      static const double cp[] =
+		{
+		  0x1.26bb1bbb55515p+1, 0x1.53524c73cea6ap+1,
+		  0x1.0470591de476p+1,  0x1.2bd7609fd4ee2p+0,
+		  0x1.1429ff70a9b48p-1, 0x1.a7ed71259ba5bp-3,
+		  0x1.16f3004fb3ac1p-4, 0x1.4116b0388aa9fp-6
+		};
+	      r = ((cp[0] + z * cp[1]) + z2 * (cp[2] + z * cp[3]))
+		  + (z2 * z2) * ((cp[4] + z * cp[5]) + z2 * (cp[6]
+							     + z * cp[7]));
+	    }
+	}
+      else
+	{
+	  static const double cp[] =
+	    {
+	      0x1.26bb1bbb55515p+1, 0x1.53524c73cea42p+1, 0x1.0470591de2d1dp+1,
+	      0x1.2bd760a010a53p+0, 0x1.1429ffd16170cp-1, 0x1.a7ed6b2a0d97fp-3,
+	      0x1.16e4e37fa51e4p-4, 0x1.4147fe4c1676fp-6, 0x1.4897c4b3e329ap-8
+	    };
+	  r = ((cp[0] + z * cp[1]) + z2 * (cp[2] + z * cp[3]))
+	      + (z2 * z2) * ((cp[4] + z * cp[5])
+			     + z2 * (cp[6] + z * (cp[7] + z * cp[8])));
+	}
+      r *= z;
+      return r;
+    }
+  else
+    {
+      /* -7.52575 < x < -0.1549/log(10) or 0.1549/log(10) < x < 38.5318  */
+      static const double tb[] =
+	{
+	  0x1p+0, 0x1.0b5586cf9890fp+0, 0x1.172b83c7d517bp+0,
+	  0x1.2387a6e756238p+0, 0x1.306fe0a31b715p+0, 0x1.3dea64c123422p+0,
+	  0x1.4bfdad5362a27p+0, 0x1.5ab07dd485429p+0, 0x1.6a09e667f3bcdp+0,
+	  0x1.7a11473eb0187p+0, 0x1.8ace5422aa0dap+0, 0x1.9c49182a3f09p+0,
+	  0x1.ae89f995ad3adp+0, 0x1.c199bdd85529cp+0, 0x1.d5818dcfba487p+0,
+	  0x1.ea4afa2a490dap+0
+	};
+      static const double c[] =
+	{
+	  0x1.62e42fefa398bp-5,  0x1.ebfbdff84555ap-11, 0x1.c6b08d4ad86d3p-17,
+	  0x1.3b2ad1b1716a2p-23, 0x1.5d7472718ce9dp-30, 0x1.4a1d7f457ac56p-37
+	};
+
+      if (__glibc_unlikely ((ux << 11) == 0))
+	{
+	  uint32_t k = (ux >> 21) - 0x1fc;
+	  if (k <= 0xb)
+	    {
+	      if (k == 0)
+		return 10.0f - 1.0f;
+	      if (k == 4)
+		return 100.0f - 1.0f;
+	      if (k == 6)
+		return 1000.0f - 1.0f;
+	      if (k == 8)
+		return 10000.0f - 1.0f;
+	      if (k == 9)
+		return 100000.0f - 1.0f;
+	      if (k == 10)
+		return 1000000.0f - 1.0f;
+	      if (k == 11)
+		return 10000000.0f - 1.0f;
+	    }
+	}
+      double a = iln10h * z;
+      double ia = floor (a);
+      double h = (a - ia) + iln10l * z;
+      int64_t i = ia;
+      int64_t j = i & 0xf;
+      int64_t e = i - j;
+      e >>= 4;
+      double s = tb[j];
+      s *= asdouble ((e + 0x3ffull) << 52);
+      double h2 = h * h;
+      double c0 = c[0] + h * c[1];
+      double c2 = c[2] + h * c[3];
+      double c4 = c[4] + h * c[5];
+      c0 += h2 * (c2 + h2 * c4);
+      double w = s * h;
+      return (s - 1.0) + w * c0;
+    }
+}
+#ifndef __exp10m1f
+libm_alias_float (__exp10m1, exp10m1)
+#endif
diff --git a/sysdeps/ieee754/flt-32/s_exp2m1f.c b/sysdeps/ieee754/flt-32/s_exp2m1f.c
new file mode 100644
index 0000000000..325ffb11b0
--- /dev/null
+++ b/sysdeps/ieee754/flt-32/s_exp2m1f.c
@@ -0,0 +1,194 @@
+/* Correctly-rounded base-2 exponent function biased by 1 for binary32 value.
+
+Copyright (c) 2022-2024 Alexei Sibidanov.
+
+The original version of this file was copied from the CORE-MATH
+project (file src/binary32/exp2m1/exp2m1f.c, revision baf5f6b).
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#include <fenv.h>
+#include <math.h>
+#include "math_config.h"
+#include <libm-alias-float.h>
+#include <math-narrow-eval.h>
+#include <float.h>
+
+float
+__exp2m1f (float x)
+{
+  double z = x;
+  uint32_t ux = asuint (x);
+  uint32_t ax = ux & (~0u >> 1);
+  if (__glibc_unlikely (ux >= 0xc1c80000u))
+    { /* x <= -25 */
+      if (ax > (0xffu << 23))
+	return x + x; /* nan */
+      return (ux == 0xff800000) ? -0x1p+0f : -0x1p+0f + 0x1p-26f;
+    }
+  else if (__glibc_unlikely (ax >= 0x43000000u))
+    { /* x >= 128 */
+      if (ax >= asuint (INFINITY))
+	return x + x; /* +Inf or NaN */
+      /* exp2m1 (MAX_EXP) should not overflow when rounding towards zero
+         or towards -Inf.  We round FLT_MAX + 2^103 which is in the middle
+         between FLT_MAX and 2^128 (the next number with unbounded range).  */
+      float ret = math_narrow_eval (FLT_MAX + 0x1p103f);
+      if (x == FLT_MAX_EXP && ret == FLT_MAX)
+        return ret;
+      return __math_oflowf (0);
+    }
+  else if (__glibc_unlikely (ax < 0x3df95f1fu))
+    { /* |x| < 8.44e-2/log(2) */
+      double z2 = z * z, r;
+      if (__glibc_unlikely (ax < 0x3d67a4ccu))
+	{ /* |x| < 3.92e-2/log(2) */
+	  if (__glibc_unlikely (ax < 0x3caa2feeu))
+	    { /* |x| < 1.44e-2/log(2) */
+	      if (__glibc_unlikely (ax < 0x3bac1405u))
+		{ /* |x| < 3.64e-3/log(2) */
+		  if (__glibc_unlikely (ax < 0x3a358876u))
+		    { /* |x| < 4.8e-4/log(2) */
+		      if (__glibc_unlikely (ax < 0x37d32ef6u))
+			{ /* |x| < 1.745e-5/log(2) */
+			  if (__glibc_unlikely (ax < 0x331fdd82u))
+			    { /* |x| < 2.58e-8/log(2) */
+			      if (__glibc_unlikely (ax < 0x2538aa3bu))
+				/* |x| < 1.60171e-16 */
+				r = 0x1.62e42fefa39efp-1;
+			      else
+				r = 0x1.62e42fefa39fp-1
+				  + z * 0x1.ebfbdff82c58fp-3;
+			    }
+			  else
+			    {
+			      if (__glibc_unlikely (ux == 0xb3d85005u))
+				return -0x1.2bdf76p-24 - 0x1.8p-77;
+			      if (__glibc_unlikely (ux == 0x3338428du))
+				return 0x1.fee08ap-26 + 0x1p-80;
+			      static const double c[] =
+				{
+				  0x1.62e42fefa39efp-1, 0x1.ebfbdff8548fdp-3,
+				  0x1.c6b08d704a06dp-5
+				};
+			      r = c[0] + z * (c[1] + z * c[2]);
+			    }
+			}
+		      else
+			{
+			  if (__glibc_unlikely (ux == 0x388bca4fu))
+			    return 0x1.839702p-15 - 0x1.8p-68;
+			  static const double c[] =
+			    {
+			      0x1.62e42fefa39efp-1, 0x1.ebfbdff82c58fp-3,
+			      0x1.c6b08dc82b347p-5, 0x1.3b2ab6fbad172p-7
+			    };
+			  r = (c[0] + z * c[1]) + z2 * (c[2] + z * c[3]);
+			}
+		    }
+		  else
+		    {
+		      static const double c[] =
+			{
+			  0x1.62e42fefa39efp-1, 0x1.ebfbdff82c068p-3,
+			  0x1.c6b08d704a6dcp-5, 0x1.3b2ac262c3eedp-7,
+			  0x1.5d87fe7af779ap-10
+			};
+		      r = (c[0] + z * c[1])
+			  + z2 * (c[2] + z * (c[3] + z * c[4]));
+		    }
+		}
+	      else
+		{
+		  static const double c[] =
+		    {
+		      0x1.62e42fefa39fp-1,   0x1.ebfbdff82c58dp-3,
+		      0x1.c6b08d7011d13p-5,  0x1.3b2ab6fbd267dp-7,
+		      0x1.5d88a81cea49ep-10, 0x1.430912ea9b963p-13
+		    };
+		  r = (c[0] + z * c[1])
+		      + z2 * ((c[2] + z * c[3]) + z2 * (c[4] + z * c[5]));
+		}
+	    }
+	  else
+	    {
+	      static const double c[] =
+		{
+		  0x1.62e42fefa39efp-1,  0x1.ebfbdff82c639p-3,
+		  0x1.c6b08d7049f1cp-5,  0x1.3b2ab6f5243bdp-7,
+		  0x1.5d87fe80a9e6cp-10, 0x1.430d0b9257fa8p-13,
+		  0x1.ffcbfc4cf0952p-17
+		};
+	      r = (c[0] + z * c[1])
+		  + z2 * ((c[2] + z * c[3])
+			  + z2 * (c[4] + z * (c[5] + z * c[6])));
+	    }
+	}
+      else
+	{
+	  static const double c[] =
+	    {
+	      0x1.62e42fefa39efp-1,  0x1.ebfbdff82c591p-3,
+	      0x1.c6b08d704cf6bp-5,  0x1.3b2ab6fba00cep-7,
+	      0x1.5d87fdfdaadb4p-10, 0x1.4309137333066p-13,
+	      0x1.ffe5e90daf7ddp-17, 0x1.62c0220eed731p-20
+	    };
+	  r = ((c[0] + z * c[1]) + z2 * (c[2] + z * c[3]))
+	      + (z2 * z2) * ((c[4] + z * c[5]) + z2 * (c[6] + z * c[7]));
+	}
+      r *= z;
+      return r;
+    }
+  else
+    {
+      static const double c[] =
+	{
+	  0x1.62e42fefa398bp-5,  0x1.ebfbdff84555ap-11,
+	  0x1.c6b08d4ad86d3p-17, 0x1.3b2ad1b1716a2p-23,
+	  0x1.5d7472718ce9dp-30, 0x1.4a1d7f457ac56p-37
+	};
+      static const double tb[] =
+	{
+	  0x1p+0,               0x1.0b5586cf9890fp+0,  0x1.172b83c7d517bp+0,
+	  0x1.2387a6e756238p+0, 0x1.306fe0a31b715p+0,  0x1.3dea64c123422p+0,
+	  0x1.4bfdad5362a27p+0, 0x1.5ab07dd485429p+0,  0x1.6a09e667f3bcdp+0,
+	  0x1.7a11473eb0187p+0, 0x1.8ace5422aa0dap+0,  0x1.9c49182a3f09p+0,
+	  0x1.ae89f995ad3adp+0, 0x1.c199bdd85529cp+0,  0x1.d5818dcfba487p+0,
+	  0x1.ea4afa2a490dap+0
+	};
+      double a = 16.0 * z;
+      double ia = floor (a);
+      double h = a - ia;
+      double h2 = h * h;
+      int64_t i = ia, j = i & 0xf, e = i - j;
+      e >>= 4;
+      double s = tb[j];
+      s *= asdouble ((e + 0x3ffull) << 52);
+      double c0 = c[0] + h * c[1];
+      double c2 = c[2] + h * c[3];
+      double c4 = c[4] + h * c[5];
+      c0 += h2 * (c2 + h2 * c4);
+      double w = s * h;
+      return (s - 1.0) + w * c0;
+    }
+}
+#ifndef __exp2m1f
+libm_alias_float (__exp2m1, exp2m1)
+#endif
diff --git a/sysdeps/ieee754/flt-32/s_expm1f.c b/sysdeps/ieee754/flt-32/s_expm1f.c
index 35f7b5214a..edd7c9acf8 100644
--- a/sysdeps/ieee754/flt-32/s_expm1f.c
+++ b/sysdeps/ieee754/flt-32/s_expm1f.c
@@ -1,132 +1,124 @@
-/* s_expm1f.c -- float version of s_expm1.c.
- */
+/* Correctly-rounded natural exponent function biased by 1 for binary32 value.
 
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
+Copyright (c) 2022-2024 Alexei Sibidanov.
+
+This file is part of the CORE-MATH project
+project (file src/binary32/expm1/expm1f.c, revision bc385c2).
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
 
-#include <errno.h>
-#include <float.h>
 #include <math.h>
-#include <math-barriers.h>
-#include <math_private.h>
 #include <math-underflow.h>
 #include <libm-alias-float.h>
-
-static const float huge = 1.0e+30;
-static const float tiny = 1.0e-30;
-
-static const float
-one		= 1.0,
-o_threshold	= 8.8721679688e+01,/* 0x42b17180 */
-ln2_hi		= 6.9313812256e-01,/* 0x3f317180 */
-ln2_lo		= 9.0580006145e-06,/* 0x3717f7d1 */
-invln2		= 1.4426950216e+00,/* 0x3fb8aa3b */
-	/* scaled coefficients related to expm1 */
-Q1  =  -3.3333335072e-02, /* 0xbd088889 */
-Q2  =   1.5873016091e-03, /* 0x3ad00d01 */
-Q3  =  -7.9365076090e-05, /* 0xb8a670cd */
-Q4  =   4.0082177293e-06, /* 0x36867e54 */
-Q5  =  -2.0109921195e-07; /* 0xb457edbb */
+#include "math_config.h"
 
 float
-__expm1f(float x)
+__expm1f (float x)
 {
-	float y,hi,lo,c,t,e,hxs,hfx,r1;
-	int32_t k,xsb;
-	uint32_t hx;
-
-	GET_FLOAT_WORD(hx,x);
-	xsb = hx&0x80000000;		/* sign bit of x */
-	if(xsb==0) y=x; else y= -x;	/* y = |x| */
-	hx &= 0x7fffffff;		/* high word of |x| */
-
-    /* filter out huge and non-finite argument */
-	if(hx >= 0x4195b844) {			/* if |x|>=27*ln2 */
-	    if(hx >= 0x42b17218) {		/* if |x|>=88.721... */
-		if(hx>0x7f800000)
-		    return x+x;		 /* NaN */
-		if(hx==0x7f800000)
-		    return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */
-		if(x > o_threshold) {
-		  __set_errno (ERANGE);
-		  return huge*huge; /* overflow */
-		}
-	    }
-	    if(xsb!=0) { /* x < -27*ln2, return -1.0 with inexact */
-		math_force_eval(x+tiny);/* raise inexact */
-		return tiny-one;	/* return -1 */
-	    }
-	}
-
-    /* argument reduction */
-	if(hx > 0x3eb17218) {		/* if  |x| > 0.5 ln2 */
-	    if(hx < 0x3F851592) {	/* and |x| < 1.5 ln2 */
-		if(xsb==0)
-		    {hi = x - ln2_hi; lo =  ln2_lo;  k =  1;}
-		else
-		    {hi = x + ln2_hi; lo = -ln2_lo;  k = -1;}
-	    } else {
-		k  = invln2*x+((xsb==0)?(float)0.5:(float)-0.5);
-		t  = k;
-		hi = x - t*ln2_hi;	/* t*ln2_hi is exact here */
-		lo = t*ln2_lo;
-	    }
-	    x  = hi - lo;
-	    c  = (hi-x)-lo;
-	}
-	else if(hx < 0x33000000) {	/* when |x|<2**-25, return x */
-	    math_check_force_underflow (x);
-	    t = huge+x;	/* return x with inexact flags when x!=0 */
-	    return x - (t-(huge+x));
+  static const double c[] =
+    {
+      1, 0x1.62e42fef4c4e7p-6, 0x1.ebfd1b232f475p-13, 0x1.c6b19384ecd93p-20
+    };
+  static const double ch[] =
+    {
+      0x1.62e42fefa39efp-6,  0x1.ebfbdff82c58fp-13, 0x1.c6b08d702e0edp-20,
+      0x1.3b2ab6fb92e5ep-27, 0x1.5d886e6d54203p-35, 0x1.430976b8ce6efp-43
+    };
+  static const double td[] =
+    {
+      0x1p+0,               0x1.059b0d3158574p+0, 0x1.0b5586cf9890fp+0,
+      0x1.11301d0125b51p+0, 0x1.172b83c7d517bp+0, 0x1.1d4873168b9aap+0,
+      0x1.2387a6e756238p+0, 0x1.29e9df51fdee1p+0, 0x1.306fe0a31b715p+0,
+      0x1.371a7373aa9cbp+0, 0x1.3dea64c123422p+0, 0x1.44e086061892dp+0,
+      0x1.4bfdad5362a27p+0, 0x1.5342b569d4f82p+0, 0x1.5ab07dd485429p+0,
+      0x1.6247eb03a5585p+0, 0x1.6a09e667f3bcdp+0, 0x1.71f75e8ec5f74p+0,
+      0x1.7a11473eb0187p+0, 0x1.82589994cce13p+0, 0x1.8ace5422aa0dbp+0,
+      0x1.93737b0cdc5e5p+0, 0x1.9c49182a3f09p+0,  0x1.a5503b23e255dp+0,
+      0x1.ae89f995ad3adp+0, 0x1.b7f76f2fb5e47p+0, 0x1.c199bdd85529cp+0,
+      0x1.cb720dcef9069p+0, 0x1.d5818dcfba487p+0, 0x1.dfc97337b9b5fp+0,
+      0x1.ea4afa2a490dap+0, 0x1.f50765b6e454p+0
+    };
+  const double iln2 = 0x1.71547652b82fep+5;
+  const double big = 0x1.8p52;
+  double z = x;
+  uint32_t ux = asuint (x);
+  uint32_t ax = ux << 1;
+  if (__glibc_likely (ax < 0x7c400000u))
+    { /* |x| < 0.15625  */
+      if (__glibc_unlikely (ax < 0x676a09e8u))
+	{ /* |x| < 0x1.6a09e8p-24 */
+	  if (__glibc_unlikely (ax == 0x0u))
+	    return x; /* x = +-0 */
+	  return fmaf (fabsf (x), 0x1p-25f, x);
 	}
-	else k = 0;
-
-    /* x is now in primary range */
-	hfx = (float)0.5*x;
-	hxs = x*hfx;
-	r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5))));
-	t  = (float)3.0-r1*hfx;
-	e  = hxs*((r1-t)/((float)6.0 - x*t));
-	if(k==0) return x - (x*e-hxs);		/* c is 0 */
-	else {
-	    e  = (x*(e-c)-c);
-	    e -= hxs;
-	    if(k== -1) return (float)0.5*(x-e)-(float)0.5;
-	    if(k==1) {
-		if(x < (float)-0.25) return -(float)2.0*(e-(x+(float)0.5));
-		else	      return  one+(float)2.0*(x-e);
-	    }
-	    if (k <= -2 || k>56) {   /* suffice to return exp(x)-1 */
-		int32_t i;
-		y = one-(e-x);
-		GET_FLOAT_WORD(i,y);
-		SET_FLOAT_WORD(y,i+(k<<23));	/* add k to y's exponent */
-		return y-one;
-	    }
-	    t = one;
-	    if(k<23) {
-		int32_t i;
-		SET_FLOAT_WORD(t,0x3f800000 - (0x1000000>>k)); /* t=1-2^-k */
-		y = t-(e-x);
-		GET_FLOAT_WORD(i,y);
-		SET_FLOAT_WORD(y,i+(k<<23));	/* add k to y's exponent */
-	   } else {
-		int32_t i;
-		SET_FLOAT_WORD(t,((0x7f-k)<<23));	/* 2^-k */
-		y = x-(e+t);
-		y += one;
-		GET_FLOAT_WORD(i,y);
-		SET_FLOAT_WORD(y,i+(k<<23));	/* add k to y's exponent */
-	    }
+      static const double b[] =
+	{
+	  0x1.fffffffffffc2p-2,  0x1.55555555555fep-3,  0x1.555555559767fp-5,
+	  0x1.1111111098dc1p-7,  0x1.6c16bca988aa9p-10, 0x1.a01a07658483fp-13,
+	  0x1.a05b04d2c3503p-16, 0x1.71de3a960b5e3p-19
+	};
+      double z2 = z * z, z4 = z2 * z2;
+      double r = z + z2
+	* ((b[0] + z * b[1]) + z2 * (b[2] + z * b[3])
+	   + z4 * ((b[4] + z * b[5]) + z2 * (b[6] + z * b[7])));
+      return r;
+    }
+  if (__glibc_unlikely (ax >= 0x8562e430u))
+    { /* |x| > 88.72 */
+      if (ax > (0xffu << 24))
+	return x + x; /* nan */
+      if (__glibc_unlikely (ux >> 31))
+	{ /* x < 0 */
+	  if (ax == (0xffu << 24))
+	    return -1.0f;
+	  return -1.0f + 0x1p-26f;
 	}
-	return y;
+      if (ax == (0xffu << 24))
+	return INFINITY;
+      return __math_oflowf (0);
+    }
+  double a = iln2 * z;
+  double ia = roundeven (a);
+  double h = a - ia;
+  double h2 = h * h;
+  uint64_t u = asuint64 (ia + big);
+  double c2 = c[2] + h * c[3], c0 = c[0] + h * c[1];
+  const uint64_t *tdl = (uint64_t *) ((void *) td);
+  double sv = asdouble (tdl[u & 0x1f] + ((u >> 5) << 52));
+  double r = (c0 + h2 * c2) * sv - 1.0;
+  float ub = r, lb = r - sv * 0x1.3b3p-33;
+  if (__glibc_unlikely (ub != lb))
+    {
+      if (__glibc_unlikely (ux > 0xc18aa123u)) /* x < -17.32 */
+	return -1.0f + 0x1p-26f;
+      const double iln2h = 0x1.7154765p+5;
+      const double iln2l = 0x1.5c17f0bbbe88p-26;
+      double s = sv;
+      h = (iln2h * z - ia) + iln2l * z;
+      h2 = h * h;
+      double w = s * h;
+      r = (s - 1) + w
+	* ((ch[0] + h * ch[1])
+	   + h2 * ((ch[2] + h * ch[3]) + h2 * (ch[4] + h * ch[5])));
+      ub = r;
+    }
+  return ub;
 }
 libm_alias_float (__expm1, expm1)
diff --git a/sysdeps/ieee754/flt-32/s_log10p1f.c b/sysdeps/ieee754/flt-32/s_log10p1f.c
new file mode 100644
index 0000000000..64deb1eeda
--- /dev/null
+++ b/sysdeps/ieee754/flt-32/s_log10p1f.c
@@ -0,0 +1,182 @@
+/* Correctly-rounded biased argument base-10 logarithm function for binary32 value.
+
+Copyright (c) 2022-2023 Alexei Sibidanov.
+
+This file is part of the CORE-MATH project
+project (file src/binary32/log10p1/log10p1f.c revision bc385c2).
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#include <stdint.h>
+#include <errno.h>
+#include <fenv.h>
+#include <libm-alias-float.h>
+#include "math_config.h"
+
+static __attribute__ ((noinline)) float
+as_special (float x)
+{
+  uint32_t ux = asuint (x);
+  if (ux == 0x7f800000u)
+    return x; /* +inf */
+  uint32_t ax = ux << 1;
+  if (ax == 0x17fu << 24)
+    /* x+1 = 0.0 */
+    return __math_divzerof (1);
+  if (ax > 0xff000000u)
+    return x + x; /* nan */
+  return  __math_invalidf (x);
+}
+
+float
+__log10p1f (float x)
+{
+  static const double tr[] =
+    {
+      0x1p+0,         0x1.f81f82p-1,  0x1.f07c1fp-1,  0x1.e9131acp-1,
+      0x1.e1e1e1ep-1, 0x1.dae6077p-1, 0x1.d41d41dp-1, 0x1.cd85689p-1,
+      0x1.c71c71cp-1, 0x1.c0e0704p-1, 0x1.bacf915p-1, 0x1.b4e81b5p-1,
+      0x1.af286bdp-1, 0x1.a98ef6p-1,  0x1.a41a41ap-1, 0x1.9ec8e95p-1,
+      0x1.999999ap-1, 0x1.948b0fdp-1, 0x1.8f9c19p-1,  0x1.8acb90fp-1,
+      0x1.8618618p-1, 0x1.8181818p-1, 0x1.7d05f41p-1, 0x1.78a4c81p-1,
+      0x1.745d174p-1, 0x1.702e05cp-1, 0x1.6c16c17p-1, 0x1.6816817p-1,
+      0x1.642c859p-1, 0x1.605816p-1,  0x1.5c9882cp-1, 0x1.58ed231p-1,
+      0x1.5555555p-1, 0x1.51d07ebp-1, 0x1.4e5e0a7p-1, 0x1.4afd6ap-1,
+      0x1.47ae148p-1, 0x1.446f865p-1, 0x1.4141414p-1, 0x1.3e22cbdp-1,
+      0x1.3b13b14p-1, 0x1.3813814p-1, 0x1.3521cfbp-1, 0x1.323e34ap-1,
+      0x1.2f684bep-1, 0x1.2c9fb4ep-1, 0x1.29e412ap-1, 0x1.27350b9p-1,
+      0x1.2492492p-1, 0x1.21fb781p-1, 0x1.1f7047ep-1, 0x1.1cf06aep-1,
+      0x1.1a7b961p-1, 0x1.1811812p-1, 0x1.15b1e5fp-1, 0x1.135c811p-1,
+      0x1.1111111p-1, 0x1.0ecf56cp-1, 0x1.0c9715p-1,  0x1.0a6810ap-1,
+      0x1.0842108p-1, 0x1.0624dd3p-1, 0x1.041041p-1,  0x1.0204081p-1,
+      0.5
+    };
+  static const double tl[] =
+    {
+      0x1.562ec497ef351p-43, 0x1.b9476892ea99cp-8, 0x1.b5e909c959eecp-7,
+      0x1.45f4f59ec84fp-6,   0x1.af5f92cbcf2aap-6, 0x1.0ba01a6069052p-5,
+      0x1.3ed119b99dd41p-5,  0x1.714834298a088p-5, 0x1.a30a9d98309c1p-5,
+      0x1.d41d51266b9d9p-5,  0x1.02428c0f62dfcp-4, 0x1.1a23444eea521p-4,
+      0x1.31b30543f2597p-4,  0x1.48f3ed39bd5e7p-4, 0x1.5fe8049a0bd06p-4,
+      0x1.769140a6a78eap-4,  0x1.8cf1836c96595p-4, 0x1.a30a9d5551a84p-4,
+      0x1.b8de4d1ee5b21p-4,  0x1.ce6e4202c7bc9p-4, 0x1.e3bc1accaa6eap-4,
+      0x1.f8c9683b584b7p-4,  0x1.06cbd68ca86ep-3,  0x1.11142f19de3a2p-3,
+      0x1.1b3e71fa795fp-3,   0x1.254b4d37a3354p-3, 0x1.2f3b6912cab79p-3,
+      0x1.390f6831144f7p-3,  0x1.42c7e7fffb21ap-3, 0x1.4c65808c779aep-3,
+      0x1.55e8c507508c7p-3,  0x1.5f52445deb049p-3, 0x1.68a288c3efe72p-3,
+      0x1.71da17bdef98bp-3,  0x1.7af9736089c4bp-3, 0x1.84011952a11ebp-3,
+      0x1.8cf1837a7d6d1p-3,  0x1.95cb2891e3048p-3, 0x1.9e8e7b0f85651p-3,
+      0x1.a73beaa5d9dfep-3,  0x1.afd3e39454544p-3, 0x1.b856cf060c662p-3,
+      0x1.c0c5134de0c6dp-3,  0x1.c91f1371bb611p-3, 0x1.d1652ffcd2bc5p-3,
+      0x1.d997c6f634ae6p-3,  0x1.e1b733ab8fbadp-3, 0x1.e9c3ceadab4c8p-3,
+      0x1.f1bdeec438f77p-3,  0x1.f9a5e7a5f906fp-3, 0x1.00be05ac02564p-2,
+      0x1.04a054d81990cp-2,  0x1.087a083594e33p-2, 0x1.0c4b457098b4fp-2,
+      0x1.101431aa1f48ap-2,  0x1.13d4f08b98411p-2, 0x1.178da53edaecbp-2,
+      0x1.1b3e71e9f9391p-2,  0x1.1ee777defd526p-2, 0x1.2288d7b48d874p-2,
+      0x1.2622b0f52dad8p-2,  0x1.29b522a4c594cp-2, 0x1.2d404b0e305b9p-2,
+      0x1.30c4478f3f21dp-2,  0x1.34413509f6f4dp-2
+    };
+  static const union
+  {
+    float f;
+    uint32_t u;
+  } st[] =
+  {
+    { 0x0p+0 },        { 0x1.2p+3 },      { 0x1.8cp+6 },
+    { 0x1.f38p+9 },    { 0x1.3878p+13 },  { 0x1.869fp+16 },
+    { 0x1.e847ep+19 }, { 0x1.312cfep+23 }
+  };
+  double z = x;
+  uint32_t ux = asuint (x);
+  if (__glibc_unlikely (ux >= 0x17fu << 23)) /* x <= -1 */
+    return as_special (x);
+  uint32_t ax = ux & (~0u >> 1);
+  if (__glibc_unlikely (ax == 0))
+    return copysign (0, x);
+  if (__glibc_unlikely (ax >= (0xff << 23))) /* +inf, nan */
+    return as_special (x);
+  int ie = ux;
+  ie >>= 23;
+  unsigned int je = ie - 126;
+  je = (je * 0x9a209a8) >> 29;
+  if (__glibc_unlikely (ux == st[je].u))
+    return je;
+
+  uint64_t tz = asuint64 (z + 1.0);
+  uint64_t m = tz & (~(uint64_t) 0 >> 12);
+  int32_t e = (tz >> 52) - 1023, j = ((m + ((int64_t) 1 << 45)) >> 46);
+  tz = m | ((uint64_t) 0x3ff << 52);
+  double ix = tr[j], l = tl[j];
+  double off = e * 0x1.34413509f79ffp-2 + l;
+  double v = asdouble (tz) * ix - 1;
+
+  static const double h[] =
+    {
+      0x1.bcb7b150bf6d8p-2, -0x1.bcb7b1738c07ep-3,
+      0x1.287de19e795c5p-3, -0x1.bca44edc44bc4p-4
+    };
+  double v2 = v * v;
+  double f = (h[0] + v * h[1]) + v2 * (h[2] + v * h[3]);
+  double r = off + v * f;
+  float ub = r;
+  float lb = r + 0x1.5cp-42;
+  if (__glibc_unlikely (ub != lb))
+    {
+      if (__glibc_unlikely (ax < 0x3d32743eu))
+	{ /* 0x1.64e87cp-5f */
+	  if (__glibc_unlikely (ux == 0xa6aba8afu))
+	    return -0x1.2a33bcp-51f + 0x1p-76f;
+	  if (__glibc_unlikely (ux == 0xaf39b9a7u))
+	    return -0x1.42a342p-34f + 0x1p-59f;
+	  if (__glibc_unlikely (ux == 0x399a7c00u))
+	    return 0x1.0c53cap-13f + 0x1p-38f;
+	  z /= 2.0 + z;
+	  double z2 = z * z, z4 = z2 * z2;
+	  static const double c[] =
+	    {
+	      0x1.bcb7b1526e50fp-1, 0x1.287a76370129dp-2,
+	      0x1.63c62378fa3dbp-3, 0x1.fca4139a42374p-4
+	    };
+	  float ret = z * ((c[0] + z2 * c[1]) + z4 * (c[2] + z2 * c[3]));
+	  if (x != 0.0f && ret == 0.0)
+	    __set_errno (ERANGE);
+	  return ret;
+	}
+      if (__glibc_unlikely (ux == 0x7956ba5eu))
+	return 0x1.16bebap+5f + 0x1p-20f;
+      if (__glibc_unlikely (ux == 0xbd86ffb9u))
+	return -0x1.e53536p-6f + 0x1p-31f;
+      static const double c[] =
+	{
+	  0x1.bcb7b1526e50ep-2,  -0x1.bcb7b1526e53dp-3, 0x1.287a7636f3fa2p-3,
+	  -0x1.bcb7b146a14b3p-4,  0x1.63c627d5219cbp-4, -0x1.2880736c8762dp-4,
+	  0x1.fc1ecf913961ap-5
+	};
+      f = v
+	  * ((c[0] + v * c[1])
+	     + v2 * ((c[2] + v * c[3]) + v2 * (c[4] + v * c[5] + v2 * c[6])));
+      f += l - tl[0];
+      double el = e * 0x1.34413509f79ffp-2;
+      r = el + f;
+      ub = r;
+    }
+  return ub;
+}
+libm_alias_float (__log10p1, log10p1)
diff --git a/sysdeps/ieee754/flt-32/s_log1pf.c b/sysdeps/ieee754/flt-32/s_log1pf.c
index 555f0f82c8..d1686e78aa 100644
--- a/sysdeps/ieee754/flt-32/s_log1pf.c
+++ b/sysdeps/ieee754/flt-32/s_log1pf.c
@@ -1,116 +1,181 @@
-/* s_log1pf.c -- float version of s_log1p.c.
- */
+/* Correctly-rounded biased argument natural logarithm function for binary32
+   value.
 
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
+Copyright (c) 2023, 2024  Alexei Sibidanov.
 
-#include <float.h>
-#include <math.h>
-#include <math-barriers.h>
-#include <math_private.h>
-#include <math-underflow.h>
-#include <libc-diag.h>
+This file is part of the CORE-MATH project
+project (file src/binary32/log1p/log1pf.c revision bc385c2).
 
-static const float
-ln2_hi =   6.9313812256e-01,	/* 0x3f317180 */
-ln2_lo =   9.0580006145e-06,	/* 0x3717f7d1 */
-two25 =    3.355443200e+07,	/* 0x4c000000 */
-Lp1 = 6.6666668653e-01,	/* 3F2AAAAB */
-Lp2 = 4.0000000596e-01,	/* 3ECCCCCD */
-Lp3 = 2.8571429849e-01, /* 3E924925 */
-Lp4 = 2.2222198546e-01, /* 3E638E29 */
-Lp5 = 1.8183572590e-01, /* 3E3A3325 */
-Lp6 = 1.5313838422e-01, /* 3E1CD04F */
-Lp7 = 1.4798198640e-01; /* 3E178897 */
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
 
-static const float zero = 0.0;
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
 
-float
-__log1pf(float x)
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#include <math.h>
+#include <stdint.h>
+#include <errno.h>
+#include <libm-alias-float.h>
+#include "math_config.h"
+
+static __attribute__ ((noinline)) float
+as_special (float x)
 {
-	float hfsq,f,c,s,z,R,u;
-	int32_t k,hx,hu,ax;
+  uint32_t t = asuint (x);
+  if (t == 0xbf800000u)
+    return __math_divzerof (1);
+  if (t == 0x7f800000u)
+    return x; /* +inf */
+  uint32_t ax = t << 1;
+  if (ax > 0xff000000u)
+    return x + x; /* nan */
+  return __math_invalidf (0.0f);
+}
 
-	GET_FLOAT_WORD(hx,x);
-	ax = hx&0x7fffffff;
+float
+__log1pf (float x)
+{
+  static const double x0[] =
+    {
+      0x1.f81f82p-1,  0x1.e9131acp-1, 0x1.dae6077p-1, 0x1.cd85689p-1,
+      0x1.c0e0704p-1, 0x1.b4e81b5p-1, 0x1.a98ef6p-1,  0x1.9ec8e95p-1,
+      0x1.948b0fdp-1, 0x1.8acb90fp-1, 0x1.8181818p-1, 0x1.78a4c81p-1,
+      0x1.702e05cp-1, 0x1.6816817p-1, 0x1.605816p-1,  0x1.58ed231p-1,
+      0x1.51d07ebp-1, 0x1.4afd6ap-1,  0x1.446f865p-1, 0x1.3e22cbdp-1,
+      0x1.3813814p-1, 0x1.323e34ap-1, 0x1.2c9fb4ep-1, 0x1.27350b9p-1,
+      0x1.21fb781p-1, 0x1.1cf06aep-1, 0x1.1811812p-1, 0x1.135c811p-1,
+      0x1.0ecf56cp-1, 0x1.0a6810ap-1, 0x1.0624dd3p-1, 0x1.0204081p-1
+    };
+  static const double lixb[] =
+    {
+      0x1.fc0a8909b4218p-7, 0x1.77458f51aac89p-5, 0x1.341d793afb997p-4,
+      0x1.a926d3a5ebd2ap-4, 0x1.0d77e7a8a823dp-3, 0x1.44d2b6c557102p-3,
+      0x1.7ab89040accecp-3, 0x1.af3c94ecab3d6p-3, 0x1.e27076d54e6c9p-3,
+      0x1.0a324e3888ad5p-2, 0x1.22941fc0c7357p-2, 0x1.3a64c56ae3fdbp-2,
+      0x1.51aad874af21fp-2, 0x1.686c81d300eap-2,  0x1.7eaf83c7fa9b5p-2,
+      0x1.947941aa610ecp-2, 0x1.a9cec9a3f023bp-2, 0x1.beb4d9ea4156ep-2,
+      0x1.d32fe7f35e5c7p-2, 0x1.e7442617b817ap-2, 0x1.faf588dd5ed1p-2,
+      0x1.0723e5c635c39p-1, 0x1.109f39d53c99p-1,  0x1.19ee6b38a4668p-1,
+      0x1.23130d7f93c3bp-1, 0x1.2c0e9ec9b0b85p-1, 0x1.34e289cb35eccp-1,
+      0x1.3d9026ad3d3f3p-1, 0x1.4618bc1eadbbbp-1, 0x1.4e7d8127dd8a9p-1,
+      0x1.56bf9d5967092p-1, 0x1.5ee02a926936ep-1
+    };
+  static const double lix[] =
+    {
+      0x1.fc0a890fc03e4p-7, 0x1.77458f532dcfcp-5, 0x1.341d793bbd1d1p-4,
+      0x1.a926d3a6ad563p-4, 0x1.0d77e7a908e59p-3, 0x1.44d2b6c5b7d1ep-3,
+      0x1.7ab890410d909p-3, 0x1.af3c94ed0bff3p-3, 0x1.e27076d5af2e6p-3,
+      0x1.0a324e38b90e3p-2, 0x1.22941fc0f7966p-2, 0x1.3a64c56b145eap-2,
+      0x1.51aad874df82dp-2, 0x1.686c81d3314afp-2, 0x1.7eaf83c82afc3p-2,
+      0x1.947941aa916fbp-2, 0x1.a9cec9a42084ap-2, 0x1.beb4d9ea71b7cp-2,
+      0x1.d32fe7f38ebd5p-2, 0x1.e7442617e8788p-2, 0x1.faf588dd8f31fp-2,
+      0x1.0723e5c64df4p-1,  0x1.109f39d554c97p-1, 0x1.19ee6b38bc96fp-1,
+      0x1.23130d7fabf43p-1, 0x1.2c0e9ec9c8e8cp-1, 0x1.34e289cb4e1d3p-1,
+      0x1.3d9026ad556fbp-1, 0x1.4618bc1ec5ec2p-1, 0x1.4e7d8127f5bb1p-1,
+      0x1.56bf9d597f399p-1, 0x1.5ee02a9281675p-1
+    };
+  static const double b[] =
+    {
+      0x1p+0,
+      -0x1p-1,
+      0x1.5555555556f6bp-2,
+      -0x1.00000000029b9p-2,
+      0x1.9999988d176e4p-3,
+      -0x1.55555418889a7p-3,
+      0x1.24adeca50e2bcp-3,
+      -0x1.001ba33bf57cfp-3
+    };
 
-	k = 1;
-	if (hx < 0x3ed413d7) {			/* x < 0.41422  */
-	    if(ax>=0x3f800000) {		/* x <= -1.0 */
-		if(x==(float)-1.0) return -two25/zero; /* log1p(-1)=-inf */
-		else return (x-x)/(x-x);	/* log1p(x<-1)=NaN */
-	    }
-	    if(ax<0x31000000) {			/* |x| < 2**-29 */
-		math_force_eval(two25+x);	/* raise inexact */
-		if (ax<0x24800000)		/* |x| < 2**-54 */
-		  {
-		    math_check_force_underflow (x);
-		    return x;
-		  }
-		else
-		    return x - x*x*(float)0.5;
-	    }
-	    if(hx>0||hx<=((int32_t)0xbe95f61f)) {
-		k=0;f=x;hu=1;}	/* -0.2929<x<0.41422 */
+  double z = x;
+  uint32_t ux = asuint (x);
+  uint32_t ax = ux & (~0u >> 1);
+  if (__glibc_likely (ax < 0x3c880000))
+    {
+      if (__glibc_unlikely (ax < 0x33000000))
+	{
+	  if (!ax)
+	    return x;
+	  return fmaf (x, -x, x);
 	}
-	if (hx >= 0x7f800000) return x+x;
-	if(k!=0) {
-	    if(hx<0x5a000000) {
-		u  = (float)1.0+x;
-		GET_FLOAT_WORD(hu,u);
-		k  = (hu>>23)-127;
-		/* correction term */
-		c  = (k>0)? (float)1.0-(u-x):x-(u-(float)1.0);
-		c /= u;
-	    } else {
-		u  = x;
-		GET_FLOAT_WORD(hu,u);
-		k  = (hu>>23)-127;
-		c  = 0;
-	    }
-	    hu &= 0x007fffff;
-	    if(hu<0x3504f7) {
-		SET_FLOAT_WORD(u,hu|0x3f800000);/* normalize u */
-	    } else {
-		k += 1;
-		SET_FLOAT_WORD(u,hu|0x3f000000);	/* normalize u/2 */
-		hu = (0x00800000-hu)>>2;
+      double z2 = z * z, z4 = z2 * z2;
+      double f = z2
+		 * ((b[1] + z * b[2]) + z2 * (b[3] + z * b[4])
+		    + z4 * ((b[5] + z * b[6]) + z2 * b[7]));
+      double r = z + f;
+      if (__glibc_unlikely ((asuint64 (r) & 0xfffffffll) == 0))
+	r += 0x1p14 * (f + (z - r));
+      return r;
+    }
+  else
+    {
+      if (__glibc_unlikely (ux >= 0xbf800000u || ax >= 0x7f800000))
+	return as_special (x);
+      uint64_t tp = asuint64 (z + 1);
+      int e = tp >> 52;
+      uint64_t m52 = tp & (~(uint64_t) 0 >> 12);
+      unsigned int j = (tp >> (52 - 5)) & 31;
+      e -= 0x3ff;
+      double xd = asdouble (m52 | ((uint64_t) 0x3ff << 52));
+      z = xd * x0[j] - 1;
+      static const double c[] =
+	{
+	  -0x1.3902c33434e7fp-43, 0x1.ffffffe1cbed5p-1, -0x1.ffffff7d1b014p-2,
+	  0x1.5564e0ed3613ap-2, -0x1.0012232a00d4ap-2
+	};
+      const double ln2 = 0x1.62e42fefa39efp-1;
+      double z2 = z * z,
+	     r = (ln2 * e + lixb[j])
+		 + z * ((c[1] + z * c[2]) + z2 * (c[3] + z * c[4]));
+      float ub = r;
+      float lb = r + 2.2e-11;
+      if (__glibc_unlikely (ub != lb))
+	{
+	  double z4 = z2 * z2,
+		 f = z
+		     * ((b[0] + z * b[1]) + z2 * (b[2] + z * b[3])
+			+ z4 * ((b[4] + z * b[5]) + z2 * (b[6] + z * b[7])));
+	  const double ln2l = 0x1.7f7d1cf79abcap-20, ln2h = 0x1.62e4p-1;
+	  double Lh = ln2h * e;
+	  double Ll = ln2l * e;
+	  double rl = f + Ll + lix[j];
+	  double tr = rl + Lh;
+	  if (__glibc_unlikely ((asuint64 (tr) & 0xfffffffll) == 0))
+	    {
+	      if (x == -0x1.247ab0p-6)
+		return -0x1.271f0ep-6f - 0x1p-31f;
+	      if (x == -0x1.3a415ep-5)
+		return -0x1.407112p-5f + 0x1p-30f;
+	      if (x == 0x1.fb035ap-2)
+		return 0x1.9bddc2p-2f + 0x1p-27f;
+	      tr += 64 * (rl + (Lh - tr));
 	    }
-	    f = u-(float)1.0;
-	}
-	hfsq=(float)0.5*f*f;
-	if(hu==0) {	/* |f| < 2**-20 */
-	    if(f==zero) {
-		if(k==0) return zero;
-		else {c += k*ln2_lo; return k*ln2_hi+c;}
+	  else if (rl + (Lh - tr) == 0.0)
+	    {
+	      if (x == 0x1.b7fd86p-4)
+		return 0x1.a1ece2p-4f + 0x1p-29f;
+	      if (x == -0x1.3a415ep-5)
+		return -0x1.407112p-5f + 0x1p-30f;
+	      if (x == 0x1.43c7e2p-6)
+		return 0x1.409f80p-6f + 0x1p-31f;
 	    }
-	    R = hfsq*(1.0f-0.66666666666666666f*f);
-	    if(k==0) return f-R; else
-		     return k*ln2_hi-((R-(k*ln2_lo+c))-f);
+	  ub = tr;
 	}
-	s = f/((float)2.0+f);
-	z = s*s;
-	R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7))))));
-	if (k == 0)
-	  return f - (hfsq - s * (hfsq + R));
-	else
-	  {
-	    /* With GCC 7 when compiling with -Os the compiler warns
-	       that c might be used uninitialized.  This can't be true
-	       because k must be 0 for c to be uninitialized and we
-	       handled that computation earlier without using c.  */
-	    DIAG_PUSH_NEEDS_COMMENT;
-	    DIAG_IGNORE_Os_NEEDS_COMMENT (7, "-Wmaybe-uninitialized");
-	    return k * ln2_hi - ((hfsq - (s * (hfsq + R)
-					  + (k * ln2_lo + c))) - f);
-	    DIAG_POP_NEEDS_COMMENT;
-	  }
+      return ub;
+    }
 }
+libm_alias_float (__log1p, log1p)
+strong_alias (__log1pf, __logp1f)
+libm_alias_float (__logp1, logp1)
diff --git a/sysdeps/ieee754/flt-32/s_log2p1f.c b/sysdeps/ieee754/flt-32/s_log2p1f.c
new file mode 100644
index 0000000000..09e77dc08a
--- /dev/null
+++ b/sysdeps/ieee754/flt-32/s_log2p1f.c
@@ -0,0 +1,248 @@
+/* Correctly-rounded biased argument natural logarithm function for binary32
+   value.
+
+Copyright (c) 2022-2024 Alexei Sibidanov.
+
+This file is part of the CORE-MATH project
+project (file src/binary32/log2p1/log2p1f.c revision bc385c2).
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#include <errno.h>
+#include <math.h>
+#include <math-underflow.h>
+#include <libm-alias-float.h>
+#include "math_config.h"
+
+float
+__log2p1f (float x)
+{
+  static const double ix[] =
+    {
+      0x1p+0,           0x1.fc07f01fcp-1, 0x1.f81f81f82p-1,
+      0x1.f44659e4ap-1, 0x1.f07c1f07cp-1, 0x1.ecc07b302p-1,
+      0x1.e9131abfp-1,  0x1.e573ac902p-1, 0x1.e1e1e1e1ep-1,
+      0x1.de5d6e3f8p-1, 0x1.dae6076bap-1, 0x1.d77b654b8p-1,
+      0x1.d41d41d42p-1, 0x1.d0cb58f6ep-1, 0x1.cd8568904p-1,
+      0x1.ca4b3055ep-1, 0x1.c71c71c72p-1, 0x1.c3f8f01c4p-1,
+      0x1.c0e070382p-1, 0x1.bdd2b8994p-1, 0x1.bacf914c2p-1,
+      0x1.b7d6c3ddap-1, 0x1.b4e81b4e8p-1, 0x1.b2036406cp-1,
+      0x1.af286bca2p-1, 0x1.ac5701ac6p-1, 0x1.a98ef606ap-1,
+      0x1.a6d01a6dp-1,  0x1.a41a41a42p-1, 0x1.a16d3f97ap-1,
+      0x1.9ec8e951p-1,  0x1.9c2d14ee4p-1, 0x1.99999999ap-1,
+      0x1.970e4f80cp-1, 0x1.948b0fcd6p-1, 0x1.920fb49dp-1,
+      0x1.8f9c18f9cp-1, 0x1.8d3018d3p-1,  0x1.8acb90f6cp-1,
+      0x1.886e5f0acp-1, 0x1.861861862p-1, 0x1.83c977ab2p-1,
+      0x1.818181818p-1, 0x1.7f405fd02p-1, 0x1.7d05f417ep-1,
+      0x1.7ad2208ep-1,  0x1.78a4c8178p-1, 0x1.767dce434p-1,
+      0x1.745d1745ep-1, 0x1.724287f46p-1, 0x1.702e05c0cp-1,
+      0x1.6e1f76b44p-1, 0x1.6c16c16c2p-1, 0x1.6a13cd154p-1,
+      0x1.681681682p-1, 0x1.661ec6a52p-1, 0x1.642c8590cp-1,
+      0x1.623fa7702p-1, 0x1.605816058p-1, 0x1.5e75bb8dp-1,
+      0x1.5c9882b94p-1, 0x1.5ac056b02p-1, 0x1.58ed23082p-1,
+      0x1.571ed3c5p-1,  0x1.555555556p-1, 0x1.5390948f4p-1,
+      0x1.51d07eae2p-1, 0x1.501501502p-1, 0x1.4e5e0a73p-1,
+      0x1.4cab88726p-1, 0x1.4afd6a052p-1, 0x1.49539e3b2p-1,
+      0x1.47ae147aep-1, 0x1.460cbc7f6p-1, 0x1.446f86562p-1,
+      0x1.42d6625d6p-1, 0x1.414141414p-1, 0x1.3fb013fbp-1,
+      0x1.3e22cbce4p-1, 0x1.3c995a47cp-1, 0x1.3b13b13b2p-1,
+      0x1.3991c2c18p-1, 0x1.381381382p-1, 0x1.3698df3dep-1,
+      0x1.3521cfb2cp-1, 0x1.33ae45b58p-1, 0x1.323e34a2cp-1,
+      0x1.30d19013p-1,  0x1.2f684bda2p-1, 0x1.2e025c04cp-1,
+      0x1.2c9fb4d82p-1, 0x1.2b404ad02p-1, 0x1.29e4129e4p-1,
+      0x1.288b01288p-1, 0x1.27350b882p-1, 0x1.25e22708p-1,
+      0x1.24924924ap-1, 0x1.23456789ap-1, 0x1.21fb78122p-1,
+      0x1.20b470c68p-1, 0x1.1f7047dc2p-1, 0x1.1e2ef3b4p-1,
+      0x1.1cf06ada2p-1, 0x1.1bb4a4046p-1, 0x1.1a7b9611ap-1,
+      0x1.19453808cp-1, 0x1.181181182p-1, 0x1.16e068942p-1,
+      0x1.15b1e5f76p-1, 0x1.1485f0e0ap-1, 0x1.135c81136p-1,
+      0x1.12358e75ep-1, 0x1.111111112p-1, 0x1.0fef010fep-1,
+      0x1.0ecf56be6p-1, 0x1.0db20a89p-1,  0x1.0c9714fbcp-1,
+      0x1.0b7e6ec26p-1, 0x1.0a6810a68p-1, 0x1.0953f3902p-1,
+      0x1.084210842p-1, 0x1.073260a48p-1, 0x1.0624dd2f2p-1,
+      0x1.05197f7d8p-1, 0x1.041041042p-1, 0x1.03091b52p-1,
+      0x1.020408102p-1, 0x1.01010101p-1,  0x1p-1
+    };
+
+  static const double lix[] = {
+      0x0p+0,               -0x1.6fe50b6f1eafap-7, -0x1.6e79685c160d5p-6,
+     -0x1.11cd1d51955bap-5, -0x1.6bad37591e03p-5,  -0x1.c4dfab908ddb5p-5,
+     -0x1.0eb389fab4795p-4, -0x1.3aa2fdd26ae99p-4, -0x1.663f6faca846bp-4,
+     -0x1.918a16e4cb157p-4, -0x1.bc84240a78a13p-4, -0x1.e72ec1181cfb1p-4,
+     -0x1.08c588cd964e4p-3, -0x1.1dcd19759f2e3p-3, -0x1.32ae9e27627c6p-3,
+     -0x1.476a9f989a58ap-3, -0x1.5c01a39fa6533p-3, -0x1.70742d4eed455p-3,
+     -0x1.84c2bd02d6434p-3, -0x1.98edd077e9f0ap-3, -0x1.acf5e2db31eeap-3,
+     -0x1.c0db6cddaa82dp-3, -0x1.d49ee4c33121ap-3, -0x1.e840be751d775p-3,
+     -0x1.fbc16b9003e0bp-3, -0x1.0790adbae3fcp-2,  -0x1.11307dad465b5p-2,
+     -0x1.1ac05b2924cc5p-2, -0x1.24407ab0cc41p-2,  -0x1.2db10fc4ea424p-2,
+     -0x1.37124cea58697p-2, -0x1.406463b1d455dp-2, -0x1.49a784bcbaa37p-2,
+     -0x1.52dbdfc4f341dp-2, -0x1.5c01a39ff2c9bp-2, -0x1.6518fe46abaa5p-2,
+     -0x1.6e221cd9d6933p-2, -0x1.771d2ba7f5791p-2, -0x1.800a56315ee2ap-2,
+     -0x1.88e9c72df8611p-2, -0x1.91bba891d495fp-2, -0x1.9a8023920fa4dp-2,
+     -0x1.a33760a7fbca6p-2, -0x1.abe18797d2effp-2, -0x1.b47ebf734b923p-2,
+     -0x1.bd0f2e9eb2b84p-2, -0x1.c592fad2be1aap-2, -0x1.ce0a4923cf5e6p-2,
+     -0x1.d6753e02f4ebcp-2, -0x1.ded3fd445afp-2,   -0x1.e726aa1e558fep-2,
+     -0x1.ef6d67325ba38p-2, -0x1.f7a8568c8aea6p-2, -0x1.ffd799a81be87p-2,
+     0x1.f804ae8d33c4p-2,    0x1.efec61b04af4ep-2,  0x1.e7df5fe572606p-2,
+     0x1.dfdd89d5b0009p-2,   0x1.d7e6c0abbd924p-2,  0x1.cffae611a74d6p-2,
+     0x1.c819dc2d8578cp-2,   0x1.c043859e5bdbcp-2,  0x1.b877c57b47c04p-2,
+     0x1.b0b67f4f29a66p-2,   0x1.a8ff97183ed07p-2,  0x1.a152f14293c74p-2,
+     0x1.99b072a9289cap-2,   0x1.921800927e284p-2,  0x1.8a8980ac4113p-2,
+     0x1.8304d90c2859dp-2,   0x1.7b89f02cbd49ap-2,  0x1.7418aceb84ab1p-2,
+     0x1.6cb0f68656c95p-2,   0x1.6552b49993dc2p-2,  0x1.5dfdcf1eacd7bp-2,
+     0x1.56b22e6b97c18p-2,   0x1.4f6fbb2ce6943p-2,  0x1.48365e6957b42p-2,
+     0x1.4106017c0dbcfp-2,   0x1.39de8e15727d9p-2,  0x1.32bfee37489bcp-2,
+     0x1.2baa0c34989c3p-2,   0x1.249cd2b177fd5p-2,  0x1.1d982c9d50468p-2,
+     0x1.169c0536677acp-2,   0x1.0fa848045f67bp-2,  0x1.08bce0d9a7c6p-2,
+     0x1.01d9bbcf66a2cp-2,   0x1.f5fd8a90e2d85p-3,  0x1.e857d3d3af1e5p-3,
+     0x1.dac22d3ec5f4ep-3,   0x1.cd3c712db459ap-3,  0x1.bfc67a7ff3c22p-3,
+     0x1.b2602497678f4p-3,   0x1.a5094b555a1f8p-3,  0x1.97c1cb136b96fp-3,
+     0x1.8a8980ac8652dp-3,   0x1.7d60496c83f66p-3,  0x1.7046031c7cdafp-3,
+     0x1.633a8bf460335p-3,   0x1.563dc2a08b102p-3,  0x1.494f863bbc1dep-3,
+     0x1.3c6fb6507a37ep-3,   0x1.2f9e32d5257ecp-3,  0x1.22dadc2a627efp-3,
+     0x1.1625931802e49p-3,   0x1.097e38cef9519p-3,  0x1.f9c95dc138295p-4,
+     0x1.e0b1ae90505f6p-4,   0x1.c7b528b5fcffap-4,  0x1.aed391abb17a1p-4,
+     0x1.960caf9bd35eap-4,   0x1.7d60496e3edebp-4,  0x1.64ce26bf2108ep-4,
+     0x1.4c560fe5b573bp-4,   0x1.33f7cde24adfbp-4,  0x1.1bb32a5ed9353p-4,
+     0x1.0387efbd3006ep-4,   0x1.d6ebd1f1d0955p-5,  0x1.a6f9c37a8beabp-5,
+     0x1.77394c9d6762cp-5,   0x1.47aa07358e1a4p-5,  0x1.184b8e4d490efp-5,
+     0x1.d23afc4d95c78p-6,   0x1.743ee8678a7cbp-6,  0x1.16a21e243bf78p-6,
+     0x1.72c7ba20c907ep-7,   0x1.720d9c0536e17p-8,  0x0p+0
+  };
+
+  double z = x;
+  uint32_t ux = asuint (x);
+  uint32_t ax = ux & (~0u >> 1);
+  if (__glibc_unlikely (ux >= 0x17fu << 23))
+    { /* x <= -1 */
+      if (ux == (0x17fu << 23))
+	return __math_divzerof (1);
+      if (ux > (0x1ffu << 23))
+	return x + x;		   /* nan */
+      return __math_invalidf (x);
+    }
+  else if (__glibc_unlikely (ax >= (0xff << 23)))
+    { /* +inf, nan  */
+      if (ax > (0xff << 23))
+	return x + x; /* nan  */
+      return INFINITY;
+    }
+  else if (__glibc_likely (ax < 0x3cb7aa26u))
+    { /* |x| < 0x1.6f544cp-6  */
+      double z2 = z * z, z4 = z2 * z2;
+      if ( __glibc_likely (ax < 0x3b9d9d34u))
+	{ /* |x| < 0x1.3b3a68p-8 */
+	  if (__glibc_likely (ax < 0x39638a7eu))
+	    { /* |x| < 0x1.c714fcp-13 */
+	      if (__glibc_likely (ax < 0x329c5639u))
+		{ /* |x| < 0x1.38ac72p-26 */
+		  static const double c[] =
+		    {
+		      0x1.71547652b82fep+0, -0x1.71547652b82ffp-1
+		    };
+		  return z * (c[0] + z * c[1]);
+		}
+	      else
+		{
+		  if (__glibc_unlikely (ux == 0x32ff7045u))
+		    return 0x1.70851ap-25f - 0x1.8p-80f;
+		  if (__glibc_unlikely (ux == 0xb395efbbu))
+		    return -0x1.b0a00ap-24f + 0x1p-76f;
+		  if (__glibc_unlikely (ux == 0x35a14df7u))
+		    return 0x1.d16d2p-20f + 0x1p-72f;
+		  if (__glibc_unlikely (ux == 0x3841cb81u))
+		    return 0x1.17949ep-14f + 0x1p-67f;
+		  static const double c[] =
+		    {
+		      0x1.71547652b82fep+0, -0x1.71547652b82fdp-1,
+		      0x1.ec709ead0c9a7p-2, -0x1.7154773c1cb29p-2
+		    };
+		  return z * ((c[0] + z * c[1]) + z2 * (c[2] + z * c[3]));
+		}
+	    }
+	  else
+	    {
+	      if (__glibc_unlikely (ux == 0xbac9363du))
+		return -0x1.2282aap-9f + 0x1p-61f;
+	      static const double c[] =
+		{
+		  0x1.71547652b82fep+0, -0x1.71547652b83p-1,
+		  0x1.ec709dc28f51bp-2, -0x1.7154765157748p-2,
+		  0x1.2778a510a3682p-2, -0x1.ec745df1551fcp-3
+		};
+	      return z
+		     * ((c[0] + z * c[1]) + z2 * (c[2] + z * c[3])
+			+ z4 * ((c[4] + z * c[5])));
+	    }
+	}
+      else
+	{
+	  static const double c[] =
+	    {
+	      0x1.71547652b82fep+0, -0x1.71547652b82fbp-1,
+	      0x1.ec709dc3b6a73p-2, -0x1.71547652dc09p-2,
+	      0x1.2776c1a88901p-2,  -0x1.ec7095bd4d208p-3,
+	      0x1.a66bec7fc8f7p-3,  -0x1.71a900fc3f3f9p-3
+	    };
+	  return z
+		 * ((c[0] + z * c[1]) + z2 * (c[2] + z * c[3])
+		    + z4 * ((c[4] + z * c[5]) + z2 * (c[6] + z * c[7])));
+	}
+    }
+  else
+    { /* |x| >= 0x1.6f544cp-6 */
+      float h, l;
+      /* With gcc 6.3.0, if we return 0x1.e90026p+4f + 0x1.fp-21
+	 in the second exceptional case, with rounding up it yields
+	 0x1.e90026p+4 which is incorrect, thus we use this workaround. See
+	 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112367. */
+      if (__glibc_unlikely (ux == 0x52928e33u))
+	{
+	  h = 0x1.318ffap+5f;
+	  l = 0x1.fp-20f;
+	  return h + l;
+	}
+      if (__glibc_unlikely (ux == 0x4ebd09e3u))
+	{
+	  h = 0x1.e90026p+4f;
+	  l = 0x1.fp-21;
+	  return h + l;
+	}
+      uint64_t tp = asuint64 (z + 1.0);
+      uint64_t m = tp & (~(uint64_t) 0 >> 12);
+      int e = (tp >> 52) - 0x3ff;
+      int j = (m + ((int64_t) 1 << (52 - 8))) >> (52 - 7), k = j > 53;
+      e += k;
+      double xd = asdouble (m | (uint64_t) 0x3ff << 52);
+      z = fma (xd, ix[j], -1.0);
+      static const double c[] =
+	{
+	   0x1.71547652b82fep+0, -0x1.71547652b82ffp-1,  0x1.ec709dc32988bp-2,
+	  -0x1.715476521ec2bp-2,  0x1.277801a1ad904p-2, -0x1.ec731704d6a88p-3
+	};
+      double z2 = z * z;
+      double c0 = c[0] + z * c[1];
+      double c2 = c[2] + z * c[3];
+      double c4 = c[4] + z * c[5];
+      c0 += z2 * (c2 + z2 * c4);
+      return (z * c0 - lix[j]) + e;
+    }
+}
+libm_alias_float (__log2p1, log2p1)
diff --git a/sysdeps/ieee754/flt-32/w_log1pf.c b/sysdeps/ieee754/flt-32/w_log1pf.c
new file mode 100644
index 0000000000..1cc8931700
--- /dev/null
+++ b/sysdeps/ieee754/flt-32/w_log1pf.c
@@ -0,0 +1 @@
+/* Not needed.  */