squiggle.c

Self-contained Monte Carlo estimation in C99
Log | Files | Refs | README

commit 6247fbfb7bcc3d396f7a29a96b8d6e90ed057849
parent 11e965be4fd5a8e45605fbdbc4213d58d8da936c
Author: NunoSempere <nuno.sempere@protonmail.com>
Date:   Sun, 16 Jul 2023 22:58:20 +0200

simplify PROCESS_ERROR macro

Diffstat:
MREADME.md | 13+++++++++++--
Mexamples/04_sample_from_cdf_simple/example | 0
Mexamples/05_sample_from_cdf_beta/example | 0
Mexamples/05_sample_from_cdf_beta/example.c | 4++--
Msquiggle.c | 45+++++++++++++++++++++++----------------------
Msquiggle.h | 16+++-------------
6 files changed, 39 insertions(+), 39 deletions(-)

diff --git 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 <https://www.squiggle-language.com/docs/Api/Dist> +- [ ] Support all distribution functions in <https://www.squiggle-language.com/docs/Api/Dist>, and do so efficiently ## Done diff --git a/examples/04_sample_from_cdf_simple/example b/examples/04_sample_from_cdf_simple/example Binary files differ. diff --git a/examples/05_sample_from_cdf_beta/example b/examples/05_sample_from_cdf_beta/example Binary files differ. diff --git 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 @@ -6,20 +6,9 @@ #include <stdlib.h> #include <time.h> -#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 @@ -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);