diff options
| author | Tyge Løvset <[email protected]> | 2023-03-07 22:26:36 +0100 |
|---|---|---|
| committer | Tyge Løvset <[email protected]> | 2023-03-07 22:26:36 +0100 |
| commit | ecc0b2108cffeb725e3b8e2574b6fb7927dfd96e (patch) | |
| tree | 221a40b1e41f64353e2b3143277a250ef2ae2ce5 | |
| parent | a203314647b5c37c7e40230551457f006ff36cd5 (diff) | |
| download | STC-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.md | 19 | ||||
| -rw-r--r-- | include/c11/fmt.h | 18 | ||||
| -rw-r--r-- | include/stc/algo/crange.h | 2 | ||||
| -rw-r--r-- | include/stc/algo/filter.h | 50 | ||||
| -rw-r--r-- | include/stc/cspan.h | 2 | ||||
| -rw-r--r-- | misc/benchmarks/shootout_hashmaps.cpp | 12 | ||||
| -rw-r--r-- | misc/examples/forfilter.c | 12 | ||||
| -rw-r--r-- | misc/examples/forloops.c | 2 | ||||
| -rwxr-xr-x | misc/examples/make.sh | 2 | ||||
| -rw-r--r-- | misc/examples/prime.c | 2 | ||||
| -rw-r--r-- | misc/examples/triples.c | 34 |
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); + } } |
