Listing 5: Division of BigNum by another BigNum
//divide a bignum by another bignum
BigNum BigNum::operator/(const BigNum &denom){
BigNum q;
q.positive = (this->positive == denom.positive);
if (abs(*this)<abs(denom)) return q;
if (denom.exp <= 0){ //denom is a long;
//send it to the easy routine
long x = denom.x[0];
return (*this/x);
}else{
delete[] q.x;
q.exp = this->exp - denom.exp;
q.x = new int[q.exp+1];
long qhat; int qpos = q.exp;
long d = BASE/(denom.x[denom.exp]+1); //d is a normalizer
BigNum u(*this); //make a copy of the numerator
BigNum v(denom); //make a copy of the denominator
long start = u.exp+1;
u = u*d; v = v*d;
if (u.exp<start){ u.exp = start; u.x[start]=0;}
for(;;){
if (abs(u)<abs(v)){ //when u<v we can't divide anymore
u = u/d; //unnormalize u to get remainder
return q;
}
int i = 0; long stop;
while(u.x[start+i]==v.x[v.exp+i] && v.exp+i)i--;
if (u.x[start+i] < v.x[v.exp+i])stop = start - v.exp -1;
else stop = start - v.exp;
qhat = long(u.x[start]); //make a guess at qhat
qhat = qhat*BASE + u.x[start-1];qhat/=v.x[v.exp];
if (qhat > BASE-1) qhat = BASE-1;
long temp;
//fast check to see if qhat is too big
if (start-1) temp = u.x[start-2]; else temp = 0;
while (long(v.x[v.exp-1])*qhat>(long(u.x[start])*BASE +
u.x[start-1]-qhat*long(v.x[v.exp]))*BASE +
temp)
qhat--;
BigNum work(v*qhat,u.exp);
//qhat still too big??
while(start-stop < work.exp){--qhat; work = work - v;}
long borrow = 0; //subtract work from u
work.x[work.exp+1] = 0;
for(i=stop;i<=start; i++){
temp = long(u.x[i]) - long(work.x[i-stop]) + borrow;
if (temp < 0){borrow = -1;temp+=BASE;}
else borrow = 0;
u.x[i] = temp;
}
v.x[v.exp+1] = 0;
while (borrow < 0 && qhat){//oops qhat was still too big
//add back
qhat--;
long carry = 0;
for(i=stop;i<=start; i++){
temp = u.x[i] + v.x[i-stop] + carry;
carry = temp/BASE;
u.x[i] = temp % BASE;
}
borrow += carry;
}
q.x[qpos--] = qhat;
start = --u.exp; //work on next digit of u
}
}
}
//End of File