From 770a39ff6ed39494569a411949f22edcdb7eb30c Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sun, 15 Jan 2023 21:18:39 +0100 Subject: Large commit: - Moved stc/algo/cspan.h to stc/cspan.h - its a data view type similar to csview. +Many updates. Added docs/cspan_api.md page! - Update c11/fmt.h to VER 2.0: NEW API, see test. NOTE: fmt.h is not officially part of STC, as it is C11, and STC is C99. - Renamed crange_LITERAL() back to crange_literal(), and cspan_LITERAL() to cspan_literal(). These returns a compound literal (lvalue) that can be passed to a c_FOR*-iterator. --- include/c11/fmt.h | 90 +++++++++++++-------------- include/stc/algo/crange.h | 4 +- include/stc/algo/cspan.h | 132 --------------------------------------- include/stc/ccommon.h | 5 ++ include/stc/cspan.h | 154 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 205 insertions(+), 180 deletions(-) delete mode 100644 include/stc/algo/cspan.h create mode 100644 include/stc/cspan.h (limited to 'include') diff --git a/include/c11/fmt.h b/include/c11/fmt.h index 6e2f8e55..b42bd9fc 100644 --- a/include/c11/fmt.h +++ b/include/c11/fmt.h @@ -1,16 +1,19 @@ #ifndef FMT_H_INCLUDED #define FMT_H_INCLUDED -/* -void fmt_print(dst, fmt, ...); -void fmt_drop_buffer(fmt_buffer* buf); +/* +VER 2.0: NEW API: - dst - destination, one of: - int fd 1=stdout, 2=stderr +void fmt_print(fmt, ...); +void fmt_println(fmt, ...); // see remark below +void fmt_printd(dest, fmt, ...); +void fmt_freebuffer(fmt_buffer* buf); + + dest - destination, one of: FILE* fp Write to a file char* strbuf Write to a pre-allocated string buffer fmt_buffer* buf Auto realloc the needed memory (safe). Set buf->stream=1 for stream-mode. - Call fmt_drop_buffer(buf) after usage. + Call fmt_freebuffer(buf) after usage. fmt - format string {} Auto-detected format. If :MOD is not specified, @@ -22,10 +25,11 @@ void fmt_drop_buffer(fmt_buffer* buf); * C11 or higher required. * MAX 255 chars fmt string by default. MAX 12 arguments after fmt string. +* fmt_println(): a) fmt must be a const char* literal. b) at least one argument after fmt required by ISO C99. * Static linking by default, shared symbols by defining FMT_HEADER / FMT_IMPLEMENT. * (c) operamint, 2022, MIT License. ----------------------------------------------------------------------------------- -#include "fmt.h" +#include "c11/fmt.h" int main() { const double pi = 3.141592653589793; @@ -37,22 +41,22 @@ int main() { unsigned char r = 123, g = 214, b = 90, w = 110; char buffer[64]; - fmt_print(1, "Color: ({} {} {}), {}\n", r, g, b, flag); - fmt_print(1, "Wide: {}, {}\n", wstr, L"wide world"); - fmt_print(1, "{:10} {:10} {:10.2f}\n", 42ull, 43, pi); - fmt_print(stdout, "{:>10} {:>10} {:>10}\n", z, z, w); - fmt_print(stdout, "{:10} {:10} {:10}\n", "Hello", "Mad", "World"); - fmt_print(stderr, "100%: {:<20} {:.*} {}\n", string, 4, pi, x); - fmt_print(buffer, "Precision: {} {:.10} {}", string, pi, x); - fmt_print(1, "{}\n", buffer); - fmt_print(1, "Vector: ({}, {}, {})\n", 3.2, 3.3, pi); + fmt_print("Color: ({} {} {}), {}\n", r, g, b, flag); + fmt_println("Wide: {}, {}", wstr, L"wide world"); + fmt_println("{:10} {:10} {:10.2f}", 42ull, 43, pi); + fmt_println("{:>10} {:>10} {:>10}", z, z, w); + fmt_printd(stdout, "{:10} {:10} {:10}\n", "Hello", "Mad", "World"); + fmt_printd(stderr, "100%: {:<20} {:.*} {}\n", string, 4, pi, x); + fmt_printd(buffer, "Precision: {} {:.10} {}", string, pi, x); + fmt_println("{}", buffer); + fmt_println("Vector: ({}, {}, {})", 3.2, 3.3, pi); fmt_buffer out[1] = {{.stream=1}}; - fmt_print(out, "{} {}", "Pi is:", pi); - fmt_print(1, "{}, len={}, cap={}\n", out->data, out->len, out->cap); - fmt_print(out, "{} {}", ", Pi squared is:", pi*pi); - fmt_print(1, "{}, len={}, cap={}\n", out->data, out->len, out->cap); - fmt_drop_buffer(out); + fmt_printd(out, "{} {}", "Pi is:", pi); + fmt_print("{}, len={}, cap={}\n", out->data, out->len, out->cap); + fmt_printd(out, "{} {}", ", Pi squared is:", pi*pi); + fmt_print("{}, len={}, cap={}\n", out->data, out->len, out->cap); + fmt_freebuffer(out); } */ #include @@ -87,58 +91,60 @@ typedef struct { _Bool stream; } fmt_buffer; -FMT_API void fmt_drop_buffer(fmt_buffer* buf); +FMT_API void fmt_freebuffer(fmt_buffer* buf); FMT_API int _fmt_parse(char* p, int nargs, const char *fmt, ...); -FMT_API void _fmt_iprint(int fd, const char* fmt, ...); FMT_API void _fmt_bprint(fmt_buffer*, const char* fmt, ...); #ifndef FMT_MAX #define FMT_MAX 256 #endif +#define fmt_print(...) fmt_printd(stdout, __VA_ARGS__) +#define fmt_println(fmt, ...) fmt_printd(stdout, fmt "\n", __VA_ARGS__) + /* Primary function. */ -#define fmt_print(...) fmt_OVERLOAD(fmt_print, __VA_ARGS__) -#define fmt_print2(to, fmt) \ +#define fmt_printd(...) fmt_OVERLOAD(fmt_printd, __VA_ARGS__) +#define fmt_printd2(to, fmt) \ do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 0, fmt); \ fmt_OK(_n == 0); _fmt_fn(to)(to, fmt); } while (0) -#define fmt_print3(to, fmt, c) \ +#define fmt_printd3(to, fmt, c) \ do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 1, fmt, _fc(c)); \ fmt_OK(_n == 1); _fmt_fn(to)(to, _fs, c); } while (0) -#define fmt_print4(to, fmt, c, d) \ +#define fmt_printd4(to, fmt, c, d) \ do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 2, fmt, _fc(c), _fc(d)); \ fmt_OK(_n == 2); _fmt_fn(to)(to, _fs, c, d); } while (0) -#define fmt_print5(to, fmt, c, d, e) \ +#define fmt_printd5(to, fmt, c, d, e) \ do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 3, fmt, _fc(c), _fc(d), _fc(e)); \ fmt_OK(_n == 3); _fmt_fn(to)(to, _fs, c, d, e); } while (0) -#define fmt_print6(to, fmt, c, d, e, f) \ +#define fmt_printd6(to, fmt, c, d, e, f) \ do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 4, fmt, _fc(c), _fc(d), _fc(e), _fc(f)); \ fmt_OK(_n == 4); _fmt_fn(to)(to, _fs, c, d, e, f); } while (0) -#define fmt_print7(to, fmt, c, d, e, f, g) \ +#define fmt_printd7(to, fmt, c, d, e, f, g) \ do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 5, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g)); \ fmt_OK(_n == 5); _fmt_fn(to)(to, _fs, c, d, e, f, g); } while (0) -#define fmt_print8(to, fmt, c, d, e, f, g, h) \ +#define fmt_printd8(to, fmt, c, d, e, f, g, h) \ do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 6, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h)); \ fmt_OK(_n == 6); _fmt_fn(to)(to, _fs, c, d, e, f, g, h); } while (0) -#define fmt_print9(to, fmt, c, d, e, f, g, h, i) \ +#define fmt_printd9(to, fmt, c, d, e, f, g, h, i) \ do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 7, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), _fc(i)); \ fmt_OK(_n == 7); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i); } while (0) -#define fmt_print10(to, fmt, c, d, e, f, g, h, i, j) \ +#define fmt_printd10(to, fmt, c, d, e, f, g, h, i, j) \ do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 8, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), \ _fc(i), _fc(j)); \ fmt_OK(_n == 8); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i, j); } while (0) -#define fmt_print11(to, fmt, c, d, e, f, g, h, i, j, k) \ +#define fmt_printd11(to, fmt, c, d, e, f, g, h, i, j, k) \ do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 9, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), \ _fc(i), _fc(j), _fc(k)); \ fmt_OK(_n == 9); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i, j, k); } while (0) -#define fmt_print12(to, fmt, c, d, e, f, g, h, i, j, k, m) \ +#define fmt_printd12(to, fmt, c, d, e, f, g, h, i, j, k, m) \ do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 10, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), \ _fc(i), _fc(j), _fc(k), _fc(m)); \ fmt_OK(_n == 10); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i, j, k, m); } while (0) -#define fmt_print13(to, fmt, c, d, e, f, g, h, i, j, k, m, n) \ +#define fmt_printd13(to, fmt, c, d, e, f, g, h, i, j, k, m, n) \ do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 11, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), \ _fc(i), _fc(j), _fc(k), _fc(m), _fc(n)); \ fmt_OK(_n == 11); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i, j, k, m, n); } while (0) -#define fmt_print14(to, fmt, c, d, e, f, g, h, i, j, k, m, n, o) \ +#define fmt_printd14(to, fmt, c, d, e, f, g, h, i, j, k, m, n, o) \ do { char _fs[FMT_MAX]; int _n = _fmt_parse(_fs, 12, fmt, _fc(c), _fc(d), _fc(e), _fc(f), _fc(g), _fc(h), \ _fc(i), _fc(j), _fc(k), _fc(m), _fc(n), _fc(o)); \ fmt_OK(_n == 12); _fmt_fn(to)(to, _fs, c, d, e, f, g, h, i, j, k, m, n, o); } while (0) @@ -146,7 +152,6 @@ FMT_API void _fmt_bprint(fmt_buffer*, const char* fmt, ...); #define _fmt_fn(x) _Generic ((x), \ FILE*: fprintf, \ char*: sprintf, \ - int: _fmt_iprint, \ fmt_buffer*: _fmt_bprint) #if defined(_MSC_VER) && !defined(__clang__) @@ -184,17 +189,10 @@ FMT_API void _fmt_bprint(fmt_buffer*, const char* fmt, ...); #include #include -FMT_API void fmt_drop_buffer(fmt_buffer* buf) { +FMT_API void fmt_freebuffer(fmt_buffer* buf) { free(buf->data); } -FMT_API void _fmt_iprint(int fd, const char* fmt, ...) { - va_list args; - va_start(args, fmt); - vfprintf(fd == 1 ? stdout : stderr, fmt, args); - va_end(args); -} - FMT_API void _fmt_bprint(fmt_buffer* buf, const char* fmt, ...) { va_list args, args2; va_start(args, fmt); diff --git a/include/stc/algo/crange.h b/include/stc/algo/crange.h index 518320b5..63242a54 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_object(a, b, 8) + c_FORFILTER (i, crange, crange_literal(a, b, 8) , i.index > 10 , c_FLT_TAKE(i, 3)) printf(" %lld", *i.ref); @@ -46,7 +46,7 @@ int main() #include -#define crange_object(...) \ +#define crange_literal(...) \ (*(crange[]){crange_make(__VA_ARGS__)}) typedef long long crange_value; diff --git a/include/stc/algo/cspan.h b/include/stc/algo/cspan.h deleted file mode 100644 index 03cb8622..00000000 --- a/include/stc/algo/cspan.h +++ /dev/null @@ -1,132 +0,0 @@ -/* MIT License - * - * Copyright (c) 2023 Tyge Løvset - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -/* -#include -#include - -using_cspan(Span3f, float, 3); - -int demo1() { - float raw[3*4*5]; - Span3f span = cspan_make(raw, 3, 4, 5); - *cspan_at(&span, 2, 3, 4) = 100; - - printf("%f\n", *cspan_at(&span, 2, 3, 4)); -} - -using_cspan(Intspan, int, 1); - -int demo2() { - int array[] = {1, 2, 3, 4, 5}; - 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_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 - printf(" %d", *i.ref); - puts(""); -} -*/ -#ifndef STC_CSPAN_H_INCLUDED -#define STC_CSPAN_H_INCLUDED - -#include "../ccommon.h" - -#define using_cspan(Self, T, RANK) \ - typedef T Self##_value, Self##_raw; \ - typedef struct { Self##_value *data; uint32_t dim[RANK]; } Self; \ - typedef struct { Self##_value *ref, *end; } Self##_iter; \ - \ - STC_INLINE Self##_iter Self##_begin(const Self* self) { \ - Self##_iter it = {self->data, self->data + cspan_size(self)}; \ - return it; \ - } \ - STC_INLINE Self##_iter Self##_end(const Self* self) { \ - Self##_iter it = {NULL, self->data + cspan_size(self)}; \ - return it; \ - } \ - STC_INLINE void Self##_next(Self##_iter* it) \ - { if (++it->ref == it->end) it->ref = NULL; } \ - struct stc_nostruct - -#define cspan_assert(self, rank) c_STATIC_ASSERT(cspan_rank(self) == rank) - -#define cspan_object(S, ...) \ - ((S){.data = (S##_value[])__VA_ARGS__, \ - .dim = {sizeof((S##_value[])__VA_ARGS__)/sizeof(S##_value)}}) - -#define cspan_make(data, ...) {data, {__VA_ARGS__}} -#define cspan_from(data) \ - {data + c_STATIC_ASSERT(sizeof(data) != sizeof(void*)), {c_ARRAYLEN(data)}} - -#define cspan_size(self) _cspan_size((self)->dim, cspan_rank(self)) -#define cspan_rank(self) c_ARRAYLEN((self)->dim) - -#define cspan_reshape(self, ...) \ - memcpy((self)->dim, (uint32_t[]){__VA_ARGS__}, \ - sizeof((self)->dim) + cspan_assert(self, c_NUMARGS(__VA_ARGS__))) - -#define cspan_at(self, ...) \ - ((self)->data + c_PASTE(_cspan_i, c_NUMARGS(__VA_ARGS__))((self)->dim, __VA_ARGS__) \ - + cspan_assert(self, c_NUMARGS(__VA_ARGS__))) - -#define cspan_4to3(self, x) \ - {cspan_at(self, x, 0, 0, 0), {(self)->dim[1], (self)->dim[2], (self)->dim[3]}} -#define cspan_4to2(self, x, y) \ - {cspan_at(self, x, y, 0, 0), {(self)->dim[2], (self)->dim[3]}} -#define cspan_4to1(self, x, y, z) \ - {cspan_at(self, x, y, z, 0), {(self)->dim[3]}} -#define cspan_3to2(self, x) \ - {cspan_at(self, x, 0, 0), {(self)->dim[1], (self)->dim[2]}} -#define cspan_3to1(self, x, y) \ - {cspan_at(self, x, y, 0), {(self)->dim[2]}} -#define cspan_2to1(self, x) \ - {cspan_at(self, x, 0), {(self)->dim[1]}} - -STC_INLINE uint32_t _cspan_i1(const uint32_t dim[1], uint32_t x) - { assert(x < dim[0]); return x; } - -STC_INLINE uint32_t _cspan_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 _cspan_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 _cspan_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 _cspan_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/ccommon.h b/include/stc/ccommon.h index a2c529a7..edf4b2cb 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -38,6 +38,11 @@ #define c_ZU PRIu64 #define c_NPOS INT64_MAX #endif +#if defined STC_NDEBUG || defined NDEBUG + #define c_ASSERT(expr) (void)(expr) +#else + #define c_ASSERT(expr) assert(expr) +#endif #if defined(_MSC_VER) #pragma warning(disable: 4116 4996) // unnamed type definition in parentheses diff --git a/include/stc/cspan.h b/include/stc/cspan.h new file mode 100644 index 00000000..f5114a11 --- /dev/null +++ b/include/stc/cspan.h @@ -0,0 +1,154 @@ +/* MIT License + * + * Copyright (c) 2023 Tyge Løvset + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +/* +#include +#include +#include +using_cspan(Span2f, float, 2); +using_cspan(Intspan, int, 1); + +int demo1() { + float raw[4*5]; + Span2f ms = cspan_make(raw, 4, 5); + + for (size_t i=0; idata, self->data + cspan_size(self)}; \ + return it; \ + } \ + STC_INLINE Self##_iter Self##_end(const Self* self) { \ + Self##_iter it = {NULL, self->data + cspan_size(self)}; \ + return it; \ + } \ + STC_INLINE void Self##_next(Self##_iter* it) \ + { if (++it->ref == it->end) it->ref = NULL; } \ + struct stc_nostruct + +#define using_cspan2(Self, T) using_cspan(Self##1, T, 1); using_cspan(Self##2, T, 2) +#define using_cspan3(Self, T) using_cspan2(Self, T); using_cspan(Self##3, T, 3) +#define using_cspan4(Self, T) using_cspan3(Self, T); using_cspan(Self##4, T, 4) + +#define cspan_check_rank(self, rank) c_STATIC_ASSERT(cspan_rank(self) == rank) + +#define cspan_literal(S, ...) \ + ((S){.data = (S##_value[])__VA_ARGS__, \ + .dim = {sizeof((S##_value[])__VA_ARGS__)/sizeof(S##_value)}}) + +#define cspan_make(data, ...) \ + {data, {__VA_ARGS__}} + +/* create a cspan from a cvec, cstack, cdeq, cqueue, or cpque (heap) */ +#define cspan_from(container) \ + {(container)->data, {(container)->_len}} + +#define cspan_from_array(array) \ + {(array) + c_STATIC_ASSERT(sizeof(array) != sizeof(void*)), {c_ARRAYLEN(array)}} + +#define cspan_size(self) _cspan_size((self)->dim, cspan_rank(self)) +#define cspan_rank(self) c_ARRAYLEN((self)->dim) +#define cspan_index(self, ...) \ + c_PASTE(_cspan_i, c_NUMARGS(__VA_ARGS__))((self)->dim, __VA_ARGS__) + \ + cspan_check_rank(self, c_NUMARGS(__VA_ARGS__)) + +#define cspan_reshape(self, ...) \ + (void)memcpy((self)->dim, (uint32_t[]){__VA_ARGS__}, \ + sizeof((self)->dim) + cspan_check_rank(self, c_NUMARGS(__VA_ARGS__))) + +#define cspan_at(self, ...) ((self)->data + cspan_index(self, __VA_ARGS__)) + +#define cspan_slice4(self, x0, width) \ + {cspan_at(self, x0, 0, 0, 0), {width, (self)->dim[1], (self)->dim[2], (self)->dim[3]}} +#define cspan_slice3(self, x0, width) \ + {cspan_at(self, x0, 0, 0), {width, (self)->dim[1], (self)->dim[2]}} +#define cspan_slice2(self, x0, width) \ + {cspan_at(self, x0, 0), {width, (self)->dim[1]}} +#define cspan_slice1(self, x0, width) \ + {cspan_at(self, x0), {width}} + +#define cspan_4to3(self, x) \ + {cspan_at(self, x, 0, 0, 0), {(self)->dim[1], (self)->dim[2], (self)->dim[3]}} +#define cspan_4to2(self, x, y) \ + {cspan_at(self, x, y, 0, 0), {(self)->dim[2], (self)->dim[3]}} +#define cspan_4to1(self, x, y, z) \ + {cspan_at(self, x, y, z, 0), {(self)->dim[3]}} +#define cspan_3to2(self, x) \ + {cspan_at(self, x, 0, 0), {(self)->dim[1], (self)->dim[2]}} +#define cspan_3to1(self, x, y) \ + {cspan_at(self, x, y, 0), {(self)->dim[2]}} +#define cspan_2to1(self, x) \ + {cspan_at(self, x, 0), {(self)->dim[1]}} + +STC_INLINE size_t _cspan_i1(const uint32_t dim[1], uint32_t x) + { c_ASSERT(x < dim[0]); return x; } + +STC_INLINE size_t _cspan_i2(const uint32_t dim[2], uint32_t x, uint32_t y) + { c_ASSERT(x < dim[0] && y < dim[1]); return dim[1]*x + y; } + +STC_INLINE size_t _cspan_i3(const uint32_t dim[3], uint32_t x, uint32_t y, uint32_t z) { + c_ASSERT(x < dim[0] && y < dim[1] && z < dim[2]); + return dim[2]*(dim[1]*x + y) + z; +} +STC_INLINE size_t _cspan_i4(const uint32_t dim[4], uint32_t x, uint32_t y, uint32_t z, uint32_t w) { + c_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 _cspan_size(const uint32_t dim[], unsigned rank) { + size_t sz = dim[0]; + while (rank --> 1) sz *= dim[rank]; + return sz; +} + +#endif -- cgit v1.2.3