[libc-commits] [libc] [libc][math][c23] Add f16sqrtf C23 math function (PR #95251)
via libc-commits
libc-commits at lists.llvm.org
Wed Jun 12 08:34:38 PDT 2024
================
@@ -120,47 +132,119 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
// So the nth digit y_n of the mantissa of sqrt(x) can be found by:
// y_n = 1 if 2*r(n-1) >= 2*y(n - 1) + 2^(-n-1)
// 0 otherwise.
- StorageType y = ONE;
- StorageType r = x_mant - ONE;
+ InStorageType y = ONE;
+ InStorageType r = x_mant - ONE;
- for (StorageType current_bit = ONE >> 1; current_bit; current_bit >>= 1) {
+ for (InStorageType current_bit = ONE >> 1; current_bit;
+ current_bit >>= 1) {
r <<= 1;
- StorageType tmp = (y << 1) + current_bit; // 2*y(n - 1) + 2^(-n-1)
+ InStorageType tmp = (y << 1) + current_bit; // 2*y(n - 1) + 2^(-n-1)
if (r >= tmp) {
r -= tmp;
y += current_bit;
}
}
// We compute one more iteration in order to round correctly.
- bool lsb = static_cast<bool>(y & 1); // Least significant bit
- bool rb = false; // Round bit
+ bool lsb = (y & (InStorageType(1) << EXTRA_FRACTION_LEN)) !=
+ 0; // Least significant bit
+ bool rb = false; // Round bit
r <<= 2;
- StorageType tmp = (y << 2) + 1;
+ InStorageType tmp = (y << 2) + 1;
if (r >= tmp) {
r -= tmp;
rb = true;
}
+ bool sticky = false;
+
+ if constexpr (EXTRA_FRACTION_LEN > 0) {
+ sticky = rb || (y & EXTRA_FRACTION_MASK) != 0;
+ rb = (y & (InStorageType(1) << (EXTRA_FRACTION_LEN - 1))) != 0;
+ }
+
// Remove hidden bit and append the exponent field.
- x_exp = ((x_exp >> 1) + FPBits_t::EXP_BIAS);
+ x_exp = ((x_exp >> 1) + OutFPBits::EXP_BIAS);
+
+ OutStorageType y_out = static_cast<OutStorageType>(
+ ((y - ONE) >> EXTRA_FRACTION_LEN) |
+ (static_cast<OutStorageType>(x_exp) << OutFPBits::FRACTION_LEN));
+
+ if constexpr (EXTRA_FRACTION_LEN > 0) {
+ if (x_exp >= OutFPBits::MAX_BIASED_EXPONENT) {
+ switch (quick_get_round()) {
+ case FE_TONEAREST:
+ case FE_UPWARD:
+ return OutFPBits::inf().get_val();
+ default:
+ return OutFPBits::max_normal().get_val();
+ }
+ }
+
+ if (x_exp == OutFPBits::MAX_BIASED_EXPONENT - 1 &&
+ y == OutFPBits::max_normal().uintval() && (rb || sticky)) {
+ switch (quick_get_round()) {
+ case FE_TONEAREST:
+ if (rb)
+ return OutFPBits::inf().get_val();
+ return OutFPBits::max_normal().get_val();
+ case FE_UPWARD:
+ return OutFPBits::inf().get_val();
+ default:
+ return OutFPBits::max_normal().get_val();
+ }
+ }
----------------
overmighty wrote:
This is actually not needed, I'll remove it.
https://github.com/llvm/llvm-project/pull/95251
More information about the libc-commits
mailing list