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 23011-59c7027a2) Lines: 606 656 92.4 %
Date: 2018-09-22 05:37:52 Functions: 97 102 95.1 %
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             : /* return hashing value for identifier s */
     122             : static ulong
     123     1870100 : hashvalue(const char *s)
     124             : {
     125     1870100 :   ulong n = 0, c;
     126     1870100 :   while ( (c = (ulong)*s++) ) n = (n<<1) ^ c;
     127     1870100 :   return n;
     128             : }
     129             : 
     130             : static ulong
     131     6538480 : hashvalue_raw(const char *s, long len)
     132             : {
     133     6538480 :   long n = 0, i;
     134     6538480 :   for(i=0; i<len; i++) { n = (n<<1) ^ *s; s++; }
     135     6538480 :   return n;
     136             : }
     137             : 
     138             : static void
     139     1897076 : insertep(entree *ep, entree **table, ulong hash)
     140             : {
     141     1897076 :   ep->hash = hash;
     142     1897076 :   hash %= functions_tblsz;
     143     1897076 :   ep->next = table[hash];
     144     1897076 :   table[hash] = ep;
     145     1897076 : }
     146             : 
     147             : static entree *
     148       27060 : initep(const char *name, long len)
     149             : {
     150       27060 :   const long add = 4*sizeof(long);
     151       27060 :   entree *ep = (entree *) pari_calloc(sizeof(entree) + add + len+1);
     152       27060 :   entree *ep1 = initial_value(ep);
     153       27060 :   char *u = (char *) ep1 + add;
     154       27060 :   ep->name    = u; memcpy(u, name,len); u[len]=0;
     155       27060 :   ep->valence = EpNEW;
     156       27060 :   ep->value   = NULL;
     157       27060 :   ep->menu    = 0;
     158       27060 :   ep->code    = NULL;
     159       27060 :   ep->help    = NULL;
     160       27060 :   ep->pvalue  = NULL;
     161       27060 :   ep->arity   = 0;
     162       27060 :   return ep;
     163             : }
     164             : 
     165             : /* Look for s of length len in T; if 'insert', insert if missing */
     166             : static entree *
     167     6538480 : findentry(const char *s, long len, entree **T, int insert)
     168             : {
     169     6538480 :   ulong hash = hashvalue_raw(s, len);
     170             :   entree *ep;
     171    37020203 :   for (ep = T[hash % functions_tblsz]; ep; ep = ep->next)
     172    36993185 :     if (ep->hash == hash)
     173             :     {
     174     6565373 :       const char *t = ep->name;
     175     6565373 :       if (!strncmp(t, s, len) && !t[len]) return ep;
     176             :     }
     177             :   /* not found */
     178       27018 :   if (insert) { ep = initep(s,len); insertep(ep, T, hash); }
     179       27018 :   return ep;
     180             : }
     181             : entree *
     182        1245 : pari_is_default(const char *s)
     183        1245 : { return findentry(s, strlen(s), defaults_hash, 0); }
     184             : entree *
     185      294685 : is_entry(const char *s)
     186      294685 : { return findentry(s, strlen(s), functions_hash, 0); }
     187             : entree *
     188     6242550 : fetch_entry_raw(const char *s, long len)
     189     6242550 : { return findentry(s, len, functions_hash, 1); }
     190             : entree *
     191      386340 : fetch_entry(const char *s) { return fetch_entry_raw(s, strlen(s)); }
     192             : 
     193             : /*******************************************************************/
     194             : /*                                                                 */
     195             : /*                  SYNTACTICAL ANALYZER FOR GP                    */
     196             : /*                                                                 */
     197             : /*******************************************************************/
     198             : static GEN
     199        4767 : readseq_i(char *t)
     200             : {
     201        4767 :   if (gp_meta(t,0)) return gnil;
     202        4767 :   return closure_evalres(pari_compile_str(t));
     203             : }
     204             : GEN
     205        4767 : readseq(char *t)
     206        4767 : { pari_sp av = avma; return gerepileupto(av, readseq_i(t)); }
     207             : 
     208             : /* filtered readseq = remove blanks and comments */
     209             : GEN
     210           0 : gp_read_str(const char *s)
     211           0 : { pari_sp av = avma; return gerepileupto(av, readseq_i(gp_filter(s))); }
     212             : 
     213             : GEN
     214       10738 : compile_str(const char *s) { return pari_compile_str(gp_filter(s)); }
     215             : 
     216             : static long
     217     1853028 : check_proto(const char *code)
     218             : {
     219     1853028 :   long arity = 0;
     220     1853028 :   const char *s = code, *old;
     221     1853028 :   if (*s == 'l' || *s == 'v' || *s == 'i' || *s == 'm' || *s == 'u') s++;
     222     9137926 :   while (*s && *s != '\n') switch (*s++)
     223             :   {
     224             :     case '&':
     225             :     case 'C':
     226             :     case 'G':
     227             :     case 'I':
     228             :     case 'J':
     229             :     case 'U':
     230             :     case 'L':
     231             :     case 'M':
     232             :     case 'P':
     233             :     case 'W':
     234             :     case 'f':
     235             :     case 'n':
     236             :     case 'p':
     237             :     case 'b':
     238             :     case 'r':
     239     3440744 :       arity++;
     240     3440744 :       break;
     241             :     case 'E':
     242             :     case 's':
     243      117952 :       if (*s == '*') s++;
     244      117952 :       arity++;
     245      117952 :       break;
     246             :     case 'D':
     247      938930 :       if (*s == 'G' || *s == '&' || *s == 'n' || *s == 'I' || *s == 'E'
     248      429874 :                     || *s == 'V' || *s == 'P' || *s == 's' || *s == 'r')
     249             :       {
     250      543200 :         if (*s != 'V') arity++;
     251      543200 :         s++; break;
     252             :       }
     253      395730 :       old = s; while (*s && *s != ',') s++;
     254      395730 :       if (*s != ',') pari_err(e_SYNTAX, "missing comma", old, code);
     255      395730 :       break;
     256             :     case 'V':
     257             :     case '=':
     258      934244 :     case ',': break;
     259           0 :     case '\n': break; /* Before the mnemonic */
     260             : 
     261             :     case 'm':
     262             :     case 'l':
     263             :     case 'i':
     264           0 :     case 'v': pari_err(e_SYNTAX, "this code has to come first", s-1, code);
     265           0 :     default: pari_err(e_SYNTAX, "unknown parser code", s-1, code);
     266             :   }
     267     1853028 :   if (arity > 20) pari_err_IMPL("functions with more than 20 parameters");
     268     1853028 :   return arity;
     269             : }
     270             : static void
     271           0 : check_name(const char *name)
     272             : {
     273           0 :   const char *s = name;
     274           0 :   if (isalpha((int)*s))
     275           0 :     while (is_keyword_char(*++s)) /* empty */;
     276           0 :   if (*s) pari_err(e_SYNTAX,"not a valid identifier", s, name);
     277           0 : }
     278             : 
     279             : entree *
     280           0 : install(void *f, const char *name, const char *code)
     281             : {
     282           0 :   long arity = check_proto(code);
     283             :   entree *ep;
     284             : 
     285           0 :   check_name(name);
     286           0 :   ep = fetch_entry(name);
     287           0 :   if (ep->valence != EpNEW)
     288             :   {
     289           0 :     if (ep->valence != EpINSTALL)
     290           0 :       pari_err(e_MISC,"[install] identifier '%s' already in use", name);
     291           0 :     pari_warn(warner, "[install] updating '%s' prototype; module not reloaded", name);
     292           0 :     if (ep->code) pari_free((void*)ep->code);
     293             :   }
     294             :   else
     295             :   {
     296           0 :     ep->value = f;
     297           0 :     ep->valence = EpINSTALL;
     298             :   }
     299           0 :   ep->code = pari_strdup(code);
     300           0 :   ep->arity = arity; return ep;
     301             : }
     302             : 
     303             : static void
     304          14 : killep(entree *ep)
     305             : {
     306          14 :   GEN p = (GEN)initial_value(ep);
     307          14 :   freeep(ep);
     308          14 :   *p = 0; /* otherwise pari_var_create won't regenerate it */
     309          14 :   ep->valence = EpNEW;
     310          14 :   ep->value   = NULL;
     311          14 :   ep->pvalue  = NULL;
     312          14 : }
     313             : /* Kill ep, i.e free all memory it references, and reset to initial value */
     314             : void
     315          14 : kill0(const char *e)
     316             : {
     317          14 :   entree *ep = is_entry(e);
     318          14 :   if (!ep || EpSTATIC(ep)) pari_err(e_MISC,"can't kill that");
     319          14 :   killep(ep);
     320          14 : }
     321             : 
     322             : void
     323          42 : addhelp(const char *e, char *s)
     324             : {
     325          42 :   entree *ep = fetch_entry(e);
     326          42 :   void *f = (void *) ep->help;
     327          42 :   ep->help = pari_strdup(s);
     328          42 :   if (f && !EpSTATIC(ep)) pari_free(f);
     329          42 : }
     330             : 
     331             : GEN
     332       23526 : type0(GEN x)
     333             : {
     334       23526 :   const char *s = type_name(typ(x));
     335       23526 :   return strtoGENstr(s);
     336             : }
     337             : 
     338             : /*******************************************************************/
     339             : /*                                                                 */
     340             : /*                              PARSER                             */
     341             : /*                                                                 */
     342             : /*******************************************************************/
     343             : 
     344             : #ifdef LONG_IS_64BIT
     345             : static const long MAX_DIGITS  = 19;
     346             : #else
     347             : static const long MAX_DIGITS  = 9;
     348             : #endif
     349             : 
     350             : static const long MAX_XDIGITS = BITS_IN_LONG>>2;
     351             : static const long MAX_BDIGITS = BITS_IN_LONG;
     352             : 
     353             : static int
     354    35416295 : ishex(const char **s)
     355             : {
     356    35416295 :   if (**s == '0' && ((*s)[1] == 'x' || (*s)[1] == 'X' ))
     357             :   {
     358          49 :     *s += 2;
     359          49 :     return 1;
     360             :   }
     361             :   else
     362    35416246 :     return 0;
     363             : }
     364             : 
     365             : static int
     366    35416344 : isbin(const char **s)
     367             : {
     368    35416344 :   if (**s == '0' && ((*s)[1] == 'b' || (*s)[1] == 'B' ))
     369             :   {
     370          49 :     *s += 2;
     371          49 :     return 1;
     372             :   }
     373             :   else
     374    35416295 :     return 0;
     375             : }
     376             : 
     377             : static ulong
     378          38 : bin_number_len(const char *s, long n)
     379             : {
     380          38 :   ulong m = 0;
     381             :   long i;
     382        1494 :   for (i = 0; i < n; i++,s++)
     383        1456 :     m = 2*m + (*s - '0');
     384          38 :   return m;
     385             : }
     386             : 
     387             : static int
     388        1484 : pari_isbdigit(int c)
     389             : {
     390        1484 :   return c=='0' || c=='1';
     391             : }
     392             : 
     393             : static ulong
     394          54 : hex_number_len(const char *s, long n)
     395             : {
     396          54 :   ulong m = 0;
     397             :   long i;
     398         593 :   for(i = 0; i < n; i++, s++)
     399             :   {
     400             :     ulong c;
     401         539 :     if( *s >= '0' && *s <= '9')
     402         455 :       c = *s - '0';
     403          84 :     else if( *s >= 'A' && *s <= 'F')
     404          84 :       c = *s - 'A' + 10;
     405             :     else
     406           0 :       c = *s - 'a' + 10;
     407         539 :     m = 16*m + c;
     408             :   }
     409          54 :   return m;
     410             : }
     411             : 
     412             : static GEN
     413          56 : strtobin_len(const char *s, long n, long B, ulong num(const char *s, long n))
     414             : {
     415          56 :   long i, l = (n+B-1)/B;
     416             :   GEN N, Np;
     417          56 :   N = cgetipos(l+2);
     418          56 :   Np = int_LSW(N);
     419          92 :   for (i=1; i<l; i++, Np = int_nextW(Np))
     420          36 :     uel(Np, 0) = num(s+n-i*B, B);
     421          56 :   uel(Np, 0) = num(s, n-(i-1)*B);
     422          56 :   return int_normalize(N, 0);
     423             : }
     424             : 
     425             : static GEN
     426          56 : binary_read(const char **ps, long B, int is(int), ulong num(const char *s, long n))
     427             : {
     428          56 :   const char *s = *ps;
     429          56 :   while (is((int)**ps)) (*ps)++;
     430          56 :   return strtobin_len(s, *ps-s, B, num);
     431             : }
     432             : 
     433             : static GEN
     434          28 : bin_read(const char **ps)
     435             : {
     436          28 :   return binary_read(ps, MAX_BDIGITS, pari_isbdigit, bin_number_len);
     437             : }
     438             : 
     439             : static GEN
     440          28 : hex_read(const char **ps)
     441             : {
     442          28 :   return binary_read(ps, MAX_XDIGITS, isxdigit, hex_number_len);
     443             : }
     444             : 
     445             : static ulong
     446     3473572 : dec_number_len(const char *s, long B)
     447             : {
     448     3473572 :   ulong m = 0;
     449             :   long n;
     450    52777634 :   for (n = 0; n < B; n++,s++)
     451    49304062 :     m = 10*m + (*s - '0');
     452     3473572 :   return m;
     453             : }
     454             : 
     455             : static GEN
     456      922843 : dec_strtoi_len(const char *s, long n)
     457             : {
     458      922843 :   const long B = MAX_DIGITS;
     459      922843 :   long i, l = (n+B-1)/B;
     460      922843 :   GEN V = cgetg(l+1, t_VECSMALL);
     461     3473572 :   for (i=1; i<l; i++)
     462     2550729 :     uel(V,i) = dec_number_len(s+n-i*B, B);
     463      922843 :   uel(V, i) = dec_number_len(s, n-(i-1)*B);
     464      922843 :   return fromdigitsu(V, powuu(10, B));
     465             : }
     466             : 
     467             : static GEN
     468      922843 : dec_read_more(const char **ps)
     469             : {
     470      922843 :   pari_sp av = avma;
     471      922843 :   const char *s = *ps;
     472      922843 :   while (isdigit((int)**ps)) (*ps)++;
     473      922843 :   return gerepileuptoint(av, dec_strtoi_len(s, *ps-s));
     474             : }
     475             : 
     476             : static ulong
     477     7976702 : number(int *n, const char **s)
     478             : {
     479     7976702 :   ulong m = 0;
     480    40326203 :   for (*n = 0; *n < MAX_DIGITS && isdigit((int)**s); (*n)++,(*s)++)
     481    32349501 :     m = 10*m + (**s - '0');
     482     7976702 :   return m;
     483             : }
     484             : 
     485             : static GEN
     486     7901151 : dec_read(const char **s)
     487             : {
     488             :   int nb;
     489     7901151 :   ulong y  = number(&nb, s);
     490     7901151 :   if (nb < MAX_DIGITS)
     491     6978308 :     return utoi(y);
     492      922843 :   *s -= MAX_DIGITS;
     493      922843 :   return dec_read_more(s);
     494             : }
     495             : 
     496             : static GEN
     497        2552 : real_read_more(GEN y, const char **ps)
     498             : {
     499        2552 :   pari_sp av = avma;
     500        2552 :   const char *s = *ps;
     501        2552 :   GEN z = dec_read(ps);
     502        2552 :   long e = *ps-s;
     503        2552 :   return gerepileuptoint(av, addmulii(z, powuu(10, e), y));
     504             : }
     505             : 
     506             : static long
     507       75551 : exponent(const char **pts)
     508             : {
     509       75551 :   const char *s = *pts;
     510             :   long n;
     511             :   int nb;
     512       75551 :   switch(*++s)
     513             :   {
     514       75418 :     case '-': s++; n = -(long)number(&nb, &s); break;
     515           0 :     case '+': s++; /* Fall through */
     516         133 :     default: n = (long)number(&nb, &s);
     517             :   }
     518       75551 :   *pts = s; return n;
     519             : }
     520             : 
     521             : static GEN
     522         175 : real_0_digits(long n) {
     523         175 :   long b = (n > 0)? (long)(n/LOG10_2): (long)-((-n)/LOG10_2 + 1);
     524         175 :   return real_0_bit(b);
     525             : }
     526             : 
     527             : static GEN
     528       83701 : real_read(pari_sp av, const char **s, GEN y, long prec)
     529             : {
     530       83701 :   long l, n = 0;
     531       83701 :   switch(**s)
     532             :   {
     533           0 :     default: return y; /* integer */
     534             :     case '.':
     535             :     {
     536        9368 :       const char *old = ++*s;
     537        9368 :       if (isalpha((int)**s) || **s=='.')
     538             :       {
     539        1211 :         if (**s == 'E' || **s == 'e') {
     540        1211 :           n = exponent(s);
     541        1211 :           if (!signe(y)) { set_avma(av); return real_0_digits(n); }
     542        1183 :           break;
     543             :         }
     544           0 :         --*s; return y; /* member */
     545             :       }
     546        8157 :       if (isdigit((int)**s)) y = real_read_more(y, s);
     547        8157 :       n = old - *s;
     548        8157 :       if (**s != 'E' && **s != 'e')
     549             :       {
     550        8150 :         if (!signe(y)) { set_avma(av); return real_0(prec); }
     551        7191 :         break;
     552             :       }
     553             :     }
     554             :     /* Fall through */
     555             :     case 'E': case 'e':
     556       74340 :       n += exponent(s);
     557       74340 :       if (!signe(y)) { set_avma(av); return real_0_digits(n); }
     558             :   }
     559       82567 :   l = nbits2prec(bit_accuracy(lgefint(y)));
     560       82567 :   if (l < prec) l = prec; else prec = l;
     561       82567 :   if (!n) return itor(y, prec);
     562       77214 :   incrprec(l);
     563       77214 :   y = itor(y, l);
     564       77214 :   if (n > 0)
     565          56 :     y = mulrr(y, rpowuu(10UL, (ulong)n, l));
     566             :   else
     567       77158 :     y = divrr(y, rpowuu(10UL, (ulong)-n, l));
     568       77214 :   return gerepileuptoleaf(av, rtor(y, prec));
     569             : }
     570             : 
     571             : static GEN
     572     7814954 : int_read(const char **s)
     573             : {
     574             :   GEN y;
     575     7814954 :   if (isbin(s))
     576          28 :     y = bin_read(s);
     577     7814926 :   else if (ishex(s))
     578          28 :     y = hex_read(s);
     579             :   else
     580     7814898 :     y = dec_read(s);
     581     7814954 :   return y;
     582             : }
     583             : 
     584             : GEN
     585     7814954 : strtoi(const char *s) { return int_read(&s); }
     586             : 
     587             : GEN
     588       83701 : strtor(const char *s, long prec)
     589             : {
     590       83701 :   pari_sp av = avma;
     591       83701 :   GEN y = dec_read(&s);
     592       83701 :   y = real_read(av, &s, y, prec);
     593       83701 :   if (typ(y) == t_REAL) return y;
     594           0 :   return gerepileuptoleaf(av, itor(y, prec));
     595             : }
     596             : 
     597             : static void
     598     7696843 : skipdigits(char **lex) {
     599     7696843 :   while (isdigit((int)**lex)) ++*lex;
     600     7696843 : }
     601             : 
     602             : static int
     603     7692776 : skipexponent(char **lex)
     604             : {
     605     7692776 :   char *old=*lex;
     606     7692776 :   if ((**lex=='e' || **lex=='E'))
     607             :   {
     608        1015 :     ++*lex;
     609        1015 :     if ( **lex=='+' || **lex=='-' ) ++*lex;
     610        1015 :     if (!isdigit((int)**lex))
     611             :     {
     612         469 :       *lex=old;
     613         469 :       return KINTEGER;
     614             :     }
     615         546 :     skipdigits(lex);
     616         546 :     return KREAL;
     617             :   }
     618     7691761 :   return KINTEGER;
     619             : }
     620             : 
     621             : static int
     622     7693675 : skipconstante(char **lex)
     623             : {
     624     7693675 :   skipdigits(lex);
     625     7693675 :   if (**lex=='.')
     626             :   {
     627       14707 :     char *old = ++*lex;
     628       14707 :     if (**lex == '.') { --*lex; return KINTEGER; }
     629       13808 :     if (isalpha((int)**lex))
     630             :     {
     631       11186 :       skipexponent(lex);
     632       11186 :       if (*lex == old)
     633             :       {
     634       11151 :         --*lex; /* member */
     635       11151 :         return KINTEGER;
     636             :       }
     637          35 :       return KREAL;
     638             :     }
     639        2622 :     skipdigits(lex);
     640        2622 :     skipexponent(lex);
     641        2622 :     return KREAL;
     642             :   }
     643     7678968 :   return skipexponent(lex);
     644             : }
     645             : 
     646             : static void
     647     1108019 : skipstring(char **lex)
     648             : {
     649     9005410 :   while (**lex)
     650             :   {
     651     7897391 :     while (**lex == '\\') *lex+=2;
     652     7897391 :     if (**lex == '"')
     653             :     {
     654     1108019 :       if ((*lex)[1] != '"') break;
     655           0 :       *lex += 2; continue;
     656             :     }
     657     6789372 :     (*lex)++;
     658             :   }
     659     1108019 : }
     660             : 
     661             : int
     662    29212749 : pari_lex(union token_value *yylval, struct node_loc *yylloc, char **lex)
     663             : {
     664             :   (void) yylval;
     665    29212749 :   yylloc->start=*lex;
     666    29212749 :   if (!**lex)
     667             :   {
     668       95028 :     yylloc->end=*lex;
     669       95028 :     return 0;
     670             :   }
     671    29117721 :   if (isalpha((int)**lex))
     672             :   {
     673      396227 :     while (is_keyword_char(**lex)) ++*lex;
     674      396227 :     yylloc->end=*lex;
     675      396227 :     return KENTRY;
     676             :   }
     677    28721494 :   if (**lex=='"')
     678             :   {
     679     1108019 :     ++*lex;
     680     1108019 :     skipstring(lex);
     681     1108019 :     if (!**lex)
     682           0 :       compile_err("run-away string",*lex-1);
     683     1108019 :     ++*lex;
     684     1108019 :     yylloc->end=*lex;
     685     1108019 :     return KSTRING;
     686             :   }
     687    27613475 :   if (**lex == '.')
     688             :   {
     689             :     int token;
     690       12085 :     if ((*lex)[1]== '.')
     691             :     {
     692         927 :       *lex+=2; yylloc->end = *lex; return KDOTDOT;
     693             :     }
     694       11158 :     token=skipconstante(lex);
     695       11158 :     if (token==KREAL)
     696             :     {
     697           7 :       yylloc->end = *lex;
     698           7 :       return token;
     699             :     }
     700       11151 :     ++*lex;
     701       11151 :     yylloc->end=*lex;
     702       11151 :     return '.';
     703             :   }
     704    27601390 :   if (isbin((const char**)lex))
     705             :   {
     706          21 :     while (**lex=='0' || **lex=='1') ++*lex;
     707          21 :     return KINTEGER;
     708             :   }
     709    27601369 :   if (ishex((const char**)lex))
     710             :   {
     711          21 :     while (isxdigit((int)**lex)) ++*lex;
     712          21 :     return KINTEGER;
     713             :   }
     714    27601348 :   if (isdigit((int)**lex))
     715             :   {
     716     7682517 :     int token=skipconstante(lex);
     717     7682517 :     yylloc->end = *lex;
     718     7682517 :     return token;
     719             :   }
     720    19918831 :   if ((*lex)[1]=='=')
     721       21298 :     switch (**lex)
     722             :     {
     723             :     case '=':
     724        8364 :       if ((*lex)[2]=='=')
     725         343 :       { *lex+=3; yylloc->end = *lex; return KID; }
     726             :       else
     727        8021 :       { *lex+=2; yylloc->end = *lex; return KEQ; }
     728             :     case '>':
     729          65 :       *lex+=2; yylloc->end = *lex; return KGE;
     730             :     case '<':
     731         170 :       *lex+=2; yylloc->end = *lex; return KLE;
     732             :     case '*':
     733         142 :       *lex+=2; yylloc->end = *lex; return KME;
     734             :     case '/':
     735          35 :       *lex+=2; yylloc->end = *lex; return KDE;
     736             :     case '%':
     737           7 :       if ((*lex)[2]=='=') break;
     738           7 :       *lex+=2; yylloc->end = *lex; return KMODE;
     739             :     case '!':
     740        1666 :       if ((*lex)[2]=='=') break;
     741        1666 :       *lex+=2; yylloc->end = *lex; return KNE;
     742             :     case '\\':
     743           7 :       *lex+=2; yylloc->end = *lex; return KEUCE;
     744             :     case '+':
     745         145 :       *lex+=2; yylloc->end = *lex; return KPE;
     746             :     case '-':
     747          49 :       *lex+=2; yylloc->end = *lex; return KSE;
     748             :     }
     749    19908181 :   if (**lex==')' && (*lex)[1]=='-' && (*lex)[2]=='>')
     750             :   {
     751        3887 :     *lex+=3; yylloc->end = *lex; return KPARROW;
     752             :   }
     753    19904294 :   if (**lex=='-' && (*lex)[1]=='>')
     754             :   {
     755         914 :     *lex+=2; yylloc->end = *lex; return KARROW;
     756             :   }
     757    19903380 :   if (**lex=='<' && (*lex)[1]=='>')
     758             :   {
     759           0 :     *lex+=2; yylloc->end = *lex; return KNE;
     760             :   }
     761    19903380 :   if (**lex=='\\' && (*lex)[1]=='/')
     762          35 :     switch((*lex)[2])
     763             :     {
     764             :     case '=':
     765           7 :       *lex+=3; yylloc->end = *lex; return KDRE;
     766             :     default:
     767          28 :       *lex+=2; yylloc->end = *lex; return KDR;
     768             :     }
     769    19903345 :   if ((*lex)[1]==**lex)
     770     2117571 :     switch (**lex)
     771             :     {
     772             :     case '&':
     773         658 :       *lex+=2; yylloc->end = *lex; return KAND;
     774             :     case '|':
     775         287 :       *lex+=2; yylloc->end = *lex; return KOR;
     776             :     case '+':
     777         119 :       *lex+=2; yylloc->end = *lex; return KPP;
     778             :     case '-':
     779          14 :       *lex+=2; yylloc->end = *lex; return KSS;
     780             :     case '>':
     781          28 :       if ((*lex)[2]=='=') { *lex+=3; yylloc->end = *lex; return KSRE;}
     782          21 :       *lex+=2; yylloc->end = *lex; return KSR;
     783             :     case '<':
     784         112 :       if ((*lex)[2]=='=')
     785           7 :       { *lex+=3; yylloc->end = *lex; return KSLE; }
     786         105 :       *lex+=2; yylloc->end = *lex; return KSL;
     787             :     }
     788    19902127 :   yylloc->end = *lex+1;
     789    19902127 :   return (unsigned char) *(*lex)++;
     790             : }
     791             : 
     792             : /********************************************************************/
     793             : /**                                                                **/
     794             : /**                            STRINGS                             **/
     795             : /**                                                                **/
     796             : /********************************************************************/
     797             : 
     798             : /* return the first n0 chars of s as a GEN [s may not be 0-terminated] */
     799             : GEN
     800      465399 : strntoGENstr(const char *s, long n0)
     801             : {
     802      465399 :   long n = nchar2nlong(n0+1);
     803      465399 :   GEN x = cgetg(n+1, t_STR);
     804      465399 :   char *t = GSTR(x);
     805      465399 :   x[n] = 0;
     806      465399 :   strncpy(t, s, n0); t[n0] = 0; return x;
     807             : }
     808             : 
     809             : GEN
     810      350747 : strtoGENstr(const char *s) { return strntoGENstr(s, strlen(s)); }
     811             : 
     812             : GEN
     813      342045 : chartoGENstr(char c)
     814             : {
     815      342045 :   GEN x = cgetg(2, t_STR);
     816      342045 :   char *t = GSTR(x);
     817      342045 :   t[0] = c; t[1] = 0; return x;
     818             : }
     819             : 
     820             : /********************************************************************/
     821             : /*                                                                  */
     822             : /*                Formal variables management                       */
     823             : /*                                                                  */
     824             : /********************************************************************/
     825             : static THREAD long max_priority, min_priority;
     826             : static THREAD long max_avail; /* max variable not yet used */
     827             : static THREAD long nvar; /* first GP free variable */
     828             : static hashtable *h_polvar;
     829             : static struct pari_varstate global_varstate;
     830             : static long *global_varpriority;
     831             : 
     832             : void
     833      106807 : varstate_save(struct pari_varstate *s)
     834             : {
     835      106807 :   s->nvar = nvar;
     836      106807 :   s->max_avail = max_avail;
     837      106807 :   s->max_priority = max_priority;
     838      106807 :   s->min_priority = min_priority;
     839      106807 : }
     840             : 
     841             : static void
     842        8445 : varentries_set(long v, entree *ep)
     843             : {
     844        8445 :   hash_insert(h_polvar, (void*)ep->name, (void*)v);
     845        8445 :   varentries[v] = ep;
     846        8445 : }
     847             : static int
     848        3143 : _given_value(void *E, hashentry *e) { return e->val == E; }
     849             : 
     850             : static void
     851       12151 : varentries_unset(long v)
     852             : {
     853       12151 :   entree *ep = varentries[v];
     854       12151 :   if (ep)
     855             :   {
     856        3143 :     hashentry *e = hash_remove_select(h_polvar, (void*)ep->name, (void*)v,
     857             :         _given_value);
     858        3143 :     if (!e) pari_err_BUG("varentries_unset [unknown var]");
     859        3143 :     varentries[v] = NULL;
     860        3143 :     pari_free(e);
     861        3143 :     if (v <= nvar && ep == is_entry(ep->name))
     862        2905 :     { /* known to the GP interpreter; entree in functions_hash is permanent */
     863        2905 :       GEN p = (GEN)initial_value(ep);
     864        2905 :       if (ep->value == p) { ep->value = NULL; ep->valence = EpNEW; }
     865        2905 :       *p = 0;
     866             :     }
     867             :     else /* from name_var() or a direct pari_var_create() */
     868         238 :       pari_free(ep);
     869             :  }
     870       12151 : }
     871             : static void
     872         336 : varentries_reset(long v, entree *ep)
     873             : {
     874         336 :   varentries_unset(v);
     875         336 :   varentries_set(v, ep);
     876         336 : }
     877             : 
     878             : static void
     879      120195 : var_restore(struct pari_varstate *s)
     880             : {
     881      120195 :   nvar = s->nvar;
     882      120195 :   max_avail = s->max_avail;
     883      120195 :   max_priority = s->max_priority;
     884      120195 :   min_priority = s->min_priority;
     885      120195 : }
     886             : 
     887             : void
     888        8889 : varstate_restore(struct pari_varstate *s)
     889             : {
     890             :   long i;
     891       20690 :   for (i = nvar; i >= s->nvar; i--)
     892             :   {
     893       11801 :     varentries_unset(i);
     894       11801 :     varpriority[i] = -i;
     895             :   }
     896        8903 :   for (i = max_avail+1; i <= s->max_avail; i++)
     897             :   {
     898          14 :     varentries_unset(i);
     899          14 :     varpriority[i] = -i;
     900             :   }
     901        8889 :   var_restore(s);
     902        8889 : }
     903             : 
     904             : void
     905      111307 : pari_thread_init_varstate(void)
     906             : {
     907             :   long i;
     908      111307 :   var_restore(&global_varstate);
     909      111180 :   varpriority = (long*)newblock((MAXVARN+2)) + 1;
     910      112006 :   varpriority[-1] = 1-LONG_MAX;
     911      112006 :   for (i = 0; i < max_avail; i++) varpriority[i] = global_varpriority[i];
     912      112006 : }
     913             : 
     914             : void
     915       11137 : pari_pthread_init_varstate(void)
     916             : {
     917       11137 :   varstate_save(&global_varstate);
     918       11137 :   global_varpriority = varpriority;
     919       11137 : }
     920             : 
     921             : /* must come before destruction of functions_hash */
     922             : void
     923        1542 : pari_var_close(void)
     924             : {
     925        1542 :   GEN h = hash_values(h_polvar);
     926        1542 :   long i, l = lg(h);
     927        6824 :   for (i = 1; i < l; i++)
     928             :   {
     929        5282 :     long v = h[i];
     930        5282 :     entree *ep = varentries[v];
     931        5282 :     if (ep && ep != is_entry(ep->name)) pari_free(ep);
     932             :   }
     933        1542 :   free((void*)varentries);
     934        1542 :   free((void*)(varpriority-1));
     935        1542 :   hash_destroy(h_polvar);
     936        1542 : }
     937             : 
     938             : void
     939        1552 : pari_var_init(void)
     940             : {
     941             :   long i;
     942        1552 :   varentries = (entree**) pari_calloc((MAXVARN+1)*sizeof(entree*));
     943        1552 :   varpriority = (long*)pari_malloc((MAXVARN+2)*sizeof(long)) + 1;
     944        1552 :   varpriority[-1] = 1-LONG_MAX;
     945        1552 :   h_polvar = hash_create_str(100, 0);
     946        1552 :   nvar = 0; max_avail = MAXVARN;
     947        1552 :   max_priority = min_priority = 0;
     948        1552 :   (void)fetch_user_var("x");
     949        1552 :   (void)fetch_user_var("y");
     950             :   /* initialize so that people can use pol_x(i) directly */
     951        1552 :   for (i = 2; i <= (long)MAXVARN; i++) varpriority[i] = -i;
     952             :   /* reserve varnum 1..9 for static temps with predictable priority wrt x */
     953        1552 :   nvar = 10;
     954        1552 :   min_priority = -MAXVARN;
     955        1552 : }
     956         252 : long pari_var_next(void) { return nvar; }
     957           0 : long pari_var_next_temp(void) { return max_avail; }
     958             : long
     959       28647 : pari_var_create(entree *ep)
     960             : {
     961       28647 :   GEN p = (GEN)initial_value(ep);
     962             :   long v;
     963       28647 :   if (*p) return varn(p);
     964        8109 :   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
     965        8109 :   v = nvar++;
     966             :   /* set p = pol_x(v) */
     967        8109 :   p[0] = evaltyp(t_POL) | _evallg(4);
     968        8109 :   p[1] = evalsigne(1) | evalvarn(v);
     969        8109 :   gel(p,2) = gen_0;
     970        8109 :   gel(p,3) = gen_1;
     971        8109 :   varentries_set(v, ep);
     972        8109 :   varpriority[v]= min_priority--;
     973        8109 :   return v;
     974             : }
     975             : 
     976             : long
     977       75464 : delete_var(void)
     978             : { /* user wants to delete one of his/her/its variables */
     979       75464 :   if (max_avail == MAXVARN) return 0; /* nothing to delete */
     980       75464 :   max_avail++;
     981       75464 :   if      (varpriority[max_avail] == min_priority) min_priority++;
     982       75464 :   else if (varpriority[max_avail] == max_priority) max_priority--;
     983       75464 :   return max_avail+1;
     984             : }
     985             : long
     986       44095 : fetch_var(void)
     987             : {
     988       44095 :   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
     989       44095 :   varpriority[max_avail] = min_priority--;
     990       44095 :   return max_avail--;
     991             : }
     992             : long
     993       34848 : fetch_var_higher(void)
     994             : {
     995       34848 :   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
     996       34848 :   varpriority[max_avail] = ++max_priority;
     997       34848 :   return max_avail--;
     998             : }
     999             : 
    1000             : static int
    1001          49 : _higher(void *E, hashentry *e)
    1002          49 : { long v = (long)e->val; return (varncmp(v, (long)E) < 0); }
    1003             : static int
    1004          42 : _lower(void *E, hashentry *e)
    1005          42 : { long v = (long)e->val; return (varncmp(v, (long)E) > 0); }
    1006             : 
    1007             : static GEN
    1008          84 : var_register(long v, const char *s)
    1009             : {
    1010          84 :   varentries_reset(v, initep(s, strlen(s)));
    1011          84 :   return pol_x(v);
    1012             : }
    1013             : GEN
    1014          77 : varhigher(const char *s, long w)
    1015             : {
    1016             :   long v;
    1017          77 :   if (w >= 0)
    1018             :   {
    1019          49 :     hashentry *e = hash_select(h_polvar, (void*)s, (void*)w, _higher);
    1020          49 :     if (e) return pol_x((long)e->val);
    1021             :   }
    1022             :   /* no luck: need to create */
    1023          63 :   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
    1024          63 :   v = nvar++;
    1025          63 :   varpriority[v]= ++max_priority;
    1026          63 :   return var_register(v, s);
    1027             : }
    1028             : GEN
    1029          28 : varlower(const char *s, long w)
    1030             : {
    1031             :   long v;
    1032          28 :   if (w >= 0)
    1033             :   {
    1034          21 :     hashentry *e = hash_select(h_polvar, (void*)s, (void*)w, _lower);
    1035          21 :     if (e) return pol_x((long)e->val);
    1036             :   }
    1037             :   /* no luck: need to create */
    1038          21 :   v = fetch_var();
    1039          21 :   return var_register(v, s);
    1040             : }
    1041             : 
    1042             : long
    1043      386242 : fetch_user_var(const char *s)
    1044             : {
    1045      386242 :   entree *ep = fetch_entry(s);
    1046             :   long v;
    1047      386242 :   switch (EpVALENCE(ep))
    1048             :   {
    1049      382991 :     case EpVAR: return varn((GEN)initial_value(ep));
    1050        3251 :     case EpNEW: break;
    1051           0 :     default: pari_err(e_MISC, "%s already exists with incompatible valence", s);
    1052             :   }
    1053        3251 :   v = pari_var_create(ep);
    1054        3251 :   ep->valence = EpVAR;
    1055        3251 :   ep->value = initial_value(ep);
    1056        3251 :   return v;
    1057             : }
    1058             : 
    1059             : GEN
    1060           7 : fetch_var_value(long v, GEN t)
    1061             : {
    1062           7 :   entree *ep = varentries[v];
    1063           7 :   if (!ep) return NULL;
    1064           7 :   if (t)
    1065             :   {
    1066           7 :     long vn = localvars_find(t,ep);
    1067           7 :     if (vn) return get_lex(vn);
    1068             :   }
    1069           7 :   return (GEN)ep->value;
    1070             : }
    1071             : 
    1072             : void
    1073         252 : name_var(long n, const char *s)
    1074             : {
    1075             :   entree *ep;
    1076             :   char *u;
    1077             : 
    1078         252 :   if (n < pari_var_next())
    1079           0 :     pari_err(e_MISC, "renaming a GP variable is forbidden");
    1080         252 :   if (n > (long)MAXVARN)
    1081           0 :     pari_err_OVERFLOW("variable number");
    1082             : 
    1083         252 :   ep = (entree*)pari_malloc(sizeof(entree) + strlen(s) + 1);
    1084         252 :   u = (char *)initial_value(ep);
    1085         252 :   ep->valence = EpVAR;
    1086         252 :   ep->name = u; strcpy(u,s);
    1087         252 :   ep->value = gen_0; /* in case geval is called */
    1088         252 :   varentries_reset(n, ep);
    1089         252 : }
    1090             : 
    1091             : static int
    1092        5136 : cmp_by_var(void *E,GEN x, GEN y)
    1093        5136 : { (void)E; return varncmp((long)x,(long)y); }
    1094             : GEN
    1095         994 : vars_sort_inplace(GEN z)
    1096         994 : { gen_sort_inplace(z,NULL,cmp_by_var,NULL); return z; }
    1097             : GEN
    1098         154 : vars_to_RgXV(GEN h)
    1099             : {
    1100         154 :   long i, l = lg(h);
    1101         154 :   GEN z = cgetg(l, t_VEC);
    1102         154 :   for (i = 1; i < l; i++) gel(z,i) = pol_x(h[i]);
    1103         154 :   return z;
    1104             : }
    1105             : GEN
    1106         987 : gpolvar(GEN x)
    1107             : {
    1108             :   long v;
    1109         987 :   if (!x) {
    1110         140 :     GEN h = hash_values(h_polvar);
    1111         140 :     return vars_to_RgXV(vars_sort_inplace(h));
    1112             :   }
    1113         847 :   if (typ(x)==t_PADIC) return gcopy( gel(x,2) );
    1114         840 :   v = gvar(x);
    1115         840 :   if (v==NO_VARIABLE) return gen_0;
    1116         777 :   return pol_x(v);
    1117             : }
    1118             : 
    1119             : static void
    1120     1870100 : fill_hashtable_single(entree **table, entree *ep)
    1121             : {
    1122     1870100 :   EpSETSTATIC(ep);
    1123     1870100 :   insertep(ep, table,  hashvalue(ep->name));
    1124     1870100 :   if (ep->code) ep->arity = check_proto(ep->code);
    1125     1870100 :   ep->pvalue = NULL;
    1126     1870100 : }
    1127             : 
    1128             : void
    1129        4646 : pari_fill_hashtable(entree **table, entree *ep)
    1130             : {
    1131        4646 :   for ( ; ep->name; ep++) fill_hashtable_single(table, ep);
    1132        4646 : }
    1133             : 
    1134             : void
    1135           0 : pari_add_function(entree *ep)
    1136             : {
    1137           0 :   fill_hashtable_single(functions_hash, ep);
    1138           0 : }
    1139             : 
    1140             : /********************************************************************/
    1141             : /**                                                                **/
    1142             : /**                        SIMPLE GP FUNCTIONS                     **/
    1143             : /**                                                                **/
    1144             : /********************************************************************/
    1145             : 
    1146             : #define ALIAS(ep) (entree *) ((GEN)ep->value)[1]
    1147             : 
    1148             : entree *
    1149     6125681 : do_alias(entree *ep)
    1150             : {
    1151     6125681 :   while (ep->valence == EpALIAS) ep = ALIAS(ep);
    1152     6125681 :   return ep;
    1153             : }
    1154             : 
    1155             : void
    1156          28 : alias0(const char *s, const char *old)
    1157             : {
    1158             :   entree *ep, *e;
    1159             :   GEN x;
    1160             : 
    1161          28 :   ep = fetch_entry(old);
    1162          28 :   e  = fetch_entry(s);
    1163          28 :   if (EpVALENCE(e) != EpALIAS && EpVALENCE(e) != EpNEW)
    1164           0 :     pari_err(e_MISC,"can't replace an existing symbol by an alias");
    1165          28 :   freeep(e);
    1166          28 :   x = cgetg_block(2, t_VECSMALL); gel(x,1) = (GEN)ep;
    1167          28 :   e->value=x; e->valence=EpALIAS;
    1168          28 : }
    1169             : 
    1170             : GEN
    1171    12855417 : ifpari(GEN g, GEN a/*closure*/, GEN b/*closure*/)
    1172             : {
    1173    12855417 :   if (gequal0(g)) /* false */
    1174     9962357 :     return b? closure_evalgen(b): gnil;
    1175             :   else /* true */
    1176     2893060 :     return a? closure_evalgen(a): gnil;
    1177             : }
    1178             : 
    1179             : void
    1180    39977153 : ifpari_void(GEN g, GEN a/*closure*/, GEN b/*closure*/)
    1181             : {
    1182    39977153 :   if (gequal0(g)) /* false */
    1183    39272259 :   { if (b) closure_evalvoid(b); }
    1184             :   else /* true */
    1185      704894 :   { if (a) closure_evalvoid(a); }
    1186    39977132 : }
    1187             : 
    1188             : GEN
    1189       31283 : ifpari_multi(GEN g, GEN a/*closure*/)
    1190             : {
    1191       31283 :   long i, nb = lg(a)-1;
    1192       31283 :   if (!gequal0(g)) /* false */
    1193        6706 :     return closure_evalgen(gel(a,1));
    1194       42042 :   for(i=2;i<nb;i+=2)
    1195             :   {
    1196       24689 :     GEN g = closure_evalgen(gel(a,i));
    1197       24689 :     if (!g) return g;
    1198       24682 :     if (!gequal0(g))
    1199        7217 :       return closure_evalgen(gel(a,i+1));
    1200             :   }
    1201       17353 :   return i<=nb? closure_evalgen(gel(a,i)): gnil;
    1202             : }
    1203             : 
    1204             : GEN
    1205      268744 : andpari(GEN a, GEN b/*closure*/)
    1206             : {
    1207             :   GEN g;
    1208      268744 :   if (gequal0(a))
    1209       42714 :     return gen_0;
    1210      226030 :   g=closure_evalgen(b);
    1211      226030 :   if (!g) return g;
    1212      226030 :   return gequal0(g)?gen_0:gen_1;
    1213             : }
    1214             : 
    1215             : GEN
    1216    16420103 : orpari(GEN a, GEN b/*closure*/)
    1217             : {
    1218             :   GEN g;
    1219    16420103 :   if (!gequal0(a))
    1220      118887 :     return gen_1;
    1221    16301216 :   g=closure_evalgen(b);
    1222    16301216 :   if (!g) return g;
    1223    16301216 :   return gequal0(g)?gen_0:gen_1;
    1224             : }
    1225             : 
    1226       79932 : GEN gmule(GEN *x, GEN y) { *x = gmul(*x,y); return *x; }
    1227          56 : GEN gdive(GEN *x, GEN y) { *x = gdiv(*x,y); return *x; }
    1228           7 : GEN gdivente(GEN *x, GEN y) { *x = gdivent(*x,y); return *x; }
    1229           7 : GEN gdivrounde(GEN *x, GEN y) { *x = gdivround(*x,y); return *x; }
    1230           7 : GEN gmode(GEN *x, GEN y) { *x = gmod(*x,y); return *x; }
    1231           7 : GEN gshiftle(GEN *x, long n) { *x = gshift(*x,n); return *x; }
    1232           7 : GEN gshiftre(GEN *x, long n) { *x = gshift(*x,-n); return *x; }
    1233     2648566 : GEN gadde(GEN *x, GEN y) { *x = gadd(*x,y); return *x; }
    1234    25675244 : GEN gadd1e(GEN *x) { *x = typ(*x)==t_INT?addiu(*x,1):gaddgs(*x,1); return *x; }
    1235    15455356 : GEN gsube(GEN *x, GEN y) { *x = gsub(*x,y); return *x; }
    1236          14 : GEN gsub1e(GEN *x) { *x = typ(*x)==t_INT?subiu(*x,1):gsubgs(*x,1); return *x; }
    1237             : 
    1238        1392 : GEN gshift_right(GEN x, long n) { return gshift(x,-n); }

Generated by: LCOV version 1.13