@@ -31,6 +31,32 @@ enum class FPType {
31
31
X86_Binary80,
32
32
};
33
33
34
+ // A type to interact with floating point type signs.
35
+ // This may be moved outside of 'fputil' if useful.
36
+ struct Sign {
37
+ LIBC_INLINE constexpr bool is_pos () const { return !is_negative; }
38
+ LIBC_INLINE constexpr bool is_neg () const { return is_negative; }
39
+
40
+ LIBC_INLINE friend constexpr bool operator ==(Sign a, Sign b) {
41
+ return a.is_negative == b.is_negative ;
42
+ }
43
+ LIBC_INLINE friend constexpr bool operator !=(Sign a, Sign b) {
44
+ return !(a == b);
45
+ }
46
+
47
+ static const Sign POS;
48
+ static const Sign NEG;
49
+
50
+ private:
51
+ LIBC_INLINE constexpr explicit Sign (bool is_negative)
52
+ : is_negative(is_negative) {}
53
+
54
+ bool is_negative;
55
+ };
56
+
57
+ LIBC_INLINE_VAR constexpr Sign Sign::NEG = Sign(true );
58
+ LIBC_INLINE_VAR constexpr Sign Sign::POS = Sign(false );
59
+
34
60
// The classes hierarchy is as follows:
35
61
//
36
62
// ┌───────────────────┐
@@ -273,9 +299,9 @@ struct FPRepBase : public internal::FPLayout<fp_type> {
273
299
return encode (exp) | encode (sig);
274
300
}
275
301
276
- LIBC_INLINE static constexpr StorageType encode (bool sign, BiasedExponent exp,
302
+ LIBC_INLINE static constexpr StorageType encode (Sign sign, BiasedExponent exp,
277
303
Significand sig) {
278
- if (sign)
304
+ if (sign. is_neg () )
279
305
return SIGN_MASK | encode (exp, sig);
280
306
return encode (exp, sig);
281
307
}
@@ -309,12 +335,12 @@ struct FPRepBase : public internal::FPLayout<fp_type> {
309
335
StorageType bits = 0 ;
310
336
311
337
public:
312
- LIBC_INLINE constexpr bool get_sign () const {
313
- return (bits & SIGN_MASK) != 0 ;
338
+ LIBC_INLINE constexpr Sign sign () const {
339
+ return (bits & SIGN_MASK) ? Sign::NEG : Sign::POS ;
314
340
}
315
341
316
- LIBC_INLINE constexpr void set_sign (bool signVal) {
317
- if (get_sign () != signVal)
342
+ LIBC_INLINE constexpr void set_sign (Sign signVal) {
343
+ if (sign () != signVal)
318
344
bits ^= SIGN_MASK;
319
345
}
320
346
@@ -363,6 +389,9 @@ struct FPRepBase : public internal::FPLayout<fp_type> {
363
389
LIBC_INLINE constexpr bool is_zero () const {
364
390
return (bits & EXP_SIG_MASK) == 0 ;
365
391
}
392
+
393
+ LIBC_INLINE constexpr bool is_neg () const { return sign ().is_neg (); }
394
+ LIBC_INLINE constexpr bool is_pos () const { return sign ().is_pos (); }
366
395
};
367
396
368
397
namespace internal {
@@ -421,35 +450,37 @@ template <FPType fp_type> struct FPRep : public FPRepBase<fp_type> {
421
450
return is_finite () && !is_subnormal ();
422
451
}
423
452
424
- LIBC_INLINE static constexpr StorageType zero (bool sign = false ) {
453
+ LIBC_INLINE static constexpr StorageType zero (Sign sign = Sign::POS ) {
425
454
return encode (sign, BiasedExponent::BITS_ALL_ZEROES (), Significand::ZERO ());
426
455
}
427
- LIBC_INLINE static constexpr StorageType one (bool sign = false ) {
456
+ LIBC_INLINE static constexpr StorageType one (Sign sign = Sign::POS ) {
428
457
return encode (sign, Exponent::ZERO (), Significand::ZERO ());
429
458
}
430
- LIBC_INLINE static constexpr StorageType min_subnormal (bool sign = false ) {
459
+ LIBC_INLINE static constexpr StorageType
460
+ min_subnormal (Sign sign = Sign::POS) {
431
461
return encode (sign, BiasedExponent::BITS_ALL_ZEROES (), Significand::LSB ());
432
462
}
433
- LIBC_INLINE static constexpr StorageType max_subnormal (bool sign = false ) {
463
+ LIBC_INLINE static constexpr StorageType
464
+ max_subnormal (Sign sign = Sign::POS) {
434
465
return encode (sign, BiasedExponent::BITS_ALL_ZEROES (),
435
466
Significand::BITS_ALL_ONES ());
436
467
}
437
- LIBC_INLINE static constexpr StorageType min_normal (bool sign = false ) {
468
+ LIBC_INLINE static constexpr StorageType min_normal (Sign sign = Sign::POS ) {
438
469
return encode (sign, Exponent::MIN (), Significand::ZERO ());
439
470
}
440
- LIBC_INLINE static constexpr StorageType max_normal (bool sign = false ) {
471
+ LIBC_INLINE static constexpr StorageType max_normal (Sign sign = Sign::POS ) {
441
472
return encode (sign, Exponent::MAX (), Significand::BITS_ALL_ONES ());
442
473
}
443
- LIBC_INLINE static constexpr StorageType inf (bool sign = false ) {
474
+ LIBC_INLINE static constexpr StorageType inf (Sign sign = Sign::POS ) {
444
475
return encode (sign, BiasedExponent::BITS_ALL_ONES (), Significand::ZERO ());
445
476
}
446
- LIBC_INLINE static constexpr StorageType build_nan (bool sign = false ,
477
+ LIBC_INLINE static constexpr StorageType build_nan (Sign sign = Sign::POS ,
447
478
StorageType v = 0 ) {
448
479
return encode (sign, BiasedExponent::BITS_ALL_ONES (),
449
480
(v ? Significand (v) : (Significand::MSB () >> 1 )));
450
481
}
451
- LIBC_INLINE static constexpr StorageType build_quiet_nan ( bool sign = false ,
452
- StorageType v = 0 ) {
482
+ LIBC_INLINE static constexpr StorageType
483
+ build_quiet_nan (Sign sign = Sign::POS, StorageType v = 0 ) {
453
484
return encode (sign, BiasedExponent::BITS_ALL_ONES (),
454
485
Significand::MSB () | Significand (v));
455
486
}
@@ -539,36 +570,38 @@ struct FPRep<FPType::X86_Binary80> : public FPRepBase<FPType::X86_Binary80> {
539
570
return get_implicit_bit ();
540
571
}
541
572
542
- LIBC_INLINE static constexpr StorageType zero (bool sign = false ) {
573
+ LIBC_INLINE static constexpr StorageType zero (Sign sign = Sign::POS ) {
543
574
return encode (sign, BiasedExponent::BITS_ALL_ZEROES (), Significand::ZERO ());
544
575
}
545
- LIBC_INLINE static constexpr StorageType one (bool sign = false ) {
576
+ LIBC_INLINE static constexpr StorageType one (Sign sign = Sign::POS ) {
546
577
return encode (sign, Exponent::ZERO (), Significand::MSB ());
547
578
}
548
- LIBC_INLINE static constexpr StorageType min_subnormal (bool sign = false ) {
579
+ LIBC_INLINE static constexpr StorageType
580
+ min_subnormal (Sign sign = Sign::POS) {
549
581
return encode (sign, BiasedExponent::BITS_ALL_ZEROES (), Significand::LSB ());
550
582
}
551
- LIBC_INLINE static constexpr StorageType max_subnormal (bool sign = false ) {
583
+ LIBC_INLINE static constexpr StorageType
584
+ max_subnormal (Sign sign = Sign::POS) {
552
585
return encode (sign, BiasedExponent::BITS_ALL_ZEROES (),
553
586
Significand::BITS_ALL_ONES () ^ Significand::MSB ());
554
587
}
555
- LIBC_INLINE static constexpr StorageType min_normal (bool sign = false ) {
588
+ LIBC_INLINE static constexpr StorageType min_normal (Sign sign = Sign::POS ) {
556
589
return encode (sign, Exponent::MIN (), Significand::MSB ());
557
590
}
558
- LIBC_INLINE static constexpr StorageType max_normal (bool sign = false ) {
591
+ LIBC_INLINE static constexpr StorageType max_normal (Sign sign = Sign::POS ) {
559
592
return encode (sign, Exponent::MAX (), Significand::BITS_ALL_ONES ());
560
593
}
561
- LIBC_INLINE static constexpr StorageType inf (bool sign = false ) {
594
+ LIBC_INLINE static constexpr StorageType inf (Sign sign = Sign::POS ) {
562
595
return encode (sign, BiasedExponent::BITS_ALL_ONES (), Significand::MSB ());
563
596
}
564
- LIBC_INLINE static constexpr StorageType build_nan (bool sign = false ,
597
+ LIBC_INLINE static constexpr StorageType build_nan (Sign sign = Sign::POS ,
565
598
StorageType v = 0 ) {
566
599
return encode (sign, BiasedExponent::BITS_ALL_ONES (),
567
600
Significand::MSB () |
568
601
(v ? Significand (v) : (Significand::MSB () >> 2 )));
569
602
}
570
- LIBC_INLINE static constexpr StorageType build_quiet_nan ( bool sign = false ,
571
- StorageType v = 0 ) {
603
+ LIBC_INLINE static constexpr StorageType
604
+ build_quiet_nan (Sign sign = Sign::POS, StorageType v = 0 ) {
572
605
return encode (sign, BiasedExponent::BITS_ALL_ONES (),
573
606
Significand::MSB () | (Significand::MSB () >> 1 ) |
574
607
Significand (v));
@@ -642,10 +675,10 @@ template <typename T> struct FPBits : public internal::FPRep<get_fp_type<T>()> {
642
675
643
676
// Constants.
644
677
static constexpr int MAX_BIASED_EXPONENT = (1 << EXP_LEN) - 1 ;
645
- static constexpr StorageType MIN_NORMAL = UP::min_normal(false );
646
- static constexpr StorageType MAX_NORMAL = UP::max_normal(false );
647
- static constexpr StorageType MIN_SUBNORMAL = UP::min_subnormal(false );
648
- static constexpr StorageType MAX_SUBNORMAL = UP::max_subnormal(false );
678
+ static constexpr StorageType MIN_NORMAL = UP::min_normal(Sign::POS );
679
+ static constexpr StorageType MAX_NORMAL = UP::max_normal(Sign::POS );
680
+ static constexpr StorageType MIN_SUBNORMAL = UP::min_subnormal(Sign::POS );
681
+ static constexpr StorageType MAX_SUBNORMAL = UP::max_subnormal(Sign::POS );
649
682
650
683
// Constructors.
651
684
LIBC_INLINE constexpr FPBits () = default;
@@ -675,45 +708,46 @@ template <typename T> struct FPBits : public internal::FPRep<get_fp_type<T>()> {
675
708
676
709
// Methods below this are used by tests.
677
710
678
- LIBC_INLINE static constexpr T zero ( bool sign = false ) {
679
- return FPBits (UP::zero (sign)).get_val ();
711
+ LIBC_INLINE static constexpr T one (Sign sign = Sign::POS ) {
712
+ return FPBits (UP::one (sign)).get_val ();
680
713
}
681
714
682
- LIBC_INLINE static constexpr T neg_zero () { return zero (true ); }
715
+ LIBC_INLINE static constexpr T zero (Sign sign = Sign::POS) {
716
+ return FPBits (UP::zero (sign)).get_val ();
717
+ }
683
718
684
- LIBC_INLINE static constexpr T inf (bool sign = false ) {
719
+ LIBC_INLINE static constexpr T inf (Sign sign = Sign::POS ) {
685
720
return FPBits (UP::inf (sign)).get_val ();
686
721
}
687
722
688
- LIBC_INLINE static constexpr T neg_inf () { return inf (true ); }
689
-
690
723
LIBC_INLINE static constexpr T min_normal () {
691
- return FPBits (UP::min_normal (false )).get_val ();
724
+ return FPBits (UP::min_normal (Sign::POS )).get_val ();
692
725
}
693
726
694
727
LIBC_INLINE static constexpr T max_normal () {
695
- return FPBits (UP::max_normal (false )).get_val ();
728
+ return FPBits (UP::max_normal (Sign::POS )).get_val ();
696
729
}
697
730
698
731
LIBC_INLINE static constexpr T min_denormal () {
699
- return FPBits (UP::min_subnormal (false )).get_val ();
732
+ return FPBits (UP::min_subnormal (Sign::POS )).get_val ();
700
733
}
701
734
702
735
LIBC_INLINE static constexpr T max_denormal () {
703
- return FPBits (UP::max_subnormal (false )).get_val ();
736
+ return FPBits (UP::max_subnormal (Sign::POS )).get_val ();
704
737
}
705
738
706
739
LIBC_INLINE static constexpr T build_nan (StorageType v) {
707
- return FPBits (UP::build_nan (false , v)).get_val ();
740
+ return FPBits (UP::build_nan (Sign::POS , v)).get_val ();
708
741
}
709
742
710
- LIBC_INLINE static constexpr T build_quiet_nan (StorageType v) {
711
- return FPBits (UP::build_quiet_nan (false , v)).get_val ();
743
+ LIBC_INLINE static constexpr T build_quiet_nan (StorageType v,
744
+ Sign sign = Sign::POS) {
745
+ return FPBits (UP::build_quiet_nan (sign, v)).get_val ();
712
746
}
713
747
714
748
// TODO: Use an uint32_t for 'biased_exp'.
715
749
LIBC_INLINE static constexpr FPBits<T>
716
- create_value (bool sign, StorageType biased_exp, StorageType mantissa) {
750
+ create_value (Sign sign, StorageType biased_exp, StorageType mantissa) {
717
751
static_assert (get_fp_type<T>() != FPType::X86_Binary80,
718
752
" This function is not tested for X86 Extended Precision" );
719
753
return FPBits (UP::encode (
0 commit comments