📄 mpi.c
字号:
/* }}} *//* {{{ mp_strerror(ec) *//* mp_strerror(ec) Return a string describing the meaning of error code 'ec'. The string returned is allocated in static memory, so the caller should not attempt to modify or free the memory associated with this string. */const char *mp_strerror(mp_err ec){ int aec = (ec < 0) ? -ec : ec; /* Code values are negative, so the senses of these comparisons are accurate */ if(ec < MP_LAST_CODE || ec > MP_OKAY) { return mp_err_string[0]; /* unknown error code */ } else { return mp_err_string[aec + 1]; }} /* end mp_strerror() *//* }}} *//*========================================================================*//*------------------------------------------------------------------------*//* Static function definitions (internal use only) *//* {{{ Memory management *//* {{{ s_mp_grow(mp, min) *//* Make sure there are at least 'min' digits allocated to mp */mp_err s_mp_grow(mp_int *mp, mp_size min){ if(min > ALLOC(mp)) { mp_digit *tmp; /* Set min to next nearest default precision block size */ min = ((min + (s_mp_defprec - 1)) / s_mp_defprec) * s_mp_defprec; if((tmp = s_mp_alloc(min, sizeof(mp_digit))) == NULL) return MP_MEM; s_mp_copy(DIGITS(mp), tmp, USED(mp));#if MP_CRYPTO s_mp_setz(DIGITS(mp), ALLOC(mp));#endif s_mp_free(DIGITS(mp)); DIGITS(mp) = tmp; ALLOC(mp) = min; } return MP_OKAY;} /* end s_mp_grow() *//* }}} *//* {{{ s_mp_pad(mp, min) *//* Make sure the used size of mp is at least 'min', growing if needed */mp_err s_mp_pad(mp_int *mp, mp_size min){ if(min > USED(mp)) { mp_err res; /* Make sure there is room to increase precision */ if(min > ALLOC(mp) && (res = s_mp_grow(mp, min)) != MP_OKAY) return res; /* Increase precision; should already be 0-filled */ USED(mp) = min; } return MP_OKAY;} /* end s_mp_pad() *//* }}} *//* {{{ s_mp_setz(dp, count) */#if MP_MACRO == 0/* Set 'count' digits pointed to by dp to be zeroes */void s_mp_setz(mp_digit *dp, mp_size count){#if MP_MEMSET == 0 int ix; for(ix = 0; ix < count; ix++) dp[ix] = 0;#else memset(dp, 0, count * sizeof(mp_digit));#endif} /* end s_mp_setz() */#endif/* }}} *//* {{{ s_mp_copy(sp, dp, count) */#if MP_MACRO == 0/* Copy 'count' digits from sp to dp */void s_mp_copy(mp_digit *sp, mp_digit *dp, mp_size count){#if MP_MEMCPY == 0 int ix; for(ix = 0; ix < count; ix++) dp[ix] = sp[ix];#else memcpy(dp, sp, count * sizeof(mp_digit));#endif} /* end s_mp_copy() */#endif/* }}} *//* {{{ s_mp_alloc(nb, ni) */#if MP_MACRO == 0/* Allocate ni records of nb bytes each, and return a pointer to that */void *s_mp_alloc(size_t nb, size_t ni){ return calloc(nb, ni);} /* end s_mp_alloc() */#endif/* }}} *//* {{{ s_mp_free(ptr) */#if MP_MACRO == 0/* Free the memory pointed to by ptr */void s_mp_free(void *ptr){ if(ptr) free(ptr);} /* end s_mp_free() */#endif/* }}} *//* {{{ s_mp_clamp(mp) *//* Remove leading zeroes from the given value */void s_mp_clamp(mp_int *mp){ mp_size du = USED(mp); mp_digit *zp = DIGITS(mp) + du - 1; while(du > 1 && !*zp--) --du; USED(mp) = du;} /* end s_mp_clamp() *//* }}} *//* {{{ s_mp_exch(a, b) *//* Exchange the data for a and b; (b, a) = (a, b) */void s_mp_exch(mp_int *a, mp_int *b){ mp_int tmp; tmp = *a; *a = *b; *b = tmp;} /* end s_mp_exch() *//* }}} *//* }}} *//* {{{ Arithmetic helpers *//* {{{ s_mp_lshd(mp, p) *//* Shift mp leftward by p digits, growing if needed, and zero-filling the in-shifted digits at the right end. This is a convenient alternative to multiplication by powers of the radix */ mp_err s_mp_lshd(mp_int *mp, mp_size p){ mp_err res; mp_size pos; mp_digit *dp; int ix; if(p == 0) return MP_OKAY; if((res = s_mp_pad(mp, USED(mp) + p)) != MP_OKAY) return res; pos = USED(mp) - 1; dp = DIGITS(mp); /* Shift all the significant figures over as needed */ for(ix = pos - p; ix >= 0; ix--) dp[ix + p] = dp[ix]; /* Fill the bottom digits with zeroes */ for(ix = 0; ix < p; ix++) dp[ix] = 0; return MP_OKAY;} /* end s_mp_lshd() *//* }}} *//* {{{ s_mp_rshd(mp, p) *//* Shift mp rightward by p digits. Maintains the invariant that digits above the precision are all zero. Digits shifted off the end are lost. Cannot fail. */void s_mp_rshd(mp_int *mp, mp_size p){ mp_size ix; mp_digit *dp; if(p == 0) return; /* Shortcut when all digits are to be shifted off */ if(p >= USED(mp)) { s_mp_setz(DIGITS(mp), ALLOC(mp)); USED(mp) = 1; SIGN(mp) = MP_ZPOS; return; } /* Shift all the significant figures over as needed */ dp = DIGITS(mp); for(ix = p; ix < USED(mp); ix++) dp[ix - p] = dp[ix]; /* Fill the top digits with zeroes */ ix -= p; while(ix < USED(mp)) dp[ix++] = 0; /* Strip off any leading zeroes */ s_mp_clamp(mp);} /* end s_mp_rshd() *//* }}} *//* {{{ s_mp_div_2(mp) *//* Divide by two -- take advantage of radix properties to do it fast */void s_mp_div_2(mp_int *mp){ s_mp_div_2d(mp, 1);} /* end s_mp_div_2() *//* }}} *//* {{{ s_mp_mul_2(mp) */mp_err s_mp_mul_2(mp_int *mp){ int ix; mp_digit kin = 0, kout, *dp = DIGITS(mp); mp_err res; /* Shift digits leftward by 1 bit */ for(ix = 0; ix < USED(mp); ix++) { kout = (dp[ix] >> (DIGIT_BIT - 1)) & 1; dp[ix] = (dp[ix] << 1) | kin; kin = kout; } /* Deal with rollover from last digit */ if(kin) { if(ix >= ALLOC(mp)) { if((res = s_mp_grow(mp, ALLOC(mp) + 1)) != MP_OKAY) return res; dp = DIGITS(mp); } dp[ix] = kin; USED(mp) += 1; } return MP_OKAY;} /* end s_mp_mul_2() *//* }}} *//* {{{ s_mp_mod_2d(mp, d) *//* Remainder the integer by 2^d, where d is a number of bits. This amounts to a bitwise AND of the value, and does not require the full division code */void s_mp_mod_2d(mp_int *mp, mp_digit d){ unsigned int ndig = (d / DIGIT_BIT), nbit = (d % DIGIT_BIT); unsigned int ix; mp_digit dmask, *dp = DIGITS(mp); if(ndig >= USED(mp)) return; /* Flush all the bits above 2^d in its digit */ dmask = (1 << nbit) - 1; dp[ndig] &= dmask; /* Flush all digits above the one with 2^d in it */ for(ix = ndig + 1; ix < USED(mp); ix++) dp[ix] = 0; s_mp_clamp(mp);} /* end s_mp_mod_2d() *//* }}} *//* {{{ s_mp_mul_2d(mp, d) *//* Multiply by the integer 2^d, where d is a number of bits. This amounts to a bitwise shift of the value, and does not require the full multiplication code. */mp_err s_mp_mul_2d(mp_int *mp, mp_digit d){ mp_err res; mp_digit save, next, mask, *dp; mp_size used; int ix; if((res = s_mp_lshd(mp, d / DIGIT_BIT)) != MP_OKAY) return res; dp = DIGITS(mp); used = USED(mp); d %= DIGIT_BIT; mask = (1 << d) - 1; /* If the shift requires another digit, make sure we've got one to work with */ if((dp[used - 1] >> (DIGIT_BIT - d)) & mask) { if((res = s_mp_grow(mp, used + 1)) != MP_OKAY) return res; dp = DIGITS(mp); } /* Do the shifting... */ save = 0; for(ix = 0; ix < used; ix++) { next = (dp[ix] >> (DIGIT_BIT - d)) & mask; dp[ix] = (dp[ix] << d) | save; save = next; } /* If, at this point, we have a nonzero carryout into the next digit, we'll increase the size by one digit, and store it... */ if(save) { dp[used] = save; USED(mp) += 1; } s_mp_clamp(mp); return MP_OKAY;} /* end s_mp_mul_2d() *//* }}} *//* {{{ s_mp_div_2d(mp, d) *//* Divide the integer by 2^d, where d is a number of bits. This amounts to a bitwise shift of the value, and does not require the full division code (used in Barrett reduction, see below) */void s_mp_div_2d(mp_int *mp, mp_digit d){ int ix; mp_digit save, next, mask, *dp = DIGITS(mp); s_mp_rshd(mp, d / DIGIT_BIT); d %= DIGIT_BIT; mask = (1 << d) - 1; save = 0; for(ix = USED(mp) - 1; ix >= 0; ix--) { next = dp[ix] & mask; dp[ix] = (dp[ix] >> d) | (save << (DIGIT_BIT - d)); save = next; } s_mp_clamp(mp);} /* end s_mp_div_2d() *//* }}} *//* {{{ s_mp_norm(a, b) *//* s_mp_norm(a, b) Normalize a and b for division, where b is the divisor. In order that we might make good guesses for quotient digits, we want the leading digit of b to be at least half the radix, which we accomplish by multiplying a and b by a constant. This constant is returned (so that it can be divided back out of the remainder at the end of the division process). We multiply by the smallest power of 2 that gives us a leading digit at least half the radix. By choosing a power of 2, we simplify the multiplication and division steps to simple shifts. */mp_digit s_mp_norm(mp_int *a, mp_int *b){ mp_digit t, d = 0; t = DIGIT(b, USED(b) - 1); while(t < (RADIX / 2)) { t <<= 1; ++d; } if(d != 0) { s_mp_mul_2d(a, d); s_mp_mul_2d(b, d); } return d;} /* end s_mp_norm() *//* }}} *//* }}} *//* {{{ Primitive digit arithmetic *//* {{{ s_mp_add_d(mp, d) *//* Add d to |mp| in place */mp_err s_mp_add_d(mp_int *mp, mp_digit d) /* unsigned digit addition */{ mp_word w, k = 0; mp_size ix = 1, used = USED(mp); mp_digit *dp = DIGITS(mp); w = dp[0] + d; dp[0] = ACCUM(w); k = CARRYOUT(w); while(ix < used && k) { w = dp[ix] + k; dp[ix] = ACCUM(w); k = CARRYOUT(w); ++ix; } if(k != 0) { mp_err res; if((res = s_mp_pad(mp, USED(mp) + 1)) != MP_OKAY) return res; DIGIT(mp, ix) = k; } return MP_OKAY;} /* end s_mp_add_d() *//* }}} *//* {{{ s_mp_sub_d(mp, d) *//* Subtract d from |mp| in place, assumes |mp| > d */mp_err s_mp_sub_d(mp_int *mp, mp_digit d) /* unsigned digit subtract */{ mp_word w, b = 0; mp_size ix = 1, used = USED(mp); mp_digit *dp = DIGITS(mp); /* Compute initial subtraction */ w = (RADIX + dp[0]) - d; b = CARRYOUT(w) ? 0 : 1; dp[0] = ACCUM(w); /* Propagate borrows leftward */ while(b && ix < used) { w = (RADIX + dp[ix]) - b; b = CARRYOUT(w) ? 0 : 1; dp[ix] = ACCUM(w); ++ix; } /* Remove leading zeroes */ s_mp_clamp(mp); /* If we have a borrow out, it's a violation of the input invariant */ if(b) return MP_RANGE; else return MP_OKAY;} /* end s_mp_sub_d() *//* }}} *//* {{{ s_mp_mul_d(a, d) *//* Compute a = a * d, single digit multiplication */mp_err s_mp_mul_d(mp_int *a, mp_digit d){ mp_word w, k = 0; mp_size ix, max; mp_err res; mp_digit *dp = DIGITS(a); /* Single-digit multiplication will increase the precision of the output by at most one digit. However, we can detect when this will happen -- if the high-order digit of a, times d, gives a two-digit result, then the precision of the result will increase; otherwise it won't. We use this fact to avoid calling s_mp_pad() unless absolutely necessary. */ max = USED(a); w = dp[max - 1] * d; if(CARRYOUT(w) != 0) { if((res = s_mp_pad(a, max + 1)) != MP_OKAY) return res; dp = DIGITS(a); } for(ix = 0; ix < max; ix++) { w = (dp[ix] * d) + k; dp[ix] = ACCUM(w); k = CARRYOUT(w); } /* If there is a precision increase, take care of it here; the above test guarantees we have enough storage to do this safely. */ if(k) { dp[max] = k; USED(a) = max + 1; } s_mp_clamp(a); return MP_OKAY; } /* end s_mp_mul_d() *//* }}} *//* {{{ s_mp_div_d(mp, d, r) *//* s_mp_div_d(mp, d, r) Compute the quotient mp = mp / d and remainder r = mp mod d, for a single digit d. If r is null, the remainder will be discarded. */mp_err s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r){ mp_word w = 0, t; mp_int quot; mp_err res; mp_digit *dp = DIGITS(mp), *qp; int ix; if(d == 0) return MP_RANGE; /* Make room for the quotient */ if((res = mp_init_size(", USED(mp))) != MP_OKAY) return res; USED(") = USED(mp); /* so clamping will work below */ qp = DIGITS("); /* Divide without subtraction */ for(ix = USED(mp) - 1; ix >= 0; ix--) { w = (w << DIGIT_BIT) | dp[ix]; if(w >= d) { t = w / d; w = w % d; } else { t = 0; } qp[ix] = t; } /* Deliver the remainder, if desired */ if(r) *r = w; s_mp_clamp("); mp_exch(", mp); mp_clear("); return MP_OKAY;} /* end s_mp_div_d() *//* }}} *//* }}} *//* {{{ Primitive full arithmetic *//* {{{ s_mp_add(a, b) *//* Compute a = |a| + |b| */mp_err s_mp_add(mp_int *a, mp_int *b) /* magnitude addition */{ mp_word w = 0; mp_digit *pa, *pb; mp_size ix
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -