/*******************************************************************/
/*******************************************************************/
/*                                                                 */
/*              PROGRAMME D'INITIALISATION DU SYSTEME              */
/*                    ET TRAITEMENT DES ERREURS                    */
/*                                                                 */
/*                       copyright Babe Cool                       */
/*                                                                 */
/*******************************************************************/
/*******************************************************************/
/* $Id: init.c,v 2.0.0.2 1997/12/14 20:11:49 karim Exp karim $ */

#include <string.h>
#include "genpari.h"
#include "anal.h"

/*      Variables statiques communes :         */
FILE    *outfile, *errfile, *logfile, *infile;
GEN     *polun, *polx;
GEN     gnil, gzero, gun, gdeux, ghalf, polvar, gi, RAVYZARC;
GEN     gpi=NULL, geuler=NULL, bernzone=NULL;
GEN     primetab; /* private primetable */
byteptr diffptr;
char    current_logfile[128], current_psfile[128], *current_function;
char    gp_colors[c_LAST];
int     disable_color = 1, added_newline = 1;

int     functions_tblsz = 135; /* size of functions_hash          */
entree  **varentries;

jmp_buf environnement;
long    *ordvar;
long    DEBUGLEVEL, DEBUGMEM, pari_randseed;
long    try_to_recover, compatible;
long    prec,precdl,defaultpadicprecision;
ulong   init_opts = INIT_JMPm | INIT_SIGm;
ulong   top, bot, avma, memused;

void *foreignHandler; 	              /* Handler for foreign commands.   */
char foreignExprSwitch = 3; 	      /* Just some unprobable char.      */
GEN  (*foreignExprHandler)(char*);    /* Handler for foreign expressions.*/
long (*foreignAutoload)(char*, long); /* Autoloader                      */
void (*foreignFuncFree)(entree *);    /* How to free external entree.    */

GEN  (*gp_history_fun)(long, long, char *, char *);
void  initout(void);

/*********************************************************************/
/*                                                                   */
/*                     INITIALISATION DU SYSTEME                     */
/*                                                                   */
/*********************************************************************/
static long next_bloc;
static GEN cur_bloc=NULL; /* current bloc in bloc list */
static long *universal_constants;

static void
pari_sighandler(int sig)
{
  char *msg;
  switch(sig)
  {
    case SIGINT:
      if (infile != stdin)
      {
	int file_depth = switchin(NULL);
	if (file_depth == -1) { freeall(); exit(0); }
      }
      msg="user interrupt";
      break;

    case SIGSEGV:
      msg="segmentation fault: bug in PARI or calling program";
      break;

#ifdef SIGBUS
    case SIGBUS:
      msg="bus error: bug in PARI or calling program";
      break;
#endif
  }
  signal(sig,pari_sighandler);
  err(talker,msg);
}

/* Initialize hashtable */
static void
init_hashtable(entree **table, int tblsz)
{
  entree *ep, *ep1, *last;
  long i;
  
  for (i = 0; i < tblsz; i++)
  {
    last = NULL; ep = table[i]; table[i] = NULL;
    for ( ; ep; ep = ep1)
    {
      ep1 = ep->next; 
      if (EpVALENCE(ep) == EpVAR) /* keep this one */
      {
        if (last)
          last->next = ep;
        else
          table[i] = ep;
        last = ep; last->next = NULL;
      }
      else freeep(ep); 
    }
  }
}

static void
fill_hashtable(entree **table, entree *ep, char **helpmessage)
{
  long n;

  for ( ; ep->name; ep++)
  {
    EpSETSTATIC(ep);
    ep->help = *helpmessage++;
    n = hashvalue(ep->name);
    ep->next = table[n]; table[n] = ep;
    ep->args = NULL;
  }
}

void
init_defaults(int force)
{
  static int done=0;

  if (done && !force) return;
  done = 1;

#ifdef LONG_IS_64BIT
  prec=4;
#else
  prec=5;
#endif

  precdl = defaultpadicprecision = 16;
  compatible = NONE;
  DEBUGLEVEL = 0;
  DEBUGMEM   = 0;
  pari_randseed = 1;

  strcpy(current_psfile,"pari.ps");
  strcpy(current_logfile,"pari.log");

  infile = stdin; outfile = stdout;
  errfile = stderr; logfile = NULL;
  initout(); next_bloc=0;
}

/* does elt belong to list, after position start (excluded) ? */
static int
list_isin(void **list, void *elt, int start)
{
  long indelt=0;

  if (list)
  {
    while (*list)
    {
      if (indelt>start && *list==elt) return indelt;
      list++; indelt++;
    }
  }
  return -1;
}

static void
list_prepend(void ***listptr, void *elt)
{
  void **list=*listptr;
  long nbelt=0;

  if (list)
    while (list[nbelt]) nbelt++;
  list = (void **) gpmalloc(sizeof(void *)*(nbelt+2));
  list[0]=elt;
  if (nbelt)
  {
    memcpy(list+1,*listptr,nbelt*sizeof(void *));
    free(*listptr);
  }
  list[nbelt+1]=NULL; *listptr=list;
}

/* Load modlist in hashtable hash. If force == 0, do not load twice the 
 * same list in the same hashtable, which would only destroy user variables.
 * As it stands keep a complete history (instead of most recent changes).
 */
int
gp_init_entrees(module *modlist, entree **hash, int force)
{
  static void **oldmodlist=NULL, **oldhash=NULL;

  if (!force) 
  {
    const long indhash = list_isin(oldhash,(void *)hash,-1);
    if (indhash != -1 && oldmodlist[indhash]==modlist) return 0;
  }
  /* record the new pair (hash,modlist) */
  list_prepend(&oldmodlist,(void *)modlist);
  list_prepend(&oldhash,(void *)hash);

  init_hashtable(hash,functions_tblsz);
  while (modlist && modlist->func)
  {
    fill_hashtable(hash, modlist->func, modlist->help);
    modlist++;
  }
  return (hash == functions_hash);
}

module *pari_modules    = NULL;
module *pari_oldmodules = NULL;
entree **functions_hash = NULL;
entree **funct_old_hash = NULL;

/* add to modlist the functions in func, with helpmsg help */
void
pari_addfunctions(module **modlist_p, entree *func, char **help)
{
  module *modlist = *modlist_p;
  int nbmodules = 0;

  while (modlist && modlist->func) { nbmodules++; modlist++; }
  modlist = *modlist_p;
  *modlist_p = (module*) gpmalloc(sizeof(module)*(nbmodules+2));
  if (nbmodules)
  {
    memcpy(1+ *modlist_p, modlist, sizeof(module)*nbmodules);
    free(modlist);
  }
  modlist = *modlist_p;
  modlist->func = func;
  modlist->help = help;

  modlist += nbmodules+1;
  modlist->func = NULL;
  modlist->help = NULL;
}

/* BYTES_IN_LONG*ceil(a/BYTES_IN_LONG) */
#define fix_size(a) ((a)+BYTES_IN_LONG - ((((a)-1) & (BYTES_IN_LONG-1)) + 1))

/* initialise les donnees de la bibliotheque PARI. Peut être précédée d'un
 * appel à pari_addfunctions si on ajoute d'autres fonctions au pool de base.
 */
