/* $Id: bibli2.c,v 1.38 2002/09/07 21:45:57 karim Exp $ Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /********************************************************************/ /** **/ /** BIBLIOTHEQUE MATHEMATIQUE **/ /** (deuxieme partie) **/ /** **/ /********************************************************************/ #include "pari.h" extern GEN _ei(long n, long i); /********************************************************************/ /** **/ /** DEVELOPPEMENTS LIMITES **/ /** **/ /********************************************************************/ GEN tayl(GEN x, long v, long precS) { long i, vx = gvar9(x); gpmem_t tetpil, av=avma; GEN p1,y; if (v <= vx) { long p1[] = { evaltyp(t_SER)|_evallg(2), 0 }; p1[1] = evalvalp(precS) | evalvarn(v); return gadd(p1,x); } p1=cgetg(v+2,t_VEC); for (i=0; i MAXVARN) err(talker,"incorrect object in O()"); m = n*gval(x,v); } return zeroser(v,m); } /*******************************************************************/ /** **/ /** SPECIAL POLYNOMIALS **/ /** **/ /*******************************************************************/ #ifdef LONG_IS_64BIT # define SQRTVERYBIGINT 3037000500 /* ceil(sqrt(VERYBIGINT)) */ #else # define SQRTVERYBIGINT 46341 #endif /* Tchebichev polynomial: T0=1; T1=X; T(n)=2*X*T(n-1)-T(n-2) * T(n) = (n/2) sum_{k=0}^{n/2} a_k x^(n-2k) * where a_k = (-1)^k 2^(n-2k) (n-k-1)! / k!(n-2k)! is an integer * and a_0 = 2^(n-1), a_k / a_{k-1} = - (n-2k+2)(n-2k+1) / 4k(n-k) */ GEN tchebi(long n, long v) /* Assume 4*n < VERYBIGINT */ { long k, l; gpmem_t av; GEN q,a,r; if (v<0) v = 0; if (n < 0) err(talker,"negative degree in tchebi"); if (n==0) return polun[v]; if (n==1) return polx[v]; q = cgetg(n+3, t_POL); r = q + n+2; a = shifti(gun, n-1); *r-- = (long)a; *r-- = zero; if (n < SQRTVERYBIGINT) for (k=1,l=n; l>1; k++,l-=2) { av = avma; a = divis(mulis(a, l*(l-1)), 4*k*(n-k)); a = gerepileuptoint(av, negi(a)); *r-- = (long)a; *r-- = zero; } else for (k=1,l=n; l>1; k++,l-=2) { av = avma; a = mulis(mulis(a, l), l-1); a = divis(divis(a, 4*k), n-k); a = gerepileuptoint(av, negi(a)); *r-- = (long)a; *r-- = zero; } q[1] = evalsigne(1) | evalvarn(v) | evallgef(n+3); return q; } GEN addshiftw(GEN x, GEN y, long d); /* Legendre polynomial */ /* L0=1; L1=X; (n+1)*L(n+1)=(2*n+1)*X*L(n)-n*L(n-1) */ GEN legendre(long n, long v) { long m; gpmem_t av, tetpil, lim; GEN p0,p1,p2; if (v<0) v = 0; if (n < 0) err(talker,"negative degree in legendre"); if (n==0) return polun[v]; if (n==1) return polx[v]; p0=polun[v]; av=avma; lim=stack_lim(av,2); p1=gmul2n(polx[v],1); for (m=1; m1) err(warnmem,"legendre"); p0=gcopy(p0); gptr[0]=&p0; gptr[1]=&p1; gerepilemanysp(av,tetpil,gptr,2); } } tetpil=avma; return gerepile(av,tetpil,gmul2n(p1,-n)); } /* cyclotomic polynomial */ GEN cyclo(long n, long v) { long d, q, m; gpmem_t av=avma, tetpil; GEN yn,yd; if (n<=0) err(arither2); if (v<0) v = 0; yn = yd = polun[0]; for (d=1; d*d<=n; d++) { if (n%d) continue; q=n/d; m = mu(stoi(q)); if (m) { /* y *= (x^d - 1) */ if (m>0) yn = addshiftw(yn, gneg(yn), d); else yd = addshiftw(yd, gneg(yd), d); } if (q==d) break; m = mu(stoi(d)); if (m) { /* y *= (x^q - 1) */ if (m>0) yn = addshiftw(yn, gneg(yn), q); else yd = addshiftw(yd, gneg(yd), q); } } tetpil=avma; yn = gerepile(av,tetpil,gdeuc(yn,yd)); setvarn(yn,v); return yn; } /* compute prod (L*x ± a[i]) */ GEN roots_to_pol_intern(GEN L, GEN a, long v, int plus) { long i,k,lx = lg(a), code; GEN p1,p2; if (lx == 1) return polun[v]; p1 = cgetg(lx, t_VEC); code = evalsigne(1)|evalvarn(v)|evallgef(5); for (k=1,i=1; i 1) { qpow = (GEN*)new_chunk(I+1); qpow[2]=q; } for (j=3; j<=I; j++) qpow[j] = gmul(q, qpow[j-1]); } for (i=1; i<=n; i++) { I = (i+1)/2; coeff(m,i,1)=un; if (q) { for (j=2; j<=I; j++) coeff(m,i,j) = ladd(gmul(qpow[j],gcoeff(m,i-1,j)), gcoeff(m,i-1,j-1)); } else { for (j=2; j<=I; j++) coeff(m,i,j) = laddii(gcoeff(m,i-1,j), gcoeff(m,i-1,j-1)); } for ( ; j<=i; j++) coeff(m,i,j) = coeff(m,i,i+1-j); for ( ; j<=n; j++) coeff(m,i,j) = zero; } return gerepilecopy(av, m); } /********************************************************************/ /** **/ /** LAPLACE TRANSFORM (OF A SERIES) **/ /** **/ /********************************************************************/ GEN laplace(GEN x) { gpmem_t av = avma; long i,l,ec; GEN y,p1; if (typ(x)!=t_SER) err(talker,"not a series in laplace"); if (gcmp0(x)) return gcopy(x); ec = valp(x); if (ec<0) err(talker,"negative valuation in laplace"); l=lg(x); y=cgetg(l,t_SER); p1=mpfact(ec); y[1]=x[1]; for (i=2; iv) v=ey; l=ex+lx; i=ey+ly; if (i=lx) for ( ; i>=lx; i--) y[i]=zero; for ( ; i>=2; i--) y[i]=lcopy((GEN)x[i]); break; case t_POL: lx=lgef(x); y=cgetg(lx,tx); y[1]=x[1]; for (i=2; i 0) { GEN z = subis(n,k); if (cmpis(z,k) < 0) k = itos(z); avma = av; if (k <= 1) { if (k < 0) return gzero; if (k == 0) return gun; return gcopy(n); } } for (i=2; i<=k; i++) y = gdivgs(gmul(y,addis(n,i-1-k)), i); } else { for (i=2; i<=k; i++) y = gdivgs(gmul(y,gaddgs(n,i-1-k)), i); } return gerepileupto(av, y); } /* Assume n >= 1, return bin, bin[k+1] = binomial(n, k) */ GEN vecbinome(long n) { long d = (n + 1)/2, k; GEN bin = cgetg(n+2, t_VEC), *C; C = (GEN*)(bin + 1); /* C[k] = binomial(n, k) */ C[0] = gun; for (k=1; k <= d; k++) { gpmem_t av = avma; C[k] = gerepileuptoint(av, diviiexact(mulsi(n-k+1, C[k-1]), stoi(k))); } for ( ; k <= n; k++) C[k] = C[n - k]; return bin; } /********************************************************************/ /** **/ /** POLYNOMIAL INTERPOLATION **/ /** **/ /********************************************************************/ /* assume n > 1 */ GEN polint_i(GEN xa, GEN ya, GEN x, long n, GEN *ptdy) { long i, m, ns=0, tx=typ(x); gpmem_t av = avma, tetpil; GEN den,ho,hp,w,y,c,d,dy; if (!xa) { xa = cgetg(n+1, t_VEC); for (i=1; i<=n; i++) xa[i] = lstoi(i); xa++; } if (is_scalar_t(tx) && tx != t_INTMOD && tx != t_PADIC && tx != t_POLMOD) { GEN dif = NULL, dift; for (i=0; i>1; fl = cmp((GEN)x[j],y); if (!fl) return flag? 0: j; if (fl<0) li=j+1; else ri=j-1; } while (ri>=li); if (!flag) return 0; return (fl<0)? j+1: j; } long setsearch(GEN x, GEN y, long flag) { gpmem_t av = avma; long res; if (typ(y) != t_STR) y = gtostr(y); res=gen_search(x,y,flag,gcmp); avma=av; return res; } #if 0 GEN gen_union(GEN x, GEN y, int (*cmp)(GEN,GEN)) { if (typ(x) != t_VEC || typ(y) != t_VEC) err(talker,"not a set in setunion"); } #endif GEN setunion(GEN x, GEN y) { gpmem_t av=avma, tetpil; GEN z; if (typ(x) != t_VEC || typ(y) != t_VEC) err(talker,"not a set in setunion"); z=concatsp(x,y); tetpil=avma; return gerepile(av,tetpil,gtoset(z)); } GEN setintersect(GEN x, GEN y) { long i, lx, c; gpmem_t av=avma; GEN z; if (!setisset(x) || !setisset(y)) err(talker,"not a set in setintersect"); lx=lg(x); z=cgetg(lx,t_VEC); c=1; for (i=1; i0) continue; find=1; } if (!find) diff[k++]=set1[i]; } setlg(diff,k); return gerepilecopy(ltop,diff); } GEN setminus(GEN x, GEN y) { if (!setisset(x) || !setisset(y)) err(talker,"not a set in setminus"); return gen_setminus(x,y,gcmp); } /***********************************************************************/ /* */ /* OPERATIONS ON DIRICHLET SERIES */ /* */ /***********************************************************************/ /* Addition, subtraction and scalar multiplication of Dirichlet series are done on the corresponding vectors */ static long dirval(GEN x) { long i=1,lx=lg(x); while (i>12)&LOWMASK, (mymyrand()>>12)&LOWMASK); #else #define GLUE4(hi1,hi2, lo1,lo2) GLUE2(((hi1)<<16)|(hi2), ((lo1)<<16)|(lo2)) # define LOWMASK2 0xffffUL return GLUE4((mymyrand()>>12)&LOWMASK2, (mymyrand()>>12)&LOWMASK2, (mymyrand()>>12)&LOWMASK2, (mymyrand()>>12)&LOWMASK2); #endif } GEN genrand(GEN N) { long lx,i,nz; GEN x, p1; if (!N) return stoi(mymyrand()); if (typ(N)!=t_INT || signe(N)<=0) err(talker,"invalid bound in random"); lx = lgefint(N); x = new_chunk(lx); nz = lx-1; while (!N[nz]) nz--; /* nz = index of last non-zero word */ for (i=2; i2) | evallgefint(lx); x[0] = evaltyp(t_INT) | evallg(lx); avma = (gpmem_t)x; return x; } long setrand(long seed) { return (pari_randseed = seed); } long getrand(void) { return pari_randseed; } long getstack(void) { return top-avma; } long gettime(void) { return timer(); } /***********************************************************************/ /** **/ /** PERMUTATIONS **/ /** **/ /***********************************************************************/ GEN numtoperm(long n, GEN x) { gpmem_t av; long i,a,r; GEN v,w; if (n < 1) err(talker,"n too small (%ld) in numtoperm",n); if (typ(x) != t_INT) err(arither1); v = cgetg(n+1, t_VEC); v[1]=1; av = avma; if (signe(x) <= 0) x = modii(x, mpfact(n)); for (r=2; r<=n; r++) { x = dvmdis(x,r,&w); a = itos(w); for (i=r; i>=a+2; i--) v[i] = v[i-1]; v[i]=r; } avma = av; for (i=1; i<=n; i++) v[i] = lstoi(v[i]); return v; } GEN permtonum(GEN x) { long lx=lg(x)-1, n=lx, last, ind, tx = typ(x); gpmem_t av=avma; GEN ary,res; if (!is_vec_t(tx)) err(talker,"not a vector in permtonum"); ary = cgetg(lx+1,t_VECSMALL); for (ind=1; ind<=lx; ind++) { res = (GEN)*++x; if (typ(res) != t_INT) err(typeer,"permtonum"); ary[ind] = itos(res); } ary++; res = gzero; for (last=lx; last>0; last--) { lx--; ind = lx; while (ind>0 && ary[ind] != last) ind--; res = addis(mulis(res,last), ind); while (ind++=2; l--) y = gres(gadd(gmul(y,x), (GEN)f[l]), T); return gerepileupto(av, y); } /* return (1,...a^l) mod T. Not memory clean */ GEN RXQ_powers(GEN a, GEN T, long l) { long i; GEN v; if (typ(a) != t_POL) err(typeer,"RXQ_powers"); l += 2; v = cgetg(l,t_VEC); v[1] = un; if (l == 2) return v; if (degpol(a) >= degpol(T)) a = gres(a, T); v[2] = (long)a; for (i=3; i (long)y)? 1: ((x == y)? 0: -1); } /* Sort x = vector of elts, using cmp to compare them. * flag & cmp_IND: indirect sort: return permutation that would sort x * flag & cmp_C : as cmp_IND, but return permutation as vector of C-longs */ GEN gen_sort(GEN x, int flag, int (*cmp)(GEN,GEN)) { long i,j,indxt,ir,l,tx=typ(x),lx=lg(x); GEN q,y,indx; if (!is_matvec_t(tx) && tx != t_VECSMALL) err(typeer,"gen_sort"); if (flag & cmp_C) tx = t_VECSMALL; else if (flag & cmp_IND) tx = t_VEC; y = cgetg(lx, tx); if (lx==1) return y; if (lx==2) { if (flag & cmp_C) y[1] = 1; else if (flag & cmp_IND) y[1] = un; else y[1] = lcopy((GEN)x[1]); return y; } if (!cmp) cmp = &longcmp; indx = (GEN) gpmalloc(lx*sizeof(long)); for (j=1; j>1)+1; for(;;) { if (l > 1) indxt = indx[--l]; else { indxt = indx[ir]; indx[ir] = indx[1]; if (--ir == 1) break; /* DONE */ } q = (GEN)x[indxt]; i = l; for (j=i<<1; j<=ir; j<<=1) { if (j= 0) break; indx[i] = indx[j]; i = j; } indx[i] = indxt; } indx[1] = indxt; if (flag & cmp_REV) { /* reverse order */ GEN indy = (GEN) gpmalloc(lx*sizeof(long)); for (j=1; jl) l=j; } t = typ(x); if (! is_matvec_t(t)) err(typeer,"vecsort"); for (j=1; j= cmp_C) err(flagerr,"vecsort"); return k? gen_vecsort(x,k,flag): gen_sort(x,flag, sort_fun(flag)); } GEN vecsort(GEN x, GEN k) { return gen_vecsort(x,k, 0); } GEN sindexsort(GEN x) { return gen_sort(x, cmp_IND | cmp_C, gcmp); } GEN sindexlexsort(GEN x) { return gen_sort(x, cmp_IND | cmp_C, lexcmp); } GEN indexsort(GEN x) { return gen_sort(x, cmp_IND, gcmp); } GEN indexlexsort(GEN x) { return gen_sort(x, cmp_IND, lexcmp); } GEN sort(GEN x) { return gen_sort(x, 0, gcmp); } GEN lexsort(GEN x) { return gen_sort(x, 0, lexcmp); } /* index of x in table T, 0 otherwise */ long tablesearch(GEN T, GEN x, int (*cmp)(GEN,GEN)) { long l=1,u=lg(T)-1,i,s; while (u>=l) { i = (l+u)>>1; s = cmp(x,(GEN)T[i]); if (!s) return i; if (s<0) u=i-1; else l=i+1; } return 0; } /* assume lg(x) = lg(y), x,y in Z^n */ int cmp_vecint(GEN x, GEN y) { long fl,i, lx = lg(x); for (i=1; i 0)? 1: -1) : cmp_vecint((GEN)x[2], (GEN)y[2]); } int cmp_prime_ideal(GEN x, GEN y) { int k = cmpii((GEN)x[1], (GEN)y[1]); return k? k: cmp_prime_over_p(x,y); }