Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Berry math.min() and math.max() #21705

Merged
merged 1 commit into from
Jun 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
59 changes: 59 additions & 0 deletions lib/libesp32/berry/src/be_mathlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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)
Expand Down
25 changes: 25 additions & 0 deletions lib/libesp32/berry/tests/math.be
Original file line number Diff line number Diff line change
Expand Up @@ -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')