void
pari_init(long parisize, long maxprime)
{
  long n;
  GEN p;

  init_defaults(0); try_to_recover=1;
  if (INIT_JMP && setjmp(environnement))
  {
    fprintferr("\n  ***   Error in the PARI system. End of program.\n");
    exit(1);
  }
  if (INIT_SIG)
  {
#ifdef SIGBUS
    signal(SIGBUS,pari_sighandler);
#endif
    signal(SIGINT,pari_sighandler);
    signal(SIGSEGV,pari_sighandler);
  }

  parisize = fix_size(parisize);
  diffptr = initprimes(maxprime);
#if __MWERKS__
  {
    OSErr resultCode;
    Handle newHand = MFTempNewHandle(parisize,&resultCode);

    if (!newHand) err(memer);
    HLock(newHand);
    bot = (long)*newHand;
  }
#else
  bot = (long) gpmalloc(parisize);
#endif
  top = avma = memused = bot+parisize;

  varentries = (entree**) gpmalloc((MAXVARN+1)*sizeof(entree*));
  polvar = (GEN) gpmalloc((MAXVARN+1)*sizeof(long));
  ordvar = (GEN) gpmalloc((MAXVARN+1)*sizeof(long));
  polx  = (GEN*) gpmalloc((MAXVARN+1)*sizeof(GEN));
  polun = (GEN*) gpmalloc((MAXVARN+1)*sizeof(GEN));
  polvar[0] = evaltyp(t_VEC) | evallg(1);
  for (n=0; n <= MAXVARN; n++) ordvar[n] = n;

 /* 2 (gnil) + 2 (gzero) + 
  * 3 (gun) + 3 (gdeux) + 3 (half) + 3 (gi)
  */
  p = universal_constants = (long *) gpmalloc(16*sizeof(long));
  
  gzero = p; p+=2; gnil = p; p+=2;
  gzero[0] = gnil[0] = evaltyp(t_INT) | evallg(2);
  gzero[1] = gnil[1] = evallgefint(2);
  
  gun = p; p+=3; gdeux = p; p+=3;
  gun[0] = gdeux[0] = evaltyp(t_INT) | evallg(3);
  gun[1] = gdeux[1] = evalsigne(1) | evallgefint(3);
  gun[2] = 1; gdeux[2]= 2;

  ghalf = p; p+=3; gi = p; p+=3;
  ghalf[0] = evaltyp(t_FRAC) | evallg(3);
  ghalf[1] = un;
  ghalf[2] = deux;
  gi[0] = evaltyp(t_COMPLEX) | evallg(3);
  gi[1] = zero;
  gi[2] = un;
  fetch_var(); /* create polx/polun[MAXVARN] */

  primetab = (GEN) gpmalloc((NUMPRTBELT+2)*sizeof(long));
  primetab[0] = evaltyp(t_VEC) | evallg(1);

  pari_addfunctions(&pari_modules, functions_basic,helpmessages_basic);
  functions_hash = (entree **) gpmalloc(sizeof(entree*)*functions_tblsz);
  for (n = 0; n < functions_tblsz; n++) functions_hash[n] = NULL;

  pari_addfunctions(&pari_oldmodules, oldfonctions,oldhelpmessage);
  funct_old_hash = (entree **) gpmalloc(sizeof(entree*)*functions_tblsz);
  for (n = 0; n < functions_tblsz; n++) funct_old_hash[n] = NULL;
  gp_init_entrees(pari_oldmodules, funct_old_hash, 1);
 
  if (new_fun_set)
    gp_init_entrees(pari_modules, functions_hash, 1);
  else
    gp_init_entrees(pari_oldmodules, functions_hash, 1);
  gp_history_fun = NULL;
  manage_var(2,NULL); /* init nvar */
  reorder(NULL); lisexpr("x");
}

void
freeall()
{
  long i;
  entree *ep,*ep1;

  free((void*)varentries); free((void*)ordvar); free((void*)polvar); 
  free((void*)polx[MAXVARN]); free((void*)polx); free((void*)polun);
  free((void*)primetab);
  free((void*)universal_constants);

  for (i = 0; i < functions_tblsz; i++)
    for (ep = functions_hash[i]; ep; ep = ep1)
    {
      ep1 = ep->next; freeep(ep);
    }
  while (cur_bloc) { unsetisclone(cur_bloc); killbloc(cur_bloc); }
  free((void *)functions_hash);
  free((void *)bot); free((void *)diffptr);

  while (delete_var()) /* empty */;
  if (gp_history_fun)
    gp_history_fun(0,-2,NULL,NULL);
}

GEN
getheap()
{
  long m=0,l=0;
  GEN x;

  for (x = cur_bloc; x; x = (GEN)x[-3]) 
  {
    m++; l+=4;
    if (! x[0]) /* user function */
      l += (strlen((char *)(x+sizeof(entree*)))) / sizeof(long);
    else        /* GEN */
      l += taille(x);
  }
  x=cgetg(3,t_VEC); x[1]=lstoi(m); x[2]=lstoi(l);
  return x;
}

long
marklist(void)
{
  return next_bloc;
}

/* Return x, where:
 * x[-4]: adress of next bloc
 * x[-3]: adress of preceding bloc.
 * x[-2]: number of allocated blocs.
 * x[-1]: original value of x
 * x[0..n-1]: malloc-ed memory.
 */
GEN
newbloc(long n)
{
  long *x = (long *) gpmalloc((n+4)*sizeof(long));

  *x++ = 0; /* the NULL address */
  *x++ = (long)cur_bloc;
  *x++ = next_bloc++;
  *x++ = 0; /* the NULL address */
  if (n)
    *x = 0; /* initialize first cell to 0. See killbloc */
  else
    if (DEBUGMEM)
      err(warner,"mallocing NULL object in newbloc");
  if (cur_bloc) cur_bloc[-4] = (long)x;
  return cur_bloc = x;
}

void
killbloc(GEN x)
{
  long tx,lx,l,i,j;
  GEN p1;

  if (!x || isonstack(x)) return;
  if (x[-4]) ((GEN)x[-4])[-3] = x[-3]; else cur_bloc = (GEN)x[-3];
  if (x[-3]) ((GEN)x[-3])[-4] = x[-4];
  tx=typ(x); /* if x is not a GEN, we will have tx=0 */
  if (is_vec_t(tx))
  {
    lx = lg(x);
    for (i=1;i<lx;i++)
    {
      p1=(GEN)x[i];
      if (isclone(p1)) killbloc(p1);
    }
  }
  else if (tx==t_MAT)
  {
    lx = lg(x);
    if (lx>1)
    {
      l=lg(x[1]);
      if (l>1)
        for (i=1;i<lx;i++)
          for (j=1;j<l;j++)
          {
            p1=gmael(x,i,j);
            if (isclone(p1)) killbloc(p1);
          }
    }
  }
  else if (tx==t_LIST)
  {
    lx = lgef(x);
    for (i=2;i<lx;i++)
    {
      p1=(GEN)x[i];
      if (isclone(p1)) killbloc(p1);
    }
  }
  unsetisclone(x); free((void *)(x-4));
}

/*******************************************************************/
/*                                                                 */
/*                       TRAITEMENT DES ERREURS                    */
/*                                                                 */
/*******************************************************************/

/* Outputs a "beautiful" error message.
 *   msg is errmessage to print.
 *   s points to the offending chars.
 *   entry tells how much we can go back from s[0].
 */
static void
errcontext(char *msg, char *s, char *entry)
{
  int i, len2, past = (s-entry);
  char *t, *dots = "", str[256], str2[21];

  if (past < 0) past=0;

  if (past && s[-1] == '\n') /* can only happen in the middle of a string */
  {
    while (past && isspace(s[-1])) { s--; past--; }
  }
  if (past>25) { dots="..."; past=25; }
  sprintf(str, "%s%s", msg, dots);
  pariputs(str); t = str+strlen(str);
  strncpy(t, s - past, past); t[past]=0;
  pariputs(t); t += strlen(t);

  strncpy(str2,s,20); str2[20]=0; /* in case strlen(s) > 19 */
  len2=strlen(str2); str2[len2--]=0;
  /* the following comes from the timer in gp, i.e. # */
  if (str2[len2]=='\n') str2[len2--]=0;
  pariputs(str2); pariputc('\n');

  while (t > str)
  {
    if (*--t == '\n') break;
    pariputc(' ');
  }
  pariputc('^');
  for (i=0; i<len2; i++) pariputc('-');
  pariputc('\n');
}

void
err_recover(long numerr)
{
  outfile=stdout; errfile=stderr;
  fprintferr("\n"); flusherr();
  if (pariErr->die) pariErr->die();
  if (environnement && try_to_recover) longjmp(environnement, numerr);
  exit(1);
}

#define op_err(str,x,op,y) (fprintferr("%s %s %s %s.",(str),(x),(op),(y)))

