/** \brief Fp域上多项式GCD. \param f,g 域上多项式. \param r 最大公因子. \note Euclid算法. */ void UniGcdZp(poly_z & r,const poly_z & f,const poly_z & g,mpz_ptr p) { poly_z u,v; poly_z q; copy_poly_z(u,f); copy_poly_z(v,g); while(v.size()> 0){ UniDivModZp(q,r,u,v,p); UniPolynomialMod(r,r,p); u.resize(0); u=v;v=r; r=poly_z(); } static mpz_t lc; mpz_init_set(lc,u[u.size()-1]); mpz_invert(lc,lc,p); r.resize(u.size()); for(size_t i=0;i<u.size();i++) { mpz_mul(r[i],u[i],lc); } UniPolynomialMod(r,r,p); mpz_clear(lc); u.resize(0);v.resize(0);q.resize(0); }
/** \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 ; }
/** \brief Fp域上多项式GCD. \param f,g 域上多项式. \param r,s,t 其中r为最大公因子,s,t为Bezout系数多项式. */ void UniGcdZp_Ext(poly_z & r,poly_z & s,poly_z & t,const poly_z & f,const poly_z & g,mpz_ptr p) { poly_z u,v; poly_z q; poly_z s1,s2,t1,t2,l1,l2; copy_poly_z(u,f); copy_poly_z(v,g); s1.resize(1);mpz_set_si(s1[0],1); s2.resize(0); t1.resize(0); t2.resize(1);mpz_set_si(t2[0],1); while(v.size()> 0){ UniDivModZp(q,r,u,v,p); UniPolynomialMod(r,r,p); UniMulZ(l1,q,t1);UniSubZ(l1,s1,l1); UniMulZ(l2,q,t2);UniSubZ(l2,s2,l2); u.resize(0);u=v;v=r;r=poly_z(); s1.resize(0);s1=t1;t1=l1;l1=poly_z(); s2.resize(0);s2=t2;t2=l2;l2=poly_z(); } static mpz_t lc; mpz_init_set(lc,u[u.size()-1]); mpz_invert(lc,lc,p); r.resize(u.size()); for(size_t i=0;i<u.size();i++) { mpz_mul(r[i],u[i],lc); } UniPolynomialMod(r,r,p); s.resize(s1.size()); for(size_t i=0;i<s1.size();i++) { mpz_mul(s[i],s1[i],lc); } UniPolynomialMod(s,s,p); t.resize(s2.size()); for(size_t i=0;i<s2.size();i++) { mpz_mul(t[i],s2[i],lc); } UniPolynomialMod(t,t,p); mpz_clear(lc); u.resize(0);v.resize(0);q.resize(0);s1.resize(0);s2.resize(0);t1.resize(0);t2.resize(0);l1.resize(0);l2.resize(0); }
/** \brief 整系数多项式最大公因子. \param f,g 整系数多项式. \return 最大公因子. \note 调用大素数算法或小素数算法. */ void UniGcdZ(poly_z & r,const poly_z & f,const poly_z & g) { uint option=1; if(f.size()==0) { copy_poly_z(r,g); return ; } if(g.size()==0) { copy_poly_z(r,f); return ; } mpz_t contf,contg,b; mpz_init(contf);mpz_init(contg);mpz_init(b); UniContZ(contf,f);UniContZ(contg,g); mpz_gcd(b,contf,contg); poly_z _f,_g,h; UniPPZ(_f,f);UniPPZ(_g,g); int n=_f.deg(),m=_g.deg(); if(n==0||m==0) { h.resize(1); mpz_set_ui(h[0],1); } else { if(n<m)UniGcdZ_SmallPrime1(h,_g,_f); else UniGcdZ_SmallPrime1(h,_f,_g); } r.resize(h.size()); for(size_t i=0;i<h.size();i++) { mpz_mul(r[i],h[i],b); } _f.resize(0);_g.resize(0);h.resize(0); mpz_clear(contf);mpz_clear(contg);mpz_clear(b); return ; }
void power_specially_for_eqldegfactorization(poly_z & a,const poly_z & f,mpz_ptr p,uint d) { poly_z poly_temp1,poly_temp2; static mpz_t exp; mpz_init(exp); copy_poly_z(poly_temp1,a); for(uint i=1;i<d;i++) { PowerMod_Pth_Power(poly_temp1,f,p); UniMulZ(poly_temp2,poly_temp1,a); UniModZp(a,poly_temp2,f,p); } mpz_sub_ui(exp,p,1); mpz_fdiv_q_2exp(exp,exp,1); PowerMod(a,exp,f,p); poly_temp1.resize(0); poly_temp2.resize(0); mpz_clear(exp); return ; }
void UniEqlDegFacZp(std::vector<poly_z> & eqlfactorlist,const poly_z & f,mpz_ptr p,uint d,uint & current) { uint n=f.size()-1; if(n==d) { copy_poly_z(eqlfactorlist[current],f); current++; return ; } poly_z g,h; while(1) { UniEqlDegFacZp_Odd(g,f,p,d); if(g.size()>=d)break; } UniEqlDegFacZp(eqlfactorlist,g,p,d,current); UniDivZp(h,f,g,p); UniEqlDegFacZp(eqlfactorlist,h,p,d,current); g.resize(0);h.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 ; }