/** \brief 整系数多项式的容度. \param f 整系数多项式. \param r 整数容度,包含正负号,使得本原部分lc为正整数. */ void UniContZ(mpz_ptr r,const poly_z & f) { if(f.size()==0) { mpz_set_ui(r,1); return ; } mpz_set(r,f[f.size()-1]); if(f.size()==1) { return ; } int sign; sign=mpz_sgn(r); mpz_gcd(r,f[0],f[1]); if(mpz_cmp_ui(r,1)==0) { if(sign<0)mpz_neg(r,r); return ; } for(uint i=2;i<f.size();i++) { mpz_gcd(r,r,f[i]); if(mpz_cmp_ui(r,1)==0) { if(sign<0)mpz_neg(r,r); return ; } } if(sign<0)mpz_neg(r,r); return ; }
bool factor_compare(const poly_z & f,const poly_z & g) { if(f.size()<g.size())return 1; if(f.size()>g.size())return 0; for(size_t i=f.size()-1;i>=0;i--) { if(mpz_cmp(f[i],g[i])<0)return 1; if(mpz_cmp(f[i],g[i])>0)return 0; } return 0; }
/** \brief 整系数多项式本原部分. \param f 整系数多项式. \param r 本原部分. \return 本原部分,其lc为正整数. */ void UniPPZ(poly_z & r,const poly_z & f) { mpz_t a; mpz_init(a); UniContZ(a,f); r.resize(f.size()); for(size_t i=0;i<f.size();i++) { mpz_divexact(r[i],f[i],a); } mpz_clear(a); }
/** \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); }
void poly_z_to_poly_fc(poly_fc & r, poly_z & f) { r.resize(f.size()); for(uint i=0;i<r.size();++i) { mpfc_set_z(r[i],f[i]); } 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 整系数多项式1-范数. \param f 整系数多项式. \return 系数向量的1-范数. */ void UniOneNormZ(mpz_ptr r,const poly_z & f) { mpz_set_ui(r,0); static mpz_t temp; mpz_init(temp); for(int i=0;i<f.size();i++) { mpz_abs(temp,f[i]); mpz_add(r,r,temp); } mpz_clear(temp); }
/** \brief 整系数多项式无穷范数. \param f 整系数多项式. \param r 系数向量的无穷范数. */ void UniMaxNormZ(mpz_ptr r,const poly_z & f) { mpz_set_ui(r,0); mpz_t tempz; mpz_init(tempz); for(int i=0;i<f.size();i++) { mpz_abs(tempz,f[i]); if(mpz_cmp(r,tempz)<0)mpz_set(r,tempz); } mpz_clear(tempz); return ; }
/** \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 ; }
/** \brief 整系数多项式的整数根(不含重数). \param f 整系数多项式. \return 整根的list. \note 利用Zp中的根. */ void UniZRootZ_ByZp(std::vector<mpz_ptr> & rootlist,const poly_z & f) { static mpz_t A,B,p,z_temp,nA; mpz_init(A); mpz_init(B); mpz_init(p); mpz_init(z_temp); mpz_init(nA); UniMaxNormZ(A,f); uint n=f.size()-1; mpz_mul(B,A,A); mpz_add(B,B,A); mpz_mul_ui(B,B,2*n); mpz_add_ui(p,B,1); mpz_nextprime(p,p); poly_z fp,vi,ui; std::vector<mpz_ptr> ulist; uint totalroot=0; UniPolynomialMod(fp,f,p); UniZpRootZp(ulist,fp,p); mpz_mul_ui(nA,A,n); ui.resize(2); mpz_set_ui(ui[1],1); for(uint i=0; i<ulist.size(); i++) { if(mpz_cmpabs(ulist[i],A)<=0) { mpz_neg(ui[0],ulist[i]); UniDivZp(vi,fp,ui,p); UniMaxNormZ(z_temp,vi); if(mpz_cmp(z_temp,nA)<=0) { totalroot++; resize_z_list(rootlist,totalroot); mpz_set(rootlist[totalroot-1],ulist[i]); } } } mpz_clear(A); mpz_clear(B); mpz_clear(p); mpz_clear(z_temp); mpz_clear(nA); fp.resize(0); vi.resize(0); ui.resize(0); resize_z_list(ulist,0); std::sort(rootlist.begin(),rootlist.end(),mpz_ptr_less); 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 ; }
//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 ; }
/** \brief Berlekamp算法. \param f 有限域上多项式.monic \param p characteristic. small prime \param faclist 返回因子list. */ void BerlekampZp_SmallPrime(const poly_z & f,mpz_ptr p,std::vector<poly_z> & faclist) { int n=f.size()-1; clear_poly_z_list(faclist); std::vector<poly_int> basis_int; int k,r; mat_int matq; int p_int=mpz_get_si(p); poly_int f_int; poly_z_to_poly_int(f_int,f); //str("matrix begin").print(); UniPetriMatrixZp_SmallPrime(matq,f_int,p_int); //for(int i=0;i<n;i++) //{ // for(int j=0;j<n;j++) // { // std::cout<<matq[i][j]<<" "; // } // std::cout<<"\n"; //} //str("matrix end").print(); for(int i=0;i<n;i++)matq[i][i]=matq[i][i]-1; NullSpaceZp_SmallPrime(basis_int,matq,n,p_int); //str("nullspace end").print(); r=basis_int.size(); //for(size_t i=0;i<r;i++) //{ // poly_z test; // poly_int_to_poly_z(test,basis_int[i]); // test.print(); //} // mat_int result_int; poly_int bk_int,g_int; int a_int; int r_temp; result_int.push_back(f_int); while(result_int.size()<r) { random::randominteger(k,0,r-1); bk_int=basis_int[k]; random::randominteger(a_int,0,p_int-1); if(bk_int.size()<=1)continue; bk_int[0]-=a_int; r_temp=result_int.size(); for(int i=0;i<r_temp;i++) { UniGcdZp_SmallPrime(g_int,bk_int,result_int[i],p_int); if(g_int.size()>1&&result_int[i].size()>g_int.size()) { UniDivZp_SmallPrime(result_int[i],result_int[i],g_int,p_int); result_int.push_back(g_int); } } } faclist.resize(r); for(size_t i=0;i<r;i++) { poly_int_to_poly_z(faclist[i],result_int[i]); } //str("berlekamp end").print(); }