diff options
| -rw-r--r-- | docs/cspan_api.md | 5 | ||||
| -rw-r--r-- | include/stc/cspan.h | 35 | ||||
| -rw-r--r-- | misc/examples/multidim.c | 55 |
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); } |
