[BACK]Return to kummer.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari-2.2 / src / modules

Annotation of OpenXM_contrib/pari-2.2/src/modules/kummer.c, Revision 1.2

1.2     ! noro        1: /* $Id: kummer.c,v 1.48 2002/09/07 01:28:54 karim Exp $
1.1       noro        2:
                      3: Copyright (C) 2000  The PARI group.
                      4:
                      5: This file is part of the PARI/GP package.
                      6:
                      7: PARI/GP is free software; you can redistribute it and/or modify it under the
                      8: terms of the GNU General Public License as published by the Free Software
                      9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
                     10: ANY WARRANTY WHATSOEVER.
                     11:
                     12: Check the License for details. You should have received a copy of it, along
                     13: with the package; see the file 'COPYING'. If not, write to the Free Software
                     14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
                     15:
                     16: /*******************************************************************/
                     17: /*                                                                 */
                     18: /*                      KUMMER EXTENSIONS                          */
                     19: /*                                                                 */
                     20: /*******************************************************************/
                     21: #include "pari.h"
1.2     ! noro       22: #include "parinf.h"
        !            23: extern GEN gmul_mati_smallvec(GEN x, GEN y);
1.1       noro       24: extern GEN check_and_build_cycgen(GEN bnf);
                     25: extern GEN get_arch_real(GEN nf,GEN x,GEN *emb,long prec);
                     26: extern GEN T2_from_embed_norm(GEN x, long r1);
1.2     ! noro       27: extern GEN vconcat(GEN A, GEN B);
        !            28: extern long int_elt_val(GEN nf, GEN x, GEN p, GEN b, GEN *newx);
1.1       noro       29:
1.2     ! noro       30: extern GEN famat_inv(GEN f);
        !            31: extern GEN famat_pow(GEN f, GEN n);
        !            32: extern GEN famat_mul(GEN f, GEN g);
        !            33: extern GEN famat_reduce(GEN fa);
        !            34: extern GEN famat_ideallog(GEN nf, GEN g, GEN e, GEN bid);
        !            35: extern GEN to_famat(GEN g, GEN e);
        !            36:
        !            37: typedef struct {
        !            38:   GEN x;  /* tau ( Mod(x, nf.pol) ) */
        !            39:   GEN zk; /* action of tau on nf.zk (as t_MAT) */
        !            40: } tau_s;
        !            41:
        !            42: typedef struct {
        !            43:   GEN polnf, invexpoteta1;
        !            44:   tau_s *tau;
        !            45:   long m;
        !            46: } toK_s;
1.1       noro       47:
1.2     ! noro       48: long
        !            49: prank(GEN cyc, long ell)
1.1       noro       50: {
1.2     ! noro       51:   long i;
        !            52:   for (i=1; i<lg(cyc); i++)
        !            53:     if (smodis((GEN)cyc[i],ell)) break;
        !            54:   return i-1;
        !            55: }
1.1       noro       56:
1.2     ! noro       57: /* increment y, which runs through [0,ell-1]^(k-1). Return 0 when done. */
        !            58: static int
        !            59: increment(GEN y, long k, long ell)
        !            60: {
        !            61:   long i = k, j;
        !            62:   do
1.1       noro       63:   {
1.2     ! noro       64:     if (--i == 0) return 0;
        !            65:     y[i]++;
        !            66:   } while (y[i] >= ell);
        !            67:   for (j = i+1; j < k; j++) y[j] = 0;
        !            68:   return 1;
1.1       noro       69: }
                     70:
1.2     ! noro       71: /* as above, y increasing (y[i] <= y[i+1]) */
        !            72: static int
        !            73: increment_inc(GEN y, long k, long ell)
1.1       noro       74: {
1.2     ! noro       75:   long i = k, j;
        !            76:   do
        !            77:   {
        !            78:     if (--i == 0) return 0;
        !            79:     y[i]++;
        !            80:   } while (y[i] >= ell);
        !            81:   for (j = i+1; j < k; j++) y[j] = y[i];
        !            82:   return 1;
        !            83: }
1.1       noro       84:
1.2     ! noro       85: static int
        !            86: ok_congruence(GEN X, GEN ell, long lW, GEN vecMsup)
        !            87: {
        !            88:   long i, l;
        !            89:   if (gcmp0(X)) return 0;
        !            90:   l = lg(X);
        !            91:   for (i=lW; i<l; i++)
        !            92:     if (gcmp0((GEN)X[i])) return 0;
        !            93:   l = lg(vecMsup);
        !            94:   for (i=1; i<l; i++)
        !            95:     if (gcmp0(FpV_red(gmul((GEN)vecMsup[i],X), ell))) return 0;
        !            96:   return 1;
1.1       noro       97: }
                     98:
                     99: static int
1.2     ! noro      100: ok_sign(GEN X, GEN msign, GEN arch)
        !           101: {
        !           102:   GEN p1 = lift(gmul(msign,X)); settyp(p1,t_VEC);
        !           103:   return gegal(p1, arch);
        !           104: }
        !           105:
        !           106: /* REDUCTION MOD ell-TH POWERS */
        !           107:
        !           108: static GEN
        !           109: fix_be(GEN bnfz, GEN be, GEN u)
        !           110: {
        !           111:   GEN nf = checknf(bnfz), fu = gmael(bnfz,8,5);
        !           112:   return element_mul(nf, be, factorbackelt(fu, u, nf));
        !           113: }
        !           114:
        !           115: static GEN
        !           116: logarch2arch(GEN x, long r1, long prec)
1.1       noro      117: {
1.2     ! noro      118:   long i, lx = lg(x), tx = typ(x);
        !           119:   GEN y = cgetg(lx, tx);
        !           120:
        !           121:   if (tx == t_MAT)
1.1       noro      122:   {
1.2     ! noro      123:     for (i=1; i<lx; i++) y[i] = (long)logarch2arch((GEN)x[i], r1, prec);
        !           124:     return y;
1.1       noro      125:   }
1.2     ! noro      126:   for (i=1; i<=r1;i++) y[i] = lexp((GEN)x[i],prec);
        !           127:   for (   ; i<lx; i++) y[i] = lexp(gmul2n((GEN)x[i],-1),prec);
        !           128:   return y;
1.1       noro      129: }
                    130:
1.2     ! noro      131: /* multiply be by ell-th powers of units as to find small L2-norm for new be */
1.1       noro      132: static GEN
1.2     ! noro      133: reducebetanaive(GEN bnfz, GEN be, GEN b, GEN ell)
1.1       noro      134: {
1.2     ! noro      135:   long i,k,n,ru,r1, prec = nfgetprec(bnfz);
        !           136:   GEN z,p1,p2,nmax,c, nf = checknf(bnfz);
1.1       noro      137:
1.2     ! noro      138:   r1 = nf_get_r1(nf);
        !           139:   if (!b)
        !           140:   {
        !           141:     if (typ(be) != t_COL) be = algtobasis(nf, be);
        !           142:     b = gmul(gmael(nf,5,1), be);
        !           143:   }
        !           144:   n = max((itos(ell)>>1), 3);
        !           145:   z = cgetg(n+1, t_VEC);
        !           146:   c = gmul(greal((GEN)bnfz[3]), ell);
        !           147:   c = logarch2arch(c, r1, prec); /* = embeddings of fu^ell */
        !           148:   c = gprec_w(gnorm(c), DEFAULTPREC);
        !           149:   b = gprec_w(gnorm(b), DEFAULTPREC); /* need little precision */
        !           150:   z[1] = (long)concatsp(c, vecinv(c));
        !           151:   for (k=2; k<=n; k++) z[k] = (long) vecmul((GEN)z[1], (GEN)z[k-1]);
        !           152:   nmax = T2_from_embed_norm(b, r1);
        !           153:   ru = lg(c)-1; c = zerovec(ru);
1.1       noro      154:   for(;;)
                    155:   {
1.2     ! noro      156:     GEN B = NULL;
        !           157:     long besti = 0, bestk = 0;
        !           158:     for (k=1; k<=n; k++)
        !           159:       for (i=1; i<=ru; i++)
1.1       noro      160:       {
1.2     ! noro      161:         p1 = vecmul(b, gmael(z,k,i));    p2 = T2_from_embed_norm(p1,r1);
        !           162:         if (gcmp(p2,nmax) < 0) { B=p1; nmax=p2; besti=i; bestk = k; continue; }
        !           163:         p1 = vecmul(b, gmael(z,k,i+ru)); p2 = T2_from_embed_norm(p1,r1);
        !           164:         if (gcmp(p2,nmax) < 0) { B=p1; nmax=p2; besti=i; bestk =-k; }
1.1       noro      165:       }
1.2     ! noro      166:     if (!B) break;
        !           167:     b = B; c[besti] = laddis((GEN)c[besti], bestk);
1.1       noro      168:   }
1.2     ! noro      169:   if (DEBUGLEVEL) fprintferr("naive reduction mod U^l: unit exp. = %Z\n",c);
        !           170:   return fix_be(bnfz, be, gmul(ell,c));
1.1       noro      171: }
                    172:
                    173: static GEN
