⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libtommath.c

📁 IEEE802.11 a/b/g 客户端应用程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    }  }  /* copy used count and sign */  b->used = a->used;  b->sign = a->sign;  return MP_OKAY;}/* shift right a certain amount of digits */static void mp_rshd (mp_int * a, int b){  int     x;  /* if b <= 0 then ignore it */  if (b <= 0) {    return;  }  /* if b > used then simply zero it and return */  if (a->used <= b) {    mp_zero (a);    return;  }  {    register mp_digit *bottom, *top;    /* shift the digits down */    /* bottom */    bottom = a->dp;    /* top [offset into digits] */    top = a->dp + b;    /* this is implemented as a sliding window where      * the window is b-digits long and digits from      * the top of the window are copied to the bottom     *     * e.g.     b-2 | b-1 | b0 | b1 | b2 | ... | bb |   ---->                 /\                   |      ---->                  \-------------------/      ---->     */    for (x = 0; x < (a->used - b); x++) {      *bottom++ = *top++;    }    /* zero the top digits */    for (; x < a->used; x++) {      *bottom++ = 0;    }  }    /* remove excess digits */  a->used -= b;}/* swap the elements of two integers, for cases where you can't simply swap the  * mp_int pointers around */static void mp_exch (mp_int * a, mp_int * b){  mp_int  t;  t  = *a;  *a = *b;  *b = t;}/* trim unused digits  * * This is used to ensure that leading zero digits are * trimed and the leading "used" digit will be non-zero * Typically very fast.  Also fixes the sign if there * are no more leading digits */static void mp_clamp (mp_int * a){  /* decrease used while the most significant digit is   * zero.   */  while (a->used > 0 && a->dp[a->used - 1] == 0) {    --(a->used);  }  /* reset the sign flag if used == 0 */  if (a->used == 0) {    a->sign = MP_ZPOS;  }}/* grow as required */static int mp_grow (mp_int * a, int size){  int     i;  mp_digit *tmp;  /* if the alloc size is smaller alloc more ram */  if (a->alloc < size) {    /* ensure there are always at least MP_PREC digits extra on top */    size += (MP_PREC * 2) - (size % MP_PREC);    /* reallocate the array a->dp     *     * We store the return in a temporary variable     * in case the operation failed we don't want     * to overwrite the dp member of a.     */    tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size);    if (tmp == NULL) {      /* reallocation failed but "a" is still valid [can be freed] */      return MP_MEM;    }    /* reallocation succeeded so set a->dp */    a->dp = tmp;    /* zero excess digits */    i        = a->alloc;    a->alloc = size;    for (; i < a->alloc; i++) {      a->dp[i] = 0;    }  }  return MP_OKAY;}#ifdef BN_MP_ABS_C/* b = |a|  * * Simple function copies the input and fixes the sign to positive */static int mp_abs (mp_int * a, mp_int * b){  int     res;  /* copy a to b */  if (a != b) {     if ((res = mp_copy (a, b)) != MP_OKAY) {       return res;     }  }  /* force the sign of b to positive */  b->sign = MP_ZPOS;  return MP_OKAY;}#endif/* set to a digit */static void mp_set (mp_int * a, mp_digit b){  mp_zero (a);  a->dp[0] = b & MP_MASK;  a->used  = (a->dp[0] != 0) ? 1 : 0;}#ifndef LTM_NO_NEG_EXP/* b = a/2 */static int mp_div_2(mp_int * a, mp_int * b){  int     x, res, oldused;  /* copy */  if (b->alloc < a->used) {    if ((res = mp_grow (b, a->used)) != MP_OKAY) {      return res;    }  }  oldused = b->used;  b->used = a->used;  {    register mp_digit r, rr, *tmpa, *tmpb;    /* source alias */    tmpa = a->dp + b->used - 1;    /* dest alias */    tmpb = b->dp + b->used - 1;    /* carry */    r = 0;    for (x = b->used - 1; x >= 0; x--) {      /* get the carry for the next iteration */      rr = *tmpa & 1;      /* shift the current digit, add in carry and store */      *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));      /* forward carry to next iteration */      r = rr;    }    /* zero excess digits */    tmpb = b->dp + b->used;    for (x = b->used; x < oldused; x++) {      *tmpb++ = 0;    }  }  b->sign = a->sign;  mp_clamp (b);  return MP_OKAY;}#endif /* LTM_NO_NEG_EXP *//* shift left by a certain bit count */static int mp_mul_2d (mp_int * a, int b, mp_int * c){  mp_digit d;  int      res;  /* copy */  if (a != c) {     if ((res = mp_copy (a, c)) != MP_OKAY) {       return res;     }  }  if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {     if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {       return res;     }  }  /* shift by as many digits in the bit count */  if (b >= (int)DIGIT_BIT) {    if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {      return res;    }  }  /* shift any bit count < DIGIT_BIT */  d = (mp_digit) (b % DIGIT_BIT);  if (d != 0) {    register mp_digit *tmpc, shift, mask, r, rr;    register int x;    /* bitmask for carries */    mask = (((mp_digit)1) << d) - 1;    /* shift for msbs */    shift = DIGIT_BIT - d;    /* alias */    tmpc = c->dp;    /* carry */    r    = 0;    for (x = 0; x < c->used; x++) {      /* get the higher bits of the current word */      rr = (*tmpc >> shift) & mask;      /* shift the current word and OR in the carry */      *tmpc = ((*tmpc << d) | r) & MP_MASK;      ++tmpc;      /* set the carry to the carry bits of the current word */      r = rr;    }        /* set final carry */    if (r != 0) {       c->dp[(c->used)++] = r;    }  }  mp_clamp (c);  return MP_OKAY;}#ifdef BN_MP_INIT_MULTI_Cstatic int mp_init_multi(mp_int *mp, ...) {    mp_err res = MP_OKAY;      /* Assume ok until proven otherwise */    int n = 0;                 /* Number of ok inits */    mp_int* cur_arg = mp;    va_list args;    va_start(args, mp);        /* init args to next argument from caller */    while (cur_arg != NULL) {        if (mp_init(cur_arg) != MP_OKAY) {            /* Oops - error! Back-track and mp_clear what we already               succeeded in init-ing, then return error.            */            va_list clean_args;                        /* end the current list */            va_end(args);                        /* now start cleaning up */                        cur_arg = mp;            va_start(clean_args, mp);            while (n--) {                mp_clear(cur_arg);                cur_arg = va_arg(clean_args, mp_int*);            }            va_end(clean_args);            res = MP_MEM;            break;        }        n++;        cur_arg = va_arg(args, mp_int*);    }    va_end(args);    return res;                /* Assumed ok, if error flagged above. */}#endif#ifdef BN_MP_CLEAR_MULTI_Cstatic void mp_clear_multi(mp_int *mp, ...) {    mp_int* next_mp = mp;    va_list args;    va_start(args, mp);    while (next_mp != NULL) {        mp_clear(next_mp);        next_mp = va_arg(args, mp_int*);    }    va_end(args);}#endif/* shift left a certain amount of digits */static int mp_lshd (mp_int * a, int b){  int     x, res;  /* if its less than zero return */  if (b <= 0) {    return MP_OKAY;  }  /* grow to fit the new digits */  if (a->alloc < a->used + b) {     if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {       return res;     }  }  {    register mp_digit *top, *bottom;    /* increment the used by the shift amount then copy upwards */    a->used += b;    /* top */    top = a->dp + a->used - 1;    /* base */    bottom = a->dp + a->used - 1 - b;    /* much like mp_rshd this is implemented using a sliding window     * except the window goes the otherway around.  Copying from     * the bottom to the top.  see bn_mp_rshd.c for more info.     */    for (x = a->used - 1; x >= b; x--) {      *top-- = *bottom--;    }    /* zero the lower digits */    top = a->dp;    for (x = 0; x < b; x++) {      *top++ = 0;    }  }  return MP_OKAY;}/* returns the number of bits in an int */static int mp_count_bits (mp_int * a){  int     r;  mp_digit q;  /* shortcut */  if (a->used == 0) {    return 0;  }  /* get number of digits and add that */  r = (a->used - 1) * DIGIT_BIT;    /* take the last digit and count the bits in it */  q = a->dp[a->used - 1];  while (q > ((mp_digit) 0)) {    ++r;    q >>= ((mp_digit) 1);  }  return r;}/* calc a value mod 2**b */static int mp_mod_2d (mp_int * a, int b, mp_int * c){  int     x, res;  /* if b is <= 0 then zero the int */  if (b <= 0) {    mp_zero (c);    return MP_OKAY;  }  /* if the modulus is larger than the value than return */  if (b >= (int) (a->used * DIGIT_BIT)) {    res = mp_copy (a, c);    return res;  }  /* copy */  if ((res = mp_copy (a, c)) != MP_OKAY) {    return res;  }  /* zero digits above the last digit of the modulus */  for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {    c->dp[x] = 0;  }  /* clear the digit that is not completely outside/inside the modulus */  c->dp[b / DIGIT_BIT] &=    (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));  mp_clamp (c);  return MP_OKAY;}#ifdef BN_MP_DIV_SMALL/* slower bit-bang division... also smaller */static int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d){   mp_int ta, tb, tq, q;   int    res, n, n2;  /* is divisor zero ? */  if (mp_iszero (b) == 1) {    return MP_VAL;  }  /* if a < b then q=0, r = a */  if (mp_cmp_mag (a, b) == MP_LT) {    if (d != NULL) {      res = mp_copy (a, d);    } else {      res = MP_OKAY;    }    if (c != NULL) {      mp_zero (c);    }    return res;  }	  /* init our temps */  if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) {     return res;  }  mp_set(&tq, 1);  n = mp_count_bits(a) - mp_count_bits(b);  if (((res = mp_abs(a, &ta)) != MP_OKAY) ||      ((res = mp_abs(b, &tb)) != MP_OKAY) ||       ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||      ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {      goto LBL_ERR;  }  while (n-- >= 0) {     if (mp_cmp(&tb, &ta) != MP_GT) {        if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||            ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {           goto LBL_ERR;        }     }     if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||         ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {           goto LBL_ERR;     }  }  /* now q == quotient and ta == remainder */  n  = a->sign;  n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);  if (c != NULL) {     mp_exch(c, &q);     c->sign  = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;  }  if (d != NULL) {     mp_exch(d, &ta);     d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;  }LBL_ERR:   mp_clear_multi(&ta, &tb, &tq, &q, NULL);   return res;}#else/* integer signed division.  * c*b + d == a [e.g. a/b, c=quotient, d=remainder] * HAC pp.598 Algorithm 14.20 * * Note that the description in HAC is horribly  * incomplete.  For example, it doesn't consider  * the case where digits are removed from 'x' in  * the inner loop.  It also doesn't consider the  * case that y has fewer than three digits, etc.. * * The overall algorithm is as described as  * 14.20 from HAC but fixed to treat these cases.*/static int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d){  mp_int  q, x, y, t1, t2;  int     res, n, t, i, norm, neg;  /* is divisor zero ? */  if (mp_iszero (b) == 1) {    return MP_VAL;  }  /* if a < b then q=0, r = a */  if (mp_cmp_mag (a, b) == MP_LT) {    if (d != NULL) {      res = mp_copy (a, d);    } else {      res = MP_OKAY;    }    if (c != NULL) {      mp_zero (c);    }    return res;  }  if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {    return res;  }  q.used = a->used + 2;  if ((res = mp_init (&t1)) != MP_OKAY) {    goto LBL_Q;  }  if ((res = mp_init (&t2)) != MP_OKAY) {    goto LBL_T1;  }  if ((res = mp_init_copy (&x, a)) != MP_OKAY) {    goto LBL_T2;  }  if ((res = mp_init_copy (&y, b)) != MP_OKAY) {    goto LBL_X;  }  /* fix the sign */  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;  x.sign = y.sign = MP_ZPOS;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -