diff options
| author | Tyge Løvset <[email protected]> | 2023-01-13 16:57:32 +0100 |
|---|---|---|
| committer | Tyge Løvset <[email protected]> | 2023-01-13 16:57:32 +0100 |
| commit | bb92cdbeaa279d8ef90dff0cf088585a50e7d52c (patch) | |
| tree | a357ad9f39e979b5354a20a78511e253d577f31d | |
| parent | 350bb65a2f68b14ce16a21ea8670cc087e39f4ce (diff) | |
| download | STC-modified-bb92cdbeaa279d8ef90dff0cf088585a50e7d52c.tar.gz STC-modified-bb92cdbeaa279d8ef90dff0cf088585a50e7d52c.zip | |
Added algo/cmspan.h: multi-dim span, similar to c++23 mdspan. May get some API changes. Changed cspan.h, these may merge.
| -rw-r--r-- | docs/ccommon_api.md | 2 | ||||
| -rw-r--r-- | include/stc/algo/cmspan.h | 74 | ||||
| -rw-r--r-- | include/stc/algo/crange.h | 4 | ||||
| -rw-r--r-- | include/stc/algo/cspan.h | 49 | ||||
| -rw-r--r-- | misc/examples/forfilter.c | 2 | ||||
| -rw-r--r-- | misc/examples/multidim.c | 49 | ||||
| -rw-r--r-- | misc/examples/prime.c | 2 |
7 files changed, 154 insertions, 28 deletions
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index 1488253d..e17e98ca 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -282,7 +282,7 @@ c_FORFILTER (i, crange, r1 // 2. The 11 first primes: printf("2"); -c_FORFILTER (i, crange, crange_LITERAL(3, INT64_MAX, 2) +c_FORFILTER (i, crange, crange_object(3, INT64_MAX, 2) , isPrime(*i.ref) , c_FLT_TAKE(10)) printf(" %lld", *i.ref); diff --git a/include/stc/algo/cmspan.h b/include/stc/algo/cmspan.h new file mode 100644 index 00000000..8edf956f --- /dev/null +++ b/include/stc/algo/cmspan.h @@ -0,0 +1,74 @@ +/* +#include <stdio.h> +#include <stc/algo/cmspan.h> +using_cmspan(S3f, float, 3); + +int main() +{ + float raw[3*4*5]; + S3f span = cmspan_make(raw, 3, 4, 5); + *cmspan_at(&span, 2, 3, 4) = 100; + + printf("%f\n", *cmspan_at(&span, 2, 3, 4)); +} +*/ +#ifndef STC_CMSPAN_H_INCLUDED +#define STC_CMSPAN_H_INCLUDED + +#include <stc/ccommon.h> + +#define using_cmspan(Self, T, DIM) \ + typedef struct { T *data; uint32_t dim[DIM]; } Self; \ + typedef T Self##_raw, Self##_value; \ + typedef struct { Self##_value *ref, *end; } Self##_iter; \ + \ + STC_INLINE Self##_iter Self##_begin(const Self* self) { \ + Self##_iter it = {self->data, self->data + cmspan_size(self)}; \ + return it; \ + } \ + STC_INLINE Self##_iter Self##_end(const Self* self) { \ + Self##_iter it = {NULL, self->data + cmspan_size(self)}; \ + return it; \ + } \ + STC_INLINE void Self##_next(Self##_iter* it) \ + { if (++it->ref == it->end) it->ref = NULL; } \ + struct stc_nostruct + +#define cmspan_assert(self, rank) c_STATIC_ASSERT(cmspan_rank(self) == rank) + +#define cmspan_init() {NULL} +#define cmspan_make(data, ...) {data, {__VA_ARGS__}} + +#define cmspan_reshape(self, ...) \ + memcpy((self)->dim, (uint32_t[]){__VA_ARGS__}, \ + sizeof((self)->dim) + cmspan_assert(self, c_NUMARGS(__VA_ARGS__))) + +#define cmspan_at(self, ...) \ + ((self)->data + c_PASTE(_cmspan_i, c_NUMARGS(__VA_ARGS__))((self)->dim, __VA_ARGS__) \ + + cmspan_assert(self, c_NUMARGS(__VA_ARGS__))) + +#define cmspan_size(self) _cmspan_size((self)->dim, cmspan_rank(self)) +#define cmspan_rank(self) c_ARRAYLEN((self)->dim) + +STC_INLINE uint32_t _cmspan_i1(const uint32_t dim[1], uint32_t x) + { assert(x < dim[0]); return x; } + +STC_INLINE uint32_t _cmspan_i2(const uint32_t dim[2], uint32_t x, uint32_t y) + { assert(x < dim[0] && y < dim[1]); return dim[1]*x + y; } + +STC_INLINE uint32_t _cmspan_i3(const uint32_t dim[3], uint32_t x, uint32_t y, uint32_t z) { + assert(x < dim[0] && y < dim[1] && z < dim[2]); + return dim[2]*(dim[1]*x + y) + z; +} +STC_INLINE uint32_t _cmspan_i4(const uint32_t dim[4], uint32_t x, uint32_t y, uint32_t z, uint32_t w) { + assert(x < dim[0] && y < dim[1] && z < dim[3] && w < dim[3]); + return dim[3]*(dim[2]*(dim[1]*x + y) + z) + w; +} + +STC_INLINE size_t _cmspan_size(const uint32_t dim[], unsigned rank) { + size_t sz = dim[0]; + while (rank --> 1) sz *= dim[rank]; + return sz; +} + +#endif diff --git a/include/stc/algo/crange.h b/include/stc/algo/crange.h index 0c4d8465..518320b5 100644 --- a/include/stc/algo/crange.h +++ b/include/stc/algo/crange.h @@ -34,7 +34,7 @@ int main() // use a temporary crange object. int a = 100, b = INT32_MAX; - c_FORFILTER (i, crange, crange_LITERAL(a, b, 8) + c_FORFILTER (i, crange, crange_object(a, b, 8) , i.index > 10 , c_FLT_TAKE(i, 3)) printf(" %lld", *i.ref); @@ -46,7 +46,7 @@ int main() #include <stc/ccommon.h> -#define crange_LITERAL(...) \ +#define crange_object(...) \ (*(crange[]){crange_make(__VA_ARGS__)}) typedef long long crange_value; diff --git a/include/stc/algo/cspan.h b/include/stc/algo/cspan.h index 8378bfe3..23507fde 100644 --- a/include/stc/algo/cspan.h +++ b/include/stc/algo/cspan.h @@ -28,14 +28,14 @@ using_cspan(IntSpan, int); int main() { int array[] = {1, 2, 3, 4, 5}; - IntSpan span = {array, c_ARRAYLEN(array)}; + IntSpan span = cspan_from(array); c_FOREACH (i, IntSpan, span) printf(" %d", *i.ref); puts(""); // use a temporary IntSpan object. - c_FORFILTER (i, IntSpan, cspan_LITERAL(IntSpan, {10, 20, 30, 23, 22, 21}) + c_FORFILTER (i, IntSpan, cspan_object(IntSpan, {10, 20, 30, 23, 22, 21}) , c_FLT_SKIPWHILE(i, *i.ref < 25) && (*i.ref & 1) == 0 // even only , c_FLT_TAKE(i, 2)) // break after 2 @@ -48,30 +48,33 @@ int main() #include <stc/ccommon.h> -#define cspan_LITERAL(C, ...) \ +#define cspan_object(C, ...) \ ((C){.data = (C##_value[])__VA_ARGS__, \ .size = sizeof((C##_value[])__VA_ARGS__)/sizeof(C##_value)}) +#define cspan_from(data) \ + {data + c_STATIC_ASSERT(sizeof(data) != sizeof(void*)), c_ARRAYLEN(data)} +#define cspan_make(data, size) \ + {data + c_STATIC_ASSERT(c_ARRAYLEN(data) >= size || sizeof(data) == sizeof(void*)), size} +#define cspan_size(self) ((size_t)(self)->size) + #define using_cspan(Self, T) \ -typedef T Self##_raw; typedef const Self##_raw Self##_value; \ -typedef struct { Self##_value *data; size_t size; } Self; \ -typedef struct { Self##_value *ref, *end; } Self##_iter; \ - \ -STC_INLINE Self##_value* Self##_at(const Self* self, size_t idx) \ - { assert(idx < self->size); return self->data + idx; } \ - \ -STC_INLINE Self##_iter Self##_begin(const Self* self) { \ - Self##_iter it = {self->data, self->data + self->size}; \ - return it; \ -} \ - \ -STC_INLINE Self##_iter Self##_end(const Self* self) { \ - Self##_iter it = {NULL, self->data + self->size}; \ - return it; \ -} \ - \ -STC_INLINE void Self##_next(Self##_iter* it) \ - { if (++it->ref == it->end) it->ref = NULL; } \ -struct stc_nostruct + typedef T Self##_raw, Self##_value; \ + typedef struct { Self##_value *data; size_t size; } Self; \ + typedef struct { Self##_value *ref, *end; } Self##_iter; \ + \ + STC_INLINE Self##_value* Self##_at(const Self* self, size_t idx) \ + { assert(idx < self->size); return self->data + idx; } \ + STC_INLINE Self##_iter Self##_begin(const Self* self) { \ + Self##_iter it = {self->data, self->data + self->size}; \ + return it; \ + } \ + STC_INLINE Self##_iter Self##_end(const Self* self) { \ + Self##_iter it = {NULL, self->data + self->size}; \ + return it; \ + } \ + STC_INLINE void Self##_next(Self##_iter* it) \ + { if (++it->ref == it->end) it->ref = NULL; } \ + struct stc_nostruct #endif diff --git a/misc/examples/forfilter.c b/misc/examples/forfilter.c index 280fdc9c..bd3d346d 100644 --- a/misc/examples/forfilter.c +++ b/misc/examples/forfilter.c @@ -65,7 +65,7 @@ void demo2(void) c_AUTO (IVec, vector) { puts("demo2:"); - c_FORFILTER (x, crange, crange_LITERAL(INT64_MAX) + c_FORFILTER (x, crange, crange_object(INT64_MAX) , c_FLT_SKIPWHILE(x, *x.ref != 11) && *x.ref % 2 != 0 , c_FLT_TAKE(x, 5)) diff --git a/misc/examples/multidim.c b/misc/examples/multidim.c new file mode 100644 index 00000000..044693be --- /dev/null +++ b/misc/examples/multidim.c @@ -0,0 +1,49 @@ +// Example from https://en.cppreference.com/w/cpp/container/mdspan +#define i_val int +#include <stc/cstack.h> +#include <stc/algo/cmspan.h> +#include <stdio.h> +using_cmspan(ispan1, int, 1); +using_cmspan(ispan2, int, 2); +using_cmspan(ispan3, int, 3); + +int main() +{ + cstack_int v = {0}; + c_FORLIST (i, unsigned, {1,2,3,4,5,6,7,8,9,10,11,12}) + cstack_int_push(&v, *i.ref); + + // View data as contiguous memory representing 12 ints + ispan1 ms1 = cmspan_make(v.data, 12); + // View data as contiguous memory representing 2 rows of 6 ints each + ispan2 ms2 = cmspan_make(v.data, 2, 6); + // View the same data as a 3D array 2 x 3 x 2 + ispan3 ms3 = cmspan_make(v.data, 2, 3, 2); + + // write data using 2D view + for(unsigned i=0; i != ms2.dim[0]; i++) + for(unsigned j=0; j != ms2.dim[1]; j++) + *cmspan_at(&ms2, i, j) = i*1000 + j; + + // print data using 1D view + for(unsigned i=0; i != ms1.dim[0]; i++) + printf(" %d", *cmspan_at(&ms1, i)); + puts(""); + + c_FOREACH (i, ispan1, ms1) + printf(" %d", *i.ref); + puts(""); + + // read back using 3D view + for(unsigned i=0; i != ms3.dim[0]; i++) + { + printf("slice @ i = %u\n", i); + for(unsigned j=0; j != ms3.dim[1]; j++) + { + for(unsigned k=0; k != ms3.dim[2]; k++) + printf("%d ", *cmspan_at(&ms3, i, j, k)); + puts(""); + } + } + cstack_int_drop(&v); +} diff --git a/misc/examples/prime.c b/misc/examples/prime.c index f6e89e09..b4d81868 100644 --- a/misc/examples/prime.c +++ b/misc/examples/prime.c @@ -43,7 +43,7 @@ int main(void) puts(""); puts("Show the last 50 primes using a temporary crange generator:"); - c_FORFILTER (i, crange, crange_LITERAL(n - 1, 0, -2) + c_FORFILTER (i, crange, crange_object(n - 1, 0, -2) , cbits_test(&primes, *i.ref>>1) , c_FLT_TAKE(i, 50)) { printf("%lld ", *i.ref); |
