xref: /plan9/sys/src/libmp/port/mpaux.c (revision 9027b8f78b93f49ddfe75d1dcbf015f5ad6582b6)
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