Annotation of OpenXM_contrib/pari/src/basemath/arith1.c, Revision 1.1.1.1
1.1 maekawa 1: /*********************************************************************/
2: /** **/
3: /** ARITHMETIC FUNCTIONS **/
4: /** (first part) **/
5: /** **/
6: /*********************************************************************/
7: /* $Id: arith1.c,v 1.2 1999/09/23 17:50:55 karim Exp $ */
8: #include "pari.h"
9:
10: /*********************************************************************/
11: /** **/
12: /** ARITHMETIC FUNCTION PROTOTYPES **/
13: /** **/
14: /*********************************************************************/
15: GEN
16: garith_proto(GEN f(GEN), GEN x, int do_error)
17: {
18: long tx=typ(x),lx,i;
19: GEN y;
20:
21: if (is_matvec_t(tx))
22: {
23: lx=lg(x); y=cgetg(lx,tx);
24: for (i=1; i<lx; i++) y[i] = (long) garith_proto(f,(GEN) x[i], do_error);
25: return y;
26: }
27: if (tx != t_INT && do_error) err(arither1);
28: return f(x);
29: }
30:
31: GEN
32: arith_proto(long f(GEN), GEN x, int do_error)
33: {
34: long tx=typ(x),lx,i;
35: GEN y;
36:
37: if (is_matvec_t(tx))
38: {
39: lx=lg(x); y=cgetg(lx,tx);
40: for (i=1; i<lx; i++) y[i] = (long) arith_proto(f,(GEN) x[i], do_error);
41: return y;
42: }
43: if (tx != t_INT && do_error) err(arither1);
44: return stoi(f(x));
45: }
46:
47: static GEN
48: arith_proto2(long f(GEN,GEN), GEN x, GEN n)
49: {
50: long l,i,tx = typ(x);
51: GEN y;
52:
53: if (is_matvec_t(tx))
54: {
55: l=lg(x); y=cgetg(l,tx);
56: for (i=1; i<l; i++) y[i] = (long) arith_proto2(f,(GEN) x[i],n);
57: return y;
58: }
59: if (tx != t_INT) err(arither1);
60: tx=typ(n);
61: if (is_matvec_t(tx))
62: {
63: l=lg(n); y=cgetg(l,tx);
64: for (i=1; i<l; i++) y[i] = (long) arith_proto2(f,x,(GEN) n[i]);
65: return y;
66: }
67: if (tx != t_INT) err(arither1);
68: return stoi(f(x,n));
69: }
70:
71: static GEN
72: arith_proto2gs(long f(GEN,long), GEN x, long y)
73: {
74: long l,i,tx = typ(x);
75: GEN t;
76:
77: if (is_matvec_t(tx))
78: {
79: l=lg(x); t=cgetg(l,tx);
80: for (i=1; i<l; i++) t[i]= (long) arith_proto2gs(f,(GEN) x[i],y);
81: return t;
82: }
83: if (tx != t_INT) err(arither1);
84: return stoi(f(x,y));
85: }
86:
87: GEN
88: garith_proto2gs(GEN f(GEN,long), GEN x, long y)
89: {
90: long l,i,tx = typ(x);
91: GEN t;
92:
93: if (is_matvec_t(tx))
94: {
95: l=lg(x); t=cgetg(l,tx);
96: for (i=1; i<l; i++) t[i]= (long) garith_proto2gs(f,(GEN) x[i],y);
97: return t;
98: }
99: if (tx != t_INT) err(arither1);
100: return f(x,y);
101: }
102:
103: /*********************************************************************/
104: /** **/
105: /** BINARY DECOMPOSITION **/
106: /** **/
107: /*********************************************************************/
108:
109: GEN
110: binaire(GEN x)
111: {
112: ulong m,u;
113: long i,lx,ex,ly,tx=typ(x);
114: GEN y,p1,p2;
115:
116: switch(tx)
117: {
118: case t_INT:
119: lx=lgefint(x);
120: if (lx==2) { y=cgetg(2,t_VEC); y[1]=zero; return y; }
121: ly = BITS_IN_LONG+1; m=HIGHBIT; u=x[2];
122: while (!(m & u)) { m>>=1; ly--; }
123: y = cgetg(ly+((lx-3)<<TWOPOTBITS_IN_LONG),t_VEC); ly=1;
124: do { y[ly] = m & u ? un : zero; ly++; } while (m>>=1);
125: for (i=3; i<lx; i++)
126: {
127: m=HIGHBIT; u=x[i];
128: do { y[ly] = m & u ? un : zero; ly++; } while (m>>=1);
129: }
130: break;
131:
132: case t_REAL:
133: ex=expo(x);
134: if (!signe(x))
135: {
136: lx=1+max(-ex,0); y=cgetg(lx,t_VEC);
137: for (i=1; i<lx; i++) y[i]=zero;
138: return y;
139: }
140:
141: lx=lg(x); y=cgetg(3,t_VEC);
142: if (ex > bit_accuracy(lx)) err(talker,"loss of precision in binary");
143: p1 = cgetg(max(ex,0)+2,t_VEC);
144: p2 = cgetg(bit_accuracy(lx)-ex,t_VEC);
145: y[1] = (long) p1; y[2] = (long) p2;
146: ly = -ex; ex++;
147: if (ex<=0)
148: {
149: p1[1]=zero; for (i=1; i <= -ex; i++) p2[i]=zero;
150: i=2; m=HIGHBIT;
151: }
152: else
153: {
154: ly=1;
155: for (i=2; i<lx && ly<=ex; i++)
156: {
157: m=HIGHBIT; u=x[i];
158: do
159: { p1[ly] = (m & u) ? un : zero; ly++; }
160: while ((m>>=1) && ly<=ex);
161: }
162: ly=1;
163: if (m) i--; else m=HIGHBIT;
164: }
165: for (; i<lx; i++)
166: {
167: u=x[i];
168: do { p2[ly] = m & u ? un : zero; ly++; } while (m>>=1);
169: m=HIGHBIT;
170: }
171: break;
172:
173: case t_VEC: case t_COL: case t_MAT:
174: lx=lg(x); y=cgetg(lx,tx);
175: for (i=1; i<lx; i++) y[i]=(long)binaire((GEN)x[i]);
176: break;
177: default: err(typeer,"binaire"); return NULL; /* not reached */
178: }
179: return y;
180: }
181:
182: /* Renvoie 0 ou 1 selon que le bit numero n de x est a 0 ou 1 */
183: long
184: bittest(GEN x, long n)
185: {
186: long l;
187:
188: if (!signe(x) || n<0) return 0;
189: l = lgefint(x)-1-(n>>TWOPOTBITS_IN_LONG);
190: if (l<=1) return 0;
191: n = (1L << (n & (BITS_IN_LONG-1))) & x[l];
192: return n? 1: 0;
193: }
194:
195: static long
196: bittestg(GEN x, GEN n)
197: {
198: return bittest(x,itos(n));
199: }
200:
201: GEN
202: gbittest(GEN x, GEN n)
203: {
204: return arith_proto2(bittestg,x,n);
205: }
206:
207: /*********************************************************************/
208: /** **/
209: /** ORDER of INTEGERMOD x in (Z/nZ)* **/
210: /** **/
211: /*********************************************************************/
212:
213: GEN
214: order(GEN x)
215: {
216: long av=avma,av1,i,e;
217: GEN o,m,p;
218:
219: if (typ(x) != t_INTMOD || !gcmp1(mppgcd((GEN) x[1],(GEN) x[2])))
220: err(talker,"not an element of (Z/nZ)* in order");
221: o=phi((GEN) x[1]); m=decomp(o);
222: for (i = lg(m[1])-1; i; i--)
223: {
224: p=gcoeff(m,i,1); e=itos(gcoeff(m,i,2));
225: do
226: {
227: GEN o1=divii(o,p), y=powgi(x,o1);
228: if (!gcmp1((GEN)y[2])) break;
229: e--; o = o1;
230: }
231: while (e);
232: }
233: av1=avma; return gerepile(av,av1,icopy(o));
234: }
235:
236: /******************************************************************/
237: /* */
238: /* GENERATOR of (Z/mZ)* */
239: /* */
240: /******************************************************************/
241:
242: GEN
243: ggener(GEN m)
244: {
245: return garith_proto(gener,m,1);
246: }
247:
248: GEN
249: gener(GEN m)
250: {
251: long av=avma,av1,k,i,e;
252: GEN x,t,q,p;
253:
254: if (typ(m) != t_INT) err(arither1);
255: e = signe(m);
256: if (!e) err(talker,"zero modulus in znprimroot");
257: if (is_pm1(m)) { avma=av; return gmodulss(0,1); }
258: if (e<0) m = absi(m);
259:
260: e = mod4(m);
261: if (e == 0) /* m = 0 mod 4 */
262: {
263: if (cmpis(m,4)) err(generer); /* m != 4, non cyclic */
264: return gmodulsg(3,m);
265: }
266: if (e == 2) /* m = 0 mod 2 */
267: {
268: q=shifti(m,-1); x = (GEN) gener(q)[2];
269: if (!mod2(x)) x = addii(x,q);
270: av1=avma; return gerepile(av,av1,gmodulcp(x,m));
271: }
272:
273: t=decomp(m); if (lg(t[1]) != 2) err(generer);
274: p=gcoeff(t,1,1); e=itos(gcoeff(t,1,2)); q=subis(p,1);
275: if (e>=2)
276: {
277: x = (GEN) gener(p)[2];
278: if (gcmp1(powmodulo(x,q, sqri(p)))) x = addii(x,p);
279: av1=avma; return gerepile(av,av1,gmodulcp(x,m));
280: }
281:
282: p=(GEN)decomp(q)[1]; k=lg(p)-1; x=stoi(1);
283: for(;;)
284: {
285: x[2]++;
286: if (gcmp1(mppgcd(m,x)))
287: {
288: for (i=k; i; i--)
289: if (gcmp1(powmodulo(x, divii(q,(GEN)p[i]), m))) break;
290: if (!i) break;
291: }
292: }
293: av1=avma; return gerepile(av,av1,gmodulcp(x,m));
294: }
295:
296: GEN
297: znstar(GEN n)
298: {
299: GEN p1,z,q,u,v,d,list,ep,h,gen,moduli,p,a;
300: long i,j,nbp,sizeh,av,tetpil;
301:
302: if (typ(n) != t_INT) err(arither1);
303: if (!signe(n))
304: {
305: z=cgetg(4,t_VEC);
306: z[1]=deux; p1=cgetg(2,t_VEC);
307: z[2]=(long)p1; p1[1]=deux; p1=cgetg(2,t_VEC);
308: z[3]=(long)p1; p1[1]=lneg(gun);
309: return z;
310: }
311: av=avma; n=absi(n);
312: if (cmpis(n,2)<=0)
313: {
314: avma=av; z=cgetg(4,t_VEC);
315: z[1]=un;
316: z[2]=lgetg(1,t_VEC);
317: z[3]=lgetg(1,t_VEC);
318: return z;
319: }
320: list=factor(n); ep=(GEN)list[2]; list=(GEN)list[1]; nbp=lg(list)-1;
321: h = cgetg(nbp+2,t_VEC);
322: gen = cgetg(nbp+2,t_VEC);
323: moduli = cgetg(nbp+2,t_VEC);
324: switch(mod8(n))
325: {
326: case 0:
327: h[1] = lmul2n(gun,itos((GEN)ep[1])-2); h[2] = deux;
328: gen[1] = lstoi(5); gen[2] = laddis(gmul2n((GEN)h[1],1),-1);
329: moduli[1] = moduli[2] = lmul2n(gun,itos((GEN)ep[1]));
330: sizeh = nbp+1; i=3; j=2; break;
331: case 4:
332: h[1] = deux;
333: gen[1] = lstoi(3);
334: moduli[1] = lmul2n(gun,itos((GEN)ep[1]));
335: sizeh = nbp; i=j=2; break;
336: case 2: case 6:
337: sizeh = nbp-1; i=1; j=2; break;
338: case 1: case 3: case 5: case 7:
339: sizeh = nbp; i=j=1; break;
340: }
341: for ( ; j<=nbp; i++,j++)
342: {
343: p = (GEN)list[j]; q = gpuigs(p, itos((GEN)ep[j])-1);
344: h[i] = lmulii(addis(p,-1),q); p1 = mulii(p,q);
345: gen[i] = gener(p1)[2];
346: moduli[i] = (long)p1;
347: }
348: #if 0
349: if (nbp == 1 && is_pm1(ep[1]))
350: gen[1] = lmodulcp((GEN)gen[1],n);
351: else
352: #endif
353: for (i=1; i<=sizeh; i++)
354: {
355: q = (GEN)moduli[i]; a = (GEN)gen[i];
356: u = mpinvmod(q,divii(n,q));
357: gen[i] = lmodulcp(addii(a,mulii(mulii(subsi(1,a),u),q)), n);
358: }
359:
360: for (i=sizeh; i>=2; i--)
361: for (j=i-1; j>=1; j--)
362: if (!divise((GEN)h[j],(GEN)h[i]))
363: {
364: d=bezout((GEN)h[i],(GEN)h[j],&u,&v);
365: q=divii((GEN)h[j],d);
366: h[j]=(long)mulii((GEN)h[i],q); h[i]=(long)d;
367: gen[j]=ldiv((GEN)gen[j], (GEN)gen[i]);
368: gen[i]=lmul((GEN)gen[i], powgi((GEN)gen[j], mulii(v,q)));
369: }
370: q=gun; for (i=1; i<=sizeh && !gcmp1((GEN)h[i]); i++) q=mulii(q,(GEN)h[i]);
371: setlg(h,i); setlg(gen,i); z=cgetg(4,t_VEC);
372: z[1]=(long)q; z[2]=(long)h; z[3]=(long)gen;
373: tetpil=avma; return gerepile(av,tetpil,gcopy(z));
374: }
375:
376: /*********************************************************************/
377: /** **/
378: /** INTEGRAL SQUARE ROOT **/
379: /** **/
380: /*********************************************************************/
381:
382: GEN
383: gracine(GEN a)
384: {
385: return garith_proto(racine,a,1); /* hm. --GN */
386: }
387:
388: GEN
389: racine(GEN a)
390: {
391: GEN x,y,z;
392: long av,tetpil,k;
393:
394: if (typ(a) != t_INT) err(arither1);
395: switch (signe(a))
396: {
397: case 0: return gzero;
398: case -1:
399: x=cgetg(3,t_COMPLEX); x[1]=zero;
400: setsigne(a,1); x[2]= (long) racine(a); setsigne(a,-1);
401: return x;
402:
403: case 1:
404: av=avma; k = (long) sqrt((double)(ulong)a[2]);
405: x = shifti(stoi(k+1), (lgefint(a)-3)*(BITS_IN_LONG/2));
406: do
407: {
408: z = shifti(addii(x,divii(a,x)), -1);
409: y = x; x = z;
410: }
411: while (cmpii(x,y) < 0);
412: tetpil=avma; return gerepile(av,tetpil,icopy(y));
413: }
414: return NULL; /* not reached */
415: }
416:
417: /*********************************************************************/
418: /** **/
419: /** PERFECT SQUARE **/
420: /** **/
421: /*********************************************************************/
422:
423: long
424: carrecomplet(GEN x, GEN *pt)
425: {
426: static int carresmod64[]={
427: 1,1,0,0,1,0,0,0,0,1, 0,0,0,0,0,0,1,1,0,0,
428: 0,0,0,0,0,1,0,0,0,0, 0,0,0,1,0,0,1,0,0,0,
429: 0,1,0,0,0,0,0,0,0,1, 0,0,0,0,0,0,0,1,0,0,
430: 0,0,0,0};
431: static int carresmod63[]={
432: 1,1,0,0,1,0,0,1,0,1, 0,0,0,0,0,0,1,0,1,0,
433: 0,0,1,0,0,1,0,0,1,0, 0,0,0,0,0,0,1,1,0,0,
434: 0,0,0,1,0,0,1,0,0,1, 0,0,0,0,0,0,0,0,1,0,
435: 0,0,0};
436: static int carresmod65[]={
437: 1,1,0,0,1,0,0,0,0,1, 1,0,0,0,1,0,1,0,0,0,
438: 0,0,0,0,0,1,1,0,0,1, 1,0,0,0,0,1,1,0,0,1,
439: 1,0,0,0,0,0,0,0,0,1, 0,1,0,0,0,1,1,0,0,0,
440: 0,1,0,0,1};
441: static int carresmod11[]={1,1,0,1,1,1,0,0,0,1,0};
442:
443: long av;
444: GEN y;
445:
446: switch(signe(x))
447: {
448: case -1: return 0;
449: case 0: if (pt) *pt=gzero; return 1;
450: case 1: if (!carresmod64[mod64(x)]) return 0;
451: }
452: if (!carresmod63[smodis(x,63)]) return 0;
453: if (!carresmod65[smodis(x,65)]) return 0;
454: if (!carresmod11[smodis(x,11)]) return 0;
455: av=avma; y=racine(x);
456: if (!egalii(sqri(y),x)) { avma=av; return 0; }
457: if (pt) { *pt = y; avma=(long)y; } else avma=av;
458: return 1;
459: }
460:
461: static GEN
462: polcarrecomplet(GEN x, GEN *pt)
463: {
464: long i,l,av,av2;
465: GEN y,a,b;
466:
467: if (!signe(x)) return gun;
468: l=lgef(x); if ((l&1) == 0) return gzero; /* odd degree */
469: i=2; while (isexactzero((GEN)x[i])) i++;
470: if (i&1) return gzero;
471: av2 = avma; a = (GEN)x[i];
472: switch (typ(a))
473: {
474: case t_POL: case t_INT:
475: y = gcarrecomplet(a,&b); break;
476: default:
477: y = gcarreparfait(a); b = NULL; break;
478: }
479: if (y == gzero) { avma = av2; return gzero; }
480: av = avma; x = gdiv(x,a);
481: y = gtrunc(gsqrt(greffe(x,l,1),0)); av2 = avma;
482: if (!gegal(gsqr(y), x)) { avma=av; return gzero; }
483: if (pt)
484: {
485: avma = av2;
486: if (!gcmp1(a))
487: {
488: if (!b) b = gsqrt(a,DEFAULTPREC);
489: y = gmul(b,y);
490: }
491: *pt = gerepileupto(av,y);
492: }
493: else avma = av;
494: return gun;
495: }
496:
497: GEN
498: gcarrecomplet(GEN x, GEN *pt)
499: {
500: long tx = typ(x),l,i;
501: GEN z,y,p,t;
502:
503: if (!pt) return gcarreparfait(x);
504: if (is_matvec_t(tx))
505: {
506: l=lg(x); y=cgetg(l,tx); z=cgetg(l,tx);
507: for (i=1; i<l; i++)
508: {
509: t=gcarrecomplet((GEN)x[i],&p);
510: y[i] = (long)t;
511: z[i] = gcmp0(t)? zero: (long)p;
512: }
513: *pt=z; return y;
514: }
515: if (tx == t_POL) return polcarrecomplet(x,pt);
516: if (tx != t_INT) err(arither1);
517: return stoi(carrecomplet(x,pt));
518: }
519:
520: GEN
521: gcarreparfait(GEN x)
522: {
523: GEN p1,p2,p3,p4;
524: long tx=typ(x),l,i,av,v;
525:
526: switch(tx)
527: {
528: case t_INT:
529: return carreparfait(x)? gun: gzero;
530:
531: case t_REAL:
532: return (signe(x)>=0)? gun: gzero;
533:
534: case t_INTMOD:
535: if (!signe(x[2])) return gun;
536: av=avma; p1=factor(absi((GEN)x[1]));
537: p2=(GEN)p1[1]; l=lg(p2); p3=(GEN)p1[2];
538: for (i=1; i<l; i++)
539: {
540: v = pvaluation((GEN)x[2],(GEN)p2[i],&p4);
541: if (v < itos((GEN)p3[i]))
542: {
543: if (v&1) break;
544: if (!egalii((GEN)p2[i], gdeux))
545: { if (kronecker(p4,(GEN)p2[i]) == -1) break; }
546: else
547: {
548: v = itos((GEN)p3[i]) - v;
549: if ((v>=3 && mod8(p4) != 1 ) ||
550: (v==2 && mod4(p4) != 1)) break;
551: }
552: }
553: }
554: avma=av; return i<l? gzero: gun;
555:
556: case t_FRAC: case t_FRACN:
557: av=avma; l=carreparfait(mulii((GEN)x[1],(GEN)x[2]));
558: avma=av; return l? gun: gzero;
559:
560: case t_COMPLEX:
561: return gun;
562:
563: case t_PADIC:
564: p4=(GEN)x[4]; if (!signe(p4)) return gun;
565: if (valp(x)&1) return gzero;
566: if (cmpis((GEN)x[2],2))
567: return (kronecker((GEN)x[4],(GEN)x[2])== -1)? gzero: gun;
568:
569: v=precp(x); /* here p=2 */
570: if ((v>=3 && mod8(p4) != 1 ) ||
571: (v==2 && mod4(p4) != 1)) return gzero;
572: return gun;
573:
574: case t_POL:
575: return polcarrecomplet(x,NULL);
576:
577: case t_SER:
578: if (!signe(x)) return gun;
579: if (valp(x)&1) return gzero;
580: return gcarreparfait((GEN)x[2]);
581:
582: case t_RFRAC: case t_RFRACN:
583: av=avma;
584: l=itos(gcarreparfait(gmul((GEN)x[1],(GEN)x[2])));
585: avma=av; return stoi(l);
586:
587: case t_QFR: case t_QFI:
588: return gcarreparfait((GEN)x[1]);
589:
590: case t_VEC: case t_COL: case t_MAT:
591: l=lg(x); p1=cgetg(l,tx);
592: for (i=1; i<l; i++) p1[i]=(long)gcarreparfait((GEN)x[i]);
593: return p1;
594: }
595: err(impl,"issquare for this type");
596: return NULL; /* not reached */
597: }
598:
599: /*********************************************************************/
600: /** **/
601: /** KRONECKER SYMBOL **/
602: /** **/
603: /*********************************************************************/
604: #define ome(t) (labs(mod8(t)-4) == 1)
605:
606: GEN
607: gkronecker(GEN x, GEN y)
608: {
609: return arith_proto2(kronecker,x,y);
610: }
611:
612: long
613: kronecker(GEN x, GEN y)
614: {
615: GEN z;
616: long av,r,s=1;
617:
618: av=avma;
619: switch (signe(y))
620: {
621: case -1: y=negi(y); if (signe(x)<0) s= -1; break;
622: case 0: return is_pm1(x);
623: }
624: r=vali(y);
625: if (r)
626: {
627: if (mpodd(x))
628: {
629: if (odd(r) && ome(x)) s= -s;
630: y=shifti(y,-r);
631: }
632: else { avma=av; return 0; }
633: }
634: x=modii(x,y);
635: while (signe(x))
636: {
637: r=vali(x);
638: if (r)
639: {
640: if (odd(r) && ome(y)) s= -s;
641: x=shifti(x,-r);
642: }
643: /* x=3 mod 4 && y=3 mod 4 ? (both are odd here) */
644: if (y[lgefint(y)-1]&2 && x[lgefint(x)-1]&2) s = -s;
645: z=resii(y,x); y=x; x=z;
646: }
647: avma=av; return is_pm1(y)? s: 0;
648: }
649:
650: GEN
651: gkrogs(GEN x, long y)
652: {
653: return arith_proto2gs(krogs,x,y);
654: }
655:
656: long
657: krogs(GEN x, long y)
658: {
659: long av,r,s=1,x1,z;
660:
661: av=avma;
662: if (y<=0)
663: {
664: if (y) { y = -y; if (signe(x)<0) s = -1; }
665: else return is_pm1(x);
666: }
667: r=vals(y);
668: if (r)
669: {
670: if (mpodd(x))
671: {
672: if (odd(r) && ome(x)) s= -s;
673: y>>=r;
674: }
675: else return 0;
676: }
677: x1=smodis(x,y);
678: while (x1)
679: {
680: r=vals(x1);
681: if (r)
682: {
683: if (odd(r) && (labs((y&7)-4)==1)) s= -s;
684: x1>>=r;
685: }
686: if (y&2 && x1&2) s= -s;
687: z=y%x1; y=x1; x1=z;
688: }
689: avma=av; return (y==1)? s: 0;
690: }
691:
692: long
693: krosg(long s, GEN x)
694: {
695: long av = avma, y = kronecker(stoi(s),x);
696: avma = av; return y;
697: }
698:
699: long
700: kross(long x, long y)
701: {
702: long r,s=1,x1,z;
703:
704: if (y<=0)
705: {
706: if (y) { y= -y; if (x<0) s = -1; }
707: else return (labs(x)==1);
708: }
709: r=vals(y);
710: if (r)
711: {
712: if (odd(x))
713: {
714: if (odd(r) && labs((x&7)-4) == 1) s = -s;
715: y>>=r;
716: }
717: else return 0;
718: }
719: x1=x%y; if (x1<0) x1+=y;
720: while (x1)
721: {
722: r=vals(x1);
723: if (r)
724: {
725: if (odd(r) && labs((y&7)-4) == 1) s= -s;
726: x1>>=r;
727: }
728: if (y&2 && x1&2) s= -s;
729: z=y%x1; y=x1; x1=z;
730: }
731: return (y==1)? s: 0;
732: }
733:
734: long
735: hil0(GEN x, GEN y, GEN p)
736: {
737: return p? hil(x,y,p): hil(x,y,gzero);
738: }
739:
740: #define eps(t) (((signe(t)*(t[lgefint(t)-1]))&3)==3)
741: long
742: hil(GEN x, GEN y, GEN p)
743: {
744: long a,b,av,tx,ty,z;
745: GEN p1,p2,u,v;
746:
747: if (gcmp0(x) || gcmp0(y)) return 0;
748: av=avma; tx=typ(x); ty=typ(y);
749: if (tx>ty) { p1=x; x=y; y=p1; a=tx,tx=ty; ty=a; }
750: switch(tx)
751: {
752: case t_INT:
753: switch(ty)
754: {
755: case t_INT:
756: if (signe(p)<=0)
757: return (signe(x)<0 && signe(y)<0)? -1: 1;
758: a = odd(pvaluation(x,p,&u));
759: b = odd(pvaluation(y,p,&v));
760: if (egalii(p,gdeux))
761: {
762: z = (eps(u) && eps(v))? -1: 1;
763: if (a && ome(v)) z= -z;
764: if (b && ome(u)) z= -z;
765: }
766: else
767: {
768: z = (a && b && eps(p))? -1: 1;
769: if (a && kronecker(v,p)<0) z= -z;
770: if (b && kronecker(u,p)<0) z= -z;
771: }
772: avma=av; return z;
773: case t_REAL:
774: return (signe(x)<0 && signe(y)<0)? -1: 1;
775: case t_INTMOD:
776: if (egalii(gdeux,(GEN)y[1])) err(hiler1);
777: return hil(x,(GEN)y[2],(GEN)y[1]);
778: case t_FRAC: case t_FRACN:
779: p1=mulii((GEN)y[1],(GEN)y[2]); z=hil(x,p1,p);
780: avma=av; return z;
781: case t_PADIC:
782: if (egalii(gdeux,(GEN)y[2]) && precp(y) <= 2) err(hiler1);
783: p1 = odd(valp(y))? mulii((GEN)y[2],(GEN)y[4]): (GEN)y[4];
784: z=hil(x,p1,(GEN)y[2]); avma=av; return z;
785: }
786: break;
787:
788: case t_REAL:
789: if (! is_frac_t(ty)) break;
790: if (signe(x) > 0) return 1;
791: return signe(y[1])*signe(y[2]);
792:
793: case t_INTMOD:
794: if (egalii(gdeux,(GEN)y[1])) err(hiler1);
795: switch(ty)
796: {
797: case t_INTMOD:
798: if (!egalii((GEN)x[1],(GEN)y[1])) break;
799: return hil((GEN)x[2],(GEN)y[2],(GEN)x[1]);
800: case t_FRAC: case t_FRACN:
801: return hil((GEN)x[2],y,(GEN)x[1]);
802: case t_PADIC:
803: if (!egalii((GEN)x[1],(GEN)y[2])) break;
804: return hil((GEN)x[2],y,(GEN)x[1]);
805: }
806: break;
807:
808: case t_FRAC: case t_FRACN:
809: p1=mulii((GEN)x[1],(GEN)x[2]);
810: switch(ty)
811: {
812: case t_FRAC: case t_FRACN:
813: p2=mulii((GEN)y[1],(GEN)y[2]);
814: z=hil(p1,p2,p); avma=av; return z;
815: case t_PADIC:
816: z=hil(p1,y,NULL); avma=av; return z;
817: }
818: break;
819:
820: case t_PADIC:
821: if (ty != t_PADIC || !egalii((GEN)x[2],(GEN)y[2])) break;
822: p1 = odd(valp(x))? mulii((GEN)x[2],(GEN)x[4]): (GEN)x[4];
823: p2 = odd(valp(y))? mulii((GEN)y[2],(GEN)y[4]): (GEN)y[4];
824: z=hil(p1,p2,(GEN)x[2]); avma=av; return z;
825: }
826: err(talker,"forbidden or incompatible types in hil");
827: return 0; /* not reached */
828: }
829: #undef eps
830: #undef ome
831:
832: /*******************************************************************/
833: /* */
834: /* SQUARE ROOT MODULO p */
835: /* */
836: /*******************************************************************/
837:
838: #define sqrmod(x,p) (resii(sqri(x),p))
839:
840: /* Assume p is prime. return NULL if (a,p) = -1 */
841: GEN
842: mpsqrtmod(GEN a, GEN p)
843: {
844: long av = avma, av1,tetpil,lim,i,k,e;
845: GEN p1,p2,v,y,w,m1,m;
846:
847: if (typ(a) != t_INT || typ(p) != t_INT) err(arither1);
848: p1=addsi(-1,p); e=vali(p1);
849: if (e == 0) /* p = 2 */
850: {
851: avma = av;
852: if (!signe(a) || !mod2(a)) return gzero;
853: return gun;
854: }
855: p2=shifti(p1,-e);
856: if (e == 1) y = p1;
857: else
858: for (k=2; ; k++)
859: {
860: av1 = avma;
861: m1 = m = powmodulo(stoi(k),p2,p);
862: for (i=1; i<e; i++)
863: if (gcmp1(m=sqrmod(m,p))) break;
864: if (i==e) { y = m1; break; }
865: avma = av1;
866: }
867: /* y contient un generateur de (Z/pZ)* eleve a la puis (p-1)/2^e */
868:
869: p1=shifti(p2,-1); p1=powmodulo(a,p1,p);
870: if (!signe(p1)) { avma=av; return gzero; }
871:
872: p2=mulii(p1,a); v = modii(p2,p);
873: p1=mulii(sqri(p1),a); w = modii(p1,p);
874: lim = stack_lim(av,1);
875: while (!gcmp1(w))
876: {
877: /* if p is not prime, next loop will not end */
878: p1=sqrmod(w,p); for (k=1; !gcmp1(p1); k++) p1 = sqrmod(p1,p);
879: if (k==e) { avma=av; return NULL; }
880: p1=y; for (i=1; i<e-k; i++) p1=sqrmod(p1,p);
881: e = k; v = modii(mulii(p1,v),p);
882: y = sqrmod(p1,p); w = modii(mulii(y,w),p);
883: if (low_stack(lim, stack_lim(av,1)))
884: {
885: GEN *gptr[3];
886: if(DEBUGMEM>1) err(warnmem,"mpsqrtmod");
887: gptr[0]=&y; gptr[1]=&v; gptr[2]=&w;
888: gerepilemany(av,gptr,3);
889: }
890: }
891: p1=subii(p,v); if (cmpii(v,p1)>0) v = p1;
892: tetpil=avma; return gerepile(av,tetpil,icopy(v));
893: }
894:
895: /*********************************************************************/
896: /** **/
897: /** GCD & BEZOUT **/
898: /** **/
899: /*********************************************************************/
900:
901: /* Ultra-fast private ulong gcd for trial divisions. Called with y odd;
902: x can be arbitrary (but will most of the time be smaller than y).
903: Will also be used from inside ifactor2.c, so it's `semi-private' really.
904: --GN */
905:
906: /* Gotos are Harmful, and Programming is a Science. E.W.Dijkstra. */
907: ulong
908: ugcd(ulong x, ulong y) /* assume y&1==1, y > 1 */
909: {
910: if (!x) return y;
911: /* fix up x */
912: while (!(x&1)) x>>=1;
913: if (x==1) return 1;
914: if (x==y) return y;
915: else if (x>y) goto xislarger;/* will be rare, given how we'll use this */
916: /* loop invariants: x,y odd and distinct. */
917: yislarger:
918: if ((x^y)&2) /* ...01, ...11 or vice versa */
919: y=(x>>2)+(y>>2)+1; /* ==(x+y)>>2 except it can't overflow */
920: else /* ...01,...01 or ...11,...11 */
921: y=(y-x)>>2; /* now y!=0 in either case */
922: while (!(y&1)) y>>=1; /* kill any windfall-gained powers of 2 */
923: if (y==1) return 1; /* comparand == return value... */
924: if (x==y) return y; /* this and the next is just one comparison */
925: else if (x<y) goto yislarger;/* else fall through to xislarger */
926:
927: xislarger: /* same as above, seen through a mirror */
928: if ((x^y)&2)
929: x=(x>>2)+(y>>2)+1;
930: else
931: x=(x-y)>>2; /* x!=0 */
932: while (!(x&1)) x>>=1;
933: if (x==1) return 1;
934: if (x==y) return y;
935: else if (x>y) goto xislarger;/* again, a decent [g]cc should notice that
936: it can re-use the comparison */
937: goto yislarger;
938: }
939: /* Gotos are useful, and Programming is an Art. D.E.Knuth. */
940: /* PS: Of course written with Dijkstra's lessons firmly in mind... --GN */
941:
942: /* modified right shift binary algorithm with at most one division */
943: long
944: cgcd(long a,long b)
945: {
946: long v;
947: a=labs(a); if (!b) return a;
948: b=labs(b); if (!a) return b;
949: if (a>b) { a %= b; if (!a) return b; }
950: else { b %= a; if (!b) return a; }
951: v=vals(a|b); a>>=v; b>>=v;
952: if (a==1 || b==1) return 1L<<v;
953: if (b&1)
954: return ((long)ugcd((ulong)a, (ulong)b)) << v;
955: else
956: return ((long)ugcd((ulong)b, (ulong)a)) << v;
957: }
958:
959: /* assume a>b>0, return gcd(a,b) as a GEN (for mppgcd) */
960: static GEN
961: mppgcd_cgcd(ulong a, ulong b)
962: {
963: GEN r = cgeti(3);
964: long v;
965:
966: r[1] = evalsigne(1)|evallgefint(3);
967: a %= b; if (!a) { r[2]=(long)b; return r; }
968: v=vals(a|b); a>>=v; b>>=v;
969: if (a==1 || b==1) { r[2]=(long)(1UL<<v); return r; }
970: if (b&1)
971: r[2] = (long)(ugcd((ulong)a, (ulong)b) << v);
972: else
973: r[2] = (long)(ugcd((ulong)b, (ulong)a) << v);
974: return r;
975: }
976:
977: void mppgcd_plus_minus(GEN x, GEN y, GEN t);
978: ulong mppgcd_resiu(GEN y, ulong x);
979:
980: /* uses modified right-shift binary algorithm now --GN 1998Jul23 */
981: GEN
982: mppgcd(GEN a, GEN b)
983: {
984: long av,v,w;
985: GEN t, p1;
986:
987: if (typ(a) != t_INT || typ(b) != t_INT) err(arither1);
988: switch (absi_cmp(a,b))
989: {
990: case 0: return absi(a);
991: case -1: t=b; b=a; a=t;
992: }
993: if (!signe(b)) return absi(a);
994: /* here |a|>|b|>0. Try single precision first */
995: if (lgefint(a)==3)
996: return mppgcd_cgcd((ulong)a[2], (ulong)b[2]);
997: if (lgefint(b)==3)
998: {
999: ulong u = mppgcd_resiu(a,(ulong)b[2]);
1000: if (!u) return absi(b);
1001: return mppgcd_cgcd((ulong)b[2], u);
1002: }
1003:
1004: /* larger than gcd: "avma=av" gerepile (erasing t) is valid */
1005: av = avma; new_chunk(lgefint(b));
1006: t = resii(a,b);
1007: if (!signe(t)) { avma=av; return absi(b); }
1008:
1009: a = b; b = t;
1010: v = vali(a); a = shifti(a,-v); setsigne(a,1);
1011: w = vali(b); b = shifti(b,-w); setsigne(b,1);
1012: if (w < v) v = w;
1013: switch(absi_cmp(a,b))
1014: {
1015: case 0: avma=av; a=shifti(a,v); return a;
1016: case -1: p1=b; b=a; a=p1;
1017: }
1018: if (is_pm1(b)) { avma=av; return shifti(gun,v); }
1019:
1020: /* we have three consecutive memory locations: a,b,t.
1021: * All computations are done in place */
1022:
1023: /* a and b are odd now, and a>b>1 */
1024: while (lgefint(a) > 3)
1025: {
1026: /* if a=b mod 4 set t=a-b, otherwise t=a+b, then strip powers of 2 */
1027: /* so that t <= (a+b)/4 < a/2 */
1028: mppgcd_plus_minus(a,b, t);
1029: if (is_pm1(t)) { avma=av; return shifti(gun,v); }
1030: switch(absi_cmp(t,b))
1031: {
1032: case -1: p1 = a; a = b; b = t; t = p1; break;
1033: case 1: p1 = a; a = t; t = p1; break;
1034: case 0: avma = av; b=shifti(b,v); return b;
1035: }
1036: }
1037: {
1038: long r[] = {evaltyp(t_INT)|m_evallg(3), evalsigne(1)|evallgefint(3), 0};
1039: r[2] = (long) ugcd((ulong)b[2], (ulong)a[2]);
1040: avma = av; return shifti(r,v);
1041: }
1042: }
1043:
1044: /* Extended bezout. Return d=pgcd(a,b) and &u,&v */
1045: long
1046: cbezout(long a,long b,long *uu,long *vv)
1047: {
1048: long av=avma,v,q,u,t,s, d = labs(a), r = labs(b);
1049: GEN p1;
1050:
1051: if (!b)
1052: {
1053: *vv=0;
1054: if (!a) { *uu=1; return 1; }
1055: if (a<0)
1056: { *uu=-1; return -a; }
1057: else
1058: { *uu= 1; return a; }
1059: }
1060: u=1; t=0;
1061: for(;;)
1062: {
1063: if (!r)
1064: {
1065: if (a<0) u = -u;
1066: p1 = mulss(a,u); s = signe(p1);
1067: if (!s) v = d / b;
1068: else if (!is_bigint(p1))
1069: {
1070: ulong ul;
1071: long sb = (b<0);
1072: b = labs(b);
1073: if (s < 0)
1074: {
1075: ul = (p1[2]+d);
1076: ul /= b; v = sb? -(long)ul: (long)ul;
1077: }
1078: else
1079: {
1080: ul = p1[2]-d;
1081: ul /= b; v = sb? (long)ul: -(long)ul;
1082: }
1083: }
1084: else v = - itos(divis(addsi(-d,p1), b));
1085: avma=av; *uu = u; *vv = v; return d;
1086: }
1087: v=d; d=r; q = v/r; r = v - q*r;
1088: v=t; t = u - q*t; u=v;
1089: }
1090: }
1091:
1092: GEN
1093: bezout(GEN a, GEN b, GEN *ptu, GEN *ptv)
1094: {
1095: GEN u,v,v1,d,d1,q,r, *tmp;
1096: long av;
1097:
1098: if (typ(a) != t_INT || typ(b) != t_INT) err(arither1);
1099: if (absi_cmp(a,b) < 0)
1100: {
1101: u=b; b=a; a=u;
1102: tmp=ptu; ptu=ptv; ptv=tmp;
1103: }
1104: /* now |a| >= |b| */
1105: if (!signe(b))
1106: {
1107: *ptv = gzero;
1108: switch(signe(a))
1109: {
1110: case 0: *ptu = gun; return gzero;
1111: case 1: *ptu = gun; return icopy(a);
1112: case -1: *ptu = negi(gun); return negi(a);
1113: }
1114: }
1115: if (!is_bigint(a))
1116: {
1117: long uu,vv, dd = cbezout(itos(a),itos(b),&uu,&vv);
1118: *ptu = stoi(uu); *ptv = stoi(vv); return stoi(dd);
1119: }
1120: av = avma;
1121: (void)new_chunk(lgefint(b) + (lgefint(a)<<1)); /* room for d, u and v */
1122: d = a; d1 = b; v = gzero; v1 = gun;
1123: for(;;)
1124: {
1125: q=dvmdii(d,d1,&r);
1126: v=subii(v,mulii(q,v1));
1127: u=v; v=v1; v1=u;
1128: u=r; d=d1; d1=u; if (!signe(d1)) break;
1129: }
1130: u = divii(subii(d,mulii(b,v)),a);
1131: avma = av; d = icopy(d); v = icopy(v); u = icopy(u);
1132: if (signe(d) < 0)
1133: {
1134: setsigne(d,1);
1135: setsigne(u,-signe(u));
1136: setsigne(v,-signe(v));
1137: }
1138: *ptu = u; *ptv = v; return d;
1139: }
1140:
1141: /*********************************************************************/
1142: /** **/
1143: /** CHINESE REMAINDERS **/
1144: /** **/
1145: /*********************************************************************/
1146:
1147: /* P.M. & M.H.
1148: *
1149: * Chinese Remainder Theorem. x and y must have the same type (integermod,
1150: * polymod, or polynomial/vector/matrix recursively constructed with these
1151: * as coefficients). Creates (with the same type) a z in the same residue
1152: * class as x and the same residue class as y, if it is possible.
1153: *
1154: * We also allow (during recursion) two identical objects even if they are
1155: * not integermod or polymod. For example, if
1156: *
1157: * x = [1. mod(5, 11), mod(X + mod(2, 7), X^2 + 1)]
1158: * y = [1, mod(7, 17), mod(X + mod(0, 3), X^2 + 1)],
1159: *
1160: * then chinois(x, y) returns
1161: *
1162: * [1, mod(16, 187), mod(X + mod(9, 21), X^2 + 1)]
1163: *
1164: * Someone else may want to allow power series, complex numbers, and
1165: * quadratic numbers.
1166: */
1167: GEN
1168: chinois(GEN x, GEN y)
1169: {
1170: long i,lx,vx,av,tetpil, tx = typ(x);
1171: GEN z,p1,p2,d,u,v;
1172:
1173: if (gegal(x,y)) return gcopy(x);
1174: if (tx == typ(y)) switch(tx)
1175: {
1176: case t_POLMOD:
1177: if (gegal((GEN)x[1],(GEN)y[1])) /* same modulus */
1178: {
1179: z=cgetg(3,tx);
1180: z[1]=lcopy((GEN)x[1]);
1181: z[2]=(long)chinois((GEN)x[2],(GEN)y[2]);
1182: return z;
1183: } /* fall through */
1184: case t_INTMOD:
1185: z=cgetg(3,tx); av=avma;
1186: d=gbezout((GEN)x[1],(GEN)y[1],&u,&v);
1187: if (!gegal(gmod((GEN)x[2],d), gmod((GEN)y[2],d))) break;
1188: p1 = gdiv((GEN)x[1],d);
1189: p2 = gadd((GEN)x[2], gmul(gmul(u,p1), gadd((GEN)y[2],gneg((GEN)x[2]))));
1190:
1191: tetpil=avma; z[1]=lmul(p1,(GEN)y[1]); z[2]=lmod(p2,(GEN)z[1]);
1192: gerepilemanyvec(av,tetpil,z+1,2); return z;
1193:
1194: case t_POL:
1195: lx=lgef(x); vx=varn(x); z=cgetg(lx,tx);
1196: if (lx!=lgef(y) || vx!=varn(y)) break;
1197: z[1]=evalsigne(1)|evallgef(lx)|evalvarn(vx);
1198: for (i=2; i<lx; i++) z[i]=(long)chinois((GEN)x[i],(GEN)y[i]);
1199: return z;
1200:
1201: case t_VEC: case t_COL: case t_MAT:
1202: lx=lg(x); z=cgetg(lx,tx); if (lx!=lg(y)) break;
1203: for (i=1; i<lx; i++) z[i]=(long)chinois((GEN)x[i],(GEN)y[i]);
1204: return z;
1205: }
1206: err(talker,"incompatible arguments in chinois");
1207: return NULL; /* not reached */
1208: }
1209:
1210: /* return lift(chinois(x2 mod x1, y2 mod y1))
1211: * assume(x1,y1)=1, xi,yi integers and z1 = x1*y1
1212: */
1213: GEN
1214: chinois_int_coprime(GEN x2, GEN y2, GEN x1, GEN y1, GEN z1)
1215: {
1216: long av = avma;
1217: GEN ax,p1;
1218: (void)new_chunk((lgefint(z1)<<1)+lgefint(x1)+lgefint(y1));
1219: ax = mulii(mpinvmod(x1,y1), x1);
1220: p1 = addii(x2, mulii(ax, subii(y2,x2)));
1221: avma = av; return modii(p1,z1);
1222: }
1223:
1224: /*********************************************************************/
1225: /** **/
1226: /** INVERSE MODULO b **/
1227: /** **/
1228: /*********************************************************************/
1229:
1230: GEN
1231: mpinvmod(GEN a, GEN m)
1232: {
1233: GEN res;
1234: if (invmod(a,m,&res)) return res;
1235: err(talker,"impossible inverse modulo: %Z",gmodulcp(res,m));
1236: return NULL; /* not reached */
1237: }
1238:
1239: /*********************************************************************/
1240: /** **/
1241: /** POWERING MODULO (a^n mod m) **/
1242: /** **/
1243: /*********************************************************************/
1244:
1245: GEN
1246: powmodulo(GEN a, GEN n, GEN m)
1247: {
1248: GEN y;
1249: long av = avma,av1,lim,*p,man,k,nb;
1250: GEN (*mul)(GEN,GEN) = mulii;
1251:
1252: if (typ(a) != t_INT || typ(n) != t_INT || typ(m) != t_INT) err(arither1);
1253: switch (signe(n))
1254: {
1255: case 0:
1256: k = signe(resii(a,m)); avma=av;
1257: return k? gun: gzero;
1258:
1259: case -1:
1260: a = mpinvmod(a,m); n = absi(n); /* fall through */
1261: case 1:
1262: y = modii(a,m);
1263: if (!signe(y)) { avma=av; return gzero; }
1264: if (lgefint(y)==3)
1265: switch(y[2])
1266: {
1267: case 1: /* y = 1 */
1268: avma=av; return gun;
1269: case 2: /* y = 2, use shifti not mulii */
1270: mul = (GEN (*)(GEN,GEN))shifti; a = (GEN)1;
1271: }
1272: p = n+2; man = *p; /* see puissii */
1273: k = 1+bfffo(man); man<<=k; k = BITS_IN_LONG-k;
1274: av1=avma; lim=stack_lim(av1,1);
1275: for (nb=lgefint(n)-2;;)
1276: {
1277: for (; k; man<<=1,k--)
1278: {
1279: y=resii(sqri(y), m);
1280: if (man<0) y = modii(mul(y,a), m);
1281: if (low_stack(lim, stack_lim(av1,1)))
1282: {
1283: if (DEBUGMEM>1) err(warnmem,"powmodulo");
1284: y = gerepileupto(av1,y);
1285: }
1286: }
1287: if (--nb == 0) break;
1288: man = *++p, k = BITS_IN_LONG;
1289: }
1290: }
1291: return gerepileupto(av,y);
1292: }
1293:
1294: /*********************************************************************/
1295: /** **/
1296: /** NEXT / PRECEDING (PSEUDO) PRIME **/
1297: /** **/
1298: /*********************************************************************/
1299: GEN
1300: gnextprime(GEN n)
1301: {
1302: return garith_proto(nextprime,n,0); /* accept non-integers */
1303: }
1304:
1305: GEN
1306: gprecprime(GEN n)
1307: {
1308: return garith_proto(precprime,n,0); /* accept non-integers */
1309: }
1310:
1311: GEN
1312: gisprime(GEN x)
1313: {
1314: return arith_proto(isprime,x,1);
1315: }
1316:
1317: long
1318: isprime(GEN x)
1319: {
1320: return millerrabin(x,10);
1321: }
1322:
1323: GEN
1324: gispsp(GEN x)
1325: {
1326: return arith_proto(ispsp,x,1);
1327: }
1328:
1329: long
1330: ispsp(GEN x)
1331: {
1332: return millerrabin(x,1);
1333: }
1334:
1335: GEN
1336: gmillerrabin(GEN n, long k)
1337: {
1338: return arith_proto2gs(millerrabin,n,k);
1339: }
1340:
1341: /*********************************************************************/
1342: /** **/
1343: /** FUNDAMENTAL DISCRIMINANTS **/
1344: /** **/
1345: /*********************************************************************/
1346:
1347: /* gissquarefree, issquarefree moved into arith2.c with the other
1348: basic arithmetic functions (issquarefree is the square of the
1349: Moebius mu function, after all...) --GN */
1350:
1351: GEN
1352: gisfundamental(GEN x)
1353: {
1354: return arith_proto(isfundamental,x,1);
1355: }
1356:
1357: long
1358: isfundamental(GEN x)
1359: {
1360: long av,r;
1361: GEN p1;
1362:
1363: if (gcmp0(x)) return 0;
1364: r=mod4(x);
1365: if (!r)
1366: {
1367: av=avma; p1=shifti(x,-2);
1368: r=mod4(p1); if (!r) return 0;
1369: if (signe(x)<0) r=4-r;
1370: r = (r==1)? 0: issquarefree(p1);
1371: avma=av; return r;
1372: }
1373: if (signe(x)<0) r=4-r;
1374: return (r==1) ? issquarefree(x) : 0;
1375: }
1376:
1377: GEN
1378: quaddisc(GEN x)
1379: {
1380: long av=avma,tetpil=avma,i,r,tx=typ(x);
1381: GEN p1,p2,f,s;
1382:
1383: if (tx != t_INT && ! is_frac_t(tx)) err(arither1);
1384: f=factor(x); p1=(GEN)f[1]; p2=(GEN)f[2];
1385: s=gun;
1386: for (i=1; i<lg(p1); i++)
1387: if ( odd(mael(p2,i,2)) ) { tetpil=avma; s=gmul(s,(GEN)p1[i]); }
1388: r=mod4(s); if (gsigne(x)<0) r=4-r;
1389: if (r>1) { tetpil=avma; s=shifti(s,2); }
1390: return gerepile(av,tetpil,s);
1391: }
1392:
1393: /*********************************************************************/
1394: /** **/
1395: /** FACTORIAL **/
1396: /** **/
1397: /*********************************************************************/
1398:
1399: GEN
1400: mpfact(long n)
1401: {
1402: long av,tetpil,lim,k;
1403: GEN f;
1404:
1405: if (n<2)
1406: {
1407: if (n<0) err(facter);
1408: return gun;
1409: }
1410: av = avma; lim = stack_lim(av,1); f = gun;
1411: for (k=2; k<n; k++)
1412: if (low_stack(lim, stack_lim(av,1)))
1413: {
1414: if(DEBUGMEM>1) err(warnmem,"mpfact k=%ld",k);
1415: tetpil = avma; f = gerepile(av,tetpil,mulsi(k,f));
1416: }
1417: else f = mulsi(k,f);
1418: tetpil = avma; return gerepile(av,tetpil,mulsi(k,f));
1419: }
1420:
1421: GEN
1422: mpfactr(long n, long prec)
1423: {
1424: long av,tetpil,lim,k;
1425: GEN f = realun(prec);
1426:
1427: if (n<2)
1428: {
1429: if (n<0) err(facter);
1430: return f;
1431: }
1432: av = avma; lim = stack_lim(av,1);
1433: for (k=2; k<n; k++)
1434: if (low_stack(lim, stack_lim(av,1)))
1435: {
1436: if(DEBUGMEM>1) err(warnmem,"mpfactr k=%ld",k);
1437: tetpil = avma; f = gerepile(av,tetpil,mulsr(k,f));
1438: }
1439: else f = mulsr(k,f);
1440: tetpil = avma; return gerepile(av,tetpil,mulsr(k,f));
1441: }
1442:
1443: /*******************************************************************/
1444: /** **/
1445: /** LUCAS & FIBONACCI **/
1446: /** **/
1447: /*******************************************************************/
1448:
1449: void
1450: lucas(long n, GEN *ln, GEN *ln1)
1451: {
1452: long taille,av;
1453: GEN z,t;
1454:
1455: if (!n) { *ln=stoi(2); *ln1=stoi(1); return; }
1456:
1457: taille=(long)(pariC3*(1+labs(n))+3);
1458: *ln=cgeti(taille); *ln1=cgeti(taille);
1459: av=avma; lucas(n/2,&z,&t);
1460: switch(n % 4)
1461: {
1462: case -3:
1463: addsiz(2,sqri(z),*ln1);
1464: subiiz(addsi(1,mulii(z,t)),*ln1,*ln); break;
1465: case -2:
1466: addsiz(2,sqri(z),*ln); addsiz(1,mulii(z,t),*ln1); break;
1467: case -1:
1468: subisz(sqri(z),2,*ln1);
1469: subiiz(subis(mulii(z,t),1),*ln1,*ln); break;
1470: case 0: subisz(sqri(z),2,*ln); subisz(mulii(z,t),1,*ln1); break;
1471: case 1: subisz(mulii(z,t),1,*ln); addsiz(2,sqri(t),*ln1); break;
1472: case 2: addsiz(2,sqri(z),*ln); addsiz(1,mulii(z,t),*ln1); break;
1473: case 3: addsiz(1,mulii(z,t),*ln); subisz(sqri(t),2,*ln1);
1474: }
1475: avma=av;
1476: }
1477:
1478: GEN
1479: fibo(long n)
1480: {
1481: long av = avma;
1482: GEN ln,ln1;
1483:
1484: lucas(n-1,&ln,&ln1);
1485: return gerepileupto(av, divis(addii(shifti(ln,1),ln1), 5));
1486: }
1487:
1488: /*******************************************************************/
1489: /* */
1490: /* CONTINUED FRACTIONS */
1491: /* */
1492: /*******************************************************************/
1493: static GEN sfcont2(GEN b, GEN x, long k);
1494:
1495: GEN
1496: gcf(GEN x)
1497: {
1498: return sfcont(x,x,0);
1499: }
1500:
1501: GEN
1502: gcf2(GEN b, GEN x)
1503: {
1504: return sfcont0(x,b,0);
1505: }
1506:
1507: GEN
1508: gboundcf(GEN x, long k)
1509: {
1510: return sfcont(x,x,k);
1511: }
1512:
1513: GEN
1514: sfcont0(GEN x, GEN b, long flag)
1515: {
1516: long lb,tb,i;
1517: GEN y;
1518:
1519: if (!b || gcmp0(b)) return sfcont(x,x,flag);
1520: tb = typ(b);
1521: if (tb == t_INT) return sfcont(x,x,itos(b));
1522: if (! is_matvec_t(tb)) err(typeer,"sfcont0");
1523:
1524: lb=lg(b); if (lb==1) return cgetg(1,t_VEC);
1525: if (tb != t_MAT) return sfcont2(b,x,flag);
1526: if (lg(b[1])==1) return sfcont(x,x,flag);
1527: y = (GEN) gpmalloc(lb*sizeof(long));
1528: for (i=1; i<lb; i++) y[i]=coeff(b,1,i);
1529: x = sfcont2(y,x,flag); free(y); return x;
1530: }
1531:
1532: GEN
1533: sfcont(GEN x, GEN x1, long k)
1534: {
1535: long av,lx=lg(x),tx=typ(x),e,i,j,l,l1,l2,lx1,tetpil,f;
1536: GEN y,p1,p2,p3,p4,yp;
1537:
1538: if (is_scalar_t(tx))
1539: {
1540: if (gcmp0(x)) { y=cgetg(2,t_VEC); y[1]=zero; return y; }
1541: switch(tx)
1542: {
1543: case t_INT:
1544: y=cgetg(2,t_VEC); y[1]=lcopy(x); return y;
1545: case t_REAL:
1546: l=avma; p1=cgetg(3,t_FRACN);
1547: p2 = rcopy(x); settyp(p2,t_INT); setlgefint(p2,lx);
1548: p1[1] = (long) p2; e = bit_accuracy(lx)-1-expo(x);
1549: if (e<0) err(talker,"integral part not significant in scfont");
1550:
1551: l1 = (e>>TWOPOTBITS_IN_LONG)+3; p2=cgeti(l1);
1552: p2[1]= evalsigne(1)|evallgefint(l1);
1553: p2[2]= (1L<<(e&(BITS_IN_LONG-1)));
1554: for (i=3; i<l1; i++) p2[i]=0;
1555: p1[2]=(long) p2; p3=cgetg(3,t_FRACN);
1556: p3[2]=lcopy(p2);
1557: p3[1]=laddsi(signe(x),(GEN)p1[1]);
1558: p1=sfcont(p1,p1,k); tetpil=avma;
1559: return gerepile(l,tetpil,sfcont(p3,p1,k));
1560:
1561: case t_FRAC: case t_FRACN:
1562: l=avma; lx1=lgefint(x[2]);
1563: l1 = (long) ((double) BYTES_IN_LONG/4.0*46.093443*(lx1-2)+3);
1564: if (k>0 && l1>k+1) l1=k+1;
1565: if (l1>LGBITS) l1=LGBITS;
1566: if (lgefint(x[1]) >= lx1) p1=icopy((GEN)x[1]);
1567: else affii((GEN)x[1],p1=cgeti(lx1));
1568: p2=icopy((GEN)x[2]); l2=avma; lx1=lg(x1);
1569: y=cgetg(l1,t_VEC); f=(x!=x1); i=0;
1570: while (!gcmp0(p2) && i<=l1-2)
1571: {
1572: i++; y[i]=ldvmdii(p1,p2,&p3);
1573: if (signe(p3)>=0) affii(p3,p1);
1574: else
1575: {
1576: p4=addii(p3,p2); affii(p4,p1); cgiv(p4);
1577: y[1]=laddsi(-1,(GEN)y[1]);
1578: }
1579: cgiv(p3); p4=p1; p1=p2; p2=p4;
1580: if (f)
1581: {
1582: if (i>=lx1) { i--; break; }
1583: if (!egalii((GEN)y[i],(GEN)x1[i]))
1584: {
1585: av=avma;
1586: if (gcmp1(absi(subii((GEN)x1[i],(GEN)y[i]))))
1587: {
1588: if (i>=lx1-1 || !gcmp1((GEN)x1[i+1]))
1589: affii((GEN)x1[i],(GEN)y[i]);
1590: }
1591: else i--;
1592: avma=av; break;
1593: }
1594: }
1595: }
1596: if (i>=2 && gcmp1((GEN)y[i]))
1597: {
1598: cgiv((GEN)y[i]); --i; cgiv((GEN)y[i]);
1599: y[i]=laddsi(1,(GEN)y[i]);
1600: }
1601: setlg(y,i+1); l2=l2-((l1-i-1)<<TWOPOTBYTES_IN_LONG);
1602: return gerepile(l,l2,y);
1603: }
1604: err(typeer,"sfcont");
1605: }
1606:
1607: switch(tx)
1608: {
1609: case t_POL:
1610: y=cgetg(2,t_VEC); y[1]=lcopy(x); break;
1611: case t_SER:
1612: av=avma; p1=gtrunc(x); tetpil=avma;
1613: y=gerepile(av,tetpil,sfcont(p1,p1,k)); break;
1614: case t_RFRAC:
1615: case t_RFRACN:
1616: av=avma; l1=lgef(x[1]); if (lgef(x[2])>l1) l1=lgef(x[2]);
1617: if (k>0 && l1>k+1) l1=k+1;
1618: yp=cgetg(l1,t_VEC); p1=(GEN)x[1]; i=0; p2=(GEN)x[2];
1619: while (!gcmp0(p2) && i<=l1-2)
1620: {
1621: i++; yp[i]=ldivres(p1,p2,&p3);
1622: p1=p2; p2=p3;
1623: }
1624: tetpil=avma; y=cgetg(i+1,t_VEC);
1625: for (j=1; j<=i; j++) y[j]=lcopy((GEN)yp[j]);
1626: y=gerepile(av,tetpil,y); break;
1627: default: err(typeer,"sfcont");
1628: }
1629: return y;
1630: }
1631:
1632: static GEN
1633: sfcont2(GEN b, GEN x, long k)
1634: {
1635: long l1 = lg(b), tx = typ(x), i,tetpil, av = avma;
1636: GEN y,p1;
1637:
1638: if (k)
1639: {
1640: if (k>=l1) err(typeer,"sfcont2");
1641: l1 = k+1;
1642: }
1643: y=cgetg(l1,t_VEC);
1644: if (l1==1) return y;
1645: if (is_scalar_t(tx))
1646: {
1647: if (!is_intreal_t(tx) && !is_frac_t(tx)) err(typeer,"sfcont2");
1648: }
1649: else if (tx == t_SER) x = gtrunc(x);
1650:
1651: if (!gcmp1((GEN)b[1])) x = gmul((GEN)b[1],x);
1652: i = 2; y[1] = lfloor(x); p1 = gsub(x,(GEN)y[1]);
1653: for ( ; i<l1 && !gcmp0(p1); i++)
1654: {
1655: x = gdiv((GEN)b[i],p1);
1656: if (tx == t_REAL)
1657: {
1658: long e = expo(x);
1659: if (e>0 && (e>>TWOPOTBITS_IN_LONG)+3 > lg(x)) break;
1660: }
1661: y[i] = lfloor(x);
1662: p1 = gsub(x,(GEN)y[i]);
1663: }
1664: setlg(y,i); tetpil=avma;
1665: return gerepile(av,tetpil,gcopy(y));
1666: }
1667:
1668: GEN
1669: pnqn(GEN x)
1670: {
1671: long av=avma,tetpil,lx,ly,tx=typ(x),i;
1672: GEN y,p0,p1,q0,q1,a,b,p2,q2;
1673:
1674: if (! is_matvec_t(tx)) err(typeer,"pnqn");
1675: lx=lg(x); if (lx==1) return idmat(2);
1676: p0=gun; q0=gzero;
1677: if (tx != t_MAT)
1678: {
1679: p1=(GEN)x[1]; q1=gun;
1680: for (i=2; i<lx; i++)
1681: {
1682: a=(GEN)x[i];
1683: p2=gadd(gmul(a,p1),p0); p0=p1; p1=p2;
1684: q2=gadd(gmul(a,q1),q0); q0=q1; q1=q2;
1685: }
1686: }
1687: else
1688: {
1689: ly=lg(x[1]);
1690: if (ly==2)
1691: {
1692: p1=cgetg(lx,t_VEC); for (i=1; i<lx; i++) p1[i]=mael(x,i,1);
1693: tetpil=avma; return gerepile(av,tetpil,pnqn(p1));
1694: }
1695: if (ly!=3) err(talker,"incorrect size in pnqn");
1696: p1=gcoeff(x,2,1); q1=gcoeff(x,1,1);
1697: for (i=2; i<lx; i++)
1698: {
1699: a=gcoeff(x,2,i); b=gcoeff(x,1,i);
1700: p2=gadd(gmul(a,p1),gmul(b,p0)); p0=p1; p1=p2;
1701: q2=gadd(gmul(a,q1),gmul(b,q0)); q0=q1; q1=q2;
1702: }
1703: }
1704: tetpil=avma; y=cgetg(3,t_MAT);
1705: p2=cgetg(3,t_COL); y[1]=(long)p2; p2[1]=lcopy(p1); p2[2]=lcopy(q1);
1706: p2=cgetg(3,t_COL); y[2]=(long)p2; p2[1]=lcopy(p0); p2[2]=lcopy(q0);
1707: return gerepile(av,tetpil,y);
1708: }
1709:
1710: GEN
1711: bestappr(GEN x, GEN k)
1712: {
1713: long av=avma,tetpil,tx,tk=typ(k),lx,i,e;
1714: GEN p0,p1,p,q0,q1,q,a,y;
1715:
1716: if (tk != t_INT)
1717: {
1718: if (tk != t_REAL && !is_frac_t(tk))
1719: err(talker,"incorrect bound type in bestappr");
1720: k = gcvtoi(k,&e);
1721: }
1722: if (cmpis(k,1) < 0) k=gun;
1723: tx=typ(x); if (tx == t_FRACN) x = gred(x);
1724: switch(tx)
1725: {
1726: case t_INT:
1727: if (av==avma) return icopy(x);
1728: tetpil=avma; return gerepile(av,tetpil,icopy(x));
1729:
1730: case t_FRAC:
1731: if (cmpii((GEN)x[2],k) <= 0)
1732: {
1733: if (av==avma) return gcopy(x);
1734: tetpil=avma; return gerepile(av,tetpil,gcopy(x));
1735: }
1736:
1737: case t_REAL:
1738: p1=gun; p0=gfloor(x); q1=gzero; q0=gun; a=p0;
1739: while (gcmp(q0,k)<=0)
1740: {
1741: x = gsub(x,a);
1742: if (gcmp0(x)) { p1=p0; q1=q0; break; }
1743:
1744: x = ginv(x); a = (gcmp(x,k)<0)? gfloor(x): k;
1745: p = addii(mulii(a,p0),p1); p1=p0; p0=p;
1746: q = addii(mulii(a,q0),q1); q1=q0; q0=q;
1747: }
1748: tetpil=avma; return gerepile(av,tetpil,gdiv(p1,q1));
1749:
1750: case t_COMPLEX: case t_POL: case t_SER: case t_RFRAC:
1751: case t_RFRACN: case t_VEC: case t_COL: case t_MAT:
1752: lx = (tx==t_POL)? lgef(x): lg(x); y=cgetg(lx,tx);
1753: for (i=1; i<lontyp[tx]; i++) y[i]=x[i];
1754: for ( ; i<lx; i++) y[i]=(long)bestappr((GEN)x[i],k);
1755: return y;
1756: }
1757: err(typeer,"bestappr");
1758: return NULL; /* not reached */
1759: }
1760:
1761: /***********************************************************************/
1762: /** **/
1763: /** FUNDAMENTAL UNIT AND REGULATOR (QUADRATIC FIELDS) **/
1764: /** **/
1765: /***********************************************************************/
1766:
1767: GEN
1768: gfundunit(GEN x)
1769: {
1770: return garith_proto(fundunit,x,1);
1771: }
1772:
1773: static GEN
1774: get_quad(GEN f, GEN pol, long r)
1775: {
1776: GEN y, c=(GEN)f[2], p1=(GEN)c[1], q1=(GEN)c[2];
1777: y=cgetg(4,t_QUAD); y[1]=(long)pol;
1778: y[2]=r? lsubii(p1,q1): (long)p1;
1779: y[3]=(long)q1; return y;
1780: }
1781:
1782: /* replace f by f * [a,1; 1,0] */
1783: static void
1784: update_f(GEN f, GEN a)
1785: {
1786: GEN p1;
1787: p1=gcoeff(f,1,1);
1788: coeff(f,1,1)=laddii(mulii(a,p1), gcoeff(f,1,2));
1789: coeff(f,1,2)=(long)p1;
1790:
1791: p1=gcoeff(f,2,1);
1792: coeff(f,2,1)=laddii(mulii(a,p1), gcoeff(f,2,2));
1793: coeff(f,2,2)=(long)p1;
1794: }
1795:
1796: GEN
1797: fundunit(GEN x)
1798: {
1799: long av = avma, av2,tetpil,lim,r,flp,flq;
1800: GEN pol,y,a,u,v,u1,v1,sqd,f;
1801:
1802: if (typ(x) != t_INT) err(arither1);
1803: if (signe(x)<=0) err(arither2);
1804: r=mod4(x); if (r==2 || r==3) err(funder2,"fundunit");
1805:
1806: sqd=racine(x); av2=avma; lim=stack_lim(av2,2);
1807: a = shifti(addsi(r,sqd),-1);
1808: f=cgetg(3,t_MAT); f[1]=lgetg(3,t_COL); f[2]=lgetg(3,t_COL);
1809: coeff(f,1,1)=(long)a; coeff(f,1,2)=un;
1810: coeff(f,2,1)=un; coeff(f,2,2)=zero;
1811: v = gdeux; u = stoi(r);
1812: for(;;)
1813: {
1814: u1=subii(mulii(a,v),u); flp=egalii(u,u1); u=u1;
1815: v1=divii(subii(x,sqri(u)),v); flq=egalii(v,v1); v=v1;
1816: if (flq) break; a = divii(addii(sqd,u),v);
1817: if (flp) break; update_f(f,a);
1818: if (low_stack(lim, stack_lim(av2,2)))
1819: {
1820: GEN *gptr[4]; gptr[0]=&a; gptr[1]=&f; gptr[2]=&u; gptr[3]=&v;
1821: if(DEBUGMEM>1) err(warnmem,"fundunit");
1822: gerepilemany(av2,gptr,4);
1823: }
1824: }
1825: pol = quadpoly(x); y = get_quad(f,pol,r);
1826: if (!flq) v1 = y; else { update_f(f,a); v1 = get_quad(f,pol,r); }
1827:
1828: u1=gconj(y); tetpil=avma; y=gdiv(v1,u1);
1829: if (signe(y[3]) < 0) { tetpil=avma; y=gneg(y); }
1830: return gerepile(av,tetpil,y);
1831: }
1832:
1833: GEN
1834: gregula(GEN x, long prec)
1835: {
1836: return garith_proto2gs(regula,x,prec);
1837: }
1838:
1839: GEN
1840: regula(GEN x, long prec)
1841: {
1842: long av = avma,av2,tetpil,lim,r,fl,rexp;
1843: GEN ln2,reg,reg1,rsqd,y,u,v,a,u1,v1,sqd;
1844:
1845: if (typ(x) != t_INT) err(arither1);
1846: if (signe(x)<=0) err(arither2);
1847: r=mod4(x); if (r==2 || r==3) err(funder2,"regula");
1848:
1849: sqd=racine(x); rsqd=gsqrt(x,prec);
1850: if (gegal(sqri(sqd),x)) err(talker,"square argument in regula");
1851:
1852: rexp=0; reg=cgetr(prec); affsr(2,reg);
1853: ln2 = mplog(reg);
1854: av2=avma; lim = stack_lim(av2,2);
1855: a = shifti(addsi(r,sqd),-1);
1856: v = gdeux; u = stoi(r);
1857: for(;;)
1858: {
1859: u1=subii(mulii(a,v),u);
1860: reg1=divri(addir(u1,rsqd),v);
1861: v1=divii(subii(x,sqri(u1)),v); fl=gegal(v,v1);
1862: if (gegal(u,u1) || fl) break;
1863: v=v1; u=u1; a = divii(addii(sqd,u),v);
1864: reg = mulrr(reg,reg1); rexp += expo(reg); setexpo(reg,0);
1865: if (rexp & ~EXPOBITS) err(muler4);
1866: if (low_stack(lim, stack_lim(av2,2)))
1867: {
1868: GEN *gptr[4]; gptr[0]=&a; gptr[1]=® gptr[2]=&u; gptr[3]=&v;
1869: if(DEBUGMEM>1) err(warnmem,"regula");
1870: gerepilemany(av2,gptr,4);
1871: }
1872: }
1873: reg = gsqr(reg); setexpo(reg,expo(reg)-1);
1874: if (fl) reg = mulrr(reg, divri(addir(u1,rsqd),v));
1875: y = mplog(divri(reg,v)); u1 = mulsr(rexp,ln2);
1876: if (signe(u1)) setexpo(u1, expo(u1)+1);
1877: tetpil=avma; return gerepile(av,tetpil,gadd(y,u1));
1878: }
1879:
1880: /*************************************************************************/
1881: /** **/
1882: /** CLASS NUMBER **/
1883: /** **/
1884: /*************************************************************************/
1885:
1886: static GEN
1887: gclassno(GEN x)
1888: {
1889: return garith_proto(classno,x,1);
1890: }
1891:
1892: static GEN
1893: gclassno2(GEN x)
1894: {
1895: return garith_proto(classno2,x,1);
1896: }
1897:
1898: GEN
1899: qfbclassno0(GEN x,long flag)
1900: {
1901: switch(flag)
1902: {
1903: case 0: return gclassno(x);
1904: case 1: return gclassno2(x);
1905: default: err(flagerr,"qfbclassno");
1906: }
1907: return NULL; /* not reached */
1908: }
1909:
1910: static GEN
1911: end_classno(GEN h, GEN hin, GEN *formes, long ptforme)
1912: {
1913: long av,i,j,lim,com;
1914: GEN p1,p2,p3,q,hp,fh,fg,ftest, f = formes[0];
1915:
1916: if (ptforme>11) ptforme = 11;
1917: p2=factor(h); p1=(GEN)p2[1]; p2=(GEN)p2[2];
1918: for (i=1; i<lg(p1); i++)
1919: {
1920: lim = itos((GEN)p2[i]);
1921: for (j=1; j<=lim; j++)
1922: {
1923: p3=divii(h,(GEN)p1[i]); fh=gpui(f,p3,0);
1924: if (!is_pm1(fh[1])) break;
1925: h = p3;
1926: }
1927: }
1928: q=ground(gdiv(hin,h)); hp=mulii(q,h);
1929: for (i=1; i<ptforme; i++)
1930: {
1931: fg=gpui(formes[i],h,0); fh=gpui(fg,q,0);
1932: if (!is_pm1(fh[1]))
1933: {
1934: av = avma; ftest = fg;
1935: for (com=1; ; com++)
1936: {
1937: if (gegal((GEN) fh[1], (GEN) ftest[1]) &&
1938: absi_equal((GEN) fh[2], (GEN) ftest[2])) break;
1939: ftest = gmul(ftest,fg);
1940: }
1941: if (signe(fh[2]) == signe(ftest[2])) com = -com;
1942: avma = av; q = addsi(com,q);
1943: hp = addii(hp, mulsi(com,h));
1944: }
1945: }
1946: return hp;
1947: }
1948:
1949: /* calcul de h(x) pour x<0 par la methode de Shanks */
1950: GEN
1951: classno(GEN x)
1952: {
1953: long av = avma, av2,c,ptforme,k,i,j,j1,lim,com,j2,s;
1954: GEN count,index,tabla,tablb,hash,court,p1,p2,hin,h,f,fh,fg,ftest,formes[100];
1955: byteptr p = diffptr;
1956:
1957: if (typ(x) != t_INT) err(arither1);
1958: s=signe(x); if (s>=0) return classno2(x);
1959:
1960: k=mod4(x); if (k==1 || k==2) err(funder2,"classno");
1961: if (gcmpgs(x,-12) >= 0) return gun;
1962:
1963: p2 = gsqrt(absi(x),DEFAULTPREC);
1964: p1 = divrr(p2,mppi(DEFAULTPREC));
1965: p2 = gtrunc(shiftr(gsqrt(p2,DEFAULTPREC),1));
1966: s = 1000;
1967: if (signe(p2))
1968: {
1969: s = p2[2];
1970: if (lgefint(p2)>3 || s<0)
1971: err(talker,"discriminant too big in classno");
1972: if (s<1000) s=1000;
1973: }
1974: c=ptforme=0; court = stoi(2);
1975: while (c <= s && *p)
1976: {
1977: c += *p++; k=krogs(x,c);
1978: if (k)
1979: {
1980: av2=avma;
1981: if (k>0)
1982: {
1983: divrsz(mulsr(c,p1),c-1,p1); avma=av2;
1984: if (ptforme<100 && c>2)
1985: {
1986: court[2]=c;
1987: formes[ptforme++]=redimag(primeform(x,court,0));
1988: }
1989: }
1990: else { divrsz(mulsr(c,p1),c+1,p1); avma=av2; }
1991: }
1992: }
1993: s = 2*itos(gceil(gpui(p1,ginv(stoi(4)),DEFAULTPREC)));
1994: if (s>=10000) s=10000;
1995:
1996: count = new_chunk(256); for (i=0; i<=255; i++) count[i]=0;
1997: index = new_chunk(257);
1998: tabla = new_chunk(10000);
1999: tablb = new_chunk(10000);
2000: hash = new_chunk(10000);
2001: h = hin = ground(p1); f=formes[0];
2002: p1 = fh = gpui(f,h,0);
2003: for (i=0; i<s; i++)
2004: {
2005: p2=(GEN)p1[1]; tabla[i]=p2[lgefint(p2)-1];
2006: p2=(GEN)p1[2]; tablb[i]=p2[lgefint(p2)-1];
2007: count[tabla[i]&255]++; p1=compimag(p1,f);
2008: }
2009: index[0]=0; for (i=0; i<=254; i++) index[i+1] = index[i]+count[i];
2010: for (i=0; i<s; i++) hash[index[tabla[i]&255]++]=i;
2011: index[0]=0; for (i=0; i<=255; i++) index[i+1] = index[i]+count[i];
2012:
2013: fg=gpuigs(f,s); av2=avma; lim=stack_lim(av2,2);
2014: ftest=gpuigs(p1,0);
2015: for (com=0; ; com++)
2016: {
2017: p1=(GEN)ftest[1]; k=p1[lgefint(p1)-1]; j=k&255;
2018: for (j1=index[j]; j1 < index[j+1]; j1++)
2019: {
2020: j2=hash[j1];
2021: if (tabla[j2] == k)
2022: {
2023: p2=(GEN)ftest[2];
2024: if (tablb[j2] == labs(p2[lgefint(p2)-1]))
2025: {
2026: p1 = gmul(gpuigs(f,j2),fh);
2027: if (gegal((GEN) p1[1],(GEN) ftest[1]) &&
2028: absi_equal((GEN) p1[2],(GEN) ftest[2]))
2029: {
2030: /* p1 = ftest or ftest^(-1), we are done */
2031: if (signe(p1[2]) == signe(ftest[2])) com = -com;
2032: h = addii(addis(h,j2), mulss(s,com));
2033: h = end_classno(h,hin,formes,ptforme);
2034: avma = av; return icopy(h); /* safe: stack big enough */
2035: }
2036: }
2037: }
2038: }
2039: ftest = gmul(ftest,fg);
2040: if (is_pm1(ftest[1])) err(impl,"classno with too small order");
2041: if (low_stack(lim, stack_lim(av2,2))) ftest = gerepileupto(av2,ftest);
2042: }
2043: }
2044:
2045: /* use Euler products */
2046: GEN
2047: classno2(GEN x)
2048: {
2049: long av=avma,tetpil,n,i,k,s=signe(x),fl2;
2050: GEN p1,p2,p3,p4,p5,p7,p8,pi4,reg,logd,d,fd;
2051:
2052: if (typ(x) != t_INT) err(arither1);
2053: if (!s) err(arither2);
2054: if (s<0 && gcmpgs(x,-12) >= 0) return gun;
2055:
2056: p1=auxdecomp(absi(x),1); p2=(GEN)p1[2]; p1=(GEN)p1[1];
2057: n=lg(p1); d=gun;
2058: for (i=1; i<n; i++)
2059: if (mod2((GEN)p2[i])) d=mulii(d,(GEN)p1[i]);
2060: fl2 = (mod4(x)==0); /* 4 | x */
2061: if (mod4(d) != 2-s)
2062: {
2063: if (!fl2) err(funder2,"classno2");
2064: d = shifti(d,2);
2065: }
2066: else fl2=0;
2067: p8=gun; fd = (s<0)? negi(d): d; /* d = abs(fd) */
2068: for (i=1; i<n; i++)
2069: {
2070: k=itos((GEN)p2[i]); p4=(GEN)p1[i];
2071: if (fl2 && i==1) k -= 2; /* p4 = 2 */
2072: if (k>=2)
2073: {
2074: p8=mulii(p8,subis(p4,kronecker(fd,p4)));
2075: if (k>=4) p8=mulii(p8,gpuigs(p4,(k>>1)-1));
2076: }
2077: }
2078: if (s<0 && lgefint(d)==3)
2079: {
2080: switch(d[2])
2081: {
2082: case 4: p8=gdivgs(p8,2); break;
2083: case 3: p8=gdivgs(p8,3); break;
2084: }
2085: if (d[2] < 12) /* |fd| < 12*/
2086: { tetpil=avma; return gerepile(av,tetpil,icopy(p8)); }
2087: }
2088:
2089: pi4=mppi(DEFAULTPREC); logd=glog(d,DEFAULTPREC);
2090: p1=gsqrt(gdiv(gmul(d,logd),gmul2n(pi4,1)),DEFAULTPREC);
2091: p4=divri(pi4,d); p7=ginv(mpsqrt(pi4));
2092: if (s>0)
2093: {
2094: reg=regula(d,DEFAULTPREC);
2095: p2=gsubsg(1,gmul2n(gdiv(glog(reg,DEFAULTPREC),logd),1));
2096: p3=gsqrt(gdivsg(2,logd),DEFAULTPREC);
2097: if (gcmp(p2,p3)>=0) p1=gmul(p2,p1);
2098: }
2099: p1 = gtrunc(p1); n=p1[2];
2100: if (lgefint(p1)!=3 || n<0)
2101: err(talker,"discriminant too large in classno");
2102:
2103: p1 = gsqrt(d,DEFAULTPREC); p3 = gzero;
2104: if (s>0)
2105: {
2106: for (i=1; i<=n; i++)
2107: {
2108: k=krogs(fd,i);
2109: if (k)
2110: {
2111: p2=mulir(mulss(i,i),p4);
2112: p5=subsr(1,mulrr(p7,incgam3(ghalf,p2,DEFAULTPREC)));
2113: p5=addrr(divrs(mulrr(p1,p5),i),eint1(p2,DEFAULTPREC));
2114: p3 = (k>0)? addrr(p3,p5): subrr(p3,p5);
2115: }
2116: }
2117: p3=shiftr(divrr(p3,reg),-1);
2118: if (!egalii(x,fd)) /* x != p3 */
2119: p8 = gdiv(p8,ground(gdiv(regula(x,DEFAULTPREC),reg)));
2120: }
2121: else
2122: {
2123: p1 = gdiv(p1,pi4);
2124: for (i=1; i<=n; i++)
2125: {
2126: k=krogs(fd,i);
2127: if (k)
2128: {
2129: p2=mulir(mulss(i,i),p4);
2130: p5=subsr(1,mulrr(p7,incgam3(ghalf,p2,DEFAULTPREC)));
2131: p5=addrr(p5,divrr(divrs(p1,i),mpexp(p2)));
2132: p3 = (k>0)? addrr(p3,p5): subrr(p3,p5);
2133: }
2134: }
2135: }
2136: p3=ground(p3); tetpil=avma;
2137: return gerepile(av,tetpil,mulii(p8,p3));
2138: }
2139:
2140: GEN
2141: hclassno(GEN x)
2142: {
2143: long d,a,b,h,b2,f;
2144:
2145: d= -itos(x); if (d>0 || (d & 3) > 1) return gzero;
2146: if (!d) return gdivgs(gun,-12);
2147: if (-d > (VERYBIGINT>>1))
2148: err(talker,"discriminant too big in hclassno. Use quadclassunit");
2149: h=0; b=d&1; b2=(b-d)>>2; f=0;
2150: if (!b)
2151: {
2152: for (a=1; a*a<b2; a++)
2153: if (b2%a == 0) h++;
2154: f = (a*a==b2); b=2; b2=(4-d)>>2;
2155: }
2156: while (b2*3+d<0)
2157: {
2158: if (b2%b == 0) h++;
2159: for (a=b+1; a*a<b2; a++)
2160: if (b2%a == 0) h+=2;
2161: if (a*a==b2) h++;
2162: b+=2; b2=(b*b-d)>>2;
2163: }
2164: if (b2*3+d==0)
2165: {
2166: GEN y = cgetg(3,t_FRAC);
2167: y[1]=lstoi(3*h+1); y[2]=lstoi(3); return y;
2168: }
2169: if (f) return gaddsg(h,ghalf);
2170: return stoi(h);
2171: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>