diff --git a/bench/Makefile b/bench/Makefile index 17c07ccc..e468cce5 100644 --- a/bench/Makefile +++ b/bench/Makefile @@ -6,7 +6,7 @@ N=4 all: benchmark bench-plain -benchmark: bench-mlib bench-mlib-mempool bench-stl bench-klib bench-qt bench-glib bench-libdynamic +benchmark: bench-mlib bench-mlib-mempool bench-stl bench-klib bench-qt bench-glib bench-libdynamic bench-sparsepp bench-mlib: $(CC) $(CFLAGS) $(CPPFLAGS) bench-mlib.c -o bench-mlib.exe @@ -86,6 +86,16 @@ bench-libdynamic0: @./bench-libdynamic.exe 41 @./bench-libdynamic.exe 50 +# SPARSEPP shall point to the directory where the headers are +bench-sparsepp: + if test -n "$${SPARSEPP}" ; then make bench-sparsepp0 ; else echo "Nothing to be done." ; fi + +bench-sparsepp0: + $(CXX) $(CFLAGS) $(CPPFLAGS) -I "$${SPARSEPP}" -I "$${SPARSEPP}/.." bench-sparsepp.cpp -o bench-sparsepp.exe + @./bench-sparsepp.exe 41 + @./bench-sparsepp.exe 42 + @./bench-sparsepp.exe 43 + bench-plain: $(CC) $(CFLAGS) $(CPPFLAGS) bench-plain-c.c -o bench-plain-c.exe @./bench-plain-c.exe @@ -94,6 +104,10 @@ bench-mempool: $(CXX) $(CFLAGS) $(CPPFLAGS) pool.cc `pkg-config --libs --cflags glib-2.0` -lboost_system -o bench-mempool.exe @./bench-mempool.exe +bench-maxdict: + $(CC) $(CFLAGS) $(CPPFLAGS) max-dict.c -o bench-max-dict.exe + @./bench-max-dict.exe + ############################################################################ clean: diff --git a/bench/bench-sparsepp.cpp b/bench/bench-sparsepp.cpp new file mode 100644 index 00000000..2c49a25f --- /dev/null +++ b/bench/bench-sparsepp.cpp @@ -0,0 +1,125 @@ +#define NDEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +using spp::sparse_hash_map; +using namespace std; + +#include "common.h" + +/********************************************************************************************/ + +static void +test_dict2(unsigned long n) +{ + sparse_hash_map dict; + + for (size_t i = 0; i < n; i++) { + dict[rand_get()] = rand_get(); + } + rand_init(); + unsigned int s = 0; + for (size_t i = 0; i < n; i++) { + sparse_hash_map::iterator it = dict.find(rand_get()); + if (it != dict.end()) + s += it->second; + } + g_result = s; +} + +/********************************************************************************************/ + +struct char_array_s { + char a[256]; + char_array_s () { a[0] = 0 ; } + char_array_s ( const char_array_s & other) { strcpy(a, other.a); } + bool operator==(const char_array_s &other) const { return strcmp(a, other.a) == 0; } +}; + +namespace std { + template <> struct hash { + std::size_t operator()(const char_array_s &k) const { + size_t hash = 0; + const char *s = k.a; + while (*s) hash = hash * 31421 + (*s++) + 6927; + return hash; + }; + }; +} + +static void +test_dict_big(unsigned long n) +{ + sparse_hash_map dict; + + for (size_t i = 0; i < n; i++) { + char_array_s s1, s2; + sprintf(s1.a, "%u", rand_get()); + sprintf(s2.a, "%u", rand_get()); + dict[s1] = s2; + } + rand_init(); + unsigned int s = 0; + for (size_t i = 0; i < n; i++) { + char_array_s s1; + sprintf(s1.a, "%u", rand_get()); + sparse_hash_map::iterator it = dict.find(s1); + if (it != dict.end()) + s ++; + } + g_result = s; +} + +/********************************************************************************************/ +static void +test_dict_str(unsigned long n) +{ + sparse_hash_map dict; + + for (size_t i = 0; i < n; i++) { + string s1 = static_cast( &(ostringstream() << rand_get()) )->str(); + string s2 = static_cast( &(ostringstream() << rand_get()) )->str(); + dict[s1] = s2; + } + rand_init(); + unsigned int s = 0; + for (size_t i = 0; i < n; i++) { + string s1 = static_cast( &(ostringstream() << rand_get()) )->str(); + sparse_hash_map::iterator it = dict.find(s1); + if (it != dict.end()) + s ++; + } + g_result = s; +} + +/********************************************************************************************/ + +int main(int argc, const char *argv[]) +{ + int n = (argc > 1) ? atoi(argv[1]) : 0; + if (n == 42) + test_function("Dict(u)time", 1000000, test_dict2); + if (n == 41) + test_function("DictB time", 1000000, test_dict_big); + if (n == 43) + test_function("DictS(u) time", 1000000, test_dict_str); + exit(0); +} diff --git a/bench/max-dict.c b/bench/max-dict.c new file mode 100644 index 00000000..a9990b91 --- /dev/null +++ b/bench/max-dict.c @@ -0,0 +1,71 @@ +/* + * MLIB - TEST module + * + * Copyright (c) 2017, Patrick Pelissier + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include +#include + +#define NDEBUG +#include "m-dict.h" + +static inline bool oor_equal_p(int64_t k, unsigned char n) +{ + return k == (int)-n-1; +} +static inline void oor_set(int64_t *k, unsigned char n) +{ + *k = (int)-n-1; +} + +DICT_OA_DEF2(int64, int64_t, M_OPEXTEND(M_DEFAULT_OPLIST, OOR_EQUAL(oor_equal_p), OOR_SET(oor_set M_IPTR)), int64_t, M_DEFAULT_OPLIST) + +static int64_t get_rand(void) +{ + int64_t n; + do { + n = (rand() * RAND_MAX + rand()) * RAND_MAX + rand(); + } while (n == -1 || n == -2); + return n; +} + +// Let's push value into the dict until the system abandons! +static void find_max(void) +{ + dict_int64_t dict; + dict_int64_init(dict); + size_t n = 0; + while (true) { + dict_int64_set_at (dict, get_rand(), get_rand()); + n++; + if ((n & ((1<<20)-1)) == 0) { + printf ("n=%lu\n", n); + } + } + dict_int64_clear(dict); +} + +int main() +{ + find_max(); +} diff --git a/example/ex-array04.c b/example/ex-array04.c index 72b64326..5f234f7a 100644 --- a/example/ex-array04.c +++ b/example/ex-array04.c @@ -6,11 +6,11 @@ ARRAY_DEF(mpz, mpz_t, M_CLASSIC_OPLIST(mpz)) ALGO_DEF(array_mpz, ARRAY_OPLIST(mpz, M_CLASSIC_OPLIST(mpz))) -static inline void my_mpz_inc(mpz_t d, const mpz_t a){ - mpz_add(d, d, a); +static inline void my_mpz_inc(mpz_t *d, const mpz_t a){ + mpz_add(*d, *d, a); } -static inline void my_mpz_sqr(mpz_t d, const mpz_t a){ - mpz_mul(d, a, a); +static inline void my_mpz_sqr(mpz_t *d, const mpz_t a){ + mpz_mul(*d, a, a); } int main(void) diff --git a/m-algo.h b/m-algo.h index ceb81e49..7d18b3d6 100644 --- a/m-algo.h +++ b/m-algo.h @@ -32,15 +32,18 @@ #include "m-core.h" -/* Define different kind of algorithms named 'name' over the container which oplist is 'cont_oplist' - USAGE: ALGO_DEF(afloat, LIST_OPLIST(float)) */ +/* Define different kind of algorithms named 'name' over the container + which oplist is 'cont_oplist' + 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) /* Map a function or a macro to all elements of a container. - USAGE: ALGO_MAP(container, containerOplist, func[, extra arguments of function]) */ + USAGE: + ALGO_MAP(container, containerOplist, func[, extra arguments of function]) */ #define ALGO_MAP(container, cont_oplist, ...) \ M_IF_NARGS_EQ1(__VA_ARGS__) \ (ALGOI_MAP(container, cont_oplist, __VA_ARGS__), \ @@ -48,7 +51,9 @@ /* Extract a subset of a container to fill in another container. - USAGE: ALGO_EXTRACT(containerDest, containerDestOplist, containerSrc, containerSrcOplist, func[, extra arguments of function]) */ + USAGE: + ALGO_EXTRACT(contDst, contDstOplist, contSrc, contSrcOplist, func + [, extra arguments of function]) */ // TODO: without 'func' parameter, extract all. #define ALGO_EXTRACT(contD, contDop, contS, contSop, ...) \ M_IF_NARGS_EQ1(__VA_ARGS__) \ @@ -57,7 +62,9 @@ /* Perform a Reduce operation over a container. - USAGE: ALGO_REDUCE(destVar, container, containerOplist, reduceFunc[, mapFunc[, extraParameters of map function]]) */ + USAGE: + ALGO_REDUCE(dstVar, container, contOplist, reduceFunc + [, mapFunc[, extraParameters of map function]]) */ #define ALGO_REDUCE(dest, cont, contOp, ...) \ M_IF_NARGS_EQ1(__VA_ARGS__) \ (ALGOI_REDUCE(dest, cont, contOp, __VA_ARGS__), \ @@ -67,7 +74,8 @@ /* Initialize & set a container with a variable array list. - USAGE: ALGO_INIT_VA(container, containerOplist, param1[, param2[, ...]]) */ + 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__); \ @@ -95,6 +103,7 @@ return !M_GET_IT_END_P cont_oplist (it); \ } \ \ + /* NOTE: If PREVIOUS & IT_LAST exist, then go backwards */ \ M_IF(M_AND(M_TEST_METHOD_P(PREVIOUS, cont_oplist), M_TEST_METHOD_P(IT_LAST, cont_oplist))) \ ( \ static inline void M_C(name, _find_last) (it_t it, container_t l, const type_t data) \ @@ -120,7 +129,7 @@ M_GET_IT_SET cont_oplist (it, it2) ; \ } \ } \ - ) \ + ) /* End of alternative of _find_last */ \ \ static inline size_t M_C(name, _count) (container_t l, const type_t data) \ { \ @@ -145,12 +154,12 @@ \ static inline void M_C(name, _reduce) (type_t *dest, \ container_t l, \ - void (*f)(type_t, type_t const) ) \ + void (*f)(type_t *, type_t const) ) \ { \ bool initDone = false; \ for M_EACH(item, l, cont_oplist) { \ if (initDone) \ - f(*dest, *item); \ + f(dest, *item); \ else { \ M_GET_SET type_oplist (*dest, *item); \ initDone = true; \ @@ -160,18 +169,18 @@ \ static inline void M_C(name, _map_reduce) (type_t *dest, \ container_t l, \ - void (*r)(type_t, type_t const), \ - void (*m)(type_t, type_t const) ) \ + void (*r)(type_t*, type_t const), \ + void (*m)(type_t*, type_t const) ) \ { \ bool initDone = false; \ type_t tmp; \ M_GET_INIT type_oplist (tmp); \ for M_EACH(item, l, cont_oplist) { \ if (initDone) { \ - m(tmp, *item); \ - r(*dest, tmp); \ + m(&tmp, *item); \ + r(dest, tmp); \ } else { \ - m(*dest, *item); \ + m(dest, *item); \ initDone = true; \ } \ } \ @@ -179,7 +188,7 @@ } \ \ M_IF_METHOD(CMP, type_oplist)( \ - static inline type_t *M_C(name, _min) (/*const*/ container_t l) \ + static inline type_t *M_C(name, _min) (const container_t l) \ { \ type_t *min = NULL; \ for M_EACH(cref, l, cont_oplist) { \ @@ -190,7 +199,7 @@ return min; \ } \ \ - static inline type_t *M_C(name, _max) (/*const*/ container_t l) \ + static inline type_t *M_C(name, _max) (const container_t l) \ { \ type_t *max = NULL; \ for M_EACH(cref, l, cont_oplist) { \ @@ -202,7 +211,7 @@ } \ \ static inline void M_C(name, _minmax) (type_t **min_p, type_t **max_p, \ - /*const*/ container_t l) \ + const container_t l) \ { \ type_t *min = NULL; \ type_t *max = NULL; \ @@ -218,7 +227,7 @@ *max_p = max; \ } \ \ - static inline bool M_C(name, _sort_p)(container_t l) \ + static inline bool M_C(name, _sort_p)(const container_t l) \ { \ it_t it1; \ it_t it2; \ @@ -462,7 +471,7 @@ #define ALGOI_REDUCE_OR(a,b) ((a) |= (b)) #define ALGOI_REDUCE_SUM(a,b) ((a) += (b)) -/* Get function pointer. +/* Return the method associated to a reduce operation. It returns the special function handler if function is and, or, sum or add. Otherwise it returns the original function */ #define ALGOI_REDUCE_FUNC(reduceFunc) \ diff --git a/m-buffer.h b/m-buffer.h index c015fe47..25254eb3 100644 --- a/m-buffer.h +++ b/m-buffer.h @@ -87,8 +87,9 @@ M_C3(buffer_, name, _init)(buffer_t v, size_t size) \ return; \ } \ if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \ - for(size_t i = 0; i < size; i++) \ + for(size_t i = 0; i < size; i++) { \ M_GET_INIT oplist(v->data[i]); \ + } \ } \ } \ \ @@ -96,8 +97,9 @@ M_C3(buffer_, name, _init)(buffer_t v, size_t size) \ M_C3(bufferi_, name, _clear_obj)(buffer_t v) \ { \ if (!BUFFERI_POLICY_P((policy), BUFFER_PUSH_INIT_POP_MOVE)) { \ - for(size_t i = 0; i < BUFFERI_SIZE(m_size); i++) \ + for(size_t i = 0; i < BUFFERI_SIZE(m_size); i++) { \ M_GET_CLEAR oplist(v->data[i]); \ + } \ } else { \ size_t i = BUFFERI_POLICY_P((policy), BUFFER_STACK) ? 0 : v->idx_cons; \ while (i != v->idx_prod) { \ @@ -140,19 +142,26 @@ M_C3(buffer_, name, _init)(buffer_t v, size_t size) \ } \ \ static inline bool \ - M_C3(buffer_, name, _empty_p)(buffer_t v) \ + M_C3(buffer_, name, _empty_p)(const buffer_t v) \ { \ assert(v->number <= BUFFERI_SIZE(m_size)); \ return v->number == 0; \ } \ \ static inline bool \ - M_C3(buffer_, name, _full_p)(buffer_t v) \ + M_C3(buffer_, name, _full_p)(const buffer_t v) \ { \ assert(v->number <= BUFFERI_SIZE(m_size)); \ return v->number == BUFFERI_SIZE(m_size); \ } \ \ + static inline size_t \ + M_C3(buffer_, name, _size)(const buffer_t v) \ + { \ + assert(v->number <= BUFFERI_SIZE(m_size)); \ + return v->number; \ + } \ + \ static inline bool \ M_C3(buffer_, name, _push)(buffer_t v, type const data) \ { \ diff --git a/m-core.h b/m-core.h index e6fae4d4..67322775 100644 --- a/m-core.h +++ b/m-core.h @@ -667,6 +667,22 @@ static inline uint32_t m_core_rotl32a (uint32_t x, uint32_t n) return (x<>(32-n)); } +/* Round to the next highest power of 2. + See https://web.archive.org/web/20160703165415/https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 +*/ +static inline uint64_t m_core_roundpow2(uint64_t v) +{ + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v |= v >> 32; + v++; + return v; +} + /* Implement FNV1A Jesteress Hash (very similar to FNV1A Meiyan Hash) See http://www.sanmayce.com/Fastest_Hash/ and https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash @@ -1063,8 +1079,8 @@ m_core_hash (const void *str, size_t length) #include #include #define M_MEMORY_FULL(size) do { \ - fprintf(stderr, "ERROR: Can not allocate memory (%lu bytes).\n", \ - (unsigned long) size); \ + fprintf(stderr, "ERROR(M*LIB): Can not allocate memory in function %s of file %s:%d (%lu bytes).\n", \ + __func__, __FILE__, __LINE__, (unsigned long) size); \ abort(); \ } while (0) #endif diff --git a/m-dict.h b/m-dict.h index 808847d0..cea1b859 100644 --- a/m-dict.h +++ b/m-dict.h @@ -693,7 +693,7 @@ typedef enum { ) \ \ static inline void \ - M_C3(dicti_,name,_resize_up)(dict_t h, size_t newSize) \ + M_C3(dicti_,name,_resize_up)(dict_t h, size_t newSize, bool updateLimit) \ { \ size_t oldSize = h->mask+1; \ assert (newSize >= oldSize); \ @@ -713,6 +713,8 @@ typedef enum { \ /* Then let's rehash all the entries in their **exact** position. \ If we can't, let's put them in the 'tmp' array. \ + It has been measured that the size of this 'tmp' array is \ + around 6% of the size of updated dictionnary. \ NOTE: This should be much cache friendly than typical hash code */ \ M_C3(array_dicti_,name,_t) tmp; \ M_C3(array_dicti_,name,_init)(tmp); \ @@ -758,10 +760,11 @@ typedef enum { M_C3(array_dicti_,name,_clear) (tmp); \ h->mask = newSize-1; \ h->count_delete = h->count; \ - M_C3(dicti_,name,_limit)(h, newSize); \ + if (updateLimit == true) { \ + M_C3(dicti_,name,_limit)(h, newSize); \ + } \ h->data = data; \ M_IF_DEBUG (assert (M_C3(dicti_,name,_control_after_resize)(h));) \ - assert (h->lower_limit < h->count && h->count < h->upper_limit); \ DICTI_OA_CONTRACT(h); \ } \ \ @@ -807,7 +810,7 @@ typedef enum { if (M_UNLIKELY (dict->count_delete >= dict->upper_limit)) { \ size_t newSize = dict->mask+1; \ if (dict->count > (dict->mask / 2)) newSize += newSize; \ - M_C3(dicti_,name,_resize_up)(dict, newSize); \ + M_C3(dicti_,name,_resize_up)(dict, newSize, true); \ } \ DICTI_OA_CONTRACT(dict); \ } \ @@ -1155,6 +1158,21 @@ typedef enum { return &it->dict->data[i]; \ } \ \ + static inline void \ + M_C3(dict_,name,_reserve)(dict_t dict, size_t capacity) \ + { \ + DICTI_OA_CONTRACT(dict); \ + size_t size; \ + /* Get the size which will allow to fit this capacity */ \ + size = m_core_roundpow2 (capacity * (1.0 / coeff_up)); \ + assert (M_POWEROF2_P(size)); \ + if (size > dict->mask+1) { \ + dict->upper_limit = (size_t) (size * coeff_up) - 1; \ + M_C3(dicti_,name,_resize_up)(dict, size, false); \ + } \ + DICTI_OA_CONTRACT(dict); \ + } \ + \ DICTI_DEF2_FUNC_ADDITIONAL(name, key_type, key_oplist, value_type, value_oplist, 0, dict_t, dict_it_t) diff --git a/m-i-list.h b/m-i-list.h index 9a161b91..7b1966ae 100644 --- a/m-i-list.h +++ b/m-i-list.h @@ -257,7 +257,7 @@ typedef struct ilist_head_s { M_C3(ilist_, name, _last_p)(const list_it_t it) \ { \ assert (it != NULL); \ - return it->next == it->head; \ + return it->next == it->head || it->current == it->head; \ } \ \ static inline void \ diff --git a/m-shared.h b/m-shared.h index 28bf2cf6..9e8903d7 100644 --- a/m-shared.h +++ b/m-shared.h @@ -195,7 +195,7 @@ { \ SHAREDI_CONTRACT(dest); \ SHAREDI_CONTRACT(shared); \ - assert (dest != shared); \ + assert (dest != shared); \ M_C3(shared_, name, _clear)(dest); \ M_C3(shared_, name, _init_move)(dest, shared); \ } \ @@ -206,11 +206,20 @@ { \ SHAREDI_CONTRACT(p1); \ SHAREDI_CONTRACT(p2); \ - M_SWAP (struct M_C3(shared_, name, _s)*, *p1, *p2); \ + M_SWAP (struct M_C3(shared_, name, _s)*, *p1, *p2); \ SHAREDI_CONTRACT(p1); \ SHAREDI_CONTRACT(p2); \ } \ \ + static inline bool \ + M_C3(shared_, name, _equal_p)(const M_C3(shared_, name, _t) p1, \ + const M_C3(shared_, name, _t) p2) \ + { \ + SHAREDI_CONTRACT(p1); \ + SHAREDI_CONTRACT(p2); \ + return *p1 == *p2; \ + } \ + \ static inline const type * \ M_C3(shared_, name, _cref)(const M_C3(shared_, name, _t) shared) \ { \ diff --git a/tests/coverage.h b/tests/coverage.h index 965f7f75..2a3173e0 100644 --- a/tests/coverage.h +++ b/tests/coverage.h @@ -53,6 +53,7 @@ #undef LIST_CONTRACT #undef DICTI_CONTRACT #undef DICTI_OA_CONTRACT +#undef SHAREDI_CONTRACT #else /* For normal builds, empty macros which does nothing */ #define START_COVERAGE diff --git a/tests/test-malgo.c b/tests/test-malgo.c index d5d00106..2ccfc2c4 100644 --- a/tests/test-malgo.c +++ b/tests/test-malgo.c @@ -23,6 +23,18 @@ static void g_f(int n) g_count++; } +static void func_map(int *d, int n) +{ + assert (g_min <= n && n <= g_max); + g_count++; + *d = n * n; +} + +static void func_reduce(int *d, int n) +{ + *d += n; +} + static void test_list(void) { list_int_t l; @@ -107,7 +119,16 @@ static void test_array(void) algo_array_map(l, g_f); assert(g_count == 101); - // FIXME: reduce functions don't have the right prototype to work with integers as the 1st argument is an int instead of a int* + int n; + algo_array_reduce(&n, l, func_reduce); + assert(n == 100*99/2+17); + + g_min = 0; + g_max = 99; + g_count = 0; + algo_array_map_reduce(&n, l, func_reduce, func_map); + assert(g_count == 101); + assert(n == (328350 + 17*17)); int *min, *max; assert (*algo_array_min(l) == 0); diff --git a/tests/test-mbuffer.c b/tests/test-mbuffer.c index 6b052a1a..f3506fef 100644 --- a/tests/test-mbuffer.c +++ b/tests/test-mbuffer.c @@ -22,8 +22,11 @@ */ #include "m-buffer.h" +#include "coverage.h" +START_COVERAGE // Define a fixed queue of unsigned int BUFFER_DEF(uint, unsigned int, 10, BUFFER_QUEUE|BUFFER_BLOCKING) +END_COVERAGE // Define a variable stack of float BUFFER_DEF(floats, float, 0, BUFFER_STACK|BUFFER_BLOCKING) @@ -71,6 +74,33 @@ static void test_global(void) m_thread_join(idx_p[i]); m_thread_join(idx_c[i]); } + assert (buffer_uint_empty_p(g_buff)); + assert (!buffer_uint_full_p(g_buff)); + assert (buffer_uint_size(g_buff) == 0); + + buffer_uint_clean(g_buff); + assert (buffer_uint_empty_p(g_buff)); + assert (!buffer_uint_full_p(g_buff)); + assert (buffer_uint_size(g_buff) == 0); + + for(unsigned int i = 0; i < 5;i++) + buffer_uint_push(g_buff, i); + + assert (!buffer_uint_empty_p(g_buff)); + assert (!buffer_uint_full_p(g_buff)); + assert (buffer_uint_size(g_buff) == 5); + + for(unsigned int i = 0; i < 5;i++) + buffer_uint_push(g_buff, i); + + assert (!buffer_uint_empty_p(g_buff)); + assert (buffer_uint_full_p(g_buff)); + assert (buffer_uint_size(g_buff) == 10); + + buffer_uint_clean(g_buff); + assert (buffer_uint_empty_p(g_buff)); + assert (!buffer_uint_full_p(g_buff)); + assert (buffer_uint_size(g_buff) == 0); buffer_uint_clear(g_buff); } diff --git a/tests/test-mdict.c b/tests/test-mdict.c index 91115cf3..62915f99 100644 --- a/tests/test-mdict.c +++ b/tests/test-mdict.c @@ -369,6 +369,15 @@ static void test_it_oa(void) assert (!dict_oa_int_it_equal_p(it2, it)); dict_oa_int_next(it2); assert (dict_oa_int_it_equal_p(it2, it)); + + s = 0; + for(dict_oa_int_it_last(it, d1); !dict_oa_int_end_p(it); dict_oa_int_previous(it)) { + dict_pair_oa_int_t *pair = dict_oa_int_ref(it); + assert (pair->key >= 0 && pair->key < 200); + assert (pair->value == pair->key + 1); + s++; + } + assert (s == 100); } } diff --git a/tests/test-milist.c b/tests/test-milist.c index e5014af2..5ad5f864 100644 --- a/tests/test-milist.c +++ b/tests/test-milist.c @@ -62,6 +62,24 @@ static void test(void) assert (n == item->n); n++; } + assert (n == 4); + ilist_it_tname_t it1, it2; + ilist_tname_it_last(it1, list); + assert (!ilist_tname_end_p(it1)); + assert (ilist_tname_last_p(it1)); + ilist_tname_it_end(it2, list); + assert (ilist_tname_end_p(it2)); + assert (ilist_tname_last_p(it2)); + assert (!ilist_tname_it_equal_p(it1, it2)); + for(ilist_tname_it_set(it2, it1) ; !ilist_tname_end_p(it2) ; ilist_tname_previous(it2)) { + const test_t *item = ilist_tname_cref(it2); + n--; + assert (n == item->n); + } + assert (n == 1); + ilist_tname_it_set(it2, it1); + assert (ilist_tname_it_equal_p(it1, it2)); + for M_EACH(item, list, ILIST_OPLIST(tname)) { if (item->n == 2) ilist_tname_unlink(item); diff --git a/tests/test-mshared.c b/tests/test-mshared.c index 30dcf156..f9fd9500 100644 --- a/tests/test-mshared.c +++ b/tests/test-mshared.c @@ -28,8 +28,8 @@ #include "coverage.h" START_COVERAGE SHARED_PTR_DEF(int, int) -SHARED_PTR_DEF(mpz, mpz_t, M_CLASSIC_OPLIST(mpz)) END_COVERAGE +SHARED_PTR_DEF(mpz, mpz_t, M_CLASSIC_OPLIST(mpz)) static int f(const shared_int_t p) { @@ -87,7 +87,22 @@ int main(void) shared_int_init_new(p1); assert(!shared_int_NULL_p(p1)); + *shared_int_ref(p1) = 1; + shared_int_init_new(p2); + assert(!shared_int_NULL_p(p2)); + *shared_int_ref(p2) = 2; + assert(!shared_int_equal_p(p1, p2)); + assert (*shared_int_cref(p1) == 1); + assert (*shared_int_cref(p2) == 2); + shared_int_swap(p1, p2); + assert (*shared_int_cref(p1) == 2); + assert (*shared_int_cref(p2) == 1); + shared_int_set(p1, p2); + assert(shared_int_equal_p(p1, p2)); + assert (*shared_int_cref(p1) == 1); + assert (*shared_int_cref(p2) == 1); shared_int_clear(p1); - + shared_int_clear(p2); + exit(0); }