summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--docs/cspan_api.md5
-rw-r--r--include/stc/cspan.h35
-rw-r--r--misc/examples/multidim.c55
3 files changed, 59 insertions, 36 deletions
diff --git a/docs/cspan_api.md b/docs/cspan_api.md
index 6da2acca..c0b86239 100644
--- a/docs/cspan_api.md
+++ b/docs/cspan_api.md
@@ -38,9 +38,12 @@ ValueType* cspan_front(SpanTypeN* self);
ValueType* cspan_back(SpanTypeN* self);
SpanType cspan_at2(SpanType2* self, size_t x); // return a 1d subspan from a 2d span.
-SpanTypeN cspan_at3(SpanType3* self, size_t x, ...); // return a 1 or 2d subspan from a 3d span.
+SpanTypeN cspan_at3(SpanType3* self, size_t x, ...); // return a 1d or 2d subspan from a 3d span.
SpanTypeN cspan_at4(SpanType4* self, size_t x, ...); // number of args determines rank of output span.
+void cspan_slice(SpanTypeN* self, uint32_t xslice[2], ...); // slice multidim span into a md subspan.
+uint32_t[2] c_SLICE(a, b) // use to specify a:b xslice, ... b is optional.
+
// return a subspan of same rank:
SpanType cspan_subspan(const SpanType* self, size_t offset, size_t count);
SpanType2 cspan_subspan2(const SpanType2 self, size_t offset, size_t count);
diff --git a/include/stc/cspan.h b/include/stc/cspan.h
index a4573b07..68a06541 100644
--- a/include/stc/cspan.h
+++ b/include/stc/cspan.h
@@ -62,27 +62,28 @@ int demo2() {
#define using_cspan(Self, T, RANK) \
typedef T Self##_value; typedef T Self##_raw; \
- typedef struct { Self##_value *ref, *end; } Self##_iter; \
typedef struct { \
Self##_value *data; \
uint32_t dim[RANK]; \
cspan_idx##RANK stride; \
} Self; \
+ typedef struct { Self##_value *ref; uint32_t pos[RANK]; const Self *_s; } Self##_iter; \
\
STC_INLINE Self Self##_from_n(Self##_raw* raw, const size_t n) { \
return (Self){.data=raw, .dim={(uint32_t)n}}; \
} \
STC_INLINE Self##_iter Self##_begin(const Self* self) { \
- size_t n = cspan_size(self); \
- Self##_iter it = {n ? self->data : NULL, self->data + n}; \
+ Self##_iter it = {.ref=self->data, .pos={0}, ._s=self}; \
return it; \
} \
STC_INLINE Self##_iter Self##_end(const Self* self) { \
- Self##_iter it = {NULL, self->data + cspan_size(self)}; \
+ Self##_iter it = {.ref=NULL}; \
return it; \
} \
- STC_INLINE void Self##_next(Self##_iter* it) \
- { if (++it->ref == it->end) it->ref = NULL; } \
+ STC_INLINE void Self##_next(Self##_iter* it) { \
+ it->ref += _cspan_next_##RANK(RANK, it->pos, it->_s->dim, it->_s->stride.d); \
+ if (it->pos[0] == it->_s->dim[0]) it->ref = NULL; \
+ } \
struct stc_nostruct
#define using_cspan2(Self, T) using_cspan(Self, T, 1); using_cspan(Self##2, T, 2)
@@ -100,9 +101,6 @@ typedef struct { uint32_t d[4]; } cspan_idx4;
#define cspan_make(SpanType, ...) \
{.data=(SpanType##_value[])__VA_ARGS__, .dim={sizeof((SpanType##_value[])__VA_ARGS__)/sizeof(SpanType##_value)}}
-#define cspan_flatten(span) \
- {.data=(span)->data, .dim={(uint32_t)cspan_size(span)}}
-
/* create a cspan from a cvec, cstack, cdeq, cqueue, or cpque (heap) */
#define cspan_from(container) \
{.data=(container)->data, .dim={(uint32_t)(container)->_len}}
@@ -153,8 +151,9 @@ typedef struct { uint32_t d[4]; } cspan_idx4;
{.data=cspan_at(self, x, y, z, 0), .dim={(self)->dim[3]}}
// cspan_slice:
+// e.g.: cspan_slice(&ms3, c_SLICE(1,3), c_SLICE(0), c_SLICE(1,4));
-#define c_SLICE(...) ((const uint32_t[2]){__VA_ARGS__})
+#define c_SLICE(...) ((const uint32_t[2]){__VA_ARGS__})z
#define cspan_slice(self, ...) \
((void)((self)->data += c_PASTE(_cspan_slice, c_NUMARGS(__VA_ARGS__))((self)->dim, (self)->stride, __VA_ARGS__)))
@@ -183,6 +182,22 @@ STC_INLINE size_t _cspan_size(const uint32_t dim[], unsigned rank) {
return sz;
}
+#define _cspan_next_1(r, pos, d, s) (++pos[0], 1)
+#define _cspan_next_3 _cspan_next_2
+#define _cspan_next_4 _cspan_next_2
+
+static size_t _cspan_next_2(int rank, uint32_t pos[], const uint32_t dim[], const uint32_t stride[]) {
+ size_t off = 1, rs = 1;
+ ++pos[rank - 1];
+ while (--rank && pos[rank] == dim[rank]) {
+ pos[rank] = 0, ++pos[rank - 1];
+ const size_t ds = rs*dim[rank];
+ rs *= stride[rank];
+ off += rs - ds;
+ }
+ return off;
+}
+
STC_INLINE size_t _cspan_slice2(uint32_t dim[2], const cspan_idx2 stri, const uint32_t x[2], const uint32_t y[2]) {
const uint32_t x1 = x[1] ? x[1] : dim[0], y1 = y[1] ? y[1] : dim[1];
const size_t ret = _cspan_i2(dim, stri, x[0], y[0]);
diff --git a/misc/examples/multidim.c b/misc/examples/multidim.c
index d69a04fb..f3d9e865 100644
--- a/misc/examples/multidim.c
+++ b/misc/examples/multidim.c
@@ -16,49 +16,54 @@ int main()
ispan ms1 = cspan_from(&v);
// View the same data as a 3D array 2 x 3 x 4
- ispan3 ms3 = cspan_multidim(v.data, 2, 2, 6);
+ ispan3 ms3 = cspan_multidim(v.data, 2, 3, 4);
- // View data as contiguous memory representing 2 rows of 6 ints each
- ispan2 ms2 = cspan_at3(&ms3, 0);
- ms2.data = cspan_at(&ms2, 1, 1);
- ms2.dim[0] = 2;
- ms2.dim[1] = 3;
- for (unsigned i=0; i != ms2.dim[0]; i++) {
- for (unsigned j=0; j != ms2.dim[1]; j++)
- printf(" %2d", *cspan_at(&ms2, i, j));
+ puts("ms3:");
+ for (unsigned i=0; i != ms3.dim[0]; i++) {
+ for (unsigned j=0; j != ms3.dim[1]; j++) {
+ for (unsigned k=0; k != ms3.dim[2]; k++) {
+ printf(" %2d", *cspan_at(&ms3, i, j, k));
+ }
+ puts("");
+ }
+ puts("");
+ }
+ puts("ss3 = ms3[:, 1:3, 1:3]");
+ ispan3 ss3 = ms3;
+ cspan_slice(&ss3, c_SLICE(0), c_SLICE(1,3), c_SLICE(1,3));
+
+ for (unsigned i=0; i != ss3.dim[0]; i++) {
+ for (unsigned j=0; j != ss3.dim[1]; j++) {
+ for (unsigned k=0; k != ss3.dim[2]; k++) {
+ printf(" %2d", *cspan_at(&ss3, i, j, k));
+ }
+ puts("");
+ }
puts("");
}
- ms2 = (ispan2)cspan_at3(&ms3, 0);
+ puts("Iterate ss3 flat:");
+ c_FOREACH (i, ispan3, ss3)
+ printf(" %d", *i.ref);
+ puts("");
+
+ ispan2 ms2 = cspan_at3(&ms3, 0);
// write data using 2D view
for (unsigned i=0; i != ms2.dim[0]; i++)
for (unsigned j=0; j != ms2.dim[1]; j++)
*cspan_at(&ms2, i, j) = i*1000 + j;
- // print all items using 1D view
- printf("all: ");
+ puts("\nview data as 1D view:");
for (unsigned i=0; i != cspan_size(&ms1); i++)
printf(" %d", *cspan_at(&ms1, i));
puts("");
- // or iterate a subspan...
+ puts("iterate subspan ms3[1]:");
ispan2 sub = cspan_at3(&ms3, 1);
- printf("sub: ");
c_FOREACH (i, ispan2, sub)
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 ", *cspan_at(&ms3, i, j, k));
- puts("");
- }
- }
cstack_int_drop(&v);
}