[libc-commits] [libc] [llvm] [libc][math] Impl bfloat16 lgamma function. (PR #199312)
Kiriti Ponduri via libc-commits
libc-commits at lists.llvm.org
Sat May 23 06:54:45 PDT 2026
================
@@ -0,0 +1,195 @@
+//===-- 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/bfloat16.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace math {
+
+// Evaluate degree-4 polynomial using Horner's method:
+// p(t) = c0 + t*(c1 + t*(c2 + t*(c3 + t*c4)))
+// coeffs = {c4, c3, c2, c1, c0}
+static inline float poly4(float t, const float c[5]) {
+ return c[4] + t * (c[3] + t * (c[2] + t * (c[1] + t * c[0])));
+}
+
+// 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
+static inline float lgamma_logf(float x) {
+ // Coefficients for ln(m) on [1,2), centered at 1.5
+ // Generated by numpy.polyfit, max_err = 1.71e-05 (well within bf16 precision)
+ constexpr float LN_COEFFS[6] = {
+ 0x1.ef26300000000p-6f, // c5
+ -0x1.c2e22a0000000p-5f, // c4
+ 0x1.929d980000000p-4f, // c3
+ -0x1.c615ec0000000p-3f, // c2
+ 0x1.5557200000000p-1f, // c1
+ 0x1.9f309c0000000p-2f, // c0
+ };
+ constexpr float LN2 = 0x1.62e430p-1f;
+
+ // Extract exponent and mantissa
+ uint32_t bits = cpp::bit_cast<uint32_t>(x);
+ int e = static_cast<int>((bits >> 23) & 0xFFU) - 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;
+ float lnm =
+ LN_COEFFS[5] +
+ t * (LN_COEFFS[4] +
+ t * (LN_COEFFS[3] +
+ t * (LN_COEFFS[2] + t * (LN_COEFFS[1] + t * LN_COEFFS[0]))));
+ return static_cast<float>(e) * LN2 + lnm;
+}
+
+// Coefficients for lgamma on [n, n+1), centered at n+0.5
+// Each row: {c4, c3, c2, c1, c0} for poly in (x - (n+0.5))
+// Generated by numpy.polyfit with degree 4
+// Intervals: n = 1..7
+static constexpr float LGAMMA_POLY[7][5] = {
----------------
udaykiriti wrote:
can i procedd with constexpr or LIBC_CONSTEXPR
https://github.com/llvm/llvm-project/pull/199312
More information about the libc-commits
mailing list