Coverage Report

Created: 2024-06-28 06:19

/src/gmp-6.2.1/mpn/jacobi_2.c
Line
Count
Source (jump to first uncovered line)
1
/* jacobi_2.c
2
3
   THE FUNCTIONS IN THIS FILE ARE INTERNAL WITH MUTABLE INTERFACES.  IT IS ONLY
4
   SAFE TO REACH THEM THROUGH DOCUMENTED INTERFACES.  IN FACT, IT IS ALMOST
5
   GUARANTEED THAT THEY'LL CHANGE OR DISAPPEAR IN A FUTURE GNU MP RELEASE.
6
7
Copyright 1996, 1998, 2000-2004, 2008, 2010 Free Software Foundation, Inc.
8
9
This file is part of the GNU MP Library.
10
11
The GNU MP Library is free software; you can redistribute it and/or modify
12
it under the terms of either:
13
14
  * the GNU Lesser General Public License as published by the Free
15
    Software Foundation; either version 3 of the License, or (at your
16
    option) any later version.
17
18
or
19
20
  * the GNU General Public License as published by the Free Software
21
    Foundation; either version 2 of the License, or (at your option) any
22
    later version.
23
24
or both in parallel, as here.
25
26
The GNU MP Library is distributed in the hope that it will be useful, but
27
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
28
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
29
for more details.
30
31
You should have received copies of the GNU General Public License and the
32
GNU Lesser General Public License along with the GNU MP Library.  If not,
33
see https://www.gnu.org/licenses/.  */
34
35
#include "gmp-impl.h"
36
#include "longlong.h"
37
38
#ifndef JACOBI_2_METHOD
39
#define JACOBI_2_METHOD 2
40
#endif
41
42
/* Computes (a / b) where b is odd, and a and b are otherwise arbitrary
43
   two-limb numbers. */
