3
3
*
4
4
* The MIT License (MIT)
5
5
*
6
- * Copyright (c) 2013, 2014 Damien P. George
6
+ * Copyright (c) 2013-2017 Damien P. George
7
7
*
8
8
* Permission is hereby granted, free of charge, to any person obtaining a copy
9
9
* of this software and associated documentation files (the "Software"), to deal
@@ -39,14 +39,31 @@ STATIC NORETURN void math_error(void) {
39
39
mp_raise_ValueError ("math domain error" );
40
40
}
41
41
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
+
42
61
#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
+ } \
44
65
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
45
66
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
-
50
67
#define MATH_FUN_1_TO_BOOL (py_name , c_name ) \
51
68
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))); } \
52
69
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) {
55
72
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))); } \
56
73
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
57
74
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)); \
65
78
} \
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);
67
86
68
87
#if MP_NEED_LOG2
69
88
// 1.442695040888963407354163704 is 1/_M_LN2
70
89
#define log2 (x ) (log(x) * 1.442695040888963407354163704)
71
90
#endif
72
91
73
92
// 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 )
75
94
// pow(x, y): returns x to the power of y
76
95
MATH_FUN_2 (pow , pow )
77
96
// exp(x)
@@ -80,9 +99,9 @@ MATH_FUN_1(exp, exp)
80
99
// expm1(x)
81
100
MATH_FUN_1 (expm1 , expm1 )
82
101
// log2(x)
83
- MATH_FUN_1_ERRCOND (log2 , log2 , ( x <= ( mp_float_t ) 0.0 ) )
102
+ MATH_FUN_1 (log2 , log2 )
84
103
// log10(x)
85
- MATH_FUN_1_ERRCOND (log10 , log10 , ( x <= ( mp_float_t ) 0.0 ) )
104
+ MATH_FUN_1 (log10 , log10 )
86
105
// cosh(x)
87
106
MATH_FUN_1 (cosh , cosh )
88
107
// sinh(x)
@@ -113,9 +132,15 @@ MATH_FUN_2(atan2, atan2)
113
132
// ceil(x)
114
133
MATH_FUN_1_TO_INT (ceil , ceil )
115
134
// 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 )
117
139
// 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 )
119
144
// floor(x)
120
145
MATH_FUN_1_TO_INT (floor , floor ) //TODO: delegate to x.__floor__() if x is not a float
121
146
// fmod(x, y)
@@ -129,7 +154,7 @@ MATH_FUN_1_TO_BOOL(isnan, isnan)
129
154
// trunc(x)
130
155
MATH_FUN_1_TO_INT (trunc , trunc )
131
156
// ldexp(x, exp)
132
- MATH_FUN_2 (ldexp , ldexp )
157
+ MATH_FUN_2_FLT_INT (ldexp , ldexp )
133
158
#if MICROPY_PY_MATH_SPECIAL_FUNCTIONS
134
159
// erf(x): return the error function of x
135
160
MATH_FUN_1 (erf , erf )
0 commit comments