summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
authorstijn <stijn@ignitron.net>2020-09-08 15:22:34 +0200
committerDamien George <damien@micropython.org>2020-09-11 10:04:57 +1000
commit2e54d9d146b34d7ad00e4394c9767f4319244cdf (patch)
treeb6d56e3d53b9fef5d5898964d7bdd086e23016d5 /py
parent8d5a40c86e384bf3cddb2f687374e0bb1ae6df7d (diff)
downloadmicropython-2e54d9d146b34d7ad00e4394c9767f4319244cdf.tar.gz
micropython-2e54d9d146b34d7ad00e4394c9767f4319244cdf.zip
py: Fix handling of NaN in certain pow implementations.
Adds a new compile-time option MICROPY_PY_MATH_POW_FIX_NAN for use with toolchains that don't handle pow-of-NaN correctly.
Diffstat (limited to 'py')
-rw-r--r--py/modmath.c12
-rw-r--r--py/mpconfig.h5
-rw-r--r--py/objfloat.c6
3 files changed, 23 insertions, 0 deletions
diff --git a/py/modmath.c b/py/modmath.c
index b312eeb3d2..b7948f39e7 100644
--- a/py/modmath.c
+++ b/py/modmath.c
@@ -98,7 +98,19 @@ mp_float_t MICROPY_FLOAT_C_FUN(log2)(mp_float_t x) {
// sqrt(x): returns the square root of x
MATH_FUN_1(sqrt, sqrt)
// pow(x, y): returns x to the power of y
+#if MICROPY_PY_MATH_POW_FIX_NAN
+mp_float_t pow_func(mp_float_t x, mp_float_t y) {
+ // pow(base, 0) returns 1 for any base, even when base is NaN
+ // pow(+1, exponent) returns 1 for any exponent, even when exponent is NaN
+ if (x == MICROPY_FLOAT_CONST(1.0) || y == MICROPY_FLOAT_CONST(0.0)) {
+ return MICROPY_FLOAT_CONST(1.0);
+ }
+ return MICROPY_FLOAT_C_FUN(pow)(x, y);
+}
+MATH_FUN_2(pow, pow_func)
+#else
MATH_FUN_2(pow, pow)
+#endif
// exp(x)
MATH_FUN_1(exp, exp)
#if MICROPY_PY_MATH_SPECIAL_FUNCTIONS
diff --git a/py/mpconfig.h b/py/mpconfig.h
index ae4cabfdcf..12517316c6 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -1160,6 +1160,11 @@ typedef double mp_float_t;
#define MICROPY_PY_MATH_MODF_FIX_NEGZERO (0)
#endif
+// Whether to provide fix for pow(1, NaN) and pow(NaN, 0), which both should be 1 not NaN.
+#ifndef MICROPY_PY_MATH_POW_FIX_NAN
+#define MICROPY_PY_MATH_POW_FIX_NAN (0)
+#endif
+
// Whether to provide "cmath" module
#ifndef MICROPY_PY_CMATH
#define MICROPY_PY_CMATH (0)
diff --git a/py/objfloat.c b/py/objfloat.c
index f1e401ecce..451609492e 100644
--- a/py/objfloat.c
+++ b/py/objfloat.c
@@ -300,6 +300,12 @@ mp_obj_t mp_obj_float_binary_op(mp_binary_op_t op, mp_float_t lhs_val, mp_obj_t
mp_raise_ValueError(MP_ERROR_TEXT("complex values not supported"));
#endif
}
+ #if MICROPY_PY_MATH_POW_FIX_NAN // Also see modmath.c.
+ if (lhs_val == MICROPY_FLOAT_CONST(1.0) || rhs_val == MICROPY_FLOAT_CONST(0.0)) {
+ lhs_val = MICROPY_FLOAT_CONST(1.0);
+ break;
+ }
+ #endif
lhs_val = MICROPY_FLOAT_C_FUN(pow)(lhs_val, rhs_val);
break;
case MP_BINARY_OP_DIVMOD: {