Annotation of OpenXM_contrib/pari-2.2/src/modules/nffactor.c, Revision 1.1.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>