BigNum/BigNum.cpp

```
#include "bigNum.hpp"

#define CHAR\_TO\_INT(x) (static\_cast<int>(x) - 48)
#define INT\_TO\_CHAR(x) (static\_cast<char>(x + 48))

/////////////////////////////
/\* K O N S T R U K T O R Y \*/
/////////////////////////////

bigNum::bigNum()
{
 number = "0";
 positive = true;
 nsize = 1;
}

bigNum::bigNum(const long long& value)
{
 number = std::to\_string(value);
 if (number[0] == '-')
 {
 positive = false;
 number.erase(0, 1); //usuwa znak minusa
 }
 else
 {
 positive = true;
 }
 cleanup();
 nsize = number.size();
}

bigNum::bigNum(const char \*value)
{
 if (value[0] == '-')
 {
 positive = false;
 number = value;
 number.erase(0, 1);
 }
 else
 {
 positive = true;
 number = value;
 }
 cleanup();
 nsize = number.size();
}

bigNum::bigNum(const std::string& value)
{
 if (value[0] == '-')
 {
 positive = false;
 number = value;
 number.erase(0, 1);
 }
 else
 {
 positive = true;
 number = value;
 }
 cleanup();
 nsize = number.size();
}

bigNum::bigNum(const int& value)
{
 if (value < 0)
 positive = false;
 else
 positive = true;
 number = std::to\_string(value);
 cleanup();
 nsize = number.size();
}

bigNum::bigNum(const bigNum& value)
{
 positive = value.positive;
 number = value.number;
 nsize = value.nsize;
}

bigNum bigNum::abs() const
{
 return bigNum(number);
}

void bigNum::cleanup()
{
 while (number.size() > 1)
 {
 if (number[0] == '0')
 {
 number.erase(0, 1);
 }
 else
 break;
 }
 if (number.size() == 1 && number[0] == '0')
 positive = true;
 updateSize();
}

void bigNum::changeSign()
{
 if (number.size() > 1 || number[0] != '0') //if number != 0
 {
 positive = !positive;
 }
}

size\_t bigNum::getSize() const
{
 return nsize;
}

bool bigNum::isPositive() const
{
 return positive;
}

void bigNum::updateSize()
{
 nsize = number.size();
}

int bigNum::getDigit(int digit) const
{
 return CHAR\_TO\_INT(number[nsize - digit - 1]);
}

void bigNum::changeDigit(int digit, int value)
{
 number[nsize - digit - 1] = INT\_TO\_CHAR(value);
}

///////////////////////////////////
/\* K O N W E R S J A T Y P Ó W \*/
///////////////////////////////////

std::string bigNum::toString() const
{
 std::string value;
 if (!positive)
 {
 value += '-';
 }
 value += number;
 return value;
}

int bigNum::toInt() const
{
 int value = std::stoi(number);
 if (!positive)
 value = -value;
 return value;
}

long long bigNum::toLongLong() const
{
 long long value = std::stoi(number);
 if (!positive)
 value = -value;
 return value;
}

double bigNum::toDouble() const
{
 double value = std::stod(number);
 if (!positive)
 value = -value;
 return value;
}

///////////////////////////////////////////////////////////
/\* O P E R A T O R Y W E J Ś C I A I W Y J Ś C I A \*/
///////////////////////////////////////////////////////////

std::ostream& operator<<(std::ostream& os, const bigNum& rhs)
{
 if (!rhs.positive)
 os << '-';
 os << rhs.number;
 return os;
}

std::istream& operator>>(std::istream& is, bigNum& rhs)
{
 is >> rhs.number;
 rhs.positive = true;
 if (rhs.number[0] == '-')
 {
 rhs.positive = false;
 rhs.number.erase(0, 1);
 }
 rhs.cleanup();
 return is;
}

bigNum& bigNum::operator=(const bigNum& rhs)
{
 positive = rhs.positive;
 nsize = rhs.nsize;
 number = rhs.number;
 return \*this;
}

/////////////////////////////////////////////
/\* O P E R A T O R Y R Z U T O W A N I A \*/
/////////////////////////////////////////////

bigNum::operator long long() const
{
 return toLongLong();
}

bigNum::operator int() const
{
 return toInt();
}

bigNum::operator double() const
{
 return toDouble();
}

bigNum::operator std::string() const
{
 return toString();
}

/////////////////////////////////////////////
/\* O P E R A T O R Y P O R Ó W N A N I A \*/
/////////////////////////////////////////////

bool operator==(const bigNum& lhs, const bigNum& rhs)
{
 if (lhs.positive != rhs.positive)
 return false;
 if (lhs.nsize != rhs.nsize)
 return false;
 for (size\_t i = 0; i < lhs.nsize; i++)
 if (lhs.getDigit(i) != rhs.getDigit(i))
 return false;
 return true;
}

bool operator!=(const bigNum& lhs, const bigNum& rhs)
{
 return !(operator==(lhs, rhs));
}

bool operator>(const bigNum& lhs, const bigNum& rhs)
{
 if (lhs.positive && !rhs.positive)
 return true;
 else if (!lhs.positive && rhs.positive)
 return false;
 else if (lhs.positive && rhs.positive)
 {
 if (lhs.nsize > rhs.nsize)
 return true;
 else if (lhs.nsize < rhs.nsize)
 return false;
 else
 {
 for (size\_t i = 0; i < lhs.nsize; i++)
 {
 if (lhs.getDigit(lhs.nsize - i - 1) < rhs.getDigit(lhs.nsize - i - 1))
 return false;
 else if (lhs.getDigit(lhs.nsize - i - 1) > rhs.getDigit(lhs.nsize - i - 1))
 return true;
 }
 return false;
 }
 }
 else //if (!positive && !rhs.positive)
 {
 if (lhs.nsize < rhs.nsize)
 return true;
 else if (lhs.nsize > rhs.nsize)
 return false;
 else
 {
 for (size\_t i = 0; i < lhs.nsize; i++)
 {
 if (lhs.getDigit(lhs.nsize - i - 1) < rhs.getDigit(lhs.nsize - i - 1))
 return true;
 else if (lhs.getDigit(lhs.nsize - i - 1) > rhs.getDigit(lhs.nsize - i - 1))
 return false;
 }
 return false;
 }
 }
}

bool operator<=(const bigNum& lhs, const bigNum& rhs)
{
 return !(operator>(lhs, rhs));
}

bool operator<(const bigNum& lhs, const bigNum& rhs)
{
 if (operator<=(lhs, rhs) && operator!=(lhs, rhs))
 return true;
 else
 return false;
}

bool operator>=(const bigNum& lhs, const bigNum& rhs)
{
 if (operator>(lhs, rhs) || operator==(lhs, rhs))
 return true;
 else
 return false;
}

///////////////////////////////////////////////////////////////////
/\* P O M O C N I C Z E F U N K C J E A R Y T M E T Y C Z N E \*/
///////////////////////////////////////////////////////////////////

bigNum bigNum::add(const bigNum& lhs, const bigNum& rhs)
{
 std::string value;
 int left, right, carry = 0, sum;
 size\_t more\_digits = lhs.nsize > rhs.nsize ? lhs.nsize : rhs.nsize;
 for (size\_t i = 0; i < more\_digits; i++)
 {
 left = (i < lhs.nsize ? lhs.getDigit(i) : 0);
 right = (i < rhs.nsize ? rhs.getDigit(i) : 0);
 sum = left + right + carry;
 if (sum >= 10)
 {
 carry = 1;
 sum -= 10;
 }
 else
 carry = 0;
 value.insert(0, 1, INT\_TO\_CHAR(sum));
 }
 if (carry > 0)
 value.insert(0, 1, '1');
 bigNum wynik;
 wynik.positive = lhs.positive;
 wynik.number = value;
 wynik.updateSize();
 return wynik;
}

bigNum bigNum::subtract(bigNum lhs, const bigNum& rhs) //wymagane: lhs >= rhs
{
 for (size\_t i = 0; rhs.nsize > i; i++)
 {
 if (lhs.getDigit(i) >= rhs.getDigit(i))
 {
 lhs.changeDigit(i, (lhs.getDigit(i) - rhs.getDigit(i)));
 }
 else
 {
 int x = i + 1;
 while (lhs.getDigit(x) < 1)
 {
 lhs.changeDigit(x, 9);
 x++;
 }
 lhs.changeDigit(x, lhs.getDigit(x) - 1);
 lhs.changeDigit(i, lhs.getDigit(i) - rhs.getDigit(i) + 10);
 }
 }
 lhs.cleanup();
 return lhs;
}

bigNum bigNum::power10(bigNum lhs, const int& times)
{
 if (times == 0)
 return lhs;
 bigNum wynik = lhs;
 for (int i = 0; i < times; i++)
 {
 for (int i = 0; i < 9; i++)
 {
 wynik = add(wynik, lhs);
 }
 lhs = wynik;
 }
 return wynik;
}

bigNum bigNum::timesx(bigNum lhs, const int& times)
{
 if (times == 0)
 return 0;
 bigNum temp = lhs;
 for (int i = 1; i < times; i++)
 {
 lhs = add(lhs, temp);
 }
 return lhs;
}

bigNum bigNum::extract(const bigNum& lhs, const int& digits)
{
 bigNum other = "";
 for (int i = 0; i < digits; i++)
 {
 other.number += lhs.number[i];
 }
 other.updateSize();
 return other;
}

bigNum bigNum::basic\_division(bigNum& lhs, const bigNum& rhs, const int& digits)
{
 if (rhs == 0)
 return 0;
 bigNum division\_value;
 bigNum divided = extract(lhs, digits);
 while (divided >= rhs.abs())
 {
 divided = subtract(divided, rhs);
 division\_value += 1;
 }
 lhs.number.erase(0, digits);
 lhs.number.insert(0, divided.number);
 return division\_value;
}

/////////////////////////////////////////////////
/\* O P E R A T O R Y A R Y T M E T Y C Z N E \*/
/////////////////////////////////////////////////

bigNum bigNum::operator+=(const bigNum& rhs)
{
 if (positive && rhs.positive)
 {
 \*this = add(\*this, rhs);
 return \*this;
 }
 else if (!positive && rhs.positive)
 {
 if (this->abs() >= rhs)
 {
 \*this = subtract(\*this, rhs);
 return \*this;
 }
 else
 {
 \*this = subtract(rhs, \*this);
 positive = true;
 return \*this;
 }
 }
 else if (positive && !rhs.positive)
 {
 if (\*this >= rhs.abs())
 {
 \*this = subtract(\*this, rhs);
 return \*this;
 }
 else
 {
 \*this = subtract(rhs, \*this);
 positive = false;
 return \*this;
 }
 }
 else //if (!positive && !rhs.positive)
 {
 \*this = add(\*this, rhs);
 positive = false;
 return \*this;
 }
}

bigNum bigNum::operator-=(const bigNum& rhs)
{
 if (positive && rhs.positive)
 {
 if (\*this >= rhs)
 {
 \*this = subtract(\*this, rhs);
 return \*this;
 }
 else
 {
 \*this = subtract(rhs, \*this);
 this->changeSign();
 return \*this;
 }
 }
 else if (!positive && rhs.positive)
 {
 \*this = add(\*this, rhs);
 return \*this;
 }
 else if (positive && !rhs.positive)
 {
 \*this = add(\*this, rhs);
 return \*this;
 }
 else //if (!positive && !rhs.positive)
 {
 if (this->abs() >= rhs.abs())
 {
 positive = true;
 bigNum wynik = \*this;
 wynik -= rhs.abs();
 \*this = wynik;
 if (\*this != 0)
 positive = false;
 return \*this;
 }
 else
 {
 bigNum wynik = rhs.abs();
 wynik -= this->abs();
 \*this = wynik;
 return \*this;
 }
 }
}

bigNum bigNum::operator\*=(const bigNum& rhs)
{
 bool positive\_prev = positive;
 bigNum base = this->abs(), adder;
 \*this = 0;
 for (size\_t i = 0; rhs.nsize > i; i++)
 {
 adder = timesx(power10(base, i), rhs.getDigit(i));
 \*this = add(\*this, adder);
 }
 positive = positive\_prev;
 if (!positive && !rhs.positive)
 positive = true;
 else if (positive && !rhs.positive)
 positive = false;
 return \*this;
}

bigNum bigNum::operator/=(const bigNum& rhs)
{
 if (rhs == 0)
 {
 return \*this;
 }
 else if (rhs.abs() > this->abs())
 {
 \*this = 0;
 return \*this;
 }
 bool positive\_prev = positive;
 bigNum value;
 while (this->abs() >= rhs.abs())
 {
 if (extract(\*this, rhs.nsize) < rhs)
 {
 value += power10(basic\_division(\*this, rhs, rhs.nsize + 1)\
 , (\*this == 0 ? 0 : nsize - rhs.nsize - 1));
 }
 else
 {
 value += power10(basic\_division(\*this, rhs, rhs.nsize), nsize - rhs.nsize);
 }
 this->cleanup();
 }
 \*this = value;
 positive = positive\_prev;
 if (!positive && !rhs.positive)
 positive = true;
 else if (positive && !rhs.positive)
 positive = false;
 return \*this;
}

bigNum bigNum::operator%=(const bigNum& rhs)
{
 if (rhs == 0)
 {
 \*this = 0;
 return \*this;
 }
 while (this->abs() >= rhs.abs())
 {
 if (extract(\*this, rhs.nsize) < rhs)
 {
 basic\_division(\*this, rhs, rhs.nsize + 1);
 }
 else
 {
 basic\_division(\*this, rhs, rhs.nsize);
 }
 this->cleanup();
 }
 if (!positive && !rhs.positive)
 positive = true;
 else if (positive && !rhs.positive)
 positive = false;
 return \*this;
}

bigNum bigNum::operator^=(const bigNum& rhs)
{
 if (rhs == 0)
 {
 \*this = 1;
 return \*this;
 }
 else if (rhs < 0)
 {
 return \*this;
 }
 bigNum base = \*this;
 for (int i = 1; i < rhs; i++)
 {
 \*this \*= base;
 }
 return \*this;
}

bigNum operator+(const bigNum& lhs, const bigNum& rhs)
{
 bigNum wynik = lhs;
 return wynik += rhs;
}

bigNum operator-(const bigNum& lhs, const bigNum& rhs)
{
 bigNum wynik = lhs;
 return wynik -= rhs;
}

bigNum operator\*(const bigNum& lhs, const bigNum& rhs)
{
 bigNum wynik = lhs;
 return wynik \*= rhs;
}

bigNum operator/(const bigNum& lhs, const bigNum& rhs)
{
 bigNum wynik = lhs;
 return wynik /= rhs;
}

bigNum operator%(const bigNum& lhs, const bigNum& rhs)
{
 bigNum wynik = lhs;
 return wynik %= rhs;
}

bigNum operator^(const bigNum& lhs, const bigNum& rhs)
{
 bigNum wynik = lhs;
 return wynik ^= rhs;
}

bigNum bigNum::operator-()
{
 bigNum wynik = \*this;
 wynik.changeSign();
 return wynik;
}

bigNum bigNum::operator++()
{
 return \*this += 1;
}

bigNum bigNum::operator++(int)
{
 bigNum wynik = \*this;
 \*this += 1;
 return wynik;
}

bigNum bigNum::operator--()
{
 return \*this -= 1;
}

bigNum bigNum::operator--(int)
{
 bigNum wynik = \*this;
 \*this -= 1;
 return wynik;
}

```