Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "[libc] Remove unnecessary FPBits functions and properties" #79118

Merged
merged 1 commit into from
Jan 23, 2024

Conversation

gchatelet
Copy link
Contributor

@gchatelet gchatelet commented Jan 23, 2024

Reverts #79113
It broke aarch64 build bot machines.

@llvmbot llvmbot added the libc label Jan 23, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jan 23, 2024

@llvm/pr-subscribers-libc

Author: Guillaume Chatelet (gchatelet)

Changes

Reverts llvm/llvm-project#79113
It broke aarch64 build bot machines.


Patch is 99.34 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/79118.diff

68 Files Affected:

  • (modified) libc/fuzzing/stdlib/strtofloat_fuzz.cpp (+1-1)
  • (modified) libc/src/__support/FPUtil/DivisionAndRemainderOperations.h (+1-1)
  • (modified) libc/src/__support/FPUtil/FPBits.h (+42-9)
  • (modified) libc/src/__support/FPUtil/Hypot.h (+2-2)
  • (modified) libc/src/__support/FPUtil/ManipulationFunctions.h (+14-10)
  • (modified) libc/src/__support/FPUtil/NormalFloat.h (+1-1)
  • (modified) libc/src/__support/FPUtil/dyadic_float.h (+1-1)
  • (modified) libc/src/__support/FPUtil/except_value_utils.h (+4-2)
  • (modified) libc/src/__support/FPUtil/generic/FMA.h (+6-4)
  • (modified) libc/src/__support/FPUtil/generic/FMod.h (+1-1)
  • (modified) libc/src/__support/FPUtil/generic/sqrt.h (+7-11)
  • (modified) libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h (+3-5)
  • (modified) libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h (+31-27)
  • (modified) libc/src/__support/common.h (+1)
  • (modified) libc/src/__support/str_to_float.h (+2-2)
  • (modified) libc/src/math/generic/acosf.cpp (+1-1)
  • (modified) libc/src/math/generic/acoshf.cpp (+1-1)
  • (modified) libc/src/math/generic/asinf.cpp (+1-1)
  • (modified) libc/src/math/generic/atanhf.cpp (+2-2)
  • (modified) libc/src/math/generic/cosf.cpp (+1-1)
  • (modified) libc/src/math/generic/coshf.cpp (+3-3)
  • (modified) libc/src/math/generic/exp.cpp (+2-2)
  • (modified) libc/src/math/generic/exp10.cpp (+2-2)
  • (modified) libc/src/math/generic/exp10f_impl.h (+3-3)
  • (modified) libc/src/math/generic/exp2.cpp (+2-2)
  • (modified) libc/src/math/generic/exp2f_impl.h (+3-3)
  • (modified) libc/src/math/generic/expf.cpp (+2-2)
  • (modified) libc/src/math/generic/expm1.cpp (+2-2)
  • (modified) libc/src/math/generic/expm1f.cpp (+2-2)
  • (modified) libc/src/math/generic/log.cpp (+5-6)
  • (modified) libc/src/math/generic/log10.cpp (+5-6)
  • (modified) libc/src/math/generic/log10f.cpp (+3-5)
  • (modified) libc/src/math/generic/log1p.cpp (+3-4)
  • (modified) libc/src/math/generic/log1pf.cpp (+2-2)
  • (modified) libc/src/math/generic/log2.cpp (+5-6)
  • (modified) libc/src/math/generic/log2f.cpp (+3-5)
  • (modified) libc/src/math/generic/logf.cpp (+4-5)
  • (modified) libc/src/math/generic/powf.cpp (+6-7)
  • (modified) libc/src/math/generic/sincosf.cpp (+1-3)
  • (modified) libc/src/math/generic/sinf.cpp (+1-1)
  • (modified) libc/src/math/generic/sinhf.cpp (+3-3)
  • (modified) libc/src/math/generic/tanf.cpp (+1-1)
  • (modified) libc/test/UnitTest/FPMatcher.h (+20-20)
  • (modified) libc/test/src/__support/FPUtil/fpbits_test.cpp (+48-33)
  • (modified) libc/test/src/math/FDimTest.h (+1-1)
  • (modified) libc/test/src/math/FmaTest.h (+16-21)
  • (modified) libc/test/src/math/HypotTest.h (+20-23)
  • (modified) libc/test/src/math/ILogbTest.h (+11-11)
  • (modified) libc/test/src/math/LdExpTest.h (+1-1)
  • (modified) libc/test/src/math/NextAfterTest.h (+5-5)
  • (modified) libc/test/src/math/RIntTest.h (+9-12)
  • (modified) libc/test/src/math/RemQuoTest.h (+11-14)
  • (modified) libc/test/src/math/RoundToIntegerTest.h (+9-13)
  • (modified) libc/test/src/math/differential_testing/BinaryOpSingleOutputDiff.h (+6-10)
  • (modified) libc/test/src/math/differential_testing/SingleInputSingleOutputDiff.h (+3-4)
  • (modified) libc/test/src/math/smoke/FDimTest.h (+1-1)
  • (modified) libc/test/src/math/smoke/FmaTest.h (+7-9)
  • (modified) libc/test/src/math/smoke/HypotTest.h (+10-10)
  • (modified) libc/test/src/math/smoke/ILogbTest.h (+9-9)
  • (modified) libc/test/src/math/smoke/LdExpTest.h (+1-1)
  • (modified) libc/test/src/math/smoke/NextAfterTest.h (+6-8)
  • (modified) libc/test/src/math/smoke/NextTowardTest.h (+10-12)
  • (modified) libc/test/src/math/smoke/RIntTest.h (+1-1)
  • (modified) libc/test/src/math/smoke/RemQuoTest.h (+1-1)
  • (modified) libc/test/src/math/smoke/RoundToIntegerTest.h (+9-13)
  • (modified) libc/test/src/stdio/sprintf_test.cpp (+11-21)
  • (modified) libc/test/src/stdio/sscanf_test.cpp (+8-13)
  • (modified) libc/utils/MPFRWrapper/MPFRUtils.cpp (+1-1)
