std::vector<std::pair<GaloisFieldDict, integer_class>> GaloisFieldDict::gf_ddf_zassenhaus() const { unsigned i = 1; GaloisFieldDict f(*this); GaloisFieldDict g = GaloisFieldDict::from_vec({0_z, 1_z}, modulo_); GaloisFieldDict to_sub(g); std::vector<std::pair<GaloisFieldDict, integer_class>> factors; auto b = f.gf_frobenius_monomial_base(); while (2 * i <= f.degree()) { g = g.gf_frobenius_map(f, b); GaloisFieldDict h = f.gf_gcd(g - to_sub); if (not h.is_one()) { factors.push_back({h, integer_class(i)}); f /= h; g %= f; b = f.gf_frobenius_monomial_base(); } i += 1; } if (not(f.is_one() || f.empty())) { factors.push_back({f, integer_class(f.degree())}); } return factors; }
std::vector<std::pair<GaloisFieldDict, integer_class>> GaloisFieldDict::gf_sqf_list() const { std::vector<std::pair<GaloisFieldDict, integer_class>> vec_out; if (degree() < 1) return vec_out; integer_class n = integer_class(1); unsigned r = mp_get_si(modulo_); bool sqf = false; integer_class LC; GaloisFieldDict f; gf_monic(LC, outArg(f)); while (true) { GaloisFieldDict F = f.gf_diff(); if (not F.dict_.empty()) { GaloisFieldDict g = f.gf_gcd(F); GaloisFieldDict h = f / g; integer_class i = integer_class(1); while (not h.is_one()) { GaloisFieldDict G = h.gf_gcd(g); GaloisFieldDict H = h / G; if (H.degree() > 0) vec_out.push_back({H, i * n}); i += integer_class(1); g /= G; h = G; } if (g.is_one()) sqf = true; else f = g; } if (not sqf) { unsigned int deg = f.degree(); unsigned int d = deg / r; GaloisFieldDict temp = f; for (unsigned int i = 0; i <= d; i++) { f.dict_[d - i] = temp.dict_[deg - i * r]; } n *= r; f.dict_.resize(d + 1); f.gf_istrip(); } else break; } return vec_out; }
GaloisFieldDict GaloisFieldDict::gf_diff() const { auto df = degree(); GaloisFieldDict out = GaloisFieldDict({}, modulo_); out.dict_.resize(df, integer_class(0)); for (unsigned i = 1; i <= df; i++) { if (dict_[i] != integer_class(0)) { out.dict_[i - 1] = i * dict_[i]; mp_fdiv_r(out.dict_[i - 1], out.dict_[i - 1], modulo_); } } out.gf_istrip(); return out; }
vec_basic GaloisField::get_args() const { vec_basic args; if (poly_.dict_.empty()) args.push_back(zero); else { for (unsigned i = 0; i < poly_.dict_.size(); i++) { if (poly_.dict_[i] == integer_class(0)) continue; if (i == 0) { args.push_back(integer(poly_.dict_[i])); } else if (i == 1) { if (poly_.dict_[i] == 1) { args.push_back(var_); } else { args.push_back( Mul::from_dict(integer(poly_.dict_[i]), {{var_, one}})); } } else { if (poly_.dict_[i] == 1) { args.push_back(pow(var_, integer(i))); } else { args.push_back(Mul::from_dict(integer(poly_.dict_[i]), {{var_, integer(i)}})); } } } } return args; }
RCP<const UIntPolyFlint> UIntPolyFlint::from_vec(const RCP<const Symbol> &var, const vec_integer_class &v) { // benchmark this against vec->str->fmpz_polyxx unsigned int deg = v.size() - 1; while (v[deg] == integer_class(0)) deg--; fp_t f(deg + 1); for (unsigned int i = 0; i <= deg; i++) { if (v[i] != integer_class(0)) { fz_t r(get_mpz_t(v[i])); f.set_coeff(i, r); } } return make_rcp<const UIntPolyFlint>(var, std::move(f)); }
void GaloisFieldDict::gf_monic(integer_class &res, const Ptr<GaloisFieldDict> &monic) const { *monic = static_cast<GaloisFieldDict>(*this); if (dict_.empty()) { res = integer_class(0); } else { res = *dict_.rbegin(); if (res != integer_class(1)) { integer_class inv, temp; mp_invert(inv, res, modulo_); for (auto &iter : monic->dict_) { temp = inv; temp *= iter; mp_fdiv_r(iter, temp, modulo_); } } } }
GaloisFieldDict GaloisFieldDict::gf_lshift(const integer_class n) const { std::vector<integer_class> dict_out; auto to_ret = GaloisFieldDict::from_vec(dict_out, modulo_); if (!dict_.empty()) { unsigned n_val = mp_get_si(n); to_ret.dict_.resize(n_val, integer_class(0)); to_ret.dict_.insert(to_ret.dict_.end(), dict_.begin(), dict_.end()); } return to_ret; }
GaloisFieldDict GaloisFieldDict::gf_pow(const integer_class n) const { if (n == 0) { return GaloisFieldDict({integer_class(1)}, modulo_); } if (n == 1) return static_cast<GaloisFieldDict>(*this); if (n == 2) return gf_sqr(); long num = mp_get_si(n); GaloisFieldDict to_sq = static_cast<GaloisFieldDict>(*this); GaloisFieldDict to_ret = GaloisFieldDict({integer_class(1)}, modulo_); while (1) { if (num & 1) { to_ret *= to_sq; } num >>= 1; if (num == 0) return to_ret; to_sq = to_sq.gf_sqr(); } }
RCP<const Number> Integer::pow_negint(const Integer &other) const { RCP<const Number> tmp = powint(*other.neg()); if (is_a<Integer>(*tmp)) { const integer_class &j = down_cast<const Integer &>(*tmp).i; #if SYMENGINE_INTEGER_CLASS == SYMENGINE_BOOSTMP // boost::multiprecision::cpp_rational lacks an (int, cpp_int) // constructor. must use cpp_rational(cpp_int,cpp_int) rational_class q(integer_class(mp_sign(j)), mp_abs(j)); #else rational_class q(mp_sign(j), mp_abs(j)); #endif return Rational::from_mpq(std::move(q)); } else { throw SymEngineException("powint returned non-integer"); } }
RCP<const UnivariateIntPolynomial> UnivariateIntPolynomial::from_dict(const RCP<const Symbol> &var, map_uint_mpz &&d) { auto itter = d.begin(); while (itter != d.end()) { if (integer_class(0) == itter->second) { auto toErase = itter; itter++; d.erase(toErase); } else { itter++; } } unsigned int degree = 0; if (!d.empty()) degree = (--(d.end()))->first; return make_rcp<const UnivariateIntPolynomial>(var, degree, std::move(d)); }