diff options
author | Kevin Ryde <user42@zip.com.au> | 2002-06-01 03:02:44 +0200 |
---|---|---|
committer | Kevin Ryde <user42@zip.com.au> | 2002-06-01 03:02:44 +0200 |
commit | 93fb6d7a40dbb522a4a96bfaae033581fe669e1b (patch) | |
tree | f1f7808993da203650456862602560238708d9d3 /mpz | |
parent | 5029da48c71bcfd7f9c8344688e8644a0af006b9 (diff) | |
download | gmp-93fb6d7a40dbb522a4a96bfaae033581fe669e1b.tar.gz |
* mpz/powm_ui.c: Fix for result range in certain circumstances.
Diffstat (limited to 'mpz')
-rw-r--r-- | mpz/powm_ui.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/mpz/powm_ui.c b/mpz/powm_ui.c index d73c3afc4..535fe1e55 100644 --- a/mpz/powm_ui.c +++ b/mpz/powm_ui.c @@ -115,6 +115,17 @@ mpz_powm_ui (mpz_ptr r, mpz_srcptr b, unsigned long int el, mpz_srcptr m) /* Main loop. */ + /* If m is already normalized (high bit of high limb set), and b is the + same size, but a bigger value, and e==1, then there's no modular + reductions done and we can end up with a result out of range at the + end. */ + if (c == 0) + { + if (xn == mn && mpn_cmp (xp, mp, mn) >= 0) + mpn_sub_n (xp, xp, mp, mn); + goto finishup; + } + while (c != 0) { mpn_sqr_n (tp, xp, xn); @@ -149,6 +160,7 @@ mpz_powm_ui (mpz_ptr r, mpz_srcptr b, unsigned long int el, mpz_srcptr m) c--; } + finishup: /* We shifted m left m_zero_cnt steps. Adjust the result by reducing it with the original MOD. */ if (m_zero_cnt != 0) |