Coverage Report

Created: 2025-03-09 06:52

/src/gmp-6.2.1/mpn/hgcd2_jacobi.c
Line
Count
Source
1
/* hgcd2_jacobi.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, 2011 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
#if GMP_NAIL_BITS > 0
39
#error Nails not supported.
40
#endif
41
42
/* FIXME: Duplicated in hgcd2.c. Should move to gmp-impl.h, and
43
   possibly be renamed. */
44
static inline mp_limb_t
45
div1 (mp_ptr rp,
46
      mp_limb_t n0,
47
      mp_limb_t d0)
48
187k
{
49
187k
  mp_limb_t q = 0;
50
51
187k
  if ((mp_limb_signed_t) n0 < 0)
52
4.22k
    {
53
4.22k
      int cnt;
54
17.7k
      for (cnt = 1; (mp_limb_signed_t) d0 >= 0; cnt++)
55
13.5k
  {
56
13.5k
    d0 = d0 << 1;
57
13.5k
  }
58
59
4.22k
      q = 0;
60
22.0k
      while (cnt)
61
17.7k
  {
62
17.7k
    q <<= 1;
63
17.7k
    if (n0 >= d0)
64
8.92k
      {
65
8.92k
        n0 = n0 - d0;
66
8.92k
        q |= 1;
67
8.92k
      }
68
17.7k
    d0 = d0 >> 1;
69
17.7k
    cnt--;
70
17.7k
  }
71
4.22k
    }
72
183k
  else
73
183k
    {
74
183k
      int cnt;
75
661k
      for (cnt = 0; n0 >= d0; cnt++)
76
477k
  {
77
477k
    d0 = d0 << 1;
78
477k
  }
79
80
183k
      q = 0;
81
661k
      while (cnt)
82
477k
  {
83
477k
    d0 = d0 >> 1;
84
477k
    q <<= 1;
85
477k
    if (n0 >= d0)
86
304k
      {
87
304k
        n0 = n0 - d0;
88
304k
        q |= 1;
89
304k
      }
90
477k
    cnt--;
91
477k
  }
92
183k
    }
93
187k
  *rp = n0;
94
187k
  return q;
95
187k
}
96
97
/* Two-limb division optimized for small quotients.  */
98
static inline mp_limb_t
99
div2 (mp_ptr rp,
100
      mp_limb_t nh, mp_limb_t nl,
101
      mp_limb_t dh, mp_limb_t dl)
102
212k
{
103
212k
  mp_limb_t q = 0;
104
105
212k
  if ((mp_limb_signed_t) nh < 0)
106
10.0k
    {
107
10.0k
      int cnt;
108
72.6k
      for (cnt = 1; (mp_limb_signed_t) dh >= 0; cnt++)
109
62.6k
  {
110
62.6k
    dh = (dh << 1) | (dl >> (GMP_LIMB_BITS - 1));
111
62.6k
    dl = dl << 1;
112
62.6k
  }
113
114
82.7k
      while (cnt)
115
72.6k
  {
116
72.6k
    q <<= 1;
117
72.6k
    if (nh > dh || (nh == dh && nl >= dl))
118
36.6k
      {
119
36.6k
        sub_ddmmss (nh, nl, nh, nl, dh, dl);
120
36.6k
        q |= 1;
121
36.6k
      }
122
72.6k
    dl = (dh << (GMP_LIMB_BITS - 1)) | (dl >> 1);
123
72.6k
    dh = dh >> 1;
124
72.6k
    cnt--;
125
72.6k
  }
126
10.0k
    }
127
202k
  else
128
202k
    {
129
202k
      int cnt;
130
750k
      for (cnt = 0; nh > dh || (nh == dh && nl >= dl); cnt++)
131
547k
  {
132
547k
    dh = (dh << 1) | (dl >> (GMP_LIMB_BITS - 1));
133
547k
    dl = dl << 1;
134
547k
  }
135
136
750k
      while (cnt)
137
547k
  {
138
547k
    dl = (dh << (GMP_LIMB_BITS - 1)) | (dl >> 1);
139
547k
    dh = dh >> 1;
140
547k
    q <<= 1;
141
547k
    if (nh > dh || (nh == dh && nl >= dl))
142
345k
      {
143
345k
        sub_ddmmss (nh, nl, nh, nl, dh, dl);
144
345k
        q |= 1;
145
345k
      }
146
547k
    cnt--;
147
547k
  }
148
202k
    }
149
150
212k
  rp[0] = nl;
151
212k
  rp[1] = nh;
152
153
212k
  return q;
154
212k
}
155
156
int
157
mpn_hgcd2_jacobi (mp_limb_t ah, mp_limb_t al, mp_limb_t bh, mp_limb_t bl,
158
      struct hgcd_matrix1 *M, unsigned *bitsp)
