Code coverage tests

This page documents the degree to which the PARI/GP source code is tested by our public test suite, distributed with the source distribution in directory src/test/. This is measured by the gcov utility; we then process gcov output using the lcov frond-end.

We test a few variants depending on Configure flags on the pari.math.u-bordeaux.fr machine (x86_64 architecture), and agregate them in the final report:

The target is to exceed 90% coverage for all mathematical modules (given that branches depending on DEBUGLEVEL or DEBUGMEM are not covered). This script is run to produce the results below.

LCOV - code coverage report
Current view: top level - language - anal.c (source / functions) Hit Total Coverage
Test: PARI/GP v2.12.0 lcov report (development 23346-507fdfd83) Lines: 584 634 92.1 %
Date: 2018-12-13 05:42:04 Functions: 91 96 94.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13