diff options
| author | Tyge Løvset <[email protected]> | 2020-07-25 23:00:09 +0200 |
|---|---|---|
| committer | Tyge Løvset <[email protected]> | 2020-07-25 23:00:09 +0200 |
| commit | 613cd9c306b200aaca7403c4c7c678634c409758 (patch) | |
| tree | 89b87063decee02c19324d4262e2bfa17c862951 | |
| parent | d67017280131e8d71dbb57daa853b56f95ccfc13 (diff) | |
| download | STC-modified-613cd9c306b200aaca7403c4c7c678634c409758.tar.gz STC-modified-613cd9c306b200aaca7403c4c7c678634c409758.zip | |
Reverted CArr to CArray again.
| -rw-r--r-- | README.md | 60 | ||||
| -rw-r--r-- | examples/complex.c | 16 | ||||
| -rw-r--r-- | examples/demos.c | 30 | ||||
| -rw-r--r-- | stc/carr.h | 195 | ||||
| -rw-r--r-- | stc/carray.h | 195 | ||||
| -rw-r--r-- | stc/cmap.h | 24 |
6 files changed, 261 insertions, 259 deletions
@@ -4,16 +4,18 @@ STC - C99 Standard Container Library Introduction
------------
-An elegant, typesafe, generic, customizable, user-friendly, consistent, and very efficient standard container library for C99. This is a small headers only library with the most used container components, and a few algorithms:
+An elegant, typesafe, generic, customizable, user-friendly, consistent, and very fast standard container library for C99. This is a small headers only library with the most used container components, and a few algorithms:
+- **stc/carray.h** - Dynamic generic **multi-dimensional array**, implemented as a single contiguous section of memory.
+- **stc/cbitset.h** - Bitset similar to c++ std::bitset or boost::dynamic_bitset.
+- **stc/clist.h** - A genric circular singly **linked list**, can be used as a **queue** - supports *pushBack, pushFront, and popFront* - **stc/cmap.h** - A generic **unordered map** implemented as open hashing without tombstones. Highly customizable and fast.
+- **stc/cset.h** - A generic **unordered set** implemented in tandem with *unordered map*
- **stc/cstr.h** - Compact and powerful **string** class.
- **stc/cvec.h** - Dynamic generic **vector** class, works well as a **stack**.
-- **stc/cmap.h** - A generic **unordered map** implemented as open hashing without tombstones. Highly customizable and fast.
-- **stc/cset.h** - A generic **unordered set** implemented in tandem with *unordered map*
-- **stc/carr.h** - Dynamic generic **multi-dimensional array**, implemented as a single contiguous section of memory.
-- **stc/clist.h** - A genric circular singly **linked list**, can be used as a **queue** - supports *pushBack, pushFront, and popFront* in *O*(1). Also contains various *splice* functions and (merge) *sort*.
+- **stc/cvecpq.h** - Priority queue adapter for **cvec.h**, implemented as a **heap**.
+in *O*(1). Also contains various *splice* functions and (merge) *sort*.
- **stc/coption.h** - Implementation of *getopt_long*-"like" function, *coption_get*, to parse command line arguments.
- **stc/crandom.h** - A few very efficent modern random number generators *pcg32* and *sfc64*. It also implements the crypto-strong *siphash* algorithm.
-- **stc/cdefs.h** - A small common include file with some general definitions.
+- **stc/cdefs.h** - A common include file with some general definitions.
The usage of the containers is similar to the C++ standard containers, so it should be easier for those who are familiar with them.
@@ -95,7 +97,7 @@ The containers are memory efficent, i.e. they occupy as little memory as practic - **CList**: Representation: one pointer size. Each node allocates block storing value and next pointer.
- **CSet**: Representation: 4 pointers size. CSet uses one table of keys, and one table of "used/hash-value", which occupies only one byte per bucket.
- **CMap**: Same as CSet, but this uses a table of (key, value) pairs, not only keys.
-- **CArr**: CArr1, CArr2 and CArr3. Representation: One pointers, plus 1, 2, or 3 size_t variables to store dimensions. Elements are stored as one block of heap memory.
+- **CArray**: CArray1, CArray2 and CArray3. Representation: One pointers, plus 1, 2, or 3 size_t variables to store dimensions. Elements are stored as one block of heap memory.
CMap, CSet and CVec discussion
----------------------------
@@ -131,19 +133,19 @@ Also look at **examples/advanced.c**, it demonstrates how to use a custom struct Example usages
--------------
The first example has a very complex nested container type, which demonstrates the power of this library. Look at the simpler examples below to understand it better. The example adds an element into the data structure, and then accesses it. The type used, with c++ template syntax is:
-**CMapMap**< **CStr**, **CMapMap**< *int*, **CList**< **CArr2**< *float* >>>>
+**CMapMap**< **CStr**, **CMapMap**< *int*, **CList**< **CArray2**< *float* >>>>
Note: The *cmap_sm_destroy(&theMap)* call below, will destroy all the nested containers including the memory allocated for CStr keys in theMap object.
```
#include <stc/cstr.h>
#include <stc/cmap.h>
#include <stc/clist.h>
-#include <stc/carr.h>
+#include <stc/carray.h>
void verify_destroy(float* v) {printf("destroy %g\n", *v);}
-declare_CArr(f, float, verify_destroy); // you should omit the last argument - float type need no destroy.
-declare_CList(t2, CArr2_f, carr2_f_destroy, c_noCompare);
+declare_CArray(f, float, verify_destroy); // you should omit the last argument - float type need no destroy.
+declare_CList(t2, CArray2_f, carray2_f_destroy, c_noCompare);
declare_CMap(il, int, CList_t2, clist_t2_destroy);
declare_CMap_str(sm, CMap_il, cmap_il_destroy);
@@ -153,20 +155,20 @@ int main() { CMap_sm theMap = cmap_init;
{
// Construct.
- CArr2_f table = carr2_f_make(xdim, ydim, 0.f);
+ CArray2_f table = carray2_f_make(xdim, ydim, 0.f);
CList_t2 tableList = clist_init;
CMap_il listMap = cmap_init;
// Put in some data.
- carr2_f_data(table, x)[y] = 3.1415927; // table[x][y]
+ carray2_f_data(table, x)[y] = 3.1415927; // table[x][y]
clist_t2_pushBack(&tableList, table);
cmap_il_put(&listMap, entry, tableList);
cmap_sm_put(&theMap, "First", listMap);
}
// Access the data entry
- CArr2_f table = clist_back(cmap_il_get(&cmap_sm_get(&theMap, "First")->value, entry)->value);
- printf("value is: %f\n", carr2_f_value(table, x, y));
+ CArray2_f table = clist_back(cmap_il_get(&cmap_sm_get(&theMap, "First")->value, entry)->value);
+ printf("value is: %f\n", carray2_f_value(table, x, y));
cmap_sm_destroy(&theMap); // free up the whole shebang!
}
@@ -310,27 +312,27 @@ int main() { clist_i_destroy(&list);
}
```
-**CArr**. 1D, 2D and 3D arrays, heap allocated in one memory block. *CArr3* can have sub-array "views" of *CArr2* and *CArr1* etc., as shown in the following example.
+**CArray**. 1D, 2D and 3D arrays, heap allocated in one memory block. *CArray3* can have sub-array "views" of *CArray2* and *CArray1* etc., as shown in the following example.
```
#include <stdio.h>
-#include <stc/carr.h>
-declare_CArr(f, float);
+#include <stc/carray.h>
+declare_CArray(f, float);
int main()
{
- CArr3_f a3 = carr3_f_make(30, 20, 10, 0.f);
- carr3_f_data(a3, 5, 4)[3] = 10.2f; // a3[5][4][3]
- CArr2_f a2 = carr3_f_at(a3, 5); // sub-array reference (no data copy).
+ CArray3_f a3 = carray3_f_make(30, 20, 10, 0.f);
+ carray3_f_data(a3, 5, 4)[3] = 10.2f; // a3[5][4][3]
+ CArray2_f a2 = carray3_f_at(a3, 5); // sub-array reference (no data copy).
- printf("%f\n", carr2_f_value(a2, 4, 3)); // readonly lookup a2[4][3] (=10.2f)
- printf("%f\n", carr2_f_data(a2, 4)[3]); // same, but this is writable.
- printf("%f\n", carr2_f_at(a2, 4).data[3]); // same, via sub-array access.
+ printf("%f\n", carray2_f_value(a2, 4, 3)); // readonly lookup a2[4][3] (=10.2f)
+ printf("%f\n", carray2_f_data(a2, 4)[3]); // same, but this is writable.
+ printf("%f\n", carray2_f_at(a2, 4).data[3]); // same, via sub-array access.
- printf("%f\n", carr3_f_value(a3, 5, 4, 3)); // same data location, via a3 array.
- printf("%f\n", carr3_f_data(a3, 5, 4)[3]);
- printf("%f\n", carr3_f_at2(a3, 5, 4).data[3]);
+ printf("%f\n", carray3_f_value(a3, 5, 4, 3)); // same data location, via a3 array.
+ printf("%f\n", carray3_f_data(a3, 5, 4)[3]);
+ printf("%f\n", carray3_f_at2(a3, 5, 4).data[3]);
- carr2_f_destroy(&a2); // does nothing, since it is a sub-array.
- carr3_f_destroy(&a3); // also invalidates a2.
+ carray2_f_destroy(&a2); // does nothing, since it is a sub-array.
+ carray3_f_destroy(&a3); // also invalidates a2.
}
```
diff --git a/examples/complex.c b/examples/complex.c index d4800260..a52bd175 100644 --- a/examples/complex.c +++ b/examples/complex.c @@ -1,12 +1,12 @@ #include <stc/cstr.h>
#include <stc/cmap.h>
#include <stc/clist.h>
-#include <stc/carr.h>
+#include <stc/carray.h>
void check_destroy(float* v) {printf("destroy %g\n", *v);}
-declare_CArr(f, float, check_destroy); // normally omit the last argument - float type need no destroy.
-declare_CList(t2, CArr2_f, carr2_f_destroy, c_noCompare);
+declare_CArray(f, float, check_destroy); // normally omit the last argument - float type need no destroy.
+declare_CList(t2, CArray2_f, carray2_f_destroy, c_noCompare);
declare_CMap(il, int, CList_t2, clist_t2_destroy);
declare_CMap_str(sm, CMap_il, cmap_il_destroy);
@@ -17,20 +17,20 @@ int main() { CMap_sm theMap = cmap_init;
{ // Construct.
- CArr2_f table = carr2_f_make(ydim, xdim, 0.f);
- printf("table: (%zu, %zu)\n", carr2_ydim(table), carr2_xdim(table));
+ CArray2_f table = carray2_f_make(ydim, xdim, 0.f);
+ printf("table: (%zu, %zu)\n", carray2_ydim(table), carray2_xdim(table));
CList_t2 tableList = clist_init;
CMap_il listMap = cmap_init;
// Put in some data.
- carr2_f_data(table, y)[x] = 3.1415927; // table[y][x]
+ carray2_f_data(table, y)[x] = 3.1415927; // table[y][x]
clist_t2_pushBack(&tableList, table);
cmap_il_put(&listMap, tableKey, tableList);
cmap_sm_put(&theMap, strKey, listMap);
}
{ // Access the data entry
- CArr2_f table = clist_back(cmap_il_find(&cmap_sm_find(&theMap, strKey)->value, tableKey)->value);
- printf("value (%d, %d) is: %f\n", y, x, carr2_f_value(table, y, x));
+ CArray2_f table = clist_back(cmap_il_find(&cmap_sm_find(&theMap, strKey)->value, tableKey)->value);
+ printf("value (%d, %d) is: %f\n", y, x, carray2_f_value(table, y, x));
}
cmap_sm_destroy(&theMap); // free up the whole shebang!
diff --git a/examples/demos.c b/examples/demos.c index 9eec136a..e6e76d7a 100644 --- a/examples/demos.c +++ b/examples/demos.c @@ -1,6 +1,6 @@ #include <stc/cvec.h>
#include <stc/clist.h>
-#include <stc/carr.h>
+#include <stc/carray.h>
#include <stc/cmap.h>
#include <stc/cstr.h>
@@ -174,28 +174,28 @@ void mapdemo3() -declare_CArr(f, float);
+declare_CArray(f, float);
void arraydemo1()
{
printf("\nARRAYDEMO1\n");
- CArr3_f a3 = carr3_f_make(30, 20, 10, 0.f);
- carr3_f_data(a3, 5, 4)[3] = 10.2f; // a3[5][4][3]
- CArr2_f a2 = carr3_f_at(a3, 5); // sub-array reference (no data copy).
+ CArray3_f a3 = carray3_f_make(30, 20, 10, 0.f);
+ carray3_f_data(a3, 5, 4)[3] = 10.2f; // a3[5][4][3]
+ CArray2_f a2 = carray3_f_at(a3, 5); // sub-array reference (no data copy).
- printf("a3: %zu: (%zu, %zu, %zu) = %zu\n", sizeof(a3), carr3_xdim(a3), carr3_ydim(a3), carr3_zdim(a3), carr3_size(a3));
- printf("a2: %zu: (%zu, %zu) = %zu\n", sizeof(a2), carr2_xdim(a2), carr2_ydim(a2), carr2_size(a2));
+ printf("a3: %zu: (%zu, %zu, %zu) = %zu\n", sizeof(a3), carray3_xdim(a3), carray3_ydim(a3), carray3_zdim(a3), carray3_size(a3));
+ printf("a2: %zu: (%zu, %zu) = %zu\n", sizeof(a2), carray2_xdim(a2), carray2_ydim(a2), carray2_size(a2));
- printf("%f\n", carr2_f_value(a2, 4, 3)); // readonly lookup a2[4][3] (=10.2f)
- printf("%f\n", carr2_f_data(a2, 4)[3]); // same, but this is writable.
- printf("%f\n", carr2_f_at(a2, 4).data[3]); // same, via sub-array access.
+ printf("%f\n", carray2_f_value(a2, 4, 3)); // readonly lookup a2[4][3] (=10.2f)
+ printf("%f\n", carray2_f_data(a2, 4)[3]); // same, but this is writable.
+ printf("%f\n", carray2_f_at(a2, 4).data[3]); // same, via sub-array access.
- printf("%f\n", carr3_f_value(a3, 5, 4, 3)); // same data location, via a3 array.
- printf("%f\n", carr3_f_data(a3, 5, 4)[3]);
- printf("%f\n", carr3_f_at2(a3, 5, 4).data[3]);
+ printf("%f\n", carray3_f_value(a3, 5, 4, 3)); // same data location, via a3 array.
+ printf("%f\n", carray3_f_data(a3, 5, 4)[3]);
+ printf("%f\n", carray3_f_at2(a3, 5, 4).data[3]);
- carr2_f_destroy(&a2); // does nothing, since it is a sub-array.
- carr3_f_destroy(&a3); // also invalidates a2.
+ carray2_f_destroy(&a2); // does nothing, since it is a sub-array.
+ carray3_f_destroy(&a3); // also invalidates a2.
}
diff --git a/stc/carr.h b/stc/carr.h deleted file mode 100644 index 0e5a65c9..00000000 --- a/stc/carr.h +++ /dev/null @@ -1,195 +0,0 @@ -/* MIT License
- *
- * Copyright (c) 2020 Tyge Løvset, NORCE, www.norceresearch.no
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#ifndef CARR__H__
-#define CARR__H__
-
-#include <stdlib.h>
-#include "cdefs.h"
-
-/*
- Multi-dimensional generic array allocated as one block of heap-memory.
- // demo:
-#include <stc/carr.h>
-declare_CArr(f, float);
-
-int main()
-{
- CArr3_f a3 = carr3_f_make(30, 20, 10, 0.f);
- carr3_f_data(a3, 5, 4)[3] = 10.2f; // a3[5][4][3]
- CArr2_f a2 = carr3_f_at(a3, 5); // sub-array reference (no data copy).
-
- printf("%f\n", carr2_f_value(a2, 4, 3)); // readonly lookup a2[4][3] (=10.2f)
- printf("%f\n", carr2_f_data(a2, 4)[3]); // same, but this is writable.
- printf("%f\n", carr2_f_at(a2, 4).data[3]); // same, via sub-array access.
-
- printf("%f\n", carr3_f_value(a3, 5, 4, 3)); // same data location, via a3 array.
- printf("%f\n", carr3_f_data(a3, 5, 4)[3]);
- printf("%f\n", carr3_f_at2(a3, 5, 4).data[3]);
-
- carr2_f_destroy(&a2); // does nothing, since it is a sub-array.
- carr3_f_destroy(&a3); // also invalidates a2.
-}
-*/
-
-#define carr1_xdim(a) ((a)._xdim & _carr_SUB)
-#define carr1_size(a) carr1_xdim(a)
-
-#define carr2_xdim(a) carr1_xdim(a)
-#define carr2_ydim(a) _carr2_ydim(&(a)._yxdim)
-#define carr2_size(a) ((a)._yxdim)
-
-#define carr3_xdim(a) carr1_xdim(a)
-#define carr3_ydim(a) carr2_ydim(a)
-#define carr3_zdim(a) ((a)._zdim)
-#define carr3_size(a) _carr3_size(&(a)._zdim)
-
-#define _carr_SUB (SIZE_MAX >> 1)
-#define _carr_OWN (_carr_SUB + 1)
-
-static inline size_t _carr2_ydim(const size_t* yxdim) {
- return yxdim[0] / (yxdim[-1] & _carr_SUB);
-}
-static inline size_t _carr3_size(const size_t* zdim) {
- return zdim[0] * zdim[-1];
-}
-
-
-#define declare_CArr(...) c_MACRO_OVERLOAD(declare_CArr, __VA_ARGS__)
-
-#define declare_CArr_2(tag, Value) \
- declare_CArr_3(tag, Value, c_defaultDestroy)
-
-
-#define declare_CArr_3(tag, Value, valueDestroy) \
- typedef struct { \
- Value *data; \
- size_t _xdim; \
- } CArr1_##tag; \
- \
- typedef struct { \
- Value *data; \
- size_t _xdim, _yxdim; \
- } CArr2_##tag; \
- \
- typedef struct { \
- Value *data; \
- size_t _xdim, _yxdim, _zdim; \
- } CArr3_##tag; \
- \
- static inline CArr1_##tag \
- carr1_##tag##_make(size_t xdim, Value val) { \
- Value* m = c_new_N(Value, xdim); \
- for (size_t i=0; i<xdim; ++i) m[i] = val; \
- CArr1_##tag a = {m, xdim | _carr_OWN}; \
- return a; \
- } \
- static inline CArr2_##tag \
- carr2_##tag##_make(size_t ydim, size_t xdim, Value val) { \
- const size_t n = ydim * xdim; \
- Value* m = c_new_N(Value, n); \
- for (size_t i=0; i<n; ++i) m[i] = val; \
- CArr2_##tag a = {m, xdim | _carr_OWN, ydim * xdim}; \
- return a; \
- } \
- static inline CArr3_##tag \
- carr3_##tag##_make(size_t zdim, size_t ydim, size_t xdim, Value val) { \
- const size_t n = zdim * ydim * xdim; \
- Value* m = c_new_N(Value, n); \
- for (size_t i=0; i<n; ++i) m[i] = val; \
- CArr3_##tag a = {m, xdim | _carr_OWN, ydim * xdim, zdim}; \
- return a; \
- } \
- \
- static inline CArr1_##tag \
- carr1_##tag##_from(size_t xdim, Value* array, bool own) { \
- CArr1_##tag a = {array, xdim | (own ? _carr_OWN : 0)}; \
- return a; \
- } \
- static inline CArr2_##tag \
- carr2_##tag##_from(size_t ydim, size_t xdim, Value* array, bool own) { \
- CArr2_##tag a = {array, xdim | (own ? _carr_OWN : 0), ydim * xdim}; \
- return a; \
- } \
- static inline CArr3_##tag \
- carr3_##tag##_from(size_t zdim, size_t ydim, size_t xdim, Value* array, bool own) { \
- CArr3_##tag a = {array, xdim | (own ? _carr_OWN : 0), ydim * xdim, zdim}; \
- return a; \
- } \
- \
- static inline void \
- carr1_##tag##_destroy(CArr1_##tag* self) { \
- if (self->_xdim & _carr_OWN) { \
- size_t n = carr1_size(*self); Value* a = self->data; \
- while (n--) valueDestroy(&a[n]); free(a); \
- } \
- } \
- static inline void \
- carr2_##tag##_destroy(CArr2_##tag* self) { \
- if (self->_xdim & _carr_OWN) { \
- size_t n = carr2_size(*self); Value* a = self->data; \
- while (n--) valueDestroy(&a[n]); free(a); \
- } \
- } \
- static inline void \
- carr3_##tag##_destroy(CArr3_##tag* self) { \
- if (self->_xdim & _carr_OWN) { \
- size_t n = carr3_size(*self); Value* a = self->data; \
- while (n--) valueDestroy(&a[n]); free(a); \
- } \
- } \
- \
- static inline CArr1_##tag \
- carr2_##tag##_at(CArr2_##tag a, size_t y) { \
- CArr1_##tag sub = {a.data + y*carr2_xdim(a), carr2_xdim(a)}; \
- return sub; \
- } \
- static inline Value* \
- carr2_##tag##_data(CArr2_##tag a, size_t y) { \
- return a.data + y*carr2_xdim(a); \
- } \
- static inline Value \
- carr2_##tag##_value(CArr2_##tag a, size_t y, size_t x) { \
- return a.data[ y*carr2_xdim(a) + x ]; \
- } \
- \
- static inline CArr2_##tag \
- carr3_##tag##_at(CArr3_##tag a, size_t z) { \
- CArr2_##tag sub = {a.data + z*a._yxdim, carr3_xdim(a), a._yxdim}; \
- return sub; \
- } \
- static inline CArr1_##tag \
- carr3_##tag##_at2(CArr3_##tag a, size_t z, size_t y) { \
- CArr1_##tag sub = {a.data + z*a._yxdim + y*carr3_xdim(a), carr3_xdim(a)}; \
- return sub; \
- } \
- static inline Value* \
- carr3_##tag##_data(CArr3_##tag a, size_t z, size_t y) { \
- return a.data + z*a._yxdim + y*carr3_xdim(a); \
- } \
- static inline Value \
- carr3_##tag##_value(CArr3_##tag a, size_t z, size_t y, size_t x) { \
- return a.data[ z*a._yxdim + y*carr3_xdim(a) + x ]; \
- } \
- typedef Value CArrValue_##tag
-
-#endif
diff --git a/stc/carray.h b/stc/carray.h new file mode 100644 index 00000000..5bacbe4c --- /dev/null +++ b/stc/carray.h @@ -0,0 +1,195 @@ +/* MIT License
+ *
+ * Copyright (c) 2020 Tyge Løvset, NORCE, www.norceresearch.no
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef CARR__H__
+#define CARR__H__
+
+#include <stdlib.h>
+#include "cdefs.h"
+
+/*
+ Multi-dimensional generic array allocated as one block of heap-memory.
+ // demo:
+#include <stc/carray.h>
+declare_CArray(f, float);
+
+int main()
+{
+ CArray3_f a3 = carray3_f_make(30, 20, 10, 0.f);
+ carray3_f_data(a3, 5, 4)[3] = 10.2f; // a3[5][4][3]
+ CArray2_f a2 = carray3_f_at(a3, 5); // sub-array reference (no data copy).
+
+ printf("%f\n", carray2_f_value(a2, 4, 3)); // readonly lookup a2[4][3] (=10.2f)
+ printf("%f\n", carray2_f_data(a2, 4)[3]); // same, but this is writable.
+ printf("%f\n", carray2_f_at(a2, 4).data[3]); // same, via sub-array access.
+
+ printf("%f\n", carray3_f_value(a3, 5, 4, 3)); // same data location, via a3 array.
+ printf("%f\n", carray3_f_data(a3, 5, 4)[3]);
+ printf("%f\n", carray3_f_at2(a3, 5, 4).data[3]);
+
+ carray2_f_destroy(&a2); // does nothing, since it is a sub-array.
+ carray3_f_destroy(&a3); // also invalidates a2.
+}
+*/
+
+#define carray1_xdim(a) ((a)._xdim & _carray_SUB)
+#define carray1_size(a) carray1_xdim(a)
+
+#define carray2_xdim(a) carray1_xdim(a)
+#define carray2_ydim(a) _carray2_ydim(&(a)._yxdim)
+#define carray2_size(a) ((a)._yxdim)
+
+#define carray3_xdim(a) carray1_xdim(a)
+#define carray3_ydim(a) carray2_ydim(a)
+#define carray3_zdim(a) ((a)._zdim)
+#define carray3_size(a) _carray3_size(&(a)._zdim)
+
+#define _carray_SUB (SIZE_MAX >> 1)
+#define _carray_OWN (_carray_SUB + 1)
+
+static inline size_t _carray2_ydim(const size_t* yxdim) {
+ return yxdim[0] / (yxdim[-1] & _carray_SUB);
+}
+static inline size_t _carray3_size(const size_t* zdim) {
+ return zdim[0] * zdim[-1];
+}
+
+
+#define declare_CArray(...) c_MACRO_OVERLOAD(declare_CArray, __VA_ARGS__)
+
+#define declare_CArray_2(tag, Value) \
+ declare_CArray_3(tag, Value, c_defaultDestroy)
+
+
+#define declare_CArray_3(tag, Value, valueDestroy) \
+ typedef struct { \
+ Value *data; \
+ size_t _xdim; \
+ } CArray1_##tag; \
+ \
+ typedef struct { \
+ Value *data; \
+ size_t _xdim, _yxdim; \
+ } CArray2_##tag; \
+ \
+ typedef struct { \
+ Value *data; \
+ size_t _xdim, _yxdim, _zdim; \
+ } CArray3_##tag; \
+ \
+ static inline CArray1_##tag \
+ carray1_##tag##_make(size_t xdim, Value val) { \
+ Value* m = c_new_N(Value, xdim); \
+ for (size_t i=0; i<xdim; ++i) m[i] = val; \
+ CArray1_##tag a = {m, xdim | _carray_OWN}; \
+ return a; \
+ } \
+ static inline CArray2_##tag \
+ carray2_##tag##_make(size_t ydim, size_t xdim, Value val) { \
+ const size_t n = ydim * xdim; \
+ Value* m = c_new_N(Value, n); \
+ for (size_t i=0; i<n; ++i) m[i] = val; \
+ CArray2_##tag a = {m, xdim | _carray_OWN, ydim * xdim}; \
+ return a; \
+ } \
+ static inline CArray3_##tag \
+ carray3_##tag##_make(size_t zdim, size_t ydim, size_t xdim, Value val) { \
+ const size_t n = zdim * ydim * xdim; \
+ Value* m = c_new_N(Value, n); \
+ for (size_t i=0; i<n; ++i) m[i] = val; \
+ CArray3_##tag a = {m, xdim | _carray_OWN, ydim * xdim, zdim}; \
+ return a; \
+ } \
+ \
+ static inline CArray1_##tag \
+ carray1_##tag##_from(size_t xdim, Value* array, bool own) { \
+ CArray1_##tag a = {array, xdim | (own ? _carray_OWN : 0)}; \
+ return a; \
+ } \
+ static inline CArray2_##tag \
+ carray2_##tag##_from(size_t ydim, size_t xdim, Value* array, bool own) { \
+ CArray2_##tag a = {array, xdim | (own ? _carray_OWN : 0), ydim * xdim}; \
+ return a; \
+ } \
+ static inline CArray3_##tag \
+ carray3_##tag##_from(size_t zdim, size_t ydim, size_t xdim, Value* array, bool own) { \
+ CArray3_##tag a = {array, xdim | (own ? _carray_OWN : 0), ydim * xdim, zdim}; \
+ return a; \
+ } \
+ \
+ static inline void \
+ carray1_##tag##_destroy(CArray1_##tag* self) { \
+ if (self->_xdim & _carray_OWN) { \
+ size_t n = carray1_size(*self); Value* a = self->data; \
+ while (n--) valueDestroy(&a[n]); free(a); \
+ } \
+ } \
+ static inline void \
+ carray2_##tag##_destroy(CArray2_##tag* self) { \
+ if (self->_xdim & _carray_OWN) { \
+ size_t n = carray2_size(*self); Value* a = self->data; \
+ while (n--) valueDestroy(&a[n]); free(a); \
+ } \
+ } \
+ static inline void \
+ carray3_##tag##_destroy(CArray3_##tag* self) { \
+ if (self->_xdim & _carray_OWN) { \
+ size_t n = carray3_size(*self); Value* a = self->data; \
+ while (n--) valueDestroy(&a[n]); free(a); \
+ } \
+ } \
+ \
+ static inline CArray1_##tag \
+ carray2_##tag##_at(CArray2_##tag a, size_t y) { \
+ CArray1_##tag sub = {a.data + y*carray2_xdim(a), carray2_xdim(a)}; \
+ return sub; \
+ } \
+ static inline Value* \
+ carray2_##tag##_data(CArray2_##tag a, size_t y) { \
+ return a.data + y*carray2_xdim(a); \
+ } \
+ static inline Value \
+ carray2_##tag##_value(CArray2_##tag a, size_t y, size_t x) { \
+ return a.data[ y*carray2_xdim(a) + x ]; \
+ } \
+ \
+ static inline CArray2_##tag \
+ carray3_##tag##_at(CArray3_##tag a, size_t z) { \
+ CArray2_##tag sub = {a.data + z*a._yxdim, carray3_xdim(a), a._yxdim}; \
+ return sub; \
+ } \
+ static inline CArray1_##tag \
+ carray3_##tag##_at2(CArray3_##tag a, size_t z, size_t y) { \
+ CArray1_##tag sub = {a.data + z*a._yxdim + y*carray3_xdim(a), carray3_xdim(a)}; \
+ return sub; \
+ } \
+ static inline Value* \
+ carray3_##tag##_data(CArray3_##tag a, size_t z, size_t y) { \
+ return a.data + z*a._yxdim + y*carray3_xdim(a); \
+ } \
+ static inline Value \
+ carray3_##tag##_value(CArray3_##tag a, size_t z, size_t y, size_t x) { \
+ return a.data[ z*a._yxdim + y*carray3_xdim(a) + x ]; \
+ } \
+ typedef Value CArrayValue_##tag
+
+#endif
@@ -55,7 +55,7 @@ int main(void) { #define cmap_init {NULL, NULL, 0, 0, 0.85f, 0.15f}
#define cmap_size(m) ((size_t) (m).size)
-#define cmap_bucketCount(m) ((size_t) (m).buckets)
+#define cmap_bucketCount(m) ((size_t) (m).bucketCount)
#define cset_init cmap_init
#define cset_size(s) cmap_size(s)
#define cset_bucketCount(s) cmap_bucketCount(s)
@@ -148,7 +148,7 @@ typedef RawKey CType##RawKey_##tag, ctype##_##tag##_rawkey_t; \ typedef struct { \
CType##Entry_##tag* table; \
uint8_t* _hashx; \
- uint32_t size, buckets; \
+ uint32_t size, bucketCount; \
float maxLoadFactor; \
float shrinkLimitFactor; \
} CType##_##tag; \
@@ -173,9 +173,9 @@ ctype##_##tag##_setLoadFactors(CType##_##tag* self, float max, float shrink) { \ } \
STC_API CType##Entry_##tag* \
ctype##_##tag##_find(const CType##_##tag* self, CType##RawKey_##tag rawKey); \
-STC_FORCE_INLINE CType##Entry_##tag* \
+STC_FORCE_INLINE CType##Entry_##tag* /* alias */ \
ctype##_##tag##_get(const CType##_##tag* self, CType##RawKey_##tag rawKey) \
- {return ctype##_##tag##_find(self, rawKey);} /* alias */ \
+ {return ctype##_##tag##_find(self, rawKey);} \
STC_API CType##Entry_##tag* /* similar to c++ std::map.insert_or_assign(): */ \
ctype##_##tag##_put(CType##_##tag* self, OPT_2_##ctype(CType##RawKey_##tag rawKey, Value value)); \
OPT_1_##ctype(STC_API CType##Entry_##tag* /* similar to c++ std::map.operator[](): */ \
@@ -219,7 +219,7 @@ ctype##_##tag##_pushN(CType##_##tag* self, const CType##Input_##tag in[], size_t \
STC_INLINE void ctype##_##tag##_wipe_(CType##_##tag* self) { \
if (self->size == 0) return; \
- CType##Entry_##tag* e = self->table, *end = e + self->buckets; \
+ CType##Entry_##tag* e = self->table, *end = e + self->bucketCount; \
uint8_t *hx = self->_hashx; \
for (; e != end; ++e) if (*hx++) ctype##entry_##tag##_destroy(e); \
} \
@@ -233,14 +233,14 @@ STC_API void ctype##_##tag##_destroy(CType##_##tag* self) { \ STC_API void ctype##_##tag##_clear(CType##_##tag* self) { \
ctype##_##tag##_wipe_(self); \
self->size = 0; \
- memset(self->_hashx, 0, self->buckets); \
+ memset(self->_hashx, 0, self->bucketCount); \
} \
\
STC_API size_t \
ctype##_##tag##_bucket(const CType##_##tag* self, const CType##RawKey_##tag* rawKeyPtr, uint32_t* hxPtr) { \
uint32_t hash = keyHashRaw(rawKeyPtr, sizeof(CType##RawKey_##tag)); \
uint32_t sx, hx = (hash & chash_HASH) | chash_USED; \
- size_t cap = self->buckets; \
+ size_t cap = self->bucketCount; \
size_t idx = chash_reduce(hash, cap); \
uint8_t* hashx = self->_hashx; \
while ((sx = hashx[idx])) { \
@@ -263,7 +263,7 @@ ctype##_##tag##_find(const CType##_##tag* self, CType##RawKey_##tag rawKey) { \ } \
\
static inline void ctype##_##tag##_reserveExpand_(CType##_##tag* self) { \
- if (self->size + 1 >= self->buckets * self->maxLoadFactor) \
+ if (self->size + 1 >= self->bucketCount * self->maxLoadFactor) \
ctype##_##tag##_reserve(self, 7 + self->size * 3 / 2); \
} \
\
@@ -302,7 +302,7 @@ ctype##_##tag##_at(CType##_##tag* self, CType##RawKey_##tag rawKey, Value initVa \
STC_API size_t \
ctype##_##tag##_reserve(CType##_##tag* self, size_t newcap) { \
- size_t oldcap = self->buckets; \
+ size_t oldcap = self->bucketCount; \
if (self->size > newcap) return oldcap; \
newcap /= self->maxLoadFactor; newcap |= 1; \
CType##_##tag tmp = { \
@@ -330,7 +330,7 @@ ctype##_##tag##_reserve(CType##_##tag* self, size_t newcap) { \ \
STC_API bool \
ctype##_##tag##_eraseEntry(CType##_##tag* self, CType##Entry_##tag* entry) { \
- size_t i = chash_entryIndex(*self, entry), j = i, k, cap = self->buckets; \
+ size_t i = chash_entryIndex(*self, entry), j = i, k, cap = self->bucketCount; \
CType##Entry_##tag* slot = self->table; \
uint8_t* hashx = self->_hashx; \
CType##RawKey_##tag r; \
@@ -355,7 +355,7 @@ STC_API bool \ ctype##_##tag##_erase(CType##_##tag* self, CType##RawKey_##tag rawKey) { \
if (self->size == 0) \
return false; \
- size_t cap = self->buckets; \
+ size_t cap = self->bucketCount; \
if (self->size < cap * self->shrinkLimitFactor && cap * sizeof(CType##Entry_##tag) > 1024) \
ctype##_##tag##_reserve(self, self->size * 6 / 5); \
uint32_t hx; \
@@ -366,7 +366,7 @@ ctype##_##tag##_erase(CType##_##tag* self, CType##RawKey_##tag rawKey) { \ STC_API ctype##_##tag##_iter_t \
ctype##_##tag##_begin(CType##_##tag* map) { \
uint8_t* hx = map->_hashx; \
- CType##Entry_##tag* e = map->table, *end = e + map->buckets; \
+ CType##Entry_##tag* e = map->table, *end = e + map->bucketCount; \
while (e != end && !*hx) ++e, ++hx; \
ctype##_##tag##_iter_t it = {e == end ? NULL : e, end, hx}; return it; \
} \
|
