From 85596c1a7aa3570c16dd17ce5b23f30d95f3166c Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Fri, 3 Mar 2017 21:30:38 +0100 Subject: [PATCH] Add ALGO_REDUCE macro --- m-algo.h | 73 +++++++++++++++++++++++++++++++++++++++------- tests/test-malgo.c | 12 ++++++++ 2 files changed, 75 insertions(+), 10 deletions(-) diff --git a/m-algo.h b/m-algo.h index 6e8a349f..0c11ff0c 100644 --- a/m-algo.h +++ b/m-algo.h @@ -46,6 +46,13 @@ (ALGOI_EXTRACT(contD, contDop, contS, contSop, __VA_ARGS__), \ ALGOI_EXTRACT_ARG(contD, contDop, contS, contSop, __VA_ARGS__ )) +#define ALGO_REDUCE(dest, cont, contOp, ...) \ + M_IF_NARGS_EQ1(__VA_ARGS__) \ + (ALGOI_REDUCE(dest, cont, 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__) ) ) + /********************************** INTERNAL ************************************/ #define ALGOI_DEF(name, container_t, cont_oplist, type_t, type_oplist, it_t) \ @@ -207,17 +214,19 @@ //TODO: const_iterator & CM_EACH missing... //TODO: Algorithm missing -// nth_element, reduce, find_last, find_if, count_if, ... +// nth_element, average, find_last, find_if, count_if, ... -#define ALGOI_MAP(container, cont_oplist, func) \ - for M_EACH(item, l, cont_oplist) { \ - func(*item); \ - } \ - -#define ALGOI_MAP_ARG(container, cont_oplist, func, ...) \ - for M_EACH(item, l, cont_oplist) { \ - func(__VA_ARGS__, *item); \ - } \ +#define ALGOI_MAP(container, cont_oplist, func) do { \ + for M_EACH(item, container, cont_oplist) { \ + func(*item); \ + } \ + } while (0) + +#define ALGOI_MAP_ARG(container, cont_oplist, func, ...) do { \ + for M_EACH(item, container, cont_oplist) { \ + func(__VA_ARGS__, *item); \ + } \ + } while (0) #define ALGOI_EXTRACT(contDst, contDstOplist, \ contSrc, contSrcOplist, \ @@ -241,4 +250,48 @@ M_IF_METHOD(REVERSE, contDstOplist) (M_GET_REVERSE contDstOplist (contDstOplist);, ) \ } while (0) +#define ALGOI_REDUCE(dest, cont, cont_oplist, reduceFunc) do { \ + bool m_init_done = false; \ + for M_EACH(item, cont, cont_oplist) { \ + if (m_init_done) { \ + reduceFunc(dest, *item); \ + } else { \ + M_GET_SET M_GET_OPLIST cont_oplist (dest, *item); \ + m_init_done = true; \ + } \ + } \ + } while (0) + +#define ALGOI_REDUCE_MAP(dest, cont, cont_oplist, reduceFunc, mapFunc) do { \ + bool m_init_done = false; \ + M_GET_SUBTYPE cont_oplist m_tmp; \ + M_GET_INIT M_GET_OPLIST cont_oplist (m_tmp); \ + for M_EACH(item, cont, cont_oplist) { \ + mapFunc(m_tmp, *item); \ + if (m_init_done) { \ + reduceFunc(dest, m_tmp); \ + } else { \ + M_GET_SET M_GET_OPLIST cont_oplist (dest, m_tmp); \ + m_init_done = true; \ + } \ + } \ + M_GET_CLEAR M_GET_OPLIST cont_oplist (m_tmp); \ + } while (0) + +#define ALGOI_REDUCE_MAP_ARG(dest, cont, cont_oplist, reduceFunc, mapFunc, ...) do { \ + bool m_init_done = false; \ + M_GET_SUBTYPE cont_oplist m_tmp; \ + M_GET_INIT M_GET_OPLIST cont_oplist (m_tmp); \ + for M_EACH(item, cont, cont_oplist) { \ + mapFunc(m_tmp, __VA_ARGS__, *item); \ + if (m_init_done) { \ + reduceFunc(dest, m_tmp); \ + } else { \ + M_GET_SET M_GET_OPLIST cont_oplist (dest, m_tmp); \ + m_init_done = true; \ + } \ + } \ + M_GET_CLEAR M_GET_OPLIST cont_oplist (m_tmp); \ + } while (0) + #endif diff --git a/tests/test-malgo.c b/tests/test-malgo.c index 3dbc4f39..6699599f 100644 --- a/tests/test-malgo.c +++ b/tests/test-malgo.c @@ -87,6 +87,18 @@ static void test_extract(void) #define cond2(c, d) ((d) > (c)) ALGO_EXTRACT(a, ARRAY_OPLIST(int), l, LIST_OPLIST(int), cond2, 10); assert(array_int_size(a) == 89); + + int dst = 0; +#define inc(d, c) (d) += (c) + ALGO_REDUCE(dst, a, ARRAY_OPLIST(int), inc); + assert (dst == 100*99/2-10*11/2); +#define sqr(d, c) (d) = (c)*(c) + ALGO_REDUCE(dst, a, ARRAY_OPLIST(int), inc, sqr); + assert (dst == 327965); +#define sqr2(d, f, c) (d) = (f) * (c) + ALGO_REDUCE(dst, a, ARRAY_OPLIST(int), inc, sqr2, 4); + assert (dst == (100*99/2-10*11/2) *4 ); + array_int_clear(a); list_int_clear(l); }