1.2     ! noro      174: reduce_mod_Qell(GEN bnfz, GEN be, GEN gell)
1.1       noro      175: {
1.2     ! noro      176:   GEN c, fa;
        !           177:   if (typ(be) != t_COL) be = algtobasis(bnfz, be);
        !           178:   be = primitive_part(be, &c);
        !           179:   if (c)
        !           180:   {
        !           181:     fa = factor(c);
        !           182:     fa[2] = (long)FpV_red((GEN)fa[2], gell);
        !           183:     c = factorback(fa, NULL);
        !           184:     be = gmul(be, c);
        !           185:   }
        !           186:   return be;
1.1       noro      187: }
                    188:
1.2     ! noro      189: /* return q, q^n r = x, v_pr(r) < n for all pr. Insist q is a genuine n-th
        !           190:  * root (i.e r = 1) if strict != 0. */
1.1       noro      191: static GEN
1.2     ! noro      192: idealsqrtn(GEN nf, GEN x, GEN gn, int strict)
1.1       noro      193: {
1.2     ! noro      194:   long i, l, n = itos(gn);
        !           195:   GEN fa, q, Ex, Pr;
1.1       noro      196:
1.2     ! noro      197:   fa = idealfactor(nf, x);
        !           198:   Pr = (GEN)fa[1]; l = lg(Pr);
        !           199:   Ex = (GEN)fa[2]; q = NULL;
        !           200:   for (i=1; i<l; i++)
        !           201:   {
        !           202:     long ex = itos((GEN)Ex[i]);
        !           203:     GEN e = stoi(ex / n);
        !           204:     if (strict && ex % n) err(talker,"not an n-th power in idealsqrtn");
        !           205:     if (q) q = idealmulpowprime(nf, q, (GEN)Pr[i], e);
        !           206:     else   q = idealpow(nf, (GEN)Pr[i], e);
        !           207:   }
        !           208:   return q? q: gun;
1.1       noro      209: }
                    210:
                    211: static GEN
1.2     ! noro      212: reducebeta(GEN bnfz, GEN be, GEN ell)
1.1       noro      213: {
1.2     ! noro      214:   long j,ru, prec = nfgetprec(bnfz);
        !           215:   GEN emb,z,u,matunit, nf = checknf(bnfz);
1.1       noro      216:
1.2     ! noro      217:   if (DEBUGLEVEL>1) fprintferr("reducing beta = %Z\n",be);
        !           218:   /* reduce mod Q^ell */
        !           219:   be = reduce_mod_Qell(nf, be, ell);
        !           220:   /* reduce l-th root */
        !           221:   z = idealsqrtn(nf, be, ell, 0);
        !           222:   if (typ(z) == t_MAT && !gcmp1(gcoeff(z,1,1)))
        !           223:   {
        !           224:     z = idealred_elt(nf, z);
        !           225:     be = element_div(nf, be, element_pow(nf, z, ell));
        !           226:     /* make be integral */
        !           227:     be = reduce_mod_Qell(nf, be, ell);
        !           228:   }
        !           229:   if (DEBUGLEVEL>1) fprintferr("beta reduced via ell-th root = %Z\n",be);
1.1       noro      230:
1.2     ! noro      231:   matunit = gmul(greal((GEN)bnfz[3]), ell); /* log. embeddings of fu^ell */
        !           232:   for (;;)
1.1       noro      233:   {
1.2     ! noro      234:     z = get_arch_real(nf, be, &emb, prec);
        !           235:     if (z) break;
        !           236:     prec = (prec-1)<<1;
        !           237:     if (DEBUGLEVEL) err(warnprec,"reducebeta",prec);
        !           238:     nf = nfnewprec(nf,prec);
        !           239:   }
        !           240:   z = concatsp(matunit, z);
        !           241:   u = lllintern(z, 100, 1, prec);
        !           242:   if (u)
1.1       noro      243:   {
1.2     ! noro      244:     ru = lg(u);
        !           245:     for (j=1; j < ru; j++)
        !           246:       if (gcmp1(gcoeff(u,ru-1,j))) break;
        !           247:     if (j < ru)
1.1       noro      248:     {
1.2     ! noro      249:       u = (GEN)u[j]; /* coords on (fu^ell, be) of a small generator */
        !           250:       ru--; setlg(u, ru);
        !           251:       be = fix_be(bnfz, be, gmul(ell,u));
1.1       noro      252:     }
                    253:   }
1.2     ! noro      254:   if (DEBUGLEVEL>1) fprintferr("beta LLL-reduced mod U^l = %Z\n",be);
        !           255:   return reducebetanaive(bnfz, be, NULL, ell);
        !           256: }
        !           257:
        !           258: static GEN
        !           259: tauofalg(GEN x, GEN U) {
        !           260:   return gsubst(lift(x), varn(U[1]), U);
        !           261: }
        !           262:
        !           263: static tau_s *
        !           264: get_tau(tau_s *tau, GEN nf, GEN U)
        !           265: {
        !           266:   GEN bas = (GEN)nf[7], Uzk;
        !           267:   long i, l = lg(bas);
        !           268:   Uzk = cgetg(l, t_MAT);
1.1       noro      269:   for (i=1; i<l; i++)
1.2     ! noro      270:     Uzk[i] = (long)algtobasis(nf, tauofalg((GEN)bas[i], U));
        !           271:   tau->zk = Uzk;
        !           272:   tau->x  = U; return tau;
        !           273: }
        !           274:
        !           275: static GEN tauoffamat(GEN x, tau_s *tau);
        !           276:
        !           277: static GEN
        !           278: tauofelt(GEN x, tau_s *tau)
        !           279: {
        !           280:   switch(typ(x))
1.1       noro      281:   {
1.2     ! noro      282:     case t_COL: return gmul(tau->zk, x);
        !           283:     case t_MAT: return tauoffamat(x, tau);
        !           284:     default: return tauofalg(x, tau->x);
1.1       noro      285:   }
                    286: }
1.2     ! noro      287: static GEN
        !           288: tauofvec(GEN x, tau_s *tau)
        !           289: {
        !           290:   long i, l = lg(x);
        !           291:   GEN y = cgetg(l, typ(x));
1.1       noro      292:
1.2     ! noro      293:   for (i=1; i<l; i++) y[i] = (long)tauofelt((GEN)x[i], tau);
        !           294:   return y;
        !           295: }
        !           296: /* [x, tau(x), ..., tau^m(x)] */
