diff --git a/mrbgems/mruby-bigint/core/bigint.c b/mrbgems/mruby-bigint/core/bigint.c index 1d5e0b621..d7b2f915a 100644 --- a/mrbgems/mruby-bigint/core/bigint.c +++ b/mrbgems/mruby-bigint/core/bigint.c @@ -961,60 +961,31 @@ mpz_xor(mrb_state *mrb, mpz_t *z, mpz_t *x, mpz_t *y) /* not the most efficient } mrb_assert(x->sz > 0 || y->sz > 0); - z->sn = x->sn > 0 && y->sn > 0 ? 1 : -1; + if (x->sn == 0) { + mpz_set(mrb, z, y); + return; + } + if (y->sn == 0) { + mpz_set(mrb, z, x); + return; + } + mrb_assert(x->sz > 0 || y->sz > 0); - mpz_t xx, yy; - if (x->sn < 0) { - mpz_init_set(mrb, &xx, x); - x = &xx; - mpz_2comp(mrb, x); - } - if (y->sn < 0) { - mpz_init_set(mrb, &yy, y); - y = &yy; - mpz_2comp(mrb, y); - } + size_t max_sz = (x->sz > y->sz) ? x->sz : y->sz; + mpz_realloc(mrb, z, max_sz); + z->sn = (x->sn == y->sn) ? 1 : -1; - uint32_t *ds1, *ds2, *zds; - size_t l1, l2; - short sign; + char c1 = 1, c2 = 1, c3 = 1; + for (size_t i = 0; i < max_sz; i++) { + uint32_t xv = (i < x->sz) ? x->p[i] : 0; + uint32_t yv = (i < y->sz) ? y->p[i] : 0; - if (x->sz > y->sz) { - l1 = y->sz; - l2 = x->sz; - ds1 = y->p; - ds2 = x->p; - sign = y->sn; + if (x->sn < 0) make_2comp(xv, c1); + if (y->sn < 0) make_2comp(yv, c2); + uint32_t zv = xv ^ yv; + if (z->sn < 0) make_2comp(zv, c3); + z->p[i] = zv; } - else { - l1 = x->sz; - l2 = y->sz; - ds1 = x->p; - ds2 = y->p; - sign =x->sn; - } - mpz_realloc(mrb, z, l2); - zds = z->p; - - size_t i; - for (i=0; i0?ds2[i]:~ds2[i]; - } - if (z->sn < 0) mpz_2comp(mrb, z); - - size_t sz = imax(x->sz, y->sz); - mpz_realloc(mrb, z, sz); - for (size_t i=0; i < sz; i++) - z->p[i] = dg(x,i) ^ dg(y,i); - if ((x->sn <= 0 && y->sn > 0) || (x->sn > 0 && y->sn <=0)) - z->sn = (-1); - else - z->sn = 1; - if (uzero_p(z)) - z->sn = 0; } static void