LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
bigint_arithmetic.cpp
浏览该文件的文档.
1#include "bigint.hpp"
3
4namespace LMCAS {
5namespace {
6void bigint_mul(mp_ptr destination, mp_srcptr lhs, mp_size_t lhs_size,
7 mp_srcptr rhs, mp_size_t rhs_size) {
9 ::lmmp_mul_(destination, lhs, lhs_size, rhs, rhs_size);
10}
11void bigint_div(mp_ptr quotient, mp_ptr remainder, mp_srcptr numerator,
12 mp_size_t numerator_size, mp_srcptr denominator,
13 mp_size_t denominator_size) {
15 ::lmmp_div_(quotient, remainder, numerator, numerator_size, denominator,
16 denominator_size);
17}
18}
19
20void BigInt::add_abs(BigInt& dst, const BigInt& a, const BigInt& b) {
21 mp_size_t n = std::max(a.size_, b.size_);
22 dst.realloc_to(n + 1);
23
24 mp_limb_t cy = 0;
25
26 mp_srcptr ap = a.data_;
27 mp_srcptr bp = b.data_;
28 mp_size_t na = a.size_;
29 mp_size_t nb = b.size_;
30
31 if (na < nb) { std::swap(ap, bp); std::swap(na, nb); }
32
33 if (nb > 0) {
34 cy = lmmp_add_n_(dst.data_, ap, bp, nb);
35 }
36
37 if (na > nb) {
38 if (dst.data_ != ap) std::memcpy(dst.data_ + nb, ap + nb, (na - nb) * sizeof(mp_limb_t));
39
40 mp_size_t k = nb;
41 while (cy && k < na) {
42 dst.data_[k]++;
43 cy = (dst.data_[k] == 0);
44 k++;
45 }
46 }
47 dst.data_[na] = cy;
48 dst.size_ = na + cy;
49 dst.normalize();
50 }
51
52void BigInt::sub_abs(BigInt& dst, const BigInt& a, const BigInt& b) {
53 mp_size_t na = a.size_;
54 mp_size_t nb = b.size_;
55 dst.realloc_to(na);
56
57 mp_limb_t bw = 0;
58 if (nb > 0)
59 bw = lmmp_sub_n_(dst.data_, a.data_, b.data_, nb);
60
61 if (na > nb) {
62 if (dst.data_ != a.data_) std::memcpy(dst.data_ + nb, a.data_ + nb, (na - nb) * sizeof(mp_limb_t));
63 mp_size_t k = nb;
64 while (bw && k < na) {
65 dst.data_[k]--;
66 bw = (dst.data_[k] == (mp_limb_t)-1);
67 k++;
68 }
69 }
70 dst.size_ = na;
71 dst.normalize();
72 }
73
74BigInt BigInt::operator+(const BigInt& other) const {
75 if (sign_ == ZERO) return other;
76 if (other.sign_ == ZERO) return *this;
77
78 BigInt res;
79 if (sign_ == other.sign_) {
80 add_abs(res, *this, other);
81 res.sign_ = sign_;
82 } else {
83
84 int cmp = cmp_abs(*this, other);
85 if (cmp == 0) {
86 return BigInt(0);
87 }
88 if (cmp > 0) {
89 sub_abs(res, *this, other);
90 res.sign_ = sign_;
91 } else {
92 sub_abs(res, other, *this);
93 res.sign_ = other.sign_;
94 }
95 }
96 return res;
97 }
98
99BigInt BigInt::operator-(const BigInt& other) const {
100 return *this + (-other);
101 }
102
103BigInt BigInt::operator*(const BigInt& other) const {
104 if (size_ == 0 || other.size_ == 0) return BigInt(0);
105
106 BigInt res;
107 mp_size_t na = size_;
108 mp_size_t nb = other.size_;
109 res.realloc_to(na + nb);
110
111 if (na >= nb) {
112 bigint_mul(res.data_, data_, na, other.data_, nb);
113 } else {
114 bigint_mul(res.data_, other.data_, nb, data_, na);
115 }
116
117 res.size_ = na + nb;
118 res.sign_ = (sign_ == other.sign_) ? POSITIVE : NEGATIVE;
119 res.normalize();
120 return res;
121 }
122
123BigInt BigInt::operator/(const BigInt& other) const {
124 if (other.size_ == 0) throw std::domain_error("Division by zero");
125 if (size_ < other.size_) return BigInt(0);
126
127 BigInt q, r;
128 mp_size_t na = size_;
129 mp_size_t nb = other.size_;
130
131 q.realloc_to(na - nb + 1);
132 r.realloc_to(nb);
133
134 bigint_div(q.data_, r.data_, data_, na, other.data_, nb);
135
136 q.size_ = na - nb + 1;
137 q.sign_ = (sign_ == other.sign_) ? POSITIVE : NEGATIVE;
138 q.normalize();
139 return q;
140 }
141
142BigInt BigInt::operator%(const BigInt& other) const {
143 if (other.size_ == 0) throw std::domain_error("Division by zero");
144 if (size_ < other.size_) return *this;
145
146 BigInt q;
147 mp_size_t na = size_;
148 mp_size_t nb = other.size_;
149 q.realloc_to(na - nb + 1);
150
151 BigInt r;
152 r.realloc_to(nb);
153
154 bigint_div(q.data_, r.data_, data_, na, other.data_, nb);
155
156 r.size_ = nb;
157 r.sign_ = sign_;
158 r.normalize();
159 return r;
160 }
161
162BigInt& BigInt::operator+=(const BigInt& other) { *this = *this + other; return *this; }
163
164BigInt& BigInt::operator-=(const BigInt& other) { *this = *this - other; return *this; }
165
166BigInt& BigInt::operator*=(const BigInt& other) { *this = *this * other; return *this; }
167
168BigInt& BigInt::operator/=(const BigInt& other) { *this = *this / other; return *this; }
169
170BigInt& BigInt::operator%=(const BigInt& other) { *this = *this % other; return *this; }
171
172BigInt BigInt::power(unsigned long exp) const {
174 if (exp == 0) return BigInt(1);
175 if (size_ == 0) return BigInt(0);
176
177 BigInt res;
178 mp_size_t needed = lmmp_pow_size_(data_, size_, exp);
179 res.realloc_to(needed);
180
181 res.size_ = lmmp_pow_(res.data_, needed, data_, size_, exp);
182
183 if (sign_ == NEGATIVE && (exp & 1)) {
184 res.sign_ = NEGATIVE;
185 } else {
186 res.sign_ = POSITIVE;
187 }
188 res.normalize();
189 return res;
190 }
191
192BigInt BigInt::power(BigInt exp) const {
193 if (exp.sign_ == NEGATIVE) throw std::domain_error("Negative exponent in integer power");
194 if (exp.size_ == 0) return BigInt(1);
195
196 if (exp.size_ <= 1) {
197 mp_limb_t lo = (exp.size_ == 0) ? 0 : exp.data_[0];
198 if (lo <= static_cast<mp_limb_t>(std::numeric_limits<unsigned long>::max())) {
199 return power(static_cast<unsigned long>(lo));
200 }
201 }
202
203 BigInt base = *this;
204 BigInt res(1);
205
206 while (!exp.is_zero()) {
207 if (exp.data_[0] & 1) {
208 res = res * base;
209 }
210 base = base * base;
211
212 mp_limb_t carry = 0;
213 for (mp_size_t i = exp.size_; i > 0; --i) {
214 mp_limb_t cur = exp.data_[i-1];
215 mp_limb_t next_carry = cur & 1;
216 exp.data_[i-1] = (cur >> 1) | (carry << (LIMB_BITS - 1));
217 carry = next_carry;
218 }
219 exp.normalize();
220 }
221 return res;
222 }
223
224BigInt BigInt::sqrt() const {
226 if (sign_ == NEGATIVE) throw std::domain_error("Sqrt of negative number");
227 if (size_ == 0) return BigInt(0);
228 if (*this == BigInt(1)) return BigInt(1);
229
230 BigInt res;
231
232 const mp_size_t root_size = (size_ + 1) / 2;
233 res.realloc_to(root_size + 1);
234
235 lmmp_sqrt_(res.data_, nullptr, data_, size_, 0);
236
237 res.size_ = root_size;
238 res.sign_ = POSITIVE;
239 res.normalize();
240
241 return res;
242 }
243
244bool BigInt::is_odd() const {
245 if (size_ == 0) return false;
246 return (data_[0] & 1);
247 }
248
249bool BigInt::is_even() const {
250 return !is_odd();
251 }
252
253mp_size_t BigInt::trailing_zeros() const {
255 if (is_zero()) return 0;
256 mp_size_t count = 0;
257 for (mp_size_t i = 0; i < size_; ++i) {
258 if (data_[i] == 0) {
259 count += LIMB_BITS;
260 } else {
261 count += lmmp_tailing_zeros_(data_[i]);
262 break;
263 }
264 }
265 return count;
266 }
267
268BigInt& BigInt::operator>>=(mp_size_t shift) {
270 if (shift == 0) return *this;
271 if (is_zero()) return *this;
272
273 mp_size_t limb_shift = shift / LIMB_BITS;
274 mp_size_t bit_shift = shift % LIMB_BITS;
275
276 if (limb_shift >= size_) {
277 zero();
278 return *this;
279 }
280
281 if (limb_shift > 0) {
282 std::memmove(data_, data_ + limb_shift, (size_ - limb_shift) * sizeof(mp_limb_t));
283 size_ -= limb_shift;
284 }
285
286 if (bit_shift > 0) {
287 lmmp_shr_(data_, data_, size_, bit_shift);
288 if (size_ > 0 && data_[size_-1] == 0) size_--;
289 }
290 normalize();
291 return *this;
292 }
293
294BigInt& BigInt::operator<<=(mp_size_t shift) {
295 if (shift == 0) return *this;
296 if (is_zero()) return *this;
297
298 mp_size_t limb_shift = shift / LIMB_BITS;
299 mp_size_t bit_shift = shift % LIMB_BITS;
300
301 mp_size_t old_size = size_;
302 mp_size_t needed = old_size + limb_shift + (bit_shift > 0 ? 1 : 0);
303 realloc_to(needed);
304
305 if (bit_shift > 0) {
306 mp_limb_t carry = lmmp_shl_(data_ + limb_shift, data_, old_size, bit_shift);
307 if (carry) {
308 data_[old_size + limb_shift] = carry;
309 size_ = old_size + limb_shift + 1;
310 } else {
311 size_ = old_size + limb_shift;
312 }
313 } else {
314 std::memmove(data_ + limb_shift, data_, old_size * sizeof(mp_limb_t));
315 size_ += limb_shift;
316 }
317
318 if (limb_shift > 0) {
319 std::memset(data_, 0, limb_shift * sizeof(mp_limb_t));
320 }
321
322 normalize();
323 return *this;
324 }
325
326BigInt BigInt::operator>>(mp_size_t shift) const {
327 BigInt res = *this;
328 res >>= shift;
329 return res;
330 }
331
332BigInt BigInt::operator<<(mp_size_t shift) const {
333 BigInt res = *this;
334 res <<= shift;
335 return res;
336 }
337
338}
任意精度整数 BigInt,底层调用 LMMP 实现高性能大数运算。
void bigint_div(mp_ptr quotient, mp_ptr remainder, mp_srcptr numerator, mp_size_t numerator_size, mp_srcptr denominator, mp_size_t denominator_size)
void bigint_mul(mp_ptr destination, mp_srcptr lhs, mp_size_t lhs_size, mp_srcptr rhs, mp_size_t rhs_size)
bool is_zero(const SymbolicExpr &expression)
ExpressionResult normalize(const Node &value, ComputationContext &context)
void ensure_lmmc_lifecycle() noexcept
ExprResult exp(const ExprPtr &expression, ComputationContext &context)
__attribute__((visibility("default"))) ComplexSymbolicResult complex_exp_form_checked(std __attribute__((visibility("default"))) ComplexSymbolicResult complex_exp_form_checked(std __attribute__((visibility("default"))) ComplexSymbolicResult complex_trig_form_checked(std __attribute__((visibility("default"))) ComplexSymbolicResult complex_trig_form_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_nth_root_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_nth_root_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_quadratic_checked(std __attribute__((visibility("default"))) ComplexRootsResult solve_complex_quadratic_checked(std std::shared_ptr< SymbolicExpr > r
const MultiPoly & b
__attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::shared_ptr< SymbolicExpr > & a
const ExprPtr & rhs
const ExprPtr & denominator