VOLATILE void
err(long numerr, ...)
{
  char str[80], *ch1, *ch2, ret = 0;
  PariOUT *out = pariOut;
  va_list poer;
   
  va_start(poer,numerr);
  if (!added_newline) pariputc('\n');
  pariflush(); pariOut = pariErr;
  pariflush(); term_color(c_ERR);

  sprintf(str,"  ***   %s",errmessage[numerr]);
  switch (numerr)
  {
    case arrayer1: case caracer1: case caseer2: case caseer: case expter1:
    case killer1: case recter1: case referer1: case referer2:
    case trucer1: case varer1: case vectmater1:
      strcat(str,": ");
      ch1=va_arg(poer,char *); ch2=va_arg(poer,char *);
      errcontext(str,ch1,ch2); break;

    case paramer1: case nparamer1:
      strcat(str,":\n    ");
      ch1=va_arg(poer,char *); ch2=va_arg(poer,char *);
      errcontext(str,ch1,ch2); break;

    case openfiler:
      strcat(str," ");
      strcat(str, va_arg(poer,char*));
      strcat(str," file: ");
      ch1 = va_arg(poer,char *);
      errcontext(str,ch1,ch1); break;

    case talker2:
      strcat(str,va_arg(poer, char*));
      ch1=va_arg(poer,char *); ch2=va_arg(poer,char *);
      errcontext(str,ch1,ch2); break;

   case member:
      strcat(str,va_arg(poer, char*)); strcat(str,": ");
      ch1=va_arg(poer,char *); ch2=va_arg(poer,char *);
      errcontext(str,ch1,ch2); break;

/* no context for these */
    case errpile:
      fprintferr(str); fprintferr("\n");
      allocatemoremem(0); break;

    case flagerr:
      fprintferr(str);
      fprintferr(" %s.",current_function); break;

    case impl:
      fprintferr(str); ch1=va_arg(poer, char*);
      fprintferr(" %s is not yet implemented.",ch1); break;

    case talker:
      fprintferr(str); ch1=va_arg(poer, char*);
      vpariputs(ch1,poer); fprintferr(".\n"); break;

    case breaker: case typeer: case mattype1: case overwriter:
    case accurer: case infprecer: case negexper: case polrationer:
    case funder2: case constpoler: case notpoler: case redpoler:
    case zeropoler:
      fprintferr(str);
      fprintferr(" %s.",va_arg(poer, char*));
      break; 

    case bugparier:
      fprintferr(str);
      fprintferr(" %s, please report",va_arg(poer, char*));
      break; 
      
    case assigneri: case assignerf:
      ch1 = va_arg(poer, char*);
      op_err(str,ch1,"-->",va_arg(poer, char*)); break; 
      
    case gadderi: case gadderf:
      ch1 = va_arg(poer, char*);
      op_err(str,ch1,"+",va_arg(poer, char*)); break; 

    case gmuleri: case gmulerf:
      ch1 = va_arg(poer, char*);
      op_err(str,ch1,"*",va_arg(poer, char*)); break; 

    case gdiveri: case gdiverf:
      ch1 = va_arg(poer, char*);
      op_err(str,ch1,"/",va_arg(poer, char*)); break; 

    /* the following four are only warnings (they return) */
    case warnmem:
      fprintferr(str);
      fprintferr(" %s().\n",va_arg(poer,char*)); 
      flusherr(); ret = 1; break;

    case warner:
      fprintferr(str); ch1=va_arg(poer, char*);
      vpariputs(ch1,poer); fprintferr(".\n"); 
      flusherr(); ret = 1; break;

    case warnprec:
      fprintferr(str);
      vpariputs(" %s; new prec = %ld\n",poer);
      flusherr(); ret = 1; break;

    default:
      fprintferr(str);
  }
  term_color(c_NONE); va_end(poer);
  pariOut = out; if (ret) return;
  err_recover(numerr); exit(1); /* not reached */
}
#undef op_err

/* ep->value = initial value. EpVAR (monomial, return) or EpNEW (kill) */
static entree*
check_then_next(entree *ep, long n)
{
  entree *ep2;
  if (EpVALENCE(ep) == EpVAR) return ep->next;
  if (ep == functions_hash[n])
  {
    functions_hash[n] = ep->next;
    freeep(ep); return functions_hash[n];
  }
  ep2 = functions_hash[n];
  while (ep2->next != ep) ep2 = ep2->next;
  ep2->next = ep->next;
  freeep(ep); return ep2->next;
}

void kill_entree_object(entree *ep);

void
recover(long listloc)
{
  long n,v;
  GEN x;
  entree *ep;

  for (n = 0; n < functions_tblsz; n++)
    for (ep = functions_hash[n]; ep; )
    {
      v = EpVALENCE(ep);
      if (EpUSER <= v && v < EpINSTALL) /* user objects */
      {
        /* restore genuine bloc variable if need be */
        while (is_temp_value(ep, ep->value))
        {
          if (ep->args) pop_val(ep);
          else
          {
            ep->value = (void*) initial_value(ep);
            break;
          }
        }
        x = (GEN)ep->value; /* x is guaranteed to be a bloc here */
        if (x == (GEN) initial_value(ep))
        {
          ep = check_then_next(ep,n);
          continue;
        }
        if (x[-2] >= listloc && x[-2] < next_bloc)
        {
          kill_entree_object(ep);
          continue;
        }
      }
      ep = ep->next;
    }
#if 0 
 /* This causes SEGV on lists and GP-2.0 vectors: internal component is
  * destroyed while global object is not updated. Two solutions: 
  *  - comment it out: should not be a big memory problem except for huge
  *  vec. components. Has the added advantadge that the results computed so
  *  far are not lost.
  *
  *  - tag every variable whose component has been modified in the last
  *  cycle. Untag it at the begining of each cycle. Maybe this should be
  *  done. But do we really want to destroy a huge global vector if one of
  *  its components was modified before the error ??? (remember, we don't
  *  copy the whole thing anymore). K.B.
  */
  {
    GEN y;
    for (x = cur_bloc; x && x[-2] >= listloc; x = y)
    {
      y = (GEN)x[-3];
      if (x != gpi && x != geuler && x != bernzone) killbloc(x);
    }
  }
#endif
}

/* Takes an array of pointers to GENs, of length n. Copies all
 * objects to contiguous locations and cleans up the stack between
 * av and avma.
 */
void
gerepilemany(long av, GEN* gptr[], long n)
{
  const long tetpil = avma;
  long i, dec;
  GEN *g1;

  /* copy objects */
  for (i=0; i<n; i++) { g1 = gptr[i]; *g1 = gcopy(*g1); }
  dec = lpile(av, tetpil, 0) >> TWOPOTBYTES_IN_LONG;

  /* update addresses */
  for (i=0; i<n; i++) { g1 = gptr[i]; *g1 += dec; }
}

/* Takes an array of pointers to GENs, of length n.
 * Cleans up the stack between av and tetpil, updating those GENs.
 */
void
gerepilemanysp(long av, long tetpil, GEN* gptr[], long n)
{
  const long av2 = avma, dec = lpile(av, tetpil, 0) >> TWOPOTBYTES_IN_LONG;
  long i;
  GEN *g1;

  for (i=0; i<n; i++)
  {
    g1 = gptr[i];
    if (*g1 < (GEN)tetpil)
      if (*g1 >= (GEN)av2) *g1 += dec;     /* Update address if in stack */
      else if (*g1 >=(GEN)av) err(gerper); /* Check if pointer got lost  */
  }
}

/* Takes an array of GENs (casted to longs), of length n. Cleans up the
 * stack between av and tetpil, and update those GENs.
 */
void
gerepilemanyvec(long av, long tetpil, long *g, long n)
{
  const long av2 = avma, dec = lpile(av, tetpil, 0);
  long i;

  for (i=0; i<n; i++,g++)
    if (*g < tetpil)
    {
      if (*g >= av2 ) *g += dec;     /* Update addresses if in stack */
      else if (*g >=av) err(gerper); /* Check if pointer got lost */
    }
}

GEN
gerepileupto(long av, GEN q)
{
  if (!isonstack(q)) { avma=av; return q; } /* universal object */
  /* empty garbage */
  if (av <= (long)q) return q;
  /* The garbage is only empty when av==q. It's probably a mistake if 
   * av < q. But "temporary variables" from sumiter are a problem since
   * ep->values are returned as-is by identifier() and they can be in the
   * stack: if we put a gerepileupto in lisseq(), we get an error. Maybe add,
   * if (DEBUGMEM) err(warner,"av>q in gerepileupto") ???
   */

  /* Beware: (long)(q+i) --> ((long)q)+i*sizeof(long) */
  return gerepile(av, (long) (q+lg(q)), q);
}

