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