simplify PROCESS_ERROR macro

This commit is contained in:
NunoSempere 2023-07-16 22:58:20 +02:00
parent 11e965be4f
commit 6247fbfb7b
6 changed files with 39 additions and 39 deletions

View File

@ -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 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 - 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. 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. 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. 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 ## To do list
- [ ] Have some more complicated & realistic example - [ ] 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, - Schema: a function which takes a sample and manipulates it,
- and at the end, an array of samples. - and at the end, an array of samples.
- Explain boxes - Explain boxes
- Explain individual examples - [x] Explain individual examples
- Explain nested functions - Explain nested functions
- [ ] Publish online - [ ] 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 ## Done

View File

@ -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. * 3. This notice may not be removed or altered from any source distribution.
*/ */
if (x < 0.0 || x > 1.0) { 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)*/ /*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) struct box cdf_beta(float x)

View File

@ -6,20 +6,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
#define EXIT_ON_ERROR 0
#define MAX_ERROR_LENGTH 500 #define MAX_ERROR_LENGTH 500
#define PROCESS_ERROR(...) \ #define EXIT_ON_ERROR 0
do { \ #define PROCESS_ERROR(error_msg) process_error(error_msg, EXIT_ON_ERROR, __FILE__, __LINE__)
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)
// PI constant // PI constant
const float PI = 3.14159265358979323846; // M_PI in gcc gnu99 const float PI = 3.14159265358979323846; // M_PI in gcc gnu99
@ -139,6 +128,18 @@ struct box {
char* error_msg; 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 // Inverse cdf at point
// Two versions of this function: // Two versions of this function:
// - raw, dealing with cdfs that return floats // - raw, dealing with cdfs that return floats
@ -176,7 +177,7 @@ struct box inverse_cdf_float(float cdf(float), float p)
} }
if (!interval_found) { 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 { } else {
int convergence_condition = 0; 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 }; struct box result = { .empty = 0, .content = low };
return result; return result;
} else { } 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. // but it's also the *correct* thing to do.
struct box cdf_low = cdf_box(low); struct box cdf_low = cdf_box(low);
if (cdf_low.empty) { if (cdf_low.empty) {
PROCESS_ERROR(cdf_low.error_msg); return PROCESS_ERROR(cdf_low.error_msg);
} }
struct box cdf_high = cdf_box(high); struct box cdf_high = cdf_box(high);
if (cdf_high.empty) { if (cdf_high.empty) {
PROCESS_ERROR(cdf_low.error_msg); return PROCESS_ERROR(cdf_low.error_msg);
} }
int low_condition = (cdf_low.content < p); 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) { 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 { } else {
int convergence_condition = 0; int convergence_condition = 0;
@ -263,7 +264,7 @@ struct box inverse_cdf_box(struct box cdf_box(float), float p)
} else { } else {
struct box cdf_mid = cdf_box(mid); struct box cdf_mid = cdf_box(mid);
if (cdf_mid.empty) { if (cdf_mid.empty) {
PROCESS_ERROR(cdf_mid.error_msg); return PROCESS_ERROR(cdf_mid.error_msg);
} }
float mid_sign = cdf_mid.content - p; float mid_sign = cdf_mid.content - p;
if (mid_sign < 0) { 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 }; struct box result = { .empty = 0, .content = low };
return result; return result;
} else { } 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 // 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); float p = rand_0_to_1(seed);
struct box result = inverse_cdf_box(cdf, p); struct box result = inverse_cdf_box(cdf, p);
return result; 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); float p = rand_0_to_1(seed);
struct box result = inverse_cdf_float(cdf, p); struct box result = inverse_cdf_float(cdf, p);

View File

@ -33,20 +33,10 @@ struct box {
}; };
// Macros to handle errors // Macros to handle errors
#define EXIT_ON_ERROR 0
#define MAX_ERROR_LENGTH 500 #define MAX_ERROR_LENGTH 500
#define PROCESS_ERROR(...) \ #define EXIT_ON_ERROR 0
do { \ #define PROCESS_ERROR(error_msg) process_error(error_msg, EXIT_ON_ERROR, __FILE__, __LINE__)
if (EXIT_ON_ERROR) { \ struct box process_error(const char* error_msg, int should_exit, char* file, int line);
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)
// Inverse cdf // Inverse cdf
struct box inverse_cdf_float(float cdf(float), float p); struct box inverse_cdf_float(float cdf(float), float p);