static void two_complement_bitop(mp_int *a, mp_int *b, mp_int *c, int (*mp_bitop)(mp_int *, mp_int *, mp_int *)) { mp_int d; if (SIGN(a) ^ SIGN(b)) { /* exactly one of them is negative, so need to perform * some magic. tommath stores a sign bit, but Perl 6 expects * 2's complement */ mp_init(&d); if (MP_NEG == SIGN(a)) { grow_and_negate(a, USED(b), &d); mp_bitop(&d, b, c); } else { grow_and_negate(b, USED(a), &d); mp_bitop(a, &d, c); } if (DIGIT(c, USED(c) - 1) & ((mp_digit)1<<(mp_digit)(DIGIT_BIT - 1))) { grow_and_negate(c, c->used, &d); mp_copy(&d, c); mp_neg(c, c); } mp_clear(&d); } else { mp_bitop(a, b, c); } }
static void two_complement_bitop(mp_int *a, mp_int *b, mp_int *c, int (*mp_bitop)(mp_int *, mp_int *, mp_int *)) { mp_int d; mp_int e; mp_int *f; mp_int *g; f = a; g = b; if (MP_NEG == SIGN(a)) { mp_init(&d); grow_and_negate(a, USED(b), &d); f = &d; } if (MP_NEG == SIGN(b)) { mp_init(&e); grow_and_negate(b, USED(a), &e); g = &e; } /* f and g now guaranteed to each point to positive bigints containing * a 2s compliment representation of the values in a and b. If either * a or b was negative, the representation is one tomath "digit" longer * than it need be and sign extended. */ mp_bitop(f, g, c); if (f == &d) mp_clear(&d); if (g == &e) mp_clear(&e); /* Use the fact that tomath clamps to detect results that should be * signed. If we created extra tomath "digits" and they resulted in * sign bits of 0, they have been clamped away. If the resulting sign * bits were 1, they remain, and c will have more digits than either of * original operands. Note this only works because we do not * support NOR/NAND/NXOR, and so two zero sign bits can never create 1s. */ if (USED(c) > MAX(USED(a),USED(b))) { int i; for (i = 0; i < USED(c); i++) { DIGIT(c, i) = (~DIGIT(c, i)) & MP_MASK; } mp_add_d(c, 1, c); mp_neg(c, c); } }