diff --git a/README.md b/README.md index 9924e15..b312736 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ A self-contained C99 library that provides a subset of [Squiggle](https://www.sq - Because if you can implement something in C, you can implement it anywhere else - Because it can be made faster if need be, e.g., with a multi-threading library like OpenMP, or by adding more algorithmic complexity -## The core scheme +## The core strategy Have some basic building blocks, like , and return samplers. Use previous samplers to . Then use the final sampler to produce an array of samples. @@ -26,6 +26,13 @@ You can follow some example usage in the examples/ folder 4. In the fourth example, we define some simple cdfs, and we draw samples from those cdfs. We see that this approach is slower than using the built-in samplers, e.g., the normal sampler. 5. In the fifth example, we define the cdf for the beta distribution, and we draw samples from it. +## Related projects + +- [Squiggle](https://www.squiggle-language.com/) +- [SquigglePy](https://github.com/rethinkpriorities/squigglepy) +- [time to botec](https://github.com/NunoSempere/time-to-botec) +- [simple squiggle](https://nunosempere.com/blog/2022/04/17/simple-squiggle/) + ## To do list - [ ] Have some more complicated & realistic example @@ -34,9 +41,11 @@ You can follow some example usage in the examples/ folder - Schema: a function which takes a sample and manipulates it, - and at the end, an array of samples. - Explain boxes - - Explain individual examples + - [x] Explain individual examples - Explain nested functions - [ ] Publish online +- [ ] Support all distribution functions in +- [ ] Support all distribution functions in , and do so efficiently ## Done diff --git a/examples/04_sample_from_cdf_simple/example b/examples/04_sample_from_cdf_simple/example index ab05dac..4bfb751 100755 Binary files a/examples/04_sample_from_cdf_simple/example and b/examples/04_sample_from_cdf_simple/example differ diff --git a/examples/05_sample_from_cdf_beta/example b/examples/05_sample_from_cdf_beta/example index 071bd69..5948358 100755 Binary files a/examples/05_sample_from_cdf_beta/example and b/examples/05_sample_from_cdf_beta/example differ diff --git a/examples/05_sample_from_cdf_beta/example.c b/examples/05_sample_from_cdf_beta/example.c index 7fe0fe3..ce023ca 100644 --- a/examples/05_sample_from_cdf_beta/example.c +++ b/examples/05_sample_from_cdf_beta/example.c @@ -42,7 +42,7 @@ struct box incbeta(float a, float b, float x) * 3. This notice may not be removed or altered from any source distribution. */ if (x < 0.0 || x > 1.0) { - PROCESS_ERROR("x out of bounds [0, 1], in function incbeta"); + return PROCESS_ERROR("x out of bounds [0, 1], in function incbeta"); } /*The continued fraction converges nicely for x < (a+1)/(a+b+2)*/ @@ -102,7 +102,7 @@ struct box incbeta(float a, float b, float x) } } - PROCESS_ERROR("More loops needed, did not converge, in function incbeta"); + return PROCESS_ERROR("More loops needed, did not converge, in function incbeta"); } struct box cdf_beta(float x) diff --git a/squiggle.c b/squiggle.c index 7d020e2..13bf4ed 100644 --- a/squiggle.c +++ b/squiggle.c @@ -6,20 +6,9 @@ #include #include -#define EXIT_ON_ERROR 0 #define MAX_ERROR_LENGTH 500 -#define PROCESS_ERROR(...) \ - do { \ - if (EXIT_ON_ERROR) { \ - printf("@, in %s (%d)", __FILE__, __LINE__); \ - exit(1); \ - } else { \ - char error_msg[MAX_ERROR_LENGTH]; \ - snprintf(error_msg, MAX_ERROR_LENGTH, "@, in %s (%d)", __FILE__, __LINE__); \ - struct box error = { .empty = 1, .error_msg = error_msg }; \ - return error; \ - } \ - } while (0) +#define EXIT_ON_ERROR 0 +#define PROCESS_ERROR(error_msg) process_error(error_msg, EXIT_ON_ERROR, __FILE__, __LINE__) // PI constant const float PI = 3.14159265358979323846; // M_PI in gcc gnu99 @@ -139,6 +128,18 @@ struct box { char* error_msg; }; +struct box process_error(const char* error_msg, int should_exit, char* file, int line){ + if(should_exit){ + printf("@, in %s (%d)", file, line); + exit(1); + }else{ + char error_msg[MAX_ERROR_LENGTH]; + snprintf(error_msg, MAX_ERROR_LENGTH, "@, in %s (%d)", file, line); + struct box error = { .empty = 1, .error_msg = error_msg }; + return error; + } +} + // Inverse cdf at point // Two versions of this function: // - raw, dealing with cdfs that return floats @@ -176,7 +177,7 @@ struct box inverse_cdf_float(float cdf(float), float p) } if (!interval_found) { - PROCESS_ERROR("Interval containing the target value not found, in function inverse_cdf"); + return PROCESS_ERROR("Interval containing the target value not found, in function inverse_cdf"); } else { int convergence_condition = 0; @@ -205,7 +206,7 @@ struct box inverse_cdf_float(float cdf(float), float p) struct box result = { .empty = 0, .content = low }; return result; } else { - PROCESS_ERROR("Search process did not converge, in function inverse_cdf"); + return PROCESS_ERROR("Search process did not converge, in function inverse_cdf"); } } } @@ -228,12 +229,12 @@ struct box inverse_cdf_box(struct box cdf_box(float), float p) // but it's also the *correct* thing to do. struct box cdf_low = cdf_box(low); if (cdf_low.empty) { - PROCESS_ERROR(cdf_low.error_msg); + return PROCESS_ERROR(cdf_low.error_msg); } struct box cdf_high = cdf_box(high); if (cdf_high.empty) { - PROCESS_ERROR(cdf_low.error_msg); + return PROCESS_ERROR(cdf_low.error_msg); } int low_condition = (cdf_low.content < p); @@ -248,7 +249,7 @@ struct box inverse_cdf_box(struct box cdf_box(float), float p) } if (!interval_found) { - PROCESS_ERROR("Interval containing the target value not found, in function inverse_cdf"); + return PROCESS_ERROR("Interval containing the target value not found, in function inverse_cdf"); } else { int convergence_condition = 0; @@ -263,7 +264,7 @@ struct box inverse_cdf_box(struct box cdf_box(float), float p) } else { struct box cdf_mid = cdf_box(mid); if (cdf_mid.empty) { - PROCESS_ERROR(cdf_mid.error_msg); + return PROCESS_ERROR(cdf_mid.error_msg); } float mid_sign = cdf_mid.content - p; if (mid_sign < 0) { @@ -281,19 +282,19 @@ struct box inverse_cdf_box(struct box cdf_box(float), float p) struct box result = { .empty = 0, .content = low }; return result; } else { - PROCESS_ERROR("Search process did not converge, in function inverse_cdf"); + return PROCESS_ERROR("Search process did not converge, in function inverse_cdf"); } } } // Sampler based on inverse cdf and randomness function -struct box sampler_box_cdf(struct box cdf(float), uint32_t* seed) +struct box sampler_cdf_box(struct box cdf(float), uint32_t* seed) { float p = rand_0_to_1(seed); struct box result = inverse_cdf_box(cdf, p); return result; } -struct box sampler_float_cdf(float cdf(float), uint32_t* seed) +struct box sampler_cdf_float(float cdf(float), uint32_t* seed) { float p = rand_0_to_1(seed); struct box result = inverse_cdf_float(cdf, p); diff --git a/squiggle.h b/squiggle.h index e75b64b..ba703c6 100644 --- a/squiggle.h +++ b/squiggle.h @@ -33,20 +33,10 @@ struct box { }; // Macros to handle errors -#define EXIT_ON_ERROR 0 #define MAX_ERROR_LENGTH 500 -#define PROCESS_ERROR(...) \ - do { \ - if (EXIT_ON_ERROR) { \ - printf("@, in %s (%d)", __FILE__, __LINE__); \ - exit(1); \ - } else { \ - char error_msg[MAX_ERROR_LENGTH]; \ - snprintf(error_msg, MAX_ERROR_LENGTH, "@, in %s (%d)", __FILE__, __LINE__); \ - struct box error = { .empty = 1, .error_msg = error_msg }; \ - return error; \ - } \ - } while (0) +#define EXIT_ON_ERROR 0 +#define PROCESS_ERROR(error_msg) process_error(error_msg, EXIT_ON_ERROR, __FILE__, __LINE__) +struct box process_error(const char* error_msg, int should_exit, char* file, int line); // Inverse cdf struct box inverse_cdf_float(float cdf(float), float p);