Coverage Report

Created: 2025-04-11 06:45

/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
324k
  ((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
95.5k
{
42
95.5k
  unsigned nbits_in_r;
43
95.5k
  mp_limb_t r;
44
95.5k
  mp_size_t i;
45
46
95.5k
  if (bi < nbits)
47
416
    {
48
416
      return p[0] & (((mp_limb_t) 1 << bi) - 1);
49
416
    }
50
95.1k
  else
51
95.1k
    {
52
95.1k
      bi -= nbits;      /* bit index of low bit to extract */
53
95.1k
      i = bi / GMP_NUMB_BITS;   /* word index of low bit to extract */
54
95.1k
      bi %= GMP_NUMB_BITS;   /* bit index in low word */
55
95.1k
      r = p[i] >> bi;     /* extract (low) bits */
56
95.1k
      nbits_in_r = GMP_NUMB_BITS - bi;  /* number of bits now in r */
57
95.1k
      if (nbits_in_r < nbits)    /* did we get enough bits? */
58
9.04k
  r += p[i + 1] << nbits_in_r; /* prepend bits from higher word */
59
95.1k
      return r & (((mp_limb_t ) 1 << nbits) - 1);
60
95.1k
    }
61
95.5k
}
62
63
static inline unsigned
64
win_size (mp_bitcnt_t eb)
65
1.02k
{
66
1.02k
  unsigned k;
67
1.02k
  static mp_bitcnt_t x[] = {7,25,81,241,673,1793,4609,11521,28161,~(mp_bitcnt_t)0};
68
1.02k
  ASSERT (eb > 1);
69
3.21k
  for (k = 0; eb > x[k++];)
70
2.19k
    ;
71
1.02k
  return k;
72
1.02k
}
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
1.02k
{
84
1.02k
  unsigned cnt;
85
1.02k
  mp_bitcnt_t ebi;
86
1.02k
  unsigned windowsize, this_windowsize;
87
1.02k
  mp_limb_t expbits;
88
1.02k
  mp_limb_t *pp;
89
1.02k
  long i;
90
1.02k
  int flipflop;
91
1.02k
  TMP_DECL;
92
93
1.02k
  ASSERT (en > 1 || (en == 1 && ep[0] > 1));
94
95
1.02k
  TMP_MARK;
96
97
1.02k
  MPN_SIZEINBASE_2EXP(ebi, ep, en, 1);
98
99
1.02k
  windowsize = win_size (ebi);
100
1.02k
  if (windowsize > 1)
101
657
    {
102
657
      mp_limb_t *this_pp, *last_pp;
103
657
      ASSERT (windowsize < ebi);
104
105
657
      pp = TMP_ALLOC_LIMBS ((n << (windowsize - 1)));
106
107
657
      this_pp = pp;
108
109
657
      MPN_COPY (this_pp, bp, n);
110
111
      /* Store b^2 in tp.  */
112
657
      mpn_sqrlo (tp, bp, n);
113
114
      /* Precompute odd powers of b and put them in the temporary area at pp.  */
115
657
      i = (1 << (windowsize - 1)) - 1;
116
657
      do
117
15.7k
  {
118
15.7k
    last_pp = this_pp;
119
15.7k
    this_pp += n;
120
15.7k
    mpn_mullo_n (this_pp, last_pp, tp, n);
121
15.7k
  } while (--i != 0);
122
123
657
      expbits = getbits (ep, ebi, windowsize);
124
125
      /* THINK: Should we initialise the case expbits % 4 == 0 with a mullo? */
126
657
      count_trailing_zeros (cnt, expbits);
127
657
      ebi -= windowsize;
128
657
      ebi += cnt;
129
657
      expbits >>= cnt;
130
131
657
      MPN_COPY (rp, pp + n * (expbits >> 1), n);
132
657
    }
133
369
  else
134
369
    {
135
369
      pp = tp + n;
136
369
      MPN_COPY (pp, bp, n);
137
369
      MPN_COPY (rp, bp, n);
138
369
      --ebi;
139
369
    }
140
141
1.02k
  flipflop = 0;
142
143
1.02k
  do
144
95.6k
    {
145
324k
      while (getbit (ep, ebi) == 0)
146
229k
  {
147
229k
    mpn_sqrlo (tp, rp, n);
148
229k
    MP_PTR_SWAP (rp, tp);
149
229k
    flipflop = ! flipflop;
150
229k
    if (--ebi == 0)
151
745
      goto done;
152
229k
  }
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
94.9k
      expbits = getbits (ep, ebi, windowsize);
158
94.9k
      this_windowsize = MIN (windowsize, ebi);
159
94.9k
      ebi -= this_windowsize;
160
161
94.9k
      count_trailing_zeros (cnt, expbits);
162
94.9k
      this_windowsize -= cnt;
163
94.9k
      ebi += cnt;
164
94.9k
      expbits >>= cnt;
165
166
366k
      while (this_windowsize > 1)
167
271k
  {
168
271k
    mpn_sqrlo (tp, rp, n);
169
271k
    mpn_sqrlo (rp, tp, n);
170
271k
    this_windowsize -= 2;
171
271k
  }
172
173
94.9k
      if (this_windowsize != 0)
174
43.2k
  mpn_sqrlo (tp, rp, n);
175
51.6k
      else
176
51.6k
  {
177
51.6k
    MP_PTR_SWAP (rp, tp);
178
51.6k
    flipflop = ! flipflop;
179
51.6k
  }
180
181
94.9k
      mpn_mullo_n (rp, tp, pp + n * (expbits >> 1), n);
182
94.9k
    } while (ebi != 0);
183
184
1.02k
 done:
185
1.02k
  if (flipflop)
186
591
    MPN_COPY (tp, rp, n);
187
1.02k
  TMP_FREE;
188
1.02k
}