GEN
gerepile(long av, long tetpil, GEN q)
{
  long avmb, dec = av - tetpil;
  GEN ll,a,b;

  if (dec==0) return q;
  if (dec<0) err(talker,"lbot>ltop in gerepile");

  if (!q || (q<(GEN)tetpil && q>=(GEN)avma) )
    q = (GEN) (((long)q) + dec);

#if 0 /* slower than the two following lines */
  avmb = avma+dec; ll = (GEN) avmb;
  memmove((char *) avmb, (char *) avma, tetpil-avma);
#endif

  for (ll=(GEN)av, a=(GEN)tetpil; a > (GEN)avma; ) *--ll= *--a;
  avmb = (long) ll;

  while (ll < (GEN)av)
  {
    const long tl=typ(ll);

    if (! is_recursive_t(tl)) { ll+=lg(ll); continue; }
    switch(tl)
    {
      case t_POL: case t_LIST:
	a=ll+lontyp[tl]; b=ll+lgef(ll); ll+=lg(ll); break;

      case t_SER:
        if (!signe(ll)) { ll+=lg(ll); continue; } /* fall through */
      default:
	a=ll+lontyp[tl]; ll+=lg(ll); b=ll;
    }
    for (  ; a<b; a++)
      if (*a < av && *a >= avma)
	if (*a < tetpil) *a += dec; else err(gerper);
  }
  avma = avmb; return q;
}

void
allocatemoremem(ulong newsize)
{
  long sizeold = top - bot, newbot;

  if (!newsize)
  {
    newsize = sizeold << 1;
    err(warner,"doubling stack size; new stack = %ld",newsize);
  }
  else
  {
    if ((long)newsize < 0)
      err(talker,"required stack memory too small");
    newsize = fix_size(newsize);
  }
  /* can't do bot = malloc directly, in case we lack memory */
  newbot = (long) gpmalloc(newsize);
  free((void*)bot); bot = newbot;
  memused = avma = top = bot + newsize;
}

/* alternate stack management routine */
stackzone *
switch_stack(stackzone *z, long n)
{
  if (!z)
  { /* create parallel stack */
    long size = n*sizeof(long) + sizeof(stackzone);
    z = (stackzone*) gpmalloc(size);
    z->zonetop = ((long)z) + size;
    return z;
  }

  if (n)
  { /* switch to parallel stack */
    z->bot     = bot;
    z->top     = top;
    z->avma    = avma;
    z->memused = memused;
    bot     = (long) (z+1);
    top     = z->zonetop;
    avma    = top;
    memused = 0;
  }
  else
  { /* back to normalcy */
    bot     = z->bot;
    top     = z->top;
    avma    = z->avma;
    memused = z->memused;
  }
  return NULL;
}

char*
gpmalloc(size_t bytes)
{
  char *tmp;

  if (bytes)
  {
    tmp = (char *) malloc(bytes);
    if (!tmp) err(memer);
    return tmp;
  }
  if (DEBUGMEM)
    err(warner,"mallocing NULL object");
  return NULL;
}

#if __MWERKS__
static void *
macrealloc(void *p, size_t newsize, size_t oldsize)
{
  char *q = gpmalloc(newsize), *qq = q, *pp = p;
  int l = newsize > oldsize ? oldsize : newsize;

  while (l--) *qq++ = *pp++;
  free(p); return q;
}
#endif

char*
gprealloc(void *pointer, size_t newsize, size_t oldsize)
{
  char *tmp;

  if (!pointer) tmp = (char *) malloc(newsize);
#if __MWERKS__
  else tmp = (char *) macrealloc(pointer,newsize,oldsize);
#else
  else tmp = (char *) realloc(pointer,newsize);
#endif
  if (!tmp) err(memer,oldsize);
  return tmp;
}

GEN
allocatemem(unsigned long newsize)
{
#if __MWERKS__
  err(impl,"allocatemem");
#endif
  allocatemoremem(newsize);
  longjmp(environnement,errpile);
  return NULL; /* not reached */
}

#ifdef MEMSTEP
void
checkmemory(long z)
{
  if (z<bot) err(errpile);
  if (DEBUGMEM)
  {
    if (memused > z+MEMSTEP)
    {
      fprintferr("...%4.0lf Mbytes used\n",(top-z)/1048576.);
      memused=z;
    }
    else if (avma > MEMSTEP && memused < avma-MEMSTEP)
    {
      fprintferr("...%4.0lf Mbytes used\n",(top-avma)/1048576.);
      memused=z;
    }
    else if (memused < avma) memused=avma;
  }
  avma=z;
}
#endif

/*******************************************************************/
/*                                                                 */
/*                               TIMER                             */
/*                                                                 */
/*******************************************************************/
#define MAX_TIMER 3

#ifdef macintosh
# include <Events.h>
  static long
  timer_proto(int i)
  {
    static long oldticks[MAX_TIMER];
    long ticks = TickCount(), delay = ticks - oldticks[i];

    oldticks[i] = ticks;
    return 50 * delay / 3;
  }
#elif USE_TIMES

# define _INCLUDE_POSIX_SOURCE
# include <sys/times.h>
# include <sys/time.h>
  static long
  timer_proto(int i)
  {
    static clock_t oldticks[MAX_TIMER];
    clock_t delay;
    struct tms t;

    times(&t);
    delay = (t.tms_utime - oldticks[i]) * (1000 / CLK_TCK);
    oldticks[i] = t.tms_utime;
    return (long) delay;
  }
#elif USE_GETRUSAGE

# include <sys/time.h>
# include <sys/resource.h>
  static long
  timer_proto(int i)
  {
    static long oldmusec[MAX_TIMER],oldsec[MAX_TIMER];
    long delay;
    struct rusage r;
    struct timeval t;

    getrusage(0,&r); t=r.ru_utime;
    delay = 1000 * (t.tv_sec - oldsec[i]) + (t.tv_usec - oldmusec[i]) / 1000;
    oldmusec[i] = t.tv_usec; oldsec[i] = t.tv_sec;
    return delay;
  }
#elif USE_FTIME

# include <sys/timeb.h>
  static long
  timer_proto(int i)
  {
    static long oldmsec[MAX_TIMER],oldsec[MAX_TIMER];
    long delay;
    struct timeb t;

    ftime(&t);
    delay = 1000 * (t.time - oldsec[i]) + (t.millitm - oldmsec[i]);
    oldmsec[i] = t.millitm; oldsec[i] = t.time;
    return delay;
  }
#else

# include <time.h>
# ifndef CLOCKS_PER_SEC
#   define CLOCKS_PER_SEC 1000000 /* probably false on YOUR system */
# endif
  static long
  timer_proto(int i)
  {
    static clock_t oldclocks[MAX_TIMER];
    clock_t totalclocks = clock();

    unsigned long delay = (totalclocks-oldclocks[i]) * 1000. / CLOCKS_PER_SEC;
    oldclocks[i] = totalclocks;
    return delay;
  }
#endif

long
gptimer() { return timer_proto(0); }
long
timer() { return timer_proto(1); }
long
timer2() { return timer_proto(2); }

void
msgtimer(char *format, ...)
{
  va_list args;
  PariOUT *out = pariOut; pariOut = pariErr;

  pariputs("Time "); va_start(args, format);
  vpariputs(format,args); va_end(args);
  pariputsf(": %ld\n",timer2()); pariflush();
  pariOut = out;
}

/*******************************************************************/
/*                                                                 */
/*                   FUNCTIONS KNOWN TO THE ANALYZER               */
/*                                                                 */
/*******************************************************************/
void  alias0(char *s, char *old);
void  break0(long n);
void  next0();
void  return0(GEN x);

GEN geni(void) { return gi; }

