forked from personal/squiggle.c
		
	move to xorshift64. Better precision.
This commit is contained in:
		
							parent
							
								
									11286211f7
								
							
						
					
					
						commit
						9e1d4ee6d4
					
				|  | @ -128,7 +128,7 @@ In squiggle.c, this ambiguity doesn't exist, at the cost of much greater overhea | |||
| 
 | ||||
| int main(){ | ||||
|     // set randomness seed | ||||
|     uint32_t* seed = malloc(sizeof(uint32_t)); | ||||
|     uint64_t* seed = malloc(sizeof(uint64_t)); | ||||
|     *seed = 1000; // xorshift can't start with a seed of 0 | ||||
| 
 | ||||
|     float a = sample_to(1, 10, seed); | ||||
|  | @ -153,7 +153,7 @@ vs | |||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| float draw_xyz(uint32_t* seed){ | ||||
| float draw_xyz(uint64_t* seed){ | ||||
|     // function could also be placed inside main with gcc nested functions extension. | ||||
|     return sample_to(1, 20, seed); | ||||
| } | ||||
|  | @ -161,7 +161,7 @@ float draw_xyz(uint32_t* seed){ | |||
| 
 | ||||
| int main(){ | ||||
|     // set randomness seed | ||||
|     uint32_t* seed = malloc(sizeof(uint32_t)); | ||||
|     uint64_t* seed = malloc(sizeof(uint64_t)); | ||||
|     *seed = 1000; // xorshift can't start with a seed of 0 | ||||
| 
 | ||||
|     float a = draw_xyz(seed); | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							|  | @ -4,29 +4,29 @@ | |||
| #include <stdio.h> | ||||
| 
 | ||||
| // Estimate functions
 | ||||
| float sample_0(uint32_t* seed) | ||||
| float sample_0(uint64_t* seed) | ||||
| { | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| float sample_1(uint32_t* seed) | ||||
| float sample_1(uint64_t* seed) | ||||
| { | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| float sample_few(uint32_t* seed) | ||||
| float sample_few(uint64_t* seed) | ||||
| { | ||||
|     return sample_to(1, 3, seed); | ||||
| } | ||||
| 
 | ||||
| float sample_many(uint32_t* seed) | ||||
| float sample_many(uint64_t* seed) | ||||
| { | ||||
|     return sample_to(2, 10, seed); | ||||
| } | ||||
| 
 | ||||
| int main(){ | ||||
|     // set randomness seed
 | ||||
| 		uint32_t* seed = malloc(sizeof(uint32_t)); | ||||
| 		uint64_t* seed = malloc(sizeof(uint64_t)); | ||||
| 		*seed = 1000; // xorshift can't start with 0
 | ||||
| 
 | ||||
|     float p_a = 0.8; | ||||
|  | @ -35,7 +35,7 @@ int main(){ | |||
| 
 | ||||
|     int n_dists = 4; | ||||
|     float weights[] = { 1 - p_c, p_c / 2, p_c / 4, p_c / 4 }; | ||||
|     float (*samplers[])(uint32_t*) = { sample_0, sample_1, sample_few, sample_many }; | ||||
|     float (*samplers[])(uint64_t*) = { sample_0, sample_1, sample_few, sample_many }; | ||||
| 
 | ||||
|     float result_one = sample_mixture(samplers, weights, n_dists, seed); | ||||
| 		printf("result_one: %f\n", result_one); | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							|  | @ -4,29 +4,29 @@ | |||
| #include "../../squiggle.h" | ||||
| 
 | ||||
| // Estimate functions
 | ||||
| float sample_0(uint32_t* seed) | ||||
| float sample_0(uint64_t* seed) | ||||
| { | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| float sample_1(uint32_t* seed) | ||||
| float sample_1(uint64_t* seed) | ||||
| { | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| float sample_few(uint32_t* seed) | ||||
| float sample_few(uint64_t* seed) | ||||
| { | ||||
|     return sample_to(1, 3, seed); | ||||
| } | ||||
| 
 | ||||
| float sample_many(uint32_t* seed) | ||||
| float sample_many(uint64_t* seed) | ||||
| { | ||||
|     return sample_to(2, 10, seed); | ||||
| } | ||||
| 
 | ||||
| int main(){ | ||||
|     // set randomness seed
 | ||||
| 		uint32_t* seed = malloc(sizeof(uint32_t)); | ||||
| 		uint64_t* seed = malloc(sizeof(uint64_t)); | ||||
| 		*seed = 1000; // xorshift can't start with 0
 | ||||
| 
 | ||||
|     float p_a = 0.8; | ||||
|  | @ -35,7 +35,7 @@ int main(){ | |||
| 
 | ||||
|     int n_dists = 4; | ||||
|     float weights[] = { 1 - p_c, p_c / 2, p_c / 4, p_c / 4 }; | ||||
|     float (*samplers[])(uint32_t*) = { sample_0, sample_1, sample_few, sample_many }; | ||||
|     float (*samplers[])(uint64_t*) = { sample_0, sample_1, sample_few, sample_many }; | ||||
| 
 | ||||
| 		int n_samples = 1000000; | ||||
| 		float* result_many = (float *) malloc(n_samples * sizeof(float)); | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							|  | @ -5,7 +5,7 @@ | |||
| 
 | ||||
| int main(){ | ||||
|     // set randomness seed
 | ||||
| 		uint32_t* seed = malloc(sizeof(uint32_t)); | ||||
| 		uint64_t* seed = malloc(sizeof(uint64_t)); | ||||
| 		*seed = 1000; // xorshift can't start with 0
 | ||||
| 
 | ||||
|     float p_a = 0.8; | ||||
|  | @ -14,12 +14,12 @@ int main(){ | |||
| 
 | ||||
|     int n_dists = 4; | ||||
| 		 | ||||
| 		float sample_0(uint32_t* seed){ return 0; } | ||||
| 		float sample_1(uint32_t* seed) { return 1; } | ||||
| 		float sample_few(uint32_t* seed){ return sample_to(1, 3, seed); } | ||||
| 		float sample_many(uint32_t* seed){ return sample_to(2, 10, seed); }  | ||||
| 		float sample_0(uint64_t* seed){ return 0; } | ||||
| 		float sample_1(uint64_t* seed) { return 1; } | ||||
| 		float sample_few(uint64_t* seed){ return sample_to(1, 3, seed); } | ||||
| 		float sample_many(uint64_t* seed){ return sample_to(2, 10, seed); }  | ||||
| 		 | ||||
|     float (*samplers[])(uint32_t*) = { sample_0, sample_1, sample_few, sample_many }; | ||||
|     float (*samplers[])(uint64_t*) = { sample_0, sample_1, sample_few, sample_many }; | ||||
| 		float weights[] = { 1 - p_c, p_c / 2, p_c / 4, p_c / 4 }; | ||||
| 
 | ||||
| 		int n_samples = 1000000; | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							|  | @ -49,7 +49,7 @@ void test_inverse_cdf_float(char* cdf_name, float cdf_float(float)) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void test_and_time_sampler_float(char* cdf_name, float cdf_float(float), uint32_t* seed) | ||||
| void test_and_time_sampler_float(char* cdf_name, float cdf_float(float), uint64_t* seed) | ||||
| { | ||||
|     printf("\nGetting some samples from %s:\n", cdf_name); | ||||
|     clock_t begin = clock(); | ||||
|  | @ -75,7 +75,7 @@ int main() | |||
| 
 | ||||
|     // Testing samplers
 | ||||
|     // set randomness seed
 | ||||
|     uint32_t* seed = malloc(sizeof(uint32_t)); | ||||
|     uint64_t* seed = malloc(sizeof(uint64_t)); | ||||
|     *seed = 1000; // xorshift can't start with 0
 | ||||
| 
 | ||||
|     // Test float sampler
 | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							|  | @ -131,7 +131,7 @@ void test_inverse_cdf_box(char* cdf_name, struct box cdf_box(float)) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void test_and_time_sampler_box(char* cdf_name, struct box cdf_box(float), uint32_t* seed) | ||||
| void test_and_time_sampler_box(char* cdf_name, struct box cdf_box(float), uint64_t* seed) | ||||
| { | ||||
|     printf("\nGetting some samples from %s:\n", cdf_name); | ||||
|     clock_t begin = clock(); | ||||
|  | @ -154,7 +154,7 @@ int main() | |||
|     test_inverse_cdf_box("cdf_beta", cdf_beta); | ||||
| 
 | ||||
|     // Test box sampler
 | ||||
|     uint32_t* seed = malloc(sizeof(uint32_t)); | ||||
|     uint64_t* seed = malloc(sizeof(uint64_t)); | ||||
|     *seed = 1000; // xorshift can't start with 0
 | ||||
|     test_and_time_sampler_box("cdf_beta", cdf_beta, seed); | ||||
|     // Ok, this is slower than python!!
 | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							|  | @ -8,7 +8,7 @@ | |||
| int main() | ||||
| { | ||||
|     // set randomness seed
 | ||||
|     uint32_t* seed = malloc(sizeof(uint32_t)); | ||||
|     uint64_t* seed = malloc(sizeof(uint64_t)); | ||||
|     *seed = 1000; // xorshift can't start with 0
 | ||||
| 
 | ||||
|     int n =  1000 * 1000; | ||||
|  |  | |||
							
								
								
									
										34
									
								
								squiggle.c
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								squiggle.c
									
									
									
									
									
								
							|  | @ -14,14 +14,14 @@ | |||
| const float PI = 3.14159265358979323846; // M_PI in gcc gnu99
 | ||||
| 
 | ||||
| // Pseudo Random number generator
 | ||||
| uint32_t xorshift32(uint32_t* seed) | ||||
| uint64_t xorshift32(uint32_t* seed) | ||||
| { | ||||
|     // Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs"
 | ||||
|     // See <https://stackoverflow.com/questions/53886131/how-does-xorshift32-works>
 | ||||
|     // See <https://stackoverflow.com/questions/53886131/how-does-xorshift64-works>
 | ||||
|     // https://en.wikipedia.org/wiki/Xorshift
 | ||||
|     // Also some drama: <https://www.pcg-random.org/posts/on-vignas-pcg-critique.html>, <https://prng.di.unimi.it/>
 | ||||
| 
 | ||||
|     uint32_t x = *seed; | ||||
|     uint64_t x = *seed; | ||||
|     x ^= x << 13; | ||||
|     x ^= x >> 17; | ||||
|     x ^= x << 5; | ||||
|  | @ -31,7 +31,7 @@ uint32_t xorshift32(uint32_t* seed) | |||
| uint64_t xorshift64(uint64_t* seed) | ||||
| { | ||||
|     // Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs"
 | ||||
|     // See <https://stackoverflow.com/questions/53886131/how-does-xorshift32-works>
 | ||||
|     // See <https://stackoverflow.com/questions/53886131/how-does-xorshift64-works>
 | ||||
|     // https://en.wikipedia.org/wiki/Xorshift
 | ||||
|     // Also some drama: <https://www.pcg-random.org/posts/on-vignas-pcg-critique.html>, <https://prng.di.unimi.it/>
 | ||||
| 
 | ||||
|  | @ -44,13 +44,13 @@ uint64_t xorshift64(uint64_t* seed) | |||
| 
 | ||||
| // Distribution & sampling functions
 | ||||
| // Unit distributions
 | ||||
| float sample_unit_uniform(uint32_t* seed) | ||||
| float sample_unit_uniform(uint64_t* seed) | ||||
| { | ||||
|     // samples uniform from [0,1] interval.
 | ||||
|     return ((float)xorshift32(seed)) / ((float)UINT32_MAX); | ||||
|     return ((float)xorshift64(seed)) / ((float)UINT64_MAX); | ||||
| } | ||||
| 
 | ||||
| float sample_unit_normal(uint32_t* seed) | ||||
| float sample_unit_normal(uint64_t* seed) | ||||
| { | ||||
|     // See: <https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform>
 | ||||
|     float u1 = sample_unit_uniform(seed); | ||||
|  | @ -60,22 +60,22 @@ float sample_unit_normal(uint32_t* seed) | |||
| } | ||||
| 
 | ||||
| // Composite distributions
 | ||||
| float sample_uniform(float start, float end, uint32_t* seed) | ||||
| float sample_uniform(float start, float end, uint64_t* seed) | ||||
| { | ||||
|     return sample_unit_uniform(seed) * (end - start) + start; | ||||
| } | ||||
| 
 | ||||
| float sample_normal(float mean, float sigma, uint32_t* seed) | ||||
| float sample_normal(float mean, float sigma, uint64_t* seed) | ||||
| { | ||||
|     return (mean + sigma * sample_unit_normal(seed)); | ||||
| } | ||||
| 
 | ||||
| float sample_lognormal(float logmean, float logsigma, uint32_t* seed) | ||||
| float sample_lognormal(float logmean, float logsigma, uint64_t* seed) | ||||
| { | ||||
|     return expf(sample_normal(logmean, logsigma, seed)); | ||||
| } | ||||
| 
 | ||||
| float sample_to(float low, float high, uint32_t* seed) | ||||
| float sample_to(float low, float high, uint64_t* seed) | ||||
| { | ||||
|     // Given a (positive) 90% confidence interval,
 | ||||
|     // returns a sample from a lognormal
 | ||||
|  | @ -88,7 +88,7 @@ float sample_to(float low, float high, uint32_t* seed) | |||
|     return sample_lognormal(logmean, logsigma, seed); | ||||
| } | ||||
| 
 | ||||
| float sample_gamma(float alpha, uint32_t* seed) | ||||
| float sample_gamma(float alpha, uint64_t* seed) | ||||
| { | ||||
| 
 | ||||
|     // A Simple Method for Generating Gamma Variables, Marsaglia and Wan Tsang, 2001
 | ||||
|  | @ -125,7 +125,7 @@ float sample_gamma(float alpha, uint32_t* seed) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| float sample_beta(float a, float b, uint32_t* seed) | ||||
| float sample_beta(float a, float b, uint64_t* seed) | ||||
| { | ||||
|     float gamma_a = sample_gamma(a, seed); | ||||
|     float gamma_b = sample_gamma(b, seed); | ||||
|  | @ -168,7 +168,7 @@ float array_std(float* array, int length) | |||
| } | ||||
| 
 | ||||
| // Mixture function
 | ||||
| float sample_mixture(float (*samplers[])(uint32_t*), float* weights, int n_dists, uint32_t* seed) | ||||
| float sample_mixture(float (*samplers[])(uint64_t*), float* weights, int n_dists, uint64_t* seed) | ||||
| { | ||||
|     // You can see a simpler version of this function in the git history
 | ||||
|     // or in C-02-better-algorithm-one-thread/
 | ||||
|  | @ -364,13 +364,13 @@ struct box inverse_cdf_box(struct box cdf_box(float), float p) | |||
| } | ||||
| 
 | ||||
| // Sampler based on inverse cdf and randomness function
 | ||||
| struct box sampler_cdf_box(struct box cdf(float), uint32_t* seed) | ||||
| struct box sampler_cdf_box(struct box cdf(float), uint64_t* seed) | ||||
| { | ||||
|     float p = sample_unit_uniform(seed); | ||||
|     struct box result = inverse_cdf_box(cdf, p); | ||||
|     return result; | ||||
| } | ||||
| struct box sampler_cdf_float(float cdf(float), uint32_t* seed) | ||||
| struct box sampler_cdf_float(float cdf(float), uint64_t* seed) | ||||
| { | ||||
|     float p = sample_unit_uniform(seed); | ||||
|     struct box result = inverse_cdf_float(cdf, p); | ||||
|  | @ -378,7 +378,7 @@ struct box sampler_cdf_float(float cdf(float), uint32_t* seed) | |||
| } | ||||
| 
 | ||||
| /* Could also define other variations, e.g.,
 | ||||
| float sampler_danger(struct box cdf(float), uint32_t* seed) | ||||
| float sampler_danger(struct box cdf(float), uint64_t* seed) | ||||
| { | ||||
|     float p = sample_unit_uniform(seed); | ||||
|     struct box result = inverse_cdf_box(cdf, p); | ||||
|  |  | |||
							
								
								
									
										26
									
								
								squiggle.h
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								squiggle.h
									
									
									
									
									
								
							|  | @ -1,24 +1,24 @@ | |||
| #ifndef SQUIGGLEC | ||||
| #define SQUIGGLEC | ||||
| 
 | ||||
| // uint32_t header
 | ||||
| // uint64_t header
 | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| // Pseudo Random number generator
 | ||||
| uint32_t xorshift32(uint32_t* seed); | ||||
| uint64_t xorshift64(uint64_t* seed); | ||||
| 
 | ||||
| // Basic distribution sampling functions
 | ||||
| float sample_unit_uniform(uint32_t* seed); | ||||
| float sample_unit_normal(uint32_t* seed); | ||||
| float sample_unit_uniform(uint64_t* seed); | ||||
| float sample_unit_normal(uint64_t* seed); | ||||
| 
 | ||||
| // Composite distribution sampling functions
 | ||||
| float sample_uniform(float start, float end, uint32_t* seed); | ||||
| float sample_normal(float mean, float sigma, uint32_t* seed); | ||||
| float sample_lognormal(float logmean, float logsigma, uint32_t* seed); | ||||
| float sample_to(float low, float high, uint32_t* seed); | ||||
| float sample_uniform(float start, float end, uint64_t* seed); | ||||
| float sample_normal(float mean, float sigma, uint64_t* seed); | ||||
| float sample_lognormal(float logmean, float logsigma, uint64_t* seed); | ||||
| float sample_to(float low, float high, uint64_t* seed); | ||||
| 
 | ||||
| float sample_gamma(float alpha, uint32_t* seed); | ||||
| float sample_beta(float a, float b, uint32_t* seed); | ||||
| float sample_gamma(float alpha, uint64_t* seed); | ||||
| float sample_beta(float a, float b, uint64_t* seed); | ||||
| 
 | ||||
| // Array helpers
 | ||||
| float array_sum(float* array, int length); | ||||
|  | @ -27,7 +27,7 @@ float array_mean(float* array, int length); | |||
| float array_std(float* array, int length); | ||||
| 
 | ||||
| // Mixture function
 | ||||
| float sample_mixture(float (*samplers[])(uint32_t*), float* weights, int n_dists, uint32_t* seed); | ||||
| float sample_mixture(float (*samplers[])(uint64_t*), float* weights, int n_dists, uint64_t* seed); | ||||
| 
 | ||||
| // Box
 | ||||
| struct box { | ||||
|  | @ -47,7 +47,7 @@ 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_cdf_float(float cdf(float), uint32_t* seed); | ||||
| struct box sampler_cdf_box(struct box cdf(float), uint32_t* seed); | ||||
| struct box sampler_cdf_float(float cdf(float), uint64_t* seed); | ||||
| struct box sampler_cdf_box(struct box cdf(float), uint64_t* seed); | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -4,9 +4,9 @@ | |||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| #define N 10 * 1000 * 1000 | ||||
| #define N  1000 * 1000 | ||||
| 
 | ||||
| void test_unit_uniform(uint32_t* seed){ | ||||
| void test_unit_uniform(uint64_t* seed){ | ||||
| 	float* unit_uniform_array = malloc(sizeof(float) * N); | ||||
| 	 | ||||
| 	for(int i=0; i<N; i++){ | ||||
|  | @ -40,7 +40,7 @@ void test_unit_uniform(uint32_t* seed){ | |||
| 
 | ||||
| } | ||||
| 
 | ||||
| void test_uniform(float start, float end, uint32_t* seed){ | ||||
| void test_uniform(float start, float end, uint64_t* seed){ | ||||
| 	float* uniform_array = malloc(sizeof(float) * N); | ||||
| 	 | ||||
| 	for(int i=0; i<N; i++){ | ||||
|  | @ -76,7 +76,7 @@ void test_uniform(float start, float end, uint32_t* seed){ | |||
| 
 | ||||
| int main(){ | ||||
|     // set randomness seed
 | ||||
|     uint32_t* seed = malloc(sizeof(uint32_t)); | ||||
|     uint64_t* seed = malloc(sizeof(uint64_t)); | ||||
|     *seed = 1000; // xorshift can't start with a seed of 0
 | ||||
|     | ||||
| 		test_unit_uniform(seed); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user