Annotation of OpenXM_contrib/pari-2.2/src/basemath/base1.c, Revision 1.2
1.2 ! noro 1: /* $Id: base1.c,v 1.103 2002/09/07 13:34:38 karim Exp $
1.1 noro 2:
3: Copyright (C) 2000 The PARI group.
4:
5: This file is part of the PARI/GP package.
6:
7: PARI/GP is free software; you can redistribute it and/or modify it under the
8: terms of the GNU General Public License as published by the Free Software
9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
10: ANY WARRANTY WHATSOEVER.
11:
12: Check the License for details. You should have received a copy of it, along
13: with the package; see the file 'COPYING'. If not, write to the Free Software
14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
15:
16: /**************************************************************/
17: /* */
18: /* NUMBER FIELDS */
19: /* */
20: /**************************************************************/
21: #include "pari.h"
22: #include "parinf.h"
1.2 ! noro 23:
! 24: int new_galois_format = 0;
! 25:
! 26: extern GEN R_from_QR(GEN x, long prec);
! 27: extern GEN to_polmod(GEN x, GEN mod);
! 28: extern GEN roots_to_pol_r1r2(GEN a, long r1, long v);
! 29: extern GEN idealhermite_aux(GEN nf, GEN x);
! 30: extern GEN cauchy_bound(GEN p);
! 31: extern GEN galoisbig(GEN x, long prec);
! 32: extern GEN lllfp_marked(int M, GEN x, long D, long flag, long prec, int gram);
! 33: extern GEN lllint_marked(long M, GEN x, long D, int g, GEN *h, GEN *fl, GEN *B);
! 34: extern GEN mulmat_pol(GEN A, GEN x);
! 35: extern ulong smulss(ulong x, ulong y, ulong *rem);
1.1 noro 36:
37: void
38: checkrnf(GEN rnf)
39: {
1.2 ! noro 40: if (typ(rnf)!=t_VEC || lg(rnf)!=12) err(idealer1);
1.1 noro 41: }
42:
43: GEN
1.2 ! noro 44: _checkbnf(GEN bnf)
1.1 noro 45: {
1.2 ! noro 46: if (typ(bnf) == t_VEC)
! 47: switch (lg(bnf))
! 48: {
! 49: case 11: return bnf;
! 50: case 7: return checkbnf((GEN)bnf[1]);
! 51:
! 52: case 3:
! 53: if (typ(bnf[2])==t_POLMOD)
! 54: return checkbnf((GEN)bnf[1]);
! 55: }
! 56: return NULL;
! 57: }
! 58:
! 59: GEN
! 60: _checknf(GEN nf)
! 61: {
! 62: if (typ(nf)==t_VEC)
! 63: switch(lg(nf))
! 64: {
! 65: case 10: return nf;
! 66: case 11: return checknf((GEN)nf[7]);
! 67: case 7: return checknf((GEN)nf[1]);
! 68: case 3: if (typ(nf[2]) == t_POLMOD) return checknf((GEN)nf[1]);
! 69: }
! 70: return NULL;
! 71: }
! 72:
! 73: GEN
! 74: checkbnf(GEN x)
! 75: {
! 76: GEN bnf = _checkbnf(x);
! 77: if (!bnf)
1.1 noro 78: {
1.2 ! noro 79: if (_checknf(x)) err(talker,"please apply bnfinit first");
! 80: err(idealer1);
1.1 noro 81: }
1.2 ! noro 82: return bnf;
1.1 noro 83: }
84:
85: GEN
86: checkbnf_discard(GEN bnf)
87: {
88: GEN x = checkbnf(bnf);
89: if (x != bnf && lg(bnf) == 3)
90: err(warner,"non-monic polynomial. Change of variables discarded");
91: return x;
92: }
93:
94: GEN
1.2 ! noro 95: checknf(GEN x)
1.1 noro 96: {
1.2 ! noro 97: GEN nf = _checknf(x);
! 98: if (!nf)
! 99: {
! 100: if (typ(x)==t_POL) err(talker,"please apply nfinit first");
! 101: err(idealer1);
1.1 noro 102: }
1.2 ! noro 103: return nf;
1.1 noro 104: }
105:
106: void
107: checkbnr(GEN bnr)
108: {
109: if (typ(bnr)!=t_VEC || lg(bnr)!=7)
110: err(talker,"incorrect bigray field");
111: (void)checkbnf((GEN)bnr[1]);
112: }
113:
114: void
115: checkbnrgen(GEN bnr)
116: {
117: checkbnr(bnr);
118: if (lg(bnr[5])<=3)
119: err(talker,"please apply bnrinit(,,1) and not bnrinit(,)");
120: }
121:
122: GEN
123: check_units(GEN bnf, char *f)
124: {
125: GEN nf, x;
126: bnf = checkbnf(bnf); nf = checknf(bnf);
127: x = (GEN)bnf[8];
128: if (lg(x) < 7 || (lg(x[5]) == 1 && lg(nf[6]) > 2))
129: err(talker,"missing units in %s", f);
130: return (GEN)x[5];
131: }
132:
133: void
134: checkid(GEN x, long N)
135: {
136: if (typ(x)!=t_MAT) err(idealer2);
137: if (lg(x) == 1 || lg(x[1]) != N+1)
138: err(talker,"incorrect matrix for ideal");
139: }
140:
141: void
142: checkbid(GEN bid)
143: {
144: if (typ(bid)!=t_VEC || lg(bid)!=6 || lg(bid[1])!=3)
145: err(talker,"incorrect bigideal");
146: }
147:
148: void
149: checkprimeid(GEN id)
150: {
151: if (typ(id) != t_VEC || lg(id) != 6)
152: err(talker,"incorrect prime ideal");
153: }
154:
155: void
156: check_pol_int(GEN x, char *s)
157: {
158: long k = lgef(x)-1;
159: for ( ; k>1; k--)
160: if (typ(x[k])!=t_INT) err(talker,"polynomial not in Z[X] in %s",s);
161: }
162:
163: GEN
164: checknfelt_mod(GEN nf, GEN x, char *s)
165: {
166: if (!gegal((GEN)x[1],(GEN)nf[1]))
167: err(talker,"incompatible modulus in %s:\n mod = %Z,\n nf = %Z",
168: s, x[1], nf[1]);
169: return (GEN)x[2];
170: }
171:
172: GEN
173: get_primeid(GEN x)
174: {
175: if (typ(x) != t_VEC) return NULL;
176: if (lg(x) == 3) x = (GEN)x[1];
177: if (lg(x) != 6 || typ(x[3]) != t_INT) return NULL;
178: return x;
179: }
180:
181: GEN
182: get_bnf(GEN x, int *t)
183: {
184: switch(typ(x))
185: {
186: case t_POL: *t = typ_POL; return NULL;
187: case t_QUAD: *t = typ_Q ; return NULL;
188: case t_VEC:
189: switch(lg(x))
190: {
191: case 3:
192: if (typ(x[2]) != t_POLMOD) break;
193: return get_bnf((GEN)x[1],t);
194: case 6 : *t = typ_QUA; return NULL;
195: case 10: *t = typ_NF; return NULL;
196: case 11: *t = typ_BNF; return x;
197: case 7 : *t = typ_BNR;
198: x = (GEN)x[1]; if (typ(x)!=t_VEC || lg(x)!=11) break;
199: return x;
200: }
201: case t_MAT:
202: if (lg(x)==2)
203: switch(lg(x[1]))
204: {
205: case 8: case 11:
206: *t = typ_CLA; return NULL;
207: }
208: }
209: *t = typ_NULL; return NULL;
210: }
211:
212: GEN
213: get_nf(GEN x, int *t)
214: {
215: switch(typ(x))
216: {
217: case t_POL : *t = typ_POL; return NULL;
218: case t_QUAD: *t = typ_Q ; return NULL;
219: case t_VEC:
220: switch(lg(x))
221: {
222: case 3:
223: if (typ(x[2]) != t_POLMOD) break;
224: return get_nf((GEN)x[1],t);
225: case 10: *t = typ_NF; return x;
226: case 11: *t = typ_BNF;
227: x = (GEN)x[7]; if (typ(x)!=t_VEC || lg(x)!=10) break;
228: return x;
229: case 7 : *t = typ_BNR;
230: x = (GEN)x[1]; if (typ(x)!=t_VEC || lg(x)!=11) break;
231: x = (GEN)x[7]; if (typ(x)!=t_VEC || lg(x)!=10) break;
232: return x;
233: case 9 :
234: x = (GEN)x[2];
235: if (typ(x) == t_VEC && lg(x) == 4) *t = typ_GAL;
236: return NULL;
237: case 14: case 20:
238: *t = typ_ELL; return NULL;
239: }break;
240: case t_MAT:
241: if (lg(x)==2)
242: switch(lg(x[1]))
243: {
244: case 8: case 11:
245: *t = typ_CLA; return NULL;
246: }
247: }
248: *t = typ_NULL; return NULL;
249: }
250:
251: /*************************************************************************/
252: /** **/
253: /** GALOIS GROUP **/
254: /** **/
255: /*************************************************************************/
256:
257: /* exchange elements i and j in vector x */
258: static GEN
259: transroot(GEN x, int i, int j)
260: {
261: long k;
262: x = dummycopy(x);
263: k=x[i]; x[i]=x[j]; x[j]=k; return x;
264: }
265:
266: #define randshift (BITS_IN_RANDOM - 3)
267:
268: GEN
269: tschirnhaus(GEN x)
270: {
1.2 ! noro 271: gpmem_t av = avma, av2;
! 272: long a, v = varn(x);
1.1 noro 273: GEN u, p1 = cgetg(5,t_POL);
274:
275: if (typ(x)!=t_POL) err(notpoler,"tschirnhaus");
276: if (lgef(x) < 4) err(constpoler,"tschirnhaus");
277: if (v) { u=dummycopy(x); setvarn(u,0); x=u; }
278: p1[1] = evalsigne(1)|evalvarn(0)|evallgef(5);
279: do
280: {
281: a = mymyrand() >> randshift; if (a==0) a =1; p1[4]=lstoi(a);
282: a = mymyrand() >> (randshift-1); if (a>=4) a-=8; p1[3]=lstoi(a);
283: a = mymyrand() >> (randshift-1); if (a>=4) a-=8; p1[2]=lstoi(a);
1.2 ! noro 284: u = caract2(x,p1,v); av2=avma;
1.1 noro 285: }
286: while (lgef(srgcd(u,derivpol(u))) > 3); /* while u not separable */
287: if (DEBUGLEVEL>1)
288: fprintferr("Tschirnhaus transform. New pol: %Z",u);
1.2 ! noro 289: avma=av2; return gerepileupto(av,u);
1.1 noro 290: }
291: #undef randshift
292:
293: int
294: gpolcomp(GEN p1, GEN p2)
295: {
296: int s,j = lgef(p1)-2;
297:
298: if (lgef(p2)-2 != j)
299: err(bugparier,"gpolcomp (different degrees)");
300: for (; j>=2; j--)
301: {
302: s = absi_cmp((GEN)p1[j], (GEN)p2[j]);
303: if (s) return s;
304: }
305: return 0;
306: }
307:
1.2 ! noro 308: /* assume pol in Z[X]. Find C, L in Z such that POL = C pol(x / L) monic in Z[X].
! 309: * Return POL and set *ptlead = L */
1.1 noro 310: GEN
311: primitive_pol_to_monic(GEN pol, GEN *ptlead)
312: {
313: long i,j,n = degpol(pol);
314: GEN lead,fa,e,a, POL = dummycopy(pol);
315:
316: a = POL + 2; lead = (GEN)a[n];
317: if (signe(lead) < 0) { POL = gneg_i(POL); a = POL+2; lead = negi(lead); }
318: if (is_pm1(lead)) { if (ptlead) *ptlead = NULL; return POL; }
319: fa = auxdecomp(lead,0); lead = gun;
320: e = (GEN)fa[2]; fa = (GEN)fa[1];
321: for (i=lg(e)-1; i>0;i--) e[i] = itos((GEN)e[i]);
322: for (i=lg(fa)-1; i>0; i--)
323: {
324: GEN p = (GEN)fa[i], p1,pk,pku;
325: long k = (long)ceil((double)e[i] / n);
326: long d = k * n - e[i], v, j0;
327: /* find d, k such that p^d pol(x / p^k) monic */
328: for (j=n-1; j>0; j--)
329: {
330: if (!signe(a[j])) continue;
331: v = pvaluation((GEN)a[j], p, &p1);
332: while (v + d < k * j) { k++; d += n; }
333: }
334: pk = gpowgs(p,k); j0 = d/k;
335: pku = gpowgs(p,d - k*j0);
336: /* a[j] *= p^(d - kj) */
337: for (j=j0; j>=0; j--)
338: {
339: if (j < j0) pku = mulii(pku, pk);
340: a[j] = lmulii((GEN)a[j], pku);
341: }
342: j0++;
343: pku = gpowgs(p,k*j0 - d);
344: /* a[j] /= p^(kj - d) */
345: for (j=j0; j<=n; j++)
346: {
347: if (j > j0) pku = mulii(pku, pk);
348: a[j] = ldivii((GEN)a[j], pku);
349: }
350: lead = mulii(lead, pk);
351: }
352: if (ptlead) *ptlead = lead; return POL;
353: }
354:
355: /* compute x1*x2^2 + x2*x3^2 + x3*x4^2 + x4*x1^2 */
356: static GEN
357: get_F4(GEN x)
358: {
359: GEN p1=gzero;
360: long i;
361:
362: for (i=1; i<=4; i++)
363: p1 = gadd(p1, gmul((GEN)x[i], gsqr((GEN)x[(i&3)+1])));
364: return p1;
365: }
366:
1.2 ! noro 367: static GEN
! 368: roots_to_ZX(GEN z, long *e)
! 369: {
! 370: GEN a = roots_to_pol(z,0);
! 371: GEN b = grndtoi(greal(a),e);
! 372: long e1 = gexpo(gimag(a));
! 373: if (e1 > *e) *e = e1;
! 374: return b;
! 375: }
! 376:
! 377: static GEN
! 378: _res(long n, long s, long k)
! 379: {
! 380: GEN y = cgetg(4, t_VEC);
! 381: y[1] = lstoi(n);
! 382: y[2] = lstoi(s);
! 383: if (!new_galois_format) k = (n == 6 && (k == 6 || k == 2))? 2: 1;
! 384: y[3] = lstoi(k); return y;
! 385: }
1.1 noro 386:
387: GEN
388: galois(GEN x, long prec)
389: {
1.2 ! noro 390: gpmem_t av = avma, av1;
! 391: long i,j,k,n,f,l,l2,e,e1,pr,ind;
! 392: GEN x1,p1,p2,p3,p4,p5,w,z,ee;
1.1 noro 393: static int ind5[20]={2,5,3,4, 1,3,4,5, 1,5,2,4, 1,2,3,5, 1,4,2,3};
394: static int ind6[60]={3,5,4,6, 2,6,4,5, 2,3,5,6, 2,4,3,6, 2,5,3,4,
395: 1,4,5,6, 1,5,3,6, 1,6,3,4, 1,3,4,5, 1,6,2,5,
396: 1,2,4,6, 1,5,2,4, 1,3,2,6, 1,2,3,5, 1,4,2,3};
397: if (typ(x)!=t_POL) err(notpoler,"galois");
398: n=degpol(x); if (n<=0) err(constpoler,"galois");
399: if (n>11) err(impl,"galois of degree higher than 11");
1.2 ! noro 400: x = primpart(x);
1.1 noro 401: check_pol_int(x, "galois");
402: if (gisirreducible(x) != gun)
403: err(impl,"galois of reducible polynomial");
404:
405: if (n<4)
406: {
1.2 ! noro 407: if (n == 1) { avma = av; return _res(1, 1,1); }
! 408: if (n == 2) { avma = av; return _res(2,-1,1); }
! 409: /* n = 3 */
! 410: f = carreparfait(ZX_disc(x));
! 411: avma = av;
! 412: return f? _res(3,1,1): _res(6,-1,2);
1.1 noro 413: }
414: x1 = x = primitive_pol_to_monic(x,NULL); av1=avma;
1.2 ! noro 415: if (n > 7) return galoisbig(x,prec);
1.1 noro 416: for(;;)
417: {
1.2 ! noro 418: GEN cb = cauchy_bound(x);
1.1 noro 419: switch(n)
420: {
421: case 4: z = cgetg(7,t_VEC);
1.2 ! noro 422: prec = DEFAULTPREC + (long)((gexpo(cb)*18. / BITS_IN_LONG));
1.1 noro 423: for(;;)
424: {
425: p1=roots(x,prec);
426: z[1] = (long)get_F4(p1);
427: z[2] = (long)get_F4(transroot(p1,1,2));
428: z[3] = (long)get_F4(transroot(p1,1,3));
429: z[4] = (long)get_F4(transroot(p1,1,4));
430: z[5] = (long)get_F4(transroot(p1,2,3));
431: z[6] = (long)get_F4(transroot(p1,3,4));
1.2 ! noro 432: p5 = roots_to_ZX(z, &e);
1.1 noro 433: if (e <= -10) break;
434: prec = (prec<<1)-2;
435: }
1.2 ! noro 436: if (!ZX_is_squarefree(p5)) goto tchi;
1.1 noro 437: p2 = (GEN)factor(p5)[1];
438: switch(lg(p2)-1)
439: {
1.2 ! noro 440: case 1: f = carreparfait(ZX_disc(x)); avma = av;
! 441: return f? _res(12,1,4): _res(24,-1,5);
1.1 noro 442:
1.2 ! noro 443: case 2: avma = av; return _res(8,-1,3);
1.1 noro 444:
1.2 ! noro 445: case 3: avma = av;
! 446: return (degpol(p2[1])==2)? _res(4,1,2): _res(4,-1,1);
1.1 noro 447:
448: default: err(bugparier,"galois (bug1)");
449: }
450:
451: case 5: z = cgetg(7,t_VEC);
1.2 ! noro 452: ee= cgetg(7,t_VECSMALL);
! 453: w = cgetg(7,t_VECSMALL);
! 454: prec = DEFAULTPREC + (long)((gexpo(cb)*21. / BITS_IN_LONG));
1.1 noro 455: for(;;)
456: {
457: for(;;)
458: {
459: p1=roots(x,prec);
460: for (l=1; l<=6; l++)
461: {
462: p2=(l==1)?p1: ((l<6)?transroot(p1,1,l): transroot(p1,2,5));
463: p3=gzero;
464: for (k=0,i=1; i<=5; i++,k+=4)
465: {
466: p5 = gadd(gmul((GEN)p2[ind5[k]],(GEN)p2[ind5[k+1]]),
467: gmul((GEN)p2[ind5[k+2]],(GEN)p2[ind5[k+3]]));
468: p3 = gadd(p3, gmul(gsqr((GEN)p2[i]),p5));
469: }
470: w[l]=lrndtoi(greal(p3),&e);
471: e1 = gexpo(gimag(p3)); if (e1>e) e=e1;
472: ee[l]=e; z[l] = (long)p3;
473: }
1.2 ! noro 474: p5 = roots_to_ZX(z, &e);
1.1 noro 475: if (e <= -10) break;
476: prec = (prec<<1)-2;
477: }
1.2 ! noro 478: if (!ZX_is_squarefree(p5)) goto tchi;
1.1 noro 479: p3=(GEN)factor(p5)[1];
1.2 ! noro 480: f=carreparfait(ZX_disc(x));
1.1 noro 481: if (lg(p3)-1==1)
482: {
1.2 ! noro 483: avma = av;
! 484: return f? _res(60,1,4): _res(120,-1,5);
1.1 noro 485: }
1.2 ! noro 486: if (!f) { avma = av; return _res(20,-1,3); }
! 487:
1.1 noro 488: pr = - (bit_accuracy(prec) >> 1);
489: for (l=1; l<=6; l++)
490: if (ee[l] <= pr && gcmp0(poleval(p5,(GEN)w[l]))) break;
491: if (l>6) err(bugparier,"galois (bug4)");
492: p2=(l==6)? transroot(p1,2,5):transroot(p1,1,l);
493: p3=gzero;
494: for (i=1; i<=5; i++)
495: {
1.2 ! noro 496: j = i+1; if (j>5) j -= 5;
! 497: p3 = gadd(p3,gmul(gmul((GEN)p2[i],(GEN)p2[j]),
! 498: gsub((GEN)p2[j],(GEN)p2[i])));
1.1 noro 499: }
500: p5=gsqr(p3); p4=grndtoi(greal(p5),&e);
501: e1 = gexpo(gimag(p5)); if (e1>e) e=e1;
502: if (e <= -10)
503: {
504: if (gcmp0(p4)) goto tchi;
1.2 ! noro 505: f = carreparfait(p4); avma = av;
! 506: return f? _res(5,1,1): _res(10,1,2);
1.1 noro 507: }
508: prec=(prec<<1)-2;
509: }
510:
511: case 6: z = cgetg(7, t_VEC);
1.2 ! noro 512: prec = DEFAULTPREC + (long)((gexpo(cb)*42. / BITS_IN_LONG));
1.1 noro 513: for(;;)
514: {
515: for(;;)
516: {
517: p1=roots(x,prec);
518: for (l=1; l<=6; l++)
519: {
520: p2=(l==1)?p1:transroot(p1,1,l);
521: p3=gzero; k=0;
522: for (i=1; i<=5; i++) for (j=i+1; j<=6; j++)
523: {
524: p5=gadd(gmul((GEN)p2[ind6[k]],(GEN)p2[ind6[k+1]]),
525: gmul((GEN)p2[ind6[k+2]],(GEN)p2[ind6[k+3]]));
1.2 ! noro 526: p3=gadd(p3,gmul(gsqr(gmul((GEN)p2[i],(GEN)p2[j])),p5));
! 527: k += 4;
1.1 noro 528: }
529: z[l] = (long)p3;
530: }
1.2 ! noro 531: p5 = roots_to_ZX(z, &e);
1.1 noro 532: if (e <= -10) break;
533: prec=(prec<<1)-2;
534: }
1.2 ! noro 535: if (!ZX_is_squarefree(p5)) goto tchi;
1.1 noro 536: p2=(GEN)factor(p5)[1];
537: switch(lg(p2)-1)
538: {
539: case 1:
540: z = cgetg(11,t_VEC); ind=0;
541: p3=gadd(gmul(gmul((GEN)p1[1],(GEN)p1[2]),(GEN)p1[3]),
542: gmul(gmul((GEN)p1[4],(GEN)p1[5]),(GEN)p1[6]));
543: z[++ind] = (long)p3;
544: for (i=1; i<=3; i++)
545: for (j=4; j<=6; j++)
546: {
547: p2=transroot(p1,i,j);
548: p3=gadd(gmul(gmul((GEN)p2[1],(GEN)p2[2]),(GEN)p2[3]),
549: gmul(gmul((GEN)p2[4],(GEN)p2[5]),(GEN)p2[6]));
550: z[++ind] = (long)p3;
551: }
1.2 ! noro 552: p5 = roots_to_ZX(z, &e);
1.1 noro 553: if (e <= -10)
554: {
1.2 ! noro 555: if (!ZX_is_squarefree(p5)) goto tchi;
! 556: p2 = (GEN)factor(p5)[1];
! 557: f = carreparfait(ZX_disc(x));
! 558: avma = av;
1.1 noro 559: if (lg(p2)-1==1)
1.2 ! noro 560: return f? _res(360,1,15): _res(720,-1,16);
1.1 noro 561: else
1.2 ! noro 562: return f? _res(36,1,10): _res(72,-1,13);
1.1 noro 563: }
564: prec=(prec<<1)-2; break;
565:
566: case 2: l2=degpol(p2[1]); if (l2>3) l2=6-l2;
567: switch(l2)
568: {
1.2 ! noro 569: case 1: f = carreparfait(ZX_disc(x));
! 570: avma = av;
! 571: return f? _res(60,1,12): _res(120,-1,14);
! 572: case 2: f = carreparfait(ZX_disc(x));
! 573: if (f) { avma = av; return _res(24,1,7); }
! 574: p3 = (degpol(p2[1])==2)? (GEN)p2[2]: (GEN)p2[1];
! 575: f = carreparfait(ZX_disc(p3));
! 576: avma = av;
! 577: return f? _res(24,-1,6): _res(48,-1,11);
! 578: case 3: f = carreparfait(ZX_disc((GEN)p2[1]))
! 579: || carreparfait(ZX_disc((GEN)p2[2]));
! 580: avma = av;
! 581: return f? _res(18,-1,5): _res(36,-1,9);
1.1 noro 582: }
583: case 3:
584: for (l2=1; l2<=3; l2++)
1.2 ! noro 585: if (degpol(p2[l2]) >= 3) p3 = (GEN)p2[l2];
! 586: if (degpol(p3) == 3)
1.1 noro 587: {
1.2 ! noro 588: f = carreparfait(ZX_disc(p3)); avma = av;
! 589: return f? _res(6,-1,1): _res(12,-1,3);
1.1 noro 590: }
591: else
592: {
1.2 ! noro 593: f = carreparfait(ZX_disc(x)); avma = av;
! 594: return f? _res(12,1,4): _res(24,-1,8);
1.1 noro 595: }
1.2 ! noro 596: case 4: avma = av; return _res(6,-1,2);
1.1 noro 597: default: err(bugparier,"galois (bug3)");
598: }
599: }
600:
601: case 7: z = cgetg(36,t_VEC);
1.2 ! noro 602: prec = DEFAULTPREC + (long)((gexpo(cb)*7. / BITS_IN_LONG));
1.1 noro 603: for(;;)
604: {
1.2 ! noro 605: ind = 0; p1=roots(x,prec);
1.1 noro 606: for (i=1; i<=5; i++)
607: for (j=i+1; j<=6; j++)
608: {
1.2 ! noro 609: GEN t = gadd((GEN)p1[i],(GEN)p1[j]);
! 610: for (k=j+1; k<=7; k++) z[++ind] = ladd(t, (GEN)p1[k]);
1.1 noro 611: }
1.2 ! noro 612: p5 = roots_to_ZX(z, &e);
1.1 noro 613: if (e <= -10) break;
614: prec = (prec<<1)-2;
615: }
1.2 ! noro 616: if (!ZX_is_squarefree(p5)) goto tchi;
1.1 noro 617: p2=(GEN)factor(p5)[1];
618: switch(lg(p2)-1)
619: {
1.2 ! noro 620: case 1: f = carreparfait(ZX_disc(x)); avma = av;
! 621: return f? _res(2520,1,6): _res(5040,-1,7);
! 622: case 2: f = degpol(p2[1]); avma = av;
! 623: return (f==7 || f==28)? _res(168,1,5): _res(42,-1,4);
! 624: case 3: avma = av; return _res(21,1,3);
! 625: case 4: avma = av; return _res(14,-1,2);
! 626: case 5: avma = av; return _res(7,1,1);
1.1 noro 627: default: err(talker,"galois (bug2)");
628: }
629: }
1.2 ! noro 630: tchi: avma = av1; x = tschirnhaus(x1);
1.1 noro 631: }
632: }
633:
634: GEN
635: galoisapply(GEN nf, GEN aut, GEN x)
636: {
1.2 ! noro 637: gpmem_t av=avma,tetpil;
! 638: long lx,j,N;
1.1 noro 639: GEN p,p1,y,pol;
640:
641: nf=checknf(nf); pol=(GEN)nf[1];
642: if (typ(aut)==t_POL) aut = gmodulcp(aut,pol);
643: else
644: {
645: if (typ(aut)!=t_POLMOD || !gegal((GEN)aut[1],pol))
646: err(talker,"incorrect galois automorphism in galoisapply");
647: }
648: switch(typ(x))
649: {
650: case t_INT: case t_INTMOD: case t_FRAC: case t_FRACN: case t_PADIC:
651: avma=av; return gcopy(x);
652:
653: case t_POLMOD: x = (GEN) x[2]; /* fall through */
654: case t_POL:
655: p1 = gsubst(x,varn(pol),aut);
656: if (typ(p1)!=t_POLMOD || !gegal((GEN)p1[1],pol)) p1 = gmodulcp(p1,pol);
657: return gerepileupto(av,p1);
658:
659: case t_VEC:
660: if (lg(x)==3)
661: {
662: y=cgetg(3,t_VEC);
663: y[1]=(long)galoisapply(nf,aut,(GEN)x[1]);
664: y[2]=lcopy((GEN)x[2]); return gerepileupto(av, y);
665: }
666: if (lg(x)!=6) err(typeer,"galoisapply");
667: y=cgetg(6,t_VEC); y[1]=x[1]; y[3]=x[3]; y[4]=x[4];
668: p = (GEN)x[1];
669: p1=centermod(galoisapply(nf,aut,(GEN)x[2]), p);
670: if (is_pm1(x[3]))
671: if (ggval(subres(gmul((GEN)nf[7],p1),pol), p) > itos((GEN)x[4]))
672: p1[1] = (signe(p1[1]) > 0)? lsub((GEN)p1[1], p)
673: : ladd((GEN)p1[1], p);
674: y[2]=(long)p1;
675: y[5]=(long)centermod(galoisapply(nf,aut,(GEN)x[5]), p);
676: return gerepilecopy(av,y);
677:
678: case t_COL:
679: N=degpol(pol);
680: if (lg(x)!=N+1) err(typeer,"galoisapply");
681: p1=galoisapply(nf,aut,gmul((GEN)nf[7],x)); tetpil=avma;
682: return gerepile(av,tetpil,algtobasis(nf,p1));
683:
684: case t_MAT:
685: lx=lg(x); if (lx==1) return cgetg(1,t_MAT);
686: N=degpol(pol);
687: if (lg(x[1])!=N+1) err(typeer,"galoisapply");
688: p1=cgetg(lx,t_MAT);
689: for (j=1; j<lx; j++) p1[j]=(long)galoisapply(nf,aut,(GEN)x[j]);
690: if (lx==N+1) p1 = idealhermite(nf,p1);
691: return gerepileupto(av,p1);
692: }
693: err(typeer,"galoisapply");
694: return NULL; /* not reached */
695: }
696:
697: GEN pol_to_monic(GEN pol, GEN *lead);
698: int cmp_pol(GEN x, GEN y);
699:
700: GEN
1.2 ! noro 701: get_bnfpol(GEN x, GEN *bnf, GEN *nf)
! 702: {
! 703: *bnf = _checkbnf(x);
! 704: *nf = _checknf(x);
! 705: if (*nf) return (GEN)(*nf)[1];
! 706: if (typ(x) != t_POL) err(idealer1);
! 707: return x;
! 708: }
! 709:
! 710: GEN
1.1 noro 711: get_nfpol(GEN x, GEN *nf)
712: {
713: if (typ(x) == t_POL) { *nf = NULL; return x; }
714: *nf = checknf(x); return (GEN)(*nf)[1];
715: }
716:
717: /* if fliso test for isomorphism, for inclusion otherwise. */
718: static GEN
719: nfiso0(GEN a, GEN b, long fliso)
720: {
1.2 ! noro 721: gpmem_t av = avma;
1.1 noro 722: long n,m,i,vb,lx;
723: GEN nfa,nfb,p1,y,la,lb;
724:
725: a = get_nfpol(a, &nfa);
726: b = get_nfpol(b, &nfb);
727: if (fliso && nfa && !nfb) { p1=a; a=b; b=p1; p1=nfa; nfa=nfb; nfb=p1; }
728: m=degpol(a);
729: n=degpol(b); if (m<=0 || n<=0) err(constpoler,"nfiso or nfincl");
730: if (fliso)
731: { if (n!=m) return gzero; }
732: else
733: { if (n%m) return gzero; }
734:
735: if (nfb) lb = NULL; else b = pol_to_monic(b,&lb);
736: if (nfa) la = NULL; else a = pol_to_monic(a,&la);
737: if (nfa && nfb)
738: {
739: if (fliso)
740: {
741: if (!gegal((GEN)nfa[2],(GEN)nfb[2])
742: || !gegal((GEN)nfa[3],(GEN)nfb[3])) return gzero;
743: }
744: else
745: if (!divise((GEN)nfb[3], gpowgs((GEN)nfa[3],n/m))) return gzero;
746: }
747: else
748: {
1.2 ! noro 749: GEN da = nfa? (GEN)nfa[3]: ZX_disc(a);
! 750: GEN db = nfb? (GEN)nfb[3]: ZX_disc(b);
1.1 noro 751: if (fliso)
752: {
753: p1=gdiv(da,db);
754: if (typ(p1)==t_FRAC) p1=mulii((GEN)p1[1],(GEN)p1[2]);
755: if (!gcarreparfait(p1)) { avma=av; return gzero; }
756: }
757: else
758: {
759: long q=n/m;
760: GEN fa=factor(da), ex=(GEN)fa[2];
761: fa=(GEN)fa[1]; lx=lg(fa);
762: for (i=1; i<lx; i++)
763: if (mod2((GEN)ex[i]) && !divise(db,gpowgs((GEN)fa[i],q)))
764: { avma=av; return gzero; }
765: }
766: }
767: a = dummycopy(a); setvarn(a,0);
768: b = dummycopy(b); vb=varn(b);
769: if (nfb)
770: {
771: if (vb == 0) nfb = gsubst(nfb, 0, polx[MAXVARN]);
772: y = lift_intern(nfroots(nfb,a));
773: }
774: else
775: {
776: if (vb == 0) setvarn(b, fetch_var());
777: y = (GEN)polfnf(a,b)[1]; lx = lg(y);
778: for (i=1; i<lx; i++)
779: {
780: if (lgef(y[i]) != 4) { setlg(y,i); break; }
781: y[i] = (long)gneg_i(lift_intern(gmael(y,i,2)));
782: }
783: y = gen_sort(y, 0, cmp_pol);
784: settyp(y, t_VEC);
1.2 ! noro 785: if (vb == 0) (void)delete_var();
1.1 noro 786: }
787: lx = lg(y); if (lx==1) { avma=av; return gzero; }
788: for (i=1; i<lx; i++)
789: {
790: p1 = (GEN)y[i];
791: if (typ(p1) == t_POL) setvarn(p1, vb); else p1 = scalarpol(p1, vb);
792: if (lb) p1 = poleval(p1, gmul(polx[vb],lb));
793: y[i] = la? ldiv(p1,la): (long)p1;
794: }
795: return gerepilecopy(av,y);
796: }
797:
798: GEN
1.2 ! noro 799: nfisisom(GEN a, GEN b) { return nfiso0(a,b,1); }
1.1 noro 800:
801: GEN
1.2 ! noro 802: nfisincl(GEN a, GEN b) { return nfiso0(a,b,0); }
1.1 noro 803:
804: /*************************************************************************/
805: /** **/
806: /** INITALG **/
807: /** **/
808: /*************************************************************************/
1.2 ! noro 809:
! 810: GEN
! 811: get_roots(GEN x,long r1,long prec)
! 812: {
! 813: GEN roo = (typ(x)==t_VEC)? dummycopy(x): roots(x,prec);
! 814: long i, ru = (lg(roo)-1 + r1) >> 1;
! 815:
! 816: for (i=1; i<=r1; i++) roo[i]=lreal((GEN)roo[i]);
! 817: for ( ; i<=ru; i++) roo[i]=roo[(i<<1)-r1];
! 818: roo[0]=evaltyp(t_VEC)|evallg(ru+1); return roo;
! 819: }
1.1 noro 820:
821: /* For internal use. compute trace(x mod pol), sym=polsym(pol,deg(pol)-1) */
822: GEN
823: quicktrace(GEN x, GEN sym)
824: {
825: GEN p1 = gzero;
826: long i;
827:
828: if (signe(x))
829: {
830: sym--;
831: for (i=lgef(x)-1; i>1; i--)
832: p1 = gadd(p1, gmul((GEN)x[i],(GEN)sym[i]));
833: }
834: return p1;
835: }
836:
837: /* T = trace(w[i]), x = sum x[i] w[i], x[i] integer */
838: static GEN
839: trace_col(GEN x, GEN T)
840: {
1.2 ! noro 841: gpmem_t av = avma;
1.1 noro 842: GEN t = gzero;
843: long i, l = lg(x);
844:
845: t = mulii((GEN)x[1],(GEN)T[1]);
846: for (i=2; i<l; i++)
847: if (signe(x[i])) t = addii(t, mulii((GEN)x[i],(GEN)T[i]));
848: return gerepileuptoint(av, t);
849: }
850:
851: /* pol belonging to Z[x], return a monic polynomial generating the same field
852: * as pol (x-> ax+b)) set lead = NULL if pol was monic (after dividing
853: * by the content), and to to leading coeff otherwise.
854: * No garbage collecting done.
855: */
856: GEN
857: pol_to_monic(GEN pol, GEN *lead)
858: {
859: long n = lgef(pol)-1;
860:
861: if (n==1 || gcmp1((GEN)pol[n])) { *lead = NULL; return pol; }
1.2 ! noro 862: return primitive_pol_to_monic(primpart(pol), lead);
1.1 noro 863: }
864:
1.2 ! noro 865: /* Let T = (Tr(wi wj)), then T^(-1) Z^n = codifferent = coD/dcoD
! 866: * NB: det(T) = dK, TI = dK T^(-1) integral */
! 867: static GEN
! 868: make_MDI(GEN nf, GEN TI, GEN *coD, GEN *dcoD)
1.1 noro 869: {
1.2 ! noro 870: GEN c, MDI, dK = (GEN)nf[3];
1.1 noro 871:
1.2 ! noro 872: TI = Q_primitive_part(TI, &c);
! 873: *dcoD = c? diviiexact(dK, c): dK;
! 874: *coD = hnfmodid(TI, *dcoD);
! 875: MDI = ideal_two_elt(nf, *coD);
! 876: return c? gmul(c, MDI): MDI;
1.1 noro 877: }
878:
879: /* assume lg(nf) > 3 && typ(nf) = container [hopefully a genuine nf] */
880: long
881: nf_get_r1(GEN nf)
882: {
883: GEN x = (GEN)nf[2];
884: if (typ(x) != t_VEC || lg(x) != 3 || typ(x[1]) != t_INT)
885: err(talker,"false nf in nf_get_r1");
886: return itos((GEN)x[1]);
887: }
888: long
889: nf_get_r2(GEN nf)
890: {
891: GEN x = (GEN)nf[2];
892: if (typ(x) != t_VEC || lg(x) != 3 || typ(x[2]) != t_INT)
893: err(talker,"false nf in nf_get_r2");
894: return itos((GEN)x[2]);
895: }
1.2 ! noro 896: void
! 897: nf_get_sign(GEN nf, long *r1, long *r2)
! 898: {
! 899: GEN x = (GEN)nf[2];
! 900: if (typ(x) != t_VEC || lg(x) != 3
! 901: || typ(x[1]) != t_INT || typ(x[2]) != t_INT)
! 902: err(talker,"false nf in nf_get_sign");
! 903: *r1 = itos((GEN)x[1]);
! 904: *r2 = (degpol(nf[1]) - *r1) >> 1;
! 905: }
1.1 noro 906:
907: static GEN
1.2 ! noro 908: get_Tr(GEN mul, GEN x, GEN basden)
1.1 noro 909: {
1.2 ! noro 910: GEN tr,T,T1,sym, bas = (GEN)basden[1], den = (GEN)basden[2];
1.1 noro 911: long i,j,n = lg(bas)-1;
912: T = cgetg(n+1,t_MAT);
913: T1 = cgetg(n+1,t_COL);
914: sym = polsym(x, n-1);
915:
916: T1[1]=lstoi(n);
917: for (i=2; i<=n; i++)
918: {
919: tr = quicktrace((GEN)bas[i], sym);
920: if (den && den[i]) tr = diviiexact(tr,(GEN)den[i]);
921: T1[i] = (long)tr; /* tr(w[i]) */
922: }
923: T[1] = (long)T1;
924: for (i=2; i<=n; i++)
925: {
926: T[i] = lgetg(n+1,t_COL); coeff(T,1,i) = T1[i];
927: for (j=2; j<=i; j++)
928: coeff(T,i,j) = coeff(T,j,i) = (long)trace_col((GEN)mul[j+(i-1)*n], T1);
929: }
930: return T;
931: }
932:
933: /* return [bas[i]*denom(bas[i]), denom(bas[i])], denom 1 is given as NULL */
934: GEN
935: get_bas_den(GEN bas)
936: {
1.2 ! noro 937: GEN z,b,d,den, dbas = dummycopy(bas);
! 938: long i, l = lg(bas);
! 939: int power = 1;
1.1 noro 940: den = cgetg(l,t_VEC);
941: for (i=1; i<l; i++)
942: {
1.2 ! noro 943: b = Q_remove_denom((GEN)bas[i], &d);
! 944: dbas[i]= (long)b;
! 945: den[i] = (long)d; if (d) power = 0;
1.1 noro 946: }
1.2 ! noro 947: if (power) den = NULL; /* power basis */
1.1 noro 948: z = cgetg(3,t_VEC);
949: z[1] = (long)dbas;
950: z[2] = (long)den; return z;
951: }
952:
953: /* allow x or y = NULL (act as 1) */
954: static GEN
955: _mulii(GEN x, GEN y)
956: {
957: if (!x) return y;
958: if (!y) return x;
959: return mulii(x,y);
960: }
961:
962: GEN
1.2 ! noro 963: get_mul_table(GEN x,GEN basden,GEN invbas)
1.1 noro 964: {
965: long i,j, n = degpol(x);
966: GEN z,d, mul = cgetg(n*n+1,t_MAT), bas=(GEN)basden[1], den=(GEN)basden[2];
1.2 ! noro 967:
1.1 noro 968: for (j=1; j<=n*n; j++) mul[j]=lgetg(n+1,t_COL);
969: for (i=1; i<=n; i++)
970: for (j=i; j<=n; j++)
971: {
1.2 ! noro 972: gpmem_t av = avma;
1.1 noro 973: z = gres(gmul((GEN)bas[j],(GEN)bas[i]), x);
974: z = mulmat_pol(invbas, z); /* integral column */
975: if (den)
976: {
977: d = _mulii((GEN)den[i], (GEN)den[j]);
978: if (d) z = gdivexact(z, d);
979: }
980: mul[j+(i-1)*n] = mul[i+(j-1)*n] = lpileupto(av,z);
981: }
982: return mul;
983: }
984:
1.2 ! noro 985: /* as get_Tr, mul_table not precomputed */
! 986: static GEN
! 987: make_Tr(GEN x, GEN w)
! 988: {
! 989: long i,j, n = degpol(x);
! 990: GEN p1,p2,t,d;
! 991: GEN sym = cgetg(n+2,t_VEC);
! 992: GEN den = cgetg(n+1,t_VEC);
! 993: GEN T = cgetg(n+1,t_MAT);
! 994: gpmem_t av;
! 995:
! 996: sym = polsym(x, n-1);
! 997: p1 = get_bas_den(w);
! 998: w = (GEN)p1[1];
! 999: den = (GEN)p1[2];
! 1000: for (i=1; i<=n; i++)
! 1001: {
! 1002: p1 = cgetg(n+1,t_COL); T[i] = (long)p1;
! 1003: for (j=1; j<i ; j++) p1[j] = coeff(T,i,j);
! 1004: for ( ; j<=n; j++)
! 1005: {
! 1006: av = avma;
! 1007: p2 = gres(gmul((GEN)w[i],(GEN)w[j]), x);
! 1008: t = quicktrace(p2, sym);
! 1009: if (den)
! 1010: {
! 1011: d = _mulii((GEN)den[i],(GEN)den[j]);
! 1012: if (d) t = diviiexact(t, d);
! 1013: }
! 1014: p1[j] = lpileuptoint(av, t);
! 1015: }
! 1016: }
! 1017: return T;
! 1018: }
! 1019:
! 1020: /* compute roots so that _absolute_ accuracy of M >= prec [also holds for G] */
! 1021: static void
! 1022: get_roots_for_M(nffp_t *F)
! 1023: {
! 1024: long n, eBD, er, PREC;
! 1025:
! 1026: if (F->extraprec < 0)
! 1027: { /* not initialized yet */
! 1028: n = degpol(F->x);
! 1029: eBD = 1 + gexpo((GEN)F->basden[1]);
! 1030: er = 1 + gexpo(F->ro? F->ro: cauchy_bound(F->x));
! 1031: if (er < 0) er = 0;
! 1032: F->extraprec = ((n*er + eBD + (long)log2(n)) >> TWOPOTBITS_IN_LONG);
! 1033: }
! 1034:
! 1035: PREC = F->prec + F->extraprec;
! 1036: if (F->ro && gprecision((GEN)F->ro[1]) >= PREC) return;
! 1037: F->ro = get_roots(F->x, F->r1, PREC);
! 1038: }
! 1039:
! 1040: /* [bas[i]/den[i]]= integer basis. roo = real part of the roots */
! 1041: static void
! 1042: make_M(nffp_t *F, int trunc)
! 1043: {
! 1044: GEN bas = (GEN)F->basden[1], den = (GEN)F->basden[2], ro = F->ro;
! 1045: GEN m, d, M;
! 1046: long i, j, l = lg(ro), n = lg(bas);
! 1047: M = cgetg(n,t_MAT);
! 1048: m = cgetg(l, t_COL); M[1] = (long)m;
! 1049: for (i=1; i<l; i++) m[i] = un; /* bas[1] = 1 */
! 1050: for (j=2; j<n; j++)
! 1051: {
! 1052: m = cgetg(l,t_COL); M[j] = (long)m;
! 1053: for (i=1; i<l; i++) m[i] = (long)poleval((GEN)bas[j], (GEN)ro[i]);
! 1054: }
! 1055: if (den)
! 1056: {
! 1057: GEN invd, rd = cgetr(F->prec + F->extraprec);
! 1058: for (j=2; j<n; j++)
! 1059: {
! 1060: d = (GEN)den[j]; if (!d) continue;
! 1061: m = (GEN)M[j]; affir(d,rd); invd = ginv(rd);
! 1062: for (i=1; i<l; i++) m[i] = lmul((GEN)m[i], invd);
! 1063: }
! 1064: }
! 1065:
! 1066: if (trunc && gprecision(M) > F->prec)
! 1067: {
! 1068: M = gprec_w(M, F->prec);
! 1069: F->ro = gprec_w(ro,F->prec);
! 1070: }
! 1071: if (DEBUGLEVEL>4) msgtimer("matrix M");
! 1072: F->M = M;
! 1073: }
! 1074:
! 1075: /* return G real such that G~ * G = T_2 */
! 1076: static void
! 1077: make_G(nffp_t *F)
! 1078: {
! 1079: GEN G, m, g, r, M = F->M, sqrt2 = gsqrt(gdeux, F->prec + F->extraprec);
! 1080: long i, j, k, r1 = F->r1, l = lg(M);
! 1081:
! 1082: G = cgetg(l, t_MAT);
! 1083: for (j=1; j<l; j++)
! 1084: {
! 1085: g = cgetg(l, t_COL);
! 1086: G[j] = (long)g; m = (GEN)M[j];
! 1087: for (k=i=1; i<=r1; i++) g[k++] = m[i];
! 1088: for ( ; k < l; i++)
! 1089: {
! 1090: r = (GEN)m[i];
! 1091: if (typ(r) == t_COMPLEX)
! 1092: {
! 1093: g[k++] = lmpmul(sqrt2, (GEN)r[1]);
! 1094: g[k++] = lmpmul(sqrt2, (GEN)r[2]);
! 1095: }
! 1096: else
! 1097: {
! 1098: g[k++] = lmpmul(sqrt2, r);
! 1099: g[k++] = zero;
! 1100: }
! 1101: }
! 1102: }
! 1103: F->G = G;
! 1104: }
! 1105:
! 1106: static void
! 1107: make_M_G(nffp_t *F, int trunc)
! 1108: {
! 1109: get_roots_for_M(F);
! 1110: make_M(F, trunc);
! 1111: make_G(F);
! 1112: }
! 1113:
1.1 noro 1114: void
1.2 ! noro 1115: remake_GM(GEN nf, nffp_t *F, long prec)
! 1116: {
! 1117: F->x = (GEN)nf[1];
! 1118: F->ro = NULL;
! 1119: F->r1 = nf_get_r1(nf);
! 1120: F->basden = get_bas_den((GEN)nf[7]);
! 1121: F->extraprec = -1;
! 1122: F->prec = prec; make_M_G(F, 1);
! 1123: }
! 1124:
! 1125: static void
! 1126: nffp_init(nffp_t *F, nfbasic_t *T, GEN ro, long prec)
! 1127: {
! 1128: F->x = T->x;
! 1129: F->ro = ro;
! 1130: F->r1 = T->r1;
! 1131: if (!T->basden) T->basden = get_bas_den(T->bas);
! 1132: F->basden = T->basden;
! 1133: F->extraprec = -1;
! 1134: F->prec = prec;
! 1135: }
! 1136:
! 1137: static void
! 1138: get_nf_fp_compo(nfbasic_t *T, nffp_t *F, GEN ro, long prec)
! 1139: {
! 1140: nffp_init(F,T,ro,prec);
! 1141: make_M_G(F, 1);
! 1142: }
! 1143:
! 1144: static GEN
! 1145: get_sign(long r1, long n)
! 1146: {
! 1147: GEN s = cgetg(3, t_VEC);
! 1148: s[1] = lstoi(r1);
! 1149: s[2] = lstoi((n - r1) >> 1); return s;
! 1150: }
! 1151:
! 1152: GEN
! 1153: nfbasic_to_nf(nfbasic_t *T, GEN ro, long prec)
1.1 noro 1154: {
1.2 ! noro 1155: GEN nf = cgetg(10,t_VEC);
! 1156: GEN x = T->x;
! 1157: GEN invbas,Tr,D,TI,A,dA, mat = cgetg(8,t_VEC);
! 1158: nffp_t F;
! 1159: get_nf_fp_compo(T, &F, ro, prec);
! 1160:
! 1161: nf[1] = (long)T->x;
! 1162: nf[2] = (long)get_sign(T->r1, degpol(T->x));
! 1163: nf[3] = (long)T->dK;
! 1164: nf[4] = (long)T->index;
! 1165: nf[6] = (long)F.ro;
! 1166: nf[5] = (long)mat;
! 1167: nf[7] = (long)T->bas;
1.1 noro 1168:
1.2 ! noro 1169: mat[1] = (long)F.M;
! 1170: mat[2] = (long)F.G;
! 1171:
! 1172: invbas = QM_inv(vecpol_to_mat(T->bas, lg(T->bas)-1), gun);
! 1173: nf[8] = (long)invbas;
! 1174: nf[9] = (long)get_mul_table(x, F.basden, invbas);
1.1 noro 1175: if (DEBUGLEVEL) msgtimer("mult. table");
1.2 ! noro 1176:
! 1177: Tr = get_Tr((GEN)nf[9], x, F.basden);
! 1178: TI = ZM_inv(Tr, T->dK); /* dK T^-1 */
! 1179: mat[6] = (long)TI;
! 1180: mat[7] = (long)make_MDI(nf,TI, &A, &dA); /* needed in idealinv below */
! 1181: if (is_pm1(T->index))
1.1 noro 1182: D = idealhermite_aux(nf, derivpol(x));
1183: else
1184: D = gmul(dA, idealinv(nf, A));
1.2 ! noro 1185: mat[3] = zero; /* FIXME: was gram matrix of current mat[2]. Useless */
! 1186: mat[4] = (long)Tr;
! 1187: mat[5] = (long)D;
1.1 noro 1188: if (DEBUGLEVEL) msgtimer("matrices");
1.2 ! noro 1189: return nf;
! 1190: }
! 1191:
! 1192: static GEN
! 1193: hnffromLLL(GEN nf)
! 1194: {
! 1195: GEN d, x;
! 1196: x = vecpol_to_mat((GEN)nf[7], degpol(nf[1]));
! 1197: x = Q_remove_denom(x, &d);
! 1198: if (!d) return x; /* power basis */
! 1199: return gauss(hnfmodid(x, d), x);
! 1200: }
! 1201:
! 1202: static GEN
! 1203: nfbasechange(GEN u, GEN x)
! 1204: {
! 1205: long i,lx;
! 1206: GEN y;
! 1207: switch(typ(x))
! 1208: {
! 1209: case t_COL: /* nfelt */
! 1210: return gmul(u, x);
! 1211:
! 1212: case t_MAT: /* ideal */
! 1213: y = dummycopy(x);
! 1214: lx = lg(x);
! 1215: for (i=1; i<lx; i++) y[i] = lmul(u, (GEN)y[i]);
! 1216: break;
! 1217:
! 1218: case t_VEC: /* pr */
! 1219: checkprimeid(x);
! 1220: y = dummycopy(x);
! 1221: y[2] = lmul(u, (GEN)y[2]);
! 1222: y[5] = lmul(u, (GEN)y[5]);
! 1223: break;
! 1224: default: y = x;
! 1225: }
! 1226: return y;
1.1 noro 1227: }
1228:
1.2 ! noro 1229: GEN
! 1230: nffromhnfbasis(GEN nf, GEN x)
! 1231: {
! 1232: long tx = typ(x);
! 1233: gpmem_t av = avma;
! 1234: GEN u;
! 1235: if (!is_vec_t(tx)) return gcopy(x);
! 1236: nf = checknf(nf);
! 1237: u = hnffromLLL(nf);
! 1238: return gerepilecopy(av, nfbasechange(u, x));
! 1239: }
1.1 noro 1240:
1241: GEN
1.2 ! noro 1242: nftohnfbasis(GEN nf, GEN x)
! 1243: {
! 1244: long tx = typ(x);
! 1245: gpmem_t av = avma;
! 1246: GEN u;
! 1247: if (!is_vec_t(tx)) return gcopy(x);
! 1248: nf = checknf(nf);
! 1249: u = ZM_inv(hnffromLLL(nf), gun);
! 1250: return gerepilecopy(av, nfbasechange(u, x));
! 1251: }
! 1252:
! 1253: static GEN
! 1254: get_red_G(nfbasic_t *T, GEN *pro)
! 1255: {
! 1256: GEN G, u, u0 = NULL;
! 1257: gpmem_t av;
! 1258: long i, prec, extraprec, n = degpol(T->x);
! 1259: nffp_t F;
! 1260:
! 1261: extraprec = (long) (0.5 * n * sizeof(long) / 8.);
! 1262: prec = DEFAULTPREC + extraprec;
! 1263: nffp_init(&F, T, *pro, prec);
! 1264: av = avma;
! 1265: for (i=1; ; i++)
! 1266: {
! 1267: F.prec = prec; make_M_G(&F, 0); G = F.G;
! 1268: if (u0) G = gmul(G, u0);
! 1269: if (DEBUGLEVEL)
! 1270: fprintferr("get_red_G: starting LLL, prec = %ld (%ld + %ld)\n",
! 1271: prec + F.extraprec, prec, F.extraprec);
! 1272: if ((u = lllfp_marked(1, G, 100, 2, prec, 0)))
! 1273: {
! 1274: if (typ(u) == t_MAT) break;
! 1275: u = (GEN)u[1];
! 1276: if (u0) u0 = gerepileupto(av, gmul(u0,u));
! 1277: else u0 = gerepilecopy(av, u);
! 1278: }
! 1279: if (i == MAXITERPOL) err(accurer,"red_T2");
! 1280: prec = (prec<<1)-2 + (gexpo(u0) >> TWOPOTBITS_IN_LONG);
! 1281: F.ro = NULL;
! 1282: if (DEBUGLEVEL) err(warnprec,"get_red_G", prec);
! 1283: }
! 1284: *pro = F.ro; return u0? gmul(u0,u): u;
! 1285: }
! 1286:
! 1287: /* Return the base change matrix giving an LLL-reduced basis for the
! 1288: * integer basis of nf(T).
! 1289: * *ro = roots of x, computed to precision prec [or NULL] */
! 1290: static GEN
! 1291: get_LLL_basis(nfbasic_t *T, GEN *pro)
! 1292: {
! 1293: GEN u;
! 1294: if (T->r1 != degpol(T->x)) u = get_red_G(T, pro);
! 1295: else
! 1296: {
! 1297: u = lllint_marked(1, make_Tr(T->x, T->bas), 100, 1, &u,NULL,NULL);
! 1298: if (!u) u = idmat(1);
! 1299: }
! 1300: return u;
! 1301: }
! 1302:
! 1303: static void
! 1304: set_LLL_basis(nfbasic_t *T, GEN *pro)
! 1305: {
! 1306: T->bas = gmul(T->bas, get_LLL_basis(T, pro));
! 1307: T->basden = NULL; /* recompute */
! 1308: }
! 1309:
! 1310: typedef struct {
! 1311: GEN xbest, dxbest;
! 1312: long ind, indmax, indbest;
! 1313: } ok_pol_t;
! 1314:
! 1315: /* is xn better than x ? */
! 1316: static int
! 1317: better_pol(GEN xn, GEN dxn, GEN x, GEN dx)
! 1318: {
! 1319: int fl;
! 1320: if (!x) return 1;
! 1321: fl = absi_cmp(dxn, dx);
! 1322: return (fl < 0 || (!fl && gpolcomp(xn, x) < 0));
! 1323: }
! 1324:
! 1325: static GEN
! 1326: ok_pol(void *TT, GEN xn)
! 1327: {
! 1328: ok_pol_t *T = (ok_pol_t*)TT;
! 1329: GEN dxn;
! 1330:
! 1331: if (++T->ind > T->indmax && T->xbest) return T->xbest;
! 1332:
! 1333: if (!ZX_is_squarefree(xn)) return (T->ind == T->indmax)? T->xbest: NULL;
! 1334: if (DEBUGLEVEL>3) outerr(xn);
! 1335: dxn = ZX_disc(xn);
! 1336: if (better_pol(xn, dxn, T->xbest, T->dxbest))
! 1337: {
! 1338: T->dxbest = dxn; T->xbest = xn; T->indbest = T->ind;
! 1339: }
! 1340: if (T->ind >= T->indmax) return T->xbest;
! 1341: return NULL;
! 1342: }
! 1343:
! 1344: /* z in Z[X] with positive leading coeff. Set z := z(-X) or z(X) so that
! 1345: * second coeff is > 0. In place. */
! 1346: static int
! 1347: canon_pol(GEN z)
1.1 noro 1348: {
1.2 ! noro 1349: long i,s;
1.1 noro 1350:
1.2 ! noro 1351: for (i=lgef(z)-2; i>=2; i-=2)
1.1 noro 1352: {
1.2 ! noro 1353: s = signe(z[i]);
! 1354: if (s > 0)
1.1 noro 1355: {
1.2 ! noro 1356: for (; i>=2; i-=2) z[i]=lnegi((GEN)z[i]);
! 1357: return -1;
1.1 noro 1358: }
1.2 ! noro 1359: if (s) return 1;
! 1360: }
! 1361: return 0;
! 1362: }
! 1363:
! 1364: static GEN _polred(GEN x, GEN a, GEN *pta, FP_chk_fun *CHECK);
! 1365:
! 1366: /* Seek a simpler, polynomial pol defining the same number field as
! 1367: * x (assumed to be monic at this point) */
! 1368: static GEN
! 1369: nfpolred(int part, nfbasic_t *T)
! 1370: {
! 1371: GEN x = T->x, dx = T->dx, a = T->bas;
! 1372: GEN phi, xbest, dxbest, mat, d, rev;
! 1373: long i, n = lg(a)-1, v = varn(x);
! 1374: ok_pol_t O;
! 1375: FP_chk_fun chk;
! 1376:
! 1377: if (degpol(x) == 1) { T->x = gsub(polx[v],gun); return gun; }
! 1378:
! 1379: if (!dx) dx = mulii(T->dK, sqri(T->index));
! 1380:
! 1381: O.ind = 0;
! 1382: O.indmax = part? min(n,3): n;
! 1383: O.xbest = NULL;
! 1384: chk.f = &ok_pol;
! 1385: chk.data = (void*)&O;
! 1386: if (!_polred(x, a, NULL, &chk))
! 1387: err(talker,"you found a counter-example to a conjecture, please report!");
! 1388: xbest = O.xbest; dxbest = O.dxbest;
! 1389: if (!better_pol(xbest, dxbest, x, dx)) return NULL; /* no improvement */
! 1390:
! 1391: /* update T */
! 1392: phi = (GEN)a[O.indbest];
! 1393: if (canon_pol(xbest) < 0) phi = gneg_i(phi);
! 1394: if (DEBUGLEVEL>1) fprintferr("xbest = %Z\n",xbest);
! 1395: rev = modreverse_i(phi, x);
! 1396: for (i=1; i<=n; i++) a[i] = (long)RX_RXQ_compo((GEN)a[i], rev, xbest);
! 1397: mat = vecpol_to_mat(Q_remove_denom(a, &d), n);
! 1398: if (!is_pm1(d)) mat = gdiv(hnfmodid(mat,d), d); else mat = idmat(n);
! 1399:
! 1400: (void)carrecomplet(diviiexact(dxbest,T->dK), &(T->index));
! 1401: T->bas= mat_to_vecpol(mat, v);
! 1402: T->dx = dxbest;
! 1403: T->x = xbest; return rev;
! 1404: }
! 1405:
! 1406: GEN
! 1407: get_nfindex(GEN bas)
! 1408: {
! 1409: gpmem_t av = avma;
! 1410: long n = lg(bas)-1;
! 1411: GEN d, mat = vecpol_to_mat(Q_remove_denom(bas, &d), n);
! 1412: if (!d) { avma = av; return gun; }
! 1413: return gerepileuptoint(av, diviiexact(gpowgs(d, n), det(mat)));
! 1414: }
! 1415:
! 1416: void
! 1417: nfbasic_init(GEN x, long flag, GEN fa, nfbasic_t *T)
! 1418: {
! 1419: GEN bas, dK, dx, index;
! 1420: long r1;
! 1421:
! 1422: T->basden = NULL;
! 1423: T->lead = NULL;
! 1424: if (DEBUGLEVEL) (void)timer2();
! 1425: if (typ(x) == t_POL)
! 1426: {
! 1427: check_pol_int(x, "nfinit");
! 1428: if (gisirreducible(x) == gzero) err(redpoler, "nfinit");
! 1429: x = pol_to_monic(x, &(T->lead));
! 1430: bas = allbase(x, flag, &dx, &dK, &index, &fa);
1.1 noro 1431: if (DEBUGLEVEL) msgtimer("round4");
1.2 ! noro 1432: r1 = sturm(x);
! 1433: }
! 1434: else if (typ(x) == t_VEC && lg(x)==3 && typ(x[1])==t_POL)
! 1435: { /* monic integral polynomial + integer basis */
! 1436: GEN mat;
! 1437: bas = (GEN)x[2]; x = (GEN)x[1];
! 1438: if (typ(bas) == t_MAT)
! 1439: { mat = bas; bas = mat_to_vecpol(mat,varn(x)); }
! 1440: else
! 1441: mat = vecpol_to_mat(bas, lg(bas)-1);
! 1442: index = get_nfindex(bas);
! 1443: dx = ZX_disc(x);
! 1444: dK = diviiexact(dx, sqri(index));
! 1445: r1 = sturm(x);
1.1 noro 1446: }
1447: else
1.2 ! noro 1448: { /* nf, bnf, bnr */
! 1449: GEN nf = checknf(x);
! 1450: x = (GEN)nf[1];
! 1451: dK = (GEN)nf[3];
! 1452: index = (GEN)nf[4];
! 1453: bas = (GEN)nf[7];
! 1454: r1 = nf_get_r1(nf); dx = NULL;
! 1455: }
! 1456:
! 1457: T->x = x;
! 1458: T->r1 = r1;
! 1459: T->dx = dx;
! 1460: T->dK = dK;
! 1461: T->bas = bas;
! 1462: T->index = index;
! 1463: }
! 1464:
! 1465: /* Initialize the number field defined by the polynomial x (in variable v)
! 1466: * flag & nf_RED: try a polred first.
! 1467: * flag & nf_PARTRED: as nf_RED but check the first two elements only.
! 1468: * flag & nf_ORIG
! 1469: * do a polred and return [nfinit(x), Mod(a,red)], where
! 1470: * Mod(a,red) = Mod(v,x) (i.e return the base change). */
! 1471: GEN
! 1472: _initalg(GEN x, long flag, long prec)
! 1473: {
! 1474: const gpmem_t av = avma;
! 1475: GEN nf, rev = NULL, ro = NULL;
! 1476: nfbasic_t T;
! 1477:
! 1478: nfbasic_init(x, flag, NULL, &T);
! 1479:
! 1480: if (T.lead && !(flag & (nf_RED|nf_PARTRED)))
! 1481: {
! 1482: err(warner,"non-monic polynomial. Result of the form [nf,c]");
! 1483: flag |= nf_PARTRED | nf_ORIG;
! 1484: }
! 1485: if (flag & (nf_RED|nf_PARTRED))
1.1 noro 1486: {
1.2 ! noro 1487: set_LLL_basis(&T, &ro);
! 1488: rev = nfpolred(flag & nf_PARTRED, &T);
! 1489: if (rev) ro = NULL; /* changed T.x */
! 1490: if (flag & nf_ORIG)
! 1491: {
! 1492: if (!rev) rev = polx[varn(T.x)]; /* no improvement */
! 1493: if (T.lead) rev = gdiv(rev, T.lead);
! 1494: rev = to_polmod(rev, T.x);
1.1 noro 1495: }
1496: if (DEBUGLEVEL) msgtimer("polred");
1497: }
1498:
1.2 ! noro 1499: set_LLL_basis(&T, &ro);
! 1500: if (DEBUGLEVEL) msgtimer("LLL basis");
1.1 noro 1501:
1.2 ! noro 1502: nf = nfbasic_to_nf(&T, ro, prec);
1.1 noro 1503: if (flag & nf_ORIG)
1504: {
1.2 ! noro 1505: GEN res = cgetg(3,t_VEC);
! 1506: res[1] = (long)nf;
! 1507: res[2] = (long)rev; nf = res;
1.1 noro 1508: }
1509: return gerepilecopy(av, nf);
1510: }
1511:
1512: GEN
1.2 ! noro 1513: initalgred(GEN x, long prec) { return _initalg(x, nf_RED, prec); }
! 1514: GEN
! 1515: initalgred2(GEN x, long prec) { return _initalg(x, nf_RED|nf_ORIG, prec); }
1.1 noro 1516: GEN
1.2 ! noro 1517: initalg(GEN x, long prec) { return _initalg(x, 0, prec); }
1.1 noro 1518:
1519: GEN
1520: nfinit0(GEN x, long flag,long prec)
1521: {
1522: switch(flag)
1523: {
1524: case 0:
1.2 ! noro 1525: case 1: return _initalg(x,0,prec);
! 1526: case 2: return _initalg(x,nf_RED,prec);
! 1527: case 3: return _initalg(x,nf_RED|nf_ORIG,prec);
! 1528: case 4: return _initalg(x,nf_PARTRED,prec);
! 1529: case 5: return _initalg(x,nf_PARTRED|nf_ORIG,prec);
1.1 noro 1530: default: err(flagerr,"nfinit");
1531: }
1532: return NULL; /* not reached */
1533: }
1534:
1535: /* assume x a bnr/bnf/nf */
1536: long
1537: nfgetprec(GEN x)
1538: {
1539: GEN nf = checknf(x), ro = (GEN)nf[6];
1.2 ! noro 1540: return (typ(ro)==t_VEC)? precision((GEN)ro[1]): DEFAULTPREC;
1.1 noro 1541: }
1542:
1543: GEN
1544: nfnewprec(GEN nf, long prec)
1545: {
1.2 ! noro 1546: gpmem_t av = avma;
! 1547: GEN NF;
! 1548: nffp_t F;
1.1 noro 1549:
1550: if (typ(nf) != t_VEC) err(talker,"incorrect nf in nfnewprec");
1551: if (lg(nf) == 11) return bnfnewprec(nf,prec);
1552: if (lg(nf) == 7) return bnrnewprec(nf,prec);
1553: (void)checknf(nf);
1.2 ! noro 1554: NF = dummycopy(nf);
! 1555: NF[5] = (long)dummycopy((GEN)NF[5]);
! 1556: remake_GM(NF, &F, prec);
! 1557: NF[6] = (long)F.ro;
! 1558: mael(NF,5,1) = (long)F.M;
! 1559: mael(NF,5,2) = (long)F.G;
! 1560: return gerepilecopy(av, NF);
! 1561: }
! 1562:
! 1563: /********************************************************************/
! 1564: /** **/
! 1565: /** POLRED **/
! 1566: /** **/
! 1567: /********************************************************************/
! 1568: /* remove duplicate polynomials in y, updating a (same indexes), in place */
! 1569: static void
! 1570: remove_duplicates(GEN y, GEN a)
! 1571: {
! 1572: long k, i, l = lg(y);
! 1573: gpmem_t av = avma;
! 1574: GEN z;
! 1575:
! 1576: if (l < 2) return;
! 1577: z = new_chunk(3);
! 1578: z[1] = (long)y;
! 1579: z[2] = (long)a; (void)sort_factor(z, gcmp);
! 1580: for (k=1, i=2; i<l; i++)
! 1581: if (!gegal((GEN)y[i], (GEN)y[k]))
! 1582: {
! 1583: k++;
! 1584: a[k] = a[i];
! 1585: y[k] = y[i];
! 1586: }
! 1587: l = k+1; setlg(a,l); setlg(y,l);
! 1588: avma = av;
! 1589: }
! 1590:
! 1591: /* if CHECK != NULL, return the first polynomial pol found such that
! 1592: * CHECK->f(CHECK->data, pol) != 0; return NULL if there are no such pol */
! 1593: static GEN
! 1594: _polred(GEN x, GEN a, GEN *pta, FP_chk_fun *CHECK)
! 1595: {
! 1596: long i, v = varn(x), l = lg(a);
! 1597: GEN ch, d, y = cgetg(l,t_VEC);
! 1598:
! 1599: for (i=1; i<l; i++)
! 1600: {
! 1601: if (DEBUGLEVEL>2) { fprintferr("i = %ld\n",i); flusherr(); }
! 1602: ch = QX_caract(x, (GEN)a[i], v);
! 1603: if (CHECK)
! 1604: {
! 1605: ch = CHECK->f(CHECK->data, ch);
! 1606: if (!ch) continue;
! 1607: return ch;
! 1608: }
! 1609: d = modulargcd(derivpol(ch), ch);
! 1610: if (degpol(d)) ch = gdivexact(ch,d);
! 1611:
! 1612: if (canon_pol(ch) < 0 && pta) a[i] = (long)gneg_i((GEN)a[i]);
! 1613: if (DEBUGLEVEL > 3) outerr(ch);
! 1614: y[i] = (long)ch;
! 1615: }
! 1616: if (CHECK) return NULL; /* no suitable polynomial found */
! 1617: remove_duplicates(y,a);
! 1618: if (pta) *pta = a;
! 1619: return y;
! 1620: }
! 1621:
! 1622: static GEN
! 1623: allpolred(GEN x, long flag, GEN fa, GEN *pta, FP_chk_fun *CHECK)
! 1624: {
! 1625: GEN ro = NULL;
! 1626: nfbasic_t T; nfbasic_init(x, flag, fa, &T);
! 1627: if (T.lead) err(impl,"polred for non-monic polynomial");
! 1628: set_LLL_basis(&T, &ro);
! 1629: return _polred(T.x, T.bas, pta, CHECK);
! 1630: }
! 1631:
! 1632: /* FIXME: backward compatibility */
! 1633: #define red_PARTIAL 1
! 1634: #define red_ORIG 2
! 1635:
! 1636: GEN
! 1637: polred0(GEN x, long flag, GEN fa)
! 1638: {
! 1639: gpmem_t av = avma;
! 1640: GEN y, a;
! 1641: int fl = 0;
! 1642:
! 1643: if (fa && gcmp0(fa)) fa = NULL; /* compatibility */
! 1644: if (flag & red_PARTIAL) fl |= nf_PARTIALFACT;
! 1645: if (flag & red_ORIG) fl |= nf_ORIG;
! 1646: y = allpolred(x, fl, fa, &a, NULL);
! 1647: if (fl & nf_ORIG) {
! 1648: GEN z = cgetg(3,t_MAT);
! 1649: z[1] = (long)a;
! 1650: z[2] = (long)y; y = z;
! 1651: }
1.1 noro 1652: return gerepilecopy(av, y);
1653: }
1654:
1.2 ! noro 1655: GEN
! 1656: ordred(GEN x)
! 1657: {
! 1658: gpmem_t av = avma;
! 1659: GEN y;
! 1660:
! 1661: if (typ(x) != t_POL) err(typeer,"ordred");
! 1662: if (!gcmp1(leading_term(x))) err(impl,"ordred");
! 1663: if (!signe(x)) return gcopy(x);
! 1664: y = cgetg(3,t_VEC);
! 1665: y[1] = (long)x;
! 1666: y[2] = (long)idmat(degpol(x));
! 1667: return gerepileupto(av, polred(y));
! 1668: }
! 1669:
! 1670: GEN
! 1671: polredfirstpol(GEN x, long flag, FP_chk_fun *CHECK)
! 1672: { return allpolred(x,flag,NULL,NULL,CHECK); }
! 1673: GEN
! 1674: polred(GEN x)
! 1675: { return polred0(x, 0, NULL); }
! 1676: GEN
! 1677: smallpolred(GEN x)
! 1678: { return polred0(x, red_PARTIAL, NULL); }
! 1679: GEN
! 1680: factoredpolred(GEN x, GEN fa)
! 1681: { return polred0(x, 0, fa); }
! 1682: GEN
! 1683: polred2(GEN x)
! 1684: { return polred0(x, red_ORIG, NULL); }
! 1685: GEN
! 1686: smallpolred2(GEN x)
! 1687: { return polred0(x, red_PARTIAL|red_ORIG, NULL); }
! 1688: GEN
! 1689: factoredpolred2(GEN x, GEN fa)
! 1690: { return polred0(x, red_PARTIAL, fa); }
! 1691:
! 1692: /********************************************************************/
! 1693: /** **/
! 1694: /** POLREDABS **/
! 1695: /** **/
! 1696: /********************************************************************/
! 1697:
! 1698: GEN
! 1699: T2_from_embed_norm(GEN x, long r1)
! 1700: {
! 1701: GEN p = sum(x, 1, r1);
! 1702: GEN q = sum(x, r1+1, lg(x)-1);
! 1703: if (q != gzero) p = gadd(p, gmul2n(q,1));
! 1704: return p;
! 1705: }
! 1706:
! 1707: GEN
! 1708: T2_from_embed(GEN x, long r1)
! 1709: {
! 1710: return T2_from_embed_norm(gnorm(x), r1);
! 1711: }
! 1712:
! 1713: typedef struct {
! 1714: long r1, v, prec;
! 1715: GEN ZKembed; /* embeddings of fincke-pohst-reduced Zk basis */
! 1716: GEN u; /* matrix giving fincke-pohst-reduced Zk basis */
! 1717: GEN M; /* embeddings of initial (LLL-reduced) Zk basis */
! 1718: GEN bound; /* T2 norm of the polynomial defining nf */
! 1719: } CG_data;
! 1720:
! 1721: /* characteristic pol of x */
! 1722: static GEN
! 1723: get_polchar(CG_data *d, GEN x)
! 1724: {
! 1725: GEN g = gmul(d->ZKembed,x);
! 1726: long e;
! 1727: g = grndtoi(roots_to_pol_r1r2(g, d->r1, d->v), &e);
! 1728: if (e > -5) err(precer, "get_polchar");
! 1729: return g;
! 1730: }
! 1731:
! 1732: /* return a defining polynomial for Q(x) */
! 1733: static GEN
! 1734: get_polmin(CG_data *d, GEN x)
! 1735: {
! 1736: GEN g = get_polchar(d,x);
! 1737: GEN h = modulargcd(g,derivpol(g));
! 1738: if (degpol(h)) g = gdivexact(g,h);
! 1739: return g;
! 1740: }
! 1741:
! 1742: /* does x generate the correct field ? */
! 1743: static GEN
! 1744: chk_gen(void *data, GEN x)
! 1745: {
! 1746: gpmem_t av = avma;
! 1747: GEN g = get_polchar((CG_data*)data,x);
! 1748: GEN h = modulargcd(g,derivpol(g));
! 1749: if (degpol(h)) { avma = av; return NULL; }
! 1750: if (DEBUGLEVEL>3) fprintferr(" generator: %Z\n",g);
! 1751: return g;
! 1752: }
! 1753:
! 1754: /* mat = base change matrix, gram = LLL-reduced T2 matrix */
! 1755: static GEN
! 1756: chk_gen_init(FP_chk_fun *chk, GEN gram, GEN mat)
! 1757: {
! 1758: CG_data *d = (CG_data*)chk->data;
! 1759: GEN P,bound,prev,x,B;
! 1760: long l = lg(gram), N = l-1,i,prec,prec2;
! 1761: int skipfirst = 0;
! 1762:
! 1763: d->u = mat;
! 1764: d->ZKembed = gmul(d->M, mat);
! 1765:
! 1766: bound = d->bound;
! 1767: prev = NULL;
! 1768: x = zerocol(N);
! 1769: for (i=1; i<l; i++)
! 1770: {
! 1771: B = gcoeff(gram,i,i);
! 1772: if (gcmp(B,bound) >= 0) continue; /* don't assume increasing norms */
! 1773:
! 1774: x[i] = un; P = get_polmin(d,x);
! 1775: x[i] = zero;
! 1776: if (degpol(P) == N)
! 1777: {
! 1778: if (gcmp(B,bound) < 0) bound = B ;
! 1779: continue;
! 1780: }
! 1781: if (DEBUGLEVEL>2) fprintferr("chk_gen_init: subfield %Z\n",P);
! 1782: if (skipfirst != i-1) continue;
! 1783:
! 1784: /* Q(w[1],...,w[i-1]) = Q[X]/(prev) is a strict subfield of nf */
! 1785: if (prev && degpol(prev) < N && !gegal(prev,P))
! 1786: {
! 1787: if (degpol(prev) * degpol(P) > 64) continue; /* too expensive */
! 1788: P = compositum(prev,P);
! 1789: P = (GEN)P[lg(P)-1];
! 1790: if (degpol(P) == N) continue;
! 1791: if (DEBUGLEVEL>2 && degpol(P) != degpol(prev))
! 1792: fprintferr("chk_gen_init: subfield %Z\n",P);
! 1793: }
! 1794: skipfirst++; prev = P;
! 1795: }
! 1796: /* x_1,...,x_skipfirst generate a strict subfield [unless N=skipfirst=1] */
! 1797: chk->skipfirst = skipfirst;
! 1798: if (DEBUGLEVEL>2) fprintferr("chk_gen_init: skipfirst = %ld\n",skipfirst);
! 1799:
! 1800: /* should be gexpo( max_k C^n_k (bound/k)^(k/2) ) */
! 1801: prec2 = (1 + (((gexpo(bound)*N)/2) >> TWOPOTBITS_IN_LONG));
! 1802: if (prec2 < 0) prec2 = 0;
! 1803: prec = 3 + prec2;
! 1804: if (DEBUGLEVEL)
! 1805: fprintferr("chk_gen_init: new prec = %ld (initially %ld)\n", prec, d->prec);
! 1806: if (prec > d->prec) err(bugparier, "precision problem in polredabs");
! 1807: if (prec < d->prec) d->ZKembed = gprec_w(d->ZKembed, prec);
! 1808: return bound;
! 1809: }
! 1810:
! 1811: /* store phi(beta mod z). Suitable for gerepileupto */
! 1812: static GEN
! 1813: storeeval(GEN beta, GEN z, GEN lead)
! 1814: {
! 1815: GEN y = cgetg(3,t_VEC);
! 1816: z = gcopy(z);
! 1817: beta = lead? gdiv(beta, lead): gcopy(beta);
! 1818: y[1] = (long)z;
! 1819: y[2] = (long)to_polmod(beta,z);
! 1820: return y;
! 1821: }
! 1822:
! 1823: static GEN
! 1824: storeraw(GEN beta, GEN z)
! 1825: {
! 1826: GEN y = cgetg(3,t_VEC);
! 1827: y[1] = lcopy(z);
! 1828: y[2] = lcopy(beta); return y;
! 1829: }
! 1830:
! 1831: static void
! 1832: findmindisc(GEN *py, GEN *pa)
! 1833: {
! 1834: GEN v, dmin, z, b, discs, y = *py, a = *pa;
! 1835: long i,k, l = lg(y);
! 1836:
! 1837: if (l == 2) { *py = (GEN)y[1]; *pa = (GEN)a[1]; return; }
! 1838:
! 1839: discs = cgetg(l,t_VEC);
! 1840: for (i=1; i<l; i++) discs[i] = labsi(ZX_disc((GEN)y[i]));
! 1841: v = sindexsort(discs);
! 1842: k = v[1];
! 1843: dmin = (GEN)discs[k];
! 1844: z = (GEN)y[k];
! 1845: b = (GEN)a[k];
! 1846: for (i=2; i<l; i++)
! 1847: {
! 1848: k = v[i];
! 1849: if (!egalii((GEN)discs[k], dmin)) break;
! 1850: if (gpolcomp((GEN)y[k],z) < 0) { z = (GEN)y[k]; b = (GEN)a[k]; }
! 1851: }
! 1852: *py = z; *pa = b;
! 1853: }
! 1854:
! 1855: static GEN
! 1856: storepol(GEN x, GEN z, GEN a, GEN lead, long flag)
! 1857: {
! 1858: GEN y, b;
! 1859: if (flag & nf_RAW)
! 1860: y = storeraw(a, z);
! 1861: else if (flag & nf_ORIG)
! 1862: {
! 1863: b = modreverse_i(a, x);
! 1864: y = storeeval(b,z, lead);
! 1865: }
! 1866: else
! 1867: y = gcopy(z);
! 1868: return y;
! 1869: }
! 1870:
! 1871: static GEN
! 1872: storeallpol(GEN x, GEN z, GEN a, GEN lead, long flag)
! 1873: {
! 1874: GEN y, b;
! 1875:
! 1876: if (flag & nf_RAW)
! 1877: {
! 1878: long i, c = lg(z);
! 1879: y = cgetg(c,t_VEC);
! 1880: for (i=1; i<c; i++) y[i] = (long)storeraw((GEN)a[i], (GEN)z[i]);
! 1881: }
! 1882: else if (flag & nf_ORIG)
! 1883: {
! 1884: long i, c = lg(z);
! 1885: b = cgetg(c, t_VEC);
! 1886: for (i=1; i<c; i++)
! 1887: b[i] = (long)modreverse_i((GEN)a[i], x);
! 1888:
! 1889: y = cgetg(c,t_VEC);
! 1890: for (i=1; i<c; i++) y[i] = (long)storeeval((GEN)b[i], (GEN)z[i], lead);
! 1891: }
! 1892: else
! 1893: y = gcopy(z);
! 1894: return y;
! 1895: }
! 1896:
! 1897: GEN
! 1898: _polredabs(nfbasic_t *T, GEN *u)
! 1899: {
! 1900: long i, prec, e, n = degpol(T->x);
! 1901: GEN v, ro = NULL;
! 1902: FP_chk_fun chk = { &chk_gen, &chk_gen_init, NULL, 0 };
! 1903: nffp_t F;
! 1904: CG_data d; chk.data = (void*)&d;
! 1905:
! 1906: set_LLL_basis(T, &ro);
! 1907: if (DEBUGLEVEL) msgtimer("LLL basis");
! 1908:
! 1909: /* || polchar ||_oo < 2^e */
! 1910: e = n * (gexpo(gmulsg(n, cauchy_bound(T->x))) + 1);
! 1911: prec = DEFAULTPREC + (e >> TWOPOTBITS_IN_LONG);
! 1912:
! 1913: get_nf_fp_compo(T, &F, ro, prec);
! 1914:
! 1915: d.v = varn(T->x);
! 1916: d.r1= T->r1;
! 1917: d.bound = gmul(T2_from_embed(F.ro, d.r1), dbltor(1.00000001));
! 1918: for (i=1; ; i++)
! 1919: {
! 1920: GEN R = R_from_QR(F.G, prec);
! 1921: d.prec = prec;
! 1922: d.M = F.M;
! 1923: if (R)
! 1924: {
! 1925: v = fincke_pohst(_vec(R),NULL,5000,1, 0, &chk);
! 1926: if (v) break;
! 1927: }
! 1928: if (i==MAXITERPOL) err(accurer,"polredabs0");
! 1929: prec = (prec<<1)-2;
! 1930: get_nf_fp_compo(T, &F, NULL, prec);
! 1931: if (DEBUGLEVEL) err(warnprec,"polredabs0",prec);
! 1932: }
! 1933: *u = d.u; return v;
! 1934: }
! 1935:
! 1936: GEN
! 1937: polredabs0(GEN x, long flag)
! 1938: {
! 1939: long i, l, vx;
! 1940: gpmem_t av = avma;
! 1941: GEN y, a, u;
! 1942: nfbasic_t T;
! 1943:
! 1944: nfbasic_init(x, flag & nf_PARTIALFACT, NULL, &T);
! 1945: x = T.x; vx = varn(x);
! 1946:
! 1947: if (degpol(x) == 1)
! 1948: {
! 1949: u = NULL;
! 1950: y = _vec(polx[vx]);
! 1951: a = _vec(gsub((GEN)y[1], (GEN)x[2]));
! 1952: }
! 1953: else
! 1954: {
! 1955: GEN v = _polredabs(&T, &u);
! 1956: y = (GEN)v[1];
! 1957: a = (GEN)v[2];
! 1958: }
! 1959: l = lg(a);
! 1960: for (i=1; i<l; i++)
! 1961: if (canon_pol((GEN)y[i]) < 0) a[i] = (long)gneg_i((GEN)a[i]);
! 1962: remove_duplicates(y,a);
! 1963: l = lg(a);
! 1964: if (l == 1)
! 1965: {
! 1966: y = _vec(x);
! 1967: a = _vec(polx[vx]);
! 1968: }
! 1969: if (DEBUGLEVEL) fprintferr("%ld minimal vectors found.\n",l-1);
! 1970: if (flag & nf_ALL)
! 1971: {
! 1972: if (u) for (i=1; i<l; i++) a[i] = lmul(T.bas, gmul(u, (GEN)a[i]));
! 1973: y = storeallpol(x,y,a,T.lead,flag);
! 1974: }
! 1975: else
! 1976: {
! 1977: findmindisc(&y, &a);
! 1978: if (u) a = gmul(T.bas, gmul(u, a));
! 1979: y = storepol(x,y,a,T.lead,flag);
! 1980: }
! 1981: return gerepileupto(av, y);
! 1982: }
! 1983:
! 1984: GEN
! 1985: polredabsall(GEN x, long flun) { return polredabs0(x, flun | nf_ALL); }
! 1986: GEN
! 1987: polredabs(GEN x) { return polredabs0(x,0); }
! 1988: GEN
! 1989: polredabs2(GEN x) { return polredabs0(x,nf_ORIG); }
! 1990:
1.1 noro 1991: static long
1992: nf_pm1(GEN y)
1993: {
1994: long i,l;
1995:
1996: if (!is_pm1(y[1])) return 0;
1997: l = lg(y);
1998: for (i=2; i<l; i++)
1999: if (signe(y[i])) return 0;
2000: return signe(y[1]);
2001: }
2002:
2003: static GEN
2004: is_primitive_root(GEN nf, GEN fa, GEN x, long w)
2005: {
2006: GEN y, exp = stoi(2), pp = (GEN)fa[1];
2007: long i,p, l = lg(pp);
2008:
2009: for (i=1; i<l; i++)
2010: {
2011: p = itos((GEN)pp[i]);
2012: exp[2] = w / p; y = element_pow(nf,x,exp);
2013: if (nf_pm1(y) > 0) /* y = 1 */
2014: {
2015: if (p!=2 || !gcmp1(gcoeff(fa,i,2))) return NULL;
2016: x = gneg_i(x);
2017: }
2018: }
2019: return x;
2020: }
2021:
1.2 ! noro 2022: /* only roots of 1 are +/- 1 */
! 2023: static GEN
! 2024: trivroots(GEN nf)
! 2025: {
! 2026: GEN y = cgetg(3, t_VEC);
! 2027: y[1] = deux;
! 2028: y[2] = (long)gscalcol_i(negi(gun), degpol(nf[1]));
! 2029: return y;
! 2030: }
! 2031:
1.1 noro 2032: GEN
2033: rootsof1(GEN nf)
2034: {
1.2 ! noro 2035: gpmem_t av = avma;
1.1 noro 2036: long N,k,i,ws,prec;
1.2 ! noro 2037: GEN p1,y,d,list,w;
! 2038:
! 2039: nf = checknf(nf);
! 2040: if ( nf_get_r1(nf) ) return trivroots(nf);
1.1 noro 2041:
1.2 ! noro 2042: N = degpol(nf[1]); prec = nfgetprec(nf);
1.1 noro 2043: for (i=1; ; i++)
2044: {
1.2 ! noro 2045: GEN R = R_from_QR(gmael(nf,5,2), prec);
! 2046: if (R)
! 2047: {
! 2048: p1 = fincke_pohst(_vec(R),stoi(N),1000,1, 0, NULL);
! 2049: if (p1) break;
! 2050: }
1.1 noro 2051: if (i == MAXITERPOL) err(accurer,"rootsof1");
1.2 ! noro 2052: prec = (prec<<1)-2;
1.1 noro 2053: if (DEBUGLEVEL) err(warnprec,"rootsof1",prec);
1.2 ! noro 2054: nf = nfnewprec(nf,prec);
1.1 noro 2055: }
2056: if (itos(ground((GEN)p1[2])) != N) err(bugparier,"rootsof1 (bug1)");
1.2 ! noro 2057: w = (GEN)p1[1]; ws = itos(w);
! 2058: if (ws == 2) { avma = av; return trivroots(nf); }
1.1 noro 2059:
2060: d = decomp(w); list = (GEN)p1[3]; k = lg(list);
2061: for (i=1; i<k; i++)
2062: {
2063: p1 = (GEN)list[i];
2064: p1 = is_primitive_root(nf,d,p1,ws);
1.2 ! noro 2065: if (p1) break;
1.1 noro 2066: }
1.2 ! noro 2067: if (!p1) err(bugparier,"rootsof1");
! 2068: y = cgetg(3, t_VEC);
! 2069: y[1] = lstoi(ws);
! 2070: y[2] = (long)p1; return gerepilecopy(av, y);
1.1 noro 2071: }
2072:
2073: /*******************************************************************/
2074: /* */
2075: /* DEDEKIND ZETA FUNCTION */
2076: /* */
2077: /*******************************************************************/
2078: static GEN
2079: dirzetak0(GEN nf, long N0)
2080: {
2081: GEN vect,p1,pol,disc,c,c2;
1.2 ! noro 2082: gpmem_t av=avma;
! 2083: long i,j,k,limk,lx;
1.1 noro 2084: ulong q,p,rem;
2085: byteptr d=diffptr;
1.2 ! noro 2086: long court[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3),0};
1.1 noro 2087:
2088: pol=(GEN)nf[1]; disc=(GEN)nf[4];
2089: c = (GEN) gpmalloc((N0+1)*sizeof(long));
2090: c2 = (GEN) gpmalloc((N0+1)*sizeof(long));
2091: c2[0]=c[0]=evaltyp(t_VEC) | evallg(N0+1);
2092: c2[1]=c[1]=1; for (i=2; i<=N0; i++) c[i]=0;
2093: court[2] = 0;
2094:
2095: while (court[2]<=N0)
2096: {
1.2 ! noro 2097: NEXT_PRIME_VIADIFF_CHECK(court[2], d);
1.1 noro 2098: if (smodis(disc,court[2])) /* court does not divide index */
2099: { vect = (GEN) simplefactmod(pol,court)[1]; lx=lg(vect); }
2100: else
2101: {
2102: p1=primedec(nf,court); lx=lg(p1); vect=cgetg(lx,t_COL);
2103: for (i=1; i<lx; i++) vect[i]=mael(p1,i,4);
2104: }
2105: for (j=1; j<lx; j++)
2106: {
2107: p1=powgi(court, (GEN)vect[j]); /* p1 = court^f */
2108: if (cmpis(p1,N0) <= 0)
2109: {
2110: q=p=p1[2]; limk=N0/q;
2111: for (k=2; k<=N0; k++) c2[k]=c[k];
2112: while (q<=(ulong)N0)
2113: {
2114: for (k=1; k<=limk; k++) c2[k*q] += c[k];
2115: q = smulss(q,p,&rem);
2116: if (rem) break;
2117: limk /= p;
2118: }
2119: p1=c; c=c2; c2=p1;
2120: }
2121: }
2122: avma=av;
2123: if (DEBUGLEVEL>6) fprintferr(" %ld",court[2]);
2124: }
2125: if (DEBUGLEVEL>6) { fprintferr("\n"); flusherr(); }
2126: free(c2); return c;
2127: }
2128:
2129: GEN
2130: dirzetak(GEN nf, GEN b)
2131: {
2132: GEN z,c;
2133: long i;
2134:
2135: if (typ(b)!=t_INT) err(talker,"not an integer type in dirzetak");
2136: if (signe(b)<=0) return cgetg(1,t_VEC);
2137: nf = checknf(nf);
2138: if (is_bigint(b)) err(talker,"too many terms in dirzetak");
2139: c = dirzetak0(nf,itos(b));
2140: i = lg(c); z=cgetg(i,t_VEC);
2141: for (i-- ; i; i--) z[i]=lstoi(c[i]);
2142: free(c); return z;
2143: }
2144:
2145: GEN
2146: initzeta(GEN pol, long prec)
2147: {
2148: GEN nfz,nf,alpha,beta,mu,gr1,gr2,gru,p1,p2,cst,A0,c0,c1,c2,eps,coef;
2149: GEN limx,bnf,resi,zet,C,coeflog,racpi,aij,tabj,colzero, *tabcstn, *tabcstni;
2150: GEN c_even,ck_even,c_odd,ck_odd,serie_even,serie_odd,serie_exp,Pi;
1.2 ! noro 2151: long N0,imin,imax,r1,r2,ru,R,N,i,j,k,n;
! 2152: gpmem_t av,av2,tetpil;
! 2153: long court[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3),0};
1.1 noro 2154: stackzone *zone, *zone0, *zone1;
2155:
2156: /*************** Calcul du residu et des constantes ***************/
2157: eps=gmul2n(gun,-bit_accuracy(prec)-6); p1=dbltor(0.5);
2158: nfz=cgetg(10,t_VEC);
1.2 ! noro 2159: bnf = bnfinit0(pol,2,NULL,prec+1); prec=(prec<<1)-1;
1.1 noro 2160: bnf = checkbnf_discard(bnf);
2161: Pi = mppi(prec); racpi=gsqrt(Pi,prec);
2162:
2163: /* Nb de classes et regulateur */
2164: nf=(GEN)bnf[7]; N=degpol(nf[1]);
2165: r1 = nf_get_r1(nf); r2 = (N-r1)>>1;
2166: gr1=gmael(nf,2,1); gr2=gmael(nf,2,2);
2167: ru=r1+r2; R=ru+2;
2168: av=avma; p1=(GEN)bnf[8]; p2 = gmul(gmul2n(gmael(p1,1,1),r1), (GEN)p1[2]);
2169: tetpil = avma; resi=gerepile(av,tetpil,gdiv(p2, gmael(p1,4,1)));
2170:
2171: /* Calcul de N0 */
2172: cst = cgetr(prec); av = avma;
2173: mu = gadd(gmul2n(gr1,-1),gr2);
2174: alpha = gmul2n(stoi(ru+1),-1);
2175: beta = gpui(gdeux,gmul2n(gr1,-1),DEFAULTPREC);
2176: A0 = gmul2n(gpowgs(mu,R),r1);
2177: A0 = gmul(A0,gpowgs(gmul2n(Pi,1),1-ru));
2178: A0 = gsqrt(A0,DEFAULTPREC);
2179:
2180: c1 = gmul(mu,gpui(beta,ginv(mu),DEFAULTPREC));
2181: c0 = gdiv(gmul(A0,gpowgs(gmul2n(Pi,1),ru-1)),mu);
2182: c0 = gmul(c0,gpui(c1,gneg_i(alpha),DEFAULTPREC));
2183: c2 = gdiv(alpha,mu);
2184:
2185: p1 = glog(gdiv(c0,eps),DEFAULTPREC);
2186: limx = gdiv(gsub(glog(p1,DEFAULTPREC),glog(c1,DEFAULTPREC)),
2187: gadd(c2,gdiv(p1,mu)));
2188: limx = gmul(gpui(gdiv(c1,p1),mu,DEFAULTPREC),
2189: gadd(gun,gmul(alpha,limx)));
2190: p1 = gsqrt(absi((GEN)nf[3]),prec);
2191: p2 = gmul2n(gpowgs(racpi,N),r2);
2192: gaffect(gdiv(p1,p2), cst);
2193:
2194: av = avma; p1 = gfloor(gdiv(cst,limx)); N0 = p1[2];
2195: if (is_bigint(p1) || N0 > 10000000)
2196: err(talker,"discriminant too large for initzeta, sorry");
2197: if (DEBUGLEVEL>=2)
1.2 ! noro 2198: { fprintferr("\ninitzeta:\nN0 = %ld\n",N0); flusherr(); (void)timer2(); }
1.1 noro 2199:
2200: /* Calcul de imax */
2201:
2202: imin=1; imax=1400;
2203: p1 = gmul(gpowgs(gmul2n(racpi,1),r2),gpowgs(stoi(5),r1));
2204: p1 = gdiv(p1,gmul(gmul(gsqrt(limx,DEFAULTPREC),gmul2n(eps,4)),
2205: gpowgs(racpi,3)));
2206: while (imax-imin >= 4)
2207: {
2208: long itest = (imax+imin)>>1;
2209: p2 = gmul(gpowgs(mpfactr(itest,DEFAULTPREC),r2),gpowgs(limx,itest));
2210: p2 = gmul(p2,gpowgs(mpfactr(itest/2,DEFAULTPREC),r1));
2211: if (gcmp(p2,p1) >= 0) imax=itest; else imin=itest;
2212: }
2213: imax -= (imax & 1); avma = av;
2214: if (DEBUGLEVEL>=2) { fprintferr("imax = %ld\n",imax); flusherr(); }
2215: /* Tableau des i/cst (i=1 a N0) */
2216:
2217: i = prec*N0;
2218: zone = switch_stack(NULL,i + 2*(N0+1) + 6*prec);
2219: zone1 = switch_stack(NULL,2*i);
2220: zone0 = switch_stack(NULL,2*i);
1.2 ! noro 2221: (void)switch_stack(zone,1);
1.1 noro 2222: tabcstn = (GEN*) cgetg(N0+1,t_VEC);
2223: tabcstni = (GEN*) cgetg(N0+1,t_VEC);
2224: p1 = ginv(cst);
2225: for (i=1; i<=N0; i++) { tabcstni[i] = gun; tabcstn[i] = mulsr(i,p1); }
1.2 ! noro 2226: (void)switch_stack(zone,0);
1.1 noro 2227:
2228: /********** Calcul des coefficients a(i,j) independants de s **********/
2229:
2230: zet=cgetg(R,t_VEC); zet[1] = lmpeuler(prec);
2231: for (i=2; i<R; i++) zet[i] = (long)gzeta(stoi(i),prec);
2232:
2233: aij=cgetg(imax+1,t_VEC);
2234: for (i=1; i<=imax; i++) aij[i] = lgetg(R,t_VEC);
2235:
2236: c_even = realun(prec);
2237: c_even = gmul2n(c_even,r1);
2238: c_odd = gmul(c_even,gpowgs(racpi,r1));
2239: if (ru&1) c_odd=gneg_i(c_odd);
2240: ck_even=cgetg(R,t_VEC); ck_odd=cgetg(r2+2,t_VEC);
2241: for (k=1; k<R; k++)
2242: {
2243: ck_even[k]=lmul((GEN)zet[k],gadd(gr2,gmul2n(gr1,-k)));
2244: if (k&1) ck_even[k]=lneg((GEN)ck_even[k]);
2245: }
2246: gru=stoi(ru);
2247: for (k=1; k<=r2+1; k++)
2248: {
2249: ck_odd[k]=lmul((GEN)zet[k], gsub(gru, gmul2n(gr1,-k)));
2250: if (k&1) ck_odd[k]=lneg((GEN)ck_odd[k]);
2251: ck_odd[k]=ladd(gru,(GEN)ck_odd[k]);
2252: }
1.2 ! noro 2253: ck_odd[1]=lsub((GEN)ck_odd[1],gmul(gr1,mplog2(prec)));
1.1 noro 2254: serie_even =cgetg(ru+3,t_SER); serie_odd=cgetg(r2+3,t_SER);
2255: serie_even[1] = serie_odd[1] = evalsigne(1)+evalvalp(1);
2256: i=0;
2257:
2258: while (i<imax/2)
2259: {
2260: for (k=1; k<R; k++)
2261: serie_even[k+1]=ldivgs((GEN)ck_even[k],k);
2262: serie_exp=gmul(c_even,gexp(serie_even,0));
2263: p1=(GEN)aij[2*i+1];
2264: for (j=1; j<R; j++) p1[j]=serie_exp[ru+3-j];
2265:
2266: for (k=1; k<=r2+1; k++)
2267: serie_odd[k+1]=ldivgs((GEN)ck_odd[k],k);
2268: serie_exp=gmul(c_odd,gexp(serie_odd,0));
2269: p1=(GEN)aij[2*i+2];
2270: for (j=1; j<=r2+1; j++) p1[j]=serie_exp[r2+3-j];
2271: for ( ; j<R; j++) p1[j]=zero;
2272: i++;
2273:
2274: c_even = gdiv(c_even,gmul(gpowgs(stoi(i),ru),gpowgs(stoi(2*i-1),r2)));
2275: c_odd = gdiv(c_odd, gmul(gpowgs(stoi(i),r2),gpowgs(stoi(2*i+1),ru)));
2276: c_even = gmul2n(c_even,-r2);
2277: c_odd = gmul2n(c_odd,r1-r2);
2278: if (r1&1) { c_even=gneg_i(c_even); c_odd=gneg_i(c_odd); }
2279: p1 = gr2; p2 = gru;
2280: for (k=1; k<R; k++)
2281: {
2282: p1=gdivgs(p1,2*i-1); p2=gdivgs(p2,2*i);
2283: ck_even[k] = ladd((GEN)ck_even[k], gadd(p1,p2));
2284: }
2285: p1 = gru; p2 = gr2;
2286: for (k=1; k<=r2+1; k++)
2287: {
2288: p1=gdivgs(p1,2*i+1); p2=gdivgs(p2,2*i);
2289: ck_odd[k] = ladd((GEN)ck_odd[k], gadd(p1,p2));
2290: }
2291: }
2292: aij=gerepilecopy(av,aij);
2293: if (DEBUGLEVEL>=2) msgtimer("a(i,j)");
2294: p1=cgetg(5,t_VEC);
2295: p1[1]=lstoi(r1); p1[2]=lstoi(r2); p1[3]=lstoi(imax); p1[4]=(long)bnf;
2296: nfz[1]=(long)p1;
2297: nfz[2]=(long)resi;
2298: nfz[5]=(long)cst;
2299: nfz[6]=llog(cst,prec);
2300: nfz[7]=(long)aij;
2301:
2302: /************* Calcul du nombre d'ideaux de norme donnee *************/
2303: coef = dirzetak0(nf,N0); tabj = cgetg(N0+1,t_MAT);
2304: if (DEBUGLEVEL>=2) msgtimer("coef");
2305: colzero=cgetg(ru+2,t_COL); for (j=1; j<=ru+1; j++) colzero[j]=zero;
2306: for (i=1; i<=N0; i++)
2307: if (coef[i])
2308: {
2309: GEN t = cgetg(ru+2,t_COL);
2310: p1 = glog((GEN)tabcstn[i],prec); setsigne(p1, -signe(p1));
2311: t[1] = lstoi(coef[i]); t[2] = lmul((GEN)t[1],p1);
2312: for (j=2; j<=ru; j++)
2313: {
1.2 ! noro 2314: gpmem_t av2 = avma;
! 2315: p2 = gmul((GEN)t[j], p1);
1.1 noro 2316: t[j+1] = (long)gerepileuptoleaf(av2, divrs(p2,j));
2317: }
2318: /* tabj[n,j]=coef(n)*ln(c/n)^(j-1)/(j-1)! */
2319: tabj[i] = (long)t;
2320: }
2321: else tabj[i]=(long)colzero;
2322: if (DEBUGLEVEL>=2) msgtimer("a(n)");
2323:
2324: coeflog=cgetg(N0+1,t_VEC); coeflog[1]=zero;
2325: for (i=2; i<=N0; i++)
2326: if (coef[i])
2327: {
2328: court[2]=i; p1=glog(court,prec);
2329: setsigne(p1,-1); coeflog[i]=(long)p1;
2330: }
2331: else coeflog[i] = zero;
2332: if (DEBUGLEVEL>=2) msgtimer("log(n)");
2333:
2334: nfz[3]=(long)tabj;
2335: p1 = cgetg(N0+1,t_VECSMALL);
2336: for (i=1; i<=N0; i++) p1[i] = coef[i];
2337: nfz[8]=(long)p1;
2338: nfz[9]=(long)coeflog;
2339:
2340: /******************** Calcul des coefficients Cik ********************/
2341:
2342: C = cgetg(ru+1,t_MAT);
2343: for (k=1; k<=ru; k++) C[k] = lgetg(imax+1,t_COL);
2344: av2 = avma;
2345: for (i=1; i<=imax; i++)
2346: {
2347: stackzone *z;
2348: for (k=1; k<=ru; k++)
2349: {
2350: p1 = NULL;
2351: for (n=1; n<=N0; n++)
2352: if (coef[n])
2353: for (j=1; j<=ru-k+1; j++)
2354: {
2355: p2 = gmul(tabcstni[n],
2356: gmul(gmael(aij,i,j+k), gmael(tabj,n,j)));
2357: p1 = p1? gadd(p1,p2): p2;
2358: }
2359: coeff(C,i,k) = p1? (long)gerepileupto(av2,p1): zero;
2360: av2 = avma;
2361: }
2362: /* use a parallel stack */
2363: z = i&1? zone1: zone0;
1.2 ! noro 2364: (void)switch_stack(z, 1);
1.1 noro 2365: for (n=1; n<=N0; n++)
2366: if (coef[n]) tabcstni[n] = mpmul(tabcstni[n],tabcstn[n]);
2367: /* come back */
1.2 ! noro 2368: (void)switch_stack(z, 0);
1.1 noro 2369: }
2370: nfz[4] = (long) C;
2371: if (DEBUGLEVEL>=2) msgtimer("Cik");
2372: gunclone(aij);
2373: free((void*)zone); free((void*)zone1); free((void*)zone0);
2374: free((void*)coef); return nfz;
2375: }
2376:
2377: GEN
2378: gzetakall(GEN nfz, GEN s, long flag, long prec2)
2379: {
2380: GEN resi,C,cst,cstlog,coeflog,cs,coef;
2381: GEN lambd,gammas,gammaunmoins,gammas2,gammaunmoins2,var1,var2;
2382: GEN p1,unmoins,gexpro,gar,val,valm,valk,valkm;
1.2 ! noro 2383: long ts = typ(s), r1,r2,ru,imax,i,j,k,N0,sl,prec,bigprec;
! 2384: gpmem_t av = avma;
1.1 noro 2385:
2386: if (typ(nfz)!=t_VEC || lg(nfz)!=10 || typ(nfz[1]) != t_VEC)
2387: err(talker,"not a zeta number field in zetakall");
2388: if (! is_intreal_t(ts) && ts != t_COMPLEX && ! is_frac_t(ts))
2389: err(typeer,"gzetakall");
2390: resi=(GEN)nfz[2]; C=(GEN)nfz[4]; cst=(GEN)nfz[5];
2391: cstlog=(GEN)nfz[6]; coef=(GEN)nfz[8]; coeflog=(GEN)nfz[9];
2392: r1 = itos(gmael(nfz,1,1));
2393: r2 = itos(gmael(nfz,1,2)); ru = r1+r2;
2394: imax = itos(gmael(nfz,1,3)); N0 = lg(coef)-1;
2395: bigprec = precision(cst); prec = prec2+1;
2396:
2397: if (ts==t_COMPLEX && gcmp0(gimag(s))) { s=greal(s); ts = typ(s); }
2398: if (ts==t_REAL && !signe(gfrac(s))) { s=mptrunc(s); ts = t_INT; }
2399: if (ts==t_INT)
2400: {
2401: sl=itos(s);
2402: if (sl==1) err(talker,"s = 1 is a pole (gzetakall)");
2403: if (sl==0)
2404: {
2405: avma = av;
2406: if (flag) err(talker,"s = 0 is a pole (gzetakall)");
2407: if (ru == 1) return gneg(r1? ghalf: resi);
2408: return gzero;
2409: }
2410: if (sl<0 && (r2 || !odd(sl)))
2411: {
2412: if (!flag) return gzero;
2413: s = subsi(1,s); sl = 1-sl;
2414: }
2415: unmoins=subsi(1,s);
2416: lambd = gdiv(resi, mulis(s,sl-1));
2417: gammas2=ggamma(gmul2n(s,-1),prec);
2418: gar=gpowgs(gammas2,r1);
2419: cs=gexp(gmul(cstlog,s),prec);
2420: val=s; valm=unmoins;
2421: if (sl < 0) /* r2 = 0 && odd(sl) */
2422: {
2423: gammaunmoins2=ggamma(gmul2n(unmoins,-1),prec);
2424: var1=var2=gun;
2425: for (i=2; i<=N0; i++)
2426: if (coef[i])
2427: {
2428: gexpro=gexp(gmul((GEN)coeflog[i],s),bigprec);
2429: var1 = gadd(var1,gmulsg(coef[i],gexpro));
2430: var2 = gadd(var2,gdivsg(coef[i],gmulsg(i,gexpro)));
2431: }
2432: lambd=gadd(lambd,gmul(gmul(var1,cs),gar));
2433: lambd=gadd(lambd,gmul(gmul(var2,gdiv(cst,cs)),
2434: gpowgs(gammaunmoins2,r1)));
2435: for (i=1; i<=imax; i+=2)
2436: {
2437: valk = val;
2438: valkm = valm;
2439: for (k=1; k<=ru; k++)
2440: {
2441: p1 = gcoeff(C,i,k);
2442: lambd = gsub(lambd,gdiv(p1,valk )); valk = mulii(val,valk);
2443: lambd = gsub(lambd,gdiv(p1,valkm)); valkm = mulii(valm,valkm);
2444: }
2445: val = addis(val, 2);
2446: valm = addis(valm,2);
2447: }
2448: }
2449: else
2450: {
2451: GEN tabj=(GEN)nfz[3], aij=(GEN)nfz[7];
2452:
2453: gar = gmul(gar,gpowgs(ggamma(s,prec),r2));
2454: var1=var2=gzero;
2455: for (i=1; i<=N0; i++)
2456: if (coef[i])
2457: {
2458: gexpro=gexp(gmul((GEN)coeflog[i],s),bigprec);
2459: var1 = gadd(var1,gmulsg(coef[i],gexpro));
2460: if (sl <= imax)
2461: {
2462: p1=gzero;
2463: for (j=1; j<=ru+1; j++)
2464: p1 = gadd(p1, gmul(gmael(aij,sl,j), gmael(tabj,i,j)));
2465: var2=gadd(var2,gdiv(p1,gmulsg(i,gexpro)));
2466: }
2467: }
2468: lambd=gadd(lambd,gmul(gmul(var1,cs),gar));
2469: lambd=gadd(lambd,gmul(var2,gdiv(cst,cs)));
2470: for (i=1; i<=imax; i++)
2471: {
2472: valk = val;
2473: valkm = valm;
2474: if (i == sl)
2475: for (k=1; k<=ru; k++)
2476: {
2477: p1 = gcoeff(C,i,k);
2478: lambd = gsub(lambd,gdiv(p1,valk)); valk = mulii(val,valk);
2479: }
2480: else
2481: for (k=1; k<=ru; k++)
2482: {
2483: p1 = gcoeff(C,i,k);
1.2 ! noro 2484: lambd = gsub(lambd,gdiv(p1,valk )); valk = mulii(val,valk);
1.1 noro 2485: lambd = gsub(lambd,gdiv(p1,valkm)); valkm = mulii(valm,valkm);
2486: }
2487: val = addis(val,1);
2488: valm = addis(valm,1);
2489: }
2490: }
2491: }
2492: else
2493: {
2494: GEN Pi = mppi(prec);
2495: if (is_frac_t(ts))
2496: s = gmul(s, realun(bigprec));
2497: else
2498: s = gprec_w(s, bigprec);
2499:
2500: unmoins = gsub(gun,s);
2501: lambd = gdiv(resi,gmul(s,gsub(s,gun)));
2502: gammas = ggamma(s,prec);
2503: gammas2= ggamma(gmul2n(s,-1),prec);
2504: gar = gmul(gpowgs(gammas,r2),gpowgs(gammas2,r1));
2505: cs = gexp(gmul(cstlog,s),prec);
2506: var1 = gmul(Pi,s);
2507: gammaunmoins = gdiv(Pi,gmul(gsin(var1,prec),gammas));
2508: gammaunmoins2= gdiv(gmul(gmul(gsqrt(Pi,prec),gpui(gdeux,gsub(s,gun),prec)),
2509: gammas2),
2510: gmul(gcos(gmul2n(var1,-1),prec),gammas));
2511: var1 = var2 = gun;
2512: for (i=2; i<=N0; i++)
2513: if (coef[i])
2514: {
2515: gexpro = gexp(gmul((GEN)coeflog[i],s),bigprec);
2516: var1 = gadd(var1,gmulsg(coef[i], gexpro));
2517: var2 = gadd(var2,gdivsg(coef[i], gmulsg(i,gexpro)));
2518: }
2519: lambd = gadd(lambd,gmul(gmul(var1,cs),gar));
2520: lambd = gadd(lambd,gmul(gmul(gmul(var2,gdiv(cst,cs)),
2521: gpowgs(gammaunmoins,r2)),
2522: gpowgs(gammaunmoins2,r1)));
2523: val = s;
2524: valm = unmoins;
2525: for (i=1; i<=imax; i++)
2526: {
2527: valk = val;
2528: valkm = valm;
2529: for (k=1; k<=ru; k++)
2530: {
2531: p1 = gcoeff(C,i,k);
2532: lambd = gsub(lambd,gdiv(p1,valk )); valk = gmul(val, valk);
2533: lambd = gsub(lambd,gdiv(p1,valkm)); valkm = gmul(valm,valkm);
2534: }
2535: if (r2)
2536: {
2537: val = gadd(val, gun);
2538: valm = gadd(valm,gun);
2539: }
2540: else
2541: {
2542: val = gadd(val, gdeux);
2543: valm = gadd(valm,gdeux); i++;
2544: }
2545: }
2546: }
2547: if (!flag) lambd = gdiv(lambd,gmul(gar,cs)); /* zetak */
2548: return gerepileupto(av, gprec_w(lambd, prec2));
2549: }
2550:
2551: GEN
2552: gzetak(GEN nfz, GEN s, long prec)
2553: {
2554: return gzetakall(nfz,s,0,prec);
2555: }
2556:
2557: GEN
2558: glambdak(GEN nfz, GEN s, long prec)
2559: {
2560: return gzetakall(nfz,s,1,prec);
2561: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>