/* Integer Version 2.1a, TP, 5.10.94	iint.h	*/
/* Integer Version 2.1, RD, 16.7.93	iint.h	*/
/* Integer Version 2.0, RD, 15.1.93	iint.h	*/

#ifndef _IINT_H
#define _IINT_H

typedef unsigned long 	DigitType;
#define BitsPerDigit	(sizeof(DigitType)*8)

/* Need definiton of FILE */

#include <stdio.h>

/*	Here is the part of c_varieties.h we shall use	*/

#ifndef C_VARIETIES_H

#ifdef __cplusplus
#define EXTERN_FUNCTION( rtn, args ) extern "C" { rtn args; }
#define _VOID_ /* anachronism */
#else
#ifdef __STDC__
#ifdef __PARC__
#define EXTERN_FUNCTION( rtn, args ) rtn()
#define _VOID_
#define const
#else
#define EXTERN_FUNCTION( rtn, args ) rtn args
#define _VOID_ void
#endif
#else
#define EXTERN_FUNCTION( rtn, args ) rtn()
#define _VOID_
#define const
#endif
#endif

#endif

/*	And now come some useful definitions	*/

#ifndef BOOLEANDEF
#define BOOLEANDEF
    typedef int     BOOLEAN;
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef NULL
#define NULL 0
#endif

/* These are the signs of our Integers */

#define PLUS 0
#define MINUS 1

/*	This is the main data type	*/

typedef struct {
    DigitType   *vec;
    int         maxlength, length, sign;
}               Integer, *pInteger;

/* added to allow changing of Ierror() TP */

#ifdef __STDC__
typedef void (*Ierror_handler)(const char *);
#else
typedef void (*Ierror_handler)();
#endif

extern Ierror_handler Ierror;

/*      Special sort of code to name the functions:
        I:      Integer
        int:    int
        as:     assign
        pl:     plus
        mi:     minus
	eq:	equal
	gt:	greater than
	mu:	multiply
	sl:	shift left
	sr:	shift right
*/


EXTERN_FUNCTION(void cI, (Integer *));			/* Creator */
EXTERN_FUNCTION(void cIasint, (Integer *, int));	/* Creator + Init int */
EXTERN_FUNCTION(void cIasuint, (Integer *, unsigned int));
	/* Creator + Init unsigned int */
EXTERN_FUNCTION(void cIaslong, (Integer *, long));
	/* Creator + Init long */
EXTERN_FUNCTION(void cIasulong, (Integer *, unsigned long));
	/* Creator + Init unsigned long */
EXTERN_FUNCTION(void cIasI, (Integer *, const Integer *));
	/* Creator + Init Int */
EXTERN_FUNCTION(void cImaxlength, (Integer *, int));
 	/* maxlength wird vorgegeben */
EXTERN_FUNCTION(void dI, (Integer *));			/* Destructor */

EXTERN_FUNCTION(Integer * ncI, (_VOID_));		/* new Integer + cI */
EXTERN_FUNCTION(Integer * ncIasint, (int));	/* new Integer + cIasint */
EXTERN_FUNCTION(Integer * ncIasuint, (unsigned int));	/* new Integer + cIasuint */
EXTERN_FUNCTION(Integer * ncIaslong, (long));	/* new Integer + cIaslong */
EXTERN_FUNCTION(Integer * ncIasulong, (unsigned long));	/* new Integer + cIasulong */
EXTERN_FUNCTION(Integer * ncIasI, (Integer *));	/* new Integer + cIasI */
EXTERN_FUNCTION(Integer * ncImaxlength, (int));	/* new Integer + cImaxlength */
EXTERN_FUNCTION(void ddI, (Integer *));		/* dI + delete Integer */

EXTERN_FUNCTION(void default_Ierror, (const char *));/*	 Error message */

EXTERN_FUNCTION(void IasI, (Integer *, const Integer *));	/* Assignment */
EXTERN_FUNCTION(void Iasint, (Integer *, int));	    /* Assignment of an int */
EXTERN_FUNCTION(void Iasuint, (Integer *, unsigned int)); /* Assignment of an unsigned int */
EXTERN_FUNCTION(void Iaslong, (Integer *, long));	    /* Assignment of an long */
EXTERN_FUNCTION(void Iasulong, (Integer *, unsigned long)); /* Assignment of an unsigned long */
EXTERN_FUNCTION(void Iasdbl, (Integer *, double)); /* Assignment of a double */
EXTERN_FUNCTION(void Ias0, (Integer *));
EXTERN_FUNCTION(void Ias1, (Integer *));
#ifdef USE_THIS_LOT_OF_MACROS
#define IAS0(A) ((A)->length=0, (A)->sign=PLUS)
#define IAS1(A) ((A)->length=1, *((A)->vec)=1, (A)->sign=PLUS)
#endif
EXTERN_FUNCTION(BOOLEAN Iisint, (const Integer *));
EXTERN_FUNCTION(BOOLEAN Iisuint, (const Integer *));
EXTERN_FUNCTION(BOOLEAN Iislong, (const Integer *));
EXTERN_FUNCTION(BOOLEAN Iisulong, (const Integer *));
EXTERN_FUNCTION(int intasI, (const Integer *));
EXTERN_FUNCTION(unsigned int uintasI, (const Integer *));
EXTERN_FUNCTION(long longasI, (const Integer *));
EXTERN_FUNCTION(unsigned long ulongasI, (const Integer *));

