/* Head file for the multi-precision package */
/*
**  $Revision: 1.5 $
**  $Source: /home/carrier/rsa/mpp.h,v $
**  $Date: 1999/11/11 19:45:58 $  
*/

#ifndef _MPP_H
#define _MPP_H

#define      LOG2            .69314718       /* Natural Log of 2.0 */
#define      LOG3            1.0986122       /* Natural Log of 3.0 */

#define RADIX		1073741824
#define RADIX_BITS	30	/* Number of bits in RADIX: 2^RADIX_BITS=RADIX */
#define SQRT_RAD	32768     /* [SQRT(RADIX)]    =2^15   */    
#define MPDIM		50
#define MPCDIM		200
#define MPBITS		30
#define LOGTWO		50
#define EOS		'\0'
#define BLANK		' '

#define SIGN(x)		((x[0]>0)?1:-1)
#define SIZE(x)		(SIGN(x)*x[0]) 
#define SET_SIZE(x)         x[0]            /* Size of x in base RADIX      */
#define LASTDIGIT(x)	x[1]
#define LAST(x)	x[1]
#define FIRST(x)	x[SIZE(x)-1]
#define MINUS(x,y)	{mpcopy(x,y); y[0]=0-x[0];}

#define SINGLE          2               /* single precision size of MP  */
#define DOUBLE          3               /* double precision size of MP  */     

#define INIT(x)		for (ini=0; ini<MPDIM; ini++) x[ini] = 0; x[0]=2;
#define COPY(a,b,ind)   for (ind=0; ind<SIZE(a); ind++) b[ind] = a[ind]

int ini;
double mplog(int num[MPDIM]);
// mpctoi(char input[], int output[]);

extern double mplog(int num[MPDIM]);
extern inline void mpzero( int a[MPDIM] );
extern inline void mpone( int a[MPDIM] );
extern void mpcopy(int a[MPDIM],int b[MPDIM]);
extern void add(int a[MPDIM], int b[MPDIM], int c[MPDIM]);
extern void add_single(int a[], int b[], int c[]);
extern void subt(int a[], int b[], int c[]);
extern void mul_single(int a[], int b, int c[]);
extern int div_single(int a[], int b, int c[]);
extern int smod(int a[], int b);
extern void mult(int a[], int b[], int c[]);
extern void div(int a[], int b[], int c[], int d[]);
extern int mpitoc(int input[], char str[], int size);
extern void mpctoi(char input[], int output[]);
extern int write_num(int num[], char str[]);
extern int fwrite_num(FILE *hOut, int n[] , char numstr[]);
extern void get_num(int number[], char numstr[]);
extern int mpcmp(int a[], int b[]);
extern int mpscmp(int a[], int b);
extern void mpsqrt(int a[], int b[]);
extern int mpodiv(int a[]);
extern void gcd(int a[], int b[], int c[]);
extern void mpower(int b[],int e[],int m[],int a[]);
extern void mulold(int a, int b, int c, int m[2]);
extern int divold(int a[2], int b, int *q);
extern void cpower(int base, int power, int result[]);
extern void binary(int n, int bits[], int *max);
extern void internal(int num[]);
extern void fileit(int number[], FILE *ptr);
extern int prime_test(int number[]);
extern int modsqrt(int N, int p);
extern int spower(int base[], int exp, int mod);
extern int fastpow(int base, int exp, int mod);
extern int single_modinv(int a, int modulus);
extern int next_prime(int N);

/* Added by Brian Carrier */
extern void mpRoot(int mpA[MPDIM], int degree, int mpRoot[MPDIM]);
extern void cpower2(int mpA[MPDIM], int pow, int mpRes[MPDIM]);
extern void mpsptomp(int iSp, int mpRes[MPDIM]);

// In sn4asm3.c
int mod_mult(unsigned long a,unsigned long b, unsigned long c);
#endif
