/* $Id: bibli2.c,v 1.23 2001/10/01 12:11:29 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" /********************************************************************/ /** **/ /** DEVELOPPEMENTS LIMITES **/ /** **/ /********************************************************************/ GEN tayl(GEN x, long v, long precdl) { long tetpil,i,vx = gvar9(x), av=avma; GEN p1,y; if (v <= vx) { long p1[] = { evaltyp(t_SER)|m_evallg(2), 0 }; p1[1] = evalvalp(precdl) | evalvarn(v); return gadd(p1,x); } p1=cgetg(v+2,t_VEC); for (i=0; i1; 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 av,tetpil,m,lim; GEN p0,p1,p2; if (v<0) v = 0; 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 av=avma,tetpil,d,q,m; 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; if (n == 1) err(talker,"degree does not divide phi(n) in subcyclo"); fa = factor(stoi(n)); p = itos(gmael(fa,1,1)); al= itos(gmael(fa,2,1)); if (lg((GEN)fa[1]) > 2 || (p==2 && al>2)) err(impl,"subcyclo in non-cyclic case"); if (d < n) { k = 1 + svaluation(d,p,&i); if (k>TWOPOTBITS_IN_LONG); if (prec>1; for (i=2; 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) { ulong 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); } /********************************************************************/ /** **/ /** POLYNOMIAL INTERPOLATION **/ /** **/ /********************************************************************/ /* assume n > 1 */ GEN polint_i(GEN xa, GEN ya, GEN x, long n, GEN *ptdy) { long av = avma,tetpil,i,m, ns=0, tx=typ(x); 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 = gcmp((GEN)x[j],y); if (!fl) { avma=av; return flag? 0: j; } if (fl<0) li=j+1; else ri=j-1; } while (ri>=li); avma=av; if (!flag) return 0; return (fl<0)? j+1: j; } GEN setunion(GEN x, GEN y) { long 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 av=avma,i,lx,c; 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; 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 = (long)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) { ulong 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 av=avma, lx=lg(x)-1, n=lx, last, ind, tx = typ(x); 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++ (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 * For private use: * 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) { l--; indxt = indx[l]; } else { indxt = indx[ir]; indx[ir]=indx[1]; ir--; if (ir == 1) { indx[1] = indxt; if (flag & cmp_C) for (i=1; i 0) j++; if (cmp(q,(GEN)x[indx[j]]) <= 0) break; indx[i]=indx[j]; i=j; } else for (j=i<<1; j<=ir; j<<=1) { if (j= 0) break; indx[i]=indx[j]; i=j; } indx[i]=indxt; } } #define sort_fun(flag) ((flag & cmp_LEX)? &lexcmp: &gcmp) GEN gen_vecsort(GEN x, GEN k, long flag) { long i,j,l,t, lx = lg(x), tmp[2]; if (lx<=2) return gen_sort(x,flag,sort_fun(flag)); t = typ(k); vcmp_cmp = sort_fun(flag); if (t==t_INT) { tmp[1] = (long)k; k = tmp; vcmp_lk = 2; } else { if (! is_vec_t(t)) err(talker,"incorrect lextype in vecsort"); vcmp_lk = lg(k); } l = 0; vcmp_k = (GEN)gpmalloc(vcmp_lk * sizeof(long)); for (i=1; il) 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); }