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