/* $Id: bibli2.c,v 1.117 2006/04/05 16:42:33 kb 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. */ #include "pari.h" #include "paripriv.h" /*******************************************************************/ /** **/ /** 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; pari_sp av; GEN q,a,r; if (v<0) v = 0; if (n < 0) n = -n; if (n==0) return pol_1[v]; if (n==1) return pol_x[v]; q = cgetg(n+3, t_POL); r = q + n+2; a = int2n(n-1); gel(r--,0) = a; gel(r--,0) = gen_0; 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)); gel(r--,0) = a; gel(r--,0) = gen_0; } 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)); gel(r--,0) = a; gel(r--,0) = gen_0; } q[1] = evalsigne(1) | evalvarn(v); return q; } GEN addmulXn(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; pari_sp av, tetpil, lim; GEN p0,p1,p2; if (v<0) v = 0; if (n < 0) pari_err(talker,"negative degree in legendre"); if (n==0) return pol_1[v]; if (n==1) return pol_x[v]; p0=pol_1[v]; av=avma; lim=stack_lim(av,2); p1=gmul2n(pol_x[v],1); for (m=1; m1) pari_warn(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; pari_sp av=avma, tetpil; GEN yn,yd; if (n <= 0) pari_err(talker, "argument must be positive in polcyclo"); if (v<0) v = 0; yn = yd = pol_1[0]; for (d=1; d*d<=n; d++) { if (n%d) continue; q = n/d; m = mu(utoipos(q)); if (m) { /* y *= (x^d - 1) */ if (m>0) yn = addmulXn(yn, gneg(yn), d); else yd = addmulXn(yd, gneg(yd), d); } if (q==d) break; m = mu(utoipos(d)); if (m) { /* y *= (x^q - 1) */ if (m>0) yn = addmulXn(yn, gneg(yn), q); else yd = addmulXn(yd, gneg(yd), q); } } tetpil=avma; yn = gerepile(av,tetpil,RgX_div(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 pol_1[v]; p1 = cgetg(lx, t_VEC); code = evalsigne(1)|evalvarn(v); 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; gcoeff(m,i,1)= gen_1; if (q) { for (j=2; j<=I; j++) gcoeff(m,i,j) = gadd(gmul(qpow[j],gcoeff(m,i-1,j)), gcoeff(m,i-1,j-1)); } else { for (j=2; j<=I; j++) gcoeff(m,i,j) = addii(gcoeff(m,i-1,j), gcoeff(m,i-1,j-1)); } for ( ; j<=i; j++) gcoeff(m,i,j) = gcoeff(m,i,i+1-j); for ( ; j<=n; j++) gcoeff(m,i,j) = gen_0; } return gerepilecopy(av, m); } /********************************************************************/ /** **/ /** LAPLACE TRANSFORM (OF A SERIES) **/ /** **/ /********************************************************************/ GEN laplace(GEN x) { pari_sp av = avma; long i, l = lg(x), e = valp(x); GEN y, t; if (typ(x) != t_SER) pari_err(talker,"not a series in laplace"); if (e < 0) pari_err(talker,"negative valuation in laplace"); y = cgetg(l,t_SER); t = mpfact(e); y[1] = x[1]; for (i=2; i=lx) for ( ; i>=lx; i--) gel(y,i) = gen_0; for ( ; i>=2; i--) gel(y,i) = gcopy(gel(x,i)); break; case t_COMPLEX: case t_POLMOD: case t_POL: case t_RFRAC: case t_VEC: case t_COL: case t_MAT: y = init_gen_op(x, tx, &lx, &i); for (; i pr)? rtor(x,pr): x; case t_COMPLEX: case t_POLMOD: case t_POL: case t_RFRAC: case t_VEC: case t_COL: case t_MAT: y = init_gen_op(x, tx, &lx, &i); for (; i 0) { GEN z = subis(n,k); if (cmpis(z,k) < 0) { k = itos(z); avma = av; if (k <= 1) { if (k < 0) return gen_0; if (k == 0) return gen_1; return icopy(n); } } } /* k > 1 */ if (lgefint(n) == 3 && signe(n) > 0) { ulong N = itou(n); y = seq_umul(N-(ulong)k+1, N); } else { y = cgetg(k+1,t_VEC); for (i=1; i<=k; i++) gel(y,i) = subis(n,i-1); y = divide_conquer_prod(y,mulii); } y = diviiexact(y, mpfact(k)); } else { y = cgetg(k+1,t_VEC); for (i=1; i<=k; i++) gel(y,i) = gsubgs(n,i-1); y = divide_conquer_prod(y,gmul); y = gdiv(y, mpfact(k)); } 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] = gen_1; for (k=1; k <= d; k++) { pari_sp av = avma; C[k] = gerepileuptoint(av, diviiexact(mulsi(n-k+1, C[k-1]), utoipos(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); pari_sp av = avma, tetpil; GEN y, c, d, dy; if (!xa) { xa = cgetg(n+1, t_VEC); for (i=1; i<=n; i++) gel(xa,i) = utoipos(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(data,gel(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; } static int cmp_nodata(void *data, GEN x, GEN y) { int (*cmp)(GEN,GEN)=(int (*)(GEN,GEN)) data; return cmp(x,y); } long gen_search(GEN x, GEN y, long flag, int (*cmp)(GEN,GEN)) { return gen_search_aux(x, y, flag, (void *)cmp, cmp_nodata); } long setsearch(GEN x, GEN y, long flag) { pari_sp av = avma; long res; if (typ(y) != t_STR) y = GENtocanonicalstr(y); res=gen_search(x,y,flag,gcmp); avma=av; return res; } long ZV_search(GEN x, GEN y) { return gen_search(x, y, 0, cmpii); } GEN ZV_sort_uniq(GEN L) { long i, c, l = lg(L); pari_sp av = avma; GEN perm; if (l < 2) return cgetg(1, typ(L)); perm = gen_sort(L, cmp_C, &cmpii); L = vecpermute(L, perm); c = 1; for (i = 2; i < l; i++) if (!equalii(gel(L,i), gel(L,c))) L[++c] = L[i]; setlg(L, c+1); return gerepilecopy(av, L); } #if 0 GEN gen_union(GEN x, GEN y, int (*cmp)(GEN,GEN)) { if (typ(x) != t_VEC || typ(y) != t_VEC) pari_err(talker,"not a set in setunion"); } #endif GEN setunion(GEN x, GEN y) { pari_sp av=avma, tetpil; GEN z; if (typ(x) != t_VEC || typ(y) != t_VEC) pari_err(talker,"not a set in setunion"); z=shallowconcat(x,y); tetpil=avma; return gerepile(av,tetpil,gtoset(z)); } GEN setintersect(GEN x, GEN y) { long i, lx, c; pari_sp av=avma; GEN z; if (!setisset(x) || !setisset(y)) pari_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)) pari_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 < lx && gcmp0(gel(x,i))) i++; return i; } GEN dirmul(GEN x, GEN y) { pari_sp av = avma, lim = stack_lim(av, 1); long lx, ly, lz, dx, dy, i, j, k; GEN z; if (typ(x)!=t_VEC || typ(y)!=t_VEC) pari_err(typeer,"dirmul"); dx = dirval(x); lx = lg(x); dy = dirval(y); ly = lg(y); if (ly-dy < lx-dx) { swap(x,y); lswap(lx,ly); lswap(dx,dy); } lz = min(lx*dy,ly*dx); z = zerovec(lz-1); for (j=dx; j=a+2; i--) v[i] = v[i-1]; v[i] = r; } avma = av; for (i=1; i<=n; i++) gel(v,i) = stoi(v[i]); return v; } GEN permtonum(GEN x) { long lx=lg(x)-1, n=lx, last, ind, tx = typ(x); pari_sp av=avma; GEN ary,res; if (!is_vec_t(tx)) pari_err(talker,"not a vector in permtonum"); ary = cgetg(lx+1,t_VECSMALL); for (ind=1; ind<=lx; ind++) { res = gel(++x, 0); if (typ(res) != t_INT) pari_err(typeer,"permtonum"); ary[ind] = itos(res); } ary++; res = gen_0; for (last=lx; last>0; last--) { lx--; ind = lx; while (ind>0 && ary[ind] != last) ind--; res = addis(mulis(res,last), ind); while (ind++(b)?1:(a)<(b)?-1:0) int pari_compare_lg(GEN x, GEN y) { return icmp(lg(x),lg(y)); } int pari_compare_long(long *a,long *b) { return icmp(*a,*b); } static int pari_compare_small(GEN x, GEN y) { return icmp((long)x,(long)y); } #undef icmp struct veccmp_s { long lk; GEN k; int (*cmp)(GEN,GEN); }; static int veccmp(void *data, GEN x, GEN y) { struct veccmp_s *v=(struct veccmp_s *) data; long i,s; for (i=1; ilk; i++) { s = v->cmp(gel(x,v->k[i]), gel(y,v->k[i])); if (s) return s; } return 0; } static GEN gen_sortspec(GEN v, long n, void *data, int (*cmp)(void*,GEN,GEN)) { long nx=n>>1, ny=n-nx; long m, ix, iy; GEN x, y; GEN w=cgetg(n+1,t_VECSMALL); if (n<=2) { if (n==1) w[1]=1; else if (n==2) { if (cmp(data,gel(v,1),gel(v,2))<=0) { w[1]=1; w[2]=2; } else { w[1]=2; w[2]=1; } } return w; } x=gen_sortspec(v,nx,data,cmp); y=gen_sortspec(v+nx,ny,data,cmp); for (m=1, ix=1, iy=1; ix<=nx && iy<=ny; ) if (cmp(data, gel(v,x[ix]), gel(v,y[iy]+nx))<=0) w[m++]=x[ix++]; else w[m++]=y[iy++]+nx; for(;ix<=nx;) w[m++]=x[ix++]; for(;iy<=ny;) w[m++]=y[iy++]+nx; avma = (pari_sp) w; return w; } /* 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_aux(GEN x, long flag, void *data, int (*cmp)(void*,GEN,GEN)) { long i, j; long tx = typ(x), lx = lg(x); GEN y; if (tx == t_LIST) { lx = lgeflist(x)-1; tx = t_VEC; x++; } if (!is_matvec_t(tx) && tx != t_VECSMALL) pari_err(typeer,"gen_sort"); if (flag & cmp_C) tx = t_VECSMALL; else if (flag & cmp_IND) tx = t_VEC; if (lx<=2) { y=cgetg(lx,tx); if (lx==1) return y; if (lx==2) { if (flag & cmp_C) y[1] = 1; else if (flag & cmp_IND) gel(y,1) = gen_1; else if (tx == t_VECSMALL) y[1] = x[1]; else gel(y,1) = gcopy(gel(x,1)); return y; } } y = gen_sortspec(x,lx-1,data,cmp); if (flag & cmp_REV) { /* reverse order */ for (j=1; j<=((lx-1)>>1); j++) { long z=y[j]; y[j]=y[lx-j]; y[lx-j]=z; } } if (flag & cmp_C) return y; settyp(y,tx); if (flag & cmp_IND) for (i=1; il) l=j; } t = typ(x); if (! is_matvec_t(t)) pari_err(typeer,"vecsort"); for (j=1; j= cmp_C) pari_err(flagerr,"vecsort"); if (k) return gen_vecsort(x, k, flag); return gen_sort(x, flag, (typ(x) == t_VECSMALL)? pari_compare_small: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,gel(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(gel(x,2), gel(y,2)); } int cmp_prime_ideal(GEN x, GEN y) { int k = cmpii(gel(x,1), gel(y,1)); return k? k: cmp_prime_over_p(x,y); }