159
20.0k
{
160
20.0k
  mp_limb_t u00, u01, u10, u11;
161
20.0k
  unsigned bits = *bitsp;
162
163
20.0k
  if (ah < 2 || bh < 2)
164
13
    return 0;
165
166
20.0k
  if (ah > bh || (ah == bh && al > bl))
167
10.2k
    {
168
10.2k
      sub_ddmmss (ah, al, ah, al, bh, bl);
169
10.2k
      if (ah < 2)
170
129
  return 0;
171
172
10.1k
      u00 = u01 = u11 = 1;
173
10.1k
      u10 = 0;
174
10.1k
      bits = mpn_jacobi_update (bits, 1, 1);
175
10.1k
    }
176
9.79k
  else
177
9.79k
    {
178
9.79k
      sub_ddmmss (bh, bl, bh, bl, ah, al);
179
9.79k
      if (bh < 2)
180
75
  return 0;
181
182
9.71k
      u00 = u10 = u11 = 1;
183
9.71k
      u01 = 0;
184
9.71k
      bits = mpn_jacobi_update (bits, 0, 1);
185
9.71k
    }
186
187
19.8k
  if (ah < bh)
188
9.78k
    goto subtract_a;
189
190
10.0k
  for (;;)
191
186k
    {
192
186k
      ASSERT (ah >= bh);
193
186k
      if (ah == bh)
194
43
  goto done;
195
196
186k
      if (ah < (CNST_LIMB(1) << (GMP_LIMB_BITS / 2)))
197
10.0k
  {
198
10.0k
    ah = (ah << (GMP_LIMB_BITS / 2) ) + (al >> (GMP_LIMB_BITS / 2));
199
10.0k
    bh = (bh << (GMP_LIMB_BITS / 2) ) + (bl >> (GMP_LIMB_BITS / 2));
200
201
10.0k
    break;
202
10.0k
  }
203
204
      /* Subtract a -= q b, and multiply M from the right by (1 q ; 0
205
   1), affecting the second column of M. */
206
176k
      ASSERT (ah > bh);
207
176k
      sub_ddmmss (ah, al, ah, al, bh, bl);
208
209
176k
      if (ah < 2)
210
7
  goto done;
211
212
176k
      if (ah <= bh)
213
70.1k
  {
214
    /* Use q = 1 */
215
70.1k
    u01 += u00;
216
70.1k
    u11 += u10;
217
70.1k
    bits = mpn_jacobi_update (bits, 1, 1);
218
70.1k
  }
219
106k
      else
220
106k
  {
221
106k
    mp_limb_t r[2];
222
106k
    mp_limb_t q = div2 (r, ah, al, bh, bl);
223
106k
    al = r[0]; ah = r[1];
224
106k
    if (ah < 2)
225
138
      {
226
        /* A is too small, but q is correct. */
227
138
        u01 += q * u00;
228
138
        u11 += q * u10;
229
138
        bits = mpn_jacobi_update (bits, 1, q & 3);
230
138
        goto done;
231
138
      }
232
105k
    q++;
233
105k
    u01 += q * u00;
234
105k
    u11 += q * u10;
235
105k
    bits = mpn_jacobi_update (bits, 1, q & 3);
236
105k
  }
237
185k
    subtract_a:
238
185k
      ASSERT (bh >= ah);
239
185k
      if (ah == bh)
240
48
  goto done;
241
242
185k
      if (bh < (CNST_LIMB(1) << (GMP_LIMB_BITS / 2)))
243
9.56k
  {
244
9.56k
    ah = (ah << (GMP_LIMB_BITS / 2) ) + (al >> (GMP_LIMB_BITS / 2));
245
9.56k
    bh = (bh << (GMP_LIMB_BITS / 2) ) + (bl >> (GMP_LIMB_BITS / 2));
246
247
9.56k
    goto subtract_a1;
248
9.56k
  }
249
250
      /* Subtract b -= q a, and multiply M from the right by (1 0 ; q
251
   1), affecting the first column of M. */
252
176k
      sub_ddmmss (bh, bl, bh, bl, ah, al);
253
254
176k
      if (bh < 2)
255
9
  goto done;
256
257
176k
      if (bh <= ah)
258
69.7k
  {
259
    /* Use q = 1 */
260
69.7k
    u00 += u01;
261
69.7k
    u10 += u11;
262
69.7k
    bits = mpn_jacobi_update (bits, 0, 1);
263
69.7k
  }
264
106k
      else
265
106k
  {
266
106k
    mp_limb_t r[2];
267
106k
    mp_limb_t q = div2 (r, bh, bl, ah, al);
268
106k
    bl = r[0]; bh = r[1];
269
106k
    if (bh < 2)
270
59
      {
271
        /* B is too small, but q is correct. */
272
59
        u00 += q * u01;
273
59
        u10 += q * u11;
274
59
        bits = mpn_jacobi_update (bits, 0, q & 3);
275
59
        goto done;
276
59
      }
277
106k
    q++;
278
106k
    u00 += q * u01;
279
106k
    u10 += q * u11;
280
106k
    bits = mpn_jacobi_update (bits, 0, q & 3);
281
106k
  }
282
176k
    }
283
284
  /* NOTE: Since we discard the least significant half limb, we don't
285
     get a truly maximal M (corresponding to |a - b| <
286
     2^{GMP_LIMB_BITS +1}). */
287
  /* Single precision loop */
288
10.0k
  for (;;)
289
165k
    {
290
165k
      ASSERT (ah >= bh);
291
165k
      if (ah == bh)
292
1
  break;
293
294
165k
      ah -= bh;
295
165k
      if (ah < (CNST_LIMB (1) << (GMP_LIMB_BITS / 2 + 1)))
296
4.47k
  break;
297
298
161k
      if (ah <= bh)
299
66.8k
  {
300
    /* Use q = 1 */
301
66.8k
    u01 += u00;
302
66.8k
    u11 += u10;
303
66.8k
    bits = mpn_jacobi_update (bits, 1, 1);
304
66.8k
  }
305
94.3k
      else
306
94.3k
  {
307
94.3k
    mp_limb_t r;
308
94.3k
    mp_limb_t q = div1 (&r, ah, bh);
309
94.3k
    ah = r;
310
94.3k
    if (ah < (CNST_LIMB(1) << (GMP_LIMB_BITS / 2 + 1)))
311
5.35k
      {
312
        /* A is too small, but q is correct. */
313
5.35k
        u01 += q * u00;
314
5.35k
        u11 += q * u10;
315
5.35k
        bits = mpn_jacobi_update (bits, 1, q & 3);
316
5.35k
        break;
317
5.35k
      }
318
88.9k
    q++;
319
88.9k
    u01 += q * u00;
320
88.9k
    u11 += q * u10;
321
88.9k
    bits = mpn_jacobi_update (bits, 1, q & 3);
322
88.9k
  }
323
165k
    subtract_a1:
324
165k
      ASSERT (bh >= ah);
325
165k
      if (ah == bh)
326
1
  break;
327
328
165k
      bh -= ah;
329
165k
      if (bh < (CNST_LIMB (1) << (GMP_LIMB_BITS / 2 + 1)))
330
4.43k
  break;
331
332
160k
      if (bh <= ah)
333
67.3k
  {
334
    /* Use q = 1 */
335
67.3k
    u00 += u01;
336
67.3k
    u10 += u11;
337
67.3k
    bits = mpn_jacobi_update (bits, 0, 1);
338
67.3k
  }
339
93.5k
      else
340
93.5k
  {
341
93.5k
    mp_limb_t r;
342
93.5k
    mp_limb_t q = div1 (&r, bh, ah);
343
93.5k
    bh = r;
344
93.5k
    if (bh < (CNST_LIMB(1) << (GMP_LIMB_BITS / 2 + 1)))
345
5.30k
      {
346
        /* B is too small, but q is correct. */
347
5.30k
        u00 += q * u01;
348
5.30k
        u10 += q * u11;
349
5.30k
        bits = mpn_jacobi_update (bits, 0, q & 3);
350
5.30k
        break;
351
5.30k
      }
352
88.2k
    q++;
353
88.2k
    u00 += q * u01;
354
88.2k
    u10 += q * u11;
355
88.2k
    bits = mpn_jacobi_update (bits, 0, q & 3);
356
88.2k
  }
357
160k
    }
358
359
19.8k
 done:
360
19.8k
  M->u[0][0] = u00; M->u[0][1] = u01;
361
19.8k
  M->u[1][0] = u10; M->u[1][1] = u11;
362
19.8k
  *bitsp = bits;
363
364
19.8k
  return 1;
365
10.0k
}