33 *
44 * The MIT License (MIT)
55 *
6- * Copyright (c) 2013, 2014 Damien P. George
6+ * Copyright (c) 2013-2017 Damien P. George
77 *
88 * Permission is hereby granted, free of charge, to any person obtaining a copy
99 * of this software and associated documentation files (the "Software"), to deal
@@ -39,14 +39,31 @@ STATIC NORETURN void math_error(void) {
3939 mp_raise_ValueError ("math domain error" );
4040}
4141
42+ STATIC mp_obj_t math_generic_1 (mp_obj_t x_obj , mp_float_t (* f )(mp_float_t )) {
43+ mp_float_t x = mp_obj_get_float (x_obj );
44+ mp_float_t ans = f (x );
45+ if ((isnan (ans ) && !isnan (x )) || (isinf (ans ) && !isinf (x ))) {
46+ math_error ();
47+ }
48+ return mp_obj_new_float (ans );
49+ }
50+
51+ STATIC mp_obj_t math_generic_2 (mp_obj_t x_obj , mp_obj_t y_obj , mp_float_t (* f )(mp_float_t , mp_float_t )) {
52+ mp_float_t x = mp_obj_get_float (x_obj );
53+ mp_float_t y = mp_obj_get_float (y_obj );
54+ mp_float_t ans = f (x , y );
55+ if ((isnan (ans ) && !isnan (x ) && !isnan (y )) || (isinf (ans ) && !isinf (x ))) {
56+ math_error ();
57+ }
58+ return mp_obj_new_float (ans );
59+ }
60+
4261#define MATH_FUN_1 (py_name , c_name ) \
43- STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \
62+ STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { \
63+ return math_generic_1(x_obj, MICROPY_FLOAT_C_FUN(c_name)); \
64+ } \
4465 STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
4566
46- #define MATH_FUN_2 (py_name , c_name ) \
47- STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj), mp_obj_get_float(y_obj))); } \
48- STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_## py_name ## _obj, mp_math_ ## py_name);
49-
5067#define MATH_FUN_1_TO_BOOL (py_name , c_name ) \
5168 STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_bool(c_name(mp_obj_get_float(x_obj))); } \
5269 STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
@@ -55,23 +72,25 @@ STATIC NORETURN void math_error(void) {
5572 STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_int_from_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \
5673 STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
5774
58- #define MATH_FUN_1_ERRCOND (py_name , c_name , error_condition ) \
59- STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { \
60- mp_float_t x = mp_obj_get_float(x_obj); \
61- if (error_condition) { \
62- math_error(); \
63- } \
64- return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(x)); \
75+ #define MATH_FUN_2 (py_name , c_name ) \
76+ STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { \
77+ return math_generic_2(x_obj, y_obj, MICROPY_FLOAT_C_FUN(c_name)); \
6578 } \
66- STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
79+ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_## py_name ## _obj, mp_math_ ## py_name);
80+
81+ #define MATH_FUN_2_FLT_INT (py_name , c_name ) \
82+ STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { \
83+ return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj), mp_obj_get_int(y_obj))); \
84+ } \
85+ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_## py_name ## _obj, mp_math_ ## py_name);
6786
6887#if MP_NEED_LOG2
6988// 1.442695040888963407354163704 is 1/_M_LN2
7089#define log2 (x ) (log(x) * 1.442695040888963407354163704)
7190#endif
7291
7392// sqrt(x): returns the square root of x
74- MATH_FUN_1_ERRCOND (sqrt , sqrt , ( x < ( mp_float_t ) 0.0 ) )
93+ MATH_FUN_1 (sqrt , sqrt )
7594// pow(x, y): returns x to the power of y
7695MATH_FUN_2 (pow , pow )
7796// exp(x)
@@ -80,9 +99,9 @@ MATH_FUN_1(exp, exp)
8099// expm1(x)
81100MATH_FUN_1 (expm1 , expm1 )
82101// log2(x)
83- MATH_FUN_1_ERRCOND (log2 , log2 , ( x <= ( mp_float_t ) 0.0 ) )
102+ MATH_FUN_1 (log2 , log2 )
84103// log10(x)
85- MATH_FUN_1_ERRCOND (log10 , log10 , ( x <= ( mp_float_t ) 0.0 ) )
104+ MATH_FUN_1 (log10 , log10 )
86105// cosh(x)
87106MATH_FUN_1 (cosh , cosh )
88107// sinh(x)
@@ -113,9 +132,15 @@ MATH_FUN_2(atan2, atan2)
113132// ceil(x)
114133MATH_FUN_1_TO_INT (ceil , ceil )
115134// copysign(x, y)
116- MATH_FUN_2 (copysign , copysign )
135+ STATIC mp_float_t MICROPY_FLOAT_C_FUN (copysign_func )(mp_float_t x , mp_float_t y ) {
136+ return MICROPY_FLOAT_C_FUN (copysign )(x , y );
137+ }
138+ MATH_FUN_2 (copysign , copysign_func )
117139// fabs(x)
118- MATH_FUN_1 (fabs , fabs )
140+ STATIC mp_float_t MICROPY_FLOAT_C_FUN (fabs_func )(mp_float_t x ) {
141+ return MICROPY_FLOAT_C_FUN (fabs )(x );
142+ }
143+ MATH_FUN_1 (fabs , fabs_func )
119144// floor(x)
120145MATH_FUN_1_TO_INT (floor , floor ) //TODO: delegate to x.__floor__() if x is not a float
121146// fmod(x, y)
@@ -129,7 +154,7 @@ MATH_FUN_1_TO_BOOL(isnan, isnan)
129154// trunc(x)
130155MATH_FUN_1_TO_INT (trunc , trunc )
131156// ldexp(x, exp)
132- MATH_FUN_2 (ldexp , ldexp )
157+ MATH_FUN_2_FLT_INT (ldexp , ldexp )
133158#if MICROPY_PY_MATH_SPECIAL_FUNCTIONS
134159// erf(x): return the error function of x
135160MATH_FUN_1 (erf , erf )
0 commit comments