From fe574434334d54bb59e83d2d829e681b5ceb153b Mon Sep 17 00:00:00 2001 From: Leonardo Date: Sun, 14 Apr 2019 20:29:48 -0300 Subject: [PATCH] Added contains test and benchmark and updated example and tests --- benchmarks/benchmark.c | 68 +++++++++------ examples/list/string.c | 46 ++++++++++- tests/contains.c | 184 +++++++++++++++++++++++++++++++++++++++++ tests/foreach.c | 2 +- tests/iterators.c | 2 +- 5 files changed, 272 insertions(+), 30 deletions(-) create mode 100644 tests/contains.c diff --git a/benchmarks/benchmark.c b/benchmarks/benchmark.c index 30c3b54..f8293ae 100644 --- a/benchmarks/benchmark.c +++ b/benchmarks/benchmark.c @@ -68,8 +68,8 @@ COLLECTION_GENERATE(TREEMAP, PUBLIC, tm, tmap, /* FMOD */, int, int) COLLECTION_GENERATE(HASHSET, PUBLIC, hs, hset, /* FMOD */, /* K */, int) COLLECTION_GENERATE(HASHMAP, PUBLIC, hm, hmap, /* FMOD */, int, int) -#define BENCHMARK(NAME, PFX, sname, initfunc, insertbody, removebody, iternext) \ - void NAME##_io_benchmark(int *array) \ +#define BENCHMARK(NAME, PFX, sname, initfunc, insertbody, removebody, iternext, searchbody) \ + void NAME##_io_benchmark(int *array, size_t s) \ { \ printf("+------------------------------------------------------------ %10s\n", #NAME); \ timer_t timer; \ @@ -80,7 +80,7 @@ COLLECTION_GENERATE(HASHMAP, PUBLIC, hm, hmap, /* FMOD */, int, int) \ TIMER_START(timer) \ \ - for (int i = 0; i < 10000000; i++) \ + for (size_t i = 0; i < 10000000; i++) \ { \ insertbody; \ } \ @@ -93,6 +93,19 @@ COLLECTION_GENERATE(HASHMAP, PUBLIC, hm, hmap, /* FMOD */, int, int) \ printf(" INPUT %10s TOOK %8.0lf milliseconds for %8lu elements\n", #NAME, timer.result, s1); \ \ + TIMER_START(timer) \ + \ + for (size_t i = 0; i < s; i++) \ + { \ + searchbody; \ + } \ + \ + TIMER_STOP(timer) \ + \ + TIMER_CALC(timer) \ + \ + printf(" SEARCH %10s TOOK %8.0lf milliseconds for %8lu elements\n", #NAME, timer.result, s); \ + \ sname##_iter iter; \ \ TIMER_START(timer) \ @@ -110,7 +123,7 @@ COLLECTION_GENERATE(HASHMAP, PUBLIC, hm, hmap, /* FMOD */, int, int) \ TIMER_START(timer); \ \ - for (int i = 0; i < 10000000; i++) \ + for (size_t i = 0; i < 10000000; i++) \ { \ removebody; \ } \ @@ -130,19 +143,24 @@ COLLECTION_GENERATE(HASHMAP, PUBLIC, hm, hmap, /* FMOD */, int, int) printf("+------------------------------------------------------------ %10s\n\n", #NAME); \ } -BENCHMARK(DEQUE, d, deque, d_new(10000000), d_push_back(collection, array[i]), d_pop_back(collection), d_iter_next(&iter, &k, &j)) -BENCHMARK(HASHMAP, hm, hmap, hm_new(10000000, 0.8, intcmp, inthash), hm_insert(collection, array[i], array[i]), hm_remove(collection, array[i], &r), hm_iter_next(&iter, &k, &v, &j)) -BENCHMARK(HASHSET, hs, hset, hs_new(10000000, 0.8, intcmp, inthash), hs_insert(collection, array[i]), hs_remove(collection, array[i]), hs_iter_next(&iter, &v, &j)) -BENCHMARK(HEAP, h, heap, h_new(10000000, MaxHeap, intcmp), h_insert(collection, array[i]), h_remove(collection, &r), h_iter_next(&iter, &v, &j)) -BENCHMARK(LINKEDLIST, ll, linked, ll_new(), ll_push_back(collection, array[i]), ll_pop_back(collection), ll_iter_next(&iter, &v, &j)) -BENCHMARK(LIST, l, list, l_new(10000000), l_push_back(collection, array[i]), l_pop_back(collection), l_iter_next(&iter, &v, &j)) -BENCHMARK(QUEUE, q, queue, q_new(10000000), q_enqueue(collection, array[i]), q_dequeue(collection), q_iter_next(&iter, &v, &j)) -BENCHMARK(STACK, s, stack, s_new(10000000), s_push(collection, array[i]), s_pop(collection), s_iter_next(&iter, &v, &j)) -BENCHMARK(TREEMAP, tm, tmap, tm_new(intcmp), tm_insert(collection, array[i], array[i]), tm_remove(collection, array[i], &r), tm_iter_next(&iter, &k, &v, &j)) -BENCHMARK(TREESET, ts, tset, ts_new(intcmp), ts_insert(collection, array[i]), ts_remove(collection, array[i]), ts_iter_next(&iter, &v, &j)) +BENCHMARK(DEQUE, d, deque, d_new(10000000), d_push_back(collection, array[i]), d_pop_back(collection), d_iter_next(&iter, &k, &j), d_contains(collection, array[i], intcmp)) +BENCHMARK(HASHMAP, hm, hmap, hm_new(10000000, 0.8, intcmp, inthash), hm_insert(collection, array[i], array[i]), hm_remove(collection, array[i], &r), hm_iter_next(&iter, &k, &v, &j), hm_contains(collection, array[i])) +BENCHMARK(HASHSET, hs, hset, hs_new(10000000, 0.8, intcmp, inthash), hs_insert(collection, array[i]), hs_remove(collection, array[i]), hs_iter_next(&iter, &v, &j), hs_contains(collection, array[i])) +BENCHMARK(HEAP, h, heap, h_new(10000000, MinHeap, intcmp), h_insert(collection, array[i]), h_remove(collection, &r), h_iter_next(&iter, &v, &j), h_contains(collection, array[i])) +BENCHMARK(LINKEDLIST, ll, linked, ll_new(), ll_push_back(collection, array[i]), ll_pop_back(collection), ll_iter_next(&iter, &v, &j), ll_contains(collection, array[i], intcmp)) +BENCHMARK(LIST, l, list, l_new(10000000), l_push_back(collection, array[i]), l_pop_back(collection), l_iter_next(&iter, &v, &j), l_contains(collection, array[i], intcmp)) +BENCHMARK(QUEUE, q, queue, q_new(10000000), q_enqueue(collection, array[i]), q_dequeue(collection), q_iter_next(&iter, &v, &j), q_contains(collection, array[i], intcmp)) +BENCHMARK(STACK, s, stack, s_new(10000000), s_push(collection, array[i]), s_pop(collection), s_iter_next(&iter, &v, &j), s_contains(collection, array[i], intcmp)) +BENCHMARK(TREEMAP, tm, tmap, tm_new(intcmp), tm_insert(collection, array[i], array[i]), tm_remove(collection, array[i], &r), tm_iter_next(&iter, &k, &v, &j), tm_contains(collection, array[i])) +BENCHMARK(TREESET, ts, tset, ts_new(intcmp), ts_insert(collection, array[i]), ts_remove(collection, array[i]), ts_iter_next(&iter, &v, &j), ts_contains(collection, array[i])) int main(void) { + // If you run this benchmark more than once in the same computer (as long + // as the rand() implementation is the same) the contents of the array will + // always be shuffled the same way. + srand(3111221); + int *array = malloc(10000000 * sizeof(int)); if (!array) @@ -156,16 +174,18 @@ int main(void) shuffle(array); - DEQUE_io_benchmark(array); - HASHMAP_io_benchmark(array); - HASHSET_io_benchmark(array); - HEAP_io_benchmark(array); - LINKEDLIST_io_benchmark(array); - LIST_io_benchmark(array); - QUEUE_io_benchmark(array); - STACK_io_benchmark(array); - TREEMAP_io_benchmark(array); - TREESET_io_benchmark(array); + // Linear containers have to search for 10000 elements and non-linear (hash + // and tree) have to search for all elements. + DEQUE_io_benchmark(array, 10000); + HASHMAP_io_benchmark(array, 10000000); + HASHSET_io_benchmark(array, 10000000); + HEAP_io_benchmark(array, 10000); + LINKEDLIST_io_benchmark(array, 10000); + LIST_io_benchmark(array, 10000); + QUEUE_io_benchmark(array, 10000); + STACK_io_benchmark(array, 10000); + TREEMAP_io_benchmark(array, 10000000); + TREESET_io_benchmark(array, 10000000); free(array); diff --git a/examples/list/string.c b/examples/list/string.c index 022cd90..5c76ef8 100644 --- a/examples/list/string.c +++ b/examples/list/string.c @@ -7,9 +7,9 @@ * Leonardo Vencovsky (https://github.com/LeoVen) * */ +#include "list.h" #include #include -#include "list.h" LIST_GENERATE(str, string, /* FMOD */, char) @@ -46,7 +46,7 @@ int main(int argc, char const *argv[]) putchar(result); } - printf("\n"); + printf("\n\n"); // You can also print it reversed for (str_iter_toend(&iter); !str_iter_start(&iter);) @@ -55,7 +55,7 @@ int main(int argc, char const *argv[]) putchar(result); } - printf("\n"); + printf("\n\n"); // Now remove the first letter supposing we don't know where it starts for (size_t i = 0; i < str_count(my_str); i++) @@ -79,7 +79,45 @@ int main(int argc, char const *argv[]) putchar(result); } - printf("\nString length: %lu\n", str_count(my_str)); + printf("\nString length: %lu\n\n", str_count(my_str)); + + // Remove last word: + for (size_t i = str_count(my_str) - 1; i > 0; i--) + { + // Find first white space + if (str_get(my_str, i) == ' ') + { + index = i; + break; + } + } + + // Extract last word + string *str_out = str_extract(my_str, index, str_count(my_str) - 1); + + // Pop white space + str_pop_front(str_out); + + if (!str_out) + printf("Could not extract string"); + else + { + for (str_iter_new(&iter, my_str); !str_iter_end(&iter);) + { + str_iter_next(&iter, &result, &index); + putchar(result); + } + printf("\nString length: %lu\n\n", str_count(my_str)); + for (str_iter_new(&iter, str_out); !str_iter_end(&iter);) + { + str_iter_next(&iter, &result, &index); + putchar(result); + } + printf("\nString length: %lu\n", str_count(str_out)); + } + + str_free(my_str); + str_free(str_out); return 0; } diff --git a/tests/contains.c b/tests/contains.c new file mode 100644 index 0000000..d48a235 --- /dev/null +++ b/tests/contains.c @@ -0,0 +1,184 @@ +#include "../src/macro_collections.h" +#include +#include +#include + +int intcmp(int a, int b) +{ + return (a > b) - (a < b); +} + +size_t inthash(int t) +{ + size_t a = t; + a += ~(a << 15); + a ^= (a >> 10); + a += (a << 3); + a ^= (a >> 6); + a += ~(a << 11); + a ^= (a >> 16); + return a; +} + +COLLECTION_GENERATE(LIST, PUBLIC, l, list, /* FMOD */, /* K */, int) +COLLECTION_GENERATE(STACK, PUBLIC, s, stack, /* FMOD */, /* K */, int) +COLLECTION_GENERATE(QUEUE, PUBLIC, q, queue, /* FMOD */, /* K */, int) +COLLECTION_GENERATE(DEQUE, PUBLIC, d, deque, /* FMOD */, /* K */, int) +COLLECTION_GENERATE(LINKEDLIST, PUBLIC, ll, linked, /* FMOD */, /* K */, int) +COLLECTION_GENERATE(HEAP, PUBLIC, h, heap, /* FMOD */, /* K */, int) +COLLECTION_GENERATE(TREESET, PUBLIC, ts, tset, /* FMOD */, /* K */, int) +COLLECTION_GENERATE(TREEMAP, PUBLIC, tm, tmap, /* FMOD */, int, int) +COLLECTION_GENERATE(HASHSET, PUBLIC, hs, hset, /* FMOD */, /* K */, int) +COLLECTION_GENERATE(HASHMAP, PUBLIC, hm, hmap, /* FMOD */, int, int) + +int main(int argc, char const *argv[]) +{ + list *l = l_new(1000); + stack *s = s_new(1000); + queue *q = q_new(1000); + deque *d = d_new(1000); + linked *ll = ll_new(); + heap *h = h_new(1000, MaxHeap, intcmp); + tset *ts = ts_new(intcmp); + tmap *tm = tm_new(intcmp); + hset *hs = hs_new(1000, 0.9, intcmp, inthash); + hmap *hm = hm_new(1000, 0.9, intcmp, inthash); + + bool a[10] = {false, false, false, false, false, false, false, false, false, false}, + b[10] = {false, false, false, false, false, false, false, false, false, false}, + c[10] = {true, true, true, true, true, true, true, true, true, true}; + + b[0] = d_contains(d, 1, intcmp); + b[1] = hm_contains(hm, 1); + b[2] = hs_contains(hs, 1); + b[3] = h_contains(h, 1); + b[4] = ll_contains(ll, 1, intcmp); + b[5] = l_contains(l, 1, intcmp); + b[6] = q_contains(q, 1, intcmp); + b[7] = s_contains(s, 1, intcmp); + b[8] = tm_contains(tm, 1); + b[9] = ts_contains(ts, 1); + + for (int i = 1; i < 1001; i++) + { + if (i % 2 == 0) + { + d_push_front(d, i); + l_push_front(l, i); + ll_push_front(ll, i); + } + else + { + d_push_back(d, i); + l_push_back(l, i); + ll_push_back(ll, i); + } + + s_push(s, i); + q_enqueue(q, i); + h_insert(h, i); + ts_insert(ts, i); + tm_insert(tm, i, i); + hs_insert(hs, i); + hm_insert(hm, i, i); + } + + for (int i = 1; i < 1001; i++) + { + c[0] = c[0] && d_contains(d, i, intcmp); + c[1] = c[1] && hm_contains(hm, i); + c[2] = c[2] && hs_contains(hs, i); + c[3] = c[3] && h_contains(h, i); + c[4] = c[4] && ll_contains(ll, i, intcmp); + c[5] = c[5] && l_contains(l, i, intcmp); + c[6] = c[6] && q_contains(q, i, intcmp); + c[7] = c[7] && s_contains(s, i, intcmp); + c[8] = c[8] && tm_contains(tm, i); + c[9] = c[9] && ts_contains(ts, i); + } + + for (int i = -500; i < 1; i++) + { + a[0] = a[0] || d_contains(d, i, intcmp); + a[1] = a[1] || hm_contains(hm, i); + a[2] = a[2] || hs_contains(hs, i); + a[3] = a[3] || h_contains(h, i); + a[4] = a[4] || ll_contains(ll, i, intcmp); + a[5] = a[5] || l_contains(l, i, intcmp); + a[6] = a[6] || q_contains(q, i, intcmp); + a[7] = a[7] || s_contains(s, i, intcmp); + a[8] = a[8] || tm_contains(tm, i); + a[9] = a[9] || ts_contains(ts, i); + } + + for (int i = 1001; i < 1500; i++) + { + a[0] = a[0] || d_contains(d, i, intcmp); + a[1] = a[1] || hm_contains(hm, i); + a[2] = a[2] || hs_contains(hs, i); + a[3] = a[3] || h_contains(h, i); + a[4] = a[4] || ll_contains(ll, i, intcmp); + a[5] = a[5] || l_contains(l, i, intcmp); + a[6] = a[6] || q_contains(q, i, intcmp); + a[7] = a[7] || s_contains(s, i, intcmp); + a[8] = a[8] || tm_contains(tm, i); + a[9] = a[9] || ts_contains(ts, i); + } + + d_clear(d); + hm_clear(hm); + hs_clear(hs); + h_clear(h); + ll_clear(ll); + l_clear(l); + q_clear(q); + s_clear(s); + tm_clear(tm); + ts_clear(ts); + + b[0] = b[0] || d_contains(d, 1, intcmp); + b[1] = b[1] || hm_contains(hm, 1); + b[2] = b[2] || hs_contains(hs, 1); + b[3] = b[3] || h_contains(h, 1); + b[4] = b[4] || ll_contains(ll, 1, intcmp); + b[5] = b[5] || l_contains(l, 1, intcmp); + b[6] = b[6] || q_contains(q, 1, intcmp); + b[7] = b[7] || s_contains(s, 1, intcmp); + b[8] = b[8] || tm_contains(tm, 1); + b[9] = b[9] || ts_contains(ts, 1); + + printf("-------------------- CONTAINS --------------------\n"); + if (c[0] && !a[0] && !b[0]) + printf("%10s PASSED\n", "DEQUE"); + if (c[1] && !a[1] && !b[1]) + printf("%10s PASSED\n", "HASHMAP"); + if (c[2] && !a[2] && !b[2]) + printf("%10s PASSED\n", "HASHSET"); + if (c[3] && !a[3] && !b[3]) + printf("%10s PASSED\n", "HEAP"); + if (c[4] && !a[4] && !b[4]) + printf("%10s PASSED\n", "LINKEDLIST"); + if (c[5] && !a[5] && !b[5]) + printf("%10s PASSED\n", "LIST"); + if (c[6] && !a[6] && !b[6]) + printf("%10s PASSED\n", "QUEUE"); + if (c[7] && !a[7] && !b[7]) + printf("%10s PASSED\n", "STACK"); + if (c[8] && !a[8] && !b[8]) + printf("%10s PASSED\n", "TREEMAP"); + if (c[9] && !a[9] && !b[9]) + printf("%10s PASSED\n", "TREESET"); + + l_free(l); + ll_free(ll); + s_free(s); + q_free(q); + d_free(d); + h_free(h); + ts_free(ts); + tm_free(tm); + hs_free(hs); + hm_free(hm); + + return 0; +} diff --git a/tests/foreach.c b/tests/foreach.c index 6543687..4c11540 100644 --- a/tests/foreach.c +++ b/tests/foreach.c @@ -1,6 +1,6 @@ +#include "../src/macro_collections.h" #include #include -#include "../src/macro_collections.h" int intcmp(int a, int b) { diff --git a/tests/iterators.c b/tests/iterators.c index ef81c67..f231d28 100644 --- a/tests/iterators.c +++ b/tests/iterators.c @@ -1,6 +1,6 @@ +#include "../src/macro_collections.h" #include #include -#include "../src/macro_collections.h" int intcmp(int a, int b) {