/* $Id: polarit1.c,v 1.66 2001/10/01 17:19:06 bill Exp $ Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /***********************************************************************/ /** **/ /** ARITHMETIC OPERATIONS ON POLYNOMIALS **/ /** (first part) **/ /** **/ /***********************************************************************/ #include "pari.h" extern GEN get_bas_den(GEN bas); extern GEN get_mul_table(GEN x,GEN bas,GEN invbas,GEN *T); extern GEN pol_to_monic(GEN pol, GEN *lead); /* see splitgen() for how to use these two */ GEN setloop(GEN a) { a=icopy(a); new_chunk(2); /* dummy to get two cells of extra space */ return a; } /* assume a > 0 */ GEN incpos(GEN a) { long i,l=lgefint(a); for (i=l-1; i>1; i--) if (++a[i]) return a; i=l+1; a--; /* use extra cell */ a[0]=evaltyp(1) | evallg(i); a[1]=evalsigne(1) | evallgefint(i); return a; } GEN incloop(GEN a) { long i,l; switch(signe(a)) { case 0: a--; /* use extra cell */ a[0]=evaltyp(t_INT) | evallg(3); a[1]=evalsigne(1) | evallgefint(3); a[2]=1; return a; case -1: l=lgefint(a); for (i=l-1; i>1; i--) if (a[i]--) break; if (a[2] == 0) { a++; /* save one cell */ a[0] = evaltyp(t_INT) | evallg(2); a[1] = evalsigne(0) | evallgefint(2); } return a; default: return incpos(a); } } /*******************************************************************/ /* */ /* DIVISIBILITE */ /* Return 1 if y | x, 0 otherwise */ /* */ /*******************************************************************/ int gdivise(GEN x, GEN y) { long av=avma; x=gmod(x,y); avma=av; return gcmp0(x); } int poldivis(GEN x, GEN y, GEN *z) { long av = avma; GEN p1 = poldivres(x,y,ONLY_DIVIDES); if (p1) { *z = p1; return 1; } avma=av; return 0; } /*******************************************************************/ /* */ /* POLYNOMIAL EUCLIDEAN DIVISION */ /* */ /*******************************************************************/ /* Polynomial division x / y: * if z = ONLY_REM return remainder, otherwise return quotient * if z != NULL set *z to remainder * *z is the last object on stack (and thus can be disposed of with cgiv * instead of gerepile) */ GEN poldivres(GEN x, GEN y, GEN *pr) { ulong avy,av,av1; long ty=typ(y),tx,vx,vy,dx,dy,dz,i,j,sx,lrem; int remainder; GEN z,p1,rem,y_lead,mod; GEN (*f)(GEN,GEN); if (pr == ONLY_DIVIDES_EXACT) { f = gdivexact; pr = ONLY_DIVIDES; } else f = gdiv; if (is_scalar_t(ty)) { if (pr == ONLY_REM) return gzero; if (pr && pr != ONLY_DIVIDES) *pr=gzero; return f(x,y); } tx=typ(x); vy=gvar9(y); if (is_scalar_t(tx) || gvar9(x)>vy) { if (pr == ONLY_REM) return gcopy(x); if (pr == ONLY_DIVIDES) return gcmp0(x)? gzero: NULL; if (pr) *pr=gcopy(x); return gzero; } if (tx!=t_POL || ty!=t_POL) err(typeer,"euclidean division (poldivres)"); vx=varn(x); if (vx=0; dy--) { y_lead = (GEN)y[dy+2]; if (!gcmp0(y_lead)) break; } } if (!dy) /* y is constant */ { if (pr && pr != ONLY_DIVIDES) { if (pr == ONLY_REM) return zeropol(vx); *pr = zeropol(vx); } return f(x, constant_term(y)); } dx=degpol(x); if (vx>vy || dx=dy; i--) { av1=avma; p1=(GEN)x[i]; for (j=i-dy+1; j<=i && j<=dz; j++) if (y[i-j]) p1 = gadd(p1, gmul((GEN)z[j],(GEN)y[i-j])); if (y_lead) p1 = f(p1,y_lead); if (!remainder) p1 = avma==av1? gcopy(p1): gerepileupto(av1,p1); z[i-dy] = (long)p1; } if (!pr) return gerepileupto(av,z-2); rem = (GEN)avma; av1 = (long)new_chunk(dx+3); for (sx=0; ; i--) { p1 = (GEN)x[i]; /* we always enter this loop at least once */ for (j=0; j<=i && j<=dz; j++) if (y[i-j]) p1 = gadd(p1, gmul((GEN)z[j],(GEN)y[i-j])); if (mod && avma==av1) p1 = gmul(p1,mod); if (!gcmp0(p1)) { sx = 1; break; } /* remainder is non-zero */ if (!isinexactreal(p1) && !isexactzero(p1)) break; if (!i) break; avma=av1; } if (pr == ONLY_DIVIDES) { if (sx) { avma=av; return NULL; } avma = (long)rem; return gerepileupto(av,z-2); } lrem=i+3; rem -= lrem; if (avma==av1) { avma = (long)rem; p1 = gcopy(p1); } else p1 = gerepileupto((long)rem,p1); rem[0]=evaltyp(t_POL) | evallg(lrem); rem[1]=evalsigne(1) | evalvarn(vx) | evallgef(lrem); rem += 2; rem[i]=(long)p1; for (i--; i>=0; i--) { av1=avma; p1 = (GEN)x[i]; for (j=0; j<=i && j<=dz; j++) if (y[i-j]) p1 = gadd(p1, gmul((GEN)z[j],(GEN)y[i-j])); if (mod && avma==av1) p1 = gmul(p1,mod); rem[i]=avma==av1? lcopy(p1):lpileupto(av1,p1); } rem -= 2; if (!sx) normalizepol_i(rem, lrem); if (remainder) return gerepileupto(av,rem); z -= 2; { GEN *gptr[2]; gptr[0]=&z; gptr[1]=&rem; gerepilemanysp(av,avy,gptr,2); *pr = rem; return z; } } /*******************************************************************/ /* */ /* ROOTS MODULO a prime p (no multiplicities) */ /* */ /*******************************************************************/ static GEN mod(GEN x, GEN y) { GEN z = cgetg(3,t_INTMOD); z[1]=(long)y; z[2]=(long)x; return z; } static long factmod_init(GEN *F, GEN pp, long *p) { GEN f = *F; long i,d; if (typ(f)!=t_POL || typ(pp)!=t_INT) err(typeer,"factmod"); if (expi(pp) > BITS_IN_LONG - 3) *p = 0; else { *p = itos(pp); if (*p < 2) err(talker,"not a prime in factmod"); } f = gmul(f, mod(gun,pp)); if (!signe(f)) err(zeropoler,"factmod"); f = lift_intern(f); d = lgef(f); for (i=2; i ss[2]); if (nbrac == 1) { avma=av; return cgetg(1,t_COL); } if (nbrac == d && p != ss[2]) { g = mpinvmod((GEN)f[3], pp); setsigne(g,-1); ss = modis(mulii(g, (GEN)f[2]), p); y[nbrac++]=ss[2]; } avma=av; g=cgetg(nbrac,t_COL); if (isonstack(pp)) pp = icopy(pp); for (i=1; i1) y[1] = (long)gmodulsg(0,p); return y; } y = cgetg(n+j,t_COL); if (j>1) { y[1] = zero; n++; } y[j] = (long)FpX_normalize(b,p); if (la) y[j+lb] = (long)FpX_normalize(a,p); pol = gadd(polx[varn(f)], gun); pol0 = constant_term(pol); while (j<=n) { a=(GEN)y[j]; la=degpol(a); if (la==1) y[j++] = lsubii(p, constant_term(a)); else if (la==2) { GEN d = subii(sqri((GEN)a[3]), shifti((GEN)a[2],2)); GEN e = mpsqrtmod(d,p), u = addis(q, 1); /* u = 1/2 */ y[j++] = lmodii(mulii(u,subii(e,(GEN)a[3])), p); y[j++] = lmodii(mulii(u,negi(addii(e,(GEN)a[3]))), p); } else for (pol0[2]=1; ; pol0[2]++) { b = ZX_s_add(FpXQ_pow(pol,q, a,p), -1); /* pol^(p-1)/2 - 1 */ b = FpX_gcd(a,b, p); lb = degpol(b); if (lb && lb 7) timer2(); Q = cgetg(N+1,t_MAT); Q[1] = (long)zerocol(N); w = v = FpXQ_pow(polx[varn(u)],p,u,p); for (j=2; j<=N; j++) { Q[j] = lgetg(N+1,t_COL); p1 = (GEN)Q[j]; d = lgef(w)-1; p2 = w+1; for (i=1; i 7) msgtimer("frobenius"); vker = FpM_ker(Q,p); if (DEBUGLEVEL > 7) msgtimer("kernel"); return vker; } /* f in ZZ[X] and p a prime number. */ long FpX_is_squarefree(GEN f, GEN p) { long av = avma; GEN z; z = FpX_gcd(f,derivpol(f),p); avma = av; return lgef(z)==3; } /* idem * leading term of f must be prime to p. */ /* Compute the number of roots in Fp without counting multiplicity * return -1 for 0 polynomial. */ long FpX_nbroots(GEN f, GEN p) { long av = avma, n=lgef(f); GEN z; if (n <= 4) return n-3; f = FpX_red(f, p); z = FpXQ_pow(polx[varn(f)], p, f, p); z = FpX_sub(z,polx[varn(f)],NULL); z = FpX_gcd(z,f,p), avma = av; return degpol(z); } long FpX_is_totally_split(GEN f, GEN p) { long av = avma, n=lgef(f); GEN z; if (n <= 4) return 1; if (!is_bigint(p) && n-3 > p[2]) return 0; f = FpX_red(f, p); z = FpXQ_pow(polx[varn(f)], p, f, p); avma = av; return lgef(z)==4 && gcmp1((GEN)z[3]) && !signe(z[2]); } /* u in ZZ[X] and p a prime number. * u must be squarefree mod p. * leading term of u must be prime to p. */ long FpX_nbfact(GEN u, GEN p) { ulong av = avma; GEN vker = Berlekamp_ker(u,p); avma = av; return lg(vker)-1; } /* Please use only use this function when you it is false, or that there is a * lot of factors. If you believe f is irreducible or that it has few factors, * then use `FpX_nbfact(f,p)==1' instead (faster). */ static GEN factcantor0(GEN f, GEN pp, long flag); long FpX_is_irred(GEN f, GEN p) { return !!factcantor0(f,p,2); } static GEN modulo; static GEN gsmul(GEN a,GEN b){return FpX_mul(a,b,modulo);} GEN FpV_roots_to_pol(GEN V, GEN p, long v) { ulong ltop=avma; long i; GEN g=cgetg(lg(V),t_VEC); for(i=1;i 1; j--) { GEN p2 = (GEN)p1[j]; if (typ(p2) == t_INTMOD) p2[1] = (long)p; } } } static GEN try_pow(GEN w0, GEN pol, GEN p, GEN q, long r) { GEN w2, w = FpXQ_pow(w0,q, pol,p); long s; if (gcmp1(w)) return w0; for (s=1; s 0 */ static GEN init_pow_p_mod_pT(GEN p, GEN T) { long i, n = degpol(T), v = varn(T); GEN p1, S = cgetg(n, t_VEC); if (n == 1) return S; S[1] = (long)FpXQ_pow(polx[v], p, T, p); /* use as many squarings as possible */ for (i=2; i < n; i+=2) { p1 = gsqr((GEN)S[i>>1]); S[i] = (long)FpX_res(p1, T, p); if (i == n-1) break; p1 = gmul((GEN)S[i], (GEN)S[1]); S[i+1] = (long)FpX_res(p1, T, p); } return S; } /* compute x^p, S is as above */ static GEN spec_FpXQ_pow(GEN x, GEN p, GEN S) { long av = avma, lim = stack_lim(av,1), i,dx = degpol(x); GEN x0 = x+2, z; z = (GEN)x0[0]; if (dx < 0) err(talker, "zero polynomial in FpXQ_pow. %Z not prime", p); for (i = 1; i <= dx; i++) { GEN d, c = (GEN)x0[i]; /* assume coeffs in [0, p-1] */ if (!signe(c)) continue; d = (GEN)S[i]; if (!gcmp1(c)) d = gmul(c,d); z = gadd(z, d); if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) err(warnmem,"spec_FpXQ_pow"); z = gerepileupto(av, z); } } z = FpX_red(z, p); return gerepileupto(av, z); } /* factor f mod pp. * If (flag = 1) return the degrees, not the factors * If (flag = 2) return NULL if f is not irreducible */ static GEN factcantor0(GEN f, GEN pp, long flag) { long i,j,k,d,e,vf,p,nbfact,tetpil,av = avma; GEN ex,y,f2,g,g1,u,v,pd,q; GEN *t; if (!(d = factmod_init(&f, pp, &p))) { avma=av; return trivfact(); } /* to hold factors and exponents */ t = (GEN*)cgetg(d+1,t_VEC); ex = new_chunk(d+1); vf=varn(f); e = nbfact = 1; for(;;) { f2 = FpX_gcd(f,derivpol(f), pp); if (flag > 1 && lgef(f2) > 3) return NULL; g1 = FpX_div(f,f2,pp); k = 0; while (lgef(g1)>3) { long du,dg; GEN S; k++; if (p && !(k%p)) { k++; f2 = FpX_div(f2,g1,pp); } u = g1; g1 = FpX_gcd(f2,g1, pp); if (lgef(g1)>3) { u = FpX_div( u,g1,pp); f2= FpX_div(f2,g1,pp); } du = degpol(u); if (du <= 0) continue; /* here u is square-free (product of irred. of multiplicity e * k) */ S = init_pow_p_mod_pT(pp, u); pd=gun; v=polx[vf]; for (d=1; d <= du>>1; d++) { if (!flag) pd = mulii(pd,pp); v = spec_FpXQ_pow(v, pp, S); g = FpX_gcd(gadd(v, gneg(polx[vf])), u, pp); dg = degpol(g); if (dg <= 0) continue; /* Ici g est produit de pol irred ayant tous le meme degre d; */ j=nbfact+dg/d; if (flag) { if (flag > 1) return NULL; for ( ; nbfact X) pour faire pgcd de g avec * w^(p^d-1)/2 jusqu'a casser. p = 2 is treated separately. */ if (p) split(p,t+nbfact,d,pp,q,r,S); else splitgen(pp,t+nbfact,d,pp,q,r); for (; nbfact 1) { avma = av; return gun; } /* irreducible */ tetpil=avma; y=cgetg(3,t_MAT); if (!flag) { y[1]=(long)t; setlg(t, nbfact); y[2]=(long)ex; (void)sort_factor(y,cmpii); } u=cgetg(nbfact,t_COL); y[1]=(long)u; v=cgetg(nbfact,t_COL); y[2]=(long)v; if (flag) for (j=1; j1 && !x[i]); if (i==1) setsigne(x,0); else { setsigne(x,1); setlgef(x,i+1); } } long split_berlekamp(GEN *t, GEN pp, GEN pps2) { GEN u = *t, p1, p2, vker,pol; long av,N = degpol(u), d,i,kk,l1,l2,p, vu = varn(u); ulong av0 = avma; vker = Berlekamp_ker(u,pp); vker = mat_to_vecpol(vker,vu); d = lg(vker)-1; p = is_bigint(pp)? 0: pp[2]; if (p) { avma = av0; p1 = cgetg(d+1, t_VEC); /* hack: hidden gerepile */ for (i=1; i<=d; i++) p1[i] = (long)pol_to_small((GEN)vker[i]); vker = p1; } pol = cgetg(N+3,t_POL); for (kk=1; kk1) { av = avma; p2 = FpX_res(polt, p1, pp); if (lgef(p2) <= 3) { avma=av; continue; } p2 = FpXQ_pow(p2,pps2, p1,pp); if (!signe(p2)) err(talker,"%Z not a prime in split_berlekamp",pp); p2 = ZX_s_add(p2, -1); p2 = FpX_gcd(p1,p2, pp); l2=degpol(p2); if (l2>0 && l2 7) msgtimer("new factor"); } else avma = av; } } } return d; } GEN factmod0(GEN f, GEN pp) { long i,j,k,e,p,N,nbfact,av = avma,tetpil,d; GEN pps2,ex,y,f2,p1,g1,u, *t; if (!(d = factmod_init(&f, pp, &p))) { avma=av; return trivfact(); } /* to hold factors and exponents */ t = (GEN*)cgetg(d+1,t_VEC); ex = cgetg(d+1,t_VECSMALL); e = nbfact = 1; pps2 = shifti(pp,-1); for(;;) { f2 = FpX_gcd(f,derivpol(f), pp); g1 = lgef(f2)==3? f: FpX_div(f,f2,pp); k = 0; while (lgef(g1)>3) { k++; if (p && !(k%p)) { k++; f2 = FpX_div(f2,g1,pp); } p1 = FpX_gcd(f2,g1, pp); u = g1; g1 = p1; if (lgef(p1)!=3) { u = FpX_div( u,p1,pp); f2= FpX_div(f2,p1,pp); } N = degpol(u); if (N) { /* here u is square-free (product of irred. of multiplicity e * k) */ t[nbfact] = FpX_normalize(u,pp); d = (N==1)? 1: split_berlekamp(t+nbfact, pp, pps2); for (j=0; j= precp(x) + v) return invlead? gmul(x, invlead): gcopy(x); sx = !gcmp0(x); p1 = (GEN)x[4]; } else { sx = signe(x); if (!sx) return gzero; v = pvaluation(x,p,&p1); } y = cgetg(5,t_PADIC); if (sx && v < r) { y[4] = lmodii(p1,pr); r -= v; } else { y[4] = zero; v = r; r = 0; } y[3] = (long)pr; y[2] = (long)p; y[1] = evalprecp(r)|evalvalp(v); return invlead? gerepileupto(av, gmul(invlead,y)): y; } /* return (x + O(p^r)) normalized (multiply by a unit such that leading coeff * is a power of p), x in Z[X] (or Z_p[X]) */ static GEN pol_to_padic(GEN x, GEN pr, GEN p, long r) { long v = 0,i,lx = lgef(x); GEN z = cgetg(lx,t_POL), lead = leading_term(x); if (gcmp1(lead)) lead = NULL; else { long av = avma; v = ggval(lead,p); if (v) lead = gdiv(lead, gpowgs(p,v)); lead = int_to_padic(lead,p,pr,r,NULL); lead = gerepileupto(av, ginv(lead)); } for (i=lx-1; i>1; i--) z[i] = (long)int_to_padic((GEN)x[i],p,pr,r,lead); z[1] = x[1]; return z; } static GEN padic_trivfact(GEN x, GEN p, long r) { GEN p1, y = cgetg(3,t_MAT); p1=cgetg(2,t_COL); y[1]=(long)p1; p = icopy(p); p1[1]=(long)pol_to_padic(x,gpowgs(p,r),p,r); p1=cgetg(2,t_COL); y[2]=(long)p1; p1[1]=un; return y; } /* a etant un p-adique, retourne le vecteur des racines p-adiques de f * congrues a a modulo p dans le cas ou on suppose f(a) congru a 0 modulo p * (ou a 4 si p=2). */ GEN apprgen(GEN f, GEN a) { GEN fp,p1,p,P,pro,x,x2,u,ip; long av=avma,tetpil,v,Ps,i,j,k,lu,n,fl2; if (typ(f)!=t_POL) err(notpoler,"apprgen"); if (gcmp0(f)) err(zeropoler,"apprgen"); if (typ(a) != t_PADIC) err(rootper1); f = padic_pol_to_int(f); fp=derivpol(f); p1=ggcd(f,fp); if (lgef(p1)>3) { f=gdeuc(f,p1); fp=derivpol(f); } p=(GEN)a[2]; p1=poleval(f,a); v=ggval(p1,p); if (v <= 0) err(rootper2); fl2=egalii(p,gdeux); if (fl2 && v==1) err(rootper2); v=ggval(poleval(fp,a),p); if (!v) /* simple zero */ { while (!gcmp0(p1)) { a = gsub(a,gdiv(p1,poleval(fp,a))); p1 = poleval(f,a); } tetpil=avma; pro=cgetg(2,t_VEC); pro[1]=lcopy(a); return gerepile(av,tetpil,pro); } n=degpol(f); pro=cgetg(n+1,t_VEC); if (is_bigint(p)) err(impl,"apprgen for p>=2^31"); x = ggrandocp(p, valp(a) | precp(a)); if (fl2) { x2=ggrandocp(p,2); P = stoi(4); } else { x2=ggrandocp(p,1); P = p; } f = poleval(f, gadd(a,gmul(P,polx[varn(f)]))); if (!gcmp0(f)) f = gdiv(f,gpuigs(p,ggval(f, p))); Ps = itos(P); for (j=0,i=0; i3) { f=gdeuc(f,p1); fp=derivpol(f); } fl2=egalii(p,gdeux); rac=(fl2 && r>=2)? rootmod(f,stoi(4)): rootmod(f,p); lx=lg(rac); p=gclone(p); if (r==1) { tetpil=avma; y=cgetg(lx,t_COL); for (i=1; i>1)+(a&1); if (a==1) break; } *pmask=mask>>j; return BITS_IN_LONG-j; } /* SPEC: q is an integer > 1 e>=0 f in ZZ[X], with leading term prime to q. S must be a simple root mod p for all p|q. return roots of f mod q^e, as integers (implicitly mod Q) */ /* STANDARD USE There exists p a prime number and a>0 such that q=p^a f in ZZ[X], with leading term prime to p. S must be a simple root mod p. return p-adics roots of f with prec b, as integers (implicitly mod q^e) */ GEN rootpadiclift(GEN T, GEN S, GEN p, long e) { ulong ltop=avma; long x; GEN qold, q, qm1; GEN W, Tr, Sr, Wr = gzero; long i, nb, mask; x = varn(T); qold = p ; q = p; qm1 = gun; nb=hensel_lift_accel(e, &mask); Tr = FpX_red(T,q); W=FpX_eval(deriv(Tr, x),S,q); W=mpinvmod(W,q); for(i=0;itotally split-->use trace trick */ { ulong av=avma; GEN z; z=(GEN)f[lgef(f)-2];/*-trace(roots)*/ for(i=1; i1; i--) { p1=(GEN)x[i]; if (typ(p1)==t_PADIC) { e=valp(p1); if (signe(p1[4])) e += precp(p1); if (e3) { f=gdeuc(f,p1); fp=derivpol(f); } t=(GEN)a[1]; prec = getprec((GEN)a[2], BIGINT, &p); prec = getprec(t, prec, &p); if (prec==BIGINT) err(rootper1); p1=poleval(f,a); v=ggval(lift_intern(p1),p); if (v<=0) err(rootper2); fl2=egalii(p,gdeux); if (fl2 && v==1) err(rootper2); v=ggval(lift_intern(poleval(fp,a)), p); if (!v) { while (!gcmp0(p1)) { a = gsub(a, gdiv(p1,poleval(fp,a))); p1 = poleval(f,a); } tetpil=avma; pro=cgetg(2,t_COL); pro[1]=lcopy(a); return gerepile(av,tetpil,pro); } n=degpol(f); pro=cgetg(n+1,t_COL); j=0; if (is_bigint(p)) err(impl,"apprgen9 for p>=2^31"); x=gmodulcp(ggrandocp(p,prec), t); if (fl2) { ps_1=3; x2=ggrandocp(p,2); p=stoi(4); } else { ps_1=itos(p)-1; x2=ggrandocp(p,1); } f = poleval(f,gadd(a,gmul(p,polx[varn(f)]))); if (!gcmp0(f)) f=gdiv(f,gpuigs(p,ggval(f,p))); d=degpol(t); vecg=cgetg(d+1,t_COL); for (i=1; i<=d; i++) vecg[i] = (long)setloop(gzero); va=varn(t); for(;;) /* loop through F_q */ { ip=gmodulcp(gtopoly(vecg,va),t); if (gcmp0(poleval(f,gadd(ip,x2)))) { u=apprgen9(f,gadd(ip,x)); lu=lg(u); for (k=1; k vy) return -1; return cmpii((GEN)x[4], (GEN)y[4]); } /* factorise le polynome T=nf[1] dans Zp avec la precision pr */ static GEN padicff2(GEN nf,GEN p,long pr) { long N=degpol(nf[1]),i,j,d,l; GEN mat,V,D,fa,p1,pk,dec_p,pke,a,theta; pk=gpuigs(p,pr); dec_p=primedec(nf,p); l=lg(dec_p); fa=cgetg(l,t_COL); for (i=1; i3) ? padicff(res,p,r) : cgetg(1,t_COL); nbfac += (lg(fa[j])-1); } av2=avma; y=cgetg(3,t_MAT); p1=cgetg(nbfac+1,t_COL); y[1]=(long)p1; p2=cgetg(nbfac+1,t_COL); y[2]=(long)p2; for (i=1,k=0; i<=j; i++) for (i1=1; i13); setlg(A,i); *ex=B; return A; } #define swap(x,y) { long _t=x; x=y; y=_t; } /* reverse x in place */ static void polreverse(GEN x) { long i, j; if (typ(x) != t_POL) err(typeer,"polreverse"); for (i=2, j=lgef(x)-1; i1; i--) { p1 = (GEN)mod[i]; if (typ(p1) == t_POLMOD) { pol = (GEN)p1[1] ; break; } } if (!pol) err(talker,"need POLMOD coeffs in Kronecker_powmod"); for (i=lgef(pol)-1; i>1; i--) { p1 = (GEN)pol[i]; if (typ(p1) == t_INTMOD) { p = (GEN)p1[1] ; break; } } if (!p) err(talker,"need Fq coeffs in Kronecker_powmod"); x = lift_intern(to_Kronecker(x,pol)); /* adapted from powgi */ av=avma; lim=stack_lim(av,1); p1 = n+2; m = *p1; y=x; j=1+bfffo(m); m<<=j; j = BITS_IN_LONG-j; for (i=lgefint(n)-2;;) { for (; j; m<<=1,j--) { y = gsqr(y); y = from_Kronecker(FpX(y,p), pol); setvarn(y, v); y = gres(y, mod); y = lift_intern(to_Kronecker(y,pol)); if (m<0) { y = gmul(y,x); y = from_Kronecker(FpX(y,p), pol); setvarn(y, v); y = gres(y, mod); y = lift_intern(to_Kronecker(y,pol)); } if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) err(warnmem,"Kronecker_powmod"); y = gerepilecopy(av, y); } } if (--i == 0) break; m = *++p1, j = BITS_IN_LONG; } y = from_Kronecker(FpX(y,p),pol); setvarn(y, v); return gerepileupto(av0, y); } GEN FpX_rand(long d1, long v, GEN p) { long i, d = d1+2; GEN y; y = cgetg(d,t_POL); y[1] = evalsigne(1) | evalvarn(v); for (i=2; i 6) timer2(); av = avma; is2 = egalii(p, gdeux); for(cnt = 1;;cnt++) { /* splits *t with probability ~ 1 - 2^(1-r) */ w = w0 = FqX_rand(dt,v, p,a); for (l=1; l 6) fprintferr("[split9] time for splitting: %ld (%ld trials)\n",timer2(),cnt); l /= d; t[l]=gdeuc(*t,w); *t=w; split9(t+l,d,p,q,a,S); split9(t ,d,p,q,a,S); } /* to "compare" (real) scalars and t_INTMODs */ static int cmp_coeff(GEN x, GEN y) { if (typ(x) == t_INTMOD) x = (GEN)x[2]; if (typ(y) == t_INTMOD) y = (GEN)y[2]; return gcmp(x,y); } int cmp_pol(GEN x, GEN y) { long fx[3], fy[3]; long i,lx,ly; int fl; if (typ(x) == t_POLMOD) x = (GEN)x[2]; if (typ(y) == t_POLMOD) y = (GEN)y[2]; if (typ(x) == t_POL) lx = lgef(x); else { lx = 3; fx[2] = (long)x; x = fx; } if (typ(y) == t_POL) ly = lgef(y); else { ly = 3; fy[2] = (long)y; y = fy; } if (lx > ly) return 1; if (lx < ly) return -1; for (i=lx-1; i>1; i--) if ((fl = cmp_coeff((GEN)x[i], (GEN)y[i]))) return fl; return 0; } /* assume n > 1, X a POLMOD over Fq */ /* return S = [ X^q, X^2q, ... X^(n-1)q ] mod T (in Fq[X]) in Kronecker form */ static GEN init_pow_q_mod_pT(GEN Xmod, GEN q, GEN a, GEN T) { long i, n = degpol(T); GEN p1, S = cgetg(n, t_VEC); S[1] = (long)Kronecker_powmod((GEN)Xmod[2], (GEN)Xmod[1], q); #if 1 /* use as many squarings as possible */ for (i=2; i < n; i+=2) { p1 = gsqr((GEN)S[i>>1]); S[i] = lres(p1, T); if (i == n-1) break; p1 = gmul((GEN)S[i], (GEN)S[1]); S[i+1] = lres(p1, T); } #else for (i=2; i < n; i++) { p1 = gmul((GEN)S[i-1], (GEN)S[1]); S[i] = lres(p1, T); } #endif for (i=1; i < n; i++) S[i] = (long)lift_intern(to_Kronecker((GEN)S[i], a)); return S; } /* compute x^q, S is as above */ static GEN spec_Fq_pow_mod_pol(GEN x, GEN p, GEN a, GEN S) { long av = avma, lim = stack_lim(av,1), i,dx = degpol(x); GEN x0 = x+2, z,c; c = (GEN)x0[0]; z = lift_intern(lift(c)); for (i = 1; i <= dx; i++) { GEN d; c = (GEN)x0[i]; if (gcmp0(c)) continue; d = (GEN)S[i]; if (!gcmp1(c)) d = gmul(lift_intern(lift(c)),d); z = gadd(z, d); if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) err(warnmem,"spec_Fq_pow_mod_pol"); z = gerepileupto(av, z); } } z = FpX(z, p); z = from_Kronecker(z, a); setvarn(z, varn(x)); return gerepileupto(av, z); } static long isabsolutepol(GEN f, GEN pp, GEN a) { int i,res=1; GEN c; for(i=2; i0) res = 0; break; case t_POL: isabsolutepol(c,pp,gzero); if (degpol(c)>0) res = 0; break; default: err(typeer,"factmod9"); } } return res; } GEN factmod9(GEN f, GEN pp, GEN a) { long av = avma, tetpil,p,i,j,k,d,e,vf,va,nbfact,nbf,pk; GEN S,ex,y,f2,f3,df1,df2,g,g1,xmod,u,v,qqd,qq,unfp,unfq, *t; GEN frobinv,X; if (typ(a)!=t_POL || typ(f)!=t_POL || gcmp0(a)) err(typeer,"factmod9"); vf=varn(f); va=varn(a); if (va<=vf) err(talker,"polynomial variable must be of higher priority than finite field\nvariable in factorff"); if (isabsolutepol(f, pp, a)) { GEN z= Fp_factor_rel0(simplify(lift(lift(f))), pp, lift(a)); GEN t=(GEN)z[1],ex=(GEN)z[2]; unfp = gmodulsg(1,pp); unfq = gmodulcp(gmul(unfp, polun[va]), gmul(unfp,a)); nbfact=lg(t); tetpil=avma; y=cgetg(3,t_MAT); u=cgetg(nbfact,t_COL); y[1]=(long)u; v=cgetg(nbfact,t_COL); y[2]=(long)v; for (j=1; j= pp: p = 0 can't happen */ pk *= p; e=pk; j=(degpol(f))/p+3; setlg(f,j); setlgef(f,j); for (i=2; i 1) S = init_pow_q_mod_pT(xmod, qq, a, u); for (d=1; d <= du>>1; d++) { qqd=mulii(qqd,qq); v = spec_Fq_pow_mod_pol(v, pp, a, S); g = ggcd(gsub(v,X),u); dg = degpol(g); if (dg <= 0) continue; /* all factors of g have degree d */ j = nbfact+dg/d; t[nbfact] = g; split9(t+nbfact,d,pp,qq,a,S); for (; nbfact0) g=0; } else if (ti != t_INT && ti != t_INTMOD && !is_frac_t(ti)) g=0; } l1=avma; p2=cgetg(3,t_COMPLEX); p2[1]=lmppi(DEFAULTPREC); p2[2]=ldivrs((GEN)p2[1],10); p11=cgetg(4,t_POL); p11[1]=evalsigne(1)+evallgef(4); setvarn(p11,v); p11[3]=un; p12=cgetg(5,t_POL); p12[1]=evalsigne(1)+evallgef(5); setvarn(p12,v); p12[4]=un; for (i=2; i<=deg0+2 && gcmp0((GEN)x[i]); i++) gaffsg(0,(GEN)y[i-1]); k=i-2; if (k!=deg0) { if (k) { j=deg0+3-k; pax=cgetg(j,t_POL); pax[1] = evalsigne(1) | evalvarn(v) | evallgef(j); for (i=2; iemax) emax=e1; } e=emax-e; if (e<0) e=0; avma=l3; if (ps!=pax) xd0=deriv(ps,v); xdabs=cgetg(deg+2,t_POL); xdabs[1]=xd0[1]; for (i=2; i= -20) { p7 = gneg_i(gdiv(p4, poleval(xd,p3))); l3 = avma; if (gcmp0(p5)) exc = -32; else exc = expo(gnorm(p7))-expo(gnorm(p3)); avma = l3; for (j=1; j<=10; j++) { p8=gadd(p3,p7); p9=poleval(xc,p8); p10=gnorm(p9); if (exc < -20 || cmprr(p10,p5) < 0) { GEN *gptr[3]; p3=p8; p4=p9; p5=p10; gptr[0]=&p3; gptr[1]=&p4; gptr[2]=&p5; gerepilemanysp(l2,l3,gptr,3); break; } gshiftz(p7,-2,p7); avma=l3; } if (j > 10) { avma=av1; if (DEBUGLEVEL) { fprintferr("too many iterations in rootsold(): "); fprintferr("using roots2()\n"); flusherr(); } return roots2(x,l); } } p1=(GEN)y[k+m*i]; setlg(p1[1],3); setlg(p1[2],3); gaffect(p3,p1); avma=l2; p14=(GEN)p1[1]; p15=(GEN)p1[2]; for (ln=4; ln<=l; ln=(ln<<1)-2) { setlg(p14,ln); setlg(p15,ln); if (gcmp0(p14)) { settyp(p14,t_INT); p14[1]=2; } if (gcmp0(p15)) { settyp(p15,t_INT); p15[1]=2; } p4=poleval(xc,p1); p5=poleval(xd,p1); p6=gneg_i(gdiv(p4,p5)); settyp(p14,t_REAL); settyp(p15,t_REAL); gaffect(gadd(p1,p6),p1); avma=l2; } } setlg(p14,l); setlg(p15,l); p7=gcopy(p1); p14=(GEN)(p7[1]); p15=(GEN)(p7[2]); setlg(p14,l+1); setlg(p15,l+1); if (gcmp0(p14)) { settyp(p14,t_INT); p14[1]=2; } if (gcmp0(p15)) { settyp(p15,t_INT); p15[1]=2; } for (ii=1; ii<=5; ii++) { p4=poleval(ps,p7); p5=poleval(xd0,p7); p6=gneg_i(gdiv(p4,p5)); p7=gadd(p7,p6); p14=(GEN)(p7[1]); p15=(GEN)(p7[2]); if (gcmp0(p14)) { settyp(p14,t_INT); p14[1]=2; } if (gcmp0(p15)) { settyp(p15,t_INT); p15[1]=2; } } gaffect(p7,p1); p4=poleval(ps,p7); p6=gdiv(p4,poleval(xdabs,gabs(p7,l))); if (gexpo(p6)>=expmin) { avma=av1; if (DEBUGLEVEL) { fprintferr("internal error in rootsold(): using roots2()\n"); flusherr(); } return roots2(x,l); } avma=l2; if (expo(p1[2])=1; k--) { p2 = (GEN)y[k]; if (gcmp0((GEN)p2[2])) f=0; else f=1; if (f0)? 0 : 1; } } rr=cgetg(N+1,t_COL); for (i=1; i<=N; i++) { p1 = cgetc(PREC); rr[i] = (long)p1; for (j=3; j=1; j--) { x=gzero; flagrealrac=0; if (j==1) x=gneg_i(gdiv((GEN)qolbis[2],(GEN)qolbis[3])); else { x=laguer(qolbis,j,x,EPS,PREC); if (x == NULL) goto RLAB; } if (flagexactpol) { x=gprec(x,(long)((PREC-1)*pariK)); x=laguer(qol,deg,x,gmul2n(EPS,-32),PREC+1); } else x=laguer(qol,deg,x,EPS,PREC); if (x == NULL) goto RLAB; if (typ(x)==t_COMPLEX && gcmp(gabs(gimag(x),PREC),gmul2n(gmul(EPS,gabs(greal(x),PREC)),1))<=0) { x[2]=zero; flagrealrac=1; } else if (j==1 && flagrealpol) { x[2]=zero; flagrealrac=1; } else if (typ(x)!=t_COMPLEX) flagrealrac=1; for (i=1; i<=multiqol; i++) gaffect(x,(GEN)rr[nbroot+i]); nbroot+=multiqol; if (!flagrealpol || flagrealrac) { ad = (GEN*) new_chunk(j+1); for (i=0; i<=j; i++) ad[i]=(GEN)qolbis[i+2]; b=(GEN)ad[j]; for (i=j-1; i>=0; i--) { c=(GEN)ad[i]; ad[i]=b; b=gadd(gmul((GEN)rr[nbroot],b),c); } v=cgetg(j+1,t_VEC); for (i=1; i<=j; i++) v[i]=(long)ad[j-i]; qolbis=gtopoly(v,varn(qolbis)); if (flagrealpol) for (i=2; i<=j+1; i++) if (typ(qolbis[i])==t_COMPLEX) mael(qolbis,i,2)=zero; } else { ad = (GEN*) new_chunk(j-1); ad[j-2]=(GEN)qolbis[j+2]; p1=gmulsg(2,greal((GEN)rr[nbroot])); p2=gnorm((GEN)rr[nbroot]); ad[j-3]=gadd((GEN)qolbis[j+1],gmul(p1,ad[j-2])); for (i=j-2; i>=2; i--) ad[i-2] = gadd((GEN)qolbis[i+2],gsub(gmul(p1,ad[i-1]),gmul(p2,ad[i]))); v=cgetg(j,t_VEC); for (i=1; i<=j-1; i++) v[i]=(long)ad[j-1-i]; qolbis=gtopoly(v,varn(qolbis)); for (i=2; i<=j; i++) if (typ(qolbis[i])==t_COMPLEX) mael(qolbis,i,2)=zero; for (i=1; i<=multiqol; i++) gaffect(gconj((GEN)rr[nbroot]), (GEN)rr[nbroot+i]); nbroot+=multiqol; j--; } } avma=av1; } for (j=2; j<=N; j++) { x=(GEN)rr[j]; if (gcmp0((GEN)x[2])) fr=0; else fr=1; for (i=j-1; i>=1; i--) { if (gcmp0(gmael(rr,i,2))) f=0; else f=1; if (f=0; j--) { f=gadd(gmul(x,f),d); d=gadd(gmul(x,d),b); b=gadd(gmul(x,b),(GEN)pol[j+2]); erre=gadd(QuickNormL1(b,PREC),gmul(abx,erre)); } erre=gmul(erre,EPS); if (gcmp(QuickNormL1(b,PREC),erre)<=0) { gaffect(x,rac); avma = av1; return rac; } g=gdiv(d,b); g2=gsqr(g); h=gsub(g2, gmul2n(gdiv(f,b),1)); sq=gsqrt(gmulsg(N-1,gsub(gmulsg(N,h),g2)),PREC); gp=gadd(g,sq); gm=gsub(g,sq); abp=gnorm(gp); abm=gnorm(gm); if (gcmp(abp,abm)<0) gp=gcopy(gm); if (gsigne(gmax(abp,abm))==1) dx = gdivsg(N,gp); else dx = gmul(gadd(gun,abx),gexp(gmulgs(I,iter),PREC)); x1=gsub(x,dx); if (gcmp(QuickNormL1(gsub(x,x1),PREC),EPS)<0) { gaffect(x,rac); avma = av1; return rac; } if (iter%MT) x=gcopy(x1); else x=gsub(x,gmul(ffrac[iter/MT],dx)); } avma=av; return NULL; } #undef MR #undef MT /***********************************************************************/ /** **/ /** ROOTS of a polynomial with REAL coeffs **/ /** **/ /***********************************************************************/ #define RADIX 1L #define COF 0.95 /* ONLY FOR REAL COEFFICIENTS MATRIX : replace the matrix x with a symmetric matrix a with the same eigenvalues */ static GEN balanc(GEN x) { ulong av = avma; long last,i,j, sqrdx = (RADIX<<1), n = lg(x); GEN r,c,cofgen,a; a = dummycopy(x); last = 0; cofgen = dbltor(COF); while (!last) { last = 1; for (i=1; i 0) {ex--; c=gmul2n(c,-sqrdx);} if (gcmp(gadd(c,r), gmul2n(s,ex)) < 0) { last = 0; for (j=1; j=0.0 ? fabs(a) : -fabs(a)) static GEN hqr(GEN mat) /* find all the eigenvalues of the matrix mat */ { long nn,n,m,l,k,j,its,i,mmin,flj,flk; double **a,p,q,r,s,t,u,v,w,x,y,z,anorm,*wr,*wi; const double eps = 0.000001; GEN eig; n=lg(mat)-1; a=(double**)gpmalloc(sizeof(double*)*(n+1)); for (i=1; i<=n; i++) a[i]=(double*)gpmalloc(sizeof(double)*(n+1)); for (j=1; j<=n; j++) for (i=1; i<=n; i++) a[i][j]=gtodouble((GEN)((GEN)mat[j])[i]); wr=(double*)gpmalloc(sizeof(double)*(n+1)); wi=(double*)gpmalloc(sizeof(double)*(n+1)); anorm=fabs(a[1][1]); for (i=2; i<=n; i++) for (j=(i-1); j<=n; j++) anorm+=fabs(a[i][j]); nn=n; t=0.0; if (DEBUGLEVEL>3) { fprintferr("* Finding eigenvalues\n"); flusherr(); } while (nn>=1) { its=0; do { for (l=nn; l>=2; l--) { s=fabs(a[l-1][l-1])+fabs(a[l][l]); if (s==0.0) s=anorm; if ((double)(fabs(a[l][l-1])+s)==s) break; } x=a[nn][nn]; if (l==nn){ wr[nn]=x+t; wi[nn--]=0.0; } else { y=a[nn-1][nn-1]; w=a[nn][nn-1]*a[nn-1][nn]; if (l == nn-1) { p=0.5*(y-x); q=p*p+w; z=sqrt(fabs(q)); x+=t; if (q>=0.0 || fabs(q)<=eps) { z=p+SIGN(z,p); wr[nn-1]=wr[nn]=x+z; if (fabs(z)>eps) wr[nn]=x-w/z; wi[nn-1]=wi[nn]=0.0; } else{ wr[nn-1]=wr[nn]=x+p; wi[nn-1]=-(wi[nn]=z); } nn-=2; } else { p = q = r = 0.0; /* for lint */ if (its==30) err(talker,"too many iterations in hqr"); if (its==10 || its==20) { t+=x; for (i=1; i<=nn; i++) a[i][i]-=x; s = fabs(a[nn][nn-1]) + fabs(a[nn-1][nn-2]); y=x=0.75*s; w=-0.4375*s*s; } its++; for (m=nn-2; m>=l; m--) { z=a[m][m]; r=x-z; s=y-z; p=(r*s-w)/a[m+1][m]+a[m][m+1]; q=a[m+1][m+1]-z-r-s; r=a[m+2][m+1]; s=fabs(p)+fabs(q)+fabs(r); p/=s; q/=s; r/=s; if (m==l) break; u=fabs(a[m][m-1])*(fabs(q)+fabs(r)); v=fabs(p)*(fabs(a[m-1][m-1])+fabs(z)+fabs(a[m+1][m+1])); if ((double)(u+v)==v) break; } for (i=m+2; i<=nn; i++){ a[i][i-2]=0.0; if (i!=(m+2)) a[i][i-3]=0.0; } for (k=m; k<=nn-1; k++) { if (k!=m) { p=a[k][k-1]; q=a[k+1][k-1]; r = (k != nn-1)? a[k+2][k-1]: 0.0; x = fabs(p)+fabs(q)+fabs(r); if (x != 0.0) { p/=x; q/=x; r/=x; } } s = SIGN(sqrt(p*p+q*q+r*r),p); if (s == 0.0) continue; if (k==m) { if (l!=m) a[k][k-1] = -a[k][k-1]; } else a[k][k-1] = -s*x; p+=s; x=p/s; y=q/s; z=r/s; q/=p; r/=p; for (j=k; j<=nn; j++) { p = a[k][j]+q*a[k+1][j]; if (k != nn-1) { p+=r*a[k+2][j]; a[k+2][j]-=p*z; } a[k+1][j] -= p*y; a[k][j] -= p*x; } mmin = (nn < k+3)? nn: k+3; for (i=l; i<=mmin; i++) { p = x*a[i][k]+y*a[i][k+1]; if (k != nn-1) { p+=z*a[i][k+2]; a[i][k+2]-=p*r; } a[i][k+1] -= p*q; a[i][k] -= p; } } } } } while (l=1; k--) { if (wi[k]) flk=1; else flk=0; if (flk0) break; wr[k+1]=wr[k]; wi[k+1]=wi[k]; } wr[k+1]=x; wi[k+1]=y; } if (DEBUGLEVEL>3) { fprintferr("* Eigenvalues computed\n"); flusherr(); } for (i=1; i<=n; i++) free(a[i]); free(a); eig=cgetg(n+1,t_COL); for (i=1; i<=n; i++) { if (wi[i]) { GEN p1 = cgetg(3,t_COMPLEX); eig[i]=(long)p1; p1[1]=(long)dbltor(wr[i]); p1[2]=(long)dbltor(wi[i]); } else eig[i]=(long)dbltor(wr[i]); } free(wr); free(wi); return eig; } /* ONLY FOR POLYNOMIAL WITH REAL COEFFICIENTS : give the roots of the * polynomial a (first, the real roots, then the non real roots) in * increasing order of their real parts MULTIPLE ROOTS ARE FORBIDDEN. */ GEN zrhqr(GEN a,long prec) { ulong av = avma; long i,j,prec2, n = degpol(a), ex = -bit_accuracy(prec); GEN aa,b,p1,rt,rr,hess,x,dx,y,newval,oldval; hess = cgetg(n+1,t_MAT); for (j=1; j<=n; j++) { p1 = cgetg(n+1,t_COL); hess[j] = (long)p1; p1[1] = lneg(gdiv((GEN)a[n-j+2],(GEN)a[n+2])); for (i=2; i<=n; i++) p1[i] = (i==(j+1))? un: zero; } rt = hqr(balanc(hess)); prec2 = 2*prec; /* polishing the roots */ aa = gprec_w(a, prec2); b = derivpol(aa); rr = cgetg(n+1,t_COL); for (i=1; i<=n; i++) { x = gprec_w((GEN)rt[i], prec2); for (oldval=NULL;; oldval=newval, x=y) { /* Newton iteration */ dx = poleval(b,x); if (gexpo(dx) < ex) err(talker,"polynomial has probably multiple roots in zrhqr"); y = gsub(x, gdiv(poleval(aa,x),dx)); newval = gabs(poleval(aa,y),prec2); if (gexpo(newval) < ex || (oldval && gcmp(newval,oldval) > 0)) break; } if (DEBUGLEVEL>3) fprintferr("%ld ",i); rr[i] = (long)cgetc(prec); gaffect(y, (GEN)rr[i]); } if (DEBUGLEVEL>3) { fprintferr("\npolished roots = %Z",rr); flusherr(); } return gerepilecopy(av, rr); }