[libc] [llvm] [libc][math] Implement C23 half precision pow function (PR #159906)
Muhammad Bassiouni via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 2 20:53:50 PST 2026
================
@@ -0,0 +1,418 @@
+//===-- Implementation header for powf16 ------------------------*- 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_POWF16_H
+#define LLVM_LIBC_SRC___SUPPORT_MATH_POWF16_H
+#include "include/llvm-libc-macros/float16-macros.h"
+
+#ifdef LIBC_TYPES_HAS_FLOAT16
+
+#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/cast.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/nearest_integer.h"
+#include "src/__support/FPUtil/sqrt.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/optimization.h"
+#include "src/__support/macros/properties/types.h"
+#include "src/__support/math/common_constants.h"
+#include "src/__support/math/exp10f_utils.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+using namespace common_constants_internal;
+
+namespace {
+
+LIBC_INLINE static double exp2_range_reduced(double x) {
+ // k = round(x * 32) => (hi + mid) * 2^5
+ double kf = fputil::nearest_integer(x * 32.0);
+ int k = static_cast<int>(kf);
+ // dx = lo = x - (hi + mid) = x - k * 2^(-5)
+ double dx = fputil::multiply_add(-0x1.0p-5, kf, x); // -2^-5 * k + x
+
+ // hi = k >> MID_BITS
+ // exp_hi = hi shifted into double exponent field
+ int64_t hi = static_cast<int64_t>(k >> ExpBase::MID_BITS);
+ int64_t exp_hi = static_cast<int64_t>(
+ static_cast<uint64_t>(hi) << fputil::FPBits<double>::FRACTION_LEN);
+
+ // mh_bits = bits for 2^hi * 2^mid (lookup contains base bits for 2^mid)
+ int tab_index = k & ExpBase::MID_MASK; // mid index in [0, 31]
+ int64_t mh_bits = ExpBase::EXP_2_MID[tab_index] + exp_hi;
+
+ // mh = 2^(hi + mid)
+ double mh = fputil::FPBits<double>(static_cast<uint64_t>(mh_bits)).get_val();
+
+ // Degree-5 polynomial approximating (2^x - 1)/x generating by Sollya with:
+ // > P = fpminimax((2^x - 1)/x, 5, [|D...|], [-1/32. 1/32]);
+ constexpr double COEFFS[5] = {0x1.62e42fefa39efp-1, 0x1.ebfbdff8131c4p-3,
+ 0x1.c6b08d7061695p-5, 0x1.3b2b1bee74b2ap-7,
+ 0x1.5d88091198529p-10};
+
+ double dx_sq = dx * dx;
+ double c1 = fputil::multiply_add(dx, COEFFS[0], 1.0); // 1 + ln2*dx
+ double c2 =
+ fputil::multiply_add(dx, COEFFS[2], COEFFS[1]); // COEFF1 + COEFF2*dx
+ double c3 =
+ fputil::multiply_add(dx, COEFFS[4], COEFFS[3]); // COEFF3 + COEFF4*dx
+ double p = fputil::multiply_add(dx_sq, c3, c2); // c2 + c3*dx^2
+
+ // 2^x = 2^(hi+mid) * 2^dx
+ // ≈ mh * (1 + dx * P(dx))
+ // = mh + (mh * dx) * P(dx)
+ double result = fputil::multiply_add(p, dx_sq * mh, c1 * mh);
+
+ return result;
+}
+
+LIBC_INLINE bool is_odd_integer(float16 x) {
----------------
bassiounix wrote:
mark as `constexpr`.
https://github.com/llvm/llvm-project/pull/159906
More information about the llvm-commits
mailing list