Annotation of OpenXM_contrib/pari-2.2/src/basemath/buch4.c, Revision 1.2
1.2 ! noro 1: /* $Id: buch4.c,v 1.36 2002/09/10 14:47:04 karim Exp $
1.1 noro 2:
3: Copyright (C) 2000 The PARI group.
4:
5: This file is part of the PARI/GP package.
6:
7: PARI/GP is free software; you can redistribute it and/or modify it under the
8: terms of the GNU General Public License as published by the Free Software
9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
10: ANY WARRANTY WHATSOEVER.
11:
12: Check the License for details. You should have received a copy of it, along
13: with the package; see the file 'COPYING'. If not, write to the Free Software
14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
15:
16: /*******************************************************************/
17: /* */
18: /* S-CLASS GROUP AND NORM SYMBOLS */
19: /* (Denis Simon, desimon@math.u-bordeaux.fr) */
20: /* */
21: /*******************************************************************/
22: #include "pari.h"
23: #include "parinf.h"
24:
1.2 ! noro 25: extern GEN to_polmod(GEN x, GEN mod);
! 26: extern GEN hnfall0(GEN A, long remove);
! 27: extern GEN get_theta_abstorel(GEN T, GEN pol, GEN k);
! 28: extern GEN _rnfequation(GEN A, GEN B, long *pk, GEN *pLPRS);
! 29:
1.1 noro 30: static long
31: psquare(GEN a,GEN p)
32: {
33: long v;
34: GEN ap;
35:
36: if (gcmp0(a) || gcmp1(a)) return 1;
37:
38: if (!cmpis(p,2))
39: {
40: v=vali(a); if (v&1) return 0;
41: return (smodis(shifti(a,-v),8)==1);
42: }
43:
44: ap=stoi(1); v=pvaluation(a,p,&ap);
45: if (v&1) return 0;
46: return (kronecker(ap,p)==1);
47: }
48:
49: static long
50: lemma6(GEN pol,GEN p,long nu,GEN x)
51: {
1.2 ! noro 52: long i, lambda, mu;
! 53: gpmem_t ltop=avma;
1.1 noro 54: GEN gx,gpx;
55:
56: for (i=lgef(pol)-2,gx=(GEN) pol[i+1]; i>1; i--)
57: gx=addii(mulii(gx,x),(GEN) pol[i]);
58: if (psquare(gx,p)) return 1;
59:
60: for (i=lgef(pol)-2,gpx=mulis((GEN) pol[i+1],i-1); i>2; i--)
61: gpx=addii(mulii(gpx,x),mulis((GEN) pol[i],i-2));
62:
63: lambda=pvaluation(gx,p,&gx);
64: if (gcmp0(gpx)) mu=BIGINT; else mu=pvaluation(gpx,p,&gpx);
65: avma=ltop;
66:
67: if (lambda>(mu<<1)) return 1;
68: if (lambda>=(nu<<1) && mu>=nu) return 0;
69: return -1;
70: }
71:
72: static long
73: lemma7(GEN pol,long nu,GEN x)
1.2 ! noro 74: {
! 75: long i,odd4,lambda,mu,mnl;
! 76: gpmem_t ltop=avma;
1.1 noro 77: GEN gx,gpx,oddgx;
78:
79: for (i=lgef(pol)-2,gx=(GEN) pol[i+1]; i>1; i--)
80: gx=addii(mulii(gx,x),(GEN) pol[i]);
81: if (psquare(gx,gdeux)) return 1;
82:
83: for (i=lgef(pol)-2,gpx=gmulgs((GEN) pol[i+1],i-1); i>2; i--)
84: gpx=gadd(gmul(gpx,x),gmulgs((GEN) pol[i],i-2));
85:
86: lambda=vali(gx);
87: if (gcmp0(gpx)) mu=BIGINT; else mu=vali(gpx);
88: oddgx=shifti(gx,-lambda);
89: mnl=mu+nu-lambda;
90: odd4=smodis(oddgx,4);
91: avma=ltop;
92: if (lambda>(mu<<1)) return 1;
93: if (nu > mu)
94: { if (mnl==1 && (lambda&1) == 0) return 1;
95: if (mnl==2 && (lambda&1) == 0 && odd4==1) return 1;
96: }
97: else
98: { if (lambda>=(nu<<1)) return 0;
99: if (lambda==((nu-1)<<1) && odd4==1) return 0;
100: }
101: return -1;
102: }
103:
104: static long
105: zpsol(GEN pol,GEN p,long nu,GEN pnu,GEN x0)
106: {
1.2 ! noro 107: long i, result;
! 108: gpmem_t ltop=avma;
1.1 noro 109: GEN x,pnup;
110:
111: result = (cmpis(p,2)) ? lemma6(pol,p,nu,x0) : lemma7(pol,nu,x0);
112: if (result==+1) return 1; if (result==-1) return 0;
113: x=gcopy(x0); pnup=mulii(pnu,p);
114: for (i=0; i<itos(p); i++)
115: {
116: x=addii(x,pnu);
117: if (zpsol(pol,p,nu+1,pnup,x)) { avma=ltop; return 1; }
118: }
119: avma=ltop; return 0;
120: }
121:
122: /* vaut 1 si l'equation y^2=Pol(x) a une solution p-adique entiere
123: * 0 sinon. Les coefficients sont entiers.
124: */
125: long
126: zpsoluble(GEN pol,GEN p)
127: {
128: if ((typ(pol)!=t_POL && typ(pol)!=t_INT) || typ(p)!=t_INT )
129: err(typeer,"zpsoluble");
130: return zpsol(pol,p,0,gun,gzero);
131: }
132:
133: /* vaut 1 si l'equation y^2=Pol(x) a une solution p-adique rationnelle
134: * (eventuellement infinie), 0 sinon. Les coefficients sont entiers.
135: */
136: long
137: qpsoluble(GEN pol,GEN p)
138: {
139: if ((typ(pol)!=t_POL && typ(pol)!=t_INT) || typ(p)!=t_INT )
140: err(typeer,"qpsoluble");
141: if (zpsol(pol,p,0,gun,gzero)) return 1;
142: return (zpsol(polrecip(pol),p,1,p,gzero));
143: }
144:
145: /* (pr,2) = 1. return 1 if a square in (ZK / pr), 0 otherwise */
146: static long
147: psquarenf(GEN nf,GEN a,GEN pr)
148: {
1.2 ! noro 149: gpmem_t av = avma;
1.1 noro 150: long v;
151: GEN norm;
152:
153: if (gcmp0(a)) return 1;
154: v = idealval(nf,a,pr); if (v&1) return 0;
155: if (v) a = gdiv(a, gpowgs(basistoalg(nf, (GEN)pr[2]), v));
156:
157: norm = gshift(idealnorm(nf,pr), -1);
158: a = gmul(a, gmodulsg(1,(GEN)pr[1]));
159: a = gaddgs(powgi(a,norm), -1);
160: if (gcmp0(a)) { avma = av; return 1; }
161: a = lift(lift(a));
162: v = idealval(nf,a,pr);
163: avma = av; return (v>0);
164: }
165:
166: static long
167: check2(GEN nf, GEN a, GEN zinit)
168: {
169: GEN zlog=zideallog(nf,a,zinit), p1 = gmael(zinit,2,2);
170: long i;
171:
172: for (i=1; i<lg(p1); i++)
173: if (!mpodd((GEN)p1[i]) && mpodd((GEN)zlog[i])) return 0;
174: return 1;
175: }
176:
177: /* pr | 2. Return 1 if a square in (ZK / pr), 0 otherwise */
178: static long
179: psquare2nf(GEN nf,GEN a,GEN pr,GEN zinit)
180: {
1.2 ! noro 181: long v;
! 182: gpmem_t ltop = avma;
1.1 noro 183:
184: if (gcmp0(a)) return 1;
185: v = idealval(nf,a,pr); if (v&1) return 0;
186: if (v) a = gdiv(a, gpowgs(basistoalg(nf, (GEN)pr[2]), v));
187: /* now (a,pr) = 1 */
188: v = check2(nf,a,zinit); avma = ltop; return v;
189: }
190:
191: /* pr | 2. Return 1 if a square in (ZK / pr^q)^*, and 0 otherwise */
192: static long
193: psquare2qnf(GEN nf,GEN a,GEN p,long q)
194: {
1.2 ! noro 195: long v;
! 196: gpmem_t ltop=avma;
1.1 noro 197: GEN zinit = zidealstarinit(nf,idealpows(nf,p,q));
198:
199: v = check2(nf,a,zinit); avma = ltop; return v;
200: }
201:
202: static long
203: lemma6nf(GEN nf,GEN pol,GEN p,long nu,GEN x)
204: {
1.2 ! noro 205: long i, lambda, mu;
! 206: gpmem_t ltop=avma;
1.1 noro 207: GEN gx,gpx;
208:
209: for (i=lgef(pol)-2,gx=(GEN) pol[i+1]; i>1; i--)
210: gx = gadd(gmul(gx,x),(GEN) pol[i]);
211: if (psquarenf(nf,gx,p)) { avma=ltop; return 1; }
212: lambda = idealval(nf,gx,p);
213:
214: for (i=lgef(pol)-2,gpx=gmulgs((GEN) pol[i+1],i-1); i>2; i--)
215: gpx=gadd(gmul(gpx,x),gmulgs((GEN) pol[i],i-2));
216: mu = gcmp0(gpx)? BIGINT: idealval(nf,gpx,p);
217:
218: avma=ltop;
219: if (lambda > mu<<1) return 1;
220: if (lambda >= nu<<1 && mu >= nu) return 0;
221: return -1;
222: }
223:
224: static long
225: lemma7nf(GEN nf,GEN pol,GEN p,long nu,GEN x,GEN zinit)
226: {
1.2 ! noro 227: long res, i, lambda, mu, q;
! 228: gpmem_t ltop=avma;
1.1 noro 229: GEN gx,gpx,p1;
230:
231: for (i=lgef(pol)-2, gx=(GEN) pol[i+1]; i>1; i--)
232: gx=gadd(gmul(gx,x),(GEN) pol[i]);
233: if (psquare2nf(nf,gx,p,zinit)) { avma=ltop; return 1; }
234: lambda=idealval(nf,gx,p);
235:
236: for (i=lgef(pol)-2,gpx=gmulgs((GEN) pol[i+1],i-1); i>2; i--)
237: gpx=gadd(gmul(gpx,x),gmulgs((GEN) pol[i],i-2));
238: if (!gcmp0(gpx)) mu=idealval(nf,gpx,p); else mu=BIGINT;
239:
240: if (lambda>(mu<<1)) { avma=ltop; return 1; }
241: if (nu > mu)
242: {
243: if (lambda&1) { avma=ltop; return -1; }
244: q=mu+nu-lambda; res=1;
245: }
246: else
247: {
248: if (lambda>=(nu<<1)) { avma=ltop; return 0; }
249: if (lambda&1) { avma=ltop; return -1; }
250: q=(nu<<1)-lambda; res=0;
251: }
252: if (q > itos((GEN) p[3])<<1) { avma=ltop; return -1; }
1.2 ! noro 253: p1 = gmodulcp(gpowgs(gmul((GEN)nf[7],(GEN)p[2]), lambda), (GEN)nf[1]);
1.1 noro 254: if (!psquare2qnf(nf,gdiv(gx,p1), p,q)) res = -1;
255: avma=ltop; return res;
256: }
257:
258: static long
259: zpsolnf(GEN nf,GEN pol,GEN p,long nu,GEN pnu,GEN x0,GEN repr,GEN zinit)
260: {
1.2 ! noro 261: long i, result;
! 262: gpmem_t ltop=avma;
1.1 noro 263: GEN pnup;
264:
265: nf=checknf(nf);
266: if (cmpis((GEN) p[1],2))
267: result=lemma6nf(nf,pol,p,nu,x0);
268: else
269: result=lemma7nf(nf,pol,p,nu,x0,zinit);
270: if (result== 1) return 1;
271: if (result==-1) return 0;
272: pnup = gmul(pnu, basistoalg(nf,(GEN)p[2]));
273: nu++;
274: for (i=1; i<lg(repr); i++)
275: if (zpsolnf(nf,pol,p,nu,pnup,gadd(x0,gmul(pnu,(GEN)repr[i])),repr,zinit))
276: { avma=ltop; return 1; }
277: avma=ltop; return 0;
278: }
279:
280: /* calcule un systeme de representants Zk/p */
281: static GEN
282: repres(GEN nf,GEN p)
283: {
284: long i,j,k,f,pp,ppf,ppi;
285: GEN mat,fond,rep;
286:
287: fond=cgetg(1,t_VEC);
288: mat=idealhermite(nf,p);
289: for (i=1; i<lg(mat); i++)
290: if (!gcmp1(gmael(mat,i,i)))
291: fond = concatsp(fond,gmael(nf,7,i));
292: f=lg(fond)-1;
293: pp=itos((GEN) p[1]);
294: for (i=1,ppf=1; i<=f; i++) ppf*=pp;
295: rep=cgetg(ppf+1,t_VEC);
296: rep[1]=zero; ppi=1;
297: for (i=0; i<f; i++,ppi*=pp)
298: for (j=1; j<pp; j++)
299: for (k=1; k<=ppi; k++)
300: rep[j*ppi+k]=ladd((GEN) rep[k],gmulsg(j,(GEN) fond[i+1]));
301: return gmodulcp(rep,(GEN) nf[1]);
302: }
303:
304: /* =1 si l'equation y^2 = z^deg(pol) * pol(x/z) a une solution rationnelle
305: * p-adique (eventuellement (1,y,0) = oo)
306: * =0 sinon.
307: * Les coefficients de pol doivent etre des entiers de nf.
308: * p est un ideal premier sous forme primedec.
309: */
310: long
311: qpsolublenf(GEN nf,GEN pol,GEN pr)
312: {
313: GEN repr,zinit,p1;
1.2 ! noro 314: gpmem_t ltop=avma;
1.1 noro 315:
316: if (gcmp0(pol)) return 1;
317: if (typ(pol)!=t_POL) err(notpoler,"qpsolublenf");
318: checkprimeid(pr);
319:
320: if (egalii((GEN) pr[1], gdeux))
321: { /* tough case */
322: zinit = zidealstarinit(nf, idealpows(nf,pr,1+2*idealval(nf,gdeux,pr)));
323: if (psquare2nf(nf,(GEN) pol[2],pr,zinit)) return 1;
324: if (psquare2nf(nf, leading_term(pol),pr,zinit)) return 1;
325: }
326: else
327: {
328: if (psquarenf(nf,(GEN) pol[2],pr)) return 1;
329: if (psquarenf(nf, leading_term(pol),pr)) return 1;
330: zinit = gzero;
331: }
332: repr = repres(nf,pr);
333: if (zpsolnf(nf,pol,pr,0,gun,gzero,repr,zinit)) { avma=ltop; return 1; }
334: p1 = gmodulcp(gmul((GEN) nf[7],(GEN) pr[2]),(GEN) nf[1]);
335: if (zpsolnf(nf,polrecip(pol),pr,1,p1,gzero,repr,zinit))
336: { avma=ltop; return 1; }
337:
338: avma=ltop; return 0;
339: }
340:
341: /* =1 si l'equation y^2 = pol(x) a une solution entiere p-adique
342: * =0 sinon.
343: * Les coefficients de pol doivent etre des entiers de nf.
344: * p est un ideal premier sous forme primedec.
345: */
346: long
347: zpsolublenf(GEN nf,GEN pol,GEN p)
348: {
349: GEN repr,zinit;
1.2 ! noro 350: gpmem_t ltop=avma;
1.1 noro 351:
352: if (gcmp0(pol)) return 1;
353: if (typ(pol)!=t_POL) err(notpoler,"zpsolublenf");
354: if (typ(p)!=t_VEC || lg(p)!=6)
355: err(talker,"not a prime ideal in zpsolublenf");
356: nf=checknf(nf);
357:
358: if (cmpis((GEN)p[1],2))
359: {
360: if (psquarenf(nf,(GEN) pol[2],p)) return 1;
361: zinit=gzero;
362: }
363: else
364: {
365: zinit=zidealstarinit(nf,idealpows(nf,p,1+2*idealval(nf,gdeux,p)));
366: if (psquare2nf(nf,(GEN) pol[2],p,zinit)) return 1;
367: }
368: repr=repres(nf,p);
369: if (zpsolnf(nf,pol,p,0,gun,gzero,repr,zinit)) { avma=ltop; return 1; }
370: avma=ltop; return 0;
371: }
372:
373: static long
374: hilb2nf(GEN nf,GEN a,GEN b,GEN p)
375: {
1.2 ! noro 376: gpmem_t av = avma;
1.1 noro 377: long rep;
1.2 ! noro 378: GEN pol;
! 379:
! 380: if (typ(a) != t_POLMOD) a = basistoalg(nf, a);
! 381: if (typ(b) != t_POLMOD) b = basistoalg(nf, b);
! 382: pol = coefs_to_pol(3, lift(a), zero, lift(b));
1.1 noro 383: /* varn(nf.pol) = 0, pol is not a valid GEN [as in Pol([x,x], x)].
384: * But it is only used as a placeholder, hence it is not a problem */
385:
386: rep = qpsolublenf(nf,pol,p)? 1: -1;
387: avma = av; return rep;
388: }
389:
390: /* local quadratic Hilbert symbol (a,b)_pr, for a,b (non-zero) in nf */
391: long
392: nfhilbertp(GEN nf,GEN a,GEN b,GEN pr)
393: {
1.2 ! noro 394: GEN ord, ordp, T,p, modpr,t;
1.1 noro 395: long va, vb, rep;
1.2 ! noro 396: gpmem_t av = avma;
1.1 noro 397:
398: if (gcmp0(a) || gcmp0(b)) err (talker,"0 argument in nfhilbertp");
399: checkprimeid(pr); nf = checknf(nf);
400: p = (GEN)pr[1];
401:
402: if (egalii(p,gdeux)) return hilb2nf(nf,a,b,pr);
403:
404: /* pr not above 2, compute t = tame symbol */
405: va = idealval(nf,a,pr);
406: vb = idealval(nf,b,pr);
407: if (!odd(va) && !odd(vb)) { avma = av; return 1; }
408: t = element_div(nf, element_pow(nf,a,stoi(vb)),
409: element_pow(nf,b,stoi(va)));
410: if (odd(va) && odd(vb)) t = gneg_i(t); /* t mod pr = tame_pr(a,b) */
411:
412: /* quad. symbol is image of t by the quadratic character */
413: ord = subis( idealnorm(nf,pr), 1 ); /* |(O_K / pr)^*| */
414: ordp= subis( p, 1); /* |F_p^*| */
1.2 ! noro 415: modpr = nf_to_ff_init(nf, &pr,&T,&p);
! 416: t = nf_to_ff(nf,t,modpr);
! 417: t = FpXQ_pow(t, diviiexact(ord, ordp), T,p); /* in F_p^* */
! 418: if (typ(t) == t_POL)
! 419: {
! 420: if (degpol(t)) err(bugparier,"nfhilbertp");
! 421: t = constant_term(t);
! 422: }
1.1 noro 423: rep = kronecker(t, p);
424: avma = av; return rep;
425: }
426:
427: /* global quadratic Hilbert symbol (a,b):
428: * = 1 if X^2 - aY^2 - bZ^2 has a point in projective plane
429: * = -1 otherwise
430: * a, b should be non-zero
431: */
432: long
433: nfhilbert(GEN nf,GEN a,GEN b)
434: {
1.2 ! noro 435: gpmem_t av = avma;
1.1 noro 436: long r1, i;
437: GEN S, al, bl, ro;
438:
439: if (gcmp0(a) || gcmp0(b)) err (talker,"0 argument in nfhilbert");
440: nf = checknf(nf);
441:
442: if (typ(a) != t_POLMOD) a = basistoalg(nf, a);
443: if (typ(b) != t_POLMOD) b = basistoalg(nf, b);
444:
445: al = lift(a);
446: bl = lift(b);
447: /* local solutions in real completions ? */
448: r1 = nf_get_r1(nf); ro = (GEN)nf[6];
449: for (i=1; i<=r1; i++)
450: if (signe(poleval(al,(GEN)ro[i])) < 0 &&
451: signe(poleval(bl,(GEN)ro[i])) < 0)
452: {
453: if (DEBUGLEVEL>=4)
454: fprintferr("nfhilbert not soluble at real place %ld\n",i);
455: avma = av; return -1;
456: }
457:
458: /* local solutions in finite completions ? (pr | 2ab)
459: * primes above 2 are toughest. Try the others first */
460:
461: S = (GEN) idealfactor(nf,gmul(gmulsg(2,a),b))[1];
462: /* product of all hilbertp is 1 ==> remove one prime (above 2!) */
463: for (i=lg(S)-1; i>1; i--)
464: if (nfhilbertp(nf,a,b,(GEN) S[i]) < 0)
465: {
466: if (DEBUGLEVEL >=4)
467: fprintferr("nfhilbert not soluble at finite place: %Z\n",S[i]);
468: avma = av; return -1;
469: }
470: avma = av; return 1;
471: }
472:
473: long
474: nfhilbert0(GEN nf,GEN a,GEN b,GEN p)
475: {
476: if (p) return nfhilbertp(nf,a,b,p);
477: return nfhilbert(nf,a,b);
478: }
479:
480: extern GEN isprincipalfact(GEN bnf,GEN P, GEN e, GEN C, long flag);
481: extern GEN vconcat(GEN Q1, GEN Q2);
482: extern GEN mathnfspec(GEN x, GEN *ptperm, GEN *ptdep, GEN *ptB, GEN *ptC);
1.2 ! noro 483: extern GEN factorback_i(GEN fa, GEN e, GEN nf, int red);
! 484: extern GEN detcyc(GEN cyc);
1.1 noro 485: /* S a list of prime ideal in primedec format. Return res:
486: * res[1] = generators of (S-units / units), as polynomials
487: * res[2] = [perm, HB, den], for bnfissunit
488: * res[3] = [] (was: log. embeddings of res[1])
489: * res[4] = S-regulator ( = R * det(res[2]) * \prod log(Norm(S[i])))
490: * res[5] = S class group
491: * res[6] = S
492: */
493: GEN
494: bnfsunit(GEN bnf,GEN S,long prec)
495: {
1.2 ! noro 496: gpmem_t ltop = avma;
1.1 noro 497: long i,j,ls;
498: GEN p1,nf,classgp,gen,M,U,H;
1.2 ! noro 499: GEN sunit,card,sreg,res,pow;
1.1 noro 500:
501: if (typ(S) != t_VEC) err(typeer,"bnfsunit");
502: bnf = checkbnf(bnf); nf=(GEN)bnf[7];
503: classgp=gmael(bnf,8,1);
504: gen = (GEN)classgp[3];
505:
506: sreg = gmael(bnf,8,2);
507: res=cgetg(7,t_VEC);
508: res[1]=res[2]=res[3]=lgetg(1,t_VEC);
509: res[4]=(long)sreg;
510: res[5]=(long)classgp;
511: res[6]=(long)S; ls=lg(S);
512:
513: /* M = relation matrix for the S class group (in terms of the class group
514: * generators given by gen)
515: * 1) ideals in S
516: */
517: M = cgetg(ls,t_MAT);
518: for (i=1; i<ls; i++)
519: {
520: p1 = (GEN)S[i]; checkprimeid(p1);
521: M[i] = (long)isprincipal(bnf,p1);
522: }
523: /* 2) relations from bnf class group */
524: M = concatsp(M, diagonal((GEN) classgp[2]));
525:
526: /* S class group */
527: H = hnfall(M); U = (GEN)H[2]; H= (GEN)H[1];
528: card = gun;
529: if (lg(H) > 1)
530: { /* non trivial (rare!) */
1.2 ! noro 531: GEN D,U, ClS = cgetg(4,t_VEC);
1.1 noro 532:
1.2 ! noro 533: D = smithall(H, &U, NULL);
! 534: for(i=1; i<lg(D); i++)
! 535: if (gcmp1((GEN)D[i])) break;
! 536: setlg(D,i); D = mattodiagonal_i(D); /* cf smithrel */
! 537: card = detcyc(D);
1.1 noro 538: ClS[1] = (long)card; /* h */
1.2 ! noro 539: ClS[2] = (long)D; /* cyc */
1.1 noro 540:
1.2 ! noro 541: p1=cgetg(i,t_VEC); pow=ZM_inv(U,gun);
1.1 noro 542: for(i--; i; i--)
1.2 ! noro 543: p1[i] = (long)factorback_i(gen, (GEN)pow[i], nf, 1);
1.1 noro 544: ClS[3]=(long)p1; /* gen */
545: res[5]=(long) ClS;
546: }
547:
548: /* S-units */
549: if (ls>1)
550: {
551: GEN den, Sperm, perm, dep, B, U1 = U;
552: long lH, lB, fl = nf_GEN|nf_FORCE;
553:
554: /* U1 = upper left corner of U, invertible. S * U1 = principal ideals
555: * whose generators generate the S-units */
556: setlg(U1,ls); p1 = cgetg(ls, t_MAT); /* p1 is junk for mathnfspec */
557: for (i=1; i<ls; i++) { setlg(U1[i],ls); p1[i] = lgetg(1,t_COL); }
558: H = mathnfspec(U1,&perm,&dep,&B,&p1);
559: lH = lg(H);
560: lB = lg(B);
561: if (lg(dep) > 1 && lg(dep[1]) > 1) err(bugparier,"bnfsunit");
562: /* [ H B ] [ H^-1 - H^-1 B ]
563: * perm o HNF(U1) = [ 0 Id ], inverse = [ 0 Id ]
564: * (permute the rows)
565: * S * HNF(U1) = _integral_ generators for S-units = sunit */
566: Sperm = cgetg(ls, t_VEC); sunit = cgetg(ls, t_VEC);
567: for (i=1; i<ls; i++) Sperm[i] = S[perm[i]]; /* S o perm */
568:
1.2 ! noro 569: setlg(Sperm, lH);
1.1 noro 570: for (i=1; i<lH; i++)
571: sunit[i] = isprincipalfact(bnf,Sperm,(GEN)H[i],NULL,fl)[2];
572: for (j=1; j<lB; j++,i++)
573: sunit[i] = isprincipalfact(bnf,Sperm,(GEN)B[j],(GEN)Sperm[i],fl)[2];
574:
575: p1 = cgetg(4,t_VEC);
576: den = dethnf_i(H); H = ZM_inv(H,den);
577: p1[1] = (long)perm;
578: p1[2] = (long)concatsp(H, gneg(gmul(H,B))); /* top part of inverse * den */
579: p1[3] = (long)den; /* keep denominator separately */
580: sunit = basistoalg(nf,sunit);
581: res[2] = (long)p1; /* HNF in split form perm + (H B) [0 Id missing] */
582: res[1] = (long)lift_intern(sunit);
583: }
584:
585: /* S-regulator */
586: sreg = gmul(sreg,card);
587: for (i=1; i<ls; i++)
588: {
589: GEN p = (GEN)S[i];
590: if (typ(p) == t_VEC) p = (GEN) p[1];
591: sreg = gmul(sreg,glog(p,prec));
592: }
593: res[4]=(long) sreg;
594: return gerepilecopy(ltop,res);
595: }
596:
1.2 ! noro 597: static GEN
! 598: make_unit(GEN bnf, GEN suni, GEN *px)
1.1 noro 599: {
1.2 ! noro 600: long lB, cH, i, k, ls;
1.1 noro 601: GEN den,gen,S,v,p1,xp,xm,xb,N,HB,perm;
602:
1.2 ! noro 603: if (gcmp0(*px)) return NULL;
! 604: S = (GEN) suni[6]; ls=lg(S);
! 605: if (ls==1) return cgetg(1, t_COL);
1.1 noro 606:
1.2 ! noro 607: xb = algtobasis(bnf,*px); p1 = Q_denom(xb);
! 608: N = mulii(gnorm(gmul(*px,p1)), p1); /* relevant primes divide N */
! 609: if (is_pm1(N)) return zerocol(ls -1);
1.1 noro 610:
611: p1 = (GEN)suni[2];
612: perm = (GEN)p1[1];
1.2 ! noro 613: HB = (GEN)p1[2];
! 614: den = (GEN)p1[3];
1.1 noro 615: cH = lg(HB[1]) - 1;
616: lB = lg(HB) - cH;
617: v = cgetg(ls, t_VECSMALL);
618: for (i=1; i<ls; i++)
619: {
620: GEN P = (GEN)S[i];
621: v[i] = (resii(N, (GEN)P[1]) == gzero)? element_val(bnf,xb,P): 0;
622: }
623: /* here, x = S v */
624: p1 = cgetg(ls, t_COL);
625: for (i=1; i<ls; i++) p1[i] = lstoi(v[perm[i]]); /* p1 = v o perm */
626: v = gmul(HB, p1);
627: for (i=1; i<=cH; i++)
628: {
629: GEN w = gdiv((GEN)v[i], den);
1.2 ! noro 630: if (typ(w) != t_INT) return NULL;
1.1 noro 631: v[i] = (long)w;
632: }
633: p1 += cH;
634: p1[0] = evaltyp(t_COL) | evallg(lB);
635: v = concatsp(v, p1); /* append bottom of p1 (= [0 Id] part) */
636:
637: xp = gun; xm = gun; gen = (GEN)suni[1];
638: for (i=1; i<ls; i++)
639: {
640: k = -itos((GEN)v[i]); if (!k) continue;
641: p1 = basistoalg(bnf, (GEN)gen[i]);
1.2 ! noro 642: if (k > 0) xp = gmul(xp, gpowgs(p1, k));
! 643: else xm = gmul(xm, gpowgs(p1,-k));
1.1 noro 644: }
1.2 ! noro 645: if (xp != gun) *px = gmul(*px,xp);
! 646: if (xm != gun) *px = gdiv(*px,xm);
! 647: return v;
1.1 noro 648: }
649:
1.2 ! noro 650: /* cette fonction est l'equivalent de isunit, sauf qu'elle donne le resultat
! 651: * avec des s-unites: si x n'est pas une s-unite alors issunit=[]~;
! 652: * si x est une s-unite alors
! 653: * x=\prod_{i=0}^r {e_i^issunit[i]}*prod{i=r+1}^{r+s} {s_i^issunit[i]}
! 654: * ou les e_i sont les unites du corps (comme dans isunit)
! 655: * et les s_i sont les s-unites calculees par sunit (dans le meme ordre).
! 656: */
! 657: GEN
! 658: bnfissunit(GEN bnf,GEN suni,GEN x)
1.1 noro 659: {
1.2 ! noro 660: gpmem_t av = avma;
! 661: GEN v, w;
1.1 noro 662:
1.2 ! noro 663: bnf = checkbnf(bnf);
! 664: if (typ(suni)!=t_VEC || lg(suni)!=7) err(typeer,"bnfissunit");
! 665: switch (typ(x))
! 666: {
! 667: case t_INT: case t_FRAC: case t_FRACN:
! 668: case t_POL: case t_COL:
! 669: x = basistoalg(bnf,x); break;
! 670: case t_POLMOD: break;
! 671: default: err(typeer,"bnfissunit");
! 672: }
! 673: v = NULL;
! 674: if ( (w = make_unit(bnf, suni, &x)) ) v = isunit(bnf, x);
! 675: if (!v || lg(v) == 1) { avma = av; return cgetg(1,t_COL); }
! 676: return gerepileupto(av, concat(v, w));
1.1 noro 677: }
678:
1.2 ! noro 679: static void
! 680: pr_append(GEN nf, GEN rel, GEN p, GEN *prod, GEN *S1, GEN *S2)
1.1 noro 681: {
1.2 ! noro 682: if (divise(*prod, p)) return;
! 683: *prod = mulii(*prod, p);
! 684: *S1 = concatsp(*S1, primedec(nf,p));
! 685: *S2 = concatsp(*S2, primedec(rel,p));
! 686: }
1.1 noro 687:
1.2 ! noro 688: static void
! 689: fa_pr_append(GEN nf,GEN rel,GEN N,GEN *prod,GEN *S1,GEN *S2)
! 690: {
! 691: if (!is_pm1(N))
1.1 noro 692: {
1.2 ! noro 693: GEN v = (GEN)factor(N)[1];
! 694: long i, l = lg(v);
! 695: for (i=1; i<l; i++) pr_append(nf,rel,(GEN)v[i],prod,S1,S2);
1.1 noro 696: }
1.2 ! noro 697: }
1.1 noro 698:
1.2 ! noro 699: static GEN
! 700: pol_up(GEN rnfeq, GEN x)
! 701: {
! 702: long i, l = lgef(x);
! 703: GEN y = cgetg(l, t_POL); y[1] = x[1];
! 704: for (i=1; i<l; i++) y[i] = (long)rnfelementreltoabs(rnfeq, (GEN)x[i]);
! 705: return y;
! 706: }
1.1 noro 707:
1.2 ! noro 708: GEN
! 709: rnfisnorminit(GEN T, GEN relpol, int galois)
! 710: {
! 711: gpmem_t av = avma;
! 712: long i, l, drel;
! 713: GEN prod, S1, S2, gen, cyc, bnf, nf, nfrel, rnfeq, rel, res, k, polabs;
! 714: GEN y = cgetg(9, t_VEC);
! 715:
! 716: T = get_bnfpol(T, &bnf, &nf);
! 717: if (!bnf) bnf = bnfinit0(nf? nf: T, 1, NULL, DEFAULTPREC);
! 718: if (!nf) nf = checknf(bnf);
! 719:
! 720: relpol = get_bnfpol(relpol, &rel, &nfrel);
! 721: drel = degpol(relpol);
! 722:
! 723: rnfeq = NULL; /* no reltoabs needed */
! 724: if (degpol(nf[1]) == 1)
! 725: { /* over Q */
! 726: polabs = lift(relpol);
! 727: k = gzero;
! 728: }
! 729: else
1.1 noro 730: {
1.2 ! noro 731: if (galois == 2 && drel > 2)
! 732: { /* needs reltoabs */
! 733: rnfeq = rnfequation2(bnf, relpol);
! 734: polabs = (GEN)rnfeq[1];
! 735: k = (GEN)rnfeq[3];
! 736: }
! 737: else
! 738: {
! 739: long sk;
! 740: polabs = _rnfequation(bnf, relpol, &sk, NULL);
! 741: k = stoi(sk);
! 742: }
1.1 noro 743: }
1.2 ! noro 744: if (!rel || !gcmp0(k)) rel = bnfinit0(polabs, 1, NULL, nfgetprec(nf));
! 745: if (!nfrel) nfrel = checknf(rel);
1.1 noro 746:
1.2 ! noro 747: if (galois < 0 || galois > 2) err(flagerr, "rnfisnorminit");
! 748: if (galois == 2)
1.1 noro 749: {
1.2 ! noro 750: GEN P = rnfeq? pol_up(rnfeq, relpol): relpol;
! 751: galois = nfisgalois(gsubst(nfrel, varn(P), polx[varn(T)]), P);
1.1 noro 752: }
753:
1.2 ! noro 754: prod = gun; S1 = S2 = cgetg(1, t_VEC);
! 755: res = gmael(rel,8,1);
! 756: cyc = (GEN)res[2];
! 757: gen = (GEN)res[3]; l = lg(cyc);
! 758: for(i=1; i<l; i++)
! 759: {
! 760: if (cgcd(smodis((GEN)cyc[i], drel), drel) == 1) break;
! 761: fa_pr_append(nf,rel,gmael3(gen,i,1,1),&prod,&S1,&S2);
! 762: }
! 763: if (!galois)
1.1 noro 764: {
1.2 ! noro 765: GEN Ndiscrel = diviiexact((GEN)nfrel[3], gpowgs((GEN)nf[3], drel));
! 766: fa_pr_append(nf,rel,absi(Ndiscrel), &prod,&S1,&S2);
1.1 noro 767: }
768:
1.2 ! noro 769: y[1] = (long)bnf;
! 770: y[2] = (long)rel;
! 771: y[3] = (long)relpol;
! 772: y[4] = (long)get_theta_abstorel(T, relpol, k);
! 773: y[5] = (long)prod;
! 774: y[6] = (long)S1;
! 775: y[7] = (long)S2;
! 776: y[8] = lstoi(galois); return gerepilecopy(av, y);
! 777: }
1.1 noro 778:
1.2 ! noro 779: /* T as output by rnfisnorminit
! 780: * if flag=0 assume extension is Galois (==> answer is unconditional)
! 781: * if flag>0 add to S all primes dividing p <= flag
! 782: * if flag<0 add to S all primes dividing abs(flag)
1.1 noro 783:
1.2 ! noro 784: * answer is a vector v = [a,b] such that
! 785: * x = N(a)*b and x is a norm iff b = 1 [assuming S large enough] */
! 786: GEN
! 787: rnfisnorm(GEN T, GEN x, long flag)
! 788: {
! 789: gpmem_t av = avma;
! 790: GEN bnf = (GEN)T[1], rel = (GEN)T[2], relpol = (GEN)T[3], theta = (GEN)T[4];
! 791: GEN nf, aux, H, Y, M, A, suni, sunitrel, futu, tu, w;
! 792: GEN prod, S1, S2;
! 793: GEN res = cgetg(3,t_VEC);
! 794: long L, i, drel, itu;
! 795:
! 796: if (typ(T) != t_VEC || lg(T) != 9)
! 797: err(talker,"please apply rnfisnorminit first");
! 798: bnf = checkbnf(bnf);
! 799: rel = checkbnf(rel);
! 800: nf = checknf(bnf);
! 801: x = basistoalg(nf,x);
! 802: if (typ(x) != t_POLMOD) err(typeer, "rnfisnorm");
! 803: drel = degpol(relpol);
! 804: if (gcmp0(x) || gcmp1(x) || (gcmp_1(x) && odd(drel)))
! 805: {
! 806: res[1] = (long)x;
! 807: res[2] = un; return res;
! 808: }
! 809:
! 810: /* build set T of ideals involved in the solutions */
! 811: prod = (GEN)T[5];
! 812: S1 = (GEN)T[6];
! 813: S2 = (GEN)T[7];
! 814: if (flag && !gcmp0((GEN)T[8]))
! 815: err(warner,"useless flag in rnfisnorm: the extension is Galois");
! 816: if (flag > 0)
! 817: {
! 818: byteptr d = diffptr;
! 819: long p = 0;
! 820: if (maxprime() < flag) err(primer1);
! 821: for(;;)
! 822: {
! 823: NEXT_PRIME_VIADIFF(p, d);
! 824: if (p > flag) break;
! 825: pr_append(nf,rel,stoi(p),&prod,&S1,&S2);
! 826: }
! 827: }
! 828: else if (flag < 0)
! 829: fa_pr_append(nf,rel,stoi(-flag),&prod,&S1,&S2);
! 830: /* overkill: prime ideals dividing x would be enough */
! 831: fa_pr_append(nf,rel,idealnorm(nf,x), &prod,&S1,&S2);
! 832:
! 833: /* computation on T-units */
! 834: w = gmael3(rel,8,4,1);
! 835: tu = gmael3(rel,8,4,2);
! 836: futu = concatsp(check_units(rel,"rnfisnorm"), tu);
! 837: suni = bnfsunit(bnf,S1,3);
! 838: sunitrel = (GEN)bnfsunit(rel,S2,3)[1];
! 839: if (lg(sunitrel) > 1) sunitrel = lift_intern(basistoalg(rel,sunitrel));
! 840: sunitrel = concatsp(futu, sunitrel);
! 841:
! 842: A = lift(bnfissunit(bnf,suni,x));
! 843: L = lg(sunitrel);
! 844: itu = lg(nf[6])-1; /* index of torsion unit in bnfsunit(nf) output */
! 845: M = cgetg(L+1,t_MAT);
! 846: for (i=1; i<L; i++)
! 847: {
! 848: GEN u = poleval((GEN)sunitrel[i], theta); /* abstorel */
! 849: if (typ(u) != t_POLMOD) u = to_polmod(u, (GEN)theta[1]);
! 850: sunitrel[i] = (long)u;
! 851: u = bnfissunit(bnf,suni, gnorm(u));
! 852: if (lg(u) == 1) err(bugparier,"rnfisnorm");
! 853: u[itu] = llift((GEN)u[itu]); /* lift root of 1 part */
! 854: M[i] = (long)u;
! 855: }
! 856: aux = zerocol(lg(A)-1); aux[itu] = (long)w;
! 857: M[L] = (long)aux;
! 858: H = hnfall0(M, 0);
! 859: Y = gmul((GEN)H[2], inverseimage((GEN)H[1],A));
! 860: /* Y: sols of MY = A over Q */
! 861: setlg(Y, L);
! 862: aux = factorback(sunitrel, gfloor(Y));
! 863: x = gdiv(x, gnorm(gmodulcp(lift_intern(aux), relpol)));
! 864: if (typ(x) == t_POLMOD && (typ(x[2]) != t_POL || !degpol(x[2])))
1.1 noro 865: {
866: x = (GEN)x[2]; /* rational number */
867: if (typ(x) == t_POL) x = (GEN)x[2];
868: }
1.2 ! noro 869: if (typ(aux) == t_POLMOD && degpol(nf[1]) == 1)
! 870: aux[2] = (long)lift_intern((GEN)aux[2]);
! 871: res[1] = (long)aux;
! 872: res[2] = (long)x;
! 873: return gerepilecopy(av, res);
1.1 noro 874: }
875:
876: GEN
877: bnfisnorm(GEN bnf,GEN x,long flag,long PREC)
878: {
1.2 ! noro 879: gpmem_t av = avma;
! 880: GEN T = rnfisnorminit(polx[MAXVARN], bnf, flag == 0? 1: 2);
! 881: return gerepileupto(av, rnfisnorm(T, x, flag));
1.1 noro 882: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>