forsyth20121205-174063a80cc13 years agoHistory
848 lines · 11.1 KB · C
RawDownload
#include "lib9.h"#include "kernel.h"#include <isa.h>#include "interp.h"#include "runt.h"#include <mp.h>#include <libsec.h>#include "pool.h"#include "ipint.h"#include "raise.h" #include "ipintsmod.h" enum{	MaxBigBytes = 1024}; /* infinite precision integer */struct IPint{	IPints_IPint x;	mpint*	b;}; Type	*TIPint;static uchar IPintmap[] = IPints_IPint_map; #define	MP(x)	checkIPint((x)) voidipintsmodinit(void){	/* can be called from modinit, Keyring or Crypt */	if(TIPint == nil)		TIPint = dtype(freeIPint, sizeof(IPint), IPintmap, sizeof(IPintmap));	builtinmod("$IPints", IPintsmodtab, IPintsmodlen);} //IPints_IPint*void*newIPint(mpint* b){	Heap *h;	IPint *ip; 	if(b == nil)		error(exHeap);	h = heap(TIPint);	/* TO DO: caller might lose other values if heap raises error here */	ip = H2D(IPint*, h);	ip->b = b;	return (IPints_IPint*)ip;} mpint*checkIPint(void *a){	IPints_IPint *v;	IPint *ip; 	v = a;	ip = (IPint*)v;	if(ip == H || ip == nil)		error(exNilref);	if(D2H(ip)->t != TIPint)		error(exType);	return ip->b;	/* non-nil by construction */} voidfreeIPint(Heap *h, int swept){	IPint *ip; 	USED(swept);	ip = H2D(IPint*, h);	if(ip->b)		mpfree(ip->b);	freeheap(h, 0);} voidIPint_iptob64z(void *fp){	F_IPint_iptob64 *f;	mpint *b;	char buf[MaxBigBytes];	/* TO DO: should allocate these */	uchar *p;	int n, o;	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	b = MP(f->i);	n = (b->top+1)*Dbytes;	p = malloc(n+1);	if(p == nil)		error(exHeap);	n = mptobe(b, p+1, n, nil);	if(n < 0){		free(p);		return;	}	p[0] = 0;	if(n != 0 && (p[1]&0x80)){		/* force leading 0 byte for compatibility with older representation */		o = 0;		n++;	}else		o = 1;	enc64(buf, sizeof(buf), p+o, n);	retstr(buf, f->ret);	free(p);} voidIPint_iptob64(void *fp){	F_IPint_iptob64 *f;	char buf[MaxBigBytes];	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	mptoa(MP(f->i), 64, buf, sizeof(buf));	retstr(buf, f->ret);} voidIPint_iptobytes(void *fp){	F_IPint_iptobytes *f;	uchar buf[MaxBigBytes];	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	/* TO DO: two's complement or have ipmagtobe? */	*f->ret = mem2array(buf, mptobe(MP(f->i), buf, sizeof(buf), nil));	/* for now we'll ignore sign */} voidIPint_iptobebytes(void *fp){	F_IPint_iptobebytes *f;	uchar buf[MaxBigBytes];	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	*f->ret = mem2array(buf, mptobe(MP(f->i), buf, sizeof(buf), nil));} voidIPint_iptostr(void *fp){	F_IPint_iptostr *f;	char buf[MaxBigBytes];	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	mptoa(MP(f->i), f->base, buf, sizeof(buf));	retstr(buf, f->ret);} static IPints_IPint*strtoipint(String *s, int base){	char *p, *q;	mpint *b; 	p = string2c(s);	b = strtomp(p, &q, base, nil);	if(b == nil)		return H;	while(*q == '=')		q++;	if(q == p || *q != 0){		mpfree(b);		return H;	}	return newIPint(b);} voidIPint_b64toip(void *fp){	F_IPint_b64toip *f;	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	*f->ret = strtoipint(f->str, 64);} voidIPint_bytestoip(void *fp){	F_IPint_bytestoip *f;	mpint *b;	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	if(f->buf == H)		error(exNilref); 	b = betomp(f->buf->data, f->buf->len, nil);	/* for now we'll ignore sign */	*f->ret = newIPint(b);} voidIPint_bebytestoip(void *fp){	F_IPint_bebytestoip *f;	mpint *b;	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	if(f->mag == H)		error(exNilref); 	b = betomp(f->mag->data, f->mag->len, nil);	*f->ret = newIPint(b);} voidIPint_strtoip(void *fp){	F_IPint_strtoip *f;	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	*f->ret = strtoipint(f->str, f->base);} /* create a random integer */voidIPint_random(void *fp){	F_IPint_random *f;	mpint *b;	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	release();	b = mprand(f->nbits, genrandom, nil);	acquire();	*f->ret = newIPint(b);} /* number of bits in number */voidIPint_bits(void *fp){	F_IPint_bits *f;	int n; 	f = fp;	*f->ret = 0;	if(f->i == H)		return; 	n = mpsignif(MP(f->i));	if(n == 0)		n = 1;	/* compatibility */	*f->ret = n;} /* create a new IP from an int */voidIPint_inttoip(void *fp){	F_IPint_inttoip *f;	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	*f->ret = newIPint(itomp(f->i, nil));} voidIPint_iptoint(void *fp){	F_IPint_iptoint *f; 	f = fp;	*f->ret = 0;	if(f->i == H)		return;	*f->ret = mptoi(MP(f->i));} /* modular exponentiation */voidIPint_expmod(void *fp){	F_IPint_expmod *f;	mpint *ret, *mod, *base, *exp;	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	base = MP(f->base);	exp = MP(f->exp);	if(f->mod != H)		mod = MP(f->mod);	else		mod = nil;	ret = mpnew(0);	if(ret != nil)		mpexp(base, exp, mod, ret);	*f->ret = newIPint(ret);} /* multiplicative inverse */voidIPint_invert(void *fp){	F_IPint_invert *f;	mpint *ret;	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	ret = mpnew(0);	if(ret != nil)		mpinvert(MP(f->base), MP(f->mod), ret);	*f->ret = newIPint(ret);} /* basic math */voidIPint_add(void *fp){	F_IPint_add *f;	mpint *i1, *i2, *ret;	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	i1 = MP(f->i1);	i2 = MP(f->i2);	ret = mpnew(0);	if(ret != nil)		mpadd(i1, i2, ret); 	*f->ret = newIPint(ret);}voidIPint_sub(void *fp){	F_IPint_sub *f;	mpint *i1, *i2, *ret;	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	i1 = MP(f->i1);	i2 = MP(f->i2);	ret = mpnew(0);	if(ret != nil)		mpsub(i1, i2, ret); 	*f->ret = newIPint(ret);}voidIPint_mul(void *fp){	F_IPint_mul *f;	mpint *i1, *i2, *ret;	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	i1 = MP(f->i1);	i2 = MP(f->i2);	ret = mpnew(0);	if(ret != nil)		mpmul(i1, i2, ret); 	*f->ret = newIPint(ret);}voidIPint_div(void *fp){	F_IPint_div *f;	mpint *i1, *i2, *quo, *rem;	void *v; 	f = fp;	v = f->ret->t0;	f->ret->t0 = H;	destroy(v);	v = f->ret->t1;	f->ret->t1 = H;	destroy(v); 	i1 = MP(f->i1);	i2 = MP(f->i2);	quo = mpnew(0);	if(quo == nil)		error(exHeap);	rem = mpnew(0);	if(rem == nil){		mpfree(quo);		error(exHeap);	}	mpdiv(i1, i2, quo, rem); 	f->ret->t0 = newIPint(quo);	f->ret->t1 = newIPint(rem);}voidIPint_mod(void *fp){	F_IPint_mod *f;	mpint *i1, *i2, *ret;	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	i1 = MP(f->i1);	i2 = MP(f->i2);	ret = mpnew(0);	if(ret != nil)		mpmod(i1, i2, ret); 	*f->ret = newIPint(ret);}voidIPint_neg(void *fp){	F_IPint_neg *f;	mpint *ret;	void *v; 	f = fp;	v = *f->ret;	*f->ret = H;	destroy(v); 	ret = mpcopy(MP(f->i));	if(ret == nil)		error(exHeap);

Lines 1–500 of 848.