diff --git a/others/large_number.h b/others/large_number.h index 84d885f67..4f3851053 100644 --- a/others/large_number.h +++ b/others/large_number.h @@ -5,6 +5,7 @@ #ifndef OTHERS_LARGE_NUMBER_H_ #define OTHERS_LARGE_NUMBER_H_ +#include #include #include #include @@ -19,263 +20,253 @@ * large number with long unsigned integers. **/ class large_number { -public: - large_number() /**< initializer with value = 1 */ { _digits.push_back(1); } + public: + /**< initializer with value = 1 */ + large_number() { _digits.push_back(1); } - large_number(uint64_t n) /**< initializer from an integer */ - { - uint64_t carry = n; - do { - add_digit(carry % 10); - carry /= 10; - } while (carry != 0); + /**< initializer from an integer */ + explicit large_number(uint64_t n) { + uint64_t carry = n; + do { + add_digit(carry % 10); + carry /= 10; + } while (carry != 0); + } + + /**< initializer from another large_number */ + explicit large_number(const large_number &a) { _digits = a._digits; } + + /**< initializer from a vector */ + explicit large_number(const std::vector &vec) { + _digits = vec; + } + + /**< initializer from a string */ + explicit large_number(const char *number_str) { + for (size_t i = strlen(number_str); i > 0; i--) { + unsigned char a = number_str[i - 1] - '0'; + if (a >= 0 && a <= 9) _digits.push_back(a); + } + } + + /** + * Function to check implementation + **/ + static bool test() { + std::cout << "------ Checking `large_number` class implementations\t" + << std::endl; + large_number a(40); + // 1. test multiplication + a *= 10; + if (a != large_number(400)) { + std::cerr << "\tFailed 1/6 (" << a << "!=400)" << std::endl; + return false; + } + std::cout << "\tPassed 1/6..."; + // 2. test compound addition with integer + a += 120; + if (a != large_number(520)) { + std::cerr << "\tFailed 2/6 (" << a << "!=520)" << std::endl; + return false; + } + std::cout << "\tPassed 2/6..."; + // 3. test compound multiplication again + a *= 10; + if (a != large_number(5200)) { + std::cerr << "\tFailed 3/6 (" << a << "!=5200)" << std::endl; + return false; + } + std::cout << "\tPassed 3/6..."; + // 4. test increment (prefix) + ++a; + if (a != large_number(5201)) { + std::cerr << "\tFailed 4/6 (" << a << "!=5201)" << std::endl; + return false; + } + std::cout << "\tPassed 4/6..."; + // 5. test increment (postfix) + a++; + if (a != large_number(5202)) { + std::cerr << "\tFailed 5/6 (" << a << "!=5202)" << std::endl; + return false; + } + std::cout << "\tPassed 5/6..."; + // 6. test addition with another large number + a = a + large_number("7000000000000000000000000000000"); + if (a != large_number("7000000000000000000000000005202")) { + std::cerr << "\tFailed 6/6 (" << a << "!=7000000000000000000000000005202)" + << std::endl; + return false; + } + std::cout << "\tPassed 6/6..." << std::endl; + return true; + } + + /** + * add a digit at MSB to the large number + **/ + void add_digit(unsigned int value) { + if (value > 9) { + std::cerr << "digit > 9!!\n"; + exit(EXIT_FAILURE); } - large_number( - const large_number &a) /**< initializer from another large_number */ - { - _digits = a._digits; - } + _digits.push_back(value); + } - large_number( - const std::vector &vec) /**< initializer from a vector */ - { - _digits = vec; - } + /** + * Get number of digits in the number + **/ + const size_t num_digits() const { return _digits.size(); } - large_number(const char *number_str) /**< initializer from a string */ - { - for (size_t i = strlen(number_str); i > 0; i--) { - unsigned char a = number_str[i - 1] - '0'; - if (a >= 0 && a <= 9) - _digits.push_back(a); - } - } + /** + * operator over load to access the + * i^th digit conveniently and also + * assign value to it + **/ + inline unsigned char &operator[](size_t n) { return this->_digits[n]; } - /** - * Function to check implementation - **/ - static bool test() { - std::cout << "------ Checking `large_number` class implementations\t" - << std::endl; - large_number a(40); - // 1. test multiplication - a *= 10; - if (a != large_number(400)) { - std::cerr << "\tFailed 1/6 (" << a << "!=400)" << std::endl; - return false; - } - std::cout << "\tPassed 1/6..."; - // 2. test compound addition with integer - a += 120; - if (a != large_number(520)) { - std::cerr << "\tFailed 2/6 (" << a << "!=520)" << std::endl; - return false; - } - std::cout << "\tPassed 2/6..."; - // 3. test compound multiplication again - a *= 10; - if (a != large_number(5200)) { - std::cerr << "\tFailed 3/6 (" << a << "!=5200)" << std::endl; - return false; - } - std::cout << "\tPassed 3/6..."; - // 4. test increment (prefix) - ++a; - if (a != large_number(5201)) { - std::cerr << "\tFailed 4/6 (" << a << "!=5201)" << std::endl; - return false; - } - std::cout << "\tPassed 4/6..."; - // 5. test increment (postfix) - a++; - if (a != large_number(5202)) { - std::cerr << "\tFailed 5/6 (" << a << "!=5202)" << std::endl; - return false; - } - std::cout << "\tPassed 5/6..."; - // 6. test addition with another large number - a = a + large_number("7000000000000000000000000000000"); - if (a != large_number("7000000000000000000000000005202")) { - std::cerr << "\tFailed 6/6 (" << a - << "!=7000000000000000000000000005202)" << std::endl; - return false; - } - std::cout << "\tPassed 6/6..." << std::endl; - return true; - } + inline const unsigned char &operator[](size_t n) const { + return this->_digits[n]; + } - /** - * add a digit at MSB to the large number - **/ - void add_digit(unsigned int value) { - if (value > 9) { - std::cerr << "digit > 9!!\n"; - exit(EXIT_FAILURE); - } + /** + * operator overload to compare two numbers + **/ + friend std::ostream &operator<<(std::ostream &out, const large_number &a) { + for (size_t i = a.num_digits(); i > 0; i--) + out << static_cast(a[i - 1]); + return out; + } - _digits.push_back(value); - } + /** + * operator overload to compare two numbers + **/ + friend bool operator==(large_number const &a, large_number const &b) { + size_t N = a.num_digits(); + if (N != b.num_digits()) return false; + for (size_t i = 0; i < N; i++) + if (a[i] != b[i]) return false; + return true; + } - /** - * Get number of digits in the number - **/ - const size_t num_digits() const { return _digits.size(); } + /** + * operator overload to compare two numbers + **/ + friend bool operator!=(large_number const &a, large_number const &b) { + return !(a == b); + } - /** - * operator over load to access the - * i^th digit conveniently and also - * assign value to it - **/ - inline unsigned char &operator[](size_t n) { return this->_digits[n]; } + /** + * operator overload to increment (prefix) + **/ + large_number &operator++() { + (*this) += 1; + return *this; + } - inline const unsigned char &operator[](size_t n) const { - return this->_digits[n]; - } + /** + * operator overload to increment (postfix) + **/ + large_number operator++(int) { + large_number tmp(_digits); + ++(*this); + return tmp; + } - /** - * operator overload to compare two numbers - **/ - friend std::ostream &operator<<(std::ostream &out, const large_number &a) { - for (size_t i = a.num_digits(); i > 0; i--) - out << static_cast(a[i - 1]); - return out; - } - - /** - * operator overload to compare two numbers - **/ - friend bool operator==(large_number const &a, large_number const &b) { - size_t N = a.num_digits(); - if (N != b.num_digits()) - return false; - for (size_t i = 0; i < N; i++) - if (a[i] != b[i]) - return false; - return true; - } - - /** - * operator overload to compare two numbers - **/ - friend bool operator!=(large_number const &a, large_number const &b) { - return !(a == b); - } - - /** - * operator overload to increment (prefix) - **/ - large_number &operator++() { - (*this) += 1; - return *this; - } - - /** - * operator overload to increment (postfix) - **/ - large_number operator++(int) { - large_number tmp(_digits); - ++(*this); - return tmp; - } - - /** - * operator overload to add - **/ - template - large_number &operator+=(T n) { - if (typeid(T) == - typeid(large_number)) // if adding with another large_number - { - large_number *b = (large_number *)&n; - const size_t max_L = std::max(this->num_digits(), b->num_digits()); - unsigned int carry = 0; - size_t i; - for (i = 0; i < max_L || carry != 0; i++) { - if (i < b->num_digits()) - carry += (*b)[i]; - if (i < this->num_digits()) - carry += (*this)[i]; - if (i < this->num_digits()) - (*this)[i] = carry % 10; - else - this->add_digit(carry % 10); - carry /= 10; - } - } else if (std::is_integral::value) - return (*this) += large_number(n); + /** + * operator overload to add + **/ + template + large_number &operator+=(T n) { + // if adding with another large_number + if (typeid(T) == typeid(large_number)) { + large_number *b = static_cast(&n); + const size_t max_L = std::max(this->num_digits(), b->num_digits()); + unsigned int carry = 0; + size_t i; + for (i = 0; i < max_L || carry != 0; i++) { + if (i < b->num_digits()) carry += (*b)[i]; + if (i < this->num_digits()) carry += (*this)[i]; + if (i < this->num_digits()) + (*this)[i] = carry % 10; else - std::cerr << "Must be integer addition unsigned integer types." - << std::endl; - return *this; + this->add_digit(carry % 10); + carry /= 10; + } + } else if (std::is_integral::value) { + return (*this) += large_number(n); + } else { + std::cerr << "Must be integer addition unsigned integer types." + << std::endl; + } + return *this; + } + + /** + * operator overload to perform addition + **/ + template + friend large_number &operator+(const large_number &a, const T &b) { + a += b; + return a; + } + + /** + * assignment operator + **/ + void operator=(const large_number &b) { _digits = b._digits; } + + /** + * operator overload to increment + **/ + template + large_number &operator*=(const T n) { + static_assert(std::is_integral::value, + "Must be integer addition unsigned integer types."); + this->multiply(n); + return *this; + } + + /** + * returns i^th digit as an ASCII character + **/ + const char digit_char(size_t i) const { + return _digits[num_digits() - i - 1] + '0'; + } + + private: + /** + * multiply large number with another integer and + * store the result in the same large number + **/ + template + void multiply(const T n) { + static_assert(std::is_integral::value, "Can only have integer types."); + // assert(!(std::is_signed::value)); //, "Implemented only for + // unsigned integer types."); + + size_t i; + uint64_t carry = 0, temp; + for (i = 0; i < this->num_digits(); i++) { + temp = (*this)[i] * n; + temp += carry; + if (temp < 10) { + carry = 0; + } else { + carry = temp / 10; + temp = temp % 10; + } + (*this)[i] = temp; } - /** - * operator overload to perform addition - **/ - template - friend large_number &operator+(large_number &a, const T &b) { - a += b; - return a; + while (carry != 0) { + this->add_digit(carry % 10); + carry /= 10; } + } - /** - * assignment operator - **/ - void operator=(const large_number &b) { _digits = b._digits; } - - /** - * operator overload to increment - **/ - template - large_number &operator*=(const T n) { - static_assert(std::is_integral::value, - "Must be integer addition unsigned integer types."); - this->multiply(n); - return *this; - } - - /** - * returns i^th digit as an ASCII character - **/ - const char digit_char(size_t i) const { - return _digits[num_digits() - i - 1] + '0'; - } - -private: - /** - * multiply large number with another integer and - * store the result in the same large number - **/ - template - void multiply(const T n) { - static_assert(std::is_integral::value, - "Can only have integer types."); - // assert(!(std::is_signed::value)); //, "Implemented only for - // unsigned integer types."); - - size_t i; - unsigned long long carry = 0, temp; - for (i = 0; i < this->num_digits(); i++) { - temp = (*this)[i] * n; - temp += carry; - if (temp < 10) - carry = 0; - else { - carry = temp / 10; - temp = temp % 10; - } - (*this)[i] = temp; - } - - while (carry != 0) { - this->add_digit(carry % 10); - carry /= 10; - } - }; - - std::vector - _digits; /**< where individual digits are stored */ + std::vector _digits; /**< where individual digits are stored */ }; #endif // OTHERS_LARGE_NUMBER_H_