]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
math: Use tanhf from CORE-MATH
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Tue, 19 Nov 2024 19:30:16 +0000 (16:30 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Wed, 18 Dec 2024 20:24:43 +0000 (17:24 -0300)
The CORE-MATH implementation is correctly rounded (for any rounding mode)
and shows slight better performance to the generic tanhf.

The code was adapted to glibc style and to use the definition of
math_config.h (to handle errno, overflow, and underflow).

Benchtest on x64_64 (Ryzen 9 5900X, gcc 14.2.1), aarch64 (Neoverse-N1,
gcc 13.3.1), and powerpc (POWER10, gcc 13.2.1):

Latency                      master        patched   improvement
x86_64                      51.5273        41.0951        20.25%
x86_64v2                    47.7021        39.1526        17.92%
x86_64v3                    45.0373        34.2737        23.90%
i686                       133.9970        83.8596        37.42%
aarch64 (Neoverse)          21.5439        14.7961        31.32%
power10                     13.3301         8.4406        36.68%

reciprocal-throughput        master        patched   improvement
x86_64                      24.9493        12.8547        48.48%
x86_64v2                    20.7051        12.7761        38.29%
x86_64v3                    19.2492        11.0851        42.41%
i686                        78.6498        29.8211        62.08%
aarch64 (Neoverse)          11.6026        7.11487        38.68%
power10                      6.3328         2.8746        54.61%

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>
Reviewed-by: DJ Delorie <dj@redhat.com>
27 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/i386/fpu/libm-test-ulps
sysdeps/i386/i686/fpu/multiarch/libm-test-ulps
sysdeps/ieee754/flt-32/s_tanhf.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/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 3bd4e7fb4adc542721fb563ef04d99f994040be8..032c407881502792e9084382ee255e19eec6a657 100644 (file)
@@ -330,3 +330,7 @@ sysdeps/ieee754/flt-32/e_sinhf.c:
   (src/binary32/sinh/sinhf.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_tanhf.c:
+  (src/binary32/tanh/tanhf.c in CORE-MATH)
+  - the code was adapted to use glibc code style and internal
+    functions to handle errno, overflow, and underflow.
index 1e9c5af0ca2449869b5cffb852ee2aaca309f8f1..190685f8933a4ecbe10b20e80cb6fb2a274f06c0 100644 (file)
@@ -1665,7 +1665,6 @@ ldouble: 1
 
 Function: "tanh":
 double: 2
-float: 2
 ldouble: 2
 
 Function: "tanh_advsimd":
@@ -1674,7 +1673,6 @@ float: 2
 
 Function: "tanh_downward":
 double: 3
-float: 3
 ldouble: 4
 
 Function: "tanh_sve":
@@ -1683,12 +1681,10 @@ float: 2
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 ldouble: 3
 
 Function: "tanh_upward":
 double: 3
-float: 3
 ldouble: 3
 
 Function: "tanpi":
index 7d5fcc7f2e2eff95b6abd6445cd87c58d2f316db..ddc851b73c4f382af3f65ca4b298e6330d637eab 100644 (file)
@@ -1318,22 +1318,18 @@ ldouble: 1
 
 Function: "tanh":
 double: 2
-float: 2
 ldouble: 2
 
 Function: "tanh_downward":
 double: 3
-float: 3
 ldouble: 4
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 ldouble: 3
 
 Function: "tanh_upward":
 double: 3
-float: 3
 ldouble: 3
 
 Function: "tgamma":
index ec42c5eac9d8f1d736983c5a17cddf6d685006a8..92fad18fc591a1a09cf7d0e40ab64796406c40b6 100644 (file)
@@ -1053,19 +1053,15 @@ double: 1
 
 Function: "tanh":
 double: 3
-float: 2
 
 Function: "tanh_downward":
 double: 3
-float: 3
 
 Function: "tanh_towardzero":
 double: 3
-float: 3
 
 Function: "tanh_upward":
 double: 3
-float: 3
 
 Function: "tgamma":
 double: 9
index 15b2b82187e71fb08dd0c17a3b4425fb66fbd98b..6fb7ce93f453497308526fba7e0760eaa87f1550 100644 (file)
@@ -251,7 +251,6 @@ double: 2
 
 Function: "tanh":
 double: 2
-float: 2
 
 Function: "tgamma":
 double: 9
index 201099d3f2339a9ee03bf41a765c165ea841e585..3ff089c1ebef76c73e578fb2b47a3af125710f32 100644 (file)
@@ -1143,19 +1143,15 @@ double: 1
 
 Function: "tanh":
 double: 2
-float: 2
 
 Function: "tanh_downward":
 double: 3
-float: 3
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 
 Function: "tanh_upward":
 double: 3
-float: 3
 
 Function: "tanpi":
 double: 2
index 3824f0041571200253b5bfd1d2b01eb4e4d31c5a..6ba3cef62331dbc630816bf0242916f842407cd3 100644 (file)
@@ -971,19 +971,15 @@ double: 1
 
 Function: "tanh":
 double: 2
-float: 2
 
 Function: "tanh_downward":
 double: 3
-float: 3
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 
 Function: "tanh_upward":
 double: 3
-float: 3
 
 Function: "tgamma":
 double: 9
index 34f5eb52a2d972e549da764f82ca5918cb237020..4f428a65c5ab283a764311b97496448d18fd7582 100644 (file)
@@ -1002,19 +1002,15 @@ double: 1
 
 Function: "tanh":
 double: 2
-float: 2
 
 Function: "tanh_downward":
 double: 3
-float: 3
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 
 Function: "tanh_upward":
 double: 3
-float: 3
 
 Function: "tgamma":
 double: 9
index e48fb8a66e4bd70b2d9db3f11ec6658ebf599d17..759e224308df793fec9b54d9c2ba389bdc87838f 100644 (file)
@@ -1176,19 +1176,15 @@ double: 1
 
 Function: "tanh":
 double: 2
-float: 2
 
 Function: "tanh_downward":
 double: 3
-float: 3
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 
 Function: "tanh_upward":
 double: 3
-float: 3
 
 Function: "tanpi":
 double: 2
index d545682fd9f9fc042c8b545ebab576b9667cbf36..423061e12eb26265b988e7bd67d1bae7623bee1b 100644 (file)
@@ -1754,25 +1754,21 @@ ldouble: 2
 
 Function: "tanh":
 double: 2
-float: 2
 float128: 2
 ldouble: 3
 
 Function: "tanh_downward":
 double: 3
-float: 3
 float128: 4
 ldouble: 4
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 float128: 3
 ldouble: 3
 
 Function: "tanh_upward":
 double: 3
-float: 3
 float128: 3
 ldouble: 4
 
index ad9a52749b1973666efc40cfd6878ccd3d3b86cb..466e68dae039a01234bcaa941171a03f84373c40 100644 (file)
@@ -1759,25 +1759,21 @@ ldouble: 2
 
 Function: "tanh":
 double: 2
-float: 2
 float128: 2
 ldouble: 3
 
 Function: "tanh_downward":
 double: 3
-float: 3
 float128: 4
 ldouble: 4
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 float128: 3
 ldouble: 3
 
 Function: "tanh_upward":
 double: 3
-float: 3
 float128: 3
 ldouble: 4
 
index 2c12f04569f0dbd06c7e145f94f4decfc85d1139..e07f3589b8afa5ffeccc5cf68e53426065fbabda 100644 (file)
@@ -1,63 +1,90 @@
-/* s_tanhf.c -- float version of s_tanh.c.
- */
+/* Correctly-rounded hyperbolic tangent 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) 2022-2024 Alexei Sibidanov.
 
-#if defined(LIBM_SCCS) && !defined(lint)
-static char rcsid[] = "$NetBSD: s_tanhf.c,v 1.4 1995/05/10 20:48:24 jtc Exp $";
-#endif
+The original version of this file was copied from the CORE-MATH
+project (file src/binary32/tanh/tanhf.c, revision b1ecd83).
 
-#include <float.h>
-#include <math.h>
-#include <math_private.h>
-#include <math-underflow.h>
-#include <libm-alias-float.h>
+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 one=1.0, two=2.0, tiny = 1.0e-30;
-
-float __tanhf(float x)
-{
-       float t,z;
-       int32_t jx,ix;
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
 
-       GET_FLOAT_WORD(jx,x);
-       ix = jx&0x7fffffff;
+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.
+*/
 
-    /* x is INF or NaN */
-       if(ix>=0x7f800000) {
-           if (jx>=0) return one/x+one;    /* tanh(+-inf)=+-1 */
-           else       return one/x-one;    /* tanh(NaN) = NaN */
-       }
+#include <math.h>
+#include <stdint.h>
+#include <libm-alias-float.h>
+#include "math_config.h"
 
-    /* |x| < 22 */
-       if (ix < 0x41b00000) {          /* |x|<22 */
-           if (ix == 0)
-               return x;               /* x == +-0 */
-           if (ix<0x24000000)          /* |x|<2**-55 */
-             {
-               math_check_force_underflow (x);
-               return x*(one+x);       /* tanh(small) = small */
-             }
-           if (ix>=0x3f800000) {       /* |x|>=1  */
-               t = __expm1f(two*fabsf(x));
-               z = one - two/(t+two);
-           } else {
-               t = __expm1f(-two*fabsf(x));
-               z= -t/(t+two);
-           }
-    /* |x| > 22, return +-1 */
-       } else {
-           z = one - tiny;             /* raised inexact flag */
+float
+__tanhf (float x)
+{
+  double z = x;
+  uint32_t ux = asuint (x);
+  int e = (ux >> 23) & 0xff;
+  if (__glibc_unlikely (e == 0xff))
+    {
+      if (ux << 9)
+       return x + x; /* x = nan */
+      static const float ir[] = { 1.0f, -1.0f };
+      return ir[ux >> 31]; /* x = +-inf */
+    }
+  if (__glibc_unlikely (e < 115))
+    {
+      if (__glibc_unlikely (e < 102))
+       {
+         if (__glibc_unlikely ((ux << 1) == 0))
+           return x;
+         return fmaf (-x, fabsf (x), x);
        }
-       return (jx>=0)? z: -z;
+      float x2 = x * x;
+      return fmaf (x, -0x1.555556p-2f * x2, x);
+    }
+  if ((ux << 1) > (0x41102cb3u << 1))
+    return copysignf (1.0f, x) - copysignf (0x1p-25f, x);
+  double z2 = z * z;
+  double z4 = z2 * z2;
+  double z8 = z4 * z4;
+  static const double cn[] =
+    {
+      0x1p+0,                0x1.30877b8b72d33p-3,  0x1.694aa09ae9e5ep-8,
+      0x1.4101377abb729p-14, 0x1.e0392b1db0018p-22, 0x1.2533756e546f7p-30,
+      0x1.d62e5abe6ae8ap-41, 0x1.b06be534182dep-54
+    };
+  static const double cd[] =
+    {
+      0x1p+0,                0x1.ed99131b0ebeap-2,  0x1.0d27ed6c95a69p-5,
+      0x1.7cbdaca0e9fccp-11, 0x1.b4e60b892578ep-18, 0x1.a6f707c5c71abp-26,
+      0x1.35a8b6e2cd94cp-35, 0x1.ca8230677aa01p-47
+    };
+  double n0 = cn[0] + z2 * cn[1];
+  double n2 = cn[2] + z2 * cn[3];
+  double n4 = cn[4] + z2 * cn[5];
+  double n6 = cn[6] + z2 * cn[7];
+  n0 += z4 * n2;
+  n4 += z4 * n6;
+  n0 += z8 * n4;
+  double d0 = cd[0] + z2 * cd[1];
+  double d2 = cd[2] + z2 * cd[3];
+  double d4 = cd[4] + z2 * cd[5];
+  double d6 = cd[6] + z2 * cd[7];
+  d0 += z4 * d2;
+  d4 += z4 * d6;
+  d0 += z8 * d4;
+  double r = z * n0 / d0;
+  return r;
 }
 libm_alias_float (__tanh, tanh)
index 1e57c6a4df73f6284b8ebdd02ad0a6d2ec3522de..0840e9e190a492f2d5d49cfc96abee05fba457d6 100644 (file)
@@ -1325,22 +1325,18 @@ ldouble: 1
 
 Function: "tanh":
 double: 2
-float: 2
 ldouble: 2
 
 Function: "tanh_downward":
 double: 3
-float: 3
 ldouble: 4
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 ldouble: 3
 
 Function: "tanh_upward":
 double: 3
-float: 3
 ldouble: 3
 
 Function: "tgamma":
index 1ef5e0e5a3625ef33c987b9e85c8bb5614410954..6acb5cd043d311e265dda055b1df589dfaa742ba 100644 (file)
@@ -1152,15 +1152,12 @@ double: 1
 
 Function: "tanh_downward":
 double: 1
-float: 1
 
 Function: "tanh_towardzero":
 double: 1
-float: 1
 
 Function: "tanh_upward":
 double: 1
-float: 1
 
 Function: "tgamma":
 double: 3
index 0f0e1fb35db38169a6d888de5513e32a7cbb5485..7a6d75f91c79c5e0cbbe8cd600dddf3934855701 100644 (file)
@@ -233,7 +233,6 @@ double: 2
 
 Function: "tanh":
 double: 2
-float: 2
 
 Function: "tgamma":
 double: 5
index 58223df3b46c156986c2198ae4cb8d0909b988cf..3ede885f9e9beebadae9fcf4ea7d2f93ce724d40 100644 (file)
@@ -1050,19 +1050,15 @@ double: 1
 
 Function: "tanh":
 double: 2
-float: 2
 
 Function: "tanh_downward":
 double: 3
-float: 3
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 
 Function: "tanh_upward":
 double: 3
-float: 3
 
 Function: "tgamma":
 double: 9
index efa76ec249408bc129b3f50a373885adbd9394d5..891f887030c32acd9b884ba000b830d97eb2deac 100644 (file)
@@ -1336,22 +1336,18 @@ ldouble: 1
 
 Function: "tanh":
 double: 2
-float: 2
 ldouble: 2
 
 Function: "tanh_downward":
 double: 3
-float: 3
 ldouble: 4
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 ldouble: 3
 
 Function: "tanh_upward":
 double: 3
-float: 3
 ldouble: 3
 
 Function: "tgamma":
index 5900e6d6d9007b014539b3c35ef6f73383d2ce22..c27afc99c8e333dbdadb8efae639745bfcd7af94 100644 (file)
@@ -984,19 +984,15 @@ double: 1
 
 Function: "tanh":
 double: 2
-float: 2
 
 Function: "tanh_downward":
 double: 3
-float: 3
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 
 Function: "tanh_upward":
 double: 3
-float: 3
 
 Function: "tgamma":
 double: 9
index 6f60e83486e2b41985b97e7d2fba825fe8ec9e70..46ef288135413b01885d60c314e8cd8b12b3142e 100644 (file)
@@ -1013,19 +1013,15 @@ double: 1
 
 Function: "tanh":
 double: 2
-float: 2
 
 Function: "tanh_downward":
 double: 3
-float: 3
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 
 Function: "tanh_upward":
 double: 3
-float: 3
 
 Function: "tanpi":
 double: 2
index 9fe6f82a41fd5b696c9fa337fba505ee03402843..07b91f8534355b524704957df3ab57358f7aaf2a 100644 (file)
@@ -1861,25 +1861,21 @@ ldouble: 3
 
 Function: "tanh":
 double: 2
-float: 2
 float128: 2
 ldouble: 1
 
 Function: "tanh_downward":
 double: 3
-float: 3
 float128: 4
 ldouble: 4
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 float128: 3
 ldouble: 4
 
 Function: "tanh_upward":
 double: 3
-float: 3
 float128: 3
 ldouble: 6
 
index 769c14e81decfc02b99df759ec93483527d0cd5a..3f02dc0be20738e9304542d19e643b716b1b9908 100644 (file)
@@ -1452,22 +1452,18 @@ ldouble: 3
 
 Function: "tanh":
 double: 2
-float: 2
 ldouble: 1
 
 Function: "tanh_downward":
 double: 3
-float: 3
 ldouble: 4
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 ldouble: 4
 
 Function: "tanh_upward":
 double: 3
-float: 3
 ldouble: 6
 
 Function: "tgamma":
index 3ce20f4bb1234ffe417c1082c6b3eee8770e3418..055826625c29d112e5a8a1cef9b68a42ec564fd7 100644 (file)
@@ -1265,22 +1265,18 @@ ldouble: 1
 
 Function: "tanh":
 double: 2
-float: 2
 ldouble: 2
 
 Function: "tanh_downward":
 double: 3
-float: 3
 ldouble: 4
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 ldouble: 3
 
 Function: "tanh_upward":
 double: 3
-float: 3
 ldouble: 3
 
 Function: "tgamma":
index 98146886d999eca1a2b9bc2db8eab5b1340522c9..69e0eb2e42c57b44c673b1316a77c3811407656a 100644 (file)
@@ -1323,22 +1323,18 @@ ldouble: 1
 
 Function: "tanh":
 double: 2
-float: 2
 ldouble: 2
 
 Function: "tanh_downward":
 double: 3
-float: 3
 ldouble: 4
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 ldouble: 3
 
 Function: "tanh_upward":
 double: 3
-float: 3
 ldouble: 3
 
 Function: "tgamma":
index e8a3754e4cf5777edb942f0c90058acc2d66749d..1a91bffcfe0dbbe369210658018c553da197d4a9 100644 (file)
@@ -1362,22 +1362,18 @@ ldouble: 1
 
 Function: "tanh":
 double: 2
-float: 2
 ldouble: 2
 
 Function: "tanh_downward":
 double: 3
-float: 3
 ldouble: 4
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 ldouble: 3
 
 Function: "tanh_upward":
 double: 3
-float: 3
 ldouble: 3
 
 Function: "tanpi":
index 3c07cd131713ca8e576d7cc29fac90011e740fa2..9378516d5828dd26e41ce2d1f9f2342b91f0f069 100644 (file)
@@ -486,11 +486,9 @@ double: 1
 
 Function: "tanh":
 double: 2
-float: 2
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 
 Function: "tgamma":
 double: 9
index ec9d2d9d21b579876bbfa7896d0e9aacafa29ef9..9123fff50b38cad483e6c82489bb3c74f9074188 100644 (file)
@@ -1377,22 +1377,18 @@ ldouble: 1
 
 Function: "tanh":
 double: 2
-float: 2
 ldouble: 2
 
 Function: "tanh_downward":
 double: 3
-float: 3
 ldouble: 4
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 ldouble: 3
 
 Function: "tanh_upward":
 double: 3
-float: 3
 ldouble: 3
 
 Function: "tanpi":
index 7ce0714683f88b1a8f9ce93b9539df072f97479d..ad936ad32f60338c6c5610e44060382e8ec9a293 100644 (file)
@@ -2280,25 +2280,21 @@ float: 2
 
 Function: "tanh":
 double: 2
-float: 2
 float128: 2
 ldouble: 3
 
 Function: "tanh_downward":
 double: 3
-float: 3
 float128: 4
 ldouble: 4
 
 Function: "tanh_towardzero":
 double: 2
-float: 2
 float128: 3
 ldouble: 3
 
 Function: "tanh_upward":
 double: 3
-float: 3
 float128: 3
 ldouble: 4