diff options
| -rw-r--r-- | docs/cspan_api.md | 17 | ||||
| -rw-r--r-- | include/stc/cspan.h | 120 | ||||
| -rw-r--r-- | misc/examples/multidim.c | 3 | ||||
| -rw-r--r-- | misc/tests/cspan_test.c | 8 |
4 files changed, 52 insertions, 96 deletions
diff --git a/docs/cspan_api.md b/docs/cspan_api.md index 70587f3e..e8c53965 100644 --- a/docs/cspan_api.md +++ b/docs/cspan_api.md @@ -35,18 +35,19 @@ ValueType* cspan_at(SpanTypeN* self, intptr_t x, ...); // at(): num ValueType* cspan_front(SpanTypeN* self); ValueType* cspan_back(SpanTypeN* self); + // general slicing: create a subspan. can do the same as submd() and subspan(). +SpanTypeN cspan_slice(T SpanTypeN, SpanTypeM* parent, {x0,x1}, {y0,y1}, ...); // {v} reduces rank. {v,-1} slice to end. + // return a subspan of lower rank: -SpanType cspan_submd2(SpanType2* self, intptr_t x); // return a 1d subspan from a 2d span. -SpanTypeN cspan_submd3(SpanType3* self, intptr_t x, ...); // return a 1d or 2d subspan from a 3d span. -SpanTypeN cspan_submd4(SpanType4* self, intptr_t x, ...); // number of args determines rank of output span. +SpanType cspan_submd2(SpanType2* self, intptr_t x); // return a 1d subspan from a 2d span. +SpanTypeN cspan_submd3(SpanType3* self, intptr_t x, ...); // return a 1d or 2d subspan from a 3d span. +SpanTypeN cspan_submd4(SpanType4* self, intptr_t x, ...); // number of args determines rank of output span. SpanTypeN cspan_submd5(SpanType5* self, intptr_t x, ...); -void cspan_slice(SpanTypeN* self, {x0,x1}, {y0,y1},...); // slice a span to make it a subspan of same rank - // return a subspan of same rank. Similar to e.g. cspan_slice(&ms3, {offset, offset+count}, {0}, {0}); -SpanType cspan_subspan(const SpanType* self, intptr_t offset, intptr_t count); -SpanType2 cspan_subspan2(const SpanType2 self, intptr_t offset, intptr_t count); -SpanType3 cspan_subspan3(const SpanType3 self, intptr_t offset, intptr_t count); +SpanType cspan_subspan(SpanType* self, intptr_t offset, intptr_t count); +SpanType2 cspan_subspan2(SpanType2 self, intptr_t offset, intptr_t count); +SpanType3 cspan_subspan3(SpanType3 self, intptr_t offset, intptr_t count); SpanTypeN_iter SpanType_begin(const SpanTypeN* self); SpanTypeN_iter SpanType_end(const SpanTypeN* self); diff --git a/include/stc/cspan.h b/include/stc/cspan.h index 78c92520..94415df7 100644 --- a/include/stc/cspan.h +++ b/include/stc/cspan.h @@ -74,10 +74,10 @@ int demo2() { STC_INLINE Self Self##_from_n(Self##_raw* raw, const intptr_t n) { \ return (Self){.data=raw, .dim={(int32_t)n}}; \ } \ - STC_INLINE Self Self##_subslice_(Self##_value* v, const int32_t dim[], const int32_t stri[], \ + STC_INLINE Self Self##_slice_(Self##_value* v, const int32_t dim[], const int32_t stri[], \ const int rank, const int32_t a[][2]) { \ Self s = {.data=v}; int outrank; \ - s.data += _cspan_subslice(s.dim, s.stride.d, &outrank, dim, stri, rank, a); \ + s.data += _cspan_slice(s.dim, s.stride.d, &outrank, dim, stri, rank, a); \ c_ASSERT(outrank == RANK); \ return s; \ } \ @@ -90,7 +90,7 @@ int demo2() { return it; \ } \ STC_INLINE void Self##_next(Self##_iter* it) { \ - it->ref += _cspan_next_##RANK(RANK, it->pos, it->_s->dim, it->_s->stride.d); \ + 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 @@ -104,8 +104,7 @@ typedef struct { int32_t d[3]; } cspan_idx3; typedef struct { int32_t d[4]; } cspan_idx4; typedef struct { int32_t d[5]; } cspan_idx5; typedef struct { int32_t d[6]; } cspan_idx6; -#define c_END -1 -#define c_ALL 0,c_END +#define c_ALL 0,-1 #define cspan_md(array, ...) \ {.data=array, .dim={__VA_ARGS__}, .stride={.d={__VA_ARGS__}}} @@ -114,10 +113,10 @@ typedef struct { int32_t d[6]; } cspan_idx6; #define cspan_make(SpanType, ...) \ {.data=(SpanType##_value[])__VA_ARGS__, .dim={sizeof((SpanType##_value[])__VA_ARGS__)/sizeof(SpanType##_value)}} -#define cspan_subslice(OutSpan, parent, ...) \ - OutSpan##_subslice_((parent)->data, (parent)->dim, (parent)->stride.d, cspan_rank(parent) + \ - c_static_assert(cspan_rank(parent) == sizeof((int32_t[][2]){__VA_ARGS__})/sizeof(int32_t[2])), \ - (const int32_t[][2]){__VA_ARGS__}) +#define cspan_slice(OutSpan, parent, ...) \ + OutSpan##_slice_((parent)->data, (parent)->dim, (parent)->stride.d, cspan_rank(parent) + \ + c_static_assert(cspan_rank(parent) == sizeof((int32_t[][2]){__VA_ARGS__})/sizeof(int32_t[2])), \ + (const int32_t[][2]){__VA_ARGS__}) /* create a cspan from a cvec, cstack, cdeq, cqueue, or cpque (heap) */ #define cspan_from(container) \ @@ -129,29 +128,33 @@ typedef struct { int32_t d[6]; } cspan_idx6; #define cspan_size(self) _cspan_size((self)->dim, cspan_rank(self)) #define cspan_rank(self) c_ARRAYLEN((self)->dim) -#define cspan_idx(self, ...) \ - c_PASTE(_cspan_i, c_NUMARGS(__VA_ARGS__))((self)->dim, (self)->stride, __VA_ARGS__) - -#define cspan_index(self, ...) \ - (_cspan_index(c_NUMARGS(__VA_ARGS__), (self)->dim, (self)->stride.d, (int32_t[]){__VA_ARGS__}) + \ +#define cspan_index(self, ...) c_PASTE(cspan_idx_, c_NUMARGS(__VA_ARGS__))(self, __VA_ARGS__) +#define cspan_idx_1 cspan_idx_4 +#define cspan_idx_2 cspan_idx_4 +#define cspan_idx_3 cspan_idx_4 +#define cspan_idx_4(self, ...) \ + c_PASTE(_cspan_idx, c_NUMARGS(__VA_ARGS__))((self)->dim, (self)->stride, __VA_ARGS__) +#define cspan_idx_5(self, ...) \ + (_cspan_idxN(c_NUMARGS(__VA_ARGS__), (self)->dim, (self)->stride.d, (int32_t[]){__VA_ARGS__}) + \ c_static_assert(cspan_rank(self) == c_NUMARGS(__VA_ARGS__))) +#define cspan_idx_6 cspan_idx_5 #define cspan_at(self, ...) ((self)->data + cspan_index(self, __VA_ARGS__)) -#define cspan_item(self, ...) ((self)->data + cspan_idx(self, __VA_ARGS__)) // same as cspan_at(), only for rank <= 5 #define cspan_front(self) ((self)->data) #define cspan_back(self) ((self)->data + cspan_size(self) - 1) -// cspan_subspanN. for N > 3, use cspan_slice(&ms4, {offset, offset + count}, {0}, {0}, {0}); - +// cspan_subspanN. (N<5) Optimized, but same as e.g. cspan_slice(Span2, &ms4, {offset, offset + count}, {c_ALL}, {c_ALL}); #define cspan_subspan(self, offset, count) \ {.data=cspan_at(self, offset), .dim={count}} #define cspan_subspan2(self, offset, count) \ {.data=cspan_at(self, offset, 0), .dim={count, (self)->dim[1]}, .stride={(self)->stride}} #define cspan_subspan3(self, offset, count) \ {.data=cspan_at(self, offset, 0, 0), .dim={count, (self)->dim[1], (self)->dim[2]}, .stride={(self)->stride}} +#define cspan_subspan4(self, offset, count) \ + {.data=cspan_at(self, offset, 0, 0, 0), .dim={count, (self)->dim[1], (self)->dim[2], (self)->dim[3]}, \ + .stride={(self)->stride}} // cspan_submdN: return reduced rank - #define cspan_submd4(...) c_MACRO_OVERLOAD(cspan_submd4, __VA_ARGS__) #define cspan_submd3(...) c_MACRO_OVERLOAD(cspan_submd3, __VA_ARGS__) #define cspan_submd2(self, x) \ @@ -169,50 +172,24 @@ typedef struct { int32_t d[6]; } cspan_idx6; #define cspan_submd4_4(self, x, y, z) \ {.data=cspan_at(self, x, y, z, 0), .dim={(self)->dim[3]}} -#define cspan_submd5_2(self, x) \ - {.data=cspan_at(self, x, 0, 0, 0, 0), .dim={(self)->dim[1], (self)->dim[2], (self)->dim[3], (self)->dim[4]}, \ - .stride={.d={0, (self)->stride.d[2], (self)->stride.d[3], (self)->stride.d[4]}}} -#define cspan_submd5_3(self, x, y) \ - {.data=cspan_at(self, x, y, 0, 0, 0), .dim={(self)->dim[2], (self)->dim[3], (self)->dim[4]}, \ - .stride={.d={0, (self)->stride.d[3], (self)->stride.d[4]}}} -#define cspan_submd5_4(self, x, y, z) \ - {.data=cspan_at(self, x, y, z, 0, 0), .dim={(self)->dim[3], (self)->dim[4]}, .stride={.d={0, (self)->stride.d[4]}}} -#define cspan_submd5_5(self, x, y, z, w) \ - {.data=cspan_at(self, x, y, z, w, 0), .dim={(self)->dim[4]}} - -// cspan_slice: -// e.g.: cspan_slice(&ms3, {1,3}, {0,-1}, {1,4}); - -#define cspan_slice(self, ...) \ - ((void)((self)->data += _cspan_slice((self)->dim, (self)->stride.d, \ - cspan_rank(self), (const int32_t[][2]){__VA_ARGS__}) + \ - c_static_assert(cspan_rank(self) == \ - sizeof((const int32_t[][2]){__VA_ARGS__})/sizeof(int32_t[2])))) - // FUNCTIONS -STC_INLINE intptr_t _cspan_i1(const int32_t dim[1], const cspan_idx1 stri, int32_t x) +STC_INLINE intptr_t _cspan_idx1(const int32_t dim[1], const cspan_idx1 stri, int32_t x) { c_ASSERT(c_LTu(x, dim[0])); return x; } -STC_INLINE intptr_t _cspan_i2(const int32_t dim[2], const cspan_idx2 stri, int32_t x, int32_t y) +STC_INLINE intptr_t _cspan_idx2(const int32_t dim[2], const cspan_idx2 stri, int32_t x, int32_t y) { c_ASSERT(c_LTu(x, dim[0]) && c_LTu(y, dim[1])); return (intptr_t)stri.d[1]*x + y; } -STC_INLINE intptr_t _cspan_i3(const int32_t dim[3], const cspan_idx3 stri, int32_t x, int32_t y, int32_t z) { +STC_INLINE intptr_t _cspan_idx3(const int32_t dim[3], const cspan_idx3 stri, int32_t x, int32_t y, int32_t z) { c_ASSERT(c_LTu(x, dim[0]) && c_LTu(y, dim[1]) && c_LTu(z, dim[2])); return (intptr_t)stri.d[2]*(stri.d[1]*x + y) + z; } -STC_INLINE intptr_t _cspan_i4(const int32_t dim[4], const cspan_idx4 stri, int32_t x, int32_t y, - int32_t z, int32_t w) { +STC_INLINE intptr_t _cspan_idx4(const int32_t dim[4], const cspan_idx4 stri, int32_t x, int32_t y, + int32_t z, int32_t w) { c_ASSERT(c_LTu(x, dim[0]) && c_LTu(y, dim[1]) && c_LTu(z, dim[2]) && c_LTu(w, dim[3])); return (intptr_t)stri.d[3]*(stri.d[2]*(stri.d[1]*x + y) + z) + w; } -STC_INLINE intptr_t _cspan_i5(const int32_t dim[4], const cspan_idx4 stri, int32_t x, int32_t y, int32_t z, - int32_t w, int32_t v) { - c_ASSERT(c_LTu(x, dim[0]) && c_LTu(y, dim[1]) && c_LTu(z, dim[2]) && c_LTu(w, dim[3]) && c_LTu(v, dim[4])); - return (intptr_t)stri.d[4]*(stri.d[3]*(stri.d[2]*(stri.d[1]*x + y) + z) + w) + v; -} - -STC_INLINE intptr_t _cspan_index(int rank, const int32_t dim[], const int32_t stri[], const int32_t a[]) { +STC_INLINE intptr_t _cspan_idxN(int rank, const int32_t dim[], const int32_t stri[], const int32_t a[]) { intptr_t off = a[0]; bool ok = c_LTu(a[0], dim[0]); for (int i = 1; i < rank; ++i) { @@ -230,12 +207,13 @@ STC_INLINE intptr_t _cspan_size(const int32_t dim[], int 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 -#define _cspan_next_5 _cspan_next_2 +#define _cspan_next1(r, pos, d, s) (++pos[0], 1) +#define _cspan_next3 _cspan_next2 +#define _cspan_next4 _cspan_next2 +#define _cspan_next5 _cspan_next2 +#define _cspan_next6 _cspan_next2 -STC_INLINE intptr_t _cspan_next_2(int rank, int32_t pos[], const int32_t dim[], const int32_t stride[]) { +STC_INLINE intptr_t _cspan_next2(int rank, int32_t pos[], const int32_t dim[], const int32_t stride[]) { intptr_t off = 1, rs = 1; ++pos[rank - 1]; while (--rank && pos[rank] == dim[rank]) { @@ -247,30 +225,10 @@ STC_INLINE intptr_t _cspan_next_2(int rank, int32_t pos[], const int32_t dim[], return off; } -STC_INLINE intptr_t _cspan_slice(int32_t dim[], const int32_t stri[], const int rank, const int32_t a[][2]) { - intptr_t off = 0; - bool ok = true; - for (int i = 0; i < rank; ++i) { - off *= stri[i]; - off += a[i][0]; - int32_t t; - switch (a[i][1]) { - case 0: t = a[i][0] + 1; break; - case -1: t = dim[i]; break; - default: t = a[i][1]; - } - dim[i] = t - a[i][0]; - ok &= c_LTu(0, dim[i]); - } - c_ASSERT(ok); - return off; -} - -STC_INLINE intptr_t _cspan_subslice(int32_t odim[], int32_t ostri[], int* orank, - const int32_t dim[], const int32_t stri[], - int rank, const int32_t a[][2]) { - intptr_t off = a[0][0]; - intptr_t s = 1; +STC_INLINE intptr_t _cspan_slice(int32_t odim[], int32_t ostri[], int* orank, + const int32_t dim[], const int32_t stri[], + int rank, const int32_t a[][2]) { + intptr_t off = 0, s = 1; int i = 0, j = 0, ok = true; for (; i < rank; ++i) { off *= stri[i]; @@ -283,11 +241,11 @@ STC_INLINE intptr_t _cspan_subslice(int32_t odim[], int32_t ostri[], int* orank, } odim[j] = t - a[i][0]; ostri[j] = s*stri[i]; + ok &= c_LTu(0, odim[j]) & !c_LTu(dim[i], t); s = 1; ++j; - ok &= c_LTu(0, odim[i]) & !c_LTu(dim[i], t); } *orank = j; - c_ASSERT(ok); /* input indices ok */ + c_ASSERT(ok); return off; } #endif diff --git a/misc/examples/multidim.c b/misc/examples/multidim.c index 49b24172..49d7fbc4 100644 --- a/misc/examples/multidim.c +++ b/misc/examples/multidim.c @@ -5,7 +5,6 @@ #include <stdio.h> using_cspan3(ispan, int); -#define c_ALL 0,-1 int main() { @@ -32,7 +31,7 @@ int main() puts("ss3 = ms3[:, 1:3, 1:3]"); ispan3 ss3 = ms3; //cspan_slice(&ss3, {c_ALL}, {1,3}, {1,3}); - ss3 = cspan_subslice(ispan3, &ms3, {c_ALL}, {1,3}, {1,3}); + ss3 = cspan_slice(ispan3, &ms3, {c_ALL}, {1,3}, {1,3}); for (int i=0; i != ss3.dim[0]; i++) { for (int j=0; j != ss3.dim[1]; j++) { diff --git a/misc/tests/cspan_test.c b/misc/tests/cspan_test.c index cd6a1271..044ce629 100644 --- a/misc/tests/cspan_test.c +++ b/misc/tests/cspan_test.c @@ -31,8 +31,7 @@ CTEST(cspan, slice) { } } - intspan2 m2 = m1; - cspan_slice(&m2, {c_ALL}, {2,4}); + intspan2 m2 = cspan_slice(intspan2, &m1, {c_ALL}, {2,4}); size_t sum2 = 0; for (size_t i = 0; i < m2.dim[0]; ++i) { @@ -54,7 +53,7 @@ CTEST(cspan, slice2) { cstack_int_push(&stack, i); intspan3 ms3 = cspan_md(stack.data, 10, 20, 30); - cspan_slice(&ms3, {1,4}, {3,7}, {20,24}); + ms3 = cspan_slice(intspan3, &ms3, {1,4}, {3,7}, {20,24}); size_t sum = 0; for (size_t i = 0; i < ms3.dim[0]; ++i) { @@ -98,8 +97,7 @@ CTEST_SETUP(cspan_cube) { c_FORRANGE (i, 0, ms3.dim[0], TSIZE) { c_FORRANGE (j, 0, ms3.dim[1], TSIZE) { c_FORRANGE (k, 0, ms3.dim[2], TSIZE) { - intspan3 tile = ms3; - cspan_slice(&tile, {i, i + TSIZE}, {j, j + TSIZE}, {k, k + TSIZE}); + intspan3 tile = cspan_slice(intspan3, &ms3, {i, i + TSIZE}, {j, j + TSIZE}, {k, k + TSIZE}); Tiles_push(&_self->tiles, tile); } } |
