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 - gen2.c (source / functions) Coverage Total Hit
Test: PARI/GP v2.18.1 lcov report (development 31041-bd73e9fcdd) Lines: 93.6 % 1667 1561
Test Date: 2026-07-22 22:45:42 Functions: 94.9 % 158 150
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              : /********************************************************************/
      16              : /**                                                                **/
      17              : /**                      GENERIC OPERATIONS                        **/
      18              : /**                        (second part)                           **/
      19              : /**                                                                **/
      20              : /********************************************************************/
      21              : #include "pari.h"
      22              : #include "paripriv.h"
      23              : 
      24              : /*********************************************************************/
      25              : /**                                                                 **/
      26              : /**                MAP FUNCTIONS WITH GIVEN PROTOTYPES              **/
      27              : /**                                                                 **/
      28              : /*********************************************************************/
      29              : GEN
      30          462 : map_proto_G(GEN (*f)(GEN), GEN x)
      31              : {
      32          462 :   if (is_matvec_t(typ(x))) pari_APPLY_same(map_proto_G(f, gel(x,i)));
      33          462 :   return f(x);
      34              : }
      35              : 
      36              : GEN
      37     37435554 : map_proto_lG(long (*f)(GEN), GEN x)
      38              : {
      39     37435638 :   if (is_matvec_t(typ(x))) pari_APPLY_same(map_proto_lG(f, gel(x,i)));
      40     37417213 :   return stoi(f(x));
      41              : }
      42              : 
      43              : GEN
      44          126 : map_proto_lGL(long (*f)(GEN,long), GEN x, long y)
      45              : {
      46          154 :   if (is_matvec_t(typ(x))) pari_APPLY_same(map_proto_lGL(f,gel(x,i),y));
      47          119 :   return stoi(f(x,y));
      48              : }
      49              : 
      50              : static GEN
      51      2258886 : _domul(void *data, GEN x, GEN y)
      52              : {
      53      2258886 :   GEN (*mul)(GEN,GEN)=(GEN (*)(GEN,GEN)) data;
      54      2258886 :   return mul(x,y);
      55              : }
      56              : 
      57              : GEN
      58      2462783 : gassoc_proto(GEN (*f)(GEN,GEN), GEN x, GEN y)
      59              : {
      60      2462783 :   if (!y)
      61              :   {
      62      2462783 :     pari_sp av = avma;
      63      2462783 :     switch(typ(x))
      64              :     {
      65           21 :       case t_LIST:
      66           21 :         x = list_data(x); if (!x) return gen_1;
      67              :       case t_VEC:
      68      2462769 :       case t_COL: break;
      69            7 :       default: pari_err_TYPE("association",x);
      70              :     }
      71      2462769 :     return gc_upto(av, gen_product(x, (void *)f, _domul));
      72              : 
      73              :   }
      74            0 :   return f(x,y);
      75              : }
      76              : 
      77              : /*******************************************************************/
      78              : /*                                                                 */
      79              : /*                            SIZES                                */
      80              : /*                                                                 */
      81              : /*******************************************************************/
      82              : 
      83              : long
      84      5150313 : glength(GEN x)
      85              : {
      86      5150313 :   long tx = typ(x);
      87      5150313 :   switch(tx)
      88              :   {
      89          126 :     case t_INT:  return lgefint(x)-2;
      90          609 :     case t_LIST: {
      91          609 :       GEN L = list_data(x);
      92          609 :       return L? lg(L)-1: 0;
      93              :     }
      94           14 :     case t_REAL: return signe(x)? lg(x)-2: 0;
      95           14 :     case t_STR:  return strlen( GSTR(x) );
      96           91 :     case t_VECSMALL: return lg(x)-1;
      97              :   }
      98      5149459 :   return lg(x) - lontyp[tx];
      99              : }
     100              : 
     101              : long
     102         3878 : gtranslength(GEN x)
     103              : {
     104         3878 :   switch(typ(x))
     105              :   {
     106            0 :     case t_VEC: case t_COL:
     107            0 :       return lg(x)-1;
     108         3878 :     case t_MAT:
     109         3878 :       return lg(x)==1 ? 0: nbrows(x);
     110            0 :     default:
     111            0 :       pari_err_TYPE("trans",x);
     112              :       return 0; /* LCOV_EXCL_LINE */
     113              :   }
     114              : }
     115              : 
     116              : GEN
     117         1862 : matsize(GEN x)
     118              : {
     119         1862 :   long L = lg(x) - 1;
     120         1862 :   switch(typ(x))
     121              :   {
     122            7 :     case t_VEC: return mkvec2s(1, L);
     123            7 :     case t_COL: return mkvec2s(L, 1);
     124         1841 :     case t_MAT: return mkvec2s(L? nbrows(x): 0, L);
     125              :   }
     126            7 :   pari_err_TYPE("matsize",x);
     127              :   return NULL; /* LCOV_EXCL_LINE */
     128              : }
     129              : 
     130              : /*******************************************************************/
     131              : /*                                                                 */
     132              : /*                 CONVERSION GEN --> long                         */
     133              : /*                                                                 */
     134              : /*******************************************************************/
     135              : 
     136              : long
     137           77 : gtolong(GEN x)
     138              : {
     139           77 :   switch(typ(x))
     140              :   {
     141           42 :     case t_INT:
     142           42 :       return itos(x);
     143            7 :     case t_REAL:
     144            7 :       return (long)(rtodbl(x) + 0.5);
     145            7 :     case t_FRAC:
     146            7 :     { pari_sp av = avma; return gc_long(av, itos(ground(x))); }
     147            7 :     case t_COMPLEX:
     148            7 :       if (gequal0(gel(x,2))) return gtolong(gel(x,1)); break;
     149            7 :     case t_QUAD:
     150            7 :       if (gequal0(gel(x,3))) return gtolong(gel(x,2)); break;
     151              :   }
     152            7 :   pari_err_TYPE("gtolong",x);
     153              :   return 0; /* LCOV_EXCL_LINE */
     154              : }
     155              : 
     156              : /*******************************************************************/
     157              : /*                                                                 */
     158              : /*                         COMPARISONS                             */
     159              : /*                                                                 */
     160              : /*******************************************************************/
     161              : static void
     162          189 : chk_true_err()
     163              : {
     164          189 :   GEN E = pari_err_last();
     165          189 :   switch(err_get_num(E))
     166              :   {
     167            0 :     case e_STACK: case e_MEM: case e_ALARM:
     168            0 :       pari_err(0, E); /* rethrow */
     169              :   }
     170          189 : }
     171              : /* x - y == 0 or undefined */
     172              : static int
     173      3195604 : gequal_try(GEN x, GEN y)
     174              : {
     175              :   int i;
     176      3195604 :   pari_CATCH(CATCH_ALL) { chk_true_err(); return 0; }
     177      3195604 :   pari_TRY { i = gequal0(gadd(x, gneg_i(y))); } pari_ENDCATCH;
     178      3195422 :   return i;
     179              : }
     180              : /* x + y == 0 or undefined */
     181              : static int
     182           28 : gmequal_try(GEN x, GEN y)
     183              : {
     184              :   int i;
     185           28 :   pari_CATCH(CATCH_ALL) { chk_true_err(); return 0; }
     186           28 :   pari_TRY { i = gequal0(gadd(x, y)); } pari_ENDCATCH;
     187           21 :   return i;
     188              : }
     189              : 
     190              : int
     191    582549487 : isexactzero(GEN g)
     192              : {
     193              :   long i, lx;
     194    582549487 :   switch (typ(g))
     195              :   {
     196    476672350 :     case t_INT:
     197    476672350 :       return !signe(g);
     198       981974 :     case t_INTMOD:
     199       981974 :       return !signe(gel(g,2));
     200     15447151 :     case t_COMPLEX:
     201     15447151 :       return isexactzero(gel(g,1)) && isexactzero(gel(g,2));
     202      8111499 :     case t_FFELT:
     203      8111499 :       return FF_equal0(g);
     204          490 :     case t_QUAD:
     205          490 :       return isexactzero(gel(g,2)) && isexactzero(gel(g,3));
     206       305327 :     case t_POLMOD:
     207       305327 :       return isexactzero(gel(g,2));
     208     35578482 :     case t_POL:
     209     35578482 :       lx = lg(g); /* cater for Mod(0,2)*x^0 */
     210     35578482 :       return lx == 2 || (lx == 3 && isexactzero(gel(g,2)));
     211       461276 :     case t_RFRAC:
     212       461276 :       return isexactzero(gel(g,1)); /* may occur: Mod(0,2)/x */
     213        63504 :     case t_VEC: case t_COL: case t_MAT:
     214        63805 :       for (i=lg(g)-1; i; i--)
     215        63700 :         if (!isexactzero(gel(g,i))) return 0;
     216          105 :       return 1;
     217              :   }
     218     44927434 :   return 0;
     219              : }
     220              : GEN
     221     57171801 : gisexactzero(GEN g)
     222              : {
     223              :   long i, lx;
     224              :   GEN a, b;
     225     57171801 :   switch (typ(g))
     226              :   {
     227     24275680 :     case t_INT:
     228     24275680 :       return !signe(g)? g: NULL;
     229      5555830 :     case t_INTMOD:
     230      5555830 :       return !signe(gel(g,2))? g: NULL;
     231         3297 :     case t_COMPLEX:
     232         3297 :       a = gisexactzero(gel(g,1)); if (!a) return NULL;
     233         1281 :       b = gisexactzero(gel(g,2)); if (!b) return NULL;
     234            0 :       return ggcd(a,b);
     235        29309 :     case t_FFELT:
     236        29309 :       return FF_equal0(g)? g: NULL;
     237          581 :     case t_QUAD:
     238          581 :       a = gisexactzero(gel(g,2)); if (!a) return NULL;
     239           77 :       b = gisexactzero(gel(g,3)); if (!b) return NULL;
     240            7 :       return ggcd(a,b);
     241        15744 :     case t_POLMOD:
     242        15744 :       return gisexactzero(gel(g,2));
     243     25495611 :     case t_POL:
     244     25495611 :       lx = lg(g); /* cater for Mod(0,2)*x^0 */
     245     25495611 :       if (lx == 2) return gen_0;
     246     20163604 :       if (lx == 3) return gisexactzero(gel(g,2));
     247     16480922 :       return NULL;
     248      1191287 :     case t_RFRAC:
     249      1191287 :       return gisexactzero(gel(g,1)); /* may occur: Mod(0,2)/x */
     250            0 :     case t_VEC: case t_COL: case t_MAT:
     251            0 :       a = gen_0;
     252            0 :       for (i=lg(g)-1; i; i--)
     253              :       {
     254            0 :         b = gisexactzero(gel(g,i));
     255            0 :         if (!b) return NULL;
     256            0 :         a = ggcd(a, b);
     257              :       }
     258            0 :       return a;
     259              :   }
     260       604462 :   return NULL;
     261              : }
     262              : 
     263              : int
     264    792601127 : isrationalzero(GEN g)
     265              : {
     266              :   long i;
     267    792601127 :   switch (typ(g))
     268              :   {
     269    453361604 :     case t_INT:
     270    453361604 :       return !signe(g);
     271     42405493 :     case t_COMPLEX:
     272     42405493 :       return isintzero(gel(g,1)) && isintzero(gel(g,2));
     273         1435 :     case t_QUAD:
     274         1435 :       return isintzero(gel(g,2)) && isintzero(gel(g,3));
     275       507942 :     case t_POLMOD:
     276       507942 :       return isrationalzero(gel(g,2));
     277    138349720 :     case t_POL: return lg(g) == 2;
     278           91 :     case t_VEC: case t_COL: case t_MAT:
     279          322 :       for (i=lg(g)-1; i; i--)
     280          231 :         if (!isrationalzero(gel(g,i))) return 0;
     281           91 :       return 1;
     282              :   }
     283    157974842 :   return 0;
     284              : }
     285              : 
     286              : int
     287   2539162329 : gequal0(GEN x)
     288              : {
     289   2539162329 :   switch(typ(x))
     290              :   {
     291   2368075147 :     case t_INT: case t_REAL: case t_POL: case t_SER:
     292   2368075147 :       return !signe(x);
     293              : 
     294      7096674 :     case t_INTMOD:
     295      7096674 :       return !signe(gel(x,2));
     296              : 
     297      3100820 :     case t_FFELT:
     298      3100820 :       return FF_equal0(x);
     299              : 
     300    109250531 :     case t_COMPLEX:
     301              :      /* is 0 iff norm(x) would be 0 (can happen with Re(x) and Im(x) != 0
     302              :       * only if Re(x) and Im(x) are of type t_REAL). See mp.c:addrr().
     303              :       */
     304    109250531 :       if (gequal0(gel(x,1)))
     305              :       {
     306      8662854 :         if (gequal0(gel(x,2))) return 1;
     307      8269879 :         if (typ(gel(x,1))!=t_REAL || typ(gel(x,2))!=t_REAL) return 0;
     308       387492 :         return (expo(gel(x,1))>=expo(gel(x,2)));
     309              :       }
     310    100588142 :       if (gequal0(gel(x,2)))
     311              :       {
     312      2640957 :         if (typ(gel(x,1))!=t_REAL || typ(gel(x,2))!=t_REAL) return 0;
     313      2556992 :         return (expo(gel(x,2))>=expo(gel(x,1)));
     314              :       }
     315     97942951 :       return 0;
     316              : 
     317      2046577 :     case t_PADIC:
     318      2046577 :       return !signe(padic_u(x));
     319              : 
     320         1729 :     case t_QUAD:
     321         1729 :       return gequal0(gel(x,2)) && gequal0(gel(x,3));
     322              : 
     323      8556399 :     case t_POLMOD:
     324      8556399 :       return gequal0(gel(x,2));
     325              : 
     326      6113966 :     case t_RFRAC:
     327      6113966 :       return gequal0(gel(x,1));
     328              : 
     329      9908404 :     case t_VEC: case t_COL: case t_MAT:
     330              :     {
     331              :       long i;
     332     23816099 :       for (i=lg(x)-1; i; i--)
     333     19966930 :         if (!gequal0(gel(x,i))) return 0;
     334      3849169 :       return 1;
     335              :     }
     336              :   }
     337     25012082 :   return 0;
     338              : }
     339              : 
     340              : /* x a t_POL or t_SER, return 1 if test(coeff(X,d)) is true and
     341              :  * coeff(X,i) = 0 for all i != d. Return 0 (false) otherwise */
     342              : static int
     343     22631172 : is_monomial_test(GEN x, long d, int(*test)(GEN))
     344              : {
     345     22631172 :   long i, l = lg(x);
     346     22631172 :   if (typ(x) == t_SER)
     347              :   { /* "0" * x^v * (1+O(x)) ?  v <= 0 or null ring */
     348          602 :     if (l == 3 && isexactzero(gel(x,2))) return d >= 2 || test(gel(x,2));
     349          553 :     if (d < 2) return 0; /* v > 0 */
     350              :   }
     351     22630941 :   if (d >= l)
     352              :   {
     353      2302410 :     if (typ(x) == t_POL) return 0; /* l = 2 */
     354              :     /* t_SER, v = 2-d <= 0 */
     355           56 :     if (!signe(x)) return 1;
     356              :   }
     357     20328531 :   else if (!test(gel(x,d))) return 0;
     358      7585351 :   for (i = 2; i < l; i++) /* 2 <= d < l */
     359      5174281 :     if (i != d && !gequal0(gel(x,i))) return 0;
     360      2411070 :   return 1;
     361              : }
     362              : static int
     363       294560 : col_test(GEN x, int(*test)(GEN))
     364              : {
     365       294560 :   long i, l = lg(x);
     366       294560 :   if (l == 1 || !test(gel(x,1))) return 0;
     367        13167 :   for (i = 2; i < l; i++)
     368        11186 :     if (!gequal0(gel(x,i))) return 0;
     369         1981 :   return 1;
     370              : }
     371              : static int
     372        16366 : mat_test(GEN x, int(*test)(GEN))
     373              : {
     374        16366 :   long i, j, l = lg(x);
     375        16366 :   if (l == 1) return 1;
     376        16352 :   if (l != lgcols(x)) return 0;
     377        52283 :   for (i = 1; i < l; i++)
     378       140973 :     for (j = 1; j < l; j++)
     379       105042 :       if (i == j) {
     380        36015 :         if (!test(gcoeff(x,i,i))) return 0;
     381              :       } else {
     382        69027 :         if (!gequal0(gcoeff(x,i,j))) return 0;
     383              :       }
     384        16268 :   return 1;
     385              : }
     386              : 
     387              : /* returns 1 whenever x = 1, and 0 otherwise */
     388              : int
     389    342203250 : gequal1(GEN x)
     390              : {
     391    342203250 :   switch(typ(x))
     392              :   {
     393    315112066 :     case t_INT:
     394    315112066 :       return equali1(x);
     395              : 
     396        82950 :     case t_REAL:
     397              :     {
     398        82950 :       long s = signe(x);
     399        82950 :       if (!s) return expo(x) >= 0;
     400        82320 :       return s > 0 ? absrnz_equal1(x): 0;
     401              :     }
     402       345933 :     case t_INTMOD:
     403       345933 :       return is_pm1(gel(x,2)) || is_pm1(gel(x,1));
     404       382817 :     case t_POLMOD:
     405       382817 :       return !degpol(gel(x,1)) || gequal1(gel(x,2));
     406              : 
     407        17108 :     case t_FFELT:
     408        17108 :       return FF_equal1(x);
     409              : 
     410      1708463 :     case t_FRAC:
     411      1708463 :       return 0;
     412              : 
     413        25681 :     case t_COMPLEX:
     414        25681 :       return gequal1(gel(x,1)) && gequal0(gel(x,2));
     415              : 
     416       166267 :     case t_PADIC:
     417       166267 :       if (!signe(padic_u(x))) return valp(x) <= 0;
     418       166225 :       return valp(x) == 0 && gequal1(padic_u(x));
     419              : 
     420           42 :     case t_QUAD:
     421           42 :       return gequal1(gel(x,2)) && gequal0(gel(x,3));
     422              : 
     423     22630504 :     case t_POL: return is_monomial_test(x, 2, &gequal1);
     424          476 :     case t_SER: return is_monomial_test(x, 2 - valser(x), &gequal1);
     425              : 
     426      1030454 :     case t_RFRAC: return gequal(gel(x,1), gel(x,2));
     427       294511 :     case t_COL: return col_test(x, &gequal1);
     428        16254 :     case t_MAT: return mat_test(x, &gequal1);
     429              :   }
     430       389724 :   return 0;
     431              : }
     432              : 
     433              : /* returns 1 whenever the x = -1, 0 otherwise */
     434              : int
     435     74234551 : gequalm1(GEN x)
     436              : {
     437              :   pari_sp av;
     438              :   GEN t;
     439              : 
     440     74234551 :   switch(typ(x))
     441              :   {
     442     74224594 :     case t_INT:
     443     74224594 :       return equalim1(x);
     444              : 
     445         2016 :     case t_REAL:
     446              :     {
     447         2016 :       long s = signe(x);
     448         2016 :       if (!s) return expo(x) >= 0;
     449         1477 :       return s < 0 ? absrnz_equal1(x): 0;
     450              :     }
     451         4658 :     case t_INTMOD:
     452         4658 :       av = avma; return gc_bool(av, equalii(addui(1,gel(x,2)), gel(x,1)));
     453              : 
     454          154 :     case t_FRAC:
     455          154 :       return 0;
     456              : 
     457           42 :     case t_FFELT:
     458           42 :       return FF_equalm1(x);
     459              : 
     460         2576 :     case t_COMPLEX:
     461         2576 :       return gequalm1(gel(x,1)) && gequal0(gel(x,2));
     462              : 
     463            7 :     case t_QUAD:
     464            7 :       return gequalm1(gel(x,2)) && gequal0(gel(x,3));
     465              : 
     466           49 :     case t_PADIC:
     467           49 :       t = padic_u(x); if (!signe(t)) return valp(x) <= 0;
     468           21 :       av = avma; return gc_bool(av, !valp(x) && equalii(addui(1,t), gel(x,3)));
     469              : 
     470           56 :     case t_POLMOD:
     471           56 :       return !degpol(gel(x,1)) || gequalm1(gel(x,2));
     472              : 
     473           70 :     case t_POL: return is_monomial_test(x, 2, &gequalm1);
     474          126 :     case t_SER: return is_monomial_test(x, 2 - valser(x), &gequalm1);
     475              : 
     476           28 :     case t_RFRAC:
     477           28 :       av = avma; return gc_bool(av, gmequal_try(gel(x,1), gel(x,2)));
     478           49 :     case t_COL: return col_test(x, &gequalm1);
     479          112 :     case t_MAT: return mat_test(x, &gequalm1);
     480              :   }
     481           14 :   return 0;
     482              : }
     483              : 
     484              : int
     485      1494621 : gequalX(GEN x) { return typ(x) == t_POL && lg(x) == 4
     486     10004134 :                       && isintzero(gel(x,2)) && isint1(gel(x,3)); }
     487              : 
     488              : static int
     489      3681020 : cmp_str(const char *x, const char *y)
     490              : {
     491      3681020 :   int f = strcmp(x, y);
     492              :   return f > 0? 1
     493      3681020 :               : f? -1: 0;
     494              : }
     495              : 
     496              : static int
     497     39285081 : cmp_universal_rec(GEN x, GEN y, long i0)
     498              : {
     499     39285081 :   long i, lx = lg(x), ly = lg(y);
     500     39285081 :   if (lx < ly) return -1;
     501     39282117 :   if (lx > ly) return 1;
     502     69618339 :   for (i = i0; i < lx; i++)
     503              :   {
     504     60673667 :     int f = cmp_universal(gel(x,i), gel(y,i));
     505     60673667 :     if (f) return f;
     506              :   }
     507      8944672 :   return 0;
     508              : }
     509              : /* Universal "meaningless" comparison function. Transitive, returns 0 iff
     510              :  * gidentical(x,y) */
     511              : int
     512     89010505 : cmp_universal(GEN x, GEN y)
     513              : {
     514     89010505 :   long lx, ly, i, tx = typ(x), ty = typ(y);
     515              : 
     516     89010505 :   if (tx < ty) return -1;
     517     88632076 :   if (ty < tx) return 1;
     518     88095303 :   switch(tx)
     519              :   {
     520     44193187 :     case t_INT: return cmpii(x,y);
     521      3680999 :     case t_STR: return cmp_str(GSTR(x),GSTR(y));
     522       935956 :     case t_REAL:
     523              :     case t_VECSMALL:
     524       935956 :       lx = lg(x);
     525       935956 :       ly = lg(y);
     526       935956 :       if (lx < ly) return -1;
     527       887684 :       if (lx > ly) return 1;
     528      3590341 :       for (i = 1; i < lx; i++)
     529              :       {
     530      3481904 :         if (x[i] < y[i]) return -1;
     531      3112823 :         if (x[i] > y[i]) return 1;
     532              :       }
     533       108437 :       return 0;
     534              : 
     535       771423 :     case t_POL:
     536              :     {
     537       771423 :       long X = x[1] & (VARNBITS|SIGNBITS);
     538       771423 :       long Y = y[1] & (VARNBITS|SIGNBITS);
     539       771423 :       if (X < Y) return -1;
     540       771402 :       if (X > Y) return 1;
     541       771353 :       return cmp_universal_rec(x, y, 2);
     542              :     }
     543       881076 :     case t_SER:
     544              :     case t_FFELT:
     545              :     case t_CLOSURE:
     546       881076 :       if (x[1] < y[1]) return -1;
     547       881069 :       if (x[1] > y[1]) return 1;
     548       881062 :       return cmp_universal_rec(x, y, 2);
     549              : 
     550           35 :     case t_LIST:
     551              :       {
     552           35 :         long tx = list_typ(x), ty = list_typ(y);
     553              :         GEN vx, vy;
     554              :         pari_sp av;
     555           35 :         if (tx < ty) return -1;
     556           35 :         if (tx > ty) return 1;
     557           35 :         vx = list_data(x);
     558           35 :         vy = list_data(y);
     559           35 :         if (!vx) return vy? -1: 0;
     560           35 :         if (!vy) return 1;
     561           35 :         av = avma;
     562           35 :         if (tx == t_LIST_MAP)
     563              :         {
     564           14 :           vx = maptomat_shallow(x);
     565           14 :           vy = maptomat_shallow(y);
     566              :         }
     567           35 :         return gc_int(av, cmp_universal_rec(vx, vy, 1));
     568              :       }
     569     37632627 :     default:
     570     37632627 :       return cmp_universal_rec(x, y, lontyp[tx]);
     571              :   }
     572              : }
     573              : 
     574              : static int
     575      4595760 : cmpfrac(GEN x, GEN y)
     576              : {
     577      4595760 :   pari_sp av = avma;
     578      4595760 :   GEN a = gel(x,1), b = gel(x,2);
     579      4595760 :   GEN c = gel(y,1), d = gel(y,2);
     580      4595760 :   return gc_bool(av, cmpii(mulii(a, d), mulii(b, c)));
     581              : }
     582              : static int
     583       455849 : cmpifrac(GEN a, GEN y)
     584              : {
     585       455849 :   pari_sp av = avma;
     586       455849 :   GEN c = gel(y,1), d = gel(y,2);
     587       455849 :   return gc_int(av, cmpii(mulii(a, d), c));
     588              : }
     589              : static int
     590        81756 : cmprfrac(GEN a, GEN y)
     591              : {
     592        81756 :   pari_sp av = avma;
     593        81756 :   GEN c = gel(y,1), d = gel(y,2);
     594        81756 :   return gc_int(av, cmpri(mulri(a, d), c));
     595              : }
     596              : static int
     597          224 : cmpgen(GEN x, GEN y)
     598              : {
     599          224 :   pari_sp av = avma;
     600          224 :   return gc_int(av, gsigne(gsub(x,y)));
     601              : }
     602              : 
     603              : /* returns the sign of x - y when it makes sense. 0 otherwise */
     604              : int
     605    255146150 : gcmp(GEN x, GEN y)
     606              : {
     607    255146150 :   long tx = typ(x), ty = typ(y);
     608              : 
     609    255146150 :   if (tx == ty) /* generic case */
     610    252936425 :     switch(tx)
     611              :     {
     612    134143498 :       case t_INT:  return cmpii(x, y);
     613    114101128 :       case t_REAL: return cmprr(x, y);
     614      4595760 :       case t_FRAC: return cmpfrac(x, y);
     615           70 :       case t_QUAD: return cmpgen(x, y);
     616           21 :       case t_STR:  return cmp_str(GSTR(x), GSTR(y));
     617       107755 :       case t_INFINITY:
     618              :       {
     619       107755 :         long sx = inf_get_sign(x), sy = inf_get_sign(y);
     620       107755 :         if (sx < sy) return -1;
     621           42 :         if (sx > sy) return 1;
     622           14 :         return 0;
     623              :       }
     624              :     }
     625      2197918 :   if (ty == t_INFINITY) return -inf_get_sign(y);
     626       998347 :   switch(tx)
     627              :   {
     628       557269 :     case t_INT:
     629       557269 :       switch(ty)
     630              :       {
     631       244326 :         case t_REAL: return cmpir(x, y);
     632       312929 :         case t_FRAC: return cmpifrac(x, y);
     633            7 :         case t_QUAD: return cmpgen(x, y);
     634              :       }
     635            7 :       break;
     636       236515 :     case t_REAL:
     637       236515 :       switch(ty)
     638              :       {
     639       199199 :         case t_INT:  return cmpri(x, y);
     640        37295 :         case t_FRAC: return cmprfrac(x, y);
     641           14 :         case t_QUAD: return cmpgen(x, y);
     642              :       }
     643            7 :       break;
     644       187395 :     case t_FRAC:
     645       187395 :       switch(ty)
     646              :       {
     647       142920 :         case t_INT:  return -cmpifrac(y, x);
     648        44461 :         case t_REAL: return -cmprfrac(y, x);
     649            7 :         case t_QUAD: return cmpgen(x, y);
     650              :       }
     651            7 :       break;
     652          126 :     case t_QUAD:
     653          126 :       return cmpgen(x, y);
     654        31660 :     case t_INFINITY: return inf_get_sign(x);
     655              :   }
     656           24 :   pari_err_TYPE2("comparison",x,y);
     657              :   return 0;/*LCOV_EXCL_LINE*/
     658              : }
     659              : 
     660              : int
     661       762253 : gcmpsg(long s, GEN y)
     662              : {
     663       762253 :   switch(typ(y))
     664              :   {
     665        12453 :     case t_INT:  return cmpsi(s,y);
     666       744606 :     case t_REAL: return cmpsr(s,y);
     667         5194 :     case t_FRAC: {
     668         5194 :       pari_sp av = avma;
     669         5194 :       return gc_int(av, cmpii(mulsi(s,gel(y,2)), gel(y,1)));
     670              :     }
     671            0 :     case t_QUAD: {
     672            0 :       pari_sp av = avma;
     673            0 :       return gc_int(av, gsigne(gsubsg(s, y)));
     674              :     }
     675            0 :     case t_INFINITY: return -inf_get_sign(y);
     676              :   }
     677            0 :   pari_err_TYPE2("comparison",stoi(s),y);
     678              :   return 0; /* LCOV_EXCL_LINE */
     679              : }
     680              : 
     681              : static long
     682      3257661 : roughtype(GEN x)
     683              : {
     684      3257661 :   switch(typ(x))
     685              :   {
     686         2114 :     case t_MAT: return t_MAT;
     687       742744 :     case t_VEC: case t_COL: return t_VEC;
     688      1634764 :     case t_VECSMALL: return t_VECSMALL;
     689       878039 :     default: return t_INT;
     690              :   }
     691              : }
     692              : 
     693              : static int lexcmpsg(long x, GEN y);
     694              : static int
     695           42 : lexcmpgs(GEN x, long y) { return -lexcmpsg(y,x); }
     696              : /* lexcmp(stoi(x),y), y t_VEC/t_COL/t_MAT */
     697              : static int
     698           21 : lexcmp_s_matvec(long x, GEN y)
     699              : {
     700              :   int fl;
     701           21 :   if (lg(y)==1) return 1;
     702           14 :   fl = lexcmpsg(x,gel(y,1));
     703           14 :   if (fl) return fl;
     704            7 :   return -1;
     705              : }
     706              : /* x a scalar, y a t_VEC/t_COL/t_MAT */
     707              : static int
     708          357 : lexcmp_scal_matvec(GEN x, GEN y)
     709              : {
     710              :   int fl;
     711          357 :   if (lg(y)==1) return 1;
     712          357 :   fl = lexcmp(x,gel(y,1));
     713          357 :   if (fl) return fl;
     714            7 :   return -1;
     715              : }
     716              : /* x a scalar, y a t_VECSMALL */
     717              : static int
     718           42 : lexcmp_scal_vecsmall(GEN x, GEN y)
     719              : {
     720              :   int fl;
     721           42 :   if (lg(y)==1) return 1;
     722           42 :   fl = lexcmpgs(x, y[1]);
     723           42 :   if (fl) return fl;
     724            0 :   return -1;
     725              : }
     726              : 
     727              : /* tx = ty = t_MAT, or x and y are both vect_t */
     728              : static int
     729       372163 : lexcmp_similar(GEN x, GEN y)
     730              : {
     731       372163 :   long i, lx = lg(x), ly = lg(y), l = minss(lx,ly);
     732       457180 :   for (i=1; i<l; i++)
     733              :   {
     734       425540 :     int fl = lexcmp(gel(x,i),gel(y,i));
     735       425540 :     if (fl) return fl;
     736              :   }
     737        31640 :   if (lx == ly) return 0;
     738           35 :   return (lx < ly)? -1 : 1;
     739              : }
     740              : /* x a t_VECSMALL, y a t_VEC/t_COL ~ lexcmp_similar */
     741              : static int
     742          154 : lexcmp_vecsmall_vec(GEN x, GEN y)
     743              : {
     744          154 :   long i, lx = lg(x), ly = lg(y), l = minss(lx,ly);
     745          343 :   for (i=1; i<l; i++)
     746              :   {
     747          287 :     int fl = lexcmpsg(x[i], gel(y,i));
     748          287 :     if (fl) return fl;
     749              :   }
     750           56 :   if (lx == ly) return 0;
     751           21 :   return (lx < ly)? -1 : 1;
     752              : }
     753              : 
     754              : /* x t_VEC/t_COL, y t_MAT */
     755              : static int
     756           98 : lexcmp_vec_mat(GEN x, GEN y)
     757              : {
     758              :   int fl;
     759           98 :   if (lg(x)==1) return -1;
     760           98 :   if (lg(y)==1) return 1;
     761           98 :   fl = lexcmp_similar(x,gel(y,1));
     762           98 :   if (fl) return fl;
     763            7 :   return -1;
     764              : }
     765              : /* x t_VECSMALl, y t_MAT ~ lexcmp_vec_mat */
     766              : static int
     767           42 : lexcmp_vecsmall_mat(GEN x, GEN y)
     768              : {
     769              :   int fl;
     770           42 :   if (lg(x)==1) return -1;
     771           42 :   if (lg(y)==1) return 1;
     772           42 :   fl = lexcmp_vecsmall_vec(x, gel(y,1));
     773           42 :   if (fl) return fl;
     774            0 :   return -1;
     775              : }
     776              : 
     777              : /* x a t_VECSMALL, not y */
     778              : static int
     779          196 : lexcmp_vecsmall_other(GEN x, GEN y, long ty)
     780              : {
     781          196 :   switch(ty)
     782              :   {
     783           42 :     case t_MAT: return lexcmp_vecsmall_mat(x, y);
     784          112 :     case t_VEC: return lexcmp_vecsmall_vec(x, y);
     785           42 :     default: return -lexcmp_scal_vecsmall(y, x); /*y scalar*/
     786              :   }
     787              : }
     788              : 
     789              : /* lexcmp(stoi(s), y) */
     790              : static int
     791          343 : lexcmpsg(long x, GEN y)
     792              : {
     793          343 :   switch(roughtype(y))
     794              :   {
     795           21 :     case t_MAT:
     796              :     case t_VEC:
     797           21 :       return lexcmp_s_matvec(x,y);
     798           14 :     case t_VECSMALL: /* ~ lexcmp_scal_matvec */
     799           14 :       if (lg(y)==1) return 1;
     800            7 :       return (x > y[1])? 1: -1;
     801          308 :     default: return gcmpsg(x,y);
     802              :   }
     803              : }
     804              : 
     805              : /* as gcmp for vector/matrices, using lexicographic ordering on components */
     806              : static int
     807      1628659 : lexcmp_i(GEN x, GEN y)
     808              : {
     809      1628659 :   const long tx = roughtype(x), ty = roughtype(y);
     810      1628659 :   if (tx == ty)
     811      1628008 :     switch(tx)
     812              :     {
     813       372065 :       case t_MAT:
     814       372065 :       case t_VEC: return lexcmp_similar(x,y);
     815       817277 :       case t_VECSMALL: return vecsmall_lexcmp(x,y);
     816       438666 :       default: return gcmp(x,y);
     817              :     }
     818          651 :   if (tx == t_VECSMALL) return  lexcmp_vecsmall_other(x,y,ty);
     819          518 :   if (ty == t_VECSMALL) return -lexcmp_vecsmall_other(y,x,tx);
     820              : 
     821          455 :   if (tx == t_INT) return  lexcmp_scal_matvec(x,y); /*scalar*/
     822          203 :   if (ty == t_INT) return -lexcmp_scal_matvec(y,x);
     823              : 
     824           98 :   if (ty==t_MAT) return  lexcmp_vec_mat(x,y);
     825           42 :   return -lexcmp_vec_mat(y,x); /*tx==t_MAT*/
     826              : }
     827              : int
     828      1628659 : lexcmp(GEN x, GEN y)
     829              : {
     830      1628659 :   pari_sp av = avma;
     831      1628659 :   if (typ(x) == t_COMPLEX)
     832              :   {
     833         1001 :     x = mkvec2(gel(x,1), gel(x,2));
     834         1001 :     if (typ(y) == t_COMPLEX) y = mkvec2(gel(y,1), gel(y,2));
     835           49 :     else y = mkvec2(y, gen_0);
     836              :   }
     837      1627658 :   else if (typ(y) == t_COMPLEX)
     838              :   {
     839           63 :     x = mkvec2(x, gen_0);
     840           63 :     y = mkvec2(gel(y,1), gel(y,2));
     841              :   }
     842      1628659 :   return gc_int(av, lexcmp_i(x, y));
     843              : }
     844              : 
     845              : /*****************************************************************/
     846              : /*                                                               */
     847              : /*                          EQUALITY                             */
     848              : /*                returns 1 if x == y, 0 otherwise               */
     849              : /*                                                               */
     850              : /*****************************************************************/
     851              : /* x,y t_POL */
     852              : static int
     853      5634065 : polidentical(GEN x, GEN y)
     854              : {
     855              :   long lx;
     856      5634065 :   if (x[1] != y[1]) return 0;
     857      5633967 :   lx = lg(x); if (lg(y) != lg(x)) return 0;
     858     37916365 :   for (lx--; lx >= 2; lx--) if (!gidentical(gel(x,lx), gel(y,lx))) return 0;
     859      5633470 :   return 1;
     860              : }
     861              : /* x,y t_SER */
     862              : static int
     863           14 : seridentical(GEN x, GEN y) { return polidentical(x,y); }
     864              : /* typ(x) = typ(y) = t_VEC/COL/MAT */
     865              : static int
     866      5440823 : vecidentical(GEN x, GEN y)
     867              : {
     868              :   long i;
     869      5440823 :   if ((x[0] ^ y[0]) & (TYPBITS|LGBITS)) return 0;
     870     17252990 :   for (i = lg(x)-1; i; i--)
     871     13123267 :     if (! gidentical(gel(x,i),gel(y,i)) ) return 0;
     872      4129723 :   return 1;
     873              : }
     874              : static int
     875         1547 : identicalrr(GEN x, GEN y)
     876              : {
     877         1547 :   long i, lx = lg(x);
     878         1547 :   if (lg(y) != lx) return 0;
     879         1547 :   if (x[1] != y[1]) return 0;
     880         5465 :   i=2; while (i<lx && x[i]==y[i]) i++;
     881         1540 :   return (i == lx);
     882              : }
     883              : 
     884              : static int
     885           70 : closure_identical(GEN x, GEN y)
     886              : {
     887           70 :   if (lg(x)!=lg(y) || x[1]!=y[1]) return 0;
     888           56 :   if (!gidentical(gel(x,2),gel(y,2)) || !gidentical(gel(x,3),gel(y,3))
     889           56 :    || !gidentical(gel(x,4),gel(y,4))) return 0;
     890           42 :   if (lg(x)<8) return 1;
     891            0 :   return gidentical(gel(x,7),gel(y,7));
     892              : }
     893              : 
     894              : static int
     895          343 : list_cmp(GEN x, GEN y, int cmp(GEN x, GEN y))
     896              : {
     897          343 :   int t = list_typ(x);
     898              :   GEN vx, vy;
     899              :   long lvx, lvy;
     900          343 :   if (list_typ(y)!=t) return 0;
     901          343 :   vx = list_data(x);
     902          343 :   vy = list_data(y);
     903          343 :   lvx = vx ? lg(vx): 1;
     904          343 :   lvy = vy ? lg(vy): 1;
     905          343 :   if (lvx==1 && lvy==1) return 1;
     906          329 :   if (lvx != lvy) return 0;
     907          301 :   switch (t)
     908              :   {
     909          280 :   case t_LIST_MAP:
     910              :     {
     911          280 :       pari_sp av = avma;
     912          280 :       GEN mx  = maptomat_shallow(x), my = maptomat_shallow(y);
     913          280 :       int ret = gidentical(gel(mx, 1), gel(my, 1)) && cmp(gel(mx, 2), gel(my, 2));
     914          280 :       return gc_bool(av, ret);
     915              :     }
     916           21 :   default:
     917           21 :     return cmp(vx, vy);
     918              :   }
     919              : }
     920              : 
     921              : int
     922    123902947 : gidentical(GEN x, GEN y)
     923              : {
     924              :   long tx;
     925              : 
     926    123902947 :   if (x == y) return 1;
     927    118396676 :   tx = typ(x); if (typ(y) != tx) return 0;
     928    118161032 :   switch(tx)
     929              :   {
     930     39945954 :     case t_INT:
     931     39945954 :       return equalii(x,y);
     932              : 
     933         1547 :     case t_REAL:
     934         1547 :       return identicalrr(x,y);
     935              : 
     936       426602 :     case t_FRAC: case t_INTMOD:
     937       426602 :       return equalii(gel(x,2), gel(y,2)) && equalii(gel(x,1), gel(y,1));
     938              : 
     939          343 :     case t_COMPLEX:
     940          343 :       return gidentical(gel(x,2),gel(y,2)) && gidentical(gel(x,1),gel(y,1));
     941           21 :     case t_PADIC:
     942           21 :       return valp(x) == valp(y) && precp(x) == precp(y)
     943           14 :         && equalii(padic_p(x), padic_p(y))
     944           42 :         && equalii(padic_u(x), padic_u(y));
     945         3892 :     case t_POLMOD:
     946         3892 :       return gidentical(gel(x,2),gel(y,2)) && polidentical(gel(x,1),gel(y,1));
     947      5634030 :     case t_POL:
     948      5634030 :       return polidentical(x,y);
     949           14 :     case t_SER:
     950           14 :       return seridentical(x,y);
     951         5320 :     case t_FFELT:
     952         5320 :       return FF_equal(x,y);
     953              : 
     954       423760 :     case t_QFB:
     955       423760 :       return equalii(gel(x,1),gel(y,1))
     956       423753 :           && equalii(gel(x,2),gel(y,2))
     957       847513 :           && equalii(gel(x,3),gel(y,3));
     958              : 
     959           14 :     case t_QUAD:
     960           14 :       return ZX_equal(gel(x,1),gel(y,1))
     961            7 :           && gidentical(gel(x,2),gel(y,2))
     962           21 :           && gidentical(gel(x,3),gel(y,3));
     963              : 
     964            7 :     case t_RFRAC:
     965            7 :       return gidentical(gel(x,1),gel(y,1)) && gidentical(gel(x,2),gel(y,2));
     966              : 
     967           70 :     case t_STR:
     968           70 :       return !strcmp(GSTR(x),GSTR(y));
     969      5440823 :     case t_VEC: case t_COL: case t_MAT:
     970      5440823 :       return vecidentical(x,y);
     971     66278425 :     case t_VECSMALL:
     972     66278425 :       return zv_equal(x,y);
     973           28 :     case t_CLOSURE:
     974           28 :       return closure_identical(x,y);
     975          161 :     case t_LIST:
     976          161 :       return list_cmp(x, y, gidentical);
     977           21 :     case t_INFINITY: return gidentical(gel(x,1),gel(y,1));
     978              :   }
     979            0 :   return 0;
     980              : }
     981              : /* x,y t_POL in the same variable */
     982              : static int
     983     12918175 : polequal(GEN x, GEN y)
     984              : {
     985              :   long lx, ly;
     986              :   /* Can't do that: Mod(0,1)*x^0 == x^0
     987              :   if (signe(x) != signe(y)) return 0; */
     988     12918175 :   lx = lg(x); ly = lg(y);
     989     12918175 :   while (lx > ly) if (!gequal0(gel(x,--lx))) return 0;
     990     12915690 :   while (ly > lx) if (!gequal0(gel(y,--ly))) return 0;
     991     45045044 :   for (lx--; lx >= 2; lx--) if (!gequal(gel(x,lx), gel(y,lx))) return 0;
     992     12844402 :   return 1;
     993              : }
     994              : 
     995              : /* x,y t_SER in the same variable */
     996              : static int
     997          420 : serequal(GEN x, GEN y)
     998              : {
     999              :   long LX, LY, lx, ly, vx, vy;
    1000          420 :   if (!signe(x) && !signe(y)) return 1;
    1001           56 :   lx = lg(x); vx = valser(x); LX = lx + vx;
    1002           56 :   ly = lg(y); vy = valser(y); LY = ly + vy;
    1003           56 :   if (LX > LY) lx = LY - vx; else ly = LX - vy;
    1004       282877 :   while (lx >= 3 && ly >= 3)
    1005       282821 :     if (!gequal(gel(x,--lx), gel(y,--ly))) return 0;
    1006           56 :   while(--ly >= 2) if (!gequal0(gel(y,ly))) return 0;
    1007           84 :   while(--lx >= 2) if (!gequal0(gel(x,lx))) return 0;
    1008           49 :   return 1;
    1009              : }
    1010              : 
    1011              : /* typ(x) = typ(y) = t_VEC/COL/MAT */
    1012              : static int
    1013      5577413 : vecequal(GEN x, GEN y)
    1014              : {
    1015              :   long i;
    1016      5577413 :   if ((x[0] ^ y[0]) & (TYPBITS|LGBITS)) return 0;
    1017     18606609 :   for (i = lg(x)-1; i; i--)
    1018     16242572 :     if (! gequal(gel(x,i),gel(y,i)) ) return 0;
    1019      2364037 :   return 1;
    1020              : }
    1021              : 
    1022              : int
    1023    244359624 : gequal(GEN x, GEN y)
    1024              : {
    1025              :   pari_sp av;
    1026              :   GEN A, B, a, b;
    1027              :   long tx, ty;
    1028              : 
    1029    244359624 :   if (x == y) return 1;
    1030    210320752 :   tx = typ(x); ty = typ(y);
    1031    210320752 :   if (tx == ty)
    1032    202489305 :     switch(tx)
    1033              :     {
    1034    172055605 :       case t_INT:
    1035    172055605 :         return equalii(x,y);
    1036              : 
    1037        20488 :       case t_REAL:
    1038        20488 :         return equalrr(x,y);
    1039              : 
    1040       299284 :       case t_FRAC:
    1041       299284 :         return equalii(gel(x,2), gel(y,2)) && equalii(gel(x,1), gel(y,1));
    1042              : 
    1043      6510007 :       case t_INTMOD:
    1044      6510007 :         A = gel(x,1); B = gel(y,1);
    1045      6510007 :         a = gel(x,2); b = gel(y,2);
    1046      6510007 :         if (equalii(A, B)) return equalii(a, b);
    1047           14 :         av = avma; A = gcdii(A, B);
    1048           14 :         return gc_bool(av, equalii(modii(a,A), modii(b,A)));
    1049              : 
    1050         1316 :       case t_COMPLEX:
    1051         1316 :         return gequal(gel(x,2),gel(y,2)) && gequal(gel(x,1),gel(y,1));
    1052          770 :       case t_PADIC:
    1053          770 :         if (!equalii(padic_p(x), padic_p(y))) return 0;
    1054          770 :         av = avma; return gc_bool(av, gequal0(gsub(x,y)));
    1055              : 
    1056      3189703 :       case t_POLMOD:
    1057      3189703 :         A = gel(x,1); B = gel(y,1);
    1058      3189703 :         if (varn(A) != varn(B)) break;
    1059      3189682 :         a = gel(x,2); b = gel(y,2);
    1060      3189682 :         if (RgX_equal_var(A, B)) return gequal(a,b);
    1061           14 :         av = avma; A = ggcd(A, B);
    1062           14 :         return gc_bool(av, gequal(gmod(a,A), gmod(b,A)));
    1063              : 
    1064     12930328 :       case t_POL:
    1065     12930328 :         if (varn(x) != varn(y)) break;
    1066     12918176 :         return polequal(x,y);
    1067          420 :       case t_SER:
    1068          420 :         if (varn(x) != varn(y)) break;
    1069          420 :         return serequal(x,y);
    1070              : 
    1071       250713 :       case t_FFELT:
    1072       250713 :         return FF_equal(x,y);
    1073              : 
    1074        91513 :       case t_QFB:
    1075        91513 :         return equalii(gel(x,1),gel(y,1))
    1076        72986 :             && equalii(gel(x,2),gel(y,2))
    1077       164499 :             && equalii(gel(x,3),gel(y,3));
    1078              : 
    1079           84 :       case t_QUAD:
    1080           84 :         return ZX_equal(gel(x,1),gel(y,1))
    1081           77 :             && gequal(gel(x,2),gel(y,2))
    1082          161 :             && gequal(gel(x,3),gel(y,3));
    1083              : 
    1084        73759 :       case t_RFRAC:
    1085              :       {
    1086        73759 :         GEN a = gel(x,1), b = gel(x,2), c = gel(y,1), d = gel(y,2);
    1087        73759 :         if (gequal(b,d)) return gequal(a,c); /* simple case */
    1088            0 :         av = avma;
    1089            0 :         a = simplify_shallow(gmul(a,d));
    1090            0 :         b = simplify_shallow(gmul(b,c));
    1091            0 :         return gc_bool(av, gequal(a,b));
    1092              :       }
    1093              : 
    1094        65814 :       case t_STR:
    1095        65814 :         return !strcmp(GSTR(x),GSTR(y));
    1096      5577413 :       case t_VEC: case t_COL: case t_MAT:
    1097      5577413 :         return vecequal(x,y);
    1098      1421844 :       case t_VECSMALL:
    1099      1421844 :         return zv_equal(x,y);
    1100          182 :       case t_LIST:
    1101          182 :         return list_cmp(x, y, gequal);
    1102           42 :       case t_CLOSURE:
    1103           42 :         return closure_identical(x,y);
    1104           28 :       case t_INFINITY:
    1105           28 :         return gequal(gel(x,1),gel(y,1));
    1106              :     }
    1107      7843612 :   if (is_noncalc_t(tx) || is_noncalc_t(ty)) return 0;
    1108      7843720 :   if (tx == t_INT && !signe(x)) return gequal0(y);
    1109      7800869 :   if (ty == t_INT && !signe(y)) return gequal0(x);
    1110      3195604 :   (void)&av; av = avma; /* emulate volatile */
    1111      3195604 :   return gc_bool(av, gequal_try(x, y));
    1112              : }
    1113              : 
    1114              : int
    1115        44058 : gequalsg(long s, GEN x)
    1116        44058 : { pari_sp av = avma; return gc_bool(av, gequal(stoi(s), x)); }
    1117              : 
    1118              : /* a and b are t_INT, t_FRAC, t_REAL or t_COMPLEX of those. Check whether
    1119              :  * a-b is invertible */
    1120              : int
    1121      2499437 : cx_approx_equal(GEN a, GEN b)
    1122              : {
    1123      2499437 :   pari_sp av = avma;
    1124              :   GEN d;
    1125      2499437 :   if (a == b) return 1;
    1126       639128 :   d = gsub(a,b);
    1127       639128 :   return gc_bool(av, gequal0(d) || (typ(d)==t_COMPLEX && gequal0(cxnorm(d))));
    1128              : }
    1129              : static int
    1130      1808928 : r_approx0(GEN x, long e) { return e - expo(x) > bit_prec(x); }
    1131              : /* x ~ 0 compared to reference y */
    1132              : int
    1133      2507016 : cx_approx0(GEN x, GEN y)
    1134              : {
    1135              :   GEN a, b;
    1136              :   long e;
    1137      2507016 :   switch(typ(x))
    1138              :   {
    1139          511 :     case t_COMPLEX:
    1140          511 :       a = gel(x,1); b = gel(x,2);
    1141          511 :       if (typ(a) != t_REAL)
    1142              :       {
    1143           14 :         if (!gequal0(a)) return 0;
    1144            0 :         a = NULL;
    1145              :       }
    1146          497 :       else if (!signe(a)) a = NULL;
    1147          497 :       if (typ(b) != t_REAL)
    1148              :       {
    1149            0 :         if (!gequal0(b)) return 0;
    1150            0 :         if (!a) return 1;
    1151            0 :         b = NULL;
    1152              :       }
    1153          497 :       else if (!signe(b))
    1154              :       {
    1155           28 :         if (!a) return 1;
    1156            7 :         b = NULL;
    1157              :       }
    1158              :       /* a or b is != NULL iff it is non-zero t_REAL; one of them is */
    1159          476 :       e = gexpo(y);
    1160          476 :       return (!a || r_approx0(a, e)) && (!b || r_approx0(b, e));
    1161      1808640 :     case t_REAL:
    1162      1808640 :       return !signe(x) || r_approx0(x, gexpo(y));
    1163       697865 :     default:
    1164       697865 :       return gequal0(x);
    1165              :   }
    1166              : }
    1167              : /*******************************************************************/
    1168              : /*                                                                 */
    1169              : /*                          VALUATION                              */
    1170              : /*             p is either a t_INT or a t_POL.                     */
    1171              : /*  returns the largest exponent of p dividing x when this makes   */
    1172              : /*  sense : error for types real, integermod and polymod if p does */
    1173              : /*  not divide the modulus, q-adic if q!=p.                        */
    1174              : /*                                                                 */
    1175              : /*******************************************************************/
    1176              : 
    1177              : static long
    1178       137186 : minval(GEN x, GEN p)
    1179              : {
    1180       137186 :   long i,k, val = LONG_MAX, lx = lg(x);
    1181       376943 :   for (i=lontyp[typ(x)]; i<lx; i++)
    1182              :   {
    1183       239757 :     k = gvaluation(gel(x,i),p);
    1184       239757 :     if (k < val) val = k;
    1185              :   }
    1186       137186 :   return val;
    1187              : }
    1188              : 
    1189              : static int
    1190           91 : intdvd(GEN x, GEN y, GEN *z) { GEN r; *z = dvmdii(x,y,&r); return (r==gen_0); }
    1191              : 
    1192              : /* x t_FRAC, p t_INT, return v_p(x) */
    1193              : static long
    1194       292596 : frac_val(GEN x, GEN p) {
    1195       292596 :   long v = Z_pval(gel(x,2),p);
    1196       292596 :   if (v) return -v;
    1197       292454 :   return Z_pval(gel(x,1),p);
    1198              : }
    1199              : long
    1200      9427422 : Q_pval(GEN x, GEN p)
    1201              : {
    1202      9427422 :   if (lgefint(p) == 3) return Q_lval(x, uel(p,2));
    1203          524 :   return (typ(x)==t_INT)? Z_pval(x, p): frac_val(x, p);
    1204              : }
    1205              : 
    1206              : static long
    1207       381836 : frac_lval(GEN x, ulong p) {
    1208       381836 :   long v = Z_lval(gel(x,2),p);
    1209       381836 :   if (v) return -v;
    1210       232156 :   return Z_lval(gel(x,1),p);
    1211              : }
    1212              : long
    1213      9431647 : Q_lval(GEN x, ulong p){return (typ(x)==t_INT)? Z_lval(x, p): frac_lval(x, p);}
    1214              : 
    1215              : long
    1216      6304453 : Q_pvalrem(GEN x, GEN p, GEN *y)
    1217              : {
    1218              :   GEN a, b;
    1219              :   long v;
    1220      6304453 :   if (lgefint(p) == 3) return Q_lvalrem(x, uel(p,2), y);
    1221         5806 :   if (typ(x) == t_INT) return Z_pvalrem(x, p, y);
    1222            0 :   a = gel(x,1);
    1223            0 :   b = gel(x,2);
    1224            0 :   v = Z_pvalrem(b, p, &b);
    1225            0 :   if (v) { *y = isint1(b)? a: mkfrac(a, b); return -v; }
    1226            0 :   v = Z_pvalrem(a, p, &a);
    1227            0 :   *y = mkfrac(a, b); return v;
    1228              : }
    1229              : long
    1230      6302861 : Q_lvalrem(GEN x, ulong p, GEN *y)
    1231              : {
    1232              :   GEN a, b;
    1233              :   long v;
    1234      6302861 :   if (typ(x) == t_INT) return Z_lvalrem(x, p, y);
    1235       398420 :   a = gel(x,1);
    1236       398420 :   b = gel(x,2);
    1237       398420 :   v = Z_lvalrem(b, p, &b);
    1238       398420 :   if (v) { *y = isint1(b)? a: mkfrac(a, b); return -v; }
    1239       228917 :   v = Z_lvalrem(a, p, &a);
    1240       228917 :   *y = mkfrac(a, b); return v;
    1241              : }
    1242              : 
    1243              : long
    1244      1401625 : gvaluation(GEN x, GEN p)
    1245              : {
    1246      1401625 :   long tx = typ(x), tp;
    1247              :   pari_sp av;
    1248              : 
    1249      1401625 :   if (!p)
    1250           28 :     switch(tx)
    1251              :     {
    1252            7 :       case t_PADIC: return valp(x);
    1253            7 :       case t_POL: return RgX_val(x);
    1254            7 :       case t_SER: return valser(x);
    1255            7 :       default: pari_err_TYPE("gvaluation", x);
    1256              :     }
    1257      1401597 :   tp  = typ(p);
    1258      1401597 :   switch(tp)
    1259              :   {
    1260      1341698 :     case t_INT:
    1261      1341698 :       if (signe(p) && !is_pm1(p)) break;
    1262           28 :       pari_err_DOMAIN("gvaluation", "p", "=", p, p);
    1263        59892 :     case t_POL:
    1264        59892 :       if (degpol(p) > 0) break;
    1265              :     default:
    1266            7 :       pari_err_DOMAIN("gvaluation", "p", "=", p, p);
    1267              :   }
    1268              : 
    1269      1401562 :   switch(tx)
    1270              :   {
    1271       224941 :     case t_INT:
    1272       224941 :       if (!signe(x)) return LONG_MAX;
    1273       160758 :       if (tp == t_POL) return 0;
    1274       160142 :       return Z_pval(x,p);
    1275              : 
    1276           49 :     case t_REAL:
    1277           49 :       if (tp == t_POL) return 0;
    1278           21 :       break;
    1279              : 
    1280           28 :     case t_FFELT:
    1281           28 :       if (tp == t_POL) return FF_equal0(x)? LONG_MAX: 0;
    1282           14 :       break;
    1283              : 
    1284          105 :     case t_INTMOD: {
    1285          105 :       GEN a = gel(x,1), b = gel(x,2);
    1286              :       long val;
    1287          133 :       if (tp == t_POL) return signe(b)? 0: LONG_MAX;
    1288           42 :       av = avma;
    1289           42 :       if (!intdvd(a, p, &a)) break;
    1290           28 :       if (!intdvd(b, p, &b)) return gc_long(av,0);
    1291           14 :       val = 1; while (intdvd(a,p,&a) && intdvd(b,p,&b)) val++;
    1292           14 :       return gc_long(av,val);
    1293              :     }
    1294              : 
    1295       292516 :     case t_FRAC:
    1296       292516 :       if (tp == t_POL) return 0;
    1297       292502 :       return frac_val(x, p);
    1298              : 
    1299       721908 :     case t_PADIC:
    1300       721908 :       if (tp == t_POL) return 0;
    1301       721887 :       if (!equalii(p, padic_p(x))) break;
    1302       721880 :       return valp(x);
    1303              : 
    1304           35 :     case t_POLMOD: {
    1305           35 :       GEN a = gel(x,1), b = gel(x,2);
    1306              :       long v, val;
    1307           35 :       if (tp == t_INT) return gvaluation(b,p);
    1308           21 :       v = varn(p);
    1309           21 :       if (varn(a) != v) return 0;
    1310           21 :       av = avma;
    1311           21 :       a = RgX_divrem(a, p, ONLY_DIVIDES);
    1312           21 :       if (!a) break;
    1313           28 :       if (typ(b) != t_POL || varn(b) != v ||
    1314           21 :           !(b = RgX_divrem(b, p, ONLY_DIVIDES)) ) return gc_long(av,0);
    1315            7 :       val = 1;
    1316           28 :       while ((a = RgX_divrem(a, p, ONLY_DIVIDES)) &&
    1317           21 :              (b = RgX_divrem(b, p, ONLY_DIVIDES)) ) val++;
    1318            7 :       return gc_long(av,val);
    1319              :     }
    1320       161315 :     case t_POL: {
    1321       161315 :       if (tp == t_POL) {
    1322        58023 :         long vp = varn(p), vx = varn(x);
    1323        58023 :         if (vp == vx)
    1324              :         {
    1325              :           long val;
    1326        24262 :           if (RgX_is_monomial(p))
    1327              :           {
    1328        24227 :             val = RgX_val(x); if (val == LONG_MAX) return LONG_MAX;
    1329        13384 :             return val / degpol(p);
    1330              :           }
    1331           35 :           if (!signe(x)) return LONG_MAX;
    1332           21 :           av = avma;
    1333           21 :           for (val=0; ; val++)
    1334              :           {
    1335           35 :             x = RgX_divrem(x,p,ONLY_DIVIDES);
    1336           35 :             if (!x) return gc_long(av,val);
    1337           14 :             if (gc_needed(av,1))
    1338              :             {
    1339            0 :               if(DEBUGMEM>1) pari_warn(warnmem,"gvaluation");
    1340            0 :               x = gc_GEN(av, x);
    1341              :             }
    1342              :           }
    1343              :         }
    1344        33761 :         if (varncmp(vx, vp) > 0) return 0;
    1345              :       }
    1346       137046 :       return minval(x,p);
    1347              :     }
    1348              : 
    1349          490 :     case t_SER: {
    1350          490 :       if (tp == t_POL) {
    1351          476 :         long vp = varn(p), vx = varn(x);
    1352          476 :         if (vp == vx)
    1353              :         {
    1354          469 :           long val = RgX_val(p);
    1355          469 :           if (!val) pari_err_DOMAIN("gvaluation", "p", "=", p, p);
    1356          462 :           return (long)(valser(x) / val);
    1357              :         }
    1358            7 :         if (varncmp(vx, vp) > 0) return 0;
    1359              :       }
    1360           14 :       return minval(x,p);
    1361              :     }
    1362              : 
    1363           49 :     case t_RFRAC:
    1364           49 :       return gvaluation(gel(x,1),p) - gvaluation(gel(x,2),p);
    1365              : 
    1366          126 :     case t_COMPLEX: case t_QUAD: case t_VEC: case t_COL: case t_MAT:
    1367          126 :       return minval(x,p);
    1368              :   }
    1369           63 :   pari_err_OP("valuation", x,p);
    1370              :   return 0; /* LCOV_EXCL_LINE */
    1371              : }
    1372              : GEN
    1373         3934 : gpvaluation(GEN x, GEN p)
    1374              : {
    1375         3934 :   long v = gvaluation(x,p);
    1376         3829 :   return v == LONG_MAX? mkoo(): stoi(v);
    1377              : }
    1378              : 
    1379              : /* x is nonzero */
    1380              : long
    1381     90399014 : u_lvalrem(ulong x, ulong p, ulong *py)
    1382              : {
    1383              :   ulong vx;
    1384     90399014 :   if (p == 2) { vx = vals(x); *py = x >> vx; return vx; }
    1385     80134871 :   for(vx = 0;;)
    1386              :   {
    1387    131105767 :     if (x % p) { *py = x; return vx; }
    1388     50970896 :     x /= p; /* gcc is smart enough to make a single div */
    1389     50970896 :     vx++;
    1390              :   }
    1391              : }
    1392              : long
    1393     71116789 : u_lval(ulong x, ulong p)
    1394              : {
    1395              :   ulong vx;
    1396     71116789 :   if (p == 2) return vals(x);
    1397     67727498 :   for(vx = 0;;)
    1398              :   {
    1399    115946131 :     if (x % p) return vx;
    1400     48218633 :     x /= p; /* gcc is smart enough to make a single div */
    1401     48218633 :     vx++;
    1402              :   }
    1403              : }
    1404              : 
    1405              : long
    1406      1839847 : z_lval(long s, ulong p) { return u_lval(labs(s), p); }
    1407              : long
    1408        87348 : z_lvalrem(long s, ulong p, long *py)
    1409              : {
    1410              :   long v;
    1411        87348 :   if (s < 0)
    1412              :   {
    1413            0 :     ulong u = (ulong)-s;
    1414            0 :     v = u_lvalrem(u, p, &u);
    1415            0 :     *py = -(long)u;
    1416              :   }
    1417              :   else
    1418              :   {
    1419        87348 :     ulong u = (ulong)s;
    1420        87348 :     v = u_lvalrem(u, p, &u);
    1421        87347 :     *py = (long)u;
    1422              :   }
    1423        87347 :   return v;
    1424              : }
    1425              : /* assume |p| > 1 */
    1426              : long
    1427      1318030 : z_pval(long s, GEN p)
    1428              : {
    1429      1318030 :   if (lgefint(p) > 3) return 0;
    1430      1318030 :   return z_lval(s, uel(p,2));
    1431              : }
    1432              : /* assume |p| > 1 */
    1433              : long
    1434          399 : z_pvalrem(long s, GEN p, long *py)
    1435              : {
    1436          399 :   if (lgefint(p) > 3) { *py = s; return 0; }
    1437          399 :   return z_lvalrem(s, uel(p,2), py);
    1438              : }
    1439              : 
    1440              : /* return v_q(x) and set *py = x / q^v_q(x), using divide & conquer */
    1441              : static long
    1442      2159114 : Z_pvalrem_DC(GEN x, GEN q, GEN *py)
    1443              : {
    1444      2159114 :   GEN r, z = dvmdii(x, q, &r);
    1445              :   long v;
    1446      2158933 :   if (r != gen_0) { *py = x; return 0; }
    1447      1488575 :   if (2 * lgefint(q) <= lgefint(z)+3) /* avoid squaring if pointless */
    1448      1472641 :     v = Z_pvalrem_DC(z, sqri(q), py) << 1;
    1449              :   else
    1450        15934 :   { v = 0; *py = z; }
    1451      1488568 :   z = dvmdii(*py, q, &r);
    1452      1488773 :   if (r != gen_0) return v + 1;
    1453       622490 :   *py = z; return v + 2;
    1454              : }
    1455              : 
    1456              : static const long VAL_DC_THRESHOLD = 16;
    1457              : 
    1458              : long
    1459     68995577 : Z_lval(GEN x, ulong p)
    1460              : {
    1461              :   long vx;
    1462              :   pari_sp av;
    1463     68995577 :   if (p == 2) return vali(x);
    1464     53756453 :   if (lgefint(x) == 3) return u_lval(uel(x,2), p);
    1465      2757274 :   av = avma;
    1466      2757274 :   for(vx = 0;;)
    1467     11886071 :   {
    1468              :     ulong r;
    1469     14643345 :     GEN q = absdiviu_rem(x, p, &r);
    1470     14644118 :     if (r) break;
    1471     12074854 :     vx++; x = q;
    1472     12074854 :     if (vx == VAL_DC_THRESHOLD) {
    1473       188783 :       if (p == 1) pari_err_DOMAIN("Z_lval", "p", "=", gen_1, gen_1);
    1474       188783 :       vx += Z_pvalrem_DC(x, sqru(p), &x) << 1;
    1475       188783 :       q = absdiviu_rem(x, p, &r); if (!r) vx++;
    1476       188783 :       break;
    1477              :     }
    1478              :   }
    1479      2758047 :   return gc_long(av,vx);
    1480              : }
    1481              : long
    1482     65060097 : Z_lvalrem(GEN x, ulong p, GEN *py)
    1483              : {
    1484              :   long vx, sx;
    1485              :   pari_sp av;
    1486     65060097 :   if (p == 2) { vx = vali(x); *py = shifti(x, -vx); return vx; }
    1487     51161197 :   if (lgefint(x) == 3) {
    1488              :     ulong u;
    1489     44389972 :     vx = u_lvalrem(uel(x,2), p, &u);
    1490     44389651 :     *py = signe(x) < 0? utoineg(u): utoipos(u);
    1491     44388985 :     return vx;
    1492              :   }
    1493      6771225 :   av = avma; (void)new_chunk(lgefint(x));
    1494      6771929 :   sx = signe(x);
    1495      6771929 :   for(vx = 0;;)
    1496     19134070 :   {
    1497              :     ulong r;
    1498     25905999 :     GEN q = absdiviu_rem(x, p, &r);
    1499     25905962 :     if (r) break;
    1500     19631168 :     vx++; x = q;
    1501     19631168 :     if (vx == VAL_DC_THRESHOLD) {
    1502       497098 :       if (p == 1) pari_err_DOMAIN("Z_lvalrem", "p", "=", gen_1, gen_1);
    1503       497098 :       vx += Z_pvalrem_DC(x, sqru(p), &x) << 1;
    1504       497098 :       q = absdiviu_rem(x, p, &r); if (!r) { vx++; x = q; }
    1505       497100 :       break;
    1506              :     }
    1507              :   }
    1508      6771894 :   set_avma(av); *py = icopy(x); setsigne(*py, sx); return vx;
    1509              : }
    1510              : 
    1511              : /* Is |q| <= p ? */
    1512              : static int
    1513     15102537 : isless_iu(GEN q, ulong p) {
    1514     15102537 :   long l = lgefint(q);
    1515     15102537 :   return l==2 || (l == 3 && uel(q,2) <= p);
    1516              : }
    1517              : 
    1518              : long
    1519    135102996 : u_lvalrem_stop(ulong *n, ulong p, int *stop)
    1520              : {
    1521    135102996 :   ulong N = *n, q = N / p, r = N % p; /* gcc makes a single div */
    1522    135102996 :   long v = 0;
    1523    135102996 :   if (!r)
    1524              :   {
    1525     22276202 :     do { v++; N = q; q = N / p; r = N % p; } while (!r);
    1526     14226043 :     *n = N;
    1527              :   }
    1528    135102996 :   *stop = q <= p; return v;
    1529              : }
    1530              : /* Assume n > 0. Return v_p(n), set *n := n/p^v_p(n). Set 'stop' if now
    1531              :  * n < p^2 [implies n prime if no prime < p divides n] */
    1532              : long
    1533    117185973 : Z_lvalrem_stop(GEN *n, ulong p, int *stop)
    1534              : {
    1535              :   pari_sp av;
    1536              :   long v;
    1537              :   ulong r;
    1538              :   GEN N, q;
    1539              : 
    1540    117185973 :   if (lgefint(*n) == 3)
    1541              :   {
    1542    102074223 :     r = (*n)[2];
    1543    102074223 :     v = u_lvalrem_stop(&r, p, stop);
    1544    102081586 :     if (v) *n = utoipos(r);
    1545    102056431 :     return v;
    1546              :   }
    1547     15111750 :   av = avma; v = 0; q = absdiviu_rem(*n, p, &r);
    1548     15102538 :   if (r) set_avma(av);
    1549              :   else
    1550              :   {
    1551              :     do {
    1552       265872 :       v++; N = q;
    1553       265872 :       if (v == VAL_DC_THRESHOLD)
    1554              :       {
    1555          629 :         v += Z_pvalrem_DC(N,sqru(p),&N) << 1;
    1556          629 :         q = absdiviu_rem(N, p, &r); if (!r) { v++; N = q; }
    1557          629 :         break;
    1558              :       }
    1559       265243 :       q = absdiviu_rem(N, p, &r);
    1560       265243 :     } while (!r);
    1561       224457 :     *n = N;
    1562              :   }
    1563     15102543 :   *stop = isless_iu(q,p); return v;
    1564              : }
    1565              : 
    1566              : /* x is a nonzero integer, |p| > 1 */
    1567              : long
    1568     69960562 : Z_pvalrem(GEN x, GEN p, GEN *py)
    1569              : {
    1570              :   long vx;
    1571              :   pari_sp av;
    1572              : 
    1573     69960562 :   if (lgefint(p) == 3) return Z_lvalrem(x, uel(p,2), py);
    1574     14540425 :   if (lgefint(x) == 3) { *py = icopy(x); return 0; }
    1575      1575247 :   av = avma; vx = 0; (void)new_chunk(lgefint(x));
    1576              :   for(;;)
    1577        21833 :   {
    1578      1597171 :     GEN r, q = dvmdii(x,p,&r);
    1579      1597171 :     if (r != gen_0) { set_avma(av); *py = icopy(x); return vx; }
    1580        21833 :     vx++; x = q;
    1581              :   }
    1582              : }
    1583              : long
    1584      2634533 : u_pvalrem(ulong x, GEN p, ulong *py)
    1585              : {
    1586      2634533 :   if (lgefint(p) == 3) return u_lvalrem(x, uel(p,2), py);
    1587          553 :   *py = x; return 0;
    1588              : }
    1589              : long
    1590       136846 : u_pval(ulong x, GEN p)
    1591              : {
    1592       136846 :   if (lgefint(p) == 3) return u_lval(x, uel(p,2));
    1593            0 :   return 0;
    1594              : }
    1595              : long
    1596     50412322 : Z_pval(GEN x, GEN p) {
    1597              :   long vx;
    1598              :   pari_sp av;
    1599              : 
    1600     50412322 :   if (lgefint(p) == 3) return Z_lval(x, uel(p,2));
    1601        32856 :   if (lgefint(x) == 3) return 0;
    1602         8081 :   av = avma; vx = 0;
    1603              :   for(;;)
    1604        25820 :   {
    1605        33901 :     GEN r, q = dvmdii(x,p,&r);
    1606        33924 :     if (r != gen_0) return gc_long(av,vx);
    1607        25820 :     vx++; x = q;
    1608              :   }
    1609              : }
    1610              : 
    1611              : /* return v_p(n!) = [n/p] + [n/p^2] + ... */
    1612              : long
    1613      1995436 : factorial_lval(ulong n, ulong p)
    1614              : {
    1615              :   ulong q, v;
    1616      1995436 :   if (p == 2) return n - hammingu(n);
    1617      1320692 :   q = p; v = 0;
    1618      1449355 :   do { v += n/q; q *= p; } while (n >= q);
    1619      1320692 :   return (long)v;
    1620              : }
    1621              : 
    1622              : /********** Same for "containers" ZX / ZV / ZC **********/
    1623              : 
    1624              : /* If the t_INT q divides the ZX/ZV x, return the quotient. Otherwise NULL.
    1625              :  * Stack clean; assumes lg(x) > 1 */
    1626              : static GEN
    1627         6855 : gen_Z_divides(GEN x, GEN q, long imin)
    1628              : {
    1629              :   long i, l;
    1630         6855 :   GEN y = cgetg_copy(x, &l);
    1631              : 
    1632         6855 :   y[1] = x[1]; /* Needed for ZX; no-op if ZV, overwritten in first iteration */
    1633        89952 :   for (i = imin; i < l; i++)
    1634              :   {
    1635        87235 :     GEN r, xi = gel(x,i);
    1636        87235 :     if (!signe(xi)) { gel(y,i) = xi; continue; }
    1637        56650 :     gel(y,i) = dvmdii(xi, q, &r);
    1638        56650 :     if (r != gen_0) { set_avma((pari_sp)(y+l)); return NULL; }
    1639              :   }
    1640         2717 :   return y;
    1641              : }
    1642              : /* If q divides the ZX/ZV x, return the quotient. Otherwise NULL.
    1643              :  * Stack clean; assumes lg(x) > 1 */
    1644              : static GEN
    1645         4935 : gen_z_divides(GEN x, ulong q, long imin)
    1646              : {
    1647              :   long i, l;
    1648         4935 :   GEN y = cgetg_copy(x, &l);
    1649              : 
    1650         4935 :   y[1] = x[1]; /* Needed for ZX; no-op if ZV, overwritten in first iteration */
    1651        42915 :   for (i = imin; i < l; i++)
    1652              :   {
    1653              :     ulong r;
    1654        41593 :     GEN xi = gel(x,i);
    1655        41593 :     if (!signe(xi)) { gel(y,i) = xi; continue; }
    1656        28208 :     gel(y,i) = absdiviu_rem(xi, q, &r);
    1657        28208 :     if (r) { set_avma((pari_sp)(y+l)); return NULL; }
    1658        24595 :     affectsign_safe(xi, &gel(y,i));
    1659              :   }
    1660         1322 :   return y;
    1661              : }
    1662              : 
    1663              : /* return v_q(x) and set *py = x / q^v_q(x), using divide & conquer */
    1664              : static long
    1665        11752 : gen_pvalrem_DC(GEN x, GEN q, GEN *py, long imin)
    1666              : {
    1667              : 
    1668        11752 :   pari_sp av = avma;
    1669        11752 :   long v, i, l, lz = LONG_MAX;
    1670        11752 :   GEN y = cgetg_copy(x, &l);
    1671              : 
    1672        11752 :   y[1] = x[1];
    1673       136351 :   for (i = imin; i < l; i++)
    1674              :   {
    1675       129496 :     GEN r, xi = gel(x,i);
    1676       129496 :     if (!signe(xi)) { gel(y,i) = xi; continue; }
    1677        87592 :     gel(y,i) = dvmdii(xi, q, &r);
    1678        87592 :     if (r != gen_0) { *py = x; return gc_long(av,0); }
    1679        82695 :     lz = minss(lz, lgefint(gel(y,i)));
    1680              :   }
    1681         6855 :   if (2 * lgefint(q) <= lz+3) /* avoid squaring if pointless */
    1682         6803 :     v = gen_pvalrem_DC(y, sqri(q), py, imin) << 1;
    1683              :   else
    1684           52 :   { v = 0; *py = y; }
    1685              : 
    1686         6855 :   y = gen_Z_divides(*py, q, imin);
    1687         6855 :   if (!y) return v+1;
    1688         2717 :   *py = y; return v+2;
    1689              : }
    1690              : 
    1691              : static long
    1692       816027 : gen_2val(GEN x, long imin)
    1693              : {
    1694       816027 :   long i, lx = lg(x), v = LONG_MAX;
    1695      3099359 :   for (i = imin; i < lx; i++)
    1696              :   {
    1697      2639347 :     GEN c = gel(x,i);
    1698              :     long w;
    1699      2639347 :     if (!signe(c)) continue;
    1700      2398557 :     w = vali(c);
    1701      2398557 :     if (w < v) { v = w; if (!v) break; }
    1702              :   }
    1703       816027 :   return v;
    1704              : }
    1705              : static long
    1706       913697 : gen_lval(GEN x, ulong p, long imin)
    1707              : {
    1708              :   long i, lx, v;
    1709              :   pari_sp av;
    1710              :   GEN y;
    1711       913697 :   if (p == 2) return gen_2val(x, imin);
    1712        97670 :   av = avma;
    1713        97670 :   lx = lg(x); y = leafcopy(x);
    1714       293227 :   for(v = 0;; v++)
    1715      1437861 :     for (i = imin; i < lx; i++)
    1716              :     {
    1717              :       ulong r;
    1718      1242304 :       gel(y,i) = absdiviu_rem(gel(y,i), p, &r);
    1719      1242304 :       if (r) return gc_long(av,v);
    1720              :     }
    1721              : }
    1722              : long
    1723       788796 : ZX_lval(GEN x, ulong p) { return gen_lval(x, p, 2); }
    1724              : long
    1725            0 : ZV_lval(GEN x, ulong p) { return gen_lval(x, p, 1); }
    1726              : 
    1727              : long
    1728        28931 : zx_lval(GEN f, long p)
    1729              : {
    1730        28931 :   long i, l = lg(f), x = LONG_MAX;
    1731        30219 :   for(i=2; i<l; i++)
    1732              :   {
    1733              :     long y;
    1734        29477 :     if (f[i] == 0) continue;
    1735        29428 :     y = z_lval(f[i], p);
    1736        29428 :     if (y < x) { x = y; if (x == 0) return x; }
    1737              :   }
    1738          742 :   return x;
    1739              : }
    1740              : 
    1741              : static long
    1742       135226 : gen_pval(GEN x, GEN p, long imin)
    1743              : {
    1744              :   long i, lx, v;
    1745              :   pari_sp av;
    1746              :   GEN y;
    1747       135226 :   if (lgefint(p) == 3) return gen_lval(x, p[2], imin);
    1748        10325 :   av = avma;
    1749        10325 :   lx = lg(x); y = leafcopy(x);
    1750        10332 :   for(v = 0;; v++)
    1751              :   {
    1752        10332 :     if (v == VAL_DC_THRESHOLD)
    1753              :     {
    1754            0 :       if (is_pm1(p)) pari_err_DOMAIN("gen_pval", "p", "=", p, p);
    1755            0 :       v += gen_pvalrem_DC(y, p, &y, imin);
    1756            0 :       return gc_long(av,v);
    1757              :     }
    1758              : 
    1759        10381 :     for (i = imin; i < lx; i++)
    1760              :     {
    1761        10374 :       GEN r; gel(y,i) = dvmdii(gel(y,i), p, &r);
    1762        10374 :       if (r != gen_0) return gc_long(av,v);
    1763              :     }
    1764              :   }
    1765              : }
    1766              : long
    1767       104292 : ZX_pval(GEN x, GEN p) { return gen_pval(x, p, 2); }
    1768              : long
    1769        30934 : ZV_pval(GEN x, GEN p) { return gen_pval(x, p, 1); }
    1770              : /* v = 0 (mod p) */
    1771              : int
    1772         1414 : ZV_Z_dvd(GEN v, GEN p)
    1773              : {
    1774         1414 :   pari_sp av = avma;
    1775         1414 :   long i, l = lg(v);
    1776         4753 :   for (i=1; i<l; i++)
    1777         3563 :     if (!dvdii(gel(v,i), p)) return gc_int(av, 0);
    1778         1190 :   return gc_int(av, 1);
    1779              : }
    1780              : 
    1781              : static long
    1782      4923700 : gen_2valrem(GEN x, GEN *px, long imin)
    1783              : {
    1784      4923700 :   long i, lx = lg(x), v = LONG_MAX;
    1785              :   GEN z;
    1786     14116866 :   for (i = imin; i < lx; i++)
    1787              :   {
    1788     12794110 :     GEN c = gel(x,i);
    1789              :     long w;
    1790     12794110 :     if (!signe(c)) continue;
    1791     11896851 :     w = vali(c);
    1792     11897076 :     if (w < v) {
    1793      7051962 :       v = w;
    1794      7051962 :       if (!v) { *px = x; return 0; } /* early abort */
    1795              :     }
    1796              :   }
    1797      1322756 :   z = cgetg_copy(x, &lx); z[1] = x[1];
    1798      8614286 :   for (i=imin; i<lx; i++) gel(z,i) = shifti(gel(x,i), -v);
    1799      1322424 :   *px = z; return v;
    1800              : }
    1801              : static long
    1802      8489331 : gen_lvalrem(GEN x, ulong p, GEN *px, long imin)
    1803              : {
    1804              :   long i, lx, v;
    1805              :   GEN y;
    1806      8489331 :   if (p == 2) return gen_2valrem(x, px, imin);
    1807      3565692 :   y = cgetg_copy(x, &lx);
    1808      3565921 :   y[1] = x[1];
    1809      3565921 :   x = leafcopy(x);
    1810      3565451 :   for(v = 0;; v++)
    1811              :   {
    1812      4982535 :     if (v == VAL_DC_THRESHOLD)
    1813              :     {
    1814         4935 :       if (p == 1) pari_err_DOMAIN("gen_lvalrem", "p", "=", gen_1, gen_1);
    1815         4935 :       v += gen_pvalrem_DC(x, sqru(p), px, imin) << 1;
    1816         4935 :       x = gen_z_divides(*px, p, imin);
    1817         4935 :       if (x) { *px = x; v++; }
    1818         4935 :       return v;
    1819              :     }
    1820              : 
    1821     15706714 :     for (i = imin; i < lx; i++)
    1822              :     {
    1823     14289630 :       ulong r; gel(y,i) = absdiviu_rem(gel(x,i), p, &r);
    1824     14289383 :       if (r) { *px = x; return v; }
    1825     10728473 :       affectsign_safe(gel(x,i), &gel(y,i));
    1826              :     }
    1827      1417084 :     swap(x, y);
    1828              :   }
    1829              : }
    1830              : long
    1831          721 : ZX_lvalrem(GEN x, ulong p, GEN *px) { return gen_lvalrem(x,p,px, 2); }
    1832              : long
    1833            0 : ZV_lvalrem(GEN x, ulong p, GEN *px) { return gen_lvalrem(x,p,px, 1); }
    1834              : 
    1835              : static long
    1836      8501435 : gen_pvalrem(GEN x, GEN p, GEN *px, long imin)
    1837              : {
    1838              :   long i, lx, v;
    1839              :   GEN y;
    1840      8501435 :   if (lgefint(p) == 3) return gen_lvalrem(x, p[2], px, imin);
    1841        12863 :   y = cgetg_copy(x, &lx);
    1842        12966 :   y[1] = x[1];
    1843        12966 :   x = leafcopy(x);
    1844        12966 :   for(v = 0;; v++)
    1845              :   {
    1846        13755 :     if (v == VAL_DC_THRESHOLD)
    1847              :     {
    1848           14 :       if (is_pm1(p)) pari_err_DOMAIN("gen_pvalrem", "p", "=", p, p);
    1849           14 :       return v + gen_pvalrem_DC(x, p, px, imin);
    1850              :     }
    1851              : 
    1852        22489 :     for (i = imin; i < lx; i++)
    1853              :     {
    1854        21700 :       GEN r; gel(y,i) = dvmdii(gel(x,i), p, &r);
    1855        21700 :       if (r != gen_0) { *px = x; return v; }
    1856              :     }
    1857          789 :     swap(x, y);
    1858              :   }
    1859              : }
    1860              : long
    1861      4317914 : ZX_pvalrem(GEN x, GEN p, GEN *px) { return gen_pvalrem(x,p,px, 2); }
    1862              : long
    1863      4183523 : ZV_pvalrem(GEN x, GEN p, GEN *px) { return gen_pvalrem(x,p,px, 1); }
    1864              : 
    1865              : static long
    1866         3801 : ZX_gen_pvalrem(GEN x, GEN p, GEN *px, long imin)
    1867              : {
    1868              :   long i, lx, v;
    1869              :   GEN y;
    1870         3801 :   y = cgetg_copy(x, &lx);
    1871         3801 :   y[1] = x[1];
    1872         3801 :   x = leafcopy(x);
    1873        28126 :   for (i = imin; i < lx; i++)
    1874        24325 :     if (typ(gel(x, i)) != t_INT)
    1875              :     {
    1876        15225 :       gel(x, i) = leafcopy(gel(x,i));
    1877        15225 :       gel(y, i) = leafcopy(gel(x,i));
    1878              :     }
    1879         3801 :   for(v = 0;; v++)
    1880              :   {
    1881              : #if 0
    1882              :     if (v == VAL_DC_THRESHOLD) /* TODO */
    1883              :     {
    1884              :       if (is_pm1(p)) pari_err_DOMAIN("ZX_gen_pvalrem", "p", "=", p, p);
    1885              :       return v + ZX_gen_pvalrem_DC(x, p, px, imin);
    1886              :     }
    1887              : #endif
    1888              : 
    1889        12747 :     for (i = imin; i < lx; i++)
    1890              :     {
    1891        11263 :       GEN r, xi = gel(x,i);
    1892        11263 :       if (typ(xi) == t_INT)
    1893              :       {
    1894         3066 :         gel(y,i) = dvmdii(xi, p, &r);
    1895         5537 :         if (r != gen_0) { *px = x; return v; }
    1896              :       } else
    1897              :       {
    1898         8197 :         long j, lxi = lg(xi);
    1899        20244 :         for(j = 2; j < lxi; j++)
    1900              :         {
    1901        14518 :           gmael(y,i,j) = dvmdii(gel(xi,j), p, &r);
    1902        14518 :           if (r != gen_0) { *px = x; return v; }
    1903              :         }
    1904              :       }
    1905              :     }
    1906         1484 :     swap(x, y);
    1907              :   }
    1908              : }
    1909              : 
    1910              : long
    1911          952 : ZXX_pval(GEN x, GEN p)
    1912              : {
    1913          952 :   pari_sp av = avma;
    1914              :   GEN px;
    1915          952 :   return gc_long(av, ZX_gen_pvalrem(x,p,&px, 2));
    1916              : }
    1917              : 
    1918              : long
    1919            0 : ZXV_pval(GEN x, GEN p)
    1920              : {
    1921            0 :   pari_sp av = avma;
    1922              :   GEN px;
    1923            0 :   return gc_long(av, ZX_gen_pvalrem(x,p,&px, 1));
    1924              : }
    1925              : 
    1926              : long
    1927         2849 : ZXX_pvalrem(GEN x, GEN p, GEN *px) { return ZX_gen_pvalrem(x,p,px, 2); }
    1928              : long
    1929            0 : ZXV_pvalrem(GEN x, GEN p, GEN *px) { return ZX_gen_pvalrem(x,p,px, 1); }
    1930              : 
    1931              : /*******************************************************************/
    1932              : /*                                                                 */
    1933              : /*                       NEGATION: Create -x                       */
    1934              : /*                                                                 */
    1935              : /*******************************************************************/
    1936              : 
    1937              : GEN
    1938    472757998 : gneg(GEN x)
    1939              : {
    1940              :   GEN y;
    1941    472757998 :   switch(typ(x))
    1942              :   {
    1943    137234308 :     case t_INT:
    1944    137234308 :       return signe(x)? negi(x): gen_0;
    1945    247634842 :     case t_REAL:
    1946    247634842 :       return mpneg(x);
    1947              : 
    1948       102753 :     case t_INTMOD: y=cgetg(3,t_INTMOD);
    1949       102753 :       gel(y,1) = icopy(gel(x,1));
    1950       102753 :       gel(y,2) = signe(gel(x,2))? subii(gel(y,1),gel(x,2)): gen_0;
    1951       102751 :       break;
    1952              : 
    1953      2617294 :     case t_FRAC:
    1954      2617294 :       y = cgetg(3, t_FRAC);
    1955      2617293 :       gel(y,1) = negi(gel(x,1));
    1956      2617287 :       gel(y,2) = icopy(gel(x,2)); break;
    1957              : 
    1958     75278296 :     case t_COMPLEX:
    1959     75278296 :       y=cgetg(3, t_COMPLEX);
    1960     75279629 :       gel(y,1) = gneg(gel(x,1));
    1961     75281392 :       gel(y,2) = gneg(gel(x,2));
    1962     75281299 :       break;
    1963              : 
    1964       250862 :     case t_POLMOD:
    1965       250862 :       retmkpolmod(gneg(gel(x,2)), RgX_copy(gel(x,1)));
    1966              : 
    1967       153370 :     case t_RFRAC:
    1968       153370 :       y = cgetg(3, t_RFRAC);
    1969       153370 :       gel(y,1) = gneg(gel(x,1));
    1970       153370 :       gel(y,2) = RgX_copy(gel(x,2)); break;
    1971              : 
    1972       648296 :     case t_PADIC:
    1973              :     {
    1974       648296 :       GEN u = padic_u(x), pd = padic_pd(x), p = padic_p(x);
    1975       648296 :       if (!signe(u)) return gcopy(x);
    1976       644663 :       retmkpadic(subii(pd, u), icopy(p), icopy(pd), valp(x), precp(x));
    1977              :     }
    1978          119 :     case t_QUAD:
    1979          119 :       y=cgetg(4,t_QUAD);
    1980          119 :       gel(y,1) = ZX_copy(gel(x,1));
    1981          119 :       gel(y,2) = gneg(gel(x,2));
    1982          119 :       gel(y,3) = gneg(gel(x,3)); break;
    1983              : 
    1984      2299160 :     case t_FFELT: return FF_neg(x);
    1985      6214298 :     case t_POL: return RgX_neg(x);
    1986        16660 :     case t_SER: pari_APPLY_ser_normalized(gneg(gel(x,i)));
    1987         1813 :     case t_VEC: return RgV_neg(x);
    1988       431128 :     case t_COL: return RgC_neg(x);
    1989         1351 :     case t_MAT: return RgM_neg(x);
    1990          798 :     case t_INFINITY: return inf_get_sign(x) == 1? mkmoo(): mkoo();
    1991            0 :     default:
    1992            0 :       pari_err_TYPE("gneg",x);
    1993              :       return NULL; /* LCOV_EXCL_LINE */
    1994              :   }
    1995     78154787 :   return y;
    1996              : }
    1997              : 
    1998              : GEN
    1999    138729072 : gneg_i(GEN x)
    2000              : {
    2001              :   GEN y;
    2002    138729072 :   switch(typ(x))
    2003              :   {
    2004     64380552 :     case t_INT:
    2005     64380552 :       return signe(x)? negi(x): gen_0;
    2006     37510672 :     case t_REAL:
    2007     37510672 :       return mpneg(x);
    2008              : 
    2009       634781 :     case t_INTMOD: y=cgetg(3,t_INTMOD);
    2010       634781 :       gel(y,1) = gel(x,1);
    2011       634781 :       gel(y,2) = signe(gel(x,2))? subii(gel(y,1),gel(x,2)): gen_0;
    2012       634781 :       break;
    2013              : 
    2014      5756594 :     case t_FRAC:
    2015      5756594 :       y = cgetg(3, t_FRAC);
    2016      5756594 :       gel(y,1) = negi(gel(x,1));
    2017      5756591 :       gel(y,2) = gel(x,2); break;
    2018              : 
    2019     12323578 :     case t_COMPLEX:
    2020     12323578 :       y = cgetg(3, t_COMPLEX);
    2021     12323631 :       gel(y,1) = gneg_i(gel(x,1));
    2022     12323696 :       gel(y,2) = gneg_i(gel(x,2)); break;
    2023              : 
    2024      2015218 :     case t_PADIC:
    2025              :     {
    2026      2015218 :       GEN u = padic_u(x), pd = padic_pd(x), p = padic_p(x);
    2027      2015218 :       if (!signe(u)) return zeropadic_shallow(p, valp(x));
    2028      2013580 :       retmkpadic(subii(pd, u), p, pd, valp(x), precp(x));
    2029              :     }
    2030       143435 :     case t_POLMOD:
    2031       143435 :       retmkpolmod(gneg_i(gel(x,2)), RgX_copy(gel(x,1)));
    2032              : 
    2033        85064 :     case t_FFELT: return FF_neg_i(x);
    2034              : 
    2035          693 :     case t_QUAD: y=cgetg(4,t_QUAD);
    2036          693 :       gel(y,1) = gel(x,1);
    2037          693 :       gel(y,2) = gneg_i(gel(x,2));
    2038          693 :       gel(y,3) = gneg_i(gel(x,3)); break;
    2039              : 
    2040         2730 :     case t_VEC:
    2041              :     case t_COL:
    2042        14462 :     case t_MAT: pari_APPLY_same(gneg_i(gel(x,i)));
    2043     37872569 :     case t_POL: pari_APPLY_pol_normalized(gneg_i(gel(x,i)));
    2044      4409173 :     case t_SER: pari_APPLY_ser_normalized(gneg_i(gel(x,i)));
    2045              : 
    2046      5005055 :     case t_RFRAC:
    2047      5005055 :       y = cgetg(3, t_RFRAC);
    2048      5005055 :       gel(y,1) = gneg_i(gel(x,1));
    2049      5005051 :       gel(y,2) = gel(x,2); break;
    2050              : 
    2051            0 :     default:
    2052            0 :       pari_err_TYPE("gneg_i",x);
    2053              :       return NULL; /* LCOV_EXCL_LINE */
    2054              :   }
    2055     23720820 :   return y;
    2056              : }
    2057              : 
    2058              : /******************************************************************/
    2059              : /*                                                                */
    2060              : /*                       ABSOLUTE VALUE                           */
    2061              : /*    Create abs(x) if x is integer, real, fraction or complex.   */
    2062              : /*                       Error otherwise.                         */
    2063              : /*                                                                */
    2064              : /******************************************************************/
    2065              : static int
    2066            0 : is_negative(GEN x) {
    2067            0 :   switch(typ(x))
    2068              :   {
    2069            0 :     case t_INT: case t_REAL:
    2070            0 :       return (signe(x) < 0);
    2071            0 :     case t_FRAC:
    2072            0 :       return (signe(gel(x,1)) < 0);
    2073              :   }
    2074            0 :   return 0;
    2075              : }
    2076              : 
    2077              : GEN
    2078     53725196 : gabs(GEN x, long prec)
    2079              : {
    2080              :   long lx;
    2081              :   pari_sp av;
    2082              :   GEN y, N;
    2083              : 
    2084     53725196 :   switch(typ(x))
    2085              :   {
    2086     35578101 :     case t_INT: case t_REAL:
    2087     35578101 :       return mpabs(x);
    2088              : 
    2089        13028 :     case t_FRAC:
    2090        13028 :       return absfrac(x);
    2091              : 
    2092     18037372 :     case t_COMPLEX:
    2093     18037372 :       av=avma; N=cxnorm(x);
    2094     18019484 :       switch(typ(N))
    2095              :       {
    2096          266 :         case t_INT:
    2097          266 :           if (!Z_issquareall(N, &y)) break;
    2098          105 :           return gc_upto(av, y);
    2099        22281 :         case t_FRAC: {
    2100              :           GEN a,b;
    2101        36946 :           if (!Z_issquareall(gel(N,1), &a)) break;
    2102        14665 :           if (!Z_issquareall(gel(N,2), &b)) break;
    2103            0 :           return gc_upto(av, gdiv(a,b));
    2104              :         }
    2105              :       }
    2106     18019379 :       return gc_upto(av, gsqrt(N,prec));
    2107              : 
    2108           21 :     case t_QUAD:
    2109           21 :       av = avma;
    2110           21 :       return gc_leaf(av, gabs(quadtofp(x, prec), prec));
    2111              : 
    2112            0 :     case t_POL:
    2113            0 :       lx = lg(x); if (lx<=2) return RgX_copy(x);
    2114            0 :       return is_negative(gel(x,lx-1))? RgX_neg(x): RgX_copy(x);
    2115              : 
    2116            7 :     case t_SER:
    2117            7 :      if (!signe(x)) pari_err_DOMAIN("abs", "argument", "=", gen_0, x);
    2118            7 :      if (valser(x)) pari_err_DOMAIN("abs", "series valuation", "!=", gen_0, x);
    2119            0 :      return is_negative(gel(x,2))? gneg(x): gcopy(x);
    2120              : 
    2121       102549 :     case t_VEC: case t_COL: case t_MAT:
    2122       593748 :       pari_APPLY_same(gabs(gel(x,i),prec));
    2123              : 
    2124           14 :     case t_INFINITY:
    2125           14 :       return mkoo();
    2126              :   }
    2127            0 :   pari_err_TYPE("gabs",x);
    2128              :   return NULL; /* LCOV_EXCL_LINE */
    2129              : }
    2130              : 
    2131              : GEN
    2132        79310 : gmax(GEN x, GEN y) { return gcopy(gmax_shallow(x,y)); }
    2133              : GEN
    2134            0 : gmaxgs(GEN x, long s) { return (gcmpsg(s,x)>=0)? stoi(s): gcopy(x); }
    2135              : 
    2136              : GEN
    2137        12180 : gmin(GEN x, GEN y) { return gcopy(gmin_shallow(x,y)); }
    2138              : GEN
    2139            0 : gmings(GEN x, long s) { return (gcmpsg(s,x)>0)? gcopy(x): stoi(s); }
    2140              : 
    2141              : long
    2142       503443 : vecindexmax(GEN x)
    2143              : {
    2144       503443 :   long lx = lg(x), i0, i;
    2145              :   GEN s;
    2146              : 
    2147       503443 :   if (lx==1) pari_err_DOMAIN("vecindexmax", "empty argument", "=", x,x);
    2148       503444 :   switch(typ(x))
    2149              :   {
    2150       503444 :     case t_VEC: case t_COL:
    2151       503444 :       s = gel(x,i0=1);
    2152      1502943 :       for (i=2; i<lx; i++)
    2153       999497 :         if (gcmp(gel(x,i),s) > 0) s = gel(x,i0=i);
    2154       503446 :       return i0;
    2155            0 :     case t_VECSMALL:
    2156            0 :       return vecsmall_indexmax(x);
    2157            0 :     default: pari_err_TYPE("vecindexmax",x);
    2158              :   }
    2159              :   /* LCOV_EXCL_LINE */
    2160            0 :   return 0;
    2161              : }
    2162              : long
    2163       183130 : vecindexmin(GEN x)
    2164              : {
    2165       183130 :   long lx = lg(x), i0, i;
    2166              :   GEN s;
    2167              : 
    2168       183130 :   if (lx==1) pari_err_DOMAIN("vecindexmin", "empty argument", "=", x,x);
    2169       183130 :   switch(typ(x))
    2170              :   {
    2171       183130 :     case t_VEC: case t_COL:
    2172       183130 :       s = gel(x,i0=1);
    2173       952909 :       for (i=2; i<lx; i++)
    2174       769779 :         if (gcmp(gel(x,i),s) < 0) s = gel(x,i0=i);
    2175       183130 :       return i0;
    2176            0 :     case t_VECSMALL:
    2177            0 :       return vecsmall_indexmin(x);
    2178            0 :     default: pari_err_TYPE("vecindexmin",x);
    2179              :   }
    2180              :   /* LCOV_EXCL_LINE */
    2181            0 :   return 0;
    2182              : }
    2183              : 
    2184              : GEN
    2185       227032 : vecmax0(GEN x, GEN *pi)
    2186              : {
    2187       227032 :   long i, lx = lg(x), tx = typ(x);
    2188       227032 :   if (!is_matvec_t(tx) && tx != t_VECSMALL
    2189           49 :       && (tx != t_LIST || list_typ(x) != t_LIST_RAW)) return gcopy(x);
    2190       227011 :   if (tx == t_LIST)
    2191           28 :   { if (list_data(x)) { x = list_data(x); lx = lg(x); } else lx = 1; }
    2192       227011 :   if (lx==1) pari_err_DOMAIN("vecmax", "empty argument", "=", x,x);
    2193       226969 :   switch(typ(x))
    2194              :   {
    2195       226492 :     case t_VEC: case t_COL:
    2196       226492 :       i = vecindexmax(x); if (pi) *pi = utoipos(i);
    2197       226496 :       return gcopy(gel(x,i));
    2198          456 :     case t_MAT: {
    2199          456 :       long j, i0 = 1, j0 = 1, lx2 = lgcols(x);
    2200              :       GEN s;
    2201          456 :       if (lx2 == 1) pari_err_DOMAIN("vecmax", "empty argument", "=", x,x);
    2202          449 :       s = gcoeff(x,i0,j0); i = 2;
    2203         1205 :       for (j=1; j<lx; j++,i=1)
    2204              :       {
    2205          756 :         GEN c = gel(x,j);
    2206         1817 :         for (; i<lx2; i++)
    2207         1061 :           if (gcmp(gel(c,i),s) > 0) { s = gel(c,i); j0=j; i0=i; }
    2208              :       }
    2209          449 :       if (pi) *pi = mkvec2(utoipos(i0), utoipos(j0));
    2210          449 :       return gcopy(s);
    2211              :     }
    2212           21 :     case t_VECSMALL:
    2213           21 :       i = vecsmall_indexmax(x); if (pi) *pi = utoipos(i);
    2214           21 :       return stoi(x[i]);
    2215              :   }
    2216              :   return NULL;/*LCOV_EXCL_LINE*/
    2217              : }
    2218              : GEN
    2219       147521 : vecmin0(GEN x, GEN *pi)
    2220              : {
    2221       147521 :   long i, lx = lg(x), tx = typ(x);
    2222       147521 :   if (!is_matvec_t(tx) && tx != t_VECSMALL
    2223           49 :       && (tx != t_LIST || list_typ(x) != t_LIST_RAW)) return gcopy(x);
    2224       147500 :   if (tx == t_LIST)
    2225           28 :   { if (list_data(x)) { x = list_data(x); lx = lg(x); } else lx = 1; }
    2226       147500 :   if (lx==1) pari_err_DOMAIN("vecmin", "empty argument", "=", x,x);
    2227       147465 :   switch(typ(x))
    2228              :   {
    2229       147423 :     case t_VEC: case t_COL:
    2230       147423 :       i = vecindexmin(x); if (pi) *pi = utoipos(i);
    2231       147423 :       return gcopy(gel(x,i));
    2232           21 :     case t_MAT: {
    2233           21 :       long j, i0 = 1, j0 = 1, lx2 = lgcols(x);
    2234              :       GEN s;
    2235           21 :       if (lx2 == 1) pari_err_DOMAIN("vecmin", "empty argument", "=", x,x);
    2236           21 :       s = gcoeff(x,i0,j0); i = 2;
    2237           63 :       for (j=1; j<lx; j++,i=1)
    2238              :       {
    2239           42 :         GEN c = gel(x,j);
    2240          105 :         for (; i<lx2; i++)
    2241           63 :           if (gcmp(gel(c,i),s) < 0) { s = gel(c,i); j0=j; i0=i; }
    2242              :       }
    2243           21 :       if (pi) *pi = mkvec2(utoipos(i0), utoipos(j0));
    2244           21 :       return gcopy(s);
    2245              :     }
    2246           21 :     case t_VECSMALL:
    2247           21 :       i = vecsmall_indexmin(x); if (pi) *pi = utoipos(i);
    2248           21 :       return stoi(x[i]);
    2249              :   }
    2250              :   return NULL;/*LCOV_EXCL_LINE*/
    2251              : }
    2252              : 
    2253              : GEN
    2254        66202 : vecmax(GEN x) { return vecmax0(x, NULL); }
    2255              : GEN
    2256        35353 : vecmin(GEN x) { return vecmin0(x, NULL); }
    2257              : 
    2258              : /*******************************************************************/
    2259              : /*                                                                 */
    2260              : /*                     GENERIC AFFECTATION                         */
    2261              : /*         Affect the content of x to y, whenever possible         */
    2262              : /*                                                                 */
    2263              : /*******************************************************************/
    2264              : /* x PADIC, Y INT, return lift(x * Mod(1,Y)) */
    2265              : GEN
    2266         4550 : padic_to_Fp(GEN x, GEN Y) {
    2267         4550 :   pari_sp av = avma;
    2268         4550 :   GEN p = padic_p(x), z;
    2269         4550 :   long vy, vx = valp(x);
    2270         4550 :   if (!signe(Y)) pari_err_INV("padic_to_Fp",Y);
    2271         4550 :   vy = Z_pvalrem(Y,p, &z);
    2272         4550 :   if (vx < 0 || !gequal1(z)) pari_err_OP("",x, mkintmod(gen_1,Y));
    2273         4529 :   if (vx >= vy) { set_avma(av); return gen_0; }
    2274         4172 :   z = padic_u(x);
    2275         4172 :   if (!signe(z) || vy > vx + precp(x)) pari_err_OP("",x, mkintmod(gen_1,Y));
    2276         4172 :   if (vx) z = mulii(z, powiu(p,vx));
    2277         4172 :   return gc_INT(av, remii(z, Y));
    2278              : }
    2279              : ulong
    2280       421699 : padic_to_Fl(GEN x, ulong Y) {
    2281       421699 :   GEN p = padic_p(x);
    2282              :   ulong u, z;
    2283       421699 :   long vy, vx = valp(x);
    2284       421699 :   vy = u_pvalrem(Y,p, &u);
    2285       421699 :   if (vx < 0 || u != 1) pari_err_OP("",x, mkintmodu(1,Y));
    2286              :   /* Y = p^vy */
    2287       421699 :   if (vx >= vy) return 0;
    2288       375989 :   z = umodiu(padic_u(x), Y);
    2289       375990 :   if (!z || vy > vx + precp(x)) pari_err_OP("",x, mkintmodu(1,Y));
    2290       375990 :   if (vx) {
    2291            0 :     ulong pp = p[2];
    2292            0 :     z = Fl_mul(z, upowuu(pp,vx), Y); /* p^vx < p^vy = Y */
    2293              :   }
    2294       375990 :   return z;
    2295              : }
    2296              : 
    2297              : /* y a t_COMPLEX of t_REAL from cgetc; x a "complex number" (INT, FRAC, REAL,
    2298              :  * COMPLEX), raise an exception on exotic types (t_QUAD, etc) */
    2299              : void
    2300         2590 : affgc(GEN x, GEN y)
    2301              : {
    2302         2590 :   switch(typ(x))
    2303              :   {
    2304            0 :     case t_INT:
    2305            0 :       affir(x, gel(y,1));
    2306            0 :       affir(gen_0,gel(y,2)); break;
    2307              : 
    2308          910 :     case t_REAL:
    2309          910 :       affrr(x,gel(y,1));
    2310          910 :       affir(gen_0,gel(y,2)); break;
    2311              : 
    2312         1680 :     case t_COMPLEX:
    2313         1680 :       affgr(gel(x,1),gel(y,1));
    2314         1680 :       affgr(gel(x,2),gel(y,2)); break;
    2315              : 
    2316            0 :     case t_FRAC:
    2317            0 :       rdiviiz(gel(x,1),gel(x,2), gel(y,1));
    2318            0 :       affir(gen_0,gel(y,2)); break;
    2319              : 
    2320            0 :     default: pari_err_TYPE2("=",x,y);
    2321              :   }
    2322         2590 : }
    2323              : 
    2324              : /*******************************************************************/
    2325              : /*                                                                 */
    2326              : /*           CONVERSION QUAD --> REAL, COMPLEX OR P-ADIC           */
    2327              : /*                                                                 */
    2328              : /*******************************************************************/
    2329              : GEN
    2330          252 : quadtofp(GEN x, long prec)
    2331              : {
    2332          252 :   GEN b, D, z, u = gel(x,2), v = gel(x,3);
    2333              :   pari_sp av;
    2334          252 :   if (prec < LOWDEFAULTPREC) prec = LOWDEFAULTPREC;
    2335          252 :   if (isintzero(v)) return cxcompotor(u, prec);
    2336          252 :   av = avma; D = quad_disc(x); b = gel(gel(x,1),3); /* 0 or -1 */
    2337              :   /* u + v (-b + sqrt(D)) / 2 */
    2338          252 :   if (!signe(b)) b = NULL;
    2339          252 :   if (b) u = gadd(gmul2n(u,1), v);
    2340          252 :   z = sqrtr_abs(itor(D, prec));
    2341          252 :   if (!b) shiftr_inplace(z, -1);
    2342          252 :   z = gmul(v, z);
    2343          252 :   if (signe(D) < 0)
    2344              :   {
    2345           35 :     z = mkcomplex(cxcompotor(u, prec), z);
    2346           35 :     if (!b) return gc_GEN(av, z);
    2347            0 :     z = gmul2n(z, -1);
    2348              :   }
    2349              :   else
    2350              :   { /* if (b) x ~ (u + z) / 2 and quadnorm(x) ~ (u^2 - z^2) / 4
    2351              :      * else x ~ u + z and quadnorm(x) ~ u^2 - z^2 */
    2352          217 :     long s = gsigne(u);
    2353          217 :     if (s == -gsigne(v)) /* conjugate expression avoids cancellation */
    2354              :     {
    2355           14 :       z = gdiv(quadnorm(x), gsub(u, z));
    2356           14 :       if (b) shiftr_inplace(z, 1);
    2357              :     }
    2358              :     else
    2359              :     {
    2360          203 :       if (s) z = gadd(u, z);
    2361          203 :       if (b) shiftr_inplace(z, -1);
    2362              :     }
    2363              :   }
    2364          217 :   return gc_upto(av, z);
    2365              : }
    2366              : 
    2367              : static GEN
    2368           42 : qtop(GEN x, GEN p, long d)
    2369              : {
    2370           42 :   GEN z, D, P, b, u = gel(x,2), v = gel(x,3);
    2371              :   pari_sp av;
    2372           42 :   if (gequal0(v)) return cvtop(u, p, d);
    2373           28 :   P = gel(x,1);
    2374           28 :   b = gel(P,3);
    2375           28 :   av = avma; D = quad_disc(x);
    2376           28 :   if (absequaliu(p,2)) d += 2;
    2377           28 :   z = Qp_sqrt(cvtop(D,p,d));
    2378           28 :   if (!z) pari_err_SQRTN("Qp_sqrt",D);
    2379           14 :   z = gmul2n(gsub(z, b), -1);
    2380              : 
    2381           14 :   z = gadd(u, gmul(v, z));
    2382           14 :   if (typ(z) != t_PADIC) /* t_INTMOD for t_QUAD of t_INTMODs... */
    2383            0 :     z = cvtop(z, p, d);
    2384           14 :   return gc_upto(av, z);
    2385              : }
    2386              : static GEN
    2387           14 : ctop(GEN x, GEN p, long d)
    2388              : {
    2389           14 :   pari_sp av = avma;
    2390           14 :   GEN z, u = gel(x,1), v = gel(x,2);
    2391           14 :   if (isrationalzero(v)) return cvtop(u, p, d);
    2392           14 :   z = Qp_sqrt(cvtop(gen_m1, p, d - gvaluation(v, p))); /* = I */
    2393           14 :   if (!z) pari_err_SQRTN("Qp_sqrt",gen_m1);
    2394              : 
    2395           14 :   z = gadd(u, gmul(v, z));
    2396           14 :   if (typ(z) != t_PADIC) /* t_INTMOD for t_COMPLEX of t_INTMODs... */
    2397            0 :     z = cvtop(z, p, d);
    2398           14 :   return gc_upto(av, z);
    2399              : }
    2400              : 
    2401              : /* cvtop2(stoi(s), y) */
    2402              : GEN
    2403          399 : cvstop2(long s, GEN y)
    2404              : {
    2405          399 :   GEN p = padic_p(y), pd = padic_pd(y), u = padic_u(y);
    2406          399 :   long v, d = signe(u)? precp(y): 0;
    2407          399 :   if (!s) return zeropadic_shallow(p, d);
    2408          399 :   v = z_pvalrem(s, p, &s);
    2409          399 :   if (d <= 0) return zeropadic_shallow(p, v);
    2410          399 :   retmkpadic(modsi(s, pd), p, pd, v, d);
    2411              : }
    2412              : 
    2413              : static GEN
    2414     17612726 : itop2_coprime(GEN x, GEN y, long v, long d)
    2415              : {
    2416     17612726 :   GEN p = padic_p(y), pd = padic_pd(y);
    2417     17612726 :   retmkpadic(modii(x, pd), p, pd, v, d);
    2418              : }
    2419              : /* cvtop(x, gel(y,2), precp(y)), shallow */
    2420              : GEN
    2421     17619972 : cvtop2(GEN x, GEN y)
    2422              : {
    2423     17619972 :   GEN p = padic_p(y), u;
    2424     17619972 :   long v, d = signe(padic_u(y))? precp(y): 0;
    2425     17619972 :   switch(typ(x))
    2426              :   {
    2427     14821560 :     case t_INT:
    2428     14821560 :       if (!signe(x)) return zeropadic_shallow(p, d);
    2429     14821560 :       if (d <= 0) return zeropadic_shallow(p, Z_pval(x,p));
    2430     14817122 :       v = Z_pvalrem(x, p, &x); return itop2_coprime(x, y, v, d);
    2431              : 
    2432            0 :     case t_INTMOD:
    2433            0 :       v = Z_pval(gel(x,1),p); if (v > d) v = d;
    2434            0 :       return cvtop(gel(x,2), p, v);
    2435              : 
    2436      2797499 :     case t_FRAC:
    2437              :     {
    2438              :       GEN num, den;
    2439      2797499 :       if (d <= 0) return zeropadic_shallow(p, Q_pval(x,p));
    2440      2796218 :       num = gel(x,1); v = Z_pvalrem(num, p, &num);
    2441      2796217 :       den = gel(x,2); if (!v) v = -Z_pvalrem(den, p, &den);
    2442      2796221 :       if (!is_pm1(den)) num = mulii(num, Fp_inv(den, padic_pd(y)));
    2443      2796222 :       return itop2_coprime(num, y, v, d);
    2444              :     }
    2445            7 :     case t_COMPLEX: return ctop(x, p, d);
    2446           42 :     case t_QUAD:    return qtop(x, p, d);
    2447         1197 :     case t_PADIC:
    2448         1197 :       u = padic_u(x);
    2449         1197 :       if (!signe(u)) return zeropadic_shallow(p, d);
    2450         1197 :       if (precp(x) <= d) return x;
    2451           35 :       return itop2_coprime(u, y, valp(x), d); /* reduce accuracy */
    2452              :   }
    2453            0 :   pari_err_TYPE("cvtop2",x);
    2454              :   return NULL; /* LCOV_EXCL_LINE */
    2455              : }
    2456              : 
    2457              : static GEN
    2458       163005 : _Fp_div(GEN n, GEN d, GEN q)
    2459       163005 : { return equali1(d)? modii(n, q): Fp_div(n, d, q); }
    2460              : 
    2461              : /* assume is_const_t(tx) */
    2462              : GEN
    2463       600656 : cvtop(GEN x, GEN p, long d)
    2464              : {
    2465              :   GEN u;
    2466              :   long v;
    2467              : 
    2468       600656 :   if (typ(p) != t_INT) pari_err_TYPE("cvtop",p);
    2469       600656 :   switch(typ(x))
    2470              :   {
    2471       268324 :     case t_INT:
    2472       268324 :       if (!signe(x)) return zeropadic(p, d);
    2473       267106 :       if (d <= 0) return zeropadic(p, Z_pval(x,p));
    2474       267050 :       v = Z_pvalrem(x, p, &x); /* not memory-clean */
    2475       267050 :       retmkpadic_i(modii(x, _pd), icopy(p), powiu(p,d), v, d);
    2476              : 
    2477           28 :     case t_INTMOD:
    2478           28 :       v = Z_pval(gel(x,1),p); if (v > d) v = d;
    2479           28 :       return cvtop(gel(x,2), p, v);
    2480              : 
    2481       163019 :     case t_FRAC:
    2482              :     {
    2483              :       GEN num, den;
    2484       163019 :       if (d <= 0) return zeropadic(p, Q_pval(x,p));
    2485       163005 :       num = gel(x,1); v = Z_pvalrem(num, p, &num); /* not memory-clean */
    2486       163004 :       den = gel(x,2); if (!v) v = -Z_pvalrem(den, p, &den);
    2487       163005 :       retmkpadic_i(_Fp_div(num, den, _pd), icopy(p), powiu(p,d), v, d);
    2488              :     }
    2489            7 :     case t_COMPLEX: return ctop(x, p, d);
    2490       169278 :     case t_PADIC:
    2491       169278 :       p = padic_p(x); /* override */
    2492       169278 :       u = padic_u(x);
    2493       169278 :       if (!signe(u)) return zeropadic(p, d);
    2494       169194 :       retmkpadic_i(modii(u, _pd), icopy(p), powiu(p,d), valp(x), d);
    2495              : 
    2496            0 :     case t_QUAD: return qtop(x, p, d);
    2497              :   }
    2498            0 :   pari_err_TYPE("cvtop",x);
    2499              :   return NULL; /* LCOV_EXCL_LINE */
    2500              : }
    2501              : 
    2502              : GEN
    2503          126 : gcvtop(GEN x, GEN p, long r)
    2504              : {
    2505          126 :   switch(typ(x))
    2506              :   {
    2507           63 :     case t_POL: pari_APPLY_pol_normalized(gcvtop(gel(x,i),p,r));
    2508           35 :     case t_SER: pari_APPLY_ser_normalized(gcvtop(gel(x,i),p,r));
    2509            0 :     case t_POLMOD: case t_RFRAC: case t_VEC: case t_COL: case t_MAT:
    2510            0 :       pari_APPLY_same(gcvtop(gel(x,i),p,r));
    2511              :   }
    2512           98 :   return cvtop(x,p,r);
    2513              : }
    2514              : 
    2515              : long
    2516    889687081 : gexpo_safe(GEN x)
    2517              : {
    2518    889687081 :   long tx = typ(x), lx, e, f, i;
    2519              : 
    2520    889687081 :   switch(tx)
    2521              :   {
    2522    199986257 :     case t_INT:
    2523    199986257 :       return expi(x);
    2524              : 
    2525       646151 :     case t_FRAC:
    2526       646151 :       return expi(gel(x,1)) - expi(gel(x,2));
    2527              : 
    2528    478327461 :     case t_REAL:
    2529    478327461 :       return expo(x);
    2530              : 
    2531     88523874 :     case t_COMPLEX:
    2532     88523874 :       e = gexpo(gel(x,1));
    2533     88523775 :       f = gexpo(gel(x,2)); return maxss(e, f);
    2534              : 
    2535           91 :     case t_QUAD: {
    2536           91 :       GEN p = gel(x,1); /* mod = X^2 + {0,1}* X - {D/4, (1-D)/4})*/
    2537           91 :       long d = 1 + expi(gel(p,2))/2; /* ~ expo(sqrt(D)) */
    2538           91 :       e = gexpo(gel(x,2));
    2539           91 :       f = gexpo(gel(x,3)) + d; return maxss(e, f);
    2540              :     }
    2541     84395759 :     case t_POL: case t_SER:
    2542     84395759 :       lx = lg(x); f = -(long)HIGHEXPOBIT;
    2543    327460138 :       for (i=2; i<lx; i++) { e=gexpo(gel(x,i)); if (e>f) f=e; }
    2544     84390737 :       return f;
    2545     37936705 :     case t_VEC: case t_COL: case t_MAT:
    2546     37936705 :       lx = lg(x); f = -(long)HIGHEXPOBIT;
    2547    262105748 :       for (i=1; i<lx; i++) { e=gexpo(gel(x,i)); if (e>f) f=e; }
    2548     37936555 :       return f;
    2549              :   }
    2550           48 :   return -1-(long)HIGHEXPOBIT;
    2551              : }
    2552              : long
    2553    889394892 : gexpo(GEN x)
    2554              : {
    2555    889394892 :   long e = gexpo_safe(x);
    2556    889392107 :   if (e < -(long)HIGHEXPOBIT) pari_err_TYPE("gexpo",x);
    2557    889394936 :   return e;
    2558              : }
    2559              : GEN
    2560        90285 : gpexponent(GEN x)
    2561              : {
    2562        90285 :   long e = gexpo(x);
    2563        90285 :   return e == -(long)HIGHEXPOBIT? mkmoo(): stoi(e);
    2564              : }
    2565              : 
    2566              : long
    2567            7 : sizedigit(GEN x)
    2568              : {
    2569            7 :   return gequal0(x)? 0: (long) ((gexpo(x)+1) * LOG10_2) + 1;
    2570              : }
    2571              : 
    2572              : /* normalize series. avma is not updated */
    2573              : GEN
    2574     15686279 : normalizeser(GEN x)
    2575              : {
    2576     15686279 :   long i, lx = lg(x), vx=varn(x), vp=valser(x);
    2577              :   GEN y, z;
    2578              : 
    2579     15686279 :   if (lx == 2) { setsigne(x,0); return x; }
    2580     15685915 :   if (lx == 3) {
    2581       118989 :     z = gel(x,2);
    2582       118989 :     if (!gequal0(z)) { setsigne(x,1); return x; }
    2583        23779 :     if (isrationalzero(z)) return zeroser(vx,vp+1);
    2584         4256 :     if (isexactzero(z)) {
    2585              :       /* dangerous case: already normalized ? */
    2586           91 :       if (!signe(x)) return x;
    2587           35 :       setvalser(x,vp+1); /* no: normalize */
    2588              :     }
    2589         4200 :     setsigne(x,0); return x;
    2590              :   }
    2591     15868280 :   for (i=2; i<lx; i++)
    2592     15821534 :     if (! isrationalzero(gel(x,i))) break;
    2593     15566926 :   if (i == lx) return zeroser(vx,lx-2+vp);
    2594     15520180 :   z = gel(x,i);
    2595     15523995 :   while (i<lx && isexactzero(gel(x,i))) i++;
    2596     15520180 :   if (i == lx)
    2597              :   {
    2598          280 :     i -= 3; y = x + i;
    2599          280 :     stackdummy((pari_sp)y, (pari_sp)x);
    2600          280 :     gel(y,2) = z;
    2601          280 :     y[1] = evalsigne(0) | evalvalser(lx-2+vp) | evalvarn(vx);
    2602          280 :     y[0] = evaltyp(t_SER) | _evallg(3);
    2603          280 :     return y;
    2604              :   }
    2605              : 
    2606     15519900 :   i -= 2; y = x + i; lx -= i;
    2607     15519900 :   y[1] = evalsigne(1) | evalvalser(vp+i) | evalvarn(vx);
    2608     15519900 :   y[0] = evaltyp(t_SER) | _evallg(lx);
    2609              : 
    2610     15519900 :   stackdummy((pari_sp)y, (pari_sp)x);
    2611     15555546 :   for (i = 2; i < lx; i++)
    2612     15554279 :     if (!gequal0(gel(y, i))) return y;
    2613         1267 :   setsigne(y, 0); return y;
    2614              : }
    2615              : 
    2616              : GEN
    2617            0 : normalizepol_approx(GEN x, long lx)
    2618              : {
    2619              :   long i;
    2620            0 :   for (i = lx-1; i>1; i--)
    2621            0 :     if (! gequal0(gel(x,i))) break;
    2622            0 :   stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + i+1));
    2623            0 :   setlg(x, i+1); setsigne(x, i!=1); return x;
    2624              : }
    2625              : 
    2626              : GEN
    2627    945334068 : normalizepol_lg(GEN x, long lx)
    2628              : {
    2629    945334068 :   long i, LX = 0;
    2630    945334068 :   GEN KEEP = NULL;
    2631              : 
    2632   1293589702 :   for (i = lx-1; i>1; i--)
    2633              :   {
    2634   1136049365 :     GEN z = gel(x,i);
    2635   1136049365 :     if (! gequal0(z) ) {
    2636    788017961 :       if (!LX) LX = i+1;
    2637    788017961 :       stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + LX));
    2638    788003267 :       x[0] = evaltyp(t_POL) | _evallg(LX);
    2639    788003267 :       setsigne(x,1); return x;
    2640    347997111 :     } else if (!isexactzero(z)) {
    2641       995495 :       if (!LX) LX = i+1; /* to be kept as leading coeff */
    2642    347263509 :     } else if (!isrationalzero(z))
    2643       718617 :       KEEP = z; /* to be kept iff all other coeffs are exact 0s */
    2644              :   }
    2645    157540337 :   if (!LX) {
    2646    157017824 :     if (KEEP) { /* e.g. Pol(Mod(0,2)) */
    2647       151278 :       gel(x,2) = KEEP;
    2648       151278 :       LX = 3;
    2649              :     } else
    2650    156866546 :       LX = 2; /* Pol(0) */
    2651              :   }
    2652    157540337 :   stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + LX));
    2653    157427083 :   x[0] = evaltyp(t_POL) | _evallg(LX);
    2654    157427083 :   setsigne(x,0); return x;
    2655              : }
    2656              : 
    2657              : /* normalize polynomial x in place */
    2658              : GEN
    2659     99685779 : normalizepol(GEN x)
    2660              : {
    2661     99685779 :   return normalizepol_lg(x, lg(x));
    2662              : }
    2663              : 
    2664              : int
    2665     84281262 : gsigne(GEN x)
    2666              : {
    2667     84281262 :   switch(typ(x))
    2668              :   {
    2669     83900514 :     case t_INT: case t_REAL: return signe(x);
    2670       380091 :     case t_FRAC: return signe(gel(x,1));
    2671          686 :     case t_QUAD:
    2672              :     {
    2673          686 :       pari_sp av = avma;
    2674          686 :       GEN T = gel(x,1), a = gel(x,2), b = gel(x,3);
    2675              :       long sa, sb;
    2676          686 :       if (signe(gel(T,2)) > 0) break;
    2677          672 :       a = gmul2n(a,1);
    2678          672 :       if (signe(gel(T,3))) a = gadd(a,b);
    2679              :       /* a + b sqrt(D) > 0 ? */
    2680          672 :       sa = gsigne(a);
    2681          672 :       sb = gsigne(b); if (sa == sb) return gc_int(av,sa);
    2682          280 :       if (sa == 0) return gc_int(av,sb);
    2683          266 :       if (sb == 0) return gc_int(av,sa);
    2684              :       /* different signs, take conjugate expression */
    2685          259 :       sb = gsigne(gsub(gsqr(a), gmul(quad_disc(x), gsqr(b))));
    2686          259 :       return gc_int(av, sb*sa);
    2687              :     }
    2688           14 :     case t_INFINITY: return inf_get_sign(x);
    2689              :   }
    2690           12 :   pari_err_TYPE("gsigne",x);
    2691              :   return 0; /* LCOV_EXCL_LINE */
    2692              : }
    2693              : 
    2694              : /*******************************************************************/
    2695              : /*                                                                 */
    2696              : /*                              LISTS                              */
    2697              : /*                                                                 */
    2698              : /*******************************************************************/
    2699              : /* make sure L can hold l elements, at least doubling the previous max number
    2700              :  * of components. */
    2701              : static void
    2702       810971 : ensure_nb(GEN L, long l)
    2703              : {
    2704       810971 :   long nmax = list_nmax(L), i, lw;
    2705              :   GEN v, w;
    2706       810971 :   if (l <= nmax) return;
    2707         1246 :   if (nmax)
    2708              :   {
    2709          490 :     nmax <<= 1;
    2710          490 :     if (l > nmax) nmax = l;
    2711          490 :     w = list_data(L); lw = lg(w);
    2712          490 :     v = newblock(nmax+1);
    2713          490 :     v[0] = w[0];
    2714      1070958 :     for (i=1; i < lw; i++) gel(v,i) = gel(w, i);
    2715          490 :     killblock(w);
    2716              :   }
    2717              :   else /* unallocated */
    2718              :   {
    2719          756 :     nmax = 32;
    2720          756 :     if (list_data(L))
    2721            0 :       pari_err(e_MISC, "store list in variable before appending elements");
    2722          756 :     v = newblock(nmax+1);
    2723          756 :     v[0] = evaltyp(t_VEC) | _evallg(1);
    2724              :   }
    2725         1246 :   list_data(L) = v;
    2726         1246 :   L[1] = evaltyp(list_typ(L))|evallg(nmax);
    2727              : }
    2728              : 
    2729              : GEN
    2730         6926 : mklist_typ(long t)
    2731              : {
    2732         6926 :   GEN L = cgetg(3,t_LIST);
    2733         6926 :   L[1] = evaltyp(t);
    2734         6926 :   list_data(L) = NULL; return L;
    2735              : }
    2736              : 
    2737              : GEN
    2738         6870 : mklist(void)
    2739              : {
    2740         6870 :   return mklist_typ(t_LIST_RAW);
    2741              : }
    2742              : 
    2743              : GEN
    2744           49 : mkmap(void)
    2745              : {
    2746           49 :   return mklist_typ(t_LIST_MAP);
    2747              : }
    2748              : 
    2749              : /* return a list with single element x, allocated on stack */
    2750              : GEN
    2751           70 : mklistcopy(GEN x)
    2752              : {
    2753           70 :   GEN y = mklist();
    2754           70 :   list_data(y) = mkveccopy(x);
    2755           70 :   return y;
    2756              : }
    2757              : 
    2758              : GEN
    2759       776125 : listput(GEN L, GEN x, long index)
    2760              : {
    2761              :   long l;
    2762              :   GEN z;
    2763              : 
    2764       776125 :   if (index < 0) pari_err_COMPONENT("listput", "<", gen_0, stoi(index));
    2765       776118 :   z = list_data(L);
    2766       776118 :   l = z? lg(z): 1;
    2767              : 
    2768       776118 :   x = gclone(x);
    2769       776118 :   if (!index || index >= l)
    2770              :   {
    2771       775964 :     ensure_nb(L, l);
    2772       775964 :     z = list_data(L); /* it may change ! */
    2773       775964 :     index = l;
    2774       775964 :     l++;
    2775              :   } else
    2776          154 :     gunclone_deep( gel(z, index) );
    2777       776118 :   gel(z,index) = x;
    2778       776118 :   z[0] = evaltyp(t_VEC) | evallg(l); /*must be after gel(z,index) is set*/
    2779       776118 :   return gel(z,index);
    2780              : }
    2781              : 
    2782              : GEN
    2783       724955 : listput0(GEN L, GEN x, long index)
    2784              : {
    2785       724955 :   if (typ(L) != t_LIST || list_typ(L) != t_LIST_RAW)
    2786           14 :     pari_err_TYPE("listput",L);
    2787       724941 :   (void) listput(L, x, index);
    2788       724934 :   return x;
    2789              : }
    2790              : 
    2791              : GEN
    2792        35014 : listinsert(GEN L, GEN x, long index)
    2793              : {
    2794              :   long l, i;
    2795              :   GEN z;
    2796              : 
    2797        35014 :   z = list_data(L); l = z? lg(z): 1;
    2798        35014 :   if (index <= 0) pari_err_COMPONENT("listinsert", "<=", gen_0, stoi(index));
    2799        35007 :   if (index > l) index = l;
    2800        35007 :   ensure_nb(L, l);
    2801        35007 :   BLOCK_SIGINT_START
    2802        35007 :   z = list_data(L);
    2803     87552507 :   for (i=l; i > index; i--) gel(z,i) = gel(z,i-1);
    2804        35007 :   z[0] = evaltyp(t_VEC) | evallg(l+1);
    2805        35007 :   gel(z,index) = gclone(x);
    2806        35007 :   BLOCK_SIGINT_END
    2807        35007 :   return gel(z,index);
    2808              : }
    2809              : 
    2810              : GEN
    2811        35028 : listinsert0(GEN L, GEN x, long index)
    2812              : {
    2813        35028 :   if (typ(L) != t_LIST || list_typ(L) != t_LIST_RAW)
    2814           14 :     pari_err_TYPE("listinsert",L);
    2815        35014 :   (void) listinsert(L, x, index);
    2816        35007 :   return x;
    2817              : }
    2818              : 
    2819              : void
    2820        21917 : listpop(GEN L, long index)
    2821              : {
    2822              :   long l, i;
    2823              :   GEN z;
    2824              : 
    2825        21917 :   if (typ(L) != t_LIST) pari_err_TYPE("listinsert",L);
    2826        21917 :   if (index < 0) pari_err_COMPONENT("listpop", "<", gen_0, stoi(index));
    2827        21917 :   z = list_data(L);
    2828        21917 :   if (!z || (l = lg(z)-1) == 0) return;
    2829              : 
    2830        21903 :   if (!index || index > l) index = l;
    2831        21903 :   BLOCK_SIGINT_START
    2832        21903 :   gunclone_deep( gel(z, index) );
    2833        21903 :   z[0] = evaltyp(t_VEC) | _evallg(l);
    2834        21910 :   for (i=index; i < l; i++) z[i] = z[i+1];
    2835        21903 :   BLOCK_SIGINT_END
    2836              : }
    2837              : 
    2838              : void
    2839           56 : listpop0(GEN L, long index)
    2840              : {
    2841           56 :   if (typ(L) != t_LIST || list_typ(L) != t_LIST_RAW)
    2842           14 :     pari_err_TYPE("listpop",L);
    2843           42 :   listpop(L, index);
    2844           42 : }
    2845              : 
    2846              : /* return a copy fully allocated on stack. gclone from changevalue is
    2847              :  * supposed to malloc() it */
    2848              : GEN
    2849         5972 : gtolist(GEN x)
    2850              : {
    2851              :   GEN y;
    2852              : 
    2853         5972 :   if (!x) return mklist();
    2854          391 :   switch(typ(x))
    2855              :   {
    2856          314 :     case t_VEC: case t_COL:
    2857          314 :       y = mklist();
    2858          314 :       if (lg(x) == 1) return y;
    2859          293 :       list_data(y) = gcopy(x);
    2860          293 :       settyp(list_data(y), t_VEC);
    2861          293 :       return y;
    2862            7 :     case t_LIST:
    2863            7 :       y = mklist();
    2864            7 :       list_data(y) = list_data(x)? gcopy(list_data(x)): NULL;
    2865            7 :       return y;
    2866           70 :     default:
    2867           70 :       return mklistcopy(x);
    2868              :   }
    2869              : }
    2870              : 
    2871              : void
    2872           21 : listsort(GEN L, long flag)
    2873              : {
    2874              :   long i, l;
    2875           21 :   pari_sp av = avma;
    2876              :   GEN perm, v, vnew;
    2877              : 
    2878           21 :   if (typ(L) != t_LIST) pari_err_TYPE("listsort",L);
    2879           21 :   v = list_data(L); l = v? lg(v): 1;
    2880           21 :   if (l < 3) return;
    2881           21 :   if (flag)
    2882              :   {
    2883              :     long lnew;
    2884           14 :     perm = gen_indexsort_uniq(L, (void*)&cmp_universal, cmp_nodata);
    2885           14 :     lnew = lg(perm); /* may have changed since 'uniq' */
    2886           14 :     vnew = cgetg(lnew,t_VEC);
    2887           56 :     for (i=1; i<lnew; i++) {
    2888           42 :       long c = perm[i];
    2889           42 :       gel(vnew,i) = gel(v,c);
    2890           42 :       gel(v,c) = NULL;
    2891              :     }
    2892           14 :     if (l != lnew) { /* was shortened */
    2893          105 :       for (i=1; i<l; i++)
    2894           91 :         if (gel(v,i)) gunclone_deep(gel(v,i));
    2895           14 :       l = lnew;
    2896              :     }
    2897              :   }
    2898              :   else
    2899              :   {
    2900            7 :     perm = gen_indexsort(L, (void*)&cmp_universal, cmp_nodata);
    2901            7 :     vnew = cgetg(l,t_VEC);
    2902           63 :     for (i=1; i<l; i++) gel(vnew,i) = gel(v,perm[i]);
    2903              :   }
    2904          119 :   for (i=1; i<l; i++) gel(v,i) = gel(vnew,i);
    2905           21 :   v[0] = vnew[0]; set_avma(av);
    2906              : }
        

Generated by: LCOV version 2.0-1