[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

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>