From eb85069b669e754836b9d4587ba03d3af1a5e975 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sun, 26 Mar 2023 00:27:45 +0100 Subject: development branch for 4.2 Removed uses of c_auto and c_with in documentation examples and code examples. Still using c_defer a few places. Renamed c11/fmt.h to c11/print.h. Some additions in ccommon.h, e.g. c_const_cast(T, x). Improved docs. --- misc/examples/shape.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'misc/examples/shape.c') diff --git a/misc/examples/shape.c b/misc/examples/shape.c index d290fb4d..2aabdcc2 100644 --- a/misc/examples/shape.c +++ b/misc/examples/shape.c @@ -138,7 +138,8 @@ void testShape(const Shape* shape) int main(void) { - c_auto (Shapes, shapes) + Shapes shapes = {0}; + c_defer (Shapes_drop(&shapes)) { Triangle* tri1 = c_new(Triangle, Triangle_from((Point){5, 7}, (Point){12, 7}, (Point){12, 20})); Polygon* pol1 = c_new(Polygon, Polygon_init()); -- cgit v1.2.3 From e35036deef4fc8f17cc9221e2e666dfdb832ba78 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Mon, 27 Mar 2023 19:57:09 +0200 Subject: More RAII cleanup in examples. Also removed gauss1.c and new_deq.c --- misc/benchmarks/various/prng_bench.cpp | 2 +- misc/examples/arc_demo.c | 2 +- misc/examples/astar.c | 2 +- misc/examples/books.c | 2 +- misc/examples/coread.c | 13 +++--- misc/examples/forfilter.c | 39 ++++++++--------- misc/examples/forloops.c | 23 ++++------ misc/examples/functor.c | 6 ++- misc/examples/gauss1.c | 58 ------------------------- misc/examples/gauss2.c | 12 +++--- misc/examples/inits.c | 2 +- misc/examples/mapmap.c | 15 +------ misc/examples/multimap.c | 2 +- misc/examples/new_deq.c | 46 -------------------- misc/examples/prime.c | 5 ++- misc/examples/printspan.c | 52 +++++++++++------------ misc/examples/rawptr_elements.c | 78 +++++++++++++++++----------------- misc/examples/regex2.c | 2 +- misc/examples/replace.c | 35 +++++++-------- misc/examples/shape.c | 38 ++++++++--------- misc/examples/sidebyside.cpp | 11 +++-- misc/examples/splitstr.c | 1 + 22 files changed, 164 insertions(+), 282 deletions(-) delete mode 100644 misc/examples/gauss1.c delete mode 100644 misc/examples/new_deq.c (limited to 'misc/examples/shape.c') diff --git a/misc/benchmarks/various/prng_bench.cpp b/misc/benchmarks/various/prng_bench.cpp index 6f4e0e47..be07f799 100644 --- a/misc/benchmarks/various/prng_bench.cpp +++ b/misc/benchmarks/various/prng_bench.cpp @@ -122,7 +122,7 @@ using namespace std; int main(void) { - enum {N = 2000000000}; + enum {N = 500000000}; uint16_t* recipient = new uint16_t[N]; static stc64_t rng; init_state(rng.state, 12345123); diff --git a/misc/examples/arc_demo.c b/misc/examples/arc_demo.c index 88555177..2339adbb 100644 --- a/misc/examples/arc_demo.c +++ b/misc/examples/arc_demo.c @@ -25,7 +25,7 @@ int main() const int years[] = {2021, 2012, 2022, 2015}; cvec_Arc vec = {0}; - c_forrange (i, c_ARRAYLEN(years)) + c_forrange (i, c_arraylen(years)) cvec_Arc_push(&vec, Arc_from(years[i])); printf("vec:"); diff --git a/misc/examples/astar.c b/misc/examples/astar.c index 6c850b08..7dd12d50 100644 --- a/misc/examples/astar.c +++ b/misc/examples/astar.c @@ -103,7 +103,7 @@ astar(cstr* maze, int width) { -1, 0, 0, width }, /* ~ ~ ~ ~ ~ ~ ~ */ { 1, 0, 0, width }, { -1, -1, 0, width }, { 0, -1, 0, width }, { 1, -1, 0, width }, }; - for (size_t i = 0; i < c_ARRAYLEN(deltas); i++) + for (size_t i = 0; i < c_arraylen(deltas); i++) { point delta = deltas[i]; point next = point_init(current.x + delta.x, current.y + delta.y, width); diff --git a/misc/examples/books.c b/misc/examples/books.c index 40fe877f..a62769b0 100644 --- a/misc/examples/books.c +++ b/misc/examples/books.c @@ -41,7 +41,7 @@ int main() // Look up the values associated with some keys. const char* to_find[] = {"Pride and Prejudice", "Alice's Adventure in Wonderland"}; - c_forrange (i, c_ARRAYLEN(to_find)) { + c_forrange (i, c_arraylen(to_find)) { const cmap_str_value* b = cmap_str_get(&book_reviews, to_find[i]); if (b) printf("%s: %s\n", cstr_str(&b->first), cstr_str(&b->second)); diff --git a/misc/examples/coread.c b/misc/examples/coread.c index c5f85e08..0a7f4816 100644 --- a/misc/examples/coread.c +++ b/misc/examples/coread.c @@ -20,17 +20,20 @@ bool file_nextline(struct file_nextline* U) while (cstr_getline(&U->line, U->fp)) cco_yield(true); - cco_final: // required label. + cco_final: // this label is required. printf("finish\n"); cstr_drop(&U->line); fclose(U->fp); cco_end(false); } -int main(void) { - struct file_nextline z = {__FILE__}; +int main(void) +{ + struct file_nextline it = {__FILE__}; int n = 0; - while (file_nextline(&z)) { - printf("%3d %s\n", ++n, cstr_str(&z.line)); + while (file_nextline(&it)) + { + printf("%3d %s\n", ++n, cstr_str(&it.line)); + //if (n == 10) cco_stop(&it); } } diff --git a/misc/examples/forfilter.c b/misc/examples/forfilter.c index fdf8be6f..0d72bd1b 100644 --- a/misc/examples/forfilter.c +++ b/misc/examples/forfilter.c @@ -28,17 +28,15 @@ void demo1(void) printf(" %d", *i.ref); puts(""); - int res, sum = 0; + int 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 + c_flt_skipwhile(i, *i.ref != 80) && + c_flt_skip(i, 1) && + flt_isEven(i) && + flt_skipValue(i, 80) && + c_flt_take(i, 5) // short-circuit ){ - sum += res = flt_square(i); - printf(" %d", res); + sum += flt_square(i); } printf("\n sum: %d\n", sum); @@ -62,11 +60,13 @@ void demo2(void) { IVec vector = {0}; - c_forfilter (x, crange, crange_obj(INT64_MAX), - c_flt_skipwhile(x, *x.ref != 11) && - *x.ref % 2 != 0 && - c_flt_take(x, 5)) + c_forfilter (x, crange, crange_object(INT64_MAX), + 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); @@ -130,13 +130,14 @@ void demo5(void) 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,5)) + 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,5) + ){ printf(" %lld", *i.ref); - + } puts(""); } diff --git a/misc/examples/forloops.c b/misc/examples/forloops.c index 54b49485..82126456 100644 --- a/misc/examples/forloops.c +++ b/misc/examples/forloops.c @@ -52,24 +52,17 @@ int main() puts("\n\nc_forpair:"); c_forpair (key, val, IMap, map) printf(" (%d %d)", *_.key, *_.val); - - puts("\n\nc_forfilter 1:"); - c_forfilter (i, IVec, vec, c_flt_take(i, 3)) - printf(" %d", *i.ref); - + #define isOdd(i) (*i.ref & 1) - puts("\n\nc_forfilter 2:"); - c_forfilter (i, IVec, vec, - c_flt_skipwhile(i, *i.ref != 65) && - c_flt_takewhile(i, *i.ref != 280) && - c_flt_skipwhile(i, isOdd(i)) && - isOdd(i) && - c_flt_skip(i, 2) && - c_flt_take(i, 2)) + puts("\n\nc_forfilter:"); + c_forfilter (i, IVec, vec, + isOdd(i) && + c_flt_skip(i, 4) && + c_flt_take(i, 4) + ){ printf(" %d", *i.ref); - puts(""); - // 189 + } IVec_drop(&vec); IMap_drop(&map); diff --git a/misc/examples/functor.c b/misc/examples/functor.c index 8952c710..f37e41d5 100644 --- a/misc/examples/functor.c +++ b/misc/examples/functor.c @@ -43,14 +43,16 @@ static bool int_lambda(const int* x, const int* y) { return (*x ^ 1) < (*y ^ 1); int main() { - const int data[] = {1,8,5,6,3,4,0,9,7,2}, n = c_ARRAYLEN(data); + const int data[] = {1,8,5,6,3,4,0,9,7,2}, n = c_arraylen(data); printf("data: \t"); - c_forrange (i, n) printf("%d ", data[i]); + c_forrange (i, n) + printf("%d ", data[i]); puts(""); IPQueue q1 = {ipque_init(), int_less}; // Max priority queue IPQueue minq1 = {ipque_init(), int_greater}; // Min priority queue IPQueue q5 = {ipque_init(), int_lambda}; // Using lambda to compare elements. + c_forrange (i, n) ipque_push(&q1.Q, data[i]); print_queue("q1", q1); diff --git a/misc/examples/gauss1.c b/misc/examples/gauss1.c deleted file mode 100644 index 67871aa9..00000000 --- a/misc/examples/gauss1.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include - -#include -#include - -// Declare int -> int hashmap. Uses typetag 'ii' for ints. -#define i_key int -#define i_val int -#define i_tag ii -#include - -// Declare int vector with entries from the cmap. -#define i_val cmap_ii_value -#define i_less(x, y) x->first < y->first -#define i_tag ii -#include - -int main() -{ - enum {N = 10000000}; - const double Mean = -12.0, StdDev = 6.0, Scale = 74; - - printf("Demo of gaussian / normal distribution of %d random samples\n", N); - - // Setup random engine with normal distribution. - uint64_t seed = (uint64_t)time(NULL); - stc64_t rng = stc64_new(seed); - stc64_normalf_t dist = stc64_normalf_new(Mean, StdDev); - - // Create and init histogram vec and map with defered destructors: - cvec_ii histvec = {0}; - cmap_ii histmap = {0}; - - c_forrange (N) { - int index = (int)round( stc64_normalf(&rng, &dist) ); - cmap_ii_insert(&histmap, index, 0).ref->second += 1; - } - - // Transfer map to vec and sort it by map keys. - c_foreach (i, cmap_ii, histmap) - cvec_ii_push(&histvec, (cmap_ii_value){i.ref->first, i.ref->second}); - - cvec_ii_sort(&histvec); - - // Print the gaussian bar chart - c_foreach (i, cvec_ii, histvec) { - int n = (int)(i.ref->second * StdDev * Scale * 2.5 / (double)N); - if (n > 0) { - printf("%4d ", i.ref->first); - c_forrange (n) printf("*"); - puts(""); - } - } - - cvec_ii_drop(&histvec); - cmap_ii_drop(&histmap); -} diff --git a/misc/examples/gauss2.c b/misc/examples/gauss2.c index 79397f0c..be514c12 100644 --- a/misc/examples/gauss2.c +++ b/misc/examples/gauss2.c @@ -6,7 +6,7 @@ // Declare int -> int sorted map. #define i_key int -#define i_val size_t +#define i_val int #include int main() @@ -22,16 +22,16 @@ int main() stc64_normalf_t dist = stc64_normalf_new(Mean, StdDev); // Create and init histogram map with defered destruct - csmap_int mhist = {0}; + csmap_int hist = {0}; cstr bar = {0}; c_forrange (N) { - int index = (int) round( stc64_normalf(&rng, &dist) ); - csmap_int_insert(&mhist, index, 0).ref->second += 1; + int index = (int)round( stc64_normalf(&rng, &dist) ); + csmap_int_insert(&hist, index, 0).ref->second += 1; } // Print the gaussian bar chart - c_forpair (index, count, csmap_int, mhist) { + c_forpair (index, count, csmap_int, hist) { int n = (int)((float)*_.count * StdDev * Scale * 2.5f / (float)N); if (n > 0) { cstr_resize(&bar, n, '*'); @@ -39,5 +39,5 @@ int main() } } cstr_drop(&bar); - csmap_int_drop(&mhist); + csmap_int_drop(&hist); } diff --git a/misc/examples/inits.c b/misc/examples/inits.c index 7530dd08..81bcdd3e 100644 --- a/misc/examples/inits.c +++ b/misc/examples/inits.c @@ -40,7 +40,7 @@ int main(void) const float nums[] = {4.0f, 2.0f, 5.0f, 3.0f, 1.0f}; // PRIORITY QUEUE - c_forrange (i, c_ARRAYLEN(nums)) + c_forrange (i, c_arraylen(nums)) cpque_f_push(&floats, nums[i]); puts("\npop and show high priorites first:"); diff --git a/misc/examples/mapmap.c b/misc/examples/mapmap.c index 8fc307ab..668da5de 100644 --- a/misc/examples/mapmap.c +++ b/misc/examples/mapmap.c @@ -7,24 +7,13 @@ #define i_key_str // name #define i_val_str // email #define i_keydrop(p) (printf("kdrop: %s\n", cstr_str(p)), cstr_drop(p)) // override -#include +#include // Departments: std::map #define i_type Departments #define i_key_str // dep. name #define i_valclass People -// i_key_str implies: -// #define i_tag str -// #define i_key cstr -// #define i_keyclone cstr_clone -// #define i_keydrop cstr_drop -// #define i_cmp cstr_cmp -// #define i_hash cstr_hash -// i_valclass implies: -// #define i_val People -// #define i_valclone People_clone -// #define i_valdrop People_drop -#include +#include void add(Departments* deps, const char* name, const char* email, const char* dep) diff --git a/misc/examples/multimap.c b/misc/examples/multimap.c index 9c37db6c..d8981a81 100644 --- a/misc/examples/multimap.c +++ b/misc/examples/multimap.c @@ -71,7 +71,7 @@ int main() csmap_OL multimap = {0}; const clist_OL empty = clist_OL_init(); - for (size_t i = 0; i < c_ARRAYLEN(ol_data); ++i) + for (size_t i = 0; i < c_arraylen(ol_data); ++i) { struct OlympicsData* d = &ol_data[i]; OlympicLoc loc = {.year = d->year, diff --git a/misc/examples/new_deq.c b/misc/examples/new_deq.c deleted file mode 100644 index 467fd4e5..00000000 --- a/misc/examples/new_deq.c +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include - -forward_cdeq(cdeq_i32, int); -forward_cdeq(cdeq_pnt, struct Point); - -struct MyStruct { - cdeq_i32 intvec; - cdeq_pnt pntvec; -} typedef MyStruct; - - -#define i_val int -#define i_opt c_is_forward -#define i_tag i32 -#include - -struct Point { int x, y; } typedef Point; -int point_cmp(const Point* a, const Point* b) { - int c = a->x - b->x; - return c ? c : a->y - b->y; -} - -#define i_val Point -#define i_cmp point_cmp -#define i_opt c_is_forward -#define i_tag pnt -#include - - -int main() -{ - cdeq_pnt pvec = {0}; - - cdeq_pnt_push_back(&pvec, (Point){42, 14}); - cdeq_pnt_push_back(&pvec, (Point){32, 94}); - cdeq_pnt_push_front(&pvec, (Point){62, 81}); - - cdeq_pnt_sort(&pvec); - - c_foreach (i, cdeq_pnt, pvec) - printf(" (%d %d)", i.ref->x, i.ref->y); - puts(""); - - cdeq_pnt_drop(&pvec); -} diff --git a/misc/examples/prime.c b/misc/examples/prime.c index 18bf3490..9ffb2f53 100644 --- a/misc/examples/prime.c +++ b/misc/examples/prime.c @@ -44,8 +44,9 @@ int main(void) 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)) { + 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/printspan.c b/misc/examples/printspan.c index 127b07b9..7459ac77 100644 --- a/misc/examples/printspan.c +++ b/misc/examples/printspan.c @@ -16,7 +16,8 @@ using_cspan(intspan, int, 1); void printMe(intspan container) { printf("%d:", (int)cspan_size(&container)); - c_foreach (e, intspan, container) printf(" %d", *e.ref); + c_foreach (e, intspan, container) + printf(" %d", *e.ref); puts(""); } @@ -31,31 +32,26 @@ int main() intspan sp2 = cspan_from_array(arr); printMe( (intspan)cspan_subspan(&sp2, 1, 4) ); - cvec_int vec; - cstack_int stk; - cdeq_int deq; - csset_str set; - c_defer( - cvec_int_drop(&vec), - cstack_int_drop(&stk), - cdeq_int_drop(&deq), - csset_str_drop(&set) - ) { - vec = c_make(cvec_int, {1, 2, 3, 4, 5}); - printMe( (intspan)cspan_from(&vec) ); - - printMe( sp2 ); - - stk = c_make(cstack_int, {1, 2, 3, 4, 5, 6, 7}); - printMe( (intspan)cspan_from(&stk) ); - - deq = c_make(cdeq_int, {1, 2, 3, 4, 5, 6, 7, 8}); - printMe( (intspan)cspan_from(&deq) ); - - set = c_make(csset_str, {"5", "7", "4", "3", "8", "2", "1", "9", "6"}); - printf("%d:", (int)csset_str_size(&set)); - c_foreach (e, csset_str, set) - printf(" %s", cstr_str(e.ref)); - puts(""); - } + cvec_int vec = c_make(cvec_int, {1, 2, 3, 4, 5}); + printMe( (intspan)cspan_from(&vec) ); + + printMe( sp2 ); + + cstack_int stk = c_make(cstack_int, {1, 2, 3, 4, 5, 6, 7}); + printMe( (intspan)cspan_from(&stk) ); + + cdeq_int deq = c_make(cdeq_int, {1, 2, 3, 4, 5, 6, 7, 8}); + printMe( (intspan)cspan_from(&deq) ); + + csset_str set = c_make(csset_str, {"5", "7", "4", "3", "8", "2", "1", "9", "6"}); + printf("%d:", (int)csset_str_size(&set)); + c_foreach (e, csset_str, set) + printf(" %s", cstr_str(e.ref)); + puts(""); + + // cleanup + cvec_int_drop(&vec); + cstack_int_drop(&stk); + cdeq_int_drop(&deq); + csset_str_drop(&set); } diff --git a/misc/examples/rawptr_elements.c b/misc/examples/rawptr_elements.c index f46a7f5e..01bcdc44 100644 --- a/misc/examples/rawptr_elements.c +++ b/misc/examples/rawptr_elements.c @@ -2,58 +2,58 @@ #include #include -// Map of cstr => int64 pointers -typedef int64_t inttype; -// Do it without cbox: +// Create cmap of cstr => long* #define i_type SIPtrMap #define i_key_str -#define i_val inttype* -#define i_valraw inttype -#define i_valfrom(raw) c_new(inttype, raw) +#define i_val long* +#define i_valraw long +#define i_valfrom(raw) c_new(long, raw) #define i_valto(x) **x -#define i_valclone(x) c_new(inttype, *x) +#define i_valclone(x) c_new(long, *x) #define i_valdrop(x) c_free(*x) #include -// With cbox: +// Alternatively, using cbox: #define i_type IBox -#define i_val int -#include // +#define i_val long +#include // unique_ptr alike. +// cmap of cstr => IBox #define i_type SIBoxMap #define i_key_str -#define i_valboxed IBox +#define i_valboxed IBox // i_valboxed: use properties from IBox automatically #include int main() { - SIPtrMap map = {0}, m1; - SIBoxMap m2 = {0}; - c_defer( - SIPtrMap_drop(&map), - SIPtrMap_drop(&m1), - SIBoxMap_drop(&m2) - ){ - printf("\nMap with pointer elements:\n"); - SIPtrMap_insert(&map, cstr_from("testing"), c_new(inttype, 1)); - SIPtrMap_insert(&map, cstr_from("done"), c_new(inttype, 2)); - - // Emplace: implicit key, val construction: - SIPtrMap_emplace(&map, "hello", 3); - SIPtrMap_emplace(&map, "goodbye", 4); - - m1 = SIPtrMap_clone(map); - - c_forpair (name, number, SIPtrMap, m1) - printf("%s: %" PRId64 "\n", cstr_str(_.name), **_.number); - - - puts("\nIBox map:"); - SIBoxMap_insert(&m2, cstr_from("Hello"), IBox_make(123)); - SIBoxMap_emplace(&m2, "World", 999); - c_forpair (name, number, SIBoxMap, m2) - printf("%s: %d\n", cstr_str(_.name), *_.number->get); - puts(""); - } + // These have the same behaviour, except IBox has a get member: + SIPtrMap map1 = {0}; + SIBoxMap map2 = {0}; + + printf("\nMap cstr => long*:\n"); + SIPtrMap_insert(&map1, cstr_from("Test1"), c_new(long, 1)); + SIPtrMap_insert(&map1, cstr_from("Test2"), c_new(long, 2)); + + // Emplace implicitly creates cstr from const char* and an owned long* from long! + SIPtrMap_emplace(&map1, "Test3", 3); + SIPtrMap_emplace(&map1, "Test4", 4); + + c_forpair (name, number, SIPtrMap, map1) + printf("%s: %ld\n", cstr_str(_.name), **_.number); + + puts("\nMap cstr => IBox:"); + SIBoxMap_insert(&map2, cstr_from("Test1"), IBox_make(1)); + SIBoxMap_insert(&map2, cstr_from("Test2"), IBox_make(2)); + + // Emplace implicitly creates cstr from const char* and IBox from long! + SIBoxMap_emplace(&map2, "Test3", 3); + SIBoxMap_emplace(&map2, "Test4", 4); + + c_forpair (name, number, SIBoxMap, map2) + printf("%s: %ld\n", cstr_str(_.name), *_.number->get); + puts(""); + + SIPtrMap_drop(&map1); + SIBoxMap_drop(&map2); } diff --git a/misc/examples/regex2.c b/misc/examples/regex2.c index 883dd112..3133f7c2 100644 --- a/misc/examples/regex2.c +++ b/misc/examples/regex2.c @@ -16,7 +16,7 @@ int main() }; cregex re = {0}; - c_forrange (i, c_ARRAYLEN(s)) + c_forrange (i, c_arraylen(s)) { int res = cregex_compile(&re, s[i].pattern); if (res < 0) { diff --git a/misc/examples/replace.c b/misc/examples/replace.c index c22c71ff..cf5b45cb 100644 --- a/misc/examples/replace.c +++ b/misc/examples/replace.c @@ -8,27 +8,28 @@ int main () // replace signatures used in the same order as described above: - // Ustring positions: 0123456789*123456789*12345 - cstr s = cstr_from(base); // "this is a test string." + // Ustring positions: 0123456789*123456789*12345 + cstr s = cstr_from(base); // "this is a test string." cstr m = cstr_clone(s); - c_defer (cstr_drop(&s), cstr_drop(&m)) { - cstr_append(&m, cstr_str(&m)); - cstr_append(&m, cstr_str(&m)); - printf("%s\n", cstr_str(&m)); - cstr_replace_at(&s, 9, 5, s2); // "this is an example string." (1) - printf("(1) %s\n", cstr_str(&s)); + cstr_append(&m, cstr_str(&m)); + cstr_append(&m, cstr_str(&m)); + printf("%s\n", cstr_str(&m)); - cstr_replace_at_sv(&s, 19, 6, c_sv(s3+7, 6)); // "this is an example phrase." (2) - printf("(2) %s\n", cstr_str(&s)); + cstr_replace_at(&s, 9, 5, s2); // "this is an example string." (1) + printf("(1) %s\n", cstr_str(&s)); - cstr_replace_at(&s, 8, 10, "just a"); // "this is just a phrase." (3) - printf("(3) %s\n", cstr_str(&s)); + cstr_replace_at_sv(&s, 19, 6, c_sv(s3+7, 6)); // "this is an example phrase." (2) + printf("(2) %s\n", cstr_str(&s)); - cstr_replace_at_sv(&s, 8, 6, c_sv("a shorty", 7)); // "this is a short phrase." (4) - printf("(4) %s\n", cstr_str(&s)); + cstr_replace_at(&s, 8, 10, "just a"); // "this is just a phrase." (3) + printf("(3) %s\n", cstr_str(&s)); - cstr_replace_at(&s, 22, 1, "!!!"); // "this is a short phrase!!!" (5) - printf("(5) %s\n", cstr_str(&s)); - } + cstr_replace_at_sv(&s, 8, 6, c_sv("a shorty", 7)); // "this is a short phrase." (4) + printf("(4) %s\n", cstr_str(&s)); + + cstr_replace_at(&s, 22, 1, "!!!"); // "this is a short phrase!!!" (5) + printf("(5) %s\n", cstr_str(&s)); + + c_drop(cstr, &s, &m); } diff --git a/misc/examples/shape.c b/misc/examples/shape.c index 2aabdcc2..e24f7fd7 100644 --- a/misc/examples/shape.c +++ b/misc/examples/shape.c @@ -139,23 +139,23 @@ void testShape(const Shape* shape) int main(void) { Shapes shapes = {0}; - c_defer (Shapes_drop(&shapes)) - { - Triangle* tri1 = c_new(Triangle, Triangle_from((Point){5, 7}, (Point){12, 7}, (Point){12, 20})); - Polygon* pol1 = c_new(Polygon, Polygon_init()); - Polygon* pol2 = c_new(Polygon, Polygon_init()); - - c_forlist (i, Point, {{50, 72}, {123, 73}, {127, 201}, {828, 333}}) - Polygon_addPoint(pol1, *i.ref); - - c_forlist (i, Point, {{5, 7}, {12, 7}, {12, 20}, {82, 33}, {17, 56}}) - Polygon_addPoint(pol2, *i.ref); - - Shapes_push(&shapes, &tri1->shape); - Shapes_push(&shapes, &pol1->shape); - Shapes_push(&shapes, &pol2->shape); - - c_foreach (i, Shapes, shapes) - testShape(*i.ref); - } + + Triangle* tri1 = c_new(Triangle, Triangle_from((Point){5, 7}, (Point){12, 7}, (Point){12, 20})); + Polygon* pol1 = c_new(Polygon, Polygon_init()); + Polygon* pol2 = c_new(Polygon, Polygon_init()); + + c_forlist (i, Point, {{50, 72}, {123, 73}, {127, 201}, {828, 333}}) + Polygon_addPoint(pol1, *i.ref); + + c_forlist (i, Point, {{5, 7}, {12, 7}, {12, 20}, {82, 33}, {17, 56}}) + Polygon_addPoint(pol2, *i.ref); + + Shapes_push(&shapes, &tri1->shape); + Shapes_push(&shapes, &pol1->shape); + Shapes_push(&shapes, &pol2->shape); + + c_foreach (i, Shapes, shapes) + testShape(*i.ref); + + Shapes_drop(&shapes); } diff --git a/misc/examples/sidebyside.cpp b/misc/examples/sidebyside.cpp index a817b5a5..a7c1008c 100644 --- a/misc/examples/sidebyside.cpp +++ b/misc/examples/sidebyside.cpp @@ -24,9 +24,8 @@ int main() { std::cout << i.first << ", " << i.second << std::endl; std::cout << std::endl; } - - IIMap hist = {0}; - c_defer (IIMap_drop(&hist)) { + { + IIMap hist = {0}; IIMap_insert(&hist, 12, 100).ref->second += 1; IIMap_insert(&hist, 13, 100).ref->second += 1; IIMap_insert(&hist, 12, 100).ref->second += 1; @@ -34,6 +33,7 @@ int main() { c_foreach (i, IIMap, hist) printf("%d, %d\n", i.ref->first, i.ref->second); puts(""); + IIMap_drop(&hist); } // =================================================== { @@ -44,15 +44,14 @@ int main() { std::cout << i.first << ", " << i.second << std::endl; std::cout << std::endl; } - - SIMap food = {0}; - c_defer (SIMap_drop(&food)) { + SIMap food = {0}; c_forlist (i, SIMap_raw, {{"burger", 5}, {"pizza", 12}, {"steak", 15}}) SIMap_emplace(&food, i.ref->first, i.ref->second); c_foreach (i, SIMap, food) printf("%s, %d\n", cstr_str(&i.ref->first), i.ref->second); puts(""); + SIMap_drop(&food); } } diff --git a/misc/examples/splitstr.c b/misc/examples/splitstr.c index bf90b5d4..2bc6fc07 100644 --- a/misc/examples/splitstr.c +++ b/misc/examples/splitstr.c @@ -15,5 +15,6 @@ int main() cregex re = cregex_from("[^ ]+"); c_formatch (i, &re, " Hello World C99! ") printf("'%.*s'\n", c_SV(i.match[0])); + cregex_drop(&re); } -- cgit v1.2.3 From 59d74d181e44dd05a8570b42fc6284745e225664 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Tue, 28 Mar 2023 19:29:05 +0200 Subject: Example changes. Added crand.h possible replacement for crandom.h --- docs/ccommon_api.md | 2 +- include/stc/crand.h | 194 +++++++++++++++++++++++++++++++++++++++++++++++++ misc/examples/gauss2.c | 11 +-- misc/examples/prime.c | 5 +- misc/examples/shape.c | 19 ++--- 5 files changed, 211 insertions(+), 20 deletions(-) create mode 100644 include/stc/crand.h (limited to 'misc/examples/shape.c') diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index 53ba096a..46966fd9 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -92,7 +92,7 @@ Iterate containers with stop-criteria and chained range filtering. | `c_flt_skipwhile(it, predicate)` | Skip items until predicate is false | | `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 | +| `c_flt_last(it)` | Get value of last count/skip*/take* | ```c // Example: #include diff --git a/include/stc/crand.h b/include/stc/crand.h new file mode 100644 index 00000000..4ebc402d --- /dev/null +++ b/include/stc/crand.h @@ -0,0 +1,194 @@ +/* MIT License + * + * Copyright (c) 2023 Tyge Løvset + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "ccommon.h" + +#ifndef CRAND_H_INCLUDED +#define CRAND_H_INCLUDED +/* +// crand: Pseudo-random number generator +#include "stc/crand.h" + +int main() { + uint64_t seed = 123456789; + crand_t rng = crand_from(seed); + crand_unif_t dist1 = crand_unif_from(1, 6); + crandf_unif_t dist2 = crandf_unif_from(1.0, 10.0); + crandf_norm_t dist3 = crandf_norm_from(1.0, 10.0); + + uint64_t i = crand_r(&rng); + int64_t iu = crand_unif(&rng, &dist1); + double xu = crandf_unif(&rng, &dist2); + double xn = crandf_norm(&rng, &dist3); +} +*/ +#include +#include + +typedef struct crand { uint64_t state[5]; } crand_t; +typedef struct crand_unif { int64_t lower; uint64_t range, threshold; } crand_unif_t; +typedef struct crandf_unif { double lower, range; } crandf_unif_t; +typedef struct crandf_norm { double mean, stddev, next; int has_next; } crandf_norm_t; + +/* PRNG crand_t. + * Very fast PRNG suited for parallel usage with Weyl-sequence parameter. + * 320-bit state, 256 bit is mutable. + * Noticable faster than xoshiro and pcg, slighly slower than wyrand64 and + * Romu, but these have restricted capacity for larger parallel jobs or unknown minimum periods. + * crand_t supports 2^63 unique threads with a minimum 2^64 period lengths each. + * Passes all statistical tests, e.g PractRand and correlation tests, i.e. interleaved + * streams with one-bit diff state. Even the 16-bit version (LR=6, RS=5, LS=3) passes + * PractRand to multiple TB input. + */ + +/* Global crand_t PRNGs */ +STC_API void csrand(uint64_t seed); +STC_API uint64_t crand(void); +STC_API double crandf(void); + +/* Init crand_t prng with a seed */ +STC_API crand_t crand_from(uint64_t seed); + +/* Unbiased bounded uniform distribution. range [low, high] */ +STC_API crand_unif_t crand_unif_from(int64_t low, int64_t high); +STC_API int64_t crand_unif(crand_t* rng, crand_unif_t* dist); + +/* Normal distribution PRNG */ +STC_API double crandf_norm(crand_t* rng, crandf_norm_t* dist); + + +/* Main crand_t prng */ +STC_INLINE uint64_t crand_r(crand_t* rng) { + enum {LR=24, RS=11, LS=3}; uint64_t *s = rng->state; + const uint64_t out = (s[0] ^ (s[3] += s[4])) + s[1]; + s[0] = s[1] ^ (s[1] >> RS); + s[1] = s[2] + (s[2] << LS); + s[2] = ((s[2] << LR) | (s[2] >> (64 - LR))) + out; + return out; +} + +/* Float64 random number in range [0.0, 1.0). */ +STC_INLINE double crandf_r(crand_t* rng) { + union {uint64_t i; double f;} u = {0x3FF0000000000000U | (crand_r(rng) >> 12)}; + return u.f - 1.0; +} + +/* Float64 uniform distributed RNG, range [low, high). */ +STC_INLINE double crandf_unif(crand_t* rng, crandf_unif_t* dist) { + return crandf_r(rng)*dist->range + dist->lower; +} + +/* Init uniform distributed float64 RNG, range [low, high). */ +STC_INLINE crandf_unif_t crandf_unif_from(double low, double high) { + return c_LITERAL(crandf_unif_t){low, high - low}; +} + +/* Marsaglia polar method for gaussian/normal distribution, float64. */ +STC_INLINE crandf_norm_t crandf_norm_from(double mean, double stddev) { + return c_LITERAL(crandf_norm_t){mean, stddev, 0.0, 0}; +} + +/* -------------------------- IMPLEMENTATION ------------------------- */ +#if defined(i_implement) + +/* Global random() */ +static crand_t crand_global = {{ + 0x26aa069ea2fb1a4d, 0x70c72c95cd592d04, + 0x504f333d3aa0b359, 0x9e3779b97f4a7c15, + 0x6a09e667a754166b +}}; + +STC_DEF void csrand(uint64_t seed) { + crand_global = crand_from(seed); +} + +STC_DEF uint64_t crand(void) { + return crand_r(&crand_global); +} + +STC_DEF double crandf(void) { + return crandf_r(&crand_global); +} + +/* rng.state[4] must be odd */ +STC_DEF crand_t crand_from(uint64_t seed) { + crand_t rng = {{seed + 0x26aa069ea2fb1a4d, + seed*0x9e3779b97f4a7c15 + 0x70c72c95cd592d04, + seed + 0x504f333d3aa0b359, + seed*0x6a09e667a754166b, seed<<1 | 1}}; + return rng; +} + +/* Init unbiased uniform uint RNG with bounds [low, high] */ +STC_DEF crand_unif_t crand_unif_from(int64_t low, int64_t high) { + crand_unif_t dist = {low, (uint64_t) (high - low + 1)}; + dist.threshold = (uint64_t)(0 - dist.range) % dist.range; + return dist; +} + +#if defined(__SIZEOF_INT128__) + #define c_umul128(a, b, lo, hi) \ + do { __uint128_t _z = (__uint128_t)(a)*(b); \ + *(lo) = (uint64_t)_z, *(hi) = (uint64_t)(_z >> 64U); } while(0) +#elif defined(_MSC_VER) && defined(_WIN64) + #include + #define c_umul128(a, b, lo, hi) ((void)(*(lo) = _umul128(a, b, hi))) +#elif defined(__x86_64__) + #define c_umul128(a, b, lo, hi) \ + asm("mulq %3" : "=a"(*(lo)), "=d"(*(hi)) : "a"(a), "rm"(b)) +#endif + +/* Int uniform distributed RNG, range [low, high]. */ +STC_DEF int64_t crand_unif(crand_t* rng, crand_unif_t* d) { +#ifdef c_umul128 + uint64_t lo, hi; + do { c_umul128(crand_r(rng), d->range, &lo, &hi); } while (lo < d->threshold); + return d->lower + (int64_t)hi; +#else + uint64_t x, r; + do { x = crand_r(rng); r = x % d->range; } while (x - r > -d->range); + return d->lower + r; +#endif +} + +/* Normal distribution PRNG */ +STC_DEF double crandf_norm(crand_t* rng, crandf_norm_t* dist) { + double u1, u2, s, m; + if (dist->has_next++ & 1) + return dist->next * dist->stddev + dist->mean; + do { + u1 = 2.0 * crandf_r(rng) - 1.0; + u2 = 2.0 * crandf_r(rng) - 1.0; + s = u1*u1 + u2*u2; + } while (s >= 1.0 || s == 0.0); + m = sqrt(-2.0 * log(s) / s); + dist->next = u2 * m; + return (u1 * m) * dist->stddev + dist->mean; +} + +#endif +#endif +#undef i_opt +#undef i_static +#undef i_header +#undef i_implement +#undef i_extern diff --git a/misc/examples/gauss2.c b/misc/examples/gauss2.c index be514c12..ce29f786 100644 --- a/misc/examples/gauss2.c +++ b/misc/examples/gauss2.c @@ -11,14 +11,15 @@ int main() { - enum {N = 10000000}; - const double Mean = -12.0, StdDev = 6.0, Scale = 74; + enum {N = 5000000}; + uint64_t seed = (uint64_t)time(NULL); + stc64_t rng = stc64_new(seed); + const float Mean = round(stc64_randf(&rng)*98.f - 49.f), StdDev = stc64_randf(&rng)*10.f + 1.f, Scale = 74.f; printf("Demo of gaussian / normal distribution of %d random samples\n", N); + printf("Mean %f, StdDev %f\n", Mean, StdDev); // Setup random engine with normal distribution. - uint64_t seed = (uint64_t)time(NULL); - stc64_t rng = stc64_new(seed); stc64_normalf_t dist = stc64_normalf_new(Mean, StdDev); // Create and init histogram map with defered destruct @@ -32,7 +33,7 @@ int main() // Print the gaussian bar chart c_forpair (index, count, csmap_int, hist) { - int n = (int)((float)*_.count * StdDev * Scale * 2.5f / (float)N); + int n = (int)round((float)*_.count * StdDev * Scale * 2.5f / (float)N); if (n > 0) { cstr_resize(&bar, n, '*'); printf("%4d %s\n", *_.index, cstr_str(&bar)); diff --git a/misc/examples/prime.c b/misc/examples/prime.c index 9ffb2f53..34d64f10 100644 --- a/misc/examples/prime.c +++ b/misc/examples/prime.c @@ -42,9 +42,8 @@ int main(void) 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_forfilter (i, crange, crange_object(n - 1, 0, -2), + cbits_test(&primes, *i.ref/2) && c_flt_take(i, 50) ){ printf("%lld ", *i.ref); diff --git a/misc/examples/shape.c b/misc/examples/shape.c index e24f7fd7..d7116039 100644 --- a/misc/examples/shape.c +++ b/misc/examples/shape.c @@ -4,7 +4,7 @@ #include #include -#define c_dyn_cast(T, s) \ +#define DYN_CAST(T, s) \ (&T##_api == (s)->api ? (T*)(s) : (T*)0) // Shape definition @@ -53,15 +53,14 @@ typedef struct { extern struct ShapeAPI Triangle_api; -Triangle Triangle_from(Point a, Point b, Point c) -{ - Triangle t = {.shape={.api=&Triangle_api}, .p={a, b, c}}; +Triangle Triangle_from(Point a, Point b, Point c) { + Triangle t = {{&Triangle_api}, {a, b, c}}; return t; } static void Triangle_draw(const Shape* shape) { - const Triangle* self = c_dyn_cast(Triangle, shape); + const Triangle* self = DYN_CAST(Triangle, shape); printf("Triangle : (%g,%g), (%g,%g), (%g,%g)\n", self->p[0].x, self->p[0].y, self->p[1].x, self->p[1].y, @@ -88,9 +87,8 @@ typedef struct { extern struct ShapeAPI Polygon_api; -Polygon Polygon_init(void) -{ - Polygon p = {.shape={.api=&Polygon_api}, .points=PointVec_init()}; +Polygon Polygon_init(void) { + Polygon p = {{&Polygon_api}, {0}}; return p; } @@ -101,15 +99,14 @@ void Polygon_addPoint(Polygon* self, Point p) static void Polygon_drop(Shape* shape) { - Polygon* self = c_dyn_cast(Polygon, shape); + Polygon* self = DYN_CAST(Polygon, shape); printf("poly destructed\n"); PointVec_drop(&self->points); - Shape_drop(shape); } static void Polygon_draw(const Shape* shape) { - const Polygon* self = c_dyn_cast(Polygon, shape); + const Polygon* self = DYN_CAST(Polygon, shape); printf("Polygon :"); c_foreach (i, PointVec, self->points) printf(" (%g,%g)", i.ref->x, i.ref->y); -- cgit v1.2.3