/* List of GP functions:
 * ---------------------
 * Format (struct entree) :
 *   char *name    : name (under GP).
 *   ulong valence : used to form arg list, now often handled by code.
 *   void *value   : For PREDEFINED FUNCTIONS: C function to call.
 *                   For USER FUNCTIONS: pointer to defining data (bloc) = 
 *                    entree*: NULL, list of entree (arguments), NULL
 *                    char*  : function text
 *   long menu     : which help section do we belong (See below).
 *   char *code    : argument list (See below).
 *   entree *next  : next entree (init to NULL, used in hashing code).
 *   char *help    : short help text (init to NULL).
 *   void *args    : For USER FUNCTIONS: default arguments (NULL terminated).
 *                   For VARIABLES: (esp. loop indexes): push_val history.
 *                   (while processing a loop, ep->value may not be a bloc)
 * menu:
 * -----
 *  1: Standard monadic or dyadic OPERATORS
 *  2: CONVERSIONS and similar elementary functions
 *  3: TRANSCENDENTAL functions
 *  4: NUMBER THEORETICAL functions
 *  5: Functions related to ELLIPTIC CURVES
 *  6: Functions related to general NUMBER FIELDS
 *  7: POLYNOMIALS and power series
 *  8: Vectors, matrices, LINEAR ALGEBRA and sets
 *  9: SUMS, products, integrals and similar functions
 *  10: GRAPHIC functions
 *  11: PROGRAMMING under GP
 *
 * code: describe function prototype. NULL = use valence instead.
 * -----
 * Arguments:
 *  I  input position (to be processed with lisexpr or lisseq).
 *  G  GEN
 *  L  long
 *  S  symbol (i.e GP function name)
 *  V  variable (same as S, but valence must equal EpVAR)
 *  n  variable number
 *  F  Fake *GEN (function requires a *GEN, but we don't use the resulting GEN)
 *  f  Fake *long
 *  p  real precision (prec for the C library)
 *  P  series precision (precdl dor the C library)
 *  r  raw input (treated as a string without quotes).
 *     Quoted args are copied as strings. Stops at first unquoted ')' or ','.
 *     Special chars can be quoted using '\'.  Ex : aa"b\n)"c => "aab\n)c".
 *  s  expanded string. Example: pi"x"2 yields "3.142x2".
 *     The unquoted components can be of any pari type (converted according to
 *     the current output format)
 *  s* any number of strings (see s)
 *  s*p idem, setting prettyp=1
 *  s*t idem, in TeX format.
 *  D  Has a default value. Format is "Dvalue,type," (the ending comma is
 *     mandatory). Ex: D0,L, (arg is long, 0 by default).
 *     Special syntax: if type = GEN, DG send NULL.
 *     The user-given args are read first, then completed by the defaults
 *  
 * Return type: GEN by default, otherwise
 *  l Return long
 *  v Return void
 *
 * Syntax requirements:
 *  = Separator '=' required.
 *
 * Origin:
 *  x Installed foreign function. Put the ep of the function as an argument,
 *  then call installedHandler (???).
 ****************************************************************************
 * If new codes are added, change identifier and skipidentifier.
 *
 * Currently the following functions have no code word:
 * 'O' 50, 'if' 80, 'until' 82, 'while' 81
 *
 * Valence 0 reserved for functions without mandatory args.
 */

