/******************************************************************/
/******************************************************************/
/*                                                                */
/*                       Fichier Include PARI                     */
/*                   commun a toutes les versions                 */
/*                                                                */
/*                       copyright  Babecool                      */
/*                                                                */
/******************************************************************/
/******************************************************************/
/* $Id: gencom.h,v 2.0.0.2 1997/12/14 20:11:49 karim Exp karim $ */

#ifdef __M68K__
#  define OLD_CODES
#endif

#ifndef ALPHA_ENDIAN
#  define   ALPHA_ENDIAN  12345678
#endif
#ifndef LITTLE_ENDIAN
#  define   LITTLE_ENDIAN 1234
#endif
#ifndef BIG_ENDIAN
#  define   BIG_ENDIAN    4321
#endif
#ifndef PDP_ENDIAN
#  define   PDP_ENDIAN    3412
#endif

#ifdef LONG_IS_64BIT
#  define MAXULONG     0xffffffffffffffffUL
#  define MAXHALFULONG 0x00000000ffffffffUL
#  define HIGHBIT      0x8000000000000000UL
#  define HIGHBITM1    0x7fffffffffffffffUL
#  define HIGHMASK     0xffffffff00000000UL
#  define LOWMASK      0x00000000ffffffffUL

#  define DEFAULTPREC     3 
#  define MEDDEFAULTPREC  4
#  define BIGDEFAULTPREC  5

#  define TWOPOTBYTES_IN_LONG  3
#  define TWOPOTBITS_IN_LONG   6
#  define BYTES_IN_LONG        8
#  define BITS_IN_LONG        64
#  define BITS_IN_HALFULONG   32
/* For a 64-bit random generator, change the following 32 to 64 */
#  define BITS_IN_RANDOM      32

#else

#  define MAXULONG     0xffffffffUL
#  define MAXHALFULONG 0x0000ffffUL
#  define HIGHBIT      0x80000000UL
#  define HIGHBITM1    0x7fffffffUL
#  define HIGHMASK     0xffff0000UL
#  define LOWMASK      0x0000ffffUL

#  define DEFAULTPREC        4
#  define MEDDEFAULTPREC     6
#  define BIGDEFAULTPREC     8

#  define TWOPOTBYTES_IN_LONG  2
#  define TWOPOTBITS_IN_LONG   5
#  define BYTES_IN_LONG        4
#  define BITS_IN_LONG        32
#  define BITS_IN_HALFULONG   16
#  define BITS_IN_RANDOM      32
#endif

#ifndef LONG_IS_64BIT
/*  second codeword x[1], for types: 1,2,7,10,11 */
#   define EXPOBITS    0x00ffffffUL
#   define HIGHEXPOBIT 0x00800000L
#   define LGEFBITS    0x0000ffffUL
#   define VALPBITS    0x0000ffffUL /* used only for type 7 */
#   define HIGHVALPBIT 0x00008000L /* used only for type 7 */
#   define PRECPBITS   0xffff0000UL /* used only for type 7 */
#   define PRECPSHIFT  16
#   define VARNSHIFT   16
 
# ifndef OLD_CODES
#   define SIGNBITS    0xc0000000UL
#   define VARNBITS    0x3fff0000UL
#   define LGEFINTBITS 0x00ffffffUL
#   define SIGNSHIFT   30
#   define MAXVARN     16383
# else
#   define SIGNBITS    0xff000000UL
#   define VARNBITS    0x00ff0000UL
#   define LGEFINTBITS 0x0000ffffUL
#   define SIGNSHIFT   24
#   define MAXVARN     255
# endif
 
/*  first codeword x[0] */
# ifndef OLD_CODES
#   define TYPBITS      0xfe000000UL
#   define CLONEBIT     0x01000000UL
#   define LGBITS       0x00ffffffUL 
#   define TYPSHIFT     25
# else
#   define TYPBITS      0xff000000UL
#   define CLONEBIT     0x00010000UL
#   define LGBITS       0x0000ffffUL
#   define TYPSHIFT     24
# endif
#endif