1.1       noro      297: static GEN
1.2     ! noro      298: powtau(GEN x, long m, tau_s *tau)
1.1       noro      299: {
1.2     ! noro      300:   GEN y = cgetg(m+1, t_VEC);
        !           301:   long i;
        !           302:   y[1] = (long)x;
        !           303:   for (i=2; i<=m; i++) y[i] = (long)tauofelt((GEN)y[i-1], tau);
        !           304:   return y;
        !           305: }
1.1       noro      306:
1.2     ! noro      307: static GEN
        !           308: tauoffamat(GEN x, tau_s *tau)
        !           309: {
        !           310:   GEN y = cgetg(3, t_MAT);
        !           311:   y[1] = (long)tauofvec((GEN)x[1], tau);
        !           312:   y[2] = x[2]; return y;
1.1       noro      313: }
                    314:
1.2     ! noro      315: /* TODO: wasteful to reduce to 2-elt form. Compute image directly */
1.1       noro      316: static GEN
1.2     ! noro      317: tauofideal(GEN nfz, GEN id, tau_s *tau)
1.1       noro      318: {
1.2     ! noro      319:   GEN I = ideal_two_elt(nfz,id);
        !           320:   I[2] = (long)tauofelt((GEN)I[2], tau);
        !           321:   return prime_to_ideal(nfz,I);
1.1       noro      322: }
                    323:
1.2     ! noro      324: static int
        !           325: isprimeidealconj(GEN nfz, GEN pr1, GEN pr2, tau_s *tau)
1.1       noro      326: {
1.2     ! noro      327:   GEN p = (GEN)pr1[1];
        !           328:   GEN x = (GEN)pr1[2];
        !           329:   GEN b1= (GEN)pr1[5];
        !           330:   GEN b2= (GEN)pr2[5];
        !           331:   if (!egalii(p, (GEN)pr2[1])
        !           332:    || !egalii((GEN)pr1[3], (GEN)pr2[3])
        !           333:    || !egalii((GEN)pr1[4], (GEN)pr2[4])) return 0;
        !           334:   if (gegal(x,(GEN)pr2[2])) return 1;
        !           335:   for(;;)
1.1       noro      336:   {
1.2     ! noro      337:     if (int_elt_val(nfz,x,p,b2,NULL)) return 1;
        !           338:     x = FpV_red(tauofelt(x, tau), p);
        !           339:     if (int_elt_val(nfz,x,p,b1,NULL)) return 0;
1.1       noro      340:   }
                    341: }
                    342:
1.2     ! noro      343: static int
        !           344: isconjinprimelist(GEN nfz, GEN S, GEN pr, tau_s *tau)
1.1       noro      345: {
1.2     ! noro      346:   long i, l;
        !           347:
        !           348:   if (!tau) return 0;
        !           349:   l = lg(S);
        !           350:   for (i=1; i<l; i++)
        !           351:     if (isprimeidealconj(nfz, (GEN)S[i],pr,tau)) return 1;
1.1       noro      352:   return 0;
                    353: }
                    354:
1.2     ! noro      355: static GEN
        !           356: downtoK(toK_s *T, GEN x)
1.1       noro      357: {
1.2     ! noro      358:   long degKz = lg(T->invexpoteta1) - 1;
        !           359:   GEN y = gmul(T->invexpoteta1, pol_to_vec(lift(x), degKz));
        !           360:   return gmodulcp(gtopolyrev(y,varn(T->polnf)), T->polnf);
1.1       noro      361: }
                    362:
                    363: static GEN
1.2     ! noro      364: tracetoK(toK_s *T, GEN x)
1.1       noro      365: {
1.2     ! noro      366:   GEN p1 = x;
1.1       noro      367:   long i;
1.2     ! noro      368:   for (i=1; i < T->m; i++) p1 = gadd(x, tauofelt(p1,T->tau));
        !           369:   return downtoK(T, p1);
1.1       noro      370: }
                    371:
                    372: static GEN
1.2     ! noro      373: normtoK(toK_s *T, GEN x)
1.1       noro      374: {
1.2     ! noro      375:   GEN p1 = x;
1.1       noro      376:   long i;
1.2     ! noro      377:   for (i=1; i < T->m; i++) p1 = gmul(x, tauofelt(p1,T->tau));
        !           378:   return downtoK(T, p1);
        !           379: }
1.1       noro      380:
1.2     ! noro      381: static GEN
        !           382: no_sol(long all, int i)
        !           383: {
        !           384:   if (!all) err(talker,"bug%d in kummer",i);
        !           385:   return cgetg(1,t_VEC);
1.1       noro      386: }
                    387:
                    388: static GEN
1.2     ! noro      389: get_gell(GEN bnr, GEN subgp, long all)
1.1       noro      390: {
1.2     ! noro      391:   GEN gell;
        !           392:   if (all)        gell = stoi(all);
        !           393:   else if (subgp) gell = det(subgp);
        !           394:   else            gell = det(diagonal(gmael(bnr,5,2)));
        !           395:   if (typ(gell) != t_INT) err(arither1);
        !           396:   return gell;
        !           397: }
        !           398:
        !           399: typedef struct {
        !           400:   GEN Sm, Sml1, Sml2, Sl, ESml2;
        !           401: } primlist;
        !           402:
        !           403: static int
        !           404: build_list_Hecke(primlist *L, GEN nfz, GEN fa, GEN gothf, GEN gell, tau_s *tau)
        !           405: {
        !           406:   GEN listpr, listex, pr, p, factell;
        !           407:   long vd, vp, e, i, l, ell = itos(gell), degKz = degpol(nfz[1]);
1.1       noro      408:
1.2     ! noro      409:   if (!fa) fa = idealfactor(nfz, gothf);
        !           410:   listpr = (GEN)fa[1];
        !           411:   listex = (GEN)fa[2]; l = lg(listpr);
        !           412:   L->Sm  = cget1(l,t_VEC);
        !           413:   L->Sml1= cget1(l,t_VEC);
        !           414:   L->Sml2= cget1(l,t_VEC);
        !           415:   L->Sl  = cget1(l+degKz,t_VEC);
        !           416:   L->ESml2=cget1(l,t_VECSMALL);
        !           417:   for (i=1; i<l; i++)
        !           418:   {
        !           419:     pr = (GEN)listpr[i]; p = (GEN)pr[1]; e = itos((GEN)pr[3]);
        !           420:     vp = itos((GEN)listex[i]);
        !           421:     if (!egalii(p,gell))
        !           422:     {
        !           423:       if (vp != 1) return 1;
        !           424:       if (!isconjinprimelist(nfz, L->Sm,pr,tau)) appendL(L->Sm,pr);
        !           425:     }
        !           426:     else
        !           427:     {
        !           428:       vd = (vp-1)*(ell-1)-ell*e;
        !           429:       if (vd > 0) return 4;
        !           430:       if (vd==0)
        !           431:       {
        !           432:        if (!isconjinprimelist(nfz, L->Sml1,pr,tau)) appendL(L->Sml1, pr);
        !           433:       }
        !           434:       else
        !           435:       {
        !           436:        if (vp==1) return 2;
        !           437:         if (!isconjinprimelist(nfz, L->Sml2,pr,tau))
        !           438:         {
        !           439:           appendL(L->Sml2, pr);
        !           440:           appendL(L->ESml2,(GEN)vp);
        !           441:         }
        !           442:       }
        !           443:     }
        !           444:   }
        !           445:   factell = primedec(nfz,gell); l = lg(factell);
        !           446:   for (i=1; i<l; i++)
1.1       noro      447:   {
1.2     ! noro      448:     pr = (GEN)factell[i];
        !           449:     if (!idealval(nfz,gothf,pr))
        !           450:       if (!isconjinprimelist(nfz, L->Sl,pr,tau)) appendL(L->Sl, pr);
1.1       noro      451:   }
1.2     ! noro      452:   return 0; /* OK */
1.1       noro      453: }
                    454:
                    455: static GEN