diff --git a/libc/fuzzing/stdlib/strtofloat_fuzz.cpp b/libc/fuzzing/stdlib/strtofloat_fuzz.cpp
index b773043bda67d8a..affef6fcf549e08 100644
--- a/libc/fuzzing/stdlib/strtofloat_fuzz.cpp
+++ b/libc/fuzzing/stdlib/strtofloat_fuzz.cpp
@@ -28,7 +28,7 @@ using LIBC_NAMESPACE::fputil::FPBits;
 // exponent. Subnormals have a lower effective precision since they don't
 // necessarily use all of the bits of the mantissa.
 template <typename F> inline constexpr int effective_precision(int exponent) {
-  const int full_precision = FPBits<F>::FRACTION_LEN + 1;
+  const int full_precision = FPBits<F>::MANTISSA_PRECISION;
 
   // This is intended to be 0 when the exponent is the lowest normal and
   // increase as the exponent's magnitude increases.
diff --git a/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h b/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
index ef9593a42b00557..1798310c3e31e30 100644
--- a/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
+++ b/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
@@ -31,7 +31,7 @@ LIBC_INLINE T remquo(T x, T y, int &q) {
   if (ybits.is_nan())
     return y;
   if (xbits.is_inf() || ybits.is_zero())
-    return FPBits<T>::build_quiet_nan(fputil::Sign::POS, 1).get_val();
+    return FPBits<T>::build_quiet_nan(1);
 
   if (xbits.is_zero()) {
     q = 0;
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 0a79b505ecbe1c2..2465158bb2cdfc7 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -390,7 +390,7 @@ struct FPRepSem : public FPStorage<fp_type> {
     return exp_bits() == encode(BiasedExp::BITS_ALL_ZEROES());
   }
   LIBC_INLINE constexpr bool is_normal() const {
-    return is_finite() && !is_subnormal();
+    return is_finite() && !UP::is_subnormal();
   }
   // Returns the mantissa with the implicit bit set iff the current
   // value is a valid normal number.
@@ -556,14 +556,6 @@ struct FPRep : public FPRepSem<fp_type, RetT> {
   using UP::FRACTION_MASK;
   using UP::SIGN_MASK;
 
-  // Comparison
-  LIBC_INLINE constexpr friend bool operator==(FPRep a, FPRep b) {
-    return a.uintval() == b.uintval();
-  }
-  LIBC_INLINE constexpr friend bool operator!=(FPRep a, FPRep b) {
-    return a.uintval() != b.uintval();
-  }
-
   // Representation
   LIBC_INLINE constexpr StorageType uintval() const { return bits & FP_MASK; }
   LIBC_INLINE constexpr void set_uintval(StorageType value) {
@@ -706,6 +698,16 @@ struct FPBits final : public internal::FPRep<get_fp_type<T>(), FPBits<T>> {
   using UP::bits;
 
   // Constants.
+  LIBC_INLINE_VAR static constexpr uint32_t MANTISSA_PRECISION =
+      UP::FRACTION_LEN + 1;
+  LIBC_INLINE_VAR static constexpr StorageType MIN_NORMAL =
+      UP::min_normal(Sign::POS).uintval();
+  LIBC_INLINE_VAR static constexpr StorageType MAX_NORMAL =
+      UP::max_normal(Sign::POS).uintval();
+  LIBC_INLINE_VAR static constexpr StorageType MIN_SUBNORMAL =
+      UP::min_subnormal(Sign::POS).uintval();
+  LIBC_INLINE_VAR static constexpr StorageType MAX_SUBNORMAL =
+      UP::max_subnormal(Sign::POS).uintval();
   LIBC_INLINE_VAR static constexpr int MAX_BIASED_EXPONENT =
       (1 << UP::EXP_LEN) - 1;
 
@@ -729,6 +731,37 @@ struct FPBits final : public internal::FPRep<get_fp_type<T>(), FPBits<T>> {
 
   LIBC_INLINE constexpr explicit operator T() const { return get_val(); }
 
+  // Methods below this are used by tests.
+  // TODO: inline and remove.
+  LIBC_INLINE static constexpr T one(Sign sign = Sign::POS) {
+    return T(UP::one(sign));
+  }
+  LIBC_INLINE static constexpr T zero(Sign sign = Sign::POS) {
+    return T(UP::zero(sign));
+  }
+  LIBC_INLINE static constexpr T inf(Sign sign = Sign::POS) {
+    return T(UP::inf(sign));
+  }
+  LIBC_INLINE static constexpr T min_normal() {
+    return T(UP::min_normal(Sign::POS));
+  }
+  LIBC_INLINE static constexpr T max_normal() {
+    return T(UP::max_normal(Sign::POS));
+  }
+  LIBC_INLINE static constexpr T min_denormal() {
+    return T(UP::min_subnormal(Sign::POS));
+  }
+  LIBC_INLINE static constexpr T max_denormal() {
+    return T(UP::max_subnormal(Sign::POS));
+  }
+  LIBC_INLINE static constexpr T build_nan(StorageType v) {
+    return T(UP::build_nan(Sign::POS, v));
+  }
+  LIBC_INLINE static constexpr T build_quiet_nan(StorageType v,
+                                                 Sign sign = Sign::POS) {
+    return T(UP::build_quiet_nan(sign, v));
+  }
+
   // TODO: Use an uint32_t for 'biased_exp'.
   LIBC_INLINE static constexpr FPBits<T>
   create_value(Sign sign, StorageType biased_exp, StorageType mantissa) {
diff --git a/libc/src/__support/FPUtil/Hypot.h b/libc/src/__support/FPUtil/Hypot.h
index 82237dec09e42e3..c38a40dfb08984a 100644
--- a/libc/src/__support/FPUtil/Hypot.h
+++ b/libc/src/__support/FPUtil/Hypot.h
@@ -197,7 +197,7 @@ LIBC_INLINE T hypot(T x, T y) {
         if (int round_mode = quick_get_round();
             round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
           return T(FPBits_t::inf());
-        return T(FPBits_t::max_normal());
+        return T(FPBits_t(FPBits_t::MAX_NORMAL));
       }
     } else {
       // For denormal result, we simply move the leading bit of the result to
@@ -254,7 +254,7 @@ LIBC_INLINE T hypot(T x, T y) {
     if (out_exp >= FPBits_t::MAX_BIASED_EXPONENT) {
       if (round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
         return T(FPBits_t::inf());
-      return T(FPBits_t::max_normal());
+      return T(FPBits_t(FPBits_t::MAX_NORMAL));
     }
   }
 
diff --git a/libc/src/__support/FPUtil/ManipulationFunctions.h b/libc/src/__support/FPUtil/ManipulationFunctions.h
index d7114625a9b3141..81c8281f3c7bbee 100644
--- a/libc/src/__support/FPUtil/ManipulationFunctions.h
+++ b/libc/src/__support/FPUtil/ManipulationFunctions.h
@@ -108,7 +108,7 @@ LIBC_INLINE T logb(T x) {
     return x;
   } else if (bits.is_inf()) {
     // Return positive infinity.
-    return T(FPBits<T>::inf());
+    return T(FPBits<T>::inf(Sign::POS));
   }
 
   NormalFloat<T> normal(bits);
@@ -127,7 +127,7 @@ LIBC_INLINE T ldexp(T x, int exp) {
   // that adding |exp| to it does not lead to integer rollover. But, if |exp|
   // value is larger the exponent range for type T, then we can return infinity
   // early. Because the result of the ldexp operation can be a subnormal number,
-  // we need to accommodate the (mantissaWidth + 1) worth of shift in
+  // we need to accommodate the (mantissaWidht + 1) worth of shift in
   // calculating the limit.
   int exp_limit = FPBits<T>::MAX_BIASED_EXPONENT + FPBits<T>::FRACTION_LEN + 1;
   if (exp > exp_limit)
@@ -164,22 +164,26 @@ LIBC_INLINE T nextafter(T from, U to) {
     return static_cast<T>(to);
 
   using StorageType = typename FPBits<T>::StorageType;
-  if (from != T(0)) {
-    if ((static_cast<U>(from) < to) == (from > T(0))) {
-      from_bits = FPBits<T>(StorageType(from_bits.uintval() + 1));
+  StorageType int_val = from_bits.uintval();
+  if (from != FPBits<T>::zero()) {
+    if ((static_cast<U>(from) < to) == (from > FPBits<T>::zero())) {
+      ++int_val;
     } else {
-      from_bits = FPBits<T>(StorageType(from_bits.uintval() - 1));
+      --int_val;
     }
   } else {
-    from_bits = FPBits<T>::min_subnormal(to_bits.sign());
+    int_val = FPBits<T>::MIN_SUBNORMAL;
+    if (to_bits.is_neg())
+      int_val |= FPBits<T>::SIGN_MASK;
   }
 
-  if (from_bits.is_subnormal())
+  StorageType exponent_bits = int_val & FPBits<T>::EXP_MASK;
+  if (exponent_bits == StorageType(0))
     raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
-  else if (from_bits.is_inf())
+  else if (exponent_bits == FPBits<T>::EXP_MASK)
     raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
 
-  return from_bits.get_val();
+  return cpp::bit_cast<T>(int_val);
 }
 
 } // namespace fputil
diff --git a/libc/src/__support/FPUtil/NormalFloat.h b/libc/src/__support/FPUtil/NormalFloat.h
index fa4da33b5b17fae..cfa9e1417510559 100644
--- a/libc/src/__support/FPUtil/NormalFloat.h
+++ b/libc/src/__support/FPUtil/NormalFloat.h
@@ -215,7 +215,7 @@ template <> LIBC_INLINE NormalFloat<long double>::operator long double() const {
   // Max exponent is of the form 0xFF...E. That is why -2 and not -1.
   constexpr int MAX_EXPONENT_VALUE = (1 << LDBits::EXP_LEN) - 2;
   if (biased_exponent > MAX_EXPONENT_VALUE) {
-    return LDBits::inf(sign).get_val();
+    return LDBits::inf(sign);
   }
 
   FPBits<long double> result(0.0l);
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 888d7ffec241ea4..5449f5561d56968 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -93,7 +93,7 @@ template <size_t Bits> struct DyadicFloat {
       return 0.0;
 
     // Assume that it is normalized, and output is also normal.
-    constexpr uint32_t PRECISION = FPBits<T>::FRACTION_LEN + 1;
+    constexpr uint32_t PRECISION = FPBits<T>::MANTISSA_PRECISION;
     using output_bits_t = typename FPBits<T>::StorageType;
 
     int exp_hi = exponent + static_cast<int>((Bits - 1) + FPBits<T>::EXP_BIAS);
diff --git a/libc/src/__support/FPUtil/except_value_utils.h b/libc/src/__support/FPUtil/except_value_utils.h
index 1e0381194009d55..89849540315f64d 100644
--- a/libc/src/__support/FPUtil/except_value_utils.h
+++ b/libc/src/__support/FPUtil/except_value_utils.h
@@ -102,13 +102,15 @@ template <typename T, size_t N> struct ExceptValues {
 // Helper functions to set results for exceptional cases.
 template <typename T> LIBC_INLINE T round_result_slightly_down(T value_rn) {
   volatile T tmp = value_rn;
-  tmp -= FPBits<T>::min_normal().get_val();
+  const T MIN_NORMAL = FPBits<T>::min_normal();
+  tmp = tmp - MIN_NORMAL;
   return tmp;
 }
 
 template <typename T> LIBC_INLINE T round_result_slightly_up(T value_rn) {
   volatile T tmp = value_rn;
-  tmp += FPBits<T>::min_normal().get_val();
+  const T MIN_NORMAL = FPBits<T>::min_normal();
+  tmp = tmp + MIN_NORMAL;
   return tmp;
 }
 
diff --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h
index 5c36463ea50213e..6285cac1983d1e9 100644
--- a/libc/src/__support/FPUtil/generic/FMA.h
+++ b/libc/src/__support/FPUtil/generic/FMA.h
@@ -130,9 +130,9 @@ template <> LIBC_INLINE double fma<double>(double x, double y, double z) {
     return x * y + z;
 
   // Extract mantissa and append hidden leading bits.
-  UInt128 x_mant = x_bits.get_explicit_mantissa();
-  UInt128 y_mant = y_bits.get_explicit_mantissa();
-  UInt128 z_mant = z_bits.get_explicit_mantissa();
+  UInt128 x_mant = x_bits.get_mantissa() | FPBits::MIN_NORMAL;
+  UInt128 y_mant = y_bits.get_mantissa() | FPBits::MIN_NORMAL;
+  UInt128 z_mant = z_bits.get_mantissa() | FPBits::MIN_NORMAL;
 
   // If the exponent of the product x*y > the exponent of z, then no extra
   // precision beside the entire product x*y is needed.  On the other hand, when
@@ -255,7 +255,9 @@ template <> LIBC_INLINE double fma<double>(double x, double y, double z) {
     if ((round_mode == FE_TOWARDZERO) ||
         (round_mode == FE_UPWARD && prod_sign.is_neg()) ||
         (round_mode == FE_DOWNWARD && prod_sign.is_pos())) {
-      return FPBits::max_normal(prod_sign).get_val();
+      result = FPBits::MAX_NORMAL;
+      return prod_sign.is_neg() ? -cpp::bit_cast<double>(result)
+                                : cpp::bit_cast<double>(result);
     }
     return static_cast<double>(FPBits::inf(prod_sign));
   }
diff --git a/libc/src/__support/FPUtil/generic/FMod.h b/libc/src/__support/FPUtil/generic/FMod.h
index 18355b801dbc7c9..f4000b97751efc4 100644
--- a/libc/src/__support/FPUtil/generic/FMod.h
+++ b/libc/src/__support/FPUtil/generic/FMod.h
@@ -124,7 +124,7 @@ template <typename T> struct FModExceptionalInputHandler {
 
   LIBC_INLINE static bool pre_check(T x, T y, T &out) {
     using FPB = fputil::FPBits<T>;
-    const T quiet_nan = FPB::build_quiet_nan().get_val();
+    const T quiet_nan = FPB::build_quiet_nan(0);
     FPB sx(x), sy(y);
     if (LIBC_LIKELY(!sy.is_zero() && !sy.is_inf_or_nan() &&
                     !sx.is_inf_or_nan())) {
diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h
index 0a0690ec1463b9d..21ae9d081d3f12e 100644
--- a/libc/src/__support/FPUtil/generic/sqrt.h
+++ b/libc/src/__support/FPUtil/generic/sqrt.h
@@ -71,19 +71,15 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
     return x86::sqrt(x);
   } else {
     // IEEE floating points formats.
-    using Sign = fputil::Sign;
-    using FPBits_t = typename fputil::FPBits<T>;
-    using StorageType = typename FPBits_t::StorageType;
-    constexpr StorageType ONE = StorageType(1) << FPBits_t::FRACTION_LEN;
-    constexpr auto FLT_NAN =
-        FPBits_t::build_quiet_nan(Sign::POS, ONE >> 1).get_val();
+    using StorageType = typename FPBits<T>::StorageType;
+    constexpr StorageType ONE = StorageType(1) << FPBits<T>::FRACTION_LEN;
 
-    FPBits_t bits(x);
+    FPBits<T> bits(x);
 
     if (bits.is_inf_or_nan()) {
       if (bits.is_neg() && (bits.get_mantissa() == 0)) {
         // sqrt(-Inf) = NaN
-        return FLT_NAN;
+        return FPBits<T>::build_quiet_nan(ONE >> 1);
       } else {
         // sqrt(NaN) = NaN
         // sqrt(+Inf) = +Inf
@@ -95,7 +91,7 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
       return x;
     } else if (bits.is_neg()) {
       // sqrt( negative numbers ) = NaN
-      return FLT_NAN;
+      return FPBits<T>::build_quiet_nan(ONE >> 1);
     } else {
       int x_exp = bits.get_exponent();
       StorageType x_mant = bits.get_mantissa();
@@ -149,10 +145,10 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
       }
 
       // Remove hidden bit and append the exponent field.
-      x_exp = ((x_exp >> 1) + FPBits_t::EXP_BIAS);
+      x_exp = ((x_exp >> 1) + FPBits<T>::EXP_BIAS);
 
       y = (y - ONE) |
-          (static_cast<StorageType>(x_exp) << FPBits_t::FRACTION_LEN);
+          (static_cast<StorageType>(x_exp) << FPBits<T>::FRACTION_LEN);
 
       switch (quick_get_round()) {
       case FE_TONEAREST:
diff --git a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
index b0a3776029ca78a..4f8d136938f56e7 100644
--- a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
+++ b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
@@ -38,16 +38,14 @@ LIBC_INLINE long double sqrt(long double x);
 LIBC_INLINE long double sqrt(long double x) {
   using LDBits = FPBits<long double>;
   using StorageType = typename LDBits::StorageType;
-  using Sign = fputil::Sign;
   constexpr StorageType ONE = StorageType(1) << int(LDBits::FRACTION_LEN);
-  constexpr auto LDNAN = LDBits::build_quiet_nan(Sign::POS, ONE >> 1).get_val();
 
-  LDBits bits(x);
+  FPBits<long double> bits(x);
 
   if (bits.is_inf_or_nan()) {
     if (bits.is_neg() && (bits.get_mantissa() == 0)) {
       // sqrt(-Inf) = NaN
-      return LDNAN;
+      return LDBits::build_quiet_nan(ONE >> 1);
     } else {
       // sqrt(NaN) = NaN
       // sqrt(+Inf) = +Inf
@@ -59,7 +57,7 @@ LIBC_INLINE long double sqrt(long double x) {
     return x;
   } else if (bits.is_neg()) {
     // sqrt( negative numbers ) = NaN
-    return LDNAN;
+    return LDBits::build_quiet_nan(ONE >> 1);
   } else {
     int x_exp = bits.get_explicit_exponent();
     StorageType x_mant = bits.get_mantissa();
diff --git a/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h b/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
index d1c76ba954b9304..512f5de4e7931ac 100644
--- a/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
+++ b/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
@@ -43,18 +43,16 @@ LIBC_INLINE long double nextafter(long double from, long double to) {
   }
 
   using StorageType = FPBits::StorageType;
-
+  constexpr StorageType SIGN_VAL = (StorageType(1) << 79);
   constexpr StorageType FRACTION_MASK = FPBits::FRACTION_MASK;
-  // StorageType int_val = from_bits.uintval();
-  if (from == 0.0l) { // +0.0 / -0.0
-    from_bits = FPBits::min_subnormal(from > to ? Sign::NEG : Sign::POS);
-  } else if (from < 0.0l) {
-    if (to < from) { // toward -inf
-      if (from_bits == FPBits::max_subnormal(Sign::NEG)) {
+  StorageType int_val = from_bits.uintval();
+  if (from < 0.0l) {
+    if (from > to) {
+      if (int_val == (SIGN_VAL + FPBits::MAX_SUBNORMAL)) {
         // We deal with normal/subnormal boundary separately to avoid
         // dealing with the implicit bit.
-        from_bits = FPBits::min_normal(Sign::NEG);
-      } else if (from_bits.get_mantissa() == FRACTION_MASK) {
+        int_val = SIGN_VAL + FPBits::MIN_NORMAL;
+      } else if ((int_val & FRACTION_MASK) == FRACTION_MASK) {
         from_bits.set_mantissa(0);
         // Incrementing exponent might overflow the value to infinity,
         // which is what is expected. Since NaNs are handling separately,
@@ -64,40 +62,45 @@ LIBC_INLINE long double nextafter(long double from, long double to) {
           raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
         return from_bits.get_val();
       } else {
-        from_bits = FPBits(StorageType(from_bits.uintval() + 1));
+        ++int_val;
       }
-    } else { // toward +inf
-      if (from_bits == FPBits::min_normal(Sign::NEG)) {
+    } else {
+      if (int_val == (SIGN_VAL + FPBits::MIN_NORMAL)) {
         // We deal with normal/subnormal boundary separately to avoid
         // dealing with the implicit bit.
-        from_bits = FPBits::max_subnormal(Sign::NEG);
-      } else if (from_bits.get_mantissa() == 0) {
+        int_val = SIGN_VAL + FPBits::MAX_SUBNORMAL;
+      } else if ((int_val & FRACTION_MASK) == 0) {
         from_bits.set_mantissa(FRACTION_MASK);
         // from == 0 is handled separately so decrementing the exponent will not
         // lead to underflow.
         from_bits.set_biased_exponent(from_bits.get_biased_exponent() - 1);
         return from_bits.get_val();
       } else {
-        from_bits = FPBits(StorageType(from_bits.uintval() - 1));
+        --int_val;
       }
     }
+  } else if (from == 0.0l) {
+    if (from > to)
+      int_val = SIGN_VAL + 1;
+    else
+      int_val = 1;
   } else {
-    if (to < from) { // toward -inf
-      if (from_bits == FPBits::min_normal(Sign::POS)) {
-        from_bits = FPBits::max_subnormal(Sign::POS);
-      } else if (from_bits.get_mantissa() == 0) {
+    if (from > to) {
+      if (int_val == FPBits::MIN_NORMAL) {
+        int_val = FPBits::MAX_SUBNORMAL;
+      } else if ((int_val & FRACTION_MASK) == 0) {
         from_bits.set_mantissa(FRACTION_MASK);
         // from == 0 is handled separately so decrementing the exponent will not
         // lead to underflow.
         from_bits.set_biased_exponent(from_bits.get_biased_exponent() - 1);
         return from_bits.get_val();
       } else {
-        from_bits = FPBits(StorageType(from_bits.uintval() - 1));
+        --int_val;
       }
-    } else { // toward +inf
-      if (from_bits == FPBits::max_subnormal(Sign::POS)) {
-        from_bits = FPBits::min_normal(Sign::POS);
-      } else if (from_bits.get_mantissa() == FRACTION_MASK) {
+    } else {
+      if (int_val == FPBits::MAX_SUBNORMAL) {
+        int_val = FPBits::MIN_NORMAL;
+      } else if ((int_val & FRACTION_MASK) == FRACTION_MASK) {
         from_bits.set_mantissa(0);
         // Incrementing exponent might overflow the value to infinity,
         // which is what is expected. Since NaNs are handling separately,
@@ -107,15 +110,16 @@ LIBC_INLINE long double nextafter(long double from, long double to) {
           raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
         return from_bits.get_val();
       } else {
-        from_bits = FPBits(StorageType(from_bits.uintval() + 1));
+        ++int_val;
       }
     }
   }
 
-  if (!from_bits.get_implicit_bit())
+  StorageType implicit_bit = int_val & (StorageType(1) << FPBits::FRACTION_LEN);
+  if (implicit_bit == StorageType(0))
     raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
 
-  return from_bits.get_val();
+  return cpp::bit_cast<long double>(int_val);
 }
 
 } // namespace fputil
diff --git a/libc/src/__support/common.h b/libc/src/__support/common.h
index a153dfc363d7374..53951dc131c28b6 100644
--- a/libc/src/__support/common.h
+++ b/libc/src/__support/common.h
@@ -2...
[truncated]

@gchatelet gchatelet merged commit b524eed into main Jan 23, 2024
4 of 5 checks passed
@gchatelet gchatelet deleted the revert-79113-remove_some_fpbit_properties branch January 23, 2024 10:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants