[libc-commits] [libc] [llvm] [libc][math] Add ExceptValues table for log1pf16 hard-to-round cases (PR #224152)

Youssef Ahmed via libc-commits libc-commits at lists.llvm.org
Fri Sep 18 01:55:03 PDT 2026


https://github.com/usefahmed07 updated https://github.com/llvm/llvm-project/pull/224152

>From 94cc36ef3df05b45c6fce9814c9b2cd20b484c48 Mon Sep 17 00:00:00 2001
From: usefahmed07 <youssef.ahmed.hamaza at gmail.com>
Date: Thu, 17 Sep 2026 01:32:02 +0300
Subject: [PATCH 1/2] [libc][math] Add ExceptValues table for log1pf16
 hard-to-round cases

Fixes #189543
---
 libc/config/linux/x86_64/entrypoints.txt |   1 +
 libc/src/__support/math/log1pf16.h       | 141 +++++++++++++++++++++++
 libc/src/math/CMakeLists.txt             |   1 +
 libc/src/math/generic/CMakeLists.txt     |  11 ++
 libc/src/math/generic/log1pf16.cpp       |  18 +++
 libc/src/math/log1pf16.h                 |  21 ++++
 6 files changed, 193 insertions(+)
 create mode 100644 libc/src/__support/math/log1pf16.h
 create mode 100644 libc/src/math/generic/log1pf16.cpp
 create mode 100644 libc/src/math/log1pf16.h

diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 3f4e563e54359..81b4ba218458f 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -977,6 +977,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.llroundf16
     libc.src.math.log10f16
     libc.src.math.log10p1f16
+    libc.src.math.log1pf16
     libc.src.math.log2f16
     libc.src.math.log2p1f16
     libc.src.math.logbf16
diff --git a/libc/src/__support/math/log1pf16.h b/libc/src/__support/math/log1pf16.h
new file mode 100644
index 0000000000000..14b1a227a2aae
--- /dev/null
+++ b/libc/src/__support/math/log1pf16.h
@@ -0,0 +1,141 @@
+//===-- Implementation header for log1pf16 -----------------------*- 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_LOG1PF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_LOG1PF16_H
+
+#include "include/llvm-libc-macros/float16-macros.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "expxf16_utils.h"
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/cast.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"
+#include "src/__support/macros/properties/cpu_features.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+namespace math {
+
+LIBC_INLINE float16 log1pf16(float16 x) {
+  using namespace math::expxf16_internal;
+  using FPBits = fputil::FPBits<float16>;
+  FPBits x_bits(x);
+
+  uint16_t x_u = x_bits.uintval();
+  uint16_t x_abs = x_u & 0x7fffU;
+
+  constexpr size_t N_LOG1PF16_EXCEPTS = 6;
+  constexpr fputil::ExceptValues<float16, N_LOG1PF16_EXCEPTS>
+      LOG1PF16_EXCEPTS = {{
+          // (input, RZ output, RU offset, RD offset, RN offset)
+          // x = 0x1.f24p-7, log1pf16(x) = 0x1.ee4p-7 (RZ)
+          {0x23C9U, 0x23B9U, 1U, 0U, 1U},
+          // x = 0x1.988p0, log1pf16(x) = 0x1.e84p-1 (RZ)
+          {0x3E62U, 0x3BA1U, 1U, 0U, 1U},
+          // x = -0x1.e5p-7, log1pf16(x) = -0x1.e88p-7 (RZ)
+          {0xA394U, 0xA3A2U, 0U, 1U, 1U},
+          // x = -0x1.ed4p-7, log1pf16(x) = -0x1.f1p-7 (RZ)
+          {0xA3B5U, 0xA3C4U, 0U, 1U, 0U},
+          // x = -0x1.ae4p-6, log1pf16(x) = -0x1.b4p-6 (RZ)
+          {0xA6B9U, 0xA6D0U, 0U, 1U, 0U},
+          // x = -0x1.f6cp-6, log1pf16(x) = -0x1.fe8p-6 (RZ)
+          {0xA7DBU, 0xA7FAU, 0U, 1U, 1U},
+      }};
+
+  if (auto r = LOG1PF16_EXCEPTS.lookup(x_u); LIBC_UNLIKELY(r.has_value()))
+    return r.value();
+
+  // If x is NaN, +/-inf, or |x| <= 2^-3.
+  if (LIBC_UNLIKELY(x_abs <= 0x3000U || x_abs >= 0x7c00U)) {
+    if (x_bits.is_nan()) {
+      if (x_bits.is_signaling_nan()) {
+        fputil::raise_except_if_required(FE_INVALID);
+        return FPBits::quiet_nan().get_val();
+      }
+      return x;
+    }
+
+    if (x_abs <= 0x3000U) {
+      // log1p(+/-0) = +/-0
+      if (x_abs == 0U)
+        return x;
+
+      // Degree-5 minimax polynomial generated by Sollya with:
+      //   > display = hexadecimal;
+      //   > P = fpminimax(log(1 + x)/x, [|0, 1, 2, 3, 4|], [|SG...|],
+      //                   [-2^-3, 2^-3]);
+      //   > x * P;
+      //   > dirtyinfnorm((log(1 + x) - x*P) / log(1 + x), [-2^-3, 2^-3]);
+      //   0x1.65afe505af70502b729765651fe9ef9d2071f0f89p-22
+      float xf = x;
+      return fputil::cast<float16>(
+          xf * fputil::polyeval(xf, 0x1p+0f, -0x1.fffc9cp-2f, 0x1.555174p-2f,
+                                -0x1.03601ap-2f, 0x1.9ff8eep-3f));
+    }
+
+    if (x_u == 0x7c00U)
+      return FPBits::inf().get_val();
+
+    fputil::set_errno_if_required(EDOM);
+    fputil::raise_except_if_required(FE_INVALID);
+    return FPBits::quiet_nan().get_val();
+  }
+
+  // log1p(-1) = -inf
+  if (LIBC_UNLIKELY(x_u == 0xbc00U)) {
+    fputil::raise_except_if_required(FE_DIVBYZERO);
+    return FPBits::inf(Sign::NEG).get_val();
+  }
+
+  // log1p(x) = NaN for x < -1
+  if (LIBC_UNLIKELY(x_u > 0xbc00U)) {
+    fputil::set_errno_if_required(EDOM);
+    fputil::raise_except_if_required(FE_INVALID);
+    return FPBits::quiet_nan().get_val();
+  }
+
+  float xf = x;
+  float y = 1.0f + xf;
+
+  using FPBitsFloat = fputil::FPBits<float>;
+  FPBitsFloat y_bits(y);
+
+  if (LIBC_UNLIKELY(y_bits.is_zero()))
+    return FPBits::inf(Sign::NEG).get_val();
+
+  int m = y_bits.get_exponent();
+  y_bits.set_biased_exponent(FPBitsFloat::EXP_BIAS);
+  float mant_f = y_bits.get_val();
+  int f = y_bits.get_mantissa() >> (FPBitsFloat::FRACTION_LEN - 5);
+
+  float v = fputil::multiply_add(mant_f, ONE_OVER_F_F[f], -1.0f);
+
+  // Reusing the same log(1+v)/v minimax poly already used in logf16.h.
+  float log1p_d_over_f =
+      v * fputil::polyeval(v, 0x1p+0f, -0x1.001804p-1f, 0x1.557ef6p-2f);
+  float log_1_mant = LOGF_F[f] + log1p_d_over_f;
+  return fputil::cast<float16>(
+      fputil::multiply_add(static_cast<float>(m), LOGF_2, log_1_mant));
+}
+
+} // namespace math
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#endif // LLVM_LIBC_SRC___SUPPORT_MATH_LOG1PF16_H
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 2c7568f0b6361..1cbcc282f6948 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -405,6 +405,7 @@ add_math_entrypoint_object(log10p1f16)
 
 add_math_entrypoint_object(log1p)
 add_math_entrypoint_object(log1pf)
