Skip to content

[libc][NFC] Introduce a Sign type for FPBits #78500

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

Merged
merged 10 commits into from
Jan 18, 2024

Conversation

gchatelet
Copy link
Contributor

Another patch is needed to cover DyadicFloat and NormalFloat constructors.

Another patch is needed to cover `DyadicFloat` and `NormalFloat` constructors.
@llvmbot
Copy link
Member

llvmbot commented Jan 17, 2024

@llvm/pr-subscribers-libc

Author: Guillaume Chatelet (gchatelet)

Changes

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 --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]

Copy link

github-actions bot commented Jan 17, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@gchatelet
Copy link
Contributor Author

@legrosbuffle this one is big but trivial. You may want to review it commit by commit.

Copy link
Contributor

@legrosbuffle legrosbuffle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing this, this is so much more readable !

@gchatelet gchatelet merged commit 11ec512 into llvm:main Jan 18, 2024
@gchatelet gchatelet deleted the add_fputil_sign branch January 18, 2024 12:40
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.

3 participants