From 64e5f87a52510f87cc1fa9f724715c3545ac3ebf Mon Sep 17 00:00:00 2001 From: SamHerts Date: Thu, 12 Mar 2026 15:59:30 -0400 Subject: [PATCH 1/7] Reduce `MAX_SIZE` and chunk size limits in `bigint` for improved compatibility. --- bigint.h | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/bigint.h b/bigint.h index 43725b3..c854c56 100644 --- a/bigint.h +++ b/bigint.h @@ -45,7 +45,7 @@ namespace BigInt { { public: // LLONG_MAX = 9'223'372'036'854'775'807 - static constexpr auto MAX_SIZE = 1'000'000'000'000'000'000LL; + static constexpr auto MAX_SIZE = 1'000'000'000LL; bigint() : vec({0}) {} @@ -591,8 +591,7 @@ namespace BigInt { for (auto it_lhs = lhs.vec.rbegin(); it_lhs != lhs.vec.rend(); ++it_lhs) { for (auto it_rhs = rhs.vec.rbegin(); it_rhs != rhs.vec.rend(); ++it_rhs) { // Calculate the product and the corresponding indices in the result vector - // use 128 bits to carefully store overflow - __int128 mul = static_cast<__int128>(*it_lhs) * static_cast<__int128>(*it_rhs); + long long mul = (*it_lhs) * (*it_rhs); auto pos_low_it = result.rbegin() + (std::distance(lhs.vec.rbegin(), it_lhs) + std::distance( rhs.vec.rbegin(), it_rhs)); auto pos_high_it = pos_low_it + 1; @@ -847,14 +846,16 @@ namespace BigInt { } inline std::vector bigint::string_to_vector(std::string input) { - // Break into chunks of 18 characters + // Break into chunks of 9 characters std::vector result; - constexpr int chunk_size = 18; + constexpr int chunk_size = 9; const int size = input.size(); if (size > chunk_size) { // Pad the length to get appropriate sized chunks - input.insert(0, chunk_size - (size % chunk_size), '0'); + if (int mod = size % chunk_size; mod != 0) { + input.insert(0, chunk_size - mod, '0'); + } } for (int i = 0; i < input.size(); i += chunk_size) { std::string temp_str = input.substr(i, chunk_size); @@ -878,8 +879,8 @@ namespace BigInt { else throw std::runtime_error("Invalid hex character."); // Multiply current value by 16 and add digit. - // Max intermediate value: (MAX_SIZE-1)*16+15 = 15,999,999,999,999,999,999 - // which fits in unsigned long long (max ~18.4 * 10^18). + // Max intermediate value: (MAX_SIZE-1)*16+15 = 15,999,999,999 + // which fits in unsigned long long. unsigned long long carry = digit; for (int i = static_cast(result.size()) - 1; i >= 0; --i) { const unsigned long long val = static_cast(result[i]) * 16 + carry; @@ -905,7 +906,7 @@ namespace BigInt { first = false; } else { - ss << std::setw(18) << std::setfill('0') << partial; // Pad to 18 digits + ss << std::setw(9) << std::setfill('0') << partial; // Pad to 9 digits } } return ss.str(); From a6f5aa421f61924131f2c78c549250e93e27d74d Mon Sep 17 00:00:00 2001 From: SamHerts Date: Fri, 13 Mar 2026 12:16:30 -0400 Subject: [PATCH 2/7] Update CI/CD workflow to use Clang 18 instead of Clang 17 --- .github/workflows/CI-CD.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/CI-CD.yml b/.github/workflows/CI-CD.yml index 76112d3..80293a4 100644 --- a/.github/workflows/CI-CD.yml +++ b/.github/workflows/CI-CD.yml @@ -40,13 +40,13 @@ jobs: echo "CXX=g++-13" >> $GITHUB_ENV echo "CC=gcc-13" >> $GITHUB_ENV - - name: Set up Clang 17 + - name: Set up Clang 18 if: matrix.compiler == 'clang' run: | sudo apt-get update - sudo apt-get install -y clang-17 - echo "CXX=clang++-17" >> $GITHUB_ENV - echo "CC=clang-17" >> $GITHUB_ENV + sudo apt-get install -y clang-18 + echo "CXX=clang++-18" >> $GITHUB_ENV + echo "CC=clang-18" >> $GITHUB_ENV - name: Configure CMake shell: bash From 9f7b009a3b6c125d88e78f2b3fbd34cb4246e722 Mon Sep 17 00:00:00 2001 From: SamHerts Date: Fri, 13 Mar 2026 12:48:55 -0400 Subject: [PATCH 3/7] Remove digit separator for consistency --- bigint.h | 2 +- tests/test.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bigint.h b/bigint.h index c854c56..67c3a6c 100644 --- a/bigint.h +++ b/bigint.h @@ -45,7 +45,7 @@ namespace BigInt { { public: // LLONG_MAX = 9'223'372'036'854'775'807 - static constexpr auto MAX_SIZE = 1'000'000'000LL; + static constexpr auto MAX_SIZE = 1000000000LL; bigint() : vec({0}) {} diff --git a/tests/test.cpp b/tests/test.cpp index 2d86402..1b660fc 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -74,8 +74,8 @@ static auto measure_execution = [](const int count, const char* label, const siz class Test_BigInt_Performance : public ::testing::Test { protected: - static constexpr size_t number_count = 500; - const std::vector sizes = {5, 20, 50, 100, 1000, 10'000, 100'000, 1'000'000}; + static constexpr size_t number_count = 2; + const std::vector sizes = {10, 100, 1000, 10000, 50000}; volatile int dce_sink = 0; void SetUp() override { From 94049032b56c28d409196a24052a87a20fac24d7 Mon Sep 17 00:00:00 2001 From: SamHerts Date: Fri, 13 Mar 2026 12:54:19 -0400 Subject: [PATCH 4/7] Forward declare comparison operators to `bigint` namespace --- bigint.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/bigint.h b/bigint.h index 67c3a6c..72a8d5e 100644 --- a/bigint.h +++ b/bigint.h @@ -41,6 +41,15 @@ #include namespace BigInt { + class bigint; + + bool operator==(const bigint& l, const bigint& r); + bool operator!=(const bigint& l, const bigint& r); + bool operator<(const bigint& lhs, const bigint& rhs); + bool operator>(const bigint& l, const bigint& r); + bool operator<=(const bigint& l, const bigint& r); + bool operator>=(const bigint& l, const bigint& r); + class bigint { public: @@ -704,7 +713,6 @@ namespace BigInt { return answer; } - inline bigint bigint::log2(const bigint& input) { if (is_negative(input) || input == 0) throw std::domain_error("Invalid input for natural log"); From 2631e578d531db3a13b4e9ded06aa1164eed06a2 Mon Sep 17 00:00:00 2001 From: SamHerts Date: Fri, 13 Mar 2026 13:46:53 -0400 Subject: [PATCH 5/7] Move comparison operator implementations to `bigint` namespace --- bigint.h | 54 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/bigint.h b/bigint.h index 72a8d5e..6806f7c 100644 --- a/bigint.h +++ b/bigint.h @@ -261,32 +261,17 @@ namespace BigInt { return *this; } - friend bool operator==(const bigint& l, const bigint& r) { - if (l.is_neg != r.is_neg) { - return false; - } - return l.vec == r.vec; - } + friend bool operator==(const bigint& l, const bigint& r); - friend bool operator!=(const bigint& l, const bigint& r) { - return !(l == r); - } + friend bool operator!=(const bigint& l, const bigint& r); - friend bool operator<(const bigint& lhs, const bigint& rhs) { - return less_than(lhs, rhs); - } + friend bool operator<(const bigint& lhs, const bigint& rhs); - friend bool operator>(const bigint& l, const bigint& r) { - return r < l; - } + friend bool operator>(const bigint& l, const bigint& r); - friend bool operator<=(const bigint& l, const bigint& r) { - return r >= l; - } + friend bool operator<=(const bigint& l, const bigint& r); - friend bool operator>=(const bigint& l, const bigint& r) { - return !(l < r); - } + friend bool operator>=(const bigint& l, const bigint& r); explicit operator bool() const { return !(vec.size() == 1 && vec.front() == 0); @@ -463,6 +448,33 @@ namespace BigInt { } }; + inline bool operator==(const bigint& l, const bigint& r) { + if (l.is_neg != r.is_neg) { + return false; + } + return l.vec == r.vec; + } + + inline bool operator!=(const bigint& l, const bigint& r) { + return !(l == r); + } + + inline bool operator<(const bigint& lhs, const bigint& rhs) { + return bigint::less_than(lhs, rhs); + } + + inline bool operator>(const bigint& l, const bigint& r) { + return r < l; + } + + inline bool operator<=(const bigint& l, const bigint& r) { + return r >= l; + } + + inline bool operator>=(const bigint& l, const bigint& r) { + return !(l < r); + } + inline bool bigint::is_bigint(const std::string& s) { if (s.empty()) From caf308887a968859f6b3c8112f6d576038ed2c4e Mon Sep 17 00:00:00 2001 From: SamHerts Date: Fri, 13 Mar 2026 14:01:31 -0400 Subject: [PATCH 6/7] Refactor `bigint` constructors for improved type handling and consistency --- bigint.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/bigint.h b/bigint.h index 6806f7c..b4dbacf 100644 --- a/bigint.h +++ b/bigint.h @@ -86,13 +86,13 @@ namespace BigInt { } } - bigint(const unsigned int n) : bigint(static_cast(n)) {} - - bigint(const int n) : bigint(static_cast(n)) {} - - bigint(const long n) : bigint(static_cast(n)) {} + bigint(const char* n) : bigint(std::string(n)) {} - bigint(const double n) : bigint(static_cast(n)) {} + bigint(const int n) : bigint(static_cast(n)) {} + bigint(const unsigned int n) : bigint(static_cast(n)) {} + bigint(const long n) : bigint(static_cast(n)) {} + bigint(const unsigned long n) : bigint(static_cast(n)) {} + bigint(const double n) : bigint(static_cast(n)) {} bigint(const long long n): is_neg(n < 0) { if (n == 0) { @@ -125,8 +125,6 @@ namespace BigInt { bigint(const bigint& n) = default; - bigint(const char* n) : bigint(std::string(n)) {} - /* If initializing from a vector that should be negative, the negative value must be set afterward. * bigint alpha(std::vector(...)); * -alpha; From 21866d512ace8a7a329fda38531fdae02042ab43 Mon Sep 17 00:00:00 2001 From: SamHerts Date: Fri, 13 Mar 2026 14:12:47 -0400 Subject: [PATCH 7/7] Revert namespace declarations for comparison operators --- bigint.h | 68 ++++++++++++++++++-------------------------------------- 1 file changed, 22 insertions(+), 46 deletions(-) diff --git a/bigint.h b/bigint.h index b4dbacf..936be5f 100644 --- a/bigint.h +++ b/bigint.h @@ -41,15 +41,6 @@ #include namespace BigInt { - class bigint; - - bool operator==(const bigint& l, const bigint& r); - bool operator!=(const bigint& l, const bigint& r); - bool operator<(const bigint& lhs, const bigint& rhs); - bool operator>(const bigint& l, const bigint& r); - bool operator<=(const bigint& l, const bigint& r); - bool operator>=(const bigint& l, const bigint& r); - class bigint { public: @@ -259,17 +250,32 @@ namespace BigInt { return *this; } - friend bool operator==(const bigint& l, const bigint& r); + friend bool operator==(const bigint& l, const bigint& r) { + if (l.is_neg != r.is_neg) { + return false; + } + return l.vec == r.vec; + } - friend bool operator!=(const bigint& l, const bigint& r); + friend bool operator!=(const bigint& l, const bigint& r) { + return !(l == r); + } - friend bool operator<(const bigint& lhs, const bigint& rhs); + friend bool operator<(const bigint& lhs, const bigint& rhs) { + return less_than(lhs, rhs); + } - friend bool operator>(const bigint& l, const bigint& r); + friend bool operator>(const bigint& l, const bigint& r) { + return r < l; + } - friend bool operator<=(const bigint& l, const bigint& r); + friend bool operator<=(const bigint& l, const bigint& r) { + return r >= l; + } - friend bool operator>=(const bigint& l, const bigint& r); + friend bool operator>=(const bigint& l, const bigint& r) { + return !(l < r); + } explicit operator bool() const { return !(vec.size() == 1 && vec.front() == 0); @@ -363,9 +369,7 @@ namespace BigInt { bool is_neg{false}; std::vector vec; - // Function Definitions for Internal Uses - static bigint trim(bigint input) { while (input.vec.size() > 1 && input.vec.front() == 0) { input.vec.erase(input.vec.begin()); @@ -446,34 +450,6 @@ namespace BigInt { } }; - inline bool operator==(const bigint& l, const bigint& r) { - if (l.is_neg != r.is_neg) { - return false; - } - return l.vec == r.vec; - } - - inline bool operator!=(const bigint& l, const bigint& r) { - return !(l == r); - } - - inline bool operator<(const bigint& lhs, const bigint& rhs) { - return bigint::less_than(lhs, rhs); - } - - inline bool operator>(const bigint& l, const bigint& r) { - return r < l; - } - - inline bool operator<=(const bigint& l, const bigint& r) { - return r >= l; - } - - inline bool operator>=(const bigint& l, const bigint& r) { - return !(l < r); - } - - inline bool bigint::is_bigint(const std::string& s) { if (s.empty()) return false; @@ -939,7 +915,7 @@ namespace BigInt { template<> struct std::hash { - std::size_t operator()(const BigInt::bigint& input) const { + std::size_t operator()(const BigInt::bigint& input) const noexcept { std::size_t seed = input.vec.size(); for (auto x : input.vec) { x = ((x >> 16) ^ x) * 0x45d9f3b;