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.18.0 lcov report (development 29712-7c8a932571) Lines: 1298 1884 68.9 %
Date: 2024-11-15 09:08:45 Functions: 116 154 75.3 %
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   145762380 : loop_break(void)
      31             : {
      32   145762380 :   switch(br_status)
      33             :   {
      34          21 :     case br_MULTINEXT :
      35          21 :       if (! --br_count) br_status = br_NEXT;
      36          21 :       return 1;
      37       70302 :     case br_BREAK : if (! --br_count) br_status = br_NONE; /* fall through */
      38       78930 :     case br_RETURN: return 1;
      39       25125 :     case br_NEXT: br_status = br_NONE; /* fall through */
      40             :   }
      41   145683429 :   return 0;
      42             : }
      43             : 
      44             : static void
      45       91086 : reset_break(void)
      46             : {
      47       91086 :   br_status = br_NONE;
      48       91086 :   if (br_res) { gunclone_deep(br_res); br_res = NULL; }
      49       91086 : }
      50             : 
      51             : GEN
      52       40897 : return0(GEN x)
      53             : {
      54       40897 :   GEN y = br_res;
      55       40897 :   br_res = (x && x != gnil)? gcloneref(x): NULL;
      56       40897 :   guncloneNULL_deep(y);
      57       40897 :   br_status = br_RETURN; return NULL;
      58             : }
      59             : 
      60             : GEN
      61       25853 : next0(long n)
      62             : {
      63       25853 :   if (n < 1) pari_err_DOMAIN("next", "n", "<", gen_1, stoi(n));
      64       25846 :   if (n == 1) br_status = br_NEXT;
      65             :   else
      66             :   {
      67          14 :     br_count = n-1;
      68          14 :     br_status = br_MULTINEXT;
      69             :   }
      70       25846 :   return NULL;
      71             : }
      72             : 
      73             : GEN
      74       70358 : break0(long n)
      75             : {
      76       70358 :   if (n < 1) pari_err_DOMAIN("break", "n", "<", gen_1, stoi(n));
      77       70351 :   br_count = n;
      78       70351 :   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       18565 : new_val_cell(entree *ep, GEN x, char flag)
     107             : {
     108       18565 :   var_cell *v = (var_cell*) pari_malloc(sizeof(var_cell));
     109       18565 :   v->value  = (GEN)ep->value;
     110       18565 :   v->prev   = (var_cell*) ep->pvalue;
     111       18565 :   v->flag   = flag;
     112       18565 :   v->valence= ep->valence;
     113             : 
     114             :   /* beware: f(p) = Nv = 0
     115             :    *         Nv = p; f(Nv) --> this call would destroy p [ isclone ] */
     116       18565 :   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       18565 :   ep->pvalue= (char*)v;
     120       18565 :   ep->valence=EpVAR;
     121       18565 : }
     122             : 
     123             : /* kill ep->value and replace by preceding one, poped from value stack */
     124             : static void
     125       18124 : pop_val(entree *ep)
     126             : {
     127       18124 :   var_cell *v = (var_cell*) ep->pvalue;
     128       18124 :   if (v != INITIAL)
     129             :   {
     130       18124 :     GEN old_val = (GEN) ep->value; /* protect against SIGINT */
     131       18124 :     ep->value  = v->value;
     132       18124 :     if (v->flag == COPY_VAL) gunclone_deep(old_val);
     133       18124 :     ep->pvalue = (char*) v->prev;
     134       18124 :     ep->valence=v->valence;
     135       18124 :     pari_free((void*)v);
     136             :   }
     137       18124 : }
     138             : 
     139             : void
     140       35118 : freeep(entree *ep)
     141             : {
     142       35118 :   if (EpSTATIC(ep)) return; /* gp function loaded at init time */
     143       35118 :   if (ep->help) {pari_free((void*)ep->help); ep->help=NULL;}
     144       35118 :   if (ep->code) {pari_free((void*)ep->code); ep->code=NULL;}
     145       35118 :   switch(EpVALENCE(ep))
     146             :   {
     147       23289 :     case EpVAR:
     148       41357 :       while (ep->pvalue!=INITIAL) pop_val(ep);
     149       23289 :       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   = COPY_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      391407 : pop_val_if_newer(entree *ep, long loc)
     177             : {
     178      391407 :   var_cell *v = (var_cell*) ep->pvalue;
     179             : 
     180      391407 :   if (v == INITIAL) return 0;
     181      357980 :   if (v->flag == COPY_VAL && !pop_entree_block(ep, loc)) return 0;
     182         455 :   ep->value = v->value;
     183         455 :   ep->pvalue= (char*) v->prev;
     184         455 :   ep->valence=v->valence;
     185         455 :   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    29488333 : changevalue(entree *ep, GEN x)
     192             : {
     193    29488333 :   var_cell *v = (var_cell*) ep->pvalue;
     194    29488333 :   if (v == INITIAL) new_val_cell(ep, x, COPY_VAL);
     195             :   else
     196             :   {
     197    29469810 :     GEN old_val = (GEN) ep->value; /* beware: gunclone_deep may destroy old x */
     198    29469810 :     ep->value = (void *) gclone(x);
     199    29469810 :     if (v->flag == COPY_VAL) gunclone_deep(old_val); else v->flag = COPY_VAL;
     200             :   }
     201    29488333 : }
     202             : 
     203             : INLINE GEN
     204      745360 : copyvalue(entree *ep)
     205             : {
     206      745360 :   var_cell *v = (var_cell*) ep->pvalue;
     207      745360 :   if (v && v->flag != COPY_VAL)
     208             :   {
     209           0 :     ep->value = (void*) gclone((GEN)ep->value);
     210           0 :     v->flag = COPY_VAL;
     211             :   }
     212      745360 :   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   123276585 : checkvalue(entree *ep, enum chk_VALUE flag)
     222             : {
     223   123276585 :   if (mt_is_thread())
     224          27 :     pari_err(e_MISC,"mt: attempt to change exported variable '%s'",ep->name);
     225   123276558 :   if (ep->valence==EpNEW)
     226       22799 :     switch(flag)
     227             :     {
     228        4543 :       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        4543 :         pari_var_create(ep);
     233        4543 :         ep->valence = EpVAR;
     234        4543 :         ep->value = initial_value(ep);
     235        4543 :         break;
     236       18256 :       case chk_NOCREATE:
     237       18256 :         break;
     238             :     }
     239   123253759 :   else if (ep->valence!=EpVAR)
     240           0 :     pari_err(e_MISC, "attempt to change built-in %s", ep->name);
     241   123276558 : }
     242             : 
     243             : INLINE GEN
     244    23308327 : checkvalueptr(entree *ep)
     245             : {
     246    23308327 :   checkvalue(ep, chk_NOCREATE);
     247    23308327 :   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   106145174 : check_array_index(long c, long l)
     270             : {
     271   106145174 :   if (c < 1) pari_err_COMPONENT("", "<", gen_1, stoi(c));
     272   106145167 :   if (c >= l) pari_err_COMPONENT("", ">", stoi(l-1), stoi(c));
     273   106145125 : }
     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     9701405 : change_compo(matcomp *c, GEN res)
     332             : {
     333     9701405 :   GEN p = c->parent, *pt = c->ptcell, po;
     334             :   long i, t;
     335             : 
     336     9701405 :   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     9701370 :   t = typ(res);
     343     9701370 :   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     9496382 :   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     9496361 :   po = *pt; /* Protect against SIGINT */
     362     9496361 :   *pt = gclone(res);
     363     9496361 :   gunclone_deep(po);
     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   161835172 : changelex(long vn, GEN x)
     396             : {
     397   161835172 :   struct var_lex *v=var+s_var.n+vn;
     398   161835172 :   GEN old_val = v->value;
     399   161835172 :   v->value = gclone(x);
     400   161835172 :   if (v->flag == COPY_VAL) gunclone_deep(old_val); else v->flag = COPY_VAL;
     401   161835172 : }
     402             : 
     403             : INLINE GEN
     404     9790697 : copylex(long vn)
     405             : {
     406     9790697 :   struct var_lex *v = var+s_var.n+vn;
     407     9790697 :   if (v->flag!=COPY_VAL && v->flag!=REF_VAL)
     408             :   {
     409       52612 :     v->value = gclone(v->value);
     410       52612 :     v->flag  = COPY_VAL;
     411             :   }
     412     9790697 :   return v->value;
     413             : }
     414             : 
     415             : INLINE void
     416         504 : setreflex(long vn)
     417             : {
     418         504 :   struct var_lex *v = var+s_var.n+vn;
     419         504 :   v->flag  = REF_VAL;
     420         504 : }
     421             : 
     422             : INLINE void
     423    63471643 : pushlex(long vn, GEN x)
     424             : {
     425    63471643 :   struct var_lex *v=var+s_var.n+vn;
     426    63471643 :   v->flag  = PUSH_VAL;
     427    63471643 :   v->value = x;
     428    63471643 : }
     429             : 
     430             : INLINE void
     431   180580339 : freelex(void)
     432             : {
     433   180580339 :   struct var_lex *v=var+s_var.n-1;
     434   180580339 :   s_var.n--;
     435   180580339 :   if (v->flag == COPY_VAL) gunclone_deep(v->value);
     436   180580339 : }
     437             : 
     438             : INLINE void
     439   311893056 : restore_vars(long nbmvar, long nblvar, long nblock)
     440             : {
     441             :   long j;
     442   486710957 :   for(j=1; j<=nbmvar; j++) freelex();
     443   311893159 :   for(j=1; j<=nblvar; j++) { s_lvars.n--; pop_val(lvars[s_lvars.n]); }
     444   311893572 :   for(j=1; j<=nblock; j++) { s_locks.n--; gunclone_deep(locks[s_locks.n]); }
     445   311893103 : }
     446             : 
     447             : INLINE void
     448     5644563 : restore_trace(long nbtrace)
     449             : {
     450             :   long j;
     451    11301885 :   for(j=1; j<=nbtrace; j++)
     452             :   {
     453     5657322 :     GEN C = trace[s_trace.n-j].closure;
     454     5657322 :     clone_unlock(C);
     455             :   }
     456     5644563 :   s_trace.n -= nbtrace;
     457     5644563 : }
     458             : 
     459             : INLINE long
     460   317393989 : trace_push(long pc, GEN C)
     461             : {
     462             :   long tr;
     463   317393989 :   BLOCK_SIGINT_START
     464   318241224 :   tr = pari_stack_new(&s_trace);
     465   317971606 :   trace[tr].pc = pc;
     466   317971606 :   clone_lock(C);
     467   317577871 :   trace[tr].closure = C;
     468   317577871 :   BLOCK_SIGINT_END
     469   318267389 :   return tr;
     470             : }
     471             : 
     472             : void
     473     5762947 : push_lex(GEN a, GEN C)
     474             : {
     475     5762947 :   long vn=pari_stack_new(&s_var);
     476     5762947 :   struct var_lex *v=var+vn;
     477     5762947 :   v->flag  = PUSH_VAL;
     478     5762947 :   v->value = a;
     479     5762947 :   if (C) (void) trace_push(-1, C);
     480     5762948 : }
     481             : 
     482             : GEN
     483    98812763 : get_lex(long vn)
     484             : {
     485    98812763 :   struct var_lex *v=var+s_var.n+vn;
     486    98812763 :   return v->value;
     487             : }
     488             : 
     489             : void
     490    83224189 : set_lex(long vn, GEN x)
     491             : {
     492    83224189 :   struct var_lex *v=var+s_var.n+vn;
     493    83224189 :   if (v->flag == COPY_VAL) { gunclone_deep(v->value); v->flag = PUSH_VAL; }
     494    83224189 :   v->value = x;
     495    83224189 : }
     496             : 
     497             : void
     498     5595581 : pop_lex(long n)
     499             : {
     500             :   long j;
     501    11358223 :   for(j=1; j<=n; j++)
     502     5762642 :     freelex();
     503     5595581 :   restore_trace(1);
     504     5595581 : }
     505             : 
     506             : static THREAD pari_stack s_relocs;
     507             : static THREAD entree **relocs;
     508             : 
     509             : void
     510      326183 : pari_init_evaluator(void)
     511             : {
     512      326183 :   sp=0;
     513      326183 :   pari_stack_init(&s_st,sizeof(*st),(void**)&st);
     514      326174 :   pari_stack_alloc(&s_st,32);
     515      326278 :   s_st.n=s_st.alloc;
     516      326278 :   rp=0;
     517      326278 :   pari_stack_init(&s_ptrs,sizeof(*ptrs),(void**)&ptrs);
     518      326260 :   pari_stack_alloc(&s_ptrs,16);
     519      326275 :   s_ptrs.n=s_ptrs.alloc;
     520      326275 :   pari_stack_init(&s_var,sizeof(*var),(void**)&var);
     521      326254 :   pari_stack_init(&s_lvars,sizeof(*lvars),(void**)&lvars);
     522      326193 :   pari_stack_init(&s_locks,sizeof(*locks),(void**)&locks);
     523      326163 :   pari_stack_init(&s_trace,sizeof(*trace),(void**)&trace);
     524      326141 :   br_res = NULL;
     525      326141 :   pari_stack_init(&s_relocs,sizeof(*relocs),(void**)&relocs);
     526      326110 :   pari_stack_init(&s_prec,sizeof(*precs),(void**)&precs);
     527      326103 : }
     528             : void
     529      322110 : pari_close_evaluator(void)
     530             : {
     531      322110 :   pari_stack_delete(&s_st);
     532      324872 :   pari_stack_delete(&s_ptrs);
     533      325137 :   pari_stack_delete(&s_var);
     534      325210 :   pari_stack_delete(&s_lvars);
     535      324424 :   pari_stack_delete(&s_trace);
     536      325264 :   pari_stack_delete(&s_relocs);
     537      324533 :   pari_stack_delete(&s_prec);
     538      325173 : }
     539             : 
     540             : static gp_pointer *
     541    58684361 : new_ptr(void)
     542             : {
     543    58684361 :   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    58684361 :   return &ptrs[rp++];
     556             : }
     557             : 
     558             : void
     559      434395 : push_localbitprec(long p)
     560             : {
     561      434395 :   long n = pari_stack_new(&s_prec);
     562      434566 :   precs[n] = p;
     563      434566 : }
     564             : void
     565       99025 : push_localprec(long p) { push_localbitprec(p); }
     566             : 
     567             : void
     568       98976 : pop_localprec(void) { s_prec.n--; }
     569             : 
     570             : long
     571    22251333 : get_localbitprec(void) { return s_prec.n? precs[s_prec.n-1]: precreal; }
     572             : 
     573             : long
     574    21897950 : get_localprec(void) { return nbits2prec(get_localbitprec()); }
     575             : 
     576             : static void
     577       11162 : checkprec(const char *f, long p, long M)
     578             : {
     579       11162 :   if (p < 1) pari_err_DOMAIN(f, "p", "<", gen_1, stoi(p));
     580       11148 :   if (p > M) pari_err_DOMAIN(f, "p", ">", utoipos(M), utoi(p));
     581       11136 : }
     582             : static long
     583       11255 : _prec(GEN p, const char *f)
     584             : {
     585       11255 :   pari_sp av = avma;
     586       11255 :   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        7847 : localprec(GEN pp)
     593             : {
     594        7847 :   long p = _prec(pp, "localprec");
     595        7839 :   checkprec("localprec", p, prec2ndec(LGBITS));
     596        7826 :   p = ndec2nbits(p); push_localbitprec(p);
     597        7826 : }
     598             : void
     599        3324 : localbitprec(GEN pp)
     600             : {
     601        3324 :   long p = _prec(pp, "localbitprec");
     602        3323 :   checkprec("localbitprec", p, (long)LGBITS);
     603        3310 :   push_localbitprec(p);
     604        3310 : }
     605             : long
     606          14 : getlocalprec(long prec) { return prec2ndec(prec); }
     607             : long
     608        3346 : getlocalbitprec(long bit) { return bit; }
     609             : 
     610             : static GEN
     611        1246 : _precision0(GEN x)
     612             : {
     613        1246 :   long a = gprecision(x);
     614        1246 :   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         676 : _bitprecision0(GEN x)
     621             : {
     622         676 :   long a = gprecision(x);
     623         676 :   return a? utoi(a): mkoo();
     624             : }
     625             : GEN
     626        1225 : bitprecision0(GEN x, long n)
     627             : {
     628        1225 :   if (n < 0)
     629           0 :     pari_err_DOMAIN("bitprecision", "bitprecision", "<", gen_0, stoi(n));
     630        1225 :   if (n) {
     631        1225 :     pari_sp av = avma;
     632        1225 :     GEN y = gprec_w(x, nbits2prec(n));
     633        1225 :     return gerepilecopy(av, y);
     634             :   }
     635           0 :   return _bitprecision0(x);
     636             : }
     637             : GEN
     638        1288 : precision00(GEN x, GEN n)
     639             : {
     640        1288 :   if (!n) return _precision0(x);
     641          42 :   return precision0(x, _prec(n, "precision"));
     642             : }
     643             : GEN
     644         718 : bitprecision00(GEN x, GEN n)
     645             : {
     646         718 :   if (!n) return _bitprecision0(x);
     647          42 :   return bitprecision0(x, _prec(n, "bitprecision"));
     648             : }
     649             : 
     650             : INLINE GEN
     651    40973130 : copyupto(GEN z, GEN t)
     652             : {
     653    40973130 :   if (is_universal_constant(z) || (z>(GEN)pari_mainstack->bot && z<=t))
     654    39541090 :     return z;
     655             :   else
     656     1431869 :     return gcopy(z);
     657             : }
     658             : 
     659             : static void closure_eval(GEN C);
     660             : 
     661             : INLINE GEN
     662       41666 : get_and_reset_break(void)
     663             : {
     664       41666 :   GEN z = br_res? gcopy(br_res): gnil;
     665       41666 :   reset_break(); return z;
     666             : }
     667             : 
     668             : INLINE GEN
     669    49566205 : closure_return(GEN C)
     670             : {
     671    49566205 :   pari_sp av = avma;
     672    49566205 :   closure_eval(C);
     673    49539562 :   if (br_status) { set_avma(av); return get_and_reset_break(); }
     674    49497945 :   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     1139072 : closure_varn(GEN x)
     687             : {
     688     1139072 :   if (!x) return -1;
     689     1138470 :   if (!gequalX(x)) err_var(x);
     690     1138470 :   return varn(x);
     691             : }
     692             : 
     693             : INLINE void
     694    92909506 : closure_castgen(GEN z, long mode)
     695             : {
     696    92909506 :   switch (mode)
     697             :   {
     698    92908638 :   case Ggen:
     699    92908638 :     gel(st,sp++)=z;
     700    92908638 :     break;
     701         868 :   case Gsmall:
     702         868 :     st[sp++]=gtos(z);
     703         868 :     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    92909506 : }
     716             : 
     717             : INLINE void
     718        5873 : closure_castlong(long z, long mode)
     719             : {
     720        5873 :   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        5866 :   case Ggen:
     731        5866 :     gel(st,sp++)=stoi(z);
     732        5866 :     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        5873 : }
     741             : 
     742             : const char *
     743       13277 : closure_func_err(void)
     744             : {
     745       13277 :   long fun=s_trace.n-1, pc;
     746             :   const char *code;
     747             :   GEN C, oper;
     748       13277 :   if (fun < 0 || trace[fun].pc < 0) return NULL;
     749       12581 :   pc = trace[fun].pc; C  = trace[fun].closure;
     750       12581 :   code = closure_codestr(C); oper = closure_get_oper(C);
     751       12581 :   if (code[pc]==OCcallgen || code[pc]==OCcallgen2 ||
     752        3528 :       code[pc]==OCcallint || code[pc]==OCcalllong || code[pc]==OCcallvoid)
     753        9627 :     return ((entree*)oper[pc])->name;
     754        2954 :   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         245 : get_next_label(const char *s, int member, char **next_fun)
     762             : {
     763         245 :   const char *v, *t = s+1;
     764             :   char *u, *next_label;
     765             : 
     766         245 :   if (!is_keyword_char(*s)) return NULL;
     767        1036 :   while (is_keyword_char(*t)) t++;
     768             :   /* e.g. (x->1/x)(0) instead of (x)->1/x */
     769         224 :   if (t[0] == '-' && t[1] == '>') return NULL;
     770         217 :   next_label = (char*)pari_malloc(t - s + 32);
     771         217 :   sprintf(next_label, "in %sfunction ", member? "member ": "");
     772         217 :   u = *next_fun = next_label + strlen(next_label);
     773         217 :   v = s;
     774        1246 :   while (v < t) *u++ = *v++;
     775         217 :   *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       12580 : closure_err(long level)
     791             : {
     792             :   GEN base;
     793       12580 :   const long lastfun = s_trace.n - 1 - level;
     794             :   char *next_label, *next_fun;
     795       12580 :   long i = maxss(0, lastfun - 19);
     796       12580 :   if (lastfun < 0) return; /*e.g. when called by gp_main_loop's simplify */
     797       12559 :   if (i > 0) while (lg(trace[i].closure)==6) i--;
     798       12559 :   base = closure_get_text(trace[i].closure); /* gcc -Wall*/
     799       12559 :   next_label = pari_strdup(i == 0? "at top-level": "[...] at");
     800       12559 :   next_fun = next_label;
     801       13237 :   for (; i <= lastfun; i++)
     802             :   {
     803       13237 :     GEN C = trace[i].closure;
     804       13237 :     if (lg(C) >= 7) base=closure_get_text(C);
     805       13237 :     if ((i==lastfun || lg(trace[i+1].closure)>=7))
     806             :     {
     807       12804 :       GEN dbg = gel(closure_get_dbg(C),1);
     808             :       /* After a SIGINT, pc can be slightly off: ensure 0 <= pc < lg() */
     809       12804 :       long pc = minss(lg(dbg)-1, trace[i].pc>=0 ? trace[i].pc: 1);
     810       12804 :       long offset = pc? dbg[pc]: 0;
     811             :       int member;
     812             :       const char *s, *sbase;
     813       12804 :       if (typ(base)!=t_VEC) sbase = GSTR(base);
     814         189 :       else if (offset>=0)   sbase = GSTR(gel(base,2));
     815          21 :       else { sbase = GSTR(gel(base,1)); offset += strlen(sbase); }
     816       12804 :       s = sbase + offset;
     817       12804 :       member = offset>0 && (s[-1] == '.');
     818             :       /* avoid "in function foo: foo" */
     819       12804 :       if (!next_fun || strcmp(next_fun, s)) {
     820       12797 :         print_errcontext(pariErr, next_label, s, sbase);
     821       12797 :         out_putc(pariErr, '\n');
     822             :       }
     823       12804 :       pari_free(next_label);
     824       12804 :       if (i == lastfun) break;
     825             : 
     826         245 :       next_label = get_next_label(s, member, &next_fun);
     827         245 :       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  2971448335 : st_alloc(long n)
     859             : {
     860  2971448335 :   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  2971448335 : }
     867             : 
     868             : INLINE void
     869     9906309 : ptr_proplock(gp_pointer *g, GEN C)
     870             : {
     871     9906309 :   g->x = C;
     872     9906309 :   if (isclone(g->x))
     873             :   {
     874      445046 :     clone_unlock_deep(g->ox);
     875      445046 :     g->ox = g->x;
     876      445046 :     ++bl_refc(g->ox);
     877             :   }
     878     9906309 : }
     879             : 
     880             : static void
     881   311874155 : closure_eval(GEN C)
     882             : {
     883   311874155 :   const char *code=closure_codestr(C);
     884   311855150 :   GEN oper=closure_get_oper(C);
     885   311837152 :   GEN data=closure_get_data(C);
     886   311828764 :   long loper=lg(oper);
     887   311828764 :   long saved_sp=sp-closure_arity(C);
     888   311824156 :   long saved_rp=rp, saved_prec=s_prec.n;
     889   311824156 :   long j, nbmvar=0, nblvar=0, nblock=0;
     890             :   long pc, t;
     891             : #ifdef STACK_CHECK
     892             :   GEN stackelt;
     893   311824156 :   if (PARI_stack_limit && (void*) &stackelt <= PARI_stack_limit)
     894           0 :     pari_err(e_MISC, "deep recursion");
     895             : #endif
     896   311824156 :   t = trace_push(0, C);
     897   312515683 :   if (lg(C)==8)
     898             :   {
     899    12890875 :     GEN z=closure_get_frame(C);
     900    12890579 :     long l=lg(z)-1;
     901    12890579 :     pari_stack_alloc(&s_var,l);
     902    12803060 :     s_var.n+=l;
     903    12803060 :     nbmvar+=l;
     904    44421998 :     for(j=1;j<=l;j++)
     905             :     {
     906    31618938 :       var[s_var.n-j].flag=PUSH_VAL;
     907    31618938 :       var[s_var.n-j].value=gel(z,j);
     908             :     }
     909             :   }
     910             : 
     911  3211992893 :   for(pc=1;pc<loper;pc++)
     912             :   {
     913  2900137192 :     op_code opcode=(op_code) code[pc];
     914  2900137192 :     long operand=oper[pc];
     915  2900137192 :     if (sp<0) pari_err_BUG("closure_eval, stack underflow");
     916  2900137192 :     st_alloc(16);
     917  2900007578 :     trace[t].pc = pc;
     918             :     CHECK_CTRLC
     919  2900007578 :     switch(opcode)
     920             :     {
     921   197698765 :     case OCpushlong:
     922   197698765 :       st[sp++]=operand;
     923   197698765 :       break;
     924       99333 :     case OCpushgnil:
     925       99333 :       gel(st,sp++)=gnil;
     926       99333 :       break;
     927   161717815 :     case OCpushgen:
     928   161717815 :       gel(st,sp++)=gel(data,operand);
     929   161717815 :       break;
     930       85947 :     case OCpushreal:
     931       85947 :       gel(st,sp++)=strtor(GSTR(data[operand]),get_localprec());
     932       85947 :       break;
     933   248622854 :     case OCpushstoi:
     934   248622854 :       gel(st,sp++)=stoi(operand);
     935   248622922 :       break;
     936       25669 :     case OCpushvar:
     937             :       {
     938       25669 :         entree *ep = (entree *)operand;
     939       25669 :         gel(st,sp++)=pol_x(pari_var_create(ep));
     940       25669 :         break;
     941             :       }
     942    93044261 :     case OCpushdyn:
     943             :       {
     944    93044261 :         entree *ep = (entree *)operand;
     945    93044261 :         if (!mt_is_thread())
     946             :         {
     947    93042761 :           checkvalue(ep, chk_CREATE);
     948    93042761 :           gel(st,sp++)=(GEN)ep->value;
     949             :         } else
     950             :         {
     951        1500 :           GEN val = export_get(ep->name);
     952        1500 :           if (!val)
     953           0 :             pari_err(e_MISC,"mt: please use export(%s)", ep->name);
     954        1500 :           gel(st,sp++)=val;
     955             :         }
     956    93044261 :         break;
     957             :       }
     958   627120544 :     case OCpushlex:
     959   627120544 :       gel(st,sp++)=var[s_var.n+operand].value;
     960   627120544 :       break;
     961    23308327 :     case OCsimpleptrdyn:
     962             :       {
     963    23308327 :         gp_pointer *g = new_ptr();
     964    23308327 :         g->vn=0;
     965    23308327 :         g->ep = (entree*) operand;
     966    23308327 :         g->x = checkvalueptr(g->ep);
     967    23308327 :         g->ox = g->x; clone_lock(g->ox);
     968    23308327 :         g->sp = sp;
     969    23308327 :         gel(st,sp++) = (GEN)&(g->x);
     970    23308327 :         break;
     971             :       }
     972    25674580 :     case OCsimpleptrlex:
     973             :       {
     974    25674580 :         gp_pointer *g = new_ptr();
     975    25674580 :         g->vn=operand;
     976    25674580 :         g->ep=(entree *)0x1L;
     977    25674580 :         g->x = (GEN) var[s_var.n+operand].value;
     978    25674580 :         g->ox = g->x; clone_lock(g->ox);
     979    25674580 :         g->sp = sp;
     980    25674580 :         gel(st,sp++) = (GEN)&(g->x);
     981    25674580 :         break;
     982             :       }
     983        5019 :     case OCnewptrdyn:
     984             :       {
     985        5019 :         entree *ep = (entree *)operand;
     986        5019 :         gp_pointer *g = new_ptr();
     987             :         matcomp *C;
     988        5019 :         checkvalue(ep, chk_ERROR);
     989        5019 :         g->sp = -1;
     990        5019 :         g->x = copyvalue(ep);
     991        5019 :         g->ox = g->x; clone_lock(g->ox);
     992        5019 :         g->vn=0;
     993        5019 :         g->ep=NULL;
     994        5019 :         C=&g->c;
     995        5019 :         C->full_col = C->full_row = 0;
     996        5019 :         C->parent   = (GEN)    g->x;
     997        5019 :         C->ptcell   = (GEN *) &g->x;
     998        5019 :         break;
     999             :       }
    1000     9696435 :     case OCnewptrlex:
    1001             :       {
    1002     9696435 :         gp_pointer *g = new_ptr();
    1003             :         matcomp *C;
    1004     9696435 :         g->sp = -1;
    1005     9696435 :         g->x = copylex(operand);
    1006     9696435 :         g->ox = g->x; clone_lock(g->ox);
    1007     9696435 :         g->vn=0;
    1008     9696435 :         g->ep=NULL;
    1009     9696435 :         C=&g->c;
    1010     9696435 :         C->full_col = C->full_row = 0;
    1011     9696435 :         C->parent   = (GEN)     g->x;
    1012     9696435 :         C->ptcell   = (GEN *) &(g->x);
    1013     9696435 :         break;
    1014             :       }
    1015      559720 :     case OCpushptr:
    1016             :       {
    1017      559720 :         gp_pointer *g = &ptrs[rp-1];
    1018      559720 :         g->sp = sp;
    1019      559720 :         gel(st,sp++) = (GEN)&(g->x);
    1020             :       }
    1021      559720 :       break;
    1022    49542571 :     case OCendptr:
    1023    99085142 :       for(j=0;j<operand;j++)
    1024             :       {
    1025    49542571 :         gp_pointer *g = &ptrs[--rp];
    1026    49542571 :         if (g->ep)
    1027             :         {
    1028    48982851 :           if (g->vn)
    1029    25674580 :             changelex(g->vn, g->x);
    1030             :           else
    1031    23308271 :             changevalue(g->ep, g->x);
    1032             :         }
    1033      559720 :         else change_compo(&(g->c), g->x);
    1034    49542571 :         clone_unlock_deep(g->ox);
    1035             :       }
    1036    49542571 :       break;
    1037     6180063 :     case OCstoredyn:
    1038             :       {
    1039     6180063 :         entree *ep = (entree *)operand;
    1040     6180063 :         checkvalue(ep, chk_NOCREATE);
    1041     6180054 :         changevalue(ep, gel(st,--sp));
    1042     6180054 :         break;
    1043             :       }
    1044   136160592 :     case OCstorelex:
    1045   136160592 :       changelex(operand,gel(st,--sp));
    1046   136160592 :       break;
    1047     9141685 :     case OCstoreptr:
    1048             :       {
    1049     9141685 :         gp_pointer *g = &ptrs[--rp];
    1050     9141685 :         change_compo(&(g->c), gel(st,--sp));
    1051     9141608 :         clone_unlock_deep(g->ox);
    1052     9141608 :         break;
    1053             :       }
    1054    25728639 :     case OCstackgen:
    1055             :       {
    1056    25728639 :         GEN z = gerepileupto(st[sp-2],gel(st,sp-1));
    1057    25728640 :         gmael(st,sp-3,operand) = copyupto(z,gel(st,sp-2));
    1058    25728646 :         st[sp-2] = avma;
    1059    25728646 :         sp--;
    1060    25728646 :         break;
    1061             :       }
    1062    21811992 :     case OCprecreal:
    1063    21811992 :       st[sp++]=get_localprec();
    1064    21811991 :       break;
    1065       28875 :     case OCbitprecreal:
    1066       28875 :       st[sp++]=get_localbitprec();
    1067       28875 :       break;
    1068         952 :     case OCprecdl:
    1069         952 :       st[sp++]=precdl;
    1070         952 :       break;
    1071        2947 :     case OCavma:
    1072        2947 :       st[sp++]=avma;
    1073        2947 :       break;
    1074      740341 :     case OCcowvardyn:
    1075             :       {
    1076      740341 :         entree *ep = (entree *)operand;
    1077      740341 :         checkvalue(ep, chk_ERROR);
    1078      740341 :         (void)copyvalue(ep);
    1079      740341 :         break;
    1080             :       }
    1081       93205 :     case OCcowvarlex:
    1082       93205 :       (void)copylex(operand);
    1083       93205 :       break;
    1084         504 :     case OCsetref:
    1085         504 :       setreflex(operand);
    1086         504 :       break;
    1087         483 :     case OClock:
    1088             :     {
    1089         483 :       GEN v = gel(st,sp-1);
    1090         483 :       if (isclone(v))
    1091             :       {
    1092         469 :         long n = pari_stack_new(&s_locks);
    1093         469 :         locks[n] = v;
    1094         469 :         nblock++;
    1095         469 :         ++bl_refc(v);
    1096             :       }
    1097         483 :       break;
    1098             :     }
    1099           0 :     case OCevalmnem:
    1100             :     {
    1101           0 :       entree *ep = (entree*) operand;
    1102           0 :       const char *flags = ep->code;
    1103           0 :       flags = strchr(flags, '\n'); /* Skip to the following '\n' */
    1104           0 :       st[sp-1] = eval_mnemonic(gel(st,sp-1), flags+1);
    1105           0 :       break;
    1106             :     }
    1107    20008111 :     case OCstoi:
    1108    20008111 :       gel(st,sp-1)=stoi(st[sp-1]);
    1109    20008443 :       break;
    1110           0 :     case OCutoi:
    1111           0 :       gel(st,sp-1)=utoi(st[sp-1]);
    1112           0 :       break;
    1113    72911337 :     case OCitos:
    1114    72911337 :       st[sp+operand]=gtos(gel(st,sp+operand));
    1115    72911305 :       break;
    1116       96695 :     case OCitou:
    1117       96695 :       st[sp+operand]=gtou(gel(st,sp+operand));
    1118       96693 :       break;
    1119        5131 :     case OCtostr:
    1120             :       {
    1121        5131 :         GEN z = gel(st,sp+operand);
    1122        5131 :         st[sp+operand] = (long) (z ? GENtostr_unquoted(z): NULL);
    1123        5131 :         break;
    1124             :       }
    1125     1139072 :     case OCvarn:
    1126     1139072 :       st[sp+operand] = closure_varn(gel(st,sp+operand));
    1127     1139072 :       break;
    1128    26234511 :     case OCcopy:
    1129    26234511 :       gel(st,sp-1) = gcopy(gel(st,sp-1));
    1130    26234518 :       break;
    1131        2947 :     case OCgerepile:
    1132             :     {
    1133             :       pari_sp av;
    1134             :       GEN x;
    1135        2947 :       sp--;
    1136        2947 :       av = st[sp-1];
    1137        2947 :       x = gel(st,sp);
    1138        2947 :       if (isonstack(x))
    1139             :       {
    1140        2947 :         pari_sp av2 = (pari_sp)(x + lg(x));
    1141        2947 :         if ((long) (av - av2) > 1000000L)
    1142             :         {
    1143           7 :           if (DEBUGMEM>=2)
    1144           0 :             pari_warn(warnmem,"eval: recovering %ld bytes", av - av2);
    1145           7 :           x = gerepileupto(av, x);
    1146             :         }
    1147           0 :       } else set_avma(av);
    1148        2947 :       gel(st,sp-1) = x;
    1149        2947 :       break;
    1150             :     }
    1151           0 :     case OCcopyifclone:
    1152           0 :       if (isclone(gel(st,sp-1)))
    1153           0 :         gel(st,sp-1) = gcopy(gel(st,sp-1));
    1154           0 :       break;
    1155    91218621 :     case OCcompo1:
    1156             :       {
    1157    91218621 :         GEN  p=gel(st,sp-2);
    1158    91218621 :         long c=st[sp-1];
    1159    91218621 :         sp-=2;
    1160    91218621 :         switch(typ(p))
    1161             :         {
    1162    91211750 :         case t_VEC: case t_COL:
    1163    91211750 :           check_array_index(c, lg(p));
    1164    91211750 :           closure_castgen(gel(p,c),operand);
    1165    91211749 :           break;
    1166         977 :         case t_LIST:
    1167             :           {
    1168             :             long lx;
    1169         977 :             if (list_typ(p)!=t_LIST_RAW)
    1170           0 :               pari_err_TYPE("_[_] OCcompo1 [not a vector]", p);
    1171         977 :             p = list_data(p); lx = p? lg(p): 1;
    1172         977 :             check_array_index(c, lx);
    1173         977 :             closure_castgen(gel(p,c),operand);
    1174         977 :             break;
    1175             :           }
    1176        5887 :         case t_VECSMALL:
    1177        5887 :           check_array_index(c,lg(p));
    1178        5873 :           closure_castlong(p[c],operand);
    1179        5874 :           break;
    1180           7 :         default:
    1181           7 :           pari_err_TYPE("_[_] OCcompo1 [not a vector]", p);
    1182           0 :           break;
    1183             :         }
    1184    91218600 :         break;
    1185             :       }
    1186     9424961 :     case OCcompo1ptr:
    1187             :       {
    1188     9424961 :         long c=st[sp-1];
    1189             :         long lx;
    1190     9424961 :         gp_pointer *g = &ptrs[rp-1];
    1191     9424961 :         matcomp *C=&g->c;
    1192     9424961 :         GEN p = g->x;
    1193     9424961 :         sp--;
    1194     9424961 :         switch(typ(p))
    1195             :         {
    1196     9424884 :         case t_VEC: case t_COL:
    1197     9424884 :           check_array_index(c, lg(p));
    1198     9424884 :           C->ptcell = (GEN *) p+c;
    1199     9424884 :           ptr_proplock(g, *(C->ptcell));
    1200     9424884 :           break;
    1201          42 :         case t_VECSMALL:
    1202          42 :           check_array_index(c, lg(p));
    1203          35 :           C->ptcell = (GEN *) p+c;
    1204          35 :           g->x = stoi(p[c]);
    1205          35 :           break;
    1206          28 :         case t_LIST:
    1207          28 :           if (list_typ(p)!=t_LIST_RAW)
    1208           0 :             pari_err_TYPE("&_[_] OCcompo1 [not a vector]", p);
    1209          28 :           p = list_data(p); lx = p? lg(p): 1;
    1210          28 :           check_array_index(c,lx);
    1211          28 :           C->ptcell = (GEN *) p+c;
    1212          28 :           ptr_proplock(g, *(C->ptcell));
    1213          28 :           break;
    1214           7 :         default:
    1215           7 :           pari_err_TYPE("&_[_] OCcompo1ptr [not a vector]", p);
    1216             :         }
    1217     9424947 :         C->parent   = p;
    1218     9424947 :         break;
    1219             :       }
    1220     1696786 :     case OCcompo2:
    1221             :       {
    1222     1696786 :         GEN  p=gel(st,sp-3);
    1223     1696786 :         long c=st[sp-2];
    1224     1696786 :         long d=st[sp-1];
    1225     1696786 :         if (typ(p)!=t_MAT) pari_err_TYPE("_[_,_] OCcompo2 [not a matrix]", p);
    1226     1696779 :         check_array_index(d, lg(p));
    1227     1696779 :         check_array_index(c, lg(gel(p,d)));
    1228     1696779 :         sp-=3;
    1229     1696779 :         closure_castgen(gcoeff(p,c,d),operand);
    1230     1696779 :         break;
    1231             :       }
    1232      126000 :     case OCcompo2ptr:
    1233             :       {
    1234      126000 :         long c=st[sp-2];
    1235      126000 :         long d=st[sp-1];
    1236      126000 :         gp_pointer *g = &ptrs[rp-1];
    1237      126000 :         matcomp *C=&g->c;
    1238      126000 :         GEN p = g->x;
    1239      126000 :         sp-=2;
    1240      126000 :         if (typ(p)!=t_MAT)
    1241           0 :           pari_err_TYPE("&_[_,_] OCcompo2ptr [not a matrix]", p);
    1242      126000 :         check_array_index(d, lg(p));
    1243      126000 :         check_array_index(c, lg(gel(p,d)));
    1244      126000 :         C->ptcell = (GEN *) gel(p,d)+c;
    1245      126000 :         C->parent   = p;
    1246      126000 :         ptr_proplock(g, *(C->ptcell));
    1247      126000 :         break;
    1248             :       }
    1249     1022635 :     case OCcompoC:
    1250             :       {
    1251     1022635 :         GEN  p=gel(st,sp-2);
    1252     1022635 :         long c=st[sp-1];
    1253     1022635 :         if (typ(p)!=t_MAT)
    1254           7 :           pari_err_TYPE("_[,_] OCcompoC [not a matrix]", p);
    1255     1022628 :         check_array_index(c, lg(p));
    1256     1022621 :         sp--;
    1257     1022621 :         gel(st,sp-1) = gel(p,c);
    1258     1022621 :         break;
    1259             :       }
    1260      355411 :     case OCcompoCptr:
    1261             :       {
    1262      355411 :         long c=st[sp-1];
    1263      355411 :         gp_pointer *g = &ptrs[rp-1];
    1264      355411 :         matcomp *C=&g->c;
    1265      355411 :         GEN p = g->x;
    1266      355411 :         sp--;
    1267      355411 :         if (typ(p)!=t_MAT)
    1268           7 :           pari_err_TYPE("&_[,_] OCcompoCptr [not a matrix]", p);
    1269      355404 :         check_array_index(c, lg(p));
    1270      355397 :         C->ptcell = (GEN *) p+c;
    1271      355397 :         C->full_col = c;
    1272      355397 :         C->parent   = p;
    1273      355397 :         ptr_proplock(g, *(C->ptcell));
    1274      355397 :         break;
    1275             :       }
    1276      273028 :     case OCcompoL:
    1277             :       {
    1278      273028 :         GEN  p=gel(st,sp-2);
    1279      273028 :         long r=st[sp-1];
    1280      273028 :         sp--;
    1281      273028 :         if (typ(p)!=t_MAT)
    1282           7 :           pari_err_TYPE("_[_,] OCcompoL [not a matrix]", p);
    1283      273021 :         check_array_index(r,lg(p) == 1? 1: lgcols(p));
    1284      273014 :         gel(st,sp-1) = row(p,r);
    1285      273014 :         break;
    1286             :       }
    1287      205002 :     case OCcompoLptr:
    1288             :       {
    1289      205002 :         long r=st[sp-1];
    1290      205002 :         gp_pointer *g = &ptrs[rp-1];
    1291      205002 :         matcomp *C=&g->c;
    1292      205002 :         GEN p = g->x, p2;
    1293      205002 :         sp--;
    1294      205002 :         if (typ(p)!=t_MAT)
    1295           7 :           pari_err_TYPE("&_[_,] OCcompoLptr [not a matrix]", p);
    1296      204995 :         check_array_index(r,lg(p) == 1? 1: lgcols(p));
    1297      204988 :         p2 = rowcopy(p,r);
    1298      204988 :         C->full_row = r; /* record row number */
    1299      204988 :         C->ptcell = &p2;
    1300      204988 :         C->parent   = p;
    1301      204988 :         g->x = p2;
    1302      204988 :         break;
    1303             :       }
    1304      102732 :     case OCdefaultarg:
    1305      102732 :       if (var[s_var.n+operand].flag==DEFAULT_VAL)
    1306             :       {
    1307        3353 :         GEN z = gel(st,sp-1);
    1308        3353 :         if (typ(z)==t_CLOSURE)
    1309             :         {
    1310        1057 :           pushlex(operand, closure_evalnobrk(z));
    1311        1057 :           copylex(operand);
    1312             :         }
    1313             :         else
    1314        2296 :           pushlex(operand, z);
    1315             :       }
    1316      102732 :       sp--;
    1317      102732 :       break;
    1318          51 :     case OClocalvar:
    1319             :       {
    1320             :         long n;
    1321          51 :         entree *ep = (entree *)operand;
    1322          51 :         checkvalue(ep, chk_NOCREATE);
    1323          42 :         n = pari_stack_new(&s_lvars);
    1324          42 :         lvars[n] = ep;
    1325          42 :         nblvar++;
    1326          42 :         pushvalue(ep,gel(st,--sp));
    1327          42 :         break;
    1328             :       }
    1329          23 :     case OClocalvar0:
    1330             :       {
    1331             :         long n;
    1332          23 :         entree *ep = (entree *)operand;
    1333          23 :         checkvalue(ep, chk_NOCREATE);
    1334          14 :         n = pari_stack_new(&s_lvars);
    1335          14 :         lvars[n] = ep;
    1336          14 :         nblvar++;
    1337          14 :         zerovalue(ep);
    1338          12 :         break;
    1339             :       }
    1340          41 :     case OCexportvar:
    1341             :       {
    1342          41 :         entree *ep = (entree *)operand;
    1343          41 :         mt_export_add(ep->name, gel(st,--sp));
    1344          41 :         break;
    1345             :       }
    1346           6 :     case OCunexportvar:
    1347             :       {
    1348           6 :         entree *ep = (entree *)operand;
    1349           6 :         mt_export_del(ep->name);
    1350           6 :         break;
    1351             :       }
    1352             : 
    1353             : #define EVAL_f(f, type, resEQ) \
    1354             :   switch (ep->arity) \
    1355             :   { \
    1356             :     case 0: resEQ ((type (*)(void))f)(); break; \
    1357             :     case 1: sp--;  resEQ ((type (*)(long))f)(st[sp]); break; \
    1358             :     case 2: sp-=2; resEQ((type (*)(long,long))f)(st[sp],st[sp+1]); break; \
    1359             :     case 3: sp-=3; resEQ((type (*)(long,long,long))f)(st[sp],st[sp+1],st[sp+2]); break; \
    1360             :     case 4: sp-=4; resEQ((type (*)(long,long,long,long))f)(st[sp],st[sp+1],st[sp+2],st[sp+3]); break; \
    1361             :     case 5: sp-=5; resEQ((type (*)(long,long,long,long,long))f)(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4]); break; \
    1362             :     case 6: sp-=6; resEQ((type (*)(long,long,long,long,long,long))f)(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5]); break; \
    1363             :     case 7: sp-=7; resEQ((type (*)(long,long,long,long,long,long,long))f)(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5],st[sp+6]); break; \
    1364             :     case 8: sp-=8; resEQ((type (*)(long,long,long,long,long,long,long,long))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; \
    1365             :     case 9: sp-=9; resEQ((type (*)(long,long,long,long,long,long,long,long,long))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; \
    1366             :     case 10: sp-=10; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long))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; \
    1367             :     case 11: sp-=11; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long))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; \
    1368             :     case 12: sp-=12; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long))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; \
    1369             :     case 13: sp-=13; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long,long))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; \
    1370             :     case 14: sp-=14; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long,long,long))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; \
    1371             :     case 15: sp-=15; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long,long,long,long))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; \
    1372             :     case 16: sp-=16; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long))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; \
    1373             :     case 17: sp-=17; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long))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; \
    1374             :     case 18: sp-=18; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long))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; \
    1375             :     case 19: sp-=19; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long))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; \
    1376             :     case 20: sp-=20; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long))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; \
    1377             :     default: \
    1378             :       pari_err_IMPL("functions with more than 20 parameters");\
    1379             :       goto endeval; /*LCOV_EXCL_LINE*/ \
    1380             :   }
    1381             : 
    1382             : 
    1383   105290963 :     case OCcallgen:
    1384             :       {
    1385   105290963 :         entree *ep = (entree *)operand;
    1386             :         GEN res;
    1387             :         /* Macro Madness : evaluate function ep->value on arguments
    1388             :          * st[sp-ep->arity .. sp]. Set res = result. */
    1389   105290963 :         EVAL_f(ep->value, GEN, res=);
    1390   105274173 :         if (br_status) goto endeval;
    1391   105137045 :         gel(st,sp++)=res;
    1392   105137045 :         break;
    1393             :       }
    1394   607466595 :     case OCcallgen2: /*same for ep->arity = 2. Is this optimization worth it ?*/
    1395             :       {
    1396   607466595 :         entree *ep = (entree *)operand;
    1397             :         GEN res;
    1398   607466595 :         sp-=2;
    1399   607466595 :         res = ((GEN (*)(GEN,GEN))ep->value)(gel(st,sp),gel(st,sp+1));
    1400   607561251 :         if (br_status) goto endeval;
    1401   607561223 :         gel(st,sp++)=res;
    1402   607561223 :         break;
    1403             :       }
    1404    18306921 :     case OCcalllong:
    1405             :       {
    1406    18306921 :         entree *ep = (entree *)operand;
    1407             :         long res;
    1408    18306921 :         EVAL_f(ep->value, long, res=);
    1409    18307844 :         if (br_status) goto endeval;
    1410    18307844 :         st[sp++] = res;
    1411    18307844 :         break;
    1412             :       }
    1413     1704247 :     case OCcallint:
    1414             :       {
    1415     1704247 :         entree *ep = (entree *)operand;
    1416             :         long res;
    1417     1704247 :         EVAL_f(ep->value, int, res=);
    1418     1704121 :         if (br_status) goto endeval;
    1419     1704121 :         st[sp++] = res;
    1420     1704121 :         break;
    1421             :       }
    1422    48839413 :     case OCcallvoid:
    1423             :       {
    1424    48839413 :         entree *ep = (entree *)operand;
    1425    48839413 :         EVAL_f(ep->value, void,(void));
    1426    48838942 :         if (br_status) goto endeval;
    1427    48680382 :         break;
    1428             :       }
    1429             : #undef EVAL_f
    1430             : 
    1431    35444394 :     case OCcalluser:
    1432             :       {
    1433    35444394 :         long n=operand;
    1434    35444394 :         GEN fun = gel(st,sp-1-n);
    1435             :         long arity, isvar;
    1436             :         GEN z;
    1437    35444394 :         if (typ(fun)!=t_CLOSURE) pari_err(e_NOTFUNC, fun);
    1438    35441685 :         isvar = closure_is_variadic(fun);
    1439    35441701 :         arity = closure_arity(fun);
    1440    35441694 :         if (!isvar || n < arity)
    1441             :         {
    1442    35441624 :           st_alloc(arity-n);
    1443    35441605 :           if (n>arity)
    1444           0 :             pari_err(e_MISC,"too many parameters in user-defined function call");
    1445    35467883 :           for (j=n+1;j<=arity;j++)
    1446       26277 :             gel(st,sp++)=0;
    1447    35441606 :           if (isvar) gel(st,sp-1) = cgetg(1,t_VEC);
    1448             :         }
    1449             :         else
    1450             :         {
    1451             :           GEN v;
    1452          70 :           long j, m = n-arity+1;
    1453          70 :           v = cgetg(m+1,t_VEC);
    1454          70 :           sp-=m;
    1455         301 :           for (j=1; j<=m; j++)
    1456         231 :             gel(v,j) = gel(st,sp+j-1)? gcopy(gel(st,sp+j-1)): gen_0;
    1457          70 :           gel(st,sp++)=v;
    1458             :         }
    1459    35441676 :         z = closure_return(fun);
    1460    35436985 :         if (br_status) goto endeval;
    1461    35436985 :         gel(st, sp-1) = z;
    1462    35436985 :         break;
    1463             :       }
    1464    42558954 :     case OCnewframe:
    1465    42558954 :       if (operand>0) nbmvar+=operand;
    1466          13 :       else operand=-operand;
    1467    42558954 :       pari_stack_alloc(&s_var,operand);
    1468    42558954 :       s_var.n+=operand;
    1469   122283152 :       for(j=1;j<=operand;j++)
    1470             :       {
    1471    79724198 :         var[s_var.n-j].flag=PUSH_VAL;
    1472    79724198 :         var[s_var.n-j].value=gen_0;
    1473             :       }
    1474    42558954 :       break;
    1475        6732 :     case OCsaveframe:
    1476             :       {
    1477        6732 :         GEN cl = (operand?gcopy:shallowcopy)(gel(st,sp-1));
    1478        6732 :         GEN f = gel(cl, 7);
    1479        6732 :         long j, l = lg(f);
    1480        6732 :         GEN v = cgetg(l, t_VEC);
    1481       75835 :         for (j = 1; j < l; j++)
    1482       69103 :           if (signe(gel(f,l-j))==0)
    1483             :           {
    1484       10080 :             GEN val = var[s_var.n-j].value;
    1485       10080 :             gel(v,j) = operand?gcopy(val):val;
    1486             :           } else
    1487       59023 :             gel(v,j) = gnil;
    1488        6732 :         gel(cl,7) = v;
    1489        6732 :         gel(st,sp-1) = cl;
    1490             :       }
    1491        6732 :       break;
    1492         105 :     case OCpackargs:
    1493             :     {
    1494         105 :       GEN def = cgetg(operand+1, t_VECSMALL);
    1495         105 :       GEN args = cgetg(operand+1, t_VEC);
    1496         105 :       pari_stack_alloc(&s_var,operand);
    1497         105 :       sp-=operand;
    1498         210 :       for (j=0;j<operand;j++)
    1499             :       {
    1500         105 :         if (gel(st,sp+j))
    1501             :         {
    1502         105 :           gel(args,j+1) = gel(st,sp+j);
    1503         105 :           uel(def ,j+1) = 1;
    1504             :         }
    1505             :         else
    1506             :         {
    1507           0 :           gel(args,j+1) = gen_0;
    1508           0 :           uel(def ,j+1) = 0;
    1509             :         }
    1510             :       }
    1511         105 :       gel(st, sp++) = args;
    1512         105 :       gel(st, sp++) = def;
    1513         105 :       break;
    1514             :     }
    1515    36489925 :     case OCgetargs:
    1516    36489925 :       pari_stack_alloc(&s_var,operand);
    1517    36489236 :       s_var.n+=operand;
    1518    36489236 :       nbmvar+=operand;
    1519    36489236 :       sp-=operand;
    1520    99965975 :       for (j=0;j<operand;j++)
    1521             :       {
    1522    63477118 :         if (gel(st,sp+j))
    1523    63468459 :           pushlex(j-operand,gel(st,sp+j));
    1524             :         else
    1525             :         {
    1526        8659 :           var[s_var.n+j-operand].flag=DEFAULT_VAL;
    1527        8659 :           var[s_var.n+j-operand].value=gen_0;
    1528             :         }
    1529             :       }
    1530    36488857 :       break;
    1531          49 :     case OCcheckuserargs:
    1532         105 :       for (j=0; j<operand; j++)
    1533          77 :         if (var[s_var.n-operand+j].flag==DEFAULT_VAL)
    1534          21 :           pari_err(e_MISC,"missing mandatory argument"
    1535             :                    " '%s' in user function",get_arg_name(C,j+1));
    1536          28 :       break;
    1537    12139514 :     case OCcheckargs:
    1538    53520432 :       for (j=sp-1;operand;operand>>=1UL,j--)
    1539    41380914 :         if ((operand&1L) && gel(st,j)==NULL)
    1540           0 :           pari_err(e_MISC,"missing mandatory argument");
    1541    12139518 :       break;
    1542         441 :     case OCcheckargs0:
    1543         882 :       for (j=sp-1;operand;operand>>=1UL,j--)
    1544         441 :         if ((operand&1L) && gel(st,j))
    1545           0 :           pari_err(e_MISC,"argument type not implemented");
    1546         441 :       break;
    1547       23456 :     case OCdefaultlong:
    1548       23456 :       sp--;
    1549       23456 :       if (st[sp+operand])
    1550        1050 :         st[sp+operand]=gtos(gel(st,sp+operand));
    1551             :       else
    1552       22406 :         st[sp+operand]=st[sp];
    1553       23456 :       break;
    1554           0 :     case OCdefaultulong:
    1555           0 :       sp--;
    1556           0 :       if (st[sp+operand])
    1557           0 :         st[sp+operand]=gtou(gel(st,sp+operand));
    1558             :       else
    1559           0 :         st[sp+operand]=st[sp];
    1560           0 :       break;
    1561           0 :     case OCdefaultgen:
    1562           0 :       sp--;
    1563           0 :       if (!st[sp+operand])
    1564           0 :         st[sp+operand]=st[sp];
    1565           0 :       break;
    1566    10731865 :     case OCvec:
    1567    10731865 :       gel(st,sp++)=cgetg(operand,t_VEC);
    1568    10731862 :       st[sp++]=avma;
    1569    10731862 :       break;
    1570        4795 :     case OCcol:
    1571        4795 :       gel(st,sp++)=cgetg(operand,t_COL);
    1572        4795 :       st[sp++]=avma;
    1573        4795 :       break;
    1574       55804 :     case OCmat:
    1575             :       {
    1576             :         GEN z;
    1577       55804 :         long l=st[sp-1];
    1578       55804 :         z=cgetg(operand,t_MAT);
    1579      185794 :         for(j=1;j<operand;j++)
    1580      129990 :           gel(z,j) = cgetg(l,t_COL);
    1581       55804 :         gel(st,sp-1) = z;
    1582       55804 :         st[sp++]=avma;
    1583             :       }
    1584       55804 :       break;
    1585    88871520 :     case OCpop:
    1586    88871520 :       sp-=operand;
    1587    88871520 :       break;
    1588    31391957 :     case OCdup:
    1589             :       {
    1590    31391957 :         long i, s=st[sp-1];
    1591    31391957 :         st_alloc(operand);
    1592    62794299 :         for(i=1;i<=operand;i++)
    1593    31402342 :           st[sp++]=s;
    1594             :       }
    1595    31391957 :       break;
    1596             :     }
    1597             :   }
    1598             :   if (0)
    1599             :   {
    1600      295716 : endeval:
    1601      295716 :     sp = saved_sp;
    1602      295716 :     for(  ; rp>saved_rp ;  )
    1603             :     {
    1604           0 :       gp_pointer *g = &ptrs[--rp];
    1605           0 :       clone_unlock_deep(g->ox);
    1606             :     }
    1607             :   }
    1608   312151417 :   s_prec.n = saved_prec;
    1609   312151417 :   s_trace.n--;
    1610   312151417 :   restore_vars(nbmvar, nblvar, nblock);
    1611   311829003 :   clone_unlock(C);
    1612   311759003 : }
    1613             : 
    1614             : GEN
    1615    34037775 : closure_evalgen(GEN C)
    1616             : {
    1617    34037775 :   pari_sp ltop=avma;
    1618    34037775 :   closure_eval(C);
    1619    34001532 :   if (br_status) return gc_NULL(ltop);
    1620    34001470 :   return gerepileupto(ltop,gel(st,--sp));
    1621             : }
    1622             : 
    1623             : long
    1624      910944 : evalstate_get_trace(void)
    1625      910944 : { return s_trace.n; }
    1626             : 
    1627             : void
    1628          18 : evalstate_set_trace(long lvl)
    1629          18 : { s_trace.n = lvl; }
    1630             : 
    1631             : void
    1632     1418810 : evalstate_save(struct pari_evalstate *state)
    1633             : {
    1634     1418810 :   state->avma = avma;
    1635     1418810 :   state->sp   = sp;
    1636     1418810 :   state->rp   = rp;
    1637     1418810 :   state->prec = s_prec.n;
    1638     1418810 :   state->var  = s_var.n;
    1639     1418810 :   state->lvars= s_lvars.n;
    1640     1418810 :   state->locks= s_locks.n;
    1641     1418810 :   state->trace= s_trace.n;
    1642     1418810 :   compilestate_save(&state->comp);
    1643     1418811 :   mtstate_save(&state->mt);
    1644     1418811 : }
    1645             : 
    1646             : void
    1647       48982 : evalstate_restore(struct pari_evalstate *state)
    1648             : {
    1649       48982 :   set_avma(state->avma);
    1650       48982 :   mtstate_restore(&state->mt);
    1651       48982 :   sp = state->sp;
    1652       48982 :   rp = state->rp;
    1653       48982 :   s_prec.n = state->prec;
    1654       48982 :   restore_vars(s_var.n-state->var, s_lvars.n-state->lvars,
    1655       48982 :                s_locks.n-state->locks);
    1656       48982 :   restore_trace(s_trace.n-state->trace);
    1657       48982 :   reset_break();
    1658       48982 :   compilestate_restore(&state->comp);
    1659       48982 : }
    1660             : 
    1661             : GEN
    1662       36243 : evalstate_restore_err(struct pari_evalstate *state)
    1663             : {
    1664       36243 :   GENbin* err = copy_bin(pari_err_last());
    1665       36243 :   evalstate_restore(state);
    1666       36243 :   return bin_copy(err);
    1667             : }
    1668             : 
    1669             : void
    1670         438 : evalstate_reset(void)
    1671             : {
    1672         438 :   mtstate_reset();
    1673         438 :   restore_vars(s_var.n, s_lvars.n, s_locks.n);
    1674         438 :   sp = rp = dbg_level = s_trace.n = 0;
    1675         438 :   reset_break();
    1676         438 :   compilestate_reset();
    1677         438 :   parsestate_reset();
    1678         438 :   set_avma(pari_mainstack->top);
    1679         438 : }
    1680             : 
    1681             : void
    1682           0 : evalstate_clone(void)
    1683             : {
    1684             :   long i;
    1685           0 :   for (i = 1; i<=s_var.n; i++) copylex(-i);
    1686           0 :   lvar_make_safe();
    1687           0 :   for (i = 0; i< s_trace.n; i++)
    1688             :   {
    1689           0 :     GEN C = trace[i].closure;
    1690           0 :     if (isonstack(C)) trace[i].closure = gclone(C);
    1691             :   }
    1692           0 : }
    1693             : 
    1694             : GEN
    1695    76015533 : closure_evalnobrk(GEN C)
    1696             : {
    1697    76015533 :   pari_sp ltop=avma;
    1698    76015533 :   closure_eval(C);
    1699    76015512 :   if (br_status) pari_err(e_MISC, "break not allowed here");
    1700    76015505 :   return gerepileupto(ltop,gel(st,--sp));
    1701             : }
    1702             : 
    1703             : void
    1704   152226246 : closure_evalvoid(GEN C)
    1705             : {
    1706   152226246 :   pari_sp ltop=avma;
    1707   152226246 :   closure_eval(C);
    1708   152197791 :   set_avma(ltop);
    1709   152179709 : }
    1710             : 
    1711             : GEN
    1712      931458 : closure_evalres(GEN C)
    1713             : {
    1714      931458 :   return closure_return(C);
    1715             : }
    1716             : 
    1717             : INLINE GEN
    1718    13193149 : closure_returnupto(GEN C)
    1719             : {
    1720    13193149 :   pari_sp av=avma;
    1721    13193149 :   return copyupto(closure_return(C),(GEN)av);
    1722             : }
    1723             : 
    1724             : GEN
    1725          12 : pareval_worker(GEN C)
    1726             : {
    1727          12 :   return closure_callgenall(C, 0);
    1728             : }
    1729             : 
    1730             : GEN
    1731           6 : pareval(GEN C)
    1732             : {
    1733           6 :   pari_sp av = avma;
    1734           6 :   long l = lg(C), i;
    1735             :   GEN worker;
    1736           6 :   if (!is_vec_t(typ(C))) pari_err_TYPE("pareval",C);
    1737          18 :   for (i=1; i<l; i++)
    1738          12 :     if (typ(gel(C,i))!=t_CLOSURE)
    1739           0 :       pari_err_TYPE("pareval",gel(C,i));
    1740           6 :   worker = snm_closure(is_entry("_pareval_worker"), NULL);
    1741           6 :   return gerepileupto(av, gen_parapply(worker, C));
    1742             : }
    1743             : 
    1744             : GEN
    1745         631 : parvector_worker(GEN i, GEN C)
    1746             : {
    1747         631 :   return closure_callgen1(C, i);
    1748             : }
    1749             : 
    1750             : GEN
    1751        9632 : parfor_worker(GEN i, GEN C)
    1752             : {
    1753        9632 :   retmkvec2(gcopy(i), closure_callgen1(C, i));
    1754             : }
    1755             : 
    1756             : GEN
    1757          31 : parvector(long n, GEN code)
    1758             : {
    1759          31 :   long i, pending = 0, workid;
    1760          31 :   GEN worker = snm_closure(is_entry("_parvector_worker"), mkvec(code));
    1761             :   GEN a, V, done;
    1762             :   struct pari_mt pt;
    1763          31 :   mt_queue_start_lim(&pt, worker, n);
    1764          31 :   a = mkvec(cgetipos(3)); /* left on the stack */
    1765          31 :   V = cgetg(n+1, t_VEC);
    1766         622 :   for (i=1; i<=n || pending; i++)
    1767             :   {
    1768         597 :     mael(a,1,2) = i;
    1769         597 :     mt_queue_submit(&pt, i, i<=n? a: NULL);
    1770         593 :     done = mt_queue_get(&pt, &workid, &pending);
    1771         591 :     if (done) gel(V,workid) = done;
    1772             :   }
    1773          25 :   mt_queue_end(&pt);
    1774          25 :   return V;
    1775             : }
    1776             : 
    1777             : /* suitable for gerepileupto */
    1778             : GEN
    1779        7474 : parsum_slice_worker(GEN a, GEN b, GEN m, GEN worker)
    1780             : {
    1781        7474 :   pari_sp av = avma;
    1782        7474 :   GEN s = gen_0;
    1783      133594 :   while (gcmp(a,b)<=0)
    1784             :   {
    1785      125690 :     s = gadd(s, closure_callgen1(worker, a));
    1786      126277 :     a = addii(a, m);
    1787      126120 :     if (gc_needed(av,1))
    1788             :     {
    1789           0 :       if (DEBUGMEM>1) pari_warn(warnmem,"parsum_slice");
    1790           0 :       gerepileall(av,2,&a,&s);
    1791             :     }
    1792             :   }
    1793        7380 :   return gerepileupto(av,s);
    1794             : }
    1795             : 
    1796             : GEN
    1797        2034 : parsum(GEN a, GEN b, GEN code)
    1798             : {
    1799        2034 :   pari_sp av = avma;
    1800             :   GEN worker, mG, v, s, N;
    1801             :   long r, m, pending;
    1802             :   struct pari_mt pt;
    1803             :   pari_sp av2;
    1804             : 
    1805        2034 :   if (typ(a) != t_INT) pari_err_TYPE("parsum",a);
    1806        2034 :   if (gcmp(b,a) < 0) return gen_0;
    1807        2034 :   b = gfloor(b);
    1808        2034 :   N = addiu(subii(b, a), 1);
    1809        2034 :   mG = sqrti(N);
    1810        2034 :   m = itou(mG);
    1811        2034 :   worker = snm_closure(is_entry("_parsum_slice_worker"), mkvec3(b,mG,code));
    1812        2034 :   mt_queue_start_lim(&pt, worker, m);
    1813        2034 :   s = gen_0; a = setloop(a); v = mkvec(a); pending = 0; av2 = avma;
    1814       12003 :   for (r = 1; r <= m || pending; r++)
    1815             :   {
    1816             :     long workid;
    1817             :     GEN done;
    1818        9990 :     mt_queue_submit(&pt, 0, r <= m? v: NULL);
    1819        9972 :     done = mt_queue_get(&pt, &workid, &pending);
    1820        9969 :     if (done)
    1821             :     {
    1822        7476 :       s = gadd(s, done);
    1823        7476 :       if (gc_needed(av2,1))
    1824             :       {
    1825           0 :         if (DEBUGMEM>1) pari_warn(warnmem,"parsum");
    1826           0 :         s = gerepileupto(av2,s);
    1827             :       }
    1828             :     }
    1829        9969 :     a = incloop(a); gel(v,1) = a;
    1830             :   }
    1831        2013 :   mt_queue_end(&pt); return gerepileupto(av, s);
    1832             : }
    1833             : 
    1834             : void
    1835         346 : parfor(GEN a, GEN b, GEN code, void *E, long call(void*, GEN, GEN))
    1836             : {
    1837         346 :   pari_sp av = avma, av2;
    1838         346 :   long running, pending = 0, lim;
    1839         346 :   long status = br_NONE;
    1840         346 :   GEN worker = snm_closure(is_entry("_parfor_worker"), mkvec(code));
    1841         346 :   GEN done, stop = NULL;
    1842             :   struct pari_mt pt;
    1843         346 :   if (typ(a) != t_INT) pari_err_TYPE("parfor",a);
    1844         346 :   if (b)
    1845             :   {
    1846         346 :     if (gcmp(b,a) < 0) return;
    1847         346 :     if (typ(b) == t_INFINITY)
    1848             :     {
    1849           6 :       if (inf_get_sign(b) < 0) return;
    1850           6 :       b = NULL;
    1851             :     }
    1852             :     else
    1853         340 :       b = gfloor(b);
    1854             :   }
    1855         346 :   lim = b ? itos_or_0(subii(addis(b,1),a)): 0;
    1856         346 :   mt_queue_start_lim(&pt, worker, lim);
    1857         346 :   a = mkvec(setloop(a));
    1858         346 :   av2 = avma;
    1859        7520 :   while ((running = (!stop && (!b || cmpii(gel(a,1),b) <= 0))) || pending)
    1860             :   {
    1861        7180 :     mt_queue_submit(&pt, 0, running ? a: NULL);
    1862        7176 :     done = mt_queue_get(&pt, NULL, &pending);
    1863        7174 :     if (call && done && (!stop || cmpii(gel(done,1),stop) < 0))
    1864        5453 :       if (call(E, gel(done,1), gel(done,2)))
    1865             :       {
    1866         222 :         status = br_status;
    1867         222 :         br_status = br_NONE;
    1868         222 :         stop = gerepileuptoint(av2, gel(done,1));
    1869             :       }
    1870        7174 :     gel(a,1) = incloop(gel(a,1));
    1871        7174 :     if (!stop) set_avma(av2);
    1872             :   }
    1873         340 :   set_avma(av2);
    1874         340 :   mt_queue_end(&pt);
    1875         340 :   br_status = status;
    1876         340 :   set_avma(av);
    1877             : }
    1878             : 
    1879             : static void
    1880           0 : parforiter_init(struct parfor_iter *T, GEN code)
    1881             : {
    1882           0 :   T->pending = 0;
    1883           0 :   T->worker = snm_closure(is_entry("_parfor_worker"), mkvec(code));
    1884           0 :   mt_queue_start(&T->pt, T->worker);
    1885           0 : }
    1886             : 
    1887             : static GEN
    1888           0 : parforiter_next(struct parfor_iter *T, GEN v)
    1889             : {
    1890           0 :   mt_queue_submit(&T->pt, 0, v);
    1891           0 :   return mt_queue_get(&T->pt, NULL, &T->pending);
    1892             : }
    1893             : 
    1894             : static void
    1895           0 : parforiter_stop(struct parfor_iter *T)
    1896             : {
    1897           0 :   while (T->pending)
    1898             :   {
    1899           0 :     mt_queue_submit(&T->pt, 0, NULL);
    1900           0 :     (void) mt_queue_get(&T->pt, NULL, &T->pending);
    1901             :   }
    1902           0 :   mt_queue_end(&T->pt);
    1903           0 : }
    1904             : 
    1905             : void
    1906           0 : parfor_init(parfor_t *T, GEN a, GEN b, GEN code)
    1907             : {
    1908           0 :   if (typ(a) != t_INT) pari_err_TYPE("parfor",a);
    1909           0 :   T->b = b ? gfloor(b): NULL;
    1910           0 :   T->a = mkvec(setloop(a));
    1911           0 :   parforiter_init(&T->iter, code);
    1912           0 : }
    1913             : 
    1914             : GEN
    1915           0 : parfor_next(parfor_t *T)
    1916             : {
    1917             :   long running;
    1918           0 :   while ((running=((!T->b || cmpii(gel(T->a,1),T->b) <= 0))) || T->iter.pending)
    1919             :   {
    1920           0 :     GEN done = parforiter_next(&T->iter, running ? T->a: NULL);
    1921           0 :     gel(T->a,1) = incloop(gel(T->a,1));
    1922           0 :     if (done) return done;
    1923             :   }
    1924           0 :   mt_queue_end(&T->iter.pt);
    1925           0 :   return NULL;
    1926             : }
    1927             : 
    1928             : void
    1929           0 : parfor_stop(parfor_t *T) { parforiter_stop(&T->iter); }
    1930             : 
    1931             : static long
    1932        8455 : gp_evalvoid2(void *E, GEN x, GEN y)
    1933             : {
    1934        8455 :   GEN code =(GEN) E;
    1935        8455 :   push_lex(x, code);
    1936        8455 :   push_lex(y, NULL);
    1937        8455 :   closure_evalvoid(code);
    1938        8455 :   pop_lex(2);
    1939        8455 :   return loop_break();
    1940             : }
    1941             : 
    1942             : void
    1943         346 : parfor0(GEN a, GEN b, GEN code, GEN code2)
    1944             : {
    1945         346 :   parfor(a, b, code, (void*)code2, code2 ? gp_evalvoid2: NULL);
    1946         340 : }
    1947             : 
    1948           0 : static int negcmp(GEN x, GEN y) { return gcmp(y,x); }
    1949             : 
    1950             : void
    1951          39 : parforstep(GEN a, GEN b, GEN s, GEN code, void *E, long call(void*, GEN, GEN))
    1952             : {
    1953          39 :   pari_sp av = avma, av2;
    1954          39 :   long running, pending = 0;
    1955          39 :   long status = br_NONE;
    1956          39 :   GEN worker = snm_closure(is_entry("_parfor_worker"), mkvec(code));
    1957          39 :   GEN done, stop = NULL;
    1958             :   struct pari_mt pt;
    1959             :   long i, ss;
    1960          39 :   GEN v = NULL, lim;
    1961             :   int (*cmp)(GEN,GEN);
    1962             : 
    1963          39 :   b = gcopy(b);
    1964          39 :   s = gcopy(s); av = avma;
    1965          39 :   switch(typ(s))
    1966             :   {
    1967          13 :     case t_VEC: case t_COL:
    1968             :     {
    1969          13 :       GEN vs = vecsum(s);
    1970          13 :       ss = gsigne(vs); v = s;
    1971          13 :       lim = gdiv(gmulgs(gadd(gsub(b,a),vs),lg(vs)-1),vs);
    1972          13 :       break;
    1973             :     }
    1974          13 :     case t_INTMOD:
    1975          13 :       if (typ(a) != t_INT) a = gceil(a);
    1976          13 :       a = addii(a, modii(subii(gel(s,2),a), gel(s,1)));
    1977          13 :       s = gel(s,1); /* FALL THROUGH */
    1978          26 :     default:
    1979          26 :       ss = gsigne(s);
    1980          26 :       lim = gdiv(gadd(gsub(b,a),s),s);
    1981             :   }
    1982          39 :   lim = ceil_safe(lim);
    1983          39 :   if (!ss || typ(lim)!=t_INT) pari_err_DOMAIN("parforstep","step","=",gen_0,s);
    1984          39 :   if (signe(lim)<=0) { set_avma(av); return; }
    1985          39 :   cmp = (ss > 0)? &gcmp: &negcmp;
    1986          39 :   i = 0;
    1987          39 :   a = mkvec(a);
    1988          39 :   mt_queue_start_lim(&pt, worker, itou_or_0(lim));
    1989          39 :   av2 = avma;
    1990        2695 :   while ((running = (!stop && (!b || cmp(gel(a,1),b) <= 0))) || pending)
    1991             :   {
    1992        2656 :     mt_queue_submit(&pt, 0, running ? a: NULL);
    1993        2656 :     done = mt_queue_get(&pt, NULL, &pending);
    1994        2656 :     if (call && done && (!stop || cmp(gel(done,1),stop) < 0))
    1995        2521 :       if (call(E, gel(done,1), gel(done,2)))
    1996             :       {
    1997           0 :         status = br_status;
    1998           0 :         br_status = br_NONE;
    1999           0 :         stop = gel(done,1);
    2000             :       }
    2001        2656 :     if (running)
    2002             :     {
    2003        2521 :       if (v)
    2004             :       {
    2005        1637 :         if (++i >= lg(v)) i = 1;
    2006        1637 :         s = gel(v,i);
    2007             :       }
    2008        2521 :       gel(a,1) = gadd(gel(a,1),s);
    2009        2521 :       if (!stop) gel(a,1) = gerepileupto(av2, gel(a,1));
    2010             :     }
    2011             :   }
    2012          39 :   mt_queue_end(&pt);
    2013          39 :   br_status = status;
    2014          39 :   set_avma(av);
    2015             : }
    2016             : 
    2017             : void
    2018          39 : parforstep0(GEN a, GEN b, GEN s, GEN code, GEN code2)
    2019             : {
    2020          39 :   parforstep(a, b, s, code, (void*)code2, code2 ? gp_evalvoid2: NULL);
    2021          39 : }
    2022             : 
    2023             : void
    2024           0 : parforstep_init(parforstep_t *T, GEN a, GEN b, GEN s, GEN code)
    2025             : {
    2026             :   long ss;
    2027           0 :   if (typ(a) != t_INT) pari_err_TYPE("parfor",a);
    2028           0 :   switch(typ(s))
    2029             :   {
    2030           0 :     case t_VEC: case t_COL:
    2031           0 :       ss = gsigne(vecsum(s));
    2032           0 :       break;
    2033           0 :     case t_INTMOD:
    2034           0 :       if (typ(a) != t_INT) a = gceil(a);
    2035           0 :       a = addii(a, modii(subii(gel(s,2),a), gel(s,1)));
    2036           0 :       s = gel(s,1);
    2037           0 :     default: /* FALL THROUGH */
    2038           0 :       ss = gsigne(s);
    2039             :   }
    2040           0 :   T->cmp = (ss > 0)? &gcmp: &negcmp;
    2041           0 :   T->s = s;
    2042           0 :   T->i = 0;
    2043           0 :   T->b = b;
    2044           0 :   T->a = mkvec(a);
    2045           0 :   parforiter_init(&T->iter, code);
    2046           0 : }
    2047             : 
    2048             : GEN
    2049           0 : parforstep_next(parforstep_t *T)
    2050             : {
    2051             :   long running;
    2052           0 :   while ((running=((!T->b || T->cmp(gel(T->a,1),T->b) <= 0))) || T->iter.pending)
    2053             :   {
    2054           0 :     GEN done = parforiter_next(&T->iter, running ? T->a: NULL);
    2055           0 :     if (running)
    2056             :     {
    2057           0 :       if (is_vec_t(typ(T->s)))
    2058             :       {
    2059           0 :         if (++(T->i) >= lg(T->s)) T->i = 1;
    2060           0 :         gel(T->a,1) = gadd(gel(T->a,1), gel(T->s,T->i));
    2061             :       }
    2062           0 :       else gel(T->a,1) = gadd(gel(T->a,1), T->s);
    2063             :     }
    2064           0 :     if (done) return done;
    2065             :   }
    2066           0 :   mt_queue_end(&T->iter.pt);
    2067           0 :   return NULL;
    2068             : }
    2069             : 
    2070             : void
    2071           0 : parforstep_stop(parforstep_t *T) { parforiter_stop(&T->iter); }
    2072             : 
    2073             : void
    2074           0 : parforprimestep_init(parforprime_t *T, GEN a, GEN b, GEN q, GEN code)
    2075             : {
    2076           0 :   forprimestep_init(&T->forprime, a, b, q);
    2077           0 :   T->v = mkvec(gen_0);
    2078           0 :   parforiter_init(&T->iter, code);
    2079           0 : }
    2080             : 
    2081             : void
    2082           0 : parforprime_init(parforprime_t *T, GEN a, GEN b, GEN code)
    2083           0 : { parforprimestep_init(T, a, b, NULL, code); }
    2084             : 
    2085             : GEN
    2086           0 : parforprime_next(parforprime_t *T)
    2087             : {
    2088             :   long running;
    2089           0 :   while ((running = !!forprime_next(&T->forprime)) || T->iter.pending)
    2090             :   {
    2091             :     GEN done;
    2092           0 :     gel(T->v, 1) = T->forprime.pp;
    2093           0 :     done = parforiter_next(&T->iter, running ? T->v: NULL);
    2094           0 :     if (done) return done;
    2095             :   }
    2096           0 :   mt_queue_end(&T->iter.pt);
    2097           0 :   return NULL;
    2098             : }
    2099             : 
    2100             : void
    2101           0 : parforprime_stop(parforprime_t *T) { parforiter_stop(&T->iter); }
    2102             : 
    2103             : void
    2104          20 : parforprimestep(GEN a, GEN b, GEN q, GEN code, void *E, long call(void*, GEN, GEN))
    2105             : {
    2106          20 :   pari_sp av = avma, av2;
    2107          20 :   long running, pending = 0;
    2108          20 :   long status = br_NONE;
    2109          20 :   GEN worker = snm_closure(is_entry("_parfor_worker"), mkvec(code));
    2110          20 :   GEN v, done, stop = NULL;
    2111             :   struct pari_mt pt;
    2112             :   forprime_t T;
    2113             : 
    2114          20 :   if (!forprimestep_init(&T, a,b,q)) { set_avma(av); return; }
    2115          20 :   mt_queue_start(&pt, worker);
    2116          20 :   v = mkvec(gen_0);
    2117          20 :   av2 = avma;
    2118         172 :   while ((running = (!stop && forprime_next(&T))) || pending)
    2119             :   {
    2120         152 :     gel(v, 1) = T.pp;
    2121         152 :     mt_queue_submit(&pt, 0, running ? v: NULL);
    2122         152 :     done = mt_queue_get(&pt, NULL, &pending);
    2123         152 :     if (call && done && (!stop || cmpii(gel(done,1),stop) < 0))
    2124         125 :       if (call(E, gel(done,1), gel(done,2)))
    2125             :       {
    2126           0 :         status = br_status;
    2127           0 :         br_status = br_NONE;
    2128           0 :         stop = gerepileuptoint(av2, gel(done,1));
    2129             :       }
    2130         152 :     if (!stop) set_avma(av2);
    2131             :   }
    2132          20 :   set_avma(av2);
    2133          20 :   mt_queue_end(&pt);
    2134          20 :   br_status = status;
    2135          20 :   set_avma(av);
    2136             : }
    2137             : 
    2138             : void
    2139          13 : parforprime(GEN a, GEN b, GEN code, void *E, long call(void*, GEN, GEN))
    2140             : {
    2141          13 :   parforprimestep(a, b, NULL, code, E, call);
    2142          13 : }
    2143             : 
    2144             : void
    2145          13 : parforprime0(GEN a, GEN b, GEN code, GEN code2)
    2146             : {
    2147          13 :   parforprime(a, b, code, (void*)code2, code2? gp_evalvoid2: NULL);
    2148          13 : }
    2149             : 
    2150             : void
    2151           7 : parforprimestep0(GEN a, GEN b, GEN q, GEN code, GEN code2)
    2152             : {
    2153           7 :   parforprimestep(a, b, q, code, (void*)code2, code2? gp_evalvoid2: NULL);
    2154           7 : }
    2155             : 
    2156             : void
    2157           0 : parforvec_init(parforvec_t *T, GEN x, GEN code, long flag)
    2158             : {
    2159           0 :   forvec_init(&T->forvec, x, flag);
    2160           0 :   T->v = mkvec(gen_0);
    2161           0 :   parforiter_init(&T->iter, code);
    2162           0 : }
    2163             : 
    2164             : GEN
    2165           0 : parforvec_next(parforvec_t *T)
    2166             : {
    2167           0 :   GEN v = gen_0;
    2168           0 :   while ((v = forvec_next(&T->forvec)) || T->iter.pending)
    2169             :   {
    2170             :     GEN done;
    2171           0 :     if (v) gel(T->v, 1) = v;
    2172           0 :     done = parforiter_next(&T->iter, v ? T->v: NULL);
    2173           0 :     if (done) return done;
    2174             :   }
    2175           0 :   mt_queue_end(&T->iter.pt);
    2176           0 :   return NULL;
    2177             : }
    2178             : 
    2179             : void
    2180           0 : parforvec_stop(parforvec_t *T) { parforiter_stop(&T->iter); }
    2181             : 
    2182             : void
    2183          39 : parforvec(GEN x, GEN code, long flag, void *E, long call(void*, GEN, GEN))
    2184             : {
    2185          39 :   pari_sp av = avma, av2;
    2186          39 :   long running, pending = 0;
    2187          39 :   long status = br_NONE;
    2188          39 :   GEN worker = snm_closure(is_entry("_parfor_worker"), mkvec(code));
    2189          39 :   GEN done, stop = NULL;
    2190             :   struct pari_mt pt;
    2191             :   forvec_t T;
    2192          39 :   GEN a, v = gen_0;
    2193             : 
    2194          39 :   if (!forvec_init(&T, x, flag)) { set_avma(av); return; }
    2195          39 :   mt_queue_start(&pt, worker);
    2196          39 :   a = mkvec(gen_0);
    2197          39 :   av2 = avma;
    2198         415 :   while ((running = (!stop && v && (v = forvec_next(&T)))) || pending)
    2199             :   {
    2200         376 :     gel(a, 1) = v;
    2201         376 :     mt_queue_submit(&pt, 0, running ? a: NULL);
    2202         376 :     done = mt_queue_get(&pt, NULL, &pending);
    2203         376 :     if (call && done && (!stop || lexcmp(gel(done,1),stop) < 0))
    2204         300 :       if (call(E, gel(done,1), gel(done,2)))
    2205             :       {
    2206           0 :         status = br_status;
    2207           0 :         br_status = br_NONE;
    2208           0 :         stop = gerepilecopy(av2, gel(done,1));
    2209             :       }
    2210         376 :     if (!stop) set_avma(av2);
    2211             :   }
    2212          39 :   set_avma(av2);
    2213          39 :   mt_queue_end(&pt);
    2214          39 :   br_status = status;
    2215          39 :   set_avma(av);
    2216             : }
    2217             : 
    2218             : void
    2219          39 : parforvec0(GEN x, GEN code, GEN code2, long flag)
    2220             : {
    2221          39 :   parforvec(x, code, flag, (void*)code2, code2? gp_evalvoid2: NULL);
    2222          39 : }
    2223             : 
    2224             : void
    2225           0 : parforeach_init(parforeach_t *T, GEN x, GEN code)
    2226             : {
    2227           0 :   switch(typ(x))
    2228             :   {
    2229           0 :     case t_LIST:
    2230           0 :       x = list_data(x); /* FALL THROUGH */
    2231           0 :       if (!x) return;
    2232             :     case t_MAT: case t_VEC: case t_COL:
    2233           0 :       break;
    2234           0 :     default:
    2235           0 :       pari_err_TYPE("foreach",x);
    2236             :       return; /*LCOV_EXCL_LINE*/
    2237             :   }
    2238           0 :   T->x = x; T->i = 1; T->l = lg(x);
    2239           0 :   T->W = mkvec(gen_0);
    2240           0 :   T->iter.pending = 0;
    2241           0 :   T->iter.worker = snm_closure(is_entry("_parvector_worker"), mkvec(code));
    2242           0 :   mt_queue_start(&T->iter.pt, T->iter.worker);
    2243             : }
    2244             : 
    2245             : GEN
    2246           0 : parforeach_next(parforeach_t *T)
    2247             : {
    2248           0 :   while (T->i < T->l || T->iter.pending)
    2249             :   {
    2250             :     GEN done;
    2251             :     long workid;
    2252           0 :     if (T->i < T->l) gel(T->W,1) = gel(T->x, T->i);
    2253           0 :     mt_queue_submit(&T->iter.pt, T->i, T->i < T->l ? T->W: NULL);
    2254           0 :     T->i = minss(T->i+1, T->l);
    2255           0 :     done = mt_queue_get(&T->iter.pt, &workid, &T->iter.pending);
    2256           0 :     if (done) return mkvec2(gel(T->x,workid),done);
    2257             :   }
    2258           0 :   mt_queue_end(&T->iter.pt);
    2259           0 :   return NULL;
    2260             : }
    2261             : 
    2262             : void
    2263           0 : parforeach_stop(parforeach_t *T) { parforiter_stop(&T->iter); }
    2264             : 
    2265             : void
    2266           7 : parforeach(GEN x, GEN code, void *E, long call(void*, GEN, GEN))
    2267             : {
    2268           7 :   pari_sp av = avma, av2;
    2269           7 :   long pending = 0, n, i, stop = 0;
    2270           7 :   long status = br_NONE, workid;
    2271           7 :   GEN worker = snm_closure(is_entry("_parvector_worker"), mkvec(code));
    2272             :   GEN done, W;
    2273             :   struct pari_mt pt;
    2274           7 :   switch(typ(x))
    2275             :   {
    2276           0 :     case t_LIST:
    2277           0 :       x = list_data(x); /* FALL THROUGH */
    2278           0 :       if (!x) return;
    2279             :     case t_MAT: case t_VEC: case t_COL:
    2280           7 :       break;
    2281           0 :     default:
    2282           0 :       pari_err_TYPE("foreach",x);
    2283             :       return; /*LCOV_EXCL_LINE*/
    2284             :   }
    2285           7 :   clone_lock(x); n = lg(x)-1;
    2286           7 :   mt_queue_start_lim(&pt, worker, n);
    2287           7 :   W = cgetg(2, t_VEC);
    2288           7 :   av2 = avma;
    2289          70 :   for (i=1; i<=n || pending; i++)
    2290             :   {
    2291          63 :     if (!stop && i <= n) gel(W,1) = gel(x,i);
    2292          63 :     mt_queue_submit(&pt, i, !stop && i<=n? W: NULL);
    2293          63 :     done = mt_queue_get(&pt, &workid, &pending);
    2294          63 :     if (call && done && (!stop || workid < stop))
    2295          56 :       if (call(E, gel(x, workid), done))
    2296             :       {
    2297           0 :         status = br_status;
    2298           0 :         br_status = br_NONE;
    2299           0 :         stop = workid;
    2300             :       }
    2301             :   }
    2302           7 :   set_avma(av2);
    2303           7 :   mt_queue_end(&pt);
    2304           7 :   clone_unlock_deep(x);
    2305           7 :   br_status = status;
    2306           7 :   set_avma(av);
    2307             : }
    2308             : 
    2309             : void
    2310           7 : parforeach0(GEN x, GEN code, GEN code2)
    2311             : {
    2312           7 :   parforeach(x, code, (void*)code2, code2? gp_evalvoid2: NULL);
    2313           7 : }
    2314             : 
    2315             : void
    2316           0 : closure_callvoid1(GEN C, GEN x)
    2317             : {
    2318           0 :   long i, ar = closure_arity(C);
    2319           0 :   gel(st,sp++) = x;
    2320           0 :   for(i=2; i <= ar; i++) gel(st,sp++) = NULL;
    2321           0 :   closure_evalvoid(C);
    2322           0 : }
    2323             : 
    2324             : GEN
    2325           7 : closure_callgen0(GEN C)
    2326             : {
    2327             :   GEN z;
    2328           7 :   long i, ar = closure_arity(C);
    2329           7 :   for(i=1; i<= ar; i++) gel(st,sp++) = NULL;
    2330           7 :   z = closure_returnupto(C);
    2331           7 :   return z;
    2332             : }
    2333             : 
    2334             : GEN
    2335         168 : closure_callgen0prec(GEN C, long prec)
    2336             : {
    2337             :   GEN z;
    2338         168 :   long i, ar = closure_arity(C);
    2339         168 :   for(i=1; i<= ar; i++) gel(st,sp++) = NULL;
    2340         168 :   push_localprec(prec);
    2341         168 :   z = closure_returnupto(C);
    2342         168 :   pop_localprec();
    2343         168 :   return z;
    2344             : }
    2345             : 
    2346             : GEN
    2347     8562317 : closure_callgen1(GEN C, GEN x)
    2348             : {
    2349     8562317 :   long i, ar = closure_arity(C);
    2350     8562077 :   gel(st,sp++) = x;
    2351     8651796 :   for(i=2; i<= ar; i++) gel(st,sp++) = NULL;
    2352     8562077 :   return closure_returnupto(C);
    2353             : }
    2354             : 
    2355             : GEN
    2356       76681 : closure_callgen1prec(GEN C, GEN x, long prec)
    2357             : {
    2358             :   GEN z;
    2359       76681 :   long i, ar = closure_arity(C);
    2360       76681 :   gel(st,sp++) = x;
    2361       76695 :   for(i=2; i<= ar; i++) gel(st,sp++) = NULL;
    2362       76681 :   push_localprec(prec);
    2363       76681 :   z = closure_returnupto(C);
    2364       76681 :   pop_localprec();
    2365       76681 :   return z;
    2366             : }
    2367             : 
    2368             : GEN
    2369       67073 : closure_callgen2(GEN C, GEN x, GEN y)
    2370             : {
    2371       67073 :   long i, ar = closure_arity(C);
    2372       67073 :   st_alloc(ar);
    2373       67073 :   gel(st,sp++) = x;
    2374       67073 :   gel(st,sp++) = y;
    2375       67073 :   for(i=3; i<=ar; i++) gel(st,sp++) = NULL;
    2376       67073 :   return closure_returnupto(C);
    2377             : }
    2378             : 
    2379             : GEN
    2380     4486619 : closure_callgenvec(GEN C, GEN args)
    2381             : {
    2382     4486619 :   long i, l = lg(args)-1, ar = closure_arity(C);
    2383     4486551 :   st_alloc(ar);
    2384     4486524 :   if (l > ar)
    2385           0 :     pari_err(e_MISC,"too many parameters in user-defined function call");
    2386     4486524 :   if (closure_is_variadic(C) && l==ar && typ(gel(args,l))!=t_VEC)
    2387           7 :     pari_err_TYPE("call", gel(args,l));
    2388     9009630 :   for (i = 1; i <= l;  i++) gel(st,sp++) = gel(args,i);
    2389     4498445 :   for(      ; i <= ar; i++) gel(st,sp++) = NULL;
    2390     4486425 :   return closure_returnupto(C);
    2391             : }
    2392             : 
    2393             : GEN
    2394           0 : closure_callgenvecprec(GEN C, GEN args, long prec)
    2395             : {
    2396             :   GEN z;
    2397           0 :   push_localprec(prec);
    2398           0 :   z = closure_callgenvec(C, args);
    2399           0 :   pop_localprec();
    2400           0 :   return z;
    2401             : }
    2402             : 
    2403             : GEN
    2404         322 : closure_callgenvecdef(GEN C, GEN args, GEN def)
    2405             : {
    2406         322 :   long i, l = lg(args)-1, ar = closure_arity(C);
    2407         322 :   st_alloc(ar);
    2408         322 :   if (l > ar)
    2409           0 :     pari_err(e_MISC,"too many parameters in user-defined function call");
    2410         322 :   if (closure_is_variadic(C) && l==ar && typ(gel(args,l))!=t_VEC)
    2411           0 :     pari_err_TYPE("call", gel(args,l));
    2412         644 :   for (i = 1; i <= l;  i++) gel(st,sp++) = def[i] ? gel(args,i): NULL;
    2413         322 :   for(      ; i <= ar; i++) gel(st,sp++) = NULL;
    2414         322 :   return closure_returnupto(C);
    2415             : }
    2416             : 
    2417             : GEN
    2418         322 : closure_callgenvecdefprec(GEN C, GEN args, GEN def, long prec)
    2419             : {
    2420             :   GEN z;
    2421         322 :   push_localprec(prec);
    2422         322 :   z = closure_callgenvecdef(C, args, def);
    2423         322 :   pop_localprec();
    2424         322 :   return z;
    2425             : }
    2426             : GEN
    2427          12 : closure_callgenall(GEN C, long n, ...)
    2428             : {
    2429             :   va_list ap;
    2430          12 :   long i, ar = closure_arity(C);
    2431          12 :   va_start(ap,n);
    2432          12 :   if (n > ar)
    2433           0 :     pari_err(e_MISC,"too many parameters in user-defined function call");
    2434          12 :   st_alloc(ar);
    2435          12 :   for (i = 1; i <=n;  i++) gel(st,sp++) = va_arg(ap, GEN);
    2436          12 :   for(      ; i <=ar; i++) gel(st,sp++) = NULL;
    2437          12 :   va_end(ap);
    2438          12 :   return closure_returnupto(C);
    2439             : }
    2440             : 
    2441             : GEN
    2442    39688178 : gp_eval(void *E, GEN x)
    2443             : {
    2444    39688178 :   GEN code = (GEN)E;
    2445    39688178 :   set_lex(-1,x);
    2446    39688178 :   return closure_evalnobrk(code);
    2447             : }
    2448             : 
    2449             : GEN
    2450     2052195 : gp_evalupto(void *E, GEN x)
    2451             : {
    2452     2052195 :   pari_sp av = avma;
    2453     2052195 :   return copyupto(gp_eval(E,x), (GEN)av);
    2454             : }
    2455             : 
    2456             : GEN
    2457       20734 : gp_evalprec(void *E, GEN x, long prec)
    2458             : {
    2459             :   GEN z;
    2460       20734 :   push_localprec(prec);
    2461       20734 :   z = gp_eval(E, x);
    2462       20734 :   pop_localprec();
    2463       20734 :   return z;
    2464             : }
    2465             : 
    2466             : long
    2467    26165027 : gp_evalbool(void *E, GEN x)
    2468    26165027 : { pari_sp av = avma; return gc_long(av, !gequal0(gp_eval(E,x))); }
    2469             : 
    2470             : long
    2471     3693816 : gp_evalvoid(void *E, GEN x)
    2472             : {
    2473     3693816 :   GEN code = (GEN)E;
    2474     3693816 :   set_lex(-1,x);
    2475     3693816 :   closure_evalvoid(code);
    2476     3693816 :   return loop_break();
    2477             : }
    2478             : 
    2479             : GEN
    2480      112134 : gp_call(void *E, GEN x)
    2481             : {
    2482      112134 :   GEN code = (GEN)E;
    2483      112134 :   return closure_callgen1(code, x);
    2484             : }
    2485             : 
    2486             : GEN
    2487       23478 : gp_callprec(void *E, GEN x, long prec)
    2488             : {
    2489       23478 :   GEN code = (GEN)E;
    2490       23478 :   return closure_callgen1prec(code, x, prec);
    2491             : }
    2492             : 
    2493             : GEN
    2494          91 : gp_call2(void *E, GEN x, GEN y)
    2495             : {
    2496          91 :   GEN code = (GEN)E;
    2497          91 :   return closure_callgen2(code, x, y);
    2498             : }
    2499             : 
    2500             : long
    2501      872130 : gp_callbool(void *E, GEN x)
    2502             : {
    2503      872130 :   pari_sp av = avma;
    2504      872130 :   GEN code = (GEN)E;
    2505      872130 :   return gc_long(av, !gequal0(closure_callgen1(code, x)));
    2506             : }
    2507             : 
    2508             : long
    2509           0 : gp_callvoid(void *E, GEN x)
    2510             : {
    2511           0 :   GEN code = (GEN)E;
    2512           0 :   closure_callvoid1(code, x);
    2513           0 :   return loop_break();
    2514             : }
    2515             : 
    2516             : INLINE const char *
    2517           0 : disassemble_cast(long mode)
    2518             : {
    2519           0 :   switch (mode)
    2520             :   {
    2521           0 :   case Gsmall:
    2522           0 :     return "small";
    2523           0 :   case Ggen:
    2524           0 :     return "gen";
    2525           0 :   case Gvar:
    2526           0 :     return "var";
    2527           0 :   case Gvoid:
    2528           0 :     return "void";
    2529           0 :   default:
    2530           0 :     return "unknown";
    2531             :   }
    2532             : }
    2533             : 
    2534             : void
    2535           0 : closure_disassemble(GEN C)
    2536             : {
    2537             :   const char * code;
    2538             :   GEN oper;
    2539             :   long i;
    2540           0 :   if (typ(C)!=t_CLOSURE) pari_err_TYPE("disassemble",C);
    2541           0 :   code=closure_codestr(C);
    2542           0 :   oper=closure_get_oper(C);
    2543           0 :   for(i=1;i<lg(oper);i++)
    2544             :   {
    2545           0 :     op_code opcode=(op_code) code[i];
    2546           0 :     long operand=oper[i];
    2547           0 :     pari_printf("%05ld\t",i);
    2548           0 :     switch(opcode)
    2549             :     {
    2550           0 :     case OCpushlong:
    2551           0 :       pari_printf("pushlong\t%ld\n",operand);
    2552           0 :       break;
    2553           0 :     case OCpushgnil:
    2554           0 :       pari_printf("pushgnil\n");
    2555           0 :       break;
    2556           0 :     case OCpushgen:
    2557           0 :       pari_printf("pushgen\t\t%ld\n",operand);
    2558           0 :       break;
    2559           0 :     case OCpushreal:
    2560           0 :       pari_printf("pushreal\t%ld\n",operand);
    2561           0 :       break;
    2562           0 :     case OCpushstoi:
    2563           0 :       pari_printf("pushstoi\t%ld\n",operand);
    2564           0 :       break;
    2565           0 :     case OCpushvar:
    2566             :       {
    2567           0 :         entree *ep = (entree *)operand;
    2568           0 :         pari_printf("pushvar\t%s\n",ep->name);
    2569           0 :         break;
    2570             :       }
    2571           0 :     case OCpushdyn:
    2572             :       {
    2573           0 :         entree *ep = (entree *)operand;
    2574           0 :         pari_printf("pushdyn\t\t%s\n",ep->name);
    2575           0 :         break;
    2576             :       }
    2577           0 :     case OCpushlex:
    2578           0 :       pari_printf("pushlex\t\t%ld\n",operand);
    2579           0 :       break;
    2580           0 :     case OCstoredyn:
    2581             :       {
    2582           0 :         entree *ep = (entree *)operand;
    2583           0 :         pari_printf("storedyn\t%s\n",ep->name);
    2584           0 :         break;
    2585             :       }
    2586           0 :     case OCstorelex:
    2587           0 :       pari_printf("storelex\t%ld\n",operand);
    2588           0 :       break;
    2589           0 :     case OCstoreptr:
    2590           0 :       pari_printf("storeptr\n");
    2591           0 :       break;
    2592           0 :     case OCsimpleptrdyn:
    2593             :       {
    2594           0 :         entree *ep = (entree *)operand;
    2595           0 :         pari_printf("simpleptrdyn\t%s\n",ep->name);
    2596           0 :         break;
    2597             :       }
    2598           0 :     case OCsimpleptrlex:
    2599           0 :       pari_printf("simpleptrlex\t%ld\n",operand);
    2600           0 :       break;
    2601           0 :     case OCnewptrdyn:
    2602             :       {
    2603           0 :         entree *ep = (entree *)operand;
    2604           0 :         pari_printf("newptrdyn\t%s\n",ep->name);
    2605           0 :         break;
    2606             :       }
    2607           0 :     case OCnewptrlex:
    2608           0 :       pari_printf("newptrlex\t%ld\n",operand);
    2609           0 :       break;
    2610           0 :     case OCpushptr:
    2611           0 :       pari_printf("pushptr\n");
    2612           0 :       break;
    2613           0 :     case OCstackgen:
    2614           0 :       pari_printf("stackgen\t%ld\n",operand);
    2615           0 :       break;
    2616           0 :     case OCendptr:
    2617           0 :       pari_printf("endptr\t\t%ld\n",operand);
    2618           0 :       break;
    2619           0 :     case OCprecreal:
    2620           0 :       pari_printf("precreal\n");
    2621           0 :       break;
    2622           0 :     case OCbitprecreal:
    2623           0 :       pari_printf("bitprecreal\n");
    2624           0 :       break;
    2625           0 :     case OCprecdl:
    2626           0 :       pari_printf("precdl\n");
    2627           0 :       break;
    2628           0 :     case OCstoi:
    2629           0 :       pari_printf("stoi\n");
    2630           0 :       break;
    2631           0 :     case OCutoi:
    2632           0 :       pari_printf("utoi\n");
    2633           0 :       break;
    2634           0 :     case OCitos:
    2635           0 :       pari_printf("itos\t\t%ld\n",operand);
    2636           0 :       break;
    2637           0 :     case OCitou:
    2638           0 :       pari_printf("itou\t\t%ld\n",operand);
    2639           0 :       break;
    2640           0 :     case OCtostr:
    2641           0 :       pari_printf("tostr\t\t%ld\n",operand);
    2642           0 :       break;
    2643           0 :     case OCvarn:
    2644           0 :       pari_printf("varn\t\t%ld\n",operand);
    2645           0 :       break;
    2646           0 :     case OCcopy:
    2647           0 :       pari_printf("copy\n");
    2648           0 :       break;
    2649           0 :     case OCcopyifclone:
    2650           0 :       pari_printf("copyifclone\n");
    2651           0 :       break;
    2652           0 :     case OCcompo1:
    2653           0 :       pari_printf("compo1\t\t%s\n",disassemble_cast(operand));
    2654           0 :       break;
    2655           0 :     case OCcompo1ptr:
    2656           0 :       pari_printf("compo1ptr\n");
    2657           0 :       break;
    2658           0 :     case OCcompo2:
    2659           0 :       pari_printf("compo2\t\t%s\n",disassemble_cast(operand));
    2660           0 :       break;
    2661           0 :     case OCcompo2ptr:
    2662           0 :       pari_printf("compo2ptr\n");
    2663           0 :       break;
    2664           0 :     case OCcompoC:
    2665           0 :       pari_printf("compoC\n");
    2666           0 :       break;
    2667           0 :     case OCcompoCptr:
    2668           0 :       pari_printf("compoCptr\n");
    2669           0 :       break;
    2670           0 :     case OCcompoL:
    2671           0 :       pari_printf("compoL\n");
    2672           0 :       break;
    2673           0 :     case OCcompoLptr:
    2674           0 :       pari_printf("compoLptr\n");
    2675           0 :       break;
    2676           0 :     case OCcheckargs:
    2677           0 :       pari_printf("checkargs\t0x%lx\n",operand);
    2678           0 :       break;
    2679           0 :     case OCcheckargs0:
    2680           0 :       pari_printf("checkargs0\t0x%lx\n",operand);
    2681           0 :       break;
    2682           0 :     case OCcheckuserargs:
    2683           0 :       pari_printf("checkuserargs\t%ld\n",operand);
    2684           0 :       break;
    2685           0 :     case OCdefaultlong:
    2686           0 :       pari_printf("defaultlong\t%ld\n",operand);
    2687           0 :       break;
    2688           0 :     case OCdefaultulong:
    2689           0 :       pari_printf("defaultulong\t%ld\n",operand);
    2690           0 :       break;
    2691           0 :     case OCdefaultgen:
    2692           0 :       pari_printf("defaultgen\t%ld\n",operand);
    2693           0 :       break;
    2694           0 :     case OCpackargs:
    2695           0 :       pari_printf("packargs\t%ld\n",operand);
    2696           0 :       break;
    2697           0 :     case OCgetargs:
    2698           0 :       pari_printf("getargs\t\t%ld\n",operand);
    2699           0 :       break;
    2700           0 :     case OCdefaultarg:
    2701           0 :       pari_printf("defaultarg\t%ld\n",operand);
    2702           0 :       break;
    2703           0 :     case OClocalvar:
    2704             :       {
    2705           0 :         entree *ep = (entree *)operand;
    2706           0 :         pari_printf("localvar\t%s\n",ep->name);
    2707           0 :         break;
    2708             :       }
    2709           0 :     case OClocalvar0:
    2710             :       {
    2711           0 :         entree *ep = (entree *)operand;
    2712           0 :         pari_printf("localvar0\t%s\n",ep->name);
    2713           0 :         break;
    2714             :       }
    2715           0 :     case OCexportvar:
    2716             :       {
    2717           0 :         entree *ep = (entree *)operand;
    2718           0 :         pari_printf("exportvar\t%s\n",ep->name);
    2719           0 :         break;
    2720             :       }
    2721           0 :     case OCunexportvar:
    2722             :       {
    2723           0 :         entree *ep = (entree *)operand;
    2724           0 :         pari_printf("unexportvar\t%s\n",ep->name);
    2725           0 :         break;
    2726             :       }
    2727           0 :     case OCcallgen:
    2728             :       {
    2729           0 :         entree *ep = (entree *)operand;
    2730           0 :         pari_printf("callgen\t\t%s\n",ep->name);
    2731           0 :         break;
    2732             :       }
    2733           0 :     case OCcallgen2:
    2734             :       {
    2735           0 :         entree *ep = (entree *)operand;
    2736           0 :         pari_printf("callgen2\t%s\n",ep->name);
    2737           0 :         break;
    2738             :       }
    2739           0 :     case OCcalllong:
    2740             :       {
    2741           0 :         entree *ep = (entree *)operand;
    2742           0 :         pari_printf("calllong\t%s\n",ep->name);
    2743           0 :         break;
    2744             :       }
    2745           0 :     case OCcallint:
    2746             :       {
    2747           0 :         entree *ep = (entree *)operand;
    2748           0 :         pari_printf("callint\t\t%s\n",ep->name);
    2749           0 :         break;
    2750             :       }
    2751           0 :     case OCcallvoid:
    2752             :       {
    2753           0 :         entree *ep = (entree *)operand;
    2754           0 :         pari_printf("callvoid\t%s\n",ep->name);
    2755           0 :         break;
    2756             :       }
    2757           0 :     case OCcalluser:
    2758           0 :       pari_printf("calluser\t%ld\n",operand);
    2759           0 :       break;
    2760           0 :     case OCvec:
    2761           0 :       pari_printf("vec\t\t%ld\n",operand);
    2762           0 :       break;
    2763           0 :     case OCcol:
    2764           0 :       pari_printf("col\t\t%ld\n",operand);
    2765           0 :       break;
    2766           0 :     case OCmat:
    2767           0 :       pari_printf("mat\t\t%ld\n",operand);
    2768           0 :       break;
    2769           0 :     case OCnewframe:
    2770           0 :       pari_printf("newframe\t%ld\n",operand);
    2771           0 :       break;
    2772           0 :     case OCsaveframe:
    2773           0 :       pari_printf("saveframe\t%ld\n", operand);
    2774           0 :       break;
    2775           0 :     case OCpop:
    2776           0 :       pari_printf("pop\t\t%ld\n",operand);
    2777           0 :       break;
    2778           0 :     case OCdup:
    2779           0 :       pari_printf("dup\t\t%ld\n",operand);
    2780           0 :       break;
    2781           0 :     case OCavma:
    2782           0 :       pari_printf("avma\n",operand);
    2783           0 :       break;
    2784           0 :     case OCgerepile:
    2785           0 :       pari_printf("gerepile\n",operand);
    2786           0 :       break;
    2787           0 :     case OCcowvardyn:
    2788             :       {
    2789           0 :         entree *ep = (entree *)operand;
    2790           0 :         pari_printf("cowvardyn\t%s\n",ep->name);
    2791           0 :         break;
    2792             :       }
    2793           0 :     case OCcowvarlex:
    2794           0 :       pari_printf("cowvarlex\t%ld\n",operand);
    2795           0 :       break;
    2796           0 :     case OCsetref:
    2797           0 :       pari_printf("setref\t\t%ld\n",operand);
    2798           0 :       break;
    2799           0 :     case OClock:
    2800           0 :       pari_printf("lock\t\t%ld\n",operand);
    2801           0 :       break;
    2802           0 :     case OCevalmnem:
    2803             :       {
    2804           0 :         entree *ep = (entree *)operand;
    2805           0 :         pari_printf("evalmnem\t%s\n",ep->name);
    2806           0 :         break;
    2807             :       }
    2808             :     }
    2809             :   }
    2810           0 : }
    2811             : 
    2812             : static int
    2813           0 : opcode_need_relink(op_code opcode)
    2814             : {
    2815           0 :   switch(opcode)
    2816             :   {
    2817           0 :   case OCpushlong:
    2818             :   case OCpushgen:
    2819             :   case OCpushgnil:
    2820             :   case OCpushreal:
    2821             :   case OCpushstoi:
    2822             :   case OCpushlex:
    2823             :   case OCstorelex:
    2824             :   case OCstoreptr:
    2825             :   case OCsimpleptrlex:
    2826             :   case OCnewptrlex:
    2827             :   case OCpushptr:
    2828             :   case OCstackgen:
    2829             :   case OCendptr:
    2830             :   case OCprecreal:
    2831             :   case OCbitprecreal:
    2832             :   case OCprecdl:
    2833             :   case OCstoi:
    2834             :   case OCutoi:
    2835             :   case OCitos:
    2836             :   case OCitou:
    2837             :   case OCtostr:
    2838             :   case OCvarn:
    2839             :   case OCcopy:
    2840             :   case OCcopyifclone:
    2841             :   case OCcompo1:
    2842             :   case OCcompo1ptr:
    2843             :   case OCcompo2:
    2844             :   case OCcompo2ptr:
    2845             :   case OCcompoC:
    2846             :   case OCcompoCptr:
    2847             :   case OCcompoL:
    2848             :   case OCcompoLptr:
    2849             :   case OCcheckargs:
    2850             :   case OCcheckargs0:
    2851             :   case OCcheckuserargs:
    2852             :   case OCpackargs:
    2853             :   case OCgetargs:
    2854             :   case OCdefaultarg:
    2855             :   case OCdefaultgen:
    2856             :   case OCdefaultlong:
    2857             :   case OCdefaultulong:
    2858             :   case OCcalluser:
    2859             :   case OCvec:
    2860             :   case OCcol:
    2861             :   case OCmat:
    2862             :   case OCnewframe:
    2863             :   case OCsaveframe:
    2864             :   case OCdup:
    2865             :   case OCpop:
    2866             :   case OCavma:
    2867             :   case OCgerepile:
    2868             :   case OCcowvarlex:
    2869             :   case OCsetref:
    2870             :   case OClock:
    2871           0 :     break;
    2872           0 :   case OCpushvar:
    2873             :   case OCpushdyn:
    2874             :   case OCstoredyn:
    2875             :   case OCsimpleptrdyn:
    2876             :   case OCnewptrdyn:
    2877             :   case OClocalvar:
    2878             :   case OClocalvar0:
    2879             :   case OCexportvar:
    2880             :   case OCunexportvar:
    2881             :   case OCcallgen:
    2882             :   case OCcallgen2:
    2883             :   case OCcalllong:
    2884             :   case OCcallint:
    2885             :   case OCcallvoid:
    2886             :   case OCcowvardyn:
    2887             :   case OCevalmnem:
    2888           0 :     return 1;
    2889             :   }
    2890           0 :   return 0;
    2891             : }
    2892             : 
    2893             : static void
    2894           0 : closure_relink(GEN C, hashtable *table)
    2895             : {
    2896           0 :   const char *code = closure_codestr(C);
    2897           0 :   GEN oper = closure_get_oper(C);
    2898           0 :   GEN fram = gel(closure_get_dbg(C),3);
    2899             :   long i, j;
    2900           0 :   for(i=1;i<lg(oper);i++)
    2901           0 :     if (oper[i] && opcode_need_relink((op_code)code[i]))
    2902           0 :       oper[i] = (long) hash_search(table,(void*) oper[i])->val;
    2903           0 :   for (i=1;i<lg(fram);i++)
    2904           0 :     for (j=1;j<lg(gel(fram,i));j++)
    2905           0 :       if (mael(fram,i,j))
    2906           0 :         mael(fram,i,j) = (long) hash_search(table,(void*) mael(fram,i,j))->val;
    2907           0 : }
    2908             : 
    2909             : void
    2910           0 : gen_relink(GEN x, hashtable *table)
    2911             : {
    2912           0 :   long i, lx, tx = typ(x);
    2913           0 :   switch(tx)
    2914             :   {
    2915           0 :     case t_CLOSURE:
    2916           0 :       closure_relink(x, table);
    2917           0 :       gen_relink(closure_get_data(x), table);
    2918           0 :       if (lg(x)==8) gen_relink(closure_get_frame(x), table);
    2919           0 :       break;
    2920           0 :     case t_LIST:
    2921           0 :       if (list_data(x)) gen_relink(list_data(x), table);
    2922           0 :       break;
    2923           0 :     case t_VEC: case t_COL: case t_MAT: case t_ERROR:
    2924           0 :       lx = lg(x);
    2925           0 :       for (i=lontyp[tx]; i<lx; i++) gen_relink(gel(x,i), table);
    2926             :   }
    2927           0 : }
    2928             : 
    2929             : static void
    2930           0 : closure_unlink(GEN C)
    2931             : {
    2932           0 :   const char *code = closure_codestr(C);
    2933           0 :   GEN oper = closure_get_oper(C);
    2934           0 :   GEN fram = gel(closure_get_dbg(C),3);
    2935             :   long i, j;
    2936           0 :   for(i=1;i<lg(oper);i++)
    2937           0 :     if (oper[i] && opcode_need_relink((op_code) code[i]))
    2938             :     {
    2939           0 :       long n = pari_stack_new(&s_relocs);
    2940           0 :       relocs[n] = (entree *) oper[i];
    2941             :     }
    2942           0 :   for (i=1;i<lg(fram);i++)
    2943           0 :     for (j=1;j<lg(gel(fram,i));j++)
    2944           0 :       if (mael(fram,i,j))
    2945             :       {
    2946           0 :         long n = pari_stack_new(&s_relocs);
    2947           0 :         relocs[n] = (entree *) mael(fram,i,j);
    2948             :       }
    2949           0 : }
    2950             : 
    2951             : static void
    2952          16 : gen_unlink(GEN x)
    2953             : {
    2954          16 :   long i, lx, tx = typ(x);
    2955          16 :   switch(tx)
    2956             :   {
    2957           0 :     case t_CLOSURE:
    2958           0 :       closure_unlink(x);
    2959           0 :       gen_unlink(closure_get_data(x));
    2960           0 :       if (lg(x)==8) gen_unlink(closure_get_frame(x));
    2961           0 :       break;
    2962           4 :     case t_LIST:
    2963           4 :       if (list_data(x)) gen_unlink(list_data(x));
    2964           4 :       break;
    2965           0 :     case t_VEC: case t_COL: case t_MAT: case t_ERROR:
    2966           0 :       lx = lg(x);
    2967           0 :       for (i = lontyp[tx]; i<lx; i++) gen_unlink(gel(x,i));
    2968             :   }
    2969          16 : }
    2970             : 
    2971             : GEN
    2972          12 : copybin_unlink(GEN C)
    2973             : {
    2974          12 :   long i, l , n, nold = s_relocs.n;
    2975             :   GEN v, w, V, res;
    2976          12 :   if (C)
    2977           8 :     gen_unlink(C);
    2978             :   else
    2979             :   { /* contents of all variables */
    2980           4 :     long v, maxv = pari_var_next();
    2981          44 :     for (v=0; v<maxv; v++)
    2982             :     {
    2983          40 :       entree *ep = varentries[v];
    2984          40 :       if (!ep || !ep->value) continue;
    2985           8 :       gen_unlink((GEN)ep->value);
    2986             :     }
    2987             :   }
    2988          12 :   n = s_relocs.n-nold;
    2989          12 :   v = cgetg(n+1, t_VECSMALL);
    2990          12 :   for(i=0; i<n; i++)
    2991           0 :     v[i+1] = (long) relocs[i];
    2992          12 :   s_relocs.n = nold;
    2993          12 :   w = vecsmall_uniq(v); l = lg(w);
    2994          12 :   res = cgetg(3,t_VEC);
    2995          12 :   V = cgetg(l, t_VEC);
    2996          12 :   for(i=1; i<l; i++)
    2997             :   {
    2998           0 :     entree *ep = (entree*) w[i];
    2999           0 :     gel(V,i) = strtoGENstr(ep->name);
    3000             :   }
    3001          12 :   gel(res,1) = vecsmall_copy(w);
    3002          12 :   gel(res,2) = V;
    3003          12 :   return res;
    3004             : }
    3005             : 
    3006             : /* e = t_VECSMALL of entree *ep [ addresses ],
    3007             :  * names = t_VEC of strtoGENstr(ep.names),
    3008             :  * Return hashtable : ep => is_entry(ep.name) */
    3009             : hashtable *
    3010           0 : hash_from_link(GEN e, GEN names, int use_stack)
    3011             : {
    3012           0 :   long i, l = lg(e);
    3013           0 :   hashtable *h = hash_create_ulong(l-1, use_stack);
    3014           0 :   if (lg(names) != l) pari_err_DIM("hash_from_link");
    3015           0 :   for (i = 1; i < l; i++)
    3016             :   {
    3017           0 :     char *s = GSTR(gel(names,i));
    3018           0 :     hash_insert(h, (void*)e[i], (void*)fetch_entry(s));
    3019             :   }
    3020           0 :   return h;
    3021             : }
    3022             : 
    3023             : void
    3024           0 : bincopy_relink(GEN C, GEN V)
    3025             : {
    3026           0 :   pari_sp av = avma;
    3027           0 :   hashtable *table = hash_from_link(gel(V,1),gel(V,2),1);
    3028           0 :   gen_relink(C, table);
    3029           0 :   set_avma(av);
    3030           0 : }

Generated by: LCOV version 1.16