[libc-commits] [libc] [libc][math] Integer-only implementations of exp, expf (PR #209406)

Hoàng Minh Thiên via libc-commits libc-commits at lists.llvm.org
Tue Jul 14 01:49:54 PDT 2026


https://github.com/hmthien050209 created https://github.com/llvm/llvm-project/pull/209406

> [!NOTE]
> Still a WIP

Implementing the integer-only implementations of `exp` and `expf`.

Accuracy: TODO

Benchmarks: TODO

Code size: TODO

>From 4e9a7cdbdff8242471fc3cf0c2ae44f5271af385 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ho=C3=A0ng=20Minh=20Thi=C3=AAn?=
 <hoangminhthien05022009 at gmail.com>
Date: Tue, 14 Jul 2026 15:46:22 +0700
Subject: [PATCH] feat: initialize compilable stubs

---
 libc/src/__support/math/CMakeLists.txt      | 47 +++++++++++++
 libc/src/__support/math/exp_integer_eval.h  | 75 ++++++++++++++++++++
 libc/src/__support/math/exp_integer_utils.h | 42 +++++++++++
 libc/src/__support/math/expf_integer_eval.h | 77 +++++++++++++++++++++
 libc/src/math/generic/CMakeLists.txt        |  2 +
 libc/src/math/generic/exp.cpp               | 12 +++-
 libc/src/math/generic/expf.cpp              | 11 ++-
 7 files changed, 264 insertions(+), 2 deletions(-)
 create mode 100644 libc/src/__support/math/exp_integer_eval.h
 create mode 100644 libc/src/__support/math/exp_integer_utils.h
 create mode 100644 libc/src/__support/math/expf_integer_eval.h

diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index deafc85b487a6..2322f6f442527 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -3060,6 +3060,22 @@ add_header_library(
     libc.src.__support.macros.config
 )
 
+add_header_library(
+  expf_integer_eval
+  HDRS
+    expf_integer_eval.h
+  DEPENDS
+    # TODO: strip the below deps down if able to
+    .exp_constants
+    .exp_integer_utils
+    libc.src.__support.CPP.bit
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+    libc.src.__support.frac128
+)
+
 add_header_library(
   expf
   HDRS
@@ -4090,6 +4106,37 @@ add_header_library(
     libc.src.__support.macros.optimization
 )
 
+add_header_library(
+  exp_integer_utils
+  HDRS
+    exp_integer_utils.h
+  DEPENDS
+    # TODO: strip the below deps down if able to
+    .exp_constants
+    libc.src.__support.CPP.bit
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+    libc.src.__support.frac128
+)
+
+add_header_library(
+  exp_integer_eval
+  HDRS
+    exp_integer_eval.h
+  DEPENDS
+    # TODO: strip the below deps down if able to
+    .exp_constants
+    .exp_integer_utils
+    libc.src.__support.CPP.bit
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+    libc.src.__support.frac128
+)
+
 add_header_library(
   exp2
   HDRS
diff --git a/libc/src/__support/math/exp_integer_eval.h b/libc/src/__support/math/exp_integer_eval.h
new file mode 100644
index 0000000000000..890254e0c2720
--- /dev/null
+++ b/libc/src/__support/math/exp_integer_eval.h
@@ -0,0 +1,75 @@
+//===-- Implementation header for exp using integer-only --------*- 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_SRC___SUPPORT_MATH_EXP_INTEGER_EVAL_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_EXP_INTEGER_EVAL_H
+
+// TODO: clean up includes
+#include "src/__support/CPP/bit.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/frac128.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+#include "src/__support/math/exp_integer_utils.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+namespace integer_only {
+
+LIBC_INLINE double exp(double x) {
+  using FPBits = typename fputil::FPBits<double>;
+  FPBits xbits(x);
+
+  bool is_neg = xbits.is_neg();
+  uint16_t x_e = xbits.get_biased_exponent();
+  // uint64_t x_u = xbits.get_mantissa();
+
+  // Exceptional values
+  // TODO: optimize the branching order
+  if (xbits.is_zero()) {
+    // e^0 = 1 (exact), for both +/-0
+    return 1.0;
+  } else {
+    // x is inf or NaN
+    if (LIBC_UNLIKELY(x_e > 2 * FPBits::EXP_BIAS)) {
+      // e^NaN = NaN
+      if (xbits.is_signaling_nan()) {
+        // Per conversation with lntue, we don't need to raise exception here,
+        // as we're assuming no FPUs/fenv in this kind of environment
+
+        // Silencing
+        return FPBits::quiet_nan().get_val();
+      }
+
+      // e^-inf = 0
+      // e^+inf = +inf
+      if (xbits.is_inf()) {
+        return is_neg ? 0.0 : FPBits::inf().get_val();
+      }
+
+      // x is a quiet NaN
+      return x;
+    } else {
+      // TODO: out-of-range (overflow/underflow), exeecute range reduction
+    }
+  }
+
+  // TODO: execute the normal exp here;
+  return 0.0;
+}
+
+} // namespace integer_only
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXP_INTEGER_EVAL_H
diff --git a/libc/src/__support/math/exp_integer_utils.h b/libc/src/__support/math/exp_integer_utils.h
new file mode 100644
index 0000000000000..d6216b6ee183f
--- /dev/null
+++ b/libc/src/__support/math/exp_integer_utils.h
@@ -0,0 +1,42 @@
+//===-- e^x range reduction and evaluation using integer-only --*- 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
+//
+//===----------------------------------------------------------------------===//
+
+// TODO: update the description of this file above
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_EXP_INTEGER_UTILS_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_EXP_INTEGER_UTILS_H
+
+#include "src/__support/CPP/bit.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/big_int.h"
+#include "src/__support/frac128.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+#include "src/__support/math_extras.h"
+
+#undef LIBC_TARGET_IS_BIG_ENDIAN
+#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) ||           \
+    !defined(__ORDER_BIG_ENDIAN__)
+#define LIBC_TARGET_IS_BIG_ENDIAN 0
+#else
+#define LIBC_TARGET_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#endif // /LIBC_TARGET_IS_BIG_ENDIAN
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+namespace integer_only {} // namespace integer_only
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXP_INTEGER_UTILS_H
diff --git a/libc/src/__support/math/expf_integer_eval.h b/libc/src/__support/math/expf_integer_eval.h
new file mode 100644
index 0000000000000..c9ed6e1c19b58
--- /dev/null
+++ b/libc/src/__support/math/expf_integer_eval.h
@@ -0,0 +1,77 @@
+//===-- Implementation header for expf using integer-only --------*- 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_SRC___SUPPORT_MATH_EXP_INTEGER_EVAL_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_EXP_INTEGER_EVAL_H
+
+// TODO: clean up includes
+#include "src/__support/CPP/bit.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/frac128.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+#include "src/__support/math/exp_integer_utils.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+namespace integer_only {
+
+LIBC_INLINE float expf(float x) {
+  using FPBits = typename fputil::FPBits<float>;
+  FPBits xbits(x);
+
+  bool is_neg = xbits.is_neg();
+  uint16_t x_e = xbits.get_biased_exponent();
+  // uint64_t x_u = xbits.get_mantissa();
+
+  // Exceptional values
+  // TODO: optimize the branching order
+  // TODO: when updating these conditions, remember to update the
+  // exp_integer_eval.h's version also
+  if (xbits.is_zero()) {
+    // e^0 = 1 (exact), for both +/-0
+    return 1.0f;
+  } else {
+    // x is inf or NaN
+    if (LIBC_UNLIKELY(x_e > 2 * FPBits::EXP_BIAS)) {
+      // e^NaN = NaN
+      if (xbits.is_signaling_nan()) {
+        // Per conversation with lntue, we don't need to raise exception here,
+        // as we're assuming no FPUs/fenv in this kind of environment
+
+        // silencing
+        return FPBits::quiet_nan().get_val();
+      }
+
+      // e^-inf = 0
+      // e^+inf = +inf
+      if (xbits.is_inf()) {
+        return is_neg ? 0.0f : FPBits::inf().get_val();
+      }
+
+      // x is a quiet NaN
+      return x;
+    } else {
+      // TODO: out-of-range (overflow/underflow), exeecute range reduction
+    }
+  }
+
+  // TODO: execute the normal exp here
+  return 0.0f;
+}
+
+} // namespace integer_only
+
+} // namespace math
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXP_INTEGER_EVAL_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 28b708e0c8f7a..1daeb41def4ad 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -1216,6 +1216,7 @@ add_entrypoint_object(
     ../exp.h
   DEPENDS
     libc.src.__support.math.exp
+    libc.src.__support.math.exp_integer_eval
     libc.src.errno.errno
 )
 
