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.
This commit is contained in:
parent
8d5a40c86e
commit
2e54d9d146
|
@ -236,6 +236,8 @@ extern const struct _mp_obj_module_t mp_module_time;
|
|||
#define MICROPY_PY_MATH_FMOD_FIX_INFNAN (1)
|
||||
#ifdef _WIN64
|
||||
#define MICROPY_PY_MATH_MODF_FIX_NEGZERO (1)
|
||||
#else
|
||||
#define MICROPY_PY_MATH_POW_FIX_NAN (1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
12
py/modmath.c
12
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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -38,7 +38,7 @@ for name, f, args in (
|
|||
|
||||
# double argument functions
|
||||
for name, f, args in (
|
||||
("pow", math.pow, ((0, 2), (-1, 2), (0, -1), (-1, 2.3))),
|
||||
("pow", math.pow, ((0, 2), (-1, 2), (0, -1), (-1, 2.3), (nan, 0), (1, nan))),
|
||||
("fmod", math.fmod, ((1.2, inf), (1.2, -inf), (1.2, 0), (inf, 1.2))),
|
||||
("atan2", math.atan2, ((0, 0), (-inf, inf), (-inf, -inf), (inf, -inf))),
|
||||
("copysign", math.copysign, ()),
|
||||
|
|
Loading…
Reference in New Issue