diff --git a/big-int/CMakeLists.txt b/big-int/CMakeLists.txt index 4cda72a..fbef76b 100644 --- a/big-int/CMakeLists.txt +++ b/big-int/CMakeLists.txt @@ -3,6 +3,9 @@ add_library( src/bigint.hpp src/bigint.cpp + ## helpers + src/helpers.cpp + ## operators src/operators/assignment_operator.cpp src/operators/divide_equal.cpp diff --git a/big-int/src/bigint.hpp b/big-int/src/bigint.hpp index a5fc749..ce47f57 100644 --- a/big-int/src/bigint.hpp +++ b/big-int/src/bigint.hpp @@ -125,6 +125,7 @@ class largeInt friend std::istream &operator>>(std::istream &, largeInt &); friend std::ostream &operator<<(std::ostream &, const largeInt &); }; +int char_int_converter(const char &x); } // namespace libbig #endif \ No newline at end of file diff --git a/big-int/src/helpers.cpp b/big-int/src/helpers.cpp new file mode 100644 index 0000000..8399ad2 --- /dev/null +++ b/big-int/src/helpers.cpp @@ -0,0 +1,38 @@ +/** + * Boost Software License - Version 1.0 - August 17th, 2003 + * Permission is hereby granted, free of charge, to any person + * or organization obtaining a copy of the software and + * accompanying documentation covered by this license + * (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative + * works of the Software, and to permit third-parties to whom the + * Software is furnished to do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, + * including the above license grant, this restriction and the following + * disclaimer, must be included in all copies of the Software, in whole or + * in part, and all derivative works of the Software, unless such copies + * or derivative works are solely in the form of machine-executable + * object code generated by a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE + * DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, + * WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include +#include +#include +#include + +namespace libbig +{ + int char_int_converter(const char &x) { + return ((x >= '0' && x <= '9') ? x - '0' : x + '0') ; + } +} // namespace libbig \ No newline at end of file diff --git a/big-int/src/operators/multiply.cpp b/big-int/src/operators/multiply.cpp index 48d792b..2ade0f6 100644 --- a/big-int/src/operators/multiply.cpp +++ b/big-int/src/operators/multiply.cpp @@ -27,10 +27,102 @@ #include #include - -#include "../bigint.hpp" +#include +#include namespace libbig { + largeInt largeInt::operator*(const largeInt &next_number) { + + auto remove_zeroes = [] (const largeInt &x) { + for(int j=0; j < x.number.length(); ++j) { + if((x.number[j]) != '0') { + return largeInt(x.number.substr(j, x.number.length())); + } + } + return largeInt("0"); + }; + + auto append_zeroes = [] (const largeInt &x, const int factor) { + largeInt Answer = x; + for(int k = 0; k < factor; k++) { + Answer.number.push_back('0'); + } + + return Answer; + }; + + auto simple_multiplication = [] (const largeInt &x, const largeInt &y) { + + largeInt x1 = x; + largeInt x2 = y; + largeInt adder; + largeInt Answer(0); + + if(x1.number.length() == 0 || x2.number.length() == 0) { + return largeInt(); + } + + int carry { 0 }, temp, f=0; + for(auto i=x1.number.rbegin(); i!=x1.number.rend(); ++i) { + for(auto j=x2.number.rbegin(); j!=x2.number.rend(); ++j) { + temp = char_int_converter(*i) * char_int_converter(*j) + carry; + carry = temp/10; + adder.number.push_back(char_int_converter(temp%10)); + } + if(carry) { + adder.number.push_back(char_int_converter(carry)); + carry = 0; + } + std::reverse(adder.number.begin(), adder.number.end()); + for(int k=1; k <= f; ++k) { + adder.number.push_back('0'); + } + Answer = Answer + adder; + adder = largeInt(); + f += 1; + } + + if(x1.sign != x2.sign) + Answer.sign = NEGATIVE; + + return Answer; + }; + + largeInt x = *this; + largeInt y = next_number; + + if(x.number == "0" || y.number == "0" || x.number.length() == 0 || y.number.length() == 0) { + return largeInt("0"); + } + 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())); + + const largeInt x3 = x1 + x2; + const largeInt y3 = y1 + y2; + + largeInt x1y1 = simple_multiplication(x1, y1); + largeInt x2y2 = simple_multiplication(x2, y2); + largeInt x3y3 = simple_multiplication(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); + } + } // namespace libbig diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2858ad9..0c7b4cd 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,4 +9,4 @@ foreach(testsourcefile ${TEST_SOURCES}) string ( REPLACE ".cpp" "" testname ${testsourcefile} ) add_executable( ${testname} ${testsourcefile} ) target_link_libraries( ${testname} big-int ) -endforeach() +endforeach() \ No newline at end of file diff --git a/tests/operators/CMakeLists.txt b/tests/operators/CMakeLists.txt index 2c2eca3..7241201 100644 --- a/tests/operators/CMakeLists.txt +++ b/tests/operators/CMakeLists.txt @@ -7,4 +7,4 @@ foreach(testsourcefile ${TEST_SOURCES}) add_test(${testname} ${testname}) endforeach() -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/input.txt DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) \ No newline at end of file +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/input.txt DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) \ No newline at end of file diff --git a/tests/operators/multiply_test.cpp b/tests/operators/multiply_test.cpp new file mode 100644 index 0000000..672fcf6 --- /dev/null +++ b/tests/operators/multiply_test.cpp @@ -0,0 +1,75 @@ +#include +#include +#include + +int main() +{ + /// Tests for multiplication of largeInt to largeInt (largeInt * largeInt) + /// Test 1 + libbig::largeInt a("1"); + libbig::largeInt b("1"); + libbig::largeInt c = a * b; + assert(c == libbig::largeInt("1")); + + /// Test 2 + a = libbig::largeInt("999"); + b = libbig::largeInt("99999"); + c = a * b; + assert(c == libbig::largeInt("99899001")); + + /// Test 3 + a = libbig::largeInt("32516889472103571029388908423975"); + b = libbig::largeInt("0"); + c = a * b; + assert(c == libbig::largeInt("0")); + + /// Test 4 + a = libbig::largeInt("6666666666666"); + b = libbig::largeInt("58723619378"); + c = a * b; + assert(c == libbig::largeInt("391490795853294184253748")); + + // Test 5 + a = libbig::largeInt("33"); + b = libbig::largeInt("-2"); + c = a * b; + assert(c == libbig::largeInt("-66")); + + // Test 6 + a = libbig::largeInt("78239823648904375"); + b = libbig::largeInt("1273898653482713986555"); + c = a * b; + assert(c == libbig::largeInt("99669605995064285419229672514230678125")); + + // Test 7 + a = libbig::largeInt("-0"); + b = libbig::largeInt("100"); + c = a * b; + assert(c == libbig::largeInt("0")); + + // Test 8 + a = libbig::largeInt("-100"); + b = libbig::largeInt("-100"); + c = a * b; + assert(c == libbig::largeInt("10000")); + + // Test 9 + a = libbig::largeInt("0000000000000000000000000000000000000000000000000000"); + b = libbig::largeInt("1111111111111111111111111111111111111111111111111111"); + c = a * b; + assert(c == libbig::largeInt("0")); + + // Test 10 + a = libbig::largeInt("746767836578647567834567834657836587"); + b = libbig::largeInt("89275924758922476024759846938475804579247593468034769835763597028476937"); + c = a * b; + assert(c == libbig::largeInt("66668389190778655840704160824409791548824154145813767587653936294222881640592188804856387839101068044294019")); + + // Test 10 + a = libbig::largeInt("8492387957349593498354782359782345782367895623478567894235692347856789234789236789342967891235627348589234567892345234567892369287345"); + b = libbig::largeInt("824358293475908745902350926589023459023485089347892650234650273456207349236502347524357832456789235623489759235623789456782394567892359478235239423569782356234659837562378965278956237489235"); + c = a * b; + assert(c == libbig::largeInt("7000770444056069403046119404826740387252166452093943636486324185225836788920060077258109995450330997820727632474615791121779806923541276193853962113432983583426568371447855101334504301369704676060587738461922443343618487980096828486083202559107333726983966552151422667448209619250487990929538296732965889159956209059231075")); + + return 0; +} \ No newline at end of file