17dd7cddfSDavid du Colombier #include "os.h"
27dd7cddfSDavid du Colombier #include <mp.h>
37dd7cddfSDavid du Colombier #include "dat.h"
47dd7cddfSDavid du Colombier
57dd7cddfSDavid du Colombier static mpdigit _mptwodata[1] = { 2 };
67dd7cddfSDavid du Colombier static mpint _mptwo =
77dd7cddfSDavid du Colombier {
87dd7cddfSDavid du Colombier 1,
97dd7cddfSDavid du Colombier 1,
107dd7cddfSDavid du Colombier 1,
117dd7cddfSDavid du Colombier _mptwodata,
127dd7cddfSDavid du Colombier MPstatic
137dd7cddfSDavid du Colombier };
147dd7cddfSDavid du Colombier mpint *mptwo = &_mptwo;
157dd7cddfSDavid du Colombier
167dd7cddfSDavid du Colombier static mpdigit _mponedata[1] = { 1 };
177dd7cddfSDavid du Colombier static mpint _mpone =
187dd7cddfSDavid du Colombier {
197dd7cddfSDavid du Colombier 1,
207dd7cddfSDavid du Colombier 1,
217dd7cddfSDavid du Colombier 1,
227dd7cddfSDavid du Colombier _mponedata,
237dd7cddfSDavid du Colombier MPstatic
247dd7cddfSDavid du Colombier };
257dd7cddfSDavid du Colombier mpint *mpone = &_mpone;
267dd7cddfSDavid du Colombier
277dd7cddfSDavid du Colombier static mpdigit _mpzerodata[1] = { 0 };
287dd7cddfSDavid du Colombier static mpint _mpzero =
297dd7cddfSDavid du Colombier {
307dd7cddfSDavid du Colombier 1,
317dd7cddfSDavid du Colombier 1,
327dd7cddfSDavid du Colombier 0,
337dd7cddfSDavid du Colombier _mpzerodata,
347dd7cddfSDavid du Colombier MPstatic
357dd7cddfSDavid du Colombier };
367dd7cddfSDavid du Colombier mpint *mpzero = &_mpzero;
377dd7cddfSDavid du Colombier
387dd7cddfSDavid du Colombier static int mpmindigits = 33;
397dd7cddfSDavid du Colombier
407dd7cddfSDavid du Colombier // set minimum digit allocation
417dd7cddfSDavid du Colombier void
mpsetminbits(int n)427dd7cddfSDavid du Colombier mpsetminbits(int n)
437dd7cddfSDavid du Colombier {
44dc5a79c1SDavid du Colombier if(n < 0)
45dc5a79c1SDavid du Colombier sysfatal("mpsetminbits: n < 0");
467dd7cddfSDavid du Colombier if(n == 0)
477dd7cddfSDavid du Colombier n = 1;
487dd7cddfSDavid du Colombier mpmindigits = DIGITS(n);
497dd7cddfSDavid du Colombier }
507dd7cddfSDavid du Colombier
517dd7cddfSDavid du Colombier // allocate an n bit 0'd number
527dd7cddfSDavid du Colombier mpint*
mpnew(int n)537dd7cddfSDavid du Colombier mpnew(int n)
547dd7cddfSDavid du Colombier {
557dd7cddfSDavid du Colombier mpint *b;
567dd7cddfSDavid du Colombier
57dc5a79c1SDavid du Colombier if(n < 0)
58dc5a79c1SDavid du Colombier sysfatal("mpsetminbits: n < 0");
59dc5a79c1SDavid du Colombier
607dd7cddfSDavid du Colombier b = mallocz(sizeof(mpint), 1);
61*9027b8f7SDavid du Colombier setmalloctag(b, getcallerpc(&n));
627dd7cddfSDavid du Colombier if(b == nil)
639a747e4fSDavid du Colombier sysfatal("mpnew: %r");
647dd7cddfSDavid du Colombier n = DIGITS(n);
657dd7cddfSDavid du Colombier if(n < mpmindigits)
667dd7cddfSDavid du Colombier n = mpmindigits;
677dd7cddfSDavid du Colombier b->p = (mpdigit*)mallocz(n*Dbytes, 1);
687dd7cddfSDavid du Colombier if(b->p == nil)
699a747e4fSDavid du Colombier sysfatal("mpnew: %r");
707dd7cddfSDavid du Colombier b->size = n;
717dd7cddfSDavid du Colombier b->sign = 1;
727dd7cddfSDavid du Colombier
737dd7cddfSDavid du Colombier return b;
747dd7cddfSDavid du Colombier }
757dd7cddfSDavid du Colombier
767dd7cddfSDavid du Colombier // guarantee at least n significant bits
777dd7cddfSDavid du Colombier void
mpbits(mpint * b,int m)787dd7cddfSDavid du Colombier mpbits(mpint *b, int m)
797dd7cddfSDavid du Colombier {
807dd7cddfSDavid du Colombier int n;
817dd7cddfSDavid du Colombier
827dd7cddfSDavid du Colombier n = DIGITS(m);
837dd7cddfSDavid du Colombier if(b->size >= n){
8459cc4ca5SDavid du Colombier if(b->top >= n)
857dd7cddfSDavid du Colombier return;
867dd7cddfSDavid du Colombier memset(&b->p[b->top], 0, Dbytes*(n - b->top));
877dd7cddfSDavid du Colombier b->top = n;
887dd7cddfSDavid du Colombier return;
897dd7cddfSDavid du Colombier }
907dd7cddfSDavid du Colombier b->p = (mpdigit*)realloc(b->p, n*Dbytes);
917dd7cddfSDavid du Colombier if(b->p == nil)
929a747e4fSDavid du Colombier sysfatal("mpbits: %r");
937dd7cddfSDavid du Colombier memset(&b->p[b->top], 0, Dbytes*(n - b->top));
947dd7cddfSDavid du Colombier b->size = n;
957dd7cddfSDavid du Colombier b->top = n;
967dd7cddfSDavid du Colombier }
977dd7cddfSDavid du Colombier
987dd7cddfSDavid du Colombier void
mpfree(mpint * b)997dd7cddfSDavid du Colombier mpfree(mpint *b)
1007dd7cddfSDavid du Colombier {
1017dd7cddfSDavid du Colombier if(b == nil)
1027dd7cddfSDavid du Colombier return;
1037dd7cddfSDavid du Colombier if(b->flags & MPstatic)
1047dd7cddfSDavid du Colombier sysfatal("freeing mp constant");
105dc5a79c1SDavid du Colombier memset(b->p, 0, b->size*Dbytes); // information hiding
1067dd7cddfSDavid du Colombier free(b->p);
1077dd7cddfSDavid du Colombier free(b);
1087dd7cddfSDavid du Colombier }
1097dd7cddfSDavid du Colombier
1107dd7cddfSDavid du Colombier void
mpnorm(mpint * b)1117dd7cddfSDavid du Colombier mpnorm(mpint *b)
1127dd7cddfSDavid du Colombier {
1137dd7cddfSDavid du Colombier int i;
1147dd7cddfSDavid du Colombier
1157dd7cddfSDavid du Colombier for(i = b->top-1; i >= 0; i--)
1167dd7cddfSDavid du Colombier if(b->p[i] != 0)
1177dd7cddfSDavid du Colombier break;
1187dd7cddfSDavid du Colombier b->top = i+1;
1197dd7cddfSDavid du Colombier if(b->top == 0)
1207dd7cddfSDavid du Colombier b->sign = 1;
1217dd7cddfSDavid du Colombier }
1227dd7cddfSDavid du Colombier
1237dd7cddfSDavid du Colombier mpint*
mpcopy(mpint * old)1247dd7cddfSDavid du Colombier mpcopy(mpint *old)
1257dd7cddfSDavid du Colombier {
1267dd7cddfSDavid du Colombier mpint *new;
1277dd7cddfSDavid du Colombier
1287dd7cddfSDavid du Colombier new = mpnew(Dbits*old->size);
1297dd7cddfSDavid du Colombier new->top = old->top;
1307dd7cddfSDavid du Colombier new->sign = old->sign;
1317dd7cddfSDavid du Colombier memmove(new->p, old->p, Dbytes*old->top);
1327dd7cddfSDavid du Colombier return new;
1337dd7cddfSDavid du Colombier }
1347dd7cddfSDavid du Colombier
1357dd7cddfSDavid du Colombier void
mpassign(mpint * old,mpint * new)1367dd7cddfSDavid du Colombier mpassign(mpint *old, mpint *new)
1377dd7cddfSDavid du Colombier {
1387dd7cddfSDavid du Colombier mpbits(new, Dbits*old->top);
1397dd7cddfSDavid du Colombier new->sign = old->sign;
14059cc4ca5SDavid du Colombier new->top = old->top;
1417dd7cddfSDavid du Colombier memmove(new->p, old->p, Dbytes*old->top);
1427dd7cddfSDavid du Colombier }
1437dd7cddfSDavid du Colombier
1447dd7cddfSDavid du Colombier // number of significant bits in mantissa
1457dd7cddfSDavid du Colombier int
mpsignif(mpint * n)1467dd7cddfSDavid du Colombier mpsignif(mpint *n)
1477dd7cddfSDavid du Colombier {
1487dd7cddfSDavid du Colombier int i, j;
1497dd7cddfSDavid du Colombier mpdigit d;
1507dd7cddfSDavid du Colombier
1517dd7cddfSDavid du Colombier if(n->top == 0)
1527dd7cddfSDavid du Colombier return 0;
1537dd7cddfSDavid du Colombier for(i = n->top-1; i >= 0; i--){
1547dd7cddfSDavid du Colombier d = n->p[i];
1557dd7cddfSDavid du Colombier for(j = Dbits-1; j >= 0; j--){
1567dd7cddfSDavid du Colombier if(d & (((mpdigit)1)<<j))
1577dd7cddfSDavid du Colombier return i*Dbits + j + 1;
1587dd7cddfSDavid du Colombier }
1597dd7cddfSDavid du Colombier }
1607dd7cddfSDavid du Colombier return 0;
1617dd7cddfSDavid du Colombier }
1627dd7cddfSDavid du Colombier
1637dd7cddfSDavid du Colombier // k, where n = 2**k * q for odd q
1647dd7cddfSDavid du Colombier int
mplowbits0(mpint * n)1657dd7cddfSDavid du Colombier mplowbits0(mpint *n)
1667dd7cddfSDavid du Colombier {
1677dd7cddfSDavid du Colombier int k, bit, digit;
1687dd7cddfSDavid du Colombier mpdigit d;
1697dd7cddfSDavid du Colombier
1707dd7cddfSDavid du Colombier if(n->top==0)
1717dd7cddfSDavid du Colombier return 0;
1727dd7cddfSDavid du Colombier k = 0;
1737dd7cddfSDavid du Colombier bit = 0;
1747dd7cddfSDavid du Colombier digit = 0;
1757dd7cddfSDavid du Colombier d = n->p[0];
1767dd7cddfSDavid du Colombier for(;;){
1777dd7cddfSDavid du Colombier if(d & (1<<bit))
1787dd7cddfSDavid du Colombier break;
1797dd7cddfSDavid du Colombier k++;
1807dd7cddfSDavid du Colombier bit++;
1817dd7cddfSDavid du Colombier if(bit==Dbits){
1827dd7cddfSDavid du Colombier if(++digit >= n->top)
1837dd7cddfSDavid du Colombier return 0;
1847dd7cddfSDavid du Colombier d = n->p[digit];
1857dd7cddfSDavid du Colombier bit = 0;
1867dd7cddfSDavid du Colombier }
1877dd7cddfSDavid du Colombier }
1887dd7cddfSDavid du Colombier return k;
1897dd7cddfSDavid du Colombier }
1907dd7cddfSDavid du Colombier
191