powm_ui.c revision 1.1.1.4 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