]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
math: Use cbrtf from CORE-MATH
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Mon, 28 Oct 2024 15:38:50 +0000 (12:38 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Fri, 22 Nov 2024 13:01:03 +0000 (10:01 -0300)
The CORE-MATH implementation is correctly rounded (for any rounding mode)
and shows better performance to the generic cbrtf.

The code was adapted to glibc style and to use the definition of
math_config.h.

Benchtest on x64_64 (Ryzen 9 5900X, gcc 14.2.1), aarch64 (M1,
gcc 13.2.1), and powerpc (POWER10, gcc 13.2.1):

latency                       master        patched       improvement
x86_64                       68.6348        36.8908            46.25%
x86_64v2                     67.3418        36.6968            45.51%
x86_64v3                     63.4981        32.7859            48.37%
aarch64                      29.3172        12.1496            58.56%
power10                      18.0845         8.8893            50.85%
powerpc                      18.0859        8.79527            51.37%

reciprocal-throughput         master        patched       improvement
x86_64                       36.4369        13.3565            63.34%
x86_64v2                     37.3611        13.1149            64.90%
x86_64v3                     31.6024        11.2102            64.53%
aarch64                      18.6866        7.3474             60.68%
power10                       9.4758        3.6329             61.66%
powerpc                      9.58896        3.90439            59.28%

Signed-off-by: Alexei Sibidanov <sibid@uvic.ca>
Signed-off-by: Paul Zimmermann <Paul.Zimmermann@inria.fr>
Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
26 files changed:
SHARED-FILES
sysdeps/aarch64/libm-test-ulps
sysdeps/alpha/fpu/libm-test-ulps
sysdeps/arc/fpu/libm-test-ulps
sysdeps/arc/nofpu/libm-test-ulps
sysdeps/arm/libm-test-ulps
sysdeps/csky/fpu/libm-test-ulps
sysdeps/csky/nofpu/libm-test-ulps
sysdeps/hppa/fpu/libm-test-ulps
sysdeps/ieee754/flt-32/s_cbrtf.c
sysdeps/loongarch/lp64/libm-test-ulps
sysdeps/m68k/m680x0/fpu/libm-test-ulps
sysdeps/microblaze/libm-test-ulps
sysdeps/mips/mips32/libm-test-ulps
sysdeps/mips/mips64/libm-test-ulps
sysdeps/nios2/libm-test-ulps
sysdeps/or1k/fpu/libm-test-ulps
sysdeps/or1k/nofpu/libm-test-ulps
sysdeps/powerpc/fpu/libm-test-ulps
sysdeps/powerpc/nofpu/libm-test-ulps
sysdeps/riscv/nofpu/libm-test-ulps
sysdeps/riscv/rvd/libm-test-ulps
sysdeps/s390/fpu/libm-test-ulps
sysdeps/sh/libm-test-ulps
sysdeps/sparc/fpu/libm-test-ulps
sysdeps/x86_64/fpu/libm-test-ulps

index 228f415dfdee742825087f1f785959ec877fc8b6..d367f4b62f441a963b4849ea455d772eb8ba726d 100644 (file)
@@ -268,3 +268,7 @@ sysdeps/ieee754/flt-32/s_log10p1f.c
   (file src/binary32/log10p1/log10p1f.c in CORE-MATH)
   - The code was adapted to use glibc code style and internal
     functions to handle errno, overflow, and underflow.
+sysdeps/ieee754/flt-32/s_cbrtf.c
+  (file src/binary32/cbrt/cbrtf.c in CORE-MATH)
+  - The code was adapted to use glibc code style and internal
+    functions to handle errno, overflow, and underflow.
index c523d45802edabd29f1aa4955a9c4d693d9a171a..4979769b5894d209881a6fe93018c8216bb5e393 100644 (file)
@@ -474,7 +474,6 @@ ldouble: 2
 
 Function: "cbrt":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_advsimd":
@@ -483,7 +482,6 @@ float: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_sve":
@@ -492,12 +490,10 @@ float: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 ldouble: 1
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 ldouble: 1
 
 Function: Real part of "ccos":
index 212c52c8cc578f94700905b96c7e55d2a213967f..a2b5404f9d274a5fade0e9fb01a29bf3426e340c 100644 (file)
@@ -417,22 +417,18 @@ ldouble: 2
 
 Function: "cbrt":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 ldouble: 1
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 ldouble: 1
 
 Function: Real part of "ccos":
index 7812a11b5b321ca4e3faed656fcdbd279429f968..c6f36467978a9d25f97cd15e9b660208902f97eb 100644 (file)
@@ -337,19 +337,15 @@ float: 2
 
 Function: "cbrt":
 double: 4
-float: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 
 Function: Real part of "ccos":
 double: 3
index d0cfa46c3dde270de5bf981cfdc206490994bf97..6319012db582da9a5e24a91fdec9dd2e2d9750a2 100644 (file)
@@ -84,7 +84,6 @@ float: 1
 
 Function: "cbrt":
 double: 4
-float: 1
 
 Function: Real part of "ccos":
 double: 1
index 6cdd3d53d6e5c525e8ec7b110dad44ac4de9a914..d9317046a9cbaf09c29d03748da9471d8bcc680f 100644 (file)
@@ -333,19 +333,15 @@ float: 1
 
 Function: "cbrt":
 double: 4
-float: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 
 Function: Real part of "ccos":
 double: 1
index a7b2bec17eee271d3d4240bcdbeeb555f9250898..c3a3db9bcb4040785f1ffd8ce28f931058649d4e 100644 (file)
@@ -330,19 +330,15 @@ float: 1
 
 Function: "cbrt":
 double: 4
-float: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 
 Function: Real part of "ccos":
 double: 1
index 4e4451a5d2a5e1150c9dbbd1cb4dfcd8ae659048..68a74bf1d0caad9610d104f68be5b6eb7749a0d1 100644 (file)
@@ -328,19 +328,15 @@ float: 1
 
 Function: "cbrt":
 double: 4
-float: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 
 Function: Real part of "ccos":
 double: 1
index 0af5b6136266e6bd3a4d732ea475e4ff300874bd..a3e66291a076dea4366e9e8cfead16340c80ed27 100644 (file)
@@ -338,20 +338,16 @@ float: 1
 
 Function: "cbrt":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 
 Function: Real part of "ccos":
 double: 1
index 68b8b0ec3791e1c47a075143a95dc410b47b5680..5a7a9a952d1692fd2c12120350acac939db375f5 100644 (file)
@@ -1,61 +1,99 @@
-/* Compute cubic root of float value.
-   Copyright (C) 1997-2024 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
+/* Correctly-rounded cubic root of binary32 value.
 
-   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/cbrt/cbrtf.c, revision bc385c2).
 
-   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:
 
-#include <math.h>
-#include <libm-alias-float.h>
+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.
+*/
 
-#define CBRT2 1.2599210498948731648            /* 2^(1/3) */
-#define SQR_CBRT2 1.5874010519681994748                /* 2^(2/3) */
-
-static const double factor[5] =
-{
-  1.0 / SQR_CBRT2,
-  1.0 / CBRT2,
-  1.0,
-  CBRT2,
-  SQR_CBRT2
-};
-
+#include <fenv.h>
+#include <libm-alias-float.h>
+#include <math.h>
+#include <stdint.h>
+#include "math_config.h"
 
 float
 __cbrtf (float x)
 {
-  float xm, ym, u, t2;
-  int xe;
-
-  /* Reduce X.  XM now is an range 1.0 to 0.5.  */
-  xm = __frexpf (fabsf (x), &xe);
-
-  /* If X is not finite or is null return it (with raising exceptions
-     if necessary.
-     Note: *Our* version of `frexp' sets XE to zero if the argument is
-     Inf or NaN.  This is not portable but faster.  */
-  if (xe == 0 && fpclassify (x) <= FP_ZERO)
-    return x + x;
-
-  u = (0.492659620528969547 + (0.697570460207922770
-                              - 0.191502161678719066 * xm) * xm);
-
-  t2 = u * u * u;
-
-  ym = u * (t2 + 2.0 * xm) / (2.0 * t2 + xm) * factor[2 + xe % 3];
-
-  return __ldexpf (x > 0.0 ? ym : -ym, xe / 3);
+  static const union
+  {
+    double d;
+    uint64_t u;
+  } escale[3] =
+  {
+    { .d = 1.0 },
+    { .d = 0x1.428a2f98d728bp+0 }, /* 2^(1/3) */
+    { .d = 0x1.965fea53d6e3dp+0 }, /* 2^(2/3) */
+  };
+  uint32_t u = asuint (x);
+  uint32_t au = u << 1;
+  uint32_t sgn = u >> 31;
+  uint32_t e = au >> 24;
+  if (__glibc_unlikely (au < 1u << 24 || au >= 0xffu << 24))
+    {
+      if (au >= 0xffu << 24)
+       return x + x; /* inf, nan */
+      if (au == 0)
+       return x;                      /* +-0 */
+      int nz = __builtin_clz (au) - 7; /* subnormal */
+      au <<= nz;
+      e -= nz - 1;
+    }
+  uint32_t mant = au & 0xffffff;
+  e += 899;
+  uint32_t et = e / 3, it = e % 3;
+  uint64_t isc = escale[it].u;
+  isc += (int64_t) (et - 342) << 52;
+  isc |= (int64_t) sgn << 63;
+  double cvt2 = asdouble (isc);
+  static const double c[] =
+    {
+       0x1.2319d352ea5d5p-1,  0x1.67ad8ee258d1ap-1, -0x1.9342edf9cbad9p-2,
+       0x1.b6388fc510a75p-3, -0x1.6002455599e2fp-4,  0x1.7b096936192c4p-6,
+      -0x1.e5577187e8bf8p-9,  0x1.169ef81d6c34ep-12
+    };
+  double z = asdouble ((uint64_t) mant << 28 | UINT64_C(0x3ff) << 52);
+  double r0 = -0x1.9931c6c2d19d1p-6 / z;
+  double z2 = z * z;
+  double z4 = z2 * z2;
+  double f = ((c[0] + z * c[1]) + z2 * (c[2] + z * c[3]))
+            + z4 * ((c[4] + z * c[5]) + z2 * (c[6] + z * c[7])) + r0;
+  double r = f * cvt2;
+  float ub = r;
+  float lb = r - cvt2 * 1.4182e-9;
+  if (__glibc_likely (ub == lb))
+    return ub;
+  const double u0 = -0x1.ab16ec65d138fp+3;
+  double h = f * f * f - z;
+  f -= (f * r0 * u0) * h;
+  r = f * cvt2;
+  uint64_t cvt1 = asuint64 (r);
+  ub = r;
+  int64_t m0 = cvt1 << 19;
+  int64_t  m1 = m0 >> 63;
+  if (__glibc_unlikely ((m0 ^ m1) < (UINT64_C(1) << 31)))
+    {
+      cvt1 = (cvt1 + (UINT64_C(1) << 31)) & UINT64_C(0xffffffff00000000);
+      ub = asdouble (cvt1);
+    }
+  return ub;
 }
 libm_alias_float (__cbrt, cbrt)
index 7c2071126893d8dab95d575773d53c54388ee651..1aaf7b3fa34b8cfbe83a97caac694bf1372dc9b4 100644 (file)
@@ -417,22 +417,18 @@ ldouble: 2
 
 Function: "cbrt":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 ldouble: 1
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 ldouble: 1
 
 Function: Real part of "ccos":
index 3964b83b812e2695e109ae48926ddef06186ce2e..8456a59010e1d7250c337268f79cd13dce896e41 100644 (file)
@@ -379,22 +379,18 @@ ldouble: 1
 
 Function: "cbrt":
 double: 1
-float: 1
 ldouble: 1
 
 Function: "cbrt_downward":
 double: 1
-float: 1
 ldouble: 1
 
 Function: "cbrt_towardzero":
 double: 1
-float: 1
 ldouble: 1
 
 Function: "cbrt_upward":
 double: 1
-float: 1
 ldouble: 1
 
 Function: Real part of "ccos":
index 328e31582bacee784f9e557631ac5737b51a1c7c..c89096defd4eae307ed04bc414c222b8217a2046 100644 (file)
@@ -81,7 +81,6 @@ float: 1
 
 Function: "cbrt":
 double: 3
-float: 1
 
 Function: Real part of "ccos":
 double: 1
index c319e0642cd09d1cf5e84fb2a877dcc89cab9135..cef264d649c528555712c79e5035e316b108ee4b 100644 (file)
@@ -333,19 +333,15 @@ float: 1
 
 Function: "cbrt":
 double: 4
-float: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 
 Function: Real part of "ccos":
 double: 1
index 365b860c540c5e2620a056aefa24cf28ffee80f1..724249d3ad3be101a54b8e3e0e95901980810a45 100644 (file)
@@ -417,22 +417,18 @@ ldouble: 2
 
 Function: "cbrt":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 ldouble: 1
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 ldouble: 1
 
 Function: Real part of "ccos":
index 5240767c0ef61d09140d259fc8acb164014404b5..dbccba13cb15a50075f6df85e69b1d69750bfd46 100644 (file)
@@ -84,7 +84,6 @@ float: 1
 
 Function: "cbrt":
 double: 4
-float: 1
 
 Function: Real part of "ccos":
 double: 1
index 9ced4b00526074b423c63a0aab6eaf8e6e5d364f..df2b69ac7593fc227d6a56abfe13278f83193288 100644 (file)
@@ -333,19 +333,15 @@ float: 1
 
 Function: "cbrt":
 double: 4
-float: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 
 Function: Real part of "ccos":
 double: 1
index c7ae0f002b56d201e99fd1ef3cd473d899838c6a..2263f3f0b7fb2ae62f045899363836f7799433f4 100644 (file)
@@ -333,19 +333,15 @@ float: 1
 
 Function: "cbrt":
 double: 4
-float: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 
 Function: Real part of "ccos":
 double: 1
index 8d0c18eed104de4147cca4d791108808144611f3..36fa54d97e45e51bfa4d461f7a86950f82b4149b 100644 (file)
@@ -506,25 +506,21 @@ ldouble: 6
 
 Function: "cbrt":
 double: 4
-float: 1
 float128: 1
 ldouble: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 float128: 1
 ldouble: 5
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 float128: 1
 ldouble: 3
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 float128: 2
 ldouble: 2
 
index 20036c779ca45bfad82ebbe95f22f1e6ed62e837..c32c8017b4ee3b447560d62dc3d2f1fa95d8732c 100644 (file)
@@ -421,22 +421,18 @@ ldouble: 6
 
 Function: "cbrt":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 ldouble: 5
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 ldouble: 3
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 ldouble: 2
 
 Function: Real part of "ccos":
index cccc864a7a02136d7d8d3fb6490986859fbea32a..79927c2bd93a004e6b34442c0084c3d728a105b8 100644 (file)
@@ -417,22 +417,18 @@ ldouble: 2
 
 Function: "cbrt":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 ldouble: 1
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 ldouble: 1
 
 Function: Real part of "ccos":
index 14fc7633af090e8cc49a28e68139290833f3b478..fbd5b8fed7050c24ab844e11332a5232d00795ee 100644 (file)
@@ -417,22 +417,18 @@ ldouble: 2
 
 Function: "cbrt":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 ldouble: 1
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 ldouble: 1
 
 Function: Real part of "ccos":
index a25bb505b38575f33faa1be25d038749990c89a7..ade5a39db45d5891079f6fffd8860044f2f26170 100644 (file)
@@ -417,22 +417,18 @@ ldouble: 2
 
 Function: "cbrt":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 ldouble: 1
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 ldouble: 1
 
 Function: Real part of "ccos":
index 8562796de8bfb5398265052b9b780fb361ee91bd..b0040d7218848b80ac8d0f6369b823c344ccc33a 100644 (file)
@@ -164,11 +164,9 @@ float: 2
 
 Function: "cbrt":
 double: 4
-float: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 
 Function: Real part of "ccos":
 double: 1
index 6ea02058e9f9305702976e02a4e95380c223fc69..d78b46b97bc07c0d6294d224a74b61015d93abab 100644 (file)
@@ -417,22 +417,18 @@ ldouble: 2
 
 Function: "cbrt":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 ldouble: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 ldouble: 1
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 ldouble: 1
 
 Function: Real part of "ccos":
index e3c811549ce7174dd7c269692caabd1fb3675a12..327937929d926689fc9c025e55e8dd044427bfec 100644 (file)
@@ -638,25 +638,21 @@ ldouble: 1
 
 Function: "cbrt":
 double: 4
-float: 1
 float128: 1
 ldouble: 1
 
 Function: "cbrt_downward":
 double: 4
-float: 1
 float128: 1
 ldouble: 1
 
 Function: "cbrt_towardzero":
 double: 3
-float: 1
 float128: 1
 ldouble: 1
 
 Function: "cbrt_upward":
 double: 5
-float: 1
 float128: 1
 ldouble: 1