From dc1b74109029bc82efea290475431cafc0307674 Mon Sep 17 00:00:00 2001 From: tylo Date: Fri, 28 Aug 2020 10:14:56 +0200 Subject: Finished adding RawValue API (convertable values) to containers. --- examples/benchmark.c | 2 +- examples/complex.c | 2 +- examples/demos.c | 10 ++--- examples/geek2.c | 43 +++++++++++-------- examples/geek3.c | 4 +- examples/geek4.c | 10 ++--- examples/geek5.c | 2 +- examples/inits.c | 2 +- examples/mapmap.c | 4 +- examples/words.c | 4 +- stc/clist.h | 2 +- stc/cmap.h | 115 ++++++++++++++++++++++++++++++--------------------- stc/crandom.h | 5 ++- 13 files changed, 117 insertions(+), 88 deletions(-) diff --git a/examples/benchmark.c b/examples/benchmark.c index 3ff193bc..0b9c4f10 100644 --- a/examples/benchmark.c +++ b/examples/benchmark.c @@ -124,7 +124,7 @@ crandom_eng64_t rng; const size_t N1 = 10000000 * 5; const size_t N2 = 10000000 * 5; -const size_t N3 = 10000000 * 10; +const size_t N3 = 10000000 * 5; #define RR 20 int rr = RR; diff --git a/examples/complex.c b/examples/complex.c index cd8a6d78..08a3b505 100644 --- a/examples/complex.c +++ b/examples/complex.c @@ -8,7 +8,7 @@ void check_destroy(float* v) {printf("destroy %g\n", *v);} declare_carray(f, float, check_destroy); // normally omit the last argument - float type need no destroy. declare_clist(t2, carray2f, carray2f_destroy, c_no_compare); declare_cmap(il, int, clist_t2, clist_t2_destroy); -declare_cmap_str(sm, cmap_il, cmap_il_destroy); +declare_cmap_strkey(sm, cmap_il, cmap_il_destroy); int main() { int xdim = 4, ydim = 6; diff --git a/examples/demos.c b/examples/demos.c index a3e512e5..4f5c2356 100644 --- a/examples/demos.c +++ b/examples/demos.c @@ -62,9 +62,9 @@ void vectordemo2() { printf("\nVECTORDEMO2\n"); cvec_str names = cvec_init; - cvec_str_push_back(&names, cstr_make("Mary")); - cvec_str_push_back(&names, cstr_make("Joe")); - cvec_str_push_back(&names, cstr_make("Chris")); + cvec_str_push_back(&names, "Mary"); + cvec_str_push_back(&names, "Joe"); + cvec_str_push_back(&names, "Chris"); cstr_assign(&names.data[1], "Jane"); // replace Joe printf("names[1]: %s\n", names.data[1].str); @@ -130,7 +130,7 @@ void mapdemo1() } -declare_cmap_str(si, int); // Shorthand macro for the general declare_cmap expansion. +declare_cmap_strkey(si, int); // Shorthand macro for the general declare_cmap expansion. void mapdemo2() { @@ -152,7 +152,7 @@ void mapdemo2() } -declare_cmap_str(ss, cstr_t, cstr_destroy); +declare_cmap_strkey(ss, cstr_t, cstr_destroy); void mapdemo3() { diff --git a/examples/geek2.c b/examples/geek2.c index 9b2785f1..6141518f 100644 --- a/examples/geek2.c +++ b/examples/geek2.c @@ -1,16 +1,16 @@ -#ifndef CXX +#ifndef RUST #include #include -declare_cmap_str(ss, cstr_t, cstr_destroy); +declare_cmap_str(); declare_cset_str(); int main() { // Lets use an explicit type signature (which would // be `cmap` in this example). - cmap_ss book_reviews = cmap_init; + cmap_str book_reviews = cmap_init; cset_str set = cset_init; cset_str_put(&set, "Hello"); cset_str_put(&set, "You"); @@ -19,50 +19,57 @@ int main() printf("%s ", i.item->key.str); puts(""); // Review some books. - cmap_ss_put(&book_reviews, + c_push(&book_reviews, cmap_str, c_items( + {"Adventures of Huckleberry Finn", "My favorite book."}, + {"Grimms' Fairy Tales", "Masterpiece."}, + {"Pride and Prejudice", "Very enjoyable."}, + {"The Adventures of Sherlock Holmes", "Eye lyked it alot."}, + )); +/* + cmap_str_insert(&book_reviews, "Adventures of Huckleberry Finn", - cstr_make("My favorite book.") + "My favorite book." ); - cmap_ss_put(&book_reviews, + cmap_str_insert(&book_reviews, "Grimms' Fairy Tales", - cstr_make("Masterpiece.") + "Masterpiece." ); - cmap_ss_put(&book_reviews, + cmap_str_insert(&book_reviews, "Pride and Prejudice", - cstr_make("Very enjoyable.") + "Very enjoyable." ); - cmap_ss_put(&book_reviews, + cmap_str_insert(&book_reviews, "The Adventures of Sherlock Holmes", - cstr_make("Eye lyked it alot.") + "Eye lyked it alot." ); - +*/ // Check for a specific one. // When collections store owned values (String), they can still be // queried using references (&str). - if (! cmap_ss_find(&book_reviews, "Les Misérables")) { + if (! cmap_str_find(&book_reviews, "Les Misérables")) { printf("We've got %zu reviews, but Les Misérables ain't one.\n", cmap_size(book_reviews)); } // oops, this review has a lot of spelling mistakes, let's delete it. - cmap_ss_erase(&book_reviews, "The Adventures of Sherlock Holmes"); + cmap_str_erase(&book_reviews, "The Adventures of Sherlock Holmes"); // Look up the values associated with some keys. const char* to_find[] = {"Pride and Prejudice", "Alice's Adventure in Wonderland", NULL}; for (const char** book = to_find; *book; ++book) { - cmap_ss_entry_t *review = cmap_ss_find(&book_reviews, *book); + cmap_str_entry_t *review = cmap_str_find(&book_reviews, *book); if (review) printf("%s: %s\n", *book, review->value.str); else printf("%s is unreviewed.\n", *book); } // Look up the value for a key (will panic if the key is not found). - printf("Review for Jane: %s\n", cmap_ss_find(&book_reviews, "Pride and Prejudice")->value.str); + printf("Review for Jane: %s\n", cmap_str_find(&book_reviews, "Pride and Prejudice")->value.str); // Iterate over everything. - c_foreach (i, cmap_ss, book_reviews) { + c_foreach (i, cmap_str, book_reviews) { printf("- %s: \"%s\"\n", i.item->key.str, i.item->value.str); } - cmap_ss_destroy(&book_reviews); + cmap_str_destroy(&book_reviews); } #else // ====================================================== diff --git a/examples/geek3.c b/examples/geek3.c index b8de97c8..ad2bdfa1 100644 --- a/examples/geek3.c +++ b/examples/geek3.c @@ -3,8 +3,8 @@ #include #include -declare_cmap_str(si, int); -declare_cmap_str(ss, cstr_t, cstr_destroy); +declare_cmap_strkey(si, int); +declare_cmap_strkey(ss, cstr_t, cstr_destroy); int main () { diff --git a/examples/geek4.c b/examples/geek4.c index b0a57844..a62a6fd1 100644 --- a/examples/geek4.c +++ b/examples/geek4.c @@ -38,7 +38,7 @@ Efficient Approach: For all the words of the first sentence, we can check if it #include declare_cvec_str(); -declare_cmap_str(sb, bool); +declare_cmap_strkey(sb, bool); declare_cvec(sb, cmap_sb_entry_t, cmap_sb_entry_destroy, c_no_compare); // Function to return the count of common words @@ -137,10 +137,10 @@ int commonWords(cvec_str S) int main() { cvec_str S = cvec_init; - cvec_str_push_back(&S, cstr_make("there is a cow")); - cvec_str_push_back(&S, cstr_make("cow is our mother")); - cvec_str_push_back(&S, cstr_make("cow gives us milk and milk is sweet")); - cvec_str_push_back(&S, cstr_make("there is a boy who loves cow")); + cvec_str_push_back(&S, "there is a cow"); + cvec_str_push_back(&S, "cow is our mother"); + cvec_str_push_back(&S, "cow gives us milk and milk is sweet"); + cvec_str_push_back(&S, "there is a boy who loves cow"); printf("%d\n", commonWords(S)); cvec_str_destroy(&S); diff --git a/examples/geek5.c b/examples/geek5.c index 67f5d097..a0531ad3 100644 --- a/examples/geek5.c +++ b/examples/geek5.c @@ -22,7 +22,7 @@ Output: 0 #include declare_cvec(i, int); -declare_cmap_str(sv, cvec_i, cvec_i_destroy); +declare_cmap_strkey(sv, cvec_i, cvec_i_destroy); // Function to return the number of occurrences of diff --git a/examples/inits.c b/examples/inits.c index 92e67b84..c55bf83f 100644 --- a/examples/inits.c +++ b/examples/inits.c @@ -5,7 +5,7 @@ #include declare_cmap(id, int, cstr_t, cstr_destroy); // Map of int -> cstr_t -declare_cmap_str(cnt, int); +declare_cmap_strkey(cnt, int); typedef struct {int x, y;} ipair_t; inline static int ipair_compare(const ipair_t* a, const ipair_t* b) { diff --git a/examples/mapmap.c b/examples/mapmap.c index 14ccd9a9..1f2bd4f5 100644 --- a/examples/mapmap.c +++ b/examples/mapmap.c @@ -8,8 +8,8 @@ static void my_str_destr(cstr_t* x) { cstr_destroy(x); } -declare_cmap_str(ss, cstr_t, my_str_destr); -declare_cmap_str(cfg, cmap_ss, cmap_ss_destroy); +declare_cmap_strkey(ss, cstr_t, my_str_destr); +declare_cmap_strkey(cfg, cmap_ss, cmap_ss_destroy); int main(void) { cmap_cfg config = cmap_init; diff --git a/examples/words.c b/examples/words.c index a10811c1..f8e86329 100644 --- a/examples/words.c +++ b/examples/words.c @@ -6,9 +6,7 @@ declare_cvec_str(); declare_clist_str(); -declare_cmap_str(si, int); - -typedef const char* input_t; +declare_cmap_strkey(si, int); int main1() { diff --git a/stc/clist.h b/stc/clist.h index ecd4fde0..2dfbb2ac 100644 --- a/stc/clist.h +++ b/stc/clist.h @@ -119,7 +119,7 @@ clist_##tag##_insert_after_v(clist_##tag* self, clist_##tag##_iter_t pos, Value value); \ STC_INLINE void \ clist_##tag##_insert_after(clist_##tag* self, clist_##tag##_iter_t pos, RawValue rawValue) { \ - clist_##tag##_insert_after_v(self, valueFromRaw(rawValue)); \ + clist_##tag##_insert_after_v(self, pos, valueFromRaw(rawValue)); \ } \ STC_API void \ clist_##tag##_erase_after(clist_##tag* self, clist_##tag##_iter_t pos); \ diff --git a/stc/cmap.h b/stc/cmap.h index 1840eda6..a7488edf 100644 --- a/stc/cmap.h +++ b/stc/cmap.h @@ -86,7 +86,7 @@ enum {chash_HASH = 0x7f, chash_USED = 0x80}; #define declare_cmap_10(tag, Key, Value, valueDestroy, keyEqualsRaw, keyHashRaw, \ keyDestroy, RawKey, keyToRaw, keyFromRaw) \ declare_CHASH(tag, cmap, Key, Value, valueDestroy, keyEqualsRaw, keyHashRaw, \ - keyDestroy, RawKey, keyToRaw, keyFromRaw) + keyDestroy, RawKey, keyToRaw, keyFromRaw, Value, c_default_from_raw) /* cset: */ #define declare_cset(...) \ @@ -105,49 +105,64 @@ enum {chash_HASH = 0x7f, chash_USED = 0x80}; #define declare_cset_8(tag, Key, keyEqualsRaw, keyHashRaw, keyDestroy, \ RawKey, keyToRaw, keyFromRaw) \ declare_CHASH(tag, cset, Key, Key, void, keyEqualsRaw, keyHashRaw, \ - keyDestroy, RawKey, keyToRaw, keyFromRaw) + keyDestroy, RawKey, keyToRaw, keyFromRaw, void, c_default_from_raw) -/* cset_str, cmap_str: */ +/* cset_str, cmap_str, cmap_strkey, cmap_strval: */ #define declare_cset_str() \ - declare_CHASH_STR(str, cset, cstr_t, void) + declare_CHASH_strkey(str, cset, cstr_t, void) -#define declare_cmap_str(...) \ - c_MACRO_OVERLOAD(declare_cmap_str, __VA_ARGS__) +#define declare_cmap_str() \ + declare_CHASH(str, cmap, cstr_t, cstr_t, cstr_destroy, cstr_equals_raw, cstr_hash_raw, \ + cstr_destroy, const char*, cstr_to_raw, cstr_make, const char*, cstr_make) -#define declare_cmap_str_2(tag, Value) \ - declare_CHASH_STR(tag, cmap, Value, c_default_destroy) +#define declare_cmap_strkey(...) \ + c_MACRO_OVERLOAD(declare_cmap_strkey, __VA_ARGS__) -#define declare_cmap_str_3(tag, Value, ValueDestroy) \ - declare_CHASH_STR(tag, cmap, Value, ValueDestroy) +#define declare_cmap_strkey_2(tag, Value) \ + declare_CHASH_strkey(tag, cmap, Value, c_default_destroy) -#define declare_CHASH_STR(tag, ctype, Value, valueDestroy) \ +#define declare_cmap_strkey_3(tag, Value, ValueDestroy) \ + declare_CHASH_strkey(tag, cmap, Value, ValueDestroy) + +#define declare_cmap_strval(...) \ + c_MACRO_OVERLOAD(declare_cmap_strval, __VA_ARGS__) + +#define declare_cmap_strval_2(tag, Key) \ + declare_cmap_strval_4(tag, Key, c_default_equals, c_default_hash16) + +#define declare_cmap_strval_4(tag, Key, keyEquals, keyHash) \ + declare_CHASH(tag, cmap, Key, cstr_t, cstr_destroy, keyEquals, keyHash, \ + c_default_destroy, Key, c_default_to_raw, c_default_from_raw, const char*, cstr_make) + +#define declare_CHASH_strkey(tag, ctype, Value, valueDestroy) \ declare_CHASH(tag, ctype, cstr_t, Value, valueDestroy, cstr_equals_raw, cstr_hash_raw, \ - cstr_destroy, const char*, cstr_to_raw, cstr_make) + cstr_destroy, const char*, cstr_to_raw, cstr_make, Value, c_default_from_raw) -#define OPT_1_cset(x) -#define OPT_1_cmap(x) x -#define OPT_2_cset(x, y) x -#define OPT_2_cmap(x, y) x, y +#define CMAP_ONLY_cset(x) +#define CMAP_ONLY_cmap(x) x +#define CMAP_BOTH_cset(x, y) x +#define CMAP_BOTH_cmap(x, y) x, y /* CHASH full: use 'void' for Value if ctype is cset */ #define declare_CHASH(tag, ctype, Key, Value, valueDestroy, keyEqualsRaw, keyHashRaw, \ - keyDestroy, RawKey, keyToRaw, keyFromRaw) \ + keyDestroy, RawKey, keyToRaw, keyFromRaw, RawValue, valueFromRaw) \ typedef struct { \ Key key; \ - OPT_1_##ctype(Value value;) \ + CMAP_ONLY_##ctype(Value value;) \ } ctype##_##tag##_entry_t; \ \ STC_INLINE void \ ctype##_##tag##_entry_destroy(ctype##_##tag##_entry_t* e) { \ keyDestroy(&e->key); \ - OPT_1_##ctype(valueDestroy(&e->value);) \ + CMAP_ONLY_##ctype(valueDestroy(&e->value);) \ } \ typedef struct { \ RawKey key; \ - OPT_1_##ctype(Value value;) \ + CMAP_ONLY_##ctype(RawValue value;) \ } ctype##_##tag##_input_t; \ \ typedef RawKey ctype##_##tag##_rawkey_t; \ +typedef RawValue ctype##_##tag##_rawvalue_t; \ \ typedef struct { \ ctype##_##tag##_entry_t* table; \ @@ -184,10 +199,34 @@ STC_API void \ ctype##_##tag##_clear(ctype##_##tag* self); \ STC_API ctype##_##tag##_entry_t* \ ctype##_##tag##_find(const ctype##_##tag* self, ctype##_##tag##_rawkey_t rawKey); \ -STC_API ctype##_##tag##_entry_t* /* like c++ std::map.insert_or_assign(): */ \ -ctype##_##tag##_put(ctype##_##tag* self, OPT_2_##ctype(ctype##_##tag##_rawkey_t rawKey, Value value)); \ -STC_API ctype##_##tag##_entry_t* /* like c++ std::map.insert(): */ \ -ctype##_##tag##_insert(ctype##_##tag* self, OPT_2_##ctype(ctype##_##tag##_rawkey_t rawKey, Value value)); \ + \ +struct ctype##_##tag##_result {ctype##_##tag##_entry_t *entry; bool inserted;}; \ +STC_API struct ctype##_##tag##_result \ +ctype##_##tag##_insert_key(ctype##_##tag* self, ctype##_##tag##_rawkey_t rawKey); \ + \ +STC_INLINE ctype##_##tag##_entry_t* /* like c++ std::map.insert_or_assign(): */ \ +ctype##_##tag##_put(ctype##_##tag* self, CMAP_BOTH_##ctype(ctype##_##tag##_rawkey_t rawKey, RawValue rawValue)) { \ + struct ctype##_##tag##_result res = ctype##_##tag##_insert_key(self, rawKey); \ + CMAP_ONLY_##ctype( if (!res.inserted) valueDestroy(&res.entry->value); \ + res.entry->value = valueFromRaw(rawValue); ) \ + return res.entry; \ +} \ +STC_INLINE ctype##_##tag##_entry_t* /* like c++ std::map.insert(): */ \ +ctype##_##tag##_insert(ctype##_##tag* self, CMAP_BOTH_##ctype(ctype##_##tag##_rawkey_t rawKey, RawValue rawValue)) { \ + struct ctype##_##tag##_result res = ctype##_##tag##_insert_key(self, rawKey); \ + CMAP_ONLY_##ctype( if (res.inserted) res.entry->value = valueFromRaw(rawValue); ) \ + return res.entry; \ +} \ + \ +CMAP_ONLY_##ctype( \ +STC_INLINE ctype##_##tag##_entry_t* /* cmap_put_v(key, move(value)) */ \ +ctype##_##tag##_put_v(ctype##_##tag* self, ctype##_##tag##_rawkey_t rawKey, Value value) { \ + struct ctype##_##tag##_result res = ctype##_##tag##_insert_key(self, rawKey); \ + if (!res.inserted) valueDestroy(&res.entry->value); \ + res.entry->value = value; \ + return res.entry; \ +} \ +) /* end CMAP_ONLY */ \ STC_API size_t \ ctype##_##tag##_reserve(ctype##_##tag* self, size_t size); \ STC_API bool \ @@ -203,7 +242,7 @@ STC_API uint32_t c_default_hash16(const void *data, size_t len); \ STC_API uint32_t c_default_hash32(const void* data, size_t len); \ \ implement_CHASH(tag, ctype, Key, Value, valueDestroy, keyEqualsRaw, keyHashRaw, \ - keyDestroy, RawKey, keyToRaw, keyFromRaw) \ + keyDestroy, RawKey, keyToRaw, keyFromRaw, RawValue, valueFromRaw) \ typedef Key ctype##_##tag##_key_t; \ typedef Value ctype##_##tag##_value_t @@ -211,7 +250,7 @@ typedef Value ctype##_##tag##_value_t #if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) #define implement_CHASH(tag, ctype, Key, Value, valueDestroy, keyEqualsRaw, keyHashRaw, \ - keyDestroy, RawKey, keyToRaw, keyFromRaw) \ + keyDestroy, RawKey, keyToRaw, keyFromRaw, RawValue, valueFromRaw) \ STC_API ctype##_##tag \ ctype##_##tag##_with_capacity(size_t cap) { \ ctype##_##tag h = ctype##_init; \ @@ -220,7 +259,7 @@ ctype##_##tag##_with_capacity(size_t cap) { \ } \ STC_API void \ ctype##_##tag##_push_n(ctype##_##tag* self, const ctype##_##tag##_input_t in[], size_t size) { \ - for (size_t i=0; isize * 3 / 2); \ } \ \ -struct ctype##_##tag##_result {ctype##_##tag##_entry_t *entry; bool inserted;}; \ -STC_INLINE struct ctype##_##tag##_result \ +STC_API struct ctype##_##tag##_result \ ctype##_##tag##_insert_key(ctype##_##tag* self, ctype##_##tag##_rawkey_t rawKey) { \ ctype##_##tag##_reserve_expand(self); \ uint32_t hx; \ @@ -288,23 +326,6 @@ ctype##_##tag##_insert_key(ctype##_##tag* self, ctype##_##tag##_rawkey_t rawKey) return res; \ } \ \ -STC_API ctype##_##tag##_entry_t* \ -ctype##_##tag##_put(ctype##_##tag* self, OPT_2_##ctype(ctype##_##tag##_rawkey_t rawKey, Value value)) { \ - struct ctype##_##tag##_result res = ctype##_##tag##_insert_key(self, rawKey); \ - OPT_1_##ctype( \ - if (!res.inserted) valueDestroy(&res.entry->value); \ - res.entry->value = value; \ - ) \ - return res.entry; \ -} \ - \ -STC_API ctype##_##tag##_entry_t* \ -ctype##_##tag##_insert(ctype##_##tag* self, OPT_2_##ctype(ctype##_##tag##_rawkey_t rawKey, Value value)) { \ - struct ctype##_##tag##_result res = ctype##_##tag##_insert_key(self, rawKey); \ - OPT_1_##ctype( if (res.inserted) res.entry->value = value; else valueDestroy(&value); ) \ - return res.entry; \ -} \ - \ STC_API size_t \ ctype##_##tag##_reserve(ctype##_##tag* self, size_t newcap) { \ size_t oldcap = self->bucket_count; \ @@ -361,7 +382,7 @@ ctype##_##tag##_erase(ctype##_##tag* self, ctype##_##tag##_rawkey_t rawKey) { \ if (self->size == 0) \ return false; \ if (self->size < self->bucket_count * self->shrink_limit_factor && self->bucket_count * sizeof(ctype##_##tag##_entry_t) > 1024) \ - ctype##_##tag##_reserve(self, (size_t) (self->size * 1.2f / self->max_load_factor)); \ + ctype##_##tag##_reserve(self, self->size * 6 / 5); \ uint32_t hx; \ size_t i = ctype##_##tag##_bucket(self, &rawKey, &hx); \ return ctype##_##tag##_erase_entry(self, self->table + i); \ diff --git a/stc/crandom.h b/stc/crandom.h index a3d0b77c..f4b609b7 100644 --- a/stc/crandom.h +++ b/stc/crandom.h @@ -95,11 +95,14 @@ STC_INLINE crandom_distrib_i64_t crandom_uniform_i64_init(int64_t low, int64_t h crandom_distrib_i64_t dist = {low, high - low + 1}; return dist; } +#if defined(_MSC_VER) && defined(_WIN64) +#include +#endif + STC_INLINE int64_t crandom_uniform_i64(crandom_eng64_t* rng, crandom_distrib_i64_t dist) { #if defined(__SIZEOF_INT128__) return dist.offset + (int64_t) (((__uint128_t) crandom_i64(rng) * dist.range) >> 64); #elif defined(_MSC_VER) && defined(_WIN64) - uint64_t _umul128(uint64_t x, uint64_t y, uint64_t *hi); uint64_t hi; _umul128(crandom_i64(rng), dist.range, &hi); return dist.offset + hi; #else return dist.offset + crandom_i64(rng) % dist.range; // slower -- cgit v1.2.3