summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2023-01-13 16:57:32 +0100
committerTyge Løvset <[email protected]>2023-01-13 16:57:32 +0100
commitbb92cdbeaa279d8ef90dff0cf088585a50e7d52c (patch)
treea357ad9f39e979b5354a20a78511e253d577f31d
parent350bb65a2f68b14ce16a21ea8670cc087e39f4ce (diff)
downloadSTC-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.md2
-rw-r--r--include/stc/algo/cmspan.h74
-rw-r--r--include/stc/algo/crange.h4
-rw-r--r--include/stc/algo/cspan.h49
-rw-r--r--misc/examples/forfilter.c2
-rw-r--r--misc/examples/multidim.c49
-rw-r--r--misc/examples/prime.c2
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);