📄 mytest01.c
字号:
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;
}
/* set a 32-bit const 本函数调用函数:mp_zero, mp_clamp mp_mul_2d */
int mp_set_int (mp_int * a, unsigned long b)
{
int x, res;
mp_zero (a);
/* set four bits at a time */
for (x = 0; x < 8; x++) {
/* shift the number up four bits */
if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) {
return res;
}
/* OR in the top four bits of the source */
a->dp[0] |= (b >> 28) & 15;
/* shift the source up to the next four bits */
b <<= 4;
/* ensure that digits are not clamped off */
a->used += 1;
}
mp_clamp (a);
return MP_OKAY;
}
/* read a string [ASCII] in a given radix 本函数调用函数:mp_iszero mp_mul_d, mp_add_d */
int mp_read_radix (mp_int * a, char *str, int radix)
{
int y, res, neg;
char ch;
/* make sure the radix is ok */
if (radix < 2 || radix > 64) {
return MP_VAL;
}
/* if the leading digit is a
* minus set the sign to negative.
*/
if (*str == '-') {
++str;
neg = MP_NEG;
} else {
neg = MP_ZPOS;
}
/* set the integer to the default of zero */
mp_zero (a);
/* process each digit of the string */
while (*str) {
/* if the radix < 36 the conversion is case insensitive
* this allows numbers like 1AB and 1ab to represent the same value
* [e.g. in hex]
*/
ch = (char) ((radix < 36) ? toupper (*str) : *str);
for (y = 0; y < 64; y++) {
if (ch == mp_s_rmap[y]) {
break;
}
}
/* if the char was found in the map
* and is less than the given radix add it
* to the number, otherwise exit the loop.
*/
if (y < radix) {
if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
return res;
}
if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
return res;
}
} else {
break;
}
++str;
}
/* set the sign only if a != 0 */
if (mp_iszero(a) != 1) {
a->sign = neg;
}
return MP_OKAY;
}
/* shift right by a certain bit count (store quotient in c, optional remainder in d)
调用:mp_copy, mp_zero, mp_init, mp_clear, mp_rshd
mp_mod_2d,
*/
int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
{
mp_digit D, r, rr;
int x, res;
mp_int t;
/* if the shift count is <= 0 then we do no work */
if (b <= 0) {
res = mp_copy (a, c);
if (d != NULL) {
mp_zero (d);
}
return res;
}
if ((res = mp_init (&t)) != MP_OKAY) {
return res;
}
/* get the remainder */
if (d != NULL) {
if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
mp_clear (&t);
return res;
}
}
/* copy */
if ((res = mp_copy (a, c)) != MP_OKAY) {
mp_clear (&t);
return res;
}
/* shift by as many digits in the bit count */
if (b >= (int)DIGIT_BIT) {
mp_rshd (c, b / DIGIT_BIT);
}
/* shift any bit count < DIGIT_BIT */
D = (mp_digit) (b % DIGIT_BIT);
if (D != 0) {
register mp_digit *tmpc, mask, shift;
/* mask */
mask = (((mp_digit)1) << D) - 1;
/* shift for lsb */
shift = DIGIT_BIT - D;
/* alias */
tmpc = c->dp + (c->used - 1);
/* carry */
r = 0;
for (x = c->used - 1; x >= 0; x--) {
/* get the lower bits of this word in a temp */
rr = *tmpc & mask;
/* shift the current word and mix in the carry bits from the previous word */
*tmpc = (*tmpc >> D) | (r << shift);
--tmpc;
/* set the carry to the carry bits of the current word found above */
r = rr;
}
}
mp_clamp (c);
if (d != NULL) {
mp_exch (&t, d);
}
mp_clear (&t);
return MP_OKAY;
}
/////////////////////////////////////////////////////////////
//mp_add_d与mp_sub_d互相调用
//
/* single digit addition
调用:mp_grow, mp_clamp
mp_sub_d
*/
int mp_add_d (mp_int * a, mp_digit b, mp_int * c)
{
int res, ix, oldused;
mp_digit *tmpa, *tmpc, mu;
/* grow c as required */
if (c->alloc < a->used + 1) {
if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
return res;
}
}
/* if a is negative and |a| >= b, call c = |a| - b */
if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) {
/* temporarily fix sign of a */
a->sign = MP_ZPOS;
/* c = |a| - b */
res = mp_sub_d(a, b, c);
/* fix sign */
a->sign = c->sign = MP_NEG;
return res;
}
/* old number of used digits in c */
oldused = c->used;
/* sign always positive */
c->sign = MP_ZPOS;
/* source alias */
tmpa = a->dp;
/* destination alias */
tmpc = c->dp;
/* if a is positive */
if (a->sign == MP_ZPOS) {
/* add digit, after this we're propagating
* the carry.
*/
*tmpc = *tmpa++ + b;
mu = *tmpc >> DIGIT_BIT;
*tmpc++ &= MP_MASK;
/* now handle rest of the digits */
for (ix = 1; ix < a->used; ix++) {
*tmpc = *tmpa++ + mu;
mu = *tmpc >> DIGIT_BIT;
*tmpc++ &= MP_MASK;
}
/* set final carry */
ix++;
*tmpc++ = mu;
/* setup size */
c->used = a->used + 1;
} else {
/* a was negative and |a| < b */
c->used = 1;
/* the result is a single digit */
if (a->used == 1) {
*tmpc++ = b - a->dp[0];
} else {
*tmpc++ = b;
}
/* setup count so the clearing of oldused
* can fall through correctly
*/
ix = 1;
}
/* now zero to oldused */
while (ix++ < oldused) {
*tmpc++ = 0;
}
mp_clamp(c);
return MP_OKAY;
}
/* single digit subtraction
调用:mp_grow, mp_clamp
mp_add_d
*/
int
mp_sub_d (mp_int * a, mp_digit b, mp_int * c)
{
mp_digit *tmpa, *tmpc, mu;
int res, ix, oldused;
/* grow c as required */
if (c->alloc < a->used + 1) {
if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
return res;
}
}
/* if a is negative just do an unsigned
* addition [with fudged signs]
*/
if (a->sign == MP_NEG) {
a->sign = MP_ZPOS;
res = mp_add_d(a, b, c);
a->sign = c->sign = MP_NEG;
return res;
}
/* setup regs */
oldused = c->used;
tmpa = a->dp;
tmpc = c->dp;
/* if a <= b simply fix the single digit */
if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) {
if (a->used == 1) {
*tmpc++ = b - *tmpa;
} else {
*tmpc++ = b;
}
ix = 1;
/* negative/1digit */
c->sign = MP_NEG;
c->used = 1;
} else {
/* positive/size */
c->sign = MP_ZPOS;
c->used = a->used;
/* subtract first digit */
*tmpc = *tmpa++ - b;
mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
*tmpc++ &= MP_MASK;
/* handle rest of the digits */
for (ix = 1; ix < a->used; ix++) {
*tmpc = *tmpa++ - mu;
mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
*tmpc++ &= MP_MASK;
}
}
/* zero excess digits */
while (ix++ < oldused) {
*tmpc++ = 0;
}
mp_clamp(c);
return MP_OKAY;
}
/* single digit division (based on routine from MPI)
调用:mp_copy, mp_iszero, s_is_power_of_two
mp_div_2d, mp_div_3
*/
int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
{
mp_int q;
mp_word w;
mp_digit t;
int res, ix;
/* cannot divide by zero */
if (b == 0) {
return MP_VAL;
}
/* quick outs */
if (b == 1 || mp_iszero(a) == 1) {
if (d != NULL) {
*d = 0;
}
if (c != NULL) {
return mp_copy(a, c);
}
return MP_OKAY;
}
/* power of two ? */
if (s_is_power_of_two(b, &ix) == 1) {
if (d != NULL) {
*d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
}
if (c != NULL) {
return mp_div_2d(a, ix, c, NULL);
}
return MP_OKAY;
}
#ifdef BN_MP_DIV_3_C
/* three? */
if (b == 3) {
return mp_div_3(a, c, d);
}
#endif
/* no easy answer [c'est la vie]. Just division */
if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
return res;
}
q.used = a->used;
q.sign = a->sign;
w = 0;
for (ix = a->used - 1; ix >= 0; ix--) {
w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
if (w >= b) {
t = (mp_digit)(w / b);
w -= ((mp_word)t) * ((mp_word)b);
} else {
t = 0;
}
q.dp[ix] = (mp_digit)t;
}
if (d != NULL) {
*d = (mp_digit)w;
}
if (c != NULL) {
mp_clamp(&q);
mp_exch(&q, c);
}
mp_clear(&q);
return res;
}
/* stores a bignum as a ASCII string in a given radix (2..64)
本函数调用函数:mp_iszero, mp_init_copy, mp_clear, bn_reverse
mp_div_d
*/
int mp_toradix (mp_int * a, char *str, int radix)
{
int res, digs;
mp_int t;
mp_digit d;
char *_s = str;
/* check range of the radix */
if (radix < 2 || radix > 64) {
return MP_VAL;
}
/* quick out if its zero */
if (mp_iszero(a) == 1) {
*str++ = '0';
*str = '\0';
return MP_OKAY;
}
if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
return res;
}
/* if it is negative output a - */
if (t.sign == MP_NEG) {
++_s;
*str++ = '-';
t.sign = MP_ZPOS;
}
digs = 0;
while (mp_iszero (&t) == 0) {
if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
mp_clear (&t);
return res;
}
*str++ = mp_s_rmap[d];
++digs;
}
/* reverse the digits of the string. In this case _s points
* to the first digit [exluding the sign] of the number]
*/
bn_reverse ((unsigned char *)_s, digs);
/* append a NULL so the string is properly terminated */
*str = '\0';
mp_clear (&t);
return MP_OKAY;
}
////////////////////////////////////////////////////////////////////////////////////
//加、减法:
//用到:s_mp_sub,mp_cmp_mag,s_mp_add,
/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
int
s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
{
int olduse, res, min, max;
/* find sizes */
min = b->used;
max = a->used;
/* init result */
if (c->alloc < max) {
if ((res = mp_grow (c, max)) != MP_OKAY) {
return res;
}
}
olduse = c->used;
c->used = max;
{
register mp_digit u, *tmpa, *tmpb, *tmpc;
register int i;
/* alias for digit pointers */
tmpa = a->dp;
tmpb = b->dp;
tmpc = c->dp;
/* set carry to zero */
u = 0;
for (i = 0; i < min; i++) {
/* T[i] = A[i] - B[i] - U */
*tmpc = *tmpa++ - *tmpb++ - u;
/* U = carry bit of T[i]
* Note this saves performing an AND operation since
* if a carry does occur it will propagate all the way to the
* MSB. As a result a single shift is enough to get the carry
*/
u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
/* Clear carry from T[i] */
*tmpc++ &= MP_MASK;
}
/* now copy higher words if any, e.g. if A has more digits than B */
for (; i < max; i++) {
/* T[i] = A[i] - U */
*tmpc = *tmpa++ - u;
/* U = carry bit of T[i] */
u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
/* Clear carry from T[i] */
*tmpc++ &= MP_MASK;
}
/* clear digits above used (since we may not have grown result above) */
for (i = c->used; i < olduse; i++) {
*tmpc++ = 0;
}
}
mp_clamp (c);
return MP_OKAY;
}
/* low level addition, based on HAC pp.594, Algorithm 14.7 */
int
s_mp_add (mp_int * a, mp_int * b, mp_int * c)
{
mp_int *x;
int olduse, res, min, max;
/* find sizes, we let |a| <= |b| which means we have to sort
* them. "x" will point to the input with the most digits
*/
if (a->used > b->used) {
min = b->used;
max = a->used;
x = a;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -