diff --git a/examples/01_one_sample/example b/examples/01_one_sample/example index 0be17e7..57b6267 100755 Binary files a/examples/01_one_sample/example and b/examples/01_one_sample/example differ diff --git a/examples/01_one_sample/makefile b/examples/01_one_sample/makefile index 302a149..963cdac 100644 --- a/examples/01_one_sample/makefile +++ b/examples/01_one_sample/makefile @@ -9,7 +9,7 @@ CC=gcc # CC=tcc # <= faster compilation # Main file -SRC=example.c +SRC=example.c ../../squiggle.c OUTPUT=example ## Dependencies diff --git a/examples/02_many_samples/example b/examples/02_many_samples/example index 02502b3..1f69607 100755 Binary files a/examples/02_many_samples/example and b/examples/02_many_samples/example differ diff --git a/examples/02_many_samples/makefile b/examples/02_many_samples/makefile index 302a149..963cdac 100644 --- a/examples/02_many_samples/makefile +++ b/examples/02_many_samples/makefile @@ -9,7 +9,7 @@ CC=gcc # CC=tcc # <= faster compilation # Main file -SRC=example.c +SRC=example.c ../../squiggle.c OUTPUT=example ## Dependencies diff --git a/examples/03_gcc_nested_function/example b/examples/03_gcc_nested_function/example index 1935e2d..b912c36 100755 Binary files a/examples/03_gcc_nested_function/example and b/examples/03_gcc_nested_function/example differ diff --git a/examples/03_gcc_nested_function/makefile b/examples/03_gcc_nested_function/makefile index f02429c..5fe6a84 100644 --- a/examples/03_gcc_nested_function/makefile +++ b/examples/03_gcc_nested_function/makefile @@ -9,7 +9,7 @@ CC=gcc # required for nested functions # CC=tcc # <= faster compilation # Main file -SRC=example.c +SRC=example.c ../../squiggle.c OUTPUT=example ## Dependencies diff --git a/squiggle.c b/squiggle.c new file mode 100644 index 0000000..0ca98e2 --- /dev/null +++ b/squiggle.c @@ -0,0 +1,113 @@ +#include +#include +#include + +// PI constant +const float PI = M_PI;// 3.14159265358979323846; + +// Pseudo Random number generator + +uint32_t xorshift32 +(uint32_t* seed) +{ + // Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" + // See + // https://en.wikipedia.org/wiki/Xorshift + // Also some drama: , + + uint32_t x = *seed; + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + return *seed = x; +} + +// Distribution & sampling functions + +float rand_0_to_1(uint32_t* seed){ + return ((float) xorshift32(seed)) / ((float) UINT32_MAX); +} + +float rand_float(float max, uint32_t* seed) +{ + return rand_0_to_1(seed) * max; +} + +float ur_normal(uint32_t* seed) +{ + float u1 = rand_0_to_1(seed); + float u2 = rand_0_to_1(seed); + float z = sqrtf(-2.0 * log(u1)) * sin(2 * PI * u2); + return z; +} + +float random_uniform(float from, float to, uint32_t* seed) +{ + return rand_0_to_1(seed) * (to - from) + from; +} + +float random_normal(float mean, float sigma, uint32_t* seed) +{ + return (mean + sigma * ur_normal(seed)); +} + +float random_lognormal(float logmean, float logsigma, uint32_t* seed) +{ + return expf(random_normal(logmean, logsigma, seed)); +} + +float random_to(float low, float high, uint32_t* seed) +{ + const float NORMAL95CONFIDENCE = 1.6448536269514722; + float loglow = logf(low); + float loghigh = logf(high); + float logmean = (loglow + loghigh) / 2; + float logsigma = (loghigh - loglow) / (2.0 * NORMAL95CONFIDENCE); + return random_lognormal(logmean, logsigma, seed); +} + +// Array helpers +float array_sum(float* array, int length) +{ + float output = 0.0; + for (int i = 0; i < length; i++) { + output += array[i]; + } + return output; +} + +void array_cumsum(float* array_to_sum, float* array_cumsummed, int length) +{ + array_cumsummed[0] = array_to_sum[0]; + for (int i = 1; i < length; i++) { + array_cumsummed[i] = array_cumsummed[i - 1] + array_to_sum[i]; + } +} + +// Mixture function +float mixture(float (*samplers[])(uint32_t*), float* weights, int n_dists, uint32_t* seed) +{ + // You can see a simpler version of this function in the git history + // or in C-02-better-algorithm-one-thread/ + float sum_weights = array_sum(weights, n_dists); + float* cumsummed_normalized_weights = (float*) malloc(n_dists * sizeof(float)); + cumsummed_normalized_weights[0] = weights[0]/sum_weights; + for (int i = 1; i < n_dists; i++) { + cumsummed_normalized_weights[i] = cumsummed_normalized_weights[i - 1] + weights[i]/sum_weights; + } + + float result; + int result_set_flag = 0; + float p = random_uniform(0, 1, seed); + for (int k = 0; k < n_dists; k++) { + if (p < cumsummed_normalized_weights[k]) { + result = samplers[k](seed); + result_set_flag = 1; + break; + } + } + if(result_set_flag == 0) result = samplers[n_dists-1](seed); + + free(cumsummed_normalized_weights); + return result; +} diff --git a/squiggle.h b/squiggle.h index d887b21..96e70c1 100644 --- a/squiggle.h +++ b/squiggle.h @@ -1,112 +1,26 @@ -#include -#include -#include +#ifndef SQUIGGLEC +#define SQUIGGLEC -const float PI = 3.14159265358979323846; +// uint32_t header +#include // Pseudo Random number generator - -uint32_t xorshift32 -(uint32_t* seed) -{ - // Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" - // See - // https://en.wikipedia.org/wiki/Xorshift - // Also some drama: , - - uint32_t x = *seed; - x ^= x << 13; - x ^= x >> 17; - x ^= x << 5; - return *seed = x; -} +uint32_t xorshift32(uint32_t* seed); // Distribution & sampling functions - -float rand_0_to_1(uint32_t* seed){ - return ((float) xorshift32(seed)) / ((float) UINT32_MAX); -} - -float rand_float(float max, uint32_t* seed) -{ - return rand_0_to_1(seed) * max; -} - -float ur_normal(uint32_t* seed) -{ - float u1 = rand_0_to_1(seed); - float u2 = rand_0_to_1(seed); - float z = sqrtf(-2.0 * log(u1)) * sin(2 * PI * u2); - return z; -} - -float random_uniform(float from, float to, uint32_t* seed) -{ - return rand_0_to_1(seed) * (to - from) + from; -} - -float random_normal(float mean, float sigma, uint32_t* seed) -{ - return (mean + sigma * ur_normal(seed)); -} - -float random_lognormal(float logmean, float logsigma, uint32_t* seed) -{ - return expf(random_normal(logmean, logsigma, seed)); -} - -float random_to(float low, float high, uint32_t* seed) -{ - const float NORMAL95CONFIDENCE = 1.6448536269514722; - float loglow = logf(low); - float loghigh = logf(high); - float logmean = (loglow + loghigh) / 2; - float logsigma = (loghigh - loglow) / (2.0 * NORMAL95CONFIDENCE); - return random_lognormal(logmean, logsigma, seed); -} +float rand_0_to_1(uint32_t* seed); +float rand_float(float max, uint32_t* seed); +float ur_normal(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_lognormal(float logmean, float logsigma, uint32_t* seed); +float random_to(float low, float high, uint32_t* seed); // Array helpers -float array_sum(float* array, int length) -{ - float output = 0.0; - for (int i = 0; i < length; i++) { - output += array[i]; - } - return output; -} - -void array_cumsum(float* array_to_sum, float* array_cumsummed, int length) -{ - array_cumsummed[0] = array_to_sum[0]; - for (int i = 1; i < length; i++) { - array_cumsummed[i] = array_cumsummed[i - 1] + array_to_sum[i]; - } -} +float array_sum(float* array, int length); +void array_cumsum(float* array_to_sum, float* array_cumsummed, int length); // Mixture function -float mixture(float (*samplers[])(uint32_t*), float* weights, int n_dists, uint32_t* seed) -{ - // You can see a simpler version of this function in the git history - // or in C-02-better-algorithm-one-thread/ - float sum_weights = array_sum(weights, n_dists); - float* cumsummed_normalized_weights = (float*) malloc(n_dists * sizeof(float)); - cumsummed_normalized_weights[0] = weights[0]/sum_weights; - for (int i = 1; i < n_dists; i++) { - cumsummed_normalized_weights[i] = cumsummed_normalized_weights[i - 1] + weights[i]/sum_weights; - } +float mixture(float (*samplers[])(uint32_t*), float* weights, int n_dists, uint32_t* seed); - float result; - int result_set_flag = 0; - float p = random_uniform(0, 1, seed); - for (int k = 0; k < n_dists; k++) { - if (p < cumsummed_normalized_weights[k]) { - result = samplers[k](seed); - result_set_flag = 1; - break; - } - } - if(result_set_flag == 0) result = samplers[n_dists-1](seed); - - free(cumsummed_normalized_weights); - return result; -} +#endif