Annotation of OpenXM_contrib/pari/src/basemath/trans1.c, Revision 1.1
1.1 ! maekawa 1: /********************************************************************/
! 2: /** **/
! 3: /** TRANSCENDENTAL FONCTIONS **/
! 4: /** **/
! 5: /********************************************************************/
! 6: /* $Id: trans1.c,v 1.2 1999/09/23 17:50:57 karim Exp $ */
! 7: #include "pari.h"
! 8:
! 9: #ifdef LONG_IS_64BIT
! 10: # define C31 (9223372036854775808.0) /* VERYBIGINT * 1.0 */
! 11: # define SQRTVERYBIGINT 3037000500 /* ceil(sqrt(VERYBIGINT)) */
! 12: # define CBRTVERYBIGINT 2097152 /* ceil(cbrt(VERYBIGINT)) */
! 13: #else
! 14: # define C31 (2147483648.0)
! 15: # define SQRTVERYBIGINT 46341
! 16: # define CBRTVERYBIGINT 1291
! 17: #endif
! 18:
! 19:
! 20: /********************************************************************/
! 21: /** **/
! 22: /** FONCTION PI **/
! 23: /** **/
! 24: /********************************************************************/
! 25:
! 26: void
! 27: constpi(long prec)
! 28: {
! 29: GEN p1,p2,p3,tmppi;
! 30: long l,n,n1,av1,av2;
! 31: double alpha;
! 32:
! 33: #define k1 545140134
! 34: #define k2 13591409
! 35: #define k3 640320
! 36: #define alpha2 (1.4722004/(BYTES_IN_LONG/4)) /* 3*log(k3/12)/(32*log(2)) */
! 37:
! 38: if (gpi && lg(gpi) >= prec) return;
! 39:
! 40: av1 = avma; tmppi = newbloc(prec);
! 41: *tmppi = evaltyp(t_REAL) | evallg(prec);
! 42:
! 43: n=(long)(1+(prec-2)/alpha2);
! 44: n1=6*n-1; p1=cgetr(prec);
! 45: p2=addsi(k2,mulss(n,k1));
! 46: affir(p2,p1);
! 47:
! 48: /* initialisation longueur mantisse */
! 49: if (prec>=4) l=4; else l=prec;
! 50: setlg(p1,l); alpha=l;
! 51:
! 52: av2 = avma;
! 53: while (n)
! 54: {
! 55: if (n < CBRTVERYBIGINT)
! 56: p3 = divrs(mulsr(n1-4,mulsr(n1*(n1-2),p1)),n*n*n);
! 57: else
! 58: {
! 59: if (n1 < SQRTVERYBIGINT)
! 60: p3 = divrs(divrs(mulsr(n1-4,mulsr(n1*(n1-2),p1)),n*n),n);
! 61: else
! 62: p3 = divrs(divrs(mulsr(n1-4,mulsr(n1,mulsr(n1-2,p1))),n*n),n);
! 63: }
! 64: p3 = divrs(divrs(p3,100100025), 327843840);
! 65: subisz(p2,k1,p2); subirz(p2,p3,p1);
! 66: alpha += alpha2; l = (long)(1+alpha); /* nouvelle longueur mantisse */
! 67: if (l>prec) l=prec;
! 68: setlg(p1,l); avma = av2;
! 69: n--; n1-=6;
! 70: }
! 71: p1 = divsr(53360,p1);
! 72: mulrrz(p1,gsqrt(stoi(k3),prec), tmppi);
! 73: gunclone(gpi); avma = av1; gpi = tmppi;
! 74: }
! 75:
! 76: GEN
! 77: mppi(long prec)
! 78: {
! 79: GEN x = cgetr(prec);
! 80: constpi(prec+1); affrr(gpi,x); return x;
! 81: }
! 82:
! 83: /********************************************************************/
! 84: /** **/
! 85: /** FONCTION EULER **/
! 86: /** **/
! 87: /********************************************************************/
! 88:
! 89: void
! 90: consteuler(long prec)
! 91: {
! 92: GEN u,v,a,b,tmpeuler;
! 93: long l,n,k,x,av1,av2;
! 94:
! 95: if (geuler && lg(geuler) >= prec) return;
! 96:
! 97: av1 = avma; tmpeuler = newbloc(prec);
! 98: *tmpeuler = evaltyp(t_REAL) | evallg(prec);
! 99:
! 100: l = prec+1; x = (long) (1 + (bit_accuracy(l) >> 2) * LOG2);
! 101: a=cgetr(l); affsr(x,a); u=mplog(a); setsigne(u,-1); affrr(u,a);
! 102: b=realun(l);
! 103: v=realun(l);
! 104: n=(long)(1+3.591*x); /* z=3.591: z*[ ln(z)-1 ]=1 */
! 105: av2 = avma;
! 106: if (x < SQRTVERYBIGINT)
! 107: {
! 108: long xx = x*x;
! 109: for (k=1; k<=n; k++)
! 110: {
! 111: divrsz(mulsr(xx,b),k*k, b);
! 112: divrsz(addrr(divrs(mulsr(xx,a),k),b),k, a);
! 113: addrrz(u,a,u); addrrz(v,b,v); avma = av2;
! 114: }
! 115: }
! 116: else
! 117: {
! 118: GEN xx = mulss(x,x);
! 119: for (k=1; k<=n; k++)
! 120: {
! 121: divrsz(mulir(xx,b),k*k, b);
! 122: divrsz(addrr(divrs(mulir(xx,a),k),b),k, a);
! 123: addrrz(u,a,u); addrrz(v,b,v); avma = av2;
! 124: }
! 125: }
! 126: divrrz(u,v,tmpeuler);
! 127: gunclone(geuler); avma = av1; geuler = tmpeuler;
! 128: }
! 129:
! 130: GEN
! 131: mpeuler(long prec)
! 132: {
! 133: GEN x=cgetr(prec);
! 134: consteuler(prec+1); affrr(geuler,x); return x;
! 135: }
! 136:
! 137: /********************************************************************/
! 138: /** **/
! 139: /** CONVERSION DE TYPES POUR FONCTIONS TRANSCENDANTES **/
! 140: /** **/
! 141: /********************************************************************/
! 142:
! 143: GEN
! 144: transc(GEN (*f)(GEN,long), GEN x, long prec)
! 145: {
! 146: GEN p1,p2,y;
! 147: long lx,i,av,tetpil;
! 148:
! 149: av=avma;
! 150: switch(typ(x))
! 151: {
! 152: case t_INT: case t_FRAC: case t_FRACN:
! 153: p1=cgetr(prec); gaffect(x,p1); tetpil=avma;
! 154: return gerepile(av,tetpil,f(p1,prec));
! 155:
! 156: case t_COMPLEX: case t_QUAD:
! 157: av=avma; p1=gmul(x,realun(prec)); tetpil=avma;
! 158: return gerepile(av,tetpil,f(p1,prec));
! 159:
! 160: case t_POL: case t_RFRAC: case t_RFRACN:
! 161: p1=tayl(x,gvar(x),precdl); tetpil=avma;
! 162: return gerepile(av,tetpil,f(p1,prec));
! 163:
! 164: case t_VEC: case t_COL: case t_MAT:
! 165: lx=lg(x); y=cgetg(lx,typ(x));
! 166: for (i=1; i<lx; i++)
! 167: y[i] = (long) f((GEN)x[i],prec);
! 168: return y;
! 169:
! 170: case t_POLMOD:
! 171: av=avma; p1=roots((GEN)x[1],prec); lx=lg(p1); p2=cgetg(lx,t_COL);
! 172: for (i=1; i<lx; i++) p2[i]=lpoleval((GEN)x[2],(GEN)p1[i]);
! 173: tetpil=avma; y=cgetg(lx,t_COL);
! 174: for (i=1; i<lx; i++)
! 175: y[i] = (long)f((GEN)p2[i],prec);
! 176: return gerepile(av,tetpil,y);
! 177:
! 178: case t_QFR: case t_QFI:
! 179: err(talker,"quadratic forms cannot be used in transcendental functions");
! 180: }
! 181: return f(x,prec);
! 182: }
! 183:
! 184: /*******************************************************************/
! 185: /* */
! 186: /* POWERING */
! 187: /* */
! 188: /*******************************************************************/
! 189: GEN real_unit_form(GEN x);
! 190: GEN imag_unit_form(GEN x);
! 191:
! 192: static GEN
! 193: puiss0(GEN x)
! 194: {
! 195: long lx,i;
! 196: GEN y;
! 197:
! 198: switch(typ(x))
! 199: {
! 200: case t_INT: case t_REAL: case t_FRAC: case t_FRACN: case t_PADIC:
! 201: return gun;
! 202:
! 203: case t_INTMOD:
! 204: y=cgetg(3,t_INTMOD); copyifstack(x[1],y[1]); y[2]=un; break;
! 205:
! 206: case t_COMPLEX:
! 207: y=cgetg(3,t_COMPLEX); y[1]=un; y[2]=zero; break;
! 208:
! 209: case t_QUAD:
! 210: y=cgetg(4,t_QUAD); copyifstack(x[1],y[1]);
! 211: y[2]=un; y[3]=zero; break;
! 212:
! 213: case t_POLMOD:
! 214: y=cgetg(3,t_POLMOD); copyifstack(x[1],y[1]);
! 215: y[2]=lpolun[varn(x[1])]; break;
! 216:
! 217: case t_POL: case t_SER: case t_RFRAC: case t_RFRACN:
! 218: return polun[gvar(x)];
! 219:
! 220: case t_MAT:
! 221: lx=lg(x); if (lx==1) return cgetg(1,t_MAT);
! 222: if (lx != (lg(x[1]))) err(mattype1,"gpowgs");
! 223: y = idmat(lx-1);
! 224: for (i=1; i<lx; i++) coeff(y,i,i) = lpuigs(gcoeff(x,i,i),0);
! 225: break;
! 226: case t_QFR: return real_unit_form(x);
! 227: case t_QFI: return imag_unit_form(x);
! 228: case t_VEC: case t_COL:
! 229: err(typeer,"gpowgs");
! 230: }
! 231: return y;
! 232: }
! 233:
! 234: /* INTEGER POWERING (a^n for integer a and integer n > 1)
! 235: *
! 236: * Nonpositive powers and exponent one should be handled by gpow() and
! 237: * gpowgs() in trans1.c, which at the time of this writing is the only place
! 238: * where the following is [slated to be] used.
! 239: *
! 240: * Use left shift binary algorithm (RS is wasteful: multiplies big numbers,
! 241: * with LS one of them is the base, hence small). If result is nonzero, its
! 242: * sign is set to s (= +-1) regardless of what it would have been. This makes
! 243: * life easier for gpow()/gpowgs(), which otherwise might do a
! 244: * setsigne(gun,-1)... -- GN1998May04
! 245: */
! 246: static GEN
! 247: puissii(GEN a, GEN n, long s)
! 248: {
! 249: long av,*p,man,k,nb,lim;
! 250: GEN y;
! 251:
! 252: if (!signe(a)) return gzero; /* a==0 */
! 253: if (lgefint(a)==3)
! 254: { /* easy if |a| < 3 */
! 255: if (a[2] == 1) return (s>0)? gun: negi(gun);
! 256: if (a[2] == 2) { a = shifti(gun, itos(n)); setsigne(a,s); return a; }
! 257: }
! 258: if (lgefint(n)==3)
! 259: { /* or if |n| < 3 */
! 260: if (n[2] == 1) { a = icopy(a); setsigne(a,s); return a; }
! 261: if (n[2] == 2) return sqri(a);
! 262: }
! 263: /* be paranoid about memory consumption */
! 264: av=avma; lim=stack_lim(av,1);
! 265: y = a; p = n+2; man = *p;
! 266: /* normalize, i.e set highest bit to 1 (we know man != 0) */
! 267: k = 1+bfffo(man); man<<=k; k = BITS_IN_LONG-k;
! 268: /* first bit is now implicit */
! 269: for (nb=lgefint(n)-2;;)
! 270: {
! 271: for (; k; man<<=1,k--)
! 272: {
! 273: y = sqri(y);
! 274: if (low_stack(lim, stack_lim(av,1)))
! 275: {
! 276: if (DEBUGMEM>1) err(warnmem,"[1]: puissii");
! 277: y = gerepileupto(av,y);
! 278: }
! 279: if (man < 0)
! 280: { /* first bit is set: multiply by the base */
! 281: y = mulii(y,a);
! 282: if (low_stack(lim, stack_lim(av,1)))
! 283: {
! 284: if (DEBUGMEM>1) err(warnmem,"[2]: puissii");
! 285: y = gerepileupto(av,y);
! 286: }
! 287: }
! 288: }
! 289: nb--; if (nb == 0) break;
! 290: man = *++p, k = BITS_IN_LONG;
! 291: }
! 292: setsigne(y,s); return gerepileupto(av,y);
! 293: }
! 294:
! 295: GEN
! 296: gpowgs(GEN x, long n)
! 297: {
! 298: long lim,av,m,tx;
! 299: static long gn[3] = {evaltyp(t_INT)|m_evallg(3), 0, 0};
! 300: GEN y;
! 301:
! 302: if (n == 0) return puiss0(x);
! 303: if (n == 1) return gcopy(x);
! 304: if (n ==-1) return ginv(x);
! 305: if (n>0)
! 306: { gn[1] = evalsigne( 1) | evallgefint(3); gn[2]= n; }
! 307: else
! 308: { gn[1] = evalsigne(-1) | evallgefint(3); gn[2]=-n; }
! 309: /* If gpowgs were only ever called from gpow, the switch wouldn't be needed.
! 310: * In fact, under current word and bit field sizes, an integer power with
! 311: * multiword exponent will always overflow. But it seems easier to call
! 312: * puissii|powmodulo() with a mock-up GEN as 2nd argument than to write
! 313: * separate versions for a long exponent. Note that n = HIGHBIT is an
! 314: * invalid argument. --GN
! 315: */
! 316: switch((tx=typ(x)))
! 317: {
! 318: case t_INT:
! 319: {
! 320: long sx=signe(x), sr = (sx<0 && (n&1))? -1: 1;
! 321: if (n>0) return puissii(x,(GEN)gn,sr);
! 322: if (!sx) err(talker, "division by zero in gpowgs");
! 323: if (is_pm1(x)) return (sr < 0)? icopy(x): gun;
! 324: /* n<0, |x|>1 */
! 325: y=cgetg(3,t_FRAC); setsigne(gn,1);
! 326: y[1]=(sr>0)? un: lnegi(gun);
! 327: y[2]=(long)puissii(x,(GEN)gn,1); /* force denominator > 0 */
! 328: return y;
! 329: }
! 330: case t_INTMOD:
! 331: y=cgetg(3,tx); copyifstack(x[1],y[1]);
! 332: y[2]=(long)powmodulo((GEN)(x[2]),(GEN)gn,(GEN)(x[1]));
! 333: return y;
! 334: case t_FRAC: case t_FRACN:
! 335: {
! 336: long sr = ((n&1) && (signe(x[1])!=signe(x[2])))? -1: 1;
! 337: if (n<0)
! 338: {
! 339: if (!signe((GEN)x[1]))
! 340: err(talker, "division by zero fraction in gpowgs");
! 341: setsigne((GEN)gn,1);
! 342: if (is_pm1((GEN)x[1])) /* +-1/x[2] inverts to an integer */
! 343: return puissii((GEN)x[2],(GEN)gn,sr);
! 344: y=cgetg(3,tx);
! 345: y[1]=(long)puissii((GEN)x[2],(GEN)gn,sr);
! 346: y[2]=(long)puissii((GEN)x[1],(GEN)gn,1);
! 347: return y;
! 348: }
! 349: else /* n > 0 */
! 350: {
! 351: y=cgetg(3,tx);
! 352: if (!signe((GEN)x[1])) { y[1]=zero; y[2]=un; return y; }
! 353: y[1]=(long)puissii((GEN)x[1],(GEN)gn,sr);
! 354: y[2]=(long)puissii((GEN)x[2],(GEN)gn,1);
! 355: return y;
! 356: }
! 357: }
! 358: case t_POL: case t_POLMOD:
! 359: return powgi(x,gn);
! 360: case t_RFRAC: case t_RFRACN:
! 361: {
! 362: av=avma; y=cgetg(3,tx); m = labs(n);
! 363: y[1]=lpuigs((GEN)x[1],m);
! 364: y[2]=lpuigs((GEN)x[2],m);
! 365: if (n<0) y=ginv(y); /* let ginv worry about normalizations */
! 366: return gerepileupto(av,y);
! 367: }
! 368: default:
! 369: m = labs(n);
! 370: av=avma; y=NULL; lim=stack_lim(av,1);
! 371: for (; m>1; m>>=1)
! 372: {
! 373: if (m&1) y = y? gmul(y,x): x;
! 374: x=gsqr(x);
! 375: if (low_stack(lim, stack_lim(av,1)))
! 376: {
! 377: GEN *gptr[2]; gptr[0]=&x; gptr[1]=&y;
! 378: if(DEBUGMEM>1) err(warnmem,"[3]: gpowgs");
! 379: gerepilemany(av,gptr,y? 2: 1);
! 380: }
! 381: }
! 382: y = y? gmul(y,x): x;
! 383: if (n<=0) y=ginv(y);
! 384: return gerepileupto(av,y);
! 385: }
! 386: }
! 387:
! 388: GEN
! 389: pow_monome(GEN x, GEN nn)
! 390: {
! 391: long n,m,i,j,dd,tetpil, av = avma;
! 392: GEN p1,y;
! 393: if (is_bigint(nn)) err(talker,"power overflow in pow_monome");
! 394: n = itos(nn); m = labs(n);
! 395: j=lgef(x); dd=(j-3)*m+3;
! 396: p1=cgetg(dd,t_POL); m = labs(n);
! 397: p1[1] = evalsigne(1) | evallgef(dd) | evalvarn(varn(x));
! 398: for (i=2; i<dd-1; i++) p1[i]=zero;
! 399: p1[i]=lpuigs((GEN)x[j-1],m);
! 400: if (n>0) return p1;
! 401:
! 402: tetpil=avma; y=cgetg(3,t_RFRAC);
! 403: y[1]=(long)denom((GEN)p1[i]);
! 404: y[2]=lmul(p1,(GEN)y[1]); return gerepile(av,tetpil,y);
! 405: }
! 406:
! 407: /* n is assumed to be an integer */
! 408: GEN
! 409: powgi(GEN x, GEN n)
! 410: {
! 411: long lim,av,i,j,m,tx, sn=signe(n);
! 412: GEN y, p1;
! 413:
! 414: if (typ(n) != t_INT) err(talker,"not an integral exponent in powgi");
! 415: if (!sn) return puiss0(x);
! 416:
! 417: switch(tx=typ(x))
! 418: {/* catch some types here, instead of trying gpowgs() first, because of
! 419: * the simpler call interface to puissii() and powmodulo() -- even though
! 420: * for integer/rational bases other than 0,+-1 and non-wordsized
! 421: * exponents the result will be certain to overflow. --GN
! 422: */
! 423: case t_INT:
! 424: {
! 425: long sx=signe(x), sr = (sx<0 && mod2(n))? -1: 1;
! 426: if (sn>0) return puissii(x,n,sr);
! 427: if (!sx) err(talker, "division by zero in powgi");
! 428: if (is_pm1(x)) return (sr < 0)? icopy(x): gun;
! 429: /* n<0, |x|>1 */
! 430: y=cgetg(3,t_FRAC); setsigne(n,1); /* temporarily replace n by abs(n) */
! 431: y[1]=(sr>0)? un: lnegi(gun);
! 432: y[2]=(long)puissii(x,n,1);
! 433: setsigne(n,-1); return y;
! 434: }
! 435: case t_INTMOD:
! 436: y=cgetg(3,tx); copyifstack(x[1],y[1]);
! 437: y[2]=(long)powmodulo((GEN)x[2],n,(GEN)x[1]);
! 438: return y;
! 439: case t_FRAC: case t_FRACN:
! 440: {
! 441: long sr = (mod2(n) && (signe(x[1])!=signe(x[2]))) ? -1 : 1;
! 442: if (sn<0)
! 443: {
! 444: if (!signe((GEN)x[1]))
! 445: err(talker, "division by zero fraction in powgi");
! 446: setsigne(n,1);
! 447: if (is_pm1((GEN)x[1])) /* +-1/x[2] inverts to an integer */
! 448: y=puissii((GEN)x[2],n,sr);
! 449: else
! 450: {
! 451: y=cgetg(3,tx);
! 452: y[1]=(long)puissii((GEN)x[2],n,sr);
! 453: y[2]=(long)puissii((GEN)x[1],n,1);
! 454: }
! 455: setsigne(n,-1); return y;
! 456: }
! 457: else /* n > 0 */
! 458: {
! 459: y=cgetg(3,tx);
! 460: if (!signe((GEN)x[1])) { y[1]=zero; y[2]=un; return y; }
! 461: y[1]=(long)puissii((GEN)x[1],n,sr);
! 462: y[2]=(long)puissii((GEN)x[2],n,1);
! 463: return y;
! 464: }
! 465: }
! 466: case t_POL:
! 467: if (ismonome(x)) return pow_monome(x,n);
! 468: default:
! 469: av=avma; lim=stack_lim(av,1);
! 470: p1 = n+2; m = *p1;
! 471: y=x; j=1+bfffo(m); m<<=j; j = BITS_IN_LONG-j;
! 472: for (i=lgefint(n)-2;;)
! 473: {
! 474: for (; j; m<<=1,j--)
! 475: {
! 476: y=gsqr(y);
! 477: if (low_stack(lim, stack_lim(av,1)))
! 478: {
! 479: if(DEBUGMEM>1) err(warnmem,"[1]: powgi");
! 480: y = gerepileupto(av, y);
! 481: }
! 482: if (m<0) y=gmul(y,x);
! 483: if (low_stack(lim, stack_lim(av,1)))
! 484: {
! 485: if(DEBUGMEM>1) err(warnmem,"[2]: powgi");
! 486: y = gerepileupto(av, y);
! 487: }
! 488: }
! 489: if (--i == 0) break;
! 490: m = *++p1, j = BITS_IN_LONG;
! 491: }
! 492: if (sn<0) y = ginv(y);
! 493: return av==avma? gcopy(y): gerepileupto(av,y);
! 494: }
! 495: }
! 496:
! 497: /* we suppose n != 0, and valp(x) = 0 */
! 498: static GEN
! 499: ser_pui(GEN x, GEN n, long prec)
! 500: {
! 501: long av,tetpil,lx,i,j;
! 502: GEN p1,p2,y,alp;
! 503:
! 504: if (gvar9(n) > varn(x))
! 505: {
! 506: GEN lead = (GEN)x[2];
! 507: if (gcmp1(lead))
! 508: {
! 509: av=avma; alp = gclone(gadd(n,gun)); avma=av;
! 510: y=cgetg(lx=lg(x),t_SER);
! 511: y[1] = evalsigne(1) | evalvalp(0) | evalvarn(varn(x));
! 512: y[2] = un;
! 513: for (i=3; i<lx; i++)
! 514: {
! 515: av=avma; p1=gzero;
! 516: for (j=1; j<i-1; j++)
! 517: {
! 518: p2 = gsubgs(gmulgs(alp,j),i-2);
! 519: p1 = gadd(p1,gmul(gmul(p2,(GEN)x[j+2]),(GEN)y[i-j]));
! 520: }
! 521: tetpil=avma; y[i]=lpile(av,tetpil,gdivgs(p1,i-2));
! 522: }
! 523: gunclone(alp); return y;
! 524: }
! 525: av=avma; p1=gdiv(x,lead); p1[2] = un; /* in case it's inexact */
! 526: p1=gpow(p1,n,prec); p2=gpow(lead,n,prec);
! 527: tetpil=avma; return gerepile(av,tetpil,gmul(p1,p2));
! 528: }
! 529: av=avma; y=gmul(n,glog(x,prec)); tetpil=avma;
! 530: return gerepile(av,tetpil,gexp(y,prec));
! 531: }
! 532:
! 533: GEN
! 534: gpow(GEN x, GEN n, long prec)
! 535: {
! 536: long av,tetpil,i,lx,tx;
! 537: GEN y;
! 538:
! 539: if (typ(n)==t_INT) return powgi(x,n);
! 540: tx = typ(x);
! 541: if (is_matvec_t(tx))
! 542: {
! 543: lx=lg(x); y=cgetg(lx,tx);
! 544: for (i=1; i<lx; i++) y[i]=lpui((GEN)x[i],n,prec);
! 545: return y;
! 546: }
! 547: if (tx==t_SER)
! 548: {
! 549: if (valp(x))
! 550: err(talker,"not an integer exponent for non invertible series in gpow");
! 551: if (lg(x) == 2) return gcopy(x); /* O(1) */
! 552: return ser_pui(x,n,prec);
! 553: }
! 554: av=avma;
! 555: if (gcmp0(x))
! 556: {
! 557: n = greal(n);
! 558: if (gsigne(n)<=0) err(talker,"zero to a non positive exponent in gpow");
! 559: i = precision(x); if (!i) return gcopy(x);
! 560:
! 561: x=ground(gmulsg(gexpo(x),n));
! 562: if (lgefint(x)<=3)
! 563: {
! 564: i = itos(x);
! 565: if (labs(i) < (long)HIGHEXPOBIT)
! 566: {
! 567: avma=av; y=cgetr(3); y[1]=evalexpo(i); y[2]=0;
! 568: return y;
! 569: }
! 570: }
! 571: err(talker,"underflow or overflow in gpow");
! 572: }
! 573: i = (long) precision(n); if (i) prec=i;
! 574: y=gmul(n,glog(x,prec)); tetpil=avma;
! 575: return gerepile(av,tetpil,gexp(y,prec));
! 576: }
! 577:
! 578: /********************************************************************/
! 579: /** **/
! 580: /** RACINE CARREE **/
! 581: /** **/
! 582: /********************************************************************/
! 583:
! 584: GEN
! 585: mpsqrt(GEN x)
! 586: {
! 587: long l,l0,l1,l2,s,eps,n,i,ex,av;
! 588: double beta;
! 589: GEN y,p1,p2,p3;
! 590:
! 591: if (typ(x)!=t_REAL) err(typeer,"mpsqrt");
! 592: s=signe(x); if (s<0) err(talker,"negative argument in mpsqrt");
! 593: if (!s)
! 594: {
! 595: y = cgetr(3);
! 596: y[1] = evalexpo(expo(x)>>1);
! 597: y[2] = 0; return y;
! 598: }
! 599: l=lg(x); y=cgetr(l); av=avma;
! 600:
! 601: p1=cgetr(l+1); affrr(x,p1);
! 602: ex=expo(x); eps = ex & 1; ex >>= 1;
! 603: setexpo(p1,eps); setlg(p1,3);
! 604:
! 605: n=(long)(2+log((double) (l-2))/LOG2);
! 606: p2=cgetr(l+1); p2[1]=evalexpo(0) | evalsigne(1);
! 607: beta=sqrt((eps+1) * (2 + p1[2]/C31));
! 608: p2[2]=(long)((beta-2)*C31);
! 609: if (!p2[2]) { p2[2]=HIGHBIT; setexpo(p2,1); }
! 610: for (i=3; i<=l; i++) p2[i]=0;
! 611: setlg(p2,3);
! 612:
! 613: p3=cgetr(l+1); l-=2; l1=1; l2=3;
! 614: for (i=1; i<=n; i++)
! 615: {
! 616: l0 = l1<<1;
! 617: if (l0<=l)
! 618: { l2 += l1; l1=l0; }
! 619: else
! 620: { l2 += l+1-l1; l1=l+1; }
! 621: setlg(p3,l1+2); setlg(p1,l1+2); setlg(p2,l2);
! 622: divrrz(p1,p2,p3); addrrz(p2,p3,p2); setexpo(p2,expo(p2)-1);
! 623: }
! 624: affrr(p2,y); setexpo(y,expo(y)+ex);
! 625: avma=av; return y;
! 626: }
! 627:
! 628: static GEN
! 629: padic_sqrt(GEN x)
! 630: {
! 631: long av = avma, av2,lim,e,r,lpp,lp,pp;
! 632: GEN y;
! 633:
! 634: e=valp(x); y=cgetg(5,t_PADIC); copyifstack(x[2],y[2]);
! 635: if (gcmp0(x))
! 636: {
! 637: y[4] = zero; e = (e+1)>>1;
! 638: y[3] = lpuigs((GEN)x[2],e);
! 639: y[1] = evalvalp(e) | evalprecp(precp(x));
! 640: return y;
! 641: }
! 642: if (e & 1) err(sqrter6);
! 643: e>>=1; setvalp(y,e); y[3] = y[2];
! 644: pp = precp(x);
! 645: if (egalii(gdeux, (GEN)x[2]))
! 646: {
! 647: lp=3; y[4] = un; r = mod8((GEN)x[4]);
! 648: if ((r!=1 && pp>=2) && (r!=5 || pp!=2)) err(sqrter5);
! 649: if (pp <= lp) { setprecp(y,1); return y; }
! 650:
! 651: x = dummycopy(x); setvalp(x,0); setvalp(y,0);
! 652: av2=avma; lim = stack_lim(av2,2);
! 653: y[3] = lstoi(8);
! 654: for(;;)
! 655: {
! 656: lpp=lp; lp=(lp<<1)-1;
! 657: if (lp < pp) y[3] = lshifti((GEN)y[3], lpp-1);
! 658: else
! 659: { lp=pp; y[3] = x[3]; }
! 660: setprecp(y,lp); y = gdiv(gadd(y, gdiv(x,y)), gdeux);
! 661: if (lp < pp) lp--;
! 662: if (cmpii((GEN)y[4], (GEN)y[3]) >= 0)
! 663: y[4] = lsubii((GEN)y[4], (GEN)y[3]);
! 664:
! 665: if (pp <= lp) break;
! 666: if (low_stack(lim,stack_lim(av2,2)))
! 667: {
! 668: if (DEBUGMEM > 1) err(warnmem,"padic_sqrt");
! 669: y = gerepileupto(av2,y);
! 670: }
! 671: }
! 672: y = gcopy(y);
! 673: }
! 674: else /* p != 2 */
! 675: {
! 676: lp=1; y[4] = (long)mpsqrtmod((GEN)x[4],(GEN)x[2]);
! 677: if (!y[4]) err(sqrter5);
! 678: if (pp <= lp) { setprecp(y,1); return y; }
! 679:
! 680: x = dummycopy(x); setvalp(x,0); setvalp(y,0);
! 681: av2=avma; lim = stack_lim(av2,2);
! 682: for(;;)
! 683: {
! 684: lp<<=1;
! 685: if (lp < pp) y[3] = lsqri((GEN)y[3]);
! 686: else
! 687: { lp=pp; y[3] = x[3]; }
! 688: setprecp(y,lp); y = gdiv(gadd(y, gdiv(x,y)), gdeux);
! 689:
! 690: if (pp <= lp) break;
! 691: if (low_stack(lim,stack_lim(av2,2)))
! 692: {
! 693: if (DEBUGMEM > 1) err(warnmem,"padic_sqrt");
! 694: y = gerepileupto(av2,y);
! 695: }
! 696: }
! 697: }
! 698: setvalp(y,e); return gerepileupto(av,y);
! 699: }
! 700:
! 701: GEN
! 702: gsqrt(GEN x, long prec)
! 703: {
! 704: long av,tetpil,e;
! 705: GEN y,p1,p2;
! 706:
! 707: switch(typ(x))
! 708: {
! 709: case t_REAL:
! 710: if (signe(x)>=0) return mpsqrt(x);
! 711: y=cgetg(3,t_COMPLEX); y[1]=zero;
! 712: setsigne(x,1); y[2]=lmpsqrt(x); setsigne(x,-1);
! 713: return y;
! 714:
! 715: case t_INTMOD:
! 716: y=cgetg(3,t_INTMOD); copyifstack(x[1],y[1]);
! 717: p1 = mpsqrtmod((GEN)x[2],(GEN)y[1]);
! 718: if (!p1) err(sqrter5);
! 719: y[2] = (long)p1; return y;
! 720:
! 721: case t_COMPLEX:
! 722: y=cgetg(3,t_COMPLEX); av=avma;
! 723: if (gcmp0((GEN)x[2]))
! 724: {
! 725: long tx=typ(x[1]);
! 726:
! 727: if ((is_intreal_t(tx) || is_frac_t(tx)) && gsigne((GEN)x[1]) < 0)
! 728: {
! 729: y[1]=zero; p1=gneg_i((GEN)x[1]); tetpil=avma;
! 730: y[2]=lpile(av,tetpil,gsqrt(p1,prec));
! 731: return y;
! 732: }
! 733: y[1]=lsqrt((GEN)x[1],prec);
! 734: y[2]=zero; return y;
! 735: }
! 736:
! 737: p1=gsqr((GEN)x[1]); p2=gsqr((GEN)x[2]);
! 738: p1=gsqrt(gadd(p1,p2),prec);
! 739: if (gcmp0(p1))
! 740: {
! 741: y[1]=lsqrt(p1,prec);
! 742: y[2]=lcopy((GEN)y[1]);
! 743: return y;
! 744: }
! 745:
! 746: if (gsigne((GEN)x[1])<0)
! 747: {
! 748: p2=gsub(p1,(GEN)x[1]); p1=gmul2n(p2,-1);
! 749: y[2]=lsqrt(p1,prec); y[1]=ldiv((GEN)x[2],gmul2n((GEN)y[2],1));
! 750: tetpil=avma;
! 751: y = (gsigne((GEN)x[2]) > 0)? gcopy(y): gneg(y);
! 752: return gerepile(av,tetpil,y);
! 753: }
! 754:
! 755: p1=gmul2n(gadd(p1,(GEN)x[1]),-1);
! 756: tetpil=avma; y[1]=lpile(av,tetpil,gsqrt(p1,prec));
! 757: av=avma; p1=gmul2n((GEN)y[1],1); tetpil=avma;
! 758: y[2]=lpile(av,tetpil,gdiv((GEN)x[2],p1));
! 759: return y;
! 760:
! 761: case t_PADIC:
! 762: return padic_sqrt(x);
! 763:
! 764: case t_SER:
! 765: e=valp(x);
! 766: if (gcmp0(x)) return zeroser(varn(x), (e+1)>>1);
! 767: if (e & 1) err(sqrter6);
! 768: /* trick: ser_pui assumes valp(x) = 0 */
! 769: y = ser_pui(x,ghalf,prec);
! 770: y[1] = evalsigne(1) | evalvalp(e>>1) | evalvarn(varn(x));
! 771: return y;
! 772: }
! 773: return transc(gsqrt,x,prec);
! 774: }
! 775:
! 776: void
! 777: gsqrtz(GEN x, GEN y)
! 778: {
! 779: long av=avma, prec = precision(y);
! 780:
! 781: if (!prec) err(infprecer,"gsqrtz");
! 782: gaffect(gsqrt(x,prec),y); avma=av;
! 783: }
! 784:
! 785: /********************************************************************/
! 786: /** **/
! 787: /** FONCTION EXPONENTIELLE-1 **/
! 788: /** **/
! 789: /********************************************************************/
! 790: #ifdef LONG_IS_64BIT
! 791: # define EXMAX 46
! 792: #else
! 793: # define EXMAX 22
! 794: #endif
! 795:
! 796: GEN
! 797: mpexp1(GEN x)
! 798: {
! 799: long l,l1,l2,i,n,m,ex,s,av,av2, sx = signe(x);
! 800: double a,b,alpha,beta, gama = 2.0 /* optimized for SUN3 */;
! 801: /* KB: 3.0 is better for UltraSparc */
! 802: GEN y,p1,p2,p3,p4,unr;
! 803:
! 804: if (typ(x)!=t_REAL) err(typeer,"mpexp1");
! 805: if (!sx)
! 806: {
! 807: y=cgetr(3); y[1]=x[1]; y[2]=0; return y;
! 808: }
! 809: l=lg(x); y=cgetr(l); av=avma; /* room for result */
! 810:
! 811: l2 = l+1; ex = expo(x);
! 812: if (ex > EXMAX) err(talker,"exponent too large in exp");
! 813: alpha = -1-log(2+x[2]/C31)-ex*LOG2;
! 814: beta = 5 + bit_accuracy(l)*LOG2;
! 815: a = sqrt(beta/(gama*LOG2));
! 816: b = (alpha + 0.5*log(beta*gama/LOG2))/LOG2;
! 817: if (a>=b)
! 818: {
! 819: n=(long)(1+sqrt(beta*gama/LOG2));
! 820: m=(long)(1+a-b);
! 821: l2 += m>>TWOPOTBITS_IN_LONG;
! 822: }
! 823: else
! 824: {
! 825: n=(long)(1+beta/alpha);
! 826: m=0;
! 827: }
! 828: unr=realun(l2);
! 829: p2=rcopy(unr); setlg(p2,4);
! 830: p4=cgetr(l2); affrr(x,p4); setsigne(p4,1);
! 831: if (m) setexpo(p4,ex-m);
! 832:
! 833: s=0; l1=4; av2 = avma;
! 834: for (i=n; i>=2; i--)
! 835: {
! 836: setlg(p4,l1); p3 = divrs(p4,i);
! 837: s -= expo(p3); p1 = mulrr(p3,p2); setlg(p1,l1);
! 838: l1 += s>>TWOPOTBITS_IN_LONG; if (l1>l2) l1=l2;
! 839: s %= BITS_IN_LONG;
! 840: setlg(unr,l1); p1 = addrr(unr,p1);
! 841: setlg(p2,l1); affrr(p1,p2); avma = av2;
! 842: }
! 843: setlg(p2,l2); setlg(p4,l2); p2 = mulrr(p4,p2);
! 844:
! 845: for (i=1; i<=m; i++)
! 846: {
! 847: setlg(p2,l2);
! 848: p2 = mulrr(addsr(2,p2),p2);
! 849: }
! 850: if (sx == -1)
! 851: {
! 852: setlg(unr,l2); p2 = addrr(unr,p2);
! 853: setlg(p2,l2); p2 = ginv(p2);
! 854: p2 = subrr(p2,unr);
! 855: }
! 856: affrr(p2,y); avma = av; return y;
! 857: }
! 858: #undef EXMAX
! 859:
! 860: /********************************************************************/
! 861: /** **/
! 862: /** FONCTION EXPONENTIELLE **/
! 863: /** **/
! 864: /********************************************************************/
! 865:
! 866: GEN
! 867: mpexp(GEN x)
! 868: {
! 869: long av, sx = signe(x);
! 870: GEN y;
! 871:
! 872: if (!sx) return addsr(1,x);
! 873: if (sx<0) setsigne(x,1);
! 874: av = avma; y = addsr(1, mpexp1(x));
! 875: if (sx<0) { y = divsr(1,y); setsigne(x,-1); }
! 876: return gerepileupto(av,y);
! 877: }
! 878:
! 879: static GEN
! 880: paexp(GEN x)
! 881: {
! 882: long k,av, e = valp(x), pp = precp(x), n = e + pp;
! 883: GEN y,r,p1;
! 884:
! 885: if (gcmp0(x)) return gaddgs(x,1);
! 886: if (e<=0 || (!cmpis((GEN)x[2],2) && e==1))
! 887: err(talker,"p-adic argument out of range in gexp");
! 888: av = avma;
! 889: if (egalii(gdeux,(GEN)x[2]))
! 890: {
! 891: n--; e--; k = n/e;
! 892: if (n%e==0) k--;
! 893: }
! 894: else
! 895: {
! 896: p1 = subis((GEN)x[2], 1);
! 897: k = itos(dvmdii(subis(mulis(p1,n), 1), subis(mulis(p1,e), 1), &r));
! 898: if (!signe(r)) k--;
! 899: }
! 900: for (y=gun; k; k--) y = gaddsg(1, gdivgs(gmul(y,x), k));
! 901: return gerepileupto(av, y);
! 902: }
! 903:
! 904: GEN
! 905: gexp(GEN x, long prec)
! 906: {
! 907: long av,tetpil,ex;
! 908: GEN r,y,p1,p2;
! 909:
! 910: switch(typ(x))
! 911: {
! 912: case t_REAL:
! 913: return mpexp(x);
! 914:
! 915: case t_COMPLEX:
! 916: y=cgetg(3,t_COMPLEX); av=avma;
! 917: r=gexp((GEN)x[1],prec);
! 918: gsincos((GEN)x[2],&p2,&p1,prec);
! 919: tetpil=avma;
! 920: y[1]=lmul(r,p1); y[2]=lmul(r,p2);
! 921: gerepilemanyvec(av,tetpil,y+1,2);
! 922: return y;
! 923:
! 924: case t_PADIC:
! 925: return paexp(x);
! 926:
! 927: case t_SER:
! 928: if (gcmp0(x)) return gaddsg(1,x);
! 929:
! 930: ex=valp(x); if (ex<0) err(negexper,"gexp");
! 931: if (ex)
! 932: {
! 933: long i,j,ly=lg(x)+ex;
! 934:
! 935: y=cgetg(ly,t_SER);
! 936: y[1] = evalsigne(1) | evalvalp(0) | evalvarn(varn(x));
! 937: y[2] = un;
! 938: for (i=3; i<ex+2; i++) y[i]=zero;
! 939: for ( ; i<ly; i++)
! 940: {
! 941: av=avma; p1=gzero;
! 942: for (j=ex; j<i-1; j++)
! 943: p1=gadd(p1,gmulgs(gmul((GEN)x[j-ex+2],(GEN)y[i-j]),j));
! 944: tetpil=avma; y[i]=lpile(av,tetpil,gdivgs(p1,i-2));
! 945: }
! 946: return y;
! 947: }
! 948: av=avma; p1=gcopy(x); p1[2]=zero;
! 949: p2=gexp(normalize(p1),prec);
! 950: p1=gexp((GEN)x[2],prec); tetpil=avma;
! 951: return gerepile(av,tetpil,gmul(p1,p2));
! 952:
! 953: case t_INTMOD:
! 954: err(typeer,"gexp");
! 955: }
! 956: return transc(gexp,x,prec);
! 957: }
! 958:
! 959: void
! 960: gexpz(GEN x, GEN y)
! 961: {
! 962: long av=avma, prec = precision(y);
! 963:
! 964: if (!prec) err(infprecer,"gexpz");
! 965: gaffect(gexp(x,prec),y); avma=av;
! 966: }
! 967:
! 968: /********************************************************************/
! 969: /** **/
! 970: /** FONCTION LOGARITHME **/
! 971: /** **/
! 972: /********************************************************************/
! 973:
! 974: GEN
! 975: mplog(GEN x)
! 976: {
! 977: long l,l1,l2,m,m1,n,i,ex,s,sgn,ltop,av;
! 978: double alpha,beta,a,b;
! 979: GEN y,p1,p2,p3,p4,p5,unr;
! 980:
! 981: if (typ(x)!=t_REAL) err(typeer,"mplog");
! 982: if (signe(x)<=0) err(talker,"non positive argument in mplog");
! 983: l=lg(x); sgn = cmpsr(1,x); if (!sgn) return realzero(l);
! 984: y=cgetr(l); ltop=avma;
! 985:
! 986: l2 = l+1; p2=p1=cgetr(l2); affrr(x,p1);
! 987: av=avma;
! 988: if (sgn > 0) p2 = divsr(1,p1); /* x<1 changer x en 1/x */
! 989: for (m1=1; expo(p2)>0; m1++) p2 = mpsqrt(p2);
! 990: if (m1 > 1 || sgn > 0) { affrr(p2,p1); avma=av; }
! 991:
! 992: alpha = 1+p1[2]/C31; if (!alpha) alpha = 0.00000001;
! 993: l -= 2; alpha = -log(alpha);
! 994: beta = (BITS_IN_LONG/2)*l*LOG2;
! 995: a = alpha/LOG2;
! 996: b = sqrt((BITS_IN_LONG/2)*l/3.0);
! 997: if (a<=b)
! 998: {
! 999: n=(long)(1+sqrt((BITS_IN_LONG/2)*3.0*l));
! 1000: m=(long)(1+b-a);
! 1001: l2 += m>>TWOPOTBITS_IN_LONG;
! 1002: p4=cgetr(l2); affrr(p1,p4);
! 1003: p1 = p4; av=avma;
! 1004: for (i=1; i<=m; i++) p1 = mpsqrt(p1);
! 1005: affrr(p1,p4); avma=av;
! 1006: }
! 1007: else
! 1008: {
! 1009: n=(long)(1+beta/alpha);
! 1010: m=0; p4 = p1;
! 1011: }
! 1012: unr=realun(l2);
! 1013: p2=cgetr(l2); p3=cgetr(l2); av=avma;
! 1014:
! 1015: /* affrr needed here instead of setlg since prec may DECREASE */
! 1016: p1 = cgetr(l2); affrr(subrr(p4,unr), p1);
! 1017:
! 1018: p5 = addrr(p4,unr); setlg(p5,l2);
! 1019: affrr(divrr(p1,p5), p2);
! 1020: affrr(mulrr(p2,p2), p3);
! 1021: affrr(divrs(unr,2*n+1), p4); setlg(p4,4); avma=av;
! 1022:
! 1023: s=0; ex=expo(p3); l1 = 4;
! 1024: for (i=n; i>=1; i--)
! 1025: {
! 1026: setlg(p3,l1); p5 = mulrr(p4,p3);
! 1027: setlg(unr,l1); p1 = divrs(unr,2*i-1);
! 1028: s -= ex;
! 1029: l1 += s>>TWOPOTBITS_IN_LONG; if (l1>l2) l1=l2;
! 1030: s %= BITS_IN_LONG;
! 1031: setlg(p1,l1); setlg(p4,l1); setlg(p5,l1);
! 1032: p1 = addrr(p1,p5); affrr(p1,p4); avma=av;
! 1033: }
! 1034: setlg(p4,l2); affrr(mulrr(p2,p4), y);
! 1035: setexpo(y, expo(y)+m+m1);
! 1036: if (sgn > 0) setsigne(y, -1);
! 1037: avma=ltop; return y;
! 1038: }
! 1039:
! 1040: GEN
! 1041: teich(GEN x)
! 1042: {
! 1043: GEN aux,y,z,p1;
! 1044: long av,n,k;
! 1045:
! 1046: if (typ(x)!=t_PADIC) err(talker,"not a p-adic argument in teichmuller");
! 1047: if (!signe(x[4])) return gcopy(x);
! 1048: y=cgetp(x); z=(GEN)x[4];
! 1049: if (!cmpis((GEN)x[2],2))
! 1050: {
! 1051: n = mod4(z);
! 1052: if (n & 2)
! 1053: addsiz(-1,(GEN)x[3],(GEN)y[4]);
! 1054: else
! 1055: affsi(1,(GEN)y[4]);
! 1056: return y;
! 1057: }
! 1058: av = avma; p1 = addsi(-1,(GEN)x[2]);
! 1059: aux = divii(addsi(-1,(GEN)x[3]),p1); n = precp(x);
! 1060: for (k=1; k<n; k<<=1)
! 1061: z=modii(mulii(z,addsi(1,mulii(aux,addsi(-1,powmodulo(z,p1,(GEN)x[3]))))),
! 1062: (GEN)x[3]);
! 1063: affii(z,(GEN)y[4]); avma=av; return y;
! 1064: }
! 1065:
! 1066: static GEN
! 1067: palogaux(GEN x)
! 1068: {
! 1069: long av1=avma,tetpil,k,e,pp;
! 1070: GEN y,s,y2;
! 1071:
! 1072: if (egalii(gun,(GEN)x[4]))
! 1073: {
! 1074: y=gaddgs(x,-1);
! 1075: if (egalii(gdeux,(GEN)x[2]))
! 1076: {
! 1077: setvalp(y,valp(y)-1);
! 1078: if (!gcmp1((GEN)y[3])) y[3]=lshifti((GEN)y[3],-1);
! 1079: }
! 1080: tetpil=avma; return gerepile(av1,tetpil,gcopy(y));
! 1081: }
! 1082: y=gdiv(gaddgs(x,-1),gaddgs(x,1)); e=valp(y); pp=e+precp(y);
! 1083: if (egalii(gdeux,(GEN)x[2])) pp--;
! 1084: else
! 1085: {
! 1086: long av=avma;
! 1087: GEN p1;
! 1088:
! 1089: for (p1=stoi(e); cmpsi(pp,p1)>0; pp++)
! 1090: p1 = mulii(p1,(GEN)x[2]);
! 1091: avma=av; pp-=2;
! 1092: }
! 1093: k=pp/e; if (!odd(k)) k--;
! 1094: y2=gsqr(y); s=gdivgs(gun,k);
! 1095: while (k>=3)
! 1096: {
! 1097: k-=2; s=gadd(gmul(y2,s),gdivgs(gun,k));
! 1098: }
! 1099: tetpil=avma; return gerepile(av1,tetpil,gmul(s,y));
! 1100: }
! 1101:
! 1102: GEN
! 1103: palog(GEN x)
! 1104: {
! 1105: long av=avma,tetpil;
! 1106: GEN p1,y;
! 1107:
! 1108: if (!signe(x[4])) err(talker,"zero argument in palog");
! 1109: if (cmpis((GEN)x[2],2))
! 1110: {
! 1111: y=cgetp(x); p1=gsubgs((GEN)x[2],1);
! 1112: affii(powmodulo((GEN)x[4],p1,(GEN)x[3]),(GEN)y[4]);
! 1113: y=gmulgs(palogaux(y),2); tetpil=avma;
! 1114: return gerepile(av,tetpil,gdiv(y,p1));
! 1115: }
! 1116: y=gsqr(x); setvalp(y,0); tetpil=avma;
! 1117: return gerepile(av,tetpil,palogaux(y));
! 1118: }
! 1119:
! 1120: GEN
! 1121: log0(GEN x, long flag,long prec)
! 1122: {
! 1123: switch(flag)
! 1124: {
! 1125: case 0: return glog(x,prec);
! 1126: case 1: return glogagm(x,prec);
! 1127: default: err(flagerr,"log");
! 1128: }
! 1129: return NULL; /* not reached */
! 1130: }
! 1131:
! 1132: GEN
! 1133: glog(GEN x, long prec)
! 1134: {
! 1135: long av,tetpil;
! 1136: GEN y,p1,p2;
! 1137:
! 1138: switch(typ(x))
! 1139: {
! 1140: case t_REAL:
! 1141: if (signe(x)>=0) return mplog(x);
! 1142: y=cgetg(3,t_COMPLEX); y[2]=lmppi(lg(x));
! 1143: setsigne(x,1); y[1]=lmplog(x);
! 1144: setsigne(x,-1); return y;
! 1145:
! 1146: case t_COMPLEX:
! 1147: y=cgetg(3,t_COMPLEX); y[2]=larg(x,prec);
! 1148: av=avma; p1=glog(gnorm(x),prec); tetpil=avma;
! 1149: y[1]=lpile(av,tetpil,gmul2n(p1,-1));
! 1150: return y;
! 1151:
! 1152: case t_PADIC:
! 1153: return palog(x);
! 1154:
! 1155: case t_SER:
! 1156: av=avma; if (valp(x)) err(negexper,"glog");
! 1157: p1=gdiv(derivser(x),x);
! 1158: tetpil=avma; p1=integ(p1,varn(x));
! 1159: if (gcmp1((GEN)x[2])) return gerepile(av,tetpil,p1);
! 1160:
! 1161: p2=glog((GEN)x[2],prec); tetpil=avma;
! 1162: return gerepile(av,tetpil,gadd(p1,p2));
! 1163:
! 1164: case t_INTMOD:
! 1165: err(typeer,"glog");
! 1166: }
! 1167: return transc(glog,x,prec);
! 1168: }
! 1169:
! 1170: void
! 1171: glogz(GEN x, GEN y)
! 1172: {
! 1173: long av=avma, prec = precision(y);
! 1174:
! 1175: if (!prec) err(infprecer,"glogz");
! 1176: gaffect(glog(x,prec),y); avma=av;
! 1177: }
! 1178:
! 1179: /********************************************************************/
! 1180: /** **/
! 1181: /** FONCTION SINCOS-1 **/
! 1182: /** **/
! 1183: /********************************************************************/
! 1184:
! 1185: static GEN
! 1186: mpsc1(GEN x, long *ptmod8)
! 1187: {
! 1188: const long mmax = 23169;
! 1189: /* on a 64-bit machine with true 128 bit/64 bit division, one could
! 1190: * take mmax=1518500248; on the alpha it does not seem worthwhile
! 1191: */
! 1192: long l,l0,l1,l2,l4,ee,i,n,m,s,t,av;
! 1193: double alpha,beta,a,b,c,d;
! 1194: GEN y,p1,p2,p3,p4,pitemp;
! 1195:
! 1196: if (typ(x)!=t_REAL) err(typeer,"mpsc1");
! 1197: if (!signe(x))
! 1198: {
! 1199: y=cgetr(3);
! 1200: y[1] = evalexpo((expo(x)<<1) - 1);
! 1201: y[2] = 0; *ptmod8=0; return y;
! 1202: }
! 1203: l=lg(x); y=cgetr(l); av=avma;
! 1204:
! 1205: l++; pitemp = mppi(l+1); setexpo(pitemp,-1);
! 1206: p1 = addrr(x,pitemp); setexpo(pitemp,0);
! 1207: if (expo(p1) >= bit_accuracy(min(l,lg(p1))) + 3)
! 1208: err(talker,"loss of precision in mpsc1");
! 1209: p3 = divrr(p1,pitemp); p2 = mpent(p3);
! 1210: if (signe(p2)) x = subrr(x, mulir(p2,pitemp));
! 1211: p1 = cgetr(l+1); affrr(x, p1);
! 1212:
! 1213: *ptmod8 = (signe(p1) < 0)? 4: 0;
! 1214: if (signe(p2))
! 1215: {
! 1216: long mod4 = mod4(p2);
! 1217: if (signe(p2) < 0 && mod4) mod4 = 4-mod4;
! 1218: *ptmod8 += mod4;
! 1219: }
! 1220: if (gcmp0(p1)) alpha=1000000.0;
! 1221: else
! 1222: {
! 1223: m=expo(p1); alpha=(m<-1023)? -1-m*LOG2: -1-log(fabs(rtodbl(p1)));
! 1224: }
! 1225: beta = 5 + bit_accuracy(l)*LOG2;
! 1226: a=0.5/LOG2; b=0.5*a;
! 1227: c = a+sqrt((beta+b)/LOG2);
! 1228: d = ((beta/c)-alpha-log(c))/LOG2;
! 1229: if (d>=0)
! 1230: {
! 1231: m=(long)(1+d);
! 1232: n=(long)((1+c)/2.0);
! 1233: setexpo(p1,expo(p1)-m);
! 1234: }
! 1235: else { m=0; n=(long)((1+beta/alpha)/2.0); }
! 1236: l2=l+1+(m>>TWOPOTBITS_IN_LONG);
! 1237: p2=realun(l2); setlg(p2,4);
! 1238: p4=cgetr(l2); av = avma;
! 1239: affrr(gsqr(p1),p4); setlg(p4,4);
! 1240:
! 1241: if (n>mmax)
! 1242: p3 = divrs(divrs(p4,2*n+2),2*n+1);
! 1243: else
! 1244: p3 = divrs(p4, (2*n+2)*(2*n+1));
! 1245: ee = -expo(p3); s=0;
! 1246: l4 = l1 = 3 + (ee>>TWOPOTBITS_IN_LONG);
! 1247: if (l4<=l2) { setlg(p2,l4); setlg(p4,l4); }
! 1248: for (i=n; i>mmax; i--)
! 1249: {
! 1250: p3 = divrs(divrs(p4,2*i),2*i-1); s -= expo(p3);
! 1251: t=s&(BITS_IN_LONG-1); l0=(s>>TWOPOTBITS_IN_LONG);
! 1252: if (t) l0++;
! 1253: l1 += l0; if (l1>l2) { l0 += l2-l1; l1=l2; }
! 1254: l4 += l0;
! 1255: p3 = mulrr(p3,p2);
! 1256: if (l4<=l2) { setlg(p2,l4); setlg(p4,l4); }
! 1257: subsrz(1,p3,p2); avma=av;
! 1258: }
! 1259: for ( ; i>=2; i--)
! 1260: {
! 1261: p3 = divrs(p4, 2*i*(2*i-1)); s -= expo(p3);
! 1262: t=s&(BITS_IN_LONG-1); l0=(s>>TWOPOTBITS_IN_LONG);
! 1263: if (t) l0++;
! 1264: l1 += l0; if (l1>l2) { l0 += l2-l1; l1=l2; }
! 1265: l4 += l0;
! 1266: p3 = mulrr(p3,p2);
! 1267: if (l4<=l2) { setlg(p2,l4); setlg(p4,l4); }
! 1268: subsrz(1,p3,p2); avma=av;
! 1269: }
! 1270: if (l4<=l2) { setlg(p2,l4); setlg(p4,l4); }
! 1271: setexpo(p4,expo(p4)-1); setsigne(p4, -signe(p4));
! 1272: p2 = mulrr(p4,p2);
! 1273: for (i=1; i<=m; i++)
! 1274: {
! 1275: p2 = mulrr(p2,addsr(2,p2)); setexpo(p2,expo(p2)+1);
! 1276: }
! 1277: affrr(p2,y); avma=av; return y;
! 1278: }
! 1279:
! 1280: /********************************************************************/
! 1281: /** **/
! 1282: /** FONCTION sqrt(-x*(x+2)) **/
! 1283: /** **/
! 1284: /********************************************************************/
! 1285:
! 1286: static GEN
! 1287: mpaut(GEN x)
! 1288: {
! 1289: long av = avma;
! 1290: GEN p1;
! 1291:
! 1292: cgetr(2*lg(x)+3); /* bound for 2*lg(p1)+1 */
! 1293: p1=mulrr(x,addsr(2,x)); setsigne(p1,-signe(p1));
! 1294: avma = av; return mpsqrt(p1); /* safe ! */
! 1295: }
! 1296:
! 1297: /********************************************************************/
! 1298: /** **/
! 1299: /** FONCTION COSINUS **/
! 1300: /** **/
! 1301: /********************************************************************/
! 1302:
! 1303: static GEN
! 1304: mpcos(GEN x)
! 1305: {
! 1306: long mod8,av,tetpil;
! 1307: GEN y,p1;
! 1308:
! 1309: if (typ(x)!=t_REAL) err(typeer,"mpcos");
! 1310: if (!signe(x)) return addsr(1,x);
! 1311:
! 1312: av=avma; p1=mpsc1(x,&mod8); tetpil=avma;
! 1313: switch(mod8)
! 1314: {
! 1315: case 0: case 4:
! 1316: y=addsr(1,p1); break;
! 1317: case 1: case 7:
! 1318: y=mpaut(p1); setsigne(y,-signe(y)); break;
! 1319: case 2: case 6:
! 1320: y=subsr(-1,p1); break;
! 1321: case 3: case 5:
! 1322: y=mpaut(p1); break;
! 1323: default:;
! 1324: }
! 1325: return gerepile(av,tetpil,y);
! 1326: }
! 1327:
! 1328: GEN
! 1329: gcos(GEN x, long prec)
! 1330: {
! 1331: long av,tetpil;
! 1332: GEN r,u,v,y,p1,p2;
! 1333:
! 1334: switch(typ(x))
! 1335: {
! 1336: case t_REAL:
! 1337: return mpcos(x);
! 1338:
! 1339: case t_COMPLEX:
! 1340: y=cgetg(3,t_COMPLEX); av=avma;
! 1341: r=gexp((GEN)x[2],prec); p1=ginv(r);
! 1342: p2=gmul2n(mpadd(p1,r),-1);
! 1343: p1=mpsub(p2,r);
! 1344: gsincos((GEN)x[1],&u,&v,prec);
! 1345: tetpil=avma;
! 1346: y[1]=lmul(p2,v); y[2]=lmul(p1,u);
! 1347: gerepilemanyvec(av,tetpil,y+1,2);
! 1348: return y;
! 1349:
! 1350: case t_SER:
! 1351: if (gcmp0(x)) return gaddsg(1,x);
! 1352: if (valp(x)<0) err(negexper,"gcos");
! 1353:
! 1354: av=avma; gsincos(x,&u,&v,prec); tetpil=avma;
! 1355: return gerepile(av,tetpil,gcopy(v));
! 1356:
! 1357: case t_INTMOD: case t_PADIC:
! 1358: err(typeer,"gcos");
! 1359: }
! 1360: return transc(gcos,x,prec);
! 1361: }
! 1362:
! 1363: void
! 1364: gcosz(GEN x, GEN y)
! 1365: {
! 1366: long av = avma, prec = precision(y);
! 1367:
! 1368: if (!prec) err(infprecer,"gcosz");
! 1369: gaffect(gcos(x,prec),y); avma=av;
! 1370: }
! 1371:
! 1372: /********************************************************************/
! 1373: /** **/
! 1374: /** FONCTION SINUS **/
! 1375: /** **/
! 1376: /********************************************************************/
! 1377:
! 1378: GEN
! 1379: mpsin(GEN x)
! 1380: {
! 1381: long mod8,av,tetpil;
! 1382: GEN y,p1;
! 1383:
! 1384: if (typ(x)!=t_REAL) err(typeer,"mpsin");
! 1385: if (!signe(x))
! 1386: {
! 1387: y=cgetr(3); y[1]=x[1]; y[2]=0;
! 1388: return y;
! 1389: }
! 1390:
! 1391: av=avma; p1=mpsc1(x,&mod8); tetpil=avma;
! 1392: switch(mod8)
! 1393: {
! 1394: case 0: case 6:
! 1395: y=mpaut(p1); break;
! 1396: case 1: case 5:
! 1397: y=addsr(1,p1); break;
! 1398: case 2: case 4:
! 1399: y=mpaut(p1); setsigne(y,-signe(y)); break;
! 1400: case 3: case 7:
! 1401: y=subsr(-1,p1); break;
! 1402: default:;
! 1403: }
! 1404: return gerepile(av,tetpil,y);
! 1405: }
! 1406:
! 1407: GEN
! 1408: gsin(GEN x, long prec)
! 1409: {
! 1410: long av,tetpil;
! 1411: GEN r,u,v,y,p1,p2;
! 1412:
! 1413: switch(typ(x))
! 1414: {
! 1415: case t_REAL:
! 1416: return mpsin(x);
! 1417:
! 1418: case t_COMPLEX:
! 1419: y=cgetg(3,t_COMPLEX); av=avma;
! 1420: r=gexp((GEN)x[2],prec); p1=ginv(r);
! 1421: p2=gmul2n(mpadd(p1,r),-1);
! 1422: p1=mpsub(p2,p1);
! 1423: gsincos((GEN)x[1],&u,&v,prec);
! 1424: tetpil=avma;
! 1425: y[1]=lmul(p2,u); y[2]=lmul(p1,v);
! 1426: gerepilemanyvec(av,tetpil,y+1,2);
! 1427: return y;
! 1428:
! 1429: case t_SER:
! 1430: if (gcmp0(x)) return gcopy(x);
! 1431: if (valp(x)<0) err(negexper,"gsin");
! 1432:
! 1433: av=avma; gsincos(x,&u,&v,prec); tetpil=avma;
! 1434: return gerepile(av,tetpil,gcopy(u));
! 1435:
! 1436: case t_INTMOD: case t_PADIC:
! 1437: err(typeer,"gsin");
! 1438: }
! 1439: return transc(gsin,x,prec);
! 1440: }
! 1441:
! 1442: void
! 1443: gsinz(GEN x, GEN y)
! 1444: {
! 1445: long av=avma, prec = precision(y);
! 1446:
! 1447: if (!prec) err(infprecer,"gsinz");
! 1448: gaffect(gsin(x,prec),y); avma=av;
! 1449: }
! 1450:
! 1451: /********************************************************************/
! 1452: /** **/
! 1453: /** PROCEDURE SINUS,COSINUS **/
! 1454: /** **/
! 1455: /********************************************************************/
! 1456:
! 1457: void
! 1458: mpsincos(GEN x, GEN *s, GEN *c)
! 1459: {
! 1460: long av,tetpil,mod8;
! 1461: GEN p1, *gptr[2];
! 1462:
! 1463: if (typ(x)!=t_REAL) err(typeer,"mpsincos");
! 1464: if (!signe(x))
! 1465: {
! 1466: p1=cgetr(3); *s=p1; p1[1]=x[1];
! 1467: p1[2]=0; *c=addsr(1,x); return;
! 1468: }
! 1469:
! 1470: av=avma; p1=mpsc1(x,&mod8); tetpil=avma;
! 1471: switch(mod8)
! 1472: {
! 1473: case 0: *c=addsr( 1,p1); *s=mpaut(p1); break;
! 1474: case 1: *s=addsr( 1,p1); *c=mpaut(p1); setsigne(*c,-signe(*c)); break;
! 1475: case 2: *c=subsr(-1,p1); *s=mpaut(p1); setsigne(*s,-signe(*s)); break;
! 1476: case 3: *s=subsr(-1,p1); *c=mpaut(p1); break;
! 1477: case 4: *c=addsr( 1,p1); *s=mpaut(p1); setsigne(*s,-signe(*s)); break;
! 1478: case 5: *s=addsr( 1,p1); *c=mpaut(p1); break;
! 1479: case 6: *c=subsr(-1,p1); *s=mpaut(p1); break;
! 1480: case 7: *s=subsr(-1,p1); *c=mpaut(p1); setsigne(*c,-signe(*c)); break;
! 1481: }
! 1482: gptr[0]=s; gptr[1]=c;
! 1483: gerepilemanysp(av,tetpil,gptr,2);
! 1484: }
! 1485:
! 1486: void
! 1487: gsincos(GEN x, GEN *s, GEN *c, long prec)
! 1488: {
! 1489: long av,tetpil,ii,i,j,ex,ex2,lx,ly;
! 1490: GEN r,u,v,u1,v1,p1,p2,p3,p4,ps,pc;
! 1491: GEN *gptr[4];
! 1492:
! 1493: switch(typ(x))
! 1494: {
! 1495: case t_INT: case t_FRAC: case t_FRACN:
! 1496: av=avma; p1=cgetr(prec); gaffect(x,p1); tetpil=avma;
! 1497: mpsincos(p1,s,c); gptr[0]=s; gptr[1]=c;
! 1498: gerepilemanysp(av,tetpil,gptr,2);
! 1499: return;
! 1500:
! 1501: case t_REAL:
! 1502: mpsincos(x,s,c); return;
! 1503:
! 1504: case t_COMPLEX:
! 1505: ps=cgetg(3,t_COMPLEX); pc=cgetg(3,t_COMPLEX);
! 1506: *s=ps; *c=pc; av=avma;
! 1507: r=gexp((GEN)x[2],prec); p1=ginv(r);
! 1508: p2=gmul2n(mpadd(p1,r),-1);
! 1509: p1=mpsub(p2,p1); r=mpsub(p2,r);
! 1510: gsincos((GEN)x[1],&u,&v,prec);
! 1511: tetpil=avma;
! 1512: p1=gmul(p2,u); p2=gmul(p1,v);
! 1513: p3=gmul(p2,v); p4=gmul(r,u);
! 1514: gptr[0]=&p1; gptr[1]=&p2; gptr[2]=&p3; gptr[3]=&p4;
! 1515: gerepilemanysp(av,tetpil,gptr,4);
! 1516: ps[1]=(long)p1; ps[2]=(long)p2; pc[1]=(long)p3; pc[2]=(long)p4;
! 1517: return;
! 1518:
! 1519: case t_SER:
! 1520: if (gcmp0(x)) { *c=gaddsg(1,x); *s=gcopy(x); return; }
! 1521:
! 1522: ex=valp(x); lx=lg(x); ex2=2*ex+2;
! 1523: if (ex < 0) err(talker,"non zero exponent in gsincos");
! 1524: if (ex2 > lx)
! 1525: {
! 1526: *s=gcopy(x); av=avma; p1=gdivgs(gsqr(x),2);
! 1527: tetpil=avma; *c=gerepile(av,tetpil,gsubsg(1,p1));
! 1528: return;
! 1529: }
! 1530: if (!ex)
! 1531: {
! 1532: av=avma; p1=gcopy(x); p1[2]=zero;
! 1533: gsincos(normalize(p1),&u,&v,prec);
! 1534: gsincos((GEN)x[2],&u1,&v1,prec);
! 1535: p1=gmul(v1,v); p2=gmul(u1,u); p3=gmul(v1,u);
! 1536: p4=gmul(u1,v); tetpil=avma;
! 1537: *c=gsub(p1,p2); *s=gadd(p3,p4);
! 1538: gptr[0]=s; gptr[1]=c;
! 1539: gerepilemanysp(av,tetpil,gptr,2);
! 1540: return;
! 1541: }
! 1542:
! 1543: ly=lx+2*ex;
! 1544: pc=cgetg(ly,t_SER); *c=pc;
! 1545: ps=cgetg(lx,t_SER); *s=ps;
! 1546: pc[1] = evalsigne(1) | evalvalp(0) | evalvarn(varn(x));
! 1547: pc[2]=un; ps[1]=x[1];
! 1548: for (i=2; i<ex+2; i++) ps[i]=lcopy((GEN)x[i]);
! 1549: for (i=3; i<ex2; i++) pc[i]=zero;
! 1550: for (i=ex2; i<ly; i++)
! 1551: {
! 1552: ii=i-ex; av=avma; p1=gzero;
! 1553: for (j=ex; j<ii-1; j++)
! 1554: p1=gadd(p1,gmulgs(gmul((GEN)x[j-ex+2],(GEN)ps[ii-j]),j));
! 1555: tetpil=avma;
! 1556: pc[i]=lpile(av,tetpil,gdivgs(p1,2-i));
! 1557: if (ii<lx)
! 1558: {
! 1559: av=avma; p1=gzero;
! 1560: for (j=ex; j<=i-ex2; j++)
! 1561: p1=gadd(p1,gmulgs(gmul((GEN)x[j-ex+2],(GEN)pc[i-j]),j));
! 1562: p1=gdivgs(p1,i-2); tetpil=avma;
! 1563: ps[i-ex]=lpile(av,tetpil,gadd(p1,(GEN)x[i-ex]));
! 1564: }
! 1565: }
! 1566: return;
! 1567: }
! 1568: err(typeer,"gsincos");
! 1569: }
! 1570:
! 1571: /********************************************************************/
! 1572: /** **/
! 1573: /** FONCTIONS TANGENTE ET COTANGENTE **/
! 1574: /** **/
! 1575: /********************************************************************/
! 1576:
! 1577: static GEN
! 1578: mptan(GEN x)
! 1579: {
! 1580: long av=avma,tetpil;
! 1581: GEN s,c;
! 1582:
! 1583: mpsincos(x,&s,&c); tetpil=avma;
! 1584: return gerepile(av,tetpil,divrr(s,c));
! 1585: }
! 1586:
! 1587: GEN
! 1588: gtan(GEN x, long prec)
! 1589: {
! 1590: long av,tetpil;
! 1591: GEN s,c;
! 1592:
! 1593: switch(typ(x))
! 1594: {
! 1595: case t_REAL:
! 1596: return mptan(x);
! 1597:
! 1598: case t_SER:
! 1599: if (gcmp0(x)) return gcopy(x);
! 1600: if (valp(x)<0) err(negexper,"gtan"); /* fall through */
! 1601: case t_COMPLEX:
! 1602: av=avma; gsincos(x,&s,&c,prec); tetpil=avma;
! 1603: return gerepile(av,tetpil,gdiv(s,c));
! 1604:
! 1605: case t_INTMOD: case t_PADIC:
! 1606: err(typeer,"gtan");
! 1607: }
! 1608: return transc(gtan,x,prec);
! 1609: }
! 1610:
! 1611: void
! 1612: gtanz(GEN x, GEN y)
! 1613: {
! 1614: long av=avma, prec = precision(y);
! 1615:
! 1616: if (!prec) err(infprecer,"gtanz");
! 1617: gaffect(gtan(x,prec),y); avma=av;
! 1618: }
! 1619:
! 1620: static GEN
! 1621: mpcotan(GEN x)
! 1622: {
! 1623: long av=avma,tetpil;
! 1624: GEN s,c;
! 1625:
! 1626: mpsincos(x,&s,&c); tetpil=avma;
! 1627: return gerepile(av,tetpil,divrr(c,s));
! 1628: }
! 1629:
! 1630: GEN
! 1631: gcotan(GEN x, long prec)
! 1632: {
! 1633: long av,tetpil;
! 1634: GEN s,c;
! 1635:
! 1636: switch(typ(x))
! 1637: {
! 1638: case t_REAL:
! 1639: return mpcotan(x);
! 1640:
! 1641: case t_SER: err(negexper,"gcotan"); /* fall through */
! 1642: case t_COMPLEX:
! 1643: av=avma; gsincos(x,&s,&c,prec); tetpil=avma;
! 1644: return gerepile(av,tetpil,gdiv(c,s));
! 1645:
! 1646: case t_INTMOD: case t_PADIC:
! 1647: err(typeer,"gcotan");
! 1648: }
! 1649: return transc(gcotan,x,prec);
! 1650: }
! 1651:
! 1652: void
! 1653: gcotanz(GEN x, GEN y)
! 1654: {
! 1655: long av=avma, prec = precision(y);
! 1656:
! 1657: if (!prec) err(infprecer,"gcotanz");
! 1658: gaffect(gcotan(x,prec),y); avma=av;
! 1659: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>