Code coverage tests

This page documents the degree to which the PARI/GP source code is tested by our public test suite, distributed with the source distribution in directory src/test/. This is measured by the gcov utility; we then process gcov output using the lcov frond-end.

We test a few variants depending on Configure flags on the pari.math.u-bordeaux.fr machine (x86_64 architecture), and agregate them in the final report:

The target is to exceed 90% coverage for all mathematical modules (given that branches depending on DEBUGLEVEL or DEBUGMEM are not covered). This script is run to produce the results below.

LCOV - code coverage report
Current view: top level - basemath - QX_factor.c (source / functions) Coverage Total Hit
Test: PARI/GP v2.18.1 lcov report (development 31042-0fbe168e69) Lines: 95.9 % 952 913
Test Date: 2026-07-23 17:04:59 Functions: 95.3 % 64 61
Legend: Lines:     hit not hit

            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              : #include "pari.h"
      15              : #include "paripriv.h"
      16              : 
      17              : #define DEBUGLEVEL DEBUGLEVEL_factor
      18              : 
      19              : /* x,y two ZX, y non constant. Return q = x/y if y divides x in Z[X] and NULL
      20              :  * otherwise. If not NULL, B is a t_INT upper bound for ||q||_oo. */
      21              : static GEN
      22      6587888 : ZX_divides_i(GEN x, GEN y, GEN B)
      23              : {
      24              :   long dx, dy, dz, i, j;
      25              :   pari_sp av;
      26              :   GEN z,p1,y_lead;
      27              : 
      28      6587888 :   dy=degpol(y);
      29      6587888 :   dx=degpol(x);
      30      6587888 :   dz=dx-dy; if (dz<0) return NULL;
      31      6586810 :   z=cgetg(dz+3,t_POL); z[1] = x[1];
      32      6586810 :   x += 2; y += 2; z += 2;
      33      6586810 :   y_lead = gel(y,dy);
      34      6586810 :   if (equali1(y_lead)) y_lead = NULL;
      35              : 
      36      6586810 :   p1 = gel(x,dx);
      37      6586810 :   if (y_lead) {
      38              :     GEN r;
      39        36295 :     p1 = dvmdii(p1,y_lead, &r);
      40        36295 :     if (r != gen_0) return NULL;
      41              :   }
      42      6550515 :   else p1 = icopy(p1);
      43      6582804 :   gel(z,dz) = p1;
      44      8280176 :   for (i=dx-1; i>=dy; i--)
      45              :   {
      46      1702644 :     av = avma; p1 = gel(x,i);
      47      5890030 :     for (j=i-dy+1; j<=i && j<=dz; j++)
      48      4187386 :       p1 = subii(p1, mulii(gel(z,j),gel(y,i-j)));
      49      1702644 :     if (y_lead) {
      50              :       GEN r;
      51        74431 :       p1 = dvmdii(p1,y_lead, &r);
      52        74431 :       if (r != gen_0) return NULL;
      53              :     }
      54      1701145 :     if (B && abscmpii(p1, B) > 0) return NULL;
      55      1697372 :     p1 = gc_INT(av, p1);
      56      1697372 :     gel(z,i-dy) = p1;
      57              :   }
      58      6577532 :   av = avma;
      59     17149211 :   for (; i >= 0; i--)
      60              :   {
      61     10614823 :     p1 = gel(x,i);
      62              :     /* we always enter this loop at least once */
      63     23906816 :     for (j=0; j<=i && j<=dz; j++)
      64     13291993 :       p1 = subii(p1, mulii(gel(z,j),gel(y,i-j)));
      65     10614823 :     if (signe(p1)) return NULL;
      66     10571679 :     set_avma(av);
      67              :   }
      68      6534388 :   return z - 2;
      69              : }
      70              : static GEN
      71      6557254 : ZX_divides(GEN x, GEN y) { return ZX_divides_i(x,y,NULL); }
      72              : 
      73              : #if 0
      74              : /* cf Beauzamy et al: upper bound for
      75              :  *      lc(x) * [2^(5/8) / pi^(3/8)] e^(1/4n) 2^(n/2) sqrt([x]_2)/ n^(3/8)
      76              :  * where [x]_2 = sqrt(\sum_i=0^n x[i]^2 / binomial(n,i)). One factor has
      77              :  * all coeffs less than then bound */
      78              : static GEN
      79              : two_factor_bound(GEN x)
      80              : {
      81              :   long i, j, n = lg(x) - 3;
      82              :   pari_sp av = avma;
      83              :   GEN *invbin, c, r = cgetr(LOWDEFAULTPREC), z;
      84              : 
      85              :   x += 2; invbin = (GEN*)new_chunk(n+1);
      86              :   z = real_1(LOWDEFAULTPREC); /* invbin[i] = 1 / binomial(n, i) */
      87              :   for (i=0,j=n; j >= i; i++,j--)
      88              :   {
      89              :     invbin[i] = invbin[j] = z;
      90              :     z = divru(mulru(z, i+1), n-i);
      91              :   }
      92              :   z = invbin[0]; /* = 1 */
      93              :   for (i=0; i<=n; i++)
      94              :   {
      95              :     c = gel(x,i); if (!signe(c)) continue;
      96              :     affir(c, r);
      97              :     z = addrr(z, mulrr(sqrr(r), invbin[i]));
      98              :   }
      99              :   z = shiftr(sqrtr(z), n);
     100              :   z = divrr(z, dbltor(pow((double)n, 0.75)));
     101              :   z = roundr_safe(sqrtr(z));
     102              :   z = mulii(z, absi_shallow(gel(x,n)));
     103              :   return gc_INT(av, shifti(z, 1));
     104              : }
     105              : #endif
     106              : 
     107              : /* A | S ==> |a_i| <= binom(d-1, i-1) || S ||_2 + binom(d-1, i) lc(S) */
     108              : static GEN
     109        62422 : Mignotte_bound(GEN S)
     110              : {
     111        62422 :   long i, d = degpol(S);
     112        62422 :   GEN C, N2, t, binlS, lS = leading_coeff(S), bin = vecbinomial(d-1);
     113              : 
     114        62422 :   N2 = sqrtr(RgX_fpnorml2(S,DEFAULTPREC));
     115        62422 :   binlS = is_pm1(lS)? bin: ZC_Z_mul(bin, lS);
     116              : 
     117              :   /* i = 0 */
     118        62422 :   C = gel(binlS,1);
     119              :   /* i = d */
     120        62422 :   t = N2; if (gcmp(C, t) < 0) C = t;
     121       532053 :   for (i = 1; i < d; i++)
     122              :   {
     123       469631 :     t = addri(mulir(gel(bin,i), N2), gel(binlS,i+1));
     124       469631 :     if (mpcmp(C, t) < 0) C = t;
     125              :   }
     126        62422 :   return C;
     127              : }
     128              : /* A | S ==> |a_i|^2 <= 3^{3/2 + d} / (4 \pi d) [P]_2^2,
     129              :  * where [P]_2 is Bombieri's 2-norm */
     130              : static GEN
     131        62422 : Beauzamy_bound(GEN S)
     132              : {
     133        62422 :   const long prec = DEFAULTPREC;
     134        62422 :   long i, d = degpol(S);
     135              :   GEN bin, lS, s, C;
     136        62422 :   bin = vecbinomial(d);
     137              : 
     138        62422 :   s = real_0(prec);
     139       656897 :   for (i=0; i<=d; i++)
     140              :   {
     141       594475 :     GEN c = gel(S,i+2);
     142       594475 :     if (gequal0(c)) continue;
     143              :     /* s += P_i^2 / binomial(d,i) */
     144       498687 :     s = addrr(s, divri(itor(sqri(c), prec), gel(bin,i+1)));
     145              :   }
     146              :   /* s = [S]_2^2 */
     147        62422 :   C = powruhalf(utor(3,prec), 3 + 2*d); /* 3^{3/2 + d} */
     148        62422 :   C = divrr(mulrr(C, s), mulur(4*d, mppi(prec)));
     149        62422 :   lS = absi_shallow(leading_coeff(S));
     150        62422 :   return mulir(lS, sqrtr(C));
     151              : }
     152              : 
     153              : static GEN
     154        62422 : factor_bound(GEN S)
     155              : {
     156        62422 :   pari_sp av = avma;
     157        62422 :   GEN a = Mignotte_bound(S);
     158        62422 :   GEN b = Beauzamy_bound(S);
     159        62422 :   if (DEBUGLEVEL>2)
     160              :   {
     161            0 :     err_printf("Mignotte bound: %Ps\n",a);
     162            0 :     err_printf("Beauzamy bound: %Ps\n",b);
     163              :   }
     164        62422 :   return gc_upto(av, ceil_safe(gmin_shallow(a, b)));
     165              : }
     166              : 
     167              : /* Naive recombination of modular factors: combine up to maxK modular
     168              :  * factors, degree <= klim
     169              :  *
     170              :  * target = polynomial we want to factor
     171              :  * famod = array of modular factors.  Product should be congruent to
     172              :  * target/lc(target) modulo p^a
     173              :  * For true factors: S1,S2 <= p^b, with b <= a and p^(b-a) < 2^31 */
     174              : static GEN
     175        51730 : cmbf(GEN pol, GEN famod, GEN bound, GEN p, long a, long b,
     176              :      long klim, long *pmaxK, int *done)
     177              : {
     178        51730 :   long K = 1, cnt = 1, i,j,k, curdeg, lfamod = lg(famod)-1;
     179              :   ulong spa_b, spa_bs2, Sbound;
     180        51730 :   GEN lc, lcpol, pa = powiu(p,a), pas2 = shifti(pa,-1);
     181        51730 :   GEN trace1   = cgetg(lfamod+1, t_VECSMALL);
     182        51730 :   GEN trace2   = cgetg(lfamod+1, t_VECSMALL);
     183        51730 :   GEN ind      = cgetg(lfamod+1, t_VECSMALL);
     184        51730 :   GEN deg      = cgetg(lfamod+1, t_VECSMALL);
     185        51730 :   GEN degsofar = cgetg(lfamod+1, t_VECSMALL);
     186        51730 :   GEN listmod  = cgetg(lfamod+1, t_VEC);
     187        51730 :   GEN fa       = cgetg(lfamod+1, t_VEC);
     188              : 
     189        51730 :   *pmaxK = cmbf_maxK(lfamod);
     190        51730 :   lc = absi_shallow(leading_coeff(pol));
     191        51730 :   if (equali1(lc)) lc = NULL;
     192        51730 :   lcpol = lc? ZX_Z_mul(pol, lc): pol;
     193              : 
     194              :   {
     195        51730 :     GEN pa_b,pa_bs2,pb, lc2 = lc? sqri(lc): NULL;
     196              : 
     197        51730 :     pa_b = powiu(p, a-b); /* < 2^31 */
     198        51730 :     pa_bs2 = shifti(pa_b,-1);
     199        51730 :     pb= powiu(p, b);
     200       182696 :     for (i=1; i <= lfamod; i++)
     201              :     {
     202       130966 :       GEN T1,T2, P = gel(famod,i);
     203       130966 :       long d = degpol(P);
     204              : 
     205       130966 :       deg[i] = d; P += 2;
     206       130966 :       T1 = gel(P,d-1);/* = - S_1 */
     207       130966 :       T2 = sqri(T1);
     208       130966 :       if (d > 1) T2 = subii(T2, shifti(gel(P,d-2),1));
     209       130966 :       T2 = modii(T2, pa); /* = S_2 Newton sum */
     210       130966 :       if (lc)
     211              :       {
     212         5075 :         T1 = Fp_mul(lc, T1, pa);
     213         5075 :         T2 = Fp_mul(lc2,T2, pa);
     214              :       }
     215       130966 :       uel(trace1,i) = itou(diviiround(T1, pb));
     216       130966 :       uel(trace2,i) = itou(diviiround(T2, pb));
     217              :     }
     218        51730 :     spa_b   = uel(pa_b,2); /* < 2^31 */
     219        51730 :     spa_bs2 = uel(pa_bs2,2); /* < 2^31 */
     220              :   }
     221        51730 :   degsofar[0] = 0; /* sentinel */
     222              : 
     223              :   /* ind runs through strictly increasing sequences of length K,
     224              :    * 1 <= ind[i] <= lfamod */
     225        93215 : nextK:
     226        93215 :   if (K > *pmaxK || 2*K > lfamod) goto END;
     227        57470 :   if (DEBUGLEVEL > 3)
     228            0 :     err_printf("\n### K = %d, %Ps combinations\n", K,binomial(utoipos(lfamod), K));
     229        57470 :   setlg(ind, K+1); ind[1] = 1;
     230        57470 :   Sbound = (ulong) ((K+1)>>1);
     231        57470 :   i = 1; curdeg = deg[ind[1]];
     232              :   for(;;)
     233              :   { /* try all combinations of K factors */
     234       642453 :     for (j = i; j < K; j++)
     235              :     {
     236        89957 :       degsofar[j] = curdeg;
     237        89957 :       ind[j+1] = ind[j]+1; curdeg += deg[ind[j+1]];
     238              :     }
     239       552496 :     if (curdeg <= klim) /* trial divide */
     240        10685 :     {
     241              :       GEN y, q, list;
     242              :       pari_sp av;
     243              :       ulong t;
     244              : 
     245              :       /* d - 1 test */
     246      1392293 :       for (t=uel(trace1,ind[1]),i=2; i<=K; i++)
     247       839797 :         t = Fl_add(t, uel(trace1,ind[i]), spa_b);
     248       552496 :       if (t > spa_bs2) t = spa_b - t;
     249       552496 :       if (t > Sbound)
     250              :       {
     251       439732 :         if (DEBUGLEVEL>6) err_printf(".");
     252       439732 :         goto NEXT;
     253              :       }
     254              :       /* d - 2 test */
     255       242096 :       for (t=uel(trace2,ind[1]),i=2; i<=K; i++)
     256       129332 :         t = Fl_add(t, uel(trace2,ind[i]), spa_b);
     257       112764 :       if (t > spa_bs2) t = spa_b - t;
     258       112764 :       if (t > Sbound)
     259              :       {
     260        59654 :         if (DEBUGLEVEL>6) err_printf("|");
     261        59654 :         goto NEXT;
     262              :       }
     263              : 
     264        53110 :       av = avma;
     265              :       /* check trailing coeff */
     266        53110 :       y = lc;
     267       154632 :       for (i=1; i<=K; i++)
     268              :       {
     269       101522 :         GEN q = constant_coeff(gel(famod,ind[i]));
     270       101522 :         if (y) q = mulii(y, q);
     271       101522 :         y = centermodii(q, pa, pas2);
     272              :       }
     273        53110 :       if (!signe(y) || !dvdii(constant_coeff(lcpol), y))
     274              :       {
     275        22637 :         if (DEBUGLEVEL>3) err_printf("T");
     276        22637 :         set_avma(av); goto NEXT;
     277              :       }
     278        30473 :       y = lc; /* full computation */
     279        67827 :       for (i=1; i<=K; i++)
     280              :       {
     281        37354 :         GEN q = gel(famod,ind[i]);
     282        37354 :         if (y) q = gmul(y, q);
     283        37354 :         y = centermod_i(q, pa, pas2);
     284              :       }
     285              : 
     286              :       /* y is the candidate factor */
     287        30473 :       if (! (q = ZX_divides_i(lcpol,y,bound)) )
     288              :       {
     289         3803 :         if (DEBUGLEVEL>3) err_printf("*");
     290         3803 :         set_avma(av); goto NEXT;
     291              :       }
     292              :       /* found a factor */
     293        26670 :       list = cgetg(K+1, t_VEC);
     294        26670 :       gel(listmod,cnt) = list;
     295        54075 :       for (i=1; i<=K; i++) list[i] = famod[ind[i]];
     296              : 
     297        26670 :       y = Q_primpart(y);
     298        26670 :       gel(fa,cnt++) = y;
     299              :       /* fix up pol */
     300        26670 :       pol = q;
     301        26670 :       if (lc) pol = Q_div_to_int(pol, leading_coeff(y));
     302        98913 :       for (i=j=k=1; i <= lfamod; i++)
     303              :       { /* remove used factors */
     304        72243 :         if (j <= K && i == ind[j]) j++;
     305              :         else
     306              :         {
     307        44838 :           gel(famod,k) = gel(famod,i);
     308        44838 :           uel(trace1,k) = uel(trace1,i);
     309        44838 :           uel(trace2,k) = uel(trace2,i);
     310        44838 :           deg[k] = deg[i]; k++;
     311              :         }
     312              :       }
     313        26670 :       lfamod -= K;
     314        26670 :       *pmaxK = cmbf_maxK(lfamod);
     315        26670 :       if (lfamod < 2*K) goto END;
     316        10685 :       i = 1; curdeg = deg[ind[1]];
     317        10685 :       bound = factor_bound(pol);
     318        10685 :       if (lc) lc = absi_shallow(leading_coeff(pol));
     319        10685 :       lcpol = lc? ZX_Z_mul(pol, lc): pol;
     320        10685 :       if (DEBUGLEVEL>3)
     321            0 :         err_printf("\nfound factor %Ps\nremaining modular factor(s): %ld\n",
     322              :                    y, lfamod);
     323        10685 :       continue;
     324              :     }
     325              : 
     326            0 : NEXT:
     327       525826 :     for (i = K+1;;)
     328              :     {
     329       656533 :       if (--i == 0) { K++; goto nextK; }
     330       615048 :       if (++ind[i] <= lfamod - K + i)
     331              :       {
     332       484341 :         curdeg = degsofar[i-1] + deg[ind[i]];
     333       484341 :         if (curdeg <= klim) break;
     334              :       }
     335              :     }
     336              :   }
     337        51730 : END:
     338        51730 :   *done = 1;
     339        51730 :   if (degpol(pol) > 0)
     340              :   { /* leftover factor */
     341        51730 :     if (signe(leading_coeff(pol)) < 0) pol = ZX_neg(pol);
     342        51730 :     if (lfamod >= 2*K) *done = 0;
     343              : 
     344        51730 :     setlg(famod, lfamod+1);
     345        51730 :     gel(listmod,cnt) = leafcopy(famod);
     346        51730 :     gel(fa,cnt++) = pol;
     347              :   }
     348        51730 :   if (DEBUGLEVEL>6) err_printf("\n");
     349        51730 :   setlg(listmod, cnt);
     350        51730 :   setlg(fa, cnt); return mkvec2(fa, listmod);
     351              : }
     352              : 
     353              : /* recombination of modular factors: van Hoeij's algorithm */
     354              : 
     355              : /* Q in Z[X], return Q(2^n) */
     356              : static GEN
     357       186381 : shifteval(GEN Q, long n)
     358              : {
     359       186381 :   pari_sp av = avma;
     360       186381 :   long i, l = lg(Q);
     361              :   GEN s;
     362              : 
     363       186381 :   if (!signe(Q)) return gen_0;
     364       186381 :   s = gel(Q,l-1);
     365       985890 :   for (i = l-2; i > 1; i--)
     366              :   {
     367       799509 :     s = addii(gel(Q,i), shifti(s, n));
     368       799509 :     if (gc_needed(av,1)) s = gc_INT(av, s);
     369              :   }
     370       186381 :   return s;
     371              : }
     372              : 
     373              : /* return integer y such that all |a| <= y if P(a) = 0 */
     374              : static GEN
     375       112919 : root_bound(GEN P0)
     376              : {
     377       112919 :   GEN Q = leafcopy(P0), lP = absi_shallow(leading_coeff(Q)), x,y,z;
     378       112919 :   long k, d = degpol(Q);
     379              : 
     380              :   /* P0 = lP x^d + Q, deg Q < d */
     381       112919 :   Q = normalizepol_lg(Q, d+2);
     382       705062 :   for (k=lg(Q)-1; k>1; k--) gel(Q,k) = absi_shallow(gel(Q,k));
     383       112919 :   k = (long)(fujiwara_bound(P0));
     384       187907 :   for (  ; k >= 0; k--)
     385              :   {
     386       186381 :     pari_sp av = avma;
     387              :     /* y = 2^k; Q(y) >= lP y^d ? */
     388       186381 :     if (cmpii(shifteval(Q,k), shifti(lP, d*k)) >= 0) break;
     389        74988 :     set_avma(av);
     390              :   }
     391       112919 :   if (k < 0) k = 0;
     392       112919 :   y = int2n(k+1);
     393       112919 :   if (d > 2000) return y; /* likely to be expensive, don't bother */
     394       112919 :   x = int2n(k);
     395       112919 :   for(k=0; ; k++)
     396              :   {
     397       604348 :     z = shifti(addii(x,y), -1);
     398       604348 :     if (equalii(x,z) || k > 5) break;
     399       491429 :     if (cmpii(ZX_Z_eval(Q,z), mulii(lP, powiu(z, d))) < 0)
     400       263425 :       y = z;
     401              :     else
     402       228004 :       x = z;
     403              :   }
     404       112919 :   return y;
     405              : }
     406              : 
     407              : GEN
     408          350 : chk_factors_get(GEN lt, GEN famod, GEN c, GEN T, GEN N)
     409              : {
     410          350 :   long i = 1, j, l = lg(famod);
     411          350 :   GEN V = cgetg(l, t_VEC);
     412         8414 :   for (j = 1; j < l; j++)
     413         8064 :     if (signe(gel(c,j))) gel(V,i++) = gel(famod,j);
     414          350 :   if (lt && i > 1) gel(V,1) = RgX_Rg_mul(gel(V,1), lt);
     415          350 :   setlg(V, i);
     416          350 :   return T? FpXQXV_prod(V, T, N): FpXV_prod(V,N);
     417              : }
     418              : 
     419              : static GEN
     420          140 : chk_factors(GEN P, GEN M_L, GEN bound, GEN famod, GEN pa)
     421              : {
     422              :   long i, r;
     423          140 :   GEN pol = P, list, piv, y, ltpol, lt, paov2;
     424              : 
     425          140 :   piv = ZM_hnf_knapsack(M_L);
     426          140 :   if (!piv) return NULL;
     427           70 :   if (DEBUGLEVEL>7) err_printf("ZM_hnf_knapsack output:\n%Ps\n",piv);
     428              : 
     429           70 :   r  = lg(piv)-1;
     430           70 :   list = cgetg(r+1, t_VEC);
     431           70 :   lt = absi_shallow(leading_coeff(pol));
     432           70 :   if (equali1(lt)) lt = NULL;
     433           70 :   ltpol = lt? ZX_Z_mul(pol, lt): pol;
     434           70 :   paov2 = shifti(pa,-1);
     435           70 :   for (i = 1;;)
     436              :   {
     437          161 :     if (DEBUGLEVEL) err_printf("LLL_cmbf: checking factor %ld\n",i);
     438          161 :     y = chk_factors_get(lt, famod, gel(piv,i), NULL, pa);
     439          161 :     y = FpX_center_i(y, pa, paov2);
     440          161 :     if (! (pol = ZX_divides_i(ltpol,y,bound)) ) return NULL;
     441          133 :     if (lt) y = Q_primpart(y);
     442          133 :     gel(list,i) = y;
     443          133 :     if (++i >= r) break;
     444              : 
     445           91 :     if (lt)
     446              :     {
     447           35 :       pol = ZX_Z_divexact(pol, leading_coeff(y));
     448           35 :       lt = absi_shallow(leading_coeff(pol));
     449           35 :       ltpol = ZX_Z_mul(pol, lt);
     450              :     }
     451              :     else
     452           56 :       ltpol = pol;
     453              :   }
     454           42 :   y = Q_primpart(pol);
     455           42 :   gel(list,i) = y; return list;
     456              : }
     457              : 
     458              : GEN
     459         1694 : LLL_check_progress(GEN Bnorm, long n0, GEN m, int final, long *ti_LLL)
     460              : {
     461              :   GEN norm, u;
     462              :   long i, R;
     463              :   pari_timer T;
     464              : 
     465         1694 :   if (DEBUGLEVEL>2) timer_start(&T);
     466         1694 :   u = ZM_lll_norms(m, final? 0.999: 0.75, LLL_INPLACE | LLL_NOFLATTER, &norm);
     467         1694 :   if (DEBUGLEVEL>2) *ti_LLL += timer_delay(&T);
     468        11571 :   for (R=lg(m)-1; R > 0; R--)
     469        11571 :     if (cmprr(gel(norm,R), Bnorm) < 0) break;
     470        17661 :   for (i=1; i<=R; i++) setlg(u[i], n0+1);
     471         1694 :   if (R <= 1)
     472              :   {
     473          126 :     if (!R) pari_err_BUG("LLL_cmbf [no factor]");
     474          126 :     return NULL; /* irreducible */
     475              :   }
     476         1568 :   setlg(u, R+1); return u;
     477              : }
     478              : 
     479              : static ulong
     480           14 : next2pow(ulong a)
     481              : {
     482           14 :   ulong b = 1;
     483          112 :   while (b < a) b <<= 1;
     484           14 :   return b;
     485              : }
     486              : 
     487              : /* Recombination phase of Berlekamp-Zassenhaus algorithm using a variant of
     488              :  * van Hoeij's knapsack
     489              :  *
     490              :  * P = squarefree in Z[X].
     491              :  * famod = array of (lifted) modular factors mod p^a
     492              :  * bound = Mignotte bound for the size of divisors of P (for the sup norm)
     493              :  * previously recombined all set of factors with less than rec elts */
     494              : static GEN
     495          147 : LLL_cmbf(GEN P, GEN famod, GEN p, GEN pa, GEN bound, long a, long rec)
     496              : {
     497          147 :   const long N0 = 1; /* # of traces added at each step */
     498          147 :   double BitPerFactor = 0.4; /* nb bits in p^(a-b) / modular factor */
     499          147 :   long i,j,tmax,n0,C, dP = degpol(P);
     500          147 :   double logp = log((double)itos(p)), LOGp2 = M_LN2/logp;
     501          147 :   double b0 = log((double)dP*2) / logp, logBr;
     502              :   GEN lP, Br, Bnorm, Tra, T2, TT, CM_L, m, list, ZERO;
     503              :   pari_sp av, av2;
     504          147 :   long ti_LLL = 0, ti_CF  = 0;
     505              : 
     506          147 :   lP = absi_shallow(leading_coeff(P));
     507          147 :   if (equali1(lP)) lP = NULL;
     508          147 :   Br = root_bound(P);
     509          147 :   if (lP) Br = mulii(lP, Br);
     510          147 :   logBr = dbllog2(Br) * LOGp2; /* log_p Br */
     511              : 
     512          147 :   n0 = lg(famod) - 1;
     513          147 :   C = (long)ceil( sqrt(N0 * n0 / 4.) ); /* > 1 */
     514          147 :   Bnorm = dbltor(n0 * (C*C + N0*n0/4.) * 1.00001);
     515          147 :   ZERO = zeromat(n0, N0);
     516              : 
     517          147 :   av = avma;
     518          147 :   TT = cgetg(n0+1, t_VEC);
     519          147 :   Tra  = cgetg(n0+1, t_MAT);
     520         2702 :   for (i=1; i<=n0; i++)
     521              :   {
     522         2555 :     gel(TT,i)  = NULL;
     523         2555 :     gel(Tra,i) = cgetg(N0+1, t_COL);
     524              :   }
     525          147 :   CM_L = scalarmat_s(C, n0);
     526              :   /* tmax = current number of traces used (and computed so far) */
     527          147 :   for (tmax = 0;; tmax += N0)
     528          518 :   {
     529          665 :     long b, bmin, delta, tnew = tmax + N0, r = lg(CM_L)-1;
     530              :     GEN M_L, CM_Lp, oldCM_L;
     531          665 :     int first = 1;
     532              :     pari_timer ti2, TI;
     533              : 
     534          665 :     bmin = (long)ceil(b0 + tnew*logBr);
     535          665 :     if (DEBUGLEVEL>2)
     536            0 :       err_printf("\nLLL_cmbf: %ld potential factors (tmax = %ld, bmin = %ld)\n",
     537              :                  r, tmax, bmin);
     538              : 
     539              :     /* compute Newton sums (possibly relifting first) */
     540          665 :     if (a <= bmin)
     541              :     {
     542           14 :       a = (long)ceil(bmin + 3*N0*logBr) + 1; /* enough for 3 more rounds */
     543           14 :       a = (long)next2pow((ulong)a);
     544              : 
     545           14 :       pa = powiu(p,a);
     546           14 :       famod = ZpX_liftfact(P, famod, pa, p, a);
     547          266 :       for (i=1; i<=n0; i++) gel(TT,i) = NULL;
     548              :     }
     549        12537 :     for (i=1; i<=n0; i++)
     550              :     {
     551        11872 :       GEN p1 = gel(Tra,i);
     552        11872 :       GEN p2 = polsym_gen(gel(famod,i), gel(TT,i), tnew, NULL, pa);
     553        11872 :       gel(TT,i) = p2;
     554        11872 :       p2 += 1+tmax; /* ignore traces number 0...tmax */
     555        23744 :       for (j=1; j<=N0; j++) gel(p1,j) = gel(p2,j);
     556        11872 :       if (lP)
     557              :       { /* make Newton sums integral */
     558         1848 :         GEN lPpow = powiu(lP, tmax);
     559         3696 :         for (j=1; j<=N0; j++)
     560              :         {
     561         1848 :           lPpow = mulii(lPpow,lP);
     562         1848 :           gel(p1,j) = mulii(gel(p1,j), lPpow);
     563              :         }
     564              :       }
     565              :     }
     566              : 
     567              :     /* compute truncation parameter */
     568          665 :     if (DEBUGLEVEL>2) { timer_start(&ti2); timer_start(&TI); }
     569          665 :     oldCM_L = CM_L;
     570          665 :     av2 = avma;
     571          665 :     delta = b = 0; /* -Wall */
     572         1218 : AGAIN:
     573         1218 :     M_L = Q_div_to_int(CM_L, utoipos(C));
     574         1218 :     T2 = centermod( ZM_mul(Tra, M_L), pa );
     575         1218 :     if (first)
     576              :     { /* initialize lattice, using few p-adic digits for traces */
     577          665 :       double t = gexpo(T2) - maxdd(32.0, BitPerFactor*r);
     578          665 :       b = maxss(bmin, (long)(t * LOGp2));
     579          665 :       delta = a - b; first = 0;
     580              :     }
     581              :     else
     582              :     { /* add more p-adic digits and continue reduction */
     583          553 :       long b0 = (long)(gexpo(T2) * LOGp2);
     584          553 :       if (b0 < b) b = b0;
     585          553 :       b = maxss(bmin, b - delta);
     586          553 :       if (b - delta/2 < bmin) b = bmin; /* near goal. Go all the way */
     587              :     }
     588         1218 :     m = vconcat(CM_L, ZM_mul(gdivround(Tra, powiu(p, b)), M_L));
     589         1218 :     m = shallowconcat( m, vconcat(ZERO, scalarmat(powiu(p, a-b), N0)) );
     590              :     /*     [ C M_L        0     ]
     591              :      * m = [                    ]   square matrix
     592              :      *     [  T2'  p^(a-b) I_N0 ]   T2' = Tra * M_L  truncated */
     593         1218 :     CM_L = LLL_check_progress(Bnorm, n0, m, b == bmin, /*dbg:*/ &ti_LLL);
     594         1218 :     if (DEBUGLEVEL>2)
     595            0 :       err_printf("LLL_cmbf: (a,b) =%4ld,%4ld; r =%3ld -->%3ld, time = %ld\n",
     596            0 :                  a,b, lg(m)-1, CM_L? lg(CM_L)-1: 1, timer_delay(&TI));
     597         1218 :     if (!CM_L) { list = mkvec(P); break; }
     598         1113 :     if (b > bmin)
     599              :     {
     600          553 :       CM_L = gc_GEN(av2, CM_L);
     601          553 :       goto AGAIN;
     602              :     }
     603          560 :     if (DEBUGLEVEL>2) timer_printf(&ti2, "for this block of traces");
     604              : 
     605          560 :     i = lg(CM_L) - 1;
     606          560 :     if (i == r && ZM_equal(CM_L, oldCM_L))
     607              :     {
     608           56 :       CM_L = oldCM_L;
     609           56 :       set_avma(av2); continue;
     610              :     }
     611              : 
     612          504 :     CM_Lp = FpM_image(CM_L, utoipos(27449)); /* inexpensive test */
     613          504 :     if (lg(CM_Lp) != lg(CM_L))
     614              :     {
     615            7 :       if (DEBUGLEVEL>2) err_printf("LLL_cmbf: rank decrease\n");
     616            7 :       CM_L = ZM_hnf(CM_L);
     617              :     }
     618              : 
     619          504 :     if (i <= r && i*rec < n0)
     620              :     {
     621              :       pari_timer ti;
     622          140 :       if (DEBUGLEVEL>2) timer_start(&ti);
     623          140 :       list = chk_factors(P, Q_div_to_int(CM_L,utoipos(C)), bound, famod, pa);
     624          140 :       if (DEBUGLEVEL>2) ti_CF += timer_delay(&ti);
     625          140 :       if (list) break;
     626           98 :       if (DEBUGLEVEL>2) err_printf("LLL_cmbf: chk_factors failed");
     627              :     }
     628          462 :     CM_L = gc_GEN(av2, CM_L);
     629          462 :     if (gc_needed(av,1))
     630              :     {
     631            0 :       if(DEBUGMEM>1) pari_warn(warnmem,"LLL_cmbf");
     632            0 :       (void)gc_all(av, 5, &CM_L, &TT, &Tra, &famod, &pa);
     633              :     }
     634              :   }
     635          147 :   if (DEBUGLEVEL>2)
     636            0 :     err_printf("* Time LLL: %ld\n* Time Check Factor: %ld\n",ti_LLL,ti_CF);
     637          147 :   return list;
     638              : }
     639              : 
     640              : /* Find a,b minimal such that A < q^a, B < q^b, 1 << q^(a-b) < 2^31 */
     641              : static int
     642        51730 : cmbf_precs(GEN q, GEN A, GEN B, long *pta, long *ptb, GEN *qa, GEN *qb)
     643              : {
     644        51730 :   long a, b, amin, d = (long)(31 / dbllog2(q) - 1e-5);
     645        51730 :   int fl = 0;
     646              : 
     647        51730 :   b = logintall(B, q, qb) + 1;
     648        51730 :   *qb = mulii(*qb, q);
     649        51730 :   amin = b + d;
     650        51730 :   if (gcmp(powiu(q, amin), A) <= 0)
     651              :   {
     652        14289 :     a = logintall(A, q, qa) + 1;
     653        14289 :     *qa = mulii(*qa, q);
     654        14289 :     b = a - d; *qb = powiu(q, b);
     655              :   }
     656              :   else
     657              :   { /* not enough room */
     658        37441 :     a = amin;  *qa = powiu(q, a);
     659        37441 :     fl = 1;
     660              :   }
     661        51730 :   if (DEBUGLEVEL > 3) {
     662            0 :     err_printf("S_2   bound: %Ps^%ld\n", q,b);
     663            0 :     err_printf("coeff bound: %Ps^%ld\n", q,a);
     664              :   }
     665        51730 :   *pta = a;
     666        51730 :   *ptb = b; return fl;
     667              : }
     668              : 
     669              : /* use van Hoeij's knapsack algorithm */
     670              : static GEN
     671        51730 : combine_factors(GEN target, GEN famod, GEN p, long klim)
     672              : {
     673              :   GEN la, B, A, res, L, pa, pb, listmod;
     674        51730 :   long a,b, l, maxK, n = degpol(target);
     675              :   int done;
     676              :   pari_timer T;
     677              : 
     678        51730 :   A = factor_bound(target);
     679              : 
     680        51730 :   la = absi_shallow(leading_coeff(target));
     681        51730 :   B = mului(n, sqri(mulii(la, root_bound(target)))); /* = bound for S_2 */
     682              : 
     683        51730 :   (void)cmbf_precs(p, A, B, &a, &b, &pa, &pb);
     684              : 
     685        51730 :   if (DEBUGLEVEL>2) timer_start(&T);
     686        51730 :   famod = ZpX_liftfact(target, famod, pa, p, a);
     687        51730 :   if (DEBUGLEVEL>2) timer_printf(&T, "Hensel lift (mod %Ps^%ld)", p,a);
     688        51730 :   L = cmbf(target, famod, A, p, a, b, klim, &maxK, &done);
     689        51730 :   if (DEBUGLEVEL>2) timer_printf(&T, "Naive recombination");
     690              : 
     691        51730 :   res     = gel(L,1);
     692        51730 :   listmod = gel(L,2); l = lg(listmod)-1;
     693        51730 :   famod = gel(listmod,l);
     694        51730 :   if (maxK > 0 && lg(famod)-1 > 2*maxK)
     695              :   {
     696          147 :     if (l!=1) A = factor_bound(gel(res,l));
     697          147 :     if (DEBUGLEVEL > 4) err_printf("last factor still to be checked\n");
     698          147 :     L = LLL_cmbf(gel(res,l), famod, p, pa, A, a, maxK);
     699          147 :     if (DEBUGLEVEL>2) timer_printf(&T,"Knapsack");
     700              :     /* remove last elt, possibly unfactored. Add all new ones. */
     701          147 :     setlg(res, l); res = shallowconcat(res, L);
     702              :   }
     703        51730 :   return res;
     704              : }
     705              : 
     706              : /* Assume 'a' a squarefree ZX; return 0 if no root (fl=1) / irreducible (fl=0).
     707              :  * Otherwise return prime p such that a mod p has fewest roots / factors */
     708              : static ulong
     709      2088729 : pick_prime(GEN a, long fl, pari_timer *T)
     710              : {
     711      2088729 :   pari_sp av = avma, av1;
     712      2088729 :   const long MAXNP = 7, da = degpol(a);
     713      2088729 :   long nmax = da+1, np;
     714      2088729 :   ulong chosenp = 0;
     715      2088729 :   GEN lead = gel(a,da+2);
     716              :   forprime_t S;
     717      2088729 :   if (equali1(lead)) lead = NULL;
     718      2088729 :   u_forprime_init(&S, 2, ULONG_MAX);
     719      2088729 :   av1 = avma;
     720      8067490 :   for (np = 0; np < MAXNP; set_avma(av1))
     721              :   {
     722      7954725 :     ulong p = u_forprime_next(&S);
     723              :     long nfacp;
     724              :     GEN z;
     725              : 
     726      7954725 :     if (!p) pari_err_OVERFLOW("DDF [out of small primes]");
     727      7954725 :     if (lead && !umodiu(lead,p)) continue;
     728      7885501 :     z = ZX_to_Flx(a, p);
     729      7885501 :     if (!Flx_is_squarefree(z, p)) continue;
     730              : 
     731      4892354 :     if (fl==1)
     732              :     {
     733      4286138 :       nfacp = Flx_nbroots(z, p);
     734      4286138 :       if (!nfacp) { chosenp = 0; break; } /* no root */
     735              :     }
     736       606216 :     else if(fl==0)
     737              :     {
     738       605467 :       nfacp = Flx_nbfact(z, p);
     739       605467 :       if (nfacp == 1) { chosenp = 0; break; } /* irreducible */
     740              :     } else
     741              :     {
     742          749 :       GEN f = gel(Flx_degfact(z, p),1);
     743          749 :       nfacp = lg(f)-1;
     744          749 :       if (f[1] > fl) { chosenp = 0; break; } /* no small factors */
     745              :     }
     746      2916397 :     if (DEBUGLEVEL>4)
     747            0 :       err_printf("...tried prime %3lu (%-3ld %s). Time = %ld\n",
     748              :                   p, nfacp, fl==1? "roots": "factors", timer_delay(T));
     749      2916397 :     if (nfacp < nmax)
     750              :     {
     751      1090337 :       nmax = nfacp; chosenp = p;
     752      1090337 :       if (da > 100 && nmax < 5) break; /* large degree, few factors. Enough */
     753              :     }
     754      2916390 :     np++;
     755              :   }
     756      2088729 :   return gc_ulong(av, chosenp);
     757              : }
     758              : 
     759              : /* Assume A a squarefree ZX; return the vector of its rational roots */
     760              : static GEN
     761      1878474 : DDF_roots(GEN A)
     762              : {
     763              :   GEN p, lc, lcpol, z, pe, pes2, bound;
     764              :   long i, m, e, lz;
     765              :   ulong pp;
     766              :   pari_sp av;
     767              :   pari_timer T;
     768              : 
     769      1878474 :   if (DEBUGLEVEL>2) timer_start(&T);
     770      1878474 :   pp = pick_prime(A, 1, &T);
     771      1878474 :   if (!pp) return cgetg(1,t_COL); /* no root */
     772        61042 :   p = utoipos(pp);
     773        61042 :   lc = leading_coeff(A);
     774        61042 :   if (is_pm1(lc))
     775        52711 :   { lc = NULL; lcpol = A; }
     776              :   else
     777         8331 :   { lc = absi_shallow(lc); lcpol = ZX_Z_mul(A, lc); }
     778        61042 :   bound = root_bound(A); if (lc) bound = mulii(lc, bound);
     779        61042 :   e = logintall(addiu(shifti(bound, 1), 1), p, &pe) + 1;
     780        61042 :   pe = mulii(pe, p);
     781        61042 :   pes2 = shifti(pe, -1);
     782        61042 :   if (DEBUGLEVEL>2) timer_printf(&T, "Root bound");
     783        61042 :   av = avma;
     784        61042 :   z = ZpX_roots(A, p, e); lz = lg(z);
     785        61042 :   z = deg1_from_roots(z, varn(A));
     786        61042 :   if (DEBUGLEVEL>2) timer_printf(&T, "Hensel lift (mod %lu^%ld)", pp,e);
     787       133067 :   for (m=1, i=1; i < lz; i++)
     788              :   {
     789        72025 :     GEN q, r, y = gel(z,i);
     790        72025 :     if (lc) y = ZX_Z_mul(y, lc);
     791        72025 :     y = centermod_i(y, pe, pes2);
     792        72025 :     if (! (q = ZX_divides(lcpol, y)) ) continue;
     793              : 
     794        27535 :     lcpol = q;
     795        27535 :     r = negi( constant_coeff(y) );
     796        27535 :     if (lc) {
     797         9649 :       r = gdiv(r,lc);
     798         9649 :       lcpol = Q_primpart(lcpol);
     799         9649 :       lc = absi_shallow( leading_coeff(lcpol) );
     800         9649 :       if (is_pm1(lc)) lc = NULL; else lcpol = ZX_Z_mul(lcpol, lc);
     801              :     }
     802        27535 :     gel(z,m++) = r;
     803        27535 :     if (gc_needed(av,2))
     804              :     {
     805            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"DDF_roots, m = %ld", m);
     806            0 :       (void)gc_all(av, lc? 3:2, &z, &lcpol, &lc);
     807              :     }
     808              :   }
     809        61042 :   if (DEBUGLEVEL>2) timer_printf(&T, "Recombination");
     810        61042 :   setlg(z, m); return z;
     811              : }
     812              : 
     813              : /* Assume a squarefree ZX, deg(a) > 0, return rational factors.
     814              :  * In fact, a(0) != 0 but we don't use this
     815              :  * if dmax>0, Only look for factor of degree at most dmax */
     816              : GEN
     817       210255 : ZX_DDF_max(GEN a, long dmax)
     818              : {
     819              :   GEN ap, prime, famod, z;
     820       210255 :   long ti = 0;
     821       210255 :   ulong p = 0;
     822       210255 :   pari_sp av = avma;
     823              :   pari_timer T, T2;
     824              : 
     825       210255 :   if (DEBUGLEVEL>2) { timer_start(&T); timer_start(&T2); }
     826       210255 :   p = pick_prime(a, dmax, &T2);
     827       210255 :   if (!p) return mkvec(a);
     828        51730 :   prime = utoipos(p);
     829        51730 :   ap = Flx_normalize(ZX_to_Flx(a, p), p);
     830        51730 :   famod = gel(Flx_factor(ap, p), 1);
     831        51730 :   if (DEBUGLEVEL>2)
     832              :   {
     833            0 :     if (DEBUGLEVEL>4) timer_printf(&T2, "splitting mod p = %lu", p);
     834            0 :     ti = timer_delay(&T);
     835            0 :     err_printf("Time setup: %ld\n", ti);
     836              :   }
     837        51730 :   z = combine_factors(a, FlxV_to_ZXV(famod), prime, degpol(a)-1);
     838        51730 :   if (DEBUGLEVEL>2)
     839            0 :     err_printf("Total Time: %ld\n===========\n", ti + timer_delay(&T));
     840        51730 :   return gc_GEN(av, z);
     841              : }
     842              : 
     843              : /* Distinct Degree Factorization (deflating first)
     844              :  * Assume x squarefree, degree(x) > 0, x(0) != 0 */
     845              : GEN
     846       155284 : ZX_DDF(GEN x)
     847              : {
     848              :   GEN L;
     849              :   long m;
     850       155284 :   if (DEBUGLEVEL>2)
     851            0 :    err_printf("ZX_DDF: factoring pol of deg %ld, %ld bits\n",degpol(x),gexpo(x));
     852       155284 :   x = ZX_deflate_max(x, &m);
     853       155284 :   L = ZX_DDF_max(x,0);
     854       155284 :   if (m > 1)
     855              :   {
     856        52433 :     GEN e, v, fa = factoru(m);
     857              :     long i,j,k, l;
     858              : 
     859        52433 :     e = gel(fa,2); k = 0;
     860        52433 :     fa= gel(fa,1); l = lg(fa);
     861       105188 :     for (i=1; i<l; i++) k += e[i];
     862        52433 :     v = cgetg(k+1, t_VECSMALL); k = 1;
     863       105188 :     for (i=1; i<l; i++)
     864       107096 :       for (j=1; j<=e[i]; j++) v[k++] = fa[i];
     865       106774 :     for (k--; k; k--)
     866              :     {
     867        54341 :       GEN L2 = cgetg(1,t_VEC);
     868       109137 :       for (i=1; i < lg(L); i++)
     869        54796 :               L2 = shallowconcat(L2, ZX_DDF_max(RgX_inflate(gel(L,i), v[k]),0));
     870        54341 :       L = L2;
     871              :     }
     872              :   }
     873       155284 :   return L;
     874              : }
     875              : 
     876              : /* SquareFree Factorization in Z[X] (char 0 is enough, if ZX_gcd -> RgX_gcd)
     877              :  * f = prod Q[i]^E[i], E[1] < E[2] < ..., and Q[i] squarefree and coprime.
     878              :  * Return Q, set *pE = E. For efficiency, caller should have used ZX_valrem
     879              :  * so that f(0) != 0 */
     880              : GEN
     881       322307 : ZX_squff(GEN f, GEN *pE)
     882              : {
     883              :   GEN T, V, P, E;
     884       322307 :   long i, k, n = 1 + degpol(f);
     885              : 
     886       322307 :   if (signe(leading_coeff(f)) < 0) f = ZX_neg(f);
     887       322307 :   E = cgetg(n, t_VECSMALL);
     888       322307 :   P = cgetg(n, t_COL);
     889       322307 :   f = Q_primpart(f); /* FIXME: caller could ensure this */
     890       322307 :   T = ZX_gcd_all(f, ZX_deriv(f), &V);
     891       322307 :   for (k = i = 1;; k++)
     892         3501 :   { /* T, V are primitive */
     893       325808 :     GEN W = ZX_gcd_all(T,V, &T); /* V and W are squarefree */
     894       325808 :     long dW = degpol(W), dV = degpol(V);
     895              :     /* T, W are primitive */
     896              :     /* f = prod_i T_i^{e_i}
     897              :      * W = prod_{i: e_i > k} T_i,
     898              :      * V = prod_{i: e_i >= k} T_i,
     899              :      * T = prod_{i: e_i > k} T_i^{e_i - k} */
     900       325808 :     if (!dW)
     901              :     {
     902       322307 :       if (dV) { gel(P,i) = V; E[i] = k; i++; }
     903       322307 :       break;
     904              :     }
     905         3501 :     if (dW == dV)
     906              :     {
     907              :       GEN U;
     908         1659 :       while ( (U = ZX_divides(T, V)) ) { k++; T = U; }
     909              :     }
     910              :     else
     911              :     {
     912         2388 :       gel(P,i) = RgX_div(V,W);
     913         2388 :       E[i] = k; i++; V = W;
     914              :     }
     915              :   }
     916       322307 :   setlg(P,i);
     917       322307 :   setlg(E,i); *pE = E; return P;
     918              : }
     919              : 
     920              : static GEN
     921        39555 : fact_from_DDF(GEN Q, GEN E, long n)
     922              : {
     923        39555 :   GEN v,w, y = cgetg(3, t_MAT);
     924        39555 :   long i,j,k, l = lg(Q);
     925              : 
     926        39555 :   v = cgetg(n+1, t_COL); gel(y,1) = v;
     927        39555 :   w = cgetg(n+1, t_COL); gel(y,2) = w;
     928        80468 :   for (k = i = 1; i < l; i++)
     929              :   {
     930        40913 :     GEN L = gel(Q,i), e = utoipos(E[i]);
     931        40913 :     long J = lg(L);
     932        95007 :     for (j = 1; j < J; j++,k++)
     933              :     {
     934        54094 :       gel(v,k) = ZX_copy(gel(L,j));
     935        54094 :       gel(w,k) = e;
     936              :     }
     937              :   }
     938        39555 :   return y;
     939              : }
     940              : 
     941              : /* Factor T in Z[x] */
     942              : static GEN
     943        39562 : ZX_factor_i(GEN T)
     944              : {
     945              :   GEN Q, E, y;
     946              :   long n, i, l, v;
     947              : 
     948        39562 :   if (!signe(T)) return prime_fact(T);
     949        39555 :   v = ZX_valrem(T, &T);
     950        39555 :   Q = ZX_squff(T, &E); l = lg(Q);
     951        79355 :   for (i = 1, n = 0; i < l; i++)
     952              :   {
     953        39800 :     gel(Q,i) = ZX_DDF(gel(Q,i));
     954        39800 :     n += lg(gel(Q,i)) - 1;
     955              :   }
     956        39555 :   if (v)
     957              :   {
     958         1113 :     Q = vec_append(Q, mkvec(pol_x(varn(T))));
     959         1113 :     E = vecsmall_append(E, v); n++;
     960              :   }
     961        39555 :   y = fact_from_DDF(Q, E, n);
     962        39555 :   return sort_factor_pol(y, cmpii);
     963              : }
     964              : GEN
     965        38757 : ZX_factor(GEN x)
     966              : {
     967        38757 :   pari_sp av = avma;
     968        38757 :   return gc_upto(av, ZX_factor_i(x));
     969              : }
     970              : GEN
     971          805 : QX_factor(GEN x)
     972              : {
     973          805 :   pari_sp av = avma;
     974          805 :   return gc_upto(av, ZX_factor_i(Q_primpart(x)));
     975              : }
     976              : 
     977              : long
     978       103076 : ZX_is_irred(GEN x)
     979              : {
     980       103076 :   pari_sp av = avma;
     981       103076 :   long l = lg(x);
     982              :   GEN y;
     983       103076 :   if (l <= 3) return 0; /* degree < 1 */
     984       103076 :   if (l == 4) return 1; /* degree 1 */
     985        99489 :   if (ZX_val(x)) return 0;
     986        99265 :   if (!ZX_is_squarefree(x)) return 0;
     987        99111 :   y = ZX_DDF(x); set_avma(av);
     988        99111 :   return (lg(y) == 2);
     989              : }
     990              : 
     991              : GEN
     992      1878474 : nfrootsQ(GEN x)
     993              : {
     994      1878474 :   pari_sp av = avma;
     995              :   GEN z;
     996              :   long val;
     997              : 
     998      1878474 :   if (typ(x)!=t_POL) pari_err_TYPE("nfrootsQ",x);
     999      1878474 :   if (!signe(x)) pari_err_ROOTS0("nfrootsQ");
    1000      1878474 :   x = Q_primpart(x);
    1001      1878474 :   RgX_check_ZX(x,"nfrootsQ");
    1002      1878474 :   val = ZX_valrem(x, &x);
    1003      1878474 :   z = DDF_roots( ZX_radical(x) );
    1004      1878474 :   if (val) z = vec_append(z, gen_0);
    1005      1878474 :   return gc_upto(av, sort(z));
    1006              : }
    1007              : 
    1008              : /************************************************************************
    1009              :  *                   GCD OVER Z[X] / Q[X]                               *
    1010              :  ************************************************************************/
    1011              : int
    1012       199470 : ZX_is_squarefree(GEN x)
    1013              : {
    1014       199470 :   pari_sp av = avma;
    1015              :   GEN d;
    1016              :   long m;
    1017       199470 :   if (lg(x) == 2) return 0;
    1018       199470 :   m = ZX_deflate_order(x);
    1019       199470 :   if (m > 1)
    1020              :   {
    1021        86817 :     if (!signe(gel(x,2))) return 0;
    1022        86579 :     x = RgX_deflate(x, m);
    1023              :   }
    1024       199232 :   d = ZX_gcd(x,ZX_deriv(x));
    1025       199232 :   return gc_bool(av, lg(d) == 3);
    1026              : }
    1027              : 
    1028              : static int
    1029       122807 : ZX_gcd_filter(GEN *pt_A, GEN *pt_P)
    1030              : {
    1031       122807 :   GEN A = *pt_A, P = *pt_P;
    1032       122807 :   long i, j, l = lg(A), n = 1, d = degpol(gel(A,1));
    1033              :   GEN B, Q;
    1034       251552 :   for (i=2; i<l; i++)
    1035              :   {
    1036       128745 :     long di = degpol(gel(A,i));
    1037       128745 :     if (di==d) n++;
    1038           36 :     else if (d > di)
    1039           36 :     { n=1; d = di; }
    1040              :   }
    1041       122807 :   if (n == l-1)
    1042       122771 :     return 0;
    1043           36 :   B = cgetg(n+1, t_VEC);
    1044           36 :   Q = cgetg(n+1, typ(P));
    1045          156 :   for (i=1, j=1; i<l; i++)
    1046              :   {
    1047          120 :     if (degpol(gel(A,i))==d)
    1048              :     {
    1049           84 :       gel(B,j) = gel(A,i);
    1050           84 :       Q[j] = P[i];
    1051           84 :       j++;
    1052              :     }
    1053              :   }
    1054           36 :   *pt_A = B; *pt_P = Q; return 1;
    1055              : }
    1056              : 
    1057              : static GEN
    1058      3368482 : ZX_gcd_Flx(GEN a, GEN b, ulong g, ulong p)
    1059              : {
    1060      3368482 :   GEN H = Flx_gcd(a, b, p);
    1061      3368482 :   if (!g)
    1062      3335552 :     return Flx_normalize(H, p);
    1063              :   else
    1064              :   {
    1065        32930 :     ulong t = Fl_mul(g, Fl_inv(Flx_lead(H), p), p);
    1066        32930 :     return Flx_Fl_mul(H, t, p);
    1067              :   }
    1068              : }
    1069              : 
    1070              : static GEN
    1071      3356781 : ZX_gcd_slice(GEN A, GEN B, GEN g, GEN P, GEN *mod)
    1072              : {
    1073      3356781 :   pari_sp av = avma;
    1074      3356781 :   long i, n = lg(P)-1;
    1075              :   GEN H, T;
    1076      3356781 :   if (n == 1)
    1077              :   {
    1078      3350576 :     ulong p = uel(P,1), gp = g ? umodiu(g, p): 0;
    1079      3350576 :     GEN a = ZX_to_Flx(A, p), b = ZX_to_Flx(B, p);
    1080      3350576 :     GEN Hp = ZX_gcd_Flx(a, b, gp, p);
    1081      3350576 :     H = gc_upto(av, Flx_to_ZX(Hp));
    1082      3350576 :     *mod = utoi(p);
    1083      3350576 :     return H;
    1084              :   }
    1085         6205 :   T = ZV_producttree(P);
    1086         6205 :   A = ZX_nv_mod_tree(A, P, T);
    1087         6205 :   B = ZX_nv_mod_tree(B, P, T);
    1088         6205 :   g = g ?  Z_ZV_mod_tree(g, P, T): NULL;
    1089         6205 :   H = cgetg(n+1, t_VEC);
    1090        24111 :   for(i=1; i <= n; i++)
    1091              :   {
    1092        17906 :     ulong p = P[i];
    1093        17906 :     GEN a = gel(A,i), b = gel(B,i);
    1094        17906 :     gel(H,i) = ZX_gcd_Flx(a, b, g? g[i]: 0, p);
    1095              :   }
    1096         6205 :   if (ZX_gcd_filter(&H, &P))
    1097           12 :     T = ZV_producttree(P);
    1098         6205 :   H = nxV_chinese_center_tree(H, P, T, ZV_chinesetree(P, T));
    1099         6205 :   *mod = gmael(T, lg(T)-1, 1); return gc_all(av, 2, &H, mod);
    1100              : }
    1101              : 
    1102              : GEN
    1103      3356781 : ZX_gcd_worker(GEN P, GEN A, GEN B, GEN g)
    1104              : {
    1105      3356781 :   GEN V = cgetg(3, t_VEC);
    1106      3356781 :   gel(V,1) = ZX_gcd_slice(A, B, equali1(g)? NULL: g, P, &gel(V,2));
    1107      3356781 :   return V;
    1108              : }
    1109              : 
    1110              : static GEN
    1111       116602 : ZX_gcd_chinese(GEN A, GEN P, GEN *mod)
    1112              : {
    1113       116602 :   ZX_gcd_filter(&A, &P);
    1114       116602 :   return nxV_chinese_center(A, P, mod);
    1115              : }
    1116              : 
    1117              : GEN
    1118     14446712 : ZX_gcd_all(GEN A, GEN B, GEN *Anew)
    1119              : {
    1120     14446712 :   pari_sp av = avma;
    1121     14446712 :   long k, valH, valA, valB, vA = varn(A), dA = degpol(A), dB = degpol(B);
    1122     14446712 :   GEN worker, c, cA, cB, g, Ag, Bg, H = NULL, mod = gen_1, R;
    1123              :   GEN Ap, Bp, Hp;
    1124              :   forprime_t S;
    1125              :   ulong pp;
    1126     14446712 :   if (dA < 0) { if (Anew) *Anew = pol_0(vA); return ZX_copy(B); }
    1127     14446390 :   if (dB < 0) { if (Anew) *Anew = pol_1(vA); return ZX_copy(A); }
    1128     14445165 :   A = Q_primitive_part(A, &cA);
    1129     14445165 :   B = Q_primitive_part(B, &cB);
    1130     14445165 :   valA = ZX_valrem(A, &A); dA -= valA;
    1131     14445165 :   valB = ZX_valrem(B, &B); dB -= valB;
    1132     14445165 :   valH = minss(valA, valB);
    1133     14445165 :   valA -= valH; /* valuation(Anew) */
    1134     14445165 :   c = (cA && cB)? gcdii(cA, cB): NULL; /* content(gcd) */
    1135     14445165 :   if (!dA || !dB)
    1136              :   {
    1137      7327750 :     if (Anew) *Anew = RgX_shift_shallow(A, valA);
    1138      7327750 :     return monomial(c? c: gen_1, valH, vA);
    1139              :   }
    1140      7117415 :   g = gcdii(leading_coeff(A), leading_coeff(B)); /* multiple of lead(gcd) */
    1141      7117415 :   if (is_pm1(g)) {
    1142      6907202 :     g = NULL;
    1143      6907202 :     Ag = A;
    1144      6907202 :     Bg = B;
    1145              :   } else {
    1146       210213 :     Ag = ZX_Z_mul(A,g);
    1147       210213 :     Bg = ZX_Z_mul(B,g);
    1148              :   }
    1149      7117415 :   init_modular_big(&S);
    1150              :   do {
    1151      7117429 :     pp = u_forprime_next(&S);
    1152      7117429 :     Ap = ZX_to_Flx(Ag, pp);
    1153      7117429 :     Bp = ZX_to_Flx(Bg, pp);
    1154      7117429 :   } while (degpol(Ap) != dA || degpol(Bp) != dB);
    1155      7117415 :   if (degpol(Flx_gcd(Ap, Bp, pp)) == 0)
    1156              :   {
    1157      3877678 :     if (Anew) *Anew = RgX_shift_shallow(A, valA);
    1158      3877678 :     return monomial(c? c: gen_1, valH, vA);
    1159              :   }
    1160      3239737 :   worker = snm_closure(is_entry("_ZX_gcd_worker"), mkvec3(A, B, g? g: gen_1));
    1161      3239737 :   av = avma;
    1162      3354370 :   for (k = 1; ;k *= 2)
    1163              :   {
    1164      3354370 :     gen_inccrt_i("ZX_gcd", worker, g, (k+1)>>1, 0, &S, &H, &mod, ZX_gcd_chinese, NULL);
    1165      3354370 :     (void)gc_all(av, 2, &H, &mod);
    1166      3354370 :     Hp = ZX_to_Flx(H, pp);
    1167      3354370 :     if (lgpol(Flx_rem(Ap, Hp, pp)) || lgpol(Flx_rem(Bp, Hp, pp))) continue;
    1168      3243803 :     if (!ZX_divides(Bg, H)) continue;
    1169      3239767 :     R = ZX_divides(Ag, H);
    1170      3239767 :     if (R) break;
    1171              :   }
    1172              :   /* lead(H) = g */
    1173      3239737 :   if (g) H = Q_primpart(H);
    1174      3239737 :   if (c) H = ZX_Z_mul(H,c);
    1175      3239737 :   if (DEBUGLEVEL>5) err_printf("done\n");
    1176      3239737 :   if (Anew)
    1177              :   {
    1178        89937 :     if (g) R = Q_primpart(R);
    1179        89937 :     *Anew = RgX_shift_shallow(R, valA);
    1180              :   }
    1181      3239737 :   return valH? RgX_shift_shallow(H, valH): H;
    1182              : }
    1183              : 
    1184              : #if 0
    1185              : /* ceil( || p ||_oo / lc(p) ) */
    1186              : static GEN
    1187              : maxnorm(GEN p)
    1188              : {
    1189              :   long i, n = degpol(p), av = avma;
    1190              :   GEN x, m = gen_0;
    1191              : 
    1192              :   p += 2;
    1193              :   for (i=0; i<n; i++)
    1194              :   {
    1195              :     x = gel(p,i);
    1196              :     if (abscmpii(x,m) > 0) m = x;
    1197              :   }
    1198              :   m = divii(m, gel(p,n));
    1199              :   return gc_INT(av, addiu(absi_shallow(m),1));
    1200              : }
    1201              : #endif
    1202              : 
    1203              : GEN
    1204     10623726 : ZX_gcd(GEN A, GEN B)
    1205              : {
    1206     10623726 :   pari_sp av = avma;
    1207     10623726 :   return gc_GEN(av, ZX_gcd_all(A,B,NULL));
    1208              : }
    1209              : 
    1210              : GEN
    1211      3170482 : ZX_radical(GEN A) { GEN B; (void)ZX_gcd_all(A,ZX_deriv(A),&B); return B; }
    1212              : 
    1213              : static GEN
    1214        19558 : _gcd(GEN a, GEN b)
    1215              : {
    1216        19558 :   if (!a) a = gen_1;
    1217        19558 :   if (!b) b = gen_1;
    1218        19558 :   return Q_gcd(a,b);
    1219              : }
    1220              : /* A0 and B0 in Q[X] */
    1221              : GEN
    1222        19369 : QX_gcd(GEN A0, GEN B0)
    1223              : {
    1224              :   GEN a, b, D;
    1225        19369 :   pari_sp av = avma, av2;
    1226              : 
    1227        19369 :   D = ZX_gcd(Q_primitive_part(A0, &a), Q_primitive_part(B0, &b));
    1228        19369 :   av2 = avma; a = _gcd(a,b);
    1229        19369 :   if (isint1(a)) set_avma(av2); else D = ZX_Q_mul(D, a);
    1230        19369 :   return gc_upto(av, D);
    1231              : }
    1232              : 
    1233              : /***************************************************************************
    1234              :  ***                                                                     ***
    1235              :  ***                                ZXk/QXk                              ***
    1236              :  ***                                                                     ***
    1237              :  ***************************************************************************/
    1238              : 
    1239              : /* ZXk/QXk: multivariate polynomials in Z[X_1,...,X_k] and Q[X_1,...,X_k] */
    1240              : 
    1241              : INLINE GEN
    1242      4958257 : ZXk_renormalize(GEN x, long lx)    { return ZXX_renormalize(x,lx); }
    1243              : 
    1244              : int
    1245            0 : Rg_is_QXk(GEN z)
    1246              : {
    1247            0 :   long i, t = typ(z), l = lg(z);
    1248            0 :   if (t==t_INT || t==t_FRAC) return 1;
    1249            0 :   if (t!=t_POL) return 0;
    1250            0 :   for (i = 2; i < l; i++)
    1251            0 :     if (!Rg_is_QXk(gel(z,i))) return 0;
    1252            0 :   return 1;
    1253              : }
    1254              : 
    1255              : static GEN
    1256      3214092 : centeri2n(GEN z, long n, GEN N)
    1257              : {
    1258      3214092 :   pari_sp av = avma;
    1259      3214092 :   z = remi2n(z, n);
    1260      3214092 :   if (expi(z)<n-1) return z;
    1261         1253 :   if (signe(z)<0) z = addii(z, N);
    1262          763 :   else            z = subii(z, N);
    1263         1253 :   return gc_INT(av, z);
    1264              : }
    1265              : 
    1266              : static GEN
    1267      4909872 : ZXk_center2n(GEN z, long n, GEN N)
    1268              : {
    1269      4909872 :   if (typ(z) == t_INT)
    1270      3214092 :     return centeri2n(z, n, N);
    1271              :   else
    1272              :   {
    1273              :     long i,l;
    1274      1695780 :     GEN x = cgetg_copy(z, &l);
    1275      1695780 :     x[1] = z[1];
    1276      3403852 :     for (i = 2; i < l; i++)
    1277      1708072 :       gel(x,i) = ZXk_center2n(gel(z,i), n, N);
    1278      1695780 :     return ZXk_renormalize(x, l);
    1279              :   }
    1280              : }
    1281              : 
    1282              : static GEN ZXk_gcd_i(GEN A, GEN B);
    1283              : static GEN
    1284      3444534 : ZXk_content_shallow(GEN x)
    1285              : {
    1286      3444534 :   long i, l = lg(x);
    1287              :   GEN c;
    1288      3444534 :   if (typ(x)==t_INT) return x;
    1289      3444534 :   if (!signe(x)) return gen_0;
    1290      3444534 :   c = gel(x, 2);
    1291      3444534 :   if (gequal1(c)) return gen_1;
    1292      6098025 :   for (i = 3; i < l; i++)
    1293              :   {
    1294      3557357 :     c = simplify_shallow(ZXk_gcd_i(c, gel(x,i)));
    1295      3557357 :     if (gequal1(c)) return gen_1;
    1296              :   }
    1297      2540668 :   return c;
    1298              : }
    1299              : 
    1300              : static GEN ZXk_divexact_s(GEN A, GEN B);
    1301              : 
    1302              : static GEN
    1303      2570537 : ZXkX_ZXk_divexact_s(GEN x, GEN B)
    1304      7608844 : { pari_APPLY_ZX(ZXk_divexact_s(gel(x,i), B)); }
    1305              : 
    1306              : static GEN
    1307      2527823 : ZXkX_ZXk_divexact(GEN A, GEN B)
    1308              : {
    1309      2527823 :   pari_sp av = avma;
    1310      2527823 :   return gc_upto(av, ZXkX_ZXk_divexact_s(A, simplify_shallow(B)));
    1311              : }
    1312              : 
    1313              : static GEN
    1314      2529108 : ZXk_divexact_i(GEN x, GEN y)
    1315              : {
    1316      2529108 :   long dx = degpol(x), dy = degpol(y), dz, i, j;
    1317      2529108 :   GEN z, y_lead = gel(y,dy+2);
    1318      2529108 :   if (dx < dy)
    1319            0 :     return gen_0;
    1320      2529108 :   dz = dx-dy;
    1321      2529108 :   z = cgetg(dz+3,t_POL); z[1] = x[1];
    1322      2529108 :   gel(z,dz+2) = ZXk_divexact_s(gel(x,dx+2), y_lead);
    1323      2544641 :   for (i=dx-1; i>=dy; i--)
    1324              :   {
    1325        15533 :     pari_sp btop = avma;
    1326        15533 :     GEN p1=gel(x,2+i);
    1327        33978 :     for (j=i-dy+1; j<=i && j<=dz; j++)
    1328        18445 :       p1 = gsub(p1, gmul(gel(z,2+j), gel(y,2+i-j)));
    1329        15533 :     gel(z,2+i-dy) = gc_upto(btop, ZXk_divexact_s(p1, y_lead));
    1330              :   }
    1331      2529108 :   return z;
    1332              : }
    1333              : 
    1334              : static GEN
    1335      7582948 : ZXk_divexact_s(GEN A, GEN B)
    1336              : {
    1337      7582948 :   if (!signe(A)) return gen_0;
    1338      5135859 :   if (typ(A)==t_INT && typ(B)==t_INT)
    1339      2564037 :     return diviiexact(A, B);
    1340      2571822 :   else if (typ(B)==t_INT || varn(A)!=varn(B))
    1341        42714 :     return ZXkX_ZXk_divexact_s(A, B);
    1342              :   else
    1343      2529108 :     return ZXk_divexact_i(A, B);
    1344              : }
    1345              : 
    1346              : GEN
    1347            0 : ZXk_divexact(GEN A, GEN B)
    1348              : {
    1349            0 :   pari_sp av = avma;
    1350            0 :   return gc_upto(av, ZXk_divexact_s(A, simplify_shallow(B)));
    1351              : }
    1352              : 
    1353              : static GEN ZXk_divides_s(GEN A, GEN B);
    1354              : 
    1355              : static GEN
    1356      3262477 : ZXkX_ZXk_divides_s(GEN x, GEN B)
    1357              : {
    1358      3262477 :   pari_sp av = avma;
    1359              :   long i, l;
    1360      3262477 :   GEN y = cgetg_copy(x, &l); y[1] = x[1];
    1361      3262477 :   if (l == 2) return y;
    1362      6910239 :   for (i=2; i<l; i++)
    1363              :   {
    1364      3647762 :     GEN c = ZXk_divides_s(gel(x,i), B);
    1365      3647762 :     if (!c) return gc_NULL(av);
    1366      3647762 :     gel(y, i) = c;
    1367              :   }
    1368      3262477 :   return ZXk_renormalize(y, l);
    1369              : }
    1370              : 
    1371              : static GEN
    1372      2789701 : ZXk_divides_i(GEN x, GEN y)
    1373              : {
    1374      2789701 :   pari_sp av = avma, av2;
    1375      2789701 :   long dx = degpol(x), dy = degpol(y), dz, i, j, c;
    1376      2789701 :   GEN z, y_lead = gel(y,dy+2);
    1377      2789701 :   if (dx < dy)
    1378            0 :     return gen_0;
    1379      2789701 :   dz = dx-dy;
    1380      2789701 :   z = cgetg(dz+3,t_POL); z[1] = x[1];
    1381      2789701 :   gel(z,dz+2) = ZXk_divides(gel(x,dx+2), y_lead);
    1382      2789701 :   if (!gel(z,dz+2)) return gc_NULL(av);
    1383      3042765 :   for (i=dx-1; i>=dy; i--)
    1384              :   {
    1385       253078 :     pari_sp btop = avma;
    1386       253078 :     GEN p1 = gel(x,2+i), c;
    1387       514164 :     for (j=i-dy+1; j<=i && j<=dz; j++)
    1388       261086 :       p1 = gsub(p1, gmul(gel(z,2+j), gel(y,2+i-j)));
    1389       253078 :     c = ZXk_divides_s(p1, y_lead);
    1390       253078 :     if (!c) return gc_NULL(av);
    1391       253078 :     gel(z,2+i-dy) = gc_upto(btop, c);
    1392              :   }
    1393      2789687 :   av2 = avma;
    1394      2789687 :   c = gc_bool(av2, gequal(gmul(z,y),x));
    1395      2789687 :   return c ? z: gc_NULL(av);
    1396              : }
    1397              : 
    1398              : static GEN
    1399      3479688 : dividesii(GEN A, GEN B)
    1400              : {
    1401      3479688 :   GEN r, q  = dvmdii(A, B, &r);
    1402      3479688 :   return signe(r) ? NULL: q;
    1403              : }
    1404              : 
    1405              : static GEN
    1406     10118541 : ZXk_divides_s(GEN A, GEN B)
    1407              : {
    1408     10118541 :   if (!signe(A)) return gen_0;
    1409      9531873 :   if (typ(B)==t_INT)
    1410      3479688 :     return typ(A)==t_INT ? dividesii(A, B)
    1411     10221195 :                          : ZXkX_ZXk_divides_s(A, B);
    1412      2790366 :   else if (typ(A)==t_INT) return NULL;
    1413              :   else
    1414              :   {
    1415      2790359 :     long c = varncmp(varn(A),varn(B));
    1416      2790359 :     if (c < 0)
    1417          658 :       return ZXkX_ZXk_divides_s(A, B);
    1418      2789701 :     else if (c>0)
    1419            0 :       return NULL;
    1420              :     else
    1421      2789701 :       return ZXk_divides_i(A, B);
    1422              :   }
    1423              : }
    1424              : 
    1425              : GEN
    1426      6217701 : ZXk_divides(GEN A, GEN B)
    1427              : {
    1428      6217701 :   pari_sp av = avma;
    1429      6217701 :   GEN z = ZXk_divides_s(A, simplify_shallow(B));
    1430      6217701 :   return z ? gc_upto(av, z): z;
    1431              : }
    1432              : 
    1433              : static GEN
    1434      1714007 : rec(GEN g, long e, GEN N, long v)
    1435              : {
    1436      1714007 :   pari_sp av = avma;
    1437      1714007 :   long i, d = (gexpo(g)+2*e-1)/e;
    1438      1714007 :   GEN s = cgetg(d+3,t_POL);
    1439      1714007 :   s[1] = evalvarn(v);
    1440      3201800 :   for (i = 0; i <= d; i++)
    1441              :   {
    1442      3201800 :     GEN c = ZXk_center2n(g, e, N);
    1443      3201800 :     gel(s,i+2) = c;
    1444      3201800 :     g = gmul2n(gsub(g,c),-e);
    1445      3201800 :     if (!signe(g)) break;
    1446              :   }
    1447      1714007 :   s = RgX_renormalize_lg(s,i+3);
    1448      1714007 :   return gc_GEN(av, s);
    1449              : }
    1450              : 
    1451              : static GEN
    1452      8688143 : ZXk_gcd_i(GEN A, GEN B)
    1453              : {
    1454              :   pari_sp av;
    1455              :   long e, v, vc;
    1456              :   GEN c, cA, cB;
    1457      8688143 :   if (signe(A)==0) return gcopy(B);
    1458      5161421 :   if (signe(B)==0) return gcopy(A);
    1459      5159818 :   if (typ(A) == t_INT) return gcdii(A, typ(B)==t_INT ? B: Q_content(B));
    1460      4291561 :   if (typ(B) == t_INT) return gcdii(Q_content(A), B);
    1461      3439067 :   v = varn(A); vc = varncmp(v, varn(B));
    1462      3439067 :   if (vc < 0) return ZXk_gcd_i(ZXk_content_shallow(A), B);
    1463      3427531 :   if (vc > 0) return ZXk_gcd_i(A, ZXk_content_shallow(B));
    1464      3422519 :   if (RgX_is_ZX(A) && RgX_is_ZX(B)) return ZX_gcd(A,B);
    1465      1713993 :   cA = ZXk_content_shallow(A); if (!gequal1(cA)) A = ZXkX_ZXk_divexact(A, cA);
    1466      1713993 :   cB = ZXk_content_shallow(B); if (!gequal1(cB)) B = ZXkX_ZXk_divexact(B, cB);
    1467      1713993 :   c = ZXk_gcd_i(cA, cB); av = avma;
    1468      1713993 :   e = maxss(3, minss(gexpo(A), gexpo(B)) + 2);
    1469           14 :   for ( ; ; e++, set_avma(av))
    1470           14 :   {
    1471      1714007 :     GEN N = int2n(e), G = ZXk_gcd_i(poleval(A,N), poleval(B,N));
    1472      1714007 :     GEN g = Q_primpart(rec(G, e, N, v));
    1473      1714007 :     if (ZXk_divides(A,g) &&  ZXk_divides(B,g))
    1474      1713993 :       return gmul(c,g);
    1475              :   }
    1476              : }
    1477              : GEN
    1478      1686049 : ZXk_gcd(GEN A, GEN B)
    1479      1686049 : { pari_sp av = avma; return gc_upto(av, ZXk_gcd_i(A, B)); }
    1480              : 
    1481              : GEN
    1482          189 : QXk_gcd(GEN A, GEN B)
    1483              : {
    1484              :   GEN a, b, D;
    1485          189 :   pari_sp av = avma, av2;
    1486          189 :   D = ZXk_gcd_i(Q_primitive_part(A, &a), Q_primitive_part(B, &b));
    1487          189 :   av2 = avma; a = _gcd(a,b);
    1488          189 :   if (isint1(a)) set_avma(av2); else D = gmul(D, a);
    1489          189 :   return gc_upto(av, D);
    1490              : }
    1491              : 
    1492              : /*****************************************************************************
    1493              :  * Variants of the Bradford-Davenport algorithm: look for cyclotomic         *
    1494              :  * factors, and decide whether a ZX is cyclotomic or a product of cyclotomic *
    1495              :  *****************************************************************************/
    1496              : /* f of degree 1, return a cyclotomic factor (Phi_1 or Phi_2) or NULL */
    1497              : static GEN
    1498            0 : BD_deg1(GEN f)
    1499              : {
    1500            0 :   GEN a = gel(f,3), b = gel(f,2); /* f = ax + b */
    1501            0 :   if (!absequalii(a,b)) return NULL;
    1502            0 :   return polcyclo((signe(a) == signe(b))? 2: 1, varn(f));
    1503              : }
    1504              : 
    1505              : /* f a squarefree ZX; not divisible by any Phi_n, n even */
    1506              : static GEN
    1507          420 : BD_odd(GEN f)
    1508              : {
    1509          427 :   while(degpol(f) > 1)
    1510              :   {
    1511          420 :     GEN f1 = ZX_graeffe(f); /* contain all cyclotomic divisors of f */
    1512          420 :     if (ZX_equal(f1, f)) return f; /* product of cyclotomics */
    1513            7 :     f = ZX_gcd(f, f1);
    1514              :   }
    1515            7 :   if (degpol(f) == 1) return BD_deg1(f);
    1516            7 :   return NULL; /* no cyclotomic divisor */
    1517              : }
    1518              : 
    1519              : static GEN
    1520         2317 : myconcat(GEN v, GEN x)
    1521              : {
    1522         2317 :   if (typ(x) != t_VEC) x = mkvec(x);
    1523         2317 :   if (!v) return x;
    1524         1470 :   return shallowconcat(v, x);
    1525              : }
    1526              : 
    1527              : /* Bradford-Davenport algorithm.
    1528              :  * f a primitive squarefree ZX of degree > 0, return NULL or a vector of
    1529              :  * coprime cyclotomic factors of f [ possibly reducible ] */
    1530              : static GEN
    1531         2366 : BD(GEN f)
    1532              : {
    1533         2366 :   GEN G = NULL, Gs = NULL, Gp = NULL, Gi = NULL;
    1534              :   GEN fs2, fp, f2, f1, fe, fo, fe1, fo1;
    1535         2366 :   RgX_even_odd(f, &fe, &fo);
    1536         2366 :   fe1 = ZX_eval1(fe);
    1537         2366 :   fo1 = ZX_eval1(fo);
    1538         2366 :   if (absequalii(fe1, fo1)) /* f(1) = 0 or f(-1) = 0 */
    1539              :   {
    1540         1519 :     long i, v = varn(f);
    1541         1519 :     if (!signe(fe1))
    1542          371 :       G = mkvec2(polcyclo(1, v), polcyclo(2, v)); /* both 0 */
    1543         1148 :     else if (signe(fe1) == signe(fo1))
    1544          693 :       G = mkvec(polcyclo(2, v)); /*f(-1) = 0*/
    1545              :     else
    1546          455 :       G = mkvec(polcyclo(1, v)); /*f(1) = 0*/
    1547         3409 :     for (i = lg(G)-1; i; i--) f = RgX_div(f, gel(G,i));
    1548              :   }
    1549              :   /* f no longer divisible by Phi_1 or Phi_2 */
    1550         2366 :   if (degpol(f) <= 1) return G;
    1551         2065 :   f1 = ZX_graeffe(f); /* primitive, has at most square factors */
    1552         2065 :   if (ZX_equal(f1, f)) return myconcat(G,f); /* f = product of Phi_n, n odd */
    1553              : 
    1554         1190 :   fs2 = ZX_gcd_all(f1, ZX_deriv(f1), &f2); /* fs2 squarefree primitive */
    1555         1190 :   if (degpol(fs2))
    1556              :   { /* fs contains all Phi_n | f, 4 | n; and only those */
    1557              :     /* In that case, Graeffe(Phi_n) = Phi_{n/2}^2, and Phi_n = Phi_{n/2}(x^2) */
    1558         1029 :     GEN fs = RgX_inflate(fs2, 2);
    1559         1029 :     (void)ZX_gcd_all(f, fs, &f); /* remove those Phi_n | f, 4 | n */
    1560         1029 :     Gs = BD(fs2);
    1561         1029 :     if (Gs)
    1562              :     {
    1563              :       long i;
    1564         2555 :       for (i = lg(Gs)-1; i; i--) gel(Gs,i) = RgX_inflate(gel(Gs,i), 2);
    1565              :       /* prod Gs[i] is the product of all Phi_n | f, 4 | n */
    1566         1029 :       G = myconcat(G, Gs);
    1567              :     }
    1568              :     /* f2 = f1 / fs2 */
    1569         1029 :     f1 = RgX_div(f2, fs2); /* f1 / fs2^2 */
    1570              :   }
    1571         1190 :   fp = ZX_gcd(f, f1); /* contains all Phi_n | f, n > 1 odd; and only those */
    1572         1190 :   if (degpol(fp))
    1573              :   {
    1574          203 :     Gp = BD_odd(fp);
    1575              :     /* Gp is the product of all Phi_n | f, n odd */
    1576          203 :     if (Gp) G = myconcat(G, Gp);
    1577          203 :     f = RgX_div(f, fp);
    1578              :   }
    1579         1190 :   if (degpol(f))
    1580              :   { /* contains all Phi_n originally dividing f, n = 2 mod 4, n > 2;
    1581              :      * and only those
    1582              :      * In that case, Graeffe(Phi_n) = Phi_{n/2}, and Phi_n = Phi_{n/2}(-x) */
    1583          217 :     Gi = BD_odd(ZX_z_unscale(f, -1));
    1584          217 :     if (Gi)
    1585              :     { /* N.B. Phi_2 does not divide f */
    1586          210 :       Gi = ZX_z_unscale(Gi, -1);
    1587              :       /* Gi is the product of all Phi_n | f, n = 2 mod 4 */
    1588          210 :       G = myconcat(G, Gi);
    1589              :     }
    1590              :   }
    1591         1190 :   return G;
    1592              : }
    1593              : 
    1594              : /* Let f be a nonzero QX, return the (squarefree) product of cyclotomic
    1595              :  * divisors of f */
    1596              : GEN
    1597          322 : polcyclofactors(GEN f)
    1598              : {
    1599          322 :   pari_sp av = avma;
    1600          322 :   if (typ(f) != t_POL || !signe(f)) pari_err_TYPE("polcyclofactors",f);
    1601          322 :   (void)RgX_valrem(f, &f);
    1602          322 :   f = Q_primpart(f);
    1603          322 :   RgX_check_ZX(f,"polcyclofactors");
    1604          322 :   if (degpol(f))
    1605              :   {
    1606          322 :     f = BD(ZX_radical(f));
    1607          322 :     if (f) return gc_GEN(av, f);
    1608              :   }
    1609            0 :   retgc_const(av, cgetg(1, t_VEC));
    1610              : }
    1611              : 
    1612              : /* list of all squarefree odd x such that phi(x) = n, P^-(x) > m. Unsorted */
    1613              : static GEN
    1614        19659 : invphi(ulong n, ulong m)
    1615              : {
    1616              :   GEN C, D;
    1617              :   long l, i;
    1618        19659 :   if (n == 1) return mkvecsmall(1);
    1619        14383 :   D = divisorsu(n); l = lg(D);
    1620        14383 :   C = cgetg(1, t_VECSMALL);
    1621        39990 :   for (i = 2; i < l; i++) /* skip 1 */
    1622              :   {
    1623        25607 :     ulong d = D[i], p;
    1624        25607 :     if (d < m) continue;
    1625        20398 :     p = d + 1; if (!uisprime(p)) continue;
    1626        10596 :     C = vecsmall_concat(C, zv_z_mul(invphi(D[l-i], p), p));
    1627              :   }
    1628        14383 :   return C;
    1629              : }
    1630              : 
    1631              : long
    1632        99218 : poliscyclo(GEN f)
    1633              : {
    1634        99218 :   const ulong p = 2147483647; /* prime */
    1635              :   pari_sp av;
    1636              :   long i, n, e, l;
    1637              :   ulong f3, fm3;
    1638              :   GEN D, fp, _3;
    1639        99218 :   if (typ(f) != t_POL) pari_err_TYPE("poliscyclo", f);
    1640        99211 :   n = degpol(f);
    1641        99211 :   if (n <= 0 || !RgX_is_ZX(f)) return 0;
    1642        99204 :   if (!equali1(gel(f,n+2)) || !is_pm1(gel(f,2))) return 0;
    1643         9168 :   if (n == 1) return signe(gel(f,2)) > 0? 2: 1;
    1644         9063 :   av = avma;
    1645         9063 :   f = ZX_deflate_max(f, &e); if (e != 1) n = degpol(f);
    1646         9063 :   D = invphi(n, 1); /* squareefree odd d s.t. phi(d) = n */
    1647         9063 :   l = lg(D); _3 = gmodulss(3, p);
    1648         9063 :   fp = ZX_to_Flx(f, p);
    1649         9063 :   f3 = Flx_eval(fp, 3, p);
    1650         9063 :   fm3 = Flx_eval(fp, p-3, p);
    1651              :   /* f(x^e) is cyclotomic (= Phi_{de}) iff f = Phi_d, where all prime dividing
    1652              :    * e also divide d. */
    1653        11847 :   for (i = 1; i < l; i++)
    1654              :   {
    1655         5143 :     long d = D[i]; /* squarefree odd */
    1656         5143 :     if (odd(e))
    1657              :     {
    1658         4092 :       if (e == 1 || u_ppo(e, d) == 1)
    1659              :       { /* early abort: check whether f(3) = Phi_d(3) or Phi_2d(3) = Phi_d(-3)
    1660              :          * mod p before checking in Z. N.B. phi(d) and value at 3 mod p
    1661              :          * determine Phi_d for all d <= 10^7 */
    1662         3861 :         ulong F3 = Rg_to_Fl(polcyclo_eval(d, _3), p);
    1663         3861 :         if (F3 == f3 && ZX_equal(f, polcyclo(d, varn(f))))
    1664         1029 :           return gc_long(av, d * e);
    1665         2832 :         if (F3 == fm3 && ZX_equal(f, polcyclo(2*d, varn(f))))
    1666          749 :           return gc_long(av, 2* d * e);
    1667              :       }
    1668              :     }
    1669              :     else
    1670              :     {
    1671         1051 :       if (u_ppo(e, 2*d) == 1)
    1672              :       { /* early abort: check whether f(3) = Phi_2d(3) mod p */
    1673         1044 :         ulong F3 = Rg_to_Fl(polcyclo_eval(2*d, _3), p);
    1674         1044 :         if (F3 == f3 && ZX_equal(f, polcyclo(2*d, varn(f))))
    1675          581 :           return gc_long(av, 2* d * e);
    1676              :       }
    1677              :     }
    1678              :   }
    1679         6704 :   return gc_long(av, 0);
    1680              : }
    1681              : 
    1682              : long
    1683         1029 : poliscycloprod(GEN f)
    1684              : {
    1685         1029 :   pari_sp av = avma;
    1686         1029 :   long i, d = degpol(f);
    1687         1029 :   if (typ(f) != t_POL) pari_err_TYPE("poliscycloprod",f);
    1688         1029 :   if (!RgX_is_ZX(f)) return 0;
    1689         1029 :   if (!ZX_is_monic(f) || !is_pm1(constant_coeff(f))) return 0;
    1690         1029 :   if (d < 2) return (d == 1);
    1691         1022 :   if ( degpol(ZX_gcd_all(f, ZX_deriv(f), &f)) )
    1692              :   {
    1693           14 :     d = degpol(f);
    1694           14 :     if (d == 1) return 1;
    1695              :   }
    1696         1015 :   f = BD(f); if (!f) return 0;
    1697         3619 :   for (i = lg(f)-1; i; i--) d -= degpol(gel(f,i));
    1698         1015 :   return gc_long(av, d == 0);
    1699              : }
        

Generated by: LCOV version 2.0-1