summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2023-03-07 22:26:36 +0100
committerTyge Løvset <[email protected]>2023-03-07 22:26:36 +0100
commitecc0b2108cffeb725e3b8e2574b6fb7927dfd96e (patch)
tree221a40b1e41f64353e2b3143277a250ef2ae2ce5
parenta203314647b5c37c7e40230551457f006ff36cd5 (diff)
downloadSTC-modified-ecc0b2108cffeb725e3b8e2574b6fb7927dfd96e.tar.gz
STC-modified-ecc0b2108cffeb725e3b8e2574b6fb7927dfd96e.zip
Improved/simplified c_forfilter (): last optional parameter gone. Now c_flt_take() and c_flt_takewhile() breaks the loop always.
c11/fmt.h : renamed fmt_freebuffer(buf) => fmt_destroy(buf).
-rw-r--r--docs/ccommon_api.md19
-rw-r--r--include/c11/fmt.h18
-rw-r--r--include/stc/algo/crange.h2
-rw-r--r--include/stc/algo/filter.h50
-rw-r--r--include/stc/cspan.h2
-rw-r--r--misc/benchmarks/shootout_hashmaps.cpp12
-rw-r--r--misc/examples/forfilter.c12
-rw-r--r--misc/examples/forloops.c2
-rwxr-xr-xmisc/examples/make.sh2
-rw-r--r--misc/examples/prime.c2
-rw-r--r--misc/examples/triples.c34
11 files changed, 84 insertions, 71 deletions
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index 034e52f5..8dcb2ff3 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -176,7 +176,6 @@ Iterate containers with stop-criteria and chained range filtering.
| Usage | Description |
|:----------------------------------------------------|:---------------------------------------|
| `c_forfilter (it, ctype, container, filter)` | Filter out items in chain with && |
-| `c_forfilter (it, ctype, container, filter, pred)` | Filter and iterate until pred is false |
| `c_forwhile (it, ctype, start, pred)` | Iterate until pred is false |
| Built-in filter | Description |
@@ -187,16 +186,14 @@ Iterate containers with stop-criteria and chained range filtering.
| `c_flt_takewhile(it, predicate)` | Take items until predicate is false |
| `c_flt_count(it)` | Increment current and return value |
| `c_flt_last(it)` | Get value of last count/skip/take |
-
-`it.index` holds the index of the source item.
```c
// Example:
#include <stc/algo/crange.h>
#include <stc/algo/filter.h>
#include <stdio.h>
-bool isPrime(int i) {
- for (int j=2; j*j <= i; ++j)
+bool isPrime(long long i) {
+ for (long long j=2; j*j <= i; ++j)
if (i % j == 0) return false;
return true;
}
@@ -209,14 +206,13 @@ int main() {
isPrime(*i.ref)
&& c_flt_skip(i, 24)
&& c_flt_count(i) % 15 == 1
- , c_flt_take(i, 10)) // , = breaks loop on false.
- printf(" %d", *i.ref);
+ && c_flt_take(i, 10))
+ printf(" %lld", *i.ref);
puts("");
}
// out: 1171 1283 1409 1493 1607 1721 1847 1973 2081 2203
```
-Note that `c_flt_take()` is given as an optional argument, which breaks the loop on false.
-With `&&` instead of the comma it will give same result, but the full input is processed first.
+Note that `c_flt_take()` and `c_flt_takewhile()`breaks the loop on false.
## Generators
@@ -235,8 +231,7 @@ void crange_next(crange_iter* it);
// 1. All primes less than 32:
crange r1 = crange_make(3, 32, 2);
printf("2"); // first prime
-c_forfilter (i, crange, r1
- , isPrime(*i.ref))
+c_forfilter (i, crange, r1, isPrime(*i.ref))
printf(" %lld", *i.ref);
// 2 3 5 7 11 13 17 19 23 29 31
@@ -244,7 +239,7 @@ c_forfilter (i, crange, r1
printf("2");
c_forfilter (i, crange, crange_obj(3, INT64_MAX, 2)
, isPrime(*i.ref)
- , c_flt_take(10))
+ && c_flt_take(10))
printf(" %lld", *i.ref);
// 2 3 5 7 11 13 17 19 23 29 31
```
diff --git a/include/c11/fmt.h b/include/c11/fmt.h
index 435193f8..a6f7985c 100644
--- a/include/c11/fmt.h
+++ b/include/c11/fmt.h
@@ -6,14 +6,14 @@ VER 2.0: NEW API:
void fmt_print(fmt, ...);
void fmt_println(fmt, ...);
void fmt_printd(dest, fmt, ...);
-void fmt_freebuffer(fmt_buffer* buf);
+void fmt_destroy(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_freebuffer(buf) after usage.
+ Call fmt_destroy(buf) after usage.
fmt - format string
{} Auto-detected format. If :MOD is not specified,
@@ -55,7 +55,7 @@ int main() {
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);
+ fmt_destroy(out);
}
*/
#include <stdio.h>
@@ -91,7 +91,7 @@ typedef struct {
_Bool stream;
} fmt_buffer;
-FMT_API void fmt_freebuffer(fmt_buffer* buf);
+FMT_API void fmt_destroy(fmt_buffer* buf);
FMT_API int _fmt_parse(char* p, int nargs, const char *fmt, ...);
FMT_API void _fmt_bprint(fmt_buffer*, const char* fmt, ...);
@@ -99,11 +99,17 @@ FMT_API void _fmt_bprint(fmt_buffer*, const char* fmt, ...);
#define FMT_MAX 256
#endif
+#ifdef FMT_SHORTS
+#define print(...) fmt_printd(stdout, __VA_ARGS__)
+#define println(...) fmt_printd((fmt_buffer*)0, __VA_ARGS__)
+#define printd fmt_printd
+#endif
+
#define fmt_print(...) fmt_printd(stdout, __VA_ARGS__)
#define fmt_println(...) fmt_printd((fmt_buffer*)0, __VA_ARGS__)
+#define fmt_printd(...) fmt_OVERLOAD(fmt_printd, __VA_ARGS__)
/* Primary function. */
-#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)
@@ -189,7 +195,7 @@ FMT_API void _fmt_bprint(fmt_buffer*, const char* fmt, ...);
#include <stdarg.h>
#include <string.h>
-FMT_API void fmt_freebuffer(fmt_buffer* buf) {
+FMT_API void fmt_destroy(fmt_buffer* buf) {
free(buf->data);
}
diff --git a/include/stc/algo/crange.h b/include/stc/algo/crange.h
index 1b840516..4fc957b6 100644
--- a/include/stc/algo/crange.h
+++ b/include/stc/algo/crange.h
@@ -36,7 +36,7 @@ int main()
int a = 100, b = INT32_MAX;
c_forfilter (i, crange, crange_obj(a, b, 8)
, i.index > 10
- , c_flt_take(i, 3))
+ && c_flt_take(i, 3))
printf(" %lld", *i.ref);
puts("");
}
diff --git a/include/stc/algo/filter.h b/include/stc/algo/filter.h
index 6f8e1654..48a36d9b 100644
--- a/include/stc/algo/filter.h
+++ b/include/stc/algo/filter.h
@@ -36,9 +36,9 @@ int main()
puts("");
c_forfilter (i, cstack_int, stk
- , c_flt_skipwhile(i, *i.ref < 3)
- && (*i.ref & 1) == 0 // even only
- , c_flt_take(i, 2)) // break after 2
+ , c_flt_skipwhile(i, *i.ref < 3)
+ && (*i.ref & 1) == 0 // even only
+ && c_flt_take(i, 2)) // break after 2
printf(" %d", *i.ref);
puts("");
}
@@ -53,27 +53,37 @@ int main()
#define c_NFILTERS 32
#endif
-#define c_flt_take(i, n) (c_flt_count(i) <= (n))
+#define c_flt_take(i, n) _flt_take(&(i).b, n)
#define c_flt_skip(i, n) (c_flt_count(i) > (n))
-#define c_flt_skipwhile(i, pred) ((i).s2[(i).s2top++] |= !(pred))
-#define c_flt_takewhile(i, pred) !c_flt_skipwhile(i, pred)
-#define c_flt_last(i) (i).s1[(i).s1top-1]
-#define c_flt_count(i) ++(i).s1[(i).s1top++]
+#define c_flt_skipwhile(i, pred) ((i).b.s2[(i).b.s2top++] |= !(pred))
+#define c_flt_takewhile(i, pred) _flt_takewhile(&(i).b, pred)
+#define c_flt_last(i) (i).b.s1[(i).b.s1top-1]
+#define c_flt_count(i) ++(i).b.s1[(i).b.s1top++]
-#define c_forfilter(...) c_MACRO_OVERLOAD(c_forfilter, __VA_ARGS__)
+#define c_forfilter(i, C, cnt, filter) \
+ for (struct {struct _flt_base b; C##_iter it; C##_value *ref;} \
+ i = {.it=C##_begin(&cnt), .ref=i.it.ref} ; !i.b.done & (i.ref != NULL) ; \
+ C##_next(&i.it), i.ref = i.it.ref, i.b.s1top=0, i.b.s2top=0) \
+ if (!(filter)) ; else
-#define c_forfilter_4(i, C, cnt, filter) \
- c_forfilter_B(i, C, C##_begin(&cnt), filter)
+// -----
-#define c_forfilter_5(i, C, cnt, filter, cond) \
- c_forfilter_B(i, C, C##_begin(&cnt), filter) if (!(cond)) break; else
+struct _flt_base {
+ uint32_t s1[c_NFILTERS];
+ bool s2[c_NFILTERS], done;
+ uint8_t s1top, s2top;
+};
-#define c_forfilter_B(i, C, start, filter) \
- for (struct {C##_iter it; C##_value *ref; \
- uint32_t s1[c_NFILTERS], index; \
- bool s2[c_NFILTERS]; uint8_t s1top, s2top;} \
- i = {.it=start, .ref=i.it.ref}; i.it.ref \
- ; C##_next(&i.it), i.ref = i.it.ref, ++i.index, i.s1top=0, i.s2top=0) \
- if (!(filter)) ; else
+static inline bool _flt_take(struct _flt_base* b, uint32_t n) {
+ uint32_t k = ++b->s1[b->s1top++];
+ b->done |= (k >= n);
+ return k <= n;
+}
+
+static inline bool _flt_takewhile(struct _flt_base* b, bool pred) {
+ bool skip = (b->s2[b->s2top++] |= !pred);
+ b->done |= skip;
+ return !skip;
+}
#endif
diff --git a/include/stc/cspan.h b/include/stc/cspan.h
index c6df51af..00313540 100644
--- a/include/stc/cspan.h
+++ b/include/stc/cspan.h
@@ -50,7 +50,7 @@ int demo2() {
c_forfilter (i, Intspan, span,
, c_flt_skipwhile(i, *i.ref < 25)
&& (*i.ref & 1) == 0 // even only
- , c_flt_take(i, 2)) // break after 2
+ && c_flt_take(i, 2)) // break after 2
printf(" %d", *i.ref);
puts("");
}
diff --git a/misc/benchmarks/shootout_hashmaps.cpp b/misc/benchmarks/shootout_hashmaps.cpp
index da523d71..39ad1786 100644
--- a/misc/benchmarks/shootout_hashmaps.cpp
+++ b/misc/benchmarks/shootout_hashmaps.cpp
@@ -2,7 +2,7 @@
#include <time.h>
#include <stc/crandom.h>
-#define MAX_LOAD_FACTOR 77
+#define MAX_LOAD_FACTOR 85
#ifdef __cplusplus
#include <limits>
@@ -314,7 +314,7 @@ int main(int argc, char* argv[])
unsigned n = n_mill * 1000000;
unsigned N1 = n, N2 = n, N3 = n, N4 = n, N5 = n;
stc64_t rng;
- size_t seed = time(NULL);
+ size_t seed = 123456; // time(NULL);
printf("\nUnordered hash map shootout\n");
printf("KMAP = https://github.com/attractivechaos/klib\n"
@@ -334,14 +334,14 @@ int main(int argc, char* argv[])
printf("\nT1: Insert %g mill. random keys range [0, 2^%u): map[rnd] = i;\n", N1/1000000.0, keybits);
RUN_TEST(1)
- printf("\nT2: Insert %g mill. SEQUENTIAL keys, erase them in same order:\n", N2/1000000.0);
- RUN_TEST(2)
+ //printf("\nT2: Insert %g mill. SEQUENTIAL keys, erase them in same order:\n", N2/1000000.0);
+ //RUN_TEST(2)
printf("\nT3: Erase all elements by lookup (%u mill. random inserts), key range [0, 2^%u)\n", n_mill*2, keybits);
RUN_TEST(3)
- printf("\nT4: Iterate map with Min(%u mill, 2^%u) inserts repeated times:\n", n_mill, keybits+1);
- RUN_TEST(4)
+ //printf("\nT4: Iterate map with Min(%u mill, 2^%u) inserts repeated times:\n", n_mill, keybits+1);
+ //RUN_TEST(4)
printf("\nT5: Lookup mix of random/existing keys in range [0, 2^%u). Num lookups depends on size.\n", keybits);
RUN_TEST(5)
diff --git a/misc/examples/forfilter.c b/misc/examples/forfilter.c
index 5e1cf15e..2be975a6 100644
--- a/misc/examples/forfilter.c
+++ b/misc/examples/forfilter.c
@@ -36,9 +36,9 @@ void demo1(void)
, c_flt_skipwhile(i, *i.ref != 80)
&& c_flt_skip(i, 1)
&& c_flt_skipwhile(i, *i.ref != 80)
- && flt_isEven(i)
- && flt_skipValue(i, 80)
- , c_flt_take(i, 5) // short-circuit
+ && flt_isEven(i)
+ && flt_skipValue(i, 80)
+ && c_flt_take(i, 5) // short-circuit
){
sum += res = flt_square(i);
printf(" %d", res);
@@ -68,7 +68,7 @@ void demo2(void)
c_forfilter (x, crange, R
, c_flt_skipwhile(x, *x.ref != 11)
&& *x.ref % 2 != 0
- , c_flt_take(x, 5))
+ && c_flt_take(x, 5))
IVec_push(&vector, (int)(*x.ref * *x.ref));
c_foreach (x, IVec, vector)
printf(" %d", *x.ref);
@@ -131,8 +131,8 @@ void demo5(void)
, c_flt_skip(i,15)
&& c_flt_skipwhile(i, flt_mid_decade(i))
&& c_flt_skip(i,30)
- && flt_even(i)
- , c_flt_take(i,10))
+ && flt_even(i)
+ && c_flt_take(i,5))
printf(" %lld", *i.ref);
puts("");
}
diff --git a/misc/examples/forloops.c b/misc/examples/forloops.c
index 66c587c4..707e8285 100644
--- a/misc/examples/forloops.c
+++ b/misc/examples/forloops.c
@@ -73,7 +73,7 @@ int main()
&& c_flt_skipwhile(i, isOdd(i))
&& isOdd(i)
&& c_flt_skip(i, 2)
- , c_flt_take(i, 1))
+ && c_flt_take(i, 2))
printf(" %d", *i.ref);
puts("");
// 189
diff --git a/misc/examples/make.sh b/misc/examples/make.sh
index 5ac0b653..0297e5a1 100755
--- a/misc/examples/make.sh
+++ b/misc/examples/make.sh
@@ -6,7 +6,7 @@ if [ "$(uname)" = 'Linux' ]; then
oflag='-o '
fi
-cc=gcc; cflags="-s -O2 -std=c99 -Wconversion -Wpedantic -Wall -Wsign-compare -Wwrite-strings"
+cc=gcc; cflags="-s -O3 -std=c99 -Wconversion -Wpedantic -Wall -Wsign-compare -Wwrite-strings"
#cc=gcc; cflags="-g -std=c99 -Werror -Wfatal-errors -Wpedantic -Wall $sanitize"
#cc=tcc; cflags="-Wall -std=c99"
#cc=clang; cflags="-s -O2 -std=c99 -Werror -Wfatal-errors -Wpedantic -Wall -Wno-unused-function -Wsign-compare -Wwrite-strings"
diff --git a/misc/examples/prime.c b/misc/examples/prime.c
index e705dcb7..59ee336c 100644
--- a/misc/examples/prime.c
+++ b/misc/examples/prime.c
@@ -45,7 +45,7 @@ int main(void)
crange R = crange_make(n - 1, 0, -2);
c_forfilter (i, crange, R
, cbits_test(&primes, *i.ref>>1)
- , c_flt_take(i, 50)) {
+ && c_flt_take(i, 50)) {
printf("%lld ", *i.ref);
if (c_flt_last(i) % 10 == 0) puts("");
}
diff --git a/misc/examples/triples.c b/misc/examples/triples.c
index 8a46d653..4783d603 100644
--- a/misc/examples/triples.c
+++ b/misc/examples/triples.c
@@ -4,11 +4,11 @@
#include <stdio.h>
void triples_vanilla(int n) {
- for (int i = 1, z = 1;; ++z) {
- for (int x = 1; x < z; ++x) {
- for (int y = x; y < z; ++y) {
- if (x*x + y*y == z*z) {
- printf("{%d, %d, %d},\n", x, y, z);
+ for (int i = 1, c = 1;; ++c) {
+ for (int a = 1; a < c; ++a) {
+ for (int b = a; b < c; ++b) {
+ if (a*a + b*b == c*c) {
+ printf("{%d, %d, %d},\n", a, b, c);
if (++i > n) goto done;
}
}
@@ -19,17 +19,17 @@ void triples_vanilla(int n) {
struct triples {
int n;
- int x, y, z;
+ int a, b, c;
int cco_state;
};
-bool triples_coro(struct triples* t) {
- cco_begin(t);
- for (t->z = 1;; ++t->z) {
- for (t->x = 1; t->x < t->z; ++t->x) {
- for (t->y = t->x; t->y < t->z; ++t->y) {
- if (t->x*t->x + t->y*t->y == t->z*t->z) {
- if (t->n-- == 0) cco_return;
+bool triples_next(struct triples* I) {
+ cco_begin(I);
+ for (I->c = 1;; ++I->c) {
+ for (I->a = 1; I->a < I->c; ++I->a) {
+ for (I->b = I->a; I->b < I->c; ++I->b) {
+ if (I->a*I->a + I->b*I->b == I->c*I->c) {
+ if (I->n-- == 0) cco_return;
cco_yield(true);
}
}
@@ -46,7 +46,9 @@ int main()
triples_vanilla(6);
puts("\nCoroutine triples:");
- struct triples t = {6};
- while (triples_coro(&t))
- printf("{%d, %d, %d},\n", t.x, t.y, t.z);
+ struct triples t = {INT32_MAX};
+ while (triples_next(&t)) {
+ if (t.c < 100) printf("{%d, %d, %d},\n", t.a, t.b, t.c);
+ else cco_stop(&t);
+ }
}