From 2199450bfe7e3bc5b703bf5c0dbc7ded21888dba Mon Sep 17 00:00:00 2001 From: Oldes Huhuman Date: Wed, 11 Dec 2024 17:04:24 +0100 Subject: [PATCH] FEAT: Add functionality to find maximum and minimum values in a vector --- src/core/t-vector.c | 118 +++++++++++++++++++++++++++++++++ src/tests/units/vector-test.r3 | 69 +++++++++++++++++++ 2 files changed, 187 insertions(+) diff --git a/src/core/t-vector.c b/src/core/t-vector.c index 613d9c3310..80ddcfdf65 100644 --- a/src/core/t-vector.c +++ b/src/core/t-vector.c @@ -168,6 +168,116 @@ void Set_Vector_Row(REBSER *ser, REBVAL *blk) } } +void Find_Minimum_Of_Vector(REBSER *vect, REBVAL *ret) { + REBLEN len, n; + REBYTE *data; + + len = SERIES_TAIL(vect); + + if (len == 0) { + SET_NONE(ret); + return; + } + +#define FIND_MIN_INT(type) { \ + type *typed_data = (type *)data; \ + type min_value = typed_data[0]; \ + for (REBLEN i = 1; i < len; i++) { \ + if (typed_data[i] < min_value) \ + min_value = typed_data[i]; \ + } \ + SET_INTEGER(ret, min_value); \ + return; \ + } + +#define FIND_MIN_DEC(type) { \ + type *typed_data = (type *)data; \ + type min_value = typed_data[0]; \ + for (REBLEN i = 1; i < len; i++) { \ + if (typed_data[i] < min_value) \ + min_value = typed_data[i]; \ + } \ + SET_DECIMAL(ret, min_value); \ + return; \ + } + + data = SERIES_DATA(vect); + + switch (VECT_TYPE(vect)) { + case VTSI08: FIND_MIN_INT(i8); break; + case VTSI16: FIND_MIN_INT(i16); break; + case VTSI32: FIND_MIN_INT(i32); break; + case VTSI64: FIND_MIN_INT(i64); break; + case VTUI08: FIND_MIN_INT(u8); break; + case VTUI16: FIND_MIN_INT(u16); break; + case VTUI32: FIND_MIN_INT(u32); break; + case VTUI64: FIND_MIN_INT(u64); break; + case VTSF32: FIND_MIN_DEC(float); break; + case VTSF64: FIND_MIN_DEC(double); break; + default: + SET_NONE(ret); // Handle unknown types + return; + } + +#undef FIND_MIN_INT +#undef FIND_MIN_DEC +} + +void Find_Maximum_Of_Vector(REBSER *vect, REBVAL *ret) { + REBLEN len, n; + REBYTE *data; + + len = SERIES_TAIL(vect); + + if (len == 0) { + SET_NONE(ret); + return; + } + +#define FIND_MAX_INT(type) { \ + type *typed_data = (type *)data; \ + type max_value = typed_data[0]; \ + for (REBLEN i = 1; i < len; i++) { \ + if (typed_data[i] > max_value) \ + max_value = typed_data[i]; \ + } \ + SET_INTEGER(ret, max_value); \ + return; \ + } + +#define FIND_MAX_DEC(type) { \ + type *typed_data = (type *)data; \ + type max_value = typed_data[0]; \ + for (REBLEN i = 1; i < len; i++) { \ + if (typed_data[i] > max_value) \ + max_value = typed_data[i]; \ + } \ + SET_DECIMAL(ret, max_value); \ + return; \ + } + + data = SERIES_DATA(vect); + + switch (VECT_TYPE(vect)) { + case VTSI08: FIND_MAX_INT(i8); break; + case VTSI16: FIND_MAX_INT(i16); break; + case VTSI32: FIND_MAX_INT(i32); break; + case VTSI64: FIND_MAX_INT(i64); break; + case VTUI08: FIND_MAX_INT(u8); break; + case VTUI16: FIND_MAX_INT(u16); break; + case VTUI32: FIND_MAX_INT(u32); break; + case VTUI64: FIND_MAX_INT(u64); break; + case VTSF32: FIND_MAX_DEC(float); break; + case VTSF64: FIND_MAX_DEC(double); break; + default: + SET_NONE(ret); // Handle unknown types + return; + } + +#undef FIND_MAX_INT +#undef FIND_MAX_DEC +} + /*********************************************************************** ** @@ -190,6 +300,14 @@ void Set_Vector_Row(REBSER *ser, REBVAL *blk) case SYM_SIGNED: SET_LOGIC(ret, !(VECT_TYPE(vect) >= VTUI08 && VECT_TYPE(vect) <= VTUI64)); break; + case SYM_MIN: + case SYM_MINIMUM: + Find_Minimum_Of_Vector(vect, ret); + break; + case SYM_MAX: + case SYM_MAXIMUM: + Find_Maximum_Of_Vector(vect, ret); + break; default: return FALSE; } diff --git a/src/tests/units/vector-test.r3 b/src/tests/units/vector-test.r3 index 68085827f1..2e6008497c 100644 --- a/src/tests/units/vector-test.r3 +++ b/src/tests/units/vector-test.r3 @@ -463,6 +463,75 @@ Rebol [ ===end-group=== +===start-group=== "VECTOR ´minimum/maximum" + vi08: #(i8! [1 -2 0]) + vi16: #(i16! [1 -2 0]) + vi32: #(i32! [1 -2 0]) + vi64: #(i64! [1 -2 0]) + vu08: #(u8! [1 2 0]) + vu16: #(u16! [1 2 0]) + vu32: #(u32! [1 2 0]) + vu64: #(u64! [1 2 0]) + vf32: #(f32! [1 -2 0]) + vf64: #(f64! [1 -2 0]) + --test-- "Find minimum of the vector" + --assert vi08/min == -2 + --assert vi16/min == -2 + --assert vi32/min == -2 + --assert vi64/min == -2 + --assert vu08/min == 0 + --assert vu16/min == 0 + --assert vu32/min == 0 + --assert vu64/min == 0 + --assert vf32/min == -2.0 + --assert vf64/min == -2.0 + ;; it can be used also full word + --assert vi08/minimum == -2 + --test-- "Find maximum of the vector" + --assert vi08/max == 1 + --assert vi16/max == 1 + --assert vi32/max == 1 + --assert vi64/max == 1 + --assert vu08/max == 2 + --assert vu16/max == 2 + --assert vu32/max == 2 + --assert vu64/max == 2 + --assert vf32/max == 1.0 + --assert vf64/max == 1.0 + --assert vi08/maximum == 1 + vi08: #(i8! []) + vi16: #(i16! []) + vi32: #(i32! []) + vi64: #(i64! []) + vu08: #(u8! []) + vu16: #(u16! []) + vu32: #(u32! []) + vu64: #(u64! []) + vf32: #(f32! []) + vf64: #(f64! []) + --test-- "Find minimum of the empty vector" + --assert none? vi08/min + --assert none? vi16/min + --assert none? vi32/min + --assert none? vi64/min + --assert none? vu08/min + --assert none? vu16/min + --assert none? vu32/min + --assert none? vu64/min + --assert none? vf32/min + --assert none? vf64/min + --test-- "Find maximum of the empty vector" + --assert none? vi08/max + --assert none? vi16/max + --assert none? vi32/max + --assert none? vi64/max + --assert none? vu08/max + --assert none? vu16/max + --assert none? vu32/max + --assert none? vu64/max + --assert none? vf32/max + --assert none? vf64/max + ===start-group=== "VECTOR Compare" --test-- "compare vectors" ;@@ https://github.com/Oldes/Rebol-issues/issues/458