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) Coverage Total Hit
Test: PARI/GP v2.19.0 lcov report (development 31057-89c4d54ba6) Lines: 89.5 % 695 622
Test Date: 2026-07-25 17:02:42 Functions: 92.1 % 101 93
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          457 : IS_ID(char c) { return isalnum((unsigned char)c) || c == '_'; }
      45              : long
      46           35 : eval_mnemonic(GEN str, const char *tmplate)
      47              : {
      48              :   const char *arg, *etmplate;
      49           35 :   ulong retval = 0;
      50              : 
      51           35 :   if (typ(str)==t_INT) return itos(str);
      52           35 :   if (typ(str)!=t_STR) pari_err_TYPE("eval_mnemonic",str);
      53              : 
      54           35 :   arg = GSTR(str);
      55           35 :   etmplate = strchr(tmplate, '\n');
      56           35 :   if (!etmplate) etmplate = tmplate + strlen(tmplate);
      57              : 
      58              :   while (1)
      59           43 :   {
      60              :     long numarg;
      61           78 :     const char *e, *id, *negated = NULL;
      62           78 :     int negate = 0; /* Arg has 'no' prefix removed */
      63              :     ulong l;
      64              :     char *buf;
      65              :     static char b[80];
      66              : 
      67           78 :     while (isspace((unsigned char)*arg)) arg++;
      68           78 :     if (!*arg) break;
      69          434 :     e = arg; while (IS_ID(*e)) e++;
      70              :     /* Now the ID is whatever is between arg and e. */
      71           43 :     l = e - arg;
      72           43 :     if (l >= sizeof(b)) pari_err(e_MISC,"id too long in a mnemonic");
      73           43 :     if (!l) pari_err(e_MISC,"mnemonic does not start with an id");
      74           43 :     strncpy(b, arg, l); b[l] = 0;
      75           43 :     arg = e; e = buf = b;
      76           43 :     while ('0' <= *e && *e <= '9') e++;
      77           43 :     if (*e == 0) pari_err(e_MISC,"numeric id in a mnemonic");
      78           43 : FIND:
      79           43 :     id = tmplate;
      80           43 :     while ((id = strstr(id, buf)) && id < etmplate)
      81              :     {
      82           43 :       const char *s = id;
      83           43 :       id += l; if (s[l] != '|') continue; /* False positive */
      84           43 :       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           43 :     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           43 :     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           43 :     if (*id++ != '|') pari_err(e_MISC,"Missing | in mnemonic template");
     103           43 :     e = id;
     104          102 :     while (*e >= '0' && *e <= '9') e++;
     105           43 :     while (isspace((unsigned char)*e)) e++;
     106           43 :     if (*e && *e != ';' && *e != ',')
     107            0 :       pari_err(e_MISC, "Non-numeric argument in mnemonic template");
     108           43 :     numarg = atol(id);
     109           43 :     if (negate) retval &= ~numarg; else retval |= numarg;
     110           43 :     while (isspace((unsigned char)*arg)) arg++;
     111           43 :     if (*arg && !ispunct((unsigned char)*arg++)) /* skip punctuation */
     112            0 :       pari_err(e_MISC,"Junk after id in mnemonic");
     113              :   }
     114           35 :   return retval;
     115              : }
     116              : 
     117              : /********************************************************************/
     118              : /**                                                                **/
     119              : /**                   HASH TABLE MANIPULATIONS                     **/
     120              : /**                                                                **/
     121              : /********************************************************************/
     122              : static void
     123      2782497 : insertep(entree *ep, entree **table, ulong hash)
     124              : {
     125      2782497 :   ep->hash = hash;
     126      2782497 :   hash %= functions_tblsz;
     127      2782497 :   ep->next = table[hash];
     128      2782497 :   table[hash] = ep;
     129      2782497 : }
     130              : 
     131              : static entree *
     132        36800 : initep(const char *name, long len)
     133              : {
     134        36800 :   const long add = 4*sizeof(long);
     135        36800 :   entree *ep = (entree *) pari_calloc(sizeof(entree) + add + len+1);
     136        36800 :   entree *ep1 = initial_value(ep);
     137        36800 :   char *u = (char *) ep1 + add;
     138        36800 :   ep->name    = u; memcpy(u, name,len); u[len]=0;
     139        36800 :   ep->valence = EpNEW;
     140        36800 :   ep->value   = NULL;
     141        36800 :   ep->menu    = 0;
     142        36800 :   ep->code    = NULL;
     143        36800 :   ep->help    = NULL;
     144        36800 :   ep->pvalue  = NULL;
     145        36800 :   ep->arity   = 0;
     146        36800 :   return ep;
     147              : }
     148              : 
     149              : /* Look for s of length len in T; if 'insert', insert if missing */
     150              : static entree *
     151     31644860 : findentry(const char *s, long len, entree **T, int insert)
     152              : {
     153     31644860 :   ulong hash = hash_str_len(s, len);
     154              :   entree *ep;
     155    344532098 :   for (ep = T[hash % functions_tblsz]; ep; ep = ep->next)
     156    344495374 :     if (ep->hash == hash)
     157              :     {
     158     31608178 :       const char *t = ep->name;
     159     31608178 :       if (!strncmp(t, s, len) && !t[len]) return ep;
     160              :     }
     161              :   /* not found */
     162        36724 :   if (insert) { ep = initep(s,len); insertep(ep, T, hash); }
     163        36724 :   return ep;
     164              : }
     165              : entree *
     166          980 : pari_is_default(const char *s)
     167          980 : { return findentry(s, strlen(s), defaults_hash, 0); }
     168              : entree *
     169      9239193 : is_entry(const char *s)
     170      9239193 : { return findentry(s, strlen(s), functions_hash, 0); }
     171              : entree *
     172     22404687 : fetch_entry_raw(const char *s, long len)
     173     22404687 : { return findentry(s, len, functions_hash, 1); }
     174              : entree *
     175       454263 : 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       804235 : readseq_i(char *t)
     184              : {
     185       804235 :   if (gp_meta(t,0)) return gnil;
     186       804235 :   return closure_evalres(pari_compile_str(t));
     187              : }
     188              : GEN
     189       804235 : readseq(char *t)
     190       804235 : { pari_sp av = avma; return gc_upto(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 gc_upto(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_prec(const char *s, long prec)
     202              : {
     203              :   GEN x;
     204            0 :   push_localbitprec(prec);
     205            0 :   x = gp_read_str(s);
     206            0 :   pop_localprec();
     207            0 :   return x;
     208              : }
     209              : 
     210              : /* Deprecated, keep for backward compatibility */
     211              : GEN
     212            0 : gp_read_str_bitprec(const char *s, long bitprec)
     213            0 : { return gp_read_str_prec(s, bitprec); }
     214              : 
     215              : /* valid return type */
     216              : static int
     217      2721180 : isreturn(char c)
     218      2721180 : { return c == 'l' || c == 'v' || c == 'i' || c == 'm' || c == 'u'; }
     219              : 
     220              : /* if is known that 2 commas follow s; base-10 signed integer followed
     221              :  * by comma? */
     222              : static int
     223       532471 : is_long(const char *s)
     224              : {
     225       532471 :   while (isspace((unsigned char)*s)) s++;
     226       532471 :   if (*s == '+' || *s == '-') s++;
     227      1068732 :   while (isdigit((unsigned char)*s)) s++;
     228       532471 :   return *s == ',';
     229              : }
     230              : /* if is known that 2 commas follow s; base-10 unsigned integer followed
     231              :  * by comma? */
     232              : static int
     233         1895 : is_ulong(const char *s)
     234              : {
     235         1895 :   while (isspace((unsigned char)*s)) s++;
     236         1895 :   if (*s == '+') s++;
     237         3790 :   while (isdigit((unsigned char)*s)) s++;
     238         1895 :   return *s == ',';
     239              : }
     240              : static long
     241      2721180 : check_proto(const char *code)
     242              : {
     243      2721180 :   long arity = 0;
     244      2721180 :   const char *s = code;
     245      2721180 :   if (isreturn(*s)) s++;
     246      9272163 :   while (*s && *s != '\n') switch (*s++)
     247              :   {
     248      4792447 :     case '&':
     249              :     case 'C':
     250              :     case 'G':
     251              :     case 'I':
     252              :     case 'J':
     253              :     case 'U':
     254              :     case 'L':
     255              :     case 'M':
     256              :     case 'P':
     257              :     case 'W':
     258              :     case 'f':
     259              :     case 'n':
     260              :     case 'p':
     261              :     case 'b':
     262              :     case 'r':
     263      4792447 :       arity++; break;
     264       145915 :     case 'E':
     265              :     case 's':
     266       145915 :       if (*s == '*') s++;
     267       145915 :       arity++; break;
     268      1407961 :     case 'D':
     269      1407961 :       switch(*s)
     270              :       {
     271       828115 :         case 'G': case '&': case 'n': case 'I': case 'E':
     272       828115 :         case 'P': case 's': case 'r': s++; arity++; break;
     273        20845 :         case 'V': s++; break;
     274            0 :         case 0:
     275            0 :           pari_err(e_SYNTAX,"function has incomplete prototype", s,code);
     276            0 :           break;
     277       559001 :         default:
     278              :         {
     279              :           const char *p;
     280              :           long i;
     281      2836695 :           for(i = 0, p = s; *p && i < 2; p++) i += *p==','; /* skip 2 commas */
     282       559001 :           if (i < 2) pari_err(e_SYNTAX,"missing comma",s,code);
     283       559001 :           arity++;
     284       559001 :           switch(p[-2])
     285              :           {
     286       532471 :             case 'L':
     287       532471 :               if (!is_long(s)) pari_err(e_SYNTAX,"not a long",s,code);
     288       532471 :               break;
     289         1895 :             case 'U':
     290         1895 :               if (!is_ulong(s)) pari_err(e_SYNTAX,"not an ulong",s,code);
     291         1895 :               break;
     292        24635 :             case 'G': case 'r': case 's': case 'M':
     293        24635 :               break;
     294            0 :             default: pari_err(e_SYNTAX,"incorrect type",s-2,code);
     295              :           }
     296       559001 :           s = p;
     297              :         }
     298              :       }
     299      1407961 :       break;
     300       204660 :     case 'V':
     301              :     case '=':
     302       204660 :     case ',': break;
     303            0 :     case '\n': break; /* Before the mnemonic */
     304            0 :     default:
     305            0 :       if (isreturn(s[-1]))
     306            0 :         pari_err(e_SYNTAX, "this code has to come first", s-1, code);
     307            0 :       pari_err(e_SYNTAX, "unknown parser code", s-1, code);
     308              :   }
     309      2721180 :   if (arity > 20) pari_err_IMPL("functions with more than 20 parameters");
     310      2721180 :   return arity;
     311              : }
     312              : static void
     313            0 : check_name(const char *name)
     314              : {
     315            0 :   const char *s = name;
     316            0 :   if (isalpha((unsigned char)*s))
     317            0 :     while (is_keyword_char(*++s)) /* empty */;
     318            0 :   if (*s) pari_err(e_SYNTAX,"not a valid identifier", s, name);
     319            0 : }
     320              : 
     321              : entree *
     322            0 : install(void *f, const char *name, const char *code)
     323              : {
     324            0 :   long arity = check_proto(code);
     325              :   entree *ep;
     326              : 
     327            0 :   check_name(name);
     328            0 :   ep = fetch_entry(name);
     329            0 :   if (ep->valence != EpNEW)
     330              :   {
     331            0 :     if (ep->valence != EpINSTALL)
     332            0 :       pari_err(e_MISC,"[install] identifier '%s' already in use", name);
     333            0 :     pari_warn(warner, "[install] updating '%s' prototype; module not reloaded", name);
     334            0 :     if (ep->code) pari_free((void*)ep->code);
     335              :   }
     336              :   else
     337              :   {
     338            0 :     ep->value = f;
     339            0 :     ep->valence = EpINSTALL;
     340              :   }
     341            0 :   ep->code = pari_strdup(code);
     342            0 :   ep->arity = arity; return ep;
     343              : }
     344              : 
     345              : static void
     346           14 : killep(entree *ep)
     347              : {
     348           14 :   GEN p = (GEN)initial_value(ep);
     349           14 :   freeep(ep);
     350           14 :   *p = 0; /* otherwise pari_var_create won't regenerate it */
     351           14 :   ep->valence = EpNEW;
     352           14 :   ep->value   = NULL;
     353           14 :   ep->pvalue  = NULL;
     354           14 : }
     355              : /* Kill ep, i.e free all memory it references, and reset to initial value */
     356              : void
     357           14 : kill0(const char *e)
     358              : {
     359           14 :   entree *ep = is_entry(e);
     360           14 :   if (!ep || EpSTATIC(ep)) pari_err(e_MISC,"can't kill that");
     361           14 :   killep(ep);
     362           14 : }
     363              : 
     364              : void
     365           42 : addhelp(const char *e, const char *s)
     366              : {
     367           42 :   entree *ep = fetch_entry(e);
     368           42 :   void *f = (void *) ep->help;
     369           42 :   ep->help = pari_strdup(s);
     370           42 :   if (f && !EpSTATIC(ep)) pari_free(f);
     371           42 : }
     372              : 
     373              : /*******************************************************************/
     374              : /*                                                                 */
     375              : /*                              PARSER                             */
     376              : /*                                                                 */
     377              : /*******************************************************************/
     378              : 
     379              : #ifdef LONG_IS_64BIT
     380              : static const long MAX_DIGITS  = 19;
     381              : #else
     382              : static const long MAX_DIGITS  = 9;
     383              : #endif
     384              : 
     385              : static const long MAX_XDIGITS = BITS_IN_LONG>>2;
     386              : static const long MAX_BDIGITS = BITS_IN_LONG;
     387              : 
     388              : static int
     389    140374906 : ishex(const char **s)
     390              : {
     391    140374906 :   if (**s == '0' && ((*s)[1] == 'x' || (*s)[1] == 'X' ))
     392              :   {
     393          130 :     *s += 2;
     394          130 :     return 1;
     395              :   }
     396              :   else
     397    140374776 :     return 0;
     398              : }
     399              : 
     400              : static int
     401    140374962 : isbin(const char **s)
     402              : {
     403    140374962 :   if (**s == '0' && ((*s)[1] == 'b' || (*s)[1] == 'B' ))
     404              :   {
     405           56 :     *s += 2;
     406           56 :     return 1;
     407              :   }
     408              :   else
     409    140374906 :     return 0;
     410              : }
     411              : 
     412              : static ulong
     413           37 : bin_number_len(const char *s, long n)
     414              : {
     415           37 :   ulong m = 0;
     416              :   long i;
     417         1073 :   for (i = 0; i < n; i++,s++)
     418         1036 :     m = 2*m + (*s - '0');
     419           37 :   return m;
     420              : }
     421              : 
     422              : static int
     423         1064 : pari_isbdigit(int c)
     424              : {
     425         1064 :   return c=='0' || c=='1';
     426              : }
     427              : 
     428              : static ulong
     429          108 : hex_number_len(const char *s, long n)
     430              : {
     431          108 :   ulong m = 0;
     432              :   long i;
     433         1249 :   for(i = 0; i < n; i++, s++)
     434              :   {
     435              :     ulong c;
     436         1141 :     if( *s >= '0' && *s <= '9')
     437          566 :       c = *s - '0';
     438          575 :     else if( *s >= 'A' && *s <= 'F')
     439           42 :       c = *s - 'A' + 10;
     440              :     else
     441          533 :       c = *s - 'a' + 10;
     442         1141 :     m = 16*m + c;
     443              :   }
     444          108 :   return m;
     445              : }
     446              : 
     447              : static GEN
     448          102 : strtobin_len(const char *s, long n, long B, ulong num(const char *s, long n))
     449              : {
     450          102 :   long i, l = (n+B-1)/B;
     451              :   GEN N, Np;
     452          102 :   N = cgetipos(l+2);
     453          102 :   Np = int_LSW(N);
     454          145 :   for (i=1; i<l; i++, Np = int_nextW(Np))
     455           43 :     uel(Np, 0) = num(s+n-i*B, B);
     456          102 :   uel(Np, 0) = num(s, n-(i-1)*B);
     457          102 :   return int_normalize(N, 0);
     458              : }
     459              : 
     460              : static GEN
     461          102 : binary_read(const char **ps, long B, int is(int), ulong num(const char *s, long n))
     462              : {
     463          102 :   const char *s = *ps;
     464         2279 :   while (is((unsigned char)**ps)) (*ps)++;
     465          102 :   return strtobin_len(s, *ps-s, B, num);
     466              : }
     467              : 
     468              : static GEN
     469           28 : bin_read(const char **ps)
     470              : {
     471           28 :   return binary_read(ps, MAX_BDIGITS, pari_isbdigit, bin_number_len);
     472              : }
     473              : 
     474              : static GEN
     475           74 : hex_read(const char **ps)
     476              : {
     477           74 :   return binary_read(ps, MAX_XDIGITS, isxdigit, hex_number_len);
     478              : }
     479              : 
     480              : static ulong
     481      4140048 : dec_number_len(const char *s, long B)
     482              : {
     483      4140048 :   ulong m = 0;
     484              :   long n;
     485     62396631 :   for (n = 0; n < B; n++,s++)
     486     58256583 :     m = 10*m + (*s - '0');
     487      4140048 :   return m;
     488              : }
     489              : 
     490              : static GEN
     491      1042580 : dec_strtoi_len(const char *s, long n)
     492              : {
     493      1042580 :   const long B = MAX_DIGITS;
     494      1042580 :   long i, l = (n+B-1)/B;
     495      1042580 :   GEN V = cgetg(l+1, t_VECSMALL);
     496      4140048 :   for (i=1; i<l; i++)
     497      3097468 :     uel(V,i) = dec_number_len(s+n-i*B, B);
     498      1042580 :   uel(V, i) = dec_number_len(s, n-(i-1)*B);
     499      1042580 :   return fromdigitsu(V, powuu(10, B));
     500              : }
     501              : 
     502              : static GEN
     503      1042580 : dec_read_more(const char **ps)
     504              : {
     505      1042580 :   pari_sp av = avma;
     506      1042580 :   const char *s = *ps;
     507     59299163 :   while (isdigit((unsigned char)**ps)) (*ps)++;
     508      1042580 :   return gc_INT(av, dec_strtoi_len(s, *ps-s));
     509              : }
     510              : 
     511              : static ulong
     512     31718742 : number(int *n, const char **s)
     513              : {
     514     31718742 :   ulong m = 0;
     515    128196372 :   for (*n = 0; *n < MAX_DIGITS && isdigit((unsigned char)**s); (*n)++,(*s)++)
     516     96477630 :     m = 10*m + (**s - '0');
     517     31718742 :   return m;
     518              : }
     519              : 
     520              : static GEN
     521     31643177 : dec_read(const char **s)
     522              : {
     523              :   int nb;
     524     31643177 :   ulong y  = number(&nb, s);
     525     31643177 :   if (nb < MAX_DIGITS)
     526     30600597 :     return utoi(y);
     527      1042580 :   *s -= MAX_DIGITS;
     528      1042580 :   return dec_read_more(s);
     529              : }
     530              : 
     531              : static GEN
     532         5690 : real_read_more(GEN y, const char **ps)
     533              : {
     534         5690 :   pari_sp av = avma;
     535         5690 :   const char *s = *ps;
     536         5690 :   GEN z = dec_read(ps);
     537         5690 :   long e = *ps-s;
     538         5690 :   return gc_INT(av, addmulii(z, powuu(10, e), y));
     539              : }
     540              : 
     541              : static long
     542        75565 : exponent(const char **pts)
     543              : {
     544        75565 :   const char *s = *pts;
     545              :   long n;
     546              :   int nb;
     547        75565 :   switch(*++s)
     548              :   {
     549        75383 :     case '-': s++; n = -(long)number(&nb, &s); break;
     550            0 :     case '+': s++; /* Fall through */
     551          182 :     default: n = (long)number(&nb, &s);
     552              :   }
     553        75565 :   *pts = s; return n;
     554              : }
     555              : 
     556              : static GEN
     557          203 : real_0_digits(long n) {
     558          203 :   long b = (n > 0)? (long)(n/LOG10_2): (long)-((-n)/LOG10_2 + 1);
     559          203 :   return real_0_bit(b);
     560              : }
     561              : 
     562              : static GEN
     563        86710 : real_read(pari_sp av, const char **s, GEN y, long prec)
     564              : {
     565        86710 :   long l, n = 0;
     566        86710 :   switch(**s)
     567              :   {
     568            0 :     default: return y; /* integer */
     569        12510 :     case '.':
     570              :     {
     571        12510 :       const char *old = ++*s;
     572        12510 :       if (isalpha((unsigned char)**s) || **s=='.')
     573              :       {
     574         1344 :         if (**s == 'E' || **s == 'e') {
     575         1344 :           n = exponent(s);
     576         1344 :           if (!signe(y)) { set_avma(av); return real_0_digits(n); }
     577         1288 :           break;
     578              :         }
     579            0 :         --*s; return y; /* member */
     580              :       }
     581        11166 :       if (isdigit((unsigned char)**s)) y = real_read_more(y, s);
     582        11166 :       n = old - *s;
     583        11166 :       if (**s != 'E' && **s != 'e')
     584              :       {
     585        11145 :         if (!signe(y)) { set_avma(av); return real_0(prec); }
     586         9878 :         break;
     587              :       }
     588              :     }
     589              :     /* Fall through */
     590              :     case 'E': case 'e':
     591        74221 :       n += exponent(s);
     592        74221 :       if (!signe(y)) { set_avma(av); return real_0_digits(n); }
     593              :   }
     594        85240 :   l = nbits2prec(bit_accuracy(lgefint(y)));
     595        85240 :   if (l < prec) l = prec; else prec = l;
     596        85240 :   if (!n) return itor(y, prec);
     597        80324 :   incrprec(l);
     598        80324 :   y = itor(y, l);
     599        80324 :   if (n > 0)
     600           84 :     y = mulrr(y, rpowuu(10UL, (ulong)n, l));
     601              :   else
     602        80240 :     y = divrr(y, rpowuu(10UL, (ulong)-n, l));
     603        80324 :   return gc_leaf(av, rtor(y, prec));
     604              : }
     605              : 
     606              : static GEN
     607     31550879 : int_read(const char **s)
     608              : {
     609              :   GEN y;
     610     31550879 :   if (isbin(s))
     611           28 :     y = bin_read(s);
     612     31550851 :   else if (ishex(s))
     613           74 :     y = hex_read(s);
     614              :   else
     615     31550777 :     y = dec_read(s);
     616     31550879 :   return y;
     617              : }
     618              : 
     619              : GEN
     620     31550879 : strtoi(const char *s) { return int_read(&s); }
     621              : 
     622              : GEN
     623        86710 : strtor(const char *s, long prec)
     624              : {
     625        86710 :   pari_sp av = avma;
     626        86710 :   GEN y = dec_read(&s);
     627        86710 :   y = real_read(av, &s, y, prec);
     628        86710 :   if (typ(y) == t_REAL) return y;
     629            0 :   return gc_leaf(av, itor(y, prec));
     630              : }
     631              : 
     632              : static void
     633     31543719 : skipdigits(char **lex) {
     634    168462116 :   while (isdigit((unsigned char)**lex)) ++*lex;
     635     31543719 : }
     636              : 
     637              : static int
     638     31535645 : skipexponent(char **lex)
     639              : {
     640     31535645 :   char *old=*lex;
     641     31535645 :   if ((**lex=='e' || **lex=='E'))
     642              :   {
     643         1155 :     ++*lex;
     644         1155 :     if ( **lex=='+' || **lex=='-' ) ++*lex;
     645         1155 :     if (!isdigit((unsigned char)**lex))
     646              :     {
     647          469 :       *lex=old;
     648          469 :       return KINTEGER;
     649              :     }
     650          686 :     skipdigits(lex);
     651          686 :     return KREAL;
     652              :   }
     653     31534490 :   return KINTEGER;
     654              : }
     655              : 
     656              : static int
     657     31537401 : skipconstante(char **lex)
     658              : {
     659     31537401 :   skipdigits(lex);
     660     31537401 :   if (**lex=='.')
     661              :   {
     662        20212 :     char *old = ++*lex;
     663        20212 :     if (**lex == '.') { --*lex; return KINTEGER; }
     664        18456 :     if (isalpha((unsigned char)**lex))
     665              :     {
     666        12824 :       skipexponent(lex);
     667        12824 :       if (*lex == old)
     668              :       {
     669        12656 :         --*lex; /* member */
     670        12656 :         return KINTEGER;
     671              :       }
     672          168 :       return KREAL;
     673              :     }
     674         5632 :     skipdigits(lex);
     675         5632 :     skipexponent(lex);
     676         5632 :     return KREAL;
     677              :   }
     678     31517189 :   return skipexponent(lex);
     679              : }
     680              : 
     681              : static void
     682      3822335 : skipstring(char **lex)
     683              : {
     684     30148521 :   while (**lex)
     685              :   {
     686     30149169 :     while (**lex == '\\') *lex+=2;
     687     30148521 :     if (**lex == '"')
     688              :     {
     689      3822335 :       if ((*lex)[1] != '"') break;
     690            0 :       *lex += 2; continue;
     691              :     }
     692     26326186 :     (*lex)++;
     693              :   }
     694      3822335 : }
     695              : 
     696              : int
     697    114191039 : pari_lex(union token_value *yylval, struct node_loc *yylloc, char **lex)
     698              : {
     699              :   (void) yylval;
     700    114191039 :   yylloc->start=*lex;
     701    114191039 :   if (!**lex)
     702              :   {
     703       937517 :     yylloc->end=*lex;
     704       937517 :     return 0;
     705              :   }
     706    113253522 :   if (isalpha((unsigned char)**lex))
     707              :   {
     708      2649818 :     while (is_keyword_char(**lex)) ++*lex;
     709       592643 :     yylloc->end=*lex;
     710       592643 :     return KENTRY;
     711              :   }
     712    112660879 :   if (**lex=='"')
     713              :   {
     714      3822335 :     ++*lex;
     715      3822335 :     skipstring(lex);
     716      3822335 :     if (!**lex)
     717            0 :       compile_err("run-away string",*lex-1);
     718      3822335 :     ++*lex;
     719      3822335 :     yylloc->end=*lex;
     720      3822335 :     return KSTRING;
     721              :   }
     722    108838544 :   if (**lex == '.')
     723              :   {
     724              :     int token;
     725        14461 :     if ((*lex)[1]== '.')
     726              :     {
     727         1784 :       *lex+=2; yylloc->end = *lex; return KDOTDOT;
     728              :     }
     729        12677 :     token=skipconstante(lex);
     730        12677 :     if (token==KREAL)
     731              :     {
     732           21 :       yylloc->end = *lex;
     733           21 :       return token;
     734              :     }
     735        12656 :     ++*lex;
     736        12656 :     yylloc->end=*lex;
     737        12656 :     return '.';
     738              :   }
     739    108824083 :   if (isbin((const char**)lex))
     740              :   {
     741         1064 :     while (**lex=='0' || **lex=='1') ++*lex;
     742           28 :     yylloc->end = *lex;
     743           28 :     return KINTEGER;
     744              :   }
     745    108824055 :   if (ishex((const char**)lex))
     746              :   {
     747          903 :     while (isxdigit((unsigned int)**lex)) ++*lex;
     748           56 :     yylloc->end = *lex;
     749           56 :     return KINTEGER;
     750              :   }
     751    108823999 :   if (isdigit((unsigned char)**lex))
     752              :   {
     753     31524724 :     int token=skipconstante(lex);
     754     31524724 :     yylloc->end = *lex;
     755     31524724 :     return token;
     756              :   }
     757     77299275 :   if ((*lex)[1]=='=')
     758        30601 :     switch (**lex)
     759              :     {
     760        12076 :     case '=':
     761        12076 :       if ((*lex)[2]=='=')
     762          343 :       { *lex+=3; yylloc->end = *lex; return KID; }
     763              :       else
     764        11733 :       { *lex+=2; yylloc->end = *lex; return KEQ; }
     765          125 :     case '>':
     766          125 :       *lex+=2; yylloc->end = *lex; return KGE;
     767          237 :     case '<':
     768          237 :       *lex+=2; yylloc->end = *lex; return KLE;
     769          195 :     case '*':
     770          195 :       *lex+=2; yylloc->end = *lex; return KME;
     771           35 :     case '/':
     772           35 :       *lex+=2; yylloc->end = *lex; return KDE;
     773            7 :     case '%':
     774            7 :       if ((*lex)[2]=='=') break;
     775            7 :       *lex+=2; yylloc->end = *lex; return KMODE;
     776         2303 :     case '!':
     777         2303 :       if ((*lex)[2]=='=') break;
     778         2303 :       *lex+=2; yylloc->end = *lex; return KNE;
     779            7 :     case '\\':
     780            7 :       *lex+=2; yylloc->end = *lex; return KEUCE;
     781          229 :     case '+':
     782          229 :       *lex+=2; yylloc->end = *lex; return KPE;
     783           63 :     case '-':
     784           63 :       *lex+=2; yylloc->end = *lex; return KSE;
     785              :     }
     786     77283998 :   if (**lex==')' && (*lex)[1]=='-' && (*lex)[2]=='>')
     787              :   {
     788         4121 :     *lex+=3; yylloc->end = *lex; return KPARROW;
     789              :   }
     790     77279877 :   if (**lex=='-' && (*lex)[1]=='>')
     791              :   {
     792         1409 :     *lex+=2; yylloc->end = *lex; return KARROW;
     793              :   }
     794     77278468 :   if (**lex=='<' && (*lex)[1]=='>')
     795              :   {
     796            0 :     *lex+=2; yylloc->end = *lex; return KNE;
     797              :   }
     798     77278468 :   if (**lex=='\\' && (*lex)[1]=='/')
     799           35 :     switch((*lex)[2])
     800              :     {
     801            7 :     case '=':
     802            7 :       *lex+=3; yylloc->end = *lex; return KDRE;
     803           28 :     default:
     804           28 :       *lex+=2; yylloc->end = *lex; return KDR;
     805              :     }
     806     77278433 :   if ((*lex)[1]==**lex)
     807      8999398 :     switch (**lex)
     808              :     {
     809          812 :     case '&':
     810          812 :       *lex+=2; yylloc->end = *lex; return KAND;
     811          462 :     case '|':
     812          462 :       *lex+=2; yylloc->end = *lex; return KOR;
     813          190 :     case '+':
     814          190 :       *lex+=2; yylloc->end = *lex; return KPP;
     815           28 :     case '-':
     816           28 :       *lex+=2; yylloc->end = *lex; return KSS;
     817           28 :     case '>':
     818           28 :       if ((*lex)[2]=='=') { *lex+=3; yylloc->end = *lex; return KSRE;}
     819           21 :       *lex+=2; yylloc->end = *lex; return KSR;
     820          154 :     case '<':
     821          154 :       if ((*lex)[2]=='=')
     822            7 :       { *lex+=3; yylloc->end = *lex; return KSLE; }
     823          147 :       *lex+=2; yylloc->end = *lex; return KSL;
     824              :     }
     825     77276759 :   yylloc->end = *lex+1;
     826     77276759 :   return (unsigned char) *(*lex)++;
     827              : }
     828              : 
     829              : /********************************************************************/
     830              : /*                                                                  */
     831              : /*                Formal variables management                       */
     832              : /*                                                                  */
     833              : /********************************************************************/
     834              : static THREAD long max_priority, min_priority;
     835              : static THREAD long max_avail; /* max variable not yet used */
     836              : static THREAD long nvar; /* first GP free variable */
     837              : static hashtable *h_polvar;
     838              : 
     839              : void
     840       523432 : varstate_save(struct pari_varstate *s)
     841              : {
     842       523432 :   s->nvar = nvar;
     843       523432 :   s->max_avail = max_avail;
     844       523432 :   s->max_priority = max_priority;
     845       523432 :   s->min_priority = min_priority;
     846       523432 : }
     847              : 
     848              : static void
     849         9494 : varentries_set(long v, entree *ep)
     850              : {
     851         9494 :   hash_insert(h_polvar, (void*)ep->name, (void*)v);
     852         9494 :   varentries[v] = ep;
     853         9494 : }
     854              : static int
     855         3010 : _given_value(void *E, hashentry *e) { return e->val == E; }
     856              : 
     857              : static void
     858         3177 : varentries_unset(long v)
     859              : {
     860         3177 :   entree *ep = varentries[v];
     861         3177 :   if (ep)
     862              :   {
     863         3010 :     hashentry *e = hash_remove_select(h_polvar, (void*)ep->name, (void*)v,
     864              :         _given_value);
     865         3010 :     if (!e) pari_err_BUG("varentries_unset [unknown var]");
     866         3010 :     varentries[v] = NULL;
     867         3010 :     pari_free(e);
     868         3010 :     if (v <= nvar && ep == is_entry(ep->name))
     869         3003 :     { /* known to the GP interpreter; entree in functions_hash is permanent */
     870         3003 :       GEN p = (GEN)initial_value(ep);
     871         3003 :       if (ep->value == p) { ep->value = NULL; ep->valence = EpNEW; }
     872         3003 :       *p = 0;
     873              :     }
     874              :     else /* from name_var() or a direct pari_var_create() */
     875            7 :       pari_free(ep);
     876              :  }
     877         3177 : }
     878              : static void
     879          118 : varentries_reset(long v, entree *ep)
     880              : {
     881          118 :   varentries_unset(v);
     882          118 :   varentries_set(v, ep);
     883          118 : }
     884              : 
     885              : static void
     886       389818 : var_restore(struct pari_varstate *s)
     887              : {
     888       389818 :   nvar = s->nvar;
     889       389818 :   max_avail = s->max_avail;
     890       389818 :   max_priority = s->max_priority;
     891       389818 :   min_priority = s->min_priority;
     892       389818 : }
     893              : 
     894              : void
     895        13165 : varstate_restore(struct pari_varstate *s)
     896              : {
     897              :   long i;
     898        16175 :   for (i = nvar-1; i >= s->nvar; i--)
     899              :   {
     900         3010 :     varentries_unset(i);
     901         3010 :     varpriority[i] = -i;
     902              :   }
     903        13214 :   for (i = max_avail+1; i <= s->max_avail; i++)
     904              :   {
     905           49 :     varentries_unset(i);
     906           49 :     varpriority[i] = -i;
     907              :   }
     908        13165 :   var_restore(s);
     909        13165 : }
     910              : 
     911              : void
     912       376653 : pari_set_varstate(long *vp, struct pari_varstate *vs)
     913              : {
     914       376653 :   var_restore(vs);
     915       376653 :   varpriority = (long*)newblock(MAXVARN+2) + 1;
     916       376653 :   memcpy(varpriority-1,vp-1,(MAXVARN+2)*sizeof(long));
     917       376653 : }
     918              : 
     919              : /* must come before destruction of functions_hash */
     920              : void
     921         1887 : pari_var_close(void)
     922              : {
     923         1887 :   GEN h = hash_values(h_polvar);
     924         1887 :   long i, l = lg(h);
     925         8355 :   for (i = 1; i < l; i++)
     926              :   {
     927         6468 :     long v = h[i];
     928         6468 :     entree *ep = varentries[v];
     929         6468 :     if (ep && ep != is_entry(ep->name)) pari_free(ep);
     930              :   }
     931         1887 :   free((void*)varentries);
     932         1887 :   free((void*)(varpriority-1));
     933         1887 :   hash_destroy(h_polvar);
     934         1887 : }
     935              : 
     936              : void
     937         1895 : pari_var_init(void)
     938              : {
     939              :   long i;
     940         1895 :   varentries = (entree**) pari_calloc((MAXVARN+1)*sizeof(entree*));
     941         1895 :   varpriority = (long*)pari_malloc((MAXVARN+2)*sizeof(long)) + 1;
     942         1895 :   varpriority[-1] = 1-LONG_MAX;
     943         1895 :   h_polvar = hash_create_str(100, 0);
     944         1895 :   nvar = 0; max_avail = MAXVARN;
     945         1895 :   max_priority = min_priority = 0;
     946         1895 :   (void)fetch_user_var("x");
     947         1895 :   (void)fetch_user_var("y");
     948              :   /* initialize so that people can use pol_x(i) directly */
     949    111163545 :   for (i = 2; i <= (long)MAXVARN; i++) varpriority[i] = -i;
     950              :   /* reserve varnum 1..9 for static temps with predictable priority wrt x */
     951         1895 :   nvar = 10;
     952         1895 :   min_priority = -MAXVARN;
     953         1895 : }
     954              : long
     955            4 : pari_var_next(void) { return nvar; }
     956              : long
     957            0 : pari_var_next_temp(void) { return max_avail; }
     958              : long
     959       485783 : pari_var_create(entree *ep)
     960              : {
     961       485783 :   GEN p = (GEN)initial_value(ep);
     962              :   long v;
     963       485783 :   if (*p) return varn(p);
     964         9376 :   if (mt_is_thread())
     965            0 :     pari_err(e_MISC,"mt: attempt to create new variable '%s'",ep->name);
     966         9376 :   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
     967         9376 :   v = nvar++;
     968              :   /* set p = pol_x(v) */
     969         9376 :   p[0] = evaltyp(t_POL) | _evallg(4);
     970         9376 :   p[1] = evalsigne(1) | evalvarn(v);
     971         9376 :   gel(p,2) = gen_0;
     972         9376 :   gel(p,3) = gen_1;
     973         9376 :   varentries_set(v, ep);
     974         9376 :   varpriority[v]= min_priority--;
     975         9376 :   return v;
     976              : }
     977              : 
     978              : long
     979      8492497 : delete_var(void)
     980              : { /* user wants to delete one of his/her/its variables */
     981      8492497 :   if (max_avail == MAXVARN) return 0; /* nothing to delete */
     982      8491853 :   max_avail++;
     983      8491853 :   if      (varpriority[max_avail] == min_priority) min_priority++;
     984      8491853 :   else if (varpriority[max_avail] == max_priority) max_priority--;
     985      8491853 :   return max_avail+1;
     986              : }
     987              : long
     988        67748 : fetch_var(void)
     989              : {
     990        67748 :   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
     991        67748 :   varpriority[max_avail] = min_priority--;
     992        67748 :   return max_avail--;
     993              : }
     994              : long
     995      8424706 : fetch_var_higher(void)
     996              : {
     997      8424706 :   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
     998      8424706 :   varpriority[max_avail] = ++max_priority;
     999      8424706 :   return max_avail--;
    1000              : }
    1001              : 
    1002              : static int
    1003           49 : _higher(void *E, hashentry *e)
    1004           49 : { long v = (long)e->val; return (varncmp(v, (long)E) < 0); }
    1005              : static int
    1006           42 : _lower(void *E, hashentry *e)
    1007           42 : { long v = (long)e->val; return (varncmp(v, (long)E) > 0); }
    1008              : 
    1009              : static GEN
    1010          118 : var_register(long v, const char *s)
    1011              : {
    1012          118 :   varentries_reset(v, initep(s, strlen(s)));
    1013          118 :   return pol_x(v);
    1014              : }
    1015              : GEN
    1016          105 : varhigher(const char *s, long w)
    1017              : {
    1018              :   long v;
    1019          105 :   if (w >= 0)
    1020              :   {
    1021           56 :     hashentry *e = hash_select(h_polvar, (void*)s, (void*)w, _higher);
    1022           56 :     if (e) return pol_x((long)e->val);
    1023              :   }
    1024              :   /* no luck: need to create */
    1025           91 :   if (nvar == max_avail) pari_err(e_MISC,"no more variables available");
    1026           91 :   v = nvar++;
    1027           91 :   varpriority[v]= ++max_priority;
    1028           91 :   return var_register(v, s);
    1029              : }
    1030              : GEN
    1031           34 : varlower(const char *s, long w)
    1032              : {
    1033              :   long v;
    1034           34 :   if (w >= 0)
    1035              :   {
    1036           21 :     hashentry *e = hash_select(h_polvar, (void*)s, (void*)w, _lower);
    1037           21 :     if (e) return pol_x((long)e->val);
    1038              :   }
    1039              :   /* no luck: need to create */
    1040           27 :   v = fetch_var();
    1041           27 :   return var_register(v, s);
    1042              : }
    1043              : 
    1044              : long
    1045       454165 : fetch_user_var(const char *s)
    1046              : {
    1047       454165 :   entree *ep = fetch_entry(s);
    1048              :   long v;
    1049       454165 :   switch (EpVALENCE(ep))
    1050              :   {
    1051       450158 :     case EpVAR: return pari_var_create(ep);
    1052         4007 :     case EpNEW: break;
    1053            0 :     default: pari_err(e_MISC, "%s already exists with incompatible valence", s);
    1054              :   }
    1055         4007 :   v = pari_var_create(ep);
    1056         4007 :   ep->valence = EpVAR;
    1057         4007 :   ep->value = initial_value(ep);
    1058         4007 :   return v;
    1059              : }
    1060              : 
    1061              : GEN
    1062            7 : fetch_var_value(long v, GEN t)
    1063              : {
    1064            7 :   entree *ep = varentries[v];
    1065            7 :   if (!ep) return NULL;
    1066            7 :   if (t)
    1067              :   {
    1068            7 :     long vn = localvars_find(t,ep);
    1069            7 :     if (vn) return get_lex(vn);
    1070              :   }
    1071            7 :   return (GEN)ep->value;
    1072              : }
    1073              : 
    1074              : void
    1075            0 : name_var(long n, const char *s)
    1076              : {
    1077              :   entree *ep;
    1078              :   char *u;
    1079              : 
    1080            0 :   if (n < pari_var_next())
    1081            0 :     pari_err(e_MISC, "renaming a GP variable is forbidden");
    1082            0 :   if (n > (long)MAXVARN)
    1083            0 :     pari_err_OVERFLOW("variable number");
    1084              : 
    1085            0 :   ep = (entree*)pari_malloc(sizeof(entree) + strlen(s) + 1);
    1086            0 :   u = (char *)initial_value(ep);
    1087            0 :   ep->valence = EpVAR;
    1088            0 :   ep->name = u; strcpy(u,s);
    1089            0 :   ep->value = gen_0; /* in case geval is called */
    1090            0 :   varentries_reset(n, ep);
    1091            0 : }
    1092              : 
    1093              : static int
    1094         5199 : cmp_by_var(void *E,GEN x, GEN y)
    1095         5199 : { (void)E; return varncmp((long)x,(long)y); }
    1096              : GEN
    1097         1484 : vars_sort_inplace(GEN z)
    1098         1484 : { gen_sort_inplace(z,NULL,cmp_by_var,NULL); return z; }
    1099              : GEN
    1100          231 : vars_to_RgXV(GEN h)
    1101              : {
    1102          231 :   long i, l = lg(h);
    1103          231 :   GEN z = cgetg(l, t_VEC);
    1104         2247 :   for (i = 1; i < l; i++) gel(z,i) = pol_x(h[i]);
    1105          231 :   return z;
    1106              : }
    1107              : GEN
    1108         4655 : gpolvar(GEN x)
    1109              : {
    1110              :   long v;
    1111         4655 :   if (!x) {
    1112          140 :     GEN h = hash_values(h_polvar);
    1113          140 :     return vars_to_RgXV(vars_sort_inplace(h));
    1114              :   }
    1115         4515 :   if (typ(x)==t_PADIC) return icopy(padic_p(x));
    1116         4508 :   v = gvar(x);
    1117         4508 :   if (v==NO_VARIABLE) return gen_0;
    1118         4452 :   return pol_x(v);
    1119              : }
    1120              : 
    1121              : static void
    1122      2745815 : fill_hashtable_single(entree **table, entree *ep)
    1123              : {
    1124      2745815 :   EpSETSTATIC(ep);
    1125      2745815 :   insertep(ep, table, hash_str(ep->name));
    1126      2745815 :   if (ep->code) ep->arity = check_proto(ep->code);
    1127      2745815 :   ep->pvalue = NULL;
    1128      2745815 : }
    1129              : 
    1130              : void
    1131         5677 : pari_fill_hashtable(entree **table, entree *ep)
    1132              : {
    1133      2751492 :   for ( ; ep->name; ep++) fill_hashtable_single(table, ep);
    1134         5677 : }
    1135              : 
    1136              : void
    1137            0 : pari_add_function(entree *ep)
    1138              : {
    1139            0 :   fill_hashtable_single(functions_hash, ep);
    1140            0 : }
    1141              : 
    1142              : /********************************************************************/
    1143              : /**                                                                **/
    1144              : /**                        SIMPLE GP FUNCTIONS                     **/
    1145              : /**                                                                **/
    1146              : /********************************************************************/
    1147              : 
    1148              : GEN
    1149           28 : arity0(GEN C)
    1150              : {
    1151           28 :   if (typ(C)!=t_CLOSURE) pari_err_TYPE("arity", C);
    1152           28 :   return utoi(closure_arity(C));
    1153              : }
    1154              : 
    1155              : #define ALIAS(ep) (entree *) ((GEN)ep->value)[1]
    1156              : 
    1157              : entree *
    1158     21989979 : do_alias(entree *ep)
    1159              : {
    1160     21990035 :   while (ep->valence == EpALIAS) ep = ALIAS(ep);
    1161     21989979 :   return ep;
    1162              : }
    1163              : 
    1164              : void
    1165           28 : alias0(const char *s, const char *old)
    1166              : {
    1167              :   entree *ep, *e;
    1168              :   GEN x;
    1169              : 
    1170           28 :   ep = fetch_entry(old);
    1171           28 :   e  = fetch_entry(s);
    1172           28 :   if (EpVALENCE(e) != EpALIAS && EpVALENCE(e) != EpNEW)
    1173            0 :     pari_err(e_MISC,"can't replace an existing symbol by an alias");
    1174           28 :   freeep(e);
    1175           28 :   x = cgetg_block(2, t_VECSMALL); gel(x,1) = (GEN)ep;
    1176           28 :   e->value=x; e->valence=EpALIAS;
    1177           28 : }
    1178              : 
    1179              : GEN
    1180     13122946 : ifpari(GEN g, GEN a/*closure*/, GEN b/*closure*/)
    1181              : {
    1182     13122946 :   if (gequal0(g)) /* false */
    1183     10095853 :     return b? closure_evalgen(b): gnil;
    1184              :   else /* true */
    1185      3027093 :     return a? closure_evalgen(a): gnil;
    1186              : }
    1187              : 
    1188              : void
    1189     42401688 : ifpari_void(GEN g, GEN a/*closure*/, GEN b/*closure*/)
    1190              : {
    1191     42401688 :   if (gequal0(g)) /* false */
    1192     41140419 :   { if (b) closure_evalvoid(b); }
    1193              :   else /* true */
    1194      1261269 :   { if (a) closure_evalvoid(a); }
    1195     42401667 : }
    1196              : 
    1197              : GEN
    1198        30723 : ifpari_multi(GEN g, GEN a/*closure*/)
    1199              : {
    1200        30723 :   long i, nb = lg(a)-1;
    1201        30723 :   if (!gequal0(g)) /* false */
    1202         6713 :     return closure_evalgen(gel(a,1));
    1203        41496 :   for(i=2;i<nb;i+=2)
    1204              :   {
    1205        24122 :     GEN g = closure_evalgen(gel(a,i));
    1206        24122 :     if (!g) return g;
    1207        24115 :     if (!gequal0(g))
    1208         6629 :       return closure_evalgen(gel(a,i+1));
    1209              :   }
    1210        17374 :   return i<=nb? closure_evalgen(gel(a,i)): gnil;
    1211              : }
    1212              : 
    1213              : GEN
    1214     64287664 : andpari(GEN a, GEN b/*closure*/)
    1215              : {
    1216              :   GEN g;
    1217     64287664 :   if (gequal0(a))
    1218     53970344 :     return gen_0;
    1219     10317320 :   g=closure_evalgen(b);
    1220     10317320 :   if (!g) return g;
    1221     10317320 :   return gequal0(g)?gen_0:gen_1;
    1222              : }
    1223              : 
    1224              : GEN
    1225     16723997 : orpari(GEN a, GEN b/*closure*/)
    1226              : {
    1227              :   GEN g;
    1228     16723997 :   if (!gequal0(a))
    1229       338407 :     return gen_1;
    1230     16385590 :   g=closure_evalgen(b);
    1231     16385590 :   if (!g) return g;
    1232     16385590 :   return gequal0(g)?gen_0:gen_1;
    1233              : }
    1234              : 
    1235              : GEN
    1236       178685 : gmule(GEN *x, GEN y) { *x = gmul(*x,y); return *x; }
    1237              : GEN
    1238           56 : gdive(GEN *x, GEN y) { *x = gdiv(*x,y); return *x; }
    1239              : GEN
    1240            7 : gdivente(GEN *x, GEN y) { *x = gdivent(*x,y); return *x; }
    1241              : GEN
    1242            7 : gdivrounde(GEN *x, GEN y) { *x = gdivround(*x,y); return *x; }
    1243              : GEN
    1244            7 : gmode(GEN *x, GEN y) { *x = gmod(*x,y); return *x; }
    1245              : GEN
    1246            7 : gshiftle(GEN *x, long n) { *x = gshift(*x,n); return *x; }
    1247              : GEN
    1248            7 : gshiftre(GEN *x, long n) { *x = gshift(*x,-n); return *x; }
    1249              : GEN
    1250       536517 : gadde(GEN *x, GEN y) { *x = gadd(*x,y); return *x; }
    1251              : GEN
    1252     25685202 : gadd1e(GEN *x) { *x = typ(*x)==t_INT?addiu(*x,1):gaddgs(*x,1); return *x; }
    1253              : GEN
    1254     15455370 : gsube(GEN *x, GEN y) { *x = gsub(*x,y); return *x; }
    1255              : GEN
    1256        20965 : gsub1e(GEN *x) { *x = typ(*x)==t_INT?subiu(*x,1):gsubgs(*x,1); return *x; }
    1257              : 
    1258              : GEN
    1259         1392 : gshift_right(GEN x, long n) { return gshift(x,-n); }
        

Generated by: LCOV version 2.0-1