Codebase list libcryptx-perl / upstream/0.066 src / ltm / bn_fast_s_mp_mul_high_digs.c
upstream/0.066

Tree @upstream/0.066 (Download .tar.gz)

bn_fast_s_mp_mul_high_digs.c @upstream/0.066

7dcfba3
b7f589b
 
 
 
 
 
 
 
 
 
 
 
be43106
 
 
 
 
 
 
 
 
 
b7f589b
be43106
b7f589b
a7d3482
 
be43106
a7d3482
 
 
b7f589b
 
a7d3482
 
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_HIGH_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
 */

/* this is a modified version of fast_s_mul_digs that only produces
 * output digits *above* digs.  See the comments for fast_s_mul_digs
 * to see how it works.
 *
 * This is used in the Barrett reduction since for one of the multiplications
 * only the higher digits were needed.  This essentially halves the work.
 *
 * Based on Algorithm 14.12 on pp.595 of HAC.
 */
int fast_s_mp_mul_high_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 */
   pa = a->used + b->used;
   if (c->alloc < pa) {
      if ((res = mp_grow(c, pa)) != MP_OKAY) {
         return res;
      }
   }

   /* number of output digits to produce */
   pa = a->used + b->used;
   _W = 0;
   for (ix = digs; ix < pa; ix++) {
      int      tx, ty, 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 its
         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 + digs;
      for (ix = digs; 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$ */