[libc-commits] [libc] [libc][NFC] Introduce a Sign type for FPBits (PR #78500)

via libc-commits libc-commits at lists.llvm.org
Wed Jan 17 12:30:49 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Guillaume Chatelet (gchatelet)

<details>
<summary>Changes</summary>

Another patch is needed to cover `DyadicFloat` and `NormalFloat` constructors.


---

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


48 Files Affected:

- (modified) libc/src/__support/FPUtil/BasicOperations.h (+6-6) 
- (modified) libc/src/__support/FPUtil/DivisionAndRemainderOperations.h (+3-3) 
- (modified) libc/src/__support/FPUtil/FPBits.h (+76-42) 
- (modified) libc/src/__support/FPUtil/ManipulationFunctions.h (+6-6) 
- (modified) libc/src/__support/FPUtil/NearestIntegerOperations.h (+9-9) 
- (modified) libc/src/__support/FPUtil/NormalFloat.h (+12-11) 
- (modified) libc/src/__support/FPUtil/dyadic_float.h (+5-5) 
- (modified) libc/src/__support/FPUtil/fpbits_str.h (+3-3) 
- (modified) libc/src/__support/FPUtil/generic/FMA.h (+4-4) 
- (modified) libc/src/__support/FPUtil/generic/FMod.h (+3-3) 
- (modified) libc/src/__support/FPUtil/generic/sqrt.h (+2-2) 
- (modified) libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h (+2-2) 
- (modified) libc/src/__support/float_to_string.h (+1-1) 
- (modified) libc/src/__support/str_to_float.h (+4-12) 
- (modified) libc/src/math/generic/acosf.cpp (+2-1) 
- (modified) libc/src/math/generic/asinf.cpp (+2-1) 
- (modified) libc/src/math/generic/atanf.cpp (+6-4) 
- (modified) libc/src/math/generic/atanhf.cpp (+2-1) 
- (modified) libc/src/math/generic/cosf.cpp (+2-1) 
- (modified) libc/src/math/generic/coshf.cpp (+2-1) 
- (modified) libc/src/math/generic/erff.cpp (+1-1) 
- (modified) libc/src/math/generic/exp10f_impl.h (+1-1) 
- (modified) libc/src/math/generic/exp2f_impl.h (+1-1) 
- (modified) libc/src/math/generic/expf.cpp (+1-1) 
- (modified) libc/src/math/generic/expm1.cpp (+6-5) 
- (modified) libc/src/math/generic/expm1f.cpp (+1-1) 
- (modified) libc/src/math/generic/inv_trigf_utils.h (+6-5) 
- (modified) libc/src/math/generic/log.cpp (+1-1) 
- (modified) libc/src/math/generic/log10.cpp (+1-1) 
- (modified) libc/src/math/generic/log10f.cpp (+1-1) 
- (modified) libc/src/math/generic/log1p.cpp (+1-1) 
- (modified) libc/src/math/generic/log1pf.cpp (+1-1) 
- (modified) libc/src/math/generic/log2.cpp (+1-1) 
- (modified) libc/src/math/generic/log2f.cpp (+1-1) 
- (modified) libc/src/math/generic/logf.cpp (+1-1) 
- (modified) libc/src/math/generic/powf.cpp (+14-12) 
- (modified) libc/src/math/generic/sinf.cpp (+3-3) 
- (modified) libc/src/math/generic/sinhf.cpp (+2-3) 
- (modified) libc/src/math/generic/tanhf.cpp (+5-6) 
- (modified) libc/src/stdio/printf_core/float_dec_converter.h (+10-12) 
- (modified) libc/src/stdio/printf_core/float_hex_converter.h (+2-2) 
- (modified) libc/src/stdio/printf_core/float_inf_nan_converter.h (+2-2) 
- (modified) libc/test/src/__support/FPUtil/fpbits_test.cpp (+30-30) 
- (modified) libc/test/src/math/RoundToIntegerTest.h (+3-2) 
- (modified) libc/test/src/math/atanhf_test.cpp (+3-2) 
- (modified) libc/test/src/math/smoke/atanhf_test.cpp (+3-2) 
- (modified) libc/test/src/stdlib/strtold_test.cpp (+1-1) 
- (modified) libc/test/src/time/difftime_test.cpp (+1-1) 


``````````diff
diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h
index 2ec61517b0b8086..4015edb1b65372f 100644
--- a/libc/src/__support/FPUtil/BasicOperations.h
+++ b/libc/src/__support/FPUtil/BasicOperations.h
@@ -20,23 +20,23 @@ namespace fputil {
 template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
 LIBC_INLINE T abs(T x) {
   FPBits<T> bits(x);
-  bits.set_sign(0);
+  bits.set_sign(Sign::POS);
   return T(bits);
 }
 
 template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
 LIBC_INLINE T fmin(T x, T y) {
-  FPBits<T> bitx(x), bity(y);
+  const FPBits<T> bitx(x), bity(y);
 
   if (bitx.is_nan()) {
     return y;
   } else if (bity.is_nan()) {
     return x;
-  } else if (bitx.get_sign() != bity.get_sign()) {
+  } else if (bitx.sign() != bity.sign()) {
     // To make sure that fmin(+0, -0) == -0 == fmin(-0, +0), whenever x and
     // y has different signs and both are not NaNs, we return the number
     // with negative sign.
-    return (bitx.get_sign() ? x : y);
+    return ((bitx.is_neg()) ? x : y);
   } else {
     return (x < y ? x : y);
   }
@@ -50,11 +50,11 @@ LIBC_INLINE T fmax(T x, T y) {
     return y;
   } else if (bity.is_nan()) {
     return x;
-  } else if (bitx.get_sign() != bity.get_sign()) {
+  } else if (bitx.sign() != bity.sign()) {
     // To make sure that fmax(+0, -0) == +0 == fmax(-0, +0), whenever x and
     // y has different signs and both are not NaNs, we return the number
     // with positive sign.
-    return (bitx.get_sign() ? y : x);
+    return (bitx.is_neg() ? y : x);
   } else {
     return (x > y ? x : y);
   }
diff --git a/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h b/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
index 65bbe6b099dd003..d3401b10a7cab81 100644
--- a/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
+++ b/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
@@ -43,13 +43,13 @@ LIBC_INLINE T remquo(T x, T y, int &q) {
     return x;
   }
 
-  bool result_sign = (xbits.get_sign() == ybits.get_sign() ? false : true);
+  bool result_sign = (xbits.is_neg() == ybits.is_neg() ? false : true);
 
   // Once we know the sign of the result, we can just operate on the absolute
   // values. The correct sign can be applied to the result after the result
   // is evaluated.
-  xbits.set_sign(0);
-  ybits.set_sign(0);
+  xbits.set_sign(Sign::POS);
+  ybits.set_sign(Sign::POS);
 
   NormalFloat<T> normalx(xbits), normaly(ybits);
   int exp = normalx.exponent - normaly.exponent;
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 4309a535abd0794..6a94798973e6345 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -31,6 +31,32 @@ enum class FPType {
   X86_Binary80,
 };
 
+// A type to interact with floating point type signs.
+// This may be moved outside of 'fputil' if useful.
+struct Sign {
+  LIBC_INLINE constexpr explicit Sign(bool is_negative)
+      : is_negative(is_negative) {}
+
+  LIBC_INLINE constexpr bool is_pos() const { return !is_negative; }
+  LIBC_INLINE constexpr bool is_neg() const { return is_negative; }
+
+  LIBC_INLINE friend constexpr bool operator==(Sign a, Sign b) {
+    return a.is_negative == b.is_negative;
+  }
+  LIBC_INLINE friend constexpr bool operator!=(Sign a, Sign b) {
+    return !(a == b);
+  }
+
+  static const Sign POS;
+  static const Sign NEG;
+
+private:
+  bool is_negative;
+};
+
+LIBC_INLINE_VAR constexpr Sign Sign::NEG = Sign(true);
+LIBC_INLINE_VAR constexpr Sign Sign::POS = Sign(false);
+
 // The classes hierarchy is as follows:
 //
 //             ┌───────────────────┐
@@ -273,9 +299,9 @@ struct FPRepBase : public internal::FPLayout<fp_type> {
     return encode(exp) | encode(sig);
   }
 
-  LIBC_INLINE static constexpr StorageType encode(bool sign, BiasedExponent exp,
+  LIBC_INLINE static constexpr StorageType encode(Sign sign, BiasedExponent exp,
                                                   Significand sig) {
-    if (sign)
+    if (sign.is_neg())
       return SIGN_MASK | encode(exp, sig);
     return encode(exp, sig);
   }
@@ -309,12 +335,12 @@ struct FPRepBase : public internal::FPLayout<fp_type> {
   StorageType bits = 0;
 
 public:
-  LIBC_INLINE constexpr bool get_sign() const {
-    return (bits & SIGN_MASK) != 0;
+  LIBC_INLINE constexpr Sign sign() const {
+    return (bits & SIGN_MASK) ? Sign::NEG : Sign::POS;
   }
 
-  LIBC_INLINE constexpr void set_sign(bool signVal) {
-    if (get_sign() != signVal)
+  LIBC_INLINE constexpr void set_sign(Sign signVal) {
+    if (sign() != signVal)
       bits ^= SIGN_MASK;
   }
 
@@ -363,6 +389,9 @@ struct FPRepBase : public internal::FPLayout<fp_type> {
   LIBC_INLINE constexpr bool is_zero() const {
     return (bits & EXP_SIG_MASK) == 0;
   }
+
+  LIBC_INLINE constexpr bool is_neg() const { return sign().is_neg(); }
+  LIBC_INLINE constexpr bool is_pos() const { return sign().is_pos(); }
 };
 
 namespace internal {
@@ -421,35 +450,37 @@ template <FPType fp_type> struct FPRep : public FPRepBase<fp_type> {
     return is_finite() && !is_subnormal();
   }
 
-  LIBC_INLINE static constexpr StorageType zero(bool sign = false) {
+  LIBC_INLINE static constexpr StorageType zero(Sign sign = Sign::POS) {
     return encode(sign, BiasedExponent::BITS_ALL_ZEROES(), Significand::ZERO());
   }
-  LIBC_INLINE static constexpr StorageType one(bool sign = false) {
+  LIBC_INLINE static constexpr StorageType one(Sign sign = Sign::POS) {
     return encode(sign, Exponent::ZERO(), Significand::ZERO());
   }
-  LIBC_INLINE static constexpr StorageType min_subnormal(bool sign = false) {
+  LIBC_INLINE static constexpr StorageType
+  min_subnormal(Sign sign = Sign::POS) {
     return encode(sign, BiasedExponent::BITS_ALL_ZEROES(), Significand::LSB());
   }
-  LIBC_INLINE static constexpr StorageType max_subnormal(bool sign = false) {
+  LIBC_INLINE static constexpr StorageType
+  max_subnormal(Sign sign = Sign::POS) {
     return encode(sign, BiasedExponent::BITS_ALL_ZEROES(),
                   Significand::BITS_ALL_ONES());
   }
-  LIBC_INLINE static constexpr StorageType min_normal(bool sign = false) {
+  LIBC_INLINE static constexpr StorageType min_normal(Sign sign = Sign::POS) {
     return encode(sign, Exponent::MIN(), Significand::ZERO());
   }
-  LIBC_INLINE static constexpr StorageType max_normal(bool sign = false) {
+  LIBC_INLINE static constexpr StorageType max_normal(Sign sign = Sign::POS) {
     return encode(sign, Exponent::MAX(), Significand::BITS_ALL_ONES());
   }
-  LIBC_INLINE static constexpr StorageType inf(bool sign = false) {
+  LIBC_INLINE static constexpr StorageType inf(Sign sign = Sign::POS) {
     return encode(sign, BiasedExponent::BITS_ALL_ONES(), Significand::ZERO());
   }
-  LIBC_INLINE static constexpr StorageType build_nan(bool sign = false,
+  LIBC_INLINE static constexpr StorageType build_nan(Sign sign = Sign::POS,
                                                      StorageType v = 0) {
     return encode(sign, BiasedExponent::BITS_ALL_ONES(),
                   (v ? Significand(v) : (Significand::MSB() >> 1)));
   }
-  LIBC_INLINE static constexpr StorageType build_quiet_nan(bool sign = false,
-                                                           StorageType v = 0) {
+  LIBC_INLINE static constexpr StorageType
+  build_quiet_nan(Sign sign = Sign::POS, StorageType v = 0) {
     return encode(sign, BiasedExponent::BITS_ALL_ONES(),
                   Significand::MSB() | Significand(v));
   }
@@ -539,36 +570,38 @@ struct FPRep<FPType::X86_Binary80> : public FPRepBase<FPType::X86_Binary80> {
     return get_implicit_bit();
   }
 
-  LIBC_INLINE static constexpr StorageType zero(bool sign = false) {
+  LIBC_INLINE static constexpr StorageType zero(Sign sign = Sign::POS) {
     return encode(sign, BiasedExponent::BITS_ALL_ZEROES(), Significand::ZERO());
   }
-  LIBC_INLINE static constexpr StorageType one(bool sign = false) {
+  LIBC_INLINE static constexpr StorageType one(Sign sign = Sign::POS) {
     return encode(sign, Exponent::ZERO(), Significand::MSB());
   }
-  LIBC_INLINE static constexpr StorageType min_subnormal(bool sign = false) {
+  LIBC_INLINE static constexpr StorageType
+  min_subnormal(Sign sign = Sign::POS) {
     return encode(sign, BiasedExponent::BITS_ALL_ZEROES(), Significand::LSB());
   }
-  LIBC_INLINE static constexpr StorageType max_subnormal(bool sign = false) {
+  LIBC_INLINE static constexpr StorageType
+  max_subnormal(Sign sign = Sign::POS) {
     return encode(sign, BiasedExponent::BITS_ALL_ZEROES(),
                   Significand::BITS_ALL_ONES() ^ Significand::MSB());
   }
-  LIBC_INLINE static constexpr StorageType min_normal(bool sign = false) {
+  LIBC_INLINE static constexpr StorageType min_normal(Sign sign = Sign::POS) {
     return encode(sign, Exponent::MIN(), Significand::MSB());
   }
-  LIBC_INLINE static constexpr StorageType max_normal(bool sign = false) {
+  LIBC_INLINE static constexpr StorageType max_normal(Sign sign = Sign::POS) {
     return encode(sign, Exponent::MAX(), Significand::BITS_ALL_ONES());
   }
-  LIBC_INLINE static constexpr StorageType inf(bool sign = false) {
+  LIBC_INLINE static constexpr StorageType inf(Sign sign = Sign::POS) {
     return encode(sign, BiasedExponent::BITS_ALL_ONES(), Significand::MSB());
   }
-  LIBC_INLINE static constexpr StorageType build_nan(bool sign = false,
+  LIBC_INLINE static constexpr StorageType build_nan(Sign sign = Sign::POS,
                                                      StorageType v = 0) {
     return encode(sign, BiasedExponent::BITS_ALL_ONES(),
                   Significand::MSB() |
                       (v ? Significand(v) : (Significand::MSB() >> 2)));
   }
-  LIBC_INLINE static constexpr StorageType build_quiet_nan(bool sign = false,
-                                                           StorageType v = 0) {
+  LIBC_INLINE static constexpr StorageType
+  build_quiet_nan(Sign sign = Sign::POS, StorageType v = 0) {
     return encode(sign, BiasedExponent::BITS_ALL_ONES(),
                   Significand::MSB() | (Significand::MSB() >> 1) |
                       Significand(v));
@@ -642,10 +675,10 @@ template <typename T> struct FPBits : public internal::FPRep<get_fp_type<T>()> {
 
   // Constants.
   static constexpr int MAX_BIASED_EXPONENT = (1 << EXP_LEN) - 1;
-  static constexpr StorageType MIN_NORMAL = UP::min_normal(false);
-  static constexpr StorageType MAX_NORMAL = UP::max_normal(false);
-  static constexpr StorageType MIN_SUBNORMAL = UP::min_subnormal(false);
-  static constexpr StorageType MAX_SUBNORMAL = UP::max_subnormal(false);
+  static constexpr StorageType MIN_NORMAL = UP::min_normal(Sign::POS);
+  static constexpr StorageType MAX_NORMAL = UP::max_normal(Sign::POS);
+  static constexpr StorageType MIN_SUBNORMAL = UP::min_subnormal(Sign::POS);
+  static constexpr StorageType MAX_SUBNORMAL = UP::max_subnormal(Sign::POS);
 
   // Constructors.
   LIBC_INLINE constexpr FPBits() = default;
@@ -675,45 +708,46 @@ template <typename T> struct FPBits : public internal::FPRep<get_fp_type<T>()> {
 
   // Methods below this are used by tests.
 
-  LIBC_INLINE static constexpr T zero(bool sign = false) {
+  LIBC_INLINE static constexpr T zero(Sign sign = Sign::POS) {
     return FPBits(UP::zero(sign)).get_val();
   }
 
-  LIBC_INLINE static constexpr T neg_zero() { return zero(true); }
+  LIBC_INLINE static constexpr T neg_zero() { return zero(Sign::NEG); }
 
-  LIBC_INLINE static constexpr T inf(bool sign = false) {
+  LIBC_INLINE static constexpr T inf(Sign sign = Sign::POS) {
     return FPBits(UP::inf(sign)).get_val();
   }
 
-  LIBC_INLINE static constexpr T neg_inf() { return inf(true); }
+  LIBC_INLINE static constexpr T neg_inf() { return inf(Sign::NEG); }
 
   LIBC_INLINE static constexpr T min_normal() {
-    return FPBits(UP::min_normal(false)).get_val();
+    return FPBits(UP::min_normal(Sign::POS)).get_val();
   }
 
   LIBC_INLINE static constexpr T max_normal() {
-    return FPBits(UP::max_normal(false)).get_val();
+    return FPBits(UP::max_normal(Sign::POS)).get_val();
   }
 
   LIBC_INLINE static constexpr T min_denormal() {
-    return FPBits(UP::min_subnormal(false)).get_val();
+    return FPBits(UP::min_subnormal(Sign::POS)).get_val();
   }
 
   LIBC_INLINE static constexpr T max_denormal() {
-    return FPBits(UP::max_subnormal(false)).get_val();
+    return FPBits(UP::max_subnormal(Sign::POS)).get_val();
   }
 
   LIBC_INLINE static constexpr T build_nan(StorageType v) {
-    return FPBits(UP::build_nan(false, v)).get_val();
+    return FPBits(UP::build_nan(Sign::POS, v)).get_val();
   }
 
-  LIBC_INLINE static constexpr T build_quiet_nan(StorageType v) {
-    return FPBits(UP::build_quiet_nan(false, v)).get_val();
+  LIBC_INLINE static constexpr T build_quiet_nan(StorageType v,
+                                                 Sign sign = Sign::POS) {
+    return FPBits(UP::build_quiet_nan(sign, v)).get_val();
   }
 
   // TODO: Use an uint32_t for 'biased_exp'.
   LIBC_INLINE static constexpr FPBits<T>
-  create_value(bool sign, StorageType biased_exp, StorageType mantissa) {
+  create_value(Sign sign, StorageType biased_exp, StorageType mantissa) {
     static_assert(get_fp_type<T>() != FPType::X86_Binary80,
                   "This function is not tested for X86 Extended Precision");
     return FPBits(UP::encode(
diff --git a/libc/src/__support/FPUtil/ManipulationFunctions.h b/libc/src/__support/FPUtil/ManipulationFunctions.h
index 42433b9b8442db3..e0bd251883e20b8 100644
--- a/libc/src/__support/FPUtil/ManipulationFunctions.h
+++ b/libc/src/__support/FPUtil/ManipulationFunctions.h
@@ -49,13 +49,13 @@ LIBC_INLINE T modf(T x, T &iptr) {
     return x;
   } else if (bits.is_inf()) {
     iptr = x;
-    return bits.get_sign() ? T(FPBits<T>::neg_zero()) : T(FPBits<T>::zero());
+    return bits.is_neg() ? T(FPBits<T>::neg_zero()) : T(FPBits<T>::zero());
   } else {
     iptr = trunc(x);
     if (x == iptr) {
       // If x is already an integer value, then return zero with the right
       // sign.
-      return bits.get_sign() ? T(FPBits<T>::neg_zero()) : T(FPBits<T>::zero());
+      return bits.is_neg() ? T(FPBits<T>::neg_zero()) : T(FPBits<T>::zero());
     } else {
       return x - iptr;
     }
@@ -65,7 +65,7 @@ LIBC_INLINE T modf(T x, T &iptr) {
 template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
 LIBC_INLINE T copysign(T x, T y) {
   FPBits<T> xbits(x);
-  xbits.set_sign(FPBits<T>(y).get_sign());
+  xbits.set_sign(FPBits<T>(y).sign());
   return T(xbits);
 }
 
@@ -131,11 +131,11 @@ LIBC_INLINE T ldexp(T x, int exp) {
   // calculating the limit.
   int exp_limit = FPBits<T>::MAX_BIASED_EXPONENT + FPBits<T>::FRACTION_LEN + 1;
   if (exp > exp_limit)
-    return bits.get_sign() ? T(FPBits<T>::neg_inf()) : T(FPBits<T>::inf());
+    return bits.is_neg() ? T(FPBits<T>::neg_inf()) : T(FPBits<T>::inf());
 
   // Similarly on the negative side we return zero early if |exp| is too small.
   if (exp < -exp_limit)
-    return bits.get_sign() ? T(FPBits<T>::neg_zero()) : T(FPBits<T>::zero());
+    return bits.is_neg() ? T(FPBits<T>::neg_zero()) : T(FPBits<T>::zero());
 
   // For all other values, NormalFloat to T conversion handles it the right way.
   NormalFloat<T> normal(bits);
@@ -173,7 +173,7 @@ LIBC_INLINE T nextafter(T from, U to) {
     }
   } else {
     int_val = FPBits<T>::MIN_SUBNORMAL;
-    if (to_bits.get_sign())
+    if (to_bits.is_neg())
       int_val |= FPBits<T>::SIGN_MASK;
   }
 
diff --git a/libc/src/__support/FPUtil/NearestIntegerOperations.h b/libc/src/__support/FPUtil/NearestIntegerOperations.h
index 64c44e0b3a0c44c..e32b4d27a7a1df9 100644
--- a/libc/src/__support/FPUtil/NearestIntegerOperations.h
+++ b/libc/src/__support/FPUtil/NearestIntegerOperations.h
@@ -41,7 +41,7 @@ LIBC_INLINE T trunc(T x) {
 
   // If the exponent is such that abs(x) is less than 1, then return 0.
   if (exponent <= -1) {
-    if (bits.get_sign())
+    if (bits.is_neg())
       return T(-0.0);
     else
       return T(0.0);
@@ -60,7 +60,7 @@ LIBC_INLINE T ceil(T x) {
   if (bits.is_inf_or_nan() || bits.is_zero())
     return x;
 
-  bool is_neg = bits.get_sign();
+  bool is_neg = bits.is_neg();
   int exponent = bits.get_exponent();
 
   // If the exponent is greater than the most negative mantissa
@@ -93,7 +93,7 @@ LIBC_INLINE T ceil(T x) {
 template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
 LIBC_INLINE T floor(T x) {
   FPBits<T> bits(x);
-  if (bits.get_sign()) {
+  if (bits.is_neg()) {
     return -ceil(-x);
   } else {
     return trunc(x);
@@ -109,7 +109,7 @@ LIBC_INLINE T round(T x) {
   if (bits.is_inf_or_nan() || bits.is_zero())
     return x;
 
-  bool is_neg = bits.get_sign();
+  bool is_neg = bits.is_neg();
   int exponent = bits.get_exponent();
 
   // If the exponent is greater than the most negative mantissa
@@ -161,7 +161,7 @@ LIBC_INLINE T round_using_current_rounding_mode(T x) {
   if (bits.is_inf_or_nan() || bits.is_zero())
     return x;
 
-  bool is_neg = bits.get_sign();
+  bool is_neg = bits.is_neg();
   int exponent = bits.get_exponent();
   int rounding_mode = quick_get_round();
 
@@ -247,18 +247,18 @@ LIBC_INLINE I rounded_float_to_signed_integer(F x) {
 
   if (bits.is_inf_or_nan()) {
     set_domain_error_and_raise_invalid();
-    return bits.get_sign() ? INTEGER_MIN : INTEGER_MAX;
+    return bits.is_neg() ? INTEGER_MIN : INTEGER_MAX;
   }
 
   int exponent = bits.get_exponent();
   constexpr int EXPONENT_LIMIT = sizeof(I) * 8 - 1;
   if (exponent > EXPONENT_LIMIT) {
     set_domain_error_and_raise_invalid();
-    return bits.get_sign() ? INTEGER_MIN : INTEGER_MAX;
+    return bits.is_neg() ? INTEGER_MIN : INTEGER_MAX;
   } else if (exponent == EXPONENT_LIMIT) {
-    if (bits.get_sign() == 0 || bits.get_mantissa() != 0) {
+    if (bits.is_neg() == 0 || bits.get_mantissa() != 0) {
       set_domain_error_and_raise_invalid();
-      return bits.get_sign() ? INTEGER_MIN : INTEGER_MAX;
+      return bits.is_neg() ? INTEGER_MIN : INTEGER_MAX;
     }
     // If the control reaches here, then it means that the rounded
     // value is the most negative number for the signed integer type I.
diff --git a/libc/src/__support/FPUtil/NormalFloat.h b/libc/src/__support/FPUtil/NormalFloat.h
index e70c89a7dbe15aa..39376bfcba03196 100644
--- a/libc/src/__support/FPUtil/NormalFloat.h
+++ b/libc/src/__support/FPUtil/NormalFloat.h
@@ -44,10 +44,10 @@ template <typename T> struct NormalFloat {
   static_assert(sizeof(StorageType) * 8 >= FPBits<T>::FRACTION_LEN + 1,
                 "Bad type for mantissa in NormalFloat.");
 
-  bool sign;
+  Sign sign = Sign::POS;
 
   LIBC_INLINE NormalFloat(int32_t e, StorageType m, bool s)
-      : exponent(e), mantissa(m), sign(s) {
+      : exponent(e), mantissa(m), sign(Sign(s)) {
     if (mantissa >= ONE)
       return;
 
@@ -64,20 +64,21 @@ template <typename T> struct NormalFloat {
   // Returns -1 is this number is less than |other|, 0 if this number is equal
   // to |other|, and 1 if this number is greater than |other|.
   LIBC_INLINE int cmp(const NormalFloat<T> &other) const {
+    const int result = sign.is_neg() ? -1 : 1;
     if (sign != other.sign)
-      return sign ? -1 : 1;
+      return result;
 
     if (exponent > other.exponent) {
-      return sign ? -1 : 1;
+      return result;
     } else if (exponent == other.exponent) {
       if (mantissa > other.mantissa)
-        return sign ? -1 : 1;
+        return result;
       else if (mantissa == other.mantissa)
         return 0;
       else
-        return sign ? 1 : -1;
+        return -result;
     } else {
-      return sign ? 1 : -1;
+      return -result;
     }
   }
 
@@ -95,7 +96,7 @@ template <typename T> struct NormalFloat {
     // Max exponent is of the form 0xFF...E. That is why -2 and not -1.
     constexpr int MAX_EXPONENT_VALUE = (1 << FPBits<T>::EXP_LEN) - 2;
     if (biased_exponent > MAX_EXPONENT_VALUE) {
-      return sign ? T(FPBits<T>::neg_inf()) : T(FPBits<T>::inf());
+      return T(FPBits<T>::inf(sign));
     }
 
     FPBits<T> result(T(0.0));
@@ -141,7 +142,7 @@ template <typename T> struct NormalFloat {
 
 private:
   LIBC_INLINE void init_from_bits(FPBits<T> bits) {
-    sign = bits.get_sign();
+    sign = bits.sign();
 
     if (bits.is_inf_or_nan() || bits.is_zero()) {
       // Ignore s...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/78500


More information about the libc-commits mailing list