44
#if JACOBI_2_METHOD == 1
45
int
46
mpn_jacobi_2 (mp_srcptr ap, mp_srcptr bp, unsigned bit)
47
{
48
  mp_limb_t ah, al, bh, bl;
49
  int c;
50
51
  al = ap[0];
52
  ah = ap[1];
53
  bl = bp[0];
54
  bh = bp[1];
55
56
  ASSERT (bl & 1);
57
58
  bl = ((bh << (GMP_NUMB_BITS - 1)) & GMP_NUMB_MASK) | (bl >> 1);
59
  bh >>= 1;
60
61
  if ( (bh | bl) == 0)
62
    return 1 - 2*(bit & 1);
63
64
  if ( (ah | al) == 0)
65
    return 0;
66
67
  if (al == 0)
68
    {
69
      al = ah;
70
      ah = 0;
71
      bit ^= GMP_NUMB_BITS & (bl ^ (bl >> 1));
72
    }
73
  count_trailing_zeros (c, al);
74
  bit ^= c & (bl ^ (bl >> 1));
75
76
  c++;
77
  if (UNLIKELY (c == GMP_NUMB_BITS))
78
    {
79
      al = ah;
80
      ah = 0;
81
    }
82
  else
83
    {
84
      al = ((ah << (GMP_NUMB_BITS - c)) & GMP_NUMB_MASK) | (al >> c);
85
      ah >>= c;
86
    }
87
  while ( (ah | bh) > 0)
88
    {
89
      mp_limb_t th, tl;
90
      mp_limb_t bgta;
91
92
      sub_ddmmss (th, tl, ah, al, bh, bl);
93
      if ( (tl | th) == 0)
94
  return 0;
95
96
      bgta = LIMB_HIGHBIT_TO_MASK (th);
97
98
      /* If b > a, invoke reciprocity */
99
      bit ^= (bgta & al & bl);
100
101
      /* b <-- min (a, b) */
102
      add_ssaaaa (bh, bl, bh, bl, th & bgta, tl & bgta);
103
104
      if ( (bh | bl) == 0)
105
  return 1 - 2*(bit & 1);
106
107
      /* a <-- |a - b| */
108
      al = (bgta ^ tl) - bgta;
109
      ah = (bgta ^ th);
110
111
      if (UNLIKELY (al == 0))
112
  {
113
    /* If b > a, al == 0 implies that we have a carry to
114
       propagate. */
115
    al = ah - bgta;
116
    ah = 0;
117
    bit ^= GMP_NUMB_BITS & (bl ^ (bl >> 1));
118
  }
119
      count_trailing_zeros (c, al);
120
      c++;
121
      bit ^= c & (bl ^ (bl >> 1));
122
123
      if (UNLIKELY (c == GMP_NUMB_BITS))
124
  {
125
    al = ah;
126
    ah = 0;
127
  }
128
      else
129
  {
130
    al = ((ah << (GMP_NUMB_BITS - c)) & GMP_NUMB_MASK) | (al >> c);
131
    ah >>= c;
132
  }
133
    }
134
135
  ASSERT (bl > 0);
136
137
  while ( (al | bl) & GMP_LIMB_HIGHBIT)
138
    {
139
      /* Need an extra comparison to get the mask. */
140
      mp_limb_t t = al - bl;
141
      mp_limb_t bgta = - (bl > al);
142
143
      if (t == 0)
144
  return 0;
145
146
      /* If b > a, invoke reciprocity */
147
      bit ^= (bgta & al & bl);
148
149
      /* b <-- min (a, b) */
150
      bl += (bgta & t);
151
152
      /* a <-- |a - b| */
153
      al = (t ^ bgta) - bgta;
154
155
      /* Number of trailing zeros is the same no matter if we look at
156
       * t or a, but using t gives more parallelism. */
157
      count_trailing_zeros (c, t);
158
      c ++;
159
      /* (2/b) = -1 if b = 3 or 5 mod 8 */
160
      bit ^= c & (bl ^ (bl >> 1));
161
162
      if (UNLIKELY (c == GMP_NUMB_BITS))
163
  return 1 - 2*(bit & 1);
164
165
      al >>= c;
166
    }
167
168
  /* Here we have a little impedance mismatch. Better to inline it? */
169
  return mpn_jacobi_base (2*al+1, 2*bl+1, bit << 1);
170
}
171
#elif JACOBI_2_METHOD == 2
172
int
173
mpn_jacobi_2 (mp_srcptr ap, mp_srcptr bp, unsigned bit)
174
0
{
175
0
  mp_limb_t ah, al, bh, bl;
176
0
  int c;
177
178
0
  al = ap[0];
179
0
  ah = ap[1];
180
0
  bl = bp[0];
181
0
  bh = bp[1];
182
183
0
  ASSERT (bl & 1);
184
185
  /* Use bit 1. */
186
0
  bit <<= 1;
187
188
0
  if (bh == 0 && bl == 1)
189
    /* (a|1) = 1 */
190
0
    return 1 - (bit & 2);
191
192
0
  if (al == 0)
193
0
    {
194
0
      if (ah == 0)
195
  /* (0|b) = 0, b > 1 */
196
0
  return 0;
197
198
0
      count_trailing_zeros (c, ah);
199
0
      bit ^= ((GMP_NUMB_BITS + c) << 1) & (bl ^ (bl >> 1));
200
201
0
      al = bl;
202
0
      bl = ah >> c;
203
204
0
      if (bl == 1)
205
  /* (1|b) = 1 */
206
0
  return 1 - (bit & 2);
207
208
0
      ah = bh;
209
210
0
      bit ^= al & bl;
211
212
0
      goto b_reduced;
213
0
    }
214
0
  if ( (al & 1) == 0)
215
0
    {
216
0
      count_trailing_zeros (c, al);
217
218
0
      al = ((ah << (GMP_NUMB_BITS - c)) & GMP_NUMB_MASK) | (al >> c);
219
0
      ah >>= c;
220
0
      bit ^= (c << 1) & (bl ^ (bl >> 1));
221
0
    }
222
0
  if (ah == 0)
223
0
    {
224
0
      if (bh > 0)
225
0
  {
226
0
    bit ^= al & bl;
227
0
    MP_LIMB_T_SWAP (al, bl);
228
0
    ah = bh;
229
0
    goto b_reduced;
230
0
  }
231
0
      goto ab_reduced;
232
0
    }
233
234
0
  while (bh > 0)
235
0
    {
236
      /* Compute (a|b) */
237
0
      while (ah > bh)
238
0
  {
239
0
    sub_ddmmss (ah, al, ah, al, bh, bl);
240
0
    if (al == 0)
241
0
      {
242
0
        count_trailing_zeros (c, ah);
243
0
        bit ^= ((GMP_NUMB_BITS + c) << 1) & (bl ^ (bl >> 1));
244
245
0
        al = bl;
246
0
        bl = ah >> c;
247
0
        ah = bh;
248
249
0
        bit ^= al & bl;
250
0
        goto b_reduced;
251
0
      }
252
0
    count_trailing_zeros (c, al);
253
0
    bit ^= (c << 1) & (bl ^ (bl >> 1));
254
0
    al = ((ah << (GMP_NUMB_BITS - c)) & GMP_NUMB_MASK) | (al >> c);
255
0
    ah >>= c;
256
0
  }
257
0
      if (ah == bh)
258
0
  goto cancel_hi;
259
260
0
      if (ah == 0)
261
0
  {
262
0
    bit ^= al & bl;
263
0
    MP_LIMB_T_SWAP (al, bl);
264
0
    ah = bh;
265
0
    break;
266
0
  }
267
268
0
      bit ^= al & bl;
269
270
      /* Compute (b|a) */
271
0
      while (bh > ah)
272
0
  {
273
0
    sub_ddmmss (bh, bl, bh, bl, ah, al);
274
0
    if (bl == 0)
275
0
      {
276
0
        count_trailing_zeros (c, bh);
277
0
        bit ^= ((GMP_NUMB_BITS + c) << 1) & (al ^ (al >> 1));
278
279
0
        bl = bh >> c;
280
0
        bit ^= al & bl;
281
0
        goto b_reduced;
282
0
      }
283
0
    count_trailing_zeros (c, bl);
284
0
    bit ^= (c << 1) & (al ^ (al >> 1));
285
0
    bl = ((bh << (GMP_NUMB_BITS - c)) & GMP_NUMB_MASK) | (bl >> c);
286
0
    bh >>= c;
287
0
  }
288
0
      bit ^= al & bl;
289
290
      /* Compute (a|b) */
291
0
      if (ah == bh)
292
0
  {
293
0
  cancel_hi:
294
0
    if (al < bl)
295
0
      {
296
0
        MP_LIMB_T_SWAP (al, bl);
297
0
        bit ^= al & bl;
298
0
      }
299
0
    al -= bl;
300
0
    if (al == 0)
301
0
      return 0;
302
303
0
    count_trailing_zeros (c, al);
304
0
    bit ^= (c << 1) & (bl ^ (bl >> 1));
305
0
    al >>= c;
306
307
0
    if (al == 1)
308
0
      return 1 - (bit & 2);
309
310
0
    MP_LIMB_T_SWAP (al, bl);
311
0
    bit ^= al & bl;
312
0
    break;
313
0
  }
314
0
    }
315
316
0
 b_reduced:
317
  /* Compute (a|b), with b a single limb. */
318
0
  ASSERT (bl & 1);
319
320
0
  if (bl == 1)
321
    /* (a|1) = 1 */
322
0
    return 1 - (bit & 2);
323
324
0
  while (ah > 0)
325
0
    {
326
0
      ah -= (al < bl);
327
0
      al -= bl;
328
0
      if (al == 0)
329
0
  {
330
0
    if (ah == 0)
331
0
      return 0;
332
0
    count_trailing_zeros (c, ah);
333
0
    bit ^= ((GMP_NUMB_BITS + c) << 1) & (bl ^ (bl >> 1));
334
0
    al = ah >> c;
335
0
    goto ab_reduced;
336
0
  }
337
0
      count_trailing_zeros (c, al);
338
339
0
      al = ((ah << (GMP_NUMB_BITS - c)) & GMP_NUMB_MASK) | (al >> c);
340
0
      ah >>= c;
341
0
      bit ^= (c << 1) & (bl ^ (bl >> 1));
342
0
    }
343
0
 ab_reduced:
344
0
  ASSERT (bl & 1);
345
0
  ASSERT (bl > 1);
346
347
0
  return mpn_jacobi_base (al, bl, bit);
348
0
}
349
#else
350
#error Unsupported value for JACOBI_2_METHOD
351
#endif