From 56402796d87f75fbb9e42fc9e3c0adc027fb7c98 Mon Sep 17 00:00:00 2001 From: Rachel Dowdall Date: Sat, 22 Mar 2014 20:19:24 +0000 Subject: [PATCH] Fixed floor division on mp ints and small ints. Added a floordivide test case. --- py/compile.c | 10 ++++++---- py/objint_mpz.c | 11 +++++++++-- py/runtime.c | 7 ++++++- tests/basics/floordivide.py | 29 +++++++++++++++++++++++++++++ tests/basics/modulo.py | 17 +++++++++++++++-- 5 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 tests/basics/floordivide.py diff --git a/py/compile.c b/py/compile.c index 4eab094230..0a10b81768 100644 --- a/py/compile.c +++ b/py/compile.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "misc.h" #include "mpconfig.h" @@ -141,12 +142,13 @@ mp_parse_node_t fold_constants(mp_parse_node_t pn) { } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_SLASH)) { ; // pass } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) { - // XXX implement this properly as Python's % operator acts differently to C's - //pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 % arg1); pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, python_modulo(arg0, arg1)); } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) { - // XXX implement this properly as Python's // operator acts differently to C's - pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 / arg1); + //pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, + // floor((mp_float_t)arg0 / arg1)); + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, + python_floor_divide(arg0, arg1)); + } else { // shouldn't happen assert(0); diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 9c7727ba42..39ea7ca115 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -1,5 +1,6 @@ #include #include +#include #include "nlr.h" #include "misc.h" @@ -97,6 +98,12 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: { mpz_t rem; mpz_init_zero(&rem); mpz_divmod_inpl(&res->mpz, &rem, zlhs, zrhs); + if (zlhs->neg != zrhs->neg) { + if (!mpz_is_zero(&rem)) { + mpz_t mpzone; mpz_init_from_int(&mpzone, -1); + mpz_add_inpl(&res->mpz, &res->mpz, &mpzone); + } + } mpz_deinit(&rem); break; } @@ -105,8 +112,8 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mpz_t quo; mpz_init_zero(&quo); mpz_divmod_inpl(&quo, &res->mpz, zlhs, zrhs); mpz_deinit(&quo); - // Check signs and do Python style modulo - if (zlhs->neg != zrhs->neg) { + // Check signs and do Python style modulo + if (zlhs->neg != zrhs->neg) { mpz_add_inpl(&res->mpz, &res->mpz, zrhs); } break; diff --git a/py/runtime.c b/py/runtime.c index 95c3a44159..94f3190566 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "nlr.h" #include "misc.h" @@ -661,7 +662,11 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { break; } case RT_BINARY_OP_FLOOR_DIVIDE: - case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: lhs_val /= rhs_val; break; + case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: + { + lhs_val = python_floor_divide(lhs_val, rhs_val); + break; + } #if MICROPY_ENABLE_FLOAT case RT_BINARY_OP_TRUE_DIVIDE: case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: return mp_obj_new_float((mp_float_t)lhs_val / (mp_float_t)rhs_val); diff --git a/tests/basics/floordivide.py b/tests/basics/floordivide.py new file mode 100644 index 0000000000..930313d6c1 --- /dev/null +++ b/tests/basics/floordivide.py @@ -0,0 +1,29 @@ +# check modulo matches python definition + +# This tests compiler version +print(123 // 7) +print(-123 // 7) +print(123 // -7) +print(-123 // -7) + +a = 10000001 +b = 10000000 +print(a // b) +print(a // -b) +print(-a // b) +print(-a // -b) + +if True: + a = 987654321987987987987987987987 + b = 19 + + print(a // b) + print(a // -b) + print(-a // b) + print(-a // -b) + a = 10000000000000000000000000000000000000000000 + b = 100 + print(a // b) + print(a // -b) + print(-a // b) + print(-a // -b) diff --git a/tests/basics/modulo.py b/tests/basics/modulo.py index ce7ed2578c..4d83db6ec8 100644 --- a/tests/basics/modulo.py +++ b/tests/basics/modulo.py @@ -1,5 +1,5 @@ # check modulo matches python definition - +# This test compiler version print(123 % 7) print(-123 % 7) print(123 % -7) @@ -7,7 +7,6 @@ print(-123 % -7) a = 321 b = 19 - print(a % b) print(a % -b) print(-a % b) @@ -21,3 +20,17 @@ print(a % b) print(a % -b) print(-a % b) print(-a % -b) + +if False: + print(1.23456 % 0.7) + print(-1.23456 % 0.7) + print(1.23456 % -0.7) + print(-1.23456 % -0.7) + + a = 1.23456 + b = 0.7 + print(a % b) + print(a % -b) + print(-a % b) + print(-a % -b) +