diff options
author | Jan Klusacek <honza.klu@gmail.com> | 2018-01-09 22:47:35 +0100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2018-05-22 14:18:16 +1000 |
commit | b318ebf1015ced6354f8bbaf035308214b3f5c5d (patch) | |
tree | 07d98e13d450884a046ff822702f787d76c2ba7a /py/modbuiltins.c | |
parent | f2ec7925542e5a75b2da7ef378f5df66fdb6fad9 (diff) |
py/modbuiltins: Add support for rounding integers.
As per CPython semantics. This feature is controlled by
MICROPY_PY_BUILTINS_ROUND_INT which is disabled by default.
Diffstat (limited to 'py/modbuiltins.c')
-rw-r--r-- | py/modbuiltins.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/py/modbuiltins.c b/py/modbuiltins.c index 0d511338b..b216e021f 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -445,7 +445,36 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_repr_obj, mp_builtin_repr); STATIC mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) { mp_obj_t o_in = args[0]; if (MP_OBJ_IS_INT(o_in)) { - return o_in; + if (n_args <= 1) { + return o_in; + } + + #if !MICROPY_PY_BUILTINS_ROUND_INT + mp_raise_NotImplementedError(NULL); + #else + mp_int_t num_dig = mp_obj_get_int(args[1]); + if (num_dig >= 0) { + return o_in; + } + + mp_obj_t mult = mp_binary_op(MP_BINARY_OP_POWER, MP_OBJ_NEW_SMALL_INT(10), MP_OBJ_NEW_SMALL_INT(-num_dig)); + mp_obj_t half_mult = mp_binary_op(MP_BINARY_OP_FLOOR_DIVIDE, mult, MP_OBJ_NEW_SMALL_INT(2)); + mp_obj_t modulo = mp_binary_op(MP_BINARY_OP_MODULO, o_in, mult); + mp_obj_t rounded = mp_binary_op(MP_BINARY_OP_SUBTRACT, o_in, modulo); + if (mp_obj_is_true(mp_binary_op(MP_BINARY_OP_MORE, half_mult, modulo))) { + return rounded; + } else if (mp_obj_is_true(mp_binary_op(MP_BINARY_OP_MORE, modulo, half_mult))) { + return mp_binary_op(MP_BINARY_OP_ADD, rounded, mult); + } else { + // round to even number + mp_obj_t floor = mp_binary_op(MP_BINARY_OP_FLOOR_DIVIDE, o_in, mult); + if (mp_obj_is_true(mp_binary_op(MP_BINARY_OP_AND, floor, MP_OBJ_NEW_SMALL_INT(1)))) { + return mp_binary_op(MP_BINARY_OP_ADD, rounded, mult); + } else { + return rounded; + } + } + #endif } #if MICROPY_PY_BUILTINS_FLOAT mp_float_t val = mp_obj_get_float(o_in); |