From 900295256d825fc323149cd223c49787f32a3696 Mon Sep 17 00:00:00 2001 From: tylov Date: Thu, 20 Jul 2023 15:09:10 +0200 Subject: Moved examples to sub-directories. Added cotask1.c cotask2.c examples. --- misc/examples/spans/multidim.c | 67 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 misc/examples/spans/multidim.c (limited to 'misc/examples/spans/multidim.c') diff --git a/misc/examples/spans/multidim.c b/misc/examples/spans/multidim.c new file mode 100644 index 00000000..798a1126 --- /dev/null +++ b/misc/examples/spans/multidim.c @@ -0,0 +1,67 @@ +// Example based on https://en.cppreference.com/w/cpp/container/mdspan +#define i_val int +#include +#include +#include + +using_cspan3(ispan, int); + +int main(void) +{ + cstack_int v = c_init(cstack_int, {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24}); + + // View data as contiguous memory representing 24 ints + ispan ms1 = cspan_from(&v); + + // View the same data as a 3D array 2 x 3 x 4 + ispan3 ms3 = cspan_md(v.data, 2, 3, 4); + + puts("ms3:"); + for (int i=0; i != ms3.shape[0]; i++) { + for (int j=0; j != ms3.shape[1]; j++) { + for (int k=0; k != ms3.shape[2]; k++) { + printf(" %2d", *cspan_at(&ms3, i, j, k)); + } + puts(""); + } + puts(""); + } + puts("ss3 = ms3[:, 1:3, 1:3]"); + ispan3 ss3 = ms3; + ss3 = cspan_slice(ispan3, &ms3, {c_ALL}, {1,3}, {1,3}); + + for (int i=0; i != ss3.shape[0]; i++) { + for (int j=0; j != ss3.shape[1]; j++) { + for (int k=0; k != ss3.shape[2]; k++) { + printf(" %2d", *cspan_at(&ss3, i, j, k)); + } + puts(""); + } + puts(""); + } + + puts("Iterate ss3 flat:"); + c_foreach (i, ispan3, ss3) + printf(" %d", *i.ref); + puts(""); + + ispan2 ms2 = cspan_submd3(&ms3, 0); + + // write data using 2D view + for (int i=0; i != ms2.shape[0]; i++) + for (int j=0; j != ms2.shape[1]; j++) + *cspan_at(&ms2, i, j) = i*1000 + j; + + puts("\nview data as 1D view:"); + for (int i=0; i != cspan_size(&ms1); i++) + printf(" %d", *cspan_at(&ms1, i)); + puts(""); + + puts("iterate subspan ms3[1]:"); + ispan2 sub = cspan_submd3(&ms3, 1); + c_foreach (i, ispan2, sub) + printf(" %d", *i.ref); + puts(""); + + cstack_int_drop(&v); +} -- cgit v1.2.3 From ac7afe963527eb66a12962c638242f0426b39575 Mon Sep 17 00:00:00 2001 From: tylov Date: Sat, 19 Aug 2023 18:55:41 +0200 Subject: Polishing cspan.h. Updated multidim.c cspan example. --- docs/cstr_api.md | 6 ++-- include/stc/cspan.h | 19 +++++++---- misc/examples/spans/multidim.c | 75 ++++++++++++++++++++++-------------------- 3 files changed, 55 insertions(+), 45 deletions(-) (limited to 'misc/examples/spans/multidim.c') diff --git a/docs/cstr_api.md b/docs/cstr_api.md index 5f6ce9e4..397634ec 100644 --- a/docs/cstr_api.md +++ b/docs/cstr_api.md @@ -120,14 +120,14 @@ cstr_iter cstr_advance(cstr_iter it, intptr_t n); // utf8 functions requires linking with src/utf8code.c symbols: bool cstr_valid_utf8(const cstr* self); // check if str is valid utf8 -cstr cstr_casefold_sv(csview sv); // returns new casefolded utf8 cstr +cstr cstr_casefold_sv(csview sv); // returns new casefolded utf8 cstr cstr cstr_tolower(const char* str); // returns new lowercase utf8 cstr -cstr cstr_tolower_sv(csview sv); // returns new lowercase utf8 cstr +cstr cstr_tolower_sv(csview sv); // returns new lowercase utf8 cstr void cstr_lowercase(cstr* self); // transform cstr to lowercase utf8 cstr cstr_toupper(const char* str); // returns new uppercase utf8 cstr -cstr cstr_toupper_sv(csview sv); // returns new uppercase utf8 cstr +cstr cstr_toupper_sv(csview sv); // returns new uppercase utf8 cstr void cstr_uppercase(cstr* self); // transform cstr to uppercase utf8 int cstr_icmp(const cstr* s1, const cstr* s2); // utf8 case-insensitive comparison diff --git a/include/stc/cspan.h b/include/stc/cspan.h index b8b191f1..32921390 100644 --- a/include/stc/cspan.h +++ b/include/stc/cspan.h @@ -244,24 +244,29 @@ STC_API int32_t* _cspan_shape2stride(char order, int32_t shape[], int rank); STC_DEF intptr_t _cspan_next2(int32_t pos[], const int32_t shape[], const int32_t stride[], int rank, int* done) { int i, inc; - if (stride[0] < stride[rank - 1]) i = rank - 1, inc = -1; else i = 0, inc = 1; + if (stride[0] < stride[rank - 1]) i = rank - 1, inc = -1; + else /* order 'C' */ i = 0, inc = 1; + intptr_t off = stride[i]; ++pos[i]; - for (; --rank && pos[i] == shape[i]; i += inc) { + while (--rank && pos[i] == shape[i]) { pos[i] = 0; ++pos[i + inc]; off += stride[i + inc] - stride[i]*shape[i]; + i += inc; } *done = pos[i] == shape[i]; return off; } STC_DEF int32_t* _cspan_shape2stride(char order, int32_t shape[], int rank) { - int32_t k = 1, i, j, inc, s1, s2; - if (order == 'F') i = 0, j = rank, inc = 1; - else /* 'C' */ i = rank - 1, j = -1, inc = -1; - s1 = shape[i]; shape[i] = 1; + int i, inc; + if (order == 'F') i = 0, inc = 1; + else i = rank - 1, inc = -1; + int32_t k = 1, s1 = shape[i], s2; - for (i += inc; i != j; i += inc) { + shape[i] = 1; + while (--rank) { + i += inc; s2 = shape[i]; shape[i] = (k *= s1); s1 = s2; diff --git a/misc/examples/spans/multidim.c b/misc/examples/spans/multidim.c index 798a1126..ebc05a70 100644 --- a/misc/examples/spans/multidim.c +++ b/misc/examples/spans/multidim.c @@ -1,66 +1,71 @@ // Example based on https://en.cppreference.com/w/cpp/container/mdspan #define i_val int #include +#define i_implement #include #include using_cspan3(ispan, int); +void print2d(ispan2 ms2) { + for (int i=0; i < ms2.shape[0]; i++) { + for (int j=0; j < ms2.shape[1]; j++) + printf(" %3d", *cspan_at(&ms2, i, j)); + puts(""); + } +} + +void print3d(ispan3 ms3) { + for (int i=0; i < ms3.shape[0]; i++) { + for (int j=0; j < ms3.shape[1]; j++) { + for (int k=0; k < ms3.shape[2]; k++) + printf(" %3d", *cspan_at(&ms3, i, j, k)); + puts(""); + } + puts(""); + } +} + int main(void) { cstack_int v = c_init(cstack_int, {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24}); - // View data as contiguous memory representing 24 ints + // Create 1d span from a compatibel container ispan ms1 = cspan_from(&v); - // View the same data as a 3D array 2 x 3 x 4 + // Create a 3D mdspan 2 x 3 x 4 ispan3 ms3 = cspan_md(v.data, 2, 3, 4); puts("ms3:"); - for (int i=0; i != ms3.shape[0]; i++) { - for (int j=0; j != ms3.shape[1]; j++) { - for (int k=0; k != ms3.shape[2]; k++) { - printf(" %2d", *cspan_at(&ms3, i, j, k)); - } - puts(""); - } - puts(""); - } - puts("ss3 = ms3[:, 1:3, 1:3]"); - ispan3 ss3 = ms3; - ss3 = cspan_slice(ispan3, &ms3, {c_ALL}, {1,3}, {1,3}); + print3d(ms3); - for (int i=0; i != ss3.shape[0]; i++) { - for (int j=0; j != ss3.shape[1]; j++) { - for (int k=0; k != ss3.shape[2]; k++) { - printf(" %2d", *cspan_at(&ss3, i, j, k)); - } - puts(""); - } - puts(""); - } + // Take a slice of md3 + ispan3 ss3 = cspan_slice(ispan3, &ms3, {c_ALL}, {1,3}, {1,3}); + puts("ss3 = ms3[:, 1:3, 1:3]"); + print3d(ss3); puts("Iterate ss3 flat:"); - c_foreach (i, ispan3, ss3) - printf(" %d", *i.ref); + c_foreach (i, ispan3, ss3) printf(" %d", *i.ref); puts(""); - ispan2 ms2 = cspan_submd3(&ms3, 0); + // submd3 span reduces rank depending on number of arguments + ispan2 ms2 = cspan_submd3(&ms3, 1); - // write data using 2D view + // Change data on the 2d subspan for (int i=0; i != ms2.shape[0]; i++) for (int j=0; j != ms2.shape[1]; j++) - *cspan_at(&ms2, i, j) = i*1000 + j; + *cspan_at(&ms2, i, j) = (i + 1)*100 + j; + + puts("\nms2 = ms3[1] with updated data:"); + print2d(ms2); + puts(""); - puts("\nview data as 1D view:"); - for (int i=0; i != cspan_size(&ms1); i++) - printf(" %d", *cspan_at(&ms1, i)); + puts("\nOriginal s1 span with updated data:"); + c_foreach (i, ispan, ms1) printf(" %d", *i.ref); puts(""); - puts("iterate subspan ms3[1]:"); - ispan2 sub = cspan_submd3(&ms3, 1); - c_foreach (i, ispan2, sub) - printf(" %d", *i.ref); + puts("\nOriginal ms3 span with updated data:"); + print3d(ms3); puts(""); cstack_int_drop(&v); -- cgit v1.2.3 From 263dbab626e6a99f7959a4c1716f0496906ee638 Mon Sep 17 00:00:00 2001 From: Tyge Lovset Date: Wed, 30 Aug 2023 08:24:54 +0200 Subject: Some simplifications. Added i_ndebug macro flag to disable assertions in cspan. --- include/stc/ccommon.h | 6 ++---- include/stc/cspan.h | 42 +++++++++++++++--------------------------- misc/examples/spans/multidim.c | 4 ++++ 3 files changed, 21 insertions(+), 31 deletions(-) (limited to 'misc/examples/spans/multidim.c') diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 6e90f75a..ad92212a 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -69,16 +69,14 @@ typedef long long _llong; #define c_new(T, ...) ((T*)memcpy(malloc(sizeof(T)), ((T[]){__VA_ARGS__}), sizeof(T))) #define c_LITERAL(T) (T) #endif -#define c_new_n(T, n) ((T*)malloc(sizeof(T)*(size_t)(n))) +#define c_new_n(T, n) ((T*)malloc(sizeof(T)*c_i2u(n))) #define c_malloc(sz) malloc(c_i2u(sz)) #define c_calloc(n, sz) calloc(c_i2u(n), c_i2u(sz)) #define c_realloc(p, sz) realloc(p, c_i2u(sz)) #define c_free(p) free(p) #define c_delete(T, ptr) do { T *_tp = ptr; T##_drop(_tp); free(_tp); } while (0) -#define c_static_assert(...) c_MACRO_OVERLOAD(c_static_assert, __VA_ARGS__) -#define c_static_assert_1(b) ((int)(0*sizeof(int[(b) ? 1 : -1]))) -#define c_static_assert_2(b, m) c_static_assert_1(b) +#define c_static_assert(expr) (1 ? 0 : (int)sizeof(int[(expr) ? 1 : -1])) #if defined STC_NDEBUG || defined NDEBUG #define c_assert(expr) ((void)0) #else diff --git a/include/stc/cspan.h b/include/stc/cspan.h index 8a422dad..3f2b300f 100644 --- a/include/stc/cspan.h +++ b/include/stc/cspan.h @@ -63,6 +63,12 @@ int demo2() { #include "priv/linkage.h" #include "ccommon.h" +#ifdef i_ndebug + #define cspan_assert(x) ((void)0) +#else + #define cspan_assert(x) c_assert(x) +#endif + #define using_cspan(...) c_MACRO_OVERLOAD(using_cspan, __VA_ARGS__) #define using_cspan_2(Self, T) \ using_cspan_3(Self, T, 1); \ @@ -85,7 +91,7 @@ int demo2() { const int rank, const int32_t a[][2]) { \ Self s; int outrank; \ s.data = d + _cspan_slice(s.shape, s.stride.d, &outrank, shape, stri, rank, a); \ - c_assert(outrank == RANK); \ + cspan_assert(outrank == RANK); \ return s; \ } \ STC_INLINE Self##_iter Self##_begin(const Self* self) { \ @@ -135,10 +141,12 @@ typedef enum {c_ROWMAJOR, c_COLMAJOR} cspan_layout; #define cspan_is_colmajor(self) ((self)->stride.d[0] < (self)->stride.d[cspan_rank(self) - 1]) #define cspan_is_rowmajor(self) (!cspan_is_colmajor(self)) #define cspan_get_layout(self) (cspan_is_colmajor(self) ? c_COLMAJOR : c_ROWMAJOR) -#define cspan_index(self, ...) c_PASTE(cspan_idx_, c_NUMARGS(__VA_ARGS__))(self, __VA_ARGS__) #define cspan_at(self, ...) ((self)->data + cspan_index(self, __VA_ARGS__)) #define cspan_front(self) ((self)->data) #define cspan_back(self) ((self)->data + cspan_size(self) - 1) +#define cspan_index(self, ...) \ + (_cspan_index(c_NUMARGS(__VA_ARGS__), (self)->shape, (self)->stride.d, (int32_t[]){__VA_ARGS__}) + \ + c_static_assert(cspan_rank(self) == c_NUMARGS(__VA_ARGS__))) // general // cspan_subspanX: (X <= 3) optimized. Similar to cspan_slice(Span3, &ms3, {off,off+count}, {c_ALL}, {c_ALL}); #define cspan_subspan(self, offset, count) \ @@ -183,17 +191,6 @@ typedef enum {c_ROWMAJOR, c_COLMAJOR} cspan_layout; /* ------------------- PRIVAT DEFINITIONS ------------------- */ -// cspan_index() helpers: -#define cspan_idx_1 cspan_idx_3 -#define cspan_idx_2 cspan_idx_3 -#define cspan_idx_3(self, ...) \ - c_PASTE(_cspan_idx, c_NUMARGS(__VA_ARGS__))((self)->shape, (self)->stride, __VA_ARGS__) // small/fast -#define cspan_idx_4(self, ...) \ - (_cspan_idxN(c_NUMARGS(__VA_ARGS__), (self)->shape, (self)->stride.d, (int32_t[]){__VA_ARGS__}) + \ - c_static_assert(cspan_rank(self) == c_NUMARGS(__VA_ARGS__))) // general -#define cspan_idx_5 cspan_idx_4 -#define cspan_idx_6 cspan_idx_4 - STC_INLINE intptr_t _cspan_size(const int32_t shape[], int rank) { intptr_t sz = shape[0]; while (--rank > 0) sz *= shape[rank]; @@ -207,20 +204,10 @@ STC_INLINE void _cspan_transpose(int32_t shape[], int32_t stride[], int rank) { } } -STC_INLINE intptr_t _cspan_idx1(const int32_t shape[1], const cspan_tuple1 stri, int32_t x) - { c_assert(c_LTu(x, shape[0])); return (intptr_t)stri.d[0]*x; } - -STC_INLINE intptr_t _cspan_idx2(const int32_t shape[2], const cspan_tuple2 stri, int32_t x, int32_t y) - { c_assert(c_LTu(x, shape[0]) && c_LTu(y, shape[1])); return (intptr_t)stri.d[0]*x + stri.d[1]*y; } - -STC_INLINE intptr_t _cspan_idx3(const int32_t shape[3], const cspan_tuple3 stri, int32_t x, int32_t y, int32_t z) { - c_assert(c_LTu(x, shape[0]) && c_LTu(y, shape[1]) && c_LTu(z, shape[2])); - return (intptr_t)stri.d[0]*x + stri.d[1]*y + stri.d[2]*z; -} -STC_INLINE intptr_t _cspan_idxN(int rank, const int32_t shape[], const int32_t stride[], const int32_t a[]) { +STC_INLINE intptr_t _cspan_index(int rank, const int32_t shape[], const int32_t stride[], const int32_t a[]) { intptr_t off = 0; while (rank--) { - c_assert(c_LTu(a[rank], shape[rank])); + cspan_assert(c_LTu(a[rank], shape[rank])); off += stride[rank]*a[rank]; } return off; @@ -283,13 +270,13 @@ STC_DEF intptr_t _cspan_slice(int32_t oshape[], int32_t ostride[], int* orank, for (; i < rank; ++i) { off += stride[i]*a[i][0]; switch (a[i][1]) { - case 0: c_assert(c_LTu(a[i][0], shape[i])); continue; + case 0: cspan_assert(c_LTu(a[i][0], shape[i])); continue; case -1: end = shape[i]; break; default: end = a[i][1]; } oshape[oi] = end - a[i][0]; ostride[oi] = stride[i]; - c_assert(c_LTu(0, oshape[oi]) & !c_LTu(shape[i], end)); + cspan_assert(c_LTu(0, oshape[oi]) & !c_LTu(shape[i], end)); ++oi; } *orank = oi; @@ -297,6 +284,7 @@ STC_DEF intptr_t _cspan_slice(int32_t oshape[], int32_t ostride[], int* orank, } #endif +#undef i_ndebug #undef i_opt #undef i_header #undef i_implement diff --git a/misc/examples/spans/multidim.c b/misc/examples/spans/multidim.c index ebc05a70..70fda7e2 100644 --- a/misc/examples/spans/multidim.c +++ b/misc/examples/spans/multidim.c @@ -66,6 +66,10 @@ int main(void) puts("\nOriginal ms3 span with updated data:"); print3d(ms3); + + puts("col = ms3[1, :, 2]"); + ispan col = cspan_slice(ispan, &ms3, {1}, {c_ALL}, {2}); + c_foreach (i, ispan, col) printf(" %d", *i.ref); puts(""); cstack_int_drop(&v); -- cgit v1.2.3