diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/libmp/port/mpaux.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libmp/port/mpaux.c')
-rwxr-xr-x | sys/src/libmp/port/mpaux.c | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/sys/src/libmp/port/mpaux.c b/sys/src/libmp/port/mpaux.c new file mode 100755 index 000000000..66f1524f0 --- /dev/null +++ b/sys/src/libmp/port/mpaux.c @@ -0,0 +1,190 @@ +#include "os.h" +#include <mp.h> +#include "dat.h" + +static mpdigit _mptwodata[1] = { 2 }; +static mpint _mptwo = +{ + 1, + 1, + 1, + _mptwodata, + MPstatic +}; +mpint *mptwo = &_mptwo; + +static mpdigit _mponedata[1] = { 1 }; +static mpint _mpone = +{ + 1, + 1, + 1, + _mponedata, + MPstatic +}; +mpint *mpone = &_mpone; + +static mpdigit _mpzerodata[1] = { 0 }; +static mpint _mpzero = +{ + 1, + 1, + 0, + _mpzerodata, + MPstatic +}; +mpint *mpzero = &_mpzero; + +static int mpmindigits = 33; + +// set minimum digit allocation +void +mpsetminbits(int n) +{ + if(n < 0) + sysfatal("mpsetminbits: n < 0"); + if(n == 0) + n = 1; + mpmindigits = DIGITS(n); +} + +// allocate an n bit 0'd number +mpint* +mpnew(int n) +{ + mpint *b; + + if(n < 0) + sysfatal("mpsetminbits: n < 0"); + + b = mallocz(sizeof(mpint), 1); + setmalloctag(b, getcallerpc(&n)); + if(b == nil) + sysfatal("mpnew: %r"); + n = DIGITS(n); + if(n < mpmindigits) + n = mpmindigits; + b->p = (mpdigit*)mallocz(n*Dbytes, 1); + if(b->p == nil) + sysfatal("mpnew: %r"); + b->size = n; + b->sign = 1; + + return b; +} + +// guarantee at least n significant bits +void +mpbits(mpint *b, int m) +{ + int n; + + n = DIGITS(m); + if(b->size >= n){ + if(b->top >= n) + return; + memset(&b->p[b->top], 0, Dbytes*(n - b->top)); + b->top = n; + return; + } + b->p = (mpdigit*)realloc(b->p, n*Dbytes); + if(b->p == nil) + sysfatal("mpbits: %r"); + memset(&b->p[b->top], 0, Dbytes*(n - b->top)); + b->size = n; + b->top = n; +} + +void +mpfree(mpint *b) +{ + if(b == nil) + return; + if(b->flags & MPstatic) + sysfatal("freeing mp constant"); + memset(b->p, 0, b->size*Dbytes); // information hiding + free(b->p); + free(b); +} + +void +mpnorm(mpint *b) +{ + int i; + + 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; +} + +mpint* +mpcopy(mpint *old) +{ + mpint *new; + + new = mpnew(Dbits*old->size); + new->top = old->top; + new->sign = old->sign; + memmove(new->p, old->p, Dbytes*old->top); + return new; +} + +void +mpassign(mpint *old, mpint *new) +{ + mpbits(new, Dbits*old->top); + new->sign = old->sign; + new->top = old->top; + memmove(new->p, old->p, Dbytes*old->top); +} + +// number of significant bits in mantissa +int +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)<<j)) + return i*Dbits + j + 1; + } + } + return 0; +} + +// k, where n = 2**k * q for odd q +int +mplowbits0(mpint *n) +{ + int k, bit, digit; + mpdigit d; + + if(n->top==0) + return 0; + k = 0; + bit = 0; + digit = 0; + d = n->p[0]; + for(;;){ + if(d & (1<<bit)) + break; + k++; + bit++; + if(bit==Dbits){ + if(++digit >= n->top) + return 0; + d = n->p[digit]; + bit = 0; + } + } + return k; +} + |