@@ -247,27 +247,69 @@ round_using_current_rounding_mode(T x) {
247
247
template <bool IsSigned, typename T>
248
248
LIBC_INLINE constexpr cpp::enable_if_t <cpp::is_floating_point_v<T>, T>
249
249
fromfp (T x, int rnd, unsigned int width) {
250
- if (width == 0U )
250
+ using StorageType = typename FPBits<T>::StorageType;
251
+
252
+ constexpr StorageType EXPLICIT_BIT =
253
+ FPBits<T>::SIG_MASK - FPBits<T>::FRACTION_MASK;
254
+
255
+ if (width == 0U ) {
256
+ raise_except_if_required (FE_INVALID);
257
+ return FPBits<T>::quiet_nan ().get_val ();
258
+ }
259
+
260
+ FPBits<T> bits (x);
261
+
262
+ if (bits.is_inf_or_nan ()) {
263
+ raise_except_if_required (FE_INVALID);
251
264
return FPBits<T>::quiet_nan ().get_val ();
265
+ }
252
266
253
267
T rounded_value = round_using_specific_rounding_mode (x, rnd);
254
268
255
269
if constexpr (IsSigned) {
256
270
// T can't hold a finite number >= 2.0 * 2^EXP_BIAS.
257
271
if (width - 1 > FPBits<T>::EXP_BIAS)
258
272
return rounded_value;
259
- if (rounded_value < -T (1U << (width - 1U )))
273
+
274
+ StorageType range_exp = width - 1U + FPBits<T>::EXP_BIAS;
275
+ // rounded_value < -2^(width - 1)
276
+ T range_min =
277
+ FPBits<T>::create_value (Sign::NEG, range_exp, EXPLICIT_BIT).get_val ();
278
+ if (rounded_value < range_min) {
279
+ raise_except_if_required (FE_INVALID);
260
280
return FPBits<T>::quiet_nan ().get_val ();
261
- if (rounded_value > T ((1U << (width - 1U )) - 1U ))
281
+ }
282
+ // rounded_value > 2^(width - 1) - 1
283
+ T range_max =
284
+ FPBits<T>::create_value (Sign::POS, range_exp, EXPLICIT_BIT).get_val () -
285
+ T (1.0 );
286
+ if (rounded_value > range_max) {
287
+ raise_except_if_required (FE_INVALID);
262
288
return FPBits<T>::quiet_nan ().get_val ();
289
+ }
290
+
263
291
return rounded_value;
264
292
}
265
293
266
- if (rounded_value < T (0.0 ))
294
+ if (rounded_value < T (0.0 )) {
295
+ raise_except_if_required (FE_INVALID);
267
296
return FPBits<T>::quiet_nan ().get_val ();
297
+ }
298
+
268
299
// T can't hold a finite number >= 2.0 * 2^EXP_BIAS.
269
- if (width <= FPBits<T>::EXP_BIAS && rounded_value > T (1U << width) - 1U )
300
+ if (width > FPBits<T>::EXP_BIAS)
301
+ return rounded_value;
302
+
303
+ StorageType range_exp = width + FPBits<T>::EXP_BIAS;
304
+ // rounded_value > 2^width - 1
305
+ T range_max =
306
+ FPBits<T>::create_value (Sign::POS, range_exp, EXPLICIT_BIT).get_val () -
307
+ T (1.0 );
308
+ if (rounded_value > range_max) {
309
+ raise_except_if_required (FE_INVALID);
270
310
return FPBits<T>::quiet_nan ().get_val ();
311
+ }
312
+
271
313
return rounded_value;
272
314
}
273
315
0 commit comments