[BACK]Return to bibli2.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari-2.2 / src / basemath

Annotation of OpenXM_contrib/pari-2.2/src/basemath/bibli2.c, Revision 1.1.1.1

1.1       noro        1: /* $Id: bibli2.c,v 1.23 2001/10/01 12:11:29 karim Exp $
                      2:
                      3: Copyright (C) 2000  The PARI group.
                      4:
                      5: This file is part of the PARI/GP package.
                      6:
                      7: PARI/GP is free software; you can redistribute it and/or modify it under the
                      8: terms of the GNU General Public License as published by the Free Software
                      9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
                     10: ANY WARRANTY WHATSOEVER.
                     11:
                     12: Check the License for details. You should have received a copy of it, along
                     13: with the package; see the file 'COPYING'. If not, write to the Free Software
                     14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
                     15:
                     16: /********************************************************************/
                     17: /**                                                                **/
                     18: /**                  BIBLIOTHEQUE  MATHEMATIQUE                    **/
                     19: /**                     (deuxieme partie)                          **/
                     20: /**                                                                **/
                     21: /********************************************************************/
                     22: #include "pari.h"
                     23:
                     24: /********************************************************************/
                     25: /**                                                                **/
                     26: /**                 DEVELOPPEMENTS  LIMITES                        **/
                     27: /**                                                                **/
                     28: /********************************************************************/
                     29:
                     30: GEN
                     31: tayl(GEN x, long v, long precdl)
                     32: {
                     33:   long tetpil,i,vx = gvar9(x), av=avma;
                     34:   GEN p1,y;
                     35:
                     36:   if (v <= vx)
                     37:   {
                     38:     long p1[] = { evaltyp(t_SER)|m_evallg(2), 0 };
                     39:     p1[1] = evalvalp(precdl) | evalvarn(v);
                     40:     return gadd(p1,x);
                     41:   }
                     42:   p1=cgetg(v+2,t_VEC);
                     43:   for (i=0; i<v; i++) p1[i+1]=lpolx[i];
                     44:   p1[vx+1]=lpolx[v]; p1[v+1]=lpolx[vx];
                     45:   y = tayl(changevar(x,p1), vx,precdl); tetpil=avma;
                     46:   return gerepile(av,tetpil, changevar(y,p1));
                     47: }
                     48:
                     49: GEN
                     50: grando0(GEN x, long n, long do_clone)
                     51: {
                     52:   long m, v, tx=typ(x);
                     53:   GEN y;
                     54:
                     55:   if (gcmp0(x)) err(talker,"zero argument in O()");
                     56:   if (tx == t_INT)
                     57:   {
                     58:     if (!gcmp1(x)) /* bug 3 + O(1). We suppose x is a truc() */
                     59:     {
                     60:       y=cgetg(5,t_PADIC);
                     61:       y[1] = evalvalp(n) | evalprecp(0);
                     62:       y[2] = do_clone? lclone(x): licopy(x);
                     63:       y[3] = un; y[4] = zero; return y;
                     64:     }
                     65:     v=0; m=0; /* 1 = x^0 */
                     66:   }
                     67:   else
                     68:   {
                     69:     if (tx != t_POL && ! is_rfrac_t(tx))
                     70:       err(talker,"incorrect argument in O()");
                     71:     v=gvar(x); m=n*gval(x,v);
                     72:   }
                     73:   return zeroser(v,m);
                     74: }
                     75:
                     76: /*******************************************************************/
                     77: /**                                                               **/
                     78: /**                      SPECIAL POLYNOMIALS                      **/
                     79: /**                                                               **/
                     80: /*******************************************************************/
                     81: #ifdef LONG_IS_64BIT
                     82: # define SQRTVERYBIGINT 3037000500   /* ceil(sqrt(VERYBIGINT)) */
                     83: #else
                     84: # define SQRTVERYBIGINT 46341
                     85: #endif
                     86:
                     87: /* Tchebichev polynomial: T0=1; T1=X; T(n)=2*X*T(n-1)-T(n-2)
                     88:  * T(n) = (n/2) sum_{k=0}^{n/2} a_k x^(n-2k)
                     89:  *   where a_k = (-1)^k 2^(n-2k) (n-k-1)! / k!(n-2k)! is an integer
                     90:  *   and a_0 = 2^(n-1), a_k / a_{k-1} = - (n-2k+2)(n-2k+1) / 4k(n-k) */
                     91: GEN
                     92: tchebi(long n, long v) /* Assume 4*n < VERYBIGINT */
                     93: {
                     94:   long av,k,l;
                     95:   GEN q,a,r;
                     96:
                     97:   if (v<0) v = 0;
                     98:   if (n==0) return polun[v];
                     99:   if (n==1) return polx[v];
                    100:
                    101:   q = cgetg(n+3, t_POL); r = q + n+2;
                    102:   a = shifti(gun, n-1);
                    103:   *r-- = (long)a;
                    104:   *r-- = zero;
                    105:   if (n < SQRTVERYBIGINT)
                    106:     for (k=1,l=n; l>1; k++,l-=2)
                    107:     {
                    108:       av = avma;
                    109:       a = divis(mulis(a, l*(l-1)), 4*k*(n-k));
                    110:       a = gerepileuptoint(av, negi(a));
                    111:       *r-- = (long)a;
                    112:       *r-- = zero;
                    113:     }
                    114:   else
                    115:     for (k=1,l=n; l>1; k++,l-=2)
                    116:     {
                    117:       av = avma;
                    118:       a = mulis(mulis(a, l), l-1);
                    119:       a = divis(divis(a, 4*k), n-k);
                    120:       a = gerepileuptoint(av, negi(a));
                    121:       *r-- = (long)a;
                    122:       *r-- = zero;
                    123:     }
                    124:   q[1] = evalsigne(1) | evalvarn(v) | evallgef(n+3);
                    125:   return q;
                    126: }
                    127:
                    128: GEN addshiftw(GEN x, GEN y, long d);
                    129: /* Legendre polynomial */
                    130: /* L0=1; L1=X; (n+1)*L(n+1)=(2*n+1)*X*L(n)-n*L(n-1) */
                    131: GEN
                    132: legendre(long n, long v)
                    133: {
                    134:   long av,tetpil,m,lim;
                    135:   GEN p0,p1,p2;
                    136:
                    137:   if (v<0) v = 0;
                    138:   if (n==0) return polun[v];
                    139:   if (n==1) return polx[v];
                    140:
                    141:   p0=polun[v]; av=avma; lim=stack_lim(av,2);
                    142:   p1=gmul2n(polx[v],1);
                    143:   for (m=1; m<n; m++)
                    144:   {
                    145:     p2 = addshiftw(gmulsg(4*m+2,p1), gmulsg(-4*m,p0), 1);
                    146:     setvarn(p2,v);
                    147:     p0 = p1; tetpil=avma; p1 = gdivgs(p2,m+1);
                    148:     if (low_stack(lim, stack_lim(av,2)))
                    149:     {
                    150:       GEN *gptr[2];
                    151:       if(DEBUGMEM>1) err(warnmem,"legendre");
                    152:       p0=gcopy(p0); gptr[0]=&p0; gptr[1]=&p1;
                    153:       gerepilemanysp(av,tetpil,gptr,2);
                    154:     }
                    155:   }
                    156:   tetpil=avma; return gerepile(av,tetpil,gmul2n(p1,-n));
                    157: }
                    158:
                    159: /* cyclotomic polynomial */
                    160: GEN
                    161: cyclo(long n, long v)
                    162: {
                    163:   long av=avma,tetpil,d,q,m;
                    164:   GEN yn,yd;
                    165:
                    166:   if (n<=0) err(arither2);
                    167:   if (v<0) v = 0;
                    168:   yn = yd = polun[0];
                    169:   for (d=1; d*d<=n; d++)
                    170:   {
                    171:     if (n%d) continue;
                    172:     q=n/d;
                    173:     m = mu(stoi(q));
                    174:     if (m)
                    175:     { /* y *= (x^d - 1) */
                    176:       if (m>0) yn = addshiftw(yn, gneg(yn), d);
                    177:       else     yd = addshiftw(yd, gneg(yd), d);
                    178:     }
                    179:     if (q==d) break;
                    180:     m = mu(stoi(d));
                    181:     if (m)
                    182:     { /* y *= (x^q - 1) */
                    183:       if (m>0) yn = addshiftw(yn, gneg(yn), q);
                    184:       else     yd = addshiftw(yd, gneg(yd), q);
                    185:     }
                    186:   }
                    187:   tetpil=avma; yn = gerepile(av,tetpil,gdeuc(yn,yd));
                    188:   setvarn(yn,v); return yn;
                    189: }
                    190:
                    191: /* compute prod (L*x ± a[i]) */
                    192: GEN
                    193: roots_to_pol_intern(GEN L, GEN a, long v, int plus)
                    194: {
                    195:   long i,k,lx = lg(a), code;
                    196:   GEN p1,p2;
                    197:   if (lx == 1) return polun[v];
                    198:   p1 = cgetg(lx, t_VEC);
                    199:   code = evalsigne(1)|evalvarn(v)|evallgef(5);
                    200:   for (k=1,i=1; i<lx-1; i+=2)
                    201:   {
                    202:     p2 = cgetg(5,t_POL); p1[k++] = (long)p2;
                    203:     p2[2] = lmul((GEN)a[i],(GEN)a[i+1]);
                    204:     p2[3] = ladd((GEN)a[i],(GEN)a[i+1]);
                    205:     if (plus == 0) p2[3] = lneg((GEN)p2[3]);
                    206:     p2[4] = (long)L; p2[1] = code;
                    207:   }
                    208:   if (i < lx)
                    209:   {
                    210:     p2 = cgetg(4,t_POL); p1[k++] = (long)p2;
                    211:     p2[1] = code = evalsigne(1)|evalvarn(v)|evallgef(4);
                    212:     p2[2] = plus? a[i]: lneg((GEN)a[i]);
                    213:     p2[3] = (long)L;
                    214:   }
                    215:   setlg(p1, k); return divide_conquer_prod(p1, gmul);
                    216: }
                    217:
                    218: GEN
                    219: roots_to_pol(GEN a, long v)
                    220: {
                    221:   return roots_to_pol_intern(gun,a,v,0);
                    222: }
                    223:
                    224: /* prod_{i=1..r1} (x - a[i]) prod_{i=1..r2} (x - a[i])(x - conj(a[i]))*/
                    225: GEN
                    226: roots_to_pol_r1r2(GEN a, long r1, long v)
                    227: {
                    228:   long i,k,lx = lg(a), code;
                    229:   GEN p1;
                    230:   if (lx == 1) return polun[v];
                    231:   p1 = cgetg(lx, t_VEC);
                    232:   code = evalsigne(1)|evalvarn(v)|evallgef(5);
                    233:   for (k=1,i=1; i<r1; i+=2)
                    234:   {
                    235:     GEN p2 = cgetg(5,t_POL); p1[k++] = (long)p2;
                    236:     p2[2] = lmul((GEN)a[i],(GEN)a[i+1]);
                    237:     p2[3] = lneg(gadd((GEN)a[i],(GEN)a[i+1]));
                    238:     p2[4] = un; p2[1] = code;
                    239:   }
                    240:   if (i < r1+1)
                    241:     p1[k++] = ladd(polx[v], gneg((GEN)a[i]));
                    242:   for (i=r1+1; i<lx; i++)
                    243:   {
                    244:     GEN p2 = cgetg(5,t_POL); p1[k++] = (long)p2;
                    245:     p2[2] = lnorm((GEN)a[i]);
                    246:     p2[3] = lneg(gtrace((GEN)a[i]));
                    247:     p2[4] = un; p2[1] = code;
                    248:   }
                    249:   setlg(p1, k); return divide_conquer_prod(p1, gmul);
                    250: }
                    251:
                    252: /* finds an equation for the d-th degree subfield of Q(zeta_n).
                    253:  * (Z/nZ)* must be cyclic.
                    254:  */
                    255: GEN
                    256: subcyclo(GEN nn, GEN dd, int v)
                    257: {
                    258:   long av=avma,tetpil,i,j,k,prec,q,d,p,pp,al,n,ex0,ex,aad,aa;
                    259:   GEN a,z,pol,fa,powz,alpha;
                    260:
                    261:   if (typ(dd)!=t_INT || signe(dd)<=0) err(typeer,"subcyclo");
                    262:   if (is_bigint(dd)) err(talker,"degree too large in subcyclo");
                    263:   if (typ(nn)!=t_INT || signe(nn)<=0) err(typeer,"subcyclo");
                    264:   if (v<0) v = 0;
                    265:   d=itos(dd); if (d==1) return polx[v];
                    266:   if (is_bigint(nn)) err(impl,"subcyclo for huge cyclotomic fields");
                    267:   n = nn[2]; if ((n & 3) == 2) n >>= 1;
                    268:   if (n == 1) err(talker,"degree does not divide phi(n) in subcyclo");
                    269:   fa = factor(stoi(n));
                    270:   p = itos(gmael(fa,1,1));
                    271:   al= itos(gmael(fa,2,1));
                    272:   if (lg((GEN)fa[1]) > 2 || (p==2 && al>2))
                    273:     err(impl,"subcyclo in non-cyclic case");
                    274:   if (d < n)
                    275:   {
                    276:     k = 1 + svaluation(d,p,&i);
                    277:     if (k<al) { al = k; nn = gpowgs(stoi(p),al); n = nn[2]; }
                    278:   }
                    279:   avma=av; q = (n/p)*(p-1); /* = phi(n) */
                    280:   if (q == d) return cyclo(n,v);
                    281:   if (q % d) err(talker,"degree does not divide phi(n) in subcyclo");
                    282:   q /= d;
                    283:   if (p==2)
                    284:   {
                    285:     pol = powgi(polx[v],gdeux); pol[2]=un; /* replace gzero */
                    286:     return pol; /* = x^2 + 1 */
                    287:   }
                    288:   a=gener(stoi(n)); aa = mael(a,2,2);
                    289:   a=gpowgs(a,d); aad = mael(a,2,2);
                    290: #if 1
                    291:   prec = expi(binome(stoi(d*q-1),d)) + expi(stoi(n));
                    292:   prec = 2 + (prec>>TWOPOTBITS_IN_LONG);
                    293:   if (prec<DEFAULTPREC) prec = DEFAULTPREC;
                    294:   if (DEBUGLEVEL) fprintferr("subcyclo prec = %ld\n",prec);
                    295:   z = cgetg(3,t_COMPLEX); a=mppi(prec); setexpo(a,2); /* a = 2\pi */
                    296:   gsincos(divrs(a,n),(GEN*)(z+2),(GEN*)(z+1),prec); /* z = e_n(1) */
                    297:   powz = cgetg(n,t_VEC); powz[1] = (long)z;
                    298:   k = (n+3)>>1;
                    299:   for (i=2; i<k; i++) powz[i] = lmul(z,(GEN)powz[i-1]);
                    300:   if ((q&1) == 0) /* totally real field, take real part */
                    301:   {
                    302:     for (i=1; i<k; i++) powz[i] = mael(powz,i,1);
                    303:     for (   ; i<n; i++) powz[i] = powz[n-i];
                    304:   }
                    305:   else
                    306:     for (   ; i<n; i++) powz[i] = lconj((GEN)powz[n-i]);
                    307:
                    308:   alpha = cgetg(d+1,t_VEC) + 1; pol=gun;
                    309:   for (ex0=1,k=0; k<d; k++, ex0=(ex0*aa)%n)
                    310:   {
                    311:     GEN p1 = gzero;
                    312:     long av1 = avma; (void)new_chunk(2*prec + 3);
                    313:     for (ex=ex0,i=0; i<q; i++)
                    314:     {
                    315:       for (pp=ex,j=0; j<al; j++)
                    316:       {
                    317:         p1 = gadd(p1,(GEN)powz[pp]);
                    318:         pp = mulssmod(pp,p, n);
                    319:       }
                    320:       ex = mulssmod(ex,aad, n);
                    321:     }
                    322:    /* p1 = sum z^{p^k*h}, k = 0..al-1, h runs through the subgroup of order
                    323:     * q = phi(n)/d of (Z/nZ)^* */
                    324:     avma = av1; alpha[k] = lneg(p1);
                    325:   }
                    326:   pol = roots_to_pol_intern(gun,alpha-1,v, 1);
                    327:   if (q&1) pol=greal(pol); /* already done otherwise */
                    328:   tetpil=avma; return gerepile(av,tetpil,ground(pol));
                    329: #else
                    330: {
                    331:   /* exact computation (much slower) */
                    332:   GEN p1 = cgetg(n+2,t_POL)+2; for (i=0; i<n; i++) p1[i]=0;
                    333:   for (ex=1,i=0; i<q; i++, ex=(ex*aad)%n)
                    334:     for (pp=ex,j=0; j<al; j++, pp=(pp*p)%n) p1[pp]++;
                    335:   for (i=0; i<n; i++) p1[i] = lstoi(p1[i]);
                    336:   p1 = normalizepol_i(p1-2,n+2); setvarn(p1,v);
                    337:   z = cyclo(n,v); a = caract2(z,gres(p1,z),v);
                    338:   a = gdeuc(a, modulargcd(a,derivpol(a)));
                    339:   return gerepileupto(av, a);
                    340: }
                    341: #endif
                    342: }
                    343:
                    344: /********************************************************************/
                    345: /**                                                                **/
                    346: /**                  HILBERT & PASCAL MATRICES                     **/
                    347: /**                                                                **/
                    348: /********************************************************************/
                    349: GEN
                    350: mathilbert(long n) /* Hilbert matrix of order n */
                    351: {
                    352:   long i,j;
                    353:   GEN a,p;
                    354:
                    355:   if (n<0) n = 0;
                    356:   p = cgetg(n+1,t_MAT);
                    357:   for (j=1; j<=n; j++)
                    358:   {
                    359:     p[j]=lgetg(n+1,t_COL);
                    360:     for (i=1+(j==1); i<=n; i++)
                    361:     {
                    362:       a=cgetg(3,t_FRAC); a[1]=un; a[2]=lstoi(i+j-1);
                    363:       coeff(p,i,j)=(long)a;
                    364:     }
                    365:   }
                    366:   if ( n ) mael(p,1,1)=un;
                    367:   return p;
                    368: }
                    369:
                    370: /* q-Pascal triangle = (choose(i,j)_q) (ordinary binomial if q = NULL) */
                    371: GEN
                    372: matqpascal(long n, GEN q)
                    373: {
                    374:   long i,j,I, av = avma;
                    375:   GEN m, *qpow = NULL; /* gcc -Wall */
                    376:
                    377:   if (n<0) n = -1;
                    378:   n++; m = cgetg(n+1,t_MAT);
                    379:   for (j=1; j<=n; j++) m[j] = lgetg(n+1,t_COL);
                    380:   if (q)
                    381:   {
                    382:     I = (n+1)/2;
                    383:     if (I > 1) { qpow = (GEN*)new_chunk(I+1); qpow[2]=q; }
                    384:     for (j=3; j<=I; j++) qpow[j] = gmul(q, qpow[j-1]);
                    385:   }
                    386:   for (i=1; i<=n; i++)
                    387:   {
                    388:     I = (i+1)/2; coeff(m,i,1)=un;
                    389:     if (q)
                    390:     {
                    391:       for (j=2; j<=I; j++)
                    392:         coeff(m,i,j) = ladd(gmul(qpow[j],gcoeff(m,i-1,j)), gcoeff(m,i-1,j-1));
                    393:     }
                    394:     else
                    395:     {
                    396:       for (j=2; j<=I; j++)
                    397:         coeff(m,i,j) = laddii(gcoeff(m,i-1,j), gcoeff(m,i-1,j-1));
                    398:     }
                    399:     for (   ; j<=i; j++) coeff(m,i,j) = coeff(m,i,i+1-j);
                    400:     for (   ; j<=n; j++) coeff(m,i,j) = zero;
                    401:   }
                    402:   return gerepilecopy(av, m);
                    403: }
                    404:
                    405: /********************************************************************/
                    406: /**                                                                **/
                    407: /**                  LAPLACE TRANSFORM (OF A SERIES)               **/
                    408: /**                                                                **/
                    409: /********************************************************************/
                    410:
                    411: GEN
                    412: laplace(GEN x)
                    413: {
                    414:   ulong av = avma;
                    415:   long i,l,ec;
                    416:   GEN y,p1;
                    417:
                    418:   if (typ(x)!=t_SER) err(talker,"not a series in laplace");
                    419:   if (gcmp0(x)) return gcopy(x);
                    420:
                    421:   ec = valp(x);
                    422:   if (ec<0) err(talker,"negative valuation in laplace");
                    423:   l=lg(x); y=cgetg(l,t_SER);
                    424:   p1=mpfact(ec); y[1]=x[1];
                    425:   for (i=2; i<l; i++)
                    426:   {
                    427:     y[i]=lmul(p1,(GEN)x[i]);
                    428:     ec++; p1=mulsi(ec,p1);
                    429:   }
                    430:   return gerepilecopy(av,y);
                    431: }
                    432:
                    433: /********************************************************************/
                    434: /**                                                                **/
                    435: /**              CONVOLUTION PRODUCT (OF TWO SERIES)               **/
                    436: /**                                                                **/
                    437: /********************************************************************/
                    438:
                    439: GEN
                    440: convol(GEN x, GEN y)
                    441: {
                    442:   long l,i,j,v, vx=varn(x), lx=lg(x), ly=lg(y), ex=valp(x), ey=valp(y);
                    443:   GEN z;
                    444:
                    445:   if (typ(x) != t_SER || typ(y) != t_SER)
                    446:     err(talker,"not a series in convol");
                    447:   if (gcmp0(x) || gcmp0(y))
                    448:     err(talker,"zero series in convol");
                    449:   if (varn(y) != vx)
                    450:     err(talker,"different variables in convol");
                    451:   v=ex; if (ey>v) v=ey;
                    452:   l=ex+lx; i=ey+ly; if (i<l) l=i;
                    453:   l -= v; if (l<3) err(talker,"non significant result in convol");
                    454:   for (i=v+2; i < v+l; i++)
                    455:     if (!gcmp0((GEN)x[i-ex]) && !gcmp0((GEN)y[i-ey])) { i++; break; }
                    456:   if (i == l+v) return zeroser(vx, v+l-2);
                    457:
                    458:   z = cgetg(l-i+3+v,t_SER);
                    459:   z[1] = evalsigne(1) | evalvalp(i-3) | evalvarn(vx);
                    460:   for (j=i-1; j<l+v; j++) z[j-i+3]=lmul((GEN)x[j-ex],(GEN)y[j-ey]);
                    461:   return z;
                    462: }
                    463:
                    464: /******************************************************************/
                    465: /**                                                              **/
                    466: /**                       PRECISION CHANGES                      **/
                    467: /**                                                              **/
                    468: /******************************************************************/
                    469:
                    470: GEN
                    471: gprec(GEN x, long l)
                    472: {
                    473:   long tx=typ(x),lx=lg(x),i,pr;
                    474:   GEN y;
                    475:
                    476:   if (l<=0) err(talker,"precision<=0 in gprec");
                    477:   switch(tx)
                    478:   {
                    479:     case t_REAL:
                    480:       pr = (long) (l*pariK1+3); y=cgetr(pr); affrr(x,y); break;
                    481:
                    482:     case t_PADIC:
                    483:       y=cgetg(lx,tx); copyifstack(x[2], y[2]);
                    484:       if (!signe(x[4]))
                    485:       {
                    486:        y[1]=evalvalp(l+precp(x)) | evalprecp(0);
                    487:        y[3]=un; y[4]=zero; return y;
                    488:       }
                    489:       y[1]=x[1]; setprecp(y,l);
                    490:       y[3]=lpuigs((GEN)x[2],l);
                    491:       y[4]=lmodii((GEN)x[4],(GEN)y[3]);
                    492:       break;
                    493:
                    494:     case t_SER:
                    495:       if (gcmp0(x)) return zeroser(varn(x), l);
                    496:       y=cgetg(l+2,t_SER); y[1]=x[1]; l++; i=l;
                    497:       if (l>=lx)
                    498:        for ( ; i>=lx; i--) y[i]=zero;
                    499:       for ( ; i>=2; i--) y[i]=lcopy((GEN)x[i]);
                    500:       break;
                    501:
                    502:     case t_POL:
                    503:       lx=lgef(x); y=cgetg(lx,tx); y[1]=x[1];
                    504:       for (i=2; i<lx; i++) y[i]=lprec((GEN)x[i],l);
                    505:       break;
                    506:
                    507:     case t_COMPLEX: case t_POLMOD: case t_RFRAC: case t_RFRACN:
                    508:     case t_VEC: case t_COL: case t_MAT:
                    509:       y=cgetg(lx,tx);
                    510:       for (i=1; i<lx; i++) y[i]=lprec((GEN)x[i],l);
                    511:       break;
                    512:     default: y=gcopy(x);
                    513:   }
                    514:   return y;
                    515: }
                    516:
                    517: /* internal: precision given in word length (including codewords) */
                    518: GEN
                    519: gprec_w(GEN x, long pr)
                    520: {
                    521:   long tx=typ(x),lx,i;
                    522:   GEN y;
                    523:
                    524:   switch(tx)
                    525:   {
                    526:     case t_REAL:
                    527:       y=cgetr(pr); affrr(x,y); break;
                    528:
                    529:     case t_POL:
                    530:       lx=lgef(x); y=cgetg(lx,tx); y[1]=x[1];
                    531:       for (i=2; i<lx; i++) y[i]=(long)gprec_w((GEN)x[i],pr);
                    532:       break;
                    533:
                    534:     case t_COMPLEX: case t_POLMOD: case t_RFRAC: case t_RFRACN:
                    535:     case t_VEC: case t_COL: case t_MAT:
                    536:       lx=lg(x); y=cgetg(lx,tx);
                    537:       for (i=1; i<lx; i++) y[i]=(long)gprec_w((GEN)x[i],pr);
                    538:       break;
                    539:     default: y=gprec(x,pr);
                    540:   }
                    541:   return y;
                    542: }
                    543:
                    544: /*******************************************************************/
                    545: /**                                                               **/
                    546: /**                     RECIPROCAL POLYNOMIAL                     **/
                    547: /**                                                               **/
                    548: /*******************************************************************/
                    549:
                    550: GEN
                    551: polrecip(GEN x)
                    552: {
                    553:   long lx=lgef(x),i,j;
                    554:   GEN y;
                    555:
                    556:   if (typ(x) != t_POL) err(typeer,"polrecip");
                    557:   y=cgetg(lx,t_POL); y[1]=x[1];
                    558:   for (i=2,j=lx-1; i<lx; i++,j--) y[i]=lcopy((GEN)x[j]);
                    559:   return normalizepol_i(y,lx);
                    560: }
                    561:
                    562: /* as above. Internal (don't copy or normalize) */
                    563: GEN
                    564: polrecip_i(GEN x)
                    565: {
                    566:   long lx=lgef(x),i,j;
                    567:   GEN y;
                    568:
                    569:   y=cgetg(lx,t_POL); y[1]=x[1];
                    570:   for (i=2,j=lx-1; i<lx; i++,j--) y[i]=x[j];
                    571:   return y;
                    572: }
                    573:
                    574: /*******************************************************************/
                    575: /**                                                               **/
                    576: /**                      BINOMIAL COEFFICIENTS                    **/
                    577: /**                                                               **/
                    578: /*******************************************************************/
                    579:
                    580: GEN
                    581: binome(GEN n, long k)
                    582: {
                    583:   long av,i;
                    584:   GEN y;
                    585:
                    586:   if (k <= 1)
                    587:   {
                    588:     if (is_noncalc_t(typ(n))) err(typeer,"binomial");
                    589:     if (k < 0) return gzero;
                    590:     if (k == 0) return gun;
                    591:     return gcopy(n);
                    592:   }
                    593:   av = avma; y = n;
                    594:   if (typ(n) == t_INT)
                    595:   {
                    596:     if (signe(n) > 0)
                    597:     {
                    598:       GEN z = subis(n,k);
                    599:       if (cmpis(z,k) < 0) k = itos(z);
                    600:       avma = av;
                    601:       if (k <= 1)
                    602:       {
                    603:         if (k < 0) return gzero;
                    604:         if (k == 0) return gun;
                    605:         return gcopy(n);
                    606:       }
                    607:     }
                    608:     for (i=2; i<=k; i++)
                    609:       y = gdivgs(gmul(y,addis(n,i-1-k)), i);
                    610:   }
                    611:   else
                    612:   {
                    613:     for (i=2; i<=k; i++)
                    614:       y = gdivgs(gmul(y,gaddgs(n,i-1-k)), i);
                    615:   }
                    616:   return gerepileupto(av, y);
                    617: }
                    618:
                    619: /********************************************************************/
                    620: /**                                                                **/
                    621: /**                  POLYNOMIAL INTERPOLATION                      **/
                    622: /**                                                                **/
                    623: /********************************************************************/
                    624: /* assume n > 1 */
                    625: GEN
                    626: polint_i(GEN xa, GEN ya, GEN x, long n, GEN *ptdy)
                    627: {
                    628:   long av = avma,tetpil,i,m, ns=0, tx=typ(x);
                    629:   GEN den,ho,hp,w,y,c,d,dy;
                    630:
                    631:   if (!xa)
                    632:   {
                    633:     xa = cgetg(n+1, t_VEC);
                    634:     for (i=1; i<=n; i++) xa[i] = lstoi(i);
                    635:     xa++;
                    636:   }
                    637:   if (is_scalar_t(tx) && tx != t_INTMOD && tx != t_PADIC && tx != t_POLMOD)
                    638:   {
                    639:     GEN dif = NULL, dift;
                    640:     for (i=0; i<n; i++)
                    641:     {
                    642:       dift = gabs(gsub(x,(GEN)xa[i]), MEDDEFAULTPREC);
                    643:       if (!dif || gcmp(dift,dif)<0) { ns=i; dif=dift; }
                    644:     }
                    645:   }
                    646:   c=new_chunk(n);
                    647:   d=new_chunk(n); for (i=0; i<n; i++) c[i] = d[i] = ya[i];
                    648:   y=(GEN)d[ns--];
                    649:   dy = NULL; tetpil = 0; /* gcc -Wall */
                    650:   for (m=1; m<n; m++)
                    651:   {
                    652:     for (i=0; i<n-m; i++)
                    653:     {
                    654:       ho = gsub((GEN)xa[i],x);
                    655:       hp = gsub((GEN)xa[i+m],x); den = gsub(ho,hp);
                    656:       if (gcmp0(den)) err(talker,"two abcissas are equal in polint");
                    657:       w=gsub((GEN)c[i+1],(GEN)d[i]); den = gdiv(w,den);
                    658:       c[i]=lmul(ho,den);
                    659:       d[i]=lmul(hp,den);
                    660:     }
                    661:     dy = (2*(ns+1) < n-m)? (GEN)c[ns+1]: (GEN)d[ns--];
                    662:     tetpil=avma; y=gadd(y,dy);
                    663:   }
                    664:   if (!ptdy) y = gerepile(av,tetpil,y);
                    665:   else
                    666:   {
                    667:     GEN *gptr[2];
                    668:     *ptdy=gcopy(dy); gptr[0]=&y; gptr[1]=ptdy;
                    669:     gerepilemanysp(av,tetpil,gptr,2);
                    670:   }
                    671:   return y;
                    672: }
                    673:
                    674: GEN
                    675: polint(GEN xa, GEN ya, GEN x, GEN *ptdy)
                    676: {
                    677:   long tx=typ(xa), ty, lx=lg(xa);
                    678:
                    679:   if (ya) ty = typ(ya); else { ya = xa; ty = tx; xa = NULL; }
                    680:
                    681:   if (! is_vec_t(tx) || ! is_vec_t(ty))
                    682:     err(talker,"not vectors in polinterpolate");
                    683:   if (lx != lg(ya))
                    684:     err(talker,"different lengths in polinterpolate");
                    685:   if (lx <= 2)
                    686:   {
                    687:     if (lx == 1) err(talker,"no data in polinterpolate");
                    688:     ya=gcopy((GEN)ya[1]); if (ptdy) *ptdy = ya;
                    689:     return ya;
                    690:   }
                    691:   if (!x) x = polx[0];
                    692:   return polint_i(xa? xa+1: xa,ya+1,x,lx-1,ptdy);
                    693: }
                    694:
                    695: /***********************************************************************/
                    696: /*                                                                     */
                    697: /*                          SET OPERATIONS                             */
                    698: /*                                                                     */
                    699: /***********************************************************************/
                    700:
                    701: static GEN
                    702: gtostr(GEN x)
                    703: {
                    704:   char *s=GENtostr(x);
                    705:   x = strtoGENstr(s,0); free(s); return x;
                    706: }
                    707:
                    708: GEN
                    709: gtoset(GEN x)
                    710: {
                    711:   ulong av;
                    712:   long i,c,tx,lx;
                    713:   GEN y;
                    714:
                    715:   if (!x) return cgetg(1, t_VEC);
                    716:   tx = typ(x); lx = lg(x);
                    717:   if (!is_vec_t(tx))
                    718:   {
                    719:     if (tx != t_LIST)
                    720:       { y=cgetg(2,t_VEC); y[1]=(long)gtostr(x); return y; }
                    721:     lx = lgef(x)-1; x++;
                    722:   }
                    723:   if (lx==1) return cgetg(1,t_VEC);
                    724:   av=avma; y=cgetg(lx,t_VEC);
                    725:   for (i=1; i<lx; i++) y[i]=(long)gtostr((GEN)x[i]);
                    726:   y = sort(y);
                    727:   c=1;
                    728:   for (i=2; i<lx; i++)
                    729:     if (!gegal((GEN)y[i], (GEN)y[c])) y[++c] = y[i];
                    730:   setlg(y,c+1); return gerepilecopy(av,y);
                    731: }
                    732:
                    733: long
                    734: setisset(GEN x)
                    735: {
                    736:   long lx,i;
                    737:
                    738:   if (typ(x)!=t_VEC) return 0;
                    739:   lx=lg(x)-1; if (!lx) return 1;
                    740:   for (i=1; i<lx; i++)
                    741:     if (typ(x[i]) != t_STR || gcmp((GEN)x[i+1],(GEN)x[i])<=0) return 0;
                    742:   return typ(x[i]) == t_STR;
                    743: }
                    744:
                    745: /* looks if y belongs to the set x and returns the index if yes, 0 if no */
                    746: long
                    747: setsearch(GEN x, GEN y, long flag)
                    748: {
                    749:   long av = avma,lx,j,li,ri,fl, tx = typ(x);
                    750:
                    751:   if (tx==t_VEC) lx = lg(x);
                    752:   else
                    753:   {
                    754:     if (tx!=t_LIST) err(talker,"not a set in setsearch");
                    755:     lx=lgef(x)-1; x++;
                    756:   }
                    757:   if (lx==1) return flag? 1: 0;
                    758:
                    759:   if (typ(y) != t_STR) y = gtostr(y);
                    760:   li=1; ri=lx-1;
                    761:   do
                    762:   {
                    763:     j = (ri+li)>>1; fl = gcmp((GEN)x[j],y);
                    764:     if (!fl) { avma=av; return flag? 0: j; }
                    765:     if (fl<0) li=j+1; else ri=j-1;
                    766:   } while (ri>=li);
                    767:   avma=av; if (!flag) return 0;
                    768:   return (fl<0)? j+1: j;
                    769: }
                    770:
                    771: GEN
                    772: setunion(GEN x, GEN y)
                    773: {
                    774:   long av=avma,tetpil;
                    775:   GEN z;
                    776:
                    777:   if (typ(x) != t_VEC || typ(y) != t_VEC) err(talker,"not a set in setunion");
                    778:   z=concatsp(x,y); tetpil=avma; return gerepile(av,tetpil,gtoset(z));
                    779: }
                    780:
                    781: GEN
                    782: setintersect(GEN x, GEN y)
                    783: {
                    784:   long av=avma,i,lx,c;
                    785:   GEN z;
                    786:
                    787:   if (!setisset(x) || !setisset(y)) err(talker,"not a set in setintersect");
                    788:   lx=lg(x); z=cgetg(lx,t_VEC); c=1;
                    789:   for (i=1; i<lx; i++)
                    790:     if (setsearch(y, (GEN)x[i], 0)) z[c++] = x[i];
                    791:   setlg(z,c); return gerepilecopy(av,z);
                    792: }
                    793:
                    794: GEN
                    795: setminus(GEN x, GEN y)
                    796: {
                    797:   long av=avma,i,lx,c;
                    798:   GEN z;
                    799:
                    800:   if (!setisset(x) || !setisset(y)) err(talker,"not a set in setminus");
                    801:   lx=lg(x); z=cgetg(lx,t_VEC); c=1;
                    802:   for (i=1; i<lx; i++)
                    803:     if (setsearch(y, (GEN)x[i], 1)) z[c++] = x[i];
                    804:   setlg(z,c); return gerepilecopy(av,z);
                    805: }
                    806:
                    807: /***********************************************************************/
                    808: /*                                                                     */
                    809: /*               OPERATIONS ON DIRICHLET SERIES                        */
                    810: /*                                                                     */
                    811: /***********************************************************************/
                    812:
                    813: /* Addition, subtraction and scalar multiplication of Dirichlet series
                    814:    are done on the corresponding vectors */
                    815:
                    816: static long
                    817: dirval(GEN x)
                    818: {
                    819:   long i=1,lx=lg(x);
                    820:   while (i<lx && gcmp0((GEN)x[i])) i++;
                    821:   return i;
                    822: }
                    823:
                    824: GEN
                    825: dirmul(GEN x, GEN y)
                    826: {
                    827:   ulong av = avma, lim = stack_lim(av,1);
                    828:   long lx,ly,lz,dx,dy,i,j,k;
                    829:   GEN z,p1;
                    830:
                    831:   if (typ(x)!=t_VEC || typ(y)!=t_VEC) err(talker,"not a dirseries in dirmul");
                    832:   dx=dirval(x); dy=dirval(y); lx=lg(x); ly=lg(y);
                    833:   if (ly-dy<lx-dx) { z=y; y=x; x=z; lz=ly; ly=lx; lx=lz; lz=dy; dy=dx; dx=lz; }
                    834:   lz=min(lx*dy,ly*dx);
                    835:   z=cgetg(lz,t_VEC); for (i=1; i<lz; i++) z[i]=zero;
                    836:   for (j=dx; j<lx; j++)
                    837:   {
                    838:     p1=(GEN)x[j];
                    839:     if (!gcmp0(p1))
                    840:     {
                    841:       if (gcmp1(p1))
                    842:        for (k=dy,i=j*dy; i<lz; i+=j,k++) z[i]=ladd((GEN)z[i],(GEN)y[k]);
                    843:       else
                    844:       {
                    845:        if (gcmp_1(p1))
                    846:          for (k=dy,i=j*dy; i<lz; i+=j,k++) z[i]=lsub((GEN)z[i],(GEN)y[k]);
                    847:        else
                    848:          for (k=dy,i=j*dy; i<lz; i+=j,k++) z[i]=ladd((GEN)z[i],gmul(p1,(GEN)y[k]));
                    849:       }
                    850:     }
                    851:     if (low_stack(lim, stack_lim(av,1)))
                    852:     {
                    853:       if (DEBUGLEVEL) fprintferr("doubling stack in dirmul\n");
                    854:       z = gerepilecopy(av,z);
                    855:     }
                    856:   }
                    857:   return gerepilecopy(av,z);
                    858: }
                    859:
                    860: GEN
                    861: dirdiv(GEN x, GEN y)
                    862: {
                    863:   ulong av = avma;
                    864:   long lx,ly,lz,dx,dy,i,j;
                    865:   GEN z,p1;
                    866:
                    867:   if (typ(x)!=t_VEC || typ(y)!=t_VEC) err(talker,"not a dirseries in dirmul");
                    868:   dx=dirval(x); dy=dirval(y); lx=lg(x); ly=lg(y);
                    869:   if (dy!=1) err(talker,"not an invertible dirseries in dirdiv");
                    870:   lz=min(lx,ly*dx); p1=(GEN)y[1];
                    871:   if (!gcmp1(p1)) { y=gdiv(y,p1); x=gdiv(x,p1); }
                    872:   else x=gcopy(x);
                    873:   z=cgetg(lz,t_VEC); for (i=1; i<dx; i++) z[i]=zero;
                    874:   for (j=dx; j<lz; j++)
                    875:   {
                    876:     p1=(GEN)x[j]; z[j]=(long)p1;
                    877:     if (!gcmp0(p1))
                    878:     {
                    879:       if (gcmp1(p1))
                    880:        for (i=j+j; i<lz; i+=j) x[i]=lsub((GEN)x[i],(GEN)y[i/j]);
                    881:       else
                    882:       {
                    883:        if (gcmp_1(p1))
                    884:          for (i=j+j; i<lz; i+=j) x[i]=ladd((GEN)x[i],(GEN)y[i/j]);
                    885:        else
                    886:          for (i=j+j; i<lz; i+=j) x[i]=lsub((GEN)x[i],gmul(p1,(GEN)y[i/j]));
                    887:       }
                    888:     }
                    889:   }
                    890:   return gerepilecopy(av,z);
                    891: }
                    892:
                    893: /*************************************************************************/
                    894: /**                                                                    **/
                    895: /**                             RANDOM                                 **/
                    896: /**                                                                    **/
                    897: /*************************************************************************/
                    898: static long pari_randseed = 1;
                    899:
                    900: /* BSD rand gives this: seed = 1103515245*seed + 12345 */
                    901: long
                    902: mymyrand(void)
                    903: {
                    904: #if BITS_IN_RANDOM == 64
                    905:   pari_randseed = (1000000000000654397*pari_randseed + 12347) & ~HIGHBIT;
                    906: #else
                    907:   pari_randseed = (1000276549*pari_randseed + 12347) & 0x7fffffff;
                    908: #endif
                    909:   return pari_randseed;
                    910: }
                    911:
                    912: GEN muluu(ulong x, ulong y);
                    913:
                    914: static ulong
                    915: gp_rand(void)
                    916: {
                    917: #define GLUE2(hi, lo) (((hi) << BITS_IN_HALFULONG) | (lo))
                    918: #if !defined(LONG_IS_64BIT) || BITS_IN_RANDOM == 64
                    919:   return GLUE2((mymyrand()>>12)&LOWMASK,
                    920:                (mymyrand()>>12)&LOWMASK);
                    921: #else
                    922: #define GLUE4(hi1,hi2, lo1,lo2) GLUE2(((hi1)<<16)|(hi2), ((lo1)<<16)|(lo2))
                    923: #  define LOWMASK2 0xffffUL
                    924:   return GLUE4((mymyrand()>>12)&LOWMASK2,
                    925:                (mymyrand()>>12)&LOWMASK2,
                    926:                (mymyrand()>>12)&LOWMASK2,
                    927:                (mymyrand()>>12)&LOWMASK2);
                    928: #endif
                    929: }
                    930:
                    931: GEN
                    932: genrand(GEN N)
                    933: {
                    934:   long lx,i,nz;
                    935:   GEN x, p1;
                    936:
                    937:   if (!N) return stoi(mymyrand());
                    938:   if (typ(N)!=t_INT || signe(N)<=0) err(talker,"invalid bound in random");
                    939:
                    940:   lx = lgefint(N); x = new_chunk(lx);
                    941:   nz = lx-1; while (!N[nz]) nz--; /* nz = index of last non-zero word */
                    942:   for (i=2; i<lx; i++)
                    943:   {
                    944:     ulong n = N[i], r;
                    945:     if (n == 0) r = 0;
                    946:     else
                    947:     {
                    948:       long av = avma;
                    949:       if (i < nz) n++; /* allow for equality if we can go down later */
                    950:       p1 = muluu(n, gp_rand()); /* < n * 2^32, so 0 <= first word < n */
                    951:       r = (lgefint(p1)<=3)? 0: p1[2]; avma = av;
                    952:     }
                    953:     x[i] = r;
                    954:     if (r < (ulong)N[i]) break;
                    955:   }
                    956:   for (i++; i<lx; i++) x[i] = gp_rand();
                    957:   i=2; while (i<lx && !x[i]) i++;
                    958:   i -= 2; x += i; lx -= i;
                    959:   x[1] = evalsigne(lx>2) | evallgefint(lx);
                    960:   x[0] = evaltyp(t_INT) | evallg(lx);
                    961:   avma = (long)x; return x;
                    962: }
                    963:
                    964: long
                    965: setrand(long seed) { return (pari_randseed = seed); }
                    966:
                    967: long
                    968: getrand(void) { return pari_randseed; }
                    969:
                    970: long
                    971: getstack(void) { return top-avma; }
                    972:
                    973: long
                    974: gettime(void) { return timer(); }
                    975:
                    976: /***********************************************************************/
                    977: /**                                                                  **/
                    978: /**                         PERMUTATIONS                             **/
                    979: /**                                                                  **/
                    980: /***********************************************************************/
                    981:
                    982: GEN
                    983: numtoperm(long n, GEN x)
                    984: {
                    985:   ulong av;
                    986:   long i,a,r;
                    987:   GEN v,w;
                    988:
                    989:   if (n < 1) err(talker,"n too small (%ld) in numtoperm",n);
                    990:   if (typ(x) != t_INT) err(arither1);
                    991:   v = cgetg(n+1, t_VEC);
                    992:   v[1]=1; av = avma;
                    993:   if (signe(x) <= 0) x = modii(x, mpfact(n));
                    994:   for (r=2; r<=n; r++)
                    995:   {
                    996:     x = dvmdis(x,r,&w); a = itos(w);
                    997:     for (i=r; i>=a+2; i--) v[i] = v[i-1];
                    998:     v[i]=r;
                    999:   }
                   1000:   avma = av;
                   1001:   for (i=1; i<=n; i++) v[i] = lstoi(v[i]);
                   1002:   return v;
                   1003: }
                   1004:
                   1005: GEN
                   1006: permtonum(GEN x)
                   1007: {
                   1008:   long av=avma, lx=lg(x)-1, n=lx, last, ind, tx = typ(x);
                   1009:   GEN ary,res;
                   1010:
                   1011:   if (!is_vec_t(tx)) err(talker,"not a vector in permtonum");
                   1012:   ary = cgetg(lx+1,t_VECSMALL);
                   1013:   for (ind=1; ind<=lx; ind++)
                   1014:   {
                   1015:     res = (GEN)*++x;
                   1016:     if (typ(res) != t_INT) err(typeer,"permtonum");
                   1017:     ary[ind] = itos(res);
                   1018:   }
                   1019:   ary++; res = gzero;
                   1020:   for (last=lx; last>0; last--)
                   1021:   {
                   1022:     lx--; ind = lx;
                   1023:     while (ind>0 && ary[ind] != last) ind--;
                   1024:     res = addis(mulis(res,last), ind);
                   1025:     while (ind++<lx) ary[ind-1] = ary[ind];
                   1026:   }
                   1027:   if (!signe(res)) res = mpfact(n);
                   1028:   return gerepileuptoint(av, res);
                   1029: }
                   1030:
                   1031: /********************************************************************/
                   1032: /**                                                                **/
                   1033: /**                       MODREVERSE                               **/
                   1034: /**                                                                **/
                   1035: /********************************************************************/
                   1036:
                   1037: GEN
                   1038: polymodrecip(GEN x)
                   1039: {
                   1040:   long v,i,j,n,av,tetpil,lx;
                   1041:   GEN p1,p2,p3,p,phi,y,col;
                   1042:
                   1043:   if (typ(x)!=t_POLMOD) err(talker,"not a polymod in polymodrecip");
                   1044:   p=(GEN)x[1]; phi=(GEN)x[2];
                   1045:   v=varn(p); n=degpol(p); if (n<=0) return gcopy(x);
                   1046:   if (n==1)
                   1047:   {
                   1048:     y=cgetg(3,t_POLMOD);
                   1049:     if (typ(phi)==t_POL) phi = (GEN)phi[2];
                   1050:     p1=cgetg(4,t_POL); p1[1]=p[1]; p1[2]=lneg(phi); p1[3]=un;
                   1051:     y[1]=(long)p1;
                   1052:     if (gcmp0((GEN)p[2])) p1 = zeropol(v);
                   1053:     else
                   1054:     {
                   1055:       p1=cgetg(3,t_POL); av=avma;
                   1056:       p1[1] = evalsigne(1) | evalvarn(n) | evallgef(3);
                   1057:       p2=gdiv((GEN)p[2],(GEN)p[3]); tetpil=avma;
                   1058:       p1[2] = lpile(av,tetpil,gneg(p2));
                   1059:     }
                   1060:     y[2]=(long)p1; return y;
                   1061:   }
                   1062:   if (gcmp0(phi) || typ(phi) != t_POL)
                   1063:     err(talker,"reverse polymod does not exist");
                   1064:   av=avma; y=cgetg(n+1,t_MAT);
                   1065:   y[1]=(long)gscalcol_i(gun,n);
                   1066:   p2=phi;
                   1067:   for (j=2; j<=n; j++)
                   1068:   {
                   1069:     lx=lgef(p2); p1=cgetg(n+1,t_COL); y[j]=(long)p1;
                   1070:     for (i=1; i<=lx-2; i++) p1[i]=p2[i+1];
                   1071:     for (   ; i<=n; i++) p1[i]=zero;
                   1072:     if (j<n) p2 = gmod(gmul(p2,phi), p);
                   1073:   }
                   1074:   col=cgetg(n+1,t_COL); col[1]=zero; col[2]=un;
                   1075:   for (i=3; i<=n; i++) col[i]=zero;
                   1076:   p1=gauss(y,col); p2=gtopolyrev(p1,v); p3=caract(x,v);
                   1077:   tetpil=avma; return gerepile(av,tetpil,gmodulcp(p2,p3));
                   1078: }
                   1079:
                   1080: /********************************************************************/
                   1081: /**                                                                **/
                   1082: /**                           HEAPSORT                             **/
                   1083: /**                                                                **/
                   1084: /********************************************************************/
                   1085: static GEN vcmp_k;
                   1086: static int vcmp_lk;
                   1087: static int (*vcmp_cmp)(GEN,GEN);
                   1088:
                   1089: int
                   1090: pari_compare_int(int *a,int *b)
                   1091: {
                   1092:   return *a - *b;
                   1093: }
                   1094:
                   1095: int
                   1096: pari_compare_long(long *a,long *b)
                   1097: {
                   1098:   return *a - *b;
                   1099: }
                   1100:
                   1101: static int
                   1102: veccmp(GEN x, GEN y)
                   1103: {
                   1104:   int i,s;
                   1105:
                   1106:   for (i=1; i<vcmp_lk; i++)
                   1107:   {
                   1108:     s = vcmp_cmp((GEN) x[vcmp_k[i]], (GEN) y[vcmp_k[i]]);
                   1109:     if (s) return s;
                   1110:   }
                   1111:   return 0;
                   1112: }
                   1113:
                   1114: static int
                   1115: longcmp(GEN x, GEN y)
                   1116: {
                   1117:   return ((long)x > (long)y)? 1: ((x == y)? 0: -1);
                   1118: }
                   1119:
                   1120: /* Sort x = vector of elts, using cmp to compare them.
                   1121:  *  flag & cmp_IND: indirect sort: return permutation that would sort x
                   1122:  * For private use:
                   1123:  *  flag & cmp_C  : as cmp_IND, but return permutation as vector of C-longs
                   1124:  */
                   1125: GEN
                   1126: gen_sort(GEN x, int flag, int (*cmp)(GEN,GEN))
                   1127: {
                   1128:   long i,j,indxt,ir,l,tx=typ(x),lx=lg(x);
                   1129:   GEN q,y,indx;
                   1130:
                   1131:   if (!is_matvec_t(tx) && tx != t_VECSMALL) err(typeer,"gen_sort");
                   1132:   if (flag & cmp_C) tx = t_VECSMALL;
                   1133:   else if (flag & cmp_IND) tx = t_VEC;
                   1134:   y = cgetg(lx, tx);
                   1135:   if (lx==1) return y;
                   1136:   if (lx==2)
                   1137:   {
                   1138:     if (flag & cmp_C)
                   1139:       y[1] = 1;
                   1140:     else if (flag & cmp_IND)
                   1141:       y[1] = un;
                   1142:     else
                   1143:       y[1] = lcopy((GEN)x[1]);
                   1144:     return y;
                   1145:   }
                   1146:   if (!cmp) cmp = &longcmp;
                   1147:   indx = (GEN) gpmalloc(lx*sizeof(long));
                   1148:   for (j=1; j<lx; j++) indx[j]=j;
                   1149:
                   1150:   ir=lx-1; l=(ir>>1)+1;
                   1151:   for(;;)
                   1152:   {
                   1153:     if (l>1)
                   1154:       { l--; indxt = indx[l]; }
                   1155:     else
                   1156:     {
                   1157:       indxt = indx[ir]; indx[ir]=indx[1]; ir--;
                   1158:       if (ir == 1)
                   1159:       {
                   1160:         indx[1] = indxt;
                   1161:         if (flag & cmp_C)
                   1162:          for (i=1; i<lx; i++) y[i]=indx[i];
                   1163:         else if (flag & cmp_IND)
                   1164:          for (i=1; i<lx; i++) y[i]=lstoi(indx[i]);
                   1165:         else
                   1166:          for (i=1; i<lx; i++) y[i]=lcopy((GEN)x[indx[i]]);
                   1167:         free(indx); return y;
                   1168:       }
                   1169:     }
                   1170:     q = (GEN)x[indxt]; i=l;
                   1171:     if (flag & cmp_REV)
                   1172:       for (j=i<<1; j<=ir; j<<=1)
                   1173:       {
                   1174:         if (j<ir && cmp((GEN)x[indx[j]],(GEN)x[indx[j+1]]) > 0) j++;
                   1175:         if (cmp(q,(GEN)x[indx[j]]) <= 0) break;
                   1176:
                   1177:         indx[i]=indx[j]; i=j;
                   1178:       }
                   1179:     else
                   1180:       for (j=i<<1; j<=ir; j<<=1)
                   1181:       {
                   1182:         if (j<ir && cmp((GEN)x[indx[j]],(GEN)x[indx[j+1]]) < 0) j++;
                   1183:         if (cmp(q,(GEN)x[indx[j]]) >= 0) break;
                   1184:
                   1185:         indx[i]=indx[j]; i=j;
                   1186:       }
                   1187:     indx[i]=indxt;
                   1188:   }
                   1189: }
                   1190:
                   1191: #define sort_fun(flag) ((flag & cmp_LEX)? &lexcmp: &gcmp)
                   1192:
                   1193: GEN
                   1194: gen_vecsort(GEN x, GEN k, long flag)
                   1195: {
                   1196:   long i,j,l,t, lx = lg(x), tmp[2];
                   1197:
                   1198:   if (lx<=2) return gen_sort(x,flag,sort_fun(flag));
                   1199:   t = typ(k); vcmp_cmp = sort_fun(flag);
                   1200:   if (t==t_INT)
                   1201:   {
                   1202:     tmp[1] = (long)k; k = tmp;
                   1203:     vcmp_lk = 2;
                   1204:   }
                   1205:   else
                   1206:   {
                   1207:     if (! is_vec_t(t)) err(talker,"incorrect lextype in vecsort");
                   1208:     vcmp_lk = lg(k);
                   1209:   }
                   1210:   l = 0;
                   1211:   vcmp_k = (GEN)gpmalloc(vcmp_lk * sizeof(long));
                   1212:   for (i=1; i<vcmp_lk; i++)
                   1213:   {
                   1214:     j = itos((GEN)k[i]);
                   1215:     if (j<=0) err(talker,"negative index in vecsort");
                   1216:     vcmp_k[i]=j; if (j>l) l=j;
                   1217:   }
                   1218:   t = typ(x);
                   1219:   if (! is_matvec_t(t)) err(typeer,"vecsort");
                   1220:   for (j=1; j<lx; j++)
                   1221:   {
                   1222:     t = typ(x[j]);
                   1223:     if (! is_vec_t(t)) err(typeer,"vecsort");
                   1224:     if (lg((GEN)x[j]) <= l) err(talker,"index too large in vecsort");
                   1225:   }
                   1226:   x = gen_sort(x, flag, veccmp);
                   1227:   free(vcmp_k); return x;
                   1228: }
                   1229:
                   1230: GEN
                   1231: vecsort0(GEN x, GEN k, long flag)
                   1232: {
                   1233:   if (flag < 0 || flag >= cmp_C) err(flagerr,"vecsort");
                   1234:   return k? gen_vecsort(x,k,flag): gen_sort(x,flag, sort_fun(flag));
                   1235: }
                   1236:
                   1237: GEN
                   1238: vecsort(GEN x, GEN k)
                   1239: {
                   1240:   return gen_vecsort(x,k, 0);
                   1241: }
                   1242:
                   1243: GEN
                   1244: sindexsort(GEN x)
                   1245: {
                   1246:   return gen_sort(x, cmp_IND | cmp_C, gcmp);
                   1247: }
                   1248:
                   1249: GEN
                   1250: sindexlexsort(GEN x)
                   1251: {
                   1252:   return gen_sort(x, cmp_IND | cmp_C, lexcmp);
                   1253: }
                   1254:
                   1255: GEN
                   1256: indexsort(GEN x)
                   1257: {
                   1258:   return gen_sort(x, cmp_IND, gcmp);
                   1259: }
                   1260:
                   1261: GEN
                   1262: indexlexsort(GEN x)
                   1263: {
                   1264:   return gen_sort(x, cmp_IND, lexcmp);
                   1265: }
                   1266:
                   1267: GEN
                   1268: sort(GEN x)
                   1269: {
                   1270:   return gen_sort(x, 0, gcmp);
                   1271: }
                   1272:
                   1273: GEN
                   1274: lexsort(GEN x)
                   1275: {
                   1276:   return gen_sort(x, 0, lexcmp);
                   1277: }
                   1278:
                   1279: /* index of x in table T, 0 otherwise */
                   1280: long
                   1281: tablesearch(GEN T, GEN x, int (*cmp)(GEN,GEN))
                   1282: {
                   1283:   long l=1,u=lg(T)-1,i,s;
                   1284:
                   1285:   while (u>=l)
                   1286:   {
                   1287:     i = (l+u)>>1; s = cmp(x,(GEN)T[i]);
                   1288:     if (!s) return i;
                   1289:     if (s<0) u=i-1; else l=i+1;
                   1290:   }
                   1291:   return 0;
                   1292: }
                   1293:
                   1294: /* assume lg(x) = lg(y), x,y in Z^n */
                   1295: int
                   1296: cmp_vecint(GEN x, GEN y)
                   1297: {
                   1298:   long fl,i, lx = lg(x);
                   1299:   for (i=1; i<lx; i++)
                   1300:     if (( fl = cmpii((GEN)x[i], (GEN)y[i]) )) return fl;
                   1301:   return 0;
                   1302: }
                   1303:
                   1304: /* assume x and y come from the same primedec call (uniformizer unique) */
                   1305: int
                   1306: cmp_prime_over_p(GEN x, GEN y)
                   1307: {
                   1308:   int k = mael(x,4,2) - mael(y,4,2); /* diff. between residue degree */
                   1309:   return k? ((k > 0)? 1: -1)
                   1310:           : cmp_vecint((GEN)x[2], (GEN)y[2]);
                   1311: }
                   1312:
                   1313: int
                   1314: cmp_prime_ideal(GEN x, GEN y)
                   1315: {
                   1316:   int k = cmpii((GEN)x[1], (GEN)y[1]);
                   1317:   return k? k: cmp_prime_over_p(x,y);
                   1318: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>