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
mpn_jacobi_2(mp_srcptr ap,mp_srcptr bp,unsigned bit)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
mpn_jacobi_2(mp_srcptr ap,mp_srcptr bp,unsigned bit)173 mpn_jacobi_2 (mp_srcptr ap, mp_srcptr bp, unsigned bit)
174 {
175   mp_limb_t ah, al, bh, bl;
176   int c;
177 
178   al = ap[0];
179   ah = ap[1];
180   bl = bp[0];
181   bh = bp[1];
182 
183   ASSERT (bl & 1);
184 
185   /* Use bit 1. */
186   bit <<= 1;
187 
188   if (bh == 0 && bl == 1)
189     /* (a|1) = 1 */
190     return 1 - (bit & 2);
191 
192   if (al == 0)
193     {
194       if (ah == 0)
195           /* (0|b) = 0, b > 1 */
196           return 0;
197 
198       count_trailing_zeros (c, ah);
199       bit ^= ((GMP_NUMB_BITS + c) << 1) & (bl ^ (bl >> 1));
200 
201       al = bl;
202       bl = ah >> c;
203 
204       if (bl == 1)
205           /* (1|b) = 1 */
206           return 1 - (bit & 2);
207 
208       ah = bh;
209 
210       bit ^= al & bl;
211 
212       goto b_reduced;
213     }
214   if ( (al & 1) == 0)
215     {
216       count_trailing_zeros (c, al);
217 
218       al = ((ah << (GMP_NUMB_BITS - c)) & GMP_NUMB_MASK) | (al >> c);
219       ah >>= c;
220       bit ^= (c << 1) & (bl ^ (bl >> 1));
221     }
222   if (ah == 0)
223     {
224       if (bh > 0)
225           {
226             bit ^= al & bl;
227             MP_LIMB_T_SWAP (al, bl);
228             ah = bh;
229             goto b_reduced;
230           }
231       goto ab_reduced;
232     }
233 
234   while (bh > 0)
235     {
236       /* Compute (a|b) */
237       while (ah > bh)
238           {
239             sub_ddmmss (ah, al, ah, al, bh, bl);
240             if (al == 0)
241               {
242                 count_trailing_zeros (c, ah);
243                 bit ^= ((GMP_NUMB_BITS + c) << 1) & (bl ^ (bl >> 1));
244 
245                 al = bl;
246                 bl = ah >> c;
247                 ah = bh;
248 
249                 bit ^= al & bl;
250                 goto b_reduced;
251               }
252             count_trailing_zeros (c, al);
253             bit ^= (c << 1) & (bl ^ (bl >> 1));
254             al = ((ah << (GMP_NUMB_BITS - c)) & GMP_NUMB_MASK) | (al >> c);
255             ah >>= c;
256           }
257       if (ah == bh)
258           goto cancel_hi;
259 
260       if (ah == 0)
261           {
262             bit ^= al & bl;
263             MP_LIMB_T_SWAP (al, bl);
264             ah = bh;
265             break;
266           }
267 
268       bit ^= al & bl;
269 
270       /* Compute (b|a) */
271       while (bh > ah)
272           {
273             sub_ddmmss (bh, bl, bh, bl, ah, al);
274             if (bl == 0)
275               {
276                 count_trailing_zeros (c, bh);
277                 bit ^= ((GMP_NUMB_BITS + c) << 1) & (al ^ (al >> 1));
278 
279                 bl = bh >> c;
280                 bit ^= al & bl;
281                 goto b_reduced;
282               }
283             count_trailing_zeros (c, bl);
284             bit ^= (c << 1) & (al ^ (al >> 1));
285             bl = ((bh << (GMP_NUMB_BITS - c)) & GMP_NUMB_MASK) | (bl >> c);
286             bh >>= c;
287           }
288       bit ^= al & bl;
289 
290       /* Compute (a|b) */
291       if (ah == bh)
292           {
293           cancel_hi:
294             if (al < bl)
295               {
296                 MP_LIMB_T_SWAP (al, bl);
297                 bit ^= al & bl;
298               }
299             al -= bl;
300             if (al == 0)
301               return 0;
302 
303             count_trailing_zeros (c, al);
304             bit ^= (c << 1) & (bl ^ (bl >> 1));
305             al >>= c;
306 
307             if (al == 1)
308               return 1 - (bit & 2);
309 
310             MP_LIMB_T_SWAP (al, bl);
311             bit ^= al & bl;
312             break;
313           }
314     }
315 
316  b_reduced:
317   /* Compute (a|b), with b a single limb. */
318   ASSERT (bl & 1);
319 
320   if (bl == 1)
321     /* (a|1) = 1 */
322     return 1 - (bit & 2);
323 
324   while (ah > 0)
325     {
326       ah -= (al < bl);
327       al -= bl;
328       if (al == 0)
329           {
330             if (ah == 0)
331               return 0;
332             count_trailing_zeros (c, ah);
333             bit ^= ((GMP_NUMB_BITS + c) << 1) & (bl ^ (bl >> 1));
334             al = ah >> c;
335             goto ab_reduced;
336           }
337       count_trailing_zeros (c, al);
338 
339       al = ((ah << (GMP_NUMB_BITS - c)) & GMP_NUMB_MASK) | (al >> c);
340       ah >>= c;
341       bit ^= (c << 1) & (bl ^ (bl >> 1));
342     }
343  ab_reduced:
344   ASSERT (bl & 1);
345   ASSERT (bl > 1);
346 
347   return mpn_jacobi_base (al, bl, bit);
348 }
349 #else
350 #error Unsupported value for JACOBI_2_METHOD
351 #endif
352