github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/mpn/generic/gcdext_1.c (about) 1 /* mpn_gcdext -- Extended Greatest Common Divisor. 2 3 Copyright 1996, 1998, 2000-2005, 2008, 2009 Free Software Foundation, Inc. 4 5 This file is part of the GNU MP Library. 6 7 The GNU MP Library is free software; you can redistribute it and/or modify 8 it under the terms of either: 9 10 * the GNU Lesser General Public License as published by the Free 11 Software Foundation; either version 3 of the License, or (at your 12 option) any later version. 13 14 or 15 16 * the GNU General Public License as published by the Free Software 17 Foundation; either version 2 of the License, or (at your option) any 18 later version. 19 20 or both in parallel, as here. 21 22 The GNU MP Library is distributed in the hope that it will be useful, but 23 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 24 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 25 for more details. 26 27 You should have received copies of the GNU General Public License and the 28 GNU Lesser General Public License along with the GNU MP Library. If not, 29 see https://www.gnu.org/licenses/. */ 30 31 #include "gmp.h" 32 #include "gmp-impl.h" 33 #include "longlong.h" 34 35 #ifndef GCDEXT_1_USE_BINARY 36 #define GCDEXT_1_USE_BINARY 0 37 #endif 38 39 #ifndef GCDEXT_1_BINARY_METHOD 40 #define GCDEXT_1_BINARY_METHOD 2 41 #endif 42 43 #ifndef USE_ZEROTAB 44 #define USE_ZEROTAB 1 45 #endif 46 47 #if GCDEXT_1_USE_BINARY 48 49 #if USE_ZEROTAB 50 static unsigned char zerotab[0x40] = { 51 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 52 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 53 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 54 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 55 }; 56 #endif 57 58 mp_limb_t 59 mpn_gcdext_1 (mp_limb_signed_t *sp, mp_limb_signed_t *tp, 60 mp_limb_t u, mp_limb_t v) 61 { 62 /* Maintain 63 64 U = t1 u + t0 v 65 V = s1 u + s0 v 66 67 where U, V are the inputs (without any shared power of two), 68 and the matrix has determinant ± 2^{shift}. 69 */ 70 mp_limb_t s0 = 1; 71 mp_limb_t t0 = 0; 72 mp_limb_t s1 = 0; 73 mp_limb_t t1 = 1; 74 mp_limb_t ug; 75 mp_limb_t vg; 76 mp_limb_t ugh; 77 mp_limb_t vgh; 78 unsigned zero_bits; 79 unsigned shift; 80 unsigned i; 81 #if GCDEXT_1_BINARY_METHOD == 2 82 mp_limb_t det_sign; 83 #endif 84 85 ASSERT (u > 0); 86 ASSERT (v > 0); 87 88 count_trailing_zeros (zero_bits, u | v); 89 u >>= zero_bits; 90 v >>= zero_bits; 91 92 if ((u & 1) == 0) 93 { 94 count_trailing_zeros (shift, u); 95 u >>= shift; 96 t1 <<= shift; 97 } 98 else if ((v & 1) == 0) 99 { 100 count_trailing_zeros (shift, v); 101 v >>= shift; 102 s0 <<= shift; 103 } 104 else 105 shift = 0; 106 107 #if GCDEXT_1_BINARY_METHOD == 1 108 while (u != v) 109 { 110 unsigned count; 111 if (u > v) 112 { 113 u -= v; 114 #if USE_ZEROTAB 115 count = zerotab [u & 0x3f]; 116 u >>= count; 117 if (UNLIKELY (count == 6)) 118 { 119 unsigned c; 120 do 121 { 122 c = zerotab[u & 0x3f]; 123 u >>= c; 124 count += c; 125 } 126 while (c == 6); 127 } 128 #else 129 count_trailing_zeros (count, u); 130 u >>= count; 131 #endif 132 t0 += t1; t1 <<= count; 133 s0 += s1; s1 <<= count; 134 } 135 else 136 { 137 v -= u; 138 #if USE_ZEROTAB 139 count = zerotab [v & 0x3f]; 140 v >>= count; 141 if (UNLIKELY (count == 6)) 142 { 143 unsigned c; 144 do 145 { 146 c = zerotab[v & 0x3f]; 147 v >>= c; 148 count += c; 149 } 150 while (c == 6); 151 } 152 #else 153 count_trailing_zeros (count, v); 154 v >>= count; 155 #endif 156 t1 += t0; t0 <<= count; 157 s1 += s0; s0 <<= count; 158 } 159 shift += count; 160 } 161 #else 162 # if GCDEXT_1_BINARY_METHOD == 2 163 u >>= 1; 164 v >>= 1; 165 166 det_sign = 0; 167 168 while (u != v) 169 { 170 unsigned count; 171 mp_limb_t d = u - v; 172 mp_limb_t vgtu = LIMB_HIGHBIT_TO_MASK (d); 173 mp_limb_t sx; 174 mp_limb_t tx; 175 176 /* When v <= u (vgtu == 0), the updates are: 177 178 (u; v) <-- ( (u - v) >> count; v) (det = +(1<<count) for corr. M factor) 179 (t1, t0) <-- (t1 << count, t0 + t1) 180 181 and when v > 0, the updates are 182 183 (u; v) <-- ( (v - u) >> count; u) (det = -(1<<count)) 184 (t1, t0) <-- (t0 << count, t0 + t1) 185 186 and similarly for s1, s0 187 */ 188 189 /* v <-- min (u, v) */ 190 v += (vgtu & d); 191 192 /* u <-- |u - v| */ 193 u = (d ^ vgtu) - vgtu; 194 195 /* Number of trailing zeros is the same no matter if we look at 196 * d or u, but using d gives more parallelism. */ 197 #if USE_ZEROTAB 198 count = zerotab[d & 0x3f]; 199 if (UNLIKELY (count == 6)) 200 { 201 unsigned c = 6; 202 do 203 { 204 d >>= c; 205 c = zerotab[d & 0x3f]; 206 count += c; 207 } 208 while (c == 6); 209 } 210 #else 211 count_trailing_zeros (count, d); 212 #endif 213 det_sign ^= vgtu; 214 215 tx = vgtu & (t0 - t1); 216 sx = vgtu & (s0 - s1); 217 t0 += t1; 218 s0 += s1; 219 t1 += tx; 220 s1 += sx; 221 222 count++; 223 u >>= count; 224 t1 <<= count; 225 s1 <<= count; 226 shift += count; 227 } 228 u = (u << 1) + 1; 229 # else /* GCDEXT_1_BINARY_METHOD == 2 */ 230 # error Unknown GCDEXT_1_BINARY_METHOD 231 # endif 232 #endif 233 234 /* Now u = v = g = gcd (u,v). Compute U/g and V/g */ 235 ug = t0 + t1; 236 vg = s0 + s1; 237 238 ugh = ug/2 + (ug & 1); 239 vgh = vg/2 + (vg & 1); 240 241 /* Now ±2^{shift} g = s0 U - t0 V. Get rid of the power of two, using 242 s0 U - t0 V = (s0 + V/g) U - (t0 + U/g) V. */ 243 for (i = 0; i < shift; i++) 244 { 245 mp_limb_t mask = - ( (s0 | t0) & 1); 246 247 s0 /= 2; 248 t0 /= 2; 249 s0 += mask & vgh; 250 t0 += mask & ugh; 251 } 252 /* FIXME: Try simplifying this condition. */ 253 if ( (s0 > 1 && 2*s0 >= vg) || (t0 > 1 && 2*t0 >= ug) ) 254 { 255 s0 -= vg; 256 t0 -= ug; 257 } 258 #if GCDEXT_1_BINARY_METHOD == 2 259 /* Conditional negation. */ 260 s0 = (s0 ^ det_sign) - det_sign; 261 t0 = (t0 ^ det_sign) - det_sign; 262 #endif 263 *sp = s0; 264 *tp = -t0; 265 266 return u << zero_bits; 267 } 268 269 #else /* !GCDEXT_1_USE_BINARY */ 270 271 272 /* FIXME: Takes two single-word limbs. It could be extended to a 273 * function that accepts a bignum for the first input, and only 274 * returns the first co-factor. */ 275 276 mp_limb_t 277 mpn_gcdext_1 (mp_limb_signed_t *up, mp_limb_signed_t *vp, 278 mp_limb_t a, mp_limb_t b) 279 { 280 /* Maintain 281 282 a = u0 A + v0 B 283 b = u1 A + v1 B 284 285 where A, B are the original inputs. 286 */ 287 mp_limb_signed_t u0 = 1; 288 mp_limb_signed_t v0 = 0; 289 mp_limb_signed_t u1 = 0; 290 mp_limb_signed_t v1 = 1; 291 292 ASSERT (a > 0); 293 ASSERT (b > 0); 294 295 if (a < b) 296 goto divide_by_b; 297 298 for (;;) 299 { 300 mp_limb_t q; 301 302 q = a / b; 303 a -= q * b; 304 305 if (a == 0) 306 { 307 *up = u1; 308 *vp = v1; 309 return b; 310 } 311 u0 -= q * u1; 312 v0 -= q * v1; 313 314 divide_by_b: 315 q = b / a; 316 b -= q * a; 317 318 if (b == 0) 319 { 320 *up = u0; 321 *vp = v0; 322 return a; 323 } 324 u1 -= q * u0; 325 v1 -= q * v0; 326 } 327 } 328 #endif /* !GCDEXT_1_USE_BINARY */