//-------------------------------------------------------------------main.cpp
#include "HugeInt.h" 
#include <iostream>
#include <conio.h> 
using namespace std;
 
 
int main()
{
	unsigned int seed;
	cout << "Enter seed: ";
	cin >> seed;
	srand(seed);
 
	int length1, length2, length3;
	cout << "Enter the lengths of three huge integers: ";
	cin >> length1 >> length2 >> length3;
 
	const HugeInt n1(length1), n2(length2); 
	HugeInt n3(length3);
	cout << "n1: " << n1 << endl; //randomized
	cout << "n2: " << n2 << endl;
	cout << "n3: " << n3 << endl;
 
 
 
	int x = 1, y = 3, z = 7;
 
	//cout << "Enter three test value x, y, z (integer type): ";
	//cin >> x >> y >> z;
 
	cout << "x: " << x << endl;
	cout << "y: " << y << endl;
	cout << "z: " << z << endl;
 
	HugeInt n4, n5, n6;
	cout << "n1 + n3 = " << (n1 + n3) << endl; 
	cout << "n4 = n2 - n3 = " << (n4 = n2 - n3) << endl; 
 
	//cout << "x + n1 = " << x + n1 << endl;
	//cout << "n1 + x = " << n1 + x << endl;
	//cout << "n5 = y - n2 = " << (n5 = y - n2) << endl;
	//cout << "n2 - y = " << n2 - y << endl;
	//cout << "n3 = n3 - n2 - n1 - x = " << (n3 = n3 - n2 - n1 - x) << endl;
	//cout << "n6 = y + z = " << (n6 = y + z) << endl << endl;
 
	cout << "n1: " << n1 << endl;
	cout << "n2: " << n2 << endl;
	cout << "n3: " << n3 << endl;
	cout << "n4: " << n4 << endl;
	cout << "n5: " << n5 << endl;
	cout << "n6: " << n6 << endl;
 
	cin >> length1;
	return 0;
}
//-------------------------------------------------------------------HugeInt.h
#ifndef HUGE_UINTEGER_H
#define HUGE_UINTEGER_H
#include <vector>
using namespace std;
#define MAX 1000 //< max length of huge interger
class HugeInt
{
	friend ostream &operator<<(ostream &output, const HugeInt &in);
 
public:
	HugeInt(); 
	HugeInt(const HugeInt &in); //< copy constructor
	static HugeInt random(unsigned int size);
 
	HugeInt operator=(const HugeInt &right);//< assignment
	bool operator==(const HugeInt &right);	//< equal to
	bool operator!=(const HugeInt &right);	//< not equal to
	bool operator<(const HugeInt &right);	//< less than
	bool operator>(const HugeInt &right);	//< greater than
 
	HugeInt operator+(const HugeInt &right);
 
	HugeInt  operator-(const HugeInt &right);
 
 
private:
	vector<int> num;
	int _size;
	int n;
};
#endif
 
 
//-------------------------------------------------------------------HugeInteger.cpp
#include <iostream>
#include "HugeInt.h"
using namespace std;
 
ostream &operator<<(ostream &output, const HugeInt &in)
{
	for (int i = in._size - 1; i >= 0; i--)
	{
		output << in.num[i];
	}
	cout << endl;
	return output;
}
 
HugeInt::HugeInt()
{
	num.clear();
	_size = 0;
}
HugeInt::HugeInt(const HugeInt &in) //< copy constructor
{
	_size = in._size;
	num.resize(in._size);
	for (int i = 0; i < in._size; i++)
		num[i] = in.num[i];
}
 
HugeInt HugeInt::random(unsigned int size)
{
	HugeInt a;
	a._size = size;
	a.num.resize(size);
	for (int i = 0; i < size; i++)
	{
		a.num[i] = (rand() % 10);
	}
	for (int i = 0;; i++)
	{
		if (a.num[a._size - 1] == 0)
		{
			a.num[a._size - 1] += (rand() % 10);
		}
		else
			break;
	}
	return a;
}
HugeInt HugeInt::operator=(const HugeInt &right) //< assignment
{
	_size = right._size;
	num.resize(right._size);
	for (int i = 0; i < right._size; i++)
	{
		num[i] = right.num[i];
	}
 
	return *this;
}
 
bool HugeInt::operator==(const HugeInt &right) //< equal to
{
	if (_size != right._size)
		return false;
	else
	{
		for (int i = 0; i < _size; i++)
		{
			if (num[i] != right.num[i])
				return false;
		}
	}
	return true;
}
 
bool HugeInt::operator!=(const HugeInt &right) //< not equal to
{
	return !(HugeInt::operator==(right));
}
 
bool HugeInt::operator<(const HugeInt &right)  //< less than
{
	if (_size < right._size)
		return true;
	else if (_size > right._size)
		return false;
	else
	{
		for (int i = _size - 1; i >= 0; i--)
		{
			if (num[i] < right.num[i])
				return true;
			else if (num[i] > right.num[i])
				return false;
		}
		return false;
	}
}
 
