LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
bigint.hpp
浏览该文件的文档.
1/**
2 * @file bigint.hpp
3 * @brief 任意精度整数 BigInt,底层调用 LMMP 实现高性能大数运算。
4 */
5#pragma once
6
7
8#include <lmmp.h>
9#include <lmmpn.h>
10#include <numth.h>
11#include "lmmc/init.h"
12#include <vector>
13#include <cstdlib>
14#include <cstdint>
15#include <cstring>
16#include <string>
17#include <iostream>
18#include <algorithm>
19#include <iomanip>
20#include <stdexcept>
21#include <limits>
22#include <optional>
23#include <type_traits>
24#include "result.hpp"
25#include "lmmc/config.h"
26#include "lmcas_export.hpp"
27
28namespace LMCAS {
29
31
32class LMCAS_API BigInt {
33public:
34 /** @brief 符号枚举 */
35 enum Sign {
36 POSITIVE = 1,
37 ZERO = 0,
38 NEGATIVE = -1
39 };
40
41private:
42 mp_ptr data_ = nullptr;
43 mp_size_t size_ = 0;
44 mp_size_t capacity_ = 0;
45 int sign_ = ZERO;
46
47 void realloc_to(mp_size_t new_alloc);
48
49 void normalize();
50
51 void zero();
52
53 void import_unsigned(std::uint64_t magnitude);
54 std::optional<std::uint64_t> magnitude_uint64() const noexcept;
55
56public:
57 /** @brief 默认构造,值为 0 */
58 BigInt();
59
60 ~BigInt();
61
62 /** @brief 拷贝构造 */
63 BigInt(const BigInt& other);
64
65 /** @brief 移动构造 */
66 BigInt(BigInt&& other) noexcept;
67
68 /** @brief 拷贝赋值 */
69 BigInt& operator=(const BigInt& other);
70
71 /** @brief 移动赋值 */
72 BigInt& operator=(BigInt&& other) noexcept;
73
74 /** @brief 精确导入有符号机器整数,包括其最小值。 */
75 BigInt(std::int64_t value);
76 /** @brief 精确导入无符号机器整数,保留各数位的完整宽度。 */
77 BigInt(std::uint64_t value);
78 BigInt(int value);
79 BigInt(unsigned int value);
80
81 template <typename Integer,
82 std::enable_if_t<std::is_integral_v<Integer> &&
83 sizeof(Integer) <= sizeof(std::uint64_t) &&
84 !std::is_same_v<Integer, int> &&
85 !std::is_same_v<Integer, unsigned int> &&
86 !std::is_same_v<Integer, std::int64_t> &&
87 !std::is_same_v<Integer, std::uint64_t>, int> = 0>
88 BigInt(Integer value)
89 : BigInt(static_cast<std::conditional_t<std::is_signed_v<Integer>,
90 std::int64_t, std::uint64_t>>(value)) {}
91
92 /**
93 * @brief 从十进制字符串构造
94 * @param str 十进制数字字符串,可带正负号
95 * @throws std::invalid_argument 若字符串为空、仅含符号或包含非十进制字符
96 */
97 BigInt(const std::string& str);
98
99 /**
100 * @brief 转换为十进制字符串
101 * @return 十进制表示的字符串
102 */
103 std::string to_string() const;
104
105 /**
106 * @brief 转换为 int(溢出时饱和到 int 范围)
107 * @return 对应的 int 值
108 */
109 int to_int() const;
110
111 /** @brief 精确转换为 int64_t;超出范围时返回空。 */
112 std::optional<std::int64_t> try_to_int64() const noexcept;
113
114 /** @brief 精确转换非负值,负值或超出范围时失败。 */
115 std::optional<std::uint64_t> try_to_uint64() const noexcept;
116 /** @brief 返回绝对值的二进制位数,零的位数为 0。 */
117 std::size_t bit_length() const noexcept;
118
119 /**
120 * @brief 转换为浮点数
121 * @return 对应的 double 值
122 */
123 lmmc_real_t to_double() const;
124
125 /**
126 * @brief 比较两个 BigInt 的绝对值
127 * @param a 第一个操作数
128 * @param b 第二个操作数
129 * @return 1 表示 |a|>|b|,-1 表示 |a|<|b|,0 表示相等
130 */
131 static int cmp_abs(const BigInt& a, const BigInt& b);
132
133 bool operator==(const BigInt& other) const;
134 bool operator!=(const BigInt& other) const;
135 bool operator<(const BigInt& other) const;
136 bool operator>(const BigInt& other) const;
137 bool operator<=(const BigInt& other) const;
138 bool operator>=(const BigInt& other) const;
139 bool operator!() const;
140 explicit operator bool() const;
141
142 /** @brief 判断是否为零 */
143 bool is_zero() const;
144
145 /**
146 * @brief 获取 limb 数组的副本
147 * @return 各 limb 值组成的 vector
148 */
149 std::vector<uint64_t> get_digits() const;
150
151 /**
152 * @brief 计算哈希值
153 * @return 哈希值
154 */
155 std::size_t hash() const;
156
157 /**
158 * @brief 取绝对值
159 * @return |*this|
160 */
161 BigInt abs() const;
162
163 /** @brief 判断是否为负数 */
164 bool is_negative() const;
165
166 /**
167 * @brief 取相反数
168 * @return -*this
169 */
170 BigInt negate() const;
171
172 /** @brief 一元负号运算符 */
173 BigInt operator-() const;
174
175 /**
176 * @brief 绝对值加法(内部使用)
177 * @param dst 结果
178 * @param a 加数
179 * @param b 加数
180 */
181 static void add_abs(BigInt& dst, const BigInt& a, const BigInt& b);
182
183 /**
184 * @brief 绝对值减法(内部使用,要求 |a| >= |b|)
185 * @param dst 结果
186 * @param a 被减数
187 * @param b 减数
188 */
189 static void sub_abs(BigInt& dst, const BigInt& a, const BigInt& b);
190
191 /** @brief 加法运算符 */
192 BigInt operator+(const BigInt& other) const;
193
194 /** @brief 减法运算符 */
195 BigInt operator-(const BigInt& other) const;
196
197 /** @brief 乘法运算符 */
198 BigInt operator*(const BigInt& other) const;
199
200 /**
201 * @brief 除法运算符(整数除法,截断)
202 * @param other 除数
203 * @return 商
204 * @throw std::domain_error 除数为零时抛出
205 */
206 BigInt operator/(const BigInt& other) const;
207
208 /**
209 * @brief 取模运算符
210 * @param other 模数
211 * @return 余数
212 * @throw std::domain_error 模数为零时抛出
213 */
214 BigInt operator%(const BigInt& other) const;
215
216 BigInt& operator+=(const BigInt& other);
217 BigInt& operator-=(const BigInt& other);
218 BigInt& operator*=(const BigInt& other);
219 BigInt& operator/=(const BigInt& other);
220 BigInt& operator%=(const BigInt& other);
221
222 /**
223 * @brief 整数幂运算
224 * @param exp 非负指数
225 * @return this^exp
226 */
227 BigInt power(unsigned long exp) const;
228
229 /**
230 * @brief 整数幂运算(BigInt 指数)
231 * @param exp 非负 BigInt 指数
232 * @return this^exp
233 * @throw std::domain_error 指数为负时抛出
234 */
235 BigInt power(BigInt exp) const;
236
237 /**
238 * @brief 整数平方根(向下取整)
239 * @return floor(sqrt(*this))
240 * @throw std::domain_error 负数时抛出
241 */
242 BigInt sqrt() const;
243
244 /** @brief 判断是否为奇数 */
245 bool is_odd() const;
246
247 /** @brief 判断是否为偶数 */
248 bool is_even() const;
249
250 /**
251 * @brief 计算末尾零比特数
252 * @return 二进制表示中末尾连续 0 的个数
253 */
254 mp_size_t trailing_zeros() const;
255
256 /**
257 * @brief 右移赋值
258 * @param shift 移位比特数
259 * @return *this
260 */
261 BigInt& operator>>=(mp_size_t shift);
262
263 /**
264 * @brief 左移赋值
265 * @param shift 移位比特数
266 * @return *this
267 */
268 BigInt& operator<<=(mp_size_t shift);
269
270 /** @brief 右移运算符 */
271 BigInt operator>>(mp_size_t shift) const;
272
273 /** @brief 左移运算符 */
274 BigInt operator<<(mp_size_t shift) const;
275
276 /**
277 * @brief 计算阶乘
278 * @param n 非负整数
279 * @return n!
280 */
281 static BigInt factorial(const BigInt& n);
282 static Result<BigInt> factorial_checked(const BigInt& n, ComputationContext& context);
283 static Result<BigInt> factorial_checked(const BigInt& n);
284
285 /**
286 * @brief 计算排列数 P(n, r)
287 * @param n 总数
288 * @param r 选取数
289 * @return n! / (n-r)!
290 */
291 static BigInt npr(const BigInt& n, const BigInt& r);
292 static Result<BigInt> npr_checked(const BigInt& n, const BigInt& r,
293 ComputationContext& context);
294 static Result<BigInt> npr_checked(const BigInt& n, const BigInt& r);
295
296 /**
297 * @brief 计算组合数 C(n, r)
298 * @param n 总数
299 * @param r 选取数
300 * @return n! / (r! * (n-r)!)
301 */
302 static BigInt ncr(const BigInt& n, const BigInt& r);
303 static Result<BigInt> ncr_checked(const BigInt& n, const BigInt& r,
304 ComputationContext& context);
305 static Result<BigInt> ncr_checked(const BigInt& n, const BigInt& r);
306
307 /**
308 * @brief 计算多项式系数(多重组合数)
309 * @param n 总数(应等于 r 各元素之和)
310 * @param r 各组大小
311 * @return n! / (r[0]! * r[1]! * ... * r[k]!)
312 * @throw std::invalid_argument r 之和不等于 n 时抛出
313 */
314 static BigInt multinomial(unsigned int n, const std::vector<unsigned int>& r);
315
316 /**
317 * @brief 计算最大公约数
318 * @param a 第一个大整数
319 * @param b 第二个大整数
320 * @return gcd(|a|, |b|)
321 */
322 static BigInt gcd(const BigInt& a, const BigInt& b);
323
324 /**
325 * @brief 计算最小公倍数
326 * @param a 第一个大整数
327 * @param b 第二个大整数
328 * @return lcm(|a|, |b|)
329 */
330 static BigInt lcm(const BigInt& a, const BigInt& b);
331
332 /**
333 * @brief Compute the canonical residue @c base^exp mod mod.
334 * @param base Signed integer base.
335 * @param exp Nonnegative integer exponent.
336 * @param mod Strictly positive modulus.
337 * @return A value in the half-open interval @c [0,mod).
338 * @throw std::domain_error If @p exp is negative or @p mod is not positive.
339 */
340 static BigInt pow_mod(const BigInt& base, const BigInt& exp, const BigInt& mod);
341
342 /**
343 * @brief 判断整数的素性并保留无法证明的结论。
344 * 单个机器字使用确定性判定;较大整数发现合数证据时返回 false,
345 * 尚无法证明素性时返回 CasErrc::Inconclusive。
346 */
347 Result<bool> is_prime_checked() const;
348
349 /**
350 * @brief 判断是否为完全平方数
351 * @return 是完全平方数返回 true
352 */
353 bool is_perfect_square() const;
354};
355
356} // namespace LMCAS
#define LMCAS_API
ExpressionResult normalize(const Node &value, ComputationContext &context)
Sign
Sign classification for symbols and expressions.