diff --git a/README.md b/README.md index f555b60..8ad0e6e 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,26 @@ * HashMap, TreeMap, MultiMap * Heaps * Heap, IntervalHeap +* Coming Soon + * BidiMap, SortedList + +| Collection | Abstract Data Type | Data Structure | Details | +| :--------------------------------: | :---------------------------------: | :-----------------------------: | :-----------------------------------: | +| BidiMap
_bidimap.h_ | Bidirectional Map | Two Hashtables | A bijection between two sets of unique keys and unique values `K <-> V` using two hashtables | +| Deque
_deque.h_ | Double-Ended Queue | Dynamic Circular Array | A circular array that allows `push` and `pop` on both ends (only) at constant time | +| HashMap
_hashmap.h_ | Map | Hashtable | A unique set of keys associated with a value `K -> V` with constant time look up using a hashtable with open addressing and robin hood hashing | +| HashSet
_hashset.h_ | Set | Hashtable | A unique set of values with constant time look up using a hashtable with open addressing and robin hood hashing | +| Heap
_heap.h_ | Priority Queue | Dynamic Array | A binary heap as a dynamic array as an implicit data structure | +| IntervalHeap
_intervalheap.h_ | Double-Ended Priority Queue | Custom Dynamic Array | A dynamic array of nodes, each hosting one value from the MinHeap and one from the MaxHeap | +| LinkedList
_linkedlist.h_ | List | Doubly-Linked List | A default doubly-linked list | +| List
_list.h_ | List | Dynamic Array | A dynamic array with `push` and `pop` anywhere on the array | +| MultiMap
_multimap.h_ | Multimap | Custom Hashtable | A mapping of multiple keys with one node per key using a hashtable with separate chaining | +| Multiset
_multiset.h_ | Multiset | Hashtable | A mapping of a value and its multiplicity using a hashtable with open addressing and robin hood hashing | +| Queue
_queue.h_ | FIFO | Dynamic Circular Array | A queue using a circular array with `enqueue` at the `back` index and `dequeue` at the `front` index | +| SortedList
_sortedlist.h_ | Sorted List | Sorted Dynamic Array | A lazily sorted dynamic array that is sorted only when necessary | +| Stack
_stack.h_ | FILO | Dynamic Array | A stack with push and pop at the end of a dynamic array | +| TreeMap
_treemap.h_ | Sorted Map | AVL Tree | A unique set of keys associated with a value `K -> V` using an AVL tree with `log(n)` look up and sorted iteration | +| TreeSet
_treeset.h_ | Sorted Set | AVL Tree | A unique set of keys using an AVL tree with `log(n)` look up and sorted iteration | ## Overall To-Do @@ -121,6 +141,18 @@ Or you can generate each part individually: * `CMC_GENERATE_SNAME_HEADER` - Generates all struct definitions and function definitions. * `CMC_GENERATE_SNAME_SOURCE` - Generates all function implementations. +### Parameters + +When including `macro_collections.h` in your source code you gain access to a macro called `CMC_COLLECTION_GENERATE` with the following parameters: + +* __C__ - Container name in uppercase (*LIST*, *LINKEDLIST*, *STACK*, *QUEUE*, *DEQUE*, *HEAP*, *TREESET*, *TREEMAP*, *HASHSET*, *HASHMAP*). +* __PFX__ - Functions prefix or namespace. +* __SNAME__ - Structure name (`typedef struct SNAME##_s SNAME`). +* __K__ - Key type. Only used in *HASHMAP*, *TREEMAP*, *MULTIMAP* and *BIDIMAP*; ignored by others. +* __V__ - Value type. Primary type for most collections, or value to be mapped by *HASHMAP*, *TREEMAP*, *MULTIMAP* and *BIDIMAP*. + +**In fact, all macros follow this pattern.** So whenever you see a macro with a bunch of parameters and you don't know what they are, you can check out the above list. + ### For Each There are 2 for-each macros: @@ -128,22 +160,6 @@ There are 2 for-each macros: * `CMC_FOR_EACH` - Starts at the start of the collection towards the end. * `CMC_FOR_EACH_REV` - Starts at the end of the collection towards the start. -Check out the documentation to know more. - -### Parameters - -When including `macro_collections.h` in your source code you gain access to a macro called `COLLECTION_GENERATE` with the following parameters: - -* __C__ - Container name in uppercase (*LIST*, *LINKEDLIST*, *STACK*, *QUEUE*, *DEQUE*, *HEAP*, *TREESET*, *TREEMAP*, *HASHSET*, *HASHMAP*). -* __PFX__ - Functions prefix or namespace. -* __SNAME__ - Structure name (`typedef struct SNAME##_s SNAME`). -* \*__K__ - Key type. Only used in *HASHMAP* and *TREEMAP*; ignored by others. -* __V__ - Value type. Primary type for most collections, or value to be mapped by *HASHMAP* and *TREEMAP*. - -\* Required only by *HASHMAP* and *TREEMAP* - -**In fact, all macros follow this pattern.** So whenever you see a macro with a bunch of parameters and you don't know what they are, you can check out the above list. - When including `foreach.h` in your source code you gain access to all for-each macros with the following parameters: * __PFX__ - Functions prefix or namespace. @@ -151,7 +167,7 @@ When including `foreach.h` in your source code you gain access to all for-each m * __TARGET__ - The variable name of the collection you wish to iterate over. * __BODY__ - Block of code. -Inside body you will have access to the iterator variable. With it you can use functions to access the key, value or index from the iterator. Checkout the documentation for more details. +Inside body you will have access to the iterator variable `iter`. With it you can use functions to access the key, value or index from the iterator. Checkout the documentation for more details.
diff --git a/benchmarks/benchmark.c b/benchmarks/benchmark.c index aada8bc..efc0b8a 100644 --- a/benchmarks/benchmark.c +++ b/benchmarks/benchmark.c @@ -59,20 +59,20 @@ void shuffle(int *array, mt_state_ptr st) } } -COLLECTION_GENERATE(DEQUE, d, deque, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(HASHMAP, hm, hmap, /* FMOD */, int, int) -COLLECTION_GENERATE(HASHSET, hs, hset, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(HEAP, h, heap, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(LIST, l, list, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(QUEUE, q, queue, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(STACK, s, stack, /* FMOD */, /* K */, int) -COLLECTION_GENERATE(TREEMAP, tm, tmap, /* FMOD */, int, int) -COLLECTION_GENERATE(TREESET, ts, tset, /* FMOD */, /* K */, int) +CMC_COLLECTION_GENERATE(DEQUE, d, deque, /* K */, int) +CMC_COLLECTION_GENERATE(HASHMAP, hm, hmap, int, int) +CMC_COLLECTION_GENERATE(HASHSET, hs, hset, /* K */, int) +CMC_COLLECTION_GENERATE(HEAP, h, heap, /* K */, int) +CMC_COLLECTION_GENERATE(LINKEDLIST, ll, linked, /* K */, int) +CMC_COLLECTION_GENERATE(LIST, l, list, /* K */, int) +CMC_COLLECTION_GENERATE(QUEUE, q, queue, /* K */, int) +CMC_COLLECTION_GENERATE(STACK, s, stack, /* K */, int) +CMC_COLLECTION_GENERATE(TREEMAP, tm, tmap, int, int) +CMC_COLLECTION_GENERATE(TREESET, ts, tset, /* K */, int) -COLLECTION_GENERATE(INTERVALHEAP, ih, iheap, , , int) -COLLECTION_GENERATE(MULTIMAP, mm, mmap, /* FMOD */, int, int) -COLLECTION_GENERATE(MULTISET, ms, mset, /* FMOD */, /* K */, int) +CMC_COLLECTION_GENERATE(INTERVALHEAP, ih, iheap, /* k */, int) +CMC_COLLECTION_GENERATE(MULTIMAP, mm, mmap, int, int) +CMC_COLLECTION_GENERATE(MULTISET, ms, mset, /* K */, int) #define BENCHMARK(NAME, PFX, sname, initfunc, insertbody, removebody, searchbody) \ void NAME##_io_benchmark(int *array, int *sarray, size_t s) \ @@ -85,17 +85,17 @@ COLLECTION_GENERATE(MULTISET, ms, mset, /* FMOD */, /* K */, int) \ sname *coll = initfunc; \ \ - timer_start(total); \ - timer_start(timer); \ + cmc_timer_start(total); \ + cmc_timer_start(timer); \ \ for (size_t i = 0; i < NTOTAL; i++) \ { \ insertbody; \ } \ \ - timer_stop(timer); \ + cmc_timer_stop(timer); \ \ - timer_calc(timer); \ + cmc_timer_calc(timer); \ \ size_t s1 = PFX##_count(coll); \ \ @@ -103,16 +103,16 @@ COLLECTION_GENERATE(MULTISET, ms, mset, /* FMOD */, /* K */, int) \ double input_time = timer.result; \ \ - timer_start(timer); \ + cmc_timer_start(timer); \ \ for (size_t i = 0; i < s; i++) \ { \ searchbody; \ } \ \ - timer_stop(timer); \ + cmc_timer_stop(timer); \ \ - timer_calc(timer); \ + cmc_timer_calc(timer); \ \ printf(" SEARCH %10s TOOK %8.0lf milliseconds for %8" PRIuMAX " elements\n", #NAME, timer.result, s); \ \ @@ -120,30 +120,30 @@ COLLECTION_GENERATE(MULTISET, ms, mset, /* FMOD */, /* K */, int) \ sname##_iter iter; \ \ - timer_start(timer); \ + cmc_timer_start(timer); \ \ for (PFX##_iter_init(&iter, coll); !PFX##_iter_end(&iter); PFX##_iter_next(&iter)) \ { \ } \ \ - timer_stop(timer); \ + cmc_timer_stop(timer); \ \ - timer_calc(timer); \ + cmc_timer_calc(timer); \ \ printf("ITERATION %10s TOOK %8.0lf milliseconds for %8" PRIuMAX " elements\n", #NAME, timer.result, s1); \ \ double iter_time = timer.result; \ \ - timer_start(timer); \ + cmc_timer_start(timer); \ \ for (size_t i = 0; i < NTOTAL; i++) \ { \ removebody; \ } \ \ - timer_stop(timer); \ + cmc_timer_stop(timer); \ \ - timer_calc(timer); \ + cmc_timer_calc(timer); \ \ size_t s2 = PFX##_count(coll); \ \ @@ -151,8 +151,8 @@ COLLECTION_GENERATE(MULTISET, ms, mset, /* FMOD */, /* K */, int) \ double output_time = timer.result; \ \ - timer_stop(total); \ - timer_calc(total); \ + cmc_timer_stop(total); \ + cmc_timer_calc(total); \ \ PFX##_free(coll, NULL); \ \ @@ -221,6 +221,9 @@ int main(void) // Linear containers have to search for NMIN elements and non-linear (hash // and tree) have to search for all elements. + cmc_timer timer; + cmc_timer_start(timer); + DEQUE_io_benchmark(array, sarray, NMIN); HASHMAP_io_benchmark(array, sarray, NTOTAL); HASHSET_io_benchmark(array, sarray, NTOTAL); @@ -236,6 +239,13 @@ int main(void) MULTIMAP_io_benchmark(array, array, NTOTAL); MULTISET_io_benchmark(array, array, NTOTAL); + cmc_timer_stop(timer); + cmc_timer_calc(timer); + + printf("+-----------------------------------------------------------+ \n"); + printf("| Total Benchmark Running Time : %12.0lf seconds | \n", timer.result / 1000); + printf("+-----------------------------------------------------------+ \n"); + free(array); free(sarray);