Skip to content

Commit 1559a97

Browse files
committed
py: Add builtin round function.
Addresses issue adafruit#934.
1 parent fa73c9c commit 1559a97

7 files changed

Lines changed: 73 additions & 1 deletion

File tree

lib/libm/roundf.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*****************************************************************************/
2+
/*****************************************************************************/
3+
// roundf from musl-0.9.15
4+
/*****************************************************************************/
5+
/*****************************************************************************/
6+
7+
#include "libm.h"
8+
9+
float roundf(float x)
10+
{
11+
union {float f; uint32_t i;} u = {x};
12+
int e = u.i >> 23 & 0xff;
13+
float_t y;
14+
15+
if (e >= 0x7f+23)
16+
return x;
17+
if (u.i >> 31)
18+
x = -x;
19+
if (e < 0x7f-1) {
20+
FORCE_EVAL(x + 0x1p23f);
21+
return 0*u.f;
22+
}
23+
y = (float)(x + 0x1p23f) - 0x1p23f - x;
24+
if (y > 0.5f)
25+
y = y + x - 1;
26+
else if (y <= -0.5f)
27+
y = y + x + 1;
28+
else
29+
y = y + x;
30+
if (u.i >> 31)
31+
y = -y;
32+
return y;
33+
}

py/builtin.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,9 +448,30 @@ STATIC mp_obj_t mp_builtin_repr(mp_obj_t o_in) {
448448
vstr_free(vstr);
449449
return s;
450450
}
451-
452451
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_repr_obj, mp_builtin_repr);
453452

453+
STATIC mp_obj_t mp_builtin_round(mp_obj_t o_in) {
454+
// TODO support second arg
455+
if (MP_OBJ_IS_INT(o_in)) {
456+
return o_in;
457+
}
458+
#if MICROPY_PY_BUILTINS_FLOAT
459+
mp_float_t val = mp_obj_get_float(o_in);
460+
mp_float_t rounded = MICROPY_FLOAT_C_FUN(round)(val);
461+
mp_int_t r = rounded;
462+
// make rounded value even if it was halfway between ints
463+
if (val - rounded == 0.5) {
464+
r = (r + 1) & (~1);
465+
} else if (val - rounded == -0.5) {
466+
r &= ~1;
467+
}
468+
#else
469+
mp_int_t r = mp_obj_get_int(o_in);
470+
#endif
471+
return mp_obj_new_int(r);
472+
}
473+
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_round_obj, mp_builtin_round);
474+
454475
STATIC mp_obj_t mp_builtin_sum(mp_uint_t n_args, const mp_obj_t *args) {
455476
assert(1 <= n_args && n_args <= 2);
456477
mp_obj_t value;

py/builtin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_ord_obj);
6161
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_pow_obj);
6262
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_print_obj);
6363
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_repr_obj);
64+
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_round_obj);
6465
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sorted_obj);
6566
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sum_obj);
6667

py/builtintables.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = {
118118
{ MP_OBJ_NEW_QSTR(MP_QSTR_pow), (mp_obj_t)&mp_builtin_pow_obj },
119119
{ MP_OBJ_NEW_QSTR(MP_QSTR_print), (mp_obj_t)&mp_builtin_print_obj },
120120
{ MP_OBJ_NEW_QSTR(MP_QSTR_repr), (mp_obj_t)&mp_builtin_repr_obj },
121+
{ MP_OBJ_NEW_QSTR(MP_QSTR_round), (mp_obj_t)&mp_builtin_round_obj },
121122
{ MP_OBJ_NEW_QSTR(MP_QSTR_sorted), (mp_obj_t)&mp_builtin_sorted_obj },
122123
{ MP_OBJ_NEW_QSTR(MP_QSTR_sum), (mp_obj_t)&mp_builtin_sum_obj },
123124

py/qstrdefs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ Q(range)
201201
Q(read)
202202
Q(repr)
203203
Q(reversed)
204+
Q(round)
204205
Q(sorted)
205206
Q(staticmethod)
206207
Q(sum)

stmhal/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ SRC_LIB = $(addprefix lib/,\
6868
libm/atanf.c \
6969
libm/atan2f.c \
7070
libm/fmodf.c \
71+
libm/roundf.c \
7172
)
7273

7374
SRC_C = \

tests/basics/builtin_round.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# test round()
2+
3+
# check basic cases
4+
tests = [
5+
False, True,
6+
0, 1, -1, 10,
7+
0.0, 1.0, 0.1, -0.1, 123.4, 123.6, -123.4, -123.6
8+
]
9+
for t in tests:
10+
print(round(t))
11+
12+
# check .5 cases
13+
for i in range(11):
14+
print(round((i - 5) / 2))

0 commit comments

Comments
 (0)