#ifdef LONG_IS_64BIT
/*  first codeword x[0] */
#  define TYPBITS      0xffff000000000000UL
#  define CLONEBIT     0x0000000100000000UL
#  define LGBITS       0x00000000ffffffffUL
#  define TYPSHIFT     48

/*  second codeword x[1] */
#  define SIGNBITS     0xffff000000000000UL
#  define VARNBITS     0x0000ffff00000000UL
#  define LGEFBITS     0x00000000ffffffffUL
#  define SIGNSHIFT    48
#  define MAXVARN      65535

#  define EXPOBITS     0x0000ffffffffffffUL
#  define HIGHEXPOBIT  0x0000800000000000L
#  define LGEFINTBITS  0x00000000ffffffffUL
#  define VALPBITS     0x00000000ffffffffUL
#  define HIGHVALPBIT  0x0000000080000000L
#  define PRECPBITS    0xffffffff00000000UL
#  define PRECPSHIFT   32
#  define VARNSHIFT    32
#endif

#ifdef ULONG_NOT_DEFINED
  typedef unsigned long ulong;
#endif
typedef long *GEN;

#define typ(x)        (((ulong) ((GEN) (x))[0]) >> TYPSHIFT)
#define settyp(x,s)   (((GEN)(x))[0] = (((GEN)(x))[0]&(~TYPBITS)) | (((ulong)(s))<<TYPSHIFT))

#define isclone(x)    (((GEN) (x))[0] & CLONEBIT)
#define setisclone(x) (((GEN) (x))[0] |= CLONEBIT)
#define unsetisclone(x) (((GEN) (x))[0] &= (~CLONEBIT))

#define lg(x)         ((long) (((GEN) (x))[0] & LGBITS))
#define setlg(x,s)    (((GEN)(x))[0] = (((GEN)(x))[0]&(~LGBITS)) | (s))

#define signe(x)      (((long) ((GEN) (x))[1]) >> SIGNSHIFT)
#define setsigne(x,s) (((GEN)(x))[1] = (((GEN)(x))[1]&(~SIGNBITS)) | (((long)(s))<<SIGNSHIFT))

#define lgef(x)       ((long) (((GEN) (x))[1] & LGEFBITS))
#define setlgef(x,s)  (((GEN)(x))[1] = (((GEN)(x))[1]&(~LGEFBITS)) | (s))

#define lgefint(x)      ((long) (((GEN) (x))[1] & LGEFINTBITS))
#define setlgefint(x,s) (((GEN)(x))[1] = (((GEN)(x))[1]&(~LGEFINTBITS)) | (s))

#define expo(x)       ((long) ((((GEN) (x))[1] & EXPOBITS) - HIGHEXPOBIT))
#define setexpo(x,s)  (((GEN)(x))[1] = (((GEN)(x))[1]&(~EXPOBITS)) + HIGHEXPOBIT + (s))

#define valp(x)       ((long) ((((GEN)(x))[1] & VALPBITS) - HIGHVALPBIT))
#define setvalp(x,s)  (((GEN)(x))[1] = (((GEN)(x))[1]&(~VALPBITS))+ HIGHVALPBIT + (s))

#define precp(x)      ((long) (((ulong) ((GEN) (x))[1]) >> PRECPSHIFT))
#define setprecp(x,s) (((GEN)(x))[1] = (((GEN)(x))[1]&(~PRECPBITS)) | (((long)(s))<<PRECPSHIFT))

#define varn(x)       ((long) ((((GEN) (x))[1]&VARNBITS) >> VARNSHIFT))
#define setvarn(x,s)  (((GEN)(x))[1] = (((GEN)(x))[1]&(~VARNBITS)) | (((ulong)(s))<<VARNSHIFT))

#define bit_accuracy(x) (((x)-2) << TWOPOTBITS_IN_LONG)

#define GSTR(x) ((char*) (((GEN) (x)) + 1 ))

typedef unsigned char *byteptr;

typedef struct stackzone
{
  long zonetop, bot, top, avma, memused;
} stackzone;

typedef struct entree {
  char *name;
  ulong valence;
  void *value;
  long menu;
  char *code;
  struct entree *next;
  char *help;
  void *args;
} entree;

