Edit

kc3-lang/libtommath/bn_mp_mul.c

Branch :

  • Show log

    Commit

  • Author : Francois Perrad
    Date : 2019-05-19 17:16:13
    Hash : 8b2daf78
    Message : always use varname err with mp_err

  • bn_mp_mul.c
  • #include "tommath_private.h"
    #ifdef BN_MP_MUL_C
    /* LibTomMath, multiple-precision integer library -- Tom St Denis */
    /* SPDX-License-Identifier: Unlicense */
    
    /* high level multiplication (handles sign) */
    mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c)
    {
       mp_err  err;
       mp_sign neg;
    #ifdef BN_S_MP_BALANCE_MUL_C
       int len_b, len_a;
    #endif
       neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
    #ifdef BN_S_MP_BALANCE_MUL_C
       len_a = a->used;
       len_b = b->used;
    
       if (len_a == len_b) {
          goto GO_ON;
       }
       /*
        * Check sizes. The smaller one needs to be larger than the Karatsuba cut-off.
        * The bigger one needs to be at least about one KARATSUBA_MUL_CUTOFF bigger
        * to make some sense, but it depends on architecture, OS, position of the
        * stars... so YMMV.
        * Using it to cut the input into slices small enough for fast_s_mp_mul_digs
        * was actually slower on the author's machine, but YMMV.
        */
       if ((MP_MIN(len_a, len_b) < MP_KARATSUBA_MUL_CUTOFF)
           || ((MP_MAX(len_a, len_b) / 2) < MP_KARATSUBA_MUL_CUTOFF)) {
          goto GO_ON;
       }
       /*
        * Not much effect was observed below a ratio of 1:2, but again: YMMV.
        */
       if ((MP_MAX(len_a, len_b) /  MP_MIN(len_a, len_b)) < 2) {
          goto GO_ON;
       }
    
       err = s_mp_balance_mul(a,b,c);
       goto END;
    
    GO_ON:
    #endif
    
       /* use Toom-Cook? */
    #ifdef BN_S_MP_TOOM_MUL_C
       if (MP_MIN(a->used, b->used) >= MP_TOOM_MUL_CUTOFF) {
          err = s_mp_toom_mul(a, b, c);
       } else
    #endif
    #ifdef BN_S_MP_KARATSUBA_MUL_C
          /* use Karatsuba? */
          if (MP_MIN(a->used, b->used) >= MP_KARATSUBA_MUL_CUTOFF) {
             err = s_mp_karatsuba_mul(a, b, c);
          } else
    #endif
          {
             /* can we use the fast multiplier?
              *
              * The fast multiplier can be used if the output will
              * have less than MP_WARRAY digits and the number of
              * digits won't affect carry propagation
              */
             int     digs = a->used + b->used + 1;
    
    #ifdef BN_S_MP_MUL_DIGS_FAST_C
             if ((digs < (int)MP_WARRAY) &&
                 (MP_MIN(a->used, b->used) <= MP_MAXFAST)) {
                err = s_mp_mul_digs_fast(a, b, c, digs);
             } else
    #endif
             {
    #ifdef BN_S_MP_MUL_DIGS_C
                err = s_mp_mul_digs(a, b, c, a->used + b->used + 1);
    #else
                err = MP_VAL;
    #endif
             }
          }
    END:
       c->sign = (c->used > 0) ? neg : MP_ZPOS;
       return err;
    }
    #endif