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