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