1
+ #pragma once
2
+ #include " basics.hpp"
3
+ #ifndef _BIG_HPP_
4
+ #define _BIG_HPP_ 0x8000'0000'0000'0000ul
5
+ namespace Mathlab {
6
+ // 1 Big integer type
7
+ class BigInt {
8
+ uintmax_t _size, * _words;
9
+ constexpr BigInt (uintmax_t size, uintmax_t * words) noexcept : _size(size), _words(words) {}
10
+ public:
11
+ static constexpr int WORD_BITS = 8 * sizeof (uintmax_t );
12
+ static constexpr int WORD_BYTES = sizeof (uintmax_t );
13
+ static constexpr uintmax_t WORD_MAX = INTMAX_MAX;
14
+ static constexpr uintmax_t WORD_MIN = INTMAX_MIN;
15
+ constexpr BigInt () noexcept : _words(0 ), _size(0 ) {}
16
+ // Built-in Integer type
17
+ template <Integral<false > _T> _CONSTEXPR20 BigInt (_T t) noexcept : _words(0 ), _size(1 ) {
18
+ if (cmpGreater (t, INTMAX_MAX))
19
+ _words = new uintmax_t [_size = 2 ]{uintmax_t (t), uintmax_t (t) >> WORD_BITS};
20
+ else
21
+ _words = new uintmax_t [1 ](t);
22
+ // Negative integer will become positive when operated with no-shorter unsigned integer
23
+ }
24
+ _CONSTEXPR20 BigInt (const BigInt& t) noexcept : _words(0 ), _size(t.size()) {
25
+ _words = new uintmax_t [_size]{*t._words };
26
+ for (uintmax_t i = 1 ; i < _size; ++i) _words[i] = t._words [i];
27
+ }
28
+ _CONSTEXPR20 ~BigInt () noexcept {
29
+ if (_words) delete[] _words;
30
+ }
31
+ _CONSTEXPR20 BigInt& operator =(const BigInt& t) noexcept {
32
+ if (_words) delete[] _words;
33
+ _words = new uintmax_t [_size = t.size ()]{*t._words };
34
+ for (uintmax_t i = 0 ; i < _size; ++i) _words[i] = t._words [i];
35
+ return *this ;
36
+ }
37
+ // Non-zero is true
38
+ constexpr operator bool () const noexcept {
39
+ for (uintmax_t i = 0 ; i < _size; ++i) if (_words[i]) return true ;
40
+ return false ;
41
+ }
42
+ // Read word
43
+ constexpr uintmax_t operator [](uintmax_t i) const noexcept {
44
+ if (i < _size) return _words ? _words[i] : 0 ;
45
+ else return _words[_size - 1 ] > WORD_MAX ? -1 : 0 ;
46
+ }
47
+ constexpr uintmax_t size (bool cap = false ) const noexcept {
48
+ if (cap) return _size;
49
+ uintmax_t n = _size;
50
+ while (n > 1 ) {
51
+ uintmax_t * p = _words + n - 2 ;
52
+ if (_words[1 ] == 0 && _words[0 ] <= WORD_MAX
53
+ || _words[1 ] == UINTPTR_MAX && _words[0 ] >= WORD_MIN) --n;
54
+ else break ;
55
+ }
56
+ return n;
57
+ }
58
+ constexpr uint8_t byte (uintmax_t i) const noexcept {
59
+ if (i >= WORD_BYTES * _size) return _words[_size - 1 ] > WORD_MAX ? -1 : 0 ;
60
+ // Sign bit
61
+ else return _words[i / WORD_BYTES] >> i % WORD_BYTES * 8 ;
62
+ }
63
+ constexpr uint16_t doublet (uintmax_t i) noexcept {
64
+ constexpr int n = WORD_BYTES / 2 ;
65
+ if (i >= n * _size) return _words[_size - 1 ] > WORD_MAX ? -1 : 0 ;
66
+ // Sign bit
67
+ else return _words[i / n] >> i % n * 8 ;
68
+ }
69
+ constexpr uint32_t quadruplet (uintmax_t i) noexcept {
70
+ constexpr int n = WORD_BYTES / 4 ;
71
+ if (i >= n * _size) return _words[_size - 1 ] > WORD_MAX ? -1 : 0 ;
72
+ // Sign bit
73
+ else return _words[i / n] >> i % n * 8 ;
74
+ }
75
+ constexpr uint64_t octuplet (uintmax_t i) noexcept {
76
+ constexpr int n = WORD_BYTES / 8 ;
77
+ if (i >= n * _size) return _words[_size - 1 ] > WORD_MAX ? -1 : 0 ;
78
+ // Sign bit
79
+ else return _words[i / n] >> i % n * 8 ;
80
+ }
81
+ template <typename _T> constexpr _T word (uintmax_t i) noexcept {
82
+ constexpr int n = WORD_BYTES / sizeof (_T);
83
+ if (i >= n * _size) return _words[_size - 1 ] > WORD_MAX ? -1 : 0 ;
84
+ // Sign bit
85
+ else return _words[i / n] >> i % n * 8 ;
86
+ }
87
+ // Unary Arithmetic
88
+ constexpr BigInt operator +() const noexcept {
89
+ return *this ;
90
+ }
91
+ constexpr BigInt operator -() const noexcept {
92
+ uintmax_t i = 0 ;
93
+ BigInt t = *this ;
94
+ for (bool flag = 1 ; i < t._size ; flag = flag && !t._words [i++]) {
95
+ t._words [i] = ~t._words [i] + flag;
96
+ if (flag && i == t._size - 1 && t._words [i] == WORD_MIN) {
97
+ uintmax_t * temp = new uintmax_t [++t._size ]{0 };
98
+ temp[_size - 2 ] = WORD_MIN;
99
+ delete[] _words;
100
+ t._words = temp;
101
+ break ;
102
+ }
103
+ }
104
+ return t;
105
+ }
106
+ constexpr BigInt operator ~() const noexcept {
107
+ BigInt t = *this ;
108
+ for (uintmax_t i = 0 ; i < t._size ; ++i) t._words [i] = ~t._words [i];
109
+ return t;
110
+ }
111
+ constexpr BigInt& operator ++() noexcept {
112
+ uintmax_t i = 0 ;
113
+ // increment the next word if this word becomes 0
114
+ for (; i < _size; ++i) if (++_words[i]) break ;
115
+ if (i == _size - 1 && _words[i] == WORD_MIN) {
116
+ // Signed Overflow, resulting in 8000 .... 0000
117
+ uintmax_t * temp = new uintmax_t [++_size]{0 };
118
+ temp[_size - 2 ] = WORD_MIN;
119
+ delete[] _words;
120
+ _words = temp;
121
+ }
122
+ return *this ;
123
+ }
124
+ constexpr BigInt& operator --() noexcept {
125
+ uintmax_t i = 0 ;
126
+ // decrement the next word if this word is 0 and becomes -1
127
+ for (; i < _size; ++i) if (_words[i]--) break ;
128
+ if (i == _size - 1 && _words[i] == WORD_MAX) {
129
+ // Signed Underflow, resulting in 7FFF .... FFFF
130
+ uintmax_t * temp = new uintmax_t [++_size]{0 };
131
+ for (i = 0 ; i < _size; ++i) temp[i] = i == _size - 2 ? WORD_MAX : -1 ;
132
+ }
133
+ return *this ;
134
+ }
135
+ // Shrink to fit
136
+ _CONSTEXPR20 BigInt& shrinkToFit () noexcept {
137
+ uintmax_t * temp = new uintmax_t [_size = this ->size ()];
138
+ for (uintmax_t i = 0 ; i < _size; ++i) temp[i] = _words[i];
139
+ delete[] _words;
140
+ _words = temp;
141
+ return *this ;
142
+ }
143
+ // Comparison with 0
144
+ constexpr bool operator ==(nullptr_t ) const noexcept {
145
+ for (uintmax_t i = 0 ; i < _size; ++i) if (_words[i]) return 0 ;
146
+ return 1 ;
147
+ }
148
+ constexpr bool operator <(nullptr_t ) const noexcept {
149
+ return _words[_size - 1 ] > WORD_MAX;
150
+ }
151
+ constexpr StrongOrder operator <=>(nullptr_t ) const noexcept {
152
+ uintmax_t i = _size - 1 ;
153
+ if (_words[i] > WORD_MAX) return StrongOrder::less;
154
+ while (i--) if (_words[i]) return StrongOrder::greater;
155
+ return StrongOrder::equal;
156
+ }
157
+ // Binary Arithmetic
158
+ friend constexpr BigInt operator +(const BigInt& lhs, const BigInt& rhs) noexcept ;
159
+ friend constexpr BigInt operator -(const BigInt& lhs, const BigInt& rhs) noexcept ;
160
+ friend constexpr BigInt operator *(const BigInt& lhs, const BigInt& rhs) noexcept ;
161
+ friend constexpr BigInt operator /(const BigInt& lhs, const BigInt& rhs) noexcept ;
162
+ friend constexpr BigInt operator %(const BigInt& lhs, const BigInt& rhs) noexcept ;
163
+ friend constexpr BigInt operator &(const BigInt& lhs, const BigInt& rhs) noexcept ;
164
+ friend constexpr BigInt operator |(const BigInt& lhs, const BigInt& rhs) noexcept ;
165
+ friend constexpr BigInt operator ^(const BigInt& lhs, const BigInt& rhs) noexcept ;
166
+ friend constexpr BigInt operator <<(const BigInt& lhs, int rhs) noexcept ;
167
+ friend constexpr BigInt operator >>(const BigInt& lhs, int rhs) noexcept ;
168
+ friend constexpr BigInt operator ==(const BigInt& lhs, const BigInt& rhs) noexcept ;
169
+ friend constexpr BigInt operator <=>(const BigInt& lhs, const BigInt& rhs) noexcept ;
170
+ private:
171
+ BigInt _sext (unsigned int i) {
172
+ _words[_size - 1 ] > WORD_MAX;
173
+ }
174
+ };
175
+ constexpr BigInt operator +(const BigInt& lhs, const BigInt& rhs) noexcept {
176
+ if (lhs == nullptr ) return lhs;
177
+ if (rhs == nullptr ) return rhs;
178
+ uintmax_t n = max (lhs.size (), rhs.size ()),
179
+ * w = new uintmax_t [n + 1 ]{0 };
180
+ bool flag = 0 ;
181
+ for (uintmax_t i = 0 ; i < n; ++i) {
182
+ uintmax_t a = lhs[i], b = rhs[i], c = w[i] = a + b + flag;
183
+ flag = c < a || c < b;
184
+ }
185
+ const int shift = BigInt::WORD_BITS - 1 ,
186
+ l = lhs[n - 1 ] >> shift, r = rhs[n - 1 ] >> shift; // either 0 or 1
187
+ switch (l + r) {
188
+ case 2 : w[n] = -1 ; break ;// lhs<0, rhs<0
189
+ case 0 : w[n] = 0 ; break ;// lhs>=0, rhs>=0
190
+ case 1 : w[n] = w[n - 1 ] >> shift ? -1 : 0 ;
191
+ }
192
+ return BigInt (n, w);
193
+ }
194
+ constexpr BigInt operator -(const BigInt& lhs, const BigInt& rhs) noexcept {
195
+ if (lhs == nullptr ) return lhs;
196
+ uintmax_t n = max (lhs.size (), rhs.size ()),
197
+ * w = new uintmax_t [n + 1 ]{0 };
198
+ bool flag = 0 ;
199
+ for (uintmax_t i = 0 ; i < n; ++i) {
200
+ uintmax_t a = lhs[i], b = rhs[i], c = w[i] = a - b - flag;
201
+ flag = c + flag > a;
202
+ }
203
+ const int shift = BigInt::WORD_BITS - 1 ,
204
+ l = lhs[n - 1 ], r = rhs[n - 1 ]; // either 0 or 1
205
+ if (l == r) w[n] = w[n - 1 ] >> shift ? -1 : 0 ;
206
+ else w[n] = l < r ? -1 : 0 ;
207
+ return BigInt (n, w);
208
+ }
209
+ constexpr BigInt operator *(const BigInt& lhs, const BigInt& rhs) noexcept {
210
+ if (lhs == nullptr || rhs == nullptr ) return 0 ;
211
+ uintmax_t n = lhs.size () + rhs.size (),
212
+ * w = new uintmax_t [n]{0 };
213
+ return BigInt (n, w);
214
+ }
215
+ }
216
+ #endif
0 commit comments