@@ -36,71 +36,74 @@ template <typename T> struct ExponentWidth {
36
36
// floating numbers. On x86 platforms however, the 'long double' type maps to
37
37
// an x87 floating point format. This format is an IEEE 754 extension format.
38
38
// It is handled as an explicit specialization of this class.
39
- template <typename T> struct FPBits {
39
+ template <typename T> struct FPBits : private FloatProperties <T> {
40
40
static_assert (cpp::is_floating_point_v<T>,
41
41
" FPBits instantiated with invalid type." );
42
+ using typename FloatProperties<T>::UIntType;
43
+ using FloatProperties<T>::BIT_WIDTH;
44
+ using FloatProperties<T>::EXP_MANT_MASK;
45
+ using FloatProperties<T>::EXPONENT_MASK;
46
+ using FloatProperties<T>::EXPONENT_BIAS;
47
+ using FloatProperties<T>::EXPONENT_WIDTH;
48
+ using FloatProperties<T>::MANTISSA_MASK;
49
+ using FloatProperties<T>::MANTISSA_WIDTH;
50
+ using FloatProperties<T>::QUIET_NAN_MASK;
51
+ using FloatProperties<T>::SIGN_MASK;
42
52
43
53
// Reinterpreting bits as an integer value and interpreting the bits of an
44
54
// integer value as a floating point value is used in tests. So, a convenient
45
55
// type is provided for such reinterpretations.
46
- using FloatProp = FloatProperties<T>;
47
- using UIntType = typename FloatProp::UIntType;
48
-
49
56
UIntType bits;
50
57
51
58
LIBC_INLINE constexpr void set_mantissa (UIntType mantVal) {
52
- mantVal &= (FloatProp:: MANTISSA_MASK) ;
53
- bits &= ~(FloatProp:: MANTISSA_MASK) ;
59
+ mantVal &= MANTISSA_MASK;
60
+ bits &= ~MANTISSA_MASK;
54
61
bits |= mantVal;
55
62
}
56
63
57
64
LIBC_INLINE constexpr UIntType get_mantissa () const {
58
- return bits & FloatProp:: MANTISSA_MASK;
65
+ return bits & MANTISSA_MASK;
59
66
}
60
67
61
68
LIBC_INLINE constexpr void set_biased_exponent (UIntType expVal) {
62
- expVal = (expVal << (FloatProp:: MANTISSA_WIDTH)) & FloatProp:: EXPONENT_MASK;
63
- bits &= ~(FloatProp:: EXPONENT_MASK) ;
69
+ expVal = (expVal << MANTISSA_WIDTH) & EXPONENT_MASK;
70
+ bits &= ~EXPONENT_MASK;
64
71
bits |= expVal;
65
72
}
66
73
67
74
LIBC_INLINE constexpr uint16_t get_biased_exponent () const {
68
- return uint16_t ((bits & FloatProp::EXPONENT_MASK) >>
69
- (FloatProp::MANTISSA_WIDTH));
75
+ return uint16_t ((bits & EXPONENT_MASK) >> MANTISSA_WIDTH);
70
76
}
71
77
72
78
// The function return mantissa with the implicit bit set iff the current
73
79
// value is a valid normal number.
74
80
LIBC_INLINE constexpr UIntType get_explicit_mantissa () {
75
81
return ((get_biased_exponent () > 0 && !is_inf_or_nan ())
76
- ? (FloatProp:: MANTISSA_MASK + 1 )
82
+ ? (MANTISSA_MASK + 1 )
77
83
: 0 ) |
78
- (FloatProp:: MANTISSA_MASK & bits);
84
+ (MANTISSA_MASK & bits);
79
85
}
80
86
81
87
LIBC_INLINE constexpr void set_sign (bool signVal) {
82
- bits |= FloatProp:: SIGN_MASK;
88
+ bits |= SIGN_MASK;
83
89
if (!signVal)
84
- bits -= FloatProp:: SIGN_MASK;
90
+ bits -= SIGN_MASK;
85
91
}
86
92
87
93
LIBC_INLINE constexpr bool get_sign () const {
88
- return (bits & FloatProp:: SIGN_MASK) != 0 ;
94
+ return (bits & SIGN_MASK) != 0 ;
89
95
}
90
96
91
97
static_assert (sizeof (T) == sizeof (UIntType),
92
98
" Data type and integral representation have different sizes." );
93
99
94
- static constexpr int EXPONENT_BIAS = (1 << (ExponentWidth<T>::VALUE - 1 )) - 1 ;
95
- static constexpr int MAX_EXPONENT = (1 << ExponentWidth<T>::VALUE) - 1 ;
100
+ static constexpr int MAX_EXPONENT = (1 << EXPONENT_WIDTH) - 1 ;
96
101
97
102
static constexpr UIntType MIN_SUBNORMAL = UIntType(1 );
98
- static constexpr UIntType MAX_SUBNORMAL =
99
- (UIntType(1 ) << MantissaWidth<T>::VALUE) - 1 ;
100
- static constexpr UIntType MIN_NORMAL =
101
- (UIntType(1 ) << MantissaWidth<T>::VALUE);
103
+ static constexpr UIntType MAX_SUBNORMAL = (UIntType(1 ) << MANTISSA_WIDTH) - 1 ;
104
+ static constexpr UIntType MIN_NORMAL = (UIntType(1 ) << MANTISSA_WIDTH);
102
105
static constexpr UIntType MAX_NORMAL =
103
- ((UIntType(MAX_EXPONENT) - 1 ) << MantissaWidth<T>::VALUE ) | MAX_SUBNORMAL;
106
+ ((UIntType(MAX_EXPONENT) - 1 ) << MANTISSA_WIDTH ) | MAX_SUBNORMAL;
104
107
105
108
// We don't want accidental type promotions/conversions, so we require exact
106
109
// type match.
@@ -151,32 +154,29 @@ template <typename T> struct FPBits {
151
154
}
152
155
153
156
LIBC_INLINE constexpr bool is_inf () const {
154
- return (bits & FloatProp:: EXP_MANT_MASK) == FloatProp:: EXPONENT_MASK;
157
+ return (bits & EXP_MANT_MASK) == EXPONENT_MASK;
155
158
}
156
159
157
160
LIBC_INLINE constexpr bool is_nan () const {
158
- return (bits & FloatProp:: EXP_MANT_MASK) > FloatProp:: EXPONENT_MASK;
161
+ return (bits & EXP_MANT_MASK) > EXPONENT_MASK;
159
162
}
160
163
161
164
LIBC_INLINE constexpr bool is_quiet_nan () const {
162
- return (bits & FloatProp::EXP_MANT_MASK) ==
163
- (FloatProp::EXPONENT_MASK | FloatProp::QUIET_NAN_MASK);
165
+ return (bits & EXP_MANT_MASK) == (EXPONENT_MASK | QUIET_NAN_MASK);
164
166
}
165
167
166
168
LIBC_INLINE constexpr bool is_inf_or_nan () const {
167
- return (bits & FloatProp:: EXPONENT_MASK) == FloatProp:: EXPONENT_MASK;
169
+ return (bits & EXPONENT_MASK) == EXPONENT_MASK;
168
170
}
169
171
170
172
LIBC_INLINE static constexpr T zero (bool sign = false ) {
171
- return FPBits (sign ? FloatProp:: SIGN_MASK : UIntType (0 )).get_val ();
173
+ return FPBits (sign ? SIGN_MASK : UIntType (0 )).get_val ();
172
174
}
173
175
174
176
LIBC_INLINE static constexpr T neg_zero () { return zero (true ); }
175
177
176
178
LIBC_INLINE static constexpr T inf (bool sign = false ) {
177
- return FPBits ((sign ? FloatProp::SIGN_MASK : UIntType (0 )) |
178
- FloatProp::EXPONENT_MASK)
179
- .get_val ();
179
+ return FPBits ((sign ? SIGN_MASK : UIntType (0 )) | EXPONENT_MASK).get_val ();
180
180
}
181
181
182
182
LIBC_INLINE static constexpr T neg_inf () { return inf (true ); }
@@ -204,7 +204,7 @@ template <typename T> struct FPBits {
204
204
}
205
205
206
206
LIBC_INLINE static constexpr T build_quiet_nan (UIntType v) {
207
- return build_nan (FloatProp:: QUIET_NAN_MASK | v);
207
+ return build_nan (QUIET_NAN_MASK | v);
208
208
}
209
209
210
210
// The function convert integer number and unbiased exponent to proper float
@@ -220,7 +220,7 @@ template <typename T> struct FPBits {
220
220
LIBC_INLINE static constexpr FPBits<T> make_value (UIntType number, int ep) {
221
221
FPBits<T> result;
222
222
// offset: +1 for sign, but -1 for implicit first bit
223
- int lz = cpp::countl_zero (number) - FloatProp:: EXPONENT_WIDTH;
223
+ int lz = cpp::countl_zero (number) - EXPONENT_WIDTH;
224
224
number <<= lz;
225
225
ep -= lz;
226
226
0 commit comments