[libc-commits] [libc] [libc][math] Implement powf function correctly rounded to all rounding modes. (PR #71188)
via libc-commits
libc-commits at lists.llvm.org
Mon Nov 6 10:17:44 PST 2023
================
@@ -0,0 +1,141 @@
+//===-- Single-precision 10^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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_MATH_GENERIC_EXP10F_IMPL_H
+#define LLVM_LIBC_SRC_MATH_GENERIC_EXP10F_IMPL_H
+
+#include "explogxf.h"
+#include "src/__support/FPUtil/BasicOperations.h"
+#include "src/__support/FPUtil/FEnvImpl.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/PolyEval.h"
+#include "src/__support/FPUtil/multiply_add.h"
+#include "src/__support/FPUtil/nearest_integer.h"
+#include "src/__support/FPUtil/rounding_mode.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+#include "src/math/exp10f.h"
+
+#include <errno.h>
+
+namespace LIBC_NAMESPACE::generic {
+
+LIBC_INLINE float exp10f(float x) {
+ using FPBits = typename fputil::FPBits<float>;
+ FPBits xbits(x);
+
+ uint32_t x_u = xbits.uintval();
+ uint32_t x_abs = x_u & 0x7fff'ffffU;
+
+ // When |x| >= log10(2^128), or x is nan
+ if (LIBC_UNLIKELY(x_abs >= 0x421a'209bU)) {
+ // When x < log10(2^-150) or nan
+ if (x_u > 0xc234'9e35U) {
+ // exp(-Inf) = 0
+ if (xbits.is_inf())
+ return 0.0f;
+ // exp(nan) = nan
+ if (xbits.is_nan())
+ return x;
+ if (fputil::fenv_is_round_up())
+ return static_cast<float>(FPBits(FPBits::MIN_SUBNORMAL));
+ fputil::set_errno_if_required(ERANGE);
+ fputil::raise_except_if_required(FE_UNDERFLOW);
+ return 0.0f;
+ }
+ // x >= log10(2^128) or nan
+ if (!xbits.get_sign() && (x_u >= 0x421a'209bU)) {
+ // x is finite
+ if (x_u < 0x7f80'0000U) {
+ int rounding = fputil::quick_get_round();
+ if (rounding == FE_DOWNWARD || rounding == FE_TOWARDZERO)
+ return static_cast<float>(FPBits(FPBits::MAX_NORMAL));
+
+ fputil::set_errno_if_required(ERANGE);
----------------
michaelrj-google wrote:
The usual way we've handled needing to set `errno` based on internal functions is by returning it in a struct (e.g. `str_to_num_result`). That would let you make the internal implementations object libraries while also sharing the complicated logic.
https://github.com/llvm/llvm-project/pull/71188
More information about the libc-commits
mailing list