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 - language - anal.c (source / functions) Hit Total Coverage
Test: PARI/GP v2.12.0 lcov report (development 23729-6349a644e) Lines: 572 633 90.4 %
Date: 2019-03-26 05:45:22 Functions: 89 96 92.7 %
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. It is distributed in the hope that it will be useful, but WITHOUT
       8             : ANY WARRANTY WHATSOEVER.
       9             : 
      10             : Check the License for details. You should have received a copy of it, along
      11             : with the package; see the file 'COPYING'. If not, write to the Free Software
      12             : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
      13             : 
      14             : #include "pari.h"
      15             : #include "paripriv.h"
      16             : #include "anal.h"
      17             : #include "parse.h"
      18             : 
      19             : /***************************************************************************
      20             :  **                                                                       **
      21             :  **                           Mnemonic codes parser                       **
      22             :  **                                                                       **
      23             :  ***************************************************************************/
      24             : 
      25             : /* TEMPLATE is assumed to be ";"-separated list of items.  Each item
      26             :  * may have one of the following forms: id=value id==value id|value id&~value.
      27             :  * Each id consists of alphanum characters, dashes and underscores.
      28             :  * IDs are case-sensitive.
      29             : 
      30             :  * ARG consists of several IDs separated by punctuation (and optional
      31             :  * whitespace).  Each modifies the return value in a "natural" way: an
      32             :  * ID from id=value should be the first in the sequence and sets RETVAL to
      33             :  * VALUE (and cannot be negated), ID from id|value bit-ORs RETVAL with
      34             :  * VALUE (and bit-ANDs RETVAL with ~VALUE if negated), ID from
      35             :  * id&~value behaves as if it were noid|value, ID from
      36             :  * id==value behaves the same as id=value, but should come alone.
      37             : 
      38             :  * For items of the form id|value and id&~value negated forms are
      39             :  * allowed: either when arg looks like no[-_]id, or when id looks like
      40             :  * this, and arg is not-negated. */
      41             : 
      42             : static int
      43         380 : IS_ID(char c) { return isalnum((int)c) || c == '_'; }
      44             : long
      45          28 : eval_mnemonic(GEN str, const char *tmplate)
      46             : {
      47             :   const char *arg, *etmplate;
      48          28 :   ulong retval = 0;
      49             : 
      50          28 :   if (typ(str)==t_INT) return itos(str);
      51          28 :   if (typ(str)!=t_STR) pari_err_TYPE("eval_mnemonic",str);
      52             : 
      53          28 :   arg = GSTR(str);
      54          28 :   etmplate = strchr(tmplate, '\n');
      55          28 :   if (!etmplate) etmplate = tmplate + strlen(tmplate);
      56             : 
      57             :   while (1)
      58          36 :   {
      59             :     long numarg;
      60          64 :     const char *e, *id, *negated = NULL;
      61          64 :     int negate = 0; /* Arg has 'no' prefix removed */
      62             :     ulong l;
      63             :     char *buf;
      64             :     static char b[80];
      65             : 
      66          64 :     while (isspace((int)*arg)) arg++;
      67          64 :     if (!*arg) break;
      68          36 :     e = arg; while (IS_ID(*e)) e++;
      69             :     /* Now the ID is whatever is between arg and e. */
      70          36 :     l = e - arg;
      71          36 :     if (l >= sizeof(b)) pari_err(e_MISC,"id too long in a mnemonic");
      72          36 :     if (!l) pari_err(e_MISC,"mnemonic does not start with an id");
      73          36 :     strncpy(b, arg, l); b[l] = 0;
      74          36 :     arg = e; e = buf = b;
      75          36 :     while ('0' <= *e && *e <= '9') e++;
      76          36 :     if (*e == 0) pari_err(e_MISC,"numeric id in a mnemonic");
      77             : FIND:
      78          36 :     id = tmplate;
      79          72 :     while ((id = strstr(id, buf)) && id < etmplate)
      80             :     {
      81          36 :       const char *s = id;
      82          36 :       id += l; if (s[l] != '|') continue; /* False positive */
      83          36 :       if (s == tmplate || !IS_ID(s[-1])) break; /* Found as is */
      84             :       /* If we found "no_ID", negate */
      85           0 :       if (!negate && s >= tmplate+3 && (s == tmplate+3 || !IS_ID(s[-4]))
      86           0 :           && s[-3] == 'n' && s[-2] == 'o' && s[-1] == '_')
      87           0 :          { negated = id; break; }
      88             :     }
      89          36 :     if (!id && !negated && !negate && l > 3
      90           0 :             && buf[0] == 'n' && buf[1] == 'o' && buf[2] == '_')
      91             :     { /* Try to find the flag without the prefix "no_". */
      92           0 :       buf += 3; l -= 3; negate = 1;
      93           0 :       if (buf[0]) goto FIND;
      94             :     }
      95             :     /* Negated and AS_IS forms, prefer AS_IS otherwise use negated form */
      96          36 :     if (!id)
      97             :     {
      98           0 :       if (!negated) pari_err(e_MISC,"Unrecognized id '%s' in mnemonic", b);
      99           0 :       id = negated; negate = 1;
     100             :     }
     101          36 :     if (*id++ != '|') pari_err(e_MISC,"Missing | in mnemonic template");
     102          36 :     e = id;
     103          36 :     while (*e >= '0' && *e <= '9') e++;
     104          36 :     while (isspace((int)*e)) e++;
     105          36 :     if (*e && *e != ';' && *e != ',')
     106           0 :       pari_err(e_MISC, "Non-numeric argument in mnemonic template");
     107          36 :     numarg = atol(id);
     108          36 :     if (negate) retval &= ~numarg; else retval |= numarg;
     109          36 :     while (isspace((int)*arg)) arg++;
     110          36 :     if (*arg && !ispunct((int)*arg++)) /* skip punctuation */
     111           0 :       pari_err(e_MISC,"Junk after id in mnemonic");
     112             :   }
     113          28 :   return retval;
     114             : }
     115             : 
     116             : /********************************************************************/
     117             : /**                                                                **/
     118             : /**                   HASH TABLE MANIPULATIONS                     **/
     119             : /**                                                                **/
     120             : /********************************************************************/
     121             : static void
     122     1963243 : insertep(entree *ep, entree **table, ulong hash)
     123             : {
     124     1963243 :   ep->hash = hash;
     125     1963243 :   hash %= functions_tblsz;
     126     1963243 :   ep->next = table[hash];
     127     1963243 :   table[hash] = ep;
     128     1963243 : }
     129             : 
     130             : static entree *
     131       27811 : initep(const char *name, long len)
     132             : {
     133       27811 :   const long add = 4*sizeof(long);
     134       27811 :   entree *ep = (entree *) pari_calloc(sizeof(entree) + add + len+1);
     135       27811 :   entree *ep1 = initial_value(ep);
     136       27811 :   char *u = (char *) ep1 + add;
     137       27811 :   ep->name    = u; memcpy(u, name,len); u[len]=0;
     138       27811 :   ep->valence = EpNEW;
     139       27811 :   ep->value   = NULL;
     140       27811 :   ep->menu    = 0;
     141       27811 :   ep->code    = NULL;
     142       27811 :   ep->help    = NULL;
     143       27811 :   ep->pvalue  = NULL;
     144       27811 :   ep->arity   = 0;
     145       27811 :   return ep;
     146             : }
     147             : 
     148             : /* Look for s of length len in T; if 'insert', insert if missing */
     149             : static entree *
     150     6598419 : findentry(const char *s, long len, entree **T, int insert)
     151             : {
     152     6598419 :   ulong hash = hash_str_len(s, len);
     153             :   entree *ep;
     154    59289804 :   for (ep = T[hash % functions_tblsz]; ep; ep = ep->next)
     155    59262035 :     if (ep->hash == hash)
     156             :     {
     157     6570673 :       const char *t = ep->name;
     158     6570673 :       if (!strncmp(t, s, len) && !t[len]) return ep;
     159             :     }
     160             :   /* not found */
     161       27769 :   if (insert) { ep = initep(s,len); insertep(ep, T, hash); }
     162       27769 :   return ep;
     163             : }
     164             : entree *
     165        1274 : pari_is_default(const char *s)
     166        1274 : { return findentry(s, strlen(s), defaults_hash, 0); }
     167             : entree *
     168      318021 : is_entry(const char *s)
     169      318021 : { return findentry(s, strlen(s), functions_hash, 0); }
     170             : entree *
     171     6279125 : fetch_entry_raw(const char *s, long len)
     172     6279125 : { return findentry(s, len, functions_hash, 1); }
     173             : entree *
     174      388881 : fetch_entry(const char *s) { return fetch_entry_raw(s, strlen(s)); }
     175             : 
     176             : /*******************************************************************/
     177             : /*                                                                 */
     178             : /*                  SYNTACTICAL ANALYZER FOR GP                    */
     179             : /*                                                                 */
     180             : /*******************************************************************/
     181             : static GEN
     182        4767 : readseq_i(char *t)
     183             : {
     184        4767 :   if (gp_meta(t,0)) return gnil;
     185        4767 :   return closure_evalres(pari_compile_str(t));
     186             : }
     187             : GEN
     188        4767 : readseq(char *t)
     189        4767 : { pari_sp av = avma; return gerepileupto(av, readseq_i(t)); }
     190             : 
     191             : /* filtered readseq = remove blanks and comments */
     192             : GEN
     193           0 : gp_read_str(const char *s)
     194           0 : { pari_sp av = avma; return gerepileupto(av, readseq_i(gp_filter(s))); }
     195             : 
     196             : GEN
     197       10738 : compile_str(const char *s) { return pari_compile_str(gp_filter(s)); }
     198             : 
     199             : static long
     200     1915158 : check_proto(const char *code)
     201             : {
     202     1915158 :   long arity = 0;
     203     1915158 :   const char *s = code, *old;
     204     1915158 :   if (*s == 'l' || *s == 'v' || *s == 'i' || *s == 'm' || *s == 'u') s++;
     205     9422372 :   while (*s && *s != '\n') switch (*s++)
     206             :   {
     207             :     case '&':
     208             :     case 'C':
     209             :     case 'G':
     210             :     case 'I':
     211             :     case 'J':
     212             :     case 'U':
     213             :     case 'L':
     214             :     case 'M':
     215             :     case 'P':
     216             :     case 'W':
     217             :     case 'f':
     218             :     case 'n':
     219             :     case 'p':
     220             :     case 'b':
     221             :     case 'r':
     222     3553214 :       arity++;
     223     3553214 :       break;
     224             :     case 'E':
     225             :     case 's':
     226      125280 :       if (*s == '*') s++;
     227      125280 :       arity++;
     228      125280 :       break;
     229             :     case 'D':
     230      967758 :       if (*s == 'G' || *s == '&' || *s == 'n' || *s == 'I' || *s == 'E'
     231      435318 :                     || *s == 'V' || *s == 'P' || *s == 's' || *s == 'r')
     232             :       {
     233      566892 :         if (*s != 'V') arity++;
     234      566892 :         s++; break;
     235             :       }
     236      400866 :       old = s; while (*s && *s != ',') s++;
     237      400866 :       if (*s != ',') pari_err(e_SYNTAX, "missing comma", old, code);
     238      400866 :       break;
     239             :     case 'V':
     240             :     case '=':
     241      945804 :     case ',': break;
     242           0 :     case '\n': break; /* Before the mnemonic */
     243             : 
     244             :     case 'm':
     245             :     case 'l':
     246             :     case 'i':
     247           0 :     case 'v': pari_err(e_SYNTAX, "this code has to come first", s-1, code);
     248           0 :     default: pari_err(e_SYNTAX, "unknown parser code", s-1, code);
     249             :   }
     250     1915158 :   if (arity > 20) pari_err_IMPL("functions with more than 20 parameters");
     251     1915158 :   return arity;
     252             : }
     253             : static void
     254           0 : check_name(const char *name)
     255             : {
     256           0 :   const char *s = name;
     257           0 :   if (isalpha((int)*s))
     258           0 :     while (is_keyword_char(*++s)) /* empty */;
     259           0 :   if (*s) pari_err(e_SYNTAX,"not a valid identifier", s, name);
     260           0 : }
     261             : 
     262             : entree *
     263           0 : install(void *f, const char *name, const char *code)
     264             : {
     265           0 :   long arity = check_proto(code);
     266             :   entree *ep;
     267             : 
     268           0 :   check_name(name);
     269           0 :   ep = fetch_entry(name);
     270           0 :   if (ep->valence != EpNEW)
     271             :   {
     272           0 :     if (ep->valence != EpINSTALL)
     273           0 :       pari_err(e_MISC,"[install] identifier '%s' already in use", name);
     274           0 :     pari_warn(warner, "[install] updating '%s' prototype; module not reloaded", name);
     275           0 :     if (ep->code) pari_free((void*)ep->code);
     276             :   }
     277             :   else
     278             :   {
     279           0 :     ep->value = f;
     280           0 :     ep->valence = EpINSTALL;
     281             :   }
     282           0 :   ep->code = pari_strdup(code);
     283           0 :   ep->arity = arity; return ep;
     284             : }
     285             : 
     286             : static void
     287          14 : killep(entree *ep)
     288             : {
     289          14 :   GEN p = (GEN)initial_value(ep);
     290          14 :   freeep(ep);
     291          14 :   *p = 0; /* otherwise pari_var_create won't regenerate it */
     292          14 :   ep->valence = EpNEW;
     293          14 :   ep->value   = NULL;
     294          14 :   ep->pvalue  = NULL;
     295          14 : }
     296             : /* Kill ep, i.e free all memory it references, and reset to initial value */
     297             : void
     298          14 : kill0(const char *e)
     299             : {
     300          14 :   entree *ep = is_entry(e);
     301          14 :   if (!ep || EpSTATIC(ep)) pari_err(e_MISC,"can't kill that");
     302          14 :   killep(ep);
     303          14 : }
     304             : 
     305             : void
     306          42 : addhelp(const char *e, char *s)
     307             : {
     308          42 :   entree *ep = fetch_entry(e);
     309          42 :   void *f = (void *) ep->help;
     310          42 :   ep->help = pari_strdup(s);
     311          42 :   if (f && !EpSTATIC(ep)) pari_free(f);
     312          42 : }
     313             : 
     314             : /*******************************************************************/
     315             : /*                                                                 */
     316             : /*                              PARSER                             */
     317             : /*                                                                 */
     318             : /*******************************************************************/
     319             : 
     320             : #ifdef LONG_IS_64BIT
     321             : static const long MAX_DIGITS  = 19;
     322             : #else
     323             : static const long MAX_DIGITS  = 9;
     324             : #endif
     325             : 
     326             : static const long MAX_XDIGITS = BITS_IN_LONG>>2;
     327             : static const long MAX_BDIGITS = BITS_IN_LONG;
     328             : 
     329             : static int
     330    35468108 : ishex(const char **s)
     331             : {
     332    35468108 :   if (**s == '0' && ((*s)[1] == 'x' || (*s)[1] == 'X' ))
     333             :   {
     334          49 :     *s += 2;
     335          49 :     return 1;
     336             :   }
     337             :   else
     338    35468059 :     return 0;
     339             : }
     340             : 
     341             : static int
     342    35468157 : isbin(const char **s)
     343             : {
     344    35468157 :   if (**s == '0' && ((*s)[1] == 'b' || (*s)[1] == 'B' ))
     345             :   {
     346          49 :     *s += 2;
     347          49 :     return 1;
     348             :   }
     349             :   else
     350    35468108 :     return 0;
     351             : }
     352             : 
     353             : static ulong
     354          38 : bin_number_len(const char *s, long n)
     355             : {
     356          38 :   ulong m = 0;
     357             :   long i;
     358        1494 :   for (i = 0; i < n; i++,s++)
     359        1456 :     m = 2*m + (*s - '0');
     360          38 :   return m;
     361             : }
     362             : 
     363             : static int
     364        1484 : pari_isbdigit(int c)
     365             : {
     366        1484 :   return c=='0' || c=='1';
     367             : }
     368             : 
     369             : static ulong
     370          54 : hex_number_len(const char *s, long n)
     371             : {
     372          54 :   ulong m = 0;
     373             :   long i;
     374         593 :   for(i = 0; i < n; i++, s++)
     375             :   {
     376             :     ulong c;
     377         539 :     if( *s >= '0' && *s <= '9')
     378         455 :       c = *s - '0';
     379          84 :     else if( *s >= 'A' && *s <= 'F')
     380          84 :       c = *s - 'A' + 10;
     381             :     else
     382           0 :       c = *s - 'a' + 10;
     383         539 :     m = 16*m + c;
     384             :   }
     385          54 :   return m;
     386             : }
     387             : 
     388             : static GEN
     389          56 : strtobin_len(const char *s, long n, long B, ulong num(const char *s, long n))
     390             : {
     391          56 :   long i, l = (n+B-1)/B;
     392             :   GEN N, Np;
     393          56 :   N = cgetipos(l+2);
     394          56 :   Np = int_LSW(N);
     395          92 :   for (i=1; i<l; i++, Np = int_nextW(Np))
     396          36 :     uel(Np, 0) = num(s+n-i*B, B);
     397          56 :   uel(Np, 0) = num(s, n-(i-1)*B);
     398          56 :   return int_normalize(N, 0);
     399             : }
     400             : 
     401             : static GEN
     402          56 : binary_read(const char **ps, long B, int is(int), ulong num(const char *s, long n))
     403             : {
     404          56 :   const char *s = *ps;
     405          56 :   while (is((int)**ps)) (*ps)++;
     406          56 :   return strtobin_len(s, *ps-s, B, num);
     407             : }
     408             : 
     409             : static GEN
     410          28 : bin_read(const char **ps)
     411             : {
     412          28 :   return binary_read(ps, MAX_BDIGITS, pari_isbdigit, bin_number_len);
     413             : }
     414             : 
     415             : static GEN
     416          28 : hex_read(const char **ps)
     417             : {
     418          28 :   return binary_read(ps, MAX_XDIGITS, isxdigit, hex_number_len);
     419             : }
     420             : 
     421             : static ulong
     422     3474442 : dec_number_len(const char *s, long B)
     423             : {
     424     3474442 :   ulong m = 0;
     425             :   long n;
     426    52788990 :   for (n = 0; n < B; n++,s++)
     427    49314548 :     m = 10*m + (*s - '0');
     428     3474442 :   return m;
     429             : }
     430             : 
     431             : static GEN
     432      923226 : dec_strtoi_len(const char *s, long n)
     433             : {
     434      923226 :   const long B = MAX_DIGITS;
     435      923226 :   long i, l = (n+B-1)/B;
     436      923226 :   GEN V = cgetg(l+1, t_VECSMALL);
     437     3474442 :   for (i=1; i<l; i++)
     438     2551216 :     uel(V,i) = dec_number_len(s+n-i*B, B);
     439      923226 :   uel(V, i) = dec_number_len(s, n-(i-1)*B);
     440      923226 :   return fromdigitsu(V, powuu(10, B));
     441             : }
     442             : 
     443             : static GEN
     444      923226 : dec_read_more(const char **ps)
     445             : {
     446      923226 :   pari_sp av = avma;
     447      923226 :   const char *s = *ps;
     448      923226 :   while (isdigit((int)**ps)) (*ps)++;
     449      923226 :   return gerepileuptoint(av, dec_strtoi_len(s, *ps-s));
     450             : }
     451             : 
     452             : static ulong
     453     7986696 : number(int *n, const char **s)
     454             : {
     455     7986696 :   ulong m = 0;
     456    40357519 :   for (*n = 0; *n < MAX_DIGITS && isdigit((int)**s); (*n)++,(*s)++)
     457    32370823 :     m = 10*m + (**s - '0');
     458     7986696 :   return m;
     459             : }
     460             : 
     461             : static GEN
     462     7911131 : dec_read(const char **s)
     463             : {
     464             :   int nb;
     465     7911131 :   ulong y  = number(&nb, s);
     466     7911131 :   if (nb < MAX_DIGITS)
     467     6987905 :     return utoi(y);
     468      923226 :   *s -= MAX_DIGITS;
     469      923226 :   return dec_read_more(s);
     470             : }
     471             : 
     472             : static GEN
     473        2594 : real_read_more(GEN y, const char **ps)
     474             : {
     475        2594 :   pari_sp av = avma;
     476        2594 :   const char *s = *ps;
     477        2594 :   GEN z = dec_read(ps);
     478        2594 :   long e = *ps-s;
     479        2594 :   return gerepileuptoint(av, addmulii(z, powuu(10, e), y));
     480             : }
     481             : 
     482             : static long
     483       75565 : exponent(const char **pts)
     484             : {
     485       75565 :   const char *s = *pts;
     486             :   long n;
     487             :   int nb;
     488       75565 :   switch(*++s)
     489             :   {
     490       75425 :     case '-': s++; n = -(long)number(&nb, &s); break;
     491           0 :     case '+': s++; /* Fall through */
     492         140 :     default: n = (long)number(&nb, &s);
     493             :   }
     494       75565 :   *pts = s; return n;
     495             : }
     496             : 
     497             : static GEN
     498         175 : real_0_digits(long n) {
     499         175 :   long b = (n > 0)? (long)(n/LOG10_2): (long)-((-n)/LOG10_2 + 1);
     500         175 :   return real_0_bit(b);
     501             : }
     502             : 
     503             : static GEN
     504       83791 : real_read(pari_sp av, const char **s, GEN y, long prec)
     505             : {
     506       83791 :   long l, n = 0;
     507       83791 :   switch(**s)
     508             :   {
     509           0 :     default: return y; /* integer */
     510             :     case '.':
     511             :     {
     512        9444 :       const char *old = ++*s;
     513        9444 :       if (isalpha((int)**s) || **s=='.')
     514             :       {
     515        1211 :         if (**s == 'E' || **s == 'e') {
     516        1211 :           n = exponent(s);
     517        1211 :           if (!signe(y)) { set_avma(av); return real_0_digits(n); }
     518        1183 :           break;
     519             :         }
     520           0 :         --*s; return y; /* member */
     521             :       }
     522        8233 :       if (isdigit((int)**s)) y = real_read_more(y, s);
     523        8233 :       n = old - *s;
     524        8233 :       if (**s != 'E' && **s != 'e')
     525             :       {
     526        8226 :         if (!signe(y)) { set_avma(av); return real_0(prec); }
     527        7267 :         break;
     528             :       }
     529             :     }
     530             :     /* Fall through */
     531             :     case 'E': case 'e':
     532       74354 :       n += exponent(s);
     533       74354 :       if (!signe(y)) { set_avma(av); return real_0_digits(n); }
     534             :   }
     535       82657 :   l = nbits2prec(bit_accuracy(lgefint(y)));
     536       82657 :   if (l < prec) l = prec; else prec = l;
     537       82657 :   if (!n) return itor(y, prec);
     538       77270 :   incrprec(l);
     539       77270 :   y = itor(y, l);
     540       77270 :   if (n > 0)
     541          63 :     y = mulrr(y, rpowuu(10UL, (ulong)n, l));
     542             :   else
     543       77207 :     y = divrr(y, rpowuu(10UL, (ulong)-n, l));
     544       77270 :   return gerepileuptoleaf(av, rtor(y, prec));
     545             : }
     546             : 
     547             : static GEN
     548     7824802 : int_read(const char **s)
     549             : {
     550             :   GEN y;
     551     7824802 :   if (isbin(s))
     552          28 :     y = bin_read(s);
     553     7824774 :   else if (ishex(s))
     554          28 :     y = hex_read(s);
     555             :   else
     556     7824746 :     y = dec_read(s);
     557     7824802 :   return y;
     558             : }
     559             : 
     560             : GEN
     561     7824802 : strtoi(const char *s) { return int_read(&s); }
     562             : 
     563             : GEN
     564       83791 : strtor(const char *s, long prec)
     565             : {
     566       83791 :   pari_sp av = avma;
     567       83791 :   GEN y = dec_read(&s);
     568       83791 :   y = real_read(av, &s, y, prec);
     569       83791 :   if (typ(y) == t_REAL) return y;
     570           0 :   return gerepileuptoleaf(av, itor(y, prec));
     571             : }
     572             : 
     573             : static void
     574     7706974 : skipdigits(char **lex) {
     575     7706974 :   while (isdigit((int)**lex)) ++*lex;
     576     7706974 : }
     577             : 
     578             : static int
     579     7702727 : skipexponent(char **lex)
     580             : {
     581     7702727 :   char *old=*lex;
     582     7702727 :   if ((**lex=='e' || **lex=='E'))
     583             :   {
     584        1029 :     ++*lex;
     585        1029 :     if ( **lex=='+' || **lex=='-' ) ++*lex;
     586        1029 :     if (!isdigit((int)**lex))
     587             :     {
     588         469 :       *lex=old;
     589         469 :       return KINTEGER;
     590             :     }
     591         560 :     skipdigits(lex);
     592         560 :     return KREAL;
     593             :   }
     594     7701698 :   return KINTEGER;
     595             : }
     596             : 
     597             : static int
     598     7703706 : skipconstante(char **lex)
     599             : {
     600     7703706 :   skipdigits(lex);
     601     7703706 :   if (**lex=='.')
     602             :   {
     603       14978 :     char *old = ++*lex;
     604       14978 :     if (**lex == '.') { --*lex; return KINTEGER; }
     605       13999 :     if (isalpha((int)**lex))
     606             :     {
     607       11291 :       skipexponent(lex);
     608       11291 :       if (*lex == old)
     609             :       {
     610       11256 :         --*lex; /* member */
     611       11256 :         return KINTEGER;
     612             :       }
     613          35 :       return KREAL;
     614             :     }
     615        2708 :     skipdigits(lex);
     616        2708 :     skipexponent(lex);
     617        2708 :     return KREAL;
     618             :   }
     619     7688728 :   return skipexponent(lex);
     620             : }
     621             : 
     622             : static void
     623     1108349 : skipstring(char **lex)
     624             : {
     625     9007726 :   while (**lex)
     626             :   {
     627     7899377 :     while (**lex == '\\') *lex+=2;
     628     7899377 :     if (**lex == '"')
     629             :     {
     630     1108349 :       if ((*lex)[1] != '"') break;
     631           0 :       *lex += 2; continue;
     632             :     }
     633     6791028 :     (*lex)++;
     634             :   }
     635     1108349 : }
     636             : 
     637             : int
     638    29272299 : pari_lex(union token_value *yylval, struct node_loc *yylloc, char **lex)
     639             : {
     640             :   (void) yylval;
     641    29272299 :   yylloc->start=*lex;
     642    29272299 :   if (!**lex)
     643             :   {
     644       98254 :     yylloc->end=*lex;
     645       98254 :     return 0;
     646             :   }
     647    29174045 :   if (isalpha((int)**lex))
     648             :   {
     649      410078 :     while (is_keyword_char(**lex)) ++*lex;
     650      410078 :     yylloc->end=*lex;
     651      410078 :     return KENTRY;
     652             :   }
     653    28763967 :   if (**lex=='"')
     654             :   {
     655     1108349 :     ++*lex;
     656     1108349 :     skipstring(lex);
     657     1108349 :     if (!**lex)
     658           0 :       compile_err("run-away string",*lex-1);
     659     1108349 :     ++*lex;
     660     1108349 :     yylloc->end=*lex;
     661     1108349 :     return KSTRING;
     662             :   }
     663    27655618 :   if (**lex == '.')
     664             :   {
     665             :     int token;
     666       12263 :     if ((*lex)[1]== '.')
     667             :     {
     668        1000 :       *lex+=2; yylloc->end = *lex; return KDOTDOT;
     669             :     }
     670       11263 :     token=skipconstante(lex);
     671       11263 :     if (token==KREAL)
     672             :     {
     673           7 :       yylloc->end = *lex;
     674           7 :       return token;
     675             :     }
     676       11256 :     ++*lex;
     677       11256 :     yylloc->end=*lex;
     678       11256 :     return '.';
     679             :   }
     680    27643355 :   if (isbin((const char**)lex))
     681             :   {
     682          21 :     while (**lex=='0' || **lex=='1') ++*lex;
     683          21 :     return KINTEGER;
     684             :   }
     685    27643334 :   if (ishex((const char**)lex))
     686             :   {
     687          21 :     while (isxdigit((int)**lex)) ++*lex;
     688          21 :     return KINTEGER;
     689             :   }
     690    27643313 :   if (isdigit((int)**lex))
     691             :   {
     692     7692443 :     int token=skipconstante(lex);
     693     7692443 :     yylloc->end = *lex;
     694     7692443 :     return token;
     695             :   }
     696    19950870 :   if ((*lex)[1]=='=')
     697       21758 :     switch (**lex)
     698             :     {
     699             :     case '=':
     700        8431 :       if ((*lex)[2]=='=')
     701         343 :       { *lex+=3; yylloc->end = *lex; return KID; }
     702             :       else
     703        8088 :       { *lex+=2; yylloc->end = *lex; return KEQ; }
     704             :     case '>':
     705          65 :       *lex+=2; yylloc->end = *lex; return KGE;
     706             :     case '<':
     707         170 :       *lex+=2; yylloc->end = *lex; return KLE;
     708             :     case '*':
     709         156 :       *lex+=2; yylloc->end = *lex; return KME;
     710             :     case '/':
     711          35 :       *lex+=2; yylloc->end = *lex; return KDE;
     712             :     case '%':
     713           7 :       if ((*lex)[2]=='=') break;
     714           7 :       *lex+=2; yylloc->end = *lex; return KMODE;
     715             :     case '!':
     716        1736 :       if ((*lex)[2]=='=') break;
     717        1736 :       *lex+=2; yylloc->end = *lex; return KNE;
     718             :     case '\\':
     719           7 :       *lex+=2; yylloc->end = *lex; return KEUCE;
     720             :     case '+':
     721         152 :       *lex+=2; yylloc->end = *lex; return KPE;
     722             :     case '-':
     723          49 :       *lex+=2; yylloc->end = *lex; return KSE;
     724             :     }
     725    19940062 :   if (**lex==')' && (*lex)[1]=='-' && (*lex)[2]=='>')
     726             :   {
     727        3903 :     *lex+=3; yylloc->end = *lex; return KPARROW;
     728             :   }
     729    19936159 :   if (**lex=='-' && (*lex)[1]=='>')
     730             :   {
     731         981 :     *lex+=2; yylloc->end = *lex; return KARROW;
     732             :   }
     733    19935178 :   if (**lex=='<' && (*lex)[1]=='>')
     734             :   {
     735           0 :     *lex+=2; yylloc->end = *lex; return KNE;
     736             :   }
     737    19935178 :   if (**lex=='\\' && (*lex)[1]=='/')
     738          35 :     switch((*lex)[2])
     739             :     {
     740             :     case '=':
     741           7 :       *lex+=3; yylloc->end = *lex; return KDRE;
     742             :     default:
     743          28 :       *lex+=2; yylloc->end = *lex; return KDR;
     744             :     }
     745    19935143 :   if ((*lex)[1]==**lex)
     746     2119010 :     switch (**lex)
     747             :     {
     748             :     case '&':
     749         658 :       *lex+=2; yylloc->end = *lex; return KAND;
     750             :     case '|':
     751         294 :       *lex+=2; yylloc->end = *lex; return KOR;
     752             :     case '+':
     753         133 :       *lex+=2; yylloc->end = *lex; return KPP;
     754             :     case '-':
     755          14 :       *lex+=2; yylloc->end = *lex; return KSS;
     756             :     case '>':
     757          28 :       if ((*lex)[2]=='=') { *lex+=3; yylloc->end = *lex; return KSRE;}
     758          21 :       *lex+=2; yylloc->end = *lex; return KSR;
     759             :     case '<':
     760         112 :       if ((*lex)[2]=='=')
     761           7 :       { *lex+=3; yylloc->end = *lex; return KSLE; }
     762         105 :       *lex+=2; yylloc->end = *lex; return KSL;
     763             :     }
     764    19933904 :   yylloc->end = *lex+1;
     765    19933904 :   return (unsigned char) *(*lex)++;
     766             : }
     767             : 
     768             : /********************************************************************/
     769             : /*                                                                  */
     770             : /*                Formal variables management                       */
     771             : /*                                                                  */
     772             : /********************************************************************/
     773             : static THREAD long max_priority, min_priority;
     774             : static THREAD long max_avail; /* max variable not yet used */
     775             : static THREAD long nvar; /* first GP free variable */
     776             : static hashtable *h_polvar;
     777             : 
     778             : void
     779      221340 : varstate_save(struct pari_varstate *s)
     780             : {
     781      221340 :   s->nvar = nvar;
     782      221340 :   s->max_avail = max_avail;
     783      221340 :   s->max_priority = max_priority;
     784      221340 :   s->min_priority = min_priority;
     785      221340 : }
     786             : 
     787             : static void
     788        8319 : varentries_set(long v, entree *ep)
     789             : {
     790        8319 :   hash_insert(h_polvar, (void*)ep->name, (void*)v);
     791        8319 :   varentries[v] = ep;
     792        8319 : }
     793             : static int
     794        2947 : _given_value(void *E, hashentry *e) { return e->val == E; }
     795             : 
     796             : static void
     797       12428 : varentries_unset(long v)
     798             : {
     799       12428 :   entree *ep = varentries[v];
     800       12428 :   if (ep)
     801             :   {
     802        2947 :     hashentry *e = hash_remove_select(h_polvar, (void*)ep->name, (void*)v,
     803             :         _given_value);
     804        2947 :     if (!e) pari_err_BUG("varentries_unset [unknown var]");
     805        2947 :     varentries[v] = NULL;
     806        2947 :     pari_free(e);
     807        2947 :     if (v <= nvar && ep == is_entry(ep->name))
     808        2940 :     { /* known to the GP interpreter; entree in functions_hash is permanent */
     809        2940 :       GEN p = (GEN)initial_value(ep);
     810        2940 :       if (ep->value == p) { ep->value = NULL; ep->valence = EpNEW; }
     811        2940 :       *p = 0;
     812             :     }
     813             :     else /* from name_var() or a direct pari_var_create() */
     814           7 :       pari_free(ep);
     815             :  }
     816       12428 : }
     817             : static void
     818          84 : varentries_reset(long v, entree *ep)
     819             : {
     820          84 :   varentries_unset(v);
     821          84 :   varentries_set(v, ep);
     822          84 : }
     823             : 
     824             : static void
     825      130678 : var_restore(struct pari_varstate *s)
     826             : {
     827      130678 :   nvar = s->nvar;
     828      130678 :   max_avail = s->max_avail;
     829      130678 :   max_priority = s->max_priority;
     830      130678 :   min_priority = s->min_priority;
     831      130678 : }
     832             : 
     833             : void
     834        9376 : varstate_restore(struct pari_varstate *s)
     835             : {
     836             :   long i;
     837       21699 :   for (i = nvar; i >= s->nvar; i--)
     838             :   {
     839       12323 :     varentries_unset(i);
     840       12323 :     varpriority[i] = -i;
     841             :   }
     842        9397 :   for (i = max_avail+1; i <= s->max_avail; i++)
     843             :   {
     844          21 :     varentries_unset(i);
     845          21 :     varpriority[i] = -i;
     846             :   }
     847        9376 :   var_restore(s);
     848        9376 : }
     849             : 
     850             : void
     851      121318 : pari_set_varstate(long *vp, struct pari_varstate *vs)
     852             : {
     853             :   long i;
     854      121318 :   var_restore(vs);
     855      121133 :   varpriority = (long*)newblock((MAXVARN+2)) + 1;
     856      121368 :   varpriority[-1] = 1-LONG_MAX;
     857      121368 :   for (i = 0; i < max_avail; i++) varpriority[i] = vp[i];
     858      121368 : }
     859             : 
     860             : /* must come before destruction of functions_hash */
     861             : void
     862        1556 : pari_var_close(void)
     863             : {
     864        1556 :   GEN h = hash_values(h_polvar);
     865        1556 :   long i, l = lg(h);
     866        6908 :   for (i = 1; i < l; i++)
     867             :   {
     868        5352 :     long v = h[i];
     869        5352 :     entree *ep = varentries[v];
     870        5352 :     if (ep && ep != is_entry(ep->name)) pari_free(ep);
     871             :   }
     872        1556 :   free((void*)varentries);
     873        1556 :   free((void*)(varpriority-1));
     874        1556 :   hash_destroy(h_polvar);
     875        1556 : }
     876             : 
     877             : void
     878        1566 : pari_var_init(void)
     879             : {
     880             :   long i;
     881        1566 :   varentries = (entree**) pari_calloc((MAXVARN+1)*sizeof(entree*));
     882        1566 :   varpriority = (long*)pari_malloc((MAXVARN+2)*sizeof(long)) + 1;
     883        1566 :   varpriority[-1] = 1-LONG_MAX;
     884        1566 :   h_polvar = hash_create_str(100, 0);
     885        1566 :   nvar = 0; max_avail = MAXVARN;
     886        1566 :   max_priority = min_priority = 0;
     887        1566 :   (void)fetch_user_var("x");
     888        1566 :   (void)fetch_user_var("y");
     889             :   /* initialize so that people can use pol_x(i) directly */
     890        1566 :   for (i = 2; i <= (long)MAXVARN; i++) varpriority[i] = -i;
     891             :   /* reserve varnum 1..9 for static temps with predictable priority wrt x */
     892        1566 :   nvar = 10;
     893        1566 :   min_priority = -MAXVARN;
     894        1566 : }
     895           0 : long pari_var_next(void) { return nvar; }
     896           0 : long pari_var_next_temp(void) { return max_avail; }
     897             : long
     898       29680 : pari_var_create(entree *ep)
     899             : {
     900       29680 :   GEN p = (GEN)initial_value(ep);
     901             :   long v;
     902       29680 :   if (*p) return varn(p);
     903        8235 :   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
     904        8235 :   v = nvar++;
     905             :   /* set p = pol_x(v) */
     906        8235 :   p[0] = evaltyp(t_POL) | _evallg(4);
     907        8235 :   p[1] = evalsigne(1) | evalvarn(v);
     908        8235 :   gel(p,2) = gen_0;
     909        8235 :   gel(p,3) = gen_1;
     910        8235 :   varentries_set(v, ep);
     911        8235 :   varpriority[v]= min_priority--;
     912        8235 :   return v;
     913             : }
     914             : 
     915             : long
     916       81370 : delete_var(void)
     917             : { /* user wants to delete one of his/her/its variables */
     918       81370 :   if (max_avail == MAXVARN) return 0; /* nothing to delete */
     919       81370 :   max_avail++;
     920       81370 :   if      (varpriority[max_avail] == min_priority) min_priority++;
     921       81370 :   else if (varpriority[max_avail] == max_priority) max_priority--;
     922       81370 :   return max_avail+1;
     923             : }
     924             : long
     925       45738 : fetch_var(void)
     926             : {
     927       45738 :   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
     928       45738 :   varpriority[max_avail] = min_priority--;
     929       45738 :   return max_avail--;
     930             : }
     931             : long
     932       39117 : fetch_var_higher(void)
     933             : {
     934       39117 :   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
     935       39118 :   varpriority[max_avail] = ++max_priority;
     936       39118 :   return max_avail--;
     937             : }
     938             : 
     939             : static int
     940          49 : _higher(void *E, hashentry *e)
     941          49 : { long v = (long)e->val; return (varncmp(v, (long)E) < 0); }
     942             : static int
     943          42 : _lower(void *E, hashentry *e)
     944          42 : { long v = (long)e->val; return (varncmp(v, (long)E) > 0); }
     945             : 
     946             : static GEN
     947          84 : var_register(long v, const char *s)
     948             : {
     949          84 :   varentries_reset(v, initep(s, strlen(s)));
     950          84 :   return pol_x(v);
     951             : }
     952             : GEN
     953          77 : varhigher(const char *s, long w)
     954             : {
     955             :   long v;
     956          77 :   if (w >= 0)
     957             :   {
     958          49 :     hashentry *e = hash_select(h_polvar, (void*)s, (void*)w, _higher);
     959          49 :     if (e) return pol_x((long)e->val);
     960             :   }
     961             :   /* no luck: need to create */
     962          63 :   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
     963          63 :   v = nvar++;
     964          63 :   varpriority[v]= ++max_priority;
     965          63 :   return var_register(v, s);
     966             : }
     967             : GEN
     968          28 : varlower(const char *s, long w)
     969             : {
     970             :   long v;
     971          28 :   if (w >= 0)
     972             :   {
     973          21 :     hashentry *e = hash_select(h_polvar, (void*)s, (void*)w, _lower);
     974          21 :     if (e) return pol_x((long)e->val);
     975             :   }
     976             :   /* no luck: need to create */
     977          21 :   v = fetch_var();
     978          21 :   return var_register(v, s);
     979             : }
     980             : 
     981             : long
     982      388783 : fetch_user_var(const char *s)
     983             : {
     984      388783 :   entree *ep = fetch_entry(s);
     985             :   long v;
     986      388783 :   switch (EpVALENCE(ep))
     987             :   {
     988      385483 :     case EpVAR: return varn((GEN)initial_value(ep));
     989        3300 :     case EpNEW: break;
     990           0 :     default: pari_err(e_MISC, "%s already exists with incompatible valence", s);
     991             :   }
     992        3300 :   v = pari_var_create(ep);
     993        3300 :   ep->valence = EpVAR;
     994        3300 :   ep->value = initial_value(ep);
     995        3300 :   return v;
     996             : }
     997             : 
     998             : GEN
     999           7 : fetch_var_value(long v, GEN t)
    1000             : {
    1001           7 :   entree *ep = varentries[v];
    1002           7 :   if (!ep) return NULL;
    1003           7 :   if (t)
    1004             :   {
    1005           7 :     long vn = localvars_find(t,ep);
    1006           7 :     if (vn) return get_lex(vn);
    1007             :   }
    1008           7 :   return (GEN)ep->value;
    1009             : }
    1010             : 
    1011             : void
    1012           0 : name_var(long n, const char *s)
    1013             : {
    1014             :   entree *ep;
    1015             :   char *u;
    1016             : 
    1017           0 :   if (n < pari_var_next())
    1018           0 :     pari_err(e_MISC, "renaming a GP variable is forbidden");
    1019           0 :   if (n > (long)MAXVARN)
    1020           0 :     pari_err_OVERFLOW("variable number");
    1021             : 
    1022           0 :   ep = (entree*)pari_malloc(sizeof(entree) + strlen(s) + 1);
    1023           0 :   u = (char *)initial_value(ep);
    1024           0 :   ep->valence = EpVAR;
    1025           0 :   ep->name = u; strcpy(u,s);
    1026           0 :   ep->value = gen_0; /* in case geval is called */
    1027           0 :   varentries_reset(n, ep);
    1028           0 : }
    1029             : 
    1030             : static int
    1031        5136 : cmp_by_var(void *E,GEN x, GEN y)
    1032        5136 : { (void)E; return varncmp((long)x,(long)y); }
    1033             : GEN
    1034        1029 : vars_sort_inplace(GEN z)
    1035        1029 : { gen_sort_inplace(z,NULL,cmp_by_var,NULL); return z; }
    1036             : GEN
    1037         154 : vars_to_RgXV(GEN h)
    1038             : {
    1039         154 :   long i, l = lg(h);
    1040         154 :   GEN z = cgetg(l, t_VEC);
    1041         154 :   for (i = 1; i < l; i++) gel(z,i) = pol_x(h[i]);
    1042         154 :   return z;
    1043             : }
    1044             : GEN
    1045         987 : gpolvar(GEN x)
    1046             : {
    1047             :   long v;
    1048         987 :   if (!x) {
    1049         140 :     GEN h = hash_values(h_polvar);
    1050         140 :     return vars_to_RgXV(vars_sort_inplace(h));
    1051             :   }
    1052         847 :   if (typ(x)==t_PADIC) return gcopy( gel(x,2) );
    1053         840 :   v = gvar(x);
    1054         840 :   if (v==NO_VARIABLE) return gen_0;
    1055         777 :   return pol_x(v);
    1056             : }
    1057             : 
    1058             : static void
    1059     1935516 : fill_hashtable_single(entree **table, entree *ep)
    1060             : {
    1061     1935516 :   EpSETSTATIC(ep);
    1062     1935516 :   insertep(ep, table, hash_str(ep->name));
    1063     1935516 :   if (ep->code) ep->arity = check_proto(ep->code);
    1064     1935516 :   ep->pvalue = NULL;
    1065     1935516 : }
    1066             : 
    1067             : void
    1068        4688 : pari_fill_hashtable(entree **table, entree *ep)
    1069             : {
    1070        4688 :   for ( ; ep->name; ep++) fill_hashtable_single(table, ep);
    1071        4688 : }
    1072             : 
    1073             : void
    1074           0 : pari_add_function(entree *ep)
    1075             : {
    1076           0 :   fill_hashtable_single(functions_hash, ep);
    1077           0 : }
    1078             : 
    1079             : /********************************************************************/
    1080             : /**                                                                **/
    1081             : /**                        SIMPLE GP FUNCTIONS                     **/
    1082             : /**                                                                **/
    1083             : /********************************************************************/
    1084             : 
    1085             : GEN
    1086          28 : arity0(GEN C)
    1087             : {
    1088          28 :   if (typ(C)!=t_CLOSURE) pari_err_TYPE("arity", C);
    1089          28 :   return utoi(closure_arity(C));
    1090             : }
    1091             : 
    1092             : #define ALIAS(ep) (entree *) ((GEN)ep->value)[1]
    1093             : 
    1094             : entree *
    1095     6182028 : do_alias(entree *ep)
    1096             : {
    1097     6182028 :   while (ep->valence == EpALIAS) ep = ALIAS(ep);
    1098     6182028 :   return ep;
    1099             : }
    1100             : 
    1101             : void
    1102          28 : alias0(const char *s, const char *old)
    1103             : {
    1104             :   entree *ep, *e;
    1105             :   GEN x;
    1106             : 
    1107          28 :   ep = fetch_entry(old);
    1108          28 :   e  = fetch_entry(s);
    1109          28 :   if (EpVALENCE(e) != EpALIAS && EpVALENCE(e) != EpNEW)
    1110           0 :     pari_err(e_MISC,"can't replace an existing symbol by an alias");
    1111          28 :   freeep(e);
    1112          28 :   x = cgetg_block(2, t_VECSMALL); gel(x,1) = (GEN)ep;
    1113          28 :   e->value=x; e->valence=EpALIAS;
    1114          28 : }
    1115             : 
    1116             : GEN
    1117    12856051 : ifpari(GEN g, GEN a/*closure*/, GEN b/*closure*/)
    1118             : {
    1119    12856051 :   if (gequal0(g)) /* false */
    1120     9963001 :     return b? closure_evalgen(b): gnil;
    1121             :   else /* true */
    1122     2893050 :     return a? closure_evalgen(a): gnil;
    1123             : }
    1124             : 
    1125             : void
    1126    40478016 : ifpari_void(GEN g, GEN a/*closure*/, GEN b/*closure*/)
    1127             : {
    1128    40478016 :   if (gequal0(g)) /* false */
    1129    39771608 :   { if (b) closure_evalvoid(b); }
    1130             :   else /* true */
    1131      706408 :   { if (a) closure_evalvoid(a); }
    1132    40477995 : }
    1133             : 
    1134             : GEN
    1135       31283 : ifpari_multi(GEN g, GEN a/*closure*/)
    1136             : {
    1137       31283 :   long i, nb = lg(a)-1;
    1138       31283 :   if (!gequal0(g)) /* false */
    1139        6706 :     return closure_evalgen(gel(a,1));
    1140       42042 :   for(i=2;i<nb;i+=2)
    1141             :   {
    1142       24689 :     GEN g = closure_evalgen(gel(a,i));
    1143       24689 :     if (!g) return g;
    1144       24682 :     if (!gequal0(g))
    1145        7217 :       return closure_evalgen(gel(a,i+1));
    1146             :   }
    1147       17353 :   return i<=nb? closure_evalgen(gel(a,i)): gnil;
    1148             : }
    1149             : 
    1150             : GEN
    1151      268961 : andpari(GEN a, GEN b/*closure*/)
    1152             : {
    1153             :   GEN g;
    1154      268961 :   if (gequal0(a))
    1155       42805 :     return gen_0;
    1156      226156 :   g=closure_evalgen(b);
    1157      226156 :   if (!g) return g;
    1158      226156 :   return gequal0(g)?gen_0:gen_1;
    1159             : }
    1160             : 
    1161             : GEN
    1162    15906723 : orpari(GEN a, GEN b/*closure*/)
    1163             : {
    1164             :   GEN g;
    1165    15906723 :   if (!gequal0(a))
    1166      119538 :     return gen_1;
    1167    15787185 :   g=closure_evalgen(b);
    1168    15787185 :   if (!g) return g;
    1169    15787185 :   return gequal0(g)?gen_0:gen_1;
    1170             : }
    1171             : 
    1172       79960 : GEN gmule(GEN *x, GEN y) { *x = gmul(*x,y); return *x; }
    1173          56 : GEN gdive(GEN *x, GEN y) { *x = gdiv(*x,y); return *x; }
    1174           7 : GEN gdivente(GEN *x, GEN y) { *x = gdivent(*x,y); return *x; }
    1175           7 : GEN gdivrounde(GEN *x, GEN y) { *x = gdivround(*x,y); return *x; }
    1176           7 : GEN gmode(GEN *x, GEN y) { *x = gmod(*x,y); return *x; }
    1177           7 : GEN gshiftle(GEN *x, long n) { *x = gshift(*x,n); return *x; }
    1178           7 : GEN gshiftre(GEN *x, long n) { *x = gshift(*x,-n); return *x; }
    1179      434466 : GEN gadde(GEN *x, GEN y) { *x = gadd(*x,y); return *x; }
    1180    25675489 : GEN gadd1e(GEN *x) { *x = typ(*x)==t_INT?addiu(*x,1):gaddgs(*x,1); return *x; }
    1181    15455356 : GEN gsube(GEN *x, GEN y) { *x = gsub(*x,y); return *x; }
    1182          14 : GEN gsub1e(GEN *x) { *x = typ(*x)==t_INT?subiu(*x,1):gsubgs(*x,1); return *x; }
    1183             : 
    1184        1392 : GEN gshift_right(GEN x, long n) { return gshift(x,-n); }

Generated by: LCOV version 1.13