@@ -56,85 +56,85 @@ template <> struct FPBits<long double> {
56
56
57
57
UIntType bits;
58
58
59
- LIBC_INLINE void set_mantissa (UIntType mantVal) {
59
+ LIBC_INLINE constexpr void set_mantissa (UIntType mantVal) {
60
60
mantVal &= (FloatProp::MANTISSA_MASK);
61
61
bits &= ~(FloatProp::MANTISSA_MASK);
62
62
bits |= mantVal;
63
63
}
64
64
65
- LIBC_INLINE UIntType get_mantissa () const {
65
+ LIBC_INLINE constexpr UIntType get_mantissa () const {
66
66
return bits & FloatProp::MANTISSA_MASK;
67
67
}
68
68
69
- LIBC_INLINE UIntType get_explicit_mantissa () const {
69
+ LIBC_INLINE constexpr UIntType get_explicit_mantissa () const {
70
70
return bits & (FloatProp::MANTISSA_MASK | FloatProp::EXPLICIT_BIT_MASK);
71
71
}
72
72
73
- LIBC_INLINE void set_unbiased_exponent (UIntType expVal) {
73
+ LIBC_INLINE constexpr void set_unbiased_exponent (UIntType expVal) {
74
74
expVal =
75
75
(expVal << (FloatProp::BIT_WIDTH - 1 - FloatProp::EXPONENT_WIDTH)) &
76
76
FloatProp::EXPONENT_MASK;
77
77
bits &= ~(FloatProp::EXPONENT_MASK);
78
78
bits |= expVal;
79
79
}
80
80
81
- LIBC_INLINE uint16_t get_unbiased_exponent () const {
81
+ LIBC_INLINE constexpr uint16_t get_unbiased_exponent () const {
82
82
return uint16_t ((bits & FloatProp::EXPONENT_MASK) >>
83
83
(FloatProp::BIT_WIDTH - 1 - FloatProp::EXPONENT_WIDTH));
84
84
}
85
85
86
- LIBC_INLINE void set_implicit_bit (bool implicitVal) {
86
+ LIBC_INLINE constexpr void set_implicit_bit (bool implicitVal) {
87
87
bits &= ~(UIntType (1 ) << FloatProp::MANTISSA_WIDTH);
88
88
bits |= (UIntType (implicitVal) << FloatProp::MANTISSA_WIDTH);
89
89
}
90
90
91
- LIBC_INLINE bool get_implicit_bit () const {
91
+ LIBC_INLINE constexpr bool get_implicit_bit () const {
92
92
return bool ((bits & (UIntType (1 ) << FloatProp::MANTISSA_WIDTH)) >>
93
93
FloatProp::MANTISSA_WIDTH);
94
94
}
95
95
96
- LIBC_INLINE void set_sign (bool signVal) {
96
+ LIBC_INLINE constexpr void set_sign (bool signVal) {
97
97
bits &= ~(FloatProp::SIGN_MASK);
98
98
UIntType sign1 = UIntType (signVal) << (FloatProp::BIT_WIDTH - 1 );
99
99
bits |= sign1;
100
100
}
101
101
102
- LIBC_INLINE bool get_sign () const {
102
+ LIBC_INLINE constexpr bool get_sign () const {
103
103
return bool ((bits & FloatProp::SIGN_MASK) >> (FloatProp::BIT_WIDTH - 1 ));
104
104
}
105
105
106
- FPBits () : bits(0 ) {}
106
+ constexpr FPBits () : bits(0 ) {}
107
107
108
108
template <typename XType,
109
109
cpp::enable_if_t <cpp::is_same_v<long double , XType>, int > = 0 >
110
- explicit FPBits (XType x) : bits(cpp::bit_cast<UIntType>(x)) {
110
+ constexpr explicit FPBits (XType x) : bits(cpp::bit_cast<UIntType>(x)) {
111
111
// bits starts uninitialized, and setting it to a long double only
112
112
// overwrites the first 80 bits. This clears those upper bits.
113
113
bits = bits & ((UIntType (1 ) << 80 ) - 1 );
114
114
}
115
115
116
116
template <typename XType,
117
117
cpp::enable_if_t <cpp::is_same_v<XType, UIntType>, int > = 0 >
118
- explicit FPBits (XType x) : bits(x) {}
118
+ constexpr explicit FPBits (XType x) : bits(x) {}
119
119
120
- LIBC_INLINE operator long double () {
120
+ LIBC_INLINE constexpr operator long double () {
121
121
return cpp::bit_cast<long double >(bits);
122
122
}
123
123
124
- LIBC_INLINE UIntType uintval () {
124
+ LIBC_INLINE constexpr UIntType uintval () {
125
125
// We zero the padding bits as they can contain garbage.
126
- static constexpr UIntType MASK =
126
+ constexpr UIntType MASK =
127
127
(UIntType (1 ) << (sizeof (long double ) * 8 -
128
128
Padding<sizeof (uintptr_t )>::VALUE)) -
129
129
1 ;
130
130
return bits & MASK;
131
131
}
132
132
133
- LIBC_INLINE long double get_val () const {
133
+ LIBC_INLINE constexpr long double get_val () const {
134
134
return cpp::bit_cast<long double >(bits);
135
135
}
136
136
137
- LIBC_INLINE int get_exponent () const {
137
+ LIBC_INLINE constexpr int get_exponent () const {
138
138
return int (get_unbiased_exponent ()) - EXPONENT_BIAS;
139
139
}
140
140
@@ -144,7 +144,7 @@ template <> struct FPBits<long double> {
144
144
// values are calculated from the exponent, since just subtracting the bias
145
145
// will give a slightly incorrect result. Additionally, zero has an exponent
146
146
// of zero, and that should actually be treated as zero.
147
- LIBC_INLINE int get_explicit_exponent () const {
147
+ LIBC_INLINE constexpr int get_explicit_exponent () const {
148
148
const int unbiased_exp = int (get_unbiased_exponent ());
149
149
if (is_zero ()) {
150
150
return 0 ;
@@ -155,17 +155,17 @@ template <> struct FPBits<long double> {
155
155
}
156
156
}
157
157
158
- LIBC_INLINE bool is_zero () const {
158
+ LIBC_INLINE constexpr bool is_zero () const {
159
159
return get_unbiased_exponent () == 0 && get_mantissa () == 0 &&
160
160
get_implicit_bit () == 0 ;
161
161
}
162
162
163
- LIBC_INLINE bool is_inf () const {
163
+ LIBC_INLINE constexpr bool is_inf () const {
164
164
return get_unbiased_exponent () == MAX_EXPONENT && get_mantissa () == 0 &&
165
165
get_implicit_bit () == 1 ;
166
166
}
167
167
168
- LIBC_INLINE bool is_nan () const {
168
+ LIBC_INLINE constexpr bool is_nan () const {
169
169
if (get_unbiased_exponent () == MAX_EXPONENT) {
170
170
return (get_implicit_bit () == 0 ) || get_mantissa () != 0 ;
171
171
} else if (get_unbiased_exponent () != 0 ) {
@@ -174,51 +174,58 @@ template <> struct FPBits<long double> {
174
174
return false ;
175
175
}
176
176
177
- LIBC_INLINE bool is_inf_or_nan () const {
177
+ LIBC_INLINE constexpr bool is_inf_or_nan () const {
178
178
return (get_unbiased_exponent () == MAX_EXPONENT) ||
179
179
(get_unbiased_exponent () != 0 && get_implicit_bit () == 0 );
180
180
}
181
181
182
182
// Methods below this are used by tests.
183
183
184
- LIBC_INLINE static FPBits<long double > zero () {
185
- return FPBits<long double >(0 .0l );
186
- }
184
+ LIBC_INLINE static constexpr long double zero () { return 0 .0l ; }
187
185
188
- LIBC_INLINE static FPBits<long double > neg_zero () {
189
- FPBits<long double > bits (0 .0l );
190
- bits.set_sign (1 );
191
- return bits;
192
- }
186
+ LIBC_INLINE static constexpr long double neg_zero () { return -0 .0l ; }
193
187
194
- LIBC_INLINE static FPBits< long double > inf () {
188
+ LIBC_INLINE static constexpr long double inf (bool sign = false ) {
195
189
FPBits<long double > bits (0 .0l );
196
190
bits.set_unbiased_exponent (MAX_EXPONENT);
197
191
bits.set_implicit_bit (1 );
198
- return bits;
192
+ if (sign) {
193
+ bits.set_sign (true );
194
+ }
195
+ return bits.get_val ();
199
196
}
200
197
201
- LIBC_INLINE static FPBits<long double > neg_inf () {
202
- FPBits<long double > bits (0 .0l );
203
- bits.set_unbiased_exponent (MAX_EXPONENT);
204
- bits.set_implicit_bit (1 );
205
- bits.set_sign (1 );
206
- return bits;
207
- }
198
+ LIBC_INLINE static constexpr long double neg_inf () { return inf (true ); }
208
199
209
- LIBC_INLINE static long double build_nan (UIntType v) {
200
+ LIBC_INLINE static constexpr long double build_nan (UIntType v) {
210
201
FPBits<long double > bits (0 .0l );
211
202
bits.set_unbiased_exponent (MAX_EXPONENT);
212
203
bits.set_implicit_bit (1 );
213
204
bits.set_mantissa (v);
214
205
return bits;
215
206
}
216
207
217
- LIBC_INLINE static long double build_quiet_nan (UIntType v) {
208
+ LIBC_INLINE static constexpr long double build_quiet_nan (UIntType v) {
218
209
return build_nan (FloatProp::QUIET_NAN_MASK | v);
219
210
}
220
211
221
- LIBC_INLINE static FPBits<long double >
212
+ LIBC_INLINE static constexpr long double min_normal () {
213
+ return FPBits (MIN_NORMAL).get_val ();
214
+ }
215
+
216
+ LIBC_INLINE static constexpr long double max_normal () {
217
+ return FPBits (MAX_NORMAL).get_val ();
218
+ }
219
+
220
+ LIBC_INLINE static constexpr long double min_denormal () {
221
+ return FPBits (MIN_SUBNORMAL).get_val ();
222
+ }
223
+
224
+ LIBC_INLINE static constexpr long double max_denormal () {
225
+ return FPBits (MAX_SUBNORMAL).get_val ();
226
+ }
227
+
228
+ LIBC_INLINE static constexpr FPBits<long double >
222
229
create_value (bool sign, UIntType unbiased_exp, UIntType mantissa) {
223
230
FPBits<long double > result;
224
231
result.set_sign (sign);
0 commit comments