146d884bbSDavid du Colombier #ifndef _PLAN9_SOURCE 246d884bbSDavid du Colombier This header file is an extension to ANSI/POSIX 346d884bbSDavid du Colombier #endif 446d884bbSDavid du Colombier 546d884bbSDavid du Colombier #ifndef __LIBMP_H_ 646d884bbSDavid du Colombier #define __LIBMP_H_ 746d884bbSDavid du Colombier 8*ba4bf427SDavid du Colombier #pragma src "/sys/src/ape/lib/mp" 9*ba4bf427SDavid du Colombier #pragma lib "/$M/lib/ape/libmp.a" 1046d884bbSDavid du Colombier 1146d884bbSDavid du Colombier typedef unsigned int mpdigit; /* from /$objtype/include/u.h */ 1246d884bbSDavid du Colombier 1346d884bbSDavid du Colombier #define _MPINT 1 1446d884bbSDavid du Colombier 1546d884bbSDavid du Colombier /* 1646d884bbSDavid du Colombier * the code assumes mpdigit to be at least an int 1746d884bbSDavid du Colombier * mpdigit must be an atomic type. mpdigit is defined 1846d884bbSDavid du Colombier * in the architecture specific u.h 1946d884bbSDavid du Colombier */ 2046d884bbSDavid du Colombier 2146d884bbSDavid du Colombier typedef struct mpint mpint; 2246d884bbSDavid du Colombier 2346d884bbSDavid du Colombier struct mpint 2446d884bbSDavid du Colombier { 2546d884bbSDavid du Colombier int sign; /* +1 or -1 */ 2646d884bbSDavid du Colombier int size; /* allocated digits */ 2746d884bbSDavid du Colombier int top; /* significant digits */ 2846d884bbSDavid du Colombier mpdigit *p; 2946d884bbSDavid du Colombier char flags; 3046d884bbSDavid du Colombier }; 3146d884bbSDavid du Colombier 3246d884bbSDavid du Colombier enum 3346d884bbSDavid du Colombier { 3446d884bbSDavid du Colombier MPstatic= 0x01, 3546d884bbSDavid du Colombier Dbytes= sizeof(mpdigit), /* bytes per digit */ 3646d884bbSDavid du Colombier Dbits= Dbytes*8 /* bits per digit */ 3746d884bbSDavid du Colombier }; 3846d884bbSDavid du Colombier 3946d884bbSDavid du Colombier /* allocation */ 4046d884bbSDavid du Colombier void mpsetminbits(int n); /* newly created mpint's get at least n bits */ 4146d884bbSDavid du Colombier mpint* mpnew(int n); /* create a new mpint with at least n bits */ 4246d884bbSDavid du Colombier void mpfree(mpint *b); 4346d884bbSDavid du Colombier void mpbits(mpint *b, int n); /* ensure that b has at least n bits */ 4446d884bbSDavid du Colombier void mpnorm(mpint *b); /* dump leading zeros */ 4546d884bbSDavid du Colombier mpint* mpcopy(mpint *b); 4646d884bbSDavid du Colombier void mpassign(mpint *old, mpint *new); 4746d884bbSDavid du Colombier 4846d884bbSDavid du Colombier /* random bits */ 4946d884bbSDavid du Colombier mpint* mprand(int bits, void (*gen)(uchar*, int), mpint *b); 5046d884bbSDavid du Colombier 5146d884bbSDavid du Colombier /* conversion */ 5246d884bbSDavid du Colombier mpint* strtomp(char*, char**, int, mpint*); /* ascii */ 5346d884bbSDavid du Colombier int mpfmt(Fmt*); 5446d884bbSDavid du Colombier char* mptoa(mpint*, int, char*, int); 5546d884bbSDavid du Colombier mpint* letomp(uchar*, uint, mpint*); /* byte array, little-endian */ 5646d884bbSDavid du Colombier int mptole(mpint*, uchar*, uint, uchar**); 5746d884bbSDavid du Colombier mpint* betomp(uchar*, uint, mpint*); /* byte array, little-endian */ 5846d884bbSDavid du Colombier int mptobe(mpint*, uchar*, uint, uchar**); 5946d884bbSDavid du Colombier uint mptoui(mpint*); /* unsigned int */ 6046d884bbSDavid du Colombier mpint* uitomp(uint, mpint*); 6146d884bbSDavid du Colombier int mptoi(mpint*); /* int */ 6246d884bbSDavid du Colombier mpint* itomp(int, mpint*); 6346d884bbSDavid du Colombier uvlong mptouv(mpint*); /* unsigned vlong */ 6446d884bbSDavid du Colombier mpint* uvtomp(uvlong, mpint*); 6546d884bbSDavid du Colombier vlong mptov(mpint*); /* vlong */ 6646d884bbSDavid du Colombier mpint* vtomp(vlong, mpint*); 6746d884bbSDavid du Colombier 6846d884bbSDavid du Colombier /* divide 2 digits by one */ 6946d884bbSDavid du Colombier void mpdigdiv(mpdigit *dividend, mpdigit divisor, mpdigit *quotient); 7046d884bbSDavid du Colombier 7146d884bbSDavid du Colombier /* in the following, the result mpint may be */ 7246d884bbSDavid du Colombier /* the same as one of the inputs. */ 7346d884bbSDavid du Colombier void mpadd(mpint *b1, mpint *b2, mpint *sum); /* sum = b1+b2 */ 7446d884bbSDavid du Colombier void mpsub(mpint *b1, mpint *b2, mpint *diff); /* diff = b1-b2 */ 7546d884bbSDavid du Colombier void mpleft(mpint *b, int shift, mpint *res); /* res = b<<shift */ 7646d884bbSDavid du Colombier void mpright(mpint *b, int shift, mpint *res); /* res = b>>shift */ 7746d884bbSDavid du Colombier void mpmul(mpint *b1, mpint *b2, mpint *prod); /* prod = b1*b2 */ 7846d884bbSDavid du Colombier void mpexp(mpint *b, mpint *e, mpint *m, mpint *res); /* res = b**e mod m */ 7946d884bbSDavid du Colombier void mpmod(mpint *b, mpint *m, mpint *remainder); /* remainder = b mod m */ 8046d884bbSDavid du Colombier 8146d884bbSDavid du Colombier /* quotient = dividend/divisor, remainder = dividend % divisor */ 8246d884bbSDavid du Colombier void mpdiv(mpint *dividend, mpint *divisor, mpint *quotient, mpint *remainder); 8346d884bbSDavid du Colombier 8446d884bbSDavid du Colombier /* return neg, 0, pos as b1-b2 is neg, 0, pos */ 8546d884bbSDavid du Colombier int mpcmp(mpint *b1, mpint *b2); 8646d884bbSDavid du Colombier 8746d884bbSDavid du Colombier /* extended gcd return d, x, and y, s.t. d = gcd(a,b) and ax+by = d */ 8846d884bbSDavid du Colombier void mpextendedgcd(mpint *a, mpint *b, mpint *d, mpint *x, mpint *y); 8946d884bbSDavid du Colombier 9046d884bbSDavid du Colombier /* res = b**-1 mod m */ 9146d884bbSDavid du Colombier void mpinvert(mpint *b, mpint *m, mpint *res); 9246d884bbSDavid du Colombier 9346d884bbSDavid du Colombier /* bit counting */ 9446d884bbSDavid du Colombier int mpsignif(mpint*); /* number of sigificant bits in mantissa */ 9546d884bbSDavid du Colombier int mplowbits0(mpint*); /* k, where n = 2**k * q for odd q */ 9646d884bbSDavid du Colombier 9746d884bbSDavid du Colombier /* well known constants */ 9846d884bbSDavid du Colombier extern mpint *mpzero, *mpone, *mptwo; 9946d884bbSDavid du Colombier 10046d884bbSDavid du Colombier /* sum[0:alen] = a[0:alen-1] + b[0:blen-1] */ 10146d884bbSDavid du Colombier /* prereq: alen >= blen, sum has room for alen+1 digits */ 10246d884bbSDavid du Colombier void mpvecadd(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *sum); 10346d884bbSDavid du Colombier 10446d884bbSDavid du Colombier /* diff[0:alen-1] = a[0:alen-1] - b[0:blen-1] */ 10546d884bbSDavid du Colombier /* prereq: alen >= blen, diff has room for alen digits */ 10646d884bbSDavid du Colombier void mpvecsub(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *diff); 10746d884bbSDavid du Colombier 10846d884bbSDavid du Colombier /* p[0:n] += m * b[0:n-1] */ 10946d884bbSDavid du Colombier /* prereq: p has room for n+1 digits */ 11046d884bbSDavid du Colombier void mpvecdigmuladd(mpdigit *b, int n, mpdigit m, mpdigit *p); 11146d884bbSDavid du Colombier 11246d884bbSDavid du Colombier /* p[0:n] -= m * b[0:n-1] */ 11346d884bbSDavid du Colombier /* prereq: p has room for n+1 digits */ 11446d884bbSDavid du Colombier int mpvecdigmulsub(mpdigit *b, int n, mpdigit m, mpdigit *p); 11546d884bbSDavid du Colombier 11646d884bbSDavid du Colombier /* p[0:alen*blen-1] = a[0:alen-1] * b[0:blen-1] */ 11746d884bbSDavid du Colombier /* prereq: alen >= blen, p has room for m*n digits */ 11846d884bbSDavid du Colombier void mpvecmul(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *p); 11946d884bbSDavid du Colombier 12046d884bbSDavid du Colombier /* sign of a - b or zero if the same */ 12146d884bbSDavid du Colombier int mpveccmp(mpdigit *a, int alen, mpdigit *b, int blen); 12246d884bbSDavid du Colombier 12346d884bbSDavid du Colombier /* divide the 2 digit dividend by the one digit divisor and stick in quotient */ 12446d884bbSDavid du Colombier /* we assume that the result is one digit - overflow is all 1's */ 12546d884bbSDavid du Colombier void mpdigdiv(mpdigit *dividend, mpdigit divisor, mpdigit *quotient); 12646d884bbSDavid du Colombier 12746d884bbSDavid du Colombier /* playing with magnitudes */ 12846d884bbSDavid du Colombier int mpmagcmp(mpint *b1, mpint *b2); 12946d884bbSDavid du Colombier void mpmagadd(mpint *b1, mpint *b2, mpint *sum); /* sum = b1+b2 */ 13046d884bbSDavid du Colombier void mpmagsub(mpint *b1, mpint *b2, mpint *sum); /* sum = b1+b2 */ 13146d884bbSDavid du Colombier 13246d884bbSDavid du Colombier /* chinese remainder theorem */ 13346d884bbSDavid du Colombier typedef struct CRTpre CRTpre; /* precomputed values for converting */ 13446d884bbSDavid du Colombier /* twixt residues and mpint */ 13546d884bbSDavid du Colombier typedef struct CRTres CRTres; /* residue form of an mpint */ 13646d884bbSDavid du Colombier 13746d884bbSDavid du Colombier #pragma incomplete CRTpre 13846d884bbSDavid du Colombier 13946d884bbSDavid du Colombier struct CRTres 14046d884bbSDavid du Colombier { 14146d884bbSDavid du Colombier int n; /* number of residues */ 14246d884bbSDavid du Colombier mpint *r[1]; /* residues */ 14346d884bbSDavid du Colombier }; 14446d884bbSDavid du Colombier 14546d884bbSDavid du Colombier CRTpre* crtpre(int, mpint**); /* precompute conversion values */ 14646d884bbSDavid du Colombier CRTres* crtin(CRTpre*, mpint*); /* convert mpint to residues */ 14746d884bbSDavid du Colombier void crtout(CRTpre*, CRTres*, mpint*); /* convert residues to mpint */ 14846d884bbSDavid du Colombier void crtprefree(CRTpre*); 14946d884bbSDavid du Colombier void crtresfree(CRTres*); 15046d884bbSDavid du Colombier 15146d884bbSDavid du Colombier 15246d884bbSDavid du Colombier #pragma varargck type "B" mpint* 15346d884bbSDavid du Colombier #endif 154