Annotation of OpenXM_contrib/pari/src/basemath/galconj.c, Revision 1.1
1.1 ! maekawa 1: /*************************************************************************/
! 2: /** **/
! 3: /** GALOIS CONJUGATES **/
! 4: /** **/
! 5: /*************************************************************************/
! 6: /* $Id: galconj.c,v 1.8 1999/09/23 17:50:56 karim Exp $ */
! 7: #include "pari.h"
! 8: GEN
! 9: galoisconj(GEN nf)
! 10: {
! 11: GEN x, y, z;
! 12: long i, lz, lx, v, av = avma;
! 13: nf = checknf(nf);
! 14: x = (GEN) nf[1];
! 15: v = varn(x);
! 16: lx = lgef(x) - 2;
! 17: if (v == 0)
! 18: nf = gsubst(nf, 0, polx[MAXVARN]);
! 19: else
! 20: {
! 21: x = dummycopy(x);
! 22: setvarn(x, 0);
! 23: }
! 24: z = nfroots(nf, x);
! 25: lz = lg(z);
! 26: y = cgetg(lz, t_COL);
! 27: for (i = 1; i < lz; i++)
! 28: {
! 29: GEN p1 = lift((GEN) z[i]);
! 30: setvarn(p1, v);
! 31: y[i] = (long) p1;
! 32: }
! 33: return gerepileupto(av, y);
! 34: }
! 35: /* nbmax: maximum number of possible conjugates */
! 36: GEN
! 37: galoisconj2pol(GEN x, long nbmax, long prec)
! 38: {
! 39: long av = avma, i, n, v, nbauto;
! 40: GEN y, w, polr, p1, p2;
! 41: n = lgef(x) - 3;
! 42: if (n <= 0)
! 43: return cgetg(1, t_VEC);
! 44: if (gisirreducible(x) == gzero)
! 45: err(redpoler, "galoisconj2pol");
! 46: polr = roots(x, prec);
! 47: p1 = (GEN) polr[1];
! 48: nbauto = 1;
! 49: prec = (long) (bit_accuracy(prec) * L2SL10 * 0.75);
! 50: w = cgetg(n + 2, t_VEC);
! 51: w[1] = un;
! 52: for (i = 2; i <= n; i++)
! 53: w[i] = lmul(p1, (GEN) w[i - 1]);
! 54: v = varn(x);
! 55: y = cgetg(nbmax + 1, t_COL);
! 56: y[1] = (long) polx[v];
! 57: for (i = 2; i <= n && nbauto < nbmax; i++)
! 58: {
! 59: w[n + 1] = polr[i];
! 60: p1 = lindep2(w, prec);
! 61: if (signe(p1[n + 1]))
! 62: {
! 63: setlg(p1, n + 1);
! 64: p2 = gdiv(gtopolyrev(p1, v), negi((GEN) p1[n + 1]));
! 65: if (gdivise(poleval(x, p2), x))
! 66: {
! 67: y[++nbauto] = (long) p2;
! 68: if (DEBUGLEVEL > 1)
! 69: fprintferr("conjugate %ld: %Z\n", i, y[nbauto]);
! 70: }
! 71: }
! 72: }
! 73: setlg(y, 1 + nbauto);
! 74: return gerepileupto(av, gen_sort(y, 0, cmp_pol));
! 75: }
! 76: GEN
! 77: galoisconj2(GEN nf, long nbmax, long prec)
! 78: {
! 79: long av = avma, i, j, n, r1, ru, nbauto;
! 80: GEN x, y, w, polr, p1, p2;
! 81: if (typ(nf) == t_POL)
! 82: return galoisconj2pol(nf, nbmax, prec);
! 83: nf = checknf(nf);
! 84: x = (GEN) nf[1];
! 85: n = lgef(x) - 3;
! 86: if (n <= 0)
! 87: return cgetg(1, t_VEC);
! 88: r1 = itos(gmael(nf, 2, 1));
! 89: p1 = (GEN) nf[6];
! 90: prec = precision((GEN) p1[1]);
! 91: /* accuracy in decimal digits */
! 92: prec = (long) (bit_accuracy(prec) * L2SL10 * 0.75);
! 93: ru = (n + r1) >> 1;
! 94: nbauto = 1;
! 95: polr = cgetg(n + 1, t_VEC);
! 96: for (i = 1; i <= r1; i++)
! 97: polr[i] = p1[i];
! 98: for (j = i; i <= ru; i++)
! 99: {
! 100: polr[j++] = p1[i];
! 101: polr[j++] = lconj((GEN) p1[i]);
! 102: }
! 103: p2 = gmael(nf, 5, 1);
! 104: w = cgetg(n + 2, t_VEC);
! 105: for (i = 1; i <= n; i++)
! 106: w[i] = coeff(p2, 1, i);
! 107: y = cgetg(nbmax + 1, t_COL);
! 108: y[1] = (long) polx[varn(x)];
! 109: for (i = 2; i <= n && nbauto < nbmax; i++)
! 110: {
! 111: w[n + 1] = polr[i];
! 112: p1 = lindep2(w, prec);
! 113: if (signe(p1[n + 1]))
! 114: {
! 115: setlg(p1, n + 1);
! 116: settyp(p1, t_COL);
! 117: p2 = gdiv(gmul((GEN) nf[7], p1), negi((GEN) p1[n + 1]));
! 118: if (gdivise(poleval(x, p2), x))
! 119: {
! 120: y[++nbauto] = (long) p2;
! 121: if (DEBUGLEVEL > 1)
! 122: fprintferr("conjugate %ld: %Z\n", i, y[nbauto]);
! 123: }
! 124: }
! 125: }
! 126: setlg(y, 1 + nbauto);
! 127: return gerepileupto(av, gen_sort(y, 0, cmp_pol));
! 128: }
! 129: /*************************************************************************/
! 130: /** **/
! 131: /** GALOIS4 **/
! 132: /** **/
! 133: /** **/
! 134: /** **/
! 135: /*************************************************************************/
! 136: struct galois_lift
! 137: {
! 138: GEN T;
! 139: GEN den;
! 140: GEN p;
! 141: GEN borne;
! 142: GEN L;
! 143: long e;
! 144: GEN Q;
! 145: };
! 146: /* Initialise la structure galois_lift */
! 147: void
! 148: initlift(GEN T, GEN den, GEN p, GEN borne, GEN L, struct galois_lift * gl)
! 149: {
! 150: ulong ltop, lbot;
! 151: gl->T = T;
! 152: gl->den = den;
! 153: gl->p = p;
! 154: gl->borne = borne;
! 155: gl->L = L;
! 156: ltop = avma;
! 157: gl->e = itos(gmax(gdeux, gceil(gdiv(glog(gmul2n(borne, 1), DEFAULTPREC),
! 158: glog(p, DEFAULTPREC)))));
! 159: lbot = avma;
! 160: gl->Q = gpowgs(p, gl->e);
! 161: gl->Q = gerepile(ltop, lbot, gl->Q);
! 162: }
! 163: /*
! 164: * T est le polynome \sum t_i*X^i S est un Polmod T Retourne un vecteur Spow
! 165: * verifiant la condition: i>=1 et t_i!=0 ==> Spow[i]=S^(i-1)*t_i Essaie
! 166: * d'etre efficace sur les polynomes lacunaires
! 167: */
! 168: GEN
! 169: compoTS(GEN T, GEN S)
! 170: {
! 171: GEN Spow;
! 172: int i;
! 173: Spow = cgetg(lgef(T) - 2, t_VEC);
! 174: for (i = 3; i < lg(Spow); i++)
! 175: Spow[i] = 0;
! 176: Spow[1] = un;
! 177: Spow[2] = (long) S;
! 178: for (i = 2; i < lg(Spow) - 1; i++)
! 179: {
! 180: if (!gcmp0((GEN) T[i + 3]))
! 181: for (;;)
! 182: {
! 183: int k, l;
! 184: for (k = 1; k <= (i >> 1); k++)
! 185: if (Spow[k + 1] && Spow[i - k + 1])
! 186: break;
! 187: if ((k << 1) < i)
! 188: {
! 189: Spow[i + 1] = lmul((GEN) Spow[k + 1], (GEN) Spow[i - k + 1]);
! 190: break;
! 191: } else if ((k << 1) == i) /* En esperant que sqr est plus
! 192: * rapide... */
! 193: {
! 194: Spow[i + 1] = lsqr((GEN) Spow[k + 1]);
! 195: break;
! 196: }
! 197: for (k = i - 1; k > 0; k--)
! 198: if (Spow[k + 1])
! 199: break;
! 200: if ((k << 1) < i)
! 201: {
! 202: Spow[(k << 1) + 1] = lsqr((GEN) Spow[k + 1]);
! 203: continue;
! 204: }
! 205: for (l = i - k; l > 0; l--)
! 206: if (Spow[l + 1])
! 207: break;
! 208: if (Spow[i - l - k + 1])
! 209: Spow[i - k + 1] = lmul((GEN) Spow[i - l - k + 1], (GEN) Spow[l + 1]);
! 210: else
! 211: Spow[l + k + 1] = lmul((GEN) Spow[k + 1], (GEN) Spow[l + 1]);
! 212: }
! 213: }
! 214: for (i = 1; i < lg(Spow); i++)
! 215: if (!gcmp0((GEN) T[i + 2]))
! 216: Spow[i] = lmul((GEN) Spow[i], (GEN) T[i + 2]);
! 217: return Spow;
! 218: }
! 219: /*
! 220: * Calcule T(S) a l'aide du vecteur Spow
! 221: */
! 222: static GEN
! 223: calcTS(GEN Spow, GEN T, GEN S)
! 224: {
! 225: GEN res = gzero;
! 226: int i;
! 227: for (i = 1; i < lg(Spow); i++)
! 228: if (!gcmp0((GEN) T[i + 2]))
! 229: res = gadd(res, (GEN) Spow[i]);
! 230: res = gmul(res, S);
! 231: return gadd(res, (GEN) T[2]);
! 232: }
! 233: /*
! 234: * Calcule T'(S) a l'aide du vecteur Spow
! 235: */
! 236: static GEN
! 237: calcderivTS(GEN Spow, GEN T, GEN mod)
! 238: {
! 239: GEN res = gzero;
! 240: int i;
! 241: for (i = 1; i < lg(Spow); i++)
! 242: if (!gcmp0((GEN) T[i + 2]))
! 243: res = gadd(res, gmul((GEN) Spow[i], stoi(i)));
! 244: res = gmul(lift(lift(res)), mod);
! 245: return gmodulcp(res, T);
! 246: }
! 247: /*
! 248: * Verifie que S est une solution presque surement et calcule sa permutation
! 249: */
! 250: static int
! 251: poltopermtest(GEN f, GEN L, GEN pf)
! 252: {
! 253: ulong ltop;
! 254: GEN fx, fp;
! 255: int i, j;
! 256: fp = cgetg(lg(L), t_VECSMALL);
! 257: ltop = avma;
! 258: for (i = 1; i < lg(fp); i++)
! 259: fp[i] = 1;
! 260: for (i = 1; i < lg(L); i++)
! 261: {
! 262: fx = gsubst(f, varn(f), (GEN) L[i]);
! 263: for (j = 1; j < lg(L); j++)
! 264: if (fp[j] && gegal(fx, (GEN) L[j]))
! 265: {
! 266: pf[i] = j;
! 267: fp[j] = 0;
! 268: break;
! 269: }
! 270: if (j == lg(L))
! 271: return 0;
! 272: avma = ltop;
! 273: }
! 274: return 1;
! 275: }
! 276: /*
! 277: * Soit T un polynome de \ZZ[X] , p un nombre premier , S\in\FF_p[X]/(T) tel
! 278: * que T(S)=0 [p,T] Relever S en S_0 tel que T(S_0)=0 [T,p^e]
! 279: */
! 280: GEN
! 281: automorphismlift(GEN S, struct galois_lift * gl)
! 282: {
! 283: ulong ltop, lbot;
! 284: long x;
! 285: GEN q, mod, modold;
! 286: GEN W, Tr, Sr, Wr = gzero, Trold, Spow;
! 287: int flag, init, ex;
! 288: GEN *gptr[2];
! 289: if (DEBUGLEVEL >= 1)
! 290: timer2();
! 291: x = varn(gl->T);
! 292: Tr = gmul(gl->T, gmodulcp(gun, gl->p));
! 293: W = ginv(gsubst(deriv(Tr, x), x, S));
! 294: q = gl->p;
! 295: modold = gl->p;
! 296: Trold = Tr;
! 297: ex = 1;
! 298: flag = 1;
! 299: init = 0;
! 300: gptr[0] = &S;
! 301: gptr[1] = &Wr;
! 302: while (flag)
! 303: {
! 304: if (DEBUGLEVEL >= 1)
! 305: timer2();
! 306: q = gsqr(q);
! 307: ex <<= 1;
! 308: if (ex >= gl->e)
! 309: {
! 310: flag = 0;
! 311: q = gl->Q;
! 312: ex = gl->e;
! 313: }
! 314: mod = gmodulcp(gun, q);
! 315: Tr = gmul(gl->T, mod);
! 316: ltop = avma;
! 317: Sr = gmodulcp(gmul(lift(lift(S)), mod), Tr);
! 318: Spow = compoTS(Tr, Sr);
! 319: if (init)
! 320: W = gmul(Wr, gsub(gdeux, gmul(Wr, calcderivTS(Spow, Trold, modold))));
! 321: else
! 322: init = 1;
! 323: Wr = gmodulcp(gmul(lift(lift(W)), mod), Tr);
! 324: S = gmul(Wr, calcTS(Spow, Tr, Sr));
! 325: lbot = avma;
! 326: Wr = gcopy(Wr);
! 327: S = gsub(Sr, S);
! 328: gerepilemanysp(ltop, lbot, gptr, 2);
! 329: modold = mod;
! 330: Trold = Tr;
! 331: }
! 332: if (DEBUGLEVEL >= 1)
! 333: msgtimer("automorphismlift()");
! 334: return S;
! 335: }
! 336: struct galois_testlift
! 337: {
! 338: long n;
! 339: long f;
! 340: long g;
! 341: GEN bezoutcoeff;
! 342: GEN pauto;
! 343: };
! 344: /*
! 345: * Si polb est un polynomes de Z[X] et pola un facteur modulo p, retourne b*v
! 346: * telqu' il existe u et a tel que: a=pola [mod p] a*b=polb [mod p^e]
! 347: * b*v+a*u=1 [mod p^e]
! 348: */
! 349: GEN
! 350: bezout_lift_fact(GEN pola, GEN polb, GEN p, GEN pev, long e)
! 351: {
! 352: long ev;
! 353: GEN ae, be, u, v, ae2, be2, s, t, pe, pe2, z, g;
! 354: long ltop = avma, lbot;
! 355: if (DEBUGLEVEL >= 1)
! 356: timer2();
! 357: ae = lift(pola);
! 358: be = Fp_poldivres(polb, ae, p, NULL);
! 359: g = (GEN) Fp_pol_extgcd(ae, be, p, &u, &v)[2]; /* deg g = 0 */
! 360: if (!gcmp1(g))
! 361: {
! 362: g = mpinvmod(g, p);
! 363: u = gmul(u, g);
! 364: v = gmul(v, g);
! 365: }
! 366: for (pe = p, ev = 1; ev < e;)
! 367: {
! 368: ev <<= 1;
! 369: pe2 = (ev >= e) ? pev : sqri(pe);
! 370: g = gadd(polb, gneg_i(gmul(ae, be)));
! 371: g = Fp_pol_red(g, pe2);
! 372: g = gdivexact(g, pe);
! 373: z = Fp_pol_red(gmul(v, g), pe);
! 374: t = Fp_poldivres(z, ae, pe, &s);
! 375: t = gadd(gmul(u, g), gmul(t, be));
! 376: t = Fp_pol_red(t, pe);
! 377: be2 = gadd(be, gmul(t, pe));
! 378: ae2 = gadd(ae, gmul(s, pe));/* already reduced mod pe2 */
! 379: g = gadd(gun, gneg_i(gadd(gmul(u, ae2), gmul(v, be2))));
! 380: g = Fp_pol_red(g, pe2);
! 381: g = gdivexact(g, pe);
! 382: z = Fp_pol_red(gmul(v, g), pe);
! 383: t = Fp_poldivres(z, ae, pe, &s);
! 384: t = gadd(gmul(u, g), gmul(t, be));
! 385: t = Fp_pol_red(t, pe);
! 386: u = gadd(u, gmul(t, pe));
! 387: v = gadd(v, gmul(s, pe));
! 388: pe = pe2;
! 389: ae = ae2;
! 390: be = be2;
! 391: }
! 392: lbot = avma;
! 393: g = gmul(v, be);
! 394: g = gerepile(ltop, lbot, g);
! 395: if (DEBUGLEVEL >= 1)
! 396: msgtimer("bezout_lift_fact()");
! 397: return g;
! 398: }
! 399: static long
! 400: inittestlift(GEN Tmod, long elift, struct galois_lift * gl, struct galois_testlift * gt, GEN frob)
! 401: {
! 402: ulong ltop = avma;
! 403: int i, j;
! 404: long v;
! 405: GEN pe, autpow, plift;
! 406: GEN Tmodp, xmodp, modQ, TmodQ, xmodQ;
! 407: GEN *gptr[2];
! 408: v = varn(gl->T);
! 409: gt->n = lg(gl->L) - 1;
! 410: gt->g = lg(Tmod) - 1;
! 411: gt->f = gt->n / gt->g;
! 412: Tmodp = gmul(gl->T, gmodulcp(gun, gl->p));
! 413: xmodp = gmodulcp(gmul(polx[v], gmodulcp(gun, gl->p)), Tmodp);
! 414: pe = gpowgs(gl->p, elift);
! 415: plift = automorphismlift(powgi(xmodp, pe), gl);
! 416: if (frob)
! 417: {
! 418: GEN tlift;
! 419: tlift = gdiv(centerlift(gmul((GEN) plift[2], gl->den)), gl->den);
! 420: if (poltopermtest(tlift, gl->L, frob))
! 421: {
! 422: avma = ltop;
! 423: return 1;
! 424: }
! 425: }
! 426: modQ = gmodulcp(gun, gl->Q);
! 427: TmodQ = gmul(gl->T, modQ);
! 428: xmodQ = gmodulcp(gmul(polx[v], modQ), TmodQ);
! 429: gt->bezoutcoeff = cgetg(gt->g + 1, t_VEC);
! 430: for (i = 1; i <= gt->g; i++)
! 431: {
! 432: GEN blift;
! 433: blift = bezout_lift_fact((GEN) Tmod[i], gl->T, gl->p, gl->Q, gl->e);
! 434: gt->bezoutcoeff[i] = (long) gmodulcp(gmul(blift, modQ), TmodQ);
! 435: }
! 436: gt->pauto = cgetg(gt->f + 1, t_VEC);
! 437: gt->pauto[1] = (long) xmodQ;
! 438: gt->pauto[2] = (long) plift;
! 439: if (gt->f > 2)
! 440: {
! 441: autpow = cgetg(gt->n, t_VEC);
! 442: autpow[1] = (long) plift;
! 443: for (i = 2; i < gt->n; i++)
! 444: autpow[i] = lmul((GEN) autpow[i - 1], plift);
! 445: for (i = 3; i <= gt->f; i++)
! 446: {
! 447: GEN s, P;
! 448: P = ((GEN **) gt->pauto)[i - 1][2];
! 449: s = (GEN) P[2];
! 450: for (j = 1; j < lgef(P) - 2; j++)
! 451: s = gadd(s, gmul((GEN) autpow[j], (GEN) P[j + 2]));
! 452: gt->pauto[i] = (long) s;
! 453: }
! 454: }
! 455: gptr[0] = >->bezoutcoeff;
! 456: gptr[1] = >->pauto;
! 457: gerepilemany(ltop, gptr, 2);
! 458: return 0;
! 459: }
! 460: /*
! 461: *
! 462: */
! 463: long
! 464: frobeniusliftall(GEN sg, GEN * psi, struct galois_lift * gl, struct galois_testlift * gt, GEN frob)
! 465: {
! 466: ulong ltop = avma, av, ltop2;
! 467: long d, N, z, m, c;
! 468: int i, j, k;
! 469: GEN pf, u, v;
! 470: m = gt->g;
! 471: c = lg(sg) - 1;
! 472: d = m / c;
! 473: pf = cgetg(m, t_VECSMALL);
! 474: *psi = pf;
! 475: ltop2 = avma;
! 476: N = itos(gdiv(mpfact(m), gmul(stoi(c), gpowgs(mpfact(d), c))));
! 477: avma = ltop2;
! 478: v = gmul((GEN) gt->pauto[2], (GEN) gt->bezoutcoeff[m]);
! 479: for (i = 1; i < m; i++)
! 480: pf[i] = 1 + i / d;
! 481: av = avma;
! 482: for (i = 0;; i++)
! 483: {
! 484: u = v;
! 485: if (DEBUGLEVEL >= 4)
! 486: {
! 487: fprintferr("GaloisConj:Testing %Z:%d:%Z:", sg, i, pf);
! 488: timer2();
! 489: }
! 490: for (j = 1; j < m; j++)
! 491: u = gadd(u, gmul((GEN) gt->pauto[sg[pf[j]] + 1], (GEN) gt->bezoutcoeff[j]));
! 492: u = gdiv(centerlift(gmul((GEN) u[2], gl->den)), gl->den);
! 493: if (poltopermtest(u, gl->L, frob))
! 494: {
! 495: if (DEBUGLEVEL >= 4)
! 496: msgtimer("");
! 497: avma = ltop2;
! 498: return 1;
! 499: }
! 500: if (DEBUGLEVEL >= 4)
! 501: msgtimer("");
! 502: avma = av;
! 503: if (i == N - 1)
! 504: break;
! 505: for (j = 2; j < m && pf[j - 1] >= pf[j]; j++);
! 506: for (k = 1; k < j - k && pf[k] != pf[j - k]; k++)
! 507: {
! 508: z = pf[k];
! 509: pf[k] = pf[j - k];
! 510: pf[j - k] = z;
! 511: }
! 512: for (k = j - 1; pf[k] >= pf[j]; k--);
! 513: z = pf[j];
! 514: pf[j] = pf[k];
! 515: pf[k] = z;
! 516: }
! 517: avma = ltop;
! 518: *psi = NULL;
! 519: return 0;
! 520: }
! 521: /*
! 522: * applique une permutation t a un vecteur s sans duplication
! 523: */
! 524: static GEN
! 525: applyperm(GEN s, GEN t)
! 526: {
! 527: GEN u;
! 528: int i;
! 529: if (lg(s) < lg(t))
! 530: err(talker, "First permutation shorter than second in applyperm");
! 531: u = cgetg(lg(s), typ(s));
! 532: for (i = 1; i < lg(s); i++)
! 533: u[i] = s[t[i]];
! 534: return u;
! 535: }
! 536: /*
! 537: * alloue une ardoise pour n entiers de longueurs pour les test de
! 538: * permutation
! 539: */
! 540: GEN
! 541: alloue_ardoise(long n, long s)
! 542: {
! 543: GEN ar;
! 544: long i;
! 545: ar = cgetg(n + 1, t_VEC);
! 546: for (i = 1; i <= n; i++)
! 547: ar[i] = lgetg(s, t_INT);
! 548: return ar;
! 549: }
! 550: /*
! 551: * structure contenant toutes les données pour le tests des permutations:
! 552: *
! 553: * ordre :ordre des tests pour verifie_test ordre[lg(ordre)]: numero du test
! 554: * principal borne : borne sur les coefficients a trouver ladic: modulo
! 555: * l-adique des racines lborne:ladic-borne TM:vecteur des ligne de M
! 556: * PV:vecteur des clones des matrices de test (Vmatrix) (ou NULL si non
! 557: * calcule) L,M comme d'habitude (voir plus bas)
! 558: */
! 559: struct galois_test
! 560: {
! 561: GEN ordre;
! 562: GEN borne, lborne, ladic;
! 563: GEN PV, TM;
! 564: GEN L, M;
! 565: };
! 566: /* Calcule la matrice de tests correspondant a la n-ieme ligne de V */
! 567: static GEN
! 568: Vmatrix(long n, struct galois_test * td)
! 569: {
! 570: ulong ltop = avma, lbot;
! 571: GEN V;
! 572: long i;
! 573: V = cgetg(lg(td->L), t_VEC);
! 574: for (i = 1; i < lg(V); i++)
! 575: V[i] = ((GEN **) td->M)[i][n][2];
! 576: V = centerlift(gmul(td->L, V));
! 577: lbot = avma;
! 578: V = gmod(V, td->ladic);
! 579: return gerepile(ltop, lbot, V);
! 580: }
! 581: /*
! 582: * Initialise la structure galois_test
! 583: */
! 584: static void
! 585: inittest(GEN L, GEN M, GEN borne, GEN ladic, struct galois_test * td)
! 586: {
! 587: ulong ltop;
! 588: long i;
! 589: int n = lg(L) - 1;
! 590: if (DEBUGLEVEL >= 8)
! 591: fprintferr("GaloisConj:Entree Init Test\n");
! 592: td->ordre = cgetg(n + 1, t_VECSMALL);
! 593: for (i = 1; i <= n - 2; i++)
! 594: td->ordre[i] = i + 2;
! 595: for (; i <= n; i++)
! 596: td->ordre[i] = i - n + 2;
! 597: td->borne = borne;
! 598: td->lborne = gsub(ladic, borne);
! 599: td->ladic = ladic;
! 600: td->L = L;
! 601: td->M = M;
! 602: td->PV = cgetg(n + 1, t_VECSMALL); /* peut-etre t_VEC est correct ici */
! 603: for (i = 1; i <= n; i++)
! 604: td->PV[i] = 0;
! 605: ltop = avma;
! 606: td->PV[td->ordre[n]] = (long) gclone(Vmatrix(td->ordre[n], td));
! 607: avma = ltop;
! 608: td->TM = gtrans(M);
! 609: settyp(td->TM, t_VEC);
! 610: for (i = 1; i < lg(td->TM); i++)
! 611: settyp(td->TM[i], t_VEC);
! 612: if (DEBUGLEVEL >= 8)
! 613: fprintferr("GaloisConj:Sortie Init Test\n");
! 614: }
! 615: /*
! 616: * liberer les clones de la structure galois_test
! 617: *
! 618: * Reservé a l'accreditation ultra-violet:Liberez les clones! Paranoia(tm)
! 619: */
! 620: static void
! 621: freetest(struct galois_test * td)
! 622: {
! 623: int i;
! 624: for (i = 1; i < lg(td->PV); i++)
! 625: if (td->PV[i])
! 626: {
! 627: gunclone((GEN) td->PV[i]);
! 628: td->PV[i] = 0;
! 629: }
! 630: }
! 631: /*
! 632: * Test si le nombre padique P est proche d'un entier inferieur a td->borne
! 633: * en valeur absolue.
! 634: */
! 635: long
! 636: padicisint(GEN P, struct galois_test * td)
! 637: {
! 638: long r;
! 639: ulong ltop = avma;
! 640: GEN U;
! 641: if (typ(P) != t_INT)
! 642: err(typeer, "padicisint");
! 643: U = modii(P, td->ladic);
! 644: r = gcmp(U, (GEN) td->borne) <= 0 || gcmp(U, (GEN) td->lborne) >= 0;
! 645: avma = ltop;
! 646: return r;
! 647: }
! 648: /*
! 649: * Verifie si pf est une vrai solution et non pas un "hop"
! 650: */
! 651: static long
! 652: verifietest(GEN pf, struct galois_test * td)
! 653: {
! 654: ulong av = avma;
! 655: GEN P, V;
! 656: int i, j;
! 657: int n = lg(td->L) - 1;
! 658: if (DEBUGLEVEL >= 8)
! 659: fprintferr("GaloisConj:Entree Verifie Test\n");
! 660: P = applyperm(td->L, pf);
! 661: for (i = 1; i < n; i++)
! 662: {
! 663: long ord;
! 664: GEN PW;
! 665: ord = td->ordre[i];
! 666: PW = (GEN) td->PV[ord];
! 667: if (PW)
! 668: {
! 669: V = ((GEN **) PW)[1][pf[1]];
! 670: for (j = 2; j <= n; j++)
! 671: V = gadd(V, ((GEN **) PW)[j][pf[j]]);
! 672: } else
! 673: V = centerlift(gmul((GEN) td->TM[ord], P));
! 674: if (!padicisint(V, td))
! 675: break;
! 676: }
! 677: if (i == n)
! 678: {
! 679: if (DEBUGLEVEL >= 8)
! 680: fprintferr("GaloisConj:Sortie Verifie Test:1\n");
! 681: avma = av;
! 682: return 1;
! 683: }
! 684: if (!td->PV[td->ordre[i]])
! 685: {
! 686: td->PV[td->ordre[i]] = (long) gclone(Vmatrix(td->ordre[i], td));
! 687: if (DEBUGLEVEL >= 2)
! 688: fprintferr("M");
! 689: }
! 690: if (DEBUGLEVEL >= 2)
! 691: fprintferr("%d.", i);
! 692: if (i > 1)
! 693: {
! 694: long z;
! 695: z = td->ordre[i];
! 696: for (j = i; j > 1; j--)
! 697: td->ordre[j] = td->ordre[j - 1];
! 698: td->ordre[1] = z;
! 699: if (DEBUGLEVEL >= 6)
! 700: fprintferr("%Z", td->ordre);
! 701: }
! 702: if (DEBUGLEVEL >= 8)
! 703: fprintferr("GaloisConj:Sortie Verifie Test:0\n");
! 704: avma = av;
! 705: return 0;
! 706: }
! 707: /*
! 708: * F est la decomposition en cycle de sigma, B est la decomposition en cycle
! 709: * de cl(tau) Teste toutes les permutations pf pouvant correspondre a tau tel
! 710: * que : tau*sigma*tau^-1=sigma^s et tau^d=sigma^t ou d est l'ordre de
! 711: * cl(tau) --------- x: vecteur des choix y: vecteur des mises a jour G:
! 712: * vecteur d'acces a F linéaire
! 713: */
! 714: GEN
! 715: testpermutation(GEN F, GEN B, long s, long t, long cut, struct galois_test * td)
! 716: {
! 717: ulong av, avm = avma, av2;
! 718: long a, b, c, d, n;
! 719: GEN pf, x, ar, y, *G;
! 720: int N, cx, p1, p2, p3, p4, p5, p6;
! 721: int i, j, hop = 0;
! 722: GEN V, W;
! 723: if (DEBUGLEVEL >= 1)
! 724: timer2();
! 725: a = lg(F) - 1;
! 726: b = lg(F[1]) - 1;
! 727: c = lg(B) - 1;
! 728: d = lg(B[1]) - 1;
! 729: n = a * b;
! 730: s = (b + s) % b;
! 731: pf = cgetg(n + 1, t_VECSMALL);
! 732: av = avma;
! 733: ar = alloue_ardoise(a, 1 + lg(td->ladic));
! 734: x = cgetg(a + 1, t_VECSMALL);
! 735: y = cgetg(a + 1, t_VECSMALL);
! 736: G = (GEN *) cgetg(a + 1, t_VECSMALL); /* Don't worry */
! 737: av2 = avma;
! 738: W = (GEN) td->PV[td->ordre[n]];
! 739: for (cx = 1, i = 1, j = 1; cx <= a; cx++, i++)
! 740: {
! 741: x[cx] = (i != d) ? 0 : t;
! 742: y[cx] = 1;
! 743: G[cx] = (GEN) F[((long **) B)[j][i]]; /* Be happy */
! 744: if (i == d)
! 745: {
! 746: i = 0;
! 747: j++;
! 748: }
! 749: } /* Be happy now! */
! 750: N = itos(gpowgs(stoi(b), c * (d - 1))) / cut;
! 751: avma = av2;
! 752: if (DEBUGLEVEL >= 4)
! 753: fprintferr("GaloisConj:I will try %d permutations\n", N);
! 754: for (cx = 0; cx < N; cx++)
! 755: {
! 756: if (DEBUGLEVEL >= 2 && cx % 1000 == 999)
! 757: fprintferr("%d%% ", (100 * cx) / N);
! 758: if (cx)
! 759: {
! 760: for (i = 1, j = d; i < a;)
! 761: {
! 762: y[i] = 1;
! 763: if ((++(x[i])) != b)
! 764: break;
! 765: x[i++] = 0;
! 766: if (i == j)
! 767: {
! 768: y[i++] = 1;
! 769: j += d;
! 770: }
! 771: }
! 772: y[i + 1] = 1;
! 773: }
! 774: for (p1 = 1, p5 = d; p1 <= a; p1++, p5++)
! 775: if (y[p1])
! 776: {
! 777: if (p5 == d)
! 778: {
! 779: p5 = 0;
! 780: p4 = 0;
! 781: } else
! 782: p4 = x[p1 - 1];
! 783: if (p5 == d - 1)
! 784: p6 = p1 + 1 - d;
! 785: else
! 786: p6 = p1 + 1;
! 787: y[p1] = 0;
! 788: V = gzero;
! 789: for (p2 = 1 + p4, p3 = 1 + x[p1]; p2 <= b; p2++)
! 790: {
! 791: V = gadd(V, ((GEN **) W)[G[p6][p3]][G[p1][p2]]);
! 792: p3 += s;
! 793: if (p3 > b)
! 794: p3 -= b;
! 795: }
! 796: p3 = 1 + x[p1] - s;
! 797: if (p3 <= 0)
! 798: p3 += b;
! 799: for (p2 = p4; p2 >= 1; p2--)
! 800: {
! 801: V = gadd(V, ((GEN **) W)[G[p6][p3]][G[p1][p2]]);
! 802: p3 -= s;
! 803: if (p3 <= 0)
! 804: p3 += b;
! 805: }
! 806: gaffect((GEN) V, (GEN) ar[p1]);
! 807: }
! 808: V = gzero;
! 809: for (p1 = 1; p1 <= a; p1++)
! 810: V = gadd(V, (GEN) ar[p1]);
! 811: if (padicisint(V, td))
! 812: {
! 813: for (p1 = 1, p5 = d; p1 <= a; p1++, p5++)
! 814: {
! 815: if (p5 == d)
! 816: {
! 817: p5 = 0;
! 818: p4 = 0;
! 819: } else
! 820: p4 = x[p1 - 1];
! 821: if (p5 == d - 1)
! 822: p6 = p1 + 1 - d;
! 823: else
! 824: p6 = p1 + 1;
! 825: for (p2 = 1 + p4, p3 = 1 + x[p1]; p2 <= b; p2++)
! 826: {
! 827: pf[G[p1][p2]] = G[p6][p3];
! 828: p3 += s;
! 829: if (p3 > b)
! 830: p3 -= b;
! 831: }
! 832: p3 = 1 + x[p1] - s;
! 833: if (p3 <= 0)
! 834: p3 += b;
! 835: for (p2 = p4; p2 >= 1; p2--)
! 836: {
! 837: pf[G[p1][p2]] = G[p6][p3];
! 838: p3 -= s;
! 839: if (p3 <= 0)
! 840: p3 += b;
! 841: }
! 842: }
! 843: if (verifietest(pf, td))
! 844: {
! 845: avma = av;
! 846: if (DEBUGLEVEL >= 1)
! 847: msgtimer("testpermutation(%d)", cx + 1);
! 848: if (DEBUGLEVEL >= 2 && hop)
! 849: fprintferr("GaloisConj:%d hop sur %d iterations\n", hop, cx + 1);
! 850: return pf;
! 851: } else
! 852: hop++;
! 853: }
! 854: avma = av2;
! 855: }
! 856: avma = avm;
! 857: if (DEBUGLEVEL >= 1)
! 858: msgtimer("testpermutation(%d)", N);
! 859: if (DEBUGLEVEL >= 2 && hop)
! 860: fprintferr("GaloisConj:%d hop sur %d iterations\n", hop, N);
! 861: return gzero;
! 862: }
! 863: /*
! 864: * Calcule la liste des sous groupes de \ZZ/m\ZZ d'ordre divisant p et
! 865: * retourne la liste de leurs elements
! 866: */
! 867: GEN
! 868: listsousgroupes(long m, long p)
! 869: {
! 870: ulong ltop = avma, lbot;
! 871: GEN zns, lss, res, sg, gen, ord, res1;
! 872: int k, card, i, j, l, n, phi, h;
! 873: if (m == 2)
! 874: {
! 875: res = cgetg(2, t_VEC);
! 876: sg = cgetg(2, t_VECSMALL);
! 877: res[1] = (long) sg;
! 878: sg[1] = 1;
! 879: return res;
! 880: }
! 881: zns = znstar(stoi(m));
! 882: phi = itos((GEN) zns[1]);
! 883: lss = subgrouplist((GEN) zns[2], 0);
! 884: gen = cgetg(lg(zns[3]), t_VECSMALL);
! 885: ord = cgetg(lg(zns[3]), t_VECSMALL);
! 886: res1 = cgetg(lg(lss), t_VECSMALL);
! 887: lbot = avma;
! 888: for (k = 1, i = lg(lss) - 1; i >= 1; i--)
! 889: {
! 890: long av;
! 891: av = avma;
! 892: card = phi / itos(det((GEN) lss[i]));
! 893: avma = av;
! 894: if (p % card == 0)
! 895: {
! 896: sg = cgetg(1 + card, t_VECSMALL);
! 897: sg[1] = 1;
! 898: av = avma;
! 899: for (j = 1; j < lg(gen); j++)
! 900: {
! 901: gen[j] = 1;
! 902: for (h = 1; h < lg(lss[i]); h++)
! 903: gen[j] = (gen[j] * itos(lift(powgi(((GEN **) zns)[3][h],
! 904: ((GEN ***) lss)[i][j][h])))) % m;
! 905: ord[j] = itos(((GEN **) zns)[2][j]) / itos(((GEN ***) lss)[i][j][j]);
! 906: }
! 907: avma = av;
! 908: for (j = 1, l = 1; j < lg(gen); j++)
! 909: {
! 910: int c = l * (ord[j] - 1);
! 911: for (n = 1; n <= c; n++)/* I like it */
! 912: sg[++l] = (sg[n] * gen[j]) % m;
! 913: }
! 914: res1[k++] = (long) sg;
! 915: }
! 916: }
! 917: res = cgetg(k, t_VEC);
! 918: for (i = 1; i < k; i++)
! 919: res[i] = res1[i];
! 920: return gerepile(ltop, lbot, res);
! 921: }
! 922: /* retourne la permutation identite */
! 923: GEN
! 924: permidentity(long l)
! 925: {
! 926: GEN perm;
! 927: int i;
! 928: perm = cgetg(l + 1, t_VECSMALL);
! 929: for (i = 1; i <= l; i++)
! 930: perm[i] = i;
! 931: return perm;
! 932: }
! 933: /* retourne la decomposition en cycle */
! 934: GEN
! 935: permtocycle(GEN p)
! 936: {
! 937: long ltop = avma, lbot;
! 938: int i, j, k, l, m;
! 939: GEN bit, cycle, cy;
! 940: cycle = cgetg(lg(p), t_VEC);
! 941: bit = cgetg(lg(p), t_VECSMALL);
! 942: for (i = 1; i < lg(p); i++)
! 943: bit[i] = 0;
! 944: for (k = 1, l = 1; k < lg(p);)
! 945: {
! 946: for (j = 1; bit[j]; j++);
! 947: cy = cgetg(lg(p), t_VECSMALL);
! 948: m = 1;
! 949: do
! 950: {
! 951: bit[j] = 1;
! 952: k++;
! 953: cy[m++] = j;
! 954: j = p[j];
! 955: } while (!bit[j]);
! 956: setlg(cy, m);
! 957: cycle[l++] = (long) cy;
! 958: }
! 959: setlg(cycle, l);
! 960: lbot = avma;
! 961: cycle = gcopy(cycle);
! 962: return gerepile(ltop, lbot, cycle);
! 963: }
! 964: /* Calcule les orbites d'un ensemble de permutations */
! 965: GEN
! 966: vecpermorbite(GEN v)
! 967: {
! 968: ulong ltop = avma, lbot;
! 969: int i, j, k, l, m, n, o, p, flag;
! 970: GEN bit, cycle, cy;
! 971: n = lg(v[1]);
! 972: cycle = cgetg(n, t_VEC);
! 973: bit = cgetg(n, t_VECSMALL);
! 974: for (i = 1; i < n; i++)
! 975: bit[i] = 0;
! 976: for (k = 1, l = 1; k < n;)
! 977: {
! 978: for (j = 1; bit[j]; j++);
! 979: cy = cgetg(n, t_VECSMALL);
! 980: m = 1;
! 981: cy[m++] = j;
! 982: bit[j] = 1;
! 983: k++;
! 984: do
! 985: {
! 986: flag = 0;
! 987: for (o = 1; o < lg(v); o++)
! 988: {
! 989: for (p = 1; p < m; p++) /* m varie! */
! 990: {
! 991: j = ((long **) v)[o][cy[p]];
! 992: if (!bit[j])
! 993: {
! 994: flag = 1;
! 995: bit[j] = 1;
! 996: k++;
! 997: cy[m++] = j;
! 998: }
! 999: }
! 1000: }
! 1001: } while (flag);
! 1002: setlg(cy, m);
! 1003: cycle[l++] = (long) cy;
! 1004: }
! 1005: setlg(cycle, l);
! 1006: lbot = avma;
! 1007: cycle = gcopy(cycle);
! 1008: return gerepile(ltop, lbot, cycle);
! 1009: }
! 1010: /*
! 1011: * Calcule la permutation associe a un polynome f des racines L
! 1012: */
! 1013: GEN
! 1014: poltoperm(GEN f, GEN L)
! 1015: {
! 1016: ulong ltop, ltop2;
! 1017: GEN pf, fx, fp;
! 1018: int i, j;
! 1019: pf = cgetg(lg(L), t_VECSMALL);
! 1020: ltop = avma;
! 1021: fp = cgetg(lg(L), t_VECSMALL);
! 1022: ltop2 = avma;
! 1023: for (i = 1; i < lg(fp); i++)
! 1024: fp[i] = 1;
! 1025: for (i = 1; i < lg(L); i++)
! 1026: {
! 1027: fx = gsubst(f, varn(f), (GEN) L[i]);
! 1028: for (j = 1; j < lg(L); j++)
! 1029: if (fp[j] && gegal(fx, (GEN) L[j]))
! 1030: {
! 1031: pf[i] = j;
! 1032: fp[j] = 0;
! 1033: break;
! 1034: }
! 1035: avma = ltop2;
! 1036: }
! 1037: avma = ltop;
! 1038: return pf;
! 1039: }
! 1040: /*
! 1041: * Calcule un polynome R definissant le corps fixe de T pour les orbites O
! 1042: * tel que R est sans-facteur carre modulo mod et l retourne dans U les
! 1043: * racines de R
! 1044: */
! 1045: GEN
! 1046: corpsfixeorbitemod(GEN L, GEN O, long x, GEN mod, GEN l, GEN * U)
! 1047: {
! 1048: ulong ltop = avma, lbot, av, av2;
! 1049: GEN g, p, PL, *gptr[2], gmod, gl, modl;
! 1050: GEN id;
! 1051: int i, j, d, dmax;
! 1052: PL = cgetg(lg(O), t_COL);
! 1053: modl = gmodulcp(gun, l);
! 1054: av2 = avma;
! 1055: dmax = lg(L) + 1;
! 1056: d = 0;
! 1057: do
! 1058: {
! 1059: avma = av2;
! 1060: id = stoi(d);
! 1061: g = polun[x];
! 1062: for (i = 1; i < lg(O); i++)
! 1063: {
! 1064: p = gadd(id, (GEN) L[((GEN *) O)[i][1]]);
! 1065: for (j = 2; j < lg(O[i]); j++)
! 1066: p = gmul(p, gadd(id, (GEN) L[((GEN *) O)[i][j]]));
! 1067: PL[i] = (long) p;
! 1068: g = gmul(g, gsub(polx[x], p));
! 1069: }
! 1070: lbot = avma;
! 1071: g = centerlift(g);
! 1072: av = avma;
! 1073: gmod = gmul(g, mod);
! 1074: gl = gmul(g, modl);
! 1075: if (DEBUGLEVEL >= 6)
! 1076: fprintferr("GaloisConj:corps fixe:%d:%Z\n", d, g);
! 1077: d = (d > 0 ? -d : 1 - d);
! 1078: if (d > dmax)
! 1079: err(talker, "prime too small in corpsfixeorbitemod");
! 1080: } while (degree(ggcd(deriv(gl, x), gl)) || degree(ggcd(deriv(gmod, x), gmod)));
! 1081: avma = av;
! 1082: *U = gcopy(PL);
! 1083: gptr[0] = &g;
! 1084: gptr[1] = U;
! 1085: gerepilemanysp(ltop, lbot, gptr, 2);
! 1086: return g;
! 1087: }
! 1088: /*
! 1089: * Calcule l'inclusion de R dans T i.e. S telque T|R\compo S
! 1090: */
! 1091: GEN
! 1092: corpsfixeinclusion(GEN O, GEN PL)
! 1093: {
! 1094: GEN S;
! 1095: int i, j;
! 1096: S = cgetg((lg(O) - 1) * (lg(O[1]) - 1) + 1, t_COL);
! 1097: for (i = 1; i < lg(O); i++)
! 1098: for (j = 1; j < lg(O[i]); j++)
! 1099: S[((GEN *) O)[i][j]] = lcopy((GEN) PL[i]);
! 1100: return S;
! 1101: }
! 1102: /* Calcule l'inverse de la matrice de van der Monde de T multiplie par den */
! 1103: GEN
! 1104: vandermondeinverse(GEN L, GEN T, GEN den)
! 1105: {
! 1106: ulong ltop = avma, lbot;
! 1107: int i, j, n = lg(L);
! 1108: long x = varn(T);
! 1109: GEN M, P, Tp;
! 1110: if (DEBUGLEVEL >= 1)
! 1111: timer2();
! 1112: M = cgetg(n, t_MAT);
! 1113: Tp = deriv(T, x);
! 1114: for (i = 1; i < n; i++)
! 1115: {
! 1116: M[i] = lgetg(n, t_COL);
! 1117: P = gdiv(gdeuc(T, gsub(polx[x], (GEN) L[i])), gsubst(Tp, x, (GEN) L[i]));
! 1118: for (j = 1; j < n; j++)
! 1119: ((GEN *) M)[i][j] = P[1 + j];
! 1120: }
! 1121: if (DEBUGLEVEL >= 1)
! 1122: msgtimer("vandermondeinverse");
! 1123: lbot = avma;
! 1124: M = gmul(den, M);
! 1125: return gerepile(ltop, lbot, M);
! 1126: }
! 1127: /* Calcule le polynome associe a un vecteur conjugue v */
! 1128: static GEN
! 1129: vectopol(GEN v, GEN L, GEN M, GEN den, long x)
! 1130: {
! 1131: ulong ltop = avma, lbot;
! 1132: GEN res;
! 1133: res = gmul(M, v);
! 1134: res = gtopolyrev(centerlift(res), x);
! 1135: lbot = avma;
! 1136: res = gdiv(res, den);
! 1137: return gerepile(ltop, lbot, res);
! 1138: }
! 1139: /* Calcule le polynome associe a une permuation p */
! 1140: static GEN
! 1141: permtopol(GEN p, GEN L, GEN M, GEN den, long x)
! 1142: {
! 1143: ulong ltop = avma, lbot;
! 1144: GEN res;
! 1145: res = gmul(M, applyperm(L, p));
! 1146: res = gtopolyrev(centerlift(res), x);
! 1147: lbot = avma;
! 1148: res = gdiv(res, den);
! 1149: return gerepile(ltop, lbot, res);
! 1150: }
! 1151: /*
! 1152: * factorise partiellement n sous la forme n=d*u*f^2 ou d est sans facteur
! 1153: * carre et u n'est pas un carre parfait et retourne u*f
! 1154: */
! 1155: GEN
! 1156: mycoredisc(GEN n)
! 1157: {
! 1158: ulong av = avma, tetpil, r;
! 1159: GEN y, p1, p2, ret;
! 1160: {
! 1161: long av = avma, tetpil, i;
! 1162: GEN fa, p1, p2, p3, res = gun, res2 = gun, y;
! 1163: fa = auxdecomp(n, 0);
! 1164: p1 = (GEN) fa[1];
! 1165: p2 = (GEN) fa[2];
! 1166: for (i = 1; i < lg(p1) - 1; i++)
! 1167: {
! 1168: p3 = (GEN) p2[i];
! 1169: if (mod2(p3))
! 1170: res = mulii(res, (GEN) p1[i]);
! 1171: if (!gcmp1(p3))
! 1172: res2 = mulii(res2, gpui((GEN) p1[i], shifti(p3, -1), 0));
! 1173: }
! 1174: p3 = (GEN) p2[i];
! 1175: if (mod2(p3)) /* impaire: verifions */
! 1176: {
! 1177: if (!gcmp1(p3))
! 1178: res2 = mulii(res2, gpui((GEN) p1[i], shifti(p3, -1), 0));
! 1179: if (isprime((GEN) p1[i]))
! 1180: res = mulii(res, (GEN) p1[i]);
! 1181: else
! 1182: res2 = mulii(res2, (GEN) p1[i]);
! 1183: } else /* paire:OK */
! 1184: res2 = mulii(res2, gpui((GEN) p1[i], shifti(p3, -1), 0));
! 1185: tetpil = avma;
! 1186: y = cgetg(3, t_VEC);
! 1187: y[1] = (long) icopy(res);
! 1188: y[2] = (long) icopy(res2);
! 1189: ret = gerepile(av, tetpil, y);
! 1190: }
! 1191: p2 = ret;
! 1192: p1 = (GEN) p2[1];
! 1193: r = mod4(p1);
! 1194: if (signe(p1) < 0)
! 1195: r = 4 - r;
! 1196: if (r == 1 || r == 4)
! 1197: return (GEN) p2[2];
! 1198: tetpil = avma;
! 1199: y = gmul2n((GEN) p2[2], -1);
! 1200: return gerepile(av, tetpil, y);
! 1201: }
! 1202: /* Calcule la puissance exp d'une permutation decompose en cycle */
! 1203: GEN
! 1204: permcyclepow(GEN O, long exp)
! 1205: {
! 1206: int j, k, n;
! 1207: GEN p;
! 1208: for (n = 0, j = 1; j < lg(O); j++)
! 1209: n += lg(O[j]) - 1;
! 1210: p = cgetg(n + 1, t_VECSMALL);
! 1211: for (j = 1; j < lg(O); j++)
! 1212: {
! 1213: n = lg(O[j]) - 1;
! 1214: for (k = 1; k <= n; k++)
! 1215: p[((long **) O)[j][k]] = ((long **) O)[j][1 + (k + exp - 1) % n];
! 1216: }
! 1217: return p;
! 1218: }
! 1219: /*
! 1220: * Casse l'orbite O en sous-orbite d'ordre premier correspondant a des
! 1221: * puissance de l'element
! 1222: */
! 1223: GEN
! 1224: splitorbite(GEN O)
! 1225: {
! 1226: ulong ltop = avma, lbot;
! 1227: int i, n;
! 1228: GEN F, fc, res;
! 1229: n = lg(O[1]) - 1;
! 1230: F = factor(stoi(n));
! 1231: fc = cgetg(lg(F[1]), t_VECSMALL);
! 1232: for (i = 1; i < lg(fc); i++)
! 1233: fc[i] = itos(gpow(((GEN **) F)[1][i], ((GEN **) F)[2][i], DEFAULTPREC));
! 1234: lbot = avma;
! 1235: res = cgetg(lg(fc), t_VEC);
! 1236: for (i = 1; i < lg(fc); i++)
! 1237: {
! 1238: GEN v;
! 1239: v = cgetg(3, t_VEC);
! 1240: res[i] = (long) v;
! 1241: v[1] = (long) permcyclepow(O, n / fc[i]);
! 1242: v[2] = (long) stoi(fc[i]);
! 1243: }
! 1244: return gerepile(ltop, lbot, res);
! 1245: }
! 1246: /*
! 1247: * structure qui contient l'analyse du groupe de Galois par etude des degres
! 1248: * de Frobenius:
! 1249: *
! 1250: * p: nombre premier a relever deg: degre du lift à effectuer pgp: plus grand
! 1251: * diviseur premier du degre de T. exception: 1 si le pgp-Sylow est
! 1252: * non-cyclique. l: un nombre premier tel que T est totalement decompose
! 1253: * modulo l ppp: plus petit diviseur premier du degre de T. primepointer:
! 1254: * permet de calculer les premiers suivant p.
! 1255: */
! 1256: struct galois_analysis
! 1257: {
! 1258: long p;
! 1259: long deg;
! 1260: long exception;
! 1261: long ord;
! 1262: long l;
! 1263: long ppp;
! 1264: long p4;
! 1265: byteptr primepointer;
! 1266: };
! 1267: /* peut-etre on peut accelerer(distinct degree factorisation */
! 1268: void
! 1269: galoisanalysis(GEN T, struct galois_analysis * ga, long calcul_l)
! 1270: {
! 1271: ulong ltop = avma;
! 1272: long n, p, ex, plift, nbmax, nbtest, exist6 = 0, p4 = 0;
! 1273: GEN F, fc;
! 1274: byteptr primepointer, pp = 0;
! 1275: long pha, ord, deg, ppp, pgp, ordmax = 0, l = 0;
! 1276: int i;
! 1277: /* Etude du cardinal: */
! 1278: /* Calcul de l'ordre garanti d'un sous-groupe cyclique */
! 1279: /* Tout les groupes d'ordre n sont cyclique ssi gcd(n,phi(n))==1 */
! 1280: if (DEBUGLEVEL >= 1)
! 1281: timer2();
! 1282: n = degree(T);
! 1283: F = factor(stoi(n));
! 1284: fc = cgetg(lg(F[1]), t_VECSMALL);
! 1285: for (i = 1; i < lg(fc); i++)
! 1286: fc[i] = itos(gpow(((GEN **) F)[1][i], ((GEN **) F)[2][i], DEFAULTPREC));
! 1287: ppp = itos(((GEN **) F)[1][1]); /* Plus Petit diviseur Premier */
! 1288: pgp = itos(((GEN **) F)[1][lg(F[1]) - 1]); /* Plus Grand diviseur
! 1289: * Premier */
! 1290: pha = 1;
! 1291: ord = 1;
! 1292: ex = 0;
! 1293: for (i = lg(F[1]) - 1; i > 0; i--)
! 1294: {
! 1295: p = itos(((GEN **) F)[1][i]);
! 1296: if (pha % p != 0)
! 1297: {
! 1298: ord *= p;
! 1299: pha *= p - 1;
! 1300: } else
! 1301: {
! 1302: ex = 1;
! 1303: break;
! 1304: }
! 1305: if (!gcmp1(((GEN **) F)[2][i]))
! 1306: break;
! 1307: }
! 1308: plift = 0;
! 1309: /* Etude des ordres des Frobenius */
! 1310: nbmax = max(4, n / 2); /* Nombre maxi d'éléments à tester */
! 1311: nbtest = 0;
! 1312: deg = 0;
! 1313: for (p = 0, primepointer = diffptr; plift == 0 || (nbtest < nbmax && ord != n) || (n == 24 && exist6 == 0 && p4 == 0);)
! 1314: {
! 1315: long u, s, c;
! 1316: long isram;
! 1317: GEN S;
! 1318: c = *primepointer++;
! 1319: if (!c)
! 1320: err(primer1);
! 1321: p += c;
! 1322: if (p <= (n << 1))
! 1323: continue;
! 1324: S = (GEN) simplefactmod(T, stoi(p));
! 1325: isram = 0;
! 1326: for (i = 1; i < lg(S[2]) && !isram; i++)
! 1327: if (!gcmp1(((GEN **) S)[2][i]))
! 1328: isram = 1;
! 1329: if (isram == 0)
! 1330: {
! 1331: s = itos(((GEN **) S)[1][1]);
! 1332: for (i = 2; i < lg(S[1]) && !isram; i++)
! 1333: if (itos(((GEN **) S)[1][i]) != s)
! 1334: {
! 1335: avma = ltop;
! 1336: if (DEBUGLEVEL >= 2)
! 1337: fprintferr("GaloisAnalysis:non Galois for p=%d\n", p);
! 1338: ga->p = p;
! 1339: ga->deg = 0;
! 1340: return; /* Not a Galois polynomial */
! 1341: }
! 1342: if (l == 0 && s == 1)
! 1343: l = p;
! 1344: nbtest++;
! 1345: if (nbtest > (3 * nbmax) && (n == 60 || n == 75))
! 1346: break;
! 1347: if (s % 6 == 0)
! 1348: exist6 = 1;
! 1349: if (p4 == 0 && s == 4)
! 1350: p4 = p;
! 1351: if (DEBUGLEVEL >= 6)
! 1352: fprintferr("GaloisAnalysis:Nbtest=%d,plift=%d,p=%d,s=%d,ord=%d\n", nbtest, plift, p, s, ord);
! 1353: if (s > ordmax)
! 1354: ordmax = s;
! 1355: if (s >= ord) /* Calcul de l'exposant distinguant minimal
! 1356: * garanti */
! 1357: {
! 1358: if (s * ppp == n) /* Tout sous groupe d'indice ppp est distingué */
! 1359: u = s;
! 1360: else /* Théorème de structure des groupes
! 1361: * hyper-résoluble */
! 1362: {
! 1363: u = 1;
! 1364: for (i = lg(fc) - 1; i > 0; i--)
! 1365: {
! 1366: if (s % fc[i] == 0)
! 1367: u *= fc[i];
! 1368: else
! 1369: break;
! 1370: }
! 1371: }
! 1372: if (u != 1)
! 1373: {
! 1374: if (!ex || s > ord || (s == ord && (plift == 0 || u > deg)))
! 1375: {
! 1376: deg = u;
! 1377: ord = s;
! 1378: plift = p;
! 1379: pp = primepointer;
! 1380: ex = 1;
! 1381: }
! 1382: } else if (!ex && (plift == 0 || s > ord))
! 1383: /*
! 1384: * J'ai besoin de plus de connaissance sur les p-groupes, surtout
! 1385: * pour p=2;
! 1386: */
! 1387: {
! 1388: deg = pgp;
! 1389: ord = s;
! 1390: plift = p;
! 1391: pp = primepointer;
! 1392: ex = 0;
! 1393: }
! 1394: }
! 1395: }
! 1396: }
! 1397: if (plift == 0 || ((n == 36 || n == 48) && !exist6) || (n == 56 && ordmax == 7) || (n == 60 && ordmax == 5) || (n == 72 && !exist6) || (n == 80 && ordmax == 5))
! 1398: {
! 1399: deg = 0;
! 1400: err(warner, "Galois group almost certainly not weakly super solvable");
! 1401: }
! 1402: avma = ltop;
! 1403: if (calcul_l)
! 1404: {
! 1405: ulong av;
! 1406: GEN x;
! 1407: long c;
! 1408: x = cgetg(3, t_POLMOD);
! 1409: x[2] = lpolx[varn(T)];
! 1410: av = avma;
! 1411: while (l == 0)
! 1412: {
! 1413: c = *primepointer++;
! 1414: if (!c)
! 1415: err(primer1);
! 1416: p += c;
! 1417: x[1] = lmul(T, gmodulss(1, p));
! 1418: if (gegal(gpuigs(x, p), x))
! 1419: l = p;
! 1420: avma = av;
! 1421: }
! 1422: avma = ltop;
! 1423: }
! 1424: ga->p = plift;
! 1425: ga->exception = ex;
! 1426: ga->deg = deg;
! 1427: ga->ord = ord;
! 1428: ga->l = l;
! 1429: ga->primepointer = pp;
! 1430: ga->ppp = ppp;
! 1431: ga->p4 = p4;
! 1432: if (DEBUGLEVEL >= 4)
! 1433: fprintferr("GaloisAnalysis:p=%d l=%d exc=%d deg=%d ord=%d ppp=%d\n", p, l, ex, deg, ord, ppp);
! 1434: if (DEBUGLEVEL >= 1)
! 1435: msgtimer("galoisanalysis()");
! 1436: }
! 1437: /* Calcule les bornes sur les coefficients a chercher */
! 1438: struct galois_borne
! 1439: {
! 1440: GEN l;
! 1441: long valsol;
! 1442: long valabs;
! 1443: GEN bornesol;
! 1444: GEN ladicsol;
! 1445: GEN ladicabs;
! 1446: };
! 1447: /*
! 1448: * recalcule L avec une precision superieur
! 1449: */
! 1450: GEN
! 1451: recalculeL(GEN T, GEN Tp, GEN L, struct galois_borne * gb, struct galois_borne * ngb)
! 1452: {
! 1453: ulong ltop = avma, lbot = avma;
! 1454: GEN L2, y, z, lad;
! 1455: long i, val;
! 1456: if (DEBUGLEVEL >= 1)
! 1457: timer2();
! 1458: L2 = cgetg(lg(L), typ(L));
! 1459: for (i = 1; i < lg(L); i++)
! 1460: {
! 1461: ltop = avma;
! 1462: val = gb->valabs;
! 1463: lad = gb->ladicabs;
! 1464: z = (GEN) L[i];
! 1465: while (val < ngb->valabs)
! 1466: {
! 1467: val <<= 1;
! 1468: if (val >= ngb->valabs)
! 1469: {
! 1470: val = ngb->valabs;
! 1471: lad = ngb->ladicabs;
! 1472: } else
! 1473: lad = gsqr(lad);
! 1474: y = gmodulcp((GEN) z[2], lad);
! 1475: z = gdiv(poleval(T, y), poleval(Tp, y));
! 1476: lbot = avma;
! 1477: z = gsub(y, z);
! 1478: }
! 1479: L2[i] = (long) gerepile(ltop, lbot, z);
! 1480: }
! 1481: return L2;
! 1482: }
! 1483: void
! 1484: initborne(GEN T, GEN disc, struct galois_borne * gb, long ppp)
! 1485: {
! 1486: ulong ltop = avma, lbot, av2;
! 1487: GEN borne, borneroots, borneabs;
! 1488: int i, j;
! 1489: int n;
! 1490: GEN L, M, z;
! 1491: L = roots(T, DEFAULTPREC);
! 1492: n = lg(L) - 1;
! 1493: for (i = 1; i <= n; i++)
! 1494: {
! 1495: z = (GEN) L[i];
! 1496: if (signe(z[2]))
! 1497: break;
! 1498: L[i] = z[1];
! 1499: }
! 1500: M = vandermondeinverse(L, gmul(T, realun(DEFAULTPREC)), disc);
! 1501: borne = gzero;
! 1502: for (i = 1; i <= n; i++)
! 1503: {
! 1504: z = gzero;
! 1505: for (j = 1; j <= n; j++)
! 1506: z = gadd(z, gabs(((GEN **) M)[j][i], DEFAULTPREC));
! 1507: if (gcmp(z, borne) > 0)
! 1508: borne = z;
! 1509: }
! 1510: borneroots = gzero;
! 1511: for (i = 1; i <= n; i++)
! 1512: {
! 1513: z = gabs((GEN) L[i], DEFAULTPREC);
! 1514: if (gcmp(z, borneroots) > 0)
! 1515: borneroots = z;
! 1516: }
! 1517: borneabs = addsr(1, gpowgs(addsr(n, borneroots), n / ppp));
! 1518: lbot = avma;
! 1519: borneroots = addsr(1, gmul(borne, borneroots));
! 1520: av2 = avma;
! 1521: borneabs = gmul2n(gmul(borne, borneabs), 4);
! 1522: gb->valsol = itos(gceil(gdiv(glog(gmul2n(borneroots, 4 + (n >> 1)), DEFAULTPREC), glog(gb->l, DEFAULTPREC))));
! 1523: if (DEBUGLEVEL >= 4)
! 1524: fprintferr("GaloisConj:val1=%d\n", gb->valsol);
! 1525: gb->valabs = max(gb->valsol, itos(gceil(gdiv(glog(borneabs, DEFAULTPREC), glog(gb->l, DEFAULTPREC)))));
! 1526: if (DEBUGLEVEL >= 4)
! 1527: fprintferr("GaloisConj:val2=%d\n", gb->valabs);
! 1528: avma = av2;
! 1529: gb->bornesol = gerepile(ltop, lbot, borneroots);
! 1530: gb->ladicsol = gpowgs(gb->l, gb->valsol);
! 1531: gb->ladicabs = gpowgs(gb->l, gb->valabs);
! 1532: }
! 1533: /* Groupe A4 */
! 1534: GEN
! 1535: a4galoisgen(GEN T, struct galois_test * td)
! 1536: {
! 1537: int ltop = avma, av, av2;
! 1538: int i, j, k;
! 1539: int n;
! 1540: int N, hop = 0;
! 1541: GEN *ar, **mt; /* tired of casting */
! 1542: GEN t, u, O;
! 1543: GEN res, orb, ry;
! 1544: GEN pft, pfu, pfv;
! 1545: n = degree(T);
! 1546: res = cgetg(4, t_VEC);
! 1547: ry = cgetg(3, t_VEC);
! 1548: res[1] = (long) ry;
! 1549: pft = cgetg(n + 1, t_VECSMALL);
! 1550: ry[1] = (long) pft;
! 1551: ry[2] = (long) stoi(2);
! 1552: ry = cgetg(3, t_VEC);
! 1553: pfu = cgetg(n + 1, t_VECSMALL);
! 1554: ry[1] = (long) pfu;
! 1555: ry[2] = (long) stoi(2);
! 1556: res[2] = (long) ry;
! 1557: ry = cgetg(3, t_VEC);
! 1558: pfv = cgetg(n + 1, t_VECSMALL);
! 1559: ry[1] = (long) pfv;
! 1560: ry[2] = (long) stoi(3);
! 1561: res[3] = (long) ry;
! 1562: av = avma;
! 1563: ar = (GEN *) alloue_ardoise(n, 1 + lg(td->ladic));
! 1564: mt = (GEN **) td->PV[td->ordre[n]];
! 1565: t = cgetg(n + 1, t_VECSMALL) + 1; /* Sorry for this hack */
! 1566: u = cgetg(n + 1, t_VECSMALL) + 1; /* too lazy to correct */
! 1567: av2 = avma;
! 1568: N = itos(gdiv(mpfact(n), mpfact(n >> 1))) >> (n >> 1);
! 1569: if (DEBUGLEVEL >= 4)
! 1570: fprintferr("A4GaloisConj:I will test %d permutations\n", N);
! 1571: avma = av2;
! 1572: for (i = 0; i < n; i++)
! 1573: t[i] = i + 1;
! 1574: for (i = 0; i < N; i++)
! 1575: {
! 1576: GEN g;
! 1577: int a, x, y;
! 1578: if (i == 0)
! 1579: {
! 1580: gaffect(gzero, ar[(n - 2) >> 1]);
! 1581: for (k = n - 2; k > 2; k -= 2)
! 1582: gaddz(ar[k >> 1], gadd(mt[k + 1][k + 2], mt[k + 2][k + 1]), ar[(k >> 1) - 1]);
! 1583: } else
! 1584: {
! 1585: x = i;
! 1586: y = 1;
! 1587: do
! 1588: {
! 1589: hiremainder = 0;
! 1590: y += 2;
! 1591: x = divll(x, y);
! 1592: a = hiremainder;
! 1593: }
! 1594: while (!a);
! 1595: switch (y)
! 1596: {
! 1597: case 3:
! 1598: x = t[2];
! 1599: if (a == 1)
! 1600: {
! 1601: t[2] = t[1];
! 1602: t[1] = x;
! 1603: } else
! 1604: {
! 1605: t[2] = t[0];
! 1606: t[0] = x;
! 1607: }
! 1608: break;
! 1609: case 5:
! 1610: x = t[0];
! 1611: t[0] = t[2];
! 1612: t[2] = t[1];
! 1613: t[1] = x;
! 1614: x = t[4];
! 1615: t[4] = t[4 - a];
! 1616: t[4 - a] = x;
! 1617: gaddz(ar[2], gadd(mt[t[4]][t[5]], mt[t[5]][t[4]]), ar[1]);
! 1618: break;
! 1619: case 7:
! 1620: x = t[0];
! 1621: t[0] = t[4];
! 1622: t[4] = t[3];
! 1623: t[3] = t[1];
! 1624: t[1] = t[2];
! 1625: t[2] = x;
! 1626: x = t[6];
! 1627: t[6] = t[6 - a];
! 1628: t[6 - a] = x;
! 1629: gaddz(ar[3], gadd(mt[t[6]][t[7]], mt[t[7]][t[6]]), ar[2]);
! 1630: gaddz(ar[2], gadd(mt[t[4]][t[5]], mt[t[5]][t[4]]), ar[1]);
! 1631: break;
! 1632: case 9:
! 1633: x = t[0];
! 1634: t[0] = t[6];
! 1635: t[6] = t[5];
! 1636: t[5] = t[3];
! 1637: t[3] = x;
! 1638: x = t[4];
! 1639: t[4] = t[1];
! 1640: t[1] = x;
! 1641: x = t[8];
! 1642: t[8] = t[8 - a];
! 1643: t[8 - a] = x;
! 1644: gaddz(ar[4], gadd(mt[t[8]][t[9]], mt[t[9]][t[8]]), ar[3]);
! 1645: gaddz(ar[3], gadd(mt[t[6]][t[7]], mt[t[7]][t[6]]), ar[2]);
! 1646: gaddz(ar[2], gadd(mt[t[4]][t[5]], mt[t[5]][t[4]]), ar[1]);
! 1647: break;
! 1648: default:
! 1649: y--;
! 1650: x = t[0];
! 1651: t[0] = t[2];
! 1652: t[2] = t[1];
! 1653: t[1] = x;
! 1654: for (k = 4; k < y; k += 2)
! 1655: {
! 1656: int j;
! 1657: x = t[k];
! 1658: for (j = k; j > 0; j--)
! 1659: t[j] = t[j - 1];
! 1660: t[0] = x;
! 1661: }
! 1662: x = t[y];
! 1663: t[y] = t[y - a];
! 1664: t[y - a] = x;
! 1665: for (k = y; k > 2; k -= 2)
! 1666: gaddz(ar[k >> 1], gadd(mt[t[k]][t[k + 1]], mt[t[k + 1]][t[k]]), ar[(k >> 1) - 1]);
! 1667: }
! 1668: }
! 1669: g = gadd(ar[1], gadd(gadd(mt[t[0]][t[1]], mt[t[1]][t[0]]),
! 1670: gadd(mt[t[2]][t[3]], mt[t[3]][t[2]])));
! 1671: if (padicisint(g, td))
! 1672: {
! 1673: for (k = 0; k < n; k += 2)
! 1674: {
! 1675: pft[t[k]] = t[k + 1];
! 1676: pft[t[k + 1]] = t[k];
! 1677: }
! 1678: if (verifietest(pft, td))
! 1679: break;
! 1680: else
! 1681: hop++;
! 1682: }
! 1683: avma = av2;
! 1684: }
! 1685: if (i == N)
! 1686: {
! 1687: avma = ltop;
! 1688: if (DEBUGLEVEL >= 1 && hop)
! 1689: fprintferr("A4GaloisConj: %d hop sur %d iterations\n", hop, N);
! 1690: return gzero;
! 1691: }
! 1692: if (DEBUGLEVEL >= 1 && hop)
! 1693: fprintferr("A4GaloisConj: %d hop sur %d iterations\n", hop, N);
! 1694: N = itos(gdiv(mpfact(n >> 1), mpfact(n >> 2))) >> 1;
! 1695: avma = av2;
! 1696: if (DEBUGLEVEL >= 4)
! 1697: fprintferr("A4GaloisConj:sigma=%Z \n", pft);
! 1698: for (i = 0; i < N; i++)
! 1699: {
! 1700: GEN g;
! 1701: int a, x, y;
! 1702: if (i == 0)
! 1703: {
! 1704: for (k = 0; k < n; k += 4)
! 1705: {
! 1706: u[k + 3] = t[k + 3];
! 1707: u[k + 2] = t[k + 1];
! 1708: u[k + 1] = t[k + 2];
! 1709: u[k] = t[k];
! 1710: }
! 1711: } else
! 1712: {
! 1713: x = i;
! 1714: y = -2;
! 1715: do
! 1716: {
! 1717: hiremainder = 0;
! 1718: y += 4;
! 1719: x = divll(x, y);
! 1720: a = hiremainder;
! 1721: } while (!a);
! 1722: x = u[2];
! 1723: u[2] = u[0];
! 1724: u[0] = x;
! 1725: switch (y)
! 1726: {
! 1727: case 2:
! 1728: break;
! 1729: case 6:
! 1730: x = u[4];
! 1731: u[4] = u[6];
! 1732: u[6] = x;
! 1733: if (a % 2 == 0)
! 1734: {
! 1735: a = 4 - a / 2;
! 1736: x = u[6];
! 1737: u[6] = u[a];
! 1738: u[a] = x;
! 1739: x = u[4];
! 1740: u[4] = u[a - 2];
! 1741: u[a - 2] = x;
! 1742: }
! 1743: break;
! 1744: case 10:
! 1745: x = u[6];
! 1746: u[6] = u[3];
! 1747: u[3] = u[2];
! 1748: u[2] = u[4];
! 1749: u[4] = u[1];
! 1750: u[1] = u[0];
! 1751: u[0] = x;
! 1752: if (a >= 3)
! 1753: a += 2;
! 1754: a = 8 - a;
! 1755: x = u[10];
! 1756: u[10] = u[a];
! 1757: u[a] = x;
! 1758: x = u[8];
! 1759: u[8] = u[a - 2];
! 1760: u[a - 2] = x;
! 1761: break;
! 1762: }
! 1763: }
! 1764: g = gzero;
! 1765: for (k = 0; k < n; k += 2)
! 1766: g = gadd(g, gadd(mt[u[k]][u[k + 1]], mt[u[k + 1]][u[k]]));
! 1767: if (padicisint(g, td))
! 1768: {
! 1769: for (k = 0; k < n; k += 2)
! 1770: {
! 1771: pfu[u[k]] = u[k + 1];
! 1772: pfu[u[k + 1]] = u[k];
! 1773: }
! 1774: if (verifietest(pfu, td))
! 1775: break;
! 1776: else
! 1777: hop++;
! 1778: }
! 1779: avma = av2;
! 1780: }
! 1781: if (i == N)
! 1782: {
! 1783: avma = ltop;
! 1784: return gzero;
! 1785: }
! 1786: if (DEBUGLEVEL >= 1 && hop)
! 1787: fprintferr("A4GaloisConj: %d hop sur %d iterations\n", hop, N);
! 1788: if (DEBUGLEVEL >= 4)
! 1789: fprintferr("A4GaloisConj:tau=%Z \n", u);
! 1790: avma = av2;
! 1791: orb = cgetg(3, t_VEC);
! 1792: orb[1] = (long) pft;
! 1793: orb[2] = (long) pfu;
! 1794: if (DEBUGLEVEL >= 4)
! 1795: fprintferr("A4GaloisConj:orb=%Z \n", orb);
! 1796: O = vecpermorbite(orb);
! 1797: if (DEBUGLEVEL >= 4)
! 1798: fprintferr("A4GaloisConj:O=%Z \n", O);
! 1799: av2 = avma;
! 1800: for (j = 0; j < 2; j++)
! 1801: {
! 1802: pfv[((long **) O)[1][1]] = ((long **) O)[2][1];
! 1803: pfv[((long **) O)[1][2]] = ((long **) O)[2][3 + j];
! 1804: pfv[((long **) O)[1][3]] = ((long **) O)[2][4 - (j << 1)];
! 1805: pfv[((long **) O)[1][4]] = ((long **) O)[2][2 + j];
! 1806: for (i = 0; i < 4; i++)
! 1807: {
! 1808: long x;
! 1809: GEN g;
! 1810: switch (i)
! 1811: {
! 1812: case 0:
! 1813: break;
! 1814: case 1:
! 1815: x = ((long **) O)[3][1];
! 1816: ((long **) O)[3][1] = ((long **) O)[3][2];
! 1817: ((long **) O)[3][2] = x;
! 1818: x = ((long **) O)[3][3];
! 1819: ((long **) O)[3][3] = ((long **) O)[3][4];
! 1820: ((long **) O)[3][4] = x;
! 1821: break;
! 1822: case 2:
! 1823: x = ((long **) O)[3][1];
! 1824: ((long **) O)[3][1] = ((long **) O)[3][4];
! 1825: ((long **) O)[3][4] = x;
! 1826: x = ((long **) O)[3][2];
! 1827: ((long **) O)[3][2] = ((long **) O)[3][3];
! 1828: ((long **) O)[3][3] = x;
! 1829: break;
! 1830: case 3:
! 1831: x = ((long **) O)[3][1];
! 1832: ((long **) O)[3][1] = ((long **) O)[3][2];
! 1833: ((long **) O)[3][2] = x;
! 1834: x = ((long **) O)[3][3];
! 1835: ((long **) O)[3][3] = ((long **) O)[3][4];
! 1836: ((long **) O)[3][4] = x;
! 1837: }
! 1838: pfv[((long **) O)[2][1]] = ((long **) O)[3][1];
! 1839: pfv[((long **) O)[2][3 + j]] = ((long **) O)[3][4 - j];
! 1840: pfv[((long **) O)[2][4 - (j << 1)]] = ((long **) O)[3][2 + (j << 1)];
! 1841: pfv[((long **) O)[2][2 + j]] = ((long **) O)[3][3 - j];
! 1842: pfv[((long **) O)[3][1]] = ((long **) O)[1][1];
! 1843: pfv[((long **) O)[3][4 - j]] = ((long **) O)[1][2];
! 1844: pfv[((long **) O)[3][2 + (j << 1)]] = ((long **) O)[1][3];
! 1845: pfv[((long **) O)[3][3 - j]] = ((long **) O)[1][4];
! 1846: g = gzero;
! 1847: for (k = 1; k <= n; k++)
! 1848: g = gadd(g, mt[k][pfv[k]]);
! 1849: if (padicisint(g, td) && verifietest(pfv, td))
! 1850: {
! 1851: avma = av;
! 1852: if (DEBUGLEVEL >= 1)
! 1853: fprintferr("A4GaloisConj:%d hop sur %d iterations max\n", hop, 10395 + 68);
! 1854: return res;
! 1855: } else
! 1856: hop++;
! 1857: avma = av2;
! 1858: }
! 1859: }
! 1860: /* Echec? */
! 1861: avma = ltop;
! 1862: return gzero;
! 1863: }
! 1864: /* Groupe S4 */
! 1865: GEN
! 1866: Fpisom(GEN p, GEN T1, GEN T2)
! 1867: {
! 1868: ulong ltop = avma, lbot;
! 1869: GEN T, res;
! 1870: long v;
! 1871: if (T1 == T2)
! 1872: return gmodulcp(polx[varn(T1)], T1);
! 1873: v = varn(T2);
! 1874: setvarn(T2, MAXVARN);
! 1875: T = (GEN) factmod9(T1, p, T2)[1];
! 1876: setvarn(T2, v);
! 1877: lbot = avma;
! 1878: res = gneg(((GEN **) T)[1][2]);
! 1879: setvarn(res[1], v);
! 1880: setvarn(res[2], v);
! 1881: return gerepile(ltop, lbot, res);
! 1882: }
! 1883: GEN
! 1884: Fpinvisom(GEN S)
! 1885: {
! 1886: ulong ltop = avma, lbot;
! 1887: GEN M, U, V;
! 1888: int n, i, j;
! 1889: long x;
! 1890: x = varn(S[1]);
! 1891: U = gmodulcp(polun[x], (GEN) S[1]);
! 1892: n = degree((GEN) S[1]);
! 1893: M = cgetg(n + 1, t_MAT);
! 1894: for (i = 1; i <= n; i++)
! 1895: {
! 1896: int d;
! 1897: if (i > 1)
! 1898: U = gmul(U, S);
! 1899: M[i] = lgetg(n + 1, t_COL);
! 1900: d = degree((GEN) U[2]);
! 1901: for (j = 1; j <= d + 1; j++)
! 1902: ((GEN *) M)[i][j] = ((GEN *) U)[2][1 + j];
! 1903: for (j = d + 2; j <= n; j++)
! 1904: ((GEN *) M)[i][j] = zero;
! 1905: }
! 1906: V = cgetg(n + 1, t_COL);
! 1907: for (i = 1; i <= n; i++)
! 1908: V[i] = zero;
! 1909: V[2] = un;
! 1910: V = gauss(M, V);
! 1911: lbot = avma;
! 1912: V = gtopolyrev(V, x);
! 1913: return gerepile(ltop, lbot, V);
! 1914: }
! 1915: static void
! 1916: makelift(GEN u, struct galois_lift * gl, GEN liftpow)
! 1917: {
! 1918: int i;
! 1919: liftpow[1] = (long) automorphismlift(u, gl);
! 1920: for (i = 2; i < lg(liftpow); i++)
! 1921: liftpow[i] = lmul((GEN) liftpow[i - 1], (GEN) liftpow[1]);
! 1922: }
! 1923: static long
! 1924: s4test(GEN u, GEN liftpow, struct galois_lift * gl, GEN phi)
! 1925: {
! 1926: GEN res;
! 1927: int i;
! 1928: if (DEBUGLEVEL >= 6)
! 1929: timer2();
! 1930: u = (GEN) u[2];
! 1931: res = (GEN) u[2];
! 1932: for (i = 1; i < lgef(u) - 2; i++)
! 1933: res = gadd(res, gmul((GEN) liftpow[i], (GEN) u[i + 2]));
! 1934: res = gdiv(centerlift(gmul((GEN) res[2], gl->den)), gl->den);
! 1935: if (DEBUGLEVEL >= 6)
! 1936: msgtimer("s4test()");
! 1937: return poltopermtest(res, gl->L, phi);
! 1938: }
! 1939: GEN
! 1940: s4galoisgen(struct galois_lift * gl)
! 1941: {
! 1942: struct galois_testlift gt;
! 1943: ulong ltop = avma, av, ltop2;
! 1944: GEN Tmod, isom, isominv, misom;
! 1945: int i, j;
! 1946: GEN sg;
! 1947: GEN sigma, tau, phi;
! 1948: GEN res, ry;
! 1949: GEN pj;
! 1950: GEN p;
! 1951: GEN bezoutcoeff, pauto, liftpow;
! 1952: long v;
! 1953: p = gl->p;
! 1954: v = varn(gl->T);
! 1955: res = cgetg(5, t_VEC);
! 1956: ry = cgetg(3, t_VEC);
! 1957: res[1] = (long) ry;
! 1958: ry[1] = lgetg(lg(gl->L), t_VECSMALL);
! 1959: ry[2] = (long) stoi(2);
! 1960: ry = cgetg(3, t_VEC);
! 1961: res[2] = (long) ry;
! 1962: ry[1] = lgetg(lg(gl->L), t_VECSMALL);
! 1963: ry[2] = (long) stoi(2);
! 1964: ry = cgetg(3, t_VEC);
! 1965: res[3] = (long) ry;
! 1966: ry[1] = lgetg(lg(gl->L), t_VECSMALL);
! 1967: ry[2] = (long) stoi(3);
! 1968: ry = cgetg(3, t_VEC);
! 1969: res[4] = (long) ry;
! 1970: ry[1] = lgetg(lg(gl->L), t_VECSMALL);
! 1971: ry[2] = (long) stoi(2);
! 1972: ltop2 = avma;
! 1973: sg = cgetg(7, t_VECSMALL);
! 1974: pj = cgetg(7, t_VECSMALL);
! 1975: sigma = cgetg(lg(gl->L), t_VECSMALL);
! 1976: tau = cgetg(lg(gl->L), t_VECSMALL);
! 1977: phi = cgetg(lg(gl->L), t_VECSMALL);
! 1978: for (i = 1; i < lg(sg); i++)
! 1979: sg[i] = i;
! 1980: Tmod = (GEN) factmod(gl->T, p)[1];
! 1981: isom = cgetg(lg(Tmod), t_VEC);
! 1982: isominv = cgetg(lg(Tmod), t_VEC);
! 1983: misom = cgetg(lg(Tmod), t_MAT);
! 1984: inittestlift(Tmod, 1, gl, >, NULL);
! 1985: bezoutcoeff = gt.bezoutcoeff;
! 1986: pauto = gt.pauto;
! 1987: for (i = 1; i < lg(pj); i++)
! 1988: pj[i] = 0;
! 1989: for (i = 1; i < lg(isom); i++)
! 1990: {
! 1991: misom[i] = lgetg(lg(Tmod), t_COL);
! 1992: isom[i] = (long) Fpisom(p, (GEN) Tmod[1], (GEN) Tmod[i]);
! 1993: if (DEBUGLEVEL >= 4)
! 1994: fprintferr("S4GaloisConj:Computing isomorphisms %d:%Z\n", i, (GEN) isom[i]);
! 1995: isominv[i] = (long) lift(Fpinvisom((GEN) isom[i]));
! 1996: }
! 1997: for (i = 1; i < lg(isom); i++)
! 1998: for (j = 1; j < lg(isom); j++)
! 1999: ((GEN **) misom)[i][j] = gsubst((GEN) isominv[i], v, (GEN) isom[j]);
! 2000: liftpow = cgetg(24, t_VEC);
! 2001: av = avma;
! 2002: for (i = 0; i < 3; i++)
! 2003: {
! 2004: ulong av2;
! 2005: GEN u;
! 2006: int j1, j2, j3;
! 2007: ulong avm1, avm2;
! 2008: GEN u1, u2, u3;
! 2009: if (i)
! 2010: {
! 2011: int x;
! 2012: x = sg[3];
! 2013: if (i == 1)
! 2014: {
! 2015: sg[3] = sg[2];
! 2016: sg[2] = x;
! 2017: } else
! 2018: {
! 2019: sg[3] = sg[1];
! 2020: sg[1] = x;
! 2021: }
! 2022: }
! 2023: u = chinois(((GEN **) misom)[sg[1]][sg[2]],
! 2024: ((GEN **) misom)[sg[2]][sg[1]]);
! 2025: u = chinois(u, ((GEN **) misom)[sg[3]][sg[4]]);
! 2026: u = chinois(u, ((GEN **) misom)[sg[4]][sg[3]]);
! 2027: u = chinois(u, ((GEN **) misom)[sg[5]][sg[6]]);
! 2028: u = chinois(u, ((GEN **) misom)[sg[6]][sg[5]]);
! 2029: makelift(u, gl, liftpow);
! 2030: av2 = avma;
! 2031: for (j1 = 0; j1 < 4; j1++)
! 2032: {
! 2033: u1 = gadd(gmul((GEN) bezoutcoeff[sg[5]], (GEN) pauto[1 + j1]),
! 2034: gmul((GEN) bezoutcoeff[sg[6]], (GEN) pauto[((-j1) & 3) + 1]));
! 2035: avm1 = avma;
! 2036: for (j2 = 0; j2 < 4; j2++)
! 2037: {
! 2038: u2 = gadd(u1, gmul((GEN) bezoutcoeff[sg[3]], (GEN) pauto[1 + j2]));
! 2039: u2 = gadd(u2, gmul((GEN) bezoutcoeff[sg[4]], (GEN) pauto[((-j2) & 3) + 1]));
! 2040: avm2 = avma;
! 2041: for (j3 = 0; j3 < 4; j3++)
! 2042: {
! 2043: u3 = gadd(u2, gmul((GEN) bezoutcoeff[sg[1]], (GEN) pauto[1 + j3]));
! 2044: u3 = gadd(u3, gmul((GEN) bezoutcoeff[sg[2]], (GEN) pauto[((-j3) & 3) + 1]));
! 2045: if (DEBUGLEVEL >= 4)
! 2046: fprintferr("S4GaloisConj:Testing %d/3:%d/4:%d/4:%d/4:%Z\n", i, j1, j2, j3, sg);
! 2047: if (s4test(u3, liftpow, gl, sigma))
! 2048: {
! 2049: pj[1] = j3;
! 2050: pj[2] = j2, pj[3] = j1;
! 2051: goto suites4;
! 2052: }
! 2053: avma = avm2;
! 2054: }
! 2055: avma = avm1;
! 2056: }
! 2057: avma = av2;
! 2058: }
! 2059: avma = av;
! 2060: }
! 2061: avma = ltop;
! 2062: return gzero;
! 2063: suites4:
! 2064: if (DEBUGLEVEL >= 4)
! 2065: fprintferr("S4GaloisConj:sigma=%Z\n", sigma);
! 2066: if (DEBUGLEVEL >= 4)
! 2067: fprintferr("S4GaloisConj:pj=%Z\n", pj);
! 2068: avma = av;
! 2069: for (j = 1; j <= 3; j++)
! 2070: {
! 2071: ulong av2;
! 2072: GEN u;
! 2073: int w, l;
! 2074: int z;
! 2075: z = sg[1];
! 2076: sg[1] = sg[3];
! 2077: sg[3] = sg[5];
! 2078: sg[5] = z;
! 2079: z = sg[2];
! 2080: sg[2] = sg[4];
! 2081: sg[4] = sg[6];
! 2082: sg[6] = z;
! 2083: z = pj[1];
! 2084: pj[1] = pj[2];
! 2085: pj[2] = pj[3];
! 2086: pj[3] = z;
! 2087: for (l = 0; l < 2; l++)
! 2088: {
! 2089: u = chinois(((GEN **) misom)[sg[1]][sg[3]],
! 2090: ((GEN **) misom)[sg[3]][sg[1]]);
! 2091: u = chinois(u, ((GEN **) misom)[sg[2]][sg[4]]);
! 2092: u = chinois(u, ((GEN **) misom)[sg[4]][sg[2]]);
! 2093: u = chinois(u, ((GEN **) misom)[sg[5]][sg[6]]);
! 2094: u = chinois(u, ((GEN **) misom)[sg[6]][sg[5]]);
! 2095: makelift(u, gl, liftpow);
! 2096: av2 = avma;
! 2097: for (w = 0; w < 4; w += 2)
! 2098: {
! 2099: GEN uu;
! 2100: long av3;
! 2101: pj[6] = (w + pj[3]) & 3;
! 2102: uu = gadd(gmul((GEN) bezoutcoeff[sg[5]], (GEN) pauto[(pj[6] & 3) + 1]),
! 2103: gmul((GEN) bezoutcoeff[sg[6]], (GEN) pauto[((-pj[6]) & 3) + 1]));
! 2104: av3 = avma;
! 2105: for (i = 0; i < 4; i++)
! 2106: {
! 2107: GEN u;
! 2108: pj[4] = i;
! 2109: pj[5] = (i + pj[2] - pj[1]) & 3;
! 2110: if (DEBUGLEVEL >= 4)
! 2111: fprintferr("S4GaloisConj:Testing %d/3:%d/2:%d/2:%d/4:%Z:%Z\n", j - 1, w >> 1, l, i, sg, pj);
! 2112: u = gadd(uu, gmul((GEN) pauto[(pj[4] & 3) + 1], (GEN) bezoutcoeff[sg[1]]));
! 2113: u = gadd(u, gmul((GEN) pauto[((-pj[4]) & 3) + 1], (GEN) bezoutcoeff[sg[3]]));
! 2114: u = gadd(u, gmul((GEN) pauto[(pj[5] & 3) + 1], (GEN) bezoutcoeff[sg[2]]));
! 2115: u = gadd(u, gmul((GEN) pauto[((-pj[5]) & 3) + 1], (GEN) bezoutcoeff[sg[4]]));
! 2116: if (s4test(u, liftpow, gl, tau))
! 2117: goto suites4_2;
! 2118: avma = av3;
! 2119: }
! 2120: avma = av2;
! 2121: }
! 2122: z = sg[4];
! 2123: sg[4] = sg[3];
! 2124: sg[3] = z;
! 2125: pj[2] = (-pj[2]) & 3;
! 2126: avma = av;
! 2127: }
! 2128: }
! 2129: avma = ltop;
! 2130: return gzero;
! 2131: suites4_2:
! 2132: avma = av;
! 2133: {
! 2134: int abc, abcdef;
! 2135: GEN u;
! 2136: ulong av2;
! 2137: abc = (pj[1] + pj[2] + pj[3]) & 3;
! 2138: abcdef = (((abc + pj[4] + pj[5] - pj[6]) & 3) >> 1);
! 2139: u = chinois(((GEN **) misom)[sg[1]][sg[4]],
! 2140: ((GEN **) misom)[sg[4]][sg[1]]);
! 2141: u = chinois(u, ((GEN **) misom)[sg[2]][sg[5]]);
! 2142: u = chinois(u, ((GEN **) misom)[sg[5]][sg[2]]);
! 2143: u = chinois(u, ((GEN **) misom)[sg[3]][sg[6]]);
! 2144: u = chinois(u, ((GEN **) misom)[sg[6]][sg[3]]);
! 2145: makelift(u, gl, liftpow);
! 2146: av2 = avma;
! 2147: for (j = 0; j < 8; j++)
! 2148: {
! 2149: int h, g, i;
! 2150: h = j & 3;
! 2151: g = abcdef + ((j & 4) >> 1);
! 2152: i = h + abc - g;
! 2153: u = gmul((GEN) pauto[(g & 3) + 1], (GEN) bezoutcoeff[sg[1]]);
! 2154: u = gadd(u, gmul((GEN) pauto[((-g) & 3) + 1], (GEN) bezoutcoeff[sg[4]]));
! 2155: u = gadd(u, gmul((GEN) pauto[(h & 3) + 1], (GEN) bezoutcoeff[sg[2]]));
! 2156: u = gadd(u, gmul((GEN) pauto[((-h) & 3) + 1], (GEN) bezoutcoeff[sg[5]]));
! 2157: u = gadd(u, gmul((GEN) pauto[(i & 3) + 1], (GEN) bezoutcoeff[sg[3]]));
! 2158: u = gadd(u, gmul((GEN) pauto[((-i) & 3) + 1], (GEN) bezoutcoeff[sg[6]]));
! 2159: if (DEBUGLEVEL >= 4)
! 2160: fprintferr("S4GaloisConj:Testing %d/8 %d:%d:%d\n", j, g & 3, h & 3, i & 3);
! 2161: if (s4test(u, liftpow, gl, phi))
! 2162: break;
! 2163: avma = av2;
! 2164: }
! 2165: }
! 2166: if (j == 8)
! 2167: {
! 2168: avma = ltop;
! 2169: return gzero;
! 2170: }
! 2171: for (i = 1; i < lg(gl->L); i++)
! 2172: {
! 2173: ((GEN **) res)[1][1][i] = sigma[tau[i]];
! 2174: ((GEN **) res)[2][1][i] = phi[sigma[tau[phi[i]]]];
! 2175: ((GEN **) res)[3][1][i] = phi[sigma[i]];
! 2176: ((GEN **) res)[4][1][i] = sigma[i];
! 2177: }
! 2178: avma = ltop2;
! 2179: return res;
! 2180: }
! 2181: GEN
! 2182: galoisgen(GEN T, GEN L, GEN M, GEN den, struct galois_borne * gb, const struct galois_analysis * ga)
! 2183: {
! 2184: struct galois_analysis Pga;
! 2185: struct galois_borne Pgb;
! 2186: struct galois_test td;
! 2187: struct galois_testlift gt;
! 2188: struct galois_lift gl;
! 2189: ulong ltop = avma, lbot;
! 2190: long n, p, deg, ex;
! 2191: byteptr primepointer;
! 2192: long sg, Pm = 0, fp;
! 2193: long x = varn(T);
! 2194: int i, j;
! 2195: GEN Tmod, res, pf = gzero, split, psi, ip, mod, ppsi;
! 2196: GEN frob;
! 2197: GEN O;
! 2198: GEN P, PG, PL, Pden, PM, Pmod, Pp;
! 2199: GEN *lo; /* tired of casting */
! 2200: n = degree(T);
! 2201: if (!ga->deg)
! 2202: return gzero;
! 2203: p = ga->p;
! 2204: ex = ga->exception;
! 2205: deg = ga->deg;
! 2206: primepointer = ga->primepointer;
! 2207: if (DEBUGLEVEL >= 9)
! 2208: fprintferr("GaloisConj:denominator:%Z\n", den);
! 2209: if (n == 12 && ga->ord == 3) /* A4 is very probable,so test it first */
! 2210: {
! 2211: long av = avma;
! 2212: if (DEBUGLEVEL >= 4)
! 2213: fprintferr("GaloisConj:Testing A4 first\n");
! 2214: inittest(L, M, gb->bornesol, gb->ladicsol, &td);
! 2215: lbot = avma;
! 2216: PG = a4galoisgen(T, &td);
! 2217: freetest(&td);
! 2218: if (PG != gzero)
! 2219: {
! 2220: return gerepile(ltop, lbot, PG);
! 2221: }
! 2222: avma = av;
! 2223: }
! 2224: if (n == 24 && ga->ord == 3) /* S4 is very probable,so test it first */
! 2225: {
! 2226: long av = avma;
! 2227: if (DEBUGLEVEL >= 4)
! 2228: fprintferr("GaloisConj:Testing S4 first\n");
! 2229: lbot = avma;
! 2230: initlift(T, den, stoi(ga->p4), gb->bornesol, L, &gl);
! 2231: PG = s4galoisgen(&gl);
! 2232: if (PG != gzero)
! 2233: {
! 2234: return gerepile(ltop, lbot, PG);
! 2235: }
! 2236: avma = av;
! 2237: }
! 2238: frob = cgetg(lg(L), t_VECSMALL);
! 2239: for (;;)
! 2240: {
! 2241: ulong av = avma;
! 2242: long isram;
! 2243: long c;
! 2244: ip = stoi(p);
! 2245: Tmod = (GEN) factmod(T, ip);
! 2246: isram = 0;
! 2247: for (i = 1; i < lg(Tmod[2]) && !isram; i++)
! 2248: if (!gcmp1(((GEN **) Tmod)[2][i]))
! 2249: isram = 1;
! 2250: if (isram == 0)
! 2251: {
! 2252: fp = degree(((GEN **) Tmod)[1][1]);
! 2253: for (i = 2; i < lg(Tmod[1]); i++)
! 2254: if (degree(((GEN **) Tmod)[1][i]) != fp)
! 2255: {
! 2256: avma = ltop;
! 2257: return gzero; /* Not Galois polynomial */
! 2258: }
! 2259: if (fp % deg == 0)
! 2260: {
! 2261: if (DEBUGLEVEL >= 4)
! 2262: fprintferr("Galoisconj:p=%d deg=%d fp=%d\n", p, deg, fp);
! 2263: lo = (GEN *) listsousgroupes(deg, n / fp);
! 2264: initlift(T, den, ip, gb->bornesol, L, &gl);
! 2265: if (inittestlift((GEN) Tmod[1], fp / deg, &gl, >, frob))
! 2266: {
! 2267: int k;
! 2268: sg = lg(lo) - 1;
! 2269: psi = cgetg(gt.g + 1, t_VECSMALL);
! 2270: for (k = 1; k <= gt.g; k++)
! 2271: psi[k] = 1;
! 2272: goto suite;
! 2273: }
! 2274: if (DEBUGLEVEL >= 4)
! 2275: fprintferr("Galoisconj:Subgroups list:%Z\n", (GEN) lo);
! 2276: if (deg == fp && cgcd(deg, n / deg) == 1) /* Pretty sure it's the
! 2277: * biggest ? */
! 2278: {
! 2279: for (sg = 1; sg < lg(lo) - 1; sg++)
! 2280: if (frobeniusliftall(lo[sg], &psi, &gl, >, frob))
! 2281: goto suite;
! 2282: } else
! 2283: {
! 2284: for (sg = lg(lo) - 2; sg >= 1; sg--) /* else start with the
! 2285: * fastest! */
! 2286: if (frobeniusliftall(lo[sg], &psi, &gl, >, frob))
! 2287: goto suite;
! 2288: }
! 2289: if (ex == 1 && (n == 12 || n % 12 != 0))
! 2290: {
! 2291: avma = ltop;
! 2292: return gzero;
! 2293: } else
! 2294: {
! 2295: ex--;
! 2296: if (n % 12 == 0)
! 2297: {
! 2298: if (n % 36 == 0)
! 2299: deg = 5 - deg;
! 2300: else
! 2301: deg = 2; /* For group like Z/2ZxA4 */
! 2302: }
! 2303: if (n % 12 == 0 && ex == -5)
! 2304: err(warner, "galoisconj _may_ hang up for this polynomial");
! 2305: }
! 2306: }
! 2307: }
! 2308: c = *primepointer++;
! 2309: if (!c)
! 2310: err(primer1);
! 2311: p += c;
! 2312: if (DEBUGLEVEL >= 4)
! 2313: fprintferr("GaloisConj:next p=%d\n", p);
! 2314: avma = av;
! 2315: }
! 2316: suite: /* Djikstra probably hates me. (Linus
! 2317: * Torvalds linux/kernel/sched.c) */
! 2318: if (deg == n) /* Cyclique */
! 2319: {
! 2320: lbot = avma;
! 2321: res = cgetg(2, t_VEC);
! 2322: res[1] = lgetg(3, t_VEC);
! 2323: ((GEN **) res)[1][1] = gcopy(frob);
! 2324: ((GEN **) res)[1][2] = stoi(deg);
! 2325: return gerepile(ltop, lbot, res);
! 2326: }
! 2327: if (DEBUGLEVEL >= 9)
! 2328: fprintferr("GaloisConj:Frobenius:%Z\n", frob);
! 2329: O = permtocycle(frob);
! 2330: if (DEBUGLEVEL >= 9)
! 2331: fprintferr("GaloisConj:Orbite:%Z\n", O);
! 2332: {
! 2333: GEN S, Tp, Fi, Sp;
! 2334: long gp = n / fp;
! 2335: ppsi = cgetg(gp + 1, t_VECSMALL);
! 2336: mod = gmodulcp(gun, ip);
! 2337: P = corpsfixeorbitemod(L, O, x, mod, gb->l, &PL);
! 2338: S = corpsfixeinclusion(O, PL);
! 2339: S = vectopol(S, L, M, den, x);
! 2340: if (DEBUGLEVEL >= 6)
! 2341: fprintferr("GaloisConj:Inclusion:%Z\n", S);
! 2342: Pmod = (GEN) factmod(P, ip)[1];
! 2343: Tp = gmul(T, mod);
! 2344: Sp = gmul(S, mod);
! 2345: Pp = gmul(P, mod);
! 2346: if (DEBUGLEVEL >= 4)
! 2347: fprintferr("GaloisConj:psi=%Z\n", psi);
! 2348: if (DEBUGLEVEL >= 4)
! 2349: fprintferr("GaloisConj:Pmod=%Z\n", Pmod);
! 2350: if (DEBUGLEVEL >= 4)
! 2351: fprintferr("GaloisConj:Tmod=%Z\n", Tmod);
! 2352: for (i = 1; i <= gp; i++)
! 2353: {
! 2354: Fi = ggcd(Tp, gsubst((GEN) Pmod[i], x, Sp));
! 2355: Fi = gdiv(Fi, (GEN) Fi[lgef(Fi) - 1]);
! 2356: if (DEBUGLEVEL >= 6)
! 2357: fprintferr("GaloisConj:Fi=%Z %d", Fi, i);
! 2358: for (j = 1; j <= gp; j++)
! 2359: if (gegal(Fi, ((GEN **) Tmod)[1][j]))
! 2360: break;
! 2361: if (DEBUGLEVEL >= 6)
! 2362: fprintferr("-->%d\n", j);
! 2363: if (j == gp + 1)
! 2364: {
! 2365: avma = ltop;
! 2366: return gzero;
! 2367: }
! 2368: if (j == gp)
! 2369: {
! 2370: Pm = i;
! 2371: ppsi[i] = 1;
! 2372: } else
! 2373: ppsi[i] = psi[j];
! 2374: }
! 2375: if (DEBUGLEVEL >= 4)
! 2376: fprintferr("GaloisConj:Pm=%d ppsi=%Z\n", Pm, ppsi);
! 2377: galoisanalysis(P, &Pga, 0);
! 2378: if (Pga.deg == 0)
! 2379: {
! 2380: avma = ltop;
! 2381: return gzero; /* Avoid computing the discriminant */
! 2382: }
! 2383: Pden = gabs(mycoredisc(discsr(P)), DEFAULTPREC);
! 2384: Pgb.l = gb->l;
! 2385: initborne(P, Pden, &Pgb, Pga.ppp);
! 2386: if (Pgb.valabs > gb->valabs)
! 2387: PL = recalculeL(P, deriv(P, x), PL, gb, &Pgb);
! 2388: PM = vandermondeinverse(PL, P, Pden);
! 2389: PG = galoisgen(P, PL, PM, Pden, &Pgb, &Pga);
! 2390: }
! 2391: if (DEBUGLEVEL >= 4)
! 2392: fprintferr("GaloisConj:Retour sur Terre:%Z\n", PG);
! 2393: if (PG == gzero)
! 2394: {
! 2395: avma = ltop;
! 2396: return gzero;
! 2397: }
! 2398: inittest(L, M, gb->bornesol, gb->ladicsol, &td);
! 2399: split = splitorbite(O);
! 2400: lbot = avma;
! 2401: res = cgetg(lg(PG) + lg(split) - 1, t_VEC);
! 2402: for (i = 1; i < lg(split); i++)
! 2403: res[i] = lcopy((GEN) split[i]);
! 2404: for (j = 1; j < lg(PG); j++)
! 2405: {
! 2406: ulong lbot = 0, av = avma;
! 2407: GEN B, tau;
! 2408: long t, g;
! 2409: long w, sr, dss;
! 2410: if (DEBUGLEVEL >= 6)
! 2411: fprintferr("GaloisConj:G[%d][1]=%Z\n", j, ((GEN **) PG)[j][1]);
! 2412: B = permtocycle(((GEN **) PG)[j][1]);
! 2413: if (DEBUGLEVEL >= 6)
! 2414: fprintferr("GaloisConj:B=%Z\n", B);
! 2415: tau = gmul(mod, permtopol(((GEN **) PG)[j][1], PL, PM, Pden, x));
! 2416: tau = gsubst((GEN) Pmod[Pm], x, tau);
! 2417: tau = ggcd(Pp, tau);
! 2418: tau = gdiv(tau, (GEN) tau[lgef(tau) - 1]);
! 2419: if (DEBUGLEVEL >= 6)
! 2420: fprintferr("GaloisConj:tau=%Z\n", tau);
! 2421: for (g = 1; g < lg(Pmod); g++)
! 2422: if (gegal(tau, (GEN) Pmod[g]))
! 2423: break;
! 2424: if (g == lg(Pmod))
! 2425: {
! 2426: freetest(&td);
! 2427: avma = ltop;
! 2428: return gzero;
! 2429: }
! 2430: w = ((long **) lo)[sg][ppsi[g]];
! 2431: dss = deg / cgcd(deg, w - 1);
! 2432: sr = 1;
! 2433: for (i = 1; i < lg(B[1]) - 1; i++)
! 2434: sr = (1 + sr * w) % deg;
! 2435: sr = cgcd(sr, deg);
! 2436: if (DEBUGLEVEL >= 6)
! 2437: fprintferr("GaloisConj:w=%d [%d] sr=%d dss=%d\n", w, deg, sr, dss);
! 2438: for (t = 0; t < sr; t += dss)
! 2439: {
! 2440: lbot = avma;
! 2441: pf = testpermutation(O, B, w, t, sr, &td);
! 2442: if (pf != gzero)
! 2443: break;
! 2444: }
! 2445: if (pf == gzero)
! 2446: {
! 2447: freetest(&td);
! 2448: avma = ltop;
! 2449: return gzero;
! 2450: } else
! 2451: {
! 2452: GEN f;
! 2453: f = cgetg(3, t_VEC);
! 2454: f[1] = (long) pf;
! 2455: f[2] = (long) gcopy(((GEN **) PG)[j][2]);
! 2456: res[lg(split) + j - 1] = (long) gerepile(av, lbot, f);
! 2457: }
! 2458: }
! 2459: if (DEBUGLEVEL >= 4)
! 2460: fprintferr("GaloisConj:Fini!\n");
! 2461: freetest(&td);
! 2462: return gerepile(ltop, lbot, res);
! 2463: }
! 2464: /*
! 2465: * T: polynome ou nf den optionnel: si présent doit etre un multiple du
! 2466: * dénominateur commun des solutions Si T est un nf et den n'est pas présent,
! 2467: * le denominateur de la base d'entiers est pris pour den
! 2468: */
! 2469: GEN
! 2470: galoisconj4(GEN T, GEN den, long flag)
! 2471: {
! 2472: ulong ltop = avma, lbot;
! 2473: GEN G, L, M, res, aut, L2, M2, grp;
! 2474: struct galois_analysis ga;
! 2475: struct galois_borne gb;
! 2476: int n, i, j, k;
! 2477: if (typ(T) != t_POL)
! 2478: {
! 2479: T = checknf(T);
! 2480: if (!den)
! 2481: den = gcoeff((GEN) T[8], degree((GEN) T[1]), degree((GEN) T[1]));
! 2482: T = (GEN) T[1];
! 2483: }
! 2484: n = lgef(T) - 3;
! 2485: if (n <= 0)
! 2486: err(constpoler, "galoisconj4");
! 2487: for (k = 2; k <= n + 2; k++)
! 2488: if (typ(T[k]) != t_INT)
! 2489: err(talker, "polynomial not in Z[X] in galoisconj4");
! 2490: if (!gcmp1((GEN) T[n + 2]))
! 2491: err(talker, "non-monic polynomial in galoisconj4");
! 2492: n = degree(T);
! 2493: if (n == 1) /* Too easy! */
! 2494: {
! 2495: res = cgetg(2, t_COL);
! 2496: res[1] = (long) polx[varn(T)];
! 2497: return res;
! 2498: }
! 2499: galoisanalysis(T, &ga, 1);
! 2500: if (ga.deg == 0)
! 2501: {
! 2502: avma = ltop;
! 2503: return stoi(ga.p); /* Avoid computing the discriminant */
! 2504: }
! 2505: if (!den)
! 2506: den = absi(mycoredisc(discsr(T)));
! 2507: else
! 2508: {
! 2509: if (typ(den) != t_INT)
! 2510: err(talker, "Second arg. must be integer in galoisconj4");
! 2511: den = absi(den);
! 2512: }
! 2513: gb.l = stoi(ga.l);
! 2514: initborne(T, den, &gb, ga.ppp);
! 2515: if (DEBUGLEVEL >= 1)
! 2516: timer2();
! 2517: {
! 2518: GEN f = rootpadic(T, gb.l, gb.valabs);
! 2519: GEN _p = gmael(f, 1, 2);
! 2520: L = gmul(gtrunc(f), gmodulcp(gun, gb.ladicabs));
! 2521: gunclone(_p);
! 2522: }
! 2523: if (DEBUGLEVEL >= 1)
! 2524: msgtimer("rootpadic()");
! 2525: M = vandermondeinverse(L, T, den);
! 2526: G = galoisgen(T, L, M, den, &gb, &ga);
! 2527: if (DEBUGLEVEL >= 6)
! 2528: fprintferr("GaloisConj:%Z\n", G);
! 2529: if (G == gzero)
! 2530: {
! 2531: avma = ltop;
! 2532: return gzero;
! 2533: }
! 2534: if (DEBUGLEVEL >= 1)
! 2535: timer2();
! 2536: L2 = gmul(L, gmodulcp(gun, gb.ladicsol));
! 2537: M2 = gmul(M, gmodulcp(gun, gb.ladicsol));
! 2538: if (flag)
! 2539: {
! 2540: lbot = avma;
! 2541: grp = cgetg(7, t_VEC);
! 2542: grp[1] = (long) gcopy(T);
! 2543: grp[2] = (long) stoi(ga.l);
! 2544: grp[3] = (long) gcopy(L);
! 2545: grp[4] = (long) gcopy(M);
! 2546: grp[5] = (long) gcopy(den);
! 2547: }
! 2548: res = cgetg(n + 1, t_VEC);
! 2549: res[1] = (long) permidentity(n);
! 2550: k = 1;
! 2551: for (i = 1; i < lg(G); i++)
! 2552: {
! 2553: int c = k * (itos(((GEN **) G)[i][2]) - 1);
! 2554: for (j = 1; j <= c; j++) /* I like it */
! 2555: res[++k] = (long) applyperm((GEN) res[j], ((GEN **) G)[i][1]);
! 2556: }
! 2557: if (flag)
! 2558: {
! 2559: grp[6] = (long) res;
! 2560: return gerepile(ltop, lbot, grp);
! 2561: }
! 2562: aut = cgetg(n + 1, t_COL);
! 2563: for (i = 1; i <= n; i++)
! 2564: aut[i] = (long) permtopol((GEN) res[i], L2, M2, den, varn(T));
! 2565: if (DEBUGLEVEL >= 1)
! 2566: msgtimer("Calcul polynomes");
! 2567: return gerepileupto(ltop, aut);
! 2568: }
! 2569: /* Calcule le nombre d'automorphisme de T avec forte probabilité */
! 2570: /* pdepart premier nombre premier a tester */
! 2571: long
! 2572: numberofconjugates(GEN T, long pdepart)
! 2573: {
! 2574: ulong ltop = avma, ltop2;
! 2575: long n, p, nbmax, nbtest;
! 2576: long card;
! 2577: byteptr primepointer;
! 2578: int i;
! 2579: GEN L;
! 2580: n = degree(T);
! 2581: card = sturm(T);
! 2582: card = cgcd(card, n - card);
! 2583: nbmax = n + 1;
! 2584: nbtest = 0;
! 2585: L = cgetg(n + 1, t_VECSMALL);
! 2586: ltop2 = avma;
! 2587: for (p = 0, primepointer = diffptr; nbtest < nbmax && card > 1;)
! 2588: {
! 2589: long s, c;
! 2590: long isram;
! 2591: GEN S;
! 2592: c = *primepointer++;
! 2593: if (!c)
! 2594: err(primer1);
! 2595: p += c;
! 2596: if (p < pdepart)
! 2597: continue;
! 2598: S = (GEN) simplefactmod(T, stoi(p));
! 2599: isram = 0;
! 2600: for (i = 1; i < lg(S[2]) && !isram; i++)
! 2601: if (!gcmp1(((GEN **) S)[2][i]))
! 2602: isram = 1;
! 2603: if (isram == 0)
! 2604: {
! 2605: for (i = 1; i <= n; i++)
! 2606: L[i] = 0;
! 2607: for (i = 1; i < lg(S[1]) && !isram; i++)
! 2608: L[itos(((GEN **) S)[1][i])]++;
! 2609: s = L[1];
! 2610: for (i = 2; i <= n; i++)
! 2611: s = cgcd(s, L[i] * i);
! 2612: card = cgcd(s, card);
! 2613: }
! 2614: if (DEBUGLEVEL >= 6)
! 2615: fprintferr("NumberOfConjugates:Nbtest=%d,card=%d,p=%d\n", nbtest, card, p);
! 2616: nbtest++;
! 2617: avma = ltop2;
! 2618: }
! 2619: if (DEBUGLEVEL >= 2)
! 2620: fprintferr("NumberOfConjugates:card=%d,p=%d\n", card, p);
! 2621: avma = ltop;
! 2622: return card;
! 2623: }
! 2624: GEN
! 2625: galoisconj0(GEN nf, long flag, GEN d, long prec)
! 2626: {
! 2627: GEN G, T;
! 2628: long card;
! 2629: if (typ(nf) != t_POL)
! 2630: {
! 2631: nf = checknf(nf);
! 2632: T = (GEN) nf[1];
! 2633: } else
! 2634: T = nf;
! 2635: switch (flag)
! 2636: {
! 2637: case 0:
! 2638: G = galoisconj4(nf, d, 0);
! 2639: if (typ(G) != t_INT) /* Success */
! 2640: return G;
! 2641: else
! 2642: {
! 2643: card = G == gzero ? degree(T) : numberofconjugates(T, itos(G));
! 2644: if (card != 1)
! 2645: {
! 2646: if (typ(nf) == t_POL)
! 2647: return galoisconj2pol(nf, card, prec);
! 2648: else
! 2649: return galoisconj(nf);
! 2650: }
! 2651: }
! 2652: break; /* Failure */
! 2653: case 1:
! 2654: return galoisconj(nf);
! 2655: case 2:
! 2656: return galoisconj2(nf, degree(T), prec);
! 2657: case 4:
! 2658: G = galoisconj4(nf, d, 0);
! 2659: if (typ(G) != t_INT)
! 2660: return G;
! 2661: break; /* Failure */
! 2662: default:
! 2663: err(flagerr, "nfgaloisconj");
! 2664: }
! 2665: G = cgetg(2, t_COL);
! 2666: G[1] = (long) polx[varn(T)];
! 2667: return G; /* Failure */
! 2668: }
! 2669: /******************************************************************************/
! 2670: /* Galois theory related algorithms */
! 2671: /******************************************************************************/
! 2672: GEN
! 2673: checkgal(GEN gal)
! 2674: {
! 2675: if (typ(gal) == t_POL)
! 2676: err(talker, "please apply galoisinit first");
! 2677: if (typ(gal) != t_VEC || lg(gal) != 7)
! 2678: err(talker, "Not a Galois field in a Galois related function");
! 2679: return gal;
! 2680: }
! 2681: GEN
! 2682: galoisinit(GEN nf, GEN den)
! 2683: {
! 2684: GEN G;
! 2685: G = galoisconj4(nf, den, 1);
! 2686: if (typ(G) == t_INT)
! 2687: err(talker, "galoisinit: field not Galois or Galois group not weakly super solvable");
! 2688: return G;
! 2689: }
! 2690: GEN
! 2691: galoispermtopol(GEN gal, GEN perm)
! 2692: {
! 2693: gal = checkgal(gal);
! 2694: if (typ(perm) != t_VEC)
! 2695: err(typeer, "galoispermtopol:");
! 2696: return permtopol(perm, (GEN) gal[3], (GEN) gal[4], (GEN) gal[5], varn((GEN) gal[1]));
! 2697: }
! 2698: GEN
! 2699: galoisfixedfield(GEN gal, GEN perm, GEN p)
! 2700: {
! 2701: ulong ltop = avma, lbot;
! 2702: GEN P, S, PL, O, res, mod;
! 2703: long x;
! 2704: x = varn((GEN) gal[1]);
! 2705: gal = checkgal(gal);
! 2706: if (typ(perm) != t_VEC)
! 2707: err(typeer, "galoisfixedfield:");
! 2708: if (p)
! 2709: {
! 2710: if (typ(p) != t_INT)
! 2711: err(talker, "galoisfixedfield: optionnal argument must be an prime integer");
! 2712: mod = gmodulcp(gun, p);
! 2713: } else
! 2714: mod = gun;
! 2715: O = vecpermorbite(perm);
! 2716: P = corpsfixeorbitemod((GEN) gal[3], O, x, mod, (GEN) gal[2], &PL);
! 2717: S = corpsfixeinclusion(O, PL);
! 2718: S = vectopol(S, (GEN) gal[3], (GEN) gal[4], (GEN) gal[5], x);
! 2719: lbot = avma;
! 2720: res = cgetg(3, t_VEC);
! 2721: res[1] = (long) gcopy(P);
! 2722: res[2] = (long) gmodulcp(S, (GEN) gal[1]);
! 2723: return gerepile(ltop, lbot, res);
! 2724: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>