summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/builtin.c5
-rw-r--r--py/smallint.c20
-rw-r--r--tests/basics/int_divmod.py21
-rw-r--r--tests/basics/modulo.py23
4 files changed, 34 insertions, 35 deletions
diff --git a/py/builtin.c b/py/builtin.c
index 1af92a448f..133473d019 100644
--- a/py/builtin.c
+++ b/py/builtin.c
@@ -33,6 +33,7 @@
#include "qstr.h"
#include "obj.h"
#include "objstr.h"
+#include "smallint.h"
#include "runtime0.h"
#include "runtime.h"
#include "builtin.h"
@@ -253,8 +254,8 @@ STATIC mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
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);
+ args[0] = MP_OBJ_NEW_SMALL_INT(mp_small_int_floor_divide(i1, i2));
+ args[1] = MP_OBJ_NEW_SMALL_INT(mp_small_int_modulo(i1, i2));
return mp_obj_new_tuple(2, args);
#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)) {
diff --git a/py/smallint.c b/py/smallint.c
index 804514799f..3a06c40a9f 100644
--- a/py/smallint.c
+++ b/py/smallint.c
@@ -57,23 +57,23 @@ bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y) {
}
mp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor) {
- mp_int_t lsign = (dividend >= 0) ? 1 :-1;
- mp_int_t rsign = (divisor >= 0) ? 1 :-1;
+ // Python specs require that mod has same sign as second operand
dividend %= divisor;
- if (lsign != rsign) {
+ if ((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)) {
dividend += divisor;
}
return dividend;
}
mp_int_t mp_small_int_floor_divide(mp_int_t num, mp_int_t denom) {
- mp_int_t lsign = num > 0 ? 1 : -1;
- mp_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;
+ if (num >= 0) {
+ if (denom < 0) {
+ num += -denom - 1;
+ }
} else {
- return num / denom;
+ if (denom >= 0) {
+ num += -denom + 1;
+ }
}
+ return num / denom;
}
diff --git a/tests/basics/int_divmod.py b/tests/basics/int_divmod.py
new file mode 100644
index 0000000000..71a990823e
--- /dev/null
+++ b/tests/basics/int_divmod.py
@@ -0,0 +1,21 @@
+# test integer floor division and modulo
+
+# test all combination of +/-/0 cases
+for i in range(-2, 3):
+ for j in range(-4, 5):
+ if j != 0:
+ print(i, j, i // j, i % j, divmod(i, j))
+
+# this tests compiler constant folding
+print(123 // 7, 123 % 7)
+print(-123 // 7, -123 % 7)
+print(123 // -7, 123 % -7)
+print(-123 // -7, -123 % -7)
+
+# this tests bignum modulo
+a = 987654321987987987987987987987
+b = 19
+print(a % b)
+print(a % -b)
+print(-a % b)
+print(-a % -b)
diff --git a/tests/basics/modulo.py b/tests/basics/modulo.py
deleted file mode 100644
index c95305d13d..0000000000
--- a/tests/basics/modulo.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# check modulo matches python definition
-
-# this tests compiler constant folding
-print(123 % 7)
-print(-123 % 7)
-print(123 % -7)
-print(-123 % -7)
-
-a = 321
-b = 19
-print(a % b)
-print(a % -b)
-print(-a % b)
-print(-a % -b)
-
-
-a = 987654321987987987987987987987
-b = 19
-
-print(a % b)
-print(a % -b)
-print(-a % b)
-print(-a % -b)