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.1 lcov report (development 24988-2584e74448) Lines: 573 640 89.5 %
Date: 2020-01-26 05:57:03 Functions: 89 98 90.8 %
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     2096044 : insertep(entree *ep, entree **table, ulong hash)
     123             : {
     124     2096044 :   ep->hash = hash;
     125     2096044 :   hash %= functions_tblsz;
     126     2096044 :   ep->next = table[hash];
     127     2096044 :   table[hash] = ep;
     128     2096044 : }
     129             : 
     130             : static entree *
     131       29001 : initep(const char *name, long len)
     132             : {
     133       29001 :   const long add = 4*sizeof(long);
     134       29001 :   entree *ep = (entree *) pari_calloc(sizeof(entree) + add + len+1);
     135       29001 :   entree *ep1 = initial_value(ep);
     136       29001 :   char *u = (char *) ep1 + add;
     137       29001 :   ep->name    = u; memcpy(u, name,len); u[len]=0;
     138       29001 :   ep->valence = EpNEW;
     139       29001 :   ep->value   = NULL;
     140       29001 :   ep->menu    = 0;
     141       29001 :   ep->code    = NULL;
     142       29001 :   ep->help    = NULL;
     143       29001 :   ep->pvalue  = NULL;
     144       29001 :   ep->arity   = 0;
     145       29001 :   return ep;
     146             : }
     147             : 
     148             : /* Look for s of length len in T; if 'insert', insert if missing */
     149             : static entree *
     150     9829668 : findentry(const char *s, long len, entree **T, int insert)
     151             : {
     152     9829668 :   ulong hash = hash_str_len(s, len);
     153             :   entree *ep;
     154    78486672 :   for (ep = T[hash % functions_tblsz]; ep; ep = ep->next)
     155    78457727 :     if (ep->hash == hash)
     156             :     {
     157     9800744 :       const char *t = ep->name;
     158     9800744 :       if (!strncmp(t, s, len) && !t[len]) return ep;
     159             :     }
     160             :   /* not found */
     161       28945 :   if (insert) { ep = initep(s,len); insertep(ep, T, hash); }
     162       28945 :   return ep;
     163             : }
     164             : entree *
     165        1358 : pari_is_default(const char *s)
     166        1358 : { return findentry(s, strlen(s), defaults_hash, 0); }
     167             : entree *
     168     3656181 : is_entry(const char *s)
     169     3656181 : { return findentry(s, strlen(s), functions_hash, 0); }
     170             : entree *
     171     6172129 : fetch_entry_raw(const char *s, long len)
     172     6172129 : { return findentry(s, len, functions_hash, 1); }
     173             : entree *
     174      390386 : 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        4452 : readseq_i(char *t)
     183             : {
     184        4452 :   if (gp_meta(t,0)) return gnil;
     185        4452 :   return closure_evalres(pari_compile_str(t));
     186             : }
     187             : GEN
     188        4452 : readseq(char *t)
     189        4452 : { 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             : GEN
     200           0 : gp_read_str_bitprec(const char *s, long bitprec)
     201             : {
     202             :   GEN x;
     203           0 :   push_localbitprec(bitprec);
     204           0 :   x = gp_read_str(s);
     205           0 :   pop_localprec();
     206           0 :   return x;
     207             : }
     208             : 
     209             : GEN
     210           0 : gp_read_str_prec(const char *s, long prec)
     211           0 : { return gp_read_str_bitprec(s, prec2nbits(prec)); }
     212             : 
     213             : static long
     214     2045964 : check_proto(const char *code)
     215             : {
     216     2045964 :   long arity = 0;
     217     2045964 :   const char *s = code, *old;
     218     2045964 :   if (*s == 'l' || *s == 'v' || *s == 'i' || *s == 'm' || *s == 'u') s++;
     219    10115840 :   while (*s && *s != '\n') switch (*s++)
     220             :   {
     221             :     case '&':
     222             :     case 'C':
     223             :     case 'G':
     224             :     case 'I':
     225             :     case 'J':
     226             :     case 'U':
     227             :     case 'L':
     228             :     case 'M':
     229             :     case 'P':
     230             :     case 'W':
     231             :     case 'f':
     232             :     case 'n':
     233             :     case 'p':
     234             :     case 'b':
     235             :     case 'r':
     236     3854174 :       arity++;
     237     3854174 :       break;
     238             :     case 'E':
     239             :     case 's':
     240      130320 :       if (*s == '*') s++;
     241      130320 :       arity++;
     242      130320 :       break;
     243             :     case 'D':
     244     1029498 :       if (*s == 'G' || *s == '&' || *s == 'n' || *s == 'I' || *s == 'E'
     245      464235 :                     || *s == 'V' || *s == 'P' || *s == 's' || *s == 'r')
     246             :       {
     247      601101 :         if (*s != 'V') arity++;
     248      601101 :         s++; break;
     249             :       }
     250      428397 :       old = s; while (*s && *s != ',') s++;
     251      428397 :       if (*s != ',') pari_err(e_SYNTAX, "missing comma", old, code);
     252      428397 :       break;
     253             :     case 'V':
     254             :     case '=':
     255     1009920 :     case ',': break;
     256           0 :     case '\n': break; /* Before the mnemonic */
     257             : 
     258             :     case 'm':
     259             :     case 'l':
     260             :     case 'i':
     261           0 :     case 'v': pari_err(e_SYNTAX, "this code has to come first", s-1, code);
     262           0 :     default: pari_err(e_SYNTAX, "unknown parser code", s-1, code);
     263             :   }
     264     2045964 :   if (arity > 20) pari_err_IMPL("functions with more than 20 parameters");
     265     2045964 :   return arity;
     266             : }
     267             : static void
     268           0 : check_name(const char *name)
     269             : {
     270           0 :   const char *s = name;
     271           0 :   if (isalpha((int)*s))
     272           0 :     while (is_keyword_char(*++s)) /* empty */;
     273           0 :   if (*s) pari_err(e_SYNTAX,"not a valid identifier", s, name);
     274           0 : }
     275             : 
     276             : entree *
     277           0 : install(void *f, const char *name, const char *code)
     278             : {
     279           0 :   long arity = check_proto(code);
     280             :   entree *ep;
     281             : 
     282           0 :   check_name(name);
     283           0 :   ep = fetch_entry(name);
     284           0 :   if (ep->valence != EpNEW)
     285             :   {
     286           0 :     if (ep->valence != EpINSTALL)
     287           0 :       pari_err(e_MISC,"[install] identifier '%s' already in use", name);
     288           0 :     pari_warn(warner, "[install] updating '%s' prototype; module not reloaded", name);
     289           0 :     if (ep->code) pari_free((void*)ep->code);
     290             :   }
     291             :   else
     292             :   {
     293           0 :     ep->value = f;
     294           0 :     ep->valence = EpINSTALL;
     295             :   }
     296           0 :   ep->code = pari_strdup(code);
     297           0 :   ep->arity = arity; return ep;
     298             : }
     299             : 
     300             : static void
     301          14 : killep(entree *ep)
     302             : {
     303          14 :   GEN p = (GEN)initial_value(ep);
     304          14 :   freeep(ep);
     305          14 :   *p = 0; /* otherwise pari_var_create won't regenerate it */
     306          14 :   ep->valence = EpNEW;
     307          14 :   ep->value   = NULL;
     308          14 :   ep->pvalue  = NULL;
     309          14 : }
     310             : /* Kill ep, i.e free all memory it references, and reset to initial value */
     311             : void
     312          14 : kill0(const char *e)
     313             : {
     314          14 :   entree *ep = is_entry(e);
     315          14 :   if (!ep || EpSTATIC(ep)) pari_err(e_MISC,"can't kill that");
     316          14 :   killep(ep);
     317          14 : }
     318             : 
     319             : void
     320          42 : addhelp(const char *e, char *s)
     321             : {
     322          42 :   entree *ep = fetch_entry(e);
     323          42 :   void *f = (void *) ep->help;
     324          42 :   ep->help = pari_strdup(s);
     325          42 :   if (f && !EpSTATIC(ep)) pari_free(f);
     326          42 : }
     327             : 
     328             : /*******************************************************************/
     329             : /*                                                                 */
     330             : /*                              PARSER                             */
     331             : /*                                                                 */
     332             : /*******************************************************************/
     333             : 
     334             : #ifdef LONG_IS_64BIT
     335             : static const long MAX_DIGITS  = 19;
     336             : #else
     337             : static const long MAX_DIGITS  = 9;
     338             : #endif
     339             : 
     340             : static const long MAX_XDIGITS = BITS_IN_LONG>>2;
     341             : static const long MAX_BDIGITS = BITS_IN_LONG;
     342             : 
     343             : static int
     344    34874961 : ishex(const char **s)
     345             : {
     346    34874961 :   if (**s == '0' && ((*s)[1] == 'x' || (*s)[1] == 'X' ))
     347             :   {
     348         106 :     *s += 2;
     349         106 :     return 1;
     350             :   }
     351             :   else
     352    34874855 :     return 0;
     353             : }
     354             : 
     355             : static int
     356    34875010 : isbin(const char **s)
     357             : {
     358    34875010 :   if (**s == '0' && ((*s)[1] == 'b' || (*s)[1] == 'B' ))
     359             :   {
     360          49 :     *s += 2;
     361          49 :     return 1;
     362             :   }
     363             :   else
     364    34874961 :     return 0;
     365             : }
     366             : 
     367             : static ulong
     368          38 : bin_number_len(const char *s, long n)
     369             : {
     370          38 :   ulong m = 0;
     371             :   long i;
     372        1494 :   for (i = 0; i < n; i++,s++)
     373        1456 :     m = 2*m + (*s - '0');
     374          38 :   return m;
     375             : }
     376             : 
     377             : static int
     378        1484 : pari_isbdigit(int c)
     379             : {
     380        1484 :   return c=='0' || c=='1';
     381             : }
     382             : 
     383             : static ulong
     384          96 : hex_number_len(const char *s, long n)
     385             : {
     386          96 :   ulong m = 0;
     387             :   long i;
     388        1211 :   for(i = 0; i < n; i++, s++)
     389             :   {
     390             :     ulong c;
     391        1115 :     if( *s >= '0' && *s <= '9')
     392         597 :       c = *s - '0';
     393         518 :     else if( *s >= 'A' && *s <= 'F')
     394          84 :       c = *s - 'A' + 10;
     395             :     else
     396         434 :       c = *s - 'a' + 10;
     397        1115 :     m = 16*m + c;
     398             :   }
     399          96 :   return m;
     400             : }
     401             : 
     402             : static GEN
     403          92 : strtobin_len(const char *s, long n, long B, ulong num(const char *s, long n))
     404             : {
     405          92 :   long i, l = (n+B-1)/B;
     406             :   GEN N, Np;
     407          92 :   N = cgetipos(l+2);
     408          92 :   Np = int_LSW(N);
     409         134 :   for (i=1; i<l; i++, Np = int_nextW(Np))
     410          42 :     uel(Np, 0) = num(s+n-i*B, B);
     411          92 :   uel(Np, 0) = num(s, n-(i-1)*B);
     412          92 :   return int_normalize(N, 0);
     413             : }
     414             : 
     415             : static GEN
     416          92 : binary_read(const char **ps, long B, int is(int), ulong num(const char *s, long n))
     417             : {
     418          92 :   const char *s = *ps;
     419          92 :   while (is((int)**ps)) (*ps)++;
     420          92 :   return strtobin_len(s, *ps-s, B, num);
     421             : }
     422             : 
     423             : static GEN
     424          28 : bin_read(const char **ps)
     425             : {
     426          28 :   return binary_read(ps, MAX_BDIGITS, pari_isbdigit, bin_number_len);
     427             : }
     428             : 
     429             : static GEN
     430          64 : hex_read(const char **ps)
     431             : {
     432          64 :   return binary_read(ps, MAX_XDIGITS, isxdigit, hex_number_len);
     433             : }
     434             : 
     435             : static ulong
     436     2655486 : dec_number_len(const char *s, long B)
     437             : {
     438     2655486 :   ulong m = 0;
     439             :   long n;
     440    40583101 :   for (n = 0; n < B; n++,s++)
     441    37927615 :     m = 10*m + (*s - '0');
     442     2655486 :   return m;
     443             : }
     444             : 
     445             : static GEN
     446      679194 : dec_strtoi_len(const char *s, long n)
     447             : {
     448      679194 :   const long B = MAX_DIGITS;
     449      679194 :   long i, l = (n+B-1)/B;
     450      679194 :   GEN V = cgetg(l+1, t_VECSMALL);
     451     2655486 :   for (i=1; i<l; i++)
     452     1976292 :     uel(V,i) = dec_number_len(s+n-i*B, B);
     453      679194 :   uel(V, i) = dec_number_len(s, n-(i-1)*B);
     454      679194 :   return fromdigitsu(V, powuu(10, B));
     455             : }
     456             : 
     457             : static GEN
     458      679194 : dec_read_more(const char **ps)
     459             : {
     460      679194 :   pari_sp av = avma;
     461      679194 :   const char *s = *ps;
     462      679194 :   while (isdigit((int)**ps)) (*ps)++;
     463      679194 :   return gerepileuptoint(av, dec_strtoi_len(s, *ps-s));
     464             : }
     465             : 
     466             : static ulong
     467     7744155 : number(int *n, const char **s)
     468             : {
     469     7744155 :   ulong m = 0;
     470    35141928 :   for (*n = 0; *n < MAX_DIGITS && isdigit((int)**s); (*n)++,(*s)++)
     471    27397773 :     m = 10*m + (**s - '0');
     472     7744155 :   return m;
     473             : }
     474             : 
     475             : static GEN
     476     7668590 : dec_read(const char **s)
     477             : {
     478             :   int nb;
     479     7668590 :   ulong y  = number(&nb, s);
     480     7668590 :   if (nb < MAX_DIGITS)
     481     6989396 :     return utoi(y);
     482      679194 :   *s -= MAX_DIGITS;
     483      679194 :   return dec_read_more(s);
     484             : }
     485             : 
     486             : static GEN
     487        2594 : real_read_more(GEN y, const char **ps)
     488             : {
     489        2594 :   pari_sp av = avma;
     490        2594 :   const char *s = *ps;
     491        2594 :   GEN z = dec_read(ps);
     492        2594 :   long e = *ps-s;
     493        2594 :   return gerepileuptoint(av, addmulii(z, powuu(10, e), y));
     494             : }
     495             : 
     496             : static long
     497       75565 : exponent(const char **pts)
     498             : {
     499       75565 :   const char *s = *pts;
     500             :   long n;
     501             :   int nb;
     502       75565 :   switch(*++s)
     503             :   {
     504       75425 :     case '-': s++; n = -(long)number(&nb, &s); break;
     505           0 :     case '+': s++; /* Fall through */
     506         140 :     default: n = (long)number(&nb, &s);
     507             :   }
     508       75565 :   *pts = s; return n;
     509             : }
     510             : 
     511             : static GEN
     512         175 : real_0_digits(long n) {
     513         175 :   long b = (n > 0)? (long)(n/LOG10_2): (long)-((-n)/LOG10_2 + 1);
     514         175 :   return real_0_bit(b);
     515             : }
     516             : 
     517             : static GEN
     518       84239 : real_read(pari_sp av, const char **s, GEN y, long prec)
     519             : {
     520       84239 :   long l, n = 0;
     521       84239 :   switch(**s)
     522             :   {
     523           0 :     default: return y; /* integer */
     524             :     case '.':
     525             :     {
     526        9892 :       const char *old = ++*s;
     527        9892 :       if (isalpha((int)**s) || **s=='.')
     528             :       {
     529        1211 :         if (**s == 'E' || **s == 'e') {
     530        1211 :           n = exponent(s);
     531        1211 :           if (!signe(y)) { set_avma(av); return real_0_digits(n); }
     532        1183 :           break;
     533             :         }
     534           0 :         --*s; return y; /* member */
     535             :       }
     536        8681 :       if (isdigit((int)**s)) y = real_read_more(y, s);
     537        8681 :       n = old - *s;
     538        8681 :       if (**s != 'E' && **s != 'e')
     539             :       {
     540        8674 :         if (!signe(y)) { set_avma(av); return real_0(prec); }
     541        7701 :         break;
     542             :       }
     543             :     }
     544             :     /* Fall through */
     545             :     case 'E': case 'e':
     546       74354 :       n += exponent(s);
     547       74354 :       if (!signe(y)) { set_avma(av); return real_0_digits(n); }
     548             :   }
     549       83091 :   l = nbits2prec(bit_accuracy(lgefint(y)));
     550       83091 :   if (l < prec) l = prec; else prec = l;
     551       83091 :   if (!n) return itor(y, prec);
     552       77270 :   incrprec(l);
     553       77270 :   y = itor(y, l);
     554       77270 :   if (n > 0)
     555          63 :     y = mulrr(y, rpowuu(10UL, (ulong)n, l));
     556             :   else
     557       77207 :     y = divrr(y, rpowuu(10UL, (ulong)-n, l));
     558       77270 :   return gerepileuptoleaf(av, rtor(y, prec));
     559             : }
     560             : 
     561             : static GEN
     562     7581849 : int_read(const char **s)
     563             : {
     564             :   GEN y;
     565     7581849 :   if (isbin(s))
     566          28 :     y = bin_read(s);
     567     7581821 :   else if (ishex(s))
     568          64 :     y = hex_read(s);
     569             :   else
     570     7581757 :     y = dec_read(s);
     571     7581849 :   return y;
     572             : }
     573             : 
     574             : GEN
     575     7581849 : strtoi(const char *s) { return int_read(&s); }
     576             : 
     577             : GEN
     578       84239 : strtor(const char *s, long prec)
     579             : {
     580       84239 :   pari_sp av = avma;
     581       84239 :   GEN y = dec_read(&s);
     582       84239 :   y = real_read(av, &s, y, prec);
     583       84239 :   if (typ(y) == t_REAL) return y;
     584           0 :   return gerepileuptoleaf(av, itor(y, prec));
     585             : }
     586             : 
     587             : static void
     588     7589238 : skipdigits(char **lex) {
     589     7589238 :   while (isdigit((int)**lex)) ++*lex;
     590     7589238 : }
     591             : 
     592             : static int
     593     7584928 : skipexponent(char **lex)
     594             : {
     595     7584928 :   char *old=*lex;
     596     7584928 :   if ((**lex=='e' || **lex=='E'))
     597             :   {
     598        1029 :     ++*lex;
     599        1029 :     if ( **lex=='+' || **lex=='-' ) ++*lex;
     600        1029 :     if (!isdigit((int)**lex))
     601             :     {
     602         469 :       *lex=old;
     603         469 :       return KINTEGER;
     604             :     }
     605         560 :     skipdigits(lex);
     606         560 :     return KREAL;
     607             :   }
     608     7583899 :   return KINTEGER;
     609             : }
     610             : 
     611             : static int
     612     7585928 : skipconstante(char **lex)
     613             : {
     614     7585928 :   skipdigits(lex);
     615     7585928 :   if (**lex=='.')
     616             :   {
     617       15125 :     char *old = ++*lex;
     618       15125 :     if (**lex == '.') { --*lex; return KINTEGER; }
     619       14125 :     if (isalpha((int)**lex))
     620             :     {
     621       11375 :       skipexponent(lex);
     622       11375 :       if (*lex == old)
     623             :       {
     624       11340 :         --*lex; /* member */
     625       11340 :         return KINTEGER;
     626             :       }
     627          35 :       return KREAL;
     628             :     }
     629        2750 :     skipdigits(lex);
     630        2750 :     skipexponent(lex);
     631        2750 :     return KREAL;
     632             :   }
     633     7570803 :   return skipexponent(lex);
     634             : }
     635             : 
     636             : static void
     637     1108209 : skipstring(char **lex)
     638             : {
     639     9009056 :   while (**lex)
     640             :   {
     641     7900847 :     while (**lex == '\\') *lex+=2;
     642     7900847 :     if (**lex == '"')
     643             :     {
     644     1108209 :       if ((*lex)[1] != '"') break;
     645           0 :       *lex += 2; continue;
     646             :     }
     647     6792638 :     (*lex)++;
     648             :   }
     649     1108209 : }
     650             : 
     651             : int
     652    28944229 : pari_lex(union token_value *yylval, struct node_loc *yylloc, char **lex)
     653             : {
     654             :   (void) yylval;
     655    28944229 :   yylloc->start=*lex;
     656    28944229 :   if (!**lex)
     657             :   {
     658      102103 :     yylloc->end=*lex;
     659      102103 :     return 0;
     660             :   }
     661    28842126 :   if (isalpha((int)**lex))
     662             :   {
     663      428388 :     while (is_keyword_char(**lex)) ++*lex;
     664      428388 :     yylloc->end=*lex;
     665      428388 :     return KENTRY;
     666             :   }
     667    28413738 :   if (**lex=='"')
     668             :   {
     669     1108209 :     ++*lex;
     670     1108209 :     skipstring(lex);
     671     1108209 :     if (!**lex)
     672           0 :       compile_err("run-away string",*lex-1);
     673     1108209 :     ++*lex;
     674     1108209 :     yylloc->end=*lex;
     675     1108209 :     return KSTRING;
     676             :   }
     677    27305529 :   if (**lex == '.')
     678             :   {
     679             :     int token;
     680       12368 :     if ((*lex)[1]== '.')
     681             :     {
     682        1021 :       *lex+=2; yylloc->end = *lex; return KDOTDOT;
     683             :     }
     684       11347 :     token=skipconstante(lex);
     685       11347 :     if (token==KREAL)
     686             :     {
     687           7 :       yylloc->end = *lex;
     688           7 :       return token;
     689             :     }
     690       11340 :     ++*lex;
     691       11340 :     yylloc->end=*lex;
     692       11340 :     return '.';
     693             :   }
     694    27293161 :   if (isbin((const char**)lex))
     695             :   {
     696          21 :     while (**lex=='0' || **lex=='1') ++*lex;
     697          21 :     return KINTEGER;
     698             :   }
     699    27293140 :   if (ishex((const char**)lex))
     700             :   {
     701          42 :     while (isxdigit((int)**lex)) ++*lex;
     702          42 :     return KINTEGER;
     703             :   }
     704    27293098 :   if (isdigit((int)**lex))
     705             :   {
     706     7574581 :     int token=skipconstante(lex);
     707     7574581 :     yylloc->end = *lex;
     708     7574581 :     return token;
     709             :   }
     710    19718517 :   if ((*lex)[1]=='=')
     711       22185 :     switch (**lex)
     712             :     {
     713             :     case '=':
     714        8564 :       if ((*lex)[2]=='=')
     715         343 :       { *lex+=3; yylloc->end = *lex; return KID; }
     716             :       else
     717        8221 :       { *lex+=2; yylloc->end = *lex; return KEQ; }
     718             :     case '>':
     719          65 :       *lex+=2; yylloc->end = *lex; return KGE;
     720             :     case '<':
     721         184 :       *lex+=2; yylloc->end = *lex; return KLE;
     722             :     case '*':
     723         156 :       *lex+=2; yylloc->end = *lex; return KME;
     724             :     case '/':
     725          35 :       *lex+=2; yylloc->end = *lex; return KDE;
     726             :     case '%':
     727           7 :       if ((*lex)[2]=='=') break;
     728           7 :       *lex+=2; yylloc->end = *lex; return KMODE;
     729             :     case '!':
     730        1813 :       if ((*lex)[2]=='=') break;
     731        1813 :       *lex+=2; yylloc->end = *lex; return KNE;
     732             :     case '\\':
     733           7 :       *lex+=2; yylloc->end = *lex; return KEUCE;
     734             :     case '+':
     735         152 :       *lex+=2; yylloc->end = *lex; return KPE;
     736             :     case '-':
     737          49 :       *lex+=2; yylloc->end = *lex; return KSE;
     738             :     }
     739    19707485 :   if (**lex==')' && (*lex)[1]=='-' && (*lex)[2]=='>')
     740             :   {
     741        3952 :     *lex+=3; yylloc->end = *lex; return KPARROW;
     742             :   }
     743    19703533 :   if (**lex=='-' && (*lex)[1]=='>')
     744             :   {
     745        1079 :     *lex+=2; yylloc->end = *lex; return KARROW;
     746             :   }
     747    19702454 :   if (**lex=='<' && (*lex)[1]=='>')
     748             :   {
     749           0 :     *lex+=2; yylloc->end = *lex; return KNE;
     750             :   }
     751    19702454 :   if (**lex=='\\' && (*lex)[1]=='/')
     752          35 :     switch((*lex)[2])
     753             :     {
     754             :     case '=':
     755           7 :       *lex+=3; yylloc->end = *lex; return KDRE;
     756             :     default:
     757          28 :       *lex+=2; yylloc->end = *lex; return KDR;
     758             :     }
     759    19702419 :   if ((*lex)[1]==**lex)
     760     2119789 :     switch (**lex)
     761             :     {
     762             :     case '&':
     763         686 :       *lex+=2; yylloc->end = *lex; return KAND;
     764             :     case '|':
     765         315 :       *lex+=2; yylloc->end = *lex; return KOR;
     766             :     case '+':
     767         133 :       *lex+=2; yylloc->end = *lex; return KPP;
     768             :     case '-':
     769          14 :       *lex+=2; yylloc->end = *lex; return KSS;
     770             :     case '>':
     771          28 :       if ((*lex)[2]=='=') { *lex+=3; yylloc->end = *lex; return KSRE;}
     772          21 :       *lex+=2; yylloc->end = *lex; return KSR;
     773             :     case '<':
     774         112 :       if ((*lex)[2]=='=')
     775           7 :       { *lex+=3; yylloc->end = *lex; return KSLE; }
     776         105 :       *lex+=2; yylloc->end = *lex; return KSL;
     777             :     }
     778    19701131 :   yylloc->end = *lex+1;
     779    19701131 :   return (unsigned char) *(*lex)++;
     780             : }
     781             : 
     782             : /********************************************************************/
     783             : /*                                                                  */
     784             : /*                Formal variables management                       */
     785             : /*                                                                  */
     786             : /********************************************************************/
     787             : static THREAD long max_priority, min_priority;
     788             : static THREAD long max_avail; /* max variable not yet used */
     789             : static THREAD long nvar; /* first GP free variable */
     790             : static hashtable *h_polvar;
     791             : 
     792             : void
     793      347256 : varstate_save(struct pari_varstate *s)
     794             : {
     795      347256 :   s->nvar = nvar;
     796      347256 :   s->max_avail = max_avail;
     797      347256 :   s->max_priority = max_priority;
     798      347256 :   s->min_priority = min_priority;
     799      347256 : }
     800             : 
     801             : static void
     802        8515 : varentries_set(long v, entree *ep)
     803             : {
     804        8515 :   hash_insert(h_polvar, (void*)ep->name, (void*)v);
     805        8515 :   varentries[v] = ep;
     806        8515 : }
     807             : static int
     808        2926 : _given_value(void *E, hashentry *e) { return e->val == E; }
     809             : 
     810             : static void
     811       12785 : varentries_unset(long v)
     812             : {
     813       12785 :   entree *ep = varentries[v];
     814       12785 :   if (ep)
     815             :   {
     816        2926 :     hashentry *e = hash_remove_select(h_polvar, (void*)ep->name, (void*)v,
     817             :         _given_value);
     818        2926 :     if (!e) pari_err_BUG("varentries_unset [unknown var]");
     819        2926 :     varentries[v] = NULL;
     820        2926 :     pari_free(e);
     821        2926 :     if (v <= nvar && ep == is_entry(ep->name))
     822        2919 :     { /* known to the GP interpreter; entree in functions_hash is permanent */
     823        2919 :       GEN p = (GEN)initial_value(ep);
     824        2919 :       if (ep->value == p) { ep->value = NULL; ep->valence = EpNEW; }
     825        2919 :       *p = 0;
     826             :     }
     827             :     else /* from name_var() or a direct pari_var_create() */
     828           7 :       pari_free(ep);
     829             :  }
     830       12785 : }
     831             : static void
     832          98 : varentries_reset(long v, entree *ep)
     833             : {
     834          98 :   varentries_unset(v);
     835          98 :   varentries_set(v, ep);
     836          98 : }
     837             : 
     838             : static void
     839      249636 : var_restore(struct pari_varstate *s)
     840             : {
     841      249636 :   nvar = s->nvar;
     842      249636 :   max_avail = s->max_avail;
     843      249636 :   max_priority = s->max_priority;
     844      249636 :   min_priority = s->min_priority;
     845      249636 : }
     846             : 
     847             : void
     848        9740 : varstate_restore(struct pari_varstate *s)
     849             : {
     850             :   long i;
     851       22406 :   for (i = nvar; i >= s->nvar; i--)
     852             :   {
     853       12666 :     varentries_unset(i);
     854       12666 :     varpriority[i] = -i;
     855             :   }
     856        9761 :   for (i = max_avail+1; i <= s->max_avail; i++)
     857             :   {
     858          21 :     varentries_unset(i);
     859          21 :     varpriority[i] = -i;
     860             :   }
     861        9740 :   var_restore(s);
     862        9740 : }
     863             : 
     864             : void
     865      239908 : pari_set_varstate(long *vp, struct pari_varstate *vs)
     866             : {
     867             :   long i;
     868      239908 :   var_restore(vs);
     869      239603 :   varpriority = (long*)newblock((MAXVARN+2)) + 1;
     870      241992 :   varpriority[-1] = 1-LONG_MAX;
     871      241992 :   for (i = 0; i < max_avail; i++) varpriority[i] = vp[i];
     872      241992 : }
     873             : 
     874             : /* must come before destruction of functions_hash */
     875             : void
     876        1619 : pari_var_close(void)
     877             : {
     878        1619 :   GEN h = hash_values(h_polvar);
     879        1619 :   long i, l = lg(h);
     880        7188 :   for (i = 1; i < l; i++)
     881             :   {
     882        5569 :     long v = h[i];
     883        5569 :     entree *ep = varentries[v];
     884        5569 :     if (ep && ep != is_entry(ep->name)) pari_free(ep);
     885             :   }
     886        1619 :   free((void*)varentries);
     887        1619 :   free((void*)(varpriority-1));
     888        1619 :   hash_destroy(h_polvar);
     889        1619 : }
     890             : 
     891             : void
     892        1629 : pari_var_init(void)
     893             : {
     894             :   long i;
     895        1629 :   varentries = (entree**) pari_calloc((MAXVARN+1)*sizeof(entree*));
     896        1629 :   varpriority = (long*)pari_malloc((MAXVARN+2)*sizeof(long)) + 1;
     897        1629 :   varpriority[-1] = 1-LONG_MAX;
     898        1629 :   h_polvar = hash_create_str(100, 0);
     899        1629 :   nvar = 0; max_avail = MAXVARN;
     900        1629 :   max_priority = min_priority = 0;
     901        1629 :   (void)fetch_user_var("x");
     902        1629 :   (void)fetch_user_var("y");
     903             :   /* initialize so that people can use pol_x(i) directly */
     904        1629 :   for (i = 2; i <= (long)MAXVARN; i++) varpriority[i] = -i;
     905             :   /* reserve varnum 1..9 for static temps with predictable priority wrt x */
     906        1629 :   nvar = 10;
     907        1629 :   min_priority = -MAXVARN;
     908        1629 : }
     909           0 : long pari_var_next(void) { return nvar; }
     910           0 : long pari_var_next_temp(void) { return max_avail; }
     911             : long
     912       33947 : pari_var_create(entree *ep)
     913             : {
     914       33947 :   GEN p = (GEN)initial_value(ep);
     915             :   long v;
     916       33947 :   if (*p) return varn(p);
     917        8417 :   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
     918        8417 :   v = nvar++;
     919             :   /* set p = pol_x(v) */
     920        8417 :   p[0] = evaltyp(t_POL) | _evallg(4);
     921        8417 :   p[1] = evalsigne(1) | evalvarn(v);
     922        8417 :   gel(p,2) = gen_0;
     923        8417 :   gel(p,3) = gen_1;
     924        8417 :   varentries_set(v, ep);
     925        8417 :   varpriority[v]= min_priority--;
     926        8417 :   return v;
     927             : }
     928             : 
     929             : long
     930       83928 : delete_var(void)
     931             : { /* user wants to delete one of his/her/its variables */
     932       83928 :   if (max_avail == MAXVARN) return 0; /* nothing to delete */
     933       83928 :   max_avail++;
     934       83928 :   if      (varpriority[max_avail] == min_priority) min_priority++;
     935       83928 :   else if (varpriority[max_avail] == max_priority) max_priority--;
     936       83928 :   return max_avail+1;
     937             : }
     938             : long
     939       48496 : fetch_var(void)
     940             : {
     941       48496 :   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
     942       48496 :   varpriority[max_avail] = min_priority--;
     943       48496 :   return max_avail--;
     944             : }
     945             : long
     946       38918 : fetch_var_higher(void)
     947             : {
     948       38918 :   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
     949       38918 :   varpriority[max_avail] = ++max_priority;
     950       38918 :   return max_avail--;
     951             : }
     952             : 
     953             : static int
     954          49 : _higher(void *E, hashentry *e)
     955          49 : { long v = (long)e->val; return (varncmp(v, (long)E) < 0); }
     956             : static int
     957          42 : _lower(void *E, hashentry *e)
     958          42 : { long v = (long)e->val; return (varncmp(v, (long)E) > 0); }
     959             : 
     960             : static GEN
     961          98 : var_register(long v, const char *s)
     962             : {
     963          98 :   varentries_reset(v, initep(s, strlen(s)));
     964          98 :   return pol_x(v);
     965             : }
     966             : GEN
     967          91 : varhigher(const char *s, long w)
     968             : {
     969             :   long v;
     970          91 :   if (w >= 0)
     971             :   {
     972          49 :     hashentry *e = hash_select(h_polvar, (void*)s, (void*)w, _higher);
     973          49 :     if (e) return pol_x((long)e->val);
     974             :   }
     975             :   /* no luck: need to create */
     976          77 :   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
     977          77 :   v = nvar++;
     978          77 :   varpriority[v]= ++max_priority;
     979          77 :   return var_register(v, s);
     980             : }
     981             : GEN
     982          28 : varlower(const char *s, long w)
     983             : {
     984             :   long v;
     985          28 :   if (w >= 0)
     986             :   {
     987          21 :     hashentry *e = hash_select(h_polvar, (void*)s, (void*)w, _lower);
     988          21 :     if (e) return pol_x((long)e->val);
     989             :   }
     990             :   /* no luck: need to create */
     991          21 :   v = fetch_var();
     992          21 :   return var_register(v, s);
     993             : }
     994             : 
     995             : long
     996      390288 : fetch_user_var(const char *s)
     997             : {
     998      390288 :   entree *ep = fetch_entry(s);
     999             :   long v;
    1000      390288 :   switch (EpVALENCE(ep))
    1001             :   {
    1002      386848 :     case EpVAR: return varn((GEN)initial_value(ep));
    1003        3440 :     case EpNEW: break;
    1004           0 :     default: pari_err(e_MISC, "%s already exists with incompatible valence", s);
    1005             :   }
    1006        3440 :   v = pari_var_create(ep);
    1007        3440 :   ep->valence = EpVAR;
    1008        3440 :   ep->value = initial_value(ep);
    1009        3440 :   return v;
    1010             : }
    1011             : 
    1012             : GEN
    1013           7 : fetch_var_value(long v, GEN t)
    1014             : {
    1015           7 :   entree *ep = varentries[v];
    1016           7 :   if (!ep) return NULL;
    1017           7 :   if (t)
    1018             :   {
    1019           7 :     long vn = localvars_find(t,ep);
    1020           7 :     if (vn) return get_lex(vn);
    1021             :   }
    1022           7 :   return (GEN)ep->value;
    1023             : }
    1024             : 
    1025             : void
    1026           0 : name_var(long n, const char *s)
    1027             : {
    1028             :   entree *ep;
    1029             :   char *u;
    1030             : 
    1031           0 :   if (n < pari_var_next())
    1032           0 :     pari_err(e_MISC, "renaming a GP variable is forbidden");
    1033           0 :   if (n > (long)MAXVARN)
    1034           0 :     pari_err_OVERFLOW("variable number");
    1035             : 
    1036           0 :   ep = (entree*)pari_malloc(sizeof(entree) + strlen(s) + 1);
    1037           0 :   u = (char *)initial_value(ep);
    1038           0 :   ep->valence = EpVAR;
    1039           0 :   ep->name = u; strcpy(u,s);
    1040           0 :   ep->value = gen_0; /* in case geval is called */
    1041           0 :   varentries_reset(n, ep);
    1042           0 : }
    1043             : 
    1044             : static int
    1045        5136 : cmp_by_var(void *E,GEN x, GEN y)
    1046        5136 : { (void)E; return varncmp((long)x,(long)y); }
    1047             : GEN
    1048        1106 : vars_sort_inplace(GEN z)
    1049        1106 : { gen_sort_inplace(z,NULL,cmp_by_var,NULL); return z; }
    1050             : GEN
    1051         147 : vars_to_RgXV(GEN h)
    1052             : {
    1053         147 :   long i, l = lg(h);
    1054         147 :   GEN z = cgetg(l, t_VEC);
    1055         147 :   for (i = 1; i < l; i++) gel(z,i) = pol_x(h[i]);
    1056         147 :   return z;
    1057             : }
    1058             : GEN
    1059        1169 : gpolvar(GEN x)
    1060             : {
    1061             :   long v;
    1062        1169 :   if (!x) {
    1063         140 :     GEN h = hash_values(h_polvar);
    1064         140 :     return vars_to_RgXV(vars_sort_inplace(h));
    1065             :   }
    1066        1029 :   if (typ(x)==t_PADIC) return gcopy( gel(x,2) );
    1067        1022 :   v = gvar(x);
    1068        1022 :   if (v==NO_VARIABLE) return gen_0;
    1069         966 :   return pol_x(v);
    1070             : }
    1071             : 
    1072             : static void
    1073     2067141 : fill_hashtable_single(entree **table, entree *ep)
    1074             : {
    1075     2067141 :   EpSETSTATIC(ep);
    1076     2067141 :   insertep(ep, table, hash_str(ep->name));
    1077     2067141 :   if (ep->code) ep->arity = check_proto(ep->code);
    1078     2067141 :   ep->pvalue = NULL;
    1079     2067141 : }
    1080             : 
    1081             : void
    1082        4877 : pari_fill_hashtable(entree **table, entree *ep)
    1083             : {
    1084        4877 :   for ( ; ep->name; ep++) fill_hashtable_single(table, ep);
    1085        4877 : }
    1086             : 
    1087             : void
    1088           0 : pari_add_function(entree *ep)
    1089             : {
    1090           0 :   fill_hashtable_single(functions_hash, ep);
    1091           0 : }
    1092             : 
    1093             : /********************************************************************/
    1094             : /**                                                                **/
    1095             : /**                        SIMPLE GP FUNCTIONS                     **/
    1096             : /**                                                                **/
    1097             : /********************************************************************/
    1098             : 
    1099             : GEN
    1100          28 : arity0(GEN C)
    1101             : {
    1102          28 :   if (typ(C)!=t_CLOSURE) pari_err_TYPE("arity", C);
    1103          28 :   return utoi(closure_arity(C));
    1104             : }
    1105             : 
    1106             : #define ALIAS(ep) (entree *) ((GEN)ep->value)[1]
    1107             : 
    1108             : entree *
    1109     5839400 : do_alias(entree *ep)
    1110             : {
    1111     5839400 :   while (ep->valence == EpALIAS) ep = ALIAS(ep);
    1112     5839400 :   return ep;
    1113             : }
    1114             : 
    1115             : void
    1116          28 : alias0(const char *s, const char *old)
    1117             : {
    1118             :   entree *ep, *e;
    1119             :   GEN x;
    1120             : 
    1121          28 :   ep = fetch_entry(old);
    1122          28 :   e  = fetch_entry(s);
    1123          28 :   if (EpVALENCE(e) != EpALIAS && EpVALENCE(e) != EpNEW)
    1124           0 :     pari_err(e_MISC,"can't replace an existing symbol by an alias");
    1125          28 :   freeep(e);
    1126          28 :   x = cgetg_block(2, t_VECSMALL); gel(x,1) = (GEN)ep;
    1127          28 :   e->value=x; e->valence=EpALIAS;
    1128          28 : }
    1129             : 
    1130             : GEN
    1131    12855533 : ifpari(GEN g, GEN a/*closure*/, GEN b/*closure*/)
    1132             : {
    1133    12855533 :   if (gequal0(g)) /* false */
    1134     9966357 :     return b? closure_evalgen(b): gnil;
    1135             :   else /* true */
    1136     2889176 :     return a? closure_evalgen(a): gnil;
    1137             : }
    1138             : 
    1139             : void
    1140    40446337 : ifpari_void(GEN g, GEN a/*closure*/, GEN b/*closure*/)
    1141             : {
    1142    40446337 :   if (gequal0(g)) /* false */
    1143    39761833 :   { if (b) closure_evalvoid(b); }
    1144             :   else /* true */
    1145      684504 :   { if (a) closure_evalvoid(a); }
    1146    40446316 : }
    1147             : 
    1148             : GEN
    1149       31325 : ifpari_multi(GEN g, GEN a/*closure*/)
    1150             : {
    1151       31325 :   long i, nb = lg(a)-1;
    1152       31325 :   if (!gequal0(g)) /* false */
    1153        6713 :     return closure_evalgen(gel(a,1));
    1154       42098 :   for(i=2;i<nb;i+=2)
    1155             :   {
    1156       24724 :     GEN g = closure_evalgen(gel(a,i));
    1157       24724 :     if (!g) return g;
    1158       24717 :     if (!gequal0(g))
    1159        7231 :       return closure_evalgen(gel(a,i+1));
    1160             :   }
    1161       17374 :   return i<=nb? closure_evalgen(gel(a,i)): gnil;
    1162             : }
    1163             : 
    1164             : GEN
    1165     2000075 : andpari(GEN a, GEN b/*closure*/)
    1166             : {
    1167             :   GEN g;
    1168     2000075 :   if (gequal0(a))
    1169     1612212 :     return gen_0;
    1170      387863 :   g=closure_evalgen(b);
    1171      387863 :   if (!g) return g;
    1172      387863 :   return gequal0(g)?gen_0:gen_1;
    1173             : }
    1174             : 
    1175             : GEN
    1176    16081891 : orpari(GEN a, GEN b/*closure*/)
    1177             : {
    1178             :   GEN g;
    1179    16081891 :   if (!gequal0(a))
    1180      125531 :     return gen_1;
    1181    15956360 :   g=closure_evalgen(b);
    1182    15956360 :   if (!g) return g;
    1183    15956360 :   return gequal0(g)?gen_0:gen_1;
    1184             : }
    1185             : 
    1186       79961 : GEN gmule(GEN *x, GEN y) { *x = gmul(*x,y); return *x; }
    1187          56 : GEN gdive(GEN *x, GEN y) { *x = gdiv(*x,y); return *x; }
    1188           7 : GEN gdivente(GEN *x, GEN y) { *x = gdivent(*x,y); return *x; }
    1189           7 : GEN gdivrounde(GEN *x, GEN y) { *x = gdivround(*x,y); return *x; }
    1190           7 : GEN gmode(GEN *x, GEN y) { *x = gmod(*x,y); return *x; }
    1191           7 : GEN gshiftle(GEN *x, long n) { *x = gshift(*x,n); return *x; }
    1192           7 : GEN gshiftre(GEN *x, long n) { *x = gshift(*x,-n); return *x; }
    1193      434466 : GEN gadde(GEN *x, GEN y) { *x = gadd(*x,y); return *x; }
    1194    25675489 : GEN gadd1e(GEN *x) { *x = typ(*x)==t_INT?addiu(*x,1):gaddgs(*x,1); return *x; }
    1195    15455356 : GEN gsube(GEN *x, GEN y) { *x = gsub(*x,y); return *x; }
    1196          14 : GEN gsub1e(GEN *x) { *x = typ(*x)==t_INT?subiu(*x,1):gsubgs(*x,1); return *x; }
    1197             : 
    1198        1392 : GEN gshift_right(GEN x, long n) { return gshift(x,-n); }

Generated by: LCOV version 1.13