InfInt karatsubaMult(string x, string y) { InfInt *result = new InfInt(0); int m = makeEqualLength(x, y); if(m == 0) return *result; size_t sz = 0; if( x.length() == 1 || y.length() == 1 ) { result = new InfInt(stoull(x, &sz, 0) * stoull(y, &sz, 0)); return *result; } // m2 + m2Rest = m int m2 = m/2; int m2Rest = m - m2; string xl = x.substr(0, m2); string xr = x.substr(m2, m2Rest); string yl = y.substr(0, m2); string yr = y.substr(m2, m2Rest); InfInt z0 = karatsubaMult(xr, yr); InfInt z1 = karatsubaMult(add(xl, xr), add(yl, yr)); InfInt z2 = karatsubaMult(xl, yl); *result = (z2 * basePower(*INFINTBASE10, 2*m2) + ((z1-z2-z0) * basePower(*INFINTBASE10, m2)) + z0); return *result; }
BigInt BigInt::karatsubaMult(const BigInt& a, const BigInt& b) { int minSize = std::min(a.size(), b.size()); if (minSize < 30) { return a * b; } BigInt x0, x1, y0, y1; BigInt z0, z1, z2; int mid = minSize / 2; x0.digits.resize(mid); x1.digits.resize(a.digits.size() - mid); y0.digits.resize(mid); y1.digits.resize(b.digits.size() - mid); copy(a.digits.begin(), a.digits.begin() + mid, x0.digits.begin()); copy(a.digits.begin() + mid, a.digits.end(), x1.digits.begin()); copy(b.digits.begin(), b.digits.begin() + mid, y0.digits.begin()); copy(b.digits.begin() + mid, b.digits.end(), y1.digits.begin()); z0 = karatsubaMult(x0, y0); z1 = karatsubaMult(x1, y1); z2 = (karatsubaMult(x0 + x1, y0 + y1) - z1) - z0; padZeros(z2, mid); padZeros(z1, 2*mid); return z0 + z1 + z2; }