Sindbad~EG File Manager
/* Bignum arithmetic package by M. Beeson */
/* Uses dynamic arrays instead of linked lists */
/* includes addition, subtraction, multiplication, division, exponentiation,
gcd, conversion to decimal form, and output. */
/* Instructions for use are given in bignum.h */
/*
11.3.88 Original date
5.3.94 modified for Windows;
put a static copy of shortshiftgcd here
introduced variable 'aa' to avoid a warning message
5.27.94 changed MAKELONG to MAKE_LONG
1.9.95 changed two remaining free 's to freespace in bigpower
3.13.96 Win32 port begun
3.21.96 eliminated macro MAKE_LONG in favor of calls to longmult and longdiv
3.24.95 addmod and mulmod written
3.25.96 rewrote bignum_double to use all significant digits
4.2.96 corrected syntax in 32-bit part of bignum_double
1.13.97 changed char* t= "four" to char t[5] in string_bignum and added t[4] = 0
3.31.97 changed assert(0) to return 1 in bignum_double.
6.18.97 Fixed a bug in bigdivide2 involving bigtrialq and trialq. Last bug
fixed, nine years after original date?
9.18.97 defined MAXINT here as values.h is a Borland file not available in Microsoft
9.18.97 changed i,j to unsigned in bigsqrt, bigroot, and string_bignum to suppress a warning
1.29.97 BIGNUMS_DLL etc.
5.8.98 changed bits to unsigned from int in bigpower. Added code to work around a
Microsoft bug in bigpower. Introduced 'max' in biggcd.
5.9.98 used LEFTDIGIT one more place where explicit hex notation was before.
Rewrote subaux.
Corrected btod for 32-bit compilation
Corrected compare for 32-bit compilation
10.13.98 some changes to work around VC bug, namely a >> expression inside
an if behaves as if it were nonzero even though it should be zero.
Corrected subaux for the case old_borrow == 0.
11.6.98 Added #ifndef __BORLANDC__ around the definition of 'c' to avoid a
warning that it's not used in 16-bit compilation.
1.15.99 corrected bigsqrt2 where we had the 16-bit and 32-bit code switched.
1.16.99 added freespace(bigtrialq.val) in a couple of places and made sure to set it
to NULL after it's been freed to avoid double freeing. This should ensure that bigdivide
allocates ONLY the space needed for the answer.
1.16.99 added one more 'freespace(s.val)' in btod.
1.18.99 changed 32-bit space allocation in btod.
3.29.99 corrected initialization of teven in bigroot2
3.29.99 corrected change from 1.18.99; should be 2* instead of /2.
5.23.99 corrected bigroot2, removing a useless and incorrect error return
that was causing failures, and removing looplimit, as it converges
for ANY starting value.
6.20.99 modified bignum_string to handle separator > 2
10.24.01 j=1 changed to j=0 line 1063 in bigsqrt2
9.28.03 corrected mod_digit_aux
Removed code used for 16-bit digits.
3.26.04 added line in bigdivide2 marked "Bug"
4.6.04 changed "pshift" to "left_shift" which is more descriptive
4.15.04 Changed the spec of bigsqrt2 and bigsqrt, and added coded in bigsqrt2 at lines 1015-1016
to meet the new spec. Modified bigroot2 similarly.
4.15.04 Modifed bigdivide2 to trap the case when dividend == divisor.
6.18.04 corrected that modification, which was blatantly wrong.
9.2.04 modified bignum_string to get rid of ultoa, using sprintf instead.
*/
#include <string.h>
#include <math.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h> /* strtoul */
#define BIGNUMS_DLL
#include "export.h"
#include "heap.h" /* callocate and free2 */
#include "bignum.h"
/* #define FFT comment this to turn off FFT multiplication */
#define MAXINT 0x7fffffff
#define DIGITSIZE sizeof(digit)
static void left_shift(bignum x, int i, bignum *y);
static unsigned shortshiftgcd(unsigned u, unsigned v);
digit *getspace(unsigned n)
/* allocate space for n bignum digits */
/* call nospace() to handle errors */
{ digit *ans = (digit *) callocate(n,DIGITSIZE);
if(ans == NULL)
nospace();
return ans;
}
/*________________ LOW-LEVEL ARITHMETIC ON DIGITS ____________*/
static void addaux(digit x, digit y, digit z, digit *sump, digit *carryp)
/* adds three digits producing a two-digit answer, carry and sum */
/* assuming the carry digit is always either 0 or 1 as will be true when
using this function for addition.
Based on the idea that MAX^m = 2^NN -1 -m, so that
(n > (MAX^m)) is the carry digit of n+m. (Here MAX^m is MAX XOR m,
and 2^NN is 2 to the power NN.)
I am indebted to Bill Giles for pointing this trick out to me.
*/
{ digit temp = x+y;
*sump = temp + z;
if( x > (y^MAX))
{ *carryp = 1;
return;
}
else if ( temp > (z^MAX) )
{ *carryp = 1;
return;
}
*carryp = 0;
}
/*_________________________________________________________________________*/
static void subaux(digit x, digit y, digit old_borrow, digit *sump, digit *borrowp)
/* called only with x > 0 or old_borrow == 0 */
/* subtract old_borrow + y from x if possible, getting *sump and
setting *borrowp = 0. If not possible, set *borrowp = 1 and
subtract old_borrow + y from x + 2^NN */
/* It is assumed that old_borrow is 0 or 1 */
{ digit s = y + old_borrow;
if(s == 0)
{ if(old_borrow == 0) /* so y == 0 too */
*borrowp = 0;
else
*borrowp = 1; /* when y == MAX and old_borrow == 1 */
*sump = x;
return;
}
*sump = x-s;
*borrowp = (s <= x) ? 0 : 1;
}
/*ADDITION________________________________________________________________*/
/* bigplus takes x and y and fills in the array ansp->val with the answer */
MEXPORT_BIGNUMS void bigplus2(bignum x, bignum y, bignum *ansp)
/* does not allocate space but presumes it done already */
{ unsigned i;
digit carry = 0;
if(x.ln < y.ln)
{ bigplus2(y,x,ansp);
return;
}
/* Now we can assume x is at least as long as y */
ansp->ln = (unsigned)(x.ln + 1);
for (i=0; i< y.ln; ++i)
{ addaux(x.val[i],y.val[i],carry,ansp->val + i,&carry);
/* ansp->val + i is the address of (*ansp).val[i] */
}
if( i < x.ln ) /* y has run out but x has not run out yet */
for ( ; i < x.ln; ++i)
addaux(x.val[i],0,carry, ansp->val + i, &carry);
if (carry)
ansp->val[i] = carry;
else
ansp->ln = (unsigned)(ansp->ln - 1);
/* ansp->ln -= 1 generates a warning, and this line generates the same
assembly code without generating a warning. */
}
MEXPORT_BIGNUMS void bigplus(bignum x, bignum y, bignum *ansp)
/* allocates space for the answer */
{ if(x.ln > y.ln)
ansp -> val = getspace(x.ln+1);
else
ansp -> val = getspace(y.ln + 1);
bigplus2(x,y,ansp);
}
/****************************************************************/
/* MULTIPLICATION */
MEXPORT_BIGNUMS void mult_by_digit2(bignum x, digit d, bignum *ansp)
/* does not allocate space */
/* multiply bignum by digit */
{ unsigned i;
unsigned carry = 0;
digit lo, hi;
if(d==0)
{ ansp->ln = 1;
ansp->val[0] = 0;
return;
}
for(i=0; i< x.ln ; i++)
{ longmult(x.val[i],d,&lo,&hi);
*(ansp->val+i) = lo + carry;
carry = hi + (lo > (MAX^carry));
}
if (carry )
{ ansp ->val [i] = carry;
ansp->ln = (unsigned)(x.ln + 1);
}
else
ansp->ln = x.ln;
}
MEXPORT_BIGNUMS void mult_by_digit(bignum x, digit d, bignum *ansp)
/* allocates space */
{ if(d==0)
{ ansp->val = getspace(2);
ansp->ln = 1;
ansp->val[0] = 0;
return;
}
ansp->val = getspace(x.ln + 1);
mult_by_digit2(x,d,ansp);
}
MEXPORT_BIGNUMS void bigmult2(bignum x, bignum y, bignum *ansp)
/* does not allocate space,expects it to have been done */
/* Inputs: x and y
Output: ansp. The array ansp->val will be filled during the computation.
ansp->val is presumed to have length at least x.ln + y.ln even though the
actual answer may be smaller.
*/
{
#ifdef FFT
fftmult(x,y,ansp);
#endif
#ifndef FFT
unsigned i,j;
digit lo,hi;
digit carry,tempcarry,tempsum;
if(x.ln < y.ln)
{ bigmult2(y,x,ansp); /* always multiply longer by shorter */
return;
}
/* check x.ln + y.ln for possible overflow. Although this is extremely
unlikely, it only costs 2 comparisons most of the time to keep the
program guaranteed correct. */
if(x.ln < MAXINT && y.ln < MAXINT) /* as it almost always will be */
ansp->ln = x.ln + y.ln; /* perhaps an overestimate */
else if (x.ln >= MAXINT && y.ln >= MAXINT)
nospace(); /* overflow */
else if (x.ln + y.ln < MAXINT)
nospace(); /* overflow; if one summand is more than MAX_INT and the other
is not, there is overflow iff the sum is < MAX_INT */
else
ansp->ln = x.ln + y.ln;
/*initialize ansp->val to zero */
for(i=0;i<ansp->ln;i++)
ansp->val[i] = 0;
/* start multiplying */
for(j=0; j< y.ln; j++) /* multiply x by j-th digit of y and add to *ansp */
{ carry = 0; /* re-initialize carry */
for(i=0; i< x.ln; i++)
{ addaux(carry,(ansp->val)[i+j],0,&tempsum,&tempcarry);
longmult(y.val[j],x.val[i],&lo,&hi);
*(ansp->val+i+j) = lo + tempsum;
/* ansp->val+i+j = &(ansp->val[i+j]) */
carry = hi + (lo > (MAX^tempsum));
if (tempcarry)
carry += tempcarry;
}
/* Now is there a leftover carry digit? */
ansp->val[i+j] += carry; /* zero or not */
}
/* Now strip off leading zero if necessary */
if (ansp->val[ansp->ln-1] == 0)
ansp->ln = (unsigned) (ansp->ln - 1);
/* avoid the warning generated by ansp->ln -= 1 */
#endif
}
MEXPORT_BIGNUMS void bigmult(bignum x, bignum y, bignum *ansp)
/* allocates space for the answer */
{
ansp->val = getspace(x.ln + y.ln);
bigmult2(x,y,ansp);
}
/* TEST INEQUALITY _____________________________________________________*/
MEXPORT_BIGNUMS int compare(bignum x, bignum y)
/* return negative, 0, or positive value according as x<y, x=y, or x>y */
{ unsigned i;
if ( x.ln > y.ln )
return 1;
else if (x.ln < y.ln)
return -1;
/*else x.ln = y.ln */
for(i=x.ln -1;i != MAX ;i--)
{ if(x.val[i] == y.val[i])
continue;
return (x.val[i] > y.val[i]) ? 1 : -1;
}
/* if you get this far they are equal */
return 0;
}
/*________________modular arithmetic on unsigneds___________________*/
MEXPORT_BIGNUMS unsigned addmod(unsigned a, unsigned b, unsigned m)
/* return a+b mod m, even if a+b overflows an unsigned */
{ unsigned carry,sum;
addaux(a,b,0,&carry,&sum);
if(carry == 0)
return sum % m;
else if(m <= MAXINT)
{ a = a % m;
b = b % m;
return (a+b) % m;
}
if(a >= m)
a = (unsigned) (a-m); // in effect, a = a % m, since a is no more than 2*m
if(b >= m)
b = (unsigned) (b-m);
addaux(a,b,0,&carry,&sum); // (a+b) < 2m but it still could overflow
if(carry)
return (unsigned) (sum-m); // correct in spite of overflow
return sum;
}
/*___________________________________________________________________*/
MEXPORT_BIGNUMS unsigned mulmod(unsigned a, unsigned b, unsigned m)
/* return a*b mod m, even if a*b overflows an unsigned */
{ bignum p; // the product
bignum q; // the quotient on division by m
unsigned ans;
digit data[2];
digit data2[3];
p.val = data;
q.val = data2;
longmult(a,b,data,data+1);
divide_by_digit2(p,m,&q,&ans);
return ans;
}
/*________________BIGNUM MOD DIGIT __________________________________*/
static digit mod_digit_aux(digit a, digit b, digit y)
/* return (a << NN | b) % y, but do so even if
digits are the same size as unsigned longs. */
{ /* (a*2^NN + b) mod y = (a%y * (2 * MAXINT) %y + b%y) %y */
if(y < (1 << (NN/2 - 1 ))) /* usually this will be the case */
/* Then we don't have to worry about overflow */
return ((a%y)*2 *(MAXINT %y) + b%y) %y;
else
{ /* We do have to worry about overflow */
unsigned p = MAXINT % y;
unsigned twop = (2*p) %y;
unsigned amody = a % y;
unsigned bmody = b % y;
return addmod(mulmod(amody,twop,y),bmody,y);
}
}
/*________________________________________________________________________*/
MEXPORT_BIGNUMS digit mod_digit(bignum x, digit y)
/* compute bignum x modulo a digit y */
{ unsigned int i;
digit s;
if (x.ln == 1 )
return x.val[0] % y;
else if (x.ln == 2)
return mod_digit_aux(x.val[1],x.val[0],y);
else
{ i= x.ln-2;
s = x.val[x.ln -1];
while (i != MAX)
{ s = mod_digit_aux(s,x.val[i],y);
--i;
}
return s;
}
}
/*________ BINARY TO DECIMAL______________________________________*/
MEXPORT_BIGNUMS bignum btod(bignum x, unsigned n)
/* x is in base 2^16 for 16-bit compilation, or base 2^32 for 32-bit compilation. */
/* returns a bignum base n; usually n = 1000 or 10000 */
{ /* first allocate space. If x has N digits, x <= B^N where B = 2^16,
so x <= 10^(3 (16/3 log 2)N) or 10 ^(4 (4 log 2)N). We have
(16/3) log 2 <= 1.60549332 and 4 log 2 <= 1.20411999 */
bignum ans,t,s;
unsigned i;
if (n==1000)
ans.ln = (unsigned ) (x.ln * 1.6054934 + 1);
else if (n==10000)
ans.ln = (unsigned) (x.ln * 1.20412 + 1);
else
ans.ln = (digit) (x.ln * (unsigned) sizeof(int) *
(unsigned)(log10(2.0)/log10((double)n)) + 1);
ans.ln = 2*ans.ln;
ans.val = getspace(ans.ln);
/* generate first digit of answer */
divide_by_digit(x,n,&s,ans.val);
for(i=1;i<ans.ln;i++) /* generate i-th digit of answer */
{ if((s.ln > 1) || (s.ln == 1 && s.val[0] != 0))
{ divide_by_digit(s,n,&t,ans.val + i);
freespace(s.val);
s = t;
}
else
ans.val[i] = 0;
}
freespace(s.val); /* last one hasn't been freed yet */
/* now strip off initial zeroes */
for(i = ans.ln-1; (ans.val[i] == 0 && i != MAX) ; --i)
--ans.ln; /* i !=MAX needed to stop loop in case answer is zero */
if (i==MAX)
ans.ln = 1;
return ans;
}
/*__________ SUBTRACTION ______________________________________*/
MEXPORT_BIGNUMS void bigminus2(bignum x, bignum y, bignum *ansp)
/* does not allocate space */
/* you can call bigminus(x,y,&x) safely, overwriting x.val */
/* subtract y from x getting ans */
/* it's assumed y is not greater than x */
{ unsigned i;
digit borrow = 0;
ansp->ln = x.ln;
for(i=0;i< ansp->ln; i++)
{ if (i >= y.ln)
{ if (borrow == 0)
ansp->val[i] = x.val[i];
else
subaux(x.val[i],0,borrow,(ansp->val) + i,&borrow);
}
else if (x.val[i] > 0 || borrow == 0)
subaux(x.val[i],y.val[i],borrow,(ansp->val)+i,&borrow);
else
{ /* borrow == 1 && x.val[i] == 0 */
/* put 0 in for borrow and MAX instead of MAX+1 */
subaux(MAX,y.val[i],0,(ansp->val)+i,&borrow);
borrow = 1;
}
}
/* Now strip off initial zeroes */
for(i=ansp->ln -1; (ansp->val[i]==0 && i!= MAX) ; --i) ; /* empty body of for loop */
if(i==MAX)
ansp->ln = 1; /* in case answer is zero, don't return length 0*/
else
ansp->ln = (unsigned)(i+1);
}
/*__________________________________________________________________*/
MEXPORT_BIGNUMS void bigminus(bignum x, bignum y, bignum *ansp)
/* allocates space for the answer */
{ ansp->ln = x.ln;
ansp->val = getspace(x.ln);
bigminus2(x,y,ansp);
}
/*___________________ DIVISION ______________________________________*/
static void left_shift(bignum x, int i, bignum *y)
/* y is passed unallocated and will be allocated */
/* given input bignum x, create a new bignum y and make it equal
to x shifted left by i bits (i<NN). Note that y may be one longer
than x was. */
{ unsigned j;
/* Theoretically we should check whether x.ln == (unsigned)(-1),
but why slow down normal operations for something that will never happen? */
y ->ln = (unsigned)(x.ln + 1); /* include room for an extra digit */
y->val = getspace(y->ln);
y->val[0] = x.val[0] << i;
for(j=1;j<x.ln;++j)
y->val[j]= (x.val[j] << i) | (x.val[j-1] >> (NN-i));
y->val[x.ln] = x.val[x.ln-1] >> (NN -i);
if (y->val[x.ln] == 0)
y->ln =(unsigned)(y->ln-1); /* extra digit not needed */
}
/*__________________________________________________________________*/
void right_shift(bignum x, int i, bignum *y)
/* not static, but not EXPORTed either; is called in bigmod.c */
/* y is passed already allocated */
/* given input bignum x, and a pointer y to a bignum with space
already allocated, make *y equal
to x shifted right by i bits (i<NN). Note that y may be one shorter
than x was. It's OK to have *y = x, in fact it will be normal to
call right_shift(x,i,&x). */
{ unsigned j;
for(j=0;j<x.ln-1;++j)
y->val[j]= (x.val[j] >> i) | (x.val[j+1] << (NN-i));
y->val[x.ln-1] = (x.val[x.ln-1] >> i);
if ((y->val[x.ln-1] == 0) && (x.ln > 1))
y->ln =(unsigned)(x.ln-1);
else
y->ln = x.ln;
}
/*__________________________________________________________________*/
/* divide a bignum x by a digit y, getting a bignum quotient and
digit remainder. This is more efficient than converting the digit y
to a bignum and using bigdivide. */
MEXPORT_BIGNUMS void divide_by_digit(bignum x, digit y, bignum *q, digit *r)
/* allocates space for the quotient */
/* but assumes space is already allocated for the remainder */
{ switch (y>>(NN-1))
{ case 0: /* left shifting dividend will be necessary */
q->val = getspace(x.ln+1);
break;
case 1: /* shifting not necessary */
q->val = getspace(x.ln);
break;
}
divide_by_digit2(x,y,q,r);
}
/*___________________________________________________________________*/
MEXPORT_BIGNUMS void divide_by_digit2(bignum x, digit y, bignum *q, digit *r)
/* assumes space already allocated */
/* assumes q has room for x.ln digits if
left-shifting quotient is not necessary and
one more if left-shifting quotient is necessary */
{ unsigned i;
digit c,d,trialq,test0,test1,product0,product1,rem;
bignum newx;
/* if x.ln <=2 then we can just use arithmetic on longs */
if (x.ln == 1)
{ q->ln = 1;
q->val[0] = x.val[0]/y;
*r = x.val[0] - q->val[0] * y;
return;
}
if (x.ln == 2)
{ if(x.val[1] < y)
{ /* one-digit quotient */
q->ln = 1;
longdiv(x.val[1],x.val[0],y,&q->val[0],r);
return;
}
/* Now the quotient will be two digits */
q->ln = 2;
q->val[1] = x.val[1]/y;
c = x.val[1] - y * (q->val[1]);
longdiv(c,x.val[0],y,&q->val[0],r);
return;
}
/* Now we can assume x.ln > 2, i.e. we have at least a three-digit dividend.*/
/* first we "normalize" by left-shifting both x and y the same number
of bits until the first bit of y is 1.
See below for the reason why we do that, and
Knuth vol. 2 p. 257 for the proofs.
*/
d= y;
for(i=0; (d & LEFTDIGIT) != LEFTDIGIT ; ++i)
d= d<<1; /* i counts the shifts */
if (i != 0)
{ left_shift(x,i,&newx);
divide_by_digit2(newx,d,q,r);
*r = (*r >> i); /* renormalize remainder */
freespace(newx.val); /* it was allocated by left_shift */
return;
}
/* henceforth we can assume the first bit of y is 1 */
newx.val = getspace(x.ln);
newx.ln = x.ln;
q->ln = x.ln; /* possibly one too big */
q->val[x.ln-1] = 0; /* in case it's never written to; it's checked later */
for (i=0; i < x.ln ; i++)
newx.val[i] = x.val[i];
i = i-2; /* = x.ln - 2 */
/* Entering the following loop, you have just subtracted, and newx represents
the last line of the calculation, without initial zeroes but
possibly with first digit bigger than first digit of y. The value of i
is newx.ln -2 at the beginning of the loop. We are going to write
ans.val[i], and possibly ans.val[i+1] in case the first digit of newx is
more than y. In that case we have previously written
zero there so it's ok to overwrite.
*/
while (i != MAX ) /* write i-th digit from right in answer,
i.e. power of base^i */
{ if(y <= newx.val[i+1])
{ q ->val[i+1] = 1;
newx.val[i+1] -=y;
assert(newx.val[i+1] < y); /* because y has 1 in the leftmost bit */
}
longdiv(newx.val[i+1],newx.val[i],y,&trialq,&rem);
/* Multiply back */
while (1)
{ test0 = newx.val[newx.ln-2];
test1 = newx.val[newx.ln-1];
longmult(y,trialq,&product0,&product1);
/* think of test1,test0 as a two-digit number test,
and product1,product0 as a two-digit number product.
We want to write
if(test < product)
--trialq;
*/
if(test1 < product1 || (test1 == product1 && test0 < product0))
-- trialq;
else
{ --newx.ln;
newx.val[newx.ln-1] -= product0;
break;
}
}
/* You have to go through that while loop AT MOST TWICE! That's why
we normalized the divisor. See Knuth volume 2. */
/* Moreover trialq is NEVER too small. */
q->val[i] = (digit) trialq; /* write this digit of the answer */
while((newx.val[i] == 0) && (i != 0 ))
{ --i;
q->val[i] = 0;
--newx.ln; /* strip off zeroes*/
}
--i;
}
/* finished, remainder is current value of newx */
/* Now adjust q->ln */
while(q->val[q->ln-1] == 0)
--q->ln;
*r = newx.val[0];
freespace(newx.val); /* release temporary workspace */
}
/*_____________________________________________________________*/
MEXPORT_BIGNUMS bignum long_to_bignum(unsigned long x)
/* convert x to a bignum */
/* presumes that either longs and digits are the same size or
longs are twice as long as digits
*/
{ bignum ans;
ans.ln = 1;
ans.val = getspace(1);
ans.val[0] = x;
return ans;
}
/*_____________________________________________________________*/
MEXPORT_BIGNUMS int bigdivide(bignum x, bignum y, bignum *q, bignum *r)
/* allocates space for the answers */
/* divide a bignum x by a bignum y, getting a bignum quotient and
remainder. Returns 0 for success, 2 for division by zero.
*/
{ if( compare(x,y) < 0 )
{ *r = x;
q->ln = 1;
q->val = getspace(1);
q->val[0]=0;
return 0;
}
/* Now we know the divisor is <= the dividend */
switch (y.val[y.ln-1] >> (NN-1))
{ case 0: /* left-shifting dividend will be necessary */
q->val = getspace(x.ln - y.ln +2);
r->val = getspace(y.ln + 1);
break;
case 1: /* shifting unnecessary */
q->val = getspace(x.ln - y.ln + 1);
r->val = getspace(y.ln);
break;
}
return bigdivide2(x,y,q,r);
}
/*_____________________________________________________________*/
/* bigdivide2 assumes space is already allocated for the answers.
It assumes there is space for x.ln - y.ln + 2 digits in the quotient
if left-shifting the dividend will be necessary, and one less if not,
even though the actual quotient may be one shorter.
It assumes there is space for y.ln +1 digits of remainder, in case
left-shifting is necessary (one more than is ever needed for the
actual remainder).
*/
MEXPORT_BIGNUMS int bigdivide2(bignum x, bignum y, bignum *q, bignum *r)
/* return 2 for attempted division by zero, 0 for success */
{ unsigned i, oldi, k, stash_length;
digit d,rem,trialq;
int test;
bignum bigtrialq;
bignum newx, newy;
bignum subtrahend;
bignum ans;
bigtrialq.val = NULL;
/* first we dispose of the simpler cases: */
if(y.ln == 1 && y.val[0] == 0)
return 2; /* attempted division by zero */
test = compare(x,y);
if(test == 0) /* x and y are equal, return 1 as a bignum */
{ r->val[0] = 0;
r->ln = 1;
q->ln = 1;
q->val[0] = 1;
return 0;
}
if(compare(x,y)== -1) /* x < y, dividend < divisor */
{ q->ln = 1;
q->val[0] = 0; /* quotient is zero */
r->ln = x.ln;
memcpy(r->val,x.val,x.ln * DIGITSIZE); /* remainder = dividend */
return 0;
}
if(y.ln == 1) /* one-digit divisor */
{ divide_by_digit2(x,y.val[0],q,&d);
r->val[0] = d;
r->ln = 1;
return 0;
}
if(x.ln == 1) /* one-digit dividend, at least 2-digit divisor */
{ q->val[0] = 0;
q->ln =1;
r->ln = x.ln;
memcpy(r->val,x.val,x.ln *DIGITSIZE); /* return copy of x for r */
}
/* Now the dividend and divisor are both at least 2 digits */
/* first we "normalize" by left-shifting both x and y the same number
of bits until the first bit of y is 1.
See below for the reason we do that , and Knuth vol. 2 p. 257 for the proofs.
*/
d= y.val[y.ln-1]; /* most significant digit of divisor */
if(d == 0)
assert(0);
for(i=0; (d & LEFTDIGIT) != LEFTDIGIT; ++i) d= d<<1; /* i counts the shifts */
if (i != 0)
{ left_shift(x,i,&newx);
left_shift(y,i,&newy);
bigdivide2(newx,newy,q,r);
/* here we may need one extra digit for r, since newy is larger than y */
right_shift(*r,i,r); /* renormalize remainder */
freespace(newx.val); /* release working space allocated by `left_shift' */
freespace(newy.val);
return 0;
}
/* henceforth we can assume the highest bit of y is 1 */
/* Initialize newx (which will represent the bottom line of the
calculation so far) to x. */
newx.ln = x.ln;
newx.val = getspace(newx.ln); /* get working space */
ans.ln = (unsigned)(x.ln - y.ln + 1); /* possibly one too big */
ans.val = q->val; /* already allocated space */
ans.val[(unsigned) (ans.ln-1)]= 0; /* something may be there from the last time it
was used; other digits will be written over or never examined,
but this particular digit is checked later and perhaps not
written into, so must be initialized to zero. */
for (i=0; i < x.ln ; i++)
newx.val[i] = x.val[i];
i = x.ln -y.ln - 1; /* first digit of quotient will be i-th one
if first digit of x < first digit of y
otherwise i+1 -st */
subtrahend.ln = newx.ln;
subtrahend.val = getspace(newx.ln+2);
/* more working space; +2 because bigmult2 expects as much space
as the sum of the lengths of its arguments, and subtrahend is
going into bigmult2 in a few lines from now
*/
/* Entering the following loop, you have just subtracted, and newx represents
the last line of the calculation, without initial zeroes but
possibly with first digit bigger than first digit of y. The value of i
is correctly set before beginning the loop: we are going to write
ans.val[i], and possibly ans.val[i+1] in case the first digit of newx is
more than the first digit of y. In that case we have previously written
zero there so it's ok to overwrite. At the end of the loop i has to be
incremented appropriately if the new value of newx is much shorter than
the old value.
*/
while ((i != MAX) && (newx.ln >= y.ln) ) /* write i-th digit from right in answer,
i.e. power of base^i */
{ if(y.val[y.ln-1] <= newx.val[i+y.ln])
{ /* two-digit trial quotient */
/* Compute that trial quotient as a bignum */
bigtrialq.ln = 2;
if(bigtrialq.val)
freespace(bigtrialq.val);
bigtrialq.val = getspace(2);
bigtrialq.val[1] = 1; /* Since the leftmost bit of y is 1 */
longdiv(newx.val[i+y.ln]-y.val[y.ln-1],newx.val[i+y.ln-1],y.val[y.ln-1],&bigtrialq.val[0],&rem);
bigmult2(y,bigtrialq,&subtrahend); /* multiply back */
}
else
{ /* one-digit trial quotient */
longdiv(newx.val[i+y.ln],newx.val[i+y.ln-1],y.val[y.ln-1],&trialq,&rem);
mult_by_digit2(y, trialq,&subtrahend); /* multiply back */
bigtrialq.ln = 0; /* bigtrialq will not be used. */
}
/* compare to the first y.ln + 1 digits of newx */
newy.ln = (unsigned)(y.ln + 1);
newy.val = newx.val + newx.ln -y.ln -1; /* pointer arithmetic */
/* makes newy a bignum consisting of the most
significant y.ln + 1 digits of newx */
while ((test = compare(subtrahend,newy)) > 0 ) /* subtrahend too big,
must decrease trialq */
{ if(bigtrialq.ln == 0)
{ --trialq;
mult_by_digit2(y, trialq, &subtrahend);
}
else if(bigtrialq.val[0])
{ --bigtrialq.val[0];
bigmult2(y,bigtrialq, &subtrahend);
}
else /* bigtrialq was [1,0] */
{ freespace(bigtrialq.val);
bigtrialq.val = NULL;
trialq = MAX;
mult_by_digit2(y,trialq,&subtrahend);
bigtrialq.ln = 0 ; // BUG --this line omitted until 3.26.04
}
}
/* You have to go through that while loop AT MOST TWICE! That's why
we normalized the divisor. See Knuth volume 2. */
/* Moreover trialq is NEVER too small. */
if(bigtrialq.ln == 0)
{ ans.val[i] = (digit) trialq; /* write this digit of the answer */
}
else
{ ans.val[i] = bigtrialq.val[0];
ans.val[i+1] = bigtrialq.val[1];
}
oldi = i;
stash_length = newy.ln;
bigminus2(newy,subtrahend,&newy); /* use same space for newy */
/* Since the digits of newy are occupying the same space as the
leftmost digits of newx, this alters the digits of newx
appropriately. However, it does not adjust newx.ln, although
it does adjust newy.ln. We must therefore adjust newx.ln
manually: */
newx.ln = (unsigned)(newx.ln - stash_length + newy.ln);
/* This is fine unless newy is zero; but in that case newx.ln should
be decreased still more: */
while(newx.val[newx.ln-1] == 0 && newx.ln > 1)
--newx.ln; /* 1 is the smallest it can get */
/* Next update i to where we will write next time;
more accurately (since we may write to digit i or i+1),
initialize i for next time through the loop */
i = y.ln < newx.ln ? newx.ln - y.ln - 1 : MAX;
/* Now perhaps i is MAX if
newy is a good bit shorter than it was before we took subtrahend away. */
for(k = oldi -1; k >= i+1 && k !=MAX; --k)
ans.val[k] = 0; /* fill in zeroes */
/* this works even if i = MAX, so i+1 = 0 */
}
/* Not necessarily finished yet; we may have i=MAX, and newx still greater
than or equal to y so the last digit of the quotient (which has been written as 0)
still needs to be overwritten. */
if( i == MAX )
{ test = compare(newx,y);
if (test > 0)
{ ans.val[0] = 1;
bigminus2(newx,y,&newx);
}
else if (test == 0)
{ newx.ln = 1;
newx.val[0] = 0;
ans.val[0]=1;
}
}
/* Now we still have to adjust ans.ln; it may be one too long as
remarked above. */
if ((ans.val[ans.ln-1] == 0) && (ans.ln != 1))
--ans.ln;
/* Now we have to copy the remainder into the given space r->val */
r->ln = newx.ln;
memcpy(r->val,newx.val,newx.ln *DIGITSIZE);
q->ln = ans.ln; /* q->val is already ans.val */
freespace(subtrahend.val); /* release working space */
freespace(newx.val);
if(bigtrialq.val)
freespace(bigtrialq.val);
return 0;
}
/*________ EXPONENTIATION __________________________________*/
MEXPORT_BIGNUMS int bigpower(bignum x, digit d, bignum *ansp)
/* return zero for success;
return 1 if the answer would require more digits than can be
represented in an unsigned int (if sizeof(int) < sizeof(long)),
or in a signed int (if sizeof(int) == sizeof(long)). That is,
if the NUMBER of digits is more than 2^32.
*/
/* x^d = ans; allocates space for ans */
{ unsigned bits; /* how many bits in d */
unsigned int i;
unsigned long s;
unsigned c;
bignum t;
/* next line computes how many bits in most sig. digit of x*/
/* Visual C++ compiler enters an infinite loop on the following lines even though
the Visual C debugger shows that what's inside the while loop is zero! */
for(bits = 0; bits <= NN; ++bits)
{ c = x.val[x.ln-1] >> bits;
if(c==0) /* assign the >> expression to a variable to avoid Visual C
bug with a >> expression inside an if */
break;
}
bits += NN * (x.ln -1);
if (d==0)
{ ansp->ln = 1;
ansp->val = getspace(1);
ansp->val[0] = 1;
return 0; /* signalling success */
}
/* first compute the length of the answer;
make it a long so as to detect overflow */
s = (unsigned long) d * (unsigned long) bits; /* length in bits */
s = s/NN + 1; /* length in digits */
if ( (s >> (NN-1)) != 0 )
return 17; /* signalling overflow to calling routine;
17 gets the appropriate message from aem() */
ansp->ln = (unsigned) s;
ansp->val = getspace(ansp->ln + 2);
/* The extra 2 so that we always have enough space going into bigmult */
/* Now do the recursive computation */
if (d==1)
{ ansp->ln = x.ln;
for(i=0;i<ansp->ln;++i)
ansp->val[i] = x.val[i];
return 0;
}
if ((d & 0x0001) == 0 ) /* d is even */
{ bigpower(x, d>>1, &t); /* allocates space for t.val */
bigmult2(t,t,ansp);
freespace(t.val);
return 0;
}
else /* d is odd */
{ bigpower(x, d-1, &t);
bigmult2(t,x,ansp);
freespace(t.val);
return 0;
}
}
/*________ SQUARE ROOT ___________________________________________*/
MEXPORT_BIGNUMS int bigsqrt(bignum x, bignum *ansp, bignum *remp)
/* ans points to the greatest integer in sqrt(x) */
/* rem points to the remainder, that is, x - *ansp^2, so you can
test whether it's an exact root by checking for *remp == 0. */
/* Space will be allocated for both *ansp and *remp */
{ ansp->val = getspace(x.ln /2 + 1);
remp->val = getspace(x.ln);
return bigsqrt2(x,ansp,remp);
}
/*________________________________________________________________*/
MEXPORT_BIGNUMS int bigsqrt2(bignum x, bignum *ansp, bignum *remp)
/* ans points to the greatest integer in sqrt(x) */
/* rem points to the remainder, that is, x-*ans^2 */
/* assumes space is already allocated */
{
bignum teven,todd;
bignum temp,rem,temp2;
unsigned i,j;
teven.val = getspace((x.ln / 2) + 1);
todd.val = getspace((x.ln / 2) + 1);
temp.val = getspace(x.ln + 2);
temp2.val = getspace(x.ln + 2);
rem.val = getspace(x.ln + 2 );
/* initialize teven to an approximation to sqrt x */
if(x.ln & 1) /* length of x is odd */
{ teven.ln = (unsigned)( (1 + x.ln)/2);
teven.val[teven.ln -1] = (digit) sqrt((double) x.val[x.ln-1]);
}
else
{ teven.ln = (unsigned)( x.ln/2);
{ double z = sqrt((double) x.val[x.ln-1]);
int exponent;
double mantissa;
/* multiply by 2^(NN/2) */
mantissa = frexp(z,&exponent);
exponent += NN/2;
teven.val[teven.ln-1] = (digit) ldexp(mantissa,exponent);
}
}
for(i=0; i < teven.ln -1; i++)
teven.val[i] = 0;
/* that completes the initialization of teven */
for(i=0; ; i++)
{ int flag;
if(i & 1)
{ bigdivide2(x,todd,&temp,&rem);
bigplus2(temp,todd,&temp2);
flag = temp2.val[0] & 1;
right_shift(temp2,1,&teven);
}
else
{ bigdivide2(x,teven,&temp,&rem);
bigplus2(temp,teven,&temp2);
flag = temp2.val[0] & 1;
right_shift(temp2,1,&todd);
}
if (! compare(todd,teven)) /* finished */
{ ansp->ln = teven.ln;
for (j=0; j< ansp->ln; j++)
ansp->val[j] = teven.val[j];
if(flag)
bigplus2(rem,i&1 ? todd : teven,&rem);
remp->ln = rem.ln;
for (j=0; j< remp->ln; j++)
remp->val[j] = rem.val[j];
freespace(teven.val);
freespace(todd.val);
freespace(temp.val);
freespace(temp2.val);
freespace(rem.val);
return 0;
}
}
}
/*________________ ROOT_____________________________________________*/
MEXPORT_BIGNUMS int bigroot(unsigned n, bignum x, bignum *ansp, bignum *remp)
/* allocate space and compute greatest integer in the n-th root of x,
making remp point to the remainder of x on division by (*ansp)^n.
(This number isn't interesting except that you can use it to see if the
root was exact or not.) */
/* return 0 for success, 1 for out of space */
/* return 2 for n too large (15 bits is the maximum) */
{ ansp->val = getspace(x.ln/n + 1);
remp->val = getspace(x.ln);
return bigroot2(n,x,ansp,remp);
}
/*_____________________________________________________________*/
MEXPORT_BIGNUMS int bigroot2(unsigned n, bignum x, bignum *ansp, bignum *remp)
/* space is already allocated for *ansp and *remp */
/* exit conditions on ans and *remp are specified in bigroot above */
/* Use Newton's method; nextguess = [(n-1) * old + (x/* old^(n-1))]/n */
/* For an initial guess, knock off digits in groups of n */
{ bignum teven,todd,rem;
bignum temp, temp2;
bignum *old,*next;
unsigned i,j;
long p;
unsigned k,u;
if(n >> (NN-1))
return 2;
teven.val = getspace(x.ln+1); /* workspace */
todd.val =getspace(x.ln+1);
rem.val = getspace(x.ln+1);
temp2.val = getspace(x.ln+1);
/* initialize teven to an approximation to root(n,x) */
k = x.ln / n; /* teven will have k trailing zero digits */
if(x.ln % n == 0)
--k;
p = (((long) x.ln - ((long) n)*k) * NN)/n;
/* p is an upper bound for the number of bits in the leading part of teven */
j = (unsigned) p;
if(j==0)
assert(0); // because of --k above, it can't be zero.
u = j/NN + 1; /*number of digits required for those bits */
/* make teven have its least significant k digits 0 and its next u
digits containing 2^j approximately */
teven.ln = (unsigned)(k + u); /* never mind checking k+u for overflow*/
for(i=0;i<k + u -1;i++)
teven.val[i] = 0;
teven.val[k+u-1] = (j % NN) ? (1 << (j % NN)) : 1;
/* that finishes initializing teven to an approximation to root(n,x) */
for(i=0; ; i++)
{ if(i & 1)
{ old = &todd;
next = &teven;
}
else
{ old = &teven;
next = &todd;
}
bigpower(*old,n-1,&temp); /* allocates temp.val */
bigdivide2(x,temp,&temp2,&rem);
if(!compare(*old,temp2))
{ /* finished, it's an exact root */
remp->ln = 1;
remp->val[0] = 0;
ansp->ln = old->ln;
for(j=0; j<ansp->ln; j++)
ansp->val[j] = old->val[j];
freespace(temp.val);
freespace(temp2.val);
freespace(rem.val);
freespace(teven.val);
freespace(todd.val);
break;
}
if(!compare(todd,teven))
{ /* finished, it's not an exact root */
bigmult2(*old,temp,&temp2); /* n-th power of the answer */
bigdivide2(x,temp2,&temp,remp);
ansp->ln = old->ln;
for(j=0; j<ansp->ln; j++)
ansp->val[j] = old->val[j];
freespace(temp.val);
freespace(temp2.val);
freespace(rem.val);
freespace(teven.val);
freespace(todd.val);
break;
}
freespace(temp.val); /* allocated by bigpower */
temp.val = getspace(x.ln+1);
mult_by_digit2(*old,n-1,&temp);
bigplus2(temp,temp2,&temp);
divide_by_digit(temp,n,next,&k);
}
return 0;
}
/*_________ GREATEST COMMON DIVISOR _____________________________*/
/* Lehmer's gcd, algorithm L p. 329 Knuth volume 2 */
/* Does not try to use single-precision arithmetic on small u,v */
/* Return answer in fresh space */
/* calls shortshiftgcd when you get down to digits */
MEXPORT_BIGNUMS void biggcd(bignum x, bignum y, bignum *ans)
{ digit uhat, vhat,q,scratch, aa;
long a,b,c,d,t,den1,den2;
bignum tt,w,r,qq,u,v;
int err;
unsigned long max = 0xffffffffUL;
err = compare(x,y);
if(err < 0) /* x < y */
{ biggcd(y,x,ans);
return;
}
if(err==0) /* x == y */
{ ans->val = getspace(x.ln + 1);
memcpy(ans->val,x.val, x.ln*DIGITSIZE);
ans->ln = x.ln;
return;
}
/* Now x >= y */
u.ln = x.ln;
u.val = getspace(u.ln + 1);
v.val = getspace(u.ln + 1);
tt.val = getspace(u.ln + 1);
qq.val = getspace(u.ln + 1);
w.val = getspace(u.ln + 1); /* make workspace */
r.val = getspace(u.ln + 1);
memcpy(u.val,x.val,u.ln *DIGITSIZE);
v.ln = y.ln;
memcpy(v.val,y.val,v.ln *DIGITSIZE);
while(u.ln > 1 && v.ln > 1)
{ uhat = u.val[u.ln -1];
vhat = (v.ln == u.ln ? v.val[v.ln-1] : 0);
a=d=1;
b=c=0; /* end of step L1 */
while(1) /* step L2; we exit by 'break' to L4 */
{ den1 = vhat + c;
den2 = vhat + d;
if((den1 & max) == 0 || (den2 & max) == 0) /* only possible overflow value */
break; /* go to L4 */
q= (digit) ((uhat+a)/den1);
if(q != (uhat + b)/den2)
break; /* That is, go to L4 */
t = a - q*c; /* Step L3 */
a = c;
c = t;
t = b - q*d;
b = d;
d = t;
t = uhat - q*vhat;
uhat = vhat;
vhat = (digit) t;
}
if(b==0) /* step L4 begins */
{ bigdivide2(u,v,&qq,&tt); /* u >= v as bigdivide2 requires */
u.ln = v.ln;
memcpy(u.val,v.val,u.ln *DIGITSIZE);
v.ln = tt.ln;
memcpy(v.val,tt.val, v.ln *DIGITSIZE);
}
else
{ if(a < 0 && b >= 0)
{ mult_by_digit2(u,(digit) -a,&tt);
mult_by_digit2(v,(digit) b,&r);
bigminus2(r,tt,&tt);
}
else if( a >= 0 && b < 0)
{ mult_by_digit2(u,(digit) a,&tt);
mult_by_digit2(v,(digit) -b,&r);
bigminus2(tt,r,&tt);
}
else /* they are both nonnegative */
{ mult_by_digit2(u,(digit) a,&tt);
mult_by_digit2(v,(digit) b,&r);
bigplus2(r,tt,&tt);
}
if(c < 0 && d >= 0)
{ mult_by_digit2(u,(digit) -c,&w);
mult_by_digit2(v,(digit) d,&qq);
bigminus2(qq,w,&w);
}
else if( c >= 0 && d < 0)
{ mult_by_digit2(u,(digit) c,&w);
mult_by_digit2(v,(digit) -d,&qq);
bigminus2(w,qq,&w);
}
else /* they are both nonnegative */
{ mult_by_digit2(u,(digit) c,&w);
mult_by_digit2(v,(digit) d,&qq);
bigplus2(qq,w,&w);
}
u.ln = tt.ln; /* u = tt makes them share digit space from now on */
memcpy(u.val,tt.val,u.ln *DIGITSIZE);
v.ln = w.ln;
memcpy(v.val,w.val,v.ln * DIGITSIZE);
}
}
if(v.ln == 1 && v.val[0] == 0)
{ ans->val = getspace(u.ln);
ans->ln = u.ln;
memcpy(ans->val,u.val,u.ln *DIGITSIZE);
return;
}
if(u.ln > 1) /* and v.ln == 1 */
{ divide_by_digit2(u,v.val[0],&tt,&scratch);
aa = scratch;
}
else
aa = u.val[0];
ans->val = getspace(1);
ans->ln = 1;
ans->val[0] = shortshiftgcd(aa,v.val[0]);
freespace(tt.val);
freespace(w.val);
freespace(r.val);
freespace(qq.val);
}
/*_______________________________________________________________________*/
MEXPORT_BIGNUMS char * bignum_string(bignum x, int separator)
/* convert binary bignum to a string, allocated by callocate,
suitable for display. */
/* separator controls the format:
0 blocks of 6 (ordinary decimal) digits separated by space
1 no separation of digits
2 blocks of 3 (ordinary decimal) digits separated by comma
n > 2 blocks of 3 (ordinary decimal) digits separated by
the symbol with ascii code n, e.g. period or space
*/
{ bignum decimal;
char *ans;
unsigned int i;
char *marker;
decimal = btod(x,1000);
if(decimal.ln==0)
return NULL; /* no space */
ans = callocate(decimal.ln * 4 + 1, sizeof(char));
if (ans == NULL)
{ freespace(decimal.val);
return NULL; /* no space */
}
i = decimal.ln-1;
marker = ans;
sprintf(ans,"%d",decimal.val[i]);
--i;
while(*marker)
++marker;
/* now marker points to the null after the first digit */
if(decimal.ln == 1)
return ans; /* stop, you're done */
if(separator == 2 )
{ *marker = ',';
++ marker;
}
if(separator == 0 && !(i & 1) ) /* i is even and we want blocks of 6 digits */
{ *marker = 32;
++marker;
}
if(separator > 2)
{ *marker = separator;
++marker;
}
while(i!=MAX) /* convert the i-th digit */
{ sprintf(marker,"%03d",decimal.val[i]);
marker += 3;
/* Now do we need a separator? */
if( separator==0 && !(i&1) && i !=0 )
{ *marker = 32;
++marker;
}
if( separator==2 && i != 0)
{ *marker = ',';
++marker;
}
if(separator > 2 && i != 0)
{ *marker = separator;
++marker;
}
--i;
}
*marker = '\0'; /* terminate the string */
freespace(decimal.val); /* no longer needed */
return ans;
}
/*_________________________________________________*/
#ifndef _Windows
int convert_and_print(bignum x, int separator)
/* convert binary bignum to decimal and print directly */
/* separator controls the format as above */
{ char *ans;
ans = bignum_string(x,separator);
if(ans)
{ printf("%s",ans);
freespace(ans);
return 0;
}
return 1; /* no space */
}
#endif
/*_____________________________________________________________*/
/* This decimal-to-binary conversion uses a quadratic amount of space,
but it's ok since we only use it to process bignums that have been
typed in, so they can't be very long. */
MEXPORT_BIGNUMS int string_bignum(char *s, unsigned n, bignum *xp)
/* convert a string of n decimal digits to a bignum, allocating space */
/* string doesn't have to be null-terminated */
{ unsigned i;
bignum aux, aux2, addit;
char p[5];
char *endptr;
char t[5];
addit.ln = 1;
addit.val = getspace(1);
if (n < 5) /* it will convert to a digit */
{ xp->ln = 1;
for(i=0; i<n; i++)
p[i] = s[i];
p[n] = '\0';
xp->val = getspace(1);
xp->val[0] = (digit) strtoul(p,&endptr,10);
return 0; /* finished */
}
if( string_bignum(s,n-4,&aux) != 0 ) /* allocating space for aux */
return 1; /* error */
for(i=0; i<4; i++)
t[i] = s[n-4+i]; /* last four decimal digits of s */
t[4] = '\0';
addit.val[0] = (digit) strtoul(t,&endptr,10);
mult_by_digit(aux, 10000, &aux2);
freespace(aux.val);
bigplus(aux2, addit,xp);
freespace(aux2.val);
freespace(addit.val);
return 0;
}
/*____________________________________________________________*/
MEXPORT_BIGNUMS int bigfactorial(unsigned int n, bignum *ans)
/* compute n! */
/* return value 1 is out of space;
return value 2 is answer too big (needs more than sizeof(int) for
the number of digits)
return value 0 is success
*/
/* How many digits are needed to hold n! ?
By Stirling's formula, the number of digits base 2 in n! is at
most, with log meaning log to the base 2,
(1/2) log(2npi) + n (log n - 1) + log(1 + (1/(12n-1))),
according to CRC tables, p. 387 12th edition. Since log(1+x) < x,
for positive x, the number of digits is at most
(1/2) log 2pi + log n + n (log n - 1) + 1/(12n -1)
which is less than
(3/2) + k + n(k-1) + 1 where k = number of digits in n
which is less than
3 + k + n(k-1). For simplicity, that is bounded by
nk so long as n-k>3, which it certainly is for n>10. */
{ bignum temp1,temp2;
unsigned int k,i;
unsigned long s;
if(n < 9)
{ ans->val = getspace(1);
ans->ln = 1;
switch(n)
{ case 0: ans->val[0] = 1; return 0;
case 1: ans->val[0] = 1; return 0;
case 2: ans->val[0] = 2; return 0;
case 3: ans->val[0] = 6; return 0;
case 4: ans->val[0] = 24; return 0;
case 5: ans->val[0] = 120; return 0;
case 6: ans->val[0] = 720; return 0;
case 7: ans->val[0] = 5040; return 0;
case 8: ans->val[0] = (digit) 40320UL;
return 0;
}
}
k=0;
while(n>>k)
++k;
/* Now k is the bitlength of n */
s = n * k;
if(s >> 16)
return 2; /* answer too big to compute */
/* s is the BIT length; now we want the length in DIGITS */
s = s>>5; /* a 32-bit machine */
temp1.val = getspace((digit) s); /* workspace */
temp2.val = getspace((digit) s); /* more workspace */
temp1.ln = 1;
if(n&1)
{ temp1.val[0]=n;
temp1.ln = 1;
}
else
{ temp2.val[0]=n;
temp2.ln = 1;
}
for(i=n-1;i > 1; i--)
{ if( i & 1)
mult_by_digit2(temp2,i,&temp1);
else
mult_by_digit2(temp1,i,&temp2);
}
*ans = temp2;
freespace(temp1.val);
return 0;
}
/*________________________________________________________________________*/
MEXPORT_BIGNUMS int bignum_double(bignum x, double *ans)
/* convert a bignum to a double unless it's too big */
/* bignum must have at least two digits */
/* return value 0 means success; 1 means failure */
/* doesn't care if bignums use 16-bit or 32-bit digits */
{ double mantissa,base;
int exponent,exp2;
if (x.ln > 65)
return 1; /* certainly too big */
if(x.ln == 1)
{ *ans = (double) x.val[0];
return 0;
}
base = pow(2.0,NN);
if(x.ln == 2)
{ *ans = x.val[1] * base + x.val[0];
return 0;
}
/* With 52-bit mantissas and 32-bit digits, 2 digits is enough; but
we include the next line in case we switch to long doubles at some
future time; then this won't need modification. */
if(x.ln == 3)
{ *ans = (x.val[2] *base + x.val[1]) * base + x.val[0];
return 0;
}
*ans = (x.val[x.ln-1]*base + x.val[x.ln-2]) *base + x.val[x.ln-3];
exponent = (int ) (NN * (x.ln - 3));
if(exponent < 0)
return 1; /* assert(0) */
if(exponent == 0)
return 0;
mantissa = frexp(*ans,&exp2);
exponent += exp2;
if(exponent > 1023) /* 1023 = maximum exponent of a double */
return 1;
*ans = ldexp(mantissa,exponent);
return 0;
}
/*________________________________________________________________________*/
MEXPORT_BIGNUMS int bigrat_double(bignum p, bignum q, double *ans)
/* convert p/q to a double if possible, returning 0 for success;
succeed even if p and q are individually too large to convert to double;
fail only if the ratio is too big. On failure ans is garbage and
1 is returned. */
{ double temp,num,denom;
int err,exp;
unsigned diff, dd;
unsigned num_discard,denom_discard;
if(p.ln < q.ln || (p.ln == q.ln && p.val[p.ln-1] < q.val[p.ln-1]))
{ err = bigrat_double(q,p,&temp);
if(err)
return err;
if(temp == 0.0)
return 1;
*ans = 1/temp;
return 0;
}
/* Now q � p */
diff = p.ln - q.ln;
dd = 308/NN;
if(diff > dd)
return 1;
denom_discard = q.ln < 7 ? 0 : q.ln - 6;
num_discard = p.ln < 7 ? 0 : p.ln - 6;
p.val += num_discard; /* affects only local copy of p */
q.val += denom_discard; /* affects only local copy of q */
/* Now q and q are short enough to convert to doubles; they are
5 digits long which is 81-96 or 161-192 bits (depending if
digits are 16 or 32 bits) but in either case is MORE accuracy
than the 80-bit coprocessor and LESS than the range of a double
(which is 10^308 > 2^192)
*/
bignum_double(p,&num);
bignum_double(q,&denom);
temp = num/denom;
frexp(temp,&exp);
exp += num_discard-denom_discard;
if(exp > 1023)
return 1;
*ans = ldexp(temp,exp);
return 0;
}
/*_______________________________________________________________________*/
static unsigned shortshiftgcd(unsigned u, unsigned v)
/* There is a copy of this in arith.c */
/* Change it too if this changes */
/* return gcd(u,v) but not lambda and mu */
/* binary method, no division: Algorithm B */
/* Adapted to use unsigned, so as to double the input capacity
and avoid portability problems from right-shifting signed ints */
{ short k;
k=0;
while (!(u&1) && !(v&1))
{ ++k;
u >>= 1;
v >>=1;
}
while(u != 0 && v != 0)
{ if(!(u&1))
{ while(!(u&1))
u >>= 1;
}
else
{ while(!(v&1))
v >>= 1;
}
/* At this point both u and v are odd */
if(u > v)
u -= v;
else
v -= u;
/* Now one is odd and one is even */
}
if(u==0)
u=v;
return u * (1 << k);
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists