xref: /plan9/sys/src/cmd/unix/drawterm/include/mp.h (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #define _MPINT 1
2*8ccd4a63SDavid du Colombier 
3*8ccd4a63SDavid du Colombier // the code assumes mpdigit to be at least an int
4*8ccd4a63SDavid du Colombier // mpdigit must be an atomic type.  mpdigit is defined
5*8ccd4a63SDavid du Colombier // in the architecture specific u.h
6*8ccd4a63SDavid du Colombier 
7*8ccd4a63SDavid du Colombier typedef struct mpint mpint;
8*8ccd4a63SDavid du Colombier 
9*8ccd4a63SDavid du Colombier struct mpint
10*8ccd4a63SDavid du Colombier {
11*8ccd4a63SDavid du Colombier 	int	sign;	// +1 or -1
12*8ccd4a63SDavid du Colombier 	int	size;	// allocated digits
13*8ccd4a63SDavid du Colombier 	int	top;	// significant digits
14*8ccd4a63SDavid du Colombier 	mpdigit	*p;
15*8ccd4a63SDavid du Colombier 	char	flags;
16*8ccd4a63SDavid du Colombier };
17*8ccd4a63SDavid du Colombier 
18*8ccd4a63SDavid du Colombier enum
19*8ccd4a63SDavid du Colombier {
20*8ccd4a63SDavid du Colombier 	MPstatic=	0x01,
21*8ccd4a63SDavid du Colombier 	Dbytes=		sizeof(mpdigit),	// bytes per digit
22*8ccd4a63SDavid du Colombier 	Dbits=		Dbytes*8		// bits per digit
23*8ccd4a63SDavid du Colombier };
24*8ccd4a63SDavid du Colombier 
25*8ccd4a63SDavid du Colombier // allocation
26*8ccd4a63SDavid du Colombier void	mpsetminbits(int n);	// newly created mpint's get at least n bits
27*8ccd4a63SDavid du Colombier mpint*	mpnew(int n);		// create a new mpint with at least n bits
28*8ccd4a63SDavid du Colombier void	mpfree(mpint *b);
29*8ccd4a63SDavid du Colombier void	mpbits(mpint *b, int n);	// ensure that b has at least n bits
30*8ccd4a63SDavid du Colombier void	mpnorm(mpint *b);		// dump leading zeros
31*8ccd4a63SDavid du Colombier mpint*	mpcopy(mpint *b);
32*8ccd4a63SDavid du Colombier void	mpassign(mpint *old, mpint *new);
33*8ccd4a63SDavid du Colombier 
34*8ccd4a63SDavid du Colombier // random bits
35*8ccd4a63SDavid du Colombier mpint*	mprand(int bits, void (*gen)(uchar*, int), mpint *b);
36*8ccd4a63SDavid du Colombier 
37*8ccd4a63SDavid du Colombier // conversion
38*8ccd4a63SDavid du Colombier mpint*	strtomp(char*, char**, int, mpint*);	// ascii
39*8ccd4a63SDavid du Colombier int	mpfmt(Fmt*);
40*8ccd4a63SDavid du Colombier char*	mptoa(mpint*, int, char*, int);
41*8ccd4a63SDavid du Colombier mpint*	letomp(uchar*, uint, mpint*);	// byte array, little-endian
42*8ccd4a63SDavid du Colombier int	mptole(mpint*, uchar*, uint, uchar**);
43*8ccd4a63SDavid du Colombier mpint*	betomp(uchar*, uint, mpint*);	// byte array, little-endian
44*8ccd4a63SDavid du Colombier int	mptobe(mpint*, uchar*, uint, uchar**);
45*8ccd4a63SDavid du Colombier uint	mptoui(mpint*);			// unsigned int
46*8ccd4a63SDavid du Colombier mpint*	uitomp(uint, mpint*);
47*8ccd4a63SDavid du Colombier int	mptoi(mpint*);			// int
48*8ccd4a63SDavid du Colombier mpint*	itomp(int, mpint*);
49*8ccd4a63SDavid du Colombier uvlong	mptouv(mpint*);			// unsigned vlong
50*8ccd4a63SDavid du Colombier mpint*	uvtomp(uvlong, mpint*);
51*8ccd4a63SDavid du Colombier vlong	mptov(mpint*);			// vlong
52*8ccd4a63SDavid du Colombier mpint*	vtomp(vlong, mpint*);
53*8ccd4a63SDavid du Colombier 
54*8ccd4a63SDavid du Colombier // divide 2 digits by one
55*8ccd4a63SDavid du Colombier void	mpdigdiv(mpdigit *dividend, mpdigit divisor, mpdigit *quotient);
56*8ccd4a63SDavid du Colombier 
57*8ccd4a63SDavid du Colombier // in the following, the result mpint may be
58*8ccd4a63SDavid du Colombier // the same as one of the inputs.
59*8ccd4a63SDavid du Colombier void	mpadd(mpint *b1, mpint *b2, mpint *sum);	// sum = b1+b2
60*8ccd4a63SDavid du Colombier void	mpsub(mpint *b1, mpint *b2, mpint *diff);	// diff = b1-b2
61*8ccd4a63SDavid du Colombier void	mpleft(mpint *b, int shift, mpint *res);	// res = b<<shift
62*8ccd4a63SDavid du Colombier void	mpright(mpint *b, int shift, mpint *res);	// res = b>>shift
63*8ccd4a63SDavid du Colombier void	mpmul(mpint *b1, mpint *b2, mpint *prod);	// prod = b1*b2
64*8ccd4a63SDavid du Colombier void	mpexp(mpint *b, mpint *e, mpint *m, mpint *res);	// res = b**e mod m
65*8ccd4a63SDavid du Colombier void	mpmod(mpint *b, mpint *m, mpint *remainder);	// remainder = b mod m
66*8ccd4a63SDavid du Colombier 
67*8ccd4a63SDavid du Colombier // quotient = dividend/divisor, remainder = dividend % divisor
68*8ccd4a63SDavid du Colombier void	mpdiv(mpint *dividend, mpint *divisor,  mpint *quotient, mpint *remainder);
69*8ccd4a63SDavid du Colombier 
70*8ccd4a63SDavid du Colombier // return neg, 0, pos as b1-b2 is neg, 0, pos
71*8ccd4a63SDavid du Colombier int	mpcmp(mpint *b1, mpint *b2);
72*8ccd4a63SDavid du Colombier 
73*8ccd4a63SDavid du Colombier // extended gcd return d, x, and y, s.t. d = gcd(a,b) and ax+by = d
74*8ccd4a63SDavid du Colombier void	mpextendedgcd(mpint *a, mpint *b, mpint *d, mpint *x, mpint *y);
75*8ccd4a63SDavid du Colombier 
76*8ccd4a63SDavid du Colombier // res = b**-1 mod m
77*8ccd4a63SDavid du Colombier void	mpinvert(mpint *b, mpint *m, mpint *res);
78*8ccd4a63SDavid du Colombier 
79*8ccd4a63SDavid du Colombier // bit counting
80*8ccd4a63SDavid du Colombier int	mpsignif(mpint*);	// number of sigificant bits in mantissa
81*8ccd4a63SDavid du Colombier int	mplowbits0(mpint*);	// k, where n = 2**k * q for odd q
82*8ccd4a63SDavid du Colombier 
83*8ccd4a63SDavid du Colombier // well known constants
84*8ccd4a63SDavid du Colombier extern mpint	*mpzero, *mpone, *mptwo;
85*8ccd4a63SDavid du Colombier 
86*8ccd4a63SDavid du Colombier // sum[0:alen] = a[0:alen-1] + b[0:blen-1]
87*8ccd4a63SDavid du Colombier // prereq: alen >= blen, sum has room for alen+1 digits
88*8ccd4a63SDavid du Colombier void	mpvecadd(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *sum);
89*8ccd4a63SDavid du Colombier 
90*8ccd4a63SDavid du Colombier // diff[0:alen-1] = a[0:alen-1] - b[0:blen-1]
91*8ccd4a63SDavid du Colombier // prereq: alen >= blen, diff has room for alen digits
92*8ccd4a63SDavid du Colombier void	mpvecsub(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *diff);
93*8ccd4a63SDavid du Colombier 
94*8ccd4a63SDavid du Colombier // p[0:n] += m * b[0:n-1]
95*8ccd4a63SDavid du Colombier // prereq: p has room for n+1 digits
96*8ccd4a63SDavid du Colombier void	mpvecdigmuladd(mpdigit *b, int n, mpdigit m, mpdigit *p);
97*8ccd4a63SDavid du Colombier 
98*8ccd4a63SDavid du Colombier // p[0:n] -= m * b[0:n-1]
99*8ccd4a63SDavid du Colombier // prereq: p has room for n+1 digits
100*8ccd4a63SDavid du Colombier int	mpvecdigmulsub(mpdigit *b, int n, mpdigit m, mpdigit *p);
101*8ccd4a63SDavid du Colombier 
102*8ccd4a63SDavid du Colombier // p[0:alen*blen-1] = a[0:alen-1] * b[0:blen-1]
103*8ccd4a63SDavid du Colombier // prereq: alen >= blen, p has room for m*n digits
104*8ccd4a63SDavid du Colombier void	mpvecmul(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *p);
105*8ccd4a63SDavid du Colombier 
106*8ccd4a63SDavid du Colombier // sign of a - b or zero if the same
107*8ccd4a63SDavid du Colombier int	mpveccmp(mpdigit *a, int alen, mpdigit *b, int blen);
108*8ccd4a63SDavid du Colombier 
109*8ccd4a63SDavid du Colombier // divide the 2 digit dividend by the one digit divisor and stick in quotient
110*8ccd4a63SDavid du Colombier // we assume that the result is one digit - overflow is all 1's
111*8ccd4a63SDavid du Colombier void	mpdigdiv(mpdigit *dividend, mpdigit divisor, mpdigit *quotient);
112*8ccd4a63SDavid du Colombier 
113*8ccd4a63SDavid du Colombier // playing with magnitudes
114*8ccd4a63SDavid du Colombier int	mpmagcmp(mpint *b1, mpint *b2);
115*8ccd4a63SDavid du Colombier void	mpmagadd(mpint *b1, mpint *b2, mpint *sum);	// sum = b1+b2
116*8ccd4a63SDavid du Colombier void	mpmagsub(mpint *b1, mpint *b2, mpint *sum);	// sum = b1+b2
117*8ccd4a63SDavid du Colombier 
118*8ccd4a63SDavid du Colombier // chinese remainder theorem
119*8ccd4a63SDavid du Colombier typedef struct CRTpre	CRTpre;		// precomputed values for converting
120*8ccd4a63SDavid du Colombier 					//  twixt residues and mpint
121*8ccd4a63SDavid du Colombier typedef struct CRTres	CRTres;		// residue form of an mpint
122*8ccd4a63SDavid du Colombier 
123*8ccd4a63SDavid du Colombier struct CRTres
124*8ccd4a63SDavid du Colombier {
125*8ccd4a63SDavid du Colombier 	int	n;		// number of residues
126*8ccd4a63SDavid du Colombier 	mpint	*r[1];		// residues
127*8ccd4a63SDavid du Colombier };
128*8ccd4a63SDavid du Colombier 
129*8ccd4a63SDavid du Colombier CRTpre*	crtpre(int, mpint**);			// precompute conversion values
130*8ccd4a63SDavid du Colombier CRTres*	crtin(CRTpre*, mpint*);			// convert mpint to residues
131*8ccd4a63SDavid du Colombier void	crtout(CRTpre*, CRTres*, mpint*);	// convert residues to mpint
132*8ccd4a63SDavid du Colombier void	crtprefree(CRTpre*);
133*8ccd4a63SDavid du Colombier void	crtresfree(CRTres*);
134*8ccd4a63SDavid du Colombier 
135