summaryrefslogtreecommitdiff
path: root/mpz/powm_ui.c
diff options
context:
space:
mode:
authorKevin Ryde <user42@zip.com.au>2002-06-01 03:02:44 +0200
committerKevin Ryde <user42@zip.com.au>2002-06-01 03:02:44 +0200
commit93fb6d7a40dbb522a4a96bfaae033581fe669e1b (patch)
treef1f7808993da203650456862602560238708d9d3 /mpz/powm_ui.c
parent5029da48c71bcfd7f9c8344688e8644a0af006b9 (diff)
downloadgmp-93fb6d7a40dbb522a4a96bfaae033581fe669e1b.tar.gz
* mpz/powm_ui.c: Fix for result range in certain circumstances.
Diffstat (limited to 'mpz/powm_ui.c')
-rw-r--r--mpz/powm_ui.c12
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)