Skip to content

Commit b83305a

Browse files
Update gcd_recursive_euclidean.cpp
1 parent b3a5af2 commit b83305a

File tree

1 file changed

+97
-32
lines changed

1 file changed

+97
-32
lines changed

math/gcd_recursive_euclidean.cpp

Lines changed: 97 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,117 @@
11
/**
22
* @file
3-
* @brief Compute the greatest common denominator of two integers using
4-
* *recursive form* of
5-
* [Euclidean algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm)
3+
* @brief Implementation of the [Euclidean
4+
* algorithm](https://en.wikipedia.org/wiki/Euclidean_algorithm) to find the
5+
* Greatest Common Divisor (GCD) using a recursive approach.
66
*
7-
* @see gcd_iterative_euclidean.cpp, gcd_of_n_numbers.cpp
7+
* @details
8+
* The Euclidean algorithm computes the GCD of two integers efficiently:
9+
* - Uses modulus instead of repeated subtraction (faster)
10+
* - Handles negative numbers and zero correctly
11+
*
12+
* ### Algorithm
13+
* For integers a and b:
14+
* 1. If b is 0, return |a|
15+
* 2. Otherwise, recursively compute GCD(b, a % b)
16+
*
17+
* ### Complexity
18+
* - Time Complexity: O(log(min(|a|, |b|)))
19+
* - Space Complexity: O(log(min(|a|, |b|))) due to recursion stack
20+
*
21+
* @author [Contributor](Optimize Recursive GCD: Use Modulus-Based Euclidean
22+
* Algorithm with Robust Edge Case Handling(https://github.com/kokatesaurabh))
823
*/
24+
25+
#include <cassert>
26+
#include <cmath>
927
#include <iostream>
28+
#include <stdexcept>
29+
30+
namespace math {
31+
namespace gcd_recursive {
1032

1133
/**
12-
* algorithm
34+
* @brief Compute GCD of two integers using recursive Euclidean algorithm
35+
* @param a First integer
36+
* @param b Second integer
37+
* @returns GCD of a and b
38+
* @throws std::invalid_argument if both a and b are zero
1339
*/
14-
int gcd(int num1, int num2) {
15-
if (num1 <= 0 | num2 <= 0) {
16-
throw std::domain_error("Euclidean algorithm domain is for ints > 0");
17-
}
40+
int64_t gcd(int64_t a, int64_t b) {
41+
a = std::abs(a);
42+
b = std::abs(b);
43+
44+
if (a == 0 && b == 0)
45+
throw std::invalid_argument("GCD(0,0) is undefined");
46+
47+
if (b == 0)
48+
return a;
49+
50+
return gcd(b, a % b);
51+
}
52+
53+
} // namespace gcd_recursive
54+
} // namespace math
55+
56+
/**
57+
* @brief Run comprehensive test cases
58+
*/
59+
static void test() {
60+
using math::gcd_recursive::gcd;
61+
62+
// Basic positive numbers
63+
assert(gcd(48, 18) == 6);
64+
assert(gcd(56, 42) == 14);
65+
assert(gcd(17, 13) == 1);
1866

19-
if (num1 == num2) {
20-
return num1;
67+
// Zero cases
68+
assert(gcd(0, 5) == 5);
69+
assert(gcd(7, 0) == 7);
70+
71+
// Both zero (should throw)
72+
try {
73+
gcd(0, 0);
74+
assert(false); // Should not reach here
75+
} catch (const std::invalid_argument&) {
2176
}
2277

23-
// Everything divides 0
24-
if (num1 == 0)
25-
return num2;
26-
if (num2 == 0)
27-
return num1;
78+
// Negative numbers
79+
assert(gcd(-48, 18) == 6);
80+
assert(gcd(48, -18) == 6);
81+
assert(gcd(-48, -18) == 6);
82+
83+
// Equal numbers
84+
assert(gcd(15, 15) == 15);
85+
assert(gcd(100, 100) == 100);
2886

29-
// base case
30-
if (num1 == num2)
31-
return num1;
87+
// Multiples
88+
assert(gcd(25, 100) == 25);
89+
assert(gcd(17, 51) == 17);
3290

33-
// a is greater
34-
if (num1 > num2)
35-
return gcd(num1 - num2, num2);
36-
return gcd(num1, num2 - num1);
91+
// Large numbers
92+
assert(gcd(123456789, 987654321) == 9);
93+
assert(gcd(1000000007, 1000000009) == 1);
94+
95+
std::cout << "All GCD tests passed successfully!\n";
3796
}
3897

3998
/**
40-
* Main function
99+
* @brief Demonstrate example usage
41100
*/
101+
static void demonstrate_usage() {
102+
using math::gcd_recursive::gcd;
103+
104+
std::cout << "GCD Examples:\n";
105+
std::cout << "GCD(48, 18) = " << gcd(48, 18) << "\n";
106+
std::cout << "GCD(17, 13) = " << gcd(17, 13) << " (co-prime)\n";
107+
std::cout << "GCD(0, 15) = " << gcd(0, 15) << "\n";
108+
std::cout << "GCD(-48, 18) = " << gcd(-48, 18) << "\n";
109+
std::cout << "GCD(123456789, 987654321) = " << gcd(123456789, 987654321)
110+
<< "\n";
111+
}
112+
42113
int main() {
43-
std::cout << "gcd of 120,7 is " << (gcd(120, 7)) << std::endl;
44-
try {
45-
std::cout << "gcd of -120,10 is " << gcd(-120, 10) << std::endl;
46-
} catch (const std::domain_error &e) {
47-
std::cout << "Error handling was successful" << std::endl;
48-
}
49-
std::cout << "gcd of 312,221 is " << (gcd(312, 221)) << std::endl;
50-
std::cout << "gcd of 289,204 is " << (gcd(289, 204)) << std::endl;
114+
test();
115+
demonstrate_usage();
51116
return 0;
52117
}

0 commit comments

Comments
 (0)