* Euclid's algorithm for GCD. * * Solves for gamma*a1 + epsilon*a2 == gcd(a1, a2) * providing |gamma| < |a2|/gcd, |epsilon| < |a1|/gcd. */
| 206 | * providing |gamma| < |a2|/gcd, |epsilon| < |a1|/gcd. |
| 207 | */ |
| 208 | static void |
| 209 | euclid(npy_int64 a1, npy_int64 a2, npy_int64 *a_gcd, npy_int64 *gamma, npy_int64 *epsilon) |
| 210 | { |
| 211 | npy_int64 gamma1, gamma2, epsilon1, epsilon2, r; |
| 212 | |
| 213 | assert(a1 > 0); |
| 214 | assert(a2 > 0); |
| 215 | |
| 216 | gamma1 = 1; |
| 217 | gamma2 = 0; |
| 218 | epsilon1 = 0; |
| 219 | epsilon2 = 1; |
| 220 | |
| 221 | /* The numbers remain bounded by |a1|, |a2| during |
| 222 | the iteration, so no integer overflows */ |
| 223 | while (1) { |
| 224 | if (a2 > 0) { |
| 225 | r = a1/a2; |
| 226 | a1 -= r*a2; |
| 227 | gamma1 -= r*gamma2; |
| 228 | epsilon1 -= r*epsilon2; |
| 229 | } |
| 230 | else { |
| 231 | *a_gcd = a1; |
| 232 | *gamma = gamma1; |
| 233 | *epsilon = epsilon1; |
| 234 | break; |
| 235 | } |
| 236 | |
| 237 | if (a1 > 0) { |
| 238 | r = a2/a1; |
| 239 | a2 -= r*a1; |
| 240 | gamma2 -= r*gamma1; |
| 241 | epsilon2 -= r*epsilon1; |
| 242 | } |
| 243 | else { |
| 244 | *a_gcd = a2; |
| 245 | *gamma = gamma2; |
| 246 | *epsilon = epsilon2; |
| 247 | break; |
| 248 | } |
| 249 | } |
| 250 | } |
| 251 | |
| 252 | |
| 253 | /** |
no outgoing calls
no test coverage detected