Skip to content

Instantly share code, notes, and snippets.

@skids
Created December 2, 2012 07:00
Show Gist options
  • Save skids/4187527 to your computer and use it in GitHub Desktop.
Save skids/4187527 to your computer and use it in GitHub Desktop.
A fix for tomath repr bitops
static void grow_and_negate(mp_int *a, int size, mp_int *b) {
int i;
/* Always add an extra digit so we can tell positive values
* with a one in the highest bit apart from negative values
* with a zero in the highest bit.
*/
int actual_size = MAX(size, USED(a)) + 1;
SIGN(b) = MP_ZPOS;
mp_grow(b, actual_size);
USED(b) = actual_size;
for (i = 0; i < USED(a); i++) {
DIGIT(b, i) = (~DIGIT(a, i)) & MP_MASK;
}
if (MP_NEG == SIGN(a)) {
for (; i < actual_size; i++) {
DIGIT(b, i) = MP_MASK;
}
}
/* Note: this is never called with a containing only zeros because:
* 1) we assume "negative zero" just does not happen (?)
* 2) positive values only come here if they have a high bit of one
* As such, this add cannot cause another grow.
*/
mp_add_d(b, 1, b);
}
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;
}
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 signed results */
if (USED(c) > MAX(USED(a),USED(b))) {
mp_init(&d);
grow_and_negate(c, c->used, &d);
mp_clamp(&d);
mp_copy(&d, c);
mp_neg(c, c);
mp_clear(&d);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment