From 282c24d204b80674f7180bcb47bd64c3410ef698 Mon Sep 17 00:00:00 2001 From: Omri Date: Tue, 10 Apr 2018 22:25:58 +0300 Subject: [PATCH 1/7] Updated functions to vector format --- include/BigInt.hpp | 3 +- include/functions/conversion.hpp | 12 ++- include/functions/random.hpp | 15 ++- include/functions/utility.hpp | 77 ++++++++++++++- include/operators/assignment.hpp | 12 +-- include/operators/binary_arithmetic.hpp | 123 +++++++++++++----------- include/operators/io_stream.hpp | 7 +- include/operators/relational.hpp | 26 +++-- include/operators/unary_arithmetic.hpp | 11 +-- 9 files changed, 193 insertions(+), 93 deletions(-) diff --git a/include/BigInt.hpp b/include/BigInt.hpp index 0ae1602..35afbde 100644 --- a/include/BigInt.hpp +++ b/include/BigInt.hpp @@ -9,10 +9,11 @@ #define BIG_INT_HPP #include +#include #include class BigInt { - std::vector magnitude; + std::vector magnitude; bool is_negative; public: diff --git a/include/functions/conversion.hpp b/include/functions/conversion.hpp index 37387c7..b5b7c58 100644 --- a/include/functions/conversion.hpp +++ b/include/functions/conversion.hpp @@ -15,8 +15,16 @@ */ std::string BigInt::to_string() const { - // prefix with sign if negative - return this->sign == '-' ? "-" + this->value : this->value; + + std::string num_string; + + for (uint64_t ull : this->magnitude) + while (ull > 0) { + num_string += ((ull % 10) + '0'); + ull /= 10; + } + + return this->is_negative ? "-" + num_string : num_string; } diff --git a/include/functions/random.hpp b/include/functions/random.hpp index 41f7375..ee15aee 100644 --- a/include/functions/random.hpp +++ b/include/functions/random.hpp @@ -30,14 +30,13 @@ BigInt big_random(size_t num_digits = 0) { // use a random number for it: num_digits = 1 + rand_generator() % MAX_RANDOM_LENGTH; - BigInt big_rand; - big_rand.value = ""; // clear value to append digits - while (big_rand.value.size() < num_digits) - big_rand.value += std::to_string(rand_generator()); - if (big_rand.value.size() != num_digits) - big_rand.value.erase(num_digits); // erase extra digits - - return big_rand; + std::string random_value = ""; + while (random_value.size() < num_digits) + random_value += std::to_string(rand_generator()); + if (random_value.size() != num_digits) + random_value.erase(num_digits); // erase extra digits + + return BigInt(random_value); } diff --git a/include/functions/utility.hpp b/include/functions/utility.hpp index a26ed45..dc67795 100644 --- a/include/functions/utility.hpp +++ b/include/functions/utility.hpp @@ -8,6 +8,8 @@ #define BIG_INT_UTILITY_FUNCTIONS_HPP #include +#include +#include /* @@ -93,7 +95,6 @@ std::tuple get_larger_and_smaller(const std::string& n return std::make_tuple(larger, smaller); } - /* is_power_of_10 ---------------------- @@ -110,4 +111,78 @@ bool is_power_of_10(const std::string& num){ return true; // first digit is 1 and the following digits are all 0 } + +/*--------------------- Vector functions ---------------------*/ + +/* + add_leading_zeroes + ------------------ + Adds a given number of leading zeroes to a string-represented integer `num`. +*/ + +void add_leading_zeroes(std::vector& num, size_t num_zeroes) { + std::vector tmp(num_zeroes, 0); + tmp.insert(tmp.end(), num.begin(), num.end()); + num = tmp; +} + + +/* + add_trailing_zeroes + ------------------- + Adds a given number of trailing zeroes to a string-represented integer `num`. +*/ + +void add_trailing_zeroes(std::vector& num, size_t num_zeroes) { + std::vector tmp(num_zeroes, 0); + num.insert(num.end(), tmp.begin(), tmp.end()); +} + +/* + strip_leading_zeroes + -------------------- + Strip the leading zeroes from a number represented as a vector. +*/ + +void strip_trailing_zeroes(std::vector& num) { + for (auto digit_itter = num.rbegin(); digit_itter != num.rend(); digit_itter++) + if (*digit_itter != 0) { + num = std::vector(num.rend(), digit_itter + 1); + return; + } + + // If all 0's + num.clear(); + num.push_back(0); +} + +/* + get_larger_and_smaller + ---------------------- + Identifies the given vector-represented integers as `larger` and `smaller`, + padding the smaller number with leading zeroes to make it equal in length to + the larger number. + Note: for simplicity and efficiency, this function only compares length and not value. +*/ + +std::tuple, std::vector> get_larger_and_smaller(const std::vector& num1, + const std::vector& num2) { + std::vector larger, smaller; + if (num1.size() > num2.size()) { + larger = num1; + smaller = num2; + } + else { + larger = num2; + smaller = num1; + } + + // pad the smaller number with zeroes + add_trailing_zeroes(smaller, larger.size() - smaller.size()); + + return std::make_tuple(larger, smaller); +} + + + #endif // BIG_INT_UTILITY_FUNCTIONS_HPP diff --git a/include/operators/assignment.hpp b/include/operators/assignment.hpp index 933c45e..15791d8 100644 --- a/include/operators/assignment.hpp +++ b/include/operators/assignment.hpp @@ -17,8 +17,8 @@ */ BigInt& BigInt::operator=(const BigInt& num) { - value = num.value; - sign = num.sign; + magnitude = num.magnitude; + is_negative = num.is_negative; return *this; } @@ -31,8 +31,8 @@ BigInt& BigInt::operator=(const BigInt& num) { BigInt& BigInt::operator=(const long long& num) { BigInt temp(num); - value = temp.value; - sign = temp.sign; + magnitude = temp.magnitude; + is_negative = temp.is_negative; return *this; } @@ -45,8 +45,8 @@ BigInt& BigInt::operator=(const long long& num) { BigInt& BigInt::operator=(const std::string& num) { BigInt temp(num); - value = temp.value; - sign = temp.sign; + magnitude = temp.magnitude; + is_negative = temp.is_negative; return *this; } diff --git a/include/operators/binary_arithmetic.hpp b/include/operators/binary_arithmetic.hpp index ad975e1..b9e0efe 100644 --- a/include/operators/binary_arithmetic.hpp +++ b/include/operators/binary_arithmetic.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include "BigInt.hpp" @@ -32,36 +33,38 @@ const long long FLOOR_SQRT_LLONG_MAX = 3037000499; BigInt BigInt::operator+(const BigInt& num) const { // if the operands are of opposite signs, perform subtraction - if (this->sign == '+' and num.sign == '-') { + if (not this->is_negative and num.is_negative) { BigInt rhs = num; - rhs.sign = '+'; + rhs.is_negative = false; return *this - rhs; } - else if (this->sign == '-' and num.sign == '+') { + else if (this->is_negative and not num.is_negative) { BigInt lhs = *this; - lhs.sign = '+'; + lhs.is_negative = false; return -(lhs - num); } - // identify the numbers as `larger` and `smaller` - std::string larger, smaller; - std::tie(larger, smaller) = get_larger_and_smaller(this->value, num.value); - - BigInt result; // the resultant sum - result.value = ""; // the value is cleared as the digits will be appended - short carry = 0, sum; - // add the two values - for (long i = larger.size() - 1; i >= 0; i--) { - sum = larger[i] - '0' + smaller[i] - '0' + carry; - result.value = std::to_string(sum % 10) + result.value; - carry = sum / (short) 10; + BigInt result; + int carry = 0; + + std::vector larger, smaller; + std::tie(larger, smaller) = get_larger_and_smaller(this->magnitude, num.magnitude); + + for (size_t i = 0; i < larger.size(); i++) { + // On overflow, sum will get the remainder of the overflow + uint64_t sum = smaller[i] + larger[i] + carry; + result.magnitude.push_back(sum); + + // Overflow check + if (larger[i] > (UINT64_MAX - carry) and smaller[i] > (UINT64_MAX - larger[i] - carry)) + carry = 1; + else if (smaller[i] > (UINT64_MAX - carry) and larger[i] > (UINT64_MAX - smaller[i] - carry)) + carry = 1; + else if (larger[i] == UINT64_MAX and smaller[i] == UINT64_MAX) + carry = 1; + else + carry = 0; } - if (carry) - result.value = std::to_string(carry) + result.value; - - // if the operands are negative, the result is negative - if (this->sign == '-' and result.value != "0") - result.sign = '-'; return result; } @@ -74,65 +77,71 @@ BigInt BigInt::operator+(const BigInt& num) const { */ BigInt BigInt::operator-(const BigInt& num) const { - // if the operands are of opposite signs, perform addition - if (this->sign == '+' and num.sign == '-') { + // If the operands are of opposite signs, perform addition + if (not this->is_negative and num.is_negative) { BigInt rhs = num; - rhs.sign = '+'; + rhs.is_negative = false; return *this + rhs; } - else if (this->sign == '-' and num.sign == '+') { + else if (this->is_negative and not num.is_negative) { BigInt lhs = *this; - lhs.sign = '+'; + lhs.is_negative = false; return -(lhs + num); } - BigInt result; // the resultant difference - // identify the numbers as `larger` and `smaller` - std::string larger, smaller; + // The resultant difference + BigInt result; + // Identify the numbers as `larger` and `smaller` + std::vector larger, smaller; + if (abs(*this) > abs(num)) { - larger = this->value; - smaller = num.value; + larger = this->magnitude; + smaller = num.magnitude; - if (this->sign == '-') // -larger - -smaller = -result - result.sign = '-'; + if (this->is_negative) // -larger - -smaller = -result + result.is_negative = true; } else { - larger = num.value; - smaller = this->value; + larger = num.magnitude; + smaller = this->magnitude; - if (num.sign == '+') // smaller - larger = -result - result.sign = '-'; + if (not num.is_negative) // smaller - larger = -result + result.is_negative = true; } // pad the smaller number with zeroes - add_leading_zeroes(smaller, larger.size() - smaller.size()); + add_trailing_zeroes(smaller, larger.size() - smaller.size()); + + uint64_t difference; + size_t i, j; - result.value = ""; // the value is cleared as the digits will be appended - short difference; - long i, j; // subtract the two values - for (i = larger.size() - 1; i >= 0; i--) { - difference = larger[i] - smaller[i]; - if (difference < 0) { - for (j = i - 1; j >= 0; j--) { - if (larger[j] != '0') { - larger[j]--; // borrow from the j-th digit + for (i = 0; i < larger.size(); i++) { + if (larger[i] >= smaller[i]) + difference = larger[i] - smaller[i]; + else { + difference = std::numeric_limits::max() - smaller[i] + 1 + larger[i]; + for (j = i + 1; j < larger.size(); j++) + if (larger[j] != 0) { + larger[j]--; // Borrow from the j-th digit break; } - } - j++; + j--; while (j != i) { - larger[j] = '9'; // add the borrow and take away 1 - j++; + // Add the borrow and take one + larger[j] = std::numeric_limits::max(); + // Walk back to i + j--; } - difference += 10; // add the borrow } - result.value = std::to_string(difference) + result.value; + result.magnitude.push_back(difference); } - strip_leading_zeroes(result.value); + + strip_trailing_zeroes(result.magnitude); // if the result is 0, set its sign as + - if (result.value == "0") - result.sign = '+'; + if ((result.magnitude.size() == 1 and result.magnitude[0] == 0) or + result.magnitude.size() == 0) + result.is_negative = false; return result; } diff --git a/include/operators/io_stream.hpp b/include/operators/io_stream.hpp index 8f2b876..827b839 100644 --- a/include/operators/io_stream.hpp +++ b/include/operators/io_stream.hpp @@ -10,6 +10,7 @@ #include "BigInt.hpp" #include "constructors/constructors.hpp" #include "operators/assignment.hpp" +#include "functions/conversion.hpp" /* @@ -32,9 +33,9 @@ std::istream& operator>>(std::istream& in, BigInt& num) { */ std::ostream& operator<<(std::ostream& out, const BigInt& num) { - if (num.sign == '-') - out << num.sign; - out << num.value; + if (num.is_negative) + out << '-'; + out << num.to_string(); return out; } diff --git a/include/operators/relational.hpp b/include/operators/relational.hpp index 460f915..29ac501 100644 --- a/include/operators/relational.hpp +++ b/include/operators/relational.hpp @@ -18,7 +18,7 @@ */ bool BigInt::operator==(const BigInt& num) const { - return (sign == num.sign) and (value == num.value); + return (is_negative == num.is_negative) and (magnitude == num.magnitude); } @@ -38,18 +38,28 @@ bool BigInt::operator!=(const BigInt& num) const { */ bool BigInt::operator<(const BigInt& num) const { - if (sign == num.sign) { - if (sign == '+') { - if (value.length() == num.value.length()) - return value < num.value; - else - return value.length() < num.value.length(); + + if (is_negative == num.is_negative) { + if (not is_negative) { + if (magnitude.size() == num.magnitude.size()) { + // Check in reverse order, magnitudes are saved LSB first. + for (int64_t i = (magnitude.size() - 1); i > 0; i--) { + if (magnitude[i] != num.magnitude[i]) { + return magnitude[i] < num.magnitude[i]; + } + } + // Values equal + return true; + } + else { + return magnitude.size() < num.magnitude.size(); + } } else return -(*this) > -num; } else - return sign == '-'; + return is_negative; } diff --git a/include/operators/unary_arithmetic.hpp b/include/operators/unary_arithmetic.hpp index 757685e..03aa492 100644 --- a/include/operators/unary_arithmetic.hpp +++ b/include/operators/unary_arithmetic.hpp @@ -33,13 +33,10 @@ BigInt BigInt::operator+() const { BigInt BigInt::operator-() const { BigInt temp; - temp.value = value; - if (value != "0") { - if (sign == '+') - temp.sign = '-'; - else - temp.sign = '+'; - } + temp.magnitude = magnitude; + // If magnitude is not 0 + if (magnitude.size() != 1 and magnitude[0] != 0) + temp.is_negative = not is_negative; return temp; } From 2a466d257943956f5cc941b7593a46d497c542cd Mon Sep 17 00:00:00 2001 From: Omri Date: Tue, 10 Apr 2018 23:49:35 +0300 Subject: [PATCH 2/7] Efficiated Relational operator functions --- include/constructors/constructors.hpp | 2 +- include/operators/relational.hpp | 43 ++++++++++++++++++++------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/include/constructors/constructors.hpp b/include/constructors/constructors.hpp index 4d64c60..6929781 100644 --- a/include/constructors/constructors.hpp +++ b/include/constructors/constructors.hpp @@ -39,7 +39,7 @@ BigInt::BigInt(const BigInt& num) { */ BigInt::BigInt(const long long& num) { - magnitude = { (unsigned long long) llabs(num) }; + magnitude = { (uint64_t) llabs(num) }; is_negative = num < 0; } diff --git a/include/operators/relational.hpp b/include/operators/relational.hpp index 29ac501..91388d9 100644 --- a/include/operators/relational.hpp +++ b/include/operators/relational.hpp @@ -99,6 +99,14 @@ bool BigInt::operator>=(const BigInt& num) const { */ bool BigInt::operator==(const long long& num) const { + // Check if it is possible to efficiate the method, 99% of the time it will be efficiated + if (sizeof(long long) == sizeof(uint64_t)) { + if ((num < 0) != this->is_negative or + this->magnitude.size() != 1) + return false; + + return this->magnitude[0] == (uint64_t)llabs(num); + } return *this == BigInt(num); } @@ -109,7 +117,7 @@ bool BigInt::operator==(const long long& num) const { */ bool operator==(const long long& lhs, const BigInt& rhs) { - return BigInt(lhs) == rhs; + return rhs == lhs; } @@ -119,7 +127,7 @@ bool operator==(const long long& lhs, const BigInt& rhs) { */ bool BigInt::operator!=(const long long& num) const { - return !(*this == BigInt(num)); + return !(*this == num); } @@ -129,7 +137,7 @@ bool BigInt::operator!=(const long long& num) const { */ bool operator!=(const long long& lhs, const BigInt& rhs) { - return BigInt(lhs) != rhs; + return !(rhs == lhs); } @@ -139,6 +147,21 @@ bool operator!=(const long long& lhs, const BigInt& rhs) { */ bool BigInt::operator<(const long long& num) const { + // Check if it is possible to efficiate the method + if (sizeof(long long) == sizeof(uint64_t)) { + if (((num <= 0) and not this->is_negative) or + this->magnitude.size() > 1) { + return false; + } + if (num >= 0 and this->is_negative) { + return true; + } + if (num > 0) { + return this->magnitude[0] < (uint64_t)num; + } + return this->magnitude[0] > (uint64_t)num; + } + return *this < BigInt(num); } @@ -149,7 +172,7 @@ bool BigInt::operator<(const long long& num) const { */ bool operator<(const long long& lhs, const BigInt& rhs) { - return BigInt(lhs) < rhs; + return rhs < lhs; } @@ -159,7 +182,7 @@ bool operator<(const long long& lhs, const BigInt& rhs) { */ bool BigInt::operator>(const long long& num) const { - return *this > BigInt(num); + return !((*this < num) or (*this == num)); } @@ -169,7 +192,7 @@ bool BigInt::operator>(const long long& num) const { */ bool operator>(const long long& lhs, const BigInt& rhs) { - return BigInt(lhs) > rhs; + return rhs > lhs; } @@ -179,7 +202,7 @@ bool operator>(const long long& lhs, const BigInt& rhs) { */ bool BigInt::operator<=(const long long& num) const { - return !(*this > BigInt(num)); + return !(*this > num); } @@ -189,7 +212,7 @@ bool BigInt::operator<=(const long long& num) const { */ bool operator<=(const long long& lhs, const BigInt& rhs) { - return BigInt(lhs) <= rhs; + return !(rhs > lhs); } @@ -199,7 +222,7 @@ bool operator<=(const long long& lhs, const BigInt& rhs) { */ bool BigInt::operator>=(const long long& num) const { - return !(*this < BigInt(num)); + return !(*this < num); } @@ -209,7 +232,7 @@ bool BigInt::operator>=(const long long& num) const { */ bool operator>=(const long long& lhs, const BigInt& rhs) { - return BigInt(lhs) >= rhs; + return !(rhs < lhs); } From 263dc010b39324362be46e6a4043e9c328f3cc1b Mon Sep 17 00:00:00 2001 From: Omri Date: Wed, 11 Apr 2018 00:18:12 +0300 Subject: [PATCH 3/7] Added long long conversion to 64 bit if bigger --- include/constructors/constructors.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/constructors/constructors.hpp b/include/constructors/constructors.hpp index 6929781..677a5fd 100644 --- a/include/constructors/constructors.hpp +++ b/include/constructors/constructors.hpp @@ -39,7 +39,13 @@ BigInt::BigInt(const BigInt& num) { */ BigInt::BigInt(const long long& num) { - magnitude = { (uint64_t) llabs(num) }; + + if (sizeof(long long) == (sizeof(uint64_t) * 2)) { + magnitude.push_back((uint64_t)llabs((uint64_t)num)); + magnitude.push_back((uint64_t)llabs(num / UINT64_MAX)); + } + else + magnitude = { (uint64_t) llabs(num) }; is_negative = num < 0; } From d5a6fe39cccd9183a4cb4e920a2893f6986e9744 Mon Sep 17 00:00:00 2001 From: Omri Date: Wed, 11 Apr 2018 11:45:54 +0300 Subject: [PATCH 4/7] Optimized Constructors --- include/constructors/constructors.hpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/include/constructors/constructors.hpp b/include/constructors/constructors.hpp index 677a5fd..156a7f9 100644 --- a/include/constructors/constructors.hpp +++ b/include/constructors/constructors.hpp @@ -16,10 +16,10 @@ ------------------- */ -BigInt::BigInt() { - magnitude = { 0 }; - is_negative = false; -} +BigInt::BigInt() + : magnitude(1,0) + , is_negative(false) + { } /* @@ -27,10 +27,10 @@ BigInt::BigInt() { ---------------- */ -BigInt::BigInt(const BigInt& num) { - magnitude = num.magnitude; - is_negative = num.is_negative; -} +BigInt::BigInt(const BigInt& num) + : magnitude(num.magnitude) + , is_negative(num.is_negative) + { } /* @@ -39,13 +39,15 @@ BigInt::BigInt(const BigInt& num) { */ BigInt::BigInt(const long long& num) { + if (sizeof(long long) == (sizeof(uint64_t))) + magnitude = { (uint64_t) llabs(num) }; - if (sizeof(long long) == (sizeof(uint64_t) * 2)) { + // If size not equal, long long will be bigger + else { magnitude.push_back((uint64_t)llabs((uint64_t)num)); - magnitude.push_back((uint64_t)llabs(num / UINT64_MAX)); + if (num / UINT64_MAX > 0) + magnitude.push_back((uint64_t)llabs(num / UINT64_MAX)); } - else - magnitude = { (uint64_t) llabs(num) }; is_negative = num < 0; } From b0844ccb336901c022a41ad615985ea2def2d45a Mon Sep 17 00:00:00 2001 From: Omri Date: Wed, 11 Apr 2018 11:46:26 +0300 Subject: [PATCH 5/7] Fixed typos --- include/operators/relational.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/operators/relational.hpp b/include/operators/relational.hpp index 91388d9..af6d8fb 100644 --- a/include/operators/relational.hpp +++ b/include/operators/relational.hpp @@ -43,7 +43,7 @@ bool BigInt::operator<(const BigInt& num) const { if (not is_negative) { if (magnitude.size() == num.magnitude.size()) { // Check in reverse order, magnitudes are saved LSB first. - for (int64_t i = (magnitude.size() - 1); i > 0; i--) { + for (int64_t i = (magnitude.size() - 1); i >= 0; i--) { if (magnitude[i] != num.magnitude[i]) { return magnitude[i] < num.magnitude[i]; } @@ -99,7 +99,7 @@ bool BigInt::operator>=(const BigInt& num) const { */ bool BigInt::operator==(const long long& num) const { - // Check if it is possible to efficiate the method, 99% of the time it will be efficiated + // Check if it is possible to optimize the method, 99% of the time it will be optimized if (sizeof(long long) == sizeof(uint64_t)) { if ((num < 0) != this->is_negative or this->magnitude.size() != 1) @@ -147,7 +147,7 @@ bool operator!=(const long long& lhs, const BigInt& rhs) { */ bool BigInt::operator<(const long long& num) const { - // Check if it is possible to efficiate the method + // Check if it is possible to optimize the method if (sizeof(long long) == sizeof(uint64_t)) { if (((num <= 0) and not this->is_negative) or this->magnitude.size() > 1) { From 17902e44ca676169aba37b0ae473fae43f8608eb Mon Sep 17 00:00:00 2001 From: Omri Date: Thu, 12 Apr 2018 15:29:42 +0300 Subject: [PATCH 6/7] Fixed uit64_t functionality --- include/BigInt.hpp | 38 +++---- include/constructors/constructors.hpp | 26 ++--- include/functions/conversion.hpp | 15 +-- include/functions/math.hpp | 10 +- include/functions/utility.hpp | 2 +- include/operators/arithmetic_assignment.hpp | 10 +- include/operators/assignment.hpp | 7 +- include/operators/binary_arithmetic.hpp | 25 +++-- include/operators/relational.hpp | 110 +++++++++----------- include/operators/unary_arithmetic.hpp | 4 +- 10 files changed, 107 insertions(+), 140 deletions(-) diff --git a/include/BigInt.hpp b/include/BigInt.hpp index 35afbde..be1a348 100644 --- a/include/BigInt.hpp +++ b/include/BigInt.hpp @@ -9,7 +9,7 @@ #define BIG_INT_HPP #include -#include +#include #include class BigInt { @@ -20,12 +20,12 @@ class BigInt { // Constructors: BigInt(); BigInt(const BigInt&); - BigInt(const long long&); + BigInt(const int64_t&); BigInt(const std::string&); // Assignment operators: BigInt& operator=(const BigInt&); - BigInt& operator=(const long long&); + BigInt& operator=(const int64_t&); BigInt& operator=(const std::string&); // Unary arithmetic operators: @@ -38,11 +38,11 @@ class BigInt { BigInt operator*(const BigInt&) const; BigInt operator/(const BigInt&) const; BigInt operator%(const BigInt&) const; - BigInt operator+(const long long&) const; - BigInt operator-(const long long&) const; - BigInt operator*(const long long&) const; - BigInt operator/(const long long&) const; - BigInt operator%(const long long&) const; + BigInt operator+(const int64_t&) const; + BigInt operator-(const int64_t&) const; + BigInt operator*(const int64_t&) const; + BigInt operator/(const int64_t&) const; + BigInt operator%(const int64_t&) const; BigInt operator+(const std::string&) const; BigInt operator-(const std::string&) const; BigInt operator*(const std::string&) const; @@ -55,11 +55,11 @@ class BigInt { BigInt& operator*=(const BigInt&); BigInt& operator/=(const BigInt&); BigInt& operator%=(const BigInt&); - BigInt& operator+=(const long long&); - BigInt& operator-=(const long long&); - BigInt& operator*=(const long long&); - BigInt& operator/=(const long long&); - BigInt& operator%=(const long long&); + BigInt& operator+=(const int64_t&); + BigInt& operator-=(const int64_t&); + BigInt& operator*=(const int64_t&); + BigInt& operator/=(const int64_t&); + BigInt& operator%=(const int64_t&); BigInt& operator+=(const std::string&); BigInt& operator-=(const std::string&); BigInt& operator*=(const std::string&); @@ -79,12 +79,12 @@ class BigInt { bool operator>=(const BigInt&) const; bool operator==(const BigInt&) const; bool operator!=(const BigInt&) const; - bool operator<(const long long&) const; - bool operator>(const long long&) const; - bool operator<=(const long long&) const; - bool operator>=(const long long&) const; - bool operator==(const long long&) const; - bool operator!=(const long long&) const; + bool operator<(const int64_t&) const; + bool operator>(const int64_t&) const; + bool operator<=(const int64_t&) const; + bool operator>=(const int64_t&) const; + bool operator==(const int64_t&) const; + bool operator!=(const int64_t&) const; bool operator<(const std::string&) const; bool operator>(const std::string&) const; bool operator<=(const std::string&) const; diff --git a/include/constructors/constructors.hpp b/include/constructors/constructors.hpp index 156a7f9..59be1b0 100644 --- a/include/constructors/constructors.hpp +++ b/include/constructors/constructors.hpp @@ -16,10 +16,9 @@ ------------------- */ -BigInt::BigInt() - : magnitude(1,0) - , is_negative(false) - { } +BigInt::BigInt(): + magnitude(1,0), + is_negative(false) { } /* @@ -27,10 +26,9 @@ BigInt::BigInt() ---------------- */ -BigInt::BigInt(const BigInt& num) - : magnitude(num.magnitude) - , is_negative(num.is_negative) - { } +BigInt::BigInt(const BigInt& num) : + magnitude(num.magnitude), + is_negative(num.is_negative) { } /* @@ -38,16 +36,8 @@ BigInt::BigInt(const BigInt& num) ----------------- */ -BigInt::BigInt(const long long& num) { - if (sizeof(long long) == (sizeof(uint64_t))) - magnitude = { (uint64_t) llabs(num) }; - - // If size not equal, long long will be bigger - else { - magnitude.push_back((uint64_t)llabs((uint64_t)num)); - if (num / UINT64_MAX > 0) - magnitude.push_back((uint64_t)llabs(num / UINT64_MAX)); - } +BigInt::BigInt(const int64_t& num) { + magnitude = { (uint64_t) llabs(num) }; is_negative = num < 0; } diff --git a/include/functions/conversion.hpp b/include/functions/conversion.hpp index b5b7c58..db9db14 100644 --- a/include/functions/conversion.hpp +++ b/include/functions/conversion.hpp @@ -15,16 +15,11 @@ */ std::string BigInt::to_string() const { - - std::string num_string; - - for (uint64_t ull : this->magnitude) - while (ull > 0) { - num_string += ((ull % 10) + '0'); - ull /= 10; - } - - return this->is_negative ? "-" + num_string : num_string; + /* + TODO + ---- + Convert to string + */ } diff --git a/include/functions/math.hpp b/include/functions/math.hpp index 9dee74e..ac8d25c 100644 --- a/include/functions/math.hpp +++ b/include/functions/math.hpp @@ -71,7 +71,7 @@ BigInt pow(const BigInt& base, int exp) { Returns a BigInt equal to base^exp. */ -BigInt pow(const long long& base, int exp) { +BigInt pow(const int64_t& base, int exp) { return pow(BigInt(base), exp); } @@ -159,7 +159,7 @@ BigInt gcd(const BigInt &num1, const BigInt &num2){ -------------------- */ -BigInt gcd(const BigInt& num1, const long long& num2){ +BigInt gcd(const BigInt& num1, const int64_t& num2){ return gcd(num1, BigInt(num2)); } @@ -179,7 +179,7 @@ BigInt gcd(const BigInt& num1, const std::string& num2){ -------------------- */ -BigInt gcd(const long long& num1, const BigInt& num2){ +BigInt gcd(const int64_t& num1, const BigInt& num2){ return gcd(BigInt(num1), num2); } @@ -213,7 +213,7 @@ BigInt lcm(const BigInt& num1, const BigInt& num2) { -------------------- */ -BigInt lcm(const BigInt& num1, const long long& num2){ +BigInt lcm(const BigInt& num1, const int64_t& num2){ return lcm(num1, BigInt(num2)); } @@ -233,7 +233,7 @@ BigInt lcm(const BigInt& num1, const std::string& num2){ -------------------- */ -BigInt lcm(const long long& num1, const BigInt& num2){ +BigInt lcm(const int64_t& num1, const BigInt& num2){ return lcm(BigInt(num1), num2); } diff --git a/include/functions/utility.hpp b/include/functions/utility.hpp index dc67795..e294578 100644 --- a/include/functions/utility.hpp +++ b/include/functions/utility.hpp @@ -8,7 +8,7 @@ #define BIG_INT_UTILITY_FUNCTIONS_HPP #include -#include +#include #include diff --git a/include/operators/arithmetic_assignment.hpp b/include/operators/arithmetic_assignment.hpp index 7d56b57..5bf6fb3 100644 --- a/include/operators/arithmetic_assignment.hpp +++ b/include/operators/arithmetic_assignment.hpp @@ -78,7 +78,7 @@ BigInt& BigInt::operator%=(const BigInt& num) { ----------------- */ -BigInt& BigInt::operator+=(const long long& num) { +BigInt& BigInt::operator+=(const int64_t& num) { *this = *this + BigInt(num); return *this; @@ -90,7 +90,7 @@ BigInt& BigInt::operator+=(const long long& num) { ----------------- */ -BigInt& BigInt::operator-=(const long long& num) { +BigInt& BigInt::operator-=(const int64_t& num) { *this = *this - BigInt(num); return *this; @@ -102,7 +102,7 @@ BigInt& BigInt::operator-=(const long long& num) { ----------------- */ -BigInt& BigInt::operator*=(const long long& num) { +BigInt& BigInt::operator*=(const int64_t& num) { *this = *this * BigInt(num); return *this; @@ -114,7 +114,7 @@ BigInt& BigInt::operator*=(const long long& num) { ----------------- */ -BigInt& BigInt::operator/=(const long long& num) { +BigInt& BigInt::operator/=(const int64_t& num) { *this = *this / BigInt(num); return *this; @@ -126,7 +126,7 @@ BigInt& BigInt::operator/=(const long long& num) { ----------------- */ -BigInt& BigInt::operator%=(const long long& num) { +BigInt& BigInt::operator%=(const int64_t& num) { *this = *this % BigInt(num); return *this; diff --git a/include/operators/assignment.hpp b/include/operators/assignment.hpp index 15791d8..de91629 100644 --- a/include/operators/assignment.hpp +++ b/include/operators/assignment.hpp @@ -29,10 +29,9 @@ BigInt& BigInt::operator=(const BigInt& num) { ---------------- */ -BigInt& BigInt::operator=(const long long& num) { - BigInt temp(num); - magnitude = temp.magnitude; - is_negative = temp.is_negative; +BigInt& BigInt::operator=(const int64_t& num) { + magnitude = { (uint64_t) llabs(num) }; + is_negative = (num < 0); return *this; } diff --git a/include/operators/binary_arithmetic.hpp b/include/operators/binary_arithmetic.hpp index b9e0efe..ba5fb35 100644 --- a/include/operators/binary_arithmetic.hpp +++ b/include/operators/binary_arithmetic.hpp @@ -9,7 +9,6 @@ #include #include -#include #include #include "BigInt.hpp" @@ -119,7 +118,7 @@ BigInt BigInt::operator-(const BigInt& num) const { if (larger[i] >= smaller[i]) difference = larger[i] - smaller[i]; else { - difference = std::numeric_limits::max() - smaller[i] + 1 + larger[i]; + difference = UINT64_MAX - smaller[i] + 1 + larger[i]; for (j = i + 1; j < larger.size(); j++) if (larger[j] != 0) { larger[j]--; // Borrow from the j-th digit @@ -128,7 +127,7 @@ BigInt BigInt::operator-(const BigInt& num) const { j--; while (j != i) { // Add the borrow and take one - larger[j] = std::numeric_limits::max(); + larger[j] = UINT64_MAX; // Walk back to i j--; } @@ -359,7 +358,7 @@ BigInt BigInt::operator%(const BigInt& num) const { ---------------- */ -BigInt BigInt::operator+(const long long& num) const { +BigInt BigInt::operator+(const int64_t& num) const { return *this + BigInt(num); } @@ -369,7 +368,7 @@ BigInt BigInt::operator+(const long long& num) const { ---------------- */ -BigInt operator+(const long long& lhs, const BigInt& rhs) { +BigInt operator+(const int64_t& lhs, const BigInt& rhs) { return BigInt(lhs) + rhs; } @@ -379,7 +378,7 @@ BigInt operator+(const long long& lhs, const BigInt& rhs) { ---------------- */ -BigInt BigInt::operator-(const long long& num) const { +BigInt BigInt::operator-(const int64_t& num) const { return *this - BigInt(num); } @@ -389,7 +388,7 @@ BigInt BigInt::operator-(const long long& num) const { ---------------- */ -BigInt operator-(const long long& lhs, const BigInt& rhs) { +BigInt operator-(const int64_t& lhs, const BigInt& rhs) { return BigInt(lhs) - rhs; } @@ -399,7 +398,7 @@ BigInt operator-(const long long& lhs, const BigInt& rhs) { ---------------- */ -BigInt BigInt::operator*(const long long& num) const { +BigInt BigInt::operator*(const int64_t& num) const { return *this * BigInt(num); } @@ -409,7 +408,7 @@ BigInt BigInt::operator*(const long long& num) const { ---------------- */ -BigInt operator*(const long long& lhs, const BigInt& rhs) { +BigInt operator*(const int64_t& lhs, const BigInt& rhs) { return BigInt(lhs) * rhs; } @@ -419,7 +418,7 @@ BigInt operator*(const long long& lhs, const BigInt& rhs) { ---------------- */ -BigInt BigInt::operator/(const long long& num) const { +BigInt BigInt::operator/(const int64_t& num) const { return *this / BigInt(num); } @@ -429,7 +428,7 @@ BigInt BigInt::operator/(const long long& num) const { ---------------- */ -BigInt operator/(const long long& lhs, const BigInt& rhs) { +BigInt operator/(const int64_t& lhs, const BigInt& rhs) { return BigInt(lhs) / rhs; } @@ -439,7 +438,7 @@ BigInt operator/(const long long& lhs, const BigInt& rhs) { ---------------- */ -BigInt BigInt::operator%(const long long& num) const { +BigInt BigInt::operator%(const int64_t& num) const { return *this % BigInt(num); } @@ -449,7 +448,7 @@ BigInt BigInt::operator%(const long long& num) const { ---------------- */ -BigInt operator%(const long long& lhs, const BigInt& rhs) { +BigInt operator%(const int64_t& lhs, const BigInt& rhs) { return BigInt(lhs) % rhs; } diff --git a/include/operators/relational.hpp b/include/operators/relational.hpp index af6d8fb..dbb824f 100644 --- a/include/operators/relational.hpp +++ b/include/operators/relational.hpp @@ -39,27 +39,21 @@ bool BigInt::operator!=(const BigInt& num) const { bool BigInt::operator<(const BigInt& num) const { - if (is_negative == num.is_negative) { - if (not is_negative) { - if (magnitude.size() == num.magnitude.size()) { - // Check in reverse order, magnitudes are saved LSB first. - for (int64_t i = (magnitude.size() - 1); i >= 0; i--) { - if (magnitude[i] != num.magnitude[i]) { - return magnitude[i] < num.magnitude[i]; - } - } - // Values equal - return true; - } - else { - return magnitude.size() < num.magnitude.size(); - } - } - else - return -(*this) > -num; - } - else + if (is_negative == num.is_negative) // Signs are opposite return is_negative; + if (is_negative) // Both numbers are negative + return -(*this) > -num; + + if (magnitude.size() != num.magnitude.size()) + return magnitude.size() < num.magnitude.size(); + + // Compare their digits from MSB to LSB + for (int64_t i = magnitude.size() - 1; i >= 0; i--) + if (magnitude[i] != num.magnitude[i]) + return magnitude[i] < num.magnitude[i]; + + // Both numbers are equal + return false; } @@ -69,7 +63,7 @@ bool BigInt::operator<(const BigInt& num) const { */ bool BigInt::operator>(const BigInt& num) const { - return !((*this < num) or (*this == num)); + return num < *this; } @@ -79,7 +73,7 @@ bool BigInt::operator>(const BigInt& num) const { */ bool BigInt::operator<=(const BigInt& num) const { - return (*this < num) or (*this == num); + return !(*this > num); } @@ -98,16 +92,12 @@ bool BigInt::operator>=(const BigInt& num) const { ----------------- */ -bool BigInt::operator==(const long long& num) const { - // Check if it is possible to optimize the method, 99% of the time it will be optimized - if (sizeof(long long) == sizeof(uint64_t)) { - if ((num < 0) != this->is_negative or - this->magnitude.size() != 1) - return false; - - return this->magnitude[0] == (uint64_t)llabs(num); - } - return *this == BigInt(num); +bool BigInt::operator==(const int64_t& num) const { + bool num_is_negative = (num < 0); + + return is_negative == num_is_negative + and magnitude.size() == 1 + and magnitude[0] == (uint64_t)llabs(num); } @@ -116,7 +106,7 @@ bool BigInt::operator==(const long long& num) const { ----------------- */ -bool operator==(const long long& lhs, const BigInt& rhs) { +bool operator==(const int64_t& lhs, const BigInt& rhs) { return rhs == lhs; } @@ -126,7 +116,7 @@ bool operator==(const long long& lhs, const BigInt& rhs) { ----------------- */ -bool BigInt::operator!=(const long long& num) const { +bool BigInt::operator!=(const int64_t& num) const { return !(*this == num); } @@ -136,7 +126,7 @@ bool BigInt::operator!=(const long long& num) const { ----------------- */ -bool operator!=(const long long& lhs, const BigInt& rhs) { +bool operator!=(const int64_t& lhs, const BigInt& rhs) { return !(rhs == lhs); } @@ -146,23 +136,17 @@ bool operator!=(const long long& lhs, const BigInt& rhs) { ---------------- */ -bool BigInt::operator<(const long long& num) const { - // Check if it is possible to optimize the method - if (sizeof(long long) == sizeof(uint64_t)) { - if (((num <= 0) and not this->is_negative) or - this->magnitude.size() > 1) { - return false; - } - if (num >= 0 and this->is_negative) { - return true; - } - if (num > 0) { - return this->magnitude[0] < (uint64_t)num; - } - return this->magnitude[0] > (uint64_t)num; - } +bool BigInt::operator<(const int64_t& num) const { + bool num_is_negative = (num < 0); - return *this < BigInt(num); + if (is_negative != num_is_negative) // Signs are opposite + return is_negative; + + if (is_negative) // Both numbers are negative + return -(this) > -num; + + // Both numbers are positive + return magnitude.size() == 1 and magnitude[0] < num; } @@ -171,8 +155,8 @@ bool BigInt::operator<(const long long& num) const { ---------------- */ -bool operator<(const long long& lhs, const BigInt& rhs) { - return rhs < lhs; +bool operator<(const int64_t& lhs, const BigInt& rhs) { + return rhs > lhs; } @@ -181,8 +165,8 @@ bool operator<(const long long& lhs, const BigInt& rhs) { ---------------- */ -bool BigInt::operator>(const long long& num) const { - return !((*this < num) or (*this == num)); +bool BigInt::operator>(const int64_t& num) const { + return !(*this < num or *this == num); } @@ -191,8 +175,8 @@ bool BigInt::operator>(const long long& num) const { ---------------- */ -bool operator>(const long long& lhs, const BigInt& rhs) { - return rhs > lhs; +bool operator>(const int64_t& lhs, const BigInt& rhs) { + return rhs < lhs; } @@ -201,7 +185,7 @@ bool operator>(const long long& lhs, const BigInt& rhs) { ----------------- */ -bool BigInt::operator<=(const long long& num) const { +bool BigInt::operator<=(const int64_t& num) const { return !(*this > num); } @@ -211,8 +195,8 @@ bool BigInt::operator<=(const long long& num) const { ----------------- */ -bool operator<=(const long long& lhs, const BigInt& rhs) { - return !(rhs > lhs); +bool operator<=(const int64_t& lhs, const BigInt& rhs) { + return !(rhs < lhs); } @@ -221,7 +205,7 @@ bool operator<=(const long long& lhs, const BigInt& rhs) { ----------------- */ -bool BigInt::operator>=(const long long& num) const { +bool BigInt::operator>=(const int64_t& num) const { return !(*this < num); } @@ -231,8 +215,8 @@ bool BigInt::operator>=(const long long& num) const { ----------------- */ -bool operator>=(const long long& lhs, const BigInt& rhs) { - return !(rhs < lhs); +bool operator>=(const int64_t& lhs, const BigInt& rhs) { + return !(rhs > lhs); } diff --git a/include/operators/unary_arithmetic.hpp b/include/operators/unary_arithmetic.hpp index 03aa492..a2b9ba7 100644 --- a/include/operators/unary_arithmetic.hpp +++ b/include/operators/unary_arithmetic.hpp @@ -34,8 +34,8 @@ BigInt BigInt::operator-() const { BigInt temp; temp.magnitude = magnitude; - // If magnitude is not 0 - if (magnitude.size() != 1 and magnitude[0] != 0) + + if (magnitude != { 0 }) temp.is_negative = not is_negative; return temp; From 8401447e96aa20ef75c726221073f1050825acfa Mon Sep 17 00:00:00 2001 From: Omri Date: Thu, 12 Apr 2018 16:48:29 +0300 Subject: [PATCH 7/7] Fixed uit64_t functionality --- include/functions/conversion.hpp | 1 + include/functions/utility.hpp | 20 +++++++------------- include/operators/binary_arithmetic.hpp | 17 ++++++++++++++--- include/operators/relational.hpp | 4 ++-- include/operators/unary_arithmetic.hpp | 5 +++-- 5 files changed, 27 insertions(+), 20 deletions(-) diff --git a/include/functions/conversion.hpp b/include/functions/conversion.hpp index db9db14..3380864 100644 --- a/include/functions/conversion.hpp +++ b/include/functions/conversion.hpp @@ -20,6 +20,7 @@ std::string BigInt::to_string() const { ---- Convert to string */ + return ""; } diff --git a/include/functions/utility.hpp b/include/functions/utility.hpp index e294578..f905909 100644 --- a/include/functions/utility.hpp +++ b/include/functions/utility.hpp @@ -134,26 +134,20 @@ void add_leading_zeroes(std::vector& num, size_t num_zeroes) { */ void add_trailing_zeroes(std::vector& num, size_t num_zeroes) { - std::vector tmp(num_zeroes, 0); - num.insert(num.end(), tmp.begin(), tmp.end()); + for (size_t i = 0; i < num_zeroes; i++) + num.push_back(0); } /* - strip_leading_zeroes + strip_trailing_zeroes -------------------- - Strip the leading zeroes from a number represented as a vector. + Strip the trailing zeroes from a number represented as a vector. */ void strip_trailing_zeroes(std::vector& num) { - for (auto digit_itter = num.rbegin(); digit_itter != num.rend(); digit_itter++) - if (*digit_itter != 0) { - num = std::vector(num.rend(), digit_itter + 1); - return; - } - - // If all 0's - num.clear(); - num.push_back(0); + // Do not strip the last zero if num is all zeros + while (num.size() > 1 and num[num.size() - 1] == 0) + num.pop_back(); } /* diff --git a/include/operators/binary_arithmetic.hpp b/include/operators/binary_arithmetic.hpp index ba5fb35..b7eeabf 100644 --- a/include/operators/binary_arithmetic.hpp +++ b/include/operators/binary_arithmetic.hpp @@ -46,6 +46,9 @@ BigInt BigInt::operator+(const BigInt& num) const { BigInt result; int carry = 0; + // Reset results magnitude + result.magnitude = std::vector(); + std::vector larger, smaller; std::tie(larger, smaller) = get_larger_and_smaller(this->magnitude, num.magnitude); @@ -65,6 +68,10 @@ BigInt BigInt::operator+(const BigInt& num) const { carry = 0; } + if (carry == 1) { + result.magnitude.push_back(1); + } + return result; } @@ -90,6 +97,9 @@ BigInt BigInt::operator-(const BigInt& num) const { // The resultant difference BigInt result; + // Reset results magnitude + result.magnitude = std::vector(); + // Identify the numbers as `larger` and `smaller` std::vector larger, smaller; @@ -118,7 +128,9 @@ BigInt BigInt::operator-(const BigInt& num) const { if (larger[i] >= smaller[i]) difference = larger[i] - smaller[i]; else { - difference = UINT64_MAX - smaller[i] + 1 + larger[i]; + // When carrying: difference = (UINT64_MAX + 1 + larger[i]) - smaller[i] + // Write like this to avoid overflow + difference = UINT64_MAX - (smaller[i] - larger[i]) + 1; for (j = i + 1; j < larger.size(); j++) if (larger[j] != 0) { larger[j]--; // Borrow from the j-th digit @@ -138,8 +150,7 @@ BigInt BigInt::operator-(const BigInt& num) const { strip_trailing_zeroes(result.magnitude); // if the result is 0, set its sign as + - if ((result.magnitude.size() == 1 and result.magnitude[0] == 0) or - result.magnitude.size() == 0) + if (result.magnitude.size() == 1 and result.magnitude[0] == 0) result.is_negative = false; return result; diff --git a/include/operators/relational.hpp b/include/operators/relational.hpp index dbb824f..6f4951d 100644 --- a/include/operators/relational.hpp +++ b/include/operators/relational.hpp @@ -143,10 +143,10 @@ bool BigInt::operator<(const int64_t& num) const { return is_negative; if (is_negative) // Both numbers are negative - return -(this) > -num; + return -(*this) > -num; // Both numbers are positive - return magnitude.size() == 1 and magnitude[0] < num; + return magnitude.size() == 1 and magnitude[0] < (uint64_t)num; } diff --git a/include/operators/unary_arithmetic.hpp b/include/operators/unary_arithmetic.hpp index a2b9ba7..182b018 100644 --- a/include/operators/unary_arithmetic.hpp +++ b/include/operators/unary_arithmetic.hpp @@ -34,8 +34,9 @@ BigInt BigInt::operator-() const { BigInt temp; temp.magnitude = magnitude; - - if (magnitude != { 0 }) + + // If magnitude is not 0 + if (magnitude.size() != 1 and magnitude[0] != 0) temp.is_negative = not is_negative; return temp;