Annotation of OpenXM_contrib/pari/src/basemath/arith1.c, Revision 1.1
1.1 ! maekawa 1: /*********************************************************************/
! 2: /** **/
! 3: /** ARITHMETIC FUNCTIONS **/
! 4: /** (first part) **/
! 5: /** **/
! 6: /*********************************************************************/
! 7: /* $Id: arith1.c,v 1.2 1999/09/23 17:50:55 karim Exp $ */
! 8: #include "pari.h"
! 9:
! 10: /*********************************************************************/
! 11: /** **/
! 12: /** ARITHMETIC FUNCTION PROTOTYPES **/
! 13: /** **/
! 14: /*********************************************************************/
! 15: GEN
! 16: garith_proto(GEN f(GEN), GEN x, int do_error)
! 17: {
! 18: long tx=typ(x),lx,i;
! 19: GEN y;
! 20:
! 21: if (is_matvec_t(tx))
! 22: {
! 23: lx=lg(x); y=cgetg(lx,tx);
! 24: for (i=1; i<lx; i++) y[i] = (long) garith_proto(f,(GEN) x[i], do_error);
! 25: return y;
! 26: }
! 27: if (tx != t_INT && do_error) err(arither1);
! 28: return f(x);
! 29: }
! 30:
! 31: GEN
! 32: arith_proto(long f(GEN), GEN x, int do_error)
! 33: {
! 34: long tx=typ(x),lx,i;
! 35: GEN y;
! 36:
! 37: if (is_matvec_t(tx))
! 38: {
! 39: lx=lg(x); y=cgetg(lx,tx);
! 40: for (i=1; i<lx; i++) y[i] = (long) arith_proto(f,(GEN) x[i], do_error);
! 41: return y;
! 42: }
! 43: if (tx != t_INT && do_error) err(arither1);
! 44: return stoi(f(x));
! 45: }
! 46:
! 47: static GEN
! 48: arith_proto2(long f(GEN,GEN), GEN x, GEN n)
! 49: {
! 50: long l,i,tx = typ(x);
! 51: GEN y;
! 52:
! 53: if (is_matvec_t(tx))
! 54: {
! 55: l=lg(x); y=cgetg(l,tx);
! 56: for (i=1; i<l; i++) y[i] = (long) arith_proto2(f,(GEN) x[i],n);
! 57: return y;
! 58: }
! 59: if (tx != t_INT) err(arither1);
! 60: tx=typ(n);
! 61: if (is_matvec_t(tx))
! 62: {
! 63: l=lg(n); y=cgetg(l,tx);
! 64: for (i=1; i<l; i++) y[i] = (long) arith_proto2(f,x,(GEN) n[i]);
! 65: return y;
! 66: }
! 67: if (tx != t_INT) err(arither1);
! 68: return stoi(f(x,n));
! 69: }
! 70:
! 71: static GEN
! 72: arith_proto2gs(long f(GEN,long), GEN x, long y)
! 73: {
! 74: long l,i,tx = typ(x);
! 75: GEN t;
! 76:
! 77: if (is_matvec_t(tx))
! 78: {
! 79: l=lg(x); t=cgetg(l,tx);
! 80: for (i=1; i<l; i++) t[i]= (long) arith_proto2gs(f,(GEN) x[i],y);
! 81: return t;
! 82: }
! 83: if (tx != t_INT) err(arither1);
! 84: return stoi(f(x,y));
! 85: }
! 86:
! 87: GEN
! 88: garith_proto2gs(GEN f(GEN,long), GEN x, long y)
! 89: {
! 90: long l,i,tx = typ(x);
! 91: GEN t;
! 92:
! 93: if (is_matvec_t(tx))
! 94: {
! 95: l=lg(x); t=cgetg(l,tx);
! 96: for (i=1; i<l; i++) t[i]= (long) garith_proto2gs(f,(GEN) x[i],y);
! 97: return t;
! 98: }
! 99: if (tx != t_INT) err(arither1);
! 100: return f(x,y);
! 101: }
! 102:
! 103: /*********************************************************************/
! 104: /** **/
! 105: /** BINARY DECOMPOSITION **/
! 106: /** **/
! 107: /*********************************************************************/
! 108:
! 109: GEN
! 110: binaire(GEN x)
! 111: {
! 112: ulong m,u;
! 113: long i,lx,ex,ly,tx=typ(x);
! 114: GEN y,p1,p2;
! 115:
! 116: switch(tx)
! 117: {
! 118: case t_INT:
! 119: lx=lgefint(x);
! 120: if (lx==2) { y=cgetg(2,t_VEC); y[1]=zero; return y; }
! 121: ly = BITS_IN_LONG+1; m=HIGHBIT; u=x[2];
! 122: while (!(m & u)) { m>>=1; ly--; }
! 123: y = cgetg(ly+((lx-3)<<TWOPOTBITS_IN_LONG),t_VEC); ly=1;
! 124: do { y[ly] = m & u ? un : zero; ly++; } while (m>>=1);
! 125: for (i=3; i<lx; i++)
! 126: {
! 127: m=HIGHBIT; u=x[i];
! 128: do { y[ly] = m & u ? un : zero; ly++; } while (m>>=1);
! 129: }
! 130: break;
! 131:
! 132: case t_REAL:
! 133: ex=expo(x);
! 134: if (!signe(x))
! 135: {
! 136: lx=1+max(-ex,0); y=cgetg(lx,t_VEC);
! 137: for (i=1; i<lx; i++) y[i]=zero;
! 138: return y;
! 139: }
! 140:
! 141: lx=lg(x); y=cgetg(3,t_VEC);
! 142: if (ex > bit_accuracy(lx)) err(talker,"loss of precision in binary");
! 143: p1 = cgetg(max(ex,0)+2,t_VEC);
! 144: p2 = cgetg(bit_accuracy(lx)-ex,t_VEC);
! 145: y[1] = (long) p1; y[2] = (long) p2;
! 146: ly = -ex; ex++;
! 147: if (ex<=0)
! 148: {
! 149: p1[1]=zero; for (i=1; i <= -ex; i++) p2[i]=zero;
! 150: i=2; m=HIGHBIT;
! 151: }
! 152: else
! 153: {
! 154: ly=1;
! 155: for (i=2; i<lx && ly<=ex; i++)
! 156: {
! 157: m=HIGHBIT; u=x[i];
! 158: do
! 159: { p1[ly] = (m & u) ? un : zero; ly++; }
! 160: while ((m>>=1) && ly<=ex);
! 161: }
! 162: ly=1;
! 163: if (m) i--; else m=HIGHBIT;
! 164: }
! 165: for (; i<lx; i++)
! 166: {
! 167: u=x[i];
! 168: do { p2[ly] = m & u ? un : zero; ly++; } while (m>>=1);
! 169: m=HIGHBIT;
! 170: }
! 171: break;
! 172:
! 173: case t_VEC: case t_COL: case t_MAT:
! 174: lx=lg(x); y=cgetg(lx,tx);
! 175: for (i=1; i<lx; i++) y[i]=(long)binaire((GEN)x[i]);
! 176: break;
! 177: default: err(typeer,"binaire"); return NULL; /* not reached */
! 178: }
! 179: return y;
! 180: }
! 181:
! 182: /* Renvoie 0 ou 1 selon que le bit numero n de x est a 0 ou 1 */
! 183: long
! 184: bittest(GEN x, long n)
! 185: {
! 186: long l;
! 187:
! 188: if (!signe(x) || n<0) return 0;
! 189: l = lgefint(x)-1-(n>>TWOPOTBITS_IN_LONG);
! 190: if (l<=1) return 0;
! 191: n = (1L << (n & (BITS_IN_LONG-1))) & x[l];
! 192: return n? 1: 0;
! 193: }
! 194:
! 195: static long
! 196: bittestg(GEN x, GEN n)
! 197: {
! 198: return bittest(x,itos(n));
! 199: }
! 200:
! 201: GEN
! 202: gbittest(GEN x, GEN n)
! 203: {
! 204: return arith_proto2(bittestg,x,n);
! 205: }
! 206:
! 207: /*********************************************************************/
! 208: /** **/
! 209: /** ORDER of INTEGERMOD x in (Z/nZ)* **/
! 210: /** **/
! 211: /*********************************************************************/
! 212:
! 213: GEN
! 214: order(GEN x)
! 215: {
! 216: long av=avma,av1,i,e;
! 217: GEN o,m,p;
! 218:
! 219: if (typ(x) != t_INTMOD || !gcmp1(mppgcd((GEN) x[1],(GEN) x[2])))
! 220: err(talker,"not an element of (Z/nZ)* in order");
! 221: o=phi((GEN) x[1]); m=decomp(o);
! 222: for (i = lg(m[1])-1; i; i--)
! 223: {
! 224: p=gcoeff(m,i,1); e=itos(gcoeff(m,i,2));
! 225: do
! 226: {
! 227: GEN o1=divii(o,p), y=powgi(x,o1);
! 228: if (!gcmp1((GEN)y[2])) break;
! 229: e--; o = o1;
! 230: }
! 231: while (e);
! 232: }
! 233: av1=avma; return gerepile(av,av1,icopy(o));
! 234: }
! 235:
! 236: /******************************************************************/
! 237: /* */
! 238: /* GENERATOR of (Z/mZ)* */
! 239: /* */
! 240: /******************************************************************/
! 241:
! 242: GEN
! 243: ggener(GEN m)
! 244: {
! 245: return garith_proto(gener,m,1);
! 246: }
! 247:
! 248: GEN
! 249: gener(GEN m)
! 250: {
! 251: long av=avma,av1,k,i,e;
! 252: GEN x,t,q,p;
! 253:
! 254: if (typ(m) != t_INT) err(arither1);
! 255: e = signe(m);
! 256: if (!e) err(talker,"zero modulus in znprimroot");
! 257: if (is_pm1(m)) { avma=av; return gmodulss(0,1); }
! 258: if (e<0) m = absi(m);
! 259:
! 260: e = mod4(m);
! 261: if (e == 0) /* m = 0 mod 4 */
! 262: {
! 263: if (cmpis(m,4)) err(generer); /* m != 4, non cyclic */
! 264: return gmodulsg(3,m);
! 265: }
! 266: if (e == 2) /* m = 0 mod 2 */
! 267: {
! 268: q=shifti(m,-1); x = (GEN) gener(q)[2];
! 269: if (!mod2(x)) x = addii(x,q);
! 270: av1=avma; return gerepile(av,av1,gmodulcp(x,m));
! 271: }
! 272:
! 273: t=decomp(m); if (lg(t[1]) != 2) err(generer);
! 274: p=gcoeff(t,1,1); e=itos(gcoeff(t,1,2)); q=subis(p,1);
! 275: if (e>=2)
! 276: {
! 277: x = (GEN) gener(p)[2];
! 278: if (gcmp1(powmodulo(x,q, sqri(p)))) x = addii(x,p);
! 279: av1=avma; return gerepile(av,av1,gmodulcp(x,m));
! 280: }
! 281:
! 282: p=(GEN)decomp(q)[1]; k=lg(p)-1; x=stoi(1);
! 283: for(;;)
! 284: {
! 285: x[2]++;
! 286: if (gcmp1(mppgcd(m,x)))
! 287: {
! 288: for (i=k; i; i--)
! 289: if (gcmp1(powmodulo(x, divii(q,(GEN)p[i]), m))) break;
! 290: if (!i) break;
! 291: }
! 292: }
! 293: av1=avma; return gerepile(av,av1,gmodulcp(x,m));
! 294: }
! 295:
! 296: GEN
! 297: znstar(GEN n)
! 298: {
! 299: GEN p1,z,q,u,v,d,list,ep,h,gen,moduli,p,a;
! 300: long i,j,nbp,sizeh,av,tetpil;
! 301:
! 302: if (typ(n) != t_INT) err(arither1);
! 303: if (!signe(n))
! 304: {
! 305: z=cgetg(4,t_VEC);
! 306: z[1]=deux; p1=cgetg(2,t_VEC);
! 307: z[2]=(long)p1; p1[1]=deux; p1=cgetg(2,t_VEC);
! 308: z[3]=(long)p1; p1[1]=lneg(gun);
! 309: return z;
! 310: }
! 311: av=avma; n=absi(n);
! 312: if (cmpis(n,2)<=0)
! 313: {
! 314: avma=av; z=cgetg(4,t_VEC);
! 315: z[1]=un;
! 316: z[2]=lgetg(1,t_VEC);
! 317: z[3]=lgetg(1,t_VEC);
! 318: return z;
! 319: }
! 320: list=factor(n); ep=(GEN)list[2]; list=(GEN)list[1]; nbp=lg(list)-1;
! 321: h = cgetg(nbp+2,t_VEC);
! 322: gen = cgetg(nbp+2,t_VEC);
! 323: moduli = cgetg(nbp+2,t_VEC);
! 324: switch(mod8(n))
! 325: {
! 326: case 0:
! 327: h[1] = lmul2n(gun,itos((GEN)ep[1])-2); h[2] = deux;
! 328: gen[1] = lstoi(5); gen[2] = laddis(gmul2n((GEN)h[1],1),-1);
! 329: moduli[1] = moduli[2] = lmul2n(gun,itos((GEN)ep[1]));
! 330: sizeh = nbp+1; i=3; j=2; break;
! 331: case 4:
! 332: h[1] = deux;
! 333: gen[1] = lstoi(3);
! 334: moduli[1] = lmul2n(gun,itos((GEN)ep[1]));
! 335: sizeh = nbp; i=j=2; break;
! 336: case 2: case 6:
! 337: sizeh = nbp-1; i=1; j=2; break;
! 338: case 1: case 3: case 5: case 7:
! 339: sizeh = nbp; i=j=1; break;
! 340: }
! 341: for ( ; j<=nbp; i++,j++)
! 342: {
! 343: p = (GEN)list[j]; q = gpuigs(p, itos((GEN)ep[j])-1);
! 344: h[i] = lmulii(addis(p,-1),q); p1 = mulii(p,q);
! 345: gen[i] = gener(p1)[2];
! 346: moduli[i] = (long)p1;
! 347: }
! 348: #if 0
! 349: if (nbp == 1 && is_pm1(ep[1]))
! 350: gen[1] = lmodulcp((GEN)gen[1],n);
! 351: else
! 352: #endif
! 353: for (i=1; i<=sizeh; i++)
! 354: {
! 355: q = (GEN)moduli[i]; a = (GEN)gen[i];
! 356: u = mpinvmod(q,divii(n,q));
! 357: gen[i] = lmodulcp(addii(a,mulii(mulii(subsi(1,a),u),q)), n);
! 358: }
! 359:
! 360: for (i=sizeh; i>=2; i--)
! 361: for (j=i-1; j>=1; j--)
! 362: if (!divise((GEN)h[j],(GEN)h[i]))
! 363: {
! 364: d=bezout((GEN)h[i],(GEN)h[j],&u,&v);
! 365: q=divii((GEN)h[j],d);
! 366: h[j]=(long)mulii((GEN)h[i],q); h[i]=(long)d;
! 367: gen[j]=ldiv((GEN)gen[j], (GEN)gen[i]);
! 368: gen[i]=lmul((GEN)gen[i], powgi((GEN)gen[j], mulii(v,q)));
! 369: }
! 370: q=gun; for (i=1; i<=sizeh && !gcmp1((GEN)h[i]); i++) q=mulii(q,(GEN)h[i]);
! 371: setlg(h,i); setlg(gen,i); z=cgetg(4,t_VEC);
! 372: z[1]=(long)q; z[2]=(long)h; z[3]=(long)gen;
! 373: tetpil=avma; return gerepile(av,tetpil,gcopy(z));
! 374: }
! 375:
! 376: /*********************************************************************/
! 377: /** **/
! 378: /** INTEGRAL SQUARE ROOT **/
! 379: /** **/
! 380: /*********************************************************************/
! 381:
! 382: GEN
! 383: gracine(GEN a)
! 384: {
! 385: return garith_proto(racine,a,1); /* hm. --GN */
! 386: }
! 387:
! 388: GEN
! 389: racine(GEN a)
! 390: {
! 391: GEN x,y,z;
! 392: long av,tetpil,k;
! 393:
! 394: if (typ(a) != t_INT) err(arither1);
! 395: switch (signe(a))
! 396: {
! 397: case 0: return gzero;
! 398: case -1:
! 399: x=cgetg(3,t_COMPLEX); x[1]=zero;
! 400: setsigne(a,1); x[2]= (long) racine(a); setsigne(a,-1);
! 401: return x;
! 402:
! 403: case 1:
! 404: av=avma; k = (long) sqrt((double)(ulong)a[2]);
! 405: x = shifti(stoi(k+1), (lgefint(a)-3)*(BITS_IN_LONG/2));
! 406: do
! 407: {
! 408: z = shifti(addii(x,divii(a,x)), -1);
! 409: y = x; x = z;
! 410: }
! 411: while (cmpii(x,y) < 0);
! 412: tetpil=avma; return gerepile(av,tetpil,icopy(y));
! 413: }
! 414: return NULL; /* not reached */
! 415: }
! 416:
! 417: /*********************************************************************/
! 418: /** **/
! 419: /** PERFECT SQUARE **/
! 420: /** **/
! 421: /*********************************************************************/
! 422:
! 423: long
! 424: carrecomplet(GEN x, GEN *pt)
! 425: {
! 426: static int carresmod64[]={
! 427: 1,1,0,0,1,0,0,0,0,1, 0,0,0,0,0,0,1,1,0,0,
! 428: 0,0,0,0,0,1,0,0,0,0, 0,0,0,1,0,0,1,0,0,0,
! 429: 0,1,0,0,0,0,0,0,0,1, 0,0,0,0,0,0,0,1,0,0,
! 430: 0,0,0,0};
! 431: static int carresmod63[]={
! 432: 1,1,0,0,1,0,0,1,0,1, 0,0,0,0,0,0,1,0,1,0,
! 433: 0,0,1,0,0,1,0,0,1,0, 0,0,0,0,0,0,1,1,0,0,
! 434: 0,0,0,1,0,0,1,0,0,1, 0,0,0,0,0,0,0,0,1,0,
! 435: 0,0,0};
! 436: static int carresmod65[]={
! 437: 1,1,0,0,1,0,0,0,0,1, 1,0,0,0,1,0,1,0,0,0,
! 438: 0,0,0,0,0,1,1,0,0,1, 1,0,0,0,0,1,1,0,0,1,
! 439: 1,0,0,0,0,0,0,0,0,1, 0,1,0,0,0,1,1,0,0,0,
! 440: 0,1,0,0,1};
! 441: static int carresmod11[]={1,1,0,1,1,1,0,0,0,1,0};
! 442:
! 443: long av;
! 444: GEN y;
! 445:
! 446: switch(signe(x))
! 447: {
! 448: case -1: return 0;
! 449: case 0: if (pt) *pt=gzero; return 1;
! 450: case 1: if (!carresmod64[mod64(x)]) return 0;
! 451: }
! 452: if (!carresmod63[smodis(x,63)]) return 0;
! 453: if (!carresmod65[smodis(x,65)]) return 0;
! 454: if (!carresmod11[smodis(x,11)]) return 0;
! 455: av=avma; y=racine(x);
! 456: if (!egalii(sqri(y),x)) { avma=av; return 0; }
! 457: if (pt) { *pt = y; avma=(long)y; } else avma=av;
! 458: return 1;
! 459: }
! 460:
! 461: static GEN
! 462: polcarrecomplet(GEN x, GEN *pt)
! 463: {
! 464: long i,l,av,av2;
! 465: GEN y,a,b;
! 466:
! 467: if (!signe(x)) return gun;
! 468: l=lgef(x); if ((l&1) == 0) return gzero; /* odd degree */
! 469: i=2; while (isexactzero((GEN)x[i])) i++;
! 470: if (i&1) return gzero;
! 471: av2 = avma; a = (GEN)x[i];
! 472: switch (typ(a))
! 473: {
! 474: case t_POL: case t_INT:
! 475: y = gcarrecomplet(a,&b); break;
! 476: default:
! 477: y = gcarreparfait(a); b = NULL; break;
! 478: }
! 479: if (y == gzero) { avma = av2; return gzero; }
! 480: av = avma; x = gdiv(x,a);
! 481: y = gtrunc(gsqrt(greffe(x,l,1),0)); av2 = avma;
! 482: if (!gegal(gsqr(y), x)) { avma=av; return gzero; }
! 483: if (pt)
! 484: {
! 485: avma = av2;
! 486: if (!gcmp1(a))
! 487: {
! 488: if (!b) b = gsqrt(a,DEFAULTPREC);
! 489: y = gmul(b,y);
! 490: }
! 491: *pt = gerepileupto(av,y);
! 492: }
! 493: else avma = av;
! 494: return gun;
! 495: }
! 496:
! 497: GEN
! 498: gcarrecomplet(GEN x, GEN *pt)
! 499: {
! 500: long tx = typ(x),l,i;
! 501: GEN z,y,p,t;
! 502:
! 503: if (!pt) return gcarreparfait(x);
! 504: if (is_matvec_t(tx))
! 505: {
! 506: l=lg(x); y=cgetg(l,tx); z=cgetg(l,tx);
! 507: for (i=1; i<l; i++)
! 508: {
! 509: t=gcarrecomplet((GEN)x[i],&p);
! 510: y[i] = (long)t;
! 511: z[i] = gcmp0(t)? zero: (long)p;
! 512: }
! 513: *pt=z; return y;
! 514: }
! 515: if (tx == t_POL) return polcarrecomplet(x,pt);
! 516: if (tx != t_INT) err(arither1);
! 517: return stoi(carrecomplet(x,pt));
! 518: }
! 519:
! 520: GEN
! 521: gcarreparfait(GEN x)
! 522: {
! 523: GEN p1,p2,p3,p4;
! 524: long tx=typ(x),l,i,av,v;
! 525:
! 526: switch(tx)
! 527: {
! 528: case t_INT:
! 529: return carreparfait(x)? gun: gzero;
! 530:
! 531: case t_REAL:
! 532: return (signe(x)>=0)? gun: gzero;
! 533:
! 534: case t_INTMOD:
! 535: if (!signe(x[2])) return gun;
! 536: av=avma; p1=factor(absi((GEN)x[1]));
! 537: p2=(GEN)p1[1]; l=lg(p2); p3=(GEN)p1[2];
! 538: for (i=1; i<l; i++)
! 539: {
! 540: v = pvaluation((GEN)x[2],(GEN)p2[i],&p4);
! 541: if (v < itos((GEN)p3[i]))
! 542: {
! 543: if (v&1) break;
! 544: if (!egalii((GEN)p2[i], gdeux))
! 545: { if (kronecker(p4,(GEN)p2[i]) == -1) break; }
! 546: else
! 547: {
! 548: v = itos((GEN)p3[i]) - v;
! 549: if ((v>=3 && mod8(p4) != 1 ) ||
! 550: (v==2 && mod4(p4) != 1)) break;
! 551: }
! 552: }
! 553: }
! 554: avma=av; return i<l? gzero: gun;
! 555:
! 556: case t_FRAC: case t_FRACN:
! 557: av=avma; l=carreparfait(mulii((GEN)x[1],(GEN)x[2]));
! 558: avma=av; return l? gun: gzero;
! 559:
! 560: case t_COMPLEX:
! 561: return gun;
! 562:
! 563: case t_PADIC:
! 564: p4=(GEN)x[4]; if (!signe(p4)) return gun;
! 565: if (valp(x)&1) return gzero;
! 566: if (cmpis((GEN)x[2],2))
! 567: return (kronecker((GEN)x[4],(GEN)x[2])== -1)? gzero: gun;
! 568:
! 569: v=precp(x); /* here p=2 */
! 570: if ((v>=3 && mod8(p4) != 1 ) ||
! 571: (v==2 && mod4(p4) != 1)) return gzero;
! 572: return gun;
! 573:
! 574: case t_POL:
! 575: return polcarrecomplet(x,NULL);
! 576:
! 577: case t_SER:
! 578: if (!signe(x)) return gun;
! 579: if (valp(x)&1) return gzero;
! 580: return gcarreparfait((GEN)x[2]);
! 581:
! 582: case t_RFRAC: case t_RFRACN:
! 583: av=avma;
! 584: l=itos(gcarreparfait(gmul((GEN)x[1],(GEN)x[2])));
! 585: avma=av; return stoi(l);
! 586:
! 587: case t_QFR: case t_QFI:
! 588: return gcarreparfait((GEN)x[1]);
! 589:
! 590: case t_VEC: case t_COL: case t_MAT:
! 591: l=lg(x); p1=cgetg(l,tx);
! 592: for (i=1; i<l; i++) p1[i]=(long)gcarreparfait((GEN)x[i]);
! 593: return p1;
! 594: }
! 595: err(impl,"issquare for this type");
! 596: return NULL; /* not reached */
! 597: }
! 598:
! 599: /*********************************************************************/
! 600: /** **/
! 601: /** KRONECKER SYMBOL **/
! 602: /** **/
! 603: /*********************************************************************/
! 604: #define ome(t) (labs(mod8(t)-4) == 1)
! 605:
! 606: GEN
! 607: gkronecker(GEN x, GEN y)
! 608: {
! 609: return arith_proto2(kronecker,x,y);
! 610: }
! 611:
! 612: long
! 613: kronecker(GEN x, GEN y)
! 614: {
! 615: GEN z;
! 616: long av,r,s=1;
! 617:
! 618: av=avma;
! 619: switch (signe(y))
! 620: {
! 621: case -1: y=negi(y); if (signe(x)<0) s= -1; break;
! 622: case 0: return is_pm1(x);
! 623: }
! 624: r=vali(y);
! 625: if (r)
! 626: {
! 627: if (mpodd(x))
! 628: {
! 629: if (odd(r) && ome(x)) s= -s;
! 630: y=shifti(y,-r);
! 631: }
! 632: else { avma=av; return 0; }
! 633: }
! 634: x=modii(x,y);
! 635: while (signe(x))
! 636: {
! 637: r=vali(x);
! 638: if (r)
! 639: {
! 640: if (odd(r) && ome(y)) s= -s;
! 641: x=shifti(x,-r);
! 642: }
! 643: /* x=3 mod 4 && y=3 mod 4 ? (both are odd here) */
! 644: if (y[lgefint(y)-1]&2 && x[lgefint(x)-1]&2) s = -s;
! 645: z=resii(y,x); y=x; x=z;
! 646: }
! 647: avma=av; return is_pm1(y)? s: 0;
! 648: }
! 649:
! 650: GEN
! 651: gkrogs(GEN x, long y)
! 652: {
! 653: return arith_proto2gs(krogs,x,y);
! 654: }
! 655:
! 656: long
! 657: krogs(GEN x, long y)
! 658: {
! 659: long av,r,s=1,x1,z;
! 660:
! 661: av=avma;
! 662: if (y<=0)
! 663: {
! 664: if (y) { y = -y; if (signe(x)<0) s = -1; }
! 665: else return is_pm1(x);
! 666: }
! 667: r=vals(y);
! 668: if (r)
! 669: {
! 670: if (mpodd(x))
! 671: {
! 672: if (odd(r) && ome(x)) s= -s;
! 673: y>>=r;
! 674: }
! 675: else return 0;
! 676: }
! 677: x1=smodis(x,y);
! 678: while (x1)
! 679: {
! 680: r=vals(x1);
! 681: if (r)
! 682: {
! 683: if (odd(r) && (labs((y&7)-4)==1)) s= -s;
! 684: x1>>=r;
! 685: }
! 686: if (y&2 && x1&2) s= -s;
! 687: z=y%x1; y=x1; x1=z;
! 688: }
! 689: avma=av; return (y==1)? s: 0;
! 690: }
! 691:
! 692: long
! 693: krosg(long s, GEN x)
! 694: {
! 695: long av = avma, y = kronecker(stoi(s),x);
! 696: avma = av; return y;
! 697: }
! 698:
! 699: long
! 700: kross(long x, long y)
! 701: {
! 702: long r,s=1,x1,z;
! 703:
! 704: if (y<=0)
! 705: {
! 706: if (y) { y= -y; if (x<0) s = -1; }
! 707: else return (labs(x)==1);
! 708: }
! 709: r=vals(y);
! 710: if (r)
! 711: {
! 712: if (odd(x))
! 713: {
! 714: if (odd(r) && labs((x&7)-4) == 1) s = -s;
! 715: y>>=r;
! 716: }
! 717: else return 0;
! 718: }
! 719: x1=x%y; if (x1<0) x1+=y;
! 720: while (x1)
! 721: {
! 722: r=vals(x1);
! 723: if (r)
! 724: {
! 725: if (odd(r) && labs((y&7)-4) == 1) s= -s;
! 726: x1>>=r;
! 727: }
! 728: if (y&2 && x1&2) s= -s;
! 729: z=y%x1; y=x1; x1=z;
! 730: }
! 731: return (y==1)? s: 0;
! 732: }
! 733:
! 734: long
! 735: hil0(GEN x, GEN y, GEN p)
! 736: {
! 737: return p? hil(x,y,p): hil(x,y,gzero);
! 738: }
! 739:
! 740: #define eps(t) (((signe(t)*(t[lgefint(t)-1]))&3)==3)
! 741: long
! 742: hil(GEN x, GEN y, GEN p)
! 743: {
! 744: long a,b,av,tx,ty,z;
! 745: GEN p1,p2,u,v;
! 746:
! 747: if (gcmp0(x) || gcmp0(y)) return 0;
! 748: av=avma; tx=typ(x); ty=typ(y);
! 749: if (tx>ty) { p1=x; x=y; y=p1; a=tx,tx=ty; ty=a; }
! 750: switch(tx)
! 751: {
! 752: case t_INT:
! 753: switch(ty)
! 754: {
! 755: case t_INT:
! 756: if (signe(p)<=0)
! 757: return (signe(x)<0 && signe(y)<0)? -1: 1;
! 758: a = odd(pvaluation(x,p,&u));
! 759: b = odd(pvaluation(y,p,&v));
! 760: if (egalii(p,gdeux))
! 761: {
! 762: z = (eps(u) && eps(v))? -1: 1;
! 763: if (a && ome(v)) z= -z;
! 764: if (b && ome(u)) z= -z;
! 765: }
! 766: else
! 767: {
! 768: z = (a && b && eps(p))? -1: 1;
! 769: if (a && kronecker(v,p)<0) z= -z;
! 770: if (b && kronecker(u,p)<0) z= -z;
! 771: }
! 772: avma=av; return z;
! 773: case t_REAL:
! 774: return (signe(x)<0 && signe(y)<0)? -1: 1;
! 775: case t_INTMOD:
! 776: if (egalii(gdeux,(GEN)y[1])) err(hiler1);
! 777: return hil(x,(GEN)y[2],(GEN)y[1]);
! 778: case t_FRAC: case t_FRACN:
! 779: p1=mulii((GEN)y[1],(GEN)y[2]); z=hil(x,p1,p);
! 780: avma=av; return z;
! 781: case t_PADIC:
! 782: if (egalii(gdeux,(GEN)y[2]) && precp(y) <= 2) err(hiler1);
! 783: p1 = odd(valp(y))? mulii((GEN)y[2],(GEN)y[4]): (GEN)y[4];
! 784: z=hil(x,p1,(GEN)y[2]); avma=av; return z;
! 785: }
! 786: break;
! 787:
! 788: case t_REAL:
! 789: if (! is_frac_t(ty)) break;
! 790: if (signe(x) > 0) return 1;
! 791: return signe(y[1])*signe(y[2]);
! 792:
! 793: case t_INTMOD:
! 794: if (egalii(gdeux,(GEN)y[1])) err(hiler1);
! 795: switch(ty)
! 796: {
! 797: case t_INTMOD:
! 798: if (!egalii((GEN)x[1],(GEN)y[1])) break;
! 799: return hil((GEN)x[2],(GEN)y[2],(GEN)x[1]);
! 800: case t_FRAC: case t_FRACN:
! 801: return hil((GEN)x[2],y,(GEN)x[1]);
! 802: case t_PADIC:
! 803: if (!egalii((GEN)x[1],(GEN)y[2])) break;
! 804: return hil((GEN)x[2],y,(GEN)x[1]);
! 805: }
! 806: break;
! 807:
! 808: case t_FRAC: case t_FRACN:
! 809: p1=mulii((GEN)x[1],(GEN)x[2]);
! 810: switch(ty)
! 811: {
! 812: case t_FRAC: case t_FRACN:
! 813: p2=mulii((GEN)y[1],(GEN)y[2]);
! 814: z=hil(p1,p2,p); avma=av; return z;
! 815: case t_PADIC:
! 816: z=hil(p1,y,NULL); avma=av; return z;
! 817: }
! 818: break;
! 819:
! 820: case t_PADIC:
! 821: if (ty != t_PADIC || !egalii((GEN)x[2],(GEN)y[2])) break;
! 822: p1 = odd(valp(x))? mulii((GEN)x[2],(GEN)x[4]): (GEN)x[4];
! 823: p2 = odd(valp(y))? mulii((GEN)y[2],(GEN)y[4]): (GEN)y[4];
! 824: z=hil(p1,p2,(GEN)x[2]); avma=av; return z;
! 825: }
! 826: err(talker,"forbidden or incompatible types in hil");
! 827: return 0; /* not reached */
! 828: }
! 829: #undef eps
! 830: #undef ome
! 831:
! 832: /*******************************************************************/
! 833: /* */
! 834: /* SQUARE ROOT MODULO p */
! 835: /* */
! 836: /*******************************************************************/
! 837:
! 838: #define sqrmod(x,p) (resii(sqri(x),p))
! 839:
! 840: /* Assume p is prime. return NULL if (a,p) = -1 */
! 841: GEN
! 842: mpsqrtmod(GEN a, GEN p)
! 843: {
! 844: long av = avma, av1,tetpil,lim,i,k,e;
! 845: GEN p1,p2,v,y,w,m1,m;
! 846:
! 847: if (typ(a) != t_INT || typ(p) != t_INT) err(arither1);
! 848: p1=addsi(-1,p); e=vali(p1);
! 849: if (e == 0) /* p = 2 */
! 850: {
! 851: avma = av;
! 852: if (!signe(a) || !mod2(a)) return gzero;
! 853: return gun;
! 854: }
! 855: p2=shifti(p1,-e);
! 856: if (e == 1) y = p1;
! 857: else
! 858: for (k=2; ; k++)
! 859: {
! 860: av1 = avma;
! 861: m1 = m = powmodulo(stoi(k),p2,p);
! 862: for (i=1; i<e; i++)
! 863: if (gcmp1(m=sqrmod(m,p))) break;
! 864: if (i==e) { y = m1; break; }
! 865: avma = av1;
! 866: }
! 867: /* y contient un generateur de (Z/pZ)* eleve a la puis (p-1)/2^e */
! 868:
! 869: p1=shifti(p2,-1); p1=powmodulo(a,p1,p);
! 870: if (!signe(p1)) { avma=av; return gzero; }
! 871:
! 872: p2=mulii(p1,a); v = modii(p2,p);
! 873: p1=mulii(sqri(p1),a); w = modii(p1,p);
! 874: lim = stack_lim(av,1);
! 875: while (!gcmp1(w))
! 876: {
! 877: /* if p is not prime, next loop will not end */
! 878: p1=sqrmod(w,p); for (k=1; !gcmp1(p1); k++) p1 = sqrmod(p1,p);
! 879: if (k==e) { avma=av; return NULL; }
! 880: p1=y; for (i=1; i<e-k; i++) p1=sqrmod(p1,p);
! 881: e = k; v = modii(mulii(p1,v),p);
! 882: y = sqrmod(p1,p); w = modii(mulii(y,w),p);
! 883: if (low_stack(lim, stack_lim(av,1)))
! 884: {
! 885: GEN *gptr[3];
! 886: if(DEBUGMEM>1) err(warnmem,"mpsqrtmod");
! 887: gptr[0]=&y; gptr[1]=&v; gptr[2]=&w;
! 888: gerepilemany(av,gptr,3);
! 889: }
! 890: }
! 891: p1=subii(p,v); if (cmpii(v,p1)>0) v = p1;
! 892: tetpil=avma; return gerepile(av,tetpil,icopy(v));
! 893: }
! 894:
! 895: /*********************************************************************/
! 896: /** **/
! 897: /** GCD & BEZOUT **/
! 898: /** **/
! 899: /*********************************************************************/
! 900:
! 901: /* Ultra-fast private ulong gcd for trial divisions. Called with y odd;
! 902: x can be arbitrary (but will most of the time be smaller than y).
! 903: Will also be used from inside ifactor2.c, so it's `semi-private' really.
! 904: --GN */
! 905:
! 906: /* Gotos are Harmful, and Programming is a Science. E.W.Dijkstra. */
! 907: ulong
! 908: ugcd(ulong x, ulong y) /* assume y&1==1, y > 1 */
! 909: {
! 910: if (!x) return y;
! 911: /* fix up x */
! 912: while (!(x&1)) x>>=1;
! 913: if (x==1) return 1;
! 914: if (x==y) return y;
! 915: else if (x>y) goto xislarger;/* will be rare, given how we'll use this */
! 916: /* loop invariants: x,y odd and distinct. */
! 917: yislarger:
! 918: if ((x^y)&2) /* ...01, ...11 or vice versa */
! 919: y=(x>>2)+(y>>2)+1; /* ==(x+y)>>2 except it can't overflow */
! 920: else /* ...01,...01 or ...11,...11 */
! 921: y=(y-x)>>2; /* now y!=0 in either case */
! 922: while (!(y&1)) y>>=1; /* kill any windfall-gained powers of 2 */
! 923: if (y==1) return 1; /* comparand == return value... */
! 924: if (x==y) return y; /* this and the next is just one comparison */
! 925: else if (x<y) goto yislarger;/* else fall through to xislarger */
! 926:
! 927: xislarger: /* same as above, seen through a mirror */
! 928: if ((x^y)&2)
! 929: x=(x>>2)+(y>>2)+1;
! 930: else
! 931: x=(x-y)>>2; /* x!=0 */
! 932: while (!(x&1)) x>>=1;
! 933: if (x==1) return 1;
! 934: if (x==y) return y;
! 935: else if (x>y) goto xislarger;/* again, a decent [g]cc should notice that
! 936: it can re-use the comparison */
! 937: goto yislarger;
! 938: }
! 939: /* Gotos are useful, and Programming is an Art. D.E.Knuth. */
! 940: /* PS: Of course written with Dijkstra's lessons firmly in mind... --GN */
! 941:
! 942: /* modified right shift binary algorithm with at most one division */
! 943: long
! 944: cgcd(long a,long b)
! 945: {
! 946: long v;
! 947: a=labs(a); if (!b) return a;
! 948: b=labs(b); if (!a) return b;
! 949: if (a>b) { a %= b; if (!a) return b; }
! 950: else { b %= a; if (!b) return a; }
! 951: v=vals(a|b); a>>=v; b>>=v;
! 952: if (a==1 || b==1) return 1L<<v;
! 953: if (b&1)
! 954: return ((long)ugcd((ulong)a, (ulong)b)) << v;
! 955: else
! 956: return ((long)ugcd((ulong)b, (ulong)a)) << v;
! 957: }
! 958:
! 959: /* assume a>b>0, return gcd(a,b) as a GEN (for mppgcd) */
! 960: static GEN
! 961: mppgcd_cgcd(ulong a, ulong b)
! 962: {
! 963: GEN r = cgeti(3);
! 964: long v;
! 965:
! 966: r[1] = evalsigne(1)|evallgefint(3);
! 967: a %= b; if (!a) { r[2]=(long)b; return r; }
! 968: v=vals(a|b); a>>=v; b>>=v;
! 969: if (a==1 || b==1) { r[2]=(long)(1UL<<v); return r; }
! 970: if (b&1)
! 971: r[2] = (long)(ugcd((ulong)a, (ulong)b) << v);
! 972: else
! 973: r[2] = (long)(ugcd((ulong)b, (ulong)a) << v);
! 974: return r;
! 975: }
! 976:
! 977: void mppgcd_plus_minus(GEN x, GEN y, GEN t);
! 978: ulong mppgcd_resiu(GEN y, ulong x);
! 979:
! 980: /* uses modified right-shift binary algorithm now --GN 1998Jul23 */
! 981: GEN
! 982: mppgcd(GEN a, GEN b)
! 983: {
! 984: long av,v,w;
! 985: GEN t, p1;
! 986:
! 987: if (typ(a) != t_INT || typ(b) != t_INT) err(arither1);
! 988: switch (absi_cmp(a,b))
! 989: {
! 990: case 0: return absi(a);
! 991: case -1: t=b; b=a; a=t;
! 992: }
! 993: if (!signe(b)) return absi(a);
! 994: /* here |a|>|b|>0. Try single precision first */
! 995: if (lgefint(a)==3)
! 996: return mppgcd_cgcd((ulong)a[2], (ulong)b[2]);
! 997: if (lgefint(b)==3)
! 998: {
! 999: ulong u = mppgcd_resiu(a,(ulong)b[2]);
! 1000: if (!u) return absi(b);
! 1001: return mppgcd_cgcd((ulong)b[2], u);
! 1002: }
! 1003:
! 1004: /* larger than gcd: "avma=av" gerepile (erasing t) is valid */
! 1005: av = avma; new_chunk(lgefint(b));
! 1006: t = resii(a,b);
! 1007: if (!signe(t)) { avma=av; return absi(b); }
! 1008:
! 1009: a = b; b = t;
! 1010: v = vali(a); a = shifti(a,-v); setsigne(a,1);
! 1011: w = vali(b); b = shifti(b,-w); setsigne(b,1);
! 1012: if (w < v) v = w;
! 1013: switch(absi_cmp(a,b))
! 1014: {
! 1015: case 0: avma=av; a=shifti(a,v); return a;
! 1016: case -1: p1=b; b=a; a=p1;
! 1017: }
! 1018: if (is_pm1(b)) { avma=av; return shifti(gun,v); }
! 1019:
! 1020: /* we have three consecutive memory locations: a,b,t.
! 1021: * All computations are done in place */
! 1022:
! 1023: /* a and b are odd now, and a>b>1 */
! 1024: while (lgefint(a) > 3)
! 1025: {
! 1026: /* if a=b mod 4 set t=a-b, otherwise t=a+b, then strip powers of 2 */
! 1027: /* so that t <= (a+b)/4 < a/2 */
! 1028: mppgcd_plus_minus(a,b, t);
! 1029: if (is_pm1(t)) { avma=av; return shifti(gun,v); }
! 1030: switch(absi_cmp(t,b))
! 1031: {
! 1032: case -1: p1 = a; a = b; b = t; t = p1; break;
! 1033: case 1: p1 = a; a = t; t = p1; break;
! 1034: case 0: avma = av; b=shifti(b,v); return b;
! 1035: }
! 1036: }
! 1037: {
! 1038: long r[] = {evaltyp(t_INT)|m_evallg(3), evalsigne(1)|evallgefint(3), 0};
! 1039: r[2] = (long) ugcd((ulong)b[2], (ulong)a[2]);
! 1040: avma = av; return shifti(r,v);
! 1041: }
! 1042: }
! 1043:
! 1044: /* Extended bezout. Return d=pgcd(a,b) and &u,&v */
! 1045: long
! 1046: cbezout(long a,long b,long *uu,long *vv)
! 1047: {
! 1048: long av=avma,v,q,u,t,s, d = labs(a), r = labs(b);
! 1049: GEN p1;
! 1050:
! 1051: if (!b)
! 1052: {
! 1053: *vv=0;
! 1054: if (!a) { *uu=1; return 1; }
! 1055: if (a<0)
! 1056: { *uu=-1; return -a; }
! 1057: else
! 1058: { *uu= 1; return a; }
! 1059: }
! 1060: u=1; t=0;
! 1061: for(;;)
! 1062: {
! 1063: if (!r)
! 1064: {
! 1065: if (a<0) u = -u;
! 1066: p1 = mulss(a,u); s = signe(p1);
! 1067: if (!s) v = d / b;
! 1068: else if (!is_bigint(p1))
! 1069: {
! 1070: ulong ul;
! 1071: long sb = (b<0);
! 1072: b = labs(b);
! 1073: if (s < 0)
! 1074: {
! 1075: ul = (p1[2]+d);
! 1076: ul /= b; v = sb? -(long)ul: (long)ul;
! 1077: }
! 1078: else
! 1079: {
! 1080: ul = p1[2]-d;
! 1081: ul /= b; v = sb? (long)ul: -(long)ul;
! 1082: }
! 1083: }
! 1084: else v = - itos(divis(addsi(-d,p1), b));
! 1085: avma=av; *uu = u; *vv = v; return d;
! 1086: }
! 1087: v=d; d=r; q = v/r; r = v - q*r;
! 1088: v=t; t = u - q*t; u=v;
! 1089: }
! 1090: }
! 1091:
! 1092: GEN
! 1093: bezout(GEN a, GEN b, GEN *ptu, GEN *ptv)
! 1094: {
! 1095: GEN u,v,v1,d,d1,q,r, *tmp;
! 1096: long av;
! 1097:
! 1098: if (typ(a) != t_INT || typ(b) != t_INT) err(arither1);
! 1099: if (absi_cmp(a,b) < 0)
! 1100: {
! 1101: u=b; b=a; a=u;
! 1102: tmp=ptu; ptu=ptv; ptv=tmp;
! 1103: }
! 1104: /* now |a| >= |b| */
! 1105: if (!signe(b))
! 1106: {
! 1107: *ptv = gzero;
! 1108: switch(signe(a))
! 1109: {
! 1110: case 0: *ptu = gun; return gzero;
! 1111: case 1: *ptu = gun; return icopy(a);
! 1112: case -1: *ptu = negi(gun); return negi(a);
! 1113: }
! 1114: }
! 1115: if (!is_bigint(a))
! 1116: {
! 1117: long uu,vv, dd = cbezout(itos(a),itos(b),&uu,&vv);
! 1118: *ptu = stoi(uu); *ptv = stoi(vv); return stoi(dd);
! 1119: }
! 1120: av = avma;
! 1121: (void)new_chunk(lgefint(b) + (lgefint(a)<<1)); /* room for d, u and v */
! 1122: d = a; d1 = b; v = gzero; v1 = gun;
! 1123: for(;;)
! 1124: {
! 1125: q=dvmdii(d,d1,&r);
! 1126: v=subii(v,mulii(q,v1));
! 1127: u=v; v=v1; v1=u;
! 1128: u=r; d=d1; d1=u; if (!signe(d1)) break;
! 1129: }
! 1130: u = divii(subii(d,mulii(b,v)),a);
! 1131: avma = av; d = icopy(d); v = icopy(v); u = icopy(u);
! 1132: if (signe(d) < 0)
! 1133: {
! 1134: setsigne(d,1);
! 1135: setsigne(u,-signe(u));
! 1136: setsigne(v,-signe(v));
! 1137: }
! 1138: *ptu = u; *ptv = v; return d;
! 1139: }
! 1140:
! 1141: /*********************************************************************/
! 1142: /** **/
! 1143: /** CHINESE REMAINDERS **/
! 1144: /** **/
! 1145: /*********************************************************************/
! 1146:
! 1147: /* P.M. & M.H.
! 1148: *
! 1149: * Chinese Remainder Theorem. x and y must have the same type (integermod,
! 1150: * polymod, or polynomial/vector/matrix recursively constructed with these
! 1151: * as coefficients). Creates (with the same type) a z in the same residue
! 1152: * class as x and the same residue class as y, if it is possible.
! 1153: *
! 1154: * We also allow (during recursion) two identical objects even if they are
! 1155: * not integermod or polymod. For example, if
! 1156: *
! 1157: * x = [1. mod(5, 11), mod(X + mod(2, 7), X^2 + 1)]
! 1158: * y = [1, mod(7, 17), mod(X + mod(0, 3), X^2 + 1)],
! 1159: *
! 1160: * then chinois(x, y) returns
! 1161: *
! 1162: * [1, mod(16, 187), mod(X + mod(9, 21), X^2 + 1)]
! 1163: *
! 1164: * Someone else may want to allow power series, complex numbers, and
! 1165: * quadratic numbers.
! 1166: */
! 1167: GEN
! 1168: chinois(GEN x, GEN y)
! 1169: {
! 1170: long i,lx,vx,av,tetpil, tx = typ(x);
! 1171: GEN z,p1,p2,d,u,v;
! 1172:
! 1173: if (gegal(x,y)) return gcopy(x);
! 1174: if (tx == typ(y)) switch(tx)
! 1175: {
! 1176: case t_POLMOD:
! 1177: if (gegal((GEN)x[1],(GEN)y[1])) /* same modulus */
! 1178: {
! 1179: z=cgetg(3,tx);
! 1180: z[1]=lcopy((GEN)x[1]);
! 1181: z[2]=(long)chinois((GEN)x[2],(GEN)y[2]);
! 1182: return z;
! 1183: } /* fall through */
! 1184: case t_INTMOD:
! 1185: z=cgetg(3,tx); av=avma;
! 1186: d=gbezout((GEN)x[1],(GEN)y[1],&u,&v);
! 1187: if (!gegal(gmod((GEN)x[2],d), gmod((GEN)y[2],d))) break;
! 1188: p1 = gdiv((GEN)x[1],d);
! 1189: p2 = gadd((GEN)x[2], gmul(gmul(u,p1), gadd((GEN)y[2],gneg((GEN)x[2]))));
! 1190:
! 1191: tetpil=avma; z[1]=lmul(p1,(GEN)y[1]); z[2]=lmod(p2,(GEN)z[1]);
! 1192: gerepilemanyvec(av,tetpil,z+1,2); return z;
! 1193:
! 1194: case t_POL:
! 1195: lx=lgef(x); vx=varn(x); z=cgetg(lx,tx);
! 1196: if (lx!=lgef(y) || vx!=varn(y)) break;
! 1197: z[1]=evalsigne(1)|evallgef(lx)|evalvarn(vx);
! 1198: for (i=2; i<lx; i++) z[i]=(long)chinois((GEN)x[i],(GEN)y[i]);
! 1199: return z;
! 1200:
! 1201: case t_VEC: case t_COL: case t_MAT:
! 1202: lx=lg(x); z=cgetg(lx,tx); if (lx!=lg(y)) break;
! 1203: for (i=1; i<lx; i++) z[i]=(long)chinois((GEN)x[i],(GEN)y[i]);
! 1204: return z;
! 1205: }
! 1206: err(talker,"incompatible arguments in chinois");
! 1207: return NULL; /* not reached */
! 1208: }
! 1209:
! 1210: /* return lift(chinois(x2 mod x1, y2 mod y1))
! 1211: * assume(x1,y1)=1, xi,yi integers and z1 = x1*y1
! 1212: */
! 1213: GEN
! 1214: chinois_int_coprime(GEN x2, GEN y2, GEN x1, GEN y1, GEN z1)
! 1215: {
! 1216: long av = avma;
! 1217: GEN ax,p1;
! 1218: (void)new_chunk((lgefint(z1)<<1)+lgefint(x1)+lgefint(y1));
! 1219: ax = mulii(mpinvmod(x1,y1), x1);
! 1220: p1 = addii(x2, mulii(ax, subii(y2,x2)));
! 1221: avma = av; return modii(p1,z1);
! 1222: }
! 1223:
! 1224: /*********************************************************************/
! 1225: /** **/
! 1226: /** INVERSE MODULO b **/
! 1227: /** **/
! 1228: /*********************************************************************/
! 1229:
! 1230: GEN
! 1231: mpinvmod(GEN a, GEN m)
! 1232: {
! 1233: GEN res;
! 1234: if (invmod(a,m,&res)) return res;
! 1235: err(talker,"impossible inverse modulo: %Z",gmodulcp(res,m));
! 1236: return NULL; /* not reached */
! 1237: }
! 1238:
! 1239: /*********************************************************************/
! 1240: /** **/
! 1241: /** POWERING MODULO (a^n mod m) **/
! 1242: /** **/
! 1243: /*********************************************************************/
! 1244:
! 1245: GEN
! 1246: powmodulo(GEN a, GEN n, GEN m)
! 1247: {
! 1248: GEN y;
! 1249: long av = avma,av1,lim,*p,man,k,nb;
! 1250: GEN (*mul)(GEN,GEN) = mulii;
! 1251:
! 1252: if (typ(a) != t_INT || typ(n) != t_INT || typ(m) != t_INT) err(arither1);
! 1253: switch (signe(n))
! 1254: {
! 1255: case 0:
! 1256: k = signe(resii(a,m)); avma=av;
! 1257: return k? gun: gzero;
! 1258:
! 1259: case -1:
! 1260: a = mpinvmod(a,m); n = absi(n); /* fall through */
! 1261: case 1:
! 1262: y = modii(a,m);
! 1263: if (!signe(y)) { avma=av; return gzero; }
! 1264: if (lgefint(y)==3)
! 1265: switch(y[2])
! 1266: {
! 1267: case 1: /* y = 1 */
! 1268: avma=av; return gun;
! 1269: case 2: /* y = 2, use shifti not mulii */
! 1270: mul = (GEN (*)(GEN,GEN))shifti; a = (GEN)1;
! 1271: }
! 1272: p = n+2; man = *p; /* see puissii */
! 1273: k = 1+bfffo(man); man<<=k; k = BITS_IN_LONG-k;
! 1274: av1=avma; lim=stack_lim(av1,1);
! 1275: for (nb=lgefint(n)-2;;)
! 1276: {
! 1277: for (; k; man<<=1,k--)
! 1278: {
! 1279: y=resii(sqri(y), m);
! 1280: if (man<0) y = modii(mul(y,a), m);
! 1281: if (low_stack(lim, stack_lim(av1,1)))
! 1282: {
! 1283: if (DEBUGMEM>1) err(warnmem,"powmodulo");
! 1284: y = gerepileupto(av1,y);
! 1285: }
! 1286: }
! 1287: if (--nb == 0) break;
! 1288: man = *++p, k = BITS_IN_LONG;
! 1289: }
! 1290: }
! 1291: return gerepileupto(av,y);
! 1292: }
! 1293:
! 1294: /*********************************************************************/
! 1295: /** **/
! 1296: /** NEXT / PRECEDING (PSEUDO) PRIME **/
! 1297: /** **/
! 1298: /*********************************************************************/
! 1299: GEN
! 1300: gnextprime(GEN n)
! 1301: {
! 1302: return garith_proto(nextprime,n,0); /* accept non-integers */
! 1303: }
! 1304:
! 1305: GEN
! 1306: gprecprime(GEN n)
! 1307: {
! 1308: return garith_proto(precprime,n,0); /* accept non-integers */
! 1309: }
! 1310:
! 1311: GEN
! 1312: gisprime(GEN x)
! 1313: {
! 1314: return arith_proto(isprime,x,1);
! 1315: }
! 1316:
! 1317: long
! 1318: isprime(GEN x)
! 1319: {
! 1320: return millerrabin(x,10);
! 1321: }
! 1322:
! 1323: GEN
! 1324: gispsp(GEN x)
! 1325: {
! 1326: return arith_proto(ispsp,x,1);
! 1327: }
! 1328:
! 1329: long
! 1330: ispsp(GEN x)
! 1331: {
! 1332: return millerrabin(x,1);
! 1333: }
! 1334:
! 1335: GEN
! 1336: gmillerrabin(GEN n, long k)
! 1337: {
! 1338: return arith_proto2gs(millerrabin,n,k);
! 1339: }
! 1340:
! 1341: /*********************************************************************/
! 1342: /** **/
! 1343: /** FUNDAMENTAL DISCRIMINANTS **/
! 1344: /** **/
! 1345: /*********************************************************************/
! 1346:
! 1347: /* gissquarefree, issquarefree moved into arith2.c with the other
! 1348: basic arithmetic functions (issquarefree is the square of the
! 1349: Moebius mu function, after all...) --GN */
! 1350:
! 1351: GEN
! 1352: gisfundamental(GEN x)
! 1353: {
! 1354: return arith_proto(isfundamental,x,1);
! 1355: }
! 1356:
! 1357: long
! 1358: isfundamental(GEN x)
! 1359: {
! 1360: long av,r;
! 1361: GEN p1;
! 1362:
! 1363: if (gcmp0(x)) return 0;
! 1364: r=mod4(x);
! 1365: if (!r)
! 1366: {
! 1367: av=avma; p1=shifti(x,-2);
! 1368: r=mod4(p1); if (!r) return 0;
! 1369: if (signe(x)<0) r=4-r;
! 1370: r = (r==1)? 0: issquarefree(p1);
! 1371: avma=av; return r;
! 1372: }
! 1373: if (signe(x)<0) r=4-r;
! 1374: return (r==1) ? issquarefree(x) : 0;
! 1375: }
! 1376:
! 1377: GEN
! 1378: quaddisc(GEN x)
! 1379: {
! 1380: long av=avma,tetpil=avma,i,r,tx=typ(x);
! 1381: GEN p1,p2,f,s;
! 1382:
! 1383: if (tx != t_INT && ! is_frac_t(tx)) err(arither1);
! 1384: f=factor(x); p1=(GEN)f[1]; p2=(GEN)f[2];
! 1385: s=gun;
! 1386: for (i=1; i<lg(p1); i++)
! 1387: if ( odd(mael(p2,i,2)) ) { tetpil=avma; s=gmul(s,(GEN)p1[i]); }
! 1388: r=mod4(s); if (gsigne(x)<0) r=4-r;
! 1389: if (r>1) { tetpil=avma; s=shifti(s,2); }
! 1390: return gerepile(av,tetpil,s);
! 1391: }
! 1392:
! 1393: /*********************************************************************/
! 1394: /** **/
! 1395: /** FACTORIAL **/
! 1396: /** **/
! 1397: /*********************************************************************/
! 1398:
! 1399: GEN
! 1400: mpfact(long n)
! 1401: {
! 1402: long av,tetpil,lim,k;
! 1403: GEN f;
! 1404:
! 1405: if (n<2)
! 1406: {
! 1407: if (n<0) err(facter);
! 1408: return gun;
! 1409: }
! 1410: av = avma; lim = stack_lim(av,1); f = gun;
! 1411: for (k=2; k<n; k++)
! 1412: if (low_stack(lim, stack_lim(av,1)))
! 1413: {
! 1414: if(DEBUGMEM>1) err(warnmem,"mpfact k=%ld",k);
! 1415: tetpil = avma; f = gerepile(av,tetpil,mulsi(k,f));
! 1416: }
! 1417: else f = mulsi(k,f);
! 1418: tetpil = avma; return gerepile(av,tetpil,mulsi(k,f));
! 1419: }
! 1420:
! 1421: GEN
! 1422: mpfactr(long n, long prec)
! 1423: {
! 1424: long av,tetpil,lim,k;
! 1425: GEN f = realun(prec);
! 1426:
! 1427: if (n<2)
! 1428: {
! 1429: if (n<0) err(facter);
! 1430: return f;
! 1431: }
! 1432: av = avma; lim = stack_lim(av,1);
! 1433: for (k=2; k<n; k++)
! 1434: if (low_stack(lim, stack_lim(av,1)))
! 1435: {
! 1436: if(DEBUGMEM>1) err(warnmem,"mpfactr k=%ld",k);
! 1437: tetpil = avma; f = gerepile(av,tetpil,mulsr(k,f));
! 1438: }
! 1439: else f = mulsr(k,f);
! 1440: tetpil = avma; return gerepile(av,tetpil,mulsr(k,f));
! 1441: }
! 1442:
! 1443: /*******************************************************************/
! 1444: /** **/
! 1445: /** LUCAS & FIBONACCI **/
! 1446: /** **/
! 1447: /*******************************************************************/
! 1448:
! 1449: void
! 1450: lucas(long n, GEN *ln, GEN *ln1)
! 1451: {
! 1452: long taille,av;
! 1453: GEN z,t;
! 1454:
! 1455: if (!n) { *ln=stoi(2); *ln1=stoi(1); return; }
! 1456:
! 1457: taille=(long)(pariC3*(1+labs(n))+3);
! 1458: *ln=cgeti(taille); *ln1=cgeti(taille);
! 1459: av=avma; lucas(n/2,&z,&t);
! 1460: switch(n % 4)
! 1461: {
! 1462: case -3:
! 1463: addsiz(2,sqri(z),*ln1);
! 1464: subiiz(addsi(1,mulii(z,t)),*ln1,*ln); break;
! 1465: case -2:
! 1466: addsiz(2,sqri(z),*ln); addsiz(1,mulii(z,t),*ln1); break;
! 1467: case -1:
! 1468: subisz(sqri(z),2,*ln1);
! 1469: subiiz(subis(mulii(z,t),1),*ln1,*ln); break;
! 1470: case 0: subisz(sqri(z),2,*ln); subisz(mulii(z,t),1,*ln1); break;
! 1471: case 1: subisz(mulii(z,t),1,*ln); addsiz(2,sqri(t),*ln1); break;
! 1472: case 2: addsiz(2,sqri(z),*ln); addsiz(1,mulii(z,t),*ln1); break;
! 1473: case 3: addsiz(1,mulii(z,t),*ln); subisz(sqri(t),2,*ln1);
! 1474: }
! 1475: avma=av;
! 1476: }
! 1477:
! 1478: GEN
! 1479: fibo(long n)
! 1480: {
! 1481: long av = avma;
! 1482: GEN ln,ln1;
! 1483:
! 1484: lucas(n-1,&ln,&ln1);
! 1485: return gerepileupto(av, divis(addii(shifti(ln,1),ln1), 5));
! 1486: }
! 1487:
! 1488: /*******************************************************************/
! 1489: /* */
! 1490: /* CONTINUED FRACTIONS */
! 1491: /* */
! 1492: /*******************************************************************/
! 1493: static GEN sfcont2(GEN b, GEN x, long k);
! 1494:
! 1495: GEN
! 1496: gcf(GEN x)
! 1497: {
! 1498: return sfcont(x,x,0);
! 1499: }
! 1500:
! 1501: GEN
! 1502: gcf2(GEN b, GEN x)
! 1503: {
! 1504: return sfcont0(x,b,0);
! 1505: }
! 1506:
! 1507: GEN
! 1508: gboundcf(GEN x, long k)
! 1509: {
! 1510: return sfcont(x,x,k);
! 1511: }
! 1512:
! 1513: GEN
! 1514: sfcont0(GEN x, GEN b, long flag)
! 1515: {
! 1516: long lb,tb,i;
! 1517: GEN y;
! 1518:
! 1519: if (!b || gcmp0(b)) return sfcont(x,x,flag);
! 1520: tb = typ(b);
! 1521: if (tb == t_INT) return sfcont(x,x,itos(b));
! 1522: if (! is_matvec_t(tb)) err(typeer,"sfcont0");
! 1523:
! 1524: lb=lg(b); if (lb==1) return cgetg(1,t_VEC);
! 1525: if (tb != t_MAT) return sfcont2(b,x,flag);
! 1526: if (lg(b[1])==1) return sfcont(x,x,flag);
! 1527: y = (GEN) gpmalloc(lb*sizeof(long));
! 1528: for (i=1; i<lb; i++) y[i]=coeff(b,1,i);
! 1529: x = sfcont2(y,x,flag); free(y); return x;
! 1530: }
! 1531:
! 1532: GEN
! 1533: sfcont(GEN x, GEN x1, long k)
! 1534: {
! 1535: long av,lx=lg(x),tx=typ(x),e,i,j,l,l1,l2,lx1,tetpil,f;
! 1536: GEN y,p1,p2,p3,p4,yp;
! 1537:
! 1538: if (is_scalar_t(tx))
! 1539: {
! 1540: if (gcmp0(x)) { y=cgetg(2,t_VEC); y[1]=zero; return y; }
! 1541: switch(tx)
! 1542: {
! 1543: case t_INT:
! 1544: y=cgetg(2,t_VEC); y[1]=lcopy(x); return y;
! 1545: case t_REAL:
! 1546: l=avma; p1=cgetg(3,t_FRACN);
! 1547: p2 = rcopy(x); settyp(p2,t_INT); setlgefint(p2,lx);
! 1548: p1[1] = (long) p2; e = bit_accuracy(lx)-1-expo(x);
! 1549: if (e<0) err(talker,"integral part not significant in scfont");
! 1550:
! 1551: l1 = (e>>TWOPOTBITS_IN_LONG)+3; p2=cgeti(l1);
! 1552: p2[1]= evalsigne(1)|evallgefint(l1);
! 1553: p2[2]= (1L<<(e&(BITS_IN_LONG-1)));
! 1554: for (i=3; i<l1; i++) p2[i]=0;
! 1555: p1[2]=(long) p2; p3=cgetg(3,t_FRACN);
! 1556: p3[2]=lcopy(p2);
! 1557: p3[1]=laddsi(signe(x),(GEN)p1[1]);
! 1558: p1=sfcont(p1,p1,k); tetpil=avma;
! 1559: return gerepile(l,tetpil,sfcont(p3,p1,k));
! 1560:
! 1561: case t_FRAC: case t_FRACN:
! 1562: l=avma; lx1=lgefint(x[2]);
! 1563: l1 = (long) ((double) BYTES_IN_LONG/4.0*46.093443*(lx1-2)+3);
! 1564: if (k>0 && l1>k+1) l1=k+1;
! 1565: if (l1>LGBITS) l1=LGBITS;
! 1566: if (lgefint(x[1]) >= lx1) p1=icopy((GEN)x[1]);
! 1567: else affii((GEN)x[1],p1=cgeti(lx1));
! 1568: p2=icopy((GEN)x[2]); l2=avma; lx1=lg(x1);
! 1569: y=cgetg(l1,t_VEC); f=(x!=x1); i=0;
! 1570: while (!gcmp0(p2) && i<=l1-2)
! 1571: {
! 1572: i++; y[i]=ldvmdii(p1,p2,&p3);
! 1573: if (signe(p3)>=0) affii(p3,p1);
! 1574: else
! 1575: {
! 1576: p4=addii(p3,p2); affii(p4,p1); cgiv(p4);
! 1577: y[1]=laddsi(-1,(GEN)y[1]);
! 1578: }
! 1579: cgiv(p3); p4=p1; p1=p2; p2=p4;
! 1580: if (f)
! 1581: {
! 1582: if (i>=lx1) { i--; break; }
! 1583: if (!egalii((GEN)y[i],(GEN)x1[i]))
! 1584: {
! 1585: av=avma;
! 1586: if (gcmp1(absi(subii((GEN)x1[i],(GEN)y[i]))))
! 1587: {
! 1588: if (i>=lx1-1 || !gcmp1((GEN)x1[i+1]))
! 1589: affii((GEN)x1[i],(GEN)y[i]);
! 1590: }
! 1591: else i--;
! 1592: avma=av; break;
! 1593: }
! 1594: }
! 1595: }
! 1596: if (i>=2 && gcmp1((GEN)y[i]))
! 1597: {
! 1598: cgiv((GEN)y[i]); --i; cgiv((GEN)y[i]);
! 1599: y[i]=laddsi(1,(GEN)y[i]);
! 1600: }
! 1601: setlg(y,i+1); l2=l2-((l1-i-1)<<TWOPOTBYTES_IN_LONG);
! 1602: return gerepile(l,l2,y);
! 1603: }
! 1604: err(typeer,"sfcont");
! 1605: }
! 1606:
! 1607: switch(tx)
! 1608: {
! 1609: case t_POL:
! 1610: y=cgetg(2,t_VEC); y[1]=lcopy(x); break;
! 1611: case t_SER:
! 1612: av=avma; p1=gtrunc(x); tetpil=avma;
! 1613: y=gerepile(av,tetpil,sfcont(p1,p1,k)); break;
! 1614: case t_RFRAC:
! 1615: case t_RFRACN:
! 1616: av=avma; l1=lgef(x[1]); if (lgef(x[2])>l1) l1=lgef(x[2]);
! 1617: if (k>0 && l1>k+1) l1=k+1;
! 1618: yp=cgetg(l1,t_VEC); p1=(GEN)x[1]; i=0; p2=(GEN)x[2];
! 1619: while (!gcmp0(p2) && i<=l1-2)
! 1620: {
! 1621: i++; yp[i]=ldivres(p1,p2,&p3);
! 1622: p1=p2; p2=p3;
! 1623: }
! 1624: tetpil=avma; y=cgetg(i+1,t_VEC);
! 1625: for (j=1; j<=i; j++) y[j]=lcopy((GEN)yp[j]);
! 1626: y=gerepile(av,tetpil,y); break;
! 1627: default: err(typeer,"sfcont");
! 1628: }
! 1629: return y;
! 1630: }
! 1631:
! 1632: static GEN
! 1633: sfcont2(GEN b, GEN x, long k)
! 1634: {
! 1635: long l1 = lg(b), tx = typ(x), i,tetpil, av = avma;
! 1636: GEN y,p1;
! 1637:
! 1638: if (k)
! 1639: {
! 1640: if (k>=l1) err(typeer,"sfcont2");
! 1641: l1 = k+1;
! 1642: }
! 1643: y=cgetg(l1,t_VEC);
! 1644: if (l1==1) return y;
! 1645: if (is_scalar_t(tx))
! 1646: {
! 1647: if (!is_intreal_t(tx) && !is_frac_t(tx)) err(typeer,"sfcont2");
! 1648: }
! 1649: else if (tx == t_SER) x = gtrunc(x);
! 1650:
! 1651: if (!gcmp1((GEN)b[1])) x = gmul((GEN)b[1],x);
! 1652: i = 2; y[1] = lfloor(x); p1 = gsub(x,(GEN)y[1]);
! 1653: for ( ; i<l1 && !gcmp0(p1); i++)
! 1654: {
! 1655: x = gdiv((GEN)b[i],p1);
! 1656: if (tx == t_REAL)
! 1657: {
! 1658: long e = expo(x);
! 1659: if (e>0 && (e>>TWOPOTBITS_IN_LONG)+3 > lg(x)) break;
! 1660: }
! 1661: y[i] = lfloor(x);
! 1662: p1 = gsub(x,(GEN)y[i]);
! 1663: }
! 1664: setlg(y,i); tetpil=avma;
! 1665: return gerepile(av,tetpil,gcopy(y));
! 1666: }
! 1667:
! 1668: GEN
! 1669: pnqn(GEN x)
! 1670: {
! 1671: long av=avma,tetpil,lx,ly,tx=typ(x),i;
! 1672: GEN y,p0,p1,q0,q1,a,b,p2,q2;
! 1673:
! 1674: if (! is_matvec_t(tx)) err(typeer,"pnqn");
! 1675: lx=lg(x); if (lx==1) return idmat(2);
! 1676: p0=gun; q0=gzero;
! 1677: if (tx != t_MAT)
! 1678: {
! 1679: p1=(GEN)x[1]; q1=gun;
! 1680: for (i=2; i<lx; i++)
! 1681: {
! 1682: a=(GEN)x[i];
! 1683: p2=gadd(gmul(a,p1),p0); p0=p1; p1=p2;
! 1684: q2=gadd(gmul(a,q1),q0); q0=q1; q1=q2;
! 1685: }
! 1686: }
! 1687: else
! 1688: {
! 1689: ly=lg(x[1]);
! 1690: if (ly==2)
! 1691: {
! 1692: p1=cgetg(lx,t_VEC); for (i=1; i<lx; i++) p1[i]=mael(x,i,1);
! 1693: tetpil=avma; return gerepile(av,tetpil,pnqn(p1));
! 1694: }
! 1695: if (ly!=3) err(talker,"incorrect size in pnqn");
! 1696: p1=gcoeff(x,2,1); q1=gcoeff(x,1,1);
! 1697: for (i=2; i<lx; i++)
! 1698: {
! 1699: a=gcoeff(x,2,i); b=gcoeff(x,1,i);
! 1700: p2=gadd(gmul(a,p1),gmul(b,p0)); p0=p1; p1=p2;
! 1701: q2=gadd(gmul(a,q1),gmul(b,q0)); q0=q1; q1=q2;
! 1702: }
! 1703: }
! 1704: tetpil=avma; y=cgetg(3,t_MAT);
! 1705: p2=cgetg(3,t_COL); y[1]=(long)p2; p2[1]=lcopy(p1); p2[2]=lcopy(q1);
! 1706: p2=cgetg(3,t_COL); y[2]=(long)p2; p2[1]=lcopy(p0); p2[2]=lcopy(q0);
! 1707: return gerepile(av,tetpil,y);
! 1708: }
! 1709:
! 1710: GEN
! 1711: bestappr(GEN x, GEN k)
! 1712: {
! 1713: long av=avma,tetpil,tx,tk=typ(k),lx,i,e;
! 1714: GEN p0,p1,p,q0,q1,q,a,y;
! 1715:
! 1716: if (tk != t_INT)
! 1717: {
! 1718: if (tk != t_REAL && !is_frac_t(tk))
! 1719: err(talker,"incorrect bound type in bestappr");
! 1720: k = gcvtoi(k,&e);
! 1721: }
! 1722: if (cmpis(k,1) < 0) k=gun;
! 1723: tx=typ(x); if (tx == t_FRACN) x = gred(x);
! 1724: switch(tx)
! 1725: {
! 1726: case t_INT:
! 1727: if (av==avma) return icopy(x);
! 1728: tetpil=avma; return gerepile(av,tetpil,icopy(x));
! 1729:
! 1730: case t_FRAC:
! 1731: if (cmpii((GEN)x[2],k) <= 0)
! 1732: {
! 1733: if (av==avma) return gcopy(x);
! 1734: tetpil=avma; return gerepile(av,tetpil,gcopy(x));
! 1735: }
! 1736:
! 1737: case t_REAL:
! 1738: p1=gun; p0=gfloor(x); q1=gzero; q0=gun; a=p0;
! 1739: while (gcmp(q0,k)<=0)
! 1740: {
! 1741: x = gsub(x,a);
! 1742: if (gcmp0(x)) { p1=p0; q1=q0; break; }
! 1743:
! 1744: x = ginv(x); a = (gcmp(x,k)<0)? gfloor(x): k;
! 1745: p = addii(mulii(a,p0),p1); p1=p0; p0=p;
! 1746: q = addii(mulii(a,q0),q1); q1=q0; q0=q;
! 1747: }
! 1748: tetpil=avma; return gerepile(av,tetpil,gdiv(p1,q1));
! 1749:
! 1750: case t_COMPLEX: case t_POL: case t_SER: case t_RFRAC:
! 1751: case t_RFRACN: case t_VEC: case t_COL: case t_MAT:
! 1752: lx = (tx==t_POL)? lgef(x): lg(x); y=cgetg(lx,tx);
! 1753: for (i=1; i<lontyp[tx]; i++) y[i]=x[i];
! 1754: for ( ; i<lx; i++) y[i]=(long)bestappr((GEN)x[i],k);
! 1755: return y;
! 1756: }
! 1757: err(typeer,"bestappr");
! 1758: return NULL; /* not reached */
! 1759: }
! 1760:
! 1761: /***********************************************************************/
! 1762: /** **/
! 1763: /** FUNDAMENTAL UNIT AND REGULATOR (QUADRATIC FIELDS) **/
! 1764: /** **/
! 1765: /***********************************************************************/
! 1766:
! 1767: GEN
! 1768: gfundunit(GEN x)
! 1769: {
! 1770: return garith_proto(fundunit,x,1);
! 1771: }
! 1772:
! 1773: static GEN
! 1774: get_quad(GEN f, GEN pol, long r)
! 1775: {
! 1776: GEN y, c=(GEN)f[2], p1=(GEN)c[1], q1=(GEN)c[2];
! 1777: y=cgetg(4,t_QUAD); y[1]=(long)pol;
! 1778: y[2]=r? lsubii(p1,q1): (long)p1;
! 1779: y[3]=(long)q1; return y;
! 1780: }
! 1781:
! 1782: /* replace f by f * [a,1; 1,0] */
! 1783: static void
! 1784: update_f(GEN f, GEN a)
! 1785: {
! 1786: GEN p1;
! 1787: p1=gcoeff(f,1,1);
! 1788: coeff(f,1,1)=laddii(mulii(a,p1), gcoeff(f,1,2));
! 1789: coeff(f,1,2)=(long)p1;
! 1790:
! 1791: p1=gcoeff(f,2,1);
! 1792: coeff(f,2,1)=laddii(mulii(a,p1), gcoeff(f,2,2));
! 1793: coeff(f,2,2)=(long)p1;
! 1794: }
! 1795:
! 1796: GEN
! 1797: fundunit(GEN x)
! 1798: {
! 1799: long av = avma, av2,tetpil,lim,r,flp,flq;
! 1800: GEN pol,y,a,u,v,u1,v1,sqd,f;
! 1801:
! 1802: if (typ(x) != t_INT) err(arither1);
! 1803: if (signe(x)<=0) err(arither2);
! 1804: r=mod4(x); if (r==2 || r==3) err(funder2,"fundunit");
! 1805:
! 1806: sqd=racine(x); av2=avma; lim=stack_lim(av2,2);
! 1807: a = shifti(addsi(r,sqd),-1);
! 1808: f=cgetg(3,t_MAT); f[1]=lgetg(3,t_COL); f[2]=lgetg(3,t_COL);
! 1809: coeff(f,1,1)=(long)a; coeff(f,1,2)=un;
! 1810: coeff(f,2,1)=un; coeff(f,2,2)=zero;
! 1811: v = gdeux; u = stoi(r);
! 1812: for(;;)
! 1813: {
! 1814: u1=subii(mulii(a,v),u); flp=egalii(u,u1); u=u1;
! 1815: v1=divii(subii(x,sqri(u)),v); flq=egalii(v,v1); v=v1;
! 1816: if (flq) break; a = divii(addii(sqd,u),v);
! 1817: if (flp) break; update_f(f,a);
! 1818: if (low_stack(lim, stack_lim(av2,2)))
! 1819: {
! 1820: GEN *gptr[4]; gptr[0]=&a; gptr[1]=&f; gptr[2]=&u; gptr[3]=&v;
! 1821: if(DEBUGMEM>1) err(warnmem,"fundunit");
! 1822: gerepilemany(av2,gptr,4);
! 1823: }
! 1824: }
! 1825: pol = quadpoly(x); y = get_quad(f,pol,r);
! 1826: if (!flq) v1 = y; else { update_f(f,a); v1 = get_quad(f,pol,r); }
! 1827:
! 1828: u1=gconj(y); tetpil=avma; y=gdiv(v1,u1);
! 1829: if (signe(y[3]) < 0) { tetpil=avma; y=gneg(y); }
! 1830: return gerepile(av,tetpil,y);
! 1831: }
! 1832:
! 1833: GEN
! 1834: gregula(GEN x, long prec)
! 1835: {
! 1836: return garith_proto2gs(regula,x,prec);
! 1837: }
! 1838:
! 1839: GEN
! 1840: regula(GEN x, long prec)
! 1841: {
! 1842: long av = avma,av2,tetpil,lim,r,fl,rexp;
! 1843: GEN ln2,reg,reg1,rsqd,y,u,v,a,u1,v1,sqd;
! 1844:
! 1845: if (typ(x) != t_INT) err(arither1);
! 1846: if (signe(x)<=0) err(arither2);
! 1847: r=mod4(x); if (r==2 || r==3) err(funder2,"regula");
! 1848:
! 1849: sqd=racine(x); rsqd=gsqrt(x,prec);
! 1850: if (gegal(sqri(sqd),x)) err(talker,"square argument in regula");
! 1851:
! 1852: rexp=0; reg=cgetr(prec); affsr(2,reg);
! 1853: ln2 = mplog(reg);
! 1854: av2=avma; lim = stack_lim(av2,2);
! 1855: a = shifti(addsi(r,sqd),-1);
! 1856: v = gdeux; u = stoi(r);
! 1857: for(;;)
! 1858: {
! 1859: u1=subii(mulii(a,v),u);
! 1860: reg1=divri(addir(u1,rsqd),v);
! 1861: v1=divii(subii(x,sqri(u1)),v); fl=gegal(v,v1);
! 1862: if (gegal(u,u1) || fl) break;
! 1863: v=v1; u=u1; a = divii(addii(sqd,u),v);
! 1864: reg = mulrr(reg,reg1); rexp += expo(reg); setexpo(reg,0);
! 1865: if (rexp & ~EXPOBITS) err(muler4);
! 1866: if (low_stack(lim, stack_lim(av2,2)))
! 1867: {
! 1868: GEN *gptr[4]; gptr[0]=&a; gptr[1]=® gptr[2]=&u; gptr[3]=&v;
! 1869: if(DEBUGMEM>1) err(warnmem,"regula");
! 1870: gerepilemany(av2,gptr,4);
! 1871: }
! 1872: }
! 1873: reg = gsqr(reg); setexpo(reg,expo(reg)-1);
! 1874: if (fl) reg = mulrr(reg, divri(addir(u1,rsqd),v));
! 1875: y = mplog(divri(reg,v)); u1 = mulsr(rexp,ln2);
! 1876: if (signe(u1)) setexpo(u1, expo(u1)+1);
! 1877: tetpil=avma; return gerepile(av,tetpil,gadd(y,u1));
! 1878: }
! 1879:
! 1880: /*************************************************************************/
! 1881: /** **/
! 1882: /** CLASS NUMBER **/
! 1883: /** **/
! 1884: /*************************************************************************/
! 1885:
! 1886: static GEN
! 1887: gclassno(GEN x)
! 1888: {
! 1889: return garith_proto(classno,x,1);
! 1890: }
! 1891:
! 1892: static GEN
! 1893: gclassno2(GEN x)
! 1894: {
! 1895: return garith_proto(classno2,x,1);
! 1896: }
! 1897:
! 1898: GEN
! 1899: qfbclassno0(GEN x,long flag)
! 1900: {
! 1901: switch(flag)
! 1902: {
! 1903: case 0: return gclassno(x);
! 1904: case 1: return gclassno2(x);
! 1905: default: err(flagerr,"qfbclassno");
! 1906: }
! 1907: return NULL; /* not reached */
! 1908: }
! 1909:
! 1910: static GEN
! 1911: end_classno(GEN h, GEN hin, GEN *formes, long ptforme)
! 1912: {
! 1913: long av,i,j,lim,com;
! 1914: GEN p1,p2,p3,q,hp,fh,fg,ftest, f = formes[0];
! 1915:
! 1916: if (ptforme>11) ptforme = 11;
! 1917: p2=factor(h); p1=(GEN)p2[1]; p2=(GEN)p2[2];
! 1918: for (i=1; i<lg(p1); i++)
! 1919: {
! 1920: lim = itos((GEN)p2[i]);
! 1921: for (j=1; j<=lim; j++)
! 1922: {
! 1923: p3=divii(h,(GEN)p1[i]); fh=gpui(f,p3,0);
! 1924: if (!is_pm1(fh[1])) break;
! 1925: h = p3;
! 1926: }
! 1927: }
! 1928: q=ground(gdiv(hin,h)); hp=mulii(q,h);
! 1929: for (i=1; i<ptforme; i++)
! 1930: {
! 1931: fg=gpui(formes[i],h,0); fh=gpui(fg,q,0);
! 1932: if (!is_pm1(fh[1]))
! 1933: {
! 1934: av = avma; ftest = fg;
! 1935: for (com=1; ; com++)
! 1936: {
! 1937: if (gegal((GEN) fh[1], (GEN) ftest[1]) &&
! 1938: absi_equal((GEN) fh[2], (GEN) ftest[2])) break;
! 1939: ftest = gmul(ftest,fg);
! 1940: }
! 1941: if (signe(fh[2]) == signe(ftest[2])) com = -com;
! 1942: avma = av; q = addsi(com,q);
! 1943: hp = addii(hp, mulsi(com,h));
! 1944: }
! 1945: }
! 1946: return hp;
! 1947: }
! 1948:
! 1949: /* calcul de h(x) pour x<0 par la methode de Shanks */
! 1950: GEN
! 1951: classno(GEN x)
! 1952: {
! 1953: long av = avma, av2,c,ptforme,k,i,j,j1,lim,com,j2,s;
! 1954: GEN count,index,tabla,tablb,hash,court,p1,p2,hin,h,f,fh,fg,ftest,formes[100];
! 1955: byteptr p = diffptr;
! 1956:
! 1957: if (typ(x) != t_INT) err(arither1);
! 1958: s=signe(x); if (s>=0) return classno2(x);
! 1959:
! 1960: k=mod4(x); if (k==1 || k==2) err(funder2,"classno");
! 1961: if (gcmpgs(x,-12) >= 0) return gun;
! 1962:
! 1963: p2 = gsqrt(absi(x),DEFAULTPREC);
! 1964: p1 = divrr(p2,mppi(DEFAULTPREC));
! 1965: p2 = gtrunc(shiftr(gsqrt(p2,DEFAULTPREC),1));
! 1966: s = 1000;
! 1967: if (signe(p2))
! 1968: {
! 1969: s = p2[2];
! 1970: if (lgefint(p2)>3 || s<0)
! 1971: err(talker,"discriminant too big in classno");
! 1972: if (s<1000) s=1000;
! 1973: }
! 1974: c=ptforme=0; court = stoi(2);
! 1975: while (c <= s && *p)
! 1976: {
! 1977: c += *p++; k=krogs(x,c);
! 1978: if (k)
! 1979: {
! 1980: av2=avma;
! 1981: if (k>0)
! 1982: {
! 1983: divrsz(mulsr(c,p1),c-1,p1); avma=av2;
! 1984: if (ptforme<100 && c>2)
! 1985: {
! 1986: court[2]=c;
! 1987: formes[ptforme++]=redimag(primeform(x,court,0));
! 1988: }
! 1989: }
! 1990: else { divrsz(mulsr(c,p1),c+1,p1); avma=av2; }
! 1991: }
! 1992: }
! 1993: s = 2*itos(gceil(gpui(p1,ginv(stoi(4)),DEFAULTPREC)));
! 1994: if (s>=10000) s=10000;
! 1995:
! 1996: count = new_chunk(256); for (i=0; i<=255; i++) count[i]=0;
! 1997: index = new_chunk(257);
! 1998: tabla = new_chunk(10000);
! 1999: tablb = new_chunk(10000);
! 2000: hash = new_chunk(10000);
! 2001: h = hin = ground(p1); f=formes[0];
! 2002: p1 = fh = gpui(f,h,0);
! 2003: for (i=0; i<s; i++)
! 2004: {
! 2005: p2=(GEN)p1[1]; tabla[i]=p2[lgefint(p2)-1];
! 2006: p2=(GEN)p1[2]; tablb[i]=p2[lgefint(p2)-1];
! 2007: count[tabla[i]&255]++; p1=compimag(p1,f);
! 2008: }
! 2009: index[0]=0; for (i=0; i<=254; i++) index[i+1] = index[i]+count[i];
! 2010: for (i=0; i<s; i++) hash[index[tabla[i]&255]++]=i;
! 2011: index[0]=0; for (i=0; i<=255; i++) index[i+1] = index[i]+count[i];
! 2012:
! 2013: fg=gpuigs(f,s); av2=avma; lim=stack_lim(av2,2);
! 2014: ftest=gpuigs(p1,0);
! 2015: for (com=0; ; com++)
! 2016: {
! 2017: p1=(GEN)ftest[1]; k=p1[lgefint(p1)-1]; j=k&255;
! 2018: for (j1=index[j]; j1 < index[j+1]; j1++)
! 2019: {
! 2020: j2=hash[j1];
! 2021: if (tabla[j2] == k)
! 2022: {
! 2023: p2=(GEN)ftest[2];
! 2024: if (tablb[j2] == labs(p2[lgefint(p2)-1]))
! 2025: {
! 2026: p1 = gmul(gpuigs(f,j2),fh);
! 2027: if (gegal((GEN) p1[1],(GEN) ftest[1]) &&
! 2028: absi_equal((GEN) p1[2],(GEN) ftest[2]))
! 2029: {
! 2030: /* p1 = ftest or ftest^(-1), we are done */
! 2031: if (signe(p1[2]) == signe(ftest[2])) com = -com;
! 2032: h = addii(addis(h,j2), mulss(s,com));
! 2033: h = end_classno(h,hin,formes,ptforme);
! 2034: avma = av; return icopy(h); /* safe: stack big enough */
! 2035: }
! 2036: }
! 2037: }
! 2038: }
! 2039: ftest = gmul(ftest,fg);
! 2040: if (is_pm1(ftest[1])) err(impl,"classno with too small order");
! 2041: if (low_stack(lim, stack_lim(av2,2))) ftest = gerepileupto(av2,ftest);
! 2042: }
! 2043: }
! 2044:
! 2045: /* use Euler products */
! 2046: GEN
! 2047: classno2(GEN x)
! 2048: {
! 2049: long av=avma,tetpil,n,i,k,s=signe(x),fl2;
! 2050: GEN p1,p2,p3,p4,p5,p7,p8,pi4,reg,logd,d,fd;
! 2051:
! 2052: if (typ(x) != t_INT) err(arither1);
! 2053: if (!s) err(arither2);
! 2054: if (s<0 && gcmpgs(x,-12) >= 0) return gun;
! 2055:
! 2056: p1=auxdecomp(absi(x),1); p2=(GEN)p1[2]; p1=(GEN)p1[1];
! 2057: n=lg(p1); d=gun;
! 2058: for (i=1; i<n; i++)
! 2059: if (mod2((GEN)p2[i])) d=mulii(d,(GEN)p1[i]);
! 2060: fl2 = (mod4(x)==0); /* 4 | x */
! 2061: if (mod4(d) != 2-s)
! 2062: {
! 2063: if (!fl2) err(funder2,"classno2");
! 2064: d = shifti(d,2);
! 2065: }
! 2066: else fl2=0;
! 2067: p8=gun; fd = (s<0)? negi(d): d; /* d = abs(fd) */
! 2068: for (i=1; i<n; i++)
! 2069: {
! 2070: k=itos((GEN)p2[i]); p4=(GEN)p1[i];
! 2071: if (fl2 && i==1) k -= 2; /* p4 = 2 */
! 2072: if (k>=2)
! 2073: {
! 2074: p8=mulii(p8,subis(p4,kronecker(fd,p4)));
! 2075: if (k>=4) p8=mulii(p8,gpuigs(p4,(k>>1)-1));
! 2076: }
! 2077: }
! 2078: if (s<0 && lgefint(d)==3)
! 2079: {
! 2080: switch(d[2])
! 2081: {
! 2082: case 4: p8=gdivgs(p8,2); break;
! 2083: case 3: p8=gdivgs(p8,3); break;
! 2084: }
! 2085: if (d[2] < 12) /* |fd| < 12*/
! 2086: { tetpil=avma; return gerepile(av,tetpil,icopy(p8)); }
! 2087: }
! 2088:
! 2089: pi4=mppi(DEFAULTPREC); logd=glog(d,DEFAULTPREC);
! 2090: p1=gsqrt(gdiv(gmul(d,logd),gmul2n(pi4,1)),DEFAULTPREC);
! 2091: p4=divri(pi4,d); p7=ginv(mpsqrt(pi4));
! 2092: if (s>0)
! 2093: {
! 2094: reg=regula(d,DEFAULTPREC);
! 2095: p2=gsubsg(1,gmul2n(gdiv(glog(reg,DEFAULTPREC),logd),1));
! 2096: p3=gsqrt(gdivsg(2,logd),DEFAULTPREC);
! 2097: if (gcmp(p2,p3)>=0) p1=gmul(p2,p1);
! 2098: }
! 2099: p1 = gtrunc(p1); n=p1[2];
! 2100: if (lgefint(p1)!=3 || n<0)
! 2101: err(talker,"discriminant too large in classno");
! 2102:
! 2103: p1 = gsqrt(d,DEFAULTPREC); p3 = gzero;
! 2104: if (s>0)
! 2105: {
! 2106: for (i=1; i<=n; i++)
! 2107: {
! 2108: k=krogs(fd,i);
! 2109: if (k)
! 2110: {
! 2111: p2=mulir(mulss(i,i),p4);
! 2112: p5=subsr(1,mulrr(p7,incgam3(ghalf,p2,DEFAULTPREC)));
! 2113: p5=addrr(divrs(mulrr(p1,p5),i),eint1(p2,DEFAULTPREC));
! 2114: p3 = (k>0)? addrr(p3,p5): subrr(p3,p5);
! 2115: }
! 2116: }
! 2117: p3=shiftr(divrr(p3,reg),-1);
! 2118: if (!egalii(x,fd)) /* x != p3 */
! 2119: p8 = gdiv(p8,ground(gdiv(regula(x,DEFAULTPREC),reg)));
! 2120: }
! 2121: else
! 2122: {
! 2123: p1 = gdiv(p1,pi4);
! 2124: for (i=1; i<=n; i++)
! 2125: {
! 2126: k=krogs(fd,i);
! 2127: if (k)
! 2128: {
! 2129: p2=mulir(mulss(i,i),p4);
! 2130: p5=subsr(1,mulrr(p7,incgam3(ghalf,p2,DEFAULTPREC)));
! 2131: p5=addrr(p5,divrr(divrs(p1,i),mpexp(p2)));
! 2132: p3 = (k>0)? addrr(p3,p5): subrr(p3,p5);
! 2133: }
! 2134: }
! 2135: }
! 2136: p3=ground(p3); tetpil=avma;
! 2137: return gerepile(av,tetpil,mulii(p8,p3));
! 2138: }
! 2139:
! 2140: GEN
! 2141: hclassno(GEN x)
! 2142: {
! 2143: long d,a,b,h,b2,f;
! 2144:
! 2145: d= -itos(x); if (d>0 || (d & 3) > 1) return gzero;
! 2146: if (!d) return gdivgs(gun,-12);
! 2147: if (-d > (VERYBIGINT>>1))
! 2148: err(talker,"discriminant too big in hclassno. Use quadclassunit");
! 2149: h=0; b=d&1; b2=(b-d)>>2; f=0;
! 2150: if (!b)
! 2151: {
! 2152: for (a=1; a*a<b2; a++)
! 2153: if (b2%a == 0) h++;
! 2154: f = (a*a==b2); b=2; b2=(4-d)>>2;
! 2155: }
! 2156: while (b2*3+d<0)
! 2157: {
! 2158: if (b2%b == 0) h++;
! 2159: for (a=b+1; a*a<b2; a++)
! 2160: if (b2%a == 0) h+=2;
! 2161: if (a*a==b2) h++;
! 2162: b+=2; b2=(b*b-d)>>2;
! 2163: }
! 2164: if (b2*3+d==0)
! 2165: {
! 2166: GEN y = cgetg(3,t_FRAC);
! 2167: y[1]=lstoi(3*h+1); y[2]=lstoi(3); return y;
! 2168: }
! 2169: if (f) return gaddsg(h,ghalf);
! 2170: return stoi(h);
! 2171: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>