/src/gmp-6.2.1/mpn/hgcd2_jacobi.c
Line | Count | Source (jump to first uncovered line) |
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 | 0 | { |
49 | 0 | mp_limb_t q = 0; |
50 | |
|
51 | 0 | if ((mp_limb_signed_t) n0 < 0) |
52 | 0 | { |
53 | 0 | int cnt; |
54 | 0 | for (cnt = 1; (mp_limb_signed_t) d0 >= 0; cnt++) |
55 | 0 | { |
56 | 0 | d0 = d0 << 1; |
57 | 0 | } |
58 | |
|
59 | 0 | q = 0; |
60 | 0 | while (cnt) |
61 | 0 | { |
62 | 0 | q <<= 1; |
63 | 0 | if (n0 >= d0) |
64 | 0 | { |
65 | 0 | n0 = n0 - d0; |
66 | 0 | q |= 1; |
67 | 0 | } |
68 | 0 | d0 = d0 >> 1; |
69 | 0 | cnt--; |
70 | 0 | } |
71 | 0 | } |
72 | 0 | else |
73 | 0 | { |
74 | 0 | int cnt; |
75 | 0 | for (cnt = 0; n0 >= d0; cnt++) |
76 | 0 | { |
77 | 0 | d0 = d0 << 1; |
78 | 0 | } |
79 | |
|
80 | 0 | q = 0; |
81 | 0 | while (cnt) |
82 | 0 | { |
83 | 0 | d0 = d0 >> 1; |
84 | 0 | q <<= 1; |
85 | 0 | if (n0 >= d0) |
86 | 0 | { |
87 | 0 | n0 = n0 - d0; |
88 | 0 | q |= 1; |
89 | 0 | } |
90 | 0 | cnt--; |
91 | 0 | } |
92 | 0 | } |
93 | 0 | *rp = n0; |
94 | 0 | return q; |
95 | 0 | } |
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 | 0 | { |
103 | 0 | mp_limb_t q = 0; |
104 | |
|
105 | 0 | if ((mp_limb_signed_t) nh < 0) |
106 | 0 | { |
107 | 0 | int cnt; |
108 | 0 | for (cnt = 1; (mp_limb_signed_t) dh >= 0; cnt++) |
109 | 0 | { |
110 | 0 | dh = (dh << 1) | (dl >> (GMP_LIMB_BITS - 1)); |
111 | 0 | dl = dl << 1; |
112 | 0 | } |
113 | |
|
114 | 0 | while (cnt) |
115 | 0 | { |
116 | 0 | q <<= 1; |
117 | 0 | if (nh > dh || (nh == dh && nl >= dl)) |
118 | 0 | { |
119 | 0 | sub_ddmmss (nh, nl, nh, nl, dh, dl); |
120 | 0 | q |= 1; |
121 | 0 | } |
122 | 0 | dl = (dh << (GMP_LIMB_BITS - 1)) | (dl >> 1); |
123 | 0 | dh = dh >> 1; |
124 | 0 | cnt--; |
125 | 0 | } |
126 | 0 | } |
127 | 0 | else |
128 | 0 | { |
129 | 0 | int cnt; |
130 | 0 | for (cnt = 0; nh > dh || (nh == dh && nl >= dl); cnt++) |
131 | 0 | { |
132 | 0 | dh = (dh << 1) | (dl >> (GMP_LIMB_BITS - 1)); |
133 | 0 | dl = dl << 1; |
134 | 0 | } |
135 | |
|
136 | 0 | while (cnt) |
137 | 0 | { |
138 | 0 | dl = (dh << (GMP_LIMB_BITS - 1)) | (dl >> 1); |
139 | 0 | dh = dh >> 1; |
140 | 0 | q <<= 1; |
141 | 0 | if (nh > dh || (nh == dh && nl >= dl)) |
142 | 0 | { |
143 | 0 | sub_ddmmss (nh, nl, nh, nl, dh, dl); |
144 | 0 | q |= 1; |
145 | 0 | } |
146 | 0 | cnt--; |
147 | 0 | } |
148 | 0 | } |
149 | |
|
150 | 0 | rp[0] = nl; |
151 | 0 | rp[1] = nh; |
152 | |
|
153 | 0 | return q; |
154 | 0 | } |
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 | 0 | { |
160 | 0 | mp_limb_t u00, u01, u10, u11; |
161 | 0 | unsigned bits = *bitsp; |
162 | |
|
163 | 0 | if (ah < 2 || bh < 2) |
164 | 0 | return 0; |
165 | | |
166 | 0 | if (ah > bh || (ah == bh && al > bl)) |
167 | 0 | { |
168 | 0 | sub_ddmmss (ah, al, ah, al, bh, bl); |
169 | 0 | if (ah < 2) |
170 | 0 | return 0; |
171 | | |
172 | 0 | u00 = u01 = u11 = 1; |
173 | 0 | u10 = 0; |
174 | 0 | bits = mpn_jacobi_update (bits, 1, 1); |
175 | 0 | } |
176 | 0 | else |
177 | 0 | { |
178 | 0 | sub_ddmmss (bh, bl, bh, bl, ah, al); |
179 | 0 | if (bh < 2) |
180 | 0 | return 0; |
181 | | |
182 | 0 | u00 = u10 = u11 = 1; |
183 | 0 | u01 = 0; |
184 | 0 | bits = mpn_jacobi_update (bits, 0, 1); |
185 | 0 | } |
186 | | |
187 | 0 | if (ah < bh) |
188 | 0 | goto subtract_a; |
189 | | |
190 | 0 | for (;;) |
191 | 0 | { |
192 | 0 | ASSERT (ah >= bh); |
193 | 0 | if (ah == bh) |
194 | 0 | goto done; |
195 | | |
196 | 0 | if (ah < (CNST_LIMB(1) << (GMP_LIMB_BITS / 2))) |
197 | 0 | { |
198 | 0 | ah = (ah << (GMP_LIMB_BITS / 2) ) + (al >> (GMP_LIMB_BITS / 2)); |
199 | 0 | bh = (bh << (GMP_LIMB_BITS / 2) ) + (bl >> (GMP_LIMB_BITS / 2)); |
200 | |
|
201 | 0 | break; |
202 | 0 | } |
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 | 0 | ASSERT (ah > bh); |
207 | 0 | sub_ddmmss (ah, al, ah, al, bh, bl); |
208 | |
|
209 | 0 | if (ah < 2) |
210 | 0 | goto done; |
211 | | |
212 | 0 | if (ah <= bh) |
213 | 0 | { |
214 | | /* Use q = 1 */ |
215 | 0 | u01 += u00; |
216 | 0 | u11 += u10; |
217 | 0 | bits = mpn_jacobi_update (bits, 1, 1); |
218 | 0 | } |
219 | 0 | else |
220 | 0 | { |
221 | 0 | mp_limb_t r[2]; |
222 | 0 | mp_limb_t q = div2 (r, ah, al, bh, bl); |
223 | 0 | al = r[0]; ah = r[1]; |
224 | 0 | if (ah < 2) |
225 | 0 | { |
226 | | /* A is too small, but q is correct. */ |
227 | 0 | u01 += q * u00; |
228 | 0 | u11 += q * u10; |
229 | 0 | bits = mpn_jacobi_update (bits, 1, q & 3); |
230 | 0 | goto done; |
231 | 0 | } |
232 | 0 | q++; |
233 | 0 | u01 += q * u00; |
234 | 0 | u11 += q * u10; |
235 | 0 | bits = mpn_jacobi_update (bits, 1, q & 3); |
236 | 0 | } |
237 | 0 | subtract_a: |
238 | 0 | ASSERT (bh >= ah); |
239 | 0 | if (ah == bh) |
240 | 0 | goto done; |
241 | | |
242 | 0 | if (bh < (CNST_LIMB(1) << (GMP_LIMB_BITS / 2))) |
243 | 0 | { |
244 | 0 | ah = (ah << (GMP_LIMB_BITS / 2) ) + (al >> (GMP_LIMB_BITS / 2)); |
245 | 0 | bh = (bh << (GMP_LIMB_BITS / 2) ) + (bl >> (GMP_LIMB_BITS / 2)); |
246 | |
|
247 | 0 | goto subtract_a1; |
248 | 0 | } |
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 | 0 | sub_ddmmss (bh, bl, bh, bl, ah, al); |
253 | |
|
254 | 0 | if (bh < 2) |
255 | 0 | goto done; |
256 | | |
257 | 0 | if (bh <= ah) |
258 | 0 | { |
259 | | /* Use q = 1 */ |
260 | 0 | u00 += u01; |
261 | 0 | u10 += u11; |
262 | 0 | bits = mpn_jacobi_update (bits, 0, 1); |
263 | 0 | } |
264 | 0 | else |
265 | 0 | { |
266 | 0 | mp_limb_t r[2]; |
267 | 0 | mp_limb_t q = div2 (r, bh, bl, ah, al); |
268 | 0 | bl = r[0]; bh = r[1]; |
269 | 0 | if (bh < 2) |
270 | 0 | { |
271 | | /* B is too small, but q is correct. */ |
272 | 0 | u00 += q * u01; |
273 | 0 | u10 += q * u11; |
274 | 0 | bits = mpn_jacobi_update (bits, 0, q & 3); |
275 | 0 | goto done; |
276 | 0 | } |
277 | 0 | q++; |
278 | 0 | u00 += q * u01; |
279 | 0 | u10 += q * u11; |
280 | 0 | bits = mpn_jacobi_update (bits, 0, q & 3); |
281 | 0 | } |
282 | 0 | } |
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 | 0 | for (;;) |
289 | 0 | { |
290 | 0 | ASSERT (ah >= bh); |
291 | 0 | if (ah == bh) |
292 | 0 | break; |
293 | | |
294 | 0 | ah -= bh; |
295 | 0 | if (ah < (CNST_LIMB (1) << (GMP_LIMB_BITS / 2 + 1))) |
296 | 0 | break; |
297 | | |
298 | 0 | if (ah <= bh) |
299 | 0 | { |
300 | | /* Use q = 1 */ |
301 | 0 | u01 += u00; |
302 | 0 | u11 += u10; |
303 | 0 | bits = mpn_jacobi_update (bits, 1, 1); |
304 | 0 | } |
305 | 0 | else |
306 | 0 | { |
307 | 0 | mp_limb_t r; |
308 | 0 | mp_limb_t q = div1 (&r, ah, bh); |
309 | 0 | ah = r; |
310 | 0 | if (ah < (CNST_LIMB(1) << (GMP_LIMB_BITS / 2 + 1))) |
311 | 0 | { |
312 | | /* A is too small, but q is correct. */ |
313 | 0 | u01 += q * u00; |
314 | 0 | u11 += q * u10; |
315 | 0 | bits = mpn_jacobi_update (bits, 1, q & 3); |
316 | 0 | break; |
317 | 0 | } |
318 | 0 | q++; |
319 | 0 | u01 += q * u00; |
320 | 0 | u11 += q * u10; |
321 | 0 | bits = mpn_jacobi_update (bits, 1, q & 3); |
322 | 0 | } |
323 | 0 | subtract_a1: |
324 | 0 | ASSERT (bh >= ah); |
325 | 0 | if (ah == bh) |
326 | 0 | break; |
327 | | |
328 | 0 | bh -= ah; |
329 | 0 | if (bh < (CNST_LIMB (1) << (GMP_LIMB_BITS / 2 + 1))) |
330 | 0 | break; |
331 | | |
332 | 0 | if (bh <= ah) |
333 | 0 | { |
334 | | /* Use q = 1 */ |
335 | 0 | u00 += u01; |
336 | 0 | u10 += u11; |
337 | 0 | bits = mpn_jacobi_update (bits, 0, 1); |
338 | 0 | } |
339 | 0 | else |
340 | 0 | { |
341 | 0 | mp_limb_t r; |
342 | 0 | mp_limb_t q = div1 (&r, bh, ah); |
343 | 0 | bh = r; |
344 | 0 | if (bh < (CNST_LIMB(1) << (GMP_LIMB_BITS / 2 + 1))) |
345 | 0 | { |
346 | | /* B is too small, but q is correct. */ |
347 | 0 | u00 += q * u01; |
348 | 0 | u10 += q * u11; |
349 | 0 | bits = mpn_jacobi_update (bits, 0, q & 3); |
350 | 0 | break; |
351 | 0 | } |
352 | 0 | q++; |
353 | 0 | u00 += q * u01; |
354 | 0 | u10 += q * u11; |
355 | 0 | bits = mpn_jacobi_update (bits, 0, q & 3); |
356 | 0 | } |
357 | 0 | } |
358 | | |
359 | 0 | done: |
360 | 0 | M->u[0][0] = u00; M->u[0][1] = u01; |
361 | 0 | M->u[1][0] = u10; M->u[1][1] = u11; |
362 | 0 | *bitsp = bits; |
363 | |
|
364 | 0 | return 1; |
365 | 0 | } |