/** \brief 有限域Fp上多项式在Fp中的根(不含重数) \param f Fp[x]中多项式 \param p 阶数 \return 根的集合 \note 利用因子分解算法求解 */ void UniZpRootZp(std::vector<mpz_ptr> & rootlist,const poly_z & f,mpz_ptr p) { resize_z_list(rootlist,0); poly_z h0,h; h0.resize(2); mpz_set_ui(h0[0],0); mpz_set_ui(h0[1],1); copy_poly_z(h,h0); PowerMod(h,p,f,p); mpz_sub_ui(h[1],h[1],1); UniGcdZp(h0,h,f,p); if(h0.size()==1) { h0.resize(0); h.resize(0); return ; } std::vector<poly_z> faclist; UniEqlDegFacZp(faclist,h0,p,1); for(uint i=0; i<faclist.size(); i++) { resize_z_list(rootlist,i+1); mpz_neg(rootlist[i],faclist[i][0]); } clear_poly_z_list(faclist); h0.resize(0); h.resize(0); std::sort(rootlist.begin(),rootlist.end(),mpz_ptr_less); return ; }
//todo using iterated frobenius alg. to improve it? void UniEqlDegFacZp_Odd(poly_z & factor,const poly_z & f,mpz_ptr p,uint d) { uint deg_bound=f.size()-2; poly_z a; while(1) { UniRandomZp(a,deg_bound,p); if(a.size()>1)break; } UniGcdZp(factor,a,f,p); if(factor.size()>1&&factor.size()<f.size()) { a.resize(0); return ; } power_specially_for_eqldegfactorization(a,f,p,d); //static mpz_t exp; //mpz_init(exp); //mpz_pow_ui(exp,p,d); //mpz_sub_ui(exp,exp,1); //mpz_divexact_ui(exp,exp,2); //PowerMod(a,exp,f,p); //mpz_clear(exp); mpz_sub_ui(a[0],a[0],1); UniGcdZp(factor,a,f,p); if(factor.size()>1&&factor.size()<f.size()) { a.resize(0); return; } a.resize(0); factor.resize(0); return ; }
/** \brief 整系数多项式最大公因子. \param f,g 整系数本原多项式,且\f$\deg f=n\ge\deg g\ge 1\f$. \param r 最大公因子. \note 小素数模方法. \todo 理论文档此处有误. */ void UniGcdZ_SmallPrime1(poly_z & r,const poly_z & f,const poly_z & g) { poly_z fp,gp,vp,v1; poly_z fstar,gstar; mpz_t c,s,t; mpz_init(c);mpz_init(s);mpz_init(t); mpz_t A,b,B,z_temp,k,p_bound,p,p_low_bound,p1,B2; mpf_t float_temp; mpz_init(A);mpz_init(b);mpz_init(B);mpz_init(z_temp);mpz_init(k);mpz_init(p_bound);mpz_init(p);mpz_init(p1);mpz_init(p_low_bound);mpf_init(float_temp);mpz_init(B2); UniMaxNormZ(A,f);UniMaxNormZ(b,g); int n=f.size()-1,m=g.size()-1; if(mpz_cmp(A,b)<0)mpz_set(A,b); mpz_gcd(b,f[n],g[m]); mpz_ui_pow_ui(B,2,n); mpz_mul(B,B,A); mpz_mul(B,B,b); mpf_sqrt_ui(float_temp,n+1); mpz_set_f(z_temp,float_temp); mpz_mul(B,B,z_temp); mpz_mul_ui(B2,B,2); mpz_set_si(z_temp,n); int tempint; tempint=2*n*mpz_sizeinbase(z_temp,2)+2*mpz_sizeinbase(b,2)+4*n*mpz_sizeinbase(A,2); //tempint=2*n*Modules::NumberTheory::IntegerLength(Z(n),2)+2*Modules::NumberTheory::IntegerLength(b,2)+4*n*Modules::NumberTheory::IntegerLength(A,2); mpz_set_si(k,tempint); mpz_mul_ui(p_bound,k,2); mpz_mul_ui(p_bound,p_bound,mpz_sizeinbase(k,2)); mpz_set_ui(p_low_bound,3); fstar.resize(n+1); for(size_t i=0;i<=n;i++) { mpz_mul(fstar[i],f[i],b); } gstar.resize(m+1); for(size_t i=0;i<=m;i++) { mpz_mul(gstar[i],g[i],b); } while(1) { while(1) { random::randominteger(p,p_low_bound,p_bound); if(mpz_probab_prime_p(p,10)>0&&mpz_divisible_p(b,p)==0)break; } UniPolynomialMod(fp,f,p); UniPolynomialMod(gp,g,p); UniGcdZp(vp,fp,gp,p); if(vp.size()==1) { r.resize(1); mpz_set_si(r[0],1); fp.resize(0);gp.resize(0);vp.resize(0);v1.resize(0); fstar.resize(0);gstar.resize(0); mpz_clear(c);mpz_clear(s);mpz_clear(t); mpz_clear(A);mpz_clear(b);mpz_clear(B);mpz_clear(z_temp);mpz_clear(k);mpz_clear(p_bound);mpz_clear(p);mpz_clear(p1);mpz_clear(p_low_bound);mpf_clear(float_temp); return ; } mpz_set(p1,p); copy_poly_z(v1,vp); while(mpz_cmp(p1,B2)<0) { while(1) { random::randominteger(p,p_low_bound,p_bound); if(mpz_probab_prime_p(p,10)>0&&mpz_divisible_p(b,p)==0)break; } UniPolynomialMod(fp,f,p); UniPolynomialMod(gp,g,p); UniGcdZp(vp,fp,gp,p); if(vp.size()==1) { r.resize(1); mpz_set_si(r[0],1); fp.resize(0);gp.resize(0);vp.resize(0);v1.resize(0); fstar.resize(0);gstar.resize(0); mpz_clear(c);mpz_clear(s);mpz_clear(t); mpz_clear(A);mpz_clear(b);mpz_clear(B);mpz_clear(z_temp);mpz_clear(k);mpz_clear(p_bound);mpz_clear(p);mpz_clear(p1);mpz_clear(p_low_bound);mpf_clear(float_temp); return ; } if(vp.size()<v1.size()) { mpz_set(p1,p); copy_poly_z(v1,vp); continue; } if(vp.size()==v1.size()) { mpz_gcdext(c,s,t,p1,p); mpz_mul(t,p,t); mpz_mul(s,p1,s); mpz_mul(p1,p1,p); for(size_t i=0;i<vp.size();i++) { mpz_mul(c,v1[i],t); mpz_addmul(c,vp[i],s); mpz_set(v1[i],c); } UniPolynomialMod(v1,v1,p1); } } for(size_t i=0;i<v1.size();i++)mpz_mul(v1[i],v1[i],b); UniPolynomialMod(v1,v1,p1); if(poly_z_divisible(fstar,v1)&&poly_z_divisible(gstar,v1)) { UniPPZ(r,v1);break; } } fp.resize(0);gp.resize(0);vp.resize(0);v1.resize(0); fstar.resize(0);gstar.resize(0); mpz_clear(c);mpz_clear(s);mpz_clear(t); mpz_clear(A);mpz_clear(b);mpz_clear(B);mpz_clear(z_temp);mpz_clear(k);mpz_clear(p_bound);mpz_clear(p);mpz_clear(p1);mpz_clear(p_low_bound);mpf_clear(float_temp); return ; }
//f and g should normalized first void MultiGcdZp_Dense_Interpolation(sparse_z & r,const sparse_z & f, const sparse_z & g,uint n, mpz_ptr p) { if(n==1)// problem of univariate polynomials { poly_z ff,gg,rr; sparse_z_to_poly_z(ff,f); sparse_z_to_poly_z(gg,g); UniGcdZp(rr,ff,gg,p); poly_z_to_sparse_z(r,rr,1,0); ff.resize(0);gg.resize(0);rr.resize(0); return ; } poly_z contf,contg,poly_temp,a,b; sparse_z _f,_g,sparse_temp; cont_in_last_zp(contf,f,p); cont_in_last_zp(contg,g,p); UniGcdZp(a,contf,contg,p); poly_z_to_sparse_z(sparse_temp,contf,n,n-1); MultiDivExactZp(_f,f,sparse_temp,p); poly_z_to_sparse_z(sparse_temp,contg,n,n-1); MultiDivExactZp(_g,g,sparse_temp,p); lc_in_last_zp(contf,_f,p); lc_in_last_zp(contg,_g,p); UniGcdZp(b,contf,contg,p); sparse_z q,h,fv,gv,hv; poly_z q_one_v; sparse_z h_temp; uint m,m1,size; mpz_t v,bv,inverse; q.resize(1);mpz_set_ui(q[0].coe,1);q[0].exponents.resize(n,0); q_one_v.resize(1);mpz_set_ui(q_one_v[0],1); h.resize(1);mpz_set_ui(h[0].coe,1);h[0].exponents.resize(n,0); m=std::min<uint>(_f.deg(0),_g.deg(0))+1; mpz_init(v);mpz_init(bv);mpz_init(inverse); mpz_set_si(v,-1); while(1) { mpz_add_ui(v,v,1); if(mpz_cmp(v,p)==0) { r.resize(0); break; } UniEvalZp(bv,b,v,p); if(mpz_cmp_ui(bv,0)==0)continue; eval_in_last_zp(fv,_f,v,p); eval_in_last_zp(gv,_g,v,p); MultiGcdZp_Dense_Interpolation(hv,fv,gv,n-1,p); if(hv.size()==0) { r.resize(0); break; } m1=hv.deg(0); size=hv.size(); if(m1>m)continue; //正则化 mpz_set(inverse,hv[size-1].coe); mpz_invert(inverse,inverse,p); for(uint i=0;i<size;++i) { mpz_mul(hv[i].coe,hv[i].coe,inverse); mpz_mul(hv[i].coe,hv[i].coe,bv); } MultiPolynomialMod(hv,hv,p); if(m1<m) { //q=x_n-v q.resize(2); mpz_neg(q[0].coe,v);q[0].exponents.resize(n); for(uint i=0;i<n;++i)q[0].exponents[i]=0; mpz_set_ui(q[1].coe,1);q[1].exponents.resize(n); for(uint i=0;i<n;++i)q[1].exponents[i]=0; q[1].exponents[n-1]=1; q_one_v.resize(2); mpz_neg(q_one_v[0],v);mpz_set_ui(q_one_v[1],1); //h=hv h.resize(hv.size()); for(uint i=0;i<hv.size();++i) { mpz_set(h[i].coe,hv[i].coe); h[i].exponents=hv[i].exponents; h[i].exponents.push_back(0); } m=m1; continue; } //modification of h eval_in_last_zp(h_temp,h,v,p); size=hv.size(); for(uint i=0;i<size;++i)hv[i].exponents.push_back(0); size=h_temp.size(); for(uint i=0;i<size;++i)h_temp[i].exponents.push_back(0); MultiSubZ(h_temp,hv,h_temp); MultiPolynomialMod(sparse_temp,h_temp,p); MultiMulZ(h_temp,sparse_temp,q); MultiPolynomialMod(h_temp,h_temp,p); UniEvalZp(inverse,q_one_v,v,p); mpz_invert(inverse,inverse,p); MultiMulZ(h_temp,h_temp,inverse); MultiPolynomialMod(h_temp,h_temp,p); MultiAddZ(h,h,h_temp); MultiPolynomialMod(h,h,p); //modification of q sparse_temp.resize(2); mpz_neg(sparse_temp[0].coe,v);sparse_temp[0].exponents.resize(n); for(uint i=0;i<n;++i)sparse_temp[0].exponents[i]=0; mpz_set_ui(sparse_temp[1].coe,1);sparse_temp[1].exponents.resize(n); for(uint i=0;i<n;++i)sparse_temp[1].exponents[i]=0; sparse_temp[1].exponents[n-1]=1; MultiMulZ(h_temp,q,sparse_temp); MultiPolynomialMod(q,h_temp,p); contf.resize(2); mpz_neg(contf[0],v);mpz_set_ui(contf[1],1); UniMulZ(contg,contf,q_one_v); UniPolynomialMod(q_one_v,contg,p); //criteria lc_in_last_zp(poly_temp,h,p); UniSubZ(poly_temp,poly_temp,b); UniPolynomialMod(poly_temp,poly_temp,p); if(m==0) { poly_z_to_sparse_z(r,a,n,n-1); return ; } if(poly_temp.size()==0) { pp_in_last_zp(h_temp,h,p); if(MultiDivisibleZp(_f,h_temp,p)&&MultiDivisibleZp(_g,h_temp,p)) { poly_z_to_sparse_z(sparse_temp,a,n,n-1); MultiMulZ(r,sparse_temp,h_temp); MultiPolynomialMod(r,r,p); return ; } } } contf.resize(0);contg.resize(0);poly_temp.resize(0);a.resize(0);b.resize(0); _f.resize(0);_g.resize(0);sparse_temp.resize(0); q.resize(0);h.resize(0);fv.resize(0);gv.resize(0);hv.resize(0); q_one_v.resize(0); h_temp.resize(0); mpz_clear(v);mpz_clear(bv);mpz_clear(inverse); return ; }