From 757970dbaec023fd9cdcbab40fb64f66cae21bb5 Mon Sep 17 00:00:00 2001 From: Krishna Vedala Date: Wed, 27 May 2020 15:06:46 -0400 Subject: [PATCH] documentation for extended euclid --- math/extended_euclid_algorithm.cpp | 74 ++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 5 deletions(-) diff --git a/math/extended_euclid_algorithm.cpp b/math/extended_euclid_algorithm.cpp index 829db4336..84dec55c5 100644 --- a/math/extended_euclid_algorithm.cpp +++ b/math/extended_euclid_algorithm.cpp @@ -1,9 +1,70 @@ +/** + * @file + * @brief GCD using [extended Euclid's algorithm] + * (https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm) + * + * Finding coefficients of a and b ie x and y in Bézout's identity + * \f[\text{gcd}(a, b) = a \times x + b \times y \f] + * This is also used in finding Modular + * multiplicative inverse of a number. (A * B)%M == 1 Here B is the MMI of A for + * given M, so extendedEuclid (A, M) gives B. + */ +#include // for swap function #include -// Finding coefficients of a and b ie x and y in gcd(a, b) = a * x + b * y -// d is gcd(a, b) -// This is also used in finding Modular multiplicative inverse of a number. -// (A * B)%M == 1 Here B is the MMI of A for given M, -// so extendedEuclid (A, M) gives B. + +/** + * function to update the coefficients per iteration + * \f[r_0,\,r = r,\, r_0 - \text{quotient}\times r\f] + * + * @param[in,out] r signed + * @param[in,out] r0 signed + * @param[in] quotient unsigned input + */ +template +inline void update_step(T &r, T &r0, const T2 quotient) { + T temp = r; + r = r0 - (quotient * temp); + r0 = temp; +} + +/** + * Implementation using iterative algorithm from + * [Wikipedia](https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Pseudocode) + * + * @param[in] A unsigned + * @param[in] B unsigned + * @param[out] GCD unsigned + * @param[out] x signed + * @param[out] y signed + */ +template +void extendedEuclid_1(T1 A, T1 B, T1 *GCD, T2 *x, T2 *y) { + if (B > A) std::swap(A, B); // Ensure that A >= B + + T2 s = 0, s0 = 1; + T2 t = 1, t0 = 0; + T1 r = B, r0 = A; + + while (r != 0) { + T1 quotient = r0 / r; + update_step(r, r0, quotient); + update_step(s, s0, quotient); + update_step(t, t0, quotient); + } + *GCD = r0; + *x = s0; + *y = t0; +} + +/** + * Implementation using recursive algorithm + * + * @param[in] A unsigned + * @param[in] B unsigned + * @param[out] GCD unsigned + * @param[in,out] x signed + * @param[in,out] y signed + */ template void extendedEuclid(T A, T B, T *GCD, T2 *x, T2 *y) { if (B > A) std::swap(A, B); // Ensure that A >= B @@ -20,11 +81,14 @@ void extendedEuclid(T A, T B, T *GCD, T2 *x, T2 *y) { } } +/// Main function int main() { uint32_t a, b, gcd; int32_t x, y; std::cin >> a >> b; extendedEuclid(a, b, &gcd, &x, &y); std::cout << gcd << " " << x << " " << y << std::endl; + extendedEuclid_1(a, b, &gcd, &x, &y); + std::cout << gcd << " " << x << " " << y << std::endl; return 0; }