Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Multiply Operator (*) overload with tests #59

Merged
merged 11 commits into from
Oct 22, 2020
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions big-int/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions big-int/src/bigint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
38 changes: 38 additions & 0 deletions big-int/src/helpers.cpp
Original file line number Diff line number Diff line change
@@ -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 <istream>
#include <ostream>
#include <bigint.hpp>
#include <algorithm>

namespace libbig
{
int char_int_converter(const char &x) {
return ((x >= '0' && x <= '9') ? x - '0' : x + '0') ;
}
} // namespace libbig
96 changes: 94 additions & 2 deletions big-int/src/operators/multiply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,102 @@

#include <istream>
#include <ostream>

#include "../bigint.hpp"
#include <bigint.hpp>
#include <algorithm>

namespace libbig
{
largeInt largeInt::operator*(const largeInt &next_number) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still two overloads are missing.
for largeInt * int and largeInt * int64_t (int64_t aka long long)


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 = false;
ayaankhan98 marked this conversation as resolved.
Show resolved Hide resolved

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 = false;
ayaankhan98 marked this conversation as resolved.
Show resolved Hide resolved

return remove_zeroes(xy);
}


} // namespace libbig
2 changes: 1 addition & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
2 changes: 1 addition & 1 deletion tests/operators/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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}/)
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/input.txt DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
75 changes: 75 additions & 0 deletions tests/operators/multiply_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <bigint.hpp>
#include <iostream>
#include <cassert>

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"));

ayaankhan98 marked this conversation as resolved.
Show resolved Hide resolved
return 0;
}