Annotation of OpenXM_contrib/pari/src/basemath/base4.c, Revision 1.1
1.1 ! maekawa 1: /*******************************************************************/
! 2: /* */
! 3: /* BASIC NF OPERATIONS */
! 4: /* (continued) */
! 5: /* */
! 6: /*******************************************************************/
! 7: /* $Id: base4.c,v 1.1.1.1 1999/09/16 13:47:22 karim Exp $ */
! 8: #include "pari.h"
! 9: #include "parinf.h"
! 10:
! 11: #define principalideal_aux(nf,x) (principalideal0((nf),(x),0))
! 12:
! 13: GEN element_muli(GEN nf, GEN x, GEN y);
! 14:
! 15: static GEN nfbezout(GEN nf, GEN a, GEN b, GEN ida, GEN idb, GEN *u, GEN *v, GEN *w, GEN *di);
! 16:
! 17: /*******************************************************************/
! 18: /* */
! 19: /* IDEAL OPERATIONS */
! 20: /* */
! 21: /*******************************************************************/
! 22:
! 23: /* A valid ideal is either principal (valid nf_element), or prime, or a matrix
! 24: * on the integer basis (preferably HNF).
! 25: * A prime ideal is of the form [p,a,e,f,b], where the ideal is p.Z_K+a.Z_K,
! 26: * p is a rational prime, a belongs to Z_K, e=e(P/p), f=f(P/p), and b
! 27: * Lenstra constant (p.P^(-1)= p Z_K + b Z_K).
! 28: *
! 29: * An idele is a couple[I,V] where I is a valid ideal and V a row vector
! 30: * with r1+r2 components (real or complex). For instance, if M=(a), V
! 31: * contains the complex logarithms of the first r1+r2 conjugates of a
! 32: * (depends on the chosen generator a). All subroutines work with either
! 33: * ideles or ideals (an omitted V is assumed to be 0).
! 34: *
! 35: * All the output ideals will be in HNF form.
! 36: */
! 37:
! 38: /* types and conversions */
! 39:
! 40: static long
! 41: idealtyp(GEN *ideal, GEN *arch)
! 42: {
! 43: GEN x = *ideal;
! 44: long t,lx,tx = typ(x);
! 45:
! 46: if (tx==t_VEC && lg(x)==3)
! 47: { *arch = (GEN)x[2]; x = (GEN)x[1]; tx = typ(x); }
! 48: else
! 49: *arch = NULL;
! 50: switch(tx)
! 51: {
! 52: case t_MAT: lx = lg(x);
! 53: if (lx>2) t = id_MAT;
! 54: else
! 55: {
! 56: t = id_PRINCIPAL;
! 57: x = (lx==2)? (GEN)x[1]: gzero;
! 58: }
! 59: break;
! 60:
! 61: case t_VEC: if (lg(x)!=6) err(idealer2);
! 62: t = id_PRIME; break;
! 63:
! 64: case t_POL: case t_POLMOD: case t_COL:
! 65: t = id_PRINCIPAL; break;
! 66: default:
! 67: if (tx!=t_INT && !is_frac_t(tx)) err(idealer2);
! 68: t = id_PRINCIPAL;
! 69: }
! 70: *ideal = x; return t;
! 71: }
! 72:
! 73: /* Assume ideal in HNF form */
! 74: long
! 75: ideal_is_zk(GEN ideal,long N)
! 76: {
! 77: long i,j, lx = lg(ideal);
! 78:
! 79: if (typ(ideal) != t_MAT || lx==1) return 0;
! 80: N++; if (lx != N || lg(ideal[1]) != N) return 0;
! 81: for (i=1; i<N; i++)
! 82: {
! 83: if (!gcmp1(gcoeff(ideal,i,i))) return 0;
! 84: for (j=i+1; j<N; j++)
! 85: if (!gcmp0(gcoeff(ideal,i,j))) return 0;
! 86: }
! 87: return 1;
! 88: }
! 89:
! 90: static GEN
! 91: prime_to_ideal_aux(GEN nf, GEN vp)
! 92: {
! 93: GEN m,el;
! 94: long i, N = lgef(nf[1])-3;
! 95:
! 96: m = cgetg(N+1,t_MAT); el = (GEN)vp[2];
! 97: for (i=1; i<=N; i++) m[i] = (long) element_mulid(nf,el,i);
! 98: return hnfmodid(m,(GEN)vp[1]);
! 99: }
! 100:
! 101: GEN
! 102: prime_to_ideal(GEN nf, GEN vp)
! 103: {
! 104: long av=avma;
! 105: if (typ(vp) == t_INT) return gscalmat(vp, lgef(nf[1])-3);
! 106: return gerepileupto(av, prime_to_ideal_aux(nf,vp));
! 107: }
! 108:
! 109: /* x = ideal in matrix form. Put it in hnf. */
! 110: static GEN
! 111: idealmat_to_hnf(GEN nf, GEN x)
! 112: {
! 113: long rx,i,j,N;
! 114: GEN m,dx;
! 115:
! 116: N=lgef(nf[1])-3; rx=lg(x)-1;
! 117: if (!rx) return gscalmat(gzero,N);
! 118:
! 119: dx=denom(x); if (gcmp1(dx)) dx = NULL; else x=gmul(dx,x);
! 120: if (rx >= N) m = x;
! 121: else
! 122: {
! 123: m=cgetg(rx*N + 1,t_MAT);
! 124: for (i=1; i<=rx; i++)
! 125: for (j=1; j<=N; j++)
! 126: m[(i-1)*N + j] = (long) element_mulid(nf,(GEN)x[i],j);
! 127: }
! 128: x = hnfmod(m,detint(m));
! 129: return dx? gdiv(x,dx): x;
! 130: }
! 131:
! 132: int
! 133: ishnfall(GEN x)
! 134: {
! 135: long i,j, lx = lg(x);
! 136: for (i=2; i<lx; i++)
! 137: {
! 138: if (gsigne(gcoeff(x,i,i)) <= 0) return 0;
! 139: for (j=1; j<i; j++)
! 140: if (!gcmp0(gcoeff(x,i,j))) return 0;
! 141: }
! 142: return (gsigne(gcoeff(x,1,1)) > 0);
! 143: }
! 144:
! 145: GEN
! 146: idealhermite_aux(GEN nf, GEN x)
! 147: {
! 148: long N,tx,lx;
! 149: GEN z;
! 150:
! 151: tx = idealtyp(&x,&z);
! 152: if (tx == id_PRIME) return prime_to_ideal(nf,x);
! 153: if (tx == id_PRINCIPAL)
! 154: {
! 155: x = principalideal(nf,x);
! 156: return idealmat_to_hnf(nf,x);
! 157: }
! 158: N=lgef(nf[1])-3; lx = lg(x);
! 159: if (lg(x[1]) != N+1) err(idealer2);
! 160:
! 161: if (lx == N+1 && ishnfall(x)) return x;
! 162: if (lx <= N) return idealmat_to_hnf(nf,x);
! 163: z=denom(x); if (gcmp1(z)) z=NULL; else x = gmul(z,x);
! 164: x = hnfmod(x,detint(x));
! 165: return z? gdiv(x,z): x;
! 166: }
! 167:
! 168: GEN
! 169: idealhermite(GEN nf, GEN x)
! 170: {
! 171: long av=avma;
! 172: GEN p1;
! 173: nf = checknf(nf); p1 = idealhermite_aux(nf,x);
! 174: if (p1==x || p1==(GEN)x[1]) return gcopy(p1);
! 175: return gerepileupto(av,p1);
! 176: }
! 177:
! 178: static GEN
! 179: principalideal0(GEN nf, GEN x, long copy)
! 180: {
! 181: GEN z = cgetg(2,t_MAT);
! 182: switch(typ(x))
! 183: {
! 184: case t_INT: case t_FRAC: case t_FRACN:
! 185: if (copy) x = gcopy(x);
! 186: x = gscalcol_i(x, lgef(nf[1])-3); break;
! 187:
! 188: case t_POLMOD:
! 189: if (!gegal((GEN)nf[1],(GEN)x[1]))
! 190: err(talker,"incompatible number fields in principalideal");
! 191: x=(GEN)x[2]; /* fall through */
! 192: case t_POL:
! 193: x = copy? algtobasis(nf,x): algtobasis_intern(nf,x);
! 194: break;
! 195:
! 196: case t_MAT:
! 197: if (lg(x)!=2) err(typeer,"principalideal");
! 198: x = (GEN)x[1];
! 199: case t_COL:
! 200: if (lg(x)==lgef(nf[1])-2)
! 201: {
! 202: if (copy) x = gcopy(x);
! 203: break;
! 204: }
! 205: default: err(typeer,"principalideal");
! 206: }
! 207: z[1]=(long)x; return z;
! 208: }
! 209:
! 210: GEN
! 211: principalideal(GEN nf, GEN x)
! 212: {
! 213: nf = checknf(nf); return principalideal0(nf,x,1);
! 214: }
! 215:
! 216: /* for internal use */
! 217: GEN
! 218: get_arch(GEN nf,GEN x,long prec)
! 219: {
! 220: long i,R1,RU;
! 221: GEN v,p1,p2;
! 222:
! 223: R1=itos(gmael(nf,2,1)); RU = R1+itos(gmael(nf,2,2));
! 224: if (typ(x)!=t_COL) x = algtobasis_intern(nf,x);
! 225: if (isnfscalar(x)) /* rational number */
! 226: {
! 227: v = cgetg(RU+1,t_VEC);
! 228: p1=glog((GEN)x[1],prec); if (RU!=R1) p2=gmul2n(p1,1);
! 229: for (i=1; i<=R1; i++) v[i]=(long)p1;
! 230: for ( ; i<=RU; i++) v[i]=(long)p2;
! 231: }
! 232: else
! 233: {
! 234: x = gmul(gmael(nf,5,1),x); v = cgetg(RU+1,t_VEC);
! 235: for (i=1; i<=R1; i++) v[i] = llog((GEN)x[i],prec);
! 236: for ( ; i<=RU; i++) v[i] = lmul2n(glog((GEN)x[i],prec),1);
! 237: }
! 238: return v;
! 239: }
! 240:
! 241: GEN
! 242: get_arch_real(GEN nf,GEN x,GEN *emb,long prec)
! 243: {
! 244: long i,R1,RU;
! 245: GEN v,p1,p2;
! 246:
! 247: R1=itos(gmael(nf,2,1)); RU = R1+itos(gmael(nf,2,2));
! 248: if (typ(x)!=t_COL) x = algtobasis_intern(nf,x);
! 249: if (isnfscalar(x)) /* rational number */
! 250: {
! 251: GEN u = (GEN)x[1];
! 252: v = cgetg(RU+1,t_COL);
! 253: i = signe(u);
! 254: if (!i) err(talker,"0 in get_arch_real");
! 255: p1= (i > 0)? glog(u,prec): gzero;
! 256: if (RU != R1) p2 = gmul2n(p1,1);
! 257: for (i=1; i<=R1; i++) v[i]=(long)p1;
! 258: for ( ; i<=RU; i++) v[i]=(long)p2;
! 259: }
! 260: else
! 261: {
! 262: x = gmul(gmael(nf,5,1),x); v = cgetg(RU+1,t_COL);
! 263: for (i=1; i<=R1; i++) v[i] = llog(gabs((GEN)x[i],prec),prec);
! 264: for ( ; i<=RU; i++) v[i] = llog(gnorm((GEN)x[i]),prec);
! 265: }
! 266: *emb = x; return v;
! 267: }
! 268:
! 269: GEN
! 270: principalidele(GEN nf, GEN x, long prec)
! 271: {
! 272: GEN p1,y = cgetg(3,t_VEC);
! 273: long av;
! 274:
! 275: nf = checknf(nf);
! 276: p1 = principalideal0(nf,x,1);
! 277: y[1] = (long)p1;
! 278: av =avma; p1 = get_arch(nf,(GEN)p1[1],prec);
! 279: y[2] = lpileupto(av,p1); return y;
! 280: }
! 281:
! 282: /* GP functions */
! 283:
! 284: GEN
! 285: ideal_two_elt0(GEN nf, GEN x, GEN a)
! 286: {
! 287: if (!a) return ideal_two_elt(nf,x);
! 288: return ideal_two_elt2(nf,x,a);
! 289: }
! 290:
! 291: GEN
! 292: idealpow0(GEN nf, GEN x, GEN n, long flag, long prec)
! 293: {
! 294: if (flag) return idealpowred(nf,x,n,prec);
! 295: return idealpow(nf,x,n);
! 296: }
! 297:
! 298: GEN
! 299: idealmul0(GEN nf, GEN x, GEN y, long flag, long prec)
! 300: {
! 301: if (flag) return idealmulred(nf,x,y,prec);
! 302: return idealmul(nf,x,y);
! 303: }
! 304:
! 305: GEN
! 306: idealpowred(GEN nf, GEN x, GEN n, long prec)
! 307: {
! 308: long av=avma, tetpil;
! 309: x = idealpow(nf,x,n); tetpil=avma;
! 310: return gerepile(av,tetpil, ideallllred(nf,x,NULL,prec));
! 311: }
! 312:
! 313: GEN
! 314: idealmulred(GEN nf, GEN x, GEN y, long prec)
! 315: {
! 316: long av=avma,tetpil;
! 317: x = idealmul(nf,x,y); tetpil=avma;
! 318: return gerepile(av,tetpil,ideallllred(nf,x,NULL,prec));
! 319: }
! 320:
! 321: GEN
! 322: idealinv0(GEN nf, GEN ix, long flag)
! 323: {
! 324: switch(flag)
! 325: {
! 326: case 0: return idealinv(nf,ix);
! 327: case 1: return oldidealinv(nf,ix);
! 328: default: err(flagerr,"idealinv");
! 329: }
! 330: return NULL; /* not reached */
! 331: }
! 332:
! 333: GEN
! 334: idealdiv0(GEN nf, GEN x, GEN y, long flag)
! 335: {
! 336: switch(flag)
! 337: {
! 338: case 0: return idealdiv(nf,x,y);
! 339: case 1: return idealdivexact(nf,x,y);
! 340: default: err(flagerr,"idealdiv");
! 341: }
! 342: return NULL; /* not reached */
! 343: }
! 344:
! 345: GEN
! 346: idealaddtoone0(GEN nf, GEN arg1, GEN arg2)
! 347: {
! 348: if (!arg2) return idealaddmultoone(nf,arg1);
! 349: return idealaddtoone(nf,arg1,arg2);
! 350: }
! 351:
! 352: static GEN
! 353: two_to_hnf(GEN nf, GEN a, GEN b)
! 354: {
! 355: a = principalideal_aux(nf,a);
! 356: b = principalideal_aux(nf,b);
! 357: a = concatsp(a,b);
! 358: if (lgef(nf[1])==5) /* quadratic field: a has to be turned into idealmat */
! 359: a = idealmul(nf,idmat(2),a);
! 360: return idealmat_to_hnf(nf, a);
! 361: }
! 362:
! 363: GEN
! 364: idealhnf0(GEN nf, GEN a, GEN b)
! 365: {
! 366: long av;
! 367: if (!b) return idealhermite(nf,a);
! 368:
! 369: /* HNF of aZ_K+bZ_K */
! 370: av = avma; nf=checknf(nf);
! 371: return gerepileupto(av, two_to_hnf(nf,a,b));
! 372: }
! 373:
! 374: GEN
! 375: idealhermite2(GEN nf, GEN a, GEN b)
! 376: {
! 377: return idealhnf0(nf,a,b);
! 378: }
! 379:
! 380: static GEN
! 381: check_elt(GEN a, GEN pol, GEN pnorm, GEN idz)
! 382: {
! 383: GEN x,norme, p2,p1;
! 384:
! 385: if (!signe(a)) return NULL;
! 386: p1 = content(a);
! 387: if (gcmp1(p1)) { x=a; p1=NULL; }
! 388: else { x=gdiv(a,p1); p2=gpowgs(p1, lgef(pol)-3); }
! 389:
! 390: norme = resultantducos(pol,x); if (p1) norme = gmul(norme,p2);
! 391: if (gcmp1(mppgcd(divii(norme,pnorm),pnorm))) return a;
! 392:
! 393: if (p1)
! 394: {
! 395: idz=gdiv(idz,p1);
! 396: if (typ(idz) == t_FRAC) /* should be exceedingly rare */
! 397: {
! 398: x = gmul(x,(GEN)idz[2]);
! 399: p2 = gdiv(p2, gpowgs((GEN)idz[2], lgef(pol)-3));
! 400: idz = (GEN)idz[1];
! 401: }
! 402: }
! 403: x = gadd(x,idz);
! 404:
! 405: norme = resultantducos(pol,x); if (p1) norme = gmul(norme,p2);
! 406: if (gcmp1(mppgcd(divii(norme,pnorm),pnorm))) return a;
! 407: return NULL;
! 408: }
! 409:
! 410: static void
! 411: setprec(GEN x, long prec)
! 412: {
! 413: long i,j, n=lg(x);
! 414: for (i=1;i<n;i++)
! 415: {
! 416: GEN p2,p1 = (GEN)x[i];
! 417: for (j=1;j<n;j++)
! 418: {
! 419: p2 = (GEN)p1[j];
! 420: if (typ(p2) == t_REAL) setlg(p2, prec);
! 421: }
! 422: }
! 423: }
! 424:
! 425: /* find a basis of x whose elements have small norm
! 426: * M a bound for the size of coeffs of x */
! 427: GEN
! 428: ideal_better_basis(GEN nf, GEN x, GEN M)
! 429: {
! 430: GEN a,b;
! 431: long nfprec = (long)nfnewprec(nf,0);
! 432: long prec = DEFAULTPREC + (expi(M) >> TWOPOTBITS_IN_LONG);
! 433:
! 434: if (typ(nf[5]) != t_VEC) return x;
! 435: if ((prec<<1) < nfprec) prec = (prec+nfprec) >> 1;
! 436: a = qf_base_change(gmael(nf,5,3),x,1);
! 437: setprec(a,prec);
! 438: b = lllgramintern(a,4,1,prec);
! 439: if (!b)
! 440: {
! 441: if (DEBUGLEVEL)
! 442: err(warner, "precision too low in ideal_better_basis (1)");
! 443: if (nfprec > prec)
! 444: {
! 445: setprec(a,nfprec);
! 446: b = lllgramintern(a,4,1,nfprec);
! 447: }
! 448: }
! 449: if (!b)
! 450: {
! 451: if (DEBUGLEVEL)
! 452: err(warner, "precision too low in ideal_better_basis (2)");
! 453: b = lllint(x); /* better than nothing */
! 454: }
! 455: return gmul(x, b);
! 456: }
! 457:
! 458: static GEN
! 459: mat_ideal_two_elt(GEN nf, GEN x)
! 460: {
! 461: GEN y,a,beta,pnorm,con,idz, pol = (GEN)nf[1];
! 462: long av,tetpil,i,z, N = lgef(pol)-3;
! 463:
! 464: y=cgetg(3,t_VEC); av=avma;
! 465: if (lg(x[1])!=N+1) err(typeer,"ideal_two_elt");
! 466: if (N == 2)
! 467: {
! 468: y[1] = lcopy(gcoeff(x,1,1));
! 469: y[2] = lcopy((GEN)x[2]); return y;
! 470: }
! 471:
! 472: con=content(x); if (!gcmp1(con)) x = gdiv(x,con);
! 473: if (lg(x) != N+1) x = idealhermite_aux(nf,x);
! 474: idz=gcoeff(x,1,1);
! 475: if (gcmp1(idz))
! 476: {
! 477: y[1]=lpileupto(av,gcopy(con));
! 478: y[2]=(long)gscalcol(con,N); return y;
! 479: }
! 480: pnorm = dethnf(x);
! 481: beta = gmul((GEN)nf[7], x);
! 482: for (i=2; i<=N; i++)
! 483: {
! 484: a = check_elt((GEN)beta[i], pol, pnorm, idz);
! 485: if (a) break;
! 486: }
! 487: if (i>N)
! 488: {
! 489: x = ideal_better_basis(nf,x,pnorm);
! 490: beta = gmul((GEN)nf[7], x);
! 491: for (i=1; i<=N; i++)
! 492: {
! 493: a = check_elt((GEN)beta[i], pol, pnorm, idz);
! 494: if (a) break;
! 495: }
! 496: }
! 497: if (i>N)
! 498: {
! 499: long c=0, av1=avma;
! 500:
! 501: if (DEBUGLEVEL>3) fprintferr("ideal_two_elt, hard case: ");
! 502: for(;;)
! 503: {
! 504: if (DEBUGLEVEL>3) fprintferr("%d ", ++c);
! 505: a = gzero;
! 506: for (i=1; i<=N; i++)
! 507: {
! 508: z = mymyrand() >> (BITS_IN_RANDOM-5); /* in [0,15] */
! 509: if (z >= 9) z -= 7;
! 510: a = gadd(a,gmulsg(z,(GEN)beta[i]));
! 511: }
! 512: a = check_elt(a, pol, pnorm, idz);
! 513: if (a) break;
! 514: avma=av1;
! 515: }
! 516: if (DEBUGLEVEL>3) fprintferr("\n");
! 517: }
! 518: a = centermod(algtobasis_intern(nf,a), idz);
! 519: tetpil=avma; y[1]=lmul(idz,con); y[2]=lmul(a,con);
! 520: gerepilemanyvec(av,tetpil,y+1,2); return y;
! 521: }
! 522:
! 523: /* Etant donne un ideal ix, ressort un vecteur [a,alpha] a deux composantes
! 524: * tel que a soit rationnel et ix=aZ_K+alpha Z_K, alpha etant un vecteur
! 525: * colonne sur la base d'entiers. On peut avoir a=0 ou alpha=0, mais on ne
! 526: * cherche pas a determiner si ix est principal.
! 527: */
! 528: GEN
! 529: ideal_two_elt(GEN nf, GEN x)
! 530: {
! 531: GEN z;
! 532: long N, tx = idealtyp(&x,&z);
! 533:
! 534: nf=checknf(nf);
! 535: if (tx==id_MAT) return mat_ideal_two_elt(nf,x);
! 536:
! 537: N=lgef(nf[1])-3; z=cgetg(3,t_VEC);
! 538: if (tx == id_PRINCIPAL)
! 539: {
! 540: switch(typ(x))
! 541: {
! 542: case t_INT: case t_FRAC: case t_FRACN:
! 543: z[1]=lcopy(x);
! 544: z[2]=(long)zerocol(N); return z;
! 545:
! 546: case t_POLMOD:
! 547: if (!gegal((GEN)nf[1],(GEN)x[1]))
! 548: err(talker,"incompatible number fields in ideal_two_elt");
! 549: x=(GEN)x[2]; /* fall through */
! 550: case t_POL:
! 551: z[1]=zero; z[2]=(long)algtobasis(nf,x); return z;
! 552: case t_COL:
! 553: if (lg(x)==N+1) { z[1]=zero; z[2]=lcopy(x); return z; }
! 554: }
! 555: }
! 556: else if (tx == id_PRIME)
! 557: {
! 558: z[1]=lcopy((GEN)x[1]);
! 559: z[2]=lcopy((GEN)x[2]); return z;
! 560: }
! 561: err(typeer,"ideal_two_elt");
! 562: return NULL; /* not reached */
! 563: }
! 564:
! 565: /* factorization */
! 566:
! 567: GEN
! 568: idealfactor(GEN nf, GEN x)
! 569: {
! 570: long av,tx, tetpil,i,j,k,lf,lff,N,ls,v,vd;
! 571: GEN d,f,f1,f2,ff,ff1,ff2,y1,y2,y,p1,p2,denx;
! 572:
! 573: tx = idealtyp(&x,&y);
! 574: if (tx == id_PRIME)
! 575: {
! 576: y=cgetg(3,t_MAT);
! 577: y[1]=lgetg(2,t_COL); mael(y,1,1)=lcopy(x);
! 578: y[2]=lgetg(2,t_COL); mael(y,2,1)=un; return y;
! 579: }
! 580: nf=checknf(nf); av=avma;
! 581: if (tx == id_PRINCIPAL) x = principalideal_aux(nf,x);
! 582:
! 583: N=lgef(nf[1])-3; if (lg(x) != N+1) x = idealmat_to_hnf(nf,x);
! 584: if (lg(x)==1) err(talker,"zero ideal in idealfactor");
! 585: denx=denom(x);
! 586: if (gcmp1(denx)) lff=1;
! 587: else
! 588: {
! 589: ff=factor(denx); ff1=(GEN)ff[1]; ff2=(GEN)ff[2];
! 590: lff=lg(ff1); x=gmul(denx,x);
! 591: }
! 592: for (d=gun,i=1; i<=N; i++) d=mulii(d,gcoeff(x,i,i));
! 593: f=factor(absi(d)); f1=(GEN)f[1]; f2=(GEN)f[2]; lf=lg(f1);
! 594: y1=cgetg((lf+lff-2)*N+1,t_COL); y2=new_chunk((lf+lff-2)*N+1);
! 595: k=0;
! 596: for (i=1; i<lf; i++)
! 597: {
! 598: p1=primedec(nf,(GEN)f1[i]); ls=itos((GEN)f2[i]);
! 599: vd=ggval(denx,(GEN)f1[i]);
! 600: for (j=1; j<lg(p1); j++)
! 601: {
! 602: p2=(GEN)p1[j];
! 603: if (ls)
! 604: {
! 605: v = idealval(nf,x,p2);
! 606: ls -= v*itos((GEN)p2[4]);
! 607: v -= vd*itos((GEN)p2[3]);
! 608: }
! 609: else v = - vd*itos((GEN)p2[3]);
! 610: if (v) { y1[++k]=(long)p2; y2[k]=v; }
! 611: }
! 612: }
! 613: for (i=1; i<lff; i++)
! 614: if (!divise(d,(GEN)ff1[i]))
! 615: {
! 616: p1=primedec(nf,(GEN)ff1[i]);
! 617: for (j=1; j<lg(p1); j++)
! 618: {
! 619: p2=(GEN)p1[j]; y1[++k]=(long)p2;
! 620: y2[k] = -itos((GEN)ff2[i])*itos((GEN)p2[3]);
! 621: }
! 622: }
! 623: tetpil=avma; y=cgetg(3,t_MAT);
! 624: p1=cgetg(k+1,t_COL); y[1]=(long)p1;
! 625: p2=cgetg(k+1,t_COL); y[2]=(long)p2;
! 626: for (i=1; i<=k; i++) { p1[i]=lcopy((GEN)y1[i]); p2[i]=lstoi(y2[i]); }
! 627: return gerepile(av,tetpil,y);
! 628: }
! 629:
! 630: /* vp prime ideal in primedec format. Return valuation(ix) at vp */
! 631: long
! 632: idealval(GEN nf, GEN ix, GEN vp)
! 633: {
! 634: long N,v,vd,w,av=avma,av1,lim,i,j,k, tx = typ(ix);
! 635: GEN mul,mat,a,x,y,r,bp,p,denx;
! 636:
! 637: nf=checknf(nf); checkprimeid(vp);
! 638: if (is_extscalar_t(tx) || tx==t_COL) return element_val(nf,ix,vp);
! 639: p=(GEN)vp[1]; N=lgef(nf[1])-3;
! 640: tx = idealtyp(&ix,&a);
! 641: denx=denom(ix); if (!gcmp1(denx)) ix=gmul(denx,ix);
! 642: if (tx != id_MAT)
! 643: ix = idealhermite_aux(nf,ix);
! 644: else
! 645: {
! 646: checkid(ix,N);
! 647: if (lg(ix) != N+1) ix=idealmat_to_hnf(nf,ix);
! 648: }
! 649: v = ggval(dethnf_i(ix), p);
! 650: vd = ggval(denx,p) * itos((GEN)vp[3]); /* v_p * e */
! 651: if (!v) return -vd;
! 652:
! 653: mul = cgetg(N+1,t_MAT); bp=(GEN)vp[5];
! 654: mat = cgetg(N+1,t_MAT);
! 655: for (j=1; j<=N; j++)
! 656: {
! 657: mul[j] = (long)element_mulid(nf,bp,j);
! 658: x = (GEN)ix[j];
! 659: y = cgetg(N+1, t_COL); mat[j] = (long)y;
! 660: for (i=1; i<=N; i++)
! 661: { /* compute (x.b)_i, ix in HNF ==> x[j+1..N] = 0 */
! 662: a = mulii((GEN)x[1], gcoeff(mul,i,1));
! 663: for (k=2; k<=j; k++) a = addii(a, mulii((GEN)x[k], gcoeff(mul,i,k)));
! 664: /* is it divisible by p ? */
! 665: y[i] = ldvmdii(a,p,&r);
! 666: if (signe(r)) { avma=av; return -vd; }
! 667: }
! 668: }
! 669: av1 = avma; lim=stack_lim(av1,3);
! 670: y = cgetg(N+1,t_COL);
! 671: for (w=1; w<v; w++)
! 672: for (j=1; j<=N; j++)
! 673: {
! 674: x = (GEN)mat[j];
! 675: for (i=1; i<=N; i++)
! 676: { /* compute (x.b)_i */
! 677: a = mulii((GEN)x[1], gcoeff(mul,i,1));
! 678: for (k=2; k<=N; k++) a = addii(a, mulii((GEN)x[k], gcoeff(mul,i,k)));
! 679: /* is it divisible by p ? */
! 680: y[i] = ldvmdii(a,p,&r);
! 681: if (signe(r)) { avma=av; return w - vd; }
! 682: }
! 683: r=x; mat[j]=(long)y; y=r;
! 684: if (low_stack(lim,stack_lim(av1,3)))
! 685: {
! 686: GEN *gptr[2]; gptr[0]=&y; gptr[1]=&mat;
! 687: if(DEBUGMEM>1) err(warnmem,"idealval");
! 688: gerepilemany(av1,gptr,2);
! 689: }
! 690: }
! 691: avma=av; return w - vd;
! 692: }
! 693:
! 694: /* gcd and generalized Bezout */
! 695:
! 696: GEN
! 697: idealadd(GEN nf, GEN x, GEN y)
! 698: {
! 699: long av=avma,N,tx,ty;
! 700: GEN z,p1,dx,dy,dz;
! 701:
! 702: tx = idealtyp(&x,&z);
! 703: ty = idealtyp(&y,&z);
! 704: nf=checknf(nf); N=lgef(nf[1])-3;
! 705: z = cgetg(N+1, t_MAT);
! 706: if (tx != id_MAT || lg(x)!=N+1) x = idealhermite_aux(nf,x);
! 707: if (ty != id_MAT || lg(y)!=N+1) y = idealhermite_aux(nf,y);
! 708: if (lg(x) == 1) return gerepileupto(av,y);
! 709: if (lg(y) == 1) return gerepileupto(av,x); /* check for 0 ideal */
! 710: dx=denom(x);
! 711: dy=denom(y); dz=mulii(dx,dy);
! 712: if (gcmp1(dz)) dz = NULL; else { x=gmul(x,dz); y=gmul(y,dz); }
! 713: p1=mppgcd(detint(x),detint(y));
! 714: if (gcmp1(p1))
! 715: {
! 716: long i,j;
! 717: if (!dz) { avma=av; return idmat(N); }
! 718: avma = (long)dz; dz = gerepileupto((long)z, ginv(dz));
! 719: for (i=1; i<=N; i++)
! 720: {
! 721: z[i]=lgetg(N+1,t_COL);
! 722: for (j=1; j<=N; j++)
! 723: coeff(z,j,i) = (i==j)? (long)dz: zero;
! 724: }
! 725: return z;
! 726: }
! 727: z=hnfmod(concatsp(x,y),p1); if (dz) z=gdiv(z,dz);
! 728: return gerepileupto(av,z);
! 729: }
! 730:
! 731: static GEN
! 732: get_p1(GEN nf, GEN x, GEN y,long fl)
! 733: {
! 734: GEN u,v,v1,v2,v3,v4;
! 735: long i,j,N;
! 736:
! 737: switch(fl)
! 738: {
! 739: case 1:
! 740: v1 = gcoeff(x,1,1);
! 741: v2 = gcoeff(y,1,1);
! 742: if (typ(v1)!=t_INT || typ(v2)!=t_INT)
! 743: err(talker,"ideals don't sum to Z_K in idealaddtoone");
! 744: if (gcmp1(bezout(v1,v2,&u,&v)))
! 745: return gmul(u,(GEN)x[1]);
! 746: default:
! 747: v=hnfperm(concatsp(x,y));
! 748: v1=(GEN)v[1]; v2=(GEN)v[2]; v3=(GEN)v[3];
! 749: j=0; N = lgef(nf[1])-3;
! 750: for (i=1; i<=N; i++)
! 751: {
! 752: if (!gcmp1(gcoeff(v1,i,i)))
! 753: err(talker,"ideals don't sum to Z_K in idealaddtoone");
! 754: if (gcmp1((GEN)v3[i])) j=i;
! 755: }
! 756: v4=(GEN)v2[N+j]; setlg(v4,N+1);
! 757: return gmul(x,v4);
! 758: }
! 759: }
! 760:
! 761: GEN
! 762: idealaddtoone_i(GEN nf, GEN x, GEN y)
! 763: {
! 764: long t, fl = 1;
! 765: GEN p1,xh,yh;
! 766:
! 767: if (DEBUGLEVEL>4)
! 768: {
! 769: fprintferr(" entering idealaddtoone:\n");
! 770: fprintferr(" x = %Z\n",x);
! 771: fprintferr(" y = %Z\n",y);
! 772: }
! 773: t = idealtyp(&x,&p1);
! 774: if (t != id_MAT || lg(x) != lg(x[1])) xh = idealhermite_aux(nf,x);
! 775: else
! 776: { xh=x; fl = isnfscalar((GEN)x[1]); }
! 777: t = idealtyp(&y,&p1);
! 778: if (t != id_MAT || lg(y) != lg(y[1])) yh = idealhermite_aux(nf,y);
! 779: else
! 780: { yh=y; if (fl) fl = isnfscalar((GEN)y[1]); }
! 781:
! 782: p1 = get_p1(nf,xh,yh,fl);
! 783: p1 = element_reduce(nf,p1, idealmullll(nf,x,y));
! 784: if (DEBUGLEVEL>4 && !gcmp0(p1))
! 785: fprintferr(" leaving idealaddtoone: %Z\n",p1);
! 786: return p1;
! 787: }
! 788:
! 789: /* ideal should be an idele (not mandatory). For internal use. */
! 790: GEN
! 791: ideleaddone_aux(GEN nf,GEN x,GEN ideal)
! 792: {
! 793: long i,nba,R1;
! 794: GEN p1,p2,p3,arch;
! 795:
! 796: idealtyp(&ideal,&arch);
! 797: if (!arch) return idealaddtoone_i(nf,x,ideal);
! 798:
! 799: R1=itos(gmael(nf,2,1));
! 800: if (typ(arch)!=t_VEC && lg(arch)!=R1+1)
! 801: err(talker,"incorrect idele in idealaddtoone");
! 802: for (nba=0,i=1; i<lg(arch); i++)
! 803: if (signe(arch[i])) nba++;
! 804: if (!nba) return idealaddtoone_i(nf,x,ideal);
! 805:
! 806: p3 = idealaddtoone_i(nf,x,ideal);
! 807: if (gcmp0(p3)) p3=(GEN)idealhermite_aux(nf,x)[1];
! 808: p1=idealmullll(nf,x,ideal);
! 809:
! 810: p2=zarchstar(nf,p1,arch,nba);
! 811: p1=lift_intern(gmul((GEN)p2[3],zsigne(nf,p3,arch)));
! 812: p2=(GEN)p2[2]; nba=0;
! 813: for (i=1; i<lg(p1); i++)
! 814: if (signe(p1[i])) { nba=1; p3=element_mul(nf,p3,(GEN)p2[i]); }
! 815: if (gcmp0(p3)) return gcopy((GEN)x[1]); /* can happen if ideal = Z_K */
! 816: return nba? p3: gcopy(p3);
! 817: }
! 818:
! 819: static GEN
! 820: unnf_minus_x(GEN x)
! 821: {
! 822: long i, N = lg(x);
! 823: GEN y = cgetg(N,t_COL);
! 824:
! 825: y[1] = lsub(gun,(GEN)x[1]);
! 826: for (i=2;i<N; i++) y[i] = lneg((GEN)x[i]);
! 827: return y;
! 828: }
! 829:
! 830: static GEN
! 831: addone(GEN f(GEN,GEN,GEN), GEN nf, GEN x, GEN y)
! 832: {
! 833: GEN z = cgetg(3,t_VEC);
! 834: long av=avma;
! 835:
! 836: nf=checknf(nf); x = gerepileupto(av, f(nf,x,y));
! 837: z[1]=(long)x; z[2]=(long)unnf_minus_x(x); return z;
! 838: }
! 839:
! 840: GEN
! 841: idealaddtoone(GEN nf, GEN x, GEN y)
! 842: {
! 843: return addone(idealaddtoone_i,nf,x,y);
! 844: }
! 845:
! 846: GEN
! 847: ideleaddone(GEN nf,GEN x,GEN idele)
! 848: {
! 849: return addone(ideleaddone_aux,nf,x,idele);
! 850: }
! 851:
! 852: GEN
! 853: nfmodprinit(GEN nf, GEN pr)
! 854: {
! 855: long av;
! 856: GEN p,e,p1,prhall;
! 857:
! 858: nf = checknf(nf); checkprimeid(pr);
! 859: prhall = cgetg(3,t_VEC);
! 860: prhall[1] = (long) prime_to_ideal(nf,pr);
! 861:
! 862: av = avma; p = (GEN)pr[1]; e = (GEN)pr[3];
! 863: p1 = cgetg(2,t_MAT);
! 864: p1[1] = ldiv(element_pow(nf,(GEN)pr[5],e), gpuigs(p,itos(e)-1));
! 865: p1 = hnfmodid(idealhermite_aux(nf,p1), p);
! 866: p1 = idealaddtoone_i(nf,pr,p1);
! 867:
! 868: /* p1 = 1 mod pr, p1 = 0 mod q^{e_q} for all other primes q | p */
! 869: prhall[2] = lpileupto(av, unnf_minus_x(p1)); return prhall;
! 870: }
! 871:
! 872: /* given an element x in Z_K and an integral ideal y with x, y coprime,
! 873: outputs an element inverse of x modulo y */
! 874: GEN
! 875: element_invmodideal(GEN nf, GEN x, GEN y)
! 876: {
! 877: long av=avma,N,i, fl = 1;
! 878: GEN v,p1,xh,yh;
! 879:
! 880: nf=checknf(nf); N=lgef(nf[1])-3;
! 881: if (ideal_is_zk(y,N)) return zerocol(N);
! 882: if (DEBUGLEVEL>4)
! 883: {
! 884: fprintferr(" entree dans element_invmodideal() :\n");
! 885: fprintferr(" x = "); outerr(x);
! 886: fprintferr(" y = "); outerr(y);
! 887: }
! 888: i = lg(y);
! 889: if (typ(y)!=t_MAT || i==1 || i != lg(y[1])) yh=idealhermite_aux(nf,y);
! 890: else
! 891: { yh=y; fl = isnfscalar((GEN)y[1]); }
! 892: switch (typ(x))
! 893: {
! 894: case t_POL: case t_POLMOD: case t_COL:
! 895: xh = idealhermite_aux(nf,x); break;
! 896: default: err(typeer,"element_invmodideal");
! 897: }
! 898: p1 = get_p1(nf,xh,yh,fl);
! 899: p1 = element_div(nf,p1,x);
! 900: v = gerepileupto(av, nfreducemodideal(nf,p1,y));
! 901: if (DEBUGLEVEL>2)
! 902: { fprintferr(" sortie de element_invmodideal : v = "); outerr(v); }
! 903: return v;
! 904: }
! 905:
! 906: GEN
! 907: idealaddmultoone(GEN nf, GEN list)
! 908: {
! 909: long av=avma,tetpil,N,i,i1,j,k;
! 910: GEN z,v,v1,v2,v3,p1;
! 911:
! 912: nf=checknf(nf); N=lgef(nf[1])-3;
! 913: if (DEBUGLEVEL>4)
! 914: {
! 915: fprintferr(" entree dans idealaddmultoone() :\n");
! 916: fprintferr(" list = "); outerr(list);
! 917: }
! 918: if (typ(list)!=t_VEC && typ(list)!=t_COL)
! 919: err(talker,"not a list in idealaddmultoone");
! 920: k=lg(list); z=cgetg(1,t_MAT); list = dummycopy(list);
! 921: if (k==1) err(talker,"ideals don't sum to Z_K in idealaddmultoone");
! 922: for (i=1; i<k; i++)
! 923: {
! 924: p1=(GEN)list[i];
! 925: if (typ(p1)!=t_MAT || lg(p1)!=lg(p1[1]))
! 926: list[i] = (long)idealhermite_aux(nf,p1);
! 927: z = concatsp(z,(GEN)list[i]);
! 928: }
! 929: v=hnfperm(z); v1=(GEN)v[1]; v2=(GEN)v[2]; v3=(GEN)v[3]; j=0;
! 930: for (i=1; i<=N; i++)
! 931: {
! 932: if (!gcmp1(gcoeff(v1,i,i)))
! 933: err(talker,"ideals don't sum to Z_K in idealaddmultoone");
! 934: if (gcmp1((GEN)v3[i])) j=i;
! 935: }
! 936:
! 937: v=(GEN)v2[(k-2)*N+j]; z=cgetg(k,t_VEC);
! 938: for (i=1; i<k; i++)
! 939: {
! 940: p1=cgetg(N+1,t_COL); z[i]=(long)p1;
! 941: for (i1=1; i1<=N; i1++) p1[i1]=v[(i-1)*N+i1];
! 942: }
! 943: tetpil=avma; v=cgetg(k,typ(list));
! 944: for (i=1; i<k; i++) v[i]=lmul((GEN)list[i],(GEN)z[i]);
! 945: if (DEBUGLEVEL>2)
! 946: { fprintferr(" sortie de idealaddmultoone v = "); outerr(v); }
! 947: return gerepile(av,tetpil,v);
! 948: }
! 949:
! 950: /* multiplication */
! 951:
! 952: /* x integral ideal (without archimedean component) in HNF form
! 953: * [a,alpha,n] corresponds to the ideal aZ_K+alpha Z_K of norm n (a is a
! 954: * rational integer). Multiply them
! 955: */
! 956: static GEN
! 957: idealmulspec(GEN nf, GEN x, GEN a, GEN alpha, GEN n)
! 958: {
! 959: long i, N=lg(x)-1;
! 960: GEN m;
! 961:
! 962: if (isnfscalar(alpha))
! 963: return gmul(mppgcd(a,(GEN)alpha[1]),x);
! 964: m = cgetg((N<<1)+1,t_MAT);
! 965: for (i=1; i<=N; i++) n = mulii(n,gcoeff(x,i,i));
! 966: for (i=1; i<=N; i++) m[i]=(long)element_muli(nf,alpha,(GEN)x[i]);
! 967: for (i=1; i<=N; i++) m[i+N]=lmul(a,(GEN)x[i]);
! 968: return hnfmod(m,n);
! 969: }
! 970:
! 971: /* x ideal (matrix form,maximal rank), vp prime ideal (primedec). Output the
! 972: * product. Can be used for arbitrary vp of the form [p,a,e,f,b], IF vp
! 973: * =pZ_K+aZ_K, p is an integer, and norm(vp) = p^f; e and b are not used. For
! 974: * internal use.
! 975: */
! 976: GEN
! 977: idealmulprime(GEN nf, GEN x, GEN vp)
! 978: {
! 979: GEN dx, denx = denom(x);
! 980:
! 981: if (gcmp1(denx)) denx = NULL; else x=gmul(denx,x);
! 982: dx = powgi((GEN)vp[1], (GEN)vp[4]);
! 983: x = idealmulspec(nf,x, (GEN)vp[1], (GEN)vp[2], dx);
! 984: return denx? gdiv(x,denx): x;
! 985: }
! 986:
! 987: /* Assume ix and iy are integral in HNF form (or ideles of the same form).
! 988: * Ideal in iy can be of the form [a,b,N], with iy = (a,b) and N = norm y
! 989: * For internal use. */
! 990: GEN
! 991: idealmulh(GEN nf, GEN ix, GEN iy)
! 992: {
! 993: long N,i, f = 0;
! 994: GEN res,x,y,dy;
! 995:
! 996: if (typ(ix)==t_VEC) {f=1; x=(GEN)ix[1];} else x=ix;
! 997: if (typ(iy)==t_VEC && lg(iy)==3) {f+=2; y=(GEN)iy[1];} else y=iy;
! 998: if (f) res = cgetg(3,t_VEC);
! 999:
! 1000: if (typ(y)==t_VEC)
! 1001: y = idealmulspec(nf,x,(GEN)y[1],(GEN)y[2],(GEN)y[3]);
! 1002: else
! 1003: {
! 1004:
! 1005: N=lg(x)-1; dy=gcoeff(y,1,1);
! 1006: for (i=2; i<=N; i++) dy=mulii(dy,gcoeff(y,i,i));
! 1007: y = ideal_two_elt(nf,y);
! 1008: y = idealmulspec(nf,x,(GEN)y[1],(GEN)y[2],dy);
! 1009: }
! 1010:
! 1011: if (!f) return y;
! 1012: res[1]=(long)y;
! 1013: if (f==3) y = gadd((GEN)ix[2],(GEN)iy[2]);
! 1014: else
! 1015: {
! 1016: y = (f==2)? (GEN)iy[2]: (GEN)ix[2];
! 1017: y = gcopy(y);
! 1018: }
! 1019: res[2]=(long)y; return res;
! 1020: }
! 1021:
! 1022: /* x and y are ideals in matrix form */
! 1023: static GEN
! 1024: idealmat_mul(GEN nf, GEN x, GEN y)
! 1025: {
! 1026: long i,j, rx=lg(x)-1, ry=lg(y)-1;
! 1027: GEN dx,dy,m;
! 1028:
! 1029: dx=denom(x); if (!gcmp1(dx)) x=gmul(dx,x);
! 1030: dy=denom(y); if (!gcmp1(dy)) y=gmul(dy,y);
! 1031: dx = mulii(dx,dy);
! 1032: if (rx<=2 || ry<=2)
! 1033: {
! 1034: m=cgetg(rx*ry+1,t_MAT);
! 1035: for (i=1; i<=rx; i++)
! 1036: for (j=1; j<=ry; j++)
! 1037: m[(i-1)*ry+j]=(long)element_muli(nf,(GEN)x[i],(GEN)y[j]);
! 1038: y=hnfmod(m, detint(m));
! 1039: }
! 1040: else
! 1041: {
! 1042: x=idealmat_to_hnf(nf,x);
! 1043: y=idealmat_to_hnf(nf,y); y=idealmulh(nf,x,y);
! 1044: }
! 1045: return gcmp1(dx)? y: gdiv(y,dx);
! 1046: }
! 1047:
! 1048: /* y is principal */
! 1049: static GEN
! 1050: add_arch(GEN nf, GEN ax, GEN y)
! 1051: {
! 1052: long tetpil, av=avma, prec=precision(ax);
! 1053:
! 1054: y = get_arch(nf,y,prec); tetpil=avma;
! 1055: return gerepile(av,tetpil,gadd(ax,y));
! 1056: }
! 1057:
! 1058: /* output the ideal product ix.iy (don't reduce) */
! 1059: GEN
! 1060: idealmul(GEN nf, GEN x, GEN y)
! 1061: {
! 1062: long tx,ty,av,f;
! 1063: GEN res,ax,ay,p1;
! 1064:
! 1065: tx = idealtyp(&x,&ax);
! 1066: ty = idealtyp(&y,&ay);
! 1067: if (tx>ty) {
! 1068: res=ax; ax=ay; ay=res;
! 1069: res=x; x=y; y=res;
! 1070: f=tx; tx=ty; ty=f;
! 1071: }
! 1072: f = (ax||ay); if (f) res = cgetg(3,t_VEC); /* product is an idele */
! 1073: nf=checknf(nf); av=avma;
! 1074: switch(tx)
! 1075: {
! 1076: case id_PRINCIPAL:
! 1077: switch(ty)
! 1078: {
! 1079: case id_PRINCIPAL:
! 1080: p1 = idealhermite_aux(nf, element_mul(nf,x,y));
! 1081: break;
! 1082: case id_PRIME:
! 1083: p1 = gmul((GEN)y[1],x);
! 1084: p1 = two_to_hnf(nf,p1, element_mul(nf,(GEN)y[2],x));
! 1085: break;
! 1086: default: /* id_MAT */
! 1087: p1 = idealmat_mul(nf,y, principalideal_aux(nf,x));
! 1088: }break;
! 1089:
! 1090: case id_PRIME:
! 1091: p1 = (ty==id_PRIME)? prime_to_ideal_aux(nf,y)
! 1092: : idealmat_to_hnf(nf,y);
! 1093: p1 = idealmulprime(nf,p1,x); break;
! 1094:
! 1095: default: /* id_MAT */
! 1096: p1 = idealmat_mul(nf,x,y);
! 1097: }
! 1098: p1 = gerepileupto(av,p1);
! 1099: if (!f) return p1;
! 1100:
! 1101: if (ax && ay) ax = gadd(ax,ay);
! 1102: else
! 1103: {
! 1104: if (ax)
! 1105: ax = (ty==id_PRINCIPAL)? add_arch(nf,ax,y): gcopy(ax);
! 1106: else
! 1107: ax = (tx==id_PRINCIPAL)? add_arch(nf,ay,x): gcopy(ay);
! 1108: }
! 1109: res[1]=(long)p1; res[2]=(long)ax; return res;
! 1110: }
! 1111:
! 1112: /* different of nf */
! 1113: GEN
! 1114: differente(GEN nf, GEN premiers)
! 1115: {
! 1116: long av=avma,i,j,vi,ei,v,nb_p,vpc;
! 1117: GEN ideal,diff,liste_id,p1,pcon,pr,pol,a,alpha;
! 1118:
! 1119: pol=(GEN)nf[1];
! 1120: if (DEBUGLEVEL>1) fprintferr("Computing different\n");
! 1121: if (gcmp1((GEN)nf[4]))
! 1122: {
! 1123: p1 = derivpol(pol);
! 1124: return gerepileupto(av,idealhermite_aux(nf,p1));
! 1125: }
! 1126:
! 1127: ideal = gmul((GEN)nf[3],ginv(gmael(nf,5,4)));
! 1128: pcon = content(ideal);
! 1129: if (!gcmp1(pcon)) ideal=gdiv(ideal,pcon);
! 1130:
! 1131: ideal=hnfmodid(ideal,divii((GEN)nf[3],pcon));
! 1132: if (DEBUGLEVEL>1) msgtimer("hnf(D*delta^-1)");
! 1133:
! 1134: if (!premiers)
! 1135: {
! 1136: premiers=factor(absi((GEN)nf[3]));
! 1137: if (DEBUGLEVEL>1) msgtimer("factor(D)");
! 1138: }
! 1139: diff=idmat(lgef(nf[1])-3); nb_p=lg(premiers[1]);
! 1140:
! 1141: for (i=1; i<nb_p; i++)
! 1142: {
! 1143: pr=gcoeff(premiers,i,1); liste_id = primedec(nf,pr);
! 1144: vi=itos(gcoeff(premiers,i,2)); vpc=ggval(pcon,pr);
! 1145: for (j=1; j<lg(liste_id); j++)
! 1146: {
! 1147: p1=(GEN)liste_id[j]; ei=itos((GEN)p1[3]);
! 1148: if (ei>1)
! 1149: {
! 1150: if (DEBUGLEVEL>1) fprintferr("treating %Z\n",p1);
! 1151: if (signe(ressi(ei,pr)))
! 1152: v = ei-1;
! 1153: else
! 1154: v = ei*(vi-vpc)-idealval(nf,ideal,p1);
! 1155: a = gpuigs(pr, 1+(v-1)/ei);
! 1156: alpha = element_pow(nf,(GEN)p1[2],stoi(v));
! 1157: v *= itos((GEN)p1[4]);
! 1158: diff = idealmulspec(nf,diff,a,alpha,gpuigs(pr,v));
! 1159: }
! 1160: }
! 1161: }
! 1162: return gerepileupto(av,diff);
! 1163: }
! 1164:
! 1165: /* norm of an ideal */
! 1166: GEN
! 1167: idealnorm(GEN nf, GEN x)
! 1168: {
! 1169: long av = avma,tetpil;
! 1170: GEN y;
! 1171:
! 1172: nf = checknf(nf);
! 1173: switch(idealtyp(&x,&y))
! 1174: {
! 1175: case id_PRIME:
! 1176: return powgi((GEN)x[1],(GEN)x[4]);
! 1177: case id_PRINCIPAL:
! 1178: x = gnorm(basistoalg(nf,x)); break;
! 1179: default:
! 1180: if (lg(x) != lgef(nf[1])-2) x = idealhermite_aux(nf,x);
! 1181: x = det(x);
! 1182: }
! 1183: tetpil=avma; return gerepile(av,tetpil,gabs(x,0));
! 1184: }
! 1185:
! 1186: /* inverse */
! 1187:
! 1188: /* P.M & M.H. */
! 1189: static GEN
! 1190: hnfideal_inv(GEN nf, GEN x)
! 1191: {
! 1192: long N = lgef(nf[1])-3;
! 1193: GEN denx = denom(x), detx,dual,p1;
! 1194:
! 1195: if (gcmp1(denx)) denx = NULL; else x = gmul(x,denx);
! 1196: detx = dethnf(x);
! 1197: if (gcmp0(detx)) err(talker, "cannot invert zero ideal");
! 1198: x = idealmulh(nf,x, gmael(nf,5,7));
! 1199: dual = gauss(x, gmul(detx, gmael(nf,5,6)));
! 1200: dual = gdiv(gtrans(dual), detx);
! 1201:
! 1202: /* nf[5][4] is a dense symmetric matrix. We computed
! 1203: * nf[5][6] = fieldd * ginv(nf[5][4]) in initalg.
! 1204: * x is upper triangular (HNF), and easily inverted.
! 1205: * The factor fieldd cancels while solving the linear equations.
! 1206: */
! 1207: p1 = denom(dual); dual = gmul(dual, p1);
! 1208: dual = hnfmod(dual, gdiv(gpowgs(p1,N),detx));
! 1209: if (denx) p1 = gdiv(p1,denx);
! 1210: return gdiv(dual,p1);
! 1211: }
! 1212:
! 1213: /* Calcule le dual de mat_id pour la forme trace */
! 1214: GEN
! 1215: oldidealinv(GEN nf, GEN x)
! 1216: {
! 1217: GEN res,dual,di,ax;
! 1218: long av,tetpil, tx = idealtyp(&x,&ax);
! 1219:
! 1220: if (tx!=id_MAT) return idealinv(nf,x);
! 1221: if (ax) res = cgetg(3,t_VEC);
! 1222: nf=checknf(nf); av=avma;
! 1223: if (lg(x)!=lgef(nf[1])) x = idealmat_to_hnf(nf,x);
! 1224:
! 1225: dual = ginv(gmul(gtrans(x), gmael(nf,5,4)));
! 1226: di=denom(dual); dual=gmul(di,dual);
! 1227: dual = idealmat_mul(nf,gmael(nf,5,5), dual);
! 1228: tetpil=avma; dual = gerepile(av,tetpil,gdiv(dual,di));
! 1229: if (!ax) return dual;
! 1230: res[1]=(long)dual; res[2]=lneg(ax); return res;
! 1231: }
! 1232:
! 1233: /* Calcule le dual de mat_id pour la forme trace */
! 1234: GEN
! 1235: idealinv(GEN nf, GEN x)
! 1236: {
! 1237: GEN res,ax,p1;
! 1238: long av=avma, tx = idealtyp(&x,&ax);
! 1239:
! 1240: if (ax) res = cgetg(3,t_VEC);
! 1241: nf=checknf(nf); av=avma;
! 1242: switch (tx)
! 1243: {
! 1244: case id_MAT:
! 1245: if (lg(x) != lg(x[1])) x = idealmat_to_hnf(nf,x);
! 1246: x = hnfideal_inv(nf,x); break;
! 1247: case id_PRINCIPAL: tx = typ(x);
! 1248: if (is_const_t(tx)) x = ginv(x);
! 1249: else
! 1250: {
! 1251: switch(tx)
! 1252: {
! 1253: case t_COL: x = gmul((GEN)nf[7],x); break;
! 1254: case t_POLMOD: x = (GEN)x[2]; break;
! 1255: }
! 1256: x = ginvmod(x,(GEN)nf[1]);
! 1257: }
! 1258: x = idealhermite_aux(nf,x); break;
! 1259: case id_PRIME:
! 1260: p1=cgetg(6,t_VEC); p1[1]=x[1]; p1[2]=x[5];
! 1261: p1[3]=p1[5]=zero; p1[4]=lsubsi(lgef(nf[1])-3, (GEN)x[4]);
! 1262: x = gdiv(prime_to_ideal_aux(nf,p1), (GEN)x[1]);
! 1263: }
! 1264: x = gerepileupto(av,x); if (!ax) return x;
! 1265: res[1]=(long)x; res[2]=lneg(ax); return res;
! 1266: }
! 1267:
! 1268: static GEN
! 1269: idealpowprime(GEN nf, GEN vp, GEN n)
! 1270: {
! 1271: GEN n1, x = dummycopy(vp);
! 1272: long s = signe(n);
! 1273:
! 1274: if (s < 0) n=negi(n);
! 1275: n1 = gceil(gdiv(n,(GEN)x[3]));
! 1276: x[1]=(long)powgi((GEN)x[1],n1);
! 1277: if (s < 0)
! 1278: x[2]=ldiv(element_pow(nf,(GEN)x[5],n), powgi((GEN)vp[1],subii(n,n1)));
! 1279: else
! 1280: x[2]=(long)element_pow(nf,(GEN)x[2],n);
! 1281: x = prime_to_ideal_aux(nf,x);
! 1282: if (s<0) x = gdiv(x, powgi((GEN)vp[1],n1));
! 1283: return x;
! 1284: }
! 1285:
! 1286: /* raise the ideal x to the power n (in Z) */
! 1287: GEN
! 1288: idealpow(GEN nf, GEN x, GEN n)
! 1289: {
! 1290: long tx,N,av,s,i;
! 1291: GEN res,ax,m,denx,denz,dx,n1,a,alpha;
! 1292:
! 1293: if (typ(n) != t_INT) err(talker,"non-integral exponent in idealpow");
! 1294: tx = idealtyp(&x,&ax);
! 1295: if (ax) res = cgetg(3,t_VEC);
! 1296: nf = checknf(nf);
! 1297: av=avma; N=lgef(nf[1])-3; s=signe(n);
! 1298: if (!s) x = idmat(N);
! 1299: else
! 1300: switch(tx)
! 1301: {
! 1302: case id_PRINCIPAL: tx = typ(x);
! 1303: if (!is_const_t(tx))
! 1304: switch(tx)
! 1305: {
! 1306: case t_COL: x = gmul((GEN)nf[7],x);
! 1307: case t_POL: x = gmodulcp(x,(GEN)nf[1]);
! 1308: }
! 1309: x = gpui(x,n,0);
! 1310: x = idealhermite_aux(nf,x); break;
! 1311: case id_PRIME:
! 1312: x = idealpowprime(nf,x,n); break;
! 1313: default:
! 1314: n1 = (s<0)? negi(n): n;
! 1315:
! 1316: denx=denom(x); if (gcmp1(denx)) denx=NULL; else x = gmul(x,denx);
! 1317: a=ideal_two_elt(nf,x); alpha=(GEN)a[2]; a=(GEN)a[1];
! 1318: dx=gcoeff(x,1,1); for (i=2; i<=N; i++) dx=mulii(dx,gcoeff(x,i,i));
! 1319:
! 1320: m = cgetg(N+1,t_MAT); a = gpui(a,n1,0);
! 1321: alpha = element_pow(nf,alpha,n1);
! 1322: for (i=1; i<=N; i++) m[i]=(long)element_mulid(nf,alpha,i);
! 1323: m = concatsp(m, gscalmat(a,N));
! 1324: x = hnfmod(m, gpui(dx,n1,0));
! 1325: if (s<0) x = hnfideal_inv(nf,x);
! 1326: if (denx) { denz=gpui(denx,negi(n),0); x=gmul(denz,x); }
! 1327: }
! 1328: x = gerepileupto(av, x);
! 1329: if (!ax) return x;
! 1330: res[1]=(long)x; res[2]=lmul(n,ax); return res;
! 1331: }
! 1332:
! 1333: /* Return ideal^e in number field nf. e is a C integer. */
! 1334: GEN
! 1335: idealpows(GEN nf, GEN ideal, long e)
! 1336: {
! 1337: long court[] = {evaltyp(t_INT) | m_evallg(3),0,0};
! 1338: affsi(e,court); return idealpow(nf,ideal,court);
! 1339: }
! 1340:
! 1341: /* compute vp^n (vp prime, n integer), reducing along the way if n is big */
! 1342: GEN
! 1343: idealpowred_prime(GEN nf, GEN vp, GEN n, long prec)
! 1344: {
! 1345: long av=avma,tetpil,i,m,RU, s = signe(n);
! 1346: GEN x = cgetg(3,t_VEC);
! 1347: ulong j;
! 1348:
! 1349: RU = itos(gmael(nf,2,1)) + itos(gmael(nf,2,2));
! 1350: x[2] =(long)zerocol(RU); settyp(x[2],t_VEC);
! 1351: if (absi_cmp(n,stoi(16)) < 0)
! 1352: {
! 1353: x[1] = s? (long)idealpowprime(nf,vp,n):
! 1354: (long)idmat(lgef(nf[1])-3);
! 1355: tetpil=avma;
! 1356: return gerepile(av,tetpil,ideallllred(nf,x,NULL,prec));
! 1357: }
! 1358:
! 1359: i = lgefint(n)-1; m=n[i]; j=HIGHBIT;
! 1360: while ((m&j)==0) j>>=1;
! 1361: x[1] = (long)prime_to_ideal_aux(nf,vp);
! 1362: for (j>>=1; j; j>>=1)
! 1363: {
! 1364: x = idealmul(nf,x,x);
! 1365: if (m&j) x[1] = (long)idealmulprime(nf,(GEN)x[1],vp);
! 1366: x = ideallllred(nf,x,NULL,prec);
! 1367: }
! 1368: for (i--; i>=2; i--)
! 1369: for (m=n[i],j=HIGHBIT; j; j>>=1)
! 1370: {
! 1371: x = idealmul(nf,x,x);
! 1372: if (m&j) x[1] = (long)idealmulprime(nf,(GEN)x[1],vp);
! 1373: x = ideallllred(nf,x,NULL,prec);
! 1374: }
! 1375: if (s < 0) x = idealinv(nf,x);
! 1376: return gerepileupto(av,x);
! 1377: }
! 1378:
! 1379: long
! 1380: isideal(GEN nf,GEN x)
! 1381: {
! 1382: long N,av,i,j,k,tx=typ(x),lx;
! 1383: GEN p1,minv;
! 1384:
! 1385: nf=checknf(nf); lx=lg(x);
! 1386: if (tx==t_VEC && lx==3) { x=(GEN)x[1]; tx=typ(x); lx=lg(x); }
! 1387: if (is_scalar_t(tx))
! 1388: return (tx==t_INT || tx==t_FRAC || tx==t_FRACN || tx==t_POL ||
! 1389: (tx==t_POLMOD && gegal((GEN)nf[1],(GEN)x[1])));
! 1390: if (typ(x)==t_VEC) return (lx==6);
! 1391: if (typ(x)!=t_MAT) return 0;
! 1392: if (lx == 1) return 1;
! 1393: N=lgef(nf[1])-2; if (lg(x[1]) != N) return 0;
! 1394:
! 1395: av=avma;
! 1396: if (lx != N) x = idealmat_to_hnf(nf,x);
! 1397: x = gdiv(x,content(x)); minv=ginv(x);
! 1398:
! 1399: for (i=1; i<N; i++)
! 1400: for (j=1; j<N; j++)
! 1401: {
! 1402: p1=gmul(minv, element_mulid(nf,(GEN)x[i],j));
! 1403: for (k=1; k<N; k++)
! 1404: if (typ(p1[k])!=t_INT) { avma=av; return 0; }
! 1405: }
! 1406: avma=av; return 1;
! 1407: }
! 1408:
! 1409: GEN
! 1410: idealdiv(GEN nf, GEN x, GEN y)
! 1411: {
! 1412: long av=avma,tetpil;
! 1413: GEN z=idealinv(nf,y);
! 1414:
! 1415: tetpil=avma; return gerepile(av,tetpil,idealmul(nf,x,z));
! 1416: }
! 1417:
! 1418: GEN
! 1419: idealdivexact(GEN nf, GEN x, GEN y)
! 1420: /* This routine computes the quotient x/y of two ideals in the number field
! 1421: * nf. It assumes that the quotient is an integral ideal.
! 1422: *
! 1423: * The idea is to find an ideal z dividing y
! 1424: * such that gcd(N(x)/N(z), N(z)) = 1. Then
! 1425: *
! 1426: * x + (N(x)/N(z)) x
! 1427: * --------------- = -----
! 1428: * y + (N(y)/N(z)) y
! 1429: *
! 1430: * When x and y are integral ideals, this identity can be checked by looking
! 1431: * at the exponent of a prime ideal p on both sides of the equation.
! 1432: *
! 1433: * Specifically, if a prime ideal p divides N(z), then it divides neither
! 1434: * N(x)/N(z) nor N(y)/N(z) (since N(x)/N(z) is the product of the integers
! 1435: * N(x/y) and N(y/z)). Both the numerator and the denominator on the left
! 1436: * will be coprime to p. So will x/y, since x/y is assumed integral and its
! 1437: * norm N(x/y) is coprime to p
! 1438: *
! 1439: * If instead p does not divide N(z), then the power of p dividing N(x)/N(z)
! 1440: * is the same as the power of p dividing N(x), which is at least as large
! 1441: * as the power of p dividing x. Likewise for N(y)/N(z). So the power of p
! 1442: * dividing the left side equals the power of dividing the right side.
! 1443: *
! 1444: * Peter Montgomery
! 1445: * July, 1994.
! 1446: */
! 1447: {
! 1448: long av = avma, tetpil,N;
! 1449: GEN x1,y1,detx1,dety1,detq,gcancel,gtemp, cy = content(y);
! 1450:
! 1451: nf=checknf(nf); N=lgef(nf[1])-3;
! 1452: if (gcmp0(cy)) err(talker, "cannot invert zero ideal");
! 1453:
! 1454: x1 = gdiv(x,cy); detx1 = idealnorm(nf,x1);
! 1455: if (gcmp0(detx1)) { avma = av; return gcopy(x); } /* numerator is zero */
! 1456:
! 1457: y1 = gdiv(y,cy); dety1 = idealnorm(nf,y1);
! 1458: detq = gdiv(detx1,dety1);
! 1459: if (!gcmp1(denom(x1)) || typ(detq) != t_INT)
! 1460: err(talker, "quotient not integral in idealdivexact");
! 1461: gcancel = dety1;
! 1462: /* Find a norm gcancel such that
! 1463: * (1) gcancel divides dety1;
! 1464: * (2) gcd(detx1/gcancel, gcancel) = 1.
! 1465: */
! 1466: do
! 1467: {
! 1468: gtemp = ggcd(gcancel, gdiv(detx1,gcancel));
! 1469: gcancel = gdiv(gcancel,gtemp);
! 1470: }
! 1471: while (!gcmp1(gtemp));
! 1472: /* x1 + (detx1/gcancel)
! 1473: * Replace x1/y1 by: --------------------
! 1474: * y1 + (dety1/gcancel)
! 1475: */
! 1476:
! 1477: x1 = idealadd(nf, x1, gscalmat(gdiv(detx1, gcancel), N));
! 1478: /* y1 reduced to unit ideal ? */
! 1479: if (gegal(gcancel,dety1)) return gerepileupto(av, x1);
! 1480:
! 1481: y1 = idealadd(nf,y1, gscalmat(gdiv(dety1,gcancel), N));
! 1482: y1 = hnfideal_inv(nf,y1); tetpil = avma;
! 1483: return gerepile(av, tetpil, idealmat_mul(nf,x1,y1));
! 1484: }
! 1485:
! 1486: GEN
! 1487: idealintersect(GEN nf, GEN x, GEN y)
! 1488: {
! 1489: long av=avma,lz,i,N;
! 1490: GEN z,dx,dy;
! 1491:
! 1492: nf=checknf(nf); N=lgef(nf[1])-3;
! 1493: if (idealtyp(&x,&z)!=t_MAT || lg(x)!=N+1) x=idealhermite_aux(nf,x);
! 1494: if (idealtyp(&y,&z)!=t_MAT || lg(y)!=N+1) y=idealhermite_aux(nf,y);
! 1495: dx=denom(x); if (!gcmp1(dx)) y=gmul(y,dx);
! 1496: dy=denom(y); if (!gcmp1(dy)) x=gmul(x,dy);
! 1497: dx = mulii(dx,dy);
! 1498: z=kerint(concatsp(x,y)); lz=lg(z);
! 1499: for (i=1; i<lz; i++) setlg(z[i], N+1);
! 1500: z=gmul(x,z); z = hnfmod(z,detint(z));
! 1501: if (!gcmp1(dx)) z = gdiv(z,dx);
! 1502: return gerepileupto(av,z);
! 1503: }
! 1504:
! 1505: static GEN
! 1506: computet2twist(GEN nf, GEN vdir)
! 1507: {
! 1508: long j, ru = lg(nf[6]);
! 1509: GEN p1,MC, mat = (GEN)nf[5];
! 1510:
! 1511: if (!vdir) return (GEN)mat[3];
! 1512: MC=(GEN)mat[2]; p1=cgetg(ru,t_MAT);
! 1513: for (j=1; j<ru; j++)
! 1514: {
! 1515: GEN v = (GEN)vdir[j];
! 1516: if (gcmp0(v))
! 1517: p1[j]=MC[j];
! 1518: else if (typ(v) == t_INT)
! 1519: p1[j]=lmul2n((GEN)MC[j],itos(v)<<1);
! 1520: else
! 1521: p1[j]=lmul((GEN)MC[j],gpui(stoi(4),v,0));
! 1522: }
! 1523: return mulmat_real(p1,(GEN)mat[1]);
! 1524: }
! 1525:
! 1526: GEN
! 1527: ideallllredall(GEN nf, GEN x, GEN vdir, long prec, long precint)
! 1528: {
! 1529: long tx,N,av,tetpil,i,j;
! 1530: GEN iax,ix,res,ax,p1,p2,y,alpha,beta,pol;
! 1531:
! 1532: nf=checknf(nf);
! 1533: if (vdir)
! 1534: {
! 1535: if (gcmp0(vdir)) vdir = NULL;
! 1536: else if (typ(vdir)!=t_VEC || lg(vdir) != lg(nf[6])) err(idealer5);
! 1537: }
! 1538: pol = (GEN)nf[1]; N=lgef(pol)-3;
! 1539: tx = idealtyp(&x,&ax); ix=x; iax=ax;
! 1540: if (ax) res = cgetg(3,t_VEC);
! 1541: av = avma;
! 1542: if (tx == id_PRINCIPAL)
! 1543: {
! 1544: if (ax)
! 1545: {
! 1546: res = cgetg(3,t_VEC);
! 1547: ax = get_arch(nf,x,prec); av=avma;
! 1548: }
! 1549: x = idealhermite_aux(nf,x);
! 1550: }
! 1551: else if (tx == id_PRIME)
! 1552: x = prime_to_ideal_aux(nf,x);
! 1553: else if (lg(x) != N+1) /* id_MAT */
! 1554: x = idealhermite_aux(nf,x);
! 1555:
! 1556: if (DEBUGLEVEL>=6) msgtimer("entering idealllred");
! 1557: p1=content(x); if (!gcmp1(p1)) x=gdiv(x,p1);
! 1558:
! 1559: for (i=1; ; i++)
! 1560: {
! 1561: p1=computet2twist(nf,vdir);
! 1562: if (DEBUGLEVEL>=6) msgtimer("twisted T2");
! 1563: y = qf_base_change(p1,x,1);
! 1564: j = 1 + (gexpo(y)>>TWOPOTBITS_IN_LONG);
! 1565: if (j<0) j=0;
! 1566: p1 = lllgramintern(y,100,1,j+precint);
! 1567: if (p1) break;
! 1568:
! 1569: if (i == MAXITERPOL) err(accurer,"ideallllredall");
! 1570: precint=(precint<<1)-2; prec=max(prec,precint);
! 1571: if (DEBUGLEVEL) err(warnprec,"ideallllredall",precint);
! 1572: nf=nfnewprec(nf,(j>>1)+precint);
! 1573: }
! 1574: y = gmul(x,(GEN)p1[1]);
! 1575: if (DEBUGLEVEL>=6) msgtimer("lllgram");
! 1576:
! 1577: i=2; while (i<=N && gcmp0((GEN)y[i])) i++;
! 1578: if (i>N)
! 1579: {
! 1580: if (x!=ix) x = gerepileupto(av,x); else { avma=av; x = gcopy(x); }
! 1581: if (!ax) return x;
! 1582: if (ax==iax) ax = gcopy(ax);
! 1583: res[1]=(long)x; res[2]=(long)ax; return res;
! 1584: }
! 1585: alpha = gmul((GEN)nf[7], y);
! 1586: /* beta = norm(alpha) / alpha */
! 1587: beta = gmul(subres(pol,alpha), ginvmod(alpha,pol));
! 1588: beta = algtobasis_intern(nf,beta);
! 1589: if (DEBUGLEVEL>=6) msgtimer("alpha/beta");
! 1590:
! 1591: p2 = cgetg(N+1,t_MAT);
! 1592: for (i=1; i<=N; i++)
! 1593: p2[i] = (long)element_muli(nf,beta,(GEN)x[i]);
! 1594: p1=content(p2); if (!gcmp1(p1)) p2=gdiv(p2,p1);
! 1595: if (DEBUGLEVEL>=6) msgtimer("new ideal");
! 1596: if (ax) y = gclone(gneg_i(get_arch(nf,y,prec)));
! 1597:
! 1598: p1 = detint(p2); tetpil = avma;
! 1599: p2 = gerepile(av,tetpil,hnfmod(p2,p1));
! 1600: if (DEBUGLEVEL>=6) msgtimer("final hnf");
! 1601: if (!ax) return p2;
! 1602: res[1]=(long)p2; res[2]=ladd(ax,y);
! 1603: gunclone(y); return res;
! 1604: }
! 1605:
! 1606: GEN
! 1607: ideallllred(GEN nf, GEN ix, GEN vdir, long prec)
! 1608: {
! 1609: return ideallllredall(nf,ix,vdir,prec,prec);
! 1610: }
! 1611:
! 1612: GEN
! 1613: minideal(GEN nf, GEN x, GEN vdir, long prec)
! 1614: {
! 1615: long N,av=avma,tetpil,j,RU,tx;
! 1616: GEN p1,p2,p3,y;
! 1617:
! 1618: if (!gcmp0(vdir) && typ(vdir)!=t_VEC) err(idealer5);
! 1619: nf=checknf(nf); N=lgef(nf[1])-3;
! 1620: tx = idealtyp(&x,&y); if (tx!=id_MAT) x = idealhermite_aux(nf,x);
! 1621: RU = N - itos(gmael(nf,2,2)); p1=(GEN)nf[5];
! 1622: if (gcmp0(vdir)) p1=(GEN)p1[3];
! 1623: else
! 1624: {
! 1625: p3=(GEN)p1[2]; p2=cgetg(RU+1,t_MAT);
! 1626: for (j=1; j<=RU; j++)
! 1627: p2[j] = lmul2n((GEN)p3[j], itos((GEN)vdir[j])<<1);
! 1628: p1=greal(gmul(p2,(GEN)p1[1]));
! 1629: }
! 1630: y = gmul(x,(GEN)lllgram(qf_base_change(p1,x,0),prec)[1]);
! 1631: tetpil = avma; return gerepile(av,tetpil,principalidele(nf,y,prec));
! 1632: }
! 1633: static GEN
! 1634: appr_reduce(GEN s, GEN y, long N)
! 1635: {
! 1636: GEN p1,u,z = cgetg(N+2,t_MAT);
! 1637: long i;
! 1638:
! 1639: s=gmod(s,gcoeff(y,1,1)); y=gmul(y,lllint(y));
! 1640: for (i=1; i<=N; i++) z[i]=y[i]; z[N+1]=(long)s;
! 1641: u=(GEN)ker(z)[1]; p1 = denom(u);
! 1642: if (!gcmp1(p1)) u=gmul(u,p1);
! 1643: p1=(GEN)u[N+1]; setlg(u,N+1);
! 1644: for (i=1; i<=N; i++) u[i]=lround(gdiv((GEN)u[i],p1));
! 1645: return gadd(s, gmul(y,u));
! 1646: }
! 1647:
! 1648: /* Given a fractional ideal x (if fl=0) or a prime ideal factorization
! 1649: * with possibly zero or negative exponents (if fl=1), gives a b such that
! 1650: * v_p(b)=v_p(x) for all prime ideals p dividing x (or in the factorization)
! 1651: * and v_p(b)>=0 for all other p, using the (standard) proof given in GTM 138.
! 1652: * Certainly not the most efficient, but sure.
! 1653: */
! 1654: GEN
! 1655: idealappr0(GEN nf, GEN x, long fl)
! 1656: {
! 1657: long av=avma,tetpil,i,j,k,l,N,r,r2;
! 1658: GEN fact,fact2,list,ep,ep1,ep2,y,z,v,p1,p2,p3,p4,s,pr,alpha,beta,den;
! 1659:
! 1660: if (DEBUGLEVEL>4)
! 1661: {
! 1662: fprintferr(" entree dans idealappr0() :\n");
! 1663: fprintferr(" x = "); outerr(x);
! 1664: }
! 1665: if (fl)
! 1666: {
! 1667: nf=checknf(nf); N=lgef(nf[1])-3;
! 1668: if (typ(x)!=t_MAT || lg(x)!=3)
! 1669: err(talker,"not a prime ideal factorization in idealappr0");
! 1670: fact=x; list=(GEN)fact[1]; ep=(GEN)fact[2]; r=lg(list);
! 1671: if (r==1) return gscalcol_i(gun,N);
! 1672: for (i=1; i<r; i++)
! 1673: if (signe(ep[i])<0)
! 1674: {
! 1675: ep1=cgetg(r,t_COL);
! 1676: for (i=1; i<r; i++)
! 1677: ep1[i] = (signe(ep[i])>=0)? zero: lnegi((GEN)ep[i]);
! 1678: fact[2]=(long)ep1; beta=idealappr0(nf,fact,1);
! 1679: fact2=idealfactor(nf,beta);
! 1680: p1=(GEN)fact2[1]; r2=lg(p1);
! 1681: ep2=(GEN)fact2[2]; l=r+r2-1;
! 1682: z=cgetg(l,t_VEC); for (i=1; i<r; i++) z[i]=list[i];
! 1683: ep1=cgetg(l,t_VEC);
! 1684: for (i=1; i<r; i++)
! 1685: ep1[i] = (signe(ep[i])<=0)? zero: licopy((GEN)ep[i]);
! 1686: j=r-1;
! 1687: for (i=1; i<r2; i++)
! 1688: {
! 1689: p3=(GEN)p1[i]; k=1;
! 1690: while (k<r &&
! 1691: ( !gegal((GEN)p3[1],gmael(list,k,1))
! 1692: || !element_val(nf,(GEN)p3[2],(GEN)list[k]) )) k++;
! 1693: if (k==r) { j++; z[j]=(long)p3; ep1[j]=ep2[i]; }
! 1694: }
! 1695: fact=cgetg(3,t_MAT);
! 1696: fact[1]=(long)z; setlg(z,j+1);
! 1697: fact[2]=(long)ep1; setlg(ep1,j+1);
! 1698: alpha=idealappr0(nf,fact,1); tetpil=avma;
! 1699: if (DEBUGLEVEL>2)
! 1700: {
! 1701: fprintferr(" alpha = "); outerr(alpha);
! 1702: fprintferr(" beta = "); outerr(beta);
! 1703: }
! 1704: return gerepile(av,tetpil,element_div(nf,alpha,beta));
! 1705: }
! 1706: y=idmat(N);
! 1707: for (i=1; i<r; i++)
! 1708: {
! 1709: pr=(GEN)list[i];
! 1710: if (signe(ep[i]))
! 1711: {
! 1712: p4=addsi(1,(GEN)ep[i]); p1=powgi((GEN)pr[1],p4);
! 1713: if (cmpis((GEN)pr[4],N))
! 1714: {
! 1715: p2=cgetg(3,t_MAT);
! 1716: p2[1]=(long)gscalcol_i(p1, N);
! 1717: p2[2]=(long)element_pow(nf,(GEN)pr[2],p4);
! 1718: y=idealmat_mul(nf,y,p2);
! 1719: }
! 1720: else y=gmul(p1,y);
! 1721: }
! 1722: else y=idealmulprime(nf,y,pr);
! 1723: }
! 1724: }
! 1725: else
! 1726: {
! 1727: den=denom(x); if (gcmp1(den)) den=NULL; else x=gmul(den,x);
! 1728: x=idealhermite_aux(nf,x); N=lgef(nf[1])-3;
! 1729: fact=idealfactor(nf,x);
! 1730: list=(GEN)fact[1]; ep=(GEN)fact[2]; r=lg(list);
! 1731: if (r==1) { avma=av; return gscalcol_i(gun,N); }
! 1732: if (den)
! 1733: {
! 1734: fact2=idealfactor(nf,den);
! 1735: p1=(GEN)fact2[1]; r2=lg(p1);
! 1736: l=r+r2-1;
! 1737: z=cgetg(l,t_COL); for (i=1; i<r; i++) z[i]=list[i];
! 1738: ep1=cgetg(l,t_COL); for (i=1; i<r; i++) ep1[i]=ep[i];
! 1739: j=r-1;
! 1740: for (i=1; i<r2; i++)
! 1741: {
! 1742: p3=(GEN)p1[i]; k=1;
! 1743: while (k<r && !gegal((GEN)list[k],p3)) k++;
! 1744: if (k==r){ j++; z[j]=(long)p3; ep1[j]=zero; }
! 1745: }
! 1746: fact=cgetg(3,t_MAT);
! 1747: fact[1]=(long)z; setlg(z,j+1);
! 1748: fact[2]=(long)ep1; setlg(ep1,j+1);
! 1749: alpha=idealappr0(nf,fact,1);
! 1750: if (DEBUGLEVEL>2) { fprintferr(" alpha = "); outerr(alpha); }
! 1751: tetpil=avma; return gerepile(av,tetpil,gdiv(alpha,den));
! 1752: }
! 1753: y=x; for (i=1; i<r; i++) y=idealmulprime(nf,y,(GEN)list[i]);
! 1754: }
! 1755:
! 1756: z=cgetg(r,t_VEC);
! 1757: for (i=1; i<r; i++)
! 1758: {
! 1759: pr=(GEN)list[i]; p4=addsi(1, (GEN)ep[i]); p1=powgi((GEN)pr[1],p4);
! 1760: if (cmpis((GEN)pr[4],N))
! 1761: {
! 1762: p2=cgetg(3,t_MAT);
! 1763: p2[1]=(long)gscalcol_i(p1,N);
! 1764: p2[2]=(long)element_pow(nf,(GEN)pr[5],p4);
! 1765: z[i]=ldiv(idealmat_mul(nf,y,p2),p1);
! 1766: }
! 1767: else z[i]=ldiv(y,p1);
! 1768: }
! 1769: v=idealaddmultoone(nf,z);
! 1770: s=cgetg(N+1,t_COL); for (i=1; i<=N; i++) s[i]=zero;
! 1771: for (i=1; i<r; i++)
! 1772: {
! 1773: pr=(GEN)list[i];
! 1774: if (signe(ep[i]))
! 1775: s=gadd(s,element_mul(nf,(GEN)v[i],element_pow(nf,(GEN)pr[2],(GEN)ep[i])));
! 1776: else s=gadd(s,(GEN)v[i]);
! 1777: }
! 1778: p3 = appr_reduce(s,y,N);
! 1779: if (DEBUGLEVEL>2)
! 1780: { fprintferr(" sortie de idealappr0 p3 = "); outerr(p3); }
! 1781: return gerepileupto(av,p3);
! 1782: }
! 1783:
! 1784: /* Given a prime ideal factorization x with possibly zero or negative exponents,
! 1785: * and a vector y of elements of nf, gives a b such that
! 1786: * v_p(b-y_p)>=v_p(x) for all prime ideals p in the ideal factorization
! 1787: * and v_p(b)>=0 for all other p, using the (standard) proof given in GTM 138.
! 1788: * Certainly not the most efficient, but sure.
! 1789: */
! 1790: GEN
! 1791: idealchinese(GEN nf, GEN x, GEN y)
! 1792: {
! 1793: long ty=typ(y),av=avma,i,j,k,l,N,r,r2;
! 1794: GEN fact,fact2,list,ep,ep1,ep2,z,t,v,p1,p2,p3,p4,s,pr,den;
! 1795:
! 1796: if (DEBUGLEVEL>4)
! 1797: {
! 1798: fprintferr(" entree dans idealchinese() :\n");
! 1799: fprintferr(" x = "); outerr(x);
! 1800: fprintferr(" y = "); outerr(y);
! 1801: }
! 1802: nf=checknf(nf); N=lgef(nf[1])-3;
! 1803: if (typ(x)!=t_MAT ||(lg(x)!=3))
! 1804: err(talker,"not a prime ideal factorization in idealchinese");
! 1805: fact=x; list=(GEN)fact[1]; ep=(GEN)fact[2]; r=lg(list);
! 1806: if (!is_vec_t(ty) || lg(y)!=r)
! 1807: err(talker,"not a suitable vector of elements in idealchinese");
! 1808: if (r==1) return gscalcol_i(gun,N);
! 1809:
! 1810: den=denom(y);
! 1811: if (!gcmp1(den))
! 1812: {
! 1813: fact2=idealfactor(nf,den);
! 1814: p1=(GEN)fact2[1]; r2=lg(p1);
! 1815: ep2=(GEN)fact2[2]; l=r+r2-1;
! 1816: z=cgetg(l,t_VEC); for (i=1; i<r; i++) z[i]=list[i];
! 1817: ep1=cgetg(l,t_VEC); for (i=1; i<r; i++) ep1[i]=ep[i];
! 1818: j=r-1;
! 1819: for (i=1; i<r2; i++)
! 1820: {
! 1821: p3=(GEN)p1[i]; k=1;
! 1822: while (k<r && !gegal((GEN)list[k],p3)) k++;
! 1823: if (k==r) { j++; z[j]=(long)p3; ep1[j]=ep2[i]; }
! 1824: else ep1[k]=ladd((GEN)ep1[k],(GEN)ep2[i]);
! 1825: }
! 1826: r=j+1; setlg(z,r); setlg(ep1,r); list=z; ep=ep1;
! 1827: }
! 1828: for (i=1; i<r; i++)
! 1829: if (signe(ep[i])<0) ep[i] = zero;
! 1830: t=idmat(N);
! 1831: for (i=1; i<r; i++)
! 1832: {
! 1833: pr=(GEN)list[i]; p4=(GEN)ep[i];
! 1834: if (signe(p4))
! 1835: {
! 1836: if (cmpis((GEN)pr[4],N))
! 1837: {
! 1838: p2=cgetg(3,t_MAT);
! 1839: p2[1]=(long)gscalcol_i(gpui((GEN)pr[1],p4,0), N);
! 1840: p2[2]=(long)element_pow(nf,(GEN)pr[2],p4);
! 1841: t=idealmat_mul(nf,t,p2);
! 1842: }
! 1843: else t=gmul(gpui((GEN)pr[1],p4,0),t);
! 1844: }
! 1845: }
! 1846: z=cgetg(r,t_VEC);
! 1847: for (i=1; i<r; i++)
! 1848: {
! 1849: pr=(GEN)list[i]; p4=(GEN)ep[i];
! 1850: if (cmpis((GEN)pr[4],N))
! 1851: {
! 1852: p2=cgetg(3,t_MAT); p1=gpui((GEN)pr[1],p4,0);
! 1853: p2[1]=(long)gscalcol_i(p1,N);
! 1854: p2[2]=(long)element_pow(nf,(GEN)pr[5],p4);
! 1855: z[i]=ldiv(idealmat_mul(nf,t,p2),p1);
! 1856: }
! 1857: else z[i]=ldiv(t,gpui((GEN)pr[1],p4,0));
! 1858: }
! 1859: v=idealaddmultoone(nf,z);
! 1860: s=cgetg(N+1,t_COL); for (i=1; i<=N; i++) s[i]=zero;
! 1861: for (i=1; i<r; i++)
! 1862: s = gadd(s,element_mul(nf,(GEN)v[i],(GEN)y[i]));
! 1863:
! 1864: p3 = appr_reduce(s,t,N);
! 1865: if (DEBUGLEVEL>2)
! 1866: { fprintferr(" sortie de idealchinese() : p3 = "); outerr(p3); }
! 1867: return gerepileupto(av,p3);
! 1868: }
! 1869:
! 1870: GEN
! 1871: idealappr(GEN nf, GEN x) { return idealappr0(nf,x,0); }
! 1872:
! 1873: GEN
! 1874: idealapprfact(GEN nf, GEN x) { return idealappr0(nf,x,1); }
! 1875:
! 1876: /* Given an integral ideal x and a in x, gives a b such that
! 1877: * x=aZ_K+bZ_K using a different algorithm than ideal_two_elt
! 1878: */
! 1879: GEN
! 1880: ideal_two_elt2(GEN nf, GEN x, GEN a)
! 1881: {
! 1882: long ta=typ(a), av=avma,tetpil,i,r;
! 1883: GEN con,ep,b,list,fact;
! 1884:
! 1885: nf = checknf(nf);
! 1886: if (!is_extscalar_t(ta) && typ(a)!=t_COL)
! 1887: err(typeer,"ideal_two_elt2");
! 1888: x = idealhermite_aux(nf,x);
! 1889: if (gcmp0(x))
! 1890: {
! 1891: if (!gcmp0(a)) err(talker,"element not in ideal in ideal_two_elt2");
! 1892: avma=av; return gcopy(a);
! 1893: }
! 1894: con = content(x);
! 1895: if (gcmp1(con)) con = NULL; else { x = gdiv(x,con); a = gdiv(a,con); }
! 1896: a = principalideal(nf,a);
! 1897: if (!gcmp1(denom(gauss(x,a))))
! 1898: err(talker,"element does not belong to ideal in ideal_two_elt2");
! 1899:
! 1900: fact=idealfactor(nf,a); list=(GEN)fact[1];
! 1901: r=lg(list); ep = (GEN)fact[2];
! 1902: for (i=1; i<r; i++) ep[i]=lstoi(idealval(nf,x,(GEN)list[i]));
! 1903: b = centermod(idealappr0(nf,fact,1), gcoeff(x,1,1));
! 1904: tetpil=avma; b = con? gmul(b,con): gcopy(b);
! 1905: return gerepile(av,tetpil,b);
! 1906: }
! 1907:
! 1908: /* Given 2 integral ideals x and y in a number field nf gives a beta
! 1909: * belonging to nf such that beta.x is an integral ideal coprime to y
! 1910: */
! 1911: GEN
! 1912: idealcoprime(GEN nf, GEN x, GEN y)
! 1913: {
! 1914: long av=avma,tetpil,i,r;
! 1915: GEN fact,list,p2,ep;
! 1916:
! 1917: if (DEBUGLEVEL>4)
! 1918: {
! 1919: fprintferr(" entree dans idealcoprime() :\n");
! 1920: fprintferr(" x = "); outerr(x);
! 1921: fprintferr(" y = "); outerr(y);
! 1922: }
! 1923: fact=idealfactor(nf,y); list=(GEN)fact[1];
! 1924: r=lg(list); ep = (GEN)fact[2];
! 1925: for (i=1; i<r; i++) ep[i]=lstoi(-idealval(nf,x,(GEN)list[i]));
! 1926: tetpil=avma; p2=idealappr0(nf,fact,1);
! 1927: if (DEBUGLEVEL>4)
! 1928: { fprintferr(" sortie de idealcoprime() : p2 = "); outerr(p2); }
! 1929: return gerepile(av,tetpil,p2);
! 1930: }
! 1931:
! 1932: /* returns the first index i<=n such that x=v[i] if it exits, 0 otherwise */
! 1933: long
! 1934: isinvector(GEN v, GEN x, long n)
! 1935: {
! 1936: long i;
! 1937:
! 1938: for (i=1; i<=n; i++)
! 1939: if (gegal((GEN)v[i],x)) return i;
! 1940: return 0;
! 1941: }
! 1942:
! 1943: /* Given an integral ideal x and three algebraic integers a, b and c in a
! 1944: * number field nf gives a beta belonging to nf such that beta.x^(-1) is an
! 1945: * integral ideal coprime to abc.Z_k
! 1946: */
! 1947: static GEN
! 1948: idealcoprimeinvabc(GEN nf, GEN x, GEN a, GEN b, GEN c)
! 1949: {
! 1950: long av=avma,tetpil,i,j,r,ra,rb,rc;
! 1951: GEN facta,factb,factc,fact,factall,p1,p2,ep;
! 1952:
! 1953: if (DEBUGLEVEL>4)
! 1954: {
! 1955: fprintferr(" entree dans idealcoprimeinvabc() :\n");
! 1956: fprintferr(" x = "); outerr(x); fprintferr(" a = "); outerr(a);
! 1957: fprintferr(" b = "); outerr(b); fprintferr(" c = "); outerr(c);
! 1958: flusherr();
! 1959: }
! 1960: facta=(GEN)idealfactor(nf,a)[1]; factb=(GEN)idealfactor(nf,b)[1];
! 1961: factc=(GEN)idealfactor(nf,c)[1]; ra=lg(facta); rb=lg(factb); rc=lg(factc);
! 1962: factall=cgetg(ra+rb+rc-2,t_COL);
! 1963: for (i=1; i<ra; i++) factall[i]=facta[i]; j=ra-1;
! 1964: for (i=1; i<rb; i++)
! 1965: if (!isinvector(factall,(GEN)factb[i],j)) factall[++j]=factb[i];
! 1966: for (i=1; i<rc; i++)
! 1967: if (!isinvector(factall,(GEN)factc[i],j)) factall[++j]=factc[i];
! 1968: r=j+1; fact=cgetg(3,t_MAT); p1=cgetg(r,t_COL); ep=cgetg(r,t_COL);
! 1969: for (i=1; i<r; i++) p1[i]=factall[i];
! 1970: for (i=1; i<r; i++) ep[i]=lstoi(idealval(nf,x,(GEN)p1[i]));
! 1971: fact[1]=(long)p1; fact[2]=(long)ep; tetpil=avma; p2=idealappr0(nf,fact,1);
! 1972: if (DEBUGLEVEL>2)
! 1973: { fprintferr(" sortie de idealcoprimeinvabc() : p2 = "); outerr(p2); }
! 1974: return gerepile(av,tetpil,p2);
! 1975: }
! 1976:
! 1977: /* Solve the equation ((b+aX).Z_k/((a,b).J),M)=Z_k. */
! 1978: static GEN
! 1979: findX(GEN nf, GEN a, GEN b, GEN J, GEN M)
! 1980: {
! 1981: long N,i,k,r,v;
! 1982: GEN p1,p2,abJ,fact,list,ve,ep,int0,int1,int2,pr;
! 1983:
! 1984: if (DEBUGLEVEL>4)
! 1985: {
! 1986: fprintferr(" entree dans findX() :\n");
! 1987: fprintferr(" a = "); outerr(a); fprintferr(" b = "); outerr(b);
! 1988: fprintferr(" J = "); outerr(J); fprintferr(" M = "); outerr(M);
! 1989: }
! 1990: N=lgef(nf[1])-3;
! 1991: p1=cgetg(3,t_MAT); p1[1]=(long)a; p1[2]=(long)b;
! 1992: if (N==2) p1=idealmul(nf,p1,idmat(2));
! 1993: abJ=idealmul(nf,p1,J);
! 1994: fact=idealfactor(nf,M); list=(GEN)fact[1]; r=lg(list);
! 1995: ve=cgetg(r,t_VEC); ep=cgetg(r,t_VEC);
! 1996: int0=cgetg(N+1,t_COL); int1=cgetg(N+1,t_COL); int2=cgetg(N+1,t_COL);
! 1997: for (i=2; i<=N; i++) int0[i]=int1[i]=int2[i]=zero;
! 1998: int0[1]=zero; int1[1]=un; int2[1]=deux;
! 1999: for (i=1; i<r; i++)
! 2000: {
! 2001: pr=(GEN)list[i]; v=element_val(nf,a,pr);
! 2002: if (v)
! 2003: {
! 2004: ep[i]=un;
! 2005: ve[i] = (element_val(nf,b,pr)<=v)? (long)int0: (long)int1;
! 2006: }
! 2007: else
! 2008: {
! 2009: v=idealval(nf,abJ,pr);
! 2010: p1=element_div(nf,idealaddtoone_i(nf,a,pr),a);
! 2011: ep[i]=lstoi(v+1); k=1;
! 2012: while (k<=v)
! 2013: {
! 2014: p1=element_mul(nf,p1,gsub(int2,element_mul(nf,a,p1)));
! 2015: k<<=1;
! 2016: }
! 2017: p1=element_mul(nf,p1,gsub(element_pow(nf,(GEN)pr[2],stoi(v)),b));
! 2018: ve[i]=lmod(p1,gpuigs((GEN)pr[1],v+1));
! 2019: }
! 2020: }
! 2021: fact[2]=(long)ep; p2=idealchinese(nf,fact,ve);
! 2022: if (DEBUGLEVEL>2) { fprintferr(" sortie de findX() : p2 = "); outerr(p2); }
! 2023: return p2;
! 2024: }
! 2025:
! 2026: /* A usage interne. Given a, b, c, d in nf, gives an algebraic integer y in
! 2027: * nf such that [c,d]-y.[a,b] is "small"
! 2028: */
! 2029: static GEN
! 2030: nfreducemat(GEN nf, GEN a, GEN b, GEN c, GEN d)
! 2031: {
! 2032: long av=avma,tetpil,i,i1,i2,j,j1,j2,k,N;
! 2033: GEN p1,p2,X,M,y,mult,s;
! 2034:
! 2035: mult=(GEN)nf[9]; N=lgef(nf[1])-3; X=cgetg(N+1,t_COL);
! 2036: for (j=1; j<=N; j++)
! 2037: {
! 2038: s=gzero;
! 2039: for (i=1; i<=N; i++) for (k=1; k<=N; k++)
! 2040: {
! 2041: p1=gcoeff(mult,k,j+(i-1)*N);
! 2042: if (!gcmp0(p1))
! 2043: s=gadd(s,gmul(p1,gadd(gmul((GEN)a[i],(GEN)c[k]),
! 2044: gmul((GEN)b[i],(GEN)d[k]))));
! 2045: }
! 2046: X[j]=(long)s;
! 2047: }
! 2048: M=cgetg(N+1,t_MAT);
! 2049: for (j2=1; j2<=N; j2++)
! 2050: {
! 2051: p1=cgetg(N+1,t_COL); M[j2]=(long)p1;
! 2052: for (j1=1; j1<=N; j1++)
! 2053: {
! 2054: s=gzero;
! 2055: for (i1=1; i1<=N; i1++)
! 2056: for (i2=1; i2<=N; i2++)
! 2057: for (k=1; k<=N; k++)
! 2058: {
! 2059: p2=gmul(gcoeff(mult,k,j1+(i1-1)*N),gcoeff(mult,k,j2+(i2-1)*N));
! 2060: if (!gcmp0(p2))
! 2061: s=gadd(s,gmul(p2,gadd(gmul((GEN)a[i1],(GEN)a[i2]),
! 2062: gmul((GEN)b[i1],(GEN)b[i2]))));
! 2063: }
! 2064: p1[j1]=(long)s;
! 2065: }
! 2066: }
! 2067: y=gauss(M,X); tetpil=avma;
! 2068: return gerepile(av,tetpil,ground(y));
! 2069: }
! 2070:
! 2071: /* Given 3 algebraic integers a,b,c in a number field nf given by their
! 2072: * components on the integral basis, gives a three-component vector [d,e,U]
! 2073: * whose first two components are algebraic integers d,e and the third a
! 2074: * unimodular 3x3-matrix U such that [a,b,c]*U=[0,d,e]
! 2075: */
! 2076: GEN
! 2077: threetotwo2(GEN nf, GEN a, GEN b, GEN c)
! 2078: {
! 2079: long av=avma,tetpil,i,N;
! 2080: GEN y,p1,p2,p3,M,X,Y,J,e,b1,c1,u,v,U,int0,Z,pk;
! 2081:
! 2082: if (DEBUGLEVEL>2)
! 2083: {
! 2084: fprintferr(" On entre dans threetotwo2() : \n");
! 2085: fprintferr(" a = "); outerr(a);
! 2086: fprintferr(" b = "); outerr(b);
! 2087: fprintferr(" c = "); outerr(c);
! 2088: }
! 2089: if (gcmp0(a))
! 2090: {
! 2091: y=cgetg(4,t_VEC); y[1]=lcopy(b); y[2]=lcopy(c); y[3]=(long)idmat(3);
! 2092: return y;
! 2093: }
! 2094: if (gcmp0(b))
! 2095: {
! 2096: y=cgetg(4,t_VEC); y[1]=lcopy(a); y[2]=lcopy(c);
! 2097: e = idmat(3); i=e[1]; e[1]=e[2]; e[2]=i;
! 2098: y[3]=(long)e; return y;
! 2099: }
! 2100: if (gcmp0(c))
! 2101: {
! 2102: y=cgetg(4,t_VEC); y[1]=lcopy(a); y[2]=lcopy(b);
! 2103: e = idmat(3); i=e[1]; e[1]=e[3]; e[3]=e[2]; e[2]=i;
! 2104: y[3]=(long)e; return y;
! 2105: }
! 2106:
! 2107: N=lgef(nf[1])-3;
! 2108: p1=cgetg(4,t_MAT); p1[1]=(long)a; p1[2]=(long)b;
! 2109: p1[3]=(long)c; p1=idealhermite_aux(nf,p1);
! 2110: if (DEBUGLEVEL>2)
! 2111: { fprintferr(" ideal a.Z_k+b.Z_k+c.Z_k = "); outerr(p1); }
! 2112: J=idealdiv(nf,e=idealcoprimeinvabc(nf,p1,a,b,c),p1);
! 2113: if (DEBUGLEVEL>2)
! 2114: { fprintferr(" ideal J = "); outerr(J); fprintferr(" e = "); outerr(e); }
! 2115: p1=cgetg(3,t_MAT); p1[1]=(long)a; p1[2]=(long)b; M=idealmul(nf,p1,J);
! 2116: if (DEBUGLEVEL>2)
! 2117: { fprintferr(" ideal M=(a.Z_k+b.Z_k).J = "); outerr(M); }
! 2118: X=findX(nf,a,b,J,M);
! 2119: if (DEBUGLEVEL>2){ fprintferr(" X = "); outerr(X); }
! 2120: p1=gadd(b,element_mul(nf,a,X));
! 2121: p2=cgetg(3,t_MAT); p2[1]=(long)element_mul(nf,a,p1);
! 2122: p2[2]=(long)element_mul(nf,c,p1);
! 2123: if (N==2) p2=idealhermite_aux(nf,p2);
! 2124: p3=cgetg(3,t_MAT); p3[1]=(long)a; p3[2]=(long)b;
! 2125: p3=idealhermite_aux(nf,p3);
! 2126: if (DEBUGLEVEL>2)
! 2127: { fprintferr(" ideal a.Z_k+b.Z_k = "); outerr(p3); }
! 2128: Y=findX(nf,a,c,J,idealdiv(nf,p2,p3));
! 2129: if (DEBUGLEVEL>2) { fprintferr(" Y = "); outerr(Y); }
! 2130: b1=element_div(nf,p1,e);
! 2131: if (DEBUGLEVEL>2) { fprintferr(" b1 = "); outerr(b1); }
! 2132: p2=gadd(c,element_mul(nf,a,Y));
! 2133: c1=element_div(nf,p2,e);
! 2134: if (DEBUGLEVEL>2) { fprintferr(" c1 = "); outerr(c1); }
! 2135: p1=idealhermite_aux(nf,b1);
! 2136: p2=idealhermite_aux(nf,c1);
! 2137: p3=idealaddtoone(nf,p1,p2);
! 2138: u=element_div(nf,(GEN)p3[1],b1); v=element_div(nf,(GEN)p3[2],c1);
! 2139: if (DEBUGLEVEL>2)
! 2140: { fprintferr(" u = "); outerr(u); fprintferr(" v = "); outerr(v); }
! 2141: U=cgetg(4,t_MAT);
! 2142: p1=cgetg(4,t_COL); p2=cgetg(4,t_COL); p3=cgetg(4,t_COL);
! 2143: U[1]=(long)p1; U[2]=(long)p2; U[3]=(long)p3;
! 2144: p1[1]=lsub(element_mul(nf,X,c1),element_mul(nf,Y,b1));
! 2145: p1[2]=(long)c1; p1[3]=lneg(b1);
! 2146: int0 = zerocol(N);
! 2147: p2[1]=(long)gscalcol_i(gun,N);
! 2148: p2[2]=p2[3]=(long)int0;
! 2149: Z=gadd(element_mul(nf,X,u),element_mul(nf,Y,v));
! 2150: pk=nfreducemat(nf,c1,(GEN)p1[3],u,v);
! 2151: p3[1]=(long)int0; p3[2]=lsub(u,element_mul(nf,pk,c1));
! 2152: p3[3]=(long)gadd(v,element_mul(nf,pk,b1));
! 2153: e=gadd(e,element_mul(nf,a,gsub(element_mul(nf,pk,(GEN)p1[1]),Z)));
! 2154: tetpil=avma;
! 2155: y=cgetg(4,t_VEC); y[1]=lcopy(a); y[2]=lcopy(e); y[3]=lcopy(U);
! 2156: if (DEBUGLEVEL>2)
! 2157: { fprintferr(" sortie de threetotwo2() : y = "); outerr(y); }
! 2158: return gerepile(av,tetpil,y);
! 2159: }
! 2160:
! 2161: /* Given 3 algebraic integers a,b,c in a number field nf given by their
! 2162: * components on the integral basis, gives a three-component vector [d,e,U]
! 2163: * whose first two components are algebraic integers d,e and the third a
! 2164: * unimodular 3x3-matrix U such that [a,b,c]*U=[0,d,e] Naive method which may
! 2165: * not work, but fast and small coefficients.
! 2166: */
! 2167: GEN
! 2168: threetotwo(GEN nf, GEN a, GEN b, GEN c)
! 2169: {
! 2170: long av=avma,tetpil,i,N;
! 2171: GEN pol,p1,p2,p3,p4,y,id,hu,h,V,U,r,vd,q1,q1a,q2,q2a,na,nb,nc,nr;
! 2172:
! 2173: nf=checknf(nf); pol=(GEN)nf[1]; N=lgef(pol)-3; id=idmat(N);
! 2174: na=gnorml2(a); nb=gnorml2(b); nc=gnorml2(c);
! 2175: U=gmul(idmat(3),gmodulsg(1,pol));
! 2176: if (gcmp(nc,nb)<0)
! 2177: {
! 2178: p1=c; c=b; b=p1; p1=nc; nc=nb; nb=p1;
! 2179: p1=(GEN)U[3]; U[3]=U[2]; U[2]=(long)p1;
! 2180: }
! 2181: if (gcmp(nc,na)<0)
! 2182: {
! 2183: p1=a; a=c; c=p1; p1=na; na=nc; nc=p1;
! 2184: p1=(GEN)U[1]; U[1]=U[3]; U[3]=(long)p1;
! 2185: }
! 2186: while (!gcmp0(gmin(na,nb)))
! 2187: {
! 2188: p1=cgetg(2*N+1,t_MAT);
! 2189: for (i=1; i<=N; i++)
! 2190: {
! 2191: p1[i]=(long)element_mul(nf,a,(GEN)id[i]);
! 2192: p1[i+N]=(long)element_mul(nf,b,(GEN)id[i]);
! 2193: }
! 2194: hu=hnfall(p1); h=(GEN)hu[1]; V=(GEN)hu[2];
! 2195: p2=(GEN)ker(concatsp(h,c))[1]; p3=(GEN)p2[N+1];
! 2196: p4=cgetg(N+1,t_COL);
! 2197: for (i=1; i<=N; i++) p4[i]=(long)ground(gdiv((GEN)p2[i],p3));
! 2198: r=gadd(c,gmul(h,p4));
! 2199: vd=cgetg(N+1,t_MAT); for (i=1; i<=N; i++) vd[i]=V[N+i];
! 2200: p2=gmul(vd,p4);
! 2201: q1=cgetg(N+1,t_COL); q2=cgetg(N+1,t_COL);
! 2202: for (i=1; i<=N; i++) { q1[i]=p2[i]; q2[i]=p2[i+N]; }
! 2203: q1a=basistoalg(nf,q1); q2a=basistoalg(nf,q2);
! 2204: U[3]=(long)gadd((GEN)U[3],gadd(gmul(q1a,(GEN)U[1]),gmul(q2a,(GEN)U[2])));
! 2205: nr=gnorml2(r);
! 2206: if (gcmp(nr,gmax(na,nb))>=0) err(talker,"threetotwo does not work");
! 2207: if (gcmp(na,nb)>=0)
! 2208: {
! 2209: c=a; nc=na; a=r; na=nr; p1=(GEN)U[1]; U[1]=U[3]; U[3]=(long)p1;
! 2210: }
! 2211: else
! 2212: {
! 2213: c=b; nc=nb; b=r; nb=nr; p1=(GEN)U[2]; U[2]=U[3]; U[3]=(long)p1;
! 2214: }
! 2215: }
! 2216: if (!gcmp0(na))
! 2217: {
! 2218: p1=a; a=b; b=p1; p1=(GEN)U[1]; U[1]=U[2]; U[2]=(long)p1;
! 2219: }
! 2220: tetpil=avma; y=cgetg(4,t_VEC); y[1]=lcopy(b); y[2]=lcopy(c);
! 2221: y[3]=(long)algtobasis(nf,U); return gerepile(av,tetpil,y);
! 2222: }
! 2223:
! 2224: /* Given 2 algebraic integers a,b in a number field nf given by their
! 2225: * components on the integral basis, gives a three-components vector [d,e,U]
! 2226: * whose first two component are algebraic integers d,e and the third a
! 2227: * unimodular 2x2-matrix U such that [a,b]*U=[d,e], with d and e hopefully
! 2228: * smaller than a and b.
! 2229: */
! 2230: GEN
! 2231: twototwo(GEN nf, GEN a, GEN b)
! 2232: {
! 2233: long av=avma,tetpil;
! 2234: GEN pol,p1,y,U,r,qr,qa,na,nb,nr;
! 2235:
! 2236: nf=checknf(nf);
! 2237: pol=(GEN)nf[1];
! 2238: na=gnorml2(a); nb=gnorml2(b);
! 2239: U=gmul(idmat(2),gmodulsg(1,pol));
! 2240: if (gcmp(na,nb)>0)
! 2241: {
! 2242: p1=a; a=b; b=p1; p1=na; na=nb; nb=p1;
! 2243: p1=(GEN)U[2]; U[2]=U[1]; U[1]=(long)p1;
! 2244: }
! 2245:
! 2246: while (!gcmp0(na))
! 2247: {
! 2248: qr=nfdivres(nf,b,a); r=(GEN)qr[2]; nr=gnorml2(r);
! 2249: if (gcmp(nr,na)<0)
! 2250: {
! 2251: b=a; a=r; nb=na; na=nr; qa=basistoalg(nf,(GEN)qr[1]);
! 2252: p1=gsub((GEN)U[2],gmul(qa,(GEN)U[1])); U[2]=U[1]; U[1]=(long)p1;
! 2253: }
! 2254: else
! 2255: {
! 2256: if (gcmp(nr,nb)<0)
! 2257: {
! 2258: qa=basistoalg(nf,(GEN)qr[1]);
! 2259: U[2]=lsub((GEN)U[2],gmul(qa,(GEN)U[1]));
! 2260: }
! 2261: break;
! 2262: }
! 2263: }
! 2264: tetpil=avma; y=cgetg(4,t_VEC); y[1]=lcopy(a); y[2]=lcopy(b);
! 2265: y[3]=(long)algtobasis(nf,U); return gerepile(av,tetpil,y);
! 2266: }
! 2267:
! 2268: GEN
! 2269: elt_mul_get_table(GEN nf, GEN x)
! 2270: {
! 2271: long i,lx = lg(x);
! 2272: GEN mul=cgetg(lx,t_MAT);
! 2273:
! 2274: /* assume w_1 = 1 */
! 2275: mul[1]=(long)x;
! 2276: for (i=2; i<lx; i++) mul[i] = (long)element_mulid(nf,x,i);
! 2277: return mul;
! 2278: }
! 2279:
! 2280: GEN
! 2281: elt_mul_table(GEN mul, GEN z)
! 2282: {
! 2283: long av = avma, i, lx = lg(mul);
! 2284: GEN p1 = gmul((GEN)z[1], (GEN)mul[1]);
! 2285:
! 2286: for (i=2; i<lx; i++)
! 2287: if (!gcmp0((GEN)z[i])) p1 = gadd(p1, gmul((GEN)z[i], (GEN)mul[i]));
! 2288: return gerepileupto(av, p1);
! 2289: }
! 2290:
! 2291: GEN
! 2292: element_mulvec(GEN nf, GEN x, GEN v)
! 2293: {
! 2294: long lv=lg(v),i;
! 2295: GEN mul = elt_mul_get_table(nf,x), y=cgetg(lv,t_COL);
! 2296:
! 2297: for (i=1; i<lv; i++)
! 2298: y[i] = (long)elt_mul_table(mul,(GEN)v[i]);
! 2299: return y;
! 2300: }
! 2301:
! 2302: static GEN
! 2303: element_mulvecrow(GEN nf, GEN x, GEN m, long i, long lim)
! 2304: {
! 2305: long lv,j;
! 2306: GEN y, mul = elt_mul_get_table(nf,x);
! 2307:
! 2308: lv=min(lg(m),lim+1); y=cgetg(lv,t_VEC);
! 2309: for (j=1; j<lv; j++)
! 2310: y[j] = (long)elt_mul_table(mul,gcoeff(m,i,j));
! 2311: return y;
! 2312: }
! 2313:
! 2314: /* Given an element x and an ideal in matrix form (not necessarily HNF),
! 2315: * gives an r such that x-r is in ideal and r is small. No checks
! 2316: */
! 2317: GEN
! 2318: element_reduce(GEN nf, GEN x, GEN ideal)
! 2319: {
! 2320: long tx=typ(x),av=avma,tetpil,N,i;
! 2321: GEN p1,u;
! 2322:
! 2323: if (is_extscalar_t(tx))
! 2324: x = algtobasis_intern(checknf(nf), x);
! 2325: N = lg(x); p1=cgetg(N+1,t_MAT);
! 2326: for (i=1; i<N; i++) p1[i]=ideal[i];
! 2327: p1[N]=(long)x; u=(GEN)ker(p1)[1];
! 2328: p1=(GEN)u[N]; setlg(u,N);
! 2329: for (i=1; i<N; i++) u[i]=lround(gdiv((GEN)u[i],p1));
! 2330: u=gmul(ideal,u); tetpil=avma;
! 2331: return gerepile(av,tetpil,gadd(u,x));
! 2332: }
! 2333:
! 2334: /* A torsion-free module M over Z_K will be given by a row vector [A,I] with
! 2335: * two components. I=[\a_1,...,\a_k] is a row vector of k fractional ideals
! 2336: * given in HNF. A is an nxk matrix (same k and n the rank of the module)
! 2337: * such that if A_j is the j-th column of A then M=\a_1A_1+...\a_kA_k. We say
! 2338: * that [A,I] is a pseudo-basis if k=n
! 2339: */
! 2340:
! 2341: /* Given a torsion-free module x as above outputs a pseudo-basis for x in
! 2342: * Hermite Normal Form
! 2343: */
! 2344: GEN
! 2345: nfhermite(GEN nf, GEN x)
! 2346: {
! 2347: long av=avma,tetpil,i,j,def,k,m;
! 2348: GEN p1,p2,y,A,I,J;
! 2349:
! 2350: nf=checknf(nf);
! 2351: if (typ(x)!=t_VEC || lg(x)!=3) err(talker,"not a module in nfhermite");
! 2352: A=(GEN)x[1]; I=(GEN)x[2]; k=lg(A)-1;
! 2353: if (typ(A)!=t_MAT) err(talker,"not a matrix in nfhermite");
! 2354: if (typ(I)!=t_VEC || lg(I)!=k+1)
! 2355: err(talker,"not a correct ideal list in nfhermite");
! 2356: if (!k) err(talker,"not a matrix of maximal rank in nfhermite");
! 2357: m=lg(A[1])-1;
! 2358: if (k<m) err(talker,"not a matrix of maximal rank in nfhermite");
! 2359:
! 2360: p1 = cgetg(k+1,t_MAT); for (j=1; j<=k; j++) p1[j]=A[j];
! 2361: A = p1; I = dummycopy(I);
! 2362: for (j=1; j<=k; j++)
! 2363: if (typ(I[j])!=t_MAT) I[j]=(long)idealhermite_aux(nf,(GEN)I[j]);
! 2364:
! 2365: J=cgetg(k+1,t_VEC); def=k+1;
! 2366: for (i=m; i>=1; i--)
! 2367: {
! 2368: GEN den,p4,p5,p6,u,v,newid, invnewid = NULL;
! 2369:
! 2370: def--; j=def; while (j>=1 && gcmp0(gcoeff(A,i,j))) j--;
! 2371: if (!j) err(talker,"not a matrix of maximal rank in nfhermite");
! 2372: if (j==def) j--;
! 2373: else
! 2374: {
! 2375: p1=(GEN)A[j]; A[j]=A[def]; A[def]=(long)p1;
! 2376: p1=(GEN)I[j]; I[j]=I[def]; I[def]=(long)p1;
! 2377: }
! 2378: p1=gcoeff(A,i,def); p2=element_inv(nf,p1);
! 2379: A[def]=(long)element_mulvec(nf,p2,(GEN)A[def]);
! 2380: I[def]=(long)idealmul(nf,p1,(GEN)I[def]);
! 2381: for ( ; j; j--)
! 2382: {
! 2383: p1=gcoeff(A,i,j);
! 2384: if (!gcmp0(p1))
! 2385: {
! 2386: p2=idealmul(nf,p1,(GEN)I[j]);
! 2387: newid = idealadd(nf,p2,(GEN)I[def]);
! 2388: invnewid = hnfideal_inv(nf,newid);
! 2389: p4 = idealmul(nf, p2, invnewid);
! 2390: p5 = idealmul(nf,(GEN)I[def],invnewid);
! 2391: y = idealaddtoone(nf,p4,p5);
! 2392: u=element_div(nf,(GEN)y[1],p1); v=(GEN)y[2];
! 2393: p6=gsub((GEN)A[j],element_mulvec(nf,p1,(GEN)A[def]));
! 2394: A[def]=ladd(element_mulvec(nf,u,(GEN)A[j]),
! 2395: element_mulvec(nf,v,(GEN)A[def]));
! 2396: A[j]=(long)p6;
! 2397: I[j]=(long)idealmul(nf,idealmul(nf,(GEN)I[j],(GEN)I[def]),invnewid);
! 2398: I[def]=(long)newid; den=denom((GEN)I[j]);
! 2399: if (!gcmp1(den))
! 2400: {
! 2401: I[j]=lmul(den,(GEN)I[j]);
! 2402: A[j]=ldiv((GEN)A[j],den);
! 2403: }
! 2404: }
! 2405: }
! 2406: if (!invnewid) invnewid = hnfideal_inv(nf,(GEN)I[def]);
! 2407: p1=(GEN)I[def]; J[def]=(long)invnewid;
! 2408: for (j=def+1; j<=k; j++)
! 2409: {
! 2410: p2=gsub(element_reduce(nf,gcoeff(A,i,j),idealmul(nf,p1,(GEN)J[j])),
! 2411: gcoeff(A,i,j));
! 2412: A[j]=ladd((GEN)A[j],element_mulvec(nf,p2,(GEN)A[def]));
! 2413: }
! 2414: }
! 2415: tetpil=avma; y=cgetg(3,t_VEC);
! 2416: p1=cgetg(m+1,t_MAT); y[1]=(long)p1;
! 2417: p2=cgetg(m+1,t_VEC); y[2]=(long)p2;
! 2418: for (j=1; j<=m; j++) p1[j]=lcopy((GEN)A[j+k-m]);
! 2419: for (j=1; j<=m; j++) p2[j]=lcopy((GEN)I[j+k-m]);
! 2420: return gerepile(av,tetpil,y);
! 2421: }
! 2422:
! 2423: /* A torsion module M over Z_K will be given by a row vector [A,I,J] with
! 2424: * three components. I=[b_1,...,b_n] is a row vector of k fractional ideals
! 2425: * given in HNF, J=[a_1,...,a_n] is a row vector of n fractional ideals in
! 2426: * HNF. A is an nxn matrix (same n) such that if A_j is the j-th column of A
! 2427: * and e_n is the canonical basis of K^n, then
! 2428: * M=(b_1e_1+...+b_ne_n)/(a_1A_1+...a_nA_n)
! 2429: */
! 2430:
! 2431: /* We input a torsion module x=[A,I,J] as above, and output the
! 2432: * smith normal form as K=[\c_1,...,\c_n] such that x=Z_K/\c_1+...+Z_K/\c_n.
! 2433: */
! 2434: GEN
! 2435: nfsmith(GEN nf, GEN x)
! 2436: {
! 2437: long av,tetpil,i,j,k,l,lim,c,fl,n,m,N;
! 2438: GEN p1,p2,p3,p4,z,b,u,v,w,d,dinv,unnf,A,I,J;
! 2439:
! 2440: nf=checknf(nf); N=lgef(nf[1])-3;
! 2441: if (typ(x)!=t_VEC || lg(x)!=4) err(talker,"not a module in nfsmith");
! 2442: A=(GEN)x[1]; I=(GEN)x[2]; J=(GEN)x[3];
! 2443: if (typ(A)!=t_MAT) err(talker,"not a matrix in nfsmith");
! 2444: n=lg(A)-1;
! 2445: if (typ(I)!=t_VEC || lg(I)!=n+1 || typ(J)!=t_VEC || lg(J)!=n+1)
! 2446: err(talker,"not a correct ideal list in nfsmith");
! 2447: if (!n) err(talker,"not a matrix of maximal rank in nfsmith");
! 2448: m=lg(A[1])-1;
! 2449: if (n<m) err(talker,"not a matrix of maximal rank in nfsmith");
! 2450: if (n>m) err(impl,"nfsmith for non square matrices");
! 2451:
! 2452: av=avma; lim=stack_lim(av,1);
! 2453: p1 = cgetg(n+1,t_MAT); for (j=1; j<=n; j++) p1[j]=A[j];
! 2454: A = p1; I = dummycopy(I); J=dummycopy(J);
! 2455: for (j=1; j<=n; j++)
! 2456: if (typ(I[j])!=t_MAT) I[j]=(long)idealhermite_aux(nf,(GEN)I[j]);
! 2457: for (j=1; j<=n; j++)
! 2458: if (typ(J[j])!=t_MAT) J[j]=(long)idealhermite_aux(nf,(GEN)J[j]);
! 2459: for (i=n; i>=2; i--)
! 2460: {
! 2461: do
! 2462: {
! 2463: c=0;
! 2464: for (j=i-1; j>=1; j--)
! 2465: {
! 2466: p1=gcoeff(A,i,j);
! 2467: if (!gcmp0(p1))
! 2468: {
! 2469: p2=gcoeff(A,i,i);
! 2470: d=nfbezout(nf,p2,p1,(GEN)J[i],(GEN)J[j],&u,&v,&w,&dinv);
! 2471: if (!gcmp0(u))
! 2472: {
! 2473: if (!gcmp0(v))
! 2474: b=gadd(element_mulvec(nf,u,(GEN)A[i]),
! 2475: element_mulvec(nf,v,(GEN)A[j]));
! 2476: else b=element_mulvec(nf,u,(GEN)A[i]);
! 2477: }
! 2478: else b=element_mulvec(nf,v,(GEN)A[j]);
! 2479: A[j]=lsub(element_mulvec(nf,p2,(GEN)A[j]),
! 2480: element_mulvec(nf,p1,(GEN)A[i]));
! 2481: A[i]=(long)b; J[j]=(long)w; J[i]=(long)d;
! 2482: }
! 2483: }
! 2484: for (j=i-1; j>=1; j--)
! 2485: {
! 2486: p1=gcoeff(A,j,i);
! 2487: if (!gcmp0(p1))
! 2488: {
! 2489: p2=gcoeff(A,i,i);
! 2490: d=nfbezout(nf,p2,p1,(GEN)I[i],(GEN)I[j],&u,&v,&w,&dinv);
! 2491: if (gcmp0(u))
! 2492: b=element_mulvecrow(nf,v,A,j,i);
! 2493: else
! 2494: {
! 2495: if (gcmp0(v))
! 2496: b=element_mulvecrow(nf,u,A,i,i);
! 2497: else
! 2498: b=gadd(element_mulvecrow(nf,u,A,i,i),
! 2499: element_mulvecrow(nf,v,A,j,i));
! 2500: }
! 2501: p3=gsub(element_mulvecrow(nf,p2,A,j,i),
! 2502: element_mulvecrow(nf,p1,A,i,i));
! 2503: for (k=1; k<=i; k++) { coeff(A,j,k)=p3[k]; coeff(A,i,k)=b[k]; }
! 2504: I[j]=(long)w; I[i]=(long)d; c++;
! 2505: }
! 2506: }
! 2507: if (!c)
! 2508: {
! 2509: b=gcoeff(A,i,i); if (gcmp0(b)) break;
! 2510:
! 2511: b=idealmul(nf,b,idealmul(nf,(GEN)J[i],(GEN)I[i]));
! 2512: fl=1;
! 2513: for (k=1; k<i && fl; k++)
! 2514: for (l=1; l<i && fl; l++)
! 2515: {
! 2516: p3=gcoeff(A,k,l);
! 2517: if (!gcmp0(p3))
! 2518: fl=gegal(idealadd(nf,b,idealmul(nf,p3,idealmul(nf,(GEN)J[l],(GEN)I[k]))),b);
! 2519: }
! 2520: if (!fl)
! 2521: {
! 2522: k--; l--;
! 2523: b=idealdiv(nf,(GEN)I[k],(GEN)I[i]);
! 2524: p4=gauss(idealdiv(nf,(GEN)J[i],idealmul(nf,p3,(GEN)J[l])),b);
! 2525: l=1; while (l<=N && gcmp1(denom((GEN)p4[l]))) l++;
! 2526: if (l>N) err(talker,"bug2 in nfsmith");
! 2527: p3=element_mulvecrow(nf,(GEN)b[l],A,k,i);
! 2528: for (l=1; l<=i; l++)
! 2529: coeff(A,i,l) = ladd(gcoeff(A,i,l),(GEN)p3[l]);
! 2530: }
! 2531: }
! 2532: if (low_stack(lim, stack_lim(av,1)))
! 2533: {
! 2534: GEN *gptr[3];
! 2535: if(DEBUGMEM>1) err(warnmem,"nfsmith");
! 2536: gptr[0]=&A; gptr[1]=&I; gptr[2]=&J; gerepilemany(av,gptr,3);
! 2537: }
! 2538: }
! 2539: while (c || !fl);
! 2540: }
! 2541: unnf=gscalcol_i(gun,N);
! 2542: p1=gcoeff(A,1,1); coeff(A,1,1)=(long)unnf;
! 2543: J[1]=(long)idealmul(nf,p1,(GEN)J[1]);
! 2544: for (i=2; i<=n; i++)
! 2545: if (!gegal(gcoeff(A,i,i),unnf)) err(talker,"bug in nfsmith");
! 2546: tetpil=avma; z=cgetg(n+1,t_VEC);
! 2547: for (i=1; i<=n; i++) z[i]=(long)idealmul(nf,(GEN)I[i],(GEN)J[i]);
! 2548: return gerepile(av,tetpil,z);
! 2549: }
! 2550:
! 2551: /*******************************************************************/
! 2552: /* */
! 2553: /* ALGEBRE LINEAIRE DANS LES CORPS DE NOMBRES */
! 2554: /* */
! 2555: /*******************************************************************/
! 2556:
! 2557: #define trivlift(x) ((typ(x)==t_POLMOD)? (GEN)x[2]: lift_intern(x))
! 2558:
! 2559: GEN
! 2560: element_mulmodpr2(GEN nf, GEN x, GEN y, GEN prhall)
! 2561: {
! 2562: long av=avma;
! 2563: GEN p1;
! 2564:
! 2565: nf=checknf(nf); checkprhall(prhall);
! 2566: p1 = element_mul(nf,x,y);
! 2567: return gerepileupto(av,nfreducemodpr(nf,p1,prhall));
! 2568: }
! 2569:
! 2570: /* On ne peut PAS definir ca comme les autres par
! 2571: * #define element_divmodpr() nfreducemodpr(element_div())
! 2572: * car le element_div ne marche pas en general
! 2573: */
! 2574: GEN
! 2575: element_divmodpr(GEN nf, GEN x, GEN y, GEN prhall)
! 2576: {
! 2577: long av=avma;
! 2578: GEN p1;
! 2579:
! 2580: nf=checknf(nf); checkprhall(prhall);
! 2581: p1=lift_intern(gdiv(gmodulcp(gmul((GEN)nf[7],trivlift(x)), (GEN)nf[1]),
! 2582: gmodulcp(gmul((GEN)nf[7],trivlift(y)), (GEN)nf[1])));
! 2583: p1=algtobasis_intern(nf,p1);
! 2584: return gerepileupto(av,nfreducemodpr(nf,p1,prhall));
! 2585: }
! 2586:
! 2587: GEN
! 2588: element_invmodpr(GEN nf, GEN y, GEN prhall)
! 2589: {
! 2590: long av=avma;
! 2591: GEN p1;
! 2592:
! 2593: p1=ginvmod(gmul((GEN)nf[7],trivlift(y)), (GEN)nf[1]);
! 2594: p1=algtobasis_intern(nf,p1);
! 2595: return gerepileupto(av,nfreducemodpr(nf,p1,prhall));
! 2596: }
! 2597:
! 2598: GEN
! 2599: element_powmodpr(GEN nf,GEN x,GEN k,GEN prhall)
! 2600: {
! 2601: long av=avma,N,s;
! 2602: GEN y,z;
! 2603:
! 2604: nf=checknf(nf); checkprhall(prhall);
! 2605: N=lgef(nf[1])-3;
! 2606: s=signe(k); k=(s>=0)?k:negi(k);
! 2607: z=x; y = gscalcol_i(gun,N);
! 2608: for(;;)
! 2609: {
! 2610: if (mpodd(k)) y=element_mulmodpr(nf,z,y,prhall);
! 2611: k=shifti(k,-1);
! 2612: if (signe(k)) z=element_sqrmodpr(nf,z,prhall);
! 2613: else
! 2614: {
! 2615: cgiv(k); if (s<0) y = element_invmodpr(nf,y,prhall);
! 2616: return gerepileupto(av,y);
! 2617: }
! 2618: }
! 2619: }
! 2620:
! 2621: /* x est une matrice dont les coefficients sont des vecteurs dans la base
! 2622: * d'entiers modulo un ideal premier prhall, sous forme reduite modulo prhall.
! 2623: */
! 2624: GEN
! 2625: nfkermodpr(GEN nf, GEN x, GEN prhall)
! 2626: {
! 2627: long i,j,k,r,t,n,m,av0,av,av1,av2,N,lim;
! 2628: GEN c,d,y,unnf,munnf,zeromodp,zeronf,p,pp,prh;
! 2629:
! 2630: nf=checknf(nf); checkprhall(prhall);
! 2631: if (typ(x)!=t_MAT) err(typeer,"nfkermodpr");
! 2632: n=lg(x)-1; if (!n) return cgetg(1,t_MAT);
! 2633: prh=(GEN)prhall[1]; av0=avma;
! 2634: N=lgef(nf[1])-3; pp=gcoeff(prh,1,1);
! 2635:
! 2636: zeromodp=gmodulsg(0,pp);
! 2637: unnf=cgetg(N+1,t_COL); unnf[1]=(long)gmodulsg(1,pp);
! 2638: zeronf=cgetg(N+1,t_COL); zeronf[1]=(long)zeromodp;
! 2639:
! 2640: av=avma; munnf=cgetg(N+1,t_COL); munnf[1]=(long)gmodulsg(-1,pp);
! 2641: for (i=2; i<=N; i++)
! 2642: zeronf[i] = munnf[i] = unnf[i] = (long)zeromodp;
! 2643:
! 2644: m=lg(x[1])-1; x=dummycopy(x); r=0;
! 2645: c=new_chunk(m+1); for (k=1; k<=m; k++) c[k]=0;
! 2646: d=new_chunk(n+1); av1=avma; lim=stack_lim(av1,1);
! 2647: for (k=1; k<=n; k++)
! 2648: {
! 2649: j=1;
! 2650: while (j<=m && (c[j] || gcmp0(gcoeff(x,j,k)))) j++;
! 2651: if (j>m) { r++; d[k]=0; }
! 2652: else
! 2653: {
! 2654: p=element_divmodpr(nf,munnf,gcoeff(x,j,k),prhall);
! 2655: c[j]=k; d[k]=j; coeff(x,j,k)=(long)munnf;
! 2656: for (i=k+1; i<=n; i++)
! 2657: coeff(x,j,i)=(long)element_mulmodpr(nf,p,gcoeff(x,j,i),prhall);
! 2658: for (t=1; t<=m; t++)
! 2659: if (t!=j)
! 2660: {
! 2661: p=gcoeff(x,t,k); coeff(x,t,k)=(long)zeronf;
! 2662: for (i=k+1; i<=n; i++)
! 2663: coeff(x,t,i)=ladd(gcoeff(x,t,i),
! 2664: element_mulmodpr(nf,p,gcoeff(x,j,i),prhall));
! 2665: }
! 2666: if (low_stack(lim, stack_lim(av1,1)))
! 2667: {
! 2668: if (DEBUGMEM>1) err(warnmem,"nfkermodpr, k = %ld / %ld",k,n);
! 2669: av2=avma; x=gerepile(av1,av2,gcopy(x));
! 2670: }
! 2671: }
! 2672: }
! 2673: if (!r) { avma=av0; return cgetg(1,t_MAT); }
! 2674: av1=avma; y=cgetg(r+1,t_MAT);
! 2675: for (j=k=1; j<=r; j++,k++)
! 2676: {
! 2677: p=cgetg(n+1,t_COL); y[j]=(long)p; while (d[k]) k++;
! 2678: for (i=1; i<k; i++) p[i]=d[i]? lcopy(gcoeff(x,d[i],k)): (long)zeronf;
! 2679: p[k]=(long)unnf; for (i=k+1; i<=n; i++) p[i]=(long)zeronf;
! 2680: }
! 2681: return gerepile(av,av1,y);
! 2682: }
! 2683:
! 2684: /* a.x=b ou b est un vecteur */
! 2685: GEN
! 2686: nfsolvemodpr(GEN nf, GEN a, GEN b, GEN prhall)
! 2687: {
! 2688: long nbli,nbco,i,j,k,av=avma,tetpil;
! 2689: GEN aa,x,p,m,u;
! 2690:
! 2691: nf=checknf(nf); checkprhall(prhall);
! 2692: if (typ(a)!=t_MAT) err(typeer,"nfsolvemodpr");
! 2693: nbco=lg(a)-1; nbli=lg(a[1])-1;
! 2694: if (typ(b)!=t_COL) err(typeer,"nfsolvemodpr");
! 2695: if (lg(b)!=nbco+1) err(mattype1,"nfsolvemodpr");
! 2696: x=cgetg(nbli+1,t_COL);
! 2697: for (j=1; j<=nbco; j++) x[j]=b[j];
! 2698: aa=cgetg(nbco+1,t_MAT);
! 2699: for (j=1; j<=nbco; j++)
! 2700: {
! 2701: aa[j]=lgetg(nbli+1,t_COL);
! 2702: for (i=1; i<=nbli; i++) coeff(aa,i,j)=coeff(a,i,j);
! 2703: }
! 2704: for (i=1; i<nbli; i++)
! 2705: {
! 2706: p=gcoeff(aa,i,i); k=i;
! 2707: if (gcmp0(p))
! 2708: {
! 2709: k=i+1; while (k<=nbli && gcmp0(gcoeff(aa,k,i))) k++;
! 2710: if (k>nbco) err(matinv1);
! 2711: for (j=i; j<=nbco; j++)
! 2712: {
! 2713: u=gcoeff(aa,i,j); coeff(aa,i,j)=coeff(aa,k,j);
! 2714: coeff(aa,k,j)=(long)u;
! 2715: }
! 2716: u=(GEN)x[i]; x[i]=x[k]; x[k]=(long)u;
! 2717: p=gcoeff(aa,i,i);
! 2718: }
! 2719: for (k=i+1; k<=nbli; k++)
! 2720: {
! 2721: m=gcoeff(aa,k,i);
! 2722: if (!gcmp0(m))
! 2723: {
! 2724: m=element_divmodpr(nf,m,p,prhall);
! 2725: for (j=i+1; j<=nbco; j++)
! 2726: coeff(aa,k,j)=lsub(gcoeff(aa,k,j),
! 2727: element_mulmodpr(nf,m,gcoeff(aa,i,j),prhall));
! 2728: x[k]=lsub((GEN)x[k],element_mulmodpr(nf,m,(GEN)x[i],prhall));
! 2729: }
! 2730: }
! 2731: }
! 2732: /* Resolution systeme triangularise */
! 2733: p=gcoeff(aa,nbli,nbco); if (gcmp0(p)) err(matinv1);
! 2734:
! 2735: x[nbli]=(long)element_divmodpr(nf,(GEN)x[nbli],p,prhall);
! 2736: for (i=nbli-1; i>0; i--)
! 2737: {
! 2738: m=(GEN)x[i];
! 2739: for (j=i+1; j<=nbco; j++)
! 2740: m=gsub(m,element_mulmodpr(nf,gcoeff(aa,i,j),(GEN)x[j],prhall));
! 2741: x[i]=(long)element_divmodpr(nf,m,gcoeff(aa,i,i),prhall);
! 2742: }
! 2743: tetpil=avma; return gerepile(av,tetpil,gcopy(x));
! 2744: }
! 2745:
! 2746: GEN
! 2747: nfsuppl(GEN nf, GEN x, long n, GEN prhall)
! 2748: {
! 2749: long av=avma,av2,k,s,t,N,lx=lg(x);
! 2750: GEN y,p1,p2,p,unmodp,zeromodp,unnf,zeronf,prh;
! 2751: stackzone *zone;
! 2752:
! 2753: k=lx-1; if (k>n) err(suppler2);
! 2754: if (k && lg(x[1])!=n+1) err(talker,"incorrect dimension in nfsupl");
! 2755: N=lgef(nf[1])-3; prh=(GEN)prhall[1]; p=gcoeff(prh,1,1);
! 2756:
! 2757: zone = switch_stack(NULL, 2*(3 + 2*lg(p) + N+1) + (n+3)*(n+1));
! 2758: switch_stack(zone,1);
! 2759: unmodp=gmodulsg(1,p); zeromodp=gmodulsg(0,p);
! 2760: unnf=gscalcol_proto(unmodp,zeromodp,N);
! 2761: zeronf=gscalcol_proto(zeromodp,zeromodp,N);
! 2762: y = idmat_intern(n,unnf,zeronf);
! 2763: switch_stack(zone,0); av2=avma;
! 2764:
! 2765: for (s=1; s<=k; s++)
! 2766: {
! 2767: p1=nfsolvemodpr(nf,y,(GEN)x[s],prhall); t=s;
! 2768: while (t<=n && gcmp0((GEN)p1[t])) t++;
! 2769: avma=av2; if (t>n) err(suppler2);
! 2770: p2=(GEN)y[s]; y[s]=x[s]; if (s!=t) y[t]=(long)p2;
! 2771: }
! 2772: avma=av; y=gcopy(y);
! 2773: free(zone); return y;
! 2774: }
! 2775:
! 2776: /* Given two fractional ideals a and b, gives x in a, y in b, z in b^-1,
! 2777: t in a^-1 such that xt-yz=1. In the present version, z is in Z. */
! 2778: GEN
! 2779: nfidealdet1(GEN nf, GEN a, GEN b)
! 2780: {
! 2781: long av=avma,tetpil;
! 2782: GEN x,p1,p2,res,z,da,db;
! 2783:
! 2784: da=denom(a); if (gcmp1(da)) da = NULL; else a=gmul(da,a);
! 2785: db=denom(b); if (gcmp1(db)) db = NULL; else b=gmul(db,b);
! 2786: a = idealinv(nf,a); x=idealcoprime(nf,a,b);
! 2787: p1=idealmul(nf,x,a); p2=idealaddtoone(nf,p1,b);
! 2788:
! 2789: tetpil=avma; res=cgetg(5,t_VEC);
! 2790: res[1] = da? ldiv(x,da): lcopy(x);
! 2791: res[2] = db? ldiv((GEN)p2[2],db): lcopy((GEN)p2[2]);
! 2792: z = db? gneg_i(db): negi(gun);
! 2793: res[3] = (long) gscalcol_i(z, lgef(nf[1])-3);
! 2794: res[4] = (long) element_div(nf,(GEN)p2[1],(GEN)res[1]);
! 2795: return gerepile(av,tetpil,res);
! 2796: }
! 2797:
! 2798: /* Given a pseudo basis pseudo, outputs a multiple of its ideal determinant */
! 2799: GEN
! 2800: nfdetint(GEN nf,GEN pseudo)
! 2801: {
! 2802: GEN pass,c,v,det1,piv,pivprec,vi,p1,x,I,unnf,zeronf,id,idprod;
! 2803: long i,j,k,rg,n,n1,m,m1,av=avma,av1,tetpil,lim,cm=0,N;
! 2804:
! 2805: nf=checknf(nf); N=lgef(nf[1])-3;
! 2806: if (typ(pseudo)!=t_VEC || lg(pseudo)!=3)
! 2807: err(talker,"not a module in nfdetint");
! 2808: x=(GEN)pseudo[1]; I=(GEN)pseudo[2];
! 2809: if (typ(x)!=t_MAT) err(talker,"not a matrix in nfdetint");
! 2810: n1=lg(x); n=n1-1; if (!n) return gun;
! 2811:
! 2812: m1=lg(x[1]); m=m1-1;
! 2813: if (typ(I)!=t_VEC || lg(I)!=n1)
! 2814: err(talker,"not a correct ideal list in nfdetint");
! 2815:
! 2816: unnf=gscalcol_i(gun,N); zeronf=zerocol(N);
! 2817: id=idmat(N); c=new_chunk(m1); for (k=1; k<=m; k++) c[k]=0;
! 2818: piv = pivprec = unnf;
! 2819:
! 2820: av1=avma; lim=stack_lim(av1,1);
! 2821: det1=idprod=gzero; /* dummy for gerepilemany */
! 2822: pass=cgetg(m1,t_MAT); v=cgetg(m1,t_COL);
! 2823: for (j=1; j<=m; j++)
! 2824: {
! 2825: v[j] = zero; /* dummy */
! 2826: p1=cgetg(m1,t_COL); pass[j]=(long)p1;
! 2827: for (i=1; i<=m; i++) p1[i]=(long)zeronf;
! 2828: }
! 2829: for (rg=0,k=1; k<=n; k++)
! 2830: {
! 2831: long t = 0;
! 2832: for (i=1; i<=m; i++)
! 2833: if (!c[i])
! 2834: {
! 2835: vi=element_mul(nf,piv,gcoeff(x,i,k));
! 2836: for (j=1; j<=m; j++)
! 2837: if (c[j]) vi=gadd(vi,element_mul(nf,gcoeff(pass,i,j),gcoeff(x,j,k)));
! 2838: v[i]=(long)vi; if (!t && !gcmp0(vi)) t=i;
! 2839: }
! 2840: if (t)
! 2841: {
! 2842: pivprec = piv;
! 2843: if (rg == m-1)
! 2844: {
! 2845: if (!cm)
! 2846: {
! 2847: cm=1; idprod = id;
! 2848: for (i=1; i<=m; i++)
! 2849: if (i!=t)
! 2850: idprod = (idprod==id)? (GEN)I[c[i]]
! 2851: : idealmul(nf,idprod,(GEN)I[c[i]]);
! 2852: }
! 2853: p1 = idealmul(nf,(GEN)v[t],(GEN)I[k]); c[t]=0;
! 2854: det1 = (typ(det1)==t_INT)? p1: idealadd(nf,p1,det1);
! 2855: }
! 2856: else
! 2857: {
! 2858: rg++; piv=(GEN)v[t]; c[t]=k;
! 2859: for (i=1; i<=m; i++)
! 2860: if (!c[i])
! 2861: {
! 2862: for (j=1; j<=m; j++)
! 2863: if (c[j] && j!=t)
! 2864: {
! 2865: p1=gsub(element_mul(nf,piv,gcoeff(pass,i,j)),
! 2866: element_mul(nf,(GEN)v[i],gcoeff(pass,t,j)));
! 2867: coeff(pass,i,j) = rg>1? (long) element_div(nf,p1,pivprec)
! 2868: : (long) p1;
! 2869: }
! 2870: coeff(pass,i,t)=lneg((GEN)v[i]);
! 2871: }
! 2872: }
! 2873: }
! 2874: if (low_stack(lim, stack_lim(av1,1)))
! 2875: {
! 2876: GEN *gptr[6];
! 2877: if(DEBUGMEM>1) err(warnmem,"nfdetint");
! 2878: gptr[0]=&det1; gptr[1]=ϖ gptr[2]=&pivprec; gptr[3]=&pass;
! 2879: gptr[4]=&v; gptr[5]=&idprod; gerepilemany(av1,gptr,6);
! 2880: }
! 2881: }
! 2882: if (!cm) { avma=av; return gscalmat(gzero,N); }
! 2883: tetpil=avma; return gerepile(av,tetpil,idealmul(nf,idprod,det1));
! 2884: }
! 2885:
! 2886: /* clean in place (destroy x) */
! 2887: static void
! 2888: nfcleanmod(GEN nf, GEN x, long lim, GEN detmat)
! 2889: {
! 2890: long lx=lg(x),i;
! 2891:
! 2892: if (lim<=0 || lim>=lx) lim=lx-1;
! 2893: for (i=1; i<=lim; i++)
! 2894: x[i]=(long)element_reduce(nf,(GEN)x[i],detmat);
! 2895: }
! 2896:
! 2897: static GEN
! 2898: zero_nfbezout(GEN nf,GEN b, GEN ida,GEN idb,GEN *u,GEN *v,GEN *w,GEN *di)
! 2899: {
! 2900: long av, tetpil, j, N=lgef(nf[1])-3;
! 2901: GEN pab,d;
! 2902:
! 2903: d=idealmulelt(nf,b,idb); *di=idealinv(nf,d);
! 2904: av=avma; pab=idealmul(nf,ida,idb); tetpil=avma;
! 2905: *w=gerepile(av,tetpil, idealmul(nf,pab,*di));
! 2906:
! 2907: *u=cgetg(N+1,t_COL); for (j=1; j<=N; j++) (*u)[j]=zero;
! 2908: *v=element_inv(nf,b); return d;
! 2909: }
! 2910:
! 2911: /* a usage interne
! 2912: * Given elements a,b, ideals ida, idb, outputs d=a.ida+b.idb and gives
! 2913: * di=d^-1, w=ida.idb.di, u, v such that au+bv=1 and u in ida.di, v in
! 2914: * idb.di. We assume ida, idb non-zero, but a and b can be zero. Error if a
! 2915: * and b are both zero.
! 2916: */
! 2917: static GEN
! 2918: nfbezout(GEN nf,GEN a,GEN b, GEN ida,GEN idb, GEN *u,GEN *v,GEN *w,GEN *di)
! 2919: {
! 2920: GEN pab,pu,pv,pw,uv,d,dinv,pa,pb,pa1,pb1, *gptr[5];
! 2921: long av,tetpil;
! 2922:
! 2923: if (gcmp0(a))
! 2924: {
! 2925: if (gcmp0(b)) err(talker,"both elements zero in nfbezout");
! 2926: return zero_nfbezout(nf,b,ida,idb,u,v,w,di);
! 2927: }
! 2928: if (gcmp0(b))
! 2929: return zero_nfbezout(nf,a,idb,ida,v,u,w,di);
! 2930:
! 2931: av = avma;
! 2932: pa=idealmulelt(nf,a,ida);
! 2933: pb=idealmulelt(nf,b,idb);
! 2934:
! 2935: d=idealadd(nf,pa,pb); dinv=idealinv(nf,d);
! 2936: pa1=idealmullll(nf,pa,dinv);
! 2937: pb1=idealmullll(nf,pb,dinv);
! 2938: uv=idealaddtoone(nf,pa1,pb1);
! 2939: pab=idealmul(nf,ida,idb); tetpil=avma;
! 2940:
! 2941: pu=element_div(nf,(GEN)uv[1],a);
! 2942: pv=element_div(nf,(GEN)uv[2],b);
! 2943: d=gcopy(d); dinv=gcopy(dinv);
! 2944: pw=idealmul(nf,pab,dinv);
! 2945:
! 2946: *u=pu; *v=pv; *w=pw; *di=dinv;
! 2947: gptr[0]=u; gptr[1]=v; gptr[2]=w; gptr[3]=di;
! 2948: gptr[4]=&d; gerepilemanysp(av,tetpil,gptr,5);
! 2949: return d;
! 2950: }
! 2951:
! 2952: /* A usage interne. Pas de verifs ni gestion de pile */
! 2953: GEN
! 2954: idealoplll(GEN op(GEN,GEN,GEN), GEN nf, GEN x, GEN y)
! 2955: {
! 2956: GEN z = op(nf,x,y), den = denom(z);
! 2957:
! 2958: if (gcmp1(den)) den = NULL; else z=gmul(den,z);
! 2959: z=gmul(z,lllintpartial(z));
! 2960: return den? gdiv(z,den): z;
! 2961: }
! 2962:
! 2963: /* A usage interne. Pas de verifs ni gestion de pile */
! 2964: GEN
! 2965: idealmulelt(GEN nf, GEN elt, GEN x)
! 2966: {
! 2967: long lx=lg(x),j;
! 2968: GEN z=cgetg(lx,t_MAT);
! 2969: for (j=1; j<lx; j++) z[j]=(long)element_mul(nf,elt,(GEN)x[j]);
! 2970: return z;
! 2971: }
! 2972:
! 2973: GEN
! 2974: nfhermitemod(GEN nf, GEN pseudo, GEN detmat)
! 2975: {
! 2976: long av0=avma,li,co,av,tetpil,i,j,jm1,def,ldef,lim,N;
! 2977: GEN b,q,w,p1,p2,d,u,v,den,x,I,J,dinv,unnf,wh;
! 2978:
! 2979: nf=checknf(nf); N=lgef(nf[1])-3;
! 2980: if (typ(pseudo)!=t_VEC || lg(pseudo)!=3)
! 2981: err(talker,"not a module in nfhermitemod");
! 2982: x=(GEN)pseudo[1]; I=(GEN)pseudo[2];
! 2983: if (typ(x)!=t_MAT) err(talker,"not a matrix in nfhermitemod");
! 2984: co=lg(x);
! 2985: if (typ(I)!=t_VEC || lg(I)!=co)
! 2986: err(talker,"not a correct ideal list in nfhermitemod");
! 2987: if (co==1) return cgetg(1,t_MAT);
! 2988:
! 2989: li=lg(x[1]); x=dummycopy(x); I=dummycopy(I);
! 2990: unnf=gscalcol_i(gun,N);
! 2991: for (j=1; j<co; j++)
! 2992: if (typ(I[j])!=t_MAT) I[j]=(long)idealhermite_aux(nf,(GEN)I[j]);
! 2993:
! 2994: den=denom(detmat); if (!gcmp1(den)) detmat=gmul(den,detmat);
! 2995: detmat=gmul(detmat,lllintpartial(detmat));
! 2996:
! 2997: av=avma; lim=stack_lim(av,1);
! 2998: def=co; ldef=(li>co)?li-co+1:1;
! 2999: for (i=li-1; i>=ldef; i--)
! 3000: {
! 3001: def--; j=def-1; while (j && gcmp0(gcoeff(x,i,j))) j--;
! 3002: while (j)
! 3003: {
! 3004: jm1=j-1; if (!jm1) jm1=def;
! 3005: d=nfbezout(nf,gcoeff(x,i,j),gcoeff(x,i,jm1),(GEN)I[j],(GEN)I[jm1],
! 3006: &u,&v,&w,&dinv);
! 3007: if (!gcmp0(u))
! 3008: {
! 3009: p1=element_mulvec(nf,u,(GEN)x[j]);
! 3010: if (!gcmp0(v)) p1=gadd(p1, element_mulvec(nf,v,(GEN)x[jm1]));
! 3011: }
! 3012: else p1=element_mulvec(nf,v,(GEN)x[jm1]);
! 3013: x[j]=lsub(element_mulvec(nf,gcoeff(x,i,j),(GEN)x[jm1]),
! 3014: element_mulvec(nf,gcoeff(x,i,jm1),(GEN)x[j]));
! 3015: nfcleanmod(nf,(GEN)x[j],i,idealdivlll(nf,detmat,w));
! 3016: nfcleanmod(nf,p1,i,idealmullll(nf,detmat,dinv));
! 3017: x[jm1]=(long)p1; I[j]=(long)w; I[jm1]=(long)d;
! 3018: j--; while (j && gcmp0(gcoeff(x,i,j))) j--;
! 3019: }
! 3020: if (low_stack(lim, stack_lim(av,1)))
! 3021: {
! 3022: GEN *gptr[2];
! 3023: if(DEBUGMEM>1) err(warnmem,"[1]: nfhermitemod");
! 3024: gptr[0]=&x; gptr[1]=&I; gerepilemany(av,gptr,2);
! 3025: }
! 3026: }
! 3027: b=detmat; wh=cgetg(li,t_MAT); def--;
! 3028: for (i=li-1; i>=1; i--)
! 3029: {
! 3030: d = nfbezout(nf,gcoeff(x,i,i+def),unnf,(GEN)I[i+def],b,&u,&v,&w,&dinv);
! 3031: p1 = element_mulvec(nf,u,(GEN)x[i+def]);
! 3032: nfcleanmod(nf,p1,i,idealmullll(nf,b,dinv));
! 3033: wh[i]=(long)p1; coeff(wh,i,i)=(long)unnf; I[i+def]=(long)d;
! 3034: if (i>1) b=idealmul(nf,b,dinv);
! 3035: }
! 3036: J=cgetg(li,t_VEC); J[1]=zero;
! 3037: for (j=2; j<li; j++) J[j]=(long)idealinv(nf,(GEN)I[j+def]);
! 3038: for (i=li-2; i>=1; i--)
! 3039: {
! 3040: for (j=i+1; j<li; j++)
! 3041: {
! 3042: q=idealmul(nf,(GEN)I[i+def],(GEN)J[j]);
! 3043: p1=gsub(element_reduce(nf,gcoeff(wh,i,j),q),gcoeff(wh,i,j));
! 3044: wh[j]=(long)gadd((GEN)wh[j],element_mulvec(nf,p1,(GEN)wh[i]));
! 3045: }
! 3046: if (low_stack(lim, stack_lim(av,1)))
! 3047: {
! 3048: GEN *gptr[3];
! 3049: if(DEBUGMEM>1) err(warnmem,"[2]: nfhermitemod");
! 3050: gptr[0]=&wh; gptr[1]=&I; gptr[2]=&J; gerepilemany(av,gptr,3);
! 3051: }
! 3052: }
! 3053: tetpil=avma; p1=cgetg(3,t_VEC); p1[1]=lcopy(wh);
! 3054: p2=cgetg(li,t_VEC); p1[2]=(long)p2;
! 3055: for (j=1; j<li; j++) p2[j]=lcopy((GEN)I[j+def]);
! 3056: return gerepile(av0,tetpil,p1);
! 3057: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>