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

Annotation of OpenXM_contrib/pari/src/modules/subfield.c, Revision 1.1

1.1     ! maekawa     1: /*******************************************************************/
        !             2: /*                                                                 */
        !             3: /*               SUBFIELDS OF A NUMBER FIELD                       */
        !             4: /*                                                                 */
        !             5: /*   J. Klueners and M. Pohst, J. Symb. Comp. (1996), vol. 11      */
        !             6: /*                                                                 */
        !             7: /*******************************************************************/
        !             8: /* $Id: subfield.c,v 1.1.1.1 1999/09/16 13:48:20 karim Exp $ */
        !             9: #include "pari.h"
        !            10: #ifdef __WIN32
        !            11: #  include <io.h> /* for open, read, close */
        !            12: #endif
        !            13: GEN roots_to_pol(GEN a, long v);
        !            14:
        !            15: static long TR; /* nombre de changements de polynomes (degre fixe) */
        !            16: static GEN FACTORDL; /* factorisation of |disc(L)| */
        !            17:
        !            18: static GEN print_block_system(long N,GEN Y,long d, GEN vbs);
        !            19: static GEN compute_data(GEN nf,GEN ff,GEN p,long m,long nn);
        !            20:
        !            21: /* Computation of potential block systems of given size d associated to a
        !            22:  * rational prime p: give a row vector of row vectors containing the
        !            23:  * potential block systems of imprimitivity; a potential block system is a
        !            24:  * vector of row vectors (enumeration of the roots).
        !            25:  */
        !            26: #define BIL 32 /* for 64bit machines also */
        !            27: static GEN
        !            28: calc_block(long N,GEN Z,long d,GEN Y,GEN vbs)
        !            29: {
        !            30:   long r,lK,i,j,k,t,tp,T,lpn,u,nn,lnon,lY;
        !            31:   GEN K,n,non,pn,pnon,e,Yp,Zp,Zpp;
        !            32:
        !            33:   if (DEBUGLEVEL>3)
        !            34:   {
        !            35:     long l = vbs? lg(vbs): 0;
        !            36:     fprintferr("avma = %ld, lg(Z) = %ld, lg(Y) = %ld, lg(vbs) = %ld\n",
        !            37:                avma,lg(Z),lg(Y),l);
        !            38:     if (DEBUGLEVEL > 5)
        !            39:     {
        !            40:       fprintferr("Z = %Z\n",Z);
        !            41:       fprintferr("Y = %Z\n",Y);
        !            42:       if (DEBUGLEVEL > 7) fprintferr("vbs = %Z\n",vbs);
        !            43:     }
        !            44:   }
        !            45:   r=lg(Z); lnon = min(BIL, r);
        !            46:   e    = new_chunk(BIL);
        !            47:   n    = new_chunk(r);
        !            48:   non  = new_chunk(lnon);
        !            49:   pnon = new_chunk(lnon);
        !            50:   pn   = new_chunk(lnon);
        !            51:   Zp   = cgetg(lnon,t_VEC);
        !            52:   Zpp  = cgetg(lnon,t_VEC);
        !            53:   for (i=1; i<r; i++) n[i] = lg(Z[i])-1;
        !            54:
        !            55:   K=divisors(stoi(n[1])); lK=lg(K);
        !            56:   for (i=1; i<lK; i++)
        !            57:   {
        !            58:     lpn=0; k = itos((GEN)K[i]);
        !            59:     for (j=2; j<r; j++)
        !            60:       if (n[j]%k == 0)
        !            61:       {
        !            62:         if (++lpn >= BIL) err(talker,"overflow in calc_block");
        !            63:         pn[lpn]=n[j]; pnon[lpn]=j;
        !            64:       }
        !            65:     if (!lpn)
        !            66:     {
        !            67:       if (d*k != n[1]) continue;
        !            68:       T=1; lpn=1;
        !            69:     }
        !            70:     else
        !            71:       T = 1<<lpn;
        !            72:     for (t=0; t<T; t++)
        !            73:     {
        !            74:       for (nn=n[1],tp=t, u=1; u<=lpn; u++,tp>>=1)
        !            75:       {
        !            76:         if (tp&1) { nn += pn[u]; e[u]=1; } else e[u]=0;
        !            77:       }
        !            78:       if (d*k == nn)
        !            79:       {
        !            80:        long av=avma;
        !            81:         int Z_equal_Zp = 1;
        !            82:
        !            83:         for (j=1; j<lnon; j++) non[j]=0;
        !            84:         Zp[1]=Z[1];
        !            85:        for (u=2,j=1; j<=lpn; j++)
        !            86:          if (e[j])
        !            87:           {
        !            88:             Zp[u]=Z[pnon[j]]; non[pnon[j]]=1;
        !            89:             if (Zp[u] != Z[u]) Z_equal_Zp = 0;
        !            90:             u++;
        !            91:           }
        !            92:         setlg(Zp, u);
        !            93:         lY=lg(Y); Yp = cgetg(lY+1,t_VEC);
        !            94:         for (j=1; j<lY; j++) Yp[j]=Y[j];
        !            95:        Yp[lY]=(long)Zp;
        !            96:         if (r == u && Z_equal_Zp)
        !            97:          vbs = print_block_system(N,Yp,d,vbs);
        !            98:        else
        !            99:        {
        !           100:          for (u=1,j=2; j<r; j++)
        !           101:            if (!non[j]) Zpp[u++] = Z[j];
        !           102:           setlg(Zpp, u);
        !           103:          vbs = calc_block(N,Zpp,d,Yp,vbs);
        !           104:        }
        !           105:         avma=av;
        !           106:       }
        !           107:     }
        !           108:   }
        !           109:   return vbs;
        !           110: }
        !           111:
        !           112: static GEN
        !           113: potential_block_systems(long N, long d,GEN ff,long *n)
        !           114: {
        !           115:   long av=avma,r,i,j,k;
        !           116:   GEN p1,vbs,Z;
        !           117:
        !           118:   r=lg(ff); Z=cgetg(r,t_VEC);
        !           119:   for (k=0,i=1; i<r; i++)
        !           120:   {
        !           121:     p1=cgetg(n[i]+1,t_VECSMALL); Z[i]=(long)p1;
        !           122:     for (j=1; j<=n[i]; j++) p1[j]= ++k;
        !           123:   }
        !           124:   vbs=calc_block(N,Z,d, cgetg(1,t_VEC), NULL);
        !           125:   avma=av; return vbs;
        !           126: }
        !           127:
        !           128: /* product of permutations. Put the result in perm1. */
        !           129: static void
        !           130: perm_mul(GEN perm1,GEN perm2)
        !           131: {
        !           132:   long av = avma,i, N = lg(perm1);
        !           133:   GEN perm=new_chunk(N);
        !           134:   for (i=1; i<N; i++) perm[i]=perm1[perm2[i]];
        !           135:   for (i=1; i<N; i++) perm1[i]=perm[i];
        !           136:   avma=av;
        !           137: }
        !           138:
        !           139: /* cy is a cycle; compute cy^l as a permutation */
        !           140: static GEN
        !           141: cycle_power_to_perm(GEN perm,GEN cy,long l)
        !           142: {
        !           143:   long lp,i,j,b, N = lg(perm), lcy = lg(cy)-1;
        !           144:
        !           145:   lp = l % lcy;
        !           146:   for (i=1; i<N; i++) perm[i] = i;
        !           147:   if (lp)
        !           148:   {
        !           149:     long av = avma;
        !           150:     GEN p1 = new_chunk(N);
        !           151:     b = cy[1];
        !           152:     for (i=1; i<lcy; i++) b = (perm[b] = cy[i+1]);
        !           153:     perm[b] = cy[1];
        !           154:     for (i=1; i<N; i++) p1[i] = perm[i];
        !           155:
        !           156:     for (j=2; j<=lp; j++) perm_mul(perm,p1);
        !           157:     avma = av;
        !           158:   }
        !           159:   return perm;
        !           160: }
        !           161:
        !           162: /* image du block system D par la permutation perm */
        !           163: static GEN
        !           164: im_block_by_perm(GEN D,GEN perm)
        !           165: {
        !           166:   long i,j,lb,lcy;
        !           167:   GEN Dn,cy,p1;
        !           168:
        !           169:   lb=lg(D); Dn=cgetg(lb,t_VEC);
        !           170:   for (i=1; i<lb; i++)
        !           171:   {
        !           172:     cy=(GEN)D[i]; lcy=lg(cy);
        !           173:     Dn[i]=lgetg(lcy,t_VECSMALL); p1=(GEN)Dn[i];
        !           174:     for (j=1; j<lcy; j++) p1[j] = perm[cy[j]];
        !           175:   }
        !           176:   return Dn;
        !           177: }
        !           178:
        !           179: /* cy is a cycle; recturn cy(a) */
        !           180: static long
        !           181: im_by_cy(long a,GEN cy)
        !           182: {
        !           183:   long k, l = lg(cy);
        !           184:
        !           185:   k=1; while (k<l && cy[k] != a) k++;
        !           186:   if (k == l) return a;
        !           187:   k++; if (k == l) k = 1;
        !           188:   return cy[k];
        !           189: }
        !           190:
        !           191: /* renvoie 0 si l'un des coefficients de g[i] est de module > M[i]; 1 sinon */
        !           192: static long
        !           193: ok_coeffs(GEN g,GEN M)
        !           194: {
        !           195:   long i, lg = lgef(g)-1; /* g is monic, and cst term is ok */
        !           196:   for (i=3; i<lg; i++)
        !           197:     if (absi_cmp((GEN)g[i], (GEN)M[i]) > 0) return 0;
        !           198:   return 1;
        !           199: }
        !           200:
        !           201: /* vbs[0] = current cardinality+1, vbs[1] = max number of elts */
        !           202: static GEN
        !           203: append_vbs(GEN vbs, GEN D)
        !           204: {
        !           205:   long l,maxl,i,j,n, lD = lg(D);
        !           206:   GEN Dn, last;
        !           207:
        !           208:   n = 0; for (i=1; i<lD; i++) n += lg(D[i]);
        !           209:   Dn = (GEN)gpmalloc((lD + n) * sizeof(long));
        !           210:   last = Dn + lD; Dn[0] = D[0];
        !           211:   for (i=1; i<lD; i++)
        !           212:   {
        !           213:     GEN cy = (GEN)D[i], cn = last;
        !           214:     for (j=0; j<lg(cy); j++) cn[j] = cy[j];
        !           215:     Dn[i] = (long)cn; last = cn + j;
        !           216:   }
        !           217:
        !           218:   if (!vbs)
        !           219:   {
        !           220:     maxl = 1024;
        !           221:     vbs = (GEN)gpmalloc((2 + maxl)*sizeof(GEN));
        !           222:     *vbs = maxl; vbs++; setlg(vbs, 1);
        !           223:   }
        !           224:   l = lg(vbs); maxl = vbs[-1];
        !           225:   if (l == maxl)
        !           226:   {
        !           227:     vbs = (GEN)gprealloc((void*)(vbs-1), (2 + (maxl<<1))*sizeof(GEN),
        !           228:                                          (2 + maxl)*sizeof(GEN));
        !           229:     *vbs = maxl<<1; vbs++; setlg(vbs, 1);
        !           230:   }
        !           231:   if (DEBUGLEVEL>5) fprintferr("appending D = %Z\n",D);
        !           232:   vbs[l] = (long)Dn; setlg(vbs, l+1); return vbs;
        !           233: }
        !           234:
        !           235: GEN
        !           236: myconcat(GEN D, long a)
        !           237: {
        !           238:   long i,l = lg(D);
        !           239:   GEN x = cgetg(l+1,t_VECSMALL);
        !           240:   for (i=1; i<l; i++) x[i]=D[i];
        !           241:   x[l] = a; return x;
        !           242: }
        !           243:
        !           244: void
        !           245: myconcat2(GEN D, GEN a)
        !           246: {
        !           247:   long i,l = lg(D), m = lg(a);
        !           248:   GEN x = D + (l-1);
        !           249:   for (i=1; i<m; i++) x[i]=a[i];
        !           250:   setlg(D, l+m-1);
        !           251: }
        !           252:
        !           253: static GEN
        !           254: print_block_system(long N,GEN Y,long d, GEN vbs)
        !           255: {
        !           256:   long a,i,j,l,ll,*k,*n,lp,**e,u,v,*t,ns, r = lg(Y);
        !           257:   GEN D,De,Z,cyperm,perm,p1,empty;
        !           258:
        !           259:   if (DEBUGLEVEL>5) fprintferr("Y = %Z\n",Y);
        !           260:   empty = cgetg(1,t_VEC);
        !           261:   n = new_chunk(N+1);
        !           262:   D = cgetg(N+1, t_VEC); setlg(D,1);
        !           263:   t=new_chunk(r+1); k=new_chunk(r+1); Z=cgetg(r+1,t_VEC);
        !           264:   for (ns=0,i=1; i<r; i++)
        !           265:   {
        !           266:     GEN Yi = (GEN)Y[i], cy;
        !           267:     long ki = 0, si = lg(Yi)-1;
        !           268:
        !           269:     for (j=1; j<=si; j++) { n[j]=lg(Yi[j])-1; ki += n[j]; }
        !           270:     ki /= d;
        !           271:     De=cgetg(ki+1,t_VEC);
        !           272:     for (j=1; j<=ki; j++) De[j]=(long)empty;
        !           273:     for (j=1; j<=si; j++)
        !           274:     {
        !           275:       a = mael(Yi,j,1); cy = (GEN)Yi[j];
        !           276:       for (l=1,lp=0; l<=n[j]; l++)
        !           277:       {
        !           278:         lp++; if (lp>ki) lp = 1;
        !           279:         a = im_by_cy(a, cy);
        !           280:         De[lp] = (long)myconcat((GEN)De[lp], a);
        !           281:       }
        !           282:     }
        !           283:     if (si>1 && ki>1)
        !           284:     {
        !           285:       ns++; t[ns]=si-1; k[ns]=ki;
        !           286:       Z[ns]=lgetg(si,t_VEC); p1=(GEN)Z[ns];
        !           287:       for (j=2; j<=si; j++) p1[j-1]=Yi[j];
        !           288:     }
        !           289:     myconcat2(D,De);
        !           290:   }
        !           291:   if (DEBUGLEVEL>2) { fprintferr("\nns = %ld\n",ns); flusherr(); }
        !           292:   if (!ns) return append_vbs(vbs,D);
        !           293:
        !           294:   setlg(Z, ns+1);
        !           295:   e=(long**)new_chunk(ns+1);
        !           296:   for (i=1; i<=ns; i++)
        !           297:   {
        !           298:     e[i]=new_chunk(t[i]+1);
        !           299:     for (j=1; j<=t[i]; j++) e[i][j]=0;
        !           300:   }
        !           301:   cyperm = cgetg(N+1,t_VEC);
        !           302:   perm = cgetg(N+1,t_VEC); i=ns;
        !           303:   do
        !           304:   {
        !           305:     long av = avma;
        !           306:     if (DEBUGLEVEL>5)
        !           307:     {
        !           308:       for (l=1; l<=ns; l++)
        !           309:       {
        !           310:        for (ll=1; ll<=t[l]; ll++)
        !           311:          fprintferr("e[%ld][%ld] = %ld, ",l,ll,e[l][ll]);
        !           312:        fprintferr("\n");
        !           313:       }
        !           314:       fprintferr("\n"); flusherr();
        !           315:     }
        !           316:     for (u=1; u<=N; u++) perm[u]=u;
        !           317:     for (u=1; u<=ns; u++)
        !           318:       for (v=1; v<=t[u]; v++)
        !           319:        perm_mul(perm, cycle_power_to_perm(cyperm,gmael(Z,u,v),e[u][v]));
        !           320:     vbs = append_vbs(vbs, im_block_by_perm(D,perm));
        !           321:     avma = av;
        !           322:
        !           323:     e[ns][t[ns]]++;
        !           324:     if (e[ns][t[ns]] >= k[ns])
        !           325:     {
        !           326:       j=t[ns]-1;
        !           327:       while (j>=1 && e[ns][j] == k[ns]-1) j--;
        !           328:       if (j>=1) { e[ns][j]++; for (l=j+1; l<=t[ns]; l++) e[ns][l]=0; }
        !           329:       else
        !           330:       {
        !           331:        i=ns-1;
        !           332:        while (i>=1)
        !           333:        {
        !           334:          j=t[i];
        !           335:          while (j>=1 && e[i][j] == k[i]-1) j--;
        !           336:          if (j<1) i--;
        !           337:           else
        !           338:          {
        !           339:            e[i][j]++;
        !           340:            for (l=j+1; l<=t[i]; l++) e[i][l]=0;
        !           341:            for (ll=i+1; ll<=ns; ll++)
        !           342:               for (l=1; l<=t[ll]; l++) e[ll][l]=0;
        !           343:             break;
        !           344:          }
        !           345:        }
        !           346:       }
        !           347:     }
        !           348:   }
        !           349:   while (i>0);
        !           350:   return vbs;
        !           351: }
        !           352:
        !           353: /* rend le numero du cycle (a1,...,an) dans le support duquel se trouve a */
        !           354: /* met dans *pt l'indice i tq ai = a */
        !           355: static long
        !           356: in_what_cycle(long a,GEN cys,long *pt)
        !           357: {
        !           358:   long i,k,nk, lcys=lg(cys);
        !           359:
        !           360:   for (k=1; k<lcys; k++)
        !           361:   {
        !           362:     GEN c = (GEN)cys[k]; nk = lg(c);
        !           363:     for (i=1; i<nk; i++)
        !           364:       if (a == c[i]) { *pt = i; return k; }
        !           365:   }
        !           366:   err(talker,"impossible to find %d in in_what_cycle",a);
        !           367:   return 0; /* not reached */
        !           368: }
        !           369:
        !           370: /* Return common factors to A and B + s the prime to A part of B */
        !           371: static GEN
        !           372: commonfactor(GEN A, GEN B)
        !           373: {
        !           374:   GEN f,p1,p2,s, y = cgetg(3,t_MAT);
        !           375:   long lf,i;
        !           376:
        !           377:   s = absi(B); f=(GEN)A[1]; lf=lg(f);
        !           378:   p1=cgetg(lf+1,t_COL); y[1]=(long)p1;
        !           379:   p2=cgetg(lf+1,t_COL); y[2]=(long)p2;
        !           380:   for (i=1; i<lf; i++)
        !           381:   {
        !           382:     p1[i] = f[i];
        !           383:     p2[i] = lstoi(pvaluation(s,(GEN)f[i], &s));
        !           384:   }
        !           385:   p1[i] = (long)s;
        !           386:   p2[i] = un; return y;
        !           387: }
        !           388:
        !           389: static void
        !           390: polsimplify(GEN x)
        !           391: {
        !           392:   long i,lx = lgef(x);
        !           393:   for (i=2; i<lx; i++)
        !           394:     if (typ(x[i]) == t_POL) x[i] = signe(x[i])? mael(x,i,2): zero;
        !           395: }
        !           396:
        !           397: /* Renvoie un polynome g definissant un sous-corps potentiel, ou
        !           398:  * 0: si le polynome trouve n'est pas separable,
        !           399:  * 1: si les coefficients du polynome trouve sont plus grands que la borne M,
        !           400:  * 2: si p divise le discriminant de g,
        !           401:  * 3: si le discriminant de g est nul,
        !           402:  * 4: si la partie s de d(g) premiere avec d(L) n'est pas un carre,
        !           403:  * 5: si s est un carre et si un des facteurs premiers communs a d(g) et d(L)
        !           404:  *    a un exposant impair dans d(g) et un exposant plus petit que d dans d(L),
        !           405:  * 6: si le discriminant du corps defini par g a la puissance d ne divise pas
        !           406:  *        le discriminant du corps nf (soit L).
        !           407:  */
        !           408: static GEN
        !           409: cand_for_subfields(GEN A,GEN DATA,GEN *ptdelta,GEN *ptrootsA)
        !           410: {
        !           411:   long av=avma,N,m,i,j,d,lf;
        !           412:   GEN P,pe,p,pol,cys,tabroots,delta,g,dg,unmodpe,tabrA;
        !           413:   GEN factcommon,ff1,ff2,p1;
        !           414:   GEN *gptr[3];
        !           415:
        !           416:   pol=(GEN)DATA[1]; N=lgef(pol)-3; m=lg(A)-1; d=N/m;
        !           417:   if (N%m) err(talker,"incompatible block system in cand_for_subfields");
        !           418:   p = (GEN)DATA[2];
        !           419:   cys=(GEN)DATA[5];
        !           420:   tabroots=(GEN)DATA[10];
        !           421:   pe = gclone((GEN)DATA[9]);
        !           422:   unmodpe = cgetg(3,t_INTMOD); unmodpe[1]=(long)pe; unmodpe[2]=un;
        !           423:
        !           424:   delta = cgetg(m+1,t_VEC);
        !           425:   tabrA = cgetg(m+1,t_VEC);
        !           426:   for (i=1; i<=m; i++)
        !           427:   {
        !           428:     GEN Ai=(GEN)A[i], col = cgetg(d+1,t_VEC);
        !           429:     long l,k;
        !           430:
        !           431:     tabrA[i]=(long)col; p1 = unmodpe;
        !           432:     for (j=1; j<=d; j++)
        !           433:     {
        !           434:       l=in_what_cycle(Ai[j],cys,&k);
        !           435:       col[j] = mael(tabroots, l, k);
        !           436:       p1 = gmul(p1, (GEN)col[j]);
        !           437:     }
        !           438:     p1 = lift_intern((GEN)p1[2]);
        !           439:     for (j=1; j<i; j++)
        !           440:       if (gegal(p1,(GEN)delta[j])) { avma=av; return gzero; }
        !           441:     if (DEBUGLEVEL>2) fprintferr("delta[%ld] = %Z\n",i,p1);
        !           442:     delta[i] = (long)p1;
        !           443:   }
        !           444:   P = gmael3(tabroots,1,1,1);
        !           445:   for (i=1; i<=m; i++)
        !           446:   {
        !           447:     p1 = cgetg(3,t_POLMOD); p1[1]=(long)P; p1[2]=delta[i];
        !           448:     delta[i] = (long)p1;
        !           449:   }
        !           450:   g = roots_to_pol(gmul(unmodpe,delta),0);
        !           451:   g=centerlift(lift_intern(g)); polsimplify(g);
        !           452:   if (DEBUGLEVEL>2) fprintferr("pol. found = %Z\n",g);
        !           453:   if (!ok_coeffs(g,(GEN)DATA[8])) return gun;
        !           454:   dg=discsr(g);
        !           455:   if (!signe(dg)) return stoi(3);
        !           456:   if (!signe(resii(dg,p))) return gdeux;
        !           457:   factcommon=commonfactor(FACTORDL,dg);
        !           458:   ff1=(GEN)factcommon[1]; lf=lg(ff1)-1;
        !           459:   if (!carreparfait((GEN)ff1[lf])) return stoi(4);
        !           460:   ff2=(GEN)factcommon[2];
        !           461:   for (i=1; i<lf; i++)
        !           462:     if (mod2((GEN)ff2[i]) && itos(gmael(FACTORDL,2,i)) < d) return stoi(5);
        !           463:   gunclone(pe);
        !           464:
        !           465:   *ptdelta=delta; *ptrootsA=tabrA;
        !           466:   gptr[0]=&g; gptr[1]=ptdelta; gptr[2]=ptrootsA;
        !           467:   gerepilemany(av,gptr,3); return g;
        !           468: }
        !           469:
        !           470: /* a partir d'un polynome h(x) dont les coefficients sont definis mod p^k,
        !           471:  * on construit un polynome a coefficients dans Q dont les coefficients ont
        !           472:  * pour approximation p-adique les coefficients de h */
        !           473: static GEN
        !           474: retrieve_p_adique_polynomial_in_Q(GEN ind,GEN h)
        !           475: {
        !           476:   return gdiv(centerlift(gmul(h,ind)), ind);
        !           477: }
        !           478:
        !           479: /* interpolation polynomial P(x) s.t P(T[j][i]) = delta[i] mod p */
        !           480: static GEN
        !           481: interpolation_polynomial(GEN T, GEN delta)
        !           482: {
        !           483:   long i,j,i1,j1, m = lg(T), d = lg(T[1]);
        !           484:   GEN P = NULL, x0 = gneg(polx[0]);
        !           485:
        !           486:   for (j=1; j<m; j++)
        !           487:   {
        !           488:     GEN p3 = NULL;
        !           489:     for (i=1; i<d; i++)
        !           490:     {
        !           491:       GEN p1=gun, p2=gun, a = gneg(gmael(T,j,i));
        !           492:       for (j1=1; j1<m; j1++)
        !           493:         for (i1=1; i1<d; i1++)
        !           494:           if (i1 != i || j1 != j)
        !           495:           {
        !           496:             p1 = gmul(p1,gadd(gmael(T,j1,i1), x0));
        !           497:             p2 = gmul(p2,gadd(gmael(T,j1,i1), a));
        !           498:           }
        !           499:       p1 = gdiv(p1,p2);
        !           500:       p3 = p3? gadd(p3, p1): p1;
        !           501:     }
        !           502:     p3 = gmul((GEN)delta[j],p3);
        !           503:     P = P? gadd(P,p3): p3;
        !           504:   }
        !           505:   return P;
        !           506: }
        !           507:
        !           508: /* nf est le corps de nombres, g un polynome de Z[x] candidat
        !           509:  * pour definir un sous-corps, p le nombre premier ayant servi a definir le
        !           510:  * potential block system rootsA donne par les racines avec une approximation
        !           511:  * convenable, e est la precision p-adique des elements de rootsA et delta la
        !           512:  * liste des racines de g dans une extension convenable en precision p^e.
        !           513:  * Renvoie un polynome h de Q[x] tel que f divise g o h et donc tel que le
        !           514:  * couple (g,h) definisse un sous-corps, ou bien gzero si rootsA n'est pas un
        !           515:  * block system
        !           516:  */
        !           517: static GEN
        !           518: embedding_of_potential_subfields(GEN nf,GEN g,GEN DATA,GEN rootsA,GEN delta)
        !           519: {
        !           520:   GEN w0_inQ,w0,w1,h0,gp,p2,f,unmodp,p,ind, maxp;
        !           521:   long av = avma, av1;
        !           522:
        !           523:   f=(GEN)nf[1]; ind=(GEN)nf[4]; p=(GEN)DATA[2];
        !           524:   maxp=mulii((GEN)DATA[11],ind);
        !           525:   gp=deriv(g,varn(g)); unmodp=gmodulsg(1,p);
        !           526:   av1 = avma;
        !           527:   w0 = interpolation_polynomial(gmul(rootsA,unmodp), delta);
        !           528:   w0 = lift_intern(w0); /* in Fp[x] */
        !           529:   polsimplify(w0);
        !           530:   w0_inQ = retrieve_p_adique_polynomial_in_Q(ind,w0);
        !           531:   (void)gbezout(poleval(gp,w0), gmul(unmodp,f), &h0, &p2);
        !           532:   w0 = lift_intern(w0); /* in Z[x] */
        !           533:   h0 = lift_intern(lift_intern(h0));
        !           534:   for(;;)
        !           535:   {
        !           536:     GEN p1;
        !           537:    /* Given g in Z[x], gp its derivative, p a prime, [w0,h0] in Z[x] s.t.
        !           538:     * h0(x).gp(w0(x)) = 1 and g(w0(x))  = 0 (mod f,mod p), return
        !           539:     * [w1,h1]  satisfying the same condition mod p^2. Moreover,
        !           540:     * [w1,h1] = [w0,h0] (mod p)
        !           541:     * (cf. Dixon: J. Austral. Math. Soc., Series A, vol.49, 1990, p.445) */
        !           542:     if (DEBUGLEVEL>2)
        !           543:     {
        !           544:       fprintferr("w = "); outerr(w0);
        !           545:       fprintferr("h = "); outerr(h0);
        !           546:     }
        !           547:     p = sqri(p); unmodp[1] = (long)p;
        !           548:     p1 = gneg(gmul(h0, poleval(g,w0)));
        !           549:     w1 = gres(gmul(unmodp,gadd(w0,p1)), f);
        !           550:     p2 = retrieve_p_adique_polynomial_in_Q(ind,w1);
        !           551:     if ((gegal(p2, w0_inQ) || cmpii(p,maxp)) && gdivise(poleval(g,p2), f))
        !           552:       return gerepileupto(av, poleval(p2, gadd(polx[0],stoi(TR))));
        !           553:     if (DEBUGLEVEL>2)
        !           554:     {
        !           555:       fprintferr("Old Q-polynomial: "); outerr(w0_inQ);
        !           556:       fprintferr("New Q-polynomial: "); outerr(p2);
        !           557:     }
        !           558:     if (cmpii(p, maxp) > 0)
        !           559:     {
        !           560:       if (DEBUGLEVEL) fprintferr("coeff too big for embedding\n");
        !           561:       avma=av; return gzero;
        !           562:     }
        !           563:
        !           564:     w1 = lift_intern(w1);
        !           565:     p1 = gneg(gmul(h0, poleval(gp,w1)));
        !           566:     p1 = gmul(h0, gadd(gdeux,p1));
        !           567:     h0 = lift_intern(gres(gmul(unmodp,p1), f));
        !           568:     w0 = w1; w0_inQ = p2;
        !           569:     {
        !           570:       GEN *gptr[4]; gptr[0]=&w0; gptr[1]=&h0; gptr[2]=&w0_inQ; gptr[3]=&p;
        !           571:       gerepilemany(av1,gptr,4);
        !           572:     }
        !           573:   }
        !           574: }
        !           575:
        !           576: static long
        !           577: choose_prime(GEN pol,GEN dpol,long d,GEN *ptff,GEN *ptlistpotbl, long *ptnn)
        !           578: {
        !           579:   long j,k,oldllist,llist,r,nn,oldnn,*n,N,pp;
        !           580:   GEN p,listpotbl,oldlistpotbl,ff,oldff,p3;
        !           581:   byteptr di=diffptr;
        !           582:
        !           583:   if (DEBUGLEVEL) timer2();
        !           584:   di++; p = stoi(2); N = lgef(pol)-3;
        !           585:   while (p[2]<=N) p[2] += *di++;
        !           586:   oldllist = oldnn = BIGINT;
        !           587:   n = new_chunk(N+1);
        !           588:   for(k=1; k<11 || oldnn == BIGINT; k++,p[2]+= *di++)
        !           589:   {
        !           590:     long av=avma;
        !           591:     while (!smodis(dpol,p[2])) p[2] += *di++;
        !           592:     ff=(GEN)factmod(pol,p)[1]; r=lg(ff)-1;
        !           593:     if (r>1 && r<N)
        !           594:     {
        !           595:       for (j=1; j<=r; j++) n[j]=lgef(ff[j])-3;
        !           596:       p3 = stoi(n[1]);
        !           597:       for (j=2; j<=r; j++) p3 = glcm(p3,stoi(n[j]));
        !           598:       nn=itos(p3);
        !           599:       if (nn > oldnn)
        !           600:       {
        !           601:         if (DEBUGLEVEL)
        !           602:         {
        !           603:           fprintferr("p = %ld,\tr = %ld,\tnn = %ld,\t#pbs = skipped\n",
        !           604:                       p[2],r,nn);
        !           605:         }
        !           606:         continue;
        !           607:       }
        !           608:       listpotbl=potential_block_systems(N,d,ff,n);
        !           609:       if (!listpotbl) { oldlistpotbl = NULL; pp = p[2]; break; }
        !           610:       llist=lg(listpotbl)-1;
        !           611:       if (DEBUGLEVEL)
        !           612:       {
        !           613:        fprintferr("Time: %ldms,\tp = %ld,\tr = %ld,\tnn = %ld,\t#pbs = %ld\n",
        !           614:                     timer2(),p[2],r,nn,llist);
        !           615:        flusherr();
        !           616:       }
        !           617:       if (nn<oldnn || llist<oldllist)
        !           618:       {
        !           619:        oldllist=llist; oldlistpotbl=listpotbl;
        !           620:        pp=p[2]; oldff=ff; oldnn=nn; continue;
        !           621:       }
        !           622:       for (j=1; j<llist; j++) free((void*)listpotbl[j]);
        !           623:       free((void*)(listpotbl-1));
        !           624:     }
        !           625:     avma = av;
        !           626:   }
        !           627:   if (DEBUGLEVEL)
        !           628:   {
        !           629:     fprintferr("Chosen prime: p = %ld\n",pp);
        !           630:     if (DEBUGLEVEL>2)
        !           631:       fprintferr("List of potential block systems of size %ld: %Z\n",
        !           632:                   d,oldlistpotbl);
        !           633:     flusherr();
        !           634:   }
        !           635:   *ptlistpotbl=oldlistpotbl; *ptff=oldff; *ptnn=oldnn; return pp;
        !           636: }
        !           637:
        !           638: static GEN
        !           639: change_pol(GEN nf, GEN ff)
        !           640: {
        !           641:   long i,l;
        !           642:   GEN pol = (GEN)nf[1], p1 = gsub(polx[0],gun);
        !           643:
        !           644:   TR++; pol=poleval(pol, p1);
        !           645:   nf = dummycopy(nf);
        !           646:   nf[6] = (long)dummycopy((GEN)nf[6]);
        !           647:   l=lg(ff);
        !           648:   for (i=1; i<l; i++) ff[i]=(long)poleval((GEN)ff[i], p1);
        !           649:   l=lg(nf[6]); p1=(GEN)nf[6];
        !           650:   for (i=1; i<l; i++) p1[i]=ladd(gun,(GEN)p1[i]);
        !           651:   nf[1]=(long)pol; return nf;
        !           652: }
        !           653:
        !           654: static GEN
        !           655: bound_for_coeff(long m,GEN rr,long r1, GEN *maxroot)
        !           656: {
        !           657:   long i, lrr=lg(rr);
        !           658:   GEN p1,b1,b2,B,M, C = matpascal(m-1);
        !           659:
        !           660:   rr = gabs(rr,DEFAULTPREC); *maxroot = vecmax(rr);
        !           661:   for (i=1; i<lrr; i++)
        !           662:     if (gcmp((GEN)rr[i], gun) < 0) rr[i] = un;
        !           663:   for (b1=gun,i=1; i<=r1; i++) b1 = gmul(b1, (GEN)rr[i]);
        !           664:   for (b2=gun    ; i<lrr; i++) b2 = gmul(b2, (GEN)rr[i]);
        !           665:   B = gmul(b1, gsqr(b2));
        !           666:   M = cgetg(m+2, t_VEC); M[1]=M[2]=zero; /* unused */
        !           667:   for (i=1; i<m; i++)
        !           668:   {
        !           669:     p1 = gadd(gmul(gcoeff(C, m, i), B),
        !           670:               gcoeff(C, m, i+1));
        !           671:     M[i+2] = lceil(p1);
        !           672:   }
        !           673:   return M;
        !           674: }
        !           675:
        !           676: /* liste des sous corps de degre d du corps de nombres nf */
        !           677: static GEN
        !           678: subfields_of_given_degree(GEN nf,GEN dpol,long d)
        !           679: {
        !           680:   long av,av1,av2,tetpil,pp,llist,i,nn,N;
        !           681:   GEN listpotbl,ff,A,delta,rootsA,CSF,ESF,p1,p2,LSB;
        !           682:   GEN DATA, pol = (GEN)nf[1];
        !           683:
        !           684:   av=avma;
        !           685:   N = lgef(pol)-3;
        !           686:   pp=choose_prime(pol,dpol,N/d,&ff,&listpotbl,&nn);
        !           687:   if (!listpotbl) { avma=av; return cgetg(1,t_VEC); }
        !           688:   llist=lg(listpotbl);
        !           689: LAB0:
        !           690:   av1=avma; LSB=cgetg(1,t_VEC);
        !           691:   DATA=compute_data(nf,ff,stoi(pp),d,nn);
        !           692:   for (i=1; i<llist; i++)
        !           693:   {
        !           694:     av2=avma; A=(GEN)listpotbl[i];
        !           695:     if (DEBUGLEVEL > 1)
        !           696:       fprintferr("\n* Potential block # %ld: %Z\n",i,A);
        !           697:     CSF=cand_for_subfields(A,DATA,&delta,&rootsA);
        !           698:     if (typ(CSF)==t_INT)
        !           699:     {
        !           700:       if (DEBUGLEVEL > 1) switch(itos(CSF))
        !           701:       {
        !           702:         case 0: fprintferr("changing f(x): non separable g(x)\n"); break;
        !           703:         case 1: fprintferr("coeff too big for pol g(x)\n"); break;
        !           704:         case 2: fprintferr("changing f(x): p divides disc(g(x))\n"); break;
        !           705:         case 3: fprintferr("non irreducible polynomial g(x)\n"); break;
        !           706:         case 4: fprintferr("prime to d(L) part of d(g) not a square\n"); break;
        !           707:         case 5: fprintferr("too small exponent of a prime factor in d(L)\n"); break;
        !           708:         case 6: fprintferr("the d-th power of d(K) does not divide d(L)\n");
        !           709:       }
        !           710:       switch(itos(CSF))
        !           711:       {
        !           712:         case 0: case 2:
        !           713:           avma=av1; nf = change_pol(nf,ff); pol = (GEN)nf[1];
        !           714:           if (DEBUGLEVEL) fprintferr("new f = %Z\n",pol);
        !           715:           goto LAB0;
        !           716:       }
        !           717:       avma=av2;
        !           718:     }
        !           719:     else
        !           720:     {
        !           721:       if (DEBUGLEVEL) fprintferr("candidate = %Z\n",CSF);
        !           722:       ESF=embedding_of_potential_subfields(nf,CSF,DATA,rootsA,delta);
        !           723:       if (ESF == gzero) avma=av2;
        !           724:       else
        !           725:       {
        !           726:         if (DEBUGLEVEL) fprintferr("embedding = %Z\n",ESF);
        !           727:        p1=cgetg(3,t_VEC); p2=cgetg(2,t_VEC); p2[1]=(long)p1;
        !           728:         p1[1]=(long)CSF;
        !           729:         p1[2]=(long)ESF; tetpil=avma;
        !           730:         LSB=gerepile(av2,tetpil, concat(LSB,p2));
        !           731:       }
        !           732:     }
        !           733:   }
        !           734:   for (i=1; i<llist; i++) free((void*)listpotbl[i]);
        !           735:   free((void*)(listpotbl-1)); tetpil=avma;
        !           736:   return gerepile(av,tetpil,gcopy(LSB));
        !           737: }
        !           738:
        !           739: GEN
        !           740: subfields(GEN nf,GEN d)
        !           741: {
        !           742:   long av=avma,di,N,v0,lp1,i;
        !           743:   GEN dpol,p1,LSB,p2,pol;
        !           744:
        !           745:   nf=checknf(nf); pol = (GEN)nf[1];
        !           746:   v0=varn(pol); N=lgef(pol)-3; di=itos(d);
        !           747:   if (di==N)
        !           748:   {
        !           749:     LSB=cgetg(2,t_VEC); p1=cgetg(3,t_VEC); LSB[1]=(long)p1;
        !           750:     p1[1]=lcopy(pol); p1[2]=lpolx[v0]; return LSB;
        !           751:   }
        !           752:   if (di==1)
        !           753:   {
        !           754:     LSB=cgetg(2,t_VEC); p1=cgetg(3,t_VEC); LSB[1]=(long)p1;
        !           755:     p1[1]=lpolx[v0]; p1[2]=lcopy(pol); return LSB;
        !           756:   }
        !           757:   if (di<=0 || di>N || N%di) return cgetg(1,t_VEC);
        !           758:
        !           759:   TR=0; dpol=mulii((GEN)nf[3],sqri((GEN)nf[4]));
        !           760:   if (v0) nf=gsubst(nf,v0,polx[0]);
        !           761:   FACTORDL=factor(absi((GEN)nf[3]));
        !           762:   p1=subfields_of_given_degree(nf,dpol,di); lp1=lg(p1)-1;
        !           763:   if (v0)
        !           764:     for (i=1; i<=lp1; i++)
        !           765:       { p2=(GEN)p1[i]; setvarn(p2[1],v0); setvarn(p2[2],v0); }
        !           766:   return gerepileupto(av,p1);
        !           767: }
        !           768:
        !           769: static GEN
        !           770: subfieldsall(GEN nf)
        !           771: {
        !           772:   long av=avma,av1,N,ld,d,i,j,lNLSB,v0,lp1;
        !           773:   GEN pol,dpol,dg,LSB,NLSB,p1,p2;
        !           774:
        !           775:   nf=checknf(nf); pol = (GEN)nf[1];
        !           776:   v0=varn(pol); N=lgef(pol)-3;
        !           777:   if (isprime(stoi(N)))
        !           778:   {
        !           779:     avma=av; LSB=cgetg(3,t_VEC);
        !           780:     LSB[1]=lgetg(3,t_VEC); LSB[2]=lgetg(3,t_VEC);
        !           781:     p1=(GEN)LSB[1]; p1[1]=lcopy(pol); p1[2]=lpolx[v0];
        !           782:     p2=(GEN)LSB[2]; p2[1]=p1[2]; p2[2]=p1[1];
        !           783:     return LSB;
        !           784:   }
        !           785:   FACTORDL=factor(absi((GEN)nf[3])); dg=divisors(stoi(N));
        !           786:   dpol=mulii(sqri((GEN)nf[4]),(GEN)nf[3]);
        !           787:   if (DEBUGLEVEL>0)
        !           788:   {
        !           789:     fprintferr("\n***** Entering subfields\n\n");
        !           790:     fprintferr("pol = "); outerr(pol);
        !           791:     fprintferr("dpol = "); outerr(dpol);
        !           792:     fprintferr("divisors = "); outerr(dg);
        !           793:   }
        !           794:   ld=lg(dg)-1; LSB=cgetg(2,t_VEC); LSB[1]=lgetg(3,t_VEC);
        !           795:   p1=(GEN)LSB[1]; p1[1]=(long)pol; p1[2]=(long)polx[0];
        !           796:   if (v0) nf=gsubst(nf,v0,polx[0]);
        !           797:   for (i=2; i<ld; i++)
        !           798:   {
        !           799:     TR=0; av1=avma; d=itos((GEN)dg[i]);
        !           800:     if (DEBUGLEVEL>0)
        !           801:     {
        !           802:       fprintferr("\n*** Looking for subfields of degree %ld\n\n",N/d);
        !           803:       flusherr();
        !           804:     }
        !           805:     NLSB=subfields_of_given_degree(nf,dpol,N/d);
        !           806:     if (DEBUGLEVEL)
        !           807:     {
        !           808:       fprintferr("\nSubfields of degree %ld:\n",N/d);
        !           809:       lNLSB=lg(NLSB)-1; for (j=1; j<=lNLSB; j++) outerr((GEN)NLSB[j]);
        !           810:     }
        !           811:     if (lg(NLSB)>1) LSB = concatsp(LSB,NLSB); else avma=av1;
        !           812:   }
        !           813:   p1=cgetg(2,t_VEC); p1[1]=lgetg(3,t_VEC);p2=(GEN)p1[1];
        !           814:   p2[1]=(long)polx[0]; p2[2]=(long)pol;
        !           815:   LSB=concatsp(LSB,p1); lp1=lg(LSB)-1;
        !           816:   LSB = gerepileupto(av, gcopy(LSB));
        !           817:   if (v0)
        !           818:     for (i=1; i<=lp1; i++)
        !           819:       { p2=(GEN)LSB[i]; setvarn(p2[1],v0); setvarn(p2[2],v0); }
        !           820:   if (DEBUGLEVEL>0) fprintferr("\n***** Leaving subfields\n\n");
        !           821:   return LSB;
        !           822: }
        !           823:
        !           824: GEN
        !           825: subfields0(GEN nf,GEN d)
        !           826: {
        !           827:   return d? subfields(nf,d): subfieldsall(nf);
        !           828: }
        !           829:
        !           830: /* irreducible (unitary) polynomial of degree n over Fp[v] */
        !           831: GEN
        !           832: ffinit(GEN p,long n,long v)
        !           833: {
        !           834:   long av,av1,tetpil,i,*a,j,l,pp;
        !           835:   GEN pol,fpol;
        !           836:
        !           837:   if (n<=0) err(talker,"non positive degree in ffinit");
        !           838:   if (is_bigint(p)) err(talker,"prime field too big in ffinit");
        !           839:   if (v<0) v = 0;
        !           840:   av=avma; pp=itos(p); pol = cgetg(n+3,t_POL);
        !           841:   pol[1] = evalsigne(1)|evalvarn(v)|evallgef(n+3);
        !           842:   a=new_chunk(n+2);
        !           843:   a[1]=1; for (i=2; i<=n+1; i++) a[i]=0;
        !           844:   pol[n+2]=un; av1=avma;
        !           845:   for(;;)
        !           846:   {
        !           847:     a[n+1]++;
        !           848:     if (a[n+1]>=pp)
        !           849:     {
        !           850:       j=n; while (j>=2 && a[j]==pp-1) j--;
        !           851:       if (j>=2) { a[j]++; for (l=j+1; l<=n+1; l++) a[l]=0; }
        !           852:     }
        !           853:     for (i=2; i<=n+1; i++) pol[i]=lstoi(a[n+3-i]);
        !           854:     fpol=simplefactmod(pol,p);
        !           855:     if (lg(fpol[1])==2 && gcmp1(gmael(fpol,2,1))) break;
        !           856:     avma=av1;
        !           857:   }
        !           858:   tetpil=avma; return gerepile(av,tetpil,Fp_pol(pol,p));
        !           859: }
        !           860:
        !           861: static GEN
        !           862: lift_coeff(GEN x, GEN fq)
        !           863: {
        !           864:   GEN r;
        !           865:   if (typ(x) == t_POLMOD) { r = x; x = (GEN)x[2]; }
        !           866:   else r = cgetg(3,t_POLMOD);
        !           867:   r[1]=(long)fq; r[2]=(long)lift_intern(x); return r;
        !           868: }
        !           869:
        !           870: /* a is a polynomial whose coeffs are in Fq (= (Z/p)[y] / (fqbar), where
        !           871:  * fqbar is the reduction of fq mod p).
        !           872:  * Lift _in place_ the coeffs so that they belong to Z[y] / (fq)
        !           873:  */
        !           874: static GEN
        !           875: special_lift(GEN a,GEN fq)
        !           876: {
        !           877:   long la,i;
        !           878:   GEN c;
        !           879:
        !           880:   if (typ(a)==t_POL)
        !           881:   {
        !           882:     la=lgef(a); c=cgetg(la,t_POL); c[1]=a[1];
        !           883:     for (i=2; i<la; i++) c[i]=(long)lift_coeff((GEN)a[i],fq);
        !           884:     return c;
        !           885:   }
        !           886:   return lift_coeff(a,fq);
        !           887: }
        !           888:
        !           889: /* Hensel lift: fk = vector of factors of pol (unramified) in finite field
        !           890:  * Fp / fkk. Lift it to the precision p^e. This is equivalent to working
        !           891:  * in precision pi^e in the unramified extension of Qp given by fkk.
        !           892:  */
        !           893: GEN
        !           894: hensel_lift(GEN pol,GEN fk,GEN fkk,GEN p,long e)
        !           895: {
        !           896:   long av = avma, i, r = lg(fk)-1;
        !           897:   GEN p1,A,B,C,R,U,V,fklift,fklift2,fk2;
        !           898:   GEN unmodp = gmodulsg(1,p), fq = lift(fkk);
        !           899:
        !           900:   fk2=cgetg(r+1,t_VEC);
        !           901:   fklift=cgetg(r+1,t_VEC);
        !           902:   fklift2=cgetg(r+1,t_VEC);
        !           903:   fk2[r] = fklift2[r] = un;
        !           904:   for (i=r; i>1; i--)
        !           905:   {
        !           906:     fk2[i-1] = lmul((GEN)fk2[i],(GEN)fk[i]);
        !           907:     fklift[i] = (long)special_lift(gcopy((GEN)fk[i]),fq);
        !           908:     fklift2[i-1] = lmul((GEN)fklift2[i],(GEN)fklift[i]);
        !           909:   }
        !           910:   fklift[1] = (long)special_lift(gcopy((GEN)fk[1]),fq);
        !           911:   R=cgetg(r+1,t_VEC); C=pol;
        !           912:   for (i=1; i<r; i++)
        !           913:   { /* treat factors two by two: fk[i] and fk2[i] = product fk[i+1..] */
        !           914:     long av1 = avma,tetpil1, ex = 1;
        !           915:     GEN pp;
        !           916:
        !           917:     (void)gbezout((GEN)fk[i],(GEN)fk2[i],&U,&V);
        !           918:     A = (GEN)fklift[i];  U = special_lift(U,fq);
        !           919:     B = (GEN)fklift2[i]; V = special_lift(V,fq);
        !           920:     for (pp=p;; pp=sqri(pp))
        !           921:     { /* Algorithm 3.5.[5,6] H. Cohen page 137 (1995) */
        !           922:       GEN f,t,A0,B0,U0,V0;
        !           923:
        !           924:       unmodp[1] = (long)pp;
        !           925:       p1 = gneg_i(gmul(A,B));
        !           926:       p1=gdiv(gadd(C,p1),pp);
        !           927:       f=gmul(p1,unmodp);
        !           928:       t=poldivres(gmul(V,f),A, &A0);
        !           929:       A0=special_lift(A0,fq);
        !           930:       B0=special_lift(gadd(gmul(U,f),gmul(B,t)),fq);
        !           931:       A0 = gmul(A0,pp);
        !           932:       B0 = gmul(B0,pp); tetpil1 = avma;
        !           933:       A = gadd(A, A0);
        !           934:       B = gadd(B, B0); ex <<= 1;
        !           935:       if (ex>=e)
        !           936:       {
        !           937:         GEN *gptr[2]; gptr[0]=&A; gptr[1]=&B;
        !           938:         gerepilemanysp(av1,tetpil1,gptr,2);
        !           939:         C = B; R[i] = (long)A; break;
        !           940:       }
        !           941:       p1 = gneg_i(gadd(gmul(U,A),gmul(V,B)));
        !           942:       p1=gdiv(gadd(gun,p1),pp);
        !           943:       f=gmul(p1,unmodp);
        !           944:       t=poldivres(gmul(V,f),A, &V0);
        !           945:       U0=special_lift(gadd(gmul(U,f),gmul(B,t)),fq);
        !           946:       V0=special_lift(V0,fq);
        !           947:       U = gadd(U, gmul(U0,pp));
        !           948:       V = gadd(V, gmul(V0,pp));
        !           949:     }
        !           950:   }
        !           951:   if (r==1) C = gcopy(C);
        !           952:   R[r] = (long)C; return gerepileupto(av,R);
        !           953: }
        !           954:
        !           955: /* etant donne nf et p et la factorisation de nf[1] mod p, et le degre m des
        !           956:  * sous corps cherches, cree un vecteur ligne a 13 composantes:
        !           957:  * 1 : le polynome nf[1],
        !           958:  * 2 : le premier p,
        !           959:  * 3 : la factorisation ff,
        !           960:  * 4 : la longeur des cycles associes (n_1,...,n_r),
        !           961:  * 5 : les cycles associes,
        !           962:  * 6 : le corps F_(p^q),
        !           963:  * 7 : les racines de f dans F_(p^q) par facteur de ff,
        !           964:  * 8 : la borne M pour les sous-corps,
        !           965:  * 9 : l'exposant e telle que la precision des lifts soit p^e>2.M,
        !           966:  * 10: le lift de Hensel a la precision p^e de la factorisation en facteurs
        !           967:  *     lineaires de nf[1] dans F_(p^q),
        !           968:  * 11: la borne de Hadamard pour les coefficients de h(x) tel que g o h = 0
        !           969:  *     mod nf[1].
        !           970:  * ces donnees sont valides pour nf, p et m (d) donnes...
        !           971:  */
        !           972: static GEN
        !           973: compute_data(GEN nf, GEN ff, GEN p, long m, long nn)
        !           974: {
        !           975:   long i,j,l,r,*n,e,N,pp,d,r1;
        !           976:   GEN DATA,p1,p2,cys,fhk,tabroots,MM,fk,dpol,maxroot,maxMM,pol;
        !           977:
        !           978:   if (DEBUGLEVEL>1) { fprintferr("Entering compute_data()\n\n"); flusherr(); }
        !           979:   pol = (GEN)nf[1]; N = lgef(pol)-3;
        !           980:   DATA=cgetg(14,t_VEC);
        !           981:   DATA[1]=(long)pol;
        !           982:   DATA[2]=(long)p; r=lg(ff)-1;
        !           983:   DATA[3]=(long)ff;
        !           984:   n = cgetg(r+1, t_VECSMALL);
        !           985:   DATA[4]= (long)n;
        !           986:   for (j=1; j<=r; j++) n[j]=lgef(ff[j])-3;
        !           987:   cys=cgetg(r+1,t_VEC); l=0;
        !           988:   for (i=1; i<=r; i++)
        !           989:   {
        !           990:     p1 = cgetg(n[i]+1, t_VECSMALL);
        !           991:     cys[i] = (long)p1; for (j=1; j<=n[i]; j++) p1[j]=++l;
        !           992:   }
        !           993:   DATA[5]=(long)cys;
        !           994:   DATA[6]=(long)ffinit(p,nn,MAXVARN);
        !           995:   tabroots=cgetg(r+1,t_VEC);
        !           996:   for (j=1; j<=r; j++)
        !           997:   {
        !           998:     p1=(GEN)factmod9((GEN)ff[j],p,(GEN)DATA[6])[1];
        !           999:     p2=cgetg(n[j]+1,t_VEC); tabroots[j]=(long)p2;
        !          1000:     p2[1]=lneg(gmael(p1,1,2));
        !          1001:     for (i=2; i<=n[j]; i++) p2[i]=(long)powgi((GEN)p2[i-1],p);
        !          1002:   }
        !          1003:   DATA[7]=(long)tabroots;
        !          1004:   r1=itos(gmael(nf,2,1));
        !          1005:   MM = bound_for_coeff(m, (GEN)nf[6], r1, &maxroot);
        !          1006:   MM = gmul2n(MM,1);
        !          1007:   DATA[8]=(long)MM;
        !          1008:   pp=itos(p); maxMM = vecmax(MM);
        !          1009:   for (e=1,p1=p; cmpii(p1, maxMM) < 0; ) { p1 = mulis(p1,pp); e++; }
        !          1010:   DATA[9]=lpuigs(p,e); fk=cgetg(N+1,t_VEC);
        !          1011:   for (l=1,j=1; j<=r; j++)
        !          1012:     for (i=1; i<=n[j]; i++)
        !          1013:       fk[l++] = lsub(polx[0],gmael(tabroots,j,i));
        !          1014:   fhk = hensel_lift(pol,fk,(GEN)DATA[6],p,e);
        !          1015:   tabroots=cgetg(r+1,t_VEC);
        !          1016:   for (l=1,j=1; j<=r; j++)
        !          1017:   {
        !          1018:     p1 = cgetg(n[j]+1,t_VEC); tabroots[j]=(long)p1;
        !          1019:     for (i=1; i<=n[j]; i++,l++) p1[i] = lneg(gmael(fhk,l,2));
        !          1020:   }
        !          1021:   DATA[10]=(long)tabroots;
        !          1022:
        !          1023:   d=N/m; p1=gmul(stoi(N), gsqrt(gpuigs(stoi(N-1),N-1),DEFAULTPREC));
        !          1024:   p2 = gpuigs(maxroot, d + N*(N-1)/2);
        !          1025:   dpol=mulii(sqri((GEN)nf[4]),(GEN)nf[3]);
        !          1026:   p1 = gdiv(gmul(p1,p2), gsqrt(absi(dpol),DEFAULTPREC));
        !          1027:   p1 = grndtoi(p1, &e);
        !          1028:   if (e>=0) p1 = addii(p1, shifti(gun, e));
        !          1029:   p1 = shifti(p1, 1);
        !          1030:   DATA[11]=(long)p1;
        !          1031:
        !          1032:   if (DEBUGLEVEL>1)
        !          1033:   {
        !          1034:     fprintferr("DATA =\n");
        !          1035:     fprintferr("f = "); outerr((GEN)DATA[1]);
        !          1036:     fprintferr("p = "); outerr((GEN)DATA[2]);
        !          1037:     fprintferr("ff = "); outerr((GEN)DATA[3]);
        !          1038:     fprintferr("lcy = "); outerr((GEN)DATA[4]);
        !          1039:     fprintferr("cys = "); outerr((GEN)DATA[5]);
        !          1040:     fprintferr("bigfq = "); outerr((GEN)DATA[6]);
        !          1041:     fprintferr("roots = "); outerr((GEN)DATA[7]);
        !          1042:     fprintferr("2 * M = "); outerr((GEN)DATA[8]);
        !          1043:     fprintferr("p^e = "); outerr((GEN)DATA[9]);
        !          1044:     fprintferr("lifted roots = "); outerr((GEN)DATA[10]);
        !          1045:     fprintferr("2 * Hadamard bound = "); outerr((GEN)DATA[11]);
        !          1046:   }
        !          1047:   return DATA;
        !          1048: }
        !          1049:
        !          1050: /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
        !          1051: /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
        !          1052: /*                                                                 */
        !          1053: /*               AUTOMORPHISMS OF AN ABELIAN NUMBER FIELD          */
        !          1054: /*                                                                 */
        !          1055: /*               V. Acciaro and J. Klueners (1996)                 */
        !          1056: /*                                                                 */
        !          1057: /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
        !          1058: /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
        !          1059:
        !          1060: /* calcul du frobenius en p pour le corps abelien defini par le polynome pol,
        !          1061:  * par relevement de hensel du frobenius frobp de l'extension des corps
        !          1062:  * residuels (frobp est un polynome mod pol a coefficients dans F_p)
        !          1063:  */
        !          1064: static GEN
        !          1065: frobenius(GEN pol,GEN frobp,GEN p,GEN B,GEN d)
        !          1066: {
        !          1067:   long av=avma,v0,deg,i,depas;
        !          1068:   GEN b0,b1,pold,polp,poldp,w0,w1,g0,g1,unmodp,polpp,v,pp,unmodpp,poldpp,bl0,bl1;
        !          1069:
        !          1070:   v0=varn(pol); unmodp=gmodulsg(1,p); pold=deriv(pol,v0);
        !          1071:   b0=frobp; polp=gmul(unmodp,pol);
        !          1072:   poldp=gsubst(deriv(polp,v0),v0,frobp);
        !          1073:   w0=ginv(poldp);
        !          1074:   bl0=lift(b0); deg=lgef(bl0)-3;
        !          1075:   v=cgetg(deg+2,t_VEC);
        !          1076:   for (i=1; i<=deg+1; i++)
        !          1077:     v[i]=ldiv(centerlift(gmul(d,compo(bl0,deg+2-i))),d);
        !          1078:   g0=gtopoly(v,v0);
        !          1079:   if (DEBUGLEVEL>2)
        !          1080:   {
        !          1081:     fprintferr("val. initiales:\n");
        !          1082:     fprintferr("b0 = "); outerr(b0);
        !          1083:     fprintferr("w0 = "); outerr(w0);
        !          1084:     fprintferr("g0 = "); outerr(g0);
        !          1085:   }
        !          1086:   depas=1; pp=gsqr(p);
        !          1087:   for(;;)
        !          1088:   {
        !          1089:     if (gcmp(pp,B)>0) depas=0;
        !          1090:     unmodpp=gmodulsg(1,pp);
        !          1091:     polpp=gmul(unmodpp,pol); poldpp=gmul(unmodpp,pold);
        !          1092:     b0=gmodulcp(gmul(unmodpp,lift_intern(lift_intern(b0))),polpp);
        !          1093:     w0=gmodulcp(gmul(unmodpp,lift_intern(lift_intern(w0))),polpp);
        !          1094:     b1=gsub(b0,gmul(w0,gsubst(polpp,v0,b0)));
        !          1095:     w1=gmul(w0,gsub(gdeux,gmul(w0,gsubst(poldpp,v0,b1))));
        !          1096:     bl1=lift(b1); deg=lgef(bl1)-3;
        !          1097:     v=cgetg(deg+2,t_VEC);
        !          1098:     for (i=1; i<=deg+1; i++)
        !          1099:       v[i]=ldiv(centerlift(gmul(d,compo(bl1,deg+2-i))),d);
        !          1100:     g1=gtopoly(v,v0);
        !          1101:     if (DEBUGLEVEL>2)
        !          1102:     {
        !          1103:       fprintferr("pp = "); outerr(pp);
        !          1104:       fprintferr("b1 = "); outerr(b1);
        !          1105:       fprintferr("w1 = "); outerr(w1);
        !          1106:       fprintferr("g1 = "); outerr(g1);
        !          1107:     }
        !          1108:     if (gegal(g0,g1)) return gerepileupto(av,g1);
        !          1109:     pp=gsqr(pp); b0=b1; w0=w1; g0=g1;
        !          1110:     if (!depas) err(talker,"the number field is not an Abelian number field");
        !          1111:   }
        !          1112: }
        !          1113:
        !          1114: static GEN
        !          1115: compute_denom(GEN dpol)
        !          1116: {
        !          1117:   long av=avma,lf,i,a;
        !          1118:   GEN d,f1,f2, f = decomp(dpol);
        !          1119:
        !          1120:   f1=(GEN)f[1];
        !          1121:   f2=(GEN)f[2]; lf=lg(f1);
        !          1122:   for (d=gun,i=1; i<lf; i++)
        !          1123:   {
        !          1124:     a = itos((GEN)f2[i]) >> 1;
        !          1125:     d = mulii(d, gpuigs((GEN)f1[i],a));
        !          1126:   }
        !          1127:   return gerepileupto(av,d);
        !          1128: }
        !          1129:
        !          1130: static GEN
        !          1131: compute_bound_for_lift(GEN pol,GEN dpol,GEN d)
        !          1132: {
        !          1133:   long av=avma,n,i;
        !          1134:   GEN p1,p2,p3;
        !          1135:
        !          1136:   n=lgef(pol)-3;
        !          1137:   p1=gdiv(gmul(stoi(n),gpui(stoi(n-1),gdivgs(stoi(n-1),2),DEFAULTPREC)),
        !          1138:           gsqrt(dpol,DEFAULTPREC));
        !          1139:   p2=gzero;
        !          1140:   for (i=2; i<=n+2; i++) p2=gadd(p2,gsqr((GEN)pol[i]));
        !          1141:   p2=gpuigs(gsqrt(p2,DEFAULTPREC),n-1);
        !          1142:   p1=gmul(p1,p2); p2=gzero;
        !          1143:   for (i=2; i<=n+2; i++)
        !          1144:   {
        !          1145:     p3 = gabs((GEN)pol[i],DEFAULTPREC);
        !          1146:     if (gcmp(p3,p2)>0) p2 = p3;
        !          1147:   }
        !          1148:   p2=gmul(d,gadd(gun,p2));
        !          1149:   return gerepileupto(av, gmul2n(gsqr(gmul(p1,p2)),1));
        !          1150:
        !          1151: /* Borne heuristique de P. S. Wang, Math. Comp. 30, 1976, p. 332
        !          1152:   p2=gzero; for (i=2; i<=n+2; i++) p2=gadd(p2,gsqr((GEN)pol[i]));
        !          1153:   p1=gzero;
        !          1154:   for (i=2; i<=n+2; i++){ if (gcmp(gabs((GEN)pol[i],4),p1)>0) p1=gabs((GEN)pol[i],4); }
        !          1155:   if (gcmp(p2,p1)>0) p1=p2;
        !          1156:   p2=gmul(gdiv(mpfactr(n,4),gsqr(mpfactr(n/2,4))),d);
        !          1157:   B=gmul(p1,p2);
        !          1158:   tetpil=avma; return gerepile(av,tetpil,gcopy(B));
        !          1159: */
        !          1160: }
        !          1161:
        !          1162: static long
        !          1163: isinlist(GEN T,long longT,GEN x)
        !          1164: {
        !          1165:   long i;
        !          1166:   for (i=1; i<=longT; i++)
        !          1167:     if (gegal(x,(GEN)T[i])) return i;
        !          1168:   return 0;
        !          1169: }
        !          1170:
        !          1171: /* renvoie 0 si frobp n'est pas dans la liste T; sinon le no de frobp dans T */
        !          1172: static long
        !          1173: isinlistmodp(GEN T,long longT,GEN frobp,GEN p)
        !          1174: {
        !          1175:   long av=avma,i;
        !          1176:   GEN p1,p2,unmodp;
        !          1177:
        !          1178:   p1=lift_intern(lift_intern(frobp)); unmodp=gmodulsg(1,p);
        !          1179:   for (i=1; i<=longT; i++)
        !          1180:   {
        !          1181:     p2=lift_intern(gmul(unmodp,(GEN)T[i]));
        !          1182:     if (gegal(p2,p1)) { avma=av; return i; }
        !          1183:   }
        !          1184:   avma=av; return 0;
        !          1185: }
        !          1186:
        !          1187: /* renvoie le plus petit f tel que frobp^f est dans la liste T */
        !          1188: static long
        !          1189: minimalexponent(GEN T,long longT,GEN frobp,GEN p,long N)
        !          1190: {
        !          1191:   long av=avma,i;
        !          1192:   GEN p1 = frobp;
        !          1193:   for (i=1; i<=N; i++)
        !          1194:   {
        !          1195:     if (isinlistmodp(T,longT,p1,p)) {avma=av; return i;}
        !          1196:     p1 = gpui(p1,p,DEFAULTPREC);
        !          1197:   }
        !          1198:   err(talker,"missing frobenius (field not abelian ?)");
        !          1199:   return 0; /* not reached */
        !          1200: }
        !          1201:
        !          1202:
        !          1203: /* Computation of all the automorphisms of the abelian number field
        !          1204:    defined by the monic irreducible polynomial pol with integral coefficients */
        !          1205: GEN
        !          1206: conjugates(GEN pol)
        !          1207: {
        !          1208:   long av,tetpil,N,i,j,pp,bound_primes,nbprimes,longT,v0,flL,f,longTnew,*tab,nop,flnf;
        !          1209:   GEN T,S,p1,p2,p,dpol,modunp,polp,xbar,frobp,frob,d,B,nf;
        !          1210:   byteptr di;
        !          1211:
        !          1212:   if (DEBUGLEVEL>2){ fprintferr("** Entree dans conjugates\n"); flusherr(); }
        !          1213:   flnf=0; if (typ(pol)!=t_POL){ nf=checknf(pol); flnf=1; pol=(GEN)nf[1]; }
        !          1214:   av=avma; N=lgef(pol)-3; v0=varn(pol);
        !          1215:   if (N==1) { S=cgetg(2,t_VEC); S[1]=(long)polx[v0]; return S; }
        !          1216:   if (N==2)
        !          1217:   {
        !          1218:     S=cgetg(3,t_VEC); S[1]=(long)polx[v0];
        !          1219:     S[2]=lsub(gneg(polx[v0]),(GEN)pol[3]);
        !          1220:     tetpil=avma; return gerepile(av,tetpil,gcopy(S));
        !          1221:   }
        !          1222:   dpol=absi(discsr(pol));
        !          1223:   if (DEBUGLEVEL>2)
        !          1224:     { fprintferr("discriminant du polynome: "); outerr(dpol); }
        !          1225:   d = flnf? (GEN)nf[4]: compute_denom(dpol);
        !          1226:   if (DEBUGLEVEL>2)
        !          1227:     { fprintferr("facteur carre du discriminant: "); outerr(d); }
        !          1228:   B=compute_bound_for_lift(pol,dpol,d);
        !          1229:   if (DEBUGLEVEL>2) { fprintferr("borne pour les lifts: "); outerr(B); }
        !          1230:   /* sous GRH il faut en fait 3.47*log(dpol) */
        !          1231:   p1=gfloor(glog(dpol,DEFAULTPREC));
        !          1232:   bound_primes=itos(p1);
        !          1233:   if (DEBUGLEVEL>2)
        !          1234:   { fprintferr("borne pour les premiers: %ld\n",bound_primes); flusherr(); }
        !          1235:   nbprimes=itos(gfloor(gmul(dbltor(1.25506),
        !          1236:                             gdiv(p1,glog(p1,DEFAULTPREC)))));
        !          1237:   if (DEBUGLEVEL>2)
        !          1238:   { fprintferr("borne pour le nombre de premiers: %ld\n",nbprimes); flusherr(); }
        !          1239:   S=cgetg(nbprimes+1,t_VEC);
        !          1240:   di=diffptr; pp=*di; i=0;
        !          1241:   while (pp<=bound_primes)
        !          1242:   {
        !          1243:     if (smodis(dpol,pp)) { i++; S[i]=lstoi(pp); }
        !          1244:     pp = pp + (*(++di));
        !          1245:   }
        !          1246:   for (j=i+1; j<=nbprimes; j++) S[j]=zero;
        !          1247:   nbprimes=i; tab=new_chunk(nbprimes+1);
        !          1248:   for (i=1; i<=nbprimes; i++) tab[i]=0;
        !          1249:   if (DEBUGLEVEL>2)
        !          1250:   {
        !          1251:     fprintferr("nombre de premiers: %ld\n",nbprimes);
        !          1252:     fprintferr("table des premiers: "); outerr(S);
        !          1253:   }
        !          1254:   T=cgetg(N+1,t_VEC); T[1]=(long)polx[v0];
        !          1255:   for (i=2; i<=N; i++) T[i]=zero; longT=1;
        !          1256:   if (DEBUGLEVEL>2) { fprintferr("table initiale: "); outerr(T); }
        !          1257:   for(;;)
        !          1258:   {
        !          1259:     do
        !          1260:     {
        !          1261:       do
        !          1262:       {
        !          1263:         nop = 1+itos(shifti(mulss(mymyrand(),nbprimes),-(BITS_IN_RANDOM-1)));
        !          1264:       }
        !          1265:       while (tab[nop]);
        !          1266:       tab[nop]=1; p=(GEN)S[nop];
        !          1267:       if (DEBUGLEVEL>2) { fprintferr("\nnombre premier: "); outerr(p); }
        !          1268:       modunp=gmodulsg(1,p);
        !          1269:       polp=gmul(modunp,pol);
        !          1270:       xbar=gmodulcp(gmul(polx[v0],modunp),polp);
        !          1271:       frobp=gpui(xbar,p,4);
        !          1272:       if (DEBUGLEVEL>2) { fprintferr("frobenius mod p: "); outerr(frobp); }
        !          1273:       flL=isinlistmodp(T,longT,frobp,p);
        !          1274:       if (DEBUGLEVEL>2){ fprintferr("flL: %ld\n",flL); flusherr(); }
        !          1275:     }
        !          1276:     while (flL);
        !          1277:     f=minimalexponent(T,longT,frobp,p,N);
        !          1278:     if (DEBUGLEVEL>2){ fprintferr("exposant minimum: %ld\n",f); flusherr(); }
        !          1279:     frob=frobenius(pol,frobp,p,B,d);
        !          1280:     if (DEBUGLEVEL>2) { fprintferr("frobenius: "); outerr(frob); }
        !          1281: /* Ce passage n'est vrai que si le corps est abelien !! */
        !          1282:     longTnew=longT;
        !          1283:     p2=gmodulcp(frob,pol);
        !          1284:     for (i=1; i<=longTnew; i++)
        !          1285:       for (j=1; j<f; j++)
        !          1286:       {
        !          1287:        p1=lift(gsubst((GEN)T[i],v0,gpuigs(p2,j)));
        !          1288:        if (DEBUGLEVEL>2)
        !          1289:        {
        !          1290:          fprintferr("test de la puissance (%ld,%ld): ",i,j); outerr(p1);
        !          1291:        }
        !          1292:        if (!isinlist(T,longTnew,p1))
        !          1293:        {
        !          1294:          longT++; T[longT]=(long)p1;
        !          1295:          if (longT==N)
        !          1296:           {
        !          1297:             if (DEBUGLEVEL>2)
        !          1298:               { fprintferr("** Sortie de conjugates\n"); flusherr(); }
        !          1299:             tetpil=avma; return gerepile(av,tetpil,gcopy(T));
        !          1300:           }
        !          1301:        }
        !          1302:       }
        !          1303:     if (DEBUGLEVEL>2) { fprintferr("nouvelle table: "); outerr(T); }
        !          1304:   }
        !          1305: }
        !          1306:

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