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

Generated by: LCOV version 1.14