simplifications: basic arithmetic functions
This commit is contained in:
parent
e60149dec7
commit
143e0376a1
37
mp_add_d.c
37
mp_add_d.c
@ -6,9 +6,7 @@
|
||||
/* single digit addition */
|
||||
mp_err mp_add_d(const mp_int *a, mp_digit b, mp_int *c)
|
||||
{
|
||||
mp_err err;
|
||||
int ix, oldused;
|
||||
mp_digit *tmpa, *tmpc;
|
||||
int oldused;
|
||||
|
||||
/* fast path for a == c */
|
||||
if (a == c) {
|
||||
@ -27,6 +25,7 @@ mp_err mp_add_d(const mp_int *a, mp_digit b, mp_int *c)
|
||||
|
||||
/* grow c as required */
|
||||
if (c->alloc < (a->used + 1)) {
|
||||
mp_err err;
|
||||
if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) {
|
||||
return err;
|
||||
}
|
||||
@ -34,6 +33,7 @@ mp_err mp_add_d(const mp_int *a, mp_digit b, mp_int *c)
|
||||
|
||||
/* if a is negative and |a| >= b, call c = |a| - b */
|
||||
if ((a->sign == MP_NEG) && ((a->used > 1) || (a->dp[0] >= b))) {
|
||||
mp_err err;
|
||||
mp_int a_ = *a;
|
||||
/* temporarily fix sign of a */
|
||||
a_.sign = MP_ZPOS;
|
||||
@ -53,24 +53,18 @@ mp_err mp_add_d(const mp_int *a, mp_digit b, mp_int *c)
|
||||
/* old number of used digits in c */
|
||||
oldused = c->used;
|
||||
|
||||
/* source alias */
|
||||
tmpa = a->dp;
|
||||
|
||||
/* destination alias */
|
||||
tmpc = c->dp;
|
||||
|
||||
/* if a is positive */
|
||||
if (a->sign == MP_ZPOS) {
|
||||
/* add digits, mu is carry */
|
||||
int i;
|
||||
mp_digit mu = b;
|
||||
for (ix = 0; ix < a->used; ix++) {
|
||||
*tmpc = *tmpa++ + mu;
|
||||
mu = *tmpc >> MP_DIGIT_BIT;
|
||||
*tmpc++ &= MP_MASK;
|
||||
for (i = 0; i < a->used; i++) {
|
||||
c->dp[i] = a->dp[i] + mu;
|
||||
mu = c->dp[i] >> MP_DIGIT_BIT;
|
||||
c->dp[i] &= MP_MASK;
|
||||
}
|
||||
/* set final carry */
|
||||
ix++;
|
||||
*tmpc++ = mu;
|
||||
c->dp[i] = mu;
|
||||
|
||||
/* setup size */
|
||||
c->used = a->used + 1;
|
||||
@ -79,23 +73,14 @@ mp_err mp_add_d(const mp_int *a, mp_digit b, mp_int *c)
|
||||
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;
|
||||
c->dp[0] = (a->used == 1) ? b - a->dp[0] : b;
|
||||
}
|
||||
|
||||
/* sign always positive */
|
||||
c->sign = MP_ZPOS;
|
||||
|
||||
/* now zero to oldused */
|
||||
MP_ZERO_DIGITS(tmpc, oldused - ix);
|
||||
MP_ZERO_DIGITS(c->dp + c->used, oldused - c->used);
|
||||
mp_clamp(c);
|
||||
|
||||
return MP_OKAY;
|
||||
|
17
mp_div_2.c
17
mp_div_2.c
@ -7,11 +7,10 @@
|
||||
mp_err mp_div_2(const mp_int *a, mp_int *b)
|
||||
{
|
||||
int x, oldused;
|
||||
mp_digit r, rr, *tmpa, *tmpb;
|
||||
mp_err err;
|
||||
mp_digit r;
|
||||
|
||||
/* copy */
|
||||
if (b->alloc < a->used) {
|
||||
mp_err err;
|
||||
if ((err = mp_grow(b, a->used)) != MP_OKAY) {
|
||||
return err;
|
||||
}
|
||||
@ -20,20 +19,14 @@ mp_err mp_div_2(const mp_int *a, mp_int *b)
|
||||
oldused = b->used;
|
||||
b->used = a->used;
|
||||
|
||||
/* 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--) {
|
||||
for (x = b->used; x --> 0;) {
|
||||
/* get the carry for the next iteration */
|
||||
rr = *tmpa & 1u;
|
||||
mp_digit rr = a->dp[x] & 1u;
|
||||
|
||||
/* shift the current digit, add in carry and store */
|
||||
*tmpb-- = (*tmpa-- >> 1) | (r << (MP_DIGIT_BIT - 1));
|
||||
b->dp[x] = (a->dp[x] >> 1) | (r << (MP_DIGIT_BIT - 1));
|
||||
|
||||
/* forward carry to next iteration */
|
||||
r = rr;
|
||||
|
34
mp_div_2d.c
34
mp_div_2d.c
@ -6,23 +6,16 @@
|
||||
/* shift right by a certain bit count (store quotient in c, optional remainder in d) */
|
||||
mp_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d)
|
||||
{
|
||||
mp_digit D, r, rr;
|
||||
int x;
|
||||
mp_err err;
|
||||
|
||||
/* if the shift count is <= 0 then we do no work */
|
||||
if (b <= 0) {
|
||||
err = mp_copy(a, c);
|
||||
if (d != NULL) {
|
||||
mp_zero(d);
|
||||
}
|
||||
return err;
|
||||
if (b < 0) {
|
||||
return MP_VAL;
|
||||
}
|
||||
|
||||
/* copy */
|
||||
if ((err = mp_copy(a, c)) != MP_OKAY) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* 'a' should not be used after here - it might be the same as d */
|
||||
|
||||
/* get the remainder */
|
||||
@ -38,28 +31,25 @@ mp_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d)
|
||||
}
|
||||
|
||||
/* shift any bit count < MP_DIGIT_BIT */
|
||||
D = (mp_digit)(b % MP_DIGIT_BIT);
|
||||
if (D != 0u) {
|
||||
mp_digit *tmpc, mask, shift;
|
||||
b %= MP_DIGIT_BIT;
|
||||
if (b != 0u) {
|
||||
int x;
|
||||
mp_digit r, mask, shift;
|
||||
|
||||
/* mask */
|
||||
mask = ((mp_digit)1 << D) - 1uL;
|
||||
mask = ((mp_digit)1 << b) - 1uL;
|
||||
|
||||
/* shift for lsb */
|
||||
shift = (mp_digit)MP_DIGIT_BIT - D;
|
||||
|
||||
/* alias */
|
||||
tmpc = c->dp + (c->used - 1);
|
||||
shift = (mp_digit)(MP_DIGIT_BIT - b);
|
||||
|
||||
/* carry */
|
||||
r = 0;
|
||||
for (x = c->used - 1; x >= 0; x--) {
|
||||
for (x = c->used; x --> 0;) {
|
||||
/* get the lower bits of this word in a temp */
|
||||
rr = *tmpc & mask;
|
||||
mp_digit rr = c->dp[x] & mask;
|
||||
|
||||
/* shift the current word and mix in the carry bits from the previous word */
|
||||
*tmpc = (*tmpc >> D) | (r << shift);
|
||||
--tmpc;
|
||||
c->dp[x] = (c->dp[x] >> b) | (r << shift);
|
||||
|
||||
/* set the carry to the carry bits of the current word found above */
|
||||
r = rr;
|
||||
|
@ -8,7 +8,6 @@ mp_err mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d)
|
||||
{
|
||||
mp_int q;
|
||||
mp_word w;
|
||||
mp_digit t;
|
||||
mp_err err;
|
||||
int ix;
|
||||
|
||||
@ -56,14 +55,12 @@ mp_err mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d)
|
||||
q.used = a->used;
|
||||
q.sign = a->sign;
|
||||
w = 0;
|
||||
for (ix = a->used - 1; ix >= 0; ix--) {
|
||||
for (ix = a->used; ix --> 0;) {
|
||||
mp_digit t = 0;
|
||||
w = (w << (mp_word)MP_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] = t;
|
||||
}
|
||||
@ -78,7 +75,7 @@ mp_err mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d)
|
||||
}
|
||||
mp_clear(&q);
|
||||
|
||||
return err;
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
16
mp_mul.c
16
mp_mul.c
@ -7,8 +7,8 @@
|
||||
mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c)
|
||||
{
|
||||
mp_err err;
|
||||
int min_len = MP_MIN(a->used, b->used),
|
||||
max_len = MP_MAX(a->used, b->used),
|
||||
int min = MP_MIN(a->used, b->used),
|
||||
max = MP_MAX(a->used, b->used),
|
||||
digs = a->used + b->used + 1;
|
||||
mp_sign neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
|
||||
|
||||
@ -20,16 +20,16 @@ mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c)
|
||||
* Using it to cut the input into slices small enough for s_mp_mul_digs_fast
|
||||
* was actually slower on the author's machine, but YMMV.
|
||||
*/
|
||||
(min_len >= MP_KARATSUBA_MUL_CUTOFF) &&
|
||||
((max_len / 2) >= MP_KARATSUBA_MUL_CUTOFF) &&
|
||||
(min >= MP_KARATSUBA_MUL_CUTOFF) &&
|
||||
((max / 2) >= MP_KARATSUBA_MUL_CUTOFF) &&
|
||||
/* Not much effect was observed below a ratio of 1:2, but again: YMMV. */
|
||||
(max_len >= (2 * min_len))) {
|
||||
(max >= (2 * min))) {
|
||||
err = s_mp_balance_mul(a,b,c);
|
||||
} else if (MP_HAS(S_MP_TOOM_MUL) &&
|
||||
(min_len >= MP_TOOM_MUL_CUTOFF)) {
|
||||
(min >= MP_TOOM_MUL_CUTOFF)) {
|
||||
err = s_mp_toom_mul(a, b, c);
|
||||
} else if (MP_HAS(S_MP_KARATSUBA_MUL) &&
|
||||
(min_len >= MP_KARATSUBA_MUL_CUTOFF)) {
|
||||
(min >= MP_KARATSUBA_MUL_CUTOFF)) {
|
||||
err = s_mp_karatsuba_mul(a, b, c);
|
||||
} else if (MP_HAS(S_MP_MUL_DIGS_FAST) &&
|
||||
/* can we use the fast multiplier?
|
||||
@ -39,7 +39,7 @@ mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c)
|
||||
* digits won't affect carry propagation
|
||||
*/
|
||||
(digs < MP_WARRAY) &&
|
||||
(min_len <= MP_MAXFAST)) {
|
||||
(min <= MP_MAXFAST)) {
|
||||
err = s_mp_mul_digs_fast(a, b, c, digs);
|
||||
} else if (MP_HAS(S_MP_MUL_DIGS)) {
|
||||
err = s_mp_mul_digs(a, b, c, digs);
|
||||
|
21
mp_mul_2.c
21
mp_mul_2.c
@ -7,10 +7,11 @@
|
||||
mp_err mp_mul_2(const mp_int *a, mp_int *b)
|
||||
{
|
||||
int x, oldused;
|
||||
mp_err err;
|
||||
mp_digit r;
|
||||
|
||||
/* grow to accomodate result */
|
||||
if (b->alloc < (a->used + 1)) {
|
||||
mp_err err;
|
||||
if ((err = mp_grow(b, a->used + 1)) != MP_OKAY) {
|
||||
return err;
|
||||
}
|
||||
@ -19,15 +20,6 @@ mp_err mp_mul_2(const mp_int *a, mp_int *b)
|
||||
oldused = b->used;
|
||||
b->used = a->used;
|
||||
|
||||
{
|
||||
mp_digit r, rr, *tmpa, *tmpb;
|
||||
|
||||
/* alias for source */
|
||||
tmpa = a->dp;
|
||||
|
||||
/* alias for dest */
|
||||
tmpb = b->dp;
|
||||
|
||||
/* carry */
|
||||
r = 0;
|
||||
for (x = 0; x < a->used; x++) {
|
||||
@ -35,10 +27,10 @@ mp_err mp_mul_2(const mp_int *a, mp_int *b)
|
||||
/* get what will be the *next* carry bit from the
|
||||
* MSB of the current digit
|
||||
*/
|
||||
rr = *tmpa >> (mp_digit)(MP_DIGIT_BIT - 1);
|
||||
mp_digit rr = a->dp[x] >> (mp_digit)(MP_DIGIT_BIT - 1);
|
||||
|
||||
/* now shift up this digit, add in the carry [from the previous] */
|
||||
*tmpb++ = ((*tmpa++ << 1uL) | r) & MP_MASK;
|
||||
b->dp[x] = ((a->dp[x] << 1uL) | r) & MP_MASK;
|
||||
|
||||
/* copy the carry that would be from the source
|
||||
* digit into the next iteration
|
||||
@ -49,15 +41,14 @@ mp_err mp_mul_2(const mp_int *a, mp_int *b)
|
||||
/* new leading digit? */
|
||||
if (r != 0u) {
|
||||
/* add a MSB which is always 1 at this point */
|
||||
*tmpb = 1;
|
||||
++(b->used);
|
||||
b->dp[b->used++] = 1;
|
||||
}
|
||||
|
||||
/* now zero any excess digits on the destination
|
||||
* that we didn't write to
|
||||
*/
|
||||
MP_ZERO_DIGITS(b->dp + b->used, oldused - b->used);
|
||||
}
|
||||
|
||||
b->sign = a->sign;
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
27
mp_mul_2d.c
27
mp_mul_2d.c
@ -6,17 +6,19 @@
|
||||
/* shift left by a certain bit count */
|
||||
mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c)
|
||||
{
|
||||
mp_digit d;
|
||||
mp_err err;
|
||||
if (b < 0) {
|
||||
return MP_VAL;
|
||||
}
|
||||
|
||||
/* copy */
|
||||
if (a != c) {
|
||||
mp_err err;
|
||||
if ((err = mp_copy(a, c)) != MP_OKAY) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (c->alloc < (c->used + (b / MP_DIGIT_BIT) + 1)) {
|
||||
mp_err err;
|
||||
if ((err = mp_grow(c, c->used + (b / MP_DIGIT_BIT) + 1)) != MP_OKAY) {
|
||||
return err;
|
||||
}
|
||||
@ -24,35 +26,32 @@ mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c)
|
||||
|
||||
/* shift by as many digits in the bit count */
|
||||
if (b >= MP_DIGIT_BIT) {
|
||||
mp_err err;
|
||||
if ((err = mp_lshd(c, b / MP_DIGIT_BIT)) != MP_OKAY) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* shift any bit count < MP_DIGIT_BIT */
|
||||
d = (mp_digit)(b % MP_DIGIT_BIT);
|
||||
if (d != 0u) {
|
||||
mp_digit *tmpc, shift, mask, r, rr;
|
||||
b %= MP_DIGIT_BIT;
|
||||
if (b != 0u) {
|
||||
mp_digit shift, mask, r;
|
||||
int x;
|
||||
|
||||
/* bitmask for carries */
|
||||
mask = ((mp_digit)1 << d) - (mp_digit)1;
|
||||
mask = ((mp_digit)1 << b) - (mp_digit)1;
|
||||
|
||||
/* shift for msbs */
|
||||
shift = (mp_digit)MP_DIGIT_BIT - d;
|
||||
|
||||
/* alias */
|
||||
tmpc = c->dp;
|
||||
shift = (mp_digit)(MP_DIGIT_BIT - b);
|
||||
|
||||
/* carry */
|
||||
r = 0;
|
||||
for (x = 0; x < c->used; x++) {
|
||||
/* get the higher bits of the current word */
|
||||
rr = (*tmpc >> shift) & mask;
|
||||
mp_digit rr = (c->dp[x] >> shift) & mask;
|
||||
|
||||
/* shift the current word and OR in the carry */
|
||||
*tmpc = ((*tmpc << d) | r) & MP_MASK;
|
||||
++tmpc;
|
||||
c->dp[x] = ((c->dp[x] << b) | r) & MP_MASK;
|
||||
|
||||
/* set the carry to the carry bits of the current word */
|
||||
r = rr;
|
||||
|
27
mp_mul_d.c
27
mp_mul_d.c
@ -6,10 +6,9 @@
|
||||
/* multiply by a digit */
|
||||
mp_err mp_mul_d(const mp_int *a, mp_digit b, mp_int *c)
|
||||
{
|
||||
mp_digit u, *tmpa, *tmpc;
|
||||
mp_word r;
|
||||
mp_digit u;
|
||||
mp_err err;
|
||||
int ix, olduse;
|
||||
int ix, oldused;
|
||||
|
||||
/* make sure c is big enough to hold a*b */
|
||||
if (c->alloc < (a->used + 1)) {
|
||||
@ -19,41 +18,35 @@ mp_err mp_mul_d(const mp_int *a, mp_digit b, mp_int *c)
|
||||
}
|
||||
|
||||
/* get the original destinations used count */
|
||||
olduse = c->used;
|
||||
oldused = c->used;
|
||||
|
||||
/* set the sign */
|
||||
c->sign = a->sign;
|
||||
|
||||
/* alias for a->dp [source] */
|
||||
tmpa = a->dp;
|
||||
|
||||
/* alias for c->dp [dest] */
|
||||
tmpc = c->dp;
|
||||
|
||||
/* zero carry */
|
||||
u = 0;
|
||||
|
||||
/* compute columns */
|
||||
for (ix = 0; ix < a->used; ix++) {
|
||||
/* compute product and carry sum for this term */
|
||||
r = (mp_word)u + ((mp_word)*tmpa++ * (mp_word)b);
|
||||
mp_word r = (mp_word)u + ((mp_word)a->dp[ix] * (mp_word)b);
|
||||
|
||||
/* mask off higher bits to get a single digit */
|
||||
*tmpc++ = (mp_digit)(r & (mp_word)MP_MASK);
|
||||
c->dp[ix] = (mp_digit)(r & (mp_word)MP_MASK);
|
||||
|
||||
/* send carry into next iteration */
|
||||
u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT);
|
||||
}
|
||||
|
||||
/* store final carry [if any] and increment ix offset */
|
||||
*tmpc++ = u;
|
||||
++ix;
|
||||
|
||||
/* now zero digits above the top */
|
||||
MP_ZERO_DIGITS(tmpc, olduse - ix);
|
||||
c->dp[ix] = u;
|
||||
|
||||
/* set used count */
|
||||
c->used = a->used + 1;
|
||||
|
||||
/* now zero digits above the top */
|
||||
MP_ZERO_DIGITS(c->dp + c->used, oldused - c->used);
|
||||
|
||||
mp_clamp(c);
|
||||
|
||||
return MP_OKAY;
|
||||
|
27
mp_sub_d.c
27
mp_sub_d.c
@ -6,9 +6,7 @@
|
||||
/* single digit subtraction */
|
||||
mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c)
|
||||
{
|
||||
mp_digit *tmpa, *tmpc;
|
||||
mp_err err;
|
||||
int ix, oldused;
|
||||
int oldused;
|
||||
|
||||
/* fast path for a == c */
|
||||
if (a == c) {
|
||||
@ -26,6 +24,7 @@ mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c)
|
||||
|
||||
/* grow c as required */
|
||||
if (c->alloc < (a->used + 1)) {
|
||||
mp_err err;
|
||||
if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) {
|
||||
return err;
|
||||
}
|
||||
@ -35,6 +34,7 @@ mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c)
|
||||
* addition [with fudged signs]
|
||||
*/
|
||||
if (a->sign == MP_NEG) {
|
||||
mp_err err;
|
||||
mp_int a_ = *a;
|
||||
a_.sign = MP_ZPOS;
|
||||
err = mp_add_d(&a_, b, c);
|
||||
@ -46,24 +46,17 @@ mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
c->dp[0] = (a->used == 1) ? b - a->dp[0] : b;
|
||||
|
||||
/* negative/1digit */
|
||||
c->sign = MP_NEG;
|
||||
c->used = 1;
|
||||
} else {
|
||||
int i;
|
||||
mp_digit mu = b;
|
||||
|
||||
/* positive/size */
|
||||
@ -71,15 +64,15 @@ mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c)
|
||||
c->used = a->used;
|
||||
|
||||
/* subtract digits, mu is carry */
|
||||
for (ix = 0; ix < a->used; ix++) {
|
||||
*tmpc = *tmpa++ - mu;
|
||||
mu = *tmpc >> (MP_SIZEOF_BITS(mp_digit) - 1u);
|
||||
*tmpc++ &= MP_MASK;
|
||||
for (i = 0; i < a->used; i++) {
|
||||
c->dp[i] = a->dp[i] - mu;
|
||||
mu = c->dp[i] >> (MP_SIZEOF_BITS(mp_digit) - 1u);
|
||||
c->dp[i] &= MP_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/* zero excess digits */
|
||||
MP_ZERO_DIGITS(tmpc, oldused - ix);
|
||||
MP_ZERO_DIGITS(c->dp + c->used, oldused - c->used);
|
||||
|
||||
mp_clamp(c);
|
||||
return MP_OKAY;
|
||||
|
53
s_mp_add.c
53
s_mp_add.c
@ -6,60 +6,42 @@
|
||||
/* low level addition, based on HAC pp.594, Algorithm 14.7 */
|
||||
mp_err s_mp_add(const mp_int *a, const mp_int *b, mp_int *c)
|
||||
{
|
||||
const mp_int *x;
|
||||
mp_err err;
|
||||
int olduse, min, max;
|
||||
int oldused, min, max, i;
|
||||
mp_digit u;
|
||||
|
||||
/* 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) {
|
||||
if (a->used < b->used) {
|
||||
MP_EXCH(const mp_int *, a, b);
|
||||
}
|
||||
|
||||
min = b->used;
|
||||
max = a->used;
|
||||
x = a;
|
||||
} else {
|
||||
min = a->used;
|
||||
max = b->used;
|
||||
x = b;
|
||||
}
|
||||
|
||||
/* init result */
|
||||
if (c->alloc < (max + 1)) {
|
||||
mp_err err;
|
||||
if ((err = mp_grow(c, max + 1)) != MP_OKAY) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* get old used digit count and set new one */
|
||||
olduse = c->used;
|
||||
oldused = c->used;
|
||||
c->used = max + 1;
|
||||
|
||||
{
|
||||
mp_digit u, *tmpa, *tmpb, *tmpc;
|
||||
int i;
|
||||
|
||||
/* alias for digit pointers */
|
||||
|
||||
/* first input */
|
||||
tmpa = a->dp;
|
||||
|
||||
/* second input */
|
||||
tmpb = b->dp;
|
||||
|
||||
/* destination */
|
||||
tmpc = c->dp;
|
||||
|
||||
/* zero the carry */
|
||||
u = 0;
|
||||
for (i = 0; i < min; i++) {
|
||||
/* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
|
||||
*tmpc = *tmpa++ + *tmpb++ + u;
|
||||
c->dp[i] = a->dp[i] + b->dp[i] + u;
|
||||
|
||||
/* U = carry bit of T[i] */
|
||||
u = *tmpc >> (mp_digit)MP_DIGIT_BIT;
|
||||
u = c->dp[i] >> (mp_digit)MP_DIGIT_BIT;
|
||||
|
||||
/* take away carry bit from T[i] */
|
||||
*tmpc++ &= MP_MASK;
|
||||
c->dp[i] &= MP_MASK;
|
||||
}
|
||||
|
||||
/* now copy higher words if any, that is in A+B
|
||||
@ -67,23 +49,22 @@ mp_err s_mp_add(const mp_int *a, const mp_int *b, mp_int *c)
|
||||
*/
|
||||
if (min != max) {
|
||||
for (; i < max; i++) {
|
||||
/* T[i] = X[i] + U */
|
||||
*tmpc = x->dp[i] + u;
|
||||
/* T[i] = A[i] + U */
|
||||
c->dp[i] = a->dp[i] + u;
|
||||
|
||||
/* U = carry bit of T[i] */
|
||||
u = *tmpc >> (mp_digit)MP_DIGIT_BIT;
|
||||
u = c->dp[i] >> (mp_digit)MP_DIGIT_BIT;
|
||||
|
||||
/* take away carry bit from T[i] */
|
||||
*tmpc++ &= MP_MASK;
|
||||
c->dp[i] &= MP_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/* add carry */
|
||||
*tmpc++ = u;
|
||||
c->dp[i] = u;
|
||||
|
||||
/* clear digits above oldused */
|
||||
MP_ZERO_DIGITS(tmpc, olduse - c->used);
|
||||
}
|
||||
MP_ZERO_DIGITS(c->dp + c->used, oldused - c->used);
|
||||
|
||||
mp_clamp(c);
|
||||
return MP_OKAY;
|
||||
|
26
s_mp_sqr.c
26
s_mp_sqr.c
@ -7,10 +7,8 @@
|
||||
mp_err s_mp_sqr(const mp_int *a, mp_int *b)
|
||||
{
|
||||
mp_int t;
|
||||
int ix, iy, pa;
|
||||
int ix, pa;
|
||||
mp_err err;
|
||||
mp_word r;
|
||||
mp_digit u, tmpx, *tmpt;
|
||||
|
||||
pa = a->used;
|
||||
if ((err = mp_init_size(&t, (2 * pa) + 1)) != MP_OKAY) {
|
||||
@ -21,9 +19,12 @@ mp_err s_mp_sqr(const mp_int *a, mp_int *b)
|
||||
t.used = (2 * pa) + 1;
|
||||
|
||||
for (ix = 0; ix < pa; ix++) {
|
||||
mp_digit u;
|
||||
int iy;
|
||||
|
||||
/* first calculate the digit at 2*ix */
|
||||
/* calculate double precision result */
|
||||
r = (mp_word)t.dp[2*ix] +
|
||||
mp_word r = (mp_word)t.dp[2*ix] +
|
||||
((mp_word)a->dp[ix] * (mp_word)a->dp[ix]);
|
||||
|
||||
/* store lower part in result */
|
||||
@ -32,32 +33,27 @@ mp_err s_mp_sqr(const mp_int *a, mp_int *b)
|
||||
/* get the carry */
|
||||
u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT);
|
||||
|
||||
/* left hand side of A[ix] * A[iy] */
|
||||
tmpx = a->dp[ix];
|
||||
|
||||
/* alias for where to store the results */
|
||||
tmpt = t.dp + ((2 * ix) + 1);
|
||||
|
||||
for (iy = ix + 1; iy < pa; iy++) {
|
||||
/* first calculate the product */
|
||||
r = (mp_word)tmpx * (mp_word)a->dp[iy];
|
||||
r = (mp_word)a->dp[ix] * (mp_word)a->dp[iy];
|
||||
|
||||
/* now calculate the double precision result, note we use
|
||||
* addition instead of *2 since it's easier to optimize
|
||||
*/
|
||||
r = (mp_word)*tmpt + r + r + (mp_word)u;
|
||||
r = (mp_word)t.dp[ix + iy] + r + r + (mp_word)u;
|
||||
|
||||
/* store lower part */
|
||||
*tmpt++ = (mp_digit)(r & (mp_word)MP_MASK);
|
||||
t.dp[ix + iy] = (mp_digit)(r & (mp_word)MP_MASK);
|
||||
|
||||
/* get carry */
|
||||
u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT);
|
||||
}
|
||||
/* propagate upwards */
|
||||
while (u != 0uL) {
|
||||
r = (mp_word)*tmpt + (mp_word)u;
|
||||
*tmpt++ = (mp_digit)(r & (mp_word)MP_MASK);
|
||||
r = (mp_word)t.dp[ix + iy] + (mp_word)u;
|
||||
t.dp[ix + iy] = (mp_digit)(r & (mp_word)MP_MASK);
|
||||
u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT);
|
||||
++iy;
|
||||
}
|
||||
}
|
||||
|
||||
|
35
s_mp_sub.c
35
s_mp_sub.c
@ -6,63 +6,50 @@
|
||||
/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
|
||||
mp_err s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c)
|
||||
{
|
||||
int olduse, min, max;
|
||||
mp_err err;
|
||||
|
||||
/* find sizes */
|
||||
min = b->used;
|
||||
max = a->used;
|
||||
int oldused = c->used, min = b->used, max = a->used, i;
|
||||
mp_digit u;
|
||||
|
||||
/* init result */
|
||||
if (c->alloc < max) {
|
||||
mp_err err;
|
||||
if ((err = mp_grow(c, max)) != MP_OKAY) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
olduse = c->used;
|
||||
|
||||
c->used = max;
|
||||
|
||||
{
|
||||
mp_digit u, *tmpa, *tmpb, *tmpc;
|
||||
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;
|
||||
c->dp[i] = (a->dp[i] - b->dp[i]) - 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_SIZEOF_BITS(mp_digit) - 1u);
|
||||
u = c->dp[i] >> (MP_SIZEOF_BITS(mp_digit) - 1u);
|
||||
|
||||
/* Clear carry from T[i] */
|
||||
*tmpc++ &= MP_MASK;
|
||||
c->dp[i] &= 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;
|
||||
c->dp[i] = a->dp[i] - u;
|
||||
|
||||
/* U = carry bit of T[i] */
|
||||
u = *tmpc >> (MP_SIZEOF_BITS(mp_digit) - 1u);
|
||||
u = c->dp[i] >> (MP_SIZEOF_BITS(mp_digit) - 1u);
|
||||
|
||||
/* Clear carry from T[i] */
|
||||
*tmpc++ &= MP_MASK;
|
||||
c->dp[i] &= MP_MASK;
|
||||
}
|
||||
|
||||
/* clear digits above used (since we may not have grown result above) */
|
||||
MP_ZERO_DIGITS(tmpc, olduse - c->used);
|
||||
}
|
||||
MP_ZERO_DIGITS(c->dp + c->used, oldused - c->used);
|
||||
|
||||
mp_clamp(c);
|
||||
return MP_OKAY;
|
||||
|
Loading…
Reference in New Issue
Block a user