hgcd2_jacobi.c revision 1.1.1.1.8.2 1 1.1.1.1.8.2 tls /* hgcd2_jacobi.c
2 1.1.1.1.8.2 tls
3 1.1.1.1.8.2 tls THE FUNCTIONS IN THIS FILE ARE INTERNAL WITH MUTABLE INTERFACES. IT IS ONLY
4 1.1.1.1.8.2 tls SAFE TO REACH THEM THROUGH DOCUMENTED INTERFACES. IN FACT, IT IS ALMOST
5 1.1.1.1.8.2 tls GUARANTEED THAT THEY'LL CHANGE OR DISAPPEAR IN A FUTURE GNU MP RELEASE.
6 1.1.1.1.8.2 tls
7 1.1.1.1.8.2 tls Copyright 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2008, 2011 Free Software
8 1.1.1.1.8.2 tls Foundation, Inc.
9 1.1.1.1.8.2 tls
10 1.1.1.1.8.2 tls This file is part of the GNU MP Library.
11 1.1.1.1.8.2 tls
12 1.1.1.1.8.2 tls The GNU MP Library is free software; you can redistribute it and/or modify
13 1.1.1.1.8.2 tls it under the terms of the GNU Lesser General Public License as published by
14 1.1.1.1.8.2 tls the Free Software Foundation; either version 3 of the License, or (at your
15 1.1.1.1.8.2 tls option) any later version.
16 1.1.1.1.8.2 tls
17 1.1.1.1.8.2 tls The GNU MP Library is distributed in the hope that it will be useful, but
18 1.1.1.1.8.2 tls WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 1.1.1.1.8.2 tls or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
20 1.1.1.1.8.2 tls License for more details.
21 1.1.1.1.8.2 tls
22 1.1.1.1.8.2 tls You should have received a copy of the GNU Lesser General Public License
23 1.1.1.1.8.2 tls along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
24 1.1.1.1.8.2 tls
25 1.1.1.1.8.2 tls #include "gmp.h"
26 1.1.1.1.8.2 tls #include "gmp-impl.h"
27 1.1.1.1.8.2 tls #include "longlong.h"
28 1.1.1.1.8.2 tls
29 1.1.1.1.8.2 tls #if GMP_NAIL_BITS > 0
30 1.1.1.1.8.2 tls #error Nails not supported.
31 1.1.1.1.8.2 tls #endif
32 1.1.1.1.8.2 tls
33 1.1.1.1.8.2 tls /* FIXME: Duplicated in hgcd2.c. Should move to gmp-impl.h, and
34 1.1.1.1.8.2 tls possibly be renamed. */
35 1.1.1.1.8.2 tls static inline mp_limb_t
36 1.1.1.1.8.2 tls div1 (mp_ptr rp,
37 1.1.1.1.8.2 tls mp_limb_t n0,
38 1.1.1.1.8.2 tls mp_limb_t d0)
39 1.1.1.1.8.2 tls {
40 1.1.1.1.8.2 tls mp_limb_t q = 0;
41 1.1.1.1.8.2 tls
42 1.1.1.1.8.2 tls if ((mp_limb_signed_t) n0 < 0)
43 1.1.1.1.8.2 tls {
44 1.1.1.1.8.2 tls int cnt;
45 1.1.1.1.8.2 tls for (cnt = 1; (mp_limb_signed_t) d0 >= 0; cnt++)
46 1.1.1.1.8.2 tls {
47 1.1.1.1.8.2 tls d0 = d0 << 1;
48 1.1.1.1.8.2 tls }
49 1.1.1.1.8.2 tls
50 1.1.1.1.8.2 tls q = 0;
51 1.1.1.1.8.2 tls while (cnt)
52 1.1.1.1.8.2 tls {
53 1.1.1.1.8.2 tls q <<= 1;
54 1.1.1.1.8.2 tls if (n0 >= d0)
55 1.1.1.1.8.2 tls {
56 1.1.1.1.8.2 tls n0 = n0 - d0;
57 1.1.1.1.8.2 tls q |= 1;
58 1.1.1.1.8.2 tls }
59 1.1.1.1.8.2 tls d0 = d0 >> 1;
60 1.1.1.1.8.2 tls cnt--;
61 1.1.1.1.8.2 tls }
62 1.1.1.1.8.2 tls }
63 1.1.1.1.8.2 tls else
64 1.1.1.1.8.2 tls {
65 1.1.1.1.8.2 tls int cnt;
66 1.1.1.1.8.2 tls for (cnt = 0; n0 >= d0; cnt++)
67 1.1.1.1.8.2 tls {
68 1.1.1.1.8.2 tls d0 = d0 << 1;
69 1.1.1.1.8.2 tls }
70 1.1.1.1.8.2 tls
71 1.1.1.1.8.2 tls q = 0;
72 1.1.1.1.8.2 tls while (cnt)
73 1.1.1.1.8.2 tls {
74 1.1.1.1.8.2 tls d0 = d0 >> 1;
75 1.1.1.1.8.2 tls q <<= 1;
76 1.1.1.1.8.2 tls if (n0 >= d0)
77 1.1.1.1.8.2 tls {
78 1.1.1.1.8.2 tls n0 = n0 - d0;
79 1.1.1.1.8.2 tls q |= 1;
80 1.1.1.1.8.2 tls }
81 1.1.1.1.8.2 tls cnt--;
82 1.1.1.1.8.2 tls }
83 1.1.1.1.8.2 tls }
84 1.1.1.1.8.2 tls *rp = n0;
85 1.1.1.1.8.2 tls return q;
86 1.1.1.1.8.2 tls }
87 1.1.1.1.8.2 tls
88 1.1.1.1.8.2 tls /* Two-limb division optimized for small quotients. */
89 1.1.1.1.8.2 tls static inline mp_limb_t
90 1.1.1.1.8.2 tls div2 (mp_ptr rp,
91 1.1.1.1.8.2 tls mp_limb_t nh, mp_limb_t nl,
92 1.1.1.1.8.2 tls mp_limb_t dh, mp_limb_t dl)
93 1.1.1.1.8.2 tls {
94 1.1.1.1.8.2 tls mp_limb_t q = 0;
95 1.1.1.1.8.2 tls
96 1.1.1.1.8.2 tls if ((mp_limb_signed_t) nh < 0)
97 1.1.1.1.8.2 tls {
98 1.1.1.1.8.2 tls int cnt;
99 1.1.1.1.8.2 tls for (cnt = 1; (mp_limb_signed_t) dh >= 0; cnt++)
100 1.1.1.1.8.2 tls {
101 1.1.1.1.8.2 tls dh = (dh << 1) | (dl >> (GMP_LIMB_BITS - 1));
102 1.1.1.1.8.2 tls dl = dl << 1;
103 1.1.1.1.8.2 tls }
104 1.1.1.1.8.2 tls
105 1.1.1.1.8.2 tls while (cnt)
106 1.1.1.1.8.2 tls {
107 1.1.1.1.8.2 tls q <<= 1;
108 1.1.1.1.8.2 tls if (nh > dh || (nh == dh && nl >= dl))
109 1.1.1.1.8.2 tls {
110 1.1.1.1.8.2 tls sub_ddmmss (nh, nl, nh, nl, dh, dl);
111 1.1.1.1.8.2 tls q |= 1;
112 1.1.1.1.8.2 tls }
113 1.1.1.1.8.2 tls dl = (dh << (GMP_LIMB_BITS - 1)) | (dl >> 1);
114 1.1.1.1.8.2 tls dh = dh >> 1;
115 1.1.1.1.8.2 tls cnt--;
116 1.1.1.1.8.2 tls }
117 1.1.1.1.8.2 tls }
118 1.1.1.1.8.2 tls else
119 1.1.1.1.8.2 tls {
120 1.1.1.1.8.2 tls int cnt;
121 1.1.1.1.8.2 tls for (cnt = 0; nh > dh || (nh == dh && nl >= dl); cnt++)
122 1.1.1.1.8.2 tls {
123 1.1.1.1.8.2 tls dh = (dh << 1) | (dl >> (GMP_LIMB_BITS - 1));
124 1.1.1.1.8.2 tls dl = dl << 1;
125 1.1.1.1.8.2 tls }
126 1.1.1.1.8.2 tls
127 1.1.1.1.8.2 tls while (cnt)
128 1.1.1.1.8.2 tls {
129 1.1.1.1.8.2 tls dl = (dh << (GMP_LIMB_BITS - 1)) | (dl >> 1);
130 1.1.1.1.8.2 tls dh = dh >> 1;
131 1.1.1.1.8.2 tls q <<= 1;
132 1.1.1.1.8.2 tls if (nh > dh || (nh == dh && nl >= dl))
133 1.1.1.1.8.2 tls {
134 1.1.1.1.8.2 tls sub_ddmmss (nh, nl, nh, nl, dh, dl);
135 1.1.1.1.8.2 tls q |= 1;
136 1.1.1.1.8.2 tls }
137 1.1.1.1.8.2 tls cnt--;
138 1.1.1.1.8.2 tls }
139 1.1.1.1.8.2 tls }
140 1.1.1.1.8.2 tls
141 1.1.1.1.8.2 tls rp[0] = nl;
142 1.1.1.1.8.2 tls rp[1] = nh;
143 1.1.1.1.8.2 tls
144 1.1.1.1.8.2 tls return q;
145 1.1.1.1.8.2 tls }
146 1.1.1.1.8.2 tls
147 1.1.1.1.8.2 tls int
148 1.1.1.1.8.2 tls mpn_hgcd2_jacobi (mp_limb_t ah, mp_limb_t al, mp_limb_t bh, mp_limb_t bl,
149 1.1.1.1.8.2 tls struct hgcd_matrix1 *M, unsigned *bitsp)
150 1.1.1.1.8.2 tls {
151 1.1.1.1.8.2 tls mp_limb_t u00, u01, u10, u11;
152 1.1.1.1.8.2 tls unsigned bits = *bitsp;
153 1.1.1.1.8.2 tls
154 1.1.1.1.8.2 tls if (ah < 2 || bh < 2)
155 1.1.1.1.8.2 tls return 0;
156 1.1.1.1.8.2 tls
157 1.1.1.1.8.2 tls if (ah > bh || (ah == bh && al > bl))
158 1.1.1.1.8.2 tls {
159 1.1.1.1.8.2 tls sub_ddmmss (ah, al, ah, al, bh, bl);
160 1.1.1.1.8.2 tls if (ah < 2)
161 1.1.1.1.8.2 tls return 0;
162 1.1.1.1.8.2 tls
163 1.1.1.1.8.2 tls u00 = u01 = u11 = 1;
164 1.1.1.1.8.2 tls u10 = 0;
165 1.1.1.1.8.2 tls bits = mpn_jacobi_update (bits, 1, 1);
166 1.1.1.1.8.2 tls }
167 1.1.1.1.8.2 tls else
168 1.1.1.1.8.2 tls {
169 1.1.1.1.8.2 tls sub_ddmmss (bh, bl, bh, bl, ah, al);
170 1.1.1.1.8.2 tls if (bh < 2)
171 1.1.1.1.8.2 tls return 0;
172 1.1.1.1.8.2 tls
173 1.1.1.1.8.2 tls u00 = u10 = u11 = 1;
174 1.1.1.1.8.2 tls u01 = 0;
175 1.1.1.1.8.2 tls bits = mpn_jacobi_update (bits, 0, 1);
176 1.1.1.1.8.2 tls }
177 1.1.1.1.8.2 tls
178 1.1.1.1.8.2 tls if (ah < bh)
179 1.1.1.1.8.2 tls goto subtract_a;
180 1.1.1.1.8.2 tls
181 1.1.1.1.8.2 tls for (;;)
182 1.1.1.1.8.2 tls {
183 1.1.1.1.8.2 tls ASSERT (ah >= bh);
184 1.1.1.1.8.2 tls if (ah == bh)
185 1.1.1.1.8.2 tls goto done;
186 1.1.1.1.8.2 tls
187 1.1.1.1.8.2 tls if (ah < (CNST_LIMB(1) << (GMP_LIMB_BITS / 2)))
188 1.1.1.1.8.2 tls {
189 1.1.1.1.8.2 tls ah = (ah << (GMP_LIMB_BITS / 2) ) + (al >> (GMP_LIMB_BITS / 2));
190 1.1.1.1.8.2 tls bh = (bh << (GMP_LIMB_BITS / 2) ) + (bl >> (GMP_LIMB_BITS / 2));
191 1.1.1.1.8.2 tls
192 1.1.1.1.8.2 tls break;
193 1.1.1.1.8.2 tls }
194 1.1.1.1.8.2 tls
195 1.1.1.1.8.2 tls /* Subtract a -= q b, and multiply M from the right by (1 q ; 0
196 1.1.1.1.8.2 tls 1), affecting the second column of M. */
197 1.1.1.1.8.2 tls ASSERT (ah > bh);
198 1.1.1.1.8.2 tls sub_ddmmss (ah, al, ah, al, bh, bl);
199 1.1.1.1.8.2 tls
200 1.1.1.1.8.2 tls if (ah < 2)
201 1.1.1.1.8.2 tls goto done;
202 1.1.1.1.8.2 tls
203 1.1.1.1.8.2 tls if (ah <= bh)
204 1.1.1.1.8.2 tls {
205 1.1.1.1.8.2 tls /* Use q = 1 */
206 1.1.1.1.8.2 tls u01 += u00;
207 1.1.1.1.8.2 tls u11 += u10;
208 1.1.1.1.8.2 tls bits = mpn_jacobi_update (bits, 1, 1);
209 1.1.1.1.8.2 tls }
210 1.1.1.1.8.2 tls else
211 1.1.1.1.8.2 tls {
212 1.1.1.1.8.2 tls mp_limb_t r[2];
213 1.1.1.1.8.2 tls mp_limb_t q = div2 (r, ah, al, bh, bl);
214 1.1.1.1.8.2 tls al = r[0]; ah = r[1];
215 1.1.1.1.8.2 tls if (ah < 2)
216 1.1.1.1.8.2 tls {
217 1.1.1.1.8.2 tls /* A is too small, but q is correct. */
218 1.1.1.1.8.2 tls u01 += q * u00;
219 1.1.1.1.8.2 tls u11 += q * u10;
220 1.1.1.1.8.2 tls bits = mpn_jacobi_update (bits, 1, q & 3);
221 1.1.1.1.8.2 tls goto done;
222 1.1.1.1.8.2 tls }
223 1.1.1.1.8.2 tls q++;
224 1.1.1.1.8.2 tls u01 += q * u00;
225 1.1.1.1.8.2 tls u11 += q * u10;
226 1.1.1.1.8.2 tls bits = mpn_jacobi_update (bits, 1, q & 3);
227 1.1.1.1.8.2 tls }
228 1.1.1.1.8.2 tls subtract_a:
229 1.1.1.1.8.2 tls ASSERT (bh >= ah);
230 1.1.1.1.8.2 tls if (ah == bh)
231 1.1.1.1.8.2 tls goto done;
232 1.1.1.1.8.2 tls
233 1.1.1.1.8.2 tls if (bh < (CNST_LIMB(1) << (GMP_LIMB_BITS / 2)))
234 1.1.1.1.8.2 tls {
235 1.1.1.1.8.2 tls ah = (ah << (GMP_LIMB_BITS / 2) ) + (al >> (GMP_LIMB_BITS / 2));
236 1.1.1.1.8.2 tls bh = (bh << (GMP_LIMB_BITS / 2) ) + (bl >> (GMP_LIMB_BITS / 2));
237 1.1.1.1.8.2 tls
238 1.1.1.1.8.2 tls goto subtract_a1;
239 1.1.1.1.8.2 tls }
240 1.1.1.1.8.2 tls
241 1.1.1.1.8.2 tls /* Subtract b -= q a, and multiply M from the right by (1 0 ; q
242 1.1.1.1.8.2 tls 1), affecting the first column of M. */
243 1.1.1.1.8.2 tls sub_ddmmss (bh, bl, bh, bl, ah, al);
244 1.1.1.1.8.2 tls
245 1.1.1.1.8.2 tls if (bh < 2)
246 1.1.1.1.8.2 tls goto done;
247 1.1.1.1.8.2 tls
248 1.1.1.1.8.2 tls if (bh <= ah)
249 1.1.1.1.8.2 tls {
250 1.1.1.1.8.2 tls /* Use q = 1 */
251 1.1.1.1.8.2 tls u00 += u01;
252 1.1.1.1.8.2 tls u10 += u11;
253 1.1.1.1.8.2 tls bits = mpn_jacobi_update (bits, 0, 1);
254 1.1.1.1.8.2 tls }
255 1.1.1.1.8.2 tls else
256 1.1.1.1.8.2 tls {
257 1.1.1.1.8.2 tls mp_limb_t r[2];
258 1.1.1.1.8.2 tls mp_limb_t q = div2 (r, bh, bl, ah, al);
259 1.1.1.1.8.2 tls bl = r[0]; bh = r[1];
260 1.1.1.1.8.2 tls if (bh < 2)
261 1.1.1.1.8.2 tls {
262 1.1.1.1.8.2 tls /* B is too small, but q is correct. */
263 1.1.1.1.8.2 tls u00 += q * u01;
264 1.1.1.1.8.2 tls u10 += q * u11;
265 1.1.1.1.8.2 tls bits = mpn_jacobi_update (bits, 0, q & 3);
266 1.1.1.1.8.2 tls goto done;
267 1.1.1.1.8.2 tls }
268 1.1.1.1.8.2 tls q++;
269 1.1.1.1.8.2 tls u00 += q * u01;
270 1.1.1.1.8.2 tls u10 += q * u11;
271 1.1.1.1.8.2 tls bits = mpn_jacobi_update (bits, 0, q & 3);
272 1.1.1.1.8.2 tls }
273 1.1.1.1.8.2 tls }
274 1.1.1.1.8.2 tls
275 1.1.1.1.8.2 tls /* NOTE: Since we discard the least significant half limb, we don't
276 1.1.1.1.8.2 tls get a truly maximal M (corresponding to |a - b| <
277 1.1.1.1.8.2 tls 2^{GMP_LIMB_BITS +1}). */
278 1.1.1.1.8.2 tls /* Single precision loop */
279 1.1.1.1.8.2 tls for (;;)
280 1.1.1.1.8.2 tls {
281 1.1.1.1.8.2 tls ASSERT (ah >= bh);
282 1.1.1.1.8.2 tls if (ah == bh)
283 1.1.1.1.8.2 tls break;
284 1.1.1.1.8.2 tls
285 1.1.1.1.8.2 tls ah -= bh;
286 1.1.1.1.8.2 tls if (ah < (CNST_LIMB (1) << (GMP_LIMB_BITS / 2 + 1)))
287 1.1.1.1.8.2 tls break;
288 1.1.1.1.8.2 tls
289 1.1.1.1.8.2 tls if (ah <= bh)
290 1.1.1.1.8.2 tls {
291 1.1.1.1.8.2 tls /* Use q = 1 */
292 1.1.1.1.8.2 tls u01 += u00;
293 1.1.1.1.8.2 tls u11 += u10;
294 1.1.1.1.8.2 tls bits = mpn_jacobi_update (bits, 1, 1);
295 1.1.1.1.8.2 tls }
296 1.1.1.1.8.2 tls else
297 1.1.1.1.8.2 tls {
298 1.1.1.1.8.2 tls mp_limb_t r;
299 1.1.1.1.8.2 tls mp_limb_t q = div1 (&r, ah, bh);
300 1.1.1.1.8.2 tls ah = r;
301 1.1.1.1.8.2 tls if (ah < (CNST_LIMB(1) << (GMP_LIMB_BITS / 2 + 1)))
302 1.1.1.1.8.2 tls {
303 1.1.1.1.8.2 tls /* A is too small, but q is correct. */
304 1.1.1.1.8.2 tls u01 += q * u00;
305 1.1.1.1.8.2 tls u11 += q * u10;
306 1.1.1.1.8.2 tls bits = mpn_jacobi_update (bits, 1, q & 3);
307 1.1.1.1.8.2 tls break;
308 1.1.1.1.8.2 tls }
309 1.1.1.1.8.2 tls q++;
310 1.1.1.1.8.2 tls u01 += q * u00;
311 1.1.1.1.8.2 tls u11 += q * u10;
312 1.1.1.1.8.2 tls bits = mpn_jacobi_update (bits, 1, q & 3);
313 1.1.1.1.8.2 tls }
314 1.1.1.1.8.2 tls subtract_a1:
315 1.1.1.1.8.2 tls ASSERT (bh >= ah);
316 1.1.1.1.8.2 tls if (ah == bh)
317 1.1.1.1.8.2 tls break;
318 1.1.1.1.8.2 tls
319 1.1.1.1.8.2 tls bh -= ah;
320 1.1.1.1.8.2 tls if (bh < (CNST_LIMB (1) << (GMP_LIMB_BITS / 2 + 1)))
321 1.1.1.1.8.2 tls break;
322 1.1.1.1.8.2 tls
323 1.1.1.1.8.2 tls if (bh <= ah)
324 1.1.1.1.8.2 tls {
325 1.1.1.1.8.2 tls /* Use q = 1 */
326 1.1.1.1.8.2 tls u00 += u01;
327 1.1.1.1.8.2 tls u10 += u11;
328 1.1.1.1.8.2 tls bits = mpn_jacobi_update (bits, 0, 1);
329 1.1.1.1.8.2 tls }
330 1.1.1.1.8.2 tls else
331 1.1.1.1.8.2 tls {
332 1.1.1.1.8.2 tls mp_limb_t r;
333 1.1.1.1.8.2 tls mp_limb_t q = div1 (&r, bh, ah);
334 1.1.1.1.8.2 tls bh = r;
335 1.1.1.1.8.2 tls if (bh < (CNST_LIMB(1) << (GMP_LIMB_BITS / 2 + 1)))
336 1.1.1.1.8.2 tls {
337 1.1.1.1.8.2 tls /* B is too small, but q is correct. */
338 1.1.1.1.8.2 tls u00 += q * u01;
339 1.1.1.1.8.2 tls u10 += q * u11;
340 1.1.1.1.8.2 tls bits = mpn_jacobi_update (bits, 0, q & 3);
341 1.1.1.1.8.2 tls break;
342 1.1.1.1.8.2 tls }
343 1.1.1.1.8.2 tls q++;
344 1.1.1.1.8.2 tls u00 += q * u01;
345 1.1.1.1.8.2 tls u10 += q * u11;
346 1.1.1.1.8.2 tls bits = mpn_jacobi_update (bits, 0, q & 3);
347 1.1.1.1.8.2 tls }
348 1.1.1.1.8.2 tls }
349 1.1.1.1.8.2 tls
350 1.1.1.1.8.2 tls done:
351 1.1.1.1.8.2 tls M->u[0][0] = u00; M->u[0][1] = u01;
352 1.1.1.1.8.2 tls M->u[1][0] = u10; M->u[1][1] = u11;
353 1.1.1.1.8.2 tls *bitsp = bits;
354 1.1.1.1.8.2 tls
355 1.1.1.1.8.2 tls return 1;
356 1.1.1.1.8.2 tls }
357