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

Annotation of OpenXM_contrib/pari-2.2/src/basemath/rootpol.c, Revision 1.1

1.1     ! noro        1: /* $Id: rootpol.c,v 1.30 2001/10/01 12:11:32 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: /*                ROOTS OF COMPLEX POLYNOMIALS                     */
        !            19: /*                (written by Xavier Gourdon)                      */
        !            20: /*                                                                 */
        !            21: /*******************************************************************/
        !            22: #include "pari.h"
        !            23:
        !            24: extern GEN polrecip_i(GEN x);
        !            25: extern GEN poldeflate(GEN x0, long *m);
        !            26: extern GEN roots_to_pol(GEN a, long v);
        !            27: #define pariINFINITY 100000
        !            28: #define NEWTON_MAX 10
        !            29:
        !            30: static long KARASQUARE_LIMIT, COOK_SQUARE_LIMIT, Lmax;
        !            31:
        !            32: /********************************************************************/
        !            33: /**                                                                **/
        !            34: /**                      ARITHMETIQUE RAPIDE                       **/
        !            35: /**                                                                **/
        !            36: /********************************************************************/
        !            37:
        !            38: /* fast product of x,y which must be integer or complex of integer */
        !            39: static GEN
        !            40: quickmulcc(GEN x, GEN y)
        !            41: {
        !            42:   long tx=typ(x),ty=typ(y);
        !            43:   GEN z;
        !            44:
        !            45:   if (tx==t_INT)
        !            46:   {
        !            47:     if (ty==t_INT) return mulii(x,y);
        !            48:     if (ty==t_COMPLEX)
        !            49:     {
        !            50:       z=cgetg(3,t_COMPLEX);
        !            51:       z[1]=(long) mulii(x,(GEN) y[1]);
        !            52:       z[2]=(long) mulii(x,(GEN) y[2]);
        !            53:       return z;
        !            54:     }
        !            55:   }
        !            56:
        !            57:   if (tx==t_COMPLEX)
        !            58:   {
        !            59:     if (ty==t_INT)
        !            60:     {
        !            61:       z=cgetg(3,t_COMPLEX);
        !            62:       z[1]=(long) mulii((GEN)x[1],y);
        !            63:       z[2]=(long) mulii((GEN)x[2],y);
        !            64:       return z;
        !            65:     }
        !            66:     if (ty==t_COMPLEX)
        !            67:     {
        !            68:       long av,tetpil;
        !            69:       GEN p1,p2;
        !            70:
        !            71:       z=cgetg(3,t_COMPLEX); av=avma;
        !            72:       p1=mulii((GEN)x[1],(GEN)y[1]); p2=mulii((GEN)x[2],(GEN)y[2]);
        !            73:       x=addii((GEN)x[1],(GEN)x[2]); y=addii((GEN)y[1],(GEN)y[2]);
        !            74:       y=mulii(x,y); x=addii(p1,p2);
        !            75:       tetpil=avma; z[1]=lsubii(p1,p2); z[2]=lsubii(y,x);
        !            76:       gerepilemanyvec(av,tetpil,z+1,2);
        !            77:       return z;
        !            78:     }
        !            79:   }
        !            80:   err(talker,"bug in quickmulcc");
        !            81:   return NULL; /* not reached */
        !            82: }
        !            83:
        !            84: static void
        !            85: set_karasquare_limit(long bitprec)
        !            86: {
        !            87:   if (bitprec<600) { KARASQUARE_LIMIT=8; COOK_SQUARE_LIMIT=400; return; }
        !            88:   if (bitprec<2000) { KARASQUARE_LIMIT=4; COOK_SQUARE_LIMIT=200; return; }
        !            89:   if (bitprec<3000) { KARASQUARE_LIMIT=4; COOK_SQUARE_LIMIT=125; return; }
        !            90:   if (bitprec<5000) { KARASQUARE_LIMIT=2; COOK_SQUARE_LIMIT=75; return; }
        !            91:   KARASQUARE_LIMIT=1; COOK_SQUARE_LIMIT=50;
        !            92: }
        !            93:
        !            94: /* the pari library does not have specific procedure for the square of
        !            95: polynomials. This one is twice faster than gmul */
        !            96: static GEN
        !            97: mysquare(GEN p)
        !            98: {
        !            99:   GEN s,aux1,aux2;
        !           100:   long i,j,n=degpol(p),nn,ltop,lbot;
        !           101:
        !           102:   if (n==-1) return gcopy(p);
        !           103:   nn=n<<1; s=cgetg(nn+3,t_POL);
        !           104:   s[1] = evalsigne(1) | evalvarn(varn(p)) | evallgef(nn+3);
        !           105:   for (i=0; i<=n; i++)
        !           106:   {
        !           107:     aux1=gzero; ltop=avma;
        !           108:     for (j=0; j<(i+1)>>1; j++)
        !           109:     {
        !           110:       aux2=quickmulcc((GEN) p[j+2],(GEN)p[i-j+2]);
        !           111:       aux1=gadd(aux1,aux2);
        !           112:     }
        !           113:     if (i%2==1) { lbot=avma; s[i+2]=lpile(ltop,lbot,gshift(aux1,1)); }
        !           114:     else
        !           115:     {
        !           116:       aux1=gshift(aux1,1);
        !           117:       aux2=quickmulcc((GEN)p[2+(i>>1)],(GEN)p[2+(i>>1)]);
        !           118:       lbot=avma; s[i+2]=lpile(ltop,lbot,gadd(aux1,aux2));
        !           119:     }
        !           120:   }
        !           121:   for (i=n+1; i<=nn; i++)
        !           122:   {
        !           123:     aux1=gzero; ltop=avma;
        !           124:     for (j=i-n; j<(i+1)>>1; j++)
        !           125:     {
        !           126:       aux2=quickmulcc((GEN)p[j+2],(GEN)p[i-j+2]);
        !           127:       aux1=gadd(aux1,aux2);
        !           128:     }
        !           129:     if (i%2==1) { lbot=avma; s[i+2]=lpile(ltop,lbot,gshift(aux1,1)); }
        !           130:     else
        !           131:     {
        !           132:       aux1=gshift(aux1,1);
        !           133:       aux2=quickmulcc((GEN)p[2+(i>>1)],(GEN)p[2+(i>>1)]);
        !           134:       lbot=avma; s[i+2]=lpile(ltop,lbot,gadd(aux1,aux2));
        !           135:     }
        !           136:   }
        !           137:   return s;
        !           138: }
        !           139:
        !           140: static GEN
        !           141: karasquare(GEN p)
        !           142: {
        !           143:   GEN p1,s0,s1,s2,aux;
        !           144:   long n=degpol(p),n0,n1,i,var,nn0;
        !           145:   ulong ltop;
        !           146:
        !           147:   if (n<=KARASQUARE_LIMIT) return mysquare(p);
        !           148:   ltop=avma;
        !           149:   var=evalsigne(1)+evalvarn(varn(p)); n0=n>>1; n1=n-n0-1;
        !           150:   setlgef(p,n0+3); /* hack to have the first half of p */
        !           151:   s0=karasquare(p);
        !           152:   p1=cgetg(n1+3,t_POL); p1[1]=var+evallgef(n1+3);
        !           153:   for (i=2; i<=n1+2; i++) p1[i]=p[1+i+n0];
        !           154:   s2=karasquare(p1);
        !           155:   s1=karasquare(gadd(p,p1));
        !           156:   s1=gsub(s1,gadd(s0,s2));
        !           157:   nn0=n0<<1;
        !           158:   aux=cgetg((n<<1)+3,t_POL); aux[1]=var+evallgef(2*n+3);
        !           159:   var=lgef(s0);
        !           160:   for (i=2; i<var; i++) aux[i]=s0[i];
        !           161:   for (   ; i<=nn0+2; i++) aux[i]=zero;
        !           162:   var=lgef(s2);
        !           163:   for (i=2; i<var; i++) aux[2+i+nn0]=s2[i];
        !           164:   for (i=var-2; i<=(n1<<1); i++) aux[4+i+nn0]=zero;
        !           165:   aux[3+nn0]=zero;
        !           166:   for (i=3; i<=lgef(s1); i++)
        !           167:     aux[i+n0]=ladd((GEN) aux[i+n0],(GEN) s1[i-1]);
        !           168:   setlgef(p,n+3); /* recover all the polynomial p */
        !           169:   return gerepilecopy(ltop,aux);
        !           170: }
        !           171:
        !           172: static GEN
        !           173: cook_square(GEN p)
        !           174: {
        !           175:   GEN p0,p1,p2,p3,q,aux0,aux1,r,aux,plus,moins;
        !           176:   long n=degpol(p),n0,n3,i,j,var;
        !           177:   ulong ltop = avma;
        !           178:
        !           179:   if (n<=COOK_SQUARE_LIMIT) return karasquare(p);
        !           180:
        !           181:   n0=(n+1)/4; n3=n+1-3*n0;
        !           182:   p0=cgetg(n0+2,t_POL); p1=cgetg(n0+2,t_POL); p2=cgetg(n0+2,t_POL);
        !           183:   p3=cgetg(n3+2,t_POL);
        !           184:   var=evalsigne(1)|evalvarn(varn(p));
        !           185:   p0[1]=p1[1]=p2[1]=var|evallgef(n0+2); p3[1]=var|evallgef(n3+2);
        !           186:
        !           187:   for (i=0; i<n0; i++)
        !           188:   {
        !           189:     p0[i+2]=p[i+2]; p1[i+2]=p[i+n0+2]; p2[i+2]=p[i+2*n0+2];
        !           190:   }
        !           191:   for (i=0; i<n3; i++) p3[i+2]=p[i+3*n0+2];
        !           192:
        !           193:   q=cgetg(8,t_VEC); q=q+4;
        !           194:
        !           195:   q[0]=(long) p0;
        !           196:   aux0=gadd(p0,p2); aux1=gadd(p1,p3);
        !           197:   q[-1]=lsub(aux0,aux1); q[1]=ladd(aux0,aux1);
        !           198:   aux0=gadd(p0,gmulgs(p2,4)); aux1=gmulgs(gadd(p1,gmulgs(p3,4)),2);
        !           199:   q[-2]=lsub(aux0,aux1); q[2]=ladd(aux0,aux1);
        !           200:   aux0=gadd(p0,gmulgs(p2,9)); aux1=gmulgs(gadd(p1,gmulgs(p3,9)),3);
        !           201:   q[-3]=lsub(aux0,aux1); q[3]=ladd(aux0,aux1);
        !           202:   for (i=-3; i<=3; i++) q[i]=(long) cook_square((GEN)q[i]);
        !           203:   r=new_chunk(7);
        !           204:   plus=cgetg(4,t_VEC); moins=cgetg(4,t_VEC);
        !           205:   for (i=1; i<=3; i++)
        !           206:   {
        !           207:     plus[i]=ladd((GEN)q[-i],(GEN)q[i]);
        !           208:     moins[i]=lsub((GEN)q[-i],(GEN)q[i]);
        !           209:   }
        !           210:   r[0]=q[0];
        !           211:   r[1]=ldivgs(
        !           212:              gsub(
        !           213:                   gsub(gmulgs((GEN)moins[2],9),(GEN)moins[3]),
        !           214:                   gmulgs((GEN)moins[1],45)),
        !           215:              60);
        !           216:   r[2]=ldivgs(
        !           217:              gadd(
        !           218:                   gadd(gmulgs((GEN)plus[1],270),gmulgs((GEN)q[0],-490)),
        !           219:                   gadd(gmulgs((GEN)plus[2],-27),gmulgs((GEN)plus[3],2))),
        !           220:              360);
        !           221:   r[3]=ldivgs(
        !           222:              gadd(
        !           223:                   gadd(gmulgs((GEN)moins[1],13),gmulgs((GEN)moins[2],-8)),
        !           224:                   (GEN)moins[3]),
        !           225:              48);
        !           226:   r[4]=ldivgs(
        !           227:              gadd(
        !           228:                   gadd(gmulgs((GEN)q[0],56),gmulgs((GEN)plus[1],-39)),
        !           229:                   gsub(gmulgs((GEN)plus[2],12),(GEN)plus[3])),
        !           230:              144);
        !           231:   r[5]=ldivgs(
        !           232:              gsub(
        !           233:                   gadd(gmulgs((GEN)moins[1],-5),gmulgs((GEN)moins[2],4)),
        !           234:                   (GEN)moins[3]),
        !           235:              240);
        !           236:   r[6]=ldivgs(
        !           237:              gadd(
        !           238:                   gadd(gmulgs((GEN)q[0],-20),gmulgs((GEN)plus[1],15)),
        !           239:                   gadd(gmulgs((GEN)plus[2],-6),(GEN)plus[3])),
        !           240:              720);
        !           241:   q=cgetg(2*n+3,t_POL); q[1]=var|evallgef(2*n+3);
        !           242:   for (i=0; i<=2*n; i++) q[i+2]=zero;
        !           243:   for (i=0; i<=6; i++)
        !           244:   {
        !           245:     aux=(GEN) r[i];
        !           246:     for (j=0; j<=degpol(aux); j++)
        !           247:       q[n0*i+j+2]=ladd((GEN)q[n0*i+j+2],(GEN)aux[j+2]);
        !           248:   }
        !           249:   return gerepilecopy(ltop,q);
        !           250: }
        !           251:
        !           252: static GEN
        !           253: graeffe(GEN p)
        !           254: {
        !           255:   GEN p0,p1,s0,s1,ss1;
        !           256:   long n=degpol(p),n0,n1,i,auxi,ns1;
        !           257:
        !           258:   if (n==0) return gcopy(p);
        !           259:   n0=n>>1; n1=(n-1)>>1;
        !           260:   auxi=evalsigne(1)|evalvarn(varn(p));
        !           261:   p0=cgetg(n0+3,t_POL); p0[1]=auxi|evallgef(n0+3);
        !           262:   p1=cgetg(n1+3,t_POL); p1[1]=auxi|evallgef(n1+3);
        !           263:   for (i=0; i<=n0; i++) p0[i+2]=p[2+(i<<1)];
        !           264:   for (i=0; i<=n1; i++) p1[i+2]=p[3+(i<<1)];
        !           265:
        !           266:   s0=cook_square(p0);
        !           267:   s1=cook_square(p1); ns1 = degpol(s1);
        !           268:   ss1 = cgetg(ns1+4, t_POL);
        !           269:   ss1[1] = auxi | evallgef(ns1+4);
        !           270:   ss1[2]=zero;
        !           271:   for (i=0; i<=ns1; i++) ss1[3+i]=lneg((GEN)s1[2+i]);
        !           272:   /* now ss1 contains -x * s1 */
        !           273:   return gadd(s0,ss1);
        !           274: }
        !           275:
        !           276: /********************************************************************/
        !           277: /**                                                                **/
        !           278: /**        FACTORISATION SQUAREFREE AVEC LE GCD MODULAIRE          **/
        !           279: /**                                                                **/
        !           280: /********************************************************************/
        !           281:
        !           282: /* return a n x 2 matrix:
        !           283:  *   col 1 contains the i's such that A_i non constant
        !           284:  *   col 2 the A_i's, s.t. pol = A_i1^i1.A_i2^i2...A_in^in.
        !           285:  * if pol is constant return [;]
        !           286:  */
        !           287: GEN
        !           288: square_free_factorization(GEN pol)
        !           289: {
        !           290:   long deg,i,j,m;
        !           291:   GEN p1,x,t1,v1,t,v,A;
        !           292:
        !           293:   if (typ(pol)!=t_POL) err(typeer,"square_free_factorization");
        !           294:   deg=degpol(pol); if (deg<1) return cgetg(1,t_MAT);
        !           295:   p1 = content(pol); if (!gcmp1(p1)) pol = gdiv(pol,p1);
        !           296:
        !           297:   x=cgetg(3,t_MAT);
        !           298:   t1 = NULL; /* gcc -Wall */
        !           299:   if (deg > 1)
        !           300:   {
        !           301:     t1 = modulargcd(pol,derivpol(pol));
        !           302:     if (isscalar(t1)) deg = 1;
        !           303:   }
        !           304:   if (deg==1)
        !           305:   {
        !           306:     x[1]=lgetg(2,t_COL); p1=(GEN)x[1]; p1[1]=un;
        !           307:     x[2]=lgetg(2,t_COL); p1=(GEN)x[2]; p1[1]=(long)pol; return x;
        !           308:   }
        !           309:   A=new_chunk(deg+1); v1=gdivexact(pol,t1); v=v1; i=0;
        !           310:   while (lgef(v)>3)
        !           311:   {
        !           312:     v=modulargcd(t1,v1); i++;
        !           313:     A[i]=(long)gdivexact(v1,v);
        !           314:     t=gdivexact(t1,v); v1=v; t1=t;
        !           315:   }
        !           316:   m=1; x[1]=lgetg(deg+1,t_COL); x[2]=lgetg(deg+1,t_COL);
        !           317:   for (j=1; j<=i; j++)
        !           318:     if (isnonscalar(A[j]))
        !           319:     {
        !           320:       p1=(GEN)x[1]; p1[m] = lstoi(j);
        !           321:       p1=(GEN)x[2]; p1[m] = A[j];
        !           322:       m++;
        !           323:     }
        !           324:   setlg(x[1],m); setlg(x[2],m); return x;
        !           325: }
        !           326:
        !           327: /********************************************************************/
        !           328: /**                                                                **/
        !           329: /**                 CALCUL DU MODULE DES RACINES                   **/
        !           330: /**                                                                **/
        !           331: /********************************************************************/
        !           332:
        !           333: static double
        !           334: log2ir(GEN x)
        !           335: {
        !           336:   double l;
        !           337:
        !           338:   if (signe(x)==0) return (double) -pariINFINITY;
        !           339:   if (typ(x)==t_INT)
        !           340:   {
        !           341:     if (lgefint(x)==3) return (double) log2( (double)(ulong) x[2]);
        !           342:     l=(double)(ulong) x[2]+
        !           343:        (double)(ulong) x[3] / exp2((double) BITS_IN_LONG);
        !           344:     return log2(l)+ (double) BITS_IN_LONG * (lgefint(x)-3.);
        !           345:   }
        !           346:   /* else x is real */
        !           347:   return 1.+ (double) expo(x)+log2( (double)(ulong) x[2]) - (double) BITS_IN_LONG;
        !           348: }
        !           349:
        !           350: static double
        !           351: mylog2(GEN z)
        !           352: {
        !           353:   double x,y;
        !           354:
        !           355:   if (typ(z)!=t_COMPLEX) return log2ir(z);
        !           356:
        !           357:   x = log2ir((GEN) z[1]);
        !           358:   y = log2ir((GEN) z[2]);
        !           359:   if (fabs(x-y)>10) return (x>y)? x: y;
        !           360:   return x+0.5*log2( 1 + exp2(2*(y-x)));
        !           361: }
        !           362:
        !           363: static long
        !           364: findpower(GEN p)
        !           365: {
        !           366:   double x, logbinomial,pente,pentemax=-pariINFINITY;
        !           367:   long n=degpol(p),i;
        !           368:
        !           369:   logbinomial = mylog2((GEN) p[n+2]);
        !           370:   for (i=n-1; i>=0; i--)
        !           371:   {
        !           372:     logbinomial += log2((double) (i+1) / (double) (n-i));
        !           373:     x = mylog2((GEN) p[2+i])-logbinomial;
        !           374:     if (x>-pariINFINITY)
        !           375:     {
        !           376:       pente = x/ (double) (n-i);
        !           377:       if (pente > pentemax) pentemax = pente;
        !           378:     }
        !           379:   }
        !           380:   return (long) -floor(pentemax);
        !           381: }
        !           382:
        !           383: /* returns the exponent for the procedure modulus, from the newton diagram */
        !           384: static long
        !           385: polygone_newton(GEN p, long k)
        !           386: {
        !           387:   double *logcoef,pente;
        !           388:   long n=degpol(p),i,j,h,l,*sommet,pentelong;
        !           389:
        !           390:   logcoef=(double*) gpmalloc((n+1)*sizeof(double));
        !           391:   sommet=(long*) gpmalloc((n+1)*sizeof(long));
        !           392:
        !           393:   /* sommet[i]=1 si i est un sommet, =0 sinon */
        !           394:   for (i=0; i<=n; i++) { logcoef[i]=mylog2((GEN)p[2+i]); sommet[i]=0; }
        !           395:   sommet[0]=1; i=0;
        !           396:   while (i<n)
        !           397:   {
        !           398:     pente=logcoef[i+1]-logcoef[i];
        !           399:     h=i+1;
        !           400:     for (j=i+1; j<=n; j++)
        !           401:     {
        !           402:       if (pente<(logcoef[j]-logcoef[i])/(double)(j-i))
        !           403:       {
        !           404:        h=j;
        !           405:        pente=(logcoef[j]-logcoef[i])/(double)(j-i);
        !           406:       }
        !           407:     }
        !           408:     i=h;
        !           409:     sommet[h]=1;
        !           410:   }
        !           411:   h=k; while (!sommet[h]) h++;
        !           412:   l=k-1; while (!sommet[l]) l--;
        !           413:   pentelong=(long) floor((logcoef[h]-logcoef[l])/(double)(h-l)+0.5);
        !           414:   free(logcoef); free(sommet); return pentelong;
        !           415: }
        !           416:
        !           417: /* change z into z*2^e, where z is real or complex of real */
        !           418: static void
        !           419: myshiftrc(GEN z, long e)
        !           420: {
        !           421:   if (typ(z)==t_COMPLEX)
        !           422:   {
        !           423:     if (signe(z[1])!=0) setexpo(z[1], expo(z[1])+e);
        !           424:     if (signe(z[2])!=0) setexpo(z[2], expo(z[2])+e);
        !           425:   }
        !           426:   else
        !           427:     if (signe(z)!=0) setexpo(z,expo(z)+e);
        !           428: }
        !           429:
        !           430: /* return z*2^e, where z is integer or complex of integer (destroy z) */
        !           431: static GEN
        !           432: myshiftic(GEN z, long e)
        !           433: {
        !           434:   if (typ(z)==t_COMPLEX)
        !           435:   {
        !           436:     z[1]=signe(z[1])? lmpshift((GEN) z[1],e): zero;
        !           437:     z[2]=lmpshift((GEN) z[2],e);
        !           438:     return z;
        !           439:   }
        !           440:   return signe(z)? mpshift(z,e): gzero;
        !           441: }
        !           442:
        !           443: /* as realun with precision in bits, not in words */
        !           444: static GEN
        !           445: myrealun(long bitprec)
        !           446: {
        !           447:   GEN x;
        !           448:   if (bitprec < 0) bitprec = 0;
        !           449:   x = cgetr(bitprec/BITS_IN_LONG+3);
        !           450:   affsr(1,x); return x;
        !           451: }
        !           452:
        !           453: static GEN
        !           454: mygprecrc(GEN x, long bitprec, long e)
        !           455: {
        !           456:   long tx=typ(x);
        !           457:   GEN y;
        !           458:
        !           459:   if (bitprec<0) bitprec=0; /* should rarely happen */
        !           460:   switch(tx)
        !           461:   {
        !           462:     case t_REAL:
        !           463:       y=cgetr(bitprec/BITS_IN_LONG+3); affrr(x,y);
        !           464:       if (!signe(x)) setexpo(y,-bitprec+e);
        !           465:       break;
        !           466:     case t_COMPLEX:
        !           467:       y=cgetg(3,t_COMPLEX);
        !           468:       y[1]=(long) mygprecrc((GEN)x[1],bitprec,e);
        !           469:       y[2]=(long) mygprecrc((GEN)x[2],bitprec,e);
        !           470:       break;
        !           471:     default: y=gcopy(x);
        !           472:   }
        !           473:   return y;
        !           474: }
        !           475:
        !           476: /* gprec behaves badly with the zero for polynomials.
        !           477: The second parameter in mygprec is the precision in base 2 */
        !           478: static GEN
        !           479: mygprec(GEN x, long bitprec)
        !           480: {
        !           481:   long tx=typ(x),lx,i,e = gexpo(x);
        !           482:   GEN y;
        !           483:
        !           484:   switch(tx)
        !           485:   {
        !           486:     case t_POL:
        !           487:       lx=lgef(x); y=cgetg(lx,tx); y[1]=x[1];
        !           488:       for (i=2; i<lx; i++) y[i]=(long) mygprecrc((GEN)x[i],bitprec,e);
        !           489:       break;
        !           490:
        !           491:     default: y=mygprecrc(x,bitprec,e);
        !           492:   }
        !           493:   return y;
        !           494: }
        !           495:
        !           496: /* the round fonction has a bug in pari. Thus I create mygfloor, using gfloor
        !           497: which has no bug (destroy z)*/
        !           498: static GEN
        !           499: mygfloor(GEN z)
        !           500: {
        !           501:   if (typ(z)!=t_COMPLEX) return gfloor(z);
        !           502:   z[1]=lfloor((GEN)z[1]); z[2]=lfloor((GEN)z[2]); return z;
        !           503: }
        !           504:
        !           505: /* returns a polynomial q in (Z[i])[x] keeping bitprec bits of p */
        !           506: static GEN
        !           507: eval_rel_pol(GEN p,long bitprec)
        !           508: {
        !           509:   long e=gexpo(p),n=lgef(p),i,shift;
        !           510:   GEN q = gprec(p,(long) ((double) bitprec * L2SL10)+2);
        !           511:
        !           512:   shift=bitprec-e+1;
        !           513:   for (i=2; i<n; i++)
        !           514:     q[i]=(long) mygfloor(myshiftic((GEN)q[i],shift));
        !           515:   return q;
        !           516: }
        !           517:
        !           518: /* normalize a polynomial p, that is change it with coefficients in Z[i],
        !           519: after making product by 2^bitprec */
        !           520: static void
        !           521: pol_to_gaussint(GEN p, long bitprec)
        !           522: {
        !           523:   long i,n=lgef(p);
        !           524:   for (i=2; i<n; i++)
        !           525:   {
        !           526:     myshiftrc((GEN) p[i],bitprec);
        !           527:     p[i]=(long) mygfloor((GEN) p[i]);
        !           528:   }
        !           529: }
        !           530:
        !           531: /* returns p(R*x)/R^n (in R or R[i]), n=deg(p), bitprec bits of precision */
        !           532: static GEN
        !           533: homothetie(GEN p, GEN R, long bitprec)
        !           534: {
        !           535:   GEN q,r,gR,aux;
        !           536:   long n=degpol(p),i;
        !           537:
        !           538:   gR=mygprec(ginv(R),bitprec);
        !           539:   q=mygprec(p,bitprec);
        !           540:   r=cgetg(n+3,t_POL); r[1]=p[1];
        !           541:   aux=gR; r[n+2]=q[n+2];
        !           542:   for (i=n-1; i>=0; i--)
        !           543:   {
        !           544:     r[i+2] = lmul(aux,(GEN)q[i+2]);
        !           545:     aux = mulrr(aux,gR);
        !           546:   }
        !           547:   return r;
        !           548: }
        !           549:
        !           550: /* change q in 2^(n*e) p(x*2^(-e)), n=deg(q) */
        !           551: static void
        !           552: homothetie2n(GEN p, long e)
        !           553: {
        !           554:   if (e)
        !           555:   {
        !           556:     long i,n=lgef(p)-1;
        !           557:     for (i=2; i<=n; i++) myshiftrc((GEN) p[i],(n-i)*e);
        !           558:   }
        !           559: }
        !           560:
        !           561: /* return 2^f * 2^(n*e) p(x*2^(-e)), n=deg(q) */
        !           562: static void
        !           563: homothetie_gauss(GEN p, long e,long f)
        !           564: {
        !           565:   if (e||f)
        !           566:   {
        !           567:     long i, n=lgef(p)-1;
        !           568:     for (i=2; i<=n; i++) p[i]=(long) myshiftic((GEN) p[i],f+(n-i)*e);
        !           569:   }
        !           570: }
        !           571:
        !           572: static long
        !           573: valuation(GEN p)
        !           574: {
        !           575:   long j=0,n=degpol(p);
        !           576:
        !           577:   while ((j<=n) && isexactzero((GEN)p[j+2])) j++;
        !           578:   return j;
        !           579: }
        !           580:
        !           581: /* provides usually a good lower bound on the largest modulus of the roots,
        !           582: puts in k an upper bound of the number of roots near the largest root
        !           583: at a distance eps */
        !           584: static double
        !           585: lower_bound(GEN p, long *k, double eps)
        !           586: {
        !           587:   long n=degpol(p),i,j,ltop=avma;
        !           588:   GEN a,s,icd;
        !           589:   double r,*rho;
        !           590:
        !           591:   if (n<4) { *k=n; return 0.; }
        !           592:   a=cgetg(6,t_POL); s=cgetg(6,t_POL);
        !           593:   rho=(double *) gpmalloc(4*sizeof(double));
        !           594:   icd = gdiv(realun(DEFAULTPREC), (GEN) p[n+2]);
        !           595:   for (i=1; i<=4; i++) a[i+1]=lmul(icd,(GEN)p[n+2-i]);
        !           596:   for (i=1; i<=4; i++)
        !           597:   {
        !           598:     s[i+1]=lmulsg(i,(GEN)a[i+1]);
        !           599:     for (j=1; j<i; j++)
        !           600:       s[i+1]=ladd((GEN)s[i+1],gmul((GEN)s[j+1],(GEN)a[i+1-j]));
        !           601:     s[i+1]=lneg((GEN)s[i+1]);
        !           602:     r=gtodouble(gabs((GEN) s[i+1],3));
        !           603:     if (r<=0.)  /* should not be strictly negative */
        !           604:       rho[i-1]=0.;
        !           605:     else
        !           606:       rho[i-1]=exp(log(r/(double)n)/(double) i);
        !           607:   }
        !           608:   r=0.;
        !           609:   for (i=0; i<4; i++) if (r<rho[i]) r=rho[i];
        !           610:   if (r>0. && eps<1.2)
        !           611:     *k=(long) floor((n*rho[0]/r+n)/(1+exp(-eps)*cos(eps)));
        !           612:   else
        !           613:     *k=n;
        !           614:   free(rho); avma=ltop; return r;
        !           615: }
        !           616:
        !           617: /* returns the maximum of the modulus of p with a relative error tau */
        !           618: static GEN
        !           619: max_modulus(GEN p, double tau)
        !           620: {
        !           621:   GEN q,aux,gunr;
        !           622:   long i,j,k,valuat,n=degpol(p),nn,ltop=avma,bitprec,imax,e;
        !           623:   double r,rho,eps, tau2 = (tau > 3.0)? 0.5: tau/6.;
        !           624:
        !           625:   eps = - 1/log(1.5*tau2); /* > 0 */
        !           626:   bitprec=(long) ((double) n*log2(1./tau2)+3*log2((double) n))+1;
        !           627:   gunr=myrealun(bitprec+2*n);
        !           628:   aux=gdiv(gunr,(GEN) p[2+n]);
        !           629:   q=gmul(aux,p); q[2+n]=lcopy(gunr);
        !           630:   k=nn=n;
        !           631:   e=findpower(q); homothetie2n(q,e); r=-(double) e;
        !           632:   q=mygprec(q,bitprec+(n<<1));
        !           633:   pol_to_gaussint(q,bitprec);
        !           634:   imax=(long) ((log(log(4.*n)/(2*tau2))) / log(2.)) + 2;
        !           635:   for (i=0,e=0;;)
        !           636:   {
        !           637:     rho=lower_bound(q,&k,eps);
        !           638:     if (rho>exp2(-(double) e)) e = (long) -floor(log2(rho));
        !           639:     r -= e / exp2((double)i);
        !           640:     if (++i == imax) {
        !           641:       avma=ltop;
        !           642:       return gpui(dbltor(2.),dbltor(r),DEFAULTPREC);
        !           643:     }
        !           644:
        !           645:     if (k<nn)
        !           646:       bitprec=(long) ((double) k* log2(1./tau2)+
        !           647:                       (double) (nn-k)*log2(1./eps)+
        !           648:                       3*log2((double) nn))+1;
        !           649:     else
        !           650:       bitprec=(long) ((double) nn* log2(1./tau2)+
        !           651:                       3.*log2((double) nn))+1;
        !           652:     homothetie_gauss(q,e,bitprec-(long)floor(mylog2((GEN) q[2+nn])+0.5));
        !           653:     valuat=valuation(q);
        !           654:     if (valuat>0)
        !           655:     {
        !           656:       nn-=valuat; setlgef(q,nn+3);
        !           657:       for (j=0; j<=nn; j++) q[2+j]=q[2+valuat+j];
        !           658:     }
        !           659:     set_karasquare_limit(gexpo(q));
        !           660:     q = gerepileupto(ltop, graeffe(q));
        !           661:     tau2=1.5*tau2; eps=1/log(1./tau2);
        !           662:     e = findpower(q);
        !           663:   }
        !           664: }
        !           665:
        !           666: /* return the k-th modulus (in ascending order) of p, rel. error tau*/
        !           667: static GEN
        !           668: modulus(GEN p, long k, double tau)
        !           669: {
        !           670:   GEN q,gunr;
        !           671:   long i,j,kk=k,imax,n=degpol(p),nn,nnn,valuat,av,ltop=avma,bitprec,decprec,e;
        !           672:   double tau2,r;
        !           673:
        !           674:   tau2=tau/6; nn=n;
        !           675:   bitprec= (long) ((double) n*(2.+log2(3.*(double) n)+log2(1./tau2)));
        !           676:   decprec=(long) ((double) bitprec * L2SL10)+1;
        !           677:   gunr=myrealun(bitprec);
        !           678:   av = avma;
        !           679:   q=gprec(p,decprec);
        !           680:   q=gmul(gunr,q);
        !           681:   e=polygone_newton(q,k);
        !           682:   homothetie2n(q,e);
        !           683:   r=(double) e;
        !           684:   imax=(long) ((log2(3./tau)+log2(log(4.*(double) n)) ))+1;
        !           685:   for (i=1; i<imax; i++)
        !           686:   {
        !           687:     q=eval_rel_pol(q,bitprec);
        !           688:
        !           689:     nnn=degpol(q); valuat=valuation(q);
        !           690:     if (valuat>0)
        !           691:     {
        !           692:       kk-=valuat;
        !           693:       for (j=0; j<=nnn-valuat; j++) q[2+j]=q[2+valuat+j];
        !           694:       setlgef(q,nnn-valuat+3);
        !           695:     }
        !           696:     nn=nnn-valuat;
        !           697:
        !           698:     set_karasquare_limit(bitprec);
        !           699:     q = gerepileupto(av, graeffe(q));
        !           700:     e=polygone_newton(q,kk);
        !           701:     r += e / exp2((double)i);
        !           702:     q=gmul(gunr,q);
        !           703:     homothetie2n(q,e);
        !           704:
        !           705:     tau2=1.5*tau2; if (tau2>1.) tau2=1.;
        !           706:     bitprec= 1+(long) ((double) nn*(2.+log2(3.*(double) nn)+log2(1./tau2)));
        !           707:   }
        !           708:   avma=ltop; return mpexp(dbltor(-r * LOG2));
        !           709: }
        !           710:
        !           711: /* return the k-th modulus r_k of p, rel. error tau, knowing that
        !           712: rmin < r_k < rmax. This helps because the information enable us to use
        !           713: less precision... quicker ! */
        !           714: static GEN
        !           715: pre_modulus(GEN p, long k, double tau, GEN rmin, GEN rmax)
        !           716: {
        !           717:   GEN R, q, aux;
        !           718:   long n=degpol(p),i,imax,imax2,bitprec,ltop=avma, av;
        !           719:   double tau2, aux2;
        !           720:
        !           721:   tau2=tau/6.;
        !           722:   aux = mulrr(mpsqrt(divrr(rmax,rmin)), dbltor(exp(4*tau2)));
        !           723:   imax = (long) log2(log((double)n)/ rtodbl(mplog(aux)));
        !           724:   if (imax<=0) return modulus(p,k,tau);
        !           725:
        !           726:   R = mpsqrt(mulrr(rmin,rmax));
        !           727:   av = avma;
        !           728:   bitprec = (long) ((double) n*(2. + log2ir(aux) - log2(tau2)));
        !           729:   q = homothetie(p,R,bitprec);
        !           730:   imax2 = (long) ((log2(3./tau)+log2(log(4.*(double) n)) ))+1;
        !           731:   if (imax>imax2) imax=imax2;
        !           732:
        !           733:   for (i=0; i<imax; i++)
        !           734:   {
        !           735:     q = eval_rel_pol(q,bitprec);
        !           736:     set_karasquare_limit(bitprec);
        !           737:     q = gerepileupto(av, graeffe(q));
        !           738:     affrr(mulrr(gsqr(aux), dbltor(exp(2*tau2))), aux);
        !           739:     tau2 *= 1.5;
        !           740:     bitprec= (long) ((double) n*(2. + log2ir(aux) - log2(1-exp(-tau2))));
        !           741:     q = gmul(myrealun(bitprec),q);
        !           742:   }
        !           743:
        !           744:   aux2 = rtodbl(mplog(modulus(q,k,exp2((double)imax)*tau/3.)));
        !           745:   R = mulrr(R, dbltor(exp(aux2*exp2(-(double)imax))));
        !           746:   return gerepileupto(ltop, R);
        !           747: }
        !           748:
        !           749: /* returns the minimum of the modulus of p with a relative error tau */
        !           750: static GEN
        !           751: min_modulus(GEN p, double tau)
        !           752: {
        !           753:   long av=avma;
        !           754:   GEN r;
        !           755:
        !           756:   if (isexactzero((GEN)p[2])) return realzero(3);
        !           757:   r = max_modulus(polrecip_i(p),tau);
        !           758:   return gerepileupto(av, ginv(r));
        !           759: }
        !           760:
        !           761: /* returns k such that r_k e^(-tau) < R < r_{ k+1 } e^tau.
        !           762: l is such that you know in advance that l<= k <= n-l */
        !           763: static long
        !           764: dual_modulus(GEN p, GEN R, double tau, long l)
        !           765: {
        !           766:   GEN q;
        !           767:   long i,j,imax,k,delta_k=0,n=degpol(p),nn,nnn,valuat,ltop=avma,bitprec,ll=l;
        !           768:   double logmax,aux,tau2;
        !           769:
        !           770:   tau2=7.*tau/8.;
        !           771:   bitprec=6*n-5*l+(long) ((double) n*(log2(1/tau2)+8.*tau2/7.));
        !           772:   q=homothetie(p,R,bitprec);
        !           773:   nn=n;
        !           774:   imax=(long)(log(log(2.*(double)n)/tau2)/log(7./4.)+1);
        !           775:
        !           776:   for (i=0; i<imax; i++)
        !           777:   {
        !           778:     bitprec=6*nn-5*ll+(long) ((double) nn*(log2(1/tau2)+8.*tau2/7.));
        !           779:
        !           780:     q=eval_rel_pol(q,bitprec);
        !           781:     nnn=degpol(q); valuat=valuation(q);
        !           782:     if (valuat>0)
        !           783:     {
        !           784:       delta_k+=valuat;
        !           785:       for (j=0; j<=nnn-valuat; j++) q[2+j]=q[2+valuat+j];
        !           786:       setlgef(q,nnn-valuat+3);
        !           787:     }
        !           788:     ll= (-valuat<nnn-n)? ll-valuat: ll+nnn-n; /* min(ll-valuat,ll+nnn-n) */
        !           789:     if (ll<0) ll=0;
        !           790:
        !           791:     nn=nnn-valuat;
        !           792:     if (nn==0) return delta_k;
        !           793:
        !           794:     set_karasquare_limit(bitprec);
        !           795:     q = gerepileupto(ltop, graeffe(q));
        !           796:     tau2=tau2*7./4.;
        !           797:   }
        !           798:   k=-1; logmax=- (double) pariINFINITY;
        !           799:   for (i=0; i<=degpol(q); i++)
        !           800:   {
        !           801:     aux=mylog2((GEN)q[2+i]);
        !           802:     if (aux>logmax) { logmax=aux; k=i; }
        !           803:   }
        !           804:   avma=ltop; return delta_k+k;
        !           805: }
        !           806:
        !           807: /********************************************************************/
        !           808: /**                                                                **/
        !           809: /**       CALCUL D'UN FACTEUR PAR INTEGRATION SUR LE CERCLE        **/
        !           810: /**                                                                **/
        !           811: /********************************************************************/
        !           812:
        !           813: static GEN
        !           814: gmulbyi(GEN z)
        !           815: {
        !           816:   GEN aux = cgetg(3,t_COMPLEX);
        !           817:
        !           818:   if (typ(z)!=t_COMPLEX)
        !           819:   {
        !           820:     aux[1]=zero;
        !           821:     aux[2]=(long) z;
        !           822:   }
        !           823:   else
        !           824:   {
        !           825:     aux[1]=lneg((GEN)z[2]);
        !           826:     aux[2]=z[1];
        !           827:   }
        !           828:   return aux;
        !           829: }
        !           830:
        !           831: static void
        !           832: fft(GEN Omega, GEN p, GEN f, long Step, long l)
        !           833: {
        !           834:   ulong ltop;
        !           835:   long i,l1,l2,l3,rap=Lmax/l,rapi,Step4;
        !           836:   GEN f1,f2,f3,f02,f13,g02,g13,ff;
        !           837:
        !           838:   if (l==2)
        !           839:   {
        !           840:     f[0]=ladd((GEN)p[0],(GEN)p[Step]);
        !           841:     f[1]=lsub((GEN)p[0],(GEN)p[Step]); return;
        !           842:   }
        !           843:   if (l==4)
        !           844:   {
        !           845:     f1=gadd((GEN)p[0],(GEN)p[(Step<<1)]);
        !           846:     f3=gadd((GEN)p[Step],(GEN)p[3*Step]);
        !           847:     f[0]=ladd(f1,f3);
        !           848:     f[2]=lsub(f1,f3);
        !           849:
        !           850:     f2=gsub((GEN)p[0],(GEN)p[(Step<<1)]);
        !           851:     f02=gsub((GEN)p[Step],(GEN)p[3*Step]);
        !           852:     f02=gmulbyi(f02);
        !           853:     f[1]=ladd(f2,f02);
        !           854:     f[3]=lsub(f2,f02);
        !           855:     return;
        !           856:   }
        !           857:
        !           858:   l1=(l>>2); l2=(l1<<1); l3=l1+l2; Step4=(Step<<2);
        !           859:
        !           860:   ltop=avma;
        !           861:   fft(Omega,p,f,Step4,l1);
        !           862:   fft(Omega,p+Step,f+l1,Step4,l1);
        !           863:   fft(Omega,p+(Step<<1),f+l2,Step4,l1);
        !           864:   fft(Omega,p+3*Step,f+l3,Step4,l1);
        !           865:
        !           866:   ff=cgetg(l+1,t_VEC);
        !           867:   for (i=0; i<l1; i++)
        !           868:   {
        !           869:     rapi=rap*i;
        !           870:     f1=gmul((GEN)Omega[rapi],(GEN) f[i+l1]);
        !           871:     f2=gmul((GEN)Omega[(rapi<<1)],(GEN) f[i+l2]);
        !           872:     f3=gmul((GEN)Omega[3*rapi],(GEN) f[i+l3]);
        !           873:
        !           874:     f02=gadd((GEN)f[i],f2);
        !           875:     g02=gsub((GEN)f[i],f2);
        !           876:     f13=gadd(f1,f3);
        !           877:     g13=gmulbyi(gsub(f1,f3));
        !           878:
        !           879:     ff[i+1]=ladd(f02,f13);
        !           880:     ff[i+l1+1]=ladd(g02,g13);
        !           881:     ff[i+l2+1]=lsub(f02,f13);
        !           882:     ff[i+l3+1]=lsub(g02,g13);
        !           883:   }
        !           884:   ff=gerepilecopy(ltop,ff);
        !           885:   for (i=0; i<l; i++) f[i]=ff[i+1];
        !           886: }
        !           887:
        !           888: extern void mpsincos(GEN x, GEN *s, GEN *c);
        !           889:
        !           890: /* return exp(ix), x a t_REAL */
        !           891: static GEN
        !           892: exp_i(GEN x)
        !           893: {
        !           894:   GEN v;
        !           895:
        !           896:   if (!signe(x)) return realun(lg(x)); /* should not happen */
        !           897:   v = cgetg(3,t_COMPLEX);
        !           898:   mpsincos(x, (GEN*)(v+2), (GEN*)(v+1));
        !           899:   return v;
        !           900: }
        !           901:
        !           902: /* e(1/N) */
        !           903: static GEN
        !           904: RUgen(long N, long bitprec)
        !           905: {
        !           906:   GEN pi2;
        !           907:   if (N == 2) return mpneg(realun(bitprec));
        !           908:   if (N == 4) return gi;
        !           909:   pi2 = gmul2n(mppi(bitprec/BITS_IN_LONG+3), 1);
        !           910:   return exp_i(gdivgs(pi2,N));
        !           911: }
        !           912:
        !           913: /* N=2^k. returns a vector RU which contains exp(2*i*k*Pi/N), k=0..N-1 */
        !           914: static GEN
        !           915: initRU(long N, long bitprec)
        !           916: {
        !           917:   GEN prim,aux,*RU;
        !           918:   long i,N2=(N>>1),N4=(N>>2),N8=(N>>3);
        !           919:
        !           920:   RU = (GEN*)cgetg(N+1,t_VEC); RU++;
        !           921:   prim = RUgen(N, bitprec);
        !           922:
        !           923:   RU[0] = myrealun(bitprec);
        !           924:   for (i=1; i<=N8; i++) RU[i] = gmul(prim, RU[i-1]);
        !           925:   for (i=1; i<N8; i++)
        !           926:   {
        !           927:     aux=cgetg(3,t_COMPLEX);
        !           928:     aux[1]=RU[i][2];
        !           929:     aux[2]=RU[i][1]; RU[N4-i]=aux;
        !           930:   }
        !           931:   for (i=0; i<N4; i++) RU[i+N4]=gmulbyi(RU[i]);
        !           932:   for (i=0; i<N2; i++) RU[i+N2]=gneg(RU[i]);
        !           933:   return (GEN)RU;
        !           934: }
        !           935:
        !           936: /* as above, N arbitrary */
        !           937: static GEN
        !           938: initRUgen(long N, long bitprec)
        !           939: {
        !           940:   GEN *RU = (GEN*)cgetg(N+1,t_VEC), z = RUgen(N,bitprec);
        !           941:   long i, k = (N+3)>>1;
        !           942:   RU[0] = gun;
        !           943:   RU[1] = z;
        !           944:   for (i=2; i<k; i++) RU[i] = gmul(z, RU[i-1]);
        !           945:   for (   ; i<N; i++) RU[i] = gconj(RU[N-i]);
        !           946:   return (GEN)RU;
        !           947: }
        !           948:
        !           949: /* returns 1 if p has only real coefficients, 0 else */
        !           950: static long
        !           951: isreal(GEN p)
        !           952: {
        !           953:   long n=degpol(p),i=0;
        !           954:
        !           955:   while (i<=n && typ(p[i+2])!=t_COMPLEX) i++;
        !           956:   return (i>n);
        !           957: }
        !           958:
        !           959: static void
        !           960: parameters(GEN p, double *mu, double *gamma,
        !           961:            long polreal, double param, double param2)
        !           962: {
        !           963:   GEN q,pc,Omega,coef,RU,prim,aux,aux0,ggamma,gx,mygpi;
        !           964:   long ltop=avma,limite=stack_lim(ltop,1),n=degpol(p),bitprec,NN,K,i,j,ltop2;
        !           965:   double lx;
        !           966:
        !           967:   bitprec=gexpo(p)+(long)param2+8;
        !           968:   NN=(long) (param*3.14)+1; if (NN<Lmax) NN=Lmax;
        !           969:   K=NN/Lmax; if (K%2==1) K++; NN=Lmax*K;
        !           970:   mygpi=mppi(bitprec/BITS_IN_LONG+3);
        !           971:   aux = gdivgs(mygpi,NN/2); /* 2 Pi/NN */
        !           972:   prim = exp_i(aux);
        !           973:   aux = gmulbyi(aux);
        !           974:   RU = myrealun(bitprec);
        !           975:
        !           976:   Omega=initRU(Lmax,bitprec);
        !           977:
        !           978:   q=mygprec(p,bitprec);
        !           979:   pc=cgetg(Lmax+1,t_VEC); pc++;
        !           980:   for (i=n+1; i<Lmax; i++) pc[i]=zero;
        !           981:
        !           982:   coef=cgetg(Lmax+1,t_VEC); coef++;
        !           983:   *mu=(double)pariINFINITY; *gamma=0.;
        !           984:   ggamma = gzero;
        !           985:   aux0 = myrealun(bitprec);
        !           986:   if (polreal) K=K/2+1;
        !           987:   ltop2=avma;
        !           988:   for (i=0; i<K; i++)
        !           989:   {
        !           990:     aux = aux0;
        !           991:     for (j=0; j<=n; j++)
        !           992:     {
        !           993:       pc[j]=lmul((GEN)q[j+2],aux);
        !           994:       aux=gmul(aux,RU); /* RU = prim^i, aux=prim^(ij) */
        !           995:     }
        !           996:
        !           997:     fft(Omega,pc,coef,1,Lmax);
        !           998:     for (j=0; j<Lmax; j++)
        !           999:     {
        !          1000:       aux=gprec((GEN)coef[j],DEFAULTPREC);
        !          1001:       gx=gabs(aux,DEFAULTPREC);
        !          1002:       lx=gtodouble(mplog(gx));
        !          1003:       if (lx<*mu) *mu=lx;
        !          1004:       if (polreal && (i>0 && i<K-1))
        !          1005:       {
        !          1006:        gx=gdiv(gdeux,gx);
        !          1007:        ggamma=gadd(ggamma,gx);
        !          1008:       }
        !          1009:       else
        !          1010:        ggamma=gadd(ggamma,ginv(gx));
        !          1011:     }
        !          1012:     RU=gmul(RU,prim);
        !          1013:     if (low_stack(limite, stack_lim(ltop,1)))
        !          1014:     {
        !          1015:       GEN *gptr[2];
        !          1016:       if(DEBUGMEM>1) err(warnmem,"parameters");
        !          1017:       gptr[0]=&ggamma; gptr[1]=&RU; gerepilemany(ltop2,gptr,2);
        !          1018:     }
        !          1019:   }
        !          1020:   ggamma=gdivgs(ggamma,NN);
        !          1021:   *gamma=gtodouble(glog(ggamma,DEFAULTPREC))/log(2.);
        !          1022:   avma=ltop;
        !          1023: }
        !          1024:
        !          1025: /* NN is a multiple of Lmax */
        !          1026: static void
        !          1027: dft(GEN p, long k, long NN, long bitprec, GEN F, GEN H, long polreal)
        !          1028: {
        !          1029:   GEN Omega,q,qd,pc,pdc,alpha,beta,gamma,RU,aux,U,W,mygpi,prim,prim2;
        !          1030:   long limite,n=degpol(p),i,j,K,ltop;
        !          1031:
        !          1032:   mygpi=mppi(bitprec/BITS_IN_LONG+3);
        !          1033:   aux = gdivgs(mygpi,NN/2); /* 2 Pi/NN */
        !          1034:   prim = exp_i(aux);
        !          1035:   aux = gmulbyi(aux);
        !          1036:   prim2 = myrealun(bitprec);
        !          1037:   RU=cgetg(n+2,t_VEC); RU++;
        !          1038:
        !          1039:   Omega=initRU(Lmax,bitprec);
        !          1040:   K=NN/Lmax; q=mygprec(p,bitprec);
        !          1041:   qd=derivpol(q);
        !          1042:
        !          1043:   pc=cgetg(Lmax+1,t_VEC); pc++;
        !          1044:   for (i=n+1; i<Lmax; i++) pc[i]=zero;
        !          1045:   pdc=cgetg(Lmax+1,t_VEC); pdc++;
        !          1046:   for (i=n; i<Lmax; i++) pdc[i]=zero;
        !          1047:
        !          1048:   alpha=cgetg(Lmax+1,t_VEC); alpha++;
        !          1049:   beta=cgetg(Lmax+1,t_VEC); beta++;
        !          1050:   gamma=cgetg(Lmax+1,t_VEC); gamma++;
        !          1051:
        !          1052:   if (polreal) K=K/2+1;
        !          1053:
        !          1054:   ltop=avma; limite = stack_lim(ltop,1);
        !          1055:   W=cgetg(k+1,t_VEC); U=cgetg(k+1,t_VEC);
        !          1056:   for (i=1; i<=k; i++) W[i]=U[i]=zero;
        !          1057:
        !          1058:   for (i=0; i<K; i++)
        !          1059:   {
        !          1060:     RU[0]=(long) gun;
        !          1061:     for (j=1; j<=n; j++) RU[j]=lmul((GEN)RU[j-1],prim2);
        !          1062:     /* RU[j]=prim^{ ij }=prim2^j */
        !          1063:
        !          1064:     for (j=0; j<n; j++) pdc[j]=lmul((GEN)qd[j+2],(GEN)RU[j]);
        !          1065:     fft(Omega,pdc,alpha,1,Lmax);
        !          1066:     for (j=0; j<=n; j++) pc[j]=lmul((GEN)q[j+2],(GEN)RU[j]);
        !          1067:     fft(Omega,pc,beta,1,Lmax);
        !          1068:     for (j=0; j<Lmax; j++) gamma[j]=linv((GEN)beta[j]);
        !          1069:     for (j=0; j<Lmax; j++) beta[j]=lmul((GEN)alpha[j],(GEN)gamma[j]);
        !          1070:     fft(Omega,beta,alpha,1,Lmax);
        !          1071:     fft(Omega,gamma,beta,1,Lmax);
        !          1072:
        !          1073:     if (polreal) /* p has real coefficients */
        !          1074:     {
        !          1075:       if (i>0 && i<K-1)
        !          1076:       {
        !          1077:        for (j=1; j<=k; j++)
        !          1078:        {
        !          1079:          aux=gmul((GEN)alpha[j+1],(GEN)RU[j+1]);
        !          1080:          W[j]=ladd((GEN)W[j],gshift(greal(aux),1));
        !          1081:          aux=gmul((GEN)beta[j],(GEN)RU[j]);
        !          1082:          U[j]=ladd((GEN)U[j],gshift(greal(aux),1));
        !          1083:        }
        !          1084:       }
        !          1085:       else
        !          1086:       {
        !          1087:        for (j=1; j<=k; j++)
        !          1088:        {
        !          1089:          aux=gmul((GEN)alpha[j+1],(GEN)RU[j+1]);
        !          1090:          W[j]=ladd((GEN)W[j],greal(aux));
        !          1091:          aux=gmul((GEN)beta[j],(GEN)RU[j]);
        !          1092:          U[j]=ladd((GEN)U[j],greal(aux));
        !          1093:        }
        !          1094:       }
        !          1095:     }
        !          1096:     else
        !          1097:     {
        !          1098:       for (j=1; j<=k; j++)
        !          1099:       {
        !          1100:        W[j]=ladd((GEN)W[j],gmul((GEN)alpha[j+1],(GEN)RU[j+1]));
        !          1101:        U[j]=ladd((GEN)U[j],gmul((GEN)beta[j],(GEN)RU[j]));
        !          1102:       }
        !          1103:     }
        !          1104:     prim2=gmul(prim2,prim);
        !          1105:     if (low_stack(limite, stack_lim(ltop,1)))
        !          1106:     {
        !          1107:       GEN *gptr[3];
        !          1108:       if(DEBUGMEM>1) err(warnmem,"dft");
        !          1109:       gptr[0]=&W; gptr[1]=&U; gptr[2]=&prim2;
        !          1110:       gerepilemany(ltop,gptr,3);
        !          1111:     }
        !          1112:   }
        !          1113:
        !          1114:   for (i=1; i<=k; i++)
        !          1115:   {
        !          1116:     aux=(GEN)W[i];
        !          1117:     for (j=1; j<i; j++) aux=gadd(aux,gmul((GEN)W[i-j],(GEN)F[k+2-j]));
        !          1118:     F[k+2-i] = ldivgs(aux,-i*NN);
        !          1119:   }
        !          1120:   for (i=0; i<k; i++)
        !          1121:   {
        !          1122:     aux=(GEN)U[k-i];
        !          1123:     for (j=1+i; j<k; j++) aux=gadd(aux,gmul((GEN)F[2+j],(GEN)U[j-i]));
        !          1124:     H[i+2] = ldivgs(aux,NN);
        !          1125:   }
        !          1126: }
        !          1127:
        !          1128: static GEN
        !          1129: refine_H(GEN F, GEN G, GEN HH, long bitprec, long shiftbitprec)
        !          1130: {
        !          1131:   GEN H=HH,D,aux;
        !          1132:   ulong ltop=avma, limite=stack_lim(ltop,1);
        !          1133:   long error=0,i,bitprec1,bitprec2;
        !          1134:
        !          1135:   D=gsub(gun,gres(gmul(HH,G),F)); error=gexpo(D);
        !          1136:   bitprec2=bitprec+shiftbitprec;
        !          1137:
        !          1138:   for (i=0; (error>-bitprec && i<NEWTON_MAX) && error<=0; i++)
        !          1139:   {
        !          1140:     if (low_stack(limite, stack_lim(ltop,1)))
        !          1141:     {
        !          1142:       GEN *gptr[2];
        !          1143:       if(DEBUGMEM>1) err(warnmem,"refine_H");
        !          1144:       gptr[0]=&D; gptr[1]=&H; gerepilemany(ltop,gptr,2);
        !          1145:     }
        !          1146:     bitprec1=-error+shiftbitprec;
        !          1147:     aux=gmul(mygprec(H,bitprec1),mygprec(D,bitprec1));
        !          1148:     aux=mygprec(aux,bitprec1);
        !          1149:     aux=gres(aux,mygprec(F,bitprec1));
        !          1150:
        !          1151:     bitprec1=-error*2+shiftbitprec;
        !          1152:     if (bitprec1>bitprec2) bitprec1=bitprec2;
        !          1153:     H=gadd(mygprec(H,bitprec1),aux);
        !          1154:     D=gsub(gun,gres(gmul(H,G),F));
        !          1155:     error=gexpo(D); if (error<-bitprec1) error=-bitprec1;
        !          1156:   }
        !          1157:   if (error<=-bitprec/2) return gerepilecopy(ltop,H);
        !          1158:   avma=ltop; return gzero; /* procedure failed */
        !          1159: }
        !          1160:
        !          1161: /* return 0 if fails, 1 else */
        !          1162: static long
        !          1163: refine_F(GEN p, GEN *F, GEN *G, GEN H, long bitprec, double gamma)
        !          1164: {
        !          1165:   GEN pp,FF,GG,r,HH,f0;
        !          1166:   long error,i,bitprec1=0,bitprec2,ltop=avma,shiftbitprec;
        !          1167:   long shiftbitprec2,n=degpol(p),enh,normF,normG,limite=stack_lim(ltop,1);
        !          1168:
        !          1169:   FF=*F; HH=H;
        !          1170:   GG=poldivres(p,*F,&r);
        !          1171:   normF=gexpo(FF);
        !          1172:   normG=gexpo(GG);
        !          1173:   enh=gexpo(H); if (enh<0) enh=0;
        !          1174:   shiftbitprec=normF+2*normG+enh+(long) (4.*log2((double)n)+gamma) +1;
        !          1175:   shiftbitprec2=enh+2*(normF+normG)+(long) (2.*gamma+5.*log2((double)n))+1;
        !          1176:   bitprec2=bitprec+shiftbitprec;
        !          1177:   error=gexpo(r);
        !          1178:   if (error<-bitprec) error=1-bitprec;
        !          1179:   for (i=0; (error>-bitprec && i<NEWTON_MAX) && error<=0; i++)
        !          1180:   {
        !          1181:     if ((bitprec1==bitprec2) && (i>=2))
        !          1182:     {
        !          1183:       shiftbitprec+=n; shiftbitprec2+=n; bitprec2+=n;
        !          1184:     }
        !          1185:     if (low_stack(limite, stack_lim(ltop,1)))
        !          1186:     {
        !          1187:       GEN *gptr[4];
        !          1188:       if(DEBUGMEM>1) err(warnmem,"refine_F");
        !          1189:       gptr[0]=&FF; gptr[1]=&GG; gptr[2]=&r; gptr[3]=&HH;
        !          1190:       gerepilemany(ltop,gptr,4);
        !          1191:     }
        !          1192:
        !          1193:     bitprec1=-error+shiftbitprec2;
        !          1194:     HH=refine_H(mygprec(FF,bitprec1),mygprec(GG,bitprec1),
        !          1195:                mygprec(HH,bitprec1),1-error,shiftbitprec2);
        !          1196:     if (HH==gzero) return 0; /* procedure failed */
        !          1197:
        !          1198:     bitprec1=-error+shiftbitprec;
        !          1199:     r=gmul(mygprec(HH,bitprec1),mygprec(r,bitprec1));
        !          1200:     r=mygprec(r,bitprec1);
        !          1201:     f0=gres(r,mygprec(FF,bitprec1));
        !          1202:
        !          1203:     bitprec1=-2*error+shiftbitprec;
        !          1204:     if (bitprec1>bitprec2) bitprec1=bitprec2;
        !          1205:     FF=gadd(mygprec(FF,bitprec1),f0);
        !          1206:
        !          1207:     bitprec1=-3*error+shiftbitprec;
        !          1208:     if (bitprec1>bitprec2) bitprec1=bitprec2;
        !          1209:     pp=mygprec(p,bitprec1);
        !          1210:     GG=poldivres(pp,mygprec(FF,bitprec1),&r);
        !          1211:     error=gexpo(r); if (error<-bitprec1) error=-bitprec1;
        !          1212:   }
        !          1213:   if (error<=-bitprec)
        !          1214:   {
        !          1215:     *F=FF; *G=GG;
        !          1216:     return 1; /* procedure succeeds */
        !          1217:   }
        !          1218:   return 0; /* procedure failed */
        !          1219: }
        !          1220:
        !          1221: /* returns F and G from the unit circle U such that |p-FG|<2^(-bitprec) |cd|,
        !          1222: where cd is the leading coefficient of p */
        !          1223: static void
        !          1224: split_fromU(GEN p, long k, double delta, long bitprec,
        !          1225:             GEN *F, GEN *G, double param, double param2)
        !          1226: {
        !          1227:   GEN pp,FF,GG,H;
        !          1228:   long n=degpol(p),NN,bitprec2,
        !          1229:   ltop=avma,polreal=isreal(p);
        !          1230:   double mu,gamma;
        !          1231:
        !          1232:   pp=gdiv(p,(GEN)p[2+n]);
        !          1233:   Lmax=4; while (Lmax<=n) Lmax=(Lmax<<1);
        !          1234:   parameters(pp,&mu,&gamma,polreal,param,param2);
        !          1235:
        !          1236:   H =cgetg(k+2,t_POL); H[1] =evalsigne(1) | evalvarn(varn(p)) | evallgef(k+2);
        !          1237:   FF=cgetg(k+3,t_POL); FF[1]=evalsigne(1) | evalvarn(varn(p)) | evallgef(k+3);
        !          1238:   FF[k+2]=un;
        !          1239:
        !          1240:   NN=(long) (0.5/delta); NN+=(NN%2); if (NN<2) NN=2;
        !          1241:   NN=NN*Lmax; ltop=avma;
        !          1242:   for(;;)
        !          1243:   {
        !          1244:     bitprec2=(long) (((double) NN*delta-mu)/log(2.))+gexpo(pp)+8;
        !          1245:     dft(pp,k,NN,bitprec2,FF,H,polreal);
        !          1246:     if (refine_F(pp,&FF,&GG,H,bitprec,gamma)) break;
        !          1247:     NN=(NN<<1); avma=ltop;
        !          1248:   }
        !          1249:   *G=gmul(GG,(GEN)p[2+n]); *F=FF;
        !          1250: }
        !          1251:
        !          1252: static void
        !          1253: optimize_split(GEN p, long k, double delta, long bitprec,
        !          1254:             GEN *F, GEN *G, double param, double param2)
        !          1255: {
        !          1256:   long n=degpol(p);
        !          1257:   GEN FF,GG;
        !          1258:
        !          1259:   if (k<=n/2)
        !          1260:     split_fromU(p,k,delta,bitprec,F,G,param,param2);
        !          1261:   else
        !          1262:   { /* start from the reciprocal of p */
        !          1263:     split_fromU(polrecip_i(p),n-k,delta,bitprec,&FF,&GG,param,param2);
        !          1264:     *F=polrecip(GG); *G=polrecip(FF);
        !          1265:   }
        !          1266: }
        !          1267:
        !          1268: /********************************************************************/
        !          1269: /**                                                                **/
        !          1270: /**             RECHERCHE DU CERCLE DE SEPARATION                  **/
        !          1271: /**                                                                **/
        !          1272: /********************************************************************/
        !          1273:
        !          1274: /* return p(2^e*x) *2^(-n*e) */
        !          1275: static void
        !          1276: scalepol2n(GEN p, long e)
        !          1277: {
        !          1278:   long i,n=lgef(p)-1;
        !          1279:   for (i=2; i<=n; i++) p[i]=lmul2n((GEN)p[i],(i-n)*e);
        !          1280: }
        !          1281:
        !          1282: /* returns p(x/R)*R^n */
        !          1283: static GEN
        !          1284: scalepol(GEN p, GEN R, long bitprec)
        !          1285: {
        !          1286:   GEN q,aux,gR;
        !          1287:   long i;
        !          1288:
        !          1289:   aux = gR = mygprec(R,bitprec); q = mygprec(p,bitprec);
        !          1290:   for (i=lgef(p)-2; i>=2; i--)
        !          1291:   {
        !          1292:     q[i]=lmul(aux,(GEN)q[i]);
        !          1293:     aux = gmul(aux,gR);
        !          1294:   }
        !          1295:   return q;
        !          1296: }
        !          1297:
        !          1298: extern GEN addshiftpol(GEN x, GEN y, long d);
        !          1299:
        !          1300: /* returns q(x) = p(x+b) */
        !          1301: static GEN
        !          1302: shiftpol(GEN p, GEN b)
        !          1303: {
        !          1304:   long av = avma,i, limit = stack_lim(av,1);
        !          1305:   GEN q = gzero;
        !          1306:
        !          1307:   if (gcmp0(b)) return p;
        !          1308:
        !          1309:   for (i=lgef(p)-1; i>=2; i--)
        !          1310:   {
        !          1311:     if (!signe(q)) { q = scalarpol((GEN)p[i], varn(p)); continue; }
        !          1312:     q = addshiftpol(q, gmul(b,q), 1); /* q = q*(x + b) */
        !          1313:     q[2] = ladd((GEN)q[2], (GEN)p[i]); /* q = q + p[i] */
        !          1314:     if (low_stack(limit, stack_lim(av,1)))
        !          1315:     {
        !          1316:       if(DEBUGMEM>1) err(warnmem,"rootpol.c:shiftpol()");
        !          1317:       q = gerepilecopy(av, q);
        !          1318:     }
        !          1319:   }
        !          1320:   return gerepilecopy(av, q);
        !          1321: }
        !          1322:
        !          1323: /* return (conj(a)X-1)^n * p[ (X-a) / (conj(a)X-1) ] */
        !          1324: static GEN
        !          1325: conformal_pol(GEN p, GEN a, long bitprec)
        !          1326: {
        !          1327:   GEN r,pui,num,aux, unr = myrealun(bitprec);
        !          1328:   long n=degpol(p), i;
        !          1329:   ulong av, limit;
        !          1330:
        !          1331:   aux = pui = cgetg(4,t_POL);
        !          1332:   pui[1] = evalsigne(1) | evalvarn(varn(p)) | evallgef(4);
        !          1333:   pui[2] = (long)negr(unr);
        !          1334:   pui[3] = lconj(a); /* X conj(a) - 1 */
        !          1335:   num = cgetg(4,t_POL);
        !          1336:   num[1] = pui[1];
        !          1337:   num[2] = lneg(a);
        !          1338:   num[3] = (long)unr; /* X - a */
        !          1339:   r = (GEN)p[2+n];
        !          1340:   av = avma; limit = stack_lim(av,2);
        !          1341:   for (i=n-1; ; i--)
        !          1342:   {
        !          1343:     r = gadd(gmul(r,num), gmul(aux,(GEN) p[2+i]));
        !          1344:     if (i == 0) return r;
        !          1345:     aux = gmul(pui,aux);
        !          1346:     if (low_stack(limit, stack_lim(av,2)))
        !          1347:     {
        !          1348:       GEN *gptr[2]; gptr[0] = &r; gptr[1] = &aux;
        !          1349:       if(DEBUGMEM>1) err(warnmem,"rootpol.c:conformal_pol()");
        !          1350:       gerepilemany(av, gptr, 2);
        !          1351:     }
        !          1352:   }
        !          1353: }
        !          1354:
        !          1355: static GEN
        !          1356: compute_radius(GEN* radii, GEN p, long k, double aux, double *delta)
        !          1357: {
        !          1358:   long i, n = degpol(p);
        !          1359:   GEN rmin,rmax,p1;
        !          1360:   if (k>1)
        !          1361:   {
        !          1362:     i=k-1; while (i>0 && !signe(radii[i])) i--;
        !          1363:     rmin = pre_modulus(p,k,aux, radii[i], radii[k]);
        !          1364:   }
        !          1365:   else /* k=1 */
        !          1366:     rmin = min_modulus(p,aux);
        !          1367:   affrr(rmin, radii[k]);
        !          1368:
        !          1369:   if (k+1<n)
        !          1370:   {
        !          1371:     i=k+2; while (i<=n && !signe(radii[i])) i++;
        !          1372:     rmax = pre_modulus(p,k+1,aux, radii[k+1], radii[i]);
        !          1373:   }
        !          1374:   else /* k+1=n */
        !          1375:     rmax = max_modulus(p,aux);
        !          1376:   affrr(rmax, radii[k+1]);
        !          1377:
        !          1378:   p1 = radii[k];
        !          1379:   for (i=k-1; i>=1; i--)
        !          1380:   {
        !          1381:     if (!signe(radii[i]) || cmprr(radii[i], p1) > 0)
        !          1382:       affrr(p1, radii[i]);
        !          1383:     else
        !          1384:       p1 = radii[i];
        !          1385:   }
        !          1386:   p1 = radii[k+1];
        !          1387:   for (i=k+1; i<=n; i++)
        !          1388:   {
        !          1389:     if (!signe(radii[i]) || cmprr(radii[i], p1) < 0)
        !          1390:       affrr(p1, radii[i]);
        !          1391:     else
        !          1392:       p1 = radii[i];
        !          1393:   }
        !          1394:   *delta = rtodbl(gmul2n(mplog(divrr(rmax,rmin)), -1));
        !          1395:   if (*delta > 1.) *delta = 1.;
        !          1396:   return mpsqrt(mulrr(rmin,rmax));
        !          1397: }
        !          1398:
        !          1399: static GEN
        !          1400: update_radius(GEN *radii, GEN rho, double *par, double *par2)
        !          1401: {
        !          1402:   GEN p1, invrho = ginv(rho);
        !          1403:   long i, n = lg(radii);
        !          1404:   double t, param = 0., param2 = 0.;
        !          1405:   for (i=1; i<n; i++)
        !          1406:   {
        !          1407:     affrr(mulrr(radii[i], invrho), radii[i]);
        !          1408:     p1 = ginv(subsr(1, radii[i]));
        !          1409:     t = fabs(rtodbl(p1));
        !          1410:     param += t; if (t > 1.) param2 += log2(t);
        !          1411:   }
        !          1412:   *par = param; *par2 = param2; return invrho;
        !          1413: }
        !          1414:
        !          1415: /* apply the conformal mapping then split from U */
        !          1416: static void
        !          1417: conformal_mapping(GEN *radii, GEN ctr, GEN p, long k, long bitprec,
        !          1418:                   double aux, GEN *F,GEN *G)
        !          1419: {
        !          1420:   long bitprec2,n=degpol(p),decprec,i,ltop = avma, av;
        !          1421:   GEN q,FF,GG,a,R, *gptr[2];
        !          1422:   GEN rho,invrho;
        !          1423:   double delta,param,param2;
        !          1424:
        !          1425:   bitprec2=bitprec+(long) (n*(2.*log2(2.732)+log2(1.5)))+1;
        !          1426:   a=gsqrt(stoi(3), 2*MEDDEFAULTPREC - 2);
        !          1427:   a=gmul(mygprec(a,bitprec2),mygprec(ctr,bitprec2));
        !          1428:   a=gdivgs(a,-6); /* a = -ctr/2sqrt(3) */
        !          1429:
        !          1430:   av = avma; q = mygprec(p,bitprec2);
        !          1431:   q = conformal_pol(q,a,bitprec2);
        !          1432:   for (i=1; i<=n; i++)
        !          1433:     if (signe(radii[i])) /* updating array radii */
        !          1434:     {
        !          1435:       long a = avma;
        !          1436:       GEN p1 = gsqr(radii[i]);
        !          1437:       /* 2(r^2 - 1) / (r^2 - 3(r-1)) */
        !          1438:       p1 = divrr(gmul2n((subrs(p1,1)),1),
        !          1439:                    subrr(p1, mulsr(3,subrs(radii[i],1))));
        !          1440:       affrr(mpsqrt(addsr(1,p1)), radii[i]);
        !          1441:       avma = a;
        !          1442:     }
        !          1443:
        !          1444:   rho = compute_radius(radii, q,k,aux/10., &delta);
        !          1445:   invrho = update_radius(radii, rho, &param, &param2);
        !          1446:
        !          1447:   bitprec2 += (long) (((double)n) * fabs(log2ir(rho)) + 1.);
        !          1448:   R = mygprec(invrho,bitprec2);
        !          1449:   q = scalepol(q,R,bitprec2);
        !          1450:   gptr[0] = &q; gptr[1] = &R;
        !          1451:   gerepilemany(av,gptr,2);
        !          1452:
        !          1453:   optimize_split(q,k,delta,bitprec2,&FF,&GG,param,param2);
        !          1454:   bitprec2 += n; R = ginv(R);
        !          1455:   FF = scalepol(FF,R,bitprec2);
        !          1456:   GG = scalepol(GG,R,bitprec2);
        !          1457:
        !          1458:   a = mygprec(a,bitprec2);
        !          1459:   FF = conformal_pol(FF,a,bitprec2);
        !          1460:   GG = conformal_pol(GG,a,bitprec2);
        !          1461:   a = ginv(gsub(gun, gnorm(a)));
        !          1462:   a = glog(a,(long) (bitprec2 * L2SL10)+1);
        !          1463:
        !          1464:   decprec = (long) ((bitprec+n) * L2SL10)+1;
        !          1465:   FF = gmul(FF,gexp(gmulgs(a,k),decprec));
        !          1466:   GG = gmul(GG,gexp(gmulgs(a,n-k),decprec));
        !          1467:
        !          1468:   *F = mygprec(FF,bitprec+n);
        !          1469:   *G = mygprec(GG,bitprec+n);
        !          1470:   gptr[0]=F; gptr[1]=G; gerepilemany(ltop,gptr,2);
        !          1471: }
        !          1472:
        !          1473: /* split p, this time with no scaling. returns in F and G two polynomials
        !          1474: such that |p-FG|< 2^(-bitprec)|p| */
        !          1475: static void
        !          1476: split_2(GEN p, long bitprec, GEN ctr, double thickness, GEN *F, GEN *G)
        !          1477: {
        !          1478:   GEN rmin,rmax,rho,invrho;
        !          1479:   double kappa,aux,delta,param,param2;
        !          1480:   long n=degpol(p),i,j,k,bitprec2;
        !          1481:   GEN q,FF,GG,R;
        !          1482:   GEN *radii = (GEN*) cgetg(n+1, t_VEC);
        !          1483:   for (i=2; i<n; i++) radii[i]=realzero(3);
        !          1484:   aux = thickness/(double) n/4.;
        !          1485:   radii[1] = rmin = min_modulus(p, aux);
        !          1486:   radii[n] = rmax = max_modulus(p, aux);
        !          1487:   i=1; j=n;
        !          1488:   rho = mpsqrt(mulrr(rmin,rmax));
        !          1489:   k = dual_modulus(p,rho,aux,1);
        !          1490:   if (k<n/5. || (n/2.<k && k<(4*n)/5.))
        !          1491:     { rmax=rho; j=k+1; affrr(rho, radii[j]); }
        !          1492:   else
        !          1493:     { rmin=rho; i=k; affrr(rho, radii[i]); }
        !          1494:   while (j>i+1)
        !          1495:   {
        !          1496:     if (i+j==n+1)
        !          1497:       rho = mpsqrt(mulrr(rmin,rmax));
        !          1498:     else
        !          1499:     {
        !          1500:       kappa = 1. - log(1.+(double)min(i,n-j)) / log(1.+(double)min(j,n-i));
        !          1501:       if (i+j<n+1)
        !          1502:         rho = addrr(mulrr(mplog(rmax),dbltor(1+kappa)), mplog(rmin));
        !          1503:       else
        !          1504:         rho = addrr(mulrr(mplog(rmin),dbltor(1+kappa)), mplog(rmax));
        !          1505:       rho = mpexp(divrr(rho, dbltor(2+kappa)));
        !          1506:     }
        !          1507:     aux = rtodbl(mplog(divrr(rmax,rmin))) / (j-i) / 4.;
        !          1508:     k = dual_modulus(p,rho,aux, min(i,n+1-j));
        !          1509:     if (k-i < j-k-1 || (k-i == j-k-1 && 2*k > n))
        !          1510:       { rmax=rho; j=k+1; affrr(mulrr(rho, dbltor(exp(-aux))), radii[j]); }
        !          1511:     else
        !          1512:       { rmin=rho; i=k; affrr(mulrr(rho, dbltor(exp(aux))), radii[i]); }
        !          1513:   }
        !          1514:   aux = rtodbl(mplog(divrr(rmax, rmin)));
        !          1515:
        !          1516:   if (ctr)
        !          1517:   {
        !          1518:     rho = mpsqrt(mulrr(rmax,rmin));
        !          1519:     invrho = ginv(rho);
        !          1520:     for (i=1; i<=n; i++)
        !          1521:       if (signe(radii[i])) affrr(mulrr(radii[i],invrho), radii[i]);
        !          1522:
        !          1523:     bitprec2 = bitprec + (long) ((double)n * fabs(log2ir(rho)) + 1.);
        !          1524:     R = mygprec(invrho,bitprec2);
        !          1525:     q = scalepol(p,R,bitprec2);
        !          1526:
        !          1527:     conformal_mapping(radii, ctr, q, k, bitprec2, aux, &FF, &GG);
        !          1528:   }
        !          1529:   else
        !          1530:   {
        !          1531:     rho = compute_radius(radii, p, k, aux/10., &delta);
        !          1532:     invrho = update_radius(radii, rho, &param, &param2);
        !          1533:
        !          1534:     bitprec2 = bitprec + (long) ((double)n * fabs(log2ir(rho)) + 1.);
        !          1535:     R = mygprec(invrho,bitprec2);
        !          1536:     q = scalepol(p,R,bitprec2);
        !          1537:
        !          1538:     optimize_split(q,k,delta,bitprec2,&FF,&GG,param,param2);
        !          1539:   }
        !          1540:   bitprec  += n;
        !          1541:   bitprec2 += n; R = ginv(mygprec(R,bitprec2));
        !          1542:   *F = mygprec(scalepol(FF,R,bitprec2), bitprec);
        !          1543:   *G = mygprec(scalepol(GG,R,bitprec2), bitprec);
        !          1544: }
        !          1545:
        !          1546: /* procedure corresponding to steps 5,6,.. page 44 in the RR n. 1852 */
        !          1547: /* put in F and G two polynomial such that |p-FG|<2^(-bitprec)|p|
        !          1548: where the maximum modulus of the roots of p is <=1 and the sum of roots
        !          1549: is zero */
        !          1550:
        !          1551: static void
        !          1552: split_1(GEN p, long bitprec, GEN *F, GEN *G)
        !          1553: {
        !          1554:   long bitprec2,i,imax,n=degpol(p), polreal = isreal(p), ep = gexpo(p);
        !          1555:   GEN rmax,rmin,thickness,quo;
        !          1556:   GEN ctr,q,qq,FF,GG,v,gr,r, newq = NULL; /* gcc -Wall */
        !          1557:
        !          1558:   r = max_modulus(p,0.01);
        !          1559:   bitprec2 = bitprec+n;
        !          1560:   gr = mygprec(ginv(r),bitprec2);
        !          1561:   q = scalepol(p,gr,bitprec2);
        !          1562:
        !          1563:   bitprec2 = bitprec + gexpo(q) - ep + (long)((double)n*2.*log2(3.)+1);
        !          1564:   v = cgetg(5,t_VEC);
        !          1565:   v[1] = lmul2n(myrealun(bitprec2), 1);
        !          1566:   v[2] = lneg((GEN)v[1]);
        !          1567:   v[3] = lmul((GEN)v[1],gi);
        !          1568:   v[4] = lneg((GEN)v[3]);
        !          1569:   q = mygprec(q,bitprec2); thickness = realun(3);
        !          1570:   ctr = NULL; imax = polreal? 3: 4;
        !          1571:   for (i=1; i<=imax; i++)
        !          1572:   {
        !          1573:     qq = shiftpol(q, (GEN)v[i]);
        !          1574:     rmin = min_modulus(qq,0.05);
        !          1575:     if (cmpsr(3, mulrr(rmin, thickness)) > 0)
        !          1576:     {
        !          1577:       rmax = max_modulus(qq,0.05);
        !          1578:       quo = divrr(rmax,rmin);
        !          1579:       if (cmprr(quo, thickness) > 0) { thickness=quo; newq=qq; ctr=(GEN)v[i]; }
        !          1580:     }
        !          1581:     if (expo(thickness) > 0) break; /* thickness > 2 */
        !          1582:     if (polreal && i==2 && rtodbl(thickness) > 1.5) break;
        !          1583:   }
        !          1584:   bitprec2 = bitprec + gexpo(newq) - ep + (long)((double)n*log2(3.)+1);
        !          1585:   split_2(newq,bitprec2,ctr, rtodbl(mplog(thickness)),&FF,&GG);
        !          1586:   r = gneg(mygprec(ctr,bitprec2));
        !          1587:   FF = shiftpol(FF,r);
        !          1588:   GG = shiftpol(GG,r);
        !          1589:
        !          1590:   gr = ginv(gr); bitprec2 = bitprec - ep + gexpo(FF)+gexpo(GG);
        !          1591:   *F = scalepol(FF,gr,bitprec2);
        !          1592:   *G = scalepol(GG,gr,bitprec2);
        !          1593: }
        !          1594:
        !          1595: /* put in F and G two polynomials such that |P-FG|<2^(-bitprec)|P|,
        !          1596: where the maximum modulus of the roots of p is < 0.5 */
        !          1597: static int
        !          1598: split_0_2(GEN p, long bitprec, GEN *F, GEN *G)
        !          1599: {
        !          1600:   GEN q,b,FF,GG;
        !          1601:   long n=degpol(p),k,bitprec2,i, eq;
        !          1602:   double aux = mylog2((GEN)p[n+1]) - mylog2((GEN)p[n+2]);
        !          1603:
        !          1604:   /* beware double overflow */
        !          1605:   if (aux >= 0 && (aux > 1e4 || exp2(aux) > 2.5*n)) return 0;
        !          1606:
        !          1607:   aux = (aux < -300)? 0.: (double) n*log2(1 + exp2(aux)/(double)n);
        !          1608:   bitprec2=bitprec+1+(long) (log2((double)n)+aux);
        !          1609:
        !          1610:   q=mygprec(p,bitprec2);
        !          1611:   b=gdivgs(gdiv((GEN)q[n+1],(GEN)q[n+2]),-n);
        !          1612:   q = shiftpol(q,b);
        !          1613:
        !          1614:   k=0; eq=gexpo(q);
        !          1615:   while
        !          1616:       (k <= n/2 && (gexpo((GEN)q[k+2]) < -(bitprec2+2*(n-k)+eq)
        !          1617:        || gcmp0((GEN)q[k+2]))) k++;
        !          1618:   if (k>0)
        !          1619:   {
        !          1620:     if (k>n/2) k=n/2;
        !          1621:     bitprec2+=(k<<1);
        !          1622:     FF=cgetg(k+3,t_POL); FF[1]=evalsigne(1)|evalvarn(varn(p))|evallgef(k+3);
        !          1623:     for (i=0; i<k; i++) FF[i+2]=zero;
        !          1624:     FF[k+2]=(long) myrealun(bitprec2);
        !          1625:     GG=cgetg(n-k+3,t_POL); GG[1]=evalsigne(1)|evalvarn(varn(p))|evallgef(n-k+3);
        !          1626:     for (i=0; i<=n-k; i++) GG[i+2]=q[i+k+2];
        !          1627:   }
        !          1628:   else
        !          1629:   {
        !          1630:     split_1(q,bitprec2,&FF,&GG);
        !          1631:     bitprec2 = bitprec+gexpo(FF)+gexpo(GG)-gexpo(p)+(long)aux+1;
        !          1632:     FF = mygprec(FF,bitprec2);
        !          1633:   }
        !          1634:   GG = mygprec(GG,bitprec2);
        !          1635:   b = mygprec(gneg(b),bitprec2);
        !          1636:   *F = shiftpol(FF,b);
        !          1637:   *G = shiftpol(GG,b); return 1;
        !          1638: }
        !          1639:
        !          1640: /* put in F and G two polynomials such that |P-FG|<2^(-bitprec)|P|,
        !          1641: where the maximum modulus of the roots of p is <2 */
        !          1642: static void
        !          1643: split_0_1(GEN p, long bitprec, GEN *F, GEN *G)
        !          1644: {
        !          1645:   GEN q,FF,GG;
        !          1646:   long n=degpol(p),bitprec2,normp;
        !          1647:
        !          1648:   if  (split_0_2(p,bitprec,F,G)) return;
        !          1649:
        !          1650:   normp = gexpo(p);
        !          1651:   scalepol2n(p,2); /* p <- 4^(-n) p(4*x) */
        !          1652:   bitprec2 = bitprec+2*n+gexpo(p)-normp;
        !          1653:   q=mygprec(p,bitprec2);
        !          1654:   split_1(q,bitprec2,&FF,&GG);
        !          1655:   scalepol2n(FF,-2); scalepol2n(GG,-2);
        !          1656:   bitprec2=bitprec+gexpo(FF)+gexpo(GG)-normp;
        !          1657:   *F=mygprec(FF,bitprec2); *G=mygprec(GG,bitprec2);
        !          1658: }
        !          1659:
        !          1660: /* put in F and G two polynomials such that |P-FG|<2^(-bitprec)|P| */
        !          1661: static void
        !          1662: split_0(GEN p, long bitprec, GEN *F, GEN *G)
        !          1663: {
        !          1664:   GEN FF,GG,q,R;
        !          1665:   long n=degpol(p),k=0,i;
        !          1666:
        !          1667:   while (gexpo((GEN)p[k+2]) < -bitprec && k <= n/2) k++;
        !          1668:   if (k>0)
        !          1669:   {
        !          1670:     if (k>n/2) k=n/2;
        !          1671:     FF=cgetg(k+3,t_POL);
        !          1672:     FF[1]=evalsigne(1) | evalvarn(varn(p)) | evallgef(k+3);
        !          1673:     for (i=0; i<k; i++) FF[i+2] = zero;
        !          1674:     FF[k+2]=(long) myrealun(bitprec);
        !          1675:     GG=cgetg(n-k+3,t_POL);
        !          1676:     GG[1]=evalsigne(1) | evalvarn(varn(p)) | evallgef(n-k+3);
        !          1677:     for (i=0; i<=n-k; i++) GG[i+2]=p[i+k+2];
        !          1678:   }
        !          1679:   else
        !          1680:   {
        !          1681:     R = max_modulus(p,0.05);
        !          1682:     if (gexpo(R)<1 && gtodouble(R)<1.9) split_0_1(p,bitprec,&FF,&GG);
        !          1683:     else
        !          1684:     {
        !          1685:       q = polrecip_i(p);
        !          1686:       R = max_modulus(q,0.05);
        !          1687:       if (gexpo(R)<1 && gtodouble(R)<1.9)
        !          1688:       {
        !          1689:        split_0_1(q,bitprec,&FF,&GG);
        !          1690:        FF=polrecip(FF); GG=polrecip(GG);
        !          1691:       }
        !          1692:       else
        !          1693:        split_2(p,bitprec,NULL, 1.2837,&FF,&GG);
        !          1694:     }
        !          1695:   }
        !          1696:   *F=FF; *G=GG;
        !          1697: }
        !          1698:
        !          1699: /********************************************************************/
        !          1700: /**                                                                **/
        !          1701: /**     CALCUL A POSTERIORI DE L'ERREUR ABSOLUE SUR LES RACINES    **/
        !          1702: /**                                                                **/
        !          1703: /********************************************************************/
        !          1704:
        !          1705: static GEN
        !          1706: root_error(long n, long k, GEN roots_pol, GEN sigma, GEN shatzle)
        !          1707: {
        !          1708:   GEN rho,d,eps,epsbis,eps2,prod,aux,rap=NULL;
        !          1709:   long i,j,m;
        !          1710:
        !          1711:   d=cgetg(n+1,t_VEC);
        !          1712:   for (i=1; i<=n; i++)
        !          1713:   {
        !          1714:     if (i!=k)
        !          1715:     {
        !          1716:       aux=gsub((GEN)roots_pol[i],(GEN)roots_pol[k]);
        !          1717:       d[i]=(long) gabs(mygprec(aux,31),DEFAULTPREC);
        !          1718:     }
        !          1719:   }
        !          1720:   rho=gabs(mygprec((GEN)roots_pol[k],31),DEFAULTPREC);
        !          1721:   if (gcmp(rho,dbltor(1.))==-1) rho=gun;
        !          1722:   eps=gmul(rho,shatzle);
        !          1723:   aux=gmul(gpowgs(rho,n),sigma);
        !          1724:
        !          1725:   for (j=1; j<=2 || (j<=5 && gcmp(rap,dbltor(1.2))==1); j++)
        !          1726:   {
        !          1727:     m=n; prod=gun;
        !          1728:     epsbis=gdivgs(gmulgs(eps,5),4);
        !          1729:     for (i=1; i<=n; i++)
        !          1730:     {
        !          1731:       if (i!=k && gcmp((GEN)d[i],epsbis)==1)
        !          1732:       {
        !          1733:        m--;
        !          1734:        prod=gmul(prod,gsub((GEN)d[i],eps));
        !          1735:       }
        !          1736:     }
        !          1737:     eps2=gdiv(gmul2n(aux,2*m-2),prod);
        !          1738:     eps2=gpui(eps2,dbltor(1./m),DEFAULTPREC);
        !          1739:     rap=gdiv(eps,eps2); eps=eps2;
        !          1740:   }
        !          1741:   return eps;
        !          1742: }
        !          1743:
        !          1744: /* round a complex or real number x to an absolute value of 2^(-e) */
        !          1745: static GEN
        !          1746: mygprec_absolute(GEN x, long bitprec)
        !          1747: {
        !          1748:   long tx=typ(x),e;
        !          1749:   GEN y;
        !          1750:
        !          1751:   switch(tx)
        !          1752:   {
        !          1753:     case t_REAL:
        !          1754:       e=gexpo(x);
        !          1755:       if (e<-bitprec || !signe(x)) { y=dbltor(0.); setexpo(y,-bitprec); }
        !          1756:       else y=mygprec(x,bitprec+e);
        !          1757:       break;
        !          1758:     case t_COMPLEX:
        !          1759:       if (gexpo((GEN)x[2])<-bitprec)
        !          1760:        y=mygprec_absolute((GEN)x[1],bitprec);
        !          1761:       else
        !          1762:       {
        !          1763:        y=cgetg(3,t_COMPLEX);
        !          1764:        y[1]=(long) mygprec_absolute((GEN)x[1],bitprec);
        !          1765:        y[2]=(long) mygprec_absolute((GEN)x[2],bitprec);
        !          1766:       }
        !          1767:       break;
        !          1768:
        !          1769:     default: y=mygprec(x,bitprec);
        !          1770:   }
        !          1771:   return y;
        !          1772: }
        !          1773:
        !          1774: static long
        !          1775: a_posteriori_errors(GEN p, GEN roots_pol, long err)
        !          1776: {
        !          1777:   GEN sigma,overn,shatzle,x;
        !          1778:   long i,n=degpol(p),e,e_max;
        !          1779:
        !          1780:   sigma = realun(3);
        !          1781:   setexpo(sigma, err + (long)log2((double)n) + 1);
        !          1782:   overn=dbltor(1./n);
        !          1783:   shatzle=gdiv(gpui(sigma,overn,0),
        !          1784:               gsub(gpui(gsub(gun,sigma),overn,0),
        !          1785:                    gpui(sigma,overn,0)));
        !          1786:   shatzle=gmul2n(shatzle,1); e_max=-pariINFINITY;
        !          1787:   for (i=1; i<=n; i++)
        !          1788:   {
        !          1789:     x=root_error(n,i,roots_pol,sigma,shatzle);
        !          1790:     e=gexpo(x); if (e>e_max) e_max=e;
        !          1791:     roots_pol[i] = (long)mygprec_absolute((GEN)roots_pol[i],-e);
        !          1792:   }
        !          1793:   return e_max;
        !          1794: }
        !          1795:
        !          1796: /********************************************************************/
        !          1797: /**                                                                **/
        !          1798: /**                           MAIN                                 **/
        !          1799: /**                                                                **/
        !          1800: /********************************************************************/
        !          1801: static GEN
        !          1802: append_root(GEN roots_pol, GEN a)
        !          1803: {
        !          1804:   long l = lg(roots_pol);
        !          1805:   setlg(roots_pol, l+1); return (GEN)(roots_pol[l] = lclone(a));
        !          1806: }
        !          1807:
        !          1808: /* put roots in placeholder roots_pol so that |P-L_1...L_n|<2^(-bitprec)|P|
        !          1809:  *  and returns  prod (x-roots_pol[i]) for i=1..degree(p) */
        !          1810: static GEN
        !          1811: split_complete(GEN p, long bitprec, GEN roots_pol)
        !          1812: {
        !          1813:   long n=degpol(p),decprec,ltop;
        !          1814:   GEN p1,F,G,a,b,m1,m2,m;
        !          1815:
        !          1816:   if (n==1)
        !          1817:   {
        !          1818:     a=gneg_i(gdiv((GEN)p[2],(GEN)p[3]));
        !          1819:     append_root(roots_pol,a); return p;
        !          1820:   }
        !          1821:   ltop = avma;
        !          1822:   if (n==2)
        !          1823:   {
        !          1824:     F=gsub(gsqr((GEN)p[3]),gmul2n(gmul((GEN)p[2],(GEN)p[4]),2));
        !          1825:     decprec=(long) ((double) bitprec * L2SL10)+1;
        !          1826:     F=gsqrt(F,decprec);
        !          1827:     p1 = gmul2n((GEN)p[4],1);
        !          1828:     a = gneg_i(gdiv(gadd(F,(GEN)p[3]), p1));
        !          1829:     b =        gdiv(gsub(F,(GEN)p[3]), p1);
        !          1830:     a = append_root(roots_pol,a);
        !          1831:     b = append_root(roots_pol,b); avma = ltop;
        !          1832:     m=gmul(gsub(polx[varn(p)],mygprec(a,3*bitprec)),
        !          1833:           gsub(polx[varn(p)],mygprec(b,3*bitprec)));
        !          1834:     return gmul(m,(GEN)p[4]);
        !          1835:   }
        !          1836:   split_0(p,bitprec,&F,&G);
        !          1837:   m1 = split_complete(F,bitprec,roots_pol);
        !          1838:   m2 = split_complete(G,bitprec,roots_pol);
        !          1839:   return gerepileupto(ltop, gmul(m1,m2));
        !          1840: }
        !          1841:
        !          1842: /* compute a bound on the maximum modulus of roots of p */
        !          1843: static GEN
        !          1844: cauchy_bound(GEN p)
        !          1845: {
        !          1846:   long i,n=degpol(p);
        !          1847:   GEN x=gzero,y,lc;
        !          1848:
        !          1849:   lc=gabs((GEN)p[n+2],DEFAULTPREC); /* leading coefficient */
        !          1850:   lc=gdiv(dbltor(1.),lc);
        !          1851:   for (i=0; i<n; i++)
        !          1852:   {
        !          1853:     y=gmul(gabs((GEN) p[i+2],DEFAULTPREC),lc);
        !          1854:     y=gpui(y,dbltor(1./(n-i)),DEFAULTPREC);
        !          1855:     if (gcmp(y,x) > 0) x=y;
        !          1856:   }
        !          1857:   return x;
        !          1858: }
        !          1859:
        !          1860: static GEN
        !          1861: mygprecrc_special(GEN x, long bitprec, long e)
        !          1862: {
        !          1863:   long tx=typ(x),lx,ex;
        !          1864:   GEN y;
        !          1865:
        !          1866:   if (bitprec<=0) bitprec=0; /* should not happen */
        !          1867:   switch(tx)
        !          1868:   {
        !          1869:     case t_REAL:
        !          1870:       lx=bitprec/BITS_IN_LONG+3;
        !          1871:       if (lx<lg(x)) lx=lg(x);
        !          1872:       y=cgetr(lx); affrr(x,y); ex=-bitprec+e;
        !          1873:       if (!signe(x) && expo(x)>ex) setexpo(y,ex);
        !          1874:       break;
        !          1875:     case t_COMPLEX:
        !          1876:       y=cgetg(3,t_COMPLEX);
        !          1877:       y[1]=(long) mygprecrc_special((GEN)x[1],bitprec,e);
        !          1878:       y[2]=(long) mygprecrc_special((GEN)x[2],bitprec,e);
        !          1879:       break;
        !          1880:     default: y=gcopy(x);
        !          1881:   }
        !          1882:   return y;
        !          1883: }
        !          1884:
        !          1885: /* like mygprec but keep at least the same precision as before */
        !          1886: static GEN
        !          1887: mygprec_special(GEN x, long bitprec)
        !          1888: {
        !          1889:   long tx=typ(x),lx,i,e;
        !          1890:   GEN y;
        !          1891:
        !          1892:   switch(tx)
        !          1893:   {
        !          1894:     case t_POL:
        !          1895:       lx=lgef(x); y=cgetg(lx,tx); y[1]=x[1]; e=gexpo(x);
        !          1896:       for (i=2; i<lx; i++) y[i]=(long) mygprecrc_special((GEN)x[i],bitprec,e);
        !          1897:       break;
        !          1898:
        !          1899:     default: y=mygprecrc_special(x,bitprec,0);
        !          1900:   }
        !          1901:   return y;
        !          1902: }
        !          1903:
        !          1904: static GEN
        !          1905: fix_roots(GEN r, GEN *m, long h, long bitprec)
        !          1906: {
        !          1907:   long i,j,k, l = lg(r)-1;
        !          1908:   GEN allr, ro1 = (h==1)? NULL: initRUgen(h, bitprec);
        !          1909:   allr = cgetg(h*l+1, t_VEC);
        !          1910:   for (k=1,i=1; i<=l; i++)
        !          1911:   {
        !          1912:     GEN p2, p1 = (GEN)r[i];
        !          1913:     if (!ro1) allr[k++] = lcopy(p1);
        !          1914:     else
        !          1915:     {
        !          1916:       p2 = (h == 2)? gsqrt(p1,0): gpow(p1, ginv(stoi(h)), 0);
        !          1917:       for (j=0; j<h; j++) allr[k++] = lmul(p2, (GEN)ro1[j]);
        !          1918:     }
        !          1919:     gunclone(p1);
        !          1920:   }
        !          1921:   if (ro1) *m = roots_to_pol(allr, varn(*m));
        !          1922:   return allr;
        !          1923: }
        !          1924:
        !          1925: static GEN
        !          1926: all_roots(GEN p, long bitprec)
        !          1927: {
        !          1928:   GEN pd,q,roots_pol,m;
        !          1929:   long bitprec0, bitprec2,n=degpol(p),i,e,h;
        !          1930:   ulong av;
        !          1931:
        !          1932: #if 0
        !          1933:   pd = poldeflate(p, &h);
        !          1934: #else
        !          1935:   pd = p; h = 1;
        !          1936: #endif
        !          1937:   e = 2*gexpo(cauchy_bound(pd)); if (e<0) e=0;
        !          1938:   bitprec0=bitprec + gexpo(pd) - gexpo(leading_term(pd)) + (long)log2(n/h)+1+e;
        !          1939:   for (av=avma,i=1;; i++,avma=av)
        !          1940:   {
        !          1941:     roots_pol = cgetg(n+1,t_VEC); setlg(roots_pol,1);
        !          1942:     bitprec2 = bitprec0 + (1<<i)*n;
        !          1943:     q = gmul(myrealun(bitprec2), mygprec(pd,bitprec2));
        !          1944:     m = split_complete(q,bitprec2,roots_pol);
        !          1945:     roots_pol = fix_roots(roots_pol, &m, h, bitprec2);
        !          1946:
        !          1947:     e = gexpo(gsub(mygprec_special(p,bitprec2), m))
        !          1948:       - gexpo(leading_term(q)) + (long)log2((double)n) + 1;
        !          1949:     if (e<-2*bitprec2) e=-2*bitprec2; /* to avoid e=-pariINFINITY */
        !          1950:     if (e < 0)
        !          1951:     {
        !          1952:       e = a_posteriori_errors(q,roots_pol,e);
        !          1953:       if (e < -bitprec) return roots_pol;
        !          1954:     }
        !          1955:     if (DEBUGLEVEL > 7)
        !          1956:       fprintferr("all_roots: restarting, i = %ld, e = %ld\n", i,e);
        !          1957:   }
        !          1958: }
        !          1959:
        !          1960: /* true if x is an exact scalar, that is integer or rational */
        !          1961: static int
        !          1962: isexactscalar(GEN x)
        !          1963: {
        !          1964:   long tx=typ(x);
        !          1965:   return (tx==t_INT || is_frac_t(tx));
        !          1966: }
        !          1967:
        !          1968: static int
        !          1969: isexactpol(GEN p)
        !          1970: {
        !          1971:   long i,n=degpol(p);
        !          1972:
        !          1973:   for (i=0; i<=n; i++)
        !          1974:     if (isexactscalar((GEN)p[i+2])==0) return 0;
        !          1975:   return 1;
        !          1976: }
        !          1977:
        !          1978: static long
        !          1979: isvalidcoeff(GEN x)
        !          1980: {
        !          1981:   long tx=typ(x);
        !          1982:
        !          1983:   switch(tx)
        !          1984:   {
        !          1985:     case t_INT: case t_REAL: case t_FRAC: case t_FRACN: return 1;
        !          1986:     case t_COMPLEX:
        !          1987:       if (isvalidcoeff((GEN)x[1]) && isvalidcoeff((GEN)x[2])) return 1;
        !          1988:   }
        !          1989:   return 0;
        !          1990: }
        !          1991:
        !          1992: static long
        !          1993: isvalidpol(GEN p)
        !          1994: {
        !          1995:   long i,n = lgef(p);
        !          1996:   for (i=2; i<n; i++)
        !          1997:     if (!isvalidcoeff((GEN)p[i])) return 0;
        !          1998:   return 1;
        !          1999: }
        !          2000:
        !          2001: static GEN
        !          2002: solve_exact_pol(GEN p, long bitprec)
        !          2003: {
        !          2004:   GEN S,ex,factors,roots_pol,roots_fact;
        !          2005:   long i,j,k,m,n,iroots;
        !          2006:
        !          2007:   n=degpol(p);
        !          2008:
        !          2009:   iroots=0;
        !          2010:   roots_pol=cgetg(n+1,t_VEC); for (i=1; i<=n; i++) roots_pol[i]=zero;
        !          2011:
        !          2012:   S=square_free_factorization(p);
        !          2013:   ex=(GEN) S[1]; factors=(GEN) S[2];
        !          2014:   for (i=1; i<lg(factors); i++)
        !          2015:   {
        !          2016:     roots_fact=all_roots((GEN)factors[i],bitprec);
        !          2017:     n=degpol(factors[i]); m=itos((GEN)ex[i]);
        !          2018:     for (j=1; j<=n; j++)
        !          2019:       for (k=1; k<=m; k++) roots_pol[++iroots] = roots_fact[j];
        !          2020:   }
        !          2021:   return roots_pol;
        !          2022: }
        !          2023:
        !          2024: /* return the roots of p with absolute error bitprec */
        !          2025: static GEN
        !          2026: roots_com(GEN p, long l)
        !          2027: {
        !          2028:   long bitprec;
        !          2029:
        !          2030:   if (typ(p)!=t_POL)
        !          2031:   {
        !          2032:     if (!isvalidcoeff(p)) err(typeer,"roots");
        !          2033:     return cgetg(1,t_VEC); /* constant polynomial */
        !          2034:   }
        !          2035:   if (!isvalidpol(p)) err(talker,"invalid coefficients in roots");
        !          2036:   if (lgef(p) == 3) return cgetg(1,t_VEC); /* constant polynomial */
        !          2037:   if (l<3) l=3;
        !          2038:   bitprec=bit_accuracy(l);
        !          2039:   return isexactpol(p)? solve_exact_pol(p,bitprec): all_roots(p,bitprec);
        !          2040: }
        !          2041:
        !          2042: static GEN
        !          2043: tocomplex(GEN x, long l)
        !          2044: {
        !          2045:   GEN y=cgetg(3,t_COMPLEX);
        !          2046:
        !          2047:   y[1]=lgetr(l);
        !          2048:   if (typ(x) == t_COMPLEX)
        !          2049:     { y[2]=lgetr(l); gaffect(x,y); }
        !          2050:   else
        !          2051:     { gaffect(x,(GEN)y[1]); y[2]=(long)realzero(l); }
        !          2052:  return y;
        !          2053: }
        !          2054:
        !          2055: /* Check if x is approximately real with precision e */
        !          2056: int
        !          2057: isrealappr(GEN x, long e)
        !          2058: {
        !          2059:   long tx=typ(x),lx,i;
        !          2060:   switch(tx)
        !          2061:   {
        !          2062:     case t_INT: case t_REAL: case t_FRAC: case t_FRACN:
        !          2063:       return 1;
        !          2064:     case t_COMPLEX:
        !          2065:       return (gexpo((GEN)x[2]) < e);
        !          2066:     case t_QUAD:
        !          2067:       err(impl,"isrealappr for type t_QUAD");
        !          2068:     case t_POL: case t_SER: case t_RFRAC: case t_RFRACN:
        !          2069:     case t_VEC: case t_COL: case t_MAT:
        !          2070:       lx = (tx==t_POL)?lgef(x): lg(x);
        !          2071:       for (i=lontyp[tx]; i<lx; i++)
        !          2072:         if (! isrealappr((GEN)x[i],e)) return 0;
        !          2073:       return 1;
        !          2074:     default: err(typeer,"isrealappr"); return 0;
        !          2075:   }
        !          2076: }
        !          2077:
        !          2078: /* x,y sont de type t_COMPLEX */
        !          2079: static int
        !          2080: isconj(GEN x, GEN y, long e)
        !          2081: {
        !          2082:   ulong av = avma;
        !          2083:   long i= (gexpo( gsub((GEN)x[1],(GEN)y[1]) ) < e
        !          2084:         && gexpo( gadd((GEN)x[2],(GEN)y[2]) ) < e);
        !          2085:   avma = av; return i;
        !          2086: }
        !          2087:
        !          2088: /* returns the vector of roots of p, with guaranteed absolute error
        !          2089:  * 2 ^ (- bit_accuracy(l))
        !          2090:  */
        !          2091: GEN
        !          2092: roots(GEN p, long l)
        !          2093: {
        !          2094:   ulong av = avma;
        !          2095:   long n,i,k,s,t,e;
        !          2096:   GEN c,L,p1,res,rea,com;
        !          2097:
        !          2098:   if (gcmp0(p)) err(zeropoler,"roots");
        !          2099:   L=roots_com(p,l); n=lg(L);
        !          2100:   if (n <= 1) return L;
        !          2101:
        !          2102:   if (!isreal(p))
        !          2103:   {
        !          2104:     res = cgetg(n,t_COL);
        !          2105:     for (i=1; i<n; i++) res[i]=(long)tocomplex((GEN)L[i],l);
        !          2106:     return gerepileupto(av,res);
        !          2107:   }
        !          2108:   e = 5 - bit_accuracy(l);
        !          2109:   rea=cgetg(n,t_COL); s = 0;
        !          2110:   com=cgetg(n,t_COL); t = 0;
        !          2111:   for (i=1; i<n; i++)
        !          2112:   {
        !          2113:     p1 = (GEN)L[i];
        !          2114:     if (isrealappr(p1,e)) {
        !          2115:       if (typ(p1) == t_COMPLEX) p1 = (GEN)p1[1];
        !          2116:       rea[++s] = (long)p1;
        !          2117:     }
        !          2118:     else com[++t] = (long)p1;
        !          2119:   }
        !          2120:   setlg(rea,s+1); rea = sort(rea);
        !          2121:   res = cgetg(n,t_COL);
        !          2122:   for (i=1; i<=s; i++) res[i] = (long)tocomplex((GEN)rea[i],l);
        !          2123:   for (i=1; i<=t; i++)
        !          2124:   {
        !          2125:     c = (GEN)com[i]; if (!c) continue;
        !          2126:     res[++s] = (long)tocomplex(c,l);
        !          2127:     for (k=i+1; k<=t; k++)
        !          2128:     {
        !          2129:       p1 = (GEN)com[k]; if (!p1) continue;
        !          2130:       if (isconj(c,p1,e))
        !          2131:       {
        !          2132:         res[++s] = (long)tocomplex(p1,l);
        !          2133:         com[k] = 0; break;
        !          2134:       }
        !          2135:     }
        !          2136:     if (k==n) err(bugparier,"roots (conjugates)");
        !          2137:   }
        !          2138:   return gerepileupto(av,res);
        !          2139: }
        !          2140:
        !          2141: GEN
        !          2142: roots0(GEN p, long flag,long l)
        !          2143: {
        !          2144:   switch(flag)
        !          2145:   {
        !          2146:     case 0: return roots(p,l);
        !          2147:     case 1: return rootsold(p,l);
        !          2148:     default: err(flagerr,"polroots");
        !          2149:   }
        !          2150:   return NULL; /* not reached */
        !          2151: }

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