/* VIRER CES DEUX LA */
#define init pari_init
#define gen2str GENtostr

typedef struct PariOUT {
  void (*putch)(char);
  void (*puts)(char*);
  void (*flush)();
  void (*die)();
} PariOUT;

/* Common global variables: */

extern PariOUT *pariOut, *pariErr;
extern FILE    *outfile, *logfile, *infile, *errfile;

extern long  pari_randseed, DEBUGLEVEL, DEBUGMEM;
extern long  precdl,defaultpadicprecision;
extern long  *ordvar;
extern ulong avma,bot,top,memused;
extern GEN   bernzone,gpi,geuler;
extern GEN   polvar,*polun,*polx,primetab;
extern GEN   gun,gdeux,ghalf,gi,gzero;
extern GEN   RAVYZARC;

extern entree  **varentries;
extern char    *errmessage[], current_psfile[128];

extern byteptr diffptr;

extern const long lontyp[];

#define NUMPRTBELT     100 /* taille table de premiers prives */
#define MAXITERPOL     10  /* nombre maximum de doublement de precision
			      dans les operations de type polredabs */

                                                /* let SL = sizeof(long) */
#define pariK  (9.632959862*(BYTES_IN_LONG/4))  /* SL*log(2)/log(10)     */
#define pariK1 (0.103810253/(BYTES_IN_LONG/4))  /* log(10)/(SL*log(2))   */
#define pariK2 (1.1239968)                      /* 1/(1-(log(2)/(2*pi))) */
#define pariK4 (17.079468445347/BITS_IN_LONG)   /* 2*e*pi/SL             */
#define LOG2   (0.69314718055994531)            /* log(2)                */
#define L2SL10 (0.301029995663981)              /* log(2)/log(10)        */
#define pariC1 (0.9189385332)                   /* log(2*pi)/2           */
#define pariC2 (22.18070978*(BYTES_IN_LONG/4))  /* SL*log(2)             */
#define pariC3 (0.0216950598/(BYTES_IN_LONG/4)) /* log((1+sqrt(5))/2)/C2 */

#ifndef  PI 
#  define PI (3.141592653589) 
#endif

#ifdef LONG_IS_64BIT 
#  define VERYBIGINT (9223372036854775807) /* 2^63-1 */ 
#  define EXP220 (1099511627776)           /* 2^40   */ 
#  define BIGINT (2147483647)              /* 2^31-1 */ 
#else 
#  define VERYBIGINT (2147483647) /* 2^31-1 */ 
#  define EXP220 (1048576)        /* 2^20   */ 
#  define BIGINT (32767)          /* 2^15-1 */ 
#endif

#ifdef __cplusplus
#  define ANYARG ...
#  define BEGINEXTERN extern "C" {
#  define ENDEXTERN }
#  define INLINE inline
#  ifndef __GNUC__
#    define VOLATILE
#  else
#    define VOLATILE volatile
#  endif
#else
#  define ANYARG
#  define BEGINEXTERN
#  define ENDEXTERN
#  ifndef __GNUC__
#    define VOLATILE
#  else
#    define VOLATILE __volatile__
#    ifdef LIB_PARI
#      define INLINE __inline__ extern
#    else
#      define INLINE static
#    endif
#  endif
#endif

#ifdef NOEXP2
#  ifdef __cplusplus
     inline double exp2(double x) {return exp(x*LOG2);}
     inline double log2(double x) {return log(x)/LOG2;}
#  else
#    define exp2(x) (exp((double)(x)*LOG2))
#    define log2(x) (log((double)(x))/LOG2)
#  endif
#else
  BEGINEXTERN
    double exp2(double);
    double log2(double);
  ENDEXTERN
#endif

#ifndef LONG_IS_64BIT
#  undef labs
#  define labs(x) abs(x)
#endif

#define min(a,b) ((a)>(b)?(b):(a))
#define max(a,b) ((a)>(b)?(a):(b))

#define gval(x,v) ggval(x,polx[v])
#define gvar9(x) ((typ(x)==t_POLMOD)? gvar2(x): gvar(x))

