Coverage Report

Created: 2024-06-28 06:19

/src/gmp-6.2.1/mpn/powlo.c
Line
Count
Source
1
/* mpn_powlo -- Compute R = U^E mod B^n, where B is the limb base.
2
3
Copyright 2007-2009, 2012, 2015, 2016, 2018 Free Software Foundation, Inc.
4
5
This file is part of the GNU MP Library.
6
7
The GNU MP Library is free software; you can redistribute it and/or modify
8
it under the terms of either:
9
10
  * the GNU Lesser General Public License as published by the Free
11
    Software Foundation; either version 3 of the License, or (at your
12
    option) any later version.
13
14
or
15
16
  * the GNU General Public License as published by the Free Software
17
    Foundation; either version 2 of the License, or (at your option) any
18
    later version.
19
20
or both in parallel, as here.
21
22
The GNU MP Library is distributed in the hope that it will be useful, but
23
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
25
for more details.
26
27
You should have received copies of the GNU General Public License and the
28
GNU Lesser General Public License along with the GNU MP Library.  If not,
29
see https://www.gnu.org/licenses/.  */
30
31
32
#include "gmp-impl.h"
33
#include "longlong.h"
34
35
36
#define getbit(p,bi) \
37
282k
  ((p[(bi - 1) / GMP_LIMB_BITS] >> (bi - 1) % GMP_LIMB_BITS) & 1)
38
39
static inline mp_limb_t
40
getbits (const mp_limb_t *p, mp_bitcnt_t bi, unsigned nbits)
41
79.5k
{
42
79.5k
  unsigned nbits_in_r;
43
79.5k
  mp_limb_t r;
44
79.5k
  mp_size_t i;
45
46
79.5k
  if (bi < nbits)
47
312
    {
48
312
      return p[0] & (((mp_limb_t) 1 << bi) - 1);
49
312
    }
50
79.2k
  else
51
79.2k
    {
52
79.2k
      bi -= nbits;      /* bit index of low bit to extract */
53
79.2k
      i = bi / GMP_NUMB_BITS;   /* word index of low bit to extract */
54
79.2k
      bi %= GMP_NUMB_BITS;   /* bit index in low word */
55
79.2k
      r = p[i] >> bi;     /* extract (low) bits */
56
79.2k
      nbits_in_r = GMP_NUMB_BITS - bi;  /* number of bits now in r */
57
79.2k
      if (nbits_in_r < nbits)    /* did we get enough bits? */
58
7.42k
  r += p[i + 1] << nbits_in_r; /* prepend bits from higher word */
59
79.2k
      return r & (((mp_limb_t ) 1 << nbits) - 1);
60
79.2k
    }
61
79.5k
}
62
63
static inline unsigned
64
win_size (mp_bitcnt_t eb)
65
696
{
66
696
  unsigned k;
67
696
  static mp_bitcnt_t x[] = {7,25,81,241,673,1793,4609,11521,28161,~(mp_bitcnt_t)0};
68
696
  ASSERT (eb > 1);
69
2.36k
  for (k = 0; eb > x[k++];)
70
1.66k
    ;
71
696
  return k;
72
696
}
73
74
/* rp[n-1..0] = bp[n-1..0] ^ ep[en-1..0] mod B^n, B is the limb base.
75
   Requires that ep[en-1] is non-zero.
76
   Uses scratch space tp[3n-1..0], i.e., 3n words.  */
77
/* We only use n words in the scratch space, we should pass tp + n to
78
   mullo/sqrlo as a temporary area, it is needed. */
79
void
80
mpn_powlo (mp_ptr rp, mp_srcptr bp,
81
     mp_srcptr ep, mp_size_t en,
82
     mp_size_t n, mp_ptr tp)
