diff --git a/m-algo.h b/m-algo.h index 51618cd9..f7ba0669 100644 --- a/m-algo.h +++ b/m-algo.h @@ -30,19 +30,18 @@ /* Define different kind of algorithms named 'name' over the container which oplist is 'cont_oplist' as static inline functions. USAGE: - ALGO_DEF(algogName, containerOplist) */ -#define ALGO_DEF(name, cont_oplist) \ - ALGOI_DEF(name, M_GET_TYPE cont_oplist, cont_oplist, \ - M_GET_SUBTYPE cont_oplist, M_GET_OPLIST cont_oplist, M_GET_IT_TYPE cont_oplist) + ALGO_DEF(algogName, containerOplist|type if oplist has been registered) */ +#define ALGO_DEF(name, cont_oplist) \ + ALGOI_DEF(name, M_GLOBAL_OPLIST(cont_oplist)) /* Map a function or a macro to all elements of a container. USAGE: ALGO_MAP(container, containerOplist, function[, extra arguments of function]) */ -#define ALGO_MAP(container, cont_oplist, ...) \ - M_IF_NARGS_EQ1(__VA_ARGS__) \ - (ALGOI_MAP(container, cont_oplist, __VA_ARGS__), \ - ALGOI_MAP_ARG(container, cont_oplist, __VA_ARGS__ )) +#define ALGO_MAP(container, cont_oplist, ...) \ + M_IF_NARGS_EQ1(__VA_ARGS__) \ + (ALGOI_MAP(container, M_GLOBAL_OPLIST(cont_oplist), __VA_ARGS__), \ + ALGOI_MAP_ARG(container, M_GLOBAL_OPLIST(cont_oplist), __VA_ARGS__ )) /* Extract a subset of a container to fill in another container. @@ -52,8 +51,8 @@ // TODO: without 'func' parameter, extract all. #define ALGO_EXTRACT(contD, contDop, contS, contSop, ...) \ M_IF_NARGS_EQ1(__VA_ARGS__) \ - (ALGOI_EXTRACT(contD, contDop, contS, contSop, __VA_ARGS__), \ - ALGOI_EXTRACT_ARG(contD, contDop, contS, contSop, __VA_ARGS__ )) + (ALGOI_EXTRACT(contD, M_GLOBAL_OPLIST(contDop), M_GLOBAL_OPLIST(contS), contSop, __VA_ARGS__), \ + ALGOI_EXTRACT_ARG(contD, M_GLOBAL_OPLIST(contDop), M_GLOBAL_OPLIST(contS), contSop, __VA_ARGS__ )) /* Perform a Reduce operation over a container. @@ -62,24 +61,34 @@ [, mapFunc[, extraParameters of map function]]) */ #define ALGO_REDUCE(dest, cont, contOp, ...) \ M_IF_NARGS_EQ1(__VA_ARGS__) \ - (ALGOI_REDUCE(dest, cont, contOp, __VA_ARGS__), \ + (ALGOI_REDUCE(dest, M_GLOBAL_OPLIST(cont), M_GLOBAL_OPLIST(contOp), __VA_ARGS__), \ M_IF_NARGS_EQ2(__VA_ARGS__) \ - (ALGOI_REDUCE_MAP(dest, cont, contOp, __VA_ARGS__), \ - ALGOI_REDUCE_MAP_ARG(dest, cont, contOp, __VA_ARGS__) ) ) + (ALGOI_REDUCE_MAP(dest, M_GLOBAL_OPLIST(cont), M_GLOBAL_OPLIST(contOp), __VA_ARGS__), \ + ALGOI_REDUCE_MAP_ARG(dest, M_GLOBAL_OPLIST(cont), M_GLOBAL_OPLIST(contOp), __VA_ARGS__) ) ) /* Initialize & set a container with a variable array list. USAGE: ALGO_INIT_VA(container, containerOplist, param1[, param2[, ...]]) */ -#define ALGO_INIT_VA(dest, contOp, ...) do { \ - M_GET_INIT contOp (dest); \ - M_MAP2(ALGOI_INIT_VA_FUNC, (dest, M_GET_PUSH contOp, ) , __VA_ARGS__); \ - } while (0) +#define ALGO_INIT_VA(dest, contOp, ...) \ + ALGO_INIT_VAI(dest, M_GLOBAL_OPLIST(contOp), __VA_ARGS__) + +/* Define, initialize, set & clear a container with a variable array list. + USAGE: + ALGO_LET_INIT_VA(container, containerOplist, param1[, param2[, ...]]) { + // Stuff with container + } */ +#define ALGO_LET_INIT_VA(dest, contOp, ...) \ + ALGO_LET_INIT_VAI(dest, M_GLOBAL_OPLIST(contOp), __VA_ARGS__) /********************************** INTERNAL ************************************/ -#define ALGOI_DEF(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ +#define ALGOI_DEF(name, cont_oplist) \ + ALGOI_DEF2(name, M_GET_TYPE cont_oplist, cont_oplist, \ + M_GET_SUBTYPE cont_oplist, M_GET_OPLIST cont_oplist, M_GET_IT_TYPE cont_oplist) + +#define ALGOI_DEF2(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ \ /* TODO: Add a specialization if container is sorted */ \ static inline void \ @@ -609,7 +618,18 @@ M_GET_CLEAR M_GET_OPLIST cont_oplist (m_tmp); \ } while (0) -#define ALGOI_INIT_VA_FUNC(d, a) \ - M_RET_ARG2 d (M_RET_ARG1 d, a) ; +#define ALGOI_INIT_VA_FUNC(d, a) \ + M_RET_ARG2 d (M_RET_ARG1 d, a) M_DEFERRED_COMMA + +#define ALGO_INIT_VAI(dest, contOp, ...) \ + (void)(M_GET_INIT contOp (dest) M_DEFERRED_COMMA \ + M_MAP2(ALGOI_INIT_VA_FUNC, (dest, M_GET_PUSH contOp, ) , __VA_ARGS__) \ + true) + +#define ALGO_LET_INIT_VAI(dest, contOp, ...) \ + for(bool cont = true; cont ; /* unused */) \ + for(M_GET_TYPE contOp dest; \ + cont && (ALGO_INIT_VAI (dest, contOp, __VA_ARGS__), true); \ + (M_GET_CLEAR contOp (dest), cont = false)) #endif diff --git a/tests/test-malgo.c b/tests/test-malgo.c index 08a4ccfd..6dfee98c 100644 --- a/tests/test-malgo.c +++ b/tests/test-malgo.c @@ -27,18 +27,21 @@ #include "test-obj.h" #include "m-algo.h" -// TODO: Test other containers? HASHMAP, RBTREE, B+TREE, Intrusive List +// TODO: Test other containers (Intrusive List) +// HASHMAP, RBTREE, B+TREE: Is this useful? ARRAY_DEF(array_int, int) +#define M_OPL_array_int_t() ARRAY_OPLIST(array_int) LIST_DEF(list_int, int) LIST_DEF(list_string, string_t, STRING_OPLIST) DEQUE_DEF(deque_obj, testobj_t, TESTOBJ_CMP_OPLIST) +#define M_OPL_deque_obj_t() DEQUE_OPLIST(deque_obj, TESTOBJ_CMP_OPLIST) #include "coverage.h" START_COVERAGE -ALGO_DEF(algo_array, ARRAY_OPLIST(array_int)) +ALGO_DEF(algo_array, array_int_t) ALGO_DEF(algo_list, LIST_OPLIST(list_int)) ALGO_DEF(algo_string, LIST_OPLIST(list_string, STRING_OPLIST)) -ALGO_DEF(algo_deque, DEQUE_OPLIST(deque_obj, TESTOBJ_CMP_OPLIST)) +ALGO_DEF(algo_deque, deque_obj_t) END_COVERAGE int g_min, g_max, g_count; @@ -137,6 +140,7 @@ static void test_array(void) #define f(x) assert((x) >= 0 && (x) < 100); ALGO_MAP(l, ARRAY_OPLIST(array_int), f); + ALGO_MAP(l, array_int_t, f); g_min = 0; g_max = 99; @@ -207,6 +211,12 @@ static void test_array(void) assert (algo_array_sort_dsc_p(l) == true); array_int_clear(l); + + ALGO_LET_INIT_VA(arr, array_int_t, 1, 5, 34) { + assert (array_int_size(arr) == 3); + assert (algo_array_sort_p(arr) == true); + assert (algo_array_sort_dsc_p(arr) == false); + } } static void test_string(void) @@ -255,6 +265,8 @@ static void test_extract(void) #define inc(d, c) (d) += (c) ALGO_REDUCE(dst, a, ARRAY_OPLIST(array_int), inc); assert (dst == 100*99/2-10*11/2); + ALGO_REDUCE(dst, a, array_int_t, inc); + assert (dst == 100*99/2-10*11/2); #define sqr(d, c) (d) = (c)*(c) ALGO_REDUCE(dst, a, ARRAY_OPLIST(array_int), inc, sqr); assert (dst == 327965);