1 1.1.1.3 mrg /* mpz_powm_ui(res,base,exp,mod) -- Set R to (B^E) mod M. 2 1.1 mrg 3 1.1.1.3 mrg Contributed to the GNU project by Torbjrn Granlund. 4 1.1.1.2 mrg 5 1.1.1.4 mrg Copyright 1991, 1993, 1994, 1996, 1997, 2000-2002, 2005, 2008, 2009, 6 1.1.1.4 mrg 2011-2013, 2015 Free Software Foundation, Inc. 7 1.1 mrg 8 1.1 mrg This file is part of the GNU MP Library. 9 1.1 mrg 10 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify 11 1.1.1.3 mrg it under the terms of either: 12 1.1.1.3 mrg 13 1.1.1.3 mrg * the GNU Lesser General Public License as published by the Free 14 1.1.1.3 mrg Software Foundation; either version 3 of the License, or (at your 15 1.1.1.3 mrg option) any later version. 16 1.1.1.3 mrg 17 1.1.1.3 mrg or 18 1.1.1.3 mrg 19 1.1.1.3 mrg * the GNU General Public License as published by the Free Software 20 1.1.1.3 mrg Foundation; either version 2 of the License, or (at your option) any 21 1.1.1.3 mrg later version. 22 1.1.1.3 mrg 23 1.1.1.3 mrg or both in parallel, as here. 24 1.1 mrg 25 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but 26 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 27 1.1.1.3 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 28 1.1.1.3 mrg for more details. 29 1.1 mrg 30 1.1.1.3 mrg You should have received copies of the GNU General Public License and the 31 1.1.1.3 mrg GNU Lesser General Public License along with the GNU MP Library. If not, 32 1.1.1.3 mrg see https://www.gnu.org/licenses/. */ 33 1.1 mrg 34 1.1 mrg 35 1.1 mrg #include "gmp-impl.h" 36 1.1 mrg #include "longlong.h" 37 1.1 mrg 38 1.1.1.2 mrg 39 1.1.1.2 mrg /* This code is very old, and should be rewritten to current GMP standard. It 40 1.1.1.2 mrg is slower than mpz_powm for large exponents, but also for small exponents 41 1.1.1.2 mrg when the mod argument is small. 42 1.1.1.2 mrg 43 1.1.1.2 mrg As an intermediate solution, we now deflect to mpz_powm for exponents >= 20. 44 1.1.1.2 mrg */ 45 1.1.1.2 mrg 46 1.1.1.2 mrg /* 47 1.1.1.2 mrg b ^ e mod m res 48 1.1.1.2 mrg 0 0 0 ? 49 1.1.1.2 mrg 0 e 0 ? 50 1.1.1.2 mrg 0 0 m ? 51 1.1.1.2 mrg 0 e m 0 52 1.1.1.2 mrg b 0 0 ? 53 1.1.1.2 mrg b e 0 ? 54 1.1.1.2 mrg b 0 m 1 mod m 55 1.1.1.2 mrg b e m b^e mod m 56 1.1.1.2 mrg */ 57 1.1.1.2 mrg 58 1.1 mrg static void 59 1.1.1.2 mrg mod (mp_ptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn, gmp_pi1_t *dinv, mp_ptr tp) 60 1.1 mrg { 61 1.1.1.4 mrg mp_ptr qp = tp; 62 1.1.1.2 mrg 63 1.1.1.2 mrg if (dn == 1) 64 1.1.1.3 mrg { 65 1.1.1.3 mrg np[0] = mpn_divrem_1 (qp, (mp_size_t) 0, np, nn, dp[0]); 66 1.1.1.3 mrg } 67 1.1.1.2 mrg else if (dn == 2) 68 1.1.1.3 mrg { 69 1.1.1.3 mrg mpn_div_qr_2n_pi1 (qp, np, np, nn, dp[1], dp[0], dinv->inv32); 70 1.1.1.3 mrg } 71 1.1.1.2 mrg else if (BELOW_THRESHOLD (dn, DC_DIV_QR_THRESHOLD) || 72 1.1.1.2 mrg BELOW_THRESHOLD (nn - dn, DC_DIV_QR_THRESHOLD)) 73 1.1.1.3 mrg { 74 1.1.1.3 mrg mpn_sbpi1_div_qr (qp, np, nn, dp, dn, dinv->inv32); 75 1.1.1.3 mrg } 76 1.1.1.2 mrg else if (BELOW_THRESHOLD (dn, MUPI_DIV_QR_THRESHOLD) || /* fast condition */ 77 1.1.1.2 mrg BELOW_THRESHOLD (nn, 2 * MU_DIV_QR_THRESHOLD) || /* fast condition */ 78 1.1.1.2 mrg (double) (2 * (MU_DIV_QR_THRESHOLD - MUPI_DIV_QR_THRESHOLD)) * dn /* slow... */ 79 1.1.1.2 mrg + (double) MUPI_DIV_QR_THRESHOLD * nn > (double) dn * nn) /* ...condition */ 80 1.1.1.2 mrg { 81 1.1.1.2 mrg mpn_dcpi1_div_qr (qp, np, nn, dp, dn, dinv); 82 1.1.1.2 mrg } 83 1.1.1.2 mrg else 84 1.1.1.2 mrg { 85 1.1.1.2 mrg /* We need to allocate separate remainder area, since mpn_mu_div_qr does 86 1.1.1.2 mrg not handle overlap between the numerator and remainder areas. 87 1.1.1.2 mrg FIXME: Make it handle such overlap. */ 88 1.1.1.4 mrg mp_ptr rp, scratch; 89 1.1.1.4 mrg mp_size_t itch; 90 1.1.1.4 mrg TMP_DECL; 91 1.1.1.4 mrg TMP_MARK; 92 1.1.1.4 mrg 93 1.1.1.4 mrg itch = mpn_mu_div_qr_itch (nn, dn, 0); 94 1.1.1.4 mrg rp = TMP_BALLOC_LIMBS (dn); 95 1.1.1.4 mrg scratch = TMP_BALLOC_LIMBS (itch); 96 1.1.1.4 mrg 97 1.1.1.2 mrg mpn_mu_div_qr (qp, rp, np, nn, dp, dn, scratch); 98 1.1.1.2 mrg MPN_COPY (np, rp, dn); 99 1.1 mrg 100 1.1.1.4 mrg TMP_FREE; 101 1.1.1.4 mrg } 102 1.1 mrg } 103 1.1 mrg 104 1.1.1.2 mrg /* Compute t = a mod m, a is defined by (ap,an), m is defined by (mp,mn), and 105 1.1.1.2 mrg t is defined by (tp,mn). */ 106 1.1.1.2 mrg static void 107 1.1.1.2 mrg reduce (mp_ptr tp, mp_srcptr ap, mp_size_t an, mp_srcptr mp, mp_size_t mn, gmp_pi1_t *dinv) 108 1.1 mrg { 109 1.1.1.2 mrg mp_ptr rp, scratch; 110 1.1 mrg TMP_DECL; 111 1.1.1.2 mrg TMP_MARK; 112 1.1 mrg 113 1.1.1.4 mrg TMP_ALLOC_LIMBS_2 (rp, an, scratch, an - mn + 1); 114 1.1.1.2 mrg MPN_COPY (rp, ap, an); 115 1.1.1.2 mrg mod (rp, an, mp, mn, dinv, scratch); 116 1.1.1.2 mrg MPN_COPY (tp, rp, mn); 117 1.1 mrg 118 1.1.1.2 mrg TMP_FREE; 119 1.1.1.2 mrg } 120 1.1 mrg 121 1.1.1.2 mrg void 122 1.1.1.2 mrg mpz_powm_ui (mpz_ptr r, mpz_srcptr b, unsigned long int el, mpz_srcptr m) 123 1.1.1.2 mrg { 124 1.1.1.2 mrg if (el < 20) 125 1.1 mrg { 126 1.1.1.2 mrg mp_ptr xp, tp, mp, bp, scratch; 127 1.1.1.2 mrg mp_size_t xn, tn, mn, bn; 128 1.1.1.2 mrg int m_zero_cnt; 129 1.1.1.2 mrg int c; 130 1.1.1.2 mrg mp_limb_t e, m2; 131 1.1.1.2 mrg gmp_pi1_t dinv; 132 1.1.1.2 mrg TMP_DECL; 133 1.1.1.2 mrg 134 1.1.1.2 mrg mp = PTR(m); 135 1.1.1.2 mrg mn = ABSIZ(m); 136 1.1.1.2 mrg if (UNLIKELY (mn == 0)) 137 1.1.1.2 mrg DIVIDE_BY_ZERO; 138 1.1 mrg 139 1.1.1.4 mrg if (el <= 1) 140 1.1.1.2 mrg { 141 1.1.1.4 mrg if (el == 1) 142 1.1.1.4 mrg { 143 1.1.1.4 mrg mpz_mod (r, b, m); 144 1.1.1.4 mrg return; 145 1.1.1.4 mrg } 146 1.1.1.2 mrg /* Exponent is zero, result is 1 mod M, i.e., 1 or 0 depending on if 147 1.1.1.2 mrg M equals 1. */ 148 1.1.1.4 mrg SIZ(r) = mn != 1 || mp[0] != 1; 149 1.1.1.4 mrg MPZ_NEWALLOC (r, 1)[0] = 1; 150 1.1.1.2 mrg return; 151 1.1.1.2 mrg } 152 1.1 mrg 153 1.1.1.2 mrg TMP_MARK; 154 1.1 mrg 155 1.1.1.2 mrg /* Normalize m (i.e. make its most significant bit set) as required by 156 1.1.1.2 mrg division functions below. */ 157 1.1.1.2 mrg count_leading_zeros (m_zero_cnt, mp[mn - 1]); 158 1.1.1.2 mrg m_zero_cnt -= GMP_NAIL_BITS; 159 1.1.1.2 mrg if (m_zero_cnt != 0) 160 1.1.1.2 mrg { 161 1.1.1.2 mrg mp_ptr new_mp = TMP_ALLOC_LIMBS (mn); 162 1.1.1.2 mrg mpn_lshift (new_mp, mp, mn, m_zero_cnt); 163 1.1.1.2 mrg mp = new_mp; 164 1.1.1.2 mrg } 165 1.1 mrg 166 1.1.1.2 mrg m2 = mn == 1 ? 0 : mp[mn - 2]; 167 1.1.1.2 mrg invert_pi1 (dinv, mp[mn - 1], m2); 168 1.1 mrg 169 1.1.1.2 mrg bn = ABSIZ(b); 170 1.1.1.2 mrg bp = PTR(b); 171 1.1.1.2 mrg if (bn > mn) 172 1.1.1.2 mrg { 173 1.1.1.2 mrg /* Reduce possibly huge base. Use a function call to reduce, since we 174 1.1.1.2 mrg don't want the quotient allocation to live until function return. */ 175 1.1.1.2 mrg mp_ptr new_bp = TMP_ALLOC_LIMBS (mn); 176 1.1.1.2 mrg reduce (new_bp, bp, bn, mp, mn, &dinv); 177 1.1.1.2 mrg bp = new_bp; 178 1.1.1.2 mrg bn = mn; 179 1.1.1.2 mrg /* Canonicalize the base, since we are potentially going to multiply with 180 1.1.1.2 mrg it quite a few times. */ 181 1.1.1.2 mrg MPN_NORMALIZE (bp, bn); 182 1.1.1.2 mrg } 183 1.1 mrg 184 1.1.1.2 mrg if (bn == 0) 185 1.1.1.2 mrg { 186 1.1.1.2 mrg SIZ(r) = 0; 187 1.1.1.2 mrg TMP_FREE; 188 1.1.1.2 mrg return; 189 1.1.1.2 mrg } 190 1.1 mrg 191 1.1.1.4 mrg TMP_ALLOC_LIMBS_3 (xp, mn, scratch, mn + 1, tp, 2 * mn + 1); 192 1.1.1.2 mrg 193 1.1.1.2 mrg MPN_COPY (xp, bp, bn); 194 1.1.1.2 mrg xn = bn; 195 1.1.1.2 mrg 196 1.1.1.2 mrg e = el; 197 1.1.1.2 mrg count_leading_zeros (c, e); 198 1.1.1.2 mrg e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ 199 1.1.1.2 mrg c = GMP_LIMB_BITS - 1 - c; 200 1.1.1.2 mrg 201 1.1.1.4 mrg ASSERT (c != 0); /* el > 1 */ 202 1.1 mrg { 203 1.1.1.2 mrg /* Main loop. */ 204 1.1.1.2 mrg do 205 1.1.1.2 mrg { 206 1.1.1.2 mrg mpn_sqr (tp, xp, xn); 207 1.1.1.2 mrg tn = 2 * xn; tn -= tp[tn - 1] == 0; 208 1.1.1.2 mrg if (tn < mn) 209 1.1.1.2 mrg { 210 1.1.1.2 mrg MPN_COPY (xp, tp, tn); 211 1.1.1.2 mrg xn = tn; 212 1.1.1.2 mrg } 213 1.1.1.2 mrg else 214 1.1.1.2 mrg { 215 1.1.1.2 mrg mod (tp, tn, mp, mn, &dinv, scratch); 216 1.1.1.2 mrg MPN_COPY (xp, tp, mn); 217 1.1.1.2 mrg xn = mn; 218 1.1.1.2 mrg } 219 1.1.1.2 mrg 220 1.1.1.2 mrg if ((mp_limb_signed_t) e < 0) 221 1.1.1.2 mrg { 222 1.1.1.2 mrg mpn_mul (tp, xp, xn, bp, bn); 223 1.1.1.2 mrg tn = xn + bn; tn -= tp[tn - 1] == 0; 224 1.1.1.2 mrg if (tn < mn) 225 1.1.1.2 mrg { 226 1.1.1.2 mrg MPN_COPY (xp, tp, tn); 227 1.1.1.2 mrg xn = tn; 228 1.1.1.2 mrg } 229 1.1.1.2 mrg else 230 1.1.1.2 mrg { 231 1.1.1.2 mrg mod (tp, tn, mp, mn, &dinv, scratch); 232 1.1.1.2 mrg MPN_COPY (xp, tp, mn); 233 1.1.1.2 mrg xn = mn; 234 1.1.1.2 mrg } 235 1.1.1.2 mrg } 236 1.1.1.2 mrg e <<= 1; 237 1.1.1.2 mrg c--; 238 1.1.1.2 mrg } 239 1.1.1.2 mrg while (c != 0); 240 1.1 mrg } 241 1.1 mrg 242 1.1.1.2 mrg /* We shifted m left m_zero_cnt steps. Adjust the result by reducing it 243 1.1.1.2 mrg with the original M. */ 244 1.1.1.2 mrg if (m_zero_cnt != 0) 245 1.1 mrg { 246 1.1.1.2 mrg mp_limb_t cy; 247 1.1.1.2 mrg cy = mpn_lshift (tp, xp, xn, m_zero_cnt); 248 1.1.1.2 mrg tp[xn] = cy; xn += cy != 0; 249 1.1.1.2 mrg 250 1.1.1.4 mrg if (xn >= mn) 251 1.1 mrg { 252 1.1.1.2 mrg mod (tp, xn, mp, mn, &dinv, scratch); 253 1.1 mrg xn = mn; 254 1.1 mrg } 255 1.1.1.4 mrg mpn_rshift (xp, tp, xn, m_zero_cnt); 256 1.1 mrg } 257 1.1.1.2 mrg MPN_NORMALIZE (xp, xn); 258 1.1 mrg 259 1.1.1.2 mrg if ((el & 1) != 0 && SIZ(b) < 0 && xn != 0) 260 1.1 mrg { 261 1.1.1.2 mrg mp = PTR(m); /* want original, unnormalized m */ 262 1.1.1.2 mrg mpn_sub (xp, mp, mn, xp, xn); 263 1.1 mrg xn = mn; 264 1.1.1.2 mrg MPN_NORMALIZE (xp, xn); 265 1.1 mrg } 266 1.1.1.4 mrg MPZ_NEWALLOC (r, xn); 267 1.1.1.2 mrg SIZ (r) = xn; 268 1.1.1.2 mrg MPN_COPY (PTR(r), xp, xn); 269 1.1 mrg 270 1.1.1.2 mrg TMP_FREE; 271 1.1.1.2 mrg } 272 1.1.1.2 mrg else 273 1.1 mrg { 274 1.1.1.3 mrg /* For large exponents, fake an mpz_t exponent and deflect to the more 275 1.1.1.2 mrg sophisticated mpz_powm. */ 276 1.1.1.2 mrg mpz_t e; 277 1.1.1.2 mrg mp_limb_t ep[LIMBS_PER_ULONG]; 278 1.1.1.2 mrg MPZ_FAKE_UI (e, ep, el); 279 1.1.1.2 mrg mpz_powm (r, b, e, m); 280 1.1 mrg } 281 1.1 mrg } 282