Annotation of OpenXM_contrib/pari-2.2/src/modules/nffactor.c, Revision 1.1
1.1 ! noro 1: /* $Id: nffactor.c,v 1.29 2001/10/01 12:11:33 karim Exp $
! 2:
! 3: Copyright (C) 2000 The PARI group.
! 4:
! 5: This file is part of the PARI/GP package.
! 6:
! 7: PARI/GP is free software; you can redistribute it and/or modify it under the
! 8: terms of the GNU General Public License as published by the Free Software
! 9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
! 10: ANY WARRANTY WHATSOEVER.
! 11:
! 12: Check the License for details. You should have received a copy of it, along
! 13: with the package; see the file 'COPYING'. If not, write to the Free Software
! 14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
! 15:
! 16: /*******************************************************************/
! 17: /* */
! 18: /* POLYNOMIAL FACTORIZATION IN A NUMBER FIELD */
! 19: /* */
! 20: /*******************************************************************/
! 21: #include "pari.h"
! 22: #include "parinf.h"
! 23:
! 24: extern GEN hensel_lift_fact(GEN pol, GEN fact, GEN T, GEN p, GEN pev, long e);
! 25: extern GEN nf_get_T2(GEN base, GEN polr);
! 26: extern GEN nfreducemodpr_i(GEN x, GEN prh);
! 27: extern GEN sort_factor(GEN y, int (*cmp)(GEN,GEN));
! 28: extern GEN pidealprimeinv(GEN nf, GEN x);
! 29:
! 30: static GEN nffactormod2(GEN nf,GEN pol,GEN pr);
! 31: static GEN nfmod_split2(GEN nf, GEN prhall, GEN polb, GEN v, GEN q);
! 32: static GEN nf_pol_mul(GEN nf,GEN pol1,GEN pol2);
! 33: static GEN nf_pol_divres(GEN nf,GEN pol1,GEN pol2, GEN *pr);
! 34: static GEN nf_pol_subres(GEN nf,GEN pol1,GEN pol2);
! 35: static GEN nfmod_pol_reduce(GEN nf,GEN prhall,GEN pol);
! 36: static GEN nfmod_pol_divres(GEN nf,GEN prhall,GEN pol1,GEN pol2, GEN *pr);
! 37: static GEN nfmod_pol_gcd(GEN nf,GEN prhall,GEN pol1,GEN pol2);
! 38: static GEN nf_bestlift(GEN id,GEN idinv,GEN den,GEN elt);
! 39: static GEN nf_pol_lift(GEN id,GEN idinv,GEN den,GEN pol);
! 40: static GEN nfsqff(GEN nf,GEN pol,long fl);
! 41: static int nf_combine_factors(GEN nf,long fxn,GEN psf,long dlim,long hint);
! 42:
! 43: typedef struct Nfcmbf /* for use in nfsqff */
! 44: {
! 45: GEN pol, h, hinv, fact, res, lt, den;
! 46: long nfact, nfactmod;
! 47: } Nfcmbf;
! 48: static Nfcmbf nfcmbf;
! 49:
! 50: static GEN
! 51: unifpol0(GEN nf,GEN pol,long flag)
! 52: {
! 53: static long n = 0;
! 54: static GEN vun = NULL;
! 55: GEN f = (GEN) nf[1];
! 56: long i = degpol(f), av;
! 57:
! 58: if (i != n)
! 59: {
! 60: n=i; if (vun) free(vun);
! 61: vun = (GEN) gpmalloc((n+1)*sizeof(long));
! 62: vun[0] = evaltyp(t_COL) | evallg(n+1); vun[1]=un;
! 63: for ( ; i>=2; i--) vun[i]=zero;
! 64: }
! 65:
! 66: av = avma;
! 67: switch(typ(pol))
! 68: {
! 69: case t_INT: case t_FRAC: case t_RFRAC:
! 70: pol = gmul(pol,vun); break;
! 71:
! 72: case t_POL:
! 73: pol = gmodulcp(pol,f); /* fall through */
! 74: case t_POLMOD:
! 75: pol = algtobasis(nf,pol);
! 76: }
! 77: if (flag) pol = basistoalg(nf, lift(pol));
! 78: return gerepileupto(av,pol);
! 79: }
! 80:
! 81: /* Let pol be a polynomial with coefficients in Z or nf (vectors or polymods)
! 82: * return the same polynomial with coefficients expressed:
! 83: * if flag=0: as vectors (on the integral basis).
! 84: * if flag=1: as polymods.
! 85: */
! 86: GEN
! 87: unifpol(GEN nf,GEN pol,long flag)
! 88: {
! 89: if (typ(pol)==t_POL && varn(pol) < varn(nf[1]))
! 90: {
! 91: long i, d = lgef(pol);
! 92: GEN p1 = pol;
! 93:
! 94: pol=cgetg(d,t_POL); pol[1]=p1[1];
! 95: for (i=2; i<d; i++)
! 96: pol[i] = (long) unifpol0(nf,(GEN) p1[i],flag);
! 97:
! 98: return pol;
! 99: }
! 100: return unifpol0(nf,(GEN) pol, flag);
! 101: }
! 102:
! 103: #if 0
! 104: /* return a monic polynomial of degree d with random coefficients in Z_nf */
! 105: static GEN
! 106: random_pol(GEN nf,long d)
! 107: {
! 108: long i,j, n = degpol(nf[1]);
! 109: GEN pl,p;
! 110:
! 111: pl=cgetg(d+3,t_POL);
! 112: for (i=2; i<d+2; i++)
! 113: {
! 114: p=cgetg(n+1,t_COL); pl[i]=(long)p;
! 115: for (j=1; j<=n; j++)
! 116: p[j] = lstoi(mymyrand()%101 - 50);
! 117: }
! 118: p=cgetg(n+1,t_COL); pl[i]=(long)p;
! 119: p[1]=un; for (i=2; i<=n; i++) p[i]=zero;
! 120:
! 121: pl[1] = evalsigne(1) | evallgef(d+3) | evalvarn(0);
! 122: return pl;
! 123: }
! 124: #endif
! 125:
! 126: /* multiplication of x by y */
! 127: static GEN
! 128: nf_pol_mul(GEN nf,GEN x,GEN y)
! 129: {
! 130: long tetpil,av=avma;
! 131: GEN res = gmul(unifpol(nf,x,1), unifpol(nf,y,1));
! 132:
! 133: tetpil = avma;
! 134: return gerepile(av,tetpil,unifpol(nf,res,0));
! 135: }
! 136:
! 137: /* compute x^2 in nf */
! 138: static GEN
! 139: nf_pol_sqr(GEN nf,GEN x)
! 140: {
! 141: long tetpil,av=avma;
! 142: GEN res = gsqr(unifpol(nf,x,1));
! 143:
! 144: tetpil = avma;
! 145: return gerepile(av,tetpil,unifpol(nf,res,0));
! 146: }
! 147:
! 148: /* reduce the coefficients of pol modulo prhall */
! 149: static GEN
! 150: nfmod_pol_reduce(GEN nf,GEN prhall,GEN pol)
! 151: {
! 152: long av=avma,tetpil,i;
! 153: GEN p1;
! 154:
! 155: if (typ(pol)!=t_POL) return nfreducemodpr(nf,pol,prhall);
! 156: pol=unifpol(nf,pol,0);
! 157:
! 158: tetpil=avma; i=lgef(pol);
! 159: p1=cgetg(i,t_POL); p1[1]=pol[1];
! 160: for (i--; i>=2; i--)
! 161: p1[i] = (long) nfreducemodpr(nf,(GEN)pol[i],prhall);
! 162: return gerepile(av,tetpil, normalizepol(p1));
! 163: }
! 164:
! 165: /* x^2 modulo prhall */
! 166: static GEN
! 167: nfmod_pol_sqr(GEN nf,GEN prhall,GEN x)
! 168: {
! 169: long av=avma,tetpil;
! 170: GEN px;
! 171:
! 172: px = nfmod_pol_reduce(nf,prhall,x);
! 173: px = unifpol(nf,lift(px),1);
! 174: px = unifpol(nf,nf_pol_sqr(nf,px),0);
! 175: tetpil=avma;
! 176: return gerepile(av,tetpil,nfmod_pol_reduce(nf,prhall,px));
! 177: }
! 178:
! 179: /* multiplication of x by y modulo prhall */
! 180: static GEN
! 181: nfmod_pol_mul(GEN nf,GEN prhall,GEN x,GEN y)
! 182: {
! 183: long av=avma,tetpil;
! 184: GEN px,py;
! 185:
! 186: px = nfmod_pol_reduce(nf,prhall,x); px = unifpol(nf,lift(px),1);
! 187: py = nfmod_pol_reduce(nf,prhall,y); py = unifpol(nf,lift(py),1);
! 188: px = unifpol(nf,nf_pol_mul(nf,px,py),0);
! 189: tetpil=avma;
! 190: return gerepile(av,tetpil,nfmod_pol_reduce(nf,prhall,px));
! 191: }
! 192:
! 193: /* Euclidan division of x by y */
! 194: static GEN
! 195: nf_pol_divres(GEN nf,GEN x,GEN y,GEN *pr)
! 196: {
! 197: long av = avma,tetpil;
! 198: GEN nq = poldivres(unifpol(nf,x,1),unifpol(nf,y,1),pr);
! 199: GEN *gptr[2];
! 200:
! 201: tetpil=avma; nq=unifpol(nf,nq,0);
! 202: if (pr) *pr = unifpol(nf,*pr,0);
! 203: gptr[0]=&nq; gptr[1]=pr;
! 204: gerepilemanysp(av,tetpil,gptr,pr ? 2:1);
! 205: return nq;
! 206: }
! 207:
! 208: /* Euclidan division of x by y modulo prhall */
! 209: static GEN
! 210: nfmod_pol_divres(GEN nf,GEN prhall,GEN x,GEN y, GEN *pr)
! 211: {
! 212: long av=avma,dx,dy,dz,i,j,k,l,n,tetpil;
! 213: GEN z,p1,p3,px,py;
! 214:
! 215: py = nfmod_pol_reduce(nf,prhall,y);
! 216: if (gcmp0(py))
! 217: err(talker, "division by zero in nfmod_pol_divres");
! 218:
! 219: tetpil=avma;
! 220: px=nfmod_pol_reduce(nf,prhall,x);
! 221: dx=degpol(px); dy=degpol(py); dz=dx-dy;
! 222: if (dx<dy)
! 223: {
! 224: GEN vzero;
! 225:
! 226: if (pr) *pr = gerepile(av,tetpil,px);
! 227: else avma = av;
! 228:
! 229: n=degpol(nf[1]);
! 230: vzero = cgetg(n+1,t_COL);
! 231: n=degpol(nf[1]);
! 232: for (i=1; i<=n; i++) vzero[i]=zero;
! 233:
! 234: z=cgetg(3,t_POL); z[2]=(long)vzero;
! 235: z[1]=evallgef(2) | evalvarn(varn(px));
! 236: return z;
! 237: }
! 238: p1 = NULL; /* gcc -Wall */
! 239:
! 240: z=cgetg(dz+3,t_POL); z[1]=evalsigne(1) | evallgef(3+dz);
! 241: setvarn(z,varn(px));
! 242: z[dz+2] = (long) element_divmodpr(nf,(GEN)px[dx+2],(GEN)py[dy+2],prhall);
! 243: for (i=dx-1; i>=dy; --i)
! 244: {
! 245: l=avma; p1=(GEN)px[i+2];
! 246: for (j=i-dy+1; j<=i && j<=dz; j++)
! 247: p1 = gsub(p1, element_mul(nf,(GEN)z[j+2],(GEN)py[i-j+2]));
! 248: p1 = nfreducemodpr(nf,p1,prhall);
! 249: tetpil=avma; p3=element_divmodpr(nf,p1,(GEN)py[dy+2],prhall);
! 250: z[i-dy+2]=lpile(l,tetpil,p3);
! 251: z[i-dy+2]=(long)nfreducemodpr(nf,(GEN)z[i-dy+2],prhall);
! 252: }
! 253: l=avma;
! 254: for (i=dy-1; i>=0; --i)
! 255: {
! 256: l=avma; p1=((GEN)px[i+2]);
! 257: for (j=0; j<=i && j<=dz; j++)
! 258: p1 = gsub(p1, element_mul(nf,(GEN)z[j+2],(GEN)py[i-j+2]));
! 259: p1 = gerepileupto(l, nfreducemodpr(nf,p1,prhall));
! 260: if (!gcmp0(p1)) break;
! 261: }
! 262:
! 263: if (!pr) { avma = l; return z; }
! 264:
! 265: if (i<0)
! 266: {
! 267: avma=l;
! 268: p3 = cgetg(3,t_POL); p3[2]=zero;
! 269: p3[1] = evallgef(2) | evalvarn(varn(px));
! 270: *pr=p3; return z;
! 271: }
! 272:
! 273: p3=cgetg(i+3,t_POL);
! 274: p3[1]=evalsigne(1) | evallgef(i+3) | evalvarn(varn(px));
! 275: p3[i+2]=(long)nfreducemodpr(nf,p1,prhall);
! 276: for (k=i-1; k>=0; --k)
! 277: {
! 278: l=avma; p1=((GEN)px[k+2]);
! 279: for (j=0; j<=k && j<=dz; j++)
! 280: p1 = gsub(p1, element_mul(nf,(GEN)z[j+2],(GEN)py[k-j+2]));
! 281: p3[k+2]=lpileupto(l,nfreducemodpr(nf,p1,prhall));
! 282: }
! 283: *pr=p3; return z;
! 284: }
! 285:
! 286: /* GCD of x and y */
! 287: static GEN
! 288: nf_pol_subres(GEN nf,GEN x,GEN y)
! 289: {
! 290: long av=avma,tetpil;
! 291: GEN s = srgcd(unifpol(nf,x,1), unifpol(nf,y,1));
! 292:
! 293: tetpil=avma; return gerepile(av,tetpil,unifpol(nf,s,1));
! 294: }
! 295:
! 296: /* GCD of x and y modulo prhall */
! 297: static GEN
! 298: nfmod_pol_gcd(GEN nf,GEN prhall,GEN x,GEN y)
! 299: {
! 300: long av=avma;
! 301: GEN p1,p2;
! 302:
! 303: if (lgef(x)<lgef(y)) { p1=y; y=x; x=p1; }
! 304: p1=nfmod_pol_reduce(nf,prhall,x);
! 305: p2=nfmod_pol_reduce(nf,prhall,y);
! 306: while (!isexactzero(p2))
! 307: {
! 308: GEN p3;
! 309:
! 310: nfmod_pol_divres(nf,prhall,p1,p2,&p3);
! 311: p1=p2; p2=p3;
! 312: }
! 313: return gerepileupto(av,p1);
! 314: }
! 315:
! 316: /* return pol^e modulo prhall and the polynomial pmod */
! 317: static GEN
! 318: nfmod_pol_pow(GEN nf,GEN prhall,GEN pmod,GEN pol,GEN e)
! 319: {
! 320: long i, av = avma, n = degpol(nf[1]);
! 321: GEN p1,p2,vun;
! 322:
! 323: vun=cgetg(n+1,t_COL); vun[1]=un; for (i=2; i<=n; i++) vun[i]=zero;
! 324: p1=gcopy(polun[varn(pol)]); p1[2]=(long)vun;
! 325: if (gcmp0(e)) return p1;
! 326:
! 327: p2=nfmod_pol_reduce(nf,prhall,pol);
! 328: for(;;)
! 329: {
! 330: if (!vali(e))
! 331: {
! 332: p1=nfmod_pol_mul(nf,prhall,p1,p2);
! 333: nfmod_pol_divres(nf,prhall,p1,pmod,&p1);
! 334: }
! 335: if (gcmp1(e)) break;
! 336:
! 337: e=shifti(e,-1);
! 338: p2=nfmod_pol_sqr(nf,prhall,p2);
! 339: nfmod_pol_divres(nf,prhall,p2,pmod,&p2);
! 340: }
! 341: return gerepileupto(av,p1);
! 342: }
! 343:
! 344: static long
! 345: isdivbyprime(GEN nf, GEN x, GEN pr)
! 346: {
! 347: GEN elt, p = (GEN)pr[1], tau = (GEN)pr[5];
! 348:
! 349: elt = element_mul(nf, x, tau);
! 350: if (divise(content(elt), p)) return 1;
! 351:
! 352: return 0;
! 353: }
! 354:
! 355: /* return the factor of nf.pol modulo p corresponding to pr */
! 356: static GEN
! 357: localpol(GEN nf, GEN pr)
! 358: {
! 359: long i, l;
! 360: GEN fct, pol = (GEN)nf[1], p = (GEN)pr[1];
! 361:
! 362: fct = lift((GEN)factmod(pol, p)[1]);
! 363: l = lg(fct) - 1;
! 364: for (i = 1; i <= l; i++)
! 365: if (isdivbyprime(nf, (GEN)fct[i], pr)) return (GEN)fct[i];
! 366:
! 367: err(talker, "cannot find a suitable factor in localpol");
! 368: return NULL; /* not reached */
! 369: }
! 370:
! 371: /* factorization of x modulo pr */
! 372: static GEN
! 373: nffactormod0(GEN nf, GEN x, GEN pr)
! 374: {
! 375: long av = avma, j, l, vx = varn(x), vn;
! 376: GEN rep, pol, xrd, prh, p1;
! 377:
! 378: nf=checknf(nf);
! 379: vn = varn((GEN)nf[1]);
! 380: if (typ(x)!=t_POL) err(typeer,"nffactormod");
! 381: if (vx >= vn)
! 382: err(talker,"polynomial variable must have highest priority in nffactormod");
! 383:
! 384: prh = nfmodprinit(nf, pr);
! 385:
! 386: if (divise((GEN)nf[4], (GEN)pr[1]))
! 387: return gerepileupto(av, nffactormod2(nf,x,pr));
! 388:
! 389: xrd = nfmod_pol_reduce(nf, prh, x);
! 390: if (gcmp1((GEN)pr[4]))
! 391: {
! 392: pol = gun; /* dummy */
! 393: for (j = 2; j < lg(xrd); j++)
! 394: xrd[j] = mael(xrd, j, 1);
! 395: rep = factmod(xrd, (GEN)pr[1]);
! 396: rep = lift(rep);
! 397: }
! 398: else
! 399: {
! 400: pol = localpol(nf, pr);
! 401: xrd = lift(unifpol(nf, xrd, 1));
! 402: p1 = gun;
! 403: for (j = 2; j < lg(xrd); j++)
! 404: {
! 405: xrd[j] = lmod((GEN)xrd[j], pol);
! 406: p1 = mpppcm(p1, denom(content((GEN)xrd[j])));
! 407: }
! 408: rep = factmod9(gmul(xrd, p1), (GEN)pr[1], pol);
! 409: rep = lift(lift(rep));
! 410: }
! 411:
! 412: l = lg((GEN)rep[1]);
! 413: for (j = 1; j < l; j++)
! 414: mael(rep, 1, j) = (long)unifpol(nf, gmael(rep, 1, j), 1);
! 415:
! 416: return gerepilecopy(av, rep);
! 417: }
! 418:
! 419: GEN
! 420: nffactormod(GEN nf, GEN x, GEN pr)
! 421: {
! 422: return nffactormod0(nf, x, pr);
! 423: }
! 424:
! 425: extern GEN trivfact(void);
! 426:
! 427: /* factorization of x modulo pr */
! 428: GEN
! 429: nffactormod2(GEN nf,GEN pol,GEN pr)
! 430: {
! 431: long av = avma, tetpil,lb,nbfact,psim,N,n,i,j,k,d,e,vf,r,kk;
! 432: GEN y,ex,*t,f1,f2,f3,df1,g1,polb,pold,polu,vker;
! 433: GEN Q,f,x,u,v,v2,v3,vz,q,vun,vzero,prhall;
! 434:
! 435: nf=checknf(nf);
! 436: if (typ(pol)!=t_POL) err(typeer,"nffactormod");
! 437: if (varn(pol) >= varn(nf[1]))
! 438: err(talker,"polynomial variable must have highest priority in nffactormod");
! 439:
! 440: prhall=nfmodprinit(nf,pr); n=degpol(nf[1]);
! 441: vun = gscalcol_i(gun, n);
! 442: vzero = gscalcol_i(gzero, n);
! 443: q = vker = NULL; /* gcc -Wall */
! 444:
! 445: f=unifpol(nf,pol,0); f=nfmod_pol_reduce(nf,prhall,f);
! 446: if (!signe(f)) err(zeropoler,"nffactormod");
! 447: d=degpol(f); vf=varn(f);
! 448: if (d == 0) return trivfact();
! 449: t = (GEN*)new_chunk(d+1); ex = cgetg(d+1, t_VECSMALL);
! 450: x=gcopy(polx[vf]); x[3]=(long)vun; x[2]=(long)vzero;
! 451: if (d<=1) { nbfact=2; t[1] = f; ex[1]=1; }
! 452: else
! 453: {
! 454: q = (GEN)pr[1]; psim = VERYBIGINT;
! 455: if (!is_bigint(q)) psim = itos(q);
! 456: /* psim has an effect only when p is small. If too big, set it to a huge
! 457: * number (i.e ignore it) to avoid an error in itos on next line.
! 458: */
! 459: q=gpuigs(q, itos((GEN)pr[4]));
! 460: f1=f; e=1; nbfact=1;
! 461: while (lgef(f1)>3)
! 462: {
! 463: df1=deriv(f1,vf); f2=nfmod_pol_gcd(nf,prhall,f1,df1);
! 464: g1=nfmod_pol_divres(nf,prhall,f1,f2,NULL); k=0;
! 465: while (lgef(g1)>3)
! 466: {
! 467: k++;
! 468: if (k%psim == 0)
! 469: {
! 470: k++; f2=nfmod_pol_divres(nf,prhall,f2,g1,NULL);
! 471: }
! 472: f3=nfmod_pol_gcd(nf,prhall,f2,g1);
! 473: u = nfmod_pol_divres(nf,prhall,g1,f3,NULL);
! 474: f2= nfmod_pol_divres(nf,prhall,f2,f3,NULL);
! 475: g1=f3;
! 476: if (lgef(u)>3)
! 477: {
! 478: N=degpol(u); Q=cgetg(N+1,t_MAT);
! 479: v3=cgetg(N+1,t_COL); Q[1]=(long)v3;
! 480: v3[1]=(long)vun; for (i=2; i<=N; i++) v3[i]=(long)vzero;
! 481:
! 482: v2 = v = nfmod_pol_pow(nf,prhall,u,x,q);
! 483: for (j=2; j<=N; j++)
! 484: {
! 485: v3=cgetg(N+1,t_COL); Q[j]=(long)v3;
! 486: for (i=1; i<=lgef(v2)-2; i++) v3[i]=v2[i+1];
! 487: for (; i<=N; i++) v3[i]=(long)vzero;
! 488: if (j<N)
! 489: {
! 490: v2=nfmod_pol_mul(nf,prhall,v2,v);
! 491: nfmod_pol_divres(nf,prhall,v2,u,&v2);
! 492: }
! 493: }
! 494: for (i=1; i<=N; i++)
! 495: coeff(Q,i,i)=lsub((GEN)coeff(Q,i,i),vun);
! 496: v2=nfkermodpr(nf,Q,prhall); r=lg(v2)-1; t[nbfact]=gcopy(u); kk=1;
! 497: if (r>1)
! 498: {
! 499: vker=cgetg(r+1,t_COL);
! 500: for (i=1; i<=r; i++)
! 501: {
! 502: v3=cgetg(N+2,t_POL);
! 503: v3[1]=evalsigne(1)+evallgef(2+N); setvarn(v3,vf);
! 504: vker[i]=(long)v3; for (j=1; j<=N; j++) v3[j+1]=coeff(v2,j,i);
! 505: normalizepol(v3);
! 506: }
! 507: }
! 508: while (kk<r)
! 509: {
! 510: v=gcopy(polun[vf]); v[2]=(long)vzero;
! 511: for (i=1; i<=r; i++)
! 512: {
! 513: vz=cgetg(n+1,t_COL);
! 514: for (j=1; j<=n; j++)
! 515: vz[j] = lmodsi(mymyrand()>>8, q);
! 516: vz=nfreducemodpr(nf,vz,prhall);
! 517: v=gadd(v,nfmod_pol_mul(nf,prhall,vz,(GEN)vker[i]));
! 518: }
! 519: for (i=1; i<=kk && kk<r; i++)
! 520: {
! 521: polb=t[nbfact+i-1]; lb=lgef(polb);
! 522: if (lb>4)
! 523: {
! 524: if(psim==2)
! 525: polu=nfmod_split2(nf,prhall,polb,v,q);
! 526: else
! 527: {
! 528: polu=nfmod_pol_pow(nf,prhall,polb,v,shifti(q,-1));
! 529: polu=gsub(polu,vun);
! 530: }
! 531: pold=nfmod_pol_gcd(nf,prhall,polb,polu);
! 532: if (lgef(pold)>3 && lgef(pold)<lb)
! 533: {
! 534: t[nbfact+i-1]=pold; kk++;
! 535: t[nbfact+kk-1]=nfmod_pol_divres(nf,prhall,polb,pold,NULL);
! 536: }
! 537: }
! 538: }
! 539: }
! 540: for (i=nbfact; i<nbfact+r; i++) ex[i]=e*k;
! 541: nbfact+=r;
! 542: }
! 543: }
! 544: e*=psim; j=(degpol(f2))/psim+3; f1=cgetg(j,t_POL);
! 545: f1[1] = evalsigne(1) | evallgef(j) | evalvarn(vf);
! 546: for (i=2; i<j; i++)
! 547: f1[i]=(long)element_powmodpr(nf,(GEN)f2[psim*(i-2)+2],
! 548: gdiv(q,(GEN)pr[1]),prhall);
! 549: }
! 550: }
! 551: if (nbfact < 2)
! 552: err(talker, "%Z not a prime (nffactormod)", q);
! 553: for (j=1; j<nbfact; j++)
! 554: {
! 555: v = element_divmodpr(nf,vun,gmael(t,j,lgef(t[j])-1),prhall);
! 556: t[j] = unifpol(nf,nfmod_pol_mul(nf,prhall,v,(GEN)t[j]),1);
! 557: }
! 558:
! 559: tetpil=avma; y=cgetg(3,t_MAT);
! 560: u=cgetg(nbfact,t_COL); y[1]=(long)u;
! 561: v=cgetg(nbfact,t_COL); y[2]=(long)v;
! 562: for (j=1,k=0; j<nbfact; j++)
! 563: if (ex[j])
! 564: {
! 565: k++;
! 566: u[k]=lcopy((GEN)t[j]);
! 567: v[k]=lstoi(ex[j]);
! 568: }
! 569: return gerepile(av,tetpil,y);
! 570: }
! 571:
! 572: /* return pol + pol^2 + ... + pol^(q/2) modulo prhall and
! 573: the polynomial pmod */
! 574: static GEN
! 575: nfmod_split2(GEN nf,GEN prhall,GEN pmod,GEN pol,GEN exp)
! 576: {
! 577: long av = avma;
! 578: GEN p1,p2,q;
! 579:
! 580: if (cmpis(exp,2)<=0) return pol;
! 581: p2=p1=pol; q=shifti(exp,-1);
! 582: while (!gcmp1(q))
! 583: {
! 584: p2=nfmod_pol_sqr(nf,prhall,p2);
! 585: nfmod_pol_divres(nf,prhall,p2,pmod,&p2);
! 586: q=shifti(q,-1); p1=gadd(p1,p2);
! 587: }
! 588: return gerepileupto(av,p1);
! 589: }
! 590:
! 591: /* If p doesn't divide either a or b and has a divisor of degree 1, return it.
! 592: * Return NULL otherwise.
! 593: */
! 594: static GEN
! 595: p_ok(GEN nf, GEN p, GEN a)
! 596: {
! 597: long av,m,i;
! 598: GEN dec;
! 599:
! 600: if (divise(a,p)) return NULL;
! 601: av = avma; dec = primedec(nf,p); m=lg(dec);
! 602: for (i=1; i<m; i++)
! 603: {
! 604: GEN pr = (GEN)dec[i];
! 605: if (is_pm1(pr[4]))
! 606: return pr;
! 607: }
! 608: avma = av; return NULL;
! 609: }
! 610:
! 611: /* for each new prime ct--, if ct = 0, return NULL */
! 612: static GEN
! 613: choose_prime(GEN nf, GEN dk, GEN lim, long ct)
! 614: {
! 615: GEN p, pr;
! 616:
! 617: p = nextprime(lim);
! 618: for (;;)
! 619: {
! 620: if ((pr = p_ok(nf,p,dk))) break;
! 621: ct--;
! 622: if (!ct) return NULL;
! 623: p = nextprime(addis(p,2));
! 624: }
! 625:
! 626: return pr;
! 627: }
! 628:
! 629: /* test if the discriminant of polbase modulo some few primes
! 630: is non-zero. Return 1 if it is so (=> polbase is square-free)
! 631: and 0 otherwise (=> polbase may or may not be square-free) */
! 632: static int
! 633: is_sqf(GEN nf, GEN polbase)
! 634: {
! 635: GEN lt, pr, prh, p2, p;
! 636: long i, d = lgef(polbase), ct = 5;
! 637:
! 638: lt = (GEN)leading_term(polbase)[1];
! 639: p = stoi(101);
! 640:
! 641: while (ct > 0)
! 642: {
! 643: /* small primes tend to divide discriminants more often
! 644: than large ones so we look at primes >= 101 */
! 645: pr = choose_prime(nf,lt,p,30);
! 646: if (!pr) break;
! 647:
! 648: p=(GEN)pr[1];
! 649: prh=prime_to_ideal(nf,pr);
! 650:
! 651: p2=gcopy(polbase);
! 652: lt=mpinvmod(lt,p);
! 653:
! 654: for (i=2; i<d; i++)
! 655: p2[i] = nfreducemodpr_i(gmul(lt,(GEN)p2[i]), prh)[1];
! 656: p2 = normalizepol(p2);
! 657:
! 658: /* discriminant is non-zero => polynomial is square-free */
! 659: if (!gcmp0(p2) && !divise(discsr(p2),p)) { return 1; }
! 660:
! 661: ct--;
! 662: p=addis(p,1);
! 663: }
! 664:
! 665: return 0;
! 666: }
! 667:
! 668: /* rescale p in K[X] (coeffs in algtobasis form) --> primitive in O_K[X] */
! 669: GEN
! 670: nf_pol_to_int(GEN p, GEN *den)
! 671: {
! 672: long i, l = lgef(p);
! 673: GEN d = gun;
! 674: for (i=2; i<l; i++)
! 675: d = mpppcm(d,denom((GEN)p[i]));
! 676: if (! gcmp1(d)) p = gmul(p, d);
! 677: *den = d; return p;
! 678: }
! 679:
! 680: /* return the roots of pol in nf */
! 681: GEN
! 682: nfroots(GEN nf,GEN pol)
! 683: {
! 684: long av=avma,tetpil,d=lgef(pol),fl;
! 685: GEN p1,p2,polbase,polmod,den;
! 686:
! 687: p2=NULL; /* gcc -Wall */
! 688: nf=checknf(nf);
! 689: if (typ(pol)!=t_POL) err(talker,"not a polynomial in nfroots");
! 690: if (varn(pol) >= varn(nf[1]))
! 691: err(talker,"polynomial variable must have highest priority in nfroots");
! 692:
! 693: polbase=unifpol(nf,pol,0);
! 694:
! 695: if (d==3)
! 696: {
! 697: tetpil=avma; p1=cgetg(1,t_VEC);
! 698: return gerepile(av,tetpil,p1);
! 699: }
! 700:
! 701: if (d==4)
! 702: {
! 703: tetpil=avma; p1=cgetg(2,t_VEC);
! 704: p1[1] = (long)basistoalg(nf,gneg_i(
! 705: element_div(nf,(GEN)polbase[2],(GEN)polbase[3])));
! 706: return gerepile(av,tetpil,p1);
! 707: }
! 708:
! 709: p1=element_inv(nf,leading_term(polbase));
! 710: polbase=nf_pol_mul(nf,p1,polbase);
! 711:
! 712: polbase = nf_pol_to_int(polbase, &den);
! 713: polmod=unifpol(nf,polbase,1);
! 714:
! 715: if (DEBUGLEVEL>=4)
! 716: fprintferr("test if the polynomial is square-free\n");
! 717:
! 718: fl = is_sqf(nf, polbase);
! 719:
! 720: /* the polynomial may not be square-free ... */
! 721: if (!fl)
! 722: {
! 723: p1=derivpol(polmod);
! 724: p2=nf_pol_subres(nf,polmod,p1);
! 725: if (degpol(p2) == 0) fl = 1;
! 726: }
! 727:
! 728: if (!fl)
! 729: {
! 730: p1=element_inv(nf,leading_term(p2));
! 731: p2=nf_pol_mul(nf,p1,p2);
! 732: polmod=nf_pol_divres(nf,polmod,p2,NULL);
! 733:
! 734: p1=element_inv(nf,leading_term(polmod));
! 735: polmod=nf_pol_mul(nf,p1,polmod);
! 736:
! 737: polmod = nf_pol_to_int(polmod, &den);
! 738: polmod=unifpol(nf,polmod,1);
! 739: }
! 740:
! 741: p1 = nfsqff(nf,polmod,1);
! 742: tetpil=avma; return gerepile(av, tetpil, gen_sort(p1, 0, cmp_pol));
! 743: }
! 744:
! 745: /* return a minimal lift of elt modulo id */
! 746: static GEN
! 747: nf_bestlift(GEN id,GEN idinv,GEN den,GEN elt)
! 748: {
! 749: GEN u = gmul(idinv,elt);
! 750: long i, l = lg(u);
! 751: for (i=1; i<l; i++) u[i] = (long)gdivround((GEN)u[i], den);
! 752: return gsub(elt, gmul(id, u));
! 753: }
! 754:
! 755: /* return the lift of pol with coefficients of T2-norm <= C (if possible) */
! 756: static GEN
! 757: nf_pol_lift(GEN id,GEN idinv,GEN den,GEN pol)
! 758: {
! 759: long i, d = lgef(pol);
! 760: GEN x = cgetg(d,t_POL);
! 761: x[1] = pol[1];
! 762: for (i=2; i<d; i++)
! 763: x[i] = (long) nf_bestlift(id,idinv,den,(GEN)pol[i]);
! 764: return x;
! 765: }
! 766:
! 767: #if 0
! 768: /* return pol(elt) */
! 769: static GEN
! 770: nf_pol_eval(GEN nf,GEN pol,GEN elt)
! 771: {
! 772: long av=avma,tetpil,i;
! 773: GEN p1;
! 774:
! 775: i=lgef(pol)-1; if (i==2) return gcopy((GEN)pol[2]);
! 776:
! 777: p1=element_mul(nf,(GEN)pol[i],elt);
! 778: for (i--; i>=3; i--)
! 779: p1=element_mul(nf,elt,gadd((GEN)pol[i],p1));
! 780: tetpil=avma; return gerepile(av,tetpil,gadd(p1,(GEN)pol[2]));
! 781: }
! 782: #endif
! 783:
! 784: /* return the factorization of x in nf */
! 785: GEN
! 786: nffactor(GEN nf,GEN pol)
! 787: {
! 788: GEN y,p1,p2,den,p3,p4,quot,rep=cgetg(3,t_MAT);
! 789: long av = avma,tetpil,i,j,d,fl;
! 790:
! 791: if (DEBUGLEVEL >= 4) timer2();
! 792:
! 793: p3=NULL; /* gcc -Wall */
! 794: nf=checknf(nf);
! 795: if (typ(pol)!=t_POL) err(typeer,"nffactor");
! 796: if (varn(pol) >= varn(nf[1]))
! 797: err(talker,"polynomial variable must have highest priority in nffactor");
! 798:
! 799: d=lgef(pol);
! 800: if (d==3)
! 801: {
! 802: rep[1]=lgetg(1,t_COL);
! 803: rep[2]=lgetg(1,t_COL);
! 804: return rep;
! 805: }
! 806: if (d==4)
! 807: {
! 808: p1=cgetg(2,t_COL); rep[1]=(long)p1; p1[1]=lcopy(pol);
! 809: p1=cgetg(2,t_COL); rep[2]=(long)p1; p1[1]=un;
! 810: return rep;
! 811: }
! 812:
! 813: p1=element_inv(nf,leading_term(pol));
! 814: pol=nf_pol_mul(nf,p1,pol);
! 815:
! 816: p1=unifpol(nf,pol,0);
! 817: p1 = nf_pol_to_int(p1, &den);
! 818:
! 819: if (DEBUGLEVEL>=4)
! 820: fprintferr("test if the polynomial is square-free\n");
! 821:
! 822: fl = is_sqf(nf, p1);
! 823:
! 824: /* polynomial may not be square-free ... */
! 825: if (!fl)
! 826: {
! 827: p2=derivpol(p1);
! 828: p3=nf_pol_subres(nf,p1,p2);
! 829: if (degpol(p3) == 0) fl = 1;
! 830: }
! 831:
! 832: if (!fl)
! 833: {
! 834: p4=element_inv(nf,leading_term(p3));
! 835: p3=nf_pol_mul(nf,p4,p3);
! 836:
! 837: p2=nf_pol_divres(nf,p1,p3,NULL);
! 838: p4=element_inv(nf,leading_term(p2));
! 839: p2=nf_pol_mul(nf,p4,p2);
! 840:
! 841: p2 = nf_pol_to_int(p2, &den);
! 842:
! 843: p2=unifpol(nf,p2,1);
! 844: tetpil = avma; y = nfsqff(nf,p2,0);
! 845: i = nfcmbf.nfact;
! 846:
! 847: quot=nf_pol_divres(nf,p1,p2,NULL);
! 848: p3=(GEN)gpmalloc((i+1) * sizeof(long));
! 849: for (j=i; j>=1; j--)
! 850: {
! 851: GEN fact=(GEN)y[j], quo = quot, rem;
! 852: long e = 0;
! 853:
! 854: do
! 855: {
! 856: quo = nf_pol_divres(nf,quo,fact,&rem);
! 857: e++;
! 858: }
! 859: while (gcmp0(rem));
! 860: p3[j]=lstoi(e);
! 861: }
! 862: avma = (long)y; y = gerepile(av, tetpil, y);
! 863: p2=cgetg(i+1, t_COL); for (; i>=1; i--) p2[i]=lcopy((GEN)p3[i]);
! 864: free(p3);
! 865: }
! 866: else
! 867: {
! 868: tetpil=avma; y = gerepile(av,tetpil,nfsqff(nf,p1,0));
! 869: i = nfcmbf.nfact;
! 870: p2=cgetg(i+1, t_COL); for (; i>=1; i--) p2[i]=un;
! 871: }
! 872: if (DEBUGLEVEL>=4)
! 873: fprintferr("number of factor(s) found: %ld\n", nfcmbf.nfact);
! 874: rep[1]=(long)y;
! 875: rep[2]=(long)p2; return sort_factor(rep, cmp_pol);
! 876: }
! 877:
! 878: /* test if the matrix M is suitable */
! 879: static long
! 880: test_mat(GEN M, GEN p, GEN C2, long k)
! 881: {
! 882: long av = avma, i, N = lg(M);
! 883: GEN min, prod, L2, R;
! 884:
! 885: min = prod = gcoeff(M,1,1);
! 886: for (i = 2; i < N; i++)
! 887: {
! 888: L2 = gcoeff(M,i,i); prod = mpmul(prod,L2);
! 889: if (mpcmp(L2,min) < 0) min = L2;
! 890: }
! 891: R = mpmul(min, gpowgs(p, k<<1));
! 892: i = mpcmp(mpmul(C2,prod), R); avma = av;
! 893: return (i < 0);
! 894: }
! 895:
! 896: /* return the matrix corresponding to pr^e with R(pr^e) > C */
! 897: static GEN
! 898: T2_matrix_pow(GEN nf, GEN pre, GEN p, GEN C, long *kmax, long prec)
! 899: {
! 900: long av=avma,av1,lim, k = *kmax, N = degpol((GEN)nf[1]);
! 901: int tot_real = !signe(gmael(nf,2,2));
! 902: GEN p1,p2,p3,u,C2,T2, x = (GEN)nf[1];
! 903:
! 904: C2 = gdiv(gmul2n(C,2), absi((GEN)nf[3]));
! 905: p1 = gmul(pre,lllintpartial(pre)); av1 = avma;
! 906: T2 = tot_real? gmael(nf,5,4)
! 907: : nf_get_T2((GEN) nf[7], roots(x,prec));
! 908: p3 = qf_base_change(T2,p1,1);
! 909:
! 910: if (N <= 6 && test_mat(p3,p,C2,k))
! 911: {
! 912: avma = av1; return gerepileupto(av,p1);
! 913: }
! 914:
! 915: av1=avma; lim = stack_lim(av1,2);
! 916: for (;;)
! 917: {
! 918: if (DEBUGLEVEL>2) fprintferr("exponent: %ld\n",k);
! 919:
! 920: for(;;)
! 921: {
! 922: u = tot_real? lllgramall(p3,2,lll_IM) : lllgramintern(p3,2,1,prec);
! 923: if (u) break;
! 924:
! 925: prec=(prec<<1)-2;
! 926: if (DEBUGLEVEL > 1) err(warnprec,"nffactor[1]",prec);
! 927: T2 = nf_get_T2((GEN) nf[7], roots(x,prec));
! 928: p3 = qf_base_change(T2,p1,1);
! 929: }
! 930: if (DEBUGLEVEL>2) msgtimer("lllgram + base change");
! 931: p3 = qf_base_change(p3,u,1);
! 932: if (test_mat(p3,p,C2,k))
! 933: {
! 934: *kmax = k;
! 935: return gerepileupto(av,gmul(p1,u));
! 936: }
! 937:
! 938: /* we also need to increase the precision */
! 939: p2=shifti(gceil(mulsr(k, glog(p,DEFAULTPREC))),-1);
! 940: prec += (long)(itos(p2)*pariK1);
! 941: if (DEBUGLEVEL > 1) err(warnprec,"nffactor[2]",prec);
! 942: k = k<<1; p1 = idealmullll(nf,p1,p1);
! 943: if (low_stack(lim, stack_lim(av1,2)))
! 944: {
! 945: if (DEBUGMEM>1) err(warnmem,"T2_matrix_pow");
! 946: p1 = gerepileupto(av1,p1);
! 947: }
! 948: if (!tot_real) T2 = nf_get_T2((GEN) nf[7], roots(x,prec));
! 949: p3 = qf_base_change(T2,p1,1);
! 950: }
! 951: }
! 952:
! 953: /* return the factorization of the square-free polynomial x.
! 954: The coeff of x are in Z_nf and its leading term is a rational
! 955: integer. If fl = 1,return only the roots of x in nf */
! 956: static GEN
! 957: nfsqff(GEN nf,GEN pol, long fl)
! 958: {
! 959: long d=lgef(pol),i,k,m,n,av=avma,tetpil,newprec,prec,nbf=BIGINT,anbf,ct=5;
! 960: GEN p1,pr,p2,rep,k2,C,h,dk,dki,p,prh,p3,T2,polbase,fact,pk,ap,apr;
! 961: GEN polmod,polred,hinv,lt,minp,den,maxp=shifti(gun,32),run,aprh;
! 962:
! 963: if (DEBUGLEVEL>=4) msgtimer("square-free");
! 964:
! 965: dk=absi((GEN)nf[3]);
! 966: dki=mulii(dk,(GEN)nf[4]);
! 967: n=degpol(nf[1]);
! 968:
! 969: polbase = unifpol(nf,pol,0);
! 970: polmod = unifpol(nf,pol,1);
! 971: dki=mulii(dki,gnorm((GEN)polmod[d-1]));
! 972:
! 973: prec = DEFAULTPREC;
! 974: for (;;)
! 975: {
! 976: if (prec <= gprecision(nf))
! 977: T2 = gprec_w(gmael(nf,5,3), prec);
! 978: else
! 979: T2 = nf_get_T2((GEN)nf[7], roots((GEN)nf[1], prec));
! 980:
! 981: run=realun(prec);
! 982: p1=realzero(prec);
! 983: for (i=2; i<d; i++)
! 984: {
! 985: p2 = gmul(run, (GEN)polbase[i]);
! 986: p2 = qfeval(T2, p2);
! 987: p1 = addrr(p1, gdiv(p2, binome(stoi(d), i-2)));
! 988: if (signe(p1) < 0) break;
! 989: }
! 990:
! 991: if (signe(p1) > 0) break;
! 992:
! 993: prec = (prec<<1)-2;
! 994: if (DEBUGLEVEL > 1) err(warnprec, "nfsqff", prec);
! 995: }
! 996:
! 997: lt = (GEN)leading_term(polbase)[1];
! 998: p1 = gmul(p1, mulis(sqri(lt), n));
! 999: C = gpow(stoi(3), gadd(gmulsg(3, ghalf), stoi(d)), prec);
! 1000: C = gdiv(gmul(C, p1), gmulsg(d, mppi(prec)));
! 1001:
! 1002: if (DEBUGLEVEL>=4)
! 1003: fprintferr("the bound on the T2-norm of the coeff. is: %Z\n", C);
! 1004:
! 1005: /* the theoretical bound for the exponent should be:
! 1006: k2=gadd(glog(gdivgs(C,n),DEFAULTPREC), mulsr(n*(n-1), dbltor(0.347))); */
! 1007: k2=gadd(glog(gdivgs(C,n),DEFAULTPREC), mulsr(n*(n-1), dbltor(0.15)));
! 1008: k2=gmul2n(gmulgs(k2,n),-1);
! 1009:
! 1010: minp=gmin(gexp(gmul2n(k2,-6),BIGDEFAULTPREC), maxp);
! 1011: minp=gceil(minp);
! 1012:
! 1013: if (DEBUGLEVEL>=4)
! 1014: {
! 1015: fprintferr("lower bound for the prime numbers: %Z\n", minp);
! 1016: msgtimer("bounds computation");
! 1017: }
! 1018:
! 1019: p = rep = polred = NULL; /* gcc -Wall */
! 1020: pr=NULL;
! 1021: for (;;)
! 1022: {
! 1023: apr = choose_prime(nf,dki,minp, pr?30:0);
! 1024: if (!apr) break;
! 1025:
! 1026: ap=(GEN)apr[1];
! 1027: aprh=prime_to_ideal(nf,apr);
! 1028:
! 1029: polred=gcopy(polbase);
! 1030: lt=(GEN)leading_term(polbase)[1];
! 1031: lt=mpinvmod(lt,ap);
! 1032:
! 1033: for (i=2; i<d; i++)
! 1034: polred[i] = nfreducemodpr_i(gmul(lt,(GEN)polbase[i]), aprh)[1];
! 1035:
! 1036: if (!divise(discsr(polred),ap))
! 1037: {
! 1038: rep=(GEN)simplefactmod(polred,ap)[1];
! 1039: anbf=lg(rep)-1;
! 1040: ct--;
! 1041: if (anbf < nbf)
! 1042: {
! 1043: nbf=anbf;
! 1044: pr=gcopy(apr);
! 1045: p=gcopy(ap);
! 1046: if (DEBUGLEVEL>=4)
! 1047: {
! 1048: fprintferr("prime ideal considered: %Z\n", pr);
! 1049: fprintferr("number of irreducible factors: %ld\n", nbf);
! 1050: }
! 1051: if (nbf == 1) break;
! 1052: }
! 1053: }
! 1054: if (pr && !ct) break;
! 1055:
! 1056: minp = addis(ap,1);
! 1057: }
! 1058:
! 1059: k = itos(gceil(gdiv(k2,glog(p,BIGDEFAULTPREC))));
! 1060:
! 1061: if (DEBUGLEVEL>=4)
! 1062: {
! 1063: fprintferr("prime ideal chosen: %Z\n", pr);
! 1064: msgtimer("choice of the prime ideal");
! 1065: }
! 1066:
! 1067: if (lg(rep)==2)
! 1068: {
! 1069: if (fl) { avma=av; return cgetg(1,t_VEC); }
! 1070: rep=cgetg(2,t_VEC); rep[1]=lcopy(polmod);
! 1071: nfcmbf.nfact=1; return gerepileupto(av, rep);
! 1072: }
! 1073:
! 1074: p2=cgetr(DEFAULTPREC);
! 1075: affir(mulii(absi(dk),gpowgs(p,k)),p2);
! 1076: p2=shifti(gceil(mplog(p2)),-1);
! 1077:
! 1078: newprec = MEDDEFAULTPREC + (long)(itos(p2)*pariK1);
! 1079: if (DEBUGLEVEL>=4)
! 1080: fprintferr("new precision: %ld\n",newprec);
! 1081:
! 1082: prh = idealpows(nf,pr,k); m = k;
! 1083: h = T2_matrix_pow(nf,prh,p,C, &k, newprec);
! 1084: if (m != k) prh=idealpows(nf,pr,k);
! 1085:
! 1086: if (DEBUGLEVEL>=4)
! 1087: {
! 1088: fprintferr("a suitable exponent is: %ld\n",(long)k);
! 1089: msgtimer("computation of H");
! 1090: }
! 1091:
! 1092: pk = gcoeff(prh,1,1);
! 1093: lt=(GEN)leading_term(polbase)[1];
! 1094: lt=mpinvmod(lt,pk);
! 1095:
! 1096: polred[1] = polbase[1];
! 1097: for (i=2; i<d; i++)
! 1098: polred[i] = nfreducemodpr_i(gmul(lt,(GEN)polbase[i]), prh)[1];
! 1099:
! 1100: fact = lift_intern((GEN)factmod(polred,p)[1]);
! 1101: rep = hensel_lift_fact(polred,fact,NULL,p,pk,k);
! 1102:
! 1103: if (DEBUGLEVEL >= 4) msgtimer("computation of the p-adic factorization");
! 1104:
! 1105: den = det(h); /* |den| = NP^k */
! 1106: hinv= adj(h);
! 1107: lt=(GEN)leading_term(polbase)[1];
! 1108:
! 1109: if (fl)
! 1110: {
! 1111: long x_a[] = { evaltyp(t_POL)|m_evallg(4), 0,0,0 };
! 1112: GEN mlt = gneg_i(lt), rem;
! 1113: x_a[1] = polbase[1]; setlgef(x_a, 4);
! 1114: x_a[3] = un;
! 1115: p1=cgetg(lg(rep)+1,t_VEC);
! 1116: polbase = unifpol(nf,polbase,1);
! 1117: for (m=1,i=1; i<lg(rep); i++)
! 1118: {
! 1119: p2=(GEN)rep[i]; if (lgef(p2)!=4) break;
! 1120:
! 1121: p3 = algtobasis(nf, gmul(mlt,(GEN)p2[2]));
! 1122: p3 = nf_bestlift(h,hinv,den,p3);
! 1123: p3 = gdiv(p3,lt);
! 1124: x_a[2] = lneg(p3); /* check P(p3) == 0 */
! 1125: p2 = poldivres(polbase, unifpol(nf,x_a,1), &rem);
! 1126: if (!signe(rem)) { polbase = p2; p1[m++] = (long)p3; }
! 1127: }
! 1128: tetpil=avma; rep=cgetg(m,t_VEC);
! 1129: for (i=1; i<m; i++) rep[i]=(long)basistoalg(nf,(GEN)p1[i]);
! 1130: return gerepile(av,tetpil,rep);
! 1131: }
! 1132:
! 1133: for (i=1; i<lg(rep); i++)
! 1134: rep[i] = (long)unifpol(nf,(GEN)rep[i],0);
! 1135:
! 1136: nfcmbf.pol = polmod;
! 1137: nfcmbf.lt = lt;
! 1138: nfcmbf.h = h;
! 1139: nfcmbf.hinv = hinv;
! 1140: nfcmbf.den = den;
! 1141: nfcmbf.fact = rep;
! 1142: nfcmbf.res = cgetg(lg(rep)+1,t_VEC);
! 1143: nfcmbf.nfact = 0;
! 1144: nfcmbf.nfactmod = lg(rep)-1;
! 1145: nf_combine_factors(nf,1,NULL,d-3,1);
! 1146:
! 1147: if (DEBUGLEVEL >= 4) msgtimer("computation of the factors");
! 1148:
! 1149: i = nfcmbf.nfact;
! 1150: if (lgef(nfcmbf.pol)>3)
! 1151: {
! 1152: nfcmbf.res[++i] = (long) nf_pol_divres(nf,nfcmbf.pol,nfcmbf.lt,NULL);
! 1153: nfcmbf.nfact = i;
! 1154: }
! 1155:
! 1156: tetpil=avma; rep=cgetg(i+1,t_VEC);
! 1157: for ( ; i>=1; i--)
! 1158: rep[i]=(long)unifpol(nf,(GEN)nfcmbf.res[i],1);
! 1159: return gerepile(av,tetpil,rep);
! 1160: }
! 1161:
! 1162: static int
! 1163: nf_combine_factors(GEN nf,long fxn,GEN psf,long dlim,long hint)
! 1164: {
! 1165: int val = 0; /* assume failure */
! 1166: GEN newf, newpsf = NULL;
! 1167: long av,newd,ltop,i;
! 1168:
! 1169: /* Assertion: fxn <= nfcmbf.nfactmod && dlim > 0 */
! 1170:
! 1171: /* first, try deeper factors without considering the current one */
! 1172: if (fxn != nfcmbf.nfactmod)
! 1173: {
! 1174: val = nf_combine_factors(nf,fxn+1,psf,dlim,hint);
! 1175: if (val && psf) return 1;
! 1176: }
! 1177:
! 1178: /* second, try including the current modular factor in the product */
! 1179: newf = (GEN)nfcmbf.fact[fxn];
! 1180: if (!newf) return val; /* modular factor already used */
! 1181: newd = degpol(newf);
! 1182: if (newd > dlim) return val; /* degree of new factor is too large */
! 1183:
! 1184: av = avma;
! 1185: if (newd % hint == 0)
! 1186: {
! 1187: GEN p, quot,rem;
! 1188:
! 1189: newpsf = nf_pol_mul(nf, psf? psf: nfcmbf.lt, newf);
! 1190: newpsf = nf_pol_lift(nfcmbf.h,nfcmbf.hinv,nfcmbf.den,newpsf);
! 1191: /* try out the new combination */
! 1192: ltop=avma;
! 1193: quot=nf_pol_divres(nf,nfcmbf.pol,newpsf,&rem);
! 1194: if (gcmp0(rem)) /* found a factor */
! 1195: {
! 1196: p = nf_pol_mul(nf,element_inv(nf,leading_term(newpsf)),newpsf);
! 1197: nfcmbf.res[++nfcmbf.nfact] = (long) p; /* store factor */
! 1198: nfcmbf.fact[fxn]=0; /* remove used modular factor */
! 1199:
! 1200: /* fix up target */
! 1201: p=gun; quot=unifpol(nf,quot,0);
! 1202: for (i=2; i<lgef(quot); i++)
! 1203: p = mpppcm(p, denom((GEN)quot[i]));
! 1204:
! 1205: nfcmbf.pol = nf_pol_mul(nf,p,quot);
! 1206: nfcmbf.lt = leading_term(nfcmbf.pol);
! 1207: return 1;
! 1208: }
! 1209: avma=ltop;
! 1210: }
! 1211:
! 1212: /* If room in degree limit + more modular factors to try, add more factors to
! 1213: * newpsf */
! 1214: if (newd < dlim && fxn < nfcmbf.nfactmod
! 1215: && nf_combine_factors(nf,fxn+1,newpsf,dlim-newd,hint))
! 1216: {
! 1217: nfcmbf.fact[fxn]=0; /* remove used modular factor */
! 1218: return 1;
! 1219: }
! 1220: avma = av; return val;
! 1221: }
! 1222:
! 1223: /* return the characteristic polynomial of alpha over nf, where alpha
! 1224: is an element of the algebra nf[X]/(T) given as a polynomial in X */
! 1225: GEN
! 1226: rnfcharpoly(GEN nf,GEN T,GEN alpha,int v)
! 1227: {
! 1228: long av = avma, vnf, vT, lT;
! 1229: GEN p1;
! 1230:
! 1231: nf=checknf(nf); vnf = varn(nf[1]);
! 1232: if (v<0) v = 0;
! 1233: T = fix_relative_pol(nf,T,1);
! 1234: if (typ(alpha) == t_POLMOD) alpha = lift_to_pol(alpha);
! 1235: lT = lgef(T);
! 1236: if (typ(alpha) != t_POL || varn(alpha) == vnf)
! 1237: return gerepileupto(av, gpowgs(gsub(polx[v], alpha), lT - 3));
! 1238: vT = varn(T);
! 1239: if (varn(alpha) != vT || v >= vnf)
! 1240: err(talker,"incorrect variables in rnfcharpoly");
! 1241: if (lgef(alpha) >= lT) alpha = gmod(alpha,T);
! 1242: if (lT <= 4)
! 1243: return gerepileupto(av, gsub(polx[v], alpha));
! 1244: p1 = caract2(unifpol(nf,T,1), unifpol(nf,alpha,1), v);
! 1245: return gerepileupto(av, unifpol(nf,p1,1));
! 1246: }
! 1247:
! 1248: #if 0
! 1249: /* return the minimal polynomial of alpha over nf, where alpha is
! 1250: an element of the algebra nf[X]/(T) given as a polynomial in X */
! 1251: GEN
! 1252: rnfminpoly(GEN nf,GEN T,GEN alpha,int n)
! 1253: {
! 1254: long av=avma,tetpil;
! 1255: GEN p1,p2;
! 1256:
! 1257: nf=checknf(nf); p1=rnfcharpoly(nf,T,alpha,n);
! 1258: tetpil=avma; p2=nf_pol_subres(nf,p1,deriv(p1,varn(T)));
! 1259: if (lgef(p2)==3) { avma=tetpil; return p1; }
! 1260:
! 1261: p1 = nf_pol_divres(nf,p1,p2,NULL);
! 1262: p2 = element_inv(nf,leading_term(p1));
! 1263: tetpil=avma; return gerepile(av,tetpil,unifpol(nf,nf_pol_mul(nf,p2,p1),1));
! 1264: }
! 1265: #endif
! 1266:
! 1267: /* relative Dedekind criterion over nf, applied to the order defined by a
! 1268: * root of irreducible polynomial T, modulo the prime ideal pr. Returns
! 1269: * [flag,basis,val], where basis is a pseudo-basis of the enlarged order,
! 1270: * flag is 1 iff this order is pr-maximal, and val is the valuation in pr of
! 1271: * the order discriminant
! 1272: */
! 1273: GEN
! 1274: rnfdedekind(GEN nf,GEN T,GEN pr)
! 1275: {
! 1276: long av=avma,vt,r,d,da,n,m,i,j;
! 1277: GEN p1,p2,p,tau,g,vecun,veczero,matid;
! 1278: GEN prhall,res,h,k,base,Ca;
! 1279:
! 1280: nf=checknf(nf); Ca=unifpol(nf,T,0);
! 1281: res=cgetg(4,t_VEC);
! 1282: if (typ(pr)==t_VEC && lg(pr)==3)
! 1283: { prhall = (GEN)pr[2]; pr = (GEN)pr[1]; }
! 1284: else
! 1285: prhall=nfmodprinit(nf,pr);
! 1286: p=(GEN)pr[1]; tau=gdiv((GEN)pr[5],p);
! 1287: n=degpol(nf[1]); m=degpol(T);
! 1288:
! 1289: vecun = gscalcol_i(gun,n);
! 1290: veczero = zerocol(n);
! 1291:
! 1292: p1=(GEN)nffactormod(nf,Ca,pr)[1];
! 1293: r=lg(p1); if (r < 2) err(constpoler,"rnfdedekind");
! 1294: g=lift((GEN)p1[1]);
! 1295: for (i=2; i<r; i++)
! 1296: g = nf_pol_mul(nf,g, lift((GEN)p1[i]));
! 1297: h=nfmod_pol_divres(nf,prhall,Ca,g,NULL);
! 1298: k=nf_pol_mul(nf,tau,gsub(Ca, nf_pol_mul(nf,lift(g),lift(h))));
! 1299: p2=nfmod_pol_gcd(nf,prhall,g,h);
! 1300: k= nfmod_pol_gcd(nf,prhall,p2,k);
! 1301:
! 1302: d=degpol(k); /* <= m */
! 1303: vt = idealval(nf,discsr(T),pr) - 2*d;
! 1304: res[3]=lstoi(vt);
! 1305: if (!d || vt<=1) res[1]=un; else res[1]=zero;
! 1306:
! 1307: base=cgetg(3,t_VEC);
! 1308: p1=cgetg(m+d+1,t_MAT); base[1]=(long)p1;
! 1309: p2=cgetg(m+d+1,t_VEC); base[2]=(long)p2;
! 1310: /* if d > 0, base[2] temporarily multiplied by p, for the final nfhermitemod
! 1311: * [ which requires integral ideals ] */
! 1312: matid = gscalmat(d? p: gun, n);
! 1313: for (j=1; j<=m; j++)
! 1314: {
! 1315: p2[j]=(long)matid;
! 1316: p1[j]=lgetg(m+1,t_COL);
! 1317: for (i=1; i<=m; i++)
! 1318: coeff(p1,i,j) = (i==j)?(long)vecun:(long)veczero;
! 1319: }
! 1320: if (d)
! 1321: {
! 1322: GEN pal = lift(nfmod_pol_divres(nf,prhall,Ca,k,NULL));
! 1323: GEN prinvp = pidealprimeinv(nf,pr); /* again multiplied by p */
! 1324: GEN nfx = unifpol(nf,polx[varn(T)],0);
! 1325:
! 1326: for ( ; j<=m+d; j++)
! 1327: {
! 1328: p1[j]=lgetg(m+1,t_COL);
! 1329: da=degpol(pal);
! 1330: for (i=1; i<=da+1; i++) coeff(p1,i,j)=pal[i+1];
! 1331: for ( ; i<=m; i++) coeff(p1,i,j)=(long)veczero;
! 1332: p2[j]=(long)prinvp;
! 1333: nf_pol_divres(nf,nf_pol_mul(nf,pal,nfx),T,&pal);
! 1334: }
! 1335: /* the modulus is integral */
! 1336: base = nfhermitemod(nf,base, gmul(gpowgs(p, m-d),
! 1337: idealpows(nf, prinvp, d)));
! 1338: base[2] = ldiv((GEN)base[2], p); /* cancel the factor p */
! 1339: }
! 1340: res[2]=(long)base; return gerepilecopy(av, res);
! 1341: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>