@@ -68,8 +68,8 @@ struct BigInt {
68
68
val[i] = other[i];
69
69
WordType sign = 0 ;
70
70
if constexpr (Signed && OtherSigned) {
71
- sign = static_cast <WordType>(- static_cast < make_signed_t <WordType>>(
72
- other[OtherBits / WORD_SIZE - 1 ] >> (WORD_SIZE - 1 )));
71
+ sign = static_cast <WordType>(
72
+ - static_cast < make_signed_t <WordType>>(other. is_neg ( )));
73
73
}
74
74
for (; i < WORD_COUNT; ++i)
75
75
val[i] = sign;
@@ -125,6 +125,11 @@ struct BigInt {
125
125
val[i] = words[i];
126
126
}
127
127
128
+ // TODO: Reuse the Sign type.
129
+ LIBC_INLINE constexpr bool is_neg () const {
130
+ return val.back () >> (WORD_SIZE - 1 );
131
+ }
132
+
128
133
template <typename T> LIBC_INLINE constexpr explicit operator T () const {
129
134
return to<T>();
130
135
}
@@ -148,7 +153,7 @@ struct BigInt {
148
153
if constexpr (Signed && (T_BITS > Bits)) {
149
154
// Extend sign for negative numbers.
150
155
constexpr T MASK = (~T (0 ) << Bits);
151
- if (val[WORD_COUNT - 1 ] >> (WORD_SIZE - 1 ))
156
+ if (is_neg ( ))
152
157
lo |= MASK;
153
158
}
154
159
@@ -267,8 +272,8 @@ struct BigInt {
267
272
if constexpr (Signed) {
268
273
BigInt<Bits, false , WordType> a (*this );
269
274
BigInt<Bits, false , WordType> b (other);
270
- bool a_neg = (a. val [WORD_COUNT - 1 ] >> (WORD_SIZE - 1 ) );
271
- bool b_neg = (b. val [WORD_COUNT - 1 ] >> (WORD_SIZE - 1 ) );
275
+ const bool a_neg = a. is_neg ( );
276
+ const bool b_neg = b. is_neg ( );
272
277
if (a_neg)
273
278
a = -a;
274
279
if (b_neg)
@@ -278,7 +283,6 @@ struct BigInt {
278
283
prod = -prod;
279
284
return static_cast <BigInt<Bits, true , WordType>>(prod);
280
285
} else {
281
-
282
286
if constexpr (WORD_COUNT == 1 ) {
283
287
return {val[0 ] * other.val [0 ]};
284
288
} else {
@@ -383,10 +387,9 @@ struct BigInt {
383
387
BigInt cur_power = *this ;
384
388
385
389
while (power > 0 ) {
386
- if ((power % 2 ) > 0 ) {
387
- result = result * cur_power;
388
- }
389
- power = power >> 1 ;
390
+ if ((power % 2 ) > 0 )
391
+ result *= cur_power;
392
+ power >>= 1 ;
390
393
cur_power *= cur_power;
391
394
}
392
395
*this = result;
@@ -709,7 +712,7 @@ struct BigInt {
709
712
const size_t shift = s % WORD_SIZE; // Bit shift in the remaining words.
710
713
711
714
size_t i = 0 ;
712
- WordType sign = Signed ? (val[WORD_COUNT - 1 ] >> (WORD_SIZE - 1 ) ) : 0 ;
715
+ WordType sign = Signed ? is_neg ( ) : 0 ;
713
716
714
717
if (drop < WORD_COUNT) {
715
718
if (shift > 0 ) {
@@ -747,49 +750,31 @@ struct BigInt {
747
750
return *this ;
748
751
}
749
752
750
- LIBC_INLINE constexpr BigInt operator &(const BigInt &other) const {
751
- BigInt result;
752
- for (size_t i = 0 ; i < WORD_COUNT; ++i)
753
- result.val [i] = val[i] & other.val [i];
754
- return result;
753
+ #define DEFINE_BINOP (OP ) \
754
+ LIBC_INLINE friend constexpr BigInt operator OP (const BigInt &lhs, \
755
+ const BigInt &rhs) { \
756
+ BigInt result; \
757
+ for (size_t i = 0 ; i < WORD_COUNT; ++i) \
758
+ result[i] = lhs[i] OP rhs[i]; \
759
+ return result; \
760
+ } \
761
+ LIBC_INLINE friend constexpr BigInt operator OP##=(BigInt &lhs, \
762
+ const BigInt &rhs) { \
763
+ for (size_t i = 0 ; i < WORD_COUNT; ++i) \
764
+ lhs[i] OP## = rhs[i]; \
765
+ return lhs; \
755
766
}
756
767
757
- LIBC_INLINE constexpr BigInt &operator &=(const BigInt &other) {
758
- for (size_t i = 0 ; i < WORD_COUNT; ++i)
759
- val[i] &= other.val [i];
760
- return *this ;
761
- }
768
+ DEFINE_BINOP (&)
769
+ DEFINE_BINOP (|)
770
+ DEFINE_BINOP (^)
762
771
763
- LIBC_INLINE constexpr BigInt operator |(const BigInt &other) const {
764
- BigInt result;
765
- for (size_t i = 0 ; i < WORD_COUNT; ++i)
766
- result.val [i] = val[i] | other.val [i];
767
- return result;
768
- }
769
-
770
- LIBC_INLINE constexpr BigInt &operator |=(const BigInt &other) {
771
- for (size_t i = 0 ; i < WORD_COUNT; ++i)
772
- val[i] |= other.val [i];
773
- return *this ;
774
- }
775
-
776
- LIBC_INLINE constexpr BigInt operator ^(const BigInt &other) const {
777
- BigInt result;
778
- for (size_t i = 0 ; i < WORD_COUNT; ++i)
779
- result.val [i] = val[i] ^ other.val [i];
780
- return result;
781
- }
782
-
783
- LIBC_INLINE constexpr BigInt &operator ^=(const BigInt &other) {
784
- for (size_t i = 0 ; i < WORD_COUNT; ++i)
785
- val[i] ^= other.val [i];
786
- return *this ;
787
- }
772
+ #undef DEFINE_BINOP
788
773
789
774
LIBC_INLINE constexpr BigInt operator ~() const {
790
775
BigInt result;
791
776
for (size_t i = 0 ; i < WORD_COUNT; ++i)
792
- result. val [i] = ~val[i];
777
+ result[i] = ~val[i];
793
778
return result;
794
779
}
795
780
@@ -799,139 +784,82 @@ struct BigInt {
799
784
return result;
800
785
}
801
786
802
- LIBC_INLINE constexpr bool operator ==(const BigInt &other) const {
803
- for (size_t i = 0 ; i < WORD_COUNT; ++i) {
804
- if (val[i] != other.val [i])
787
+ LIBC_INLINE friend constexpr bool operator ==(const BigInt &lhs,
788
+ const BigInt &rhs) {
789
+ for (size_t i = 0 ; i < WORD_COUNT; ++i)
790
+ if (lhs.val [i] != rhs.val [i])
805
791
return false ;
806
- }
807
792
return true ;
808
793
}
809
794
810
- LIBC_INLINE constexpr bool operator !=(const BigInt &other) const {
811
- for (size_t i = 0 ; i < WORD_COUNT; ++i) {
812
- if (val[i] != other.val [i])
813
- return true ;
814
- }
815
- return false ;
795
+ LIBC_INLINE friend constexpr bool operator !=(const BigInt &lhs,
796
+ const BigInt &rhs) {
797
+ return !(lhs == rhs);
816
798
}
817
799
818
- LIBC_INLINE constexpr bool operator >(const BigInt &other) const {
800
+ private:
801
+ LIBC_INLINE friend constexpr int cmp (const BigInt &lhs, const BigInt &rhs) {
802
+ const auto compare = [](WordType a, WordType b) {
803
+ return a == b ? 0 : a > b ? 1 : -1 ;
804
+ };
819
805
if constexpr (Signed) {
820
- // Check for different signs;
821
- bool a_sign = val[WORD_COUNT - 1 ] >> (WORD_SIZE - 1 );
822
- bool b_sign = other.val [WORD_COUNT - 1 ] >> (WORD_SIZE - 1 );
823
- if (a_sign != b_sign) {
824
- return b_sign;
825
- }
826
- }
827
- for (size_t i = WORD_COUNT; i > 0 ; --i) {
828
- WordType word = val[i - 1 ];
829
- WordType other_word = other.val [i - 1 ];
830
- if (word > other_word)
831
- return true ;
832
- else if (word < other_word)
833
- return false ;
806
+ const bool lhs_is_neg = lhs.is_neg ();
807
+ const bool rhs_is_neg = rhs.is_neg ();
808
+ if (lhs_is_neg != rhs_is_neg)
809
+ return rhs_is_neg ? 1 : -1 ;
834
810
}
835
- // Equal
836
- return false ;
811
+ for (size_t i = WORD_COUNT; i-- > 0 ;)
812
+ if (auto cmp = compare (lhs[i], rhs[i]); cmp != 0 )
813
+ return cmp;
814
+ return 0 ;
837
815
}
838
816
839
- LIBC_INLINE constexpr bool operator >=(const BigInt &other) const {
840
- if constexpr (Signed) {
841
- // Check for different signs;
842
- bool a_sign = val[WORD_COUNT - 1 ] >> (WORD_SIZE - 1 );
843
- bool b_sign = other.val [WORD_COUNT - 1 ] >> (WORD_SIZE - 1 );
844
- if (a_sign != b_sign) {
845
- return b_sign;
846
- }
847
- }
848
- for (size_t i = WORD_COUNT; i > 0 ; --i) {
849
- WordType word = val[i - 1 ];
850
- WordType other_word = other.val [i - 1 ];
851
- if (word > other_word)
852
- return true ;
853
- else if (word < other_word)
854
- return false ;
855
- }
856
- // Equal
857
- return true ;
817
+ public:
818
+ LIBC_INLINE friend constexpr bool operator >(const BigInt &lhs,
819
+ const BigInt &rhs) {
820
+ return cmp (lhs, rhs) > 0 ;
858
821
}
859
-
860
- LIBC_INLINE constexpr bool operator <(const BigInt &other) const {
861
- if constexpr (Signed) {
862
- // Check for different signs;
863
- bool a_sign = val[WORD_COUNT - 1 ] >> (WORD_SIZE - 1 );
864
- bool b_sign = other.val [WORD_COUNT - 1 ] >> (WORD_SIZE - 1 );
865
- if (a_sign != b_sign) {
866
- return a_sign;
867
- }
868
- }
869
-
870
- for (size_t i = WORD_COUNT; i > 0 ; --i) {
871
- WordType word = val[i - 1 ];
872
- WordType other_word = other.val [i - 1 ];
873
- if (word > other_word)
874
- return false ;
875
- else if (word < other_word)
876
- return true ;
877
- }
878
- // Equal
879
- return false ;
822
+ LIBC_INLINE friend constexpr bool operator >=(const BigInt &lhs,
823
+ const BigInt &rhs) {
824
+ return cmp (lhs, rhs) >= 0 ;
880
825
}
881
-
882
- LIBC_INLINE constexpr bool operator <=(const BigInt &other) const {
883
- if constexpr (Signed) {
884
- // Check for different signs;
885
- bool a_sign = val[WORD_COUNT - 1 ] >> (WORD_SIZE - 1 );
886
- bool b_sign = other.val [WORD_COUNT - 1 ] >> (WORD_SIZE - 1 );
887
- if (a_sign != b_sign) {
888
- return a_sign;
889
- }
890
- }
891
- for (size_t i = WORD_COUNT; i > 0 ; --i) {
892
- WordType word = val[i - 1 ];
893
- WordType other_word = other.val [i - 1 ];
894
- if (word > other_word)
895
- return false ;
896
- else if (word < other_word)
897
- return true ;
898
- }
899
- // Equal
900
- return true ;
826
+ LIBC_INLINE friend constexpr bool operator <(const BigInt &lhs,
827
+ const BigInt &rhs) {
828
+ return cmp (lhs, rhs) < 0 ;
829
+ }
830
+ LIBC_INLINE friend constexpr bool operator <=(const BigInt &lhs,
831
+ const BigInt &rhs) {
832
+ return cmp (lhs, rhs) <= 0 ;
901
833
}
902
834
903
835
LIBC_INLINE constexpr BigInt &operator ++() {
904
- BigInt one (1 );
905
- add (one);
836
+ add (BigInt (1 ));
906
837
return *this ;
907
838
}
908
839
909
840
LIBC_INLINE constexpr BigInt operator ++(int ) {
910
841
BigInt oldval (*this );
911
- BigInt one (1 );
912
- add (one);
842
+ add (BigInt (1 ));
913
843
return oldval;
914
844
}
915
845
916
846
LIBC_INLINE constexpr BigInt &operator --() {
917
- BigInt one (1 );
918
- sub (one);
847
+ sub (BigInt (1 ));
919
848
return *this ;
920
849
}
921
850
922
851
LIBC_INLINE constexpr BigInt operator --(int ) {
923
852
BigInt oldval (*this );
924
- BigInt one (1 );
925
- sub (one);
853
+ sub (BigInt (1 ));
926
854
return oldval;
927
855
}
928
856
929
- // Return the i-th 64-bit word of the number.
857
+ // Return the i-th word of the number.
930
858
LIBC_INLINE constexpr const WordType &operator [](size_t i) const {
931
859
return val[i];
932
860
}
933
861
934
- // Return the i-th 64-bit word of the number.
862
+ // Return the i-th word of the number.
935
863
LIBC_INLINE constexpr WordType &operator [](size_t i) { return val[i]; }
936
864
937
865
LIBC_INLINE WordType *data () { return val; }
0 commit comments