1.2     ! noro      456: logall(GEN nf, GEN vec, long lW, long mginv, long ell, GEN pr, long ex)
1.1       noro      457: {
1.2     ! noro      458:   GEN m, M, bid = zidealstarinitgen(nf, idealpows(nf, pr, ex));
        !           459:   long ellrank, i, l = lg(vec);
1.1       noro      460:
1.2     ! noro      461:   ellrank = prank(gmael(bid,2,2), ell);
        !           462:   M = cgetg(l,t_MAT);
        !           463:   for (i=1; i<l; i++)
1.1       noro      464:   {
1.2     ! noro      465:     m = zideallog(nf, (GEN)vec[i], bid);
        !           466:     setlg(m, ellrank+1);
        !           467:     if (i < lW) m = gmulsg(mginv, m);
        !           468:     M[i] = (long)m;
1.1       noro      469:   }
1.2     ! noro      470:   return M;
1.1       noro      471: }
                    472:
1.2     ! noro      473: /* compute the u_j (see remark 5.2.15.) */
1.1       noro      474: static GEN
1.2     ! noro      475: get_u(GEN cyc, long rc, GEN gell)
1.1       noro      476: {
1.2     ! noro      477:   long i, l = lg(cyc);
        !           478:   GEN u = cgetg(l,t_VEC);
        !           479:   for (i=1; i<=rc; i++) u[i] = zero;
        !           480:   for (   ; i<  l; i++) u[i] = lmpinvmod((GEN)cyc[i], gell);
        !           481:   return u;
1.1       noro      482: }
                    483:
1.2     ! noro      484: /* alg. 5.2.15. with remark */
1.1       noro      485: static GEN
1.2     ! noro      486: isprincipalell(GEN bnfz, GEN id, GEN cycgen, GEN u, GEN gell, long rc)
1.1       noro      487: {
1.2     ! noro      488:   long i, l = lg(cycgen);
        !           489:   GEN logdisc, b, y = quick_isprincipalgen(bnfz, id);
1.1       noro      490:
1.2     ! noro      491:   logdisc = gmod((GEN)y[1], gell);
        !           492:   b = (GEN)y[2];
        !           493:   for (i=rc+1; i<l; i++)
1.1       noro      494:   {
1.2     ! noro      495:     GEN e = modii(mulii((GEN)logdisc[i],(GEN)u[i]), gell);
        !           496:     if (signe(e)) b = famat_mul(b, famat_pow((GEN)cycgen[i], e));
1.1       noro      497:   }
1.2     ! noro      498:   y = cgetg(3,t_VEC);
        !           499:   y[1] = (long)logdisc; setlg(logdisc,rc+1);
        !           500:   y[2] = (long)b; return y;
1.1       noro      501: }
                    502:
                    503: static GEN
1.2     ! noro      504: famat_factorback(GEN v, GEN e)
1.1       noro      505: {
1.2     ! noro      506:   long i, l = lg(e);
        !           507:   GEN V = cgetg(1, t_MAT);
        !           508:   for (i=1; i<l; i++)
        !           509:     if (signe(e[i])) V = famat_mul(V, famat_pow((GEN)v[i], (GEN)e[i]));
        !           510:   return V;
1.1       noro      511: }
                    512:
                    513: static GEN
1.2     ! noro      514: compute_beta(GEN X, GEN vecWB, GEN ell, GEN bnfz)
1.1       noro      515: {
1.2     ! noro      516:   GEN BE, be;
        !           517:   BE = famat_reduce(famat_factorback(vecWB, X));
        !           518:   BE[2] = (long)centermod((GEN)BE[2], ell);
        !           519:   be = factorbackelt(BE, bnfz, NULL);
        !           520:   be = reducebeta(bnfz, be, ell);
        !           521:   if (DEBUGLEVEL>1) fprintferr("beta reduced = %Z\n",be);
        !           522:   return basistoalg(bnfz, be); /* FIXME */
1.1       noro      523: }
                    524:
                    525: static GEN
1.2     ! noro      526: get_Selmer(GEN bnf, GEN cycgen, long rc)
1.1       noro      527: {
1.2     ! noro      528:   GEN fu = check_units(bnf,"rnfkummer");
        !           529:   GEN tu = gmael3(bnf,8,4,2);
        !           530:   return concatsp(algtobasis(bnf,concatsp(fu,tu)), vecextract_i(cycgen,1,rc));
1.1       noro      531: }
                    532:
1.2     ! noro      533: /* if all!=0, give all equations of degree 'all'. Assume bnr modulus is the
        !           534:  * conductor */
1.1       noro      535: static GEN
1.2     ! noro      536: rnfkummersimple(GEN bnr, GEN subgroup, GEN gell, long all)
1.1       noro      537: {
1.2     ! noro      538:   long ell, i, j, degK, dK;
        !           539:   long lSml2, lSl2, lSp, rc, lW;
        !           540:   long prec;
1.1       noro      541:
1.2     ! noro      542:   GEN bnf,nf,bid,ideal,arch,cycgen;
        !           543:   GEN clgp,cyc;
        !           544:   GEN Sp,listprSp,matP;
        !           545:   GEN res,u,M,K,y,vecMsup,vecW,vecWB,vecBp,msign;
        !           546:   primlist L;
1.1       noro      547:
1.2     ! noro      548:   bnf = (GEN)bnr[1];
        !           549:   nf  = (GEN)bnf[7];
        !           550:   degK = degpol(nf[1]);
        !           551:
        !           552:   bid = (GEN)bnr[2];
        !           553:   ideal= gmael(bid,1,1);
        !           554:   arch = gmael(bid,1,2); /* this is the conductor */
        !           555:   ell = itos(gell);
        !           556:   i = build_list_Hecke(&L, nf, (GEN)bid[3], ideal, gell, NULL);
        !           557:   if (i) return no_sol(all,i);
1.1       noro      558:
1.2     ! noro      559:   lSml2 = lg(L.Sml2)-1;
        !           560:   Sp = concatsp(L.Sm, L.Sml1); lSp = lg(Sp)-1;
        !           561:   listprSp = concatsp(L.Sml2, L.Sl); lSl2 = lg(listprSp)-1;
1.1       noro      562:
1.2     ! noro      563:   cycgen = check_and_build_cycgen(bnf);
        !           564:   clgp = gmael(bnf,8,1);
        !           565:   cyc = (GEN)clgp[2]; rc = prank(cyc, ell);
1.1       noro      566:
1.2     ! noro      567:   vecW = get_Selmer(bnf, cycgen, rc);
        !           568:   u = get_u(cyc, rc, gell);
1.1       noro      569:
1.2     ! noro      570:   vecBp = cgetg(lSp+1, t_VEC);
        !           571:   matP  = cgetg(lSp+1, t_MAT);
        !           572:   for (j=1; j<=lSp; j++)
        !           573:   {
        !           574:     GEN e, a, L;
        !           575:     L = isprincipalell(bnf,(GEN)Sp[j], cycgen,u,gell,rc);
        !           576:     e = (GEN)L[1]; matP[j]  = (long)e;
        !           577:     a = (GEN)L[2]; vecBp[j] = (long)a;
        !           578:   }
        !           579:   vecWB = concatsp(vecW, vecBp);
        !           580:
        !           581:   prec = DEFAULTPREC +
        !           582:     ((gexpo(vecWB) + gexpo(gmael(nf,5,1))) >> TWOPOTBYTES_IN_LONG);
        !           583:   if (nfgetprec(nf) < prec) nf = nfnewprec(nf, prec);
        !           584:   msign = zsigns(nf, vecWB);
1.1       noro      585:
1.2     ! noro      586:   vecMsup = cgetg(lSml2+1,t_VEC);
        !           587:   M = NULL;
        !           588:   for (i=1; i<=lSl2; i++)
1.1       noro      589:   {
1.2     ! noro      590:     GEN pr = (GEN)listprSp[i];
        !           591:     long e = itos((GEN)pr[3]), z = ell * (e / (ell-1));
1.1       noro      592:
1.2     ! noro      593:     if (i <= lSml2)
1.1       noro      594:     {
1.2     ! noro      595:       z += 1 - L.ESml2[i];
        !           596:       vecMsup[i] = (long)logall(nf, vecWB, 0,0, ell, pr,z+1);
        !           597:     }
        !           598:     M = vconcat(M, logall(nf, vecWB, 0,0, ell, pr,z));
        !           599:   }
        !           600:   lW = lg(vecW);
        !           601:   M = vconcat(M, concatsp(zeromat(rc,lW-1), matP));
        !           602:
        !           603:   K = FpM_ker(M, gell);
        !           604:   dK = lg(K)-1;
        !           605:   y = cgetg(dK+1,t_VECSMALL);
        !           606:   res = cgetg(1,t_VEC); /* in case all = 1 */
        !           607:   while (dK)
        !           608:   {
        !           609:     for (i=1; i<dK; i++) y[i] = 0;
        !           610:     y[i] = 1; /* y = [0,...,0,1,0,...,0], 1 at dK'th position */
        !           611:     do
        !           612:     {
        !           613:       GEN be, P, X = FpV_red(gmul_mati_smallvec(K, y), gell);
        !           614:       if (ok_congruence(X, gell, lW, vecMsup) && ok_sign(X, msign, arch))
        !           615:       {/* be satisfies all congruences, x^ell - be is irreducible, signature
        !           616:         * and relative discriminant are correct */
        !           617:         be = compute_beta(X, vecWB, gell, bnf);
        !           618:         P = gsub(gpowgs(polx[0],ell), be);
        !           619:         if (!all && gegal(rnfnormgroup(bnr,P),subgroup)) return P; /*DONE*/
        !           620:         res = concatsp(res, P);
1.1       noro      621:       }
1.2     ! noro      622:     } while (increment(y, dK, ell));
        !           623:     y[dK--] = 0;
1.1       noro      624:   }
1.2     ! noro      625:   if (all) return res;
        !           626:   return gzero;
1.1       noro      627: }
                    628:
