Skip to content

Commit c58607a

Browse files
authored
Berry math.min() and math.max() (#21705)
1 parent 8a0493b commit c58607a

File tree

3 files changed

+85
-0
lines changed

3 files changed

+85
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file.
77
### Added
88
- ESP32 support for power and energy limit checks, like ``MaxEnergy2`` per phase (#21695)
99
- Berry `tasmota.rtc("config_time")` (#21698)
10+
- Berry `math.min()` and `math.max()`
1011

1112
### Breaking Changed
1213

lib/libesp32/berry/src/be_mathlib.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,61 @@ static int m_rand(bvm *vm)
303303
be_return(vm);
304304
}
305305

306+
/* check that all arguments are either int or real, and return true if at least one is real */
307+
static int m_check_int_or_has_real(bvm *vm)
308+
{
309+
int argc = be_top(vm);
310+
int has_real = 0;
311+
for (int i = 1; i <= argc; ++i) {
312+
if (be_isreal(vm, i)) {
313+
has_real = 1;
314+
} else if (!be_isint(vm, i)) {
315+
be_raise(vm, "type_error", "arguments must be numbers");
316+
}
317+
}
318+
return has_real;
319+
}
320+
321+
static int m_min_max(bvm *vm, int is_min) {
322+
int argc = be_top(vm);
323+
if (argc > 0) {
324+
/* see if at least one argument is float, else they are all ints */
325+
int has_real = m_check_int_or_has_real(vm);
326+
if (has_real) {
327+
breal bound = be_toreal(vm, 1);
328+
for (int i = 2; i <= argc; ++i) {
329+
breal x = be_toreal(vm, i);
330+
if (is_min ? (x < bound) : (x > bound)) {
331+
bound = x;
332+
}
333+
}
334+
be_pushreal(vm, bound);
335+
} else {
336+
bint bound = be_toint(vm, 1);
337+
for (int i = 2; i <= argc; ++i) {
338+
bint x = be_toint(vm, i);
339+
if (is_min ? (x < bound) : (x > bound)) {
340+
bound = x;
341+
}
342+
}
343+
be_pushint(vm, bound);
344+
}
345+
be_return(vm);
346+
}
347+
be_return_nil(vm);
348+
349+
}
350+
351+
int m_min(bvm *vm)
352+
{
353+
return m_min_max(vm, 1);
354+
}
355+
356+
int m_max(bvm *vm)
357+
{
358+
return m_min_max(vm, 0);
359+
}
360+
306361
#if !BE_USE_PRECOMPILED_OBJECT
307362
be_native_module_attr_table(math) {
308363
be_native_module_function("isnan", m_isnan),
@@ -330,6 +385,8 @@ be_native_module_attr_table(math) {
330385
be_native_module_function("pow", m_pow),
331386
be_native_module_function("srand", m_srand),
332387
be_native_module_function("rand", m_rand),
388+
be_native_module_function("min", m_min),
389+
be_native_module_function("max", m_max),
333390
be_native_module_real("pi", M_PI),
334391
be_native_module_real("nan", NAN),
335392
be_native_module_real("inf", INFINITY),
@@ -366,6 +423,8 @@ module math (scope: global, depend: BE_USE_MATH_MODULE) {
366423
pow, func(m_pow)
367424
srand, func(m_srand)
368425
rand, func(m_rand)
426+
min, func(m_min)
427+
max, func(m_max)
369428
pi, real(M_PI)
370429
nan, real(NAN)
371430
inf, real(INFINITY)

lib/libesp32/berry/tests/math.be

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,28 @@ assert(math.round(-3.6) == -4)
5858

5959
assert(math.round() == 0)
6060

61+
#- min and max -#
62+
def assert_error(f, error_type)
63+
try
64+
f()
65+
assert(false, 'unexpected execution flow')
66+
except .. as e, m
67+
assert(e == error_type)
68+
end
69+
end
70+
71+
assert(math.min() == nil)
72+
assert(math.min(0) == 0)
73+
assert(math.min(0,2,10,56) == 0)
74+
assert(math.min(4, 2, -10, 3) == -10)
75+
assert(math.min(4, 2) == 2)
76+
77+
# result is int unless one of the parameters is real
78+
assert(type(math.min(4, 2, -10, 3)) == 'int')
79+
assert(type(math.min(4, 2, -10.0, 3)) == 'real')
80+
81+
assert(math.min(-3.4, 5) == -3.4)
82+
83+
# test invalid parameters
84+
assert_error(def () return math.min(4, nil) end, 'type_error')
85+
assert_error(def () return math.min(4, "", 4.5) end, 'type_error')

0 commit comments

Comments
 (0)