polynomial operator+(const polynomial<T>& o) const { int len; const polynomial<T> *p; size() >= o.size() ? (p=this, len=size()) : (p=&o, len=o.size()); polynomial<T> out(len); std::transform(vals->data(),vals->data()+std::min(size(),o.size()),o.vals->data(),out.vals->data(),[](T a, T b){return a+b;}); if (size() != o.size()) std::copy_n(&p->element(std::min(size(),o.size())),abs(size()-o.size()),&out(std::min(size(),o.size()))); return out; }
polynomial operator*(const polynomial<T>& o) const { int len = size()+o.size()-1; polynomial<T> out(len); for (int ii = 0; ii<size(); ii++) { for (int jj = 0; jj<o.size(); jj++) out(ii+jj) += (element(ii)*o(jj)); } return out; }
friend polynomial derivative(polynomial const& p) { int s = p.size(); if(s == 0) return {}; polynomial res; res.coeffs.resize(s-1); for(int n = 0; n < s-1; ++n) res.coeffs(n) = p.coeffs(n+1) * CoeffType(n+1); return res; }
friend polynomial antiderivative(polynomial const& p) { int s = p.size(); if(s == 0) return {}; polynomial res; res.coeffs.resize(s+1); res.coeffs(0) = CoeffType{}; for(int n = 1; n < s+1; ++n) res.coeffs(n) = p.coeffs(n-1) / CoeffType(n); return res; }
void divide(const polynomial &b) { int m=b.size(),res[1110]; for (int i=n;i>=m;i--) { int t=a[i]/b[m]; for (int j=i;j>=i-m;j--) a[j]-=b[j-i+m]*t; res[i-m]=t; } n-=m; for (int i=0;i<=n;i++) a[i]=res[i]; }
void fr_kernels(int i, const polynomial& P, const monomial& d, monomial& bk, polynomial& bcok, int& bv) { for (int j = i; j < literal_size(); ++j) { int times = 0; for (int k = 0; k < P.size(); ++k) { if (P[k].getpow(j) != 0) { ++times; } } if (times > 1) { monomial Lj(j); polynomial Ft = P / Lj; monomial C = Ft.gcd(); bool cflag = true; for (int k = 0; k < C.size(); ++k) { if (C.lit(k) < j) { cflag = false; break; } } if (cflag) { polynomial FI = Ft / C;//kernel monomial DI = d * C * Lj;//co-kernel int v = fr_value(DI, FI); if (v > bv) { bv = v; bk = DI; bcok = FI; } fr_kernels(j, FI, DI, bk, bcok, bv); } } } }
polynomial operator-(const polynomial<T>& o) const { int len, sign; int min = std::min(size(),o.size()); const polynomial<T> *p; size() >= o.size() ? (p=this, len=size(), sign=1) : (p=&o, len=o.size(), sign=-1); polynomial<T> out(len); std::transform(vals->data(),vals->data()+min,o.vals->data(),out.vals->data(),[](T a, T b){return a-b;}); if (size() != o.size()) { std::copy_n(&p->element(min),abs(size()-o.size()),&out(min)); if (sign == -1) std::transform(&out(min),&out(min)+abs(size()-o.size()),&out(min),[](T a){return -1.0*a;}); } return out; }
//The fr_kernels part are part of initial fastrun stategy //Now they are deprecated, but we still keep these code in case. int fr_value(const monomial& bk, const polynomial& bcok) { return (bcok.size() - 1) * bk.multiplication_number(); }
void kernels(int i, const polynomial& P, const monomial& d, vector<pair<monomial, polynomial>>& kernelmap) { //we use bitset for sj1 as we need fast lookup //while for sj2 we need iteration therefore we use set std::set<int> sj2; //brackets here for early release sj1, to reduce memory cost, as in recursive calling we may waste lots of memory { boost::dynamic_bitset<uint64_t> sj1(literal_size());//default value should be 0, i.e. false for (int mi = 0; mi < P.size(); ++mi) { for (int ti = 0; ti < P[mi].size(); ++ti) { int tmp = P[mi].lit(ti); if (tmp < i) { continue; } if (sj1[tmp] == 0) { sj1[tmp] = 1; } else { sj2.insert(tmp); } } } } for (auto j : sj2) { monomial Lj(j); polynomial Ft = P / Lj; monomial C = Ft.gcd(); //optimization for this common case if (C == monomial()) { monomial DI = d * Lj;//co-kernel kernelmap.push_back(make_pair(DI, Ft)); kernels(j, Ft, DI, kernelmap); continue; } bool cflag = true; for (int k = 0; k < C.size(); ++k) { if (C.lit(k) < j) { cflag = false; break; } } if (cflag) { polynomial FI = Ft / C;//kernel monomial DI = d * C * Lj;//co-kernel //special for if FI=1+... /* if (FI.contain(monomial())) { for (int l = 0; l < C.size(); ++l) { polynomial NFI = FI * monomial(C.lit(l)); monomial NDI = DI; NDI /= monomial(C.lit(l)); std::cout<<NDI<<" "<<NFI<<std::endl; kernelmap.push_back(make_pair(NDI, NFI)); kernels(j, NFI, NDI, kernelmap); } } */ kernelmap.push_back(make_pair(DI, FI)); kernels(j, FI, DI, kernelmap); } } }
polynomial(const polynomial& o) : vals(std::make_shared<std::vector<T>>(o.size())) { std::copy_n(o.vals->data(), size(), vals->data()); }