[libc-commits] [libc] [libc][NFC] Simplify FloatProperties implementation #2 (PR #74821)
Guillaume Chatelet via libc-commits
libc-commits at lists.llvm.org
Fri Dec 8 06:40:13 PST 2023
https://github.com/gchatelet updated https://github.com/llvm/llvm-project/pull/74821
>From 36f717f6818bc372b4bdac9875606ec74c8b7d43 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Tue, 5 Dec 2023 14:59:52 +0000
Subject: [PATCH 1/6] [libc][NFC] Simplify FloatProperties implementation
---
libc/src/__support/FPUtil/FloatProperties.h | 131 ++++++++++++++------
1 file changed, 94 insertions(+), 37 deletions(-)
diff --git a/libc/src/__support/FPUtil/FloatProperties.h b/libc/src/__support/FPUtil/FloatProperties.h
index 59e261e1047f1..7f59679c477b9 100644
--- a/libc/src/__support/FPUtil/FloatProperties.h
+++ b/libc/src/__support/FPUtil/FloatProperties.h
@@ -10,7 +10,7 @@
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FLOATPROPERTIES_H
#include "src/__support/UInt128.h"
-#include "src/__support/macros/attributes.h" // LIBC_INLINE
+#include "src/__support/macros/attributes.h" // LIBC_INLINE, LIBC_INLINE_VAR
#include "src/__support/macros/properties/float.h" // LIBC_COMPILER_HAS_FLOAT128
#include <stdint.h>
@@ -27,22 +27,98 @@ enum class FPType {
X86_Binary80,
};
-template <FPType> struct FPProperties {};
-template <> struct FPProperties<FPType::IEEE754_Binary32> {
- typedef uint32_t BitsType;
+// For now 'FPEncoding', 'FPBaseProperties' and 'FPCommonProperties' are
+// implementation details.
+namespace internal {
+
+// The type of encoding for supported floating point types.
+enum class FPEncoding {
+ IEEE754,
+ X86_ExtendedPrecision,
+};
+
+template <FPType> struct FPBaseProperties {};
+
+template <> struct FPBaseProperties<FPType::IEEE754_Binary16> {
+ LIBC_INLINE_VAR static constexpr int FP_BITS = 16;
+ LIBC_INLINE_VAR static constexpr int SIG_BITS = 10;
+ LIBC_INLINE_VAR static constexpr int EXP_BITS = 5;
+ LIBC_INLINE_VAR static constexpr auto ENCODING = FPEncoding::IEEE754;
+ using UIntType = uint16_t;
+};
+
+template <> struct FPBaseProperties<FPType::IEEE754_Binary32> {
+ LIBC_INLINE_VAR static constexpr int FP_BITS = 32;
+ LIBC_INLINE_VAR static constexpr int SIG_BITS = 23;
+ LIBC_INLINE_VAR static constexpr int EXP_BITS = 8;
+ LIBC_INLINE_VAR static constexpr auto ENCODING = FPEncoding::IEEE754;
+ using UIntType = uint32_t;
+};
+
+template <> struct FPBaseProperties<FPType::IEEE754_Binary64> {
+ LIBC_INLINE_VAR static constexpr int FP_BITS = 64;
+ LIBC_INLINE_VAR static constexpr int SIG_BITS = 52;
+ LIBC_INLINE_VAR static constexpr int EXP_BITS = 11;
+ LIBC_INLINE_VAR static constexpr auto ENCODING = FPEncoding::IEEE754;
+ using UIntType = uint64_t;
+};
+
+template <> struct FPBaseProperties<FPType::IEEE754_Binary128> {
+ LIBC_INLINE_VAR static constexpr int FP_BITS = 128;
+ LIBC_INLINE_VAR static constexpr int SIG_BITS = 112;
+ LIBC_INLINE_VAR static constexpr int EXP_BITS = 15;
+ LIBC_INLINE_VAR static constexpr auto ENCODING = FPEncoding::IEEE754;
+ using UIntType = UInt128;
+};
+
+template <> struct FPBaseProperties<FPType::X86_Binary80> {
+ LIBC_INLINE_VAR static constexpr int FP_BITS = 80;
+ LIBC_INLINE_VAR static constexpr int SIG_BITS = 64;
+ LIBC_INLINE_VAR static constexpr int EXP_BITS = 15;
+ LIBC_INLINE_VAR static constexpr auto ENCODING =
+ FPEncoding::X86_ExtendedPrecision;
+ using UIntType = UInt128;
+};
+
+// Derives more properties from 'FPBaseProperties' above.
+// This class serves as a halfway point between 'FPBaseProperties' and
+// 'FPProperties' below.
+template <FPType fp_type>
+struct FPCommonProperties : private FPBaseProperties<fp_type> {
+ using UP = FPBaseProperties<fp_type>;
+ using BitsType = typename UP::UIntType;
+
+ LIBC_INLINE_VAR static constexpr uint32_t BIT_WIDTH = UP::FP_BITS;
+ LIBC_INLINE_VAR static constexpr uint32_t MANTISSA_WIDTH = UP::SIG_BITS;
+ LIBC_INLINE_VAR static constexpr uint32_t EXPONENT_WIDTH = UP::EXP_BITS;
+
+ // The exponent bias. Always positive.
+ LIBC_INLINE_VAR static constexpr uint32_t EXPONENT_BIAS =
+ (1U << (UP::EXP_BITS - 1U)) - 1U;
+ static_assert(EXPONENT_BIAS > 0);
+};
+
+} // namespace internal
- static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) * 8;
+template <FPType> struct FPProperties {};
- static constexpr uint32_t MANTISSA_WIDTH = 23;
+// ----------------
+// Work In Progress
+// ----------------
+// The 'FPProperties' template specializations below are being slowly replaced
+// with properties from 'FPCommonProperties' above. Once specializations are
+// empty, 'FPProperties' declaration can be fully replace with
+// 'FPCommonProperties' implementation.
+
+template <>
+struct FPProperties<FPType::IEEE754_Binary32>
+ : public internal::FPCommonProperties<FPType::IEEE754_Binary32> {
// The mantissa precision includes the implicit bit.
static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
- static constexpr uint32_t EXPONENT_WIDTH = 8;
static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
static constexpr BitsType SIGN_MASK = BitsType(1)
<< (EXPONENT_WIDTH + MANTISSA_WIDTH);
static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
- static constexpr uint32_t EXPONENT_BIAS = 127;
-
static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK + EXPONENT_MASK;
static_assert(EXP_MANT_MASK == ~SIGN_MASK,
"Exponent and mantissa masks are not as expected.");
@@ -53,20 +129,14 @@ template <> struct FPProperties<FPType::IEEE754_Binary32> {
static constexpr BitsType QUIET_NAN_MASK = 0x00400000U;
};
-template <> struct FPProperties<FPType::IEEE754_Binary64> {
- typedef uint64_t BitsType;
-
- static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) * 8;
-
- static constexpr uint32_t MANTISSA_WIDTH = 52;
+template <>
+struct FPProperties<FPType::IEEE754_Binary64>
+ : public internal::FPCommonProperties<FPType::IEEE754_Binary64> {
static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
- static constexpr uint32_t EXPONENT_WIDTH = 11;
static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
static constexpr BitsType SIGN_MASK = BitsType(1)
<< (EXPONENT_WIDTH + MANTISSA_WIDTH);
static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
- static constexpr uint32_t EXPONENT_BIAS = 1023;
-
static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK + EXPONENT_MASK;
static_assert(EXP_MANT_MASK == ~SIGN_MASK,
"Exponent and mantissa masks are not as expected.");
@@ -79,27 +149,20 @@ template <> struct FPProperties<FPType::IEEE754_Binary64> {
// Properties for numbers represented in 80 bits long double on non-Windows x86
// platforms.
-template <> struct FPProperties<FPType::X86_Binary80> {
- typedef UInt128 BitsType;
-
- static constexpr uint32_t BIT_WIDTH = (sizeof(BitsType) * 8) - 48;
+template <>
+struct FPProperties<FPType::X86_Binary80>
+ : public internal::FPCommonProperties<FPType::X86_Binary80> {
static constexpr BitsType FULL_WIDTH_MASK = ((BitsType(1) << BIT_WIDTH) - 1);
-
static constexpr uint32_t MANTISSA_WIDTH = 63;
static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
- static constexpr uint32_t EXPONENT_WIDTH = 15;
static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
-
// The x86 80 bit float represents the leading digit of the mantissa
// explicitly. This is the mask for that bit.
static constexpr BitsType EXPLICIT_BIT_MASK = (BitsType(1) << MANTISSA_WIDTH);
-
static constexpr BitsType SIGN_MASK =
BitsType(1) << (EXPONENT_WIDTH + MANTISSA_WIDTH + 1);
static constexpr BitsType EXPONENT_MASK =
((BitsType(1) << EXPONENT_WIDTH) - 1) << (MANTISSA_WIDTH + 1);
- static constexpr uint32_t EXPONENT_BIAS = 16383;
-
static constexpr BitsType EXP_MANT_MASK =
MANTISSA_MASK | EXPLICIT_BIT_MASK | EXPONENT_MASK;
static_assert(EXP_MANT_MASK == (~SIGN_MASK & FULL_WIDTH_MASK),
@@ -114,20 +177,14 @@ template <> struct FPProperties<FPType::X86_Binary80> {
// Properties for numbers represented in 128 bits long double on non x86
// platform.
-template <> struct FPProperties<FPType::IEEE754_Binary128> {
- typedef UInt128 BitsType;
-
- static constexpr uint32_t BIT_WIDTH = sizeof(BitsType) << 3;
-
- static constexpr uint32_t MANTISSA_WIDTH = 112;
+template <>
+struct FPProperties<FPType::IEEE754_Binary128>
+ : public internal::FPCommonProperties<FPType::IEEE754_Binary128> {
static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
- static constexpr uint32_t EXPONENT_WIDTH = 15;
static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
static constexpr BitsType SIGN_MASK = BitsType(1)
<< (EXPONENT_WIDTH + MANTISSA_WIDTH);
static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
- static constexpr uint32_t EXPONENT_BIAS = 16383;
-
static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK | EXPONENT_MASK;
static_assert(EXP_MANT_MASK == ~SIGN_MASK,
"Exponent and mantissa masks are not as expected.");
>From 8fa3aeac9045c4917072923724bfea7a7c70f0c4 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Wed, 6 Dec 2023 15:33:14 +0000
Subject: [PATCH 2/6] Use TOTAL_BITS instead of FP_BITS
---
libc/src/__support/FPUtil/FloatProperties.h | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/libc/src/__support/FPUtil/FloatProperties.h b/libc/src/__support/FPUtil/FloatProperties.h
index 7f59679c477b9..478c34482d820 100644
--- a/libc/src/__support/FPUtil/FloatProperties.h
+++ b/libc/src/__support/FPUtil/FloatProperties.h
@@ -40,7 +40,7 @@ enum class FPEncoding {
template <FPType> struct FPBaseProperties {};
template <> struct FPBaseProperties<FPType::IEEE754_Binary16> {
- LIBC_INLINE_VAR static constexpr int FP_BITS = 16;
+ LIBC_INLINE_VAR static constexpr int TOTAL_BITS = 16;
LIBC_INLINE_VAR static constexpr int SIG_BITS = 10;
LIBC_INLINE_VAR static constexpr int EXP_BITS = 5;
LIBC_INLINE_VAR static constexpr auto ENCODING = FPEncoding::IEEE754;
@@ -48,7 +48,7 @@ template <> struct FPBaseProperties<FPType::IEEE754_Binary16> {
};
template <> struct FPBaseProperties<FPType::IEEE754_Binary32> {
- LIBC_INLINE_VAR static constexpr int FP_BITS = 32;
+ LIBC_INLINE_VAR static constexpr int TOTAL_BITS = 32;
LIBC_INLINE_VAR static constexpr int SIG_BITS = 23;
LIBC_INLINE_VAR static constexpr int EXP_BITS = 8;
LIBC_INLINE_VAR static constexpr auto ENCODING = FPEncoding::IEEE754;
@@ -56,7 +56,7 @@ template <> struct FPBaseProperties<FPType::IEEE754_Binary32> {
};
template <> struct FPBaseProperties<FPType::IEEE754_Binary64> {
- LIBC_INLINE_VAR static constexpr int FP_BITS = 64;
+ LIBC_INLINE_VAR static constexpr int TOTAL_BITS = 64;
LIBC_INLINE_VAR static constexpr int SIG_BITS = 52;
LIBC_INLINE_VAR static constexpr int EXP_BITS = 11;
LIBC_INLINE_VAR static constexpr auto ENCODING = FPEncoding::IEEE754;
@@ -64,7 +64,7 @@ template <> struct FPBaseProperties<FPType::IEEE754_Binary64> {
};
template <> struct FPBaseProperties<FPType::IEEE754_Binary128> {
- LIBC_INLINE_VAR static constexpr int FP_BITS = 128;
+ LIBC_INLINE_VAR static constexpr int TOTAL_BITS = 128;
LIBC_INLINE_VAR static constexpr int SIG_BITS = 112;
LIBC_INLINE_VAR static constexpr int EXP_BITS = 15;
LIBC_INLINE_VAR static constexpr auto ENCODING = FPEncoding::IEEE754;
@@ -72,7 +72,7 @@ template <> struct FPBaseProperties<FPType::IEEE754_Binary128> {
};
template <> struct FPBaseProperties<FPType::X86_Binary80> {
- LIBC_INLINE_VAR static constexpr int FP_BITS = 80;
+ LIBC_INLINE_VAR static constexpr int TOTAL_BITS = 80;
LIBC_INLINE_VAR static constexpr int SIG_BITS = 64;
LIBC_INLINE_VAR static constexpr int EXP_BITS = 15;
LIBC_INLINE_VAR static constexpr auto ENCODING =
@@ -88,7 +88,7 @@ struct FPCommonProperties : private FPBaseProperties<fp_type> {
using UP = FPBaseProperties<fp_type>;
using BitsType = typename UP::UIntType;
- LIBC_INLINE_VAR static constexpr uint32_t BIT_WIDTH = UP::FP_BITS;
+ LIBC_INLINE_VAR static constexpr uint32_t BIT_WIDTH = UP::TOTAL_BITS;
LIBC_INLINE_VAR static constexpr uint32_t MANTISSA_WIDTH = UP::SIG_BITS;
LIBC_INLINE_VAR static constexpr uint32_t EXPONENT_WIDTH = UP::EXP_BITS;
>From 63477a442e974f74547894c56944b00ae092ffcc Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Wed, 6 Dec 2023 15:34:51 +0000
Subject: [PATCH 3/6] Move UIntType next to TOTAL_BITS
---
libc/src/__support/FPUtil/FloatProperties.h | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/libc/src/__support/FPUtil/FloatProperties.h b/libc/src/__support/FPUtil/FloatProperties.h
index 478c34482d820..caa9b710c5121 100644
--- a/libc/src/__support/FPUtil/FloatProperties.h
+++ b/libc/src/__support/FPUtil/FloatProperties.h
@@ -40,44 +40,44 @@ enum class FPEncoding {
template <FPType> struct FPBaseProperties {};
template <> struct FPBaseProperties<FPType::IEEE754_Binary16> {
+ using UIntType = uint16_t;
LIBC_INLINE_VAR static constexpr int TOTAL_BITS = 16;
LIBC_INLINE_VAR static constexpr int SIG_BITS = 10;
LIBC_INLINE_VAR static constexpr int EXP_BITS = 5;
LIBC_INLINE_VAR static constexpr auto ENCODING = FPEncoding::IEEE754;
- using UIntType = uint16_t;
};
template <> struct FPBaseProperties<FPType::IEEE754_Binary32> {
+ using UIntType = uint32_t;
LIBC_INLINE_VAR static constexpr int TOTAL_BITS = 32;
LIBC_INLINE_VAR static constexpr int SIG_BITS = 23;
LIBC_INLINE_VAR static constexpr int EXP_BITS = 8;
LIBC_INLINE_VAR static constexpr auto ENCODING = FPEncoding::IEEE754;
- using UIntType = uint32_t;
};
template <> struct FPBaseProperties<FPType::IEEE754_Binary64> {
+ using UIntType = uint64_t;
LIBC_INLINE_VAR static constexpr int TOTAL_BITS = 64;
LIBC_INLINE_VAR static constexpr int SIG_BITS = 52;
LIBC_INLINE_VAR static constexpr int EXP_BITS = 11;
LIBC_INLINE_VAR static constexpr auto ENCODING = FPEncoding::IEEE754;
- using UIntType = uint64_t;
};
template <> struct FPBaseProperties<FPType::IEEE754_Binary128> {
+ using UIntType = UInt128;
LIBC_INLINE_VAR static constexpr int TOTAL_BITS = 128;
LIBC_INLINE_VAR static constexpr int SIG_BITS = 112;
LIBC_INLINE_VAR static constexpr int EXP_BITS = 15;
LIBC_INLINE_VAR static constexpr auto ENCODING = FPEncoding::IEEE754;
- using UIntType = UInt128;
};
template <> struct FPBaseProperties<FPType::X86_Binary80> {
LIBC_INLINE_VAR static constexpr int TOTAL_BITS = 80;
+ using UIntType = UInt128;
LIBC_INLINE_VAR static constexpr int SIG_BITS = 64;
LIBC_INLINE_VAR static constexpr int EXP_BITS = 15;
LIBC_INLINE_VAR static constexpr auto ENCODING =
FPEncoding::X86_ExtendedPrecision;
- using UIntType = UInt128;
};
// Derives more properties from 'FPBaseProperties' above.
>From fa3855a02d34a9cdbf3e99e393056b8b2ea06bd6 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Wed, 6 Dec 2023 15:35:19 +0000
Subject: [PATCH 4/6] Fix wrong move
---
libc/src/__support/FPUtil/FloatProperties.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/src/__support/FPUtil/FloatProperties.h b/libc/src/__support/FPUtil/FloatProperties.h
index caa9b710c5121..4288cd719a1d8 100644
--- a/libc/src/__support/FPUtil/FloatProperties.h
+++ b/libc/src/__support/FPUtil/FloatProperties.h
@@ -72,8 +72,8 @@ template <> struct FPBaseProperties<FPType::IEEE754_Binary128> {
};
template <> struct FPBaseProperties<FPType::X86_Binary80> {
- LIBC_INLINE_VAR static constexpr int TOTAL_BITS = 80;
using UIntType = UInt128;
+ LIBC_INLINE_VAR static constexpr int TOTAL_BITS = 80;
LIBC_INLINE_VAR static constexpr int SIG_BITS = 64;
LIBC_INLINE_VAR static constexpr int EXP_BITS = 15;
LIBC_INLINE_VAR static constexpr auto ENCODING =
>From a416d0b2bea55d6ec4ae90f4c75eabafa2fb310b Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Fri, 8 Dec 2023 10:25:26 +0000
Subject: [PATCH 5/6] [libc][NFC] Simplify FloatProperties implementation #2
This is a follow up on #74481 that migrates code from all specialization into
FPCommonProperties (except X86_Binary80 EXPLICIT_BIT_MASK)
---
libc/src/__support/FPUtil/FloatProperties.h | 161 ++++++++++----------
1 file changed, 77 insertions(+), 84 deletions(-)
diff --git a/libc/src/__support/FPUtil/FloatProperties.h b/libc/src/__support/FPUtil/FloatProperties.h
index 4288cd719a1d8..1bee06dd42575 100644
--- a/libc/src/__support/FPUtil/FloatProperties.h
+++ b/libc/src/__support/FPUtil/FloatProperties.h
@@ -80,27 +80,96 @@ template <> struct FPBaseProperties<FPType::X86_Binary80> {
FPEncoding::X86_ExtendedPrecision;
};
+// TODO: Move this utility elsewhere.
+template <typename T, size_t count> static constexpr T mask_trailing_ones() {
+ static_assert(cpp::is_unsigned_v<T>);
+ constexpr unsigned t_bits = CHAR_BIT * sizeof(T);
+ static_assert(count <= t_bits && "Invalid bit index");
+ return count == 0 ? 0 : (T(-1) >> (t_bits - count));
+}
+
// Derives more properties from 'FPBaseProperties' above.
// This class serves as a halfway point between 'FPBaseProperties' and
// 'FPProperties' below.
template <FPType fp_type>
struct FPCommonProperties : private FPBaseProperties<fp_type> {
+private:
using UP = FPBaseProperties<fp_type>;
- using BitsType = typename UP::UIntType;
+ using UP::EXP_BITS;
+ using UP::SIG_BITS;
+ using UP::TOTAL_BITS;
+ using UIntType = typename UP::UIntType;
+
+ LIBC_INLINE_VAR static constexpr bool HAS_EXPLICIT_SIG_BIT =
+ UP::ENCODING == FPEncoding::X86_ExtendedPrecision;
+ LIBC_INLINE_VAR static constexpr int EXPLICIT_SIG_BITS =
+ HAS_EXPLICIT_SIG_BIT ? 1 : 0;
- LIBC_INLINE_VAR static constexpr uint32_t BIT_WIDTH = UP::TOTAL_BITS;
- LIBC_INLINE_VAR static constexpr uint32_t MANTISSA_WIDTH = UP::SIG_BITS;
- LIBC_INLINE_VAR static constexpr uint32_t EXPONENT_WIDTH = UP::EXP_BITS;
+ LIBC_INLINE_VAR static constexpr int STORAGE_BITS =
+ sizeof(UIntType) * CHAR_BIT;
+ static_assert(STORAGE_BITS >= TOTAL_BITS);
+
+ // The number of bits to represent sign.
+ // For documentation purpose, always 1.
+ LIBC_INLINE_VAR static constexpr int SIGN_BITS = 1;
+ static_assert(SIGN_BITS + EXP_BITS + SIG_BITS == TOTAL_BITS);
// The exponent bias. Always positive.
- LIBC_INLINE_VAR static constexpr uint32_t EXPONENT_BIAS =
- (1U << (UP::EXP_BITS - 1U)) - 1U;
- static_assert(EXPONENT_BIAS > 0);
+ LIBC_INLINE_VAR static constexpr int32_t EXP_BIAS =
+ (1U << (EXP_BITS - 1U)) - 1U;
+ static_assert(EXP_BIAS > 0);
+
+ // Shifts
+ LIBC_INLINE_VAR static constexpr int SIG_MASK_SHIFT = 0;
+ LIBC_INLINE_VAR static constexpr int EXP_MASK_SHIFT = SIG_BITS;
+ LIBC_INLINE_VAR static constexpr int SIGN_MASK_SHIFT = SIG_BITS + EXP_BITS;
+
+ // Masks
+ LIBC_INLINE_VAR static constexpr UIntType SIG_MASK =
+ mask_trailing_ones<UIntType, SIG_BITS>() << SIG_MASK_SHIFT;
+ LIBC_INLINE_VAR static constexpr UIntType EXP_MASK =
+ mask_trailing_ones<UIntType, EXP_BITS>() << EXP_MASK_SHIFT;
+ LIBC_INLINE_VAR static constexpr UIntType SIGN_MASK_ =
+ mask_trailing_ones<UIntType, SIGN_BITS>() << SIGN_MASK_SHIFT;
+ LIBC_INLINE_VAR static constexpr UIntType FP_MASK =
+ mask_trailing_ones<UIntType, TOTAL_BITS>();
+ static_assert((SIG_MASK & EXP_MASK & SIGN_MASK_) == 0, "masks disjoint");
+ static_assert((SIG_MASK | EXP_MASK | SIGN_MASK_) == FP_MASK, "masks covers");
+
+ //
+ LIBC_INLINE_VAR static constexpr int FRACTION_BITS =
+ SIG_BITS - EXPLICIT_SIG_BITS;
+ LIBC_INLINE_VAR static constexpr UIntType QNAN_MASK = UIntType(1)
+ << (FRACTION_BITS - 1);
+ LIBC_INLINE_VAR static constexpr UIntType SNAN_MASK = UIntType(1)
+ << (FRACTION_BITS - 2);
+
+public:
+ // Public facing API to keep the change local to this file.
+ using BitsType = UIntType;
+
+ LIBC_INLINE_VAR static constexpr uint32_t BIT_WIDTH = TOTAL_BITS;
+ LIBC_INLINE_VAR static constexpr uint32_t MANTISSA_WIDTH = FRACTION_BITS;
+ LIBC_INLINE_VAR static constexpr uint32_t MANTISSA_PRECISION =
+ MANTISSA_WIDTH + 1;
+ LIBC_INLINE_VAR static constexpr BitsType MANTISSA_MASK =
+ (BitsType(1) << MANTISSA_WIDTH) - 1;
+ LIBC_INLINE_VAR static constexpr uint32_t EXPONENT_WIDTH = EXP_BITS;
+ LIBC_INLINE_VAR static constexpr uint32_t EXPONENT_BIAS = EXP_BIAS;
+ LIBC_INLINE_VAR static constexpr BitsType SIGN_MASK = SIGN_MASK_;
+ LIBC_INLINE_VAR static constexpr BitsType EXPONENT_MASK = EXP_MASK;
+ LIBC_INLINE_VAR static constexpr BitsType EXP_MANT_MASK = EXP_MASK | SIG_MASK;
+
+ // If a number x is a NAN, then it is a quiet NAN if:
+ // QuietNaNMask & bits(x) != 0
+ // Else, it is a signalling NAN.
+ static constexpr BitsType QUIET_NAN_MASK = QNAN_MASK;
};
} // namespace internal
-template <FPType> struct FPProperties {};
+template <FPType fp_type>
+struct FPProperties : public internal::FPCommonProperties<fp_type> {};
// ----------------
// Work In Progress
@@ -110,90 +179,14 @@ template <FPType> struct FPProperties {};
// empty, 'FPProperties' declaration can be fully replace with
// 'FPCommonProperties' implementation.
-template <>
-struct FPProperties<FPType::IEEE754_Binary32>
- : public internal::FPCommonProperties<FPType::IEEE754_Binary32> {
- // The mantissa precision includes the implicit bit.
- static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
- static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
- static constexpr BitsType SIGN_MASK = BitsType(1)
- << (EXPONENT_WIDTH + MANTISSA_WIDTH);
- static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
- static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK + EXPONENT_MASK;
- static_assert(EXP_MANT_MASK == ~SIGN_MASK,
- "Exponent and mantissa masks are not as expected.");
-
- // If a number x is a NAN, then it is a quiet NAN if:
- // QuietNaNMask & bits(x) != 0
- // Else, it is a signalling NAN.
- static constexpr BitsType QUIET_NAN_MASK = 0x00400000U;
-};
-
-template <>
-struct FPProperties<FPType::IEEE754_Binary64>
- : public internal::FPCommonProperties<FPType::IEEE754_Binary64> {
- static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
- static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
- static constexpr BitsType SIGN_MASK = BitsType(1)
- << (EXPONENT_WIDTH + MANTISSA_WIDTH);
- static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
- static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK + EXPONENT_MASK;
- static_assert(EXP_MANT_MASK == ~SIGN_MASK,
- "Exponent and mantissa masks are not as expected.");
-
- // If a number x is a NAN, then it is a quiet NAN if:
- // QuietNaNMask & bits(x) != 0
- // Else, it is a signalling NAN.
- static constexpr BitsType QUIET_NAN_MASK = 0x0008000000000000ULL;
-};
-
// Properties for numbers represented in 80 bits long double on non-Windows x86
// platforms.
template <>
struct FPProperties<FPType::X86_Binary80>
: public internal::FPCommonProperties<FPType::X86_Binary80> {
- static constexpr BitsType FULL_WIDTH_MASK = ((BitsType(1) << BIT_WIDTH) - 1);
- static constexpr uint32_t MANTISSA_WIDTH = 63;
- static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
- static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
// The x86 80 bit float represents the leading digit of the mantissa
// explicitly. This is the mask for that bit.
static constexpr BitsType EXPLICIT_BIT_MASK = (BitsType(1) << MANTISSA_WIDTH);
- static constexpr BitsType SIGN_MASK =
- BitsType(1) << (EXPONENT_WIDTH + MANTISSA_WIDTH + 1);
- static constexpr BitsType EXPONENT_MASK =
- ((BitsType(1) << EXPONENT_WIDTH) - 1) << (MANTISSA_WIDTH + 1);
- static constexpr BitsType EXP_MANT_MASK =
- MANTISSA_MASK | EXPLICIT_BIT_MASK | EXPONENT_MASK;
- static_assert(EXP_MANT_MASK == (~SIGN_MASK & FULL_WIDTH_MASK),
- "Exponent and mantissa masks are not as expected.");
-
- // If a number x is a NAN, then it is a quiet NAN if:
- // QuietNaNMask & bits(x) != 0
- // Else, it is a signalling NAN.
- static constexpr BitsType QUIET_NAN_MASK = BitsType(1)
- << (MANTISSA_WIDTH - 1);
-};
-
-// Properties for numbers represented in 128 bits long double on non x86
-// platform.
-template <>
-struct FPProperties<FPType::IEEE754_Binary128>
- : public internal::FPCommonProperties<FPType::IEEE754_Binary128> {
- static constexpr uint32_t MANTISSA_PRECISION = MANTISSA_WIDTH + 1;
- static constexpr BitsType MANTISSA_MASK = (BitsType(1) << MANTISSA_WIDTH) - 1;
- static constexpr BitsType SIGN_MASK = BitsType(1)
- << (EXPONENT_WIDTH + MANTISSA_WIDTH);
- static constexpr BitsType EXPONENT_MASK = ~(SIGN_MASK | MANTISSA_MASK);
- static constexpr BitsType EXP_MANT_MASK = MANTISSA_MASK | EXPONENT_MASK;
- static_assert(EXP_MANT_MASK == ~SIGN_MASK,
- "Exponent and mantissa masks are not as expected.");
-
- // If a number x is a NAN, then it is a quiet NAN if:
- // QuietNaNMask & bits(x) != 0
- // Else, it is a signalling NAN.
- static constexpr BitsType QUIET_NAN_MASK = BitsType(1)
- << (MANTISSA_WIDTH - 1);
};
//-----------------------------------------------------------------------------
>From 5ee15af4257c770445b755252b4af9b16e4a60c5 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Fri, 8 Dec 2023 14:39:55 +0000
Subject: [PATCH 6/6] Make cast obvious
---
libc/src/__support/FPUtil/FloatProperties.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libc/src/__support/FPUtil/FloatProperties.h b/libc/src/__support/FPUtil/FloatProperties.h
index 1bee06dd42575..6c311db9d40e6 100644
--- a/libc/src/__support/FPUtil/FloatProperties.h
+++ b/libc/src/__support/FPUtil/FloatProperties.h
@@ -155,7 +155,8 @@ struct FPCommonProperties : private FPBaseProperties<fp_type> {
LIBC_INLINE_VAR static constexpr BitsType MANTISSA_MASK =
(BitsType(1) << MANTISSA_WIDTH) - 1;
LIBC_INLINE_VAR static constexpr uint32_t EXPONENT_WIDTH = EXP_BITS;
- LIBC_INLINE_VAR static constexpr uint32_t EXPONENT_BIAS = EXP_BIAS;
+ LIBC_INLINE_VAR static constexpr uint32_t EXPONENT_BIAS =
+ static_cast<uint32_t>(EXP_BIAS);
LIBC_INLINE_VAR static constexpr BitsType SIGN_MASK = SIGN_MASK_;
LIBC_INLINE_VAR static constexpr BitsType EXPONENT_MASK = EXP_MASK;
LIBC_INLINE_VAR static constexpr BitsType EXP_MANT_MASK = EXP_MASK | SIG_MASK;
More information about the libc-commits
mailing list