|
3 | 3 | /* LibTomMath, multiple-precision integer library -- Tom St Denis */ |
4 | 4 | /* SPDX-License-Identifier: Unlicense */ |
5 | 5 |
|
6 | | -/* AND two ints together */ |
| 6 | +/* two complement and */ |
7 | 7 | mp_err mp_and(const mp_int *a, const mp_int *b, mp_int *c) |
8 | 8 | { |
9 | | - int ix, px; |
| 9 | + int used = MP_MAX(a->used, b->used) + 1, i; |
10 | 10 | mp_err err; |
11 | | - mp_int t; |
12 | | - const mp_int *x; |
| 11 | + mp_digit ac = 1, bc = 1, cc = 1; |
| 12 | + mp_sign csign = (a->sign == MP_NEG && b->sign == MP_NEG) ? MP_NEG : MP_ZPOS; |
13 | 13 |
|
14 | | - if (a->used > b->used) { |
15 | | - if ((err = mp_init_copy(&t, a)) != MP_OKAY) { |
| 14 | + if (c->alloc < used) { |
| 15 | + if ((err = mp_grow(c, used)) != MP_OKAY) { |
16 | 16 | return err; |
17 | 17 | } |
18 | | - px = b->used; |
19 | | - x = b; |
20 | | - } else { |
21 | | - if ((err = mp_init_copy(&t, b)) != MP_OKAY) { |
22 | | - return err; |
23 | | - } |
24 | | - px = a->used; |
25 | | - x = a; |
26 | 18 | } |
27 | 19 |
|
28 | | - for (ix = 0; ix < px; ix++) { |
29 | | - t.dp[ix] &= x->dp[ix]; |
30 | | - } |
| 20 | + for (i = 0; i < used; i++) { |
| 21 | + mp_digit x, y; |
| 22 | + |
| 23 | + /* convert to two complement if negative */ |
| 24 | + if (a->sign == MP_NEG) { |
| 25 | + ac += i >= a->used ? MP_MASK : ~a->dp[i] & MP_MASK; |
| 26 | + x = ac & MP_MASK; |
| 27 | + ac >>= MP_DIGIT_BIT; |
| 28 | + } else { |
| 29 | + x = i >= a->used ? 0 : a->dp[i]; |
| 30 | + } |
31 | 31 |
|
32 | | - /* zero digits above the last from the smallest mp_int */ |
33 | | - MP_ZERO_DIGITS(t.dp + ix, t.used - ix); |
| 32 | + /* convert to two complement if negative */ |
| 33 | + if (b->sign == MP_NEG) { |
| 34 | + bc += i >= b->used ? MP_MASK : ~b->dp[i] & MP_MASK; |
| 35 | + y = bc & MP_MASK; |
| 36 | + bc >>= MP_DIGIT_BIT; |
| 37 | + } else { |
| 38 | + y = i >= b->used ? 0 : b->dp[i]; |
| 39 | + } |
| 40 | + |
| 41 | + c->dp[i] = x & y; |
| 42 | + |
| 43 | + /* convert to to sign-magnitude if negative */ |
| 44 | + if (csign == MP_NEG) { |
| 45 | + cc += ~c->dp[i] & MP_MASK; |
| 46 | + c->dp[i] = cc & MP_MASK; |
| 47 | + cc >>= MP_DIGIT_BIT; |
| 48 | + } |
| 49 | + } |
34 | 50 |
|
35 | | - mp_clamp(&t); |
36 | | - mp_exch(c, &t); |
37 | | - mp_clear(&t); |
| 51 | + c->used = used; |
| 52 | + c->sign = csign; |
| 53 | + mp_clamp(c); |
38 | 54 | return MP_OKAY; |
39 | 55 | } |
40 | 56 | #endif |
0 commit comments