diff options
| -rw-r--r-- | README.md | 69 | ||||
| -rw-r--r-- | docs/cspan_api.md | 47 |
2 files changed, 61 insertions, 55 deletions
@@ -3,14 +3,14 @@ STC - Smart Template Containers for C ===================================== -News: Version 4.1 RC3 (Feb 2023) +News: Version 4.1 Released (Feb 2023) ------------------------------------------------ Major changes: - A new exciting [**cspan**](docs/cspan_api.md) single/multi-dimensional array view (with numpy-like slicing). - Signed sizes and indices for all containers. See C++ Core Guidelines by Stroustrup/Sutter: [ES.100](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es100-dont-mix-signed-and-unsigned-arithmetic), [ES.102](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es102-use-signed-types-for-arithmetic), [ES.106](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es106-dont-try-to-avoid-negative-values-by-using-unsigned), and [ES.107](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es107-dont-use-unsigned-for-subscripts-prefer-gslindex). - Customizable allocator [per templated container type](https://github.com/tylov/STC/discussions/44#discussioncomment-4891925). - Updates on cregex with several [new unicode character classes](docs/cregex_api.md#regex-cheatsheet). -- Uppercase flow-control macro names in ccommon.h [supported as alternative](include/stc/priv/altnames.h). +- Uppercase flow-control macro names in ccommon.h [supported as alternatives](include/stc/priv/altnames.h). - Some API changes in cregex and cstr. - [Previous changes for version 4](#version-4). @@ -46,7 +46,7 @@ Containers - [***cstack*** - **std::stack** alike type](docs/cstack_api.md) - [***cstr*** - **std::string** alike type](docs/cstr_api.md) - [***csview*** - **std::string_view** alike type](docs/csview_api.md) -- [***cspan*** - **std::mdspan** alike type](docs/cspan_api.md) +- [***cspan*** - **std::span/std::mdspan** alike type](docs/cspan_api.md) - [***cdeq*** - **std::deque** alike type](docs/cdeq_api.md) - [***cvec*** - **std::vector** alike type](docs/cvec_api.md) @@ -86,49 +86,53 @@ Benchmark notes: - **deque**: *insert*: n/3 push_front(), n/3 push_back()+pop_front(), n/3 push_back(). - **map and unordered map**: *insert*: n/2 random numbers, n/2 sequential numbers. *erase*: n/2 keys in the map, n/2 random keys. -Three standout features of STC ------------------------------- -1. ***Centralized analysis of template arguments***. Assigns good defaults to non-specified templates. -You may specify a number of "standard" template arguments for each container, but as minimum only one is -required (two for maps). In the latter case, STC assumes the elements are basic types. For more complex types, -additional template arguments should be defined. -2. ***General "heterogeneous lookup"-like feature***. Allows specification of an alternative type to use -for lookup in containers. E.g. for containers with string type (**cstr**) elements, `const char*` is used -as lookup type. It will then use the input `const char*` directly when comparing with the string data in the -container. This avoids the construction of a new `cstr` (which possible allocates memory) for the lookup. -Finally, destruction of the lookup key (i.e. string literal) after usage is not needed (or allowed), which -is convenient in C. A great ergonomic feature is that the alternative lookup type can also be used for adding -entries into containers through using the *emplace*-functions. E.g. `MyCStrVec_emplace_back(&vec, "Hello")`. -3. ***Standardized container iterators***. All container can be iterated the same way, and uses the -same element access syntax. E.g. `c_foreach (it, IntContainer, container) printf(" %d", *it.ref);` will work for -every type of container defined as `IntContainer` with `int` elements. Also the form `c_foreach (it, IntContainer, it1, it2)` -may be used to iterate from `it1` up to `it2`. - -Naming conventions ------------------- +STC conventions +--------------- - Container names are prefixed by `c`, e.g. `cvec`, `cstr`. - Public STC macros are prefixed by `c_`, e.g. `c_foreach`, `c_make`. - Template parameter macros are prefixed by `i_`, e.g. `i_val`, `i_type`. +- All containers can be initialized with `{0}`, i.e. no heap allocation used for empty init. - Common types for container type Con: - Con - - Con_value -- element type - - Con_raw -- same as Con_value by default + - Con_value + - Con_raw - Con_iter + - Con_ssize - Common function names for container type Con: - Con_init() - Con_reserve(&con, capacity) - Con_drop(&con) - Con_empty(&con) - Con_size(&con) - - Con_push(&con, value) - - Con_put_n(&con, values, n) - Con_clone(con) + - Con_push(&con, value) + - Con_emplace(&con, rawval) + - Con_put_n(&con, rawval[], n) - Con_erase_at(&con, iter) - Con_front(&con) - Con_back(&con) - Con_begin(&con) - Con_end(&con) - Con_next(&iter) + - Con_advance(iter, n) + +Standout features of STC +------------------------ +1. ***Centralized analysis of template arguments***. Assigns good defaults to non-specified templates. +You may specify a number of "standard" template arguments for each container, but as minimum only one is +required (two for maps). In the latter case, STC assumes the elements are basic types. For more complex types, +additional template arguments should be defined. +2. ***General "heterogeneous lookup"-like feature***. Allows specification of an alternative type to use +for lookup in containers. E.g. for containers with string type (**cstr**) elements, `const char*` is used +as lookup type. It will then use the input `const char*` directly when comparing with the string data in the +container. This avoids the construction of a new `cstr` (which possible allocates memory) for the lookup. +Finally, destruction of the lookup key (i.e. string literal) after usage is not needed (or allowed), which +is convenient in C. A great ergonomic feature is that the alternative lookup type can also be used for adding +entries into containers through using the *emplace*-functions. E.g. `MyCStrVec_emplace_back(&vec, "Hello")`. +3. ***Standardized container iterators***. All container can be iterated the same way, and uses the +same element access syntax. E.g. `c_foreach (it, IntContainer, container) printf(" %d", *it.ref);` will work for +every type of container defined as `IntContainer` with `int` elements. Also the form `c_foreach (it, IntContainer, it1, it2)` +may be used to iterate from `it1` up to `it2`. Usage ----- @@ -153,17 +157,16 @@ int main(void) FVec_drop(&vec); // cleanup memory } ``` -Below is an alternative way to write this code with STC. It uses the generic flow control macros c_auto and c_foreach, -and the function macro *c_make()*. This simplifies the code and makes it less prone to errors, while maintaining readability: +Below is an alternative way to write this with STC. It uses the generic flow control macros `c_auto` and `c_foreach`, and the function macro *c_make()*. This simplifies the code and makes it less prone to errors: ```c int main() { - c_auto (FVec, vec) // RAII: define vec, init() and drop() all-in-one syntax. + c_auto (FVec, vec) // RAII: define, init() and drop() combined. { - vec = c_make(FVec, {10.f, 20.f, 30.f}); // Initialize with a list of floats. + vec = c_make(FVec, {10.f, 20.f, 30.f}); // Initialize with a list of floats. - c_foreach (i, FVec, vec) // Iterate elements of the container. - printf(" %g", *i.ref); // i.ref is a pointer to the current element. + c_foreach (i, FVec, vec) // Iterate elements of the container. + printf(" %g", *i.ref); // i.ref is a pointer to the current element. } // vec is "dropped" at end of c_auto scope } diff --git a/docs/cspan_api.md b/docs/cspan_api.md index db706a51..1bd36446 100644 --- a/docs/cspan_api.md +++ b/docs/cspan_api.md @@ -1,16 +1,19 @@ # STC [cspan](../include/stc/cspan.h): Multi-dimensional Array View  -The **cspan** is templated non-owning multi-dimensional view of an array. It is similar to Python's -numpy array slicing and C++ [std::span](https://en.cppreference.com/w/cpp/container/span) / [std::mdspan](https://en.cppreference.com/w/cpp/container/mdspan). +The **cspan** is templated non-owning *single* and *multi-dimensional* view of an array. It is similar +to Python's numpy array slicing and C++ [std::span](https://en.cppreference.com/w/cpp/container/span) / +[std::mdspan](https://en.cppreference.com/w/cpp/container/mdspan). ## Header file and declaration - +**cspan** types are defined by the *using_cspan()* macro after the header is included. +This is different from other containers where template parameters are defined prior to +including each container. This works well mainly because cspan is non-owning. ```c #include <stc/cspan.h> using_cspan(SpanType, ValueType); // define a 1-d SpanType with ValueType elements. -using_cspan(SpanTypeN, ValueType, Rank); // define multi-dimensional span with Rank. - // Rank is number of dimensions (max 5) +using_cspan(SpanTypeN, ValueType, RANK); // define multi-dimensional span with RANK. + // RANK is the literal number of dimensions // Shorthands: using_cspan2(S, ValueType); // define span types S, S2 with ranks 1, 2. using_cspan3(S, ValueType); // define span types S, S2, S3 with ranks 1, 2, 3. @@ -20,25 +23,25 @@ using_cspan4(S, ValueType); // define span types S, S2, S3, S4 with All functions are type-safe. Note that the span argument itself is generally not side-effect safe, i.e., it may be expanded multiple times. However, all integer arguments are safe, e.g. -`cspan_at(&ms3, i++, j++, k++)` is fine. If the number of arguments does not match the span rank, -a compile error is issued. Runtime bounds checks are enabled by default (define STC_NDEBUG or NDEBUG to disable). +`cspan_at(&ms3, i++, j++, k++)` is allowed. If the number of arguments does not match the span rank, +a compile error is issued. Runtime bounds checks are enabled by default (define `STC_NDEBUG` or `NDEBUG` to disable). ```c -SpanTypeN cspan_md(ValueType* data, intptr_t xdim, ...); // create a multi-dimensional cspan -SpanType cspan_make(T SpanType, {v1, v2, ...}); // make a 1d-dimensional cspan from values -SpanType cspan_from(STCContainer* cnt); // create a 1d cspan from a compatible STC container -SpanType cspan_from_array(ValueType array[]); // create a 1d cspan from a C array +SpanType cspan_make(T SpanType, {v1, v2, ...}); // make a 1-d cspan from values +SpanType cspan_from(STCContainer* cnt); // make a 1-d cspan from compatible STC container +SpanType cspan_from_array(ValueType array[]); // make a 1-d cspan from C array +SpanTypeN cspan_md(ValueType* data, intptr_t xdim, ...); // make a multi-dimensional cspan intptr_t cspan_size(const SpanTypeN* self); // return number of elements -unsigned cspan_rank(const SpanTypeN* self); // return number of dimensions +intptr_t cspan_rank(const SpanTypeN* self); // dimensions; compile time constant intptr_t cspan_index(const SpanTypeN* self, intptr_t x, ..); // index of element -ValueType* cspan_at(const SpanTypeN* self, intptr_t x, ...); // at(): num of args specifies rank of input span. +ValueType* cspan_at(const SpanTypeN* self, intptr_t x, ...); // #args must match input span rank ValueType* cspan_front(const SpanTypeN* self); ValueType* cspan_back(const SpanTypeN* self); // general index slicing to create a subspan. - // {x} reduces rank. {x,c_END} slice to end. {c_ALL} take the full extent. -SpanTypeN cspan_slice(T SpanTypeN, const SpanTypeM* parent, {x0,x1}, {y0,y1}, ...); + // {i} reduces rank. {i,c_END} slice to end. {c_ALL} use the full extent. +SpanTypeR cspan_slice(T SpanTypeR, const SpanTypeN* self, {x0,x1}, {y0,y1}.., {N0,N1}); // create a subspan of lower rank. Like e.g. cspan_slice(Span2, &ms4, {x}, {y}, {c_ALL}, {c_ALL}); SpanType cspan_submd2(const SpanType2* self, intptr_t x); // return a 1d subspan from a 2d span. @@ -56,13 +59,13 @@ void SpanType_next(SpanTypeN_iter* it); ``` ## Types -| Type name | Type definition | Used to represent... | -|:------------------|:-----------------------------------------------|:---------------------| -| SpanTypeN | `struct { ValueType *data; uint32_t shape[N]; }` | SpanType with rank N | -| SpanTypeN`_value` | `ValueType` | The ValueType | -| `c_ALL` | `0,-1` | Full extent | -| `c_END` | `-1` | End of extent | - +| Type name | Type definition | Used to represent... | +|:------------------|:----------------------------------------------------|:---------------------| +| SpanTypeN | `struct { ValueType *data; uint32_t shape[N]; .. }` | SpanType with rank N | +| SpanTypeN`_value` | `ValueType` | The ValueType | +| `c_ALL` | | Full extent | +| `c_END` | | End of extent | + ## Example 1 The *cspan_slice()* function is similar to pythons numpy multi-dimensional arrays slicing, e.g.: |
