@@ -200,35 +200,56 @@ MATH_FUN_1(gamma, tgamma)
200
200
// lgamma(x): return the natural logarithm of the gamma function of x
201
201
MATH_FUN_1 (lgamma , lgamma )
202
202
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 ;
213
219
}
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 ));
216
234
}
235
+ return mp_unary_op (MP_UNARY_OP_ABS , presumed_integer );
236
+ }
217
237
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 );
219
243
if (n_args == 0 ) {
220
- return mp_obj_new_int ( ans ) ;
244
+ return ans ;
221
245
}
222
246
223
247
// gcd(a, gcd(b, gcd(c, gcd(d, e)))))
224
248
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 ]);
229
250
ans = gcd_func (next_variable , ans );
230
251
} while (n_args > 0 );
231
- return mp_obj_new_int ( ans ) ;
252
+ return ans ;
232
253
}
233
254
MP_DEFINE_CONST_FUN_OBJ_VAR (mp_math_gcd_obj , 2 , mp_math_gcd );
234
255
0 commit comments