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 - ZX.c (source / functions) Hit Total Coverage
Test: PARI/GP v2.18.1 lcov report (development 30139-6baedb63b1) Lines: 714 793 90.0 %
Date: 2025-04-17 09:19:05 Functions: 96 107 89.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Copyright (C) 2007  The PARI group.
       2             : 
       3             : This file is part of the PARI/GP package.
       4             : 
       5             : PARI/GP is free software; you can redistribute it and/or modify it under the
       6             : terms of the GNU General Public License as published by the Free Software
       7             : Foundation; either version 2 of the License, or (at your option) any later
       8             : version. It is distributed in the hope that it will be useful, but WITHOUT
       9             : ANY WARRANTY WHATSOEVER.
      10             : 
      11             : Check the License for details. You should have received a copy of it, along
      12             : with the package; see the file 'COPYING'. If not, write to the Free Software
      13             : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
      14             : 
      15             : #include "pari.h"
      16             : #include "paripriv.h"
      17             : 
      18             : /*******************************************************************/
      19             : /*                                                                 */
      20             : /*                                ZX                               */
      21             : /*                                                                 */
      22             : /*******************************************************************/
      23             : void
      24      366274 : RgX_check_QX(GEN x, const char *s)
      25      366274 : { if (!RgX_is_QX(x)) pari_err_TYPE(stack_strcat(s," [not in Q[X]]"), x); }
      26             : void
      27     2713011 : RgX_check_ZX(GEN x, const char *s)
      28     2713011 : { if (!RgX_is_ZX(x)) pari_err_TYPE(stack_strcat(s," [not in Z[X]]"), x); }
      29             : long
      30      107322 : ZX_max_lg(GEN x)
      31             : {
      32      107322 :   long i, l = 0, lx = lg(x);
      33      648375 :   for (i = 2; i < lx; i++) l = maxss(l, lgefint(gel(x,i)));
      34      107322 :   return l;
      35             : }
      36             : 
      37             : GEN
      38    41389848 : ZX_add(GEN x, GEN y)
      39             : {
      40             :   long lx,ly,i;
      41             :   GEN z;
      42    41389848 :   lx = lg(x); ly = lg(y); if (lx < ly) swapspec(x,y, lx,ly);
      43    41389848 :   z = cgetg(lx,t_POL); z[1] = x[1];
      44   317242588 :   for (i=2; i<ly; i++) gel(z,i) = addii(gel(x,i),gel(y,i));
      45    83269841 :   for (   ; i<lx; i++) gel(z,i) = icopy(gel(x,i));
      46    41269593 :   if (lx == ly) z = ZX_renormalize(z, lx);
      47    41269753 :   if (!lgpol(z)) { set_avma((pari_sp)(z + lx)); return pol_0(varn(x)); }
      48    40053413 :   return z;
      49             : }
      50             : 
      51             : GEN
      52    29589581 : ZX_sub(GEN x,GEN y)
      53             : {
      54    29589581 :   long i, lx = lg(x), ly = lg(y);
      55             :   GEN z;
      56    29589581 :   if (lx >= ly)
      57             :   {
      58    29135153 :     z = cgetg(lx,t_POL); z[1] = x[1];
      59   118272008 :     for (i=2; i<ly; i++) gel(z,i) = subii(gel(x,i),gel(y,i));
      60    29090282 :     if (lx == ly)
      61             :     {
      62    23444997 :       z = ZX_renormalize(z, lx);
      63    23444595 :       if (!lgpol(z)) { set_avma((pari_sp)(z + lx)); z = pol_0(varn(x)); }
      64             :     }
      65             :     else
      66    17419911 :       for (   ; i<lx; i++) gel(z,i) = icopy(gel(x,i));
      67             :   }
      68             :   else
      69             :   {
      70      454428 :     z = cgetg(ly,t_POL); z[1] = y[1];
      71     1199299 :     for (i=2; i<lx; i++) gel(z,i) = subii(gel(x,i),gel(y,i));
      72     1409285 :     for (   ; i<ly; i++) gel(z,i) = negi(gel(y,i));
      73             :   }
      74    29585639 :   return z;
      75             : }
      76             : 
      77             : GEN
      78      599057 : ZX_neg(GEN x)
      79             : {
      80      599057 :   long i, l = lg(x);
      81      599057 :   GEN y = cgetg(l,t_POL);
      82     2468682 :   y[1] = x[1]; for(i=2; i<l; i++) gel(y,i) = negi(gel(x,i));
      83      599138 :   return y;
      84             : }
      85             : GEN
      86     5397267 : ZX_copy(GEN x)
      87             : {
      88     5397267 :   long i, l = lg(x);
      89     5397267 :   GEN y = cgetg(l, t_POL);
      90     5397275 :   y[1] = x[1];
      91    22125069 :   for (i=2; i<l; i++)
      92             :   {
      93    16727810 :     GEN c = gel(x,i);
      94    16727810 :     gel(y,i) = lgefint(c) == 2? gen_0: icopy(c);
      95             :   }
      96     5397259 :   return y;
      97             : }
      98             : 
      99             : GEN
     100       56464 : scalar_ZX(GEN x, long v)
     101             : {
     102             :   GEN z;
     103       56464 :   if (!signe(x)) return pol_0(v);
     104        4558 :   z = cgetg(3, t_POL);
     105        4558 :   z[1] = evalsigne(1) | evalvarn(v);
     106        4558 :   gel(z,2) = icopy(x); return z;
     107             : }
     108             : 
     109             : GEN
     110       23009 : scalar_ZX_shallow(GEN x, long v)
     111             : {
     112             :   GEN z;
     113       23009 :   if (!signe(x)) return pol_0(v);
     114       22725 :   z = cgetg(3, t_POL);
     115       22725 :   z[1] = evalsigne(1) | evalvarn(v);
     116       22725 :   gel(z,2) = x; return z;
     117             : }
     118             : 
     119             : GEN
     120       87350 : ZX_Z_add(GEN y, GEN x)
     121             : {
     122             :   long lz, i;
     123       87350 :   GEN z = cgetg_copy(y, &lz);
     124       87350 :   if (lz == 2) { set_avma((pari_sp)(z + 2)); return scalar_ZX(x,varn(y)); }
     125       76612 :   z[1] = y[1];
     126       76612 :   gel(z,2) = addii(gel(y,2),x);
     127     1773469 :   for(i=3; i<lz; i++) gel(z,i) = icopy(gel(y,i));
     128       76893 :   if (lz==3) z = ZX_renormalize(z,lz);
     129       76612 :   return z;
     130             : }
     131             : GEN
     132       94656 : ZX_Z_add_shallow(GEN y, GEN x)
     133             : {
     134             :   long lz, i;
     135       94656 :   GEN z = cgetg_copy(y, &lz);
     136       94659 :   if (lz == 2) { set_avma((pari_sp)(z + 2)); return scalar_ZX_shallow(x,varn(y)); }
     137       94414 :   z[1] = y[1];
     138       94414 :   gel(z,2) = addii(gel(y,2),x);
     139      552954 :   for(i=3; i<lz; i++) gel(z,i) = gel(y,i);
     140       94399 :   if (lz==3) z = ZX_renormalize(z,lz);
     141       94397 :   return z;
     142             : }
     143             : 
     144             : GEN
     145      181745 : ZX_Z_sub(GEN y, GEN x)
     146             : {
     147             :   long lz, i;
     148      181745 :   GEN z = cgetg_copy(y, &lz);
     149      181745 :   if (lz == 2)
     150             :   { /* scalarpol(negi(x), v) */
     151         441 :     long v = varn(y);
     152         441 :     set_avma((pari_sp)(z + 2));
     153         441 :     if (!signe(x)) return pol_0(v);
     154         441 :     z = cgetg(3,t_POL);
     155         441 :     z[1] = evalvarn(v) | evalsigne(1);
     156         441 :     gel(z,2) = negi(x); return z;
     157             :   }
     158      181304 :   z[1] = y[1];
     159      181304 :   gel(z,2) = subii(gel(y,2),x);
     160      909423 :   for(i=3; i<lz; i++) gel(z,i) = icopy(gel(y,i));
     161      181304 :   if (lz==3) z = ZX_renormalize(z,lz);
     162      181304 :   return z;
     163             : }
     164             : 
     165             : GEN
     166     2714521 : Z_ZX_sub(GEN x, GEN y)
     167             : {
     168             :   long lz, i;
     169     2714521 :   GEN z = cgetg_copy(y, &lz);
     170     2714557 :   if (lz == 2) { set_avma((pari_sp)(z + 2)); return scalar_ZX(x,varn(y)); }
     171     2714557 :   z[1] = y[1];
     172     2714557 :   gel(z,2) = subii(x, gel(y,2));
     173    13602075 :   for(i=3; i<lz; i++) gel(z,i) = negi(gel(y,i));
     174     2714993 :   if (lz==3) z = ZX_renormalize(z,lz);
     175     2714656 :   return z;
     176             : }
     177             : 
     178             : GEN
     179     5083768 : ZX_Z_divexact(GEN y,GEN x)
     180             : {
     181     5083768 :   long i, l = lg(y);
     182     5083768 :   GEN z = cgetg(l,t_POL); z[1] = y[1];
     183    32470984 :   for(i=2; i<l; i++) gel(z,i) = diviiexact(gel(y,i),x);
     184     5081408 :   return z;
     185             : }
     186             : 
     187             : GEN
     188      977795 : ZX_divuexact(GEN y, ulong x)
     189             : {
     190      977795 :   long i, l = lg(y);
     191      977795 :   GEN z = cgetg(l,t_POL); z[1] = y[1];
     192     9684353 :   for(i=2; i<l; i++) gel(z,i) = diviuexact(gel(y,i),x);
     193      977795 :   return z;
     194             : }
     195             : 
     196             : GEN
     197         112 : zx_z_divexact(GEN y, long x)
     198             : {
     199         112 :   long i, l = lg(y);
     200         112 :   GEN z = cgetg(l,t_VECSMALL); z[1] = y[1];
     201         595 :   for (i=2; i<l; i++) z[i] = y[i]/x;
     202         112 :   return z;
     203             : }
     204             : 
     205             : GEN
     206    17810519 : ZX_Z_mul(GEN y,GEN x)
     207             : {
     208             :   GEN z;
     209             :   long i, l;
     210    17810519 :   if (!signe(x)) return pol_0(varn(y));
     211    14814797 :   l = lg(y); z = cgetg(l,t_POL); z[1] = y[1];
     212   163000695 :   for(i=2; i<l; i++) gel(z,i) = mulii(gel(y,i),x);
     213    14809647 :   return z;
     214             : }
     215             : 
     216             : GEN
     217      253094 : ZX_mulu(GEN y, ulong x)
     218             : {
     219             :   GEN z;
     220             :   long i, l;
     221      253094 :   if (!x) return pol_0(varn(y));
     222      253094 :   l = lg(y); z = cgetg(l,t_POL); z[1] = y[1];
     223     1025517 :   for(i=2; i<l; i++) gel(z,i) = mului(x,gel(y,i));
     224      253094 :   return z;
     225             : }
     226             : 
     227             : GEN
     228     6419800 : ZX_shifti(GEN y, long n)
     229             : {
     230             :   GEN z;
     231             :   long i, l;
     232     6419800 :   l = lg(y); z = cgetg(l,t_POL); z[1] = y[1];
     233    30964084 :   for(i=2; i<l; i++) gel(z,i) = shifti(gel(y,i),n);
     234     6416341 :   return ZX_renormalize(z,l);
     235             : }
     236             : 
     237             : GEN
     238      105896 : ZX_remi2n(GEN y, long n)
     239             : {
     240             :   GEN z;
     241             :   long i, l;
     242      105896 :   l = lg(y); z = cgetg(l,t_POL); z[1] = y[1];
     243     4707112 :   for(i=2; i<l; i++) gel(z,i) = remi2n(gel(y,i),n);
     244      104404 :   return ZX_renormalize(z,l);
     245             : }
     246             : 
     247             : GEN
     248       45402 : ZXT_remi2n(GEN z, long n)
     249             : {
     250       45402 :   if (typ(z) == t_POL)
     251       39344 :     return ZX_remi2n(z, n);
     252             :   else
     253             :   {
     254        6058 :     long i,l = lg(z);
     255        6058 :     GEN x = cgetg(l, t_VEC);
     256       18200 :     for (i=1; i<l; i++) gel(x,i) = ZXT_remi2n(gel(z,i), n);
     257        6060 :     return x;
     258             :   }
     259             : }
     260             : 
     261             : GEN
     262        1330 : zx_to_ZX(GEN z)
     263             : {
     264        1330 :   long i, l = lg(z);
     265        1330 :   GEN x = cgetg(l,t_POL);
     266      100954 :   for (i=2; i<l; i++) gel(x,i) = stoi(z[i]);
     267        1330 :   x[1] = evalsigne(l-2!=0)| z[1]; return x;
     268             : }
     269             : 
     270             : GEN
     271     7415868 : ZX_deriv(GEN x)
     272             : {
     273     7415868 :   long i,lx = lg(x)-1;
     274             :   GEN y;
     275             : 
     276     7415868 :   if (lx<3) return pol_0(varn(x));
     277     7333438 :   y = cgetg(lx,t_POL);
     278    38945944 :   for (i=2; i<lx ; i++) gel(y,i) = mului(i-1,gel(x,i+1));
     279     7332122 :   y[1] = x[1]; return y;
     280             : }
     281             : 
     282             : int
     283     2066860 : ZX_equal(GEN V, GEN W)
     284             : {
     285     2066860 :   long i, l = lg(V);
     286     2066860 :   if (lg(W) != l) return 0;
     287     6003398 :   for (i = 2; i < l; i++)
     288     4672389 :     if (!equalii(gel(V,i), gel(W,i))) return 0;
     289     1331009 :   return 1;
     290             : }
     291             : 
     292             : static long
     293   334488266 : ZX_valspec(GEN x, long nx)
     294             : {
     295             :   long vx;
     296   499166993 :   for (vx = 0; vx<nx ; vx++)
     297   499181701 :     if (signe(gel(x,vx))) break;
     298   334488266 :   return vx;
     299             : }
     300             : 
     301             : long
     302      331023 : ZX_val(GEN x)
     303             : {
     304             :   long vx;
     305      331023 :   if (!signe(x)) return LONG_MAX;
     306      265393 :   for (vx = 0;; vx++)
     307      265393 :     if (signe(gel(x,2+vx))) break;
     308      215390 :   return vx;
     309             : }
     310             : long
     311    30291624 : ZX_valrem(GEN x, GEN *Z)
     312             : {
     313             :   long vx;
     314    30291624 :   if (!signe(x)) { *Z = pol_0(varn(x)); return LONG_MAX; }
     315    51006371 :   for (vx = 0;; vx++)
     316    51006371 :     if (signe(gel(x,2+vx))) break;
     317    30291624 :   *Z = RgX_shift_shallow(x, -vx);
     318    30291621 :   return vx;
     319             : }
     320             : 
     321             : GEN
     322          21 : ZX_div_by_X_1(GEN a, GEN *r)
     323             : {
     324          21 :   long l = lg(a), i;
     325          21 :   GEN a0, z0, z = cgetg(l-1, t_POL);
     326          21 :   z[1] = a[1];
     327          21 :   a0 = a + l-1;
     328          21 :   z0 = z + l-2; *z0 = *a0--;
     329        4732 :   for (i=l-3; i>1; i--) /* z[i] = a[i+1] + z[i+1] */
     330             :   {
     331        4711 :     GEN t = addii(gel(a0--,0), gel(z0--,0));
     332        4711 :     gel(z0,0) = t;
     333             :   }
     334          21 :   if (r) *r = addii(gel(a0,0), gel(z0,0));
     335          21 :   return z;
     336             : }
     337             : 
     338             : /* return P(X + c) using destructive Horner, optimize for c = 1,-1 */
     339             : static GEN
     340     3546752 : ZX_translate_basecase(GEN P, GEN c)
     341             : {
     342     3546752 :   pari_sp av = avma;
     343             :   GEN Q, R;
     344             :   long i, k, n;
     345             : 
     346     3546752 :   if (!signe(P) || !signe(c)) return ZX_copy(P);
     347     3506840 :   Q = leafcopy(P);
     348     3506895 :   R = Q+2; n = degpol(P);
     349     3506894 :   if (equali1(c))
     350             :   {
     351    17217315 :     for (i=1; i<=n; i++)
     352             :     {
     353    98365423 :       for (k=n-i; k<n; k++) gel(R,k) = addii(gel(R,k), gel(R,k+1));
     354    14580425 :       if (gc_needed(av,2))
     355             :       {
     356           0 :         if(DEBUGMEM>1) pari_warn(warnmem,"ZX_translate(1), i = %ld/%ld", i,n);
     357           0 :         Q = gc_GEN(av, Q); R = Q+2;
     358             :       }
     359             :     }
     360             :   }
     361      870010 :   else if (equalim1(c))
     362             :   {
     363      953328 :     for (i=1; i<=n; i++)
     364             :     {
     365     3165183 :       for (k=n-i; k<n; k++) gel(R,k) = subii(gel(R,k), gel(R,k+1));
     366      727196 :       if (gc_needed(av,2))
     367             :       {
     368           0 :         if(DEBUGMEM>1) pari_warn(warnmem,"ZX_translate(-1), i = %ld/%ld", i,n);
     369           0 :         Q = gc_GEN(av, Q); R = Q+2;
     370             :       }
     371             :     }
     372             :   }
     373             :   else
     374             :   {
     375     4577792 :     for (i=1; i<=n; i++)
     376             :     {
     377    26237187 :       for (k=n-i; k<n; k++) gel(R,k) = addmulii_inplace(gel(R,k), c, gel(R,k+1));
     378     3933914 :       if (gc_needed(av,2))
     379             :       {
     380           0 :         if(DEBUGMEM>1) pari_warn(warnmem,"ZX_translate, i = %ld/%ld", i,n);
     381           0 :         Q = gc_GEN(av, Q); R = Q+2;
     382             :       }
     383             :     }
     384             :   }
     385     3506479 :   return gc_GEN(av, Q);
     386             : }
     387             : 
     388             : GEN
     389         434 : Xpm1_powu(long n, long s, long v)
     390             : {
     391             :   long d, k;
     392             :   GEN C;
     393         434 :   if (!n) return pol_1(v);
     394         434 :   d = (n + 1) >> 1;
     395         434 :   C = cgetg(n+3, t_POL);
     396         434 :   C[1] = evalsigne(1)| evalvarn(v);
     397         434 :   gel(C,2) = gen_1;
     398         434 :   gel(C,3) = utoipos(n);
     399        1771 :   for (k=2; k <= d; k++)
     400        1337 :     gel(C,k+2) = diviuexact(mului(n-k+1, gel(C,k+1)), k);
     401         434 :   if (s < 0)
     402           0 :     for (k = odd(n)? 0: 1; k <= d; k += 2)
     403           0 :       togglesign_safe(&gel(C,k+2));
     404         434 :   if (s > 0 || !odd(n))
     405        2058 :     for (k = d+1; k <= n; k++) gel(C,k+2) = gel(C,n-k+2);
     406             :   else
     407           0 :     for (k = d+1; k <= n; k++) gel(C,k+2) = negi(gel(C,n-k+2));
     408         434 :   return C;
     409             : }
     410             : /* return (x+u)^n */
     411             : static GEN
     412           0 : Z_XpN_powu(GEN u, long n, long v)
     413             : {
     414             :   pari_sp av;
     415             :   long k;
     416             :   GEN B, C, V;
     417           0 :   if (!n) return pol_1(v);
     418           0 :   if (is_pm1(u))
     419           0 :     return Xpm1_powu(n, signe(u), v);
     420           0 :   av = avma;
     421           0 :   V = gpowers(u, n);
     422           0 :   B = vecbinomial(n);
     423           0 :   C = cgetg(n+3, t_POL);
     424           0 :   C[1] = evalsigne(1)| evalvarn(v);
     425           0 :   for (k=1; k <= n+1; k++)
     426           0 :     gel(C,k+1) = mulii(gel(V,n+2-k), gel(B,k));
     427           0 :   return gerepileupto(av, C);
     428             : }
     429             : 
     430             : GEN
     431     3563440 : ZX_translate(GEN P, GEN c)
     432             : {
     433     3563440 :   pari_sp av = avma;
     434             :   long n;
     435     3563440 :   if (!signe(c)) return ZX_copy(P);
     436     3546755 :   n = degpol(P);
     437     3546751 :   if (n < 220)
     438     3546751 :     return ZX_translate_basecase(P, c);
     439             :   else
     440             :   {
     441           0 :     long d = n >> 1;
     442           0 :     GEN Q = ZX_translate(RgX_shift_shallow(P, -d), c);
     443           0 :     GEN R = ZX_translate(RgXn_red_shallow(P, d), c);
     444           0 :     GEN S = Z_XpN_powu(c, d, varn(P));
     445           0 :     return gerepileupto(av, ZX_add(ZX_mul(Q, S), R));
     446             :   }
     447             : }
     448             : 
     449             : /* P(ax + b) */
     450             : GEN
     451      994797 : ZX_affine(GEN P, GEN a, GEN b)
     452             : {
     453      994797 :   if (signe(b)) P = ZX_translate(P, b);
     454      994797 :   return ZX_unscale(P, a);
     455             : }
     456             : 
     457             : GEN
     458      531132 : ZX_Z_eval(GEN x, GEN y)
     459             : {
     460      531132 :   long i = lg(x)-1, j;
     461      531132 :   pari_sp av = avma;
     462             :   GEN t, r;
     463             : 
     464      531132 :   if (i<=2) return (i==2)? icopy(gel(x,2)): gen_0;
     465      493003 :   if (!signe(y)) return icopy(gel(x,2));
     466             : 
     467      492884 :   t = gel(x,i); i--;
     468             : #if 0 /* standard Horner's rule */
     469             :   for ( ; i>=2; i--)
     470             :     t = addii(mulii(t,y),gel(x,i));
     471             : #endif
     472             :   /* specific attention to sparse polynomials */
     473     2438290 :   for ( ; i>=2; i = j-1)
     474             :   {
     475     2121780 :     for (j = i; !signe(gel(x,j)); j--)
     476      176366 :       if (j==2)
     477             :       {
     478        2975 :         if (i != j) y = powiu(y, i-j+1);
     479        2975 :         return gc_INT(av, mulii(t,y));
     480             :       }
     481     1945414 :     r = (i==j)? y: powiu(y, i-j+1);
     482     1945419 :     t = addii(mulii(t,r), gel(x,j));
     483     1945408 :     if (gc_needed(av,2))
     484             :     {
     485           0 :       if (DEBUGMEM>1) pari_warn(warnmem,"ZX_Z_eval: i = %ld",i);
     486           0 :       t = gc_INT(av, t);
     487             :     }
     488             :   }
     489      489901 :   return gc_INT(av, t);
     490             : }
     491             : 
     492             : /* Return 2^(n degpol(P))  P(x >> n) */
     493             : GEN
     494           0 : ZX_rescale2n(GEN P, long n)
     495             : {
     496           0 :   long i, l = lg(P), ni = n;
     497             :   GEN Q;
     498           0 :   if (l==2) return pol_0(varn(P));
     499           0 :   Q = cgetg(l,t_POL);
     500           0 :   gel(Q,l-1) = icopy(gel(P,l-1));
     501           0 :   for (i=l-2; i>=2; i--)
     502             :   {
     503           0 :     gel(Q,i) = shifti(gel(P,i), ni);
     504           0 :     ni += n;
     505             :   }
     506           0 :   Q[1] = P[1]; return Q;
     507             : }
     508             : 
     509             : /* Return h^deg(P) P(x / h), not memory clean. h integer, P ZX */
     510             : GEN
     511       35828 : ZX_rescale(GEN P, GEN h)
     512             : {
     513       35828 :   long l = lg(P);
     514       35828 :   GEN Q = cgetg(l,t_POL);
     515       35830 :   if (l != 2)
     516             :   {
     517       35830 :     long i = l-1;
     518       35830 :     GEN hi = h;
     519       35830 :     gel(Q,i) = gel(P,i);
     520       35830 :     if (l != 3) { i--; gel(Q,i) = mulii(gel(P,i), h); }
     521      111381 :     for (i--; i>=2; i--) { hi = mulii(hi,h); gel(Q,i) = mulii(gel(P,i), hi); }
     522             :   }
     523       35831 :   Q[1] = P[1]; return Q;
     524             : }
     525             : /* Return h^(deg(P)-1) P(x / h), P!=0, h=lt(P), memory unclean; monic result */
     526             : GEN
     527           0 : ZX_rescale_lt(GEN P)
     528             : {
     529           0 :   long l = lg(P);
     530           0 :   GEN Q = cgetg(l,t_POL);
     531           0 :   gel(Q,l-1) = gen_1;
     532           0 :   if (l != 3)
     533             :   {
     534           0 :     long i = l-1;
     535           0 :     GEN h = gel(P,i), hi = h;
     536           0 :     i--; gel(Q,i) = gel(P,i);
     537           0 :     if (l != 4) { i--; gel(Q,i) = mulii(gel(P,i), h); }
     538           0 :     for (i--; i>=2; i--) { hi = mulii(hi,h); gel(Q,i) = mulii(gel(P,i), hi); }
     539             :   }
     540           0 :   Q[1] = P[1]; return Q;
     541             : }
     542             : 
     543             : /*Eval x in 2^(k*BIL) in linear time*/
     544             : static GEN
     545    95832987 : ZX_eval2BILspec(GEN x, long k, long nx)
     546             : {
     547    95832987 :   pari_sp av = avma;
     548    95832987 :   long i,j, lz = k*nx, ki;
     549    95832987 :   GEN pz = cgetipos(2+lz);
     550    95828513 :   GEN nz = cgetipos(2+lz);
     551  4208381197 :   for(i=0; i < lz; i++)
     552             :   {
     553  4112542486 :     *int_W(pz,i) = 0UL;
     554  4112542486 :     *int_W(nz,i) = 0UL;
     555             :   }
     556  1284206423 :   for(i=0, ki=0; i<nx; i++, ki+=k)
     557             :   {
     558  1188367712 :     GEN c = gel(x,i);
     559  1188367712 :     long lc = lgefint(c)-2;
     560  1188367712 :     if (signe(c)==0) continue;
     561   964672455 :     if (signe(c) > 0)
     562  2328362810 :       for (j=0; j<lc; j++) *int_W(pz,j+ki) = *int_W(c,j);
     563             :     else
     564   340405985 :       for (j=0; j<lc; j++) *int_W(nz,j+ki) = *int_W(c,j);
     565             :   }
     566    95838711 :   pz = int_normalize(pz,0);
     567    95844762 :   nz = int_normalize(nz,0); return gc_INT(av, subii(pz,nz));
     568             : }
     569             : 
     570             : static long
     571   172174376 : ZX_expispec(GEN x, long nx)
     572             : {
     573   172174376 :   long i, m = 0;
     574  1556432160 :   for(i = 0; i < nx; i++)
     575             :   {
     576  1384299064 :     long e = expi(gel(x,i));
     577  1384257784 :     if (e > m) m = e;
     578             :   }
     579   172133096 :   return m;
     580             : }
     581             : 
     582             : static GEN
     583    57585732 : Z_mod2BIL_ZX(GEN x, long bs, long d, long vx)
     584             : {
     585    57585732 :   long i, offset, lm = lgefint(x)-2, l = d+vx+3, sx = signe(x);
     586    57585732 :   GEN s1 = int2n(bs*BITS_IN_LONG), pol = cgetg(l, t_POL);
     587    57567546 :   int carry = 0;
     588    57567546 :   pol[1] = evalsigne(1);
     589    78125218 :   for (i=0; i<vx; i++) gel(pol,i+2) = gen_0;
     590  1317888674 :   for (offset=0; i <= d+vx; i++, offset += bs)
     591             :   {
     592  1260469499 :     pari_sp av = avma;
     593  1260469499 :     long lz = minss(bs, lm-offset);
     594  1260377485 :     GEN z = lz > 0 ?adduispec_offset(carry, x, offset, lz): utoi(carry);
     595  1260205912 :     if (lgefint(z) == 3+bs) { carry = 1; z = gen_0;}
     596             :     else
     597             :     {
     598  1246754880 :       carry = (lgefint(z) == 2+bs && (HIGHBIT & *int_W(z,bs-1)));
     599  1246754880 :       if (carry)
     600    57248116 :         z = gc_INT(av, (sx==-1)? subii(s1,z): subii(z,s1));
     601  1189506764 :       else if (sx==-1) togglesign(z);
     602             :     }
     603  1260321128 :     gel(pol,i+2) = z;
     604             :   }
     605    57419175 :   return ZX_renormalize(pol,l);
     606             : }
     607             : 
     608             : static GEN
     609    18126895 : ZX_sqrspec_sqri(GEN x, long nx, long ex, long v)
     610             : {
     611    18126895 :   long e = 2*ex + expu(nx) + 3;
     612    18126776 :   long N = divsBIL(e)+1;
     613    18126672 :   GEN  z = sqri(ZX_eval2BILspec(x,N,nx));
     614    18123597 :   return Z_mod2BIL_ZX(z, N, nx*2-2, v);
     615             : }
     616             : 
     617             : static GEN
     618    38208865 : ZX_mulspec_mulii(GEN x, GEN y, long nx, long ny, long ex, long ey, long v)
     619             : {
     620    38208865 :   long e = ex + ey + expu(minss(nx,ny)) + 3;
     621    38208460 :   long N = divsBIL(e)+1;
     622    38208454 :   GEN  z = mulii(ZX_eval2BILspec(x,N,nx), ZX_eval2BILspec(y,N,ny));
     623    38203536 :   return Z_mod2BIL_ZX(z, N, nx+ny-2, v);
     624             : }
     625             : 
     626             : INLINE GEN
     627   315115462 : ZX_sqrspec_basecase_limb(GEN x, long a, long i)
     628             : {
     629   315115462 :   pari_sp av = avma;
     630   315115462 :   GEN s = gen_0;
     631   315115462 :   long j, l = (i+1)>>1;
     632   621773760 :   for (j=a; j<l; j++)
     633             :   {
     634   307583755 :     GEN xj = gel(x,j), xx = gel(x,i-j);
     635   307583755 :     if (signe(xj) && signe(xx))
     636   304878984 :       s = addii(s, mulii(xj, xx));
     637             :   }
     638   314190005 :   s = shifti(s,1);
     639   314508308 :   if ((i&1) == 0)
     640             :   {
     641   195766151 :     GEN t = gel(x, i>>1);
     642   195766151 :     if (signe(t))
     643   195525492 :       s = addii(s, sqri(t));
     644             :   }
     645   314086308 :   return gc_INT(av,s);
     646             : }
     647             : 
     648             : static GEN
     649    76327081 : ZX_sqrspec_basecase(GEN x, long nx, long v)
     650             : {
     651             :   long i, lz, nz;
     652             :   GEN z;
     653             : 
     654    76327081 :   lz = (nx << 1) + 1; nz = lz-2;
     655    76327081 :   lz += v;
     656    76327081 :   z = cgetg(lz,t_POL); z[1] = evalsigne(1); z += 2;
     657    76520241 :   for (i=0; i<v; i++) gel(z++, 0) = gen_0;
     658   271993579 :   for (i=0; i<nx; i++)
     659   195825990 :     gel(z,i) = ZX_sqrspec_basecase_limb(x, 0, i);
     660   195770231 :   for (  ; i<nz; i++) gel(z,i) = ZX_sqrspec_basecase_limb(x, i-nx+1, i);
     661    76147336 :   z -= v+2; return z;
     662             : }
     663             : 
     664             : static GEN
     665    43543422 : Z_sqrshiftspec_ZX(GEN x, long vx)
     666             : {
     667    43543422 :   long i, nz = 2*vx+1;
     668    43543422 :   GEN z = cgetg(2+nz, t_POL);
     669    43539989 :   z[1] = evalsigne(1);
     670    46348813 :   for(i=2;i<nz+1;i++) gel(z,i) = gen_0;
     671    43539989 :   gel(z,nz+1) = sqri(x);
     672    43503621 :   return z;
     673             : }
     674             : 
     675             : static GEN
     676    47637411 : Z_ZX_mulshiftspec(GEN x, GEN y, long ny, long vz)
     677             : {
     678    47637411 :   long i, nz = vz+ny;
     679    47637411 :   GEN z = cgetg(2+nz, t_POL);
     680    47637420 :   z[1] = evalsigne(1);
     681   188308948 :   for (i=0; i<vz; i++)   gel(z,i+2)    = gen_0;
     682   135150253 :   for (i=0; i<ny; i++) gel(z,i+vz+2) = mulii(x, gel(y,i));
     683    47630412 :   return z;
     684             : }
     685             : 
     686             : GEN
     687   138669895 : ZX_sqrspec(GEN x, long nx)
     688             : {
     689             : #ifdef PARI_KERNEL_GMP
     690    79790359 :   const long low[]={ 17, 32, 96, 112, 160, 128, 128, 160, 160, 160, 160, 160, 176, 192, 192, 192, 192, 192, 224, 224, 224, 240, 240, 240, 272, 288, 288, 240, 288, 304, 304, 304, 304, 304, 304, 352, 352, 368, 352, 352, 352, 368, 368, 432, 432, 496, 432, 496, 496};
     691    79790359 :   const long high[]={ 102860, 70254, 52783, 27086, 24623, 18500, 15289, 13899, 12635, 11487, 10442, 9493, 8630, 7845, 7132, 7132, 6484, 6484, 5894, 5894, 4428, 4428, 3660, 4428, 3660, 3660, 2749, 2499, 2272, 2066, 1282, 1282, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 963, 963, 724, 658, 658, 658, 528, 528, 528, 528};
     692             : #else
     693    58879536 :   const long low[]={ 17, 17, 32, 32, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 112, 112, 128, 112, 112, 112, 112, 112, 128, 128, 160, 160, 112, 128, 128, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 176, 160, 160, 176, 160, 160, 176, 176, 208, 176, 176, 176, 192, 192, 176, 176, 224, 176, 224, 224, 176, 224, 224, 224, 176, 176, 176, 176, 176, 176, 176, 176, 224, 176, 176, 224, 224, 224, 224, 224, 224, 224, 240, 288, 240, 288, 288, 240, 288, 288, 240, 240, 304, 304};
     694    58879536 :   const long high[]={ 165657, 85008, 52783, 43622, 32774, 27086, 22385, 15289, 13899, 12635, 11487, 10442, 9493, 7845, 6484, 6484, 5894, 5894, 4871, 4871, 4428, 4026, 3660, 3660, 3660, 3327, 3327, 3024, 2749, 2749, 2272, 2749, 2499, 2499, 2272, 1878, 1878, 1878, 1707, 1552, 1552, 1552, 1552, 1552, 1411, 1411, 1411, 1282, 1282, 1282, 1282, 1282, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1166, 1060, 1060, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 963, 876, 876, 876, 876, 796, 658, 724, 658, 724, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 658, 336, 658, 658, 592, 336, 336};
     695             : #endif
     696   138669895 :   const long nblow = numberof(low);
     697             :   pari_sp av;
     698             :   long ex, vx;
     699             :   GEN z;
     700   138669895 :   if (!nx) return pol_0(0);
     701   137880539 :   vx = ZX_valspec(x,nx); nx-=vx; x+=vx;
     702   137995742 :   if (nx==1) return Z_sqrshiftspec_ZX(gel(x, 0), vx);
     703    94452210 :   av = avma;
     704    94452210 :   ex = ZX_expispec(x,nx);
     705    94445605 :   if (nx-2 < nblow && low[nx-2]<=ex && ex<=high[nx-2])
     706    76327800 :     z = ZX_sqrspec_basecase(x, nx, 2*vx);
     707             :   else
     708    18117805 :     z = ZX_sqrspec_sqri(x, nx, ex, 2*vx);
     709    94368815 :   return gerepileupto(av, z);
     710             : }
     711             : 
     712             : GEN
     713   138675069 : ZX_sqr(GEN x)
     714             : {
     715   138675069 :   GEN z = ZX_sqrspec(x+2, lgpol(x));
     716   138554890 :   z[1] = x[1];
     717   138554890 :   return z;
     718             : }
     719             : 
     720             : GEN
     721   122680196 : ZX_mulspec(GEN x, GEN y, long nx, long ny)
     722             : {
     723             :   pari_sp av;
     724             :   long ex, ey, vx, vy, v;
     725   122680196 :   if (!nx || !ny) return pol_0(0);
     726    98259910 :   vx = ZX_valspec(x,nx); nx-=vx; x += vx;
     727    98260102 :   vy = ZX_valspec(y,ny); ny-=vy; y += vy;
     728    98263095 :   v = vx + vy;
     729    98263095 :   if (nx==1) return Z_ZX_mulshiftspec(gel(x,0), y, ny, v);
     730    60514204 :   if (ny==1) return Z_ZX_mulshiftspec(gel(y,0), x, nx, v);
     731    50625627 :   if (nx == 2 && ny == 2)
     732             :   {
     733    12417611 :     GEN a0 = gel(x,0), a1 = gel(x,1), A0, A1, A2;
     734    12417611 :     GEN b0 = gel(y,0), b1 = gel(y,1), z = cgetg(5 + v, t_POL);
     735             :     long i;
     736    12417658 :     z[1] = evalvarn(0) | evalsigne(1);
     737    12417658 :     A0 = mulii(a0, b0);
     738    12417291 :     A2 = mulii(a1, b1); av = avma;
     739    12417144 :     A1 = gc_INT(av, subii(addii(A0,A2),
     740             :                                    mulii(subii(a1,a0), subii(b1,b0))));
     741    12417474 :     i = 4 + v;
     742    12417474 :     gel(z,i--) = A2;
     743    12417474 :     gel(z,i--) = A1;
     744    14523205 :     gel(z,i--) = A0; while (i > 1) gel(z, i--) = gen_0;
     745    12417474 :     return z;
     746             :   }
     747             : #if 0
     748             :   /* generically slower even when degrees differ a lot; sometimes about twice
     749             :    * faster when bitsize is moderate */
     750             :   if (DEBUGVAR)
     751             :     return RgX_mulspec(x - vx, y - vy, nx + vx, ny + vy);
     752             : #endif
     753    38208016 :   av = avma;
     754    38208016 :   ex = ZX_expispec(x, nx);
     755    38207968 :   ey = ZX_expispec(y, ny);
     756    38208388 :   return gerepileupto(av,  ZX_mulspec_mulii(x,y,nx,ny,ex,ey,v));
     757             : }
     758             : GEN
     759   114217052 : ZX_mul(GEN x, GEN y)
     760             : {
     761             :   GEN z;
     762   114217052 :   if (x == y) return ZX_sqr(x);
     763   113478554 :   z = ZX_mulspec(x+2,y+2,lgpol(x),lgpol(y));
     764   113471996 :   z[1] = x[1];
     765   113471996 :   if (!signe(y)) z[1] &= VARNBITS;
     766   113471996 :   return z;
     767             : }
     768             : 
     769             : /* x,y two ZX in the same variable; assume y is monic */
     770             : GEN
     771    11065928 : ZX_rem(GEN x, GEN y)
     772             : {
     773             :   long vx, dx, dy, dz, i, j, sx, lr;
     774             :   pari_sp av0, av;
     775             :   GEN z,p1,rem;
     776             : 
     777    11065928 :   vx = varn(x);
     778    11065928 :   dy = degpol(y);
     779    11065876 :   dx = degpol(x);
     780    11065887 :   if (dx < dy) return ZX_copy(x);
     781     6068620 :   if (!dy) return pol_0(vx); /* y is constant */
     782     6065855 :   av0 = avma; dz = dx-dy;
     783     6065855 :   z=cgetg(dz+3,t_POL); z[1] = x[1];
     784     6065888 :   x += 2; y += 2; z += 2;
     785             : 
     786     6065888 :   p1 = gel(x,dx);
     787     6065888 :   gel(z,dz) = icopy(p1);
     788    28641996 :   for (i=dx-1; i>=dy; i--)
     789             :   {
     790    22576130 :     av=avma; p1=gel(x,i);
     791   212849748 :     for (j=i-dy+1; j<=i && j<=dz; j++)
     792   190286675 :       p1 = subii(p1, mulii(gel(z,j),gel(y,i-j)));
     793    22563073 :     gel(z,i-dy) = avma == av? icopy(p1): gc_INT(av, p1);
     794             :   }
     795     6065866 :   rem = (GEN)avma; av = (pari_sp)new_chunk(dx+3);
     796     8966713 :   for (sx=0; ; i--)
     797             :   {
     798     8966713 :     p1 = gel(x,i);
     799    57520218 :     for (j=0; j<=i && j<=dz; j++)
     800    48553671 :       p1 = subii(p1, mulii(gel(z,j),gel(y,i-j)));
     801     8966547 :     if (signe(p1)) { sx = 1; break; }
     802     3277518 :     if (!i) break;
     803     2900911 :     set_avma(av);
     804             :   }
     805     6065636 :   lr=i+3; rem -= lr;
     806     6065636 :   rem[0] = evaltyp(t_POL) | _evallg(lr);
     807     6065636 :   rem[1] = z[-1];
     808     6065636 :   p1 = gc_INT((pari_sp)rem, p1);
     809     6065828 :   rem += 2; gel(rem,i) = p1;
     810    33878112 :   for (i--; i>=0; i--)
     811             :   {
     812    27812788 :     av=avma; p1 = gel(x,i);
     813   249758163 :     for (j=0; j<=i && j<=dz; j++)
     814   221982801 :       p1 = subii(p1, mulii(gel(z,j),gel(y,i-j)));
     815    27775362 :     gel(rem,i) = avma == av? icopy(p1): gc_INT(av, p1);
     816             :   }
     817     6065324 :   rem -= 2;
     818     6065324 :   if (!sx) (void)ZX_renormalize(rem, lr);
     819     6065324 :   return gerepileupto(av0,rem);
     820             : }
     821             : 
     822             : /* return x(1) */
     823             : GEN
     824        4718 : ZX_eval1(GEN x)
     825             : {
     826        4718 :   pari_sp av = avma;
     827        4718 :   long i = lg(x)-1;
     828             :   GEN s;
     829        4718 :   if (i < 2) return gen_0;
     830        4193 :   s = gel(x,i); i--;
     831        4193 :   if (i == 1) return icopy(s);
     832       34608 :   for ( ; i>=2; i--)
     833             :   {
     834       31423 :     GEN c = gel(x,i);
     835       31423 :     if (signe(c)) s = addii(s, c);
     836             :   }
     837        3185 :   return gc_INT(av,s);
     838             : }
     839             : 
     840             : /* reduce T mod X^n - 1. Shallow function */
     841             : GEN
     842     1735980 : ZX_mod_Xnm1(GEN T, ulong n)
     843             : {
     844     1735980 :   long i, j, L = lg(T), l = n+2;
     845             :   GEN S;
     846     1735980 :   if (L <= l) return T;
     847     1573366 :   S = cgetg(l, t_POL);
     848     1573194 :   S[1] = T[1];
     849    12141063 :   for (i = 2; i < l; i++) gel(S,i) = gel(T,i);
     850     7388219 :   for (j = 2; i < L; i++) {
     851     5823634 :     gel(S,j) = addii(gel(S,j), gel(T,i));
     852     5815025 :     if (++j == l) j = 2;
     853             :   }
     854     1564585 :   return normalizepol_lg(S, l);
     855             : }
     856             : 
     857             : static GEN
     858           0 : _ZX_mul(void* E, GEN x, GEN y)
     859           0 : { (void) E; return ZX_mul(x, y); }
     860             : static GEN
     861           0 : _ZX_sqr(void *E, GEN x)
     862           0 : { (void) E; return ZX_sqr(x); }
     863             : 
     864             : static GEN
     865           0 : _ZX_divrem(void * E, GEN x, GEN y, GEN *r)
     866           0 : { (void) E; return RgX_divrem(x, y, r); }
     867             : 
     868             : static GEN
     869           0 : _ZX_add(void * E, GEN x, GEN y)
     870           0 : { (void) E; return ZX_add(x, y); }
     871             : 
     872             : static struct bb_ring ZX_ring = { _ZX_add,_ZX_mul,_ZX_sqr };
     873             : 
     874             : GEN
     875           0 : ZX_digits(GEN x, GEN T)
     876             : {
     877           0 :   long d = degpol(T), n = (lgpol(x)+d-1)/d;
     878           0 :   if (signe(x)==0) return(cgetg(1, t_VEC));
     879           0 :   return gen_digits(x, T, n, NULL, &ZX_ring, _ZX_divrem);
     880             : }
     881             : 
     882             : GEN
     883           0 : ZXV_ZX_fromdigits(GEN x, GEN T)
     884           0 : { return gen_fromdigits(x,T, NULL, &ZX_ring); }
     885             : 
     886             : /*******************************************************************/
     887             : /*                                                                 */
     888             : /*                                ZXV                              */
     889             : /*                                                                 */
     890             : /*******************************************************************/
     891             : 
     892             : int
     893          28 : ZXV_equal(GEN V, GEN W)
     894             : {
     895          28 :   long l = lg(V);
     896          28 :   if (l!=lg(W)) return 0;
     897          28 :   while (--l > 0)
     898          28 :     if (!ZX_equal(gel(V,l), gel(W,l))) return 0;
     899           0 :   return 1;
     900             : }
     901             : 
     902             : GEN
     903        7476 : ZXV_Z_mul(GEN x, GEN y)
     904       29904 : { pari_APPLY_same(ZX_Z_mul(gel(x,i), y)) }
     905             : 
     906             : GEN
     907           0 : ZXV_remi2n(GEN x, long N)
     908           0 : { pari_APPLY_same(ZX_remi2n(gel(x,i), N)) }
     909             : 
     910             : GEN
     911       82943 : ZXV_dotproduct(GEN x, GEN y)
     912             : {
     913       82943 :   pari_sp av = avma;
     914       82943 :   long i, lx = lg(x);
     915             :   GEN c;
     916       82943 :   if (lx == 1) return pol_0(varn(x));
     917       82943 :   c = ZX_mul(gel(x,1), gel(y,1));
     918      392175 :   for (i = 2; i < lx; i++)
     919             :   {
     920      309232 :     GEN t = ZX_mul(gel(x,i), gel(y,i));
     921      309232 :     if (signe(t)) c = ZX_add(c, t);
     922             :   }
     923       82943 :   return gerepileupto(av, c);
     924             : }
     925             : 
     926             : GEN
     927      107581 : ZXC_to_FlxC(GEN x, ulong p, long sv)
     928     4805684 : { pari_APPLY_type(t_COL,typ(gel(x,i))==t_INT ?
     929             :                   Z_to_Flx(gel(x,i), p, sv): ZX_to_Flx(gel(x,i), p)) }
     930             : 
     931             : GEN
     932        8344 : ZXM_to_FlxM(GEN x, ulong p, long sv)
     933       84179 : { pari_APPLY_same(ZXC_to_FlxC(gel(x,i), p, sv)) }
     934             : 
     935             : /*******************************************************************/
     936             : /*                                                                 */
     937             : /*                                ZXQM                             */
     938             : /*                                                                 */
     939             : /*******************************************************************/
     940             : 
     941             : GEN
     942     2605568 : ZXn_mul(GEN x, GEN y, long n)
     943     2605568 : { return RgXn_red_shallow(ZX_mul(x, y), n); }
     944             : 
     945             : GEN
     946        1575 : ZXn_sqr(GEN x, long n)
     947        1575 : { return RgXn_red_shallow(ZX_sqr(x), n); }
     948             : 
     949             : /*******************************************************************/
     950             : /*                                                                 */
     951             : /*                                ZXQM                             */
     952             : /*                                                                 */
     953             : /*******************************************************************/
     954             : 
     955             : static long
     956     5554160 : ZX_expi(GEN x)
     957             : {
     958     5554160 :   if (signe(x)==0) return 0;
     959     2879989 :   if (typ(x)==t_INT) return expi(x);
     960     1303084 :   return ZX_expispec(x+2, lgpol(x));
     961             : }
     962             : 
     963             : static long
     964     1090871 : ZXC_expi(GEN x)
     965             : {
     966     1090871 :   long i, l = lg(x), m=0;
     967     6645031 :   for(i = 1; i < l; i++)
     968             :   {
     969     5554160 :     long e = ZX_expi(gel(x,i));
     970     5554160 :     if (e > m) m = e;
     971             :   }
     972     1090871 :   return m;
     973             : }
     974             : 
     975             : static long
     976      176218 : ZXM_expi(GEN x)
     977             : {
     978      176218 :   long i, l = lg(x), m=0;
     979     1267089 :   for(i = 1; i < l; i++)
     980             :   {
     981     1090871 :     long e = ZXC_expi(gel(x,i));
     982     1090871 :     if (e > m) m = e;
     983             :   }
     984      176218 :   return m;
     985             : }
     986             : 
     987             : static GEN
     988     5554160 : ZX_eval2BIL(GEN x, long k)
     989             : {
     990     5554160 :   if (signe(x)==0) return gen_0;
     991     2879989 :   if (typ(x)==t_INT) return x;
     992     1303084 :   return ZX_eval2BILspec(x+2, k, lgpol(x));
     993             : }
     994             : 
     995             : /*Eval x in 2^(k*BIL) in linear time*/
     996             : static GEN
     997     1090871 : ZXC_eval2BIL(GEN x, long k)
     998             : {
     999     1090871 :   long i, lx = lg(x);
    1000     1090871 :   GEN A = cgetg(lx, t_COL);
    1001     6645031 :   for (i=1; i<lx; i++) gel(A,i) = ZX_eval2BIL(gel(x,i), k);
    1002     1090871 :   return A;
    1003             : }
    1004             : 
    1005             : static GEN
    1006      176218 : ZXM_eval2BIL(GEN x, long k)
    1007             : {
    1008      176218 :   long i, lx = lg(x);
    1009      176218 :   GEN A = cgetg(lx, t_MAT);
    1010     1267089 :   for (i=1; i<lx; i++) gel(A,i) = ZXC_eval2BIL(gel(x,i), k);
    1011      176218 :   return A;
    1012             : }
    1013             : 
    1014             : static GEN
    1015       63700 : Z_mod2BIL_ZXQ(GEN x, long bs, GEN T)
    1016             : {
    1017       63700 :   pari_sp av = avma;
    1018       63700 :   long v = varn(T), d = 2*(degpol(T)-1);
    1019       63700 :   GEN z = Z_mod2BIL_ZX(x, bs, d, 0);
    1020       63700 :   setvarn(z, v);
    1021       63700 :   return gerepileupto(av, ZX_rem(z, T));
    1022             : }
    1023             : 
    1024             : static GEN
    1025       14000 : ZC_mod2BIL_ZXQC(GEN x, long bs, GEN T)
    1026             : {
    1027       14000 :   long i, lx = lg(x);
    1028       14000 :   GEN A = cgetg(lx, t_COL);
    1029       77700 :   for (i=1; i<lx; i++) gel(A,i) = Z_mod2BIL_ZXQ(gel(x,i), bs, T);
    1030       14000 :   return A;
    1031             : }
    1032             : 
    1033             : static GEN
    1034        6328 : ZM_mod2BIL_ZXQM(GEN x, long bs, GEN T)
    1035             : {
    1036        6328 :   long i, lx = lg(x);
    1037        6328 :   GEN A = cgetg(lx, t_MAT);
    1038       20328 :   for (i=1; i<lx; i++) gel(A,i) = ZC_mod2BIL_ZXQC(gel(x,i), bs, T);
    1039        6328 :   return A;
    1040             : }
    1041             : 
    1042             : GEN
    1043        6188 : ZXQM_mul(GEN x, GEN y, GEN T)
    1044             : {
    1045        6188 :   long d = degpol(T);
    1046             :   GEN z;
    1047        6188 :   pari_sp av = avma;
    1048        6188 :   if (d == 0)
    1049           0 :     z = ZM_mul(simplify_shallow(x),simplify_shallow(y));
    1050             :   else
    1051             :   {
    1052        6188 :     long e, N, ex = ZXM_expi(x), ey = ZXM_expi(y), n = lg(x)-1;
    1053        6188 :     e = ex + ey + expu(d) + expu(n) + 4;
    1054        6188 :     N = divsBIL(e)+1;
    1055        6188 :     z = ZM_mul(ZXM_eval2BIL(x,N), ZXM_eval2BIL(y,N));
    1056        6188 :     z = ZM_mod2BIL_ZXQM(z, N, T);
    1057             :   }
    1058        6188 :   return gerepileupto(av, z);
    1059             : }
    1060             : 
    1061             : GEN
    1062         140 : ZXQM_sqr(GEN x, GEN T)
    1063             : {
    1064         140 :   long d = degpol(T);
    1065             :   GEN z;
    1066         140 :   pari_sp av = avma;
    1067         140 :   if (d == 0)
    1068           0 :     z = ZM_sqr(simplify_shallow(x));
    1069             :   else
    1070             :   {
    1071         140 :     long ex = ZXM_expi(x), d = degpol(T), n = lg(x)-1;
    1072         140 :     long e = 2*ex + expu(d) + expu(n) + 4;
    1073         140 :     long N = divsBIL(e)+1;
    1074         140 :     z = ZM_sqr(ZXM_eval2BIL(x,N));
    1075         140 :     z = ZM_mod2BIL_ZXQM(z, N, T);
    1076             :   }
    1077         140 :   return gerepileupto(av, z);
    1078             : }
    1079             : 
    1080             : GEN
    1081        4725 : QXQM_mul(GEN x, GEN y, GEN T)
    1082             : {
    1083        4725 :   GEN dx, nx = Q_primitive_part(x, &dx);
    1084        4725 :   GEN dy, ny = Q_primitive_part(y, &dy);
    1085        4725 :   GEN z = ZXQM_mul(nx, ny, T);
    1086        4725 :   if (dx || dy)
    1087             :   {
    1088        4725 :     GEN d = dx ? dy ? gmul(dx, dy): dx : dy;
    1089        4725 :     if (!gequal1(d)) z = RgM_Rg_mul(z, d);
    1090             :   }
    1091        4725 :   return z;
    1092             : }
    1093             : 
    1094             : GEN
    1095           7 : QXQM_sqr(GEN x, GEN T)
    1096             : {
    1097           7 :   GEN dx, nx = Q_primitive_part(x, &dx);
    1098           7 :   GEN z = ZXQM_sqr(nx, T);
    1099           7 :   if (dx) z = RgM_Rg_mul(z, gsqr(dx));
    1100           7 :   return z;
    1101             : }
    1102             : 
    1103             : static GEN
    1104     1199133 : Z_mod2BIL_Fq(GEN x, long bs, GEN T, GEN p)
    1105             : {
    1106     1199133 :   pari_sp av = avma;
    1107     1199133 :   long v = get_FpX_var(T), d = 2*(get_FpX_degree(T)-1);
    1108     1199133 :   GEN z = Z_mod2BIL_ZX(x, bs, d, 0);
    1109     1199133 :   setvarn(z, v);
    1110     1199133 :   return gerepileupto(av, FpX_rem(z, T, p));
    1111             : }
    1112             : 
    1113             : static GEN
    1114      305402 : ZC_mod2BIL_FqC(GEN x, long bs, GEN T, GEN p)
    1115             : {
    1116      305402 :   long i, lx = lg(x);
    1117      305402 :   GEN A = cgetg(lx, t_COL);
    1118     1504535 :   for (i=1; i<lx; i++) gel(A,i) = Z_mod2BIL_Fq(gel(x,i), bs, T, p);
    1119      305402 :   return A;
    1120             : }
    1121             : 
    1122             : static GEN
    1123       81851 : ZM_mod2BIL_FqM(GEN x, long bs, GEN T, GEN p)
    1124             : {
    1125       81851 :   long i, lx = lg(x);
    1126       81851 :   GEN A = cgetg(lx, t_MAT);
    1127      387253 :   for (i=1; i<lx; i++) gel(A,i) = ZC_mod2BIL_FqC(gel(x,i), bs, T, p);
    1128       81851 :   return A;
    1129             : }
    1130             : 
    1131             : GEN
    1132       81851 : FqM_mul_Kronecker(GEN x, GEN y, GEN T, GEN p)
    1133             : {
    1134       81851 :   pari_sp av = avma;
    1135       81851 :   long ex = ZXM_expi(x), ey = ZXM_expi(y), d= degpol(T), n = lg(x)-1;
    1136       81851 :   long e = ex + ey + expu(d) + expu(n) + 4;
    1137       81851 :   long N = divsBIL(e)+1;
    1138       81851 :   GEN  z = ZM_mul(ZXM_eval2BIL(x,N), ZXM_eval2BIL(y,N));
    1139       81851 :   return gerepileupto(av, ZM_mod2BIL_FqM(z, N, T, p));
    1140             : }
    1141             : 
    1142             : /*******************************************************************/
    1143             : /*                                                                 */
    1144             : /*                                ZXX                              */
    1145             : /*                                                                 */
    1146             : /*******************************************************************/
    1147             : 
    1148             : void
    1149        1022 : RgX_check_ZXX(GEN x, const char *s)
    1150             : {
    1151        1022 :   long k = lg(x)-1;
    1152        9891 :   for ( ; k>1; k--) {
    1153        8869 :     GEN t = gel(x,k);
    1154        8869 :     switch(typ(t)) {
    1155        7812 :       case t_INT: break;
    1156        1057 :       case t_POL: if (RgX_is_ZX(t)) break;
    1157             :       /* fall through */
    1158           0 :       default: pari_err_TYPE(stack_strcat(s, " not in Z[X,Y]"),x);
    1159             :     }
    1160             :   }
    1161        1022 : }
    1162             : 
    1163             : /*Renormalize (in place) polynomial with t_INT or ZX coefficients.*/
    1164             : GEN
    1165   313817679 : ZXX_renormalize(GEN x, long lx)
    1166             : {
    1167             :   long i;
    1168   385133996 :   for (i = lx-1; i>1; i--)
    1169   370319278 :     if (signe(gel(x,i))) break;
    1170   313817679 :   stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + (i+1)));
    1171   313811974 :   setlg(x, i+1); setsigne(x, i!=1); return x;
    1172             : }
    1173             : 
    1174             : GEN
    1175       28548 : ZXX_evalx0(GEN y)
    1176             : {
    1177       28548 :   long i, l = lg(y);
    1178       28548 :   GEN z = cgetg(l,t_POL); z[1] = y[1];
    1179      480693 :   for(i=2; i<l; i++)
    1180             :   {
    1181      452145 :     GEN yi = gel(y,i);
    1182      452145 :     gel(z,i) = typ(yi)==t_INT? yi: constant_coeff(yi);
    1183             :   }
    1184       28548 :   return ZX_renormalize(z,l);
    1185             : }
    1186             : 
    1187             : long
    1188        5355 : ZXX_max_lg(GEN x)
    1189             : {
    1190        5355 :   long i, prec = 0, lx = lg(x);
    1191       37520 :   for (i=2; i<lx; i++)
    1192             :   {
    1193       32165 :     GEN p = gel(x,i);
    1194       32165 :     long l = (typ(p) == t_INT)? lgefint(p): ZX_max_lg(p);
    1195       32165 :     if (l > prec) prec = l;
    1196             :   }
    1197        5355 :   return prec;
    1198             : }
    1199             : 
    1200             : GEN
    1201        8883 : ZXX_Z_mul(GEN y, GEN x)
    1202             : {
    1203        8883 :   long i, l = lg(y);
    1204        8883 :   GEN z = cgetg(l,t_POL); z[1] = y[1];
    1205      230727 :   for(i=2; i<l; i++)
    1206      221844 :     if(typ(gel(y,i))==t_INT)
    1207           0 :       gel(z,i) = mulii(gel(y,i),x);
    1208             :     else
    1209      221844 :       gel(z,i) = ZX_Z_mul(gel(y,i),x);
    1210        8883 :   return z;
    1211             : }
    1212             : 
    1213             : GEN
    1214           0 : ZXX_Z_add_shallow(GEN x, GEN y)
    1215             : {
    1216           0 :   long i, l = lg(x);
    1217             :   GEN z, a;
    1218           0 :   if (signe(x)==0) return scalarpol(y,varn(x));
    1219           0 :   z = cgetg(l,t_POL); z[1] = x[1];
    1220           0 :   a = gel(x,2);
    1221           0 :   gel(z, 2) = typ(a)==t_INT? addii(a,y): ZX_Z_add(a,y);
    1222           0 :   for(i=3; i<l; i++)
    1223           0 :     gel(z,i) = gel(x,i);
    1224           0 :   return z;
    1225             : }
    1226             : 
    1227             : GEN
    1228       56469 : ZXX_Z_divexact(GEN y, GEN x)
    1229             : {
    1230       56469 :   long i, l = lg(y);
    1231       56469 :   GEN z = cgetg(l,t_POL); z[1] = y[1];
    1232      467026 :   for(i=2; i<l; i++)
    1233      410557 :     if(typ(gel(y,i))==t_INT)
    1234        2989 :       gel(z,i) = diviiexact(gel(y,i),x);
    1235             :     else
    1236      407568 :       gel(z,i) = ZX_Z_divexact(gel(y,i),x);
    1237       56469 :   return z;
    1238             : }
    1239             : 
    1240             : /* Kronecker substitution, ZXX -> ZX:
    1241             :  * P(X,Y) = sum_{0<=i<lP} P_i(X) * Y^i, where deg P_i < n.
    1242             :  * Returns P(X,X^(2n-1)) */
    1243             : GEN
    1244    10014673 : RgXX_to_Kronecker_spec(GEN P, long lP, long n)
    1245             : {
    1246    10014673 :   long i, k, N = (n<<1) + 1;
    1247             :   GEN y;
    1248    10014673 :   if (!lP) return pol_0(0);
    1249     9995056 :   y = cgetg((N-2)*lP + 2, t_POL) + 2;
    1250    45127000 :   for (k=i=0; i<lP; i++)
    1251             :   {
    1252             :     long j;
    1253    45128693 :     GEN c = gel(P,i);
    1254    45128693 :     if (typ(c)!=t_POL)
    1255             :     {
    1256     3208038 :       gel(y,k++) = c;
    1257     3208038 :       j = 3;
    1258             :     }
    1259             :     else
    1260             :     {
    1261    41920655 :       long l = lg(c);
    1262    41920655 :       if (l-3 >= n)
    1263           0 :         pari_err_BUG("RgXX_to_Kronecker, P is not reduced mod Q");
    1264   247637011 :       for (j=2; j < l; j++) gel(y,k++) = gel(c,j);
    1265             :     }
    1266    45128811 :     if (i == lP-1) break;
    1267   195665759 :     for (   ; j < N; j++) gel(y,k++) = gen_0;
    1268             :   }
    1269     9994213 :   y-=2; setlg(y, k+2); y[1] = evalsigne(1); return y;
    1270             : }
    1271             : 
    1272             : /* shallow, n = deg(T) */
    1273             : GEN
    1274     1768075 : Kronecker_to_ZXX(GEN z, long n, long v)
    1275             : {
    1276     1768075 :   long i,j,lx,l, N = (n<<1)+1;
    1277             :   GEN x, t;
    1278     1768075 :   l = lg(z); lx = (l-2) / (N-2);
    1279     1768075 :   x = cgetg(lx+3,t_POL);
    1280     1768171 :   x[1] = z[1];
    1281     8932707 :   for (i=2; i<lx+2; i++)
    1282             :   {
    1283     7163907 :     t = cgetg(N,t_POL); t[1] = evalvarn(v);
    1284   107248729 :     for (j=2; j<N; j++) gel(t,j) = gel(z,j);
    1285     7163291 :     z += (N-2);
    1286     7163291 :     gel(x,i) = ZX_renormalize(t,N);
    1287             :   }
    1288     1768800 :   N = (l-2) % (N-2) + 2;
    1289     1768800 :   t = cgetg(N,t_POL); t[1] = evalvarn(v);
    1290     5133486 :   for (j=2; j<N; j++) gel(t,j) = gel(z,j);
    1291     1768468 :   gel(x,i) = ZX_renormalize(t,N);
    1292     1768466 :   return ZXX_renormalize(x, i+1);
    1293             : }
    1294             : 
    1295             : GEN
    1296     6678326 : RgXX_to_Kronecker(GEN P, long n)
    1297             : {
    1298     6678326 :   GEN z = RgXX_to_Kronecker_spec(P+2, lgpol(P), n);
    1299     6678068 :   setvarn(z,varn(P)); return z;
    1300             : }
    1301             : GEN
    1302     3028362 : ZXX_mul_Kronecker(GEN x, GEN y, long n)
    1303     3028362 : { return ZX_mul(RgXX_to_Kronecker(x,n), RgXX_to_Kronecker(y,n)); }
    1304             : 
    1305             : GEN
    1306        5306 : ZXX_sqr_Kronecker(GEN x, long n)
    1307        5306 : { return ZX_sqr(RgXX_to_Kronecker(x,n)); }
    1308             : 
    1309             : /* shallow, n = deg(T) */
    1310             : GEN
    1311       24269 : Kronecker_to_ZXQX(GEN z, GEN T)
    1312             : {
    1313       24269 :   long i,j,lx,l, N = (degpol(T)<<1)+1;
    1314             :   GEN x, t;
    1315       24269 :   l = lg(z); lx = (l-2) / (N-2);
    1316       24269 :   x = cgetg(lx+3,t_POL);
    1317       24269 :   x[1] = z[1];
    1318      236283 :   for (i=2; i<lx+2; i++)
    1319             :   {
    1320      212014 :     t = cgetg(N,t_POL); t[1] = T[1];
    1321     1898244 :     for (j=2; j<N; j++) gel(t,j) = gel(z,j);
    1322      212014 :     z += (N-2);
    1323      212014 :     gel(x,i) = ZX_rem(ZX_renormalize(t,N), T);
    1324             :   }
    1325       24269 :   N = (l-2) % (N-2) + 2;
    1326       24269 :   t = cgetg(N,t_POL); t[1] = T[1];
    1327       57152 :   for (j=2; j<N; j++) gel(t,j) = gel(z,j);
    1328       24269 :   gel(x,i) = ZX_rem(ZX_renormalize(t,N), T);
    1329       24269 :   return ZXX_renormalize(x, i+1);
    1330             : }
    1331             : 
    1332             : GEN
    1333        1904 : ZXQX_sqr(GEN x, GEN T)
    1334             : {
    1335        1904 :   pari_sp av = avma;
    1336        1904 :   long n = degpol(T);
    1337        1904 :   GEN z = ZXX_sqr_Kronecker(x, n);
    1338        1904 :   z = Kronecker_to_ZXQX(z, T);
    1339        1904 :   return gc_GEN(av, z);
    1340             : }
    1341             : 
    1342             : GEN
    1343       22365 : ZXQX_mul(GEN x, GEN y, GEN T)
    1344             : {
    1345       22365 :   pari_sp av = avma;
    1346       22365 :   long n = degpol(T);
    1347       22365 :   GEN z = ZXX_mul_Kronecker(x, y, n);
    1348       22365 :   z = Kronecker_to_ZXQX(z, T);
    1349       22365 :   return gc_GEN(av, z);
    1350             : }
    1351             : 
    1352             : GEN
    1353        8988 : ZXQX_ZXQ_mul(GEN P, GEN U, GEN T)
    1354             : {
    1355             :   long i, lP;
    1356             :   GEN res;
    1357        8988 :   res = cgetg_copy(P, &lP); res[1] = P[1];
    1358       47109 :   for(i=2; i<lP; i++)
    1359       38120 :     gel(res,i) = typ(gel(P,i))==t_POL? ZXQ_mul(U, gel(P,i), T)
    1360       38120 :                                      : gmul(U, gel(P,i));
    1361        8989 :   return ZXX_renormalize(res,lP);
    1362             : }
    1363             : 
    1364             : GEN
    1365     3532612 : QX_mul(GEN x, GEN y)
    1366             : {
    1367     3532612 :   GEN dx, nx = Q_primitive_part(x, &dx);
    1368     3532612 :   GEN dy, ny = Q_primitive_part(y, &dy);
    1369     3532612 :   GEN z = ZX_mul(nx, ny);
    1370     3532612 :   if (dx || dy)
    1371             :   {
    1372     3440172 :     GEN d = dx ? dy ? gmul(dx, dy): dx : dy;
    1373     3440172 :     return ZX_Q_mul(z, d);
    1374             :   } else
    1375       92440 :     return z;
    1376             : }
    1377             : 
    1378             : GEN
    1379       96667 : QX_sqr(GEN x)
    1380             : {
    1381       96667 :   GEN dx, nx = Q_primitive_part(x, &dx);
    1382       96661 :   GEN z = ZX_sqr(nx);
    1383       96668 :   if (dx)
    1384       86296 :     return ZX_Q_mul(z, gsqr(dx));
    1385             :   else
    1386       10372 :     return z;
    1387             : }
    1388             : 
    1389             : GEN
    1390     1834434 : QX_ZX_rem(GEN x, GEN y)
    1391             : {
    1392     1834434 :   pari_sp av = avma;
    1393     1834434 :   GEN d, nx = Q_primitive_part(x, &d);
    1394     1834434 :   GEN r = ZX_rem(nx, y);
    1395     1834434 :   if (d) r = ZX_Q_mul(r, d);
    1396     1834434 :   return gerepileupto(av, r);
    1397             : }
    1398             : 
    1399             : GEN
    1400       13377 : QXQX_mul(GEN x, GEN y, GEN T)
    1401             : {
    1402       13377 :   GEN dx, nx = Q_primitive_part(x, &dx);
    1403       13377 :   GEN dy, ny = Q_primitive_part(y, &dy);
    1404       13377 :   GEN z = ZXQX_mul(nx, ny, T);
    1405       13377 :   if (dx || dy)
    1406             :   {
    1407        8309 :     GEN d = dx ? dy ? gmul(dx, dy): dx : dy;
    1408        8309 :     return ZXX_Q_mul(z, d);
    1409             :   } else
    1410        5068 :     return z;
    1411             : }
    1412             : 
    1413             : GEN
    1414        1904 : QXQX_sqr(GEN x, GEN T)
    1415             : {
    1416        1904 :   GEN dx, nx = Q_primitive_part(x, &dx);
    1417        1904 :   GEN z = ZXQX_sqr(nx, T);
    1418        1904 :   if (dx)
    1419         588 :     return ZXX_Q_mul(z, gsqr(dx));
    1420             :   else
    1421        1316 :     return z;
    1422             : }
    1423             : 
    1424             : GEN
    1425         476 : QXQX_powers(GEN P, long n, GEN T)
    1426             : {
    1427         476 :   GEN v = cgetg(n+2, t_VEC);
    1428             :   long i;
    1429         476 :   gel(v, 1) = pol_1(varn(T));
    1430         476 :   if (n==0) return v;
    1431         476 :   gel(v, 2) = gcopy(P);
    1432        1554 :   for (i = 2; i <= n; i++) gel(v,i+1) = QXQX_mul(P, gel(v,i), T);
    1433         476 :   return v;
    1434             : }
    1435             : 
    1436             : GEN
    1437        3465 : QXQX_QXQ_mul(GEN P, GEN U, GEN T)
    1438             : {
    1439             :   long i, lP;
    1440             :   GEN res;
    1441        3465 :   res = cgetg_copy(P, &lP); res[1] = P[1];
    1442       22715 :   for(i=2; i<lP; i++)
    1443       19250 :     gel(res,i) = typ(gel(P,i))==t_POL? QXQ_mul(U, gel(P,i), T)
    1444       19250 :                                      : gmul(U, gel(P,i));
    1445        3465 :   return ZXX_renormalize(res,lP);
    1446             : }

Generated by: LCOV version 1.16