Annotation of OpenXM_contrib/pari/src/basemath/base2.c, Revision 1.1.1.1
1.1 maekawa 1: /*******************************************************************/
2: /* */
3: /* MAXIMAL ORDERS */
4: /* */
5: /*******************************************************************/
6: /* $Id: base2.c,v 1.4 1999/09/21 19:17:40 karim Exp $ */
7: #include "pari.h"
8:
9: GEN caractducos(GEN p, GEN x, int v);
10: GEN element_muli(GEN nf, GEN x, GEN y);
11: GEN element_mulid(GEN nf, GEN x, long i);
12: GEN eleval(GEN f,GEN h,GEN a);
13: GEN ideal_better_basis(GEN nf, GEN x, GEN M);
14: long int_elt_val(GEN nf, GEN x, GEN p, GEN bp, long v);
15: GEN mat_to_vecpol(GEN x, long v);
16: GEN nfidealdet1(GEN nf, GEN a, GEN b);
17: GEN nfsuppl(GEN nf, GEN x, long n, GEN prhall);
18: GEN pol_to_monic(GEN pol, GEN *lead);
19: GEN pol_to_vec(GEN x, long N);
20: GEN quicktrace(GEN x, GEN sym);
21: GEN respm(GEN f1,GEN f2,GEN pm);
22:
23: static void
24: allbase_check_args(GEN f, long code, GEN *y, GEN *ptw1, GEN *ptw2)
25: {
26: GEN w,w1,w2,q;
27: long i,h;
28:
29: if (typ(f)!=t_POL) err(notpoler,"allbase");
30: if (lgef(f)<=3) err(constpoler,"allbase");
31: *y=discsr(f);
32: if (!signe(*y)) err(talker,"reducible polynomial in allbase");
33: if (DEBUGLEVEL) timer2();
34: switch(code)
35: {
36: case 0: case 1:
37: w=auxdecomp(absi(*y),1-code);
38: w1=(GEN)w[1]; w2=(GEN)w[2]; break;
39: default: w=(GEN)code;
40: if (typ(w)!=t_MAT || lg(w)!=3)
41: err(talker,"not a n x 2 matrix as factorization in factoredbase");
42: w1=(GEN)w[1]; w2=(GEN)w[2]; h=lg(w1); q=gun;
43: for (i=1; i<h; i++)
44: q=gmul(q,powgi((GEN)w1[i], (GEN)w2[i]));
45: if (gcmp(absi(q), absi(*y)))
46: err(talker,"incorrect factorization in factoredbase");
47: }
48: if (DEBUGLEVEL) msgtimer("disc. factorisation");
49: *ptw1=w1; *ptw2=w2;
50: }
51:
52: /*******************************************************************/
53: /* */
54: /* ROUND 2 */
55: /* */
56: /*******************************************************************/
57: /* Normalized quotient and remainder ( -1/2 |y| < r = x-q*y <= 1/2 |y| ) */
58: static GEN
59: rquot(GEN x, GEN y)
60: {
61: long av=avma,av1;
62: GEN u,v,w,p;
63:
64: u=absi(y); v=shifti(x,1); w=shifti(y,1);
65: if (cmpii(u,v)>0) p=subii(v,u);
66: else p=addsi(-1,addii(u,v));
67: av1=avma; return gerepile(av,av1,divii(p,w));
68: }
69:
70: /* space needed lx + 2*ly */
71: static GEN
72: rrmdr(GEN x, GEN y)
73: {
74: long av=avma,tetpil,k;
75: GEN r,ys2;
76:
77: if (!signe(x)) return gzero;
78: r = resii(x,y); tetpil = avma;
79: ys2 = shifti(y,-1);
80: k = absi_cmp(r, ys2);
81: if (k>0 || (k==0 && signe(r)>0))
82: {
83: avma = tetpil;
84: if (signe(y) == signe(r)) r = subii(r,y); else r = addii(r,y);
85: return gerepile(av,tetpil,r);
86: }
87: avma = tetpil; return r;
88: }
89:
90: /* companion matrix of unitary polynomial x */
91: static GEN
92: companion(GEN x) /* cf assmat */
93: {
94: long i,j,l;
95: GEN y;
96:
97: l=lgef(x)-2; y=cgetg(l,t_MAT);
98: for (j=1; j<l; j++)
99: {
100: y[j] = lgetg(l,t_COL);
101: for (i=1; i<l-1; i++)
102: coeff(y,i,j)=(i+1==j)? un: zero;
103: coeff(y,i,j) = lneg((GEN)x[j+1]);
104: }
105: return y;
106: }
107:
108: /* assume x, y are square integer matrices of same dim. Multiply them */
109: static GEN
110: mulmati(GEN x, GEN y)
111: {
112: long n = lg(x),i,j,k,av;
113: GEN z = cgetg(n,t_MAT),p1,p2;
114:
115: for (j=1; j<n; j++)
116: {
117: z[j] = lgetg(n,t_COL);
118: for (i=1; i<n; i++)
119: {
120: p1=gzero; av=avma;
121: for (k=1; k<n; k++)
122: {
123: p2=mulii(gcoeff(x,i,k),gcoeff(y,k,j));
124: if (p2 != gzero) p1=addii(p1,p2);
125: }
126: coeff(z,i,j)=lpileupto(av,p1);
127: }
128: }
129: return z;
130: }
131:
132: static GEN
133: powmati(GEN x, long m)
134: {
135: long av=avma,j;
136: GEN y = x;
137:
138: j=1+bfffo(m); m<<=j; j = BITS_IN_LONG-j;
139: for (; j; m<<=1,j--)
140: {
141: y=mulmati(y,y);
142: if (m<0) y=mulmati(y,x);
143: }
144: return gerepileupto(av,y);
145: }
146:
147: static GEN
148: rtran(GEN v, GEN w, GEN q)
149: {
150: long av,tetpil;
151: GEN p1;
152:
153: if (signe(q))
154: {
155: av=avma; p1=gneg(gmul(q,w)); tetpil=avma;
156: return gerepile(av,tetpil,gadd(v,p1));
157: }
158: return v;
159: }
160:
161: /* return (v - qw) mod m (only compute entries k0,..,n)
162: * v and w are expected to have entries smaller than m */
163: static GEN
164: mtran(GEN v, GEN w, GEN q, GEN m, long k0)
165: {
166: long k,l;
167: GEN p1;
168:
169: if (signe(q))
170: {
171: l = lgefint(m) << 2;
172: for (k=lg(v)-1; k>= k0; k--)
173: {
174: long av = avma; (void)new_chunk(l);
175: p1 = subii((GEN)v[k], mulii(q,(GEN)w[k]));
176: avma = av; v[k]=(long)rrmdr(p1, m);
177: }
178: }
179: return v;
180: }
181:
182: /* entries of v and w are C small integers */
183: static GEN
184: mtran_long(GEN v, GEN w, long q, long m, long k0)
185: {
186: long k, p1;
187:
188: if (q)
189: {
190: for (k=lg(v)-1; k>= k0; k--)
191: {
192: p1 = v[k] - q * w[k];
193: v[k] = p1 % m;
194: }
195: }
196: return v;
197: }
198:
199: /* coeffs of a are C-long integers */
200: static void
201: rowred_long(GEN a, long rmod)
202: {
203: long q,j,k,pro, c = lg(a), r = lg(a[1]);
204:
205: for (j=1; j<r; j++)
206: {
207: for (k=j+1; k<c; k++)
208: while (coeff(a,j,k))
209: {
210: q = coeff(a,j,j) / coeff(a,j,k);
211: pro=(long)mtran_long((GEN)a[j],(GEN)a[k],q,rmod, j);
212: a[j]=a[k]; a[k]=pro;
213: }
214: if (coeff(a,j,j) < 0)
215: for (k=j; k<r; k++) coeff(a,k,j)=-coeff(a,k,j);
216: for (k=1; k<j; k++)
217: {
218: q = coeff(a,j,k) / coeff(a,j,j);
219: a[k]=(long)mtran_long((GEN)a[k],(GEN)a[j],q,rmod, k);
220: }
221: }
222: /* don't update the 0s in the last columns */
223: for (j=1; j<r; j++)
224: for (k=1; k<r; k++) coeff(a,j,k) = lstoi(coeff(a,j,k));
225: }
226:
227: static void
228: rowred(GEN a, GEN rmod)
229: {
230: long j,k,pro, c = lg(a), r = lg(a[1]);
231: long av=avma, lim=stack_lim(av,1);
232: GEN q;
233:
234: for (j=1; j<r; j++)
235: {
236: for (k=j+1; k<c; k++)
237: while (signe(gcoeff(a,j,k)))
238: {
239: q=rquot(gcoeff(a,j,j),gcoeff(a,j,k));
240: pro=(long)mtran((GEN)a[j],(GEN)a[k],q,rmod, j);
241: a[j]=a[k]; a[k]=pro;
242: }
243: if (signe(gcoeff(a,j,j)) < 0)
244: for (k=j; k<r; k++) coeff(a,k,j)=lnegi(gcoeff(a,k,j));
245: for (k=1; k<j; k++)
246: {
247: q=rquot(gcoeff(a,j,k),gcoeff(a,j,j));
248: a[k]=(long)mtran((GEN)a[k],(GEN)a[j],q,rmod, k);
249: }
250: if (low_stack(lim, stack_lim(av,1)))
251: {
252: long j1,k1, tetpil = avma;
253: GEN p1 = a;
254: if(DEBUGMEM>1) err(warnmem,"rowred j=%ld", j);
255: p1 = gerepile(av,tetpil,gcopy(a));
256: for (j1=1; j1<r; j1++)
257: for (k1=1; k1<c; k1++) coeff(a,j1,k1) = coeff(p1,j1,k1);
258: }
259: }
260: }
261:
262: /* Calcule d/x ou d est entier et x matrice triangulaire inferieure
263: * entiere dont les coeff diagonaux divisent d (resultat entier).
264: */
265: static GEN
266: matinv(GEN x, GEN d, long n)
267: {
268: long i,j,k,av,av1;
269: GEN y,h;
270:
271: y=idmat(n);
272: for (i=1; i<=n; i++)
273: coeff(y,i,i)=ldivii(d,gcoeff(x,i,i));
274: av=avma;
275: for (i=2; i<=n; i++)
276: for (j=i-1; j; j--)
277: {
278: for (h=gzero,k=j+1; k<=i; k++)
279: {
280: GEN p1 = mulii(gcoeff(y,i,k),gcoeff(x,k,j));
281: if (p1 != gzero) h=addii(h,p1);
282: }
283: setsigne(h,-signe(h)); av1=avma;
284: coeff(y,i,j) = lpile(av,av1,divii(h,gcoeff(x,j,j)));
285: av = avma;
286: }
287: return y;
288: }
289:
290: static GEN
291: ordmax(GEN *cf, GEN p, long epsilon, GEN *ptdelta)
292: {
293: long sp,hard_case_exponent,i,n=lg(cf)-1,av=avma, av2,limit;
294: GEN T,T2,Tn,m,v,delta, *w;
295: const GEN pp = sqri(p);
296: const long pps = (2*expi(pp)+2<BITS_IN_LONG)? pp[2]: 0;
297:
298: if (cmpis(p,n) > 0) hard_case_exponent = 0;
299: else
300: {
301: long k;
302: k = sp = itos(p);
303: i=1; while (k < n) { k *= sp; i++; }
304: hard_case_exponent = i;
305: }
306: T=cgetg(n+1,t_MAT); for (i=1; i<=n; i++) T[i]=lgetg(n+1,t_COL);
307: T2=cgetg(2*n+1,t_MAT); for (i=1; i<=2*n; i++) T2[i]=lgetg(n+1,t_COL);
308: Tn=cgetg(n*n+1,t_MAT); for (i=1; i<=n*n; i++) Tn[i]=lgetg(n+1,t_COL);
309: v = new_chunk(n+1);
310: w = (GEN*)new_chunk(n+1);
311:
312: av2 = avma; limit = stack_lim(av2,1);
313: delta=gun; m=idmat(n);
314:
315: for(;;)
316: {
317: long j,k,h, av0 = avma;
318: GEN t,b,jp,hh,index,p1, dd = sqri(delta), ppdd = mulii(dd,pp);
319:
320: if (DEBUGLEVEL > 3)
321: fprintferr("ROUND2: epsilon = %ld\tavma = %ld\n",epsilon,avma);
322:
323: b=matinv(m,delta,n);
324: for (i=1; i<=n; i++)
325: {
326: for (j=1; j<=n; j++)
327: for (k=1; k<=n; k++)
328: {
329: p1 = j==k? gcoeff(m,i,1): gzero;
330: for (h=2; h<=n; h++)
331: {
332: GEN p2 = mulii(gcoeff(m,i,h),gcoeff(cf[h],j,k));
333: if (p2!=gzero) p1 = addii(p1,p2);
334: }
335: coeff(T,j,k) = (long)rrmdr(p1, ppdd);
336: }
337: p1 = mulmati(m, mulmati(T,b));
338: for (j=1; j<=n; j++)
339: for (k=1; k<=n; k++)
340: coeff(p1,j,k)=(long)rrmdr(divii(gcoeff(p1,j,k),dd),pp);
341: w[i] = p1;
342: }
343:
344: if (hard_case_exponent)
345: {
346: for (j=1; j<=n; j++)
347: {
348: for (i=1; i<=n; i++) coeff(T,i,j) = coeff(w[j],1,i);
349: /* ici la boucle en k calcule la puissance p mod p de w[j] */
350: for (k=1; k<sp; k++)
351: {
352: for (i=1; i<=n; i++)
353: {
354: p1 = gzero;
355: for (h=1; h<=n; h++)
356: {
357: GEN p2=mulii(gcoeff(T,h,j),gcoeff(w[j],h,i));
358: if (p2!=gzero) p1 = addii(p1,p2);
359: }
360: v[i] = lmodii(p1, p);
361: }
362: for (i=1; i<=n; i++) coeff(T,i,j)=v[i];
363: }
364: }
365: t = powmati(T, hard_case_exponent);
366: }
367: else
368: {
369: for (i=1; i<=n; i++)
370: for (j=1; j<=n; j++)
371: {
372: long av1 = avma;
373: p1 = gzero;
374: for (k=1; k<=n; k++)
375: for (h=1; h<=n; h++)
376: {
377: const GEN r=modii(gcoeff(w[i],k,h),p);
378: const GEN s=modii(gcoeff(w[j],h,k),p);
379: const GEN p2 = mulii(r,s);
380: if (p2!=gzero) p1 = addii(p1,p2);
381: }
382: coeff(T,i,j) = lpileupto(av1,p1);
383: }
384: t = T;
385: }
386:
387: if (pps)
388: {
389: long ps = p[2];
390: for (i=1; i<=n; i++)
391: for (j=1; j<=n; j++)
392: {
393: coeff(T2,j,i)=(i==j)? ps: 0;
394: coeff(T2,j,n+i)=smodis(gcoeff(t,i,j),ps);
395: }
396: rowred_long(T2,pps);
397: }
398: else
399: {
400: for (i=1; i<=n; i++)
401: for (j=1; j<=n; j++)
402: {
403: coeff(T2,j,i)=(i==j)? (long)p: zero;
404: coeff(T2,j,n+i)=lmodii(gcoeff(t,i,j),p);
405: }
406: rowred(T2,pp);
407: }
408: jp=matinv(T2,p,n);
409: if (pps)
410: {
411: for (k=1; k<=n; k++)
412: {
413: long av1=avma;
414: t = mulmati(mulmati(jp,w[k]), T2);
415: for (h=i=1; i<=n; i++)
416: for (j=1; j<=n; j++)
417: { coeff(Tn,k,h) = itos(divii(gcoeff(t,i,j), p)) % pps; h++; }
418: avma=av1;
419: }
420: avma = av0;
421: rowred_long(Tn,pps);
422: }
423: else
424: {
425: for (k=1; k<=n; k++)
426: {
427: t = mulmati(mulmati(jp,w[k]), T2);
428: for (h=i=1; i<=n; i++)
429: for (j=1; j<=n; j++)
430: { coeff(Tn,k,h) = ldivii(gcoeff(t,i,j), p); h++; }
431: }
432: rowred(Tn,pp);
433: }
434: for (index=gun,i=1; i<=n; i++)
435: index = mulii(index,gcoeff(Tn,i,i));
436: if (gcmp1(index)) break;
437:
438: m = mulmati(matinv(Tn,index,n), m);
439: hh = delta = mulii(index,delta);
440: for (i=1; i<=n; i++)
441: for (j=1; j<=n; j++)
442: hh = mppgcd(gcoeff(m,i,j),hh);
443: if (!is_pm1(hh))
444: {
445: m = gdiv(m,hh);
446: delta = divii(delta,hh);
447: }
448: epsilon -= 2 * ggval(index,p);
449: if (epsilon < 2) break;
450: if (low_stack(limit,stack_lim(av2,1)))
451: {
452: GEN *gptr[3]; gptr[0]=&m; gptr[1]=δ
453: if(DEBUGMEM>1) err(warnmem,"ordmax");
454: gerepilemany(av2, gptr,2);
455: }
456: }
457: {
458: GEN *gptr[2]; gptr[0]=&m; gptr[1]=δ
459: gerepilemany(av,gptr,2);
460: }
461: *ptdelta=delta; return m;
462: }
463:
464: #if 0
465: static void
466: to_col(GEN x, GEN col)
467: {
468: long i,n = lg(col), k = lgef(x)-1;
469: x++;
470: for (i=1; i<k; i++) col[i] = x[i];
471: for ( ; i<n; i++) col[i] = zero;
472: }
473:
474: static GEN
475: ordmax2(GEN f, GEN p, long epsilon, GEN *ptdelta)
476: {
477: long sp,i,n=lgef(f)-3,av=avma, av2,limit;
478: GEN col,sym,hard_case_exponent,T2,Tn,m,v,delta,w,a;
479: const GEN pp = sqri(p);
480:
481: if (cmpis(p,n) > 0)
482: {
483: hard_case_exponent = NULL;
484: sym = polsym(f,n-1);
485: }
486: else
487: {
488: long k; k = sp = itos(p);
489: while (k < n) k *= sp;
490: hard_case_exponent = stoi(k);
491: }
492: col = cgetg(n+1,t_COL);
493: T2=cgetg(2*n+1,t_MAT); for (i=1; i<=2*n; i++) T2[i]=lgetg(n+1,t_COL);
494: Tn=cgetg(n*n+1,t_MAT); for (i=1; i<=n*n; i++) Tn[i]=lgetg(n+1,t_COL);
495: v = new_chunk(n+1);
496:
497: av2 = avma; limit = stack_lim(av2,1);
498: delta=gun; m=idmat(n);
499:
500: for(;;)
501: {
502: long j,k,h, av0 = avma;
503: GEN hh,index,p1;
504:
505: if (DEBUGLEVEL > 3)
506: fprintferr("ROUND2: epsilon = %ld\tavma = %ld\n",epsilon,avma);
507:
508: w = mat_to_vecpol(m, 0);
509: if (hard_case_exponent)
510: {
511: for (i=1; i<=n; i++)
512: {
513: p1 = Fp_pow_mod_pol((GEN)w[i], hard_case_exponent, f,p);
514: to_col(p1, (GEN)T2[i]);
515: }
516: for (i=1; i<=n; i++) /* transpose */
517: for (j=1; j<i; j++)
518: {
519: p1 = gcoeff(T2,i,j);
520: coeff(T2,i,j) = coeff(T2,j,i);
521: coeff(T2,j,i)= (long)p1;
522: }
523: }
524: else
525: {
526: for (i=1; i<=n; i++)
527: {
528: for (j=1; j<i; j++)
529: {
530: p1 = Fp_res(gmul((GEN)w[i], (GEN)w[j]), f, p);
531: coeff(T2,j,i) = coeff(T2,i,j) = lresii(quicktrace(p1,sym), p);
532: }
533: p1 = Fp_res(gsqr((GEN)w[i]), f, p);
534: coeff(T2,i,i) = lresii(quicktrace(p1,sym), p);
535: }
536: }
537: for (i=1; i<=n; i++)
538: for (j=1; j<=n; j++)
539: coeff(T2,j,n+i)=(i==j)? (long)p : zero;
540: rowred(T2,pp);
541: a = mat_to_vecpol(matinv(T2,p,n), 0);
542: if (2*expi(pp)+2<BITS_IN_LONG)
543: {
544: for (k=1; k<=n; k++)
545: {
546: long av1=avma;
547: for (h=i=1; i<=n; i++)
548: {
549: p1 = gres(gmul((GEN)a[i], (GEN)w[k]), f);
550: to_col(p1, col);
551: for (j=1; j<=n; j++)
552: { coeff(Tn,k,h)=itos(divii((GEN)col[j],p)); h++; }
553: }
554: avma=av1;
555: }
556: avma = av0;
557: rowred_long(Tn,pp[2]);
558: }
559: else
560: {
561: for (k=1; k<=n; k++)
562: {
563: for (h=i=1; i<=n; i++)
564: {
565: p1 = gres(gmul((GEN)a[i], (GEN)w[k]), f);
566: to_col(p1, col);
567: for (j=1; j<=n; j++)
568: #if 0
569: { coeff(Tn,k,h)=ldivii((GEN)col[j],p); h++; }
570: #endif
571: { coeff(Tn,k,h)=col[j]; h++; }
572: }
573: }
574: rowred(Tn,pp);
575: }
576: for (index=gun,i=1; i<=n; i++)
577: index = mulii(index,gcoeff(Tn,i,i));
578: if (gcmp1(index)) break;
579:
580: m = mulmati(matinv(Tn,index,n), m);
581: hh = delta = mulii(index,delta);
582: for (i=1; i<=n; i++)
583: for (j=1; j<=n; j++)
584: hh = mppgcd(gcoeff(m,i,j),hh);
585: if (!is_pm1(hh))
586: {
587: m = gdiv(m,hh);
588: delta = divii(delta,hh);
589: }
590: epsilon -= 2 * ggval(index,p);
591: if (epsilon < 2) break;
592: if (low_stack(limit,stack_lim(av2,1)))
593: {
594: GEN *gptr[3]; gptr[0]=&m; gptr[1]=δ
595: if(DEBUGMEM>1) err(warnmem,"ordmax");
596: gerepilemany(av2, gptr,2);
597: }
598: }
599: {
600: GEN *gptr[2]; gptr[0]=&m; gptr[1]=δ
601: gerepilemany(av,gptr,2);
602: }
603: *ptdelta=delta; return m;
604: }
605: #endif
606:
607: /* Input:
608: * x normalized integral polynomial of degree n, defining K=Q(theta).
609: *
610: * code 0, 1 or (long)p if we want base, smallbase ou factoredbase (resp.).
611: * y is GEN *, which will receive the discriminant of K.
612: *
613: * Output
614: * 1) A t_COL whose n components are rationnal polynomials (with degree
615: * 0,1...n-1) : integral basis for K (putting x=theta).
616: * Rem: common denominator is in da.
617: *
618: * 2) discriminant of K (in *y).
619: */
620: GEN
621: allbase(GEN f, long code, GEN *y)
622: {
623: GEN w1,w2,a,pro,at,bt,b,da,db,q, *cf,*gptr[2];
624: long av=avma,tetpil,n,h,j,i,k,r,s,t,v,mf;
625:
626: allbase_check_args(f,code,y, &w1,&w2);
627: v = varn(f); n = lgef(f)-3; h = lg(w1)-1;
628: cf = (GEN*)cgetg(n+1,t_VEC);
629: cf[2]=companion(f);
630: for (i=3; i<=n; i++) cf[i]=mulmati(cf[2],cf[i-1]);
631:
632: a=idmat(n); da=gun;
633: for (i=1; i<=h; i++)
634: {
635: long av1 = avma;
636: mf=itos((GEN)w2[i]); if (mf==1) continue;
637: if (DEBUGLEVEL) fprintferr("Treating p^k = %Z^%ld\n",w1[i],mf);
638:
639: b=ordmax(cf,(GEN)w1[i],mf,&db);
640: a=gmul(db,a); b=gmul(da,b);
641: da=mulii(db,da);
642: at=gtrans(a); bt=gtrans(b);
643: for (r=n; r; r--)
644: for (s=r; s; s--)
645: while (signe(gcoeff(bt,s,r)))
646: {
647: q=rquot(gcoeff(at,s,s),gcoeff(bt,s,r));
648: pro=rtran((GEN)at[s],(GEN)bt[r],q);
649: for (t=s-1; t; t--)
650: {
651: q=rquot(gcoeff(at,t,s),gcoeff(at,t,t));
652: pro=rtran(pro,(GEN)at[t],q);
653: }
654: at[s]=bt[r]; bt[r]=(long)pro;
655: }
656: for (j=n; j; j--)
657: {
658: for (k=1; k<j; k++)
659: {
660: while (signe(gcoeff(at,j,k)))
661: {
662: q=rquot(gcoeff(at,j,j),gcoeff(at,j,k));
663: pro=rtran((GEN)at[j],(GEN)at[k],q);
664: at[j]=at[k]; at[k]=(long)pro;
665: }
666: }
667: if (signe(gcoeff(at,j,j))<0)
668: for (k=1; k<=j; k++) coeff(at,k,j)=lnegi(gcoeff(at,k,j));
669: for (k=j+1; k<=n; k++)
670: {
671: q=rquot(gcoeff(at,j,k),gcoeff(at,j,j));
672: at[k]=(long)rtran((GEN)at[k],(GEN)at[j],q);
673: }
674: }
675: for (j=2; j<=n; j++)
676: if (egalii(gcoeff(at,j,j), gcoeff(at,j-1,j-1)))
677: {
678: coeff(at,1,j)=zero;
679: for (k=2; k<=j; k++) coeff(at,k,j)=coeff(at,k-1,j-1);
680: }
681: tetpil=avma; a=gtrans(at);
682: {
683: GEN *gptr[2];
684: da = icopy(da); gptr[0]=&a; gptr[1]=&da;
685: gerepilemanysp(av1,tetpil,gptr,2);
686: }
687: }
688: for (j=1; j<=n; j++)
689: *y = divii(mulii(*y,sqri(gcoeff(a,j,j))), sqri(da));
690: tetpil=avma; *y=icopy(*y);
691: at=cgetg(n+1,t_VEC); v=varn(f);
692: for (k=1; k<=n; k++)
693: {
694: q=cgetg(k+2,t_POL); at[k]=(long)q;
695: q[1] = evalsigne(1) | evallgef(2+k) | evalvarn(v);
696: for (j=1; j<=k; j++) q[j+1]=ldiv(gcoeff(a,k,j),da);
697: }
698: gptr[0]=&at; gptr[1]=y;
699: gerepilemanysp(av,tetpil,gptr,2);
700: return at;
701: }
702:
703: GEN
704: base2(GEN x, GEN *y)
705: {
706: return allbase(x,0,y);
707: }
708:
709: GEN
710: discf2(GEN x)
711: {
712: GEN y;
713: long av=avma,tetpil;
714:
715: allbase(x,0,&y); tetpil=avma;
716: return gerepile(av,tetpil,icopy(y));
717: }
718:
719: /*******************************************************************/
720: /* */
721: /* ROUND 4 */
722: /* */
723: /*******************************************************************/
724:
725: static GEN Decomp(GEN p,GEN f,long mf,GEN theta,GEN chi,GEN nu);
726: static GEN dbasis(GEN p, GEN f, long mf, GEN alpha, GEN U);
727: static GEN eltppm(GEN f,GEN pd,GEN theta,GEN k);
728: static GEN maxord(GEN p,GEN f,long mf);
729: static GEN nbasis(GEN ibas,GEN pd);
730: #if 0
731: static GEN nilord(GEN p,GEN fx,long mf,GEN gx);
732: #endif
733: static GEN nilord2(GEN p,GEN fx,long mf,GEN gx);
734: static GEN testd(GEN p,GEN fa,long c,long Da,GEN alph2,long Ma,GEN theta);
735: static GEN testb(GEN p,GEN fa,long Da,GEN theta,long Dt);
736: static GEN testb2(GEN p,GEN fa,long Fa,GEN theta,long Ft);
737: static GEN testc2(GEN p,GEN fa,GEN pmr,GEN alph2,long Ea,GEN thet2,long Et);
738:
739: static long clcm(long a,long b);
740:
741: static int
742: fnz(GEN x,long j)
743: {
744: long i=1; while (!signe(x[i])) i++;
745: return i==j;
746: }
747:
748: /* retourne la base, dans y le discf et dans ptw la factorisation (peut
749: etre partielle) de discf */
750: GEN
751: allbase4(GEN f,long code, GEN *y, GEN *ptw)
752: {
753: GEN w,w1,w2,a,da,b,db,bas,q,p1,*gptr[3];
754: long v,n,mf,h,lfa,i,j,k,l,first,tetpil,av = avma;
755:
756: allbase_check_args(f,code,y, &w1,&w2);
757: first=1; v = varn(f); n = lgef(f)-3; h = lg(w1)-1;
758: for (i=1; i<=h; i++)
759: {
760: mf=itos((GEN)w2[i]); if (mf == 1) continue;
761: if (DEBUGLEVEL) fprintferr("Treating p^k = %Z^%ld\n",w1[i],mf);
762:
763: b = maxord((GEN)w1[i],f,mf);
764: p1=cgetg(n+1,t_VEC); for (j=1; j<=n; j++) p1[j]=coeff(b,j,j);
765: db=denom(p1);
766: if (! gcmp1(db))
767: {
768: if (first==1) { da=db; a=gmul(b,db); first=0; }
769: else
770: {
771: da=mulii(da,db); b=gmul(da,b); a=gmul(db,a);
772: j=1; while (j<=n && fnz((GEN)a[j],j) && fnz((GEN)b[j],j)) j++;
773: k=j-1; p1=cgetg(2*n-k+1,t_MAT);
774: for (j=1; j<=k; j++)
775: {
776: p1[j]=a[j];
777: coeff(p1,j,j) = lmppgcd(gcoeff(a,j,j),gcoeff(b,j,j));
778: }
779: for ( ; j<=n; j++) p1[j]=a[j];
780: for ( ; j<=2*n-k; j++) p1[j]=b[j+k-n];
781: a=hnfmod(p1,detint(p1));
782: }
783: }
784: if (DEBUGLEVEL>5)
785: fprintferr("Result for prime %Z is:\n%Z\n",w1[i],b);
786: }
787: if (!first)
788: {
789: for (j=1; j<=n; j++)
790: *y = mulii(divii(*y,sqri(da)),sqri(gcoeff(a,j,j)));
791: for (j=n-1; j; j--)
792: if (cmpis(gcoeff(a,j,j),2) > 0)
793: {
794: p1=shifti(gcoeff(a,j,j),-1);
795: for (k=j+1; k<=n; k++)
796: if (cmpii(gcoeff(a,j,k),p1) > 0)
797: for (l=1; l<=j; l++)
798: coeff(a,l,k)=lsubii(gcoeff(a,l,k),gcoeff(a,l,j));
799: }
800: }
801: if (ptw)
802: {
803: lfa=0;
804: for (j=1; j<=h; j++)
805: {
806: k=ggval(*y,(GEN)w1[j]);
807: if (k) { lfa++; w1[lfa]=w1[j]; w2[lfa]=k; }
808: }
809: }
810: tetpil=avma; *y=icopy(*y);
811: bas=cgetg(n+1,t_VEC); v=varn(f);
812: for (k=1; k<=n; k++)
813: {
814: q=cgetg(k+2,t_POL); bas[k]=(long)q;
815: q[1] = evalsigne(1) | evallgef(k+2) | evalvarn(v);
816: if (!first)
817: for (j=1; j<=k; j++) q[j+1]=ldiv(gcoeff(a,j,k),da);
818: else
819: {
820: for (j=2; j<=k; j++) q[j]=zero;
821: q[j]=un;
822: }
823: }
824: if (ptw)
825: {
826: *ptw=w=cgetg(3,t_MAT); w[1]=lgetg(lfa+1,t_COL); w[2]=lgetg(lfa+1,t_COL);
827: for (j=1; j<=lfa; j++)
828: {
829: coeff(w,j,1)=(long)icopy((GEN)w1[j]);
830: coeff(w,j,2)=lstoi(w2[j]);
831: }
832: gptr[2]=ptw;
833: }
834: gptr[0]=&bas; gptr[1]=y;
835: gerepilemanysp(av,tetpil,gptr, ptw?3:2);
836: return bas;
837: }
838:
839: /* if y is non-NULL, it receives the discriminant
840: * return basis if (ret_basis != 0), discriminant otherwise
841: */
842: static GEN
843: nfbasis00(GEN x, long flag, GEN p, long ret_basis, GEN *y)
844: {
845: GEN disc, basis, lead;
846: GEN *gptr[2];
847: long k, tetpil, av = avma, n = lgef(x)-3, smll;
848:
849: if (typ(x)!=t_POL) err(typeer,"nfbasis00");
850: if (n<=0) err(zeropoler,"nfbasis00");
851: for (k=n+2; k>=2; k--)
852: if (typ(x[k])!=t_INT) err(talker,"polynomial not in Z[X] in nfbasis");
853:
854: x = pol_to_monic(x,&lead);
855:
856: if (!p || gcmp0(p))
857: smll = (flag & 1); /* small basis */
858: else
859: smll = (long) p; /* factored basis */
860:
861: if (flag & 2)
862: basis = allbase(x,smll,&disc); /* round 2 */
863: else
864: basis = allbase4(x,smll,&disc,NULL); /* round 4 */
865:
866: tetpil=avma;
867: if (!ret_basis)
868: return gerepile(av,tetpil,gcopy(disc));
869:
870: if (!lead) basis = gcopy(basis);
871: else
872: {
873: long v = varn(x);
874: GEN pol = gmul(polx[v],lead);
875:
876: tetpil = avma; basis = gsubst(basis,v,pol);
877: }
878: if (!y)
879: return gerepile(av,tetpil,basis);
880:
881: *y = gcopy(disc);
882: gptr[0]=&basis; gptr[1]=y;
883: gerepilemanysp(av,tetpil,gptr,2);
884: return basis;
885: }
886:
887: GEN
888: nfbasis(GEN x, GEN *y, long flag, GEN p)
889: {
890: return nfbasis00(x,flag,p,1,y);
891: }
892:
893: GEN
894: nfbasis0(GEN x, long flag, GEN p)
895: {
896: return nfbasis00(x,flag,p,1,NULL);
897: }
898:
899: GEN
900: nfdiscf0(GEN x, long flag, GEN p)
901: {
902: return nfbasis00(x,flag,p,0,&p);
903: }
904:
905: GEN
906: base(GEN x, GEN *y)
907: {
908: return allbase4(x,0,y,NULL);
909: }
910:
911: GEN
912: smallbase(GEN x, GEN *y)
913: {
914: return allbase4(x,1,y,NULL);
915: }
916:
917: GEN
918: factoredbase(GEN x, GEN p, GEN *y)
919: {
920: return allbase4(x,(long)p,y,NULL);
921: }
922:
923: GEN
924: discf(GEN x)
925: {
926: GEN y;
927: long av=avma,tetpil;
928:
929: allbase4(x,0,&y,NULL); tetpil=avma;
930: return gerepile(av,tetpil,icopy(y));
931: }
932:
933: GEN
934: smalldiscf(GEN x)
935: {
936: GEN y;
937: long av=avma,tetpil;
938:
939: allbase4(x,1,&y,NULL); tetpil=avma;
940: return gerepile(av,tetpil,icopy(y));
941: }
942:
943: GEN
944: factoreddiscf(GEN x, GEN p)
945: {
946: GEN y;
947: long av=avma,tetpil;
948:
949: allbase4(x,(long)p,&y,NULL); tetpil=avma;
950: return gerepile(av,tetpil,icopy(y));
951: }
952:
953: /* return U if Z[alpha] is not maximal or 2*dU < m-1; else return NULL */
954: static GEN
955: dedek(GEN f, long mf, GEN p,GEN g)
956: {
957: GEN k,h;
958: long dk;
959:
960: if (DEBUGLEVEL>=3)
961: {
962: fprintferr(" entering dedek ");
963: if (DEBUGLEVEL>5)
964: fprintferr("with parameters p=%Z,\n f=%Z",p,f);
965: fprintferr("\n");
966: }
967: h = Fp_deuc(f,g,p);
968: k = gdiv(gadd(f, gneg_i(gmul(g,h))), p);
969: k = Fp_pol_gcd(k, Fp_pol_gcd(g,h, p), p);
970:
971: dk = lgef(k)-3;
972: if (DEBUGLEVEL>=3) fprintferr(" gcd has degree %ld\n", dk);
973: if (2*dk >= mf-1) return Fp_deuc(f,k,p);
974: return dk? (GEN)NULL: f;
975: }
976:
977: /* p-maximal order of Af; mf = v_p(Disc(f)) */
978: static GEN
979: maxord(GEN p,GEN f,long mf)
980: {
981: long j,r, av = avma, flw = (cmpsi(lgef(f)-3,p) < 0);
982: GEN w,g,h,res;
983:
984: if (flw)
985: g = Fp_deuc(f, Fp_pol_gcd(f,derivpol(f), p), p);
986: else
987: {
988: w=(GEN)factmod(f,p)[1]; r=lg(w)-1;
989: g = h = lift_intern((GEN)w[r]); /* largest factor */
990: for (j=1; j<r; j++) g = Fp_pol_red(gmul(g, lift_intern((GEN)w[j])), p);
991: }
992: res = dedek(f,mf,p,g);
993: if (res)
994: res = dbasis(p,f,mf,polx[varn(f)],res);
995: else
996: {
997: if (flw) { w=(GEN)factmod(f,p)[1]; r=lg(w)-1; h=lift_intern((GEN)w[r]); }
998: #if 0
999: res = (r==1)? nilord(p,f,mf,h): Decomp(p,f,mf,polx[varn(f)],f,h);
1000: #else
1001: res = (r==1)? nilord2(p,f,mf,h): Decomp(p,f,mf,polx[varn(f)],f,h);
1002: #endif
1003: }
1004: return gerepileupto(av,res);
1005: }
1006:
1007: /* do a centermod on integer or rational number */
1008: static GEN
1009: polmodiaux(GEN x, GEN y, GEN ys2)
1010: {
1011: if (typ(x)!=t_INT)
1012: x = mulii((GEN)x[1], mpinvmod((GEN)x[2],y));
1013: x = modii(x,y);
1014: if (cmpii(x,ys2) > 0) x = subii(x,y);
1015: return x;
1016: }
1017:
1018: /* x polynomial with integer or rational coeff. Reduce them mod y IN PLACE */
1019: GEN
1020: polmodi(GEN x, GEN y)
1021: {
1022: long lx=lgef(x), i;
1023: GEN ys2 = shifti(y,-1);
1024: for (i=2; i<lx; i++) x[i]=(long)polmodiaux((GEN)x[i],y,ys2);
1025: return normalizepol_i(x, lx);
1026: }
1027:
1028: /* same but not in place */
1029: GEN
1030: polmodi_keep(GEN x, GEN y)
1031: {
1032: long lx=lgef(x), i;
1033: GEN ys2 = shifti(y,-1);
1034: GEN z = cgetg(lx,t_POL);
1035: for (i=2; i<lx; i++) z[i]=(long)polmodiaux((GEN)x[i],y,ys2);
1036: z[1]=x[1]; return normalizepol_i(z, lx);
1037: }
1038:
1039: static GEN
1040: dbasis(GEN p, GEN f, long mf, GEN alpha, GEN U)
1041: {
1042: long n=lgef(f)-3,dU,c,i,dh;
1043: GEN b,p1,ha,pd,pdp;
1044:
1045: if (n == 1) return gscalmat(gun, 1);
1046: if (DEBUGLEVEL>=3)
1047: {
1048: fprintferr(" entering Dedekind Basis ");
1049: if (DEBUGLEVEL>5)
1050: {
1051: fprintferr("with parameters p=%Z\n",p);
1052: fprintferr(" f = %Z,\n alpha = %Z",f,alpha);
1053: }
1054: fprintferr("\n");
1055: }
1056: ha = pd = gpuigs(p,mf/2); pdp = mulii(pd,p);
1057: dU = lgef(U)-3;
1058: b = cgetg(n,t_MAT); /* Z[a] + U/p Z[a] is maximal */
1059: /* skip first column = gscalcol(pd,n) */
1060: for (c=1; c<n; c++)
1061: {
1062: p1=cgetg(n+1,t_COL); b[c]=(long)p1;
1063: if (c == dU)
1064: {
1065: ha = gdiv(gmul(pd,eleval(f,U,alpha)),p);
1066: ha = polmodi(ha,pdp);
1067: }
1068: else
1069: {
1070: GEN p2, mod;
1071: ha = gmul(ha,alpha);
1072: p2 = content(ha); /* to cancel denominator */
1073: if (gcmp1(p2)) { p2 = NULL; mod = pdp; }
1074: else
1075: {
1076: ha = gdiv(ha,p2);
1077: if (typ(p2)==t_INT)
1078: mod = divii(pdp, mppgcd(pdp,p2));
1079: else
1080: mod = mulii(pdp, (GEN)p2[2]); /* p2 = a / p^e */
1081: }
1082: ha = Fp_res(ha, f, mod);
1083: if (p2) ha = gmul(ha,p2);
1084: }
1085: dh = lgef(ha)-2;
1086: for (i=1; i<=dh; i++) p1[i]=ha[i+1];
1087: for ( ; i<=n; i++) p1[i]=zero;
1088: }
1089: b = hnfmodid(b,pd);
1090: if (DEBUGLEVEL>5) fprintferr(" new order: %Z\n",b);
1091: return gdiv(b,pd);
1092: }
1093:
1094: static GEN
1095: get_partial_order_as_pols(GEN p, GEN f)
1096: {
1097: long i,j,n=lgef(f)-3, vf = varn(f);
1098: GEN b,ib,h,col;
1099:
1100: b = maxord(p,f, ggval(discsr(f),p));
1101: ib = cgetg(n+1,t_VEC);
1102: for (i=1; i<=n; i++)
1103: {
1104: h=cgetg(i+2,t_POL); ib[i]=(long)h; col=(GEN)b[i];
1105: h[1]=evalsigne(1)|evallgef(i+2)|evalvarn(vf);
1106: for (j=1;j<=i;j++) h[j+1]=col[j];
1107: }
1108: return ib;
1109: }
1110:
1111: static GEN
1112: Decomp(GEN p,GEN f,long mf,GEN theta,GEN chi,GEN nu)
1113: {
1114: GEN pk,ph,pdr,pmr,unmodp;
1115: GEN b1,b2,b3,a1,e,f1,f2,ib1,ib2,ibas;
1116: long n1,n2,j;
1117:
1118: if (DEBUGLEVEL>=3)
1119: {
1120: fprintferr(" entering Decomp ");
1121: if (DEBUGLEVEL>5)
1122: {
1123: fprintferr("with parameters: p=%Z, expo=%ld\n",p,mf);
1124: fprintferr(" f=%Z",f);
1125: }
1126: fprintferr("\n");
1127: }
1128: pdr=respm(f,derivpol(f),gpuigs(p,mf));
1129:
1130: unmodp=gmodulsg(1,p);
1131: b1=lift_intern(gmul(chi,unmodp));
1132: a1=gun; b2=gun;
1133: b3=lift_intern(gmul(nu,unmodp));
1134: while (lgef(b3) > 3)
1135: {
1136: GEN p1;
1137: b1 = Fp_deuc(b1,b3, p);
1138: b2 = Fp_pol_red(gmul(b2,b3), p);
1139: b3 = Fp_pol_extgcd(b2,b1, p, &a1,&p1); /* p1 = junk */
1140: p1 = leading_term(b3);
1141: if (!gcmp1(p1))
1142: { /* Fp_pol_extgcd does not return normalized gcd */
1143: p1 = mpinvmod(p1,p);
1144: b3 = gmul(b3,p1);
1145: a1 = gmul(a1,p1);
1146: }
1147: }
1148: e=eleval(f,Fp_pol_red(gmul(a1,b2), p),theta);
1149: e=gdiv(polmodi(gmul(pdr,e), mulii(pdr,p)),pdr);
1150:
1151: pk=p; pmr=mulii(p,sqri(pdr)); ph=mulii(pdr,pmr);
1152: /* E(t)- e(t) belongs to p^k Op, which is contained in p^(k-df)*Zp[xi] */
1153: while (cmpii(pk,ph) < 0)
1154: {
1155: e = gmul(gsqr(e), gsubsg(3,gmul2n(e,1)));
1156: e = gres(e,f); pk = sqri(pk);
1157: e=gdiv(polmodi(gmul(pdr,e), mulii(pk,pdr)), pdr);
1158: }
1159: f1 = gcdpm(f,gmul(pdr,gsubsg(1,e)), ph);
1160: f1 = Fp_res(f1,f, pmr);
1161: f2 = Fp_res(Fp_deuc(f,f1, pmr), f, pmr);
1162: f1 = polmodi(f1,pmr);
1163: f2 = polmodi(f2,pmr);
1164:
1165: if (DEBUGLEVEL>=3)
1166: {
1167: fprintferr(" leaving Decomp");
1168: if (DEBUGLEVEL>5)
1169: fprintferr(" with parameters: f1 = %Z\nf2 = %Z\ne = %Z\n", f1,f2,e);
1170: fprintferr("\n");
1171: }
1172: ib1 = get_partial_order_as_pols(p,f1); n1=lg(ib1)-1;
1173: ib2 = get_partial_order_as_pols(p,f2); n2=lg(ib2)-1;
1174: ibas=cgetg(n1+n2+1,t_VEC);
1175:
1176: for (j=1; j<=n1; j++)
1177: ibas[j]=(long)polmodi(gmod(gmul(gmul(pdr,(GEN)ib1[j]),e),f), pdr);
1178: e=gsubsg(1,e);
1179: for ( ; j<=n1+n2; j++)
1180: ibas[j]=(long)polmodi(gmod(gmul(gmul(pdr,(GEN)ib2[j-n1]),e),f), pdr);
1181: return nbasis(ibas,pdr);
1182: }
1183:
1184: /* minimum extension valuation: res[0]/res[1] (both are longs) */
1185: long *
1186: vstar(GEN p,GEN h)
1187: {
1188: static long res[2];
1189: long m,first,j,k,v,w;
1190:
1191: m=lgef(h)-3; first=1; k=1; v=0;
1192: for (j=1; j<=m; j++)
1193: if (! gcmp0((GEN)h[m-j+2]))
1194: {
1195: w = ggval((GEN)h[m-j+2],p);
1196: if (first || w*k < v*j) { v=w; k=j; }
1197: first=0;
1198: }
1199: m = cgcd(v,k);
1200: res[0]=v/m; res[1]=k/m; return res;
1201: }
1202:
1203: /* Returns [theta,chi,nu] with theta non-primary */
1204: static GEN
1205: csrch(GEN p,GEN fa,GEN gamma)
1206: {
1207: GEN b,h,theta,w;
1208: long pp,t,v=varn(fa);
1209:
1210: pp = p[2]; if (lgef(p)>3 || pp<0) pp=0;
1211: for (t=1; ; t++)
1212: {
1213: h = pp? stopoly(t,pp,v): scalarpol(stoi(t),v);
1214: theta = gadd(gamma,gmod(h,fa));
1215: w=factcp(p,fa,theta); h=(GEN)w[3];
1216: if (h[2] > 1)
1217: {
1218: b=cgetg(5,t_VEC); b[1]=un; b[2]=(long)theta;
1219: b[3]=w[1]; b[4]=w[2]; return b;
1220: }
1221: }
1222: }
1223:
1224: /* Returns
1225: * [1,theta,chi,nu] if theta non-primary
1226: * [2,phi, * , * ] if D_phi > D_alpha or M_phi > M_alpha
1227: */
1228: GEN
1229: bsrch(GEN p,GEN fa,long ka,GEN eta,long Ma)
1230: {
1231: long n=lgef(fa)-3,Da=lgef(eta)-3;
1232: long c,r,j,MaVb,av=avma;
1233: GEN famod,pc,pcc,beta,gamma,delta,pik,w,h;
1234:
1235: pc=respm(fa,derivpol(fa),gpuigs(p,ka));
1236: c=ggval(pc,p); pcc=sqri(pc);
1237: famod=polmodi_keep(fa,pcc);
1238:
1239: r=1+(long)ceil(c/(double)(Da)+gtodouble(gdivsg(c*n-2,mulsi(Da,subis(p,1)))));
1240:
1241: beta=gdiv(lift_intern(gpuigs(gmodulcp(eta,famod),Ma)),p);
1242:
1243: for(;;)
1244: { /* Compute modulo pc. denom(pik, delta)=1. denom(beta, gamma) | pc */
1245: beta=gdiv(polmodi(gmul(pc,beta),pcc), pc);
1246: w=testd(p,fa,c,Da,eta,Ma,beta);
1247: h=(GEN)w[1]; if (h[2] < 3) return gerepileupto(av,w);
1248:
1249: w = vstar(p,(GEN)w[3]);
1250: MaVb = (w[0]*Ma) / w[1];
1251: pik=eltppm(famod,pc,eta,stoi(MaVb));
1252:
1253: gamma=gmod(gmul(beta,(GEN)(vecbezout(pik,famod))[1]),famod);
1254: gamma=gdiv(polmodi(gmul(pc,gamma),pcc),pc);
1255: w=testd(p,fa,c,Da,eta,Ma,gamma);
1256: h=(GEN)w[1]; if (h[2] < 3) return gerepileupto(av,w);
1257:
1258: delta=eltppm(famod,pc,gamma,gpuigs(p,r*Da));
1259: delta=gdiv(polmodi(gmul(pc,delta),pcc),pc);
1260: w=testd(p,fa,c,Da,eta,Ma,delta);
1261: h=(GEN)w[1]; if (h[2] < 3) return gerepileupto(av,w);
1262:
1263: for (j=lgef(delta)-1; j>1; j--)
1264: if (typ(delta[j]) != t_INT)
1265: {
1266: w = csrch(p,fa,gamma);
1267: return gerepileupto(av,gcopy(w));
1268: }
1269: beta=gsub(beta,gmod(gmul(pik,delta),famod));
1270: }
1271: }
1272:
1273: static GEN
1274: mycaract(GEN f, GEN beta)
1275: {
1276: GEN chi,p1;
1277: long v = varn(f);
1278:
1279: if (gcmp0(beta)) return zeropol(v);
1280: p1 = content(beta);
1281: if (gcmp1(p1)) p1 = NULL; else beta = gdiv(beta,p1);
1282: chi = caractducos(f,beta,v);
1283: if (p1)
1284: {
1285: chi=poleval(chi,gdiv(polx[v],p1));
1286: p1=gpuigs(p1,lgef(f)-3); chi=gmul(chi,p1);
1287: }
1288: return chi;
1289: }
1290:
1291: /* USED TO Return [theta_1,theta_2,L_theta,M_theta] with theta non-primary */
1292: /* Now return theta_2 */
1293: GEN
1294: setup(GEN p,GEN f,GEN theta,GEN nut, long *La, long *Ma)
1295: {
1296: GEN t1,t2,v,dt,pv;
1297: long Lt,Mt,r,s,av=avma,tetpil,m,n,k;
1298:
1299: n=lgef(nut)-1; pv=p;
1300: for (m=1; ; m++) /* compute mod p^(2^m) */
1301: {
1302: t1=gzero; pv = sqri(pv);
1303: for (k=n; k>=2; k--)
1304: {
1305: t1 = gres(gadd(gmul(t1,theta),(GEN)nut[k]), f);
1306: dt = denom(content(t1));
1307: if (gcmp1(dt))
1308: t1 = polmodi(t1,pv);
1309: else
1310: t1 = gdiv(polmodi(gmul(t1,dt),mulii(dt,pv)),dt);
1311: }
1312: v = vstar(p, mycaract(f,t1));
1313: if (v[0] < (v[1]<<m)) break;
1314: }
1315: Lt=v[0]; Mt=v[1]; cbezout(Lt,-Mt,&r,&s);
1316: if (r<=0) { long q = (-r) / Mt; q++; r += q*Mt; s += q*Lt; }
1317: t2 = lift_intern(gpuigs(gmodulcp(t1,f),r));
1318: p = gpuigs(p,s); tetpil=avma; *La=Lt; *Ma=Mt;
1319: return gerepile(av,tetpil,gdiv(t2,p));
1320: }
1321:
1322: #define RED 1
1323:
1324: #if 0
1325: static GEN
1326: nilord(GEN p,GEN fx,long mf,GEN gx)
1327: {
1328: long La,Ma,first=1,v=varn(fx);
1329: GEN h,res,alpha,chi,nu,eta,w,phi,pmf,Dchi,pdr,pmr;
1330:
1331: if (DEBUGLEVEL>=3)
1332: {
1333: fprintferr(" entering Nilord");
1334: if (DEBUGLEVEL>5)
1335: {
1336: fprintferr(" with parameters: p=%Z, expo=%ld\n",p,mf);
1337: fprintferr(" fx=%Z, gx=%Z",fx,gx);
1338: }
1339: fprintferr("\n");
1340: }
1341: pmf=gpuigs(p,mf+1); alpha=polx[v];
1342: nu=gx; chi=fx; Dchi=gpuigs(p,mf);
1343: #if RED
1344: pdr=respm(fx,derivpol(fx), Dchi);
1345: pmr=mulii(sqri(pdr),p); chi = dummycopy(chi);
1346: #endif
1347:
1348: for(;;)
1349: {
1350: #if RED
1351: chi = polmodi(chi, pmr);
1352: #endif
1353: if (first) first=0;
1354: else
1355: {
1356: res=dedek(chi,mf,p,nu);
1357: if (res) return dbasis(p,fx,mf,alpha,res);
1358: }
1359: if (vstar(p,chi)[0] > 0)
1360: {
1361: alpha = gadd(alpha,gun);
1362: chi = poleval(chi, gsub(polx[v],gun));
1363: #if RED
1364: chi = polmodi(chi, pmr);
1365: #endif
1366: nu = polmodi(poleval(nu, gsub(polx[v],gun)), p);
1367: }
1368: eta=setup(p,chi,polx[v],nu, &La,&Ma);
1369: if (La>1)
1370: alpha=gadd(alpha,eleval(fx,eta,alpha));
1371: else
1372: {
1373: w=bsrch(p,chi,ggval(Dchi,p),eta,Ma);
1374: phi=eleval(fx,(GEN)w[2],alpha);
1375: if (gcmp1((GEN)w[1]))
1376: return Decomp(p,fx,mf,phi,(GEN)w[3],(GEN)w[4]);
1377: alpha=gdiv(polmodi(gmul(pmf,phi), mulii(pmf,p)),pmf);
1378: }
1379:
1380: for (;;)
1381: {
1382: w=factcp(p,fx,alpha); chi=(GEN)w[1]; nu=(GEN)w[2]; h=(GEN)w[3];
1383: if (h[2] > 1) return Decomp(p,fx,mf,alpha,chi,nu);
1384: #if 0
1385: Dchi = respm(chi,derivpol(chi), pmf);
1386: #endif
1387: Dchi = modii(discsr(polmodi_keep(chi,pmf)), pmf);
1388: if (gcmp0(Dchi))
1389: {
1390: Dchi= discsr(chi);
1391: if (gcmp0(Dchi)) { alpha=gadd(alpha,gmul(p,polx[v])); continue; }
1392: #if RED
1393: pmr = gpowgs(p, 2 * ggval(Dchi,p) + 1);
1394: #endif
1395: }
1396: break;
1397: }
1398: }
1399: }
1400: #endif
1401:
1402: /* reduce the element elt modulo rd, taking first of the denominators */
1403: static GEN
1404: redelt(GEN elt, GEN rd, GEN pd)
1405: {
1406: GEN den, relt;
1407:
1408: den = ggcd(denom(content(elt)), pd);
1409: relt = polmodi(gmul(den, elt), gmul(den, rd));
1410: return gdiv(relt, den);
1411: }
1412:
1413: /* return the prime element in Zp[phi] */
1414: static GEN
1415: getprime(GEN p, GEN chi, GEN phi, GEN chip, GEN nup, long *Lp, long *Ep)
1416: {
1417: long v = varn(chi), L, E, r, s;
1418: GEN chin, pip, pp, vn;
1419:
1420: if (gegal(nup, polx[v]))
1421: chin = chip;
1422: else
1423: chin = mycaract(chip, nup);
1424:
1425: vn = vstar(p, chin);
1426: L = vn[0];
1427: E = vn[1];
1428:
1429: cbezout(L, -E, &r, &s);
1430:
1431: if (r <= 0)
1432: {
1433: long q = (-r) / E;
1434: q++;
1435: r += q*E;
1436: s += q*L;
1437: }
1438:
1439: pip = eleval(chi, nup, phi);
1440: pip = lift_intern(gpuigs(gmodulcp(pip, chi), r));
1441: pp = gpuigs(p, s);
1442:
1443: *Lp = L;
1444: *Ep = E;
1445: return gdiv(pip, pp);
1446: }
1447:
1448: static GEN
1449: update_alpha(GEN p, GEN fx, GEN alph, GEN chi, GEN pmr, GEN pmf, long mf)
1450: {
1451: long l, v = varn(fx);
1452: GEN nalph, nchi, w, nnu, pdr, npmr, rep;
1453:
1454: nalph = alph;
1455: if (!chi)
1456: nchi = mycaract(fx, alph);
1457: else
1458: nchi = chi;
1459:
1460: pdr = modii(respm(nchi, derivpol(nchi), pmr), pmr);
1461: for (;;)
1462: {
1463: if (signe(pdr)) break;
1464: pdr = modii(respm(nchi, derivpol(nchi), pmf), pmf);
1465: if (signe(pdr)) break;
1466: if (DEBUGLEVEL >= 6)
1467: fprintferr(" non separable polynomial in update_alpha!\n");
1468: /* at this point, we assume that chi is not square-free */
1469: nalph = gadd(nalph, gmul(p, polx[v]));
1470: w = factcp(p, fx, nalph);
1471: nchi = (GEN)w[1];
1472: nnu = (GEN)w[2];
1473: l = itos((GEN)w[3]);
1474: if (l > 1) return Decomp(p, fx, mf, nalph, nchi, nnu);
1475: pdr = modii(respm(nchi, derivpol(nchi), pmr), pmr);
1476: }
1477:
1478: if (is_pm1(pdr))
1479: npmr = gun;
1480: else
1481: {
1482: npmr = mulii(sqri(pdr), p);
1483: nchi = polmodi(nchi, npmr);
1484: nalph = redelt(nalph, npmr, pmf);
1485: }
1486:
1487: rep = cgetg(5, t_VEC);
1488: rep[1] = (long)nalph;
1489: rep[2] = (long)nchi;
1490: rep[3] = (long)npmr;
1491: rep[4] = lmulii(p, pdr);
1492:
1493: return rep;
1494: }
1495:
1496: static GEN
1497: nilord2(GEN p, GEN fx, long mf, GEN gx)
1498: {
1499: long Fa, La, Ea, oE, Fg, eq, er, v = varn(fx), i, nv, Le, Ee, N, l, vn;
1500: GEN p1, alph, chi, nu, w, phi, pmf, pdr, pmr, kapp, pie, chib;
1501: GEN gamm, chig, nug, delt, beta, eta, chie, nue, pia, vb, opa;
1502:
1503: if (DEBUGLEVEL >= 3)
1504: {
1505: fprintferr(" entering Nilord2");
1506: if (DEBUGLEVEL >= 5)
1507: {
1508: fprintferr(" with parameters: p = %Z, expo = %ld\n", p, mf);
1509: fprintferr(" fx = %Z, gx = %Z", fx, gx);
1510: }
1511: fprintferr("\n");
1512: }
1513:
1514: /* this is quite arbitrary; what is important is that >= mf + 1 */
1515: pmf = gpuigs(p, mf + 3);
1516: pdr = respm(fx, derivpol(fx), pmf);
1517: pmr = mulii(sqri(pdr), p);
1518: pdr = mulii(p, pdr);
1519: chi = polmodi_keep(fx, pmr);
1520:
1521: alph = polx[v];
1522: nu = gx;
1523: N = degree(fx);
1524: oE = 0;
1525: opa = NULL;
1526:
1527: for(;;)
1528: {
1529: /* kappa need to be recomputed */
1530: kapp = NULL;
1531: Fa = degree(nu);
1532: /* the prime element in Zp[alpha] */
1533: pia = getprime(p, chi, polx[v], chi, nu, &La, &Ea);
1534: pia = redelt(pia, pmr, pmf);
1535:
1536: if (Ea < oE)
1537: {
1538: alph = gadd(alph, opa);
1539: w = update_alpha(p, fx, alph, NULL, pmr, pmf, mf);
1540: alph = (GEN)w[1];
1541: chi = (GEN)w[2];
1542: pmr = (GEN)w[3];
1543: pdr = (GEN)w[4];
1544: kapp = NULL;
1545: pia = getprime(p, chi, polx[v], chi, nu, &La, &Ea);
1546: pia = redelt(pia, pmr, pmf);
1547: }
1548:
1549: oE = Ea; opa = pia;
1550:
1551: if (DEBUGLEVEL >= 5)
1552: fprintferr(" Fa = %ld and Ea = %ld \n", Fa, Ea);
1553:
1554: /* we change alpha such that nu = pia */
1555: if (La > 1)
1556: {
1557: alph = gadd(alph, eleval(fx, pia, alph));
1558:
1559: w = update_alpha(p, fx, alph, NULL, pmr, pmf, mf);
1560: alph = (GEN)w[1];
1561: chi = (GEN)w[2];
1562: pmr = (GEN)w[3];
1563: pdr = (GEN)w[4];
1564: }
1565:
1566: /* if Ea*Fa == N then O = Zp[alpha] */
1567: if (Ea*Fa == N)
1568: {
1569: alph = redelt(alph, sqri(p), pmf);
1570: return dbasis(p, fx, mf, alph, p);
1571: }
1572:
1573: /* during the process beta tends to a factor of chi */
1574: beta = lift_intern(gpowgs(gmodulcp(nu, chi), Ea));
1575:
1576: for (;;)
1577: {
1578: if (DEBUGLEVEL >= 5)
1579: fprintferr(" beta = %Z\n", beta);
1580:
1581: p1 = gnorm(gmodulcp(beta, chi));
1582: if (signe(p1))
1583: {
1584: chib = NULL;
1585: vn = ggval(p1, p);
1586: eq = (long)(vn / N);
1587: er = (long)(vn*Ea/N - eq*Ea);
1588: }
1589: else
1590: {
1591: chib = mycaract(chi, beta);
1592: vb = vstar(p, chib);
1593: eq = (long)(vb[0] / vb[1]);
1594: er = (long)(vb[0]*Ea / vb[1] - eq*Ea);
1595: }
1596:
1597: /* the following code can be used to check if beta approximates
1598: a factor of chi well enough to derive a factorization of chi.
1599: However, in general, the process will always end before this
1600: happens. */
1601: #if 0
1602: {
1603: GEN quo, rem;
1604:
1605: quo = poldivres(chi, beta, &rem);
1606: p1 = content(lift(rem));
1607: fprintferr(" val(rem) = %ld\n", ggval(p1, p));
1608: p1 = respm(beta, quo, pmr);
1609: fprintferr(" val(id) = %ld\n", ggval(p1, p));
1610: }
1611: #endif
1612:
1613: /* eq and er are such that gamma = beta.p^-eq.nu^-er is a unit */
1614: if (eq) gamm = gdiv(beta, gpowgs(p, eq));
1615: else gamm = beta;
1616:
1617: if (er)
1618: {
1619: /* kappa = nu^-1 in Zp[alpha] */
1620: if (!kapp)
1621: {
1622: kapp = ginvmod(nu, chi);
1623: kapp = redelt(kapp, pmr, pmr);
1624: kapp = gmodulcp(kapp, chi);
1625: }
1626: gamm = lift(gmul(gamm, gpowgs(kapp, er)));
1627: gamm = redelt(gamm, p, pmr);
1628: }
1629:
1630: if (DEBUGLEVEL >= 6)
1631: fprintferr(" gamma = %Z\n", gamm);
1632:
1633: if (er || !chib)
1634: {
1635: p1 = mulii(pdr, ggcd(denom(content(gamm)), pdr));
1636: chig = mycaract(redelt(chi, mulii(pdr, p1), pdr), gamm);
1637: }
1638: else
1639: {
1640: chig = poleval(chib, gmul(polx[v], gpowgs(p, eq)));
1641: chig = gdiv(chig, gpowgs(p, N*eq));
1642: }
1643:
1644: if (!gcmp1(denom(content(chig))))
1645: {
1646: /* the valuation of beta was wrong... This also means
1647: that chi_gamma has more than one factor modulo p */
1648: vb = vstar(p, chig);
1649: eq = (long)(-vb[0] / vb[1]);
1650: er = (long)(-vb[0]*Ea / vb[1] - eq*Ea);
1651: if (eq) gamm = gmul(gamm, gpowgs(p, eq));
1652: if (er)
1653: {
1654: gamm = gmul(gamm, gpowgs(nu, er));
1655: gamm = gmod(gamm, chi);
1656: gamm = redelt(gamm, p, pmr);
1657: }
1658: p1 = mulii(pdr, ggcd(denom(content(gamm)), pdr));
1659: chig = mycaract(redelt(chi, mulii(pdr, p1), pdr), gamm);
1660: }
1661:
1662: chig = polmodi(chig, pmr);
1663: nug = (GEN)factmod(chig, p)[1];
1664: l = lg(nug) - 1;
1665: nug = lift((GEN)nug[l]);
1666:
1667: if (l > 1)
1668: {
1669: /* there are at least 2 factors mod. p => chi can be split */
1670: phi = eleval(fx, gamm, alph);
1671: phi = redelt(phi, p, pmf);
1672: return Decomp(p, fx, mf, phi, chig, nug);
1673: }
1674:
1675: Fg = degree(nug);
1676: if (Fa%Fg)
1677: {
1678: if (DEBUGLEVEL >= 5)
1679: fprintferr(" Increasing Fa\n");
1680: /* we compute a new element such F = lcm(Fa, Fg) */
1681: w = testb2(p, chi, Fa, gamm, Fg);
1682: if (gcmp1((GEN)w[1]))
1683: {
1684: /* there are at least 2 factors mod. p => chi can be split */
1685: phi = eleval(fx, (GEN)w[2], alph);
1686: phi = redelt(phi, p, pmf);
1687: return Decomp(p, fx, mf, phi, (GEN)w[3], (GEN)w[4]);
1688: }
1689: break;
1690: }
1691:
1692: /* we look for a root delta of nug in Fp[alpha] such that
1693: vp(gamma - delta) > 0. This root can then be used to
1694: improved the approximation given by beta */
1695: nv = fetch_var();
1696: w = factmod9(nug, p, gsubst(nu, varn(nu), polx[nv]));
1697: w = lift(lift((GEN)w[1]));
1698:
1699: for (i = 1;; i++)
1700: if (degree((GEN)w[i]) == 1)
1701: {
1702: delt = gneg_i(gsubst(gcoeff(w, 2, i), nv, polx[v]));
1703: eta = gsub(gamm, delt);
1704: if (typ(delt) == t_INT)
1705: {
1706: chie = poleval(chig, gadd(polx[v], delt));
1707: chie = polmodi(chie, pmr);
1708: nue = (GEN)factmod(chie, p)[1];
1709: l = lg(nue) - 1;
1710: nue = lift((GEN)nue[l]);
1711: }
1712: else
1713: {
1714: p1 = factcp(p, chi, eta);
1715: chie = (GEN)p1[1];
1716: chie = polmodi(chie, pmr);
1717: nue = (GEN)p1[2];
1718: l = itos((GEN)p1[3]);
1719: }
1720: if (l > 1)
1721: {
1722: /* there are at least 2 factors mod. p => chi can be split */
1723: delete_var();
1724: phi = eleval(fx, eta, alph);
1725: phi = redelt(phi, p, pmf);
1726: return Decomp(p, fx, mf, phi, chie, nue);
1727: }
1728:
1729: /* if vp(eta) = vp(gamma - delta) > 0 */
1730: if (gegal(nue, polx[v])) break;
1731: }
1732: delete_var();
1733:
1734: pie = getprime(p, chi, eta, chie, nue, &Le, &Ee);
1735: if (Ea%Ee)
1736: {
1737: if (DEBUGLEVEL >= 5)
1738: fprintferr(" Increasing Ea\n");
1739: pie = redelt(pie, p, pmf);
1740: /* we compute a new element such E = lcm(Ea, Ee) */
1741: w = testc2(p, chi, pmr, nu, Ea, pie, Ee);
1742: if (gcmp1((GEN)w[1]))
1743: {
1744: /* there are at least 2 factors mod. p => chi can be split */
1745: phi = eleval(fx, (GEN)w[2], alph);
1746: phi = redelt(phi, p, pmf);
1747: return Decomp(p, fx, mf, phi, (GEN)w[3], (GEN)w[4]);
1748: }
1749: break;
1750: }
1751:
1752: if (eq) delt = gmul(delt, gpowgs(p, eq));
1753: if (er) delt = gmul(delt, gpowgs(nu, er));
1754: beta = gsub(beta, delt);
1755: }
1756:
1757: /* we replace alpha by a new alpha with a larger F or E */
1758: alph = eleval(fx, (GEN)w[2], alph);
1759: chi = (GEN)w[3];
1760: nu = (GEN)w[4];
1761:
1762: w = update_alpha(p, fx, alph, chi, pmr, pmf, mf);
1763: alph = (GEN)w[1];
1764: chi = (GEN)w[2];
1765: pmr = (GEN)w[3];
1766: pdr = (GEN)w[4];
1767:
1768: /* that can happen if p does not divide the field discriminant! */
1769: if (is_pm1(pmr))
1770: return dbasis(p, fx, mf, alph, chi);
1771: }
1772: }
1773:
1774: /* Returns [1,phi,chi,nu] if phi non-primary
1775: * [2,phi,chi,nu] if D_phi = lcm (D_alpha, D_theta)
1776: */
1777: static GEN
1778: testb(GEN p,GEN fa,long Da,GEN theta,long Dt)
1779: {
1780: long pp,Dat,t,v=varn(fa);
1781: GEN b,w,phi,h;
1782:
1783: Dat=clcm(Da,Dt)+3; b=cgetg(5,t_VEC);
1784: pp = p[2]; if (lgef(p)>3 || pp<0) pp=0;
1785: for (t=1; ; t++)
1786: {
1787: h = pp? stopoly(t,pp,v): scalarpol(stoi(t),v);
1788: phi = gadd(theta,gmod(h,fa));
1789: w=factcp(p,fa,phi); h=(GEN)w[3];
1790: if (h[2] > 1) { b[1]=un; break; }
1791: if (lgef(w[2]) == Dat) { b[1]=deux; break; }
1792: }
1793: b[2]=(long)phi; b[3]=w[1]; b[4]=w[2]; return b;
1794: }
1795:
1796: /* Returns [1,phi,chi,nu] if phi non-primary
1797: * [2,phi,chi,nu] with F_phi = lcm (F_alpha, F_theta)
1798: * and E_phi = E_alpha
1799: */
1800: static GEN
1801: testb2(GEN p, GEN fa, long Fa, GEN theta, long Ft)
1802: {
1803: long pp, Dat, t, v = varn(fa);
1804: GEN b, w, phi, h;
1805:
1806: Dat = clcm(Fa, Ft) + 3;
1807: b = cgetg(5, t_VEC);
1808: pp = p[2];
1809: if (lgef(p) > 3 || pp < 0) pp = 0;
1810:
1811: for (t = 1;; t++)
1812: {
1813: h = pp? stopoly(t, pp, v): scalarpol(stoi(t), v);
1814: phi = gadd(theta, gmod(h, fa));
1815: w = factcp(p, fa, phi);
1816: h = (GEN)w[3];
1817: if (h[2] > 1) { b[1] = un; break; }
1818: if (lgef(w[2]) == Dat) { b[1] = deux; break; }
1819: }
1820:
1821: b[2] = (long)phi;
1822: b[3] = w[1];
1823: b[4] = w[2];
1824: return b;
1825: }
1826:
1827: /* Returns [1,phi,chi,nu] if phi non-primary
1828: * [2,phi,chi,nu] if M_phi = lcm (M_alpha, M_theta)
1829: */
1830: static GEN
1831: testc(GEN p, GEN fa, long c, GEN alph2, long Ma, GEN thet2, long Mt)
1832: {
1833: GEN b,pc,ppc,c1,c2,c3,psi,phi,w,h;
1834: long r,s,t,v=varn(fa);
1835:
1836: b=cgetg(5,t_VEC); pc=gpuigs(p,c); ppc=mulii(pc,p);
1837:
1838: cbezout(Ma,Mt,&r,&s); t=0;
1839: while (r<0) { r=r+Mt; t++; }
1840: while (s<0) { s=s+Ma; t++; }
1841:
1842: c1=lift_intern(gpuigs(gmodulcp(alph2,fa),s));
1843: c2=lift_intern(gpuigs(gmodulcp(thet2,fa),r));
1844: c3=gdiv(gmod(gmul(c1,c2),fa),gpuigs(p,t));
1845: psi=gdiv(polmodi(gmul(pc,c3),ppc),pc);
1846: phi=gadd(polx[v],psi);
1847:
1848: w=factcp(p,fa,phi); h=(GEN)w[3];
1849: b[1] = (h[2] > 1)? un: deux;
1850: b[2]=(long)phi; b[3]=w[1]; b[4]=w[2]; return b;
1851: }
1852:
1853: /* Returns [1, phi, chi, nu] if phi non-primary
1854: * [2, phi, chi, nu] if E_phi = lcm (E_alpha, E_theta)
1855: */
1856: static GEN
1857: testc2(GEN p, GEN fa, GEN pmr, GEN alph2, long Ea, GEN thet2, long Et)
1858: {
1859: GEN b, c1, c2, c3, psi, phi, w, h;
1860: long r, s, t, v = varn(fa);
1861:
1862: b=cgetg(5, t_VEC);
1863:
1864: cbezout(Ea, Et, &r, &s); t = 0;
1865: while (r < 0) { r = r + Et; t++; }
1866: while (s < 0) { s = s + Ea; t++; }
1867:
1868: c1 = lift_intern(gpuigs(gmodulcp(alph2, fa), s));
1869: c2 = lift_intern(gpuigs(gmodulcp(thet2, fa), r));
1870: c3 = gdiv(gmod(gmul(c1, c2), fa), gpuigs(p, t));
1871:
1872: psi = redelt(c3, pmr, pmr);
1873: phi = gadd(polx[v], psi);
1874:
1875: w = factcp(p,fa,phi); h = (GEN)w[3];
1876: b[1] = (h[2] > 1)? un: deux;
1877: b[2] = (long)phi;
1878: b[3] = w[1];
1879: b[4] = w[2];
1880: return b;
1881: }
1882:
1883: /* Returns
1884: * [1,phi,chi,nu] if theta non-primary
1885: * [2,phi,chi,nu] if D_phi > D_aplha or M_phi > M_alpha
1886: * [3,phi,chi,nu] otherwise
1887: */
1888: static GEN
1889: testd(GEN p,GEN fa,long c,long Da,GEN alph2,long Ma,GEN theta)
1890: {
1891: long Lt,Mt,Dt,av=avma,tetpil;
1892: GEN chi,nu,thet2,b,w,h;
1893:
1894: b=cgetg(5,t_VEC); w=factcp(p,fa,theta);
1895: chi=(GEN)w[1]; nu=(GEN)w[2]; h=(GEN)w[3];
1896: if (h[2] > 1)
1897: {
1898: b[1]=un; b[2]=(long)theta; b[3]=(long)chi; b[4]=(long)nu;
1899: }
1900: else
1901: {
1902: Dt=lgef(nu)-3;
1903: if (Da < clcm(Da,Dt)) b = testb(p,fa,Da,theta,Dt);
1904: else
1905: {
1906: thet2=setup(p,fa,theta,nu, &Lt,&Mt);
1907: if (Ma < clcm(Ma,Mt)) b = testc(p,fa,c,alph2,Ma,thet2,Mt);
1908: else
1909: {
1910: b[1]=lstoi(3); b[2]=(long)theta; b[3]=(long)chi; b[4]=(long)nu;
1911: }
1912: }
1913: }
1914: tetpil=avma; return gerepile(av,tetpil,gcopy(b));
1915: }
1916:
1917: /* Factor characteristic polynomial of beta mod p */
1918: GEN
1919: factcp(GEN p,GEN f,GEN beta)
1920: {
1921: long av,tetpil,l;
1922: GEN chi,nu, b = cgetg(4,t_VEC);
1923:
1924: chi = mycaract(f,beta);
1925: av=avma; nu=(GEN)factmod(chi,p)[1]; l=lg(nu)-1;
1926: nu=lift_intern((GEN)nu[1]); tetpil=avma;
1927: b[1]=(long)chi;
1928: b[2]=lpile(av,tetpil,gcopy(nu));
1929: b[3]=lstoi(l); return b;
1930: }
1931:
1932: /* evaluate h(a) mod f */
1933: GEN
1934: eleval(GEN f,GEN h,GEN a)
1935: {
1936: long n,av,tetpil;
1937: GEN y;
1938:
1939: if (typ(h) != t_POL) return gcopy(h);
1940: av = tetpil = avma;
1941: n=lgef(h)-1; y=(GEN)h[n];
1942: for (n--; n>=2; n--)
1943: {
1944: y = gadd(gmul(y,a),(GEN)h[n]);
1945: tetpil=avma; y = gmod(y,f);
1946: }
1947: return gerepile(av,tetpil,y);
1948: }
1949:
1950: /* Compute theta^k mod (f,pd) */
1951: static GEN
1952: eltppm(GEN f,GEN pd,GEN theta,GEN k)
1953: {
1954: GEN phi,psi,D, q = k;
1955: long av = avma, av1, lim = stack_lim(av,2);
1956:
1957: if (!signe(k)) return polun[varn(f)];
1958: D = mulii(pd, sqri(pd)); av1 = avma;
1959: phi=pd; psi=gmul(pd,theta);
1960:
1961: for(;;)
1962: {
1963: if (mod2(q)) phi = gdivexact(Fp_res(gmul(phi,psi), f, D), pd);
1964: q=shifti(q,-1); if (!signe(q)) break;
1965: psi = gdivexact(Fp_res(gsqr(psi), f, D), pd);
1966: if (low_stack(lim,stack_lim(av,2)))
1967: {
1968: GEN *gptr[3]; gptr[0]=ψ gptr[1]=φ gptr[2]=&q;
1969: if(DEBUGMEM>1) err(warnmem,"eltppm");
1970: gerepilemany(av1,gptr,3);
1971: }
1972: }
1973: return gerepileupto(av,gdiv(phi,pd));
1974: }
1975:
1976: /* Sylvester's matrix, mod p^m (assumes f1 monic) */
1977: static GEN
1978: sylpm(GEN f1,GEN f2,GEN pm)
1979: {
1980: long n,deg,k,j,v=varn(f1);
1981: GEN a,h;
1982:
1983: n=lgef(f1)-3; a=cgetg(n+1,t_MAT);
1984: h = Fp_res(f2,f1,pm);
1985: for (j=1; j<=n; j++)
1986: {
1987: a[j] = lgetg(n+1,t_COL);
1988: deg=lgef(h)-3;
1989: for (k=1; k<=deg+1; k++) coeff(a,k,j)=h[k+1];
1990: for ( ; k<=n; k++) coeff(a,k,j)=zero;
1991:
1992: if (j<n) h = Fp_res(gmul(polx[v],h),f1,pm);
1993: }
1994: return hnfmodid(a,pm);
1995: }
1996:
1997: /* polynomial gcd mod p^m (assumes f1 monic) */
1998: GEN
1999: gcdpm(GEN f1,GEN f2,GEN pm)
2000: {
2001: long n,c,v=varn(f1),av=avma,tetpil;
2002: GEN a,col;
2003:
2004: n=lgef(f1)-3; a=sylpm(f1,f2,pm);
2005: for (c=1; c<=n; c++)
2006: if (signe(resii(gcoeff(a,c,c),pm))) break;
2007: if (c > n) { avma=av; return zeropol(v); }
2008:
2009: col = gdiv((GEN)a[c], gcoeff(a,c,c)); tetpil=avma;
2010: return gerepile(av,tetpil, gtopolyrev(col,v));
2011: }
2012:
2013: /* reduced resultant mod p^m (assumes x monic) */
2014: GEN
2015: respm(GEN x,GEN y,GEN pm)
2016: {
2017: long av=avma,tetpil;
2018:
2019: x = sylpm(x,y,pm); tetpil=avma;
2020: return gerepile(av,tetpil, icopy(gcoeff(x,1,1)));
2021: }
2022:
2023: /* Normalized integral basis */
2024: static GEN
2025: nbasis(GEN ibas,GEN pd)
2026: {
2027: long n,j,k,m;
2028: GEN a;
2029:
2030: n=lg(ibas)-1; m=lgef(ibas[1])-2;
2031: a=cgetg(n+1,t_MAT);
2032: for (k=1; k<=n; k++)
2033: {
2034: m=lgef(ibas[k])-2; a[k]=lgetg(n+1,t_COL);
2035: for (j=1; j<=m; j++) coeff(a,j,k)=coeff(ibas,j+1,k);
2036: for ( ; j<=n; j++) coeff(a,j,k)=zero;
2037: }
2038: return gdiv(hnfmodid(a,pd), pd);
2039: }
2040:
2041: static long
2042: clcm(long a,long b)
2043: {
2044: long d,r,v1;
2045:
2046: d=a; r=b;
2047: for(;;)
2048: {
2049: if (!r) return (a*b)/d;
2050: v1=r; r=d%r; d=labs(v1);
2051: }
2052: }
2053:
2054: /*******************************************************************/
2055: /* */
2056: /* BUCHMANN-LENSTRA ALGORITHM */
2057: /* */
2058: /*******************************************************************/
2059: static GEN lens(GEN nf,GEN p,GEN a);
2060: GEN element_powid_mod_p(GEN nf, long I, GEN n, GEN p);
2061:
2062: /* return a Z basis of Z_K's p-radical, modfrob = x--> x^p-x */
2063: static GEN
2064: pradical(GEN nf, GEN p, GEN *modfrob)
2065: {
2066: long i,N=lgef(nf[1])-3;
2067: GEN p1,m,frob,rad;
2068:
2069: frob = cgetg(N+1,t_MAT);
2070: for (i=1; i<=N; i++)
2071: frob[i] = (long) element_powid_mod_p(nf,i,p, p);
2072:
2073: /* p1 = smallest power of p st p^k >= N */
2074: p1=p; while (cmpis(p1,N)<0) p1=mulii(p1,p);
2075: if (p1==p) m = frob;
2076: else
2077: {
2078: m=cgetg(N+1,t_MAT); p1 = divii(p1,p);
2079: for (i=1; i<=N; i++)
2080: m[i]=(long)element_pow_mod_p(nf,(GEN)frob[i],p1, p);
2081: }
2082: rad = ker_mod_p(m, p);
2083: for (i=1; i<=N; i++)
2084: coeff(frob,i,i) = lsubis(gcoeff(frob,i,i), 1);
2085: *modfrob = frob; return rad;
2086: }
2087:
2088: static GEN
2089: project(GEN algebre, GEN x, long k, long kbar)
2090: {
2091: x = inverseimage(algebre,x);
2092: x += k; x[0] = evaltyp(t_COL) | evallg(kbar+1);
2093: return x;
2094: }
2095:
2096: /* Calcule le polynome minimal de alpha dans algebre (coeffs dans Z) */
2097: static GEN
2098: pol_min(GEN alpha,GEN nf,GEN algebre,long kbar,GEN p)
2099: {
2100: long av=avma,tetpil,i,N,k;
2101: GEN p1,puiss;
2102:
2103: N = lg(nf[1])-3; puiss=cgetg(N+2,t_MAT);
2104: k = N-kbar; p1=alpha;
2105: puiss[1] = (long)gscalcol_i(gun,kbar);
2106: for (i=2; i<=N+1; i++)
2107: {
2108: if (i>2) p1 = element_mul(nf,p1,alpha);
2109: puiss[i] = (long) project(algebre,p1,k,kbar);
2110: }
2111: puiss = lift_intern(puiss);
2112: p1 = (GEN)ker_mod_p(puiss, p)[1]; tetpil=avma;
2113: return gerepile(av,tetpil,gtopolyrev(p1,0));
2114: }
2115:
2116: /* Evalue le polynome pol en alpha,element de nf */
2117: static GEN
2118: eval_pol(GEN nf,GEN pol,GEN alpha,GEN algebre,GEN algebre1)
2119: {
2120: long av=avma,tetpil,i,kbar,k, lx = lgef(pol)-1, N = lgef(nf[1])-3;
2121: GEN res;
2122:
2123: kbar = lg(algebre1)-1; k = N-kbar;
2124: res = gscalcol_i((GEN)pol[lx], N);
2125: for (i=2; i<lx; i++)
2126: {
2127: res = element_mul(nf,alpha,res);
2128: res[1] = ladd((GEN)res[1],(GEN)pol[i]);
2129: }
2130: res = project(algebre,res,k,kbar); tetpil=avma;
2131: return gerepile(av,tetpil,gmul(algebre1,res));
2132: }
2133:
2134: static GEN
2135: kerlens2(GEN x, GEN p)
2136: {
2137: long i,j,k,t,nbc,nbl,av,av1;
2138: GEN a,c,l,d,y,q;
2139:
2140: av=avma; a=gmul(x,gmodulsg(1,p));
2141: nbl=nbc=lg(x)-1;
2142: c=new_chunk(nbl+1); for (i=1; i<=nbl; i++) c[i]=0;
2143: l=new_chunk(nbc+1);
2144: d=new_chunk(nbc+1);
2145: k = t = 1;
2146: while (t<=nbl && k<=nbc)
2147: {
2148: for (j=1; j<k; j++)
2149: for (i=1; i<=nbl; i++)
2150: if (i!=l[j])
2151: coeff(a,i,k) = lsub(gmul((GEN)d[j],gcoeff(a,i,k)),
2152: gmul(gcoeff(a,l[j],k),gcoeff(a,i,j)));
2153: t=1; while (t<=nbl && (c[t] || gcmp0(gcoeff(a,t,k)))) t++;
2154: if (t<=nbl) { d[k]=coeff(a,t,k); c[t]=k; l[k]=t; k++; }
2155: }
2156: if (k>nbc) err(bugparier,"kerlens2");
2157: y=cgetg(nbc+1,t_COL);
2158: y[1]=(k>1)?coeff(a,l[1],k):un;
2159: for (q=gun,j=2; j<k; j++)
2160: {
2161: q=gmul(q,(GEN)d[j-1]);
2162: y[j]=lmul(gcoeff(a,l[j],k),q);
2163: }
2164: if (k>1) y[k]=lneg(gmul(q,(GEN)d[k-1]));
2165: for (j=k+1; j<=nbc; j++) y[j]=zero;
2166: av1=avma; return gerepile(av,av1,lift(y));
2167: }
2168:
2169: static GEN
2170: kerlens(GEN x, GEN pgen)
2171: {
2172: long av = avma, i,j,k,t,nbc,nbl,p,q,*c,*l,*d,**a;
2173: GEN y;
2174:
2175: if (cmpis(pgen, MAXHALFULONG>>1) > 0)
2176: return kerlens2(x,pgen);
2177: /* ici p <= (MAXHALFULONG>>1) ==> long du C */
2178: p=itos(pgen); nbl=nbc=lg(x)-1;
2179: a=(long**)new_chunk(nbc+1);
2180: for (j=1; j<=nbc; j++)
2181: {
2182: c=a[j]=new_chunk(nbl+1);
2183: for (i=1; i<=nbl; i++) c[i]=smodis(gcoeff(x,i,j),p);
2184: }
2185: c=new_chunk(nbl+1); for (i=1; i<=nbl; i++) c[i]=0;
2186: l=new_chunk(nbc+1);
2187: d=new_chunk(nbc+1);
2188: k = t = 1;
2189: while (t<=nbl && k<=nbc)
2190: {
2191: for (j=1; j<k; j++)
2192: for (i=1; i<=nbl; i++)
2193: if (i!=l[j])
2194: a[k][i] = (d[j]*a[k][i] - a[j][i]*a[k][l[j]]) % p;
2195: t=1; while (t<=nbl && (c[t] || !a[k][t])) t++;
2196: if (t<=nbl) { d[k]=a[k][t]; c[t]=k; l[k++]=t; }
2197: }
2198: if (k>nbc) err(bugparier,"kerlens");
2199: avma=av; y=cgetg(nbc+1,t_COL);
2200: t=(k>1) ? a[k][l[1]]:1;
2201: y[1]=(t>0)? lstoi(t):lstoi(t+p);
2202: for (q=1,j=2; j<k; j++)
2203: {
2204: q = (q*d[j-1]) % p;
2205: t = (a[k][l[j]]*q) % p;
2206: y[j] = (t>0) ? lstoi(t) : lstoi(t+p);
2207: }
2208: if (k>1)
2209: {
2210: t = (q*d[k-1]) % p;
2211: y[k] = (t>0) ? lstoi(p-t) : lstoi(-t);
2212: }
2213: for (j=k+1; j<=nbc; j++) y[j]=zero;
2214: return y;
2215: }
2216:
2217: /* Calcule la constante de lenstra de l'ideal p.Z_K+a.Z_K ou a est un
2218: vecteur sur la base d'entiers */
2219: static GEN
2220: lens(GEN nf, GEN p, GEN a)
2221: {
2222: long av=avma,tetpil,N=lgef(nf[1])-3,j;
2223: GEN mat=cgetg(N+1,t_MAT);
2224: for (j=1; j<=N; j++) mat[j]=(long)element_mulid(nf,a,j);
2225: tetpil=avma; return gerepile(av,tetpil,kerlens(mat,p));
2226: }
2227:
2228: GEN det_mod_P_n(GEN a, GEN N, GEN P);
2229: GEN sylvestermatrix_i(GEN x, GEN y);
2230:
2231: /* check if p^va doesnt divide norm x (or norm(x+p)) */
2232: #if 0
2233: /* compute norm mod p^whatneeded using Sylvester's matrix */
2234: /* looks slower than the new subresultant. Have to re-check this */
2235: static GEN
2236: prime_check_elt(GEN a, GEN pol, GEN p, GEN pf)
2237: {
2238: GEN M,mod,x, c = denom(content(a));
2239: long v = pvaluation(c, p, &x); /* x is junk */
2240:
2241: mod = mulii(pf, gpowgs(p, (lgef(pol)-3)*v + 1));
2242:
2243: x = Fp_pol_red(gmul(a,c), mod);
2244: M = sylvestermatrix_i(pol,x);
2245: if (det_mod_P_n(M,mod,p) == gzero)
2246: {
2247: x[2] = ladd((GEN)x[2], mulii(p,c));
2248: M = sylvestermatrix_i(pol,x);
2249: if (det_mod_P_n(M,mod,p) == gzero) return NULL;
2250: a[2] = ladd((GEN)a[2], p);
2251: }
2252: return a;
2253: }
2254: #else
2255: /* use subres to compute norm */
2256: static GEN
2257: prime_check_elt(GEN a, GEN pol, GEN p, GEN pf)
2258: {
2259: GEN norme=subres(pol,a);
2260: if (resii(divii(norme,pf),p) != gzero) return a;
2261: a=gadd(a,p); norme=subres(pol,a);
2262: if (resii(divii(norme,pf),p) != gzero) return a;
2263: return NULL;
2264: }
2265: #endif
2266:
2267: #if 0
2268: GEN
2269: prime_two_elt_loop(GEN beta, GEN pol, GEN p, GEN pf)
2270: {
2271: long av, m = lg(beta)-1;
2272: int i,j,K, *x = (int*)new_chunk(m+1);
2273: GEN a;
2274:
2275: K = 1; av = avma;
2276: for(;;)
2277: { /* x runs through strictly increasing sequences of length K,
2278: * 1 <= x[i] <= m */
2279: nextK:
2280: if (DEBUGLEVEL) fprintferr("K = %d\n", K);
2281: for (i=1; i<=K; i++) x[i] = i;
2282: for(;;)
2283: {
2284: if (DEBUGLEVEL > 1)
2285: {
2286: for (i=1; i<=K; i++) fprintferr("%d ",x[i]);
2287: fprintferr("\n"); flusherr();
2288: }
2289: a = (GEN)beta[x[1]];
2290: for (i=2; i<=K; i++) a = gadd(a, (GEN)beta[x[i]]);
2291: if ((a = prime_check_elt(a,pol,p,pf))) return a;
2292: avma = av;
2293:
2294: /* start: i = K+1; */
2295: do
2296: {
2297: if (--i == 0)
2298: {
2299: if (++K > m) return NULL; /* fail */
2300: goto nextK;
2301: }
2302: x[i]++;
2303: } while (x[i] > m - K + i);
2304: for (j=i; j<K; j++) x[j+1] = x[j]+1;
2305: }
2306: }
2307: }
2308: #endif
2309:
2310: GEN
2311: random_prime_two_elt_loop(GEN beta, GEN pol, GEN p, GEN pf)
2312: {
2313: long av = avma, z,i, m = lg(beta)-1;
2314: long keep = getrand();
2315: int c = 0;
2316: GEN a;
2317:
2318: for(i=1; i<=m; i++)
2319: if ((a = prime_check_elt((GEN)beta[i],pol,p,pf))) return a;
2320: (void)setrand(1);
2321: if (DEBUGLEVEL) fprintferr("prime_two_elt_loop, hard case: ");
2322: for(;;avma=av)
2323: {
2324: if (DEBUGLEVEL) fprintferr("%d ", ++c);
2325: a = gzero;
2326: for (i=1; i<=m; i++)
2327: {
2328: z = mymyrand() >> (BITS_IN_RANDOM-5); /* in [0,15] */
2329: if (z >= 9) z -= 7;
2330: a = gadd(a,gmulsg(z,(GEN)beta[i]));
2331: }
2332: if ((a = prime_check_elt(a,pol,p,pf)))
2333: {
2334: if (DEBUGLEVEL) fprintferr("\n");
2335: (void)setrand(keep); return a;
2336: }
2337: }
2338: }
2339:
2340: /* Input: an ideal mod p (!= Z_K)
2341: * Output: a 2-elt representation [p, x] */
2342: static GEN
2343: prime_two_elt(GEN nf, GEN p, GEN ideal)
2344: {
2345: GEN beta,a,pf, pol = (GEN)nf[1];
2346: long av,tetpil,f, N=lgef(pol)-3, m=lg(ideal)-1;
2347:
2348: if (!m) return gscalcol_i(p,N);
2349:
2350: /* we want v_p(Norm(beta)) = p^f, f = N-m */
2351: av = avma; f = N-m; pf = gpuigs(p,f);
2352: ideal = centerlift(ideal);
2353: ideal = concatsp(gscalcol(p,N), ideal);
2354: ideal = ideal_better_basis(nf, ideal, p);
2355: beta = gmul((GEN)nf[7], ideal);
2356:
2357: #if 0
2358: a = prime_two_elt_loop(beta,pol,p,pf);
2359: if (!a) err(bugparier, "prime_two_elt (failed)");
2360: #else
2361: a = random_prime_two_elt_loop(beta,pol,p,pf);
2362: #endif
2363:
2364: a = centermod(algtobasis_intern(nf,a), p);
2365: if (resii(divii(subres(gmul((GEN)nf[7],a),pol),pf),p) == gzero)
2366: a[1] = laddii((GEN)a[1],p);
2367: tetpil = avma; return gerepile(av,tetpil,gcopy(a));
2368: }
2369:
2370: static GEN
2371: apply_kummer(GEN nf,GEN pol,GEN e,GEN p,long N,GEN *beta)
2372: {
2373: GEN T,p1, res = cgetg(6,t_VEC);
2374: long f = lgef(pol)-3;
2375:
2376: res[1]=(long)p;
2377: res[3]=(long)e;
2378: res[4]=lstoi(f);
2379: if (f == N) /* inert */
2380: {
2381: res[2]=(long)gscalcol_i(p,N);
2382: res[5]=(long)gscalcol_i(gun,N);
2383: }
2384: else
2385: {
2386: T = (GEN) nf[1];
2387: if (ggval(subres(pol,T),p) > f)
2388: pol[2] = laddii((GEN)pol[2],p);
2389: res[2] = (long) algtobasis_intern(nf,pol);
2390:
2391: p1 = Fp_deuc(T,pol,p);
2392: res[5] = (long) centermod(algtobasis_intern(nf,p1), p);
2393:
2394: if (beta)
2395: *beta = *beta? Fp_deuc(*beta,pol,p): p1;
2396: }
2397: return res;
2398: }
2399:
2400: /* prime ideal decomposition of p sorted by increasing residual degree */
2401: GEN
2402: primedec(GEN nf, GEN p)
2403: {
2404: long av=avma,tetpil,i,j,k,kbar,np,c,indice,N,lp;
2405: GEN ex,f,list,ip,elth,h;
2406: GEN modfrob,algebre,algebre1,b,mat1,T,nfp;
2407: GEN alpha,beta,p1,p2,unmodp,zmodp,idmodp;
2408:
2409: if (DEBUGLEVEL>=3) timer2();
2410: nf=checknf(nf); T=(GEN)nf[1]; N=lgef(T)-3;
2411: f=factmod(T,p); ex=(GEN)f[2];
2412: f=centerlift((GEN)f[1]); np=lg(f);
2413: if (DEBUGLEVEL>=6) msgtimer("factmod");
2414:
2415: if (signe(modii((GEN)nf[4],p))) /* p doesn't divide index */
2416: {
2417: list=cgetg(np,t_VEC);
2418: for (i=1; i<np; i++)
2419: list[i]=(long)apply_kummer(nf,(GEN)f[i],(GEN)ex[i],p,N, NULL);
2420: if (DEBUGLEVEL>=6) msgtimer("simple primedec");
2421: p1=stoi(4); tetpil=avma;
2422: return gerepile(av,tetpil,vecsort(list,p1));
2423: }
2424:
2425: p1 = (GEN)f[1];
2426: for (i=2; i<np; i++)
2427: p1 = Fp_pol_red(gmul(p1, (GEN)f[i]), p);
2428: p1 = Fp_pol_red(gdiv(gadd(gmul(p1, Fp_deuc(T,p1,p)), gneg(T)), p), p);
2429: list = cgetg(N+1,t_VEC);
2430: indice=1; beta=NULL;
2431: for (i=1; i<np; i++) /* e = 1 or f[i] does not divide p1 (mod p) */
2432: if (is_pm1(ex[i]) || signe(Fp_res(p1,(GEN)f[i],p)))
2433: list[indice++] = (long)apply_kummer(nf,(GEN)f[i],(GEN)ex[i],p,N,&beta);
2434: if (DEBUGLEVEL>=3) msgtimer("unramified factors");
2435:
2436: /* modfrob = modified Frobenius: x -> x^p - x mod p */
2437: ip = pradical(nf,p,&modfrob);
2438: if (DEBUGLEVEL>=3) msgtimer("pradical");
2439:
2440: if (beta)
2441: {
2442: beta = algtobasis_intern(nf,beta);
2443: lp=lg(ip)-1; p1=cgetg(2*lp+N+1,t_MAT);
2444: for (i=1; i<=N; i++) p1[i]=(long)element_mulid(nf,beta,i);
2445: for ( ; i<=N+lp; i++)
2446: {
2447: p2 = (GEN) ip[i-N];
2448: p1[i+lp] = (long) p2;
2449: p1[i] = ldiv(element_mul(nf,lift(p2),beta),p);
2450: }
2451: ip = image_mod_p(p1, p);
2452: if (lg(ip)>N) err(bugparier,"primedec (bad pradical)");
2453: }
2454: unmodp=gmodulsg(1,p); zmodp=gmodulsg(0,p);
2455: idmodp = idmat_intern(N,unmodp,zmodp);
2456: ip = gmul(ip, unmodp);
2457: nfp = gscalcol_i(p,N);
2458:
2459: h=cgetg(N+1,t_VEC); h[1]=(long)ip;
2460: for (c=1; c; c--)
2461: {
2462: elth=(GEN)h[c]; k=lg(elth)-1; kbar=N-k;
2463: p1 = concatsp(elth,(GEN)idmodp[1]);
2464: algebre = suppl_intern(p1,idmodp);
2465: algebre1 = cgetg(kbar+1,t_MAT);
2466: for (i=1; i<=kbar; i++) algebre1[i]=algebre[i+k];
2467: b = gmul(modfrob,algebre1);
2468: for (i=1;i<=kbar;i++)
2469: b[i] = (long) project(algebre,(GEN) b[i],k,kbar);
2470: mat1 = ker_mod_p(lift_intern(b), p);
2471: if (lg(mat1)>2)
2472: {
2473: GEN mat2 = cgetg(k+N+1,t_MAT);
2474: for (i=1; i<=k; i++) mat2[i]=elth[i];
2475: alpha=gmul(algebre1,(GEN)mat1[2]);
2476: p1 = pol_min(alpha,nf,algebre,kbar,p);
2477: p1 = (GEN)factmod(p1,p)[1];
2478: for (i=1; i<lg(p1); i++)
2479: {
2480: beta = eval_pol(nf,(GEN)p1[i],alpha,algebre,algebre1);
2481: beta = lift_intern(beta);
2482: for (j=1; j<=N; j++)
2483: mat2[k+j] = (long)Fp_vec(element_mulid(nf,beta,j), p);
2484: h[c] = (long) image(mat2); c++;
2485: }
2486: }
2487: else
2488: {
2489: long av1; p1 = cgetg(6,t_VEC);
2490: list[indice++] = (long)p1;
2491: p1[1]=(long)p; p1[4]=lstoi(kbar);
2492: p1[2]=(long)prime_two_elt(nf,p,elth);
2493: p1[5]=(long)lens(nf,p,(GEN)p1[2]);
2494: av1=avma;
2495: i = int_elt_val(nf,nfp,p,(GEN)p1[5],N);
2496: avma=av1;
2497: p1[3]=lstoi(i);
2498: }
2499: if (DEBUGLEVEL>=3) msgtimer("h[%ld]",c);
2500: }
2501: setlg(list, indice); tetpil=avma;
2502: return gerepile(av,tetpil,gen_sort(list,0,cmp_prime_over_p));
2503: }
2504:
2505: /* REDUCTION Modulo a prime ideal */
2506:
2507: /* x integral, reduce mod prh in HNF */
2508: GEN
2509: nfreducemodpr_i(GEN x, GEN prh)
2510: {
2511: GEN p = gcoeff(prh,1,1);
2512: long i,j;
2513:
2514: x = dummycopy(x);
2515: for (i=lg(x)-1; i>=2; i--)
2516: {
2517: GEN t = (GEN)prh[i], p1 = resii((GEN)x[i], p);
2518: x[i] = (long)p1;
2519: if (signe(p1) && is_pm1(t[i]))
2520: {
2521: for (j=1; j<i; j++)
2522: x[j] = lsubii((GEN)x[j], mulii(p1, (GEN)t[j]));
2523: x[i] = zero;
2524: }
2525: }
2526: x[1] = lresii((GEN)x[1], p); return x;
2527: }
2528:
2529: /* for internal use */
2530: GEN
2531: nfreducemodpr(GEN nf, GEN x, GEN prhall)
2532: {
2533: long i,v;
2534: GEN p,prh,den;
2535:
2536: for (i=lg(x)-1; i>0; i--)
2537: if (typ(x[i]) == t_INTMOD) { x=lift_intern(x); break; }
2538: prh=(GEN)prhall[1]; p=gcoeff(prh,1,1);
2539: den=denom(x);
2540: if (!gcmp1(den))
2541: {
2542: v=ggval(den,p);
2543: if (v) x=element_mul(nf,x,element_pow(nf,(GEN)prhall[2],stoi(v)));
2544: x = gmod(x,p);
2545: }
2546: return Fp_vec(nfreducemodpr_i(x, prh), p);
2547: }
2548:
2549: /* public function */
2550: GEN
2551: nfreducemodpr2(GEN nf, GEN x, GEN prhall)
2552: {
2553: long av = avma; checkprhall(prhall);
2554: if (typ(x) != t_COL) x = algtobasis(nf,x);
2555: return gerepileupto(av, nfreducemodpr(nf,x,prhall));
2556: }
2557:
2558: /* relative ROUND 2
2559: *
2560: * input: nf = base field K
2561: * x monic polynomial, coefficients in Z_K, degree n defining a relative
2562: * extension L=K(theta).
2563: * One MUST have varn(x) < varn(nf[1]).
2564: * output: a pseudo-basis [A,I] of Z_L, where A is in M_n(K) in HNF form and
2565: * I a vector of n ideals.
2566: */
2567:
2568: /* given MODULES x and y by their pseudo-bases in HNF, gives a
2569: * pseudo-basis of the module generated by x and y. For internal use.
2570: */
2571: static GEN
2572: rnfjoinmodules(GEN nf, GEN x, GEN y)
2573: {
2574: long i,lx,ly;
2575: GEN p1,p2,z,Hx,Hy,Ix,Iy;
2576:
2577: if (x == NULL) return y;
2578: Hx=(GEN)x[1]; lx=lg(Hx); Ix=(GEN)x[2];
2579: Hy=(GEN)y[1]; ly=lg(Hy); Iy=(GEN)y[2];
2580: i = lx+ly-1;
2581: z = (GEN)gpmalloc(sizeof(long*)*(3+2*i));
2582: *z = evaltyp(t_VEC)|evallg(3);
2583: p1 = z+3; z[1]=(long)p1; *p1 = evaltyp(t_MAT)|evallg(i);
2584: p2 = p1+i; z[2]=(long)p2; *p2 = evaltyp(t_VEC)|evallg(i);
2585:
2586: for (i=1; i<lx; i++) { p1[i]=Hx[i]; p2[i]=Ix[i]; }
2587: for ( ; i<lx+ly-1; i++) { p1[i]=Hy[i-lx+1]; p2[i]=Iy[i-lx+1]; }
2588: x = nfhermite(nf,z); free(z); return x;
2589: }
2590:
2591: /* a usage interne, pas de gestion de pile : x et y sont des vecteurs dont
2592: * les coefficients sont les composantes sur nf[7]; avec reduction mod pr sauf
2593: * si prhall=NULL
2594: */
2595: static GEN
2596: rnfelement_mulidmod(GEN nf, GEN multab, GEN unnf, GEN x, long h, GEN prhall)
2597: {
2598: long j,k,N;
2599: GEN p1,c,v,s,znf;
2600:
2601: if (h==1) return gcopy(x);
2602: N = lg(x)-1; multab += (h-1)*N;
2603: x = lift(x); v = cgetg(N+1,t_COL);
2604: znf = gscalcol_i(gzero,lg(unnf)-1);
2605: for (k=1; k<=N; k++)
2606: {
2607: s = gzero;
2608: for (j=1; j<=N; j++)
2609: if (!gcmp0(p1 = (GEN)x[j]) && !gcmp0(c = gcoeff(multab,k,j)))
2610: {
2611: if (!gegal(c,unnf)) p1 = element_mul(nf,p1,c);
2612: s = gadd(s,p1);
2613: }
2614: if (s == gzero) s = znf;
2615: else
2616: if (prhall) s = nfreducemodpr(nf,s,prhall);
2617: v[k] = (long)s;
2618: }
2619: return v;
2620: }
2621:
2622: /* a usage interne, pas de gestion de pile : x est un vecteur dont
2623: * les coefficients sont les composantes sur nf[7]
2624: */
2625: static GEN
2626: rnfelement_sqrmod(GEN nf, GEN multab, GEN unnf, GEN x, GEN prhall)
2627: {
2628: long i,j,k,n;
2629: GEN p1,c,z,s;
2630:
2631: n=lg(x)-1; x=lift(x); z=cgetg(n+1,t_COL);
2632: for (k=1; k<=n; k++)
2633: {
2634: if (k == 1)
2635: s = element_sqr(nf,(GEN)x[1]);
2636: else
2637: s = gmul2n(element_mul(nf,(GEN)x[1],(GEN)x[k]), 1);
2638: for (i=2; i<=n; i++)
2639: {
2640: c = gcoeff(multab,k,(i-1)*n+i);
2641: if (!gcmp0(c))
2642: {
2643: p1=element_sqr(nf,(GEN)x[i]);
2644: if (!gegal(c,unnf)) p1 = element_mul(nf,p1,c);
2645: s = gadd(s,p1);
2646: }
2647: for (j=i+1; j<=n; j++)
2648: {
2649: c = gcoeff(multab,k,(i-1)*n+j);
2650: if (!gcmp0(c))
2651: {
2652: p1=gmul2n(element_mul(nf,(GEN)x[i],(GEN)x[j]),1);
2653: if (!gegal(c,unnf)) p1 = element_mul(nf,p1,c);
2654: s = gadd(s,p1);
2655: }
2656: }
2657: }
2658: if (prhall) s = nfreducemodpr(nf,s,prhall);
2659: z[k]=(long)s;
2660: }
2661: return z;
2662: }
2663:
2664: /* Compute x^n mod pr in the extension, assume n >= 0 */
2665: static GEN
2666: rnfelementid_powmod(GEN nf, GEN multab, GEN matId, long h, GEN n, GEN prhall)
2667: {
2668: long i,m,av=avma,tetpil;
2669: GEN y, unrnf=(GEN)matId[1], unnf=(GEN)unrnf[1];
2670: ulong j;
2671:
2672: if (!signe(n)) return unrnf;
2673: y=(GEN)matId[h]; i = lgefint(n)-1; m=n[i]; j=HIGHBIT;
2674: while ((m&j)==0) j>>=1;
2675: for (j>>=1; j; j>>=1)
2676: {
2677: y = rnfelement_sqrmod(nf,multab,unnf,y,prhall);
2678: if (m&j) y = rnfelement_mulidmod(nf,multab,unnf,y,h,prhall);
2679: }
2680: for (i--; i>=2; i--)
2681: for (m=n[i],j=HIGHBIT; j; j>>=1)
2682: {
2683: y = rnfelement_sqrmod(nf,multab,unnf,y,prhall);
2684: if (m&j) y = rnfelement_mulidmod(nf,multab,unnf,y,h,prhall);
2685: }
2686: tetpil=avma; return gerepile(av,tetpil,gcopy(y));
2687: }
2688:
2689: GEN
2690: mymod(GEN x, GEN p)
2691: {
2692: long i,lx, tx = typ(x);
2693: GEN y,p1;
2694:
2695: if (tx == t_INT) return resii(x,p);
2696: if (tx == t_FRAC)
2697: {
2698: p1 = resii((GEN)x[2], p);
2699: if (p1 != gzero) { cgiv(p1); return gmod(x,p); }
2700: return x;
2701: }
2702: if (!is_matvec_t(tx))
2703: err(bugparier, "mymod (missing type)");
2704: lx = lg(x); y = cgetg(lx,tx);
2705: for (i=1; i<lx; i++) y[i] = (long)mymod((GEN)x[i],p);
2706: return y;
2707: }
2708:
2709: static GEN
2710: rnfordmax(GEN nf, GEN pol, GEN pr, GEN unnf, GEN id, GEN matId)
2711: {
2712: long av=avma,tetpil,av1,lim,i,j,k,n,v1,v2,vpol,m,cmpt,sep;
2713: GEN p,q,q1,prhall,A,Aa,Aaa,A1,I,R,p1,p2,p3,multab,multabmod,Aainv;
2714: GEN pip,baseIp,baseOp,alpha,matprod,alphainv,matC,matG,vecpro,matH;
2715: GEN neworder,H,Hid,alphalistinv,alphalist,prhinv;
2716:
2717: if (DEBUGLEVEL>1) fprintferr(" treating %Z\n",pr);
2718: prhall=nfmodprinit(nf,pr);
2719: q=cgetg(3,t_VEC); q[1]=(long)pr;q[2]=(long)prhall;
2720: p1=rnfdedekind(nf,pol,q);
2721: if (gcmp1((GEN)p1[1]))
2722: {tetpil=avma; return gerepile(av,tetpil,gcopy((GEN)p1[2]));}
2723:
2724: sep=itos((GEN)p1[3]);
2725: A=gmael(p1,2,1);
2726: I=gmael(p1,2,2);
2727:
2728: n=lgef(pol)-3; vpol=varn(pol);
2729: p=(GEN)pr[1]; q=powgi(p,(GEN)pr[4]); pip=(GEN)pr[2];
2730: q1=q; while (cmpis(q1,n)<0) q1=mulii(q1,q);
2731:
2732: multab=cgetg(n*n+1,t_MAT);
2733: for (j=1; j<=n*n; j++) multab[j]=lgetg(n+1,t_COL);
2734: prhinv = idealinv(nf,(GEN)prhall[1]);
2735: alphalistinv=cgetg(n+1,t_VEC);
2736: alphalist=cgetg(n+1,t_VEC);
2737: A1=cgetg(n+1,t_MAT);
2738: av1=avma; lim=stack_lim(av1,1);
2739: for(cmpt=1; ; cmpt++)
2740: {
2741: if (DEBUGLEVEL>1)
2742: {
2743: fprintferr(" %ld%s pass\n",cmpt,eng_ord(cmpt));
2744: flusherr();
2745: }
2746: for (i=1; i<=n; i++)
2747: {
2748: if (gegal((GEN)I[i],id)) alphalist[i]=alphalistinv[i]=(long)unnf;
2749: else
2750: {
2751: p1=ideal_two_elt(nf,(GEN)I[i]);
2752: v1=gcmp0((GEN)p1[1])? EXP220
2753: : element_val(nf,(GEN)p1[1],pr);
2754: v2=element_val(nf,(GEN)p1[2],pr);
2755: if (v1>v2) p2=(GEN)p1[2]; else p2=(GEN)p1[1];
2756: alphalist[i]=(long)p2;
2757: alphalistinv[i]=(long)element_inv(nf,p2);
2758: }
2759: }
2760: for (j=1; j<=n; j++)
2761: {
2762: p1=cgetg(n+1,t_COL); A1[j]=(long)p1;
2763: for (i=1; i<=n; i++)
2764: p1[i] = (long)element_mul(nf,gcoeff(A,i,j),(GEN)alphalist[j]);
2765: }
2766: Aa=basistoalg(nf,A1); Aainv=lift_intern(ginv(Aa));
2767: Aaa=mat_to_vecpol(Aa,vpol);
2768: for (i=1; i<=n; i++) for (j=i; j<=n; j++)
2769: {
2770: long tp;
2771: p1 = lift_intern(gres(gmul((GEN)Aaa[i],(GEN)Aaa[j]), pol));
2772: tp = typ(p1);
2773: if (is_scalar_t(tp) || (tp==t_POL && varn(p1)>vpol))
2774: p2 = gmul(p1, (GEN)Aainv[1]);
2775: else
2776: p2 = gmul(Aainv, pol_to_vec(p1, n));
2777:
2778: p3 = algtobasis(nf,p2);
2779: for (k=1; k<=n; k++)
2780: {
2781: coeff(multab,k,(i-1)*n+j) = p3[k];
2782: coeff(multab,k,(j-1)*n+i) = p3[k];
2783: }
2784: }
2785: R=cgetg(n+1,t_MAT); multabmod = mymod(multab,p);
2786: R[1] = matId[1];
2787: for (j=2; j<=n; j++)
2788: R[j] = (long) rnfelementid_powmod(nf,multabmod,matId, j,q1,prhall);
2789: baseIp = nfkermodpr(nf,R,prhall);
2790: baseOp = lift_intern(nfsuppl(nf,baseIp,n,prhall));
2791: alpha=cgetg(n+1,t_MAT);
2792: for (j=1; j<lg(baseIp); j++) alpha[j]=baseOp[j];
2793: for ( ; j<=n; j++)
2794: {
2795: p1=cgetg(n+1,t_COL); alpha[j]=(long)p1;
2796: for (i=1; i<=n; i++)
2797: p1[i]=(long)element_mul(nf,pip,gcoeff(baseOp,i,j));
2798: }
2799: matprod=cgetg(n+1,t_MAT);
2800: for (j=1; j<=n; j++)
2801: {
2802: p1=cgetg(n+1,t_COL); matprod[j]=(long)p1;
2803: for (i=1; i<=n; i++)
2804: {
2805: p2 = rnfelement_mulidmod(nf,multab,unnf, (GEN)alpha[i],j, NULL);
2806: for (k=1; k<=n; k++)
2807: p2[k] = lmul((GEN)nf[7], (GEN)p2[k]);
2808: p1[i] = (long)p2;
2809: }
2810: }
2811: alphainv = lift_intern(ginv(basistoalg(nf,alpha)));
2812: matC = cgetg(n+1,t_MAT);
2813: for (j=1; j<=n; j++)
2814: {
2815: p1=cgetg(n*n+1,t_COL); matC[j]=(long)p1;
2816: for (i=1; i<=n; i++)
2817: {
2818: p2 = gmul(alphainv, gcoeff(matprod,i,j));
2819: for (k=1; k<=n; k++)
2820: p1[(i-1)*n+k]=(long)nfreducemodpr(nf,algtobasis(nf,(GEN)p2[k]),prhall);
2821: }
2822: }
2823: matG=nfkermodpr(nf,matC,prhall); m=lg(matG)-1;
2824: vecpro=cgetg(3,t_VEC);
2825: p1=cgetg(n+m+1,t_MAT); vecpro[1]=(long)p1;
2826: p2=cgetg(n+m+1,t_VEC); vecpro[2]=(long)p2;
2827: for (j=1; j<=m; j++)
2828: {
2829: p1[j] = llift((GEN)matG[j]);
2830: p2[j] = (long)prhinv;
2831: }
2832: p1 += m;
2833: p2 += m;
2834: for (j=1; j<=n; j++)
2835: {
2836: p1[j] = matId[j];
2837: p2[j] = (long)idealmul(nf,(GEN)I[j],(GEN)alphalistinv[j]);
2838: }
2839: matH=nfhermite(nf,vecpro);
2840: p1=algtobasis(nf,gmul(Aa,basistoalg(nf,(GEN)matH[1])));
2841: p2=(GEN)matH[2];
2842:
2843: tetpil=avma; neworder=cgetg(3,t_VEC);
2844: H=cgetg(n+1,t_MAT); Hid=cgetg(n+1,t_VEC);
2845: for (j=1; j<=n; j++)
2846: {
2847: p3=cgetg(n+1,t_COL); H[j]=(long)p3;
2848: for (i=1; i<=n; i++)
2849: p3[i]=(long)element_mul(nf,gcoeff(p1,i,j),(GEN)alphalistinv[j]);
2850: Hid[j]=(long)idealmul(nf,(GEN)p2[j],(GEN)alphalist[j]);
2851: }
2852: if (DEBUGLEVEL>3)
2853: { fprintferr(" new order:\n"); outerr(H); outerr(Hid); }
2854: if (sep == 2 || gegal(I,Hid))
2855: {
2856: neworder[1]=(long)H; neworder[2]=(long)Hid;
2857: return gerepile(av,tetpil,neworder);
2858: }
2859:
2860: A=H; I=Hid;
2861: if (low_stack(lim, stack_lim(av1,1)))
2862: {
2863: GEN *gptr[2]; gptr[0]=&A; gptr[1]=&I;
2864: if(DEBUGMEM>1) err(warnmem,"rnfordmax");
2865: gerepilemany(av1,gptr,2);
2866: }
2867: }
2868: }
2869:
2870: static void
2871: check_pol(GEN x, long v)
2872: {
2873: long i,tx, lx = lg(x);
2874: if (varn(x) != v)
2875: err(talker,"incorrect variable in rnf function");
2876: for (i=2; i<lx; i++)
2877: {
2878: tx = typ(x[i]);
2879: if (!is_scalar_t(tx) || tx == t_POLMOD)
2880: err(talker,"incorrect polcoeff in rnf function");
2881: }
2882: }
2883:
2884: GEN
2885: fix_relative_pol(GEN nf, GEN x)
2886: {
2887: GEN xnf = (typ(nf) == t_POL)? nf: (GEN)nf[1];
2888: long i, vnf = varn(xnf), lx = lg(x);
2889: if (typ(x) != t_POL || varn(x) >= vnf)
2890: err(talker,"incorrect polynomial in rnf function");
2891: x = dummycopy(x);
2892: for (i=2; i<lx; i++)
2893: if (typ(x[i]) == t_POL)
2894: {
2895: check_pol((GEN)x[i], vnf);
2896: x[i] = lmodulcp((GEN)x[i], xnf);
2897: }
2898: return x;
2899: }
2900:
2901: static GEN
2902: rnfround2all(GEN nf, GEN pol, long all)
2903: {
2904: long av=avma,tetpil,i,j,n,N,nbidp,vpol,*ep;
2905: GEN p1,p2,p3,p4,polnf,list,unnf,id,matId,I,W,pseudo,y,discpol,d,D,sym;
2906:
2907: nf=checknf(nf); polnf=(GEN)nf[1]; vpol=varn(pol);
2908: pol = fix_relative_pol(nf,pol);
2909: N=lgef(polnf)-3; n=lgef(pol)-3; discpol=discsr(pol);
2910: list=idealfactor(nf,discpol); ep=(long*)list[2]; list=(GEN)list[1];
2911: nbidp=lg(list)-1; for(i=1;i<=nbidp;i++) ep[i]=itos((GEN)ep[i]);
2912: if (DEBUGLEVEL>1)
2913: {
2914: fprintferr("Ideals to consider:\n");
2915: for (i=1; i<=nbidp; i++)
2916: if (ep[i]>1) fprintferr("%Z^%ld\n",list[i],ep[i]);
2917: flusherr();
2918: }
2919: id=idmat(N); unnf=gscalcol_i(gun,N);
2920: matId=idmat_intern(n,unnf, gscalcol_i(gzero,N));
2921: pseudo = NULL;
2922: for (i=1; i<=nbidp; i++)
2923: if (ep[i] > 1)
2924: {
2925: y=rnfordmax(nf,pol,(GEN)list[i],unnf,id,matId);
2926: pseudo = rnfjoinmodules(nf,pseudo,y);
2927: }
2928: if (!pseudo)
2929: {
2930: I=cgetg(n+1,t_VEC); for (i=1; i<=n; i++) I[i]=(long)id;
2931: pseudo=cgetg(3,t_VEC); pseudo[1]=(long)matId; pseudo[2]=(long)I;
2932: }
2933: W=gmodulcp(mat_to_vecpol(basistoalg(nf,(GEN)pseudo[1]),vpol),pol);
2934: p2=cgetg(n+1,t_MAT); for (j=1; j<=n; j++) p2[j]=lgetg(n+1,t_COL);
2935: sym=polsym(pol,n-1);
2936: for (j=1; j<=n; j++)
2937: for (i=j; i<=n; i++)
2938: {
2939: p1 = lift_intern(gmul((GEN)W[i],(GEN)W[j]));
2940: coeff(p2,j,i)=coeff(p2,i,j)=(long)quicktrace(p1,sym);
2941: }
2942: d = algtobasis_intern(nf,det(p2));
2943:
2944: I=(GEN)pseudo[2];
2945: i=1; while (i<=n && gegal((GEN)I[i],id)) i++;
2946: if (i>n) D=id;
2947: else
2948: {
2949: D = (GEN)I[i];
2950: for (i++; i<=n; i++)
2951: if (!gegal((GEN)I[i],id)) D = idealmul(nf,D,(GEN)I[i]);
2952: D = idealpow(nf,D,gdeux);
2953: }
2954: p4=gun; p3=auxdecomp(content(d),0);
2955: for (i=1; i<lg(p3[1]); i++)
2956: p4 = gmul(p4, gpuigs(gcoeff(p3,i,1), itos(gcoeff(p3,i,2))>>1));
2957: p4 = gsqr(p4); tetpil=avma;
2958: i = all? 2: 0;
2959: p1=cgetg(3 + i,t_VEC);
2960: if (i) { p1[1]=lcopy((GEN)pseudo[1]); p1[2]=lcopy(I); }
2961: p1[1+i] = (long)idealmul(nf,D,d);
2962: p1[2+i] = ldiv(d,p4);
2963: return gerepile(av,tetpil,p1);
2964: }
2965:
2966: GEN
2967: rnfpseudobasis(GEN nf, GEN pol)
2968: {
2969: return rnfround2all(nf,pol,1);
2970: }
2971:
2972: GEN
2973: rnfdiscf(GEN nf, GEN pol)
2974: {
2975: return rnfround2all(nf,pol,0);
2976: }
2977:
2978: /* given bnf as output by buchinit and a pseudo-basis of an order
2979: * in HNF [A,I] (or [A,I,D,d] it does not matter), tries to simplify the
2980: * HNF as much as possible. The resulting matrix will be upper triangular
2981: * but the diagonal coefficients will not be equal to 1. The ideals
2982: * are guaranteed to be integral and primitive.
2983: */
2984: GEN
2985: rnfsimplifybasis(GEN bnf, GEN order)
2986: {
2987: long av=avma,tetpil,j,N,n;
2988: GEN p1,id,Az,Iz,nf,A,I;
2989:
2990: bnf = checkbnf(bnf);
2991: if (typ(order)!=t_VEC || lg(order)<3)
2992: err(talker,"not a pseudo-basis in nfsimplifybasis");
2993: A=(GEN)order[1]; I=(GEN)order[2]; n=lg(A)-1; nf=(GEN)bnf[7];
2994: N=lgef(nf[1])-3; id=idmat(N); Iz=cgetg(n+1,t_VEC); Az=cgetg(n+1,t_MAT);
2995: for (j=1; j<=n; j++)
2996: {
2997: if (gegal((GEN)I[j],id)) { Iz[j]=(long)id; Az[j]=A[j]; }
2998: else
2999: {
3000: p1=content((GEN)I[j]);
3001: if (!gcmp1(p1))
3002: {
3003: Iz[j]=(long)gdiv((GEN)I[j],p1); Az[j]=lmul((GEN)A[j],p1);
3004: }
3005: else Az[j]=A[j];
3006: if (!gegal((GEN)Iz[j],id))
3007: {
3008: p1=isprincipalgen(bnf,(GEN)Iz[j]);
3009: if (gcmp0((GEN)p1[1]))
3010: {
3011: p1=(GEN)p1[2]; Iz[j]=(long)id;
3012: Az[j]=(long)element_mulvec(nf,p1,(GEN)Az[j]);
3013: }
3014: }
3015: }
3016: }
3017: tetpil=avma; p1=cgetg(lg(order),t_VEC); p1[1]=lcopy(Az); p1[2]=lcopy(Iz);
3018: for (j=3; j<lg(order); j++) p1[j]=lcopy((GEN)order[j]);
3019: return gerepile(av,tetpil,p1);
3020: }
3021:
3022: GEN
3023: rnfdet2(GEN nf, GEN A, GEN I)
3024: {
3025: long av,tetpil,i;
3026: GEN p1;
3027:
3028: nf=checknf(nf); av = tetpil = avma;
3029: p1=idealhermite(nf,det(matbasistoalg(nf,A)));
3030: for(i=1;i<lg(I);i++) { tetpil=avma; p1=idealmul(nf,p1,(GEN)I[i]); }
3031: tetpil=avma; return gerepile(av,tetpil,p1);
3032: }
3033:
3034: GEN
3035: rnfdet(GEN nf, GEN order)
3036: {
3037: if (typ(order)!=t_VEC || lg(order)<3)
3038: err(talker,"not a pseudo-matrix in rnfdet");
3039: return rnfdet2(nf,(GEN)order[1],(GEN)order[2]);
3040: }
3041:
3042: GEN
3043: rnfdet0(GEN nf, GEN x, GEN y)
3044: {
3045: return y? rnfdet2(nf,x,y): rnfdet(nf,x);
3046: }
3047:
3048: /* given a pseudo-basis of an order in HNF [A,I] (or [A,I,D,d] it does
3049: * not matter), gives an nxn matrix (not in HNF) of a pseudo-basis and
3050: * an ideal vector [id,id,...,id,I] such that order=nf[7]^(n-1)xI.
3051: * Since it uses the approximation theorem, can be long.
3052: */
3053: GEN
3054: rnfsteinitz(GEN nf, GEN order)
3055: {
3056: long av=avma,tetpil,N,j,n;
3057: GEN id,A,I,p1,p2,a,b;
3058:
3059: nf=checknf(nf);
3060: N=lgef(nf[1])-3; id=idmat(N);
3061: if (typ(order)==t_POL) order=rnfpseudobasis(nf,order);
3062: if (typ(order)!=t_VEC || lg(order)<3)
3063: err(talker,"not a pseudo-matrix in rnfsteinitz");
3064: A=gcopy((GEN)order[1]); I=gcopy((GEN)order[2]); n=lg(A)-1;
3065: for (j=1; j<=n-1; j++)
3066: {
3067: a=(GEN)I[j];
3068: if (!gegal(a,id))
3069: {
3070: b=(GEN)I[j+1];
3071: if (gegal(b,id))
3072: {
3073: p1=(GEN)A[j]; A[j]=A[j+1]; A[j+1]=lneg(p1);
3074: I[j]=(long)b; I[j+1]=(long)a;
3075: }
3076: else
3077: {
3078: p2=nfidealdet1(nf,a,b);
3079: p1=gadd(element_mulvec(nf,(GEN)p2[1],(GEN)A[j]),
3080: element_mulvec(nf,(GEN)p2[2],(GEN)A[j+1]));
3081: A[j+1]= (long) gadd(element_mulvec(nf,(GEN)p2[3],(GEN)A[j]),
3082: element_mulvec(nf,(GEN)p2[4],(GEN)A[j+1]));
3083: A[j]=(long)p1;
3084: I[j]=(long)id; I[j+1]=(long)idealmul(nf,a,b);
3085: p1=content((GEN)I[j+1]);
3086: if (!gcmp1(p1))
3087: {
3088: I[j+1] = (long) gdiv((GEN)I[j+1],p1);
3089: A[j+1]=lmul(p1,(GEN)A[j+1]);
3090: }
3091: }
3092: }
3093: }
3094: tetpil=avma; p1=cgetg(lg(order),t_VEC);
3095: p1[1]=lcopy(A); p1[2]=lcopy(I);
3096: for (j=3; j<lg(order); j++) p1[j]=lcopy((GEN)order[j]);
3097: return gerepile(av,tetpil,p1);
3098: }
3099:
3100: /* Given bnf as output by buchinit and either an order as output by
3101: * rnfpseudobasis or a polynomial, and outputs a basis if it is free,
3102: * an n+1-generating set if it is not
3103: */
3104: GEN
3105: rnfbasis(GEN bnf, GEN order)
3106: {
3107: long av=avma,tetpil,j,N,n;
3108: GEN nf,A,I,classe,p1,p2,id;
3109:
3110: bnf = checkbnf(bnf);
3111: nf=(GEN)bnf[7]; N=lgef(nf[1])-3; id=idmat(N);
3112: if (typ(order)==t_POL) order=rnfpseudobasis(nf,order);
3113: if (typ(order)!=t_VEC || lg(order)<3)
3114: err(talker,"not a pseudo-matrix in rnfbasis");
3115: A=(GEN)order[1]; I=(GEN)order[2]; n=lg(A)-1;
3116: j=1; while (j<n && gegal((GEN)I[j],id)) j++;
3117: if (j<n) order=rnfsteinitz(nf,order);
3118: A=(GEN)order[1]; I=(GEN)order[2]; classe=(GEN)I[n];
3119: p1=isprincipalgen(bnf,classe);
3120: if (gcmp0((GEN)p1[1]))
3121: {
3122: p2=cgetg(n+1,t_MAT);
3123: p2[n]=(long)element_mulvec(nf,(GEN)p1[2],(GEN)A[n]);
3124: }
3125: else
3126: {
3127: p1=ideal_two_elt(nf,classe);
3128: p2=cgetg(n+2,t_MAT);
3129: p2[n]=lmul((GEN)p1[1],(GEN)A[n]);
3130: p2[n+1]=(long)element_mulvec(nf,(GEN)p1[2],(GEN)A[n]);
3131: }
3132: for (j=1; j<n; j++) p2[j]=A[j];
3133: tetpil = avma; return gerepile(av,tetpil,gcopy(p2));
3134: }
3135:
3136: /* Given bnf as output by buchinit and either an order as output by
3137: * rnfpseudobasis or a polynomial, and outputs a basis (not pseudo)
3138: * in Hermite Normal Form if it exists, zero if not
3139: */
3140: GEN
3141: rnfhermitebasis(GEN bnf, GEN order)
3142: {
3143: long av=avma,tetpil,j,N,n;
3144: GEN nf,A,I,p1,id;
3145:
3146: bnf = checkbnf(bnf); nf=(GEN)bnf[7];
3147: N=lgef(nf[1])-3; id=idmat(N);
3148: if (typ(order)==t_POL)
3149: {
3150: order=rnfpseudobasis(nf,order);
3151: A=(GEN)order[1];
3152: }
3153: else
3154: {
3155: if (typ(order)!=t_VEC || lg(order)<3)
3156: err(talker,"not a pseudo-matrix in rnfbasis");
3157: A=gcopy((GEN)order[1]);
3158: }
3159: I=(GEN)order[2]; n=lg(A)-1;
3160: for (j=1; j<=n; j++)
3161: {
3162: if (!gegal((GEN)I[j],id))
3163: {
3164: p1=isprincipalgen(bnf,(GEN)I[j]);
3165: if (gcmp0((GEN)p1[1]))
3166: A[j]=(long)element_mulvec(nf,(GEN)p1[2],(GEN)A[j]);
3167: else { avma=av; return gzero; }
3168: }
3169: }
3170: tetpil=avma; return gerepile(av,tetpil,gcopy(A));
3171: }
3172:
3173: long
3174: rnfisfree(GEN bnf, GEN order)
3175: {
3176: long av=avma,n,N,j;
3177: GEN nf,p1,id,I;
3178:
3179: bnf = checkbnf(bnf);
3180: if (gcmp1(gmael3(bnf,8,1,1))) return 1;
3181:
3182: nf=(GEN)bnf[7]; N=lgef(nf[1])-3; id=idmat(N);
3183: if (typ(order)==t_POL) order=rnfpseudobasis(nf,order);
3184: if (typ(order)!=t_VEC || lg(order)<3)
3185: err(talker,"not a pseudo-matrix in rnfisfree");
3186:
3187: I=(GEN)order[2]; n=lg(I)-1;
3188: j=1; while (j<=n && gegal((GEN)I[j],id)) j++;
3189: if (j>n) { avma=av; return 1; }
3190:
3191: p1=(GEN)I[j];
3192: for (j++; j<=n; j++)
3193: if (!gegal((GEN)I[j],id)) p1=idealmul(nf,p1,(GEN)I[j]);
3194: j = gcmp0(isprincipal(bnf,p1));
3195: avma=av; return j;
3196: }
3197:
3198: /**********************************************************************/
3199: /** **/
3200: /** COMPOSITUM OF TWO NUMBER FIELDS **/
3201: /** **/
3202: /**********************************************************************/
3203:
3204: #define nexta(a) (a>0 ? -a : 1-a)
3205:
3206: GEN
3207: polcompositum0(GEN pol1, GEN pol2, long flall)
3208: {
3209: long av=avma,tetpil,i,v,a,l;
3210: GEN pro1,p1,p2,p3,p4,p5,fa,rk,y;
3211:
3212: if (typ(pol1)!=t_POL || typ(pol2)!=t_POL) err(typeer,"polcompositum0");
3213: v=varn(pol1);
3214: if (varn(pol2)!=v) err(talker,"not the same variable in compositum");
3215: if (lgef(pol1)<=3 || lgef(pol2)<=3)
3216: err(constpoler,"compositum");
3217: if (lgef(ggcd(pol1,derivpol(pol1)))>3 || lgef(ggcd(pol2,derivpol(pol2)))>3)
3218: err(talker,"not a separable polynomial in compositum");
3219:
3220: for (a=1; ; a=nexta(a))
3221: {
3222: avma=av;
3223: if (DEBUGLEVEL>=2)
3224: {
3225: fprintferr("trying beta ");
3226: if (a>0) fprintferr("- "); else fprintferr("+ ");
3227: if (labs(a)>1) fprintferr("%ld ",labs(a));
3228: fprintferr("alpha\n"); flusherr();
3229: }
3230: pro1 = gadd(polx[MAXVARN],gmulsg(a,polx[v]));
3231: p1 = gsubst(pol2,v,pro1);
3232: p2 = subresall(pol1,p1,&rk);
3233: if (lgef(ggcd(p2,deriv(p2,MAXVARN)))==3)
3234: {
3235: p2 = gsubst(p2,MAXVARN,polx[v]);
3236: fa = factor(p2); fa = (GEN)fa[1];
3237: if (typ(rk)==t_POL && lgef(rk)==4)
3238: {
3239: if (flall)
3240: {
3241: l=lg(fa); y=cgetg(l,t_VEC);
3242: for (i=1; i<l; i++)
3243: {
3244: p3=cgetg(5,t_VEC); p3[1]=fa[i]; y[i]=(long)p3;
3245: p4=gmodulcp(polx[v],(GEN)fa[i]);
3246: p5=gneg_i(gdiv(gsubst((GEN)rk[2],MAXVARN,p4),
3247: gsubst((GEN)rk[3],MAXVARN,p4)));
3248: p3[2]=(long)p5;
3249: p3[3]=ladd(p4,gmulsg(a,p5));
3250: p3[4]=lstoi(-a);
3251: }
3252: }
3253: else y=fa;
3254: tetpil=avma; return gerepile(av,tetpil,gcopy(y));
3255: }
3256: }
3257: }
3258: }
3259:
3260: GEN
3261: compositum(GEN pol1,GEN pol2)
3262: {
3263: return polcompositum0(pol1,pol2,0);
3264: }
3265:
3266: GEN
3267: compositum2(GEN pol1,GEN pol2)
3268: {
3269: return polcompositum0(pol1,pol2,1);
3270: }
3271:
3272: GEN
3273: rnfequation0(GEN nf, GEN pol2, long flall)
3274: {
3275: long av=avma,av1,tetpil,v,vpol,a,l1,l2;
3276: GEN pol1,pro1,p1,p2,p4,p5,rk,y;
3277:
3278: if (typ(nf)==t_POL) pol1=nf; else { nf=checknf(nf); pol1=(GEN)nf[1]; }
3279: pol2 = fix_relative_pol(nf,pol2);
3280: v=varn(pol1); vpol=varn(pol2);
3281:
3282: l1=lgef(pol1); l2=lgef(pol2);
3283: if (l1<=3 || l2<=3) err(constpoler,"rnfequation");
3284:
3285: p2=cgetg(l2,t_POL); p2[1]=pol2[1];
3286: for (a=2; a<l2; a++)
3287: p2[a] = (lgef(pol2[a]) < l1)? pol2[a]: lres((GEN)pol2[a],pol1);
3288: pol2=p2;
3289: if (lgef(ggcd(pol2,derivpol(pol2)))>3)
3290: err(talker,"not a separable relative equation in rnfequation");
3291: pol2=lift_intern(pol2);
3292:
3293: a=0; av1=avma;
3294: for(;;)
3295: {
3296: avma=av1;
3297: if (DEBUGLEVEL>=2)
3298: {
3299: fprintferr("trying beta ");
3300: if (a)
3301: {
3302: if (a>0) fprintferr("- "); else fprintferr("+ ");
3303: if (labs(a)>1) fprintferr("%ld alpha\n",labs(a));
3304: else fprintferr("alpha\n");
3305: }
3306: flusherr();
3307: }
3308: pro1=gadd(polx[MAXVARN],gmulsg(a,polx[v]));
3309: p1=poleval(pol2,pro1);
3310: p2=subresall(pol1,p1,&rk);
3311: if (rk != gzero && lgef(rk)==4 && lgef(ggcd(p2,deriv(p2,MAXVARN)))==3)
3312: {
3313: p2=gsubst(p2,MAXVARN,polx[vpol]);
3314: if (gsigne(leadingcoeff(p2))<0) p2=gneg_i(p2);
3315: if (flall)
3316: {
3317: y=cgetg(4,t_VEC); y[1]=(long)p2;
3318: p4=gmodulcp(polx[vpol],p2);
3319: p5=gneg_i(gdiv(gsubst((GEN)rk[2],MAXVARN,p4),
3320: gsubst((GEN)rk[3],MAXVARN,p4)));
3321: y[3]=(long)stoi(-a);
3322: y[2]=lmul(gmodulcp(polun[vpol],p2),p5);
3323: }
3324: else y=p2;
3325: if (DEBUGLEVEL>=2) fprintferr("ok! leaving rnfequation\n");
3326: tetpil=avma; return gerepile(av,tetpil,gcopy(y));
3327: }
3328: a=nexta(a);
3329: }
3330: }
3331:
3332: GEN
3333: rnfequation(GEN nf,GEN pol2)
3334: {
3335: return rnfequation0(nf,pol2,0);
3336: }
3337:
3338: GEN
3339: rnfequation2(GEN nf,GEN pol2)
3340: {
3341: return rnfequation0(nf,pol2,1);
3342: }
3343:
3344: static GEN
3345: nftau(long r1, GEN x)
3346: {
3347: long i, ru = lg(x);
3348: GEN s;
3349:
3350: s = r1 ? (GEN)x[1] : gmul2n(greal((GEN)x[1]),1);
3351: for (i=2; i<=r1; i++) s=gadd(s,(GEN)x[i]);
3352: for ( ; i<ru; i++) s=gadd(s,gmul2n(greal((GEN)x[i]),1));
3353: return s;
3354: }
3355:
3356: static GEN
3357: nftocomplex(GEN nf, GEN x)
3358: {
3359: long ru,vnf,k;
3360: GEN p2,p3,ronf;
3361:
3362: p2 = (typ(x)==t_POLMOD)? (GEN)x[2]: gmul((GEN)nf[7],x);
3363: vnf=varn(nf[1]);
3364: ronf=(GEN)nf[6]; ru=lg(ronf); p3=cgetg(ru,t_COL);
3365: for (k=1; k<ru; k++) p3[k]=lsubst(p2,vnf,(GEN)ronf[k]);
3366: return p3;
3367: }
3368:
3369: static GEN
3370: rnfscal(GEN mth, GEN xth, GEN yth)
3371: {
3372: long n,ru,i,j,kk;
3373: GEN x,y,m,res,p1,p2;
3374:
3375: n=lg(mth)-1; ru=lg(gcoeff(mth,1,1));
3376: res=cgetg(ru,t_COL);
3377: for (kk=1; kk<ru; kk++)
3378: {
3379: m=cgetg(n+1,t_MAT);
3380: for (j=1; j<=n; j++)
3381: {
3382: p1=cgetg(n+1,t_COL); m[j]=(long)p1;
3383: for (i=1; i<=n; i++) { p2=gcoeff(mth,i,j); p1[i]=p2[kk]; }
3384: }
3385: x=cgetg(n+1,t_VEC);
3386: for (j=1; j<=n; j++) x[j]=(long)gconj((GEN)((GEN)xth[j])[kk]);
3387: y=cgetg(n+1,t_COL);
3388: for (j=1; j<=n; j++) y[j]=((GEN)yth[j])[kk];
3389: res[kk]=(long)gmul(x,gmul(m,y));
3390: }
3391: return res;
3392: }
3393:
3394: static GEN
3395: rnfdiv(GEN x, GEN y)
3396: {
3397: long i, ru = lg(x);
3398: GEN z;
3399:
3400: z=cgetg(ru,t_COL);
3401: for (i=1; i<ru; i++) z[i]=(long)gdiv((GEN)x[i],(GEN)y[i]);
3402: return z;
3403: }
3404:
3405: static GEN
3406: rnfmul(GEN x, GEN y)
3407: {
3408: long i, ru = lg(x);
3409: GEN z;
3410:
3411: z=cgetg(ru,t_COL);
3412: for (i=1; i<ru; i++) z[i]=(long)gmul((GEN)x[i],(GEN)y[i]);
3413: return z;
3414: }
3415:
3416: static GEN
3417: rnfvecmul(GEN x, GEN v)
3418: {
3419: long i, lx = lg(v);
3420: GEN y;
3421:
3422: y=cgetg(lx,typ(v));
3423: for (i=1; i<lx; i++) y[i]=(long)rnfmul(x,(GEN)v[i]);
3424: return y;
3425: }
3426:
3427: static GEN
3428: allonge(GEN v, long N)
3429: {
3430: long r,r2,i;
3431: GEN y;
3432:
3433: r=lg(v)-1; r2=N-r;
3434: y=cgetg(N+1,t_COL);
3435: for (i=1; i<=r; i++) y[i]=v[i];
3436: for ( ; i<=N; i++) y[i]=(long)gconj((GEN)v[i-r2]);
3437: return y;
3438: }
3439:
3440: static GEN
3441: findmin(GEN nf, GEN ideal, GEN muf,long prec)
3442: {
3443: long av=avma,N,tetpil,i;
3444: GEN m,y;
3445:
3446: m = qf_base_change(gmael(nf,5,3), ideal, 0); /* nf[5][3] = T2 */
3447: m = lllgramintern(m,4,1,prec);
3448: if (!m)
3449: {
3450: m = lllint(ideal);
3451: m = qf_base_change(gmael(nf,5,3), gmul(ideal,m), 0);
3452: m = lllgramintern(m,4,1,prec);
3453: if (!m) err(talker,"precision too low in rnflllgram");
3454: }
3455: ideal=gmul(ideal,m);
3456: N=lg(ideal)-1; y=cgetg(N+1,t_MAT);
3457: for (i=1; i<=N; i++)
3458: y[i] = (long) allonge(nftocomplex(nf,(GEN)ideal[i]),N);
3459: m=ground(greal(gauss(y,allonge(muf,N))));
3460: tetpil=avma; return gerepile(av,tetpil,gmul(ideal,m));
3461: }
3462:
3463: #define swap(x,y) { long _t=x; x=y; y=_t; }
3464:
3465: /* given a base field nf (e.g main variable y), a polynomial pol with
3466: * coefficients in nf (e.g main variable x), and an order as output
3467: * by rnfpseudobasis, outputs a reduced order.
3468: */
3469: GEN
3470: rnflllgram(GEN nf, GEN pol, GEN order,long prec)
3471: {
3472: long av=avma,tetpil,i,j,k,l,kk,kmax,r1,ru,lx,n,vnf;
3473: GEN p1,p2,M,I,U,ronf,poll,unro,roorder,powreorder,mth,s,MC,MPOL,MCS;
3474: GEN B,mu,Bf,temp,ideal,x,xc,xpol,muf,mufc,muno,y,z,Ikk_inv;
3475:
3476: /* Initializations and verifications */
3477:
3478: nf=checknf(nf);
3479: if (typ(order)!=t_VEC || lg(order)<3)
3480: err(talker,"not a pseudo-matrix in rnflllgram");
3481: M=(GEN)order[1]; I=gcopy((GEN)order[2]); lx=lg(I); n=lg(I)-1;
3482:
3483: /* Initialize U to the n x n identity matrix with coefficients in nf in
3484: the form of polymods */
3485:
3486: U=cgetg(n+1,t_MAT);
3487: for (j=1; j<=n; j++)
3488: {
3489: p1=cgetg(n+1,t_COL); U[j]=(long)p1;
3490: for (i=1; i<=n; i++) p1[i]=(i==j)?un:zero;
3491: }
3492:
3493: /* Compute the relative T2 matrix of powers of theta */
3494:
3495: vnf=varn(nf[1]); ronf=(GEN)nf[6]; ru=lg(ronf); poll=lift(pol);
3496: r1=itos(gmael(nf,2,1));
3497: unro=cgetg(n+1,t_COL); for (i=1; i<=n; i++) unro[i]=un;
3498: roorder=cgetg(ru,t_VEC);
3499: for (i=1; i<ru; i++)
3500: roorder[i]=lroots(gsubst(poll,vnf,(GEN)ronf[i]),prec);
3501: powreorder=cgetg(n+1,t_MAT);
3502: p1=cgetg(ru,t_COL); powreorder[1]=(long)p1;
3503: for (i=1; i<ru; i++) p1[i]=(long)unro;
3504: for (k=2; k<=n; k++)
3505: {
3506: p1=cgetg(ru,t_COL); powreorder[k]=(long)p1;
3507: for (i=1; i<ru; i++)
3508: {
3509: p2=cgetg(n+1,t_COL); p1[i]=(long)p2;
3510: for (j=1; j<=n; j++)
3511: p2[j] = lmul(gmael(roorder,i,j),gmael3(powreorder,k-1,i,j));
3512: }
3513: }
3514: mth=cgetg(n+1,t_MAT);
3515: for (l=1; l<=n; l++)
3516: {
3517: p1=cgetg(n+1,t_COL); mth[l]=(long)p1;
3518: for (k=1; k<=n; k++)
3519: {
3520: p2=cgetg(ru,t_COL); p1[k]=(long)p2;
3521: for (i=1; i<ru; i++)
3522: {
3523: s=gzero;
3524: for (j=1; j<=n; j++)
3525: s = gadd(s,gmul(gconj(gmael3(powreorder,k,i,j)),
3526: gmael3(powreorder,l,i,j)));
3527: p2[i]=(long)s;
3528: }
3529: }
3530: }
3531:
3532: /* Transform the matrix M into a matrix with coefficients in K and also
3533: with coefficients polymod */
3534:
3535: MC=cgetg(lx,t_MAT); MPOL=cgetg(lx,t_MAT);
3536: for (j=1; j<=n; j++)
3537: {
3538: p1=cgetg(lx,t_COL); MC[j]=(long)p1;
3539: p2=cgetg(lx,t_COL); MPOL[j]=(long)p2;
3540: for (i=1; i<=n; i++)
3541: {
3542: p2[i]=(long)basistoalg(nf,gcoeff(M,i,j));
3543: p1[i]=(long)nftocomplex(nf,(GEN)p2[i]);
3544: }
3545: }
3546: MCS=cgetg(lx,t_MAT);
3547:
3548: /* Start LLL algorithm */
3549:
3550: mu=cgetg(lx,t_MAT); B=cgetg(lx,t_COL);
3551: for (j=1; j<lx; j++)
3552: {
3553: p1=cgetg(lx,t_COL); mu[j]=(long)p1; for (i=1; i<lx; i++) p1[i]=zero;
3554: B[j]=zero;
3555: }
3556: kk=2; if (DEBUGLEVEL) fprintferr("kk = %ld ",kk);
3557: kmax=1; B[1]=lreal(rnfscal(mth,(GEN)MC[1],(GEN)MC[1]));
3558: MCS[1]=lcopy((GEN)MC[1]);
3559: do
3560: {
3561: if (kk>kmax)
3562: {
3563: /* Incremental Gram-Schmidt */
3564: kmax=kk; MCS[kk]=lcopy((GEN)MC[kk]);
3565: for (j=1; j<kk; j++)
3566: {
3567: coeff(mu,kk,j) = (long) rnfdiv(rnfscal(mth,(GEN)MCS[j],(GEN)MC[kk]),
3568: (GEN) B[j]);
3569: MCS[kk] = lsub((GEN) MCS[kk], rnfvecmul(gcoeff(mu,kk,j),(GEN)MCS[j]));
3570: }
3571: B[kk] = lreal(rnfscal(mth,(GEN)MCS[kk],(GEN)MCS[kk]));
3572: if (gcmp0((GEN)B[kk])) err(lllger3);
3573: }
3574:
3575: /* RED(k,k-1) */
3576: l=kk-1; Ikk_inv=idealinv(nf, (GEN)I[kk]);
3577: ideal=idealmul(nf,(GEN)I[l],Ikk_inv);
3578: x=findmin(nf,ideal,gcoeff(mu,kk,l),2*prec-2);
3579: if (!gcmp0(x))
3580: {
3581: xpol=basistoalg(nf,x); xc=nftocomplex(nf,xpol);
3582: MC[kk]=lsub((GEN)MC[kk],rnfvecmul(xc,(GEN)MC[l]));
3583: U[kk]=lsub((GEN)U[kk],gmul(xpol,(GEN)U[l]));
3584: coeff(mu,kk,l)=lsub(gcoeff(mu,kk,l),xc);
3585: for (i=1; i<l; i++)
3586: coeff(mu,kk,i)=lsub(gcoeff(mu,kk,i),rnfmul(xc,gcoeff(mu,l,i)));
3587: }
3588: /* Test LLL condition */
3589: p1=nftau(r1,gadd((GEN) B[kk],
3590: gmul(gnorml2(gcoeff(mu,kk,kk-1)),(GEN)B[kk-1])));
3591: p2=gdivgs(gmulsg(9,nftau(r1,(GEN)B[kk-1])),10);
3592: if (gcmp(p1,p2)<=0)
3593: {
3594: /* Execute SWAP(k) */
3595: k=kk;
3596: swap(MC[k-1],MC[k]);
3597: swap(U[k-1],U[k]);
3598: swap(I[k-1],I[k]);
3599: for (j=1; j<=k-2; j++) swap(coeff(mu,k-1,j),coeff(mu,k,j));
3600: muf=gcoeff(mu,k,k-1);
3601: mufc=gconj(muf); muno=greal(rnfmul(muf,mufc));
3602: Bf=gadd((GEN)B[k],rnfmul(muno,(GEN)B[k-1]));
3603: p1=rnfdiv((GEN)B[k-1],Bf);
3604: coeff(mu,k,k-1)=(long)rnfmul(mufc,p1);
3605: temp=(GEN)MCS[k-1];
3606: MCS[k-1]=ladd((GEN)MCS[k],rnfvecmul(muf,(GEN)MCS[k-1]));
3607: MCS[k]=lsub(rnfvecmul(rnfdiv((GEN)B[k],Bf),temp),
3608: rnfvecmul(gcoeff(mu,k,k-1),(GEN)MCS[k]));
3609: B[k]=(long)rnfmul((GEN)B[k],p1); B[k-1]=(long)Bf;
3610: for (i=k+1; i<=kmax; i++)
3611: {
3612: temp=gcoeff(mu,i,k);
3613: coeff(mu,i,k)=lsub(gcoeff(mu,i,k-1),rnfmul(muf,gcoeff(mu,i,k)));
3614: coeff(mu,i,k-1) = ladd(temp, rnfmul(gcoeff(mu,k,k-1),gcoeff(mu,i,k)));
3615: }
3616: if (kk>2) { kk--; if (DEBUGLEVEL) fprintferr("%ld ",kk); }
3617: }
3618: else
3619: {
3620: for (l=kk-2; l; l--)
3621: {
3622: /* RED(k,l) */
3623: ideal=idealmul(nf,(GEN)I[l],Ikk_inv);
3624: x=findmin(nf,ideal,gcoeff(mu,kk,l),2*prec-2);
3625: if (!gcmp0(x))
3626: {
3627: xpol=basistoalg(nf,x); xc=nftocomplex(nf,xpol);
3628: MC[kk]=(long)gsub((GEN)MC[kk],rnfvecmul(xc,(GEN)MC[l]));
3629: U[kk]=(long)gsub((GEN)U[kk],gmul(xpol,(GEN)U[l]));
3630: coeff(mu,kk,l)=lsub(gcoeff(mu,kk,l),xc);
3631: for (i=1; i<l; i++)
3632: coeff(mu,kk,i) = lsub(gcoeff(mu,kk,i), rnfmul(xc,gcoeff(mu,l,i)));
3633: }
3634: }
3635: kk++; if (DEBUGLEVEL) fprintferr("%ld ",kk);
3636: }
3637: }
3638: while (kk<=n);
3639: if (DEBUGLEVEL) fprintferr("\n");
3640: p1=gmul(MPOL,U); tetpil=avma;
3641: y=cgetg(3,t_VEC); z=cgetg(3,t_VEC); y[1]=(long)z;
3642: z[2]=lcopy(I); z[1]=(long)algtobasis(nf,p1);
3643: y[2]=(long)algtobasis(nf,U);
3644: return gerepile(av,tetpil,y);
3645: }
3646:
3647: GEN
3648: rnfpolred(GEN nf, GEN pol, long prec)
3649: {
3650: long av=avma,tetpil,i,j,k,n,N,vpol,flbnf;
3651: GEN id,id2,newid,newor,p1,p2,al,newpol,w,z;
3652: GEN bnf,zk,newideals,ideals,order,neworder;
3653:
3654: if (typ(nf)!=t_VEC) err(idealer1);
3655: switch(lg(nf))
3656: {
3657: case 10: flbnf=0; break;
3658: case 11: flbnf=1; bnf=nf; nf=checknf((GEN)nf[7]); break;
3659: default: err(idealer1);
3660: }
3661: id=rnfpseudobasis(nf,pol); N=lgef(nf[1])-3;
3662: if (flbnf && gcmp1(gmael3(bnf,8,1,1))) /* if bnf is principal */
3663: {
3664: ideals=(GEN)id[2]; n=lg(ideals)-1; order=(GEN)id[1];
3665: newideals=cgetg(n+1,t_VEC); neworder=cgetg(n+1,t_MAT);
3666: zk=idmat(N);
3667: for (j=1; j<=n; j++)
3668: {
3669: newideals[j]=(long)zk; p1=cgetg(n+1,t_COL); neworder[j]=(long)p1;
3670: p2=(GEN)order[j];
3671: al=(GEN)isprincipalgen(bnf,(GEN)ideals[j])[2];
3672: for (k=1; k<=n; k++)
3673: p1[k]=(long)element_mul(nf,(GEN)p2[k],al);
3674: }
3675: id=cgetg(3,t_VEC); id[1]=(long)neworder; id[2]=(long)newideals;
3676: }
3677: id2=rnflllgram(nf,pol,id,prec);
3678: z=(GEN)id2[1]; newid=(GEN)z[2]; newor=(GEN)z[1];
3679: n=lg(newor)-1; w=cgetg(n+1,t_VEC); vpol=varn(pol);
3680: for (j=1; j<=n; j++)
3681: {
3682: p1=(GEN)newid[j]; al=gmul(gcoeff(p1,1,1),(GEN)newor[j]);
3683: p1=basistoalg(nf,(GEN)al[n]);
3684: for (i=n-1; i; i--)
3685: p1=gadd(basistoalg(nf,(GEN)al[i]),gmul(polx[vpol],p1));
3686: newpol=gtopoly(gmodulcp(gtovec(caract2(lift(pol),lift(p1),vpol)),
3687: (GEN) nf[1]), vpol);
3688: p1 = ggcd(newpol, derivpol(newpol));
3689: if (degree(p1)>0)
3690: {
3691: newpol=gdiv(newpol,p1);
3692: newpol=gdiv(newpol,leading_term(newpol));
3693: }
3694: w[j]=(long)newpol;
3695: if (DEBUGLEVEL>=4) outerr(newpol);
3696: }
3697: tetpil=avma; return gerepile(av,tetpil,gcopy(w));
3698: }
3699:
3700: GEN
3701: makebasis(GEN nf,GEN pol)
3702: /* Etant donne un corps de nombres nf et un polynome relatif relpol,
3703: construit une pseudo-base de l'extension puis calcule une base absolue
3704: de cette extension pour une racine \theta de relpol. Renvoie le
3705: polynome irreductible de theta sur Q et la matrice de la base */
3706: {
3707: GEN elts,ids,polabs,plg,B,bs,p1,colonne,p2,rep,a;
3708: GEN den,vbs,vbspro,mpro,vpro,rnf;
3709: long av=avma,tetpil,n,N,m,i,j,k,v1,v2;
3710:
3711: v1=varn((GEN)nf[1]); v2=varn(pol);
3712: p1=rnfequation2(nf,pol);
3713: polabs=(GEN)p1[1]; plg=(GEN)p1[2];
3714: a=(GEN)p1[3];
3715: rnf=cgetg(12,t_VEC); rnf[1]=(long)pol;
3716: for (i=2;i<=9;i++) rnf[i]=zero;
3717: rnf[10]=(long)nf;
3718: p2=cgetg(4,t_VEC); p2[1] = p2[2] = zero;
3719: p2[3]=(long)a; rnf[11]=(long)p2;
3720: if (signe(a))
3721: pol=gsubst(pol,v2,gsub(polx[v2],
3722: gmul(a,gmodulcp(polx[v1],(GEN)nf[1]))));
3723: p1=rnfpseudobasis(nf,pol);
3724: if (DEBUGLEVEL>=2) { fprintferr("relative basis computed\n"); flusherr(); }
3725: elts=(GEN)p1[1];ids=(GEN)p1[2];
3726: N=lgef(pol)-3;n=lgef((GEN)nf[1])-3;m=n*N;
3727: den=denom(content(lift(plg)));
3728: vbs=cgetg(n+1,t_VEC);
3729: vbs[1]=un;vbs[2]=(long)plg;
3730: vbspro=gmul(den,plg);
3731: for(i=3;i<=n;i++)
3732: vbs[i]=ldiv(gmul((GEN)vbs[i-1],vbspro),den);
3733: mpro=cgetg(n+1,t_MAT);
3734: for(j=1;j<=n;j++)
3735: {
3736: p2=cgetg(n+1,t_COL);mpro[j]=(long)p2;
3737: for(i=1;i<=n;i++)
3738: p2[i]=(long)truecoeff(gmael(nf,7,j),i-1);
3739: }
3740: bs=gmul(vbs,mpro); B=idmat(m);
3741: vpro=cgetg(N+1,t_VEC);
3742: for (i=1;i<=N;i++)
3743: {
3744: p1=cgetg(3,t_POLMOD);
3745: p1[1]=(long)polabs;
3746: p1[2]=lpuigs(polx[v2],i-1); vpro[i]=(long)p1;
3747: }
3748: vpro=gmul(vpro,elts);
3749: for(i=1;i<=N;i++)
3750: for(j=1;j<=n;j++)
3751: {
3752: colonne=gmul(bs,element_mul(nf,(GEN)vpro[i],gmael(ids,i,j)));
3753: p1=gtovec(lift_intern(colonne));
3754: p2=cgetg(m+1,t_COL);
3755: for(k=1;k<lg(p1);k++) p2[lg(p1)-k]=p1[k];
3756: for( ;k<=m;k++) p2[k]=zero;
3757: B[(i-1)*n+j]=(long)p2;
3758: }
3759: rep=cgetg(4,t_VEC);
3760: rep[1]=(long)polabs;
3761: rep[2]=(long)B;
3762: rep[3]=(long)rnf;
3763: tetpil=avma;
3764: return gerepile(av,tetpil,gcopy(rep));
3765: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>