+add_math_entrypoint_object(log1pf16)
 
 add_math_entrypoint_object(log2)
 add_math_entrypoint_object(log2f)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 28b8e954530dd..03a6106959b81 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -1791,6 +1791,17 @@ add_entrypoint_object(
     libc.src.errno.errno
 )
 
+add_entrypoint_object(
+  log1pf16
+  SRCS
+    log1pf16.cpp
+  HDRS
+    ../log1pf16.h
+  DEPENDS
+    libc.src.__support.math.log1pf16
+    libc.src.errno.errno
+)
+
 add_entrypoint_object(
   log2p1f16
   SRCS
diff --git a/libc/src/math/generic/log1pf16.cpp b/libc/src/math/generic/log1pf16.cpp
new file mode 100644
index 0000000000000..123426202d7dd
--- /dev/null
+++ b/libc/src/math/generic/log1pf16.cpp
@@ -0,0 +1,18 @@
+//===-- Half-precision log(1+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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/math/log1pf16.h"
+#include "src/__support/math/log1pf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(float16, log1pf16, (float16 x)) {
+  return math::log1pf16(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/log1pf16.h b/libc/src/math/log1pf16.h
new file mode 100644
index 0000000000000..2fdfe19bf7da9
--- /dev/null
+++ b/libc/src/math/log1pf16.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for log1pf16 -----------------------*- 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_MATH_LOG1PF16_H
+#define LLVM_LIBC_SRC_MATH_LOG1PF16_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float16 log1pf16(float16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_LOG1PF16_H

>From ec3d757ec97961256b03437260edfc49a3bcd78d Mon Sep 17 00:00:00 2001
From: usefahmed07 <youssef.ahmed.hamaza at gmail.com>
Date: Fri, 18 Sep 2026 11:54:26 +0300
Subject: [PATCH 2/2] [libc][math] Complete registration checklist for log1pf16

Adds math.yaml entry, entrypoints across all supported platforms
(gpu/amdgpu, gpu/nvptx, baremetal/riscv, baremetal/aarch64,
freebsd/x86_64, darwin/aarch64, linux/riscv, linux/aarch64), and
shared math library support (shared/math.h, shared/math/log1pf16.h,
shared_math_test.cpp) per the add_math_function.md checklist.
---
 libc/config/baremetal/aarch64/entrypoints.txt |  1 +
 libc/config/baremetal/riscv/entrypoints.txt   |  1 +
 libc/config/darwin/aarch64/entrypoints.txt    |  1 +
 libc/config/freebsd/x86_64/entrypoints.txt    |  1 +
 libc/config/gpu/amdgpu/entrypoints.txt        |  1 +
 libc/config/gpu/nvptx/entrypoints.txt         |  1 +
 libc/config/linux/aarch64/entrypoints.txt     |  1 +
 libc/config/linux/riscv/entrypoints.txt       |  1 +
 libc/include/math.yaml                        |  7 +++
 libc/shared/math.h                            |  1 +
 libc/shared/math/log1pf16.h                   | 29 +++++++++++
 libc/src/__support/math/CMakeLists.txt        | 18 +++++++
 libc/test/shared/CMakeLists.txt               |  1 +
 libc/test/shared/shared_math_test.cpp         |  1 +
 libc/test/src/math/CMakeLists.txt             | 11 +++++
 libc/test/src/math/log1pf16_test.cpp          | 49 +++++++++++++++++++
 libc/test/src/math/smoke/CMakeLists.txt       | 13 +++++
 libc/test/src/math/smoke/log1pf16_test.cpp    | 48 ++++++++++++++++++
 .../llvm-project-overlay/libc/BUILD.bazel     | 28 +++++++++++
 .../libc/test/src/math/BUILD.bazel            |  2 +
 20 files changed, 216 insertions(+)
 create mode 100644 libc/shared/math/log1pf16.h
 create mode 100644 libc/test/src/math/log1pf16_test.cpp
 create mode 100644 libc/test/src/math/smoke/log1pf16_test.cpp

diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index 757e4729699d1..88848562eb694 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -699,6 +699,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.log10f16
     libc.src.math.log10p1f16
     libc.src.math.log2f16
+    libc.src.math.log1pf16
     libc.src.math.log2p1f16
     libc.src.math.logbf16
     libc.src.math.logf16
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 622d6156cff11..a1d9806a87f51 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -707,6 +707,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.log10f16
     libc.src.math.log10p1f16
     libc.src.math.log2f16
+    libc.src.math.log1pf16
     libc.src.math.log2p1f16
     libc.src.math.logbf16
     libc.src.math.logf16
diff --git a/libc/config/darwin/aarch64/entrypoints.txt b/libc/config/darwin/aarch64/entrypoints.txt
index d702b2c5a6549..19f5324e71114 100644
--- a/libc/config/darwin/aarch64/entrypoints.txt
+++ b/libc/config/darwin/aarch64/entrypoints.txt
@@ -526,6 +526,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.log10f16
     libc.src.math.log10p1f16
     libc.src.math.log2f16
+    libc.src.math.log1pf16
     libc.src.math.log2p1f16
     libc.src.math.logbf16
     libc.src.math.logf16
diff --git a/libc/config/freebsd/x86_64/entrypoints.txt b/libc/config/freebsd/x86_64/entrypoints.txt
index 8f6c178301c2f..60ce0a98e6f05 100644
--- a/libc/config/freebsd/x86_64/entrypoints.txt
+++ b/libc/config/freebsd/x86_64/entrypoints.txt
@@ -468,6 +468,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.log10f16
     libc.src.math.log10p1f16
     libc.src.math.log2f16
+    libc.src.math.log1pf16
     libc.src.math.log2p1f16
     libc.src.math.logbf16
     libc.src.math.logf16
diff --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt
index 5c5e5891da822..c8a3df8da9256 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -640,6 +640,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.log10f16
     libc.src.math.log10p1f16
     libc.src.math.log2f16
+    libc.src.math.log1pf16
     libc.src.math.log2p1f16
     libc.src.math.logbf16
     libc.src.math.logf16
diff --git a/libc/config/gpu/nvptx/entrypoints.txt b/libc/config/gpu/nvptx/entrypoints.txt
index afae725484a89..ceb0f59b379dd 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -638,6 +638,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.log10f16
     libc.src.math.log10p1f16
     libc.src.math.log2f16
+    libc.src.math.log1pf16
     libc.src.math.log2p1f16
     libc.src.math.logbf16
     libc.src.math.logf16
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index a63d6ad6282c1..fa433ccd3de56 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -887,6 +887,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.llrintf16
     libc.src.math.llroundf16
     libc.src.math.log10p1f16
+    libc.src.math.log1pf16
     libc.src.math.log2p1f16
     libc.src.math.logbf16
     libc.src.math.lrintf16
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index e8180cbb0c70e..462b59ba77a3c 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -967,6 +967,7 @@ if(LIBC_TYPES_HAS_FLOAT16)
     libc.src.math.log10f16
     libc.src.math.log10p1f16
     libc.src.math.log2f16
+    libc.src.math.log1pf16
     libc.src.math.log2p1f16
     libc.src.math.logbf16
     libc.src.math.logf16
diff --git a/libc/include/math.yaml b/libc/include/math.yaml
index 006233e579f86..84ef73c323819 100644
--- a/libc/include/math.yaml
+++ b/libc/include/math.yaml
@@ -1868,6 +1868,13 @@ functions:
     arguments:
       - type: _Float16
     guard: LIBC_TYPES_HAS_FLOAT16
+  - name: log1pf16
+    standards:
+      - stdc
+    return_type: _Float16
+    arguments:
+      - type: _Float16
+    guard: LIBC_TYPES_HAS_FLOAT16
   - name: log2p1f16
     standards:
       - stdc
diff --git a/libc/shared/math.h b/libc/shared/math.h
index 7b52cedf99c24..0c883b5d480b2 100644
--- a/libc/shared/math.h
+++ b/libc/shared/math.h
@@ -337,6 +337,7 @@
 #include "math/log10p1f16.h"
 #include "math/log1p.h"
 #include "math/log1pf.h"
+#include "math/log1pf16.h"
 #include "math/log2.h"
 #include "math/log2f.h"
 #include "math/log2f16.h"
diff --git a/libc/shared/math/log1pf16.h b/libc/shared/math/log1pf16.h
new file mode 100644
index 0000000000000..5622b03eba366
--- /dev/null
+++ b/libc/shared/math/log1pf16.h
@@ -0,0 +1,29 @@
+//===-- Shared log1pf16 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_LOG1PF16_H
+#define LLVM_LIBC_SHARED_MATH_LOG1PF16_H
+
+#include "include/llvm-libc-macros/float16-macros.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#include "shared/libc_common.h"
+#include "src/__support/math/log1pf16.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace shared {
+
+using math::log1pf16;
+
+} // namespace shared
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LIBC_TYPES_HAS_FLOAT16
+
+#endif // LLVM_LIBC_SHARED_MATH_LOG1PF16_H
diff --git a/libc/src/__support/math/CMakeLists.txt b/libc/src/__support/math/CMakeLists.txt
index 0871a5bf229b6..1c3fbd2ff9c42 100644
--- a/libc/src/__support/math/CMakeLists.txt
+++ b/libc/src/__support/math/CMakeLists.txt
@@ -5066,6 +5066,24 @@ add_header_library(
     libc.src.__support.macros.properties.cpu_features
 )
 
+add_header_library(
+  log1pf16
+  HDRS
+    log1pf16.h
+  DEPENDS
+    .expxf16_utils
+    libc.hdr.errno_macros
+    libc.hdr.fenv_macros
+    libc.src.__support.FPUtil.cast
+    libc.src.__support.FPUtil.except_value_utils
+    libc.src.__support.FPUtil.fenv_impl
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.FPUtil.multiply_add
+    libc.src.__support.FPUtil.polyeval
+    libc.src.__support.macros.optimization
+    libc.src.__support.macros.properties.cpu_features
+)
+
 add_header_library(
   log2p1f16
   HDRS
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index 74eda7cdaf065..749218b759dd4 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -334,6 +334,7 @@ else()
       libc.src.__support.math.log10f
       libc.src.__support.math.log1p
       libc.src.__support.math.log1pf
+      libc.src.__support.math.log1pf16
       libc.src.__support.math.log2
       libc.src.__support.math.logb
       libc.src.__support.math.log2f
diff --git a/libc/test/shared/shared_math_test.cpp b/libc/test/shared/shared_math_test.cpp
index 7b785331f36c6..d926f52998b69 100644
--- a/libc/test/shared/shared_math_test.cpp
+++ b/libc/test/shared/shared_math_test.cpp
@@ -60,6 +60,7 @@ TEST(LlvmLibcSharedMathTest, AllFloat16) {
   EXPECT_FP_EQ(1.0f16, LIBC_NAMESPACE::shared::log10f16(10.0f16));
   EXPECT_FP_EQ(1.0f16, LIBC_NAMESPACE::shared::log10p1f16(9.0f16));
   EXPECT_FP_EQ(1.0f16, LIBC_NAMESPACE::shared::log2f16(2.0f16));
+  EXPECT_FP_EQ(0.0f16, LIBC_NAMESPACE::shared::log1pf16(0.0f16));
   EXPECT_FP_EQ(1.0f16, LIBC_NAMESPACE::shared::log2p1f16(1.0f16));
   EXPECT_FP_EQ(0.0f16, LIBC_NAMESPACE::shared::logbf16(1.0f16));
   EXPECT_FP_EQ(0.0f16, LIBC_NAMESPACE::shared::lgammaf16(1.0f16));
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index 8f1a543de0a5e..6d6c9c1a7c67e 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2488,6 +2488,17 @@ add_fp_unittest(
     libc.src.math.log10p1f16
 )
 
+add_fp_unittest(
+  log1pf16_test
+  NEED_MPFR
+  SUITE
+    libc-math-unittests
+  SRCS
+    log1pf16_test.cpp
+  DEPENDS
+    libc.src.math.log1pf16
+)
+
 add_fp_unittest(
   log2p1f16_test
   NEED_MPFR
diff --git a/libc/test/src/math/log1pf16_test.cpp b/libc/test/src/math/log1pf16_test.cpp
new file mode 100644
index 0000000000000..e671aa670fece
--- /dev/null
+++ b/libc/test/src/math/log1pf16_test.cpp
@@ -0,0 +1,49 @@
+//===-- Exhaustive test for log1pf16 --------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/macros/optimization.h"
+#include "src/math/log1pf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+#ifdef LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+#define TOLERANCE 1
+#else
+#define TOLERANCE 0
+#endif // LIBC_MATH_HAS_SKIP_ACCURATE_PASS
+
+using LlvmLibcLog1pf16Test = LIBC_NAMESPACE::testing::FPTest<float16>;
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+// Range: [0, Inf];
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7c00U;
+
+// Range: [-1, 0];
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xbc00U;
+
+TEST_F(LlvmLibcLog1pf16Test, PositiveRange) {
+  for (uint16_t v = POS_START; v <= POS_STOP; ++v) {
+    float16 x = FPBits(v).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log1p, x,
+                                   LIBC_NAMESPACE::log1pf16(x),
+                                   TOLERANCE + 0.5);
+  }
+}
+
+TEST_F(LlvmLibcLog1pf16Test, NegativeRange) {
+  for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) {
+    float16 x = FPBits(v).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log1p, x,
+                                   LIBC_NAMESPACE::log1pf16(x),
+                                   TOLERANCE + 0.5);
+  }
+}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index a61b854a85fb2..5da6ccb6bcb0a 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4591,6 +4591,19 @@ add_fp_unittest(
     libc.src.__support.FPUtil.cast
 )
 
+add_fp_unittest(
+  log1pf16_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    log1pf16_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.fenv_macros
+    libc.src.math.log1pf16
+    libc.src.__support.FPUtil.cast
+)
+
 add_fp_unittest(
   log2p1f16_test
   SUITE
diff --git a/libc/test/src/math/smoke/log1pf16_test.cpp b/libc/test/src/math/smoke/log1pf16_test.cpp
new file mode 100644
index 0000000000000..da0a0653981f2
--- /dev/null
+++ b/libc/test/src/math/smoke/log1pf16_test.cpp
@@ -0,0 +1,48 @@
+//===-- Unittests for log1pf16 --------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/math/log1pf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcLog1pf16Test = LIBC_NAMESPACE::testing::FPTest<float16>;
+
+TEST_F(LlvmLibcLog1pf16Test, SpecialNumbers) {
+  EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::log1pf16(aNaN));
+  EXPECT_MATH_ERRNO(0);
+
+  EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::log1pf16(sNaN),
+                              FE_INVALID);
+  EXPECT_MATH_ERRNO(0);
+
+  EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::log1pf16(inf));
+  EXPECT_MATH_ERRNO(0);
+
+  EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::log1pf16(neg_inf));
+  EXPECT_MATH_ERRNO(EDOM);
+
+  EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::log1pf16(zero));
+  EXPECT_MATH_ERRNO(0);
+
+  EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, LIBC_NAMESPACE::log1pf16(neg_zero));
+  EXPECT_MATH_ERRNO(0);
+
+  EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+      neg_inf,
+      LIBC_NAMESPACE::log1pf16(LIBC_NAMESPACE::fputil::cast<float16>(-1.0)),
+      FE_DIVBYZERO);
+  EXPECT_MATH_ERRNO(0);
+
+  EXPECT_FP_EQ_ALL_ROUNDING(
+      aNaN,
+      LIBC_NAMESPACE::log1pf16(LIBC_NAMESPACE::fputil::cast<float16>(-2.0)));
+  EXPECT_MATH_ERRNO(EDOM);
+}
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 751096294f26f..ec952d0e58218 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -9912,6 +9912,27 @@ libc_support_library(
     ],
 )
 
+libc_support_library(
+    name = "__support_math_log1pf16",
+    hdrs = ["src/__support/math/log1pf16.h"],
+    deps = [
+        ":__support_common",
+        ":__support_fputil_cast",
+        ":__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_expxf16_utils",
+        ":hdr_errno_macros",
+        ":hdr_fenv_macros",
+        ":llvm_libc_macros_float16_macros",
+    ],
+)
+
 libc_support_library(
     name = "__support_math_log2p1f16",
     hdrs = ["src/__support/math/log2p1f16.h"],
@@ -13741,6 +13762,13 @@ libc_math_function(
     ],
 )
 
+libc_math_function(
+    name = "log1pf16",
+    additional_deps = [
+        ":__support_math_log1pf16",
+    ],
+)
+
 libc_math_function(
     name = "log2p1f16",
     additional_deps = [
diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel
index 8e5706c085f39..c77d5fe99d532 100644
--- a/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel
@@ -938,6 +938,8 @@ math_mpfr_test(name = "logf16")
 
 math_mpfr_test(name = "log2f16")
 
+math_mpfr_test(name = "log1pf16")
+
 math_mpfr_test(name = "log2p1f16")
 
 math_mpfr_test(name = "log10f16")



More information about the libc-commits mailing list