From f5a3f4f2eabe822bc0b87856b35592ce5c6ae413 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 26 Aug 2022 14:21:09 +0900 Subject: [PATCH] bigint.c (mpz_powm): avoid stack allocations. --- mrbgems/mruby-bigint/core/bigint.c | 59 +++++------------------------- 1 file changed, 10 insertions(+), 49 deletions(-) diff --git a/mrbgems/mruby-bigint/core/bigint.c b/mrbgems/mruby-bigint/core/bigint.c index e2cd988e0..dd6dbd7d2 100644 --- a/mrbgems/mruby-bigint/core/bigint.c +++ b/mrbgems/mruby-bigint/core/bigint.c @@ -906,44 +906,10 @@ mpz_pow(mrb_state *mrb, mpz_t *zz, mpz_t *x, mrb_int e) mpz_move(mrb, zz, &t); } -#define lowdigit(x) (((x)->p)[0]) - -struct is { - mp_limb v; - struct is *next; -}; - -static void -push(mrb_state *mrb, mp_limb i, struct is **sp) -{ - struct is *tmp; - tmp = *sp; - *sp = (struct is*)mrb_malloc(mrb, sizeof(struct is)); - (*sp)->v = i; - (*sp)->next=tmp; -} - -static mp_limb -pop(mrb_state *mrb, struct is **sp) -{ - struct is *tmp; - mp_limb i; - if (!(*sp)) - return (-1); - tmp = *sp; - *sp = (*sp)->next; - i = tmp->v; - tmp->v = 0; - mrb_free(mrb, tmp); - return i; -} - static void mpz_powm(mrb_state *mrb, mpz_t *zz, mpz_t *x, mrb_int ex, mpz_t *n) { - mpz_t t, e; - struct is *stack = NULL; - int k, i; + mpz_t t, b; if (ex == 0) { mpz_set_int(mrb, zz, 1); @@ -953,26 +919,21 @@ mpz_powm(mrb_state *mrb, mpz_t *zz, mpz_t *x, mrb_int ex, mpz_t *n) if (ex < 0) { return; } - mpz_init_set_int(mrb, &e, ex); - mpz_init(mrb, &t); - for (k=0; !uzero(&e); k++, mpz_div_2exp(mrb, &e, &e, 1)) - push(mrb, lowdigit(&e)&1, &stack); - k--; - i=pop(mrb, &stack); + mpz_init_set_int(mrb, &t, 1); + mpz_init_set(mrb, &b, x); - mpz_mod(mrb, &t, x, n); /* t=x%n */ - - for (i=k-1;i>=0;i--) { - mpz_mul(mrb, &t, &t, &t); - mpz_mod(mrb, &t, &t, n); - if (pop(mrb, &stack)) { - mpz_mul(mrb, &t, &t, x); + while (ex > 0) { + if ((ex & 1) == 1) { + mpz_mul(mrb, &t, &t, &b); mpz_mod(mrb, &t, &t, n); } + ex >>= 1; + mpz_mul(mrb, &b, &b, &b); + mpz_mod(mrb, &b, &b, n); } mpz_move(mrb, zz, &t); - mpz_clear(mrb, &e); + mpz_clear(mrb, &b); } /* --- mruby functions --- */