forked from personal/squiggle.c
simplify PROCESS_ERROR macro
This commit is contained in:
parent
11e965be4f
commit
6247fbfb7b
13
README.md
13
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
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -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)
|
||||
|
|
45
squiggle.c
45
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);
|
||||
|
|
16
squiggle.h
16
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);
|
||||
|
|
Loading…
Reference in New Issue
Block a user