void poly_mul(const umap_vec_mpz &A, const umap_vec_mpz &B, umap_vec_mpz &C) { vec_int exp; int n = (A.begin()->first).size(); exp.assign(n, 0); // Initialize to [0]*n /* std::cout << "A: " << A.load_factor() << " " << A.bucket_count() << " " << A.size() << " " << A.max_bucket_count() << std::endl; std::cout << "B: " << B.load_factor() << " " << B.bucket_count() << " " << B.size() << " " << B.max_bucket_count() << std::endl; std::cout << "C: " << C.load_factor() << " " << C.bucket_count() << " " << C.size() << " " << C.max_bucket_count() << std::endl; */ for (const auto &a: A) { for (const auto &b: B) { monomial_mul(a.first, b.first, exp); mp_addmul(C[exp], a.second, b.second); } } /* std::cout << "C: " << C.load_factor() << " " << C.bucket_count() << " " << C.size() << " " << C.max_bucket_count() << std::endl; for (const std::size_t n=0; n < C.bucket_count(); n++) { std::cout << n << ": " << C.bucket_size(n) << "|"; for (auto it = C.begin(n); it != C.end(n); ++it) std::cout << " " << it->first << myhash2(it->first) % C.bucket_count(); std::cout << std::endl; } */ }
void GaloisFieldDict::gf_div(const GaloisFieldDict &o, const Ptr<GaloisFieldDict> &quo, const Ptr<GaloisFieldDict> &rem) const { if (modulo_ != o.modulo_) throw std::runtime_error("Error: field must be same."); if (o.dict_.empty()) throw std::runtime_error("ZeroDivisionError"); std::vector<integer_class> dict_out; if (dict_.empty()) { *quo = GaloisFieldDict::from_vec(dict_out, modulo_); *rem = GaloisFieldDict::from_vec(dict_, modulo_); return; } auto dict_divisor = o.dict_; unsigned int deg_dividend = this->degree(); unsigned int deg_divisor = o.degree(); if (deg_dividend < deg_divisor) { *quo = GaloisFieldDict::from_vec(dict_out, modulo_); *rem = GaloisFieldDict::from_vec(dict_, modulo_); } else { dict_out = dict_; integer_class inv; mp_invert(inv, *(dict_divisor.rbegin()), modulo_); integer_class coeff; for (auto it = deg_dividend + 1; it-- != 0;) { coeff = dict_out[it]; auto lb = deg_divisor + it > deg_dividend ? deg_divisor + it - deg_dividend : 0; auto ub = std::min(it + 1, deg_divisor); for (size_t j = lb; j < ub; ++j) { mp_addmul(coeff, dict_out[it - j + deg_divisor], -dict_divisor[j]); } if (it >= deg_divisor) coeff *= inv; mp_fdiv_r(coeff, coeff, modulo_); dict_out[it] = coeff; } std::vector<integer_class> dict_rem, dict_quo; dict_rem.resize(deg_divisor); dict_quo.resize(deg_dividend - deg_divisor + 1); for (unsigned it = 0; it < dict_out.size(); it++) { if (it < deg_divisor) dict_rem[it] = dict_out[it]; else dict_quo[it - deg_divisor] = dict_out[it]; } *quo = GaloisFieldDict::from_vec(dict_quo, modulo_); *rem = GaloisFieldDict::from_vec(dict_rem, modulo_); } }