#define ggrando(x,n) grando0(x,n,1)
#define ggrandocp(x,n) grando0(x,n,0)

#define addis(x,s)  addsi(s,x)
#define addrs(x,s)  addsr(s,x)
#define mulis(x,s)  mulsi(s,x)
#define mulri(x,s)  mulir(s,x)
#define mulrs(x,s)  mulsr(s,x)
#define gmulgs(y,s) gmulsg(s,y)
#define lmulgs(y,s) ((long)gmulsg(s,y))

#define mpmodz(x,y,z) (modiiz(x,y,z))
#define mpresz(x,y,z) (resiiz(x,y,z))
#define mpmod(x,y)    (modii(x,y))
#define mpres(x,y)    (resii(x,y))

#define laddgs(y,s)    (lopsg2(gadd,s,y))
#define laddsg(s,y)    (lopsg2(gadd,s,y))
#define ldiventgs(y,s) (lopgs2(gdivent,y,s))
#define ldiventsg(s,y) (lopsg2(gdivent,s,y))
#define ldivsg(s,y)    (lopsg2(gdiv,s,y))
#define lmaxgs(y,s)    (lopgs2(gmax,y,s))
#define lmaxsg(s,y)    (lopsg2(gmax,s,y))
#define lmings(y,s)    (lopgs2(gmin,y,s))
#define lminsg(s,y)    (lopsg2(gmin,s,y))
#define lmodgs(y,s)    (lopgs2(gmod,y,s))
#define lmodsg(s,y)    (lopsg2(gmod,s,y))
#define lsubgs(y,s)    (lopgs2(gsub,y,s))
#define lsubsg(s,y)    (lopsg2(gsub,s,y))

#define mppiz(x)       (gop0z(mppi,x))
#define mpeulerz(x)    (gop0z(mpeuler,x))

#define autz(x,y)      (gop1z(mpaut,x,y))
#define mpsqrtz(x,y)   (gop1z(mpsqrt,x,y))
#define mpexpz(x,y)    (gop1z(mpexp,x,y))
#define mpexp1z(x,y)   (gop1z(mpexp1,x,y))
#define mplogz(x,y)    (gop1z(mplog,x,y))
#define mpcosz(x,y)    (gop1z(mpcos,x,y))
#define mpsinz(x,y)    (gop1z(mpsin,x,y))
#define mptanz(x,y)    (gop1z(mptan,x,y))
#define mpatanz(x,y)   (gop1z(mpatan,x,y))
#define mpasinz(x,y)   (gop1z(mpasin,x,y))
#define mpacosz(x,y)   (gop1z(mpacos,x,y))
#define mpchz(x,y)     (gop1z(mpch,x,y))
#define mpshz(x,y)     (gop1z(mpsh,x,y))
#define mpthz(x,y)     (gop1z(mpth,x,y))
#define mpathz(x,y)    (gop1z(mpath,x,y))
#define mpashz(x,y)    (gop1z(mpash,x,y))
#define mpachz(x,y)    (gop1z(mpach,x,y))
#define mpgammaz(x,y)  (gop1z(mpgamma,x,y))
#define gredz(x,y)     (gop1z(gred,x,y))
#define gnegz(x,y)     (gop1z(gneg,x,y))

#define mpargz(x,y,z)   (gop2z(mparg,x,y,z))
#define gabsz(x,prec,y) (gop2z(gabs,x,prec,y))
#define gmaxz(x,y,z)    (gop2z(gmax,x,y,z))
#define gminz(x,y,z)    (gop2z(gmin,x,y,z))
#define gaddz(x,y,z)    (gop2z(gadd,x,y,z))
#define gsubz(x,y,z)    (gop2z(gsub,x,y,z))
#define gmulz(x,y,z)    (gop2z(gmul,x,y,z))
#define gdivz(x,y,z)    (gop2z(gdiv,x,y,z))
#define gdiventz(x,y,z) (gop2z(gdivent,x,y,z))
#define gmodz(x,y,z)    (gop2z(gmod,x,y,z))