bool HugeInt::operator>(const HugeInt &right)  //< greater than
{
	if (_size < right._size)
		return false;
	else if (_size > right._size)
		return true;
	else
	{
		for (int i = _size - 1; i >= 0; i--)
		{
			if (num[i] < right.num[i])
				return false;
			else if (num[i] > right.num[i])
				return true;
		}
		return false;
	}
}
HugeInt HugeInt::operator+(const HugeInt &right)
{
	HugeInt temp;
 
	if (_size < right._size)
		temp._size = right._size;
	else
		temp._size = _size;
 
	temp.num.resize(temp._size);
 
	for (int i = 0; i < _size; i++)
	{
		temp.num[i] = num[i];
	}
	for (int i = 0; i < temp._size; i++)
	{
		temp.num[i] += right.num[i];
	}
	for (int i = 0; i < temp._size; i++)
	{
		if (temp.num[i]>9)
		{
			temp.num[i] -= 10;
			if (i + 1 >= temp._size)
			{
				temp._size++;
				temp.num.resize(temp._size);
			}
			temp.num[i + 1] += 1;
		}
	}
 
	return temp;
}
HugeInt  HugeInt::operator-(const HugeInt &right)//< subtraction operator; HugeInt  - HugeInt ; 
{
	HugeInt temp;
	HugeInt righttemp;
	if (_size > right._size)				//left > right
	{
		temp._size = _size;
		temp.num.resize(_size);
 
		for (int i = 0; i < _size; i++)	
			temp.num[i] = num[i];
 
		for (int i = 0; i < right._size; i++)		//sub
			temp.num[i] -= right.num[i];
 
		n = temp._size;
 
		for (int i = 0; i < n; i++)					//進位
		{
			if (temp.num[i] < 0)
			{
				temp.num[i] += 10;
				if (i + 1 >= temp._size)
				{
					temp._size++;
					temp.num.resize(temp._size);
				}
				temp.num[i + 1] -= 1;
			}
		}
 
		for (;temp.num[temp._size - 1] == 0;)
		{
			temp.num.resize(temp._size--);
			if (temp._size == 1)
				break;
		}
		return temp;
	}
	else if (_size == right._size)			//left.size == right.size
	{
		temp._size = _size;
		temp.num.resize(_size);
 
		for (int i = 0; i < _size; i++)	
			temp.num[i] = num[i];
 
		bool comparebigsmall = 0;
 
		n = temp._size;
 
		for (int i = n-1; i > -1; i--)
		{
			if (temp.num[i] > right.num[i])		//left > right
			{
				comparebigsmall = 0;
				break;
			}
			else if (temp.num[i] < right.num[i])	//right > left
			{
				comparebigsmall = 1;
				break;
			}
			else if (temp.num[i] == right.num[i])
				continue;
		}
		if (comparebigsmall == 0)			//left > right
		{
			for (int i = 0; i < _size; i++)	
				temp.num[i] = num[i];
 
			for (int i = 0; i < right._size; i++)		//sub
				temp.num[i] -= right.num[i];
 
			n = temp._size;
 
			for (int i = 0; i < n; i++)					//進位
			{
				if (temp.num[i] < 0)
				{
					temp.num[i] += 10;
					if (i + 1 >= temp._size)
					{
						temp._size++;
						temp.num.resize(temp._size);
					}
					temp.num[i + 1] -= 1;
				}
			}
 
			for (; temp.num[temp._size - 1] == 0;)
			{
				temp.num.resize(temp._size--);
				if (temp._size == 1)
					break;
			}
			return temp;
		}
		else if (comparebigsmall == 1)	//right > left
		{
			righttemp._size = right._size;
			righttemp.num.resize(right._size);
 
			for (int i = 0; i < _size; i++)	
				righttemp.num[i] = right.num[i];
 
			for (int i = 0; i < righttemp._size; i++)		//sub
				righttemp.num[i] -= temp.num[i];
 
			n = righttemp._size;
 
			for (int i = 0; i < n; i++)					//進位
			{
				if (righttemp.num[i] < 0)
				{
					righttemp.num[i] += 10;
					if (i + 1 >= righttemp._size)
					{
						righttemp._size++;
						righttemp.num.resize(righttemp._size);
					}
					righttemp.num[i + 1] -= 1;
				}
			}
 
			for (; righttemp.num[righttemp._size - 1] == 0;)
			{
				righttemp.num.resize(temp._size--);
				if (righttemp._size == 1)
					break;
			}
			righttemp.num[righttemp._size-1] = righttemp.num[righttemp._size-1] * (-1);	//負號
			return righttemp;
		}
	}
	else if (_size < right._size)
	{
		temp._size = _size;
		temp.num.resize(_size);
		righttemp._size = right._size;
		righttemp.num.resize(right._size);
 
		for (int i = 0; i < _size; i++)	
			temp.num[i] = num[i];
		for (int i = 0; i < righttemp._size; i++)	
			righttemp.num[i] = right.num[i];
 
 
		for (int i = 0; i < temp._size; i++)		//sub
		{
			righttemp.num[i] -= temp.num[i];
 
		}
 
		n = righttemp._size;
 
		for (int i = 0; i < n; i++)					//進位
		{
			if (righttemp.num[i] < 0)
			{
				righttemp.num[i] += 10;
				if (i + 1 >= righttemp._size)
				{
					righttemp._size++;
					righttemp.num.resize(righttemp._size);
				}
				righttemp.num[i + 1] -= 1;
			}
		}
 
		for (; righttemp.num[righttemp._size - 1] == 0;)
		{
			righttemp.num.resize(righttemp._size--);
			if (righttemp._size == 1)
				break;
		}
		righttemp.num[righttemp._size - 1] = righttemp.num[righttemp._size - 1] * (-1);	//負號
		return righttemp;
	}
}