diff --git a/mrbgems/mruby-bigint/core/bigint.c b/mrbgems/mruby-bigint/core/bigint.c index e22601bd7..328bca61e 100644 --- a/mrbgems/mruby-bigint/core/bigint.c +++ b/mrbgems/mruby-bigint/core/bigint.c @@ -945,17 +945,59 @@ mpz_and(mrb_state *mrb, mpz_t *z, mpz_t *x, mpz_t *y) static void mpz_or(mrb_state *mrb, mpz_t *z, mpz_t *x, mpz_t *y) /* not the most efficient way to do this */ { - size_t sz = imax(x->sz, y->sz); + 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_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) - z->sn = (-1); - else - z->sn = 1; - if (uzero(z)) - z->sn = 0; + z->sn = x->sn > 0 && y->sn > 0 ? 1 : -1; + + 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); + } + + uint32_t *ds1, *ds2, *zds; + size_t l1, l2; + short sign; + + if (x->sz > y->sz) { + l1 = y->sz; + l2 = x->sz; + ds1 = y->p; + ds2 = x->p; + sign = y->sn; + } + 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]:DIG_MASK; + } + if (z->sn < 0) mpz_2comp(mrb, z); } static void