Coverage Report

Created: 2025-12-31 06:37

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