diff --git a/README.md b/README.md index a13492e..9924e15 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,30 @@ # Squiggle.c - +A self-contained C99 library that provides a subset of [Squiggle](https://www.squiggle-language.com/)'s functionality in C. ## Why C? - Because it is fast -- Because it can be made faster if need be, e.g., with a multi-threading library like OpenMP -- Because if you can implement something in C, you can implement it anywhere else -- Because it will last long -- Because the language is honest - Because I enjoy it +- Because C is honest +- Because it will last long +- Because it can fit in my head +- 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 + +Have some basic building blocks, like , and return samplers. Use previous samplers to . Then use the final sampler to produce an array of samples. + +## Getting started + +You can follow some example usage in the examples/ folder + +1. In the first example, we define a small model, and draw one sample from it +2. In the second example, we define a small model, and return many samples +3. In the third example, we use a gcc extension—nested functions—to rewrite the code from point 2. in a more linear way. +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. ## To do list diff --git a/examples/04_sample_from_cdf_simple/example b/examples/04_sample_from_cdf_simple/example index d280840..ab05dac 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/04_sample_from_cdf_simple/example.c b/examples/04_sample_from_cdf_simple/example.c index 77eee02..76bd474 100644 --- a/examples/04_sample_from_cdf_simple/example.c +++ b/examples/04_sample_from_cdf_simple/example.c @@ -54,7 +54,7 @@ void test_and_time_sampler_float(char* cdf_name, float cdf_float(float), uint32_ printf("\nGetting some samples from %s:\n", cdf_name); clock_t begin = clock(); for (int i = 0; i < NUM_SAMPLES; i++) { - struct box sample = sampler_float_cdf(cdf_float, seed); + struct box sample = sampler_cdf_float(cdf_float, seed); if (sample.empty) { printf("Error in sampler function for %s", cdf_name); } else { diff --git a/examples/04_sample_from_cdf_simple/makefile b/examples/04_sample_from_cdf_simple/makefile index 69adb6d..ac5766b 100644 --- a/examples/04_sample_from_cdf_simple/makefile +++ b/examples/04_sample_from_cdf_simple/makefile @@ -19,7 +19,7 @@ DEPENDENCIES=$(MATH) ## Flags DEBUG= #'-g' -STANDARD=-std=gnu99 ## allows for nested functions. +STANDARD=-std=c99 ## gnu99 allows for nested functions. EXTENSIONS= #-fnested-functions WARNINGS=-Wall OPTIMIZED=-O3#-Ofast diff --git a/examples/05_sample_from_cdf_beta/example b/examples/05_sample_from_cdf_beta/example index 481e2d0..071bd69 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 03198a5..7fe0fe3 100644 --- a/examples/05_sample_from_cdf_beta/example.c +++ b/examples/05_sample_from_cdf_beta/example.c @@ -136,7 +136,7 @@ void test_and_time_sampler_box(char* cdf_name, struct box cdf_box(float), uint32 printf("\nGetting some samples from %s:\n", cdf_name); clock_t begin = clock(); for (int i = 0; i < NUM_SAMPLES; i++) { - struct box sample = sampler_box_cdf(cdf_box, seed); + struct box sample = sampler_cdf_box(cdf_box, seed); if (sample.empty) { printf("Error in sampler function for %s", cdf_name); } else { diff --git a/examples/05_sample_from_cdf_beta/makefile b/examples/05_sample_from_cdf_beta/makefile index 24c2c1c..30cebab 100644 --- a/examples/05_sample_from_cdf_beta/makefile +++ b/examples/05_sample_from_cdf_beta/makefile @@ -19,7 +19,7 @@ DEPENDENCIES=$(MATH) ## Flags DEBUG= #'-g' -STANDARD=-std=gnu99 ## allows for nested functions. +STANDARD=-std=c99 ## gnu99 allows for nested functions. EXTENSIONS= #-fnested-functions WARNINGS=-Wall OPTIMIZED=-O3#-Ofast diff --git a/squiggle.c b/squiggle.c index c68a14a..7d020e2 100644 --- a/squiggle.c +++ b/squiggle.c @@ -22,7 +22,7 @@ } while (0) // PI constant -const float PI = M_PI; // 3.14159265358979323846; +const float PI = 3.14159265358979323846; // M_PI in gcc gnu99 // Pseudo Random number generator diff --git a/squiggle.h b/squiggle.h index 682a8c8..e75b64b 100644 --- a/squiggle.h +++ b/squiggle.h @@ -4,29 +4,15 @@ // uint32_t header #include -// Macros -#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) - // Pseudo Random number generator uint32_t xorshift32(uint32_t* seed); -// Distribution & sampling functions +// Basic distribution sampling functions float rand_0_to_1(uint32_t* seed); float rand_float(float max, uint32_t* seed); float unit_normal(uint32_t* seed); + +// Composite distribution sampling functions float random_uniform(float from, float to, uint32_t* seed); float random_normal(float mean, float sigma, uint32_t* seed); float random_lognormal(float logmean, float logsigma, uint32_t* seed); @@ -46,12 +32,28 @@ struct box { char* error_msg; }; +// 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) + // Inverse cdf struct box inverse_cdf_float(float cdf(float), float p); struct box inverse_cdf_box(struct box cdf_box(float), float p); // Samplers from cdf -struct box sampler_box_cdf(struct box cdf(float), uint32_t* seed); -struct box sampler_float_cdf(float cdf(float), uint32_t* seed); +struct box sampler_cdf_float(float cdf(float), uint32_t* seed); +struct box sampler_cdf_box(struct box cdf(float), uint32_t* seed); #endif