EXTERN_FUNCTION(int Ilog, (const Integer *));	/* Two's logarithm */
EXTERN_FUNCTION(int intlog, (int));	/* Two's logarithm */

EXTERN_FUNCTION(void IasIplI, (Integer *, const Integer *, const Integer *));
	/* Addition + */
EXTERN_FUNCTION(void IasImiI, (Integer *, const Integer *, const Integer *));
	/* Subtraction - */
EXTERN_FUNCTION(void IplasI, (Integer *, const Integer *));
	/* Addition += */
EXTERN_FUNCTION(void ImiasI, (Integer *, const Integer *));
	/* Subtraction -= */
EXTERN_FUNCTION(void Ineg, (Integer *));
	/* Change the sign */
EXTERN_FUNCTION(void Iinc, (Integer *));		/* ++ */
EXTERN_FUNCTION(void Idec, (Integer *));		/* -- */

EXTERN_FUNCTION(BOOLEAN IeqI, (const Integer *, const Integer *));
	/* Test equality == */
EXTERN_FUNCTION(BOOLEAN IgtI, (const Integer *, const Integer *));
	/* Test greater > */
EXTERN_FUNCTION(BOOLEAN IneI, (const Integer *, const Integer *));
EXTERN_FUNCTION(BOOLEAN IgeI, (const Integer *, const Integer *));
EXTERN_FUNCTION(BOOLEAN IltI, (const Integer *, const Integer *));
EXTERN_FUNCTION(BOOLEAN IleI, (const Integer *, const Integer *));
EXTERN_FUNCTION(BOOLEAN Ige0, (const Integer *));
EXTERN_FUNCTION(BOOLEAN Igt0, (const Integer *));
EXTERN_FUNCTION(BOOLEAN Ile0, (const Integer *));
EXTERN_FUNCTION(BOOLEAN Ilt0, (const Integer *));
EXTERN_FUNCTION(BOOLEAN Ieq0, (const Integer *));
EXTERN_FUNCTION(BOOLEAN Ieq1, (const Integer *));

#ifdef USE_THIS_LOT_OF_MACROS
#define INEI(A, B)	(!IeqI((A), (B)))
#define IGEI(A, B)	(!IgtI((B), (A)))
#define ILTI(A, B)	(IgtI((B), (A)))
#define ILEI(A, B)	(!IgtI((A), (B)))
#define IGE0(A)		((A)->sign==PLUS)
#define IGT0(A)		(((A)->sign==PLUS)&&((A)->length))
#define ILE0(A)		(!(A)->length || ((A)->sign==MINUS))
#define ILT0(A)		((A)->sign==MINUS)
#define IEQ0(A)		(!(A)->length)
#define IEQ1(A)	((*((A)->vec)==1)&&((A)->length==1)&&((A)->sign==PLUS))
#endif

EXTERN_FUNCTION(void IasIandI, (Integer *, const Integer *, const Integer *));
	/* bitweise And, & */
EXTERN_FUNCTION(void IasIxorI, (Integer *, const Integer *, const Integer *));
	/* bitweise Xor, ^ */
EXTERN_FUNCTION(void IasIorI, (Integer *, const Integer *, const Integer *));
	/* bitweise Or, | */
EXTERN_FUNCTION(void IasnotI, (Integer *, const Integer *));
	/* bitweise Not, ~ */
EXTERN_FUNCTION(void IandasI, (Integer *, const Integer *));
	/*  bitweise And with Assign &= */
EXTERN_FUNCTION(void IxorasI, (Integer *, const Integer *));
	/*  bitweise Xor with Assign ^= */
EXTERN_FUNCTION(void IorasI, (Integer *, const Integer *));
	/*  bitweise Or with Assign |= */
#ifdef USE_THIS_LOT_OF_MACROS
#define IANDASI(A, B)	IasIandI(A, A, B)	
#define IXORASI(A, B)	IasIxorI(A, A, B)	
#define IORASI(A, B)	IasIorI(A, A, B)	
#endif

EXTERN_FUNCTION(void IasIpowD, (Integer *, const Integer *, DigitType));
	/* power DigitType */
EXTERN_FUNCTION(void Iroot, (Integer *, const Integer *, DigitType));
	/* newton n-th root */
EXTERN_FUNCTION(void IassqrtI, (Integer *, const Integer *));
	/* sqrt */

EXTERN_FUNCTION(void IasImuI, (Integer *, const Integer *, const Integer *));
	/* Multiplication * */
EXTERN_FUNCTION(void ImuasI, (Integer *, const Integer *));
	/* Multiplication *= */
