Annotation of OpenXM_contrib/pari-2.2/src/basemath/arith2.c, Revision 1.1.1.1
1.1 noro 1: /* $Id: arith2.c,v 1.26 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: /** (second part) **/
20: /** **/
21: /*********************************************************************/
22: #include "pari.h"
23:
24: extern GEN arith_proto(long f(GEN), GEN x, int do_error);
25: extern GEN arith_proto2(long f(GEN,GEN), GEN x, GEN n);
26: extern GEN garith_proto(GEN f(GEN), GEN x, int do_error);
27: extern GEN garith_proto2gs(GEN f(GEN,long), GEN x, long y);
28:
29: #define sqru(i) (muluu((i),(i)))
30:
31: /***********************************************************************/
32: /** **/
33: /** PRIME NUMBERS **/
34: /** **/
35: /***********************************************************************/
36:
37: GEN
38: prime(long n)
39: {
40: byteptr p = diffptr;
41: long c, prime = 0;
42:
43: if (n <= 0) err(talker, "n-th prime meaningless if n = %ld",n);
44: while (n--)
45: {
46: c = *p++; if (!c) err(primer1);
47: prime += c;
48: }
49: return stoi(prime);
50: }
51:
52: GEN
53: pith(long n)
54: {
55: byteptr p = diffptr;
56: ulong prime = 0, res = 0;
57:
58: if (n <= 0) err(talker, "pith meaningless if n = %ld",n);
59: if (maxprime() <= n) err(primer1);
60: while (prime<=n) { prime += *p++; res++; }
61: return stoi(res-1);
62: }
63:
64: GEN
65: primes(long n)
66: {
67: byteptr p = diffptr;
68: long c, prime = 0;
69: GEN y,z;
70:
71: if (n < 0) n = 0;
72: z = y = cgetg(n+1,t_VEC);
73: while (n--)
74: {
75: c = *p++; if (!c) err(primer1);
76: prime += c; *++z = lstoi(prime);
77: }
78: return y;
79: }
80:
81: /* Building/Rebuilding the diffptr table. Incorporates Ilya Zakharevich's
82: * block sweep algorithm (see pari-dev-111, 25 April 1998). The actual work
83: * is done by the following two subroutines; the user entry point is the
84: * function initprimes() below. initprimes1() is the old algorithm, called
85: * when maxnum (size) is moderate.
86: */
87: static byteptr
88: initprimes1(long size, long *lenp, long *lastp)
89: {
90: long k;
91: byteptr q,r,s,fin, p = (byteptr) gpmalloc(size+2);
92:
93: memset(p, 0, size + 2); fin = p + size;
94: for (r=q=p,k=1; r<=fin; )
95: {
96: do { r+=k; k+=2; r+=k; } while (*++q);
97: for (s=r; s<=fin; s+=k) *s=1;
98: }
99: r=p; *r++=2; *r++=1; /* 2 and 3 */
100: for (s=q=r-1; ; s=q)
101: {
102: do q++; while (*q);
103: if (q>fin) break;
104: *r++ = (q-s) << 1;
105: }
106: *r++=0;
107: *lenp = r - p;
108: *lastp = ((s - p) << 1) + 1;
109: #if 0
110: fprintferr("initprimes1: q = %ld, len = %ld, last = %ld\n",
111: q, *lenp, *lastp);
112: #endif
113: return (byteptr) gprealloc(p,r-p,size + 2);
114: }
115:
116: #define PRIME_ARENA (200 * 1024) /* No slowdown even with 256K level-2 cache */
117:
118: /* Here's the workhorse. This is recursive, although normally the first
119: recursive call will bottom out and invoke initprimes1() at once.
120: (Not static; might conceivably be useful to someone in library mode) */
121: byteptr
122: initprimes0(ulong maxnum, long *lenp, long *lastp)
123: {
124: long k, size, alloced, asize, psize, rootnum, curlow, last, remains;
125: byteptr q,r,s,fin, p, p1, fin1, plast, curdiff;
126:
127: #if 0
128: fprintferr("initprimes0: called for maxnum = %lu\n", maxnum);
129: #endif
130: if (maxnum <= 1ul<<17) /* Arbitrary. */
131: return initprimes1(maxnum>>1, lenp, lastp);
132:
133: maxnum |= 1; /* make it odd. */
134:
135: /* Checked to be enough up to 40e6, attained at 155893 */
136: size = (long) (1.09 * maxnum/log((double)maxnum)) + 145;
137: p1 = (byteptr) gpmalloc(size);
138: rootnum = (long) sqrt((double)maxnum); /* cast it back to a long */
139: rootnum |= 1;
140: #if 0
141: fprintferr("initprimes0: rootnum = %ld\n", rootnum);
142: #endif
143: {
144: byteptr p2 = initprimes0(rootnum, &psize, &last); /* recursive call */
145: memcpy(p1, p2, psize); free(p2);
146: }
147: fin1 = p1 + psize - 1;
148: remains = (maxnum - rootnum) >> 1; /* number of odd numbers to check */
149:
150: /* ARENA_IN_ROOTS below 12: some slowdown starts to be noticable
151: * when things fit into the cache.
152: * XXX The choice of 10 gives a slowdown of 1-2% on UltraSparcII,
153: * but makes calculations even for (the current) maximum of 436273009
154: * fit into 256K cache (still common for some architectures).
155: *
156: * One may change it when small caches become uncommon, but the gain
157: * is not going to be very noticable... */
158: #define ARENA_IN_ROOTS 10
159:
160: asize = ARENA_IN_ROOTS * rootnum; /* Make % overhead negligeable. */
161: if (asize < PRIME_ARENA) asize = PRIME_ARENA;
162: if (asize > remains) asize = remains + 1;/* + room for a sentinel byte */
163: alloced = (avma - bot < asize>>1); /* enough room on the stack ? */
164: if (alloced)
165: p = (byteptr) gpmalloc(asize);
166: else
167: p = (byteptr) bot;
168: fin = p + asize - 1; /* the 0 sentinel goes at fin. */
169: curlow = rootnum + 2; /* We know all primes up to rootnum (odd). */
170: curdiff = fin1;
171:
172: /* During each iteration p..fin-1 represents a range of odd
173: numbers. plast is a pointer which represents the last prime seen,
174: it may point before p..fin-1. */
175: plast = p - ((rootnum - last) >> 1) - 1;
176: while (remains)
177: {
178: if (asize > remains)
179: {
180: asize = remains + 1;
181: fin = p + asize - 1;
182: }
183: memset(p, 0, asize);
184: /* p corresponds to curlow. q runs over primediffs. */
185: for (q = p1+2, k = 3; q <= fin1; k += *q++)
186: {
187: /* The first odd number which is >= curlow and divisible by p
188: equals (if curlow > p)
189: the last odd number which is <= curlow + 2p - 1 and 0 (mod p)
190: which equals
191: p + the last even number which is <= curlow + p - 1 and 0 (mod p)
192: which equals
193: p + the last even number which is <= curlow + p - 2 and 0 (mod p)
194: which equals
195: p + curlow + p - 2 - (curlow + p - 2)) % 2p.
196: */
197: long k2 = k*k - curlow;
198:
199: if (k2 > 0)
200: {
201: r = p + (k2 >>= 1);
202: if (k2 > remains) break; /* Guard against an address wrap. */
203: } else
204: r = p - (((curlow+k-2) % (2*k)) >> 1) + k - 1;
205: for (s = r; s < fin; s += k) *s = 1;
206: }
207: /* now q runs over addresses corresponding to primes */
208: for (q = p; ; plast = q++)
209: {
210: while (*q) q++; /* use 0-sentinel at end */
211: if (q >= fin) break;
212: *curdiff++ = (q - plast) << 1;
213: }
214: plast -= asize - 1;
215: remains -= asize - 1;
216: curlow += ((asize - 1)<<1);
217: } /* while (remains) */
218: last = curlow - ((p - plast) << 1);
219: *curdiff++ = 0; /* sentinel */
220: *lenp = curdiff - p1;
221: *lastp = last;
222: if (alloced) free(p);
223: return (byteptr) gprealloc(p1, *lenp, size);
224: }
225: #if 0 /* not yet... GN */
226: /* The diffptr table will contain at least 6548 entries (up to and including
227: the 6547th prime, 65557, and the terminal null byte), because the isprime/
228: small-factor-extraction machinery wants to depend on everything up to 65539
229: being in the table, and we might as well go to a multiple of 4 Bytes.--GN */
230:
231: void
232: init_tinyprimes_tridiv(byteptr p); /* in ifactor2.c */
233: #endif
234:
235: static ulong _maxprime = 0;
236:
237: ulong
238: maxprime() { return _maxprime; }
239:
240: byteptr
241: initprimes(long maxnum)
242: {
243: long len, last;
244: byteptr p;
245: /* The algorithm must see the next prime beyond maxnum, whence the +257. */
246: /* switch to unsigned: adding the 257 _could_ wrap to a negative number. */
247: ulong maxnum1 = ((maxnum<65302?65302:maxnum)+257ul);
248:
249: if (maxnum1 > 436273000)
250: err(talker,"impossible to have prestored primes > 436273009");
251:
252: p = initprimes0(maxnum1, &len, &last);
253: #if 0 /* not yet... GN */
254: static int build_the_tables = 1;
255: if (build_the_tables) { init_tinyprimes_tridiv(p); build_the_tables=0; }
256: #endif
257: _maxprime = last; return p;
258: }
259:
260: static void
261: cleanprimetab(void)
262: {
263: long i,j, lp = lg(primetab);
264:
265: for (i=j=1; i < lp; i++)
266: if (primetab[i]) primetab[j++] = primetab[i];
267: setlg(primetab,j);
268: }
269:
270: /* p is a single element or a row vector with "primes" to add to primetab.
271: * If p shares a non-trivial factor with another element in primetab, take it
272: * into account. */
273: GEN
274: addprimes(GEN p)
275: {
276: ulong av;
277: long i,k,tx,lp;
278: GEN L;
279:
280: if (!p) return primetab;
281: tx = typ(p);
282: if (is_vec_t(tx))
283: {
284: for (i=1; i < lg(p); i++) addprimes((GEN) p[i]);
285: return primetab;
286: }
287: if (tx != t_INT) err(typeer,"addprime");
288: if (is_pm1(p)) return primetab;
289: av = avma; i = signe(p);
290: if (i == 0) err(talker,"can't accept 0 in addprimes");
291: if (i < 0) p = absi(p);
292:
293: lp = lg(primetab);
294: L = cgetg(2*lp,t_VEC); k = 1;
295: for (i=1; i < lp; i++)
296: {
297: GEN n = (GEN)primetab[i], d = mppgcd(n, p);
298: if (! is_pm1(d))
299: {
300: if (!egalii(p,d)) L[k++] = (long)d;
301: L[k++] = ldivii(n,d);
302: gunclone(n); primetab[i] = 0;
303: }
304: }
305: primetab = (GEN) gprealloc(primetab, (lp+1)*sizeof(long), lp*sizeof(long));
306: primetab[i] = lclone(p); setlg(primetab, lp+1);
307: if (k > 1) { cleanprimetab(); setlg(L,k); addprimes(L); }
308: avma = av; return primetab;
309: }
310:
311: static GEN
312: removeprime(GEN prime)
313: {
314: long i;
315:
316: if (typ(prime) != t_INT) err(typeer,"removeprime");
317: for (i=lg(primetab) - 1; i; i--)
318: if (absi_equal((GEN) primetab[i], prime))
319: {
320: gunclone((GEN)primetab[i]); primetab[i]=0;
321: cleanprimetab(); break;
322: }
323: if (!i) err(talker,"prime %Z is not in primetable", prime);
324: return primetab;
325: }
326:
327: GEN
328: removeprimes(GEN prime)
329: {
330: long i,tx;
331:
332: if (!prime) return primetab;
333: tx = typ(prime);
334: if (is_vec_t(tx))
335: {
336: if (prime == primetab)
337: {
338: for (i=1; i < lg(prime); i++) gunclone((GEN)prime[i]);
339: setlg(prime, 1);
340: }
341: else
342: {
343: for (i=1; i < lg(prime); i++) removeprime((GEN) prime[i]);
344: }
345: return primetab;
346: }
347: return removeprime(prime);
348: }
349:
350: /***********************************************************************/
351: /** **/
352: /** COMPUTING THE MATRIX OF PRIME DIVISORS AND EXPONENTS **/
353: /** **/
354: /***********************************************************************/
355:
356: /* Configure may/should define this to 1 if MPQS is not installed --GN */
357: #ifndef decomp_default_hint
358: #define decomp_default_hint 0
359: #endif
360:
361: /* Some overkill removed from this (15 spsp for an integer < 2^32 ?!).
362: Should really revert to isprime() once the new primality tester is ready
363: --GN */
364: #define pseudoprime(p) millerrabin(p,3*lgefint(p))
365:
366: /* where to stop trial dividing in factorization */
367:
368: static long
369: tridiv_bound(GEN n, long all)
370: {
371: long size = expi(n) + 1;
372: if (all > 1) /* bounded factoring */
373: return all; /* use the given limit */
374: if (all == 0)
375: return VERYBIGINT; /* smallfact() case */
376: if (size <= 32)
377: return 16384;
378: else if (size <= 512)
379: return (size-16) << 10;
380: return 1L<<19; /* Rho will generally be faster above this */
381: }
382:
383: /* function imported from ifactor1.c */
384: extern long ifac_decomp(GEN n, long hint);
385: extern long ifac_decomp_break(GEN n, long (*ifac_break)(GEN,GEN,GEN,GEN),
386: GEN state, long hint);
387: static GEN
388: aux_end(GEN n, long nb)
389: {
390: GEN p1,p2, z = (GEN)avma;
391: long i;
392:
393: if (n) gunclone(n);
394: p1=cgetg(nb+1,t_COL);
395: p2=cgetg(nb+1,t_COL);
396: for (i=nb; i; i--)
397: {
398: p2[i] = (long)z; z += lg(z);
399: p1[i] = (long)z; z += lg(z);
400: }
401: z[1] = (long)p1;
402: z[2] = (long)p2;
403: if (nb) (void)sort_factor_gen(z,cmpii);
404: return z;
405: }
406:
407: GEN
408: auxdecomp1(GEN n, long (*ifac_break)(GEN n, GEN pairs, GEN here, GEN state),
409: GEN state, long all, long hint)
410: {
411: long pp[] = { evaltyp(t_INT)|m_evallg(3), evalsigne(1)|evallgefint(3),2,0 };
412: long nb = 0,i,k,lim1,av,lp;
413: byteptr d=diffptr+1;
414:
415: if (typ(n) != t_INT) err(arither1);
416: i=signe(n); if (!i) err(arither2);
417: cgetg(3,t_MAT);
418: if (i<0) { stoi(-1); stoi(1); nb++; }
419: if (is_pm1(n)) return aux_end(NULL,nb);
420:
421: n = gclone(n); setsigne(n,1);
422: i = vali(n);
423: if (i)
424: {
425: stoi(2); stoi(i); nb++;
426: av=avma; affii(shifti(n,-i), n); avma=av;
427: }
428: if (is_pm1(n)) return aux_end(n,nb);
429: lim1 = tridiv_bound(n, all);
430:
431: /* trial division */
432: while (*d && pp[2] <= lim1)
433: {
434: pp[2] += *d++;
435: if (mpdivis(n,pp,n))
436: {
437: nb++; k=1; while (mpdivis(n,pp,n)) k++;
438: icopy(pp); stoi(k);
439: if (is_pm1(n)) return aux_end(n,nb);
440: }
441: }
442:
443: /* pp = square of biggest p tried so far */
444: av=avma; setlg(pp,4); affii(sqri(pp),pp); avma=av;
445: if (cmpii(pp,n) > 0)
446: {
447: nb++;
448: icopy(n); stoi(1); return aux_end(n,nb);
449: }
450:
451: /* trial divide by the "special primes" (usually huge composites...) */
452: lp = lg(primetab); k=0;
453: for (i=1; i<lp; i++)
454: if (mpdivis(n,(GEN) primetab[i],n))
455: {
456: nb++; k=1; while (mpdivis(n,(GEN) primetab[i],n)) k++;
457: icopy((GEN) primetab[i]); stoi(k);
458: if (is_pm1(n)) return aux_end(n,nb);
459: }
460:
461: /* test primality (unless all != 1 (i.e smallfact))*/
462: if ((k && cmpii(pp,n) > 0) || (all==1 && pseudoprime(n)))
463: {
464: nb++;
465: icopy(n); stoi(1); return aux_end(n,nb);
466: }
467:
468: /* now we have a large composite. Use hint as is if all==1 */
469: if (all!=1) hint = 15; /* turn off everything except pure powers */
470: if (ifac_break && (*ifac_break)(n,NULL,NULL,state))
471: /*Initialize ifac_break*/
472: {
473: if (DEBUGLEVEL >= 3)
474: fprintferr("IFAC: (Partial fact.) Initial stop requested.\n");
475: }
476: else
477: nb += ifac_decomp_break(n, ifac_break, state, hint);
478:
479: return aux_end(n, nb);
480: }
481:
482: /* state[1]: current unfactored part.
483: * state[2]: limit. */
484: static long
485: ifac_break_limit(GEN n, GEN pairs/*unused*/, GEN here, GEN state)
486: {
487: ulong ltop = avma;
488: int res;
489: if (!here) /* initial call */
490: /* Small prime have been removed since start, n is the new unfactored part.
491: * Result is affect()ed to state[1] to preserve stack. */
492: affii(n, (GEN)state[1]);
493: else
494: {
495: GEN q = powgi((GEN)here[0],(GEN)here[1]); /* primary factor found.*/
496: if (DEBUGLEVEL>2) fprintferr("IFAC: Stop: Primary factor: %Z\n",q);
497: /* divide unfactored part by q and assign the result to state[1] */
498: diviiz((GEN)state[1],q, (GEN)state[1]);
499: }
500: if (DEBUGLEVEL>=3) fprintferr("IFAC: Stop: remaining %Z\n",state[1]);
501: /* check the stopping criterion, then restore stack */
502: res = cmpii((GEN)state[1],(GEN)state[2]) <= 0;
503: avma = ltop; return res;
504: }
505:
506: static GEN
507: auxdecomp0(GEN n, long all, long hint)
508: {
509: return auxdecomp1(n, NULL, gzero, all, hint);
510: }
511:
512: GEN
513: auxdecomp(GEN n, long all)
514: {
515: return auxdecomp0(n,all,decomp_default_hint);
516: }
517:
518: /* see before ifac_crack() in ifactor1.c for current semantics of `hint'
519: (factorint's `flag') */
520: GEN
521: factorint(GEN n, long flag)
522: {
523: return auxdecomp0(n,1,flag);
524: }
525:
526: GEN
527: decomp(GEN n)
528: {
529: return auxdecomp0(n,1,decomp_default_hint);
530: }
531:
532: /* Factor until the unfactored part is smaller than limit. */
533: GEN
534: decomp_limit(GEN n, GEN limit)
535: {
536: GEN state = cgetg(3,t_VEC);
537: /* icopy is mainly done to allocate memory for affect().
538: * Currently state[1] value is discarded in initial call to ifac_break_limit */
539: state[1] = licopy(n);
540: state[2] = lcopy(limit);
541: return auxdecomp1(n, &ifac_break_limit, state, 1, decomp_default_hint);
542: }
543:
544: GEN
545: smallfact(GEN n)
546: {
547: return boundfact(n,0);
548: }
549:
550: GEN
551: gboundfact(GEN n, long lim)
552: {
553: return garith_proto2gs(boundfact,n,lim);
554: }
555:
556: GEN
557: boundfact(GEN n, long lim)
558: {
559: GEN p1,p2,p3,p4,p5,y;
560: long av = avma,tetpil;
561:
562: if (lim<=1) lim=0;
563: switch(typ(n))
564: {
565: case t_INT:
566: return auxdecomp(n,lim);
567: case t_FRACN:
568: n=gred(n); /* fall through */
569: case t_FRAC:
570: p1=auxdecomp((GEN)n[1],lim);
571: p2=auxdecomp((GEN)n[2],lim);
572: p4=concatsp((GEN)p1[1],(GEN)p2[1]);
573: p5=concatsp((GEN)p1[2],gneg((GEN)p2[2]));
574: p3=indexsort(p4);
575:
576: tetpil=avma; y=cgetg(3,t_MAT);
577: y[1]=(long)extract(p4,p3);
578: y[2]=(long)extract(p5,p3);
579: return gerepile(av,tetpil,y);
580: }
581: err(arither1);
582: return NULL; /* not reached */
583: }
584:
585: /***********************************************************************/
586: /** **/
587: /** BASIC ARITHMETIC FUNCTIONS **/
588: /** **/
589: /***********************************************************************/
590:
591: /* functions imported from ifactor1.c */
592: long
593: ifac_moebius(GEN n, long hint);
594:
595: long
596: ifac_issquarefree(GEN n, long hint);
597:
598: long
599: ifac_omega(GEN n, long hint);
600:
601: long
602: ifac_bigomega(GEN n, long hint);
603:
604: GEN
605: ifac_totient(GEN n, long hint);
606:
607: GEN
608: ifac_numdiv(GEN n, long hint);
609:
610: GEN
611: ifac_sumdiv(GEN n, long hint);
612:
613: GEN
614: ifac_sumdivk(GEN n, long k, long hint);
615:
616: GEN
617: gmu(GEN n)
618: {
619: return arith_proto(mu,n,1);
620: }
621:
622: long
623: mu(GEN n)
624: {
625: byteptr d = diffptr+1; /* point at 3 - 2 */
626: ulong p,lim1, av = avma;
627: long s, v;
628:
629: if (typ(n) != t_INT) err(arither1);
630: if (!signe(n)) err(arither2);
631: if (is_pm1(n)) return 1;
632: v = vali(n);
633: if (v>1) return 0;
634: s = v ? -1 : 1;
635: n=absi(shifti(n,-v)); p = 2;
636: if (is_pm1(n)) return s;
637: lim1 = tridiv_bound(n,1);
638:
639: while (*d && p < lim1)
640: {
641: p += *d++;
642: if (mpdivisis(n,p,n))
643: {
644: if (smodis(n,p) == 0) { avma=av; return 0; }
645: s = -s; if (is_pm1(n)) { avma=av; return s; }
646: }
647: }
648: /* we normally get here with p==nextprime(PRE_TUNE), which will already
649: have been tested against n, so p^2 >= n (instead of p^2 > n) is
650: enough to guarantee n is prime */
651: if (cmpii(sqru(p),n) >= 0 || pseudoprime(n)) { avma=av; return -s; }
652: /* large composite without small factors */
653: v = ifac_moebius(n, decomp_default_hint);
654: avma=av;
655: return (s<0 ? -v : v); /* correct also if v==0 */
656: }
657:
658: GEN
659: gissquarefree(GEN x)
660: {
661: return arith_proto(issquarefree,x,0);
662: }
663:
664: long
665: issquarefree(GEN x)
666: {
667: ulong av = avma,lim1,p;
668: long tx;
669: GEN d;
670:
671: if (gcmp0(x)) return 0;
672: tx = typ(x);
673: if (tx == t_INT)
674: {
675: long v;
676: byteptr d=diffptr+1;
677: if (is_pm1(x)) return 1;
678: if((v = vali(x)) > 1) return 0;
679: x = absi(shifti(x,-v));
680: if (is_pm1(x)) return 1;
681: lim1 = tridiv_bound(x,1);
682:
683: p = 2;
684: while (*d && p < lim1)
685: {
686: p += *d++;
687: if (mpdivisis(x,p,x))
688: {
689: if (smodis(x,p) == 0) { avma = av; return 0; }
690: if (is_pm1(x)) { avma = av; return 1; }
691: }
692: }
693: if (cmpii(sqru(p),x) >= 0 || pseudoprime(x)) { avma = av; return 1; }
694: v = ifac_issquarefree(x, decomp_default_hint);
695: avma = av; return v;
696: }
697: if (tx != t_POL) err(typeer,"issquarefree");
698: d = ggcd(x, derivpol(x));
699: avma = av; return (lgef(d) == 3);
700: }
701:
702: GEN
703: gomega(GEN n)
704: {
705: return arith_proto(omega,n,1);
706: }
707:
708: long
709: omega(GEN n)
710: {
711: byteptr d=diffptr+1;
712: ulong p, lim1, av = avma;
713: long nb,v;
714:
715: if (typ(n) != t_INT) err(arither1);
716: if (!signe(n)) err(arither2);
717: if (is_pm1(n)) return 0;
718: v=vali(n);
719: nb = v ? 1 : 0;
720: n = absi(shifti(n,-v)); p = 2;
721: if (is_pm1(n)) return nb;
722: lim1 = tridiv_bound(n,1);
723:
724: while (*d && p < lim1)
725: {
726: p += *d++;
727: if (mpdivisis(n,p,n))
728: {
729: nb++; while (mpdivisis(n,p,n)); /* empty */
730: if (is_pm1(n)) { avma = av; return nb; }
731: }
732: }
733: if (cmpii(sqru(p),n) >= 0 || pseudoprime(n)) { avma = av; return nb+1; }
734: /* large composite without small factors */
735: nb += ifac_omega(n, decomp_default_hint);
736: avma=av; return nb;
737: }
738:
739: GEN
740: gbigomega(GEN n)
741: {
742: return arith_proto(bigomega,n,1);
743: }
744:
745: long
746: bigomega(GEN n)
747: {
748: byteptr d=diffptr+1;
749: ulong av = avma, p,lim1;
750: long nb,v;
751:
752: if (typ(n) != t_INT) err(arither1);
753: if (!signe(n)) err(arither2);
754: if (is_pm1(n)) return 0;
755: nb=v=vali(n);
756: n=absi(shifti(n,-v)); p = 2;
757: if (is_pm1(n)) { avma = av; return nb; }
758: lim1 = tridiv_bound(n,1);
759:
760: while (*d && p < lim1)
761: {
762: p += *d++;
763: if (mpdivisis(n,p,n))
764: {
765: do nb++; while (mpdivisis(n,p,n));
766: if (is_pm1(n)) { avma = av; return nb; }
767: }
768: }
769: if (cmpii(sqru(p),n) >= 0 || pseudoprime(n)) { avma = av; return nb+1; }
770: nb += ifac_bigomega(n, decomp_default_hint);
771: avma=av; return nb;
772: }
773:
774: GEN
775: gphi(GEN n)
776: {
777: return garith_proto(phi,n,1);
778: }
779:
780: GEN
781: phi(GEN n)
782: {
783: byteptr d = diffptr+1;
784: GEN m;
785: ulong av = avma, lim1, p;
786: long v;
787:
788: if (typ(n) != t_INT) err(arither1);
789: if (!signe(n)) err(arither2);
790: if (is_pm1(n)) return gun;
791: v = vali(n);
792: n = absi(shifti(n,-v)); p = 2;
793: m = (v > 1 ? shifti(gun,v-1) : stoi(1));
794: if (is_pm1(n)) { return gerepileupto(av,m); }
795: lim1 = tridiv_bound(n,1);
796:
797: while (*d && p < lim1)
798: {
799: p += *d++;
800: if (mpdivisis(n,p,n))
801: {
802: m = mulis(m, p-1);
803: while (mpdivisis(n,p,n)) m = mulis(m,p);
804: if (is_pm1(n)) { return gerepileupto(av,m); }
805: }
806: }
807: if (cmpii(sqru(p),n) >= 0 || pseudoprime(n))
808: {
809: m = mulii(m,addsi(-1,n));
810: return gerepileupto(av,m);
811: }
812: m = mulii(m, ifac_totient(n, decomp_default_hint));
813: return gerepileupto(av,m);
814: }
815:
816: GEN
817: gnumbdiv(GEN n)
818: {
819: return garith_proto(numbdiv,n,1);
820: }
821:
822: GEN
823: numbdiv(GEN n)
824: {
825: byteptr d=diffptr+1;
826: GEN m;
827: long l, v;
828: ulong av = avma, p,lim1;
829:
830: if (typ(n) != t_INT) err(arither1);
831: if (!signe(n)) err(arither2);
832: if (is_pm1(n)) return gun;
833: v = vali(n);
834: n = absi(shifti(n,-v)); p = 2;
835: m = stoi(v+1);
836: if (is_pm1(n)) return gerepileupto(av,m);
837: lim1 = tridiv_bound(n,1);
838:
839: while (*d && p < lim1)
840: {
841: p += *d++;
842: l=1; while (mpdivisis(n,p,n)) l++;
843: m = mulsi(l,m); if (is_pm1(n)) { return gerepileupto(av,m); }
844: }
845: if(cmpii(sqru(p),n) >= 0 || pseudoprime(n))
846: {
847: m = shifti(m,1);
848: return gerepileupto(av,m);
849: }
850: m = mulii(m, ifac_numdiv(n, decomp_default_hint));
851: return gerepileupto(av,m);
852: }
853:
854: GEN
855: gsumdiv(GEN n)
856: {
857: return garith_proto(sumdiv,n,1);
858: }
859:
860: GEN
861: sumdiv(GEN n)
862: {
863: byteptr d=diffptr+1;
864: GEN m,m1;
865: ulong av=avma,lim1,p;
866: long v;
867:
868: if (typ(n) != t_INT) err(arither1);
869: if (!signe(n)) err(arither2);
870: if (is_pm1(n)) return gun;
871: v = vali(n);
872: n = absi(shifti(n,-v)); p = 2;
873: m = (v ? addsi(-1,shifti(gun,v+1)) : stoi(1));
874: if (is_pm1(n)) { return gerepileupto(av,m); }
875: lim1 = tridiv_bound(n,1);
876:
877: while (*d && p < lim1)
878: {
879: p += *d++;
880: if (mpdivisis(n,p,n))
881: {
882: m1 = utoi(p+1);
883: while (mpdivisis(n,p,n)) m1 = addsi(1, mului(p,m1));
884: m = mulii(m1,m); if (is_pm1(n)) { return gerepileupto(av,m); }
885: }
886: }
887: if(cmpii(sqru(p),n) >= 0 || pseudoprime(n))
888: {
889: m = mulii(m,addsi(1,n));
890: return gerepileupto(av,m);
891: }
892: m = mulii(m, ifac_sumdiv(n, decomp_default_hint));
893: return gerepileupto(av,m);
894: }
895:
896: GEN
897: gsumdivk(GEN n, long k)
898: {
899: return garith_proto2gs(sumdivk,n,k);
900: }
901:
902: GEN
903: sumdivk(GEN n, long k)
904: {
905: byteptr d=diffptr+1;
906: GEN n1,m,m1,pk;
907: ulong av = avma, p, lim1;
908: long k1,v;
909:
910: if (!k) return numbdiv(n);
911: if (k==1) return sumdiv(n);
912: if (typ(n) != t_INT) err(arither1);
913: if (!signe(n)) err(arither2);
914: if (is_pm1(n)) return gun;
915: k1 = k; n1 = n;
916: if (k==-1) { m=sumdiv(n); goto fin; }
917: if (k<0) k = -k;
918: v=vali(n);
919: n=absi(shifti(n,-v));
920: p = 2; m = stoi(1);
921: while (v--) m = addsi(1,shifti(m,k));
922: if (is_pm1(n)) goto fin;
923: lim1 = tridiv_bound(n,1);
924:
925: while (*d && p < lim1)
926: {
927: p += *d++;
928: if (mpdivisis(n,p,n))
929: {
930: pk = gpowgs(utoi(p),k); m1 = addsi(1,pk);
931: while (mpdivisis(n,p,n)) m1 = addsi(1, mulii(pk,m1));
932: m = mulii(m1,m); if (is_pm1(n)) goto fin;
933: }
934: }
935: if(cmpii(sqru(p),n) >= 0 || pseudoprime(n))
936: {
937: pk = gpuigs(n,k);
938: m = mulii(m,addsi(1,pk));
939: goto fin;
940: }
941: m = mulii(m, ifac_sumdivk(n, k, decomp_default_hint));
942: fin:
943: if (k1 < 0) m = gdiv(m, gpowgs(n1,k));
944: return gerepileupto(av,m);
945: }
946:
947: /***********************************************************************/
948: /** **/
949: /** MISCELLANEOUS ARITHMETIC FUNCTIONS **/
950: /** (all of these ultimately depend on auxdecomp()) **/
951: /** **/
952: /***********************************************************************/
953:
954: GEN
955: divisors(GEN n)
956: {
957: long tetpil,av=avma,i,j,l;
958: GEN *d,*t,*t1,*t2,*t3, nbdiv,e;
959:
960: if (typ(n) != t_MAT || lg(n) != 3) n = auxdecomp(n,1);
961:
962: e = (GEN) n[2], n = (GEN) n[1]; l = lg(n);
963: if (l>1 && signe(n[1]) < 0) { e++; n++; l--; } /* skip -1 */
964: nbdiv = gun;
965: for (i=1; i<l; i++)
966: {
967: e[i] = itos((GEN)e[i]);
968: nbdiv = mulis(nbdiv,1+e[i]);
969: }
970: if (is_bigint(nbdiv) || (itos(nbdiv) & ~LGBITS))
971: err(talker, "too many divisors (more than %ld)", LGBITS - 1);
972: d = t = (GEN*) cgetg(itos(nbdiv)+1,t_VEC);
973: *++d = gun;
974: for (i=1; i<l; i++)
975: for (t1=t,j=e[i]; j; j--,t1=t2)
976: for (t2=d,t3=t1; t3<t2; )
977: *++d = mulii(*++t3, (GEN)n[i]);
978: tetpil=avma; return gerepile(av,tetpil,sort((GEN)t));
979: }
980:
981: GEN
982: core(GEN n)
983: {
984: long av=avma,tetpil,i;
985: GEN fa,p1,p2,res=gun;
986:
987: fa=auxdecomp(n,1); p1=(GEN)fa[1]; p2=(GEN)fa[2];
988: for (i=1; i<lg(p1); i++)
989: if (mod2((GEN)p2[i])) res = mulii(res,(GEN)p1[i]);
990: tetpil=avma; return gerepile(av,tetpil,icopy(res));
991: }
992:
993: GEN
994: core2(GEN n)
995: {
996: long av=avma,tetpil,i;
997:
998: GEN fa,p1,p2,p3,res=gun,res2=gun,y;
999:
1000: fa=auxdecomp(n,1); p1=(GEN)fa[1]; p2=(GEN)fa[2];
1001: for (i=1; i<lg(p1); i++)
1002: {
1003: p3=(GEN)p2[i];
1004: if (mod2(p3)) res=mulii(res,(GEN)p1[i]);
1005: if (!gcmp1(p3)) res2=mulii(res2,gpui((GEN)p1[i],shifti(p3,-1),0));
1006: }
1007: tetpil=avma; y=cgetg(3,t_VEC);
1008: y[1]=(long)icopy(res); y[2]=(long)icopy(res2);
1009: return gerepile(av,tetpil,y);
1010: }
1011:
1012: GEN
1013: core0(GEN n,long flag)
1014: {
1015: return flag? core2(n): core(n);
1016: }
1017:
1018: GEN
1019: coredisc(GEN n)
1020: {
1021: long av=avma,tetpil,r;
1022: GEN p1=core(n);
1023:
1024: r=mod4(p1); if (signe(p1)<0) r = 4-r;
1025: if (r==1 || r==4) return p1;
1026: tetpil=avma; return gerepile(av,tetpil,shifti(p1,2));
1027: }
1028:
1029: GEN
1030: coredisc2(GEN n)
1031: {
1032: long av=avma,tetpil,r;
1033: GEN y,p1,p2=core2(n);
1034:
1035: p1=(GEN)p2[1]; r=mod4(p1); if (signe(p1)<0) r=4-r;
1036: if (r==1 || r==4) return p2;
1037: tetpil=avma; y=cgetg(3,t_VEC);
1038: y[1]=lshifti(p1,2); y[2]=lmul2n((GEN)p2[2],-1);
1039: return gerepile(av,tetpil,y);
1040: }
1041:
1042: GEN
1043: coredisc0(GEN n,long flag)
1044: {
1045: return flag? coredisc2(n): coredisc(n);
1046: }
1047:
1048: /***********************************************************************/
1049: /** **/
1050: /** BINARY QUADRATIC FORMS **/
1051: /** **/
1052: /***********************************************************************/
1053:
1054: GEN
1055: qf_disc(GEN x, GEN y, GEN z)
1056: {
1057: if (!y) { y=(GEN)x[2]; z=(GEN)x[3]; x=(GEN)x[1]; }
1058: return subii(sqri(y), shifti(mulii(x,z),2));
1059: }
1060:
1061: static GEN
1062: qf_create(GEN x, GEN y, GEN z, long s)
1063: {
1064: GEN t;
1065: if (typ(x)!=t_INT || typ(y)!=t_INT || typ(z)!=t_INT) err(typeer,"Qfb");
1066: if (!s)
1067: {
1068: long av=avma; s = signe(qf_disc(x,y,z)); avma=av;
1069: if (!s) err(talker,"zero discriminant in Qfb");
1070: }
1071: t = (s>0)? cgetg(5,t_QFR): cgetg(4,t_QFI);
1072: t[1]=(long)icopy(x); t[2]=(long)icopy(y); t[3]=(long)icopy(z);
1073: return t;
1074: }
1075:
1076: GEN
1077: qfi(GEN x, GEN y, GEN z)
1078: {
1079: return qf_create(x,y,z,-1);
1080: }
1081:
1082: GEN
1083: qfr(GEN x, GEN y, GEN z, GEN d)
1084: {
1085: GEN t = qf_create(x,y,z,1);
1086: if (typ(d) != t_REAL)
1087: err(talker,"Shanks distance should be a t_REAL (in qfr)");
1088: t[4]=lrcopy(d); return t;
1089: }
1090:
1091: GEN
1092: Qfb0(GEN x, GEN y, GEN z, GEN d, long prec)
1093: {
1094: GEN t = qf_create(x,y,z,0);
1095: if (lg(t)==4) return t;
1096: if (!d) d = gzero;
1097: if (typ(d) == t_REAL)
1098: t[4] = lrcopy(d);
1099: else
1100: { t[4]=lgetr(prec); gaffect(d,(GEN)t[4]); }
1101: return t;
1102: }
1103:
1104: /* composition */
1105: static void
1106: sq_gen(GEN z, GEN x)
1107: {
1108: GEN d1,x2,y2,v1,v2,c3,m,p1,r;
1109:
1110: d1 = bezout((GEN)x[2],(GEN)x[1],&x2,&y2);
1111: if (gcmp1(d1)) v1 = v2 = (GEN)x[1];
1112: else
1113: {
1114: v1 = divii((GEN)x[1],d1);
1115: v2 = mulii(v1,mppgcd(d1,(GEN)x[3]));
1116: }
1117: m = mulii((GEN)x[3],x2); setsigne(m,-signe(m));
1118: r = modii(m,v2); p1 = mulii(v1,r);
1119: c3 = addii(mulii((GEN)x[3],d1), mulii(r,addii((GEN)x[2],p1)));
1120: z[1] = lmulii(v1,v2);
1121: z[2] = laddii((GEN)x[2], shifti(p1,1));
1122: z[3] = ldivii(c3,v2);
1123: }
1124:
1125: void
1126: comp_gen(GEN z,GEN x,GEN y)
1127: {
1128: GEN s,n,d,d1,x1,x2,y1,y2,v1,v2,c3,m,p1,r;
1129:
1130: if (x == y) { sq_gen(z,x); return; }
1131: s = shifti(addii((GEN)x[2],(GEN)y[2]),-1);
1132: n = subii((GEN)y[2],s);
1133: d = bezout((GEN)y[1],(GEN)x[1],&y1,&x1);
1134: d1 = bezout(s,d,&x2,&y2);
1135: if (gcmp1(d1))
1136: {
1137: v1 = (GEN)x[1];
1138: v2 = (GEN)y[1];
1139: }
1140: else
1141: {
1142: v1 = divii((GEN)x[1],d1);
1143: v2 = divii((GEN)y[1],d1);
1144: v1 = mulii(v1, mppgcd(d1,mppgcd((GEN)x[3],mppgcd((GEN)y[3],n))));
1145: }
1146: m = addii(mulii(mulii(y1,y2),n), mulii((GEN)y[3],x2));
1147: setsigne(m,-signe(m));
1148: r = modii(m,v1); p1 = mulii(v2,r);
1149: c3 = addii(mulii((GEN)y[3],d1), mulii(r,addii((GEN)y[2],p1)));
1150: z[1] = lmulii(v1,v2);
1151: z[2] = laddii((GEN)y[2], shifti(p1,1));
1152: z[3] = ldivii(c3,v1);
1153: }
1154:
1155: static GEN
1156: compimag0(GEN x, GEN y, int raw)
1157: {
1158: ulong tx = typ(x), av = avma;
1159: GEN z;
1160:
1161: if (typ(y) != tx || tx!=t_QFI) err(typeer,"composition");
1162: if (cmpii((GEN)x[1],(GEN)y[1]) > 0) { z=x; x=y; y=z; }
1163: z=cgetg(4,t_QFI); comp_gen(z,x,y);
1164: if (raw) return gerepilecopy(av,z);
1165: return gerepileupto(av, redimag(z));
1166: }
1167:
1168: static GEN
1169: compreal0(GEN x, GEN y, int raw)
1170: {
1171: ulong tx = typ(x), av = avma;
1172: GEN z;
1173:
1174: if (typ(y) != tx || tx!=t_QFR) err(typeer,"composition");
1175: z=cgetg(5,t_QFR); comp_gen(z,x,y);
1176: z[4]=laddrr((GEN)x[4],(GEN)y[4]);
1177: if (raw) return gerepilecopy(av,z);
1178: return gerepileupto(av,redreal(z));
1179: }
1180:
1181: GEN
1182: compreal(GEN x, GEN y) { return compreal0(x,y,0); }
1183:
1184: GEN
1185: comprealraw(GEN x, GEN y) { return compreal0(x,y,1); }
1186:
1187: GEN
1188: compimag(GEN x, GEN y) { return compimag0(x,y,0); }
1189:
1190: GEN
1191: compimagraw(GEN x, GEN y) { return compimag0(x,y,1); }
1192:
1193: GEN
1194: compraw(GEN x, GEN y)
1195: {
1196: return (typ(x)==t_QFI)? compimagraw(x,y): comprealraw(x,y);
1197: }
1198:
1199: GEN
1200: sqcompimag0(GEN x, long raw)
1201: {
1202: long av = avma;
1203: GEN z = cgetg(4,t_QFI);
1204:
1205: if (typ(x)!=t_QFI) err(typeer,"composition");
1206: sq_gen(z,x);
1207: if (raw) return gerepilecopy(av,z);
1208: return gerepileupto(av,redimag(z));
1209: }
1210:
1211: static GEN
1212: sqcompreal0(GEN x, long raw)
1213: {
1214: long av = avma;
1215: GEN z = cgetg(5,t_QFR);
1216:
1217: if (typ(x)!=t_QFR) err(typeer,"composition");
1218: sq_gen(z,x); z[4]=lshiftr((GEN)x[4],1);
1219: if (raw) return gerepilecopy(av,z);
1220: return gerepileupto(av,redreal(z));
1221: }
1222:
1223: GEN
1224: sqcompreal(GEN x) { return sqcompreal0(x,0); }
1225:
1226: GEN
1227: sqcomprealraw(GEN x) { return sqcompreal0(x,1); }
1228:
1229: GEN
1230: sqcompimag(GEN x) { return sqcompimag0(x,0); }
1231:
1232: GEN
1233: sqcompimagraw(GEN x) { return sqcompimag0(x,1); }
1234:
1235: static GEN
1236: real_unit_form_by_disc(GEN D, long prec)
1237: {
1238: GEN y = cgetg(5,t_QFR), isqrtD;
1239: long av = avma;
1240:
1241: if (typ(D) != t_INT || signe(D) <= 0) err(typeer,"real_unit_form_by_disc");
1242: switch(mod4(D))
1243: {
1244: case 2:
1245: case 3: err(funder2,"real_unit_form_by_disc");
1246: }
1247: y[1]=un; isqrtD = racine(D);
1248: /* we know that D and isqrtD are non-zero */
1249: if (mod2(D) != mod2(isqrtD))
1250: isqrtD = gerepileuptoint(av, addsi(-1,isqrtD));
1251: y[2] = (long)isqrtD; av = avma;
1252: y[3] = (long)gerepileuptoint(av, shifti(subii(sqri(isqrtD),D),-2));
1253: y[4] = (long)realzero(prec); return y;
1254: }
1255:
1256: GEN
1257: real_unit_form(GEN x)
1258: {
1259: long av = avma, prec;
1260: GEN D;
1261: if (typ(x) != t_QFR) err(typeer,"real_unit_form");
1262: prec = precision((GEN)x[4]);
1263: if (!prec) err(talker,"not a t_REAL in 4th component of a t_QFR");
1264: D = qf_disc(x,NULL,NULL);
1265: return gerepileupto(av, real_unit_form_by_disc(D,prec));
1266: }
1267:
1268: static GEN
1269: imag_unit_form_by_disc(GEN D)
1270: {
1271: GEN y = cgetg(4,t_QFI);
1272: long isodd;
1273:
1274: if (typ(D) != t_INT || signe(D) >= 0) err(typeer,"real_unit_form_by_disc");
1275: switch(4 - mod4(D))
1276: {
1277: case 2:
1278: case 3: err(funder2,"imag_unit_form_by_disc");
1279: }
1280: y[1] = un; isodd = mpodd(D);
1281: y[2] = isodd? un: zero;
1282: /* y[3] = (1-D) / 4 or -D / 4, whichever is an integer */
1283: y[3] = lshifti(D,-2); setsigne(y[3],1);
1284: if (isodd)
1285: {
1286: long av = avma;
1287: y[3] = (long)gerepileuptoint(av, addis((GEN)y[3],1));
1288: }
1289: return y;
1290: }
1291:
1292: GEN
1293: imag_unit_form(GEN x)
1294: {
1295: GEN p1,p2, y = cgetg(4,t_QFI);
1296: long av;
1297: if (typ(x) != t_QFI) err(typeer,"imag_unit_form");
1298: y[1] = un;
1299: y[2] = mpodd((GEN)x[2])? un: zero;
1300: av = avma; p1 = mulii((GEN)x[1],(GEN)x[3]);
1301: p2 = shifti(sqri((GEN)x[2]),-2);
1302: y[3] = (long)gerepileuptoint(av, subii(p1,p2));
1303: return y;
1304: }
1305:
1306: GEN
1307: powrealraw(GEN x, long n)
1308: {
1309: long av = avma, m;
1310: GEN y;
1311:
1312: if (typ(x) != t_QFR)
1313: err(talker,"not a real quadratic form in powrealraw");
1314: if (!n) return real_unit_form(x);
1315: if (n== 1) return gcopy(x);
1316: if (n==-1) return ginv(x);
1317:
1318: y = NULL; m=labs(n);
1319: for (; m>1; m>>=1)
1320: {
1321: if (m&1) y = y? comprealraw(y,x): x;
1322: x=sqcomprealraw(x);
1323: }
1324: y = y? comprealraw(y,x): x;
1325: if (n<0) y = ginv(y);
1326: return gerepileupto(av,y);
1327: }
1328:
1329: GEN
1330: powimagraw(GEN x, long n)
1331: {
1332: long av = avma, m;
1333: GEN y;
1334:
1335: if (typ(x) != t_QFI)
1336: err(talker,"not an imaginary quadratic form in powimag");
1337: if (!n) return imag_unit_form(x);
1338: if (n== 1) return gcopy(x);
1339: if (n==-1) return ginv(x);
1340:
1341: y = NULL; m=labs(n);
1342: for (; m>1; m>>=1)
1343: {
1344: if (m&1) y = y? compimagraw(y,x): x;
1345: x=sqcompimagraw(x);
1346: }
1347: y = y? compimagraw(y,x): x;
1348: if (n<0) y = ginv(y);
1349: return gerepileupto(av,y);
1350: }
1351:
1352: GEN
1353: powraw(GEN x, long n)
1354: {
1355: return (typ(x)==t_QFI)? powimagraw(x,n): powrealraw(x,n);
1356: }
1357:
1358: /* composition: Shanks' NUCOMP & NUDUPL */
1359: /* l = floor((|d|/4)^(1/4)) */
1360: GEN
1361: nucomp(GEN x, GEN y, GEN l)
1362: {
1363: long av=avma,tetpil,cz;
1364: GEN a,a1,a2,b,b2,d,d1,e,g,n,p1,p2,p3,q1,q2,q3,q4,s,t2,t3,u,u1,v,v1,v2,v3,z;
1365:
1366: if (x==y) return nudupl(x,l);
1367: if (typ(x) != t_QFI || typ(y) != t_QFI)
1368: err(talker,"not an imaginary quadratic form in nucomp");
1369:
1370: if (cmpii((GEN)x[1],(GEN)y[1]) < 0) { s=x; x=y; y=s; }
1371: s=shifti(addii((GEN)x[2],(GEN)y[2]),-1); n=subii((GEN)y[2],s);
1372: a1=(GEN)x[1]; a2=(GEN)y[1]; d=bezout(a2,a1,&u,&v);
1373: if (gcmp1(d)) { a=negi(gmul(u,n)); d1=d; }
1374: else
1375: if (divise(s,d))
1376: {
1377: a=negi(gmul(u,n)); d1=d; a1=divii(a1,d1);
1378: a2=divii(a2,d1); s=divii(s,d1);
1379: }
1380: else
1381: {
1382: d1=bezout(s,d,&u1,&v1);
1383: if (!gcmp1(d1))
1384: {
1385: a1=divii(a1,d1); a2=divii(a2,d1);
1386: s=divii(s,d1); d=divii(d,d1);
1387: }
1388: p1=resii((GEN)x[3],d); p2=resii((GEN)y[3],d);
1389: p3=modii(negi(mulii(u1,addii(mulii(u,p1),mulii(v,p2)))),d);
1390: a=subii(mulii(p3,divii(a1,d)),mulii(u,divii(n,d)));
1391: }
1392: a=modii(a,a1); p1=subii(a1,a); if (cmpii(a,p1)>0) a=negi(p1);
1393: v=gzero; d=a1; v2=gun; v3=a;
1394: for (cz=0; absi_cmp(v3,l) > 0; cz++)
1395: {
1396: p1=dvmdii(d,v3,&t3); t2=subii(v,mulii(p1,v2));
1397: v=v2; d=v3; v2=t2; v3=t3;
1398: }
1399: z=cgetg(4,t_QFI);
1400: if (!cz)
1401: {
1402: q1=mulii(a2,v3); q2=addii(q1,n);
1403: g=divii(addii(mulii(v3,s),(GEN)y[3]),d);
1404: z[1]=lmulii(d,a2);
1405: z[2]=laddii(shifti(q1,1),(GEN)y[2]);
1406: z[3]=laddii(mulii(v3,divii(q2,d)), mulii(g,d1));
1407: }
1408: else
1409: {
1410: if (cz&1) { v3=negi(v3); v2=negi(v2); }
1411: b=divii(addii(mulii(a2,d),mulii(n,v)),a1);
1412: q1=mulii(b,v3); q2=addii(q1,n);
1413: e=divii(addii(mulii(s,d),mulii((GEN)y[3],v)),a1);
1414: q3=mulii(e,v2); q4=subii(q3,s);
1415: g=divii(q4,v); b2=addii(q3,q4);
1416: if (!gcmp1(d1)) { v2=mulii(d1,v2); v=mulii(d1,v); b2=mulii(d1,b2); }
1417: z[1]=laddii(mulii(d,b),mulii(e,v));
1418: z[2]=laddii(b2,addii(q1,q2));
1419: z[3]=laddii(mulii(v3,divii(q2,d)), mulii(g,v2));
1420: }
1421: tetpil=avma; return gerepile(av,tetpil,redimag(z));
1422: }
1423:
1424: GEN
1425: nudupl(GEN x, GEN l)
1426: {
1427: long av=avma,tetpil,cz;
1428: GEN u,v,d,d1,p1,a,b,c,b2,z,v2,v3,t2,t3,e,g;
1429:
1430: if (typ(x) != t_QFI)
1431: err(talker,"not an imaginary quadratic form in nudupl");
1432: d1=bezout((GEN)x[2],(GEN)x[1],&u,&v);
1433: a=divii((GEN)x[1],d1); b=divii((GEN)x[2],d1);
1434: c=modii(negi(mulii(u,(GEN)x[3])),a); p1=subii(a,c);
1435: if (cmpii(c,p1)>0) c=negi(p1);
1436: v=gzero; d=a; v2=gun; v3=c;
1437: for (cz=0; absi_cmp(v3,l) > 0; cz++)
1438: {
1439: p1=dvmdii(d,v3,&t3); t2=subii(v,mulii(p1,v2));
1440: v=v2; d=v3; v2=t2; v3=t3;
1441: }
1442: z=cgetg(4,t_QFI);
1443: if (!cz)
1444: {
1445: g=divii(addii(mulii(v3,b),(GEN)x[3]),d);
1446: z[1]=(long)sqri(d);
1447: z[2]=laddii((GEN)x[2],shifti(mulii(d,v3),1));
1448: z[3]=laddii(sqri(v3),mulii(g,d1));
1449: }
1450: else
1451: {
1452: if (cz&1) { v=negi(v); d=negi(d); }
1453: e=divii(addii(mulii((GEN)x[3],v),mulii(b,d)),a);
1454: g=divii(subii(mulii(e,v2),b),v);
1455: b2=addii(mulii(e,v2),mulii(v,g));
1456: if (!gcmp1(d1)) { v2=mulii(d1,v2); v=mulii(d1,v); b2=mulii(d1,b2); }
1457: z[1]=laddii(sqri(d),mulii(e,v));
1458: z[2]=laddii(b2,shifti(mulii(d,v3),1));
1459: z[3]=laddii(sqri(v3),mulii(g,v2));
1460: }
1461: tetpil=avma; return gerepile(av,tetpil,redimag(z));
1462: }
1463:
1464: GEN
1465: nupow(GEN x, GEN n)
1466: {
1467: long av,tetpil,i,j;
1468: unsigned long m;
1469: GEN y,l;
1470:
1471: if (typ(n) != t_INT) err(talker,"not an integer exponent in nupow");
1472: if (gcmp1(n)) return gcopy(x);
1473: av=avma; y = imag_unit_form(x);
1474: if (!signe(n)) return y;
1475:
1476: l = racine(shifti(racine((GEN)y[3]),1));
1477: for (i=lgefint(n)-1; i>2; i--)
1478: for (m=n[i],j=0; j<BITS_IN_LONG; j++,m>>=1)
1479: {
1480: if (m&1) y=nucomp(y,x,l);
1481: x=nudupl(x,l);
1482: }
1483: for (m=n[2]; m>1; m>>=1)
1484: {
1485: if (m&1) y=nucomp(y,x,l);
1486: x=nudupl(x,l);
1487: }
1488: tetpil=avma; y=nucomp(y,x,l);
1489: if (signe(n)<0 && !egalii((GEN)y[1],(GEN)y[2])
1490: && !egalii((GEN)y[1],(GEN)y[3]))
1491: setsigne(y[2],-signe(y[2]));
1492: return gerepile(av,tetpil,y);
1493: }
1494:
1495: /* reduction */
1496:
1497: static GEN
1498: abs_dvmdii(GEN b, GEN p1, GEN *pt, long s)
1499: {
1500: if (s<0) setsigne(b, 1); p1 = dvmdii(b,p1,pt);
1501: if (s<0) setsigne(b,-1); return p1;
1502: }
1503:
1504: static GEN
1505: rhoimag0(GEN x, long *flag)
1506: {
1507: GEN p1,b,d,z;
1508: long fl, s = signe(x[2]);
1509:
1510: fl = cmpii((GEN)x[1], (GEN)x[3]);
1511: if (fl <= 0)
1512: {
1513: long fg = absi_cmp((GEN)x[1], (GEN)x[2]);
1514: if (fg >= 0)
1515: {
1516: *flag = (s<0 && (!fl || !fg))? 2 /* set x[2] = negi(x[2]) in caller */
1517: : 1;
1518: return x;
1519: }
1520: }
1521: p1=shifti((GEN)x[3],1); d = abs_dvmdii((GEN)x[2],p1,&b,s);
1522: if (s>=0)
1523: {
1524: setsigne(d,-signe(d));
1525: if (cmpii(b,(GEN)x[3])<=0) setsigne(b,-signe(b));
1526: else { d=addsi(-1,d); b=subii(p1,b); }
1527: }
1528: else if (cmpii(b,(GEN)x[3])>=0) { d=addsi(1,d); b=subii(b,p1); }
1529:
1530: z=cgetg(4,t_QFI);
1531: z[1] = x[3];
1532: z[3] = laddii((GEN)x[1], mulii(d,shifti(subii((GEN)x[2],b),-1)));
1533: if (signe(b)<0 && !fl) setsigne(b,1);
1534: z[2] = (long)b; *flag = 0; return z;
1535: }
1536:
1537: static void
1538: fix_expo(GEN x)
1539: {
1540: long e = expo(x[5]);
1541: if (e >= EXP220)
1542: {
1543: x[4] = laddsi(1,(GEN)x[4]);
1544: setexpo(x[5], e - EXP220);
1545: }
1546: }
1547:
1548: GEN
1549: rhoreal_aux(GEN x, GEN D, GEN sqrtD, GEN isqrtD)
1550: {
1551: GEN p1,p2, y = cgetg(6,t_VEC);
1552: GEN b = (GEN)x[2];
1553: GEN c = (GEN)x[3];
1554: long s = signe(c);
1555:
1556: y[1] = (long)c;
1557: p2 = (absi_cmp(isqrtD,c) >= 0)? isqrtD: c;
1558: setsigne(c,1);
1559: p1 = shifti(c,1);
1560: p2 = divii(addii(p2,b), p1);
1561: setsigne(c,s);
1562: y[2] = lsubii(mulii(p2,p1), b);
1563:
1564: p1 = shifti(subii(sqri((GEN)y[2]),D),-2);
1565: y[3] = ldivii(p1,(GEN)y[1]);
1566:
1567: if (lg(x) <= 5) setlg(y,4);
1568: else
1569: {
1570: y[4] = x[4];
1571: y[5] = x[5];
1572: if (signe(b))
1573: {
1574: p1 = divrr(addir(b,sqrtD), subir(b,sqrtD));
1575: y[5] = lmulrr(p1, (GEN)y[5]);
1576: fix_expo(y);
1577: }
1578: }
1579: return y;
1580: }
1581:
1582: #define qf_NOD 2
1583: #define qf_STEP 1
1584:
1585: GEN
1586: codeform5(GEN x, long prec)
1587: {
1588: GEN y = cgetg(6,t_VEC);
1589: y[1]=x[1];
1590: y[2]=x[2];
1591: y[3]=x[3];
1592: y[4]=zero;
1593: y[5]=(long)realun(prec); return y;
1594: }
1595:
1596: static GEN
1597: add_distance(GEN x, GEN d0)
1598: {
1599: GEN y = cgetg(5, t_QFR);
1600: y[1] = licopy((GEN)x[1]);
1601: y[2] = licopy((GEN)x[2]);
1602: y[3] = licopy((GEN)x[3]);
1603: y[4] = lcopy(d0); return y;
1604: }
1605:
1606: /* d0 = initial distance, assume |n| > 1 */
1607: static GEN
1608: decodeform(GEN x, GEN d0)
1609: {
1610: GEN p1,p2;
1611:
1612: if (lg(x) < 6) return add_distance(x,d0);
1613: /* x = (a,b,c, expo(d), d), d = exp(2*distance) */
1614: p1 = absr((GEN)x[5]);
1615: p2 = (GEN)x[4];
1616: if (signe(p2))
1617: {
1618: long e = expo(p1);
1619: p1 = shiftr(p1,-e);
1620: p2 = addis(mulsi(EXP220,p2), e);
1621: p1 = mplog(p1);
1622: p1 = mpadd(p1, mulir(p2, glog(gdeux, lg(d0))));
1623: }
1624: else
1625: { /* to avoid loss of precision */
1626: p1 = gcmp1(p1)? NULL: mplog(p1);
1627: }
1628: if (p1)
1629: d0 = addrr(d0, shiftr(p1,-1));
1630: return add_distance(x, d0);
1631: }
1632:
1633: static long
1634: get_prec(GEN d)
1635: {
1636: long k = lg(d);
1637: long l = ((BITS_IN_LONG-1-expo(d))>>TWOPOTBITS_IN_LONG)+2;
1638: if (l < k) l = k;
1639: if (l < 3) l = 3;
1640: return l;
1641: }
1642:
1643: static int
1644: real_isreduced(GEN x, GEN isqrtD)
1645: {
1646: GEN a = (GEN)x[1];
1647: GEN b = (GEN)x[2];
1648: if (signe(b) > 0 && cmpii(b,isqrtD) <= 0 )
1649: {
1650: GEN p1 = subii(isqrtD, shifti(absi(a),1));
1651: long l = absi_cmp(b, p1);
1652: if (l > 0 || (l == 0 && signe(p1) < 0)) return 1;
1653: }
1654: return 0;
1655: }
1656:
1657: GEN
1658: redrealform5(GEN x, GEN D, GEN sqrtD, GEN isqrtD)
1659: {
1660: while (!real_isreduced(x,isqrtD))
1661: x = rhoreal_aux(x,D,sqrtD,isqrtD);
1662: return x;
1663: }
1664:
1665: static GEN
1666: redreal0(GEN x, long flag, GEN D, GEN isqrtD, GEN sqrtD)
1667: {
1668: long av = avma, prec;
1669: GEN d0;
1670:
1671: if (typ(x) != t_QFR) err(talker,"not a real quadratic form in redreal");
1672:
1673: if (!D)
1674: D = qf_disc(x,NULL,NULL);
1675: else
1676: if (typ(D) != t_INT) err(arither1);
1677:
1678: d0 = (GEN)x[4]; prec = get_prec(d0);
1679: x = codeform5(x,prec);
1680: if ((flag & qf_NOD)) setlg(x,4);
1681: else
1682: {
1683: if (!sqrtD)
1684: sqrtD = gsqrt(D,prec);
1685: else
1686: {
1687: long l = typ(sqrtD);
1688: if (!is_intreal_t(l)) err(arither1);
1689: }
1690: }
1691: if (!isqrtD)
1692: isqrtD = sqrtD? mptrunc(sqrtD): racine(D);
1693: else
1694: if (typ(isqrtD) != t_INT) err(arither1);
1695:
1696: if (flag & qf_STEP)
1697: x = rhoreal_aux(x,D,sqrtD,isqrtD);
1698: else
1699: x = redrealform5(x,D,sqrtD,isqrtD);
1700: return gerepileupto(av, decodeform(x,d0));
1701: }
1702:
1703: GEN
1704: comprealform5(GEN x, GEN y, GEN D, GEN sqrtD, GEN isqrtD)
1705: {
1706: ulong av = avma;
1707: GEN z = cgetg(6,t_VEC); comp_gen(z,x,y);
1708: if (x == y)
1709: {
1710: z[4] = lshifti((GEN)x[4],1);
1711: z[5] = lsqr((GEN)x[5]);
1712: }
1713: else
1714: {
1715: z[4] = laddii((GEN)x[4],(GEN)y[4]);
1716: z[5] = lmulrr((GEN)x[5],(GEN)y[5]);
1717: }
1718: fix_expo(z); z = redrealform5(z,D,sqrtD,isqrtD);
1719: return gerepilecopy(av,z);
1720: }
1721:
1722: /* assume n!=0 */
1723: GEN
1724: powrealform(GEN x, GEN n)
1725: {
1726: long av = avma, i,m;
1727: GEN y,D,sqrtD,isqrtD,d0;
1728:
1729: if (typ(x) != t_QFR)
1730: err(talker,"not a real quadratic form in powreal");
1731: if (gcmp1(n)) return gcopy(x);
1732: if (gcmp_1(n)) return ginv(x);
1733:
1734: d0 = (GEN)x[4];
1735: D = qf_disc(x,NULL,NULL);
1736: sqrtD = gsqrt(D, get_prec(d0));
1737: isqrtD = mptrunc(sqrtD);
1738: if (signe(n) < 0) { x = ginv(x); d0 = (GEN)x[4]; }
1739: n = absi(n);
1740: x = codeform5(x, lg(d0)); y = NULL;
1741: for (i=lgefint(n)-1; i>1; i--)
1742: {
1743: m = n[i];
1744: for (; m; m>>=1)
1745: {
1746: if (m&1) y = y? comprealform5(y,x,D,sqrtD,isqrtD): x;
1747: if (m == 1 && i == 2) break;
1748: x = comprealform5(x,x,D,sqrtD,isqrtD);
1749: }
1750: }
1751: d0 = mulri(d0,n);
1752: return gerepileupto(av, decodeform(y,d0));
1753: }
1754:
1755: GEN
1756: redimag(GEN x)
1757: {
1758: long av=avma, fl;
1759: do x = rhoimag0(x, &fl); while (fl == 0);
1760: x = gerepilecopy(av,x);
1761: if (fl == 2) setsigne(x[2], -signe(x[2]));
1762: return x;
1763: }
1764:
1765: GEN
1766: redreal(GEN x)
1767: {
1768: return redreal0(x,0,NULL,NULL,NULL);
1769: }
1770:
1771: GEN
1772: rhoreal(GEN x)
1773: {
1774: return redreal0(x,qf_STEP,NULL,NULL,NULL);
1775: }
1776:
1777: GEN
1778: redrealnod(GEN x, GEN isqrtD)
1779: {
1780: return redreal0(x,qf_NOD,NULL,isqrtD,NULL);
1781: }
1782:
1783: GEN
1784: rhorealnod(GEN x, GEN isqrtD)
1785: {
1786: return redreal0(x,qf_STEP|qf_NOD,NULL,isqrtD,NULL);
1787: }
1788:
1789: GEN
1790: qfbred0(GEN x, long flag, GEN D, GEN isqrtD, GEN sqrtD)
1791: {
1792: long tx=typ(x),fl;
1793: ulong av;
1794:
1795: if (!is_qf_t(tx)) err(talker,"not a quadratic form in qfbred");
1796: if (!D) D = qf_disc(x,NULL,NULL);
1797: switch(signe(D))
1798: {
1799: case 1 :
1800: return redreal0(x,flag,D,isqrtD,sqrtD);
1801:
1802: case -1:
1803: if (!flag) return redimag(x);
1804: if (flag !=1) err(flagerr,"qfbred");
1805: av=avma; x = rhoimag0(x,&fl);
1806: x = gerepilecopy(av,x);
1807: if (fl == 2) setsigne(x[2], -signe(x[2]));
1808: return x;
1809: }
1810: err(redpoler,"qfbred");
1811: return NULL; /* not reached */
1812: }
1813:
1814: /* special case: p = 1 return unit form */
1815: GEN
1816: primeform(GEN x, GEN p, long prec)
1817: {
1818: long av,tetpil,s=signe(x);
1819: GEN y,b;
1820:
1821: if (typ(x) != t_INT || !s) err(arither1);
1822: if (typ(p) != t_INT || signe(p) <= 0) err(arither1);
1823: if (is_pm1(p))
1824: return s<0? imag_unit_form_by_disc(x)
1825: : real_unit_form_by_disc(x,prec);
1826: if (s < 0)
1827: {
1828: y = cgetg(4,t_QFI); s = 8-mod8(x);
1829: }
1830: else
1831: {
1832: y = cgetg(5,t_QFR); s = mod8(x);
1833: y[4]=(long)realzero(prec);
1834: }
1835: switch(s&3)
1836: {
1837: case 2: case 3: err(funder2,"primeform");
1838: }
1839: y[1] = (long)icopy(p); av = avma;
1840: if (egalii(p,gdeux))
1841: {
1842: switch(s)
1843: {
1844: case 0: y[2]=zero; break;
1845: case 8: s=0; y[2]=zero; break;
1846: case 1: s=1; y[2]=un; break;
1847: case 4: s=4; y[2]=deux; break;
1848: default: err(sqrter5);
1849: }
1850: b=subsi(s,x); tetpil=avma; b=shifti(b,-3);
1851: }
1852: else
1853: {
1854: b = mpsqrtmod(x,p); if (!b) err(sqrter5);
1855: if (mod2(b) == mod2(x)) y[2] = (long)b;
1856: else
1857: { tetpil = avma; y[2] = lpile(av,tetpil,subii(p,b)); }
1858:
1859: av=avma; b=shifti(subii(sqri((GEN)y[2]),x),-2);
1860: tetpil=avma; b=divii(b,p);
1861: }
1862: y[3]=lpile(av,tetpil,b); return y;
1863: }
1864:
1865: /*********************************************************************/
1866: /** **/
1867: /** BINARY DECOMPOSITION **/
1868: /** **/
1869: /*********************************************************************/
1870:
1871: GEN
1872: binaire(GEN x)
1873: {
1874: ulong m,u;
1875: long i,lx,ex,ly,tx=typ(x);
1876: GEN y,p1,p2;
1877:
1878: switch(tx)
1879: {
1880: case t_INT:
1881: lx=lgefint(x);
1882: if (lx==2) { y=cgetg(2,t_VEC); y[1]=zero; return y; }
1883: ly = BITS_IN_LONG+1; m=HIGHBIT; u=x[2];
1884: while (!(m & u)) { m>>=1; ly--; }
1885: y = cgetg(ly+((lx-3)<<TWOPOTBITS_IN_LONG),t_VEC); ly=1;
1886: do { y[ly] = m & u ? un : zero; ly++; } while (m>>=1);
1887: for (i=3; i<lx; i++)
1888: {
1889: m=HIGHBIT; u=x[i];
1890: do { y[ly] = m & u ? un : zero; ly++; } while (m>>=1);
1891: }
1892: break;
1893:
1894: case t_REAL:
1895: ex=expo(x);
1896: if (!signe(x))
1897: {
1898: lx=1+max(-ex,0); y=cgetg(lx,t_VEC);
1899: for (i=1; i<lx; i++) y[i]=zero;
1900: return y;
1901: }
1902:
1903: lx=lg(x); y=cgetg(3,t_VEC);
1904: if (ex > bit_accuracy(lx)) err(precer,"binary");
1905: p1 = cgetg(max(ex,0)+2,t_VEC);
1906: p2 = cgetg(bit_accuracy(lx)-ex,t_VEC);
1907: y[1] = (long) p1; y[2] = (long) p2;
1908: ly = -ex; ex++; m = HIGHBIT;
1909: if (ex<=0)
1910: {
1911: p1[1]=zero; for (i=1; i <= -ex; i++) p2[i]=zero;
1912: i=2;
1913: }
1914: else
1915: {
1916: ly=1;
1917: for (i=2; i<lx && ly<=ex; i++)
1918: {
1919: m=HIGHBIT; u=x[i];
1920: do
1921: { p1[ly] = (m & u) ? un : zero; ly++; }
1922: while ((m>>=1) && ly<=ex);
1923: }
1924: ly=1;
1925: if (m) i--; else m=HIGHBIT;
1926: }
1927: for (; i<lx; i++)
1928: {
1929: u=x[i];
1930: do { p2[ly] = m & u ? un : zero; ly++; } while (m>>=1);
1931: m=HIGHBIT;
1932: }
1933: break;
1934:
1935: case t_VEC: case t_COL: case t_MAT:
1936: lx=lg(x); y=cgetg(lx,tx);
1937: for (i=1; i<lx; i++) y[i]=(long)binaire((GEN)x[i]);
1938: break;
1939: default: err(typeer,"binaire");
1940: return NULL; /* not reached */
1941: }
1942: return y;
1943: }
1944:
1945: /* return 1 if bit n of x is set, 0 otherwise */
1946: long
1947: bittest(GEN x, long n)
1948: {
1949: long l;
1950:
1951: if (!signe(x) || n<0) return 0;
1952: l = lgefint(x)-1 - (n>>TWOPOTBITS_IN_LONG);
1953: if (l < 2) return 0;
1954: n = (1L << (n & (BITS_IN_LONG-1))) & x[l];
1955: return n? 1: 0;
1956: }
1957:
1958: static long
1959: bittestg(GEN x, GEN n)
1960: {
1961: return bittest(x,itos(n));
1962: }
1963:
1964: GEN
1965: gbittest(GEN x, GEN n)
1966: {
1967: return arith_proto2(bittestg,x,n);
1968: }
1969:
1970: /***********************************************************************/
1971: /** **/
1972: /** BITMAP OPS **/
1973: /** x & y (and), x | y (or), x ^ y (xor), ~x (neg), x & ~y (negimply) **/
1974: /** **/
1975: /***********************************************************************/
1976:
1977: /* Normalize a non-negative integer. */
1978: static void
1979: inormalize(GEN x, long known_zero_words)
1980: {
1981: int xl = lgefint(x);
1982: int i, j;
1983:
1984: /* Normalize */
1985: i = 2 + known_zero_words;
1986: while (i < xl) {
1987: if (x[i])
1988: break;
1989: i++;
1990: }
1991: j = 2;
1992: while (i < xl)
1993: x[j++] = x[i++];
1994: xl -= i - j;
1995: setlgefint(x, xl);
1996: if (xl == 2)
1997: setsigne(x,0);
1998: }
1999:
2000: /* Truncate a non-negative integer to a number of bits. */
2001: static void
2002: ibittrunc(GEN x, long bits, long normalized)
2003: {
2004: int xl = lgefint(x);
2005: int len_out = ((bits + BITS_IN_LONG - 1) >> TWOPOTBITS_IN_LONG) + 2;
2006: int known_zero_words, i = 2 + xl - len_out;
2007:
2008: if (xl < len_out && normalized)
2009: return;
2010: /* Check whether mask is trivial */
2011: if (!(bits & (BITS_IN_LONG - 1))) {
2012: if (xl == len_out && normalized)
2013: return;
2014: } else if (len_out <= xl) {
2015: /* Non-trival mask is given by a formula, if x is not
2016: normalized, this works even in the exceptional case */
2017: x[i] = x[i] & ((1 << (bits & (BITS_IN_LONG - 1))) - 1);
2018: if (x[i] && xl == len_out)
2019: return;
2020: }
2021: /* Normalize */
2022: if (xl <= len_out) /* Not normalized */
2023: known_zero_words = 0;
2024: else
2025: known_zero_words = xl - len_out;
2026: inormalize(x, known_zero_words);
2027: }
2028:
2029: /* Increment/decrement absolute value of non-zero integer in place.
2030: It is assumed that the increment will not increase the length.
2031: Decrement may result in a non-normalized value.
2032: Returns 1 if the increment overflows (thus the result is 0). */
2033: static int
2034: incdec(GEN x, long incdec)
2035: {
2036: long *xf = x + 2, *xl;
2037: long len = lgefint(x);
2038: const ulong uzero = 0;
2039:
2040: xl = x + len;
2041: if (incdec == 1) {
2042: while (--xl >= xf) {
2043: if ((ulong)*xl != ~uzero) {
2044: (*xl)++;
2045: return 0;
2046: }
2047: *xl = 0;
2048: }
2049: return 1;
2050: } else {
2051: while (--xl >= xf) {
2052: if (*xl != 0) {
2053: (*xl)--;
2054: return 0;
2055: }
2056: *xl = (long)~uzero;
2057: }
2058: return 0;
2059: }
2060: }
2061:
2062: GEN
2063: gbitneg(GEN x, long bits)
2064: {
2065: long xl, len_out, i;
2066: const ulong uzero = 0;
2067:
2068: if (typ(x) != t_INT)
2069: err(typeer, "bitwise negation");
2070: if (bits < -1)
2071: err(talker, "negative exponent in bitwise negation");
2072: if (bits == -1)
2073: return gsub(gneg(gun),x);
2074: if (bits == 0)
2075: return gzero;
2076: if (signe(x) == -1) { /* Consider as if mod big power of 2 */
2077: x = gcopy(x);
2078: setsigne(x, 1);
2079: incdec(x, -1);
2080: /* Now truncate this! */
2081: ibittrunc(x, bits, x[2]);
2082: return x;
2083: }
2084: xl = lgefint(x);
2085: len_out = ((bits + BITS_IN_LONG - 1) >> TWOPOTBITS_IN_LONG) + 2;
2086: if (len_out > xl) { /* Need to grow */
2087: GEN out = cgeti(len_out);
2088: int j = 2;
2089:
2090: if (!(bits & (BITS_IN_LONG - 1)))
2091: out[2] = ~uzero;
2092: else
2093: out[2] = (1 << (bits & (BITS_IN_LONG - 1))) - 1;
2094: for (i = 3; i < len_out - xl + 2; i++)
2095: out[i] = ~uzero;
2096: while (i < len_out)
2097: out[i++] = ~x[j++];
2098: setlgefint(out, len_out);
2099: setsigne(out,1);
2100: return out;
2101: }
2102: x = gcopy(x);
2103: for (i = 2; i < xl; i++)
2104: x[i] = ~x[i];
2105: ibittrunc(x, bits, x[2]);
2106: return x;
2107: }
2108:
2109: /* bitwise 'and' of two positive integers (any integers, but we ignore sign).
2110: * Inputs are not necessary normalized. */
2111: static GEN
2112: ibitand(GEN x, GEN y)
2113: {
2114: long lx, ly, lout;
2115: long *xp, *yp, *outp, *xlim;
2116: GEN out;
2117:
2118: lx=lgefint(x); ly=lgefint(y);
2119: if (lx > ly)
2120: lout = ly;
2121: else
2122: lout = lx;
2123: xlim = x + lx;
2124: xp = xlim + 2 - lout;
2125: yp = y + 2 + ly - lout;
2126: out = cgeti(lout);
2127: outp = out + 2;
2128: while (xp < xlim)
2129: *outp++ = (*xp++) & (*yp++);
2130: setsigne(out,1);
2131: setlgefint(out,lout);
2132: if (lout == 2)
2133: setsigne(out,0);
2134: else if ( !out[2] )
2135: inormalize(out, 1);
2136: return out;
2137: }
2138:
2139: #define swaplen(x,y, nx,ny) {long _a=nx;GEN _z=x; nx=ny; ny=_a; x=y; y=_z;}
2140:
2141: /* bitwise 'or' of two positive integers (any integers, but we ignore sign).
2142: * Inputs are not necessary normalized. */
2143: static GEN
2144: ibitor(GEN x, GEN y, long exclusive)
2145: {
2146: long lx, ly, lout;
2147: long *xp, *yp, *outp, *xlim, *xprep;
2148: GEN out;
2149:
2150: lx=lgefint(x); ly=lgefint(y);
2151: if (lx < ly)
2152: swaplen(x,y,lx,ly);
2153: lout = lx;
2154: xlim = x + lx;
2155: xp = xlim + 2 - ly;
2156: yp = y + 2;
2157: out = cgeti(lout);
2158: outp = out + 2;
2159: if (lx > ly) {
2160: xprep = x + 2;
2161: while (xprep < xp)
2162: *outp++ = *xprep++;
2163: }
2164: if (exclusive) {
2165: while (xp < xlim)
2166: *outp++ = (*xp++) ^ (*yp++);
2167: } else {
2168: while (xp < xlim)
2169: *outp++ = (*xp++) | (*yp++);
2170: }
2171: setsigne(out,1);
2172: setlgefint(out,lout);
2173: if (lout == 2)
2174: setsigne(out,0);
2175: else if ( !out[2] )
2176: inormalize(out, 1);
2177: return out;
2178: }
2179:
2180: /* bitwise negated 'implies' of two positive integers (any integers, but we
2181: * ignore sign). "Neg-Implies" is x & ~y unless "negated".
2182: * Inputs are not necessary normalized. */
2183: static GEN
2184: ibitnegimply(GEN x, GEN y)
2185: {
2186: long lx, ly, lout, inverted = 0;
2187: long *xp, *yp, *outp, *xlim, *xprep;
2188: GEN out;
2189:
2190: lx=lgefint(x); ly=lgefint(y);
2191: if (lx < ly) {
2192: inverted = 1;
2193: swaplen(x,y,lx,ly);
2194: }
2195: /* x is longer than y */
2196: lout = lx;
2197: xlim = x + lx;
2198: xp = xlim + 2 - ly;
2199: yp = y + 2;
2200: out = cgeti(lout);
2201: outp = out + 2;
2202: if (lx > ly) {
2203: xprep = x + 2;
2204: if (!inverted) { /* x & ~y */
2205: while (xprep < xp)
2206: *outp++ = *xprep++;
2207: } else { /* ~x & y */
2208: while (xprep++ < xp)
2209: *outp++ = 0;
2210: }
2211: }
2212: if (inverted) { /* ~x & y */
2213: while (xp < xlim)
2214: *outp++ = ~(*xp++) & (*yp++);
2215: } else {
2216: while (xp < xlim)
2217: *outp++ = (*xp++) & ~(*yp++);
2218: }
2219: setsigne(out,1);
2220: setlgefint(out,lout);
2221: if (lout == 2)
2222: setsigne(out,0);
2223: else if ( !out[2] )
2224: inormalize(out, 1);
2225: return out;
2226: }
2227:
2228: static GEN
2229: inegate_inplace(GEN z, long ltop)
2230: {
2231: long lbot, o;
2232:
2233: /* Negate z */
2234: o = incdec(z, 1); /* Can overflow z... */
2235: setsigne(z, -1);
2236: if (!o)
2237: return z;
2238: else if (lgefint(z) == 2)
2239: setsigne(z, 0);
2240: incdec(z,-1); /* Restore a normalized value */
2241: lbot = avma;
2242: z = gsub(z,gun);
2243: return gerepile(ltop,lbot,z);
2244: }
2245:
2246: GEN
2247: gbitor(GEN x, GEN y)
2248: {
2249: long sx,sy;
2250: long ltop;
2251: GEN z;
2252:
2253: if (typ(x) != t_INT || typ(y) != t_INT)
2254: err(typeer, "bitwise or");
2255: sx=signe(x); if (!sx) return icopy(y);
2256: sy=signe(y); if (!sy) return icopy(x);
2257: if (sx == 1) {
2258: if (sy == 1)
2259: return ibitor(x,y,0);
2260: goto posneg;
2261: } else if (sy == -1) {
2262: ltop = avma;
2263: incdec(x, -1); incdec(y, -1);
2264: z = ibitand(x,y);
2265: incdec(x, 1); incdec(y, 1); /* Restore x and y... */
2266: } else {
2267: z = x; x = y; y = z;
2268: /* x is positive, y is negative. The result will be negative. */
2269: posneg:
2270: ltop = avma;
2271: incdec(y, -1);
2272: z = ibitnegimply(y,x); /* ~x & y */
2273: incdec(y, 1);
2274: }
2275: return inegate_inplace(z, ltop);
2276: }
2277:
2278: GEN
2279: gbitand(GEN x, GEN y)
2280: {
2281: long sx,sy;
2282: long ltop;
2283: GEN z;
2284:
2285: if (typ(x) != t_INT || typ(y) != t_INT)
2286: err(typeer, "bitwise and");
2287: sx=signe(x); if (!sx) return gzero;
2288: sy=signe(y); if (!sy) return gzero;
2289: if (sx == 1) {
2290: if (sy == 1)
2291: return ibitand(x,y);
2292: goto posneg;
2293: } else if (sy == -1) {
2294: ltop = avma;
2295: incdec(x, -1); incdec(y, -1);
2296: z = ibitor(x,y,0);
2297: incdec(x, 1); incdec(y, 1); /* Restore x and y... */
2298: return inegate_inplace(z, ltop);
2299: } else {
2300: z = x; x = y; y = z;
2301: /* x is positive, y is negative. The result will be positive. */
2302: posneg:
2303: ltop = avma;
2304: incdec(y, -1);
2305: /* x & ~y */
2306: z = ibitnegimply(x,y); /* x & ~y */
2307: incdec(y, 1);
2308: return z;
2309: }
2310: }
2311:
2312: GEN
2313: gbitxor(GEN x, GEN y)
2314: {
2315: long sx,sy;
2316: long ltop;
2317: GEN z;
2318:
2319: if (typ(x) != t_INT || typ(y) != t_INT)
2320: err(typeer, "bitwise xor");
2321: sx=signe(x); if (!sx) return icopy(y);
2322: sy=signe(y); if (!sy) return icopy(x);
2323: if (sx == 1) {
2324: if (sy == 1)
2325: return ibitor(x,y,1);
2326: goto posneg;
2327: } else if (sy == -1) {
2328: incdec(x, -1); incdec(y, -1);
2329: z = ibitor(x,y,1);
2330: incdec(x, 1); incdec(y, 1); /* Restore x and y... */
2331: return z;
2332: } else {
2333: z = x; x = y; y = z;
2334: /* x is positive, y is negative. The result will be negative. */
2335: posneg:
2336: ltop = avma;
2337: incdec(y, -1);
2338: /* ~(x ^ ~y) == x ^ y */
2339: z = ibitor(x,y,1);
2340: incdec(y, 1);
2341: }
2342: return inegate_inplace(z, ltop);
2343: }
2344:
2345: GEN
2346: gbitnegimply(GEN x, GEN y) /* x & ~y */
2347: {
2348: long sx,sy;
2349: long ltop;
2350: GEN z;
2351:
2352: if (typ(x) != t_INT || typ(y) != t_INT)
2353: err(typeer, "bitwise negated imply");
2354: sx=signe(x); if (!sx) return gzero;
2355: sy=signe(y); if (!sy) return icopy(x);
2356: if (sx == 1) {
2357: if (sy == 1)
2358: return ibitnegimply(x,y);
2359: /* x is positive, y is negative. The result will be positive. */
2360: incdec(y, -1);
2361: z = ibitand(x,y);
2362: incdec(y, 1);
2363: return z;
2364: } else if (sy == -1) {
2365: /* both negative. The result will be positive. */
2366: incdec(x, -1); incdec(y, -1);
2367: /* ((~x) & ~(~y)) == ~x & y */
2368: z = ibitnegimply(y,x);
2369: incdec(x, 1); incdec(y, 1); /* Restore x and y... */
2370: return z;
2371: } else {
2372: /* x is negative, y is positive. The result will be negative. */
2373: ltop = avma;
2374: incdec(x, -1);
2375: /* ~((~x) & ~y) == x | y */
2376: z = ibitor(x,y,0);
2377: incdec(x, 1);
2378: }
2379: return inegate_inplace(z, ltop);
2380: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>