From e1c9275739584fcb353e7a17a5afb5e733389324 Mon Sep 17 00:00:00 2001 From: Hashir Hameed Niazi Date: Sat, 24 Oct 2020 16:39:30 +0530 Subject: [PATCH 1/7] Optimized multiplication operator (*) overload --- big-int/src/operators/multiply.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/big-int/src/operators/multiply.cpp b/big-int/src/operators/multiply.cpp index 2ade0f6..05d2b93 100644 --- a/big-int/src/operators/multiply.cpp +++ b/big-int/src/operators/multiply.cpp @@ -109,12 +109,12 @@ namespace libbig largeInt x2 = (f == x.number.length()) ? x:largeInt(x.number.substr(x.number.length() - f, x.number.length())); largeInt y2 = (f == y.number.length()) ? y:largeInt(y.number.substr(y.number.length() - f, y.number.length())); - const largeInt x3 = x1 + x2; - const largeInt y3 = y1 + y2; + largeInt x3 = x1 + x2; + largeInt y3 = y1 + y2; - largeInt x1y1 = simple_multiplication(x1, y1); - largeInt x2y2 = simple_multiplication(x2, y2); - largeInt x3y3 = simple_multiplication(x3, y3); + largeInt x1y1 = x1 * y1; + largeInt x2y2 = x2 * y2; + largeInt x3y3 = x3 * y3; largeInt xy = append_zeroes(x1y1, 2*f) + append_zeroes((x3y3 - x1y1 - x2y2), f) + x2y2; From c8bbeeb16a356c403772f9b7cf511ab126f7bfd9 Mon Sep 17 00:00:00 2001 From: Hashir Hameed Niazi Date: Sat, 24 Oct 2020 17:28:28 +0530 Subject: [PATCH 2/7] feat: Added more multiplication operator overloads --- big-int/src/operators/multiply.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/big-int/src/operators/multiply.cpp b/big-int/src/operators/multiply.cpp index 05d2b93..1e4f72f 100644 --- a/big-int/src/operators/multiply.cpp +++ b/big-int/src/operators/multiply.cpp @@ -124,5 +124,11 @@ namespace libbig return remove_zeroes(xy); } + largeInt largeInt::operator*(int next_number) { + return *this * largeInt(next_number); + } + largeInt largeInt::operator*(int64_t next_number) { + return *this * largeInt(std::to_string(next_number)); + } } // namespace libbig From 036e18b035ded6244111e9ea7509f7720aadc092 Mon Sep 17 00:00:00 2001 From: Hashir Hameed Niazi Date: Sat, 24 Oct 2020 18:07:05 +0530 Subject: [PATCH 3/7] test: Added tests for new multiplication overloads --- tests/operators/multiply_test.cpp | 128 ++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/tests/operators/multiply_test.cpp b/tests/operators/multiply_test.cpp index 672fcf6..aead563 100644 --- a/tests/operators/multiply_test.cpp +++ b/tests/operators/multiply_test.cpp @@ -71,5 +71,133 @@ int main() c = a * b; assert(c == libbig::largeInt("7000770444056069403046119404826740387252166452093943636486324185225836788920060077258109995450330997820727632474615791121779806923541276193853962113432983583426568371447855101334504301369704676060587738461922443343618487980096828486083202559107333726983966552151422667448209619250487990929538296732965889159956209059231075")); + /// Tests for multiplication of largeInt to largeInt (largeInt * int) + /// Test 1 + a = libbig::largeInt("1"); + int d { 1 }; + c = a * d; + assert(c == libbig::largeInt("1")); + + /// Test 2 + a = libbig::largeInt("999"); + d = 99999; + c = a * d; + assert(c == libbig::largeInt("99899001")); + + /// Test 3 + a = libbig::largeInt("32516889472103571029388908423975"); + d = 0; + c = a * d; + assert(c == libbig::largeInt("0")); + + /// Test 4 + a = libbig::largeInt("6666666666666"); + d = 2147000000; + c = a * d; + assert(c == libbig::largeInt("14313333333331902000000")); + + // Test 5 + a = libbig::largeInt("33"); + d = -2; + c = a * d; + assert(c == libbig::largeInt("-66")); + + // Test 6 + a = libbig::largeInt("-0"); + d = 100; + c = a * d; + assert(c == libbig::largeInt("0")); + + // Test 7 + a = libbig::largeInt("-100"); + d = -100; + c = a * d; + assert(c == libbig::largeInt("10000")); + + // Test 8 + a = libbig::largeInt("0000000000000000000000000000000000000000000000000000"); + d = 1111111111; + c = a * d; + assert(c == libbig::largeInt("0")); + + // Test 9 + a = libbig::largeInt("824358293475908745902350926589023459023485089347892650234650273456207349236502347524357832456789235623489759235623789456782394567892359478235239423569782356234659837562378965278956237489235"); + d = 2147111111; + c = a * d; + assert(c == libbig::largeInt("1769988851367122479149013395500437599508978045281688053754054359337011171465551557147132045207848595192391874649522705358582133685907728887725045238091914980923198260535639031943130151995891211390085")); + + // Test 10 + a = libbig::largeInt("824358293475908745902350926589023459023485089347892650234650273456207349236502347524357832456789235623489759235623789456782394567892359478235239423569782356234659837562378965278956237489235"); + d = -0; + c = a * d; + assert(c == libbig::largeInt("0")); + + /// Tests for multiplication of largeInt to largeInt (largeInt * int64_t(long long)) + /// Test 1 + a = libbig::largeInt("1"); + int64_t e { 1 }; + c = a * e; + assert(c == libbig::largeInt("1")); + + /// Test 2 + a = libbig::largeInt("999"); + e = 99999; + c = a * e; + assert(c == libbig::largeInt("99899001")); + + /// Test 3 + a = libbig::largeInt("32516889472103571029388908423975"); + e = 0; + c = a * e; + assert(c == libbig::largeInt("0")); + + /// Test 4 + a = libbig::largeInt("6666666666666"); + e = 2147000000; + c = a * e; + assert(c == libbig::largeInt("14313333333331902000000")); + + // Test 5 + a = libbig::largeInt("33"); + e = -2; + c = a * e; + assert(c == libbig::largeInt("-66")); + + // Test 6 + a = libbig::largeInt("-0"); + e = 100; + c = a * e; + assert(c == libbig::largeInt("0")); + + // Test 7 + a = libbig::largeInt("-100"); + e = -100; + c = a * e; + assert(c == libbig::largeInt("10000")); + + // Test 8 + a = libbig::largeInt("0000000000000000000000000000000000000000000000000000"); + e = 1111111111; + c = a * e; + assert(c == libbig::largeInt("0")); + + // Test 9 + a = libbig::largeInt("824358293475908745902350926589023459023485089347892650234650273456207349236502347524357832456789235623489759235623789456782394567892359478235239423569782356234659837562378965278956237489235"); + e = 2147111111; + c = a * e; + assert(c == libbig::largeInt("1769988851367122479149013395500437599508978045281688053754054359337011171465551557147132045207848595192391874649522705358582133685907728887725045238091914980923198260535639031943130151995891211390085")); + + // Test 10 + a = libbig::largeInt("824358293475908745902350926589023459023485089347892650234650273456207349236502347524357832456789235623489759235623789456782394567892359478235239423569782356234659837562378965278956237489235"); + e = -0; + c = a * e; + assert(c == libbig::largeInt("0")); + + // Test 1 + a = libbig::largeInt("824358293475908745902350926589023459023485089347892650234650273456207349236502347524357832456789235623489759235623789456782394567892359478235239423569782356234659837562378965278956237489235"); + e = 1265387145178649877; + c = a * e; + assert(c == libbig::largeInt("1043132387585823801991307287703268230197717355664659943770242721775843792669363443147242163866322648004732006134963833033002779153256893032797217422608922304113441680757314641399751543910917847399909621574095")); + return 0; } \ No newline at end of file From 420e3cbef756ca1d3047c723378abd01978bbdff Mon Sep 17 00:00:00 2001 From: Hashir Hameed Niazi Date: Mon, 26 Oct 2020 07:22:54 +0530 Subject: [PATCH 4/7] feat: Added Fast Fourier Transform Implementation --- big-int/src/bigint.hpp | 1 + big-int/src/helpers.cpp | 37 ++++++++++++++++++++++++++++++ big-int/src/operators/multiply.cpp | 1 + 3 files changed, 39 insertions(+) diff --git a/big-int/src/bigint.hpp b/big-int/src/bigint.hpp index ce47f57..b414dbc 100644 --- a/big-int/src/bigint.hpp +++ b/big-int/src/bigint.hpp @@ -37,6 +37,7 @@ namespace libbig // this->sign = POSITIVE; instead of this->sign = true; constexpr bool POSITIVE = true; constexpr bool NEGATIVE = false; +constexpr double PI = 2*acos(0.0); class largeInt { private: diff --git a/big-int/src/helpers.cpp b/big-int/src/helpers.cpp index 8399ad2..c6eb4c4 100644 --- a/big-int/src/helpers.cpp +++ b/big-int/src/helpers.cpp @@ -29,10 +29,47 @@ #include #include #include +#include +#include + +typedef std::vector> complexCoeffs; namespace libbig { int char_int_converter(const char &x) { return ((x >= '0' && x <= '9') ? x - '0' : x + '0') ; } + + complexCoeffs fast_fourier_transform(const complexCoeffs num) { + + const int len = num.size(); + const int half_len = len/2; + const double phase_angle = (2*PI)/len; + if(len == 1) { + return num; + } + std::complex w_n (1.0, phase_angle); + std::complex w (1, 0); + complexCoeffs even_coeffs; + complexCoeffs odd_coeffs; + for (int i = 0; i #include #include +#include namespace libbig { From dec077b13edd947580535cd6fda833721a3ac888 Mon Sep 17 00:00:00 2001 From: Hashir Hameed Niazi Date: Mon, 26 Oct 2020 07:47:38 +0530 Subject: [PATCH 5/7] feat: Added polynomial converter, removed Karatsuba Algo, configured FFT for IDFT --- big-int/src/bigint.hpp | 5 +++- big-int/src/helpers.cpp | 10 ++++---- big-int/src/operators/multiply.cpp | 38 +++++++++++------------------- 3 files changed, 24 insertions(+), 29 deletions(-) diff --git a/big-int/src/bigint.hpp b/big-int/src/bigint.hpp index b414dbc..77ebe83 100644 --- a/big-int/src/bigint.hpp +++ b/big-int/src/bigint.hpp @@ -30,6 +30,8 @@ #include #include +#include +#include namespace libbig { @@ -37,7 +39,8 @@ namespace libbig // this->sign = POSITIVE; instead of this->sign = true; constexpr bool POSITIVE = true; constexpr bool NEGATIVE = false; -constexpr double PI = 2*acos(0.0); +const double PI = 2*acos(0.0); +typedef std::vector> complexCoeffs; class largeInt { private: diff --git a/big-int/src/helpers.cpp b/big-int/src/helpers.cpp index c6eb4c4..90c0f70 100644 --- a/big-int/src/helpers.cpp +++ b/big-int/src/helpers.cpp @@ -32,19 +32,17 @@ #include #include -typedef std::vector> complexCoeffs; - namespace libbig { int char_int_converter(const char &x) { return ((x >= '0' && x <= '9') ? x - '0' : x + '0') ; } - complexCoeffs fast_fourier_transform(const complexCoeffs num) { + complexCoeffs fast_fourier_transform(const complexCoeffs num, const bool is_IDFT = false) { const int len = num.size(); const int half_len = len/2; - const double phase_angle = (2*PI)/len; + const double phase_angle = (is_IDFT) ? (-PI/half_len):(PI/half_len); if(len == 1) { return num; } @@ -68,6 +66,10 @@ namespace libbig for(int i = 0; i single(static_cast (factor*char_int_converter(num.number[i])), 0.0); + Answer.push_back(single); + factor *= 10; + ++i; + } + return Answer; + }; + largeInt x = *this; largeInt y = next_number; @@ -99,30 +113,6 @@ namespace libbig else if(x.number.length() == 1 || y.number.length() == 1) { return simple_multiplication(x, y); } - - const int lower = std::min(x.number.length(), y.number.length()); - const int higher = std::max(x.number.length(), y.number.length()); - - const int f = (higher >= 2*lower) ? lower:higher/2; - - largeInt x1 = (f == x.number.length()) ? largeInt():largeInt(x.number.substr(0, x.number.length() - f)); - largeInt y1 = (f == y.number.length()) ? largeInt():largeInt(y.number.substr(0, y.number.length() - f)); - largeInt x2 = (f == x.number.length()) ? x:largeInt(x.number.substr(x.number.length() - f, x.number.length())); - largeInt y2 = (f == y.number.length()) ? y:largeInt(y.number.substr(y.number.length() - f, y.number.length())); - - largeInt x3 = x1 + x2; - largeInt y3 = y1 + y2; - - largeInt x1y1 = x1 * y1; - largeInt x2y2 = x2 * y2; - largeInt x3y3 = x3 * y3; - - largeInt xy = append_zeroes(x1y1, 2*f) + append_zeroes((x3y3 - x1y1 - x2y2), f) + x2y2; - - if(x.sign != y.sign) - xy.sign = NEGATIVE; - - return remove_zeroes(xy); } largeInt largeInt::operator*(int next_number) { From 27e1e6f23793b8f373e475fe011fe327c5a240a3 Mon Sep 17 00:00:00 2001 From: Hashir Hameed Niazi Date: Mon, 26 Oct 2020 10:27:00 +0530 Subject: [PATCH 6/7] feat, fix:- Implemented Schonhage Starressen for in range integers and bug fixes --- big-int/src/bigint.hpp | 4 +++- big-int/src/helpers.cpp | 14 +++++++------- big-int/src/operators/multiply.cpp | 30 ++++++++++++++++++++++++++---- tests/operators/multiply_test.cpp | 10 +++++----- 4 files changed, 41 insertions(+), 17 deletions(-) diff --git a/big-int/src/bigint.hpp b/big-int/src/bigint.hpp index 77ebe83..4cb3859 100644 --- a/big-int/src/bigint.hpp +++ b/big-int/src/bigint.hpp @@ -129,7 +129,9 @@ class largeInt friend std::istream &operator>>(std::istream &, largeInt &); friend std::ostream &operator<<(std::ostream &, const largeInt &); }; -int char_int_converter(const char &x); +// HELPERS +int char_int_converter(const char&); +complexCoeffs fast_fourier_transform(const bool is_IDFT, const complexCoeffs); } // namespace libbig #endif \ No newline at end of file diff --git a/big-int/src/helpers.cpp b/big-int/src/helpers.cpp index 90c0f70..ca99d24 100644 --- a/big-int/src/helpers.cpp +++ b/big-int/src/helpers.cpp @@ -38,7 +38,7 @@ namespace libbig return ((x >= '0' && x <= '9') ? x - '0' : x + '0') ; } - complexCoeffs fast_fourier_transform(const complexCoeffs num, const bool is_IDFT = false) { + complexCoeffs fast_fourier_transform(const bool is_IDFT, const complexCoeffs num) { const int len = num.size(); const int half_len = len/2; @@ -52,23 +52,23 @@ namespace libbig complexCoeffs odd_coeffs; for (int i = 0; i single(static_cast (factor*char_int_converter(num.number[i])), 0.0); + int i = 1; + while (i != len+1) { + std::complex single(static_cast (factor*char_int_converter(num.number[len - i])), 0.0); Answer.push_back(single); factor *= 10; ++i; - } + std::cout<(std::abs(IDFT_xy[i])))); + Answer = Answer + single; + } + return Answer; } largeInt largeInt::operator*(int next_number) { diff --git a/tests/operators/multiply_test.cpp b/tests/operators/multiply_test.cpp index aead563..88000f5 100644 --- a/tests/operators/multiply_test.cpp +++ b/tests/operators/multiply_test.cpp @@ -6,16 +6,16 @@ int main() { /// Tests for multiplication of largeInt to largeInt (largeInt * largeInt) /// Test 1 - libbig::largeInt a("1"); + libbig::largeInt a("1111"); libbig::largeInt b("1"); libbig::largeInt c = a * b; - assert(c == libbig::largeInt("1")); + assert(c == libbig::largeInt("1111")); /// Test 2 - a = libbig::largeInt("999"); - b = libbig::largeInt("99999"); + a = libbig::largeInt("24"); + b = libbig::largeInt("25"); c = a * b; - assert(c == libbig::largeInt("99899001")); + assert(c == libbig::largeInt("600")); /// Test 3 a = libbig::largeInt("32516889472103571029388908423975"); From 608c4c6e60eae51bbbb2be14238025f8b9d4ca8d Mon Sep 17 00:00:00 2001 From: Hashir Hameed Niazi Date: Mon, 26 Oct 2020 10:33:12 +0530 Subject: [PATCH 7/7] fix: bug fixes --- big-int/src/operators/multiply.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/big-int/src/operators/multiply.cpp b/big-int/src/operators/multiply.cpp index bf78a0a..b8c12aa 100644 --- a/big-int/src/operators/multiply.cpp +++ b/big-int/src/operators/multiply.cpp @@ -100,6 +100,7 @@ namespace libbig Answer.push_back(single); factor *= 10; ++i; + } std::cout<