diff --git a/divide_and_conquer/karatsuba_algorithm_for_fast_multiplication.cpp b/divide_and_conquer/karatsuba_algorithm_for_fast_multiplication.cpp new file mode 100644 index 000000000..68db3ee6a --- /dev/null +++ b/divide_and_conquer/karatsuba_algorithm_for_fast_multiplication.cpp @@ -0,0 +1,141 @@ +/** + * @file + * @brief Implementation of the [Karatsuba algorithm for fast multiplication](https://en.wikipedia.org/wiki/Karatsuba_algorithm) + * @details + * Given two strings in binary notation we want to multiply them and return the value + * Simple approach is to multiply bits one by one which will give the time complexity of + * around O(n^2). To make it more efficient we will be using Karatsuba' algorithm to find the product which will solve the problem O(nlogn) of time. + * @author [Swastika Gupta](https://github.com/Swastyy) + */ + +#include /// for assert +#include /// for IO operations +#include /// for std::vector +#include /// for string +#include /// for string + +/** + * @namespace divide_and_conquer + * @brief Divide and Conquer algorithms + */ +namespace divide_and_conquer { +/** + * @namespace karatsuba_algorithm + * @brief Functions for the [Karatsuba algorithm for fast multiplication](https://en.wikipedia.org/wiki/Karatsuba_algorithm) + */ +namespace karatsuba_algorithm { +/** + * @brief Helper function for the main function, that implements Karatsuba's algorithm for fast multiplication + * @param first the input string 1 + * @param second the input string 2 + * @returns the concatenated string + */ +std::string addStrings( std::string first, std::string second ) +{ + std::string result; // To store the resulting sum bits + + int64_t len1 = first.size(); + int64_t len2 = second.size(); + int64_t length = std::max(len1,len2); + if (len1 < len2) // make the string lengths equal + { + for (int64_t i = 0 ; i < len2 - len1 ; i++) + first = '0' + first; + } + else if (len1 > len2) + { + for (int64_t i = 0 ; i < len1 - len2 ; i++) + second = '0' + second; + } + int64_t carry = 0; + for (int64_t i = length-1 ; i >= 0 ; i--) + { + int64_t firstBit = first.at(i) - '0'; + int64_t secondBit = second.at(i) - '0'; + + int64_t sum = (firstBit ^ secondBit ^ carry)+'0'; // sum of 3 bits + + result = (char)sum + result; + + carry = (firstBit&secondBit) | (secondBit&carry) | (firstBit&carry); // sum of 3 bits + } + + if(carry) result = '1' + result; // adding 1 incase of overflow + return result; +} +/** + * @brief The main function implements Karatsuba's algorithm for fast multiplication + * @param str1 the input string 1 + * @param str2 the input string 2 + * @returns the multiplicative number value + */ +int64_t karatsuba_algorithm(std::string str1, std::string str2) { + int64_t len1 = str1.size(); + int64_t len2 = str2.size(); + int64_t n = std::max(len1,len2); + if (len1 < len2) + { + for (int64_t i = 0 ; i < len2 - len1 ; i++) + str1 = '0' + str1; + } + else if (len1 > len2) + { + for (int64_t i = 0 ; i < len1 - len2 ; i++) + str2 = '0' + str2; + } + if(n==0) return 0; + if(n==1) return (str1[0] - '0')*(str2[0] - '0'); + int64_t fh = n/2; // first half of string + int64_t sh = (n-fh); // second half of string + + std::string Xl = str1.substr(0, fh); // first half of first string + std::string Xr = str1.substr(fh, sh); // second half of first string + + std::string Yl = str2.substr(0, fh); // first half of second string + std::string Yr = str2.substr(fh, sh); // second half of second string + + // Calculating the three products of inputs of size n/2 recursively + int64_t product1 = karatsuba_algorithm(Xl, Yl); + int64_t product2 = karatsuba_algorithm(Xr, Yr); + int64_t product3 = karatsuba_algorithm(divide_and_conquer::karatsuba_algorithm::addStrings(Xl, Xr), divide_and_conquer::karatsuba_algorithm::addStrings(Yl, Yr)); + + return product1*(1<<(2*sh)) + (product3 - product1 - product2)*(1<