#define gaddgs(y,s)     (gopsg2(gadd,s,y))
#define gaddsg(s,y)     (gopsg2(gadd,s,y))
#define gaddsmat(s,y)   (gopsg2(gaddmat,s,y))
#define gdiventsg(s,y)  (gopsg2(gdivent,s,y))
#define gdivsg(s,y)     (gopsg2(gdiv,s,y))
#define gmaxsg(s,y)     (gopsg2(gmax,s,y))
#define gminsg(s,y)     (gopsg2(gmin,s,y))
#define gmodsg(s,y)     (gopsg2(gmod,s,y))
#define gsubsg(s,y)     (gopsg2(gsub,s,y))

#define gdiventgs(y,s)  (gopgs2(gdivent,y,s))
#define gmaxgs(y,s)     (gopgs2(gmax,y,s))
#define gmings(y,s)     (gopgs2(gmin,y,s))
#define gmodgs(y,s)     (gopgs2(gmod,y,s))
#define gsubgs(y,s)     (gopgs2(gsub,y,s))

#define gcmpsg(s,y)     (-opgs2(gcmp,y,s))
#define gcmpgs(y,s)     (opgs2(gcmp,y,s))
#define gegalsg(s,y)    (opgs2(gegal,y,s))
#define gegalgs(y,s)    (opgs2(gegal,y,s))

#define gaddgsz(y,s,z)    (gopsg2z(gadd,s,y,z))
#define gaddsgz(s,y,z)    (gopsg2z(gadd,s,y,z))
#define gdiventsgz(s,y,z) (gopsg2z(gdivent,s,y,z))
#define gdivsgz(s,y,z)    (gopsg2z(gdiv,s,y,z))
#define gmaxsgz(s,y,z)    (gopsg2z(gmax,s,y,z))
#define gminsgz(s,y,z)    (gopsg2z(gmin,s,y,z))
#define gmodsgz(s,y,z)    (gopsg2z(gmod,s,y,z))
#define gsubsgz(s,y,z)    (gopsg2z(gsub,s,y,z))

#define gdiventgsz(y,s,z) (gopgs2z(gdivent,y,s,z))
#define gmaxgsz(y,s,z)    (gopgs2z(gmax,y,s,z))
#define gmingsz(y,s,z)    (gopgs2z(gmin,y,s,z))
#define gmodgsz(y,s,z)    (gopgs2z(gmod,y,s,z))
#define gsubgsz(y,s,z)    (gopgs2z(gsub,y,s,z))

#define gdivgsz(y,s,z)  (gops2gsz(gdivgs,y,s,z))
#define gmul2nz(x,s,z)  (gops2gsz(gmul2n,x,s,z))
#define gmulgsz(y,s,z)  (gops2sgz(gmulsg,s,y,z))
#define gmulsgz(s,y,z)  (gops2sgz(gmulsg,s,y,z))
#define gshiftz(x,s,z)  (gops2gsz(gshift,x,s,z))

#define bern(i)       (bernzone + 3 + (i)*bernzone[2]) 

#define is_universal_constant(x) \
  ((long)(x) >= (long)gzero && (long)(x)<=(long)gi)

#define copyifstack(x) (RAVYZARC=(GEN)(x),(RAVYZARC>=(GEN)bot && RAVYZARC<(GEN)top)?lcopy(RAVYZARC):(long)RAVYZARC)

#define gcopyifstack(x) (GEN)(copyifstack(x))
/* #define copyifstack(x) (lcopy((GEN)(x))) */
 
#ifdef __cplusplus
  inline int isonstack(GEN x)
  {
    GEN RAVYZARC=x;
    return (RAVYZARC>=(GEN)bot && RAVYZARC<(GEN)top);
  }
#else
# define isonstack(x) (\
    RAVYZARC=(GEN)(x),(RAVYZARC>=(GEN)bot && RAVYZARC<(GEN)top)\
  )
#endif

/* Define this to (1) locally (in a given file, NOT here) to check the global
 * "random" garbage collecting
 */
#ifdef DYNAMIC_STACK
#  define low_stack(x,l) (avma < (l))
#else
#  define low_stack(x,l) (avma < (x))
#endif

