diff options
author | stijn <stijn@ignitron.net> | 2020-09-08 15:22:34 +0200 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2020-09-11 10:04:57 +1000 |
commit | 2e54d9d146b34d7ad00e4394c9767f4319244cdf (patch) | |
tree | b6d56e3d53b9fef5d5898964d7bdd086e23016d5 /py | |
parent | 8d5a40c86e384bf3cddb2f687374e0bb1ae6df7d (diff) | |
download | micropython-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.c | 12 | ||||
-rw-r--r-- | py/mpconfig.h | 5 | ||||
-rw-r--r-- | py/objfloat.c | 6 |
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: { |