summaryrefslogtreecommitdiffhomepage
path: root/include/stc
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 /include/stc
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.
Diffstat (limited to 'include/stc')
-rw-r--r--include/stc/algo/cmspan.h74
-rw-r--r--include/stc/algo/crange.h4
-rw-r--r--include/stc/algo/cspan.h49
3 files changed, 102 insertions, 25 deletions
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