1.2     ! noro      629: /* alg. 5.3.11 (return only discrete log mod ell) */
1.1       noro      630: static GEN
1.2     ! noro      631: isvirtualunit(GEN bnf, GEN v, GEN cycgen, GEN cyc, GEN gell, long rc)
1.1       noro      632: {
1.2     ! noro      633:   GEN L, b, eps, y, q, nf = checknf(bnf);
        !           634:   long i, l = lg(cycgen);
        !           635:
        !           636:   L = quick_isprincipalgen(bnf, idealsqrtn(nf, v, gell, 1));
        !           637:   q = (GEN)L[1];
        !           638:   if (gcmp0(q)) { eps = v; y = q; }
        !           639:   else
        !           640:   {
        !           641:     b = (GEN)L[2];
        !           642:     y = cgetg(l,t_COL);
        !           643:     for (i=1; i<l; i++)
        !           644:       y[i] = (long)diviiexact(mulii(gell,(GEN)q[i]), (GEN)cyc[i]);
        !           645:     eps = famat_mul(famat_factorback(cycgen, y), famat_pow(b, gell));
        !           646:     eps = famat_mul(famat_inv(eps), v);
        !           647:   }
        !           648:   setlg(y, rc+1);
        !           649:   b = isunit(bnf,eps);
        !           650:   if (lg(b) == 1) err(bugparier,"isvirtualunit");
        !           651:   return concatsp(lift_intern(b), y);
1.1       noro      652: }
                    653:
1.2     ! noro      654: /* id a vector of elements in nfz = relative extension of nf by polrel,
        !           655:  * return the Steinitz element associated to the module generated by id */
1.1       noro      656: static GEN
1.2     ! noro      657: steinitzaux(GEN nf, GEN id, GEN polrel)
1.1       noro      658: {
1.2     ! noro      659:   long i, degKz = lg(id)-1, degK = degpol(nf[1]);
        !           660:   GEN V = dummycopy(id),vecid,matid,pseudomat,pid;
        !           661:
        !           662:   vecid = cgetg(degKz+1,t_VEC); matid = idmat(degK);
        !           663:   for (i=1; i<=degKz; i++) vecid[i] = (long)matid;
        !           664:   for (i=1; i<=degKz; i++)
        !           665:   {
        !           666:     GEN v = (GEN)V[i];
        !           667:     if (typ(v) == t_POL) { v = dummycopy(v); setvarn(v, 0); }
        !           668:     V[i] = (long)gmod(v, polrel);
        !           669:   }
        !           670:   pseudomat = cgetg(3,t_VEC);
        !           671:   pseudomat[1] = (long)vecpol_to_mat(V, degpol(polrel));
        !           672:   pseudomat[2] = (long)vecid;
        !           673:   pid = (GEN)nfhermite(nf,pseudomat)[2];
        !           674:   return factorback(pid, nf); /* product */
1.1       noro      675: }
                    676:
                    677: static GEN
1.2     ! noro      678: polrelKzK(toK_s *T, GEN x)
1.1       noro      679: {
1.2     ! noro      680:   GEN P = roots_to_pol(powtau(x, T->m, T->tau), 0);
        !           681:   long i, l = lg(P);
        !           682:   for (i=2; i<l; i++) P[i] = (long)downtoK(T, (GEN)P[i]);
        !           683:   return P;
1.1       noro      684: }
                    685:
1.2     ! noro      686: /* N: Cl_m(Kz) --> Cl_m(K), lift subgroup from bnr to bnrz using Algo 4.1.11 */
1.1       noro      687: static GEN
1.2     ! noro      688: invimsubgroup(GEN bnrz, GEN bnr, GEN subgroup, toK_s *T)
1.1       noro      689: {
1.2     ! noro      690:   long l, j;
        !           691:   GEN P,raycycz,rayclgpz,raygenz,U,polrel,steinitzZk;
        !           692:   GEN nf = checknf(bnr), nfz = checknf(bnrz), polz = (GEN)nfz[1];
1.1       noro      693:
1.2     ! noro      694:   polrel = polrelKzK(T, polx[varn(polz)]);
        !           695:   steinitzZk = steinitzaux(nf, (GEN)nfz[7], polrel);
        !           696:   rayclgpz = (GEN)bnrz[5];
        !           697:   raycycz = (GEN)rayclgpz[2]; l = lg(raycycz);
        !           698:   raygenz = (GEN)rayclgpz[3];
        !           699:   P = cgetg(l,t_MAT);
        !           700:   for (j=1; j<l; j++)
        !           701:   {
        !           702:     GEN g, id = idealhermite(nfz, (GEN)raygenz[j]);
        !           703:     g = steinitzaux(nf, gmul((GEN)nfz[7], id), polrel);
        !           704:     g = idealdiv(nf, g, steinitzZk); /* N_{Kz/K}(gen[j]) */
        !           705:     P[j] = (long)isprincipalray(bnr, g);
        !           706:   }
        !           707:   U = (GEN)hnfall(concatsp(P, subgroup))[2];
        !           708:   setlg(U, l); for (j=1; j<l; j++) setlg(U[j], l);
        !           709:   return hnfmod(concatsp(U, diagonal(raycycz)), (GEN)raycycz[1]);
1.1       noro      710: }
                    711:
