#include "platform.h" #include "mp.h" static mpdigit _mptwodata[1] = { 2 }; static mpint _mptwo = { _mptwodata, 1, 1, 1, MPstatic|MPnorm }; mpint *mptwo = &_mptwo; static mpdigit _mponedata[1] = { 1 }; static mpint _mpone = { _mponedata, 1, 1, 1, MPstatic|MPnorm }; mpint *mpone = &_mpone; static mpdigit _mpzerodata[1] = { 0 }; static mpint _mpzero = { _mpzerodata, 1, 0, 1, MPstatic|MPnorm }; mpint *mpzero = &_mpzero; static int mpmindigits = 33; // set minimum digit allocation void mpsetminbits(int n) { if(n < 0) abort(); if(n == 0) n = 1; mpmindigits = DIGITS(n); } // allocate an n bit 0'd number mpint* mpnew(int n) { mpint *b; if(n < 0) abort(); n = DIGITS(n); if(n < mpmindigits) n = mpmindigits; b = MEM_CALLOC(1, sizeof(mpint) + n*Dbytes); if(b == nil) return nil; b->p = (mpdigit*)&b[1]; b->size = n; b->sign = 1; b->flags = MPnorm; return b; } // guarantee at least m significant bits void mpbits(mpint *b, int m) { u32int n; mpdigit *p; n = DIGITS(m); if(b->size >= n){ if(b->top >= n) return; } else { if(b->p == (mpdigit*)&b[1]){ p = (mpdigit*)MEM_ALLOC(n*Dbytes); if(p == nil) abort(); memmove(p, &b[1], Dbytes*b->top); b->p = p; } else { p = (mpdigit*)MEM_REALLOC(b->p, n*Dbytes); if(p == nil) abort(); b->p = p; } b->size = n; } memset(&b->p[b->top], 0, Dbytes*(n - b->top)); b->top = n; b->flags &= ~MPnorm; } void mpfree(mpint *b) { if(b == nil) return; if(b->flags & MPstatic) abort(); memset(b->p, 0, b->size*Dbytes); if(b->p != (mpdigit*)&b[1]) MEM_FREE(b->p); MEM_FREE(b); } mpint* mpnorm(mpint *b) { int i; if(b->flags & MPtimesafe){ assert(b->sign == 1); b->flags &= ~MPnorm; return b; } for(i = b->top-1; i >= 0; i--) if(b->p[i] != 0) break; b->top = i+1; if(b->top == 0) b->sign = 1; b->flags |= MPnorm; return b; } mpint* mpcopy(mpint *old) { mpint *new; new = mpnew(Dbits*old->size); if(new == nil) return nil; new->sign = old->sign; new->top = old->top; new->flags = old->flags & ~(MPstatic); memmove(new->p, old->p, Dbytes*old->top); return new; } void mpassign(mpint *old, mpint *new) { if(new == nil || old == new) return; new->top = 0; mpbits(new, Dbits*old->top); new->sign = old->sign; new->top = old->top; new->flags &= ~MPnorm; new->flags |= old->flags & ~(MPstatic); memmove(new->p, old->p, Dbytes*old->top); } // number of significant bits in mantissa u32int mpsignif(mpint *n) { int i, j; mpdigit d; if(n->top == 0) return 0; for(i = n->top-1; i >= 0; i--){ d = n->p[i]; for(j = Dbits-1; j >= 0; j--){ if(d & (((mpdigit)1)<