EXTERN_FUNCTION(void IasImuD, (Integer *, const Integer *, DigitType));
	/* Multiplication with DigitType */
EXTERN_FUNCTION(void ImuasD, (Integer *, DigitType));

EXTERN_FUNCTION(void IasIsrD, (Integer *, const Integer *, DigitType));
	/* Shift to the right */
EXTERN_FUNCTION(void IsrasD, (Integer *, DigitType));
	/* Shift to the right */
EXTERN_FUNCTION(void IasIslD, (Integer *, const Integer *, DigitType));
	/* Shift to the left */
EXTERN_FUNCTION(void IslasD, (Integer *, DigitType));
	/* Shift to the left */
EXTERN_FUNCTION(BOOLEAN Isr1, (Integer *));	/* Shift by one */
EXTERN_FUNCTION(BOOLEAN Ieven, (const Integer *));	/* is a even? */
#ifdef USE_THIS_LOT_OF_MACROS
#define IEVEN(A)	(!(*((A)->vec) & 1))
#endif

EXTERN_FUNCTION(DigitType uIdiasD, (Integer *, DigitType));
	/* Division by DigitType, no sign, return remainder. */
EXTERN_FUNCTION(DigitType IdiasD, (Integer *, DigitType));
	/* Division by DigitType, with sign, return remainder. */
EXTERN_FUNCTION(DigitType uIasIdiD, (Integer *, const Integer *, DigitType));
	/* Division by DigitType, no sign, return remainder. */
EXTERN_FUNCTION(DigitType IasIdiD, (Integer *, const Integer *, DigitType));
	/* Division by DigitType, with sign, return remainder. */
EXTERN_FUNCTION(void uIdiv, (Integer *q, Integer *r, const Integer *a, const Integer *b));
	/* Division with remainder a=bq+r, no sign */
EXTERN_FUNCTION(void Idiv, (Integer *q, Integer *r, const Integer *a, const Integer *b));
	/* Division with remainder a=bq+r, with sign */
EXTERN_FUNCTION(void IasIdiI, (Integer *, const Integer *, const Integer *));
	/* Division, quotient */
EXTERN_FUNCTION(void IasIreI, (Integer *, const Integer *, const Integer *));
	/* Division, remainder */
EXTERN_FUNCTION(void IdiasI, (Integer *, const Integer *));
	/* Division, quotient */
EXTERN_FUNCTION(void IreasI, (Integer *, const Integer *));
	/* Division, remainder */

EXTERN_FUNCTION(int fscanI, (FILE *, Integer *));	/* Input from file */
EXTERN_FUNCTION(int fprintI, (FILE *, const Integer *));
	/* Output to file */

EXTERN_FUNCTION(void Idgcd, (Integer *d, const Integer *a, const Integer *b));
	/* Euklid's Algorithm (Division)  d=gcd(a, b); */
EXTERN_FUNCTION(void Ibgcd, (Integer *d, const Integer *a, const Integer *b));
	/* Binary gcd */
#define Igcd	Ibgcd
	/* Standard gcd	*/
EXTERN_FUNCTION(void Idxgcd,(Integer*d,Integer*u,Integer*v,const Integer*a,const Integer*b));
	/* Extended gcd:  d=gcd(a, b)==ua+vb; */
#define Ixgcd	Idxgcd
EXTERN_FUNCTION(void Ibxgcd,(Integer*d,Integer*u,Integer*v,const Integer*a,const Integer*b));
	/* Binary xgcd */
EXTERN_FUNCTION(void Ireduce, (Integer *a, Integer *b));	/* reduce gcd */

EXTERN_FUNCTION(void IasrandomI, (Integer * a, const Integer * b));
 /*
  * Randomgenerator: choose random a with 0<=|a|<|b|, a->sign=b->sign.
  * a and b have to be distinct.
  */

/* Now come some functions for fast writing and reading or sending and
 * receiving Integers. The result of these functions are pointers to
 * memory blocks consisting of l bytes, that have to be sent/received
 * by appropriate funtions.
 *	The calling sequences are:
 *	- sender:	p=wIdata1(a, &l);
 *			send(channel, p, l);	(or write(file, p, l); ...)
 *			p=wIdata2(a, &l);
 *			send(channel, p, l);
 *	- receiver:	p=rIdata1(a, &l);
 *			receive(channel, p, l);
 *			p=rIdata2(a, &l);
 *			receive(channel, p, l);
 */
EXTERN_FUNCTION(char *wIdata1, (const Integer * a, int *l));
EXTERN_FUNCTION(char *wIdata2, (const Integer * a, int *l));
EXTERN_FUNCTION(char *rIdata1, (const Integer * a, int *l));
EXTERN_FUNCTION(char *rIdata2, (Integer * a, int *l));

EXTERN_FUNCTION(int Itoa, (const Integer * n, char s[]));
EXTERN_FUNCTION(int atoI, (char s[], Integer * n));

EXTERN_FUNCTION(void IprintStatistics, (_VOID_));



#endif
