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) Hit Total Coverage
Test: PARI/GP v2.18.1 lcov report (development 30702-bddb8d6928) Lines: 912 954 95.6 %
Date: 2026-02-23 02:23:56 Functions: 61 64 95.3 %
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     4757973 : 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     4757973 :   dy=degpol(y);
      29     4757973 :   dx=degpol(x);
      30     4757973 :   dz=dx-dy; if (dz<0) return NULL;
      31     4757061 :   z=cgetg(dz+3,t_POL); z[1] = x[1];
      32     4757061 :   x += 2; y += 2; z += 2;
      33     4757061 :   y_lead = gel(y,dy);
      34     4757061 :   if (equali1(y_lead)) y_lead = NULL;
      35             : 
      36     4757061 :   p1 = gel(x,dx);
      37     4757061 :   if (y_lead) {
      38             :     GEN r;
      39       29438 :     p1 = dvmdii(p1,y_lead, &r);
      40       29438 :     if (r != gen_0) return NULL;
      41             :   }
      42     4727623 :   else p1 = icopy(p1);
      43     4753469 :   gel(z,dz) = p1;
      44     6108884 :   for (i=dx-1; i>=dy; i--)
      45             :   {
      46     1359835 :     av = avma; p1 = gel(x,i);
      47     4746606 :     for (j=i-dy+1; j<=i && j<=dz; j++)
      48     3386771 :       p1 = subii(p1, mulii(gel(z,j),gel(y,i-j)));
      49     1359835 :     if (y_lead) {
      50             :       GEN r;
      51       52431 :       p1 = dvmdii(p1,y_lead, &r);
      52       52431 :       if (r != gen_0) return NULL;
      53             :     }
      54     1358577 :     if (B && abscmpii(p1, B) > 0) return NULL;
      55     1355415 :     p1 = gc_INT(av, p1);
      56     1355415 :     gel(z,i-dy) = p1;
      57             :   }
      58     4749049 :   av = avma;
      59    12466168 :   for (; i >= 0; i--)
      60             :   {
      61     7748098 :     p1 = gel(x,i);
      62             :     /* we always enter this loop at least once */
      63    17654755 :     for (j=0; j<=i && j<=dz; j++)
      64     9906657 :       p1 = subii(p1, mulii(gel(z,j),gel(y,i-j)));
      65     7748098 :     if (signe(p1)) return NULL;
      66     7717119 :     set_avma(av);
      67             :   }
      68     4718070 :   return z - 2;
      69             : }
      70             : static GEN
      71     4732774 : 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       52221 : Mignotte_bound(GEN S)
     110             : {
     111       52221 :   long i, d = degpol(S);
     112       52221 :   GEN C, N2, t, binlS, lS = leading_coeff(S), bin = vecbinomial(d-1);
     113             : 
     114       52221 :   N2 = sqrtr(RgX_fpnorml2(S,DEFAULTPREC));
     115       52221 :   binlS = is_pm1(lS)? bin: ZC_Z_mul(bin, lS);
     116             : 
     117             :   /* i = 0 */
     118       52221 :   C = gel(binlS,1);
     119             :   /* i = d */
     120       52221 :   t = N2; if (gcmp(C, t) < 0) C = t;
     121      446972 :   for (i = 1; i < d; i++)
     122             :   {
     123      394751 :     t = addri(mulir(gel(bin,i), N2), gel(binlS,i+1));
     124      394751 :     if (mpcmp(C, t) < 0) C = t;
     125             :   }
     126       52221 :   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       52221 : Beauzamy_bound(GEN S)
     132             : {
     133       52221 :   const long prec = DEFAULTPREC;
     134       52221 :   long i, d = degpol(S);
     135             :   GEN bin, lS, s, C;
     136       52221 :   bin = vecbinomial(d);
     137             : 
     138       52221 :   s = real_0(prec);
     139      551414 :   for (i=0; i<=d; i++)
     140             :   {
     141      499193 :     GEN c = gel(S,i+2);
     142      499193 :     if (gequal0(c)) continue;
     143             :     /* s += P_i^2 / binomial(d,i) */
     144      419328 :     s = addrr(s, divri(itor(sqri(c), prec), gel(bin,i+1)));
     145             :   }
     146             :   /* s = [S]_2^2 */
     147       52221 :   C = powruhalf(utor(3,prec), 3 + 2*d); /* 3^{3/2 + d} */
     148       52221 :   C = divrr(mulrr(C, s), mulur(4*d, mppi(prec)));
     149       52221 :   lS = absi_shallow(leading_coeff(S));
     150       52221 :   return mulir(lS, sqrtr(C));
     151             : }
     152             : 
     153             : static GEN
     154       52221 : factor_bound(GEN S)
     155             : {
     156       52221 :   pari_sp av = avma;
     157       52221 :   GEN a = Mignotte_bound(S);
     158       52221 :   GEN b = Beauzamy_bound(S);
     159       52221 :   if (DEBUGLEVEL>2)
     160             :   {
     161           0 :     err_printf("Mignotte bound: %Ps\n",a);
     162           0 :     err_printf("Beauzamy bound: %Ps\n",b);
     163             :   }
     164       52221 :   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       43224 : cmbf(GEN pol, GEN famod, GEN bound, GEN p, long a, long b,
     176             :      long klim, long *pmaxK, int *done)
     177             : {
     178       43224 :   long K = 1, cnt = 1, i,j,k, curdeg, lfamod = lg(famod)-1;
     179             :   ulong spa_b, spa_bs2, Sbound;
     180       43224 :   GEN lc, lcpol, pa = powiu(p,a), pas2 = shifti(pa,-1);
     181       43224 :   GEN trace1   = cgetg(lfamod+1, t_VECSMALL);
     182       43224 :   GEN trace2   = cgetg(lfamod+1, t_VECSMALL);
     183       43224 :   GEN ind      = cgetg(lfamod+1, t_VECSMALL);
     184       43224 :   GEN deg      = cgetg(lfamod+1, t_VECSMALL);
     185       43224 :   GEN degsofar = cgetg(lfamod+1, t_VECSMALL);
     186       43224 :   GEN listmod  = cgetg(lfamod+1, t_VEC);
     187       43224 :   GEN fa       = cgetg(lfamod+1, t_VEC);
     188             : 
     189       43224 :   *pmaxK = cmbf_maxK(lfamod);
     190       43224 :   lc = absi_shallow(leading_coeff(pol));
     191       43224 :   if (equali1(lc)) lc = NULL;
     192       43224 :   lcpol = lc? ZX_Z_mul(pol, lc): pol;
     193             : 
     194             :   {
     195       43224 :     GEN pa_b,pa_bs2,pb, lc2 = lc? sqri(lc): NULL;
     196             : 
     197       43224 :     pa_b = powiu(p, a-b); /* < 2^31 */
     198       43224 :     pa_bs2 = shifti(pa_b,-1);
     199       43224 :     pb= powiu(p, b);
     200      152606 :     for (i=1; i <= lfamod; i++)
     201             :     {
     202      109382 :       GEN T1,T2, P = gel(famod,i);
     203      109382 :       long d = degpol(P);
     204             : 
     205      109382 :       deg[i] = d; P += 2;
     206      109382 :       T1 = gel(P,d-1);/* = - S_1 */
     207      109382 :       T2 = sqri(T1);
     208      109382 :       if (d > 1) T2 = subii(T2, shifti(gel(P,d-2),1));
     209      109382 :       T2 = modii(T2, pa); /* = S_2 Newton sum */
     210      109382 :       if (lc)
     211             :       {
     212        3590 :         T1 = Fp_mul(lc, T1, pa);
     213        3590 :         T2 = Fp_mul(lc2,T2, pa);
     214             :       }
     215      109382 :       uel(trace1,i) = itou(diviiround(T1, pb));
     216      109382 :       uel(trace2,i) = itou(diviiround(T2, pb));
     217             :     }
     218       43224 :     spa_b   = uel(pa_b,2); /* < 2^31 */
     219       43224 :     spa_bs2 = uel(pa_bs2,2); /* < 2^31 */
     220             :   }
     221       43224 :   degsofar[0] = 0; /* sentinel */
     222             : 
     223             :   /* ind runs through strictly increasing sequences of length K,
     224             :    * 1 <= ind[i] <= lfamod */
     225       78334 : nextK:
     226       78334 :   if (K > *pmaxK || 2*K > lfamod) goto END;
     227       47994 :   if (DEBUGLEVEL > 3)
     228           0 :     err_printf("\n### K = %d, %Ps combinations\n", K,binomial(utoipos(lfamod), K));
     229       47994 :   setlg(ind, K+1); ind[1] = 1;
     230       47994 :   Sbound = (ulong) ((K+1)>>1);
     231       47994 :   i = 1; curdeg = deg[ind[1]];
     232             :   for(;;)
     233             :   { /* try all combinations of K factors */
     234      534277 :     for (j = i; j < K; j++)
     235             :     {
     236       73672 :       degsofar[j] = curdeg;
     237       73672 :       ind[j+1] = ind[j]+1; curdeg += deg[ind[j+1]];
     238             :     }
     239      460605 :     if (curdeg <= klim) /* trial divide */
     240        8991 :     {
     241             :       GEN y, q, list;
     242             :       pari_sp av;
     243             :       ulong t;
     244             : 
     245             :       /* d - 1 test */
     246     1159926 :       for (t=uel(trace1,ind[1]),i=2; i<=K; i++)
     247      699321 :         t = Fl_add(t, uel(trace1,ind[i]), spa_b);
     248      460605 :       if (t > spa_bs2) t = spa_b - t;
     249      460605 :       if (t > Sbound)
     250             :       {
     251      366114 :         if (DEBUGLEVEL>6) err_printf(".");
     252      366114 :         goto NEXT;
     253             :       }
     254             :       /* d - 2 test */
     255      203739 :       for (t=uel(trace2,ind[1]),i=2; i<=K; i++)
     256      109248 :         t = Fl_add(t, uel(trace2,ind[i]), spa_b);
     257       94491 :       if (t > spa_bs2) t = spa_b - t;
     258       94491 :       if (t > Sbound)
     259             :       {
     260       50153 :         if (DEBUGLEVEL>6) err_printf("|");
     261       50153 :         goto NEXT;
     262             :       }
     263             : 
     264       44338 :       av = avma;
     265             :       /* check trailing coeff */
     266       44338 :       y = lc;
     267      129925 :       for (i=1; i<=K; i++)
     268             :       {
     269       85587 :         GEN q = constant_coeff(gel(famod,ind[i]));
     270       85587 :         if (y) q = mulii(y, q);
     271       85587 :         y = centermodii(q, pa, pas2);
     272             :       }
     273       44338 :       if (!signe(y) || !dvdii(constant_coeff(lcpol), y))
     274             :       {
     275       19277 :         if (DEBUGLEVEL>3) err_printf("T");
     276       19277 :         set_avma(av); goto NEXT;
     277             :       }
     278       25061 :       y = lc; /* full computation */
     279       55915 :       for (i=1; i<=K; i++)
     280             :       {
     281       30854 :         GEN q = gel(famod,ind[i]);
     282       30854 :         if (y) q = gmul(y, q);
     283       30854 :         y = centermod_i(q, pa, pas2);
     284             :       }
     285             : 
     286             :       /* y is the candidate factor */
     287       25061 :       if (! (q = ZX_divides_i(lcpol,y,bound)) )
     288             :       {
     289        3186 :         if (DEBUGLEVEL>3) err_printf("*");
     290        3186 :         set_avma(av); goto NEXT;
     291             :       }
     292             :       /* found a factor */
     293       21875 :       list = cgetg(K+1, t_VEC);
     294       21875 :       gel(listmod,cnt) = list;
     295       44359 :       for (i=1; i<=K; i++) list[i] = famod[ind[i]];
     296             : 
     297       21875 :       y = Q_primpart(y);
     298       21875 :       gel(fa,cnt++) = y;
     299             :       /* fix up pol */
     300       21875 :       pol = q;
     301       21875 :       if (lc) pol = Q_div_to_int(pol, leading_coeff(y));
     302       80675 :       for (i=j=k=1; i <= lfamod; i++)
     303             :       { /* remove used factors */
     304       58800 :         if (j <= K && i == ind[j]) j++;
     305             :         else
     306             :         {
     307       36316 :           gel(famod,k) = gel(famod,i);
     308       36316 :           uel(trace1,k) = uel(trace1,i);
     309       36316 :           uel(trace2,k) = uel(trace2,i);
     310       36316 :           deg[k] = deg[i]; k++;
     311             :         }
     312             :       }
     313       21875 :       lfamod -= K;
     314       21875 :       *pmaxK = cmbf_maxK(lfamod);
     315       21875 :       if (lfamod < 2*K) goto END;
     316        8991 :       i = 1; curdeg = deg[ind[1]];
     317        8991 :       bound = factor_bound(pol);
     318        8991 :       if (lc) lc = absi_shallow(leading_coeff(pol));
     319        8991 :       lcpol = lc? ZX_Z_mul(pol, lc): pol;
     320        8991 :       if (DEBUGLEVEL>3)
     321           0 :         err_printf("\nfound factor %Ps\nremaining modular factor(s): %ld\n",
     322             :                    y, lfamod);
     323        8991 :       continue;
     324             :     }
     325             : 
     326           0 : NEXT:
     327      438730 :     for (i = K+1;;)
     328             :     {
     329      546903 :       if (--i == 0) { K++; goto nextK; }
     330      511793 :       if (++ind[i] <= lfamod - K + i)
     331             :       {
     332      403620 :         curdeg = degsofar[i-1] + deg[ind[i]];
     333      403620 :         if (curdeg <= klim) break;
     334             :       }
     335             :     }
     336             :   }
     337       43224 : END:
     338       43224 :   *done = 1;
     339       43224 :   if (degpol(pol) > 0)
     340             :   { /* leftover factor */
     341       43224 :     if (signe(leading_coeff(pol)) < 0) pol = ZX_neg(pol);
     342       43224 :     if (lfamod >= 2*K) *done = 0;
     343             : 
     344       43224 :     setlg(famod, lfamod+1);
     345       43224 :     gel(listmod,cnt) = leafcopy(famod);
     346       43224 :     gel(fa,cnt++) = pol;
     347             :   }
     348       43224 :   if (DEBUGLEVEL>6) err_printf("\n");
     349       43224 :   setlg(listmod, cnt);
     350       43224 :   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      147188 : shifteval(GEN Q, long n)
     358             : {
     359      147188 :   pari_sp av = avma;
     360      147188 :   long i, l = lg(Q);
     361             :   GEN s;
     362             : 
     363      147188 :   if (!signe(Q)) return gen_0;
     364      147188 :   s = gel(Q,l-1);
     365      799095 :   for (i = l-2; i > 1; i--)
     366             :   {
     367      651907 :     s = addii(gel(Q,i), shifti(s, n));
     368      651907 :     if (gc_needed(av,1)) s = gc_INT(av, s);
     369             :   }
     370      147188 :   return s;
     371             : }
     372             : 
     373             : /* return integer y such that all |a| <= y if P(a) = 0 */
     374             : static GEN
     375       88747 : root_bound(GEN P0)
     376             : {
     377       88747 :   GEN Q = leafcopy(P0), lP = absi_shallow(leading_coeff(Q)), x,y,z;
     378       88747 :   long k, d = degpol(Q);
     379             : 
     380             :   /* P0 = lP x^d + Q, deg Q < d */
     381       88747 :   Q = normalizepol_lg(Q, d+2);
     382      568831 :   for (k=lg(Q)-1; k>1; k--) gel(Q,k) = absi_shallow(gel(Q,k));
     383       88747 :   k = (long)(fujiwara_bound(P0));
     384      147896 :   for (  ; k >= 0; k--)
     385             :   {
     386      147188 :     pari_sp av = avma;
     387             :     /* y = 2^k; Q(y) >= lP y^d ? */
     388      147188 :     if (cmpii(shifteval(Q,k), shifti(lP, d*k)) >= 0) break;
     389       59149 :     set_avma(av);
     390             :   }
     391       88747 :   if (k < 0) k = 0;
     392       88747 :   y = int2n(k+1);
     393       88747 :   if (d > 2000) return y; /* likely to be expensive, don't bother */
     394       88747 :   x = int2n(k);
     395       88747 :   for(k=0; ; k++)
     396             :   {
     397      471712 :     z = shifti(addii(x,y), -1);
     398      471712 :     if (equalii(x,z) || k > 5) break;
     399      382965 :     if (cmpii(ZX_Z_eval(Q,z), mulii(lP, powiu(z, d))) < 0)
     400      205405 :       y = z;
     401             :     else
     402      177560 :       x = z;
     403             :   }
     404       88747 :   return y;
     405             : }
     406             : 
     407             : GEN
     408         290 : chk_factors_get(GEN lt, GEN famod, GEN c, GEN T, GEN N)
     409             : {
     410         290 :   long i = 1, j, l = lg(famod);
     411         290 :   GEN V = cgetg(l, t_VEC);
     412        7078 :   for (j = 1; j < l; j++)
     413        6788 :     if (signe(gel(c,j))) gel(V,i++) = gel(famod,j);
     414         290 :   if (lt && i > 1) gel(V,1) = RgX_Rg_mul(gel(V,1), lt);
     415         290 :   setlg(V, i);
     416         290 :   return T? FpXQXV_prod(V, T, N): FpXV_prod(V,N);
     417             : }
     418             : 
     419             : static GEN
     420         118 : chk_factors(GEN P, GEN M_L, GEN bound, GEN famod, GEN pa)
     421             : {
     422             :   long i, r;
     423         118 :   GEN pol = P, list, piv, y, ltpol, lt, paov2;
     424             : 
     425         118 :   piv = ZM_hnf_knapsack(M_L);
     426         118 :   if (!piv) return NULL;
     427          60 :   if (DEBUGLEVEL>7) err_printf("ZM_hnf_knapsack output:\n%Ps\n",piv);
     428             : 
     429          60 :   r  = lg(piv)-1;
     430          60 :   list = cgetg(r+1, t_VEC);
     431          60 :   lt = absi_shallow(leading_coeff(pol));
     432          60 :   if (equali1(lt)) lt = NULL;
     433          60 :   ltpol = lt? ZX_Z_mul(pol, lt): pol;
     434          60 :   paov2 = shifti(pa,-1);
     435          60 :   for (i = 1;;)
     436             :   {
     437         138 :     if (DEBUGLEVEL) err_printf("LLL_cmbf: checking factor %ld\n",i);
     438         138 :     y = chk_factors_get(lt, famod, gel(piv,i), NULL, pa);
     439         138 :     y = FpX_center_i(y, pa, paov2);
     440         138 :     if (! (pol = ZX_divides_i(ltpol,y,bound)) ) return NULL;
     441         114 :     if (lt) y = Q_primpart(y);
     442         114 :     gel(list,i) = y;
     443         114 :     if (++i >= r) break;
     444             : 
     445          78 :     if (lt)
     446             :     {
     447          30 :       pol = ZX_Z_divexact(pol, leading_coeff(y));
     448          30 :       lt = absi_shallow(leading_coeff(pol));
     449          30 :       ltpol = ZX_Z_mul(pol, lt);
     450             :     }
     451             :     else
     452          48 :       ltpol = pol;
     453             :   }
     454          36 :   y = Q_primpart(pol);
     455          36 :   gel(list,i) = y; return list;
     456             : }
     457             : 
     458             : GEN
     459        1297 : 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        1297 :   if (DEBUGLEVEL>2) timer_start(&T);
     466        1297 :   u = ZM_lll_norms(m, final? 0.999: 0.75, LLL_INPLACE | LLL_NOFLATTER, &norm);
     467        1297 :   if (DEBUGLEVEL>2) *ti_LLL += timer_delay(&T);
     468        8657 :   for (R=lg(m)-1; R > 0; R--)
     469        8657 :     if (cmprr(gel(norm,R), Bnorm) < 0) break;
     470       13669 :   for (i=1; i<=R; i++) setlg(u[i], n0+1);
     471        1297 :   if (R <= 1)
     472             :   {
     473          89 :     if (!R) pari_err_BUG("LLL_cmbf [no factor]");
     474          89 :     return NULL; /* irreducible */
     475             :   }
     476        1208 :   setlg(u, R+1); return u;
     477             : }
     478             : 
     479             : static ulong
     480          12 : next2pow(ulong a)
     481             : {
     482          12 :   ulong b = 1;
     483          96 :   while (b < a) b <<= 1;
     484          12 :   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         107 : LLL_cmbf(GEN P, GEN famod, GEN p, GEN pa, GEN bound, long a, long rec)
     496             : {
     497         107 :   const long N0 = 1; /* # of traces added at each step */
     498         107 :   double BitPerFactor = 0.4; /* nb bits in p^(a-b) / modular factor */
     499         107 :   long i,j,tmax,n0,C, dP = degpol(P);
     500         107 :   double logp = log((double)itos(p)), LOGp2 = M_LN2/logp;
     501         107 :   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         107 :   long ti_LLL = 0, ti_CF  = 0;
     505             : 
     506         107 :   lP = absi_shallow(leading_coeff(P));
     507         107 :   if (equali1(lP)) lP = NULL;
     508         107 :   Br = root_bound(P);
     509         107 :   if (lP) Br = mulii(lP, Br);
     510         107 :   logBr = dbllog2(Br) * LOGp2; /* log_p Br */
     511             : 
     512         107 :   n0 = lg(famod) - 1;
     513         107 :   C = (long)ceil( sqrt(N0 * n0 / 4.) ); /* > 1 */
     514         107 :   Bnorm = dbltor(n0 * (C*C + N0*n0/4.) * 1.00001);
     515         107 :   ZERO = zeromat(n0, N0);
     516             : 
     517         107 :   av = avma;
     518         107 :   TT = cgetg(n0+1, t_VEC);
     519         107 :   Tra  = cgetg(n0+1, t_MAT);
     520        2046 :   for (i=1; i<=n0; i++)
     521             :   {
     522        1939 :     gel(TT,i)  = NULL;
     523        1939 :     gel(Tra,i) = cgetg(N0+1, t_COL);
     524             :   }
     525         107 :   CM_L = scalarmat_s(C, n0);
     526             :   /* tmax = current number of traces used (and computed so far) */
     527         107 :   for (tmax = 0;; tmax += N0)
     528         397 :   {
     529         504 :     long b, bmin, bgood, delta, tnew = tmax + N0, r = lg(CM_L)-1;
     530             :     GEN M_L, q, CM_Lp, oldCM_L;
     531         504 :     int first = 1;
     532             :     pari_timer ti2, TI;
     533             : 
     534         504 :     bmin = (long)ceil(b0 + tnew*logBr);
     535         504 :     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         504 :     if (a <= bmin)
     541             :     {
     542          12 :       a = (long)ceil(bmin + 3*N0*logBr) + 1; /* enough for 3 more rounds */
     543          12 :       a = (long)next2pow((ulong)a);
     544             : 
     545          12 :       pa = powiu(p,a);
     546          12 :       famod = ZpX_liftfact(P, famod, pa, p, a);
     547         228 :       for (i=1; i<=n0; i++) gel(TT,i) = NULL;
     548             :     }
     549        9834 :     for (i=1; i<=n0; i++)
     550             :     {
     551        9330 :       GEN p1 = gel(Tra,i);
     552        9330 :       GEN p2 = polsym_gen(gel(famod,i), gel(TT,i), tnew, NULL, pa);
     553        9330 :       gel(TT,i) = p2;
     554        9330 :       p2 += 1+tmax; /* ignore traces number 0...tmax */
     555       18660 :       for (j=1; j<=N0; j++) gel(p1,j) = gel(p2,j);
     556        9330 :       if (lP)
     557             :       { /* make Newton sums integral */
     558        1584 :         GEN lPpow = powiu(lP, tmax);
     559        3168 :         for (j=1; j<=N0; j++)
     560             :         {
     561        1584 :           lPpow = mulii(lPpow,lP);
     562        1584 :           gel(p1,j) = mulii(gel(p1,j), lPpow);
     563             :         }
     564             :       }
     565             :     }
     566             : 
     567             :     /* compute truncation parameter */
     568         504 :     if (DEBUGLEVEL>2) { timer_start(&ti2); timer_start(&TI); }
     569         504 :     oldCM_L = CM_L;
     570         504 :     av2 = avma;
     571         504 :     delta = b = 0; /* -Wall */
     572         907 : AGAIN:
     573         907 :     M_L = Q_div_to_int(CM_L, utoipos(C));
     574         907 :     T2 = centermod( ZM_mul(Tra, M_L), pa );
     575         907 :     if (first)
     576             :     { /* initialize lattice, using few p-adic digits for traces */
     577         504 :       double t = gexpo(T2) - maxdd(32.0, BitPerFactor*r);
     578         504 :       bgood = (long) (t * LOGp2);
     579         504 :       b = maxss(bmin, bgood);
     580         504 :       delta = a - b;
     581             :     }
     582             :     else
     583             :     { /* add more p-adic digits and continue reduction */
     584         403 :       long b0 = (long)(gexpo(T2) * LOGp2);
     585         403 :       if (b0 < b) b = b0;
     586         403 :       b = maxss(b-delta, bmin);
     587         403 :       if (b - delta/2 < bmin) b = bmin; /* near there. Go all the way */
     588             :     }
     589             : 
     590         907 :     q = powiu(p, b);
     591         907 :     m = vconcat( CM_L, gdivround(T2, q) );
     592         907 :     if (first)
     593             :     {
     594         504 :       GEN P1 = scalarmat(powiu(p, a-b), N0);
     595         504 :       first = 0;
     596         504 :       m = shallowconcat( m, vconcat(ZERO, P1) );
     597             :       /*     [ C M_L        0     ]
     598             :        * m = [                    ]   square matrix
     599             :        *     [  T2'  p^(a-b) I_N0 ]   T2' = Tra * M_L  truncated
     600             :        */
     601             :     }
     602             : 
     603         907 :     CM_L = LLL_check_progress(Bnorm, n0, m, b == bmin, /*dbg:*/ &ti_LLL);
     604         907 :     if (DEBUGLEVEL>2)
     605           0 :       err_printf("LLL_cmbf: (a,b) =%4ld,%4ld; r =%3ld -->%3ld, time = %ld\n",
     606           0 :                  a,b, lg(m)-1, CM_L? lg(CM_L)-1: 1, timer_delay(&TI));
     607         907 :     if (!CM_L) { list = mkvec(P); break; }
     608         836 :     if (b > bmin)
     609             :     {
     610         403 :       CM_L = gc_GEN(av2, CM_L);
     611         403 :       goto AGAIN;
     612             :     }
     613         433 :     if (DEBUGLEVEL>2) timer_printf(&ti2, "for this block of traces");
     614             : 
     615         433 :     i = lg(CM_L) - 1;
     616         433 :     if (i == r && ZM_equal(CM_L, oldCM_L))
     617             :     {
     618          54 :       CM_L = oldCM_L;
     619          54 :       set_avma(av2); continue;
     620             :     }
     621             : 
     622         379 :     CM_Lp = FpM_image(CM_L, utoipos(27449)); /* inexpensive test */
     623         379 :     if (lg(CM_Lp) != lg(CM_L))
     624             :     {
     625           6 :       if (DEBUGLEVEL>2) err_printf("LLL_cmbf: rank decrease\n");
     626           6 :       CM_L = ZM_hnf(CM_L);
     627             :     }
     628             : 
     629         379 :     if (i <= r && i*rec < n0)
     630             :     {
     631             :       pari_timer ti;
     632         118 :       if (DEBUGLEVEL>2) timer_start(&ti);
     633         118 :       list = chk_factors(P, Q_div_to_int(CM_L,utoipos(C)), bound, famod, pa);
     634         118 :       if (DEBUGLEVEL>2) ti_CF += timer_delay(&ti);
     635         118 :       if (list) break;
     636          82 :       if (DEBUGLEVEL>2) err_printf("LLL_cmbf: chk_factors failed");
     637             :     }
     638         343 :     CM_L = gc_GEN(av2, CM_L);
     639         343 :     if (gc_needed(av,1))
     640             :     {
     641           0 :       if(DEBUGMEM>1) pari_warn(warnmem,"LLL_cmbf");
     642           0 :       (void)gc_all(av, 5, &CM_L, &TT, &Tra, &famod, &pa);
     643             :     }
     644             :   }
     645         107 :   if (DEBUGLEVEL>2)
     646           0 :     err_printf("* Time LLL: %ld\n* Time Check Factor: %ld\n",ti_LLL,ti_CF);
     647         107 :   return list;
     648             : }
     649             : 
     650             : /* Find a,b minimal such that A < q^a, B < q^b, 1 << q^(a-b) < 2^31 */
     651             : static int
     652       43224 : cmbf_precs(GEN q, GEN A, GEN B, long *pta, long *ptb, GEN *qa, GEN *qb)
     653             : {
     654       43224 :   long a, b, amin, d = (long)(31 / dbllog2(q) - 1e-5);
     655       43224 :   int fl = 0;
     656             : 
     657       43224 :   b = logintall(B, q, qb) + 1;
     658       43224 :   *qb = mulii(*qb, q);
     659       43224 :   amin = b + d;
     660       43224 :   if (gcmp(powiu(q, amin), A) <= 0)
     661             :   {
     662       12179 :     a = logintall(A, q, qa) + 1;
     663       12179 :     *qa = mulii(*qa, q);
     664       12179 :     b = a - d; *qb = powiu(q, b);
     665             :   }
     666             :   else
     667             :   { /* not enough room */
     668       31045 :     a = amin;  *qa = powiu(q, a);
     669       31045 :     fl = 1;
     670             :   }
     671       43224 :   if (DEBUGLEVEL > 3) {
     672           0 :     err_printf("S_2   bound: %Ps^%ld\n", q,b);
     673           0 :     err_printf("coeff bound: %Ps^%ld\n", q,a);
     674             :   }
     675       43224 :   *pta = a;
     676       43224 :   *ptb = b; return fl;
     677             : }
     678             : 
     679             : /* use van Hoeij's knapsack algorithm */
     680             : static GEN
     681       43224 : combine_factors(GEN target, GEN famod, GEN p, long klim)
     682             : {
     683             :   GEN la, B, A, res, L, pa, pb, listmod;
     684       43224 :   long a,b, l, maxK, n = degpol(target);
     685             :   int done;
     686             :   pari_timer T;
     687             : 
     688       43224 :   A = factor_bound(target);
     689             : 
     690       43224 :   la = absi_shallow(leading_coeff(target));
     691       43224 :   B = mului(n, sqri(mulii(la, root_bound(target)))); /* = bound for S_2 */
     692             : 
     693       43224 :   (void)cmbf_precs(p, A, B, &a, &b, &pa, &pb);
     694             : 
     695       43224 :   if (DEBUGLEVEL>2) timer_start(&T);
     696       43224 :   famod = ZpX_liftfact(target, famod, pa, p, a);
     697       43224 :   if (DEBUGLEVEL>2) timer_printf(&T, "Hensel lift (mod %Ps^%ld)", p,a);
     698       43224 :   L = cmbf(target, famod, A, p, a, b, klim, &maxK, &done);
     699       43224 :   if (DEBUGLEVEL>2) timer_printf(&T, "Naive recombination");
     700             : 
     701       43224 :   res     = gel(L,1);
     702       43224 :   listmod = gel(L,2); l = lg(listmod)-1;
     703       43224 :   famod = gel(listmod,l);
     704       43224 :   if (maxK > 0 && lg(famod)-1 > 2*maxK)
     705             :   {
     706         107 :     if (l!=1) A = factor_bound(gel(res,l));
     707         107 :     if (DEBUGLEVEL > 4) err_printf("last factor still to be checked\n");
     708         107 :     L = LLL_cmbf(gel(res,l), famod, p, pa, A, a, maxK);
     709         107 :     if (DEBUGLEVEL>2) timer_printf(&T,"Knapsack");
     710             :     /* remove last elt, possibly unfactored. Add all new ones. */
     711         107 :     setlg(res, l); res = shallowconcat(res, L);
     712             :   }
     713       43224 :   return res;
     714             : }
     715             : 
     716             : /* Assume 'a' a squarefree ZX; return 0 if no root (fl=1) / irreducible (fl=0).
     717             :  * Otherwise return prime p such that a mod p has fewest roots / factors */
     718             : static ulong
     719     1619081 : pick_prime(GEN a, long fl, pari_timer *T)
     720             : {
     721     1619081 :   pari_sp av = avma, av1;
     722     1619081 :   const long MAXNP = 7, da = degpol(a);
     723     1619081 :   long nmax = da+1, np;
     724     1619081 :   ulong chosenp = 0;
     725     1619081 :   GEN lead = gel(a,da+2);
     726             :   forprime_t S;
     727     1619081 :   if (equali1(lead)) lead = NULL;
     728     1619081 :   u_forprime_init(&S, 2, ULONG_MAX);
     729     1619081 :   av1 = avma;
     730     6140789 :   for (np = 0; np < MAXNP; set_avma(av1))
     731             :   {
     732     6052154 :     ulong p = u_forprime_next(&S);
     733             :     long nfacp;
     734             :     GEN z;
     735             : 
     736     6052154 :     if (!p) pari_err_OVERFLOW("DDF [out of small primes]");
     737     6052154 :     if (lead && !umodiu(lead,p)) continue;
     738     5996047 :     z = ZX_to_Flx(a, p);
     739     5996047 :     if (!Flx_is_squarefree(z, p)) continue;
     740             : 
     741     3716773 :     if (fl==1)
     742             :     {
     743     3209879 :       nfacp = Flx_nbroots(z, p);
     744     3209879 :       if (!nfacp) { chosenp = 0; break; } /* no root */
     745             :     }
     746      506894 :     else if(fl==0)
     747             :     {
     748      506259 :       nfacp = Flx_nbfact(z, p);
     749      506259 :       if (nfacp == 1) { chosenp = 0; break; } /* irreducible */
     750             :     } else
     751             :     {
     752         635 :       GEN f = gel(Flx_degfact(z, p),1);
     753         635 :       nfacp = lg(f)-1;
     754         635 :       if (f[1] > fl) { chosenp = 0; break; } /* no small factors */
     755             :     }
     756     2186332 :     if (DEBUGLEVEL>4)
     757           0 :       err_printf("...tried prime %3lu (%-3ld %s). Time = %ld\n",
     758             :                   p, nfacp, fl==1? "roots": "factors", timer_delay(T));
     759     2186332 :     if (nfacp < nmax)
     760             :     {
     761      819794 :       nmax = nfacp; chosenp = p;
     762      819794 :       if (da > 100 && nmax < 5) break; /* large degree, few factors. Enough */
     763             :     }
     764     2186327 :     np++;
     765             :   }
     766     1619081 :   return gc_ulong(av, chosenp);
     767             : }
     768             : 
     769             : /* Assume A a squarefree ZX; return the vector of its rational roots */
     770             : static GEN
     771     1443471 : DDF_roots(GEN A)
     772             : {
     773             :   GEN p, lc, lcpol, z, pe, pes2, bound;
     774             :   long i, m, e, lz;
     775             :   ulong pp;
     776             :   pari_sp av;
     777             :   pari_timer T;
     778             : 
     779     1443471 :   if (DEBUGLEVEL>2) timer_start(&T);
     780     1443471 :   pp = pick_prime(A, 1, &T);
     781     1443471 :   if (!pp) return cgetg(1,t_COL); /* no root */
     782       45416 :   p = utoipos(pp);
     783       45416 :   lc = leading_coeff(A);
     784       45416 :   if (is_pm1(lc))
     785       39029 :   { lc = NULL; lcpol = A; }
     786             :   else
     787        6387 :   { lc = absi_shallow(lc); lcpol = ZX_Z_mul(A, lc); }
     788       45416 :   bound = root_bound(A); if (lc) bound = mulii(lc, bound);
     789       45416 :   e = logintall(addiu(shifti(bound, 1), 1), p, &pe) + 1;
     790       45416 :   pe = mulii(pe, p);
     791       45416 :   pes2 = shifti(pe, -1);
     792       45416 :   if (DEBUGLEVEL>2) timer_printf(&T, "Root bound");
     793       45416 :   av = avma;
     794       45416 :   z = ZpX_roots(A, p, e); lz = lg(z);
     795       45416 :   z = deg1_from_roots(z, varn(A));
     796       45416 :   if (DEBUGLEVEL>2) timer_printf(&T, "Hensel lift (mod %lu^%ld)", pp,e);
     797       99686 :   for (m=1, i=1; i < lz; i++)
     798             :   {
     799       54270 :     GEN q, r, y = gel(z,i);
     800       54270 :     if (lc) y = ZX_Z_mul(y, lc);
     801       54270 :     y = centermod_i(y, pe, pes2);
     802       54270 :     if (! (q = ZX_divides(lcpol, y)) ) continue;
     803             : 
     804       22157 :     lcpol = q;
     805       22157 :     r = negi( constant_coeff(y) );
     806       22157 :     if (lc) {
     807        7113 :       r = gdiv(r,lc);
     808        7113 :       lcpol = Q_primpart(lcpol);
     809        7113 :       lc = absi_shallow( leading_coeff(lcpol) );
     810        7113 :       if (is_pm1(lc)) lc = NULL; else lcpol = ZX_Z_mul(lcpol, lc);
     811             :     }
     812       22157 :     gel(z,m++) = r;
     813       22157 :     if (gc_needed(av,2))
     814             :     {
     815           0 :       if (DEBUGMEM>1) pari_warn(warnmem,"DDF_roots, m = %ld", m);
     816           0 :       (void)gc_all(av, lc? 3:2, &z, &lcpol, &lc);
     817             :     }
     818             :   }
     819       45416 :   if (DEBUGLEVEL>2) timer_printf(&T, "Recombination");
     820       45416 :   setlg(z, m); return z;
     821             : }
     822             : 
     823             : /* Assume a squarefree ZX, deg(a) > 0, return rational factors.
     824             :  * In fact, a(0) != 0 but we don't use this
     825             :  * if dmax>0, Only look for factor of degree at most dmax */
     826             : GEN
     827      175610 : ZX_DDF_max(GEN a, long dmax)
     828             : {
     829             :   GEN ap, prime, famod, z;
     830      175610 :   long ti = 0;
     831      175610 :   ulong p = 0;
     832      175610 :   pari_sp av = avma;
     833             :   pari_timer T, T2;
     834             : 
     835      175610 :   if (DEBUGLEVEL>2) { timer_start(&T); timer_start(&T2); }
     836      175610 :   p = pick_prime(a, dmax, &T2);
     837      175610 :   if (!p) return mkvec(a);
     838       43224 :   prime = utoipos(p);
     839       43224 :   ap = Flx_normalize(ZX_to_Flx(a, p), p);
     840       43224 :   famod = gel(Flx_factor(ap, p), 1);
     841       43224 :   if (DEBUGLEVEL>2)
     842             :   {
     843           0 :     if (DEBUGLEVEL>4) timer_printf(&T2, "splitting mod p = %lu", p);
     844           0 :     ti = timer_delay(&T);
     845           0 :     err_printf("Time setup: %ld\n", ti);
     846             :   }
     847       43224 :   z = combine_factors(a, FlxV_to_ZXV(famod), prime, degpol(a)-1);
     848       43224 :   if (DEBUGLEVEL>2)
     849           0 :     err_printf("Total Time: %ld\n===========\n", ti + timer_delay(&T));
     850       43224 :   return gc_GEN(av, z);
     851             : }
     852             : 
     853             : /* Distinct Degree Factorization (deflating first)
     854             :  * Assume x squarefree, degree(x) > 0, x(0) != 0 */
     855             : GEN
     856      130642 : ZX_DDF(GEN x)
     857             : {
     858             :   GEN L;
     859             :   long m;
     860      130642 :   if (DEBUGLEVEL>2)
     861           0 :    err_printf("ZX_DDF: factoring pol of deg %ld, %ld bits\n",degpol(x),gexpo(x));
     862      130642 :   x = ZX_deflate_max(x, &m);
     863      130642 :   L = ZX_DDF_max(x,0);
     864      130642 :   if (m > 1)
     865             :   {
     866       43042 :     GEN e, v, fa = factoru(m);
     867             :     long i,j,k, l;
     868             : 
     869       43042 :     e = gel(fa,2); k = 0;
     870       43042 :     fa= gel(fa,1); l = lg(fa);
     871       86343 :     for (i=1; i<l; i++) k += e[i];
     872       43042 :     v = cgetg(k+1, t_VECSMALL); k = 1;
     873       86343 :     for (i=1; i<l; i++)
     874       87813 :       for (j=1; j<=e[i]; j++) v[k++] = fa[i];
     875       87554 :     for (k--; k; k--)
     876             :     {
     877       44512 :       GEN L2 = cgetg(1,t_VEC);
     878       89331 :       for (i=1; i < lg(L); i++)
     879       44819 :               L2 = shallowconcat(L2, ZX_DDF_max(RgX_inflate(gel(L,i), v[k]),0));
     880       44512 :       L = L2;
     881             :     }
     882             :   }
     883      130642 :   return L;
     884             : }
     885             : 
     886             : /* SquareFree Factorization in Z[X] (char 0 is enough, if ZX_gcd -> RgX_gcd)
     887             :  * f = prod Q[i]^E[i], E[1] < E[2] < ..., and Q[i] squarefree and coprime.
     888             :  * Return Q, set *pE = E. For efficiency, caller should have used ZX_valrem
     889             :  * so that f(0) != 0 */
     890             : GEN
     891      273219 : ZX_squff(GEN f, GEN *pE)
     892             : {
     893             :   GEN T, V, P, E;
     894      273219 :   long i, k, n = 1 + degpol(f);
     895             : 
     896      273219 :   if (signe(leading_coeff(f)) < 0) f = ZX_neg(f);
     897      273219 :   E = cgetg(n, t_VECSMALL);
     898      273219 :   P = cgetg(n, t_COL);
     899      273219 :   T = ZX_gcd_all(f, ZX_deriv(f), &V);
     900      273219 :   for (k = i = 1;; k++)
     901        3106 :   {
     902      276325 :     GEN W = ZX_gcd_all(T,V, &T); /* V and W are squarefree */
     903      276325 :     long dW = degpol(W), dV = degpol(V);
     904             :     /* f = prod_i T_i^{e_i}
     905             :      * W = prod_{i: e_i > k} T_i,
     906             :      * V = prod_{i: e_i >= k} T_i,
     907             :      * T = prod_{i: e_i > k} T_i^{e_i - k} */
     908      276325 :     if (!dW)
     909             :     {
     910      273219 :       if (dV) { gel(P,i) = Q_primpart(V); E[i] = k; i++; }
     911      273219 :       break;
     912             :     }
     913        3106 :     if (dW == dV)
     914             :     {
     915             :       GEN U;
     916        1399 :       while ( (U = ZX_divides(T, V)) ) { k++; T = U; }
     917             :     }
     918             :     else
     919             :     {
     920        2036 :       gel(P,i) = Q_primpart(RgX_div(V,W));
     921        2036 :       E[i] = k; i++; V = W;
     922             :     }
     923             :   }
     924      273219 :   setlg(P,i);
     925      273219 :   setlg(E,i); *pE = E; return P;
     926             : }
     927             : 
     928             : static GEN
     929       32400 : fact_from_DDF(GEN Q, GEN E, long n)
     930             : {
     931       32400 :   GEN v,w, y = cgetg(3, t_MAT);
     932       32400 :   long i,j,k, l = lg(Q);
     933             : 
     934       32400 :   v = cgetg(n+1, t_COL); gel(y,1) = v;
     935       32400 :   w = cgetg(n+1, t_COL); gel(y,2) = w;
     936       65954 :   for (k = i = 1; i < l; i++)
     937             :   {
     938       33554 :     GEN L = gel(Q,i), e = utoipos(E[i]);
     939       33554 :     long J = lg(L);
     940       77430 :     for (j = 1; j < J; j++,k++)
     941             :     {
     942       43876 :       gel(v,k) = ZX_copy(gel(L,j));
     943       43876 :       gel(w,k) = e;
     944             :     }
     945             :   }
     946       32400 :   return y;
     947             : }
     948             : 
     949             : /* Factor T in Z[x] */
     950             : static GEN
     951       32405 : ZX_factor_i(GEN T)
     952             : {
     953             :   GEN Q, E, y;
     954             :   long n, i, l, v;
     955             : 
     956       32405 :   if (!signe(T)) return prime_fact(T);
     957       32400 :   v = ZX_valrem(T, &T);
     958       32400 :   Q = ZX_squff(T, &E); l = lg(Q);
     959       65007 :   for (i = 1, n = 0; i < l; i++)
     960             :   {
     961       32607 :     gel(Q,i) = ZX_DDF(gel(Q,i));
     962       32607 :     n += lg(gel(Q,i)) - 1;
     963             :   }
     964       32400 :   if (v)
     965             :   {
     966         947 :     Q = vec_append(Q, mkvec(pol_x(varn(T))));
     967         947 :     E = vecsmall_append(E, v); n++;
     968             :   }
     969       32400 :   y = fact_from_DDF(Q, E, n);
     970       32400 :   return sort_factor_pol(y, cmpii);
     971             : }
     972             : GEN
     973       31715 : ZX_factor(GEN x)
     974             : {
     975       31715 :   pari_sp av = avma;
     976       31715 :   return gc_upto(av, ZX_factor_i(x));
     977             : }
     978             : GEN
     979         690 : QX_factor(GEN x)
     980             : {
     981         690 :   pari_sp av = avma;
     982         690 :   return gc_upto(av, ZX_factor_i(Q_primpart(x)));
     983             : }
     984             : 
     985             : long
     986       87425 : ZX_is_irred(GEN x)
     987             : {
     988       87425 :   pari_sp av = avma;
     989       87425 :   long l = lg(x);
     990             :   GEN y;
     991       87425 :   if (l <= 3) return 0; /* degree < 1 */
     992       87425 :   if (l == 4) return 1; /* degree 1 */
     993       84372 :   if (ZX_val(x)) return 0;
     994       84180 :   if (!ZX_is_squarefree(x)) return 0;
     995       84048 :   y = ZX_DDF(x); set_avma(av);
     996       84048 :   return (lg(y) == 2);
     997             : }
     998             : 
     999             : GEN
    1000     1443471 : nfrootsQ(GEN x)
    1001             : {
    1002     1443471 :   pari_sp av = avma;
    1003             :   GEN z;
    1004             :   long val;
    1005             : 
    1006     1443471 :   if (typ(x)!=t_POL) pari_err_TYPE("nfrootsQ",x);
    1007     1443471 :   if (!signe(x)) pari_err_ROOTS0("nfrootsQ");
    1008     1443471 :   x = Q_primpart(x);
    1009     1443471 :   RgX_check_ZX(x,"nfrootsQ");
    1010     1443471 :   val = ZX_valrem(x, &x);
    1011     1443471 :   z = DDF_roots( ZX_radical(x) );
    1012     1443471 :   if (val) z = vec_append(z, gen_0);
    1013     1443471 :   return gc_upto(av, sort(z));
    1014             : }
    1015             : 
    1016             : /************************************************************************
    1017             :  *                   GCD OVER Z[X] / Q[X]                               *
    1018             :  ************************************************************************/
    1019             : int
    1020      169291 : ZX_is_squarefree(GEN x)
    1021             : {
    1022      169291 :   pari_sp av = avma;
    1023             :   GEN d;
    1024             :   long m;
    1025      169291 :   if (lg(x) == 2) return 0;
    1026      169291 :   m = ZX_deflate_order(x);
    1027      169291 :   if (m > 1)
    1028             :   {
    1029       73362 :     if (!signe(gel(x,2))) return 0;
    1030       73159 :     x = RgX_deflate(x, m);
    1031             :   }
    1032      169088 :   d = ZX_gcd(x,ZX_deriv(x));
    1033      169088 :   return gc_bool(av, lg(d) == 3);
    1034             : }
    1035             : 
    1036             : static int
    1037      103668 : ZX_gcd_filter(GEN *pt_A, GEN *pt_P)
    1038             : {
    1039      103668 :   GEN A = *pt_A, P = *pt_P;
    1040      103668 :   long i, j, l = lg(A), n = 1, d = degpol(gel(A,1));
    1041             :   GEN B, Q;
    1042      212642 :   for (i=2; i<l; i++)
    1043             :   {
    1044      108974 :     long di = degpol(gel(A,i));
    1045      108974 :     if (di==d) n++;
    1046          30 :     else if (d > di)
    1047          30 :     { n=1; d = di; }
    1048             :   }
    1049      103668 :   if (n == l-1)
    1050      103638 :     return 0;
    1051          30 :   B = cgetg(n+1, t_VEC);
    1052          30 :   Q = cgetg(n+1, typ(P));
    1053         130 :   for (i=1, j=1; i<l; i++)
    1054             :   {
    1055         100 :     if (degpol(gel(A,i))==d)
    1056             :     {
    1057          70 :       gel(B,j) = gel(A,i);
    1058          70 :       Q[j] = P[i];
    1059          70 :       j++;
    1060             :     }
    1061             :   }
    1062          30 :   *pt_A = B; *pt_P = Q; return 1;
    1063             : }
    1064             : 
    1065             : static GEN
    1066     2445759 : ZX_gcd_Flx(GEN a, GEN b, ulong g, ulong p)
    1067             : {
    1068     2445759 :   GEN H = Flx_gcd(a, b, p);
    1069     2445759 :   if (!g)
    1070     2417346 :     return Flx_normalize(H, p);
    1071             :   else
    1072             :   {
    1073       28413 :     ulong t = Fl_mul(g, Fl_inv(Flx_lead(H), p), p);
    1074       28413 :     return Flx_Fl_mul(H, t, p);
    1075             :   }
    1076             : }
    1077             : 
    1078             : static GEN
    1079     2435484 : ZX_gcd_slice(GEN A, GEN B, GEN g, GEN P, GEN *mod)
    1080             : {
    1081     2435484 :   pari_sp av = avma;
    1082     2435484 :   long i, n = lg(P)-1;
    1083             :   GEN H, T;
    1084     2435484 :   if (n == 1)
    1085             :   {
    1086     2430129 :     ulong p = uel(P,1), gp = g ? umodiu(g, p): 0;
    1087     2430129 :     GEN a = ZX_to_Flx(A, p), b = ZX_to_Flx(B, p);
    1088     2430129 :     GEN Hp = ZX_gcd_Flx(a, b, gp, p);
    1089     2430129 :     H = gc_upto(av, Flx_to_ZX(Hp));
    1090     2430129 :     *mod = utoi(p);
    1091     2430129 :     return H;
    1092             :   }
    1093        5355 :   T = ZV_producttree(P);
    1094        5355 :   A = ZX_nv_mod_tree(A, P, T);
    1095        5355 :   B = ZX_nv_mod_tree(B, P, T);
    1096        5355 :   g = g ?  Z_ZV_mod_tree(g, P, T): NULL;
    1097        5355 :   H = cgetg(n+1, t_VEC);
    1098       20985 :   for(i=1; i <= n; i++)
    1099             :   {
    1100       15630 :     ulong p = P[i];
    1101       15630 :     GEN a = gel(A,i), b = gel(B,i);
    1102       15630 :     gel(H,i) = ZX_gcd_Flx(a, b, g? g[i]: 0, p);
    1103             :   }
    1104        5355 :   if (ZX_gcd_filter(&H, &P))
    1105          10 :     T = ZV_producttree(P);
    1106        5355 :   H = nxV_chinese_center_tree(H, P, T, ZV_chinesetree(P, T));
    1107        5355 :   *mod = gmael(T, lg(T)-1, 1); return gc_all(av, 2, &H, mod);
    1108             : }
    1109             : 
    1110             : GEN
    1111     2435484 : ZX_gcd_worker(GEN P, GEN A, GEN B, GEN g)
    1112             : {
    1113     2435484 :   GEN V = cgetg(3, t_VEC);
    1114     2435484 :   gel(V,1) = ZX_gcd_slice(A, B, equali1(g)? NULL: g , P, &gel(V,2));
    1115     2435484 :   return V;
    1116             : }
    1117             : 
    1118             : static GEN
    1119       98313 : ZX_gcd_chinese(GEN A, GEN P, GEN *mod)
    1120             : {
    1121       98313 :   ZX_gcd_filter(&A, &P);
    1122       98313 :   return nxV_chinese_center(A, P, mod);
    1123             : }
    1124             : 
    1125             : GEN
    1126    11441685 : ZX_gcd_all(GEN A, GEN B, GEN *Anew)
    1127             : {
    1128    11441685 :   pari_sp av = avma;
    1129    11441685 :   long k, valH, valA, valB, vA = varn(A), dA = degpol(A), dB = degpol(B);
    1130    11441685 :   GEN worker, c, cA, cB, g, Ag, Bg, H = NULL, mod = gen_1, R;
    1131             :   GEN Ap, Bp, Hp;
    1132             :   forprime_t S;
    1133             :   ulong pp;
    1134    11441685 :   if (dA < 0) { if (Anew) *Anew = pol_0(vA); return ZX_copy(B); }
    1135    11441668 :   if (dB < 0) { if (Anew) *Anew = pol_1(vA); return ZX_copy(A); }
    1136    11440693 :   A = Q_primitive_part(A, &cA);
    1137    11440693 :   B = Q_primitive_part(B, &cB);
    1138    11440693 :   valA = ZX_valrem(A, &A); dA -= valA;
    1139    11440693 :   valB = ZX_valrem(B, &B); dB -= valB;
    1140    11440693 :   valH = minss(valA, valB);
    1141    11440693 :   valA -= valH; /* valuation(Anew) */
    1142    11440693 :   c = (cA && cB)? gcdii(cA, cB): NULL; /* content(gcd) */
    1143    11440693 :   if (!dA || !dB)
    1144             :   {
    1145     6057313 :     if (Anew) *Anew = RgX_shift_shallow(A, valA);
    1146     6057313 :     return monomial(c? c: gen_1, valH, vA);
    1147             :   }
    1148     5383380 :   g = gcdii(leading_coeff(A), leading_coeff(B)); /* multiple of lead(gcd) */
    1149     5383380 :   if (is_pm1(g)) {
    1150     5205571 :     g = NULL;
    1151     5205571 :     Ag = A;
    1152     5205571 :     Bg = B;
    1153             :   } else {
    1154      177809 :     Ag = ZX_Z_mul(A,g);
    1155      177809 :     Bg = ZX_Z_mul(B,g);
    1156             :   }
    1157     5383380 :   init_modular_big(&S);
    1158             :   do {
    1159     5383390 :     pp = u_forprime_next(&S);
    1160     5383390 :     Ap = ZX_to_Flx(Ag, pp);
    1161     5383390 :     Bp = ZX_to_Flx(Bg, pp);
    1162     5383390 :   } while (degpol(Ap) != dA || degpol(Bp) != dB);
    1163     5383380 :   if (degpol(Flx_gcd(Ap, Bp, pp)) == 0)
    1164             :   {
    1165     3046595 :     if (Anew) *Anew = RgX_shift_shallow(A, valA);
    1166     3046595 :     return monomial(c? c: gen_1, valH, vA);
    1167             :   }
    1168     2336785 :   worker = snm_closure(is_entry("_ZX_gcd_worker"), mkvec3(A, B, g? g: gen_1));
    1169     2336785 :   av = avma;
    1170     2433383 :   for (k = 1; ;k *= 2)
    1171             :   {
    1172     2433383 :     gen_inccrt_i("ZX_gcd", worker, g, (k+1)>>1, 0, &S, &H, &mod, ZX_gcd_chinese, NULL);
    1173     2433383 :     (void)gc_all(av, 2, &H, &mod);
    1174     2433383 :     Hp = ZX_to_Flx(H, pp);
    1175     2433383 :     if (lgpol(Flx_rem(Ap, Hp, pp)) || lgpol(Flx_rem(Bp, Hp, pp))) continue;
    1176     2340295 :     if (!ZX_divides(Bg, H)) continue;
    1177     2336810 :     R = ZX_divides(Ag, H);
    1178     2336810 :     if (R) break;
    1179             :   }
    1180             :   /* lead(H) = g */
    1181     2336785 :   if (g) H = Q_primpart(H);
    1182     2336785 :   if (c) H = ZX_Z_mul(H,c);
    1183     2336785 :   if (DEBUGLEVEL>5) err_printf("done\n");
    1184     2336785 :   if (Anew) *Anew = RgX_shift_shallow(R, valA);
    1185     2336785 :   return valH? RgX_shift_shallow(H, valH): H;
    1186             : }
    1187             : 
    1188             : #if 0
    1189             : /* ceil( || p ||_oo / lc(p) ) */
    1190             : static GEN
    1191             : maxnorm(GEN p)
    1192             : {
    1193             :   long i, n = degpol(p), av = avma;
    1194             :   GEN x, m = gen_0;
    1195             : 
    1196             :   p += 2;
    1197             :   for (i=0; i<n; i++)
    1198             :   {
    1199             :     x = gel(p,i);
    1200             :     if (abscmpii(x,m) > 0) m = x;
    1201             :   }
    1202             :   m = divii(m, gel(p,n));
    1203             :   return gc_INT(av, addiu(absi_shallow(m),1));
    1204             : }
    1205             : #endif
    1206             : 
    1207             : GEN
    1208     8408567 : ZX_gcd(GEN A, GEN B)
    1209             : {
    1210     8408567 :   pari_sp av = avma;
    1211     8408567 :   return gc_GEN(av, ZX_gcd_all(A,B,NULL));
    1212             : }
    1213             : 
    1214             : GEN
    1215     2479952 : ZX_radical(GEN A) { GEN B; (void)ZX_gcd_all(A,ZX_deriv(A),&B); return B; }
    1216             : 
    1217             : static GEN
    1218       16613 : _gcd(GEN a, GEN b)
    1219             : {
    1220       16613 :   if (!a) a = gen_1;
    1221       16613 :   if (!b) b = gen_1;
    1222       16613 :   return Q_gcd(a,b);
    1223             : }
    1224             : /* A0 and B0 in Q[X] */
    1225             : GEN
    1226       16453 : QX_gcd(GEN A0, GEN B0)
    1227             : {
    1228             :   GEN a, b, D;
    1229       16453 :   pari_sp av = avma, av2;
    1230             : 
    1231       16453 :   D = ZX_gcd(Q_primitive_part(A0, &a), Q_primitive_part(B0, &b));
    1232       16453 :   av2 = avma; a = _gcd(a,b);
    1233       16453 :   if (isint1(a)) set_avma(av2); else D = ZX_Q_mul(D, a);
    1234       16453 :   return gc_upto(av, D);
    1235             : }
    1236             : 
    1237             : /***************************************************************************
    1238             :  ***                                                                     ***
    1239             :  ***                                ZXk/QXk                              ***
    1240             :  ***                                                                     ***
    1241             :  ***************************************************************************/
    1242             : 
    1243             : /* ZXk/QXk: multivariate polynomials in Z[X_1,...,X_k] and Q[X_1,...,X_k] */
    1244             : 
    1245             : INLINE GEN
    1246     4304419 : ZXk_renormalize(GEN x, long lx)    { return ZXX_renormalize(x,lx); }
    1247             : 
    1248             : int
    1249           0 : Rg_is_QXk(GEN z)
    1250             : {
    1251           0 :   long i, t = typ(z), l = lg(z);
    1252           0 :   if (t==t_INT || t==t_FRAC) return 1;
    1253           0 :   if (t!=t_POL) return 0;
    1254           0 :   for (i = 2; i < l; i++)
    1255           0 :     if (!Rg_is_QXk(gel(z,i))) return 0;
    1256           0 :   return 1;
    1257             : }
    1258             : 
    1259             : static GEN
    1260     2792984 : centeri2n(GEN z, long n, GEN N)
    1261             : {
    1262     2792984 :   pari_sp av = avma;
    1263     2792984 :   z = remi2n(z, n);
    1264     2792984 :   if (expi(z)<n-1) return z;
    1265        1049 :   if (signe(z)<0) z = addii(z, N);
    1266         636 :   else            z = subii(z, N);
    1267        1049 :   return gc_INT(av, z);
    1268             : }
    1269             : 
    1270             : static GEN
    1271     4270232 : ZXk_center2n(GEN z, long n, GEN N)
    1272             : {
    1273     4270232 :   if (typ(z) == t_INT)
    1274     2792984 :     return centeri2n(z, n, N);
    1275             :   else
    1276             :   {
    1277             :     long i,l;
    1278     1477248 :     GEN x = cgetg_copy(z, &l);
    1279     1477248 :     x[1] = z[1];
    1280     2964457 :     for (i = 2; i < l; i++)
    1281     1487209 :       gel(x,i) = ZXk_center2n(gel(z,i), n, N);
    1282     1477248 :     return ZXk_renormalize(x, l);
    1283             :   }
    1284             : }
    1285             : 
    1286             : static GEN ZXk_gcd_i(GEN A, GEN B);
    1287             : static GEN
    1288     2988749 : ZXk_content_shallow(GEN x)
    1289             : {
    1290     2988749 :   long i, l = lg(x);
    1291             :   GEN c;
    1292     2988749 :   if (typ(x)==t_INT) return x;
    1293     2988749 :   if (!signe(x)) return gen_0;
    1294     2988749 :   c = gel(x, 2);
    1295     2988749 :   if (gequal1(c)) return gen_1;
    1296     5301819 :   for (i = 3; i < l; i++)
    1297             :   {
    1298     3094411 :     c = simplify_shallow(ZXk_gcd_i(c, gel(x,i)));
    1299     3094411 :     if (gequal1(c)) return gen_1;
    1300             :   }
    1301     2207408 :   return c;
    1302             : }
    1303             : 
    1304             : static GEN ZXk_divexact_s(GEN A, GEN B);
    1305             : 
    1306             : static GEN
    1307     2230698 : ZXkX_ZXk_divexact_s(GEN x, GEN B)
    1308     6611650 : { pari_APPLY_ZX(ZXk_divexact_s(gel(x,i), B)); }
    1309             : 
    1310             : static GEN
    1311     2198171 : ZXkX_ZXk_divexact(GEN A, GEN B)
    1312             : {
    1313     2198171 :   pari_sp av = avma;
    1314     2198171 :   return gc_upto(av, ZXkX_ZXk_divexact_s(A, simplify_shallow(B)));
    1315             : }
    1316             : 
    1317             : static GEN
    1318     2198619 : ZXk_divexact_i(GEN x, GEN y)
    1319             : {
    1320     2198619 :   long dx = degpol(x), dy = degpol(y), dz, i, j;
    1321     2198619 :   GEN z, y_lead = gel(y,dy+2);
    1322     2198619 :   if (dx < dy)
    1323           0 :     return gen_0;
    1324     2198619 :   dz = dx-dy;
    1325     2198619 :   z = cgetg(dz+3,t_POL); z[1] = x[1];
    1326     2198619 :   gel(z,dz+2) = ZXk_divexact_s(gel(x,dx+2), y_lead);
    1327     2211573 :   for (i=dx-1; i>=dy; i--)
    1328             :   {
    1329       12954 :     pari_sp btop = avma;
    1330       12954 :     GEN p1=gel(x,2+i);
    1331       28330 :     for (j=i-dy+1; j<=i && j<=dz; j++)
    1332       15376 :       p1 = gsub(p1, gmul(gel(z,2+j), gel(y,2+i-j)));
    1333       12954 :     gel(z,2+i-dy) = gc_upto(btop, ZXk_divexact_s(p1, y_lead));
    1334             :   }
    1335     2198619 :   return z;
    1336             : }
    1337             : 
    1338             : static GEN
    1339     6592525 : ZXk_divexact_s(GEN A, GEN B)
    1340             : {
    1341     6592525 :   if (!signe(A)) return gen_0;
    1342     4459607 :   if (typ(A)==t_INT && typ(B)==t_INT)
    1343     2228461 :     return diviiexact(A, B);
    1344     2231146 :   else if (typ(B)==t_INT || varn(A)!=varn(B))
    1345       32527 :     return ZXkX_ZXk_divexact_s(A, B);
    1346             :   else
    1347     2198619 :     return ZXk_divexact_i(A, B);
    1348             : }
    1349             : 
    1350             : GEN
    1351           0 : ZXk_divexact(GEN A, GEN B)
    1352             : {
    1353           0 :   pari_sp av = avma;
    1354           0 :   return gc_upto(av, ZXk_divexact_s(A, simplify_shallow(B)));
    1355             : }
    1356             : 
    1357             : static GEN ZXk_divides_s(GEN A, GEN B);
    1358             : 
    1359             : static GEN
    1360     2827171 : ZXkX_ZXk_divides_s(GEN x, GEN B)
    1361             : {
    1362     2827171 :   pari_sp av = avma;
    1363             :   long i, l;
    1364     2827171 :   GEN y = cgetg_copy(x, &l); y[1] = x[1];
    1365     2827171 :   if (l == 2) return y;
    1366     5986875 :   for (i=2; i<l; i++)
    1367             :   {
    1368     3159704 :     GEN c = ZXk_divides_s(gel(x,i), B);
    1369     3159704 :     if (!c) return gc_NULL(av);
    1370     3159704 :     gel(y, i) = c;
    1371             :   }
    1372     2827171 :   return ZXk_renormalize(y, l);
    1373             : }
    1374             : 
    1375             : static GEN
    1376     2424873 : ZXk_divides_i(GEN x, GEN y)
    1377             : {
    1378     2424873 :   pari_sp av = avma, av2;
    1379     2424873 :   long dx = degpol(x), dy = degpol(y), dz, i, j, c;
    1380     2424873 :   GEN z, y_lead = gel(y,dy+2);
    1381     2424873 :   if (dx < dy)
    1382           0 :     return gen_0;
    1383     2424873 :   dz = dx-dy;
    1384     2424873 :   z = cgetg(dz+3,t_POL); z[1] = x[1];
    1385     2424873 :   gel(z,dz+2) = ZXk_divides(gel(x,dx+2), y_lead);
    1386     2424873 :   if (!gel(z,dz+2)) return gc_NULL(av);
    1387     2645161 :   for (i=dx-1; i>=dy; i--)
    1388             :   {
    1389      220299 :     pari_sp btop = avma;
    1390      220299 :     GEN p1 = gel(x,2+i), c;
    1391      447413 :     for (j=i-dy+1; j<=i && j<=dz; j++)
    1392      227114 :       p1 = gsub(p1, gmul(gel(z,2+j), gel(y,2+i-j)));
    1393      220299 :     c = ZXk_divides_s(p1, y_lead);
    1394      220299 :     if (!c) return gc_NULL(av);
    1395      220299 :     gel(z,2+i-dy) = gc_upto(btop, c);
    1396             :   }
    1397     2424862 :   av2 = avma;
    1398     2424862 :   c = gc_bool(av2, gequal(gmul(z,y),x));
    1399     2424862 :   return c ? z: gc_NULL(av);
    1400             : }
    1401             : 
    1402             : static GEN
    1403     3020523 : dividesii(GEN A, GEN B)
    1404             : {
    1405     3020523 :   GEN r, q  = dvmdii(A, B, &r);
    1406     3020523 :   return signe(r) ? NULL: q;
    1407             : }
    1408             : 
    1409             : static GEN
    1410     8781745 : ZXk_divides_s(GEN A, GEN B)
    1411             : {
    1412     8781745 :   if (!signe(A)) return gen_0;
    1413     8272573 :   if (typ(B)==t_INT)
    1414     3020523 :     return typ(A)==t_INT ? dividesii(A, B)
    1415     8867684 :                          : ZXkX_ZXk_divides_s(A, B);
    1416     2425412 :   else if (typ(A)==t_INT) return NULL;
    1417             :   else
    1418             :   {
    1419     2425406 :     long c = varncmp(varn(A),varn(B));
    1420     2425406 :     if (c < 0)
    1421         533 :       return ZXkX_ZXk_divides_s(A, B);
    1422     2424873 :     else if (c>0)
    1423           0 :       return NULL;
    1424             :     else
    1425     2424873 :       return ZXk_divides_i(A, B);
    1426             :   }
    1427             : }
    1428             : 
    1429             : GEN
    1430     5401742 : ZXk_divides(GEN A, GEN B)
    1431             : {
    1432     5401742 :   pari_sp av = avma;
    1433     5401742 :   GEN z = ZXk_divides_s(A, simplify_shallow(B));
    1434     5401742 :   return z ? gc_upto(av, z): z;
    1435             : }
    1436             : 
    1437             : static GEN
    1438     1488440 : rec(GEN g, long e, GEN N, long v)
    1439             : {
    1440     1488440 :   pari_sp av = avma;
    1441     1488440 :   long i, d = (gexpo(g)+2*e-1)/e;
    1442     1488440 :   GEN s = cgetg(d+3,t_POL);
    1443     1488440 :   s[1] = evalvarn(v);
    1444     2783023 :   for (i = 0; i <= d; i++)
    1445             :   {
    1446     2783023 :     GEN c = ZXk_center2n(g, e, N);
    1447     2783023 :     gel(s,i+2) = c;
    1448     2783023 :     g = gmul2n(gsub(g,c),-e);
    1449     2783023 :     if (!signe(g)) break;
    1450             :   }
    1451     1488440 :   s = RgX_renormalize_lg(s,i+3);
    1452     1488440 :   return gc_GEN(av, s);
    1453             : }
    1454             : 
    1455             : static GEN
    1456     7551157 : ZXk_gcd_i(GEN A, GEN B)
    1457             : {
    1458             :   pari_sp av;
    1459             :   long e, v, vc;
    1460             :   GEN c, cA, cB;
    1461     7551157 :   if (signe(A)==0) return gcopy(B);
    1462     4481896 :   if (signe(B)==0) return gcopy(A);
    1463     4480353 :   if (typ(A) == t_INT) return gcdii(A, typ(B)==t_INT ? B: Q_content(B));
    1464     3729104 :   if (typ(B) == t_INT) return gcdii(Q_content(A), B);
    1465     2994362 :   v = varn(A); vc = varncmp(v, varn(B));
    1466     2994362 :   if (vc < 0) return ZXk_gcd_i(ZXk_content_shallow(A), B);
    1467     2986083 :   if (vc > 0) return ZXk_gcd_i(A, ZXk_content_shallow(B));
    1468     2982471 :   if (RgX_is_ZX(A) && RgX_is_ZX(B)) return ZX_gcd(A,B);
    1469     1488429 :   cA = ZXk_content_shallow(A); if (!gequal1(cA)) A = ZXkX_ZXk_divexact(A, cA);
    1470     1488429 :   cB = ZXk_content_shallow(B); if (!gequal1(cB)) B = ZXkX_ZXk_divexact(B, cB);
    1471     1488429 :   c = ZXk_gcd_i(cA, cB); av = avma;
    1472     1488429 :   e = maxss(3, minss(gexpo(A), gexpo(B)) + 2);
    1473          11 :   for ( ; ; e++, set_avma(av))
    1474          11 :   {
    1475     1488440 :     GEN N = int2n(e), G = ZXk_gcd_i(poleval(A,N), poleval(B,N));
    1476     1488440 :     GEN g = Q_primpart(rec(G, e, N, v));
    1477     1488440 :     if (ZXk_divides(A,g) &&  ZXk_divides(B,g))
    1478     1488429 :       return gmul(c,g);
    1479             :   }
    1480             : }
    1481             : GEN
    1482     1467826 : ZXk_gcd(GEN A, GEN B)
    1483     1467826 : { pari_sp av = avma; return gc_upto(av, ZXk_gcd_i(A, B)); }
    1484             : 
    1485             : GEN
    1486         160 : QXk_gcd(GEN A, GEN B)
    1487             : {
    1488             :   GEN a, b, D;
    1489         160 :   pari_sp av = avma, av2;
    1490         160 :   D = ZXk_gcd_i(Q_primitive_part(A, &a), Q_primitive_part(B, &b));
    1491         160 :   av2 = avma; a = _gcd(a,b);
    1492         160 :   if (isint1(a)) set_avma(av2); else D = gmul(D, a);
    1493         160 :   return gc_upto(av, D);
    1494             : }
    1495             : 
    1496             : /*****************************************************************************
    1497             :  * Variants of the Bradford-Davenport algorithm: look for cyclotomic         *
    1498             :  * factors, and decide whether a ZX is cyclotomic or a product of cyclotomic *
    1499             :  *****************************************************************************/
    1500             : /* f of degree 1, return a cyclotomic factor (Phi_1 or Phi_2) or NULL */
    1501             : static GEN
    1502           0 : BD_deg1(GEN f)
    1503             : {
    1504           0 :   GEN a = gel(f,3), b = gel(f,2); /* f = ax + b */
    1505           0 :   if (!absequalii(a,b)) return NULL;
    1506           0 :   return polcyclo((signe(a) == signe(b))? 2: 1, varn(f));
    1507             : }
    1508             : 
    1509             : /* f a squarefree ZX; not divisible by any Phi_n, n even */
    1510             : static GEN
    1511         348 : BD_odd(GEN f)
    1512             : {
    1513         348 :   while(degpol(f) > 1)
    1514             :   {
    1515         348 :     GEN f1 = ZX_graeffe(f); /* contain all cyclotomic divisors of f */
    1516         348 :     if (ZX_equal(f1, f)) return f; /* product of cyclotomics */
    1517           0 :     f = ZX_gcd(f, f1);
    1518             :   }
    1519           0 :   if (degpol(f) == 1) return BD_deg1(f);
    1520           0 :   return NULL; /* no cyclotomic divisor */
    1521             : }
    1522             : 
    1523             : static GEN
    1524        1980 : myconcat(GEN v, GEN x)
    1525             : {
    1526        1980 :   if (typ(x) != t_VEC) x = mkvec(x);
    1527        1980 :   if (!v) return x;
    1528        1260 :   return shallowconcat(v, x);
    1529             : }
    1530             : 
    1531             : /* Bradford-Davenport algorithm.
    1532             :  * f a squarefree ZX of degree > 0, return NULL or a vector of coprime
    1533             :  * cyclotomic factors of f [ possibly reducible ] */
    1534             : static GEN
    1535        2022 : BD(GEN f)
    1536             : {
    1537        2022 :   GEN G = NULL, Gs = NULL, Gp = NULL, Gi = NULL;
    1538             :   GEN fs2, fp, f2, f1, fe, fo, fe1, fo1;
    1539        2022 :   RgX_even_odd(f, &fe, &fo);
    1540        2022 :   fe1 = ZX_eval1(fe);
    1541        2022 :   fo1 = ZX_eval1(fo);
    1542        2022 :   if (absequalii(fe1, fo1)) /* f(1) = 0 or f(-1) = 0 */
    1543             :   {
    1544        1302 :     long i, v = varn(f);
    1545        1302 :     if (!signe(fe1))
    1546         318 :       G = mkvec2(polcyclo(1, v), polcyclo(2, v)); /* both 0 */
    1547         984 :     else if (signe(fe1) == signe(fo1))
    1548         594 :       G = mkvec(polcyclo(2, v)); /*f(-1) = 0*/
    1549             :     else
    1550         390 :       G = mkvec(polcyclo(1, v)); /*f(1) = 0*/
    1551        2922 :     for (i = lg(G)-1; i; i--) f = RgX_div(f, gel(G,i));
    1552             :   }
    1553             :   /* f no longer divisible by Phi_1 or Phi_2 */
    1554        2022 :   if (degpol(f) <= 1) return G;
    1555        1764 :   f1 = ZX_graeffe(f); /* has at most square factors */
    1556        1764 :   if (ZX_equal(f1, f)) return myconcat(G,f); /* f = product of Phi_n, n odd */
    1557             : 
    1558        1014 :   fs2 = ZX_gcd_all(f1, ZX_deriv(f1), &f2); /* fs2 squarefree */
    1559        1014 :   if (degpol(fs2))
    1560             :   { /* fs contains all Phi_n | f, 4 | n; and only those */
    1561             :     /* In that case, Graeffe(Phi_n) = Phi_{n/2}^2, and Phi_n = Phi_{n/2}(x^2) */
    1562         882 :     GEN fs = RgX_inflate(fs2, 2);
    1563         882 :     (void)ZX_gcd_all(f, fs, &f); /* remove those Phi_n | f, 4 | n */
    1564         882 :     Gs = BD(fs2);
    1565         882 :     if (Gs)
    1566             :     {
    1567             :       long i;
    1568        2190 :       for (i = lg(Gs)-1; i; i--) gel(Gs,i) = RgX_inflate(gel(Gs,i), 2);
    1569             :       /* prod Gs[i] is the product of all Phi_n | f, 4 | n */
    1570         882 :       G = myconcat(G, Gs);
    1571             :     }
    1572             :     /* f2 = f1 / fs2 */
    1573         882 :     f1 = RgX_div(f2, fs2); /* f1 / fs2^2 */
    1574             :   }
    1575        1014 :   fp = ZX_gcd(f, f1); /* contains all Phi_n | f, n > 1 odd; and only those */
    1576        1014 :   if (degpol(fp))
    1577             :   {
    1578         168 :     Gp = BD_odd(fp);
    1579             :     /* Gp is the product of all Phi_n | f, n odd */
    1580         168 :     if (Gp) G = myconcat(G, Gp);
    1581         168 :     f = RgX_div(f, fp);
    1582             :   }
    1583        1014 :   if (degpol(f))
    1584             :   { /* contains all Phi_n originally dividing f, n = 2 mod 4, n > 2;
    1585             :      * and only those
    1586             :      * In that case, Graeffe(Phi_n) = Phi_{n/2}, and Phi_n = Phi_{n/2}(-x) */
    1587         180 :     Gi = BD_odd(ZX_z_unscale(f, -1));
    1588         180 :     if (Gi)
    1589             :     { /* N.B. Phi_2 does not divide f */
    1590         180 :       Gi = ZX_z_unscale(Gi, -1);
    1591             :       /* Gi is the product of all Phi_n | f, n = 2 mod 4 */
    1592         180 :       G = myconcat(G, Gi);
    1593             :     }
    1594             :   }
    1595        1014 :   return G;
    1596             : }
    1597             : 
    1598             : /* Let f be a nonzero QX, return the (squarefree) product of cyclotomic
    1599             :  * divisors of f */
    1600             : GEN
    1601         270 : polcyclofactors(GEN f)
    1602             : {
    1603         270 :   pari_sp av = avma;
    1604         270 :   if (typ(f) != t_POL || !signe(f)) pari_err_TYPE("polcyclofactors",f);
    1605         270 :   (void)RgX_valrem(f, &f);
    1606         270 :   f = Q_primpart(f);
    1607         270 :   RgX_check_ZX(f,"polcyclofactors");
    1608         270 :   if (degpol(f))
    1609             :   {
    1610         270 :     f = BD(ZX_radical(f));
    1611         270 :     if (f) return gc_GEN(av, f);
    1612             :   }
    1613           0 :   retgc_const(av, cgetg(1, t_VEC));
    1614             : }
    1615             : 
    1616             : /* list of all squarefree odd x such that phi(x) = n, P^-(x) > m. Unsorted */
    1617             : static GEN
    1618       16690 : invphi(ulong n, ulong m)
    1619             : {
    1620             :   GEN C, D;
    1621             :   long l, i;
    1622       16690 :   if (n == 1) return mkvecsmall(1);
    1623       12194 :   D = divisorsu(n); l = lg(D);
    1624       12194 :   C = cgetg(1, t_VECSMALL);
    1625       33843 :   for (i = 2; i < l; i++) /* skip 1 */
    1626             :   {
    1627       21649 :     ulong d = D[i], p;
    1628       21649 :     if (d < m) continue;
    1629       17250 :     p = d + 1; if (!uisprime(p)) continue;
    1630        8957 :     C = vecsmall_concat(C, zv_z_mul(invphi(D[l-i], p), p));
    1631             :   }
    1632       12194 :   return C;
    1633             : }
    1634             : 
    1635             : long
    1636       84783 : poliscyclo(GEN f)
    1637             : {
    1638       84783 :   const ulong p = 2147483647; /* prime */
    1639             :   pari_sp av;
    1640             :   long i, n, e, l;
    1641             :   ulong f3, fm3;
    1642             :   GEN D, fp, _3;
    1643       84783 :   if (typ(f) != t_POL) pari_err_TYPE("poliscyclo", f);
    1644       84777 :   n = degpol(f);
    1645       84777 :   if (n <= 0 || !RgX_is_ZX(f)) return 0;
    1646       84771 :   if (!equali1(gel(f,n+2)) || !is_pm1(gel(f,2))) return 0;
    1647        7823 :   if (n == 1) return signe(gel(f,2)) > 0? 2: 1;
    1648        7733 :   av = avma;
    1649        7733 :   f = ZX_deflate_max(f, &e); if (e != 1) n = degpol(f);
    1650        7733 :   D = invphi(n, 1); /* squareefree odd d s.t. phi(d) = n */
    1651        7733 :   l = lg(D); _3 = gmodulss(3, p);
    1652        7733 :   fp = ZX_to_Flx(f, p);
    1653        7733 :   f3 = Flx_eval(fp, 3, p);
    1654        7733 :   fm3 = Flx_eval(fp, p-3, p);
    1655             :   /* f(x^e) is cyclotomic (= Phi_{de}) iff f = Phi_d, where all prime dividing
    1656             :    * e also divide d. */
    1657       10144 :   for (i = 1; i < l; i++)
    1658             :   {
    1659        4382 :     long d = D[i]; /* squarefree odd */
    1660        4382 :     if (odd(e))
    1661             :     {
    1662        3468 :       if (e == 1 || u_ppo(e, d) == 1)
    1663             :       { /* early abort: check whether f(3) = Phi_d(3) or Phi_2d(3) = Phi_d(-3)
    1664             :          * mod p before checking in Z. N.B. phi(d) and value at 3 mod p
    1665             :          * determine Phi_d for all d <= 10^7 */
    1666        3259 :         ulong F3 = Rg_to_Fl(polcyclo_eval(d, _3), p);
    1667        3259 :         if (F3 == f3 && ZX_equal(f, polcyclo(d, varn(f))))
    1668         838 :           return gc_long(av, d * e);
    1669        2421 :         if (F3 == fm3 && ZX_equal(f, polcyclo(2*d, varn(f))))
    1670         638 :           return gc_long(av, 2* d * e);
    1671             :       }
    1672             :     }
    1673             :     else
    1674             :     {
    1675         914 :       if (u_ppo(e, 2*d) == 1)
    1676             :       { /* early abort: check whether f(3) = Phi_2d(3) mod p */
    1677         908 :         ulong F3 = Rg_to_Fl(polcyclo_eval(2*d, _3), p);
    1678         908 :         if (F3 == f3 && ZX_equal(f, polcyclo(2*d, varn(f))))
    1679         495 :           return gc_long(av, 2* d * e);
    1680             :       }
    1681             :     }
    1682             :   }
    1683        5762 :   return gc_long(av, 0);
    1684             : }
    1685             : 
    1686             : long
    1687         882 : poliscycloprod(GEN f)
    1688             : {
    1689         882 :   pari_sp av = avma;
    1690         882 :   long i, d = degpol(f);
    1691         882 :   if (typ(f) != t_POL) pari_err_TYPE("poliscycloprod",f);
    1692         882 :   if (!RgX_is_ZX(f)) return 0;
    1693         882 :   if (!ZX_is_monic(f) || !is_pm1(constant_coeff(f))) return 0;
    1694         882 :   if (d < 2) return (d == 1);
    1695         876 :   if ( degpol(ZX_gcd_all(f, ZX_deriv(f), &f)) )
    1696             :   {
    1697          12 :     d = degpol(f);
    1698          12 :     if (d == 1) return 1;
    1699             :   }
    1700         870 :   f = BD(f); if (!f) return 0;
    1701        3102 :   for (i = lg(f)-1; i; i--) d -= degpol(gel(f,i));
    1702         870 :   return gc_long(av, d == 0);
    1703             : }

Generated by: LCOV version 1.16