LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
bigint_number_theory.cpp
浏览该文件的文档.
1#include "bigint.hpp"
3
4namespace LMCAS {
5namespace {
6
7BigInt binary_modular_power(const BigInt& base, const BigInt& exp, const BigInt& mod) {
8 BigInt result = 1;
9 BigInt residue = base % mod;
10 if (residue.is_negative()) {
11 residue += mod;
12 }
13 BigInt exponent = exp;
14 while (!exponent.is_zero()) {
15 if (exponent.is_odd()) {
16 result = (result * residue) % mod;
17 }
18 residue = (residue * residue) % mod;
19 exponent >>= 1;
20 }
21 return result;
22}
23
24}
25
26BigInt BigInt::multinomial(unsigned int n, const std::vector<unsigned int>& r) {
28 if (r.empty()) return BigInt(1);
29
30 std::vector<uint> r_uints;
31 r_uints.reserve(r.size());
32 ulong sum = 0;
33 for(auto val : r) {
34 r_uints.push_back((uint)val);
35 sum += val;
36 }
37 if (sum != n) throw std::invalid_argument("multinomial: sum of ranks must equal n");
38
39 BigInt res;
40
41 ulong n_calc = 0;
42 mp_size_t needed = lmmp_multinomial_size_(r_uints.data(), (uint)r_uints.size(), &n_calc);
43
44 res.realloc_to(needed);
45 res.size_ = lmmp_multinomial_(res.data_, needed, (uint)sum, r_uints.data(), (uint)r_uints.size());
46 res.sign_ = POSITIVE;
47 res.normalize();
48 return res;
49 }
50
51BigInt BigInt::gcd(const BigInt& a, const BigInt& b) {
53 if (a.is_zero()) return b.abs();
54 if (b.is_zero()) return a.abs();
55
56 BigInt abs_a = a.abs();
57 BigInt abs_b = b.abs();
58
59 BigInt res;
60 mp_size_t na = abs_a.size_;
61 mp_size_t nb = abs_b.size_;
62
63 mp_size_t min_n = (na < nb) ? na : nb;
64 res.realloc_to(min_n);
65
66 res.size_ = lmmp_gcd_lehmer_(res.data_, abs_a.data_, na, abs_b.data_, nb);
67
68 res.sign_ = POSITIVE;
69 res.normalize();
70 return res;
71 }
72
73BigInt BigInt::lcm(const BigInt& a, const BigInt& b) {
74 if (a.is_zero() || b.is_zero()) return BigInt(0);
75 return (a.abs() / gcd(a, b)) * b.abs();
76 }
77
78BigInt BigInt::pow_mod(const BigInt& base, const BigInt& exp, const BigInt& mod) {
80 if (exp.is_negative()) {
81 throw std::domain_error(
82 "Negative exponent in modular integer power");
83 }
84 if (mod.is_zero() || mod.is_negative()) {
85 throw std::domain_error(
86 "Modulus must be positive in modular integer power");
87 }
88 if (mod == BigInt(1)) return BigInt(0);
89
90 if (base.size_ <= 1 && exp.size_ <= 1 && mod.size_ <= 1) {
91 const ulong modulus = mod.data_[0];
92 ulong residue = base.is_zero() ? 0 : base.data_[0] % modulus;
93 const ulong exponent = exp.is_zero() ? 0 : exp.data_[0];
94 if (base.is_negative() && residue != 0) {
95 residue = modulus - residue;
96 }
97 if ((modulus & 1U) != 0) {
98 return BigInt(
99 lmmp_powmod_ulong_odd_(residue, exponent, modulus));
100 }
101 }
102
103 return binary_modular_power(base, exp, mod);
104 }
105
106Result<bool> BigInt::is_prime_checked() const {
108 if (sign_ == NEGATIVE) return false;
109
110 if (size_ <= 1) {
111 return lmmp_is_prime_ulong_(size_ == 0 ? 0 : data_[0]);
112 }
113 if (is_even()) return false;
114
115 static const uint64_t small_primes[] = {3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
116 for (auto p : small_primes) {
117 if ((*this % p).is_zero()) return false;
118 }
119
120 const BigInt& n = *this;
121 const BigInt n_minus_one = n - 1;
122 BigInt d = n_minus_one;
123 BigInt two(2);
124 int s = 0;
125 while (d.is_even()) {
126 d = d / two;
127 s++;
128 }
129
130 static const uint64_t mr_bases[] = {2, 3, 5, 7, 11, 13, 17};
131 for (auto base : mr_bases) {
132 BigInt x = BigInt::pow_mod(BigInt(base), d, n);
133 if (x == 1 || x == n_minus_one) continue;
134
135 bool composite = true;
136 for (int r = 1; r < s; ++r) {
137 x = BigInt::pow_mod(x, two, n);
138 if (x == n_minus_one) {
139 composite = false;
140 break;
141 }
142 }
143 if (composite) return false;
144 }
146 CasErrc::Inconclusive, "primality is unproved beyond the LMMP word range",
147 "BigInt::is_prime_checked");
148 }
149
150bool BigInt::is_perfect_square() const {
151 if (sign_ == NEGATIVE) return false;
152 if (size_ == 0) return true;
153 BigInt s = this->sqrt();
154 return (s * s) == *this;
155 }
156
157}
任意精度整数 BigInt,底层调用 LMMP 实现高性能大数运算。
static Result failure(CasErrc code, std::string message, std::string operation={})
BigInt binary_modular_power(const BigInt &base, const BigInt &exp, const BigInt &mod)
bool is_zero(const SymbolicExpr &expression)
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
const ExprPtr & exponent
__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
ExprResult sqrt(const ExprPtr &expression, ComputationContext &context)