TheAlgorithms/C++ 1.0.0
All the algorithms implemented in C++
Loading...
Searching...
No Matches
karatsuba_algorithm_for_fast_multiplication.cpp
Go to the documentation of this file.
1
15#include <cassert>
16#include <cstring>
17#include <iostream>
18#include <vector>
19
24namespace divide_and_conquer {
30namespace karatsuba_algorithm {
37std::string add_strings(std::string first, std::string second) {
38 std::string result; // to store the resulting sum bits
39
40 // make the string lengths equal
41 int64_t len1 = first.size();
42 int64_t len2 = second.size();
43 std::string zero = "0";
44 if (len1 < len2) {
45 for (int64_t i = 0; i < len2 - len1; i++) {
46 zero += first;
47 first = zero;
48 zero = "0"; // Prevents CI from failing
49 }
50 } else if (len1 > len2) {
51 for (int64_t i = 0; i < len1 - len2; i++) {
52 zero += second;
53 second = zero;
54 zero = "0"; // Prevents CI from failing
55 }
56 }
57
58 int64_t length = std::max(len1, len2);
59 int64_t carry = 0;
60 for (int64_t i = length - 1; i >= 0; i--) {
61 int64_t firstBit = first.at(i) - '0';
62 int64_t secondBit = second.at(i) - '0';
63
64 int64_t sum = (char(firstBit ^ secondBit ^ carry)) + '0'; // sum of 3 bits
65 result.insert(result.begin(), sum);
66
67 carry = char((firstBit & secondBit) | (secondBit & carry) |
68 (firstBit & carry)); // sum of 3 bits
69 }
70
71 if (carry) {
72 result.insert(result.begin(), '1'); // adding 1 incase of overflow
73 }
74 return result;
75}
76
86std::string safe_substr(const std::string &str, int64_t x1, int64_t x2, int64_t n) {
87 int64_t len = str.size();
88
89 if (len >= n) {
90 return str.substr(x1, x2);
91 }
92
93 int64_t y1 = x1 - (n - len); // index in str of first char of substring of "whole" string
94 int64_t y2 = (x1 + x2 - 1) - (n - len); // index in str of last char of substring of "whole" string
95
96 if (y2 < 0) {
97 return "0";
98 } else if (y1 < 0) {
99 return str.substr(0, y2 + 1);
100 } else {
101 return str.substr(y1, x2);
102 }
103}
104
112int64_t karatsuba_algorithm(std::string str1, std::string str2) {
113 int64_t len1 = str1.size();
114 int64_t len2 = str2.size();
115 int64_t n = std::max(len1, len2);
116
117 if (n == 0) {
118 return 0;
119 }
120 if (n == 1) {
121 return (str1[0] - '0') * (str2[0] - '0');
122 }
123
124 int64_t fh = n / 2; // first half of string
125 int64_t sh = n - fh; // second half of string
126
127 std::string Xl = divide_and_conquer::karatsuba_algorithm::safe_substr(str1, 0, fh, n); // first half of first string
128 std::string Xr = divide_and_conquer::karatsuba_algorithm::safe_substr(str1, fh, sh, n); // second half of first string
129
130 std::string Yl = divide_and_conquer::karatsuba_algorithm::safe_substr(str2, 0, fh, n); // first half of second string
131 std::string Yr = divide_and_conquer::karatsuba_algorithm::safe_substr(str2, fh, sh, n); // second half of second string
132
133 // calculating the three products of inputs of size n/2 recursively
134 int64_t product1 = karatsuba_algorithm(Xl, Yl);
135 int64_t product2 = karatsuba_algorithm(Xr, Yr);
136 int64_t product3 = karatsuba_algorithm(
139
140 return product1 * (1 << (2 * sh)) +
141 (product3 - product1 - product2) * (1 << sh) +
142 product2; // combining the three products to get the final result.
143}
144} // namespace karatsuba_algorithm
145} // namespace divide_and_conquer
146
151static void test() {
152 // 1st test
153 std::string s11 = "1"; // 1
154 std::string s12 = "1010"; // 10
155 std::cout << "1st test... ";
156 assert(divide_and_conquer::karatsuba_algorithm::karatsuba_algorithm(
157 s11, s12) == 10);
158 std::cout << "passed" << std::endl;
159
160 // 2nd test
161 std::string s21 = "11"; // 3
162 std::string s22 = "1010"; // 10
163 std::cout << "2nd test... ";
164 assert(divide_and_conquer::karatsuba_algorithm::karatsuba_algorithm(
165 s21, s22) == 30);
166 std::cout << "passed" << std::endl;
167
168 // 3rd test
169 std::string s31 = "110"; // 6
170 std::string s32 = "1010"; // 10
171 std::cout << "3rd test... ";
172 assert(divide_and_conquer::karatsuba_algorithm::karatsuba_algorithm(
173 s31, s32) == 60);
174 std::cout << "passed" << std::endl;
175}
176
181int main() {
182 test(); // run self-test implementations
183 return 0;
184}
static void test()
Self-test implementations.
std::string safe_substr(const std::string &str, int64_t x1, int64_t x2, int64_t n)
Wrapper function for substr that considers leading zeros.
std::string add_strings(std::string first, std::string second)
Binary addition.
for std::vector
Functions for the Karatsuba algorithm for fast multiplication implementation.