Skip to content

Commit 86495b7

Browse files
Joseph Wangjbbjarnason
authored andcommitted
py/modmath: Working math gcd algorithm.
Inputs are constrained to only integers.
1 parent a0936db commit 86495b7

File tree

2 files changed

+42
-19
lines changed

2 files changed

+42
-19
lines changed

py/modmath.c

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -200,35 +200,56 @@ MATH_FUN_1(gamma, tgamma)
200200
// lgamma(x): return the natural logarithm of the gamma function of x
201201
MATH_FUN_1(lgamma, lgamma)
202202

203-
// gcd(x, y): return the greatest common divisor
204-
STATIC mp_int_t gcd_func(mp_int_t x, mp_int_t y) {
205-
return (y != 0) ? gcd_func(y, x % y) : x;
206-
}
207-
STATIC mp_obj_t mp_math_gcd(size_t n_args, const mp_obj_t *args) {
208-
mp_int_t e = mp_obj_get_int(args[--n_args]);
209-
mp_int_t d = mp_obj_get_int(args[--n_args]);
210-
// calc absolute value manually, makes it unnecessary to include stdlib
211-
if (d < 0) {
212-
d = -d;
203+
/* gcd(x, y): return the greatest common divisor
204+
GCD Pseudocode
205+
* gcd(x,y)
206+
* if x < y;
207+
* x, y = y, x
208+
*
209+
* while y != 0:
210+
* x,y = y, x mod y
211+
* return x
212+
*/
213+
STATIC mp_obj_t gcd_func(mp_obj_t x, mp_obj_t y) {
214+
mp_obj_t temp;
215+
if (mp_binary_op(MP_BINARY_OP_LESS, x, y) == mp_const_true) {
216+
temp = x;
217+
x = y;
218+
y = temp;
213219
}
214-
if (e < 0) {
215-
e = -e;
220+
221+
mp_obj_t zero = mp_obj_new_int(0);
222+
while (mp_binary_op(MP_BINARY_OP_NOT_EQUAL, y, zero) == mp_const_true) {
223+
temp = y;
224+
y = mp_binary_op(MP_BINARY_OP_MODULO, x, y);
225+
x = temp;
226+
}
227+
return x;
228+
}
229+
230+
STATIC mp_obj_t gcd_preprocess_arg(mp_obj_t presumed_integer) {
231+
if (!mp_obj_is_int(presumed_integer)) {
232+
mp_raise_msg_varg(&mp_type_TypeError,
233+
MP_ERROR_TEXT("can't convert %s to int"), mp_obj_get_type_str(presumed_integer));
216234
}
235+
return mp_unary_op(MP_UNARY_OP_ABS, presumed_integer);
236+
}
217237

218-
mp_int_t ans = gcd_func(d, e);
238+
STATIC mp_obj_t mp_math_gcd(size_t n_args, const mp_obj_t *args) {
239+
mp_obj_t e = gcd_preprocess_arg(args[--n_args]);
240+
mp_obj_t d = gcd_preprocess_arg(args[--n_args]);
241+
242+
mp_obj_t ans = gcd_func(d, e);
219243
if (n_args == 0) {
220-
return mp_obj_new_int(ans);
244+
return ans;
221245
}
222246

223247
// gcd(a, gcd(b, gcd(c, gcd(d, e)))))
224248
do {
225-
mp_int_t next_variable = mp_obj_get_int(args[--n_args]);
226-
if (next_variable < 0) {
227-
next_variable = -next_variable;
228-
}
249+
mp_obj_t next_variable = gcd_preprocess_arg(args[--n_args]);
229250
ans = gcd_func(next_variable, ans);
230251
} while (n_args > 0);
231-
return mp_obj_new_int(ans);
252+
return ans;
232253
}
233254
MP_DEFINE_CONST_FUN_OBJ_VAR(mp_math_gcd_obj, 2, mp_math_gcd);
234255

tests/float/math_fun_special.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,5 @@
7878
print("{:.4g}".format(function(*values)))
7979
except ValueError as e:
8080
print(str(e))
81+
82+
print(gcd(12345678912345678912345678911561561658135153135135135, 123456))

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy