1 /* mpn_gcdext -- Extended Greatest Common Divisor.
3 Copyright 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009 Free Software
6 This file is part of the GNU MP Library.
8 The GNU MP Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
13 The GNU MP Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
25 #ifndef GCDEXT_1_USE_BINARY
26 #define GCDEXT_1_USE_BINARY 0
29 #ifndef GCDEXT_1_BINARY_METHOD
30 #define GCDEXT_1_BINARY_METHOD 2
37 #if GCDEXT_1_USE_BINARY
40 static unsigned char zerotab[0x40] = {
41 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
42 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
43 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
44 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
49 mpn_gcdext_1 (mp_limb_signed_t *sp, mp_limb_signed_t *tp,
50 mp_limb_t u, mp_limb_t v)
57 where U, V are the inputs (without any shared power of two),
58 and the matris has determinant ± 2^{shift}.
71 #if GCDEXT_1_BINARY_METHOD == 2
78 count_trailing_zeros (zero_bits, u | v);
84 count_trailing_zeros (shift, u);
88 else if ((v & 1) == 0)
90 count_trailing_zeros (shift, v);
97 #if GCDEXT_1_BINARY_METHOD == 1
105 count = zerotab [u & 0x3f];
107 if (UNLIKELY (count == 6))
112 c = zerotab[u & 0x3f];
119 count_trailing_zeros (count, u);
122 t0 += t1; t1 <<= count;
123 s0 += s1; s1 <<= count;
129 count = zerotab [v & 0x3f];
131 if (UNLIKELY (count == 6))
136 c = zerotab[v & 0x3f];
143 count_trailing_zeros (count, v);
146 t1 += t0; t0 <<= count;
147 s1 += s0; s0 <<= count;
152 # if GCDEXT_1_BINARY_METHOD == 2
162 mp_limb_t vgtu = LIMB_HIGHBIT_TO_MASK (d);
166 /* When v <= u (vgtu == 0), the updates are:
168 (u; v) <-- ( (u - v) >> count; v) (det = +(1<<count) for corr. M factor)
169 (t1, t0) <-- (t1 << count, t0 + t1)
171 and when v > 0, the updates are
173 (u; v) <-- ( (v - u) >> count; u) (det = -(1<<count))
174 (t1, t0) <-- (t0 << count, t0 + t1)
176 and similarly for s1, s0
179 /* v <-- min (u, v) */
183 u = (d ^ vgtu) - vgtu;
185 /* Number of trailing zeros is the same no matter if we look at
186 * d or u, but using d gives more parallelism. */
188 count = zerotab[d & 0x3f];
189 if (UNLIKELY (count == 6))
195 c = zerotab[d & 0x3f];
201 count_trailing_zeros (count, d);
205 tx = vgtu & (t0 - t1);
206 sx = vgtu & (s0 - s1);
219 # else /* GCDEXT_1_BINARY_METHOD == 2 */
220 # error Unknown GCDEXT_1_BINARY_METHOD
224 /* Now u = v = g = gcd (u,v). Compute U/g and V/g */
228 ugh = ug/2 + (ug & 1);
229 vgh = vg/2 + (vg & 1);
231 /* Now ±2^{shift} g = s0 U - t0 V. Get rid of the power of two, using
232 s0 U - t0 V = (s0 + V/g) U - (t0 + U/g) V. */
233 for (i = 0; i < shift; i++)
235 mp_limb_t mask = - ( (s0 | t0) & 1);
242 /* FIXME: Try simplifying this condition. */
243 if ( (s0 > 1 && 2*s0 >= vg) || (t0 > 1 && 2*t0 >= ug) )
248 #if GCDEXT_1_BINARY_METHOD == 2
249 /* Conditional negation. */
250 s0 = (s0 ^ det_sign) - det_sign;
251 t0 = (t0 ^ det_sign) - det_sign;
256 return u << zero_bits;
259 #else /* !GCDEXT_1_USE_BINARY */
262 /* FIXME: Takes two single-word limbs. It could be extended to a
263 * function that accepts a bignum for the first input, and only
264 * returns the first co-factor. */
267 mpn_gcdext_1 (mp_limb_signed_t *up, mp_limb_signed_t *vp,
268 mp_limb_t a, mp_limb_t b)
275 where A, B are the original inputs.
277 mp_limb_signed_t u0 = 1;
278 mp_limb_signed_t v0 = 0;
279 mp_limb_signed_t u1 = 0;
280 mp_limb_signed_t v1 = 1;
318 #endif /* !GCDEXT_1_USE_BINARY */