summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--docs/cspan_api.md110
-rw-r--r--docs/cstr_api.md5
-rw-r--r--include/stc/cspan.h24
-rw-r--r--include/stc/cstr.h6
-rw-r--r--include/stc/priv/altnames.h12
-rw-r--r--misc/examples/demos.c2
-rw-r--r--misc/examples/multidim.c6
-rw-r--r--misc/tests/cspan_test.c39
8 files changed, 141 insertions, 63 deletions
diff --git a/docs/cspan_api.md b/docs/cspan_api.md
index 32ef49c4..c4cb7c16 100644
--- a/docs/cspan_api.md
+++ b/docs/cspan_api.md
@@ -1,9 +1,8 @@
# STC [cspan](../include/stc/cspan.h): Multi-dimensional Array View
![Array](pics/array.jpg)
-The **cspan** is templated non-owning multi-dimensional view of an array.
-
-See the c++ classes [std::span](https://en.cppreference.com/w/cpp/container/span) and
+The **cspan** is templated non-owning multi-dimensional view of an array. See the c++ classes
+[std::span](https://en.cppreference.com/w/cpp/container/span) and
[std::mdspan](https://en.cppreference.com/w/cpp/container/mdspan) for similar functionality.
## Header file and declaration
@@ -18,17 +17,14 @@ using_cspan3(S, ValueType); // define span types S, S2, S3 with rank
using_cspan4(S, ValueType); // define span types S, S2, S3, S4 with ranks 1, 2, 3, 4.
```
## Methods
-Note that `cspan_multidim()`, `cmake_from*()`, `cspan_atN()`, `and cspan_subspanN()` require a (safe) cast to its span-type
+Note that `cspan_md()`, `cmake_from*()`, `cspan_atN()`, `and cspan_subspanN()` require a (safe) cast to its span-type
on assignment, but not on initialization of a span variable. All functions are type-safe, and arguments are side-effect safe, except for SpanType arg. which must not have side-effects.
```c
+SpanTypeN cspan_md(ValueType* data, size_t xdim, ...); // create a multi-dimensional cspan
SpanType cspan_make(T SpanType, {v1, v2, ...}); // make a 1d-dimensional cspan from values
-SpanTypeN cspan_multidim(ValueType* data, size_t xdim, ...); // create a multi-dimensional cspan
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_flatten(SpanTypeN* span); // create a 1d cspan from a multidim span
-void cspan_resize(SpanTypeN* self, size_t xdim, ...); // change the extent of each dimension
-
size_t cspan_size(const SpanTypeN* self); // return number of elements
unsigned cspan_rank(const SpanTypeN* self); // return number of dimensions
size_t cspan_index(const SpanTypeN* self, size_t x, ...); // index of element
@@ -37,13 +33,15 @@ ValueType* cspan_at(SpanTypeN* self, size_t x, ...); // at():
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 1d or 2d subspan from a 3d span.
-SpanTypeN cspan_at4(SpanType4* self, size_t x, ...); // number of args determines rank of output span.
+ // return a subspan of lower rank:
+SpanType cspan_submd2(SpanType2* self, size_t x); // return a 1d subspan from a 2d span.
+SpanTypeN cspan_submd3(SpanType3* self, size_t x, ...); // return a 1d or 2d subspan from a 3d span.
+SpanTypeN cspan_submd4(SpanType4* self, size_t x, ...); // number of args determines rank of output span.
+ // return a sliced span of same rank:
void cspan_slice(SpanTypeN* self, {x0,x1}, {y0,y1},...); // slice multidim span into a md subspan.
- // return a subspan of same rank:
+ // return a subspan of same rank. Like e.g. cspan_slice(&ms3, {offset, offset+count}, {0}, {0});
SpanType cspan_subspan(const SpanType* self, size_t offset, size_t count);
SpanType2 cspan_subspan2(const SpanType2 self, size_t offset, size_t count);
SpanType3 cspan_subspan3(const SpanType3 self, size_t offset, size_t count);
@@ -61,9 +59,73 @@ void SpanType_next(SpanTypeN_iter* it);
| SpanTypeN`_value` | `ValueType` | The ValueType |
| SpanTypeN`_iter` | `struct { ValueType *ref; ... }` | Iterator type |
-## Example
+## Example 1
+
+The *cspan_slice()* function is similar to pythons numpy multi-dimensional arrays slicing, e.g.:
+```py
+import numpy as np
+ms3 = np.array((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24), int)
+
+ms3 = np.reshape(ms3, (2, 3, 4))
+ss3 = ms3[:, 1:3, 2:]
+ss2 = ss3[1]
+
+for i in range(ss2.shape[0]):
+ for j in range(ss2.shape[1]):
+ print(" {}".format(ss2[i, j]), end='')
+print('')
+
+for i in ss2.flat:
+ print(" {}".format(i), end='')
+# 19 20 23 24
+# 19 20 23 24
+```
+... can be done in C with STC:
+```c
+#include <c11/fmt.h>
+#include <stc/cspan.h>
+using_cspan3(myspan, int); // define myspan, myspan2, myspan3.
+
+int main() {
+ int arr[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24};
+
+ myspan3 ms3 = cspan_md(arr, 2, 3, 4), ss3 = ms3;
+ cspan_slice(&ss3, {0}, {1,3}, {2,});
+ myspan2 ss2 = cspan_submd3(&ss3, 1);
+
+ c_FORRANGE (i, ss2.dim[0])
+ c_FORRANGE (j, ss2.dim[1])
+ fmt_print(" {}", *cspan_at(&ss2, i, j));
+ puts("");
+
+ c_FOREACH (i, myspan2, ss2)
+ fmt_print(" {}", *i.ref);
+}
+```
+... or (mostly) in C++23:
+```c++
+#include <print>
+#include <mdspan>
+#include <tuple>
+
+int main() {
+ int arr[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24};
+
+ std::mdspan ms3(arr, 2, 3, 4);
+ auto ss3 = std::submdspan(ms3, std::full_extent, std::tuple{1,3}, std::tuple{2,4});
+ auto ss2 = std::submdspan(ss3, 1, std::full_extent, std::full_extent);
+
+ for (std::size_t i = 0; i < ss2.extent(0); ++i)
+ for (std::size_t j = 0; j < ss2.extent(1); ++j)
+ std::print(" {}", ss2[i, j]);
+ std::println();
+
+ // mdspan can't printed as a flat array, afaik.
+}
+```
+## Example 2
```c
-#include <stdio.h>
+#include <c11/fmt.h>
#include <stc/cspan.h>
#define i_val float
#include <stc/cstack.h>
@@ -79,33 +141,33 @@ int main()
cstack_float_push(&vec, i);
// define "span3[xd][yd][zd]"
- Span3 span3 = cspan_multidim(vec.data, xd, yd, zd);
+ Span3 span3 = cspan_md(vec.data, xd, yd, zd);
*cspan_at(&span3, 4, 3, 2) = 3.14159f;
- printf("index: %d", (int)cspan_index(&span3, 4, 3, 2));
+ fmt_print("index: {}", cspan_index(&span3, 4, 3, 2));
- Span span1 = cspan_at3(&span3, 4, 3);
+ Span span1 = cspan_submd3(&span3, 4, 3);
printf("\niterate span1: ");
c_FOREACH (i, Span, span1)
- printf("%g ", *i.ref);
+ fmt_print("{} ", *i.ref);
- Span2 span2 = cspan_at3(&span3, 4);
+ Span2 span2 = cspan_submd3(&span3, 4);
printf("\niterate span2: ");
c_FOREACH (i, Span2, span2)
- printf("%g ", *i.ref);
+ fmt_print("{} ", *i.ref);
puts("\niterate span3 by dimensions:");
c_FORRANGE (i, span3.dim[0]) {
c_FORRANGE (j, span3.dim[1]) {
c_FORRANGE (k, span3.dim[2])
- printf(" %2g", *cspan_at(&span3, i, j, k));
+ fmt_printf(" {:2}", *cspan_at(&span3, i, j, k));
printf(" |");
}
puts("");
}
- printf("%g\n", *cspan_at(&span3, 4, 3, 2));
- printf("%g\n", *cspan_at(&span2, 3, 2));
- printf("%g\n", *cspan_at(&span1, 2));
+ fmt_println("{}", *cspan_at(&span3, 4, 3, 2));
+ fmt_println("{}", *cspan_at(&span2, 3, 2));
+ fmt_println("{}", *cspan_at(&span1, 2));
}
}
```
diff --git a/docs/cstr_api.md b/docs/cstr_api.md
index 4f895549..48999654 100644
--- a/docs/cstr_api.md
+++ b/docs/cstr_api.md
@@ -68,8 +68,7 @@ void cstr_insert_s(cstr* self, size_t pos, cstr ins);
void cstr_erase(cstr* self, size_t pos, size_t len); // erase len bytes from pos
-void cstr_replace(cstr* self, const char* search, const char* repl);
-void cstr_replace_ex(cstr* self, const char* search, const char* repl, unsigned count);
+void cstr_replace(cstr* self, const char* search, const char* repl, unsigned count = MAX_INT);
cstr cstr_replace_sv(csview in, csview search, csview repl, unsigned count);
void cstr_replace_at(cstr* self, size_t pos, size_t len, const char* repl); // replace at a position
void cstr_replace_at_sv(cstr* self, size_t pos, size_t len, const csview repl);
@@ -174,7 +173,7 @@ int main() {
cstr_erase(&s1, 7, 5); // -nine
printf("%s\n", cstr_str(&s1));
- cstr_replace_ex(&s1, "seven", "four", 1);
+ cstr_replace(&s1, "seven", "four", 1);
printf("%s\n", cstr_str(&s1));
// reassign:
diff --git a/include/stc/cspan.h b/include/stc/cspan.h
index 19dd74d4..7886c9f6 100644
--- a/include/stc/cspan.h
+++ b/include/stc/cspan.h
@@ -30,7 +30,7 @@ using_cspan(Intspan, int, 1);
int demo1() {
float raw[4*5];
- Span2f ms = cspan_multidim(raw, 4, 5);
+ Span2f ms = cspan_md(raw, 4, 5);
for (size_t i=0; i<ms.dim[0]; i++)
for (size_t j=0; j<ms.dim[1]; j++)
@@ -94,7 +94,7 @@ typedef struct { uint32_t d[2]; } cspan_idx2;
typedef struct { uint32_t d[3]; } cspan_idx3;
typedef struct { uint32_t d[4]; } cspan_idx4;
-#define cspan_multidim(array, ...) \
+#define cspan_md(array, ...) \
{.data=array, .dim={__VA_ARGS__}, .stride={.d={__VA_ARGS__}}}
/* For static initialization, use cspan_make(). c_make() for non-static only. */
@@ -117,7 +117,7 @@ typedef struct { uint32_t d[4]; } cspan_idx4;
#define cspan_front(self) ((self)->data)
#define cspan_back(self) ((self)->data + cspan_size(self) - 1)
-// cspan_subspan:
+// cspan_subspanN:
#define cspan_subspan(self, offset, count) \
{.data=cspan_at(self, offset), .dim={count}}
@@ -130,24 +130,24 @@ typedef struct { uint32_t d[4]; } cspan_idx4;
{.data=cspan_at(self, offset, 0, 0, 0), .dim={count, (self)->dim[1], (self)->dim[2], (self)->dim[3]}, \
.stride={(self)->stride}}
-// cspan_atN:
+// cspan_submdN:
-#define cspan_at4(...) c_MACRO_OVERLOAD(cspan_at4, __VA_ARGS__)
-#define cspan_at3(...) c_MACRO_OVERLOAD(cspan_at3, __VA_ARGS__)
-#define cspan_at2(self, x) \
+#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) \
{.data=cspan_at(self, x, 0), .dim={(self)->dim[1]}}
-#define cspan_at3_2(self, x) \
+#define cspan_submd3_2(self, x) \
{.data=cspan_at(self, x, 0, 0), .dim={(self)->dim[1], (self)->dim[2]}, \
.stride={.d={0, (self)->stride.d[2]}}}
-#define cspan_at3_3(self, x, y) \
+#define cspan_submd3_3(self, x, y) \
{.data=cspan_at(self, x, y, 0), .dim={(self)->dim[2]}}
-#define cspan_at4_2(self, x) \
+#define cspan_submd4_2(self, x) \
{.data=cspan_at(self, x, 0, 0, 0), .dim={(self)->dim[1], (self)->dim[2], (self)->dim[3]}, \
.stride={.d={0, (self)->stride.d[2], (self)->stride.d[3]}}}
-#define cspan_at4_3(self, x, y) \
+#define cspan_submd4_3(self, x, y) \
{.data=cspan_at(self, x, y, 0, 0), .dim={(self)->dim[2], (self)->dim[3]}, \
.stride={.d={0, (self)->stride.d[3]}}}
-#define cspan_at4_4(self, x, y, z) \
+#define cspan_submd4_4(self, x, y, z) \
{.data=cspan_at(self, x, y, z, 0), .dim={(self)->dim[3]}}
// cspan_slice:
diff --git a/include/stc/cstr.h b/include/stc/cstr.h
index 04091968..071e40e8 100644
--- a/include/stc/cstr.h
+++ b/include/stc/cstr.h
@@ -373,12 +373,12 @@ STC_INLINE char* cstr_append_s(cstr* self, cstr s) {
return cstr_append_n(self, sv.str, sv.size);
}
-STC_INLINE void cstr_replace_ex(cstr* self, const char* search, const char* repl, unsigned count) {
+#define cstr_replace(...) c_MACRO_OVERLOAD(cstr_replace, __VA_ARGS__)
+#define cstr_replace_3(self, search, repl) cstr_replace_4(self, search, repl, ~0U)
+STC_INLINE void cstr_replace_4(cstr* self, const char* search, const char* repl, unsigned count) {
cstr_take(self, cstr_replace_sv(cstr_sv(self), c_SV(search, strlen(search)),
c_SV(repl, strlen(repl)), count));
}
-STC_INLINE void cstr_replace(cstr* self, const char* search, const char* repl)
- { cstr_replace_ex(self, search, repl, ~0U); }
STC_INLINE void cstr_replace_at_sv(cstr* self, size_t pos, size_t len, const csview repl) {
char* d = _cstr_internal_move(self, pos + len, pos + repl.size);
diff --git a/include/stc/priv/altnames.h b/include/stc/priv/altnames.h
index 7f58384c..695d3ebc 100644
--- a/include/stc/priv/altnames.h
+++ b/include/stc/priv/altnames.h
@@ -42,15 +42,3 @@
#define c_scope c_SCOPE
#define c_defer c_DEFER
#define c_sv c_SV
-
-#define c_DROP c_drop
-#define c_DELETE c_delete
-#define c_SWAP c_swap
-#define c_FIND_IF c_find_if
-#define c_ERASE_IF c_erase_if
-#define c_FLT_TAKE c_flt_take
-#define c_FLT_SKIP c_flt_skip
-#define c_FLT_SKIPWHILE c_flt_skipwhile
-#define c_FLT_TAKEWHILE c_flt_takewhile
-#define c_CONTAINER_OF c_container_of
-#define c_STATIC_ASSERT c_static_assert
diff --git a/misc/examples/demos.c b/misc/examples/demos.c
index 4455b840..c92f95b2 100644
--- a/misc/examples/demos.c
+++ b/misc/examples/demos.c
@@ -13,7 +13,7 @@ void stringdemo1()
cstr_erase(&cs, 7, 5); // -nine
printf("%s.\n", cstr_str(&cs));
- cstr_replace_ex(&cs, "seven", "four", 1);
+ cstr_replace(&cs, "seven", "four", 1);
printf("%s.\n", cstr_str(&cs));
cstr_take(&cs, cstr_from_fmt("%s *** %s", cstr_str(&cs), cstr_str(&cs)));
diff --git a/misc/examples/multidim.c b/misc/examples/multidim.c
index e25d727e..b7ee46fb 100644
--- a/misc/examples/multidim.c
+++ b/misc/examples/multidim.c
@@ -16,7 +16,7 @@ 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, 3, 4);
+ ispan3 ms3 = cspan_md(v.data, 2, 3, 4);
puts("ms3:");
for (unsigned i=0; i != ms3.dim[0]; i++) {
@@ -47,7 +47,7 @@ int main()
printf(" %d", *i.ref);
puts("");
- ispan2 ms2 = cspan_at3(&ms3, 0);
+ ispan2 ms2 = cspan_submd3(&ms3, 0);
// write data using 2D view
for (unsigned i=0; i != ms2.dim[0]; i++)
@@ -60,7 +60,7 @@ int main()
puts("");
puts("iterate subspan ms3[1]:");
- ispan2 sub = cspan_at3(&ms3, 1);
+ ispan2 sub = cspan_submd3(&ms3, 1);
c_FOREACH (i, ispan2, sub)
printf(" %d", *i.ref);
puts("");
diff --git a/misc/tests/cspan_test.c b/misc/tests/cspan_test.c
index 6b85af00..32634795 100644
--- a/misc/tests/cspan_test.c
+++ b/misc/tests/cspan_test.c
@@ -7,12 +7,12 @@ using_cspan3(intspan, int);
CTEST(cspan, subdim) {
int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
- intspan3 m = cspan_multidim(array, 2, 2, 3);
+ intspan3 m = cspan_md(array, 2, 2, 3);
for (size_t i = 0; i < m.dim[0]; ++i) {
- intspan2 sub_i = cspan_at3(&m, i);
+ intspan2 sub_i = cspan_submd3(&m, i);
for (size_t j = 0; j < m.dim[1]; ++j) {
- intspan sub_i_j = cspan_at2(&sub_i, j);
+ intspan sub_i_j = cspan_submd2(&sub_i, j);
for (size_t k = 0; k < m.dim[2]; ++k) {
ASSERT_EQ(*cspan_at(&sub_i_j, k), *cspan_at(&m, i, j, k));
}
@@ -22,7 +22,7 @@ CTEST(cspan, subdim) {
CTEST(cspan, slice) {
int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
- intspan2 m1 = cspan_multidim(array, 3, 4);
+ intspan2 m1 = cspan_md(array, 3, 4);
size_t sum1 = 0;
for (size_t i = 0; i < m1.dim[0]; ++i) {
@@ -32,7 +32,7 @@ CTEST(cspan, slice) {
}
intspan2 m2 = m1;
- cspan_slice(&m2, c_SLICE(0), c_SLICE(2,4));
+ cspan_slice(&m2, {0}, {2,4});
size_t sum2 = 0;
for (size_t i = 0; i < m2.dim[0]; ++i) {
@@ -43,3 +43,32 @@ CTEST(cspan, slice) {
ASSERT_EQ(78, sum1);
ASSERT_EQ(45, sum2);
}
+
+#define i_val int
+#include <stc/cstack.h>
+
+CTEST(cspan, slice2) {
+ c_AUTO (cstack_int, stack)
+ {
+ c_FORRANGE (i, 10*20*30)
+ cstack_int_push(&stack, i);
+
+ intspan3 ms3 = cspan_md(stack.data, 10, 20, 30);
+ cspan_slice(&ms3, {1,4}, {3,7}, {20,24});
+
+ size_t sum = 0;
+ for (size_t i = 0; i < ms3.dim[0]; ++i) {
+ for (size_t j = 0; j < ms3.dim[1]; ++j) {
+ for (size_t k = 0; k < ms3.dim[2]; ++k) {
+ sum += *cspan_at(&ms3, i, j, k);
+ }
+ }
+ }
+ ASSERT_EQ(65112, sum);
+
+ sum = 0;
+ c_FOREACH (i, intspan3, ms3)
+ sum += *i.ref;
+ ASSERT_EQ(65112, sum);
+ }
+}