Annotation of OpenXM_contrib/pari-2.2/src/basemath/base3.c, Revision 1.1.1.1
1.1 noro 1: /* $Id: base3.c,v 1.41 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: /* */
20: /*******************************************************************/
21: #include "pari.h"
22: extern int ker_trivial_mod_p(GEN x, GEN p);
23: extern long ideal_is_zk(GEN ideal,long N);
24: extern GEN famat_ideallog(GEN nf, GEN g, GEN e, GEN bid);
25: extern GEN famat_to_nf_modidele(GEN nf, GEN g, GEN e, GEN bid);
26: extern GEN hnfall_i(GEN A, GEN *ptB, long remove);
27: extern GEN vconcat(GEN A, GEN B);
28:
29: /*******************************************************************/
30: /* */
31: /* OPERATIONS OVER NUMBER FIELD ELEMENTS. */
32: /* These are always represented as column vectors over the */
33: /* integral basis nf[7] */
34: /* */
35: /*******************************************************************/
36:
37: int
38: isnfscalar(GEN x)
39: {
40: long lx=lg(x),i;
41:
42: for (i=2; i<lx; i++)
43: if (!gcmp0((GEN)x[i])) return 0;
44: return 1;
45: }
46:
47: static GEN
48: scal_mul(GEN nf, GEN x, GEN y, long ty)
49: {
50: long av=avma, tetpil;
51: GEN p1;
52:
53: if (!is_extscalar_t(ty))
54: {
55: if (ty!=t_COL) err(typeer,"nfmul");
56: y = gmul((GEN)nf[7],y);
57: }
58: p1 = gmul(x,y); tetpil=avma;
59: return gerepile(av,tetpil,algtobasis(nf,p1));
60: }
61:
62: static GEN
63: get_tab(GEN nf, long *N)
64: {
65: GEN tab = (typ(nf) == t_MAT)? nf: (GEN)nf[9];
66: *N = lg(tab[1])-1; return tab;
67: }
68:
69: /* product of x and y in nf */
70: GEN
71: element_mul(GEN nf, GEN x, GEN y)
72: {
73: long av,i,j,k,N,tx,ty;
74: GEN s,v,c,p1,tab;
75:
76: if (x == y) return element_sqr(nf,x);
77:
78: tx=typ(x); ty=typ(y);
79: nf=checknf(nf); tab = get_tab(nf, &N);
80: if (tx==t_POLMOD) x=checknfelt_mod(nf,x,"element_mul");
81: if (ty==t_POLMOD) y=checknfelt_mod(nf,y,"element_mul");
82: if (is_extscalar_t(tx)) return scal_mul(nf,x,y,ty);
83: if (is_extscalar_t(ty)) return scal_mul(nf,y,x,tx);
84: if (isnfscalar(x)) return gmul((GEN)x[1],y);
85: if (isnfscalar(y)) return gmul((GEN)y[1],x);
86:
87: v=cgetg(N+1,t_COL); av=avma;
88: for (k=1; k<=N; k++)
89: {
90: if (k == 1)
91: s = gmul((GEN)x[1],(GEN)y[1]);
92: else
93: s = gadd(gmul((GEN)x[1],(GEN)y[k]),
94: gmul((GEN)x[k],(GEN)y[1]));
95: for (i=2; i<=N; i++)
96: {
97: c=gcoeff(tab,k,(i-1)*N+i);
98: if (signe(c))
99: {
100: p1 = gmul((GEN)x[i],(GEN)y[i]);
101: if (!gcmp1(c)) p1 = gmul(p1,c);
102: s = gadd(s, p1);
103: }
104: for (j=i+1; j<=N; j++)
105: {
106: c=gcoeff(tab,k,(i-1)*N+j);
107: if (signe(c))
108: {
109: p1 = gadd(gmul((GEN)x[i],(GEN)y[j]),
110: gmul((GEN)x[j],(GEN)y[i]));
111: if (!gcmp1(c)) p1 = gmul(p1,c);
112: s = gadd(s, p1);
113: }
114: }
115: }
116: v[k]=(long)gerepileupto(av,s); av=avma;
117: }
118: return v;
119: }
120:
121: /* inverse of x in nf */
122: GEN
123: element_inv(GEN nf, GEN x)
124: {
125: long av=avma,i,N,tx=typ(x);
126: GEN p1,p;
127:
128: nf=checknf(nf); N=degpol(nf[1]);
129: if (is_extscalar_t(tx))
130: {
131: if (tx==t_POLMOD) checknfelt_mod(nf,x,"element_inv");
132: else if (tx==t_POL) x=gmodulcp(x,(GEN)nf[1]);
133: return gerepileupto(av, algtobasis(nf, ginv(x)));
134: }
135: if (isnfscalar(x))
136: {
137: p1=cgetg(N+1,t_COL); p1[1]=linv((GEN)x[1]);
138: for (i=2; i<=N; i++) p1[i]=lcopy((GEN)x[i]);
139: return p1;
140: }
141: p = NULL;
142: for (i=1; i<=N; i++)
143: if (typ(x[i])==t_INTMOD)
144: {
145: p = gmael(x,i,1);
146: x = lift(x); break;
147: }
148: p1 = ginvmod(gmul((GEN)nf[7],x), (GEN)nf[1]);
149: p1 = algtobasis_intern(nf,p1);
150:
151: if (p) p1 = FpV(p1, p);
152: return gerepileupto(av,p1);
153: }
154:
155: /* quotient of x and y in nf */
156: GEN
157: element_div(GEN nf, GEN x, GEN y)
158: {
159: long av=avma,i,N,tx=typ(x),ty=typ(y);
160: GEN p1,p;
161:
162: nf=checknf(nf); N=degpol(nf[1]);
163: if (tx==t_POLMOD) checknfelt_mod(nf,x,"element_div");
164: else if (tx==t_POL) x=gmodulcp(x,(GEN)nf[1]);
165:
166: if (ty==t_POLMOD) checknfelt_mod(nf,y,"element_div");
167: else if (ty==t_POL) y=gmodulcp(y,(GEN)nf[1]);
168:
169: if (is_extscalar_t(tx))
170: {
171: if (is_extscalar_t(ty)) p1=gdiv(x,y);
172: else
173: {
174: if (ty!=t_COL) err(typeer,"nfdiv");
175: p1=gdiv(x,gmodulcp(gmul((GEN)nf[7],y),(GEN)nf[1]));
176: }
177: return gerepileupto(av, algtobasis(nf,p1));
178: }
179: if (is_extscalar_t(ty))
180: {
181: if (tx!=t_COL) err(typeer,"nfdiv");
182: p1=gdiv(gmodulcp(gmul((GEN)nf[7],x),(GEN)nf[1]),y);
183: return gerepileupto(av, algtobasis(nf,p1));
184: }
185:
186: if (isnfscalar(y)) return gdiv(x,(GEN)y[1]);
187: if (isnfscalar(x))
188: {
189: p1=element_inv(nf,y);
190: return gerepileupto(av, gmul((GEN)x[1],p1));
191: }
192:
193: p = NULL;
194: for (i=1; i<=N; i++)
195: if (typ(x[i])==t_INTMOD)
196: {
197: p = gmael(x,i,1);
198: x = lift(x); break;
199: }
200: for (i=1; i<=N; i++)
201: if (typ(y[i])==t_INTMOD)
202: {
203: p1 = gmael(y,i,1);
204: if (p && !egalii(p,p1))
205: err(talker,"inconsistant prime moduli in element_inv");
206: y = lift(y); break;
207: }
208:
209: p1 = gmul(gmul((GEN)nf[7],x), ginvmod(gmul((GEN)nf[7],y), (GEN)nf[1]));
210: p1 = algtobasis_intern(nf, gres(p1, (GEN)nf[1]));
211: if (p) p1 = FpV(p1,p);
212: return gerepileupto(av,p1);
213: }
214:
215: /* product of INTEGERS (i.e vectors with integral coeffs) x and y in nf */
216: GEN
217: element_muli(GEN nf, GEN x, GEN y)
218: {
219: long av,i,j,k,N;
220: GEN p1,s,v,c,tab;
221:
222: tab = get_tab(nf, &N);
223: v=cgetg(N+1,t_COL); av=avma;
224: for (k=1; k<=N; k++)
225: {
226: if (k == 1)
227: s = mulii((GEN)x[1],(GEN)y[1]);
228: else
229: s = addii(mulii((GEN)x[1],(GEN)y[k]),
230: mulii((GEN)x[k],(GEN)y[1]));
231: for (i=2; i<=N; i++)
232: {
233: c=gcoeff(tab,k,(i-1)*N+i);
234: if (signe(c))
235: {
236: p1 = mulii((GEN)x[i],(GEN)y[i]);
237: if (!gcmp1(c)) p1 = mulii(p1,c);
238: s = addii(s,p1);
239: }
240: for (j=i+1; j<=N; j++)
241: {
242: c=gcoeff(tab,k,(i-1)*N+j);
243: if (signe(c))
244: {
245: p1 = addii(mulii((GEN)x[i],(GEN)y[j]),
246: mulii((GEN)x[j],(GEN)y[i]));
247: if (!gcmp1(c)) p1 = mulii(p1,c);
248: s = addii(s,p1);
249: }
250: }
251: }
252: v[k]=(long) gerepileuptoint(av,s); av=avma;
253: }
254: return v;
255: }
256:
257: /* product of INTEGERS (i.e vectors with integral coeffs) x and y in nf */
258: GEN
259: element_sqri(GEN nf, GEN x)
260: {
261: GEN p1,s,v,c,tab;
262: long av,i,j,k,N;
263:
264: tab = get_tab(nf, &N);
265:
266: v=cgetg(N+1,t_COL); av=avma;
267: for (k=1; k<=N; k++)
268: {
269: if (k == 1)
270: s = sqri((GEN)x[1]);
271: else
272: s = shifti(mulii((GEN)x[1],(GEN)x[k]), 1);
273: for (i=2; i<=N; i++)
274: {
275: c=gcoeff(tab,k,(i-1)*N+i);
276: if (signe(c))
277: {
278: p1 = sqri((GEN)x[i]);
279: if (!gcmp1(c)) p1 = mulii(p1,c);
280: s = addii(s,p1);
281: }
282: for (j=i+1; j<=N; j++)
283: {
284: c=gcoeff(tab,k,(i-1)*N+j);
285: if (signe(c))
286: {
287: p1 = shifti(mulii((GEN)x[i],(GEN)x[j]),1);
288: if (!gcmp1(c)) p1 = mulii(p1,c);
289: s = addii(s,p1);
290: }
291: }
292: }
293: v[k]=(long) gerepileuptoint(av,s); av=avma;
294: }
295: return v;
296: }
297:
298: /* square of x in nf */
299: GEN
300: element_sqr(GEN nf, GEN x)
301: {
302: long av = avma,i,j,k,N, tx = typ(x);
303: GEN p1,s,v,c,tab;
304:
305: nf = checknf(nf);
306: tab = get_tab(nf, &N);
307: if (tx==t_POLMOD) x=checknfelt_mod(nf,x,"element_sqr");
308: if (is_extscalar_t(tx))
309: return gerepileupto(av, algtobasis(nf, gsqr(x)));
310: if (isnfscalar(x))
311: {
312: s=cgetg(N+1,t_COL); s[1]=lsqr((GEN)x[1]);
313: for (i=2; i<=N; i++) s[i]=lcopy((GEN)x[i]);
314: return s;
315: }
316: v=cgetg(N+1,t_COL); av = avma;
317: for (k=1; k<=N; k++)
318: {
319: if (k == 1)
320: s = gsqr((GEN)x[1]);
321: else
322: s = gmul2n(gmul((GEN)x[1],(GEN)x[k]), 1);
323: for (i=2; i<=N; i++)
324: {
325: c=gcoeff(tab,k,(i-1)*N+i);
326: if (signe(c))
327: {
328: p1 = gsqr((GEN)x[i]);
329: if (!gcmp1(c)) p1 = gmul(p1,c);
330: s = gadd(s,p1);
331: }
332: for (j=i+1; j<=N; j++)
333: {
334: c=gcoeff(tab,k,(i-1)*N+j);
335: if (signe(c))
336: {
337: p1 = gmul((GEN)x[i],(GEN)x[j]);
338: p1 = gcmp1(c)? gmul2n(p1,1): gmul(p1,shifti(c,1));
339: s = gadd(s,p1);
340: }
341: }
342: }
343: v[k]=(long)gerepileupto(av,s); av=avma;
344: }
345: return v;
346: }
347:
348: /* Compute x^n in nf, left-shift binary powering */
349: GEN
350: element_pow(GEN nf, GEN x, GEN n)
351: {
352: ulong av = avma;
353: long s,N,i,j,m;
354: GEN y,p1,cx;
355:
356: if (typ(n)!=t_INT) err(talker,"not an integer exponent in nfpow");
357: nf=checknf(nf); N=degpol(nf[1]);
358: s=signe(n); if (!s) return gscalcol_i(gun,N);
359: if (typ(x)!=t_COL) x=algtobasis(nf,x);
360:
361: if (isnfscalar(x))
362: {
363: y = gscalcol_i(gun,N);
364: y[1] = (long)powgi((GEN)x[1],n); return y;
365: }
366: cx = content(x);
367: if (gcmp1(cx)) cx = NULL; else x = gdiv(x,cx);
368: p1 = n+2; m = *p1;
369: y=x; j=1+bfffo(m); m<<=j; j = BITS_IN_LONG-j;
370: for (i=lgefint(n)-2;;)
371: {
372: for (; j; m<<=1,j--)
373: {
374: y = element_sqr(nf, y);
375: if (m<0) y=element_mul(nf, y, x);
376: }
377: if (--i == 0) break;
378: m = *++p1, j = BITS_IN_LONG;
379: }
380: if (s<0) y = element_inv(nf, y);
381: if (cx) y = gmul(y, powgi(cx, n));
382: return av==avma? gcopy(y): gerepileupto(av,y);
383: }
384:
385: /* x in Z^n, compute lift(x^n mod p) */
386: GEN
387: element_pow_mod_p(GEN nf, GEN x, GEN n, GEN p)
388: {
389: ulong av = avma;
390: long s,N,i,j,m;
391: GEN y,p1;
392:
393: if (typ(n)!=t_INT) err(talker,"not an integer exponent in nfpow");
394: nf=checknf(nf); N=degpol(nf[1]);
395: s=signe(n); if (!s) return gscalcol_i(gun,N);
396: if (typ(x)!=t_COL) x=algtobasis(nf,x);
397:
398: if (isnfscalar(x))
399: {
400: y = gscalcol_i(gun,N);
401: y[1] = (long)powmodulo((GEN)x[1],n,p); return y;
402: }
403: p1 = n+2; m = *p1;
404: y=x; j=1+bfffo(m); m<<=j; j = BITS_IN_LONG-j;
405: for (i=lgefint(n)-2;;)
406: {
407: for (; j; m<<=1,j--)
408: {
409: y = element_sqri(nf, y);
410: if (m<0) y=element_muli(nf, y, x);
411: y = FpV_red(y, p);
412: }
413: if (--i == 0) break;
414: m = *++p1, j = BITS_IN_LONG;
415: }
416: if (s<0) y = FpV_red(element_inv(nf,y), p);
417: return av==avma? gcopy(y): gerepileupto(av,y);
418: }
419:
420: /* x = I-th vector of the Z-basis of Z_K, in Z^n, compute lift(x^n mod p) */
421: GEN
422: element_powid_mod_p(GEN nf, long I, GEN n, GEN p)
423: {
424: ulong av = avma;
425: long s,N,i,j,m;
426: GEN y,p1;
427:
428: if (typ(n)!=t_INT) err(talker,"not an integer exponent in nfpow");
429: nf=checknf(nf); N=degpol(nf[1]);
430: s=signe(n);
431: if (!s || I == 1) return gscalcol_i(gun,N);
432: p1 = n+2; m = *p1;
433: y = zerocol(N); y[I] = un;
434: j=1+bfffo(m); m<<=j; j = BITS_IN_LONG-j;
435: for (i=lgefint(n)-2;;)
436: {
437: for (; j; m<<=1,j--)
438: {
439: y = element_sqri(nf, y);
440: if (m<0) y=element_mulid(nf, y, I);
441: y = FpV_red(y, p);
442: }
443: if (--i == 0) break;
444: m = *++p1, j = BITS_IN_LONG;
445: }
446: if (s<0) y = FpV_red(element_inv(nf,y), p);
447: return av==avma? gcopy(y): gerepileupto(av,y);
448: }
449:
450: /* Outputs x.w_i, where w_i is the i-th elt of the integral basis */
451: GEN
452: element_mulid(GEN nf, GEN x, long i)
453: {
454: long av,j,k,N;
455: GEN s,v,c,p1, tab;
456:
457: if (i==1) return gcopy(x);
458: tab = get_tab(nf, &N);
459: if (typ(x) != t_COL || lg(x) != N+1) err(typeer,"element_mulid");
460: tab += (i-1)*N;
461: v=cgetg(N+1,t_COL); av=avma;
462: for (k=1; k<=N; k++)
463: {
464: s = gzero;
465: for (j=1; j<=N; j++)
466: if (signe(c = gcoeff(tab,k,j)) && !gcmp0(p1 = (GEN)x[j]))
467: {
468: if (!gcmp1(c)) p1 = gmul(p1,c);
469: s = gadd(s,p1);
470: }
471: v[k]=lpileupto(av,s); av=avma;
472: }
473: return v;
474: }
475:
476: /* valuation of integer x, with resp. to prime ideal P above p.
477: * p.P^(-1) = b Z_K, v >= val_p(norm(x)), and N = deg(nf)
478: * [b may be given as the 'multiplication by b' matrix]
479: */
480: long
481: int_elt_val(GEN nf, GEN x, GEN p, GEN b, GEN *newx, long v)
482: {
483: long i,k,w, N = degpol(nf[1]);
484: GEN r,a,y,mul;
485:
486: if (typ(b) == t_MAT) mul = b;
487: else
488: {
489: mul = cgetg(N+1,t_MAT);
490: for (i=1; i<=N; i++) mul[i] = (long)element_mulid(nf,b,i);
491: }
492: y = cgetg(N+1, t_COL); /* will hold the new x */
493: x = dummycopy(x);
494: for(w=0; w<=v; w++)
495: {
496: for (i=1; i<=N; i++)
497: { /* compute (x.b)_i */
498: a = mulii((GEN)x[1], gcoeff(mul,i,1));
499: for (k=2; k<=N; k++) a = addii(a, mulii((GEN)x[k], gcoeff(mul,i,k)));
500: /* is it divisible by p ? */
501: y[i] = ldvmdii(a,p,&r);
502: if (signe(r)) goto END;
503: }
504: r=x; x=y; y=r;
505: }
506: END:
507: if (newx) *newx = x;
508: return w;
509: }
510:
511: long
512: element_val(GEN nf, GEN x, GEN vp)
513: {
514: long av = avma,N,w,vcx,e;
515: GEN cx,p;
516:
517: if (gcmp0(x)) return VERYBIGINT;
518: nf=checknf(nf); N=degpol(nf[1]);
519: checkprimeid(vp); p=(GEN)vp[1]; e=itos((GEN)vp[3]);
520: switch(typ(x))
521: {
522: case t_INT: case t_FRAC: case t_FRACN:
523: return ggval(x,p)*e;
524: case t_POLMOD: x = (GEN)x[2]; /* fall through */
525: case t_POL:
526: x = algtobasis_intern(nf,x); break;
527: case t_COL:
528: if (lg(x)==N+1) break;
529: default: err(typeer,"element_val");
530: }
531: if (isnfscalar(x)) return ggval((GEN)x[1],p)*e;
532:
533: cx = content(x);
534: if (gcmp1(cx)) vcx=0; else { x = gdiv(x,cx); vcx = ggval(cx,p); }
535: w = int_elt_val(nf,x,p,(GEN)vp[5],NULL,VERYBIGINT);
536: avma=av; return w + vcx*e;
537: }
538:
539: /* d = a multiple of norm(x), x integral */
540: long
541: element_val2(GEN nf, GEN x, GEN d, GEN vp)
542: {
543: GEN p = (GEN)vp[1];
544: long av, v = ggval(d,p);
545:
546: if (!v) return 0;
547: av=avma;
548: v = int_elt_val(nf,x,p,(GEN)vp[5],NULL,v);
549: avma=av; return v;
550: }
551:
552: /* polegal without comparing variables */
553: long
554: polegal_spec(GEN x, GEN y)
555: {
556: long i = lgef(x);
557:
558: if (i != lgef(y)) return 0;
559: for (i--; i > 1; i--)
560: if (!gegal((GEN)x[i],(GEN)y[i])) return 0;
561: return 1;
562: }
563:
564: GEN
565: basistoalg(GEN nf, GEN x)
566: {
567: long tx=typ(x),lx=lg(x),i;
568: GEN z;
569:
570: nf=checknf(nf);
571: switch(tx)
572: {
573: case t_COL:
574: for (i=1; i<lx; i++)
575: {
576: long t = typ(x[i]);
577: if (is_matvec_t(t)) break;
578: }
579: if (i==lx)
580: {
581: z = cgetg(3,t_POLMOD);
582: z[1] = lcopy((GEN)nf[1]);
583: z[2] = lmul((GEN)nf[7],x); return z;
584: }
585: /* fall through */
586:
587: case t_VEC: case t_MAT: z=cgetg(lx,tx);
588: for (i=1; i<lx; i++) z[i]=(long)basistoalg(nf,(GEN)x[i]);
589: return z;
590:
591: case t_POLMOD:
592: if (!polegal_spec((GEN)nf[1],(GEN)x[1]))
593: err(talker,"not the same number field in basistoalg");
594: return gcopy(x);
595: default: z=cgetg(3,t_POLMOD);
596: z[1]=lcopy((GEN)nf[1]);
597: z[2]=lmul(x,polun[varn(nf[1])]); return z;
598: }
599: }
600:
601: /* return the (N-dimensional) vector of coeffs of p */
602: GEN
603: pol_to_vec(GEN x, long N)
604: {
605: long i, l;
606: GEN z = cgetg(N+1,t_COL);
607: if (typ(x) != t_POL)
608: {
609: z[1] = (long)x;
610: for (i=2; i<=N; i++) z[i]=zero;
611: return z;
612: }
613: l = lgef(x)-1; x++;
614: for (i=1; i<l ; i++) z[i]=x[i];
615: for ( ; i<=N; i++) z[i]=zero;
616: return z;
617: }
618:
619: /* gmul(A, pol_to_vec(x)), A matrix of compatible dimensions */
620: GEN
621: mulmat_pol(GEN A, GEN x)
622: {
623: long i,l;
624: GEN z;
625: if (typ(x) != t_POL) return gscalcol(x, lg(A[1])-1);
626: l=lgef(x)-1; if (l == 1) return zerocol(lg(A[1])-1);
627: x++; z = gmul((GEN)x[1], (GEN)A[1]);
628: for (i=2; i<l ; i++)
629: if (!gcmp0((GEN)x[i])) z = gadd(z, gmul((GEN)x[i], (GEN)A[i]));
630: return z;
631: }
632:
633: /* valid for scalars and polynomial, degree less than N.
634: * No garbage collecting. No check (SEGV for vectors).
635: */
636: GEN
637: algtobasis_intern(GEN nf, GEN x)
638: {
639: GEN P = (GEN)nf[1];
640: long tx = typ(x), N = degpol(P);
641:
642: if (tx==t_POLMOD) { x=(GEN)x[2]; tx=typ(x); }
643: if (tx==t_POL)
644: {
645: if (varn(x) != varn(P))
646: err(talker,"incompatible variables in algtobasis");
647: if (degpol(x) >= N) x = gres(x,P);
648: return mulmat_pol((GEN)nf[8], x);
649: }
650: return gscalcol(x,N);
651: }
652:
653: GEN
654: algtobasis(GEN nf, GEN x)
655: {
656: long tx=typ(x),lx=lg(x),av=avma,i,N;
657: GEN z;
658:
659: nf=checknf(nf);
660: switch(tx)
661: {
662: case t_VEC: case t_COL: case t_MAT:
663: z=cgetg(lx,tx);
664: for (i=1; i<lx; i++) z[i]=(long)algtobasis(nf,(GEN)x[i]);
665: return z;
666: case t_POLMOD:
667: if (!polegal_spec((GEN)nf[1],(GEN)x[1]))
668: err(talker,"not the same number field in algtobasis");
669: x = (GEN)x[2]; /* fall through */
670: case t_POL:
671: return gerepileupto(av,algtobasis_intern(nf,x));
672:
673: default: N=degpol(nf[1]); return gscalcol(x,N);
674: }
675: }
676:
677: /* Given a and b in nf, gives an algebraic integer y in nf such that a-b.y
678: * is "small"
679: */
680: GEN
681: nfdiveuc(GEN nf, GEN a, GEN b)
682: {
683: long av=avma, tetpil;
684: a = element_div(nf,a,b); tetpil=avma;
685: return gerepile(av,tetpil,ground(a));
686: }
687:
688: /* Given a and b in nf, gives a "small" algebraic integer r in nf
689: * of the form a-b.y
690: */
691: GEN
692: nfmod(GEN nf, GEN a, GEN b)
693: {
694: long av=avma,tetpil;
695: GEN p1=gneg_i(element_mul(nf,b,ground(element_div(nf,a,b))));
696: tetpil=avma; return gerepile(av,tetpil,gadd(a,p1));
697: }
698:
699: /* Given a and b in nf, gives a two-component vector [y,r] in nf such
700: * that r=a-b.y is "small".
701: */
702: GEN
703: nfdivres(GEN nf, GEN a, GEN b)
704: {
705: long av=avma,tetpil;
706: GEN p1,z, y = ground(element_div(nf,a,b));
707:
708: p1=gneg_i(element_mul(nf,b,y)); tetpil=avma;
709: z=cgetg(3,t_VEC); z[1]=lcopy(y); z[2]=ladd(a,p1);
710: return gerepile(av,tetpil,z);
711: }
712:
713: /*************************************************************************/
714: /** **/
715: /** (Z_K/I)^* **/
716: /** **/
717: /*************************************************************************/
718:
719: /* return (column) vector of R1 signatures of x (coeff modulo 2)
720: * if arch = NULL, assume arch = [0,..0]
721: */
722: GEN
723: zsigne(GEN nf,GEN x,GEN arch)
724: {
725: GEN _0,_1, vecsign, rac = (GEN)nf[6];
726: long i,j,l,e,B;
727: ulong av0, av;
728:
729: if (!arch) return cgetg(1,t_COL);
730: av0 = avma;
731: l = lg(arch); vecsign = cgetg(l,t_COL);
732: _0 = gmodulss(0,2);
733: _1 = gmodulss(1,2); av = avma;
734: switch(typ(x))
735: {
736: case t_MAT: /* factorisation */
737: {
738: GEN t = (GEN)x[1], e = (GEN)x[2];
739: for (j=i=1; i<l; i++)
740: if (signe(arch[i])) vecsign[j++] = (long)_0;
741: setlg(vecsign,j);
742: if (j==1) { avma = av0; return cgetg(1, t_COL); }
743: for (i=1; i<lg(t); i++)
744: {
745: GEN p1 = (GEN)e[i];
746: if (mpodd(p1))
747: vecsign = gadd(vecsign, zsigne(nf,(GEN)t[i],arch));
748: }
749: return gerepileupto(av0, vecsign);
750: }
751: case t_COL: x = gmul((GEN)nf[7],x); break;
752: case t_POLMOD: x = (GEN)x[2];
753: }
754: if (gcmp0(x)) err(talker,"zero element in zsigne");
755:
756: B = bit_accuracy(precision((GEN)rac[1]));
757: e = gexpo(x);
758: for (j=i=1; i<l; i++)
759: if (signe(arch[i]))
760: {
761: GEN y = poleval(x,(GEN)rac[i]);
762: if (e + gexpo((GEN)rac[i]) - gexpo(y) > B)
763: err(precer, "zsigne");
764: vecsign[j++] = (gsigne(y) > 0)? (long)_0: (long)_1;
765: }
766: avma = av; setlg(vecsign,j); return vecsign;
767: }
768:
769: GEN
770: lllreducemodmatrix(GEN x,GEN y)
771: {
772: ulong av = avma;
773: GEN z = gmul(y,lllint(y));
774: return gerepileupto(av, reducemodinvertible(x, z));
775: }
776:
777: /* for internal use...reduce x modulo (invertible) y */
778: GEN
779: reducemodinvertible(GEN x, GEN y)
780: {
781: return gadd(x, gneg(gmul(y, ground(gauss(y,x)))));
782: }
783:
784: /* Reduce column x modulo y in HNF */
785: GEN
786: colreducemodmat(GEN x, GEN y, GEN *Q)
787: {
788: long i, l = lg(x);
789: GEN q;
790:
791: if (Q) *Q = cgetg(l,t_COL);
792: if (l == 1) return cgetg(1,t_COL);
793: for (i = l-1; i>0; i--)
794: {
795: q = negi(gdivround((GEN)x[i], gcoeff(y,i,i)));
796: if (Q) (*Q)[i] = (long)q;
797: if (signe(q)) x = gadd(x, gmul(q, (GEN)y[i]));
798: }
799: return x;
800: }
801:
802: /* for internal use...Reduce matrix x modulo matrix y */
803: GEN
804: reducemodmatrix(GEN x, GEN y)
805: {
806: return reducemodHNF(x, hnfmod(y,detint(y)), NULL);
807: }
808:
809: /* x = y Q + R */
810: GEN
811: reducemodHNF(GEN x, GEN y, GEN *Q)
812: {
813: long lx = lg(x), i;
814: GEN R = cgetg(lx, t_MAT);
815: if (Q)
816: {
817: GEN q = cgetg(lx, t_MAT); *Q = q;
818: for (i=1; i<lx; i++) R[i] = (long)colreducemodmat((GEN)x[i],y,(GEN*)(q+i));
819: }
820: else
821: for (i=1; i<lx; i++)
822: {
823: long av = avma;
824: R[i] = lpileupto(av, colreducemodmat((GEN)x[i],y,NULL));
825: }
826: return R;
827: }
828:
829: /* For internal use. Reduce x modulo ideal. We want a non-zero result */
830: GEN
831: nfreducemodideal(GEN nf,GEN x0,GEN ideal)
832: {
833: GEN y = idealhermite(nf,ideal);
834: GEN x = colreducemodmat(x0, y, NULL);
835: if (gcmp0(x)) return (GEN)y[1];
836: return x == x0? gcopy(x) : x;
837: }
838:
839: /* multiply y by t = 1 mod^* f such that sign(x) = sign(y) at arch = idele[2].
840: * If x == NULL, make y >> 0 at sarch */
841: GEN
842: set_sign_mod_idele(GEN nf, GEN x, GEN y, GEN idele, GEN sarch)
843: {
844: GEN s,arch,gen;
845: long nba,i;
846: if (!sarch) return y;
847: gen = (GEN)sarch[2]; nba = lg(gen);
848: if (nba == 1) return y;
849:
850: arch = (GEN)idele[2];
851: s = zsigne(nf,y,arch);
852: if (x) s = gadd(s, zsigne(nf,x,arch));
853: s = lift_intern(gmul((GEN)sarch[3],s));
854: for (i=1; i<nba; i++)
855: if (signe(s[i])) y = element_mul(nf,y,(GEN)gen[i]);
856: return y;
857: }
858:
859: /* compute elt = x mod idele, with sign(elt) = sign(x) at arch */
860: GEN
861: nfreducemodidele(GEN nf,GEN x,GEN idele,GEN sarch)
862: {
863: GEN y;
864:
865: if (gcmp0(x)) return gcopy(x);
866: if (!sarch || typ(idele)!=t_VEC || lg(idele)!=3)
867: return nfreducemodideal(nf,x,idele);
868:
869: y = nfreducemodideal(nf,x,(GEN)idele[1]);
870: y = set_sign_mod_idele(nf, x, y, idele, sarch);
871: return (gexpo(y) > gexpo(x))? x: y;
872: }
873:
874: GEN
875: element_powmodideal(GEN nf,GEN x,GEN k,GEN ideal)
876: {
877: GEN y = gscalcol_i(gun,degpol(nf[1]));
878: for(;;)
879: {
880: if (mpodd(k)) y=element_mulmodideal(nf,x,y,ideal);
881: k=shifti(k,-1); if (!signe(k)) return y;
882: x = element_sqrmodideal(nf,x,ideal);
883: }
884: }
885:
886: GEN
887: element_powmodidele(GEN nf,GEN x,GEN k,GEN idele,GEN sarch)
888: {
889: GEN y = element_powmodideal(nf,x,k,idele);
890: if (mpodd(k))
891: { if (!gcmp1(k)) y = set_sign_mod_idele(nf, x, y, idele, sarch); }
892: else
893: { if (!gcmp0(k)) y = set_sign_mod_idele(nf, NULL, y, idele, sarch); }
894: return y;
895: }
896:
897: /* H relation matrix among row of generators g. Let URV = D its SNF, newU R
898: * newV = newD its clean SNF (no 1 in Dnew). Return the diagonal of newD,
899: * newU and newUi such that 1/U = (newUi, ?).
900: * Rationale: let (G,0) = g Ui be the new generators then
901: * 0 = G U R --> G D = 0, g = G newU and G = g newUi */
902: GEN
903: smithrel(GEN H, GEN *newU, GEN *newUi)
904: {
905: GEN z,U,Ui,D,p1;
906: long l,c;
907:
908: z = smith2(H);
909: U = (GEN)z[1];
910: D = (GEN)z[3]; l = lg(D);
911: for (c=1; c<l; c++)
912: {
913: p1 = gcoeff(D,c,c);
914: if (is_pm1(p1)) break;
915: }
916: if (newU) *newU = rowextract_i(U, 1, c-1);
917: if (newUi) {
918: Ui = ginv(U); setlg(Ui, c);
919: *newUi = reducemodHNF(Ui, H, NULL);
920: }
921: setlg(D, c); return mattodiagonal_i(D);
922: }
923:
924: /* given 2 integral ideals x, y in HNF s.t x | y | x^2, compute the quotient
925: (1+x)/(1+y) in the form [[cyc],[gen],ux^-1]. */
926: static GEN
927: zidealij(GEN x, GEN y)
928: {
929: GEN U,R,G,p1,cyc,z,xi;
930: long j,N;
931:
932: xi = ginv(x); R = gmul(xi, y); /* relations between the 1 + x_i (HNF) */
933: cyc = smithrel(R, &U, &G);
934: N = lg(cyc); G = gmul(x,G); settyp(G, t_VEC); /* new generators */
935: for (j=1; j<N; j++)
936: {
937: p1 = (GEN)G[j];
938: p1[1] = laddsi(1, (GEN)p1[1]); /* 1 + g_j */
939: }
940: z = cgetg(4,t_VEC);
941: z[1] = (long)cyc;
942: z[2] = (long)G;
943: z[3] = lmul(U,xi); return z;
944: }
945:
946: static GEN
947: get_multab(GEN nf, GEN x)
948: {
949: long lx = lg(x), i;
950: GEN multab = cgetg(lx, t_MAT);
951: for (i=1; i<lx; i++)
952: multab[i]=(long)element_mulid(nf,x,i);
953: return multab;
954: }
955:
956: /* return mat * y mod prh */
957: static GEN
958: mul_matvec_mod_pr(GEN mat, GEN y, GEN prh)
959: {
960: long av,i,j, lx = lg(mat);
961: GEN v, res = cgetg(lx,t_COL), p = gcoeff(prh,1,1);
962:
963: av = avma; (void)new_chunk((lx-1) * lgefint(p));
964: v = zerocol(lx-1);
965: for (i=lx-1; i; i--)
966: {
967: GEN p1 = (GEN)v[i], t = (GEN)prh[i];
968: for (j=1; j<lx; j++)
969: p1 = addii(p1, mulii(gcoeff(mat,i,j), (GEN)y[j]));
970: p1 = modii(p1, p);
971: if (p1 != gzero && is_pm1(t[i]))
972: {
973: for (j=1; j<i; j++)
974: v[j] = lsubii((GEN)v[j], mulii(p1, (GEN)t[j]));
975: p1 = gzero;
976: }
977: if (p1 == gzero) /* intended */
978: res[i] = zero;
979: else
980: av = res[i] = (long)icopy_av(p1, (GEN)av);
981: }
982: avma = av; return res;
983: }
984:
985: /* smallest integer n such that g0^n=x modulo p prime. Assume g0 has order q
986: * (p-1 if q = NULL) */
987: GEN
988: Fp_shanks(GEN x,GEN g0,GEN p, GEN q)
989: {
990: long av=avma,av1,lim,lbaby,i,k,c;
991: GEN p1,smalltable,giant,perm,v,g0inv;
992:
993: x = modii(x,p);
994: if (is_pm1(x) || egalii(p,gdeux)) { avma = av; return gzero; }
995: p1 = addsi(-1, p); if (!q) q = p1;
996: if (egalii(p1,x)) { avma = av; return shifti(q,-1); }
997: p1 = racine(q);
998: if (cmpis(p1,LGBITS) >= 0) err(talker,"module too large in Fp_shanks");
999: lbaby=itos(p1)+1; smalltable=cgetg(lbaby+1,t_VEC);
1000: g0inv = mpinvmod(g0, p); p1 = x;
1001:
1002: c = 3 * lgefint(p);
1003: for (i=1;;i++)
1004: {
1005: av1 = avma;
1006: if (is_pm1(p1)) { avma=av; return stoi(i-1); }
1007: smalltable[i]=(long)p1; if (i==lbaby) break;
1008: new_chunk(c); p1 = mulii(p1,g0inv);
1009: avma = av1; p1 = resii(p1, p);
1010: }
1011: giant = resii(mulii(x, mpinvmod(p1,p)), p);
1012: p1=cgetg(lbaby+1,t_VEC);
1013: perm = gen_sort(smalltable, cmp_IND | cmp_C, cmpii);
1014: for (i=1; i<=lbaby; i++) p1[i]=smalltable[perm[i]];
1015: smalltable=p1; p1=giant;
1016:
1017: av1 = avma; lim=stack_lim(av1,2);
1018: for (k=1;;k++)
1019: {
1020: i=tablesearch(smalltable,p1,cmpii);
1021: if (i)
1022: {
1023: v=addis(mulss(lbaby-1,k),perm[i]);
1024: return gerepileuptoint(av,addsi(-1,v));
1025: }
1026: p1 = resii(mulii(p1,giant), p);
1027:
1028: if (low_stack(lim, stack_lim(av1,2)))
1029: {
1030: if(DEBUGMEM>1) err(warnmem,"Fp_shanks, k = %ld", k);
1031: p1 = gerepileuptoint(av1, p1);
1032: }
1033: }
1034: }
1035:
1036: /* Pohlig-Hellman */
1037: GEN
1038: Fp_PHlog(GEN a, GEN g, GEN p, GEN ord)
1039: {
1040: ulong av = avma;
1041: GEN v,t0,a0,b,q,g_q,n_q,ginv0,qj,ginv;
1042: GEN fa, ex;
1043: long e,i,j,l;
1044:
1045: if (!ord) ord = subis(p,1);
1046: if (typ(ord) == t_MAT)
1047: {
1048: fa = ord;
1049: ord= factorback(fa,NULL);
1050: }
1051: else
1052: fa = decomp(ord);
1053: if (typ(g) == t_INTMOD) g = lift_intern(g);
1054: ex = (GEN)fa[2];
1055: fa = (GEN)fa[1];
1056: l = lg(fa);
1057: ginv = mpinvmod(g,p);
1058: v = cgetg(l, t_VEC);
1059: for (i=1; i<l; i++)
1060: {
1061: q = (GEN)fa[i];
1062: e = itos((GEN)ex[i]);
1063: if (DEBUGLEVEL>5)
1064: fprintferr("Pohlig-Hellman: DL mod %Z^%ld\n",q,e);
1065: qj = new_chunk(e+1); qj[0] = un;
1066: for (j=1; j<=e; j++) qj[j] = lmulii((GEN)qj[j-1], q);
1067: t0 = divii(ord, (GEN)qj[e]);
1068: a0 = powmodulo(a, t0, p);
1069: ginv0 = powmodulo(ginv, t0, p); /* order q^e */
1070: g_q = powmodulo(g, divii(ord,q), p); /* order q */
1071: n_q = gzero;
1072: for (j=0; j<e; j++)
1073: {
1074: b = modii(mulii(a0, powmodulo(ginv0, n_q, p)), p);
1075: b = powmodulo(b, (GEN)qj[e-1-j], p);
1076: b = Fp_shanks(b, g_q, p, q);
1077: n_q = addii(n_q, mulii(b, (GEN)qj[j]));
1078: }
1079: v[i] = lmodulcp(n_q, (GEN)qj[e]);
1080: }
1081: return gerepileuptoint(av, lift(chinese(v,NULL)));
1082: }
1083:
1084: /* smallest n >= 0 such that g0^n=x modulo pr, assume g0 reduced
1085: * q = order of g0 (Npr - 1 if q = NULL)
1086: * TODO: should be done in F_(p^f), not in Z_k mod pr (done for f=1) */
1087: static GEN
1088: nfshanks(GEN nf,GEN x,GEN g0,GEN pr,GEN prhall,GEN q)
1089: {
1090: long av=avma,av1,lim,lbaby,i,k, f = itos((GEN)pr[4]);
1091: GEN p1,smalltable,giant,perm,v,g0inv,prh = (GEN)prhall[1];
1092: GEN multab, p = (GEN)pr[1];
1093:
1094: x = lift_intern(nfreducemodpr(nf,x,prhall));
1095: p1 = q? q: addsi(-1, gpowgs(p,f));
1096: p1 = racine(p1);
1097: if (cmpis(p1,LGBITS) >= 0) err(talker,"module too large in nfshanks");
1098: lbaby=itos(p1)+1; smalltable=cgetg(lbaby+1,t_VEC);
1099: g0inv = lift_intern(element_invmodpr(nf,g0,prhall));
1100: p1 = x;
1101:
1102: multab = get_multab(nf, g0inv);
1103: for (i=lg(multab)-1; i; i--)
1104: multab[i]=(long)FpV_red((GEN)multab[i], p);
1105:
1106: for (i=1;;i++)
1107: {
1108: if (isnfscalar(p1) && gcmp1((GEN)p1[1])) { avma=av; return stoi(i-1); }
1109:
1110: smalltable[i]=(long)p1; if (i==lbaby) break;
1111: p1 = mul_matvec_mod_pr(multab,p1,prh);
1112: }
1113: giant=lift_intern(element_divmodpr(nf,x,p1,prhall));
1114: p1=cgetg(lbaby+1,t_VEC);
1115: perm = gen_sort(smalltable, cmp_IND | cmp_C, cmp_vecint);
1116: for (i=1; i<=lbaby; i++) p1[i]=smalltable[perm[i]];
1117: smalltable=p1; p1=giant;
1118:
1119: multab = get_multab(nf, giant);
1120: for (i=lg(multab)-1; i; i--)
1121: multab[i]=(long)FpV_red((GEN)multab[i], p);
1122:
1123: av1 = avma; lim=stack_lim(av1,2);
1124: for (k=1;;k++)
1125: {
1126: i=tablesearch(smalltable,p1,cmp_vecint);
1127: if (i)
1128: {
1129: v=addis(mulss(lbaby-1,k),perm[i]);
1130: return gerepileuptoint(av,addsi(-1,v));
1131: }
1132: p1 = mul_matvec_mod_pr(multab,p1,prh);
1133:
1134: if (low_stack(lim, stack_lim(av1,2)))
1135: {
1136: if(DEBUGMEM>1) err(warnmem,"nfshanks");
1137: p1 = gerepileupto(av1, p1);
1138: }
1139: }
1140: }
1141:
1142: /* same in nf.zk / pr
1143: * TODO: should be done in F_(p^f), not in Z_k mod pr (done for f=1) */
1144: GEN
1145: nf_PHlog(GEN nf, GEN a, GEN g, GEN pr, GEN prhall)
1146: {
1147: ulong av = avma;
1148: GEN v,t0,a0,b,q,g_q,n_q,ginv0,qj,ginv,ord,fa,ex;
1149: long e,i,j,l;
1150:
1151: a = lift_intern(nfreducemodpr(nf,a,prhall));
1152: if (isnfscalar(a))
1153: { /* can be done in Fp^* */
1154: GEN p = (GEN)pr[1], ordp = subis(p, 1);
1155: a = (GEN)a[1];
1156: if (gcmp1(a) || egalii(p, gdeux)) { avma = av; return gzero; }
1157: ord = subis(idealnorm(nf,pr), 1);
1158: if (egalii(a, ordp)) /* -1 */
1159: return gerepileuptoint(av, shifti(ord,-1));
1160:
1161: if (egalii(ord, ordp))
1162: q = NULL;
1163: else /* we want < g > = Fp^* */
1164: {
1165: q = divii(ord,ordp);
1166: g = element_powmodpr(nf,g,q,prhall);
1167: }
1168: g = lift_intern((GEN)g[1]);
1169: n_q = Fp_PHlog(a,g,p,NULL);
1170: if (q) n_q = mulii(q, n_q);
1171: return gerepileuptoint(av, n_q);
1172: }
1173: ord = subis(idealnorm(nf,pr),1);
1174: fa = factor(ord); ex = (GEN)fa[2];
1175: fa = (GEN)fa[1];
1176: l = lg(fa);
1177: ginv = lift_intern(element_invmodpr(nf, g, prhall));
1178: v = cgetg(l, t_VEC);
1179: for (i=1; i<l; i++)
1180: {
1181: q = (GEN)fa[i];
1182: e = itos((GEN)ex[i]);
1183: if (DEBUGLEVEL>5)
1184: fprintferr("nf_Pohlig-Hellman: DL mod %Z^%ld\n",q,e);
1185: qj = new_chunk(e+1); qj[0] = un;
1186: for (j=1; j<=e; j++) qj[j] = lmulii((GEN)qj[j-1], q);
1187: t0 = divii(ord, (GEN)qj[e]);
1188: a0 = element_powmodpr(nf, a, t0, prhall);
1189: ginv0 = element_powmodpr(nf, ginv, t0, prhall); /* order q^e */
1190: g_q = element_powmodpr(nf, g, divii(ord,q), prhall); /* order q */
1191: n_q = gzero;
1192: for (j=0; j<e; j++)
1193: {
1194: b = element_mulmodpr(nf,a0,
1195: element_powmodpr(nf, ginv0, n_q, prhall), prhall);
1196: b = element_powmodpr(nf, b, (GEN)qj[e-1-j], prhall);
1197: b = nfshanks(nf,b, g_q, pr,prhall, q);
1198: n_q = addii(n_q, mulii(b, (GEN)qj[j]));
1199: }
1200: v[i] = lmodulcp(n_q, (GEN)qj[e]);
1201: }
1202: return gerepileuptoint(av, lift(chinese(v,NULL)));
1203: }
1204:
1205: GEN
1206: znlog(GEN x, GEN g0)
1207: {
1208: long av=avma;
1209: GEN p = (GEN)g0[1];
1210: if (typ(g0) != t_INTMOD)
1211: err(talker,"not an element of (Z/pZ)* in znlog");
1212: switch(typ(x))
1213: {
1214: case t_INT: break;
1215: default: x = gmul(x, gmodulsg(1,p));
1216: if (typ(x) != t_INTMOD)
1217: err(talker,"not an element of (Z/pZ)* in znlog");
1218: case t_INTMOD: x = (GEN)x[2]; break;
1219: }
1220: return gerepileuptoint(av, Fp_PHlog(x,(GEN)g0[2],p,NULL));
1221: }
1222:
1223: GEN
1224: dethnf(GEN mat)
1225: {
1226: long i,l = lg(mat);
1227: ulong av;
1228: GEN s;
1229:
1230: if (l<3) return l<2? gun: icopy(gcoeff(mat,1,1));
1231: av = avma; s = gcoeff(mat,1,1);
1232: for (i=2; i<l; i++) s = gmul(s,gcoeff(mat,i,i));
1233: return av==avma? gcopy(s): gerepileupto(av,s);
1234: }
1235:
1236: GEN
1237: dethnf_i(GEN mat)
1238: {
1239: long av,i,l = lg(mat);
1240: GEN s;
1241:
1242: if (l<3) return l<2? gun: icopy(gcoeff(mat,1,1));
1243: av = avma; s = gcoeff(mat,1,1);
1244: for (i=2; i<l; i++) s = mulii(s,gcoeff(mat,i,i));
1245: return gerepileuptoint(av,s);
1246: }
1247:
1248: /* as above with cyc = diagonal(mat) */
1249: GEN
1250: detcyc(GEN cyc)
1251: {
1252: long av,i,l = lg(cyc);
1253: GEN s;
1254:
1255: if (l<3) return l<2? gun: icopy((GEN)cyc[1]);
1256: av = avma; s = (GEN)cyc[1];
1257: for (i=2; i<l; i++) s = mulii(s,(GEN)cyc[i]);
1258: return gerepileuptoint(av,s);
1259: }
1260:
1261: /* (U,V) = 1. Return y = x mod U, = 1 mod V (uv: u + v = 1, u in U, v in V) */
1262: static GEN
1263: makeprimetoideal(GEN nf,GEN UV,GEN uv,GEN x)
1264: {
1265: GEN y = gadd((GEN)uv[1], element_mul(nf,x,(GEN)uv[2]));
1266: return nfreducemodideal(nf,y,UV);
1267: }
1268:
1269: static GEN
1270: makeprimetoidealvec(GEN nf,GEN UV,GEN uv,GEN gen)
1271: {
1272: long i, lx = lg(gen);
1273: GEN y = cgetg(lx,t_VEC);
1274: for (i=1; i<lx; i++)
1275: y[i] = (long)makeprimetoideal(nf,UV,uv,(GEN)gen[i]);
1276: return y;
1277: }
1278:
1279: /* Given an ideal pr^ep, and an integral ideal x (in HNF form) compute a list
1280: * of vectors, each with 5 components as follows :
1281: * [[clh],[gen1],[gen2],[signat2],U.X^-1]. Each component corresponds to
1282: * d_i,g_i,g'_i,s_i. Generators g_i are not necessarily prime to x, the
1283: * generators g'_i are. signat2 is the (horizontal) vector made of the
1284: * signatures (column vectors) of the g'_i. If x = NULL, the original ideal
1285: * was a prime power
1286: */
1287: static GEN
1288: zprimestar(GEN nf,GEN pr,GEN ep,GEN x,GEN arch)
1289: {
1290: long av=avma,av1,N,f,nbp,j,n,m,tetpil,i,e,a,b;
1291: GEN prh,p,pf_1,list,v,p1,p3,p4,prk,uv,g0,newgen,pra,prb;
1292: GEN *gptr[2];
1293:
1294: if(DEBUGLEVEL>3) { fprintferr("treating pr = %Z ^ %Z\n",pr,ep); flusherr(); }
1295: prh=prime_to_ideal(nf,pr); N=lg(prh)-1;
1296: f=itos((GEN)pr[4]); p=(GEN)pr[1];
1297:
1298: pf_1 = addis(gpowgs(p,f), -1);
1299: v = zerocol(N);
1300: if (f==1) v[1]=gener(p)[2];
1301: else
1302: {
1303: GEN prhall = cgetg(3,t_VEC);
1304: long psim;
1305: if (is_bigint(p)) err(talker,"prime too big in zprimestar");
1306: psim = itos(p);
1307: list = (GEN)factor(pf_1)[1]; nbp=lg(list)-1;
1308: prhall[1]=(long)prh; prhall[2]=zero;
1309: for (n=psim; n>=0; n++)
1310: {
1311: m=n;
1312: for (i=1; i<=N; i++)
1313: if (!gcmp1(gcoeff(prh,i,i))) { v[i]=lstoi(m%psim); m/=psim; }
1314: for (j=1; j<=nbp; j++)
1315: {
1316: p1 = divii(pf_1,(GEN)list[j]);
1317: p1 = lift_intern(element_powmodpr(nf,v,p1,prhall));
1318: if (isnfscalar(p1) && gcmp1((GEN)p1[1])) break;
1319: }
1320: if (j>nbp) break;
1321: }
1322: if (n < 0) err(talker,"prime too big in zprimestar");
1323: }
1324: /* v generates (Z_K / pr)^* */
1325: if(DEBUGLEVEL>3) {fprintferr("v computed\n");flusherr();}
1326: e = itos(ep); prk=(e==1)? pr: idealpow(nf,pr,ep);
1327: if(DEBUGLEVEL>3) {fprintferr("prk computed\n");flusherr();}
1328: g0 = v;
1329: uv = NULL; /* gcc -Wall */
1330: if (x)
1331: {
1332: uv = idealaddtoone(nf,prk, idealdivexact(nf,x,prk));
1333: g0 = makeprimetoideal(nf,x,uv,v);
1334: if(DEBUGLEVEL>3) {fprintferr("g0 computed\n");flusherr();}
1335: }
1336:
1337: p1 = cgetg(6,t_VEC); list = _vec(p1);
1338: p1[1] = (long)_vec(pf_1);
1339: p1[2] = (long)_vec(v);
1340: p1[3] = (long)_vec(g0);
1341: p1[4] = (long)_vec(zsigne(nf,g0,arch));
1342: p1[5] = un;
1343: if (e==1) return gerepilecopy(av, list);
1344:
1345: a=1; b=2; av1=avma;
1346: pra = prh; prb = (e==2)? prk: idealpow(nf,pr,gdeux);
1347: for(;;)
1348: {
1349: if(DEBUGLEVEL>3)
1350: {fprintferr(" treating a = %ld, b = %ld\n",a,b); flusherr();}
1351: p1 = zidealij(pra,prb);
1352: newgen = dummycopy((GEN)p1[2]);
1353: p3 = cgetg(lg(newgen),t_VEC);
1354: if(DEBUGLEVEL>3) {fprintferr("zidealij done\n"); flusherr();}
1355: for (i=1; i<lg(newgen); i++)
1356: {
1357: if (x) newgen[i]=(long)makeprimetoideal(nf,x,uv,(GEN)newgen[i]);
1358: p3[i]=(long)zsigne(nf,(GEN)newgen[i],arch);
1359: }
1360: p4 = cgetg(6,t_VEC);
1361: p4[1] = p1[1];
1362: p4[2] = p1[2];
1363: p4[3] = (long)newgen;
1364: p4[4] = (long)p3;
1365: p4[5] = p1[3]; p4 = _vec(p4);
1366:
1367: a=b; b=min(e,b<<1); tetpil = avma;
1368: list = concat(list, p4);
1369: if (a==b) return gerepile(av,tetpil,list);
1370:
1371: pra = gcopy(prb);
1372: gptr[0]=&pra; gptr[1]=&list;
1373: gerepilemanysp(av1,tetpil,gptr,2);
1374: prb = (b==(a<<1))? idealpow(nf,pra,gdeux): prk;
1375: }
1376: }
1377:
1378: /* x ideal, compute elements in 1+x whose sign matrix is invertible */
1379: GEN
1380: zarchstar(GEN nf,GEN x,GEN arch,long nba)
1381: {
1382: long av,N,i,j,k,r,rr,limr,zk,lgmat;
1383: GEN p1,y,bas,genarch,mat,lambda,nfun,vun;
1384:
1385: y = cgetg(4,t_VEC);
1386: if (!nba)
1387: {
1388: y[1]=lgetg(1,t_VEC);
1389: y[2]=lgetg(1,t_VEC);
1390: y[3]=lgetg(1,t_MAT); return y;
1391: }
1392: N = degpol(nf[1]);
1393: p1 = cgetg(nba+1,t_VEC); for (i=1; i<=nba; i++) p1[i] = deux;
1394: y[1] = (long)p1; av = avma;
1395: if (N == 1)
1396: {
1397: p1 = gerepileuptoint(av, subsi(1, shifti(gcoeff(x,1,1),1)));
1398: y[2] = (long)_vec(_col(p1));
1399: y[3] = (long)gscalmat(gun,1); return y;
1400: }
1401: zk = ideal_is_zk(x,N);
1402: genarch = cgetg(nba+1,t_VEC);
1403: mat = cgetg(nba+1,t_MAT); setlg(mat,2);
1404: for (i=1; i<=nba; i++) mat[i] = lgetg(nba+1, t_MAT);
1405: lambda = cgetg(N+1, t_VECSMALL);
1406:
1407: bas = dummycopy(gmael(nf,5,1)); r = lg(arch);
1408: for (k=1,i=1; i<r; i++)
1409: if (signe(arch[i]))
1410: {
1411: if (k < i)
1412: for (j=1; j<=N; j++) coeff(bas,k,j) = coeff(bas,i,j);
1413: k++;
1414: }
1415: r = nba+1; for (i=1; i<=N; i++) setlg(bas[i], r);
1416: if (!zk)
1417: {
1418: x = gmul(x,lllintpartial(x));
1419: bas = gmul(bas, x);
1420: }
1421:
1422: vun = cgetg(nba+1, t_COL);
1423: for (i=1; i<=nba; i++) vun[i] = un;
1424: nfun = gscalcol(gun, N); lgmat = 1;
1425: for (r=1, rr=3; ; r<<=1, rr=(r<<1)+1)
1426: {
1427: if (DEBUGLEVEL>5) fprintferr("zarchstar: r = %ld\n",r);
1428: p1 = gpowgs(stoi(rr),N);
1429: limr = is_bigint(p1)? BIGINT: p1[2];
1430: limr = (limr-1)>>1;
1431: k = zk? rr: 1; /* to avoid 0 */
1432: for ( ; k<=limr; k++)
1433: {
1434: long av1=avma, kk = k;
1435: GEN alpha = vun;
1436: for (i=1; i<=N; i++)
1437: {
1438: lambda[i] = (kk+r)%rr - r; kk/=rr;
1439: if (lambda[i])
1440: alpha = gadd(alpha, gmulsg(lambda[i],(GEN)bas[i]));
1441: }
1442: p1 = (GEN)mat[lgmat];
1443: for (i=1; i<=nba; i++)
1444: p1[i] = (gsigne((GEN)alpha[i]) > 0)? zero: un;
1445:
1446: if (ker_trivial_mod_p(mat, gdeux)) avma = av1;
1447: else
1448: { /* new vector indep. of previous ones */
1449: avma = av1; alpha = nfun;
1450: for (i=1; i<=N; i++)
1451: if (lambda[i])
1452: alpha = gadd(alpha, gmulsg(lambda[i],(GEN)x[i]));
1453: genarch[lgmat++] = (long)alpha;
1454: if (lgmat > nba)
1455: {
1456: GEN *gptr[2];
1457: mat = ginv(mat); gptr[0]=&genarch; gptr[1]=&mat;
1458: gerepilemany(av,gptr,2);
1459: y[2]=(long)genarch;
1460: y[3]=(long)mat; return y;
1461: }
1462: setlg(mat,lgmat+1);
1463: }
1464: }
1465: }
1466: }
1467:
1468: GEN
1469: zinternallog_pk(GEN nf, GEN a0, GEN y, GEN pr, GEN prk, GEN list, GEN *psigne)
1470: {
1471: GEN a = a0, L,e,p1,cyc,gen;
1472: long i,j, llist = lg(list)-1;
1473:
1474: e = gzero; /* gcc -Wall */
1475: for (j=1; j<=llist; j++)
1476: {
1477: L = (GEN)list[j]; cyc=(GEN)L[1]; gen=(GEN)L[2];
1478: if (j==1)
1479: p1 = nf_PHlog(nf,a,(GEN)gen[1],pr, nfmodprinit(nf,pr));
1480: else
1481: {
1482: p1 = (GEN)a[1]; a[1] = laddsi(-1,(GEN)a[1]);
1483: e = gmul((GEN)L[5],a); a[1] = (long)p1;
1484: /* here lg(e) == lg(cyc) */
1485: p1 = (GEN)e[1];
1486: }
1487: for (i=1; i<lg(cyc); i++, p1 = (GEN)e[i])
1488: {
1489: p1 = modii(negi(p1), (GEN)cyc[i]);
1490: *++y = lnegi(p1);
1491: if (!signe(p1)) continue;
1492:
1493: if (psigne && mpodd(p1)) *psigne = gadd(*psigne,gmael(L,4,i));
1494: if (j == llist) continue;
1495:
1496: if (DEBUGLEVEL>5) fprintferr("do element_powmodideal\n");
1497: p1 = element_powmodideal(nf,(GEN)gen[i],p1,prk);
1498: a = element_mulmodideal(nf,a,p1,prk);
1499: }
1500: }
1501: return y;
1502: }
1503:
1504: /* Retourne la decomposition de a sur les nbgen generateurs successifs
1505: * contenus dans list_set et si index !=0 on ne fait ce calcul que pour
1506: * l'ideal premier correspondant a cet index en mettant a 0 les autres
1507: * composantes
1508: */
1509: static GEN
1510: zinternallog(GEN nf,GEN a,GEN list_set,long nbgen,GEN arch,GEN fa,long index)
1511: {
1512: GEN prlist,ep,y0,y,ainit,list,pr,prk,cyc,psigne,p1,p2;
1513: long av,nbp,i,j,k;
1514:
1515: y0 = y = cgetg(nbgen+1,t_COL); av=avma;
1516: prlist=(GEN)fa[1]; ep=(GEN)fa[2]; nbp=lg(ep)-1;
1517: i=typ(a); if (is_extscalar_t(i)) a = algtobasis(nf,a);
1518: if (DEBUGLEVEL>3)
1519: {
1520: fprintferr("entering zinternallog, "); flusherr();
1521: if (DEBUGLEVEL>5) fprintferr("with a = %Z\n",a);
1522: }
1523: ainit = a; psigne = zsigne(nf,ainit,arch);
1524: p2 = NULL; /* gcc -Wall */
1525: for (k=1; k<=nbp; k++)
1526: {
1527: list = (GEN)list_set[k];
1528: if (index && index!=k)
1529: {
1530: for (j=1; j<lg(list); j++)
1531: {
1532: cyc = gmael(list,j,1);
1533: for (i=1; i<lg(cyc); i++) *++y = zero;
1534: }
1535: continue;
1536: }
1537: pr = (GEN)prlist[k]; prk = idealpow(nf,pr,(GEN)ep[k]);
1538: y = zinternallog_pk(nf, ainit, y, pr, prk, list, &psigne);
1539: }
1540: p1 = lift_intern(gmul(gmael(list_set,k,3), psigne));
1541: avma=av; for (i=1; i<lg(p1); i++) *++y = p1[i];
1542: if (DEBUGLEVEL>3) { fprintferr("leaving\n"); flusherr(); }
1543: for (i=1; i<=nbgen; i++) y0[i] = licopy((GEN)y0[i]);
1544: return y0;
1545: }
1546:
1547: static GEN
1548: compute_gen(GEN nf, GEN u1, GEN gen, GEN bid)
1549: {
1550: long i, c = lg(u1);
1551: GEN basecl = cgetg(c,t_VEC);
1552:
1553: for (i=1; i<c; i++)
1554: basecl[i] = (long)famat_to_nf_modidele(nf, gen, (GEN)u1[i], bid);
1555: return basecl;
1556: }
1557:
1558: /* Compute [[ideal,arch], [h,[cyc],[gen]], idealfact, [liste], U]
1559: gen not computed unless add_gen != 0 */
1560: GEN
1561: zidealstarinitall(GEN nf, GEN ideal,long add_gen)
1562: {
1563: long av = avma,i,j,k,nba,nbp,R1,nbgen,cp;
1564: GEN p1,y,h,cyc,U,u1,fa,fa2,ep,x,arch,list,sarch,gen;
1565:
1566: nf = checknf(nf); R1=itos(gmael(nf,2,1));
1567: if (typ(ideal)==t_VEC && lg(ideal)==3)
1568: {
1569: arch=(GEN)ideal[2]; ideal = (GEN)ideal[1];
1570: i = typ(arch);
1571: if (!is_vec_t(i) || lg(arch) != R1+1)
1572: err(talker,"incorrect archimedean component in zidealstarinit");
1573: for (nba=0,i=1; i<=R1; i++)
1574: if (signe(arch[i])) nba++;
1575: }
1576: else
1577: {
1578: arch=cgetg(R1+1,t_VEC);
1579: for (nba=0,i=1; i<=R1; i++) arch[i]=zero;
1580: }
1581: x = idealhermite(nf,ideal);
1582: if (!gcmp1(denom(x)))
1583: err(talker,"zidealstarinit needs an integral ideal: %Z",x);
1584: p1=cgetg(3,t_VEC); ideal=p1;
1585: p1[1]=(long)x;
1586: p1[2]=(long)arch;
1587:
1588: fa=idealfactor(nf,x); list=(GEN)fa[1]; ep=(GEN)fa[2];
1589: nbp=lg(list)-1; fa2=cgetg(nbp+2,t_VEC);
1590:
1591: gen = cgetg(1,t_VEC);
1592: p1 = (nbp==1)? (GEN)NULL: x;
1593: for (i=1; i<=nbp; i++)
1594: {
1595: GEN L = zprimestar(nf,(GEN)list[i],(GEN)ep[i],p1,arch);
1596: fa2[i] = (long)L;
1597: for (j=1; j<lg(L); j++) gen = concatsp(gen,gmael(L,j,3));
1598: }
1599: sarch = zarchstar(nf,x,arch,nba);
1600: fa2[i]=(long)sarch;
1601: gen = concatsp(gen,(GEN)sarch[2]);
1602:
1603: nbgen = lg(gen)-1;
1604: h=cgetg(nbgen+1,t_MAT); cp=0;
1605: for (i=1; i<=nbp; i++)
1606: {
1607: list = (GEN)fa2[i];
1608: for (j=1; j<lg(list); j++)
1609: {
1610: GEN a, L = (GEN)list[j], e = (GEN)L[1], g = (GEN)L[3];
1611: for (k=1; k<lg(g); k++)
1612: {
1613: a = element_powmodidele(nf,(GEN)g[k],(GEN)e[k],ideal,sarch);
1614: h[++cp] = lneg(zinternallog(nf,a,fa2,nbgen,arch,fa,i));
1615: coeff(h,cp,cp) = e[k];
1616: }
1617: }
1618: }
1619: for (j=1; j<=nba; j++) { h[++cp]=(long)zerocol(nbgen); coeff(h,cp,cp)=deux; }
1620: if (cp!=nbgen) err(talker,"bug in zidealstarinit");
1621: h = hnfall_i(h,NULL,0);
1622: cyc = smithrel(h, &U, add_gen? &u1: NULL);
1623: p1 = cgetg(add_gen? 4: 3, t_VEC);
1624: p1[1] = (long)detcyc(cyc);
1625: p1[2] = (long)cyc;
1626:
1627: y = cgetg(6,t_VEC);
1628: y[1] = (long)ideal;
1629: y[2] = (long)p1;
1630: y[3] = (long)fa;
1631: y[4] = (long)fa2;
1632: y[5] = (long)U;
1633: if (add_gen) p1[3] = (long)compute_gen(nf,u1,gen, y);
1634: return gerepilecopy(av, y);
1635: }
1636:
1637: GEN
1638: zidealstarinitgen(GEN nf, GEN ideal)
1639: {
1640: return zidealstarinitall(nf,ideal,1);
1641: }
1642:
1643: GEN
1644: zidealstarinit(GEN nf, GEN ideal)
1645: {
1646: return zidealstarinitall(nf,ideal,0);
1647: }
1648:
1649: GEN
1650: zidealstar(GEN nf, GEN ideal)
1651: {
1652: long av = avma;
1653: GEN y = zidealstarinitall(nf,ideal,1);
1654: return gerepilecopy(av,(GEN)y[2]);
1655: }
1656:
1657: GEN
1658: idealstar0(GEN nf, GEN ideal,long flag)
1659: {
1660: switch(flag)
1661: {
1662: case 0: return zidealstar(nf,ideal);
1663: case 1: return zidealstarinit(nf,ideal);
1664: case 2: return zidealstarinitgen(nf,ideal);
1665: default: err(flagerr,"idealstar");
1666: }
1667: return NULL; /* not reached */
1668: }
1669:
1670: void
1671: check_nfelt(GEN x, GEN *den)
1672: {
1673: long l = lg(x), i;
1674: GEN t, d = NULL;
1675: if (typ(x) != t_COL) err(talker,"%Z not a nfelt", x);
1676: for (i=1; i<l; i++)
1677: {
1678: t = (GEN)x[i];
1679: switch (typ(t))
1680: {
1681: case t_INT: case t_INTMOD: break;
1682: case t_FRACN: case t_FRAC:
1683: if (!d) d = (GEN)t[2]; else d = mpppcm(d, (GEN)t[2]);
1684: break;
1685: default: err(talker,"%Z not a nfelt", x);
1686: }
1687: }
1688: *den = d;
1689: }
1690:
1691: /* Given x (not necessarily integral), and bid as output by zidealstarinit,
1692: * compute the vector of components on the generators bid[2].
1693: * Assume (x,bid) = 1 */
1694: GEN
1695: zideallog(GEN nf, GEN x, GEN bid)
1696: {
1697: long av,l,i,N,c;
1698: GEN fa,fa2,ideal,arch,den,p1,cyc,y;
1699:
1700: nf=checknf(nf); checkbid(bid);
1701: cyc=gmael(bid,2,2); c=lg(cyc);
1702: y=cgetg(c,t_COL); av=avma;
1703: N = degpol(nf[1]); ideal = (GEN) bid[1];
1704: if (typ(ideal)==t_VEC && lg(ideal)==3)
1705: arch = (GEN)ideal[2];
1706: else
1707: arch = NULL;
1708: switch(typ(x))
1709: {
1710: case t_INT: case t_FRAC: case t_FRACN:
1711: x = gscalcol_i(x,N); break;
1712: case t_POLMOD: case t_POL:
1713: x = algtobasis(nf,x); break;
1714: case t_MAT:
1715: return famat_ideallog(nf,(GEN)x[1],(GEN)x[2],bid);
1716: case t_COL: break;
1717: default: err(talker,"not an element in zideallog");
1718: }
1719: if (lg(x) != N+1) err(talker,"not an element in zideallog");
1720: check_nfelt(x, &den);
1721: if (den)
1722: {
1723: GEN g = cgetg(3, t_COL);
1724: GEN e = cgetg(3, t_COL);
1725: g[1] = lmul(x,den); e[1] = un;
1726: g[2] = (long)den; e[2] = lstoi(-1);
1727: p1 = famat_ideallog(nf, g, e, bid);
1728: }
1729: else
1730: {
1731: l=lg(bid[5])-1; fa=(GEN)bid[3]; fa2=(GEN)bid[4];
1732: p1 = zinternallog(nf,x,fa2,l,arch,fa,0);
1733: p1 = gmul((GEN)bid[5],p1); /* apply smith */
1734: }
1735: if (lg(p1)!=c) err(bugparier,"zideallog");
1736: for (i=1; i<c; i++)
1737: y[i] = lmodii((GEN)p1[i],(GEN)cyc[i]);
1738: avma=av; /* following line does a gerepile ! */
1739: for (i=1; i<c; i++)
1740: y[i] = (long)icopy((GEN)y[i]);
1741: return y;
1742: }
1743:
1744: /* bid1, bid2: output from 'zidealstarinit' for coprime modules m1 and m2
1745: * (without arch. part).
1746: * Output: zidealstarinit [[ideal,arch],[h,[cyc],[gen]],idealfact,[liste],U]
1747: * associated to m1 m2 */
1748: GEN
1749: zidealstarinitjoin(GEN nf, GEN bid1, GEN bid2, long add_gen)
1750: {
1751: long av=avma,i,nbp,nbgen,lx1,lx2,l1,l2,lx;
1752: GEN module1,module2,struct1,struct2,fact1,fact2,liste1,liste2;
1753: GEN module,liste,fact,U,U1,U2,cyc,cyc1,cyc2,uv;
1754: GEN p1,p2,y,u1,x,fa1,fa2, gen = add_gen? gun: NULL;
1755:
1756: nf = checknf(nf); checkbid(bid1); checkbid(bid2);
1757: module1 = (GEN)bid1[1]; struct1 = (GEN)bid1[2]; fact1 = (GEN)bid1[3];
1758: module2 = (GEN)bid2[1]; struct2 = (GEN)bid2[2]; fact2 = (GEN)bid2[3];
1759: x = idealmul(nf,(GEN)module1[1],(GEN)module2[1]);
1760: module = cgetg(3,t_VEC);
1761: module[1] = (long)x;
1762: module[2] = module1[2];
1763: if (!gcmp0((GEN)module1[2]) || !gcmp0((GEN)module2[2]))
1764: err(talker,"non-0 Archimedian components in zidealstarinitjoin");
1765:
1766: fa1 = (GEN)fact1[1]; lx1 = lg(fa1);
1767: fa2 = (GEN)fact2[1]; lx2 = lg(fa2);
1768: fact = cgetg(3,t_MAT);
1769: fact[1] = (long)concatsp(fa1,fa2);
1770: fact[2] = (long)concatsp((GEN)fact1[2],(GEN)fact2[2]);
1771: for (i=1; i<lx1; i++)
1772: if (isinvector(fa2,(GEN)fa1[i],lx2-1))
1773: err(talker,"noncoprime ideals in zidealstarinitjoin");
1774:
1775: liste1 = (GEN)bid1[4]; lx1 = lg(liste1);
1776: liste2 = (GEN)bid2[4]; lx2 = lg(liste2);
1777: /* concat (liste1 - last elt [zarchstar]) + liste2 */
1778: lx = lx1+lx2-2; liste = cgetg(lx,t_VEC);
1779: for (i=1; i<lx1-1; i++) liste[i] = liste1[i];
1780: for ( ; i<lx; i++) liste[i] = liste2[i-lx1+2];
1781:
1782: U1 = (GEN)bid1[5]; cyc1 = (GEN)struct1[2]; l1 = lg(cyc1);
1783: U2 = (GEN)bid2[5]; cyc2 = (GEN)struct2[2]; l2 = lg(cyc2);
1784: nbgen = l1+l2-2;
1785: cyc = diagonal(concatsp(cyc1,cyc2));
1786: cyc = smithrel(cyc, &U, gen? &u1: NULL);
1787:
1788: if (nbgen)
1789: U = concatsp(
1790: gmul(vecextract_i(U, 1, l1-1), U1) ,
1791: gmul(vecextract_i(U, l1, nbgen), U2)
1792: );
1793:
1794: if (gen)
1795: {
1796: if (lg(struct1)<=3 || lg(struct2)<=3)
1797: err(talker,"please apply idealstar(,,2) and not idealstar(,,1)");
1798:
1799: uv = idealaddtoone(nf,(GEN)module1[1],(GEN)module2[1]);
1800: p1 = makeprimetoidealvec(nf,x,uv,(GEN)struct1[3]);
1801: p2 = (GEN)uv[1]; uv[1] = uv[2]; uv[2] = (long)p2;
1802: p2 = makeprimetoidealvec(nf,x,uv,(GEN)struct2[3]);
1803: gen = concatsp(p1,p2);
1804: nbp = lg((GEN)fact[1])-1;
1805: }
1806: p1 = cgetg(gen? 4: 3,t_VEC);
1807: p1[1] = (long)detcyc(cyc);
1808: p1[2] = (long)cyc;
1809:
1810: y = cgetg(6,t_VEC);
1811: y[1] = (long)module;
1812: y[2] = (long)p1;
1813: y[3] = (long)fact;
1814: y[4] = (long)liste;
1815: y[5] = (long)U;
1816: if (gen) p1[3] = (long)compute_gen(nf,u1,gen, y);
1817: return gerepilecopy(av,y);
1818: }
1819:
1820: /* bid1: output from 'zidealstarinit' for module m1 (without arch. part)
1821: * arch: archimedean part.
1822: * Output: zidealstarinit [[ideal,arch],[h,[cyc],[gen]],idealfact,[liste],U]
1823: * associated to m1.arch */
1824: GEN
1825: zidealstarinitjoinarch(GEN nf, GEN bid1, GEN arch, long nba, long add_gen)
1826: {
1827: long av=avma,i,nbp,lx1;
1828: GEN module1,struct1,fact1,liste1,U1,U;
1829: GEN module,liste,cyc,p1,y,u1,x,sarch, gen = add_gen? gun: NULL;
1830:
1831: nf = checknf(nf); checkbid(bid1);
1832: module1 = (GEN)bid1[1]; struct1 = (GEN)bid1[2]; fact1 = (GEN)bid1[3];
1833: x = (GEN)module1[1];
1834: module = cgetg(3,t_VEC);
1835: module[1] = (long)x;
1836: module[2] = (long)arch;
1837: if (!gcmp0((GEN)module1[2]))
1838: err(talker,"non-0 Archimedian components in zidealstarinitjoinarch");
1839:
1840: sarch = zarchstar(nf,x,arch,nba);
1841: liste1 = (GEN)bid1[4]; lx1 = lg(liste1);
1842: liste = cgetg(lx1,t_VEC);
1843: for (i=1; i<lx1-1; i++) liste[i]=liste1[i];
1844: liste[i] = (long)sarch;
1845:
1846: U1 = (GEN)bid1[5]; lx1 = lg(U1);
1847: cyc = diagonal(concatsp((GEN)struct1[2],(GEN)sarch[1]));
1848: cyc = smithrel(cyc, &U, gen? &u1: NULL);
1849:
1850: if (gen)
1851: {
1852: if (lg(struct1)<=3)
1853: err(talker,"please apply idealstar(,,2) and not idealstar(,,1)");
1854: gen = concatsp((GEN)struct1[3],(GEN)sarch[2]);
1855: nbp = lg((GEN)fact1[1])-1;
1856: }
1857: p1 = cgetg(gen? 4: 3, t_VEC);
1858: p1[1] = (long)detcyc(cyc);
1859: p1[2] = (long)cyc;
1860:
1861: y = cgetg(6,t_VEC);
1862: y[1] = (long)module;
1863: y[2] = (long)p1;
1864: y[3] = (long)fact1;
1865: y[4] = (long)liste;
1866: y[5] = (long)U;
1867: if (gen) p1[3] = (long)compute_gen(nf,u1,gen, y);
1868: return gerepilecopy(av,y);
1869: }
1870:
1871: /* calcule la matrice des zinternallog des unites */
1872: GEN
1873: logunitmatrix(GEN nf,GEN funits,GEN racunit,GEN bid)
1874: {
1875: long R,j,sizeh;
1876: GEN m,fa2,fa,arch;
1877:
1878: R=lg(funits)-1; m=cgetg(R+2,t_MAT);
1879: fa2=(GEN)bid[4]; sizeh=lg(bid[5])-1; arch=gmael(bid,1,2);
1880: fa=(GEN)bid[3];
1881: m[1]=(long)zinternallog(nf,racunit,fa2,sizeh,arch,fa,0);
1882: for (j=2; j<=R+1; j++)
1883: m[j]=(long)zinternallog(nf,(GEN)funits[j-1],fa2,sizeh,arch,fa,0);
1884: return m;
1885: }
1886:
1887: /* calcule la matrice des zinternallog des unites */
1888: static GEN
1889: logunitmatrixarch(GEN nf,GEN funits,GEN racunit,GEN bid)
1890: {
1891: long R,j;
1892: GEN m,liste,structarch,arch;
1893:
1894: R=lg(funits)-1; m=cgetg(R+2,t_MAT); arch=gmael(bid,1,2);
1895: liste=(GEN)bid[4]; structarch=(GEN)liste[lg(liste)-1];
1896: m[1]=(long)zsigne(nf,racunit,arch);
1897: for (j=2; j<=R+1; j++)
1898: m[j]=(long)zsigne(nf,(GEN)funits[j-1],arch);
1899: return lift_intern(gmul((GEN)structarch[3],m));
1900: }
1901:
1902: static void
1903: init_units(GEN bnf, GEN *funits, GEN *racunit)
1904: {
1905: GEN p1;
1906: bnf = checkbnf(bnf); p1=(GEN)bnf[8];
1907: if (lg(p1)==5) *funits=(GEN)buchfu(bnf)[1];
1908: else
1909: {
1910: if (lg(p1)!=7) err(talker,"incorrect big number field");
1911: *funits=(GEN)p1[5];
1912: }
1913: *racunit=gmael(p1,4,2);
1914: }
1915:
1916: /* flag &1 : generateurs, sinon non
1917: * flag &2 : unites, sinon pas.
1918: * flag &4 : ideaux, sinon zidealstar.
1919: */
1920: static GEN
1921: ideallistzstarall(GEN bnf,long bound,long flag)
1922: {
1923: byteptr ptdif=diffptr;
1924: long lim,av0=avma,av,i,j,k,l,q2,lp1,q;
1925: long do_gen = flag & 1, do_units = flag & 2, big_id = !(flag & 4);
1926: GEN y,nf,p,z,z2,p1,p2,p3,fa,pr,ideal,lu,lu2,funits,racunit,embunit;
1927:
1928: nf = checknf(bnf);
1929: if (bound <= 0) return cgetg(1,t_VEC);
1930: z = cgetg(bound+1,t_VEC);
1931: for (i=2; i<=bound; i++) z[i] = lgetg(1,t_VEC);
1932:
1933: ideal = idmat(degpol(nf[1]));
1934: if (big_id) ideal = zidealstarinitall(nf,ideal,do_gen);
1935: z[1] = (long)_vec(ideal);
1936: if (do_units)
1937: {
1938: init_units(bnf,&funits,&racunit);
1939: lu = cgetg(bound+1,t_VEC);
1940: for (i=2; i<=bound; i++) lu[i]=lgetg(1,t_VEC);
1941: lu[1] = (long)_vec(logunitmatrix(nf,funits,racunit,ideal));
1942: }
1943:
1944: p=cgeti(3); p[1]=evalsigne(1) | evallgefint(3);
1945: av=avma; lim=stack_lim(av,1);
1946: lu2 = embunit = NULL; /* gcc -Wall */
1947: if (bound > (long)maxprime()) err(primer1);
1948: for (p[2]=0; p[2]<=bound; )
1949: {
1950: p[2] += *ptdif++;
1951: if (DEBUGLEVEL>1) { fprintferr("%ld ",p[2]); flusherr(); }
1952: fa = primedec(nf,p);
1953: for (j=1; j<lg(fa); j++)
1954: {
1955: pr = (GEN)fa[j]; p1 = powgi(p,(GEN)pr[4]);
1956: if (is_bigint(p1) || (q = itos(p1)) > bound) continue;
1957:
1958: q2=q; ideal=pr; z2=dummycopy(z);
1959: if (do_units) lu2=dummycopy(lu);
1960: for (l=2; ;l++)
1961: {
1962: if (big_id) ideal = zidealstarinitall(nf,ideal,do_gen);
1963: if (do_units) embunit = logunitmatrix(nf,funits,racunit,ideal);
1964: for (i=q; i<=bound; i+=q)
1965: {
1966: p1 = (GEN)z[i/q]; lp1 = lg(p1);
1967: if (lp1 == 1) continue;
1968:
1969: p2 = cgetg(lp1,t_VEC);
1970: for (k=1; k<lp1; k++)
1971: if (big_id)
1972: p2[k] = (long)zidealstarinitjoin(nf,(GEN)p1[k],ideal,do_gen);
1973: else
1974: p2[k] = (long)idealmul(nf,(GEN)p1[k],ideal);
1975: z2[i] = (long)concatsp((GEN)z2[i],p2);
1976: if (do_units)
1977: {
1978: p1 = (GEN)lu[i/q];
1979: p2 = cgetg(lp1,t_VEC);
1980: for (k=1; k<lp1; k++)
1981: p2[k] = (long)vconcat((GEN)p1[k],embunit);
1982: lu2[i] = (long)concatsp((GEN)lu2[i],p2);
1983: }
1984: }
1985: q *= q2; if ((ulong)q > (ulong)bound) break;
1986: ideal = idealpows(nf,pr,l);
1987: }
1988: z = z2; if (do_units) lu = lu2;
1989: }
1990: if (low_stack(lim, stack_lim(av,1)))
1991: {
1992: GEN *gptr[2]; gptr[0]=&z; gptr[1]=&lu;
1993: if(DEBUGMEM>1) err(warnmem,"ideallistzstarall");
1994: gerepilemany(av,gptr,do_units?2:1);
1995: }
1996: }
1997: if (!do_units) return gerepilecopy(av0, z);
1998: y = cgetg(3,t_VEC);
1999: y[1] = lcopy(z);
2000: lu2 = cgetg(lg(z),t_VEC);
2001: for (i=1; i<lg(z); i++)
2002: {
2003: p1=(GEN)z[i]; p2=(GEN)lu[i]; lp1=lg(p1);
2004: p3=cgetg(lp1,t_VEC); lu2[i]=(long)p3;
2005: for (j=1; j<lp1; j++) p3[j] = lmul(gmael(p1,j,5),(GEN)p2[j]);
2006: }
2007: y[2]=(long)lu2; return gerepileupto(av0, y);
2008: }
2009:
2010: GEN
2011: ideallist0(GEN bnf,long bound, long flag)
2012: {
2013: if (flag<0 || flag>4) err(flagerr,"ideallist");
2014: return ideallistzstarall(bnf,bound,flag);
2015: }
2016:
2017: GEN
2018: ideallistzstar(GEN nf,long bound)
2019: {
2020: return ideallistzstarall(nf,bound,0);
2021: }
2022:
2023: GEN
2024: ideallistzstargen(GEN nf,long bound)
2025: {
2026: return ideallistzstarall(nf,bound,1);
2027: }
2028:
2029: GEN
2030: ideallistunit(GEN nf,long bound)
2031: {
2032: return ideallistzstarall(nf,bound,2);
2033: }
2034:
2035: GEN
2036: ideallistunitgen(GEN nf,long bound)
2037: {
2038: return ideallistzstarall(nf,bound,3);
2039: }
2040:
2041: GEN
2042: ideallist(GEN bnf,long bound)
2043: {
2044: return ideallistzstarall(bnf,bound,4);
2045: }
2046:
2047: static GEN
2048: ideallist_arch(GEN nf,GEN list,GEN arch,long flun)
2049: {
2050: long nba,i,j,lx,ly;
2051: GEN p1,z,p2;
2052:
2053: nba=0; for (i=1; i<lg(arch); i++) if (signe(arch[i])) nba++;
2054: lx=lg(list); z=cgetg(lx,t_VEC);
2055: for (i=1; i<lx; i++)
2056: {
2057: p2=(GEN)list[i]; checkbid(p2); ly=lg(p2);
2058: p1=cgetg(ly,t_VEC); z[i]=(long)p1;
2059: for (j=1; j<ly; j++)
2060: p1[j]=(long)zidealstarinitjoinarch(nf,(GEN)p2[j],arch,nba,flun);
2061: }
2062: return z;
2063: }
2064:
2065: static GEN
2066: ideallistarchall(GEN bnf,GEN list,GEN arch,long flag)
2067: {
2068: ulong av;
2069: long i,j,lp1, do_units = flag & 2;
2070: GEN nf = checknf(bnf), p1,p2,p3,racunit,funits,lu2,lu,embunit,z,y;
2071:
2072: if (typ(list) != t_VEC || (do_units && lg(list) != 3))
2073: err(typeer, "ideallistarch");
2074: if (lg(list) == 1) return cgetg(1,t_VEC);
2075: if (do_units)
2076: {
2077: y = cgetg(3,t_VEC);
2078: z = (GEN)list[1];
2079: lu= (GEN)list[2]; if (typ(lu) != t_VEC) err(typeer, "ideallistarch");
2080: }
2081: else
2082: {
2083: z = list;
2084: y = lu = NULL; /* gcc -Wall */
2085: }
2086: if (typ(z) != t_VEC) err(typeer, "ideallistarch");
2087: z = ideallist_arch(nf,z,arch, flag & 1);
2088: if (!do_units) return z;
2089:
2090: y[1]=(long)z; av=avma;
2091: init_units(bnf,&funits,&racunit);
2092: lu2=cgetg(lg(z),t_VEC);
2093: for (i=1; i<lg(z); i++)
2094: {
2095: p1=(GEN)z[i]; p2=(GEN)lu[i]; lp1=lg(p1);
2096: p3=cgetg(lp1,t_VEC); lu2[i]=(long)p3;
2097: for (j=1; j<lp1; j++)
2098: {
2099: embunit = logunitmatrixarch(nf,funits,racunit,(GEN)p1[j]);
2100: p3[j] = lmul(gmael(p1,j,5), vconcat((GEN)p2[j],embunit));
2101: }
2102: }
2103: y[2]=lpilecopy(av,lu2); return y;
2104: }
2105:
2106: GEN
2107: ideallistarch(GEN nf, GEN list, GEN arch)
2108: {
2109: return ideallistarchall(nf,list,arch,0);
2110: }
2111:
2112: GEN
2113: ideallistarchgen(GEN nf, GEN list, GEN arch)
2114: {
2115: return ideallistarchall(nf,list,arch,1);
2116: }
2117:
2118: GEN
2119: ideallistunitarch(GEN bnf,GEN list,GEN arch)
2120: {
2121: return ideallistarchall(bnf,list,arch,2);
2122: }
2123:
2124: GEN
2125: ideallistunitarchgen(GEN bnf,GEN list,GEN arch)
2126: {
2127: return ideallistarchall(bnf,list,arch,3);
2128: }
2129:
2130: GEN
2131: ideallistarch0(GEN nf, GEN list, GEN arch,long flag)
2132: {
2133: if (!arch) arch=cgetg(1,t_VEC);
2134: if (flag<0 || flag>3) err(flagerr,"ideallistarch");
2135: return ideallistarchall(nf,list,arch,flag);
2136: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>