From c58607a5b538e3c5ff6d3c4db844a7caa24d4835 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sat, 29 Jun 2024 10:42:21 +0200 Subject: [PATCH] Berry `math.min()` and `math.max()` (#21705) --- CHANGELOG.md | 1 + lib/libesp32/berry/src/be_mathlib.c | 59 +++++++++++++++++++++++++++++ lib/libesp32/berry/tests/math.be | 25 ++++++++++++ 3 files changed, 85 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c77af5405..2fb703c71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added - ESP32 support for power and energy limit checks, like ``MaxEnergy2`` per phase (#21695) - Berry `tasmota.rtc("config_time")` (#21698) +- Berry `math.min()` and `math.max()` ### Breaking Changed diff --git a/lib/libesp32/berry/src/be_mathlib.c b/lib/libesp32/berry/src/be_mathlib.c index 17fbfe159..0cef918e0 100644 --- a/lib/libesp32/berry/src/be_mathlib.c +++ b/lib/libesp32/berry/src/be_mathlib.c @@ -303,6 +303,61 @@ static int m_rand(bvm *vm) be_return(vm); } +/* check that all arguments are either int or real, and return true if at least one is real */ +static int m_check_int_or_has_real(bvm *vm) +{ + int argc = be_top(vm); + int has_real = 0; + for (int i = 1; i <= argc; ++i) { + if (be_isreal(vm, i)) { + has_real = 1; + } else if (!be_isint(vm, i)) { + be_raise(vm, "type_error", "arguments must be numbers"); + } + } + return has_real; +} + +static int m_min_max(bvm *vm, int is_min) { + int argc = be_top(vm); + if (argc > 0) { + /* see if at least one argument is float, else they are all ints */ + int has_real = m_check_int_or_has_real(vm); + if (has_real) { + breal bound = be_toreal(vm, 1); + for (int i = 2; i <= argc; ++i) { + breal x = be_toreal(vm, i); + if (is_min ? (x < bound) : (x > bound)) { + bound = x; + } + } + be_pushreal(vm, bound); + } else { + bint bound = be_toint(vm, 1); + for (int i = 2; i <= argc; ++i) { + bint x = be_toint(vm, i); + if (is_min ? (x < bound) : (x > bound)) { + bound = x; + } + } + be_pushint(vm, bound); + } + be_return(vm); + } + be_return_nil(vm); + +} + +int m_min(bvm *vm) +{ + return m_min_max(vm, 1); +} + +int m_max(bvm *vm) +{ + return m_min_max(vm, 0); +} + #if !BE_USE_PRECOMPILED_OBJECT be_native_module_attr_table(math) { be_native_module_function("isnan", m_isnan), @@ -330,6 +385,8 @@ be_native_module_attr_table(math) { be_native_module_function("pow", m_pow), be_native_module_function("srand", m_srand), be_native_module_function("rand", m_rand), + be_native_module_function("min", m_min), + be_native_module_function("max", m_max), be_native_module_real("pi", M_PI), be_native_module_real("nan", NAN), be_native_module_real("inf", INFINITY), @@ -366,6 +423,8 @@ module math (scope: global, depend: BE_USE_MATH_MODULE) { pow, func(m_pow) srand, func(m_srand) rand, func(m_rand) + min, func(m_min) + max, func(m_max) pi, real(M_PI) nan, real(NAN) inf, real(INFINITY) diff --git a/lib/libesp32/berry/tests/math.be b/lib/libesp32/berry/tests/math.be index 6ad8b01c1..9cc39a226 100644 --- a/lib/libesp32/berry/tests/math.be +++ b/lib/libesp32/berry/tests/math.be @@ -58,3 +58,28 @@ assert(math.round(-3.6) == -4) assert(math.round() == 0) +#- min and max -# +def assert_error(f, error_type) + try + f() + assert(false, 'unexpected execution flow') + except .. as e, m + assert(e == error_type) + end +end + +assert(math.min() == nil) +assert(math.min(0) == 0) +assert(math.min(0,2,10,56) == 0) +assert(math.min(4, 2, -10, 3) == -10) +assert(math.min(4, 2) == 2) + +# result is int unless one of the parameters is real +assert(type(math.min(4, 2, -10, 3)) == 'int') +assert(type(math.min(4, 2, -10.0, 3)) == 'real') + +assert(math.min(-3.4, 5) == -3.4) + +# test invalid parameters +assert_error(def () return math.min(4, nil) end, 'type_error') +assert_error(def () return math.min(4, "", 4.5) end, 'type_error')