summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--benchmarks/others/carray_v1.h215
-rw-r--r--docs/carray_api.md123
-rw-r--r--examples/complex.c43
-rw-r--r--examples/demos.c23
-rw-r--r--stc/carray.h280
5 files changed, 454 insertions, 230 deletions
diff --git a/benchmarks/others/carray_v1.h b/benchmarks/others/carray_v1.h
new file mode 100644
index 00000000..fdd69013
--- /dev/null
+++ b/benchmarks/others/carray_v1.h
@@ -0,0 +1,215 @@
+/* MIT License
+ *
+ * Copyright (c) 2021 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 CARRAY_H_INCLUDED
+#define CARRAY_H_INCLUDED
+
+#include <stdlib.h>
+#include "ccommon.h"
+
+/*
+ Multi-dimensional generic array allocated as one block of heap-memory.
+ // demo:
+#include <stdio.h>
+#include "stc/carray.h"
+using_carray3(f, float);
+
+int main()
+{
+ carray3f a3 = carray3f_init(30, 20, 10, 0.0f);
+ *carray3f_at(&a3, 5, 4, 3) = 10.2f; // a3[5][4][3]
+ carray2f a2 = carray3f_at1(&a3, 5); // sub-array reference: a2 = a3[5]
+ printf("%g\n", *carray2f_at(&a2, 4, 3)); // lookup a2[4][3] (=10.2f)
+ printf("%g\n", *carray3f_at(&a3, 5, 4, 3)); // same data location, via a3 array.
+
+ carray2f_del(&a2); // does nothing, since it is a sub-array.
+ carray3f_del(&a3); // destroy a3, invalidates a2.
+}
+*/
+
+#define using_carray2(...) c_MACRO_OVERLOAD(using_carray2, __VA_ARGS__)
+
+#define using_carray2_2(X, Value) \
+ using_carray2_4(X, Value, c_trivial_del, c_trivial_fromraw)
+
+#define using_carray2_4(X, Value, valueDel, valueClone) \
+\
+ typedef Value carray1##X##_value_t, carray2##X##_value_t; \
+\
+ typedef struct { \
+ carray1##X##_value_t *data; \
+ size_t _xdim; \
+ } carray1##X; \
+\
+ typedef struct { \
+ carray2##X##_value_t *data; \
+ size_t _xdim, _ydim; \
+ } carray2##X; \
+\
+ STC_INLINE size_t \
+ carray1##X##_size(carray1##X a) {return _carray_xdim(a);} \
+ STC_INLINE size_t \
+ carray2##X##_size(carray2##X a) {return _carray_xdim(a)*_carray_ydim(a);} \
+ STC_INLINE size_t \
+ carray2##X##_ydim(carray2##X a) {return _carray_ydim(a);} \
+\
+ _using_carray_common(1, X, Value, valueDel, valueClone) \
+ _using_carray_common(2, X, Value, valueDel, valueClone) \
+\
+ STC_INLINE carray1##X \
+ carray1##X##_init(size_t xdim, Value val) { \
+ carray1##X##_value_t* m = c_new_2(carray1##X##_value_t, xdim); \
+ for (size_t i=0; i<xdim; ++i) m[i] = val; \
+ carray1##X a = {m, xdim | _carray_OWN}; \
+ return a; \
+ } \
+ STC_INLINE carray2##X \
+ carray2##X##_init(size_t ydim, size_t xdim, Value val) { \
+ const size_t n = ydim * xdim; \
+ carray2##X##_value_t* m = c_new_2(carray2##X##_value_t, n); \
+ for (size_t i=0; i<n; ++i) m[i] = val; \
+ carray2##X a = {m, xdim | _carray_OWN, ydim}; \
+ return a; \
+ } \
+\
+ STC_INLINE carray1##X \
+ carray1##X##_from(carray1##X##_value_t* array, size_t xdim) { \
+ carray1##X a = {array, xdim}; \
+ return a; \
+ } \
+ STC_INLINE carray2##X \
+ carray2##X##_from(carray2##X##_value_t* array, size_t ydim, size_t xdim) { \
+ carray2##X a = {array, xdim, ydim}; \
+ return a; \
+ } \
+\
+ STC_INLINE carray1##X##_value_t* \
+ carray1##X##_at(const carray1##X *a, size_t x) { return a->data + x; } \
+ \
+ STC_INLINE carray1##X \
+ carray2##X##_at1(const carray2##X *a, size_t y) { \
+ carray1##X sub = {a->data + y*_carray_xdim(*a), _carray_xdim(*a)}; \
+ return sub; \
+ } \
+ STC_INLINE carray2##X##_value_t* \
+ carray2##X##_at(const carray2##X *a, size_t y, size_t x) { \
+ return a->data + y*_carray_xdim(*a) + x; \
+ } \
+ typedef carray2##X carray2##X##_t
+
+
+#define using_carray3(...) c_MACRO_OVERLOAD(using_carray3, __VA_ARGS__)
+
+#define using_carray3_2(X, Value) \
+ using_carray3_4(X, Value, c_trivial_del, c_trivial_fromraw)
+
+#define using_carray3_4(X, Value, valueDel, valueClone) \
+\
+ using_carray2_4(X, Value, valueDel, valueClone); \
+ typedef Value carray3##X##_value_t; \
+\
+ typedef struct { \
+ carray3##X##_value_t *data; \
+ size_t _xdim, _ydim, _zdim; \
+ } carray3##X; \
+\
+ STC_INLINE size_t \
+ carray3##X##_size(carray3##X a) {return _carray_xdim(a)*_carray_ydim(a)*_carray_zdim(a);} \
+ STC_INLINE size_t \
+ carray3##X##_ydim(carray3##X a) {return _carray_ydim(a);} \
+ STC_INLINE size_t \
+ carray3##X##_zdim(carray3##X a) {return _carray_zdim(a);} \
+\
+ _using_carray_common(3, X, Value, valueDel, valueClone) \
+\
+ STC_INLINE carray3##X \
+ carray3##X##_init(size_t zdim, size_t ydim, size_t xdim, Value val) { \
+ const size_t n = zdim * ydim * xdim; \
+ carray3##X##_value_t* m = c_new_2(carray3##X##_value_t, n); \
+ for (size_t i=0; i<n; ++i) m[i] = val; \
+ carray3##X a = {m, xdim | _carray_OWN, ydim, zdim}; \
+ return a; \
+ } \
+\
+ STC_INLINE carray3##X \
+ carray3##X##_from(carray3##X##_value_t* array, size_t zdim, size_t ydim, size_t xdim) { \
+ carray3##X a = {array, xdim, ydim, zdim}; \
+ return a; \
+ } \
+\
+ STC_INLINE carray2##X \
+ carray3##X##_at1(const carray3##X *a, size_t z) { \
+ carray2##X sub = {a->data + z*_carray_ydim(*a)*_carray_xdim(*a), _carray_xdim(*a), _carray_ydim(*a)}; \
+ return sub; \
+ } \
+ STC_INLINE carray1##X \
+ carray3##X##_at2(const carray3##X *a, size_t z, size_t y) { \
+ carray1##X sub = {a->data + (z*_carray_ydim(*a) + y)*_carray_xdim(*a), _carray_xdim(*a)}; \
+ return sub; \
+ } \
+ STC_INLINE carray3##X##_value_t* \
+ carray3##X##_at(const carray3##X *a, size_t z, size_t y, size_t x) { \
+ return a->data + (z*_carray_ydim(*a) + y)*_carray_xdim(*a) + x; \
+ } \
+ typedef carray3##X carray3##X##_t
+
+
+#define _carray_SUB (SIZE_MAX >> 1)
+#define _carray_OWN (_carray_SUB + 1)
+#define _carray_xdim(a) ((a)._xdim & _carray_SUB)
+#define _carray_ydim(a) (a)._ydim
+#define _carray_zdim(a) (a)._zdim
+
+#define _using_carray_common(D, X, Value, valueDel, valueClone) \
+ typedef struct { carray1##X##_value_t *ref; } carray##D##X##_iter_t; \
+\
+ STC_INLINE carray##D##X##_iter_t \
+ carray##D##X##_begin(const carray##D##X* a) { \
+ carray##D##X##_iter_t it = {a->data}; return it; \
+ } \
+ STC_INLINE carray##D##X##_iter_t \
+ carray##D##X##_end(const carray##D##X* a) { \
+ carray##D##X##_iter_t it = {a->data + carray##D##X##_size(*a)}; return it; \
+ } \
+ STC_INLINE void \
+ carray##D##X##_next(carray##D##X##_iter_t* it) {++it->ref;} \
+\
+ STC_INLINE void \
+ carray##D##X##_del(carray##D##X* self) { \
+ if (self->_xdim & _carray_OWN) { \
+ c_foreach_3 (i, carray##D##X, *self) \
+ valueDel(i.ref); \
+ c_free(self->data); \
+ } \
+ } \
+ STC_INLINE carray##D##X \
+ carray##D##X##_clone(carray##D##X arr) { \
+ carray##D##X cp = arr; size_t k = 0; \
+ cp.data = c_new_2(carray1##X##_value_t, carray##D##X##_size(arr)); \
+ c_foreach_3 (i, carray##D##X, arr) \
+ cp.data[k++] = valueClone(*i.ref); \
+ return cp; \
+ } \
+ STC_INLINE size_t \
+ carray##D##X##_xdim(carray##D##X a) {return _carray_xdim(a);} \
+
+#endif
diff --git a/docs/carray_api.md b/docs/carray_api.md
index 356b09ad..b9b3451d 100644
--- a/docs/carray_api.md
+++ b/docs/carray_api.md
@@ -1,89 +1,106 @@
# STC [carray](../stc/carray.h): Multi-dimensional Array
![Array](pics/array.jpg)
-The **carray** containers provides templates for multidimensional arrays of contiguous data It supports 1-, 2- and
+The **carray** containers provides templates for multidimensional arrays. It supports 2- and
3-dimensional arrays, which are allocated from the heap as a single contiguous block of memory.
+The carrays can be used almost like regular constant size multi-dimensional arrays in C, and has
+the same property of storing data in one block of memory, which can be passed to any method.
See the c++ class [boost::multi_array](https://www.boost.org/doc/libs/release/libs/multi_array) for similar functionality.
## Declaration
```c
-using_carray(X, Value);
-using_carray(X, Value, valueDel, valueClone);
+using_carray2(X, Value);
+using_carray2(X, Value, valueDel, valueClone);
+using_carray3(X, Value);
+using_carray3(X, Value, valueDel, valueClone);
```
-The macro `using_carray()` must be instantiated in the global scope. `X` and `N` are type tags and
-will affect the names of all cset types and methods. E.g. declaring `using_carray(i, int);`, `X` should
-be replaced by `i` in all of the following documentation. The `N` character should be replaced by `1`, `2` or `3`.
+The macro `using_carray2()` must be instantiated in the global scope. `X` and `N` are type tags and
+will affect the names of all cset types and methods. E.g. declaring `using_carray3(i, int);`, `X` should
+be replaced by `i` in all of the following documentation.
## Header file
All carray definitions and prototypes are available by including a single header file.
```c
-#include "stc/carray.h"
+#include <stc/carray.h>
```
## Methods
```c
-carray1X carray1X_init(size_t xdim, Value val);
-carray2X carray2X_init(size_t ydim, size_t xdim, Value val);
-carray3X carray3X_init(size_t zdim, size_t ydim, size_t xdim, Value val);
-carray1X carray1X_from(Value* array, size_t xdim);
-carray2X carray2X_from(Value* array, size_t ydim, size_t xdim);
-carray3X carray3X_from(Value* array, size_t zdim, size_t ydim, size_t xdim);
-carrayNX carrayNX_clone(carrayNX arr);
-
-void carrayNX_del(carrayNX* self);
-
-size_t carrayNX_size(carrayNX arr);
-size_t carrayNX_xdim(carrayNX arr);
-size_t carrayNX_ydim(carrayNX arr); // not N=3
-size_t carrayNX_zdim(carrayNX arr); // only N=3
-
-Value* carray1X_at(const carray1X *self, size_t x);
-Value* carray2X_at(const carray2X *self, size_t y, size_t x);
-Value* carray3X_at(const carray3X *self, size_t z, size_t y, size_t x);
-
-carray1X carray2X_at1(const carray2X *self, size_t y);
-carray2X carray3X_at1(const carray3X *self, size_t z);
-carray1X carray3X_at2(const carray3X *self, size_t z, size_t y);
-
-carrayNX_iter_t carrayNX_begin(const carrayNX* self);
-carrayNX_iter_t carrayNX_end(const carrayNX* self);
-void carrayNX_next(carrayNX_iter_t* it);
-carrayNX_value_t* carrayNX_itval(carrayNX_iter_t it);
+carray2X carray2X_init(size_t xdim, size_t ydim, Value val);
+carray2X carray2X_from(Value* array, size_t xdim, size_t ydim);
+carray2X carray2X_clone(carray2X arr);
+void carray2X_del(carray2X* self);
+void carray2X_del_internals(carray2X* self); // destroy pointers only
+
+size_t carray2X_size(carray2X arr);
+Value* carray2X_data(carray2X* self); // contiguous memory
+
+carray2X_iter_t carray2X_begin(const carray2X* self);
+carray2X_iter_t carray2X_end(const carray2X* self);
+void carray2X_next(carray2X_iter_t* it);
+```
+```c
+carray3X carray3X_init(size_t xdim, size_t ydim, size_t zdim, Value val);
+carray3X carray3X_from(Value* array, size_t xdim, size_t ydim, size_t zdim);
+carray3X carray3X_clone(carray3X arr);
+void carray3X_del(carray3X* self);
+void carray3X_del_internals(carray3X* self); // destroy pointers only
+
+size_t carray3X_size(carray3X arr);
+Value* carray3X_data(carray3X* self); // contiguous memory
+
+carray3X_iter_t carray3X_begin(const carray3X* self);
+carray3X_iter_t carray3X_end(const carray3X* self);
+void carray3X_next(carray3X_iter_t* it);
```
## Types
-| Type name | Type definition | Used to represent... |
-|:---------------------|:------------------------------|:--------------------------|
-| `carrayNX` | `struct { ... }` | The carray type |
-| `carrayNX_value_t` | `Value` | The value type |
-| `carrayNX_iter_t` | `struct { Value *ref; }` | Iterator type |
+| Type name | Type definition | Used to represent... |
+|:---------------------|:-------------------------------------------------|:--------------------------|
+| `carray2X` | `struct { Value **at; size_t xdim,ydim; }` | The carray2 type |
+| `carray2X_value_t` | `Value` | The value type |
+| `carray2X_iter_t` | `struct { Value *ref; }` | Iterator type |
+| `carray3X` | `struct { Value ***at; size_t xdim,ydim,zdim; }` | The carray3 type |
+| `carray3X_value_t` | `Value` | The value type |
+| `carray3X_iter_t` | `struct { Value *ref; }` | Iterator type |
## Example
```c
-#include <stdio.h>
#include "stc/carray.h"
+#include <stdio.h>
-using_carray(f, float);
+using_carray3(f, float);
+using_carray2(i, uint32_t);
int main()
{
+ // Ex1
carray3f a3 = carray3f_init(30, 20, 10, 0.0f); // define a3[30][20][10], init with 0.0f.
- *carray3f_at(&a3, 5, 4, 3) = 3.14f; // a3[5][4][3] = 3.14
-
- carray1f a1 = carray3f_at2(&a3, 5, 4); // sub-array a3[5][4] (no data copy).
- carray2f a2 = carray3f_at1(&a3, 5); // sub-array a3[5]
-
- printf("%f\n", *carray1f_at(&a1, 3)); // a1[3] (3.14f)
- printf("%f\n", *carray2f_at(&a2, 4, 3)); // a2[4][3] (3.14f)
- printf("%f\n", *carray3f_at(&a3, 5, 4, 3)); // a3[5][4][3] (3.14f)
- // ...
- carray1f_del(&a1); // does nothing, since it is a sub-array.
- carray2f_del(&a2); // same.
- carray3f_del(&a3); // free array, and invalidates a1, a2.
+ a3.at[5][4][3] = 3.14f;
+
+ float *a1 = a3.at[5][4];
+ float **a2 = a3.at[5];
+
+ printf("%f\n", a1[3]); // 3.14
+ printf("%f\n", a2[4][3]); // 3.14
+ printf("%f\n", a3.at[5][4][3]); // 3.14
+ carray3f_del(&a3); // free array
+
+ // Ex2
+ carray2i image = carray2i_from(c_new(uint32_t, 256*128), 256, 128); // no value init
+ int n = 0;
+ c_foreach (i, carray2i, image) {
+ uint32_t t = n++ % 256;
+ *i.ref = t | t << 8 | t << 16 | 255;
+ }
+
+ for (int y=0; y<image.ydim; ++y)
+ image.at[y][y] = 0xffffffff;
+ carray2i_del(&image);
}
```
Output:
diff --git a/examples/complex.c b/examples/complex.c
index 4ca833d4..6095a03e 100644
--- a/examples/complex.c
+++ b/examples/complex.c
@@ -6,32 +6,39 @@
void check_del(float* v) {printf("destroy %g\n", *v);}
using_carray2(f, float, check_del, c_trivial_fromraw);
-using_clist(a, carray2f, c_no_compare, carray2f_del, c_no_clone);
-using_cmap(l, int, clist_a, c_default_equals, c_default_hash, clist_a_del, c_no_clone);
-using_cmap_strkey(s, cmap_l, cmap_l_del, c_no_clone);
+using_clist(arr, carray2f, c_no_compare, carray2f_del, c_no_clone);
+using_cmap(lst, int, clist_arr, c_default_equals, c_default_hash, clist_arr_del, c_no_clone);
+using_cmap_strkey(map, cmap_lst, cmap_lst_del, c_no_clone);
+// c++:
+// using array2f = std::array<std::array<float, 6>, 4>>;
+// using map_lst = std::unordered_map<int, std::forward_list<array2f>>;
+// using map_map = std::unordered_map<std::string, map_lst>;
int main() {
int xdim = 4, ydim = 6;
- int x = 1, y = 5, tableKey = 42;
+ int x = 1, y = 3, tableKey = 42;
const char* strKey = "first";
- cmap_l listMap = cmap_l_init();
- cmap_s myMap = cmap_s_init();
+ cmap_map myMap = cmap_map_init();
+ cmap_lst listMap = cmap_lst_init();
+ clist_arr tableList = clist_arr_init();
+ carray2f arr2 = carray2f_init(xdim, ydim, 1.f);
- // Construct.
- carray2f arr_a = carray2f_init(ydim, xdim, 0.f);
- printf("arr_a: (%zu, %zu)\n", carray2f_ydim(arr_a), carray2f_xdim(arr_a));
+ printf("arr2 size: %zu x %zu\n", arr2.xdim, arr2.ydim);
- 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);
- cmap_l_insert(&listMap, tableKey, tableList);
- cmap_s_insert(&myMap, cstr_from(strKey), listMap);
+ // Put in some data in 2D array
+ arr2.at[x][y] = 3.1415927f;
+ clist_arr_push_back(&tableList, arr2);
+ cmap_lst_insert(&listMap, tableKey, tableList);
+ cmap_map_insert(&myMap, cstr_from(strKey), listMap);
// Access the data entry
- carray2f arr_b = *clist_a_back(&cmap_l_find(&cmap_s_find(&myMap, strKey).ref->second, tableKey).ref->second);
- printf("value (%d, %d) is: %f\n", y, x, *carray2f_at(&arr_b, y, x));
+ cmap_lst* mapl = &cmap_map_find(&myMap, strKey).ref->second;
+ clist_arr* lsta = &cmap_lst_find(mapl, tableKey).ref->second;
+ carray2f arr = *clist_arr_back(lsta);
- cmap_s_del(&myMap); // free up everything!
+ printf("value (%d, %d) is: %f\n", x, y, arr.at[x][y]);
+
+ arr2.at[x][y] = 1.41421356f; // change the value in array
+ cmap_map_del(&myMap); // free up everything!
}
diff --git a/examples/demos.c b/examples/demos.c
index eca5609f..9d7f894c 100644
--- a/examples/demos.c
+++ b/examples/demos.c
@@ -181,23 +181,22 @@ void arraydemo1()
{
printf("\nARRAYDEMO1\n");
carray3f a3 = carray3f_init(30, 20, 10, 0.0f);
- *carray3f_at(&a3, 5, 4, 3) = 10.2f; // a3[5][4][3]
- carray2f a2 = carray3f_at1(&a3, 5); // sub-array reference: a2 = a3[5]
- carray1f a1 = carray3f_at2(&a3, 5, 4); // sub-array reference: a1 = a3[5][4]
+ a3.at[5][4][3] = 10.2f;
+ float **a2 = a3.at[5];
+ float *a1 = a3.at[5][4];
- printf("a3: %zu: (%zu, %zu, %zu) = %zu\n", sizeof(a3), carray3f_xdim(a3), carray3f_ydim(a3), carray3f_zdim(a3), carray3f_size(a3));
- printf("a2: %zu: (%zu, %zu) = %zu\n", sizeof(a2), carray2f_xdim(a2), carray2f_ydim(a2), carray2f_size(a2));
+ printf("a3: %zu: (%zu, %zu, %zu) = %zu\n", sizeof(a3), a3.xdim, a3.ydim, a3.zdim, carray3f_size(a3));
- printf("%f\n", a1.data[3]); // lookup a1[3] (=10.2f)
- printf("%f\n", *carray2f_at(&a2, 4, 3)); // lookup a2[4][3] (=10.2f)
- printf("%f\n", *carray3f_at(&a3, 5, 4, 3)); // lookup a3[5][4][3] (=10.2f)
+ printf("%g\n", a1[3]); // = 10.2
+ printf("%g\n", a2[4][3]); // = 10.2
+ printf("%g\n", a3.at[5][4][3]); // = 10.2
+ float x = 0.0;
c_foreach (i, carray3f, a3)
- *i.ref = 1.0f;
- printf("%f\n", *carray3f_at(&a3, 29, 19, 9));
+ *i.ref = ++x;
+ printf("%g\n", a3.at[29][19][9]); // = 6000
- carray2f_del(&a2); // does nothing, since it is a sub-array.
- carray3f_del(&a3); // also invalidates a2.
+ carray3f_del(&a3);
}
diff --git a/stc/carray.h b/stc/carray.h
index fdd69013..3fe60bf6 100644
--- a/stc/carray.h
+++ b/stc/carray.h
@@ -23,29 +23,37 @@
#ifndef CARRAY_H_INCLUDED
#define CARRAY_H_INCLUDED
-#include <stdlib.h>
#include "ccommon.h"
-
+#include <stdlib.h>
/*
- Multi-dimensional generic array allocated as one block of heap-memory.
- // demo:
+// carray2 and carray3 - 2D and 3D dynamic arrays in one memory block with easy indexing.
+#include <stc/carray.h>
#include <stdio.h>
-#include "stc/carray.h"
-using_carray3(f, float);
-
-int main()
-{
- carray3f a3 = carray3f_init(30, 20, 10, 0.0f);
- *carray3f_at(&a3, 5, 4, 3) = 10.2f; // a3[5][4][3]
- carray2f a2 = carray3f_at1(&a3, 5); // sub-array reference: a2 = a3[5]
- printf("%g\n", *carray2f_at(&a2, 4, 3)); // lookup a2[4][3] (=10.2f)
- printf("%g\n", *carray3f_at(&a3, 5, 4, 3)); // same data location, via a3 array.
-
- carray2f_del(&a2); // does nothing, since it is a sub-array.
- carray3f_del(&a3); // destroy a3, invalidates a2.
+using_carray2(i, int);
+
+int main() {
+ int w = 7, h = 5;
+ carray2i image = carray2i_init(w, h, 0);
+
+ int *dat = carray2i_data(&image);
+ for (int i = 0; i < carray2i_size(image); ++i)
+ dat[i] = i;
+
+ for (int x = 0; x < image.xdim; ++x)
+ for (int y = 0; y < image.ydim; ++y)
+ printf(" %d", image.at[x][y]);
+ puts("\n");
+
+ c_foreach (i, carray2i, image)
+ printf(" %d", *i.ref);
+ puts("");
+
+ carray2i_del(&image);
}
*/
+// carray2:
+
#define using_carray2(...) c_MACRO_OVERLOAD(using_carray2, __VA_ARGS__)
#define using_carray2_2(X, Value) \
@@ -53,69 +61,30 @@ int main()
#define using_carray2_4(X, Value, valueDel, valueClone) \
\
- typedef Value carray1##X##_value_t, carray2##X##_value_t; \
-\
- typedef struct { \
- carray1##X##_value_t *data; \
- size_t _xdim; \
- } carray1##X; \
-\
- typedef struct { \
- carray2##X##_value_t *data; \
- size_t _xdim, _ydim; \
- } carray2##X; \
-\
- STC_INLINE size_t \
- carray1##X##_size(carray1##X a) {return _carray_xdim(a);} \
- STC_INLINE size_t \
- carray2##X##_size(carray2##X a) {return _carray_xdim(a)*_carray_ydim(a);} \
- STC_INLINE size_t \
- carray2##X##_ydim(carray2##X a) {return _carray_ydim(a);} \
-\
- _using_carray_common(1, X, Value, valueDel, valueClone) \
- _using_carray_common(2, X, Value, valueDel, valueClone) \
-\
- STC_INLINE carray1##X \
- carray1##X##_init(size_t xdim, Value val) { \
- carray1##X##_value_t* m = c_new_2(carray1##X##_value_t, xdim); \
- for (size_t i=0; i<xdim; ++i) m[i] = val; \
- carray1##X a = {m, xdim | _carray_OWN}; \
- return a; \
- } \
- STC_INLINE carray2##X \
- carray2##X##_init(size_t ydim, size_t xdim, Value val) { \
- const size_t n = ydim * xdim; \
- carray2##X##_value_t* m = c_new_2(carray2##X##_value_t, n); \
- for (size_t i=0; i<n; ++i) m[i] = val; \
- carray2##X a = {m, xdim | _carray_OWN, ydim}; \
- return a; \
- } \
+ typedef Value carray2##X##_value_t; \
+ typedef struct { carray2##X##_value_t **at; size_t xdim, ydim; } carray2##X; \
+ typedef struct { carray2##X##_value_t *ref; } carray2##X##_iter_t; \
\
- STC_INLINE carray1##X \
- carray1##X##_from(carray1##X##_value_t* array, size_t xdim) { \
- carray1##X a = {array, xdim}; \
- return a; \
- } \
- STC_INLINE carray2##X \
- carray2##X##_from(carray2##X##_value_t* array, size_t ydim, size_t xdim) { \
- carray2##X a = {array, xdim, ydim}; \
- return a; \
- } \
+ STC_API carray2##X carray2##X##_from(carray2##X##_value_t* block, size_t xdim, size_t ydim); \
+ STC_API carray2##X carray2##X##_init(size_t xdim, size_t ydim, Value value); \
+ STC_API carray2##X carray2##X##_clone(carray2##X src); \
+\
+ STC_INLINE size_t carray2##X##_size(carray2##X arr) { return arr.xdim*arr.ydim; } \
+ STC_INLINE carray2##X##_value_t* carray2##X##_data(carray2##X* self) { return self->at[0]; } \
+ STC_INLINE void carray2##X##_del_internals(carray2##X* self) { c_free(self->at); } \
\
- STC_INLINE carray1##X##_value_t* \
- carray1##X##_at(const carray1##X *a, size_t x) { return a->data + x; } \
- \
- STC_INLINE carray1##X \
- carray2##X##_at1(const carray2##X *a, size_t y) { \
- carray1##X sub = {a->data + y*_carray_xdim(*a), _carray_xdim(*a)}; \
- return sub; \
+ STC_INLINE carray2##X##_iter_t carray2##X##_begin(const carray2##X* self) { \
+ carray2##X##_iter_t it = {self->at[0]}; return it; \
} \
- STC_INLINE carray2##X##_value_t* \
- carray2##X##_at(const carray2##X *a, size_t y, size_t x) { \
- return a->data + y*_carray_xdim(*a) + x; \
+ STC_INLINE carray2##X##_iter_t carray2##X##_end(const carray2##X* self) { \
+ carray2##X##_iter_t it = {self->at[0] + carray2##X##_size(*self)}; return it; \
} \
- typedef carray2##X carray2##X##_t
+ STC_INLINE void carray2##X##_next(carray2##X##_iter_t* it) { ++it->ref; } \
+\
+ _c_implement_carray2_4(X, Value, valueDel, valueClone) \
+ STC_API void carray2##X##_del(carray2##X* self)
+// carray3:
#define using_carray3(...) c_MACRO_OVERLOAD(using_carray3, __VA_ARGS__)
@@ -124,92 +93,109 @@ int main()
#define using_carray3_4(X, Value, valueDel, valueClone) \
\
- using_carray2_4(X, Value, valueDel, valueClone); \
typedef Value carray3##X##_value_t; \
+ typedef struct { carray3##X##_value_t ***at; size_t xdim, ydim, zdim; } carray3##X; \
+ typedef struct { carray3##X##_value_t *ref; } carray3##X##_iter_t; \
\
- typedef struct { \
- carray3##X##_value_t *data; \
- size_t _xdim, _ydim, _zdim; \
- } carray3##X; \
-\
- STC_INLINE size_t \
- carray3##X##_size(carray3##X a) {return _carray_xdim(a)*_carray_ydim(a)*_carray_zdim(a);} \
- STC_INLINE size_t \
- carray3##X##_ydim(carray3##X a) {return _carray_ydim(a);} \
- STC_INLINE size_t \
- carray3##X##_zdim(carray3##X a) {return _carray_zdim(a);} \
-\
- _using_carray_common(3, X, Value, valueDel, valueClone) \
-\
- STC_INLINE carray3##X \
- carray3##X##_init(size_t zdim, size_t ydim, size_t xdim, Value val) { \
- const size_t n = zdim * ydim * xdim; \
- carray3##X##_value_t* m = c_new_2(carray3##X##_value_t, n); \
- for (size_t i=0; i<n; ++i) m[i] = val; \
- carray3##X a = {m, xdim | _carray_OWN, ydim, zdim}; \
- return a; \
- } \
+ STC_API carray3##X carray3##X##_from(carray3##X##_value_t* block, size_t xdim, size_t ydim, size_t zdim); \
+ STC_API carray3##X carray3##X##_init(size_t xdim, size_t ydim, size_t zdim, Value value); \
+ STC_API carray3##X carray3##X##_clone(carray3##X src); \
\
- STC_INLINE carray3##X \
- carray3##X##_from(carray3##X##_value_t* array, size_t zdim, size_t ydim, size_t xdim) { \
- carray3##X a = {array, xdim, ydim, zdim}; \
- return a; \
- } \
+ STC_INLINE size_t carray3##X##_size(carray3##X arr) { return arr.xdim*arr.ydim*arr.zdim; } \
+ STC_INLINE carray3##X##_value_t* carray3##X##_data(carray3##X* self) { return self->at[0][0]; } \
+ STC_INLINE void carray3##X##_del_internals(carray3##X* self) { c_free(self->at); } \
\
- STC_INLINE carray2##X \
- carray3##X##_at1(const carray3##X *a, size_t z) { \
- carray2##X sub = {a->data + z*_carray_ydim(*a)*_carray_xdim(*a), _carray_xdim(*a), _carray_ydim(*a)}; \
- return sub; \
+ STC_INLINE carray3##X##_iter_t carray3##X##_begin(const carray3##X* self) { \
+ carray3##X##_iter_t it = {self->at[0][0]}; return it; \
} \
- STC_INLINE carray1##X \
- carray3##X##_at2(const carray3##X *a, size_t z, size_t y) { \
- carray1##X sub = {a->data + (z*_carray_ydim(*a) + y)*_carray_xdim(*a), _carray_xdim(*a)}; \
- return sub; \
+ STC_INLINE carray3##X##_iter_t carray3##X##_end(const carray3##X* self) { \
+ carray3##X##_iter_t it = {self->at[0][0] + carray3##X##_size(*self)}; return it; \
} \
- STC_INLINE carray3##X##_value_t* \
- carray3##X##_at(const carray3##X *a, size_t z, size_t y, size_t x) { \
- return a->data + (z*_carray_ydim(*a) + y)*_carray_xdim(*a) + x; \
- } \
- typedef carray3##X carray3##X##_t
+ STC_INLINE void carray3##X##_next(carray3##X##_iter_t* it) { ++it->ref; } \
+\
+ _c_implement_carray3_4(X, Value, valueDel, valueClone) \
+ STC_API void carray3##X##_del(carray3##X* self)
+/* -------------------------- IMPLEMENTATION ------------------------- */
-#define _carray_SUB (SIZE_MAX >> 1)
-#define _carray_OWN (_carray_SUB + 1)
-#define _carray_xdim(a) ((a)._xdim & _carray_SUB)
-#define _carray_ydim(a) (a)._ydim
-#define _carray_zdim(a) (a)._zdim
+#if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION)
-#define _using_carray_common(D, X, Value, valueDel, valueClone) \
- typedef struct { carray1##X##_value_t *ref; } carray##D##X##_iter_t; \
+#define _c_implement_carray2_4(X, Value, valueDel, valueClone) \
+\
+ STC_DEF carray2##X carray2##X##_from(carray2##X##_value_t* block, size_t xdim, size_t ydim) { \
+ size_t n = xdim * ydim; \
+ carray2##X _arr = {c_new_2(carray2##X##_value_t*, xdim), xdim, ydim}; \
+ _arr.at[0] = block; \
+ for (size_t x = 1; x < xdim; ++x) \
+ _arr.at[x] = _arr.at[x - 1] + ydim; \
+ return _arr; \
+ } \
\
- STC_INLINE carray##D##X##_iter_t \
- carray##D##X##_begin(const carray##D##X* a) { \
- carray##D##X##_iter_t it = {a->data}; return it; \
+ STC_DEF carray2##X carray2##X##_init(size_t xdim, size_t ydim, Value value) { \
+ size_t n = xdim*ydim; \
+ carray2##X _arr = carray2##X##_from(c_new_2(carray2##X##_value_t, n), xdim, ydim); \
+ for (carray2##X##_value_t* p = _arr.at[0], *e = p + n; p != e; ++p) \
+ *p = value; \
+ return _arr; \
} \
- STC_INLINE carray##D##X##_iter_t \
- carray##D##X##_end(const carray##D##X* a) { \
- carray##D##X##_iter_t it = {a->data + carray##D##X##_size(*a)}; return it; \
+\
+ STC_DEF carray2##X carray2##X##_clone(carray2##X src) { \
+ size_t n = src.xdim*src.ydim; \
+ carray2##X _arr = carray2##X##_from(c_new_2(carray2##X##_value_t, n), src.xdim, src.ydim); \
+ for (carray2##X##_value_t* p = _arr.at[0], *q = src.at[0], *e = p + n; p != e; ++p, ++q) \
+ *p = valueClone(*q); \
+ return _arr; \
} \
- STC_INLINE void \
- carray##D##X##_next(carray##D##X##_iter_t* it) {++it->ref;} \
-\
- STC_INLINE void \
- carray##D##X##_del(carray##D##X* self) { \
- if (self->_xdim & _carray_OWN) { \
- c_foreach_3 (i, carray##D##X, *self) \
- valueDel(i.ref); \
- c_free(self->data); \
+\
+ STC_DEF void carray2##X##_del(carray2##X* self) { \
+ for (carray2##X##_value_t* p = self->at[0], *e = p + self->xdim*self->ydim; p != e; ++p) \
+ valueDel(p); \
+ c_free(self->at[0]); /* data */ \
+ c_free(self->at); \
+ }
+
+#define _c_implement_carray3_4(X, Value, valueDel, valueClone) \
+\
+ STC_DEF carray3##X carray3##X##_from(carray3##X##_value_t* block, size_t xdim, size_t ydim, size_t zdim) { \
+ carray3##X _arr = {c_new_2(carray3##X##_value_t**, xdim*(ydim + 1)), xdim, ydim, zdim}; \
+ _arr.at[0] = (carray3##X##_value_t**) &_arr.at[xdim]; \
+ _arr.at[0][0] = block; \
+ for (size_t x = 1, m = zdim*ydim; x < xdim; ++x) { \
+ _arr.at[x] = _arr.at[x - 1] + ydim; \
+ _arr.at[x][0] = _arr.at[x - 1][0] + m; \
} \
+ for (size_t x = 0; x < xdim; ++x) \
+ for (size_t y = 1; y < ydim; ++y) \
+ _arr.at[x][y] = _arr.at[x][y - 1] + zdim; \
+ return _arr; \
+ } \
+\
+ STC_DEF carray3##X carray3##X##_init(size_t xdim, size_t ydim, size_t zdim, Value value) { \
+ size_t n = xdim*ydim*zdim; \
+ carray3##X _arr = carray3##X##_from(c_new_2(carray3##X##_value_t, n), xdim, ydim, zdim); \
+ for (carray3##X##_value_t* p = **_arr.at, *e = p + n; p != e; ++p) \
+ *p = value; \
+ return _arr; \
} \
- STC_INLINE carray##D##X \
- carray##D##X##_clone(carray##D##X arr) { \
- carray##D##X cp = arr; size_t k = 0; \
- cp.data = c_new_2(carray1##X##_value_t, carray##D##X##_size(arr)); \
- c_foreach_3 (i, carray##D##X, arr) \
- cp.data[k++] = valueClone(*i.ref); \
- return cp; \
+\
+ STC_DEF carray3##X carray3##X##_clone(carray3##X src) { \
+ size_t n = carray3##X##_size(src); \
+ carray3##X _arr = carray3##X##_from(c_new_2(carray3##X##_value_t, n), src.xdim, src.ydim, src.zdim); \
+ for (carray3##X##_value_t* p = **_arr.at, *q = **src.at, *e = p + n; p != e; ++p, ++q) \
+ *p = valueClone(*q); \
+ return _arr; \
} \
- STC_INLINE size_t \
- carray##D##X##_xdim(carray##D##X a) {return _carray_xdim(a);} \
+\
+ STC_DEF void carray3##X##_del(carray3##X* self) { \
+ for (carray3##X##_value_t* p = **self->at, *e = p + carray3##X##_size(*self); p != e; ++p) \
+ valueDel(p); \
+ c_free(self->at[0][0]); /* data */ \
+ c_free(self->at); /* pointers */ \
+ }
+
+#else
+#define _c_implement_carray2_4(X, Value, valueDel, valueClone)
+#define _c_implement_carray3_4(X, Value, valueDel, valueClone)
+#endif
#endif