@@ -1227,6 +1228,7 @@ add_entrypoint_object(
     ../expf.h
   DEPENDS
     libc.src.__support.math.expf
+    libc.src.__support.math.expf_integer_eval
     libc.src.errno.errno
 )
 
diff --git a/libc/src/math/generic/exp.cpp b/libc/src/math/generic/exp.cpp
index dc4d2ca480cb8..2e831a790a44a 100644
--- a/libc/src/math/generic/exp.cpp
+++ b/libc/src/math/generic/exp.cpp
@@ -8,8 +8,18 @@
 
 #include "src/math/exp.h"
 #include "src/__support/math/exp.h"
+#include "src/__support/math/exp_integer_eval.h"
+
 namespace LIBC_NAMESPACE_DECL {
 
-LLVM_LIBC_FUNCTION(double, exp, (double x)) { return math::exp(x); }
+LLVM_LIBC_FUNCTION(double, exp, (double x)) {
+#if defined(LIBC_MATH_HAS_SKIP_ACCURATE_PASS) &&                               \
+    defined(LIBC_MATH_SMALL_TABLES) &&                                         \
+    !defined(LIBC_TARGET_CPU_HAS_FPU_DOUBLE)
+  return math::integer_only::exp(x);
+#else
+  return math::exp(x);
+#endif
+}
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/generic/expf.cpp b/libc/src/math/generic/expf.cpp
index de11f51ac64a0..de8a97a46f1af 100644
--- a/libc/src/math/generic/expf.cpp
+++ b/libc/src/math/generic/expf.cpp
@@ -8,9 +8,18 @@
 
 #include "src/math/expf.h"
 #include "src/__support/math/expf.h"
+#include "src/__support/math/expf_integer_eval.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
-LLVM_LIBC_FUNCTION(float, expf, (float x)) { return math::expf(x); }
+LLVM_LIBC_FUNCTION(float, expf, (float x)) {
+#if defined(LIBC_MATH_HAS_SKIP_ACCURATE_PASS) &&                               \
+    defined(LIBC_MATH_SMALL_TABLES) &&                                         \
+    !defined(LIBC_TARGET_CPU_HAS_FPU_DOUBLE)
+  return math::integer_only::expf(x);
+#else
+  return math::expf(x);
+#endif
+}
 
 } // namespace LIBC_NAMESPACE_DECL



More information about the libc-commits mailing list