Codebase list libcryptx-perl / b695019d-2dff-4c2e-a82a-3970260cfcd6/main src / ltm / bn_fast_s_mp_mul_digs.c
b695019d-2dff-4c2e-a82a-3970260cfcd6/main

Tree @b695019d-2dff-4c2e-a82a-3970260cfcd6/main (Download .tar.gz)

bn_fast_s_mp_mul_digs.c @b695019d-2dff-4c2e-a82a-3970260cfcd6/main

7dcfba3
b7f589b
 
 
 
 
 
 
 
 
 
 
 
be43106
 
 
a7d3482
 
 
be43106
 
 
a7d3482
 
 
be43106
 
 
 
 
b7f589b
be43106
b7f589b
a7d3482
 
be43106
a7d3482
 
b7f589b
 
a7d3482
 
be43106
a7d3482
b7f589b
be43106
a7d3482
 
 
be43106
 
 
 
 
b7f589b
be43106
 
 
 
 
 
a7d3482
be43106
 
b7f589b
be43106
 
 
a7d3482
be43106
 
 
 
a7d3482
be43106
 
b7f589b
a7d3482
be43106
a7d3482
 
 
be43106
a7d3482
 
 
 
 
 
 
be43106
a7d3482
b7f589b
 
 
a7d3482
 
 
be43106
 
b7f589b
 
 
 
#include "tommath_private.h"
#ifdef BN_FAST_S_MP_MUL_DIGS_C
/* LibTomMath, multiple-precision integer library -- Tom St Denis
 *
 * LibTomMath is a library that provides multiple-precision
 * integer arithmetic as well as number theoretic functionality.
 *
 * The library was designed directly after the MPI library by
 * Michael Fromberger but has been written from scratch with
 * additional optimizations in place.
 *
 * SPDX-License-Identifier: Unlicense
 */

/* Fast (comba) multiplier
 *
 * This is the fast column-array [comba] multiplier.  It is
 * designed to compute the columns of the product first
 * then handle the carries afterwards.  This has the effect
 * of making the nested loops that compute the columns very
 * simple and schedulable on super-scalar processors.
 *
 * This has been modified to produce a variable number of
 * digits of output so if say only a half-product is required
 * you don't have to compute the upper half (a feature
 * required for fast Barrett reduction).
 *
 * Based on Algorithm 14.12 on pp.595 of HAC.
 *
 */
int fast_s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs)
{
   int     olduse, res, pa, ix, iz;
   mp_digit W[MP_WARRAY];
   mp_word  _W;

   /* grow the destination as required */
   if (c->alloc < digs) {
      if ((res = mp_grow(c, digs)) != MP_OKAY) {
         return res;
      }
   }

   /* number of output digits to produce */
   pa = MIN(digs, a->used + b->used);

   /* clear the carry */
   _W = 0;
   for (ix = 0; ix < pa; ix++) {
      int      tx, ty;
      int      iy;
      mp_digit *tmpx, *tmpy;

      /* get offsets into the two bignums */
      ty = MIN(b->used-1, ix);
      tx = ix - ty;

      /* setup temp aliases */
      tmpx = a->dp + tx;
      tmpy = b->dp + ty;

      /* this is the number of times the loop will iterrate, essentially
         while (tx++ < a->used && ty-- >= 0) { ... }
       */
      iy = MIN(a->used-tx, ty+1);

      /* execute loop */
      for (iz = 0; iz < iy; ++iz) {
         _W += (mp_word)*tmpx++ * (mp_word)*tmpy--;

      }

      /* store term */
      W[ix] = (mp_digit)_W & MP_MASK;

      /* make next carry */
      _W = _W >> (mp_word)DIGIT_BIT;
   }

   /* setup dest */
   olduse  = c->used;
   c->used = pa;

   {
      mp_digit *tmpc;
      tmpc = c->dp;
      for (ix = 0; ix < pa; ix++) {
         /* now extract the previous digit [below the carry] */
         *tmpc++ = W[ix];
      }

      /* clear unused digits [that existed in the old copy of c] */
      for (; ix < olduse; ix++) {
         *tmpc++ = 0;
      }
   }
   mp_clamp(c);
   return MP_OKAY;
}
#endif

/* ref:         $Format:%D$ */
/* git commit:  $Format:%H$ */
/* commit time: $Format:%ai$ */