rename sampler functions, elaborate on README, etc.
This commit is contained in:
parent
ea80c930e6
commit
11e965be4f
25
README.md
25
README.md
|
@ -1,15 +1,30 @@
|
||||||
# Squiggle.c
|
# Squiggle.c
|
||||||
|
|
||||||
|
A self-contained C99 library that provides a subset of [Squiggle](https://www.squiggle-language.com/)'s functionality in C.
|
||||||
|
|
||||||
## Why C?
|
## Why C?
|
||||||
|
|
||||||
- Because it is fast
|
- 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 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
|
## To do list
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -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);
|
printf("\nGetting some samples from %s:\n", cdf_name);
|
||||||
clock_t begin = clock();
|
clock_t begin = clock();
|
||||||
for (int i = 0; i < NUM_SAMPLES; i++) {
|
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) {
|
if (sample.empty) {
|
||||||
printf("Error in sampler function for %s", cdf_name);
|
printf("Error in sampler function for %s", cdf_name);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -19,7 +19,7 @@ DEPENDENCIES=$(MATH)
|
||||||
|
|
||||||
## Flags
|
## Flags
|
||||||
DEBUG= #'-g'
|
DEBUG= #'-g'
|
||||||
STANDARD=-std=gnu99 ## allows for nested functions.
|
STANDARD=-std=c99 ## gnu99 allows for nested functions.
|
||||||
EXTENSIONS= #-fnested-functions
|
EXTENSIONS= #-fnested-functions
|
||||||
WARNINGS=-Wall
|
WARNINGS=-Wall
|
||||||
OPTIMIZED=-O3#-Ofast
|
OPTIMIZED=-O3#-Ofast
|
||||||
|
|
Binary file not shown.
|
@ -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);
|
printf("\nGetting some samples from %s:\n", cdf_name);
|
||||||
clock_t begin = clock();
|
clock_t begin = clock();
|
||||||
for (int i = 0; i < NUM_SAMPLES; i++) {
|
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) {
|
if (sample.empty) {
|
||||||
printf("Error in sampler function for %s", cdf_name);
|
printf("Error in sampler function for %s", cdf_name);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -19,7 +19,7 @@ DEPENDENCIES=$(MATH)
|
||||||
|
|
||||||
## Flags
|
## Flags
|
||||||
DEBUG= #'-g'
|
DEBUG= #'-g'
|
||||||
STANDARD=-std=gnu99 ## allows for nested functions.
|
STANDARD=-std=c99 ## gnu99 allows for nested functions.
|
||||||
EXTENSIONS= #-fnested-functions
|
EXTENSIONS= #-fnested-functions
|
||||||
WARNINGS=-Wall
|
WARNINGS=-Wall
|
||||||
OPTIMIZED=-O3#-Ofast
|
OPTIMIZED=-O3#-Ofast
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
// PI constant
|
// PI constant
|
||||||
const float PI = M_PI; // 3.14159265358979323846;
|
const float PI = 3.14159265358979323846; // M_PI in gcc gnu99
|
||||||
|
|
||||||
// Pseudo Random number generator
|
// Pseudo Random number generator
|
||||||
|
|
||||||
|
|
40
squiggle.h
40
squiggle.h
|
@ -4,29 +4,15 @@
|
||||||
// uint32_t header
|
// uint32_t header
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
// 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
|
// Pseudo Random number generator
|
||||||
uint32_t xorshift32(uint32_t* seed);
|
uint32_t xorshift32(uint32_t* seed);
|
||||||
|
|
||||||
// Distribution & sampling functions
|
// Basic distribution sampling functions
|
||||||
float rand_0_to_1(uint32_t* seed);
|
float rand_0_to_1(uint32_t* seed);
|
||||||
float rand_float(float max, uint32_t* seed);
|
float rand_float(float max, uint32_t* seed);
|
||||||
float unit_normal(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_uniform(float from, float to, uint32_t* seed);
|
||||||
float random_normal(float mean, float sigma, uint32_t* seed);
|
float random_normal(float mean, float sigma, uint32_t* seed);
|
||||||
float random_lognormal(float logmean, float logsigma, uint32_t* seed);
|
float random_lognormal(float logmean, float logsigma, uint32_t* seed);
|
||||||
|
@ -46,12 +32,28 @@ struct box {
|
||||||
char* error_msg;
|
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
|
// Inverse cdf
|
||||||
struct box inverse_cdf_float(float cdf(float), float p);
|
struct box inverse_cdf_float(float cdf(float), float p);
|
||||||
struct box inverse_cdf_box(struct box cdf_box(float), float p);
|
struct box inverse_cdf_box(struct box cdf_box(float), float p);
|
||||||
|
|
||||||
// Samplers from cdf
|
// Samplers from cdf
|
||||||
struct box sampler_box_cdf(struct box cdf(float), uint32_t* seed);
|
struct box sampler_cdf_float(float cdf(float), uint32_t* seed);
|
||||||
struct box sampler_float_cdf(float cdf(float), uint32_t* seed);
|
struct box sampler_cdf_box(struct box cdf(float), uint32_t* seed);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user