83
696
{
84
696
  unsigned cnt;
85
696
  mp_bitcnt_t ebi;
86
696
  unsigned windowsize, this_windowsize;
87
696
  mp_limb_t expbits;
88
696
  mp_limb_t *pp;
89
696
  long i;
90
696
  int flipflop;
91
696
  TMP_DECL;
92
93
696
  ASSERT (en > 1 || (en == 1 && ep[0] > 1));
94
95
696
  TMP_MARK;
96
97
696
  MPN_SIZEINBASE_2EXP(ebi, ep, en, 1);
98
99
696
  windowsize = win_size (ebi);
100
696
  if (windowsize > 1)
101
448
    {
102
448
      mp_limb_t *this_pp, *last_pp;
103
448
      ASSERT (windowsize < ebi);
104
105
448
      pp = TMP_ALLOC_LIMBS ((n << (windowsize - 1)));
106
107
448
      this_pp = pp;
108
109
448
      MPN_COPY (this_pp, bp, n);
110
111
      /* Store b^2 in tp.  */
112
448
      mpn_sqrlo (tp, bp, n);
113
114
      /* Precompute odd powers of b and put them in the temporary area at pp.  */
115
448
      i = (1 << (windowsize - 1)) - 1;
116
448
      do
117
12.8k
  {
118
12.8k
    last_pp = this_pp;
119
12.8k
    this_pp += n;
120
12.8k
    mpn_mullo_n (this_pp, last_pp, tp, n);
121
12.8k
  } while (--i != 0);
122
123
448
      expbits = getbits (ep, ebi, windowsize);
124
125
      /* THINK: Should we initialise the case expbits % 4 == 0 with a mullo? */
126
448
      count_trailing_zeros (cnt, expbits);
127
448
      ebi -= windowsize;
128
448
      ebi += cnt;
129
448
      expbits >>= cnt;
130
131
448
      MPN_COPY (rp, pp + n * (expbits >> 1), n);
132
448
    }
133
248
  else
134
248
    {
135
248
      pp = tp + n;
136
248
      MPN_COPY (pp, bp, n);
137
248
      MPN_COPY (rp, bp, n);
138
248
      --ebi;
139
248
    }
140
141
696
  flipflop = 0;
142
143
696
  do
144
79.4k
    {
145
282k
      while (getbit (ep, ebi) == 0)
146
203k
  {
147
203k
    mpn_sqrlo (tp, rp, n);
148
203k
    MP_PTR_SWAP (rp, tp);
149
203k
    flipflop = ! flipflop;
150
203k
    if (--ebi == 0)
151
388
      goto done;
152
203k
  }
153
154
      /* The next bit of the exponent is 1.  Now extract the largest block of
155
   bits <= windowsize, and such that the least significant bit is 1.  */
156
157
79.0k
      expbits = getbits (ep, ebi, windowsize);
158
79.0k
      this_windowsize = MIN (windowsize, ebi);
159
79.0k
      ebi -= this_windowsize;
160
161
79.0k
      count_trailing_zeros (cnt, expbits);
162
79.0k
      this_windowsize -= cnt;
163
79.0k
      ebi += cnt;
164
79.0k
      expbits >>= cnt;
165
166
303k
      while (this_windowsize > 1)
167
224k
  {
168
224k
    mpn_sqrlo (tp, rp, n);
169
224k
    mpn_sqrlo (rp, tp, n);
170
224k
    this_windowsize -= 2;
171
224k
  }
172
173
79.0k
      if (this_windowsize != 0)
174
37.6k
  mpn_sqrlo (tp, rp, n);
175
41.4k
      else
176
41.4k
  {
177
41.4k
    MP_PTR_SWAP (rp, tp);
178
41.4k
    flipflop = ! flipflop;
179
41.4k
  }
180
181
79.0k
      mpn_mullo_n (rp, tp, pp + n * (expbits >> 1), n);
182
79.0k
    } while (ebi != 0);
183
184
696
 done:
185
696
  if (flipflop)
186
412
    MPN_COPY (tp, rp, n);
187
696
  TMP_FREE;
188
696
}