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

Annotation of OpenXM_contrib/pari/src/basemath/arith2.c, Revision 1.1.1.1

1.1       maekawa     1: /*********************************************************************/
                      2: /**                                                                 **/
                      3: /**                     ARITHMETIC FUNCTIONS                        **/
                      4: /**                        (second part)                            **/
                      5: /**                                                                 **/
                      6: /*********************************************************************/
                      7: /* $Id: arith2.c,v 1.1.1.1 1999/09/16 13:47:17 karim Exp $ */
                      8: #include "pari.h"
                      9:
                     10: GEN arith_proto(long f(GEN), GEN x, int do_error);
                     11: GEN garith_proto(GEN f(GEN), GEN x, int do_error);
                     12: GEN garith_proto2gs(GEN f(GEN,long), GEN x, long y);
                     13: static long court_p[]={evaltyp(t_INT)|m_evallg(3),evalsigne(1)|evallgefint(3),0};
                     14:
                     15: /***********************************************************************/
                     16: /**                                                                   **/
                     17: /**                          PRIME NUMBERS                            **/
                     18: /**                                                                   **/
                     19: /***********************************************************************/
                     20:
                     21: GEN
                     22: prime(long n)
                     23: {
                     24:   byteptr p = diffptr;
                     25:   long c, prime = 0;
                     26:
                     27:   while (n--)
                     28:   {
                     29:     c = *p++; if (!c) err(primer1);
                     30:     prime += c;
                     31:   }
                     32:   return stoi(prime);
                     33: }
                     34:
                     35: GEN
                     36: primes(long n)
                     37: {
                     38:   byteptr p = diffptr;
                     39:   long c, prime = 0;
                     40:   GEN y,z;
                     41:
                     42:   z = y = cgetg(n+1,t_VEC);
                     43:   while (n--)
                     44:   {
                     45:     c = *p++; if (!c) err(primer1);
                     46:     prime += c; *++z = lstoi(prime);
                     47:   }
                     48:   return y;
                     49: }
                     50:
                     51: /* Building/Rebuilding the diffptr table. Incorporates Ilya Zakharevich's
                     52:  * block sweep algorithm  (see pari-dev-111, 25 April 1998).  The actual work
                     53:  * is done by the following two subroutines;  the user entry point is the
                     54:  * function initprimes() below.  initprimes1() is the old algorithm, called
                     55:  * when maxnum (size) is moderate.
                     56:  */
                     57: static byteptr
                     58: initprimes1(long size, long *lenp, long *lastp)
                     59: {
                     60:   long k;
                     61:   byteptr q,r,s,fin, p = (byteptr) gpmalloc(size+2);
                     62:
                     63:   memset(p, 0, size + 2); fin = p + size;
                     64:   for (r=q=p,k=1; r<=fin; )
                     65:   {
                     66:     do { r+=k; k+=2; r+=k; } while (*++q);
                     67:     for (s=r; s<=fin; s+=k) *s=1;
                     68:   }
                     69:   r=p; *r++=2; *r++=1; /* 2 and 3 */
                     70:   for (s=q=r-1; ; s=q)
                     71:   {
                     72:     do q++; while (*q);
                     73:     if (q>fin) break;
                     74:     *r++ = (q-s) << 1;
                     75:   }
                     76:   *r++=0;
                     77:   *lenp = r - p;
                     78:   *lastp = ((s - p) << 1) + 1;
                     79: #if 0
                     80:   fprintferr("initprimes1: q = %ld, len = %ld, last = %ld\n",
                     81:             q, *lenp, *lastp);
                     82: #endif
                     83:   return (byteptr) gprealloc(p,r-p,size + 2);
                     84: }
                     85:
                     86: #define PRIME_ARENA (512 * 1024)
                     87:
                     88: /* Here's the workhorse.  This is recursive, although normally the first
                     89:    recursive call will bottom out and invoke initprimes1() at once.
                     90:    (Not static;  might conceivably be useful to someone in library mode) */
                     91: byteptr
                     92: initprimes0(ulong maxnum, long *lenp, long *lastp)
                     93: {
                     94:   long k, size, alloced, asize, psize, rootnum, curlow, last, remains, need;
                     95:   byteptr q,r,s,fin, p, p1, fin1, plast, curdiff;
                     96:
                     97: #if 0
                     98:   fprintferr("initprimes0: called for maxnum = %lu\n", maxnum);
                     99: #endif
                    100:   if (maxnum <= 1ul<<17)       /* Arbitrary. */
                    101:     return initprimes1(maxnum>>1, lenp, lastp);
                    102:
                    103:   maxnum |= 1;                 /* make it odd. */
                    104:
                    105:   /* Checked to be enough up to 40e6, attained at 155893 */
                    106:   size = (long) (1.09 * maxnum/log((double)maxnum)) + 145;
                    107:   p1 = (byteptr) gpmalloc(size);
                    108:   rootnum = (long) sqrt((double)maxnum); /* cast it back to a long */
                    109:   rootnum |= 1;
                    110: #if 0
                    111:   fprintferr("initprimes0: rootnum = %ld\n", rootnum);
                    112: #endif
                    113:   {
                    114:     byteptr p2 = initprimes0(rootnum, &psize, &last); /* recursive call */
                    115:     memcpy(p1, p2, psize); free(p2);
                    116:   }
                    117:   fin1 = p1 + psize - 1;
                    118:   remains = (maxnum - rootnum) >> 1; /* number of odd numbers to check */
                    119:
                    120:   need = 100 * rootnum;                /* Make % overhead negligeable. */
                    121:   if (need < PRIME_ARENA) need = PRIME_ARENA;
                    122:   if (avma - bot < need>>1) {  /* need to do our own allocation */
                    123:     alloced = 1; asize = need;
                    124:   } else {                     /* scratch area is free part of PARI stack */
                    125:     alloced = 0; asize = avma - bot;
                    126:   }
                    127:   if (asize > remains) asize = remains + 1;/* + room for a sentinel byte */
                    128:   if (alloced)
                    129:     p = (byteptr) gpmalloc(asize);
                    130:   else
                    131:     p = (byteptr) bot;
                    132:   fin = p + asize - 1;         /* the 0 sentinel goes at fin. */
                    133:   curlow = rootnum + 2;                /* We know all primes up to rootnum (odd). */
                    134:   curdiff = fin1;
                    135:
                    136:   /* During each iteration p..fin-1 represents a range of odd
                    137:      numbers.  plast is a pointer which represents the last prime seen,
                    138:      it may point before p..fin-1. */
                    139:   plast = p - ((rootnum - last) >> 1) - 1;
                    140:   while (remains)
                    141:   {
                    142:     if (asize > remains)
                    143:     {
                    144:       asize = remains + 1;
                    145:       fin = p + asize - 1;
                    146:     }
                    147:     memset(p, 0, asize);
                    148:     /* p corresponds to curlow.  q runs over primediffs.  */
                    149:     for (q = p1+2, k = 3; q <= fin1; k += *q++)
                    150:     {
                    151:       /* The first odd number which is >= curlow and divisible by p
                    152:        equals (if curlow > p)
                    153:         the last odd number which is <= curlow + 2p - 1 and 0 (mod p)
                    154:        which equals
                    155:         p + the last even number which is <= curlow + p - 1 and 0 (mod p)
                    156:        which equals
                    157:         p + the last even number which is <= curlow + p - 2 and 0 (mod p)
                    158:        which equals
                    159:         p + curlow + p - 2 - (curlow + p - 2)) % 2p.
                    160:        */
                    161:       long k2 = k*k - curlow;
                    162:
                    163:       if (k2 > 0)
                    164:       {
                    165:        r = p + (k2 >>= 1);
                    166:        if (k2 > remains) break; /* Guard against an address wrap. */
                    167:       } else
                    168:        r = p - (((curlow+k-2) % (2*k)) >> 1) + k - 1;
                    169:       for (s = r; s < fin; s += k) *s = 1;
                    170:     }
                    171:     /* now q runs over addresses corresponding to primes */
                    172:     for (q = p; ; plast = q++)
                    173:     {
                    174:       while (*q) q++;          /* use 0-sentinel at end */
                    175:       if (q >= fin) break;
                    176:       *curdiff++ = (q - plast) << 1;
                    177:     }
                    178:     plast -= asize - 1;
                    179:     remains -= asize - 1;
                    180:     curlow += ((asize - 1)<<1);
                    181:   } /* while (remains) */
                    182:   last = curlow - ((p - plast) << 1);
                    183:   *curdiff++ = 0;              /* sentinel */
                    184:   *lenp = curdiff - p1;
                    185:   *lastp = last;
                    186:   if (alloced) free(p);
                    187:   return (byteptr) gprealloc(p1, *lenp, size);
                    188: }
                    189: #if 0 /* not yet... GN */
                    190: /* The diffptr table will contain at least 6548 entries (up to and including
                    191:    the 6547th prime, 65557, and the terminal null byte), because the isprime/
                    192:    small-factor-extraction machinery wants to depend on everything up to 65539
                    193:    being in the table, and we might as well go to a multiple of 4 Bytes.--GN */
                    194:
                    195: void
                    196: init_tinyprimes_tridiv(byteptr p);     /* in ifactor2.c */
                    197: #endif
                    198: byteptr
                    199: initprimes(long maxnum)
                    200: {
                    201:   long len, last;
                    202:   byteptr p;
                    203:   /* The algorithm must see the next prime beyond maxnum, whence the +257. */
                    204:   /* switch to unsigned: adding the 257 _could_ wrap to a negative number. */
                    205:   ulong maxnum1 = ((maxnum<65302?65302:maxnum)+257ul);
                    206:
                    207:   if (maxnum1 > 436273000)
                    208:     err(talker,"impossible to have prestored primes > 436273009");
                    209:
                    210:   p = initprimes0(maxnum1, &len, &last);
                    211: #if 0 /* not yet... GN */
                    212:   static int build_the_tables = 1;
                    213:   if (build_the_tables) { init_tinyprimes_tridiv(p); build_the_tables=0; }
                    214: #endif
                    215:   return p;
                    216: }
                    217:
                    218: static void
                    219: cleanprimetab(void)
                    220: {
                    221:   long i,j, lp = lg(primetab);
                    222:
                    223:   for (i=j=1; i < lp; i++)
                    224:     if (primetab[i]) primetab[j++] = primetab[i];
                    225:   setlg(primetab,j);
                    226: }
                    227:
                    228: /* primes is a single element or a row vector with "primes" to add to
                    229:  * primetab. If the "prime" shares a non-trivial factor with another element
                    230:  * in primetab, it is taken into account.
                    231:  */
                    232: GEN
                    233: addprimes(GEN prime)
                    234: {
                    235:   long i,tx, av = avma, lp = lg(primetab);
                    236:   GEN p1,p2;
                    237:
                    238:   if (!prime) return primetab;
                    239:   tx = typ(prime);
                    240:   if (is_vec_t(tx))
                    241:   {
                    242:     for (i=1; i < lg(prime); i++) addprimes((GEN) prime[i]);
                    243:     return primetab;
                    244:   }
                    245:   if (tx != t_INT) err(typeer,"addprime");
                    246:   if (is_pm1(prime)) return primetab;
                    247:   if (signe(prime) < 0) prime=absi(prime);
                    248:
                    249:   p1=cgetg(1,t_VEC);
                    250:   for (i=1; i < lp; i++)
                    251:   {
                    252:     p2 = mppgcd((GEN) primetab[i], prime);
                    253:     if (! gcmp1(p2))
                    254:     {
                    255:       if (!egalii(prime,p2)) p1=concatsp(p1,p2);
                    256:       p1 = concatsp(p1,divii((GEN)primetab[i],p2));
                    257:       gunclone((GEN)primetab[i]); primetab[i]=0;
                    258:     }
                    259:   }
                    260:   if (i == NUMPRTBELT+1 && lg(p1) == 1)
                    261:     err(talker,"extra primetable overflows");
                    262:   primetab[i] = lclone(prime); setlg(primetab, lp+1);
                    263:   cleanprimetab();
                    264:   if (lg(p1) > 1) addprimes(p1);
                    265:   avma=av; return primetab;
                    266: }
                    267:
                    268: GEN
                    269: removeprimes(GEN prime)
                    270: {
                    271:   long i,tx, av = avma;
                    272:
                    273:   if (!prime) return primetab;
                    274:   tx = typ(prime);
                    275:   if (is_vec_t(tx))
                    276:   {
                    277:     for (i=1; i < lg(prime); i++) removeprimes((GEN) prime[i]);
                    278:     return primetab;
                    279:   }
                    280:   if (tx != t_INT) err(typeer,"removeprimes");
                    281:   if (is_pm1(prime)) return primetab;
                    282:   if (signe(prime) < 0) prime=absi(prime);
                    283:
                    284:   for (i=1; i < lg(primetab); i++)
                    285:     if (egalii((GEN) primetab[i], prime))
                    286:     {
                    287:       gunclone((GEN)primetab[i]); primetab[i]=0;
                    288:       cleanprimetab(); avma=av; return primetab;
                    289:     }
                    290:   err(talker,"prime is not in primetable in removeprimes");
                    291:   return NULL; /* not reached */
                    292: }
                    293:
                    294: /***********************************************************************/
                    295: /**                                                                   **/
                    296: /**       COMPUTING THE MATRIX OF PRIME DIVISORS AND EXPONENTS        **/
                    297: /**                                                                   **/
                    298: /***********************************************************************/
                    299:
                    300: /* Configure may/should define this to 1 if MPQS is not installed --GN */
                    301: #ifndef decomp_default_hint
                    302: #define decomp_default_hint 0
                    303: #endif
                    304:
                    305: /* Some overkill removed from this  (15 spsp for an integer < 2^32 ?!).
                    306:    Should really revert to isprime() once the new primality tester is ready
                    307:    --GN */
                    308: #define pseudoprime(p) millerrabin(p,3*lgefint(p))
                    309:
                    310: /* where to stop trial dividing in factorization */
                    311:
                    312: static long
                    313: tridiv_bound(GEN n, long all)
                    314: {
                    315:   long size = expi(n) + 1;
                    316:   if (all > 1)                 /* bounded factoring */
                    317:     return all;                        /* use the given limit */
                    318:   if (all == 0)
                    319:     return VERYBIGINT;         /* smallfact() case */
                    320:   if (size <= 32)
                    321:     return 16384;
                    322:   else if (size <= 512)
                    323:     return (size-16) << 10;
                    324:   return 1L<<19;               /* Rho will generally be faster above this */
                    325: }
                    326:
                    327: /********** about to become obsolete --GN **********/
                    328: #if 0
                    329: /* If flag != 1, use the new MPQS code: Try to factor N using ECM if flag = 2
                    330:  * and N is not too small, followed by MPQS, or just MPQS otherwise.
                    331:  */
                    332: static GEN
                    333: find_fact(GEN N, long *flag)
                    334: {
                    335:   GEN f;
                    336:
                    337:   if (*flag == 2)
                    338:   {
                    339:     if ((f = pollardbrent(N))) /* assignment */
                    340:       return f;
                    341:     f = ellfacteur(N, 0);
                    342:     if (!f)
                    343:     {
                    344:       /* *flag = 0; */
                    345:       f = mpqs(N);
                    346:     }
                    347:   }
                    348:   else if (*flag == 1)
                    349:   {
                    350:     if ((f = pollardbrent(N))) /* assignment */
                    351:       return f;
                    352:     f = ellfacteur(N, 1);
                    353:   }
                    354:   else
                    355:     f = mpqs(N);               /* may bail out and call ellfacteur(_,1) */
                    356:                                /* (this is to be changed) */
                    357:
                    358:   return f;
                    359: }
                    360: #endif
                    361: /***************************************************/
                    362:
                    363: /* function imported from ifactor1.c */
                    364: long
                    365: ifac_decomp(GEN n, long hint);
                    366:
                    367: static GEN
                    368: aux_end(GEN n, long nb)
                    369: {
                    370:   GEN p,p1,p2, z = (GEN)avma;
                    371:   long i;
                    372:
                    373:   if (n) gunclone(n);
                    374:   p1=cgetg(nb+1,t_COL);
                    375:   p2=cgetg(nb+1,t_COL);
                    376:   for (i=nb; i; i--)
                    377:   {
                    378:     p2[i] = (long)z; z += lg(z);
                    379:     p1[i] = (long)z; z += lg(z);
                    380:   }
                    381:   z[1]=(long)p1;
                    382:   z[2]=(long)p2;
                    383:   if (nb)
                    384:   {
                    385:     long av = avma;
                    386:     GEN p1old = dummycopy(p1), p2old = dummycopy(p2);
                    387:     p=sindexsort(p1);
                    388:     for (i=1;i<=nb; i++)
                    389:     {
                    390:       p1[i]=p1old[p[i]];
                    391:       p2[i]=p2old[p[i]];
                    392:     }
                    393:     avma = av;
                    394:   }
                    395:   return z;
                    396: }
                    397:
                    398: static GEN
                    399: auxdecomp0(GEN n, long all, long hint)
                    400: {
                    401:   long pp[] = { evaltyp(t_INT)|m_evallg(3), evalsigne(1)|evallgefint(3),2,0 };
                    402:   long nb = 0,i,k,lim1,av,lp;
                    403:   byteptr d=diffptr+1;
                    404:
                    405:   if (typ(n) != t_INT) err(arither1);
                    406:   i=signe(n); if (!i) err(arither2);
                    407:   cgetg(3,t_MAT);
                    408:   if (i<0) { stoi(-1); stoi(1); nb++; }
                    409:   if (is_pm1(n)) return aux_end(NULL,nb);
                    410:
                    411:   n = gclone(n);  setsigne(n,1);
                    412:   i = vali(n);
                    413:   if (i)
                    414:   {
                    415:     stoi(2); stoi(i); nb++;
                    416:     av=avma; affii(shifti(n,-i), n); avma=av;
                    417:   }
                    418:   if (is_pm1(n)) return aux_end(n,nb);
                    419:   lim1 = tridiv_bound(n, all);
                    420:
                    421:   /* trial division */
                    422:   while (*d && pp[2] <= lim1)
                    423:   {
                    424:     pp[2] += *d++;
                    425:     if (mpdivis(n,pp,n))
                    426:     {
                    427:       nb++; k=1; while (mpdivis(n,pp,n)) k++;
                    428:       icopy(pp); stoi(k);
                    429:       if (is_pm1(n)) return aux_end(n,nb);
                    430:     }
                    431:   }
                    432:
                    433:   /* pp = square of biggest p tried so far */
                    434:   av=avma; setlg(pp,4); affii(sqri(pp),pp); avma=av;
                    435:   if (cmpii(pp,n) > 0 || pseudoprime(n))
                    436:   {
                    437:     nb++;
                    438:     icopy(n); stoi(1); return aux_end(n,nb);
                    439:   }
                    440:
                    441:   lp = lg(primetab); k=0;
                    442:   for (i=1; i<lp; i++)
                    443:     if (mpdivis(n,(GEN) primetab[i],n))
                    444:     {
                    445:       nb++; k=1; while (mpdivis(n,(GEN) primetab[i],n)) k++;
                    446:       icopy((GEN) primetab[i]); stoi(k);
                    447:       if (is_pm1(n)) return aux_end(n,nb);
                    448:     }
                    449:
                    450:   /* test primality again, _if_ primetab made a difference  */
                    451:   if(k && (cmpii(pp,n) > 0 || pseudoprime(n)))
                    452:   {
                    453:     nb++;
                    454:     icopy(n); stoi(1); return aux_end(n,nb);
                    455:   }
                    456:
                    457:   /* now we have a large composite.  Use hint as is if all==1 */
                    458:   if (all!=1) hint = 15; /* turn off everything except pure powers */
                    459:   nb += ifac_decomp(n, hint);
                    460:
                    461:   return aux_end(n, nb);
                    462: }
                    463:
                    464: GEN
                    465: auxdecomp(GEN n, long all)
                    466: {
                    467:   return auxdecomp0(n,all,decomp_default_hint);
                    468: }
                    469:
                    470: /* see before ifac_crack() in ifactor1.c for current semantics of `hint'
                    471:    (factorint's `flag') */
                    472: GEN
                    473: factorint(GEN n, long flag)
                    474: {
                    475:   return auxdecomp0(n,1,flag);
                    476: }
                    477:
                    478: GEN
                    479: decomp(GEN n)
                    480: {
                    481:   return auxdecomp0(n,1,decomp_default_hint);
                    482: }
                    483:
                    484: GEN
                    485: smallfact(GEN n)
                    486: {
                    487:   return boundfact(n,0);
                    488: }
                    489:
                    490: GEN
                    491: gboundfact(GEN n, long lim)
                    492: {
                    493:   return garith_proto2gs(boundfact,n,lim);
                    494: }
                    495:
                    496: GEN
                    497: boundfact(GEN n, long lim)
                    498: {
                    499:   GEN p1,p2,p3,p4,p5,y;
                    500:   long av,tetpil;
                    501:
                    502:   if (lim<=1) lim=0;
                    503:   switch(typ(n))
                    504:   {
                    505:     case t_INT:
                    506:       return auxdecomp(n,lim);
                    507:     case t_FRACN:
                    508:       av=avma; n=gred(n); /* fall through */
                    509:     case t_FRAC:
                    510:       if (typ(n)==t_FRAC) av=avma;
                    511:       p1=auxdecomp((GEN)n[1],lim);
                    512:       p2=auxdecomp((GEN)n[2],lim);
                    513:       p4=concatsp((GEN)p1[1],(GEN)p2[1]);
                    514:       p5=concatsp((GEN)p1[2],gneg((GEN)p2[2]));
                    515:       p3=indexsort(p4);
                    516:
                    517:       tetpil=avma; y=cgetg(3,t_MAT);
                    518:       y[1]=(long)extract(p4,p3);
                    519:       y[2]=(long)extract(p5,p3);
                    520:       return gerepile(av,tetpil,y);
                    521:   }
                    522:   err(arither1);
                    523:   return NULL; /* not reached */
                    524: }
                    525:
                    526: /***********************************************************************/
                    527: /**                                                                   **/
                    528: /**                    BASIC ARITHMETIC FUNCTIONS                     **/
                    529: /**                                                                   **/
                    530: /***********************************************************************/
                    531:
                    532: /* functions imported from ifactor1.c */
                    533: long
                    534: ifac_moebius(GEN n, long hint);
                    535:
                    536: long
                    537: ifac_issquarefree(GEN n, long hint);
                    538:
                    539: long
                    540: ifac_omega(GEN n, long hint);
                    541:
                    542: long
                    543: ifac_bigomega(GEN n, long hint);
                    544:
                    545: GEN
                    546: ifac_totient(GEN n, long hint);
                    547:
                    548: GEN
                    549: ifac_numdiv(GEN n, long hint);
                    550:
                    551: GEN
                    552: ifac_sumdiv(GEN n, long hint);
                    553:
                    554: GEN
                    555: ifac_sumdivk(GEN n, long k, long hint);
                    556:
                    557: GEN
                    558: gmu(GEN n)
                    559: {
                    560:   return arith_proto(mu,n,1);
                    561: }
                    562:
                    563: long
                    564: mu(GEN n)
                    565: {
                    566:   byteptr d = diffptr+1;       /* point at 3 - 2 */
                    567:   GEN p;
                    568:   long av = avma, lim1, s, v;
                    569:
                    570:   if (typ(n) != t_INT) err(arither1);
                    571:   if (!signe(n)) err(arither2);
                    572:   if (is_pm1(n)) return 1;
                    573:   v = vali(n);
                    574:   if (v>1) return 0;
                    575:   s = v ? -1 : 1;
                    576:   n=absi(shifti(n,-v)); p=court_p; p[2]=2;
                    577:   if (is_pm1(n)) return s;
                    578:   lim1 = tridiv_bound(n,1);
                    579:
                    580:   while (*d && p[2] < lim1)
                    581:   {
                    582:     p[2] += *d++;
                    583:     if (mpdivis(n,p,n))
                    584:     {
                    585:       if (divise(n,p)) { avma=av; return 0; }
                    586:       s = -s; if (is_pm1(n)) { avma=av; return s; }
                    587:     }
                    588:   }
                    589:   /* we normally get here with p==nextprime(PRE_TUNE), which will already
                    590:      have been tested against n, so p^2 >= n  (instead of p^2 > n)  is
                    591:      enough to guarantee n is prime */
                    592:   if (cmpii(sqri(p),n) >= 0 || pseudoprime(n)) { avma=av; return -s; }
                    593:   /* large composite without small factors */
                    594:   v = ifac_moebius(n, decomp_default_hint);
                    595:   avma=av;
                    596:   return (s<0 ? -v : v);       /* correct also if v==0 */
                    597: }
                    598:
                    599: GEN
                    600: gissquarefree(GEN x)
                    601: {
                    602:   return arith_proto(issquarefree,x,0);
                    603: }
                    604:
                    605: long
                    606: issquarefree(GEN x)
                    607: {
                    608:   long av=avma,lim1,tx;
                    609:   GEN p;
                    610:
                    611:   if (gcmp0(x)) return 0;
                    612:   tx=typ(x);
                    613:   if (tx == t_INT)
                    614:   {
                    615:     long v;
                    616:     byteptr d=diffptr+1;
                    617:     if (is_pm1(x)) return 1;
                    618:     if((v = vali(x)) > 1) return 0;
                    619:     x=absi(shifti(x,-v)); p=court_p; p[2]=2;
                    620:     if (is_pm1(x)) return 1;
                    621:     lim1 = tridiv_bound(x,1);
                    622:
                    623:     while (*d && p[2] < lim1)
                    624:     {
                    625:       p[2] += *d++;
                    626:       if (mpdivis(x,p,x))
                    627:       {
                    628:        if (divise(x,p)) { avma=av; return 0; }
                    629:        if (is_pm1(x)) { avma=av; return 1; }
                    630:       }
                    631:     }
                    632:     if (cmpii(sqri(p),x) >= 0 || pseudoprime(x)) { avma=av; return 1; }
                    633:     v = ifac_issquarefree(x, decomp_default_hint);
                    634:     avma=av;
                    635:     return v;
                    636:   }
                    637:   if (tx != t_POL) err(typeer,"issquarefree");
                    638:   p = ggcd(x, derivpol(x));
                    639:   avma=av; return (lgef(p)==3);
                    640: }
                    641:
                    642: GEN
                    643: gomega(GEN n)
                    644: {
                    645:   return arith_proto(omega,n,1);
                    646: }
                    647:
                    648: long
                    649: omega(GEN n)
                    650: {
                    651:   byteptr d=diffptr+1;
                    652:   GEN p;
                    653:   long nb,av=avma,lim1,v;
                    654:
                    655:   if (typ(n) != t_INT) err(arither1);
                    656:   if (!signe(n)) err(arither2);
                    657:   if (is_pm1(n)) return 0;
                    658:   v=vali(n);
                    659:   nb = v ? 1 : 0;
                    660:   n=absi(shifti(n,-v)); p=court_p; p[2]=2;
                    661:   if (is_pm1(n)) return nb;
                    662:   lim1 = tridiv_bound(n,1);
                    663:
                    664:   while (*d && p[2] < lim1)
                    665:   {
                    666:     p[2] += *d++;
                    667:     if (mpdivis(n,p,n))
                    668:     {
                    669:       nb++; while (mpdivis(n,p,n)); /* empty */
                    670:       if (is_pm1(n)) { avma = av; return nb; }
                    671:     }
                    672:   }
                    673:   if (cmpii(sqri(p),n) >= 0 || pseudoprime(n)) { avma = av; return nb+1; }
                    674:   /* large composite without small factors */
                    675:   nb += ifac_omega(n, decomp_default_hint);
                    676:   avma=av; return nb;
                    677: }
                    678:
                    679: GEN
                    680: gbigomega(GEN n)
                    681: {
                    682:   return arith_proto(bigomega,n,1);
                    683: }
                    684:
                    685: long
                    686: bigomega(GEN n)
                    687: {
                    688:   byteptr d=diffptr+1;
                    689:   GEN p;
                    690:   long nb,av=avma,lim1,v;
                    691:
                    692:   if (typ(n) != t_INT) err(arither1);
                    693:   if (!signe(n)) err(arither2);
                    694:   if (is_pm1(n)) return 0;
                    695:   nb=v=vali(n);
                    696:   n=absi(shifti(n,-v)); p=court_p; p[2]=2;
                    697:   if (is_pm1(n)) { avma = av; return nb; }
                    698:   lim1 = tridiv_bound(n,1);
                    699:
                    700:   while (*d && p[2] < lim1)
                    701:   {
                    702:     p[2] += *d++;
                    703:     if (mpdivis(n,p,n))
                    704:     {
                    705:       do nb++; while (mpdivis(n,p,n));
                    706:       if (is_pm1(n)) { avma = av; return nb; }
                    707:     }
                    708:   }
                    709:   if (cmpii(sqri(p),n) >= 0 || pseudoprime(n)) { avma = av; return nb+1; }
                    710:   nb += ifac_bigomega(n, decomp_default_hint);
                    711:   avma=av; return nb;
                    712: }
                    713:
                    714: GEN
                    715: gphi(GEN n)
                    716: {
                    717:   return garith_proto(phi,n,1);
                    718: }
                    719:
                    720: GEN
                    721: phi(GEN n)
                    722: {
                    723:   byteptr d = diffptr+1;
                    724:   GEN p,m;
                    725:   long av = avma, lim1, v;
                    726:
                    727:   if (typ(n) != t_INT) err(arither1);
                    728:   if (!signe(n)) err(arither2);
                    729:   if (is_pm1(n)) return gun;
                    730:   v=vali(n);
                    731:   n=absi(shifti(n,-v)); p=court_p; p[2]=2;
                    732:   m = (v > 1 ? shifti(gun,v-1) : stoi(1));
                    733:   if (is_pm1(n)) { return gerepileupto(av,m); }
                    734:   lim1 = tridiv_bound(n,1);
                    735:
                    736:   while (*d && p[2] < lim1)
                    737:   {
                    738:     court_p[2] += *d++;
                    739:     if (mpdivis(n,p,n))
                    740:     {
                    741:       m = mulii(m,addsi(-1,p));
                    742:       while (mpdivis(n,p,n)) m = mulii(m,p);
                    743:       if (is_pm1(n)) { return gerepileupto(av,m); }
                    744:     }
                    745:   }
                    746:   if (cmpii(sqri(p),n) >= 0 || pseudoprime(n))
                    747:   {
                    748:     m = mulii(m,addsi(-1,n));
                    749:     return gerepileupto(av,m);
                    750:   }
                    751:   m = mulii(m, ifac_totient(n, decomp_default_hint));
                    752:   return gerepileupto(av,m);
                    753: }
                    754:
                    755: GEN
                    756: gnumbdiv(GEN n)
                    757: {
                    758:   return garith_proto(numbdiv,n,1);
                    759: }
                    760:
                    761: GEN
                    762: numbdiv(GEN n)
                    763: {
                    764:   byteptr d=diffptr+1;
                    765:   GEN p,m;
                    766:   long l, av=avma, lim1, v;
                    767:
                    768:   if (typ(n) != t_INT) err(arither1);
                    769:   if (!signe(n)) err(arither2);
                    770:   if (is_pm1(n)) return gun;
                    771:   v=vali(n);
                    772:   n=absi(shifti(n,-v)); p=court_p; p[2]=2;
                    773:   m = stoi(v+1);
                    774:   if (is_pm1(n)) { return gerepileupto(av,m); }
                    775:   lim1 = tridiv_bound(n,1);
                    776:
                    777:   while (*d && p[2] < lim1)
                    778:   {
                    779:     p[2] += *d++;
                    780:     l=1; while (mpdivis(n,p,n)) l++;
                    781:     m = mulsi(l,m); if (is_pm1(n)) { return gerepileupto(av,m); }
                    782:   }
                    783:   if(cmpii(sqri(p),n) >= 0 || pseudoprime(n))
                    784:   {
                    785:     m = shifti(m,1);
                    786:     return gerepileupto(av,m);
                    787:   }
                    788:   m = mulii(m, ifac_numdiv(n, decomp_default_hint));
                    789:   return gerepileupto(av,m);
                    790: }
                    791:
                    792: GEN
                    793: gsumdiv(GEN n)
                    794: {
                    795:   return garith_proto(sumdiv,n,1);
                    796: }
                    797:
                    798: GEN
                    799: sumdiv(GEN n)
                    800: {
                    801:   byteptr d=diffptr+1;
                    802:   GEN p,m,m1;
                    803:   long av=avma,lim1,v;
                    804:
                    805:   if (typ(n) != t_INT) err(arither1);
                    806:   if (!signe(n)) err(arither2);
                    807:   if (is_pm1(n)) return gun;
                    808:   v=vali(n);
                    809:   n=absi(shifti(n,-v)); p=court_p; p[2]=2;
                    810:   m = (v ? addsi(-1,shifti(gun,v+1)) : stoi(1));
                    811:   if (is_pm1(n)) { return gerepileupto(av,m); }
                    812:   lim1 = tridiv_bound(n,1);
                    813:
                    814:   while (*d && p[2] < lim1)
                    815:   {
                    816:     p[2] += *d++;
                    817:     if (mpdivis(n,p,n))
                    818:     {
                    819:       m1=addsi(1,p);
                    820:       while (mpdivis(n,p,n)) m1=addsi(1,mulii(p,m1));
                    821:       m = mulii(m1,m); if (is_pm1(n)) { return gerepileupto(av,m); }
                    822:     }
                    823:   }
                    824:   if(cmpii(sqri(p),n) >= 0 || pseudoprime(n))
                    825:   {
                    826:     m = mulii(m,addsi(1,n));
                    827:     return gerepileupto(av,m);
                    828:   }
                    829:   m = mulii(m, ifac_sumdiv(n, decomp_default_hint));
                    830:   return gerepileupto(av,m);
                    831: }
                    832:
                    833: GEN
                    834: gsumdivk(GEN n, long k)
                    835: {
                    836:   return garith_proto2gs(sumdivk,n,k);
                    837: }
                    838:
                    839: GEN
                    840: sumdivk(GEN n, long k)
                    841: {
                    842:   byteptr d=diffptr+1;
                    843:   GEN p,p1,m,m1,pk;
                    844:   long av=avma,tetpil,k1,lim1,v;
                    845:
                    846:   if (!k) return numbdiv(n);
                    847:   if (k==1) return sumdiv(n);
                    848:   if (typ(n) != t_INT) err(arither1);
                    849:   if (!signe(n)) err(arither2);
                    850:   if (is_pm1(n)) return gun;
                    851:   k1=k;
                    852:   if (k==-1) { p1=ginv(n); m=sumdiv(n); goto fin; }
                    853:   if (k<0) { k= -k; p1=gpuigs(n,k1); }
                    854:   v=vali(n);
                    855:   n=absi(shifti(n,-v));
                    856:   p = court_p; p[2]=2; m=stoi(1);
                    857:   while (v--) { m=addsi(1,shifti(m,k)); }
                    858:   if (is_pm1(n)) goto fin;
                    859:   lim1 = tridiv_bound(n,1);
                    860:
                    861:   while (*d && p[2] < lim1)
                    862:   {
                    863:     p[2] += *d++;
                    864:     if (mpdivis(n,p,n))
                    865:     {
                    866:       pk=gpuigs(p,k); m1=addsi(1,pk);
                    867:       while (mpdivis(n,p,n)) m1=addsi(1,mulii(pk,m1));
                    868:       m = mulii(m1,m); if (is_pm1(n)) goto fin;
                    869:     }
                    870:   }
                    871:   if(cmpii(sqri(p),n) >= 0 || pseudoprime(n))
                    872:   {
                    873:     pk=gpuigs(n,k);
                    874:     m = mulii(m,addsi(1,pk));
                    875:     goto fin;
                    876:   }
                    877:   m = mulii(m, ifac_sumdivk(n, k, decomp_default_hint));
                    878:  fin:
                    879:   if (k1>=0) return gerepileupto(av,m);
                    880:   tetpil=avma; return gerepile(av,tetpil,gmul(p1,m));
                    881: }
                    882:
                    883: /***********************************************************************/
                    884: /**                                                                   **/
                    885: /**                MISCELLANEOUS ARITHMETIC FUNCTIONS                 **/
                    886: /**         (all of these ultimately depend on auxdecomp())           **/
                    887: /**                                                                   **/
                    888: /***********************************************************************/
                    889:
                    890: GEN
                    891: divisors(GEN n)
                    892: {
                    893:   long tetpil,av=avma,i,j,l;
                    894:   GEN *d,*t,*t1,*t2,*t3, nbdiv,e;
                    895:
                    896:   if (typ(n) != t_MAT || lg(n) != 3) n = auxdecomp(n,1);
                    897:
                    898:   e = (GEN) n[2], n = (GEN) n[1]; l = lg(n);
                    899:   if (l>1 && signe(n[1]) < 0) { e++; n++; l--; } /* skip -1 */
                    900:   nbdiv = gun;
                    901:   for (i=1; i<l; i++)
                    902:   {
                    903:     e[i] = itos((GEN)e[i]);
                    904:     nbdiv = mulis(nbdiv,1+e[i]);
                    905:   }
                    906:   d = t = (GEN*) cgetg(itos(nbdiv)+1,t_VEC);
                    907:   *++d = gun;
                    908:   for (i=1; i<l; i++)
                    909:     for (t1=t,j=e[i]; j; j--,t1=t2)
                    910:       for (t2=d,t3=t1; t3<t2; )
                    911:        *++d = mulii(*++t3, (GEN)n[i]);
                    912:   tetpil=avma; return gerepile(av,tetpil,sort((GEN)t));
                    913: }
                    914:
                    915: GEN
                    916: core(GEN n)
                    917: {
                    918:   long av=avma,tetpil,i;
                    919:   GEN fa,p1,p2,res=gun;
                    920:
                    921:   fa=auxdecomp(n,1); p1=(GEN)fa[1]; p2=(GEN)fa[2];
                    922:   for (i=1; i<lg(p1); i++)
                    923:     if (mod2((GEN)p2[i])) res = mulii(res,(GEN)p1[i]);
                    924:   tetpil=avma; return gerepile(av,tetpil,icopy(res));
                    925: }
                    926:
                    927: GEN
                    928: core2(GEN n)
                    929: {
                    930:   long av=avma,tetpil,i;
                    931:
                    932:   GEN fa,p1,p2,p3,res=gun,res2=gun,y;
                    933:
                    934:   fa=auxdecomp(n,1); p1=(GEN)fa[1]; p2=(GEN)fa[2];
                    935:   for (i=1; i<lg(p1); i++)
                    936:   {
                    937:     p3=(GEN)p2[i];
                    938:     if (mod2(p3)) res=mulii(res,(GEN)p1[i]);
                    939:     if (!gcmp1(p3)) res2=mulii(res2,gpui((GEN)p1[i],shifti(p3,-1),0));
                    940:   }
                    941:   tetpil=avma; y=cgetg(3,t_VEC);
                    942:   y[1]=(long)icopy(res); y[2]=(long)icopy(res2);
                    943:   return gerepile(av,tetpil,y);
                    944: }
                    945:
                    946: GEN
                    947: core0(GEN n,long flag)
                    948: {
                    949:   return flag? core2(n): core(n);
                    950: }
                    951:
                    952: GEN
                    953: coredisc(GEN n)
                    954: {
                    955:   long av=avma,tetpil,r;
                    956:   GEN p1=core(n);
                    957:
                    958:   r=mod4(p1); if (signe(p1)<0) r = 4-r;
                    959:   if (r==1 || r==4) return p1;
                    960:   tetpil=avma; return gerepile(av,tetpil,shifti(p1,2));
                    961: }
                    962:
                    963: GEN
                    964: coredisc2(GEN n)
                    965: {
                    966:   long av=avma,tetpil,r;
                    967:   GEN y,p1,p2=core2(n);
                    968:
                    969:   p1=(GEN)p2[1]; r=mod4(p1); if (signe(p1)<0) r=4-r;
                    970:   if (r==1 || r==4) return p2;
                    971:   tetpil=avma; y=cgetg(3,t_VEC);
                    972:   y[1]=lshifti(p1,2); y[2]=lmul2n((GEN)p2[2],-1);
                    973:   return gerepile(av,tetpil,y);
                    974: }
                    975:
                    976: GEN
                    977: coredisc0(GEN n,long flag)
                    978: {
                    979:   return flag? coredisc2(n): coredisc(n);
                    980: }
                    981:
                    982: /***********************************************************************/
                    983: /**                                                                   **/
                    984: /**                      BINARY QUADRATIC FORMS                       **/
                    985: /**                                                                   **/
                    986: /***********************************************************************/
                    987:
                    988: GEN
                    989: qf_disc(GEN x, GEN y, GEN z)
                    990: {
                    991:   if (!y) { y=(GEN)x[2]; z=(GEN)x[3]; x=(GEN)x[1]; }
                    992:   return subii(sqri(y), shifti(mulii(x,z),2));
                    993: }
                    994:
                    995: static GEN
                    996: qf_create(GEN x, GEN y, GEN z, long s)
                    997: {
                    998:   GEN t;
                    999:   if (typ(x)!=t_INT || typ(y)!=t_INT || typ(z)!=t_INT) err(typeer,"Qfb");
                   1000:   if (!s)
                   1001:   {
                   1002:     long av=avma; s = signe(qf_disc(x,y,z)); avma=av;
                   1003:     if (!s) err(talker,"zero discriminant in Qfb");
                   1004:   }
                   1005:   t = (s>0)? cgetg(5,t_QFR): cgetg(4,t_QFI);
                   1006:   t[1]=(long)icopy(x); t[2]=(long)icopy(y); t[3]=(long)icopy(z);
                   1007:   return t;
                   1008: }
                   1009:
                   1010: GEN
                   1011: qfi(GEN x, GEN y, GEN z)
                   1012: {
                   1013:   return qf_create(x,y,z,-1);
                   1014: }
                   1015:
                   1016: GEN
                   1017: qfr(GEN x, GEN y, GEN z, GEN d)
                   1018: {
                   1019:   GEN t = qf_create(x,y,z,1);
                   1020:   if (typ(d) != t_REAL)
                   1021:     err(talker,"Shanks distance should be a t_REAL (in qfr)");
                   1022:   t[4]=lrcopy(d); return t;
                   1023: }
                   1024:
                   1025: GEN
                   1026: Qfb0(GEN x, GEN y, GEN z, GEN d, long prec)
                   1027: {
                   1028:   GEN t = qf_create(x,y,z,0);
                   1029:   if (lg(t)==4) return t;
                   1030:   if (!d) d = gzero;
                   1031:   if (typ(d) == t_REAL)
                   1032:     t[4] = lrcopy(d);
                   1033:   else
                   1034:     { t[4]=lgetr(prec); gaffect(d,(GEN)t[4]); }
                   1035:   return t;
                   1036: }
                   1037:
                   1038: /* composition */
                   1039:
                   1040: static void
                   1041: comp_gen(GEN z,GEN x,GEN y)
                   1042: {
                   1043:   GEN s,n,d,d1,x1,x2,y1,y2,v1,v2,v3,b3,c3,m,p1,r;
                   1044:
                   1045:   s=shifti(addii((GEN)x[2],(GEN)y[2]),-1);
                   1046:   n=subii((GEN)y[2],s);
                   1047:   d = bezout((GEN)y[1],(GEN)x[1],&y1,&x1);
                   1048:   d1 = bezout(s,d,&x2,&y2);
                   1049:   if (gcmp1(d1))
                   1050:   {
                   1051:     v3 = (GEN)x[1];
                   1052:     v2 = (GEN)y[1];
                   1053:   }
                   1054:   else
                   1055:   {
                   1056:     v1=divii((GEN)x[1],d1);
                   1057:     v2=divii((GEN)y[1],d1);
                   1058:     v3 = mulii(v1, mppgcd(d1,mppgcd((GEN)x[3],mppgcd((GEN)y[3],n))));
                   1059:   }
                   1060:   m = addii(mulii(mulii(y1,y2),n), mulii((GEN)y[3],x2));
                   1061:   setsigne(m,-signe(m));
                   1062:   r=modii(m,v3); p1=mulii(v2,r); b3=shifti(p1,1);
                   1063:   c3=addii(mulii((GEN)y[3],d1),mulii(r,addii((GEN)y[2],p1)));
                   1064:   z[1]=lmulii(v3,v2);
                   1065:   z[2]=laddii((GEN)y[2],b3);
                   1066:   z[3]=ldivii(c3,v3);
                   1067: }
                   1068:
                   1069: static GEN
                   1070: compimag0(GEN x, GEN y, int raw)
                   1071: {
                   1072:   long tx = typ(x), av = avma, tetpil;
                   1073:   GEN z;
                   1074:
                   1075:   if (typ(y) != tx || tx!=t_QFI) err(typeer,"composition");
                   1076:   if (cmpii((GEN)x[1],(GEN)y[1]) > 0) { z=x; x=y; y=z; }
                   1077:   z=cgetg(4,t_QFI); comp_gen(z,x,y); tetpil=avma;
                   1078:   return gerepile(av,tetpil,raw? gcopy(z): redimag(z));
                   1079: }
                   1080:
                   1081: static GEN
                   1082: compreal0(GEN x, GEN y, int raw)
                   1083: {
                   1084:   long tx = typ(x), av = avma, tetpil;
                   1085:   GEN z;
                   1086:
                   1087:   if (typ(y) != tx || tx!=t_QFR) err(typeer,"composition");
                   1088:   z=cgetg(5,t_QFR); comp_gen(z,x,y);
                   1089:   z[4]=laddrr((GEN)x[4],(GEN)y[4]); tetpil=avma;
                   1090:   return gerepile(av,tetpil, raw? gcopy(z): redreal(z));
                   1091: }
                   1092:
                   1093: GEN
                   1094: compreal(GEN x, GEN y) { return compreal0(x,y,0); }
                   1095:
                   1096: GEN
                   1097: comprealraw(GEN x, GEN y) { return compreal0(x,y,1); }
                   1098:
                   1099: GEN
                   1100: compimag(GEN x, GEN y) { return compimag0(x,y,0); }
                   1101:
                   1102: GEN
                   1103: compimagraw(GEN x, GEN y) { return compimag0(x,y,1); }
                   1104:
                   1105: GEN
                   1106: compraw(GEN x, GEN y)
                   1107: {
                   1108:   return (typ(x)==t_QFI)? compimagraw(x,y): comprealraw(x,y);
                   1109: }
                   1110:
                   1111: static void
                   1112: sq_gen(GEN z, GEN x)
                   1113: {
                   1114:   GEN d1,x2,y2,v1,v3,b3,c3,m,p1,r;
                   1115:
                   1116:   d1 = bezout((GEN)x[2],(GEN)x[1],&x2,&y2);
                   1117:   if (gcmp1(d1)) v1 = v3 = (GEN)x[1];
                   1118:   else
                   1119:   {
                   1120:     v1 = divii((GEN)x[1],d1);
                   1121:     v3 = mulii(v1,mppgcd(d1,(GEN)x[3]));
                   1122:   }
                   1123:   m=mulii((GEN)x[3],x2); setsigne(m,-signe(m));
                   1124:   r=modii(m,v3); p1=mulii(v1,r); b3=shifti(p1,1);
                   1125:   c3=addii(mulii((GEN)x[3],d1),mulii(r,addii((GEN)x[2],p1)));
                   1126:   z[1]=lmulii(v3,v1);
                   1127:   z[2]=laddii((GEN)x[2],b3);
                   1128:   z[3]=ldivii(c3,v3);
                   1129: }
                   1130:
                   1131: GEN
                   1132: sqcompimag0(GEN x, long raw)
                   1133: {
                   1134:   long av = avma, tetpil;
                   1135:   GEN z = cgetg(4,t_QFI);
                   1136:
                   1137:   if (typ(x)!=t_QFI) err(typeer,"composition");
                   1138:   sq_gen(z,x); tetpil=avma;
                   1139:   return gerepile(av,tetpil,raw? gcopy(z): redimag(z));
                   1140: }
                   1141:
                   1142: static GEN
                   1143: sqcompreal0(GEN x, long raw)
                   1144: {
                   1145:   long av = avma, tetpil;
                   1146:   GEN z = cgetg(5,t_QFR);
                   1147:
                   1148:   if (typ(x)!=t_QFR) err(typeer,"composition");
                   1149:   sq_gen(z,x); z[4]=lshiftr((GEN)x[4],1); tetpil=avma;
                   1150:   return gerepile(av,tetpil,raw? gcopy(z): redreal(z));
                   1151: }
                   1152:
                   1153: GEN
                   1154: sqcompreal(GEN x) { return sqcompreal0(x,0); }
                   1155:
                   1156: GEN
                   1157: sqcomprealraw(GEN x) { return sqcompreal0(x,1); }
                   1158:
                   1159: GEN
                   1160: sqcompimag(GEN x) { return sqcompimag0(x,0); }
                   1161:
                   1162: GEN
                   1163: sqcompimagraw(GEN x) { return sqcompimag0(x,1); }
                   1164:
                   1165: GEN
                   1166: real_unit_form(GEN x)
                   1167: {
                   1168:   long av = avma, tetpil,prec;
                   1169:   GEN p1,p2, y = cgetg(5,t_QFR);
                   1170:
                   1171:   y[1]=un; p1=qf_disc(x,NULL,NULL); p2=racine(p1);
                   1172:   /* we know that p1 and p2 are non-zero */
                   1173:   if (mod2(p1) != mod2(p2)) p2=addsi(-1,p2);
                   1174:   y[2]=(long)p2;
                   1175:   y[3]=lshifti(subii(sqri(p2),p1),-2);
                   1176:   prec = precision((GEN)x[4]);
                   1177:   if (!prec)
                   1178:     err(talker,"not a type real in 4th component of a t_QFR");
                   1179:   y[4]=(long)realzero(prec); tetpil=avma;
                   1180:   return gerepile(av,tetpil,gcopy(y));
                   1181: }
                   1182:
                   1183: GEN
                   1184: imag_unit_form(GEN x)
                   1185: {
                   1186:   long av,tetpil;
                   1187:   GEN p1,p2, y = cgetg(4,t_QFI);
                   1188:   y[1]=un;
                   1189:   y[2]=mpodd((GEN)x[2])? un: zero;
                   1190:   av=avma; p1=mulii((GEN)x[1],(GEN)x[3]);
                   1191:   p2=shifti(sqri((GEN)x[2]),-2); tetpil=avma;
                   1192:   y[3]=lpile(av,tetpil,subii(p1,p2));
                   1193:   return y;
                   1194: }
                   1195:
                   1196: GEN
                   1197: powrealraw(GEN x, long n)
                   1198: {
                   1199:   long av = avma, m;
                   1200:   GEN y;
                   1201:
                   1202:   if (typ(x) != t_QFR)
                   1203:     err(talker,"not a real quadratic form in powreal");
                   1204:   if (!n) return real_unit_form(x);
                   1205:   if (n== 1) return gcopy(x);
                   1206:   if (n==-1) return ginv(x);
                   1207:
                   1208:   y = NULL; m=labs(n);
                   1209:   for (; m>1; m>>=1)
                   1210:   {
                   1211:     if (m&1) y = y? comprealraw(y,x): x;
                   1212:     x=sqcomprealraw(x);
                   1213:   }
                   1214:   y = y? comprealraw(y,x): x;
                   1215:   if (n<0) y = ginv(y);
                   1216:   return gerepileupto(av,y);
                   1217: }
                   1218:
                   1219: GEN
                   1220: powimagraw(GEN x, long n)
                   1221: {
                   1222:   long av = avma, m;
                   1223:   GEN y;
                   1224:
                   1225:   if (typ(x) != t_QFI)
                   1226:     err(talker,"not an imaginary quadratic form in powimag");
                   1227:   if (!n) return imag_unit_form(x);
                   1228:   if (n== 1) return gcopy(x);
                   1229:   if (n==-1) return ginv(x);
                   1230:
                   1231:   y = NULL; m=labs(n);
                   1232:   for (; m>1; m>>=1)
                   1233:   {
                   1234:     if (m&1) y = y? compimagraw(y,x): x;
                   1235:     x=sqcompimagraw(x);
                   1236:   }
                   1237:   y = y? compimagraw(y,x): x;
                   1238:   if (n<0) y = ginv(y);
                   1239:   return gerepileupto(av,y);
                   1240: }
                   1241:
                   1242: GEN
                   1243: powraw(GEN x, long n)
                   1244: {
                   1245:   return (typ(x)==t_QFI)? powimagraw(x,n): powrealraw(x,n);
                   1246: }
                   1247:
                   1248: /* composition: Shanks' NUCOMP & NUDUPL */
                   1249: /* l = floor((|d|/4)^(1/4)) */
                   1250: GEN
                   1251: nucomp(GEN x, GEN y, GEN l)
                   1252: {
                   1253:   long av=avma,tetpil,cz;
                   1254:   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;
                   1255:
                   1256:   if (x==y) return nudupl(x,l);
                   1257:   if (typ(x) != t_QFI || typ(y) != t_QFI)
                   1258:     err(talker,"not an imaginary quadratic form in nucomp");
                   1259:
                   1260:   if (cmpii((GEN)x[1],(GEN)y[1]) < 0) { s=x; x=y; y=s; }
                   1261:   s=shifti(addii((GEN)x[2],(GEN)y[2]),-1); n=subii((GEN)y[2],s);
                   1262:   a1=(GEN)x[1]; a2=(GEN)y[1]; d=bezout(a2,a1,&u,&v);
                   1263:   if (gcmp1(d)) { a=negi(gmul(u,n)); d1=d; }
                   1264:   else
                   1265:     if (divise(s,d))
                   1266:     {
                   1267:       a=negi(gmul(u,n)); d1=d; a1=divii(a1,d1);
                   1268:       a2=divii(a2,d1); s=divii(s,d1);
                   1269:     }
                   1270:     else
                   1271:     {
                   1272:       d1=bezout(s,d,&u1,&v1);
                   1273:       if (!gcmp1(d1))
                   1274:       {
                   1275:        a1=divii(a1,d1); a2=divii(a2,d1);
                   1276:        s=divii(s,d1); d=divii(d,d1);
                   1277:       }
                   1278:       p1=resii((GEN)x[3],d); p2=resii((GEN)y[3],d);
                   1279:       p3=modii(negi(mulii(u1,addii(mulii(u,p1),mulii(v,p2)))),d);
                   1280:       a=subii(mulii(p3,divii(a1,d)),mulii(u,divii(n,d)));
                   1281:     }
                   1282:   a=modii(a,a1); p1=subii(a1,a); if (cmpii(a,p1)>0) a=negi(p1);
                   1283:   v=gzero; d=a1; v2=gun; v3=a;
                   1284:   for (cz=0; absi_cmp(v3,l) > 0; cz++)
                   1285:   {
                   1286:     p1=dvmdii(d,v3,&t3); t2=subii(v,mulii(p1,v2));
                   1287:     v=v2; d=v3; v2=t2; v3=t3;
                   1288:   }
                   1289:   z=cgetg(4,t_QFI);
                   1290:   if (!cz)
                   1291:   {
                   1292:     q1=mulii(a2,v3); q2=addii(q1,n);
                   1293:     g=divii(addii(mulii(v3,s),(GEN)y[3]),d);
                   1294:     z[1]=lmulii(d,a2);
                   1295:     z[2]=laddii(shifti(q1,1),(GEN)y[2]);
                   1296:     z[3]=laddii(mulii(v3,divii(q2,d)), mulii(g,d1));
                   1297:   }
                   1298:   else
                   1299:   {
                   1300:     if (cz&1) { v3=negi(v3); v2=negi(v2); }
                   1301:     b=divii(addii(mulii(a2,d),mulii(n,v)),a1);
                   1302:     q1=mulii(b,v3); q2=addii(q1,n);
                   1303:     e=divii(addii(mulii(s,d),mulii((GEN)y[3],v)),a1);
                   1304:     q3=mulii(e,v2); q4=subii(q3,s);
                   1305:     g=divii(q4,v); b2=addii(q3,q4);
                   1306:     if (!gcmp1(d1)) { v2=mulii(d1,v2); v=mulii(d1,v); b2=mulii(d1,b2); }
                   1307:     z[1]=laddii(mulii(d,b),mulii(e,v));
                   1308:     z[2]=laddii(b2,addii(q1,q2));
                   1309:     z[3]=laddii(mulii(v3,divii(q2,d)), mulii(g,v2));
                   1310:   }
                   1311:   tetpil=avma; return gerepile(av,tetpil,redimag(z));
                   1312: }
                   1313:
                   1314: GEN
                   1315: nudupl(GEN x, GEN l)
                   1316: {
                   1317:   long av=avma,tetpil,cz;
                   1318:   GEN u,v,d,d1,p1,a,b,c,b2,z,v2,v3,t2,t3,e,g;
                   1319:
                   1320:   if (typ(x) != t_QFI)
                   1321:     err(talker,"not an imaginary quadratic form in nudupl");
                   1322:   d1=bezout((GEN)x[2],(GEN)x[1],&u,&v);
                   1323:   a=divii((GEN)x[1],d1); b=divii((GEN)x[2],d1);
                   1324:   c=modii(negi(mulii(u,(GEN)x[3])),a); p1=subii(a,c);
                   1325:   if (cmpii(c,p1)>0) c=negi(p1);
                   1326:   v=gzero; d=a; v2=gun; v3=c;
                   1327:   for (cz=0; absi_cmp(v3,l) > 0; cz++)
                   1328:   {
                   1329:     p1=dvmdii(d,v3,&t3); t2=subii(v,mulii(p1,v2));
                   1330:     v=v2; d=v3; v2=t2; v3=t3;
                   1331:   }
                   1332:   z=cgetg(4,t_QFI);
                   1333:   if (!cz)
                   1334:   {
                   1335:     g=divii(addii(mulii(v3,b),(GEN)x[3]),d);
                   1336:     z[1]=(long)sqri(d);
                   1337:     z[2]=laddii((GEN)x[2],shifti(mulii(d,v3),1));
                   1338:     z[3]=laddii(sqri(v3),mulii(g,d1));
                   1339:   }
                   1340:   else
                   1341:   {
                   1342:     if (cz&1) { v=negi(v); d=negi(d); }
                   1343:     e=divii(addii(mulii((GEN)x[3],v),mulii(b,d)),a);
                   1344:     g=divii(subii(mulii(e,v2),b),v);
                   1345:     b2=addii(mulii(e,v2),mulii(v,g));
                   1346:     if (!gcmp1(d1)) { v2=mulii(d1,v2); v=mulii(d1,v); b2=mulii(d1,b2); }
                   1347:     z[1]=laddii(sqri(d),mulii(e,v));
                   1348:     z[2]=laddii(b2,shifti(mulii(d,v3),1));
                   1349:     z[3]=laddii(sqri(v3),mulii(g,v2));
                   1350:   }
                   1351:   tetpil=avma; return gerepile(av,tetpil,redimag(z));
                   1352: }
                   1353:
                   1354: GEN
                   1355: nupow(GEN x, GEN n)
                   1356: {
                   1357:   long av,tetpil,i,j;
                   1358:   unsigned long m;
                   1359:   GEN y,l;
                   1360:
                   1361:   if (typ(n) != t_INT) err(talker,"not an integer exponent in nupow");
                   1362:   if (gcmp1(n)) return gcopy(x);
                   1363:   av=avma; y = imag_unit_form(x);
                   1364:   if (!signe(n)) return y;
                   1365:
                   1366:   l = racine(shifti(racine((GEN)y[3]),1));
                   1367:   for (i=lgefint(n)-1; i>2; i--)
                   1368:     for (m=n[i],j=0; j<BITS_IN_LONG; j++,m>>=1)
                   1369:     {
                   1370:       if (m&1) y=nucomp(y,x,l);
                   1371:       x=nudupl(x,l);
                   1372:     }
                   1373:   for (m=n[2]; m>1; m>>=1)
                   1374:   {
                   1375:     if (m&1) y=nucomp(y,x,l);
                   1376:     x=nudupl(x,l);
                   1377:   }
                   1378:   tetpil=avma; y=nucomp(y,x,l);
                   1379:   if (signe(n)<0 && !egalii((GEN)y[1],(GEN)y[2])
                   1380:                  && !egalii((GEN)y[1],(GEN)y[3]))
                   1381:     setsigne(y[2],-signe(y[2]));
                   1382:   return gerepile(av,tetpil,y);
                   1383: }
                   1384:
                   1385: /* reduction */
                   1386:
                   1387: static GEN
                   1388: abs_dvmdii(GEN b, GEN p1, GEN *pt, long s)
                   1389: {
                   1390:   if (s<0) setsigne(b, 1); p1 = dvmdii(b,p1,pt);
                   1391:   if (s<0) setsigne(b,-1); return p1;
                   1392: }
                   1393:
                   1394: static GEN
                   1395: rhoimag0(GEN x, long *flag)
                   1396: {
                   1397:   GEN p1,b,d,z;
                   1398:   long fl, s = signe(x[2]);
                   1399:
                   1400:   fl = cmpii((GEN)x[1], (GEN)x[3]);
                   1401:   if (fl <= 0)
                   1402:   {
                   1403:     long fg = absi_cmp((GEN)x[1], (GEN)x[2]);
                   1404:     if (fg >= 0)
                   1405:     {
                   1406:       *flag = (s<0 && (!fl || !fg))? 2 /* set x[2] = negi(x[2]) in caller */
                   1407:                                    : 1;
                   1408:       return x;
                   1409:     }
                   1410:   }
                   1411:   p1=shifti((GEN)x[3],1); d = abs_dvmdii((GEN)x[2],p1,&b,s);
                   1412:   if (s>=0)
                   1413:   {
                   1414:     setsigne(d,-signe(d));
                   1415:     if (cmpii(b,(GEN)x[3])<=0) setsigne(b,-signe(b));
                   1416:     else { d=addsi(-1,d); b=subii(p1,b); }
                   1417:   }
                   1418:   else if (cmpii(b,(GEN)x[3])>=0) { d=addsi(1,d); b=subii(b,p1); }
                   1419:
                   1420:   z=cgetg(4,t_QFI);
                   1421:   z[1] = x[3];
                   1422:   z[3] = laddii((GEN)x[1], mulii(d,shifti(subii((GEN)x[2],b),-1)));
                   1423:   if (signe(b)<0 && !fl) setsigne(b,1);
                   1424:   z[2] = (long)b; *flag = 0; return z;
                   1425: }
                   1426:
                   1427: /* if sqrtD != NULL, compute Shanks' distance as well */
                   1428: static GEN
                   1429: rhoreal0(GEN x, GEN D, GEN isqrtD, GEN sqrtD)
                   1430: {
                   1431:   long s = signe(x[3]);
                   1432:   GEN p1,p2, z = cgetg(5,t_QFR);
                   1433:
                   1434:   if (!sqrtD)
                   1435:     z[4] = x[4];
                   1436:   else
                   1437:   {
                   1438:     p1 = divrr(addir((GEN)x[2],sqrtD), subir((GEN)x[2],sqrtD));
                   1439:     if (signe(p1)<0) setsigne(p1,1); /* p1 = |(b+sqrtD) / (b-sqrtD)| */
                   1440:     z[4] = laddrr(shiftr(mplog(p1),-1), (GEN) x[4]);
                   1441:   }
                   1442:   z[1] = x[3]; setsigne(z[1],1);
                   1443:   p1=shifti((GEN)z[1],1);
                   1444:   p2 = (cmpii(isqrtD,(GEN)z[1]) >= 0)? isqrtD: (GEN)z[1];
                   1445:   p2 = divii(addii(p2,(GEN)x[2]),p1);
                   1446:   z[2] = lsubii(mulii(p2,p1), (GEN)x[2]);
                   1447:
                   1448:   setsigne(z[1],s);
                   1449:   p1=shifti(subii(sqri((GEN)z[2]),D),-2);
                   1450:   z[3] = ldivii(p1,(GEN)z[1]); return z;
                   1451: }
                   1452:
                   1453: static GEN
                   1454: redreal0(GEN x, long flag, GEN D, GEN isqrtD, GEN sqrtD)
                   1455: {
                   1456:   long av=avma,l,step, use_d;
                   1457:
                   1458:   if (typ(x) != t_QFR) err(talker,"not a real quadratic form in redreal");
                   1459:   switch(flag)
                   1460:   {
                   1461:     case 0: use_d=1; step=0; break;
                   1462:     case 1: use_d=1; step=1; break;
                   1463:     case 2: use_d=0; step=0; break;
                   1464:     case 3: use_d=0; step=1; break;
                   1465:     default: err(flagerr,"qfbred");
                   1466:   }
                   1467:
                   1468:   if (!D) D = qf_disc(x,NULL,NULL);
                   1469:   else if (typ(D) != t_INT) err(arither1);
                   1470:
                   1471:   if (!isqrtD || (use_d && !sqrtD))
                   1472:   {
                   1473:     l=max(lg(x[4]),3);
                   1474:     l=max(l,((BITS_IN_LONG-1-expo(x[4]))>>TWOPOTBITS_IN_LONG)+2);
                   1475:     sqrtD=gsqrt(D,l); isqrtD=mptrunc(sqrtD);
                   1476:   }
                   1477:   else
                   1478:   {
                   1479:     if (typ(isqrtD) != t_INT) err(arither1);
                   1480:     if (sqrtD)
                   1481:     {
                   1482:       l=typ(sqrtD); if (!is_intreal_t(l)) err(arither1);
                   1483:     }
                   1484:   }
                   1485:   if (step)
                   1486:     x = rhoreal0(x,D,isqrtD,sqrtD);
                   1487:   else
                   1488:     for(;;)
                   1489:     {
                   1490:       if (signe(x[2]) > 0 && cmpii((GEN)x[2],isqrtD) <= 0 )
                   1491:       {
                   1492:         GEN p1=subii(isqrtD, shifti(absi((GEN)x[1]),1));
                   1493:
                   1494:         l = absi_cmp((GEN)x[2],p1);
                   1495:         if (l>0 || (l==0 && signe(p1)<0)) break;
                   1496:       }
                   1497:       x = rhoreal0(x,D,isqrtD,sqrtD);
                   1498:     }
                   1499:   l=avma; return gerepile(av,l,gcopy(x));
                   1500: }
                   1501:
                   1502: GEN
                   1503: redimag(GEN x)
                   1504: {
                   1505:   long av=avma, tetpil, fl;
                   1506:   do x = rhoimag0(x, &fl); while (fl == 0);
                   1507:   tetpil=avma; x = gerepile(av,tetpil,gcopy(x));
                   1508:   if (fl == 2) setsigne(x[2], -signe(x[2]));
                   1509:   return x;
                   1510: }
                   1511:
                   1512: GEN
                   1513: redreal(GEN x)
                   1514: {
                   1515:   return redreal0(x,0,NULL,NULL,NULL);
                   1516: }
                   1517:
                   1518: GEN
                   1519: rhoreal(GEN x)
                   1520: {
                   1521:   return redreal0(x,1,NULL,NULL,NULL);
                   1522: }
                   1523:
                   1524: GEN
                   1525: redrealnod(GEN x, GEN isqrtD)
                   1526: {
                   1527:   return redreal0(x,2,NULL,isqrtD,NULL);
                   1528: }
                   1529:
                   1530: GEN
                   1531: rhorealnod(GEN x, GEN isqrtD)
                   1532: {
                   1533:   return redreal0(x,3,NULL,isqrtD,NULL);
                   1534: }
                   1535:
                   1536: GEN
                   1537: qfbred0(GEN x, long flag, GEN D, GEN isqrtD, GEN sqrtD)
                   1538: {
                   1539:   long tx=typ(x),av,tetpil,fl;
                   1540:
                   1541:   if (!is_qf_t(tx)) err(talker,"not a quadratic form in qfbred");
                   1542:   if (!D) D = qf_disc(x,NULL,NULL);
                   1543:   switch(signe(D))
                   1544:   {
                   1545:     case 1 :
                   1546:       return redreal0(x,flag,D,isqrtD,sqrtD);
                   1547:
                   1548:     case -1:
                   1549:       if (!flag) return  redimag(x);
                   1550:       if (flag !=1) err(flagerr,"qfbred");
                   1551:       av=avma; x = rhoimag0(x,&fl); tetpil=avma;
                   1552:       x = gerepile(av,tetpil,gcopy(x));
                   1553:       if (fl == 2) setsigne(x[2], -signe(x[2]));
                   1554:       return x;
                   1555:   }
                   1556:   err(redpoler,"qfbred");
                   1557:   return NULL; /* not reached */
                   1558: }
                   1559:
                   1560: GEN
                   1561: primeform(GEN x, GEN p, long prec)
                   1562: {
                   1563:   long av,tetpil,s=signe(x);
                   1564:   GEN y,b;
                   1565:
                   1566:   if (typ(x) != t_INT || !s) err(arither1);
                   1567:   if (typ(p) != t_INT || signe(p) <= 0) err(arither1);
                   1568:   if (s < 0)
                   1569:   {
                   1570:     y = cgetg(4,t_QFI); s = 8-mod8(x);
                   1571:   }
                   1572:   else
                   1573:   {
                   1574:     y = cgetg(5,t_QFR); s = mod8(x);
                   1575:     y[4]=(long)realzero(prec);
                   1576:   }
                   1577:   switch(s&3)
                   1578:   {
                   1579:     case 2: case 3: err(funder2,"primeform");
                   1580:   }
                   1581:   y[1] = (long)icopy(p); av=avma;
                   1582:   if (egalii(p,gdeux))
                   1583:   {
                   1584:     switch(s)
                   1585:     {
                   1586:       case 0: y[2]=zero; break;
                   1587:       case 8: s=0; y[2]=zero; break;
                   1588:       case 1: s=1; y[2]=un; break;
                   1589:       case 4: s=4; y[2]=deux; break;
                   1590:       default: err(sqrter5);
                   1591:     }
                   1592:     b=subsi(s,x); tetpil=avma; b=shifti(b,-3);
                   1593:   }
                   1594:   else
                   1595:   {
                   1596:     b = mpsqrtmod(x,p); if (!b) err(sqrter5);
                   1597:     if (mod2(b) == mod2(x)) y[2] = (long)b;
                   1598:     else
                   1599:     { tetpil = avma; y[2] = lpile(av,tetpil,subii(p,b)); }
                   1600:
                   1601:     av=avma; b=shifti(subii(sqri((GEN)y[2]),x),-2);
                   1602:     tetpil=avma; b=divii(b,p);
                   1603:   }
                   1604:   y[3]=lpile(av,tetpil,b); return y;
                   1605: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>