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