summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2020-09-20 07:54:04 +0200
committerTyge Løvset <[email protected]>2020-09-20 07:54:04 +0200
commita9881058fbe47a90d4614f9fb5d693633dbdc7af (patch)
treeb49db605aed741b43a1cd6ef7c369fcee59e24ad
parent240c4d27067fb6dd04b3964dcfd46342ee1a2de3 (diff)
downloadSTC-modified-a9881058fbe47a90d4614f9fb5d693633dbdc7af.tar.gz
STC-modified-a9881058fbe47a90d4614f9fb5d693633dbdc7af.zip
Added c_foreach (i,N) and c_foreach (N), and updated README.md
-rw-r--r--README.md44
-rw-r--r--examples/birthday.c4
-rw-r--r--examples/priority.c6
-rw-r--r--examples/random.c8
-rw-r--r--examples/rngtest.c12
-rw-r--r--stc/cdefs.h2
6 files changed, 33 insertions, 43 deletions
diff --git a/README.md b/README.md
index 6c2a7913..4d29af78 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,7 @@ The usage of the containers is vert similar to the C++ standard containers, so i
All containers mentioned above, except cstr_t and cbitset_t are generic and typesafe (similar to templates in C++). No casting is used. A simple example:
```C
#include <stc/cvec.h>
+
using_cvec(i, int);
int main(void) {
@@ -114,37 +115,17 @@ The containers are memory efficent, i.e. they occupy as little memory as practic
cmap discussion
---------------
-**cmap/cset** are the most complex of the containers (although, currently less than 500 lines of code). It uses open hashing, but does not rely on power-of-two size table, nor prime number lengths, and it does not have tombstone buckets. It is still among the fastest hash-tables, as shown above. The default max load-factor is 0.85, and it shrinks (and rehashes) when load-factor goes below 0.15, by default (can be set per hash container).
+**cmap/cset** uses open hashing and is among the fastest hash-tables for C and C++. The default max load-factor is 0.85.
+
+You can customize the destroy-, hash-, equals- functions, but also define a convertion from a raw/literal type to the key-type specified. This is very useful when e.g. having cstr as key, and therefore a few using-macros are pre-defined
+for cmaps with cstr_t keys and/or values:
-You can customize the destroy-, hash- and equals- function. **cmap/cset** also supports a few other arguments in the declare-statement that allows to define a convertion from a raw/literal type to the key-type specified. This is very useful when e.g. having cstr as key, as it enables the usage of string literals as key in *put() and find()* functions, instead of requering a constructed cstr. Without it, the code would become:
-```C
-using_cmap(si, cstr_t, int); // don't do this.
-...
-cmap_si_put(&map, cstr("mykey"), 12);
-```
-This is a problem because cstr_t key may exist in the map, and it would need to destroy the current key and replace it with the new to avoid memory leak. Lookup would also be problematic:
-```C
-cstr lookup = cstr("mykey");
-int x = cmap_si_find(&map, lookup)->value;
-cstr_del(&lookup);
-```
-To avoid this, use
- *using_cmap_strkey(tag, valuetype)*
- *using_cmap_strval(tag, keytype)*
- *using_cmap_str()* // cstr_t -> cstr_t
- *using_cset_str()* // cstr_t set
-```C
-using_cmap_strkey(si, int);
-...
-cmap_si map = cmap_INIT;
-cmap_si_put(&map, "mykey", 12); // constructs a cstr_t key from the const char* internally.
-int x = cmap_si_find(&map, "mykey")->value; // no allocation of string key happens here.
-cmap_si_del(&map);
-```
-An alternative is to use *char* * as key type, but then you must manage allcoated memory of the hash char* keys yourself.
-Note that this predefined customization is also available for **cvec** and **clist**. See *using_cvec_str()*, *using_clist_str()*.
-To customize your own cmap type to work like cmap_str, you may want to look at **examples/advanced.c**. It demonstrates how to use a custom struct as a hash map key, using the optional parameters to using_cmap().
+To customize your own cmap type to work like these, you may want to look at **examples/advanced.c**. It demonstrates how to use a custom struct as a hash map key, by using the optional parameters to using_cmap().
Example usages
--------------
@@ -181,17 +162,18 @@ int main() {
**cvec** of *int64_t*.
```C
#include <stc/cvec.h>
+
using_cvec(ix, int64_t); // ix is just an example type tag name.
int main() {
cvec_ix bignums = cvec_INIT; // use cvec_ix_init() if initializing after declaration.
cvec_ix_reserve(&bignums, 100);
- for (size_t i = 0; i<100; ++i)
+ c_forrange (i, 100)
cvec_ix_push_back(&bignums, i * i * i);
cvec_ix_pop_back(&bignums); // erase the last
uint64_t value;
- for (size_t i = 0; i < cvec_size(bignums); ++i)
+ c_forrange (i, cvec_size(bignums))
value = bignums.data[i];
cvec_ix_del(&bignums);
}
@@ -200,6 +182,7 @@ int main() {
```C
#include <stc/cstr.h>
#include <stc/cvec.h>
+
using_cvec_str();
int main() {
@@ -220,6 +203,7 @@ int main() {
```C
#include <stdio.h>
#include <stc/cmap.h>
+
using_cmap(ii, int, int);
int main() {
@@ -235,6 +219,7 @@ int main() {
```C
#include <stc/cstr.h>
#include <stc/cmap.h>
+
using_cset_str(); // cstr set. See the discussion above.
int main() {
@@ -254,6 +239,7 @@ int main() {
```C
#include <stc/cstr.h>
#include <stc/cmap.h>
+
using_cmap_str();
int main() {
@@ -276,6 +262,7 @@ int main() {
#include <time.h>
#include <stc/clist.h>
#include <stc/crandom.h>
+
using_clist(fx, double);
int main() {
@@ -284,7 +271,7 @@ int main() {
crand_uniform_f64_t dist = crand_uniform_f64_init(100.0, 1000.0);
int k;
- for (int i = 0; i < 10000000; ++i)
+ c_forrange (10000000)
clist_fx_push_back(&list, crand_uniform_f64(&eng, dist));
k = 0;
c_foreach (i, clist_fx, list)
@@ -313,6 +300,7 @@ int main() {
```C
#include <stdio.h>
#include <stc/carray.h>
+
using_carray(f, float);
int main()
diff --git a/examples/birthday.c b/examples/birthday.c
index a5cce918..fae36430 100644
--- a/examples/birthday.c
+++ b/examples/birthday.c
@@ -19,7 +19,7 @@ void repeats(void)
cmap_ic m = cmap_INIT;
cmap_ic_reserve(&m, N);
clock_t now = clock();
- c_forrange (i, size_t, N) {
+ c_forrange (i, N) {
uint64_t k = crand_i64(&rng) & mask;
int v = ++cmap_ic_emplace(&m, k, 0).first->second;
if (v > 1) printf("%zu: %llx - %d\n", i, k, v);
@@ -40,7 +40,7 @@ void distribution(void)
clock_t now = clock();
crand_uniform_i32_t dist = crand_uniform_i32_init(0, M);
- c_forrange (i, size_t, N) {
+ c_forrange (N) {
++cmap_x_emplace(&map, crand_uniform_i32(&rng, &dist), 0).first->second;
}
float diff = (float) (clock() - now) / CLOCKS_PER_SEC;
diff --git a/examples/priority.c b/examples/priority.c
index bce14f49..e4a20da9 100644
--- a/examples/priority.c
+++ b/examples/priority.c
@@ -16,18 +16,18 @@ int main() {
cpqueue_i heap = cpqueue_i_init();
// Push ten million random numbers to priority queue
- c_forrange (i, int, N)
+ c_forrange (N)
cpqueue_i_push(&heap, crand_uniform_i64(&pcg, &dist));
// push some negative numbers too.
c_push_items(&heap, cpqueue_i, {-231, -32, -873, -4, -343});
- c_forrange (i, int, N)
+ c_forrange (N)
cpqueue_i_push(&heap, crand_uniform_i64(&pcg, &dist));
// Extract the hundred smallest.
- c_forrange (i, int, 100) {
+ c_forrange (100) {
printf("%zd ", *cpqueue_i_top(&heap));
cpqueue_i_pop(&heap);
}
diff --git a/examples/random.c b/examples/random.c
index 44465ce7..fa63d2af 100644
--- a/examples/random.c
+++ b/examples/random.c
@@ -18,7 +18,7 @@ int main()
printf("32 uniform: %u\n", dist0.range);
double fsum = 0;
before = clock();
- c_forrange (i, size_t, N) {
+ c_forrange (N) {
fsum += (double) crand_uniform_i32(&pcg, &dist0) / dist0.range;
}
difference = clock() - before;
@@ -29,7 +29,7 @@ int main()
puts("32 unbiased");
fsum = 0;
before = clock();
- c_forrange (i, size_t, N) {
+ c_forrange (N) {
fsum += (double) crand_unbiased_i32(&pcg, &dist0) / dist0.range;
}
difference = clock() - before;
@@ -40,7 +40,7 @@ int main()
crand_uniform_i64_t dist1 = crand_uniform_i64_init(0, N);
sum = 0;
before = clock();
- c_forrange (i, size_t, N) {
+ c_forrange (N) {
sum += crand_uniform_i64(&stc, &dist1);
}
difference = clock() - before;
@@ -52,7 +52,7 @@ int main()
size_t N2 = 10000000;
int hist[R] = {0};
sum = 0;
- c_forrange (i, size_t, N2) {
+ c_forrange (N2) {
int n = (int) (crand_normal_f64(&stc, &dist2) + 0.5);
sum += n;
if (n >= 0 && n < R) ++hist[n];
diff --git a/examples/rngtest.c b/examples/rngtest.c
index 16360eac..df3aa41c 100644
--- a/examples/rngtest.c
+++ b/examples/rngtest.c
@@ -17,7 +17,7 @@ int main(void)
crand_uniform_i64_t idist = crand_uniform_i64_init(10, 20);
crand_uniform_f64_t fdist = crand_uniform_f64_init(10, 20);
- c_forrange (i, int, 30) printf("%02zd ", crand_uniform_i64(&stc, &idist));
+ c_forrange (30) printf("%02zd ", crand_uniform_i64(&stc, &idist));
puts("");
crand_rng32_t pcg = crand_rng32_init(time(NULL));
@@ -26,7 +26,7 @@ int main(void)
before = clock(); \
v = 0;
- c_forrange (i, size_t, NN) {
+ c_forrange (NN) {
//v += crand_i32(&pcg);
v += crand_uniform_i32(&pcg, &i32dist);
}
@@ -35,20 +35,20 @@ int main(void)
before = clock(); \
v = 0;
- c_forrange (i, size_t, NN) {
+ c_forrange (NN) {
//v += crand_i64(&stc) & 0xffffffff;
v += crand_uniform_i64(&stc, &idist);
}
difference = clock() - before;
printf("stc64: %.02f, %zu\n", (float) difference / CLOCKS_PER_SEC, v);
- c_forrange (i, int, 8) printf("%d ", crand_uniform_i32(&pcg, &i32dist));
+ c_forrange (8) printf("%d ", crand_uniform_i32(&pcg, &i32dist));
puts("");
- c_forrange (i, int, 8) printf("%f ", crand_uniform_f32(&pcg, &f32dist));
+ c_forrange (8) printf("%f ", crand_uniform_f32(&pcg, &f32dist));
puts("");
- c_forrange (i, int, 8) printf("%f ", crand_uniform_f64(&stc, &fdist));
+ c_forrange (8) printf("%f ", crand_uniform_f64(&stc, &fdist));
puts("");
} \ No newline at end of file
diff --git a/stc/cdefs.h b/stc/cdefs.h
index 571dafd7..9dc496d1 100644
--- a/stc/cdefs.h
+++ b/stc/cdefs.h
@@ -87,6 +87,8 @@
for (ctype##_iter_t it = start, it##_end_ = finish; it.get != it##_end_.get; ctype##_next(&it))
#define c_forrange(...) c_MACRO_OVERLOAD(c_forrange, __VA_ARGS__)
+#define c_forrange_1(stop) for (size_t _c_i=0, _c_end_=stop; _c_i < _c_end_; ++_c_i)
+#define c_forrange_2(i, stop) for (size_t i=0, i##_end_=stop; i < i##_end_; ++i)
#define c_forrange_3(i, type, stop) for (type i=0, i##_end_=stop; i < i##_end_; ++i)
#define c_forrange_4(i, type, start, stop) for (type i=start, i##_end_=stop; i < i##_end_; ++i)
#define c_forrange_5(i, type, start, stop, step) \