diff --git a/py/builtin.c b/py/builtin.c index 5b70531ae..471e294cc 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -247,14 +247,16 @@ STATIC mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) { mp_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1_in); mp_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2_in); if (i2 == 0) { + #if MICROPY_PY_BUILTINS_FLOAT zero_division_error: + #endif nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "division by zero")); } mp_obj_t args[2]; args[0] = MP_OBJ_NEW_SMALL_INT(i1 / i2); args[1] = MP_OBJ_NEW_SMALL_INT(i1 % i2); return mp_obj_new_tuple(2, args); -#if MICROPY_PY_BUILTINS_FLOAT + #if MICROPY_PY_BUILTINS_FLOAT } else if (MP_OBJ_IS_TYPE(o1_in, &mp_type_float) || MP_OBJ_IS_TYPE(o2_in, &mp_type_float)) { mp_float_t f1 = mp_obj_get_float(o1_in); mp_float_t f2 = mp_obj_get_float(o2_in); @@ -267,7 +269,7 @@ STATIC mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) { mp_obj_new_float(f2), }; return mp_obj_new_tuple(2, tuple); -#endif + #endif } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in))); } diff --git a/tests/float/float_divmod.py b/tests/float/float_divmod.py new file mode 100644 index 000000000..8e7cd435a --- /dev/null +++ b/tests/float/float_divmod.py @@ -0,0 +1,25 @@ +# test floating point floor divide and modulus +# it has some tricky corner cases + +def test(x, y): + div, mod = divmod(x, y) + print('%.8f %.8f %.8f %.8f' % (x // y, x % y, div, mod)) + print(div == x // y, mod == x % y, abs(div * y + mod - x) < 1e-15) + +test(1.23456, 0.7) +test(-1.23456, 0.7) +test(1.23456, -0.7) +test(-1.23456, -0.7) + +a = 1.23456 +b = 0.7 +test(a, b) +test(a, -b) +test(-a, b) +test(-a, -b) + +for i in range(25): + x = (i - 12.5) / 6 + for j in range(25): + y = (j - 12.5) / 6 + test(x, y) diff --git a/tests/float/float_divmod_relaxed.py b/tests/float/float_divmod_relaxed.py new file mode 100644 index 000000000..7054d2ca6 --- /dev/null +++ b/tests/float/float_divmod_relaxed.py @@ -0,0 +1,27 @@ +# test floating point floor divide and modulus +# it has some tricky corner cases + +# pyboard has 32-bit floating point and gives different (but still +# correct) answers for certain combinations of divmod arguments. + +def test(x, y): + div, mod = divmod(x, y) + print(div == x // y, mod == x % y, abs(div * y + mod - x) < 1e-6) + +test(1.23456, 0.7) +test(-1.23456, 0.7) +test(1.23456, -0.7) +test(-1.23456, -0.7) + +a = 1.23456 +b = 0.7 +test(a, b) +test(a, -b) +test(-a, b) +test(-a, -b) + +for i in range(25): + x = (i - 12.5) / 6 + for j in range(25): + y = (j - 12.5) / 6 + test(x, y)