Skip to content
Snippets Groups Projects
Commit 125eae1b authored by Damien George's avatar Damien George
Browse files

py/modbuiltins: For round() builtin use nearbyint instead of round.

The C nearbyint function has exactly the semantics that Python's round()
requires, whereas C's round() requires extra steps to handle rounding of
numbers half way between integers.  So using nearbyint reduces code size
and potentially eliminates any source of errors in the handling of half-way
numbers.

Also, bare-metal implementations of nearbyint can be more efficient than
round, so further code size is saved (and efficiency improved).

nearbyint is provided in the C99 standard so it should be available on all
supported platforms.
parent fb161aa4
No related branches found
No related tags found
No related merge requests found
...@@ -108,7 +108,7 @@ LIB_SRC_C = $(addprefix lib/,\ ...@@ -108,7 +108,7 @@ LIB_SRC_C = $(addprefix lib/,\
libc/string0.c \ libc/string0.c \
libm/math.c \ libm/math.c \
libm/fmodf.c \ libm/fmodf.c \
libm/roundf.c \ libm/nearbyintf.c \
libm/ef_sqrt.c \ libm/ef_sqrt.c \
libm/kf_rem_pio2.c \ libm/kf_rem_pio2.c \
libm/kf_sin.c \ libm/kf_sin.c \
......
...@@ -473,18 +473,11 @@ STATIC mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) { ...@@ -473,18 +473,11 @@ STATIC mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) {
mp_float_t val = mp_obj_get_float(o_in); mp_float_t val = mp_obj_get_float(o_in);
mp_float_t mult = MICROPY_FLOAT_C_FUN(pow)(10, num_dig); mp_float_t mult = MICROPY_FLOAT_C_FUN(pow)(10, num_dig);
// TODO may lead to overflow // TODO may lead to overflow
mp_float_t rounded = MICROPY_FLOAT_C_FUN(round)(val * mult) / mult; mp_float_t rounded = MICROPY_FLOAT_C_FUN(nearbyint)(val * mult) / mult;
return mp_obj_new_float(rounded); return mp_obj_new_float(rounded);
} }
mp_float_t val = mp_obj_get_float(o_in); mp_float_t val = mp_obj_get_float(o_in);
mp_float_t rounded = MICROPY_FLOAT_C_FUN(round)(val); mp_float_t rounded = MICROPY_FLOAT_C_FUN(nearbyint)(val);
mp_int_t r = rounded;
// make rounded value even if it was halfway between ints
if (val - rounded == 0.5) {
r = (r + 1) & (~1);
} else if (val - rounded == -0.5) {
r &= ~1;
}
#else #else
mp_int_t r = mp_obj_get_int(o_in); mp_int_t r = mp_obj_get_int(o_in);
#endif #endif
......
...@@ -47,7 +47,7 @@ SRC_TEST_C = \ ...@@ -47,7 +47,7 @@ SRC_TEST_C = \
LIB_SRC_C = $(addprefix lib/,\ LIB_SRC_C = $(addprefix lib/,\
libm/math.c \ libm/math.c \
libm/fmodf.c \ libm/fmodf.c \
libm/roundf.c \ libm/nearbyintf.c \
libm/ef_sqrt.c \ libm/ef_sqrt.c \
libm/kf_rem_pio2.c \ libm/kf_rem_pio2.c \
libm/kf_sin.c \ libm/kf_sin.c \
......
...@@ -86,7 +86,7 @@ SRC_LIB = $(addprefix lib/,\ ...@@ -86,7 +86,7 @@ SRC_LIB = $(addprefix lib/,\
libm/atanf.c \ libm/atanf.c \
libm/atan2f.c \ libm/atan2f.c \
libm/fmodf.c \ libm/fmodf.c \
libm/roundf.c \ libm/nearbyintf.c \
libm/log1pf.c \ libm/log1pf.c \
libm/acoshf.c \ libm/acoshf.c \
libm/asinhf.c \ libm/asinhf.c \
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment