// References : Cohen H., A course in computational algebraic number theory // (1996), page 25. bool multiplicative_order(const Ptr<RCP<const Integer>> &o, const RCP<const Integer> &a, const RCP<const Integer> &n) { integer_class order, p, t; integer_class _a = a->as_integer_class(), _n = mp_abs(n->as_integer_class()); mp_gcd(t, _a, _n); if (t != 1) return false; RCP<const Integer> lambda = carmichael(n); map_integer_uint prime_mul; prime_factor_multiplicities(prime_mul, *lambda); _a %= _n; order = lambda->as_integer_class(); for (const auto it : prime_mul) { p = it.first->as_integer_class(); mp_pow_ui(t, p, it.second); mp_divexact(order, order, t); mp_powm(t, _a, order, _n); while (t != 1) { mp_powm(t, t, p, _n); order *= p; } } *o = integer(std::move(order)); return true; }
RCP<const Integer> carmichael(const RCP<const Integer> &n) { if (n->is_zero()) return integer(1); map_integer_uint prime_mul; integer_class lambda, t, p; unsigned multiplicity; prime_factor_multiplicities(prime_mul, *n); lambda = 1; for (const auto it : prime_mul) { p = it.first->as_integer_class(); multiplicity = it.second; if (p == 2 and multiplicity > 2) { // For powers of 2 greater than 4 divide by 2. multiplicity--; } t = p - 1; mp_lcm(lambda, lambda, t); mp_pow_ui(t, p, multiplicity - 1); // lambda and p are relatively prime. lambda = lambda * t; } return integer(std::move(lambda)); }
integer_class UnivariateIntPolynomial::eval(const integer_class &x) const { unsigned int last_deg = dict_.rbegin()->first; integer_class result(0), x_pow; for (auto it = dict_.rbegin(); it != dict_.rend(); ++it) { mp_pow_ui(x_pow, x, last_deg - (*it).first); last_deg = (*it).first; result = (*it).second + x_pow * result; } mp_pow_ui(x_pow, x, last_deg); result *= x_pow; return result; }
RCP<const Number> harmonic(unsigned long n, long m) { rational_class res(0); if (m == 1) { for (unsigned i = 1; i <= n; ++i) { res += rational_class(1, i); } return Rational::from_mpq(res); } else { for (unsigned i = 1; i <= n; ++i) { if (m > 0) { rational_class t(1u, i); mp_pow_ui(get_den(t), get_den(t), m); res += t; } else { integer_class t(i); mp_pow_ui(t, t, -m); res += t; } } return Rational::from_mpq(res); } }
integer_class MIntPoly::eval( std::map<RCP<const Basic>, integer_class, RCPBasicKeyLess> &vals) const { // TODO : handle missing values integer_class ans(0), temp, term; for (auto bucket : poly_.dict_) { term = bucket.second; unsigned int whichvar = 0; for (auto sym : vars_) { mp_pow_ui(temp, vals.find(sym)->second, bucket.first[whichvar]); term *= temp; whichvar++; } ans += term; } return ans; }