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

Annotation of OpenXM_contrib/pari-2.2/src/basemath/galconj.c, Revision 1.1

1.1     ! noro        1: /* $Id: galconj.c,v 1.67 2001/10/01 16:41:42 bill Exp $
        !             2:
        !             3: Copyright (C) 2000  The PARI group.
        !             4:
        !             5: This file is part of the PARI/GP package.
        !             6:
        !             7: PARI/GP is free software; you can redistribute it and/or modify it under the
        !             8: terms of the GNU General Public License as published by the Free Software
        !             9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
        !            10: ANY WARRANTY WHATSOEVER.
        !            11:
        !            12: Check the License for details. You should have received a copy of it, along
        !            13: with the package; see the file 'COPYING'. If not, write to the Free Software
        !            14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
        !            15:
        !            16: /*************************************************************************/
        !            17: /**                                                                    **/
        !            18: /**                           GALOIS CONJUGATES                                **/
        !            19: /**                                                                    **/
        !            20: /*************************************************************************/
        !            21: #include "pari.h"
        !            22: #define mylogint(x,y) logint((x),(y),NULL)
        !            23: GEN
        !            24: galoisconj(GEN nf)
        !            25: {
        !            26:   GEN     x, y, z;
        !            27:   long    i, lz, v, av = avma;
        !            28:   nf = checknf(nf);
        !            29:   x = (GEN) nf[1];
        !            30:   v = varn(x);
        !            31:   if (v == 0)
        !            32:     nf = gsubst(nf, 0, polx[MAXVARN]);
        !            33:   else
        !            34:   {
        !            35:     x = dummycopy(x);
        !            36:     setvarn(x, 0);
        !            37:   }
        !            38:   z = nfroots(nf, x);
        !            39:   lz = lg(z);
        !            40:   y = cgetg(lz, t_COL);
        !            41:   for (i = 1; i < lz; i++)
        !            42:   {
        !            43:     GEN     p1 = lift((GEN) z[i]);
        !            44:     setvarn(p1, v);
        !            45:     y[i] = (long) p1;
        !            46:   }
        !            47:   return gerepileupto(av, y);
        !            48: }
        !            49:
        !            50: /* nbmax: maximum number of possible conjugates */
        !            51: GEN
        !            52: galoisconj2pol(GEN x, long nbmax, long prec)
        !            53: {
        !            54:   long    av = avma, i, n, v, nbauto;
        !            55:   GEN     y, w, polr, p1, p2;
        !            56:   n = degpol(x);
        !            57:   if (n <= 0)
        !            58:     return cgetg(1, t_VEC);
        !            59:   if (gisirreducible(x) == gzero)
        !            60:     err(redpoler, "galoisconj2pol");
        !            61:   polr = roots(x, prec);
        !            62:   p1 = (GEN) polr[1];
        !            63:   nbauto = 1;
        !            64:   prec = (long) (bit_accuracy(prec) * L2SL10 * 0.75);
        !            65:   w = cgetg(n + 2, t_VEC);
        !            66:   w[1] = un;
        !            67:   for (i = 2; i <= n; i++)
        !            68:     w[i] = lmul(p1, (GEN) w[i - 1]);
        !            69:   v = varn(x);
        !            70:   y = cgetg(nbmax + 1, t_COL);
        !            71:   y[1] = (long) polx[v];
        !            72:   for (i = 2; i <= n && nbauto < nbmax; i++)
        !            73:   {
        !            74:     w[n + 1] = polr[i];
        !            75:     p1 = lindep2(w, prec);
        !            76:     if (signe(p1[n + 1]))
        !            77:     {
        !            78:       setlg(p1, n + 1);
        !            79:       p2 = gdiv(gtopolyrev(p1, v), negi((GEN) p1[n + 1]));
        !            80:       if (gdivise(poleval(x, p2), x))
        !            81:       {
        !            82:        y[++nbauto] = (long) p2;
        !            83:        if (DEBUGLEVEL > 1)
        !            84:          fprintferr("conjugate %ld: %Z\n", i, y[nbauto]);
        !            85:       }
        !            86:     }
        !            87:   }
        !            88:   setlg(y, 1 + nbauto);
        !            89:   return gerepileupto(av, gen_sort(y, 0, cmp_pol));
        !            90: }
        !            91:
        !            92: GEN
        !            93: galoisconj2(GEN nf, long nbmax, long prec)
        !            94: {
        !            95:   long    av = avma, i, j, n, r1, ru, nbauto;
        !            96:   GEN     x, y, w, polr, p1, p2;
        !            97:   if (typ(nf) == t_POL)
        !            98:     return galoisconj2pol(nf, nbmax, prec);
        !            99:   nf = checknf(nf);
        !           100:   x = (GEN) nf[1];
        !           101:   n = degpol(x);
        !           102:   if (n <= 0)
        !           103:     return cgetg(1, t_VEC);
        !           104:   r1 = nf_get_r1(nf);
        !           105:   p1 = (GEN) nf[6];
        !           106:   prec = precision((GEN) p1[1]);
        !           107:   /* accuracy in decimal digits */
        !           108:   prec = (long) (bit_accuracy(prec) * L2SL10 * 0.75);
        !           109:   ru = (n + r1) >> 1;
        !           110:   nbauto = 1;
        !           111:   polr = cgetg(n + 1, t_VEC);
        !           112:   for (i = 1; i <= r1; i++)
        !           113:     polr[i] = p1[i];
        !           114:   for (j = i; i <= ru; i++)
        !           115:   {
        !           116:     polr[j++] = p1[i];
        !           117:     polr[j++] = lconj((GEN) p1[i]);
        !           118:   }
        !           119:   p2 = gmael(nf, 5, 1);
        !           120:   w = cgetg(n + 2, t_VEC);
        !           121:   for (i = 1; i <= n; i++)
        !           122:     w[i] = coeff(p2, 1, i);
        !           123:   y = cgetg(nbmax + 1, t_COL);
        !           124:   y[1] = (long) polx[varn(x)];
        !           125:   for (i = 2; i <= n && nbauto < nbmax; i++)
        !           126:   {
        !           127:     w[n + 1] = polr[i];
        !           128:     p1 = lindep2(w, prec);
        !           129:     if (signe(p1[n + 1]))
        !           130:     {
        !           131:       setlg(p1, n + 1);
        !           132:       settyp(p1, t_COL);
        !           133:       p2 = gdiv(gmul((GEN) nf[7], p1), negi((GEN) p1[n + 1]));
        !           134:       if (gdivise(poleval(x, p2), x))
        !           135:       {
        !           136:        y[++nbauto] = (long) p2;
        !           137:        if (DEBUGLEVEL > 1)
        !           138:          fprintferr("conjugate %ld: %Z\n", i, y[nbauto]);
        !           139:       }
        !           140:     }
        !           141:   }
        !           142:   setlg(y, 1 + nbauto);
        !           143:   return gerepileupto(av, gen_sort(y, 0, cmp_pol));
        !           144: }
        !           145: /*************************************************************************/
        !           146: /**                                                                    **/
        !           147: /**                           GALOISCONJ4                              **/
        !           148: /**                                                                    **/
        !           149: /**                                                                     **/
        !           150: /*************************************************************************/
        !           151: /*DEBUGLEVEL:
        !           152:   1: timing
        !           153:   2: outline
        !           154:   4: complete outline
        !           155:   6: detail
        !           156:   7: memory
        !           157:   9: complete detail
        !           158: */
        !           159: /* retourne la permutation identite */
        !           160: GEN
        !           161: permidentity(long l)
        !           162: {
        !           163:   GEN     perm;
        !           164:   int     i;
        !           165:   perm = cgetg(l + 1, t_VECSMALL);
        !           166:   for (i = 1; i <= l; i++)
        !           167:     perm[i] = i;
        !           168:   return perm;
        !           169: }
        !           170:
        !           171: GEN vandermondeinverseprepold(GEN T, GEN L)
        !           172: {
        !           173:   int     i, n = lg(L);
        !           174:   GEN     V, dT;
        !           175:   dT = derivpol(T);
        !           176:   V = cgetg(n, t_VEC);
        !           177:   for (i = 1; i < n; i++)
        !           178:     V[i] = (long) poleval(dT, (GEN) L[i]);
        !           179:   return V;
        !           180: }
        !           181:
        !           182: GEN vandermondeinverseprep(GEN T, GEN L)
        !           183: {
        !           184:   int     i, j, n = lg(L);
        !           185:   GEN     V;
        !           186:   V = cgetg(n, t_VEC);
        !           187:   for (i = 1; i < n; i++)
        !           188:   {
        !           189:     ulong ltop=avma;
        !           190:     GEN W=cgetg(n,t_VEC);
        !           191:     for (j = 1; j < n; j++)
        !           192:       if (i==j)
        !           193:        W[j]=un;
        !           194:       else
        !           195:        W[j]=lsub((GEN)L[i],(GEN)L[j]);
        !           196:     V[i]=lpileupto(ltop,divide_conquer_prod(W,&gmul));
        !           197:   }
        !           198:   return V;
        !           199: }
        !           200:
        !           201: /* Calcule l'inverse de la matrice de van der Monde de T multiplie par den */
        !           202: GEN
        !           203: vandermondeinverse(GEN L, GEN T, GEN den, GEN prep)
        !           204: {
        !           205:   ulong   ltop = avma, lbot;
        !           206:   int     i, j, n = lg(L);
        !           207:   long    x = varn(T);
        !           208:   GEN     M, P;
        !           209:   if (!prep)
        !           210:     prep=vandermondeinverseprep(T,L);
        !           211:   M = cgetg(n, t_MAT);
        !           212:   for (i = 1; i < n; i++)
        !           213:   {
        !           214:     M[i] = lgetg(n, t_COL);
        !           215:     P = gdiv(gdeuc(T, gsub(polx[x], (GEN) L[i])), (GEN) prep[i]);
        !           216:     for (j = 1; j < n; j++)
        !           217:       ((GEN *) M)[i][j] = P[1 + j];
        !           218:   }
        !           219:   lbot = avma;
        !           220:   M = gmul(den, M);
        !           221:   return gerepile(ltop, lbot, M);
        !           222: }
        !           223:
        !           224: /* Calcule les bornes sur les coefficients a chercher */
        !           225: struct galois_borne
        !           226: {
        !           227:   GEN     l;
        !           228:   long    valsol;
        !           229:   long    valabs;
        !           230:   GEN     bornesol;
        !           231:   GEN     ladicsol;
        !           232:   GEN     ladicabs;
        !           233:   GEN     lbornesol;
        !           234: };
        !           235:
        !           236:
        !           237: GEN indexpartial(GEN,GEN);
        !           238: GEN ZX_disc_all(GEN,long);
        !           239:
        !           240: GEN
        !           241: galoisborne(GEN T, GEN dn, struct galois_borne *gb, long ppp)
        !           242: {
        !           243:   ulong   ltop = avma, av2;
        !           244:   GEN     borne, borneroots, borneabs;
        !           245:   int     i, j;
        !           246:   int     n;
        !           247:   GEN     L, M, z, prep, den;
        !           248:   long    prec;
        !           249:   n = degpol(T);
        !           250:   prec = 1;
        !           251:   for (i = 2; i < lgef(T); i++)
        !           252:     if (lg(T[i]) > prec)
        !           253:       prec = lg(T[i]);
        !           254:   /*prec++;*/
        !           255:   if (DEBUGLEVEL>=4) gentimer(3);
        !           256:   L = roots(T, prec);
        !           257:   if (DEBUGLEVEL>=4) genmsgtimer(3,"roots");
        !           258:   for (i = 1; i <= n; i++)
        !           259:   {
        !           260:     z = (GEN) L[i];
        !           261:     if (signe(z[2]))
        !           262:       break;
        !           263:     L[i] = z[1];
        !           264:   }
        !           265:   if (DEBUGLEVEL>=4) gentimer(3);
        !           266:   prep=vandermondeinverseprep(T, L);
        !           267:   if (!dn)
        !           268:   {
        !           269:     GEN res = divide_conquer_prod(gabs(prep,prec), mpmul);
        !           270:     GEN dis;
        !           271:     disable_dbg(0);
        !           272:     dis = ZX_disc_all(T, 1+mylogint(res,gdeux));
        !           273:     disable_dbg(-1);
        !           274:     den = gclone(indexpartial(T,dis));
        !           275:   }
        !           276:   else
        !           277:     den=dn;
        !           278:   M = vandermondeinverse(L, gmul(T, realun(prec)), den, prep);
        !           279:   if (DEBUGLEVEL>=4) genmsgtimer(3,"vandermondeinverse");
        !           280:   borne = realzero(prec);
        !           281:   for (i = 1; i <= n; i++)
        !           282:   {
        !           283:     z = gzero;
        !           284:     for (j = 1; j <= n; j++)
        !           285:       z = gadd(z, gabs(gcoeff(M,i,j), prec));
        !           286:     if (gcmp(z, borne) > 0)
        !           287:       borne = z;
        !           288:   }
        !           289:   borneroots = realzero(prec);
        !           290:   for (i = 1; i <= n; i++)
        !           291:   {
        !           292:     z = gabs((GEN) L[i], prec);
        !           293:     if (gcmp(z, borneroots) > 0)
        !           294:       borneroots = z;
        !           295:   }
        !           296:   borneabs = addsr(1, gmulsg(n, gpowgs(borneroots, n/ppp)));
        !           297:   /*if (ppp == 1)
        !           298:     borneabs = addsr(1, gmulsg(n, gpowgs(borneabs, 2)));*/
        !           299:   borneroots = addsr(1, gmul(borne, borneroots));
        !           300:   av2 = avma;
        !           301:   /*We use d-1 test, so we must overlift to 2^BITS_IN_LONG*/
        !           302:   gb->valsol = mylogint(gmul2n(borneroots,2+BITS_IN_LONG), gb->l);
        !           303:   gb->valabs = mylogint(gmul2n(borneabs,2), gb->l);
        !           304:   gb->valabs = max(gb->valsol,gb->valabs);
        !           305:   if (DEBUGLEVEL >= 4)
        !           306:     fprintferr("GaloisConj:val1=%ld val2=%ld\n", gb->valsol, gb->valabs);
        !           307:   avma = av2;
        !           308:   gb->bornesol = gerepileupto(ltop, ceil_safe(borneroots));
        !           309:   if (DEBUGLEVEL >= 9)
        !           310:     fprintferr("GaloisConj: Bound %Z\n",borneroots);
        !           311:   gb->ladicsol = gpowgs(gb->l, gb->valsol);
        !           312:   gb->ladicabs = gpowgs(gb->l, gb->valabs);
        !           313:   gb->lbornesol = subii(gb->ladicsol,gb->bornesol);
        !           314:   if (!dn)
        !           315:   {
        !           316:     dn=forcecopy(den);
        !           317:     gunclone(den);
        !           318:   }
        !           319:   return dn;
        !           320: }
        !           321:
        !           322: struct galois_lift
        !           323: {
        !           324:   GEN     T;
        !           325:   GEN     den;
        !           326:   GEN     p;
        !           327:   GEN     L;
        !           328:   GEN     Lden;
        !           329:   long    e;
        !           330:   GEN     Q;
        !           331:   GEN     TQ;
        !           332:   struct galois_borne *gb;
        !           333: };
        !           334: /* Initialise la structure galois_lift */
        !           335: GEN makeLden(GEN L,GEN den, struct galois_borne *gb)
        !           336: {
        !           337:   ulong ltop=avma;
        !           338:   long i,l=lg(L);
        !           339:   GEN Lden;
        !           340:   Lden=cgetg(l,t_VEC);
        !           341:   for (i=1;i<l;i++)
        !           342:     Lden[i]=lmulii((GEN)L[i],den);
        !           343:   for (i=1;i<l;i++)
        !           344:     Lden[i]=lmodii((GEN)Lden[i],gb->ladicsol);
        !           345:   return gerepileupto(ltop,Lden);
        !           346: }
        !           347: void
        !           348: initlift(GEN T, GEN den, GEN p, GEN L, GEN Lden, struct galois_borne *gb, struct galois_lift *gl)
        !           349: {
        !           350:   ulong   ltop, lbot;
        !           351:   gl->gb=gb;
        !           352:   gl->T = T;
        !           353:   gl->den = den;
        !           354:   gl->p = p;
        !           355:   gl->L = L;
        !           356:   gl->Lden = Lden;
        !           357:   ltop = avma;
        !           358:   gl->e = mylogint(gmul2n(gb->bornesol, 2+BITS_IN_LONG),p);
        !           359:   gl->e = max(2,gl->e);
        !           360:   lbot = avma;
        !           361:   gl->Q = gpowgs(p, gl->e);
        !           362:   gl->Q = gerepile(ltop, lbot, gl->Q);
        !           363:   gl->TQ = FpX_red(T,gl->Q);
        !           364: }
        !           365: #if 0
        !           366: /*
        !           367:  * T est le polynome \sum t_i*X^i S est un Polmod T
        !           368:  * Retourne un vecteur Spow
        !           369:  * verifiant la condition: i>=1 et t_i!=0 ==> Spow[i]=S^(i-1)*t_i
        !           370:  * Essaie d'etre efficace sur les polynomes lacunaires
        !           371:  */
        !           372: GEN
        !           373: compoTS(GEN T, GEN S, GEN Q, GEN mod)
        !           374: {
        !           375:   GEN     Spow;
        !           376:   int     i;
        !           377:   Spow = cgetg(lgef(T) - 2, t_VEC);
        !           378:   for (i = 3; i < lg(Spow); i++)
        !           379:     Spow[i] = 0;
        !           380:   Spow[1] = (long) polun[varn(S)];
        !           381:   Spow[2] = (long) S;
        !           382:   for (i = 2; i < lg(Spow) - 1; i++)
        !           383:   {
        !           384:     if (signe((GEN) T[i + 3]))
        !           385:       for (;;)
        !           386:       {
        !           387:        int     k, l;
        !           388:        for (k = 1; k <= (i >> 1); k++)
        !           389:          if (Spow[k + 1] && Spow[i - k + 1])
        !           390:            break;
        !           391:        if ((k << 1) < i)
        !           392:        {
        !           393:          Spow[i + 1] = (long) FpXQ_mul((GEN) Spow[k + 1], (GEN) Spow[i - k + 1],Q,mod);
        !           394:          break;
        !           395:        }
        !           396:        else if ((k << 1) == i)
        !           397:        {
        !           398:          Spow[i + 1] = (long) FpXQ_sqr((GEN) Spow[k + 1],Q,mod);
        !           399:          break;
        !           400:        }
        !           401:        for (k = i - 1; k > 0; k--)
        !           402:          if (Spow[k + 1])
        !           403:            break;
        !           404:        if ((k << 1) < i)
        !           405:        {
        !           406:          Spow[(k << 1) + 1] = (long) FpXQ_sqr((GEN) Spow[k + 1],Q,mod);
        !           407:          continue;
        !           408:        }
        !           409:        for (l = i - k; l > 0; l--)
        !           410:          if (Spow[l + 1])
        !           411:            break;
        !           412:        if (Spow[i - l - k + 1])
        !           413:          Spow[i - k + 1] = (long) FpXQ_mul((GEN) Spow[i - l - k + 1], (GEN) Spow[l + 1],Q,mod);
        !           414:        else
        !           415:          Spow[l + k + 1] = (long) FpXQ_mul((GEN) Spow[k + 1], (GEN) Spow[l + 1],Q,mod);
        !           416:       }
        !           417:   }
        !           418:   for (i = 1; i < lg(Spow); i++)
        !           419:     if (signe((GEN) T[i + 2]))
        !           420:       Spow[i] = (long) FpX_Fp_mul((GEN) Spow[i], (GEN) T[i + 2],mod);
        !           421:   return Spow;
        !           422: }
        !           423:
        !           424: /*
        !           425:  * Calcule T(S) a l'aide du vecteur Spow
        !           426:  */
        !           427: static GEN
        !           428: calcTS(GEN Spow, GEN P, GEN S, GEN Q, GEN mod)
        !           429: {
        !           430:   GEN     res = gzero;
        !           431:   int     i;
        !           432:   for (i = 1; i < lg(Spow); i++)
        !           433:     if (signe((GEN) P[i + 2]))
        !           434:       res = FpX_add(res, (GEN) Spow[i],NULL);
        !           435:   res = FpXQ_mul(res,S,Q,mod);
        !           436:   res=FpX_Fp_add(res,(GEN)P[2],mod);
        !           437:   return res;
        !           438: }
        !           439:
        !           440: /*
        !           441:  * Calcule T'(S) a l'aide du vecteur Spow
        !           442:  */
        !           443: static GEN
        !           444: calcderivTS(GEN Spow, GEN P, GEN mod)
        !           445: {
        !           446:   GEN     res = gzero;
        !           447:   int     i;
        !           448:   for (i = 1; i < lg(Spow); i++)
        !           449:     if (signe((GEN) P[i + 2]))
        !           450:       res = FpX_add(res, FpX_Fp_mul((GEN) Spow[i], stoi(i),mod),NULL);
        !           451:   return FpX_red(res,mod);
        !           452: }
        !           453: #endif
        !           454: /*
        !           455:  * Verifie que f est une solution presque surement et calcule sa permutation
        !           456:  */
        !           457: static int
        !           458: poltopermtest(GEN f, struct galois_lift *gl, GEN pf)
        !           459: {
        !           460:   ulong   ltop;
        !           461:   GEN     fx, fp;
        !           462:   long     i, j,ll;
        !           463:   for (i = 2; i< lgef(f); i++)
        !           464:     if (cmpii((GEN)f[i],gl->gb->bornesol)>0
        !           465:        && cmpii((GEN)f[i],gl->gb->lbornesol)<0)
        !           466:     {
        !           467:       if (DEBUGLEVEL>=4)
        !           468:        fprintferr("GaloisConj: Solution too large, discard it.\n");
        !           469:       return 0;
        !           470:     }
        !           471:   ll=lg(gl->L);
        !           472:   fp = cgetg(ll, t_VECSMALL);
        !           473:   ltop = avma;
        !           474:   for (i = 1; i < ll; i++)
        !           475:     fp[i] = 1;
        !           476:   for (i = 1; i < ll; i++)
        !           477:   {
        !           478:     fx = FpX_eval(f, (GEN) gl->L[i],gl->gb->ladicsol);
        !           479:     for (j = 1; j < ll; j++)
        !           480:     {
        !           481:       if (fp[j] && egalii(fx, (GEN) gl->Lden[j]))
        !           482:       {
        !           483:        pf[i] = j;
        !           484:        fp[j] = 0;
        !           485:        break;
        !           486:       }
        !           487:     }
        !           488:     if (j == ll)
        !           489:       return 0;
        !           490:     avma = ltop;
        !           491:   }
        !           492:   return 1;
        !           493: }
        !           494:
        !           495: GEN polratlift(GEN P, GEN mod, GEN amax, GEN bmax, GEN denom);
        !           496:
        !           497: /*
        !           498:  * Soit P un polynome de \ZZ[X] , p un nombre premier , S\in\FF_p[X]/(Q) tel
        !           499:  * que P(S)=0 [p,Q] Relever S en S_0 tel que P(S_0)=0 [p^e,Q]
        !           500:  * Unclean stack.
        !           501:  */
        !           502: static long monoratlift(GEN S, GEN q, GEN qm1old,struct galois_lift *gl, GEN frob)
        !           503: {
        !           504:   ulong ltop=avma;
        !           505:   GEN tlift = polratlift(S,q,qm1old,qm1old,gl->den);
        !           506:   if (tlift)
        !           507:   {
        !           508:     if(DEBUGLEVEL>=4)
        !           509:       fprintferr("MonomorphismLift: trying early solution %Z\n",tlift);
        !           510:     /*Rationals coefficients*/
        !           511:     tlift=lift(gmul(tlift,gmodulcp(gl->den,gl->gb->ladicsol)));
        !           512:     if (poltopermtest(tlift, gl, frob))
        !           513:     {
        !           514:       if(DEBUGLEVEL>=4)
        !           515:        fprintferr("MonomorphismLift: true early solution.\n");
        !           516:       avma=ltop;
        !           517:       return 1;
        !           518:     }
        !           519:     if(DEBUGLEVEL>=4)
        !           520:       fprintferr("MonomorphismLift: false early solution.\n");
        !           521:   }
        !           522:   avma=ltop;
        !           523:   return 0;
        !           524: }
        !           525:   GEN
        !           526: monomorphismratlift(GEN P, GEN S, struct galois_lift *gl, GEN frob)
        !           527: {
        !           528:   ulong   ltop, lbot;
        !           529:   long rt;
        !           530:   GEN     Q=gl->T, p=gl->p;
        !           531:   long    e=gl->e, level=1;
        !           532:   long    x;
        !           533:   GEN     q, qold, qm1, qm1old;
        !           534:   GEN     W, Pr, Qr, Sr, Wr = gzero, Prold, Qrold, Spow;
        !           535:   long    i,nb,mask;
        !           536:   GEN    *gptr[2];
        !           537:   if (DEBUGLEVEL == 1)
        !           538:     timer2();
        !           539:   x = varn(P);
        !           540:   rt = brent_kung_optpow(degpol(Q),1);
        !           541:   q = p; qm1 = gun; /*during the run, we have p*qm1=q*/
        !           542:   nb=hensel_lift_accel(e, &mask);
        !           543:   Pr = FpX_red(P,q);
        !           544:   Qr = (P==Q)?Pr:FpX_red(Q, q);/*A little speed up for automorphismlift*/
        !           545:   W=FpX_FpXQ_compo(deriv(Pr, x),S,Qr,q);
        !           546:   W=FpXQ_inv(W,Qr,q);
        !           547:   qold = p; qm1old=gun;
        !           548:   Prold = Pr;
        !           549:   Qrold = Qr;
        !           550:   gptr[0] = &S;
        !           551:   gptr[1] = &Wr;
        !           552:   for (i=0; i<nb;i++)
        !           553:   {
        !           554:     if (DEBUGLEVEL>=2)
        !           555:     {
        !           556:       level=(level<<1)-((mask>>i)&1);
        !           557:       timer2();
        !           558:     }
        !           559:     qm1 = (mask&(1<<i))?sqri(qm1):mulii(qm1, q);
        !           560:     q   =  mulii(qm1, p);
        !           561:     Pr = FpX_red(P, q);
        !           562:     Qr = (P==Q)?Pr:FpX_red(Q, q);/*A little speed up for automorphismlift*/
        !           563:     ltop = avma;
        !           564:     Sr = S;
        !           565:     /*Spow = compoTS(Pr, Sr, Qr, q);*/
        !           566:     Spow = FpXQ_powers(Sr, rt, Qr, q);
        !           567:
        !           568:     if (i)
        !           569:     {
        !           570:       /*W = FpXQ_mul(Wr, calcderivTS(Spow, Prold,qold), Qrold, qold);*/
        !           571:       W = FpXQ_mul(Wr, FpX_FpXQV_compo(deriv(Pr,-1),FpXV_red(Spow,qold),Qrold,qold), Qrold, qold);
        !           572:       W = FpX_neg(W, qold);
        !           573:       W = FpX_Fp_add(W, gdeux, qold);
        !           574:       W = FpXQ_mul(Wr, W, Qrold, qold);
        !           575:     }
        !           576:     Wr = W;
        !           577:     /*S = FpXQ_mul(Wr, calcTS(Spow, Pr, Sr, Qr, q),Qr,q);*/
        !           578:     S = FpXQ_mul(Wr, FpX_FpXQV_compo(Pr, Spow, Qr, q),Qr,q);
        !           579:     S = FpX_sub(Sr, S, NULL);
        !           580:     lbot = avma;
        !           581:     Wr = gcopy(Wr);
        !           582:     S = FpX_red(S, q);
        !           583:     gerepilemanysp(ltop, lbot, gptr, 2);
        !           584:     if (i && i<nb-1 && frob && monoratlift(S,q,qm1old,gl,frob))
        !           585:       return NULL;
        !           586:     qold = q; qm1old=qm1; Prold = Pr; Qrold = Qr;
        !           587:     if (DEBUGLEVEL >= 2)
        !           588:       msgtimer("MonomorphismLift: lift to prec %d",level);
        !           589:   }
        !           590:   if (DEBUGLEVEL == 1)
        !           591:     msgtimer("monomorphismlift()");
        !           592:   return S;
        !           593: }
        !           594: /*
        !           595:  * Soit T un polynome de \ZZ[X] , p un nombre premier , S\in\FF_p[X]/(T) tel
        !           596:  * que T(S)=0 [p,T] Relever S en S_0 tel que T(S_0)=0 [T,p^e]
        !           597:  * Unclean stack.
        !           598:  */
        !           599: GEN
        !           600: automorphismlift(GEN S, struct galois_lift *gl, GEN frob)
        !           601: {
        !           602:   return  monomorphismratlift(gl->T, S, gl, frob);
        !           603: }
        !           604: GEN
        !           605: monomorphismlift(GEN P, GEN S, GEN Q, GEN p, long e)
        !           606: {
        !           607:   struct galois_lift gl;
        !           608:   gl.T=Q;
        !           609:   gl.p=p;
        !           610:   gl.e=e;
        !           611:   return monomorphismratlift(P,S,&gl,NULL);
        !           612: }
        !           613:
        !           614: struct galois_testlift
        !           615: {
        !           616:   long    n;
        !           617:   long    f;
        !           618:   long    g;
        !           619:   GEN     bezoutcoeff;
        !           620:   GEN     pauto;
        !           621:   GEN     C;
        !           622:   GEN     Cd;
        !           623: };
        !           624: GEN bezout_lift_fact(GEN T, GEN Tmod, GEN p, long e);
        !           625: static GEN
        !           626: galoisdolift(struct galois_lift *gl, GEN frob)
        !           627: {
        !           628:   ulong ltop=avma;
        !           629:   long v = varn(gl->T);
        !           630:   GEN Tp = FpX_red(gl->T, gl->p);
        !           631:   GEN S = FpXQ_pow(polx[v],gl->p, Tp,gl->p);
        !           632:   GEN plift = automorphismlift(S, gl, frob);
        !           633:   return gerepileupto(ltop,plift);
        !           634: }
        !           635:
        !           636: static void
        !           637: inittestlift( GEN plift, GEN Tmod, struct galois_lift *gl,
        !           638:     struct galois_testlift *gt)
        !           639: {
        !           640:   long v = varn(gl->T);
        !           641:   gt->n = lg(gl->L) - 1;
        !           642:   gt->g = lg(Tmod) - 1;
        !           643:   gt->f = gt->n / gt->g;
        !           644:   gt->bezoutcoeff = bezout_lift_fact(gl->T, Tmod, gl->p, gl->e);
        !           645:   gt->pauto = cgetg(gt->f + 1, t_VEC);
        !           646:   gt->pauto[1] = (long) polx[v];
        !           647:   gt->pauto[2] = (long) gcopy(plift);
        !           648:   if (gt->f > 2)
        !           649:   {
        !           650:     ulong ltop=avma;
        !           651:     int i;
        !           652:     long nautpow=brent_kung_optpow(gt->n-1,gt->f-2);
        !           653:     GEN autpow;
        !           654:     if (DEBUGLEVEL >= 1) timer2();
        !           655:     autpow = FpXQ_powers(plift,nautpow,gl->TQ,gl->Q);
        !           656:     for (i = 3; i <= gt->f; i++)
        !           657:       gt->pauto[i] = (long) FpX_FpXQV_compo((GEN)gt->pauto[i-1],autpow,gl->TQ,gl->Q);
        !           658:     /*Somewhat paranoid with memory, but this function use a lot of stack.*/
        !           659:     gt->pauto=gerepileupto(ltop, gt->pauto);
        !           660:     if (DEBUGLEVEL >= 1) msgtimer("frobenius power");
        !           661:   }
        !           662: }
        !           663:
        !           664: long intheadlong(GEN x, GEN mod)
        !           665: {
        !           666:   ulong ltop=avma;
        !           667:   GEN r;
        !           668:   int s;
        !           669:   long res;
        !           670:   r=divii(shifti(x,BITS_IN_LONG),mod);
        !           671:   s=signe(r);
        !           672:   res=s?s>0?r[2]:-r[2]:0;
        !           673:   avma=ltop;
        !           674:   return res;
        !           675: }
        !           676:
        !           677: GEN matheadlong(GEN W, GEN mod)
        !           678: {
        !           679:   long i,j;
        !           680:   GEN V=cgetg(lg(W),t_VEC);
        !           681:   for(i=1;i<lg(W);i++)
        !           682:   {
        !           683:     V[i]=lgetg(lg(W[i]),t_VECSMALL);
        !           684:     for(j=1;j<lg(W[i]);j++)
        !           685:       mael(V,i,j)=intheadlong(gmael(W,i,j),mod);
        !           686:   }
        !           687:   return V;
        !           688: }
        !           689:
        !           690: long polheadlong(GEN P, long n, GEN mod)
        !           691: {
        !           692:   return (lgef(P)>n+2)?intheadlong((GEN)P[n+2],mod):0;
        !           693: }
        !           694: /*
        !           695:  *
        !           696:  */
        !           697: long
        !           698: frobeniusliftall(GEN sg, long el, GEN *psi, struct galois_lift *gl,
        !           699:                 struct galois_testlift *gt, GEN frob)
        !           700: {
        !           701:   ulong   ltop = avma, av, ltop2;
        !           702:   long    d, z, m, c, n, ord;
        !           703:   int     i, j, k;
        !           704:   GEN     pf, u, v;
        !           705:   GEN     C, Cd;
        !           706:   long           Z, Zv;
        !           707:   long    stop=0;
        !           708:   GEN NN,NQ,NR;
        !           709:   long N1,N2,R1,Ni;
        !           710:   m = gt->g;
        !           711:   ord = gt->f;
        !           712:   n = lg(gl->L) - 1;
        !           713:   c = lg(sg) - 1;
        !           714:   d = m / c;
        !           715:   pf = cgetg(m, t_VECSMALL);
        !           716:   *psi = pf;
        !           717:   ltop2 = avma;
        !           718:   NN = gdiv(mpfact(m), gmul(stoi(c), gpowgs(mpfact(d), c)));
        !           719:   if (DEBUGLEVEL >= 4)
        !           720:     fprintferr("GaloisConj:I will try %Z permutations\n", NN);
        !           721:   N1=10000000;
        !           722:   NQ=dvmdis(NN,N1,&NR);
        !           723:   if (cmpis(NQ,1000000000)>0)
        !           724:   {
        !           725:     err(warner,"Combinatorics too hard : would need %Z tests!\n
        !           726:        I will skip it,but it may induce galoisinit to loop",NN);
        !           727:     avma = ltop;
        !           728:     *psi = NULL;
        !           729:     return 0;
        !           730:   }
        !           731:   N2=itos(NQ); R1=itos(NR); if(!N2) N1=R1;
        !           732:   if (DEBUGLEVEL>=4)
        !           733:   {
        !           734:     stop=N1/20;
        !           735:     timer2();
        !           736:   }
        !           737:   avma = ltop2;
        !           738:   C=gt->C;
        !           739:   Cd=gt->Cd;
        !           740:   v = FpX_Fp_mul(FpXQ_mul((GEN)gt->pauto[1+el%ord], (GEN)
        !           741:        gt->bezoutcoeff[m],gl->TQ,gl->Q),gl->den,gl->Q);
        !           742:   Zv=polheadlong(v,0,gl->Q);
        !           743:   for (i = 1; i < m; i++)
        !           744:     pf[i] = 1 + i / d;
        !           745:   av = avma;
        !           746:   for (Ni = 0, i = 0; ;i++)
        !           747:   {
        !           748:     Z=Zv;
        !           749:     for (j = 1; j < m; j++)
        !           750:     {
        !           751:       long h;
        !           752:       h=(el*sg[pf[j]])%ord + 1;
        !           753:       if (!mael(C,h,j))
        !           754:       {
        !           755:        ulong av3=avma;
        !           756:        GEN r;
        !           757:        r=FpX_Fp_mul(FpXQ_mul((GEN) gt->pauto[h],
        !           758:              (GEN) gt->bezoutcoeff[j],gl->TQ,gl->Q),gl->den,gl->Q);
        !           759:        mael(C,h,j)  = lclone(r);
        !           760:        mael(Cd,h,j) = polheadlong(r,0,gl->Q);
        !           761:        avma=av3;
        !           762:       }
        !           763:       Z += mael(Cd,h,j);
        !           764:     }
        !           765:     if (labs(Z)<=n )
        !           766:     {
        !           767:       Z=polheadlong(v,1,gl->Q);
        !           768:       for (j = 1; j < m; j++)
        !           769:        Z += polheadlong(gmael(C,(el*sg[pf[j]])%ord + 1,j),1,gl->Q);
        !           770:       if (labs(Z)<=n )
        !           771:       {
        !           772:        u = v;
        !           773:        for (j = 1; j < m; j++)
        !           774:          u = FpX_add(u, gmael(C,1+(el*sg[pf[j]])%ord,j),NULL);
        !           775:        u = FpX_center(FpX_red(u, gl->Q), gl->Q);
        !           776:        if (poltopermtest(u, gl, frob))
        !           777:        {
        !           778:          if (DEBUGLEVEL >= 4 )
        !           779:            msgtimer("");
        !           780:          avma = ltop2;
        !           781:          return 1;
        !           782:        }
        !           783:       }
        !           784:     }
        !           785:     if (DEBUGLEVEL >= 4 && i==stop)
        !           786:     {
        !           787:       stop+=N1/20;
        !           788:       msgtimer("GaloisConj:Testing %Z", addis(mulss(Ni,N1),i));
        !           789:     }
        !           790:     avma = av;
        !           791:     if (i == N1 - 1)
        !           792:     {
        !           793:       if (Ni==N2-1)
        !           794:        N1=R1;
        !           795:       if (Ni==N2)
        !           796:        break;
        !           797:       Ni++;
        !           798:       i=0;
        !           799:       if (DEBUGLEVEL>=4)
        !           800:       {
        !           801:        stop=N1/20;
        !           802:        timer2();
        !           803:       }
        !           804:     }
        !           805:     for (j = 2; j < m && pf[j - 1] >= pf[j]; j++);
        !           806:     for (k = 1; k < j - k && pf[k] != pf[j - k]; k++)
        !           807:     {
        !           808:       z = pf[k];
        !           809:       pf[k] = pf[j - k];
        !           810:       pf[j - k] = z;
        !           811:     }
        !           812:     for (k = j - 1; pf[k] >= pf[j]; k--);
        !           813:     z = pf[j];
        !           814:     pf[j] = pf[k];
        !           815:     pf[k] = z;
        !           816:   }
        !           817:   avma = ltop;
        !           818:   *psi = NULL;
        !           819:   return 0;
        !           820: }
        !           821: /*
        !           822:  * applique une permutation t a un vecteur s sans duplication
        !           823:  * Propre si s est un VECSMALL
        !           824:  */
        !           825: static GEN
        !           826: permapply(GEN s, GEN t)
        !           827: {
        !           828:   GEN     u;
        !           829:   int     i;
        !           830:   if (lg(s) < lg(t))
        !           831:     err(talker, "First permutation shorter than second in permapply");
        !           832:   u = cgetg(lg(s), typ(s));
        !           833:   for (i = 1; i < lg(s); i++)
        !           834:     u[i] = s[t[i]];
        !           835:   return u;
        !           836: }
        !           837:
        !           838: /*
        !           839:  * alloue une ardoise pour n entiers de longueurs pour les test de
        !           840:  * permutation
        !           841:  */
        !           842: GEN
        !           843: alloue_ardoise(long n, long s)
        !           844: {
        !           845:   GEN     ar;
        !           846:   long    i;
        !           847:   ar = cgetg(n + 1, t_VEC);
        !           848:   for (i = 1; i <= n; i++)
        !           849:     ar[i] = lgetg(s, t_INT);
        !           850:   return ar;
        !           851: }
        !           852:
        !           853: /*
        !           854:  * structure contenant toutes les données pour le tests des permutations:
        !           855:  *
        !           856:  * ordre :ordre des tests pour verifie_test ordre[lg(ordre)]: numero du test
        !           857:  * principal borne : borne sur les coefficients a trouver ladic: modulo
        !           858:  * l-adique des racines lborne:ladic-borne TM:vecteur des ligne de M
        !           859:  * PV:vecteur des clones des matrices de test (Vmatrix) (ou NULL si non
        !           860:  * calcule) L,M comme d'habitude (voir plus bas)
        !           861:  */
        !           862: struct galois_test
        !           863: {
        !           864:   GEN     ordre;
        !           865:   GEN     borne, lborne, ladic;
        !           866:   GEN     PV, TM;
        !           867:   GEN     L, M;
        !           868: };
        !           869: /* Calcule la matrice de tests correspondant a la n-ieme ligne de V */
        !           870: static GEN
        !           871: Vmatrix(long n, struct galois_test *td)
        !           872: {
        !           873:   ulong   ltop = avma, lbot;
        !           874:   GEN     V;
        !           875:   long    i;
        !           876:   V = cgetg(lg(td->L), t_VEC);
        !           877:   for (i = 1; i < lg(V); i++)
        !           878:     V[i] = mael(td->M,i,n);
        !           879:   V = gmul(td->L, V);
        !           880:   lbot = avma;
        !           881:   V = gmod(V, td->ladic);
        !           882:   return gerepile(ltop, lbot, V);
        !           883: }
        !           884:
        !           885: /*
        !           886:  * Initialise la structure galois_test
        !           887:  */
        !           888: static void
        !           889: inittest(GEN L, GEN M, GEN borne, GEN ladic, struct galois_test *td)
        !           890: {
        !           891:   ulong   ltop;
        !           892:   long    i;
        !           893:   int     n = lg(L) - 1;
        !           894:   if (DEBUGLEVEL >= 8)
        !           895:     fprintferr("GaloisConj:Entree Init Test\n");
        !           896:   td->ordre = cgetg(n + 1, t_VECSMALL);
        !           897:   for (i = 1; i <= n - 2; i++)
        !           898:     td->ordre[i] = i + 2;
        !           899:   for (; i <= n; i++)
        !           900:     td->ordre[i] = i - n + 2;
        !           901:   td->borne = borne;ltop = avma;
        !           902:   td->lborne = subii(ladic, borne);
        !           903:   td->ladic = ladic;
        !           904:   td->L = L;
        !           905:   td->M = M;
        !           906:   td->PV = cgetg(n + 1, t_VECSMALL);   /* peut-etre t_VEC est correct ici */
        !           907:   for (i = 1; i <= n; i++)
        !           908:     td->PV[i] = 0;
        !           909:   ltop = avma;
        !           910:   td->PV[td->ordre[n]] = (long) gclone(Vmatrix(td->ordre[n], td));
        !           911:   avma = ltop;
        !           912:   td->TM = gtrans(M);
        !           913:   settyp(td->TM, t_VEC);
        !           914:   for (i = 1; i < lg(td->TM); i++)
        !           915:     settyp(td->TM[i], t_VEC);
        !           916:   if (DEBUGLEVEL >= 8)
        !           917:     fprintferr("GaloisConj:Sortie Init Test\n");
        !           918: }
        !           919:
        !           920: /*
        !           921:  * liberer les clones de la structure galois_test
        !           922:  *
        !           923:  * Reservé a l'accreditation ultra-violet:Liberez les clones! Paranoia(tm)
        !           924:  */
        !           925: static void
        !           926: freetest(struct galois_test *td)
        !           927: {
        !           928:   int     i;
        !           929:   for (i = 1; i < lg(td->PV); i++)
        !           930:     if (td->PV[i])
        !           931:     {
        !           932:       gunclone((GEN) td->PV[i]);
        !           933:       td->PV[i] = 0;
        !           934:     }
        !           935: }
        !           936:
        !           937: /*
        !           938:  * Test si le nombre padique P est proche d'un entier inferieur a td->borne
        !           939:  * en valeur absolue.
        !           940:  */
        !           941: static long
        !           942: padicisint(GEN P, struct galois_test *td)
        !           943: {
        !           944:   long    r;
        !           945:   ulong   ltop = avma;
        !           946:   GEN     U;
        !           947:   /*if (typ(P) != t_INT)    err(typeer, "padicisint");*/
        !           948:   U = modii(P, td->ladic);
        !           949:   r = gcmp(U, (GEN) td->borne) <= 0 || gcmp(U, (GEN) td->lborne) >= 0;
        !           950:   avma = ltop;
        !           951:   return r;
        !           952: }
        !           953:
        !           954: /*
        !           955:  * Verifie si pf est une vrai solution et non pas un "hop"
        !           956:  */
        !           957: static long
        !           958: verifietest(GEN pf, struct galois_test *td)
        !           959: {
        !           960:   ulong   av = avma;
        !           961:   GEN     P, V;
        !           962:   int     i, j;
        !           963:   int     n = lg(td->L) - 1;
        !           964:   if (DEBUGLEVEL >= 8)
        !           965:     fprintferr("GaloisConj:Entree Verifie Test\n");
        !           966:   P = permapply(td->L, pf);
        !           967:   for (i = 1; i < n; i++)
        !           968:   {
        !           969:     long    ord;
        !           970:     GEN     PW;
        !           971:     ord = td->ordre[i];
        !           972:     PW = (GEN) td->PV[ord];
        !           973:     if (PW)
        !           974:     {
        !           975:       V = ((GEN **) PW)[1][pf[1]];
        !           976:       for (j = 2; j <= n; j++)
        !           977:        V = addii(V, ((GEN **) PW)[j][pf[j]]);
        !           978:     }
        !           979:     else
        !           980:       V = centermod(gmul((GEN) td->TM[ord], P),td->ladic);
        !           981:     if (!padicisint(V, td))
        !           982:       break;
        !           983:   }
        !           984:   if (i == n)
        !           985:   {
        !           986:     if (DEBUGLEVEL >= 8)
        !           987:       fprintferr("GaloisConj:Sortie Verifie Test:1\n");
        !           988:     avma = av;
        !           989:     return 1;
        !           990:   }
        !           991:   if (!td->PV[td->ordre[i]])
        !           992:   {
        !           993:     td->PV[td->ordre[i]] = (long) gclone(Vmatrix(td->ordre[i], td));
        !           994:     if (DEBUGLEVEL >= 4)
        !           995:       fprintferr("M");
        !           996:   }
        !           997:   if (DEBUGLEVEL >= 4)
        !           998:     fprintferr("%d.", i);
        !           999:   if (i > 1)
        !          1000:   {
        !          1001:     long    z;
        !          1002:     z = td->ordre[i];
        !          1003:     for (j = i; j > 1; j--)
        !          1004:       td->ordre[j] = td->ordre[j - 1];
        !          1005:     td->ordre[1] = z;
        !          1006:     if (DEBUGLEVEL >= 8)
        !          1007:       fprintferr("%Z", td->ordre);
        !          1008:   }
        !          1009:   if (DEBUGLEVEL >= 8)
        !          1010:     fprintferr("GaloisConj:Sortie Verifie Test:0\n");
        !          1011:   avma = av;
        !          1012:   return 0;
        !          1013: }
        !          1014: /*Compute a*b/c when a*b will overflow*/
        !          1015: static long muldiv(long a,long b,long c)
        !          1016: {
        !          1017:   return (long)((double)a*(double)b/c);
        !          1018: }
        !          1019:
        !          1020: /*
        !          1021:  * F est la decomposition en cycle de sigma, B est la decomposition en cycle
        !          1022:  * de cl(tau) Teste toutes les permutations pf pouvant correspondre a tau tel
        !          1023:  * que : tau*sigma*tau^-1=sigma^s et tau^d=sigma^t  ou d est l'ordre de
        !          1024:  * cl(tau) --------- x: vecteur des choix y: vecteur des mises a jour G:
        !          1025:  * vecteur d'acces a F linéaire
        !          1026:  */
        !          1027: GEN
        !          1028: testpermutation(GEN F, GEN B, long s, long t, long cut,
        !          1029:                struct galois_test *td)
        !          1030: {
        !          1031:   ulong   av, avm = avma;
        !          1032:   int     a, b, c, d, n;
        !          1033:   GEN     pf, x, ar, y, *G;
        !          1034:   int     p1, p2, p3, p4, p5, p6;
        !          1035:   long           l1, l2, N1, N2, R1;
        !          1036:   long    i, j, cx, hop = 0, start = 0;
        !          1037:   GEN     W, NN, NQ, NR;
        !          1038:   long    V;
        !          1039:   if (DEBUGLEVEL >= 1)
        !          1040:     timer2();
        !          1041:   a = lg(F) - 1;
        !          1042:   b = lg(F[1]) - 1;
        !          1043:   c = lg(B) - 1;
        !          1044:   d = lg(B[1]) - 1;
        !          1045:   n = a * b;
        !          1046:   s = (b + s) % b;
        !          1047:   pf = cgetg(n + 1, t_VECSMALL);
        !          1048:   av = avma;
        !          1049:   ar = cgetg(a + 1, t_VECSMALL);
        !          1050:   x = cgetg(a + 1, t_VECSMALL);
        !          1051:   y = cgetg(a + 1, t_VECSMALL);
        !          1052:   G = (GEN *) cgetg(a + 1, t_VECSMALL);        /* Don't worry */
        !          1053:   W = matheadlong((GEN) td->PV[td->ordre[n]],td->ladic);
        !          1054:   for (cx = 1, i = 1, j = 1; cx <= a; cx++, i++)
        !          1055:   {
        !          1056:     x[cx] = (i != d) ? 0 : t;
        !          1057:     y[cx] = 1;
        !          1058:     G[cx] = (GEN) F[((long **) B)[j][i]];      /* Be happy */
        !          1059:     if (i == d)
        !          1060:     {
        !          1061:       i = 0;
        !          1062:       j++;
        !          1063:     }
        !          1064:   }                            /* Be happy now! */
        !          1065:   NN = divis(gpowgs(stoi(b), c * (d - 1)),cut);
        !          1066:   if (DEBUGLEVEL >= 4)
        !          1067:     fprintferr("GaloisConj:I will try %Z permutations\n", NN);
        !          1068:   N1=100000;
        !          1069:   NQ=dvmdis(NN,N1,&NR);
        !          1070:   if (cmpis(NQ,1000000000)>0)
        !          1071:   {
        !          1072:     avma=avm;
        !          1073:     err(warner,"Combinatorics too hard : would need %Z tests!\n I'll skip it but you will get a partial result...",NN);
        !          1074:     return permidentity(n);
        !          1075:   }
        !          1076:   N2=itos(NQ); R1=itos(NR);
        !          1077:   for (l2 = 0; l2 <= N2; l2++)
        !          1078:   {
        !          1079:     long nbiter = (l2<N2) ? N1: R1;
        !          1080:     if (DEBUGLEVEL >= 2 && N2)
        !          1081:       fprintferr("%d%% ", muldiv(l2,100,N2));
        !          1082:     for (l1 = 0; l1 < nbiter; l1++)
        !          1083:     {
        !          1084:       if (start)
        !          1085:       {
        !          1086:        for (i = 1, j = d; i < a;)
        !          1087:        {
        !          1088:          y[i] = 1;
        !          1089:          if ((++(x[i])) != b)
        !          1090:            break;
        !          1091:          x[i++] = 0;
        !          1092:          if (i == j)
        !          1093:          {
        !          1094:            y[i++] = 1;
        !          1095:            j += d;
        !          1096:          }
        !          1097:        }
        !          1098:        y[i + 1] = 1;
        !          1099:       }
        !          1100:       else start=1;
        !          1101:       for (p1 = 1, p5 = d; p1 <= a; p1++, p5++)
        !          1102:        if (y[p1])
        !          1103:        {
        !          1104:          if (p5 == d)
        !          1105:          {
        !          1106:            p5 = 0;
        !          1107:            p4 = 0;
        !          1108:          }
        !          1109:          else
        !          1110:            p4 = x[p1 - 1];
        !          1111:          if (p5 == d - 1)
        !          1112:            p6 = p1 + 1 - d;
        !          1113:          else
        !          1114:            p6 = p1 + 1;
        !          1115:          y[p1] = 0;
        !          1116:          V = 0;
        !          1117:          for (p2 = 1 + p4, p3 = 1 + x[p1]; p2 <= b; p2++)
        !          1118:          {
        !          1119:            V += mael(W,G[p6][p3],G[p1][p2]);
        !          1120:            p3 += s;
        !          1121:            if (p3 > b)
        !          1122:              p3 -= b;
        !          1123:          }
        !          1124:          p3 = 1 + x[p1] - s;
        !          1125:          if (p3 <= 0)
        !          1126:            p3 += b;
        !          1127:          for (p2 = p4; p2 >= 1; p2--)
        !          1128:          {
        !          1129:            V += mael(W,G[p6][p3],G[p1][p2]);
        !          1130:            p3 -= s;
        !          1131:            if (p3 <= 0)
        !          1132:              p3 += b;
        !          1133:          }
        !          1134:          ar[p1]=V;
        !          1135:        }
        !          1136:       V = 0;
        !          1137:       for (p1 = 1; p1 <= a; p1++)
        !          1138:        V += ar[p1];
        !          1139:       if (labs(V)<=n)
        !          1140:       {
        !          1141:        for (p1 = 1, p5 = d; p1 <= a; p1++, p5++)
        !          1142:        {
        !          1143:          if (p5 == d)
        !          1144:          {
        !          1145:            p5 = 0;
        !          1146:            p4 = 0;
        !          1147:          }
        !          1148:          else
        !          1149:            p4 = x[p1 - 1];
        !          1150:          if (p5 == d - 1)
        !          1151:            p6 = p1 + 1 - d;
        !          1152:          else
        !          1153:            p6 = p1 + 1;
        !          1154:          for (p2 = 1 + p4, p3 = 1 + x[p1]; p2 <= b; p2++)
        !          1155:          {
        !          1156:            pf[G[p1][p2]] = G[p6][p3];
        !          1157:            p3 += s;
        !          1158:            if (p3 > b)
        !          1159:              p3 -= b;
        !          1160:          }
        !          1161:          p3 = 1 + x[p1] - s;
        !          1162:          if (p3 <= 0)
        !          1163:            p3 += b;
        !          1164:          for (p2 = p4; p2 >= 1; p2--)
        !          1165:          {
        !          1166:            pf[G[p1][p2]] = G[p6][p3];
        !          1167:            p3 -= s;
        !          1168:            if (p3 <= 0)
        !          1169:              p3 += b;
        !          1170:          }
        !          1171:        }
        !          1172:        if (verifietest(pf, td))
        !          1173:        {
        !          1174:          if (DEBUGLEVEL >= 1)
        !          1175:          {
        !          1176:            GEN nb=addis(mulss(l2,N1),l1);
        !          1177:            msgtimer("testpermutation(%Z)", nb);
        !          1178:            if (DEBUGLEVEL >= 2 && hop)
        !          1179:              fprintferr("GaloisConj:%d hop sur %Z iterations\n", hop, nb);
        !          1180:          }
        !          1181:          avma = av;
        !          1182:          return pf;
        !          1183:        }
        !          1184:        else
        !          1185:          hop++;
        !          1186:       }
        !          1187:     }
        !          1188:   }
        !          1189:   if (DEBUGLEVEL >= 1)
        !          1190:   {
        !          1191:     msgtimer("testpermutation(%Z)", NN);
        !          1192:     if (DEBUGLEVEL >= 2 && hop)
        !          1193:       fprintferr("GaloisConj:%d hop sur %Z iterations\n", hop, NN);
        !          1194:   }
        !          1195:   avma = avm;
        !          1196:   return gzero;
        !          1197: }
        !          1198: /* Compute generators for the subgroup of (Z/nZ)* given in HNF.
        !          1199:  * I apologize for the following spec:
        !          1200:  * If zns=znstar(2) then
        !          1201:  * zn2=gtovecsmall((GEN)zns[2]);
        !          1202:  * zn3=lift((GEN)zns[3]);
        !          1203:  * gen and ord : VECSMALL of length lg(zn3).
        !          1204:  * the result is in gen.
        !          1205:  * ord contains the relatives orders of the generators.
        !          1206:  */
        !          1207: GEN hnftogeneratorslist(long n, GEN zn2, GEN zn3, GEN lss, GEN gen, GEN ord)
        !          1208: {
        !          1209:   ulong ltop=avma;
        !          1210:   int j,h;
        !          1211:   GEN m=stoi(n);
        !          1212:   for (j = 1; j < lg(gen); j++)
        !          1213:   {
        !          1214:     gen[j] = 1;
        !          1215:     for (h = 1; h < lg(lss); h++)
        !          1216:       gen[j] = mulssmod(gen[j], itos(powmodulo((GEN)zn3[h],gmael(lss,j,h),m)),n);
        !          1217:     ord[j] = zn2[j] / itos(gmael(lss,j,j));
        !          1218:   }
        !          1219:   avma=ltop;
        !          1220:   return gen;
        !          1221: }
        !          1222: /*in place sort. Return V for convenience only*/
        !          1223: GEN sortvecsmall(GEN V)
        !          1224: {
        !          1225:   long i,j,k,l,m;
        !          1226:   for(l=1;l<lg(V);l<<=1)
        !          1227:     for(j=1;(j>>1)<lg(V);j+=l<<1)
        !          1228:       for(k=j+l,i=j; i<k && k<j+(l<<1) && k<lg(V);)
        !          1229:        if (V[i]>V[k])
        !          1230:        {
        !          1231:          long z=V[k];
        !          1232:          for (m=k;m>i;m--)
        !          1233:            V[m]=V[m-1];
        !          1234:          V[i]=z;
        !          1235:          k++;
        !          1236:        }
        !          1237:        else
        !          1238:          i++;
        !          1239:   return V ;
        !          1240: }
        !          1241: GEN uniqvecsmall(GEN V)
        !          1242: {
        !          1243:   ulong ltop=avma;
        !          1244:   GEN W;
        !          1245:   long i,j;
        !          1246:   if ( lg(V) == 1 ) return gcopy(V);
        !          1247:   W=cgetg(lg(V),t_VECSMALL);
        !          1248:   W[1]=V[1];
        !          1249:   for(i=2,j=1;i<lg(V);i++)
        !          1250:     if (V[i]!=W[j])
        !          1251:       W[++j]=V[i];
        !          1252:   setlg(W,j+1);
        !          1253:   return gerepileupto(ltop,W);
        !          1254: }
        !          1255: int pari_compare_lg(GEN x, GEN y)
        !          1256: {
        !          1257:   return lg(x)-lg(y);
        !          1258: }
        !          1259: /* Compute the elements of the subgroup of (Z/nZ)* given in HNF.
        !          1260:  * I apologize for the following spec:
        !          1261:  * If zns=znstar(2) then
        !          1262:  * zn2=gtovecsmall((GEN)zns[2]);
        !          1263:  * zn3=lift((GEN)zns[3]);
        !          1264:  * card=cardinal of the subgroup(i.e phi(n)/det(lss))
        !          1265:  */
        !          1266: GEN
        !          1267: hnftoelementslist(long n, GEN zn2, GEN zn3, GEN lss, long card)
        !          1268: {
        !          1269:   ulong   ltop;
        !          1270:   GEN     sg, gen, ord;
        !          1271:   int     k, j, l;
        !          1272:   sg = cgetg(1 + card, t_VECSMALL);
        !          1273:   ltop=avma;
        !          1274:   gen = cgetg(lg(zn3), t_VECSMALL);
        !          1275:   ord = cgetg(lg(zn3), t_VECSMALL);
        !          1276:   sg[1] = 1;
        !          1277:   hnftogeneratorslist(n,zn2,zn3,lss,gen,ord);
        !          1278:   for (j = 1, l = 1; j < lg(gen); j++)
        !          1279:   {
        !          1280:     int     c = l * (ord[j] - 1);
        !          1281:     for (k = 1; k <= c; k++)   /* I like it */
        !          1282:       sg[++l] = mulssmod(sg[k], gen[j], n);
        !          1283:   }
        !          1284:   sortvecsmall(sg);
        !          1285:   avma=ltop;
        !          1286:   return sg;
        !          1287: }
        !          1288:
        !          1289: /*
        !          1290:  * Calcule la liste des sous groupes de \ZZ/m\ZZ d'ordre divisant p et
        !          1291:  * retourne la liste de leurs elements
        !          1292:  */
        !          1293: GEN
        !          1294: listsousgroupes(long m, long p)
        !          1295: {
        !          1296:   ulong   ltop = avma;
        !          1297:   GEN     zns, lss, sg, res, zn2, zn3;
        !          1298:   int     k, card, i, phi;
        !          1299:   if (m == 2)
        !          1300:   {
        !          1301:     res = cgetg(2, t_VEC);
        !          1302:     sg = cgetg(2, t_VECSMALL);
        !          1303:     res[1] = (long) sg;
        !          1304:     sg[1] = 1;
        !          1305:     return res;
        !          1306:   }
        !          1307:   zns = znstar(stoi(m));
        !          1308:   phi = itos((GEN) zns[1]);
        !          1309:   zn2 = gtovecsmall((GEN)zns[2]);
        !          1310:   zn3 = lift((GEN)zns[3]);
        !          1311:   lss = subgrouplist((GEN) zns[2], 0);
        !          1312:   res = cgetg(lg(lss), t_VEC);
        !          1313:   for (k = 1, i = lg(lss) - 1; i >= 1; i--)
        !          1314:   {
        !          1315:     long    av;
        !          1316:     av = avma;
        !          1317:     card = phi / itos(det((GEN) lss[i]));
        !          1318:     avma = av;
        !          1319:     if (p % card == 0)
        !          1320:       res[k++] = (long) hnftoelementslist(m,zn2,zn3,(GEN)lss[i],card);
        !          1321:   }
        !          1322:   setlg(res,k);
        !          1323:   res=gen_sort(res,0,&pari_compare_lg);
        !          1324:   return gerepileupto(ltop,res);
        !          1325: }
        !          1326:
        !          1327: /* Compute the orbits decomposition of a permutation
        !          1328:  * or of a set of permutations given by a vector.
        !          1329:  * v must not be an empty vector, becaude there is no way then
        !          1330:  * to tell the length of the permutation.
        !          1331:  */
        !          1332:
        !          1333: GEN
        !          1334: permorbite(GEN v)
        !          1335: {
        !          1336:   ulong   ltop = avma, lbot;
        !          1337:   int     i, j, k, l, m, n, o, p, flag;
        !          1338:   GEN     bit, cycle, cy, u;
        !          1339:   if (typ(v) == t_VECSMALL)
        !          1340:   {
        !          1341:     u = cgetg(2, t_VEC);
        !          1342:     u[1] = (long) v;
        !          1343:     v = u;
        !          1344:   }
        !          1345:   n = lg(v[1]);
        !          1346:   cycle = cgetg(n, t_VEC);
        !          1347:   bit = cgetg(n, t_VECSMALL);
        !          1348:   for (i = 1; i < n; i++)
        !          1349:     bit[i] = 0;
        !          1350:   for (k = 1, l = 1; k < n;)
        !          1351:   {
        !          1352:     for (j = 1; bit[j]; j++);
        !          1353:     cy = cgetg(n, t_VECSMALL);
        !          1354:     m = 1;
        !          1355:     cy[m++] = j;
        !          1356:     bit[j] = 1;
        !          1357:     k++;
        !          1358:     do
        !          1359:     {
        !          1360:       flag = 0;
        !          1361:       for (o = 1; o < lg(v); o++)
        !          1362:       {
        !          1363:        for (p = 1; p < m; p++) /* m varie! */
        !          1364:        {
        !          1365:          j = ((long **) v)[o][cy[p]];
        !          1366:          if (!bit[j])
        !          1367:          {
        !          1368:            flag = 1;
        !          1369:            bit[j] = 1;
        !          1370:            k++;
        !          1371:            cy[m++] = j;
        !          1372:          }
        !          1373:        }
        !          1374:       }
        !          1375:     }
        !          1376:     while (flag);
        !          1377:     setlg(cy, m);
        !          1378:     cycle[l++] = (long) cy;
        !          1379:   }
        !          1380:   setlg(cycle, l);
        !          1381:   lbot = avma;
        !          1382:   cycle = gcopy(cycle);
        !          1383:   return gerepile(ltop, lbot, cycle);
        !          1384: }
        !          1385:
        !          1386: GEN
        !          1387: fixedfieldpolsigma(GEN sigma, GEN p, GEN Tp, GEN sym, GEN deg, long g)
        !          1388: {
        !          1389:   ulong ltop=avma;
        !          1390:   long i, j, npows;
        !          1391:   GEN  s, f, pows;
        !          1392:   sigma=lift(gmul(sigma,gmodulsg(1,p)));
        !          1393:   f=polx[varn(sigma)];
        !          1394:   s=zeropol(varn(sigma));
        !          1395:   for(j=1;j<lg(sym);j++)
        !          1396:     if(sym[j])
        !          1397:     {
        !          1398:       s=FpX_add(s,FpX_Fp_mul(FpXQ_pow(f,stoi(deg[j]),Tp,p),stoi(sym[j]),p),p);
        !          1399:     }
        !          1400:   npows = brent_kung_optpow(lgef(Tp)-4,g-1);
        !          1401:   pows  = FpXQ_powers(sigma,npows,Tp,p);
        !          1402:   for(i=2; i<=g;i++)
        !          1403:   {
        !          1404:     f=FpX_FpXQV_compo(f,pows,Tp,p);
        !          1405:     for(j=1;j<lg(sym);j++)
        !          1406:       if(sym[j])
        !          1407:       {
        !          1408:        s=FpX_add(s,FpX_Fp_mul(FpXQ_pow(f,stoi(deg[j]),Tp,p),stoi(sym[j]),p),p);
        !          1409:       }
        !          1410:   }
        !          1411:   return gerepileupto(ltop, s);
        !          1412: }
        !          1413:
        !          1414: GEN
        !          1415: fixedfieldfactmod(GEN Sp, GEN p, GEN Tmod)
        !          1416: {
        !          1417:   long i;
        !          1418:   long l=lg(Tmod);
        !          1419:   GEN F=cgetg(l,t_VEC);
        !          1420:   for(i=1;i<l;i++)
        !          1421:     F[i]=(long)FpXQ_minpoly(Sp, (GEN) Tmod[i],p);
        !          1422:   return F;
        !          1423: }
        !          1424:
        !          1425: GEN
        !          1426: fixedfieldnewtonsumaut(GEN sigma, GEN p, GEN Tp, GEN e, long g)
        !          1427: {
        !          1428:   ulong ltop=avma;
        !          1429:   long i;
        !          1430:   GEN s,f,V;
        !          1431:   long rt;
        !          1432:   sigma=lift(gmul(sigma,gmodulsg(1,p)));
        !          1433:   f=polx[varn(sigma)];
        !          1434:   rt=brent_kung_optpow(lgef(Tp)-4,g-1);
        !          1435:   V=FpXQ_powers(sigma,rt,Tp,p);
        !          1436:   s=FpXQ_pow(f,e,Tp,p);
        !          1437:   for(i=2; i<=g;i++)
        !          1438:   {
        !          1439:     f=FpX_FpXQV_compo(f,V,Tp,p);
        !          1440:     s=FpX_add(s,FpXQ_pow(f,e,Tp,p),p);
        !          1441:   }
        !          1442:   return gerepileupto(ltop, s);
        !          1443: }
        !          1444:
        !          1445: GEN
        !          1446: fixedfieldnewtonsum(GEN O, GEN L, GEN mod, GEN e)
        !          1447: {
        !          1448:   long f,g;
        !          1449:   long i,j;
        !          1450:   GEN PL;
        !          1451:   f=lg(O)-1;
        !          1452:   g=lg(O[1])-1;
        !          1453:   PL=cgetg(lg(O), t_COL);
        !          1454:   for(i=1; i<=f; i++)
        !          1455:   {
        !          1456:     ulong ltop=avma;
        !          1457:     GEN s=gzero;
        !          1458:     for(j=1; j<=g; j++)
        !          1459:       s=addii(s,powmodulo((GEN)L[mael(O,i,j)],e,mod));
        !          1460:     PL[i]=lpileupto(ltop,modii(s,mod));
        !          1461:   }
        !          1462:   return PL;
        !          1463: }
        !          1464:
        !          1465: GEN
        !          1466: fixedfieldpol(GEN O, GEN L, GEN mod, GEN sym, GEN deg)
        !          1467: {
        !          1468:   ulong ltop=avma;
        !          1469:   long i;
        !          1470:   GEN S=gzero;
        !          1471:   for(i=1;i<lg(sym);i++)
        !          1472:     if (sym[i])
        !          1473:       S=gadd(S,gmulsg(sym[i],fixedfieldnewtonsum(O, L, mod, stoi(deg[i]))));
        !          1474:   S=FpV_red(S,mod);
        !          1475:   return gerepileupto(ltop, S);
        !          1476: }
        !          1477:
        !          1478: static long
        !          1479: fixedfieldtests(GEN LN, long n)
        !          1480: {
        !          1481:   long i,j,k;
        !          1482:   for (i=1;i<lg(LN[1]);i++)
        !          1483:     for(j=i+1;j<lg(LN[1]);j++)
        !          1484:     {
        !          1485:       for(k=1;k<=n;k++)
        !          1486:        if (cmpii(gmael(LN,k,j),gmael(LN,k,i)))
        !          1487:          break;
        !          1488:       if (k>n)
        !          1489:        return 0;
        !          1490:     }
        !          1491:   return 1;
        !          1492: }
        !          1493:
        !          1494: static long
        !          1495: fixedfieldtest(GEN V)
        !          1496: {
        !          1497:   long i,j;
        !          1498:   for (i=1;i<lg(V);i++)
        !          1499:     for(j=i+1;j<lg(V);j++)
        !          1500:       if (!cmpii((GEN)V[i],(GEN)V[j]))
        !          1501:        return 0;
        !          1502:   return 1;
        !          1503: }
        !          1504:
        !          1505: void
        !          1506: debug_surmer(char *s,GEN S, long n)
        !          1507: {
        !          1508:   long l=lg(S);
        !          1509:   setlg(S,n+1);
        !          1510:   fprintferr(s,S);
        !          1511:   setlg(S,l);
        !          1512: }
        !          1513:
        !          1514: /*We try hard to find a polynomial R squarefree mod p.
        !          1515: Unfortunately, it may be too much asked.
        !          1516: A less bugprone way would be to only ask it to be squarefree mod p^e
        !          1517: with e not too big. Most of the code is here, but I lack the theoretical
        !          1518: knowledge to make it to work smoothly.B.A.
        !          1519: */
        !          1520: static GEN
        !          1521: fixedfieldsurmer(GEN O, GEN L, GEN mod, GEN l, GEN p, GEN S, GEN deg, long v, GEN LN,long n)
        !          1522: {
        !          1523:   long i;
        !          1524:   GEN V;
        !          1525:   V=(GEN)LN[n];
        !          1526:   for (i=1;i<lg(S);i++)
        !          1527:     S[i]=0;
        !          1528:   S[n]=1;
        !          1529:   for (i=0;i<2*n-1;i++)
        !          1530:   {
        !          1531:     long k;
        !          1532:     if (fixedfieldtest(V))
        !          1533:     {
        !          1534:       ulong av=avma;
        !          1535:       GEN s=fixedfieldpol(O,L,mod,S,deg);
        !          1536:       GEN P=FpV_roots_to_pol(s,mod,v);
        !          1537:       P=FpX_center(P,mod);
        !          1538:       if (p==gun || FpX_is_squarefree(P,p))
        !          1539:       {
        !          1540:        GEN V;
        !          1541:        if (DEBUGLEVEL>=4)
        !          1542:          debug_surmer("FixedField: Sym: %Z\n",S,n);
        !          1543:        V=cgetg(3,t_VEC);
        !          1544:        V[1]=lcopy(s);/*do not swap*/
        !          1545:        V[2]=lcopy(P);
        !          1546:        return V;
        !          1547:       }
        !          1548:       else
        !          1549:       {
        !          1550:        if (DEBUGLEVEL>=6)
        !          1551:          debug_surmer("FixedField: bad mod: %Z\n",S,n);
        !          1552:        avma=av;
        !          1553:       }
        !          1554:     }
        !          1555:     else
        !          1556:     {
        !          1557:       if (DEBUGLEVEL>=6)
        !          1558:         debug_surmer("FixedField: Tested: %Z\n",S,n);
        !          1559:     }
        !          1560:     k=1+(i%n);
        !          1561:     S[k]++;
        !          1562:     V=FpV_red(gadd(V,(GEN)LN[k]),l);
        !          1563:   }
        !          1564:   return NULL;
        !          1565: }
        !          1566:
        !          1567: GEN
        !          1568: fixedfieldsympol(GEN O, GEN L, GEN mod, GEN l, GEN p, GEN S, GEN deg, long v)
        !          1569: {
        !          1570:   ulong ltop=avma;
        !          1571:   GEN V=NULL;
        !          1572:   GEN LN=cgetg(lg(L),t_VEC);
        !          1573:   GEN Ll=FpV_red(L,l);
        !          1574:   long n,i;
        !          1575:   for(i=1;i<lg(deg);i++)
        !          1576:     deg[i]=0;
        !          1577:   for(n=1,i=1;i<lg(L);i++)
        !          1578:   {
        !          1579:     long j;
        !          1580:     LN[n]=(long)fixedfieldnewtonsum(O,Ll,l,stoi(i));
        !          1581:     for(j=2;j<lg(LN[n]);j++)
        !          1582:       if(cmpii(gmael(LN,n,j),gmael(LN,n,1)))
        !          1583:        break;
        !          1584:     if(j==lg(LN[n]) && j>2)
        !          1585:       continue;
        !          1586:     if (DEBUGLEVEL>=6) fprintferr("FixedField: LN[%d]=%Z\n",n,LN[n]);
        !          1587:     deg[n]=i;
        !          1588:     if (fixedfieldtests(LN,n))
        !          1589:     {
        !          1590:       V=fixedfieldsurmer(O,L,mod,l,p,S,deg,v,LN,n);
        !          1591:       if (V)
        !          1592:        break;
        !          1593:     }
        !          1594:     n++;
        !          1595:   }
        !          1596:   if (DEBUGLEVEL>=4)
        !          1597:   {
        !          1598:     long l=lg(deg);
        !          1599:     setlg(deg,n);
        !          1600:     fprintferr("FixedField: Computed degrees: %Z\n",deg);
        !          1601:     setlg(deg,l);
        !          1602:   }
        !          1603:   if (!V)
        !          1604:     err(talker, "prime too small in fixedfield");
        !          1605:   return gerepileupto(ltop,V);
        !          1606: }
        !          1607: /*
        !          1608:  * Calcule l'inclusion de R dans T i.e. S telque T|R\compo S
        !          1609:  * Ne recopie pas PL.
        !          1610:  */
        !          1611: GEN
        !          1612: fixedfieldinclusion(GEN O, GEN PL)
        !          1613: {
        !          1614:   GEN     S;
        !          1615:   int     i, j;
        !          1616:   S = cgetg((lg(O) - 1) * (lg(O[1]) - 1) + 1, t_COL);
        !          1617:   for (i = 1; i < lg(O); i++)
        !          1618:     for (j = 1; j < lg(O[i]); j++)
        !          1619:       S[((GEN *) O)[i][j]] = PL[i];
        !          1620:   return S;
        !          1621: }
        !          1622:
        !          1623: /*Usually mod is bigger than than den so there is no need to reduce it.*/
        !          1624: GEN
        !          1625: vandermondeinversemod(GEN L, GEN T, GEN den, GEN mod)
        !          1626: {
        !          1627:   ulong   av;
        !          1628:   int     i, j, n = lg(L);
        !          1629:   long    x = varn(T);
        !          1630:   GEN     M, P, Tp;
        !          1631:   M = cgetg(n, t_MAT);
        !          1632:   av=avma;
        !          1633:   Tp = gclone(FpX_red(deriv(T, x),mod)); /*clone*/
        !          1634:   avma=av;
        !          1635:   for (i = 1; i < n; i++)
        !          1636:   {
        !          1637:     GEN z;
        !          1638:     av = avma;
        !          1639:     z = mpinvmod(FpX_eval(Tp, (GEN) L[i],mod),mod);
        !          1640:     z = modii(mulii(den,z),mod);
        !          1641:     P = FpX_Fp_mul(FpX_div(T, deg1pol(gun,negi((GEN) L[i]),x),mod), z, mod);
        !          1642:     M[i] = lgetg(n, t_COL);
        !          1643:     for (j = 1; j < n; j++)
        !          1644:       mael(M,i,j) = lcopy((GEN) P[1 + j]);
        !          1645:     M[i] = lpileupto(av,(GEN)M[i]);
        !          1646:   }
        !          1647:   gunclone(Tp); /*unclone*/
        !          1648:   return M;
        !          1649: }
        !          1650: /* Calcule le polynome associe a un vecteur conjugue v*/
        !          1651: static GEN
        !          1652: vectopol(GEN v, GEN M, GEN den , GEN mod, long x)
        !          1653: {
        !          1654:   long n = lg(v),i,k,av;
        !          1655:   GEN z = cgetg(n+1,t_POL),p1,p2,mod2;
        !          1656:   av=avma;
        !          1657:   mod2=gclone(shifti(mod,-1));/*clone*/
        !          1658:   avma=av;
        !          1659:   z[1]=evalsigne(1)|evalvarn(x)|evallgef(n+1);
        !          1660:   for (i=2; i<=n; i++)
        !          1661:   {
        !          1662:     p1=gzero; av=avma;
        !          1663:     for (k=1; k<n; k++)
        !          1664:     {
        !          1665:       p2=mulii(gcoeff(M,i-1,k),(GEN)v[k]);
        !          1666:       p1=addii(p1,p2);
        !          1667:     }
        !          1668:     p1=modii(p1,mod);
        !          1669:     if (cmpii(p1,mod2)>0) p1=subii(p1,mod);
        !          1670:     p1=gdiv(p1,den);
        !          1671:     z[i]=lpileupto(av,p1);
        !          1672:   }
        !          1673:   gunclone(mod2);/*unclone*/
        !          1674:   return normalizepol_i(z,n+1);
        !          1675: }
        !          1676: /* Calcule le polynome associe a une permutation des racines*/
        !          1677: static GEN
        !          1678: permtopol(GEN p, GEN L, GEN M, GEN den, GEN mod, long x)
        !          1679: {
        !          1680:   long n = lg(L),i,k,av;
        !          1681:   GEN z = cgetg(n+1,t_POL),p1,p2,mod2;
        !          1682:   if (lg(p) != n) err(talker,"incorrect permutation in permtopol");
        !          1683:   av=avma;
        !          1684:   mod2=gclone(shifti(mod,-1)); /*clone*/
        !          1685:   avma=av;
        !          1686:   z[1]=evalsigne(1)|evalvarn(x)|evallgef(n+1);
        !          1687:   for (i=2; i<=n; i++)
        !          1688:   {
        !          1689:     p1=gzero; av=avma;
        !          1690:     for (k=1; k<n; k++)
        !          1691:     {
        !          1692:       p2=mulii(gcoeff(M,i-1,k),(GEN)L[p[k]]);
        !          1693:       p1=addii(p1,p2);
        !          1694:     }
        !          1695:     p1=modii(p1,mod);
        !          1696:     if (cmpii(p1,mod2)>0) p1=subii(p1,mod);
        !          1697:     p1=gdiv(p1,den);
        !          1698:     z[i]=lpileupto(av,p1);
        !          1699:   }
        !          1700:   gunclone(mod2); /*unclone*/
        !          1701:   return normalizepol_i(z,n+1);
        !          1702: }
        !          1703:
        !          1704: GEN
        !          1705: galoisgrouptopol( GEN res, GEN L, GEN M, GEN den, GEN mod, long v)
        !          1706: {
        !          1707:   GEN aut = cgetg(lg(res), t_COL);
        !          1708:   long i;
        !          1709:   for (i = 1; i < lg(res); i++)
        !          1710:   {
        !          1711:     if (DEBUGLEVEL>=6)
        !          1712:       fprintferr("%d ",i);
        !          1713:     aut[i] = (long) permtopol((GEN) res[i], L, M, den, mod, v);
        !          1714:   }
        !          1715:   return aut;
        !          1716: }
        !          1717: /* No more used and ugly.
        !          1718:  * However adding corepartial to GP seem a good idea.
        !          1719:  *
        !          1720:  * factorise partiellement n sous la forme n=d*u*f^2 ou d est un
        !          1721:  * discriminant fondamental et u n'est pas un carre parfait et
        !          1722:  * retourne u*f
        !          1723:  * Note: Parfois d n'est pas un discriminant (congru a 3 mod 4).
        !          1724:  * Cela se produit si u est congrue a 3 mod 4.
        !          1725:  */
        !          1726: GEN
        !          1727: corediscpartial(GEN n)
        !          1728: {
        !          1729:   ulong   av = avma;
        !          1730:   long i,r,s;
        !          1731:   GEN fa, p1, p2, p3, res = gun, res2 = gun, res3=gun;
        !          1732:   /*d=res,f=res2,u=res3*/
        !          1733:   if (gcmp1(n))
        !          1734:     return gun;
        !          1735:   fa = auxdecomp(n, 0);
        !          1736:   p1 = (GEN) fa[1];
        !          1737:   p2 = (GEN) fa[2];
        !          1738:   for (i = 1; i < lg(p1) - 1; i++)
        !          1739:   {
        !          1740:     p3 = (GEN) p2[i];
        !          1741:     if (mod2(p3))
        !          1742:       res = mulii(res, (GEN) p1[i]);
        !          1743:     if (!gcmp1(p3))
        !          1744:       res2 = mulii(res2, gpow((GEN) p1[i], shifti(p3, -1), 0));
        !          1745:   }
        !          1746:   p3 = (GEN) p2[i];
        !          1747:   if (mod2(p3))                /* impaire: verifions */
        !          1748:   {
        !          1749:     if (!gcmp1(p3))
        !          1750:       res2 = mulii(res2, gpow((GEN) p1[i], shifti(p3, -1), 0));
        !          1751:     if (isprime((GEN) p1[i]))
        !          1752:       res = mulii(res, (GEN) p1[i]);
        !          1753:     else
        !          1754:       res3 = (GEN)p1[i];
        !          1755:   }
        !          1756:   else                 /* paire:OK */
        !          1757:     res2 = mulii(res2, gpow((GEN) p1[i], shifti(p3, -1), 0));
        !          1758:   r = mod4(res);
        !          1759:   if (signe(res) < 0)
        !          1760:     r = 4 - r;
        !          1761:   s = mod4(res3);/*res2 est >0*/
        !          1762:   if (r == 3 && s!=3)
        !          1763:     /*d est n'est pas un discriminant mais res2 l'est: corrige*/
        !          1764:     res2 = gmul2n((GEN) res2, -1);
        !          1765:   return gerepileupto(av,gmul(res2,res3));
        !          1766: }
        !          1767: GEN respm(GEN x,GEN y,GEN pm);
        !          1768: GEN ZX_disc(GEN x);
        !          1769:
        !          1770: GEN
        !          1771: indexpartial(GEN P, GEN DP)
        !          1772: {
        !          1773:   ulong   av = avma;
        !          1774:   long i, nb;
        !          1775:   GEN fa, p1, res = gun, dP;
        !          1776:   dP = derivpol(P);
        !          1777:   if(DEBUGLEVEL>=5) gentimer(3);
        !          1778:   if(!DP) DP = ZX_disc(P);
        !          1779:   DP = mpabs(DP);
        !          1780:   if(DEBUGLEVEL>=5) genmsgtimer(3,"IndexPartial: discriminant");
        !          1781:   fa = auxdecomp(DP, 0);
        !          1782:   if(DEBUGLEVEL>=5) genmsgtimer(3,"IndexPartial: factorization");
        !          1783:   nb = lg(fa[1]);
        !          1784:   for (i = 1; i < nb; i++)
        !          1785:   {
        !          1786:     GEN p=gmael(fa,1,i);
        !          1787:     GEN e=gmael(fa,2,i);
        !          1788:     p1 = powgi(p,shifti(e,-1));
        !          1789:     if ( i==nb-1 )
        !          1790:     {
        !          1791:       if ( mod2(e) && !isprime(p) )
        !          1792:        p1 = mulii(p1,p);
        !          1793:     }
        !          1794:     else if ( cmpis(e,4)>=0 )
        !          1795:     {
        !          1796:       if(DEBUGLEVEL>=5) fprintferr("IndexPartial: factor %Z ",p1);
        !          1797:       p1 = mppgcd(p1, respm(P,dP,p1));
        !          1798:       if(DEBUGLEVEL>=5)
        !          1799:       {
        !          1800:         fprintferr("--> %Z : ",p1);
        !          1801:         genmsgtimer(3,"");
        !          1802:       }
        !          1803:     }
        !          1804:     res=mulii(res,p1);
        !          1805:   }
        !          1806:   return gerepileupto(av,res);
        !          1807: }
        !          1808:
        !          1809: /* Calcule la puissance exp d'une permutation decompose en cycle */
        !          1810: GEN
        !          1811: permcyclepow(GEN O, long exp)
        !          1812: {
        !          1813:   int     j, k, n;
        !          1814:   GEN     p;
        !          1815:   for (n = 0, j = 1; j < lg(O); j++)
        !          1816:     n += lg(O[j]) - 1;
        !          1817:   p = cgetg(n + 1, t_VECSMALL);
        !          1818:   for (j = 1; j < lg(O); j++)
        !          1819:   {
        !          1820:     n = lg(O[j]) - 1;
        !          1821:     for (k = 1; k <= n; k++)
        !          1822:       p[mael(O,j,k)] = mael(O,j,1 + (k + exp - 1) % n);
        !          1823:   }
        !          1824:   return p;
        !          1825: }
        !          1826:
        !          1827: /*
        !          1828:  * Casse l'orbite O en sous-orbite d'ordre premier correspondant a des
        !          1829:  * puissance de l'element
        !          1830:  */
        !          1831: GEN
        !          1832: splitorbite(GEN O)
        !          1833: {
        !          1834:   ulong   ltop = avma, lbot;
        !          1835:   int     i, n;
        !          1836:   GEN     F, fc, res;
        !          1837:   n = lg(O[1]) - 1;
        !          1838:   F = factor(stoi(n));
        !          1839:   fc = cgetg(lg(F[1]), t_VECSMALL);
        !          1840:   for (i = 1; i < lg(fc); i++)
        !          1841:     fc[i] = itos(powgi(gmael(F,1,i), gmael(F,2,i)));
        !          1842:   lbot = avma;
        !          1843:   res = cgetg(3, t_VEC);
        !          1844:   res[1] = lgetg(lg(fc), t_VEC);
        !          1845:   res[2] = lgetg(lg(fc), t_VECSMALL);
        !          1846:   for (i = 1; i < lg(fc); i++)
        !          1847:   {
        !          1848:     ((GEN **) res)[1][lg(fc) - i] = permcyclepow(O, n / fc[i]);
        !          1849:     ((GEN *) res)[2][lg(fc) - i] = fc[i];
        !          1850:   }
        !          1851:   if ( DEBUGLEVEL>=4 )
        !          1852:     fprintferr("GaloisConj:splitorbite: %Z\n",res);
        !          1853:   return gerepile(ltop, lbot, res);
        !          1854: }
        !          1855:
        !          1856: /*
        !          1857:  * structure qui contient l'analyse du groupe de Galois par etude des degres
        !          1858:  * de Frobenius:
        !          1859:  *
        !          1860:  * p: nombre premier a relever deg: degre du lift à effectuer pgp: plus grand
        !          1861:  * diviseur premier du degre de T.
        !          1862:  * l: un nombre premier tel que T est totalement decompose
        !          1863:  * modulo l ppp:  plus petit diviseur premier du degre de T. primepointer:
        !          1864:  * permet de calculer les premiers suivant p.
        !          1865:  */
        !          1866: struct galois_analysis
        !          1867: {
        !          1868:   long    p;
        !          1869:   long    deg;
        !          1870:   long    ord;
        !          1871:   long    l;
        !          1872:   long    ppp;
        !          1873:   long    p4;
        !          1874:   enum {ga_all_normal=1,ga_ext_2=2,ga_non_wss=4} group;
        !          1875:   byteptr primepointer;
        !          1876: };
        !          1877: void
        !          1878: galoisanalysis(GEN T, struct galois_analysis *ga, long calcul_l, long karma_type)
        !          1879: {
        !          1880:   ulong ltop=avma;
        !          1881:   long n,p;
        !          1882:   long i;
        !          1883:   enum {k_amoeba=0,k_snake=1,k_fish=2,k_bird=4,k_rodent=6,k_dog=8,k_human=9,k_cat=12} karma;
        !          1884:   long group,linf;
        !          1885:   /*TODO: complete the table to at least 200*/
        !          1886:   const int prim_nonss_orders[]={36,48,56,60,72,75,80,96,108,120,132,0};
        !          1887:   GEN F,Fp,Fe,Fpe,O;
        !          1888:   long np;
        !          1889:   long order,phi_order;
        !          1890:   long plift,nbmax,nbtest,deg;
        !          1891:   byteptr primepointer,pp;
        !          1892:   if (DEBUGLEVEL >= 1)
        !          1893:     timer2();
        !          1894:   n = degpol(T);
        !          1895:   if (!karma_type) karma_type=n;
        !          1896:   else err(warner,"entering black magic computation");
        !          1897:   O = cgetg(n+1,t_VECSMALL);
        !          1898:   for(i=1;i<=n;i++) O[i]=0;
        !          1899:   F = factor(stoi(n));
        !          1900:   Fp=gtovecsmall((GEN)F[1]);
        !          1901:   Fe=gtovecsmall((GEN)F[2]);
        !          1902:   np=lg(Fp)-1;
        !          1903:   Fpe=cgetg(np+1, t_VECSMALL);
        !          1904:   for (i = 1; i < lg(Fpe); i++)
        !          1905:     Fpe[i] = itos(powgi(gmael(F,1,i), gmael(F,2,i)));
        !          1906:   /*In this part, we study the cardinal of the group to have an information
        !          1907:     about the orders, so if we are unlucky we can continue.*/
        !          1908:
        !          1909:   /*Are there non WSS groups of this order ?*/
        !          1910:   group=0;
        !          1911:   for(i=0;prim_nonss_orders[i];i++)
        !          1912:     if (n%prim_nonss_orders[i] == 0)
        !          1913:     {
        !          1914:       group |= ga_non_wss;
        !          1915:       break;
        !          1916:     }
        !          1917:   if ( n>12 && n%12 == 0 )
        !          1918:   {
        !          1919:     /*We need to know the greatest prime dividing n/12*/
        !          1920:     if ( Fp[np] == 3 && Fe[np] == 1 )
        !          1921:       group |= ga_ext_2;
        !          1922:   }
        !          1923:   phi_order = 1;
        !          1924:   order = 1;
        !          1925:   for (i = np; i > 0; i--)
        !          1926:   {
        !          1927:     p = Fp[i];
        !          1928:     if (phi_order % p != 0)
        !          1929:     {
        !          1930:       order *= p;
        !          1931:       phi_order *= p - 1;
        !          1932:     }
        !          1933:     else
        !          1934:     {
        !          1935:       group |= ga_all_normal;
        !          1936:       break;
        !          1937:     }
        !          1938:     if (Fe[i]>1)
        !          1939:       break;
        !          1940:   }
        !          1941:   /*Now, we study the orders of the Frobenius elements*/
        !          1942:   plift = 0;
        !          1943:   nbmax = 8+(n>>1);
        !          1944:   nbtest = 0; karma = k_amoeba;
        !          1945:   deg = Fp[np];
        !          1946:   for (p = 0, pp = primepointer = diffptr;
        !          1947:        (plift == 0
        !          1948:        || (nbtest < nbmax && (nbtest <=8 || order < (n>>1)))
        !          1949:        || (n == 24 && O[6] == 0 && O[4] == 0)
        !          1950:         || ((group&ga_non_wss) && order == Fp[np]))
        !          1951:          && (nbtest < 3 * nbmax || !(group&ga_non_wss)) ;)
        !          1952:   {
        !          1953:     ulong   av;
        !          1954:     long    prime_incr;
        !          1955:     GEN     ip,FS,p1;
        !          1956:     long o,norm_o=1;
        !          1957:     prime_incr = *primepointer++;
        !          1958:     if (!prime_incr)
        !          1959:       err(primer1);
        !          1960:     p += prime_incr;
        !          1961:     /*discard small primes*/
        !          1962:     if (p <= (n << 1))
        !          1963:       continue;
        !          1964:     ip=stoi(p);
        !          1965:     if (!FpX_is_squarefree(T,ip))
        !          1966:       continue;
        !          1967:     nbtest++;
        !          1968:     av=avma;
        !          1969:     FS=(GEN)simplefactmod(T,ip)[1];
        !          1970:     p1=(GEN)FS[1];
        !          1971:     for(i=2;i<lg(FS);i++)
        !          1972:       if (cmpii(p1,(GEN)FS[i]))
        !          1973:        break;
        !          1974:     if (i<lg(FS))
        !          1975:     {
        !          1976:       avma = ltop;
        !          1977:       if (DEBUGLEVEL >= 2)
        !          1978:        fprintferr("GaloisAnalysis:non Galois for p=%ld\n", p);
        !          1979:       ga->p = p;
        !          1980:       ga->deg = 0;
        !          1981:       return;          /* Not a Galois polynomial */
        !          1982:     }
        !          1983:     o=n/(lg(FS)-1);
        !          1984:     avma=av;
        !          1985:     if (!O[o])
        !          1986:       O[o]=p;
        !          1987:     if (o % deg == 0)
        !          1988:     {
        !          1989:       /*We try to find a power of the Frobenius which generate
        !          1990:        a normal subgroup just by looking at the order.*/
        !          1991:       if (o * Fp[1] >= n)
        !          1992:        /*Subgroup of smallest index are normal*/
        !          1993:        norm_o = o;
        !          1994:       else
        !          1995:       {
        !          1996:        norm_o = 1;
        !          1997:        for (i = np; i > 0; i--)
        !          1998:        {
        !          1999:          if (o % Fpe[i] == 0)
        !          2000:            norm_o *= Fpe[i];
        !          2001:          else
        !          2002:            break;
        !          2003:        }
        !          2004:       }
        !          2005:       if (norm_o != 1)
        !          2006:       {
        !          2007:        if (!(group&ga_all_normal) || o > order ||
        !          2008:            (o == order && (plift == 0 || norm_o > deg
        !          2009:                            || (norm_o == deg && cgcd(p-1,karma_type)>karma ))))
        !          2010:        {
        !          2011:          deg = norm_o;
        !          2012:          order = o;
        !          2013:          plift = p;
        !          2014:          karma=cgcd(p-1,karma_type);
        !          2015:          pp = primepointer;
        !          2016:          group |= ga_all_normal;
        !          2017:        }
        !          2018:       }
        !          2019:       else if (!(group&ga_all_normal) && (plift == 0 || o > order
        !          2020:            || ( o == order && cgcd(p-1,karma_type)>karma )))
        !          2021:       {
        !          2022:        order = o;
        !          2023:        plift = p;
        !          2024:        karma=cgcd(p-1,karma_type);
        !          2025:        pp = primepointer;
        !          2026:       }
        !          2027:     }
        !          2028:     if (DEBUGLEVEL >= 5)
        !          2029:       fprintferr("GaloisAnalysis:Nbtest=%ld,p=%ld,o=%ld,n_o=%d,best p=%ld,ord=%ld,k=%ld\n",
        !          2030:                 nbtest, p, o, norm_o, plift, order,karma);
        !          2031:   }
        !          2032:   /* This is to avoid looping on non-wss group.
        !          2033:      To be checked for large groups.  */
        !          2034:   /*Would it be better to disable this check if we are in a good case ?
        !          2035:    * (ga_all_normal and !(ga_ext_2) (e.g. 60)) ?*/
        !          2036:   if (plift == 0 || ((group&ga_non_wss) && order == Fp[np]))
        !          2037:   {
        !          2038:     deg = 0;
        !          2039:     err(warner, "Galois group almost certainly not weakly super solvable");
        !          2040:   }
        !          2041:   /*linf=(n*(n-1))>>2;*/
        !          2042:   linf=n;
        !          2043:   if (calcul_l && O[1]<=linf)
        !          2044:   {
        !          2045:     ulong   av;
        !          2046:     long    prime_incr;
        !          2047:     long    l=0;
        !          2048:     /*we need a totally splited prime l*/
        !          2049:     av = avma;
        !          2050:     while (l == 0)
        !          2051:     {
        !          2052:       long nb;
        !          2053:       prime_incr = *primepointer++;
        !          2054:       if (!prime_incr)
        !          2055:        err(primer1);
        !          2056:       p += prime_incr;
        !          2057:       if (p<=linf) continue;
        !          2058:       nb=FpX_nbroots(T,stoi(p));
        !          2059:       if (nb == n)
        !          2060:        l = p;
        !          2061:       else if (nb && FpX_is_squarefree(T,stoi(p)))
        !          2062:       {
        !          2063:        avma = ltop;
        !          2064:        if (DEBUGLEVEL >= 2)
        !          2065:          fprintferr("GaloisAnalysis:non Galois for p=%ld\n", p);
        !          2066:        ga->p = p;
        !          2067:        ga->deg = 0;
        !          2068:        return;         /* Not a Galois polynomial */
        !          2069:       }
        !          2070:       avma = av;
        !          2071:     }
        !          2072:     O[1]=l;
        !          2073:   }
        !          2074:   ga->p = plift;
        !          2075:   ga->group = group;
        !          2076:   ga->deg = deg;
        !          2077:   ga->ord = order;
        !          2078:   ga->l = O[1];
        !          2079:   ga->primepointer = pp;
        !          2080:   ga->ppp = Fp[1];
        !          2081:   ga->p4 = O[4];
        !          2082:   if (DEBUGLEVEL >= 4)
        !          2083:     fprintferr("GaloisAnalysis:p=%ld l=%ld group=%ld deg=%ld ord=%ld\n",
        !          2084:               plift, O[1], group, deg, order);
        !          2085:   if (DEBUGLEVEL >= 1)
        !          2086:     msgtimer("galoisanalysis()");
        !          2087:   avma = ltop;
        !          2088: }
        !          2089:
        !          2090: /* Groupe A4 */
        !          2091: GEN
        !          2092: a4galoisgen(GEN T, struct galois_test *td)
        !          2093: {
        !          2094:   ulong   ltop = avma, av, av2;
        !          2095:   long    i, j, k;
        !          2096:   long    n;
        !          2097:   long    N, hop = 0;
        !          2098:   long  **O;
        !          2099:   GEN    *ar, **mt;            /* tired of casting */
        !          2100:   GEN     t, u;
        !          2101:   GEN     res, orb, ry;
        !          2102:   GEN     pft, pfu, pfv;
        !          2103:   n = degpol(T);
        !          2104:   res = cgetg(3, t_VEC);
        !          2105:   ry = cgetg(4, t_VEC);
        !          2106:   res[1] = (long) ry;
        !          2107:   pft = cgetg(n + 1, t_VECSMALL);
        !          2108:   pfu = cgetg(n + 1, t_VECSMALL);
        !          2109:   pfv = cgetg(n + 1, t_VECSMALL);
        !          2110:   ry[1] = (long) pft;
        !          2111:   ry[2] = (long) pfu;
        !          2112:   ry[3] = (long) pfv;
        !          2113:   ry = cgetg(4, t_VECSMALL);
        !          2114:   ry[1] = 2;
        !          2115:   ry[2] = 2;
        !          2116:   ry[3] = 3;
        !          2117:   res[2] = (long) ry;
        !          2118:   av = avma;
        !          2119:   ar = (GEN *) alloue_ardoise(n, 1 + lg(td->ladic));
        !          2120:   mt = (GEN **) td->PV[td->ordre[n]];
        !          2121:   t = cgetg(n + 1, t_VECSMALL) + 1;    /* Sorry for this hack */
        !          2122:   u = cgetg(n + 1, t_VECSMALL) + 1;    /* too lazy to correct */
        !          2123:   av2 = avma;
        !          2124:   N = itos(gdiv(mpfact(n), mpfact(n >> 1))) >> (n >> 1);
        !          2125:   if (DEBUGLEVEL >= 4)
        !          2126:     fprintferr("A4GaloisConj:I will test %ld permutations\n", N);
        !          2127:   avma = av2;
        !          2128:   for (i = 0; i < n; i++)
        !          2129:     t[i] = i + 1;
        !          2130:   for (i = 0; i < N; i++)
        !          2131:   {
        !          2132:     GEN     g;
        !          2133:     int     a, x, y;
        !          2134:     if (i == 0)
        !          2135:     {
        !          2136:       gaffect(gzero, ar[(n - 2) >> 1]);
        !          2137:       for (k = n - 2; k > 2; k -= 2)
        !          2138:        addiiz(ar[k >> 1], addii(mt[k + 1][k + 2], mt[k + 2][k + 1]),
        !          2139:              ar[(k >> 1) - 1]);
        !          2140:     }
        !          2141:     else
        !          2142:     {
        !          2143:       x = i;
        !          2144:       y = 1;
        !          2145:       do
        !          2146:       {
        !          2147:        y += 2;
        !          2148:        a = x%y;
        !          2149:        x = x/y;
        !          2150:       }
        !          2151:       while (!a);
        !          2152:       switch (y)
        !          2153:       {
        !          2154:       case 3:
        !          2155:        x = t[2];
        !          2156:        if (a == 1)
        !          2157:        {
        !          2158:          t[2] = t[1];
        !          2159:          t[1] = x;
        !          2160:        }
        !          2161:        else
        !          2162:        {
        !          2163:          t[2] = t[0];
        !          2164:          t[0] = x;
        !          2165:        }
        !          2166:        break;
        !          2167:       case 5:
        !          2168:        x = t[0];
        !          2169:        t[0] = t[2];
        !          2170:        t[2] = t[1];
        !          2171:        t[1] = x;
        !          2172:        x = t[4];
        !          2173:        t[4] = t[4 - a];
        !          2174:        t[4 - a] = x;
        !          2175:        addiiz(ar[2], addii(mt[t[4]][t[5]], mt[t[5]][t[4]]), ar[1]);
        !          2176:        break;
        !          2177:       case 7:
        !          2178:        x = t[0];
        !          2179:        t[0] = t[4];
        !          2180:        t[4] = t[3];
        !          2181:        t[3] = t[1];
        !          2182:        t[1] = t[2];
        !          2183:        t[2] = x;
        !          2184:        x = t[6];
        !          2185:        t[6] = t[6 - a];
        !          2186:        t[6 - a] = x;
        !          2187:        addiiz(ar[3], addii(mt[t[6]][t[7]], mt[t[7]][t[6]]), ar[2]);
        !          2188:        addiiz(ar[2], addii(mt[t[4]][t[5]], mt[t[5]][t[4]]), ar[1]);
        !          2189:        break;
        !          2190:       case 9:
        !          2191:        x = t[0];
        !          2192:        t[0] = t[6];
        !          2193:        t[6] = t[5];
        !          2194:        t[5] = t[3];
        !          2195:        t[3] = x;
        !          2196:        x = t[4];
        !          2197:        t[4] = t[1];
        !          2198:        t[1] = x;
        !          2199:        x = t[8];
        !          2200:        t[8] = t[8 - a];
        !          2201:        t[8 - a] = x;
        !          2202:        addiiz(ar[4], addii(mt[t[8]][t[9]], mt[t[9]][t[8]]), ar[3]);
        !          2203:        addiiz(ar[3], addii(mt[t[6]][t[7]], mt[t[7]][t[6]]), ar[2]);
        !          2204:        addiiz(ar[2], addii(mt[t[4]][t[5]], mt[t[5]][t[4]]), ar[1]);
        !          2205:        break;
        !          2206:       default:
        !          2207:        y--;
        !          2208:        x = t[0];
        !          2209:        t[0] = t[2];
        !          2210:        t[2] = t[1];
        !          2211:        t[1] = x;
        !          2212:        for (k = 4; k < y; k += 2)
        !          2213:        {
        !          2214:          int     j;
        !          2215:          x = t[k];
        !          2216:          for (j = k; j > 0; j--)
        !          2217:            t[j] = t[j - 1];
        !          2218:          t[0] = x;
        !          2219:        }
        !          2220:        x = t[y];
        !          2221:        t[y] = t[y - a];
        !          2222:        t[y - a] = x;
        !          2223:        for (k = y; k > 2; k -= 2)
        !          2224:          addiiz(ar[k >> 1],
        !          2225:                addii(mt[t[k]][t[k + 1]], mt[t[k + 1]][t[k]]),
        !          2226:                ar[(k >> 1) - 1]);
        !          2227:       }
        !          2228:     }
        !          2229:     g = addii(ar[1], addii(addii(mt[t[0]][t[1]], mt[t[1]][t[0]]),
        !          2230:                         addii(mt[t[2]][t[3]], mt[t[3]][t[2]])));
        !          2231:     if (padicisint(g, td))
        !          2232:     {
        !          2233:       for (k = 0; k < n; k += 2)
        !          2234:       {
        !          2235:        pft[t[k]] = t[k + 1];
        !          2236:        pft[t[k + 1]] = t[k];
        !          2237:       }
        !          2238:       if (verifietest(pft, td))
        !          2239:        break;
        !          2240:       else
        !          2241:        hop++;
        !          2242:     }
        !          2243:     avma = av2;
        !          2244:   }
        !          2245:   if (i == N)
        !          2246:   {
        !          2247:     avma = ltop;
        !          2248:     if (DEBUGLEVEL >= 1 && hop)
        !          2249:       fprintferr("A4GaloisConj: %ld hop sur %ld iterations\n", hop, N);
        !          2250:     return gzero;
        !          2251:   }
        !          2252:   if (DEBUGLEVEL >= 1 && hop)
        !          2253:     fprintferr("A4GaloisConj: %ld hop sur %ld iterations\n", hop, N);
        !          2254:   N = itos(gdiv(mpfact(n >> 1), mpfact(n >> 2))) >> 1;
        !          2255:   avma = av2;
        !          2256:   if (DEBUGLEVEL >= 4)
        !          2257:     fprintferr("A4GaloisConj:sigma=%Z \n", pft);
        !          2258:   for (i = 0; i < N; i++)
        !          2259:   {
        !          2260:     GEN     g;
        !          2261:     int     a, x, y;
        !          2262:     if (i == 0)
        !          2263:     {
        !          2264:       for (k = 0; k < n; k += 4)
        !          2265:       {
        !          2266:        u[k + 3] = t[k + 3];
        !          2267:        u[k + 2] = t[k + 1];
        !          2268:        u[k + 1] = t[k + 2];
        !          2269:        u[k] = t[k];
        !          2270:       }
        !          2271:     }
        !          2272:     else
        !          2273:     {
        !          2274:       x = i;
        !          2275:       y = -2;
        !          2276:       do
        !          2277:       {
        !          2278:        y += 4;
        !          2279:        a = x%y;
        !          2280:        x = x/y;
        !          2281:       }
        !          2282:       while (!a);
        !          2283:       x = u[2];
        !          2284:       u[2] = u[0];
        !          2285:       u[0] = x;
        !          2286:       switch (y)
        !          2287:       {
        !          2288:       case 2:
        !          2289:        break;
        !          2290:       case 6:
        !          2291:        x = u[4];
        !          2292:        u[4] = u[6];
        !          2293:        u[6] = x;
        !          2294:        if (!(a & 1))
        !          2295:        {
        !          2296:          a = 4 - (a >> 1);
        !          2297:          x = u[6];
        !          2298:          u[6] = u[a];
        !          2299:          u[a] = x;
        !          2300:          x = u[4];
        !          2301:          u[4] = u[a - 2];
        !          2302:          u[a - 2] = x;
        !          2303:        }
        !          2304:        break;
        !          2305:       case 10:
        !          2306:        x = u[6];
        !          2307:        u[6] = u[3];
        !          2308:        u[3] = u[2];
        !          2309:        u[2] = u[4];
        !          2310:        u[4] = u[1];
        !          2311:        u[1] = u[0];
        !          2312:        u[0] = x;
        !          2313:        if (a >= 3)
        !          2314:          a += 2;
        !          2315:        a = 8 - a;
        !          2316:        x = u[10];
        !          2317:        u[10] = u[a];
        !          2318:        u[a] = x;
        !          2319:        x = u[8];
        !          2320:        u[8] = u[a - 2];
        !          2321:        u[a - 2] = x;
        !          2322:        break;
        !          2323:       }
        !          2324:     }
        !          2325:     g = gzero;
        !          2326:     for (k = 0; k < n; k += 2)
        !          2327:       g = addii(g, addii(mt[u[k]][u[k + 1]], mt[u[k + 1]][u[k]]));
        !          2328:     if (padicisint(g, td))
        !          2329:     {
        !          2330:       for (k = 0; k < n; k += 2)
        !          2331:       {
        !          2332:        pfu[u[k]] = u[k + 1];
        !          2333:        pfu[u[k + 1]] = u[k];
        !          2334:       }
        !          2335:       if (verifietest(pfu, td))
        !          2336:        break;
        !          2337:       else
        !          2338:        hop++;
        !          2339:     }
        !          2340:     avma = av2;
        !          2341:   }
        !          2342:   if (i == N)
        !          2343:   {
        !          2344:     avma = ltop;
        !          2345:     return gzero;
        !          2346:   }
        !          2347:   if (DEBUGLEVEL >= 1 && hop)
        !          2348:     fprintferr("A4GaloisConj: %ld hop sur %ld iterations\n", hop, N);
        !          2349:   if (DEBUGLEVEL >= 4)
        !          2350:     fprintferr("A4GaloisConj:tau=%Z \n", pfu);
        !          2351:   avma = av2;
        !          2352:   orb = cgetg(3, t_VEC);
        !          2353:   orb[1] = (long) pft;
        !          2354:   orb[2] = (long) pfu;
        !          2355:   if (DEBUGLEVEL >= 4)
        !          2356:     fprintferr("A4GaloisConj:orb=%Z \n", orb);
        !          2357:   O = (long**)permorbite(orb);
        !          2358:   if (DEBUGLEVEL >= 4)
        !          2359:     fprintferr("A4GaloisConj:O=%Z \n", O);
        !          2360:   av2 = avma;
        !          2361:   for (j = 0; j < 2; j++)
        !          2362:   {
        !          2363:     pfv[O[1][1]] = O[2][1];
        !          2364:     pfv[O[1][2]] = O[2][3 + j];
        !          2365:     pfv[O[1][3]] = O[2][4 - (j << 1)];
        !          2366:     pfv[O[1][4]] = O[2][2 + j];
        !          2367:     for (i = 0; i < 4; i++)
        !          2368:     {
        !          2369:       long    x;
        !          2370:       GEN     g;
        !          2371:       switch (i)
        !          2372:       {
        !          2373:       case 0:
        !          2374:        break;
        !          2375:       case 1:
        !          2376:        x = O[3][1];
        !          2377:        O[3][1] = O[3][2];
        !          2378:        O[3][2] = x;
        !          2379:        x = O[3][3];
        !          2380:        O[3][3] = O[3][4];
        !          2381:        O[3][4] = x;
        !          2382:        break;
        !          2383:       case 2:
        !          2384:        x = O[3][1];
        !          2385:        O[3][1] = O[3][4];
        !          2386:        O[3][4] = x;
        !          2387:        x = O[3][2];
        !          2388:        O[3][2] = O[3][3];
        !          2389:        O[3][3] = x;
        !          2390:        break;
        !          2391:       case 3:
        !          2392:        x = O[3][1];
        !          2393:        O[3][1] = O[3][2];
        !          2394:        O[3][2] = x;
        !          2395:        x = O[3][3];
        !          2396:        O[3][3] = O[3][4];
        !          2397:        O[3][4] = x;
        !          2398:       }
        !          2399:       pfv[O[2][1]] = O[3][1];
        !          2400:       pfv[O[2][3 + j]] = O[3][4 - j];
        !          2401:       pfv[O[2][4 - (j << 1)]] = O[3][2 + (j << 1)];
        !          2402:       pfv[O[2][2 + j]] = O[3][3 - j];
        !          2403:       pfv[O[3][1]] = O[1][1];
        !          2404:       pfv[O[3][4 - j]] = O[1][2];
        !          2405:       pfv[O[3][2 + (j << 1)]] = O[1][3];
        !          2406:       pfv[O[3][3 - j]] = O[1][4];
        !          2407:       g = gzero;
        !          2408:       for (k = 1; k <= n; k++)
        !          2409:        g = addii(g, mt[k][pfv[k]]);
        !          2410:       if (padicisint(g, td) && verifietest(pfv, td))
        !          2411:       {
        !          2412:        avma = av;
        !          2413:        if (DEBUGLEVEL >= 1)
        !          2414:          fprintferr("A4GaloisConj:%ld hop sur %d iterations max\n",
        !          2415:                     hop, 10395 + 68);
        !          2416:        return res;
        !          2417:       }
        !          2418:       else
        !          2419:        hop++;
        !          2420:       avma = av2;
        !          2421:     }
        !          2422:   }
        !          2423:   /* Echec? */
        !          2424:   avma = ltop;
        !          2425:   return gzero;
        !          2426: }
        !          2427:
        !          2428: /* Groupe S4 */
        !          2429: static void
        !          2430: s4makelift(GEN u, struct galois_lift *gl, GEN liftpow)
        !          2431: {
        !          2432:   int     i;
        !          2433:   liftpow[1] = (long) automorphismlift(u, gl, NULL);
        !          2434:   for (i = 2; i < lg(liftpow); i++)
        !          2435:     liftpow[i] = (long) FpXQ_mul((GEN) liftpow[i - 1], (GEN) liftpow[1],gl->TQ,gl->Q);
        !          2436: }
        !          2437: static long
        !          2438: s4test(GEN u, GEN liftpow, struct galois_lift *gl, GEN phi)
        !          2439: {
        !          2440:   ulong ltop=avma;
        !          2441:   GEN     res;
        !          2442:   int     bl,i,d = lgef(u)-2;
        !          2443:   if (DEBUGLEVEL >= 6)
        !          2444:     timer2();
        !          2445:   if ( !d ) return 0;
        !          2446:   res=(GEN)u[2];
        !          2447:   for (i = 1; i < d; i++)
        !          2448:   {
        !          2449:     if (lgef(liftpow[i])>2)
        !          2450:       res=addii(res,mulii(gmael(liftpow,i,2), (GEN) u[i + 2]));
        !          2451:   }
        !          2452:   res=modii(mulii(res,gl->den),gl->Q);
        !          2453:   if (cmpii(res,gl->gb->bornesol)>0
        !          2454:       && cmpii(res,subii(gl->Q,gl->gb->bornesol))<0)
        !          2455:   {
        !          2456:     avma=ltop;
        !          2457:     return 0;
        !          2458:   }
        !          2459:   res = (GEN) scalarpol((GEN)u[2],varn(u));
        !          2460:   for (i = 1; i < d ; i++)
        !          2461:   {
        !          2462:     GEN z;
        !          2463:     z = FpX_Fp_mul((GEN) liftpow[i], (GEN) u[i + 2],NULL);
        !          2464:     res = FpX_add(res,z ,gl->Q);
        !          2465:   }
        !          2466:   res = FpX_center(FpX_Fp_mul(res,gl->den,gl->Q), gl->Q);
        !          2467:   if (DEBUGLEVEL >= 6)
        !          2468:     msgtimer("s4test()");
        !          2469:   bl = poltopermtest(res, gl, phi);
        !          2470:   avma=ltop;
        !          2471:   return bl;
        !          2472: }
        !          2473: static GEN
        !          2474: s4releveauto(GEN misom,GEN Tmod,GEN Tp,GEN p,long a1,long a2,long a3,long a4,long a5,long a6)
        !          2475: {
        !          2476:   ulong ltop=avma;
        !          2477:   GEN u1,u2,u3,u4,u5;
        !          2478:   GEN pu1,pu2,pu3,pu4;
        !          2479:   pu1=FpX_mul( (GEN) Tmod[a2], (GEN) Tmod[a1],p);
        !          2480:   u1 = FpX_chinese_coprime(gmael(misom,a1,a2),gmael(misom,a2,a1),
        !          2481:                         (GEN) Tmod[a2], (GEN) Tmod[a1],pu1,p);
        !          2482:   pu2=FpX_mul( (GEN) Tmod[a4], (GEN) Tmod[a3],p);
        !          2483:   u2 = FpX_chinese_coprime(gmael(misom,a3,a4),gmael(misom,a4,a3),
        !          2484:                         (GEN) Tmod[a4], (GEN) Tmod[a3],pu2,p);
        !          2485:   pu3=FpX_mul( (GEN) Tmod[a6], (GEN) Tmod[a5],p);
        !          2486:   u3 = FpX_chinese_coprime(gmael(misom,a5,a6),gmael(misom,a6,a5),
        !          2487:                         (GEN) Tmod[a6], (GEN) Tmod[a5],pu3,p);
        !          2488:   pu4=FpX_mul(pu1,pu2,p);
        !          2489:   u4 = FpX_chinese_coprime(u1,u2,pu1,pu2,pu4,p);
        !          2490:   u5 = FpX_chinese_coprime(u4,u3,pu4,pu3,Tp,p);
        !          2491:   return gerepileupto(ltop,u5);
        !          2492: }
        !          2493: GEN
        !          2494: s4galoisgen(struct galois_lift *gl)
        !          2495: {
        !          2496:   struct galois_testlift gt;
        !          2497:   ulong   ltop = avma, av, ltop2;
        !          2498:   GEN     Tmod, isom, isominv, misom;
        !          2499:   int     i, j;
        !          2500:   GEN     sg;
        !          2501:   GEN     sigma, tau, phi;
        !          2502:   GEN     res, ry;
        !          2503:   GEN     pj;
        !          2504:   GEN     p,Q,TQ,Tp;
        !          2505:   GEN     bezoutcoeff, pauto, liftpow, aut;
        !          2506:
        !          2507:   p = gl->p;
        !          2508:   Q = gl->Q;
        !          2509:   res = cgetg(3, t_VEC);
        !          2510:   ry  = cgetg(5, t_VEC);
        !          2511:   res[1] = (long) ry;
        !          2512:   for (i = 1; i < lg(ry); i++)
        !          2513:     ry[i] = lgetg(lg(gl->L), t_VECSMALL);
        !          2514:   ry = cgetg(5, t_VECSMALL);
        !          2515:   res[2] = (long) ry;
        !          2516:   ry[1] = 2;
        !          2517:   ry[2] = 2;
        !          2518:   ry[3] = 3;
        !          2519:   ry[4] = 2;
        !          2520:   ltop2 = avma;
        !          2521:   sg = cgetg(7, t_VECSMALL);
        !          2522:   pj = cgetg(7, t_VECSMALL);
        !          2523:   sigma = cgetg(lg(gl->L), t_VECSMALL);
        !          2524:   tau = cgetg(lg(gl->L), t_VECSMALL);
        !          2525:   phi = cgetg(lg(gl->L), t_VECSMALL);
        !          2526:   for (i = 1; i < lg(sg); i++)
        !          2527:     sg[i] = i;
        !          2528:   Tp = FpX_red(gl->T,p);
        !          2529:   TQ = gl->TQ;
        !          2530:   Tmod = lift((GEN) factmod(gl->T, p)[1]);
        !          2531:   isom = cgetg(lg(Tmod), t_VEC);
        !          2532:   isominv = cgetg(lg(Tmod), t_VEC);
        !          2533:   misom = cgetg(lg(Tmod), t_MAT);
        !          2534:   aut=galoisdolift(gl, NULL);
        !          2535:   inittestlift(aut,Tmod, gl, &gt);
        !          2536:   bezoutcoeff = gt.bezoutcoeff;
        !          2537:   pauto = gt.pauto;
        !          2538:   for (i = 1; i < lg(pj); i++)
        !          2539:     pj[i] = 0;
        !          2540:   for (i = 1; i < lg(isom); i++)
        !          2541:   {
        !          2542:     misom[i] = lgetg(lg(Tmod), t_COL);
        !          2543:     isom[i] = (long) Fp_isom((GEN) Tmod[1], (GEN) Tmod[i], p);
        !          2544:     if (DEBUGLEVEL >= 6)
        !          2545:       fprintferr("S4GaloisConj:Computing isomorphisms %d:%Z\n", i,
        !          2546:                 (GEN) isom[i]);
        !          2547:     isominv[i] = (long) Fp_inv_isom((GEN) isom[i], (GEN) Tmod[i],p);
        !          2548:   }
        !          2549:   for (i = 1; i < lg(isom); i++)
        !          2550:     for (j = 1; j < lg(isom); j++)
        !          2551:       mael(misom,i,j) = (long) FpX_FpXQ_compo((GEN) isominv[i],(GEN) isom[j],
        !          2552:                                                (GEN) Tmod[j],p);
        !          2553:   liftpow = cgetg(24, t_VEC);
        !          2554:   av = avma;
        !          2555:   for (i = 0; i < 3; i++)
        !          2556:   {
        !          2557:     ulong   av2;
        !          2558:     GEN     u;
        !          2559:     int     j1, j2, j3;
        !          2560:     ulong   avm1, avm2;
        !          2561:     GEN     u1, u2, u3;
        !          2562:     if (i)
        !          2563:     {
        !          2564:       int     x;
        !          2565:       x = sg[3];
        !          2566:       if (i == 1)
        !          2567:       {
        !          2568:        sg[3] = sg[2];
        !          2569:        sg[2] = x;
        !          2570:       }
        !          2571:       else
        !          2572:       {
        !          2573:        sg[3] = sg[1];
        !          2574:        sg[1] = x;
        !          2575:       }
        !          2576:     }
        !          2577:     u=s4releveauto(misom,Tmod,Tp,p,sg[1],sg[2],sg[3],sg[4],sg[5],sg[6]);
        !          2578:     s4makelift(u, gl, liftpow);
        !          2579:     av2 = avma;
        !          2580:     for (j1 = 0; j1 < 4; j1++)
        !          2581:     {
        !          2582:       u1 = FpX_add(FpXQ_mul((GEN) bezoutcoeff[sg[5]],
        !          2583:                                 (GEN) pauto[1 + j1],TQ,Q),
        !          2584:                  FpXQ_mul((GEN) bezoutcoeff[sg[6]],
        !          2585:                                 (GEN) pauto[((-j1) & 3) + 1],TQ,Q),Q);
        !          2586:       avm1 = avma;
        !          2587:       for (j2 = 0; j2 < 4; j2++)
        !          2588:       {
        !          2589:        u2 = FpX_add(u1, FpXQ_mul((GEN) bezoutcoeff[sg[3]],
        !          2590:                                       (GEN) pauto[1 + j2],TQ,Q),NULL);
        !          2591:        u2 = FpX_add(u2, FpXQ_mul((GEN) bezoutcoeff[sg[4]], (GEN)
        !          2592:                                       pauto[((-j2) & 3) + 1],TQ,Q),Q);
        !          2593:        avm2 = avma;
        !          2594:        for (j3 = 0; j3 < 4; j3++)
        !          2595:        {
        !          2596:          u3 = FpX_add(u2, FpXQ_mul((GEN) bezoutcoeff[sg[1]],
        !          2597:                                         (GEN) pauto[1 + j3],TQ,Q),NULL);
        !          2598:          u3 = FpX_add(u3, FpXQ_mul((GEN) bezoutcoeff[sg[2]], (GEN)
        !          2599:                                         pauto[((-j3) & 3) + 1],TQ,Q),Q);
        !          2600:          if (DEBUGLEVEL >= 4)
        !          2601:            fprintferr("S4GaloisConj:Testing %d/3:%d/4:%d/4:%d/4:%Z\n",
        !          2602:                       i, j1,j2, j3, sg);
        !          2603:          if (s4test(u3, liftpow, gl, sigma))
        !          2604:          {
        !          2605:            pj[1] = j3;
        !          2606:            pj[2] = j2;
        !          2607:            pj[3] = j1;
        !          2608:            goto suites4;
        !          2609:          }
        !          2610:          avma = avm2;
        !          2611:        }
        !          2612:        avma = avm1;
        !          2613:       }
        !          2614:       avma = av2;
        !          2615:     }
        !          2616:     avma = av;
        !          2617:   }
        !          2618:   avma = ltop;
        !          2619:   return gzero;
        !          2620: suites4:
        !          2621:   if (DEBUGLEVEL >= 4)
        !          2622:     fprintferr("S4GaloisConj:sigma=%Z\n", sigma);
        !          2623:   if (DEBUGLEVEL >= 4)
        !          2624:     fprintferr("S4GaloisConj:pj=%Z\n", pj);
        !          2625:   avma = av;
        !          2626:   for (j = 1; j <= 3; j++)
        !          2627:   {
        !          2628:     ulong   av2;
        !          2629:     GEN     u;
        !          2630:     int     w, l;
        !          2631:     int     z;
        !          2632:     z = sg[1]; sg[1] = sg[3]; sg[3] = sg[5]; sg[5] = z;
        !          2633:     z = sg[2]; sg[2] = sg[4]; sg[4] = sg[6]; sg[6] = z;
        !          2634:     z = pj[1]; pj[1] = pj[2]; pj[2] = pj[3]; pj[3] = z;
        !          2635:     for (l = 0; l < 2; l++)
        !          2636:     {
        !          2637:       u=s4releveauto(misom,Tmod,Tp,p,sg[1],sg[3],sg[2],sg[4],sg[5],sg[6]);
        !          2638:       s4makelift(u, gl, liftpow);
        !          2639:       av2 = avma;
        !          2640:       for (w = 0; w < 4; w += 2)
        !          2641:       {
        !          2642:        GEN     uu;
        !          2643:        long    av3;
        !          2644:        pj[6] = (w + pj[3]) & 3;
        !          2645:        uu =FpX_add(FpXQ_mul((GEN) bezoutcoeff[sg[5]],
        !          2646:                          (GEN) pauto[(pj[6] & 3) + 1],TQ,Q),
        !          2647:                   FpXQ_mul((GEN) bezoutcoeff[sg[6]],
        !          2648:                          (GEN) pauto[((-pj[6]) & 3) + 1],TQ,Q),Q);
        !          2649:        av3 = avma;
        !          2650:        for (i = 0; i < 4; i++)
        !          2651:        {
        !          2652:          GEN     u;
        !          2653:          pj[4] = i;
        !          2654:          pj[5] = (i + pj[2] - pj[1]) & 3;
        !          2655:          if (DEBUGLEVEL >= 4)
        !          2656:            fprintferr("S4GaloisConj:Testing %d/3:%d/2:%d/2:%d/4:%Z:%Z\n",
        !          2657:                       j - 1, w >> 1, l, i, sg, pj);
        !          2658:          u = FpX_add(uu, FpXQ_mul((GEN) pauto[(pj[4] & 3) + 1],
        !          2659:                                (GEN) bezoutcoeff[sg[1]],TQ,Q),Q);
        !          2660:          u = FpX_add(u,         FpXQ_mul((GEN) pauto[((-pj[4]) & 3) + 1],
        !          2661:                                (GEN) bezoutcoeff[sg[3]],TQ,Q),Q);
        !          2662:          u = FpX_add(u,         FpXQ_mul((GEN) pauto[(pj[5] & 3) + 1],
        !          2663:                                (GEN) bezoutcoeff[sg[2]],TQ,Q),Q);
        !          2664:          u = FpX_add(u,         FpXQ_mul((GEN) pauto[((-pj[5]) & 3) + 1],
        !          2665:                                (GEN) bezoutcoeff[sg[4]],TQ,Q),Q);
        !          2666:          if (s4test(u, liftpow, gl, tau))
        !          2667:            goto suites4_2;
        !          2668:          avma = av3;
        !          2669:        }
        !          2670:        avma = av2;
        !          2671:       }
        !          2672:       z = sg[4];
        !          2673:       sg[4] = sg[3];
        !          2674:       sg[3] = z;
        !          2675:       pj[2] = (-pj[2]) & 3;
        !          2676:       avma = av;
        !          2677:     }
        !          2678:   }
        !          2679:   avma = ltop;
        !          2680:   return gzero;
        !          2681: suites4_2:
        !          2682:   avma = av;
        !          2683:   {
        !          2684:     int     abc, abcdef;
        !          2685:     GEN     u;
        !          2686:     ulong   av2;
        !          2687:     abc = (pj[1] + pj[2] + pj[3]) & 3;
        !          2688:     abcdef = (((abc + pj[4] + pj[5] - pj[6]) & 3) >> 1);
        !          2689:     u = s4releveauto(misom,Tmod,Tp,p,sg[1],sg[4],sg[2],sg[5],sg[3],sg[6]);
        !          2690:     s4makelift(u, gl, liftpow);
        !          2691:     av2 = avma;
        !          2692:     for (j = 0; j < 8; j++)
        !          2693:     {
        !          2694:       int     h, g, i;
        !          2695:       h = j & 3;
        !          2696:       g = abcdef + ((j & 4) >> 1);
        !          2697:       i = h + abc - g;
        !          2698:       u = FpXQ_mul((GEN) pauto[(g & 3) + 1],
        !          2699:                   (GEN) bezoutcoeff[sg[1]],TQ,Q);
        !          2700:       u = FpX_add(u, FpXQ_mul((GEN) pauto[((-g) & 3) + 1],
        !          2701:                              (GEN) bezoutcoeff[sg[4]],TQ,Q),NULL);
        !          2702:       u = FpX_add(u, FpXQ_mul((GEN) pauto[(h & 3) + 1],
        !          2703:                              (GEN) bezoutcoeff[sg[2]],TQ,Q),NULL);
        !          2704:       u = FpX_add(u, FpXQ_mul((GEN) pauto[((-h) & 3) + 1],
        !          2705:                              (GEN) bezoutcoeff[sg[5]],TQ,Q),NULL);
        !          2706:       u = FpX_add(u, FpXQ_mul((GEN) pauto[(i & 3) + 1],
        !          2707:                              (GEN) bezoutcoeff[sg[3]],TQ,Q),NULL);
        !          2708:       u = FpX_add(u, FpXQ_mul((GEN) pauto[((-i) & 3) + 1],
        !          2709:                              (GEN) bezoutcoeff[sg[6]],TQ,Q),Q);
        !          2710:       if (DEBUGLEVEL >= 4)
        !          2711:        fprintferr("S4GaloisConj:Testing %d/8 %d:%d:%d\n",
        !          2712:                   j, g & 3, h & 3, i & 3);
        !          2713:       if (s4test(u, liftpow, gl, phi))
        !          2714:        break;
        !          2715:       avma = av2;
        !          2716:     }
        !          2717:   }
        !          2718:   if (j == 8)
        !          2719:   {
        !          2720:     avma = ltop;
        !          2721:     return gzero;
        !          2722:   }
        !          2723:   for (i = 1; i < lg(gl->L); i++)
        !          2724:   {
        !          2725:     ((GEN **) res)[1][1][i] = sigma[tau[i]];
        !          2726:     ((GEN **) res)[1][2][i] = phi[sigma[tau[phi[i]]]];
        !          2727:     ((GEN **) res)[1][3][i] = phi[sigma[i]];
        !          2728:     ((GEN **) res)[1][4][i] = sigma[i];
        !          2729:   }
        !          2730:   avma = ltop2;
        !          2731:   return res;
        !          2732: }
        !          2733: struct galois_frobenius
        !          2734: {
        !          2735:   long p;
        !          2736:   long fp;
        !          2737:   long deg;
        !          2738:   GEN Tmod;
        !          2739:   GEN psi;
        !          2740: };
        !          2741:
        !          2742: /*Warning : the output of this function is not gerepileupto
        !          2743:  * compatible...*/
        !          2744: static GEN
        !          2745: galoisfindgroups(GEN lo, GEN sg, long f)
        !          2746: {
        !          2747:   ulong ltop=avma;
        !          2748:   GEN V,W;
        !          2749:   long i,j,k;
        !          2750:   V=cgetg(lg(lo),t_VEC);
        !          2751:   for(j=1,i=1;i<lg(lo);i++)
        !          2752:   {
        !          2753:     ulong av=avma;
        !          2754:     GEN U;
        !          2755:     W=cgetg(lg(lo[i]),t_VECSMALL);
        !          2756:     for(k=1;k<lg(lo[i]);k++)
        !          2757:       W[k]=mael(lo,i,k)%f;
        !          2758:     sortvecsmall(W);
        !          2759:     U=uniqvecsmall(W);
        !          2760:     if (gegal(U, sg))
        !          2761:     {
        !          2762:       cgiv(U);
        !          2763:       V[j++]=lo[i];
        !          2764:     }
        !          2765:     else
        !          2766:       avma=av;
        !          2767:   }
        !          2768:   setlg(V,j);
        !          2769:   /*warning components of V point to W*/
        !          2770:   return gerepileupto(ltop,V);
        !          2771: }
        !          2772:
        !          2773: static long
        !          2774: galoisfrobeniustest(GEN aut, struct galois_lift *gl, GEN frob)
        !          2775: {
        !          2776:   ulong ltop=avma;
        !          2777:   GEN tlift = FpX_center(FpX_Fp_mul(aut,gl->den,gl->Q), gl->Q);
        !          2778:   long res=poltopermtest(tlift, gl, frob);
        !          2779:   avma=ltop;
        !          2780:   return res;
        !          2781: }
        !          2782:
        !          2783: static GEN
        !          2784: galoismakepsiab(long g)
        !          2785: {
        !          2786:   GEN psi=cgetg(g+1,t_VECSMALL);
        !          2787:   long i;
        !          2788:   for (i = 1; i <= g; i++)
        !          2789:     psi[i] = 1;
        !          2790:   return psi;
        !          2791: }
        !          2792:
        !          2793: static GEN
        !          2794: galoismakepsi(long g, GEN sg, GEN pf)
        !          2795: {
        !          2796:   GEN psi=cgetg(g+1,t_VECSMALL);
        !          2797:   long i;
        !          2798:   for (i = 1; i < g; i++)
        !          2799:     psi[i] = sg[pf[i]];
        !          2800:   psi[g]=sg[1];
        !          2801:   return psi;
        !          2802: }
        !          2803:
        !          2804: static GEN
        !          2805: galoisfrobeniuslift(GEN T, GEN den, GEN L,  GEN Lden, long gmask,
        !          2806:     struct galois_frobenius *gf,  struct galois_borne *gb)
        !          2807: {
        !          2808:   ulong ltop=avma,av2;
        !          2809:   struct galois_testlift gt;
        !          2810:   struct galois_lift gl;
        !          2811:   GEN res;
        !          2812:   long i,j,k;
        !          2813:   long n=lg(L)-1, deg=1, g=lg(gf->Tmod)-1;
        !          2814:   GEN F,Fp,Fe;
        !          2815:   GEN ip=stoi(gf->p), aut, frob;
        !          2816:   if (DEBUGLEVEL >= 4)
        !          2817:     fprintferr("GaloisConj:p=%ld deg=%ld fp=%ld\n", gf->p, deg, gf->fp);
        !          2818:   res = cgetg(lg(L), t_VECSMALL);
        !          2819:   gf->psi = galoismakepsiab(g);
        !          2820:   av2=avma;
        !          2821:   initlift(T, den, ip, L, Lden, gb, &gl);
        !          2822:   aut = galoisdolift(&gl, res);
        !          2823:   if (!aut || galoisfrobeniustest(aut,&gl,res))
        !          2824:   {
        !          2825:     avma=av2;
        !          2826:     gf->deg = gf->fp;
        !          2827:     return res;
        !          2828:   }
        !          2829:   inittestlift(aut,gf->Tmod, &gl, &gt);
        !          2830:   gt.C=cgetg(gf->fp+1,t_VEC);
        !          2831:   for (i = 1; i <= gf->fp; i++)
        !          2832:   {
        !          2833:     gt.C[i]=lgetg(gt.g+1,t_VECSMALL);
        !          2834:     for(j = 1; j <= gt.g; j++)
        !          2835:       mael(gt.C,i,j)=0;
        !          2836:   }
        !          2837:   gt.Cd=gcopy(gt.C);
        !          2838:
        !          2839:   F=factor(stoi(gf->fp));
        !          2840:   Fp=gtovecsmall((GEN)F[1]);
        !          2841:   Fe=gtovecsmall((GEN)F[2]);
        !          2842:   frob = cgetg(lg(L), t_VECSMALL);
        !          2843:   for(k=lg(Fp)-1;k>=1;k--)
        !          2844:   {
        !          2845:     long btop=avma;
        !          2846:     GEN psi=NULL,fres=NULL,sg;
        !          2847:     long el=gf->fp, dg=1, dgf=1;
        !          2848:     long e,pr;
        !          2849:     sg=permidentity(1);
        !          2850:     for(e=1;e<=Fe[k];e++)
        !          2851:     {
        !          2852:       long l;
        !          2853:       GEN lo;
        !          2854:       GEN pf;
        !          2855:       dg *= Fp[k]; el /= Fp[k];
        !          2856:       if ( DEBUGLEVEL>=4 )
        !          2857:        fprintferr("Trying degre %d.\n",dg);
        !          2858:       if (galoisfrobeniustest((GEN)gt.pauto[el+1],&gl,frob))
        !          2859:       {
        !          2860:        dgf = dg;
        !          2861:        psi = galoismakepsiab(g);
        !          2862:        fres= gcopy(frob);
        !          2863:        continue;
        !          2864:       }
        !          2865:       disable_dbg(0);
        !          2866:       lo = listsousgroupes(dg, n / gf->fp);
        !          2867:       disable_dbg(-1);
        !          2868:       if (e!=1)
        !          2869:        lo = galoisfindgroups(lo, sg, dgf);
        !          2870:       if (DEBUGLEVEL >= 4)
        !          2871:        fprintferr("Galoisconj:Subgroups list:%Z\n", lo);
        !          2872:       for (l = 1; l < lg(lo); l++)
        !          2873:        if ( lg(lo[l])>2 &&
        !          2874:            frobeniusliftall((GEN)lo[l], el, &pf, &gl, &gt, frob))
        !          2875:        {
        !          2876:          sg  = gcopy((GEN)lo[l]);
        !          2877:          psi = galoismakepsi(g,sg,pf);
        !          2878:          dgf = dg;
        !          2879:          fres=gcopy(frob);
        !          2880:          break;
        !          2881:        }
        !          2882:       if ( l == lg(lo) )
        !          2883:        break;
        !          2884:     }
        !          2885:     if (dgf==1) { avma=btop; continue; }
        !          2886:     pr=deg*dgf;
        !          2887:     if (deg==1)
        !          2888:     {
        !          2889:       for(i=1;i<lg(res);i++) res[i]=fres[i];
        !          2890:       for(i=1;i<lg(psi);i++) gf->psi[i]=psi[i];
        !          2891:     }
        !          2892:     else
        !          2893:     {
        !          2894:       GEN cp=permapply(res,fres);
        !          2895:       for(i=1;i<lg(res);i++) res[i]=cp[i];
        !          2896:       for(i=1;i<lg(psi);i++) gf->psi[i]=(dgf*gf->psi[i]+deg*psi[i])%pr;
        !          2897:     }
        !          2898:     deg=pr;
        !          2899:     avma=btop;
        !          2900:   }
        !          2901:   for (i = 1; i <= gf->fp; i++)
        !          2902:     for (j = 1; j <= gt.g; j++)
        !          2903:       if (mael(gt.C,i,j))
        !          2904:        gunclone(gmael(gt.C,i,j));
        !          2905:   if (DEBUGLEVEL>=4 && res)
        !          2906:     fprintferr("Best lift: %d\n",deg);
        !          2907:   if (deg==1)
        !          2908:   {
        !          2909:     avma=ltop;
        !          2910:     return NULL;
        !          2911:   }
        !          2912:   else
        !          2913:   {
        !          2914:     /*We need to normalise result so that psi[g]=1*/
        !          2915:     long im=itos(mpinvmod(stoi(gf->psi[g]),stoi(gf->fp)));
        !          2916:     GEN cp=permcyclepow(permorbite(res), im);
        !          2917:     for(i=1;i<lg(res);i++) res[i]=cp[i];
        !          2918:     for(i=1;i<lg(gf->psi);i++) gf->psi[i]=mulssmod(im,gf->psi[i],gf->fp);
        !          2919:     avma=av2;
        !          2920:     gf->deg=deg;
        !          2921:     return res;
        !          2922:   }
        !          2923: }
        !          2924:
        !          2925: static GEN
        !          2926: galoisfindfrobenius(GEN T, GEN L, GEN M, GEN den, struct galois_frobenius *gf,
        !          2927:     struct galois_borne *gb, const struct galois_analysis *ga)
        !          2928: {
        !          2929:   ulong ltop=avma,lbot;
        !          2930:   long try=0;
        !          2931:   long n = degpol(T), deg, gmask;
        !          2932:   byteptr primepointer = ga->primepointer;
        !          2933:   GEN Lden,frob;
        !          2934:   Lden=makeLden(L,den,gb);
        !          2935:   gf->deg=ga->deg;gf->p=ga->p; deg=ga->deg;
        !          2936:   gmask=(ga->group&ga_ext_2)?3:1;
        !          2937:   for (;;)
        !          2938:   {
        !          2939:     ulong   av = avma;
        !          2940:     long    isram;
        !          2941:     long    i,c;
        !          2942:     GEN     ip,Tmod;
        !          2943:     ip = stoi(gf->p);
        !          2944:     Tmod = lift((GEN) factmod(T, ip));
        !          2945:     isram = 0;
        !          2946:     for (i = 1; i < lg(Tmod[2]) && !isram; i++)
        !          2947:       if (!gcmp1(gmael(Tmod,2,i)))
        !          2948:        isram = 1;
        !          2949:     if (isram == 0)
        !          2950:     {
        !          2951:       gf->fp = degpol(gmael(Tmod,1,1));
        !          2952:       for (i = 2; i < lg(Tmod[1]); i++)
        !          2953:        if (degpol(gmael(Tmod,1,i)) != gf->fp)
        !          2954:        {
        !          2955:          avma = ltop;
        !          2956:          return NULL;          /* Not Galois polynomial */
        !          2957:        }
        !          2958:       lbot=avma;
        !          2959:       gf->Tmod=gcopy((GEN)Tmod[1]);
        !          2960:       if ( ((gmask&1) && gf->fp % deg == 0) || ((gmask&2) && gf->fp % 2== 0) )
        !          2961:       {
        !          2962:        frob=galoisfrobeniuslift(T, den, L, Lden, gmask, gf, gb);
        !          2963:        if (frob)
        !          2964:        {
        !          2965:          GEN *gptr[3];
        !          2966:          gptr[0]=&gf->Tmod;
        !          2967:          gptr[1]=&gf->psi;
        !          2968:          gptr[2]=&frob;
        !          2969:          gerepilemanysp(ltop,lbot,gptr,3);
        !          2970:          return frob;
        !          2971:        }
        !          2972:        if ((ga->group&ga_all_normal) && gf->fp % deg == 0)
        !          2973:          gmask&=~1;
        !          2974:        /*The first prime degree is always divisible by deg, so we don't
        !          2975:         * have to worry about ext_2 being used before regular supersolvable*/
        !          2976:        if (!gmask)
        !          2977:        {
        !          2978:          avma = ltop;
        !          2979:          return NULL;
        !          2980:        }
        !          2981:        try++;
        !          2982:        if ( (ga->group&ga_non_wss) && try > n )
        !          2983:          err(warner, "galoisconj _may_ hang up for this polynomial");
        !          2984:       }
        !          2985:     }
        !          2986:     c = *primepointer++;
        !          2987:     if (!c)
        !          2988:       err(primer1);
        !          2989:     gf->p += c;
        !          2990:     if (DEBUGLEVEL >= 4)
        !          2991:       fprintferr("GaloisConj:next p=%ld\n", gf->p);
        !          2992:     avma = av;
        !          2993:   }
        !          2994: }
        !          2995:
        !          2996: GEN
        !          2997: galoisgen(GEN T, GEN L, GEN M, GEN den, struct galois_borne *gb,
        !          2998:          const struct galois_analysis *ga)
        !          2999: {
        !          3000:   struct galois_test td;
        !          3001:   struct galois_frobenius gf;
        !          3002:   ulong   ltop = avma, lbot, ltop2;
        !          3003:   long    n, p, deg;
        !          3004:   long    fp,gp;
        !          3005:   long    x;
        !          3006:   int     i, j;
        !          3007:   GEN     Lden, sigma;
        !          3008:   GEN     Tmod, res, pf = gzero, split, ip;
        !          3009:   GEN     frob;
        !          3010:   GEN     O;
        !          3011:   GEN     P, PG, PL, Pden, PM, Pmod, Pp, Pladicabs;
        !          3012:   n = degpol(T);
        !          3013:   if (!ga->deg)
        !          3014:     return gzero;
        !          3015:   x = varn(T);
        !          3016:   if (DEBUGLEVEL >= 9)
        !          3017:     fprintferr("GaloisConj:denominator:%Z\n", den);
        !          3018:   if (n == 12 && ga->ord==3)   /* A4 is very probable,so test it first */
        !          3019:   {
        !          3020:     long    av = avma;
        !          3021:     if (DEBUGLEVEL >= 4)
        !          3022:       fprintferr("GaloisConj:Testing A4 first\n");
        !          3023:     inittest(L, M, gb->bornesol, gb->ladicsol, &td);
        !          3024:     lbot = avma;
        !          3025:     PG = a4galoisgen(T, &td);
        !          3026:     freetest(&td);
        !          3027:     if (PG != gzero)
        !          3028:       return gerepile(ltop, lbot, PG);
        !          3029:     avma = av;
        !          3030:   }
        !          3031:   if (n == 24 && ga->ord==3)   /* S4 is very probable,so test it first */
        !          3032:   {
        !          3033:     long    av = avma;
        !          3034:     struct galois_lift gl;
        !          3035:     if (DEBUGLEVEL >= 4)
        !          3036:       fprintferr("GaloisConj:Testing S4 first\n");
        !          3037:     lbot = avma;
        !          3038:     Lden=makeLden(L,den,gb);
        !          3039:     initlift(T, den, stoi(ga->p4), L, Lden, gb, &gl);
        !          3040:     PG = s4galoisgen(&gl);
        !          3041:     if (PG != gzero)
        !          3042:       return gerepile(ltop, lbot, PG);
        !          3043:     avma = av;
        !          3044:   }
        !          3045:   frob=galoisfindfrobenius(T, L, M, den, &gf, gb, ga);
        !          3046:   if (!frob)
        !          3047:   {
        !          3048:     ltop=avma;
        !          3049:     return gzero;
        !          3050:   }
        !          3051:   p=gf.p;deg=gf.deg;
        !          3052:   ip=stoi(p);
        !          3053:   Tmod=gf.Tmod;
        !          3054:   fp=gf.fp; gp=n/fp;
        !          3055:   O = permorbite(frob);
        !          3056:   split = splitorbite(O);
        !          3057:   deg=lg(O[1])-1;
        !          3058:   sigma = permtopol(frob, L, M, den, gb->ladicabs, x);
        !          3059:   if (DEBUGLEVEL >= 9)
        !          3060:     fprintferr("GaloisConj:Orbite:%Z\n", O);
        !          3061:   if (deg == n)                        /* Cyclique */
        !          3062:   {
        !          3063:     lbot = avma;
        !          3064:     res = cgetg(3, t_VEC);
        !          3065:     res[1] = lgetg(lg(split[1]), t_VEC);
        !          3066:     res[2] = lgetg(lg(split[2]), t_VECSMALL);
        !          3067:     for (i = 1; i < lg(split[1]); i++)
        !          3068:     {
        !          3069:       mael(res,1,i) = lcopy(gmael(split,1,i));
        !          3070:       mael(res,2,i) = mael(split,2,i);
        !          3071:     }
        !          3072:     return gerepile(ltop, lbot, res);
        !          3073:   }
        !          3074:   if (DEBUGLEVEL >= 9)
        !          3075:     fprintferr("GaloisConj:Frobenius:%Z\n", sigma);
        !          3076:   {
        !          3077:     GEN     V, Tp, Sp, sym, dg;
        !          3078:     sym=cgetg(lg(L),t_VECSMALL);
        !          3079:     dg=cgetg(lg(L),t_VECSMALL);
        !          3080:     V = fixedfieldsympol(O, L, gb->ladicabs, gb->l, ip, sym, dg, x);
        !          3081:     P=(GEN)V[2];
        !          3082:     PL=(GEN)V[1];
        !          3083:     Tp = FpX_red(T,ip);
        !          3084:     Sp = fixedfieldpolsigma(sigma,ip,Tp,sym,dg,deg);
        !          3085:     Pmod = fixedfieldfactmod(Sp,ip,Tmod);
        !          3086:     Pp = FpX_red(P,ip);
        !          3087:     if (DEBUGLEVEL >= 4)
        !          3088:     {
        !          3089:       fprintferr("GaloisConj:P=%Z   \n", P);
        !          3090:       fprintferr("GaloisConj:psi=%Z\n", gf.psi);
        !          3091:       fprintferr("GaloisConj:Sp=%Z\n", Sp);
        !          3092:       fprintferr("GaloisConj:Pmod=%Z\n", Pmod);
        !          3093:       fprintferr("GaloisConj:Tmod=%Z\n", Tmod);
        !          3094:     }
        !          3095:     if ( n == (deg<<1))
        !          3096:     {
        !          3097:       PG=cgetg(3,t_VEC);
        !          3098:       PG[1]=lgetg(2,t_VEC);
        !          3099:       PG[2]=lgetg(2,t_VECSMALL);
        !          3100:       mael(PG,1,1)=lgetg(3,t_VECSMALL);
        !          3101:       mael(PG,2,1)=2;
        !          3102:       mael3(PG,1,1,1)=2;
        !          3103:       mael3(PG,1,1,2)=1;
        !          3104:       Pden=NULL; PM=NULL; Pladicabs=NULL;/*make KB happy*/
        !          3105:     }
        !          3106:     else
        !          3107:     {
        !          3108:       struct galois_analysis Pga;
        !          3109:       struct galois_borne Pgb;
        !          3110:       galoisanalysis(P, &Pga, 0, 0);
        !          3111:       if (Pga.deg == 0)
        !          3112:       {
        !          3113:        avma = ltop;
        !          3114:        return gzero;           /* Avoid computing the discriminant */
        !          3115:       }
        !          3116:       Pgb.l = gb->l;
        !          3117:       Pden = galoisborne(P, NULL, &Pgb, Pga.ppp);
        !          3118:       Pladicabs=Pgb.ladicabs;
        !          3119:       if (Pgb.valabs > gb->valabs)
        !          3120:       {
        !          3121:        if (DEBUGLEVEL>=4)
        !          3122:          fprintferr("GaloisConj:increase prec of p-adic roots of %ld.\n"
        !          3123:              ,Pgb.valabs-gb->valabs);
        !          3124:        PL = rootpadicliftroots(P,PL,gb->l,Pgb.valabs);
        !          3125:       }
        !          3126:       PM = vandermondeinversemod(PL, P, Pden, Pgb.ladicabs);
        !          3127:       PG = galoisgen(P, PL, PM, Pden, &Pgb, &Pga);
        !          3128:     }
        !          3129:   }
        !          3130:   if (DEBUGLEVEL >= 4)
        !          3131:     fprintferr("GaloisConj:Retour sur Terre:%Z\n", PG);
        !          3132:   if (PG == gzero)
        !          3133:   {
        !          3134:     avma = ltop;
        !          3135:     return gzero;
        !          3136:   }
        !          3137:   inittest(L, M, gb->bornesol, gb->ladicsol, &td);
        !          3138:   lbot = avma;
        !          3139:   res = cgetg(3, t_VEC);
        !          3140:   res[1] = lgetg(lg(PG[1]) + lg(split[1]) - 1, t_VEC);
        !          3141:   res[2] = lgetg(lg(PG[1]) + lg(split[1]) - 1, t_VECSMALL);
        !          3142:   for (i = 1; i < lg(split[1]); i++)
        !          3143:   {
        !          3144:     ((GEN **) res)[1][i] = gcopy(((GEN **) split)[1][i]);
        !          3145:     ((GEN *) res)[2][i] = ((GEN *) split)[2][i];
        !          3146:   }
        !          3147:   for (i = lg(split[1]); i < lg(res[1]); i++)
        !          3148:     ((GEN **) res)[1][i] = cgetg(n + 1, t_VECSMALL);
        !          3149:   ltop2 = avma;
        !          3150:   for (j = 1; j < lg(PG[1]); j++)
        !          3151:   {
        !          3152:     GEN     B, tau;
        !          3153:     long    t, g;
        !          3154:     long    w, sr, dss;
        !          3155:     if (DEBUGLEVEL >= 6)
        !          3156:       fprintferr("GaloisConj:G[%d]=%Z  d'ordre relatif %d\n", j,
        !          3157:          ((GEN **) PG)[1][j], ((long **) PG)[2][j]);
        !          3158:     B = permorbite(((GEN **) PG)[1][j]);
        !          3159:     if (DEBUGLEVEL >= 6)
        !          3160:       fprintferr("GaloisConj:B=%Z\n", B);
        !          3161:     if (n == (deg<<1))
        !          3162:       tau=deg1pol(stoi(-1),negi((GEN)P[3]),x);
        !          3163:     else
        !          3164:       tau = permtopol(gmael(PG,1,j), PL, PM, Pden, Pladicabs, x);
        !          3165:     if (DEBUGLEVEL >= 9)
        !          3166:       fprintferr("GaloisConj:Paut=%Z\n", tau);
        !          3167:     /*tau not in Z[X]*/
        !          3168:     tau = lift(gmul(tau,gmodulcp(gun,ip)));
        !          3169:     tau = FpX_FpXQ_compo((GEN) Pmod[gp], tau,Pp,ip);
        !          3170:     tau = FpX_gcd(Pp, tau,ip);
        !          3171:     /*normalize gcd*/
        !          3172:     tau = FpX_Fp_mul(tau,mpinvmod((GEN) tau[lgef(tau) - 1],ip),ip);
        !          3173:     if (DEBUGLEVEL >= 6)
        !          3174:       fprintferr("GaloisConj:tau=%Z\n", tau);
        !          3175:     for (g = 1; g < lg(Pmod); g++)
        !          3176:       if (gegal(tau, (GEN) Pmod[g]))
        !          3177:        break;
        !          3178:     if (DEBUGLEVEL >= 6)
        !          3179:       fprintferr("GaloisConj:g=%ld\n", g);
        !          3180:     if (g == lg(Pmod))
        !          3181:     {
        !          3182:       freetest(&td);
        !          3183:       avma = ltop;
        !          3184:       return gzero;
        !          3185:     }
        !          3186:     w = gf.psi[g];
        !          3187:     dss = deg / cgcd(deg, w - 1);
        !          3188:     sr = 1;
        !          3189:     for (i = 1; i < lg(B[1]) - 1; i++)
        !          3190:       sr = (1 + sr * w) % deg;
        !          3191:     sr = cgcd(sr, deg);
        !          3192:     if (DEBUGLEVEL >= 6)
        !          3193:       fprintferr("GaloisConj:w=%ld [%ld] sr=%ld dss=%ld\n", w, deg, sr, dss);
        !          3194:     for (t = 0; t < sr; t += dss)
        !          3195:     {
        !          3196:       pf = testpermutation(O, B, w, t, sr, &td);
        !          3197:       if (pf != gzero)
        !          3198:        break;
        !          3199:     }
        !          3200:     if (pf == gzero)
        !          3201:     {
        !          3202:       freetest(&td);
        !          3203:       avma = ltop;
        !          3204:       return gzero;
        !          3205:     }
        !          3206:     else
        !          3207:     {
        !          3208:       int     i;
        !          3209:       for (i = 1; i <= n; i++)
        !          3210:        ((GEN **) res)[1][lg(split[1]) + j - 1][i] = pf[i];
        !          3211:       ((GEN *) res)[2][lg(split[1]) + j - 1] = ((GEN *) PG)[2][j];
        !          3212:     }
        !          3213:     avma = ltop2;
        !          3214:   }
        !          3215:   if (DEBUGLEVEL >= 4)
        !          3216:     fprintferr("GaloisConj:Fini!\n");
        !          3217:   freetest(&td);
        !          3218:   return gerepile(ltop, lbot, res);
        !          3219: }
        !          3220:
        !          3221: /*
        !          3222:  * T: polynome ou nf den optionnel: si présent doit etre un multiple du
        !          3223:  * dénominateur commun des solutions Si T est un nf et den n'est pas présent,
        !          3224:  * le denominateur de la base d'entiers est pris pour den
        !          3225:  */
        !          3226: GEN
        !          3227: galoisconj4(GEN T, GEN den, long flag, long karma)
        !          3228: {
        !          3229:   ulong   ltop = avma;
        !          3230:   GEN     G, L, M, res, aut, grp=NULL;/*keep gcc happy on the wall*/
        !          3231:   struct galois_analysis ga;
        !          3232:   struct galois_borne gb;
        !          3233:   int     n, i, j, k;
        !          3234:   if (typ(T) != t_POL)
        !          3235:   {
        !          3236:     T = checknf(T);
        !          3237:     if (!den)
        !          3238:       den = gcoeff((GEN) T[8], degpol(T[1]), degpol(T[1]));
        !          3239:     T = (GEN) T[1];
        !          3240:   }
        !          3241:   n = degpol(T);
        !          3242:   if (n <= 0)
        !          3243:     err(constpoler, "galoisconj4");
        !          3244:   for (k = 2; k <= n + 2; k++)
        !          3245:     if (typ(T[k]) != t_INT)
        !          3246:       err(talker, "polynomial not in Z[X] in galoisconj4");
        !          3247:   if (!gcmp1((GEN) T[n + 2]))
        !          3248:     err(talker, "non-monic polynomial in galoisconj4");
        !          3249:   n = degpol(T);
        !          3250:   if (n == 1)                  /* Too easy! */
        !          3251:   {
        !          3252:     if (!flag)
        !          3253:     {
        !          3254:       res = cgetg(2, t_COL);
        !          3255:       res[1] = (long) polx[varn(T)];
        !          3256:       return res;
        !          3257:     }
        !          3258:     ga.l = 3;
        !          3259:     ga.deg = 1;
        !          3260:     ga.ppp = 1;
        !          3261:     den = gun;
        !          3262:   }
        !          3263:   else
        !          3264:     galoisanalysis(T, &ga, 1, karma);
        !          3265:   if (ga.deg == 0)
        !          3266:   {
        !          3267:     avma = ltop;
        !          3268:     return stoi(ga.p);         /* Avoid computing the discriminant */
        !          3269:   }
        !          3270:   if (den)
        !          3271:   {
        !          3272:     if (typ(den) != t_INT)
        !          3273:       err(talker, "Second arg. must be integer in galoisconj4");
        !          3274:     den = absi(den);
        !          3275:   }
        !          3276:   gb.l = stoi(ga.l);
        !          3277:   if (DEBUGLEVEL >= 1)
        !          3278:     timer2();
        !          3279:   den = galoisborne(T, den, &gb, ga.ppp);
        !          3280:   if (DEBUGLEVEL >= 1)
        !          3281:     msgtimer("galoisborne()");
        !          3282:   L = rootpadicfast(T, gb.l, gb.valabs);
        !          3283:   if (DEBUGLEVEL >= 1)
        !          3284:     msgtimer("rootpadicfast()");
        !          3285:   M = vandermondeinversemod(L, T, den, gb.ladicabs);
        !          3286:   if (DEBUGLEVEL >= 1)
        !          3287:     msgtimer("vandermondeinversemod()");
        !          3288:   if (n == 1)
        !          3289:   {
        !          3290:     G = cgetg(3, t_VEC);
        !          3291:     G[1] = lgetg(1, t_VECSMALL);
        !          3292:     G[2] = lgetg(1, t_VECSMALL);
        !          3293:   }
        !          3294:   else
        !          3295:     G = galoisgen(T, L, M, den, &gb, &ga);
        !          3296:   if (DEBUGLEVEL >= 6)
        !          3297:     fprintferr("GaloisConj:%Z\n", G);
        !          3298:   if (G == gzero)
        !          3299:   {
        !          3300:     avma = ltop;
        !          3301:     return gzero;
        !          3302:   }
        !          3303:   if (DEBUGLEVEL >= 1)
        !          3304:     timer2();
        !          3305:   if (flag)
        !          3306:   {
        !          3307:     grp = cgetg(9, t_VEC);
        !          3308:     grp[1] = (long) gcopy(T);
        !          3309:     grp[2] = lgetg(4,t_VEC); /*Make K.B. happy(8 components)*/
        !          3310:     mael(grp,2,1) = lstoi(ga.l);
        !          3311:     mael(grp,2,2) = lstoi(gb.valabs);
        !          3312:     mael(grp,2,3) = licopy(gb.ladicabs);
        !          3313:     grp[3] = (long) gcopy(L);
        !          3314:     grp[4] = (long) gcopy(M);
        !          3315:     grp[5] = (long) gcopy(den);
        !          3316:     grp[7] = (long) gcopy((GEN) G[1]);
        !          3317:     grp[8] = (long) gcopy((GEN) G[2]);
        !          3318:   }
        !          3319:   res = cgetg(n + 1, t_VEC);
        !          3320:   res[1] = (long) permidentity(n);
        !          3321:   k = 1;
        !          3322:   for (i = 1; i < lg(G[1]); i++)
        !          3323:   {
        !          3324:     int     c = k * (((long **) G)[2][i] - 1);
        !          3325:     for (j = 1; j <= c; j++)   /* I like it */
        !          3326:       res[++k] = (long) permapply((GEN) res[j], ((GEN **) G)[1][i]);
        !          3327:   }
        !          3328:   if (flag)
        !          3329:   {
        !          3330:     grp[6] = (long) res;
        !          3331:     return gerepileupto(ltop, grp);
        !          3332:   }
        !          3333:   aut = galoisgrouptopol(res,L,M,den,gb.ladicsol, varn(T));
        !          3334:   if (DEBUGLEVEL >= 1)
        !          3335:     msgtimer("Calcul polynomes");
        !          3336:   return gerepileupto(ltop, aut);
        !          3337: }
        !          3338:
        !          3339: /* Calcule le nombre d'automorphisme de T avec forte probabilité */
        !          3340: /* pdepart premier nombre premier a tester */
        !          3341: long
        !          3342: numberofconjugates(GEN T, long pdepart)
        !          3343: {
        !          3344:   ulong   ltop = avma, ltop2;
        !          3345:   long    n, p, nbmax, nbtest;
        !          3346:   long    card;
        !          3347:   byteptr primepointer;
        !          3348:   int     i;
        !          3349:   GEN     L;
        !          3350:   n = degpol(T);
        !          3351:   card = sturm(T);
        !          3352:   card = cgcd(card, n - card);
        !          3353:   nbmax = (n<<1) + 1;
        !          3354:   if (nbmax < 20) nbmax=20;
        !          3355:   nbtest = 0;
        !          3356:   L = cgetg(n + 1, t_VECSMALL);
        !          3357:   ltop2 = avma;
        !          3358:   for (p = 0, primepointer = diffptr; nbtest < nbmax && card > 1;)
        !          3359:   {
        !          3360:     long    s, c;
        !          3361:     long    isram;
        !          3362:     GEN     S;
        !          3363:     c = *primepointer++;
        !          3364:     if (!c)
        !          3365:       err(primer1);
        !          3366:     p += c;
        !          3367:     if (p < pdepart)
        !          3368:       continue;
        !          3369:     S = (GEN) simplefactmod(T, stoi(p));
        !          3370:     isram = 0;
        !          3371:     for (i = 1; i < lg(S[2]) && !isram; i++)
        !          3372:       if (!gcmp1(((GEN **) S)[2][i]))
        !          3373:        isram = 1;
        !          3374:     if (isram == 0)
        !          3375:     {
        !          3376:       for (i = 1; i <= n; i++)
        !          3377:        L[i] = 0;
        !          3378:       for (i = 1; i < lg(S[1]) && !isram; i++)
        !          3379:        L[itos(((GEN **) S)[1][i])]++;
        !          3380:       s = L[1];
        !          3381:       for (i = 2; i <= n; i++)
        !          3382:        s = cgcd(s, L[i] * i);
        !          3383:       card = cgcd(s, card);
        !          3384:     }
        !          3385:     if (DEBUGLEVEL >= 6)
        !          3386:       fprintferr("NumberOfConjugates:Nbtest=%ld,card=%ld,p=%ld\n", nbtest,
        !          3387:                 card, p);
        !          3388:     nbtest++;
        !          3389:     avma = ltop2;
        !          3390:   }
        !          3391:   if (DEBUGLEVEL >= 2)
        !          3392:     fprintferr("NumberOfConjugates:card=%ld,p=%ld\n", card, p);
        !          3393:   avma = ltop;
        !          3394:   return card;
        !          3395: }
        !          3396:
        !          3397: GEN
        !          3398: galoisconj0(GEN nf, long flag, GEN d, long prec)
        !          3399: {
        !          3400:   ulong   ltop;
        !          3401:   GEN     G, T;
        !          3402:   long    card;
        !          3403:   if (typ(nf) != t_POL)
        !          3404:   {
        !          3405:     nf = checknf(nf);
        !          3406:     T = (GEN) nf[1];
        !          3407:   }
        !          3408:   else
        !          3409:     T = nf;
        !          3410:   switch (flag)
        !          3411:   {
        !          3412:   case 0:
        !          3413:     ltop = avma;
        !          3414:     G = galoisconj4(nf, d, 0, 0);
        !          3415:     if (typ(G) != t_INT)       /* Success */
        !          3416:       return G;
        !          3417:     else
        !          3418:     {
        !          3419:       card = numberofconjugates(T, G == gzero ? 2 : itos(G));
        !          3420:       avma = ltop;
        !          3421:       if (card != 1)
        !          3422:       {
        !          3423:        if (typ(nf) == t_POL)
        !          3424:        {
        !          3425:          G = galoisconj2pol(nf, card, prec);
        !          3426:          if (lg(G) <= card)
        !          3427:            err(warner, "conjugates list may be incomplete in nfgaloisconj");
        !          3428:          return G;
        !          3429:        }
        !          3430:        else
        !          3431:          return galoisconj(nf);
        !          3432:       }
        !          3433:     }
        !          3434:     break;                     /* Failure */
        !          3435:   case 1:
        !          3436:     return galoisconj(nf);
        !          3437:   case 2:
        !          3438:     return galoisconj2(nf, degpol(T), prec);
        !          3439:   case 4:
        !          3440:     G = galoisconj4(nf, d, 0, 0);
        !          3441:     if (typ(G) != t_INT)
        !          3442:       return G;
        !          3443:     break;                     /* Failure */
        !          3444:   default:
        !          3445:     err(flagerr, "nfgaloisconj");
        !          3446:   }
        !          3447:   G = cgetg(2, t_COL);
        !          3448:   G[1] = (long) polx[varn(T)];
        !          3449:   return G;                    /* Failure */
        !          3450: }
        !          3451:
        !          3452:
        !          3453:
        !          3454: /******************************************************************************/
        !          3455: /* Isomorphism between number fields                                          */
        !          3456: /******************************************************************************/
        !          3457: long
        !          3458: isomborne(GEN P, GEN den, GEN p)
        !          3459: {
        !          3460:   ulong ltop=avma;
        !          3461:   struct galois_borne gb;
        !          3462:   gb.l=p;
        !          3463:   galoisborne(P,den,&gb,degpol(P));
        !          3464:   avma=ltop;
        !          3465:   return gb.valsol;
        !          3466: }
        !          3467:
        !          3468:
        !          3469:
        !          3470: /******************************************************************************/
        !          3471: /* Galois theory related algorithms                                           */
        !          3472: /******************************************************************************/
        !          3473: GEN
        !          3474: checkgal(GEN gal)
        !          3475: {
        !          3476:   if (typ(gal) == t_POL)
        !          3477:     err(talker, "please apply galoisinit first");
        !          3478:   if (typ(gal) != t_VEC || lg(gal) != 9)
        !          3479:     err(talker, "Not a Galois field in a Galois related function");
        !          3480:   return gal;
        !          3481: }
        !          3482:
        !          3483: GEN
        !          3484: galoisinit(GEN nf, GEN den, long karma)
        !          3485: {
        !          3486:   GEN     G;
        !          3487:   G = galoisconj4(nf, den, 1, karma);
        !          3488:   if (typ(G) == t_INT)
        !          3489:     err(talker,
        !          3490:        "galoisinit: field not Galois or Galois group not weakly super solvable");
        !          3491:   return G;
        !          3492: }
        !          3493:
        !          3494: GEN
        !          3495: galoispermtopol(GEN gal, GEN perm)
        !          3496: {
        !          3497:   GEN     v;
        !          3498:   long    t = typ(perm);
        !          3499:   int     i;
        !          3500:   gal = checkgal(gal);
        !          3501:   switch (t)
        !          3502:   {
        !          3503:   case t_VECSMALL:
        !          3504:     return permtopol(perm, (GEN) gal[3], (GEN) gal[4], (GEN) gal[5],
        !          3505:                     gmael(gal,2,3), varn((GEN) gal[1]));
        !          3506:   case t_VEC:
        !          3507:   case t_COL:
        !          3508:   case t_MAT:
        !          3509:     v = cgetg(lg(perm), t);
        !          3510:     for (i = 1; i < lg(v); i++)
        !          3511:       v[i] = (long) galoispermtopol(gal, (GEN) perm[i]);
        !          3512:     return v;
        !          3513:   }
        !          3514:   err(typeer, "galoispermtopol");
        !          3515:   return NULL;                 /* not reached */
        !          3516: }
        !          3517:
        !          3518:
        !          3519: GEN
        !          3520: galoiscosets(GEN O, GEN perm)
        !          3521: {
        !          3522:   long i,j,k,u;
        !          3523:   long o = lg(O)-1, f = lg(O[1])-1;
        !          3524:   GEN C = cgetg(lg(O),t_VECSMALL);
        !          3525:   ulong av=avma;
        !          3526:   GEN RC=cgetg(lg(perm),t_VECSMALL);
        !          3527:   for(i=1;i<lg(RC);i++)
        !          3528:     RC[i]=0;
        !          3529:   u=mael(O,1,1);
        !          3530:   for(i=1,j=1;j<=o;i++)
        !          3531:   {
        !          3532:     if (RC[mael(perm,i,u)])
        !          3533:       continue;
        !          3534:     for(k=1;k<=f;k++)
        !          3535:       RC[mael(perm,i,mael(O,1,k))]=1;
        !          3536:     C[j++]=i;
        !          3537:   }
        !          3538:   avma=av;
        !          3539:   return C;
        !          3540: }
        !          3541:
        !          3542: GEN
        !          3543: fixedfieldfactor(GEN L, GEN O, GEN perm, GEN M, GEN den, GEN mod,
        !          3544:                  long x,long y)
        !          3545: {
        !          3546:   ulong   ltop=avma;
        !          3547:   GEN     F,G,V,res,cosets;
        !          3548:   int     i, j, k;
        !          3549:   F=cgetg(lg(O[1])+1,t_COL);
        !          3550:   F[lg(O[1])]=un;
        !          3551:   G=cgetg(lg(O),t_VEC);
        !          3552:   for (i = 1; i < lg(O); i++)
        !          3553:   {
        !          3554:     GEN Li = cgetg(lg(O[i]),t_VEC);
        !          3555:     for (j = 1; j < lg(O[i]); j++)
        !          3556:       Li[j] = L[mael(O,i,j)];
        !          3557:     G[i]=(long)FpV_roots_to_pol(Li,mod,x);
        !          3558:   }
        !          3559:
        !          3560:   cosets=galoiscosets(O,perm);
        !          3561:   if (DEBUGLEVEL>=4) fprintferr("GaloisFixedField:cosets=%Z \n",cosets);
        !          3562:   V=cgetg(lg(O),t_COL);
        !          3563:   if (DEBUGLEVEL>=6) fprintferr("GaloisFixedField:den=%Z mod=%Z \n",den,mod);
        !          3564:   res=cgetg(lg(O),t_VEC);
        !          3565:   for (i = 1; i < lg(O); i++)
        !          3566:   {
        !          3567:     ulong av=avma;
        !          3568:     long ii,jj;
        !          3569:     GEN G=cgetg(lg(O),t_VEC);
        !          3570:     for (ii = 1; ii < lg(O); ii++)
        !          3571:     {
        !          3572:       GEN Li = cgetg(lg(O[ii]),t_VEC);
        !          3573:       for (jj = 1; jj < lg(O[ii]); jj++)
        !          3574:        Li[jj] = L[mael(perm,cosets[i],mael(O,ii,jj))];
        !          3575:       G[ii]=(long)FpV_roots_to_pol(Li,mod,x);
        !          3576:     }
        !          3577:     for (j = 1; j < lg(O[1]); j++)
        !          3578:     {
        !          3579:       for(k = 1; k < lg(O); k++)
        !          3580:        V[k]=mael(G,k,j+1);
        !          3581:       F[j]=(long) vectopol(V, M, den, mod, y);
        !          3582:     }
        !          3583:     res[i]=(long)gerepileupto(av,gtopolyrev(F,x));
        !          3584:   }
        !          3585:   return gerepileupto(ltop,res);
        !          3586: }
        !          3587:
        !          3588: GEN
        !          3589: galoisfixedfield(GEN gal, GEN perm, long flag, long y)
        !          3590: {
        !          3591:   ulong   ltop = avma, lbot;
        !          3592:   GEN     L, P, S, PL, O, res, mod;
        !          3593:   long    x, n;
        !          3594:   int     i;
        !          3595:   gal = checkgal(gal);
        !          3596:   x = varn((GEN) gal[1]);
        !          3597:   L = (GEN) gal[3]; n=lg(L)-1;
        !          3598:   mod = gmael(gal,2,3);
        !          3599:   if (flag<0 || flag>2)
        !          3600:     err(flagerr, "galoisfixedfield");
        !          3601:   if (typ(perm) == t_VEC)
        !          3602:   {
        !          3603:     if (lg(perm)==1)
        !          3604:       perm=permidentity(n);
        !          3605:     else
        !          3606:       for (i = 1; i < lg(perm); i++)
        !          3607:        if (typ(perm[i]) != t_VECSMALL || lg(perm[i])!=n+1)
        !          3608:          err(typeer, "galoisfixedfield");
        !          3609:   }
        !          3610:   else if (typ(perm) != t_VECSMALL || lg(perm)!=n+1 )
        !          3611:     err(typeer, "galoisfixedfield");
        !          3612:   O = permorbite(perm);
        !          3613:   {
        !          3614:     GEN sym=cgetg(lg(L),t_VECSMALL);
        !          3615:     GEN dg=cgetg(lg(L),t_VECSMALL);
        !          3616:     GEN V;
        !          3617:     V = fixedfieldsympol(O, L, mod, gmael(gal,2,1), gun, sym, dg, x);
        !          3618:     P=(GEN)V[2];
        !          3619:     PL=(GEN)V[1];
        !          3620:   }
        !          3621:   if (flag==1)
        !          3622:     return gerepileupto(ltop,P);
        !          3623:   S = fixedfieldinclusion(O, PL);
        !          3624:   S = vectopol(S, (GEN) gal[4], (GEN) gal[5], mod, x);
        !          3625:   if (flag==0)
        !          3626:   {
        !          3627:     lbot = avma;
        !          3628:     res = cgetg(3, t_VEC);
        !          3629:     res[1] = (long) gcopy(P);
        !          3630:     res[2] = (long) gmodulcp(S, (GEN) gal[1]);
        !          3631:     return gerepile(ltop, lbot, res);
        !          3632:   }
        !          3633:   else
        !          3634:   {
        !          3635:     GEN PM,Pden;
        !          3636:     {
        !          3637:       struct galois_borne Pgb;
        !          3638:       long val=itos(gmael(gal,2,2));
        !          3639:       Pgb.l = gmael(gal,2,1);
        !          3640:       Pden = galoisborne(P, NULL, &Pgb, 1);
        !          3641:       if (Pgb.valabs > val)
        !          3642:       {
        !          3643:        if (DEBUGLEVEL>=4)
        !          3644:          fprintferr("GaloisConj:increase prec of p-adic roots of %ld.\n"
        !          3645:              ,Pgb.valabs-val);
        !          3646:        PL = rootpadicliftroots(P,PL,Pgb.l,Pgb.valabs);
        !          3647:        L = rootpadicliftroots((GEN) gal[1],L,Pgb.l,Pgb.valabs);
        !          3648:        mod = Pgb.ladicabs;
        !          3649:       }
        !          3650:     }
        !          3651:     PM = vandermondeinversemod(PL, P, Pden, mod);
        !          3652:     lbot = avma;
        !          3653:     if (y==-1)
        !          3654:       y = fetch_user_var("y");
        !          3655:     if (y<=x)
        !          3656:       err(talker,"priority of optional variable too high in galoisfixedfield");
        !          3657:     res = cgetg(4, t_VEC);
        !          3658:     res[1] = (long) gcopy(P);
        !          3659:     res[2] = (long) gmodulcp(S, (GEN) gal[1]);
        !          3660:     res[3] = (long) fixedfieldfactor(L,O,(GEN)gal[6],
        !          3661:        PM,Pden,mod,x,y);
        !          3662:     return gerepile(ltop, lbot, res);
        !          3663:   }
        !          3664: }
        !          3665:
        !          3666: /*return 1 if gal is abelian, else 0*/
        !          3667: long
        !          3668: galoistestabelian(GEN gal)
        !          3669: {
        !          3670:   ulong ltop=avma;
        !          3671:   long i,j;
        !          3672:   gal = checkgal(gal);
        !          3673:   for(i=2;i<lg(gal[7]);i++)
        !          3674:     for(j=1;j<i;j++)
        !          3675:     {
        !          3676:       long test=gegal(permapply(gmael(gal,7,i),gmael(gal,7,j)),
        !          3677:          permapply(gmael(gal,7,j),gmael(gal,7,i)));
        !          3678:       avma=ltop;
        !          3679:       if (!test) return 0;
        !          3680:     }
        !          3681:   return 1;
        !          3682: }
        !          3683:
        !          3684: GEN galoisisabelian(GEN gal, long flag)
        !          3685: {
        !          3686:   long i, j;
        !          3687:   long test, n=lg(gal[7]);
        !          3688:   GEN M;
        !          3689:   gal = checkgal(gal);
        !          3690:   test=galoistestabelian(gal);
        !          3691:   if (!test) return gzero;
        !          3692:   if (flag==1)  return gun;
        !          3693:   if (flag) err(flagerr,"galoisisabelian");
        !          3694:   M=cgetg(n,t_MAT);
        !          3695:   for(i=1;i<n;i++)
        !          3696:   {
        !          3697:     ulong btop;
        !          3698:     GEN P;
        !          3699:     long k;
        !          3700:     M[i]=lgetg(n,t_COL);
        !          3701:     btop=avma;
        !          3702:     P=permcyclepow(permorbite(gmael(gal,7,i)),mael(gal,8,i));
        !          3703:     for(j=1;j<lg(gal[6]);j++)
        !          3704:       if (gegal(P,gmael(gal,6,j)))
        !          3705:          break;
        !          3706:     avma=btop;
        !          3707:     if (j==lg(gal[6])) err(talker,"wrong argument in galoisisabelian");
        !          3708:     j--;
        !          3709:     for(k=1;k<i;k++)
        !          3710:     {
        !          3711:       mael(M,i,k)=lstoi(j%mael(gal,8,k));
        !          3712:       j/=mael(gal,8,k);
        !          3713:     }
        !          3714:     mael(M,i,k++)=lstoi(mael(gal,8,i));
        !          3715:     for(  ;k<n;k++)
        !          3716:       mael(M,i,k)=zero;
        !          3717:   }
        !          3718:   return M;
        !          3719: }
        !          3720: /* Calcule les orbites d'un sous-groupe de Z/nZ donne par un
        !          3721:  * generateur ou d'un ensemble de generateur donne par un vecteur.
        !          3722:  */
        !          3723: GEN
        !          3724: subgroupcoset(long n, GEN v)
        !          3725: {
        !          3726:   ulong   ltop = avma, lbot;
        !          3727:   int     i, j, k = 1, l, m, o, p, flag;
        !          3728:   GEN     bit, cycle, cy;
        !          3729:   cycle = cgetg(n, t_VEC);
        !          3730:   bit = cgetg(n, t_VECSMALL);
        !          3731:   for (i = 1; i < n; i++)
        !          3732:     if (cgcd(i,n)==1)
        !          3733:       bit[i] = 0;
        !          3734:     else
        !          3735:     {
        !          3736:       bit[i] = -1;
        !          3737:       k++;
        !          3738:     }
        !          3739:   for (l = 1; k < n;)
        !          3740:   {
        !          3741:     for (j = 1; bit[j]; j++);
        !          3742:     cy = cgetg(n, t_VECSMALL);
        !          3743:     m = 1;
        !          3744:     cy[m++] = j;
        !          3745:     bit[j] = 1;
        !          3746:     k++;
        !          3747:     do
        !          3748:     {
        !          3749:       flag = 0;
        !          3750:       for (o = 1; o < lg(v); o++)
        !          3751:       {
        !          3752:        for (p = 1; p < m; p++) /* m varie! */
        !          3753:        {
        !          3754:          j = mulssmod(v[o],cy[p],n);
        !          3755:          if (!bit[j])
        !          3756:          {
        !          3757:            flag = 1;
        !          3758:            bit[j] = 1;
        !          3759:            k++;
        !          3760:            cy[m++] = j;
        !          3761:          }
        !          3762:        }
        !          3763:       }
        !          3764:     }
        !          3765:     while (flag);
        !          3766:     setlg(cy, m);
        !          3767:     cycle[l++] = (long) cy;
        !          3768:   }
        !          3769:   setlg(cycle, l);
        !          3770:   lbot = avma;
        !          3771:   cycle = gcopy(cycle);
        !          3772:   return gerepile(ltop, lbot, cycle);
        !          3773: }
        !          3774: /* Calcule les elements d'un sous-groupe H de Z/nZ donne par un
        !          3775:  * generateur ou d'un ensemble de generateur donne par un vecteur (v).
        !          3776:  *
        !          3777:  * cy liste des elements   VECSMALL de longueur au moins card H.
        !          3778:  * bit bitmap des elements VECSMALL de longueur au moins n.
        !          3779:  * retourne le nombre d'elements+1
        !          3780:  */
        !          3781: long
        !          3782: sousgroupeelem(long n, GEN v, GEN cy, GEN bit)
        !          3783: {
        !          3784:   int     j, m, o, p, flag;
        !          3785:   for(j=1;j<n;j++)
        !          3786:     bit[j]=0;
        !          3787:   m = 1;
        !          3788:   bit[m] = 1;
        !          3789:   cy[m++] = 1;
        !          3790:   do
        !          3791:   {
        !          3792:     flag = 0;
        !          3793:     for (o = 1; o < lg(v); o++)
        !          3794:     {
        !          3795:       for (p = 1; p < m; p++)  /* m varie! */
        !          3796:       {
        !          3797:        j = mulssmod(v[o],cy[p],n);
        !          3798:        if (!bit[j])
        !          3799:        {
        !          3800:          flag = 1;
        !          3801:          bit[j] = 1;
        !          3802:          cy[m++] = j;
        !          3803:        }
        !          3804:       }
        !          3805:     }
        !          3806:   }
        !          3807:   while (flag);
        !          3808:   return m;
        !          3809: }
        !          3810: /* n,v comme precedemment.
        !          3811:  * Calcule le conducteur et retourne le nouveau groupe de congruence dans V
        !          3812:  * V doit etre un t_VECSMALL de taille n+1 au moins.
        !          3813:  */
        !          3814: long znconductor(long n, GEN v, GEN V)
        !          3815: {
        !          3816:   ulong ltop;
        !          3817:   int i,j;
        !          3818:   long m;
        !          3819:   GEN F,W;
        !          3820:   W = cgetg(n, t_VECSMALL);
        !          3821:   ltop=avma;
        !          3822:   m = sousgroupeelem(n,v,V,W);
        !          3823:   setlg(V,m);
        !          3824:   if (DEBUGLEVEL>=6)
        !          3825:     fprintferr("SubCyclo:elements:%Z\n",V);
        !          3826:   F = factor(stoi(n));
        !          3827:   for(i=lg((GEN)F[1])-1;i>0;i--)
        !          3828:   {
        !          3829:     long p,e,q;
        !          3830:     p=itos(gcoeff(F,i,1));
        !          3831:     e=itos(gcoeff(F,i,2));
        !          3832:     if (DEBUGLEVEL>=4)
        !          3833:       fprintferr("SubCyclo:testing %ld^%ld\n",p,e);
        !          3834:     while (e>=1)
        !          3835:     {
        !          3836:       int z = 1;
        !          3837:       q=n/p;
        !          3838:       for(j=1;j<p;j++)
        !          3839:       {
        !          3840:        z += q;
        !          3841:        if (!W[z] && z%p) break;
        !          3842:       }
        !          3843:       if (j<p)
        !          3844:       {
        !          3845:        if (DEBUGLEVEL>=4)
        !          3846:          fprintferr("SubCyclo:%ld not found\n",z);
        !          3847:        break;
        !          3848:       }
        !          3849:       e--;
        !          3850:       n=q;
        !          3851:       if (DEBUGLEVEL>=4)
        !          3852:        fprintferr("SubCyclo:new conductor:%ld\n",n);
        !          3853:       m=sousgroupeelem(n,v,V,W);
        !          3854:       setlg(V,m);
        !          3855:       if (DEBUGLEVEL>=6)
        !          3856:        fprintferr("SubCyclo:elements:%Z\n",V);
        !          3857:     }
        !          3858:   }
        !          3859:   if (DEBUGLEVEL>=6)
        !          3860:     fprintferr("SubCyclo:conductor:%ld\n",n);
        !          3861:   avma=ltop;
        !          3862:   return n;
        !          3863: }
        !          3864:
        !          3865: static GEN gscycloconductor(GEN g, long n, long flag)
        !          3866: {
        !          3867:   if (flag==2)
        !          3868:   {
        !          3869:     GEN V=cgetg(3,t_VEC);
        !          3870:     V[1]=lcopy(g);
        !          3871:     V[2]=lstoi(n);
        !          3872:     return V;
        !          3873:   }
        !          3874:   return g;
        !          3875: }
        !          3876: static GEN
        !          3877: lift_check_modulus(GEN H, GEN n)
        !          3878: {
        !          3879:   long t=typ(H), l=lg(H);
        !          3880:   long i;
        !          3881:   GEN V;
        !          3882:   switch(t)
        !          3883:   {
        !          3884:     case t_INTMOD:
        !          3885:       if (cmpii(n,(GEN)H[1]))
        !          3886:        err(talker,"wrong modulus in galoissubcyclo");
        !          3887:       H = (GEN)H[2];
        !          3888:     case t_INT:
        !          3889:       if (!is_pm1(mppgcd(H,n)))
        !          3890:        err(talker,"generators must be prime to conductor in galoissubcyclo");
        !          3891:       return modii(H,n);
        !          3892:     case t_VEC: case t_COL:
        !          3893:       V=cgetg(l,t);
        !          3894:       for(i=1;i<l;i++)
        !          3895:        V[i] = (long)lift_check_modulus((GEN)H[i],n);
        !          3896:       return V;
        !          3897:     case t_VECSMALL:
        !          3898:       return H;
        !          3899:   }
        !          3900:   err(talker,"wrong type in galoissubcyclo");
        !          3901:   return NULL;/*not reached*/
        !          3902: }
        !          3903:
        !          3904: GEN
        !          3905: galoissubcyclo(long n, GEN H, GEN Z, long v, long flag)
        !          3906: {
        !          3907:   ulong ltop=avma,av;
        !          3908:   GEN l,borne,le,powz,z,V;
        !          3909:   long i;
        !          3910:   long e,val;
        !          3911:   long u,o,j;
        !          3912:   GEN O,g;
        !          3913:   if (flag<0 || flag>2) err(flagerr,"galoisubcyclo");
        !          3914:   if ( v==-1 ) v=0;
        !          3915:   if ( n<1 ) err(arither2);
        !          3916:   if ( n>=VERYBIGINT)
        !          3917:     err(impl,"galoissubcyclo for huge conductor");
        !          3918:   if ( typ(H)==t_MAT )
        !          3919:   {
        !          3920:     GEN zn2, zn3, gen, ord;
        !          3921:     if (lg(H) == 1 || lg(H) != lg(H[1]))
        !          3922:       err(talker,"not a HNF matrix in galoissubcyclo");
        !          3923:     if (!Z)
        !          3924:       Z=znstar(stoi(n));
        !          3925:     else if (typ(Z)!=t_VEC || lg(Z)!=4)
        !          3926:       err(talker,"Optionnal parameter must be as output by znstar in galoissubcyclo");
        !          3927:     zn2 = gtovecsmall((GEN)Z[2]);
        !          3928:     zn3 = lift((GEN)Z[3]);
        !          3929:     if ( lg(zn2) != lg(H) || lg(zn3) != lg(H))
        !          3930:       err(talker,"Matrix of wrong dimensions in galoissubcyclo");
        !          3931:     gen = cgetg(lg(zn3), t_VECSMALL);
        !          3932:     ord = cgetg(lg(zn3), t_VECSMALL);
        !          3933:     hnftogeneratorslist(n,zn2,zn3,H,gen,ord);
        !          3934:     H=gen;
        !          3935:   }
        !          3936:   else
        !          3937:   {
        !          3938:     H=lift_check_modulus(H,stoi(n));
        !          3939:     H=gtovecsmall(H);
        !          3940:     for (i=1;i<lg(H);i++)
        !          3941:       if (H[i]<0)
        !          3942:        H[i]=mulssmod(-H[i],n-1,n);
        !          3943:     /*Should check components are prime to n, but it is costly*/
        !          3944:   }
        !          3945:   V = cgetg(n, t_VECSMALL);
        !          3946:   if (DEBUGLEVEL >= 1)
        !          3947:     timer2();
        !          3948:   n = znconductor(n,H,V);
        !          3949:   if (flag==1)  {avma=ltop;return stoi(n);}
        !          3950:   if (DEBUGLEVEL >= 1)
        !          3951:     msgtimer("znconductor.");
        !          3952:   H = V;
        !          3953:   O = subgroupcoset(n,H);
        !          3954:   if (DEBUGLEVEL >= 1)
        !          3955:     msgtimer("subgroupcoset.");
        !          3956:   if (DEBUGLEVEL >= 6)
        !          3957:     fprintferr("Subcyclo: orbit=%Z\n",O);
        !          3958:   if (lg(O)==1 || lg(O[1])==2)
        !          3959:   {
        !          3960:     avma=ltop;
        !          3961:     return gscycloconductor(cyclo(n,v),n,flag);
        !          3962:   }
        !          3963:   u=lg(O)-1;o=lg(O[1])-1;
        !          3964:   if (DEBUGLEVEL >= 4)
        !          3965:     fprintferr("Subcyclo: %ld orbits with %ld elements each\n",u,o);
        !          3966:   l=stoi(n+1);e=1;
        !          3967:   while(!isprime(l))
        !          3968:   {
        !          3969:     l=addis(l,n);
        !          3970:     e++;
        !          3971:   }
        !          3972:   if (DEBUGLEVEL >= 4)
        !          3973:     fprintferr("Subcyclo: prime l=%Z\n",l);
        !          3974:   av=avma;
        !          3975:   /*Borne utilise':
        !          3976:     Vecmax(Vec((x+o)^u)=max{binome(u,i)*o^i ;1<=i<=u}
        !          3977:   */
        !          3978:   i=u-(1+u)/(1+o);
        !          3979:   borne=mulii(binome(stoi(u),i),gpowgs(stoi(o),i));
        !          3980:   if (DEBUGLEVEL >= 4)
        !          3981:     fprintferr("Subcyclo: borne=%Z\n",borne);
        !          3982:   val=mylogint(shifti(borne,1),l);
        !          3983:   avma=av;
        !          3984:   if (DEBUGLEVEL >= 4)
        !          3985:     fprintferr("Subcyclo: val=%ld\n",val);
        !          3986:   le=gpowgs(l,val);
        !          3987:   z=lift(gpowgs(gener(l),e));
        !          3988:   z=padicsqrtnlift(gun,stoi(n),z,l,val);
        !          3989:   if (DEBUGLEVEL >= 1)
        !          3990:     msgtimer("padicsqrtnlift.");
        !          3991:   powz = cgetg(n,t_VEC); powz[1] = (long)z;
        !          3992:   for (i=2; i<n; i++) powz[i] = lmodii(mulii(z,(GEN)powz[i-1]),le);
        !          3993:   if (DEBUGLEVEL >= 1)
        !          3994:     msgtimer("computing roots.");
        !          3995:   g=cgetg(u+1,t_VEC);
        !          3996:   for(i=1;i<=u;i++)
        !          3997:   {
        !          3998:     GEN s;
        !          3999:     s=gzero;
        !          4000:     for(j=1;j<=o;j++)
        !          4001:       s=addii(s,(GEN)powz[mael(O,i,j)]);
        !          4002:     g[i]=(long)modii(negi(s),le);
        !          4003:   }
        !          4004:   if (DEBUGLEVEL >= 1)
        !          4005:     msgtimer("computing new roots.");
        !          4006:   g=FpV_roots_to_pol(g,le,v);
        !          4007:   if (DEBUGLEVEL >= 1)
        !          4008:     msgtimer("computing products.");
        !          4009:   g=FpX_center(g,le);
        !          4010:   return gerepileupto(ltop,gscycloconductor(g,n,flag));
        !          4011: }

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