[libc-commits] [libc] [libc][math][c++23] Add log2bf16 math function (PR #177275)

via libc-commits libc-commits at lists.llvm.org
Wed Jan 21 15:45:57 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Krishna Pandey (krishna2803)

<details>
<summary>Changes</summary>

This PR adds log2bf16 higher math function for BFloat16 type along with the tests.


---
Full diff: https://github.com/llvm/llvm-project/pull/177275.diff


21 Files Affected:

- (modified) libc/config/baremetal/aarch64/entrypoints.txt (+1) 
- (modified) libc/config/baremetal/arm/entrypoints.txt (+1) 
- (modified) libc/config/baremetal/riscv/entrypoints.txt (+1) 
- (modified) libc/config/darwin/aarch64/entrypoints.txt (+1) 
- (modified) libc/config/darwin/x86_64/entrypoints.txt (+1) 
- (modified) libc/config/gpu/amdgpu/entrypoints.txt (+1) 
- (modified) libc/config/gpu/nvptx/entrypoints.txt (+1) 
- (modified) libc/config/linux/aarch64/entrypoints.txt (+1) 
- (modified) libc/config/linux/arm/entrypoints.txt (+1) 
- (modified) libc/config/linux/riscv/entrypoints.txt (+1) 
- (modified) libc/config/linux/x86_64/entrypoints.txt (+1) 
- (modified) libc/config/windows/entrypoints.txt (+1) 
- (modified) libc/docs/headers/math/index.rst (+2-2) 
- (modified) libc/src/math/CMakeLists.txt (+1) 
- (modified) libc/src/math/generic/CMakeLists.txt (+15) 
- (added) libc/src/math/generic/log2bf16.cpp (+121) 
- (added) libc/src/math/log2bf16.h (+21) 
- (modified) libc/test/src/math/CMakeLists.txt (+12) 
- (added) libc/test/src/math/log2bf16_test.cpp (+41) 
- (modified) libc/test/src/math/smoke/CMakeLists.txt (+13) 
- (added) libc/test/src/math/smoke/log2bf16_test.cpp (+52) 


``````````diff
diff --git a/libc/config/baremetal/aarch64/entrypoints.txt b/libc/config/baremetal/aarch64/entrypoints.txt
index 742d96761c415..a37c65e87e8ff 100644
--- a/libc/config/baremetal/aarch64/entrypoints.txt
+++ b/libc/config/baremetal/aarch64/entrypoints.txt
@@ -817,6 +817,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log2bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 95cb0dea8e49e..b901081417818 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -820,6 +820,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log2bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 3fc71280f5163..3b66cf4fbfdce 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -818,6 +818,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log2bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/darwin/aarch64/entrypoints.txt b/libc/config/darwin/aarch64/entrypoints.txt
index 3909417f9730d..5c7881f50ecf4 100644
--- a/libc/config/darwin/aarch64/entrypoints.txt
+++ b/libc/config/darwin/aarch64/entrypoints.txt
@@ -634,6 +634,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log2bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/darwin/x86_64/entrypoints.txt b/libc/config/darwin/x86_64/entrypoints.txt
index e899bf97ea3f6..edd67cfdeb0d1 100644
--- a/libc/config/darwin/x86_64/entrypoints.txt
+++ b/libc/config/darwin/x86_64/entrypoints.txt
@@ -276,6 +276,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log2bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/gpu/amdgpu/entrypoints.txt b/libc/config/gpu/amdgpu/entrypoints.txt
index 0dda7d5c683ec..4c02cf4bae6ac 100644
--- a/libc/config/gpu/amdgpu/entrypoints.txt
+++ b/libc/config/gpu/amdgpu/entrypoints.txt
@@ -659,6 +659,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log2bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/gpu/nvptx/entrypoints.txt b/libc/config/gpu/nvptx/entrypoints.txt
index 6070fb5b17b3c..454c14021c046 100644
--- a/libc/config/gpu/nvptx/entrypoints.txt
+++ b/libc/config/gpu/nvptx/entrypoints.txt
@@ -661,6 +661,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log2bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 970c825bbfc96..dd64ecd6f1327 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -890,6 +890,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log2bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index f04ac40145d3a..0fce31dc2efd5 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -503,6 +503,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log2bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 7baf4de9d8a5b..405403f4fb6ae 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -911,6 +911,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log2bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 9399b284fa2da..c08515cd3db3c 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -957,6 +957,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log2bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt
index 3a76595b258e2..45d8b8400578d 100644
--- a/libc/config/windows/entrypoints.txt
+++ b/libc/config/windows/entrypoints.txt
@@ -349,6 +349,7 @@ list(APPEND TARGET_LIBM_ENTRYPOINTS
   libc.src.math.llogbbf16
   libc.src.math.llrintbf16
   libc.src.math.llroundbf16
+  libc.src.math.log2bf16
   libc.src.math.log_bf16
   libc.src.math.logbbf16
   libc.src.math.lrintbf16
diff --git a/libc/docs/headers/math/index.rst b/libc/docs/headers/math/index.rst
index 51bb17ff8dab6..57c97b3558715 100644
--- a/libc/docs/headers/math/index.rst
+++ b/libc/docs/headers/math/index.rst
@@ -327,7 +327,7 @@ Higher Math Functions
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
 | log1p     | |check|          | |check|         |                        |                      |                        |                        | 7.12.6.14              | F.10.3.14                  |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
-| log2      | |check|          | |check|         |                        | |check|              |                        |                        | 7.12.6.15              | F.10.3.15                  |
+| log2      | |check|          | |check|         |                        | |check|              |                        | |check|                | 7.12.6.15              | F.10.3.15                  |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
 | log2p1    |                  |                 |                        |                      |                        |                        | 7.12.6.16              | F.10.3.16                  |
 +-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+------------------------+----------------------------+
@@ -636,4 +636,4 @@ References
 * `The GNU C Library (glibc) <https://www.gnu.org/software/libc/>`_.
 * `The GNU MPFR Library <https://www.mpfr.org/>`_.
 * `C++23 Standard <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4950.pdf>`_.
-* `BFloat16 <https://en.wikipedia.org/wiki/Bfloat16_floating-point_format>`_.
\ No newline at end of file
+* `BFloat16 <https://en.wikipedia.org/wiki/Bfloat16_floating-point_format>`_.
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index e37e22fdb58e6..fd02a737934d4 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -388,6 +388,7 @@ add_math_entrypoint_object(log1pf)
 add_math_entrypoint_object(log2)
 add_math_entrypoint_object(log2f)
 add_math_entrypoint_object(log2f16)
+add_math_entrypoint_object(log2bf16)
 
 add_math_entrypoint_object(log)
 add_math_entrypoint_object(logf)
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index 6e58434415ead..44a3bfbeb16a7 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -2069,6 +2069,21 @@ add_entrypoint_object(
     libc.src.__support.math.expxf16_utils
 )
 
+add_entrypoint_object(
+  log2bf16
+  SRCS
+    log2bf16.cpp
+  HDRS
+    ../log2bf16.h
+  DEPENDS
+    libc.src.__support.common
+    libc.src.__support.FPUtil.bfloat16
+    libc.src.__support.FPUtil.cast
+    libc.src.__support.FPUtil.fp_bits
+    libc.src.__support.macros.config
+    libc.src.__support.macros.optimization
+)
+
 add_entrypoint_object(
   log
   SRCS
diff --git a/libc/src/math/generic/log2bf16.cpp b/libc/src/math/generic/log2bf16.cpp
new file mode 100644
index 0000000000000..0158b58b1f79a
--- /dev/null
+++ b/libc/src/math/generic/log2bf16.cpp
@@ -0,0 +1,121 @@
+//===-- BFloat16 log2(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/log2bf16.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+// Generated by Sollya with the following commands:
+//   > display = hexadecimal;
+//   > for i from 0 to 127 do print(round(log2(1 + i * 2^-7), SG, RN));
+static constexpr float LOG2F_1_PLUS_M[128] = {
+    0x0.0p0f,       0x1.6fe50cp-7f, 0x1.6e7968p-6f, 0x1.11cd1ep-5f,
+    0x1.6bad38p-5f, 0x1.c4dfacp-5f, 0x1.0eb38ap-4f, 0x1.3aa2fep-4f,
+    0x1.663f7p-4f,  0x1.918a16p-4f, 0x1.bc8424p-4f, 0x1.e72ec2p-4f,
+    0x1.08c588p-3f, 0x1.1dcd1ap-3f, 0x1.32ae9ep-3f, 0x1.476aap-3f,
+    0x1.5c01a4p-3f, 0x1.70742ep-3f, 0x1.84c2bep-3f, 0x1.98eddp-3f,
+    0x1.acf5e2p-3f, 0x1.c0db6cp-3f, 0x1.d49ee4p-3f, 0x1.e840bep-3f,
+    0x1.fbc16cp-3f, 0x1.0790aep-2f, 0x1.11307ep-2f, 0x1.1ac05cp-2f,
+    0x1.24407ap-2f, 0x1.2db11p-2f,  0x1.37124cp-2f, 0x1.406464p-2f,
+    0x1.49a784p-2f, 0x1.52dbep-2f,  0x1.5c01a4p-2f, 0x1.6518fep-2f,
+    0x1.6e221cp-2f, 0x1.771d2cp-2f, 0x1.800a56p-2f, 0x1.88e9c8p-2f,
+    0x1.91bba8p-2f, 0x1.9a8024p-2f, 0x1.a3376p-2f,  0x1.abe188p-2f,
+    0x1.b47ecp-2f,  0x1.bd0f2ep-2f, 0x1.c592fap-2f, 0x1.ce0a4ap-2f,
+    0x1.d6753ep-2f, 0x1.ded3fep-2f, 0x1.e726aap-2f, 0x1.ef6d68p-2f,
+    0x1.f7a856p-2f, 0x1.ffd79ap-2f, 0x1.03fda8p-1f, 0x1.0809dp-1f,
+    0x1.0c105p-1f,  0x1.10113cp-1f, 0x1.140cap-1f,  0x1.18028cp-1f,
+    0x1.1bf312p-1f, 0x1.1fde3ep-1f, 0x1.23c41ep-1f, 0x1.27a4cp-1f,
+    0x1.2b8034p-1f, 0x1.2f5688p-1f, 0x1.3327c6p-1f, 0x1.36f4p-1f,
+    0x1.3abb4p-1f,  0x1.3e7d94p-1f, 0x1.423b08p-1f, 0x1.45f3aap-1f,
+    0x1.49a784p-1f, 0x1.4d56a6p-1f, 0x1.510118p-1f, 0x1.54a6e8p-1f,
+    0x1.584822p-1f, 0x1.5be4dp-1f,  0x1.5f7dp-1f,   0x1.6310b8p-1f,
+    0x1.66a008p-1f, 0x1.6a2afap-1f, 0x1.6db196p-1f, 0x1.7133eap-1f,
+    0x1.74b1fep-1f, 0x1.782bdcp-1f, 0x1.7ba19p-1f,  0x1.7f1322p-1f,
+    0x1.82809ep-1f, 0x1.85ea0cp-1f, 0x1.894f74p-1f, 0x1.8cb0e4p-1f,
+    0x1.900e62p-1f, 0x1.9367f6p-1f, 0x1.96bdaep-1f, 0x1.9a0f8ep-1f,
+    0x1.9d5dap-1f,  0x1.a0a7eep-1f, 0x1.a3ee8p-1f,  0x1.a7315ep-1f,
+    0x1.aa709p-1f,  0x1.adac1ep-1f, 0x1.b0e412p-1f, 0x1.b41874p-1f,
+    0x1.b74948p-1f, 0x1.ba769cp-1f, 0x1.bda072p-1f, 0x1.c0c6d4p-1f,
+    0x1.c3e9cap-1f, 0x1.c7095ap-1f, 0x1.ca258ep-1f, 0x1.cd3e6ap-1f,
+    0x1.d053f6p-1f, 0x1.d3663cp-1f, 0x1.d6753ep-1f, 0x1.d98106p-1f,
+    0x1.dc899ap-1f, 0x1.df8f02p-1f, 0x1.e29142p-1f, 0x1.e59064p-1f,
+    0x1.e88c6cp-1f, 0x1.eb856p-1f,  0x1.ee7b48p-1f, 0x1.f16e28p-1f,
+    0x1.f45e08p-1f, 0x1.f74afp-1f,  0x1.fa34e2p-1f, 0x1.fd1be4p-1f,
+};
+
+LLVM_LIBC_FUNCTION(bfloat16, log2bf16, (bfloat16 x)) {
+  using FPBits = fputil::FPBits<bfloat16>;
+  FPBits x_bits(x);
+
+  uint16_t x_u = x_bits.uintval();
+
+  // If x <= 0, or x is 1, or x is +inf, or x is NaN.
+  if (LIBC_UNLIKELY(x_u == 0U || x_u == 0x3f80U || x_u >= 0x7f80U)) {
+    // log(NaN) = NaN
+    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;
+    }
+
+    // log(+/-0) = −inf
+    if ((x_u & 0x7fffU) == 0U) {
+      fputil::raise_except_if_required(FE_DIVBYZERO);
+      return FPBits::inf(Sign::NEG).get_val();
+    }
+
+    // log(1) = 0
+    if (x_u == 0x3f80U)
+      return FPBits::zero().get_val();
+
+    // x < 0
+    if (x_u > 0x8000U) {
+      fputil::set_errno_if_required(EDOM);
+      fputil::raise_except_if_required(FE_INVALID);
+      return FPBits::quiet_nan().get_val();
+    }
+
+    // log(+inf) = +inf
+    return FPBits::inf().get_val();
+  }
+
+  int e = -FPBits::EXP_BIAS;
+
+  // When x is subnormal, normalize it.
+  if ((x_u & FPBits::EXP_MASK) == 0U) {
+    // Can't pass an integer to fputil::cast directly.
+    constexpr float NORMALIZE_EXP = 1U << FPBits::FRACTION_LEN;
+    x_bits = FPBits(x_bits.get_val() * fputil::cast<bfloat16>(NORMALIZE_EXP));
+    x_u = x_bits.uintval();
+    e -= FPBits::FRACTION_LEN;
+  }
+
+  // To compute log2(x), we do the following:
+  //   x = 2^e * (1 + m),
+  //   log2(x) = e + log2(1 + m).
+  // for BFloat16, mantissa is at most 7 explicit bits, so we lookup
+  // log2(1 + m) in LOG2F_1_PLUS_M table using `m` as key.
+
+  // Get the 7-bit mantissa directly as the table index
+  uint16_t m = x_bits.get_mantissa();
+
+  // Get unbiased exponent
+  e += x_u >> FPBits::FRACTION_LEN;
+
+  return fputil::cast<bfloat16>(static_cast<float>(e) + LOG2F_1_PLUS_M[m]);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/math/log2bf16.h b/libc/src/math/log2bf16.h
new file mode 100644
index 0000000000000..897ed60f093c8
--- /dev/null
+++ b/libc/src/math/log2bf16.h
@@ -0,0 +1,21 @@
+//===-- Implementation header for log2bf16 ----------------------*- 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_LOG2BF16_H
+#define LLVM_LIBC_SRC_MATH_LOG2BF16_H
+
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+bfloat16 log2bf16(bfloat16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_LOG2BF16_H
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index ff5c511922171..3e6a51ceab793 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -2128,6 +2128,18 @@ add_fp_unittest(
     libc.src.math.log2f16
 )
 
+add_fp_unittest(
+  log2bf16_test
+  NEED_MPFR
+  SUITE
+    libc-math-unittests
+  SRCS
+    log2bf16_test.cpp
+  DEPENDS
+    libc.src.math.log2bf16
+    libc.src.__support.FPUtil.bfloat16
+)
+
 add_fp_unittest(
  log10_test
  NEED_MPFR
diff --git a/libc/test/src/math/log2bf16_test.cpp b/libc/test/src/math/log2bf16_test.cpp
new file mode 100644
index 0000000000000..c023e9db50c19
--- /dev/null
+++ b/libc/test/src/math/log2bf16_test.cpp
@@ -0,0 +1,41 @@
+//===-- Full range tests for BFloat16 log2(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/__support/FPUtil/bfloat16.h"
+#include "src/math/log2bf16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+using LlvmLibcLogBf16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+
+// range: [0, inf]
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7f80U;
+
+// range: [-0, -inf]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xff80U;
+
+TEST_F(LlvmLibcLogBf16Test, PositiveRange) {
+  for (uint16_t v = POS_START; v <= POS_STOP; ++v) {
+    bfloat16 x = FPBits(v).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log2, x,
+                                   LIBC_NAMESPACE::log2bf16(x), 0.5);
+  }
+}
+
+TEST_F(LlvmLibcLogBf16Test, NegativeRange) {
+  for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) {
+    bfloat16 x = FPBits(v).get_val();
+    EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Log2, x,
+                                   LIBC_NAMESPACE::log2bf16(x), 0.5);
+  }
+}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 5afd3a9f22967..db3ab203d80f2 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -4405,6 +4405,19 @@ add_fp_unittest(
     libc.src.__support.FPUtil.cast
 )
 
+add_fp_unittest(
+  log2bf16_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    log2bf16_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.fenv_macros
+    libc.src.math.log2bf16
+    libc.src.__support.FPUtil.bfloat16
+)
+
 add_fp_unittest(
   log10_test
   SUITE
diff --git a/libc/test/src/math/smoke/log2bf16_test.cpp b/libc/test/src/math/smoke/log2bf16_test.cpp
new file mode 100644
index 0000000000000..de4a05af643e8
--- /dev/null
+++ b/libc/test/src/math/smoke/log2bf16_test.cpp
@@ -0,0 +1,52 @@
+//===-- Unittests for BFloat16 log2(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 "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/macros/properties/types.h"
+#include "src/math/log2bf16.h"
+#include "test/UnitTest/FEnvSafeTest.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+class LlvmLibcLogBf16Test : public LIBC_NAMESPACE::testing::FEnvSafeTest {
+  DECLARE_SPECIAL_CONSTANTS(bfloat16)
+
+public:
+  void test_special_numbers() {
+    EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::log2bf16(aNaN));
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, LIBC_NAMESPACE::log2bf16(sNaN),
+                                FE_INVALID);
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::log2bf16(inf));
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::log2bf16(neg_inf));
+    EXPECT_MATH_ERRNO(EDOM);
+
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        neg_inf, LIBC_NAMESPACE::log2bf16(zero), FE_DIVBYZERO);
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_WITH_EXCEPTION_ALL_ROUNDING(
+        neg_inf, LIBC_NAMESPACE::log2bf16(neg_zero), FE_DIVBYZERO);
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_ALL_ROUNDING(zero, LIBC_NAMESPACE::log2bf16(bfloat16(1.0)));
+    EXPECT_MATH_ERRNO(0);
+
+    EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::log2bf16(bfloat16(-1.0)));
+    EXPECT_MATH_ERRNO(EDOM);
+  }
+};
+
+TEST_F(LlvmLibcLogBf16Test, SpecialNumbers) { test_special_numbers(); }

``````````

</details>


https://github.com/llvm/llvm-project/pull/177275


More information about the libc-commits mailing list