Annotation of OpenXM_contrib/pari-2.2/src/basemath/buch3.c, Revision 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>