2 #include <boost/multiprecision/miller_rabin.hpp>
3 #include <boost/mpl/int.hpp>
6 #include <symengine/symengine_assert.h>
7 #include <symengine/symengine_exception.h>
8 #include <symengine/prime_sieve.h>
10 using boost::multiprecision::denominator;
11 using boost::multiprecision::miller_rabin_test;
12 using boost::multiprecision::numerator;
13 using boost::multiprecision::detail::find_lsb;
15 #if SYMENGINE_INTEGER_CLASS == SYMENGINE_BOOSTMP
20 integer_class
pow(
const integer_class &a,
unsigned long b)
22 return boost::multiprecision::pow(a, numeric_cast<unsigned>(b));
25 void mp_fdiv_qr(integer_class &q, integer_class &r,
const integer_class &a,
26 const integer_class &b)
45 integer_class a_cpy = a, b_cpy = b;
46 bool neg_quotient = ((a < 0 && b > 0) || (a > 0 && b < 0)) ?
true :
false;
47 boost::multiprecision::divide_qr(a_cpy, b_cpy, q, r);
49 if (neg_quotient && r != 0) {
53 if ((b_cpy > 0 && r < 0) || (b_cpy < 0 && r > 0)) {
59 void mp_cdiv_qr(integer_class &q, integer_class &r,
const integer_class &a,
60 const integer_class &b)
62 integer_class a_cpy = a, b_cpy = b;
63 bool pos_quotient = ((a < 0 && b < 0) || (a > 0 && b > 0)) ?
true :
false;
64 boost::multiprecision::divide_qr(a_cpy, b_cpy, q, r);
66 if (pos_quotient && r != 0) {
70 if ((b_cpy > 0 && r > 0) || (b_cpy < 0 && r < 0)) {
76 void mp_gcdext(integer_class &
gcd, integer_class &s, integer_class &t,
77 const integer_class &a,
const integer_class &b)
80 integer_class this_s(1);
81 integer_class this_t(0);
82 integer_class next_s(0);
83 integer_class next_t(1);
84 integer_class this_r(a);
85 integer_class next_r(b);
92 integer_class this_r_cpy = this_r;
93 boost::multiprecision::divide_qr(this_r_cpy, next_r, q, this_r);
111 bool mp_invert(integer_class &res,
const integer_class &a,
112 const integer_class &m)
114 integer_class
gcd, s, t;
115 mp_gcdext(
gcd, s, t, a, m);
131 integer_class
fmod(
const integer_class &a,
const integer_class &
mod)
133 integer_class res = a %
mod;
140 void mp_pow_ui(rational_class &res,
const rational_class &i,
unsigned long n)
142 integer_class num = numerator(i);
143 integer_class den = denominator(i);
149 void mp_powm(integer_class &res,
const integer_class &base,
150 const integer_class &
exp,
const integer_class &m)
157 integer_class base_inverse;
158 if (!mp_invert(base_inverse, base, m)) {
159 throw SymEngine::SymEngineException(
"negative exponent undefined "
160 "in powm if base is not "
163 res = boost::multiprecision::powm(base_inverse, mp_abs(
exp), m);
166 res = boost::multiprecision::powm(base,
exp, m);
175 integer_class step(
const unsigned long &n,
const integer_class &i,
178 SYMENGINE_ASSERT(n > 1);
179 unsigned long m = n - 1;
180 integer_class &&x_m =
pow(x, m);
181 return integer_class((integer_class(m * x) + integer_class(i / x_m)) / n);
184 bool positive_root(integer_class &res,
const integer_class &i,
185 const unsigned long n)
189 integer_class y = step(n, i, x);
195 if (
pow(x, n) == i) {
202 bool mp_root(integer_class &res,
const integer_class &i,
const unsigned long n)
216 return positive_root(res, i, n);
218 if (i < 0 && (n % 2 == 0)) {
221 bool b = positive_root(res, -i, n);
226 integer_class mp_sqrt(
const integer_class &i)
236 void mp_rootrem(integer_class &a, integer_class &b,
const integer_class &i,
240 integer_class p =
pow(a, n);
245 void mp_sqrtrem(integer_class &a, integer_class &b,
const integer_class &i)
248 b = i - boost::multiprecision::pow(a, 2);
252 int mp_probab_prime_p(
const integer_class &i,
unsigned retries)
256 return miller_rabin_test(i, retries);
259 void mp_nextprime(integer_class &res,
const integer_class &i)
266 integer_class candidate;
267 candidate = (i % 2 == 0) ? i + 1 : i + 2;
270 while (!mp_probab_prime_p(candidate, 25)) {
276 unsigned long mp_scan1(
const integer_class &i)
281 return find_lsb(i, {});
288 integer_class data[2][2];
292 : data{{a, b}, {c, d}}
299 this->data[0][0] = other.data[0][0];
300 this->data[0][1] = other.data[0][1];
301 this->data[1][0] = other.data[1][0];
302 this->data[1][1] = other.data[1][1];
308 res.data[0][0] = this->data[0][0] * other.data[0][0]
309 + this->data[0][1] * other.data[1][0];
310 res.data[0][1] = this->data[0][0] * other.data[0][1]
311 + this->data[0][1] * other.data[1][1];
312 res.data[1][0] = this->data[1][0] * other.data[0][0]
313 + this->data[1][1] * other.data[1][0];
314 res.data[1][1] = this->data[1][0] * other.data[0][1]
315 + this->data[1][1] * other.data[1][1];
322 return two_by_two_matrix::identity();
328 return (*
this) * (*this);
331 return (this->pow(n / 2)).pow(2);
333 return ((this->pow((n - 1) / 2)).pow(2)) * (*this);
348 void mp_fib_ui(integer_class &res,
unsigned long n)
351 res = fib_matrix(n).data[0][1];
355 void mp_fib2_ui(integer_class &a, integer_class &b,
unsigned long n)
358 two_by_two_matrix result_matrix = fib_matrix(n);
359 a = result_matrix.data[0][1];
360 b = result_matrix.data[1][1];
363 inline two_by_two_matrix luc_matrix(
unsigned long n)
365 two_by_two_matrix multiplier(1, 1, 1, 0);
366 two_by_two_matrix start(1, 0, 2, 0);
367 return multiplier.pow(n) * start;
370 void mp_lucnum_ui(integer_class &res,
unsigned long n)
375 res = luc_matrix(n).data[1][0];
378 void mp_lucnum2_ui(integer_class &a, integer_class &b,
unsigned long n)
383 two_by_two_matrix result_matrix = luc_matrix(n - 1);
384 a = result_matrix.data[0][0];
385 b = result_matrix.data[1][0];
388 void mp_fac_ui(integer_class &res,
unsigned long n)
393 for (
unsigned long i = 2; i <= n; ++i) {
398 void mp_bin_ui(integer_class &res,
const integer_class &n,
unsigned long r)
401 integer_class x = n - r;
403 for (
unsigned long i = 1; i <= r; ++i) {
410 bool mp_perfect_power_p(
const integer_class &i)
412 if (i == 0 || i == 1 || i == -1) {
430 if (mp_perfect_square_p(i)) {
434 integer_class root(0);
440 if (mp_root(root, i, p.convert_to<
unsigned long>())) {
446 bool mp_perfect_square_p(
const integer_class &i)
452 return mp_root(root, i, 2);
455 integer_class mp_primorial(
unsigned long n)
457 integer_class res = 1;
458 Sieve::iterator pi(
static_cast<unsigned>(n));
460 while ((p = pi.next_prime()) <= n) {
471 int mp_legendre(
const integer_class &a,
const integer_class &n)
474 mp_powm(res, a, integer_class((n - 1) / 2), n);
475 return res <= 1 ? res.convert_to<
int>() : -1;
481 int unchecked_jacobi(
const integer_class &a,
const integer_class &n)
487 integer_class num = a;
488 integer_class den = n;
490 num =
fmod(num, den);
493 unsigned long factors_of_two = 0;
494 while (num % 2 == 0 && num != 0) {
498 int product_of_twos = 1;
504 int den_mod_8 =
fmod(den, 8).convert_to<
int>();
505 if ((factors_of_two % 2 == 1) && (den_mod_8 == 3 || den_mod_8 == 5)) {
506 product_of_twos = -1;
513 return product_of_twos;
515 if (boost::multiprecision::gcd(num, den) != 1) {
525 int quadratic_reciprocity_factor = 1;
526 if ((
fmod(num, 4) == 3) && (
fmod(den, 4) == 3)) {
527 quadratic_reciprocity_factor = -1;
529 return product_of_twos * quadratic_reciprocity_factor
530 * unchecked_jacobi(den, num);
534 int mp_jacobi(
const integer_class &a,
const integer_class &n)
542 return unchecked_jacobi(a, n);
545 int mp_kronecker(
const integer_class &a,
const integer_class &n)
582 if (n.sign() == -1 && a < 0) {
587 integer_class m = boost::multiprecision::abs(n);
589 while (m % 2 == 0 && m != 0) {
597 int a_mod_8 =
fmod(a, 8).convert_to<
int>();
600 kr_a_2 = (a_mod_8 == 1 || a_mod_8 == 7) ? 1 : -1;
601 kr_a_2_to_j = (kr_a_2 == -1 && (j % 2 != 0))
607 return kr_a_u * kr_a_2_to_j * unchecked_jacobi(a, m);
609 return kr_a_u * unchecked_jacobi(a, m);
Main namespace for SymEngine package.
RCP< const Integer > gcd(const Integer &a, const Integer &b)
Greatest Common Divisor.
RCP< const Basic > max(const vec_basic &arg)
Canonicalize Max:
RCP< const Integer > mod(const Integer &n, const Integer &d)
modulo round toward zero
RCP< const Basic > exp(const RCP< const Basic > &x)
Returns the natural exponential function E**x = pow(E, x)