[BACK]Return to arith2.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari-2.2 / src / basemath

Annotation of OpenXM_contrib/pari-2.2/src/basemath/arith2.c, Revision 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>