1.2     ! noro      712: /* t(b1,...,b_{k-1}) [prop 5.3.9] */
1.1       noro      713: static GEN
1.2     ! noro      714: compute_t(GEN b, GEN r, long m, long ell)
1.1       noro      715: {
1.2     ! noro      716:   long z, s, a, i, k = lg(b);
        !           717:   GEN t = cgetg(m+1, t_COL);
1.1       noro      718:
1.2     ! noro      719:   for (a = 0; a < m; a++)
1.1       noro      720:   {
1.2     ! noro      721:     z = m-1 - a; s = r[1 + z] - ell;
        !           722:     for (i=1; i < k; i++) s += r[1 + ((z + b[i]) % m)];
        !           723:     t[1 + a] = lstoi(s / ell);
1.1       noro      724:   }
1.2     ! noro      725:   return t;
1.1       noro      726: }
                    727:
1.2     ! noro      728: /* Return multinomial(k-1; m1,...,m_{k-1}) where the mi are the
        !           729:  * multiplicities of the bi [ assume b1 <= ... <= b_{k-1} ] */
1.1       noro      730: static GEN
1.2     ! noro      731: get_multinomial(GEN b)
1.1       noro      732: {
1.2     ! noro      733:   long i, k = lg(b), a, m;
        !           734:   GEN z = mpfact(k - 1);
1.1       noro      735:
1.2     ! noro      736:   a = b[1]; m = 1;
        !           737:   for (i = 2; i < k; i++)
1.1       noro      738:   {
1.2     ! noro      739:     if (b[i] == a) m++;
        !           740:     else
        !           741:     {
        !           742:       if (m > 1) z = diviiexact(z, mpfact(m));
        !           743:       a = b[i]; m = 1;
        !           744:     }
1.1       noro      745:   }
1.2     ! noro      746:   if (m > 1) z = diviiexact(z, mpfact(m));
        !           747:   return z;
        !           748: }
        !           749:
        !           750: /* r[b[1]] + ... + r[b[k-1]] + 1 = 0 mod ell ?*/
        !           751: static int
        !           752: b_suitable(GEN b, GEN r, long k, long ell)
        !           753: {
        !           754:   long i, s = 1;
        !           755:   for (i = 1; i < k; i++) s += r[ 1 + b[i] ];
        !           756:   return (s % ell) == 0;
1.1       noro      757: }
                    758:
                    759: static GEN
1.2     ! noro      760: pol_from_Newton(GEN S)
1.1       noro      761: {
1.2     ! noro      762:   long i, k, l = lg(S);
        !           763:   GEN c = cgetg(l, t_VEC);
1.1       noro      764:
1.2     ! noro      765:   c[1] = S[1];
        !           766:   for (k = 2; k < l; k++)
1.1       noro      767:   {
1.2     ! noro      768:     GEN s = (GEN)S[k];
        !           769:     for (i = 1; i < k; i++) s = gadd(s, gmul((GEN)S[i], (GEN)c[k-i]));
        !           770:     c[k] = ldivgs(s, -k);
1.1       noro      771:   }
1.2     ! noro      772:   return gadd(gpowgs(polx[0], l-1), gtopoly(c, 0));
1.1       noro      773: }
                    774:
1.2     ! noro      775: /* th. 5.3.5. and prop. 5.3.9. */
1.1       noro      776: static GEN
1.2     ! noro      777: compute_polrel(GEN nfz, toK_s *T, GEN be, long g, long ell)
1.1       noro      778: {
1.2     ! noro      779:   long i, k, m = T->m;
        !           780:   GEN r, powtaubet, S, X = polx[0], e = normtoK(T,be);
        !           781:
        !           782:   switch (ell)
        !           783:   { /* special-cased for efficiency */
        !           784:     GEN p1, u;
        !           785:     case 2: err(bugparier,"rnfkummer (-1 not in nf?)"); break;
        !           786:     case 3: u = tracetoK(T,be);
        !           787:       p1 = gsub(gsqr(X), gmulsg(3,e));
        !           788:       return gsub(gmul(X,p1), gmul(e,u));
        !           789:     case 5:
        !           790:       if (m == 2)
1.1       noro      791:       {
1.2     ! noro      792:        u = tracetoK(T, gpowgs(be,3));
        !           793:        p1 = gadd(gmulsg(5,gsqr(e)), gmul(gsqr(X), gsub(gsqr(X),gmulsg(5,e))));
        !           794:        return gsub(gmul(X,p1), gmul(e,u));
        !           795:       }
        !           796:       else
        !           797:       { /* m = 4 */
        !           798:         GEN be1, be2, u1, u2, u3;
        !           799:         be1 = tauofelt(be, T->tau);
        !           800:         be2 = tauofelt(be1,T->tau);
        !           801:         u1 = tracetoK(T, gmul(be,be1));
        !           802:         u2 = tracetoK(T, gmul(gmul(be,be2),gsqr(be1)));
        !           803:         u3 = tracetoK(T, gmul(gmul(gsqr(be),gpowgs(be1,3)),be2));
        !           804:         p1 = gsub(gsqr(X), gmulsg(10,e));
        !           805:         p1 = gsub(gmul(X,p1), gmulsg(5,gmul(e,u1)));
        !           806:         p1 = gadd(gmul(X,p1), gmul(gmulsg(5,e),gsub(e,u2)));
        !           807:         return gsub(gmul(X,p1), gmul(e,u3));
1.1       noro      808:       }
                    809:   }
1.2     ! noro      810:   /* general case */
        !           811:   r = cgetg(m+1,t_VECSMALL); /* r[i+1] = g^i mod ell */
        !           812:   r[1] = 1;
        !           813:   for (i=2; i<=m; i++) r[i] = (r[i-1] * g) % ell;
        !           814:   powtaubet = powtau(be, m, T->tau);
        !           815:   S = cgetg(ell+1, t_VEC); /* Newton sums */
        !           816:   S[1] = zero;
        !           817:   for (k = 2; k <= ell; k++)
        !           818:   {
        !           819:     GEN z, g = gzero, b = vecsmall_const(k-1, 0);
        !           820:     do
        !           821:     {
        !           822:       if (! b_suitable(b, r, k, ell)) continue;
        !           823:       z = factorbackelt(powtaubet, compute_t(b, r, m, ell), nfz);
        !           824:       if (typ(z) == t_COL) z = basistoalg(nfz, z);
        !           825:       g = gadd(g, gmul(get_multinomial(b), z));
        !           826:     } while (increment_inc(b, k, m));
        !           827:     S[k] = lmul(gmulsg(ell, e), tracetoK(T,g));
        !           828:   }
        !           829:   return pol_from_Newton(S);
        !           830: }
        !           831:
        !           832: typedef struct {
        !           833:   GEN R; /* compositum(P,Q) */
        !           834:   GEN p; /* Mod(p,R) root of P */
        !           835:   GEN q; /* Mod(q,R) root of Q */
        !           836:   GEN k; /* Q[X]/R generated by q + k p */
        !           837:   GEN rev;
        !           838: } compo_s;
        !           839:
        !           840: static GEN
        !           841: lifttoKz(GEN nfz, GEN nf, GEN id, compo_s *C)
        !           842: {
        !           843:   GEN I = ideal_two_elt(nf,id);
        !           844:   GEN x = gmul((GEN)nf[7], (GEN)I[2]);
        !           845:   I[2] = (long)algtobasis(nfz, RX_RXQ_compo(x, C->p, C->R));
        !           846:   return prime_to_ideal(nfz,I);
1.1       noro      847: }
1.2     ! noro      848:
        !           849: static void
        !           850: compositum_red(compo_s *C, GEN P, GEN Q)
