[libc-commits] [libc] [llvm] [libc][math] Refractor logf to Header only (PR #176834)

Anikesh Parashar via libc-commits libc-commits at lists.llvm.org
Wed Jan 21 03:59:48 PST 2026


https://github.com/an1k3sh updated https://github.com/llvm/llvm-project/pull/176834

>From d2492c1cf657e151cdfef804adb6ea0cc4a99e92 Mon Sep 17 00:00:00 2001
From: Anikesh Parashar <anikeshparashar at gmail.com>
Date: Tue, 20 Jan 2026 04:20:38 +0530
Subject: [PATCH 1/5] Refractor logf to header only

---
 libc/shared/math.h                            |   1 +
 libc/shared/math/logf.h                       |  23 +++
 libc/src/__support/math/CMakeLists.txt        |  17 ++
 libc/src/__support/math/logf.h                | 193 ++++++++++++++++++
 libc/src/math/generic/CMakeLists.txt          |   1 +
 libc/src/math/generic/logf.cpp                |  11 +-
 libc/test/shared/CMakeLists.txt               |   1 +
 libc/test/shared/shared_math_test.cpp         |   1 +
 .../llvm-project-overlay/libc/BUILD.bazel     |  17 ++
 9 files changed, 255 insertions(+), 10 deletions(-)
 create mode 100644 libc/shared/math/logf.h
 create mode 100644 libc/src/__support/math/logf.h

diff --git a/libc/shared/math.h b/libc/shared/math.h
index d58238703701d..6cbacc059b6ee 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -76,6 +76,7 @@
 #include "math/logbf.h"
 #include "math/logbf128.h"
 #include "math/logbf16.h"
+#include "math/logf.h"
 #include "math/rsqrtf.h"
 #include "math/rsqrtf16.h"
 #include "math/sin.h"
diff --git a/libc/shared/math/logf.h b/libc/shared/math/logf.h
new file mode 100644
index 0000000000000..a36ecfd3d4a39
--- /dev/null
+++ b/libc/shared/math/logf.h
@@ -0,0 +1,23 @@
+//===-- Shared logf function ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SHARED_MATH_LOGF_H
+#define LLVM_LIBC_SHARED_MATH_LOGF_H
+
+#include "shared/libc_common.h"
+#include "src/__support/math/logf.h"
+
+namespace LIBC_NAMESPACE_DECL {
+    
+namespace shared {
+using math::logf;
+} // namespace shared
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SHARED_MATH_LOGF_H
\ No newline at end of file
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index bf1c4463b8066..5f234f2263532 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -1148,6 +1148,23 @@ add_header_library(
     libc.src.__support.FPUtil.manipulation_functions
 )
 
+add_header_library(
+  logf
+  HDRS
+    logf.h
+  DEPENDS
+    .common_constants
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.polyeval
+    libc.src.__support.FPUtil.except_value_utils
+    libc.src.__support.FPUtil.multiply_add
+    libc.src.__support.common
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+    libc.src.__support.macros.properties.cpu_features
+)
+
 add_header_library(
   log_range_reduction
   HDRS
diff --git a/libc/src/__support/math/logf.h b/libc/src/__support/math/logf.h
new file mode 100644
index 0000000000000..a6a1452ef87ab
--- /dev/null
+++ b/libc/src/__support/math/logf.h
@@ -0,0 +1,193 @@
+//===-- Single-precision log(x) function ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_LOGF_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_LOGF_H
+
+#include "src/math/logf.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/except_value_utils.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/__support/macros/properties/cpu_features.h"
+#include "src/__support/math/common_constants.h" // Lookup table for (1/f) and log(f)
+
+// This is an algorithm for log(x) in single precision which is correctly
+// rounded for all rounding modes, based on the implementation of log(x) from
+// the RLIBM project at:
+// https://people.cs.rutgers.edu/~sn349/rlibm
+
+// Step 1 - Range reduction:
+//   For x = 2^m * 1.mant, log(x) = m * log(2) + log(1.m)
+//   If x is denormal, we normalize it by multiplying x by 2^23 and subtracting
+//   m by 23.
+
+// Step 2 - Another range reduction:
+//   To compute log(1.mant), let f be the highest 8 bits including the hidden
+// bit, and d be the difference (1.mant - f), i.e. the remaining 16 bits of the
+// mantissa. Then we have the following approximation formula:
+//   log(1.mant) = log(f) + log(1.mant / f)
+//               = log(f) + log(1 + d/f)
+//               ~ log(f) + P(d/f)
+// since d/f is sufficiently small.
+//   log(f) and 1/f are then stored in two 2^7 = 128 entries look-up tables.
+
+// Step 3 - Polynomial approximation:
+//   To compute P(d/f), we use a single degree-5 polynomial in double precision
+// which provides correct rounding for all but few exception values.
+//   For more detail about how this polynomial is obtained, please refer to the
+// paper:
+//   Lim, J. and Nagarakatte, S., "One Polynomial Approximation to Produce
+// Correctly Rounded Results of an Elementary Function for Multiple
+// Representations and Rounding Modes", Proceedings of the 49th ACM SIGPLAN
+// Symposium on Principles of Programming Languages (POPL-2022), Philadelphia,
+// USA, January 16-22, 2022.
+// https://people.cs.rutgers.edu/~sn349/papers/rlibmall-popl-2022.pdf
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+static constexpr float logf(float x) {
+  using namespace common_constants_internal;
+  constexpr double LOG_2 = 0x1.62e42fefa39efp-1;
+  using FPBits = typename fputil::FPBits<float>;
+
+  FPBits xbits(x);
+  uint32_t x_u = xbits.uintval();
+
+  int m = -FPBits::EXP_BIAS;
+
+  using fputil::round_result_slightly_down;
+  using fputil::round_result_slightly_up;
+
+  // Small inputs
+  if (x_u < 0x4c5d65a5U) {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+    // Hard-to-round cases.
+    switch (x_u) {
+    case 0x3f7f4d6fU: // x = 0x1.fe9adep-1f
+      return round_result_slightly_up(-0x1.659ec8p-9f);
+    case 0x41178febU: // x = 0x1.2f1fd6p+3f
+      return round_result_slightly_up(0x1.1fcbcep+1f);
+#ifdef LIBC_TARGET_CPU_HAS_FMA
+    case 0x3f800000U: // x = 1.0f
+      return 0.0f;
+#else
+    case 0x1e88452dU: // x = 0x1.108a5ap-66f
+      return round_result_slightly_up(-0x1.6d7b18p+5f);
+#endif // LIBC_TARGET_CPU_HAS_FMA
+    }
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+    // Subnormal inputs.
+    if (LIBC_UNLIKELY(x_u < FPBits::min_normal().uintval())) {
+      if (x == 0.0f) {
+        // Return -inf and raise FE_DIVBYZERO
+        fputil::set_errno_if_required(ERANGE);
+        fputil::raise_except_if_required(FE_DIVBYZERO);
+        return FPBits::inf(Sign::NEG).get_val();
+      }
+      // Normalize denormal inputs.
+      xbits = FPBits(xbits.get_val() * 0x1.0p23f);
+      m -= 23;
+      x_u = xbits.uintval();
+    }
+  } else {
+#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+    // Hard-to-round cases.
+    switch (x_u) {
+    case 0x4c5d65a5U: // x = 0x1.bacb4ap+25f
+      return round_result_slightly_down(0x1.1e0696p+4f);
+    case 0x65d890d3U: // x = 0x1.b121a6p+76f
+      return round_result_slightly_down(0x1.a9a3f2p+5f);
+    case 0x6f31a8ecU: // x = 0x1.6351d8p+95f
+      return round_result_slightly_down(0x1.08b512p+6f);
+    case 0x7a17f30aU: // x = 0x1.2fe614p+117f
+      return round_result_slightly_up(0x1.451436p+6f);
+#ifndef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+    case 0x500ffb03U: // x = 0x1.1ff606p+33f
+      return round_result_slightly_up(0x1.6fdd34p+4f);
+    case 0x5cd69e88U: // x = 0x1.ad3d1p+58f
+      return round_result_slightly_up(0x1.45c146p+5f);
+    case 0x5ee8984eU: // x = 0x1.d1309cp+62f;
+      return round_result_slightly_up(0x1.5c9442p+5f);
+#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
+    }
+#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+    // Exceptional inputs.
+    if (LIBC_UNLIKELY(x_u > FPBits::max_normal().uintval())) {
+      if (x_u == 0x8000'0000U) {
+        // Return -inf and raise FE_DIVBYZERO
+        fputil::set_errno_if_required(ERANGE);
+        fputil::raise_except_if_required(FE_DIVBYZERO);
+        return FPBits::inf(Sign::NEG).get_val();
+      }
+      if (xbits.is_neg() && !xbits.is_nan()) {
+        // Return NaN and raise FE_INVALID
+        fputil::set_errno_if_required(EDOM);
+        fputil::raise_except_if_required(FE_INVALID);
+        return FPBits::quiet_nan().get_val();
+      }
+      // x is +inf or nan
+      if (xbits.is_signaling_nan()) {
+        fputil::raise_except_if_required(FE_INVALID);
+        return FPBits::quiet_nan().get_val();
+      }
+
+      return x;
+    }
+  }
+
+#ifndef LIBC_TARGET_CPU_HAS_FMA
+  // Returning the correct +0 when x = 1.0 for non-FMA targets with FE_DOWNWARD
+  // rounding mode.
+  if (LIBC_UNLIKELY((x_u & 0x007f'ffffU) == 0))
+    return static_cast<float>(
+        static_cast<double>(m + xbits.get_biased_exponent()) * LOG_2);
+#endif // LIBC_TARGET_CPU_HAS_FMA
+
+  uint32_t mant = xbits.get_mantissa();
+  // Extract 7 leading fractional bits of the mantissa
+  int index = mant >> 16;
+  // Add unbiased exponent. Add an extra 1 if the 7 leading fractional bits are
+  // all 1's.
+  m += static_cast<int>((x_u + (1 << 16)) >> 23);
+
+  // Set bits to 1.m
+  xbits.set_biased_exponent(0x7F);
+
+  float u = xbits.get_val();
+  double v = 0.0;
+#ifdef LIBC_TARGET_CPU_HAS_FMA_FLOAT
+  v = static_cast<double>(fputil::multiply_add(u, R[index], -1.0f)); // Exact.
+#else
+  v = fputil::multiply_add(static_cast<double>(u), RD[index], -1.0); // Exact
+#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT
+
+  // Degree-5 polynomial approximation of log generated by Sollya with:
+  // > P = fpminimax(log(1 + x)/x, 4, [|1, D...|], [-2^-8, 2^-7]);
+  constexpr double COEFFS[4] = {-0x1.000000000fe63p-1, 0x1.555556e963c16p-2,
+                                -0x1.000028dedf986p-2, 0x1.966681bfda7f7p-3};
+  double v2 = v * v; // Exact
+  double p2 = fputil::multiply_add(v, COEFFS[3], COEFFS[2]);
+  double p1 = fputil::multiply_add(v, COEFFS[1], COEFFS[0]);
+  double p0 = LOG_R[index] + v;
+  double r = fputil::multiply_add(static_cast<double>(m), LOG_2,
+                                  fputil::polyeval(v2, p0, p1, p2));
+  return static_cast<float>(r);
+}
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LOGF_H
\ No newline at end of file
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index b578d1805f2a8..96d2e22f98fa3 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -2120,6 +2120,7 @@ add_entrypoint_object(
     libc.src.__support.macros.optimization
     libc.src.__support.macros.properties.cpu_features
     libc.src.__support.math.common_constants
+    libc.src.__support.math.logf
 )
 
 add_entrypoint_object(
diff --git a/libc/src/math/generic/logf.cpp b/libc/src/math/generic/logf.cpp
index 4d2947dc14db0..80b757ddf3658 100644
--- a/libc/src/math/generic/logf.cpp
+++ b/libc/src/math/generic/logf.cpp
@@ -7,16 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/math/logf.h"
-#include "src/__support/FPUtil/FEnvImpl.h"
-#include "src/__support/FPUtil/FPBits.h"
-#include "src/__support/FPUtil/PolyEval.h"
-#include "src/__support/FPUtil/except_value_utils.h"
-#include "src/__support/FPUtil/multiply_add.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
-#include "src/__support/macros/properties/cpu_features.h"
-#include "src/__support/math/common_constants.h" // Lookup table for (1/f) and log(f)
+#include "src/__support/math/logf.h" // Lookup table for (1/f) and log(f)
 
 // This is an algorithm for log(x) in single precision which is correctly
 // rounded for all rounding modes, based on the implementation of log(x) from
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index cfc2eda1aaec9..bf8d8eca9abf5 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -68,6 +68,7 @@ add_fp_unittest(
     libc.src.__support.math.logbf
     libc.src.__support.math.logbf128
     libc.src.__support.math.logbf16
+    libc.src.__support.math.logf
     libc.src.__support.math.ldexpf
     libc.src.__support.math.ldexpf128
     libc.src.__support.math.ldexpf16
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index 88e6ecc98a0a7..e1ce06831bb3b 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -73,6 +73,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat) {
   EXPECT_FP_EQ(0x1p+0f, LIBC_NAMESPACE::shared::exp2f(0.0f));
   EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::expm1f(0.0f));
   EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::hypotf(0.0f, 0.0f));
+  EXPECT_FP_EQ(0x0p+0f, LIBC_NAMESPACE::shared::logf(1.0f));
 
   EXPECT_FP_EQ_ALL_ROUNDING(0.75f,
                             LIBC_NAMESPACE::shared::frexpf(24.0f, &exponent));
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 90b1da0e3376e..74b7b4901d6da 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -2977,6 +2977,23 @@ libc_support_library(
     ],
 )
 
+libc_support_library(
+    name = "__support_math_logf",
+    hdrs = ["src/__support/math/logf.h"],
+    deps = [
+        ":__support_common",
+        ":__support_fputil_except_value_utils",
+        ":__support_fputil_fenv_impl",
+        ":__support_fputil_fp_bits",
+        ":__support_fputil_multiply_add",
+        ":__support_fputil_polyeval",
+        ":__support_macros_config",
+        ":__support_macros_optimization",
+        ":__support_macros_properties_cpu_features",
+        ":__support_math_common_constants",
+    ],
+)
+
 libc_support_library(
     name = "__support_math_exp_constants",
     hdrs = ["src/__support/math/exp_constants.h"],

>From 3f01af142a29502207c6fbb4f645bebc829fe0ec Mon Sep 17 00:00:00 2001
From: Anikesh Parashar <anikeshparashar at gmail.com>
Date: Tue, 20 Jan 2026 04:21:42 +0530
Subject: [PATCH 2/5] Refractor logf to header only

---
 libc/shared/math/logf.h        | 2 +-
 libc/src/__support/math/logf.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/libc/shared/math/logf.h b/libc/shared/math/logf.h
index a36ecfd3d4a39..aa1caa4f0272a 100644
--- a/libc/shared/math/logf.h
+++ b/libc/shared/math/logf.h
@@ -13,7 +13,7 @@
 #include "src/__support/math/logf.h"
 
 namespace LIBC_NAMESPACE_DECL {
-    
+
 namespace shared {
 using math::logf;
 } // namespace shared
diff --git a/libc/src/__support/math/logf.h b/libc/src/__support/math/logf.h
index a6a1452ef87ab..dc85483ea011c 100644
--- a/libc/src/__support/math/logf.h
+++ b/libc/src/__support/math/logf.h
@@ -9,7 +9,6 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_MATH_LOGF_H
 #define LLVM_LIBC_SRC___SUPPORT_MATH_LOGF_H
 
-#include "src/math/logf.h"
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/PolyEval.h"
@@ -20,6 +19,7 @@
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 #include "src/__support/macros/properties/cpu_features.h"
 #include "src/__support/math/common_constants.h" // Lookup table for (1/f) and log(f)
+#include "src/math/logf.h"
 
 // This is an algorithm for log(x) in single precision which is correctly
 // rounded for all rounding modes, based on the implementation of log(x) from

>From 2d9f31764bf4899fdcef230cf7442ae718977246 Mon Sep 17 00:00:00 2001
From: Anikesh Parashar <anikeshparashar at gmail.com>
Date: Tue, 20 Jan 2026 04:28:46 +0530
Subject: [PATCH 3/5] Add newline at EOF

---
 libc/shared/math/logf.h        | 2 +-
 libc/src/__support/math/logf.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/libc/shared/math/logf.h b/libc/shared/math/logf.h
index aa1caa4f0272a..8d12f2d7fd9f7 100644
--- a/libc/shared/math/logf.h
+++ b/libc/shared/math/logf.h
@@ -20,4 +20,4 @@ using math::logf;
 
 } // namespace LIBC_NAMESPACE_DECL
 
-#endif // LLVM_LIBC_SHARED_MATH_LOGF_H
\ No newline at end of file
+#endif // LLVM_LIBC_SHARED_MATH_LOGF_H
diff --git a/libc/src/__support/math/logf.h b/libc/src/__support/math/logf.h
index dc85483ea011c..c608e9d11b1dd 100644
--- a/libc/src/__support/math/logf.h
+++ b/libc/src/__support/math/logf.h
@@ -190,4 +190,4 @@ static constexpr float logf(float x) {
 
 } // namespace LIBC_NAMESPACE_DECL
 
-#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LOGF_H
\ No newline at end of file
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LOGF_H

>From 206d1850a31b548bd26c19f315eecea4352f1f5f Mon Sep 17 00:00:00 2001
From: Anikesh Parashar <anikeshparashar at gmail.com>
Date: Tue, 20 Jan 2026 04:36:49 +0530
Subject: [PATCH 4/5] Remove redundant header inclusion

---
 libc/src/__support/math/logf.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libc/src/__support/math/logf.h b/libc/src/__support/math/logf.h
index c608e9d11b1dd..e8d6e879cf2a9 100644
--- a/libc/src/__support/math/logf.h
+++ b/libc/src/__support/math/logf.h
@@ -19,7 +19,6 @@
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 #include "src/__support/macros/properties/cpu_features.h"
 #include "src/__support/math/common_constants.h" // Lookup table for (1/f) and log(f)
-#include "src/math/logf.h"
 
 // This is an algorithm for log(x) in single precision which is correctly
 // rounded for all rounding modes, based on the implementation of log(x) from

>From 0d38e7eaadfef3e122ae0a28962e8dfc8215c744 Mon Sep 17 00:00:00 2001
From: Anikesh Parashar <anikeshparashar at gmail.com>
Date: Wed, 21 Jan 2026 17:29:30 +0530
Subject: [PATCH 5/5] use header implementation for logf

---
 libc/src/math/generic/logf.cpp | 129 +--------------------------------
 1 file changed, 1 insertion(+), 128 deletions(-)

diff --git a/libc/src/math/generic/logf.cpp b/libc/src/math/generic/logf.cpp
index 80b757ddf3658..863a9378d3135 100644
--- a/libc/src/math/generic/logf.cpp
+++ b/libc/src/math/generic/logf.cpp
@@ -43,133 +43,6 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
-LLVM_LIBC_FUNCTION(float, logf, (float x)) {
-  using namespace common_constants_internal;
-  constexpr double LOG_2 = 0x1.62e42fefa39efp-1;
-  using FPBits = typename fputil::FPBits<float>;
-
-  FPBits xbits(x);
-  uint32_t x_u = xbits.uintval();
-
-  int m = -FPBits::EXP_BIAS;
-
-  using fputil::round_result_slightly_down;
-  using fputil::round_result_slightly_up;
-
-  // Small inputs
-  if (x_u < 0x4c5d65a5U) {
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-    // Hard-to-round cases.
-    switch (x_u) {
-    case 0x3f7f4d6fU: // x = 0x1.fe9adep-1f
-      return round_result_slightly_up(-0x1.659ec8p-9f);
-    case 0x41178febU: // x = 0x1.2f1fd6p+3f
-      return round_result_slightly_up(0x1.1fcbcep+1f);
-#ifdef LIBC_TARGET_CPU_HAS_FMA
-    case 0x3f800000U: // x = 1.0f
-      return 0.0f;
-#else
-    case 0x1e88452dU: // x = 0x1.108a5ap-66f
-      return round_result_slightly_up(-0x1.6d7b18p+5f);
-#endif // LIBC_TARGET_CPU_HAS_FMA
-    }
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-    // Subnormal inputs.
-    if (LIBC_UNLIKELY(x_u < FPBits::min_normal().uintval())) {
-      if (x == 0.0f) {
-        // Return -inf and raise FE_DIVBYZERO
-        fputil::set_errno_if_required(ERANGE);
-        fputil::raise_except_if_required(FE_DIVBYZERO);
-        return FPBits::inf(Sign::NEG).get_val();
-      }
-      // Normalize denormal inputs.
-      xbits = FPBits(xbits.get_val() * 0x1.0p23f);
-      m -= 23;
-      x_u = xbits.uintval();
-    }
-  } else {
-#ifndef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-    // Hard-to-round cases.
-    switch (x_u) {
-    case 0x4c5d65a5U: // x = 0x1.bacb4ap+25f
-      return round_result_slightly_down(0x1.1e0696p+4f);
-    case 0x65d890d3U: // x = 0x1.b121a6p+76f
-      return round_result_slightly_down(0x1.a9a3f2p+5f);
-    case 0x6f31a8ecU: // x = 0x1.6351d8p+95f
-      return round_result_slightly_down(0x1.08b512p+6f);
-    case 0x7a17f30aU: // x = 0x1.2fe614p+117f
-      return round_result_slightly_up(0x1.451436p+6f);
-#ifndef LIBC_TARGET_CPU_HAS_FMA_DOUBLE
-    case 0x500ffb03U: // x = 0x1.1ff606p+33f
-      return round_result_slightly_up(0x1.6fdd34p+4f);
-    case 0x5cd69e88U: // x = 0x1.ad3d1p+58f
-      return round_result_slightly_up(0x1.45c146p+5f);
-    case 0x5ee8984eU: // x = 0x1.d1309cp+62f;
-      return round_result_slightly_up(0x1.5c9442p+5f);
-#endif // LIBC_TARGET_CPU_HAS_FMA_DOUBLE
-    }
-#endif // !LIBC_MATH_HAS_SKIP_ACCURATE_PASS
-    // Exceptional inputs.
-    if (LIBC_UNLIKELY(x_u > FPBits::max_normal().uintval())) {
-      if (x_u == 0x8000'0000U) {
-        // Return -inf and raise FE_DIVBYZERO
-        fputil::set_errno_if_required(ERANGE);
-        fputil::raise_except_if_required(FE_DIVBYZERO);
-        return FPBits::inf(Sign::NEG).get_val();
-      }
-      if (xbits.is_neg() && !xbits.is_nan()) {
-        // Return NaN and raise FE_INVALID
-        fputil::set_errno_if_required(EDOM);
-        fputil::raise_except_if_required(FE_INVALID);
-        return FPBits::quiet_nan().get_val();
-      }
-      // x is +inf or nan
-      if (xbits.is_signaling_nan()) {
-        fputil::raise_except_if_required(FE_INVALID);
-        return FPBits::quiet_nan().get_val();
-      }
-
-      return x;
-    }
-  }
-
-#ifndef LIBC_TARGET_CPU_HAS_FMA
-  // Returning the correct +0 when x = 1.0 for non-FMA targets with FE_DOWNWARD
-  // rounding mode.
-  if (LIBC_UNLIKELY((x_u & 0x007f'ffffU) == 0))
-    return static_cast<float>(
-        static_cast<double>(m + xbits.get_biased_exponent()) * LOG_2);
-#endif // LIBC_TARGET_CPU_HAS_FMA
-
-  uint32_t mant = xbits.get_mantissa();
-  // Extract 7 leading fractional bits of the mantissa
-  int index = mant >> 16;
-  // Add unbiased exponent. Add an extra 1 if the 7 leading fractional bits are
-  // all 1's.
-  m += static_cast<int>((x_u + (1 << 16)) >> 23);
-
-  // Set bits to 1.m
-  xbits.set_biased_exponent(0x7F);
-
-  float u = xbits.get_val();
-  double v;
-#ifdef LIBC_TARGET_CPU_HAS_FMA_FLOAT
-  v = static_cast<double>(fputil::multiply_add(u, R[index], -1.0f)); // Exact.
-#else
-  v = fputil::multiply_add(static_cast<double>(u), RD[index], -1.0); // Exact
-#endif // LIBC_TARGET_CPU_HAS_FMA_FLOAT
-
-  // Degree-5 polynomial approximation of log generated by Sollya with:
-  // > P = fpminimax(log(1 + x)/x, 4, [|1, D...|], [-2^-8, 2^-7]);
-  constexpr double COEFFS[4] = {-0x1.000000000fe63p-1, 0x1.555556e963c16p-2,
-                                -0x1.000028dedf986p-2, 0x1.966681bfda7f7p-3};
-  double v2 = v * v; // Exact
-  double p2 = fputil::multiply_add(v, COEFFS[3], COEFFS[2]);
-  double p1 = fputil::multiply_add(v, COEFFS[1], COEFFS[0]);
-  double p0 = LOG_R[index] + v;
-  double r = fputil::multiply_add(static_cast<double>(m), LOG_2,
-                                  fputil::polyeval(v2, p0, p1, p2));
-  return static_cast<float>(r);
-}
+LLVM_LIBC_FUNCTION(float, logf, (float x)) { return math::logf(x); }
 
 } // namespace LIBC_NAMESPACE_DECL



More information about the libc-commits mailing list