Beispiel #1
0
std::deque<int> bigint::karatsuba_mul(const std::deque<int> &lhs, const std::deque<int> &rhs)
{
	auto n = std::max(lhs.size(), rhs.size());

	if (n == 1)
		return to_deque(lhs[0] * rhs[0]);

	auto len = lhs.size();
	int k = len / 2;

	std::deque<int> res;
	std::deque<int> Xl, Xr, Yl, Yr;
	std::deque<int> P1, P2, P3;
	std::deque<int> Xlr(k), Ylr(k);

	Xr.assign(lhs.begin() + k, lhs.end());
	Xl.assign(lhs.begin(), lhs.begin() + k);
	Yr.assign(rhs.begin() + k, rhs.end());
	Yl.assign(rhs.begin(), rhs.begin() + k);

	P1 = karatsuba_mul(Xl, Yl);
	P2 = karatsuba_mul(Xr, Yr);

	for (int i = 0; i < k; ++i)
	{
		Xlr[i] = Xl[i] + Xr[i];
		Ylr[i] = Yl[i] + Yr[i];
	}

	P3 = karatsuba_mul(Xlr, Ylr);

	//P1 * 10 ^ n + (P3 - P1 - P2) * 10 ^ (n / 2) + P2
	res = to_deque(P1[0] * std::pow(10, n) + (P3 - P1 - P2) * pow(10, n / 2) + P2[0]);


	/*
	for (std::size_t i = 0; i < len; ++i)
		P3[i] -= P2[i] + P1[i];

	for (std::size_t i = 0; i < len; ++i)
		res[i] = P2[i];

	for (std::size_t i = len; i < 2 * len; ++i)
		res[i] = P1[i - len];

	for (std::size_t i = k; i < len; ++i)
		res[i] += P3[i - k];
	*/
	return res;
}
Beispiel #2
0
bigint & bigint::operator*(const std::deque<int> &rhs)
{
	std::deque<int> tmp(rhs);
	align(deq, tmp);
	*this = karatsuba_mul(deq, tmp);
	return *this;
}
Beispiel #3
0
void bigint_mul(word z[], size_t z_size,
                const word x[], size_t x_size, size_t x_sw,
                const word y[], size_t y_size, size_t y_sw,
                word workspace[], size_t ws_size)
   {
   clear_mem(z, z_size);

   if(x_sw == 1)
      {
      bigint_linmul3(z, y, y_sw, x[0]);
      }
   else if(y_sw == 1)
      {
      bigint_linmul3(z, x, x_sw, y[0]);
      }
   else if(sized_for_comba_mul<4>(x_sw, x_size, y_sw, y_size, z_size))
      {
      bigint_comba_mul4(z, x, y);
      }
   else if(sized_for_comba_mul<6>(x_sw, x_size, y_sw, y_size, z_size))
      {
      bigint_comba_mul6(z, x, y);
      }
   else if(sized_for_comba_mul<8>(x_sw, x_size, y_sw, y_size, z_size))
      {
      bigint_comba_mul8(z, x, y);
      }
   else if(sized_for_comba_mul<9>(x_sw, x_size, y_sw, y_size, z_size))
      {
      bigint_comba_mul9(z, x, y);
      }
   else if(sized_for_comba_mul<16>(x_sw, x_size, y_sw, y_size, z_size))
      {
      bigint_comba_mul16(z, x, y);
      }
   else if(x_sw < KARATSUBA_MULTIPLY_THRESHOLD ||
           y_sw < KARATSUBA_MULTIPLY_THRESHOLD ||
           !workspace)
      {
      basecase_mul(z, z_size, x, x_sw, y, y_sw);
      }
   else
      {
      const size_t N = karatsuba_size(z_size, x_size, x_sw, y_size, y_sw);

      if(N && z_size >= 2*N && ws_size >= 2*N)
         karatsuba_mul(z, x, y, N, workspace);
      else
         basecase_mul(z, z_size, x, x_sw, y, y_sw);
      }
   }
Beispiel #4
0
/*************************************************
* Multiplication Algorithm Dispatcher            *
*************************************************/
void bigint_mul(word z[], u32bit z_size, word workspace[],
                const word x[], u32bit x_size, u32bit x_sw,
                const word y[], u32bit y_size, u32bit y_sw)
   {
   if(x_size <= 8 || y_size <= 8)
      {
      handle_small_mul(z, z_size, x, x_size, x_sw, y, y_size, y_sw);
      return;
      }

   const u32bit N = karatsuba_size(z_size, x_size, x_sw, y_size, y_sw);

   if(N)
      {
      clear_mem(workspace, 2*N);
      karatsuba_mul(z, x, y, N, workspace);
      }
   else
      bigint_simple_mul(z, x, x_sw, y, y_sw);
   }