Annotation of OpenXM_contrib/pari-2.2/src/basemath/buch3.c, Revision 1.1.1.1
1.1 noro 1: /* $Id: buch3.c,v 1.47 2001/10/01 12:11:30 karim Exp $
2:
3: Copyright (C) 2000 The PARI group.
4:
5: This file is part of the PARI/GP package.
6:
7: PARI/GP is free software; you can redistribute it and/or modify it under the
8: terms of the GNU General Public License as published by the Free Software
9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
10: ANY WARRANTY WHATSOEVER.
11:
12: Check the License for details. You should have received a copy of it, along
13: with the package; see the file 'COPYING'. If not, write to the Free Software
14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
15:
16: /*******************************************************************/
17: /* */
18: /* RAY CLASS FIELDS */
19: /* */
20: /*******************************************************************/
21: #include "pari.h"
22: #include "parinf.h"
23:
24: extern GEN concatsp3(GEN x, GEN y, GEN z);
25: extern GEN check_and_build_cycgen(GEN bnf);
26: extern GEN gmul_mat_smallvec(GEN x, GEN y);
27: extern GEN ideleaddone_aux(GEN nf,GEN x,GEN ideal);
28: extern GEN logunitmatrix(GEN nf,GEN funits,GEN racunit,GEN bid);
29: extern GEN vconcat(GEN Q1, GEN Q2);
30: extern void minim_alloc(long n, double ***q, GEN *x, double **y, double **z, double **v);
31: extern GEN to_famat_all(GEN x, GEN y);
32: extern GEN trivfact(void);
33: extern GEN arch_mul(GEN x, GEN y);
34: extern GEN isprincipalfact(GEN bnf,GEN P, GEN e, GEN C, long flag);
35: extern GEN idealaddtoone_i(GEN nf, GEN x, GEN y);
36: extern GEN ideallllred_elt(GEN nf, GEN I);
37:
38: /* U W V = D, Ui = U^(-1) */
39: GEN
40: compute_class_number(GEN W, GEN *D,GEN *Ui,GEN *V)
41: {
42: GEN S = smith2(W);
43:
44: *Ui= ginv((GEN)S[1]);
45: if (V) *V = (GEN)S[2];
46: *D = (GEN)S[3];
47: if (DEBUGLEVEL>=4) msgtimer("smith/class group");
48: return dethnf_i(*D);
49: }
50:
51: /* FIXME: obsolete, see zarchstar (which is much slower unfortunately). */
52: static GEN
53: get_full_rank(GEN nf, GEN v, GEN _0, GEN _1, GEN gen, long ngen, long rankmax)
54: {
55: GEN vecsign,v1,p1,alpha, bas=(GEN)nf[7], rac=(GEN)nf[6];
56: long rankinit = lg(v)-1, N = degpol(nf[1]), va = varn(nf[1]);
57: long limr,i,k,kk,r,rr;
58: vecsign = cgetg(rankmax+1,t_COL);
59: for (r=1,rr=3; ; r++,rr+=2)
60: {
61: p1 = gpowgs(stoi(rr),N);
62: limr = is_bigint(p1)? BIGINT: p1[2];
63: limr = (limr-1)>>1;
64: for (k=rr; k<=limr; k++)
65: {
66: long av1=avma;
67: alpha = gzero;
68: for (kk=k,i=1; i<=N; i++,kk/=rr)
69: {
70: long lambda = (kk+r)%rr - r;
71: if (lambda)
72: alpha = gadd(alpha,gmulsg(lambda,(GEN)bas[i]));
73: }
74: for (i=1; i<=rankmax; i++)
75: vecsign[i] = (gsigne(gsubst(alpha,va,(GEN)rac[i])) > 0)? (long)_0
76: : (long)_1;
77: v1 = concatsp(v, vecsign);
78: if (rank(v1) == rankinit) avma=av1;
79: else
80: {
81: v=v1; rankinit++; ngen++;
82: gen[ngen] = (long) alpha;
83: if (rankinit == rankmax) return ginv(v); /* full rank */
84: }
85: }
86: }
87: }
88:
89: /* FIXME: obsolete. Replace by a call to buchrayall (currently much slower) */
90: GEN
91: buchnarrow(GEN bnf)
92: {
93: GEN nf,_0,_1,cyc,gen,v,matsign,arch,cycgen,logs;
94: GEN dataunit,p1,p2,h,clh,basecl,met,u1;
95: long r1,R,i,j,ngen,sizeh,t,lo,c;
96: ulong av = avma;
97:
98: bnf = checkbnf(bnf);
99: nf = checknf(bnf); r1 = nf_get_r1(nf);
100: if (!r1) return gcopy(gmael(bnf,8,1));
101:
102: _1 = gmodulss(1,2);
103: _0 = gmodulss(0,2);
104: cyc = gmael3(bnf,8,1,2);
105: gen = gmael3(bnf,8,1,3); ngen = lg(gen)-1;
106: matsign = signunits(bnf); R = lg(matsign);
107: dataunit = cgetg(R+1,t_MAT);
108: for (j=1; j<R; j++)
109: {
110: p1=cgetg(r1+1,t_COL); dataunit[j]=(long)p1;
111: for (i=1; i<=r1; i++)
112: p1[i] = (signe(gcoeff(matsign,i,j)) > 0)? (long)_0: (long)_1;
113: }
114: v = cgetg(r1+1,t_COL); for (i=1; i<=r1; i++) v[i] = (long)_1;
115: dataunit[R] = (long)v; v = image(dataunit); t = lg(v)-1;
116: if (t == r1) { avma = av; return gcopy(gmael(bnf,8,1)); }
117:
118: sizeh = ngen+r1-t; p1 = cgetg(sizeh+1,t_COL);
119: for (i=1; i<=ngen; i++) p1[i] = gen[i];
120: gen = p1;
121: v = get_full_rank(nf,v,_0,_1,gen,ngen,r1);
122:
123: arch = cgetg(r1+1,t_VEC); for (i=1; i<=r1; i++) arch[i]=un;
124: cycgen = check_and_build_cycgen(bnf);
125: logs = cgetg(ngen+1,t_MAT);
126: for (j=1; j<=ngen; j++)
127: {
128: GEN u = lift_intern(gmul(v, zsigne(nf,(GEN)cycgen[j],arch)));
129: logs[j] = (long)vecextract_i(u, t+1, r1);
130: }
131: /* [ cyc 0 ]
132: * [ logs 2 ] = relation matrix for Cl_f */
133: h = concatsp(
134: vconcat(diagonal(cyc), logs),
135: vconcat(zeromat(ngen, r1-t), gscalmat(gdeux,r1-t))
136: );
137: clh = compute_class_number(h,&met,&u1,NULL);
138: lo = lg(met)-1;
139: for (c=1; c<=lo; c++)
140: if (gcmp1(gcoeff(met,c,c))) break;
141:
142: u1 = reducemodmatrix(u1,h);
143: basecl = cgetg(c,t_VEC);
144: for (j=1; j<c; j++)
145: {
146: p1 = gcoeff(u1,1,j);
147: p2 = idealpow(nf,(GEN)gen[1],p1);
148: if (signe(p1) < 0) p2 = numer(p2);
149: for (i=2; i<=lo; i++)
150: {
151: p1 = gcoeff(u1,i,j);
152: if (signe(p1))
153: {
154: p2 = idealmul(nf,p2, idealpow(nf,(GEN)gen[i],p1));
155: p1 = content(p2); if (!gcmp1(p1)) p2 = gdiv(p2,p1);
156: }
157: }
158: basecl[j] = (long)p2;
159: }
160: v = cgetg(4,t_VEC);
161: v[1] = lcopy(clh); setlg(met,c);
162: v[2] = (long)mattodiagonal(met);
163: v[3] = lcopy(basecl); return gerepileupto(av, v);
164: }
165:
166: /* given two coprime ideals x (integral) and id, compute alpha in x,
167: * alpha = 1 mod (id), with x/alpha nearly reduced.
168: */
169: static GEN
170: findalpha(GEN nf,GEN x,GEN id)
171: {
172: GEN p1, y;
173: GEN alp = idealaddtoone_i(nf,x,id);
174:
175: y = ideallllred_elt(nf, idealmullll(nf,x,id));
176: p1 = ground(element_div(nf,alp,y));
177: alp = gsub(alp, element_mul(nf,p1,y));
178: return gcmp0(alp)? y: alp;
179: }
180:
181: static int
182: too_big(GEN nf, GEN bet)
183: {
184: GEN x = gnorm(basistoalg(nf,bet));
185: switch (typ(x))
186: {
187: case t_INT: return absi_cmp(x, gun);
188: case t_FRAC: return absi_cmp((GEN)x[1], (GEN)x[2]);
189: }
190: err(bugparier, "wrong type in too_big");
191: return 0; /* not reached */
192: }
193:
194: static GEN
195: idealmodidele(GEN nf, GEN x, GEN ideal, GEN sarch, GEN arch)
196: {
197: long av = avma,i,l;
198: GEN p1,p2,alp,bet,b;
199:
200: nf=checknf(nf); alp=findalpha(nf,x,ideal);
201: p1=idealdiv(nf,alp,x);
202: bet = element_div(nf,findalpha(nf,p1,ideal),alp);
203: if (too_big(nf,bet) > 0) { avma=av; return x; }
204: p1=(GEN)sarch[2]; l=lg(p1);
205: if (l > 1)
206: {
207: b=bet; p2=lift_intern(gmul((GEN)sarch[3],zsigne(nf,bet,arch)));
208: for (i=1; i<l; i++)
209: if (signe(p2[i])) bet = element_mul(nf,bet,(GEN)p1[i]);
210: if (b != bet && too_big(nf,bet) > 0) { avma=av; return x; }
211: }
212: return idealmul(nf,bet,x);
213: }
214:
215: static GEN
216: idealmulmodidele(GEN nf,GEN x,GEN y, GEN ideal,GEN sarch,GEN arch)
217: {
218: return idealmodidele(nf,idealmul(nf,x,y),ideal,sarch,arch);
219: }
220:
221: /* assume n > 0 */
222: /* FIXME: should compute x^n = a I using idealred, then reduce a mod idele */
223: static GEN
224: idealpowmodidele(GEN nf,GEN x,GEN n, GEN ideal,GEN sarch,GEN arch)
225: {
226: long i,m,av=avma;
227: GEN y;
228: ulong j;
229:
230: if (cmpis(n, 16) < 0)
231: {
232: if (gcmp1(n)) return x;
233: x = idealpow(nf,x,n);
234: x = idealmodidele(nf,x,ideal,sarch,arch);
235: return gerepileupto(av,x);
236: }
237:
238: i = lgefint(n)-1; m=n[i]; j=HIGHBIT;
239: while ((m&j)==0) j>>=1;
240: y = x;
241: for (j>>=1; j; j>>=1)
242: {
243: y = idealmul(nf,y,y);
244: if (m&j) y = idealmul(nf,y,x);
245: y = idealmodidele(nf,y,ideal,sarch,arch);
246: }
247: for (i--; i>=2; i--)
248: for (m=n[i],j=HIGHBIT; j; j>>=1)
249: {
250: y = idealmul(nf,y,y);
251: if (m&j) y = idealmul(nf,y,x);
252: y = idealmodidele(nf,y,ideal,sarch,arch);
253: }
254: return gerepileupto(av,y);
255: }
256:
257: static GEN
258: buchrayall(GEN bnf,GEN module,long flag)
259: {
260: GEN nf,cyc,gen,genplus,fa2,sarch,hmatu,u,clg,logs;
261: GEN dataunit,p1,p2,h,clh,genray,met,u1,u2,u1old,cycgen;
262: GEN racunit,bigres,bid,cycbid,genbid,x,y,funits,hmat,vecel;
263: long RU,Ri,i,j,ngen,lh,lo,c,av=avma;
264:
265: bnf = checkbnf(bnf); nf = checknf(bnf);
266: funits = check_units(bnf, "buchrayall"); RU = lg(funits);
267: vecel = genplus = NULL; /* gcc -Wall */
268: bigres = (GEN)bnf[8];
269: cyc = gmael(bigres,1,2);
270: gen = gmael(bigres,1,3); ngen = lg(cyc)-1;
271:
272: bid = zidealstarinitall(nf,module,1);
273: cycbid = gmael(bid,2,2);
274: genbid = gmael(bid,2,3);
275: Ri = lg(cycbid)-1; lh = ngen+Ri;
276:
277: x = idealhermite(nf,module);
278: if (Ri || flag & (nf_INIT|nf_GEN))
279: {
280: vecel = cgetg(ngen+1,t_VEC);
281: for (j=1; j<=ngen; j++)
282: {
283: p1 = idealcoprime(nf,(GEN)gen[j],x);
284: if (isnfscalar(p1)) p1 = (GEN)p1[1];
285: vecel[j]=(long)p1;
286: }
287: }
288: if (flag & nf_GEN)
289: {
290: genplus = cgetg(lh+1,t_VEC);
291: for (j=1; j<=ngen; j++)
292: genplus[j] = (long) idealmul(nf,(GEN)vecel[j],(GEN)gen[j]);
293: for ( ; j<=lh; j++)
294: genplus[j] = genbid[j-ngen];
295: }
296: if (!Ri)
297: {
298: if (!(flag & nf_GEN)) clg = cgetg(3,t_VEC);
299: else
300: { clg = cgetg(4,t_VEC); clg[3] = (long)genplus; }
301: clg[1] = mael(bigres,1,1);
302: clg[2] = (long)cyc;
303: if (!(flag & nf_INIT)) return gerepilecopy(av,clg);
304: y = cgetg(7,t_VEC);
305: y[1] = lcopy(bnf);
306: y[2] = lcopy(bid);
307: y[3] = lcopy(vecel);
308: y[4] = (long)idmat(ngen);
309: y[5] = lcopy(clg); u = cgetg(3,t_VEC);
310: y[6] = (long)u;
311: u[1] = lgetg(1,t_MAT);
312: u[2] = (long)idmat(RU);
313: return gerepileupto(av,y);
314: }
315: fa2 = (GEN)bid[4]; sarch = (GEN)fa2[lg(fa2)-1];
316:
317: cycgen = check_and_build_cycgen(bnf);
318: dataunit = cgetg(RU+1,t_MAT); racunit = gmael(bigres,4,2);
319: dataunit[1] = (long)zideallog(nf,racunit,bid);
320: for (j=2; j<=RU; j++)
321: dataunit[j] = (long)zideallog(nf,(GEN)funits[j-1],bid);
322: dataunit = concatsp(dataunit, diagonal(cycbid));
323: hmatu = hnfall(dataunit); hmat = (GEN)hmatu[1];
324:
325: logs = cgetg(ngen+1, t_MAT);
326: /* FIXME: cycgen[j] is not necessarily coprime to bid, but it is made coprime
327: * in zideallog using canonical uniformizers [from bid data]: no need to
328: * correct it here. The same ones will be used in isprincipalrayall. Hence
329: * modification by vecel is useless. */
330: for (j=1; j<=ngen; j++)
331: {
332: p1 = (GEN)cycgen[j];
333: if (typ(vecel[j]) != t_INT) /* <==> != 1 */
334: p1 = arch_mul(to_famat_all((GEN)vecel[j], (GEN)cyc[j]), p1);
335: logs[j] = (long)zideallog(nf,p1,bid); /* = log(genplus[j]) */
336: }
337: /* [ cyc 0 ]
338: * [-logs hmat] = relation matrix for Cl_f */
339: h = concatsp(
340: vconcat(diagonal(cyc), gneg_i(logs)),
341: vconcat(zeromat(ngen, Ri), hmat)
342: );
343: clh = compute_class_number(h,&met,&u1,NULL);
344: u1old = u1; lo = lg(met)-1;
345: for (c=1; c<=lo; c++)
346: if (gcmp1(gcoeff(met,c,c))) break;
347:
348: if (flag & nf_GEN)
349: {
350: GEN Id = idmat(degpol(nf[1])), arch = (GEN)module[2];
351: u1 = reducemodmatrix(u1,h);
352: genray = cgetg(c,t_VEC);
353: for (j=1; j<c; j++)
354: {
355: GEN *op, minus = Id, plus = Id;
356: long av1 = avma, s;
357: for (i=1; i<=lo; i++)
358: {
359: p1 = gcoeff(u1,i,j);
360: if (!(s = signe(p1))) continue;
361:
362: if (s > 0) op = + else { op = − p1 = negi(p1); }
363: p1 = idealpowmodidele(nf,(GEN)genplus[i],p1,x,sarch,arch);
364: *op = *op==Id? p1
365: : idealmulmodidele(nf,*op,p1,x,sarch,arch);
366: }
367: if (minus == Id) p1 = plus;
368: else
369: {
370: p2 = ideleaddone_aux(nf,minus,module);
371: p1 = idealdivexact(nf,idealmul(nf,p2,plus),minus);
372: p1 = idealmodidele(nf,p1,x,sarch,arch);
373: }
374: genray[j]=lpileupto(av1,p1);
375: }
376: clg = cgetg(4,t_VEC); clg[3] = lcopy(genray);
377: } else clg = cgetg(3,t_VEC);
378: clg[1] = licopy(clh); setlg(met,c);
379: clg[2] = (long)mattodiagonal(met);
380: if (!(flag & nf_INIT)) return gerepileupto(av,clg);
381:
382: u2 = cgetg(Ri+1,t_MAT);
383: u1 = cgetg(RU+1,t_MAT); u = (GEN)hmatu[2];
384: for (j=1; j<=RU; j++) { u1[j]=u[j]; setlg(u[j],RU+1); }
385: u += RU;
386: for (j=1; j<=Ri; j++) { u2[j]=u[j]; setlg(u[j],RU+1); }
387: p1 = lllint(u1); p2 = ginv(hmat);
388: y = cgetg(7,t_VEC);
389: y[1] = lcopy(bnf);
390: y[2] = lcopy(bid);
391: y[3] = lcopy(vecel);
392: y[4] = linv(u1old);
393: y[5] = lcopy(clg); u = cgetg(3,t_VEC);
394: y[6] = (long)u;
395: u[1] = lmul(u2,p2);
396: u[2] = lmul(u1,p1);
397: return gerepileupto(av,y);
398: }
399:
400: GEN
401: buchrayinitgen(GEN bnf, GEN ideal)
402: {
403: return buchrayall(bnf,ideal, nf_INIT | nf_GEN);
404: }
405:
406: GEN
407: buchrayinit(GEN bnf, GEN ideal)
408: {
409: return buchrayall(bnf,ideal, nf_INIT);
410: }
411:
412: GEN
413: buchray(GEN bnf, GEN ideal)
414: {
415: return buchrayall(bnf,ideal, nf_GEN);
416: }
417:
418: GEN
419: bnrclass0(GEN bnf, GEN ideal, long flag)
420: {
421: switch(flag)
422: {
423: case 0: flag = nf_GEN; break;
424: case 1: flag = nf_INIT; break;
425: case 2: flag = nf_INIT | nf_GEN; break;
426: default: err(flagerr,"bnrclass");
427: }
428: return buchrayall(bnf,ideal,flag);
429: }
430:
431: GEN
432: bnrinit0(GEN bnf, GEN ideal, long flag)
433: {
434: switch(flag)
435: {
436: case 0: flag = nf_INIT; break;
437: case 1: flag = nf_INIT | nf_GEN; break;
438: default: err(flagerr,"bnrinit");
439: }
440: return buchrayall(bnf,ideal,flag);
441: }
442:
443: GEN
444: rayclassno(GEN bnf,GEN ideal)
445: {
446: GEN nf,h,dataunit,racunit,bigres,bid,cycbid,funits,H;
447: long RU,i;
448: ulong av = avma;
449:
450: bnf = checkbnf(bnf); nf = (GEN)bnf[7];
451: bigres = (GEN)bnf[8]; h = gmael(bigres,1,1); /* class number */
452: bid = zidealstarinitall(nf,ideal,0);
453: cycbid = gmael(bid,2,2);
454: if (lg(cycbid) == 1) return gerepileuptoint(av, icopy(h));
455:
456: funits = check_units(bnf,"rayclassno");
457: RU = lg(funits); racunit = gmael(bigres,4,2);
458: dataunit = cgetg(RU+1,t_MAT);
459: dataunit[1] = (long)zideallog(nf,racunit,bid);
460: for (i=2; i<=RU; i++)
461: dataunit[i] = (long)zideallog(nf,(GEN)funits[i-1],bid);
462: dataunit = concatsp(dataunit, diagonal(cycbid));
463: H = hnfmodid(dataunit,(GEN)cycbid[1]); /* (Z_K/f)^* / units ~ Z^n / H */
464: return gerepileuptoint(av, mulii(h, dethnf_i(H)));
465: }
466:
467: GEN
468: quick_isprincipalgen(GEN bnf, GEN x)
469: {
470: GEN z = cgetg(3, t_VEC), gen = gmael3(bnf,8,1,3);
471: GEN idep, ep = isprincipal(bnf,x);
472: /* x \prod g[i]^(-ep[i]) = factorisation of principal ideal */
473: idep = isprincipalfact(bnf, gen, gneg(ep), x, nf_GENMAT | nf_GEN);
474: z[1] = (long)ep;
475: z[2] = idep[2]; return z;
476: }
477:
478: GEN
479: isprincipalrayall(GEN bnr, GEN x, long flag)
480: {
481: long av=avma,i,j,c;
482: GEN bnf,nf,bid,matu,vecel,ep,p1,beta,idep,y,rayclass;
483: GEN divray,genray,alpha,alphaall,racunit,res,funit;
484:
485: checkbnr(bnr);
486: bnf = (GEN)bnr[1]; nf = (GEN)bnf[7];
487: bid = (GEN)bnr[2];
488: vecel=(GEN)bnr[3];
489: matu =(GEN)bnr[4];
490: rayclass=(GEN)bnr[5];
491:
492: if (typ(x) == t_VEC && lg(x) == 3)
493: { idep = (GEN)x[2]; x = (GEN)x[1]; } /* precomputed */
494: else
495: idep = quick_isprincipalgen(bnf, x);
496: ep = (GEN)idep[1];
497: beta= (GEN)idep[2];
498: c = lg(ep);
499: for (i=1; i<c; i++) /* modify beta as if gen -> vecel.gen (coprime to bid) */
500: if (typ(vecel[i]) != t_INT && signe(ep[i])) /* <==> != 1 */
501: beta = arch_mul(to_famat_all((GEN)vecel[i], negi((GEN)ep[i])), beta);
502: p1 = gmul(matu, concatsp(ep, zideallog(nf,beta,bid)));
503: divray = (GEN)rayclass[2]; c = lg(divray);
504: y = cgetg(c,t_COL);
505: for (i=1; i<c; i++)
506: y[i] = lmodii((GEN)p1[i],(GEN)divray[i]);
507: if (!(flag & nf_GEN)) return gerepileupto(av, y);
508:
509: /* compute generator */
510: if (lg(rayclass)<=3)
511: err(talker,"please apply bnrinit(,,1) and not bnrinit(,,0)");
512:
513: genray = (GEN)rayclass[3];
514: /* TODO: should be using nf_GENMAT and function should return a famat */
515: alphaall = isprincipalfact(bnf, genray, gneg(y), x, nf_GEN | nf_FORCE);
516: if (!gcmp0((GEN)alphaall[1])) err(bugparier,"isprincipalray (bug1)");
517:
518: res = (GEN)bnf[8];
519: funit = check_units(bnf,"isprincipalrayall");
520: alpha = basistoalg(nf,(GEN)alphaall[2]);
521: p1 = zideallog(nf,(GEN)alphaall[2],bid);
522: if (lg(p1) > 1)
523: {
524: GEN mat = (GEN)bnr[6], pol = (GEN)nf[1];
525: p1 = gmul((GEN)mat[1],p1);
526: if (!gcmp1(denom(p1))) err(bugparier,"isprincipalray (bug2)");
527:
528: x = reducemodinvertible(p1,(GEN)mat[2]);
529: racunit = gmael(res,4,2);
530: p1 = powgi(gmodulcp(racunit,pol), (GEN)x[1]);
531: for (j=1; j<lg(funit); j++)
532: p1 = gmul(p1, powgi(gmodulcp((GEN)funit[j],pol), (GEN)x[j+1]));
533: alpha = gdiv(alpha,p1);
534: }
535: p1 = cgetg(4,t_VEC);
536: p1[1] = lcopy(y);
537: p1[2] = (long)algtobasis(nf,alpha);
538: p1[3] = lcopy((GEN)alphaall[3]);
539: return gerepileupto(av, p1);
540: }
541:
542: GEN
543: isprincipalray(GEN bnr, GEN x)
544: {
545: return isprincipalrayall(bnr,x,nf_REGULAR);
546: }
547:
548: GEN
549: isprincipalraygen(GEN bnr, GEN x)
550: {
551: return isprincipalrayall(bnr,x,nf_GEN);
552: }
553:
554: GEN
555: minkowski_bound(GEN D, long N, long r2, long prec)
556: {
557: long av = avma;
558: GEN p1;
559: p1 = gdiv(mpfactr(N,prec), gpowgs(stoi(N),N));
560: p1 = gmul(p1, gpowgs(gdivsg(4,mppi(prec)), r2));
561: p1 = gmul(p1, gsqrt(absi(D),prec));
562: return gerepileupto(av, p1);
563: }
564:
565: /* DK = |dK| */
566: static long
567: zimmertbound(long N,long R2,GEN DK)
568: {
569: long av = avma;
570: GEN w;
571:
572: if (N < 2) return 1;
573: if (N < 21)
574: {
575: static double c[21][11] = {
576: {/*2*/ 0.6931, 0.45158},
577: {/*3*/ 1.71733859, 1.37420604},
578: {/*4*/ 2.91799837, 2.50091538, 2.11943331},
579: {/*5*/ 4.22701425, 3.75471588, 3.31196660},
580: {/*6*/ 5.61209925, 5.09730381, 4.60693851, 4.14303665},
581: {/*7*/ 7.05406203, 6.50550021, 5.97735406, 5.47145968},
582: {/*8*/ 8.54052636, 7.96438858, 7.40555445, 6.86558259, 6.34608077},
583: {/*9*/ 10.0630022, 9.46382812, 8.87952524, 8.31139202, 7.76081149},
584: {/*10*/11.6153797, 10.9966020, 10.3907654, 9.79895170, 9.22232770, 8.66213267},
585: {/*11*/13.1930961, 12.5573772, 11.9330458, 11.3210061, 10.7222412, 10.1378082},
586: {/*12*/14.7926394, 14.1420915, 13.5016616, 12.8721114, 12.2542699, 11.6490374,
587: 11.0573775},
588: {/*13*/16.4112395, 15.7475710, 15.0929680, 14.4480777, 13.8136054, 13.1903162,
589: 12.5790381},
590: {/*14*/18.0466672, 17.3712806, 16.7040780, 16.0456127, 15.3964878, 14.7573587,
591: 14.1289364, 13.5119848},
592: {/*15*/19.6970961, 19.0111606, 18.3326615, 17.6620757, 16.9999233, 16.3467686,
593: 15.7032228, 15.0699480},
594: {/*16*/21.3610081, 20.6655103, 19.9768082, 19.2953176, 18.6214885, 17.9558093,
595: 17.2988108, 16.6510652, 16.0131906},
596:
597: {/*17*/23.0371259, 22.3329066, 21.6349299, 20.9435607, 20.2591899, 19.5822454,
598: 18.9131878, 18.2525157, 17.6007672},
599:
600: {/*18*/24.7243611, 24.0121449, 23.3056902, 22.6053167, 21.9113705, 21.2242247,
601: 20.5442836, 19.8719830, 19.2077941, 18.5522234},
602:
603: {/*19*/26.4217792, 25.7021950, 24.9879497, 24.2793271, 23.5766321, 22.8801952,
604: 22.1903709, 21.5075437, 20.8321263, 20.1645647},
605: {/*20*/28.1285704, 27.4021674, 26.6807314, 25.9645140, 25.2537867, 24.5488420,
606: 23.8499943, 23.1575823, 22.4719720, 21.7935548, 21.1227537}
607: };
608: w = gmul(dbltor(exp(-c[N-2][R2])), gsqrt(DK,MEDDEFAULTPREC));
609: }
610: else
611: {
612: w = minkowski_bound(DK, N, R2, MEDDEFAULTPREC);
613: if (cmpis(w, 500000))
614: err(warner,"large Minkowski bound: certification will be VERY long");
615: }
616: w = gceil(w);
617: if (is_bigint(w))
618: err(talker,"Minkowski bound is too large");
619: avma = av; return itos(w);
620: }
621:
622: /* all primes up to Minkowski bound factor on factorbase ? */
623: static void
624: testprime(GEN bnf, long minkowski)
625: {
626: ulong av = avma;
627: long pp,i,nbideal,k,pmax;
628: GEN f,p1,vectpp,fb,dK, nf=checknf(bnf);
629: byteptr delta = diffptr;
630:
631: if (DEBUGLEVEL>1)
632: fprintferr("PHASE 1: check primes to Zimmert bound = %ld\n\n",minkowski);
633: f=(GEN)nf[4]; dK=(GEN)nf[3];
634: if (!gcmp1(f))
635: {
636: GEN different = gmael(nf,5,5);
637: if (DEBUGLEVEL>1)
638: fprintferr("**** Testing Different = %Z\n",different);
639: p1 = isprincipalall(bnf,different,nf_FORCE);
640: if (DEBUGLEVEL>1) fprintferr(" is %Z\n",p1);
641: }
642: fb=(GEN)bnf[5];
643: p1 = gmael(fb, lg(fb)-1, 1); /* largest p in factorbase */
644: pp = 0; pmax = is_bigint(p1)? VERYBIGINT: itos(p1);
645: if ((ulong)minkowski > maxprime()) err(primer1);
646: while (pp < minkowski)
647: {
648: pp += *delta++;
649: if (DEBUGLEVEL>1) fprintferr("*** p = %ld\n",pp);
650: vectpp=primedec(bnf,stoi(pp)); nbideal=lg(vectpp)-1;
651: /* loop through all P | p if ramified, all but one otherwise */
652: if (!smodis(dK,pp)) nbideal++;
653: for (i=1; i<nbideal; i++)
654: {
655: GEN P = (GEN)vectpp[i];
656: if (DEBUGLEVEL>1)
657: fprintferr(" Testing P = %Z\n",P);
658: if (cmpis(idealnorm(bnf,P), minkowski) < 1)
659: {
660: if (pp <= pmax && (k = tablesearch(fb, P, cmp_prime_ideal)))
661: {
662: if (DEBUGLEVEL>1) fprintferr(" #%ld in factor base\n",k);
663: }
664: else
665: {
666: p1 = isprincipal(bnf,P);
667: if (DEBUGLEVEL>1) fprintferr(" is %Z\n",p1);
668: }
669: }
670: else if (DEBUGLEVEL>1)
671: fprintferr(" Norm(P) > Zimmert bound\n");
672: }
673: avma = av;
674: }
675: if (DEBUGLEVEL>1) { fprintferr("End of PHASE 1.\n\n"); flusherr(); }
676: }
677:
678: /* return \gamma_n^n if known, an upper bound otherwise */
679: static GEN
680: hermiteconstant(long n)
681: {
682: GEN h,h1;
683: long av;
684:
685: switch(n)
686: {
687: case 1: return gun;
688: case 2: h=cgetg(3,t_FRAC); h[1]=lstoi(4); h[2]=lstoi(3); return h;
689: case 3: return gdeux;
690: case 4: return stoi(4);
691: case 5: return stoi(8);
692: case 6: h=cgetg(3,t_FRAC); h[1]=lstoi(64); h[2]=lstoi(3); return h;
693: case 7: return stoi(64);
694: case 8: return stoi(256);
695: }
696: av = avma;
697: h = gpuigs(divsr(2,mppi(DEFAULTPREC)), n);
698: h1 = gsqr(ggamma(gdivgs(stoi(n+4),2),DEFAULTPREC));
699: return gerepileupto(av, gmul(h,h1));
700: }
701:
702: /* 1 if L (= nf != Q) primitive for sure, 0 if MAYBE imprimitive (may have a
703: * subfield K) */
704: static long
705: isprimitive(GEN nf)
706: {
707: long N,p,i,l,ep;
708: GEN d,fa;
709:
710: N = degpol(nf[1]); fa = (GEN)factor(stoi(N))[1]; /* primes | N */
711: p = itos((GEN)fa[1]); if (p == N) return 1; /* prime degree */
712:
713: /* N = [L:Q] = product of primes >= p, same is true for [L:K]
714: * d_L = t d_K^[L:K] --> check that some q^p divides d_L */
715: d = absi((GEN)nf[3]);
716: fa = (GEN)auxdecomp(d,0)[2]; /* list of v_q(d_L). Don't check large primes */
717: if (mod2(d)) i = 1;
718: else
719: { /* q = 2 */
720: ep = itos((GEN)fa[1]);
721: if ((ep>>1) >= p) return 0; /* 2 | d_K ==> 4 | d_K */
722: i = 2;
723: }
724: l = lg(fa);
725: for ( ; i < l; i++)
726: {
727: ep = itos((GEN)fa[i]);
728: if (ep >= p) return 0;
729: }
730: return 1;
731: }
732:
733: static GEN
734: regulatorbound(GEN bnf)
735: {
736: long N,R1,R2,R;
737: GEN nf,dKa,bound,p1,c1;
738:
739: nf = (GEN)bnf[7]; N = degpol(nf[1]);
740: bound = dbltor(0.2);
741: if (!isprimitive(nf))
742: {
743: if (DEBUGLEVEL>1) fprintferr("Default bound for regulator: 0.2\n");
744: return bound;
745: }
746: dKa = absi((GEN)nf[3]);
747: R1 = itos(gmael(nf,2,1));
748: R2 = itos(gmael(nf,2,2)); R = R1+R2-1;
749: if (!R2 && N<12) c1 = gpuigs(stoi(4),N>>1); else c1 = gpuigs(stoi(N),N);
750: if (cmpii(dKa,c1) <= 0)
751: {
752: if (DEBUGLEVEL>1) fprintferr("Default bound for regulator: 0.2\n");
753: return bound;
754: }
755: p1 = gsqr(glog(gdiv(dKa,c1),DEFAULTPREC));
756: p1 = gdivgs(gmul2n(gpuigs(gdivgs(gmulgs(p1,3),N*(N*N-1)-6*R2),R),R2),N);
757: p1 = gsqrt(gdiv(p1, hermiteconstant(R)), DEFAULTPREC);
758: if (gcmp(p1,bound) > 0) bound = p1;
759: if (DEBUGLEVEL>1) fprintferr("Mahler bound for regulator: %Z\n",p1);
760: return bound;
761: }
762:
763: /* x given by its embeddings */
764: GEN
765: norm_by_embed(long r1, GEN x)
766: {
767: long i, ru = lg(x)-1;
768: GEN p = (GEN)x[ru];
769: if (r1 == ru)
770: {
771: for (i=ru-1; i>0; i--) p = gmul(p, (GEN)x[i]);
772: return p;
773: }
774: p = gnorm(p);
775: for (i=ru-1; i>r1; i--) p = gmul(p, gnorm((GEN)x[i]));
776: for ( ; i>0 ; i--) p = gmul(p, (GEN)x[i]);
777: return p;
778: }
779:
780: static int
781: is_unit(GEN M, long r1, GEN x)
782: {
783: long av = avma;
784: GEN Nx = ground( norm_by_embed(r1, gmul_mat_smallvec(M,x)) );
785: int ok = is_pm1(Nx);
786: avma = av; return ok;
787: }
788:
789: #define NBMAX 5000
790: /* FIXME: should use smallvectors */
791: static GEN
792: minimforunits(GEN nf, long BORNE, long stockmax)
793: {
794: const long prec = MEDDEFAULTPREC;
795: long av = avma,n,i,j,k,s,norme,normax,*x,cmpt,r1;
796: GEN u,r,S,a,M,p1;
797: double p;
798: double **q,*v,*y,*z;
799: double eps=0.000001, BOUND = BORNE + eps;
800:
801: if (DEBUGLEVEL>=2)
802: {
803: fprintferr("Searching minimum of T2-form on units:\n");
804: if (DEBUGLEVEL>2) fprintferr(" BOUND = %ld\n",BOUND);
805: flusherr();
806: }
807: r1 = nf_get_r1(nf);
808: a = gmael(nf,5,3); n = lg(a);
809: minim_alloc(n, &q, &x, &y, &z, &v);
810: n--;
811: u = lllgram(a,prec);
812: M = gmul(gmael(nf,5,1), u); /* embeddings of T2-reduced basis */
813: M = gprec_w(M, prec);
814: a = gmul(qf_base_change(a,u,1), realun(prec));
815: r = sqred1(a);
816: for (j=1; j<=n; j++)
817: {
818: v[j] = rtodbl(gcoeff(r,j,j));
819: for (i=1; i<j; i++) q[i][j] = rtodbl(gcoeff(r,i,j));
820: }
821: normax=0;
822: S = cgetg(stockmax+1,t_MAT);
823: s=0; k=n; cmpt=0; y[n]=z[n]=0;
824: x[n]=(long)(sqrt(BOUND/v[n]));
825:
826: for(;;)
827: {
828: do
829: {
830: if (k>1)
831: {
832: long l = k-1;
833: z[l] = 0;
834: for (j=k; j<=n; j++) z[l] = z[l]+q[l][j]*x[j];
835: p = x[k]+z[k];
836: y[l] = y[k]+p*p*v[k];
837: x[l] = (long)floor(sqrt((BOUND-y[l])/v[l])-z[l]);
838: k = l;
839: }
840: for(;;)
841: {
842: p = x[k]+z[k];
843: if (y[k] + p*p*v[k] <= BOUND) break;
844: k++; x[k]--;
845: }
846: }
847: while (k>1);
848: if (!x[1] && y[1]<=eps) break;
849: if (++cmpt > NBMAX) { av=avma; return NULL; }
850:
851: if (DEBUGLEVEL>8){ fprintferr("."); flusherr(); }
852: p = x[1]+z[1]; norme = (long)(y[1] + p*p*v[1] + eps);
853: if (norme > normax) normax = norme;
854: if (is_unit(M,r1, x))
855: {
856: if (DEBUGLEVEL>=2) { fprintferr("*"); flusherr(); }
857: cmpt = 0;
858: if (++s <= stockmax)
859: {
860: p1 = cgetg(n+1,t_COL);
861: for (i=1; i<=n; i++) p1[i]=lstoi(x[i]);
862: S[s] = lmul(u,p1);
863: }
864: }
865: x[k]--;
866: }
867: if (DEBUGLEVEL>=2){ fprintferr("\n"); flusherr(); }
868: k = (s<stockmax)? s:stockmax; setlg(S,k+1);
869: S = gerepilecopy(av, S);
870: u = cgetg(4,t_VEC);
871: u[1] = lstoi(s<<1);
872: u[2] = lstoi(normax);
873: u[3] = (long)S; return u;
874: }
875:
876: #undef NBMAX
877: static int
878: is_zero(GEN x, long bitprec) { return (gexpo(x) < -bitprec); }
879:
880: static int
881: is_complex(GEN x, long bitprec) { return (!is_zero(gimag(x), bitprec)); }
882:
883: static GEN
884: compute_M0(GEN M_star,long N)
885: {
886: long m1,m2,n1,n2,n3,k,kk,lr,lr1,lr2,i,j,l,vx,vy,vz,vM,prec;
887: GEN pol,p1,p2,p3,p4,p5,p6,p7,p8,p9,u,v,w,r,r1,r2,M0,M0_pro,S,P,M;
888: GEN f1,f2,f3,g1,g2,g3,pg1,pg2,pg3,pf1,pf2,pf3,X,Y,Z;
889: long bitprec = 24, PREC = gprecision(M_star);
890:
891: if (N==2) return gmul2n(gsqr(gach(gmul2n(M_star,-1),PREC)), -1);
892: vM = fetch_var(); M = polx[vM];
893: vz = fetch_var(); Z = polx[vz];
894: vy = fetch_var(); Y = polx[vy];
895: vx = fetch_var(); X = polx[vx];
896:
897: PREC = PREC>>1; if (!PREC) PREC = DEFAULTPREC;
898: M0 = NULL; m1 = N/3;
899: for (n1=1; n1<=m1; n1++)
900: {
901: m2 = (N-n1)>>1;
902: for (n2=n1; n2<=m2; n2++)
903: {
904: long av = avma; n3=N-n1-n2; prec=PREC;
905: if (n1==n2 && n1==n3) /* n1 = n2 = n3 = m1 = N/3 */
906: {
907: p1=gdivgs(M_star,m1);
908: p2=gaddsg(1,p1);
909: p3=gsubgs(p1,3);
910: p4=gsqrt(gmul(p2,p3),prec);
911: p5=gsubgs(p1,1);
912: u=gun;
913: v=gmul2n(gadd(p5,p4),-1);
914: w=gmul2n(gsub(p5,p4),-1);
915: M0_pro=gmul2n(gmulsg(m1,gadd(gsqr(glog(v,prec)),gsqr(glog(w,prec)))),-2);
916: if (DEBUGLEVEL>2)
917: {
918: fprintferr("[ %ld, %ld, %ld ]: %Z\n",n1,n2,n3,gprec_w(M0_pro,3));
919: flusherr();
920: }
921: if (!M0 || gcmp(M0_pro,M0)<0) M0 = M0_pro;
922: }
923: else if (n1==n2 || n2==n3)
924: { /* n3 > N/3 >= n1 */
925: k = n2; kk = N-2*k;
926: p2=gsub(M_star,gmulgs(X,k));
927: p3=gmul(gpuigs(stoi(kk),kk),gpuigs(gsubgs(gmul(M_star,p2),kk*kk),k));
928: pol=gsub(p3,gmul(gmul(gpuigs(stoi(k),k),gpuigs(X,k)),gpuigs(p2,N-k)));
929: prec=gprecision(pol); if (!prec) prec = MEDDEFAULTPREC;
930: r=roots(pol,prec); lr = lg(r);
931: for (i=1; i<lr; i++)
932: {
933: if (is_complex((GEN)r[i], bitprec) ||
934: signe(S = greal((GEN)r[i])) <= 0) continue;
935:
936: p4=gsub(M_star,gmulsg(k,S));
937: P=gdiv(gmul(gmulsg(k,S),p4),gsubgs(gmul(M_star,p4),kk*kk));
938: p5=gsub(gsqr(S),gmul2n(P,2));
939: if (gsigne(p5) < 0) continue;
940:
941: p6=gsqrt(p5,prec);
942: v=gmul2n(gsub(S,p6),-1);
943: if (gsigne(v) <= 0) continue;
944:
945: u=gmul2n(gadd(S,p6),-1);
946: w=gpui(P,gdivgs(stoi(-k),kk),prec);
947: p6=gmulsg(k,gadd(gsqr(glog(u,prec)),gsqr(glog(v,prec))));
948: M0_pro=gmul2n(gadd(p6,gmulsg(kk,gsqr(glog(w,prec)))),-2);
949: if (DEBUGLEVEL>2)
950: {
951: fprintferr("[ %ld, %ld, %ld ]: %Z\n",n1,n2,n3,gprec_w(M0_pro,3));
952: flusherr();
953: }
954: if (!M0 || gcmp(M0_pro,M0)<0) M0 = M0_pro;
955: }
956: }
957: else
958: {
959: f1 = gsub(gadd(gmulsg(n1,X),gadd(gmulsg(n2,Y),gmulsg(n3,Z))), M);
960: f2 = gmulsg(n1,gmul(Y,Z));
961: f2 = gadd(f2,gmulsg(n2,gmul(X,Z)));
962: f2 = gadd(f2,gmulsg(n3,gmul(X,Y)));
963: f2 = gsub(f2,gmul(M,gmul(X,gmul(Y,Z))));
964: f3 = gsub(gmul(gpuigs(X,n1),gmul(gpuigs(Y,n2),gpuigs(Z,n3))), gun);
965: /* f1 = n1 X + n2 Y + n3 Z - M */
966: /* f2 = n1 YZ + n2 XZ + n3 XY */
967: /* f3 = X^n1 Y^n2 Z^n3 - 1*/
968: g1=subres(f1,f2); g1=gdiv(g1,content(g1));
969: g2=subres(f1,f3); g2=gdiv(g2,content(g2));
970: g3=subres(g1,g2); g3=gdiv(g3,content(g3));
971: pf1=gsubst(f1,vM,M_star); pg1=gsubst(g1,vM,M_star);
972: pf2=gsubst(f2,vM,M_star); pg2=gsubst(g2,vM,M_star);
973: pf3=gsubst(f3,vM,M_star); pg3=gsubst(g3,vM,M_star);
974: prec=gprecision(pg3); if (!prec) prec = MEDDEFAULTPREC;
975: r=roots(pg3,prec); lr = lg(r);
976: for (i=1; i<lr; i++)
977: {
978: if (is_complex((GEN)r[i], bitprec) ||
979: signe(w = greal((GEN)r[i])) <= 0) continue;
980: p1=gsubst(pg1,vz,w);
981: p2=gsubst(pg2,vz,w);
982: p3=gsubst(pf1,vz,w);
983: p4=gsubst(pf2,vz,w);
984: p5=gsubst(pf3,vz,w);
985: prec=gprecision(p1); if (!prec) prec = MEDDEFAULTPREC;
986: r1 = roots(p1,prec); lr1 = lg(r1);
987: for (j=1; j<lr1; j++)
988: {
989: if (is_complex((GEN)r1[j], bitprec)
990: || signe(v = greal((GEN)r1[j])) <= 0
991: || !is_zero(gsubst(p2,vy,v), bitprec)) continue;
992:
993: p7=gsubst(p3,vy,v);
994: p8=gsubst(p4,vy,v);
995: p9=gsubst(p5,vy,v);
996: prec=gprecision(p7); if (!prec) prec = MEDDEFAULTPREC;
997: r2 = roots(p7,prec); lr2 = lg(r2);
998: for (l=1; l<lr2; l++)
999: {
1000: if (is_complex((GEN)r2[l], bitprec)
1001: || signe(u = greal((GEN)r2[l])) <= 0
1002: || !is_zero(gsubst(p8,vx,u), bitprec)
1003: || !is_zero(gsubst(p9,vx,u), bitprec)) continue;
1004:
1005: M0_pro = gmulsg(n1,gsqr(mplog(u)));
1006: M0_pro = gadd(M0_pro, gmulsg(n2,gsqr(mplog(v))));
1007: M0_pro = gadd(M0_pro, gmulsg(n3,gsqr(mplog(w))));
1008: M0_pro = gmul2n(M0_pro,-2);
1009: if (DEBUGLEVEL>2)
1010: {
1011: fprintferr("[ %ld, %ld, %ld ]: %Z\n",n1,n2,n3,gprec_w(M0_pro,3));
1012: flusherr();
1013: }
1014: if (!M0 || gcmp(M0_pro,M0) < 0) M0 = M0_pro;
1015: }
1016: }
1017: }
1018: }
1019: if (!M0) avma = av; else M0 = gerepilecopy(av, M0);
1020: }
1021: }
1022: for (i=1;i<=4;i++) delete_var();
1023: return M0? M0: gzero;
1024: }
1025:
1026: static GEN
1027: lowerboundforregulator_i(GEN bnf)
1028: {
1029: long N,R1,R2,RU,i,nbrootsofone,nbmin;
1030: GEN rootsofone,nf,M0,M,m,col,T2,bound,minunit,newminunit;
1031: GEN vecminim,colalg,p1,pol,y;
1032: GEN units = check_units(bnf,"bnfcertify");
1033:
1034: rootsofone=gmael(bnf,8,4); nbrootsofone=itos((GEN)rootsofone[1]);
1035: nf=(GEN)bnf[7]; T2=gmael(nf,5,3); N=degpol(nf[1]);
1036: R1=itos(gmael(nf,2,1)); R2=itos(gmael(nf,2,2)); RU=R1+R2-1;
1037: if (RU==0) return gun;
1038:
1039: units=algtobasis(bnf,units); minunit=qfeval(T2,(GEN)units[1]);
1040: for (i=2; i<=RU; i++)
1041: {
1042: newminunit=qfeval(T2,(GEN)units[i]);
1043: if (gcmp(newminunit,minunit)<0) minunit=newminunit;
1044: }
1045: if (gcmpgs(minunit,1000000000)>0) return NULL;
1046:
1047: vecminim = minimforunits(nf,itos(gceil(minunit)),10000);
1048: if (!vecminim) return NULL;
1049: m=(GEN)vecminim[3]; nbmin=lg(m)-1;
1050: if (nbmin==10000) return NULL;
1051: bound=gaddgs(minunit,1);
1052: for (i=1; i<=nbmin; i++)
1053: {
1054: col=(GEN)m[i]; colalg=basistoalg(nf,col);
1055: if (!gcmp1(lift_intern(gpuigs(colalg,nbrootsofone))))
1056: {
1057: newminunit=qfeval(T2,col);
1058: if (gcmp(newminunit,bound)<0) bound=newminunit;
1059: }
1060: }
1061: if (gcmp(bound,minunit)>0) err(talker,"bug in lowerboundforregulator");
1062: if (DEBUGLEVEL>1)
1063: {
1064: fprintferr("M* = %Z\n",gprec_w(bound,3));
1065: if (DEBUGLEVEL>2)
1066: {
1067: p1=polx[0]; pol=gaddgs(gsub(gpuigs(p1,N),gmul(bound,p1)),N-1);
1068: p1 = roots(pol,DEFAULTPREC);
1069: if (N&1) y=greal((GEN)p1[3]); else y=greal((GEN)p1[2]);
1070: M0 = gmul2n(gmulsg(N*(N-1),gsqr(glog(y,DEFAULTPREC))),-2);
1071: fprintferr("pol = %Z\n",pol);
1072: fprintferr("old method: y = %Z, M0 = %Z\n",y,gprec_w(M0,3));
1073: }
1074: flusherr();
1075: }
1076: M0 = compute_M0(bound,N);
1077: if (DEBUGLEVEL>1) { fprintferr("M0 = %Z\n",gprec_w(M0,3)); flusherr(); }
1078: M = gmul2n(gdivgs(gdiv(gpuigs(M0,RU),hermiteconstant(RU)),N),R2);
1079: if (gcmp(M,dbltor(0.04))<0) return NULL;
1080: M = gsqrt(M,DEFAULTPREC);
1081: if (DEBUGLEVEL>1)
1082: {
1083: fprintferr("(lower bound for regulator) M = %Z\n",gprec_w(M,3));
1084: flusherr();
1085: }
1086: return M;
1087: }
1088:
1089: static GEN
1090: lowerboundforregulator(GEN bnf)
1091: {
1092: long av = avma;
1093: GEN x = lowerboundforregulator_i(bnf);
1094: if (!x) { avma = av; x = regulatorbound(bnf); }
1095: return x;
1096: }
1097:
1098: extern GEN to_Fp_simple(GEN x, GEN prh);
1099: extern GEN Fp_PHlog(GEN a, GEN g, GEN p, GEN ord);
1100:
1101: /* Compute a square matrix of rank length(beta) associated to a family
1102: * (P_i), 1<=i<=length(beta), of primes s.t. N(P_i) = 1 mod pp, and
1103: * (P_i,beta[j]) = 1 for all i,j */
1104: static void
1105: primecertify(GEN bnf,GEN beta,long pp,GEN big)
1106: {
1107: long i,j,qq,nbcol,lb,nbqq,ra,N;
1108: GEN nf,mat,mat1,qgen,decqq,newcol,Qh,Q,g,ord;
1109:
1110: ord = NULL; /* gcc -Wall */
1111: nbcol = 0; nf = (GEN)bnf[7]; N = degpol(nf[1]);
1112: lb = lg(beta)-1; mat = cgetg(1,t_MAT); qq = 1;
1113: for(;;)
1114: {
1115: qq += 2*pp; qgen = stoi(qq);
1116: if (smodis(big,qq)==0 || !isprime(qgen)) continue;
1117:
1118: decqq = primedec(bnf,qgen); nbqq = lg(decqq)-1;
1119: g = NULL;
1120: for (i=1; i<=nbqq; i++)
1121: {
1122: Q = (GEN)decqq[i]; if (!gcmp1((GEN)Q[4])) break;
1123: /* Q has degree 1 */
1124: if (!g)
1125: {
1126: g = lift_intern(gener(qgen)); /* primitive root */
1127: ord = decomp(stoi(qq-1));
1128: }
1129: Qh = prime_to_ideal(nf,Q);
1130: newcol = cgetg(lb+1,t_COL);
1131: for (j=1; j<=lb; j++)
1132: {
1133: GEN t = to_Fp_simple((GEN)beta[j], Qh);
1134: newcol[j] = (long)Fp_PHlog(t,g,qgen,ord);
1135: }
1136: if (DEBUGLEVEL>3)
1137: {
1138: if (i==1) fprintferr(" generator of (Zk/Q)^*: %Z\n", g);
1139: fprintferr(" prime ideal Q: %Z\n",Q);
1140: fprintferr(" column #%ld of the matrix log(b_j/Q): %Z\n",
1141: nbcol, newcol);
1142: }
1143: mat1 = concatsp(mat,newcol); ra = rank(mat1);
1144: if (ra==nbcol) continue;
1145:
1146: if (DEBUGLEVEL>2) fprintferr(" new rank: %ld\n\n",ra);
1147: if (++nbcol == lb) return;
1148: mat = mat1;
1149: }
1150: }
1151: }
1152:
1153: static void
1154: check_prime(long p, GEN bnf, GEN cyc, GEN cycgen, GEN fu, GEN mu, GEN big)
1155: {
1156: ulong av = avma;
1157: long i,b, lc = lg(cyc), w = itos((GEN)mu[1]), lf = lg(fu);
1158: GEN beta = cgetg(lf+lc, t_VEC);
1159:
1160: if (DEBUGLEVEL>1) fprintferr(" *** testing p = %ld\n",p);
1161: for (b=1; b<lc; b++)
1162: {
1163: if (smodis((GEN)cyc[b], p)) break; /* p \nmod cyc[b] */
1164: if (b==1 && DEBUGLEVEL>2) fprintferr(" p divides h(K)\n");
1165: beta[b] = cycgen[b];
1166: }
1167: if (w % p == 0)
1168: {
1169: if (DEBUGLEVEL>2) fprintferr(" p divides w(K)\n");
1170: beta[b++] = mu[2];
1171: }
1172: for (i=1; i<lf; i++) beta[b++] = fu[i];
1173: setlg(beta, b); /* beta = [cycgen[i] if p|cyc[i], tu if p|w, fu] */
1174: if (DEBUGLEVEL>3) {fprintferr(" Beta list = %Z\n",beta); flusherr();}
1175: primecertify(bnf,beta,p,big); avma = av;
1176: }
1177:
1178: long
1179: certifybuchall(GEN bnf)
1180: {
1181: ulong av = avma;
1182: long nbgen,i,j,p,N,R1,R2,R,bound;
1183: GEN big,nf,reg,rootsofone,funits,gen,p1,gbound,cycgen,cyc;
1184: byteptr delta = diffptr;
1185:
1186: bnf = checkbnf(bnf); nf = (GEN)bnf[7];
1187: N=degpol(nf[1]); if (N==1) return 1;
1188: R1=itos(gmael(nf,2,1)); R2=itos(gmael(nf,2,2)); R=R1+R2-1;
1189: funits = check_units(bnf,"bnfcertify");
1190: testprime(bnf, zimmertbound(N,R2,absi((GEN)nf[3])));
1191: reg = gmael(bnf,8,2);
1192: cyc = gmael3(bnf,8,1,2); nbgen = lg(cyc)-1;
1193: gen = gmael3(bnf,8,1,3); rootsofone = gmael(bnf,8,4);
1194: gbound = ground(gdiv(reg,lowerboundforregulator(bnf)));
1195: if (is_bigint(gbound))
1196: err(talker,"sorry, too many primes to check");
1197:
1198: bound = itos(gbound); if ((ulong)bound > maxprime()) err(primer1);
1199: if (DEBUGLEVEL>1)
1200: {
1201: fprintferr("\nPHASE 2: are all primes good ?\n\n");
1202: fprintferr(" Testing primes <= B (= %ld)\n\n",bound); flusherr();
1203: }
1204: cycgen = check_and_build_cycgen(bnf);
1205: for (big=gun,i=1; i<=nbgen; i++)
1206: big = mpppcm(big, gcoeff(gen[i],1,1));
1207: for (i=1; i<=nbgen; i++)
1208: {
1209: p1 = (GEN)cycgen[i];
1210: if (typ(p1) == t_MAT)
1211: {
1212: GEN h, g = (GEN)p1[1];
1213: for (j=1; j<lg(g); j++)
1214: {
1215: h = idealhermite(nf, (GEN)g[j]);
1216: big = mpppcm(big, gcoeff(h,1,1));
1217: }
1218: }
1219: } /* p | big <--> p | some cycgen[i] */
1220:
1221: funits = dummycopy(funits);
1222: for (i=1; i<lg(funits); i++)
1223: funits[i] = (long)algtobasis(nf, (GEN)funits[i]);
1224: rootsofone = dummycopy(rootsofone);
1225: rootsofone[2] = (long)algtobasis(nf, (GEN)rootsofone[2]);
1226:
1227: for (p = *delta++; p <= bound; p += *delta++)
1228: check_prime(p,bnf,cyc,cycgen,funits,rootsofone,big);
1229:
1230: if (nbgen)
1231: {
1232: GEN f = factor((GEN)cyc[1]), f1 = (GEN)f[1];
1233: long nbf1 = lg(f1);
1234: if (DEBUGLEVEL>1) { fprintferr(" Testing primes | h(K)\n\n"); flusherr(); }
1235: for (i=1; i<nbf1; i++)
1236: {
1237: p = itos((GEN)f1[i]);
1238: if (p > bound) check_prime(p,bnf,cyc,cycgen,funits,rootsofone,big);
1239: }
1240: }
1241: avma=av; return 1;
1242: }
1243:
1244: /*******************************************************************/
1245: /* */
1246: /* RAY CLASS FIELDS: CONDUCTORS AND DISCRIMINANTS */
1247: /* */
1248: /*******************************************************************/
1249:
1250: /* s: <gen> = Cl_f --> Cl_n --> 0, H subgroup of Cl_f (generators given as
1251: * HNF on [gen]). Return subgroup s(H) in Cl_n (associated to bnr) */
1252: static GEN
1253: imageofgroup0(GEN gen,GEN bnr,GEN H)
1254: {
1255: long j,l;
1256: GEN E,Delta = diagonal(gmael(bnr,5,2)); /* SNF structure of Cl_n */
1257:
1258: if (!H || gcmp0(H)) return Delta;
1259:
1260: l=lg(gen); E=cgetg(l,t_MAT);
1261: for (j=1; j<l; j++) /* compute s(gen) */
1262: E[j] = (long)isprincipalray(bnr,(GEN)gen[j]);
1263: return hnf(concatsp(gmul(E,H), Delta)); /* s(H) in Cl_n */
1264: }
1265:
1266: static GEN
1267: imageofgroup(GEN gen,GEN bnr,GEN H)
1268: {
1269: ulong av = avma;
1270: return gerepileupto(av,imageofgroup0(gen,bnr,H));
1271: }
1272:
1273: /* see imageofgroup0, return [Cl_f : s(H)], H given on gen */
1274: static GEN
1275: orderofquotient(GEN bnf, GEN f, GEN H, GEN gen)
1276: {
1277: GEN bnr;
1278: if (!H) return rayclassno(bnf,f);
1279: bnr = buchrayall(bnf,f,nf_INIT);
1280: return dethnf_i(imageofgroup0(gen,bnr,H));
1281: }
1282:
1283: static GEN
1284: args_to_bnr(GEN arg0, GEN arg1, GEN arg2, GEN *subgroup)
1285: {
1286: GEN bnr,bnf;
1287:
1288: if (typ(arg0)!=t_VEC)
1289: err(talker,"neither bnf nor bnr in conductor or discray");
1290: if (!arg1) arg1 = gzero;
1291: if (!arg2) arg2 = gzero;
1292:
1293: switch(lg(arg0))
1294: {
1295: case 7: /* bnr */
1296: bnr=arg0; (void)checkbnf((GEN)bnr[1]);
1297: *subgroup=arg1; break;
1298:
1299: case 11: /* bnf */
1300: bnf = checkbnf(arg0);
1301: bnr=buchrayall(bnf,arg1,nf_INIT | nf_GEN);
1302: *subgroup=arg2; break;
1303:
1304: default: err(talker,"neither bnf nor bnr in conductor or discray");
1305: return NULL; /* not reached */
1306: }
1307: if (!gcmp0(*subgroup))
1308: {
1309: long tx=typ(*subgroup);
1310: if (!is_matvec_t(tx))
1311: err(talker,"bad subgroup in conductor or discray");
1312: }
1313: return bnr;
1314: }
1315:
1316: GEN
1317: bnrconductor(GEN arg0,GEN arg1,GEN arg2,long all)
1318: {
1319: GEN sub=arg1, bnr=args_to_bnr(arg0,arg1,arg2,&sub);
1320: return conductor(bnr,sub,all);
1321: }
1322:
1323: long
1324: bnrisconductor(GEN arg0,GEN arg1,GEN arg2)
1325: {
1326: GEN sub=arg1, bnr=args_to_bnr(arg0,arg1,arg2,&sub);
1327: return itos(conductor(bnr,sub,-1));
1328: }
1329:
1330: /* special for isprincipalrayall */
1331: static GEN
1332: getgen(GEN bnf, GEN gen)
1333: {
1334: long i,l = lg(gen);
1335: GEN p1, g = cgetg(l, t_VEC);
1336: for (i=1; i<l; i++)
1337: {
1338: p1 = cgetg(3,t_VEC); g[i] = (long)p1;
1339: p1[1] = (long)gen[i];
1340: p1[2] = (long)quick_isprincipalgen(bnf, (GEN)gen[i]);
1341: }
1342: return g;
1343: }
1344:
1345: /* Given a number field bnf=bnr[1], a ray class group structure bnr (from
1346: * buchrayinit), and a subgroup H (HNF form) of the ray class group, compute
1347: * the conductor of H (copy of discrayrelall) if all=0. If all > 0, compute
1348: * furthermore the corresponding H' and output
1349: * if all = 1: [[ideal,arch],[hm,cyc,gen],H']
1350: * if all = 2: [[ideal,arch],newbnr,H']
1351: * if all < 0, answer only 1 is module is the conductor, 0 otherwise. */
1352: GEN
1353: conductor(GEN bnr, GEN H, long all)
1354: {
1355: ulong av = avma;
1356: long r1,j,k,ep;
1357: GEN bnf,nf,gen,bid,ideal,arch,p1,clhray,clhss,fa,arch2,bnr2,P,ex,mod;
1358:
1359: checkbnrgen(bnr);
1360: bnf = (GEN)bnr[1];
1361: bid = (GEN)bnr[2];
1362: clhray = gmael(bnr,5,1); gen = gmael(bnr,5,3);
1363: nf = (GEN)bnf[7]; r1 = nf_get_r1(nf);
1364: ideal= gmael(bid,1,1);
1365: arch = gmael(bid,1,2);
1366: if (gcmp0(H)) H = NULL;
1367: else
1368: {
1369: p1 = gauss(H, diagonal(gmael(bnr,5,2)));
1370: if (!gcmp1(denom(p1))) err(talker,"incorrect subgroup in conductor");
1371: p1 = absi(det(H));
1372: if (egalii(p1, clhray)) H = NULL; else clhray = p1;
1373: }
1374: /* H = NULL --> trivial subgroup, else precompute isprincipal(gen) */
1375: if (H || all > 0) gen = getgen(bnf, gen);
1376:
1377: fa = (GEN)bid[3];
1378: P = (GEN)fa[1];
1379: ex = (GEN)fa[2];
1380: mod = cgetg(3,t_VEC); mod[2] = (long)arch;
1381: for (k=1; k<lg(ex); k++)
1382: {
1383: GEN pr = (GEN)P[k];
1384: ep = (all>=0)? itos((GEN)ex[k]): 1;
1385: for (j=1; j<=ep; j++)
1386: {
1387: mod[1] = (long)idealdivexact(nf,ideal,pr);
1388: clhss = orderofquotient(bnf,mod,H,gen);
1389: if (!egalii(clhss,clhray)) break;
1390: if (all < 0) { avma = av; return gzero; }
1391: ideal = (GEN)mod[1];
1392: }
1393: }
1394: mod[1] = (long)ideal; arch2 = dummycopy(arch);
1395: mod[2] = (long)arch2;
1396: for (k=1; k<=r1; k++)
1397: if (signe(arch[k]))
1398: {
1399: arch2[k] = zero;
1400: clhss = orderofquotient(bnf,mod,H,gen);
1401: if (!egalii(clhss,clhray)) { arch2[k] = un; continue; }
1402: if (all < 0) { avma = av; return gzero; }
1403: }
1404: if (all < 0) { avma = av; return gun; }
1405: if (!all) return gerepilecopy(av, mod);
1406:
1407: bnr2 = buchrayall(bnf,mod,nf_INIT | nf_GEN);
1408: p1 = cgetg(4,t_VEC);
1409: p1[3] = (long)imageofgroup(gen,bnr2,H);
1410: if (all==1) bnr2 = (GEN)bnr2[5];
1411: p1[2] = lcopy(bnr2);
1412: p1[1] = lcopy(mod); return gerepileupto(av, p1);
1413: }
1414:
1415: /* etant donne un bnr et un polynome relatif, trouve le groupe des normes
1416: correspondant a l'extension relative en supposant qu'elle est abelienne
1417: et que le module donnant bnr est multiple du conducteur. Verifie que
1418: l'extension est bien abelienne (sous GRH) si rnf != NULL, dans ce cas
1419: rnf est le rnf de l'extension relative. */
1420: static GEN
1421: rnfnormgroup0(GEN bnr, GEN polrel, GEN rnf)
1422: {
1423: long av=avma,i,j,reldeg,sizemat,p,pmax,nfac,k;
1424: GEN bnf,polreldisc,discnf,nf,raycl,group,detgroup,fa,greldeg;
1425: GEN contreld,primreld,reldisc,famo,ep,fac,col,p1,bd,upnf;
1426: byteptr d = diffptr + 1; /* start at p = 2 */
1427:
1428: checkbnr(bnr); bnf=(GEN)bnr[1]; raycl=(GEN)bnr[5];
1429: nf=(GEN)bnf[7];
1430: polrel = fix_relative_pol(nf,polrel,1);
1431: if (typ(polrel)!=t_POL) err(typeer,"rnfnormgroup");
1432: reldeg=degpol(polrel);
1433: /* reldeg-th powers are in norm group */
1434: greldeg = stoi(reldeg);
1435: group = diagonal(gmod((GEN)raycl[2], greldeg));
1436: for (i=1; i<lg(group); i++)
1437: if (!signe(gcoeff(group,i,i))) coeff(group,i,i) = (long)greldeg;
1438: detgroup = dethnf_i(group);
1439: k = cmpis(detgroup,reldeg);
1440: if (k<0)
1441: {
1442: if (rnf) return NULL;
1443: err(talker,"not an Abelian extension in rnfnormgroup?");
1444: }
1445: if (!rnf && !k) return gerepilecopy(av, group);
1446:
1447: polreldisc=discsr(polrel);
1448:
1449: if (rnf)
1450: {
1451: reldisc=gmael(rnf,3,1);
1452: upnf=nfinit0(gmael(rnf,11,1),1,DEFAULTPREC);
1453: }
1454: else
1455: {
1456: reldisc = idealhermite(nf,polreldisc);
1457: upnf = NULL;
1458: }
1459:
1460: reldisc = idealmul(nf, reldisc, gmael3(bnr,2,1,1));
1461: contreld= content(reldisc);
1462: primreld= gcmp1(contreld)? reldisc: gdiv(reldisc, contreld);
1463:
1464: discnf = (GEN)nf[3];
1465: k = degpol(nf[1]);
1466: bd = gmulsg(k, glog(absi(discnf), DEFAULTPREC));
1467: bd = gadd(bd,glog(mpabs(det(reldisc)),DEFAULTPREC));
1468: p1 = dbltor(reldeg * k * 2.5 + 5);
1469: bd = gfloor(gsqr(gadd(gmulsg(4,bd),p1)));
1470:
1471: pmax = is_bigint(bd)? 0: itos(bd);
1472: if (rnf)
1473: {
1474: if (DEBUGLEVEL) fprintferr("rnfnormgroup: bound for primes = %Z\n", bd);
1475: if (!pmax) err(warner,"rnfnormgroup: prime bound too large, can't certify");
1476: }
1477: sizemat=lg(group)-1;
1478: for (p=2; !pmax || p < pmax; p += *d++)
1479: {
1480: long oldf = -1, lfa;
1481: /* If all pr are unramified and have the same residue degree, p =prod pr
1482: * and including last pr^f or p^f is the same, but the last isprincipal
1483: * is much easier! oldf is used to track this */
1484:
1485: if (!*d) err(primer1);
1486: if (!smodis(contreld,p)) continue; /* all pr|p ramified */
1487:
1488: fa = primedec(nf,stoi(p)); lfa = lg(fa)-1;
1489:
1490: for (i=1; i<=lfa; i++)
1491: {
1492: GEN pr = (GEN)fa[i];
1493: long f;
1494: /* check decomposition of pr has Galois type */
1495: if (element_val(nf,polreldisc,pr) != 0)
1496: {
1497: /* if pr ramified, we will have to use all (non-ram) P | pr */
1498: if (idealval(nf,primreld,pr)!=0) { oldf = 0; continue; }
1499:
1500: famo=idealfactor(upnf,rnfidealup(rnf,pr));
1501: ep=(GEN)famo[2];
1502: fac=(GEN)famo[1];
1503: nfac=lg(ep)-1;
1504: f = itos(gmael(fac,1,4));
1505: for (j=1; j<=nfac; j++)
1506: {
1507: if (!gcmp1((GEN)ep[j])) err(bugparier,"rnfnormgroup");
1508: if (itos(gmael(fac,j,4)) != f)
1509: {
1510: if (rnf) return NULL;
1511: err(talker,"non Galois extension in rnfnormgroup");
1512: }
1513: }
1514: }
1515: else
1516: {
1517: famo=nffactormod(nf,polrel,pr);
1518: ep=(GEN)famo[2];
1519: fac=(GEN)famo[1];
1520: nfac=lg(ep)-1;
1521: f = degpol((GEN)fac[1]);
1522: for (j=1; j<=nfac; j++)
1523: {
1524: if (!gcmp1((GEN)ep[j])) err(bugparier,"rnfnormgroup");
1525: if (degpol(fac[j]) != f)
1526: {
1527: if (rnf) return NULL;
1528: err(talker,"non Galois extension in rnfnormgroup");
1529: }
1530: }
1531: }
1532: if (oldf < 0) oldf = f; else if (oldf != f) oldf = 0;
1533: if (f == reldeg) continue; /* reldeg-th powers already included */
1534:
1535: if (oldf && i == lfa && !smodis(discnf, p)) pr = stoi(p);
1536:
1537: /* pr^f = N P, P | pr, hence is in norm group */
1538: col = gmulsg(f, isprincipalrayall(bnr,pr,nf_REGULAR));
1539: group = hnf(concatsp(group, col));
1540: detgroup = dethnf_i(group);
1541: k = cmpis(detgroup,reldeg);
1542: if (k < 0)
1543: {
1544: if (rnf) return NULL;
1545: err(talker,"not an Abelian extension in rnfnormgroup");
1546: }
1547: if (!rnf && !k) { cgiv(detgroup); return gerepileupto(av,group); }
1548: }
1549: }
1550: if (k>0) err(bugparier,"rnfnormgroup");
1551: cgiv(detgroup); return gerepileupto(av,group);
1552: }
1553:
1554: GEN
1555: rnfnormgroup(GEN bnr, GEN polrel)
1556: {
1557: return rnfnormgroup0(bnr,polrel,NULL);
1558: }
1559:
1560: /* Etant donne un bnf et un polynome relatif polrel definissant une extension
1561: abelienne, calcule le conducteur et le groupe de congruence correspondant
1562: a l'extension definie par polrel sous la forme
1563: [[ideal,arch],[hm,cyc,gen],group] ou [ideal,arch] est le conducteur, et
1564: [hm,cyc,gen] est le groupe de classes de rayon correspondant. Verifie
1565: (sous GRH) que polrel definit bien une extension abelienne si flag != 0 */
1566: GEN
1567: rnfconductor(GEN bnf, GEN polrel, long flag)
1568: {
1569: long av=avma,tetpil,R1,i,v;
1570: GEN nf,module,rnf,arch,bnr,group,p1,pol2;
1571:
1572: bnf = checkbnf(bnf); nf=(GEN)bnf[7];
1573: if (typ(polrel)!=t_POL) err(typeer,"rnfconductor");
1574: module=cgetg(3,t_VEC); R1=itos(gmael(nf,2,1));
1575: v=varn(polrel);
1576: p1=unifpol((GEN)bnf[7],polrel,0);
1577: p1=denom(gtovec(p1));
1578: pol2=gsubst(polrel,v,gdiv(polx[v],p1));
1579: pol2=gmul(pol2,gpuigs(p1,degpol(pol2)));
1580: if (flag)
1581: {
1582: rnf=rnfinitalg(bnf,pol2,DEFAULTPREC);
1583: module[1]=mael(rnf,3,1);
1584: }
1585: else
1586: {
1587: rnf=NULL;
1588: module[1]=rnfdiscf(nf,pol2)[1];
1589: }
1590: arch=cgetg(R1+1,t_VEC);
1591: module[2]=(long)arch; for (i=1; i<=R1; i++) arch[i]=un;
1592: bnr=buchrayall(bnf,module,nf_INIT | nf_GEN);
1593: group=rnfnormgroup0(bnr,pol2,rnf);
1594: if (!group) { avma = av; return gzero; }
1595: tetpil=avma;
1596: return gerepile(av,tetpil,conductor(bnr,group,1));
1597: }
1598:
1599: /* Given a number field bnf=bnr[1], a ray class group structure
1600: * bnr (from buchrayinit), and a subgroup H (HNF form) of the ray class
1601: * group, compute [n, r1, dk] associated to H (cf. discrayall).
1602: * If flcond = 1, abort (return gzero) if module is not the conductor
1603: * If flrel = 0, compute only N(dk) instead of the ideal dk proper */
1604: static GEN
1605: discrayrelall(GEN bnr, GEN H, long flag)
1606: {
1607: ulong av = avma;
1608: long r1,j,k,ep, nz, flrel = flag & nf_REL, flcond = flag & nf_COND;
1609: GEN bnf,nf,gen,bid,ideal,arch,p1,clhray,clhss,fa,arch2,idealrel,P,ex,mod,dlk;
1610:
1611: checkbnrgen(bnr);
1612: bnf = (GEN)bnr[1];
1613: bid = (GEN)bnr[2];
1614: clhray = gmael(bnr,5,1); gen = gmael(bnr,5,3);
1615: nf = (GEN)bnf[7]; r1 = nf_get_r1(nf);
1616: ideal= gmael(bid,1,1);
1617: arch = gmael(bid,1,2);
1618: if (gcmp0(H)) H = NULL;
1619: else
1620: {
1621: p1 = gauss(H, diagonal(gmael(bnr,5,2)));
1622: if (!gcmp1(denom(p1))) err(talker,"incorrect subgroup in discray");
1623: p1 = absi(det(H));
1624: if (egalii(p1, clhray)) H = NULL; else clhray = p1;
1625: }
1626: /* H = NULL --> trivial subgroup, else precompute isprincipal(gen) */
1627: if (H) gen = getgen(bnf,gen);
1628:
1629: fa = (GEN)bid[3];
1630: P = (GEN)fa[1];
1631: ex = (GEN)fa[2];
1632: mod = cgetg(3,t_VEC); mod[2] = (long)arch;
1633:
1634: idealrel = flrel? idmat(degpol(nf[1])): gun;
1635: for (k=1; k<lg(P); k++)
1636: {
1637: GEN pr = (GEN)P[k], S = gzero;
1638: ep = itos((GEN)ex[k]);
1639: mod[1] = (long)ideal;
1640: for (j=1; j<=ep; j++)
1641: {
1642: mod[1] = (long)idealdivexact(nf,(GEN)mod[1],pr);
1643: clhss = orderofquotient(bnf,mod,H,gen);
1644: if (flcond && j==1 && egalii(clhss,clhray)) { avma = av; return gzero; }
1645: if (is_pm1(clhss)) { S = addis(S, ep-j+1); break; }
1646: S = addii(S, clhss);
1647: }
1648: idealrel = flrel? idealmul(nf,idealrel, idealpow(nf,pr, S))
1649: : mulii(idealrel, powgi(idealnorm(nf,pr),S));
1650: }
1651: dlk = flrel? idealdivexact(nf,idealpow(nf,ideal,clhray), idealrel)
1652: : divii(powgi(dethnf_i(ideal),clhray), idealrel);
1653:
1654: mod[1] = (long)ideal; arch2 = dummycopy(arch);
1655: mod[2] = (long)arch2; nz = 0;
1656: for (k=1; k<=r1; k++)
1657: {
1658: if (signe(arch[k]))
1659: {
1660: arch2[k] = zero;
1661: clhss = orderofquotient(bnf,mod,H,gen);
1662: if (!egalii(clhss,clhray)) { arch2[k] = un; continue; }
1663: if (flcond) { avma = av; return gzero; }
1664: }
1665: nz++;
1666: }
1667: p1 = cgetg(4,t_VEC);
1668: p1[1] = lcopy(clhray);
1669: p1[2] = lstoi(nz);
1670: p1[3] = lcopy(dlk); return gerepileupto(av, p1);
1671: }
1672:
1673: static GEN
1674: discrayabsall(GEN bnr, GEN subgroup,long flag)
1675: {
1676: ulong av = avma;
1677: long degk,clhray,n,R1;
1678: GEN z,p1,D,dk,nf,dkabs,bnf;
1679:
1680: D = discrayrelall(bnr,subgroup,flag);
1681: if (flag & nf_REL) return D;
1682: if (D == gzero) { avma = av; return gzero; }
1683:
1684: bnf = (GEN)bnr[1]; nf = (GEN)bnf[7];
1685: degk = degpol(nf[1]);
1686: dkabs = absi((GEN)nf[3]);
1687: dk = (GEN)D[3];
1688: clhray = itos((GEN)D[1]); p1 = gpowgs(dkabs, clhray);
1689: n = clhray * degk;
1690: R1= clhray * itos((GEN)D[2]);
1691: if (((n-R1)&3)==2) dk = negi(dk); /* (2r2) mod 4 = 2 : r2(relext) is odd */
1692: z = cgetg(4,t_VEC);
1693: z[1] = lstoi(n);
1694: z[2] = lstoi(R1);
1695: z[3] = lmulii(dk,p1); return gerepileupto(av, z);
1696: }
1697:
1698: GEN
1699: bnrdisc0(GEN arg0, GEN arg1, GEN arg2, long flag)
1700: {
1701: GEN H, bnr = args_to_bnr(arg0,arg1,arg2,&H);
1702: return discrayabsall(bnr,H,flag);
1703: }
1704:
1705: GEN
1706: discrayrel(GEN bnr, GEN H)
1707: {
1708: return discrayrelall(bnr,H,nf_REL);
1709: }
1710:
1711: GEN
1712: discrayrelcond(GEN bnr, GEN H)
1713: {
1714: return discrayrelall(bnr,H,nf_REL | nf_COND);
1715: }
1716:
1717: GEN
1718: discrayabs(GEN bnr, GEN H)
1719: {
1720: return discrayabsall(bnr,H,nf_REGULAR);
1721: }
1722:
1723: GEN
1724: discrayabscond(GEN bnr, GEN H)
1725: {
1726: return discrayabsall(bnr,H,nf_COND);
1727: }
1728:
1729: /* Given a number field bnf=bnr[1], a ray class group structure bnr and a
1730: * vector chi representing a character on the generators bnr[2][3], compute
1731: * the conductor of chi. */
1732: GEN
1733: bnrconductorofchar(GEN bnr, GEN chi)
1734: {
1735: ulong av = avma;
1736: long nbgen,i;
1737: GEN p1,m,U,d1,cyc;
1738:
1739: checkbnrgen(bnr);
1740: cyc = gmael(bnr,5,2); nbgen = lg(cyc)-1;
1741: if (lg(chi)-1 != nbgen)
1742: err(talker,"incorrect character length in conductorofchar");
1743: if (!nbgen) return conductor(bnr,gzero,0);
1744:
1745: d1 = (GEN)cyc[1]; m = cgetg(nbgen+2,t_MAT);
1746: for (i=1; i<=nbgen; i++)
1747: {
1748: if (typ(chi[i]) != t_INT) err(typeer,"conductorofchar");
1749: p1 = cgetg(2,t_COL); m[i] = (long)p1;
1750: p1[1] = lmulii((GEN)chi[i], divii(d1, (GEN)cyc[i]));
1751: }
1752: p1 = cgetg(2,t_COL); m[i] = (long)p1;
1753: p1[1] = (long)d1; U = (GEN)hnfall(m)[2];
1754: setlg(U,nbgen+1);
1755: for (i=1; i<=nbgen; i++) setlg(U[i],nbgen+1); /* U = Ker chi */
1756: return gerepileupto(av, conductor(bnr,U,0));
1757: }
1758:
1759: /* Given lists of [zidealstarinit, unit ideallogs], return lists of ray class
1760: * numbers */
1761: GEN
1762: rayclassnolist(GEN bnf,GEN lists)
1763: {
1764: ulong av = avma;
1765: long i,j,lx,ly;
1766: GEN blist,ulist,Llist,h,b,u,L,m;
1767:
1768: if (typ(lists)!=t_VEC || lg(lists)!=3) err(typeer,"rayclassnolist");
1769: bnf = checkbnf(bnf); h = gmael3(bnf,8,1,1);
1770: blist = (GEN)lists[1];
1771: ulist = (GEN)lists[2];
1772: lx = lg(blist); Llist = cgetg(lx,t_VEC);
1773: for (i=1; i<lx; i++)
1774: {
1775: b = (GEN)blist[i]; /* bid's */
1776: u = (GEN)ulist[i]; /* units zideallogs */
1777: ly = lg(b); L = cgetg(ly,t_VEC); Llist[i] = (long)L;
1778: for (j=1; j<ly; j++)
1779: {
1780: GEN bid = (GEN)b[j], cyc = gmael(bid,2,2);
1781: m = concatsp((GEN)u[j], diagonal(cyc));
1782: L[j] = lmulii(h, dethnf_i(hnf(m)));
1783: }
1784: }
1785: return gerepilecopy(av, Llist);
1786: }
1787:
1788: static long
1789: rayclassnolists(GEN sous, GEN sousclass, GEN fac)
1790: {
1791: long i;
1792: for (i=1; i<lg(sous); i++)
1793: if (gegal(gmael(sous,i,3),fac)) return itos((GEN)sousclass[i]);
1794: err(bugparier,"discrayabslist");
1795: return 0; /* not reached */
1796: }
1797:
1798: static GEN
1799: rayclassnolistessimp(GEN sous, GEN fac)
1800: {
1801: long i;
1802: for (i=1; i<lg(sous); i++)
1803: if (gegal(gmael(sous,i,1),fac)) return gmael(sous,i,2);
1804: err(bugparier,"discrayabslistlong");
1805: return NULL; /* not reached */
1806: }
1807:
1808: static GEN
1809: factormul(GEN fa1,GEN fa2)
1810: {
1811: GEN p,pnew,e,enew,v,P, y = cgetg(3,t_MAT);
1812: long i,c,lx;
1813:
1814: p = concatsp((GEN)fa1[1],(GEN)fa2[1]); y[1] = (long)p;
1815: e = concatsp((GEN)fa1[2],(GEN)fa2[2]); y[2] = (long)e;
1816: v = sindexsort(p); lx = lg(p);
1817: pnew = cgetg(lx,t_COL); for (i=1; i<lx; i++) pnew[i] = p[v[i]];
1818: enew = cgetg(lx,t_COL); for (i=1; i<lx; i++) enew[i] = e[v[i]];
1819: P = gzero; c = 0;
1820: for (i=1; i<lx; i++)
1821: {
1822: if (gegal((GEN)pnew[i],P))
1823: e[c] = laddii((GEN)e[c],(GEN)enew[i]);
1824: else
1825: {
1826: c++; P = (GEN)pnew[i];
1827: p[c] = (long)P;
1828: e[c] = enew[i];
1829: }
1830: }
1831: setlg(p, c+1);
1832: setlg(e, c+1); return y;
1833: }
1834:
1835: static GEN
1836: factordivexact(GEN fa1,GEN fa2)
1837: {
1838: long i,j,k,c,lx1,lx2;
1839: GEN Lpr,Lex,y,Lpr1,Lex1,Lpr2,Lex2,p1;
1840:
1841: Lpr1 = (GEN)fa1[1]; Lex1 = (GEN)fa1[2]; lx1 = lg(Lpr1);
1842: Lpr2 = (GEN)fa2[1]; Lex2 = (GEN)fa2[2]; lx2 = lg(Lpr1);
1843: y = cgetg(3,t_MAT);
1844: Lpr = cgetg(lx1,t_COL); y[1] = (long)Lpr;
1845: Lex = cgetg(lx1,t_COL); y[2] = (long)Lex;
1846: for (c=0,i=1; i<lx1; i++)
1847: {
1848: j = isinvector(Lpr2,(GEN)Lpr1[i],lx2-1);
1849: if (!j) { c++; Lpr[c] = Lpr1[i]; Lex[c] = Lex1[i]; }
1850: else
1851: {
1852: p1 = subii((GEN)Lex1[i], (GEN)Lex2[j]); k = signe(p1);
1853: if (k<0) err(talker,"factordivexact is not exact!");
1854: if (k>0) { c++; Lpr[c] = Lpr1[i]; Lex[c] = (long)p1; }
1855: }
1856: }
1857: setlg(Lpr,c+1);
1858: setlg(Lex,c+1); return y;
1859: }
1860:
1861: static GEN
1862: factorpow(GEN fa,long n)
1863: {
1864: GEN y;
1865: if (!n) return trivfact();
1866: y = cgetg(3,t_MAT);
1867: y[1] = fa[1];
1868: y[2] = lmulsg(n, (GEN)fa[2]); return y;
1869: }
1870:
1871: /* Etant donne la liste des zidealstarinit et des matrices d'unites
1872: * correspondantes, sort la liste des discrayabs. On ne garde pas les modules
1873: * qui ne sont pas des conducteurs
1874: */
1875: GEN
1876: discrayabslist(GEN bnf,GEN lists)
1877: {
1878: ulong av = avma;
1879: long ii,jj,i,j,k,clhss,ep,clhray,lx,ly,r1,degk,nz;
1880: long n,R1,lP;
1881: GEN hlist,blist,dlist,nf,dkabs,b,h,d;
1882: GEN z,ideal,arch,fa,P,ex,idealrel,mod,pr,dlk,arch2,p3,fac;
1883:
1884: hlist = rayclassnolist(bnf,lists);
1885: blist = (GEN)lists[1];
1886: lx = lg(hlist); dlist = cgetg(lx,t_VEC);
1887: nf = (GEN)bnf[7]; r1 = nf_get_r1(nf);
1888: degk = degpol(nf[1]); dkabs = absi((GEN)nf[3]);
1889: nz = 0; dlk = NULL; /* gcc -Wall */
1890: for (ii=1; ii<lx; ii++)
1891: {
1892: b = (GEN)blist[ii]; /* zidealstarinits */
1893: h = (GEN)hlist[ii]; /* class numbers */
1894: ly = lg(b); d = cgetg(ly,t_VEC); dlist[ii] = (long)d; /* discriminants */
1895: for (jj=1; jj<ly; jj++)
1896: {
1897: GEN fac1,fac2, bid = (GEN)b[jj];
1898: clhray = itos((GEN)h[jj]);
1899: ideal= gmael(bid,1,1);
1900: arch = gmael(bid,1,2);
1901: fa = (GEN)bid[3]; fac = dummycopy(fa);
1902: P = (GEN)fa[1]; fac1 = (GEN)fac[1];
1903: ex= (GEN)fa[2]; fac2 = (GEN)fac[2];
1904: lP = lg(P)-1; idealrel = trivfact();
1905: for (k=1; k<=lP; k++)
1906: {
1907: GEN normp;
1908: long S = 0, normps, normi;
1909: pr = (GEN)P[k]; ep = itos((GEN)ex[k]);
1910: normi = ii; normps = itos(idealnorm(nf,pr));
1911: for (j=1; j<=ep; j++)
1912: {
1913: GEN fad, fad1, fad2;
1914: if (j < ep) { fac2[k] = lstoi(ep-j); fad = fac; }
1915: else
1916: {
1917: fad = cgetg(3,t_MAT);
1918: fad1 = cgetg(lP,t_COL); fad[1] = (long)fad1;
1919: fad2 = cgetg(lP,t_COL); fad[2] = (long)fad2;
1920: for (i=1; i< k; i++) { fad1[i] = fac1[i]; fad2[i] = fac2[i]; }
1921: for ( ; i<lP; i++) { fad1[i] = fac1[i+1];fad2[i] = fac2[i+1]; }
1922: }
1923: normi /= normps;
1924: clhss = rayclassnolists((GEN)blist[normi],(GEN)hlist[normi], fad);
1925: if (j==1 && clhss==clhray)
1926: {
1927: clhray = 0; fac2[k] = ex[k]; goto LLDISCRAY;
1928: }
1929: if (clhss == 1) { S += ep-j+1; break; }
1930: S += clhss;
1931: }
1932: fac2[k] = ex[k];
1933: normp = to_famat_all((GEN)pr[1], (GEN)pr[4]);
1934: idealrel = factormul(idealrel, factorpow(normp,S));
1935: }
1936: dlk = factordivexact(factorpow(factor(stoi(ii)),clhray), idealrel);
1937: mod = cgetg(3,t_VEC);
1938: mod[1] = (long)ideal; arch2 = dummycopy(arch);
1939: mod[2] = (long)arch2; nz = 0;
1940: for (k=1; k<=r1; k++)
1941: {
1942: if (signe(arch[k]))
1943: {
1944: arch2[k] = zero;
1945: clhss = itos(rayclassno(bnf,mod));
1946: arch2[k] = un;
1947: if (clhss == clhray) { clhray = 0; break; }
1948: }
1949: else nz++;
1950: }
1951: LLDISCRAY:
1952: if (!clhray) { d[jj] = lgetg(1,t_VEC); continue; }
1953:
1954: p3 = factorpow(factor(dkabs),clhray);
1955: n = clhray * degk;
1956: R1= clhray * nz;
1957: if (((n-R1)&3) == 2) /* r2 odd, set dlk = -dlk */
1958: dlk = factormul(to_famat_all(stoi(-1),gun), dlk);
1959: z = cgetg(4,t_VEC);
1960: z[1] = lstoi(n);
1961: z[2] = lstoi(R1);
1962: z[3] = (long)factormul(dlk,p3);
1963: d[jj] = (long)z;
1964: }
1965: }
1966: return gerepilecopy(av, dlist);
1967: }
1968:
1969: #define SHLGVINT 15
1970: #define LGVINT (1L << SHLGVINT)
1971:
1972: /* Attention: bound est le nombre de vraies composantes voulues. */
1973: static GEN
1974: bigcgetvec(long bound)
1975: {
1976: long nbcext,nbfinal,i;
1977: GEN vext;
1978:
1979: nbcext = ((bound-1)>>SHLGVINT)+1;
1980: nbfinal = bound-((nbcext-1)<<SHLGVINT);
1981: vext = cgetg(nbcext+1,t_VEC);
1982: for (i=1; i<nbcext; i++) vext[i] = lgetg(LGVINT+1,t_VEC);
1983: vext[nbcext] = lgetg(nbfinal+1,t_VEC); return vext;
1984: }
1985:
1986: static GEN
1987: getcompobig(GEN vext,long i)
1988: {
1989: long cext;
1990:
1991: if (i<=LGVINT) return gmael(vext,1,i);
1992: cext = ((i-1)>>SHLGVINT)+1;
1993: return gmael(vext, cext, i-((cext-1)<<SHLGVINT));
1994: }
1995:
1996: static void
1997: putcompobig(GEN vext,long i,GEN x)
1998: {
1999: long cext;
2000:
2001: if (i<=LGVINT) { mael(vext,1,i)=(long)x; return; }
2002: cext=((i-1)>>SHLGVINT)+1;
2003: mael(vext, cext, i-((cext-1)<<SHLGVINT)) = (long)x;
2004: }
2005:
2006: static GEN
2007: zsimp(GEN bid, GEN matunit)
2008: {
2009: GEN y = cgetg(5,t_VEC);
2010: y[1] = bid[3];
2011: y[2] = mael(bid,2,2);
2012: y[3] = bid[5];
2013: y[4] = (long)matunit; return y;
2014: }
2015:
2016: static GEN
2017: zsimpjoin(GEN bidsimp, GEN bidp, GEN dummyfa, GEN matunit)
2018: {
2019: long i,l1,l2,nbgen,c, av = avma;
2020: GEN U,U1,U2,cyc1,cyc2,cyc,u1u2,met, y = cgetg(5,t_VEC);
2021:
2022: y[1] = (long)vconcat((GEN)bidsimp[1],dummyfa);
2023: U1 = (GEN)bidsimp[3]; cyc1 = (GEN)bidsimp[2]; l1 = lg(cyc1);
2024: U2 = (GEN)bidp[5]; cyc2 = gmael(bidp,2,2); l2 = lg(cyc2);
2025: nbgen = l1+l2-2;
2026: if (nbgen)
2027: {
2028: cyc = diagonal(concatsp(cyc1,cyc2));
2029: u1u2 = matsnf0(cyc, 1 | 4); /* all && clean */
2030: U = (GEN)u1u2[1];
2031: met=(GEN)u1u2[3];
2032: y[3] = (long)concatsp(
2033: l1==1 ? zeromat(nbgen, lg(U1)-1): gmul(vecextract_i(U, 1, l1-1), U1) ,
2034: l1>nbgen? zeromat(nbgen, lg(U2)-1): gmul(vecextract_i(U, l1, nbgen), U2)
2035: );
2036: }
2037: else
2038: {
2039: c = lg(U1)+lg(U2)-1; U = cgetg(c,t_MAT);
2040: for (i=1; i<c; i++) U[i]=lgetg(1,t_COL);
2041: met = cgetg(1,t_MAT);
2042: y[3] = (long)U;
2043: }
2044: c = lg(met); cyc = cgetg(c,t_VEC);
2045: for (i=1; i<c; i++) cyc[i] = coeff(met,i,i);
2046: y[2] = (long)cyc;
2047: y[4] = (long)vconcat((GEN)bidsimp[4],matunit);
2048: return gerepilecopy(av, y);
2049: }
2050:
2051: static GEN
2052: rayclassnointern(GEN blist, GEN h)
2053: {
2054: long lx,j;
2055: GEN bid,qm,L,cyc,m,z;
2056:
2057: lx = lg(blist); L = cgetg(lx,t_VEC);
2058: for (j=1; j<lx; j++)
2059: {
2060: bid = (GEN)blist[j];
2061: qm = gmul((GEN)bid[3],(GEN)bid[4]);
2062: cyc = (GEN)bid[2];
2063: m = concatsp(qm, diagonal(cyc));
2064: z = cgetg(3,t_VEC); L[j] = (long)z;
2065: z[1] = bid[1];
2066: z[2] = lmulii(h, dethnf_i(hnf(m)));
2067: }
2068: return L;
2069: }
2070:
2071: void rowselect_p(GEN A, GEN B, GEN p, long init);
2072:
2073: static GEN
2074: rayclassnointernarch(GEN blist, GEN h, GEN matU)
2075: {
2076: long lx,nc,k,kk,j,r1,jj,nba,nbarch;
2077: GEN _2,bid,qm,Lray,cyc,m,z,z2,mm,rowsel;
2078:
2079: if (!matU) return rayclassnointern(blist,h);
2080: lx = lg(blist); if (lx == 1) return blist;
2081:
2082: r1 = lg(matU[1])-1; _2 = gscalmat(gdeux,r1);
2083: Lray = cgetg(lx,t_VEC); nbarch = 1<<r1;
2084: for (j=1; j<lx; j++)
2085: {
2086: bid = (GEN)blist[j];
2087: qm = gmul((GEN)bid[3],(GEN)bid[4]);
2088: cyc = (GEN)bid[2]; nc = lg(cyc)-1;
2089: /* [ qm cyc 0 ]
2090: * [ matU 0 2 ] */
2091: m = concatsp3(vconcat(qm, matU),
2092: vconcat(diagonal(cyc), zeromat(r1,nc)),
2093: vconcat(zeromat(nc,r1), _2));
2094: m = hnf(m); mm = dummycopy(m);
2095: z2 = cgetg(nbarch+1,t_VEC);
2096: rowsel = cgetg(nc+r1+1,t_VECSMALL);
2097: for (k = 0; k < nbarch; k++)
2098: {
2099: nba = nc+1;
2100: for (kk=k,jj=1; jj<=r1; jj++,kk>>=1)
2101: if (kk&1) rowsel[nba++] = nc + jj;
2102: setlg(rowsel, nba);
2103: rowselect_p(m, mm, rowsel, nc+1);
2104: z2[k+1] = lmulii(h, dethnf_i(hnf(mm)));
2105: }
2106: z = cgetg(3,t_VEC); Lray[j] = (long)z;
2107: z[1] = bid[1];
2108: z[2] = (long)z2;
2109: }
2110: return Lray;
2111: }
2112:
2113: GEN
2114: decodemodule(GEN nf, GEN fa)
2115: {
2116: long n,k,j,fauxpr,av=avma;
2117: GEN g,e,id,pr;
2118:
2119: nf = checknf(nf);
2120: if (typ(fa)!=t_MAT || lg(fa)!=3)
2121: err(talker,"incorrect factorisation in decodemodule");
2122: n = degpol(nf[1]); id = idmat(n);
2123: g = (GEN)fa[1];
2124: e = (GEN)fa[2];
2125: for (k=1; k<lg(g); k++)
2126: {
2127: fauxpr = itos((GEN)g[k]);
2128: j = (fauxpr%n)+1; fauxpr /= n*n;
2129: pr = (GEN)primedec(nf,stoi(fauxpr))[j];
2130: id = idealmul(nf,id, idealpow(nf,pr,(GEN)e[k]));
2131: }
2132: return gerepileupto(av,id);
2133: }
2134:
2135: /* Do all from scratch, bound < 2^30. For the time being, no subgroups.
2136: * Ouput: vector vext whose components vint have exactly 2^LGVINT entries
2137: * but for the last one which is allowed to be shorter. vext[i][j]
2138: * (where j<=2^LGVINT) is understood as component number I = (i-1)*2^LGVINT+j
2139: * in a unique huge vector V. Such a component V[I] is a vector indexed by
2140: * all ideals of norm I. Given such an ideal m_0, the component is as follows:
2141: *
2142: * + if arch = NULL, run through all possible archimedean parts, the archs
2143: * are ordered using inverse lexicographic order, [0,..,0], [1,0,..,0],
2144: * [0,1,..,0],... Component is [m_0,V] where V is a vector with
2145: * 2^r1 entries, giving for each arch the triple [N,R1,D], with N, R1, D
2146: * as in discrayabs [D is in factored form]
2147: *
2148: * + otherwise [m_0,arch,N,R1,D]
2149: *
2150: * If ramip != 0 and -1, keep only modules which are squarefree outside ramip
2151: * If ramip < 0, archsquare. (????)
2152: */
2153: static GEN
2154: discrayabslistarchintern(GEN bnf, GEN arch, long bound, long ramip)
2155: {
2156: byteptr ptdif=diffptr;
2157: long degk,i,j,k,p2s,lfa,lp1,sqbou,cex, allarch;
2158: long ffs,fs,resp,flbou,nba, k2,karch,kka,nbarch,jjj,jj,square;
2159: long ii2,ii,ly,clhray,lP,ep,S,clhss,normps,normi,nz,r1,R1,n,c;
2160: ulong q, av0 = avma, av,av1,lim;
2161: GEN nf,p,z,p1,p2,p3,fa,pr,normp,ideal,bidp,z2,matarchunit;
2162: GEN funits,racunit,embunit,sous,clh,sousray,raylist;
2163: GEN clhrayall,discall,faall,Id,idealrel,idealrelinit;
2164: GEN sousdisc,mod,P,ex,fac,fadkabs,pz;
2165: GEN arch2,dlk,disclist,p4,faussefa,fauxpr,gprime;
2166: GEN *gptr[2];
2167:
2168: if (bound <= 0) err(talker,"non-positive bound in discrayabslist");
2169: clhray = nz = 0; /* gcc -Wall */
2170: mod = Id = dlk = ideal = clhrayall = discall = faall = NULL;
2171:
2172: /* ce qui suit recopie d'assez pres ideallistzstarall */
2173: if (DEBUGLEVEL>2) timer2();
2174: bnf = checkbnf(bnf); flbou=0;
2175: nf = (GEN)bnf[7]; r1 = nf_get_r1(nf);
2176: degk = degpol(nf[1]);
2177: fadkabs = factor(absi((GEN)nf[3]));
2178: clh = gmael3(bnf,8,1,1);
2179: racunit = gmael3(bnf,8,4,2);
2180: funits = check_units(bnf,"discrayabslistarchintern");
2181:
2182: if (ramip >= 0) square = 0;
2183: else
2184: {
2185: square = 1; ramip = -ramip;
2186: if (ramip==1) ramip=0;
2187: }
2188: nba = 0; allarch = (arch==NULL);
2189: if (allarch)
2190: { arch=cgetg(r1+1,t_VEC); for (i=1; i<=r1; i++) arch[i]=un; nba=r1; }
2191: else if (gcmp0(arch))
2192: { arch=cgetg(r1+1,t_VEC); for (i=1; i<=r1; i++) arch[i]=zero; }
2193: else
2194: {
2195: if (lg(arch)!=r1+1)
2196: err(talker,"incorrect archimedean argument in discrayabslistarchintern");
2197: for (i=1; i<=r1; i++) if (signe(arch[i])) nba++;
2198: if (nba) mod = cgetg(3,t_VEC);
2199: }
2200: p1 = cgetg(3,t_VEC);
2201: p1[1] = (long)idmat(degk);
2202: p1[2] = (long)arch; bidp = zidealstarinitall(nf,p1,0);
2203: if (allarch)
2204: {
2205: matarchunit = logunitmatrix(nf,funits,racunit,bidp);
2206: if (r1>15) err(talker,"r1>15 in discrayabslistarchintern");
2207: }
2208: else
2209: matarchunit = (GEN)NULL;
2210:
2211: p = cgeti(3); p[1] = evalsigne(1)|evallgef(3);
2212: sqbou = (long)sqrt((double)bound) + 1;
2213: av = avma; lim = stack_lim(av,1);
2214: z = bigcgetvec(bound); for (i=2;i<=bound;i++) putcompobig(z,i,cgetg(1,t_VEC));
2215: if (allarch) bidp = zidealstarinitall(nf,idmat(degk),0);
2216: embunit = logunitmatrix(nf,funits,racunit,bidp);
2217: putcompobig(z,1, _vec(zsimp(bidp,embunit)));
2218: if (DEBUGLEVEL>1) fprintferr("Starting zidealstarunits computations\n");
2219: if (bound > (long)maxprime()) err(primer1);
2220: for (p[2]=0; p[2]<=bound; )
2221: {
2222: p[2] += *ptdif++;
2223: if (!flbou && p[2]>sqbou)
2224: {
2225: if (DEBUGLEVEL>1) fprintferr("\nStarting rayclassno computations\n");
2226: flbou = 1;
2227: z = gerepilecopy(av,z);
2228: av1 = avma; raylist = bigcgetvec(bound);
2229: for (i=1; i<=bound; i++)
2230: {
2231: sous = getcompobig(z,i);
2232: sousray = rayclassnointernarch(sous,clh,matarchunit);
2233: putcompobig(raylist,i,sousray);
2234: }
2235: raylist = gerepilecopy(av1,raylist);
2236: z2 = bigcgetvec(sqbou);
2237: for (i=1; i<=sqbou; i++)
2238: putcompobig(z2,i, gcopy(getcompobig(z,i)));
2239: z = z2;
2240: }
2241: fa = primedec(nf,p); lfa = lg(fa)-1;
2242: for (j=1; j<=lfa; j++)
2243: {
2244: pr = (GEN)fa[j]; p1 = powgi(p,(GEN)pr[4]);
2245: if (DEBUGLEVEL>1) { fprintferr("%ld ",p[2]); flusherr(); }
2246: if (is_bigint(p1) || (q = (ulong)itos(p1)) > (ulong)bound) continue;
2247:
2248: fauxpr = stoi((p[2]*degk + itos((GEN)pr[4])-1)*degk + j-1);
2249: p2s = q; ideal = pr; cex = 0;
2250: while (q <= (ulong)bound)
2251: {
2252: cex++; bidp = zidealstarinitall(nf,ideal,0);
2253: faussefa = to_famat_all(fauxpr, stoi(cex));
2254: embunit = logunitmatrix(nf,funits,racunit,bidp);
2255: for (i=q; i<=bound; i+=q)
2256: {
2257: p1 = getcompobig(z,i/q); lp1 = lg(p1);
2258: if (lp1 == 1) continue;
2259:
2260: p2 = cgetg(lp1,t_VEC); c=0;
2261: for (k=1; k<lp1; k++)
2262: {
2263: p3=(GEN)p1[k];
2264: if (q == (ulong)i ||
2265: ((p4=gmael(p3,1,1)) && !isinvector(p4,fauxpr,lg(p4)-1)))
2266: p2[++c] = (long)zsimpjoin(p3,bidp,faussefa,embunit);
2267: }
2268:
2269: setlg(p2, c+1);
2270: if (p[2] <= sqbou)
2271: {
2272: pz = getcompobig(z,i);
2273: if (lg(pz) > 1) p2 = concatsp(pz,p2);
2274: putcompobig(z,i,p2);
2275: }
2276: else
2277: {
2278: p2 = rayclassnointernarch(p2,clh,matarchunit);
2279: pz = getcompobig(raylist,i);
2280: if (lg(pz) > 1) p2 = concatsp(pz,p2);
2281: putcompobig(raylist,i,p2);
2282: }
2283: }
2284: if (ramip && ramip % p[2]) break;
2285: pz = mulss(q,p2s);
2286: if (is_bigint(pz) || (q = (ulong)pz[2]) > (ulong)bound) break;
2287:
2288: ideal = idealmul(nf,ideal,pr);
2289: }
2290: }
2291: if (low_stack(lim, stack_lim(av,1)))
2292: {
2293: if(DEBUGMEM>1) err(warnmem,"[1]: discrayabslistarch");
2294: if (!flbou)
2295: {
2296: if (DEBUGLEVEL>2)
2297: fprintferr("avma = %ld, t(z) = %ld ",avma-bot,taille2(z));
2298: z = gerepilecopy(av, z);
2299: }
2300: else
2301: {
2302: if (DEBUGLEVEL>2)
2303: fprintferr("avma = %ld, t(r) = %ld ",avma-bot,taille2(raylist));
2304: gptr[0]=&z; gptr[1]=&raylist; gerepilemany(av,gptr,2);
2305: }
2306: if (DEBUGLEVEL>2) { fprintferr("avma = %ld ",avma-bot); flusherr(); }
2307: }
2308: }
2309: if (!flbou)
2310: {
2311: if (DEBUGLEVEL>1) fprintferr("\nStarting rayclassno computations\n");
2312: z = gerepilecopy(av, z);
2313: av1 = avma; raylist = bigcgetvec(bound);
2314: for (i=1; i<=bound; i++)
2315: {
2316: sous = getcompobig(z,i);
2317: sousray = rayclassnointernarch(sous,clh,matarchunit);
2318: putcompobig(raylist,i,sousray);
2319: }
2320: }
2321: if (DEBUGLEVEL>2)
2322: fprintferr("avma = %ld, t(r) = %ld ",avma-bot,taille2(raylist));
2323: raylist = gerepilecopy(av, raylist);
2324: if (DEBUGLEVEL>2)
2325: { fprintferr("avma = %ld ",avma-bot); msgtimer("zidealstarlist"); }
2326: /* following discrayabslist */
2327: if (DEBUGLEVEL>1)
2328: { fprintferr("Starting discrayabs computations\n"); flusherr(); }
2329:
2330: if (allarch) nbarch = 1<<r1;
2331: else
2332: {
2333: nbarch = 1;
2334: clhrayall = cgetg(2,t_VEC);
2335: discall = cgetg(2,t_VEC);
2336: faall = cgetg(2,t_VEC);
2337: Id = idmat(degk);
2338: }
2339: idealrelinit = trivfact();
2340: av1 = avma; lim = stack_lim(av1,1);
2341: if (square) bound = sqbou-1;
2342: disclist = bigcgetvec(bound);
2343: for (ii=1; ii<=bound; ii++) putcompobig(disclist,ii,cgetg(1,t_VEC));
2344: for (ii2=1; ii2<=bound; ii2++)
2345: {
2346: ii = square? ii2*ii2: ii2;
2347: if (DEBUGLEVEL>1 && ii%100==0) { fprintferr("%ld ",ii); flusherr(); }
2348: sous = getcompobig(raylist,ii); ly = lg(sous); sousdisc = cgetg(ly,t_VEC);
2349: putcompobig(disclist, square? ii2: ii,sousdisc);
2350: for (jj=1; jj<ly; jj++)
2351: {
2352: GEN fac1, fac2, bidsimp = (GEN)sous[jj];
2353: fa = (GEN)bidsimp[1]; fac = dummycopy(fa);
2354: P = (GEN)fa[1]; fac1 = (GEN)fac[1];
2355: ex= (GEN)fa[2]; fac2 = (GEN)fac[2];
2356: lP = lg(P)-1;
2357:
2358: if (allarch)
2359: {
2360: clhrayall = (GEN)bidsimp[2];
2361: discall = cgetg(nbarch+1,t_VEC);
2362: }
2363: else
2364: clhray = itos((GEN)bidsimp[2]);
2365: for (karch=0; karch<nbarch; karch++)
2366: {
2367: if (!allarch) ideal = Id;
2368: else
2369: {
2370: nba=0;
2371: for (kka=karch,jjj=1; jjj<=r1; jjj++,kka>>=1)
2372: if (kka & 1) nba++;
2373: clhray = itos((GEN)clhrayall[karch+1]);
2374: for (k2=1,k=1; k<=r1; k++,k2<<=1)
2375: {
2376: if (karch&k2 && clhray==itos((GEN)clhrayall[karch-k2+1]))
2377: { clhray=0; goto LDISCRAY; }
2378: }
2379: }
2380: idealrel = idealrelinit;
2381: for (k=1; k<=lP; k++)
2382: {
2383: fauxpr = (GEN)P[k]; ep = itos((GEN)ex[k]); ffs = itos(fauxpr);
2384: /* Hack for NeXTgcc 2.5.8 -- splitting "resp=fs%degk+1" */
2385: fs = ffs/degk; resp = fs%degk; resp++;
2386: gprime = stoi((long)(fs/degk));
2387: if (!allarch && nba)
2388: {
2389: p1 = (GEN)primedec(nf,gprime)[ffs%degk+1];
2390: ideal = idealmul(nf,ideal,idealpow(nf,p1,(GEN)ex[k]));
2391: }
2392: S=0; clhss=0;
2393: normi = ii; normps= itos(gpuigs(gprime,resp));
2394: for (j=1; j<=ep; j++)
2395: {
2396: GEN fad, fad1, fad2;
2397: if (clhss==1) S++;
2398: else
2399: {
2400: if (j < ep) { fac2[k] = lstoi(ep-j); fad = fac; }
2401: else
2402: {
2403: fad = cgetg(3,t_MAT);
2404: fad1 = cgetg(lP,t_COL); fad[1] = (long)fad1;
2405: fad2 = cgetg(lP,t_COL); fad[2] = (long)fad2;
2406: for (i=1; i<k; i++) { fad1[i]=fac1[i]; fad2[i]=fac2[i]; }
2407: for ( ; i<lP; i++){ fad1[i]=fac1[i+1]; fad2[i]=fac2[i+1]; }
2408: }
2409: normi /= normps;
2410: dlk = rayclassnolistessimp(getcompobig(raylist,normi),fad);
2411: if (allarch) dlk = (GEN)dlk[karch+1];
2412: clhss = itos(dlk);
2413: if (j==1 && clhss==clhray)
2414: {
2415: clhray=0; fac2[k] = ex[k]; goto LDISCRAY;
2416: }
2417: S += clhss;
2418: }
2419: }
2420: fac2[k] = ex[k];
2421: normp = to_famat_all(gprime, stoi(resp));
2422: idealrel = factormul(idealrel,factorpow(normp,S));
2423: }
2424: dlk = factordivexact(factorpow(factor(stoi(ii)),clhray),idealrel);
2425: if (!allarch && nba)
2426: {
2427: mod[1] = (long)ideal; arch2 = dummycopy(arch);
2428: mod[2] = (long)arch2; nz = 0;
2429: for (k=1; k<=r1; k++)
2430: {
2431: if (signe(arch[k]))
2432: {
2433: arch2[k] = zero;
2434: clhss = itos(rayclassno(bnf,mod));
2435: arch2[k] = un;
2436: if (clhss==clhray) { clhray=0; goto LDISCRAY; }
2437: }
2438: else nz++;
2439: }
2440: }
2441: else nz = r1-nba;
2442: LDISCRAY:
2443: p1=cgetg(4,t_VEC); discall[karch+1]=(long)p1;
2444: if (!clhray) p1[1]=p1[2]=p1[3]=zero;
2445: else
2446: {
2447: p3 = factorpow(fadkabs,clhray);
2448: n = clhray * degk;
2449: R1= clhray * nz;
2450: if (((n-R1)&3)==2)
2451: dlk=factormul(to_famat_all(stoi(-1),gun), dlk);
2452: p1[1] = lstoi(n);
2453: p1[2] = lstoi(R1);
2454: p1[3] = (long)factormul(dlk,p3);
2455: }
2456: }
2457: if (allarch)
2458: { p1 = cgetg(3,t_VEC); p1[1]=(long)fa; p1[2]=(long)discall; }
2459: else
2460: { faall[1]=(long)fa; p1 = concatsp(faall, p1); }
2461: sousdisc[jj]=(long)p1;
2462: if (low_stack(lim, stack_lim(av1,1)))
2463: {
2464: if(DEBUGMEM>1) err(warnmem,"[2]: discrayabslistarch");
2465: if (DEBUGLEVEL>2)
2466: fprintferr("avma = %ld, t(d) = %ld ",avma-bot,taille2(disclist));
2467: disclist = gerepilecopy(av1, disclist);
2468: if (DEBUGLEVEL>2) { fprintferr("avma = %ld ",avma-bot); flusherr(); }
2469: }
2470: }
2471: }
2472: if (DEBUGLEVEL>2) msgtimer("discrayabs");
2473: return gerepilecopy(av0, disclist);
2474: }
2475:
2476: GEN
2477: discrayabslistarch(GEN bnf, GEN arch, long bound)
2478: { return discrayabslistarchintern(bnf,arch,bound, 0); }
2479:
2480: GEN
2481: discrayabslistlong(GEN bnf, long bound)
2482: { return discrayabslistarchintern(bnf,gzero,bound, 0); }
2483:
2484: GEN
2485: discrayabslistarchsquare(GEN bnf, GEN arch, long bound)
2486: { return discrayabslistarchintern(bnf,arch,bound, -1); }
2487:
2488: static GEN
2489: computehuv(GEN bnr,GEN id, GEN arch)
2490: {
2491: long i,nbgen, av = avma;
2492: GEN bnf,bnrnew,listgen,P,U,DC;
2493: GEN newmod=cgetg(3,t_VEC);
2494: newmod[1]=(long)id;
2495: newmod[2]=(long)arch;
2496:
2497: bnf=(GEN)bnr[1];
2498: bnrnew=buchrayall(bnf,newmod,nf_INIT);
2499: listgen=gmael(bnr,5,3); nbgen=lg(listgen);
2500: P=cgetg(nbgen,t_MAT);
2501: for (i=1; i<nbgen; i++)
2502: P[i] = (long)isprincipalray(bnrnew,(GEN)listgen[i]);
2503: DC=diagonal(gmael(bnrnew,5,2));
2504: U=(GEN)hnfall(concatsp(P,DC))[2];
2505: setlg(U,nbgen); for (i=1; i<nbgen; i++) setlg(U[i], nbgen);
2506: return gerepileupto(av, hnf(concatsp(U,diagonal(gmael(bnr,5,2)))));
2507: }
2508:
2509: /* 0 if hinv*list[i] has a denominator for all i, 1 otherwise */
2510: static int
2511: hnflistdivise(GEN list,GEN h)
2512: {
2513: long av = avma, i, I = lg(list);
2514: GEN hinv = ginv(h);
2515:
2516: for (i=1; i<I; i++)
2517: if (gcmp1(denom(gmul(hinv,(GEN)list[i])))) break;
2518: avma = av; return i < I;
2519: }
2520:
2521: static GEN
2522: subgroupcond(GEN bnr, long indexbound)
2523: {
2524: ulong av = avma;
2525: long i,j,lgi,lp;
2526: GEN li,p1,lidet,perm,nf,bid,ideal,arch,primelist,listkernels;
2527:
2528: checkbnrgen(bnr); bid=(GEN)bnr[2];
2529: ideal=gmael(bid,1,1);
2530: arch =gmael(bid,1,2); nf=gmael(bnr,1,7);
2531: primelist=gmael(bid,3,1); lp=lg(primelist)-1;
2532: listkernels=cgetg(lp+lg(arch),t_VEC);
2533: for (i=1; i<=lp; )
2534: {
2535: p1=idealdiv(nf,ideal,(GEN)primelist[i]);
2536: listkernels[i++]=(long)computehuv(bnr,p1,arch);
2537: }
2538: for (j=1; j<lg(arch); j++)
2539: if (signe((GEN)arch[j]))
2540: {
2541: p1=dummycopy(arch); p1[j]=zero;
2542: listkernels[i++]=(long)computehuv(bnr,ideal,p1);
2543: }
2544: setlg(listkernels,i);
2545:
2546: li=subgrouplist(gmael(bnr,5,2),indexbound);
2547: lgi=lg(li);
2548: for (i=1,j=1; j<lgi; j++)
2549: if (!hnflistdivise(listkernels, (GEN)li[j])) li[i++] = li[j];
2550: /* sort by increasing index */
2551: lgi = i; setlg(li,i); lidet=cgetg(lgi,t_VEC);
2552: for (i=1; i<lgi; i++) lidet[i]=(long)dethnf_i((GEN)li[i]);
2553: perm = sindexsort(lidet); p1=li; li=cgetg(lgi,t_VEC);
2554: for (i=1; i<lgi; i++) li[i] = p1[perm[lgi-i]];
2555: return gerepilecopy(av,li);
2556: }
2557:
2558: GEN
2559: subgrouplist0(GEN bnr, long indexbound, long all)
2560: {
2561: if (typ(bnr)!=t_VEC) err(typeer,"subgrouplist");
2562: if (lg(bnr)!=1 && typ(bnr[1])!=t_INT)
2563: {
2564: if (!all) return subgroupcond(bnr,indexbound);
2565: checkbnr(bnr); bnr = gmael(bnr,5,2);
2566: }
2567: return subgrouplist(bnr,indexbound);
2568: }
2569:
2570: GEN
2571: bnrdisclist0(GEN bnf, GEN borne, GEN arch, long all)
2572: {
2573: if (typ(borne)==t_INT)
2574: {
2575: if (!arch) arch = gzero;
2576: if (all==1) { arch = NULL; all = 0; }
2577: return discrayabslistarchintern(bnf,arch,itos(borne),all);
2578: }
2579: return discrayabslist(bnf,borne);
2580: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>