#include "bignum.h"

#include <iostream>
#include <vector>
#include <cstdlib>
#include <cassert>

using namespace std;

BigNum::BigNum(int nn) {
    assert(nn >= 0);
    while (nn > 0) {
	div_t d = div(nn, base);
	n.push_back(d.rem);
	nn = d.quot;
    }
}

BigNum& BigNum::operator+=(const BigNum &r) {
    vector<int>::size_type i = 0;
    int carry = 0;
    for ( ; i < n.size() && i < r.n.size(); ++i) {
	n[i] += r.n[i] + carry;
	div_t d = div(n[i], base);
	n[i] = d.rem;
	carry = d.quot;
    }
    for ( ; i < n.size(); ++i) {
	n[i] += carry;
	div_t d = div(n[i], base);
	n[i] = d.rem;
	carry = d.quot;
    }
    for ( ; i < r.n.size(); ++i) {
	n.push_back(r.n[i] + carry);
	div_t d = div(n.back(), base);
	n.back() = d.rem;
	carry = d.quot;
    }
    if (carry)
	n.push_back(carry);
    return *this;
}

BigNum& BigNum::mul(int d) {
    assert(d >= 0);
    vector<int>::size_type i = 0;
    int carry = 0;
    for ( ; i < n.size(); ++i) {
	n[i] *= d;
	n[i] += carry;
	div_t d = div(n[i], base);
	n[i] = d.rem;
	carry = d.quot;
    }
    while (carry) {
	div_t d = div(carry, base);
	n.push_back(d.rem);
	carry = d.quot;
    }
    return *this;
}

int BigNum::digits10(int m) {
    int count = 0;
    while (m) {
	++count;
	m /= 10;
    }
    return count;
}

int BigNum::sum_digits10(int m) {
    int sum = 0;
    while (m) {
	div_t d = div(m, 10);
	sum += d.rem;
	m = d.quot;
    }
    return sum;
}

int BigNum::sum_digits10() const {
    int sum = 0;
    vector<int>::size_type i = 0;
    for ( ; i < n.size(); ++i)
	sum += sum_digits10(n[i]);
    return sum;
}

void BigNum::print(ostream &out) const {
    // bug: should fix cases when for example *it == 0084 and only 84
    // gets printed
    vector<int>::const_reverse_iterator it = n.rbegin();
    for ( ; it != n.rend(); ++it)
	out << *it;
}

