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