From dcf8d43f14d7116561957089192451b9ac832872 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sun, 24 Jan 2021 00:01:27 +0100 Subject: Improved cvec cdeq. Must be initied with cvec_X_init() and cdeq_X_init(). Not cvec_inits. Improved docs. --- benchmarks/cdeq_benchmark.cpp | 6 ++--- benchmarks/crand_benchmark.cpp | 38 ++++++++++++++++++++--------- benchmarks/vector_vs_deque.cpp | 4 +-- docs/ccommon_api.md | 26 +++++++++++++++----- docs/cpque_api.md | 2 +- docs/cptr_api.md | 6 ++--- docs/cqueue_api.md | 2 +- docs/cstack_api.md | 2 +- docs/cstr_api.md | 2 +- docs/cvec_api.md | 2 +- examples/complex.c | 2 +- examples/demos.c | 6 ++--- examples/inits.c | 6 ++--- examples/list.c | 2 +- examples/ptr.c | 6 ++--- stc/cdeq.h | 50 ++++++++++++++++++++++---------------- stc/clist.h | 8 +++--- stc/cvec.h | 55 +++++++++++++++++++++++------------------- 18 files changed, 132 insertions(+), 93 deletions(-) diff --git a/benchmarks/cdeq_benchmark.cpp b/benchmarks/cdeq_benchmark.cpp index ea1c69b3..b56c5c38 100644 --- a/benchmarks/cdeq_benchmark.cpp +++ b/benchmarks/cdeq_benchmark.cpp @@ -51,7 +51,7 @@ void test2() { clock_t t1 = clock(), t2, t3; stc64_t rng = stc64_init(0); { - cdeq_i deq = cdeq_inits; + cdeq_i deq = cdeq_i_init(); for (size_t i = 1; i < N; i++) { cdeq_i_push_front(&deq, stc64_rand(&rng)); if (i % M == 0) @@ -68,7 +68,7 @@ void test2() { printf("stc access : %5.2f sec, sum=%zu\n", (float)(t3 - t2) / CLOCKS_PER_SEC, sum); cdeq_i_del(&deq); }{ - cdeq_i deq = cdeq_inits; + cdeq_i deq = cdeq_i_init(); for (size_t i = 1; i < N/10; i++) { if (i & 1) cdeq_i_push_front(&deq, stc64_rand(&rng)); else cdeq_i_push_back(&deq, stc64_rand(&rng)); @@ -77,7 +77,7 @@ void test2() { printf("stc pushf/pushb : %5.2f sec\n", (float)(t2 - t3) / CLOCKS_PER_SEC); cdeq_i_del(&deq); }{ - cdeq_i deq = cdeq_inits; + cdeq_i deq = cdeq_i_init(); for (size_t i = 1; i < N/2; i++) { cdeq_i_push_back(&deq, stc64_rand(&rng)); } diff --git a/benchmarks/crand_benchmark.cpp b/benchmarks/crand_benchmark.cpp index 136dcf30..df13befd 100644 --- a/benchmarks/crand_benchmark.cpp +++ b/benchmarks/crand_benchmark.cpp @@ -66,14 +66,28 @@ static inline uint64_t xoshiro256starstar(uint64_t* s) { return result; } - -inline unsigned long long wyhash64(uint64_t* s) { - *s += 0x60bee2bee120fc15ull; - __uint128_t tmp = (__uint128_t) *s * 0xa3b195354a39b70dull; - unsigned long long m1 = (tmp >> 64) ^ tmp; - tmp = (__uint128_t)m1 * 0x1b03738712fad5c9ull; - return (tmp >> 64) ^ tmp; +// wyrand - 2020-12-07 +static inline void _wymum(uint64_t *A, uint64_t *B){ +#if defined(__SIZEOF_INT128__) + __uint128_t r = *A; r *= *B; + *A = (uint64_t) r; *B = (uint64_t ) (r >> 64); +#elif defined(_MSC_VER) && defined(_M_X64) + *A = _umul128(*A, *B, B); +#else + uint64_t ha=*A>>32, hb=*B>>32, la=(uint32_t)*A, lb=(uint32_t)*B, hi, lo; + uint64_t rh=ha*hb, rm0=ha*lb, rm1=hb*la, rl=la*lb, t=rl+(rm0<<32), c=t>32)+(rm1>>32)+c; + *A=lo; *B=hi; +#endif +} +static inline uint64_t _wymix(uint64_t A, uint64_t B){ + _wymum(&A,&B); return A^B; } +static inline uint64_t wyrand64(uint64_t *seed){ + static const uint64_t _wyp[] = {0xa0761d6478bd642full, 0xe7037ed1a0b428dbull}; + *seed+=_wyp[0]; return _wymix(*seed,*seed^_wyp[1]); +} + inline unsigned long long lehmer64(uint64_t* s) { *(__uint128_t *)s *= 0xda942042e4dd58b5ull; @@ -91,16 +105,16 @@ int main(void) cout << "WARMUP" << endl; for (size_t i = 0; i < N; i++) - recipient[i] = wyhash64(rng.state); + recipient[i] = wyrand64(rng.state); clock_t beg, end; for (size_t ti = 0; ti < 4; ti++) { cout << endl << "ROUND " << ti+1 << endl; beg = clock(); for (size_t i = 0; i < N; i++) - recipient[i] = wyhash64(rng.state); + recipient[i] = wyrand64(rng.state); end = clock(); - cout << "wyhash64:\t" + cout << "wyrand64:\t" << (float(end - beg) / CLOCKS_PER_SEC) << " s: " << recipient[312] << endl; beg = clock(); @@ -140,9 +154,9 @@ int main(void) uint64_t s = 0; beg = clock(); for (size_t i = 0; i < N; i++) - s += wyhash64(rng.state); + s += wyrand64(rng.state); end = clock(); - cout << "wyhash64:\t" + cout << "wyrand64:\t" << ((float) end - beg) / CLOCKS_PER_SEC << " s: " << s << endl; diff --git a/benchmarks/vector_vs_deque.cpp b/benchmarks/vector_vs_deque.cpp index a488b7ab..46da98b7 100644 --- a/benchmarks/vector_vs_deque.cpp +++ b/benchmarks/vector_vs_deque.cpp @@ -12,7 +12,7 @@ typedef struct {const char* first; int second;} Si; using_cvec(si, Si, c_no_compare); -cvec_si tm = cvec_inits; +cvec_si tm = cvec_si_init(); void add(cvec_si* tm, const char* s, int n) { Si si = {s, n}; cvec_si_push_back(tm, si); } @@ -176,7 +176,7 @@ using_cvec(i, int); void test_cvec(const int num_iterations) { - cvec_i v = cvec_inits; + cvec_i v = cvec_i_init(); stc64_t rng = stc64_init(0); //v.reserve(num_iterations + 2); //Ensure there is enough space reserved. diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index b6f0b83c..9e1d1767 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -1,16 +1,35 @@ -# STC Module [ccommon](../stc/ccommon.h): Common methods and definitions +# STC [ccommon](../stc/ccommon.h): Common definitions and safe macros This describes the features the ccommon.h header file. ## Macros +The following macros a completely safe to use, with no side-effects. #### c_new, c_del +- Type* c_new (VType) +- Type* c_new (VType, size_t N) +- c_del (CType, CType* x1, ..., CType* xN) #### c_malloc, c_calloc, c_realloc, c_free +Macros that can be overloaded by user to use a different allocator for the entire library #### c_foreach +- c_foreach (it, CType, container) +```c +using_cvec(x, double); +... +cvec_x vec = cvec_x_init(); +double sum = 0; +c_foreach (i, cvec_x, vec) sum += *i.ref; +``` #### c_forrange +Declare an iterator and specify a range to iterate with a for loop. +- c_forrange (end) +- c_forrange (it, end) +- c_forrange (it, IterType, end) +- c_forrange (it, IterType, begin, end) +- c_forrange (it, IterType, begin, end, step) #### c_withbuffer @@ -19,8 +38,3 @@ This describes the features the ccommon.h header file. #### c_push_items #### c_swap - -## Example - -```c -``` diff --git a/docs/cpque_api.md b/docs/cpque_api.md index e85b8bb9..a1762fbe 100644 --- a/docs/cpque_api.md +++ b/docs/cpque_api.md @@ -1,4 +1,4 @@ -# STC Container [cpque](../stc/cpque.h): Priority Queue +# STC [cpque](../stc/cpque.h): Priority Queue A priority queue is a container adaptor that provides constant time lookup of the largest (by default) element, at the expense of logarithmic insertion and extraction. A user-provided argument `<`or `>` must be supplied to set the ordering, e.g. using `>` would cause the smallest element to appear as the top(). diff --git a/docs/cptr_api.md b/docs/cptr_api.md index f95b0062..f1fd0cf1 100644 --- a/docs/cptr_api.md +++ b/docs/cptr_api.md @@ -110,9 +110,9 @@ const char* names[] = { }; int main() { - cvec_pe vec1 = cvec_inits; - cvec_pp vec2 = cvec_inits; - cvec_ps vec3 = cvec_inits; + cvec_pe vec1 = cvec_pe_init(); + cvec_pp vec2 = cvec_pp_init(); + cvec_ps vec3 = cvec_ps_init(); for (int i = 0; i < 6; i += 2) { Person tmp; diff --git a/docs/cqueue_api.md b/docs/cqueue_api.md index 7a225e92..fee5bee4 100644 --- a/docs/cqueue_api.md +++ b/docs/cqueue_api.md @@ -1,4 +1,4 @@ -# STC Container [cqueue](../stc/cqueue.h): Queue +# STC [cqueue](../stc/cqueue.h): Queue ![Queue](pics/queue.jpg) The **cqueue** is container adapter that gives the programmer the functionality of a queue - specifically, a FIFO (first-in, first-out) data structure. The class template acts as a wrapper to the underlying container - only a specific set of functions is provided. The queue pushes the elements on the back of the underlying container and pops them from the front. diff --git a/docs/cstack_api.md b/docs/cstack_api.md index 764b258b..3028f6cb 100644 --- a/docs/cstack_api.md +++ b/docs/cstack_api.md @@ -3,7 +3,7 @@ The **cstack** is a container adapter that gives the programmer the functionality of a stack - specifically, a LIFO (last-in, first-out) data structure. The class template acts as a wrapper to the underlying container - only a specific set of functions is provided. The stack pushes and pops the element from the back of the underlying container, known as the top of the stack. -See [std::stack](https://en.cppreference.com/w/cpp/container/stack) for a similar c++ class. +See the c++ class [std::stack](https://en.cppreference.com/w/cpp/container/stack) for a functional description. ## Declaration diff --git a/docs/cstr_api.md b/docs/cstr_api.md index c6292906..d5e2f4b0 100644 --- a/docs/cstr_api.md +++ b/docs/cstr_api.md @@ -3,7 +3,7 @@ A **cstr* is an object that represent sequences of characters. It supports an interface similar to that of a standard container of bytes, but adding features specifically designed to operate with strings of single-byte characters. -See [std::basic_string](https://en.cppreference.com/w/cpp/string/basic_string) for a similar c++ class. +See the c++ class [std::basic_string](https://en.cppreference.com/w/cpp/string/basic_string) for a functional description. ## Header file diff --git a/docs/cvec_api.md b/docs/cvec_api.md index 8cc7af15..aeaf8ca7 100644 --- a/docs/cvec_api.md +++ b/docs/cvec_api.md @@ -114,7 +114,7 @@ using_cvec(i, int); int main() { // Create a vector containing integers - cvec_i vec = cvec_inits; + cvec_i vec = cvec_i_init(); c_push_items(&vec, cvec_i, {7, 5, 16, 8}); // Add two more integers to vector diff --git a/examples/complex.c b/examples/complex.c index 1346007a..67397669 100644 --- a/examples/complex.c +++ b/examples/complex.c @@ -22,7 +22,7 @@ int main() { carray2f arr_a = carray2f_init(ydim, xdim, 0.f); printf("arr_a: (%zu, %zu)\n", carray2f_ydim(arr_a), carray2f_xdim(arr_a)); - clist_a tableList = clist_inits; + clist_a tableList = clist_a_init(); // Put in some data. *carray2f_at(&arr_a, y, x) = 3.1415927f; // aa[y][x] clist_a_push_back(&tableList, arr_a); diff --git a/examples/demos.c b/examples/demos.c index e460591b..2ee267e6 100644 --- a/examples/demos.c +++ b/examples/demos.c @@ -39,7 +39,7 @@ using_cvec(ix, int64_t); // ix is just an example tag name. void vectordemo1() { printf("\nVECTORDEMO1\n"); - cvec_ix bignums = cvec_inits; // = (cvec_ix) cvec_inits; if initializing after declaration. + cvec_ix bignums = cvec_ix_init(); cvec_ix_reserve(&bignums, 100); for (size_t i = 10; i <= 100; i += 10) cvec_ix_push_back(&bignums, i * i); @@ -63,7 +63,7 @@ using_cvec_str(); void vectordemo2() { printf("\nVECTORDEMO2\n"); - cvec_str names = cvec_inits; + cvec_str names = cvec_str_init(); cvec_str_emplace_back(&names, "Mary"); cvec_str_emplace_back(&names, "Joe"); cvec_str_emplace_back(&names, "Chris"); @@ -81,7 +81,7 @@ using_clist(ix, int); void listdemo1() { printf("\nLISTDEMO1\n"); - clist_ix nums = clist_inits, nums2 = clist_inits; + clist_ix nums = clist_ix_init(), nums2 = clist_ix_init(); for (int i = 0; i < 10; ++i) clist_ix_push_back(&nums, i); for (int i = 100; i < 110; ++i) diff --git a/examples/inits.c b/examples/inits.c index 1ef722ea..759fc7a7 100644 --- a/examples/inits.c +++ b/examples/inits.c @@ -23,7 +23,7 @@ int main(void) { // CVEC FLOAT / PRIORITY QUEUE - cvec_f floats = cvec_inits; + cvec_f floats = cvec_f_init(); c_push_items(&floats, cvec_f, {4.0f, 2.0f, 5.0f, 3.0f, 1.0f}); c_foreach (i, cvec_f, floats) printf("%.1f ", *i.ref); @@ -82,7 +82,7 @@ int main(void) // CVEC PAIR - cvec_ip pairs1 = cvec_inits; + cvec_ip pairs1 = cvec_ip_init(); c_push_items(&pairs1, cvec_ip, { {5, 6}, {3, 4}, @@ -98,7 +98,7 @@ int main(void) // CLIST PAIR - clist_ip pairs2 = clist_inits; + clist_ip pairs2 = clist_ip_init(); c_push_items(&pairs2, clist_ip, { {5, 6}, {3, 4}, diff --git a/examples/list.c b/examples/list.c index 394d0b38..84ef90f7 100644 --- a/examples/list.c +++ b/examples/list.c @@ -8,7 +8,7 @@ int main() { int k; const int n = 2000000; - clist_fx list = clist_inits; + clist_fx list = clist_fx_init(); stc64_t rng = stc64_init(1234); stc64_uniformf_t dist = stc64_uniformf_init(100.0f, n); int m = 0; diff --git a/examples/ptr.c b/examples/ptr.c index a7b18ad5..98fe0811 100644 --- a/examples/ptr.c +++ b/examples/ptr.c @@ -40,9 +40,9 @@ const char* names[] = { }; int main() { - cvec_pe vec1 = cvec_inits; - cvec_pp vec2 = cvec_inits; - cvec_ps vec3 = cvec_inits; + cvec_pe vec1 = cvec_pe_init(); + cvec_pp vec2 = cvec_pp_init(); + cvec_ps vec3 = cvec_ps_init(); for (int i = 0; i < 6; i += 2) { Person tmp; diff --git a/stc/cdeq.h b/stc/cdeq.h index f714b0cb..4b89b15c 100644 --- a/stc/cdeq.h +++ b/stc/cdeq.h @@ -27,8 +27,6 @@ #include #include -#define cdeq_inits {NULL, NULL} - #define using_cdeq(...) c_MACRO_OVERLOAD(using_cdeq, __VA_ARGS__) #define using_cdeq_2(X, Value) \ using_cdeq_3(X, Value, c_default_compare) @@ -50,14 +48,14 @@ #define using_cdeq_7(X, Value, valueCompareRaw, valueDestroy, valueFromRaw, valueToRaw, RawValue) \ typedefs_cdeq(X, Value, RawValue); \ \ - STC_INLINE cdeq_##X \ - cdeq_##X##_init(void) {cdeq_##X deq = cdeq_inits; return deq;} \ + STC_API cdeq_##X \ + cdeq_##X##_init(void); \ STC_INLINE bool \ - cdeq_##X##_empty(cdeq_##X deq) {return !deq.base || _cdeq_size(&deq) == 0;} \ + cdeq_##X##_empty(cdeq_##X deq) {return !_cdeq_size(&deq);} \ STC_INLINE size_t \ - cdeq_##X##_size(cdeq_##X deq) {return deq.base ? _cdeq_size(&deq) : 0;} \ + cdeq_##X##_size(cdeq_##X deq) {return _cdeq_size(&deq);} \ STC_INLINE size_t \ - cdeq_##X##_capacity(cdeq_##X deq) {return deq.base ? _cdeq_capacity(&deq) : 0;} \ + cdeq_##X##_capacity(cdeq_##X deq) {return _cdeq_cap(&deq);} \ STC_INLINE Value \ cdeq_##X##_value_from_raw(RawValue raw) {return valueFromRaw(raw);} \ STC_INLINE cdeq_##X##_value_t \ @@ -75,13 +73,13 @@ \ STC_INLINE cdeq_##X \ cdeq_##X##_with_size(size_t size, Value null_val) { \ - cdeq_##X x = cdeq_inits; \ + cdeq_##X x = cdeq_##X##_init(); \ cdeq_##X##_resize(&x, size, null_val); \ return x; \ } \ STC_INLINE cdeq_##X \ cdeq_##X##_with_capacity(size_t size) { \ - cdeq_##X x = cdeq_inits; \ + cdeq_##X x = cdeq_##X##_init(); \ _cdeq_##X##_expand(&x, size, false); \ return x; \ } \ @@ -182,7 +180,7 @@ } \ STC_INLINE void \ cdeq_##X##_sort(cdeq_##X* self) { \ - cdeq_##X##_sort_with(self, 0, cdeq_##X##_size(*self), cdeq_##X##_value_compare); \ + cdeq_##X##_sort_with(self, 0, _cdeq_size(self), cdeq_##X##_value_compare); \ } \ \ STC_INLINE cdeq_##X##_iter_t \ @@ -191,7 +189,7 @@ } \ STC_INLINE cdeq_##X##_iter_t \ cdeq_##X##_end(const cdeq_##X* self) { \ - cdeq_##X##_iter_t it = {self->data ? self->data + _cdeq_size(self) : NULL}; return it; \ + cdeq_##X##_iter_t it = {self->data + _cdeq_size(self)}; return it; \ } \ STC_INLINE void \ cdeq_##X##_next(cdeq_##X##_iter_t* it) {++it->ref;} \ @@ -207,11 +205,17 @@ #if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) #define _c_implement_cdeq_7(X, Value, valueCompareRaw, valueDestroy, valueFromRaw, valueToRaw, RawValue) \ +\ + STC_DEF cdeq_##X \ + cdeq_##X##_init(void) { \ + cdeq_##X##_value_t *t = (cdeq_##X##_value_t *) (_cdeq_inits + 2); \ + cdeq_##X deq = {t, t}; return deq; \ + } \ \ STC_DEF void \ cdeq_##X##_push_n(cdeq_##X *self, const cdeq_##X##_rawvalue_t arr[], size_t n) { \ _cdeq_##X##_expand(self, n, false); \ - cdeq_##X##_value_t* p = self->data + cdeq_##X##_size(*self); \ + cdeq_##X##_value_t* p = self->data + _cdeq_size(self); \ for (size_t i=0; i < n; ++i) *p++ = valueFromRaw(arr[i]); \ _cdeq_size(self) += n; \ } \ @@ -227,18 +231,20 @@ STC_DEF void \ cdeq_##X##_del(cdeq_##X* self) { \ cdeq_##X##_clear(self); \ - if (self->base) c_free(_cdeq_alloced(self)); \ + if (_cdeq_alloced(self) != _cdeq_inits) \ + c_free(_cdeq_alloced(self)); \ } \ \ STC_DEF void \ _cdeq_##X##_expand(cdeq_##X* self, size_t n, bool at_front) { \ - size_t len = cdeq_##X##_size(*self), cap = cdeq_##X##_capacity(*self); \ + size_t len = _cdeq_size(self), cap = _cdeq_cap(self); \ size_t nfront = self->data - self->base, nback = cap - (nfront + len); \ if (at_front && nfront >= n || !at_front && nback >= n) \ return; \ if ((len + n)*1.3 > cap) { \ cap = (len + n + 6)*1.8; \ - size_t* rep = (size_t *) c_realloc(_cdeq_alloced(self), 2*sizeof(size_t) + cap*sizeof(Value)); \ + size_t* rep = (size_t *) c_realloc(_cdeq_alloced(self) != _cdeq_inits ? _cdeq_alloced(self) : NULL, \ + 2*sizeof(size_t) + cap*sizeof(Value)); \ rep[0] = len, rep[1] = cap; \ self->base = (cdeq_##X##_value_t *) (rep + 2); \ self->data = self->base + nfront; \ @@ -254,7 +260,7 @@ STC_DEF void \ cdeq_##X##_resize(cdeq_##X* self, size_t size, Value null_val) { \ _cdeq_##X##_expand(self, size, false); \ - size_t i, n = cdeq_##X##_size(*self); \ + size_t i, n = _cdeq_size(self); \ for (i=size; idata + i); \ for (i=n; idata[i] = null_val; \ if (self->data) _cdeq_size(self) = size; \ @@ -269,14 +275,14 @@ } \ STC_DEF void \ cdeq_##X##_push_back(cdeq_##X* self, Value value) { \ - if (!self->data || _cdeq_nfront(self) + _cdeq_size(self) == _cdeq_capacity(self)) \ + if (_cdeq_nfront(self) + _cdeq_size(self) == _cdeq_cap(self)) \ _cdeq_##X##_expand(self, 1, false); \ self->data[_cdeq_size(self)++] = value; \ } \ \ STC_DEF cdeq_##X \ cdeq_##X##_clone(cdeq_##X vec) { \ - size_t len = cdeq_##X##_size(vec); \ + size_t len = _cdeq_size(&vec); \ cdeq_##X out = cdeq_##X##_with_capacity(len); \ cdeq_##X##_insert_range_p(&out, out.data, vec.data, vec.data + len); \ return out; \ @@ -285,7 +291,7 @@ STC_DEF cdeq_##X##_iter_t \ cdeq_##X##_insert_range_p(cdeq_##X* self, cdeq_##X##_value_t* pos, \ const cdeq_##X##_value_t* first, const cdeq_##X##_value_t* finish) { \ - size_t n = finish - first, idx = pos - self->data, size = cdeq_##X##_size(*self); \ + size_t n = finish - first, idx = pos - self->data, size = _cdeq_size(self); \ bool at_front = (idx < size/2); \ _cdeq_##X##_expand(self, n, at_front); \ if (at_front) { \ @@ -335,6 +341,9 @@ return valueCompareRaw(&rx, &ry); \ } +static size_t _cdeq_inits[2] = {0, 0}; +#define _cdeq_alloced(self) (((size_t *) (self)->base) - 2) + #else #define _c_implement_cdeq_7(X, Value, valueCompareRaw, valueDestroy, valueFromRaw, valueToRaw, RawValue) #endif @@ -349,9 +358,8 @@ typedef int(*_cdeq_cmp)(const void*, const void*); STC_EXTERN_IMPORT void qsort(void *start, size_t nitems, size_t size, _cdeq_cmp cmp); #define _cdeq_size(self) ((size_t *) (self)->base)[-2] -#define _cdeq_capacity(self) ((size_t *) (self)->base)[-1] +#define _cdeq_cap(self) ((size_t *) (self)->base)[-1] #define _cdeq_nfront(self) ((self)->data - (self)->base) -#define _cdeq_alloced(self) ((self)->base ? ((size_t *) (self)->base) - 2 : NULL) static inline double c_minf(double x, double y) { return x < y ? x : y; } static inline double c_maxf(double x, double y) { return x > y ? x : y; } diff --git a/stc/clist.h b/stc/clist.h index 1673d71e..c9189ffa 100644 --- a/stc/clist.h +++ b/stc/clist.h @@ -35,7 +35,7 @@ using_clist(ix, int64_t); int main() { - clist_ix list = clist_inits; + clist_ix list = clist_ix_init(); stc64_t rng = stc64_init(12345); int n; for (int i=0; i<1000000; ++i) // one million @@ -83,8 +83,6 @@ int _state; \ } clist_##X##_iter_t -#define clist_inits {NULL} - #define c_emplace_after(self, ctype, pos, ...) do { \ ctype* __self = self; \ ctype##_iter_t __pos = pos; \ @@ -104,7 +102,7 @@ STC_API size_t _clist_size(const clist_void* self); typedef RawValue clist_##X##_rawvalue_t; \ \ STC_INLINE clist_##X \ - clist_##X##_init(void) {clist_##X x = clist_inits; return x;} \ + clist_##X##_init(void) {clist_##X x = {NULL}; return x;} \ STC_INLINE bool \ clist_##X##_empty(clist_##X ls) {return ls.last == NULL;} \ STC_INLINE size_t \ @@ -219,7 +217,7 @@ STC_API size_t _clist_size(const clist_void* self); \ STC_DEF clist_##X \ clist_##X##_clone(clist_##X list) { \ - clist_##X out = clist_inits; \ + clist_##X out = clist_##X##_init(); \ c_foreach_3 (i, clist_##X, list) \ clist_##X##_emplace_back(&out, valueToRaw(i.ref)); \ return out; \ diff --git a/stc/cvec.h b/stc/cvec.h index 64b5dcd9..e8f24ac7 100644 --- a/stc/cvec.h +++ b/stc/cvec.h @@ -27,8 +27,6 @@ #include #include -#define cvec_inits {NULL} - #define using_cvec(...) c_MACRO_OVERLOAD(using_cvec, __VA_ARGS__) #define using_cvec_2(X, Value) \ using_cvec_3(X, Value, c_default_compare) @@ -50,16 +48,14 @@ #define using_cvec_7(X, Value, valueCompareRaw, valueDestroy, valueFromRaw, valueToRaw, RawValue) \ typedefs_cvec(X, Value, RawValue); \ \ - STC_INLINE cvec_##X \ - cvec_##X##_init(void) {cvec_##X vec = cvec_inits; return vec;} \ + STC_API cvec_##X \ + cvec_##X##_init(void); \ STC_INLINE size_t \ - cvec_##X##_size(cvec_##X vec) \ - {return vec.data ? ((const size_t *) vec.data)[-2] : 0;} \ + cvec_##X##_size(cvec_##X vec) { return _cvec_size(&vec); } \ STC_INLINE size_t \ - cvec_##X##_capacity(cvec_##X vec) \ - {return vec.data ? ((const size_t *) vec.data)[-1] : 0;} \ + cvec_##X##_capacity(cvec_##X vec) { return _cvec_cap(&vec); } \ STC_INLINE bool \ - cvec_##X##_empty(cvec_##X vec) {return !cvec_##X##_size(vec);} \ + cvec_##X##_empty(cvec_##X vec) {return !_cvec_size(&vec);} \ STC_INLINE Value \ cvec_##X##_value_from_raw(RawValue raw) {return valueFromRaw(raw);} \ STC_INLINE cvec_##X##_value_t \ @@ -77,13 +73,13 @@ \ STC_INLINE cvec_##X \ cvec_##X##_with_size(size_t size, Value null_val) { \ - cvec_##X x = cvec_inits; \ + cvec_##X x = cvec_##X##_init(); \ cvec_##X##_resize(&x, size, null_val); \ return x; \ } \ STC_INLINE cvec_##X \ cvec_##X##_with_capacity(size_t size) { \ - cvec_##X x = cvec_inits; \ + cvec_##X x = cvec_##X##_init(); \ cvec_##X##_reserve(&x, size); \ return x; \ } \ @@ -158,8 +154,8 @@ STC_INLINE cvec_##X##_value_t* \ cvec_##X##_back(cvec_##X* self) {return self->data + _cvec_size(self) - 1;} \ STC_INLINE cvec_##X##_value_t* \ - cvec_##X##_at(cvec_##X* self, size_t i) { \ - assert(i < cvec_##X##_size(*self)); \ + cvec_##X##_at(cvec_##X* self, size_t i) { \ + assert(i < _cvec_size(self)); \ return self->data + i; \ } \ \ @@ -171,7 +167,7 @@ } \ STC_INLINE void \ cvec_##X##_sort(cvec_##X* self) { \ - cvec_##X##_sort_with(self, 0, cvec_##X##_size(*self), cvec_##X##_value_compare); \ + cvec_##X##_sort_with(self, 0, _cvec_size(self), cvec_##X##_value_compare); \ } \ \ STC_INLINE cvec_##X##_iter_t \ @@ -180,7 +176,7 @@ } \ STC_INLINE cvec_##X##_iter_t \ cvec_##X##_end(const cvec_##X* self) { \ - cvec_##X##_iter_t it = {self->data + cvec_##X##_size(*self)}; return it; \ + cvec_##X##_iter_t it = {self->data + _cvec_size(self)}; return it; \ } \ STC_INLINE void \ cvec_##X##_next(cvec_##X##_iter_t* it) {++it->ref;} \ @@ -196,10 +192,15 @@ #if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) #define _c_implement_cvec_7(X, Value, valueCompareRaw, valueDestroy, valueFromRaw, valueToRaw, RawValue) \ +\ + STC_DEF cvec_##X \ + cvec_##X##_init(void) { \ + cvec_##X vec = {(cvec_##X##_value_t *) (_cvec_inits + 2)}; return vec; \ + } \ \ STC_DEF void \ cvec_##X##_push_n(cvec_##X *self, const cvec_##X##_rawvalue_t arr[], size_t n) { \ - cvec_##X##_reserve(self, cvec_##X##_size(*self) + n); \ + cvec_##X##_reserve(self, _cvec_size(self) + n); \ cvec_##X##_value_t* p = self->data + _cvec_size(self); \ for (size_t i=0; i < n; ++i) *p++ = valueFromRaw(arr[i]); \ _cvec_size(self) += n; \ @@ -215,15 +216,17 @@ STC_DEF void \ cvec_##X##_del(cvec_##X* self) { \ cvec_##X##_clear(self); \ - if (self->data) c_free(_cvec_alloced(self->data)); \ + if (_cvec_alloced(self) != _cvec_inits) \ + c_free(_cvec_alloced(self)); \ } \ \ STC_DEF void \ cvec_##X##_reserve(cvec_##X* self, size_t cap) { \ size_t* rep; \ if (cap > cvec_##X##_capacity(*self)) { \ - size_t len = cvec_##X##_size(*self); \ - rep = (size_t *) c_realloc(_cvec_alloced(self->data), 2 * sizeof(size_t) + cap * sizeof(Value)); \ + size_t len = _cvec_size(self); \ + rep = (size_t *) c_realloc(_cvec_alloced(self) != _cvec_inits ? _cvec_alloced(self) : NULL, \ + 2*sizeof(size_t) + cap*sizeof(Value)); \ self->data = (Value *) (rep + 2); \ rep[0] = len; \ rep[1] = cap; \ @@ -232,7 +235,7 @@ STC_DEF void \ cvec_##X##_resize(cvec_##X* self, size_t size, Value null_val) { \ cvec_##X##_reserve(self, size); \ - size_t i, n = cvec_##X##_size(*self); \ + size_t i, n = _cvec_size(self); \ for (i=size; idata + i); \ for (i=n; idata[i] = null_val; \ if (self->data) _cvec_size(self) = size; \ @@ -240,7 +243,7 @@ \ STC_DEF void \ cvec_##X##_push_back(cvec_##X* self, Value value) { \ - size_t len = cvec_##X##_size(*self); \ + size_t len = _cvec_size(self); \ if (len == cvec_##X##_capacity(*self)) \ cvec_##X##_reserve(self, 4 + len*3/2); \ self->data[_cvec_size(self)++] = value; \ @@ -248,7 +251,7 @@ \ STC_DEF cvec_##X \ cvec_##X##_clone(cvec_##X vec) { \ - size_t len = cvec_##X##_size(vec); \ + size_t len = _cvec_size(&vec); \ cvec_##X out = cvec_##X##_with_capacity(len); \ cvec_##X##_insert_range_p(&out, out.data, vec.data, vec.data + len); \ return out; \ @@ -256,7 +259,7 @@ \ STC_DEF cvec_##X##_iter_t \ cvec_##X##_insert_range_p(cvec_##X* self, cvec_##X##_value_t* pos, const cvec_##X##_value_t* first, const cvec_##X##_value_t* finish) { \ - size_t len = finish - first, idx = pos - self->data, size = cvec_##X##_size(*self); \ + size_t len = finish - first, idx = pos - self->data, size = _cvec_size(self); \ cvec_##X##_iter_t it = {pos}; \ if (len == 0) return it; \ if (size + len > cvec_##X##_capacity(*self)) \ @@ -301,6 +304,9 @@ return valueCompareRaw(&rx, &ry); \ } +static size_t _cvec_inits[2] = {0, 0}; +#define _cvec_alloced(self) (((size_t *) (self)->data) - 2) + #else #define _c_implement_cvec_7(X, Value, valueCompareRaw, valueDestroy, valueFromRaw, valueToRaw, RawValue) #endif @@ -313,8 +319,7 @@ typedef int(*_cvec_cmp)(const void*, const void*); STC_EXTERN_IMPORT void qsort(void *base, size_t nitems, size_t size, _cvec_cmp cmp); - #define _cvec_size(self) ((size_t *) (self)->data)[-2] -#define _cvec_alloced(data) ((data) ? ((size_t *) (data)) - 2 : NULL) +#define _cvec_cap(self) ((size_t *) (self)->data)[-1] #endif -- cgit v1.2.3