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 - eval.c (source / functions) Hit Total Coverage
Test: PARI/GP v2.14.0 lcov report (development 27783-affec94c65) Lines: 1252 1790 69.9 %
Date: 2022-07-07 07:34:25 Functions: 115 149 77.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Copyright (C) 2006  The PARI group.
       2             : 
       3             : This file is part of the PARI 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 "opcode.h"
      19             : 
      20             : /********************************************************************/
      21             : /*                                                                  */
      22             : /*                   break/next/return handling                     */
      23             : /*                                                                  */
      24             : /********************************************************************/
      25             : 
      26             : static THREAD long br_status, br_count;
      27             : static THREAD GEN br_res;
      28             : 
      29             : long
      30   145486784 : loop_break(void)
      31             : {
      32   145486784 :   switch(br_status)
      33             :   {
      34          21 :     case br_MULTINEXT :
      35          21 :       if (! --br_count) br_status = br_NEXT;
      36          21 :       return 1;
      37       70274 :     case br_BREAK : if (! --br_count) br_status = br_NONE; /* fall through */
      38       78770 :     case br_RETURN: return 1;
      39       23380 :     case br_NEXT: br_status = br_NONE; /* fall through */
      40             :   }
      41   145407993 :   return 0;
      42             : }
      43             : 
      44             : static void
      45       87985 : reset_break(void)
      46             : {
      47       87985 :   br_status = br_NONE;
      48       87985 :   if (br_res) { gunclone_deep(br_res); br_res = NULL; }
      49       87985 : }
      50             : 
      51             : GEN
      52       40723 : return0(GEN x)
      53             : {
      54       40723 :   GEN y = br_res;
      55       40723 :   br_res = (x && x != gnil)? gcloneref(x): NULL;
      56       40723 :   guncloneNULL_deep(y);
      57       40723 :   br_status = br_RETURN; return NULL;
      58             : }
      59             : 
      60             : GEN
      61       24108 : next0(long n)
      62             : {
      63       24108 :   if (n < 1) pari_err_DOMAIN("next", "n", "<", gen_1, stoi(n));
      64       24101 :   if (n == 1) br_status = br_NEXT;
      65             :   else
      66             :   {
      67          14 :     br_count = n-1;
      68          14 :     br_status = br_MULTINEXT;
      69             :   }
      70       24101 :   return NULL;
      71             : }
      72             : 
      73             : GEN
      74       70330 : break0(long n)
      75             : {
      76       70330 :   if (n < 1) pari_err_DOMAIN("break", "n", "<", gen_1, stoi(n));
      77       70323 :   br_count = n;
      78       70323 :   br_status = br_BREAK; return NULL;
      79             : }
      80             : 
      81             : /*******************************************************************/
      82             : /*                                                                 */
      83             : /*                            VARIABLES                            */
      84             : /*                                                                 */
      85             : /*******************************************************************/
      86             : 
      87             : /* As a rule, ep->value is a clone (COPY). push_val and pop_val are private
      88             :  * functions for use in sumiter: we want a temporary ep->value, which is NOT
      89             :  * a clone (PUSH), to avoid unnecessary copies. */
      90             : 
      91             : enum {PUSH_VAL = 0, COPY_VAL = 1, DEFAULT_VAL = 2, REF_VAL = 3};
      92             : 
      93             : /* ep->args is the stack of old values (INITIAL if initial value, from
      94             :  * installep) */
      95             : typedef struct var_cell {
      96             :   struct var_cell *prev; /* cell attached to previous value on stack */
      97             :   GEN value; /* last value (not including current one, in ep->value) */
      98             :   char flag; /* status of _current_ ep->value: PUSH or COPY ? */
      99             :   long valence; /* valence of entree* attached to 'value', to be restored
     100             :                     * by pop_val */
     101             : } var_cell;
     102             : #define INITIAL NULL
     103             : 
     104             : /* Push x on value stack attached to ep. */
     105             : static void
     106       17025 : new_val_cell(entree *ep, GEN x, char flag)
     107             : {
     108       17025 :   var_cell *v = (var_cell*) pari_malloc(sizeof(var_cell));
     109       17025 :   v->value  = (GEN)ep->value;
     110       17025 :   v->prev   = (var_cell*) ep->pvalue;
     111       17025 :   v->flag   = flag;
     112       17025 :   v->valence= ep->valence;
     113             : 
     114             :   /* beware: f(p) = Nv = 0
     115             :    *         Nv = p; f(Nv) --> this call would destroy p [ isclone ] */
     116       17025 :   ep->value = (flag == COPY_VAL)? gclone(x):
     117           0 :                                   (x && isclone(x))? gcopy(x): x;
     118             :   /* Do this last. In case the clone is <C-C>'ed before completion ! */
     119       17025 :   ep->pvalue= (char*)v;
     120       17025 :   ep->valence=EpVAR;
     121       17025 : }
     122             : 
     123             : /* kill ep->value and replace by preceding one, poped from value stack */
     124             : static void
     125       16640 : pop_val(entree *ep)
     126             : {
     127       16640 :   var_cell *v = (var_cell*) ep->pvalue;
     128       16640 :   if (v != INITIAL)
     129             :   {
     130       16640 :     GEN old_val = (GEN) ep->value; /* protect against SIGINT */
     131       16640 :     ep->value  = v->value;
     132       16640 :     if (v->flag == COPY_VAL) gunclone_deep(old_val);
     133       16640 :     ep->pvalue = (char*) v->prev;
     134       16640 :     ep->valence=v->valence;
     135       16640 :     pari_free((void*)v);
     136             :   }
     137       16640 : }
     138             : 
     139             : void
     140       32948 : freeep(entree *ep)
     141             : {
     142       32948 :   if (EpSTATIC(ep)) return; /* gp function loaded at init time */
     143       32948 :   if (ep->help) {pari_free((void*)ep->help); ep->help=NULL;}
     144       32948 :   if (ep->code) {pari_free((void*)ep->code); ep->code=NULL;}
     145       32948 :   switch(EpVALENCE(ep))
     146             :   {
     147       21896 :     case EpVAR:
     148       38480 :       while (ep->pvalue!=INITIAL) pop_val(ep);
     149       21896 :       break;
     150          28 :     case EpALIAS:
     151          28 :       killblock((GEN)ep->value); ep->value=NULL; break;
     152             :   }
     153             : }
     154             : 
     155             : INLINE void
     156          42 : pushvalue(entree *ep, GEN x) {
     157          42 :   new_val_cell(ep, x, COPY_VAL);
     158          42 : }
     159             : 
     160             : INLINE void
     161          14 : zerovalue(entree *ep)
     162             : {
     163          14 :   var_cell *v = (var_cell*) pari_malloc(sizeof(var_cell));
     164          14 :   v->value  = (GEN)ep->value;
     165          14 :   v->prev   = (var_cell*) ep->pvalue;
     166          14 :   v->flag   = PUSH_VAL;
     167          14 :   v->valence= ep->valence;
     168          14 :   ep->value = gen_0;
     169          14 :   ep->pvalue= (char*)v;
     170          14 :   ep->valence=EpVAR;
     171          14 : }
     172             : 
     173             : /* as above IF ep->value was PUSHed, or was created after block number 'loc'
     174             :    return 0 if not deleted, 1 otherwise [for recover()] */
     175             : int
     176      253472 : pop_val_if_newer(entree *ep, long loc)
     177             : {
     178      253472 :   var_cell *v = (var_cell*) ep->pvalue;
     179             : 
     180      253472 :   if (v == INITIAL) return 0;
     181      223398 :   if (v->flag == COPY_VAL && !pop_entree_block(ep, loc)) return 0;
     182         399 :   ep->value = v->value;
     183         399 :   ep->pvalue= (char*) v->prev;
     184         399 :   ep->valence=v->valence;
     185         399 :   pari_free((void*)v); return 1;
     186             : }
     187             : 
     188             : /* set new value of ep directly to val (COPY), do not save last value unless
     189             :  * it's INITIAL. */
     190             : void
     191    29450750 : changevalue(entree *ep, GEN x)
     192             : {
     193    29450750 :   var_cell *v = (var_cell*) ep->pvalue;
     194    29450750 :   if (v == INITIAL) new_val_cell(ep, x, COPY_VAL);
     195             :   else
     196             :   {
     197    29433767 :     GEN old_val = (GEN) ep->value; /* beware: gunclone_deep may destroy old x */
     198    29433767 :     ep->value = (void *) gclone(x);
     199    29433767 :     if (v->flag == COPY_VAL) gunclone_deep(old_val); else v->flag = COPY_VAL;
     200             :   }
     201    29450750 : }
     202             : 
     203             : INLINE GEN
     204      743449 : copyvalue(entree *ep)
     205             : {
     206      743449 :   var_cell *v = (var_cell*) ep->pvalue;
     207      743449 :   if (v && v->flag != COPY_VAL)
     208             :   {
     209           0 :     ep->value = (void*) gclone((GEN)ep->value);
     210           0 :     v->flag = COPY_VAL;
     211             :   }
     212      743449 :   return (GEN) ep->value;
     213             : }
     214             : 
     215             : INLINE void
     216           0 : err_var(GEN x) { pari_err_TYPE("evaluator [variable name expected]", x); }
     217             : 
     218             : enum chk_VALUE { chk_ERROR, chk_NOCREATE, chk_CREATE };
     219             : 
     220             : INLINE void
     221   121648774 : checkvalue(entree *ep, enum chk_VALUE flag)
     222             : {
     223   121648774 :   if (mt_is_thread())
     224          24 :     pari_err(e_MISC,"mt: attempt to change exported variable '%s'",ep->name);
     225   121648750 :   if (ep->valence==EpNEW)
     226       21427 :     switch(flag)
     227             :     {
     228        4711 :       case chk_ERROR:
     229             :         /* Do nothing until we can report a meaningful error message
     230             :            The extra variable will be cleaned-up anyway */
     231             :       case chk_CREATE:
     232        4711 :         pari_var_create(ep);
     233        4711 :         ep->valence = EpVAR;
     234        4711 :         ep->value = initial_value(ep);
     235        4711 :         break;
     236       16716 :       case chk_NOCREATE:
     237       16716 :         break;
     238             :     }
     239   121648750 :   else if (ep->valence!=EpVAR)
     240           0 :     pari_err(e_MISC, "attempt to change built-in %s", ep->name);
     241   121648750 : }
     242             : 
     243             : INLINE GEN
     244    23308222 : checkvalueptr(entree *ep)
     245             : {
     246    23308222 :   checkvalue(ep, chk_NOCREATE);
     247    23308222 :   return ep->valence==EpNEW? gen_0: (GEN)ep->value;
     248             : }
     249             : 
     250             : /* make GP variables safe for set_avma(top) */
     251             : static void
     252           0 : lvar_make_safe(void)
     253             : {
     254             :   long n;
     255             :   entree *ep;
     256           0 :   for (n = 0; n < functions_tblsz; n++)
     257           0 :     for (ep = functions_hash[n]; ep; ep = ep->next)
     258           0 :       if (EpVALENCE(ep) == EpVAR)
     259             :       { /* make sure ep->value is a COPY */
     260           0 :         var_cell *v = (var_cell*)ep->pvalue;
     261           0 :         if (v && v->flag == PUSH_VAL) {
     262           0 :           GEN x = (GEN)ep->value;
     263           0 :           if (x) changevalue(ep, (GEN)ep->value); else pop_val(ep);
     264             :         }
     265             :       }
     266           0 : }
     267             : 
     268             : static void
     269   105129899 : check_array_index(long c, long l)
     270             : {
     271   105129899 :   if (c < 1) pari_err_COMPONENT("", "<", gen_1, stoi(c));
     272   105129892 :   if (c >= l) pari_err_COMPONENT("", ">", stoi(l-1), stoi(c));
     273   105129850 : }
     274             : 
     275             : GEN*
     276           0 : safegel(GEN x, long l)
     277             : {
     278           0 :   if (!is_matvec_t(typ(x)))
     279           0 :     pari_err_TYPE("safegel",x);
     280           0 :   check_array_index(l, lg(x));
     281           0 :   return &(gel(x,l));
     282             : }
     283             : 
     284             : GEN*
     285           0 : safelistel(GEN x, long l)
     286             : {
     287             :   GEN d;
     288           0 :   if (typ(x)!=t_LIST || list_typ(x)!=t_LIST_RAW)
     289           0 :     pari_err_TYPE("safelistel",x);
     290           0 :   d = list_data(x);
     291           0 :   check_array_index(l, lg(d));
     292           0 :   return &(gel(d,l));
     293             : }
     294             : 
     295             : long*
     296           0 : safeel(GEN x, long l)
     297             : {
     298           0 :   if (typ(x)!=t_VECSMALL)
     299           0 :     pari_err_TYPE("safeel",x);
     300           0 :   check_array_index(l, lg(x));
     301           0 :   return &(x[l]);
     302             : }
     303             : 
     304             : GEN*
     305           0 : safegcoeff(GEN x, long a, long b)
     306             : {
     307           0 :   if (typ(x)!=t_MAT) pari_err_TYPE("safegcoeff", x);
     308           0 :   check_array_index(b, lg(x));
     309           0 :   check_array_index(a, lg(gel(x,b)));
     310           0 :   return &(gcoeff(x,a,b));
     311             : }
     312             : 
     313             : typedef struct matcomp
     314             : {
     315             :   GEN *ptcell;
     316             :   GEN parent;
     317             :   int full_col, full_row;
     318             : } matcomp;
     319             : 
     320             : typedef struct gp_pointer
     321             : {
     322             :   matcomp c;
     323             :   GEN x, ox;
     324             :   entree *ep;
     325             :   long vn;
     326             :   long sp;
     327             : } gp_pointer;
     328             : 
     329             : /* assign res at *pt in "simple array object" p and return it, or a copy.*/
     330             : static void
     331     9697366 : change_compo(matcomp *c, GEN res)
     332             : {
     333     9697366 :   GEN p = c->parent, *pt = c->ptcell;
     334             :   long i, t;
     335             : 
     336     9697366 :   if (typ(p) == t_VECSMALL)
     337             :   {
     338          35 :     if (typ(res) != t_INT || is_bigint(res))
     339          14 :       pari_err_TYPE("t_VECSMALL assignment", res);
     340          21 :     *pt = (GEN)itos(res); return;
     341             :   }
     342     9697331 :   t = typ(res);
     343     9697331 :   if (c->full_row)
     344             :   {
     345      204988 :     if (t != t_VEC) pari_err_TYPE("matrix row assignment", res);
     346      204967 :     if (lg(res) != lg(p)) pari_err_DIM("matrix row assignment");
     347     2105362 :     for (i=1; i<lg(p); i++)
     348             :     {
     349     1900416 :       GEN p1 = gcoeff(p,c->full_row,i); /* Protect against SIGINT */
     350     1900416 :       gcoeff(p,c->full_row,i) = gclone(gel(res,i));
     351     1900416 :       if (isclone(p1)) gunclone_deep(p1);
     352             :     }
     353      204946 :     return;
     354             :   }
     355     9492343 :   if (c->full_col)
     356             :   {
     357      355397 :     if (t != t_COL) pari_err_TYPE("matrix col assignment", res);
     358      355383 :     if (lg(res) != lg(*pt)) pari_err_DIM("matrix col assignment");
     359             :   }
     360             : 
     361     9492322 :   res = gclone(res);
     362     9492322 :   gunclone_deep(*pt);
     363     9492322 :   *pt = res;
     364             : }
     365             : 
     366             : /***************************************************************************
     367             :  **                                                                       **
     368             :  **                           Byte-code evaluator                         **
     369             :  **                                                                       **
     370             :  ***************************************************************************/
     371             : 
     372             : struct var_lex
     373             : {
     374             :   long flag;
     375             :   GEN value;
     376             : };
     377             : 
     378             : struct trace
     379             : {
     380             :   long pc;
     381             :   GEN closure;
     382             : };
     383             : 
     384             : static THREAD long sp, rp, dbg_level;
     385             : static THREAD long *st, *precs;
     386             : static THREAD GEN *locks;
     387             : static THREAD gp_pointer *ptrs;
     388             : static THREAD entree **lvars;
     389             : static THREAD struct var_lex *var;
     390             : static THREAD struct trace *trace;
     391             : static THREAD pari_stack s_st, s_ptrs, s_var, s_trace, s_prec;
     392             : static THREAD pari_stack s_lvars, s_locks;
     393             : 
     394             : static void
     395   159066518 : changelex(long vn, GEN x)
     396             : {
     397   159066518 :   struct var_lex *v=var+s_var.n+vn;
     398   159066518 :   GEN old_val = v->value;
     399   159066518 :   v->value = gclone(x);
     400   159066518 :   if (v->flag == COPY_VAL) gunclone_deep(old_val); else v->flag = COPY_VAL;
     401   159066518 : }
     402             : 
     403             : INLINE GEN
     404     9768731 : copylex(long vn)
     405             : {
     406     9768731 :   struct var_lex *v = var+s_var.n+vn;
     407     9768731 :   if (v->flag!=COPY_VAL && v->flag!=REF_VAL)
     408             :   {
     409       52584 :     v->value = gclone(v->value);
     410       52584 :     v->flag  = COPY_VAL;
     411             :   }
     412     9768731 :   return v->value;
     413             : }
     414             : 
     415             : INLINE void
     416         385 : setreflex(long vn)
     417             : {
     418         385 :   struct var_lex *v = var+s_var.n+vn;
     419         385 :   v->flag  = REF_VAL;
     420         385 : }
     421             : 
     422             : INLINE void
     423    62054951 : pushlex(long vn, GEN x)
     424             : {
     425    62054951 :   struct var_lex *v=var+s_var.n+vn;
     426    62054951 :   v->flag  = PUSH_VAL;
     427    62054951 :   v->value = x;
     428    62054951 : }
     429             : 
     430             : INLINE void
     431   169549859 : freelex(void)
     432             : {
     433   169549859 :   struct var_lex *v=var+s_var.n-1;
     434   169549859 :   s_var.n--;
     435   169549859 :   if (v->flag == COPY_VAL) gunclone_deep(v->value);
     436   169549859 : }
     437             : 
     438             : INLINE void
     439   300744161 : restore_vars(long nbmvar, long nblvar, long nblock)
     440             : {
     441             :   long j;
     442   464579687 :   for(j=1; j<=nbmvar; j++) freelex();
     443   300744494 :   for(j=1; j<=nblvar; j++) { s_lvars.n--; pop_val(lvars[s_lvars.n]); }
     444   300744816 :   for(j=1; j<=nblock; j++) { s_locks.n--; gunclone(locks[s_locks.n]); }
     445   300744438 : }
     446             : 
     447             : INLINE void
     448     5596128 : restore_trace(long nbtrace)
     449             : {
     450             :   long j;
     451    11203697 :   for(j=1; j<=nbtrace; j++)
     452             :   {
     453     5607569 :     GEN C = trace[s_trace.n-j].closure;
     454     5607569 :     clone_unlock(C);
     455             :   }
     456     5596128 :   s_trace.n -= nbtrace;
     457     5596128 : }
     458             : 
     459             : INLINE long
     460   306216893 : trace_push(long pc, GEN C)
     461             : {
     462             :   long tr;
     463   306216893 :   BLOCK_SIGINT_START
     464   307191665 :   tr = pari_stack_new(&s_trace);
     465   306798633 :   trace[tr].pc = pc;
     466   306798633 :   clone_lock(C);
     467   306335690 :   trace[tr].closure = C;
     468   306335690 :   BLOCK_SIGINT_END
     469   307207082 :   return tr;
     470             : }
     471             : 
     472             : void
     473     5714799 : push_lex(GEN a, GEN C)
     474             : {
     475     5714799 :   long vn=pari_stack_new(&s_var);
     476     5714799 :   struct var_lex *v=var+vn;
     477     5714799 :   v->flag  = PUSH_VAL;
     478     5714799 :   v->value = a;
     479     5714799 :   if (C) (void) trace_push(-1, C);
     480     5714802 : }
     481             : 
     482             : GEN
     483    99286396 : get_lex(long vn)
     484             : {
     485    99286396 :   struct var_lex *v=var+s_var.n+vn;
     486    99286396 :   return v->value;
     487             : }
     488             : 
     489             : void
     490    72869136 : set_lex(long vn, GEN x)
     491             : {
     492    72869136 :   struct var_lex *v=var+s_var.n+vn;
     493    72869136 :   if (v->flag == COPY_VAL) { gunclone_deep(v->value); v->flag = PUSH_VAL; }
     494    72869136 :   v->value = x;
     495    72869136 : }
     496             : 
     497             : void
     498     5550121 : pop_lex(long n)
     499             : {
     500             :   long j;
     501    11264626 :   for(j=1; j<=n; j++)
     502     5714505 :     freelex();
     503     5550121 :   restore_trace(1);
     504     5550121 : }
     505             : 
     506             : static THREAD pari_stack s_relocs;
     507             : static THREAD entree **relocs;
     508             : 
     509             : void
     510      228318 : pari_init_evaluator(void)
     511             : {
     512      228318 :   sp=0;
     513      228318 :   pari_stack_init(&s_st,sizeof(*st),(void**)&st);
     514      228326 :   pari_stack_alloc(&s_st,32);
     515      229508 :   s_st.n=s_st.alloc;
     516      229508 :   rp=0;
     517      229508 :   pari_stack_init(&s_ptrs,sizeof(*ptrs),(void**)&ptrs);
     518      229314 :   pari_stack_alloc(&s_ptrs,16);
     519      229538 :   s_ptrs.n=s_ptrs.alloc;
     520      229538 :   pari_stack_init(&s_var,sizeof(*var),(void**)&var);
     521      229218 :   pari_stack_init(&s_lvars,sizeof(*lvars),(void**)&lvars);
     522      228511 :   pari_stack_init(&s_locks,sizeof(*locks),(void**)&locks);
     523      228278 :   pari_stack_init(&s_trace,sizeof(*trace),(void**)&trace);
     524      228020 :   br_res = NULL;
     525      228020 :   pari_stack_init(&s_relocs,sizeof(*relocs),(void**)&relocs);
     526      227696 :   pari_stack_init(&s_prec,sizeof(*precs),(void**)&precs);
     527      227529 : }
     528             : void
     529      227781 : pari_close_evaluator(void)
     530             : {
     531      227781 :   pari_stack_delete(&s_st);
     532      229491 :   pari_stack_delete(&s_ptrs);
     533      229539 :   pari_stack_delete(&s_var);
     534      229641 :   pari_stack_delete(&s_lvars);
     535      229132 :   pari_stack_delete(&s_trace);
     536      229652 :   pari_stack_delete(&s_relocs);
     537      229121 :   pari_stack_delete(&s_prec);
     538      229494 : }
     539             : 
     540             : static gp_pointer *
     541    58676548 : new_ptr(void)
     542             : {
     543    58676548 :   if (rp==s_ptrs.n-1)
     544             :   {
     545             :     long i;
     546           0 :     gp_pointer *old = ptrs;
     547           0 :     (void)pari_stack_new(&s_ptrs);
     548           0 :     if (old != ptrs)
     549           0 :       for(i=0; i<rp; i++)
     550             :       {
     551           0 :         gp_pointer *g = &ptrs[i];
     552           0 :         if(g->sp >= 0) gel(st,g->sp) = (GEN) &(g->x);
     553             :       }
     554             :   }
     555    58676548 :   return &ptrs[rp++];
     556             : }
     557             : 
     558             : void
     559      331204 : push_localbitprec(long p)
     560             : {
     561      331204 :   long n = pari_stack_new(&s_prec);
     562      332548 :   precs[n] = p;
     563      332548 : }
     564             : void
     565       94076 : push_localprec(long p) { push_localbitprec(prec2nbits(p)); }
     566             : 
     567             : void
     568       94027 : pop_localprec(void) { s_prec.n--; }
     569             : 
     570             : long
     571    22130116 : get_localbitprec(void) { return s_prec.n? precs[s_prec.n-1]: precreal; }
     572             : 
     573             : long
     574    21874616 : get_localprec(void) { return nbits2prec(get_localbitprec()); }
     575             : 
     576             : static void
     577       11050 : checkprec(const char *f, long p, long M)
     578             : {
     579       11050 :   if (p < 1) pari_err_DOMAIN(f, "p", "<", gen_1, stoi(p));
     580       11036 :   if (p > M) pari_err_DOMAIN(f, "p", ">", utoipos(M), utoi(p));
     581       11024 : }
     582             : static long
     583       11150 : _prec(GEN p, const char *f)
     584             : {
     585       11150 :   pari_sp av = avma;
     586       11150 :   if (typ(p) == t_INT) return itos(p);
     587          35 :   p = gceil(p);
     588          35 :   if (typ(p) != t_INT) pari_err_TYPE(f, p);
     589          28 :   return gc_long(av, itos(p));
     590             : }
     591             : void
     592        7833 : localprec(GEN pp)
     593             : {
     594        7833 :   long p = _prec(pp, "localprec");
     595        7825 :   checkprec("localprec", p, prec2ndec(LGBITS));
     596        7812 :   p = ndec2nbits(p); push_localbitprec(p);
     597        7812 : }
     598             : void
     599        3226 : localbitprec(GEN pp)
     600             : {
     601        3226 :   long p = _prec(pp, "localbitprec");
     602        3225 :   checkprec("localbitprec", p, (long)LGBITS);
     603        3212 :   push_localbitprec(p);
     604        3212 : }
     605             : long
     606          14 : getlocalprec(long prec) { return prec2ndec(prec); }
     607             : long
     608        3101 : getlocalbitprec(long bit) { return bit; }
     609             : 
     610             : static GEN
     611        1232 : _precision0(GEN x)
     612             : {
     613        1232 :   long a = gprecision(x);
     614        1232 :   return a? utoi(prec2ndec(a)): mkoo();
     615             : }
     616             : GEN
     617          42 : precision0(GEN x, long n)
     618          42 : { return n? gprec(x,n): _precision0(x); }
     619             : static GEN
     620         697 : _bitprecision0(GEN x)
     621             : {
     622         697 :   long a = gprecision(x);
     623         697 :   return a? utoi(prec2nbits(a)): mkoo();
     624             : }
     625             : GEN
     626          49 : bitprecision0(GEN x, long n)
     627             : {
     628          49 :   if (n < 0)
     629           0 :     pari_err_DOMAIN("bitprecision", "bitprecision", "<", gen_0, stoi(n));
     630          49 :   if (n) {
     631          49 :     pari_sp av = avma;
     632          49 :     GEN y = gprec_w(x, nbits2prec(n));
     633          49 :     return gerepilecopy(av, y);
     634             :   }
     635           0 :   return _bitprecision0(x);
     636             : }
     637             : GEN
     638        1274 : precision00(GEN x, GEN n)
     639             : {
     640        1274 :   if (!n) return _precision0(x);
     641          42 :   return precision0(x, _prec(n, "precision"));
     642             : }
     643             : GEN
     644         746 : bitprecision00(GEN x, GEN n)
     645             : {
     646         746 :   if (!n) return _bitprecision0(x);
     647          49 :   return bitprecision0(x, _prec(n, "bitprecision"));
     648             : }
     649             : 
     650             : INLINE GEN
     651   100001626 : copyupto(GEN z, GEN t)
     652             : {
     653   100001626 :   if (is_universal_constant(z) || (z>(GEN)pari_mainstack->bot && z<=t))
     654    98236010 :     return z;
     655             :   else
     656     1765356 :     return gcopy(z);
     657             : }
     658             : 
     659             : static void closure_eval(GEN C);
     660             : 
     661             : INLINE GEN
     662       41491 : get_and_reset_break(void)
     663             : {
     664       41491 :   GEN z = br_res? gcopy(br_res): gnil;
     665       41491 :   reset_break(); return z;
     666             : }
     667             : 
     668             : INLINE GEN
     669    52131242 : closure_return(GEN C)
     670             : {
     671    52131242 :   pari_sp av = avma;
     672    52131242 :   closure_eval(C);
     673    52106059 :   if (br_status) { set_avma(av); return get_and_reset_break(); }
     674    52064617 :   return gerepileupto(av, gel(st,--sp));
     675             : }
     676             : 
     677             : /* for the break_loop debugger. Not memory clean */
     678             : GEN
     679         175 : closure_evalbrk(GEN C, long *status)
     680             : {
     681         175 :   closure_eval(C); *status = br_status;
     682         140 :   return br_status? get_and_reset_break(): gel(st,--sp);
     683             : }
     684             : 
     685             : INLINE long
     686     1138470 : closure_varn(GEN x)
     687             : {
     688     1138470 :   if (!x) return -1;
     689     1137910 :   if (!gequalX(x)) err_var(x);
     690     1137910 :   return varn(x);
     691             : }
     692             : 
     693             : INLINE void
     694    91901302 : closure_castgen(GEN z, long mode)
     695             : {
     696    91901302 :   switch (mode)
     697             :   {
     698    91900637 :   case Ggen:
     699    91900637 :     gel(st,sp++)=z;
     700    91900637 :     break;
     701         665 :   case Gsmall:
     702         665 :     st[sp++]=gtos(z);
     703         665 :     break;
     704           0 :   case Gusmall:
     705           0 :     st[sp++]=gtou(z);
     706           0 :     break;
     707           0 :   case Gvar:
     708           0 :     st[sp++]=closure_varn(z);
     709           0 :     break;
     710           0 :   case Gvoid:
     711           0 :     break;
     712           0 :   default:
     713           0 :     pari_err_BUG("closure_castgen, type unknown");
     714             :   }
     715    91901302 : }
     716             : 
     717             : INLINE void
     718        5481 : closure_castlong(long z, long mode)
     719             : {
     720        5481 :   switch (mode)
     721             :   {
     722           0 :   case Gsmall:
     723           0 :     st[sp++]=z;
     724           0 :     break;
     725           0 :   case Gusmall:
     726           0 :     if (z < 0)
     727           0 :       pari_err_TYPE("stou [integer >=0 expected]", stoi(z));
     728           0 :     st[sp++]=(ulong) z;
     729           0 :     break;
     730        5474 :   case Ggen:
     731        5474 :     gel(st,sp++)=stoi(z);
     732        5474 :     break;
     733           0 :   case Gvar:
     734           0 :     err_var(stoi(z));
     735           7 :   case Gvoid:
     736           7 :     break;
     737           0 :   default:
     738           0 :     pari_err_BUG("closure_castlong, type unknown");
     739             :   }
     740        5481 : }
     741             : 
     742             : const char *
     743       11716 : closure_func_err(void)
     744             : {
     745       11716 :   long fun=s_trace.n-1, pc;
     746             :   const char *code;
     747             :   GEN C, oper;
     748       11716 :   if (fun < 0 || trace[fun].pc < 0) return NULL;
     749       10985 :   pc = trace[fun].pc; C  = trace[fun].closure;
     750       10985 :   code = closure_codestr(C); oper = closure_get_oper(C);
     751       10985 :   if (code[pc]==OCcallgen || code[pc]==OCcallgen2 ||
     752        3465 :       code[pc]==OCcallint || code[pc]==OCcalllong || code[pc]==OCcallvoid)
     753        8038 :     return ((entree*)oper[pc])->name;
     754        2947 :   return NULL;
     755             : }
     756             : 
     757             : /* return the next label for the call chain debugger closure_err(),
     758             :  * incorporating the name of the user of member function. Return NULL for an
     759             :  * anonymous (inline) closure. */
     760             : static char *
     761         238 : get_next_label(const char *s, int member, char **next_fun)
     762             : {
     763         238 :   const char *v, *t = s+1;
     764             :   char *u, *next_label;
     765             : 
     766         238 :   if (!is_keyword_char(*s)) return NULL;
     767         966 :   while (is_keyword_char(*t)) t++;
     768             :   /* e.g. (x->1/x)(0) instead of (x)->1/x */
     769         217 :   if (t[0] == '-' && t[1] == '>') return NULL;
     770         210 :   next_label = (char*)pari_malloc(t - s + 32);
     771         210 :   sprintf(next_label, "in %sfunction ", member? "member ": "");
     772         210 :   u = *next_fun = next_label + strlen(next_label);
     773         210 :   v = s;
     774        1169 :   while (v < t) *u++ = *v++;
     775         210 :   *u++ = 0; return next_label;
     776             : }
     777             : 
     778             : static const char *
     779          21 : get_arg_name(GEN C, long i)
     780             : {
     781          21 :   GEN d = closure_get_dbg(C), frpc = gel(d,2), fram = gel(d,3);
     782          21 :   long j, l = lg(frpc);
     783          28 :   for (j=1; j<l; j++)
     784          28 :     if (frpc[j]==1 && i<lg(gel(fram,j)))
     785          21 :       return ((entree*)mael(fram,j,i))->name;
     786           0 :   return "(unnamed)";
     787             : }
     788             : 
     789             : void
     790       10977 : closure_err(long level)
     791             : {
     792             :   GEN base;
     793       10977 :   const long lastfun = s_trace.n - 1 - level;
     794             :   char *next_label, *next_fun;
     795       10977 :   long i = maxss(0, lastfun - 19);
     796       10977 :   if (lastfun < 0) return; /*e.g. when called by gp_main_loop's simplify */
     797       10956 :   if (i > 0) while (lg(trace[i].closure)==6) i--;
     798       10956 :   base = closure_get_text(trace[i].closure); /* gcc -Wall*/
     799       10956 :   next_label = pari_strdup(i == 0? "at top-level": "[...] at");
     800       10956 :   next_fun = next_label;
     801       11620 :   for (; i <= lastfun; i++)
     802             :   {
     803       11620 :     GEN C = trace[i].closure;
     804       11620 :     if (lg(C) >= 7) base=closure_get_text(C);
     805       11620 :     if ((i==lastfun || lg(trace[i+1].closure)>=7))
     806             :     {
     807       11194 :       GEN dbg = gel(closure_get_dbg(C),1);
     808             :       /* After a SIGINT, pc can be slightly off: ensure 0 <= pc < lg() */
     809       11194 :       long pc = minss(lg(dbg)-1, trace[i].pc>=0 ? trace[i].pc: 1);
     810       11194 :       long offset = pc? dbg[pc]: 0;
     811             :       int member;
     812             :       const char *s, *sbase;
     813       11194 :       if (typ(base)!=t_VEC) sbase = GSTR(base);
     814         182 :       else if (offset>=0)   sbase = GSTR(gel(base,2));
     815          21 :       else { sbase = GSTR(gel(base,1)); offset += strlen(sbase); }
     816       11194 :       s = sbase + offset;
     817       11194 :       member = offset>0 && (s[-1] == '.');
     818             :       /* avoid "in function foo: foo" */
     819       11194 :       if (!next_fun || strcmp(next_fun, s)) {
     820       11187 :         print_errcontext(pariErr, next_label, s, sbase);
     821       11187 :         out_putc(pariErr, '\n');
     822             :       }
     823       11194 :       pari_free(next_label);
     824       11194 :       if (i == lastfun) break;
     825             : 
     826         238 :       next_label = get_next_label(s, member, &next_fun);
     827         238 :       if (!next_label) {
     828          28 :         next_label = pari_strdup("in anonymous function");
     829          28 :         next_fun = NULL;
     830             :       }
     831             :     }
     832             :   }
     833             : }
     834             : 
     835             : GEN
     836          41 : pari_self(void)
     837             : {
     838          41 :   long fun = s_trace.n - 1;
     839          76 :   if (fun > 0) while (lg(trace[fun].closure)==6) fun--;
     840          41 :   return fun >= 0 ? trace[fun].closure: NULL;
     841             : }
     842             : 
     843             : long
     844          91 : closure_context(long start, long level)
     845             : {
     846          91 :   const long lastfun = s_trace.n - 1 - level;
     847          91 :   long i, fun = lastfun;
     848          91 :   if (fun<0) return lastfun;
     849         224 :   while (fun>start && lg(trace[fun].closure)==6) fun--;
     850         315 :   for (i=fun; i <= lastfun; i++)
     851         224 :     push_frame(trace[i].closure, trace[i].pc,0);
     852         126 :   for (  ; i < s_trace.n; i++)
     853          35 :     push_frame(trace[i].closure, trace[i].pc,1);
     854          91 :   return s_trace.n-level;
     855             : }
     856             : 
     857             : INLINE void
     858  2992093106 : st_alloc(long n)
     859             : {
     860  2992093106 :   if (sp+n>s_st.n)
     861             :   {
     862          70 :     pari_stack_alloc(&s_st,n+16);
     863          70 :     s_st.n=s_st.alloc;
     864          70 :     if (DEBUGMEM>=2) pari_warn(warner,"doubling evaluator stack");
     865             :   }
     866  2992093106 : }
     867             : 
     868             : INLINE void
     869     9902263 : ptr_proplock(gp_pointer *g, GEN C)
     870             : {
     871     9902263 :   g->x = C;
     872     9902263 :   if (isclone(g->x))
     873             :   {
     874      444500 :     clone_unlock_deep(g->ox);
     875      444500 :     g->ox = g->x;
     876      444500 :     ++bl_refc(g->ox);
     877             :   }
     878     9902263 : }
     879             : 
     880             : static void
     881   300746269 : closure_eval(GEN C)
     882             : {
     883   300746269 :   const char *code=closure_codestr(C);
     884   300728590 :   GEN oper=closure_get_oper(C);
     885   300712675 :   GEN data=closure_get_data(C);
     886   300703356 :   long loper=lg(oper);
     887   300703356 :   long saved_sp=sp-closure_arity(C);
     888   300695268 :   long saved_rp=rp, saved_prec=s_prec.n;
     889   300695268 :   long j, nbmvar=0, nblvar=0, nblock=0;
     890             :   long pc, t;
     891             : #ifdef STACK_CHECK
     892             :   GEN stackelt;
     893   300695268 :   if (PARI_stack_limit && (void*) &stackelt <= PARI_stack_limit)
     894           0 :     pari_err(e_MISC, "deep recursion");
     895             : #endif
     896   300695268 :   t = trace_push(0, C);
     897   301429994 :   if (lg(C)==8)
     898             :   {
     899     7985882 :     GEN z=closure_get_frame(C);
     900     7985579 :     long l=lg(z)-1;
     901     7985579 :     pari_stack_alloc(&s_var,l);
     902     7986320 :     s_var.n+=l;
     903     7986320 :     nbmvar+=l;
     904    30738777 :     for(j=1;j<=l;j++)
     905             :     {
     906    22752457 :       var[s_var.n-j].flag=PUSH_VAL;
     907    22752457 :       var[s_var.n-j].value=gel(z,j);
     908             :     }
     909             :   }
     910             : 
     911  3225048027 :   for(pc=1;pc<loper;pc++)
     912             :   {
     913  2924227344 :     op_code opcode=(op_code) code[pc];
     914  2924227344 :     long operand=oper[pc];
     915  2924227344 :     if (sp<0) pari_err_BUG("closure_eval, stack underflow");
     916  2924227344 :     st_alloc(16);
     917  2924075393 :     trace[t].pc = pc;
     918             :     CHECK_CTRLC
     919  2924075393 :     switch(opcode)
     920             :     {
     921   204063865 :     case OCpushlong:
     922   204063865 :       st[sp++]=operand;
     923   204063865 :       break;
     924       97676 :     case OCpushgnil:
     925       97676 :       gel(st,sp++)=gnil;
     926       97676 :       break;
     927   150846082 :     case OCpushgen:
     928   150846082 :       gel(st,sp++)=gel(data,operand);
     929   150846082 :       break;
     930       83540 :     case OCpushreal:
     931       83540 :       gel(st,sp++)=strtor(GSTR(data[operand]),get_localprec());
     932       83540 :       break;
     933   289840879 :     case OCpushstoi:
     934   289840879 :       gel(st,sp++)=stoi(operand);
     935   289840873 :       break;
     936       25060 :     case OCpushvar:
     937             :       {
     938       25060 :         entree *ep = (entree *)operand;
     939       25060 :         gel(st,sp++)=pol_x(pari_var_create(ep));
     940       25060 :         break;
     941             :       }
     942    91455945 :     case OCpushdyn:
     943             :       {
     944    91455945 :         entree *ep = (entree *)operand;
     945    91455945 :         if (!mt_is_thread())
     946             :         {
     947    91454447 :           checkvalue(ep, chk_CREATE);
     948    91454447 :           gel(st,sp++)=(GEN)ep->value;
     949             :         } else
     950             :         {
     951        1498 :           GEN val = export_get(ep->name);
     952        1498 :           if (!val)
     953           0 :             pari_err(e_MISC,"mt: please use export(%s)", ep->name);
     954        1498 :           gel(st,sp++)=val;
     955             :         }
     956    91455945 :         break;
     957             :       }
     958   583572696 :     case OCpushlex:
     959   583572696 :       gel(st,sp++)=var[s_var.n+operand].value;
     960   583572696 :       break;
     961    23308222 :     case OCsimpleptrdyn:
     962             :       {
     963    23308222 :         gp_pointer *g = new_ptr();
     964    23308222 :         g->vn=0;
     965    23308222 :         g->ep = (entree*) operand;
     966    23308222 :         g->x = checkvalueptr(g->ep);
     967    23308222 :         g->ox = g->x; clone_lock(g->ox);
     968    23308222 :         g->sp = sp;
     969    23308222 :         gel(st,sp++) = (GEN)&(g->x);
     970    23308222 :         break;
     971             :       }
     972    25670911 :     case OCsimpleptrlex:
     973             :       {
     974    25670911 :         gp_pointer *g = new_ptr();
     975    25670911 :         g->vn=operand;
     976    25670911 :         g->ep=(entree *)0x1L;
     977    25670911 :         g->x = (GEN) var[s_var.n+operand].value;
     978    25670911 :         g->ox = g->x; clone_lock(g->ox);
     979    25670911 :         g->sp = sp;
     980    25670911 :         gel(st,sp++) = (GEN)&(g->x);
     981    25670911 :         break;
     982             :       }
     983        3101 :     case OCnewptrdyn:
     984             :       {
     985        3101 :         entree *ep = (entree *)operand;
     986        3101 :         gp_pointer *g = new_ptr();
     987             :         matcomp *C;
     988        3101 :         checkvalue(ep, chk_ERROR);
     989        3101 :         g->sp = -1;
     990        3101 :         g->x = copyvalue(ep);
     991        3101 :         g->ox = g->x; clone_lock(g->ox);
     992        3101 :         g->vn=0;
     993        3101 :         g->ep=NULL;
     994        3101 :         C=&g->c;
     995        3101 :         C->full_col = C->full_row = 0;
     996        3101 :         C->parent   = (GEN)    g->x;
     997        3101 :         C->ptcell   = (GEN *) &g->x;
     998        3101 :         break;
     999             :       }
    1000     9694314 :     case OCnewptrlex:
    1001             :       {
    1002     9694314 :         gp_pointer *g = new_ptr();
    1003             :         matcomp *C;
    1004     9694314 :         g->sp = -1;
    1005     9694314 :         g->x = copylex(operand);
    1006     9694314 :         g->ox = g->x; clone_lock(g->ox);
    1007     9694314 :         g->vn=0;
    1008     9694314 :         g->ep=NULL;
    1009     9694314 :         C=&g->c;
    1010     9694314 :         C->full_col = C->full_row = 0;
    1011     9694314 :         C->parent   = (GEN)     g->x;
    1012     9694314 :         C->ptcell   = (GEN *) &(g->x);
    1013     9694314 :         break;
    1014             :       }
    1015      557648 :     case OCpushptr:
    1016             :       {
    1017      557648 :         gp_pointer *g = &ptrs[rp-1];
    1018      557648 :         g->sp = sp;
    1019      557648 :         gel(st,sp++) = (GEN)&(g->x);
    1020             :       }
    1021      557648 :       break;
    1022    49536725 :     case OCendptr:
    1023    99073450 :       for(j=0;j<operand;j++)
    1024             :       {
    1025    49536725 :         gp_pointer *g = &ptrs[--rp];
    1026    49536725 :         if (g->ep)
    1027             :         {
    1028    48979077 :           if (g->vn)
    1029    25670911 :             changelex(g->vn, g->x);
    1030             :           else
    1031    23308166 :             changevalue(g->ep, g->x);
    1032             :         }
    1033      557648 :         else change_compo(&(g->c), g->x);
    1034    49536725 :         clone_unlock_deep(g->ox);
    1035             :       }
    1036    49536725 :       break;
    1037     6142584 :     case OCstoredyn:
    1038             :       {
    1039     6142584 :         entree *ep = (entree *)operand;
    1040     6142584 :         checkvalue(ep, chk_NOCREATE);
    1041     6142576 :         changevalue(ep, gel(st,--sp));
    1042     6142576 :         break;
    1043             :       }
    1044   133395607 :     case OCstorelex:
    1045   133395607 :       changelex(operand,gel(st,--sp));
    1046   133395607 :       break;
    1047     9139718 :     case OCstoreptr:
    1048             :       {
    1049     9139718 :         gp_pointer *g = &ptrs[--rp];
    1050     9139718 :         change_compo(&(g->c), gel(st,--sp));
    1051     9139641 :         clone_unlock_deep(g->ox);
    1052     9139641 :         break;
    1053             :       }
    1054    89844385 :     case OCstackgen:
    1055             :       {
    1056    89844385 :         GEN z = gerepileupto(st[sp-2],gel(st,sp-1));
    1057    89844406 :         gmael(st,sp-3,operand) = copyupto(z,gel(st,sp-2));
    1058    89844405 :         st[sp-2] = avma;
    1059    89844405 :         sp--;
    1060    89844405 :         break;
    1061             :       }
    1062    21791070 :     case OCprecreal:
    1063    21791070 :       st[sp++]=get_localprec();
    1064    21791080 :       break;
    1065       26712 :     case OCbitprecreal:
    1066       26712 :       st[sp++]=get_localbitprec();
    1067       26712 :       break;
    1068         945 :     case OCprecdl:
    1069         945 :       st[sp++]=precdl;
    1070         945 :       break;
    1071        2905 :     case OCavma:
    1072        2905 :       st[sp++]=avma;
    1073        2905 :       break;
    1074      740348 :     case OCcowvardyn:
    1075             :       {
    1076      740348 :         entree *ep = (entree *)operand;
    1077      740348 :         checkvalue(ep, chk_ERROR);
    1078      740348 :         (void)copyvalue(ep);
    1079      740348 :         break;
    1080             :       }
    1081       73367 :     case OCcowvarlex:
    1082       73367 :       (void)copylex(operand);
    1083       73367 :       break;
    1084         385 :     case OCsetref:
    1085         385 :       setreflex(operand);
    1086         385 :       break;
    1087         392 :     case OClock:
    1088             :     {
    1089         392 :       GEN v = gel(st,sp-1);
    1090         392 :       if (isclone(v))
    1091             :       {
    1092         378 :         long n = pari_stack_new(&s_locks);
    1093         378 :         locks[n] = v;
    1094         378 :         nblock++;
    1095         378 :         ++bl_refc(v);
    1096             :       }
    1097         392 :       break;
    1098             :     }
    1099    17715554 :     case OCstoi:
    1100    17715554 :       gel(st,sp-1)=stoi(st[sp-1]);
    1101    17716092 :       break;
    1102           0 :     case OCutoi:
    1103           0 :       gel(st,sp-1)=utoi(st[sp-1]);
    1104           0 :       break;
    1105    71123787 :     case OCitos:
    1106    71123787 :       st[sp+operand]=gtos(gel(st,sp+operand));
    1107    71123767 :       break;
    1108       96612 :     case OCitou:
    1109       96612 :       st[sp+operand]=gtou(gel(st,sp+operand));
    1110       96612 :       break;
    1111        6426 :     case OCtostr:
    1112             :       {
    1113        6426 :         GEN z = gel(st,sp+operand);
    1114        6426 :         st[sp+operand] = (long) (z ? GENtostr_unquoted(z): NULL);
    1115        6426 :         break;
    1116             :       }
    1117     1138470 :     case OCvarn:
    1118     1138470 :       st[sp+operand] = closure_varn(gel(st,sp+operand));
    1119     1138470 :       break;
    1120    25405909 :     case OCcopy:
    1121    25405909 :       gel(st,sp-1) = gcopy(gel(st,sp-1));
    1122    25405924 :       break;
    1123        2905 :     case OCgerepile:
    1124             :     {
    1125             :       pari_sp av;
    1126             :       GEN x;
    1127        2905 :       sp--;
    1128        2905 :       av = st[sp-1];
    1129        2905 :       x = gel(st,sp);
    1130        2905 :       if (isonstack(x))
    1131             :       {
    1132        2905 :         pari_sp av2 = (pari_sp)(x + lg(x));
    1133        2905 :         if ((long) (av - av2) > 1000000L)
    1134             :         {
    1135           7 :           if (DEBUGMEM>=2)
    1136           0 :             pari_warn(warnmem,"eval: recovering %ld bytes", av - av2);
    1137           7 :           x = gerepileupto(av, x);
    1138             :         }
    1139           0 :       } else set_avma(av);
    1140        2905 :       gel(st,sp-1) = x;
    1141        2905 :       break;
    1142             :     }
    1143           0 :     case OCcopyifclone:
    1144           0 :       if (isclone(gel(st,sp-1)))
    1145           0 :         gel(st,sp-1) = gcopy(gel(st,sp-1));
    1146           0 :       break;
    1147    90236215 :     case OCcompo1:
    1148             :       {
    1149    90236215 :         GEN  p=gel(st,sp-2);
    1150    90236215 :         long c=st[sp-1];
    1151    90236215 :         sp-=2;
    1152    90236215 :         switch(typ(p))
    1153             :         {
    1154    90230688 :         case t_VEC: case t_COL:
    1155    90230688 :           check_array_index(c, lg(p));
    1156    90230689 :           closure_castgen(gel(p,c),operand);
    1157    90230699 :           break;
    1158          25 :         case t_LIST:
    1159             :           {
    1160             :             long lx;
    1161          25 :             if (list_typ(p)!=t_LIST_RAW)
    1162           0 :               pari_err_TYPE("_[_] OCcompo1 [not a vector]", p);
    1163          25 :             p = list_data(p); lx = p? lg(p): 1;
    1164          25 :             check_array_index(c, lx);
    1165          25 :             closure_castgen(gel(p,c),operand);
    1166          25 :             break;
    1167             :           }
    1168        5495 :         case t_VECSMALL:
    1169        5495 :           check_array_index(c,lg(p));
    1170        5481 :           closure_castlong(p[c],operand);
    1171        5480 :           break;
    1172           7 :         default:
    1173           7 :           pari_err_TYPE("_[_] OCcompo1 [not a vector]", p);
    1174           0 :           break;
    1175             :         }
    1176    90236204 :         break;
    1177             :       }
    1178     9422994 :     case OCcompo1ptr:
    1179             :       {
    1180     9422994 :         long c=st[sp-1];
    1181             :         long lx;
    1182     9422994 :         gp_pointer *g = &ptrs[rp-1];
    1183     9422994 :         matcomp *C=&g->c;
    1184     9422994 :         GEN p = g->x;
    1185     9422994 :         sp--;
    1186     9422994 :         switch(typ(p))
    1187             :         {
    1188     9422917 :         case t_VEC: case t_COL:
    1189     9422917 :           check_array_index(c, lg(p));
    1190     9422917 :           C->ptcell = (GEN *) p+c;
    1191     9422917 :           ptr_proplock(g, *(C->ptcell));
    1192     9422917 :           break;
    1193          42 :         case t_VECSMALL:
    1194          42 :           check_array_index(c, lg(p));
    1195          35 :           C->ptcell = (GEN *) p+c;
    1196          35 :           g->x = stoi(p[c]);
    1197          35 :           break;
    1198          28 :         case t_LIST:
    1199          28 :           if (list_typ(p)!=t_LIST_RAW)
    1200           0 :             pari_err_TYPE("&_[_] OCcompo1 [not a vector]", p);
    1201          28 :           p = list_data(p); lx = p? lg(p): 1;
    1202          28 :           check_array_index(c,lx);
    1203          28 :           C->ptcell = (GEN *) p+c;
    1204          28 :           ptr_proplock(g, *(C->ptcell));
    1205          28 :           break;
    1206           7 :         default:
    1207           7 :           pari_err_TYPE("&_[_] OCcompo1ptr [not a vector]", p);
    1208             :         }
    1209     9422980 :         C->parent   = p;
    1210     9422980 :         break;
    1211             :       }
    1212     1670585 :     case OCcompo2:
    1213             :       {
    1214     1670585 :         GEN  p=gel(st,sp-3);
    1215     1670585 :         long c=st[sp-2];
    1216     1670585 :         long d=st[sp-1];
    1217     1670585 :         if (typ(p)!=t_MAT) pari_err_TYPE("_[_,_] OCcompo2 [not a matrix]", p);
    1218     1670578 :         check_array_index(d, lg(p));
    1219     1670578 :         check_array_index(c, lg(gel(p,d)));
    1220     1670578 :         sp-=3;
    1221     1670578 :         closure_castgen(gcoeff(p,c,d),operand);
    1222     1670578 :         break;
    1223             :       }
    1224      123921 :     case OCcompo2ptr:
    1225             :       {
    1226      123921 :         long c=st[sp-2];
    1227      123921 :         long d=st[sp-1];
    1228      123921 :         gp_pointer *g = &ptrs[rp-1];
    1229      123921 :         matcomp *C=&g->c;
    1230      123921 :         GEN p = g->x;
    1231      123921 :         sp-=2;
    1232      123921 :         if (typ(p)!=t_MAT)
    1233           0 :           pari_err_TYPE("&_[_,_] OCcompo2ptr [not a matrix]", p);
    1234      123921 :         check_array_index(d, lg(p));
    1235      123921 :         check_array_index(c, lg(gel(p,d)));
    1236      123921 :         C->ptcell = (GEN *) gel(p,d)+c;
    1237      123921 :         C->parent   = p;
    1238      123921 :         ptr_proplock(g, *(C->ptcell));
    1239      123921 :         break;
    1240             :       }
    1241     1048306 :     case OCcompoC:
    1242             :       {
    1243     1048306 :         GEN  p=gel(st,sp-2);
    1244     1048306 :         long c=st[sp-1];
    1245     1048306 :         if (typ(p)!=t_MAT)
    1246           7 :           pari_err_TYPE("_[,_] OCcompoC [not a matrix]", p);
    1247     1048299 :         check_array_index(c, lg(p));
    1248     1048292 :         sp--;
    1249     1048292 :         gel(st,sp-1) = gel(p,c);
    1250     1048292 :         break;
    1251             :       }
    1252      355411 :     case OCcompoCptr:
    1253             :       {
    1254      355411 :         long c=st[sp-1];
    1255      355411 :         gp_pointer *g = &ptrs[rp-1];
    1256      355411 :         matcomp *C=&g->c;
    1257      355411 :         GEN p = g->x;
    1258      355411 :         sp--;
    1259      355411 :         if (typ(p)!=t_MAT)
    1260           7 :           pari_err_TYPE("&_[,_] OCcompoCptr [not a matrix]", p);
    1261      355404 :         check_array_index(c, lg(p));
    1262      355397 :         C->ptcell = (GEN *) p+c;
    1263      355397 :         C->full_col = c;
    1264      355397 :         C->parent   = p;
    1265      355397 :         ptr_proplock(g, *(C->ptcell));
    1266      355397 :         break;
    1267             :       }
    1268      273014 :     case OCcompoL:
    1269             :       {
    1270      273014 :         GEN  p=gel(st,sp-2);
    1271      273014 :         long r=st[sp-1];
    1272      273014 :         sp--;
    1273      273014 :         if (typ(p)!=t_MAT)
    1274           7 :           pari_err_TYPE("_[_,] OCcompoL [not a matrix]", p);
    1275      273007 :         check_array_index(r,lg(p) == 1? 1: lgcols(p));
    1276      273000 :         gel(st,sp-1) = row(p,r);
    1277      273000 :         break;
    1278             :       }
    1279      205002 :     case OCcompoLptr:
    1280             :       {
    1281      205002 :         long r=st[sp-1];
    1282      205002 :         gp_pointer *g = &ptrs[rp-1];
    1283      205002 :         matcomp *C=&g->c;
    1284      205002 :         GEN p = g->x, p2;
    1285      205002 :         sp--;
    1286      205002 :         if (typ(p)!=t_MAT)
    1287           7 :           pari_err_TYPE("&_[_,] OCcompoLptr [not a matrix]", p);
    1288      204995 :         check_array_index(r,lg(p) == 1? 1: lgcols(p));
    1289      204988 :         p2 = rowcopy(p,r);
    1290      204988 :         C->full_row = r; /* record row number */
    1291      204988 :         C->ptcell = &p2;
    1292      204988 :         C->parent   = p;
    1293      204988 :         g->x = p2;
    1294      204988 :         break;
    1295             :       }
    1296      101934 :     case OCdefaultarg:
    1297      101934 :       if (var[s_var.n+operand].flag==DEFAULT_VAL)
    1298             :       {
    1299        3045 :         GEN z = gel(st,sp-1);
    1300        3045 :         if (typ(z)==t_CLOSURE)
    1301             :         {
    1302        1050 :           pushlex(operand, closure_evalnobrk(z));
    1303        1050 :           copylex(operand);
    1304             :         }
    1305             :         else
    1306        1995 :           pushlex(operand, z);
    1307             :       }
    1308      101934 :       sp--;
    1309      101934 :       break;
    1310          50 :     case OClocalvar:
    1311             :       {
    1312             :         long n;
    1313          50 :         entree *ep = (entree *)operand;
    1314          50 :         checkvalue(ep, chk_NOCREATE);
    1315          42 :         n = pari_stack_new(&s_lvars);
    1316          42 :         lvars[n] = ep;
    1317          42 :         nblvar++;
    1318          42 :         pushvalue(ep,gel(st,--sp));
    1319          42 :         break;
    1320             :       }
    1321          22 :     case OClocalvar0:
    1322             :       {
    1323             :         long n;
    1324          22 :         entree *ep = (entree *)operand;
    1325          22 :         checkvalue(ep, chk_NOCREATE);
    1326          14 :         n = pari_stack_new(&s_lvars);
    1327          14 :         lvars[n] = ep;
    1328          14 :         nblvar++;
    1329          14 :         zerovalue(ep);
    1330          12 :         break;
    1331             :       }
    1332          41 :     case OCexportvar:
    1333             :       {
    1334          41 :         entree *ep = (entree *)operand;
    1335          41 :         mt_export_add(ep->name, gel(st,--sp));
    1336          41 :         break;
    1337             :       }
    1338           6 :     case OCunexportvar:
    1339             :       {
    1340           6 :         entree *ep = (entree *)operand;
    1341           6 :         mt_export_del(ep->name);
    1342           6 :         break;
    1343             :       }
    1344             : 
    1345             : #define EVAL_f(f) \
    1346             :   switch (ep->arity) \
    1347             :   { \
    1348             :     case 0: f(); break; \
    1349             :     case 1: sp--; f(st[sp]); break; \
    1350             :     case 2: sp-=2; f(st[sp],st[sp+1]); break; \
    1351             :     case 3: sp-=3; f(st[sp],st[sp+1],st[sp+2]); break; \
    1352             :     case 4: sp-=4; f(st[sp],st[sp+1],st[sp+2],st[sp+3]); break; \
    1353             :     case 5: sp-=5; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4]); break; \
    1354             :     case 6: sp-=6; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5]); break; \
    1355             :     case 7: sp-=7; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6]); break; \
    1356             :     case 8: sp-=8; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7]); break; \
    1357             :     case 9: sp-=9; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8]); break; \
    1358             :     case 10: sp-=10; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9]); break; \
    1359             :     case 11: sp-=11; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10]); break; \
    1360             :     case 12: sp-=12; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11]); break; \
    1361             :     case 13: sp-=13; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12]); break; \
    1362             :     case 14: sp-=14; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13]); break; \
    1363             :     case 15: sp-=15; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14]); break; \
    1364             :     case 16: sp-=16; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14],st[sp+15]); break; \
    1365             :     case 17: sp-=17; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14],st[sp+15],st[sp+16]); break; \
    1366             :     case 18: sp-=18; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14],st[sp+15],st[sp+16],st[sp+17]); break; \
    1367             :     case 19: sp-=19; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14],st[sp+15],st[sp+16],st[sp+17],st[sp+18]); break; \
    1368             :     case 20: sp-=20; f(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6],st[sp+7],st[sp+8],st[sp+9],st[sp+10],st[sp+11],st[sp+12],st[sp+13],st[sp+14],st[sp+15],st[sp+16],st[sp+17],st[sp+18],st[sp+19]); break; \
    1369             :     default: \
    1370             :       pari_err_IMPL("functions with more than 20 parameters");\
    1371             :       goto endeval; /*LCOV_EXCL_LINE*/ \
    1372             :   }
    1373             : 
    1374    93623396 :     case OCcallgen:
    1375             :       {
    1376    93623396 :         entree *ep = (entree *)operand;
    1377             :         GEN res;
    1378             :         /* Macro Madness : evaluate function ep->value on arguments
    1379             :          * st[sp-ep->arity .. sp]. Set res = result. */
    1380    93623396 :         EVAL_f(res = ((GEN (*)(ANYARG))ep->value));
    1381    93607212 :         if (br_status) goto endeval;
    1382    93472031 :         gel(st,sp++)=res;
    1383    93472031 :         break;
    1384             :       }
    1385   572465168 :     case OCcallgen2: /*same for ep->arity = 2. Is this optimization worth it ?*/
    1386             :       {
    1387   572465168 :         entree *ep = (entree *)operand;
    1388             :         GEN res;
    1389   572465168 :         sp-=2;
    1390   572465168 :         res = ((GEN (*)(GEN,GEN))ep->value)(gel(st,sp),gel(st,sp+1));
    1391   572466074 :         if (br_status) goto endeval;
    1392   572466046 :         gel(st,sp++)=res;
    1393   572466046 :         break;
    1394             :       }
    1395    16018605 :     case OCcalllong:
    1396             :       {
    1397    16018605 :         entree *ep = (entree *)operand;
    1398             :         long res;
    1399    16018605 :         EVAL_f(res = ((long (*)(ANYARG))ep->value));
    1400    16020257 :         if (br_status) goto endeval;
    1401    16020257 :         st[sp++] = res;
    1402    16020257 :         break;
    1403             :       }
    1404     1698396 :     case OCcallint:
    1405             :       {
    1406     1698396 :         entree *ep = (entree *)operand;
    1407             :         long res;
    1408     1698396 :         EVAL_f(res = ((int (*)(ANYARG))ep->value));
    1409     1698284 :         if (br_status) goto endeval;
    1410     1698284 :         st[sp++] = res;
    1411     1698284 :         break;
    1412             :       }
    1413    48346056 :     case OCcallvoid:
    1414             :       {
    1415    48346056 :         entree *ep = (entree *)operand;
    1416    48346056 :         EVAL_f(((void (*)(ANYARG))ep->value));
    1417    48345604 :         if (br_status) goto endeval;
    1418    48189285 :         break;
    1419             :       }
    1420             : #undef EVAL_f
    1421             : 
    1422    34737233 :     case OCcalluser:
    1423             :       {
    1424    34737233 :         long n=operand;
    1425    34737233 :         GEN fun = gel(st,sp-1-n);
    1426             :         long arity, isvar;
    1427             :         GEN z;
    1428    34737233 :         if (typ(fun)!=t_CLOSURE) pari_err(e_NOTFUNC, fun);
    1429    34734524 :         isvar = closure_is_variadic(fun);
    1430    34734524 :         arity = closure_arity(fun);
    1431    34734525 :         if (!isvar || n < arity)
    1432             :         {
    1433    34734455 :           st_alloc(arity-n);
    1434    34734447 :           if (n>arity)
    1435           0 :             pari_err(e_MISC,"too many parameters in user-defined function call");
    1436    34759661 :           for (j=n+1;j<=arity;j++)
    1437       25214 :             gel(st,sp++)=0;
    1438    34734447 :           if (isvar) gel(st,sp-1) = cgetg(1,t_VEC);
    1439             :         }
    1440             :         else
    1441             :         {
    1442             :           GEN v;
    1443          70 :           long j, m = n-arity+1;
    1444          70 :           v = cgetg(m+1,t_VEC);
    1445          70 :           sp-=m;
    1446         301 :           for (j=1; j<=m; j++)
    1447         231 :             gel(v,j) = gel(st,sp+j-1)? gcopy(gel(st,sp+j-1)): gen_0;
    1448          70 :           gel(st,sp++)=v;
    1449             :         }
    1450    34734517 :         z = closure_return(fun);
    1451    34730886 :         if (br_status) goto endeval;
    1452    34730886 :         gel(st, sp-1) = z;
    1453    34730886 :         break;
    1454             :       }
    1455    42238269 :     case OCnewframe:
    1456    42238269 :       if (operand>0) nbmvar+=operand;
    1457          13 :       else operand=-operand;
    1458    42238269 :       pari_stack_alloc(&s_var,operand);
    1459    42238269 :       s_var.n+=operand;
    1460   121264161 :       for(j=1;j<=operand;j++)
    1461             :       {
    1462    79025892 :         var[s_var.n-j].flag=PUSH_VAL;
    1463    79025892 :         var[s_var.n-j].value=gen_0;
    1464             :       }
    1465    42238269 :       break;
    1466        6583 :     case OCsaveframe:
    1467             :       {
    1468        6583 :         GEN cl = (operand?gcopy:shallowcopy)(gel(st,sp-1));
    1469        6583 :         GEN f = gel(cl, 7);
    1470        6583 :         long j, l = lg(f);
    1471        6583 :         GEN v = cgetg(l, t_VEC);
    1472       75348 :         for (j = 1; j < l; j++)
    1473       68765 :           if (signe(gel(f,l-j))==0)
    1474             :           {
    1475        9955 :             GEN val = var[s_var.n-j].value;
    1476        9955 :             gel(v,j) = operand?gcopy(val):val;
    1477             :           } else
    1478       58810 :             gel(v,j) = gnil;
    1479        6583 :         gel(cl,7) = v;
    1480        6583 :         gel(st,sp-1) = cl;
    1481             :       }
    1482        6583 :       break;
    1483         105 :     case OCpackargs:
    1484             :     {
    1485         105 :       GEN def = cgetg(operand+1, t_VECSMALL);
    1486         105 :       GEN args = cgetg(operand+1, t_VEC);
    1487         105 :       pari_stack_alloc(&s_var,operand);
    1488         105 :       sp-=operand;
    1489         210 :       for (j=0;j<operand;j++)
    1490             :       {
    1491         105 :         if (gel(st,sp+j))
    1492             :         {
    1493         105 :           gel(args,j+1) = gel(st,sp+j);
    1494         105 :           uel(def ,j+1) = 1;
    1495             :         }
    1496             :         else
    1497             :         {
    1498           0 :           gel(args,j+1) = gen_0;
    1499           0 :           uel(def ,j+1) = 0;
    1500             :         }
    1501             :       }
    1502         105 :       gel(st, sp++) = args;
    1503         105 :       gel(st, sp++) = def;
    1504         105 :       break;
    1505             :     }
    1506    35769694 :     case OCgetargs:
    1507    35769694 :       pari_stack_alloc(&s_var,operand);
    1508    35768814 :       s_var.n+=operand;
    1509    35768814 :       nbmvar+=operand;
    1510    35768814 :       sp-=operand;
    1511    97829564 :       for (j=0;j<operand;j++)
    1512             :       {
    1513    62060357 :         if (gel(st,sp+j))
    1514    62051978 :           pushlex(j-operand,gel(st,sp+j));
    1515             :         else
    1516             :         {
    1517        8379 :           var[s_var.n+j-operand].flag=DEFAULT_VAL;
    1518        8379 :           var[s_var.n+j-operand].value=gen_0;
    1519             :         }
    1520             :       }
    1521    35769207 :       break;
    1522          49 :     case OCcheckuserargs:
    1523         105 :       for (j=0; j<operand; j++)
    1524          77 :         if (var[s_var.n-operand+j].flag==DEFAULT_VAL)
    1525          21 :           pari_err(e_MISC,"missing mandatory argument"
    1526             :                    " '%s' in user function",get_arg_name(C,j+1));
    1527          28 :       break;
    1528     7245328 :     case OCcheckargs:
    1529    34876777 :       for (j=sp-1;operand;operand>>=1UL,j--)
    1530    27631307 :         if ((operand&1L) && gel(st,j)==NULL)
    1531           0 :           pari_err(e_MISC,"missing mandatory argument");
    1532     7245470 :       break;
    1533         441 :     case OCcheckargs0:
    1534         882 :       for (j=sp-1;operand;operand>>=1UL,j--)
    1535         441 :         if ((operand&1L) && gel(st,j))
    1536           0 :           pari_err(e_MISC,"argument type not implemented");
    1537         441 :       break;
    1538       22718 :     case OCdefaultlong:
    1539       22718 :       sp--;
    1540       22718 :       if (st[sp+operand])
    1541         980 :         st[sp+operand]=gtos(gel(st,sp+operand));
    1542             :       else
    1543       21738 :         st[sp+operand]=st[sp];
    1544       22718 :       break;
    1545           0 :     case OCdefaultulong:
    1546           0 :       sp--;
    1547           0 :       if (st[sp+operand])
    1548           0 :         st[sp+operand]=gtou(gel(st,sp+operand));
    1549             :       else
    1550           0 :         st[sp+operand]=st[sp];
    1551           0 :       break;
    1552           0 :     case OCdefaultgen:
    1553           0 :       sp--;
    1554           0 :       if (!st[sp+operand])
    1555           0 :         st[sp+operand]=st[sp];
    1556           0 :       break;
    1557    26651158 :     case OCvec:
    1558    26651158 :       gel(st,sp++)=cgetg(operand,t_VEC);
    1559    26651159 :       st[sp++]=avma;
    1560    26651159 :       break;
    1561        3913 :     case OCcol:
    1562        3913 :       gel(st,sp++)=cgetg(operand,t_COL);
    1563        3913 :       st[sp++]=avma;
    1564        3913 :       break;
    1565       55181 :     case OCmat:
    1566             :       {
    1567             :         GEN z;
    1568       55181 :         long l=st[sp-1];
    1569       55181 :         z=cgetg(operand,t_MAT);
    1570      183743 :         for(j=1;j<operand;j++)
    1571      128562 :           gel(z,j) = cgetg(l,t_COL);
    1572       55181 :         gel(st,sp-1) = z;
    1573       55181 :         st[sp++]=avma;
    1574             :       }
    1575       55181 :       break;
    1576   106131569 :     case OCpop:
    1577   106131569 :       sp-=operand;
    1578   106131569 :       break;
    1579    31384383 :     case OCdup:
    1580             :       {
    1581    31384383 :         long i, s=st[sp-1];
    1582    31384383 :         st_alloc(operand);
    1583    62777765 :         for(i=1;i<=operand;i++)
    1584    31393382 :           st[sp++]=s;
    1585             :       }
    1586    31384383 :       break;
    1587             :     }
    1588  2923617595 :   }
    1589             :   if (0)
    1590             :   {
    1591      291528 : endeval:
    1592      291528 :     sp = saved_sp;
    1593      291528 :     for(  ; rp>saved_rp ;  )
    1594             :     {
    1595           0 :       gp_pointer *g = &ptrs[--rp];
    1596           0 :       clone_unlock_deep(g->ox);
    1597             :     }
    1598             :   }
    1599   301112211 :   s_prec.n = saved_prec;
    1600   301112211 :   s_trace.n--;
    1601   301112211 :   restore_vars(nbmvar, nblvar, nblock);
    1602   300679468 :   clone_unlock(C);
    1603   300589970 : }
    1604             : 
    1605             : GEN
    1606    31561067 : closure_evalgen(GEN C)
    1607             : {
    1608    31561067 :   pari_sp ltop=avma;
    1609    31561067 :   closure_eval(C);
    1610    31526161 :   if (br_status) return gc_NULL(ltop);
    1611    31526099 :   return gerepileupto(ltop,gel(st,--sp));
    1612             : }
    1613             : 
    1614             : long
    1615      294408 : evalstate_get_trace(void)
    1616      294408 : { return s_trace.n; }
    1617             : 
    1618             : void
    1619          18 : evalstate_set_trace(long lvl)
    1620          18 : { s_trace.n = lvl; }
    1621             : 
    1622             : void
    1623     1400787 : evalstate_save(struct pari_evalstate *state)
    1624             : {
    1625     1400787 :   state->avma = avma;
    1626     1400787 :   state->sp   = sp;
    1627     1400787 :   state->rp   = rp;
    1628     1400787 :   state->prec = s_prec.n;
    1629     1400787 :   state->var  = s_var.n;
    1630     1400787 :   state->lvars= s_lvars.n;
    1631     1400787 :   state->locks= s_locks.n;
    1632     1400787 :   state->trace= s_trace.n;
    1633     1400787 :   compilestate_save(&state->comp);
    1634     1400790 :   mtstate_save(&state->mt);
    1635     1400790 : }
    1636             : 
    1637             : void
    1638       46007 : evalstate_restore(struct pari_evalstate *state)
    1639             : {
    1640       46007 :   set_avma(state->avma);
    1641       46007 :   mtstate_restore(&state->mt);
    1642       46007 :   sp = state->sp;
    1643       46007 :   rp = state->rp;
    1644       46007 :   s_prec.n = state->prec;
    1645       46007 :   restore_vars(s_var.n-state->var, s_lvars.n-state->lvars,
    1646       46007 :                s_locks.n-state->locks);
    1647       46007 :   restore_trace(s_trace.n-state->trace);
    1648       46007 :   reset_break();
    1649       46007 :   compilestate_restore(&state->comp);
    1650       46007 : }
    1651             : 
    1652             : GEN
    1653       34892 : evalstate_restore_err(struct pari_evalstate *state)
    1654             : {
    1655       34892 :   GENbin* err = copy_bin(pari_err_last());
    1656       34892 :   evalstate_restore(state);
    1657       34892 :   return bin_copy(err);
    1658             : }
    1659             : 
    1660             : void
    1661         487 : evalstate_reset(void)
    1662             : {
    1663         487 :   mtstate_reset();
    1664         487 :   restore_vars(s_var.n, s_lvars.n, s_locks.n);
    1665         487 :   sp = rp = dbg_level = s_trace.n = 0;
    1666         487 :   reset_break();
    1667         487 :   compilestate_reset();
    1668         487 :   parsestate_reset();
    1669         487 :   set_avma(pari_mainstack->top);
    1670         487 : }
    1671             : 
    1672             : void
    1673           0 : evalstate_clone(void)
    1674             : {
    1675             :   long i;
    1676           0 :   for (i = 1; i<=s_var.n; i++) copylex(-i);
    1677           0 :   lvar_make_safe();
    1678           0 :   for (i = 0; i< s_trace.n; i++)
    1679             :   {
    1680           0 :     GEN C = trace[i].closure;
    1681           0 :     if (isonstack(C)) trace[i].closure = gclone(C);
    1682             :   }
    1683           0 : }
    1684             : 
    1685             : GEN
    1686          21 : closure_trapgen(GEN C, long numerr)
    1687             : {
    1688             :   VOLATILE GEN x;
    1689             :   struct pari_evalstate state;
    1690          21 :   evalstate_save(&state);
    1691          21 :   pari_CATCH(numerr) { x = (GEN)1L; }
    1692          21 :   pari_TRY { x = closure_evalgen(C); } pari_ENDCATCH;
    1693          14 :   if (x == (GEN)1L) evalstate_restore(&state);
    1694          14 :   return x;
    1695             : }
    1696             : 
    1697             : GEN
    1698    65033460 : closure_evalnobrk(GEN C)
    1699             : {
    1700    65033460 :   pari_sp ltop=avma;
    1701    65033460 :   closure_eval(C);
    1702    65033439 :   if (br_status) pari_err(e_MISC, "break not allowed here");
    1703    65033432 :   return gerepileupto(ltop,gel(st,--sp));
    1704             : }
    1705             : 
    1706             : void
    1707   152021485 : closure_evalvoid(GEN C)
    1708             : {
    1709   152021485 :   pari_sp ltop=avma;
    1710   152021485 :   closure_eval(C);
    1711   151914509 :   set_avma(ltop);
    1712   151899818 : }
    1713             : 
    1714             : GEN
    1715     9109632 : closure_evalres(GEN C)
    1716             : {
    1717     9109632 :   return closure_return(C);
    1718             : }
    1719             : 
    1720             : INLINE GEN
    1721     8287022 : closure_returnupto(GEN C)
    1722             : {
    1723     8287022 :   pari_sp av=avma;
    1724     8287022 :   return copyupto(closure_return(C),(GEN)av);
    1725             : }
    1726             : 
    1727             : GEN
    1728          12 : pareval_worker(GEN C)
    1729             : {
    1730          12 :   return closure_callgenall(C, 0);
    1731             : }
    1732             : 
    1733             : GEN
    1734           6 : pareval(GEN C)
    1735             : {
    1736           6 :   pari_sp av = avma;
    1737           6 :   long l = lg(C), i;
    1738             :   GEN worker;
    1739           6 :   if (!is_vec_t(typ(C))) pari_err_TYPE("pareval",C);
    1740          18 :   for (i=1; i<l; i++)
    1741          12 :     if (typ(gel(C,i))!=t_CLOSURE)
    1742           0 :       pari_err_TYPE("pareval",gel(C,i));
    1743           6 :   worker = snm_closure(is_entry("_pareval_worker"), NULL);
    1744           6 :   return gerepileupto(av, gen_parapply(worker, C));
    1745             : }
    1746             : 
    1747             : GEN
    1748         658 : parvector_worker(GEN i, GEN C)
    1749             : {
    1750         658 :   return closure_callgen1(C, i);
    1751             : }
    1752             : 
    1753             : GEN
    1754        7218 : parfor_worker(GEN i, GEN C)
    1755             : {
    1756        7218 :   retmkvec2(gcopy(i), closure_callgen1(C, i));
    1757             : }
    1758             : 
    1759             : GEN
    1760          31 : parvector(long n, GEN code)
    1761             : {
    1762          31 :   long i, pending = 0, workid;
    1763          31 :   GEN worker = snm_closure(is_entry("_parvector_worker"), mkvec(code));
    1764             :   GEN a, V, done;
    1765             :   struct pari_mt pt;
    1766          31 :   mt_queue_start_lim(&pt, worker, n);
    1767          31 :   a = mkvec(cgetipos(3)); /* left on the stack */
    1768          31 :   V = cgetg(n+1, t_VEC);
    1769         649 :   for (i=1; i<=n || pending; i++)
    1770             :   {
    1771         624 :     mael(a,1,2) = i;
    1772         624 :     mt_queue_submit(&pt, i, i<=n? a: NULL);
    1773         620 :     done = mt_queue_get(&pt, &workid, &pending);
    1774         618 :     if (done) gel(V,workid) = done;
    1775             :   }
    1776          25 :   mt_queue_end(&pt);
    1777          25 :   return V;
    1778             : }
    1779             : 
    1780             : /* B <- {a + k * m : k = 0, ..., (b-a)/m)} */
    1781             : static void
    1782         782 : arithprogset(GEN B, GEN a, GEN b, long m)
    1783             : {
    1784             :   long k;
    1785       62182 :   for (k = 1; cmpii(a, b) <= 0; a = addui(m,a), k++) gel(B, k) = a;
    1786         782 :   setlg(B, k);
    1787         782 : }
    1788             : static GEN
    1789         755 : vecsum_i(GEN v)
    1790             : {
    1791         755 :   long i, l = lg(v);
    1792             :   GEN s;
    1793         755 :   if (l == 1) return gen_0;
    1794       61298 :   s = gel(v,1); for (i = 2; i < l; i++) s = gadd(s, gel(v,i));
    1795         755 :   return s;
    1796             : }
    1797             : GEN
    1798          60 : parsum(GEN a, GEN b, GEN code)
    1799             : {
    1800          60 :   pari_sp av = avma;
    1801             :   GEN worker, L, v, s, N;
    1802             :   long r, m, pending;
    1803             :   struct pari_mt pt;
    1804             :   pari_sp av2;
    1805             : 
    1806          60 :   if (typ(a) != t_INT) pari_err_TYPE("parsum",a);
    1807          60 :   if (gcmp(b,a) < 0) return gen_0;
    1808          60 :   worker = snm_closure(is_entry("_parapply_slice_worker"), mkvec(code));
    1809          60 :   b = gfloor(b);
    1810          60 :   N = addiu(subii(b, a), 1);
    1811          60 :   m = itou(sqrti(N));
    1812          60 :   mt_queue_start_lim(&pt, worker, m);
    1813          60 :   L = cgetg(m + 2, t_VEC); v = mkvec(L);
    1814          60 :   s = gen_0; a = setloop(a); pending = 0; av2 = avma;
    1815         921 :   for (r = 1; r <= m || pending; r++)
    1816             :   {
    1817             :     long workid;
    1818             :     GEN done;
    1819         882 :     if (r <= m) { arithprogset(L, icopy(a), b, m); a = incloop(a); }
    1820         882 :     mt_queue_submit(&pt, 0, r <= m? v: NULL);
    1821         864 :     done = mt_queue_get(&pt, &workid, &pending);
    1822         861 :     if (done) s = gerepileupto(av2, gadd(s, vecsum_i(done)));
    1823             :   }
    1824          39 :   mt_queue_end(&pt); return gerepileupto(av, s);
    1825             : }
    1826             : 
    1827             : void
    1828         346 : parfor(GEN a, GEN b, GEN code, void *E, long call(void*, GEN, GEN))
    1829             : {
    1830         346 :   pari_sp av = avma, av2;
    1831         346 :   long running, pending = 0, lim;
    1832         346 :   long status = br_NONE;
    1833         346 :   GEN worker = snm_closure(is_entry("_parfor_worker"), mkvec(code));
    1834         346 :   GEN done, stop = NULL;
    1835             :   struct pari_mt pt;
    1836         346 :   if (typ(a) != t_INT) pari_err_TYPE("parfor",a);
    1837         346 :   if (b)
    1838             :   {
    1839         346 :     if (gcmp(b,a) < 0) return;
    1840         346 :     if (typ(b) == t_INFINITY)
    1841             :     {
    1842           6 :       if (inf_get_sign(b) < 0) return;
    1843           6 :       b = NULL;
    1844             :     }
    1845             :     else
    1846         340 :       b = gfloor(b);
    1847             :   }
    1848         346 :   lim = b ? itos_or_0(subii(addis(b,1),a)): 0;
    1849         346 :   mt_queue_start_lim(&pt, worker, lim);
    1850         346 :   a = mkvec(setloop(a));
    1851         346 :   av2 = avma;
    1852        7816 :   while ((running = (!stop && (!b || cmpii(gel(a,1),b) <= 0))) || pending)
    1853             :   {
    1854        7476 :     mt_queue_submit(&pt, 0, running ? a: NULL);
    1855        7472 :     done = mt_queue_get(&pt, NULL, &pending);
    1856        7470 :     if (call && done && (!stop || cmpii(gel(done,1),stop) < 0))
    1857        5465 :       if (call(E, gel(done,1), gel(done,2)))
    1858             :       {
    1859         223 :         status = br_status;
    1860         223 :         br_status = br_NONE;
    1861         223 :         stop = gerepileuptoint(av2, gel(done,1));
    1862             :       }
    1863        7470 :     gel(a,1) = incloop(gel(a,1));
    1864        7470 :     if (!stop) set_avma(av2);
    1865             :   }
    1866         340 :   set_avma(av2);
    1867         340 :   mt_queue_end(&pt);
    1868         340 :   br_status = status;
    1869         340 :   set_avma(av);
    1870             : }
    1871             : 
    1872             : static void
    1873           0 : parforiter_init(struct parfor_iter *T, GEN code)
    1874             : {
    1875           0 :   T->pending = 0;
    1876           0 :   T->worker = snm_closure(is_entry("_parfor_worker"), mkvec(code));
    1877           0 :   mt_queue_start(&T->pt, T->worker);
    1878           0 : }
    1879             : 
    1880             : static GEN
    1881           0 : parforiter_next(struct parfor_iter *T, GEN v)
    1882             : {
    1883           0 :   mt_queue_submit(&T->pt, 0, v);
    1884           0 :   return mt_queue_get(&T->pt, NULL, &T->pending);
    1885             : }
    1886             : 
    1887             : static void
    1888           0 : parforiter_stop(struct parfor_iter *T)
    1889             : {
    1890           0 :   while (T->pending)
    1891             :   {
    1892           0 :     mt_queue_submit(&T->pt, 0, NULL);
    1893           0 :     (void) mt_queue_get(&T->pt, NULL, &T->pending);
    1894             :   }
    1895           0 :   mt_queue_end(&T->pt);
    1896           0 : }
    1897             : 
    1898             : void
    1899           0 : parfor_init(parfor_t *T, GEN a, GEN b, GEN code)
    1900             : {
    1901           0 :   if (typ(a) != t_INT) pari_err_TYPE("parfor",a);
    1902           0 :   T->b = b ? gfloor(b): NULL;
    1903           0 :   T->a = mkvec(setloop(a));
    1904           0 :   parforiter_init(&T->iter, code);
    1905           0 : }
    1906             : 
    1907             : GEN
    1908           0 : parfor_next(parfor_t *T)
    1909             : {
    1910             :   long running;
    1911           0 :   while ((running=((!T->b || cmpii(gel(T->a,1),T->b) <= 0))) || T->iter.pending)
    1912             :   {
    1913           0 :     GEN done = parforiter_next(&T->iter, running ? T->a: NULL);
    1914           0 :     gel(T->a,1) = incloop(gel(T->a,1));
    1915           0 :     if (done) return done;
    1916             :   }
    1917           0 :   mt_queue_end(&T->iter.pt);
    1918           0 :   return NULL;
    1919             : }
    1920             : 
    1921             : void
    1922           0 : parfor_stop(parfor_t *T) { parforiter_stop(&T->iter); }
    1923             : 
    1924             : static long
    1925        5946 : gp_evalvoid2(void *E, GEN x, GEN y)
    1926             : {
    1927        5946 :   GEN code =(GEN) E;
    1928        5946 :   push_lex(x, code);
    1929        5946 :   push_lex(y, NULL);
    1930        5946 :   closure_evalvoid(code);
    1931        5946 :   pop_lex(2);
    1932        5946 :   return loop_break();
    1933             : }
    1934             : 
    1935             : void
    1936         346 : parfor0(GEN a, GEN b, GEN code, GEN code2)
    1937             : {
    1938         346 :   parfor(a, b, code, (void*)code2, code2 ? gp_evalvoid2: NULL);
    1939         340 : }
    1940             : 
    1941             : void
    1942           0 : parforprimestep_init(parforprime_t *T, GEN a, GEN b, GEN q, GEN code)
    1943             : {
    1944           0 :   forprimestep_init(&T->forprime, a, b, q);
    1945           0 :   T->v = mkvec(gen_0);
    1946           0 :   parforiter_init(&T->iter, code);
    1947           0 : }
    1948             : 
    1949             : void
    1950           0 : parforprime_init(parforprime_t *T, GEN a, GEN b, GEN code)
    1951           0 : { parforprimestep_init(T, a, b, NULL, code); }
    1952             : 
    1953             : GEN
    1954           0 : parforprime_next(parforprime_t *T)
    1955             : {
    1956             :   long running;
    1957           0 :   while ((running = !!forprime_next(&T->forprime)) || T->iter.pending)
    1958             :   {
    1959             :     GEN done;
    1960           0 :     gel(T->v, 1) = T->forprime.pp;
    1961           0 :     done = parforiter_next(&T->iter, running ? T->v: NULL);
    1962           0 :     if (done) return done;
    1963             :   }
    1964           0 :   mt_queue_end(&T->iter.pt);
    1965           0 :   return NULL;
    1966             : }
    1967             : 
    1968             : void
    1969           0 : parforprime_stop(parforprime_t *T) { parforiter_stop(&T->iter); }
    1970             : 
    1971             : void
    1972          20 : parforprimestep(GEN a, GEN b, GEN q, GEN code, void *E, long call(void*, GEN, GEN))
    1973             : {
    1974          20 :   pari_sp av = avma, av2;
    1975          20 :   long running, pending = 0;
    1976          20 :   long status = br_NONE;
    1977          20 :   GEN worker = snm_closure(is_entry("_parfor_worker"), mkvec(code));
    1978          20 :   GEN v, done, stop = NULL;
    1979             :   struct pari_mt pt;
    1980             :   forprime_t T;
    1981             : 
    1982          20 :   if (!forprimestep_init(&T, a,b,q)) { set_avma(av); return; }
    1983          20 :   mt_queue_start(&pt, worker);
    1984          20 :   v = mkvec(gen_0);
    1985          20 :   av2 = avma;
    1986         172 :   while ((running = (!stop && forprime_next(&T))) || pending)
    1987             :   {
    1988         152 :     gel(v, 1) = T.pp;
    1989         152 :     mt_queue_submit(&pt, 0, running ? v: NULL);
    1990         152 :     done = mt_queue_get(&pt, NULL, &pending);
    1991         152 :     if (call && done && (!stop || cmpii(gel(done,1),stop) < 0))
    1992         125 :       if (call(E, gel(done,1), gel(done,2)))
    1993             :       {
    1994           0 :         status = br_status;
    1995           0 :         br_status = br_NONE;
    1996           0 :         stop = gerepileuptoint(av2, gel(done,1));
    1997             :       }
    1998         152 :     if (!stop) set_avma(av2);
    1999             :   }
    2000          20 :   set_avma(av2);
    2001          20 :   mt_queue_end(&pt);
    2002          20 :   br_status = status;
    2003          20 :   set_avma(av);
    2004             : }
    2005             : 
    2006             : void
    2007          13 : parforprime(GEN a, GEN b, GEN code, void *E, long call(void*, GEN, GEN))
    2008             : {
    2009          13 :   parforprimestep(a, b, NULL, code, E, call);
    2010          13 : }
    2011             : 
    2012             : void
    2013          13 : parforprime0(GEN a, GEN b, GEN code, GEN code2)
    2014             : {
    2015          13 :   parforprime(a, b, code, (void*)code2, code2? gp_evalvoid2: NULL);
    2016          13 : }
    2017             : 
    2018             : void
    2019           7 : parforprimestep0(GEN a, GEN b, GEN q, GEN code, GEN code2)
    2020             : {
    2021           7 :   parforprimestep(a, b, q, code, (void*)code2, code2? gp_evalvoid2: NULL);
    2022           7 : }
    2023             : 
    2024             : void
    2025           0 : parforvec_init(parforvec_t *T, GEN x, GEN code, long flag)
    2026             : {
    2027           0 :   forvec_init(&T->forvec, x, flag);
    2028           0 :   T->v = mkvec(gen_0);
    2029           0 :   parforiter_init(&T->iter, code);
    2030           0 : }
    2031             : 
    2032             : GEN
    2033           0 : parforvec_next(parforvec_t *T)
    2034             : {
    2035           0 :   GEN v = gen_0;
    2036           0 :   while ((v = forvec_next(&T->forvec)) || T->iter.pending)
    2037             :   {
    2038             :     GEN done;
    2039           0 :     if (v) gel(T->v, 1) = v;
    2040           0 :     done = parforiter_next(&T->iter, v ? T->v: NULL);
    2041           0 :     if (done) return done;
    2042             :   }
    2043           0 :   mt_queue_end(&T->iter.pt);
    2044           0 :   return NULL;
    2045             : }
    2046             : 
    2047             : void
    2048           0 : parforvec_stop(parforvec_t *T) { parforiter_stop(&T->iter); }
    2049             : 
    2050             : void
    2051          39 : parforvec(GEN x, GEN code, long flag, void *E, long call(void*, GEN, GEN))
    2052             : {
    2053          39 :   pari_sp av = avma, av2;
    2054          39 :   long running, pending = 0;
    2055          39 :   long status = br_NONE;
    2056          39 :   GEN worker = snm_closure(is_entry("_parfor_worker"), mkvec(code));
    2057          39 :   GEN done, stop = NULL;
    2058             :   struct pari_mt pt;
    2059             :   forvec_t T;
    2060          39 :   GEN a, v = gen_0;
    2061             : 
    2062          39 :   if (!forvec_init(&T, x, flag)) { set_avma(av); return; }
    2063          39 :   mt_queue_start(&pt, worker);
    2064          39 :   a = mkvec(gen_0);
    2065          39 :   av2 = avma;
    2066         415 :   while ((running = (!stop && v && (v = forvec_next(&T)))) || pending)
    2067             :   {
    2068         376 :     gel(a, 1) = v;
    2069         376 :     mt_queue_submit(&pt, 0, running ? a: NULL);
    2070         376 :     done = mt_queue_get(&pt, NULL, &pending);
    2071         376 :     if (call && done && (!stop || lexcmp(gel(done,1),stop) < 0))
    2072         300 :       if (call(E, gel(done,1), gel(done,2)))
    2073             :       {
    2074           0 :         status = br_status;
    2075           0 :         br_status = br_NONE;
    2076           0 :         stop = gerepilecopy(av2, gel(done,1));
    2077             :       }
    2078         376 :     if (!stop) set_avma(av2);
    2079             :   }
    2080          39 :   set_avma(av2);
    2081          39 :   mt_queue_end(&pt);
    2082          39 :   br_status = status;
    2083          39 :   set_avma(av);
    2084             : }
    2085             : 
    2086             : void
    2087          39 : parforvec0(GEN x, GEN code, GEN code2, long flag)
    2088             : {
    2089          39 :   parforvec(x, code, flag, (void*)code2, code2? gp_evalvoid2: NULL);
    2090          39 : }
    2091             : 
    2092             : void
    2093           0 : parforeach_init(parforeach_t *T, GEN x, GEN code)
    2094             : {
    2095           0 :   switch(typ(x))
    2096             :   {
    2097           0 :     case t_LIST:
    2098           0 :       x = list_data(x); /* FALL THROUGH */
    2099           0 :       if (!x) return;
    2100             :     case t_MAT: case t_VEC: case t_COL:
    2101           0 :       break;
    2102           0 :     default:
    2103           0 :       pari_err_TYPE("foreach",x);
    2104             :       return; /*LCOV_EXCL_LINE*/
    2105             :   }
    2106           0 :   T->x = x; T->i = 1; T->l = lg(x);
    2107           0 :   T->W = mkvec(gen_0);
    2108           0 :   T->iter.pending = 0;
    2109           0 :   T->iter.worker = snm_closure(is_entry("_parvector_worker"), mkvec(code));
    2110           0 :   mt_queue_start(&T->iter.pt, T->iter.worker);
    2111             : }
    2112             : 
    2113             : GEN
    2114           0 : parforeach_next(parforeach_t *T)
    2115             : {
    2116           0 :   while (T->i < T->l || T->iter.pending)
    2117             :   {
    2118             :     GEN done;
    2119             :     long workid;
    2120           0 :     if (T->i < T->l) gel(T->W,1) = gel(T->x, T->i);
    2121           0 :     mt_queue_submit(&T->iter.pt, T->i, T->i < T->l ? T->W: NULL);
    2122           0 :     T->i = minss(T->i+1, T->l);
    2123           0 :     done = mt_queue_get(&T->iter.pt, &workid, &T->iter.pending);
    2124           0 :     if (done) return mkvec2(gel(T->x,workid),done);
    2125             :   }
    2126           0 :   mt_queue_end(&T->iter.pt);
    2127           0 :   return NULL;
    2128             : }
    2129             : 
    2130             : void
    2131           0 : parforeach_stop(parforeach_t *T) { parforiter_stop(&T->iter); }
    2132             : 
    2133             : void
    2134           7 : parforeach(GEN x, GEN code, void *E, long call(void*, GEN, GEN))
    2135             : {
    2136           7 :   pari_sp av = avma, av2;
    2137           7 :   long pending = 0, n, i, stop = 0;
    2138           7 :   long status = br_NONE, workid;
    2139           7 :   GEN worker = snm_closure(is_entry("_parvector_worker"), mkvec(code));
    2140             :   GEN done, W;
    2141             :   struct pari_mt pt;
    2142           7 :   switch(typ(x))
    2143             :   {
    2144           0 :     case t_LIST:
    2145           0 :       x = list_data(x); /* FALL THROUGH */
    2146           0 :       if (!x) return;
    2147             :     case t_MAT: case t_VEC: case t_COL:
    2148           7 :       break;
    2149           0 :     default:
    2150           0 :       pari_err_TYPE("foreach",x);
    2151             :       return; /*LCOV_EXCL_LINE*/
    2152             :   }
    2153           7 :   clone_lock(x); n = lg(x)-1;
    2154           7 :   mt_queue_start_lim(&pt, worker, n);
    2155           7 :   W = cgetg(2, t_VEC);
    2156           7 :   av2 = avma;
    2157          70 :   for (i=1; i<=n || pending; i++)
    2158             :   {
    2159          63 :     if (!stop && i <= n) gel(W,1) = gel(x,i);
    2160          63 :     mt_queue_submit(&pt, i, !stop && i<=n? W: NULL);
    2161          63 :     done = mt_queue_get(&pt, &workid, &pending);
    2162          63 :     if (call && done && (!stop || workid < stop))
    2163          56 :       if (call(E, gel(x, workid), done))
    2164             :       {
    2165           0 :         status = br_status;
    2166           0 :         br_status = br_NONE;
    2167           0 :         stop = workid;
    2168             :       }
    2169             :   }
    2170           7 :   set_avma(av2);
    2171           7 :   mt_queue_end(&pt);
    2172           7 :   clone_unlock_deep(x);
    2173           7 :   br_status = status;
    2174           7 :   set_avma(av);
    2175             : }
    2176             : 
    2177             : void
    2178           7 : parforeach0(GEN x, GEN code, GEN code2)
    2179             : {
    2180           7 :   parforeach(x, code, (void*)code2, code2? gp_evalvoid2: NULL);
    2181           7 : }
    2182             : 
    2183             : void
    2184           0 : closure_callvoid1(GEN C, GEN x)
    2185             : {
    2186           0 :   long i, ar = closure_arity(C);
    2187           0 :   gel(st,sp++) = x;
    2188           0 :   for(i=2; i <= ar; i++) gel(st,sp++) = NULL;
    2189           0 :   closure_evalvoid(C);
    2190           0 : }
    2191             : 
    2192             : GEN
    2193         168 : closure_callgen0prec(GEN C, long prec)
    2194             : {
    2195             :   GEN z;
    2196         168 :   long i, ar = closure_arity(C);
    2197         168 :   for(i=1; i<= ar; i++) gel(st,sp++) = NULL;
    2198         168 :   push_localprec(prec);
    2199         168 :   z = closure_returnupto(C);
    2200         168 :   pop_localprec();
    2201         168 :   return z;
    2202             : }
    2203             : 
    2204             : GEN
    2205     6368293 : closure_callgen1(GEN C, GEN x)
    2206             : {
    2207     6368293 :   long i, ar = closure_arity(C);
    2208     6368243 :   gel(st,sp++) = x;
    2209     6469817 :   for(i=2; i<= ar; i++) gel(st,sp++) = NULL;
    2210     6368243 :   return closure_returnupto(C);
    2211             : }
    2212             : 
    2213             : GEN
    2214       71732 : closure_callgen1prec(GEN C, GEN x, long prec)
    2215             : {
    2216             :   GEN z;
    2217       71732 :   long i, ar = closure_arity(C);
    2218       71732 :   gel(st,sp++) = x;
    2219       71746 :   for(i=2; i<= ar; i++) gel(st,sp++) = NULL;
    2220       71732 :   push_localprec(prec);
    2221       71732 :   z = closure_returnupto(C);
    2222       71732 :   pop_localprec();
    2223       71732 :   return z;
    2224             : }
    2225             : 
    2226             : GEN
    2227       67053 : closure_callgen2(GEN C, GEN x, GEN y)
    2228             : {
    2229       67053 :   long i, ar = closure_arity(C);
    2230       67053 :   st_alloc(ar);
    2231       67053 :   gel(st,sp++) = x;
    2232       67053 :   gel(st,sp++) = y;
    2233       67053 :   for(i=3; i<=ar; i++) gel(st,sp++) = NULL;
    2234       67053 :   return closure_returnupto(C);
    2235             : }
    2236             : 
    2237             : GEN
    2238     1780024 : closure_callgenvec(GEN C, GEN args)
    2239             : {
    2240     1780024 :   long i, l = lg(args)-1, ar = closure_arity(C);
    2241     1779952 :   st_alloc(ar);
    2242     1779903 :   if (l > ar)
    2243           0 :     pari_err(e_MISC,"too many parameters in user-defined function call");
    2244     1779903 :   if (closure_is_variadic(C) && l==ar && typ(gel(args,l))!=t_VEC)
    2245           7 :     pari_err_TYPE("call", gel(args,l));
    2246     3596903 :   for (i = 1; i <= l;  i++) gel(st,sp++) = gel(args,i);
    2247     1779654 :   for(      ; i <= ar; i++) gel(st,sp++) = NULL;
    2248     1779642 :   return closure_returnupto(C);
    2249             : }
    2250             : 
    2251             : GEN
    2252           0 : closure_callgenvecprec(GEN C, GEN args, long prec)
    2253             : {
    2254             :   GEN z;
    2255           0 :   push_localprec(prec);
    2256           0 :   z = closure_callgenvec(C, args);
    2257           0 :   pop_localprec();
    2258           0 :   return z;
    2259             : }
    2260             : 
    2261             : GEN
    2262         322 : closure_callgenvecdef(GEN C, GEN args, GEN def)
    2263             : {
    2264         322 :   long i, l = lg(args)-1, ar = closure_arity(C);
    2265         322 :   st_alloc(ar);
    2266         322 :   if (l > ar)
    2267           0 :     pari_err(e_MISC,"too many parameters in user-defined function call");
    2268         322 :   if (closure_is_variadic(C) && l==ar && typ(gel(args,l))!=t_VEC)
    2269           0 :     pari_err_TYPE("call", gel(args,l));
    2270         644 :   for (i = 1; i <= l;  i++) gel(st,sp++) = def[i] ? gel(args,i): NULL;
    2271         322 :   for(      ; i <= ar; i++) gel(st,sp++) = NULL;
    2272         322 :   return closure_returnupto(C);
    2273             : }
    2274             : 
    2275             : GEN
    2276         322 : closure_callgenvecdefprec(GEN C, GEN args, GEN def, long prec)
    2277             : {
    2278             :   GEN z;
    2279         322 :   push_localprec(prec);
    2280         322 :   z = closure_callgenvecdef(C, args, def);
    2281         322 :   pop_localprec();
    2282         322 :   return z;
    2283             : }
    2284             : GEN
    2285          12 : closure_callgenall(GEN C, long n, ...)
    2286             : {
    2287             :   va_list ap;
    2288          12 :   long i, ar = closure_arity(C);
    2289          12 :   va_start(ap,n);
    2290          12 :   if (n > ar)
    2291           0 :     pari_err(e_MISC,"too many parameters in user-defined function call");
    2292          12 :   st_alloc(ar);
    2293          12 :   for (i = 1; i <=n;  i++) gel(st,sp++) = va_arg(ap, GEN);
    2294          12 :   for(      ; i <=ar; i++) gel(st,sp++) = NULL;
    2295          12 :   va_end(ap);
    2296          12 :   return closure_returnupto(C);
    2297             : }
    2298             : 
    2299             : GEN
    2300    39640777 : gp_eval(void *E, GEN x)
    2301             : {
    2302    39640777 :   GEN code = (GEN)E;
    2303    39640777 :   set_lex(-1,x);
    2304    39640777 :   return closure_evalnobrk(code);
    2305             : }
    2306             : 
    2307             : GEN
    2308     1871672 : gp_evalupto(void *E, GEN x)
    2309             : {
    2310     1871672 :   pari_sp av = avma;
    2311     1871672 :   return copyupto(gp_eval(E,x), (GEN)av);
    2312             : }
    2313             : 
    2314             : GEN
    2315       20734 : gp_evalprec(void *E, GEN x, long prec)
    2316             : {
    2317             :   GEN z;
    2318       20734 :   push_localprec(prec);
    2319       20734 :   z = gp_eval(E, x);
    2320       20734 :   pop_localprec();
    2321       20734 :   return z;
    2322             : }
    2323             : 
    2324             : long
    2325    26165027 : gp_evalbool(void *E, GEN x)
    2326    26165027 : { pari_sp av = avma; return gc_long(av, !gequal0(gp_eval(E,x))); }
    2327             : 
    2328             : long
    2329     3655883 : gp_evalvoid(void *E, GEN x)
    2330             : {
    2331     3655883 :   GEN code = (GEN)E;
    2332     3655883 :   set_lex(-1,x);
    2333     3655883 :   closure_evalvoid(code);
    2334     3655883 :   return loop_break();
    2335             : }
    2336             : 
    2337             : GEN
    2338      111588 : gp_call(void *E, GEN x)
    2339             : {
    2340      111588 :   GEN code = (GEN)E;
    2341      111588 :   return closure_callgen1(code, x);
    2342             : }
    2343             : 
    2344             : GEN
    2345       18529 : gp_callprec(void *E, GEN x, long prec)
    2346             : {
    2347       18529 :   GEN code = (GEN)E;
    2348       18529 :   return closure_callgen1prec(code, x, prec);
    2349             : }
    2350             : 
    2351             : GEN
    2352          91 : gp_call2(void *E, GEN x, GEN y)
    2353             : {
    2354          91 :   GEN code = (GEN)E;
    2355          91 :   return closure_callgen2(code, x, y);
    2356             : }
    2357             : 
    2358             : long
    2359      871997 : gp_callbool(void *E, GEN x)
    2360             : {
    2361      871997 :   pari_sp av = avma;
    2362      871997 :   GEN code = (GEN)E;
    2363      871997 :   return gc_long(av, !gequal0(closure_callgen1(code, x)));
    2364             : }
    2365             : 
    2366             : long
    2367           0 : gp_callvoid(void *E, GEN x)
    2368             : {
    2369           0 :   GEN code = (GEN)E;
    2370           0 :   closure_callvoid1(code, x);
    2371           0 :   return loop_break();
    2372             : }
    2373             : 
    2374             : INLINE const char *
    2375           0 : disassemble_cast(long mode)
    2376             : {
    2377           0 :   switch (mode)
    2378             :   {
    2379           0 :   case Gsmall:
    2380           0 :     return "small";
    2381           0 :   case Ggen:
    2382           0 :     return "gen";
    2383           0 :   case Gvar:
    2384           0 :     return "var";
    2385           0 :   case Gvoid:
    2386           0 :     return "void";
    2387           0 :   default:
    2388           0 :     return "unknown";
    2389             :   }
    2390             : }
    2391             : 
    2392             : void
    2393           0 : closure_disassemble(GEN C)
    2394             : {
    2395             :   const char * code;
    2396             :   GEN oper;
    2397             :   long i;
    2398           0 :   if (typ(C)!=t_CLOSURE) pari_err_TYPE("disassemble",C);
    2399           0 :   code=closure_codestr(C);
    2400           0 :   oper=closure_get_oper(C);
    2401           0 :   for(i=1;i<lg(oper);i++)
    2402             :   {
    2403           0 :     op_code opcode=(op_code) code[i];
    2404           0 :     long operand=oper[i];
    2405           0 :     pari_printf("%05ld\t",i);
    2406           0 :     switch(opcode)
    2407             :     {
    2408           0 :     case OCpushlong:
    2409           0 :       pari_printf("pushlong\t%ld\n",operand);
    2410           0 :       break;
    2411           0 :     case OCpushgnil:
    2412           0 :       pari_printf("pushgnil\n");
    2413           0 :       break;
    2414           0 :     case OCpushgen:
    2415           0 :       pari_printf("pushgen\t\t%ld\n",operand);
    2416           0 :       break;
    2417           0 :     case OCpushreal:
    2418           0 :       pari_printf("pushreal\t%ld\n",operand);
    2419           0 :       break;
    2420           0 :     case OCpushstoi:
    2421           0 :       pari_printf("pushstoi\t%ld\n",operand);
    2422           0 :       break;
    2423           0 :     case OCpushvar:
    2424             :       {
    2425           0 :         entree *ep = (entree *)operand;
    2426           0 :         pari_printf("pushvar\t%s\n",ep->name);
    2427           0 :         break;
    2428             :       }
    2429           0 :     case OCpushdyn:
    2430             :       {
    2431           0 :         entree *ep = (entree *)operand;
    2432           0 :         pari_printf("pushdyn\t\t%s\n",ep->name);
    2433           0 :         break;
    2434             :       }
    2435           0 :     case OCpushlex:
    2436           0 :       pari_printf("pushlex\t\t%ld\n",operand);
    2437           0 :       break;
    2438           0 :     case OCstoredyn:
    2439             :       {
    2440           0 :         entree *ep = (entree *)operand;
    2441           0 :         pari_printf("storedyn\t%s\n",ep->name);
    2442           0 :         break;
    2443             :       }
    2444           0 :     case OCstorelex:
    2445           0 :       pari_printf("storelex\t%ld\n",operand);
    2446           0 :       break;
    2447           0 :     case OCstoreptr:
    2448           0 :       pari_printf("storeptr\n");
    2449           0 :       break;
    2450           0 :     case OCsimpleptrdyn:
    2451             :       {
    2452           0 :         entree *ep = (entree *)operand;
    2453           0 :         pari_printf("simpleptrdyn\t%s\n",ep->name);
    2454           0 :         break;
    2455             :       }
    2456           0 :     case OCsimpleptrlex:
    2457           0 :       pari_printf("simpleptrlex\t%ld\n",operand);
    2458           0 :       break;
    2459           0 :     case OCnewptrdyn:
    2460             :       {
    2461           0 :         entree *ep = (entree *)operand;
    2462           0 :         pari_printf("newptrdyn\t%s\n",ep->name);
    2463           0 :         break;
    2464             :       }
    2465           0 :     case OCnewptrlex:
    2466           0 :       pari_printf("newptrlex\t%ld\n",operand);
    2467           0 :       break;
    2468           0 :     case OCpushptr:
    2469           0 :       pari_printf("pushptr\n");
    2470           0 :       break;
    2471           0 :     case OCstackgen:
    2472           0 :       pari_printf("stackgen\t%ld\n",operand);
    2473           0 :       break;
    2474           0 :     case OCendptr:
    2475           0 :       pari_printf("endptr\t\t%ld\n",operand);
    2476           0 :       break;
    2477           0 :     case OCprecreal:
    2478           0 :       pari_printf("precreal\n");
    2479           0 :       break;
    2480           0 :     case OCbitprecreal:
    2481           0 :       pari_printf("bitprecreal\n");
    2482           0 :       break;
    2483           0 :     case OCprecdl:
    2484           0 :       pari_printf("precdl\n");
    2485           0 :       break;
    2486           0 :     case OCstoi:
    2487           0 :       pari_printf("stoi\n");
    2488           0 :       break;
    2489           0 :     case OCutoi:
    2490           0 :       pari_printf("utoi\n");
    2491           0 :       break;
    2492           0 :     case OCitos:
    2493           0 :       pari_printf("itos\t\t%ld\n",operand);
    2494           0 :       break;
    2495           0 :     case OCitou:
    2496           0 :       pari_printf("itou\t\t%ld\n",operand);
    2497           0 :       break;
    2498           0 :     case OCtostr:
    2499           0 :       pari_printf("tostr\t\t%ld\n",operand);
    2500           0 :       break;
    2501           0 :     case OCvarn:
    2502           0 :       pari_printf("varn\t\t%ld\n",operand);
    2503           0 :       break;
    2504           0 :     case OCcopy:
    2505           0 :       pari_printf("copy\n");
    2506           0 :       break;
    2507           0 :     case OCcopyifclone:
    2508           0 :       pari_printf("copyifclone\n");
    2509           0 :       break;
    2510           0 :     case OCcompo1:
    2511           0 :       pari_printf("compo1\t\t%s\n",disassemble_cast(operand));
    2512           0 :       break;
    2513           0 :     case OCcompo1ptr:
    2514           0 :       pari_printf("compo1ptr\n");
    2515           0 :       break;
    2516           0 :     case OCcompo2:
    2517           0 :       pari_printf("compo2\t\t%s\n",disassemble_cast(operand));
    2518           0 :       break;
    2519           0 :     case OCcompo2ptr:
    2520           0 :       pari_printf("compo2ptr\n");
    2521           0 :       break;
    2522           0 :     case OCcompoC:
    2523           0 :       pari_printf("compoC\n");
    2524           0 :       break;
    2525           0 :     case OCcompoCptr:
    2526           0 :       pari_printf("compoCptr\n");
    2527           0 :       break;
    2528           0 :     case OCcompoL:
    2529           0 :       pari_printf("compoL\n");
    2530           0 :       break;
    2531           0 :     case OCcompoLptr:
    2532           0 :       pari_printf("compoLptr\n");
    2533           0 :       break;
    2534           0 :     case OCcheckargs:
    2535           0 :       pari_printf("checkargs\t0x%lx\n",operand);
    2536           0 :       break;
    2537           0 :     case OCcheckargs0:
    2538           0 :       pari_printf("checkargs0\t0x%lx\n",operand);
    2539           0 :       break;
    2540           0 :     case OCcheckuserargs:
    2541           0 :       pari_printf("checkuserargs\t%ld\n",operand);
    2542           0 :       break;
    2543           0 :     case OCdefaultlong:
    2544           0 :       pari_printf("defaultlong\t%ld\n",operand);
    2545           0 :       break;
    2546           0 :     case OCdefaultulong:
    2547           0 :       pari_printf("defaultulong\t%ld\n",operand);
    2548           0 :       break;
    2549           0 :     case OCdefaultgen:
    2550           0 :       pari_printf("defaultgen\t%ld\n",operand);
    2551           0 :       break;
    2552           0 :     case OCpackargs:
    2553           0 :       pari_printf("packargs\t%ld\n",operand);
    2554           0 :       break;
    2555           0 :     case OCgetargs:
    2556           0 :       pari_printf("getargs\t\t%ld\n",operand);
    2557           0 :       break;
    2558           0 :     case OCdefaultarg:
    2559           0 :       pari_printf("defaultarg\t%ld\n",operand);
    2560           0 :       break;
    2561           0 :     case OClocalvar:
    2562             :       {
    2563           0 :         entree *ep = (entree *)operand;
    2564           0 :         pari_printf("localvar\t%s\n",ep->name);
    2565           0 :         break;
    2566             :       }
    2567           0 :     case OClocalvar0:
    2568             :       {
    2569           0 :         entree *ep = (entree *)operand;
    2570           0 :         pari_printf("localvar0\t%s\n",ep->name);
    2571           0 :         break;
    2572             :       }
    2573           0 :     case OCexportvar:
    2574             :       {
    2575           0 :         entree *ep = (entree *)operand;
    2576           0 :         pari_printf("exportvar\t%s\n",ep->name);
    2577           0 :         break;
    2578             :       }
    2579           0 :     case OCunexportvar:
    2580             :       {
    2581           0 :         entree *ep = (entree *)operand;
    2582           0 :         pari_printf("unexportvar\t%s\n",ep->name);
    2583           0 :         break;
    2584             :       }
    2585           0 :     case OCcallgen:
    2586             :       {
    2587           0 :         entree *ep = (entree *)operand;
    2588           0 :         pari_printf("callgen\t\t%s\n",ep->name);
    2589           0 :         break;
    2590             :       }
    2591           0 :     case OCcallgen2:
    2592             :       {
    2593           0 :         entree *ep = (entree *)operand;
    2594           0 :         pari_printf("callgen2\t%s\n",ep->name);
    2595           0 :         break;
    2596             :       }
    2597           0 :     case OCcalllong:
    2598             :       {
    2599           0 :         entree *ep = (entree *)operand;
    2600           0 :         pari_printf("calllong\t%s\n",ep->name);
    2601           0 :         break;
    2602             :       }
    2603           0 :     case OCcallint:
    2604             :       {
    2605           0 :         entree *ep = (entree *)operand;
    2606           0 :         pari_printf("callint\t\t%s\n",ep->name);
    2607           0 :         break;
    2608             :       }
    2609           0 :     case OCcallvoid:
    2610             :       {
    2611           0 :         entree *ep = (entree *)operand;
    2612           0 :         pari_printf("callvoid\t%s\n",ep->name);
    2613           0 :         break;
    2614             :       }
    2615           0 :     case OCcalluser:
    2616           0 :       pari_printf("calluser\t%ld\n",operand);
    2617           0 :       break;
    2618           0 :     case OCvec:
    2619           0 :       pari_printf("vec\t\t%ld\n",operand);
    2620           0 :       break;
    2621           0 :     case OCcol:
    2622           0 :       pari_printf("col\t\t%ld\n",operand);
    2623           0 :       break;
    2624           0 :     case OCmat:
    2625           0 :       pari_printf("mat\t\t%ld\n",operand);
    2626           0 :       break;
    2627           0 :     case OCnewframe:
    2628           0 :       pari_printf("newframe\t%ld\n",operand);
    2629           0 :       break;
    2630           0 :     case OCsaveframe:
    2631           0 :       pari_printf("saveframe\t%ld\n", operand);
    2632           0 :       break;
    2633           0 :     case OCpop:
    2634           0 :       pari_printf("pop\t\t%ld\n",operand);
    2635           0 :       break;
    2636           0 :     case OCdup:
    2637           0 :       pari_printf("dup\t\t%ld\n",operand);
    2638           0 :       break;
    2639           0 :     case OCavma:
    2640           0 :       pari_printf("avma\n",operand);
    2641           0 :       break;
    2642           0 :     case OCgerepile:
    2643           0 :       pari_printf("gerepile\n",operand);
    2644           0 :       break;
    2645           0 :     case OCcowvardyn:
    2646             :       {
    2647           0 :         entree *ep = (entree *)operand;
    2648           0 :         pari_printf("cowvardyn\t%s\n",ep->name);
    2649           0 :         break;
    2650             :       }
    2651           0 :     case OCcowvarlex:
    2652           0 :       pari_printf("cowvarlex\t%ld\n",operand);
    2653           0 :       break;
    2654           0 :     case OCsetref:
    2655           0 :       pari_printf("setref\t\t%ld\n",operand);
    2656           0 :       break;
    2657           0 :     case OClock:
    2658           0 :       pari_printf("lock\t\t%ld\n",operand);
    2659           0 :       break;
    2660             :     }
    2661           0 :   }
    2662           0 : }
    2663             : 
    2664             : static int
    2665           0 : opcode_need_relink(op_code opcode)
    2666             : {
    2667           0 :   switch(opcode)
    2668             :   {
    2669           0 :   case OCpushlong:
    2670             :   case OCpushgen:
    2671             :   case OCpushgnil:
    2672             :   case OCpushreal:
    2673             :   case OCpushstoi:
    2674             :   case OCpushlex:
    2675             :   case OCstorelex:
    2676             :   case OCstoreptr:
    2677             :   case OCsimpleptrlex:
    2678             :   case OCnewptrlex:
    2679             :   case OCpushptr:
    2680             :   case OCstackgen:
    2681             :   case OCendptr:
    2682             :   case OCprecreal:
    2683             :   case OCbitprecreal:
    2684             :   case OCprecdl:
    2685             :   case OCstoi:
    2686             :   case OCutoi:
    2687             :   case OCitos:
    2688             :   case OCitou:
    2689             :   case OCtostr:
    2690             :   case OCvarn:
    2691             :   case OCcopy:
    2692             :   case OCcopyifclone:
    2693             :   case OCcompo1:
    2694             :   case OCcompo1ptr:
    2695             :   case OCcompo2:
    2696             :   case OCcompo2ptr:
    2697             :   case OCcompoC:
    2698             :   case OCcompoCptr:
    2699             :   case OCcompoL:
    2700             :   case OCcompoLptr:
    2701             :   case OCcheckargs:
    2702             :   case OCcheckargs0:
    2703             :   case OCcheckuserargs:
    2704             :   case OCpackargs:
    2705             :   case OCgetargs:
    2706             :   case OCdefaultarg:
    2707             :   case OCdefaultgen:
    2708             :   case OCdefaultlong:
    2709             :   case OCdefaultulong:
    2710             :   case OCcalluser:
    2711             :   case OCvec:
    2712             :   case OCcol:
    2713             :   case OCmat:
    2714             :   case OCnewframe:
    2715             :   case OCsaveframe:
    2716             :   case OCdup:
    2717             :   case OCpop:
    2718             :   case OCavma:
    2719             :   case OCgerepile:
    2720             :   case OCcowvarlex:
    2721             :   case OCsetref:
    2722             :   case OClock:
    2723           0 :     break;
    2724           0 :   case OCpushvar:
    2725             :   case OCpushdyn:
    2726             :   case OCstoredyn:
    2727             :   case OCsimpleptrdyn:
    2728             :   case OCnewptrdyn:
    2729             :   case OClocalvar:
    2730             :   case OClocalvar0:
    2731             :   case OCexportvar:
    2732             :   case OCunexportvar:
    2733             :   case OCcallgen:
    2734             :   case OCcallgen2:
    2735             :   case OCcalllong:
    2736             :   case OCcallint:
    2737             :   case OCcallvoid:
    2738             :   case OCcowvardyn:
    2739           0 :     return 1;
    2740             :   }
    2741           0 :   return 0;
    2742             : }
    2743             : 
    2744             : static void
    2745           0 : closure_relink(GEN C, hashtable *table)
    2746             : {
    2747           0 :   const char *code = closure_codestr(C);
    2748           0 :   GEN oper = closure_get_oper(C);
    2749           0 :   GEN fram = gel(closure_get_dbg(C),3);
    2750             :   long i, j;
    2751           0 :   for(i=1;i<lg(oper);i++)
    2752           0 :     if (oper[i] && opcode_need_relink((op_code)code[i]))
    2753           0 :       oper[i] = (long) hash_search(table,(void*) oper[i])->val;
    2754           0 :   for (i=1;i<lg(fram);i++)
    2755           0 :     for (j=1;j<lg(gel(fram,i));j++)
    2756           0 :       if (mael(fram,i,j))
    2757           0 :         mael(fram,i,j) = (long) hash_search(table,(void*) mael(fram,i,j))->val;
    2758           0 : }
    2759             : 
    2760             : void
    2761           0 : gen_relink(GEN x, hashtable *table)
    2762             : {
    2763           0 :   long i, lx, tx = typ(x);
    2764           0 :   switch(tx)
    2765             :   {
    2766           0 :     case t_CLOSURE:
    2767           0 :       closure_relink(x, table);
    2768           0 :       gen_relink(closure_get_data(x), table);
    2769           0 :       if (lg(x)==8) gen_relink(closure_get_frame(x), table);
    2770           0 :       break;
    2771           0 :     case t_LIST:
    2772           0 :       if (list_data(x)) gen_relink(list_data(x), table);
    2773           0 :       break;
    2774           0 :     case t_VEC: case t_COL: case t_MAT: case t_ERROR:
    2775           0 :       lx = lg(x);
    2776           0 :       for (i=lontyp[tx]; i<lx; i++) gen_relink(gel(x,i), table);
    2777             :   }
    2778           0 : }
    2779             : 
    2780             : static void
    2781           0 : closure_unlink(GEN C)
    2782             : {
    2783           0 :   const char *code = closure_codestr(C);
    2784           0 :   GEN oper = closure_get_oper(C);
    2785           0 :   GEN fram = gel(closure_get_dbg(C),3);
    2786             :   long i, j;
    2787           0 :   for(i=1;i<lg(oper);i++)
    2788           0 :     if (oper[i] && opcode_need_relink((op_code) code[i]))
    2789             :     {
    2790           0 :       long n = pari_stack_new(&s_relocs);
    2791           0 :       relocs[n] = (entree *) oper[i];
    2792             :     }
    2793           0 :   for (i=1;i<lg(fram);i++)
    2794           0 :     for (j=1;j<lg(gel(fram,i));j++)
    2795           0 :       if (mael(fram,i,j))
    2796             :       {
    2797           0 :         long n = pari_stack_new(&s_relocs);
    2798           0 :         relocs[n] = (entree *) mael(fram,i,j);
    2799             :       }
    2800           0 : }
    2801             : 
    2802             : static void
    2803          16 : gen_unlink(GEN x)
    2804             : {
    2805          16 :   long i, lx, tx = typ(x);
    2806          16 :   switch(tx)
    2807             :   {
    2808           0 :     case t_CLOSURE:
    2809           0 :       closure_unlink(x);
    2810           0 :       gen_unlink(closure_get_data(x));
    2811           0 :       if (lg(x)==8) gen_unlink(closure_get_frame(x));
    2812           0 :       break;
    2813           4 :     case t_LIST:
    2814           4 :       if (list_data(x)) gen_unlink(list_data(x));
    2815           4 :       break;
    2816           0 :     case t_VEC: case t_COL: case t_MAT: case t_ERROR:
    2817           0 :       lx = lg(x);
    2818           0 :       for (i = lontyp[tx]; i<lx; i++) gen_unlink(gel(x,i));
    2819             :   }
    2820          16 : }
    2821             : 
    2822             : GEN
    2823          12 : copybin_unlink(GEN C)
    2824             : {
    2825          12 :   long i, l , n, nold = s_relocs.n;
    2826             :   GEN v, w, V, res;
    2827          12 :   if (C)
    2828           8 :     gen_unlink(C);
    2829             :   else
    2830             :   { /* contents of all variables */
    2831           4 :     long v, maxv = pari_var_next();
    2832          44 :     for (v=0; v<maxv; v++)
    2833             :     {
    2834          40 :       entree *ep = varentries[v];
    2835          40 :       if (!ep || !ep->value) continue;
    2836           8 :       gen_unlink((GEN)ep->value);
    2837             :     }
    2838             :   }
    2839          12 :   n = s_relocs.n-nold;
    2840          12 :   v = cgetg(n+1, t_VECSMALL);
    2841          12 :   for(i=0; i<n; i++)
    2842           0 :     v[i+1] = (long) relocs[i];
    2843          12 :   s_relocs.n = nold;
    2844          12 :   w = vecsmall_uniq(v); l = lg(w);
    2845          12 :   res = cgetg(3,t_VEC);
    2846          12 :   V = cgetg(l, t_VEC);
    2847          12 :   for(i=1; i<l; i++)
    2848             :   {
    2849           0 :     entree *ep = (entree*) w[i];
    2850           0 :     gel(V,i) = strtoGENstr(ep->name);
    2851             :   }
    2852          12 :   gel(res,1) = vecsmall_copy(w);
    2853          12 :   gel(res,2) = V;
    2854          12 :   return res;
    2855             : }
    2856             : 
    2857             : /* e = t_VECSMALL of entree *ep [ addresses ],
    2858             :  * names = t_VEC of strtoGENstr(ep.names),
    2859             :  * Return hashtable : ep => is_entry(ep.name) */
    2860             : hashtable *
    2861           0 : hash_from_link(GEN e, GEN names, int use_stack)
    2862             : {
    2863           0 :   long i, l = lg(e);
    2864           0 :   hashtable *h = hash_create_ulong(l-1, use_stack);
    2865           0 :   if (lg(names) != l) pari_err_DIM("hash_from_link");
    2866           0 :   for (i = 1; i < l; i++)
    2867             :   {
    2868           0 :     char *s = GSTR(gel(names,i));
    2869           0 :     hash_insert(h, (void*)e[i], (void*)fetch_entry(s));
    2870             :   }
    2871           0 :   return h;
    2872             : }
    2873             : 
    2874             : void
    2875           0 : bincopy_relink(GEN C, GEN V)
    2876             : {
    2877           0 :   pari_sp av = avma;
    2878           0 :   hashtable *table = hash_from_link(gel(V,1),gel(V,2),1);
    2879           0 :   gen_relink(C, table);
    2880           0 :   set_avma(av);
    2881           0 : }

Generated by: LCOV version 1.13