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