From 78a7e85535fd02e643bf98103223d4218e80133f Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 1 Mar 2023 14:36:38 +0100 Subject: Moved algorithm examples to algo folder. --- CMakeLists.txt | 4 +- include/stc/algo/coroutine.h | 5 +- misc/examples/algo/coread.c | 36 ++++++++++ misc/examples/algo/coroutines.c | 105 ++++++++++++++++++++++++++++ misc/examples/algo/forfilter.c | 147 ++++++++++++++++++++++++++++++++++++++++ misc/examples/algo/generator.c | 53 +++++++++++++++ misc/examples/algo/prime.c | 53 +++++++++++++++ misc/examples/algo/triples.c | 52 ++++++++++++++ misc/examples/coread.c | 36 ---------- misc/examples/coroutines.c | 105 ---------------------------- misc/examples/forfilter.c | 147 ---------------------------------------- misc/examples/prime.c | 53 --------------- misc/examples/triples.c | 52 -------------- 13 files changed, 449 insertions(+), 399 deletions(-) create mode 100644 misc/examples/algo/coread.c create mode 100644 misc/examples/algo/coroutines.c create mode 100644 misc/examples/algo/forfilter.c create mode 100644 misc/examples/algo/generator.c create mode 100644 misc/examples/algo/prime.c create mode 100644 misc/examples/algo/triples.c delete mode 100644 misc/examples/coread.c delete mode 100644 misc/examples/coroutines.c delete mode 100644 misc/examples/forfilter.c delete mode 100644 misc/examples/prime.c delete mode 100644 misc/examples/triples.c diff --git a/CMakeLists.txt b/CMakeLists.txt index a4659ff6..b86c1879 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,8 +13,8 @@ endif() include(CTest) if(BUILD_TESTING) - file(GLOB misc/examples misc/examples/*.c) - foreach(file IN LISTS misc/examples) + file(GLOB_RECURSE examples misc/examples/*.c) + foreach(file IN LISTS examples) get_filename_component(name "${file}" NAME_WE) add_executable(${name} ${file}) #target_compile_options(${name} PRIVATE "-pthread") diff --git a/include/stc/algo/coroutine.h b/include/stc/algo/coroutine.h index f3e42165..84be4a4e 100644 --- a/include/stc/algo/coroutine.h +++ b/include/stc/algo/coroutine.h @@ -24,7 +24,6 @@ #define STC_COROUTINE_INCLUDED /* #include -#include #include struct iterate { @@ -61,7 +60,6 @@ int main(void) { enum { cco_state_final = -1, cco_state_expired = -2, - cco_state_illegal = -3, }; #define cco_alive(ctx) ((ctx)->cco_state > 0) @@ -74,8 +72,7 @@ enum { #define cco_end(retval) \ *_state = cco_state_expired; break; \ - default: assert(!"illegal coroutine state"); \ - goto _cco_final_; /* avoid unused-warning */ \ + default: goto _cco_final_; /* avoid unused-warning */ \ } \ return retval diff --git a/misc/examples/algo/coread.c b/misc/examples/algo/coread.c new file mode 100644 index 00000000..c5f85e08 --- /dev/null +++ b/misc/examples/algo/coread.c @@ -0,0 +1,36 @@ +#include +#include +#include + +// Read file line by line using coroutines: + +struct file_nextline { + const char* filename; + int cco_state; + FILE* fp; + cstr line; +}; + +bool file_nextline(struct file_nextline* U) +{ + cco_begin(U) + U->fp = fopen(U->filename, "r"); + U->line = cstr_init(); + + while (cstr_getline(&U->line, U->fp)) + cco_yield(true); + + cco_final: // required label. + printf("finish\n"); + cstr_drop(&U->line); + fclose(U->fp); + cco_end(false); +} + +int main(void) { + struct file_nextline z = {__FILE__}; + int n = 0; + while (file_nextline(&z)) { + printf("%3d %s\n", ++n, cstr_str(&z.line)); + } +} diff --git a/misc/examples/algo/coroutines.c b/misc/examples/algo/coroutines.c new file mode 100644 index 00000000..2c9e6d5c --- /dev/null +++ b/misc/examples/algo/coroutines.c @@ -0,0 +1,105 @@ +#include +#include +#include + +// Demonstrate to call another coroutine from a coroutine: +// First create prime generator, then call fibonacci sequence: + +bool is_prime(int64_t i) { + for (int64_t j=2; j*j <= i; ++j) + if (i % j == 0) return false; + return true; +} + +struct prime { + int count, idx; + int64_t result, pos; + int cco_state; +}; + +bool prime(struct prime* U) { + cco_begin(U); + if (U->result < 2) U->result = 2; + if (U->result == 2) { + if (U->count-- == 0) cco_return; + ++U->idx; + cco_yield(true); + } + U->result += !(U->result & 1); + for (U->pos = U->result; U->count > 0; U->pos += 2) { + if (is_prime(U->pos)) { + --U->count; + ++U->idx; + U->result = U->pos; + cco_yield(true); + } + } + cco_final: + printf("final prm\n"); + cco_end(false); +} + + +// Use coroutine to create a fibonacci sequence generator: + +struct fibonacci { + int count, idx; + int64_t result, b; + int cco_state; +}; + +bool fibonacci(struct fibonacci* F) { + assert(F->count < 94); + + cco_begin(F); + F->idx = 0; + F->result = 0; + F->b = 1; + for (;;) { + if (F->count-- == 0) + cco_return; + if (++F->idx > 1) { + int64_t sum = F->result + F->b; // NB! locals only lasts until next cco_yield! + F->result = F->b; + F->b = sum; + } + cco_yield(true); + } + cco_final: + printf("final fib\n"); + cco_end(false); +} + +// Combine + +struct combined { + struct prime prm; + struct fibonacci fib; + int cco_state; +}; + +bool combined(struct combined* C) { + cco_begin(C); + cco_yield(prime(&C->prm), &C->prm, true); + cco_yield(fibonacci(&C->fib), &C->fib, true); + + // Reuse the C->prm context and extend the count: + C->prm.count = 8; C->prm.result += 2; + cco_yield(prime(&C->prm), &C->prm, true); + + cco_final: puts("final comb"); + cco_end(false); +} + +int main(void) { + struct combined comb = {.prm={.count=8}, .fib={14}}; + if (true) + while (combined(&comb)) + printf("Prime(%d)=%lld, Fib(%d)=%lld\n", + comb.prm.idx, (long long)comb.prm.result, + comb.fib.idx, (long long)comb.fib.result); + else + while (prime(&comb.prm)) + printf("Prime(%d)=%lld\n", + comb.prm.idx, (long long)comb.prm.result); +} diff --git a/misc/examples/algo/forfilter.c b/misc/examples/algo/forfilter.c new file mode 100644 index 00000000..5e1cf15e --- /dev/null +++ b/misc/examples/algo/forfilter.c @@ -0,0 +1,147 @@ +#include +#define i_extern +#include +#include +#include +#include + +#define i_type IVec +#define i_val int +#include + +#define i_type SVec +#define i_valclass csview +#include + +// filters and transforms: +#define flt_skipValue(i, x) (*i.ref != (x)) +#define flt_isEven(i) ((*i.ref & 1) == 0) +#define flt_isOdd(i) (*i.ref & 1) +#define flt_square(i) (*i.ref * *i.ref) + +void demo1(void) +{ + c_auto (IVec, vec) { + c_forlist (i, int, {0, 1, 2, 3, 4, 5, 80, 6, 7, 80, 8, 9, 80, + 10, 11, 12, 13, 14, 15, 80, 16, 17}) + IVec_push(&vec, *i.ref); + + puts("demo1:"); + c_forfilter (i, IVec, vec, flt_skipValue(i, 80)) + printf(" %d", *i.ref); + puts(""); + + int res, sum = 0; + c_forfilter (i, IVec, vec + , 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 + ){ + sum += res = flt_square(i); + printf(" %d", res); + } + printf("\n sum: %d\n", sum); + } +} + + +/* Rust: +fn main() { + let vector = (1..) // Infinite range of integers + .skip_while(|x| *x != 11) // Skip initial numbers unequal 11 + .filter(|x| x % 2 != 0) // Collect odd numbers + .take(5) // Only take five numbers + .map(|x| x * x) // Square each number + .collect::>(); // Return as a new Vec + println!("{:?}", vector); // Print result +} +*/ + +void demo2(void) +{ + c_auto (IVec, vector) { + puts("demo2:"); + crange R = crange_make(INT64_MAX); + c_forfilter (x, crange, R + , c_flt_skipwhile(x, *x.ref != 11) + && *x.ref % 2 != 0 + , c_flt_take(x, 5)) + IVec_push(&vector, (int)(*x.ref * *x.ref)); + c_foreach (x, IVec, vector) + printf(" %d", *x.ref); + puts(""); + } +} + +/* Rust: +fn main() { + let sentence = "This is a sentence in Rust."; + let words: Vec<&str> = sentence + .split_whitespace() + .collect(); + let words_containing_i: Vec<&str> = words + .into_iter() + .filter(|word| word.contains("i")) + .collect(); + println!("{:?}", words_containing_i); +} +*/ +void demo3(void) +{ + c_auto (SVec, words, words_containing_i) { + const char* sentence = "This is a sentence in C99."; + c_fortoken (w, sentence, " ") + SVec_push(&words, *w.ref); + + c_forfilter (w, SVec, words, + csview_contains(*w.ref, "i")) + SVec_push(&words_containing_i, *w.ref); + + puts("demo3:"); + c_foreach (w, SVec, words_containing_i) + printf(" %.*s", c_SV(*w.ref)); + puts(""); + } +} + +void demo4(void) +{ + csview s = c_sv("ab123cReAghNGnΩoEp"); // Ω = multi-byte + c_auto (cstr, out) { + c_forfilter (i, csview, s, utf8_isupper(utf8_peek(i.ref))) { + char chr[4]; + utf8_encode(chr, utf8_tolower(utf8_peek(i.ref))); + cstr_push(&out, chr); + } + puts("demo4:"); + printf(" %s\n", cstr_str(&out)); + } +} + +void demo5(void) +{ + #define flt_even(i) ((*i.ref & 1) == 0) + #define flt_mid_decade(i) ((*i.ref % 10) != 0) + puts("demo5:"); + crange R = crange_make(1963, INT32_MAX); + c_forfilter (i, crange, R + , 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)) + printf(" %lld", *i.ref); + puts(""); +} + +int main(void) +{ + demo1(); + demo2(); + demo3(); + demo4(); + demo5(); +} diff --git a/misc/examples/algo/generator.c b/misc/examples/algo/generator.c new file mode 100644 index 00000000..fce44a52 --- /dev/null +++ b/misc/examples/algo/generator.c @@ -0,0 +1,53 @@ +// https://quuxplusone.github.io/blog/2019/03/06/pythagorean-triples/ + +#include +#include + +typedef struct { + int n; + int a, b, c; +} Triple_value, Triple; + +typedef struct { + Triple_value* ref; + int cco_state; +} Triple_iter; + +bool Triple_next(Triple_iter* it) { + Triple_value* t = it->ref; + cco_begin(it); + for (t->c = 1;; ++t->c) { + for (t->a = 1; t->a < t->c; ++t->a) { + for (t->b = t->a; t->b < t->c; ++t->b) { + if (t->a*t->a + t->b*t->b == t->c*t->c) { + cco_yield(true); + if (t->n-- == 1) cco_return; + } + } + } + } + cco_final: + it->ref = NULL; + cco_end(false); +} + +Triple_iter Triple_begin(Triple* t) { + Triple_iter it = {t}; + if (t->n > 0) Triple_next(&it); + else it.ref = NULL; + return it; +} + + +int main() +{ + puts("Pythagorean triples with c < 100:"); + Triple t = {INT32_MAX}; + c_foreach (i, Triple, t) + { + if (i.ref->c < 100) + printf("%u: (%d, %d, %d)\n", INT32_MAX - i.ref->n + 1, i.ref->a, i.ref->b, i.ref->c); + else + (void)cco_stop(&i); + } +} diff --git a/misc/examples/algo/prime.c b/misc/examples/algo/prime.c new file mode 100644 index 00000000..e705dcb7 --- /dev/null +++ b/misc/examples/algo/prime.c @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include +#include + + +cbits sieveOfEratosthenes(int64_t n) +{ + cbits bits = cbits_with_size(n/2 + 1, true); + int64_t q = (int64_t)sqrt((double) n) + 1; + for (int64_t i = 3; i < q; i += 2) { + int64_t j = i; + for (; j < n; j += 2) { + if (cbits_test(&bits, j>>1)) { + i = j; + break; + } + } + for (int64_t j = i*i; j < n; j += i*2) + cbits_reset(&bits, j>>1); + } + return bits; +} + +int main(void) +{ + int64_t n = 1000000000; + printf("Computing prime numbers up to %" c_ZI "\n", n); + + clock_t t1 = clock(); + c_with (cbits primes = sieveOfEratosthenes(n + 1), cbits_drop(&primes)) { + int64_t np = cbits_count(&primes); + clock_t t2 = clock(); + + printf("Number of primes: %" c_ZI ", time: %f\n\n", np, (float)(t2 - t1) / (float)CLOCKS_PER_SEC); + puts("Show all the primes in the range [2, 1000):"); + printf("2"); + c_forrange (i, 3, 1000, 2) + if (cbits_test(&primes, i>>1)) printf(" %lld", i); + puts("\n"); + + puts("Show the last 50 primes using a temporary crange generator:"); + crange R = crange_make(n - 1, 0, -2); + c_forfilter (i, crange, R + , cbits_test(&primes, *i.ref>>1) + , c_flt_take(i, 50)) { + printf("%lld ", *i.ref); + if (c_flt_last(i) % 10 == 0) puts(""); + } + } +} diff --git a/misc/examples/algo/triples.c b/misc/examples/algo/triples.c new file mode 100644 index 00000000..8a46d653 --- /dev/null +++ b/misc/examples/algo/triples.c @@ -0,0 +1,52 @@ +// https://quuxplusone.github.io/blog/2019/03/06/pythagorean-triples/ + +#include +#include + +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); + if (++i > n) goto done; + } + } + } + } + done:; +} + +struct triples { + int n; + int x, y, z; + 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; + cco_yield(true); + } + } + } + } + cco_final: + cco_end(false); +} + + +int main() +{ + puts("Vanilla triples:"); + 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); +} diff --git a/misc/examples/coread.c b/misc/examples/coread.c deleted file mode 100644 index c5f85e08..00000000 --- a/misc/examples/coread.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include - -// Read file line by line using coroutines: - -struct file_nextline { - const char* filename; - int cco_state; - FILE* fp; - cstr line; -}; - -bool file_nextline(struct file_nextline* U) -{ - cco_begin(U) - U->fp = fopen(U->filename, "r"); - U->line = cstr_init(); - - while (cstr_getline(&U->line, U->fp)) - cco_yield(true); - - cco_final: // required label. - printf("finish\n"); - cstr_drop(&U->line); - fclose(U->fp); - cco_end(false); -} - -int main(void) { - struct file_nextline z = {__FILE__}; - int n = 0; - while (file_nextline(&z)) { - printf("%3d %s\n", ++n, cstr_str(&z.line)); - } -} diff --git a/misc/examples/coroutines.c b/misc/examples/coroutines.c deleted file mode 100644 index 2c9e6d5c..00000000 --- a/misc/examples/coroutines.c +++ /dev/null @@ -1,105 +0,0 @@ -#include -#include -#include - -// Demonstrate to call another coroutine from a coroutine: -// First create prime generator, then call fibonacci sequence: - -bool is_prime(int64_t i) { - for (int64_t j=2; j*j <= i; ++j) - if (i % j == 0) return false; - return true; -} - -struct prime { - int count, idx; - int64_t result, pos; - int cco_state; -}; - -bool prime(struct prime* U) { - cco_begin(U); - if (U->result < 2) U->result = 2; - if (U->result == 2) { - if (U->count-- == 0) cco_return; - ++U->idx; - cco_yield(true); - } - U->result += !(U->result & 1); - for (U->pos = U->result; U->count > 0; U->pos += 2) { - if (is_prime(U->pos)) { - --U->count; - ++U->idx; - U->result = U->pos; - cco_yield(true); - } - } - cco_final: - printf("final prm\n"); - cco_end(false); -} - - -// Use coroutine to create a fibonacci sequence generator: - -struct fibonacci { - int count, idx; - int64_t result, b; - int cco_state; -}; - -bool fibonacci(struct fibonacci* F) { - assert(F->count < 94); - - cco_begin(F); - F->idx = 0; - F->result = 0; - F->b = 1; - for (;;) { - if (F->count-- == 0) - cco_return; - if (++F->idx > 1) { - int64_t sum = F->result + F->b; // NB! locals only lasts until next cco_yield! - F->result = F->b; - F->b = sum; - } - cco_yield(true); - } - cco_final: - printf("final fib\n"); - cco_end(false); -} - -// Combine - -struct combined { - struct prime prm; - struct fibonacci fib; - int cco_state; -}; - -bool combined(struct combined* C) { - cco_begin(C); - cco_yield(prime(&C->prm), &C->prm, true); - cco_yield(fibonacci(&C->fib), &C->fib, true); - - // Reuse the C->prm context and extend the count: - C->prm.count = 8; C->prm.result += 2; - cco_yield(prime(&C->prm), &C->prm, true); - - cco_final: puts("final comb"); - cco_end(false); -} - -int main(void) { - struct combined comb = {.prm={.count=8}, .fib={14}}; - if (true) - while (combined(&comb)) - printf("Prime(%d)=%lld, Fib(%d)=%lld\n", - comb.prm.idx, (long long)comb.prm.result, - comb.fib.idx, (long long)comb.fib.result); - else - while (prime(&comb.prm)) - printf("Prime(%d)=%lld\n", - comb.prm.idx, (long long)comb.prm.result); -} diff --git a/misc/examples/forfilter.c b/misc/examples/forfilter.c deleted file mode 100644 index 5e1cf15e..00000000 --- a/misc/examples/forfilter.c +++ /dev/null @@ -1,147 +0,0 @@ -#include -#define i_extern -#include -#include -#include -#include - -#define i_type IVec -#define i_val int -#include - -#define i_type SVec -#define i_valclass csview -#include - -// filters and transforms: -#define flt_skipValue(i, x) (*i.ref != (x)) -#define flt_isEven(i) ((*i.ref & 1) == 0) -#define flt_isOdd(i) (*i.ref & 1) -#define flt_square(i) (*i.ref * *i.ref) - -void demo1(void) -{ - c_auto (IVec, vec) { - c_forlist (i, int, {0, 1, 2, 3, 4, 5, 80, 6, 7, 80, 8, 9, 80, - 10, 11, 12, 13, 14, 15, 80, 16, 17}) - IVec_push(&vec, *i.ref); - - puts("demo1:"); - c_forfilter (i, IVec, vec, flt_skipValue(i, 80)) - printf(" %d", *i.ref); - puts(""); - - int res, sum = 0; - c_forfilter (i, IVec, vec - , 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 - ){ - sum += res = flt_square(i); - printf(" %d", res); - } - printf("\n sum: %d\n", sum); - } -} - - -/* Rust: -fn main() { - let vector = (1..) // Infinite range of integers - .skip_while(|x| *x != 11) // Skip initial numbers unequal 11 - .filter(|x| x % 2 != 0) // Collect odd numbers - .take(5) // Only take five numbers - .map(|x| x * x) // Square each number - .collect::>(); // Return as a new Vec - println!("{:?}", vector); // Print result -} -*/ - -void demo2(void) -{ - c_auto (IVec, vector) { - puts("demo2:"); - crange R = crange_make(INT64_MAX); - c_forfilter (x, crange, R - , c_flt_skipwhile(x, *x.ref != 11) - && *x.ref % 2 != 0 - , c_flt_take(x, 5)) - IVec_push(&vector, (int)(*x.ref * *x.ref)); - c_foreach (x, IVec, vector) - printf(" %d", *x.ref); - puts(""); - } -} - -/* Rust: -fn main() { - let sentence = "This is a sentence in Rust."; - let words: Vec<&str> = sentence - .split_whitespace() - .collect(); - let words_containing_i: Vec<&str> = words - .into_iter() - .filter(|word| word.contains("i")) - .collect(); - println!("{:?}", words_containing_i); -} -*/ -void demo3(void) -{ - c_auto (SVec, words, words_containing_i) { - const char* sentence = "This is a sentence in C99."; - c_fortoken (w, sentence, " ") - SVec_push(&words, *w.ref); - - c_forfilter (w, SVec, words, - csview_contains(*w.ref, "i")) - SVec_push(&words_containing_i, *w.ref); - - puts("demo3:"); - c_foreach (w, SVec, words_containing_i) - printf(" %.*s", c_SV(*w.ref)); - puts(""); - } -} - -void demo4(void) -{ - csview s = c_sv("ab123cReAghNGnΩoEp"); // Ω = multi-byte - c_auto (cstr, out) { - c_forfilter (i, csview, s, utf8_isupper(utf8_peek(i.ref))) { - char chr[4]; - utf8_encode(chr, utf8_tolower(utf8_peek(i.ref))); - cstr_push(&out, chr); - } - puts("demo4:"); - printf(" %s\n", cstr_str(&out)); - } -} - -void demo5(void) -{ - #define flt_even(i) ((*i.ref & 1) == 0) - #define flt_mid_decade(i) ((*i.ref % 10) != 0) - puts("demo5:"); - crange R = crange_make(1963, INT32_MAX); - c_forfilter (i, crange, R - , 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)) - printf(" %lld", *i.ref); - puts(""); -} - -int main(void) -{ - demo1(); - demo2(); - demo3(); - demo4(); - demo5(); -} diff --git a/misc/examples/prime.c b/misc/examples/prime.c deleted file mode 100644 index e705dcb7..00000000 --- a/misc/examples/prime.c +++ /dev/null @@ -1,53 +0,0 @@ -#include -#include -#include -#include -#include -#include - - -cbits sieveOfEratosthenes(int64_t n) -{ - cbits bits = cbits_with_size(n/2 + 1, true); - int64_t q = (int64_t)sqrt((double) n) + 1; - for (int64_t i = 3; i < q; i += 2) { - int64_t j = i; - for (; j < n; j += 2) { - if (cbits_test(&bits, j>>1)) { - i = j; - break; - } - } - for (int64_t j = i*i; j < n; j += i*2) - cbits_reset(&bits, j>>1); - } - return bits; -} - -int main(void) -{ - int64_t n = 1000000000; - printf("Computing prime numbers up to %" c_ZI "\n", n); - - clock_t t1 = clock(); - c_with (cbits primes = sieveOfEratosthenes(n + 1), cbits_drop(&primes)) { - int64_t np = cbits_count(&primes); - clock_t t2 = clock(); - - printf("Number of primes: %" c_ZI ", time: %f\n\n", np, (float)(t2 - t1) / (float)CLOCKS_PER_SEC); - puts("Show all the primes in the range [2, 1000):"); - printf("2"); - c_forrange (i, 3, 1000, 2) - if (cbits_test(&primes, i>>1)) printf(" %lld", i); - puts("\n"); - - puts("Show the last 50 primes using a temporary crange generator:"); - crange R = crange_make(n - 1, 0, -2); - c_forfilter (i, crange, R - , cbits_test(&primes, *i.ref>>1) - , 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 deleted file mode 100644 index 0ce0eb37..00000000 --- a/misc/examples/triples.c +++ /dev/null @@ -1,52 +0,0 @@ -// https://quuxplusone.github.io/blog/2019/03/06/pythagorean-triples/ - -#include -#include - -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); - if (++i > n) goto done; - } - } - } - } - done:; -} - -struct tricoro { - int n; - int cco_state; - int x, y, z; -}; - -bool triples_coro(struct tricoro* 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; - cco_yield(true); - } - } - } - } - cco_final: - cco_end(false); -} - - -int main() -{ - puts("Vanilla triples:"); - triples_vanilla(6); - - puts("\nCoroutine triples:"); - struct tricoro t = {6}; - while (triples_coro(&t)) - printf("{%d, %d, %d},\n", t.x, t.y, t.z); -} \ No newline at end of file -- cgit v1.2.3