Line data Source code
1 : /* Copyright (C) 2000 The PARI group.
2 :
3 : This file is part of the PARI/GP package.
4 :
5 : PARI/GP is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 2 of the License, or (at your option) any later
8 : version. It is distributed in the hope that it will be useful, but WITHOUT
9 : ANY WARRANTY WHATSOEVER.
10 :
11 : Check the License for details. You should have received a copy of it, along
12 : with the package; see the file 'COPYING'. If not, write to the Free Software
13 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14 :
15 : /*******************************************************************/
16 : /* */
17 : /* ROOTS OF COMPLEX POLYNOMIALS */
18 : /* (original code contributed by Xavier Gourdon, INRIA RR 1852) */
19 : /* */
20 : /*******************************************************************/
21 : #include "pari.h"
22 : #include "paripriv.h"
23 :
24 : #define DEBUGLEVEL DEBUGLEVEL_polroots
25 :
26 : static const double pariINFINITY = 1./0.;
27 :
28 : static long
29 1235245 : isvalidcoeff(GEN x)
30 : {
31 1235245 : switch (typ(x))
32 : {
33 1210887 : case t_INT: case t_REAL: case t_FRAC: return 1;
34 24344 : case t_COMPLEX: return isvalidcoeff(gel(x,1)) && isvalidcoeff(gel(x,2));
35 : }
36 14 : return 0;
37 : }
38 :
39 : static void
40 268043 : checkvalidpol(GEN p, const char *f)
41 : {
42 268043 : long i,n = lg(p);
43 1454579 : for (i=2; i<n; i++)
44 1186543 : if (!isvalidcoeff(gel(p,i))) pari_err_TYPE(f, gel(p,i));
45 268036 : }
46 :
47 : /********************************************************************/
48 : /** **/
49 : /** FAST ARITHMETIC over Z[i] **/
50 : /** **/
51 : /********************************************************************/
52 :
53 : static GEN
54 16441572 : ZX_to_ZiX(GEN Pr, GEN Pi)
55 : {
56 16441572 : long i, lr = lg(Pr), li = lg(Pi), l = maxss(lr, li), m = minss(lr, li);
57 16443716 : GEN P = cgetg(l, t_POL);
58 16449145 : P[1] = Pr[1];
59 66667023 : for(i = 2; i < m; i++)
60 50219719 : gel(P,i) = signe(gel(Pi,i)) ? mkcomplex(gel(Pr,i), gel(Pi,i))
61 50219719 : : gel(Pr,i);
62 22346195 : for( ; i < lr; i++)
63 5898891 : gel(P,i) = gel(Pr, i);
64 16482236 : for( ; i < li; i++)
65 34932 : gel(P,i) = mkcomplex(gen_0, gel(Pi, i));
66 16447304 : return normalizepol_lg(P, l);
67 : }
68 :
69 : static GEN
70 99289138 : ZiX_sqr(GEN P)
71 : {
72 99289138 : pari_sp av = avma;
73 : GEN Pr2, Pi2, Qr, Qi;
74 99289138 : GEN Pr = real_i(P), Pi = imag_i(P);
75 99285551 : if (signe(Pi)==0) return gc_upto(av, ZX_sqr(Pr));
76 16507454 : if (signe(Pr)==0) return gc_upto(av, ZX_neg(ZX_sqr(Pi)));
77 16449896 : Pr2 = ZX_sqr(Pr); Pi2 = ZX_sqr(Pi);
78 16443128 : Qr = ZX_sub(Pr2, Pi2);
79 16443868 : if (degpol(Pr)==degpol(Pi))
80 10692080 : Qi = ZX_sub(ZX_sqr(ZX_add(Pr, Pi)), ZX_add(Pr2, Pi2));
81 : else
82 5755064 : Qi = ZX_shifti(ZX_mul(Pr, Pi), 1);
83 16445249 : return gc_GEN(av, ZX_to_ZiX(Qr, Qi));
84 : }
85 :
86 : static GEN
87 49632838 : graeffe(GEN p)
88 : {
89 49632838 : pari_sp av = avma;
90 : GEN p0, p1, s0, s1;
91 49632838 : long n = degpol(p);
92 :
93 49639063 : if (!n) return RgX_copy(p);
94 49639063 : RgX_even_odd(p, &p0, &p1);
95 : /* p = p0(x^2) + x p1(x^2) */
96 49646373 : s0 = ZiX_sqr(p0);
97 49656018 : s1 = ZiX_sqr(p1);
98 49654415 : return gc_upto(av, RgX_sub(s0, RgX_shift_shallow(s1,1)));
99 : }
100 :
101 : /* return q such that p(x)p(-x) = q(x^2) */
102 : GEN
103 5460 : ZX_graeffe(GEN p)
104 : {
105 5460 : pari_sp av = avma;
106 : GEN p0, p1, s0, s1;
107 5460 : long n = degpol(p);
108 :
109 5460 : if (!n) return ZX_copy(p);
110 5460 : RgX_even_odd(p, &p0, &p1);
111 : /* p = p0(x^2) + x p1(x^2) */
112 5460 : s0 = ZX_sqr(p0);
113 5460 : s1 = ZX_sqr(p1);
114 5460 : return gc_upto(av, ZX_sub(s0, RgX_shift_shallow(s1,1)));
115 : }
116 :
117 : GEN
118 14 : RgX_Graeffe(GEN T, long d)
119 : {
120 14 : pari_sp av = avma;
121 14 : if (d <= 0) pari_err_DOMAIN("polgraeffe","n","<=",gen_0,stoi(d));
122 14 : switch(d)
123 : {
124 0 : case 1: return gcopy(T);
125 14 : case 2:
126 : {
127 : GEN T0, T1;
128 14 : RgX_even_odd(T, &T0, &T1);
129 14 : T0 = RgX_sqr(T0);
130 14 : T1 = RgX_sqr(T1);
131 14 : return gc_upto(av, RgX_sub(T0, RgX_shift_shallow(T1,1)));
132 : }
133 0 : case 3:
134 : {
135 0 : GEN h = RgX_splitting(T,3);
136 0 : GEN h1s = RgX_sqr(gel(h,1)), h2s = RgX_sqr(gel(h,2)), h3s = RgX_sqr(gel(h,3));
137 0 : GEN h13 = RgX_mul(gel(h,1), gel(h,3));
138 0 : GEN h1c = RgX_mul(gel(h,1), h1s);
139 0 : GEN h3c = RgX_mul(gel(h,3), h3s);
140 0 : GEN th = RgX_mul(RgX_sub(h2s, RgX_muls(h13,3)), gel(h,2));
141 0 : GEN R = RgX_add(RgX_shift_shallow(h3c,2), RgX_add(RgX_shift_shallow(th,1), h1c));
142 0 : return gc_upto(av, R);
143 : }
144 0 : default:
145 : {
146 : GEN P;
147 0 : long i, v = RgX_valrem(T, &P), l = lgpol(P);
148 0 : GEN Q = RgXn_div(RgX_deriv(P),P,l*d), R;
149 0 : GEN S = cgetg(l+2, t_POL);
150 0 : S[1] = P[1];
151 0 : for(i = 1; i <= l; i++)
152 0 : gel(S,1+i) = gel(Q,1+i*d);
153 0 : R = RgX_shift(RgX_Rg_mul(RgXn_expint(S,l), gpowgs(gel(P,2),d)), v);
154 0 : return gc_upto(av, R);
155 : }
156 : }
157 : }
158 :
159 : /* return q such that p(x)p(-x) = q(x^2) */
160 : GEN
161 0 : polgraeffe(GEN p)
162 : {
163 0 : pari_sp av = avma;
164 : GEN p0, p1, s0, s1;
165 0 : long n = degpol(p);
166 :
167 0 : if (typ(p) != t_POL) pari_err_TYPE("polgraeffe",p);
168 0 : n = degpol(p);
169 0 : if (!n) return gcopy(p);
170 0 : RgX_even_odd(p, &p0, &p1);
171 : /* p = p0(x^2) + x p1(x^2) */
172 0 : s0 = RgX_sqr(p0);
173 0 : s1 = RgX_sqr(p1);
174 0 : return gc_upto(av, RgX_sub(s0, RgX_shift_shallow(s1,1)));
175 : }
176 :
177 : GEN
178 14 : polgraeffe0(GEN p, long d)
179 : {
180 14 : if (typ(p) != t_POL) pari_err_TYPE("polgraeffe",p);
181 14 : return RgX_Graeffe(p, d);
182 : }
183 :
184 : /********************************************************************/
185 : /** **/
186 : /** MODULUS OF ROOTS **/
187 : /** **/
188 : /********************************************************************/
189 :
190 : /* Quick approximation to log2(|x|); first define y s.t. |y-x| < 2^-32 then
191 : * return y rounded to 2 ulp. In particular, if result < 2^21, absolute error
192 : * is bounded by 2^-31. If result > 2^21, it is correct to 2 ulp */
193 : static double
194 226870160 : mydbllog2i(GEN x)
195 : {
196 : #ifdef LONG_IS_64BIT
197 195102381 : const double W = 1/(4294967296. * 4294967296.); /* 2^-64 */
198 : #else
199 31767779 : const double W = 1/4294967296.; /*2^-32*/
200 : #endif
201 : GEN m;
202 226870160 : long lx = lgefint(x);
203 : double l;
204 226870160 : if (lx == 2) return -pariINFINITY;
205 226048913 : m = int_MSW(x);
206 226048913 : l = (double)(ulong)*m;
207 226048913 : if (lx == 3) return log2(l);
208 70331269 : l += ((double)(ulong)*int_precW(m)) * W;
209 : /* at least m = min(53,BIL) bits are correct in the mantissa, thus log2
210 : * is correct with error < log(1 + 2^-m) ~ 2^-m. Adding the correct
211 : * exponent BIL(lx-3) causes 1ulp further round-off error */
212 70331269 : return log2(l) + (double)(BITS_IN_LONG*(lx-3));
213 : }
214 :
215 : /* return log(|x|) or -pariINFINITY */
216 : static double
217 9572431 : mydbllogr(GEN x) {
218 9572431 : if (!signe(x)) return -pariINFINITY;
219 9572431 : return M_LN2*dbllog2r(x);
220 : }
221 :
222 : /* return log2(|x|) or -pariINFINITY */
223 : static double
224 58096677 : mydbllog2r(GEN x) {
225 58096677 : if (!signe(x)) return -pariINFINITY;
226 57657205 : return dbllog2r(x);
227 : }
228 : double
229 304402897 : dbllog2(GEN z)
230 : {
231 : double x, y;
232 304402897 : switch(typ(z))
233 : {
234 226763063 : case t_INT: return mydbllog2i(z);
235 22385 : case t_FRAC: return mydbllog2i(gel(z,1))-mydbllog2i(gel(z,2));
236 50605330 : case t_REAL: return mydbllog2r(z);
237 27012119 : default: /*t_COMPLEX*/
238 27012119 : x = dbllog2(gel(z,1));
239 27095239 : y = dbllog2(gel(z,2));
240 27095221 : if (x == -pariINFINITY) return y;
241 26851580 : if (y == -pariINFINITY) return x;
242 26647184 : if (fabs(x-y) > 10) return maxdd(x,y);
243 26026800 : return x + 0.5*log2(1 + exp2(2*(y-x)));
244 : }
245 : }
246 : static GEN /* beware overflow */
247 6568890 : dblexp(double x) { return fabs(x) < 100.? dbltor(exp(x)): mpexp(dbltor(x)); }
248 :
249 : /* find s such that A_h <= 2^s <= 2 A_i for one h and all i < n = deg(p),
250 : * with A_i := (binom(n,i) lc(p) / p_i) ^ 1/(n-i), and p = sum p_i X^i */
251 : static long
252 41052048 : findpower(GEN p)
253 : {
254 41052048 : double x, L, mins = pariINFINITY;
255 41052048 : long n = degpol(p),i;
256 :
257 41051441 : L = dbllog2(gel(p,n+2)); /* log2(lc * binom(n,i)) */
258 165094306 : for (i=n-1; i>=0; i--)
259 : {
260 124040906 : L += log2((double)(i+1) / (double)(n-i));
261 124040906 : x = dbllog2(gel(p,i+2));
262 124038930 : if (x != -pariINFINITY)
263 : {
264 123244464 : double s = (L - x) / (double)(n-i);
265 123244464 : if (s < mins) mins = s;
266 : }
267 : }
268 41053400 : i = (long)ceil(mins);
269 41053400 : if (i - mins > 1 - 1e-12) i--;
270 41053400 : return i;
271 : }
272 :
273 : /* returns the exponent for logmodulus(), from the Newton diagram */
274 : static long
275 5526473 : newton_polygon(GEN p, long k)
276 : {
277 5526473 : pari_sp av = avma;
278 5526473 : long n = degpol(p), i, j, h, l, *vertex = (long*)new_chunk(n+1);
279 5526468 : double *L = (double*)stack_malloc_align((n+1)*sizeof(double), sizeof(double));
280 :
281 : /* vertex[i] = 1 if i a vertex of convex hull, 0 otherwise */
282 26554910 : for (i=0; i<=n; i++) { L[i] = dbllog2(gel(p,2+i)); vertex[i] = 0; }
283 5526453 : vertex[0] = 1; /* sentinel */
284 19682022 : for (i=0; i < n; i=h)
285 : {
286 : double slope;
287 14155569 : h = i+1;
288 14160558 : while (L[i] == -pariINFINITY) { vertex[h] = 1; i = h; h = i+1; }
289 14155569 : slope = L[h] - L[i];
290 38151962 : for (j = i+2; j<=n; j++) if (L[j] != -pariINFINITY)
291 : {
292 23990138 : double pij = (L[j] - L[i])/(double)(j - i);
293 23990138 : if (slope < pij) { slope = pij; h = j; }
294 : }
295 14155569 : vertex[h] = 1;
296 : }
297 6243896 : h = k; while (!vertex[h]) h++;
298 5716485 : l = k-1; while (!vertex[l]) l--;
299 5526453 : set_avma(av);
300 5526495 : return (long)floor((L[h]-L[l])/(double)(h-l) + 0.5);
301 : }
302 :
303 : /* change z into z*2^e, where z is real or complex of real */
304 : static void
305 35613427 : myshiftrc(GEN z, long e)
306 : {
307 35613427 : if (typ(z)==t_COMPLEX)
308 : {
309 6405421 : if (signe(gel(z,1))) shiftr_inplace(gel(z,1), e);
310 6405442 : if (signe(gel(z,2))) shiftr_inplace(gel(z,2), e);
311 : }
312 : else
313 29208006 : if (signe(z)) shiftr_inplace(z, e);
314 35613499 : }
315 :
316 : /* return z*2^e, where z is integer or complex of integer (destroy z) */
317 : static GEN
318 136186856 : myshiftic(GEN z, long e)
319 : {
320 136186856 : if (typ(z)==t_COMPLEX)
321 : {
322 17867439 : gel(z,1) = signe(gel(z,1))? mpshift(gel(z,1),e): gen_0;
323 17866348 : gel(z,2) = mpshift(gel(z,2),e);
324 17863391 : return z;
325 : }
326 118319417 : return signe(z)? mpshift(z,e): gen_0;
327 : }
328 :
329 : static GEN
330 7055846 : RgX_gtofp_bit(GEN q, long bit) { return RgX_gtofp(q, nbits2prec(bit)); }
331 :
332 : static GEN
333 215653226 : mygprecrc(GEN x, long prec, long e)
334 : {
335 : GEN y;
336 215653226 : switch(typ(x))
337 : {
338 160987933 : case t_REAL:
339 160987933 : if (!signe(x)) return real_0_bit(e);
340 157695611 : return realprec(x) == prec? x: rtor(x, prec);
341 37236915 : case t_COMPLEX:
342 37236915 : y = cgetg(3,t_COMPLEX);
343 37236254 : gel(y,1) = mygprecrc(gel(x,1),prec,e);
344 37236091 : gel(y,2) = mygprecrc(gel(x,2),prec,e);
345 37236317 : return y;
346 17428378 : default: return x;
347 : }
348 : }
349 :
350 : /* gprec behaves badly with the zero for polynomials.
351 : The second parameter in mygprec is the precision in base 2 */
352 : static GEN
353 63959448 : mygprec(GEN x, long bit)
354 : {
355 : long e, prec;
356 63959448 : if (bit < 0) bit = 0; /* should rarely happen */
357 63959448 : e = gexpo(x) - bit;
358 63960513 : prec = nbits2prec(bit);
359 63965874 : switch(typ(x))
360 : {
361 168490169 : case t_POL: pari_APPLY_pol_normalized(mygprecrc(gel(x,i),prec,e));
362 17384898 : default: return mygprecrc(x,prec,e);
363 : }
364 : }
365 :
366 : /* normalize a polynomial x, that is change it with coefficients in Z[i],
367 : after making product by 2^shift */
368 : static GEN
369 17641202 : pol_to_gaussint(GEN x, long shift)
370 100672397 : { pari_APPLY_pol_normalized(gtrunc2n(gel(x,i), shift)); }
371 :
372 : /* returns a polynomial q in Z[i][x] keeping bit bits of p */
373 : static GEN
374 13180337 : eval_rel_pol(GEN p, long bit)
375 : {
376 : long i;
377 74272814 : for (i = 2; i < lg(p); i++)
378 61092467 : if (gequal0(gel(p,i))) gel(p,i) = gen_0; /* bad behavior of gexpo */
379 13180347 : return pol_to_gaussint(p, bit-gexpo(p)+1);
380 : }
381 :
382 : /* returns p(R*x)/R^n (in R or R[i]), R = exp(lrho), bit bits of precision */
383 : static GEN
384 1614881 : homothetie(GEN p, double lrho, long bit)
385 : {
386 : GEN q, r, t, iR;
387 1614881 : long n = degpol(p), i;
388 :
389 1614878 : iR = mygprec(dblexp(-lrho),bit);
390 1614849 : q = mygprec(p, bit);
391 1614886 : r = cgetg(n+3,t_POL); r[1] = p[1];
392 1614885 : t = iR; r[n+2] = q[n+2];
393 6819704 : for (i=n-1; i>0; i--)
394 : {
395 5204849 : gel(r,i+2) = gmul(t, gel(q,i+2));
396 5204807 : t = mulrr(t, iR);
397 : }
398 1614855 : gel(r,2) = gmul(t, gel(q,2)); return r;
399 : }
400 :
401 : /* change q in 2^(n*e) p(x*2^(-e)), n=deg(q) [ ~as above with R = 2^-e ]*/
402 : static void
403 9987030 : homothetie2n(GEN p, long e)
404 : {
405 9987030 : if (e)
406 : {
407 7997529 : long i,n = lg(p)-1;
408 43610962 : for (i=2; i<=n; i++) myshiftrc(gel(p,i), (n-i)*e);
409 : }
410 9987142 : }
411 :
412 : /* return 2^f * 2^(n*e) p(x*2^(-e)), n=deg(q) */
413 : static void
414 36582262 : homothetie_gauss(GEN p, long e, long f)
415 : {
416 36582262 : if (e || f)
417 : {
418 32681760 : long i, n = lg(p)-1;
419 168810666 : for (i=2; i<=n; i++) gel(p,i) = myshiftic(gel(p,i), f+(n-i)*e);
420 : }
421 36527940 : }
422 :
423 : /* Lower bound on the modulus of the largest root z_0
424 : * k is set to an upper bound for #{z roots, |z-z_0| < eps} */
425 : static double
426 41051549 : lower_bound(GEN p, long *k, double eps)
427 : {
428 41051549 : long n = degpol(p), i, j;
429 41052080 : pari_sp ltop = avma;
430 : GEN a, s, S, ilc;
431 : double r, R, rho;
432 :
433 41052080 : if (n < 4) { *k = n; return 0.; }
434 8279821 : S = cgetg(5,t_VEC);
435 8280520 : a = cgetg(5,t_VEC); ilc = gdiv(real_1(DEFAULTPREC), gel(p,n+2));
436 41381772 : for (i=1; i<=4; i++) gel(a,i) = gmul(ilc,gel(p,n+2-i));
437 : /* i = 1 split out from next loop for efficiency and initialization */
438 8279312 : s = gel(a,1);
439 8279312 : gel(S,1) = gneg(s); /* Newton sum S_i */
440 8279933 : rho = r = gtodouble(gabs(s,3));
441 8280495 : R = r / n;
442 33117876 : for (i=2; i<=4; i++)
443 : {
444 24837559 : s = gmulsg(i,gel(a,i));
445 74432931 : for (j=1; j<i; j++) s = gadd(s, gmul(gel(S,j),gel(a,i-j)));
446 24821159 : gel(S,i) = gneg(s); /* Newton sum S_i */
447 24831735 : r = gtodouble(gabs(s,3));
448 24837381 : if (r > 0.)
449 : {
450 24790530 : r = exp(log(r/n) / (double)i);
451 24790530 : if (r > R) R = r;
452 : }
453 : }
454 8280317 : if (R > 0. && eps < 1.2)
455 8276591 : *k = (long)floor((rho/R + n) / (1 + exp(-eps)*cos(eps)));
456 : else
457 3726 : *k = n;
458 8280317 : return gc_double(ltop, R);
459 : }
460 :
461 : /* return R such that exp(R - tau) <= rho_n(P) <= exp(R + tau)
462 : * P(0) != 0 and P non constant */
463 : static double
464 4460906 : logmax_modulus(GEN p, double tau)
465 : {
466 : GEN r, q, aux, gunr;
467 4460906 : pari_sp av, ltop = avma;
468 4460906 : long i,k,n=degpol(p),nn,bit,M,e;
469 4460900 : double rho,eps, tau2 = (tau > 3.0)? 0.5: tau/6.;
470 :
471 4460900 : r = cgeti(BIGDEFAULTPREC);
472 4460870 : av = avma;
473 :
474 4460870 : eps = - 1/log(1.5*tau2); /* > 0 */
475 4460870 : bit = (long) ((double) n*log2(1./tau2)+3*log2((double) n))+1;
476 4460870 : gunr = real_1_bit(bit+2*n);
477 4460839 : aux = gdiv(gunr, gel(p,2+n));
478 4460844 : q = RgX_Rg_mul(p, aux); gel(q,2+n) = gunr;
479 4460702 : e = findpower(q);
480 4460851 : homothetie2n(q,e);
481 4460885 : affsi(e, r);
482 4460882 : q = pol_to_gaussint(q, bit);
483 4460533 : M = (long) (log2( log(4.*n) / (2*tau2) )) + 2;
484 4460533 : nn = n;
485 4460533 : for (i=0,e=0;;)
486 : { /* nn = deg(q) */
487 41054352 : rho = lower_bound(q, &k, eps);
488 41051549 : if (rho > exp2(-(double)e)) e = (long)-floor(log2(rho));
489 41051549 : affii(shifti(addis(r,e), 1), r);
490 41009448 : if (++i == M) break;
491 :
492 36549304 : bit = (long) ((double)k * log2(1./tau2) +
493 36549304 : (double)(nn-k)*log2(1./eps) + 3*log2((double)nn)) + 1;
494 36549304 : homothetie_gauss(q, e, bit-(long)floor(dbllog2(gel(q,2+nn))+0.5));
495 36565297 : nn -= RgX_valrem(q, &q);
496 36569576 : q = gc_upto(av, graeffe(q));
497 36592996 : tau2 *= 1.5; if (tau2 > 0.9) tau2 = 0.5;
498 36592996 : eps = -1/log(tau2); /* > 0 */
499 36592996 : e = findpower(q);
500 : }
501 4460144 : if (!signe(r)) return gc_double(ltop,0.);
502 4036507 : r = itor(r, DEFAULTPREC); shiftr_inplace(r, -M);
503 4036966 : return gc_double(ltop, -rtodbl(r) * M_LN2); /* -log(2) sum e_i 2^-i */
504 : }
505 :
506 : static GEN
507 36408 : RgX_normalize1(GEN x)
508 : {
509 36408 : long i, n = lg(x)-1;
510 : GEN y;
511 36422 : for (i = n; i > 1; i--)
512 36415 : if (!gequal0( gel(x,i) )) break;
513 36408 : if (i == n) return x;
514 14 : pari_warn(warner,"normalizing a polynomial with 0 leading term");
515 14 : if (i == 1) pari_err_ROOTS0("roots");
516 14 : y = cgetg(i+1, t_POL); y[1] = x[1];
517 42 : for (; i > 1; i--) gel(y,i) = gel(x,i);
518 14 : return y;
519 : }
520 :
521 : static GEN
522 27800 : polrootsbound_i(GEN P, double TAU)
523 : {
524 27800 : pari_sp av = avma;
525 : double d;
526 27800 : (void)RgX_valrem_inexact(P,&P);
527 27800 : P = RgX_normalize1(P);
528 27800 : switch(degpol(P))
529 : {
530 7 : case -1: pari_err_ROOTS0("roots");
531 140 : case 0: set_avma(av); return gen_0;
532 : }
533 27653 : d = logmax_modulus(P, TAU) + TAU;
534 : /* not dblexp: result differs on ARM emulator */
535 27653 : return gc_leaf(av, mpexp(dbltor(d)));
536 : }
537 : GEN
538 27807 : polrootsbound(GEN P, GEN tau)
539 : {
540 27807 : if (typ(P) != t_POL) pari_err_TYPE("polrootsbound",P);
541 27800 : checkvalidpol(P, "polrootsbound");
542 27800 : return polrootsbound_i(P, tau? gtodouble(tau): 0.01);
543 : }
544 :
545 : /* log of modulus of the smallest root of p, with relative error tau */
546 : static double
547 1618088 : logmin_modulus(GEN p, double tau)
548 : {
549 1618088 : pari_sp av = avma;
550 1618088 : if (gequal0(gel(p,2))) return -pariINFINITY;
551 1618086 : return gc_double(av, - logmax_modulus(RgX_recip_i(p),tau));
552 : }
553 :
554 : /* return the log of the k-th modulus (ascending order) of p, rel. error tau*/
555 : static double
556 608816 : logmodulus(GEN p, long k, double tau)
557 : {
558 : GEN q;
559 608816 : long i, kk = k, imax, n = degpol(p), nn, bit, e;
560 608816 : pari_sp av, ltop=avma;
561 608816 : double r, tau2 = tau/6;
562 :
563 608816 : bit = (long)(n * (2. + log2(3.*n/tau2)));
564 608816 : av = avma;
565 608816 : q = gprec_w(p, nbits2prec(bit));
566 608817 : q = RgX_gtofp_bit(q, bit);
567 608815 : e = newton_polygon(q,k);
568 608816 : r = (double)e;
569 608816 : homothetie2n(q,e);
570 608821 : imax = (long)(log2(3./tau) + log2(log(4.*n)))+1;
571 5526440 : for (i=1; i<imax; i++)
572 : {
573 4917624 : q = eval_rel_pol(q,bit);
574 4917390 : kk -= RgX_valrem(q, &q);
575 4917515 : nn = degpol(q);
576 :
577 4917507 : q = gc_upto(av, graeffe(q));
578 4917671 : e = newton_polygon(q,kk);
579 4917688 : r += e / exp2((double)i);
580 4917688 : q = RgX_gtofp_bit(q, bit);
581 4917546 : homothetie2n(q,e);
582 :
583 4917619 : tau2 *= 1.5; if (tau2 > 1.) tau2 = 1.;
584 4917619 : bit = 1 + (long)(nn*(2. + log2(3.*nn/tau2)));
585 : }
586 608816 : return gc_double(ltop, -r * M_LN2);
587 : }
588 :
589 : /* return the log of the k-th modulus r_k of p, rel. error tau, knowing that
590 : * rmin < r_k < rmax. This information helps because we may reduce precision
591 : * quicker */
592 : static double
593 608816 : logpre_modulus(GEN p, long k, double tau, double lrmin, double lrmax)
594 : {
595 : GEN q;
596 608816 : long n = degpol(p), i, imax, imax2, bit;
597 608816 : pari_sp ltop = avma, av;
598 608816 : double lrho, aux, tau2 = tau/6.;
599 :
600 608816 : aux = (lrmax - lrmin) / 2. + 4*tau2;
601 608816 : imax = (long) log2(log((double)n)/ aux);
602 608816 : if (imax <= 0) return logmodulus(p,k,tau);
603 :
604 599693 : lrho = (lrmin + lrmax) / 2;
605 599693 : av = avma;
606 599693 : bit = (long)(n*(2. + aux / M_LN2 - log2(tau2)));
607 599693 : q = homothetie(p, lrho, bit);
608 599690 : imax2 = (long)(log2(3./tau * log(4.*n))) + 1;
609 599690 : if (imax > imax2) imax = imax2;
610 :
611 1590571 : for (i=0; i<imax; i++)
612 : {
613 990878 : q = eval_rel_pol(q,bit);
614 990865 : q = gc_upto(av, graeffe(q));
615 990881 : aux = 2*aux + 2*tau2;
616 990881 : tau2 *= 1.5;
617 990881 : bit = (long)(n*(2. + aux / M_LN2 - log2(1-exp(-tau2))));
618 990881 : q = RgX_gtofp_bit(q, bit);
619 : }
620 599693 : aux = exp2((double)imax);
621 599693 : return gc_double(ltop, lrho + logmodulus(q,k, aux*tau/3.) / aux);
622 : }
623 :
624 : static double
625 904839 : ind_maxlog2(GEN q)
626 : {
627 904839 : long i, k = -1;
628 904839 : double L = - pariINFINITY;
629 2227554 : for (i=0; i<=degpol(q); i++)
630 : {
631 1322712 : double d = dbllog2(gel(q,2+i));
632 1322715 : if (d > L) { L = d; k = i; }
633 : }
634 904839 : return k;
635 : }
636 :
637 : /* Returns k such that r_k e^(-tau) < R < r_{k+1} e^tau.
638 : * Assume that l <= k <= n-l */
639 : static long
640 1015194 : dual_modulus(GEN p, double lrho, double tau, long l)
641 : {
642 1015194 : long i, imax, delta_k = 0, n = degpol(p), nn, v2, v, bit, ll = l;
643 1015193 : double tau2 = tau * 7./8.;
644 1015193 : pari_sp av = avma;
645 : GEN q;
646 :
647 1015193 : bit = 6*n - 5*l + (long)(n*(-log2(tau2) + tau2 * 8./7.));
648 1015193 : q = homothetie(p, lrho, bit);
649 1015191 : imax = (long)(log(log(2.*n)/tau2)/log(7./4.)+1);
650 :
651 8176954 : for (i=0; i<imax; i++)
652 : {
653 7272115 : q = eval_rel_pol(q,bit); v2 = n - degpol(q);
654 7270885 : v = RgX_valrem(q, &q);
655 7271518 : ll -= maxss(v, v2); if (ll < 0) ll = 0;
656 :
657 7271706 : nn = degpol(q); delta_k += v;
658 7271716 : if (!nn) return delta_k;
659 :
660 7161355 : q = gc_upto(av, graeffe(q));
661 7161763 : tau2 *= 7./4.;
662 7161763 : bit = 6*nn - 5*ll + (long)(nn*(-log2(tau2) + tau2 * 8./7.));
663 : }
664 904839 : return gc_long(av, delta_k + (long)ind_maxlog2(q));
665 : }
666 :
667 : /********************************************************************/
668 : /** **/
669 : /** FACTORS THROUGH CIRCLE INTEGRATION **/
670 : /** **/
671 : /********************************************************************/
672 : /* l power of 2, W[step*j] = w_j; set f[j] = p(w_j)
673 : * if inv, w_j = exp(2IPi*j/l), else exp(-2IPi*j/l) */
674 :
675 : static void
676 7462 : fft2(GEN W, GEN p, GEN f, long step, long l)
677 : {
678 : pari_sp av;
679 : long i, s1, l1, step2;
680 :
681 7462 : if (l == 2)
682 : {
683 3766 : gel(f,0) = gadd(gel(p,0), gel(p,step));
684 3766 : gel(f,1) = gsub(gel(p,0), gel(p,step)); return;
685 : }
686 3696 : av = avma;
687 3696 : l1 = l>>1; step2 = step<<1;
688 3696 : fft2(W,p, f, step2,l1);
689 3696 : fft2(W,p+step, f+l1,step2,l1);
690 32760 : for (i = s1 = 0; i < l1; i++, s1 += step)
691 : {
692 29064 : GEN f0 = gel(f,i);
693 29064 : GEN f1 = gmul(gel(W,s1), gel(f,i+l1));
694 29064 : gel(f,i) = gadd(f0, f1);
695 29064 : gel(f,i+l1) = gsub(f0, f1);
696 : }
697 3696 : gc_slice(av, f, l);
698 : }
699 :
700 : static void
701 14224039 : fft(GEN W, GEN p, GEN f, long step, long l, long inv)
702 : {
703 : pari_sp av;
704 : long i, s1, l1, l2, l3, step4;
705 : GEN f1, f2, f3, f02;
706 :
707 14224039 : if (l == 2)
708 : {
709 6685650 : gel(f,0) = gadd(gel(p,0), gel(p,step));
710 6685352 : gel(f,1) = gsub(gel(p,0), gel(p,step)); return;
711 : }
712 7538389 : av = avma;
713 7538389 : if (l == 4)
714 : {
715 : pari_sp av2;
716 5324756 : f1 = gadd(gel(p,0), gel(p,step<<1));
717 5324264 : f2 = gsub(gel(p,0), gel(p,step<<1));
718 5324278 : f3 = gadd(gel(p,step), gel(p,3*step));
719 5324208 : f02 = gsub(gel(p,step), gel(p,3*step));
720 5324242 : f02 = inv? mulcxI(f02): mulcxmI(f02);
721 5324669 : av2 = avma;
722 5324669 : gel(f,0) = gadd(f1, f3);
723 5324080 : gel(f,1) = gadd(f2, f02);
724 5324248 : gel(f,2) = gsub(f1, f3);
725 5324108 : gel(f,3) = gsub(f2, f02);
726 5324334 : gc_all_unsafe(av,av2,4,&gel(f,0),&gel(f,1),&gel(f,2),&gel(f,3));
727 5324912 : return;
728 : }
729 2213633 : l1 = l>>2; l2 = 2*l1; l3 = l1+l2; step4 = step<<2;
730 2213633 : fft(W,p, f, step4,l1,inv);
731 2214042 : fft(W,p+step, f+l1,step4,l1,inv);
732 2214047 : fft(W,p+(step<<1),f+l2,step4,l1,inv);
733 2214052 : fft(W,p+3*step, f+l3,step4,l1,inv);
734 8239467 : for (i = s1 = 0; i < l1; i++, s1 += step)
735 : {
736 6025473 : long s2 = s1 << 1, s3 = s1 + s2;
737 : GEN g02, g13, f13;
738 6025473 : f1 = gmul(gel(W,s1), gel(f,i+l1));
739 6025656 : f2 = gmul(gel(W,s2), gel(f,i+l2));
740 6025569 : f3 = gmul(gel(W,s3), gel(f,i+l3));
741 :
742 6025688 : f02 = gadd(gel(f,i),f2);
743 6025126 : g02 = gsub(gel(f,i),f2);
744 6025187 : f13 = gadd(f1,f3);
745 6025098 : g13 = gsub(f1,f3); g13 = inv? mulcxI(g13): mulcxmI(g13);
746 :
747 6025632 : gel(f,i) = gadd(f02, f13);
748 6025187 : gel(f,i+l1) = gadd(g02, g13);
749 6025190 : gel(f,i+l2) = gsub(f02, f13);
750 6025203 : gel(f,i+l3) = gsub(g02, g13);
751 : }
752 2213994 : gc_slice(av, f, l);
753 : }
754 :
755 : static GEN
756 98 : FFT_i(GEN W, GEN x)
757 : {
758 98 : long i, l = lg(W), n = lg(x), tx = typ(x), tw, pa;
759 : GEN y, z, p, pol;
760 98 : if (l==1 || ((l-1) & (l-2))) pari_err_DIM("fft");
761 84 : tw = RgV_type(W, &p, &pol, &pa);
762 84 : if (tx == t_POL) { x++; n--; }
763 49 : else if (!is_vec_t(tx)) pari_err_TYPE("fft",x);
764 84 : if (n > l) pari_err_DIM("fft");
765 84 : if (n < l) {
766 0 : z = cgetg(l, t_VECSMALL); /* cf stackdummy */
767 0 : for (i = 1; i < n; i++) gel(z,i) = gel(x,i);
768 0 : for ( ; i < l; i++) gel(z,i) = gen_0;
769 : }
770 84 : else z = x;
771 84 : if (l == 2) return mkveccopy(gel(z,1));
772 70 : y = cgetg(l, t_VEC);
773 70 : if (tw == RgX_type_code(t_COMPLEX,t_INT) ||
774 : tw == RgX_type_code(t_COMPLEX,t_REAL))
775 0 : {
776 0 : long inv = (l >= 5 && signe(imag_i(gel(W,1+(l>>2))))==1) ? 1 : 0;
777 0 : fft(W+1, z+1, y+1, 1, l-1, inv);
778 : } else
779 70 : fft2(W+1, z+1, y+1, 1, l-1);
780 70 : return y;
781 : }
782 :
783 : GEN
784 56 : FFT(GEN W, GEN x)
785 : {
786 56 : if (!is_vec_t(typ(W))) pari_err_TYPE("fft",W);
787 56 : return FFT_i(W, x);
788 : }
789 :
790 : GEN
791 56 : FFTinv(GEN W, GEN x)
792 : {
793 56 : long l = lg(W), i;
794 : GEN w;
795 56 : if (!is_vec_t(typ(W))) pari_err_TYPE("fft",W);
796 56 : if (l==1 || ((l-1) & (l-2))) pari_err_DIM("fft");
797 42 : w = cgetg(l, t_VECSMALL); /* cf stackdummy */
798 42 : gel(w,1) = gel(W,1); /* w = gconj(W), faster */
799 3773 : for (i = 2; i < l; i++) gel(w, i) = gel(W, l-i+1);
800 42 : return FFT_i(w, x);
801 : }
802 :
803 : /* returns 1 if p has only real coefficients, 0 else */
804 : static int
805 964382 : isreal(GEN p)
806 : {
807 : long i;
808 4877965 : for (i = lg(p)-1; i > 1; i--)
809 4075002 : if (typ(gel(p,i)) == t_COMPLEX) return 0;
810 802963 : return 1;
811 : }
812 :
813 : /* x non complex */
814 : static GEN
815 781157 : abs_update_r(GEN x, double *mu) {
816 781157 : GEN y = gtofp(x, DEFAULTPREC);
817 781159 : double ly = mydbllogr(y); if (ly < *mu) *mu = ly;
818 781159 : setabssign(y); return y;
819 : }
820 : /* return |x|, low accuracy. Set *mu = min(log(y), *mu) */
821 : static GEN
822 8026400 : abs_update(GEN x, double *mu) {
823 : GEN y, xr, yr;
824 : double ly;
825 8026400 : if (typ(x) != t_COMPLEX) return abs_update_r(x, mu);
826 7258568 : xr = gel(x,1);
827 7258568 : yr = gel(x,2);
828 7258568 : if (gequal0(xr)) return abs_update_r(yr,mu);
829 7256617 : if (gequal0(yr)) return abs_update_r(xr,mu);
830 : /* have to treat 0 specially: 0E-10 + 1e-20 = 0E-10 */
831 7245456 : xr = gtofp(xr, DEFAULTPREC);
832 7246081 : yr = gtofp(yr, DEFAULTPREC);
833 7246106 : y = sqrtr(addrr(sqrr(xr), sqrr(yr)));
834 7246075 : ly = mydbllogr(y); if (ly < *mu) *mu = ly;
835 7246231 : return y;
836 : }
837 :
838 : static void
839 998957 : initdft(GEN *Omega, GEN *prim, long N, long Lmax, long bit)
840 : {
841 998957 : long prec = nbits2prec(bit);
842 998957 : *Omega = grootsof1(Lmax, prec) + 1;
843 998953 : *prim = rootsof1u_cx(N, prec);
844 998959 : }
845 :
846 : static void
847 495259 : parameters(GEN p, long *LMAX, double *mu, double *gamma,
848 : int polreal, double param, double param2)
849 : {
850 : GEN q, pc, Omega, A, RU, prim, g, TWO;
851 495259 : long n = degpol(p), bit, NN, K, i, j, Lmax;
852 495259 : pari_sp av2, av = avma;
853 :
854 495259 : bit = gexpo(p) + (long)param2+8;
855 686006 : Lmax = 4; while (Lmax <= n) Lmax <<= 1;
856 495259 : NN = (long)(param*3.14)+1; if (NN < Lmax) NN = Lmax;
857 495259 : K = NN/Lmax; if (K & 1) K++;
858 495259 : NN = Lmax*K;
859 495259 : if (polreal) K = K/2+1;
860 :
861 495259 : initdft(&Omega, &prim, NN, Lmax, bit);
862 495259 : q = mygprec(p,bit) + 2;
863 495259 : A = cgetg(Lmax+1,t_VEC); A++;
864 495259 : pc= cgetg(Lmax+1,t_VEC); pc++;
865 2965720 : for (i=0; i <= n; i++) gel(pc,i)= gel(q,i);
866 971561 : for ( ; i<Lmax; i++) gel(pc,i) = gen_0;
867 :
868 495259 : *mu = pariINFINITY;
869 495259 : g = real_0_bit(-bit);
870 495259 : TWO = real2n(1, DEFAULTPREC);
871 495262 : av2 = avma;
872 495262 : RU = gen_1;
873 1741522 : for (i=0; i<K; i++)
874 : {
875 1246265 : if (i) {
876 751008 : GEN z = RU;
877 3451375 : for (j=1; j<n; j++)
878 : {
879 2700365 : gel(pc,j) = gmul(gel(q,j),z);
880 2700314 : z = gmul(z,RU); /* RU = prim^i, z=prim^(ij) */
881 : }
882 751010 : gel(pc,n) = gmul(gel(q,n),z);
883 : }
884 :
885 1246258 : fft(Omega,pc,A,1,Lmax,1);
886 1246269 : if (polreal && i>0 && i<K-1)
887 1147349 : for (j=0; j<Lmax; j++) g = addrr(g, divrr(TWO, abs_update(gel(A,j),mu)));
888 : else
889 8125173 : for (j=0; j<Lmax; j++) g = addrr(g, invr(abs_update(gel(A,j),mu)));
890 1245996 : RU = gmul(RU, prim);
891 1246260 : if (gc_needed(av,1))
892 : {
893 0 : if(DEBUGMEM>1) pari_warn(warnmem,"parameters");
894 0 : (void)gc_all(av2,2, &g,&RU);
895 : }
896 : }
897 495257 : *gamma = mydbllog2r(divru(g,NN));
898 495255 : *LMAX = Lmax; set_avma(av);
899 495254 : }
900 :
901 : /* NN is a multiple of Lmax */
902 : static void
903 503700 : dft(GEN p, long k, long NN, long Lmax, long bit, GEN F, GEN H, long polreal)
904 : {
905 : GEN Omega, q, qd, pc, pd, A, B, C, RU, aux, U, W, prim, prim2;
906 503700 : long n = degpol(p), i, j, K;
907 : pari_sp ltop;
908 :
909 503700 : initdft(&Omega, &prim, NN, Lmax, bit);
910 503700 : RU = cgetg(n+2,t_VEC) + 1;
911 :
912 503700 : K = NN/Lmax; if (polreal) K = K/2+1;
913 503700 : q = mygprec(p,bit);
914 503700 : qd = RgX_deriv(q);
915 :
916 503698 : A = cgetg(Lmax+1,t_VEC); A++;
917 503699 : B = cgetg(Lmax+1,t_VEC); B++;
918 503699 : C = cgetg(Lmax+1,t_VEC); C++;
919 503699 : pc = cgetg(Lmax+1,t_VEC); pc++;
920 503699 : pd = cgetg(Lmax+1,t_VEC); pd++;
921 1022071 : gel(pc,0) = gel(q,2); for (i=n+1; i<Lmax; i++) gel(pc,i) = gen_0;
922 1525770 : gel(pd,0) = gel(qd,2); for (i=n; i<Lmax; i++) gel(pd,i) = gen_0;
923 :
924 503699 : ltop = avma;
925 503699 : W = cgetg(k+1,t_VEC);
926 503699 : U = cgetg(k+1,t_VEC);
927 1205843 : for (i=1; i<=k; i++) gel(W,i) = gel(U,i) = gen_0;
928 :
929 503699 : gel(RU,0) = gen_1;
930 503699 : prim2 = gen_1;
931 1534346 : for (i=0; i<K; i++)
932 : {
933 1030647 : gel(RU,1) = prim2;
934 4462458 : for (j=1; j<n; j++) gel(RU,j+1) = gmul(gel(RU,j),prim2);
935 : /* RU[j] = prim^(ij)= prim2^j */
936 :
937 4462405 : for (j=1; j<n; j++) gel(pd,j) = gmul(gel(qd,j+2),gel(RU,j));
938 1030602 : fft(Omega,pd,A,1,Lmax,1);
939 5492997 : for (j=1; j<=n; j++) gel(pc,j) = gmul(gel(q,j+2),gel(RU,j));
940 1030576 : fft(Omega,pc,B,1,Lmax,1);
941 7691449 : for (j=0; j<Lmax; j++) gel(C,j) = ginv(gel(B,j));
942 7691290 : for (j=0; j<Lmax; j++) gel(B,j) = gmul(gel(A,j),gel(C,j));
943 1030515 : fft(Omega,B,A,1,Lmax,1);
944 1030647 : fft(Omega,C,B,1,Lmax,1);
945 :
946 1030646 : if (polreal) /* p has real coefficients */
947 : {
948 799544 : if (i>0 && i<K-1)
949 : {
950 103352 : for (j=1; j<=k; j++)
951 : {
952 86650 : gel(W,j) = gadd(gel(W,j), gshift(mulreal(gel(A,j+1),gel(RU,j+1)),1));
953 86650 : gel(U,j) = gadd(gel(U,j), gshift(mulreal(gel(B,j),gel(RU,j)),1));
954 : }
955 : }
956 : else
957 : {
958 1838118 : for (j=1; j<=k; j++)
959 : {
960 1055290 : gel(W,j) = gadd(gel(W,j), mulreal(gel(A,j+1),gel(RU,j+1)));
961 1055287 : gel(U,j) = gadd(gel(U,j), mulreal(gel(B,j),gel(RU,j)));
962 : }
963 : }
964 : }
965 : else
966 : {
967 604980 : for (j=1; j<=k; j++)
968 : {
969 373882 : gel(W,j) = gadd(gel(W,j), gmul(gel(A,j+1),gel(RU,j+1)));
970 373875 : gel(U,j) = gadd(gel(U,j), gmul(gel(B,j),gel(RU,j)));
971 : }
972 : }
973 1030628 : prim2 = gmul(prim2,prim);
974 1030632 : (void)gc_all(ltop,3, &W,&U,&prim2);
975 : }
976 :
977 1205832 : for (i=1; i<=k; i++)
978 : {
979 702143 : aux=gel(W,i);
980 1103805 : for (j=1; j<i; j++) aux = gadd(aux, gmul(gel(W,i-j),gel(F,k+2-j)));
981 702142 : gel(F,k+2-i) = gdivgs(aux,-i*NN);
982 : }
983 1205821 : for (i=0; i<k; i++)
984 : {
985 702135 : aux=gel(U,k-i);
986 1103796 : for (j=1+i; j<k; j++) aux = gadd(aux,gmul(gel(F,2+j),gel(U,j-i)));
987 702132 : gel(H,i+2) = gdivgu(aux,NN);
988 : }
989 503686 : }
990 :
991 : #define NEWTON_MAX 10
992 : static GEN
993 2465884 : refine_H(GEN F, GEN G, GEN HH, long bit, long Sbit)
994 : {
995 2465884 : GEN H = HH, D, aux;
996 2465884 : pari_sp ltop = avma;
997 : long error, i, bit1, bit2;
998 :
999 2465884 : D = Rg_RgX_sub(gen_1, RgX_rem(RgX_mul(H,G),F)); error = gexpo(D);
1000 2465859 : bit2 = bit + Sbit;
1001 4506276 : for (i=0; error>-bit && i<NEWTON_MAX && error<=0; i++)
1002 : {
1003 2040418 : if (gc_needed(ltop,1))
1004 : {
1005 0 : if(DEBUGMEM>1) pari_warn(warnmem,"refine_H");
1006 0 : (void)gc_all(ltop,2, &D,&H);
1007 : }
1008 2040418 : bit1 = -error + Sbit;
1009 2040418 : aux = RgX_mul(mygprec(H,bit1), mygprec(D,bit1));
1010 2040415 : aux = RgX_rem(mygprec(aux,bit1), mygprec(F,bit1));
1011 :
1012 2040428 : bit1 = -error*2 + Sbit; if (bit1 > bit2) bit1 = bit2;
1013 2040428 : H = RgX_add(mygprec(H,bit1), aux);
1014 2040362 : D = Rg_RgX_sub(gen_1, RgX_rem(RgX_mul(H,G),F));
1015 2040418 : error = gexpo(D); if (error < -bit1) error = -bit1;
1016 : }
1017 2465858 : if (error > -bit/2) return NULL; /* FAIL */
1018 2465535 : return gc_GEN(ltop,H);
1019 : }
1020 :
1021 : /* return 0 if fails, 1 else */
1022 : static long
1023 503690 : refine_F(GEN p, GEN *F, GEN *G, GEN H, long bit, double gamma)
1024 : {
1025 503690 : GEN f0, FF, GG, r, HH = H;
1026 503690 : long error, i, bit1 = 0, bit2, Sbit, Sbit2, enh, normF, normG, n = degpol(p);
1027 503690 : pari_sp av = avma;
1028 :
1029 503690 : FF = *F; GG = RgX_divrem(p, FF, &r);
1030 503698 : error = gexpo(r); if (error <= -bit) error = 1-bit;
1031 503698 : normF = gexpo(FF);
1032 503700 : normG = gexpo(GG);
1033 503699 : enh = gexpo(H); if (enh < 0) enh = 0;
1034 503699 : Sbit = normF + 2*normG + enh + (long)(4.*log2((double)n)+gamma) + 1;
1035 503699 : Sbit2 = enh + 2*(normF+normG) + (long)(2.*gamma+5.*log2((double)n)) + 1;
1036 503699 : bit2 = bit + Sbit;
1037 2969250 : for (i=0; error>-bit && i<NEWTON_MAX && error<=0; i++)
1038 : {
1039 2465878 : if (bit1 == bit2 && i >= 2) { Sbit += n; Sbit2 += n; bit2 += n; }
1040 2465878 : if (gc_needed(av,1))
1041 : {
1042 0 : if(DEBUGMEM>1) pari_warn(warnmem,"refine_F");
1043 0 : (void)gc_all(av,4, &FF,&GG,&r,&HH);
1044 : }
1045 :
1046 2465878 : bit1 = -error + Sbit2;
1047 2465878 : HH = refine_H(mygprec(FF,bit1), mygprec(GG,bit1), mygprec(HH,bit1),
1048 : 1-error, Sbit2);
1049 2465899 : if (!HH) return 0; /* FAIL */
1050 :
1051 2465576 : bit1 = -error + Sbit;
1052 2465576 : r = RgX_mul(mygprec(HH,bit1), mygprec(r,bit1));
1053 2465532 : f0 = RgX_rem(mygprec(r,bit1), mygprec(FF,bit1));
1054 :
1055 2465561 : bit1 = -2*error + Sbit; if (bit1 > bit2) bit1 = bit2;
1056 2465561 : FF = gadd(mygprec(FF,bit1),f0);
1057 :
1058 2465527 : bit1 = -3*error + Sbit; if (bit1 > bit2) bit1 = bit2;
1059 2465527 : GG = RgX_divrem(mygprec(p,bit1), mygprec(FF,bit1), &r);
1060 2465562 : error = gexpo(r); if (error < -bit1) error = -bit1;
1061 : }
1062 503372 : if (error>-bit) return 0; /* FAIL */
1063 495254 : *F = FF; *G = GG; return 1;
1064 : }
1065 :
1066 : /* returns F and G from the unit circle U such that |p-FG|<2^(-bit) |cd|,
1067 : where cd is the leading coefficient of p */
1068 : static void
1069 495258 : split_fromU(GEN p, long k, double delta, long bit,
1070 : GEN *F, GEN *G, double param, double param2)
1071 : {
1072 : GEN pp, FF, GG, H;
1073 495258 : long n = degpol(p), NN, bit2, Lmax;
1074 495258 : int polreal = isreal(p);
1075 : pari_sp ltop;
1076 : double mu, gamma;
1077 :
1078 495258 : pp = gdiv(p, gel(p,2+n));
1079 495259 : parameters(pp, &Lmax,&mu,&gamma, polreal,param,param2);
1080 :
1081 495254 : H = cgetg(k+2,t_POL); H[1] = p[1];
1082 495255 : FF = cgetg(k+3,t_POL); FF[1]= p[1];
1083 495257 : gel(FF,k+2) = gen_1;
1084 :
1085 495257 : NN = (long)(0.5/delta); NN |= 1; if (NN < 2) NN = 2;
1086 495257 : NN *= Lmax; ltop = avma;
1087 : for(;;)
1088 : {
1089 503698 : bit2 = (long)(((double)NN*delta-mu)/M_LN2) + gexpo(pp) + 8;
1090 503698 : dft(pp, k, NN, Lmax, bit2, FF, H, polreal);
1091 503690 : if (refine_F(pp,&FF,&GG,H,bit,gamma)) break;
1092 8441 : NN <<= 1; set_avma(ltop);
1093 : }
1094 495258 : *G = gmul(GG,gel(p,2+n)); *F = FF;
1095 495253 : }
1096 :
1097 : static void
1098 495259 : optimize_split(GEN p, long k, double delta, long bit,
1099 : GEN *F, GEN *G, double param, double param2)
1100 : {
1101 495259 : long n = degpol(p);
1102 : GEN FF, GG;
1103 :
1104 495259 : if (k <= n/2)
1105 384024 : split_fromU(p,k,delta,bit,F,G,param,param2);
1106 : else
1107 : {
1108 111235 : split_fromU(RgX_recip_i(p),n-k,delta,bit,&FF,&GG,param,param2);
1109 111235 : *F = RgX_recip_i(GG);
1110 111235 : *G = RgX_recip_i(FF);
1111 : }
1112 495254 : }
1113 :
1114 : /********************************************************************/
1115 : /** **/
1116 : /** SEARCH FOR SEPARATING CIRCLE **/
1117 : /** **/
1118 : /********************************************************************/
1119 :
1120 : /* return p(2^e*x) *2^(-n*e) */
1121 : static void
1122 0 : scalepol2n(GEN p, long e)
1123 : {
1124 0 : long i,n=lg(p)-1;
1125 0 : for (i=2; i<=n; i++) gel(p,i) = gmul2n(gel(p,i),(i-n)*e);
1126 0 : }
1127 :
1128 : /* returns p(x/R)*R^n; assume R is at the correct accuracy */
1129 : static GEN
1130 4300453 : scalepol(GEN p, GEN R, long bit)
1131 4300453 : { return RgX_rescale(mygprec(p, bit), R); }
1132 :
1133 : /* return (conj(a)X-1)^n * p[ (X-a) / (conj(a)X-1) ] */
1134 : static GEN
1135 1407487 : conformal_basecase(GEN p, GEN a)
1136 : {
1137 : GEN z, r, ma, ca;
1138 1407487 : long i, n = degpol(p);
1139 : pari_sp av;
1140 :
1141 1407485 : if (n <= 0) return p;
1142 1407485 : ma = gneg(a); ca = conj_i(a);
1143 1407487 : av = avma;
1144 1407487 : z = deg1pol_shallow(ca, gen_m1, 0);
1145 1407487 : r = scalarpol_shallow(gel(p,2+n), 0);
1146 1407486 : for (i=n-1; ; i--)
1147 : {
1148 3652440 : r = RgX_addmulXn_shallow(r, gmul(ma,r), 1); /* r *= (X - a) */
1149 3652412 : r = gadd(r, gmul(z, gel(p,2+i)));
1150 3652417 : if (i == 0) return gc_upto(av, r);
1151 2244945 : z = RgX_addmulXn_shallow(gmul(z,ca), gneg(z), 1); /* z *= conj(a)X - 1 */
1152 2244955 : if (gc_needed(av,2))
1153 : {
1154 0 : if(DEBUGMEM>1) pari_warn(warnmem,"conformal_pol (%ld/%ld)",n-i, n);
1155 0 : (void)gc_all(av,2, &r,&z);
1156 : }
1157 : }
1158 : }
1159 : static GEN
1160 1407606 : conformal_pol(GEN p, GEN a)
1161 : {
1162 1407606 : pari_sp av = avma;
1163 1407606 : long d, nR, n = degpol(p), v;
1164 : GEN Q, R, S, T;
1165 1407606 : if (n < 35) return conformal_basecase(p, a);
1166 119 : d = (n+1) >> 1; v = varn(p);
1167 119 : Q = RgX_shift_shallow(p, -d);
1168 119 : R = RgXn_red_shallow(p, d);
1169 119 : Q = conformal_pol(Q, a);
1170 119 : R = conformal_pol(R, a);
1171 119 : S = gpowgs(deg1pol_shallow(gen_1, gneg(a), v), d);
1172 119 : T = RgX_recip_i(S);
1173 119 : if (typ(a) == t_COMPLEX) T = gconj(T);
1174 119 : if (odd(d)) T = RgX_neg(T);
1175 : /* S = (X - a)^d, T = (conj(a) X - 1)^d */
1176 119 : nR = n - degpol(R) - d; /* >= 0 */
1177 119 : if (nR) T = RgX_mul(T, gpowgs(deg1pol_shallow(gconj(a), gen_m1, v), nR));
1178 119 : return gc_upto(av, RgX_add(RgX_mul(Q, S), RgX_mul(R, T)));
1179 : }
1180 :
1181 : static const double UNDEF = -100000.;
1182 :
1183 : static double
1184 495257 : logradius(double *radii, GEN p, long k, double aux, double *delta)
1185 : {
1186 495257 : long i, n = degpol(p);
1187 : double lrho, lrmin, lrmax;
1188 495258 : if (k > 1)
1189 : {
1190 283862 : i = k-1; while (i>0 && radii[i] == UNDEF) i--;
1191 208007 : lrmin = logpre_modulus(p,k,aux, radii[i], radii[k]);
1192 : }
1193 : else /* k=1 */
1194 287251 : lrmin = logmin_modulus(p,aux);
1195 495256 : radii[k] = lrmin;
1196 :
1197 495256 : if (k+1<n)
1198 : {
1199 592756 : i = k+2; while (i<=n && radii[i] == UNDEF) i++;
1200 400809 : lrmax = logpre_modulus(p,k+1,aux, radii[k+1], radii[i]);
1201 : }
1202 : else /* k+1=n */
1203 94447 : lrmax = logmax_modulus(p,aux);
1204 495255 : radii[k+1] = lrmax;
1205 :
1206 495255 : lrho = radii[k];
1207 827251 : for (i=k-1; i>=1; i--)
1208 : {
1209 331996 : if (radii[i] == UNDEF || radii[i] > lrho)
1210 243730 : radii[i] = lrho;
1211 : else
1212 88266 : lrho = radii[i];
1213 : }
1214 495255 : lrho = radii[k+1];
1215 1643200 : for (i=k+1; i<=n; i++)
1216 : {
1217 1147945 : if (radii[i] == UNDEF || radii[i] < lrho)
1218 569485 : radii[i] = lrho;
1219 : else
1220 578460 : lrho = radii[i];
1221 : }
1222 495255 : *delta = (lrmax - lrmin) / 2;
1223 495255 : if (*delta > 1.) *delta = 1.;
1224 495255 : return (lrmin + lrmax) / 2;
1225 : }
1226 :
1227 : static void
1228 495255 : update_radius(long n, double *radii, double lrho, double *par, double *par2)
1229 : {
1230 495255 : double t, param = 0., param2 = 0.;
1231 : long i;
1232 2470360 : for (i=1; i<=n; i++)
1233 : {
1234 1975143 : radii[i] -= lrho;
1235 1975143 : t = fabs(rtodbl( invr(subsr(1, dblexp(radii[i]))) ));
1236 1975105 : param += t; if (t > 1.) param2 += log2(t);
1237 : }
1238 495217 : *par = param; *par2 = param2;
1239 495217 : }
1240 :
1241 : /* apply the conformal mapping then split from U */
1242 : static void
1243 469126 : conformal_mapping(double *radii, GEN ctr, GEN p, long k, long bit,
1244 : double aux, GEN *F,GEN *G)
1245 : {
1246 469126 : long bit2, n = degpol(p), i;
1247 469126 : pari_sp ltop = avma, av;
1248 : GEN q, FF, GG, a, R;
1249 : double lrho, delta, param, param2;
1250 : /* n * (2.*log2(2.732)+log2(1.5)) + 1 */
1251 469126 : bit2 = bit + (long)(n*3.4848775) + 1;
1252 469126 : a = sqrtr_abs( utor(3, precdbl(MEDDEFAULTPREC)) );
1253 469125 : a = divrs(a, -6);
1254 469123 : a = gmul(mygprec(a,bit2), mygprec(ctr,bit2)); /* a = -ctr/2sqrt(3) */
1255 :
1256 469120 : av = avma;
1257 469120 : q = conformal_pol(mygprec(p,bit2), a);
1258 2295387 : for (i=1; i<=n; i++)
1259 1826263 : if (radii[i] != UNDEF) /* update array radii */
1260 : {
1261 1545603 : pari_sp av2 = avma;
1262 1545603 : GEN t, r = dblexp(radii[i]), r2 = sqrr(r);
1263 : /* 2(r^2 - 1) / (r^2 - 3(r-1)) */
1264 1545571 : t = divrr(shiftr((subrs(r2,1)),1), subrr(r2, mulur(3,subrs(r,1))));
1265 1545596 : radii[i] = mydbllogr(addsr(1,t)) / 2;
1266 1545587 : set_avma(av2);
1267 : }
1268 469124 : lrho = logradius(radii, q,k,aux/10., &delta);
1269 469122 : update_radius(n, radii, lrho, ¶m, ¶m2);
1270 :
1271 469121 : bit2 += (long)(n * fabs(lrho)/M_LN2 + 1.);
1272 469121 : R = mygprec(dblexp(-lrho), bit2);
1273 469123 : q = scalepol(q,R,bit2);
1274 469126 : (void)gc_all(av,2, &q,&R);
1275 :
1276 469126 : optimize_split(q,k,delta,bit2,&FF,&GG,param,param2);
1277 469122 : bit2 += n; R = invr(R);
1278 469124 : FF = scalepol(FF,R,bit2);
1279 469125 : GG = scalepol(GG,R,bit2);
1280 :
1281 469123 : a = mygprec(a,bit2);
1282 469125 : FF = conformal_pol(FF,a);
1283 469124 : GG = conformal_pol(GG,a);
1284 :
1285 469125 : a = invr(subsr(1, gnorm(a)));
1286 469121 : FF = RgX_Rg_mul(FF, powru(a,k));
1287 469126 : GG = RgX_Rg_mul(GG, powru(a,n-k));
1288 :
1289 469124 : *F = mygprec(FF,bit+n);
1290 469126 : *G = mygprec(GG,bit+n); (void)gc_all(ltop,2, F,G);
1291 469126 : }
1292 :
1293 : /* split p, this time without scaling. returns in F and G two polynomials
1294 : * such that |p-FG|< 2^(-bit)|p| */
1295 : static void
1296 495257 : split_2(GEN p, long bit, GEN ctr, double thickness, GEN *F, GEN *G)
1297 : {
1298 : GEN q, FF, GG, R;
1299 : double aux, delta, param, param2;
1300 495257 : long n = degpol(p), i, j, k, bit2;
1301 : double lrmin, lrmax, lrho, *radii;
1302 :
1303 495257 : radii = (double*) stack_malloc_align((n+1) * sizeof(double), sizeof(double));
1304 :
1305 1479947 : for (i=2; i<n; i++) radii[i] = UNDEF;
1306 495257 : aux = thickness/(double)(4 * n);
1307 495257 : lrmin = logmin_modulus(p, aux);
1308 495255 : lrmax = logmax_modulus(p, aux);
1309 495251 : radii[1] = lrmin;
1310 495251 : radii[n] = lrmax;
1311 495251 : i = 1; j = n;
1312 495251 : lrho = (lrmin + lrmax) / 2;
1313 495251 : k = dual_modulus(p, lrho, aux, 1);
1314 495258 : if (5*k < n || (n < 2*k && 5*k < 4*n))
1315 78289 : { lrmax = lrho; j=k+1; radii[j] = lrho; }
1316 : else
1317 416969 : { lrmin = lrho; i=k; radii[i] = lrho; }
1318 1015201 : while (j > i+1)
1319 : {
1320 519945 : if (i+j == n+1)
1321 372682 : lrho = (lrmin + lrmax) / 2;
1322 : else
1323 : {
1324 147263 : double kappa = 2. - log(1. + minss(i,n-j)) / log(1. + minss(j,n-i));
1325 147263 : if (i+j < n+1) lrho = lrmax * kappa + lrmin;
1326 117353 : else lrho = lrmin * kappa + lrmax;
1327 147263 : lrho /= 1+kappa;
1328 : }
1329 519945 : aux = (lrmax - lrmin) / (4*(j-i));
1330 519945 : k = dual_modulus(p, lrho, aux, minss(i,n+1-j));
1331 519943 : if (k-i < j-k-1 || (k-i == j-k-1 && 2*k > n))
1332 388291 : { lrmax = lrho; j=k+1; radii[j] = lrho - aux; }
1333 : else
1334 131652 : { lrmin = lrho; i=k; radii[i] = lrho + aux; }
1335 : }
1336 495256 : aux = lrmax - lrmin;
1337 :
1338 495256 : if (ctr)
1339 : {
1340 469124 : lrho = (lrmax + lrmin) / 2;
1341 2295421 : for (i=1; i<=n; i++)
1342 1826297 : if (radii[i] != UNDEF) radii[i] -= lrho;
1343 :
1344 469124 : bit2 = bit + (long)(n * fabs(lrho)/M_LN2 + 1.);
1345 469124 : R = mygprec(dblexp(-lrho), bit2);
1346 469122 : q = scalepol(p,R,bit2);
1347 469126 : conformal_mapping(radii, ctr, q, k, bit2, aux, &FF, &GG);
1348 : }
1349 : else
1350 : {
1351 26132 : lrho = logradius(radii, p, k, aux/10., &delta);
1352 26133 : update_radius(n, radii, lrho, ¶m, ¶m2);
1353 :
1354 26132 : bit2 = bit + (long)(n * fabs(lrho)/M_LN2 + 1.);
1355 26132 : R = mygprec(dblexp(-lrho), bit2);
1356 26133 : q = scalepol(p,R,bit2);
1357 26133 : optimize_split(q, k, delta, bit2, &FF, &GG, param, param2);
1358 : }
1359 495259 : bit += n;
1360 495259 : bit2 += n; R = invr(mygprec(R,bit2));
1361 495255 : *F = mygprec(scalepol(FF,R,bit2), bit);
1362 495259 : *G = mygprec(scalepol(GG,R,bit2), bit);
1363 495258 : }
1364 :
1365 : /* procedure corresponding to steps 5,6,.. page 44 in RR n. 1852 */
1366 : /* put in F and G two polynomial such that |p-FG|<2^(-bit)|p|
1367 : * where the maximum modulus of the roots of p is <=1.
1368 : * Assume sum of roots is 0. */
1369 : static void
1370 469124 : split_1(GEN p, long bit, GEN *F, GEN *G)
1371 : {
1372 469124 : long i, imax, n = degpol(p), polreal = isreal(p), ep = gexpo(p), bit2 = bit+n;
1373 : GEN ctr, q, qq, FF, GG, v, gr, r, newq;
1374 : double lrmin, lrmax, lthick;
1375 469124 : const double LOG3 = 1.098613;
1376 :
1377 469124 : lrmax = logmax_modulus(p, 0.01);
1378 469124 : gr = mygprec(dblexp(-lrmax), bit2);
1379 469122 : q = scalepol(p,gr,bit2);
1380 :
1381 469125 : bit2 = bit + gexpo(q) - ep + (long)((double)n*2.*log2(3.)+1);
1382 469123 : v = cgetg(5,t_VEC);
1383 469123 : gel(v,1) = gen_2;
1384 469123 : gel(v,2) = gen_m2;
1385 469123 : gel(v,3) = mkcomplex(gen_0, gel(v,1));
1386 469123 : gel(v,4) = mkcomplex(gen_0, gel(v,2));
1387 469123 : q = mygprec(q,bit2); lthick = 0;
1388 469125 : newq = ctr = NULL; /* -Wall */
1389 469125 : imax = polreal? 3: 4;
1390 842092 : for (i=1; i<=imax; i++)
1391 : {
1392 835580 : qq = RgX_Rg_translate(q, gel(v,i));
1393 835586 : lrmin = logmin_modulus(qq,0.05);
1394 835589 : if (LOG3 > lrmin + lthick)
1395 : {
1396 823465 : double lquo = logmax_modulus(qq,0.05) - lrmin;
1397 823457 : if (lquo > lthick) { lthick = lquo; newq = qq; ctr = gel(v,i); }
1398 : }
1399 835581 : if (lthick > M_LN2) break;
1400 424323 : if (polreal && i==2 && lthick > LOG3 - M_LN2) break;
1401 : }
1402 469126 : bit2 = bit + gexpo(newq) - ep + (long)(n*LOG3/M_LN2 + 1);
1403 469125 : split_2(newq, bit2, ctr, lthick, &FF, &GG);
1404 469125 : r = gneg(mygprec(ctr,bit2));
1405 469124 : FF = RgX_Rg_translate(FF,r);
1406 469126 : GG = RgX_Rg_translate(GG,r);
1407 :
1408 469126 : gr = invr(gr); bit2 = bit - ep + gexpo(FF)+gexpo(GG);
1409 469125 : *F = scalepol(FF,gr,bit2);
1410 469126 : *G = scalepol(GG,gr,bit2);
1411 469125 : }
1412 :
1413 : /* put in F and G two polynomials such that |P-FG|<2^(-bit)|P|,
1414 : where the maximum modulus of the roots of p is < 0.5 */
1415 : static int
1416 469494 : split_0_2(GEN p, long bit, GEN *F, GEN *G)
1417 : {
1418 : GEN q, b;
1419 469494 : long n = degpol(p), k, bit2, eq;
1420 469495 : double aux0 = dbllog2(gel(p,n+2)); /* != -oo */
1421 469495 : double aux1 = dbllog2(gel(p,n+1)), aux;
1422 :
1423 469497 : if (aux1 == -pariINFINITY) /* p1 = 0 */
1424 9911 : aux = 0;
1425 : else
1426 : {
1427 459586 : aux = aux1 - aux0; /* log2(p1/p0) */
1428 : /* beware double overflow */
1429 459586 : if (aux >= 0 && (aux > 1e4 || exp2(aux) > 2.5*n)) return 0;
1430 459586 : aux = (aux < -300)? 0.: n*log2(1 + exp2(aux)/(double)n);
1431 : }
1432 469497 : bit2 = bit+1 + (long)(log2((double)n) + aux);
1433 469497 : q = mygprec(p,bit2);
1434 469498 : if (aux1 == -pariINFINITY) b = NULL;
1435 : else
1436 : {
1437 459587 : b = gdivgs(gdiv(gel(q,n+1),gel(q,n+2)),-n);
1438 459585 : q = RgX_Rg_translate(q,b);
1439 : }
1440 469498 : gel(q,n+1) = gen_0; eq = gexpo(q);
1441 469497 : k = 0;
1442 470140 : while (k <= n/2 && (- gexpo(gel(q,k+2)) > bit2 + 2*(n-k) + eq
1443 469971 : || gequal0(gel(q,k+2)))) k++;
1444 469496 : if (k > 0)
1445 : {
1446 372 : if (k > n/2) k = n/2;
1447 372 : bit2 += k<<1;
1448 372 : *F = pol_xn(k, 0);
1449 372 : *G = RgX_shift_shallow(q, -k);
1450 : }
1451 : else
1452 : {
1453 469124 : split_1(q,bit2,F,G);
1454 469125 : bit2 = bit + gexpo(*F) + gexpo(*G) - gexpo(p) + (long)aux+1;
1455 469125 : *F = mygprec(*F,bit2);
1456 : }
1457 469498 : *G = mygprec(*G,bit2);
1458 469498 : if (b)
1459 : {
1460 459587 : GEN mb = mygprec(gneg(b), bit2);
1461 459587 : *F = RgX_Rg_translate(*F, mb);
1462 459586 : *G = RgX_Rg_translate(*G, mb);
1463 : }
1464 469498 : return 1;
1465 : }
1466 :
1467 : /* put in F and G two polynomials such that |P-FG|<2^(-bit)|P|.
1468 : * Assume max_modulus(p) < 2 */
1469 : static void
1470 469493 : split_0_1(GEN p, long bit, GEN *F, GEN *G)
1471 : {
1472 : GEN FF, GG;
1473 : long n, bit2, normp;
1474 :
1475 469493 : if (split_0_2(p,bit,F,G)) return;
1476 :
1477 0 : normp = gexpo(p);
1478 0 : scalepol2n(p,2); /* p := 4^(-n) p(4*x) */
1479 0 : n = degpol(p); bit2 = bit + 2*n + gexpo(p) - normp;
1480 0 : split_1(mygprec(p,bit2), bit2,&FF,&GG);
1481 0 : scalepol2n(FF,-2);
1482 0 : scalepol2n(GG,-2); bit2 = bit + gexpo(FF) + gexpo(GG) - normp;
1483 0 : *F = mygprec(FF,bit2);
1484 0 : *G = mygprec(GG,bit2);
1485 : }
1486 :
1487 : /* put in F and G two polynomials such that |P-FG|<2^(-bit)|P| */
1488 : static void
1489 495629 : split_0(GEN p, long bit, GEN *F, GEN *G)
1490 : {
1491 495629 : const double LOG1_9 = 0.6418539;
1492 495629 : long n = degpol(p), k = 0;
1493 : GEN q;
1494 :
1495 495629 : while (gexpo(gel(p,k+2)) < -bit && k <= n/2) k++;
1496 495629 : if (k > 0)
1497 : {
1498 0 : if (k > n/2) k = n/2;
1499 0 : *F = pol_xn(k, 0);
1500 0 : *G = RgX_shift_shallow(p, -k);
1501 : }
1502 : else
1503 : {
1504 495629 : double lr = logmax_modulus(p, 0.05);
1505 495630 : if (lr < LOG1_9) split_0_1(p, bit, F, G);
1506 : else
1507 : {
1508 437319 : q = RgX_recip_i(p);
1509 437319 : lr = logmax_modulus(q,0.05);
1510 437316 : if (lr < LOG1_9)
1511 : {
1512 411183 : split_0_1(q, bit, F, G);
1513 411187 : *F = RgX_recip_i(*F);
1514 411185 : *G = RgX_recip_i(*G);
1515 : }
1516 : else
1517 26133 : split_2(p,bit,NULL, 1.2837,F,G);
1518 : }
1519 : }
1520 495629 : }
1521 :
1522 : /********************************************************************/
1523 : /** **/
1524 : /** ERROR ESTIMATE FOR THE ROOTS **/
1525 : /** **/
1526 : /********************************************************************/
1527 :
1528 : static GEN
1529 1919216 : root_error(long n, long k, GEN roots_pol, long err, GEN shatzle)
1530 : {
1531 1919216 : GEN rho, d, eps, epsbis, eps2, aux, rap = NULL;
1532 : long i, j;
1533 :
1534 1919216 : d = cgetg(n+1,t_VEC);
1535 12256394 : for (i=1; i<=n; i++)
1536 : {
1537 10337306 : if (i!=k)
1538 : {
1539 8418184 : aux = gsub(gel(roots_pol,i), gel(roots_pol,k));
1540 8417644 : gel(d,i) = gabs(mygprec(aux,31), DEFAULTPREC);
1541 : }
1542 : }
1543 1919088 : rho = gabs(mygprec(gel(roots_pol,k),31), DEFAULTPREC);
1544 1919222 : if (expo(rho) < 0) rho = real_1(DEFAULTPREC);
1545 1919222 : eps = mulrr(rho, shatzle);
1546 1919114 : aux = shiftr(powru(rho,n), err);
1547 :
1548 5825739 : for (j=1; j<=2 || (j<=5 && cmprr(rap, dbltor(1.2)) > 0); j++)
1549 : {
1550 3906680 : GEN prod = NULL; /* 1. */
1551 3906680 : long m = n;
1552 3906680 : epsbis = mulrr(eps, dbltor(1.25));
1553 26846393 : for (i=1; i<=n; i++)
1554 : {
1555 22939554 : if (i != k && cmprr(gel(d,i),epsbis) > 0)
1556 : {
1557 18990261 : GEN dif = subrr(gel(d,i),eps);
1558 18988389 : prod = prod? mulrr(prod, dif): dif;
1559 18989449 : m--;
1560 : }
1561 : }
1562 3906839 : eps2 = prod? divrr(aux, prod): aux;
1563 3906726 : if (m > 1) eps2 = sqrtnr(shiftr(eps2, 2*m-2), m);
1564 3906726 : rap = divrr(eps,eps2); eps = eps2;
1565 : }
1566 1919015 : return eps;
1567 : }
1568 :
1569 : /* round a complex or real number x to an absolute value of 2^(-bit) */
1570 : static GEN
1571 4355847 : mygprec_absolute(GEN x, long bit)
1572 : {
1573 : long e;
1574 : GEN y;
1575 :
1576 4355847 : switch(typ(x))
1577 : {
1578 2985238 : case t_REAL:
1579 2985238 : e = expo(x) + bit;
1580 2985238 : return (e <= 0 || !signe(x))? real_0_bit(-bit): rtor(x, nbits2prec(e));
1581 1235706 : case t_COMPLEX:
1582 1235706 : if (gexpo(gel(x,2)) < -bit) return mygprec_absolute(gel(x,1),bit);
1583 1201031 : y = cgetg(3,t_COMPLEX);
1584 1201038 : gel(y,1) = mygprec_absolute(gel(x,1),bit);
1585 1201059 : gel(y,2) = mygprec_absolute(gel(x,2),bit);
1586 1201070 : return y;
1587 134903 : default: return x;
1588 : }
1589 : }
1590 :
1591 : static long
1592 538493 : a_posteriori_errors(GEN p, GEN roots_pol, long err)
1593 : {
1594 538493 : long i, n = degpol(p), e_max = -(long)EXPOBITS;
1595 : GEN sigma, shatzle;
1596 :
1597 538492 : err += (long)log2((double)n) + 1;
1598 538492 : if (err > -2) return 0;
1599 538492 : sigma = real2n(-err, LOWDEFAULTPREC);
1600 : /* 2 / ((s - 1)^(1/n) - 1) */
1601 538493 : shatzle = divur(2, subrs(sqrtnr(subrs(sigma,1),n), 1));
1602 2457690 : for (i=1; i<=n; i++)
1603 : {
1604 1919198 : pari_sp av = avma;
1605 1919198 : GEN x = root_error(n,i,roots_pol,err,shatzle);
1606 1919012 : long e = gexpo(x);
1607 1919041 : set_avma(av); if (e > e_max) e_max = e;
1608 1919115 : gel(roots_pol,i) = mygprec_absolute(gel(roots_pol,i), -e);
1609 : }
1610 538492 : return e_max;
1611 : }
1612 :
1613 : /********************************************************************/
1614 : /** **/
1615 : /** MAIN **/
1616 : /** **/
1617 : /********************************************************************/
1618 : static GEN
1619 1618769 : append_clone(GEN r, GEN a) { a = gclone(a); vectrunc_append(r, a); return a; }
1620 :
1621 : /* put roots in placeholder roots_pol so that |P - L_1...L_n| < 2^(-bit)|P|
1622 : * returns prod (x-roots_pol[i]) */
1623 : static GEN
1624 1529745 : split_complete(GEN p, long bit, GEN roots_pol)
1625 : {
1626 1529745 : long n = degpol(p);
1627 : pari_sp ltop;
1628 : GEN p1, F, G, a, b, m1, m2;
1629 :
1630 1529742 : if (n == 1)
1631 : {
1632 449449 : a = gneg_i(gdiv(gel(p,2), gel(p,3)));
1633 449455 : (void)append_clone(roots_pol,a); return p;
1634 : }
1635 1080293 : ltop = avma;
1636 1080293 : if (n == 2)
1637 : {
1638 584664 : F = gsub(gsqr(gel(p,3)), gmul2n(gmul(gel(p,2),gel(p,4)), 2));
1639 584656 : F = gsqrt(F, nbits2prec(bit));
1640 584664 : p1 = ginv(gmul2n(gel(p,4),1));
1641 584665 : a = gneg_i(gmul(gadd(F,gel(p,3)), p1));
1642 584665 : b = gmul(gsub(F,gel(p,3)), p1);
1643 584661 : a = append_clone(roots_pol,a);
1644 584666 : b = append_clone(roots_pol,b); set_avma(ltop);
1645 584666 : a = mygprec(a, 3*bit);
1646 584667 : b = mygprec(b, 3*bit);
1647 584665 : return gmul(gel(p,4), mkpoln(3, gen_1, gneg(gadd(a,b)), gmul(a,b)));
1648 : }
1649 495629 : split_0(p,bit,&F,&G);
1650 495629 : m1 = split_complete(F,bit,roots_pol);
1651 495629 : m2 = split_complete(G,bit,roots_pol);
1652 495627 : return gc_upto(ltop, gmul(m1,m2));
1653 : }
1654 :
1655 : static GEN
1656 6997488 : quicktofp(GEN x)
1657 : {
1658 6997488 : const long prec = DEFAULTPREC;
1659 6997488 : switch(typ(x))
1660 : {
1661 6975986 : case t_INT: return itor(x, prec);
1662 9064 : case t_REAL: return rtor(x, prec);
1663 0 : case t_FRAC: return fractor(x, prec);
1664 12437 : case t_COMPLEX: {
1665 12437 : GEN a = gel(x,1), b = gel(x,2);
1666 : /* avoid problem with 0, e.g. x = 0 + I*1e-100. We don't want |x| = 0. */
1667 12437 : if (isintzero(a)) return cxcompotor(b, prec);
1668 12395 : if (isintzero(b)) return cxcompotor(a, prec);
1669 12395 : a = cxcompotor(a, prec);
1670 12395 : b = cxcompotor(b, prec); return sqrtr(addrr(sqrr(a), sqrr(b)));
1671 : }
1672 1 : default: pari_err_TYPE("quicktofp",x);
1673 : return NULL;/*LCOV_EXCL_LINE*/
1674 : }
1675 :
1676 : }
1677 :
1678 : /* bound log_2 |largest root of p| (Fujiwara's bound) */
1679 : double
1680 2276602 : fujiwara_bound(GEN p)
1681 : {
1682 2276602 : pari_sp av = avma;
1683 2276602 : long i, n = degpol(p);
1684 : GEN cc;
1685 : double loglc, Lmax;
1686 :
1687 2276603 : if (n <= 0) pari_err_CONSTPOL("fujiwara_bound");
1688 2276603 : loglc = mydbllog2r( quicktofp(gel(p,n+2)) ); /* log_2 |lc(p)| */
1689 2276566 : cc = gel(p, 2);
1690 2276566 : if (gequal0(cc))
1691 784537 : Lmax = -pariINFINITY-1;
1692 : else
1693 1492047 : Lmax = (mydbllog2r(quicktofp(cc)) - loglc - 1) / n;
1694 7423433 : for (i = 1; i < n; i++)
1695 : {
1696 5146868 : GEN y = gel(p,i+2);
1697 : double L;
1698 5146868 : if (gequal0(y)) continue;
1699 3228963 : L = (mydbllog2r(quicktofp(y)) - loglc) / (n-i);
1700 3228970 : if (L > Lmax) Lmax = L;
1701 : }
1702 2276565 : return gc_double(av, Lmax+1);
1703 : }
1704 :
1705 : /* Fujiwara's bound, real roots. Based on the following remark: if
1706 : * p = x^n + sum a_i x^i and q = x^n + sum min(a_i,0)x^i
1707 : * then for all x >= 0, p(x) >= q(x). Thus any bound for the (positive) roots
1708 : * of q is a bound for the positive roots of p. */
1709 : double
1710 1408132 : fujiwara_bound_real(GEN p, long sign)
1711 : {
1712 1408132 : pari_sp av = avma;
1713 : GEN x;
1714 1408132 : long n = degpol(p), i, signodd, signeven;
1715 1408129 : if (n <= 0) pari_err_CONSTPOL("fujiwara_bound");
1716 1408129 : x = shallowcopy(p);
1717 1408129 : if (gsigne(gel(x, n+2)) > 0)
1718 1408108 : { signeven = 1; signodd = sign; }
1719 : else
1720 21 : { signeven = -1; signodd = -sign; }
1721 5785257 : for (i = 0; i < n; i++)
1722 : {
1723 4377125 : if ((n - i) % 2)
1724 2492940 : { if (gsigne(gel(x, i+2)) == signodd ) gel(x, i+2) = gen_0; }
1725 : else
1726 1884185 : { if (gsigne(gel(x, i+2)) == signeven) gel(x, i+2) = gen_0; }
1727 : }
1728 1408132 : return gc_double(av, fujiwara_bound(x));
1729 : }
1730 :
1731 : static GEN
1732 2185045 : mygprecrc_special(GEN x, long prec, long e)
1733 : {
1734 : GEN y;
1735 2185045 : switch(typ(x))
1736 : {
1737 37383 : case t_REAL:
1738 37383 : if (!signe(x)) return real_0_bit(minss(e, expo(x)));
1739 36235 : return (prec > realprec(x))? rtor(x, prec): x;
1740 13885 : case t_COMPLEX:
1741 13885 : y = cgetg(3,t_COMPLEX);
1742 13885 : gel(y,1) = mygprecrc_special(gel(x,1),prec,e);
1743 13885 : gel(y,2) = mygprecrc_special(gel(x,2),prec,e);
1744 13885 : return y;
1745 2133777 : default: return x;
1746 : }
1747 : }
1748 :
1749 : /* like mygprec but keep at least the same precision as before */
1750 : static GEN
1751 538495 : mygprec_special(GEN x, long bit)
1752 : {
1753 538495 : long e = gexpo(x) - bit, prec = nbits2prec(bit);
1754 538491 : switch(typ(x))
1755 : {
1756 2695766 : case t_POL: pari_APPLY_pol_normalized(mygprecrc_special(gel(x,i),prec,e));
1757 0 : default: return mygprecrc_special(x,prec,e);
1758 : }
1759 : }
1760 :
1761 : static GEN
1762 398949 : fix_roots1(GEN R)
1763 : {
1764 398949 : long i, l = lg(R);
1765 398949 : GEN v = cgetg(l, t_VEC);
1766 1768305 : for (i=1; i < l; i++) { GEN r = gel(R,i); gel(v,i) = gcopy(r); gunclone(r); }
1767 398949 : return v;
1768 : }
1769 : static GEN
1770 538490 : fix_roots(GEN R, long h, long bit)
1771 : {
1772 : long i, j, c, n, prec;
1773 : GEN v, Z, gh;
1774 :
1775 538490 : if (h == 1) return fix_roots1(R);
1776 139541 : prec = nbits2prec(bit); Z = grootsof1(h, prec); gh = utoipos(h);
1777 139544 : n = lg(R)-1; v = cgetg(h*n + 1, t_VEC);
1778 388974 : for (c = i = 1; i <= n; i++)
1779 : {
1780 249428 : GEN s, r = gel(R,i);
1781 249428 : s = (h == 2)? gsqrt(r, prec): gsqrtn(r, gh, NULL, prec);
1782 799272 : for (j = 1; j <= h; j++) gel(v, c++) = gmul(s, gel(Z,j));
1783 249404 : gunclone(r);
1784 : }
1785 139546 : return v;
1786 : }
1787 :
1788 : static GEN
1789 537385 : all_roots(GEN p, long bit)
1790 : {
1791 537385 : long bit2, i, e, h, n = degpol(p), elc = gexpo(leading_coeff(p));
1792 537383 : GEN q, R, m, pd = RgX_deflate_max(p, &h);
1793 537388 : double fb = fujiwara_bound(pd);
1794 : pari_sp av;
1795 :
1796 537387 : if (fb < 0) fb = 0;
1797 537387 : bit2 = bit + maxss(gexpo(p), 0) + (long)ceil(log2(n / h) + 2 * fb);
1798 538489 : for (av = avma, i = 1, e = 0;; i++, set_avma(av))
1799 : {
1800 538489 : R = vectrunc_init(n+1);
1801 538489 : bit2 += e + (n << i);
1802 538489 : q = RgX_gtofp_bit(mygprec(pd,bit2), bit2);
1803 538491 : q[1] = evalsigne(1)|evalvarn(0);
1804 538491 : m = split_complete(q, bit2, R);
1805 538490 : R = fix_roots(R, h, bit2);
1806 538495 : q = mygprec_special(pd,bit2);
1807 538492 : q[1] = evalsigne(1)|evalvarn(0);
1808 538492 : e = gexpo(RgX_sub(q, m)) - elc + (long)log2((double)n) + 1;
1809 538492 : if (e < 0)
1810 : {
1811 538492 : if (e < -2*bit2) e = -2*bit2; /* avoid e = -oo */
1812 538492 : e = bit + a_posteriori_errors(p, R, e);
1813 538492 : if (e < 0) return R;
1814 : }
1815 1100 : if (DEBUGLEVEL)
1816 0 : err_printf("all_roots: restarting, i = %ld, e = %ld\n", i,e);
1817 : }
1818 : }
1819 :
1820 : INLINE int
1821 934563 : isexactscalar(GEN x) { long tx = typ(x); return is_rational_t(tx); }
1822 :
1823 : static int
1824 240229 : isexactpol(GEN p)
1825 : {
1826 240229 : long i,n = degpol(p);
1827 1166184 : for (i=0; i<=n; i++)
1828 934563 : if (!isexactscalar(gel(p,i+2))) return 0;
1829 231621 : return 1;
1830 : }
1831 :
1832 : /* p(0) != 0 [for efficiency] */
1833 : static GEN
1834 231621 : solve_exact_pol(GEN p, long bit)
1835 : {
1836 231621 : long i, j, k, m, n = degpol(p), iroots = 0;
1837 231621 : GEN ex, factors, v = zerovec(n);
1838 :
1839 231621 : factors = ZX_squff(Q_primpart(p), &ex);
1840 463242 : for (i=1; i<lg(factors); i++)
1841 : {
1842 231621 : GEN roots_fact = all_roots(gel(factors,i), bit);
1843 231621 : n = degpol(gel(factors,i));
1844 231621 : m = ex[i];
1845 925311 : for (j=1; j<=n; j++)
1846 1387380 : for (k=1; k<=m; k++) v[++iroots] = roots_fact[j];
1847 : }
1848 231621 : return v;
1849 : }
1850 :
1851 : /* return the roots of p with absolute error bit */
1852 : static GEN
1853 240229 : roots_com(GEN q, long bit)
1854 : {
1855 : GEN L, p;
1856 240229 : long v = RgX_valrem_inexact(q, &p);
1857 240229 : int ex = isexactpol(p);
1858 240229 : if (!ex) p = RgX_normalize1(p);
1859 240229 : if (lg(p) == 3)
1860 0 : L = cgetg(1,t_VEC); /* constant polynomial */
1861 : else
1862 240229 : L = ex? solve_exact_pol(p,bit): all_roots(p,bit);
1863 240229 : if (v)
1864 : {
1865 4026 : GEN M, z, t = gel(q,2);
1866 : long i, x, y, l, n;
1867 :
1868 4026 : if (isrationalzero(t)) x = -bit;
1869 : else
1870 : {
1871 7 : n = gexpo(t);
1872 7 : x = n / v; l = degpol(q);
1873 35 : for (i = v; i <= l; i++)
1874 : {
1875 28 : t = gel(q,i+2);
1876 28 : if (isrationalzero(t)) continue;
1877 28 : y = (n - gexpo(t)) / i;
1878 28 : if (y < x) x = y;
1879 : }
1880 : }
1881 4026 : z = real_0_bit(x); l = v + lg(L);
1882 4026 : M = cgetg(l, t_VEC); L -= v;
1883 8115 : for (i = 1; i <= v; i++) gel(M,i) = z;
1884 12351 : for ( ; i < l; i++) gel(M,i) = gel(L,i);
1885 4026 : L = M;
1886 : }
1887 240229 : return L;
1888 : }
1889 :
1890 : static GEN
1891 1219382 : tocomplex(GEN x, long l, long bit)
1892 : {
1893 : GEN y;
1894 1219382 : if (typ(x) == t_COMPLEX)
1895 : {
1896 1199136 : if (signe(gel(x,1))) return mygprecrc(x, l, -bit);
1897 142554 : x = gel(x,2);
1898 142554 : y = cgetg(3,t_COMPLEX);
1899 142557 : gel(y,1) = real_0_bit(-bit);
1900 142556 : gel(y,2) = mygprecrc(x, l, -bit);
1901 : }
1902 : else
1903 : {
1904 20246 : y = cgetg(3,t_COMPLEX);
1905 20247 : gel(y,1) = mygprecrc(x, l, -bit);
1906 20247 : gel(y,2) = real_0_bit(-bit);
1907 : }
1908 162803 : return y;
1909 : }
1910 :
1911 : /* x,y are t_COMPLEX of t_REALs or t_REAL, compare wrt |Im x| - |Im y|,
1912 : * then Re x - Re y, up to 2^-e absolute error */
1913 : static int
1914 2249761 : cmp_complex_appr(void *E, GEN x, GEN y)
1915 : {
1916 2249761 : long e = (long)E;
1917 : GEN z, xi, yi, xr, yr;
1918 : long sz, sxi, syi;
1919 2249761 : if (typ(x) == t_COMPLEX) { xr = gel(x,1); xi = gel(x,2); sxi = signe(xi); }
1920 842337 : else { xr = x; xi = NULL; sxi = 0; }
1921 2249761 : if (typ(y) == t_COMPLEX) { yr = gel(y,1); yi = gel(y,2); syi = signe(yi); }
1922 564096 : else { yr = y; yi = NULL; syi = 0; }
1923 : /* Compare absolute values of imaginary parts */
1924 2249761 : if (!sxi)
1925 : {
1926 863070 : if (syi && expo(yi) >= e) return -1;
1927 : /* |Im x| ~ |Im y| ~ 0 */
1928 : }
1929 1386691 : else if (!syi)
1930 : {
1931 50634 : if (sxi && expo(xi) >= e) return 1;
1932 : /* |Im x| ~ |Im y| ~ 0 */
1933 : }
1934 : else
1935 : {
1936 1336057 : z = addrr_sign(xi, 1, yi, -1); sz = signe(z);
1937 1336017 : if (sz && expo(z) >= e) return (int)sz;
1938 : }
1939 : /* |Im x| ~ |Im y|, sort according to real parts */
1940 1347611 : z = subrr(xr, yr); sz = signe(z);
1941 1347641 : if (sz && expo(z) >= e) return (int)sz;
1942 : /* Re x ~ Re y. Place negative imaginary part before positive */
1943 594528 : return (int) (sxi - syi);
1944 : }
1945 :
1946 : static GEN
1947 537434 : clean_roots(GEN L, long l, long bit, long clean)
1948 : {
1949 537434 : long i, n = lg(L), ex = 5 - bit;
1950 537434 : GEN res = cgetg(n,t_COL);
1951 2456529 : for (i=1; i<n; i++)
1952 : {
1953 1919096 : GEN c = gel(L,i);
1954 1919096 : if (clean && isrealappr(c,ex))
1955 : {
1956 699717 : if (typ(c) == t_COMPLEX) c = gel(c,1);
1957 699717 : c = mygprecrc(c, l, -bit);
1958 : }
1959 : else
1960 1219380 : c = tocomplex(c, l, bit);
1961 1919095 : gel(res,i) = c;
1962 : }
1963 537433 : gen_sort_inplace(res, (void*)ex, &cmp_complex_appr, NULL);
1964 537433 : return res;
1965 : }
1966 :
1967 : /* the vector of roots of p, with absolute error 2^(- prec2nbits(l)) */
1968 : static GEN
1969 240257 : roots_aux(GEN p, long l, long clean)
1970 : {
1971 240257 : pari_sp av = avma;
1972 : long bit;
1973 : GEN L;
1974 :
1975 240257 : if (typ(p) != t_POL)
1976 : {
1977 21 : if (gequal0(p)) pari_err_ROOTS0("roots");
1978 14 : if (!isvalidcoeff(p)) pari_err_TYPE("roots",p);
1979 7 : return cgetg(1,t_COL); /* constant polynomial */
1980 : }
1981 240236 : if (!signe(p)) pari_err_ROOTS0("roots");
1982 240236 : checkvalidpol(p,"roots");
1983 240229 : if (lg(p) == 3) return cgetg(1,t_COL); /* constant polynomial */
1984 240229 : if (l < LOWDEFAULTPREC) l = LOWDEFAULTPREC;
1985 240229 : bit = prec2nbits(l);
1986 240229 : L = roots_com(p, bit);
1987 240229 : return gc_GEN(av, clean_roots(L, l, bit, clean));
1988 : }
1989 : GEN
1990 8382 : roots(GEN p, long l) { return roots_aux(p,l, 0); }
1991 : /* clean up roots. If root is real replace it by its real part */
1992 : GEN
1993 231875 : cleanroots(GEN p, long l) { return roots_aux(p,l, 1); }
1994 :
1995 : /* private variant of conjvec. Allow non rational coefficients, shallow
1996 : * function. */
1997 : GEN
1998 84 : polmod_to_embed(GEN x, long prec)
1999 : {
2000 84 : GEN v, T = gel(x,1), A = gel(x,2);
2001 : long i, l;
2002 84 : if (typ(A) != t_POL || varn(A) != varn(T))
2003 : {
2004 7 : checkvalidpol(T,"polmod_to_embed");
2005 7 : return const_col(degpol(T), A);
2006 : }
2007 77 : v = cleanroots(T,prec); l = lg(v);
2008 231 : for (i=1; i<l; i++) gel(v,i) = poleval(A,gel(v,i));
2009 77 : return v;
2010 : }
2011 :
2012 : GEN
2013 297203 : QX_complex_roots(GEN p, long l)
2014 : {
2015 297203 : pari_sp av = avma;
2016 : long bit, v;
2017 : GEN L;
2018 :
2019 297203 : if (!signe(p)) pari_err_ROOTS0("QX_complex_roots");
2020 297203 : if (lg(p) == 3) return cgetg(1,t_COL); /* constant polynomial */
2021 297203 : if (l < LOWDEFAULTPREC) l = LOWDEFAULTPREC;
2022 297203 : bit = prec2nbits(l);
2023 297203 : v = RgX_valrem(p, &p);
2024 297203 : L = lg(p) > 3? all_roots(Q_primpart(p), bit): cgetg(1,t_COL);
2025 297205 : if (v) L = shallowconcat(const_vec(v, real_0_bit(-bit)), L);
2026 297205 : return gc_GEN(av, clean_roots(L, l, bit, 1));
2027 : }
2028 :
2029 : /********************************************************************/
2030 : /** **/
2031 : /** REAL ROOTS OF INTEGER POLYNOMIAL **/
2032 : /** **/
2033 : /********************************************************************/
2034 :
2035 : /* Count sign changes in the coefficients of (x+1)^deg(P)*P(1/(x+1)), P
2036 : * has no rational root. The inversion is implicit (we take coefficients
2037 : * backwards). */
2038 : static long
2039 6000746 : X2XP1(GEN P, GEN *Premapped)
2040 : {
2041 6000746 : const pari_sp av = avma;
2042 6000746 : GEN v = shallowcopy(P);
2043 6000847 : long i, j, nb, s, dP = degpol(P), vlim = dP+2;
2044 :
2045 34829593 : for (j = 2; j < vlim; j++) gel(v, j+1) = addii(gel(v, j), gel(v, j+1));
2046 6000402 : s = -signe(gel(v, vlim));
2047 6000402 : vlim--; nb = 0;
2048 16703835 : for (i = 1; i < dP; i++)
2049 : {
2050 14174512 : long s2 = -signe(gel(v, 2));
2051 14174512 : int flag = (s2 == s);
2052 90601758 : for (j = 2; j < vlim; j++)
2053 : {
2054 76427179 : gel(v, j+1) = addii(gel(v, j), gel(v, j+1));
2055 76427246 : if (flag) flag = (s2 != signe(gel(v, j+1)));
2056 : }
2057 14174579 : if (s == signe(gel(v, vlim)))
2058 : {
2059 5034507 : if (++nb >= 2) return gc_long(av,2);
2060 3774361 : s = -s;
2061 : }
2062 : /* if flag is set there will be no further sign changes */
2063 12914433 : if (flag && (!Premapped || !nb)) return gc_long(av, nb);
2064 10702882 : vlim--;
2065 10702882 : if (gc_needed(av, 3))
2066 : {
2067 0 : if (DEBUGMEM>1) pari_warn(warnmem, "X2XP1, i = %ld/%ld", i, dP-1);
2068 0 : if (!Premapped) setlg(v, vlim + 2);
2069 0 : v = gc_GEN(av, v);
2070 : }
2071 : }
2072 2529323 : if (vlim >= 2 && s == signe(gel(v, vlim))) nb++;
2073 2529323 : if (Premapped && nb == 1) *Premapped = v; else set_avma(av);
2074 2528969 : return nb;
2075 : }
2076 :
2077 : static long
2078 0 : _intervalcmp(GEN x, GEN y)
2079 : {
2080 0 : if (typ(x) == t_VEC) x = gel(x, 1);
2081 0 : if (typ(y) == t_VEC) y = gel(y, 1);
2082 0 : return gcmp(x, y);
2083 : }
2084 :
2085 : static GEN
2086 11234358 : _gen_nored(void *E, GEN x) { (void)E; return x; }
2087 : static GEN
2088 24920293 : _mp_add(void *E, GEN x, GEN y) { (void)E; return mpadd(x, y); }
2089 : static GEN
2090 0 : _mp_sub(void *E, GEN x, GEN y) { (void)E; return mpsub(x, y); }
2091 : static GEN
2092 4429697 : _mp_mul(void *E, GEN x, GEN y) { (void)E; return mpmul(x, y); }
2093 : static GEN
2094 6348292 : _mp_sqr(void *E, GEN x) { (void)E; return mpsqr(x); }
2095 : static GEN
2096 14509099 : _gen_one(void *E) { (void)E; return gen_1; }
2097 : static GEN
2098 326030 : _gen_zero(void *E) { (void)E; return gen_0; }
2099 :
2100 : static struct bb_algebra mp_algebra = { _gen_nored, _mp_add, _mp_sub,
2101 : _mp_mul, _mp_sqr, _gen_one, _gen_zero };
2102 :
2103 : static GEN
2104 35041553 : _mp_cmul(void *E, GEN P, long a, GEN x) {(void)E; return mpmul(gel(P,a+2), x);}
2105 :
2106 : /* Split the polynom P in two parts, whose coeffs have constant sign:
2107 : * P(X) = X^D*Pp + Pm. Also compute the two parts of the derivative of P,
2108 : * Pprimem = Pm', Pprimep = X*Pp'+ D*Pp => P' = X^(D-1)*Pprimep + Pprimem;
2109 : * Pprimep[i] = (i+D) Pp[i]. Return D */
2110 : static long
2111 166976 : split_pols(GEN P, GEN *pPp, GEN *pPm, GEN *pPprimep, GEN *pPprimem)
2112 : {
2113 166976 : long i, D, dP = degpol(P), s0 = signe(gel(P,2));
2114 : GEN Pp, Pm, Pprimep, Pprimem;
2115 515539 : for(i=1; i <= dP; i++)
2116 515541 : if (signe(gel(P, i+2)) == -s0) break;
2117 166977 : D = i;
2118 166977 : Pm = cgetg(D + 2, t_POL);
2119 166980 : Pprimem = cgetg(D + 1, t_POL);
2120 166980 : Pp = cgetg(dP-D + 3, t_POL);
2121 166980 : Pprimep = cgetg(dP-D + 3, t_POL);
2122 166976 : Pm[1] = Pp[1] = Pprimem[1] = Pprimep[1] = P[1];
2123 682498 : for(i=0; i < D; i++)
2124 : {
2125 515522 : GEN c = gel(P, i+2);
2126 515522 : gel(Pm, i+2) = c;
2127 515522 : if (i) gel(Pprimem, i+1) = mului(i, c);
2128 : }
2129 697309 : for(; i <= dP; i++)
2130 : {
2131 530336 : GEN c = gel(P, i+2);
2132 530336 : gel(Pp, i+2-D) = c;
2133 530336 : gel(Pprimep, i+2-D) = mului(i, c);
2134 : }
2135 166973 : *pPm = normalizepol_lg(Pm, D+2);
2136 166977 : *pPprimem = normalizepol_lg(Pprimem, D+1);
2137 166981 : *pPp = normalizepol_lg(Pp, dP-D+3);
2138 166981 : *pPprimep = normalizepol_lg(Pprimep, dP-D+3);
2139 166981 : return dP - degpol(*pPp);
2140 : }
2141 :
2142 : static GEN
2143 5246231 : bkeval_single_power(long d, GEN V)
2144 : {
2145 5246231 : long mp = lg(V) - 2;
2146 5246231 : if (d > mp) return gmul(gpowgs(gel(V, mp+1), d/mp), gel(V, (d%mp)+1));
2147 5246231 : return gel(V, d+1);
2148 : }
2149 :
2150 : static GEN
2151 5245734 : splitpoleval(GEN Pp, GEN Pm, GEN pows, long D, long bitprec)
2152 : {
2153 5245734 : GEN vp = gen_bkeval_powers(Pp, degpol(Pp), pows, NULL, &mp_algebra, _mp_cmul);
2154 5246039 : GEN vm = gen_bkeval_powers(Pm, degpol(Pm), pows, NULL, &mp_algebra, _mp_cmul);
2155 5246200 : GEN xa = bkeval_single_power(D, pows);
2156 : GEN r;
2157 5246165 : if (!signe(vp)) return vm;
2158 5246165 : vp = gmul(vp, xa);
2159 5244808 : r = gadd(vp, vm);
2160 5241549 : if (gexpo(vp) - (signe(r)? gexpo(r): 0) > prec2nbits(realprec(vp)) - bitprec)
2161 344585 : return NULL;
2162 4897453 : return r;
2163 : }
2164 :
2165 : /* optimized Cauchy bound for P = X^D*Pp + Pm, D > deg(Pm) */
2166 : static GEN
2167 166980 : splitcauchy(GEN Pp, GEN Pm, long prec)
2168 : {
2169 166980 : GEN S = gel(Pp,2), A = gel(Pm,2);
2170 166980 : long i, lPm = lg(Pm), lPp = lg(Pp);
2171 512443 : for (i=3; i < lPm; i++) { GEN c = gel(Pm,i); if (abscmpii(A, c) < 0) A = c; }
2172 530348 : for (i=3; i < lPp; i++) S = addii(S, gel(Pp, i));
2173 166978 : return subsr(1, rdivii(A, S, prec)); /* 1 + |Pm|_oo / |Pp|_1 */
2174 : }
2175 :
2176 : static GEN
2177 15274 : ZX_deg1root(GEN P, long prec)
2178 : {
2179 15274 : GEN a = gel(P,3), b = gel(P,2);
2180 15274 : if (is_pm1(a))
2181 : {
2182 15274 : b = itor(b, prec); if (signe(a) > 0) togglesign(b);
2183 15274 : return b;
2184 : }
2185 0 : return rdivii(negi(b), a, prec);
2186 : }
2187 :
2188 : /* Newton for polynom P, P(0)!=0, with unique sign change => one root in ]0,oo[
2189 : * P' has also at most one zero there */
2190 : static GEN
2191 166971 : polsolve(GEN P, long bitprec)
2192 : {
2193 : pari_sp av;
2194 : GEN Pp, Pm, Pprimep, Pprimem, Pprime, Pprime2, ra, rb, rc, Pc;
2195 166971 : long dP = degpol(P), prec = nbits2prec(bitprec);
2196 : long expoold, iter, D, rt, s0, bitaddprec, cprec, PREC;
2197 :
2198 166973 : if (dP == 1) return ZX_deg1root(P, prec);
2199 166973 : Pprime = ZX_deriv(P);
2200 166975 : Pprime2 = ZX_deriv(Pprime);
2201 166978 : bitaddprec = 1 + 2*expu(dP); PREC = prec + nbits2prec(bitaddprec);
2202 166976 : D = split_pols(P, &Pp, &Pm, &Pprimep, &Pprimem); /* P = X^D*Pp + Pm */
2203 166981 : s0 = signe(gel(P, 2));
2204 166981 : rt = maxss(D, brent_kung_optpow(maxss(degpol(Pp), degpol(Pm)), 2, 1));
2205 166980 : rb = splitcauchy(Pp, Pm, DEFAULTPREC);
2206 166965 : for (cprec = DEFAULTPREC, expoold = LONG_MAX;;)
2207 0 : {
2208 166965 : GEN pows = gen_powers(rb, rt, 1, NULL, _mp_sqr, _mp_mul, _gen_one);
2209 166974 : Pc = splitpoleval(Pp, Pm, pows, D, bitaddprec);
2210 166965 : if (!Pc) { cprec += EXTRAPREC64; rb = rtor(rb, cprec); continue; }
2211 166965 : if (signe(Pc) != s0) break;
2212 0 : shiftr_inplace(rb,1);
2213 : }
2214 166965 : for (iter = 0, ra = NULL;;)
2215 1820582 : {
2216 : GEN wdth;
2217 1987547 : iter++;
2218 1987547 : if (ra)
2219 909427 : rc = shiftr(addrr(ra, rb), -1);
2220 : else
2221 1078120 : rc = shiftr(rb, -1);
2222 : for(;;)
2223 0 : {
2224 1987750 : GEN pows = gen_powers(rc, rt, 1, NULL, _mp_sqr, _mp_mul, _gen_one);
2225 1987500 : Pc = splitpoleval(Pp, Pm, pows, D, bitaddprec+2);
2226 1987330 : if (Pc) break;
2227 0 : cprec += EXTRAPREC64;
2228 0 : rc = rtor(rc, cprec);
2229 : }
2230 1987330 : if (signe(Pc) == s0)
2231 598213 : ra = rc;
2232 : else
2233 1389117 : rb = rc;
2234 1987330 : if (!ra) continue;
2235 1076158 : wdth = subrr(rb, ra);
2236 1076328 : if (!(iter % 8))
2237 : {
2238 168203 : GEN m1 = poleval(Pprime, ra), M2;
2239 168205 : if (signe(m1) == s0) continue;
2240 167022 : M2 = poleval(Pprime2, rb);
2241 167021 : if (abscmprr(gmul(M2, wdth), shiftr(m1, 1)) > 0) continue;
2242 163833 : break;
2243 : }
2244 908125 : else if (gexpo(wdth) <= -bitprec)
2245 3157 : break;
2246 : }
2247 166990 : rc = rb; av = avma;
2248 1380086 : for(;; rc = gc_leaf(av, rc))
2249 1380327 : {
2250 : long exponew;
2251 1547317 : GEN Ppc, dist, rcold = rc;
2252 1547317 : GEN pows = gen_powers(rc, rt, 1, NULL, _mp_sqr, _mp_mul, _gen_one);
2253 1547040 : Ppc = splitpoleval(Pprimep, Pprimem, pows, D-1, bitaddprec+4);
2254 1546729 : if (Ppc) Pc = splitpoleval(Pp, Pm, pows, D, bitaddprec+4);
2255 1546942 : if (!Ppc || !Pc)
2256 : {
2257 344598 : if (cprec >= PREC)
2258 43978 : cprec += EXTRAPREC64;
2259 : else
2260 300620 : cprec = minss(2*cprec, PREC);
2261 344596 : rc = rtor(rc, cprec); continue; /* backtrack one step */
2262 : }
2263 1202344 : dist = divrmp(Pc, Ppc);
2264 1202581 : rc = subrr(rc, dist);
2265 1202058 : if (cmprr(ra, rc) > 0 || cmprr(rb, rc) < 0)
2266 : {
2267 0 : if (cprec >= PREC) break;
2268 0 : cprec = minss(2*cprec, PREC);
2269 0 : rc = rtor(rcold, cprec); continue; /* backtrack one step */
2270 : }
2271 1202442 : if (expoold == LONG_MAX) { expoold = expo(dist); continue; }
2272 980994 : exponew = expo(dist);
2273 980994 : if (exponew < -bitprec - 1)
2274 : {
2275 232746 : if (cprec >= PREC) break;
2276 65778 : cprec = minss(2*cprec, PREC);
2277 65781 : rc = rtor(rc, cprec); continue;
2278 : }
2279 748248 : if (exponew > expoold - 2)
2280 : {
2281 54498 : if (cprec >= PREC) break;
2282 54498 : expoold = LONG_MAX;
2283 54498 : cprec = minss(2*cprec, PREC);
2284 54499 : rc = rtor(rc, cprec); continue;
2285 : }
2286 693750 : expoold = exponew;
2287 : }
2288 166968 : return rtor(rc, prec);
2289 : }
2290 :
2291 : /* Return primpart(P(x / 2)) */
2292 : static GEN
2293 2237594 : ZX_rescale2prim(GEN P)
2294 : {
2295 2237594 : long i, l = lg(P), v, n;
2296 : GEN Q;
2297 2237594 : if (l==2) return pol_0(varn(P));
2298 2237594 : Q = cgetg(l,t_POL); v = vali(gel(P,l-1));
2299 10793565 : for (i = l-2, n = 1; v > n && i >= 2; i--, n++)
2300 8555920 : v = minss(v, vali(gel(P,i)) + n);
2301 2237645 : gel(Q,l-1) = v? shifti(gel(P,l-1), -v): gel(P,l-1);
2302 12740730 : for (i = l-2, n = 1-v; i >= 2; i--, n++)
2303 10503182 : gel(Q,i) = shifti(gel(P,i), n);
2304 2237548 : Q[1] = P[1]; return Q;
2305 : }
2306 :
2307 : /* assume Q0 has no rational root */
2308 : static GEN
2309 1127825 : usp(GEN Q0, long flag, long bitprec)
2310 : {
2311 1127825 : const pari_sp av = avma;
2312 : GEN Qremapped, Q, c, Lc, Lk, sol;
2313 1127825 : GEN *pQremapped = flag == 1? &Qremapped: NULL;
2314 1127825 : const long prec = nbits2prec(bitprec), deg = degpol(Q0);
2315 1127827 : long listsize = 64, nbr = 0, nb_todo, ind, indf, i, k, nb;
2316 :
2317 1127827 : sol = zerocol(deg);
2318 1127855 : Lc = zerovec(listsize);
2319 1127876 : Lk = cgetg(listsize+1, t_VECSMALL);
2320 1127873 : k = Lk[1] = 0;
2321 1127873 : ind = 1; indf = 2;
2322 1127873 : Q = Q0;
2323 1127873 : c = gen_0;
2324 1127873 : nb_todo = 1;
2325 7128402 : while (nb_todo)
2326 : {
2327 6000571 : GEN nc = gel(Lc, ind);
2328 : pari_sp av2;
2329 6000571 : if (Lk[ind] == k + 1)
2330 : {
2331 2237595 : Q = Q0 = ZX_rescale2prim(Q0);
2332 2237593 : c = gen_0;
2333 : }
2334 6000569 : if (!equalii(nc, c)) Q = ZX_Z_translate(Q, subii(nc, c));
2335 6000605 : av2 = avma;
2336 6000605 : k = Lk[ind];
2337 6000605 : ind++;
2338 6000605 : c = nc;
2339 6000605 : nb_todo--;
2340 6000605 : nb = X2XP1(Q, pQremapped);
2341 :
2342 6000399 : if (nb == 1)
2343 : { /* exactly one root */
2344 1914551 : GEN s = gen_0;
2345 1914551 : if (flag == 0)
2346 : {
2347 0 : s = mkvec2(gmul2n(c,-k), gmul2n(addiu(c,1),-k));
2348 0 : s = gc_GEN(av2, s);
2349 : }
2350 1914551 : else if (flag == 1) /* Caveat: Qremapped is the reciprocal polynomial */
2351 : {
2352 166971 : s = polsolve(*pQremapped, bitprec+1);
2353 166974 : s = addir(c, divrr(s, addsr(1, s)));
2354 166975 : shiftr_inplace(s, -k);
2355 166976 : if (realprec(s) != prec) s = rtor(s, prec);
2356 166981 : s = gc_upto(av2, s);
2357 : }
2358 1747580 : else set_avma(av2);
2359 1914569 : gel(sol, ++nbr) = s;
2360 : }
2361 4085848 : else if (nb)
2362 : { /* unknown, add two nodes to refine */
2363 2436466 : if (indf + 2 > listsize)
2364 : {
2365 1802 : if (ind>1)
2366 : {
2367 5493 : for (i = ind; i < indf; i++)
2368 : {
2369 3691 : gel(Lc, i-ind+1) = gel(Lc, i);
2370 3691 : Lk[i-ind+1] = Lk[i];
2371 : }
2372 1802 : indf -= ind-1;
2373 1802 : ind = 1;
2374 : }
2375 1802 : if (indf + 2 > listsize)
2376 : {
2377 0 : listsize *= 2;
2378 0 : Lc = vec_lengthen(Lc, listsize);
2379 0 : Lk = vecsmall_lengthen(Lk, listsize);
2380 : }
2381 113439 : for (i = indf; i <= listsize; i++) gel(Lc, i) = gen_0;
2382 : }
2383 2436466 : gel(Lc, indf) = nc = shifti(c, 1);
2384 2436468 : gel(Lc, indf + 1) = addiu(nc, 1);
2385 2436469 : Lk[indf] = Lk[indf + 1] = k + 1;
2386 2436469 : indf += 2;
2387 2436469 : nb_todo += 2;
2388 : }
2389 6000420 : if (gc_needed(av, 2))
2390 : {
2391 0 : (void)gc_all(av, 6, &Q0, &Q, &c, &Lc, &Lk, &sol);
2392 0 : if (DEBUGMEM > 1) pari_warn(warnmem, "ZX_Uspensky", avma);
2393 : }
2394 : }
2395 1127831 : setlg(sol, nbr+1);
2396 1127835 : return gc_GEN(av, sol);
2397 : }
2398 :
2399 : static GEN
2400 14 : ZX_Uspensky_equal_yes(GEN a, long flag, long bit)
2401 : {
2402 14 : if (flag == 2) return gen_1;
2403 7 : if (flag == 1 && typ(a) != t_REAL)
2404 : {
2405 7 : if (typ(a) == t_INT && !signe(a))
2406 0 : a = real_0_bit(bit);
2407 : else
2408 7 : a = gtofp(a, nbits2prec(bit));
2409 : }
2410 7 : return mkcol(a);
2411 : }
2412 : static GEN
2413 21 : ZX_Uspensky_no(long flag)
2414 21 : { return flag <= 1 ? cgetg(1, t_COL) : gen_0; }
2415 : /* ZX_Uspensky(P, [a,a], flag) */
2416 : static GEN
2417 28 : ZX_Uspensky_equal(GEN P, GEN a, long flag, long bit)
2418 : {
2419 28 : if (typ(a) != t_INFINITY && gequal0(poleval(P, a)))
2420 14 : return ZX_Uspensky_equal_yes(a, flag, bit);
2421 : else
2422 14 : return ZX_Uspensky_no(flag);
2423 : }
2424 : static int
2425 3378 : sol_ok(GEN r, GEN a, GEN b) { return gcmp(a, r) <= 0 && gcmp(r, b) <= 0; }
2426 :
2427 : /* P a ZX without real double roots; better if primitive and squarefree but
2428 : * caller should ensure that. If flag & 4 assume that P has no rational root
2429 : * (modest speedup) */
2430 : GEN
2431 1315028 : ZX_Uspensky(GEN P, GEN ab, long flag, long bitprec)
2432 : {
2433 1315028 : pari_sp av = avma;
2434 : GEN a, b, res, sol;
2435 : double fb;
2436 : long l, nbz, deg;
2437 :
2438 1315028 : if (ab)
2439 : {
2440 1207329 : if (typ(ab) == t_VEC)
2441 : {
2442 1179271 : if (lg(ab) != 3) pari_err_DIM("ZX_Uspensky");
2443 1179271 : a = gel(ab, 1);
2444 1179271 : b = gel(ab, 2);
2445 : }
2446 : else
2447 : {
2448 28058 : a = ab;
2449 28058 : b = mkoo();
2450 : }
2451 : }
2452 : else
2453 : {
2454 107699 : a = mkmoo();
2455 107698 : b = mkoo();
2456 : }
2457 1315029 : if (flag & 4)
2458 : {
2459 129803 : if (gcmp(a, b) >= 0) { set_avma(av); return ZX_Uspensky_no(flag); }
2460 129803 : flag &= ~4;
2461 129803 : sol = cgetg(1, t_COL);
2462 : }
2463 : else
2464 : {
2465 1185226 : switch (gcmp(a, b))
2466 : {
2467 7 : case 1: set_avma(av); return ZX_Uspensky_no(flag);
2468 28 : case 0: return gc_GEN(av, ZX_Uspensky_equal(P, a, flag, bitprec));
2469 : }
2470 1185191 : sol = nfrootsQ(P);
2471 : }
2472 1314992 : nbz = 0; l = lg(sol);
2473 1314992 : if (l > 1)
2474 : {
2475 : long i, j;
2476 2706 : P = RgX_div(P, roots_to_pol(sol, varn(P)));
2477 2706 : if (!RgV_is_ZV(sol)) P = Q_primpart(P);
2478 6084 : for (i = j = 1; i < l; i++)
2479 3378 : if (sol_ok(gel(sol,i), a, b)) gel(sol,j++) = gel(sol,i);
2480 2706 : setlg(sol, j);
2481 2706 : if (flag == 2) { nbz = j-1; sol = utoi(nbz); }
2482 2559 : else if (flag == 1) sol = RgC_gtofp(sol, nbits2prec(bitprec));
2483 : }
2484 1312286 : else if (flag == 2) sol = gen_0;
2485 1314992 : deg = degpol(P);
2486 1314992 : if (deg == 0) return gc_GEN(av, sol);
2487 1313045 : if (typ(a) == t_INFINITY && typ(b) != t_INFINITY && gsigne(b))
2488 : {
2489 28 : fb = fujiwara_bound_real(P, -1);
2490 28 : if (fb <= -pariINFINITY) a = gen_0;
2491 21 : else if (fb < 0) a = gen_m1;
2492 21 : else a = negi(int2n((long)ceil(fb)));
2493 : }
2494 1313045 : if (typ(b) == t_INFINITY && typ(a) != t_INFINITY && gsigne(a))
2495 : {
2496 21 : fb = fujiwara_bound_real(P, 1);
2497 21 : if (fb <= -pariINFINITY) b = gen_0;
2498 21 : else if (fb < 0) b = gen_1;
2499 7 : else b = int2n((long)ceil(fb));
2500 : }
2501 1313045 : if (typ(a) != t_INFINITY && typ(b) != t_INFINITY)
2502 : {
2503 : GEN d, ad, bd, diff;
2504 : long i;
2505 : /* can occur if one of a,b was initially a t_INFINITY */
2506 12582 : if (gequal(a,b)) return gc_GEN(av, sol);
2507 12575 : d = lcmii(Q_denom(a), Q_denom(b));
2508 12575 : if (is_pm1(d)) { d = NULL; ad = a; bd = b; }
2509 : else
2510 14 : { P = ZX_rescale(P, d); ad = gmul(a, d); bd = gmul(b, d); }
2511 12575 : diff = subii(bd, ad);
2512 12575 : P = ZX_affine(P, diff, ad);
2513 12575 : res = usp(P, flag, bitprec);
2514 12575 : if (flag <= 1)
2515 : {
2516 34176 : for (i = 1; i < lg(res); i++)
2517 : {
2518 21916 : GEN z = gmul(diff, gel(res, i));
2519 21916 : if (typ(z) == t_VEC)
2520 : {
2521 0 : gel(z, 1) = gadd(ad, gel(z, 1));
2522 0 : gel(z, 2) = gadd(ad, gel(z, 2));
2523 : }
2524 : else
2525 21916 : z = gadd(ad, z);
2526 21916 : if (d) z = gdiv(z, d);
2527 21916 : gel(res, i) = z;
2528 : }
2529 12260 : sol = shallowconcat(sol, res);
2530 : }
2531 : else
2532 315 : nbz += lg(res) - 1;
2533 : }
2534 1313038 : if (typ(b) == t_INFINITY && (fb=fujiwara_bound_real(P, 1)) > -pariINFINITY)
2535 : {
2536 1024775 : long bp = maxss((long)ceil(fb), 0);
2537 1024775 : res = usp(ZX_unscale2n(P, bp), flag, bitprec);
2538 1024784 : if (flag <= 1)
2539 71284 : sol = shallowconcat(sol, gmul2n(res, bp));
2540 : else
2541 953500 : nbz += lg(res)-1;
2542 : }
2543 1313046 : if (typ(a) == t_INFINITY && (fb=fujiwara_bound_real(P,-1)) > -pariINFINITY)
2544 : {
2545 90507 : long i, bm = maxss((long)ceil(fb), 0);
2546 90507 : res = usp(ZX_unscale2n(ZX_z_unscale(P, -1), bm), flag, bitprec);
2547 90513 : if (flag <= 1)
2548 : {
2549 75771 : for (i = 1; i < lg(res); i++)
2550 : {
2551 47493 : GEN z = gneg(gmul2n(gel(res, i), bm));
2552 47492 : if (typ(z) == t_VEC) swap(gel(z, 1), gel(z, 2));
2553 47492 : gel(res, i) = z;
2554 : }
2555 28278 : sol = shallowconcat(res, sol);
2556 : }
2557 : else
2558 62234 : nbz += lg(res)-1;
2559 : }
2560 1313050 : if (flag >= 2) return utoi(nbz);
2561 83630 : if (flag)
2562 83630 : sol = sort(sol);
2563 : else
2564 0 : sol = gen_sort(sol, (void *)_intervalcmp, cmp_nodata);
2565 83630 : return gc_upto(av, sol);
2566 : }
2567 :
2568 : /* x a scalar */
2569 : static GEN
2570 42 : rootsdeg0(GEN x)
2571 : {
2572 42 : if (!is_real_t(typ(x))) pari_err_TYPE("realroots",x);
2573 35 : if (gequal0(x)) pari_err_ROOTS0("realroots");
2574 14 : return cgetg(1,t_COL); /* constant polynomial */
2575 : }
2576 : static void
2577 2356256 : checkbound(GEN a)
2578 : {
2579 2356256 : switch(typ(a))
2580 : {
2581 2356256 : case t_INT: case t_FRAC: case t_INFINITY: break;
2582 0 : default: pari_err_TYPE("polrealroots", a);
2583 : }
2584 2356256 : }
2585 : static GEN
2586 1179563 : check_ab(GEN ab)
2587 : {
2588 : GEN a, b;
2589 1179563 : if (!ab) return NULL;
2590 1178128 : if (typ(ab) != t_VEC || lg(ab) != 3) pari_err_TYPE("polrootsreal",ab);
2591 1178128 : a = gel(ab,1); checkbound(a);
2592 1178128 : b = gel(ab,2); checkbound(b);
2593 1178128 : if (typ(a) == t_INFINITY && inf_get_sign(a) < 0 &&
2594 448 : typ(b) == t_INFINITY && inf_get_sign(b) > 0) ab = NULL;
2595 1178128 : return ab;
2596 : }
2597 : /* e^(1/h) assuming the h-th root is real, beware that sqrtnr assumes e >= 0 */
2598 : static GEN
2599 22877 : _sqrtnr(GEN e, long h)
2600 : {
2601 : long s;
2602 : GEN r;
2603 22877 : if (h == 2) return sqrtr(e);
2604 14 : s = signe(e); setsigne(e, 1); /* e < 0 is possible, implies h is odd */
2605 14 : r = sqrtnr(e, h); if (s < 0) setsigne(r, -1);
2606 14 : return r;
2607 : }
2608 : GEN
2609 50627 : realroots(GEN P, GEN ab, long prec)
2610 : {
2611 50627 : pari_sp av = avma;
2612 50627 : GEN sol = NULL, fa, ex;
2613 : long i, j, v, l;
2614 :
2615 50627 : ab = check_ab(ab);
2616 50627 : if (typ(P) != t_POL) return rootsdeg0(P);
2617 50606 : if (!RgX_is_ZX(P)) P = RgX_rescale_to_int(P);
2618 50606 : switch(degpol(P))
2619 : {
2620 14 : case -1: return rootsdeg0(gen_0);
2621 7 : case 0: return rootsdeg0(gel(P,2));
2622 : }
2623 50585 : v = ZX_valrem(Q_primpart(P), &P);
2624 50585 : fa = ZX_squff(P, &ex); l = lg(fa); sol = cgetg(l + 1, t_VEC);
2625 102711 : for (i = 1; i < l; i++)
2626 : {
2627 52126 : GEN Pi = gel(fa, i), soli, soli2;
2628 : long n, h;
2629 52126 : if (ab) h = 1; else Pi = ZX_deflate_max(Pi, &h);
2630 52126 : soli = ZX_Uspensky(Pi, odd(h)? ab: gen_0, 1, prec2nbits(prec));
2631 52126 : n = lg(soli); soli2 = odd(h)? NULL: cgetg(n, t_COL);
2632 119122 : for (j = 1; j < n; j++)
2633 : {
2634 66996 : GEN r = gel(soli, j); /* != 0 */
2635 66996 : if (typ(r) != t_REAL) gel(soli, j) = r = gtofp(r, prec);
2636 66996 : if (h > 1)
2637 : {
2638 77 : gel(soli, j) = r = _sqrtnr(r, h);
2639 77 : if (soli2) gel(soli2, j) = negr(r);
2640 : }
2641 : }
2642 52126 : if (soli2) soli = shallowconcat(soli, soli2);
2643 52126 : if (ex[i] > 1) soli = shallowconcat1( const_vec(ex[i], soli) );
2644 52126 : gel(sol, i) = soli;
2645 : }
2646 50585 : if (v && (!ab || (gsigne(gel(ab,1)) <= 0 && gsigne(gel(ab,2)) >= 0)))
2647 84 : gel(sol, i++) = const_col(v, real_0(prec));
2648 50585 : setlg(sol, i); if (i == 1) retgc_const(av, cgetg(1, t_COL));
2649 50571 : return gc_upto(av, sort(shallowconcat1(sol)));
2650 : }
2651 : GEN
2652 48668 : ZX_realroots_irred(GEN P, long prec)
2653 : {
2654 48668 : long dP = degpol(P), j, n, h;
2655 : GEN sol, sol2;
2656 : pari_sp av;
2657 48668 : if (dP == 1) retmkvec(ZX_deg1root(P, prec));
2658 45360 : av = avma; P = ZX_deflate_max(P, &h);
2659 45360 : if (h == dP)
2660 : {
2661 11966 : GEN r = _sqrtnr(ZX_deg1root(P, prec), h);
2662 11965 : return gc_GEN(av, odd(h)? mkvec(r): mkvec2(negr(r), r));
2663 : }
2664 33394 : sol = ZX_Uspensky(P, odd(h)? NULL: gen_0, 1 | 4, prec2nbits(prec));
2665 33395 : n = lg(sol); sol2 = odd(h)? NULL: cgetg(n, t_COL);
2666 134137 : for (j = 1; j < n; j++)
2667 : {
2668 100742 : GEN r = gel(sol, j);
2669 100742 : if (typ(r) != t_REAL) gel(sol, j) = r = gtofp(r, prec);
2670 100742 : if (h > 1)
2671 : {
2672 10834 : gel(sol, j) = r = _sqrtnr(r, h);
2673 10834 : if (sol2) gel(sol2, j) = negr(r);
2674 : }
2675 : }
2676 33395 : if (sol2) sol = shallowconcat(sol, sol2);
2677 33395 : return gc_upto(av, sort(sol));
2678 : }
2679 :
2680 : static long
2681 123558 : ZX_sturm_i(GEN P, long flag)
2682 : {
2683 : pari_sp av;
2684 123558 : long h, r, dP = degpol(P);
2685 123558 : if (dP == 1) return 1;
2686 120216 : av = avma; P = ZX_deflate_max(P, &h);
2687 120214 : if (h == dP)
2688 : { /* now deg P = 1 */
2689 18236 : if (odd(h))
2690 665 : r = 1;
2691 : else
2692 17571 : r = (signe(gel(P,2)) != signe(gel(P,3)))? 2: 0;
2693 18236 : return gc_long(av, r);
2694 : }
2695 101978 : if (odd(h))
2696 78828 : r = itou(ZX_Uspensky(P, NULL, flag, 0));
2697 : else
2698 23152 : r = 2*itou(ZX_Uspensky(P, gen_0, flag, 0));
2699 101982 : return gc_long(av,r);
2700 : }
2701 : /* P nonconstant, squarefree ZX */
2702 : long
2703 1128935 : ZX_sturmpart(GEN P, GEN ab)
2704 : {
2705 1128935 : pari_sp av = avma;
2706 1128935 : if (!check_ab(ab)) return ZX_sturm(P);
2707 1127530 : return gc_long(av, itou(ZX_Uspensky(P, ab, 2, 0)));
2708 : }
2709 : /* P nonconstant, squarefree ZX */
2710 : long
2711 6395 : ZX_sturm(GEN P) { return ZX_sturm_i(P, 2); }
2712 : /* P irreducible ZX */
2713 : long
2714 117163 : ZX_sturm_irred(GEN P) { return ZX_sturm_i(P, 2 + 4); }
|