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