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

Generated by: LCOV version 2.0-1