/*************************************************
* MP Multiplication Source File                  *
* (C) 1999-2003 The Botan Project                *
*************************************************/

#include <botan/mp_core.h>
#include <botan/mp_mul.h>
#include <botan/util.h>

namespace Botan {

namespace {

/*************************************************
* Length Checking                                *
*************************************************/
bool use_op(u32bit x_sw, u32bit y_sw,
            u32bit x_size, u32bit y_size, u32bit z_size,
            u32bit limit, u32bit min = 0)
   {
   return (x_sw <= limit && y_sw <= limit &&
           x_size >= limit && y_size >= limit && z_size >= 2*limit &&
           (x_sw + y_sw) >= min);
   }

}

/*************************************************
* MP Multiplication Algorithm Dispatcher         *
*************************************************/
void bigint_mul3(word* const z, u32bit z_size,
                 const word* x, u32bit x_size, u32bit x_sw,
                 const word* y, u32bit y_size, u32bit y_sw)
   {
   const u32bit KARAT_16_BOUND = 28;
   const u32bit KARAT_32_BOUND = 56;
   const u32bit KARAT_64_BOUND = 110;
   const u32bit KARAT_128_BOUND = 230;

   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(x_size < 4 || y_size < 4)
      bigint_smul(z, x, x_sw, y, y_sw);
   else if(use_op(x_sw, y_sw, x_size, y_size, z_size, 4))
      bigint_comba4(z, x, y);
   else if(use_op(x_sw, y_sw, x_size, y_size, z_size, 8))
      bigint_comba8(z, x, y);
   else if(use_op(x_sw, y_sw, x_size, y_size, z_size, 16, KARAT_16_BOUND))
      bigint_karat16(z, x, y);
   else if(use_op(x_sw, y_sw, x_size, y_size, z_size, 32, KARAT_32_BOUND))
      bigint_karat32(z, x, y);
   else if(use_op(x_sw, y_sw, x_size, y_size, z_size, 64, KARAT_64_BOUND))
      bigint_karat64(z, x, y);
   else if(use_op(x_sw, y_sw, x_size, y_size, z_size, 128, KARAT_128_BOUND))
      bigint_karat128(z, x, y);
   else
      bigint_smul(z, x, x_sw, y, y_sw);
   }

}
