| #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); |
| 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; |
| } |
| |