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>
10using boost::multiprecision::denominator;
11using boost::multiprecision::miller_rabin_test;
12using boost::multiprecision::numerator;
13using boost::multiprecision::detail::find_lsb;
15#if SYMENGINE_INTEGER_CLASS == SYMENGINE_BOOSTMP
20integer_class
pow(
const integer_class &a,
unsigned long b)
25void mp_fdiv_qr(integer_class &
q, integer_class &
r,
const integer_class &a,
26 const integer_class &b)
59void mp_cdiv_qr(integer_class &
q, integer_class &
r,
const integer_class &a,
60 const integer_class &b)
76void mp_gcdext(integer_class &
gcd, integer_class &s, integer_class &t,
77 const integer_class &a,
const integer_class &b)
111bool 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);
131integer_class
fmod(
const integer_class &a,
const integer_class &
mod)
133 integer_class
res = a %
mod;
140void 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);
149void mp_powm(integer_class &
res,
const integer_class &base,
150 const integer_class &
exp,
const integer_class &m)
159 throw SymEngine::SymEngineException(
"negative exponent undefined "
160 "in powm if base is not "
166 res = boost::multiprecision::powm(base,
exp, m);
175integer_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);
184bool 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) {
202bool 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);
226integer_class mp_sqrt(
const integer_class &i)
236void mp_rootrem(integer_class &a, integer_class &b,
const integer_class &i,
240 integer_class p =
pow(a, n);
245void mp_sqrtrem(integer_class &a, integer_class &b,
const integer_class &i)
248 b = i - boost::multiprecision::pow(a, 2);
252int mp_probab_prime_p(
const integer_class &i,
unsigned retries)
256 return miller_rabin_test(i,
retries);
259void mp_nextprime(integer_class &
res,
const integer_class &i)
267 candidate = (i % 2 == 0) ? i + 1 : i + 2;
270 while (!mp_probab_prime_p(
candidate, 25)) {
276unsigned 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);
348void mp_fib_ui(integer_class &
res,
unsigned long n)
351 res = fib_matrix(n).data[0][1];
355void mp_fib2_ui(integer_class &a, integer_class &b,
unsigned long n)
363inline two_by_two_matrix luc_matrix(
unsigned long n)
366 two_by_two_matrix
start(1, 0, 2, 0);
370void mp_lucnum_ui(integer_class &
res,
unsigned long n)
375 res = luc_matrix(n).data[1][0];
378void mp_lucnum2_ui(integer_class &a, integer_class &b,
unsigned long n)
388void mp_fac_ui(integer_class &
res,
unsigned long n)
393 for (
unsigned long i = 2; i <= n; ++i) {
398void 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) {
410bool 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>())) {
446bool mp_perfect_square_p(
const integer_class &i)
452 return mp_root(root, i, 2);
455integer_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) {
471int 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;
481int unchecked_jacobi(
const integer_class &a,
const integer_class &n)
487 integer_class
num = a;
488 integer_class
den = n;
494 while (
num % 2 == 0 &&
num != 0) {
515 if (boost::multiprecision::gcd(
num,
den) != 1) {
530 * unchecked_jacobi(
den,
num);
534int mp_jacobi(
const integer_class &a,
const integer_class &n)
542 return unchecked_jacobi(a, n);
545int 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) {
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
void hash_combine(hash_t &seed, const T &v)
RCP< const Basic > exp(const RCP< const Basic > &x)
Returns the natural exponential function E**x = pow(E, x)