[libc-commits] [libc] [libc][math][c23] fmul correcly rounded to all rounding modes (PR #91537)
via libc-commits
libc-commits at lists.llvm.org
Fri Jun 7 18:53:07 PDT 2024
================
@@ -0,0 +1,131 @@
+//===-- Implementation of fmul 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/fmul.h"
+#include "src/__support/CPP/bit.h"
+#include "src/__support/FPUtil/BasicOperations.h"
+#include "src/__support/FPUtil/FPBits.h"
+#include "src/__support/FPUtil/rounding_mode.h"
+#include "src/__support/common.h"
+#include "src/__support/uint128.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
+ auto x_bits = fputil::FPBits<double>(x);
+ // uint64_t x_u = x_bits.uintval();
+
+ auto y_bits = fputil::FPBits<double>(y);
+ // uint64_t y_u = y_bits.uintval();
+
+ auto output_sign = (x_bits.sign() != y_bits.sign()) ? Sign::NEG : Sign::POS;
+
+ if (LIBC_UNLIKELY(x_bits.is_inf_or_nan() || y_bits.is_inf_or_nan() ||
+ x_bits.is_zero() || y_bits.is_zero())) {
+ if (x_bits.is_nan())
+ return static_cast<float>(x);
+ if (y_bits.is_nan())
+ return static_cast<float>(y);
+ if (x_bits.is_inf())
+ return y_bits.is_zero()
+ ? fputil::FPBits<float>::quiet_nan().get_val()
+ : fputil::FPBits<float>::inf(output_sign).get_val();
+ if (y_bits.is_inf())
+ return x_bits.is_zero()
+ ? fputil::FPBits<float>::quiet_nan().get_val()
+ : fputil::FPBits<float>::inf(output_sign).get_val();
+ // Now either x or y is zero, and the other one is finite.
+ return fputil::FPBits<float>::zero(output_sign).get_val();
+ }
+
+ uint64_t mx, my;
+
+ // Get mantissa and append the hidden bit if needed.
+ mx = x_bits.get_explicit_mantissa();
+ my = y_bits.get_explicit_mantissa();
+
+ // Get the corresponding biased exponent.
+ int ex = x_bits.get_explicit_exponent();
+ int ey = y_bits.get_explicit_exponent();
+
+ // Count the number of leading zeros of the explicit mantissas.
+ int nx = cpp::countl_zero(mx);
+ int ny = cpp::countl_zero(my);
+ // Shift the leading 1 bit to the most significant bit.
+ mx <<= nx;
+ my <<= ny;
+
+ // Adjust exponent accordingly: If x or y are normal, we will only need to
+ // shift by (exponent length + sign bit = 11 bits. If x or y are denormal, we
+ // will need to shift more than 11 bits.
+ ex -= (nx - 11);
+ ey -= (ny - 11);
+
+ UInt128 product = static_cast<UInt128>(mx) * static_cast<UInt128>(my);
+ int32_t dm1;
+ uint64_t highs, lows, b;
+ uint64_t g, hight, lowt, m;
+ bool c;
+
+ highs = static_cast<uint64_t>(product >> 64);
+ c = highs >= 0x8000000000000000;
+ lows = static_cast<uint64_t>(product);
+
+ lowt = (lows != 0);
+
+ int32_t cint = static_cast<int32_t>(c);
+ dm1 = ex + ey + cint + fputil::FPBits<float>::EXP_BIAS;
----------------
lntue wrote:
replace `cint` with `c`.
https://github.com/llvm/llvm-project/pull/91537
More information about the libc-commits
mailing list