summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
authorRachel Dowdall <rjdowdall@gmail.com>2014-03-22 20:29:56 +0000
committerRachel Dowdall <rjdowdall@gmail.com>2014-03-22 20:29:56 +0000
commit2d15deebdcf7d6fb8f78907e0c6ca9cb9c2aa000 (patch)
tree4dba583967542dd95ebdf3f62865f9bb56db2350 /py
parentcde8631f15db9941986f8d04534e52462a76094b (diff)
downloadmicropython-2d15deebdcf7d6fb8f78907e0c6ca9cb9c2aa000.tar.gz
micropython-2d15deebdcf7d6fb8f78907e0c6ca9cb9c2aa000.zip
Fixed floor division on mp ints and small ints. Added a floordivide test case.
Diffstat (limited to 'py')
-rw-r--r--py/compile.c10
-rw-r--r--py/intdivmod.c24
-rw-r--r--py/intdivmod.h4
-rw-r--r--py/objint_mpz.c11
-rw-r--r--py/runtime.c7
5 files changed, 49 insertions, 7 deletions
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 <stdio.h>
#include <string.h>
#include <assert.h>
+#include <math.h>
#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/intdivmod.c b/py/intdivmod.c
new file mode 100644
index 0000000000..4cb363b511
--- /dev/null
+++ b/py/intdivmod.c
@@ -0,0 +1,24 @@
+#include "mpconfig.h"
+
+machine_int_t python_modulo(machine_int_t dividend, machine_int_t divisor) {
+ machine_int_t lsign = (dividend >= 0) ? 1 :-1;
+ machine_int_t rsign = (divisor >= 0) ? 1 :-1;
+ dividend %= divisor;
+ if (lsign != rsign) {
+ dividend += divisor;
+ }
+ return dividend;
+}
+
+
+machine_int_t python_floor_divide(machine_int_t num, machine_int_t denom) {
+ machine_int_t lsign = num > 0 ? 1 : -1;
+ machine_int_t rsign = denom > 0 ? 1 : -1;
+ if (lsign == -1) {num *= -1;}
+ if (rsign == -1) {denom *= -1;}
+ if (lsign != rsign){
+ return - ( num + denom - 1) / denom;
+ } else {
+ return num / denom;
+ }
+}
diff --git a/py/intdivmod.h b/py/intdivmod.h
new file mode 100644
index 0000000000..7716bd21e9
--- /dev/null
+++ b/py/intdivmod.h
@@ -0,0 +1,4 @@
+// Functions for integer modulo and floor division
+
+machine_int_t python_modulo(machine_int_t dividend, machine_int_t divisor);
+machine_int_t python_floor_divide(machine_int_t num, machine_int_t denom);
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 <stdint.h>
#include <string.h>
+#include <stdio.h>
#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 <stdio.h>
#include <string.h>
#include <assert.h>
+#include <math.h>
#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);