entree functions_basic[]={
{"Euler",0,(void*)mpeuler,3,"p"},
{"I",0,(void*)geni,2,""},
{"List",0,(void*)gtolist,2,"D[],G,"},
{"Mat",0,(void*)gtomat,2,"D[],G,"},
{"Mod",25,(void*)Mod0,2,"GGD0,L,"},
{"O",50,NULL,7,NULL},
{"Pi",0,(void*)mppi,3,"p"},
{"Pol",14,(void*)gtopoly,2,"GDx,n,"},
{"Polrev",14,(void*)gtopolyrev,2,"GDx,n,"},
{"Qfb",3,(void*)Qfb0,2,"GGGDGp"},
{"Ser",14,(void*)gtoser,2,"GDx,n,"},
{"Set",0,(void*)gtoset,2,"D[],G,"},
{"Str",0,(void*)gtostr,2,"D[],G,"},
{"Vec",0,(void*)gtovec,2,"D[],G,"},
{"abs",1,(void*)gabs,3,"Gp"},
{"acos",1,(void*)gacos,3,"Gp"},
{"acosh",1,(void*)gach,3,"Gp"},
{"addprimes",0,(void*)addprimes,4,"D[],G,"},
{"agm",2,(void*)agm,3,"GGp"},
{"algdep",23,(void*)algdep0,8,"GLD0,L,p"},
{"alias",2,(void*)alias0,11,"vrr"},
{"arg",1,(void*)garg,3,"Gp"},
{"asin",1,(void*)gasin,3,"Gp"},
{"asinh",1,(void*)gash,3,"Gp"},
{"atan",1,(void*)gatan,3,"Gp"},
{"atanh",1,(void*)gath,3,"Gp"},
{"bernreal",11,(void*)bernreal,3,"Lp"},
{"bernvec",11,(void*)bernvec,3,"L"},
{"besseljh",2,(void*)jbesselh,3,"GGp"},
{"besselk",2,(void*)kbessel0,3,"GGD0,L,p"},
{"bestappr",2,(void*)bestappr,4,"GG"},
{"bezout",2,(void*)vecbezout,4,"GG"},
{"bezoutres",2,(void*)vecbezoutres,4,"GG"},
{"bigomega",1,(void*)gbigomega,4,"G"},
{"binary",1,(void*)binaire,2,"G"},
{"binomial",21,(void*)binome,4,"GL"},
{"bittest",2,(void*)gbittest,2,"GG"},
{"bnfcertify",10,(void*)certifybuchall,6,"Gl"},
{"bnfclassunit",1,(void*)bnfclassunit0,6,"GD0,L,DGp"},
{"bnfclgp",1,(void*)classgrouponly,6,"GDGp"},
{"bnfdecodemodule",2,(void*)decodemodule,6,"GG"},
{"bnfinit",91,(void*)bnfinit0,6,"GD0,L,DGp"},
{"bnfisintnorm",3,(void*)bnfisintnorm,6,"GG"},
{"bnfisnorm",3,(void*)bnfisnorm,6,"GGD1,L,p"},
{"bnfisprincipal",2,(void*)isprincipalall,6,"GGD1,L,"},
{"bnfissunit",2,(void*)bnfissunit,6,"GGG"},
{"bnfisunit",2,(void*)isunit,6,"GG"},
{"bnfmake",1,(void*)bnfmake,6,"Gp"},
{"bnfnarrow",91,(void*)buchnarrow,6,"G"},
{"bnfreg",1,(void*)regulator,6,"GDGp"},
{"bnfsignunit",1,(void*)signunits,6,"G"},
{"bnfsunit",1,(void*)bnfsunit,6,"GGp"},
{"bnfunit",1,(void*)buchfu,6,"Gp"},
{"bnrclass",2,(void*)bnrclass0,6,"GGD0,L,p"},
{"bnrclassno",2,(void*)rayclassno,6,"GG"},
{"bnrclassnolist",2,(void*)rayclassnolist,6,"GG"},
{"bnrconductor",62,(void*)bnrconductor,6,"GD0,G,D0,G,D0,L,p"},
{"bnrconductorofchar",2,(void*)bnrconductorofchar,6,"GGp"},
{"bnrdisc",62,(void*)bnrdisc0,6,"GD0,G,D0,G,D0,L,p"},
{"bnrdisclist",32,(void*)bnrdisclist0,6,"GGD0,G,D0,L,"},
{"bnrinit",2,(void*)bnrinit0,6,"GGD0,L,p"},
{"bnrisconductor",62,(void*)bnrisconductor,6,"GD0,G,D0,G,pl"},
{"bnrisprincipal",2,(void*)isprincipalrayall,6,"GGD1,L,"},
{"break",0,(void*)break0,11,"vD1,L,"},
{"ceil",1,(void*)gceil,2,"G"},
{"centerlift",1,(void*)centerlift,2,"G"},
{"changevar",2,(void*)changevar,2,"GG"},
{"charpoly",14,(void*)charpoly0,8,"GDx,n,D0,L,"},
{"chinese",2,(void*)chinois,4,"GG"},
{"component",21,(void*)compo,2,"GL"},
{"concat",2,(void*)concat,8,"GG"},
{"conj",1,(void*)gconj,2,"G"},
{"conjvec",1,(void*)conjvec,2,"Gp"},
{"content",1,(void*)content,4,"G"},
{"contfrac",1,(void*)sfcont0,4,"GD0,G,D0,L,"},
{"contfracpnqn",1,(void*)pnqn,4,"G"},
{"core",1,(void*)core0,4,"GD0,L,"},
{"coredisc",1,(void*)coredisc0,4,"GD0,L,"},
{"cos",1,(void*)gcos,3,"Gp"},
{"cosh",1,(void*)gch,3,"Gp"},
{"denominator",1,(void*)denom,2,"G"},
{"deriv",14,(void*)deriv,7,"Gn"},
{"dilog",1,(void*)dilog,3,"Gp"},
{"dirdiv",2,(void*)dirdiv,7,"GG"},
{"direuler",83,(void*)direuler,7,"V=GGI"},
{"dirmul",2,(void*)dirmul,7,"GG"},
{"dirzetak",2,(void*)dirzetak,6,"GG"},
{"divisors",1,(void*)divisors,4,"G"},
{"divrem",2,(void*)gdiventres,1,"GG"},
{"eint1",1,(void*)eint1,3,"Gp"},
{"elladd",3,(void*)addell,5,"GGG"},
{"ellak",2,(void*)akell,5,"GG"},
{"ellan",23,(void*)anell,5,"GL"},
{"ellap",2,(void*)ellap0,5,"GGD0,L,"},
{"ellbil",3,(void*)bilhell,5,"GGGp"},
{"ellchangecurve",2,(void*)coordch,5,"GG"},
{"ellchangepoint",2,(void*)pointch,5,"GG"},
{"ellglobalred",1,(void*)globalreduction,5,"G"},
{"ellheight",2,(void*)ellheight0,5,"GGD0,L,p"},
{"ellheightmatrix",2,(void*)mathell,5,"GGp"},
{"ellinit",1,(void*)ellinit0,5,"GD0,L,p"},
{"ellisoncurve",20,(void*)oncurve,5,"GGl"},
{"ellj",1,(void*)jell,5,"Gp"},
{"elllocalred",2,(void*)localreduction,5,"GG"},
{"elllseries",4,(void*)lseriesell,5,"GGGGp"},
{"ellorder",2,(void*)orderell,5,"GG"},
{"ellordinate",2,(void*)ordell,5,"GGp"},
{"ellpointtoz",2,(void*)zell,5,"GGp"},
{"ellpow",3,(void*)powell,5,"GGGp"},
{"ellsub",3,(void*)subell,5,"GGGp"},
{"elltaniyama",1,(void*)taniyama,5,"Gp"},
{"elltors",1,(void*)torsell,5,"Gp"},
{"ellwp",1,(void*)weipell,5,"GP"},
{"ellztopoint",2,(void*)pointell,5,"GGp"},
{"erfc",1,(void*)gerfc,3,"Gp"},
{"eta",1,(void*)eta0,3,"GD0,L,p"},
{"eulerphi",1,(void*)gphi,4,"G"},
{"eval",1,(void*)geval,7,"G"},
{"exp",1,(void*)gexp,3,"Gp"},
{"factor",1,(void*)factor0,4,"GD-1,L,"},
{"factorback",1,(void*)factorback,4,"GDG"},
{"factorcantor",2,(void*)factcantor,4,"GG"},
{"factorff",3,(void*)factmod9,4,"GGG"},
{"factorial",11,(void*)mpfactr,4,"Lp"},
{"factormod",2,(void*)factormod0,4,"GGD0,L,"},
{"factornf",2,(void*)polfnf,6,"GG"},
{"factorpadic",32,(void*)factorpadic0,7,"GGLD0,L,"},
{"ffinit",21,(void*)ffinit,4,"GLDx,n,"},
{"fibonacci",11,(void*)fibo,4,"L"},
{"floor",1,(void*)gfloor,2,"G"},
{"for",83,(void*)forpari,11,"vV=GGI"},
{"fordiv",84,(void*)fordiv,11,"vGVI"},
{"forprime",83,(void*)forprime,11,"vV=GGI"},
{"forstep",86,(void*)forstep,11,"vV=GGGI"},
{"forvec",87,(void*)forvec,11,"vV=GI"},
{"frac",1,(void*)gfrac,2,"G"},
{"gamma",1,(void*)ggamma,3,"Gp"},
{"gammah",1,(void*)ggamd,3,"Gp"},
{"gcd",2,(void*)gcd0,4,"GGD0,L,"},
{"getheap",0,(void*)getheap,11,""},
{"getrand",0,(void*)getrand,11,""},
{"getstack",0,(void*)getstack,11,""},
{"gettime",0,(void*)gettime,11,""},
{"hilbert",30,(void*)hil0,4,"GGDGl"},
{"hyperu",3,(void*)hyperu,3,"GGGp"},
{"idealadd",3,(void*)idealadd,6,"GGG"},
{"idealaddtoone",3,(void*)idealaddtoone0,6,"GGDG"},
{"idealappr",2,(void*)idealappr0,6,"GGD0,L,"},
{"idealchinese",3,(void*)idealchinese,6,"GGG"},
{"idealcoprime",3,(void*)idealcoprime,6,"GGG"},
{"idealdiv",3,(void*)idealdiv0,6,"GGGD0,L,"},
{"idealfactor",2,(void*)idealfactor,6,"GG"},
{"idealhnf",2,(void*)idealhnf0,6,"GGDG"},
{"idealintersect",3,(void*)idealintersect,6,"GGG"},
{"idealinv",2,(void*)idealinv0,6,"GGD0,L,"},
{"ideallist",21,(void*)ideallist0,6,"GLD4,L,"},
{"ideallistarch",3,(void*)ideallistarch0,6,"GGDGD0,L,"},
{"ideallog",3,(void*)zideallog,6,"GGGp"},
{"idealmin",3,(void*)minideal,6,"GGGp"},
{"idealmul",3,(void*)idealmul0,6,"GGGD0,L,p"},
{"idealnorm",2,(void*)idealnorm,6,"GG"},
{"idealpow",3,(void*)idealpow0,6,"GGGD0,L,p"},
{"idealprimedec",2,(void*)primedec,6,"GGp"},
{"idealprincipal",2,(void*)principalideal,6,"GG"},
{"idealred",3,(void*)ideallllred,6,"GGD0,G,p"},
{"idealstar",2,(void*)idealstar0,6,"GGD1,L,"},
{"idealtwoelt",2,(void*)ideal_two_elt0,6,"GGDG"},
{"idealval",30,(void*)idealval,6,"GGGl"},
{"ideleprincipal",2,(void*)principalidele,6,"GGp"},
{"if",80,NULL,11,NULL},
{"imag",1,(void*)gimag,2,"G"},
{"incgam",2,(void*)incgam0,3,"GGD0,G,p"},
{"incgamc",2,(void*)incgam3,3,"GGp"},
{"intformal",14,(void*)integ,7,"Gn"},
{"intnum",37,(void*)intnum0,9,"V=GGID0,L,p"},
{"isfundamental",1,(void*)gisfundamental,4,"G"},
{"isprime",1,(void*)gisprime,4,"G"},
{"ispseudoprime",1,(void*)gispsp,4,"G"},
{"issquare",1,(void*)gcarreparfait,4,"G"},
{"issquarefree",1,(void*)gissquarefree,4,"G"},
{"kronecker",2,(void*)gkronecker,4,"GG"},
{"lcm",2,(void*)glcm,4,"GG"},
{"length",1,(void*)glength,2,"G"},
{"lex",20,(void*)lexcmp,2,"GGl"},
{"lift",1,(void*)lift,2,"G"},
{"lindep",1,(void*)lindep0,8,"GD0,L,p"},
{"listcreate",11,(void*)listcreate,8,"L"},
{"listinsert",3,(void*)listinsert,8,"GGL"},
{"listkill",1,(void*)listkill,8,"vG"},
{"listput",2,(void*)listput,8,"GGD0,L,"},
{"listsort",1,(void*)listsort,8,"GD0,L,"},
{"lngamma",1,(void*)glngamma,3,"Gp"},
{"log",1,(void*)log0,3,"GD0,L,p"},
{"matadjoint",1,(void*)adj,8,"G"},
{"matalgtobasis",2,(void*)matalgtobasis,6,"GG"},
{"matbasistoalg",2,(void*)matbasistoalg,6,"GG"},
{"matcompanion",1,(void*)assmat,8,"G"},
{"matdet",1,(void*)det0,8,"GD0,L,"},
{"matdetint",1,(void*)detint,8,"G"},
{"matdiagonal",1,(void*)diagonal,8,"G"},
{"mateigen",1,(void*)eigen,8,"Gp"},
{"mathess",1,(void*)hess,8,"G"},
{"mathilbert",11,(void*)mathilbert,8,"L"},
{"mathnf",1,(void*)mathnf0,8,"GD0,L,"},
{"mathnfmod",2,(void*)hnfmod,8,"GG"},
{"mathnfmodid",2,(void*)hnfmodid,8,"GG"},
{"matid",11,(void*)idmat,8,"L"},
{"matimage",1,(void*)matimage0,8,"GD0,L,"},
{"matimagecompl",1,(void*)imagecompl,8,"G"},
{"matindexrank",1,(void*)indexrank,8,"G"},
{"matintersect",2,(void*)intersect,8,"GG"},
{"matinverseimage",2,(void*)inverseimage,8,"GG"},
{"matisdiagonal",10,(void*)isdiagonal,8,"Gl"},
{"matker",1,(void*)matker0,8,"GD0,L,p"},
{"matkerint",1,(void*)matkerint0,8,"GD0,L,"},
{"matmuldiagonal",2,(void*)matmuldiagonal,8,"GG"},
{"matmultodiagonal",2,(void*)matmultodiagonal,8,"GG"},
{"matpascal",11,(void*)matpascal,8,"L"},
{"matrank",10,(void*)rank,8,"Gl"},
{"matrix",49,(void*)matrice,8,"GGVVI"},
{"matrixqz",2,(void*)matrixqz0,8,"GG"},
{"matsize",1,(void*)matsize,8,"G"},
{"matsnf",1,(void*)matsnf0,8,"GD0,L,"},
{"matsolve",2,(void*)gauss,8,"GG"},
{"matsolvemod",3,(void*)matsolvemod0,8,"GGGD0,L,"},
{"matsupplement",1,(void*)suppl,8,"Gp"},
{"mattranspose",1,(void*)gtrans,8,"G"},
{"max",2,(void*)gmax,1,"GG"},
{"min",2,(void*)gmin,1,"GG"},
{"modreverse",1,(void*)polymodrecip,6,"G"},
{"moebius",1,(void*)gmu,4,"G"},
{"newtonpoly",2,(void*)newtonpoly,6,"GG"},
{"next",0,(void*)next0,11,"v"},
{"nextprime",1,(void*)gnextprime,4,"G"},
{"nfalgtobasis",2,(void*)algtobasis,6,"GG"},
{"nfbasis",13,(void*)nfbasis0,6,"GD0,L,D0,G,"},
{"nfbasistoalg",2,(void*)basistoalg,6,"GG"},
{"nfdetint",2,(void*)nfdetint,6,"GG"},
{"nfdisc",1,(void*)nfdiscf0,6,"GD0,L,D0,G,"},
{"nfeltdiv",3,(void*)element_div,6,"GGG"},
{"nfeltdiveuc",3,(void*)nfdiveuc,6,"GGG"},
{"nfeltdivrem",3,(void*)nfdivres,6,"GGG"},
{"nfeltmod",3,(void*)nfmod,6,"GGG"},
{"nfeltmul",3,(void*)element_mul,6,"GGG"},
{"nfeltpow",3,(void*)element_pow,6,"GGG"},
{"nfeltreduce",3,(void*)element_reduce,6,"GGG"},
{"nfeltval",30,(void*)element_val,6,"GGGl"},
{"nffactor",30,(void*)nffactor,6,"GG"},
{"nffactormod",30,(void*)nffactormod,6,"GGG"},
{"nfgaloisapply",3,(void*)galoisapply,6,"GGG"},
{"nfgaloisconj",1,(void*)galoisconj0,6,"GD0,L,p"},
{"nfhilbert",10,(void*)nfhilbert0,6,"lGGGDG"},
{"nfhnf",2,(void*)nfhermite,6,"GG"},
{"nfhnfmod",3,(void*)nfhermitemod,6,"GGG"},
{"nfinit",1,(void*)nfinit0,6,"GD0,L,p"},
{"nfisideal",20,(void*)isideal,6,"GGl"},
{"nfisincl",2,(void*)nfisincl0,6,"GGD0,L,"},
{"nfisisom",2,(void*)nfisisom0,6,"GGD0,L,"},
{"nfnewprec",1,(void*)nfnewprec,6,"Gp"},
{"nfroots",30,(void*)nfroots,6,"GG"},
{"nfrootsof1",1,(void*)rootsof1,6,"Gp"},
{"nfsnf",2,(void*)nfsmith,6,"GG"},
{"nfsubfields",2,(void*)subfields0,6,"GD0,G,"},
{"norm",1,(void*)gnorm,2,"G"},
{"norml2",1,(void*)gnorml2,2,"G"},
{"numdiv",1,(void*)gnumbdiv,4,"G"},
{"numerator",1,(void*)numer,2,"G"},
{"numtoperm",24,(void*)permute,2,"LG"},
{"omega",1,(void*)gomega,4,"G"},
{"padicappr",2,(void*)apprgen9,7,"GG"},
{"padicprec",20,(void*)padicprec,2,"GGl"},
{"permtonum",1,(void*)permuteInv,2,"G"},
{"polcoeff",21,(void*)truecoeff,2,"GL"},
{"polcompositum",2,(void*)polcompositum0,6,"GGD0,L,"},
{"polcyclo",11,(void*)cyclo,7,"LDx,n,"},
{"poldegree",10,(void*)degree,7,"Gl"},
{"poldisc",1,(void*)discsr,7,"G"},
{"poldiscreduced",1,(void*)reduceddiscsmith,7,"G"},
{"polgalois",1,(void*)galois,6,"Gp"},
{"polinterpolate",31,(void*)polint,7,"GGDGF"},
{"polisirreducible",1,(void*)gisirreducible,7,"G"},
{"polkaramul",32,(void*)karamul,7,"GGL"},
{"pollead",1,(void*)leadingcoeff,7,"G"},
{"pollegendre",11,(void*)legendre,7,"LDx,n,"},
{"polrecip",1,(void*)polrecip,7,"G"},
{"polred",1,(void*)polred0,6,"GD0,L,D0,G,p"},
{"polredabs",1,(void*)polredabs0,6,"GD0,L,p"},
{"polredord",1,(void*)ordred,6,"Gp"},
{"polresultant",2,(void*)polresultant0,7,"GGD0,L,"},
{"polroots",1,(void*)roots0,7,"GD0,L,p"},
{"polrootsmod",2,(void*)rootmod0,7,"GGD0,L,"},
{"polrootspadic",32,(void*)rootpadic,7,"GGL"},
{"polsturm",10,(void*)sturmpart,7,"GDGDGl"},
{"polsubcyclo",2,(void*)subcyclo,6,"GGDx,n,"},
{"polsylvestermatrix",2,(void*)sylvestermatrix,7,"GGp"},
{"polsym",21,(void*)polsym,7,"GL"},
{"poltchebi",11,(void*)tchebi,7,"LDx,n,"},
{"poltschirnhaus",1,(void*)tschirnhaus,6,"G"},
{"polylog",24,(void*)polylog0,3,"LGD0,L,p"},
{"polzagier",21,(void*)polzag,7,"LL"},
{"precision",1,(void*)precision0,2,"GD0,L,"},
{"precprime",1,(void*)gprecprime,4,"G"},
{"prime",11,(void*)prime,4,"L"},
{"primes",11,(void*)primes,4,"L"},
{"prod",48,(void*)produit,9,"V=GGID1,G,"},
{"prodeuler",37,(void*)prodeuler,9,"V=GGIp"},
{"prodinf",27,(void*)prodinf0,9,"V=GID0,L,p"},
{"psi",1,(void*)gpsi,3,"Gp"},
{"qfbclassno",1,(void*)qfbclassno0,4,"GD0,L,"},
{"qfbcompraw",2,(void*)compraw,4,"GG"},
{"qfbhclassno",1,(void*)classno3,4,"G"},
{"qfbnucomp",3,(void*)nucomp,4,"GGG"},
{"qfbnupow",2,(void*)nupow,4,"GG"},
{"qfbpowraw",23,(void*)powraw,4,"GL"},
{"qfbprimeform",2,(void*)primeform,4,"GGp"},
{"qfbred",1,(void*)qfbred0,4,"GD0,L,DGDGDG"},
{"qfgaussred",1,(void*)sqred,8,"G"},
{"qfjacobi",1,(void*)jacobi,8,"Gp"},
{"qflll",1,(void*)qflll0,8,"GD0,L,p"},
{"qflllgram",1,(void*)qflllgram0,8,"GD0,L,p"},
{"qfminim",33,(void*)minim0,8,"GGGD0,L,p"},
{"qfperfection",10,(void*)perf,8,"G"},
{"qfsign",1,(void*)signat,8,"G"},
{"quadclassunit",96,(void*)quadclassunit0,4,"GD0,L,DGp"},
{"quaddisc",1,(void*)quaddisc,4,"G"},
{"quadgen",1,(void*)quadgen,4,"G"},
{"quadhilbert",11,(void*)quadhilbert,4,"GD0,G,p"},
{"quadpoly",1,(void*)quadpoly,4,"G"},
{"quadregulator",1,(void*)gregula,4,"Gp"},
{"quadunit",1,(void*)gfundunit,4,"Gp"},
{"random",0,(void*)genrand,2,"DG"},
{"real",1,(void*)greal,2,"G"},
{"removeprimes",0,(void*)removeprimes,4,"D[],G,"},
{"reorder",0,(void*)reorder,11,"D[],G,"},
{"return",0,(void*)return0,11,"vD0,G,"},
{"rnfalgtobasis",2,(void*)rnfalgtobasis,6,"GG"},
{"rnfbasis",2,(void*)rnfbasis,6,"GG"},
{"rnfbasistoalg",2,(void*)rnfbasistoalg,6,"GG"},
{"rnfcharpoly",14,(void*)rnfcharpoly,6,"GGGDx,n,"},
{"rnfconductor",2,(void*)rnfconductor,6,"GGp"},
{"rnfdedekind",30,(void*)rnfdedekind,6,"GGG"},
{"rnfdet",2,(void*)rnfdet0,6,"GGD0,G,"},
{"rnfdisc",2,(void*)rnfdiscf,6,"GG"},
{"rnfeltabstorel",2,(void*)rnfelementabstorel,6,"GG"},
{"rnfeltdown",2,(void*)rnfelementdown,6,"GG"},
{"rnfeltreltoabs",2,(void*)rnfelementreltoabs,6,"GG"},
{"rnfeltup",2,(void*)rnfelementup,6,"GG"},
{"rnfequation",2,(void*)rnfequationall,6,"GGD0,L,"},
{"rnfhnfbasis",2,(void*)rnfhermitebasis,6,"GG"},
{"rnfidealabstorel",2,(void*)rnfidealabstorel,6,"GG"},
{"rnfidealdown",2,(void*)rnfidealdown,6,"GG"},
{"rnfidealhnf",2,(void*)rnfidealhermite,6,"GG"},
{"rnfidealmul",2,(void*)rnfidealmul,6,"GG"},
{"rnfidealnormabs",2,(void*)rnfidealnormabs,6,"GG"},
{"rnfidealnormrel",2,(void*)rnfidealnormrel,6,"GG"},
{"rnfidealreltoabs",2,(void*)rnfidealreltoabs,6,"GG"},
{"rnfidealtwoelt",2,(void*)rnfidealtwoelement,6,"GG"},
{"rnfidealup",2,(void*)rnfidealup,6,"GG"},
{"rnfinit",2,(void*)rnfinitalg,6,"GGp"},
{"rnfisfree",20,(void*)rnfisfree,6,"GGl"},
{"rnfisnorm",3,(void*)rnfisnorm,6,"GGGD1,L,p"},
{"rnfkummer",2,(void*)rnfkummer,6,"GGD0,L,p"},
{"rnflllgram",3,(void*)rnflllgram,6,"GGGp"},
{"rnfnormgroup",2,(void*)rnfnormgroup,6,"GG"},
{"rnfpolred",2,(void*)rnfpolred,6,"GGp"},
{"rnfpolredabs",2,(void*)rnfpolredabs,6,"GGp"},
{"rnfpseudobasis",2,(void*)rnfpseudobasis,6,"GG"},
{"rnfsteinitz",2,(void*)rnfsteinitz,6,"GG"},
{"round",1,(void*)round0,2,"GD0,L,"},
{"rounderror",10,(void*)rounderror,2,"Gl"},
{"serconvol",2,(void*)convol,7,"GG"},
{"serlaplace",1,(void*)laplace,7,"G"},
{"serreverse",1,(void*)recip,7,"G"},
{"setintersect",2,(void*)setintersect,8,"GG"},
{"setisset",10,(void*)setisset,8,"Gl"},
{"setminus",2,(void*)setminus,8,"GG"},
{"setrand",11,(void*)setrand,11,"Lp"},
{"setsearch",20,(void*)setsearch,8,"lGGD0,L,"},
{"setunion",2,(void*)setunion,8,"GG"},
{"shift",21,(void*)gshift,1,"GL"},
{"shiftmul",21,(void*)gmul2n,1,"GL"},
{"sigma",1,(void*)gsumdivk,4,"GD1,L,"},
{"sign",10,(void*)gsigne,1,"Gl"},
{"simplify",1,(void*)simplify,2,"G"},
{"sin",1,(void*)gsin,3,"Gp"},
{"sinh",1,(void*)gsh,3,"Gp"},
{"sizebyte",10,(void*)taille2,2,"Gl"},
{"sizedigit",10,(void*)gsize,2,"Gl"},
{"solve",37,(void*)zbrent,9,"V=GGIp"},
{"sqr",1,(void*)gsqr,3,"G"},
{"sqrt",1,(void*)gsqrt,3,"Gp"},
{"sqrtint",1,(void*)racine,4,"Gp"},
{"subgrouplist",10,(void*)subgrouplist0,6,"GD0,L,D0,L,p"},
{"subst",26,(void*)gsubst,7,"GnG"},
{"sum",48,(void*)somme,9,"V=GGID0,G,p"},
{"sumalt",27,(void*)sumalt0,9,"V=GID0,L,p"},
{"sumdiv",22,(void*)divsum,9,"GVI"},
{"suminf",27,(void*)suminf,9,"V=GIp"},
{"sumpos",27,(void*)sumpos0,9,"V=GID0,L,p"},
{"tan",1,(void*)gtan,3,"Gp"},
{"tanh",1,(void*)gth,3,"Gp"},
{"taylor",12,(void*)tayl,7,"GnP"},
{"teichmuller",1,(void*)teich,3,"Gp"},
{"theta",2,(void*)theta,3,"GGp"},
{"thetanullk",21,(void*)thetanullk,3,"GL"},
{"thue",2,(void*)thue,7,"GGDG"},
{"thueinit",2,(void*)thueinit,7,"GD0,L,p"},
{"trace",1,(void*)gtrace,8,"Gp"},
{"truncate",1,(void*)trunc0,2,"GD0,L,"},
{"until",82,NULL,11,NULL},
{"valuation",20,(void*)ggval,2,"GGl"},
{"variable",1,(void*)gpolvar,2,"G"},
{"veceint1",2,(void*)veceint1,3,"GGp"},
{"vecextract",2,(void*)extract0,8,"GGDG"},
{"vecindexsort",1,(void*)indexsort,8,"G"},
{"veclexsort",1,(void*)lexsort,8,"G"},
{"vecmax",1,(void*)vecmax,1,"Gp"},
{"vecmin",1,(void*)vecmin,1,"Gp"},
{"vecsort",2,(void*)vecsort0,8,"GDG"},
{"vector",22,(void*)vecteur,8,"GVI"},
{"vectorv",22,(void*)vvecteur,8,"GVI"},
{"weber",1,(void*)weber0,3,"GD0,L,p"},
{"while",81,NULL,11,NULL},
{"zeta",1,(void*)gzeta,3,"Gp"},
{"zetak",2,(void*)gzetakall,6,"GGD0,L,p"},
{"zetakinit",1,(void*)initzeta,6,"Gp"},
{"znorder",1,(void*)order,4,"G"},
{"znprimroot",1,(void*)ggener,4,"G"},
{"znstar",1,(void*)znstar,4,"Gp"},

/* DO NOT REMOVE THIS BLANK LINE: chname & helpsynchro depend on it */
{NULL,0,NULL,0,NULL} /* sentinel */
};
