v0.24.0 preview
This commit is contained in:
1 parent
767fc0d7fd
commit
203516d8cf
7 files changed
+256
-5
No files matched your search
+5
-5
@@ -12,11 +12,11 @@ addons:
|
||||
- cmake
|
||||
- python3.8
|
||||
script:
|
||||
- sudo ln -s /usr/bin/gcc-6 /usr/local/bin/gcc
|
||||
- export CC=gcc-7
|
||||
- sudo ln -s /usr/bin/gcc-9 /usr/local/bin/gcc
|
||||
- sudo ln -s /usr/bin/python3.8 /usr/local/bin/python
|
||||
- export CC=gcc-9
|
||||
- gcc --version
|
||||
- python3 --version
|
||||
- python3.8 autogen.py
|
||||
- make coverage
|
||||
- python --version
|
||||
- make
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
@@ -1,5 +1,22 @@
|
||||
# RELEASE.MAJOR.MINOR
|
||||
|
||||
0.24.0
|
||||
A lot of breaking changes, with the library more modular now
|
||||
Comeback of PUBLIC and PRIVATE for the CMC sub-library
|
||||
Callbacks are now optional and can be turned off by defining CMC_NO_CALLBACKS
|
||||
Added EXT library
|
||||
New macro CMC_CAMEL_CASE can change the library's style where the default is snake case
|
||||
Added:
|
||||
./cor/alloc.h
|
||||
./cor/callbacks.h
|
||||
./cor/heap.h
|
||||
Complete rework of tests and code coverage
|
||||
Removed cmc_flags, where now every flag is an enum (CMC_FLAGS_OK, CMC_FLAGS_ERROR, etc)
|
||||
Different include guards
|
||||
New way to generate code using PARAM
|
||||
Code now completely changed by using the CMC_ macro to concatenate tokens
|
||||
Token concatenation with SNAME now uses special macros that allow customization of the suffixes
|
||||
|
||||
0.23.1
|
||||
Added ./cor/bitset.h
|
||||
Added foreach tests
|
||||
@@ -8,6 +25,7 @@
|
||||
|
||||
0.23.0
|
||||
Added ./cmc/bitset.h
|
||||
Added ./cor/flags.h
|
||||
Added ./utl/futils.h
|
||||
Added ./utl/mutex.h
|
||||
Added ./utl/thread.h
|
||||
|
||||
@@ -21,6 +21,77 @@
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* Installation
|
||||
* Usage
|
||||
* Contributing
|
||||
* License
|
||||
* Features
|
||||
|
||||
## Installation
|
||||
|
||||
No installation is required. The entire library is made of header files and can be directly included into your project.
|
||||
|
||||
## Usage
|
||||
|
||||
The header `macro_collections.h` includes every feature from the library and comes with higher level APIs that help you generate collections from specific sub-libraries with specific extensions.
|
||||
|
||||
```c
|
||||
// WIP
|
||||
#include "macro_collections.h"
|
||||
|
||||
// A PARAM is a standard way to pass required parameters to the lower level API.
|
||||
// It is a tuple of form (PFX, SNAME, SIZE, K, V). In this case, not all of them
|
||||
// are used, so we can leave them empty.
|
||||
#define MY_LIST_PARAMS (si32, stacki32, , , int32_t)
|
||||
|
||||
// High level API. Generate a LIST from the CMC library with the STR extension
|
||||
C_MACRO_COLLECTIONS_GEN(PUBLIC, CMC, LIST, MY_LIST_PARAMS, (STR))
|
||||
|
||||
bool int_str(FILE *fptr, int val)
|
||||
{
|
||||
return 0 <= fprintf(fptr, "%d", val);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct stack_int *stack = sint_new(100, &(struct stack_int_fval) { .str = int_str });
|
||||
|
||||
si32_free(stack);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
## Features
|
||||
|
||||
The C Macro Collections library is organized into many other sub-libraries. The following table is a quick overview.
|
||||
|
||||
| Library | Name | Description |
|
||||
| :-----: | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||
| CMC | The main C Macro Collections | The main library with variably-sized collections |
|
||||
| COR | Core | Core functionalities used by more than one collection, usually from different sub-libraries |
|
||||
| EXT | Extensions | Extension to collections from CMC, SAC and TSC libraries |
|
||||
| INT | Integrations | Macros that facilitate the creation of code that involves more than one type of collection, e.g. transforming a set to a list |
|
||||
| SAC | Statically Allocated Collections | Collections with a fixed sized array that don't use any heap allocation |
|
||||
| TSC | Thread-Safe Collections | Collections that allow multiple operations from multiple threads |
|
||||
| UTL | Utilities | Utilities for the library |
|
||||
|
||||
Every macro that generates code for a certain collection can be found with the following template. Some exceptions exist as certain collections don't have or can't have some features. One big example is the `UTL` library, which does not follow this pattern.
|
||||
|
||||
```
|
||||
macro_name := CMC_[ lib ]_[ collection ]_[ part ]_[ file ]
|
||||
|
||||
lib := CMC | COR | DEV | EXT | INT | SAC | TSC
|
||||
collection := BITSET | DEQUE | HASHBIDIMAP | HASHMAP | HASHMULTIMAP | HASHMULTISET | HASHSET | HEAP | INTERVALHEAP | LINKEDLIST | LIST | QUEUE | SORTEDLIST | STACK | TREEBIDIMAP | TREEMAP | TREEMULTIMAP | TREEMULTISET | TREESET
|
||||
part := CORE | ITER | INIT | SETF | NODE ...
|
||||
file := HEADER | SOURCE
|
||||
```
|
||||
|
||||
__Some `collection`s might not be present in a certain `lib`. Check the documentation.__
|
||||
|
||||
Every macro is suffixed by `CMC` and each section is separated by an underscore (`_`). The first section is the library (`lib`). The second is the collection name in all uppercase. Then the `part` (or which feature from it) that you wish to generate. And last, if it is code that should belong to a header file or code that should belong to a source file.
|
||||
|
||||
* Project Structure
|
||||
* Available Collections
|
||||
* Features
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef COUNT
|
||||
#error "Please define COUNT"
|
||||
#endif
|
||||
|
||||
#include "cmc/hashmap.h"
|
||||
|
||||
CMC_CMC_HASHMAP_CORE(PUBLIC, HEADER, (hmi32, hashmapi32, , int32_t, int32_t))
|
||||
CMC_CMC_HASHMAP_CORE(PUBLIC, SOURCE, (hmi32, hashmapi32, , int32_t, int32_t))
|
||||
|
||||
int cmp(int32_t a, int32_t b)
|
||||
{
|
||||
return (a > b) - (a < b);
|
||||
}
|
||||
|
||||
size_t hash(int32_t a)
|
||||
{
|
||||
size_t x = (size_t)a;
|
||||
x = ((x >> 16) ^ x) * 0x45d9f3b;
|
||||
x = ((x >> 16) ^ x) * 0x45d9f3b;
|
||||
x = (x >> 16) ^ x;
|
||||
return x;
|
||||
}
|
||||
|
||||
struct hashmapi32_fkey *fkey = &(struct hashmapi32_fkey) {
|
||||
.cmp = cmp,
|
||||
.hash = hash,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct hashmapi32_fval *fval = &(struct hashmapi32_fval) {
|
||||
.cmp = cmp,
|
||||
.hash = hash,
|
||||
NULL
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct hashmapi32 *map = hmi32_new(COUNT, 0.6, fkey, fval);
|
||||
|
||||
for (int32_t i = 0; i < COUNT; i++)
|
||||
hmi32_insert(map, i, i);
|
||||
|
||||
hmi32_free(map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import sys
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
ITERATIONS = 10
|
||||
VERBOSE = False
|
||||
|
||||
NL = '\n'
|
||||
|
||||
INCLUDE = "../../../src"
|
||||
CC = 'gcc'
|
||||
CCPP = 'g++' # LoL
|
||||
OPT = '-O3'
|
||||
COUNT = 2000000
|
||||
|
||||
# Common args
|
||||
args = ['-I', INCLUDE, OPT, f'-DCOUNT={COUNT}', '-DCMC_NO_CALLBACKS']
|
||||
|
||||
c_args = [CC, 'hashmap.c', '-o', 'hashmap.exe']
|
||||
cpp_args = [CCPP, 'unorderedmap.cpp', '-I', INCLUDE, '-o', 'unorderedmap.exe', OPT, f'-DCOUNT={COUNT}']
|
||||
|
||||
c_args.extend(args)
|
||||
cpp_args.extend(args)
|
||||
|
||||
subprocess.check_output(c_args)
|
||||
subprocess.check_output(cpp_args)
|
||||
|
||||
total = 0
|
||||
for i in range(ITERATIONS):
|
||||
print(f'{i}...', end='')
|
||||
sys.stdout.flush()
|
||||
start_time = time.time()
|
||||
subprocess.call(['./hashmap.exe'])
|
||||
|
||||
delta = time.time() - start_time
|
||||
total += delta
|
||||
|
||||
if VERBOSE:
|
||||
print(f'({delta})')
|
||||
|
||||
avg = int(((total / ITERATIONS) * 1e9) / COUNT)
|
||||
print(f'{"" if VERBOSE else NL}{total / ITERATIONS} seconds for {COUNT} -> AVG[{avg} ns] [hashmap.exe]{NL if VERBOSE else ""}')
|
||||
|
||||
total = 0
|
||||
for i in range(ITERATIONS):
|
||||
print(f'{i}...', end='')
|
||||
sys.stdout.flush()
|
||||
start_time = time.time()
|
||||
subprocess.call(['./unorderedmap.exe'])
|
||||
|
||||
delta = time.time() - start_time
|
||||
total += delta
|
||||
|
||||
if VERBOSE:
|
||||
print(f'({delta})')
|
||||
|
||||
avg = int(((total / ITERATIONS) * 1e9) / COUNT)
|
||||
print(f'{"" if VERBOSE else NL}{total / ITERATIONS} seconds for {COUNT} -> AVG[{avg} ns] [unorderedmap.exe]{NL if VERBOSE else ""}')
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef COUNT
|
||||
#error "Please define COUNT"
|
||||
#endif
|
||||
|
||||
#include <unordered_map>
|
||||
#include <cstdint>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
std::unordered_map<int32_t, int32_t> map(COUNT);
|
||||
|
||||
for (int32_t i = 0; i < COUNT; i++)
|
||||
map.insert({i, i});
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#include <math.h>
|
||||
#include "cmc/bitset.h"
|
||||
|
||||
CMC_CMC_BITSET_CORE(PUBLIC, HEADER, (bs, bitset))
|
||||
CMC_CMC_BITSET_CORE(PUBLIC, SOURCE, (bs, bitset))
|
||||
|
||||
// All the prime numbers up to 1 billion
|
||||
// With -O3:
|
||||
// 28.583 s runtime
|
||||
// 120 MB RAM
|
||||
// 490 MB file size
|
||||
int main(void)
|
||||
{
|
||||
const size_t n = 1000000000;
|
||||
|
||||
struct bitset *set = bs_new(n);
|
||||
|
||||
if (!set)
|
||||
return 1;
|
||||
|
||||
bs_set_range(set, 0, n);
|
||||
|
||||
size_t up_to = sqrt((double)n) + 1;
|
||||
for (size_t i = 2; i < up_to; ++i)
|
||||
{
|
||||
if (bs_get(set, i))
|
||||
{
|
||||
for (size_t j = 2 * i; j < n; j += i)
|
||||
bs_clear(set, j);
|
||||
}
|
||||
}
|
||||
|
||||
FILE *file = fopen("primes.txt", "w");
|
||||
|
||||
for (size_t i = 2; i < n; i++)
|
||||
{
|
||||
if (bs_get(set, i))
|
||||
fprintf(file, "%" PRIuMAX " ", i);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
Reference in new issue
Block a user