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