Listing 6: Other BigNum routines

//raise bignum to the nth power
BigNum BigNum::operator^(const long n){
  if (n>0){
     if (n==2) return ((*this) * (*this));
     if (n%2==0) return (((*this)^(n/2))^2);
     else return (*this * ((*this)^(n-1)));
  }else{
     if (!n) return BigNum(1); else return BigNum(long(0));
  }
}

//construct BigNum from char string; only works if BASE == 10000
BigNum::BigNum(char *s){
  int k,ind,l = strlen(s);
  exp = l/4;
  if (l%4==0) exp--;
  x = new int[exp+1];
  char *d, *s2;
  d = new char[l];  s2 = new char[l];
  strcpy(s2,s);  //make copy of s so that we don't trash original
  l--; k = l - 3; if (k<0) k = 0; ind = l-k+1;
  for (int i = 0;i<=exp;i++){
     d = s2+k;
     d[ind] = '\0'; x[i] = atoi(d)
     l -=4;  k-=4; if (k<0) k = 0;
     ind = l-k+1;
  }
  delete[] d;   delete[] s2;
}

//construct BigNum from long; new_sz param allows one to create
//a larger than necessary array of ints
BigNum::BigNum(long k,long new_sz){
  long k2 = k/BASE; int sz = 1;
  while(k2){sz++; k2 /= BASE;}    //determine size of int array
  if (sz >= new_sz) x = new int[sz]; else x = new int[new_sz];
  if (k>=0) positive = 1;
  else{ k = -k; positive = 0;}
  long carry = k; exp = -1;
  while (carry){ x[++exp] = carry % BASE; carry /= BASE;}
}

//copy constructor
BigNum::BigNum(const BigNum &b,long new_sz){
  if (b.exp+1 >= new_sz) x = new int[b.exp+1];
  else x = new int[new_sz];
  positive = b.positive; exp = b.exp;
  for (int i=0;i<=exp;i++)x[i] = b.x[i];
}

//assign a long to a bignum
BigNum & BigNum::operator=(long k){
  delete[] x;
  long k2 = k/BASE; int sz = 1;
  while(k2){sz++; k2 /= BASE;}
  x = new int[sz];

  if (k>=0)positive = 1;
  else{ k = -k; positive = 0;}

  long carry = k;
  exp = -1;
  while (carry){x[++exp] = carry % BASE; carry /= BASE;}
  return *this;
}

//assign a bignum to a bignum
BigNum & BigNum::operator=(const BigNum &b){
  delete[] x;
  x = new int[b.exp+1];
  exp = b.exp; positive = b.positive;
  for (int i = 0;i<=exp; i++) x[i] = b.x[i];
  return *this;
}

//allow easy printing of bignums
ostream& operator<<(ostream & os, BigNum &b){
  if (!b.positive){ os << "-";}
  int j = 0;
  for (int i = b.exp; i >=0; i--){
      if (++j % 15 == 0) os << "\n";
      os.fill('0');os.width(4);os <<  b.x[i];
  }
  return os;
}
//End of File