Skip to content

Commit 5dba62d

Browse files
author
jbbjarnason
committed
py/modmath: Tighten math.gcd recursion.
Refactor math.gcd algorithm to recursive Euclid algorithm, see more info here: https://www.rosettacode.org/wiki/Greatest_common_divisor#C.
1 parent a8d421e commit 5dba62d

File tree

2 files changed

+6
-16
lines changed

2 files changed

+6
-16
lines changed

py/modmath.c

+4-16
Original file line numberDiff line numberDiff line change
@@ -202,29 +202,17 @@ MATH_FUN_1(lgamma, lgamma)
202202

203203
// gcd(x, y): return the greatest common divisor
204204
STATIC mp_int_t gcd_func(mp_int_t x, mp_int_t y) {
205-
if (x == 0) {
206-
return y;
207-
}
208-
if (y == 0) {
209-
return x;
210-
}
211-
if (x == y) {
212-
return x;
213-
}
214-
if (x > y) {
215-
return gcd_func(x - y, y);
216-
}
217-
return gcd_func(x, y - x);
205+
return (y != 0) ? gcd_func(y, x % y) : x;
218206
}
219207
STATIC mp_obj_t mp_math_gcd(size_t n_args, const mp_obj_t *args) {
220208
mp_int_t e = mp_obj_get_int(args[--n_args]);
221209
mp_int_t d = mp_obj_get_int(args[--n_args]);
222210
// calc absolute value manually, makes it unnecessary to include stdlib
223211
if (d < 0) {
224-
d *= -1;
212+
d = -d;
225213
}
226214
if (e < 0) {
227-
e *= -1;
215+
e = -e;
228216
}
229217

230218
mp_int_t ans = gcd_func(d, e);
@@ -236,7 +224,7 @@ STATIC mp_obj_t mp_math_gcd(size_t n_args, const mp_obj_t *args) {
236224
do {
237225
mp_int_t next_variable = mp_obj_get_int(args[--n_args]);
238226
if (next_variable < 0) {
239-
next_variable *= -1;
227+
next_variable = -next_variable;
240228
}
241229
ans = gcd_func(next_variable, ans);
242230
} while (n_args > 0);

tests/float/math_fun_special.py

+2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@
6565
(-9, -2),
6666
(0, 0),
6767
(6, 30, 40, -60, 20, 40),
68+
(2147483643, 42),
69+
(-9223372036854775807, -922337203685477580, -92233720368547758)
6870
),
6971
),
7072
]

0 commit comments

Comments
 (0)