aboutsummaryrefslogtreecommitdiff
path: root/libinterp/ipint.c
diff options
context:
space:
mode:
authorbhgv <bhgv.empire@gmail.com>2018-03-01 16:54:45 +0200
committerbhgv <bhgv.empire@gmail.com>2018-03-01 16:54:45 +0200
commitb786f20bbab5a59046aa78a2c6c2a11536497202 (patch)
tree0851ecdec889eb9b7ba3751cc04d4f0b474e4a9e /libinterp/ipint.c
inferno-os tree was separated from the inferno-os-android (separated from the Android driver)
Diffstat (limited to 'libinterp/ipint.c')
-rw-r--r--libinterp/ipint.c848
1 files changed, 848 insertions, 0 deletions
diff --git a/libinterp/ipint.c b/libinterp/ipint.c
new file mode 100644
index 0000000..5728420
--- /dev/null
+++ b/libinterp/ipint.c
@@ -0,0 +1,848 @@
+#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))
+
+void
+ipintsmodinit(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 */
+}
+
+void
+freeIPint(Heap *h, int swept)
+{
+ IPint *ip;
+
+ USED(swept);
+ ip = H2D(IPint*, h);
+ if(ip->b)
+ mpfree(ip->b);
+ freeheap(h, 0);
+}
+
+void
+IPint_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);
+}
+
+void
+IPint_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);
+}
+
+void
+IPint_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 */
+}
+
+void
+IPint_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));
+}
+
+void
+IPint_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);
+}
+
+void
+IPint_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);
+}
+
+void
+IPint_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);
+}
+
+void
+IPint_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);
+}
+
+void
+IPint_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 */
+void
+IPint_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 */
+void
+IPint_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 */
+void
+IPint_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));
+}
+
+void
+IPint_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 */
+void
+IPint_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 */
+void
+IPint_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 */
+void
+IPint_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);
+}
+void
+IPint_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);
+}
+void
+IPint_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);
+}
+void
+IPint_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);
+}
+void
+IPint_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);
+}
+void
+IPint_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);
+ ret->sign = -ret->sign;
+
+ *f->ret = newIPint(ret);
+}
+
+/* copy */
+void
+IPint_copy(void *fp)
+{
+ F_IPint_copy *f;
+ void *v;
+
+ f = fp;
+ v = *f->ret;
+ *f->ret = H;
+ destroy(v);
+
+ *f->ret = newIPint(mpcopy(MP(f->i)));
+}
+
+
+/* equality */
+void
+IPint_eq(void *fp)
+{
+ F_IPint_eq *f;
+
+ f = fp;
+ *f->ret = mpcmp(MP(f->i1), MP(f->i2)) == 0;
+}
+
+/* compare */
+void
+IPint_cmp(void *fp)
+{
+ F_IPint_eq *f;
+
+ f = fp;
+ *f->ret = mpcmp(MP(f->i1), MP(f->i2));
+}
+
+/* shifts */
+void
+IPint_shl(void *fp)
+{
+ F_IPint_shl *f;
+ mpint *ret, *i;
+ void *v;
+
+ f = fp;
+ v = *f->ret;
+ *f->ret = H;
+ destroy(v);
+
+ i = MP(f->i);
+ ret = mpnew(0);
+ if(ret != nil)
+ mpleft(i, f->n, ret);
+ *f->ret = newIPint(ret);
+}
+void
+IPint_shr(void *fp)
+{
+ F_IPint_shr *f;
+ mpint *ret, *i;
+ void *v;
+
+ f = fp;
+ v = *f->ret;
+ *f->ret = H;
+ destroy(v);
+
+ i = MP(f->i);
+ ret = mpnew(0);
+ if(ret != nil)
+ mpright(i, f->n, ret);
+ *f->ret = newIPint(ret);
+}
+
+static void
+mpand(mpint *b, mpint *m, mpint *res)
+{
+ int i;
+
+ res->sign = b->sign;
+ if(b->top == 0 || m->top == 0){
+ res->top = 0;
+ return;
+ }
+ mpbits(res, b->top*Dbits);
+ res->top = b->top;
+ for(i = b->top; --i >= 0;){
+ if(i < m->top)
+ res->p[i] = b->p[i] & m->p[i];
+ else
+ res->p[i] = 0;
+ }
+ mpnorm(res);
+}
+
+static void
+mpor(mpint *b1, mpint *b2, mpint *res)
+{
+ mpint *t;
+ int i;
+
+ if(b2->top > b1->top){
+ t = b1;
+ b1 = b2;
+ b2 = t;
+ }
+ if(b1->top == 0){
+ mpassign(b2, res);
+ return;
+ }
+ if(b2->top == 0){
+ mpassign(b1, res);
+ return;
+ }
+ mpassign(b1, res);
+ for(i = b2->top; --i >= 0;)
+ res->p[i] |= b2->p[i];
+ mpnorm(res);
+}
+
+static void
+mpxor(mpint *b1, mpint *b2, mpint *res)
+{
+ mpint *t;
+ int i;
+
+ if(b2->top > b1->top){
+ t = b1;
+ b1 = b2;
+ b2 = t;
+ }
+ if(b1->top == 0){
+ mpassign(b2, res);
+ return;
+ }
+ if(b2->top == 0){
+ mpassign(b1, res);
+ return;
+ }
+ mpassign(b1, res);
+ for(i = b2->top; --i >= 0;)
+ res->p[i] ^= b2->p[i];
+ mpnorm(res);
+}
+
+static void
+mpnot(mpint *b1, mpint *res)
+{
+ int i;
+
+ mpbits(res, Dbits*b1->top);
+ res->sign = 1;
+ res->top = b1->top;
+ for(i = res->top; --i >= 0;)
+ res->p[i] = ~b1->p[i];
+ mpnorm(res);
+}
+
+/* bits */
+void
+IPint_and(void *fp)
+{
+ F_IPint_and *f;
+ mpint *ret, *i1, *i2;
+ 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)
+ mpand(i1, i2, ret);
+ *f->ret = newIPint(ret);
+}
+
+void
+IPint_ori(void *fp)
+{
+ F_IPint_ori *f;
+ mpint *ret, *i1, *i2;
+ 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)
+ mpor(i1, i2, ret);
+ *f->ret = newIPint(ret);
+}
+
+void
+IPint_xor(void *fp)
+{
+ F_IPint_xor *f;
+ mpint *ret, *i1, *i2;
+ 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)
+ mpxor(i1, i2, ret);
+ *f->ret = newIPint(ret);
+}
+
+void
+IPint_not(void *fp)
+{
+ F_IPint_not *f;
+ mpint *ret, *i1;
+ void *v;
+
+ f = fp;
+ v = *f->ret;
+ *f->ret = H;
+ destroy(v);
+
+ i1 = MP(f->i1);
+ ret = mpnew(0);
+ if(ret != nil)
+ mpnot(i1, ret);
+ *f->ret = newIPint(ret);
+}
+
+/*
+ * primes
+ */
+
+void
+IPints_probably_prime(void *fp)
+{
+ F_IPints_probably_prime *f;
+
+ f = fp;
+ release();
+ *f->ret = probably_prime(checkIPint(f->n), f->nrep);
+ acquire();
+}
+
+void
+IPints_genprime(void *fp)
+{
+ F_IPints_genprime *f;
+ mpint *p;
+ void *r;
+
+ f = fp;
+ r = *f->ret;
+ *f->ret = H;
+ destroy(r);
+ p = mpnew(0);
+ release();
+ genprime(p, f->nbits, f->nrep);
+ acquire();
+ *f->ret = newIPint(p);
+}
+
+void
+IPints_genstrongprime(void *fp)
+{
+ F_IPints_genstrongprime *f;
+ mpint *p;
+ void *r;
+
+ f = fp;
+ r = *f->ret;
+ *f->ret = H;
+ destroy(r);
+ p = mpnew(0);
+ release();
+ genstrongprime(p, f->nbits, f->nrep);
+ acquire();
+ *f->ret = newIPint(p);
+}
+
+void
+IPints_gensafeprime(void *fp)
+{
+ F_IPints_gensafeprime *f;
+ mpint *p, *alpha;
+ void *v;
+
+ f = fp;
+ v = f->ret->t0;
+ f->ret->t0 = H;
+ destroy(v);
+ v = f->ret->t1;
+ f->ret->t1 = H;
+ destroy(v);
+
+ p = mpnew(0);
+ alpha = mpnew(0);
+ release();
+ gensafeprime(p, alpha, f->nbits, f->nrep);
+ acquire();
+ f->ret->t0 = newIPint(p);
+ f->ret->t1 = newIPint(alpha);
+}
+
+void
+IPints_DSAprimes(void *fp)
+{
+ F_IPints_DSAprimes *f;
+ mpint *p, *q;
+ Heap *h;
+ void *v;
+
+ f = fp;
+ v = f->ret->t0;
+ f->ret->t0 = H;
+ destroy(v);
+ v = f->ret->t1;
+ f->ret->t1 = H;
+ destroy(v);
+ v = f->ret->t2;
+ f->ret->t2 = H;
+ destroy(v);
+
+ h = heaparray(&Tbyte, SHA1dlen);
+ f->ret->t2 = H2D(Array*, h);
+
+ p = mpnew(0);
+ q = mpnew(0);
+ release();
+ DSAprimes(q, p, f->ret->t2->data);
+ acquire();
+ f->ret->t0 = newIPint(q);
+ f->ret->t1 = newIPint(p);
+}