1.1       noro      851: {
1.2     ! noro      852:   GEN a, z = (GEN)compositum2(P, Q)[1];
        !           853:   C->R = (GEN)z[1];
        !           854:   C->p = (GEN)z[2];
        !           855:   C->q = (GEN)z[3];
        !           856:   C->k = (GEN)z[4];
        !           857:   /* reduce R */
        !           858:   z = polredabs0(C->R, nf_ORIG|nf_PARTIALFACT);
        !           859:   C->R = (GEN)z[1];
        !           860:   if (DEBUGLEVEL>1) fprintferr("polred(compositum) = %Z\n",C->R);
        !           861:   a    = (GEN)z[2];
        !           862:   C->p = poleval(lift_intern(C->p), a);
        !           863:   C->q = poleval(lift_intern(C->q), a);
        !           864:   C->rev = modreverse_i((GEN)a[2], (GEN)a[1]);
1.1       noro      865: }
                    866:
1.2     ! noro      867: static GEN
        !           868: _rnfkummer(GEN bnr, GEN subgroup, long all, long prec)
        !           869: {
        !           870:   long ell, i, j, m, d, dK, dc, rc, ru, rv, g, mginv, degK, degKz, vnf;
        !           871:   long l, lSp, lSml2, lSl2, lW;
        !           872:   GEN polnf,bnf,nf,bnfz,nfz,bid,ideal,cycgen,gell,p1,p2,wk,U,vselmer;
        !           873:   GEN clgp,cyc,gen;
        !           874:   GEN Q,idealz,gothf;
        !           875:   GEN res,u,M,K,y,vecMsup,vecW,vecWA,vecWB,vecB,vecC,vecAp,vecBp;
        !           876:   GEN matP,Sp,listprSp,Tc,Tv,P;
        !           877:   primlist L;
        !           878:   toK_s T;
        !           879:   tau_s _tau, *tau;
        !           880:   compo_s COMPO;
1.1       noro      881:
                    882:   checkbnrgen(bnr);
                    883:   bnf = (GEN)bnr[1];
1.2     ! noro      884:   nf  = (GEN)bnf[7];
        !           885:   polnf = (GEN)nf[1]; vnf = varn(polnf);
1.1       noro      886:   if (!vnf) err(talker,"main variable in kummer must not be x");
1.2     ! noro      887:   wk = gmael3(bnf,8,4,1);
        !           888:   /* step 7 */
        !           889:   if (all) subgroup = NULL;
        !           890:   p1 = conductor(bnr, subgroup, 2);
        !           891:   bnr      = (GEN)p1[2];
1.1       noro      892:   subgroup = (GEN)p1[3];
1.2     ! noro      893:   gell = get_gell(bnr,subgroup,all);
        !           894:   if (gcmp1(gell)) return polx[vnf];
        !           895:   if (!isprime(gell)) err(impl,"kummer for composite relative degree");
        !           896:   if (divise(wk,gell)) return rnfkummersimple(bnr, subgroup, gell, all);
        !           897:
        !           898:   bid = (GEN)bnr[2];
        !           899:   ideal = gmael(bid,1,1);
1.1       noro      900:   ell = itos(gell);
1.2     ! noro      901:   /* step 1 of alg 5.3.5. */
1.1       noro      902:   if (DEBUGLEVEL>2) fprintferr("Step 1\n");
1.2     ! noro      903:   compositum_red(&COMPO, polnf, cyclo(ell,vnf));
        !           904:   /* step 2 */
1.1       noro      905:   if (DEBUGLEVEL>2) fprintferr("Step 2\n");
1.2     ! noro      906:   degK  = degpol(polnf);
        !           907:   degKz = degpol(COMPO.R);
        !           908:   m = degKz / degK;
        !           909:   d = (ell-1) / m;
        !           910:   g = powuumod(u_gener(ell), d, ell);
        !           911:   if (powuumod(g, m, ell*ell) == 1) g += ell; /* ord(g)=m in all (Z/ell^k)^* */
        !           912:   /* step 3 */
1.1       noro      913:   if (DEBUGLEVEL>2) fprintferr("Step 3\n");
1.2     ! noro      914:   /* could factor disc(R) using th. 2.1.6. */
        !           915:   bnfz = bnfinit0(COMPO.R,1,NULL,prec);
        !           916:   cycgen = check_and_build_cycgen(bnfz);
1.1       noro      917:   nfz = (GEN)bnfz[7];
                    918:   clgp = gmael(bnfz,8,1);
1.2     ! noro      919:   cyc = (GEN)clgp[2]; rc = prank(cyc,ell);
        !           920:   gen = (GEN)clgp[3]; l = lg(cyc);
        !           921:   u = get_u(cyc, rc, gell);
        !           922:
        !           923:   vselmer = get_Selmer(bnfz, cycgen, rc);
        !           924:   ru = (degKz>>1)-1;
        !           925:   rv = rc+ru+1;
        !           926:
        !           927:   /* compute action of tau */
        !           928:   U = gadd(gpowgs(COMPO.q, g), gmul(COMPO.k, COMPO.p));
        !           929:   U = poleval(COMPO.rev, U);
        !           930:   tau = get_tau(&_tau, nfz, U);
        !           931:
        !           932:   /* step 4 */
1.1       noro      933:   if (DEBUGLEVEL>2) fprintferr("Step 4\n");
                    934:   vecB=cgetg(rc+1,t_VEC);
                    935:   Tc=cgetg(rc+1,t_MAT);
                    936:   for (j=1; j<=rc; j++)
                    937:   {
1.2     ! noro      938:     p1 = tauofideal(nfz, (GEN)gen[j], tau);
        !           939:     p1 = isprincipalell(bnfz, p1, cycgen,u,gell,rc);
1.1       noro      940:     Tc[j]  = p1[1];
                    941:     vecB[j]= p1[2];
                    942:   }
1.2     ! noro      943:
        !           944:   vecC = cgetg(rc+1,t_VEC);
        !           945:   for (j=1; j<=rc; j++) vecC[j] = lgetg(1, t_MAT);
        !           946:   p1 = cgetg(m,t_VEC);
        !           947:   p1[1] = (long)idmat(rc);
        !           948:   for (j=2; j<=m-1; j++) p1[j] = lmul((GEN)p1[j-1],Tc);
        !           949:   p2 = vecB;
1.1       noro      950:   for (j=1; j<=m-1; j++)
                    951:   {
1.2     ! noro      952:     GEN T = FpM_red(gmulsg((j*d)%ell,(GEN)p1[m-j]), gell);
        !           953:     p2 = tauofvec(p2, tau);
        !           954:     for (i=1; i<=rc; i++)
        !           955:       vecC[i] = (long)famat_mul((GEN)vecC[i], famat_factorback(p2, (GEN)T[i]));
1.1       noro      956:   }
1.2     ! noro      957:   for (i=1; i<=rc; i++) vecC[i] = (long)famat_reduce((GEN)vecC[i]);
        !           958:   /* step 5 */
1.1       noro      959:   if (DEBUGLEVEL>2) fprintferr("Step 5\n");
                    960:   Tv = cgetg(rv+1,t_MAT);
                    961:   for (j=1; j<=rv; j++)
                    962:   {
1.2     ! noro      963:     p1 = tauofelt((GEN)vselmer[j], tau);
        !           964:     if (typ(p1) == t_MAT) /* famat */
        !           965:       p1 = factorbackelt((GEN)p1[1], FpV_red((GEN)p1[2],gell), nfz);
        !           966:     Tv[j] = (long)isvirtualunit(bnfz, p1, cycgen,cyc,gell,rc);
        !           967:   }
        !           968:   P = FpM_ker(gsubgs(Tv, g), gell);
        !           969:   lW = lg(P); vecW = cgetg(lW,t_VEC);
        !           970:   for (j=1; j<lW; j++) vecW[j] = (long)famat_factorback(vselmer, (GEN)P[j]);
        !           971:   /* step 6 */
1.1       noro      972:   if (DEBUGLEVEL>2) fprintferr("Step 6\n");
1.2     ! noro      973:   Q = FpM_ker(gsubgs(gtrans(Tc), g), gell);
        !           974:   /* step 8 */
        !           975:   if (DEBUGLEVEL>2) fprintferr("Step 8\n");
        !           976:   p1 = RXQ_powers(lift_intern(COMPO.p), COMPO.R, degK-1);
        !           977:   p1 = vecpol_to_mat(p1, degKz);
        !           978:   T.invexpoteta1 = invmat(p1); /* left inverse */
        !           979:   T.polnf = polnf;
        !           980:   T.tau = tau;
        !           981:   T.m = m;
        !           982:
        !           983:   idealz = lifttoKz(nfz, nf, ideal, &COMPO);
        !           984:   if (smodis(idealnorm(nf,ideal), ell)) gothf = idealz;
1.1       noro      985:   else
1.2     ! noro      986:   { /* ell | N(ideal) */
        !           987:     GEN bnrz = buchrayinitgen(bnfz, idealz);
        !           988:     GEN subgroupz = invimsubgroup(bnrz, bnr, subgroup, &T);
1.1       noro      989:     gothf = conductor(bnrz,subgroupz,0);
                    990:   }
1.2     ! noro      991:   /* step 9, 10, 11 */
        !           992:   if (DEBUGLEVEL>2) fprintferr("Step 9, 10 and 11\n");
        !           993:   i = build_list_Hecke(&L, nfz, NULL, gothf, gell, tau);
        !           994:   if (i) return no_sol(all,i);
        !           995:
        !           996:   lSml2 = lg(L.Sml2)-1;
        !           997:   Sp = concatsp(L.Sm, L.Sml1); lSp = lg(Sp)-1;
        !           998:   listprSp = concatsp(L.Sml2, L.Sl); lSl2 = lg(listprSp)-1;
        !           999:
        !          1000:   /* step 12 */
1.1       noro     1001:   if (DEBUGLEVEL>2) fprintferr("Step 12\n");
1.2     ! noro     1002:   vecAp = cgetg(lSp+1, t_VEC);
        !          1003:   vecBp = cgetg(lSp+1, t_VEC);
        !          1004:   matP  = cgetg(lSp+1, t_MAT);
1.1       noro     1005:   for (j=1; j<=lSp; j++)
                   1006:   {
1.2     ! noro     1007:     GEN e, a, ap;
        !          1008:     p1 = isprincipalell(bnfz, (GEN)Sp[j], cycgen,u,gell,rc);
        !          1009:     e = (GEN)p1[1]; matP[j] = (long)e;
        !          1010:     a = (GEN)p1[2];
        !          1011:     p2 = famat_mul(famat_factorback(vecC, gneg(e)), a);
        !          1012:     vecBp[j] = (long)p2;
        !          1013:     ap = cgetg(1, t_MAT);
1.1       noro     1014:     for (i=0; i<m; i++)
                   1015:     {
1.2     ! noro     1016:       ap = famat_mul(ap, famat_pow(p2, utoi(powuumod(g,m-1-i,ell))));
        !          1017:       if (i < m-1) p2 = tauofelt(p2, tau);
1.1       noro     1018:     }
1.2     ! noro     1019:     vecAp[j] = (long)ap;
1.1       noro     1020:   }
1.2     ! noro     1021:   /* step 13 */
1.1       noro     1022:   if (DEBUGLEVEL>2) fprintferr("Step 13\n");
1.2     ! noro     1023:   vecWA = concatsp(vecW, vecAp);
        !          1024:   vecWB = concatsp(vecW, vecBp);
        !          1025:
        !          1026:   /* step 14, 15, and 17 */
        !          1027:   if (DEBUGLEVEL>2) fprintferr("Step 14, 15 and 17\n");
        !          1028:   mginv = (m * u_invmod(g,ell)) % ell;
        !          1029:   vecMsup = cgetg(lSml2+1,t_VEC);
        !          1030:   M = NULL;
        !          1031:   for (i=1; i<=lSl2; i++)
1.1       noro     1032:   {
1.2     ! noro     1033:     GEN pr = (GEN)listprSp[i];
1.1       noro     1034:     long e = itos((GEN)pr[3]), z = ell * (e / (ell-1));
1.2     ! noro     1035:
        !          1036:     if (i <= lSml2)
        !          1037:     {
        !          1038:       z += 1 - L.ESml2[i];
        !          1039:       vecMsup[i] = (long)logall(nfz, vecWA,lW,mginv,ell, pr,z+1);
        !          1040:     }
        !          1041:     M = vconcat(M, logall(nfz, vecWA,lW,mginv,ell, pr,z));
        !          1042:   }
        !          1043:   dc = lg(Q)-1;
        !          1044:   if (dc)
1.1       noro     1045:   {
1.2     ! noro     1046:     GEN QtP = gmul(gtrans_i(Q), matP);
        !          1047:     M = vconcat(M, concatsp(zeromat(dc,lW-1), QtP));
1.1       noro     1048:   }
1.2     ! noro     1049:   if (!M) M = zeromat(1, lSp + lW - 1);
        !          1050:   /* step 16 */
1.1       noro     1051:   if (DEBUGLEVEL>2) fprintferr("Step 16\n");
                   1052:   K = FpM_ker(M, gell);
1.2     ! noro     1053:   /* step 18 & ff */
1.1       noro     1054:   if (DEBUGLEVEL>2) fprintferr("Step 18\n");
1.2     ! noro     1055:   dK = lg(K)-1;
        !          1056:   y = cgetg(dK+1,t_VECSMALL);
        !          1057:   res = cgetg(1, t_VEC); /* in case all = 1 */
        !          1058:   while (dK)
1.1       noro     1059:   {
                   1060:     for (i=1; i<dK; i++) y[i] = 0;
1.2     ! noro     1061:     y[i] = 1; /* y = [0,...,0,1,0,...,0], 1 at dK'th position */
        !          1062:     do
        !          1063:     { /* cf. algo 5.3.18 */
        !          1064:       GEN be, P, X = FpV_red(gmul_mati_smallvec(K, y), gell);
        !          1065:       if (ok_congruence(X, gell, lW, vecMsup))
1.1       noro     1066:       {
1.2     ! noro     1067:         be = compute_beta(X, vecWB, gell, bnfz);
        !          1068:         P = compute_polrel(nfz, &T, be, g, ell);
        !          1069:         if (DEBUGLEVEL>1) fprintferr("polrel(beta) = %Z\n", P);
        !          1070:         if (!all && gegal(subgroup, rnfnormgroup(bnr, P))) return P; /* DONE */
        !          1071:         res = concatsp(res, P);
        !          1072:       }
        !          1073:     } while (increment(y, dK, ell));
        !          1074:     y[dK--] = 0;
1.1       noro     1075:   }
1.2     ! noro     1076:   if (all) return res;
        !          1077:   return gzero; /* FAIL */
        !          1078: }
        !          1079:
        !          1080: GEN
        !          1081: rnfkummer(GEN bnr, GEN subgroup, long all, long prec)
        !          1082: {
        !          1083:   gpmem_t av = avma;
        !          1084:   return gerepilecopy(av, _rnfkummer(bnr, subgroup, all, prec));
1.1       noro     1085: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>