diff options
author | Damien George <damien.p.george@gmail.com> | 2014-10-22 23:05:50 +0100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2014-10-22 23:05:50 +0100 |
commit | e72be1b999a3337f74a8e5a8f61705666f834d2b (patch) | |
tree | 6275c2b8eb01130f987df7ebe414f6690b971bec /py | |
parent | 5fc42a6c9733bd8f165be7fa8d70fb614ae8de53 (diff) | |
download | micropython-e72be1b999a3337f74a8e5a8f61705666f834d2b.tar.gz micropython-e72be1b999a3337f74a8e5a8f61705666f834d2b.zip |
py: Fix smallint modulo with negative arguments.
Addresses issue #927.
Diffstat (limited to 'py')
-rw-r--r-- | py/builtin.c | 5 | ||||
-rw-r--r-- | py/smallint.c | 20 |
2 files changed, 13 insertions, 12 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; } |