// P-2 MCS 360 due Mon 4 Oct 2010 : big_nat.cpp

#include "big_nat.h"
#include <iomanip>
#include <iostream>
#include <sstream>

Big_Nat::Big_Nat( std::string n )
{
   size_t index = 0;
   size_t r = 0;
   bool first = true;
   size_t ns = n.size();

   lead = ns/base_digits;
   if(lead*base_digits < ns) lead = lead+1;
   coeff.reserve(lead+1);

   for(int i=0; i<=lead; i++) coeff[i] = 0;

   for(int i=0; i<lead; i++)
   {
      r = 0;
      index = (ns < base_digits) ? 0 : (ns - base_digits);
      for(int j=0; j<base_digits; j++)
      {
         if(j >= ns) break;
         if(index+j >= n.size()) break;
         r = 10*r + (int(n[index+j]) - int('0'));
      }
      coeff[i] = r;
      if(ns - base_digits < 0) break;
      ns = ns - base_digits;
   }
   if(coeff[lead] == 0) lead = lead-1;
}

std::string Big_Nat::to_string() const
{
   std::ostringstream s;

   s << coeff[lead];
   for(int i=lead-1; i>= 0; i--)
      s << std::setw(base_digits) << std::setfill('0') << coeff[i];

   return s.str();
}


Big_Nat Big_Nat::operator+( const Big_Nat& other )
{
   Big_Nat r = *this;

   size_t mx = (this->lead > other.lead) ? this->lead : other.lead;

   r.coeff.reserve(mx+2);
   r.lead = mx;

   for(int i=0; i<=this->lead; i++) r.coeff[i] = this->coeff[i];

   size_t carry = 0;
   for(int i=0; i<=this->lead; i++)
   {
      size_t sum = this->coeff[i] + other.coeff[i] + carry;
      r.coeff[i] = sum % base;
      carry = sum/base;
      if(i > other.lead) break;
   }

   if(other.lead > this->lead)
      for(int i=this->lead+1; i<=other.lead; i++)
      {
         size_t sum = other.coeff[i] + carry;
         r.coeff[i] = sum % base;
         carry = sum/base;
      }

   if(carry>0)
   {
      r.lead = r.lead + 1;
      r.coeff[r.lead] = carry;
   }

   return r;
}

