[libc-commits] [libc] [llvm] [libc][math] Impl bfloat16 lgamma function. (PR #199312)

via libc-commits libc-commits at lists.llvm.org
Mon May 25 01:36:41 PDT 2026


================
@@ -0,0 +1,193 @@
+//===-- Implementation of lgammabf16 ----------------------------*- 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_LGAMMABF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_LGAMMABF16_H
+
+#include "hdr/errno_macros.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/CPP/bit.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace math {
+
+// Compute natural log of positive float x using range reduction.
+// x = 2^e * m, m in [1, 2)
+// ln(x) = e * ln(2) + ln(m)
+// ln(m) approximated by degree-5 poly centered at 1.5
+// Maximum relative error: ~1.71e-05 (well within bfloat16 precision)
+LIBC_INLINE float lgamma_logf(float x) {
+  constexpr float LN_COEFFS[6] = {
+      0x1.9f309cp-2f,  // c0
+      0x1.555720p-1f,  // c1
+      -0x1.c615ecp-3f, // c2
+      0x1.929d98p-4f,  // c3
+      -0x1.c2e22ap-5f, // c4
+      0x1.ef2630p-6f,  // c5
+  };
+  constexpr float LN2 = 0x1.62e430p-1f;
+
+  uint32_t bits = cpp::bit_cast<uint32_t>(x);
+  int e_tmp = (bits >> 23) & 0xFFU;
+
+  // Normalize subnormal float32 values
+  if (e_tmp == 0) {
+    x *= 0x1.0p23f; // Multiply by 2^23
+    bits = cpp::bit_cast<uint32_t>(x);
+    e_tmp = ((bits >> 23) & 0xFFU) - 23;
+  }
+
+  int e = e_tmp - 127;
+
+  // Set exponent to 127 (i.e. value in [1,2))
+  bits = (bits & 0x807FFFFFU) | (127U << 23);
+  float m = cpp::bit_cast<float>(bits);
+
+  float t = m - 1.5f;
+  return static_cast<float>(e) * LN2 +
+         fputil::polyeval(t, LN_COEFFS[0], LN_COEFFS[1], LN_COEFFS[2],
+                          LN_COEFFS[3], LN_COEFFS[4], LN_COEFFS[5]);
+}
+
+// Coefficients for lgamma on [n, n+1), centered at n+0.5
+// Each row: {c0, c1, c2, c3, c4} for fputil::polyeval in (x - (n+0.5))
+// Generated by numpy.polyfit with degree 4
+// Intervals: n = 1..7
+// (Maximum relative errors per intrvel)
----------------
Sukumarsawant wrote:

```suggestion
// (Maximum relative errors per intervel)
```
nit.


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


More information about the libc-commits mailing list