/* works only for POSITIVE integers */
#define mod64(x)  (((x)[lgefint(x)-1]) & 63)
#define mod32(x)  (((x)[lgefint(x)-1]) & 31)
#define mod16(x)  (((x)[lgefint(x)-1]) & 15)
#define mod8(x)   (((x)[lgefint(x)-1]) & 7)
#define mod4(x)   (((x)[lgefint(x)-1]) & 3)
#define mod2(x)   (((x)[lgefint(x)-1]) & 1)
#define is_pm1(n)     ((((GEN)(n))[2]==1) && (lgefint(n)==3))

#define leading_term(x) ((GEN)(((GEN)x)[lgef(x)-1]))

#ifdef __cplusplus
   inline int odd(long x) {return x&1;}
#else
#  define odd(x) ((x) & 1)
#endif

#define mpodd(x) (signe(x) && mod2(x))

#define evalsigne(x)   (((long)(x)) << SIGNSHIFT)
#define evaltyp(x)     (((ulong)(x)) << TYPSHIFT)
#define evallg(x)      (x)
#define evallgef(x)    (x)
#define evallgefint(x) (x)
#define evalvarn(x)    (((ulong)(x)) << VARNSHIFT)
#define evalprecp(x)   (((long)(x)) << PRECPSHIFT)
#define evalexpo(x)    (HIGHEXPOBIT + (x))
#define evalvalp(x)    (HIGHVALPBIT + (x))

#define ONLY_REM ((GEN*)MAXULONG)
#define gdeuc(x,y) (poldivres((x),(y),NULL))
#define gres(x,y) (poldivres((x),(y),ONLY_REM))
#define sturm(x) (sturmpart((x),NULL,NULL))
#define carreparfait(x) carrecomplet(x,NULL)

#define idealmullll(nf,x,y) (idealoplll(idealmul,nf,x,y))
#define idealdivlll(nf,x,y) (idealoplll(idealdiv,nf,x,y))

#define invmat(a) gauss(a,NULL)

#define element_divmodideal(nf,x,y,ideal) (\
  nfreducemodideal(nf,\
    element_mul(nf,x,element_invmodideal(nf,y,ideal))\
    ,ideal\
  )\
)
#define element_mulmodideal(nf,x,y,ideal) (\
  nfreducemodideal(nf,element_mul(nf,x,y),ideal)\
)
#define element_mulmodidele(nf,x,y,idele,structarch) (\
  nfreducemodidele(nf,element_mul(nf,x,y),idele,structarch)\
)
#define element_mulmodpr(nf,x,y,prhall) (\
  nfreducemodpr(nf,element_mul(nf,x,y),prhall)\
)
#define element_sqrmodideal(nf,x,ideal) (\
  nfreducemodideal(nf,element_sqr(nf,x),ideal)\
)
#define element_sqrmodidele(nf,x,idele,structarch) (\
  nfreducemodidele(nf,element_sqr(nf,x),idele,structarch)\
)
#define element_sqrmodpr(nf,x,prhall) (\
  nfreducemodpr(nf,element_sqr(nf,x),prhall)\
)
#define idealmulmodideal(nf,x,y,ideal,prec) (\
  ideallllredmodideal(nf,idealmullll(nf,x,y),ideal,prec)\
)
#define idealsqrmodideal(nf,x,ideal,prec) (\
  ideallllredmodideal(nf,idealsqrlll(nf,x),ideal,prec)\
)

#define buchgen(P,gcbach,gcbach2,prec) (\
  buchall(P,gcbach,gcbach2,stoi(5),gzero,4,3,0,prec)\
)
#define buchgenfu(P,gcbach,gcbach2,prec) (\
  buchall(P,gcbach,gcbach2,stoi(5),gzero,4,3,2,prec)\
)
#define buchinit(P,gcbach,gcbach2,prec) (\
  buchall(P,gcbach,gcbach2,stoi(5),gzero,4,3,-1,prec)\
)
#define buchinitfu(P,gcbach,gcbach2,prec) (\
  buchall(P,gcbach,gcbach2,stoi(5),gzero,4,3,-2,prec)\
)
