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 - bibli2.c (source / functions) Coverage Total Hit
Test: PARI/GP v2.19.0 lcov report (development 31057-89c4d54ba6) Lines: 95.3 % 1305 1244
Test Date: 2026-07-25 17:02:42 Functions: 95.9 % 121 116
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              : 
      15              : #include "pari.h"
      16              : #include "paripriv.h"
      17              : 
      18              : /*******************************************************************/
      19              : /**                                                               **/
      20              : /**                      SPECIAL POLYNOMIALS                      **/
      21              : /**                                                               **/
      22              : /*******************************************************************/
      23              : /* Tchebichev polynomial: T0=1; T1=X; T(n)=2*X*T(n-1)-T(n-2)
      24              :  * T(n) = (n/2) sum_{k=0}^{n/2} a_k x^(n-2k)
      25              :  *   where a_k = (-1)^k 2^(n-2k) (n-k-1)! / k!(n-2k)! is an integer
      26              :  *   and a_0 = 2^(n-1), a_k / a_{k-1} = - (n-2k+2)(n-2k+1) / 4k(n-k) */
      27              : GEN
      28         2156 : polchebyshev1(long n, long v) /* Assume 4*n < LONG_MAX */
      29              : {
      30              :   long k, l;
      31              :   pari_sp av;
      32              :   GEN q,a,r;
      33              : 
      34         2156 :   if (v<0) v = 0;
      35              :   /* polchebyshev(-n,1) = polchebyshev(n,1) */
      36         2156 :   if (n < 0) n = -n;
      37         2156 :   if (n==0) return pol_1(v);
      38         2135 :   if (n==1) return pol_x(v);
      39              : 
      40         2093 :   q = cgetg(n+3, t_POL); r = q + n+2;
      41         2093 :   a = int2n(n-1);
      42         2093 :   gel(r--,0) = a;
      43         2093 :   gel(r--,0) = gen_0;
      44        31955 :   for (k=1,l=n; l>1; k++,l-=2)
      45              :   {
      46        29862 :     av = avma;
      47        29862 :     a = diviuuexact(muluui(l, l-1, a), 4*k, n-k);
      48        29862 :     togglesign(a); a = gc_INT(av, a);
      49        29862 :     gel(r--,0) = a;
      50        29862 :     gel(r--,0) = gen_0;
      51              :   }
      52         2093 :   q[1] = evalsigne(1) | evalvarn(v);
      53         2093 :   return q;
      54              : }
      55              : static void
      56           70 : polchebyshev1_eval_aux(long n, GEN x, GEN *pt1, GEN *pt2)
      57              : {
      58              :   GEN t1, t2, b;
      59           70 :   if (n == 1) { *pt1 = gen_1; *pt2 = x; return; }
      60           56 :   if (n == 0) { *pt1 = x; *pt2 = gen_1; return; }
      61           56 :   polchebyshev1_eval_aux((n+1) >> 1, x, &t1, &t2);
      62           56 :   b = gsub(gmul(gmul2n(t1,1), t2), x);
      63           56 :   if (odd(n)) { *pt1 = gadd(gmul2n(gsqr(t1), 1), gen_m1); *pt2 = b; }
      64           42 :   else        { *pt1 = b; *pt2 = gadd(gmul2n(gsqr(t2), 1), gen_m1); }
      65              : }
      66              : static GEN
      67           14 : polchebyshev1_eval(long n, GEN x)
      68              : {
      69              :   GEN t1, t2;
      70              :   long i, v;
      71              :   pari_sp av;
      72              : 
      73           14 :   if (n < 0) n = -n;
      74           14 :   if (n==0) return gen_1;
      75           14 :   if (n==1) return gcopy(x);
      76           14 :   av = avma;
      77           14 :   v = u_lvalrem(n, 2, (ulong*)&n);
      78           14 :   polchebyshev1_eval_aux((n+1)>>1, x, &t1, &t2);
      79           14 :   if (n != 1) t2 = gsub(gmul(gmul2n(t1,1), t2), x);
      80           35 :   for (i = 1; i <= v; i++) t2 = gadd(gmul2n(gsqr(t2), 1), gen_m1);
      81           14 :   return gc_upto(av, t2);
      82              : }
      83              : 
      84              : /* Chebychev  polynomial of the second kind U(n,x): the coefficient in front of
      85              :  * x^(n-2*m) is (-1)^m * 2^(n-2m)*(n-m)!/m!/(n-2m)!  for m=0,1,...,n/2 */
      86              : GEN
      87         2135 : polchebyshev2(long n, long v)
      88              : {
      89              :   pari_sp av;
      90              :   GEN q, a, r;
      91              :   long m;
      92         2135 :   int neg = 0;
      93              : 
      94         2135 :   if (v<0) v = 0;
      95              :   /* polchebyshev(-n,2) = -polchebyshev(n-2,2) */
      96         2135 :   if (n < 0) {
      97         1050 :     if (n == -1) return zeropol(v);
      98         1029 :     neg = 1; n = -n-2;
      99              :   }
     100         2114 :   if (n==0) return neg ? scalar_ZX_shallow(gen_m1, v): pol_1(v);
     101              : 
     102         2072 :   q = cgetg(n+3, t_POL); r = q + n+2;
     103         2072 :   a = int2n(n);
     104         2072 :   if (neg) togglesign(a);
     105         2072 :   gel(r--,0) = a;
     106         2072 :   gel(r--,0) = gen_0;
     107        30807 :   for (m=1; 2*m<= n; m++)
     108              :   {
     109        28735 :     av = avma;
     110        28735 :     a = diviuuexact(muluui(n-2*m+2, n-2*m+1, a), 4*m, n-m+1);
     111        28735 :     togglesign(a); a = gc_INT(av, a);
     112        28735 :     gel(r--,0) = a;
     113        28735 :     gel(r--,0) = gen_0;
     114              :   }
     115         2072 :   q[1] = evalsigne(1) | evalvarn(v);
     116         2072 :   return q;
     117              : }
     118              : static void
     119           91 : polchebyshev2_eval_aux(long n, GEN x, GEN *pu1, GEN *pu2)
     120              : {
     121              :   GEN u1, u2, u, mu1;
     122           91 :   if (n == 1) { *pu1 = gen_1; *pu2 = gmul2n(x,1); return; }
     123           70 :   if (n == 0) { *pu1 = gen_0; *pu2 = gen_1; return; }
     124           70 :   polchebyshev2_eval_aux(n >> 1, x, &u1, &u2);
     125           70 :   mu1 = gneg(u1);
     126           70 :   u = gmul(gadd(u2,u1), gadd(u2,mu1));
     127           70 :   if (odd(n)) { *pu1 = u; *pu2 = gmul(gmul2n(u2,1), gadd(gmul(x,u2), mu1)); }
     128           35 :   else        { *pu2 = u; *pu1 = gmul(gmul2n(u1,1), gadd(u2, gmul(x,mu1))); }
     129              : }
     130              : static GEN
     131           35 : polchebyshev2_eval(long n, GEN x)
     132              : {
     133              :   GEN u1, u2, mu1;
     134           35 :   long neg = 0;
     135              :   pari_sp av;
     136              : 
     137           35 :   if (n < 0) {
     138           14 :     if (n == -1) return gen_0;
     139            7 :     neg = 1; n = -n-2;
     140              :   }
     141           28 :   if (n==0) return neg ? gen_m1: gen_1;
     142           21 :   av = avma;
     143           21 :   polchebyshev2_eval_aux(n>>1, x, &u1, &u2);
     144           21 :   mu1 = gneg(u1);
     145           21 :   if (odd(n)) u2 = gmul(gmul2n(u2,1), gadd(gmul(x,u2), mu1));
     146           14 :   else        u2 = gmul(gadd(u2,u1), gadd(u2,mu1));
     147           21 :   if (neg) u2 = gneg(u2);
     148           21 :   return gc_upto(av, u2);
     149              : }
     150              : 
     151              : GEN
     152         4284 : polchebyshev(long n, long kind, long v)
     153              : {
     154         4284 :   switch (kind)
     155              :   {
     156         2149 :     case 1: return polchebyshev1(n, v);
     157         2135 :     case 2: return polchebyshev2(n, v);
     158            0 :     default: pari_err_FLAG("polchebyshev");
     159              :   }
     160              :   return NULL; /* LCOV_EXCL_LINE */
     161              : }
     162              : GEN
     163         4333 : polchebyshev_eval(long n, long kind, GEN x)
     164              : {
     165         4333 :   if (!x) return polchebyshev(n, kind, 0);
     166           63 :   if (gequalX(x)) return polchebyshev(n, kind, varn(x));
     167           49 :   switch (kind)
     168              :   {
     169           14 :     case 1: return polchebyshev1_eval(n, x);
     170           35 :     case 2: return polchebyshev2_eval(n, x);
     171            0 :     default: pari_err_FLAG("polchebyshev");
     172              :   }
     173              :   return NULL; /* LCOV_EXCL_LINE */
     174              : }
     175              : 
     176              : /* Hermite polynomial H(n,x):  H(n+1) = 2x H(n) - 2n H(n-1)
     177              :  * The coefficient in front of x^(n-2*m) is
     178              :  * (-1)^m * n! * 2^(n-2m)/m!/(n-2m)!  for m=0,1,...,n/2.. */
     179              : GEN
     180         1442 : polhermite(long n, long v)
     181              : {
     182              :   long m;
     183              :   pari_sp av;
     184              :   GEN q,a,r;
     185              : 
     186         1442 :   if (v<0) v = 0;
     187         1442 :   if (n==0) return pol_1(v);
     188              : 
     189         1435 :   q = cgetg(n+3, t_POL); r = q + n+2;
     190         1435 :   a = int2n(n);
     191         1435 :   gel(r--,0) = a;
     192         1435 :   gel(r--,0) = gen_0;
     193        40327 :   for (m=1; 2*m<= n; m++)
     194              :   {
     195        38892 :     av = avma;
     196        38892 :     a = diviuexact(muluui(n-2*m+2, n-2*m+1, a), 4*m);
     197        38892 :     togglesign(a);
     198        38892 :     gel(r--,0) = a = gc_INT(av, a);
     199        38892 :     gel(r--,0) = gen_0;
     200              :   }
     201         1435 :   q[1] = evalsigne(1) | evalvarn(v);
     202         1435 :   return q;
     203              : }
     204              : static void
     205           21 : err_hermite(long n)
     206           21 : { pari_err_DOMAIN("polhermite", "degree", "<", gen_0, stoi(n)); }
     207              : GEN
     208         1477 : polhermite_eval0(long n, GEN x, long flag)
     209              : {
     210              :   long i;
     211              :   pari_sp av, av2;
     212              :   GEN x2, u, v;
     213              : 
     214         1477 :   if (n < 0) err_hermite(n);
     215         1470 :   if (!x || gequalX(x))
     216              :   {
     217         1442 :     long v = x? varn(x): 0;
     218         1442 :     if (flag)
     219              :     {
     220           14 :       if (!n) err_hermite(-1);
     221            7 :       retmkvec2(polhermite(n-1,v),polhermite(n,v));
     222              :     }
     223         1428 :     return polhermite(n, v);
     224              :   }
     225           28 :   if (n==0)
     226              :   {
     227            7 :     if (flag) err_hermite(-1);
     228            0 :     return gen_1;
     229              :   }
     230           21 :   if (n==1)
     231              :   {
     232            0 :     if (flag) retmkvec2(gen_1, gmul2n(x,1));
     233            0 :     return gmul2n(x,1);
     234              :   }
     235           21 :   av = avma; x2 = gmul2n(x,1); v = gen_1; u = x2;
     236           21 :   av2= avma;
     237         7070 :   for (i=1; i<n; i++)
     238              :   { /* u = H_i(x), v = H_{i-1}(x), compute t = H_{i+1}(x) */
     239              :     GEN t;
     240         7049 :     if ((i & 0xff) == 0) (void)gc_all(av2,2,&u, &v);
     241         7049 :     t = gsub(gmul(x2, u), gmulsg(2*i,v));
     242         7049 :     v = u; u = t;
     243              :   }
     244           21 :   if (flag) return gc_GEN(av, mkvec2(v, u));
     245           14 :   return gc_upto(av, u);
     246              : }
     247              : GEN
     248            0 : polhermite_eval(long n, GEN x) { return polhermite_eval0(n, x, 0); }
     249              : 
     250              : /* Legendre polynomial
     251              :  * L0=1; L1=X; (n+1)*L(n+1)=(2*n+1)*X*L(n)-n*L(n-1)
     252              :  * L(n) = 2^-n sum_{k=0}^{n/2} a_k x^(n-2k)
     253              :  *   where a_k = (-1)^k (2n-2k)! / k! (n-k)! (n-2k)! is an integer
     254              :  *   and a_0 = binom(2n,n), a_k / a_{k-1} = - (n-2k+1)(n-2k+2) / 2k (2n-2k+1) */
     255              : GEN
     256         2163 : pollegendre(long n, long v)
     257              : {
     258              :   long k, l;
     259              :   pari_sp av;
     260              :   GEN a, r, q;
     261              : 
     262         2163 :   if (v<0) v = 0;
     263              :   /* pollegendre(-n) = pollegendre(n-1) */
     264         2163 :   if (n < 0) n = -n-1;
     265         2163 :   if (n==0) return pol_1(v);
     266         2121 :   if (n==1) return pol_x(v);
     267              : 
     268         2079 :   av = avma;
     269         2079 :   q = cgetg(n+3, t_POL); r = q + n+2;
     270         2079 :   gel(r--,0) = a = binomialuu(n<<1,n);
     271         2079 :   gel(r--,0) = gen_0;
     272        31423 :   for (k=1,l=n; l>1; k++,l-=2)
     273              :   { /* l = n-2*k+2 */
     274        29344 :     av = avma;
     275        29344 :     a = diviuuexact(muluui(l, l-1, a), 2*k, n+l-1);
     276        29344 :     togglesign(a); a = gc_INT(av, a);
     277        29344 :     gel(r--,0) = a;
     278        29344 :     gel(r--,0) = gen_0;
     279              :   }
     280         2079 :   q[1] = evalsigne(1) | evalvarn(v);
     281         2079 :   return gc_upto(av, gmul2n(q,-n));
     282              : }
     283              : /* q such that Ln * 2^n = q(x^2) [n even] or x q(x^2) [n odd] */
     284              : GEN
     285            0 : pollegendre_reduced(long n, long v)
     286              : {
     287              :   long k, l, N;
     288              :   pari_sp av;
     289              :   GEN a, r, q;
     290              : 
     291            0 :   if (v<0) v = 0;
     292              :   /* pollegendre(-n) = pollegendre(n-1) */
     293            0 :   if (n < 0) n = -n-1;
     294            0 :   if (n<=1) return n? scalarpol_shallow(gen_2,v): pol_1(v);
     295              : 
     296            0 :   N = n >> 1;
     297            0 :   q = cgetg(N+3, t_POL); r = q + N+2;
     298            0 :   gel(r--,0) = a = binomialuu(n<<1,n);
     299            0 :   for (k=1,l=n; l>1; k++,l-=2)
     300              :   { /* l = n-2*k+2 */
     301            0 :     av = avma;
     302            0 :     a = diviuuexact(muluui(l, l-1, a), 2*k, n+l-1);
     303            0 :     togglesign(a);
     304            0 :     gel(r--,0) = a = gc_INT(av, a);
     305              :   }
     306            0 :   q[1] = evalsigne(1) | evalvarn(v);
     307            0 :   return q;
     308              : }
     309              : 
     310              : GEN
     311         2177 : pollegendre_eval0(long n, GEN x, long flag)
     312              : {
     313              :   pari_sp av;
     314              :   GEN u, v;
     315              :   long i;
     316              : 
     317         2177 :   if (n < 0) n = -n-1; /* L(-n) = L(n-1) */
     318              :   /* n >= 0 */
     319         2177 :   if (flag && flag != 1) pari_err_FLAG("pollegendre");
     320         2177 :   if (!x || gequalX(x))
     321              :   {
     322         2156 :     long v = x? varn(x): 0;
     323         2156 :     if (flag) retmkvec2(pollegendre(n-1,v), pollegendre(n,v));
     324         2149 :     return pollegendre(n, v);
     325              :   }
     326           21 :   if (n==0)
     327              :   {
     328            0 :     if (flag) retmkvec2(gen_1, gcopy(x));
     329            0 :     return gen_1;
     330              :   }
     331           21 :   if (n==1)
     332              :   {
     333            0 :     if (flag) retmkvec2(gcopy(x), gen_1);
     334            0 :     return gcopy(x);
     335              :   }
     336           21 :   av = avma; v = gen_1; u = x;
     337         7070 :   for (i=1; i<n; i++)
     338              :   { /* u = P_i(x), v = P_{i-1}(x), compute t = P_{i+1}(x) */
     339              :     GEN t;
     340         7049 :     if ((i & 0xff) == 0) (void)gc_all(av,2,&u, &v);
     341         7049 :     t = gdivgu(gsub(gmul(gmulsg(2*i+1,x), u), gmulsg(i,v)), i+1);
     342         7049 :     v = u; u = t;
     343              :   }
     344           21 :   if (flag) return gc_GEN(av, mkvec2(v, u));
     345           14 :   return gc_upto(av, u);
     346              : }
     347              : GEN
     348            0 : pollegendre_eval(long n, GEN x) { return pollegendre_eval0(n, x, 0); }
     349              : 
     350              : /* Laguerre polynomial
     351              :  * L0^a = 1; L1^a = -X+a+1;
     352              :  * (n+1)*L^a(n+1) = (-X+(2*n+a+1))*L^a(n) - (n+a)*L^a(n-1)
     353              :  * L^a(n) = sum_{k=0}^n (-1)^k * binom(n+a,n-k) * x^k/k! */
     354              : GEN
     355         2128 : pollaguerre(long n, GEN a, long v)
     356              : {
     357         2128 :   pari_sp av = avma;
     358         2128 :   GEN L = cgetg(n+3, t_POL), c1 = gen_1, c2 = mpfact(n);
     359              :   long i;
     360              : 
     361         2128 :   L[1] = evalsigne(1) | evalvarn(v);
     362         2128 :   if (odd(n)) togglesign_safe(&c2);
     363       117404 :   for (i = n; i >= 0; i--)
     364              :   {
     365       115276 :     gel(L, i+2) = gdiv(c1, c2);
     366       115276 :     if (i)
     367              :     {
     368       113148 :       c2 = divis(c2,-i);
     369       113148 :       c1 = gdivgu(gmul(c1, gaddsg(i,a)), n+1-i);
     370              :     }
     371              :   }
     372         2128 :   return gc_GEN(av, L);
     373              : }
     374              : static void
     375           21 : err_lag(long n)
     376           21 : { pari_err_DOMAIN("pollaguerre", "degree", "<", gen_0, stoi(n)); }
     377              : GEN
     378         2163 : pollaguerre_eval0(long n, GEN a, GEN x, long flag)
     379              : {
     380         2163 :   pari_sp av = avma;
     381              :   long i;
     382              :   GEN v, u;
     383              : 
     384         2163 :   if (n < 0) err_lag(n);
     385         2156 :   if (flag && flag != 1) pari_err_FLAG("pollaguerre");
     386         2156 :   if (!a) a = gen_0;
     387         2156 :   if (!x || gequalX(x))
     388              :   {
     389         2128 :     long v = x? varn(x): 0;
     390         2128 :     if (flag)
     391              :     {
     392           14 :       if (!n) err_lag(-1);
     393            7 :       retmkvec2(pollaguerre(n-1,a,v), pollaguerre(n,a,v));
     394              :     }
     395         2114 :     return pollaguerre(n,a,v);
     396              :   }
     397           28 :   if (n==0)
     398              :   {
     399            7 :     if (flag) err_lag(-1);
     400            0 :     return gen_1;
     401              :   }
     402           21 :   if (n==1)
     403              :   {
     404            0 :     if (flag) retmkvec2(gsub(gaddgs(a,1),x), gen_1);
     405            0 :     return gsub(gaddgs(a,1),x);
     406              :   }
     407           21 :   av = avma; v = gen_1; u = gsub(gaddgs(a,1),x);
     408         7070 :   for (i=1; i<n; i++)
     409              :   { /* u = P_i(x), v = P_{i-1}(x), compute t = P_{i+1}(x) */
     410              :     GEN t;
     411         7049 :     if ((i & 0xff) == 0) (void)gc_all(av,2,&u, &v);
     412         7049 :     t = gdivgu(gsub(gmul(gsub(gaddsg(2*i+1,a),x), u), gmul(gaddsg(i,a),v)), i+1);
     413         7049 :     v = u; u = t;
     414              :   }
     415           21 :   if (flag) return gc_GEN(av, mkvec2(v, u));
     416           14 :   return gc_upto(av, u);
     417              : }
     418              : GEN
     419            0 : pollaguerre_eval(long n, GEN x, GEN a) { return pollaguerre_eval0(n, x, a, 0); }
     420              : 
     421              : /* polcyclo(p) = X^(p-1) + ... + 1 */
     422              : static GEN
     423       487799 : polcyclo_prime(long p, long v)
     424              : {
     425       487799 :   GEN T = cgetg(p+2, t_POL);
     426              :   long i;
     427       487799 :   T[1] = evalsigne(1) | evalvarn(v);
     428      3323584 :   for (i = 2; i < p+2; i++) gel(T,i) = gen_1;
     429       487799 :   return T;
     430              : }
     431              : 
     432              : /* cyclotomic polynomial */
     433              : GEN
     434       614581 : polcyclo(long n, long v)
     435              : {
     436              :   long s, q, i, l;
     437       614581 :   pari_sp av=avma;
     438              :   GEN T, P;
     439              : 
     440       614581 :   if (v<0) v = 0;
     441       614581 :   if (n < 3)
     442       126782 :     switch(n)
     443              :     {
     444        34153 :       case 1: return deg1pol_shallow(gen_1, gen_m1, v);
     445        92629 :       case 2: return deg1pol_shallow(gen_1, gen_1, v);
     446            0 :       default: pari_err_DOMAIN("polcyclo", "index", "<=", gen_0, stoi(n));
     447              :     }
     448       487799 :   P = gel(factoru(n), 1); l = lg(P);
     449       487799 :   s = P[1]; T = polcyclo_prime(s, v);
     450       779111 :   for (i = 2; i < l; i++)
     451              :   { /* Phi_{np}(X) = Phi_n(X^p) / Phi_n(X) */
     452       291312 :     s *= P[i];
     453       291312 :     T = RgX_div(RgX_inflate(T, P[i]), T);
     454              :   }
     455              :   /* s = squarefree part of n */
     456       487799 :   q = n / s;
     457       487799 :   if (q == 1) return gc_upto(av, T);
     458       243202 :   return gc_GEN(av, RgX_inflate(T,q));
     459              : }
     460              : 
     461              : /* cyclotomic polynomial */
     462              : GEN
     463       100293 : polcyclo_eval(long n, GEN x)
     464              : {
     465       100293 :   pari_sp av= avma;
     466              :   GEN P, md, xd, yneg, ypos;
     467       100293 :   long vpx, l, s, i, j, q, tx, root_of_1 = 0;
     468              : 
     469       100293 :   if (!x) return polcyclo(n, 0);
     470        15166 :   tx = typ(x);
     471        15166 :   if (gequalX(x)) return polcyclo(n, varn(x));
     472        14571 :   if (n <= 0) pari_err_DOMAIN("polcyclo", "index", "<=", gen_0, stoi(n));
     473        14571 :   if (n == 1) return gsubgs(x, 1);
     474        14571 :   if (tx == t_INT && !signe(x)) return gen_1;
     475        15747 :   while ((n & 3) == 0) { n >>= 1; x = gsqr(x); } /* Phi_4n(x) = Phi_2n(x^2) */
     476              :   /* n not divisible by 4 */
     477        14571 :   if (n == 2) return gc_upto(av, gaddgs(x,1));
     478         6430 :   if (!odd(n)) { n >>= 1; x = gneg(x); } /* Phi_2n(x) = Phi_n(-x) for n>1 odd */
     479              :   /* n odd > 2.  s largest squarefree divisor of n */
     480         6430 :   P = gel(factoru(n), 1); s = zv_prod(P);
     481              :   /* replace n by largest squarefree divisor */
     482         6430 :   q = n/s; if (q != 1) { x = gpowgs(x, q); n = s; }
     483         6430 :   l = lg(P)-1;
     484              :   /* n squarefree odd > 2, l distinct prime divisors. Now handle x = 1 or -1 */
     485         6430 :   if (tx == t_INT) { /* shortcut */
     486         1715 :     if (is_pm1(x))
     487              :     {
     488           56 :       set_avma(av);
     489           56 :       if (signe(x) > 0 && l == 1) return utoipos(P[1]);
     490           35 :       return gen_1;
     491              :     }
     492              :   } else {
     493         4715 :     if (gequal1(x))
     494              :     { /* n is prime, return n; multiply by x to keep the type */
     495           14 :       if (l == 1) return gc_upto(av, gmulgu(x,n));
     496            7 :       return gc_GEN(av, x); /* else 1 */
     497              :     }
     498         4701 :     if (gequalm1(x)) return gc_upto(av, gneg(x)); /* -1 */
     499              :   }
     500              :   /* Heuristic: evaluation will probably not improve things */
     501         6353 :   if (tx == t_POL || tx == t_MAT || lg(x) > n)
     502           24 :     return gc_upto(av, poleval(polcyclo(n,0), x));
     503              : 
     504         6329 :   xd = cgetg((1L<<l) + 1, t_VEC); /* the x^d, where d | n */
     505         6329 :   md = cgetg((1L<<l) + 1, t_VECSMALL); /* the mu(d), where d | n */
     506         6329 :   gel(xd, 1) = x;
     507         6329 :   md[1] = 1;
     508              :   /* Use Phi_n(x) = Prod_{d|n} (x^d-1)^mu(n/d).
     509              :    * If x has exact order D, n = Dq, then the result is 0 if q = 1. Otherwise
     510              :    * the factors with x^d-1, D|d are omitted and we multiply at the end by
     511              :    *   prod_{d | q} d^mu(q/d) = q if prime, 1 otherwise */
     512              :   /* We store the factors with mu(d)= 1 (resp.-1) in ypos (resp yneg).
     513              :    * At the end we return ypos/yneg if mu(n)=1 and yneg/ypos if mu(n)=-1 */
     514         6329 :   ypos = gsubgs(x,1);
     515         6329 :   yneg = gen_1;
     516         6329 :   vpx = (typ(x) == t_PADIC)? valp(x): 0;
     517        13999 :   for (i = 1; i <= l; i++)
     518              :   {
     519         7670 :     long ti = 1L<<(i-1), p = P[i];
     520        16779 :     for (j = 1; j <= ti; j++) {
     521         9109 :       GEN X = gel(xd,j), t;
     522         9109 :       if (vpx > 0)
     523              :       { /* ypos, X t_PADIC */
     524           98 :         ulong a = umuluu_or_0(p, valp(X)), b = precp(ypos) - 1;
     525           98 :         long e = (a && a < b) ? b - a : 0;
     526           98 :         if (precp(X) > e) X = cvtop(X, padic_p(ypos), e);
     527           98 :         if (e > 0) X = gpowgs(X, p); /* avoid valp overflow of p-adic 0*/
     528              :       }
     529              :       else
     530         9011 :         X = gpowgs(X, p);
     531         9109 :       md[ti+j] = -md[j];
     532         9109 :       gel(xd,ti+j) = X;
     533              :       /* avoid precp overflow */
     534         9109 :       t = (vpx > 0 && gequal0(X))? gen_m1: gsubgs(X,1);
     535         9109 :       if (gequal0(t))
     536              :       { /* x^d = 1; root_of_1 := the smallest index ti+j such that X == 1
     537              :         * (whose bits code d: bit i-1 is set iff P[i] | d). If no such index
     538              :         * exists, then root_of_1 remains 0. Do not multiply with X-1 if X = 1,
     539              :         * we handle these factors at the end */
     540           28 :         if (!root_of_1) root_of_1 = ti+j;
     541              :       }
     542              :       else
     543              :       {
     544         9081 :         if (md[ti+j] == 1) ypos = gmul(ypos, t);
     545         7705 :         else               yneg = gmul(yneg, t);
     546              :       }
     547              :     }
     548              :   }
     549         6329 :   ypos = odd(l)? gdiv(yneg,ypos): gdiv(ypos,yneg);
     550         6329 :   if (root_of_1)
     551              :   {
     552           21 :     GEN X = gel(xd,(1<<l)); /* = x^n = 1 */
     553           21 :     long bitmask_q = (1<<l) - root_of_1;
     554              :     /* bitmask_q encodes q = n/d: bit (i-1) is 1 iff P[i] | q */
     555              : 
     556              :     /* x is a root of unity.  If bitmask_q = 0, then x was a primitive n-th
     557              :      * root of 1 and the result is zero. Return X - 1 to preserve type. */
     558           21 :     if (!bitmask_q) return gc_upto(av, gsubgs(X, 1));
     559              :     /* x is a primitive d-th root of unity, where d|n and d<n: we
     560              :      * must multiply ypos by if(isprime(n/d), n/d, 1) */
     561            7 :     ypos = gmul(ypos, X); /* multiply by X = 1 to preserve type */
     562              :     /* If bitmask_q = 1<<(i-1) for some i <= l, then q == P[i] and we multiply
     563              :      * by P[i]; otherwise q is composite and nothing more needs to be done */
     564            7 :     if (!(bitmask_q & (bitmask_q-1))) /* detects power of 2, since bitmask!=0 */
     565              :     {
     566            7 :       i = vals(bitmask_q)+1; /* q = P[i] */
     567            7 :       ypos = gmulgu(ypos, P[i]);
     568              :     }
     569              :   }
     570         6315 :   return gc_upto(av, ypos);
     571              : }
     572              : /********************************************************************/
     573              : /**                                                                **/
     574              : /**                  HILBERT & PASCAL MATRICES                     **/
     575              : /**                                                                **/
     576              : /********************************************************************/
     577              : GEN
     578          133 : mathilbert(long n) /* Hilbert matrix of order n */
     579              : {
     580              :   long i,j;
     581              :   GEN p;
     582              : 
     583          133 :   if (n < 0) pari_err_DOMAIN("mathilbert", "dimension", "<", gen_0, stoi(n));
     584          133 :   p = cgetg(n+1,t_MAT);
     585         1120 :   for (j=1; j<=n; j++)
     586              :   {
     587          987 :     gel(p,j) = cgetg(n+1,t_COL);
     588        16583 :     for (i=1+(j==1); i<=n; i++)
     589        15596 :       gcoeff(p,i,j) = mkfrac(gen_1, utoipos(i+j-1));
     590              :   }
     591          133 :   if (n) gcoeff(p,1,1) = gen_1;
     592          133 :   return p;
     593              : }
     594              : 
     595              : /* q-Pascal triangle = (choose(i,j)_q) (ordinary binomial if q = NULL) */
     596              : GEN
     597         5061 : matqpascal(long n, GEN q)
     598              : {
     599              :   long i, j, I;
     600         5061 :   pari_sp av = avma;
     601         5061 :   GEN m, qpow = NULL; /* gcc -Wall */
     602              : 
     603         5061 :   if (n < -1)  pari_err_DOMAIN("matpascal", "n", "<", gen_m1, stoi(n));
     604         5061 :   n++; m = cgetg(n+1,t_MAT);
     605        46921 :   for (j=1; j<=n; j++) gel(m,j) = cgetg(n+1,t_COL);
     606         5061 :   if (q)
     607              :   {
     608           42 :     I = (n+1)/2;
     609           42 :     if (I > 1) { qpow = new_chunk(I+1); gel(qpow,2)=q; }
     610           84 :     for (j=3; j<=I; j++) gel(qpow,j) = gmul(q, gel(qpow,j-1));
     611              :   }
     612        46921 :   for (i=1; i<=n; i++)
     613              :   {
     614        41860 :     I = (i+1)/2; gcoeff(m,i,1)= gen_1;
     615        41860 :     if (q)
     616              :     {
     617          483 :       for (j=2; j<=I; j++)
     618          238 :         gcoeff(m,i,j) = gadd(gmul(gel(qpow,j),gcoeff(m,i-1,j)),
     619          238 :                              gcoeff(m,i-1,j-1));
     620              :     }
     621              :     else
     622              :     {
     623      1008805 :       for (j=2; j<=I; j++)
     624       967190 :         gcoeff(m,i,j) = addii(gcoeff(m,i-1,j), gcoeff(m,i-1,j-1));
     625              :     }
     626      1028664 :     for (   ; j<=i; j++) gcoeff(m,i,j) = gcoeff(m,i,i+1-j);
     627      1996092 :     for (   ; j<=n; j++) gcoeff(m,i,j) = gen_0;
     628              :   }
     629         5061 :   return gc_GEN(av, m);
     630              : }
     631              : 
     632              : GEN
     633           77 : eulerianpol(long N, long v)
     634              : {
     635           77 :   pari_sp av = avma;
     636           77 :   long n, n2, k = 0;
     637              :   GEN A;
     638           77 :   if (v < 0) v = 0;
     639           77 :   if (N < 0) pari_err_DOMAIN("eulerianpol", "index", "<", gen_0, stoi(N));
     640           70 :   if (N <= 1) return pol_1(v);
     641           42 :   if (N == 2) return deg1pol_shallow(gen_1, gen_1, v);
     642           35 :   A = cgetg(N+1, t_VEC);
     643           35 :   gel(A,1) = gen_1; gel(A,2) = gen_1; /* A_2 = x+1 */
     644          567 :   for (n = 3; n <= N; n++)
     645              :   { /* A(n,k) = (n-k)A(n-1,k-1) + (k+1)A(n-1,k) */
     646          532 :     n2 = n >> 1;
     647          532 :     if (odd(n)) gel(A,n2+1) = mului(n+1, gel(A,n2));
     648         8652 :     for (k = n2-1; k; k--)
     649         8120 :       gel(A,k+1) = addii(mului(n-k, gel(A,k)), mului(k+1, gel(A,k+1)));
     650          532 :     if (gc_needed(av,1))
     651              :     {
     652            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"eulerianpol, %ld/%ld",n,N);
     653            0 :       for (k = odd(n)? n2+1: n2; k < N; k++) gel(A,k+1) = gen_0;
     654            0 :       A = gc_GEN(av, A);
     655              :     }
     656              :   }
     657           35 :   k = N >> 1; if (odd(N)) k++;
     658          329 :   for (; k < N; k++) gel(A,k+1) = gel(A, N-k);
     659           35 :   return gc_GEN(av, RgV_to_RgX(A, v));
     660              : }
     661              : 
     662              : /******************************************************************/
     663              : /**                                                              **/
     664              : /**                       PRECISION CHANGES                      **/
     665              : /**                                                              **/
     666              : /******************************************************************/
     667              : 
     668              : GEN
     669           91 : gprec(GEN x, long d)
     670              : {
     671           91 :   pari_sp av = avma;
     672           91 :   if (d <= 0) pari_err_DOMAIN("gprec", "precision", "<=", gen_0, stoi(d));
     673           91 :   return gc_GEN(av, gprec_w(x, ndec2prec(d)));
     674              : }
     675              : 
     676              : /* not GC-safe */
     677              : GEN
     678     19822811 : gprec_w(GEN x, long pr)
     679              : {
     680     19822811 :   switch(typ(x))
     681              :   {
     682     14543079 :     case t_REAL:
     683     14543079 :       if (signe(x)) return realprec(x) != pr? rtor(x,pr): x;
     684       173777 :       return real_0_bit(minss(-prec2nbits(pr), expo(x)));
     685      3488239 :     case t_COMPLEX:
     686      3488239 :       retmkcomplex(gprec_w(gel(x,1),pr), gprec_w(gel(x,2),pr));
     687      3895125 :     case t_POL: pari_APPLY_pol_normalized(gprec_w(gel(x,i),pr));
     688        31017 :     case t_SER: pari_APPLY_ser_normalized(gprec_w(gel(x,i),pr));
     689       456645 :     case t_POLMOD: case t_RFRAC: case t_VEC: case t_COL: case t_MAT:
     690      2041103 :       pari_APPLY_same(gprec_w(gel(x,i), pr));
     691              :   }
     692       717895 :   return x;
     693              : }
     694              : /* not GC-safe */
     695              : GEN
     696      6842542 : gprec_wensure(GEN x, long pr)
     697              : {
     698      6842542 :   switch(typ(x))
     699              :   {
     700      5681413 :     case t_REAL:
     701      5681413 :       if (signe(x)) return realprec(x) < pr? rtor(x,pr): x;
     702        12858 :       return real_0_bit(minss(-prec2nbits(pr), expo(x)));
     703       453277 :     case t_COMPLEX:
     704       453277 :       retmkcomplex(gprec_wensure(gel(x,1),pr), gprec_wensure(gel(x,2),pr));
     705          854 :    case t_POL: pari_APPLY_pol_normalized(gprec_wensure(gel(x,i),pr));
     706       867482 :    case t_SER: pari_APPLY_ser_normalized(gprec_wensure(gel(x,i),pr));
     707        83529 :     case t_POLMOD: case t_RFRAC: case t_VEC: case t_COL: case t_MAT:
     708      1300863 :       pari_APPLY_same(gprec_wensure(gel(x,i), pr));
     709              :   }
     710       574539 :   return x;
     711              : }
     712              : 
     713              : /* not GC-safe; truncate mantissa to precision 'pr' but never increase it */
     714              : GEN
     715      5824448 : gprec_wtrunc(GEN x, long pr)
     716              : {
     717      5824448 :   switch(typ(x))
     718              :   {
     719      4625465 :     case t_REAL:
     720      4625465 :       return (signe(x) && realprec(x) > pr)? rtor(x,pr): x;
     721       633523 :     case t_COMPLEX:
     722       633523 :       retmkcomplex(gprec_wtrunc(gel(x,1),pr), gprec_wtrunc(gel(x,2),pr));
     723        16751 :     case t_POL: pari_APPLY_pol_normalized(gprec_wtrunc(gel(x,i),pr));
     724         8554 :     case t_SER: pari_APPLY_ser_normalized(gprec_wtrunc(gel(x,i),pr));
     725       434041 :     case t_POLMOD: case t_RFRAC: case t_VEC: case t_COL: case t_MAT:
     726      1768284 :       pari_APPLY_same(gprec_wtrunc(gel(x,i), pr));
     727              :   }
     728       127947 :   return x;
     729              : }
     730              : 
     731              : /********************************************************************/
     732              : /**                                                                **/
     733              : /**                      SERIES TRANSFORMS                         **/
     734              : /**                                                                **/
     735              : /********************************************************************/
     736              : /**                  LAPLACE TRANSFORM (OF A SERIES)               **/
     737              : /********************************************************************/
     738              : static GEN
     739           14 : serlaplace(GEN x)
     740              : {
     741           14 :   long i, l = lg(x), e = valser(x);
     742           14 :   GEN t, y = cgetg(l,t_SER);
     743           14 :   if (e < 0) pari_err_DOMAIN("laplace","valuation","<",gen_0,stoi(e));
     744           14 :   t = mpfact(e); y[1] = x[1];
     745          154 :   for (i=2; i<l; i++)
     746              :   {
     747          140 :     gel(y,i) = gmul(t, gel(x,i));
     748          140 :     e++; t = mului(e,t);
     749              :   }
     750           14 :   return y;
     751              : }
     752              : static GEN
     753           14 : pollaplace(GEN x)
     754              : {
     755           14 :   long i, e = 0, l = lg(x);
     756           14 :   GEN t = gen_1, y = cgetg(l,t_POL);
     757           14 :   y[1] = x[1];
     758           63 :   for (i=2; i<l; i++)
     759              :   {
     760           49 :     gel(y,i) = gmul(t, gel(x,i));
     761           49 :     e++; t = mului(e,t);
     762              :   }
     763           14 :   return y;
     764              : }
     765              : GEN
     766           35 : laplace(GEN x)
     767              : {
     768           35 :   pari_sp av = avma;
     769           35 :   switch(typ(x))
     770              :   {
     771           14 :     case t_POL: x = pollaplace(x); break;
     772           14 :     case t_SER: x = serlaplace(x); break;
     773            7 :     default: if (is_scalar_t(typ(x))) return gcopy(x);
     774            0 :              pari_err_TYPE("laplace",x);
     775              :   }
     776           28 :   return gc_GEN(av, x);
     777              : }
     778              : 
     779              : /********************************************************************/
     780              : /**              CONVOLUTION PRODUCT (OF TWO SERIES)               **/
     781              : /********************************************************************/
     782              : GEN
     783           14 : convol(GEN x, GEN y)
     784              : {
     785           14 :   long j, lx, ly, ex, ey, vx = varn(x);
     786              :   GEN z;
     787              : 
     788           14 :   if (typ(x) != t_SER) pari_err_TYPE("convol",x);
     789           14 :   if (typ(y) != t_SER) pari_err_TYPE("convol",y);
     790           14 :   if (varn(y) != vx) pari_err_VAR("convol", x,y);
     791           14 :   ex = valser(x);
     792           14 :   ey = valser(y);
     793           14 :   if (ser_isexactzero(x))
     794              :   {
     795            7 :     z = scalarser(gadd(Rg_get_0(x), Rg_get_0(y)), varn(x), 1);
     796            7 :     setvalser(z, maxss(ex,ey)); return z;
     797              :   }
     798            7 :   lx = lg(x) + ex; x -= ex;
     799            7 :   ly = lg(y) + ey; y -= ey;
     800              :   /* inputs shifted: x[i] and y[i] now correspond to monomials of same degree */
     801            7 :   if (ly < lx) lx = ly; /* min length */
     802            7 :   if (ex < ey) ex = ey; /* max valuation */
     803            7 :   if (lx - ex < 3) return zeroser(vx, lx-2);
     804              : 
     805            7 :   z = cgetg(lx - ex, t_SER);
     806            7 :   z[1] = evalvalser(ex) | evalvarn(vx);
     807          119 :   for (j = ex+2; j<lx; j++) gel(z,j-ex) = gmul(gel(x,j),gel(y,j));
     808            7 :   return normalizeser(z);
     809              : }
     810              : 
     811              : /***********************************************************************/
     812              : /*               OPERATIONS ON DIRICHLET SERIES: *, /                  */
     813              : /* (+, -, scalar multiplication are done on the corresponding vectors) */
     814              : /***********************************************************************/
     815              : static long
     816       869526 : dirval(GEN x)
     817              : {
     818       869526 :   long i = 1, lx = lg(x);
     819       869547 :   while (i < lx && gequal0(gel(x,i))) i++;
     820       869526 :   return i;
     821              : }
     822              : 
     823              : GEN
     824          441 : dirmul(GEN x, GEN y)
     825              : {
     826          441 :   pari_sp av = avma, av2;
     827              :   long nx, ny, nz, dx, dy, i, j, k;
     828              :   GEN z;
     829              : 
     830          441 :   if (typ(x)!=t_VEC) pari_err_TYPE("dirmul",x);
     831          441 :   if (typ(y)!=t_VEC) pari_err_TYPE("dirmul",y);
     832          441 :   dx = dirval(x); nx = lg(x)-1;
     833          441 :   dy = dirval(y); ny = lg(y)-1;
     834          441 :   if (ny-dy < nx-dx) { swap(x,y); lswap(nx,ny); lswap(dx,dy); }
     835          441 :   nz = minss(nx*dy,ny*dx);
     836          441 :   y = RgV_kill0(y);
     837          441 :   av2 = avma;
     838          441 :   z = zerovec(nz);
     839        40740 :   for (j=dx; j<=nx; j++)
     840              :   {
     841        40299 :     GEN c = gel(x,j);
     842        40299 :     if (gequal0(c)) continue;
     843        18571 :     if (gequal1(c))
     844              :     {
     845       100408 :       for (k=dy,i=j*dy; i<=nz; i+=j,k++)
     846        93219 :         if (gel(y,k)) gel(z,i) = gadd(gel(z,i),gel(y,k));
     847              :     }
     848        11382 :     else if (gequalm1(c))
     849              :     {
     850         5649 :       for (k=dy,i=j*dy; i<=nz; i+=j,k++)
     851         4298 :         if (gel(y,k)) gel(z,i) = gsub(gel(z,i),gel(y,k));
     852              :     }
     853              :     else
     854              :     {
     855        46508 :       for (k=dy,i=j*dy; i<=nz; i+=j,k++)
     856        36477 :         if (gel(y,k)) gel(z,i) = gadd(gel(z,i),gmul(c,gel(y,k)));
     857              :     }
     858        18571 :     if (gc_needed(av2,3))
     859              :     {
     860            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"dirmul, %ld/%ld",j,nx);
     861            0 :       z = gc_GEN(av2,z);
     862              :     }
     863              :   }
     864          441 :   return gc_GEN(av,z);
     865              : }
     866              : 
     867              : GEN
     868       434322 : dirdiv(GEN x, GEN y)
     869              : {
     870       434322 :   pari_sp av = avma, av2;
     871              :   long nx,ny,nz, dx,dy, i,j,k;
     872              :   GEN p1;
     873              : 
     874       434322 :   if (typ(x)!=t_VEC) pari_err_TYPE("dirdiv",x);
     875       434322 :   if (typ(y)!=t_VEC) pari_err_TYPE("dirdiv",y);
     876       434322 :   dx = dirval(x); nx = lg(x)-1;
     877       434322 :   dy = dirval(y); ny = lg(y)-1;
     878       434322 :   if (dy != 1 || !ny) pari_err_INV("dirdiv",y);
     879       434322 :   nz = minss(nx,ny*dx);
     880       434322 :   p1 = gel(y,1);
     881       434322 :   if (gequal1(p1)) p1 = NULL; else y = gdiv(y,p1);
     882       434322 :   y = RgV_kill0(y);
     883       434322 :   av2 = avma;
     884       434322 :   x = p1 ? gdiv(x,p1): leafcopy(x);
     885       434329 :   for (j=1; j<dx; j++) gel(x,j) = gen_0;
     886       434322 :   setlg(x,nz+1);
     887    109807992 :   for (j=dx; j<=nz; j++)
     888              :   {
     889    109373670 :     GEN c = gel(x,j);
     890    109373670 :     if (gequal0(c)) continue;
     891     75821501 :     if (gequal1(c))
     892              :     {
     893    133758387 :       for (i=j+j,k=2; i<=nz; i+=j,k++)
     894    131988864 :         if (gel(y,k)) gel(x,i) = gsub(gel(x,i),gel(y,k));
     895              :     }
     896     74051978 :     else if (gequalm1(c))
     897              :     {
     898     28856261 :       for (i=j+j,k=2; i<=nz; i+=j,k++)
     899     27302821 :         if (gel(y,k)) gel(x,i) = gadd(gel(x,i),gel(y,k));
     900              :     }
     901              :     else
     902              :     {
     903    331182936 :       for (i=j+j,k=2; i<=nz; i+=j,k++)
     904    258684398 :         if (gel(y,k)) gel(x,i) = gsub(gel(x,i),gmul(c,gel(y,k)));
     905              :     }
     906     75821501 :     if (gc_needed(av2,3))
     907              :     {
     908            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"dirdiv, %ld/%ld",j,nz);
     909            0 :       x = gc_GEN(av2,x);
     910              :     }
     911              :   }
     912       434322 :   return gc_GEN(av,x);
     913              : }
     914              : 
     915              : /*******************************************************************/
     916              : /**                                                               **/
     917              : /**                       COMBINATORICS                           **/
     918              : /**                                                               **/
     919              : /*******************************************************************/
     920              : /**                      BINOMIAL COEFFICIENTS                    **/
     921              : /*******************************************************************/
     922              : /* Lucas's formula for v_p(\binom{n}{k}), used in the tough case p <= sqrt(n) */
     923              : static long
     924         3206 : binomial_lval(ulong n, ulong k, ulong p)
     925              : {
     926         3206 :   ulong r = 0, e = 0;
     927              :   do
     928              :   {
     929        10290 :     ulong a = n % p, b = k % p + r;
     930        10290 :     n /= p; k /= p;
     931        10290 :     if (a < b) { e++; r = 1; } else r = 0;
     932        10290 :   } while (n);
     933         3206 :   return e;
     934              : }
     935              : GEN
     936        63139 : binomialuu(ulong n, ulong k)
     937              : {
     938        63139 :   pari_sp av = avma;
     939              :   ulong p, nk, sn;
     940              :   long c, l;
     941              :   forprime_t T;
     942              :   GEN v, z;
     943        63139 :   if (k > n) return gen_0;
     944        63132 :   nk = n-k; if (k > nk) lswap(nk, k);
     945        63132 :   if (!k) return gen_1;
     946        61508 :   if (k == 1) return utoipos(n);
     947        57357 :   if (k == 2) return muluu(odd(n)? n: n-1, n>>1);
     948        43049 :   if (k < 1000 || ((double)k/ n) * log((double)n) < 0.5)
     949              :   { /* k "small" */
     950        43035 :     z = diviiexact(mulu_interval(n-k+1, n), mulu_interval(2UL, k));
     951        43035 :     return gc_INT(av, z);
     952              :   }
     953           14 :   sn = usqrt(n);
     954              :   /* use Lucas's formula, k <= n/2 */
     955           14 :   l = minuu(1UL << 20, n); v = cgetg(l+1, t_VECSMALL); c = 1;
     956           14 :   u_forprime_init(&T, nk+1, n);
     957      1553958 :   while ((p = u_forprime_next(&T))) /* all primes n-k < p <= n occur, v_p = 1 */
     958              :   {
     959      1553944 :     if (c == l) { ulong L = l << 1; v = vecsmall_lengthen(v, L); l = L; }
     960      1553944 :     v[c++] = p;
     961              :   }
     962           14 :   u_forprime_init(&T, sn+1, n >> 1);
     963      2437785 :   while ((p = u_forprime_next(&T))) /* p^2 > n, v_p <= 1 */
     964      2437771 :     if (n % p < k % p)
     965              :     {
     966      1428679 :       if (c == l) { ulong L = l << 1; v = vecsmall_lengthen(v, L); l = L; }
     967      1428679 :       v[c++] = p;
     968              :     }
     969           14 :   setlg(v, c); z = zv_prod_Z(v);
     970           14 :   u_forprime_init(&T, 3, sn);
     971           14 :   l = minuu(1UL << 20, sn); v = cgetg(l + 1, t_VEC); c = 1;
     972         3220 :   while ((p = u_forprime_next(&T))) /* p <= sqrt(n) */
     973              :   {
     974         3206 :     ulong e = binomial_lval(n, k, p);
     975         3206 :     if (e)
     976              :     {
     977         2541 :       if (c == l) { ulong L = l << 1; v = vec_lengthen(v, L); l = L; }
     978         2541 :       gel(v, c++) = powuu(p, e);
     979              :     }
     980              :   }
     981           14 :   setlg(v, c); z = mulii(z, ZV_prod(v));
     982              :   { /* p = 2 */
     983           14 :     ulong e = hammingu(k);
     984           14 :     e += (k == nk)? e: hammingu(nk);
     985           14 :     e -= hammingu(n); if (e) z = shifti(z, e);
     986              :   }
     987           14 :   return gc_INT(av, z);
     988              : }
     989              : 
     990              : GEN
     991        74592 : binomial(GEN n, long k)
     992              : {
     993        74592 :   long i, prec, tn = typ(n);
     994              :   pari_sp av;
     995              :   GEN y;
     996              : 
     997        74592 :   av = avma;
     998        74592 :   if (tn == t_INT)
     999              :   {
    1000              :     long sn;
    1001              :     GEN z;
    1002        74417 :     if (k == 0) return gen_1;
    1003        50344 :     sn = signe(n);
    1004        50344 :     if (sn == 0) return gen_0; /* k != 0 */
    1005        50344 :     if (sn > 0)
    1006              :     { /* n > 0 */
    1007        49889 :       if (k < 0) return gen_0;
    1008        49889 :       if (k == 1) return icopy(n);
    1009        31101 :       z = subiu(n, k);
    1010        31101 :       if (cmpiu(z, k) < 0)
    1011              :       {
    1012         1386 :         switch(signe(z))
    1013              :         {
    1014            7 :           case -1: return gc_const(av, gen_0);
    1015           63 :           case 0: return gc_const(av, gen_1);
    1016              :         }
    1017         1316 :         k = z[2];
    1018         1316 :         if (k == 1) { set_avma(av); return icopy(n); }
    1019              :       }
    1020        30555 :       set_avma(av);
    1021        30555 :       if (lgefint(n) == 3) return binomialuu(n[2],(ulong)k);
    1022              :     }
    1023              :     else
    1024              :     { /* n < 0, k != 0; use Kronenburg's definition */
    1025          455 :       if (k > 0)
    1026          434 :         z = binomial(subsi(k - 1, n), k);
    1027              :       else
    1028              :       {
    1029           21 :         z = subis(n, k); if (signe(z) < 0) return gen_0;
    1030           14 :         n = stoi(-k-1); k = itos(z);
    1031           14 :         z = binomial(n, k);
    1032              :       }
    1033          448 :       if (odd(k)) togglesign_safe(&z);
    1034          448 :       return gc_INT(av, z);
    1035              :     }
    1036              :     /* n >= 0 and huge, k != 0 */
    1037            8 :     if (k < 0) return gen_0;
    1038            8 :     if (k == 1) return icopy(n);
    1039              :     /* k > 1 */
    1040            8 :     y = cgetg(k+1,t_VEC); gel(y,1) = n;
    1041           18 :     for (i = 2; i <= k; i++) gel(y,i) = subiu(n,i-1);
    1042            8 :     y = diviiexact(ZV_prod(y), mpfact(k));
    1043            8 :     return gc_INT(av, y);
    1044              :   }
    1045          175 :   if (is_noncalc_t(tn)) pari_err_TYPE("binomial",n);
    1046          175 :   if (k <= 1)
    1047              :   {
    1048           14 :     if (k < 0) return Rg_get_0(n);
    1049            7 :     if (k == 0) return Rg_get_1(n);
    1050            0 :     return gcopy(n);
    1051              :   }
    1052          161 :   prec = precision(n);
    1053          161 :   if (prec && k > 200 + 0.8*prec2nbits(prec)) {
    1054            7 :     GEN A = mpfactr(k, prec), B = ggamma(gsubgs(n,k-1), prec);
    1055            7 :     return gc_upto(av, gdiv(ggamma(gaddgs(n,1), prec), gmul(A,B)));
    1056              :   }
    1057              : 
    1058          154 :   y = cgetg(k+1,t_VEC);
    1059        12236 :   for (i=1; i<=k; i++) gel(y,i) = gsubgs(n,i-1);
    1060          154 :   return gc_upto(av, gdiv(RgV_prod(y), mpfact(k)));
    1061              : }
    1062              : 
    1063              : GEN
    1064         1855 : binomial0(GEN x, GEN k)
    1065              : {
    1066         1855 :   if (!k)
    1067              :   {
    1068           21 :     if (typ(x) != t_INT || signe(x) < 0) pari_err_TYPE("binomial", x);
    1069            7 :     return vecbinomial(itos(x));
    1070              :   }
    1071         1834 :   if (typ(k) != t_INT) pari_err_TYPE("binomial", k);
    1072         1827 :   return binomial(x, itos(k));
    1073              : }
    1074              : 
    1075              : /* Assume n >= 0, return bin, bin[k+1] = binomial(n, k) */
    1076              : GEN
    1077      7190614 : vecbinomial(long n)
    1078              : {
    1079              :   long d, k;
    1080              :   GEN C;
    1081      7190614 :   if (!n) return mkvec(gen_1);
    1082      7190243 :   C = cgetg(n+2, t_VEC) + 1; /* C[k] = binomial(n, k) */
    1083      7190243 :   gel(C,0) = gen_1;
    1084      7190243 :   gel(C,1) = utoipos(n); d = (n + 1) >> 1;
    1085     21762119 :   for (k=2; k <= d; k++)
    1086              :   {
    1087     14571876 :     pari_sp av = avma;
    1088     14571876 :     gel(C,k) = gc_INT(av, diviuexact(mului(n-k+1, gel(C,k-1)), k));
    1089              :   }
    1090     21840423 :   for (   ; k <= n; k++) gel(C,k) = gel(C,n-k);
    1091      7190243 :   return C - 1;
    1092              : }
    1093              : 
    1094              : /********************************************************************/
    1095              : /**                  STIRLING NUMBERS                              **/
    1096              : /********************************************************************/
    1097              : /* Stirling number of the 2nd kind. The number of ways of partitioning
    1098              :    a set of n elements into m nonempty subsets. */
    1099              : GEN
    1100         1694 : stirling2(ulong n, ulong m)
    1101              : {
    1102         1694 :   pari_sp av = avma;
    1103              :   GEN s, bmk;
    1104              :   ulong k;
    1105         1694 :   if (n==0) return (m == 0)? gen_1: gen_0;
    1106         1694 :   if (m > n || m == 0) return gen_0;
    1107         1694 :   if (m==n) return gen_1;
    1108              :   /* k = 0 */
    1109         1694 :   bmk = gen_1; s  = powuu(m, n);
    1110        20314 :   for (k = 1; k <= ((m-1)>>1); ++k)
    1111              :   { /* bmk = binomial(m, k) */
    1112              :     GEN c, kn, mkn;
    1113        18620 :     bmk = diviuexact(mului(m-k+1, bmk), k);
    1114        18620 :     kn  = powuu(k, n); mkn = powuu(m-k, n);
    1115        18620 :     c = odd(m)? subii(mkn,kn): addii(mkn,kn);
    1116        18620 :     c = mulii(bmk, c);
    1117        18620 :     s = odd(k)? subii(s, c): addii(s, c);
    1118        18620 :     if (gc_needed(av,2))
    1119              :     {
    1120            0 :       if(DEBUGMEM>1) pari_warn(warnmem,"stirling2");
    1121            0 :       (void)gc_all(av, 2, &s, &bmk);
    1122              :     }
    1123              :   }
    1124              :   /* k = m/2 */
    1125         1694 :   if (!odd(m))
    1126              :   {
    1127              :     GEN c;
    1128          805 :     bmk = diviuexact(mului(k+1, bmk), k);
    1129          805 :     c = mulii(bmk, powuu(k,n));
    1130          805 :     s = odd(k)? subii(s, c): addii(s, c);
    1131              :   }
    1132         1694 :   return gc_INT(av, diviiexact(s, mpfact(m)));
    1133              : }
    1134              : 
    1135              : /* Stirling number of the first kind. Up to the sign, the number of
    1136              :    permutations of n symbols which have exactly m cycles. */
    1137              : GEN
    1138          154 : stirling1(ulong n, ulong m)
    1139              : {
    1140          154 :   pari_sp ltop=avma;
    1141              :   ulong k;
    1142              :   GEN s, t;
    1143          154 :   if (n < m) return gen_0;
    1144          154 :   else if (n==m) return gen_1;
    1145              :   /* t = binomial(n-1+k, m-1) * binomial(2n-m, n-m-k) */
    1146              :   /* k = n-m > 0 */
    1147          154 :   t = binomialuu(2*n-m-1, m-1);
    1148          154 :   s = mulii(t, stirling2(2*(n-m), n-m));
    1149          154 :   if (odd(n-m)) togglesign(s);
    1150         1547 :   for (k = n-m-1; k > 0; --k)
    1151              :   {
    1152              :     GEN c;
    1153         1393 :     t = diviuuexact(muluui(n-m+k+1, n+k+1, t), n+k, n-m-k);
    1154         1393 :     c = mulii(t, stirling2(n-m+k, k));
    1155         1393 :     s = odd(k)? subii(s, c): addii(s, c);
    1156         1393 :     if ((k & 0x1f) == 0) {
    1157           21 :       t = gc_INT(ltop, t);
    1158           21 :       s = gc_INT(avma, s);
    1159              :     }
    1160              :   }
    1161          154 :   return gc_INT(ltop, s);
    1162              : }
    1163              : 
    1164              : GEN
    1165          301 : stirling(long n, long m, long flag)
    1166              : {
    1167          301 :   if (n < 0) pari_err_DOMAIN("stirling", "n", "<", gen_0, stoi(n));
    1168          301 :   if (m < 0) pari_err_DOMAIN("stirling", "m", "<", gen_0, stoi(m));
    1169          301 :   switch (flag)
    1170              :   {
    1171          154 :     case 1: return stirling1((ulong)n,(ulong)m);
    1172          147 :     case 2: return stirling2((ulong)n,(ulong)m);
    1173            0 :     default: pari_err_FLAG("stirling");
    1174              :   }
    1175              :   return NULL; /*LCOV_EXCL_LINE*/
    1176              : }
    1177              : 
    1178              : /*******************************************************************/
    1179              : /**                                                               **/
    1180              : /**                     RECIPROCAL POLYNOMIAL                     **/
    1181              : /**                                                               **/
    1182              : /*******************************************************************/
    1183              : /* return coefficients s.t x = x_0 X^n + ... + x_n */
    1184              : GEN
    1185          161 : polrecip(GEN x)
    1186              : {
    1187          161 :   long tx = typ(x);
    1188          161 :   if (is_scalar_t(tx)) return gcopy(x);
    1189          154 :   if (tx != t_POL) pari_err_TYPE("polrecip",x);
    1190          154 :   return RgX_recip(x);
    1191              : }
    1192              : 
    1193              : /********************************************************************/
    1194              : /**                                                                **/
    1195              : /**                  POLYNOMIAL INTERPOLATION                      **/
    1196              : /**                                                                **/
    1197              : /********************************************************************/
    1198              : /* given complex roots L[i], i <= n of some monic T in C[X], return
    1199              :  * the T'(L[i]), computed stably via products of differences */
    1200              : GEN
    1201        85730 : vandermondeinverseinit(GEN L)
    1202              : {
    1203        85730 :   long i, j, l = lg(L);
    1204        85730 :   GEN V = cgetg(l, t_VEC);
    1205       479232 :   for (i = 1; i < l; i++)
    1206              :   {
    1207       393502 :     pari_sp av = avma;
    1208       393502 :     GEN W = cgetg(l-1,t_VEC);
    1209       393502 :     long k = 1;
    1210      4310118 :     for (j = 1; j < l; j++)
    1211      3916616 :       if (i != j) gel(W, k++) = gsub(gel(L,i), gel(L,j));
    1212       393502 :     gel(V,i) = gc_upto(av, RgV_prod(W));
    1213              :   }
    1214        85730 :   return V;
    1215              : }
    1216              : 
    1217              : /* Compute the inverse of the van der Monde matrix of T multiplied by den */
    1218              : GEN
    1219        54839 : vandermondeinverse(GEN L, GEN T, GEN den, GEN V)
    1220              : {
    1221        54839 :   pari_sp av = avma;
    1222        54839 :   long i, n = lg(L)-1;
    1223        54839 :   GEN M = cgetg(n+1, t_MAT);
    1224              : 
    1225        54839 :   if (!V) V = vandermondeinverseinit(L);
    1226        54839 :   if (den && equali1(den)) den = NULL;
    1227       298275 :   for (i = 1; i <= n; i++)
    1228              :   {
    1229       486872 :     GEN d = gel(V,i), P = RgX_Rg_mul(RgX_div_by_X_x(T, gel(L,i), NULL),
    1230       243436 :                                      den? gdiv(den,d): ginv(d));
    1231       243436 :     gel(M,i) = RgX_to_RgC(P, n);
    1232              :   }
    1233        54839 :   return gc_GEN(av, M);
    1234              : }
    1235              : 
    1236              : static GEN
    1237          224 : RgV_polint_fast(GEN X, GEN Y, long v)
    1238              : {
    1239              :   GEN p, pol;
    1240              :   long t, pa;
    1241          224 :   if (X) t = RgV_type2(X,Y, &p, &pol, &pa);
    1242           21 :   else   t = Rg_type(Y, &p, &pol, &pa);
    1243          224 :   if (t != t_INTMOD) return NULL;
    1244            7 :   Y = RgC_to_FpC(Y, p);
    1245            7 :   X = X? RgC_to_FpC(X, p): identity_ZV(lg(Y)-1);
    1246            7 :   return FpX_to_mod(FpV_polint(X, Y, p, v), p);
    1247              : }
    1248              : /* allow X = NULL for [1,...,n] */
    1249              : GEN
    1250          224 : RgV_polint(GEN X, GEN Y, long v)
    1251              : {
    1252          224 :   pari_sp av0 = avma, av;
    1253          224 :   GEN Q, L, P = NULL;
    1254          224 :   long i, l = lg(Y);
    1255          224 :   if ((Q = RgV_polint_fast(X,Y,v))) return Q;
    1256          217 :   if (!X) X = identity_ZV(l-1);
    1257          217 :   L = vandermondeinverseinit(X);
    1258          217 :   Q = roots_to_pol(X, v); av = avma;
    1259          553 :   for (i=1; i<l; i++)
    1260              :   {
    1261              :     GEN T, dP;
    1262          336 :     if (gequal0(gel(Y,i))) continue;
    1263          238 :     T = RgX_div_by_X_x(Q, gel(X,i), NULL);
    1264          238 :     dP = RgX_Rg_mul(T, gdiv(gel(Y,i), gel(L,i)));
    1265          238 :     P = P? RgX_add(P, dP): dP;
    1266          238 :     if (gc_needed(av,2))
    1267              :     {
    1268            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"RgV_polint i = %ld/%ld", i, l-1);
    1269            0 :       P = gc_upto(av, P);
    1270              :     }
    1271              :   }
    1272          217 :   if (!P) { set_avma(av); return zeropol(v); }
    1273          147 :   return gc_upto(av0, P);
    1274              : }
    1275              : static int
    1276        17357 : inC(GEN x)
    1277              : {
    1278        17357 :   switch(typ(x)) {
    1279         1365 :     case t_INT: case t_REAL: case t_FRAC: case t_COMPLEX: case t_QUAD: return 1;
    1280        15992 :     default: return 0;
    1281              :   }
    1282              : }
    1283              : static long
    1284        16188 : check_dy(GEN X, GEN x, long n)
    1285              : {
    1286        16188 :   GEN D = NULL;
    1287        16188 :   long i, ns = 0;
    1288        16188 :   if (!inC(x)) return -1;
    1289         1176 :   for (i = 0; i < n; i++)
    1290              :   {
    1291          966 :     GEN t = gsub(x, gel(X,i));
    1292          966 :     if (!inC(t)) return -1;
    1293          952 :     t = gabs(t, DEFAULTPREC);
    1294          952 :     if (!D || gcmp(t,D) < 0) { ns = i; D = t; }
    1295              :   }
    1296              :   /* X[ns] is closest to x */
    1297          210 :   return ns;
    1298              : }
    1299              : /* X,Y are "spec" GEN vectors with n > 0 components ( at X[0], ... X[n-1] ) */
    1300              : GEN
    1301        16223 : polintspec(GEN X, GEN Y, GEN x, long n, long *pe)
    1302              : {
    1303              :   long i, m, ns;
    1304        16223 :   pari_sp av = avma, av2;
    1305        16223 :   GEN y, c, d, dy = NULL; /* gcc -Wall */
    1306              : 
    1307        16223 :   if (pe) *pe = -HIGHEXPOBIT;
    1308        16223 :   if (n == 1) return gmul(gel(Y,0), Rg_get_1(x));
    1309        16188 :   if (!X) X = identity_ZV(n) + 1;
    1310        16188 :   av2 = avma;
    1311        16188 :   ns = check_dy(X, x, n); if (ns < 0) { pe = NULL; ns = 0; }
    1312        16188 :   c = cgetg(n+1, t_VEC);
    1313        81031 :   d = cgetg(n+1, t_VEC); for (i=0; i<n; i++) gel(c,i+1) = gel(d,i+1) = gel(Y,i);
    1314        16188 :   y = gel(d,ns+1);
    1315              :   /* divided differences */
    1316        64836 :   for (m = 1; m < n; m++)
    1317              :   {
    1318       146238 :     for (i = 0; i < n-m; i++)
    1319              :     {
    1320        97590 :       GEN ho = gsub(gel(X,i),x), hp = gsub(gel(X,i+m),x), den = gsub(ho,hp);
    1321        97590 :       if (gequal0(den))
    1322              :       {
    1323            7 :         char *x1 = stack_sprintf("X[%ld]", i+1);
    1324            7 :         char *x2 = stack_sprintf("X[%ld]", i+m+1);
    1325            7 :         pari_err_DOMAIN("polinterpolate",x1,"=",strtoGENstr(x2), X);
    1326              :       }
    1327        97583 :       den = gdiv(gsub(gel(c,i+2),gel(d,i+1)), den);
    1328        97583 :       gel(c,i+1) = gmul(ho,den);
    1329        97583 :       gel(d,i+1) = gmul(hp,den);
    1330              :     }
    1331        48648 :     dy = (2*ns < n-m)? gel(c,ns+1): gel(d,ns--);
    1332        48648 :     y = gadd(y,dy);
    1333        48648 :     if (gc_needed(av2,2))
    1334              :     {
    1335            0 :       if (DEBUGMEM>1) pari_warn(warnmem,"polint, %ld/%ld",m,n-1);
    1336            0 :       (void)gc_all(av2, 4, &y, &c, &d, &dy);
    1337              :     }
    1338              :   }
    1339        16181 :   if (pe && inC(dy)) *pe = gexpo(dy);
    1340        16181 :   return gc_upto(av, y);
    1341              : }
    1342              : 
    1343              : GEN
    1344          329 : polint_i(GEN X, GEN Y, GEN t, long *pe)
    1345              : {
    1346          329 :   long lx = lg(X), vt;
    1347              : 
    1348          329 :   if (! is_vec_t(typ(X))) pari_err_TYPE("polinterpolate",X);
    1349          329 :   if (Y)
    1350              :   {
    1351          301 :     if (! is_vec_t(typ(Y))) pari_err_TYPE("polinterpolate",Y);
    1352          301 :     if (lx != lg(Y)) pari_err_DIM("polinterpolate");
    1353              :   }
    1354              :   else
    1355              :   {
    1356           28 :     Y = X;
    1357           28 :     X = NULL;
    1358              :   }
    1359          329 :   if (pe) *pe = -HIGHEXPOBIT;
    1360          329 :   vt = t? gvar(t): 0;
    1361          329 :   if (vt != NO_VARIABLE)
    1362              :   { /* formal interpolation */
    1363              :     pari_sp av;
    1364          224 :     long v0, vY = gvar(Y);
    1365              :     GEN P;
    1366          224 :     if (X) vY = varnmax(vY, gvar(X));
    1367              :     /* shortcut */
    1368          224 :     if (varncmp(vY, vt) > 0 && (!t || gequalX(t))) return RgV_polint(X, Y, vt);
    1369           84 :     av = avma;
    1370              :     /* first interpolate in high priority variable, then substitute t */
    1371           84 :     v0 = fetch_var_higher();
    1372           84 :     P = RgV_polint(X, Y, v0);
    1373           84 :     P = gsubst(P, v0, t? t: pol_x(0));
    1374           84 :     (void)delete_var();
    1375           84 :     return gc_upto(av, P);
    1376              :   }
    1377              :   /* numerical interpolation */
    1378          105 :   if (lx == 1) return Rg_get_0(t);
    1379           91 :   return polintspec(X? X+1: NULL,Y+1,t,lx-1, pe);
    1380              : }
    1381              : GEN
    1382          329 : polint(GEN X, GEN Y, GEN t, GEN *pe)
    1383              : {
    1384              :   long e;
    1385          329 :   GEN p = polint_i(X, Y, t, &e);
    1386          322 :   if (pe) *pe = stoi(e);
    1387          322 :   return p;
    1388              : }
    1389              : 
    1390              : /********************************************************************/
    1391              : /**                                                                **/
    1392              : /**                       MODREVERSE                               **/
    1393              : /**                                                                **/
    1394              : /********************************************************************/
    1395              : static void
    1396            7 : err_reverse(GEN x, GEN T)
    1397              : {
    1398            7 :   pari_err_DOMAIN("modreverse","deg(minpoly(z))", "<", stoi(degpol(T)),
    1399              :                   mkpolmod(x,T));
    1400            0 : }
    1401              : 
    1402              : /* return y such that Mod(y, charpoly(Mod(a,T)) = Mod(a,T) */
    1403              : GEN
    1404          189 : RgXQ_reverse(GEN a, GEN T)
    1405              : {
    1406          189 :   pari_sp av = avma;
    1407          189 :   long n = degpol(T);
    1408              :   GEN y;
    1409              : 
    1410          189 :   if (n <= 1) {
    1411            7 :     if (n <= 0) return gcopy(a);
    1412            7 :     return gc_upto(av, gneg(gdiv(gel(T,2), gel(T,3))));
    1413              :   }
    1414          182 :   if (typ(a) != t_POL || !signe(a)) err_reverse(a,T);
    1415          182 :   y = RgXV_to_RgM(RgXQ_powers(a,n-1,T), n);
    1416          182 :   y = RgM_solve(y, col_ei(n, 2));
    1417          182 :   if (!y) err_reverse(a,T);
    1418          175 :   return gc_GEN(av, RgV_to_RgX(y, varn(T)));
    1419              : }
    1420              : GEN
    1421         6111 : QXQ_reverse(GEN a, GEN T)
    1422              : {
    1423         6111 :   pari_sp av = avma;
    1424         6111 :   long n = degpol(T);
    1425              :   GEN y;
    1426              : 
    1427         6111 :   if (n <= 1) {
    1428           14 :     if (n <= 0) return gcopy(a);
    1429           14 :     return gc_upto(av, gneg(gdiv(gel(T,2), gel(T,3))));
    1430              :   }
    1431         6097 :   if (typ(a) != t_POL || !signe(a)) err_reverse(a,T);
    1432         6097 :   if (gequalX(a)) return gcopy(a);
    1433         5950 :   y = RgXV_to_RgM(QXQ_powers(a,n-1,T), n);
    1434         5950 :   y = QM_gauss(y, col_ei(n, 2));
    1435         5950 :   if (!y) err_reverse(a,T);
    1436         5950 :   return gc_GEN(av, RgV_to_RgX(y, varn(T)));
    1437              : }
    1438              : 
    1439              : GEN
    1440           28 : modreverse(GEN x)
    1441              : {
    1442              :   long v, n;
    1443              :   GEN T, a;
    1444              : 
    1445           28 :   if (typ(x)!=t_POLMOD) pari_err_TYPE("modreverse",x);
    1446           28 :   T = gel(x,1); n = degpol(T); if (n <= 0) return gcopy(x);
    1447           21 :   a = gel(x,2);
    1448           21 :   v = varn(T);
    1449           21 :   retmkpolmod(RgXQ_reverse(a, T),
    1450              :               (n==1)? gsub(pol_x(v), a): RgXQ_charpoly(a, T, v));
    1451              : }
    1452              : 
    1453              : /********************************************************************/
    1454              : /**                                                                **/
    1455              : /**                          MERGESORT                             **/
    1456              : /**                                                                **/
    1457              : /********************************************************************/
    1458              : static int
    1459           77 : cmp_small(GEN x, GEN y) {
    1460           77 :   long a = (long)x, b = (long)y;
    1461           77 :   return a>b? 1: (a<b? -1: 0);
    1462              : }
    1463              : 
    1464              : static int
    1465       295183 : veccmp(void *data, GEN x, GEN y)
    1466              : {
    1467       295183 :   GEN k = (GEN)data;
    1468       295183 :   long i, s, tx = typ(x), ty = typ(y), lk = lg(k), lx = minss(lg(x), lg(y));
    1469              : 
    1470       295183 :   if (tx == t_VECSMALL)
    1471              :   {
    1472          168 :     if (ty != t_VECSMALL) pari_err_TYPE("lexicographic vecsort",x);
    1473          182 :     for (i = 1; i < lk; i++)
    1474              :     {
    1475          168 :       long c = k[i];
    1476          168 :       if (c >= lx)
    1477            0 :         pari_err_TYPE("lexicographic vecsort, index too large", stoi(c));
    1478          168 :       s = cmpss(x[c], y[c]);
    1479          168 :       if (s) return s;
    1480              :     }
    1481           14 :     return 0;
    1482              :   }
    1483       295015 :   if (ty == t_VECSMALL) pari_err_TYPE("lexicographic vecsort",x);
    1484       295015 :   if (!is_vec_t(tx)) pari_err_TYPE("lexicographic vecsort",x);
    1485       295015 :   if (!is_vec_t(ty)) pari_err_TYPE("lexicographic vecsort",y);
    1486       306684 :   for (i = 1; i < lk; i++)
    1487              :   {
    1488       295043 :     long c = k[i];
    1489       295043 :     if (c >= lx)
    1490           14 :       pari_err_TYPE("lexicographic vecsort, index too large", stoi(c));
    1491       295029 :     s = lexcmp(gel(x,c), gel(y,c));
    1492       295029 :     if (s) return s;
    1493              :   }
    1494        11641 :   return 0;
    1495              : }
    1496              : 
    1497              : /* return permutation sorting v[1..n], removing duplicates. Assume n > 0 */
    1498              : static GEN
    1499      2292965 : gen_sortspec_uniq(GEN v, long n, void *E, int (*cmp)(void*,GEN,GEN))
    1500              : {
    1501              :   pari_sp av;
    1502              :   long NX, nx, ny, m, ix, iy, i;
    1503              :   GEN x, y, w, W;
    1504              :   int s;
    1505      2292965 :   switch(n)
    1506              :   {
    1507        99728 :     case 1: return mkvecsmall(1);
    1508       968355 :     case 2:
    1509       968355 :       s = cmp(E,gel(v,1),gel(v,2));
    1510       968355 :       if      (s < 0) return mkvecsmall2(1,2);
    1511       334967 :       else if (s > 0) return mkvecsmall2(2,1);
    1512        37422 :       return mkvecsmall(1);
    1513       287730 :     case 3:
    1514       287730 :       s = cmp(E,gel(v,1),gel(v,2));
    1515       287730 :       if (s < 0) {
    1516       183097 :         s = cmp(E,gel(v,2),gel(v,3));
    1517       183097 :         if (s < 0) return mkvecsmall3(1,2,3);
    1518        67830 :         else if (s == 0) return mkvecsmall2(1,2);
    1519        66591 :         s = cmp(E,gel(v,1),gel(v,3));
    1520        66591 :         if      (s < 0) return mkvecsmall3(1,3,2);
    1521        34832 :         else if (s > 0) return mkvecsmall3(3,1,2);
    1522         2478 :         return mkvecsmall2(1,2);
    1523       104633 :       } else if (s > 0) {
    1524        99018 :         s = cmp(E,gel(v,1),gel(v,3));
    1525        99018 :         if (s < 0) return mkvecsmall3(2,1,3);
    1526        67551 :         else if (s == 0) return mkvecsmall2(2,1);
    1527        65102 :         s = cmp(E,gel(v,2),gel(v,3));
    1528        65102 :         if (s < 0) return mkvecsmall3(2,3,1);
    1529        31843 :         else if (s > 0) return mkvecsmall3(3,2,1);
    1530          721 :         return mkvecsmall2(2,1);
    1531              :       } else {
    1532         5615 :         s = cmp(E,gel(v,1),gel(v,3));
    1533         5615 :         if (s < 0) return mkvecsmall2(1,3);
    1534         1862 :         else if (s == 0) return mkvecsmall(1);
    1535         1008 :         return mkvecsmall2(3,1);
    1536              :       }
    1537              :   }
    1538       937152 :   NX = nx = n>>1; ny = n-nx;
    1539       937152 :   av = avma;
    1540       937152 :   x = gen_sortspec_uniq(v,   nx,E,cmp); nx = lg(x)-1;
    1541       937152 :   y = gen_sortspec_uniq(v+NX,ny,E,cmp); ny = lg(y)-1;
    1542       937152 :   w = cgetg(n+1, t_VECSMALL);
    1543       937152 :   m = ix = iy = 1;
    1544     10288013 :   while (ix<=nx && iy<=ny)
    1545              :   {
    1546      9350861 :     s = cmp(E, gel(v,x[ix]), gel(v,y[iy]+NX));
    1547      9350861 :     if (s < 0)
    1548      4435672 :       w[m++] = x[ix++];
    1549      4915189 :     else if (s > 0)
    1550      3764713 :       w[m++] = y[iy++]+NX;
    1551              :     else {
    1552      1150476 :       w[m++] = x[ix++];
    1553      1150476 :       iy++;
    1554              :     }
    1555              :   }
    1556      1426738 :   while (ix<=nx) w[m++] = x[ix++];
    1557      2345573 :   while (iy<=ny) w[m++] = y[iy++]+NX;
    1558       937152 :   set_avma(av);
    1559       937152 :   W = cgetg(m, t_VECSMALL);
    1560     12186020 :   for (i = 1; i < m; i++) W[i] = w[i];
    1561       937152 :   return W;
    1562              : }
    1563              : 
    1564              : /* return permutation sorting v[1..n]. Assume n > 0 */
    1565              : static GEN
    1566    191728173 : gen_sortspec(GEN v, long n, void *E, int (*cmp)(void*,GEN,GEN))
    1567              : {
    1568              :   long nx, ny, m, ix, iy;
    1569              :   GEN x, y, w;
    1570    191728173 :   switch(n)
    1571              :   {
    1572      5800761 :     case 1:
    1573      5800761 :       (void)cmp(E,gel(v,1),gel(v,1)); /* check for type error */
    1574      5800761 :       return mkvecsmall(1);
    1575     79503924 :     case 2:
    1576    136456621 :       return cmp(E,gel(v,1),gel(v,2)) <= 0? mkvecsmall2(1,2)
    1577    136456607 :                                           : mkvecsmall2(2,1);
    1578     37580182 :     case 3:
    1579     37580182 :       if (cmp(E,gel(v,1),gel(v,2)) <= 0) {
    1580     27309283 :         if (cmp(E,gel(v,2),gel(v,3)) <= 0) return mkvecsmall3(1,2,3);
    1581     12138510 :         return (cmp(E,gel(v,1),gel(v,3)) <= 0)? mkvecsmall3(1,3,2)
    1582     12138510 :                                               : mkvecsmall3(3,1,2);
    1583              :       } else {
    1584     10270899 :         if (cmp(E,gel(v,1),gel(v,3)) <= 0) return mkvecsmall3(2,1,3);
    1585     10746076 :         return (cmp(E,gel(v,2),gel(v,3)) <= 0)? mkvecsmall3(2,3,1)
    1586     10746076 :                                               : mkvecsmall3(3,2,1);
    1587              :       }
    1588              :   }
    1589     68843306 :   nx = n>>1; ny = n-nx;
    1590     68843306 :   w = cgetg(n+1,t_VECSMALL);
    1591     68843306 :   x = gen_sortspec(v,   nx,E,cmp);
    1592     68843292 :   y = gen_sortspec(v+nx,ny,E,cmp);
    1593     68843292 :   m = ix = iy = 1;
    1594    460034998 :   while (ix<=nx && iy<=ny)
    1595    391191706 :     if (cmp(E, gel(v,x[ix]), gel(v,y[iy]+nx))<=0)
    1596    216864234 :       w[m++] = x[ix++];
    1597              :     else
    1598    174327472 :       w[m++] = y[iy++]+nx;
    1599    104844516 :   while (ix<=nx) w[m++] = x[ix++];
    1600    174691062 :   while (iy<=ny) w[m++] = y[iy++]+nx;
    1601     68843292 :   set_avma((pari_sp)w); return w;
    1602              : }
    1603              : 
    1604              : static void
    1605     47748450 : init_sort(GEN *x, long *tx, long *lx)
    1606              : {
    1607     47748450 :   *tx = typ(*x);
    1608     47748450 :   if (*tx == t_LIST)
    1609              :   {
    1610           35 :     if (list_typ(*x)!=t_LIST_RAW) pari_err_TYPE("sort",*x);
    1611           35 :     *x = list_data(*x);
    1612           35 :     *lx = *x? lg(*x): 1;
    1613              :   } else {
    1614     47748415 :     if (!is_matvec_t(*tx) && *tx != t_VECSMALL) pari_err_TYPE("gen_sort",*x);
    1615     47748415 :     *lx = lg(*x);
    1616              :   }
    1617     47748450 : }
    1618              : 
    1619              : /* (x o y)[1..lx-1], destroy y */
    1620              : INLINE GEN
    1621      3237348 : sort_extract(GEN x, GEN y, long tx, long lx)
    1622              : {
    1623              :   long i;
    1624      3237348 :   switch(tx)
    1625              :   {
    1626            7 :     case t_VECSMALL:
    1627           35 :       for (i=1; i<lx; i++) y[i] = x[y[i]];
    1628            7 :       break;
    1629            7 :     case t_LIST:
    1630            7 :       settyp(y,t_VEC);
    1631           35 :       for (i=1; i<lx; i++) gel(y,i) = gel(x,y[i]);
    1632            7 :       return gtolist(y);
    1633      3237334 :     default:
    1634      3237334 :       settyp(y,tx);
    1635      9958306 :       for (i=1; i<lx; i++) gel(y,i) = gcopy(gel(x,y[i]));
    1636              :   }
    1637      3237341 :   return y;
    1638              : }
    1639              : 
    1640              : static GEN
    1641      2260553 : triv_sort(long tx) { return tx == t_LIST? mklist(): cgetg(1, tx); }
    1642              : /* Sort the vector x, using cmp to compare entries. */
    1643              : GEN
    1644       353892 : gen_sort_uniq(GEN x, void *E, int (*cmp)(void*,GEN,GEN))
    1645              : {
    1646              :   long tx, lx;
    1647              :   GEN y;
    1648              : 
    1649       353892 :   init_sort(&x, &tx, &lx);
    1650       353892 :   if (lx==1) return triv_sort(tx);
    1651       349195 :   y = gen_sortspec_uniq(x,lx-1,E,cmp);
    1652       349195 :   return sort_extract(x, y, tx, lg(y)); /* lg(y) <= lx */
    1653              : }
    1654              : /* Sort the vector x, using cmp to compare entries. */
    1655              : GEN
    1656      5144016 : gen_sort(GEN x, void *E, int (*cmp)(void*,GEN,GEN))
    1657              : {
    1658              :   long tx, lx;
    1659              :   GEN y;
    1660              : 
    1661      5144016 :   init_sort(&x, &tx, &lx);
    1662      5144016 :   if (lx==1) return triv_sort(tx);
    1663      2888160 :   y = gen_sortspec(x,lx-1,E,cmp);
    1664      2888146 :   return sort_extract(x, y, tx, lx);
    1665              : }
    1666              : /* indirect sort: return the permutation that would sort x */
    1667              : GEN
    1668        76271 : gen_indexsort_uniq(GEN x, void *E, int (*cmp)(void*,GEN,GEN))
    1669              : {
    1670              :   long tx, lx;
    1671        76271 :   init_sort(&x, &tx, &lx);
    1672        76271 :   if (lx==1) return cgetg(1, t_VECSMALL);
    1673        69466 :   return gen_sortspec_uniq(x,lx-1,E,cmp);
    1674              : }
    1675              : /* indirect sort: return the permutation that would sort x */
    1676              : GEN
    1677       859982 : gen_indexsort(GEN x, void *E, int (*cmp)(void*,GEN,GEN))
    1678              : {
    1679              :   long tx, lx;
    1680       859982 :   init_sort(&x, &tx, &lx);
    1681       859982 :   if (lx==1) return cgetg(1, t_VECSMALL);
    1682       859653 :   return gen_sortspec(x,lx-1,E,cmp);
    1683              : }
    1684              : 
    1685              : /* Sort the vector x in place, using cmp to compare entries */
    1686              : void
    1687     40890012 : gen_sort_inplace(GEN x, void *E, int (*cmp)(void*,GEN,GEN), GEN *perm)
    1688              : {
    1689              :   long tx, lx, i;
    1690     40890012 :   pari_sp av = avma;
    1691              :   GEN y;
    1692              : 
    1693     40890012 :   init_sort(&x, &tx, &lx);
    1694     40890012 :   if (lx<=2)
    1695              :   {
    1696       782019 :     if (perm) *perm = lx == 1? cgetg(1, t_VECSMALL): mkvecsmall(1);
    1697       782019 :     return;
    1698              :   }
    1699     40107993 :   y = gen_sortspec(x,lx-1, E, cmp);
    1700     40107993 :   if (perm)
    1701              :   {
    1702        16107 :     GEN z = new_chunk(lx);
    1703       123592 :     for (i=1; i<lx; i++) gel(z,i) = gel(x,y[i]);
    1704       123592 :     for (i=1; i<lx; i++) gel(x,i) = gel(z,i);
    1705        16107 :     *perm = y;
    1706        16107 :     set_avma((pari_sp)y);
    1707              :   } else {
    1708    285642022 :     for (i=1; i<lx; i++) gel(y,i) = gel(x,y[i]);
    1709    285642022 :     for (i=1; i<lx; i++) gel(x,i) = gel(y,i);
    1710     40091886 :     set_avma(av);
    1711              :   }
    1712              : }
    1713              : GEN
    1714       424249 : gen_sort_shallow(GEN x, void *E, int (*cmp)(void*,GEN,GEN))
    1715              : {
    1716              :   long tx, lx, i;
    1717              :   pari_sp av;
    1718              :   GEN y, z;
    1719              : 
    1720       424249 :   init_sort(&x, &tx, &lx);
    1721       424249 :   if (lx<=2) return x;
    1722       259294 :   z = cgetg(lx, tx); av = avma;
    1723       259294 :   y = gen_sortspec(x,lx-1, E, cmp);
    1724      1311331 :   for (i=1; i<lx; i++) gel(z,i) = gel(x,y[i]);
    1725       259294 :   return gc_const(av, z);
    1726              : }
    1727              : 
    1728              : static int
    1729         7909 : closurecmp(void *data, GEN x, GEN y)
    1730              : {
    1731         7909 :   pari_sp av = avma;
    1732         7909 :   long s = gsigne(closure_callgen2((GEN)data, x,y));
    1733         7909 :   set_avma(av); return s;
    1734              : }
    1735              : static void
    1736          140 : check_positive_entries(GEN k)
    1737              : {
    1738          140 :   long i, l = lg(k);
    1739          315 :   for (i=1; i<l; i++)
    1740          175 :     if (k[i] <= 0) pari_err_DOMAIN("sort_function", "index", "<", gen_0, stoi(k[i]));
    1741          140 : }
    1742              : 
    1743              : typedef int (*CMP_FUN)(void*,GEN,GEN);
    1744              : /* return NULL if t_CLOSURE k is a "key" (arity 1) and not a sorting func */
    1745              : static CMP_FUN
    1746       128996 : sort_function(void **E, GEN x, GEN k)
    1747              : {
    1748       128996 :   int (*cmp)(GEN,GEN) = &lexcmp;
    1749       128996 :   long tx = typ(x);
    1750       128996 :   if (!k)
    1751              :   {
    1752       128303 :     *E = (void*)((typ(x) == t_VECSMALL)? cmp_small: cmp);
    1753       128303 :     return &cmp_nodata;
    1754              :   }
    1755          693 :   if (tx == t_VECSMALL) pari_err_TYPE("sort_function", x);
    1756          679 :   switch(typ(k))
    1757              :   {
    1758          105 :     case t_INT: k = mkvecsmall(itos(k));  break;
    1759           35 :     case t_VEC: case t_COL: k = ZV_to_zv(k); break;
    1760            0 :     case t_VECSMALL: break;
    1761          539 :     case t_CLOSURE:
    1762          539 :      if (closure_is_variadic(k))
    1763            0 :        pari_err_TYPE("sort_function, variadic cmpf",k);
    1764          539 :      *E = (void*)k;
    1765          539 :      switch(closure_arity(k))
    1766              :      {
    1767           35 :        case 1: return NULL; /* wrt key */
    1768          504 :        case 2: return &closurecmp;
    1769            0 :        default: pari_err_TYPE("sort_function, cmpf arity != 1, 2",k);
    1770              :      }
    1771            0 :     default: pari_err_TYPE("sort_function",k);
    1772              :   }
    1773          140 :   check_positive_entries(k);
    1774          140 :   *E = (void*)k; return &veccmp;
    1775              : }
    1776              : 
    1777              : #define cmp_IND 1
    1778              : #define cmp_LEX 2 /* FIXME: backward compatibility, ignored */
    1779              : #define cmp_REV 4
    1780              : #define cmp_UNIQ 8
    1781              : GEN
    1782          749 : vecsort0(GEN x, GEN k, long flag)
    1783              : {
    1784              :   void *E;
    1785          749 :   int (*CMP)(void*,GEN,GEN) = sort_function(&E, x, k);
    1786              : 
    1787          742 :   if (flag < 0 || flag > (cmp_REV|cmp_LEX|cmp_IND|cmp_UNIQ))
    1788            0 :     pari_err_FLAG("vecsort");
    1789          742 :   if (!CMP)
    1790              :   { /* wrt key: precompute all values, O(n) calls instead of O(n log n) */
    1791           28 :     pari_sp av = avma;
    1792              :     GEN v, y;
    1793              :     long i, tx, lx;
    1794           28 :     init_sort(&x, &tx, &lx);
    1795           28 :     if (lx == 1) return flag&cmp_IND? cgetg(1,t_VECSMALL): triv_sort(tx);
    1796           28 :     v = cgetg(lx, t_VEC);
    1797          140 :     for (i = 1; i < lx; i++) gel(v,i) = closure_callgen1(k, gel(x,i));
    1798           28 :     y = vecsort0(v, NULL, flag | cmp_IND);
    1799           28 :     y = flag&cmp_IND? y: sort_extract(x, y, tx, lg(y));
    1800           28 :     return gc_upto(av, y);
    1801              :   }
    1802          714 :   if (flag&cmp_UNIQ)
    1803           35 :     x = flag&cmp_IND? gen_indexsort_uniq(x, E, CMP): gen_sort_uniq(x, E, CMP);
    1804              :   else
    1805          679 :     x = flag&cmp_IND? gen_indexsort(x, E, CMP): gen_sort(x, E, CMP);
    1806          700 :   if (flag & cmp_REV)
    1807              :   { /* reverse order */
    1808           35 :     GEN y = x;
    1809           35 :     if (typ(x)==t_LIST) { y = list_data(x); if (!y) return x; }
    1810           28 :     vecreverse_inplace(y);
    1811              :   }
    1812          693 :   return x;
    1813              : }
    1814              : 
    1815              : GEN
    1816       205793 : indexsort(GEN x) { return gen_indexsort(x, (void*)&gcmp, cmp_nodata); }
    1817              : GEN
    1818            0 : indexlexsort(GEN x) { return gen_indexsort(x, (void*)&lexcmp, cmp_nodata); }
    1819              : GEN
    1820           42 : indexvecsort(GEN x, GEN k)
    1821              : {
    1822           42 :   if (typ(k) != t_VECSMALL) pari_err_TYPE("vecsort",k);
    1823           42 :   return gen_indexsort(x, (void*)k, &veccmp);
    1824              : }
    1825              : 
    1826              : GEN
    1827      2098400 : sort(GEN x) { return gen_sort(x, (void*)gcmp, cmp_nodata); }
    1828              : GEN
    1829       127981 : lexsort(GEN x) { return gen_sort(x, (void*)lexcmp, cmp_nodata); }
    1830              : GEN
    1831         2954 : vecsort(GEN x, GEN k)
    1832              : {
    1833         2954 :   if (typ(k) != t_VECSMALL) pari_err_TYPE("vecsort",k);
    1834         2954 :   return gen_sort(x, (void*)k, &veccmp);
    1835              : }
    1836              : /* adapted from gen_search; don't export: keys of T[i] should be precomputed */
    1837              : static long
    1838            7 : key_search(GEN T, GEN x, GEN code)
    1839              : {
    1840            7 :   long u = lg(T)-1, i, l, s;
    1841              : 
    1842            7 :   if (!u) return 0;
    1843            7 :   l = 1; x = closure_callgen1(code, x);
    1844              :   do
    1845              :   {
    1846           14 :     i = (l+u)>>1; s = lexcmp(x, closure_callgen1(code, gel(T,i)));
    1847           14 :     if (!s) return i;
    1848            7 :     if (s<0) u=i-1; else l=i+1;
    1849            7 :   } while (u>=l);
    1850            0 :   return 0;
    1851              : }
    1852              : long
    1853       128247 : vecsearch(GEN v, GEN x, GEN k)
    1854              : {
    1855       128247 :   pari_sp av = avma;
    1856              :   long r;
    1857              :   void *E;
    1858       128247 :   int (*CMP)(void*,GEN,GEN) = sort_function(&E, v, k);
    1859       128240 :   switch(typ(v))
    1860              :   {
    1861           21 :     case t_VECSMALL: x = (GEN)itos(x); break;
    1862       128198 :     case t_VEC: case t_COL: case t_MAT: break;
    1863           21 :     case t_LIST:
    1864           21 :       if (list_typ(v)==t_LIST_RAW)
    1865              :       {
    1866           21 :         v = list_data(v); if (!v) v = cgetg(1, t_VEC);
    1867           21 :         break;
    1868              :       }
    1869              :       /* fall through */
    1870              :     default:
    1871            0 :       pari_err_TYPE("vecsearch", v);
    1872              :   }
    1873       128240 :   r = CMP? gen_search(v, x, E, CMP): key_search(v, x, k);
    1874       128240 :   return gc_long(av, r < 0? 0: r);
    1875              : }
    1876              : 
    1877              : GEN
    1878         3773 : ZV_indexsort(GEN L) { return gen_indexsort(L, (void*)&cmpii, &cmp_nodata); }
    1879              : GEN
    1880           63 : ZV_sort(GEN L) { return gen_sort(L, (void*)&cmpii, &cmp_nodata); }
    1881              : GEN
    1882        66248 : ZV_sort_uniq(GEN L) { return gen_sort_uniq(L, (void*)&cmpii, &cmp_nodata); }
    1883              : void
    1884      1991692 : ZV_sort_inplace(GEN L) { gen_sort_inplace(L, (void*)&cmpii, &cmp_nodata,NULL); }
    1885              : GEN
    1886        39850 : ZV_sort_uniq_shallow(GEN L)
    1887              : {
    1888        39850 :   GEN v = gen_indexsort_uniq(L, (void*)&cmpii, &cmp_nodata);
    1889        39850 :   return vecpermute(L, v);
    1890              : }
    1891              : GEN
    1892         1288 : ZV_sort_shallow(GEN L)
    1893              : {
    1894         1288 :   GEN v = gen_indexsort(L, (void*)&cmpii, &cmp_nodata);
    1895         1288 :   return vecpermute(L, v);
    1896              : }
    1897              : 
    1898              : GEN
    1899         1141 : vec_equiv(GEN F)
    1900              : {
    1901         1141 :   pari_sp av = avma;
    1902         1141 :   long j, k, L = lg(F);
    1903         1141 :   GEN w = cgetg(L, t_VEC);
    1904         1141 :   GEN perm = gen_indexsort(F, (void*)&cmp_universal, cmp_nodata);
    1905         3451 :   for (j = k = 1; j < L;)
    1906              :   {
    1907         2310 :     GEN v = cgetg(L, t_VECSMALL);
    1908         2310 :     long l = 1, o = perm[j];
    1909         2310 :     v[l++] = o;
    1910         5593 :     for (j++; j < L; v[l++] = perm[j++])
    1911         4452 :       if (!gequal(gel(F,o), gel(F, perm[j]))) break;
    1912         2310 :     setlg(v, l); gel(w, k++) = v;
    1913              :   }
    1914         1141 :   setlg(w, k); return gc_GEN(av,w);
    1915              : }
    1916              : 
    1917              : GEN
    1918        23044 : vec_reduce(GEN v, GEN *pE)
    1919              : {
    1920        23044 :   GEN E, F, P = gen_indexsort(v, (void*)cmp_universal, cmp_nodata);
    1921              :   long i, m, l;
    1922        23044 :   F = cgetg_copy(v, &l);
    1923        23044 :   *pE = E = cgetg(l, t_VECSMALL);
    1924        59458 :   for (i = m = 1; i < l;)
    1925              :   {
    1926        36414 :     GEN u = gel(v, P[i]);
    1927              :     long k;
    1928        44688 :     for(k = i + 1; k < l; k++)
    1929        21651 :       if (cmp_universal(gel(v, P[k]), u)) break;
    1930        36414 :     E[m] = k - i; gel(F, m) = u; i = k; m++;
    1931              :   }
    1932        23044 :   setlg(F, m);
    1933        23044 :   setlg(E, m); return F;
    1934              : }
    1935              : 
    1936              : /********************************************************************/
    1937              : /**                      SEARCH IN SORTED VECTOR                   **/
    1938              : /********************************************************************/
    1939              : /* index of x in table T, 0 otherwise */
    1940              : long
    1941      1148558 : tablesearch(GEN T, GEN x, int (*cmp)(GEN,GEN))
    1942              : {
    1943      1148558 :   long l = 1, u = lg(T)-1, i, s;
    1944              : 
    1945      8213904 :   while (u>=l)
    1946              :   {
    1947      8161751 :     i = (l+u)>>1; s = cmp(x, gel(T,i));
    1948      8161751 :     if (!s) return i;
    1949      7065346 :     if (s<0) u=i-1; else l=i+1;
    1950              :   }
    1951        52153 :   return 0;
    1952              : }
    1953              : 
    1954              : /* looks if x belongs to the set T and returns the index if yes, 0 if no */
    1955              : long
    1956     24034171 : gen_search(GEN T, GEN x, void *data, int (*cmp)(void*,GEN,GEN))
    1957              : {
    1958     24034171 :   long u = lg(T)-1, i, l, s;
    1959              : 
    1960     24034171 :   if (!u) return -1;
    1961     24034143 :   l = 1;
    1962              :   do
    1963              :   {
    1964    113915907 :     i = (l+u) >> 1; s = cmp(data, x, gel(T,i));
    1965    113915907 :     if (!s) return i;
    1966     90387402 :     if (s < 0) u = i-1; else l = i+1;
    1967     90387402 :   } while (u >= l);
    1968       505638 :   return -((s < 0)? i: i+1);
    1969              : }
    1970              : 
    1971              : long
    1972      1074432 : ZV_search(GEN x, GEN y) { return tablesearch(x, y, cmpii); }
    1973              : 
    1974              : long
    1975     13191589 : zv_search(GEN T, long x)
    1976              : {
    1977     13191589 :   long l = 1, u = lg(T)-1;
    1978     53337164 :   while (u>=l)
    1979              :   {
    1980     42602556 :     long i = (l+u)>>1;
    1981     42602556 :     if (x < T[i]) u = i-1;
    1982     26394980 :     else if (x > T[i]) l = i+1;
    1983      2456981 :     else return i;
    1984              :   }
    1985     10734608 :   return 0;
    1986              : }
    1987              : 
    1988              : /********************************************************************/
    1989              : /**                   COMPARISON FUNCTIONS                         **/
    1990              : /********************************************************************/
    1991              : int
    1992    649770776 : cmp_nodata(void *data, GEN x, GEN y)
    1993              : {
    1994    649770776 :   int (*cmp)(GEN,GEN)=(int (*)(GEN,GEN)) data;
    1995    649770776 :   return cmp(x,y);
    1996              : }
    1997              : 
    1998              : /* assume x and y come from the same idealprimedec call (uniformizer unique) */
    1999              : int
    2000      3477963 : cmp_prime_over_p(GEN x, GEN y)
    2001              : {
    2002      3477963 :   long k = pr_get_f(x) - pr_get_f(y); /* diff. between residue degree */
    2003       222125 :   return k? ((k > 0)? 1: -1)
    2004      3700088 :           : ZV_cmp(pr_get_gen(x), pr_get_gen(y));
    2005              : }
    2006              : 
    2007              : int
    2008       705492 : cmp_prime_ideal(GEN x, GEN y)
    2009              : {
    2010       705492 :   int k = cmpii(pr_get_p(x), pr_get_p(y));
    2011       705492 :   return k? k: cmp_prime_over_p(x,y);
    2012              : }
    2013              : 
    2014              : /* assume x and y are t_POL in the same variable whose coeffs can be
    2015              :  * compared (used to sort polynomial factorizations) */
    2016              : int
    2017      5653778 : gen_cmp_RgX(void *data, GEN x, GEN y)
    2018              : {
    2019      5653778 :   int (*coeff_cmp)(GEN,GEN)=(int(*)(GEN,GEN))data;
    2020      5653778 :   long i, lx = lg(x), ly = lg(y);
    2021              :   int fl;
    2022      5653778 :   if (lx > ly) return  1;
    2023      5615820 :   if (lx < ly) return -1;
    2024     12554879 :   for (i=lx-1; i>1; i--)
    2025     11776805 :     if ((fl = coeff_cmp(gel(x,i), gel(y,i)))) return fl;
    2026       778074 :   return 0;
    2027              : }
    2028              : 
    2029              : static int
    2030         4661 : cmp_RgX_Rg(GEN x, GEN y)
    2031              : {
    2032         4661 :   long lx = lgpol(x), ly;
    2033         4661 :   if (lx > 1) return  1;
    2034            0 :   ly = gequal0(y) ? 0:1;
    2035            0 :   if (lx > ly) return  1;
    2036            0 :   if (lx < ly) return -1;
    2037            0 :   if (lx==0) return 0;
    2038            0 :   return gcmp(gel(x,2), y);
    2039              : }
    2040              : int
    2041       130371 : cmp_RgX(GEN x, GEN y)
    2042              : {
    2043       130371 :   if (typ(x) == t_POLMOD) x = gel(x,2);
    2044       130371 :   if (typ(y) == t_POLMOD) y = gel(y,2);
    2045       130371 :   if (typ(x) == t_POL) {
    2046        63007 :     if (typ(y) != t_POL) return cmp_RgX_Rg(x, y);
    2047              :   } else {
    2048        67364 :     if (typ(y) != t_POL) return gcmp(x,y);
    2049         3870 :     return - cmp_RgX_Rg(y,x);
    2050              :   }
    2051        62216 :   return gen_cmp_RgX((void*)&gcmp,x,y);
    2052              : }
    2053              : 
    2054              : int
    2055       326390 : cmp_Flx(GEN x, GEN y)
    2056              : {
    2057       326390 :   long i, lx = lg(x), ly = lg(y);
    2058       326390 :   if (lx > ly) return  1;
    2059       310041 :   if (lx < ly) return -1;
    2060       551879 :   for (i=lx-1; i>1; i--)
    2061       467093 :     if (uel(x,i) != uel(y,i)) return uel(x,i)<uel(y,i)? -1: 1;
    2062        84786 :   return 0;
    2063              : }
    2064              : /********************************************************************/
    2065              : /**                   MERGE & SORT FACTORIZATIONS                  **/
    2066              : /********************************************************************/
    2067              : /* merge fx, fy two factorizations, whose 1st column is sorted in strictly
    2068              :  * increasing order wrt cmp */
    2069              : GEN
    2070       692082 : merge_factor(GEN fx, GEN fy, void *data, int (*cmp)(void *,GEN,GEN))
    2071              : {
    2072       692082 :   GEN x = gel(fx,1), e = gel(fx,2), M, E;
    2073       692082 :   GEN y = gel(fy,1), f = gel(fy,2);
    2074       692082 :   long ix, iy, m, lx = lg(x), ly = lg(y), l = lx+ly-1;
    2075              : 
    2076       692082 :   M = cgetg(l, t_COL);
    2077       692082 :   E = cgetg(l, t_COL);
    2078              : 
    2079       692082 :   m = ix = iy = 1;
    2080     10044970 :   while (ix<lx && iy<ly)
    2081              :   {
    2082      9352888 :     int s = cmp(data, gel(x,ix), gel(y,iy));
    2083      9352888 :     if (s < 0)
    2084      8718202 :     { gel(M,m) = gel(x,ix); gel(E,m) = gel(e,ix); ix++; }
    2085       634686 :     else if (s == 0)
    2086              :     {
    2087        95018 :       GEN z = gel(x,ix), g = addii(gel(e,ix), gel(f,iy));
    2088        95018 :       iy++; ix++; if (!signe(g)) continue;
    2089        11081 :       gel(M,m) = z; gel(E,m) = g;
    2090              :     }
    2091              :     else
    2092       539668 :     { gel(M,m) = gel(y,iy); gel(E,m) = gel(f,iy); iy++; }
    2093      9268951 :     m++;
    2094              :   }
    2095      4860139 :   while (ix<lx) { gel(M,m) = gel(x,ix); gel(E,m) = gel(e,ix); ix++; m++; }
    2096       937118 :   while (iy<ly) { gel(M,m) = gel(y,iy); gel(E,m) = gel(f,iy); iy++; m++; }
    2097       692082 :   setlg(M, m);
    2098       692082 :   setlg(E, m); return mkmat2(M, E);
    2099              : }
    2100              : 
    2101              : GEN
    2102        30792 : ZM_merge_factor(GEN A, GEN B)
    2103              : {
    2104        30792 :   return merge_factor(A, B, (void*)&cmpii, cmp_nodata);
    2105              : }
    2106              : 
    2107              : /* merge two sorted vectors, removing duplicates. Shallow */
    2108              : GEN
    2109       455057 : merge_sort_uniq(GEN x, GEN y, void *data, int (*cmp)(void *,GEN,GEN))
    2110              : {
    2111       455057 :   long i, j, k, lx = lg(x), ly = lg(y);
    2112       455057 :   GEN z = cgetg(lx + ly - 1, typ(x));
    2113       455057 :   i = j = k = 1;
    2114       595816 :   while (i<lx && j<ly)
    2115              :   {
    2116       140759 :     int s = cmp(data, gel(x,i), gel(y,j));
    2117       140759 :     if (s < 0)
    2118       120043 :       gel(z,k++) = gel(x,i++);
    2119        20716 :     else if (s > 0)
    2120        20695 :       gel(z,k++) = gel(y,j++);
    2121              :     else
    2122           21 :     { gel(z,k++) = gel(x,i++); j++; }
    2123              :   }
    2124       808986 :   while (i<lx) gel(z,k++) = gel(x,i++);
    2125       589026 :   while (j<ly) gel(z,k++) = gel(y,j++);
    2126       455057 :   setlg(z, k); return z;
    2127              : }
    2128              : /* in case of equal keys in x,y, take the key from x */
    2129              : static GEN
    2130        39536 : ZV_union_shallow_t(GEN x, GEN y, long t)
    2131              : {
    2132        39536 :   long i, j, k, lx = lg(x), ly = lg(y);
    2133        39536 :   GEN z = cgetg(lx + ly - 1, t);
    2134        39536 :   i = j = k = 1;
    2135        92344 :   while (i<lx && j<ly)
    2136              :   {
    2137        52808 :     int s = cmpii(gel(x,i), gel(y,j));
    2138        52808 :     if (s < 0)
    2139        23639 :       gel(z,k++) = gel(x,i++);
    2140        29169 :     else if (s > 0)
    2141        19649 :       gel(z,k++) = gel(y,j++);
    2142              :     else
    2143         9520 :     { gel(z,k++) = gel(x,i++); j++; }
    2144              :   }
    2145        51422 :   while (i < lx) gel(z,k++) = gel(x,i++);
    2146        75236 :   while (j < ly) gel(z,k++) = gel(y,j++);
    2147        39536 :   setlg(z, k); return z;
    2148              : }
    2149              : GEN
    2150        39354 : ZV_union_shallow(GEN x, GEN y)
    2151        39354 : { return ZV_union_shallow_t(x, y, t_VEC); }
    2152              : GEN
    2153          182 : ZC_union_shallow(GEN x, GEN y)
    2154          182 : { return ZV_union_shallow_t(x, y, t_COL); }
    2155              : 
    2156              : /* sort generic factorization, in place */
    2157              : GEN
    2158      9949280 : sort_factor(GEN y, void *data, int (*cmp)(void *,GEN,GEN))
    2159              : {
    2160              :   GEN a, b, A, B, w;
    2161              :   pari_sp av;
    2162              :   long n, i;
    2163              : 
    2164      9949280 :   a = gel(y,1); n = lg(a); if (n == 1) return y;
    2165      9926475 :   b = gel(y,2); av = avma;
    2166      9926475 :   A = new_chunk(n);
    2167      9926475 :   B = new_chunk(n);
    2168      9926475 :   w = gen_sortspec(a, n-1, data, cmp);
    2169     29631706 :   for (i=1; i<n; i++) { long k=w[i]; gel(A,i) = gel(a,k); gel(B,i) = gel(b,k); }
    2170     29631706 :   for (i=1; i<n; i++) { gel(a,i) = gel(A,i); gel(b,i) = gel(B,i); }
    2171      9926475 :   set_avma(av); return y;
    2172              : }
    2173              : /* sort polynomial factorization, in place */
    2174              : GEN
    2175      2017052 : sort_factor_pol(GEN y,int (*cmp)(GEN,GEN))
    2176              : {
    2177      2017052 :   (void)sort_factor(y,(void*)cmp, &gen_cmp_RgX);
    2178      2017052 :   return y;
    2179              : }
    2180              : 
    2181              : /***********************************************************************/
    2182              : /*                                                                     */
    2183              : /*                          SET OPERATIONS                             */
    2184              : /*                                                                     */
    2185              : /***********************************************************************/
    2186              : GEN
    2187       227122 : gtoset(GEN x)
    2188              : {
    2189              :   long lx;
    2190       227122 :   if (!x) return cgetg(1, t_VEC);
    2191       227122 :   switch(typ(x))
    2192              :   {
    2193       227094 :     case t_VEC:
    2194       227094 :     case t_COL: lx = lg(x); break;
    2195           14 :     case t_LIST:
    2196           14 :       if (list_typ(x)==t_LIST_MAP) return mapdomain(x);
    2197           14 :       x = list_data(x); lx = x? lg(x): 1; break;
    2198            7 :     case t_VECSMALL: lx = lg(x); x = zv_to_ZV(x); break;
    2199            7 :     default: return mkveccopy(x);
    2200              :   }
    2201       227115 :   if (lx==1) return cgetg(1,t_VEC);
    2202       226940 :   x = gen_sort_uniq(x, (void*)&cmp_universal, cmp_nodata);
    2203       226940 :   settyp(x, t_VEC); /* it may be t_COL */
    2204       226940 :   return x;
    2205              : }
    2206              : 
    2207              : long
    2208           14 : setisset(GEN x)
    2209              : {
    2210           14 :   long i, lx = lg(x);
    2211              : 
    2212           14 :   if (typ(x) != t_VEC) return 0;
    2213           14 :   if (lx == 1) return 1;
    2214           70 :   for (i=1; i<lx-1; i++)
    2215           63 :     if (cmp_universal(gel(x,i+1), gel(x,i)) <= 0) return 0;
    2216            7 :   return 1;
    2217              : }
    2218              : 
    2219              : long
    2220       536431 : setsearch(GEN T, GEN y, long flag)
    2221              : {
    2222              :   long i, lx;
    2223       536431 :   switch(typ(T))
    2224              :   {
    2225       536417 :     case t_VEC: lx = lg(T); break;
    2226            7 :     case t_LIST:
    2227            7 :     if (list_typ(T) != t_LIST_RAW) pari_err_TYPE("setsearch",T);
    2228            7 :     T = list_data(T); lx = T? lg(T): 1; break;
    2229            7 :     default: pari_err_TYPE("setsearch",T);
    2230              :       return 0; /*LCOV_EXCL_LINE*/
    2231              :   }
    2232       536424 :   if (lx==1) return flag? 1: 0;
    2233       536424 :   i = gen_search(T,y,(void*)cmp_universal,cmp_nodata);
    2234       536424 :   if (i > 0) return flag? 0: i;
    2235       452200 :   return flag ? -i: 0;
    2236              : }
    2237              : 
    2238              : GEN
    2239            7 : setunion_i(GEN x, GEN y)
    2240            7 : { return merge_sort_uniq(x,y, (void*)cmp_universal, cmp_nodata); }
    2241              : 
    2242              : GEN
    2243            7 : setunion(GEN x, GEN y)
    2244              : {
    2245            7 :   pari_sp av = avma;
    2246            7 :   if (typ(x) != t_VEC) pari_err_TYPE("setunion",x);
    2247            7 :   if (typ(y) != t_VEC) pari_err_TYPE("setunion",y);
    2248            7 :   return gc_GEN(av, setunion_i(x, y));
    2249              : }
    2250              : 
    2251              : GEN
    2252           14 : setdelta(GEN x, GEN y)
    2253              : {
    2254           14 :   long ix = 1, iy = 1, iz = 1, lx = lg(x), ly = lg(y);
    2255           14 :   pari_sp av = avma;
    2256           14 :   GEN z = cgetg(lx + ly - 1,t_VEC);
    2257           14 :   if (typ(x) != t_VEC) pari_err_TYPE("setdelta",x);
    2258           14 :   if (typ(y) != t_VEC) pari_err_TYPE("setdelta",y);
    2259           84 :   while (ix < lx && iy < ly)
    2260              :   {
    2261           70 :     int c = cmp_universal(gel(x,ix), gel(y,iy));
    2262           70 :     if      (c < 0) gel(z, iz++) = gel(x,ix++);
    2263           42 :     else if (c > 0) gel(z, iz++) = gel(y,iy++);
    2264           28 :     else { ix++; iy++; }
    2265              :   }
    2266           21 :   while (ix<lx) gel(z,iz++) = gel(x,ix++);
    2267           14 :   while (iy<ly) gel(z,iz++) = gel(y,iy++);
    2268           14 :   setlg(z,iz); return gc_GEN(av,z);
    2269              : }
    2270              : 
    2271              : GEN
    2272            7 : setintersect(GEN x, GEN y)
    2273              : {
    2274            7 :   long ix = 1, iy = 1, iz = 1, lx = lg(x), ly = lg(y);
    2275            7 :   pari_sp av = avma;
    2276            7 :   GEN z = cgetg(lx,t_VEC);
    2277            7 :   if (typ(x) != t_VEC) pari_err_TYPE("setintersect",x);
    2278            7 :   if (typ(y) != t_VEC) pari_err_TYPE("setintersect",y);
    2279           70 :   while (ix < lx && iy < ly)
    2280              :   {
    2281           63 :     int c = cmp_universal(gel(x,ix), gel(y,iy));
    2282           63 :     if      (c < 0) ix++;
    2283           35 :     else if (c > 0) iy++;
    2284           21 :     else { gel(z, iz++) = gel(x,ix); ix++; iy++; }
    2285              :   }
    2286            7 :   setlg(z,iz); return gc_GEN(av,z);
    2287              : }
    2288              : 
    2289              : GEN
    2290          259 : gen_setminus(GEN A, GEN B, int (*cmp)(GEN,GEN))
    2291              : {
    2292          259 :   pari_sp ltop = avma;
    2293          259 :   long i = 1, j = 1, k = 1, lx = lg(A), ly = lg(B);
    2294          259 :   GEN  diff = cgetg(lx,t_VEC);
    2295         5481 :   while (i < lx && j < ly)
    2296         5222 :     switch ( cmp(gel(A,i),gel(B,j)) )
    2297              :     {
    2298          938 :       case -1: gel(diff,k++) = gel(A,i++); break;
    2299         2044 :       case 1: j++; break;
    2300         2240 :       case 0: i++; break;
    2301              :     }
    2302          308 :   while (i < lx) gel(diff,k++) = gel(A,i++);
    2303          259 :   setlg(diff,k);
    2304          259 :   return gc_GEN(ltop,diff);
    2305              : }
    2306              : 
    2307              : GEN
    2308          259 : setminus(GEN x, GEN y)
    2309              : {
    2310          259 :   if (typ(x) != t_VEC) pari_err_TYPE("setminus",x);
    2311          259 :   if (typ(y) != t_VEC) pari_err_TYPE("setminus",y);
    2312          259 :   return gen_setminus(x,y,cmp_universal);
    2313              : }
    2314              : 
    2315              : GEN
    2316           21 : setbinop(GEN f, GEN x, GEN y)
    2317              : {
    2318           21 :   pari_sp av = avma;
    2319           21 :   long i, j, lx, ly, k = 1;
    2320              :   GEN z;
    2321           21 :   if (typ(f) != t_CLOSURE || closure_arity(f) != 2 || closure_is_variadic(f))
    2322            7 :     pari_err_TYPE("setbinop [function needs exactly 2 arguments]",f);
    2323           14 :   lx = lg(x);
    2324           14 :   if (typ(x) != t_VEC) pari_err_TYPE("setbinop", x);
    2325           14 :   if (y == NULL) { /* assume x = y and f symmetric */
    2326            7 :     z = cgetg((((lx-1)*lx) >> 1) + 1, t_VEC);
    2327           28 :     for (i = 1; i < lx; i++)
    2328           63 :       for (j = i; j < lx; j++)
    2329           42 :         gel(z, k++) = closure_callgen2(f, gel(x,i),gel(x,j));
    2330              :   } else {
    2331            7 :     ly = lg(y);
    2332            7 :     if (typ(y) != t_VEC) pari_err_TYPE("setbinop", y);
    2333            7 :     z = cgetg((lx-1)*(ly-1) + 1, t_VEC);
    2334           28 :     for (i = 1; i < lx; i++)
    2335           84 :       for (j = 1; j < ly; j++)
    2336           63 :         gel(z, k++) = closure_callgen2(f, gel(x,i),gel(y,j));
    2337              :   }
    2338           14 :   return gc_upto(av, gtoset(z));
    2339              : }
        

Generated by: LCOV version 2.0-1