Skip to content

Commit 136e23e

Browse files
Add files via upload
1 parent ab6b764 commit 136e23e

File tree

11 files changed

+2046
-964
lines changed

11 files changed

+2046
-964
lines changed

basics.hpp

Lines changed: 590 additions & 363 deletions
Large diffs are not rendered by default.

big.hpp

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
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

Comments
 (0)