pow_1.c revision 1.1.1.2 1 1.1 mrg /* mpn_pow_1 -- Compute powers R = U^exp.
2 1.1 mrg
3 1.1 mrg THE FUNCTIONS IN THIS FILE ARE FOR INTERNAL USE ONLY. THEY'RE ALMOST
4 1.1 mrg CERTAIN TO BE SUBJECT TO INCOMPATIBLE CHANGES OR DISAPPEAR COMPLETELY IN
5 1.1 mrg FUTURE GNU MP RELEASES.
6 1.1 mrg
7 1.1.1.2 mrg Copyright 2002, 2014 Free Software Foundation, Inc.
8 1.1 mrg
9 1.1 mrg This file is part of the GNU MP Library.
10 1.1 mrg
11 1.1.1.2 mrg The GNU MP Library is free software; you can redistribute it and/or modify
12 1.1.1.2 mrg it under the terms of either:
13 1.1.1.2 mrg
14 1.1.1.2 mrg * the GNU Lesser General Public License as published by the Free
15 1.1.1.2 mrg Software Foundation; either version 3 of the License, or (at your
16 1.1.1.2 mrg option) any later version.
17 1.1.1.2 mrg
18 1.1.1.2 mrg or
19 1.1.1.2 mrg
20 1.1.1.2 mrg * the GNU General Public License as published by the Free Software
21 1.1.1.2 mrg Foundation; either version 2 of the License, or (at your option) any
22 1.1.1.2 mrg later version.
23 1.1.1.2 mrg
24 1.1.1.2 mrg or both in parallel, as here.
25 1.1 mrg
26 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but
27 1.1.1.2 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
28 1.1.1.2 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
29 1.1 mrg for more details.
30 1.1 mrg
31 1.1.1.2 mrg You should have received copies of the GNU General Public License and the
32 1.1.1.2 mrg GNU Lesser General Public License along with the GNU MP Library. If not,
33 1.1.1.2 mrg see https://www.gnu.org/licenses/. */
34 1.1 mrg
35 1.1 mrg
36 1.1 mrg #include "gmp.h"
37 1.1 mrg #include "gmp-impl.h"
38 1.1 mrg #include "longlong.h"
39 1.1 mrg
40 1.1 mrg mp_size_t
41 1.1 mrg mpn_pow_1 (mp_ptr rp, mp_srcptr bp, mp_size_t bn, mp_limb_t exp, mp_ptr tp)
42 1.1 mrg {
43 1.1 mrg mp_limb_t x;
44 1.1 mrg int cnt, i;
45 1.1 mrg mp_size_t rn;
46 1.1 mrg int par;
47 1.1 mrg
48 1.1 mrg ASSERT (bn >= 1);
49 1.1 mrg /* FIXME: Add operand overlap criteria */
50 1.1 mrg
51 1.1 mrg if (exp <= 1)
52 1.1 mrg {
53 1.1 mrg if (exp == 0)
54 1.1 mrg {
55 1.1 mrg rp[0] = 1;
56 1.1 mrg return 1;
57 1.1 mrg }
58 1.1 mrg else
59 1.1 mrg {
60 1.1 mrg MPN_COPY (rp, bp, bn);
61 1.1 mrg return bn;
62 1.1 mrg }
63 1.1 mrg }
64 1.1 mrg
65 1.1 mrg /* Count number of bits in exp, and compute where to put initial square in
66 1.1 mrg order to magically get results in the entry rp. Use simple code,
67 1.1 mrg optimized for small exp. For large exp, the bignum operations will take
68 1.1 mrg so much time that the slowness of this code will be negligible. */
69 1.1 mrg par = 0;
70 1.1 mrg cnt = GMP_LIMB_BITS;
71 1.1.1.2 mrg x = exp;
72 1.1.1.2 mrg do
73 1.1 mrg {
74 1.1.1.2 mrg par ^= x;
75 1.1 mrg cnt--;
76 1.1.1.2 mrg x >>= 1;
77 1.1.1.2 mrg } while (x != 0);
78 1.1 mrg exp <<= cnt;
79 1.1 mrg
80 1.1 mrg if (bn == 1)
81 1.1 mrg {
82 1.1 mrg mp_limb_t bl = bp[0];
83 1.1 mrg
84 1.1 mrg if ((cnt & 1) != 0)
85 1.1 mrg MP_PTR_SWAP (rp, tp);
86 1.1 mrg
87 1.1 mrg mpn_sqr (rp, bp, bn);
88 1.1 mrg rn = 2 * bn; rn -= rp[rn - 1] == 0;
89 1.1 mrg
90 1.1 mrg for (i = GMP_LIMB_BITS - cnt - 1;;)
91 1.1 mrg {
92 1.1 mrg exp <<= 1;
93 1.1 mrg if ((exp & GMP_LIMB_HIGHBIT) != 0)
94 1.1 mrg {
95 1.1 mrg rp[rn] = mpn_mul_1 (rp, rp, rn, bl);
96 1.1 mrg rn += rp[rn] != 0;
97 1.1 mrg }
98 1.1 mrg
99 1.1 mrg if (--i == 0)
100 1.1 mrg break;
101 1.1 mrg
102 1.1 mrg mpn_sqr (tp, rp, rn);
103 1.1 mrg rn = 2 * rn; rn -= tp[rn - 1] == 0;
104 1.1 mrg MP_PTR_SWAP (rp, tp);
105 1.1 mrg }
106 1.1 mrg }
107 1.1 mrg else
108 1.1 mrg {
109 1.1 mrg if (((par ^ cnt) & 1) == 0)
110 1.1 mrg MP_PTR_SWAP (rp, tp);
111 1.1 mrg
112 1.1 mrg mpn_sqr (rp, bp, bn);
113 1.1 mrg rn = 2 * bn; rn -= rp[rn - 1] == 0;
114 1.1 mrg
115 1.1 mrg for (i = GMP_LIMB_BITS - cnt - 1;;)
116 1.1 mrg {
117 1.1 mrg exp <<= 1;
118 1.1 mrg if ((exp & GMP_LIMB_HIGHBIT) != 0)
119 1.1 mrg {
120 1.1 mrg rn = rn + bn - (mpn_mul (tp, rp, rn, bp, bn) == 0);
121 1.1 mrg MP_PTR_SWAP (rp, tp);
122 1.1 mrg }
123 1.1 mrg
124 1.1 mrg if (--i == 0)
125 1.1 mrg break;
126 1.1 mrg
127 1.1 mrg mpn_sqr (tp, rp, rn);
128 1.1 mrg rn = 2 * rn; rn -= tp[rn - 1] == 0;
129 1.1 mrg MP_PTR_SWAP (rp, tp);
130 1.1 mrg }
131 1.1 mrg }
132 1.1 mrg
133 1.1 mrg return rn;
134 1.1 mrg }
135