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