From b6b54180019c5cc3cccadf89528f42dbe61c409b Mon Sep 17 00:00:00 2001 From: UhJdQRtAhN95rbscFCJtIA== Date: Sun, 3 Mar 2024 13:04:02 +0100 Subject: [PATCH] Initial folder refactor --- .../core/00_example_template/example | Bin .../core/00_example_template/example.c | 0 .../examples}/core/01_one_sample/example | Bin .../examples}/core/01_one_sample/example.c | 0 .../examples}/core/02_time_to_botec/example | Bin .../examples}/core/02_time_to_botec/example.c | 0 .../core/03_gcc_nested_function/example | Bin .../core/03_gcc_nested_function/example.c | 0 .../examples}/core/04_gamma_beta/example | Bin .../examples}/core/04_gamma_beta/example.c | 0 .../core/05_hundred_lognormals/example | Bin .../core/05_hundred_lognormals/example.c | 0 .../core/05_hundred_lognormals/run-sorted.sh | 0 .../core/06_dissolving_fermi_paradox/example | Bin .../06_dissolving_fermi_paradox/example.c | 0 .../06_dissolving_fermi_paradox/fermi.pdf | Bin .../core/06_dissolving_fermi_paradox/naive.c | 0 .../06_dissolving_fermi_paradox/scratchpad | Bin {examples => C/examples}/core/makefile | 0 .../more/00_example_template/example | Bin .../more/00_example_template/example.c | 0 .../examples}/more/02_ci_beta/example | Bin .../examples}/more/02_ci_beta/example.c | 0 .../more/03_ci_beta_parallel/example | Bin .../more/03_ci_beta_parallel/example.c | 0 .../examples}/more/04_nuclear_war/example | Bin .../examples}/more/04_nuclear_war/example.c | 0 .../more/04_nuclear_war/scratchpad/example | Bin .../more/04_nuclear_war/scratchpad/example.c | 0 .../more/04_nuclear_war/scratchpad/makefile | 0 .../examples}/more/05_burn_10kg_fat/example | Bin .../examples}/more/05_burn_10kg_fat/example.c | 0 .../more/06_nuclear_recovery/example | Bin .../more/06_nuclear_recovery/example.c | 0 .../examples}/more/07_algebra/example | Bin .../examples}/more/07_algebra/example.c | 0 .../more/08_algebra_and_conversion/example | Bin .../more/08_algebra_and_conversion/example.c | 0 .../more/09_ergonomic_algebra/example | Bin .../more/09_ergonomic_algebra/example.c | 0 .../more/10_twitter_thread_example/example | Bin .../more/10_twitter_thread_example/example.c | 0 .../11_billion_lognormals_paralell/example | Bin .../11_billion_lognormals_paralell/example.c | 0 .../more/12_time_to_botec_parallel/example | Bin .../more/12_time_to_botec_parallel/example.c | 0 .../examples}/more/13_parallelize_min/example | Bin .../more/13_parallelize_min/example.c | 0 .../more/14_check_confidence_interval/example | Bin .../14_check_confidence_interval/example.c | 0 .../15_time_to_botec_custom_mixture/example | Bin .../15_time_to_botec_custom_mixture/example.c | 0 {examples => C/examples}/more/makefile | 0 makefile => C/makefile | 0 squiggle.c => C/squiggle.c | 0 squiggle.h => C/squiggle.h | 0 squiggle_more.c => C/squiggle_more.c | 0 squiggle_more.h => C/squiggle_more.h | 0 {test => C/test}/makefile | 0 {test => C/test}/test | Bin {test => C/test}/test.c | 0 .../examples/core/00_example_template/example | Bin 0 -> 21656 bytes .../core/00_example_template/example.c | 14 + CUDA/examples/core/01_one_sample/example | Bin 0 -> 21928 bytes CUDA/examples/core/01_one_sample/example.c | 34 ++ CUDA/examples/core/02_time_to_botec/example | Bin 0 -> 22032 bytes CUDA/examples/core/02_time_to_botec/example.c | 38 ++ .../core/03_gcc_nested_function/example | Bin 0 -> 22096 bytes .../core/03_gcc_nested_function/example.c | 44 ++ CUDA/examples/core/04_gamma_beta/example | Bin 0 -> 21752 bytes CUDA/examples/core/04_gamma_beta/example.c | 29 ++ .../core/05_hundred_lognormals/example | Bin 0 -> 21704 bytes .../core/05_hundred_lognormals/example.c | 17 + .../core/05_hundred_lognormals/run-sorted.sh | 1 + .../core/06_dissolving_fermi_paradox/example | Bin 0 -> 21848 bytes .../06_dissolving_fermi_paradox/example.c | 99 ++++ .../06_dissolving_fermi_paradox/fermi.pdf | Bin 0 -> 255897 bytes .../core/06_dissolving_fermi_paradox/naive.c | 79 +++ .../06_dissolving_fermi_paradox/scratchpad | Bin 0 -> 26992 bytes CUDA/examples/core/makefile | 91 ++++ .../examples/more/00_example_template/example | Bin 0 -> 27360 bytes .../more/00_example_template/example.c | 19 + CUDA/examples/more/02_ci_beta/example | Bin 0 -> 27368 bytes CUDA/examples/more/02_ci_beta/example.c | 30 ++ .../examples/more/03_ci_beta_parallel/example | Bin 0 -> 27368 bytes .../more/03_ci_beta_parallel/example.c | 28 ++ CUDA/examples/more/04_nuclear_war/example | Bin 0 -> 27472 bytes CUDA/examples/more/04_nuclear_war/example.c | 63 +++ .../more/04_nuclear_war/scratchpad/example | Bin 0 -> 22271 bytes .../more/04_nuclear_war/scratchpad/example.c | 20 + .../more/04_nuclear_war/scratchpad/makefile | 53 ++ CUDA/examples/more/05_burn_10kg_fat/example | Bin 0 -> 27408 bytes CUDA/examples/more/05_burn_10kg_fat/example.c | 43 ++ .../examples/more/06_nuclear_recovery/example | Bin 0 -> 27696 bytes .../more/06_nuclear_recovery/example.c | 84 ++++ CUDA/examples/more/07_algebra/example | Bin 0 -> 27328 bytes CUDA/examples/more/07_algebra/example.c | 26 + .../more/08_algebra_and_conversion/example | Bin 0 -> 27328 bytes .../more/08_algebra_and_conversion/example.c | 33 ++ .../more/09_ergonomic_algebra/example | Bin 0 -> 27328 bytes .../more/09_ergonomic_algebra/example.c | 26 + .../more/10_twitter_thread_example/example | Bin 0 -> 27480 bytes .../more/10_twitter_thread_example/example.c | 49 ++ .../11_billion_lognormals_paralell/example | Bin 0 -> 27360 bytes .../11_billion_lognormals_paralell/example.c | 30 ++ .../more/12_time_to_botec_parallel/example | Bin 0 -> 27520 bytes .../more/12_time_to_botec_parallel/example.c | 31 ++ CUDA/examples/more/13_parallelize_min/example | Bin 0 -> 27424 bytes .../more/13_parallelize_min/example.c | 70 +++ .../more/14_check_confidence_interval/example | Bin 0 -> 27328 bytes .../14_check_confidence_interval/example.c | 22 + .../15_time_to_botec_custom_mixture/example | Bin 0 -> 27536 bytes .../15_time_to_botec_custom_mixture/example.c | 34 ++ CUDA/examples/more/makefile | 117 +++++ CUDA/makefile | 35 ++ CUDA/squiggle.c | 228 +++++++++ CUDA/squiggle.h | 37 ++ CUDA/squiggle_more.c | 459 ++++++++++++++++++ CUDA/squiggle_more.h | 42 ++ CUDA/test/makefile | 56 +++ CUDA/test/test | Bin 0 -> 26288 bytes CUDA/test/test.c | 328 +++++++++++++ 122 files changed, 2409 insertions(+) rename {examples => C/examples}/core/00_example_template/example (100%) rename {examples => C/examples}/core/00_example_template/example.c (100%) rename {examples => C/examples}/core/01_one_sample/example (100%) rename {examples => C/examples}/core/01_one_sample/example.c (100%) rename {examples => C/examples}/core/02_time_to_botec/example (100%) rename {examples => C/examples}/core/02_time_to_botec/example.c (100%) rename {examples => C/examples}/core/03_gcc_nested_function/example (100%) rename {examples => C/examples}/core/03_gcc_nested_function/example.c (100%) rename {examples => C/examples}/core/04_gamma_beta/example (100%) rename {examples => C/examples}/core/04_gamma_beta/example.c (100%) rename {examples => C/examples}/core/05_hundred_lognormals/example (100%) rename {examples => C/examples}/core/05_hundred_lognormals/example.c (100%) rename {examples => C/examples}/core/05_hundred_lognormals/run-sorted.sh (100%) rename {examples => C/examples}/core/06_dissolving_fermi_paradox/example (100%) rename {examples => C/examples}/core/06_dissolving_fermi_paradox/example.c (100%) rename {examples => C/examples}/core/06_dissolving_fermi_paradox/fermi.pdf (100%) rename {examples => C/examples}/core/06_dissolving_fermi_paradox/naive.c (100%) rename {examples => C/examples}/core/06_dissolving_fermi_paradox/scratchpad (100%) rename {examples => C/examples}/core/makefile (100%) rename {examples => C/examples}/more/00_example_template/example (100%) rename {examples => C/examples}/more/00_example_template/example.c (100%) rename {examples => C/examples}/more/02_ci_beta/example (100%) rename {examples => C/examples}/more/02_ci_beta/example.c (100%) rename {examples => C/examples}/more/03_ci_beta_parallel/example (100%) rename {examples => C/examples}/more/03_ci_beta_parallel/example.c (100%) rename {examples => C/examples}/more/04_nuclear_war/example (100%) rename {examples => C/examples}/more/04_nuclear_war/example.c (100%) rename {examples => C/examples}/more/04_nuclear_war/scratchpad/example (100%) rename {examples => C/examples}/more/04_nuclear_war/scratchpad/example.c (100%) rename {examples => C/examples}/more/04_nuclear_war/scratchpad/makefile (100%) rename {examples => C/examples}/more/05_burn_10kg_fat/example (100%) rename {examples => C/examples}/more/05_burn_10kg_fat/example.c (100%) rename {examples => C/examples}/more/06_nuclear_recovery/example (100%) rename {examples => C/examples}/more/06_nuclear_recovery/example.c (100%) rename {examples => C/examples}/more/07_algebra/example (100%) rename {examples => C/examples}/more/07_algebra/example.c (100%) rename {examples => C/examples}/more/08_algebra_and_conversion/example (100%) rename {examples => C/examples}/more/08_algebra_and_conversion/example.c (100%) rename {examples => C/examples}/more/09_ergonomic_algebra/example (100%) rename {examples => C/examples}/more/09_ergonomic_algebra/example.c (100%) rename {examples => C/examples}/more/10_twitter_thread_example/example (100%) rename {examples => C/examples}/more/10_twitter_thread_example/example.c (100%) rename {examples => C/examples}/more/11_billion_lognormals_paralell/example (100%) rename {examples => C/examples}/more/11_billion_lognormals_paralell/example.c (100%) rename {examples => C/examples}/more/12_time_to_botec_parallel/example (100%) rename {examples => C/examples}/more/12_time_to_botec_parallel/example.c (100%) rename {examples => C/examples}/more/13_parallelize_min/example (100%) rename {examples => C/examples}/more/13_parallelize_min/example.c (100%) rename {examples => C/examples}/more/14_check_confidence_interval/example (100%) rename {examples => C/examples}/more/14_check_confidence_interval/example.c (100%) rename {examples => C/examples}/more/15_time_to_botec_custom_mixture/example (100%) rename {examples => C/examples}/more/15_time_to_botec_custom_mixture/example.c (100%) rename {examples => C/examples}/more/makefile (100%) rename makefile => C/makefile (100%) rename squiggle.c => C/squiggle.c (100%) rename squiggle.h => C/squiggle.h (100%) rename squiggle_more.c => C/squiggle_more.c (100%) rename squiggle_more.h => C/squiggle_more.h (100%) rename {test => C/test}/makefile (100%) rename {test => C/test}/test (100%) rename {test => C/test}/test.c (100%) create mode 100755 CUDA/examples/core/00_example_template/example create mode 100644 CUDA/examples/core/00_example_template/example.c create mode 100755 CUDA/examples/core/01_one_sample/example create mode 100644 CUDA/examples/core/01_one_sample/example.c create mode 100755 CUDA/examples/core/02_time_to_botec/example create mode 100644 CUDA/examples/core/02_time_to_botec/example.c create mode 100755 CUDA/examples/core/03_gcc_nested_function/example create mode 100644 CUDA/examples/core/03_gcc_nested_function/example.c create mode 100755 CUDA/examples/core/04_gamma_beta/example create mode 100644 CUDA/examples/core/04_gamma_beta/example.c create mode 100755 CUDA/examples/core/05_hundred_lognormals/example create mode 100644 CUDA/examples/core/05_hundred_lognormals/example.c create mode 100644 CUDA/examples/core/05_hundred_lognormals/run-sorted.sh create mode 100755 CUDA/examples/core/06_dissolving_fermi_paradox/example create mode 100644 CUDA/examples/core/06_dissolving_fermi_paradox/example.c create mode 100644 CUDA/examples/core/06_dissolving_fermi_paradox/fermi.pdf create mode 100644 CUDA/examples/core/06_dissolving_fermi_paradox/naive.c create mode 100755 CUDA/examples/core/06_dissolving_fermi_paradox/scratchpad create mode 100644 CUDA/examples/core/makefile create mode 100755 CUDA/examples/more/00_example_template/example create mode 100644 CUDA/examples/more/00_example_template/example.c create mode 100755 CUDA/examples/more/02_ci_beta/example create mode 100644 CUDA/examples/more/02_ci_beta/example.c create mode 100755 CUDA/examples/more/03_ci_beta_parallel/example create mode 100644 CUDA/examples/more/03_ci_beta_parallel/example.c create mode 100755 CUDA/examples/more/04_nuclear_war/example create mode 100644 CUDA/examples/more/04_nuclear_war/example.c create mode 100755 CUDA/examples/more/04_nuclear_war/scratchpad/example create mode 100644 CUDA/examples/more/04_nuclear_war/scratchpad/example.c create mode 100644 CUDA/examples/more/04_nuclear_war/scratchpad/makefile create mode 100755 CUDA/examples/more/05_burn_10kg_fat/example create mode 100644 CUDA/examples/more/05_burn_10kg_fat/example.c create mode 100755 CUDA/examples/more/06_nuclear_recovery/example create mode 100644 CUDA/examples/more/06_nuclear_recovery/example.c create mode 100755 CUDA/examples/more/07_algebra/example create mode 100644 CUDA/examples/more/07_algebra/example.c create mode 100755 CUDA/examples/more/08_algebra_and_conversion/example create mode 100644 CUDA/examples/more/08_algebra_and_conversion/example.c create mode 100755 CUDA/examples/more/09_ergonomic_algebra/example create mode 100644 CUDA/examples/more/09_ergonomic_algebra/example.c create mode 100755 CUDA/examples/more/10_twitter_thread_example/example create mode 100644 CUDA/examples/more/10_twitter_thread_example/example.c create mode 100755 CUDA/examples/more/11_billion_lognormals_paralell/example create mode 100644 CUDA/examples/more/11_billion_lognormals_paralell/example.c create mode 100755 CUDA/examples/more/12_time_to_botec_parallel/example create mode 100644 CUDA/examples/more/12_time_to_botec_parallel/example.c create mode 100755 CUDA/examples/more/13_parallelize_min/example create mode 100644 CUDA/examples/more/13_parallelize_min/example.c create mode 100755 CUDA/examples/more/14_check_confidence_interval/example create mode 100644 CUDA/examples/more/14_check_confidence_interval/example.c create mode 100755 CUDA/examples/more/15_time_to_botec_custom_mixture/example create mode 100644 CUDA/examples/more/15_time_to_botec_custom_mixture/example.c create mode 100644 CUDA/examples/more/makefile create mode 100644 CUDA/makefile create mode 100644 CUDA/squiggle.c create mode 100644 CUDA/squiggle.h create mode 100644 CUDA/squiggle_more.c create mode 100644 CUDA/squiggle_more.h create mode 100644 CUDA/test/makefile create mode 100755 CUDA/test/test create mode 100644 CUDA/test/test.c diff --git a/examples/core/00_example_template/example b/C/examples/core/00_example_template/example similarity index 100% rename from examples/core/00_example_template/example rename to C/examples/core/00_example_template/example diff --git a/examples/core/00_example_template/example.c b/C/examples/core/00_example_template/example.c similarity index 100% rename from examples/core/00_example_template/example.c rename to C/examples/core/00_example_template/example.c diff --git a/examples/core/01_one_sample/example b/C/examples/core/01_one_sample/example similarity index 100% rename from examples/core/01_one_sample/example rename to C/examples/core/01_one_sample/example diff --git a/examples/core/01_one_sample/example.c b/C/examples/core/01_one_sample/example.c similarity index 100% rename from examples/core/01_one_sample/example.c rename to C/examples/core/01_one_sample/example.c diff --git a/examples/core/02_time_to_botec/example b/C/examples/core/02_time_to_botec/example similarity index 100% rename from examples/core/02_time_to_botec/example rename to C/examples/core/02_time_to_botec/example diff --git a/examples/core/02_time_to_botec/example.c b/C/examples/core/02_time_to_botec/example.c similarity index 100% rename from examples/core/02_time_to_botec/example.c rename to C/examples/core/02_time_to_botec/example.c diff --git a/examples/core/03_gcc_nested_function/example b/C/examples/core/03_gcc_nested_function/example similarity index 100% rename from examples/core/03_gcc_nested_function/example rename to C/examples/core/03_gcc_nested_function/example diff --git a/examples/core/03_gcc_nested_function/example.c b/C/examples/core/03_gcc_nested_function/example.c similarity index 100% rename from examples/core/03_gcc_nested_function/example.c rename to C/examples/core/03_gcc_nested_function/example.c diff --git a/examples/core/04_gamma_beta/example b/C/examples/core/04_gamma_beta/example similarity index 100% rename from examples/core/04_gamma_beta/example rename to C/examples/core/04_gamma_beta/example diff --git a/examples/core/04_gamma_beta/example.c b/C/examples/core/04_gamma_beta/example.c similarity index 100% rename from examples/core/04_gamma_beta/example.c rename to C/examples/core/04_gamma_beta/example.c diff --git a/examples/core/05_hundred_lognormals/example b/C/examples/core/05_hundred_lognormals/example similarity index 100% rename from examples/core/05_hundred_lognormals/example rename to C/examples/core/05_hundred_lognormals/example diff --git a/examples/core/05_hundred_lognormals/example.c b/C/examples/core/05_hundred_lognormals/example.c similarity index 100% rename from examples/core/05_hundred_lognormals/example.c rename to C/examples/core/05_hundred_lognormals/example.c diff --git a/examples/core/05_hundred_lognormals/run-sorted.sh b/C/examples/core/05_hundred_lognormals/run-sorted.sh similarity index 100% rename from examples/core/05_hundred_lognormals/run-sorted.sh rename to C/examples/core/05_hundred_lognormals/run-sorted.sh diff --git a/examples/core/06_dissolving_fermi_paradox/example b/C/examples/core/06_dissolving_fermi_paradox/example similarity index 100% rename from examples/core/06_dissolving_fermi_paradox/example rename to C/examples/core/06_dissolving_fermi_paradox/example diff --git a/examples/core/06_dissolving_fermi_paradox/example.c b/C/examples/core/06_dissolving_fermi_paradox/example.c similarity index 100% rename from examples/core/06_dissolving_fermi_paradox/example.c rename to C/examples/core/06_dissolving_fermi_paradox/example.c diff --git a/examples/core/06_dissolving_fermi_paradox/fermi.pdf b/C/examples/core/06_dissolving_fermi_paradox/fermi.pdf similarity index 100% rename from examples/core/06_dissolving_fermi_paradox/fermi.pdf rename to C/examples/core/06_dissolving_fermi_paradox/fermi.pdf diff --git a/examples/core/06_dissolving_fermi_paradox/naive.c b/C/examples/core/06_dissolving_fermi_paradox/naive.c similarity index 100% rename from examples/core/06_dissolving_fermi_paradox/naive.c rename to C/examples/core/06_dissolving_fermi_paradox/naive.c diff --git a/examples/core/06_dissolving_fermi_paradox/scratchpad b/C/examples/core/06_dissolving_fermi_paradox/scratchpad similarity index 100% rename from examples/core/06_dissolving_fermi_paradox/scratchpad rename to C/examples/core/06_dissolving_fermi_paradox/scratchpad diff --git a/examples/core/makefile b/C/examples/core/makefile similarity index 100% rename from examples/core/makefile rename to C/examples/core/makefile diff --git a/examples/more/00_example_template/example b/C/examples/more/00_example_template/example similarity index 100% rename from examples/more/00_example_template/example rename to C/examples/more/00_example_template/example diff --git a/examples/more/00_example_template/example.c b/C/examples/more/00_example_template/example.c similarity index 100% rename from examples/more/00_example_template/example.c rename to C/examples/more/00_example_template/example.c diff --git a/examples/more/02_ci_beta/example b/C/examples/more/02_ci_beta/example similarity index 100% rename from examples/more/02_ci_beta/example rename to C/examples/more/02_ci_beta/example diff --git a/examples/more/02_ci_beta/example.c b/C/examples/more/02_ci_beta/example.c similarity index 100% rename from examples/more/02_ci_beta/example.c rename to C/examples/more/02_ci_beta/example.c diff --git a/examples/more/03_ci_beta_parallel/example b/C/examples/more/03_ci_beta_parallel/example similarity index 100% rename from examples/more/03_ci_beta_parallel/example rename to C/examples/more/03_ci_beta_parallel/example diff --git a/examples/more/03_ci_beta_parallel/example.c b/C/examples/more/03_ci_beta_parallel/example.c similarity index 100% rename from examples/more/03_ci_beta_parallel/example.c rename to C/examples/more/03_ci_beta_parallel/example.c diff --git a/examples/more/04_nuclear_war/example b/C/examples/more/04_nuclear_war/example similarity index 100% rename from examples/more/04_nuclear_war/example rename to C/examples/more/04_nuclear_war/example diff --git a/examples/more/04_nuclear_war/example.c b/C/examples/more/04_nuclear_war/example.c similarity index 100% rename from examples/more/04_nuclear_war/example.c rename to C/examples/more/04_nuclear_war/example.c diff --git a/examples/more/04_nuclear_war/scratchpad/example b/C/examples/more/04_nuclear_war/scratchpad/example similarity index 100% rename from examples/more/04_nuclear_war/scratchpad/example rename to C/examples/more/04_nuclear_war/scratchpad/example diff --git a/examples/more/04_nuclear_war/scratchpad/example.c b/C/examples/more/04_nuclear_war/scratchpad/example.c similarity index 100% rename from examples/more/04_nuclear_war/scratchpad/example.c rename to C/examples/more/04_nuclear_war/scratchpad/example.c diff --git a/examples/more/04_nuclear_war/scratchpad/makefile b/C/examples/more/04_nuclear_war/scratchpad/makefile similarity index 100% rename from examples/more/04_nuclear_war/scratchpad/makefile rename to C/examples/more/04_nuclear_war/scratchpad/makefile diff --git a/examples/more/05_burn_10kg_fat/example b/C/examples/more/05_burn_10kg_fat/example similarity index 100% rename from examples/more/05_burn_10kg_fat/example rename to C/examples/more/05_burn_10kg_fat/example diff --git a/examples/more/05_burn_10kg_fat/example.c b/C/examples/more/05_burn_10kg_fat/example.c similarity index 100% rename from examples/more/05_burn_10kg_fat/example.c rename to C/examples/more/05_burn_10kg_fat/example.c diff --git a/examples/more/06_nuclear_recovery/example b/C/examples/more/06_nuclear_recovery/example similarity index 100% rename from examples/more/06_nuclear_recovery/example rename to C/examples/more/06_nuclear_recovery/example diff --git a/examples/more/06_nuclear_recovery/example.c b/C/examples/more/06_nuclear_recovery/example.c similarity index 100% rename from examples/more/06_nuclear_recovery/example.c rename to C/examples/more/06_nuclear_recovery/example.c diff --git a/examples/more/07_algebra/example b/C/examples/more/07_algebra/example similarity index 100% rename from examples/more/07_algebra/example rename to C/examples/more/07_algebra/example diff --git a/examples/more/07_algebra/example.c b/C/examples/more/07_algebra/example.c similarity index 100% rename from examples/more/07_algebra/example.c rename to C/examples/more/07_algebra/example.c diff --git a/examples/more/08_algebra_and_conversion/example b/C/examples/more/08_algebra_and_conversion/example similarity index 100% rename from examples/more/08_algebra_and_conversion/example rename to C/examples/more/08_algebra_and_conversion/example diff --git a/examples/more/08_algebra_and_conversion/example.c b/C/examples/more/08_algebra_and_conversion/example.c similarity index 100% rename from examples/more/08_algebra_and_conversion/example.c rename to C/examples/more/08_algebra_and_conversion/example.c diff --git a/examples/more/09_ergonomic_algebra/example b/C/examples/more/09_ergonomic_algebra/example similarity index 100% rename from examples/more/09_ergonomic_algebra/example rename to C/examples/more/09_ergonomic_algebra/example diff --git a/examples/more/09_ergonomic_algebra/example.c b/C/examples/more/09_ergonomic_algebra/example.c similarity index 100% rename from examples/more/09_ergonomic_algebra/example.c rename to C/examples/more/09_ergonomic_algebra/example.c diff --git a/examples/more/10_twitter_thread_example/example b/C/examples/more/10_twitter_thread_example/example similarity index 100% rename from examples/more/10_twitter_thread_example/example rename to C/examples/more/10_twitter_thread_example/example diff --git a/examples/more/10_twitter_thread_example/example.c b/C/examples/more/10_twitter_thread_example/example.c similarity index 100% rename from examples/more/10_twitter_thread_example/example.c rename to C/examples/more/10_twitter_thread_example/example.c diff --git a/examples/more/11_billion_lognormals_paralell/example b/C/examples/more/11_billion_lognormals_paralell/example similarity index 100% rename from examples/more/11_billion_lognormals_paralell/example rename to C/examples/more/11_billion_lognormals_paralell/example diff --git a/examples/more/11_billion_lognormals_paralell/example.c b/C/examples/more/11_billion_lognormals_paralell/example.c similarity index 100% rename from examples/more/11_billion_lognormals_paralell/example.c rename to C/examples/more/11_billion_lognormals_paralell/example.c diff --git a/examples/more/12_time_to_botec_parallel/example b/C/examples/more/12_time_to_botec_parallel/example similarity index 100% rename from examples/more/12_time_to_botec_parallel/example rename to C/examples/more/12_time_to_botec_parallel/example diff --git a/examples/more/12_time_to_botec_parallel/example.c b/C/examples/more/12_time_to_botec_parallel/example.c similarity index 100% rename from examples/more/12_time_to_botec_parallel/example.c rename to C/examples/more/12_time_to_botec_parallel/example.c diff --git a/examples/more/13_parallelize_min/example b/C/examples/more/13_parallelize_min/example similarity index 100% rename from examples/more/13_parallelize_min/example rename to C/examples/more/13_parallelize_min/example diff --git a/examples/more/13_parallelize_min/example.c b/C/examples/more/13_parallelize_min/example.c similarity index 100% rename from examples/more/13_parallelize_min/example.c rename to C/examples/more/13_parallelize_min/example.c diff --git a/examples/more/14_check_confidence_interval/example b/C/examples/more/14_check_confidence_interval/example similarity index 100% rename from examples/more/14_check_confidence_interval/example rename to C/examples/more/14_check_confidence_interval/example diff --git a/examples/more/14_check_confidence_interval/example.c b/C/examples/more/14_check_confidence_interval/example.c similarity index 100% rename from examples/more/14_check_confidence_interval/example.c rename to C/examples/more/14_check_confidence_interval/example.c diff --git a/examples/more/15_time_to_botec_custom_mixture/example b/C/examples/more/15_time_to_botec_custom_mixture/example similarity index 100% rename from examples/more/15_time_to_botec_custom_mixture/example rename to C/examples/more/15_time_to_botec_custom_mixture/example diff --git a/examples/more/15_time_to_botec_custom_mixture/example.c b/C/examples/more/15_time_to_botec_custom_mixture/example.c similarity index 100% rename from examples/more/15_time_to_botec_custom_mixture/example.c rename to C/examples/more/15_time_to_botec_custom_mixture/example.c diff --git a/examples/more/makefile b/C/examples/more/makefile similarity index 100% rename from examples/more/makefile rename to C/examples/more/makefile diff --git a/makefile b/C/makefile similarity index 100% rename from makefile rename to C/makefile diff --git a/squiggle.c b/C/squiggle.c similarity index 100% rename from squiggle.c rename to C/squiggle.c diff --git a/squiggle.h b/C/squiggle.h similarity index 100% rename from squiggle.h rename to C/squiggle.h diff --git a/squiggle_more.c b/C/squiggle_more.c similarity index 100% rename from squiggle_more.c rename to C/squiggle_more.c diff --git a/squiggle_more.h b/C/squiggle_more.h similarity index 100% rename from squiggle_more.h rename to C/squiggle_more.h diff --git a/test/makefile b/C/test/makefile similarity index 100% rename from test/makefile rename to C/test/makefile diff --git a/test/test b/C/test/test similarity index 100% rename from test/test rename to C/test/test diff --git a/test/test.c b/C/test/test.c similarity index 100% rename from test/test.c rename to C/test/test.c diff --git a/CUDA/examples/core/00_example_template/example b/CUDA/examples/core/00_example_template/example new file mode 100755 index 0000000000000000000000000000000000000000..e4195e1241e8500236b425adbb9a44dc7113a36f GIT binary patch literal 21656 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 literal 0 HcmV?d00001 diff --git a/CUDA/examples/core/00_example_template/example.c b/CUDA/examples/core/00_example_template/example.c new file mode 100644 index 0000000..41c7ef5 --- /dev/null +++ b/CUDA/examples/core/00_example_template/example.c @@ -0,0 +1,14 @@ +#include "../../../squiggle.h" +#include +#include + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with 0 + + // ... + + free(seed); +} diff --git a/CUDA/examples/core/01_one_sample/example b/CUDA/examples/core/01_one_sample/example new file mode 100755 index 0000000000000000000000000000000000000000..a65e937b1e702b891245e9b0431508f4d4bc0cda GIT binary patch literal 21928 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 Or9w$uU{SC%#eV{-fU_Y0 literal 0 HcmV?d00001 diff --git a/CUDA/examples/core/01_one_sample/example.c b/CUDA/examples/core/01_one_sample/example.c new file mode 100644 index 0000000..a74718b --- /dev/null +++ b/CUDA/examples/core/01_one_sample/example.c @@ -0,0 +1,34 @@ +#include "../../../squiggle.h" +#include +#include + +// Estimate functions + +double sample_0(uint64_t* seed) { UNUSED(seed); return 0; } +double sample_1(uint64_t* seed) { UNUSED(seed); return 1; } +double sample_few(uint64_t* seed) { return sample_to(1, 3, seed); } +double sample_many(uint64_t* seed) { return sample_to(2, 10, seed); } + +double sample_model(uint64_t* seed){ + + double p_a = 0.8; + double p_b = 0.5; + double p_c = p_a * p_b; + + int n_dists = 4; + double weights[] = { 1 - p_c, p_c / 2, p_c / 4, p_c / 4 }; + double (*samplers[])(uint64_t*) = { sample_0, sample_1, sample_few, sample_many }; + double result = sample_mixture(samplers, weights, n_dists, seed); + + return result; +} + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with 0 + + printf("result_one: %f\n", sample_model(seed)); + free(seed); +} diff --git a/CUDA/examples/core/02_time_to_botec/example b/CUDA/examples/core/02_time_to_botec/example new file mode 100755 index 0000000000000000000000000000000000000000..3735046491ec5fad00697dc7705005dc00593a75 GIT binary patch literal 22032 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 +#include + +double sample_0(uint64_t* seed) { UNUSED(seed); return 0; } +double sample_1(uint64_t* seed) { UNUSED(seed); return 1; } +double sample_few(uint64_t* seed) { return sample_to(1, 3, seed); } +double sample_many(uint64_t* seed) { return sample_to(2, 10, seed); } + +double sample_model(uint64_t* seed){ + + double p_a = 0.8; + double p_b = 0.5; + double p_c = p_a * p_b; + + int n_dists = 4; + double weights[] = { 1 - p_c, p_c / 2, p_c / 4, p_c / 4 }; + double (*samplers[])(uint64_t*) = { sample_0, sample_1, sample_few, sample_many }; + double result = sample_mixture(samplers, weights, n_dists, seed); + + return result; +} + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with 0 + + int n_samples = 1000000; + double* result_many = (double*)malloc((size_t)n_samples * sizeof(double)); + for (int i = 0; i < n_samples; i++) { + result_many[i] = sample_model(seed); + } + printf("Mean: %f\n", array_mean(result_many, n_samples)); + + free(seed); +} diff --git a/CUDA/examples/core/03_gcc_nested_function/example b/CUDA/examples/core/03_gcc_nested_function/example new file mode 100755 index 0000000000000000000000000000000000000000..42ec59c9be5829b60865a3467d5b4c54b885b74f GIT binary patch literal 22096 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 O_pMVLx7Y-1Me*Ox977QR literal 0 HcmV?d00001 diff --git a/CUDA/examples/core/03_gcc_nested_function/example.c b/CUDA/examples/core/03_gcc_nested_function/example.c new file mode 100644 index 0000000..828aaea --- /dev/null +++ b/CUDA/examples/core/03_gcc_nested_function/example.c @@ -0,0 +1,44 @@ +#include "../../../squiggle.h" +#include +#include + +double sample_model(uint64_t* seed){ + + double sample_0(uint64_t* seed) { UNUSED(seed); return 0; } + // Using a gcc extension, you can define a function inside another function + double sample_1(uint64_t* seed) { UNUSED(seed); return 1; } + double sample_few(uint64_t* seed) { return sample_to(1, 3, seed); } + double sample_many(uint64_t* seed) { return sample_to(2, 10, seed); } + + double p_a = 0.8; + double p_b = 0.5; + double p_c = p_a * p_b; + + int n_dists = 4; + double weights[] = { 1 - p_c, p_c / 2, p_c / 4, p_c / 4 }; + double (*samplers[])(uint64_t*) = { sample_0, sample_1, sample_few, sample_many }; + double result = sample_mixture(samplers, weights, n_dists, seed); + + return result; +} + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with 0 + + int n_samples = 1000000; + double* result_many = (double*)malloc((size_t)n_samples * sizeof(double)); + for (int i = 0; i < n_samples; i++) { + result_many[i] = sample_model(seed); + } + + printf("result_many: ["); + for (int i = 0; i < 100; i++) { + printf("%.2f, ", result_many[i]); + } + printf("]\n"); + + free(seed); +} diff --git a/CUDA/examples/core/04_gamma_beta/example b/CUDA/examples/core/04_gamma_beta/example new file mode 100755 index 0000000000000000000000000000000000000000..d38f27f459b28ec281d0134b9b43d49ce6713ba1 GIT binary patch literal 21752 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 F{THXhjl%!{ literal 0 HcmV?d00001 diff --git a/CUDA/examples/core/04_gamma_beta/example.c b/CUDA/examples/core/04_gamma_beta/example.c new file mode 100644 index 0000000..1243235 --- /dev/null +++ b/CUDA/examples/core/04_gamma_beta/example.c @@ -0,0 +1,29 @@ +#include "../../../squiggle.h" +#include +#include + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with 0 + + int n = 1000 * 1000; + double* gamma_array = malloc(sizeof(double) * (size_t)n); + for (int i = 0; i < n; i++) { + gamma_array[i] = sample_gamma(1.0, seed); + } + printf("gamma(1) summary statistics = mean: %f, std: %f\n", array_mean(gamma_array, n), array_std(gamma_array, n)); + printf("\n"); + + double* beta_array = malloc(sizeof(double) * (size_t)n); + for (int i = 0; i < n; i++) { + beta_array[i] = sample_beta(1, 2.0, seed); + } + printf("beta(1,2) summary statistics: mean: %f, std: %f\n", array_mean(beta_array, n), array_std(beta_array, n)); + printf("\n"); + + free(gamma_array); + free(beta_array); + free(seed); +} diff --git a/CUDA/examples/core/05_hundred_lognormals/example b/CUDA/examples/core/05_hundred_lognormals/example new file mode 100755 index 0000000000000000000000000000000000000000..a25f8bab3a570126752fe925878a54b2a492ddb8 GIT binary patch literal 21704 zcmeHPeQ;D&mcN}&AP97K2GF1)Jxna)2Tg*&kg*ujkig3rG+gxv2gAGroRd;SEc=Eg|931f+6>} z5_061Z(2Cat8{;3#i2+0ks-yK%ABUg>IL)WG}X>-YHVrmnBB2(!R!U|JfWaxuB4M) z)Cc9%@;g>jSb7Pk-6&%*Rkw*g{=a>{pElvyp6#IpHMcC;@$ajD^Y~8IL46Vr6_V!= zQ=96O@gp8J{zp(#ID!L#_nHZgRbB!?r*;y{M6}#V7}Zz@kcz)@4E!@=;BNrlji0qV z1Vk$R!7=duG4Kn3cjIR*RY0WDUoi&03;0=9CDcaznZXA3`Rbd4Exu6L-xl`y6l+SxKu4=+3f7Cz18rf^8r&d4jV;tijqbzO z+Sb?-uJhG2+%KB_O-;cX=&tGT`|287{7sENq^^ivch&5NcwJi{AeNVxEm`WD>zV7B zKT^I?Q4s$tZ!cSsk8m2vv_CVSLX%D15koG{@11UW4C+BtNjjqqL zjjdT9EEd9etT&tyKWKFA&fX=tZpd1Kfr+i=;IrLfV7& zyWc14M%sHU?Kdp#*DUQ{TiX9@Y5$X@{j9mY`c2xo-SyjA{3TyTpNFN!J`u&ZjmREp z7ySFeb<{jn=RDP0XE5tJpKLn2GeGu+CVQYUEywMq?3Bf4ry=UDn z=geX`-ole*k%9F_Iv~d=gdxYE}&dO@c)H~-SdYD+<4K53>kf2EH?Vi*$vxXW8h+V zDipk?6=cT;>*V-Yp7Nn{5s^jv&8v;BMbA*xh#U(~GPW*y4vlEh#dthg3lsNdb)#*g zfhGDU`Pc>!wLR1}wvIO<{YKxB$wuKpSvx+SYe#ZqZG6X-Ffx(fh+*zG=u=zNZ$t)+z8EZeOV<7f zi%`3&BaB`TP=9X?J6+R$jyqYf4E3DyylgmM(i0Zq4{{`cFJzjnCi1U!P1*bzhcjTME)2npTCj67D35a{z6UjL27*qi#7bv!gG72Nq#f z10pjIZtaUc2Ar|g4mA7~=?CsDn!j*0+`SevdVSU_SK+!)2+w1d)0#H<1wxR=Evq{? zkZ~M}F_zmY&Mgt^6fb~6C{{}@`P#Xqd(<31{AcCwiC`YX-y28#eez29`;ZbDr zv5!Df*ZVQ^wwnB&xa445sjpA5_2mDDq3=Ye)&Fqkeieg)I_I3MRv6`cv=h57_;&Jr zXu;qtf*2649kl!+o%3-u!4)MR5m%x?Fe7p*^Rk^=UR6Gn`-A<^a0sKH{R{k$ z0R&NBGdYAh@c)52txhryKaupcQ3O4@ zFSx0nU0{F&h6~v>Gp<)XmgMCFgG;X}(3u@A@{~*a}qozI_2AkjRNZwdf zK}mGVX_;;b>!2w0L^|DzJO4Fi%SiG;oYN#E z?|qyI(-hL}nz|2b{6S1hERt2fM?W87jr{~2V4+y~{)QsdXrnDCbon2ic$+MVJvg$i z(Euf7H`OH9?$|QW>CgiL)(2XkqM2XHq(_ww7g{UkKl#slxAz~)BJX)umqjjkE4`8b zT#X&UpGd)D?>nD7j>9Z6!@2njRLGI14$Cv-kxWu=*oH6T&yvU>60@Xe(7AarG$@bm zT2b>gEW3Ox+H3O`o!)c<6qTI8c{=k9(gV|KPTzx{lt=#TjaO!g z6FEK56@CT$KrM||E;`3cO!Paa4tt(&oP?ZO%~Ie7)M}o_+cz z+&L+~k=EPnXz(QRu+ASQ$h>0Z ziJ{xHM|yK-msEcB?dcjnxcH6x>L;vPc?I(=UM!;Qo(&uS!_RCC2Soo+clHMXZN5_!sGv5MF(u3 zLmVaJ>9JRlhu=K>4*mfTMG(T_TIR_8fpg-9>`t-x>hIljYu+qEll)rz7Q!b|kdP>Z z593z=d?z3m()$E{+kkH(WU0gTcm`B=*~=X6jJq7UOC2t+Bb#)+ir+!lRZV;-_`e~s zAHQ4R-z?ZJ3`o3ug(G|UMER`lQJ~!L_5FZUi2odZ4*_?*;xEV;Q2a!j3S19jl8Q$0 zdodZllJLAFc&%CvdlcU)X2Z9PTv^dIH42Zy{(OA`dAa#WIKM zsf;C#+$Zg&4tIBEsU!c1tP)4TmBHcLJvJ=lP+lwq&<-KK-vRo52QVi_CVSL ze_s#q`)~Zd8*L$}SRwCACn<8`g*$#X?a(Ymz%y&I@OyUG=r-*~sodU=zv|pW zRemQ9PhrX8)(FPms|{hhdo>@w8^`_Q32IrG56?@=@xi|mh5we6ZK3tWb(`(Ne<(}( zQ9XVS@U!&VJDHSE!FyM`8Zmu>QUmdlqe{hm92 zb#;47xZPdkndd2(UDz&Lg`4IUcnaou=H96AmsN?kMs11r`_0_+9xA_|o{YB(e*Zif zpD7+n5db^hQ{}u(<{u|GUz73U1?P1#K3j0Slkvzdo&Y9-U0fkJA5CbC7w270SQEi6 zFpE>f#f~?--6`=7u_GnkDSA`lU7}cjuffzU?8y;q)~wxqw01sMezIhW~v=` zCvpqT80Mdrc)!<7wd1Z2uQ$o~t3;}Nx8u$OuMf%mSluej7*)4pRdc1p^XfMuL+fg$ z_%c3%Q8ik(QsL=-RR)4JXz?elFNAmL_mq_uA#T=qUe6itMa5>alh=1L+m^yV8?+w2 zKCqrH$v@i9KLb9M{bP;m*HX_^ar#!)JOWec`K=^R8x==d_ibWy9Dk?z`8vefqp~tO zufCFcM#udQEW{Zp=1UG7_$~PV;4Gz?uT$Tac2@a_?|L~U5& zN9WsG;9X++sC=sd-jWJZS4iSrVu%t6McxksyoT@@qvzujn!i9_z~ntL@IR;VJ#=Fb zMc#7*d`aRZD(Mg1A0_{|@N6U%dA|>E-x&O#YW^X8!Iby1z&`{$jn_KwE&%Ta-C8Cg zUO5@l1z$gyKArI7A-&FIYC=BnWM_fym+!UBXS`c6%KK-imT3IFvlKp{fT)ys-7tX$ z&EKmxBJ8();BjF-=33T`v)T{*y_-2&*G8?URol5y9MXq^!*ST7q7!jn*Uje z*9{Z+w=wX&z>`0%`sp4X>38dVxL@l!47}TdOV`byNb}#T`Q?39Fc=bV=2UgMu2a9;^`xn0mOzKUxwR?asS!18;ZV38&vMm> zk*{s|!p*)K`rbweAHb*$`s$m4)&3@5Z8+E#^7-34L`{&y!+~1Q!h!{bshQ{_8jU`G zTbqBQFVGTh+lWtR_?rX1+V+DE7W#b4R(V&H`bzI8p^tqe z^VSMq$(lR7E6SE8Q{=ZnfWjAEe5HogV3e#9zUAe2F7cN8?p(I)uF^_hrFThrDQT6T z`KSrCORMEaK8lOYU-<}0hxzLL&CUKxf1D&x>ks?sYa=EFMMBHB1l#bT5sW?9>?eUin4ppT^%P%iDCleOx75;? zRm$!JS8Zd9uRRo~)f#Hrn?vo*Y+iF?N4UK$@nsZp8AVTjKPA}$J!lL?TdYiK4)|MO zMs+BpO_Cp0@tMBHGNOh)rGl@vj3DTfD?T5-2cr{0_W{4u!MB(A7z}*`CRvSk(8$=T z1BhJm7hsYlctHNvCVx#p;QKNrdLqa&Mr@Gqgf=#Z{ndcsHU%5FhL6t#+FFIDB^VBP z>RZ}9t!=^9KwEgD302+Ri0>ga)@qb@N!jeMzg|f827jnQcxpGcpbG`VZHn?>pe@uG zY)NYPKx+#$`AI<6TARYcBg5xG)l(ltlPaM=jqrp69ca=l26s?qwI|S^=WRnRv~f%6 zP!m{5a2;Lwn;W4_i6i8~gThQCoUz}yQq?j^^OWdK6fju;^jKQ@8CyA z2bN!`bNN$K#lGN zusoj!8FKvCe&%Di3G#Grf!m35qZYVV_ryMC`!!n7i)rLjmgn;&!(PqE{j)re|9LIH zMDw|+BNT?cvZao*Bx9BTDRATy){jfIDjHf(R@V5xXpwhoIfgx29RrJc@e7MQpMM!L z|5)-nEb_ftfMF*KYRLK+{>CED`#6TrTF!$k$7X%SeyjiXXnBr5@0%G` zv7m+=KSsZ6k>_(f!`GQnLu>zsE%JQcXE>NJOewJTe++260U_rgaqu~izq@DU=QhJH zA>%a3^ZkR4MWk&cUsY?Q&GHvOpxo8VUgACje@BrgmYx=g{O36SD`YAE6Y_VWfzqj; zZ0VG(kw4ro!*LKc%O}oH#Y%?zVGS(D?MV +#include + +// Estimate functions +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with 0 + + for (int i = 0; i < 100; i++) { + double sample = sample_lognormal(0, 10, seed); + printf("%f\n", sample); + } + free(seed); +} diff --git a/CUDA/examples/core/05_hundred_lognormals/run-sorted.sh b/CUDA/examples/core/05_hundred_lognormals/run-sorted.sh new file mode 100644 index 0000000..b7c3750 --- /dev/null +++ b/CUDA/examples/core/05_hundred_lognormals/run-sorted.sh @@ -0,0 +1 @@ +./example | sort -h diff --git a/CUDA/examples/core/06_dissolving_fermi_paradox/example b/CUDA/examples/core/06_dissolving_fermi_paradox/example new file mode 100755 index 0000000000000000000000000000000000000000..0d13c3f87e28da5d1121316080da60c37f9508ce GIT binary patch literal 21848 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 L$K^HwTT%Qcy>9`& literal 0 HcmV?d00001 diff --git a/CUDA/examples/core/06_dissolving_fermi_paradox/example.c b/CUDA/examples/core/06_dissolving_fermi_paradox/example.c new file mode 100644 index 0000000..1fd185c --- /dev/null +++ b/CUDA/examples/core/06_dissolving_fermi_paradox/example.c @@ -0,0 +1,99 @@ +#include "../../../squiggle.h" +#include +#include +#include +#include + +double sample_fermi_logspace(uint64_t * seed) +{ + // Replicate , and in particular the red line in page 11. + // You can see a simple version of this function in naive.c in this same folder + double log_rate_of_star_formation = sample_uniform(log(1), log(100), seed); + double log_fraction_of_stars_with_planets = sample_uniform(log(0.1), log(1), seed); + double log_number_of_habitable_planets_per_star_system = sample_uniform(log(0.1), log(1), seed); + + double log_rate_of_life_formation_in_habitable_planets = sample_normal(1, 50, seed); + double log_fraction_of_habitable_planets_in_which_any_life_appears; + /* + Consider: + a = underlying normal + b = rate_of_life_formation_in_habitable_planets = exp(underlying normal) = exp(a) + c = 1 - exp(-b) = fraction_of_habitable_planets_in_which_any_life_appears + d = log(c) + + Looking at the Taylor expansion for c = 1 - exp(-b), it's + b - b^2/2 + b^3/6 - x^b/24, etc. + + When b ~ 0 (as is often the case), this is close to b. + + But now, if b ~ 0, c ~ b + and d = log(c) ~ log(b) = log(exp(a)) = a + + Now, we could play around with estimating errors, + and indeed if we want b^2/2 = exp(a)^2/2 < 10^(-n), i.e., to have n decimal digits of precision, + we could compute this as e.g., a < (nlog(10) + log(2))/2 + so for example if we want ten digits of precision, that's a < -11 + + Empirically, the two numbers as calculated in C do become really close around 11 or so, + and at 38 that calculation results in a -inf (so probably a floating point error or similar.) + So we should be using that formula for somewhere between -38 << a < -11 + + I chose -16 as a happy medium after playing around with + double invert(double x){ + return log(1-exp(-exp(-x))); + } + for(int i=0; i<64; i++){ + double j = i; + printf("for %lf, log(1-exp(-exp(-x))) is calculated as... %lf\n", j, invert(j)); + } + and + */ + if (log_rate_of_life_formation_in_habitable_planets < -16) { + log_fraction_of_habitable_planets_in_which_any_life_appears = log_rate_of_life_formation_in_habitable_planets; + } else { + double rate_of_life_formation_in_habitable_planets = exp(log_rate_of_life_formation_in_habitable_planets); + double fraction_of_habitable_planets_in_which_any_life_appears = -expm1(-rate_of_life_formation_in_habitable_planets); + log_fraction_of_habitable_planets_in_which_any_life_appears = log(fraction_of_habitable_planets_in_which_any_life_appears); + } + + double log_fraction_of_planets_with_life_in_which_intelligent_life_appears = sample_uniform(log(0.001), log(1), seed); + double log_fraction_of_intelligent_planets_which_are_detectable_as_such = sample_uniform(log(0.01), log(1), seed); + double log_longevity_of_detectable_civilizations = sample_uniform(log(100), log(10000000000), seed); + + double log_n = + log_rate_of_star_formation + + log_fraction_of_stars_with_planets + + log_number_of_habitable_planets_per_star_system + + log_fraction_of_habitable_planets_in_which_any_life_appears + + log_fraction_of_planets_with_life_in_which_intelligent_life_appears + + log_fraction_of_intelligent_planets_which_are_detectable_as_such + + log_longevity_of_detectable_civilizations; + return log_n; +} + +double sample_are_we_alone_logspace(uint64_t * seed) +{ + double log_n = sample_fermi_logspace(seed); + return ((log_n > 0) ? 1 : 0); + // log_n > 0 => n > 1 +} + + +int main() +{ + + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1001; // xorshift can't start with a seed of 0 + + double logspace_fermi_proportion = 0; + int n_samples = 1000 * 1000; + for (int i = 0; i < n_samples; i++) { + double result = sample_are_we_alone_logspace(seed); + logspace_fermi_proportion += result; + } + double p_not_alone = logspace_fermi_proportion / n_samples; + printf("Probability that we are not alone: %lf (%.lf%%)\n", p_not_alone, p_not_alone * 100); + + free(seed); +} diff --git a/CUDA/examples/core/06_dissolving_fermi_paradox/fermi.pdf b/CUDA/examples/core/06_dissolving_fermi_paradox/fermi.pdf new file mode 100644 index 0000000000000000000000000000000000000000..df2e8286af483169707f05682f5031a2735727db GIT binary patch literal 255897 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

M+xvSbWTM_)K{p_8+ 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 literal 0 HcmV?d00001 diff --git a/CUDA/examples/core/06_dissolving_fermi_paradox/naive.c b/CUDA/examples/core/06_dissolving_fermi_paradox/naive.c new file mode 100644 index 0000000..0990a43 --- /dev/null +++ b/CUDA/examples/core/06_dissolving_fermi_paradox/naive.c @@ -0,0 +1,79 @@ +#include "../../../squiggle.h" +#include +#include +#include +#include + +#define VERBOSE 0 + +double sample_loguniform(double a, double b, uint64_t* seed) +{ + return exp(sample_uniform(log(a), log(b), seed)); +} + +int main() +{ + // Replicate , and in particular the red line in page 11. + // Could also be interesting to just produce and save many samples. + + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = UINT64_MAX / 64; // xorshift can't start with a seed of 0 + + // Do this naïvely, without worrying that much about numerical precision + double sample_fermi_naive(uint64_t * seed) + { + double rate_of_star_formation = sample_loguniform(1, 100, seed); + double fraction_of_stars_with_planets = sample_loguniform(0.1, 1, seed); + double number_of_habitable_planets_per_star_system = sample_loguniform(0.1, 1, seed); + double rate_of_life_formation_in_habitable_planets = sample_lognormal(1, 50, seed); + double fraction_of_habitable_planets_in_which_any_life_appears = -expm1(-rate_of_life_formation_in_habitable_planets); + // double fraction_of_habitable_planets_in_which_any_life_appears = 1-exp(-rate_of_life_formation_in_habitable_planets); + // but with more precision + double fraction_of_planets_with_life_in_which_intelligent_life_appears = sample_loguniform(0.001, 1, seed); + double fraction_of_intelligent_planets_which_are_detectable_as_such = sample_loguniform(0.01, 1, seed); + double longevity_of_detectable_civilizations = sample_loguniform(100, 10000000000, seed); + + if(VERBOSE) printf(" rate_of_star_formation = %lf\n", rate_of_star_formation); + if(VERBOSE) printf(" fraction_of_stars_with_planets = %lf\n", fraction_of_stars_with_planets); + if(VERBOSE) printf(" number_of_habitable_planets_per_star_system = %lf\n", number_of_habitable_planets_per_star_system); + if(VERBOSE) printf(" rate_of_life_formation_in_habitable_planets = %.16lf\n", rate_of_life_formation_in_habitable_planets); + if(VERBOSE) printf(" fraction_of_habitable_planets_in_which_any_life_appears = %lf\n", fraction_of_habitable_planets_in_which_any_life_appears); + if(VERBOSE) printf(" fraction_of_planets_with_life_in_which_intelligent_life_appears = %lf\n", fraction_of_planets_with_life_in_which_intelligent_life_appears); + if(VERBOSE) printf(" fraction_of_intelligent_planets_which_are_detectable_as_such = %lf\n", fraction_of_intelligent_planets_which_are_detectable_as_such); + if(VERBOSE) printf(" longevity_of_detectable_civilizations = %lf\n", longevity_of_detectable_civilizations); + + // Expected number of civilizations in the Milky way; + // see footnote 3 (p. 5) + double n = rate_of_star_formation * fraction_of_stars_with_planets * number_of_habitable_planets_per_star_system * fraction_of_habitable_planets_in_which_any_life_appears * fraction_of_planets_with_life_in_which_intelligent_life_appears * fraction_of_intelligent_planets_which_are_detectable_as_such * longevity_of_detectable_civilizations; + + return n; + } + + double sample_are_we_alone_naive(uint64_t * seed) + { + double n = sample_fermi_naive(seed); + return ((n > 1) ? 1 : 0); + } + + double n = 1000000; + double naive_fermi_proportion = 0; + for (int i = 0; i < n; i++) { + double result = sample_are_we_alone_naive(seed); + if(VERBOSE) printf("result: %lf\n", result); + naive_fermi_proportion += result; + } + printf("Naïve %% that we are not alone: %lf\n", naive_fermi_proportion / n); + + free(seed); + + /* + double invert(double x){ + return log(1-exp(-exp(-x))); + } + for(int i=0; i<64; i++){ + double j = i; + printf("for %lf, log(1-exp(-exp(-x))) is calculated as... %lf\n", j, invert(j)); + } + */ +} diff --git a/CUDA/examples/core/06_dissolving_fermi_paradox/scratchpad b/CUDA/examples/core/06_dissolving_fermi_paradox/scratchpad new file mode 100755 index 0000000000000000000000000000000000000000..f3010c5a74d179998e74509811bd7296b6a10383 GIT binary patch literal 26992 zcmeHw3v^UfmiA35foMqGLWxENEw#{6AtVTzwAxld1#Yy^prJc7fl5)SkhFQ3RPk_> zK|_EN%1*m%+kVUp_G67sJ0tqr^J_nTE8*R~5^ZgK5&`uV0gUlM8iD%1eI7Trii+C3 zdd_ANdqTxv?8IDkRY`iE!ofHH4-W|UZ!^0 zlojPv_-iMplTg+h{keF(F)&en_6&}f(A|kj|Kk@99V>dS|Lnk($EN@EXGQOMXKp!P@}NG6 zh7z@xCZ;mwX(|#8AOF3`aU8+E;LA+}M@!G4;;b~4@lo)<90i{Xyd8h3DGEe7{^Yjl z@DGlHuN(#cmr?NRN5NkXyd8h3={G>6lP5R|{^?Qh;ZgAZQSkSTg1-iMJN{Br6%gs< ztQZBqVHEr>;4i`7DG7evL~eYI;w!J5=c^621(!9nhk|XD^JX`;GzTmFOB;iV&$q0p zrP3`hwBOklQd(P9DD4f+3Xo033VI5No_wus4b7oCU!eXD zR5pZ^_BMZWt%BP&gK>RYBYCcM-U)on20#a4qg=`!KRNhW}gnD8*D zkv5y~Rs*XjkD2hQ3BSdJmp(()&zkV#P4qDn{%jL|mkCenlT5uPe7;1UhNm@fS_7vw za9RWZ-)i7f^}=IX$Dtf;WA>Z3DvH(_3uPvHwT^8$TiKWsGtUQlC^7j00QDk;=Y;eIQKkiYDE^dDrj5l={86J!3-wU^henwe=%M(%Mwu4o zq4=FfnHJ=sxZfz#hGZx{-zd|pi;XfZ%tP_e!>URr=Lep!Zg{__^njz?koLHYA}$>qZ-QD;CV9G?Z0=;QWf}`rmuiz>(r0m)*{=r zXOX95(IRC^T^IZ?J{5i#`4|MTA$5GUqoht#n|JBc;T3umlpuN8AlVHPkHbkMF$J-$szcfK9`epaT3O%fOP`a9YAtYKisZP{ciT-!06Aw*r;tv;abE=A11Ek zA0W9cg~Y~5+KJ?4PI4_LVIAklj)$hmjx{3vB}j){AX7!ahuP{SnM(47}99bEAlX-^FV$ zNU3ECkLlICHb13SSnJ!oHUVLHk4fgX^V&GCW!hx+*acyJMe;MJIELs0B{h;-su~>y zjFHf#9hCQj5;fcL2S;MRMfmNOc4=eva56C-y0!to8}6eX)M>-&y2mISP-`1}_AqeU zmsf#eQVHi=?SLuZ$2m;xzn5x5XQ82UiPPG;i<41a2q*%S8Tz z<%;rI7mCjzqeZiyCQv#Y%7>1dDUYS)j6}bB(HfFttAL=7F#4JI5xC-{78%sKkKCwr z4_ma19a`VX&;&3j6AW?^{ag>SJ*_`$ZlG!wq{Zsom#UmjPl^1A{6Nppr7g#+9v!Gk=1P`hD@mUVwdh|OvZk&Tm z^$;czOl4afKM3@Q28o}xajX{U(Yp8LX~n%PcW|uC?HkW>V^^NT;+>{m8NF%XiuG5xNAtA z|27&;bgb}8H(!_?29e&yTVy$)xB}td5TRoqjd!=!7uU|{BmS85RlAvy5PwF~2dmc? zgXO>@CY1>NLm004ue8A>q-Qyz?C#5H#MKz_!fr^=1Go7Kdknm2tpCuz6Z&WFV}rm< zWd&bp|F5xyx`AeIl07bE(lL9$13P2thI=`QF@PTZm80AwiObTO1R-ff6Ks;@AiM1Y zk$!@=V8IA03Dz14Yp{>=Ywfd)BF9(Qht_5NkKjMBDb+sz6Z-mevf;m@>g(UW;QD$6 zv}s&8Szk|sNPmg9NTaX#K2(uDM)T)yq^~HLjHWO6bRYZ^6RfHi2F$;Ljc`dGhisOn zMjd$K1V>8f`5M<-c~6qtJ>f9a=!Ih-3{btv=N5g=b+{3PX?0kzqJhN$gx7`HO`y^@ z@FvXN;B>UQv6uj#`wIOve~rIUy*>}D2f9-H?RG8lCFZD|&C4A9@y|$N8=@KzEVg&+ zKLSqMXaO4fiu6F$f1>#d$)N6P%;+WAJ(nWl7en*3NMI~^j}wA4o)X-lVT zLnL*IyTA~PdB`PQs~e)H%<+LwxxOy|@hJLUHKOkmSh)29Hef!z&HA=4icduqi({kv z?NZXav7f-W(yvePC8YnCAl<;4RQ*GpySNRojh&WlgHY;yYjA3WZu8nug234XF(9lR z6n^2(*a8<~MWL!5T>+7V|TWh7)Lro{df zC1(Ex_4+S{xFU%kT4NvQ>_?9}dOHB#wGNxQzK!>p{ojls=}v!vH$#+!FkVLin!buY zA!JqFwT#uYKJ~sIp-cFa;RU_v9L1;|Wl26;jZB784bxytAeTs5pki?wYURFaRJ-IR z+i#-<14SHJ*k^Q4!ZAduCuA#9UAzlbHsw7_uD zcHyL%yhpxq#}YLSEYx*$v|)^#pdqVwY%5xX<=ew1DEC+FFXVm-6Ab%{YoQl3%D#_v z34enuRo(i{IR606ind8XRI<3hC;gH)lazMK)Q7?#^9w7JHx~6^qMtoTd`F}Mqx2JL z;6;5sXya>{AQaa16|5~qtoSk7&W}t-wqG~xUx_*b5;lSyY*e9T5#ri78u6_I+g6N~ zqFOJ+?J;jDllQ|_*|isvK@iaN>1fXxLc^rEa#n@Vt)Dy6qu>o=Eg|!Dn|afIiuiYa zvAUw;WJahWGNeU@Y39N--TSh%jALD34D-d9Es)oS$tYTBPx!;gU`PMSjt?`i(SHQU ztetFshMzSG5^>pD93wEW*Q6lo4}55IHm2iP#_CHt4ra0gu-4I&iMYWyk&@YyA2@`uLKb!HVPqmhs5$^0_8o+-w+S6GzyBINmhMp3{tz65WRPe(jc^rlbPnS0 z9l>?N7Y0`*Po1z&om%~Jow|^=>TlMm`3#cw_8Mk7n|RwM?8J2Lh2tYgR=tIO-bIYv zj}8zh=D)h46gk>xD`Yz7I|DC}B=O}Vag7GZYPM01QEiLQK|LLMP=WYB0ZOkt%$y!s zI$Q{@nE#|d_jldjDUZDDUQix6;jVN?{=5J?f=`J-=d0=i2Q#42W6iNyFa2Jn&t3D5_`q}Es z!N~JD&huHH!#yyqrgbmh?~NRFCn~d*f$?476?z)t zeD1FF2KFt8oVeW^*qlf4&1m-mcV&6xxE46}lcNdD=#E1rw8xBu9L|W> z;fQz~cLH+3$V6+a9gBC})KbrT)oceDWd(l(;wvf{&9q#L!^ z`C(@Q`)SeY9XZ-jYQb;?a=*3_#~)ARpvTha80U@7DDadXyysjx|9lKFa@>hOlbYrX zmzTa59?&|ryEIER&R^F}afG*_Cwpng;aGhQm^ieJ*eYv*H#+nTEjqF9ib0Yu+Sm;b zMEpb4f%J@@I)3)BR{C!E5F%s=@FSBnKIbDjKlpm%e4k2ZMCuOxHe@Zy~IIy1W#ZDN|?>ra5+S$b((NrFiS3PFzH+Ln|M&z>vqzryp zSOAH#*JEs?lm87!61Fgyq?3W=*BUwj$qf_OAe{R!kbbF>PcfK5QVG_$%A?T8dqN|5 zg-m&dRtA=zs+FyHt79~+I9~uG>~>SMQhIJN6Ii zmjLDNPGrrC9PvgDmPb2@o=-#gu@WyIu19WILwvqyyrT;PEdau z7CB5~kA`W6y>!S?f+wYzd?hFY2?7jr48>XPx{#wF{DNkIXqdh(?{zaA;h(!p-&tMa zj(QvkE%4eEd%V%RUq@W^WMZCHZ->#?`Gk0TY0~e^NwCm3ci3C{W%wiD^e6Yzw4_ZV z4oPL0>hOrlDjF)^v->lJLYL9yd*|*hg|MaypQ#b+>IT%ztY*h!&!aPDTq_U z6T{5c#yJdE!+6;Yd=NFp?qT~rMuzPhB*yJY$F{0Pi)lWl?jy+mv}b?%6H1TY$e#FU z&(^VYgcWzi7vkV#tWQJ_{m}jtXC2ySFN9KP&svD%BZZ9lyH{khnQz)rVrsy&6CC;p zF4qJE4Vo{;-tr&C|6jfde-aGhKyi?>Tc-!{5QphXKAU)*yfa z&OeT4*dx-993YuKaUTnsyj_eQ{h+sMoZ#q8tmkqG`FXgKs`yd3>Q79VL%d_`V!_=B z6g#v-wPJt3;sw^}-M4G^9?HRWO0BjrYcie&U`DTX3}e$&9P4~F9MmHFG0YqUk>3HQ zxGRcdc<$5*sh|4{i2p-BT4b-jsUJ~dXO@GA%H?Cq@(9+(s_$tVImcSeL(QU*xXdszrwQzBxMca&Xo^1~Z1xvoQ>P4T@6U!C zL3?!_y$kAEdstmN78x|aM7QN#4N-naJ;Ad3VKuCpg)gW-i>YNjYh!BXPnisbed^D8 zR1d>!0Hzq{N4hNo6Jb}BYw77HNlG$SGw-5jiI4ztLK>2DSY7`X<2a2rt4ykctV}DI z6L)Y`v^3}aE8d_GvY=8g_@ZcA_vT;>iQ7&^X_MFAg_t$ zT@LZEE5|NAILs#nkXJG_t z=Q#X|R)`|3<@@oY=uUUNC;W%+Ot}Z$duS!UM9e=gkCbG~YhcQvY37YKVo}0Rg~^@P zI_lAYjwQ4{FbmnxPd63>6cB_GuWh{BQ3OsbO2H_$PKb3j>xHH)h;e2lVrUk`Ax8y> zS-2qE;ufLvB=iDYwWA8Zct(z27yz1kS6$Zw-6N-~>q@xW!NOJKdfCs8GhA;Wwkn0Y zM%*r+krwtE=I*qxF38EaEM7JvAS~p9uR$&^lM8w9W_Uvb;SUUl6UEayaIcQPsC3&=#IHyXk6yU2>j<(-7&+(V8d2h5PV{ueMA7Gg&$ z#hv;HdLw^e(T9Z`L>r1hc?WY5Kcd;k09X{#&v+-1sQMm@Ij2OTfy+nyXZOI`x~{Yy zPbq`P3^be8K-@A?6Mfkm&-U6UoX}SZi+818|kp+LKf3JFf9U(ev@GIy@6GYn| zznRg(`{fA37-4*p)Xxb1F2ZM@ihqRghrva!f1A4H@y&>jTI4S{7JLrnIZe(Br!J1^ zM-fOh%(lo8{SfxqG`r!IE#n;JbSlD>#|jTzfid`SF0CFIHBEMX_^rROzx5;iU5_2? z-`d}Xl>XRpCvp@+v!61wi6dQ&$Iv!rIXYwEiOHj3vneM`k5TQ5xAFz%SLj2(2tR4g zvvfOk^7%zDzk7iialO4@ooF|X) z0x9mt^1XdZRad zi9k()y&-Ny+>zr8Aj2V`Z}(n7?@Q$9PyPkU?ml4&T~z$G@JnxG2-hQ?$VcwPguOU< z;s)y7@Ih!IXXLnPzF;MP+KQ1AB%VY`<v<6OV;Isx#Yv3QJ0s41~ly32F zeR6rwK6$b|RPPVjR|M_;wxGSaC1m&0zY6`9eR5;nnV?&Mf8V*x-qeChe;^QU^M`_V z{QJ-LR(~L9541GlA8-0Y4K2;>Q@)-T^?S~O-~RroJI-?DGng489L|F-29&`YHz$7Z zllvdNAja#@iY@w&UtIaGW3FZOYt|OJIh`xUq4B%M$g#}eb)po;=zC9bCJC!hYOq0KiI7EWuwGu*IjS!2*gqb>|6lQA~e6njIn zeR8|qIl1-E0C!ms%>0dEZjQQ^aC0r|-Qd~Kygb;}9`prj z>$vzz(QM;JOk9QWaUK)n8+;!7d!$!5NW4Oicvun$qnvSp~yqrj^LEesL zj{z0|#sFQtiNr9V^5;aN9&iwF58+==B%E-sEr8bp#@@g|39ty;#74lHJ&D8yz%J}J ze+Af!-D(W50tc!CfLrz^5)&-oi#_%Xz#70xz+S+5KpQS;?gs1v>>@m_rk(&)a4S3v zxcS3G!jpwEp6+x3+VJS+SwK4;)b#^y#?#j+*=Pso0xZHa<0`-|z*fLPzzu*EM-qw6 zfXc^-#5;g4yqsbi13q|JY7Jl);1ht#=NLC&E8uY|aS-PJX89e0;J1_zNO)eT4C1d5IQngSv5SMYiodk*|N>)k{mNcBjBn+RMDaAa>v zgewAW6L6~-hU>@!+%Rz0(ReJAGOYH6uo%>fzZ%p{#JrgTsLZk2evmoKTJV6S%xaHj zm06vevOU(Kbz|Jtl8&)+treCkD51n{Epl6(v#fTI&a&EOS#z{p;`Idaz})&F^@ECN zW|_5Mlf`4TugjWkb#`Rm0u@~k4ohSuS(3%?-4J}kPDqgvu2T8 zHyLtytgV)-GOQ(#G({{lrTO52jq33zgnhQ=7OQPjre-ZzXMs^O_gD*HV2pt18bMca zAd#T!QqqN>yBT!*Bpr?OA<&f|W~@rq*@$dVkkFaO+Ld9c%9J{rW6~M7S3h_);^`^g z&Sr_`-)F#W0PeelX|dV^uomIRAqMrP!8?F2K+IY|^fYHQYYx$04}1;qjE{y<%(3Q_ z0AC6GW591AdNxiE&C|Ko%~?yVk7eCt-ICP?=tlW_n6@6KAUJXn$SE#PL|k-kluN^2iYjksNBid|38zqY5<_zm&*=5!( z*^PkcJ3DhRJO$2Uc#1nWv;0g!bW?7+Y+0@o{mnqkeFU+%9(g{#x!m5aOwBwVqOAe# zJKuoT4%$tiwIjCsk>_(5PMGO7COYYM3uqcavw>)!+XpglvKB;XK5c?Ro$D~NqK+|{ zORP>9%9ua!QIH=(+ZfsgMcW@_mZzDE8lQ`$)0<%pU%CxVdgx64#l4z!s_&AzEJtf*F zQKI#TlGxVD&&?>uwAvn1*8N(vhvx??CjcVJ~r@WVNU zm8D#GBbt@Z5%qr+WjPMP{vQU6@3EzDETT;tl1sn}0c!+o6>yD!T>@?vaEpL30ec1P z7jRHO1<&Rw(KCHYb^(h7YN(!vZIf@y67xVxcdLxy%@zwT@_T&dS_@`->ufVd(&roBoif*2@WnbAx03Pa zD(U8p1yM-GnPhrI$r>|;=Pk-p2IWuw0MfknJ`ub-n26( z;!OB8DfmKxm+OLTL;JrBlbj-KDz`KIsrtD~@G%0ZV6=|WpQ`6y1D|eOTSmdhfG7Fw zmm`D3&UApI>ET7xWx(#wloNGwO4l#F6+){>s@(^G&A^~i?f#jdm+K!Z;)k8p()i)| zP#~hoDSq-6;zFi!>ijAK{aF}qmsoG*`siYK+1m)L9tGbl__T@ziro*O**^)q{aVh$ zFIYV=3ZGvBZx=LXFbVS8X*W<~#wrRusZBGbl|F{IDO;}L^!1|I0pM-mlR7U3M&a|N zcE&~aZh_x2jpNyw7}=i*e1+IZu{$B)9~XFgF{gK-Oz95{&-3Qr7X^K<*x#{x zDiG`)h5qCy`0=nK>0!&IoIAUlLG}XR$u6n(bqe~Tt2jOPd;a}aJ4Yq`&ISGW%<~kv zPRmO2$8>gCHVXbO;zKQ5oCA*XEJYYS?05+;&k*>BCEmdi>|P1kUkkh|#Secg@D;*d z(vH0XZx{11DERj?yeOCe-IJ0$n3y1YuApxf zens(-(#2995zmFV%49)r#}_du$xkCs7x+Qpw{l!_1it7}PQQu+Wj^pEPwISJEa+>5 z(Vl@El$J6)&zpbm7WA$u9Lw&gkli>6{m%t`*R`B}gJAa9DD=Mrp8P6R&K-hJzu2JP zA^5xwyj|qY;NwyFXCUx0I|{#&cFz^~-itYxGQsRzfv>rmBiJ1ivX=udSO`iEW(#_| zsGKiqZ)5l*QdUT0rk^iMWxv9&mdd8>0X*Xh)VKO;@#rVe7HSWL@ybp>8ToLkFVy4< z&_go%mT7H^Z&_o@Qh%ebHq_GA?(>IND)d;aF^ES&g(XGT6sISmPnkCO{B3RiRlZtvRPuo`lte0@P(du2l@F`%>?&|ad$2JW2!YF-+uZZYd}X(I z=$o#|d}9pm}and~?0G&T@Nwx6YY!ds(Hg(ml&t zMqJs4SOe{0HX@YGpKW!ym%Ytq4 z)3C{nzUn)+^o7}EYTkw5+7f0TyA9U*Lw@>tt%Xh&1ni`Nj=rg^^DDI-|A@~cd67utJ?kXHTGPKkW z2>WW=TYUB4hK~#L5BrX=#b9Vbul6-J)1FUKj%!JaZY9<>^-9Nr9sRUv$v7PlRw9t z%t5Nt-`a?m1jy8;`ed(^0xE^=tC~XorGTL}4(nwOACeBXwJL>pHz8QKtT|i=TeM;p ztumpOh8ytZ_J&%4a?dKC8uBkw7(I1IJ%8hVP3XY@%0AL`nIjecq% za;=RarI0yKA+m+bT2Q1+doZ9BhJq_mq+kx}78X|ugY_bO*VlrZEO8z@j`J2WkFNYp z4PeHb!(Ws_tRYQU7v!q+cSG9lV~dY76HoGfMnZYdD5@E)%oC(-4qdUy_VOM_LObfr ziCx~A5VT!1x33cW9|;{MTFPQuk(B5-YHly@g(S2mQJ>nL_HB3^-y-GTEc%yF_Al>G zQ|0%geJ=iFdwIVqA-(TFiDV=_%l7h~vjI5jQnr`(Q4-4gS&*A6+xJI;-I+pSav=T*zY$DssdoT%Of>8D^+spC)ShSxd z=;VE|gz|ow+Ebg<_KyNbI+6Ub$>vEwahw&%Q|_;+??PQtW*&&?lU!EIn zqJ1ho^<_@uMgK)+B=WNTRVjGc-VCMhm`Pot|9_%{^1%&1 >/dev/null | grep real | awk '{print $$2}' ); echo "scale=2; 1000 * $$t / 100" | bc | sed "s|^|Time using 1 thread: |" | sed 's|$$|ms|' && echo + +## e.g., make profile-linux-one DIR=01_one_sample +profile-linux-one: + echo "Requires perf, which depends on the kernel version, and might be in linux-tools package or similar" + echo "Must be run as sudo" + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) $(DIR)/$(SRC) $(DEPS) -o $(DIR)/$(OUTPUT) + # $(CC) $(SRC) $(DEPS) -o $(OUTPUT) + sudo perf record $(DIR)/$(OUTPUT) + sudo perf report + rm perf.data diff --git a/CUDA/examples/more/00_example_template/example b/CUDA/examples/more/00_example_template/example new file mode 100755 index 0000000000000000000000000000000000000000..ac90d49a12194c87bc1a26b543e6b16efdcf92d0 GIT binary patch literal 27360 zcmeHw3v|;}*6%+}3*pfuI7O?1MopcFw6+d7?I@Q9QutQ`7A*=R5=tJW+BTgwf#M*8 z6GSp4$jlvQ^v>LG@!jwH)_CVzvz*smqw`E#K)_e);0z2p)cX2|D%65ddFB50c_jaY zM)~GG*1GHZUnKjSefHUBpMCb(XP@&=58tYBFUT_(6!{pH|D;fE_%e>E76mr1NB~qT zl}aJLuT`#5#vz~2aJ;;l1C;XTU|uFP3A_=I>J?LB3^b>X^t|Cvv=m`g)|BQ8zCiU6Bc8zbi%mWj#_C)iW*P z^riWd*}c}ib}57Dsx8y+Kk9^tOWr{Di-OVvo1oF-J3@l>Fqn93RW_mCS4Pt(Vi zLCG_(0gOfO&4KUCfj^J~|MeXBYjeoIF9-ccIq=Wqz}M%%e;IfiKH1MnAjZ`cTGdP;sxuVS84ILc-z)1Ej-r|LZ91}z`FLP5Ovhs+29E@wKg<2JwjP(Q}nx~ z0lf&c`~6(hS!Lx4iCh7=&|N!kzUS7mTgzsr(^aYDSITCk(iQ3CEELH~V5KVErAD8Gm>aXrxnTEIsV zhE$#wnvulE7i52FfkFRMd0JS||5Tn96!brpr-cOlPvvO=LH}hQ+HGOlbtz20$Un7+ zw4Kh!vht5-SLD_@e8pPrSUnw2li z$`@qi&*PXyudh$^`HFaNz;f+oD4pxK;-lJV|4KDFs7Br$uB&&)3T|}3^kaq3eVM?V zy%_l9)E=-nxdYh*5^AhqkU-UFXey@4KT#S}WkPbma_uJK+bbaGUtsjJe@Wn`3u<&& z?LIbF?H)C%hCOQkg-{U~gardrasZ-XoMnBQPn+h%P^^S+UaCgs+(St<`d(rg1m~gsswQIZ@?NPf2 z3)PA~mO46KrUs|5)cDTJ1D50Q5!EsyK4Mv3@Yc;tBc)M&rjoq$C9S?X;_gwz$CA+)-W+S`wgO}z_kK{BML zxa}qk4l7Sd+@s||Z6x{(5K_&6#c?oTDcd_@S#lVarrFmufRD>=BBDYNX?46tz8&tc zm`n)c1Q8;G)Zcw-e?pzmPwnqRfA=w^2X^Gt2P@Y~!E)$nol0nYpbH4YHUF7oa6Rcc zH3rLPP>)xj$IH7RK@ZH}Gsa`+<<$Iu{vBu&op#x+5SXc~_%p}85m1bAQc>M0B z)Obv`V>m2ZALAsc4)kcjvwTQ?2--1*WQEJ%71Vq{&cnv;EE_*ThO?`;$ za(wRiG-6VG*7!VxaxDh_L))^)=l_Pjy5NG)O|svd`kH%&>#Gs8pR2DsL8QfajWP6< z=s^+bBbPm2lD-}UlU(|OP4~k-F~OGgp=VRO;ax{8D+@Vfvozc5pz}rcEZ6fnrq}ss zhS|ATBf$qi7s&gRaJavk0P!ZCGNysnA)0V^3@0jM!BT4_I9rtJ&QSNWAoCa)iQ~#@M=Kh+o9HOZ8mUfml1+OU(p`m_S5`@ zs-f-`n9(Z>zJ4RTRRuJUSx!E!&`Ai=c$Rku1uRYuMGklSCCk=m_7p!@k}_F0CLzu7 z*hO=^>onK*uRxqb-|N%*ehO6DL0;t|ecK*L6r$gsu$o{+abN_N?6W*E z%;>Gte~Q`|k3*nYVJ}Yn02;zND2)g#9|LM|(`FjlwpTfY4inuI;2 ztbi{@S%#7-&1oai5-2t0QV7$Vz} z)hK4flzO|#vh~+ohb%tW3l0a-`_gM~U)JxD z9V8QH&S5sDrz6`hE>)xF;ol%IqmF_EvQyL+Jr103aqS!p{}$P0eGq*muhs`~d-NeC z#ZPH|%L?wejs^q{O}iEKIYab;6n7mfg6r0W3X1z@OA5XQ#?idA3wFRE^@&T zs*8@O(NUVY7@F?EeARGf2N+}c;%qFCR!3=2)T*BF`_bXZz=g>B1_bU;1DXFKi_h@2 z38u;Be{V&cm<=7#DM-ZY6r7EVoH1;?K5{hgdD>sAk)AyG4aSL-v{bY^{G9E(0Cy*ghOaM<5lRUTPHUnXDp}^Pnn81MVG8!BtK9eq5Rn6r!3n) zgy@jPviTzQM*+nTvwJWgz<+SNR0sI3wD9!#cGkPRxb0N55 z{*(Tk_dD;ajlSw!S{ps@tanBaEJZ|cf*3shx@G%OSOYA>viTSiq{!ok*&cH+pV+I0 zk?wfbX5&lHq%QRuF>8_-gA%)eyq0p19GDIc6T(Xl?^i~zXZh~;)(7C1PS^K z4NbAuc8yE97c2>VYPW`68cz+-zR?*uXW00tGgfcE@Tas5vvC2Z$!Ec6FVqb0KBfLV zEc`_n^qKIxwb5}DxNSh!xc|m*6h1s%Q7TS>`lX@C(7zhlV{lfT-1ucMa(#mRdHyFb z4@|3Dy4Swrj-GZV>kE{jDLcR`^h?kKH9uKDXH>cv?LQx5UE`a(2Oe~;a6af<>GViD zPr18`{BSU1eHvSDr#SO}RBwrWSRnX*lZKbZHSqvL9Y4%Wsy9)Ctn^Q0FV3aTdh&z! z!b}|60<<6P)sBAz(A`y2{LJaIRsEK2uR=qX=k^-bMc%&J?m?`)xAdUq6>F!`WV$ovy29i{e~>W~A6U4l zw(4Z~6>8E*>?ff}aaL)T&0XNX(dCS($*TU4YlErkkY(FFPy(A}FFZ!A$EL2wd&P>l z8k>C(39aKpQLIIgg3>pGN>QA#Izv@|`1h)JAA0nf=n+;-t$m115FP*&bDj6@KvyzE zc|43}As5xC9;=3KZIkvI-ODW&?oIWcdFFHyrb~9K)<$t$Hp?DGDBx4OW|d$E3pIx9 zl@+I8Jd-WYy{LA7FwTjwdkRf)mlEBrRU%V^MenQ5*ve#W^h4N;fy`7j4DHZ{P*@w; zRjqmvHo`>>T&rUEx(D)V!7^T3^=A0Z6PAtncG%_QihUKY2UJVzD{3rcx4O`>1Lt|q zAX*4mn!7+FBQpu=x=!+9JGSnB_VW$eV-DjXioq@aU*%Fz)Q zqM}K73mLF1)#z9Wgbq06p3!kg><&0B^$2HH90^$N!?LyfWgxM33RYhsR^ZN9y^R)2 zyYZeAoY;}rL2!8oTeUVj=I`Mc0a;bJfZUTS4%?ZsO8cgApRtvFr+BSiOETB&4* zToe#zYvmeVGKN;*@FQrmiXSSV|9#Yd3W~9H?Kw#O$2mj&o9I7@jfi>Xs5`nR@f|uxO6|8<{DSD^!k-=> z@3PeGJw~%zoAp65>5QB=Y@F?k)m(5RoQahlLpzINzCD;ABo=m`$3&RWYhp34_D9sB zsq*&7d@S?FMp-crhhwvUjq2KuLGb`4=}(ani+JMT`?NN4|HkBD_E8%>$Lu5e3Hh38 zG+6KiESBu!uYjbNAcM?42GCU)LD`#W`@k;SI_FKiyMZPUcJV0#ItS(;w~yVzKHi6Z zc7eL2j75DN%I=Go*ySB;j-gk ziMcd$GeVT>qo}F4m^--udjs>3(A$hJK%B z2S_x5sNbK$G@vT@Z0h%~kVC&W1E8yy)Nc*%^DeF5D>>Io>i73J*GunrIUDav?MmJ| zpS?2OZ^Y#2caoj;px+=}UbqAeu>Qla(BtoseW{j>y>gi0yz4Qe%MPZ!R-BCXQ@qYZ zcbOlLLr3Jx57G38uVB+3=NR`PZlC!nYhR0^)#x$ASWL;4+Innl()n^NfjnlMiO=oW z?8hM2y=Z6y9Y#6&o;Sf!&3zzE@Cp&?yyj!4cPf`VO(%RY%KY zFWc|ZZfJWSUNXx-7|S9LC}`)oy$dBc&HH0MMHAjL(Koa!z@j#~n-1GHzlKt$C_ z5YD>nI5RkcNQl-=^buBL8oHYMCxaU4HUT|6VtEj;FACYWhmopP-C-OBLVS>v4L>q5 z41#5aKf|kHOdsfV1*|bvgHUP4ZUhoVeCvZn5IUf9A5|m~0ucbg zVVuDn0USbpW4!v*ZewV+>fP_`a>taay%u+Oq{o1`{<<-6g{t>;XIK4GN>!i5jpH2a z>=<6HGez1Wqqka~>_!ldps1*(0;dFURDm7THxM?ngUcjB&lv|0H^Un`UV)7xm|9j( zDqFUH?PbJo4)~$`6U!65813H{;Ohn2c_M5@l^$nwpR~eng7SH25Rr1}6G&_Kyq!$C zs(kjM=kcOR`R#-Fvefh;eDBe}YGHT=HyU?@T5F@b660u($;J^^=^eeND^J>djevBbOVv% zB}|I+YLF)WfTITtD$N)=&Id;YC}H`Fn{5^A0qB^ z-bc|Q?VHJ6MBfl^T~u_rfaC$3{znc=?_-b!2C$?0KSRMs(?Js%Xld_c<~0wJcF5KS zrFP&gDGFWzyStjPaSYJANH#7Fq{5bHtelqNxEeAB5^z zcukDcLFC_=s!iGnesm*)NJ5Ly`VcFjH~{gOW&3LQMI6*jv}`X$O7)&+j#4}E78Hp& z$X-coK8_;v@(u*&@X8MK|J)5pB19s&g| zmF9J8yl}58$AhLva9F^ z(nro|!W4#e z<7uw^i9Dl|O+VDa?zi54M@{tOn&>Eg2D1Tm;G`Y_U{0#0;v*4rmp%xb=6I956Bac% zKZLn(erS3oIln9MJ~Zw3b{n+whso~^k>48x%PS>I_`N|C!Pnbh6SUK|!w)AXpkWwB zdD=gT-eNlr*<8^xtW6BFUHb7~p$_xo@a>QV&KM{B_!`Dsc~yIqwePdrvYq;OP>r1W zDaJ=z3Od@3o2b17T{Cx5J8-yo&bC*hC0Haaf|=2kNS~!bf2Sl?)AT zEntITx*bJo7mhiy{PVqsn4^6YzWKK^bdL5cjbWxMcQ6)(zaUb*E3X6T5PYd)xAt$~ zhF(rx1OovqeGf$_z_esL)Wo_w5FySSejde&^Yq`HkqZ-Dmb-_Yu?6F5VjJ^eGj}Au z0@vSV&@Ty=T0`P#I!F-98SQRMufhaCcsus)_AQJH+uaU5iB%+tH|80u$SLR~aSb2D z%@Bp+Ec$&Fd#?beK!M(Jgn{&qp$v|njy#s^TUUToPcI!oB7vh6tc8eK@KXnEI`4N8 z4Ka{V9FgFZL%)ChU*P|TgG{fV&7TBgZWz{&-xeJDE33oeD*iIAN88PDli`Wwk2+Qs zj>3tcuUL$hPkk5ZwDjruOZowS2WSe{Kzpnmw6=mAKVDjDw{r>k`^$RrBouRlE&MBl znZ}Fp)&bldK*1y&y_x!P-tUghx%qln1`ZznB2Ivv*zUunOauB}_f7P^(WF`4fX#NF zH-@gQI4tIuJ34~nU{~}5XR_!BJ2<3yfVNEOSVaGVjrv2OrRWz)C4MQ(%;Af#FEsFl z2ENe1|1%n(zt>AY_G+FUo-5$(qAXrq>Z(6`-IbzzVD29tYMgM-l8Mzz+4F{=zrMO< z_k~}6b7be-va(z7uj3oxrpCr*zo#YG?l1EyC4reXeBqDr9w?bnHUl{ZloIdPY>KVK zH&GesQEO3$20l6=f53bR7*X zZO#5P>6)g-HF`?Y7S8GY7{c{7_NT1S8#GI5W^K@)zWROONl&`{&*WP!$XOlyW$FC? z@(exyeQtm~$L8|<3v*w2nVt`Yef0^b30PY#7$}Iz==m1UyQ;Z;o|((ADLj5Hf3@*; zx?7+GgypX!lWUOP@hbkX18^tcvw*{|C6fmLmA+)Mj`DzUKx;qV#sO{uJO{Yr^<=V` zrq7>~$(exV2M}HWu0ojM1KjzSWRiY0XhRJ1uYjAdBRBxq2Y3>&9Q&vu>{WLHIsgX% z?*Lqdt#=*a|DH@X1NPy_=Xol}$x}Wy;+t@MSqB(@H<{cC*!NyCxfgH%?>&YASK*yV zKH{-qz-qugyaMe6RIu@vY|G?_FZTBZkw z$LujYa*tx@v>L9SJl;e)BRpL`@GNw93sJbnUn zv`LwJ)z@Zx#eO}otUg_hG5T^c$tn^O5AhA*GYmY9fqaN&8$J$<5ngYxhj2UbDS`|_ zT=w_JzXr|*y48U6(BE6`#b*O>1;kS|+wy)f(QH~ciP66cR2#nhCG?yEv7$%yn zPP6IGNi%_NLswywkc~#z# zFx8M~C|wObN5*d%x2+(Szuov`p5jB3yQp3Km|`J(8@C_0r0vE9Df?mV&*!#?ahg^z zrUlhZT9E?}w&b^F!pCaIlgay$R)S`m7qfxzF5t`IgR}7~fbRr;DbbTpQq3l!4*?&S z^eRSmf!X8&ejD&6yj1fOJ)2XtW6UX)_oKRXtO>>D@&WKE2Ooeho-Z`;|CI*hy&&=) z5OSgPWJ4JXNc_(@nKD^GHj$9VVLW>(Z|6|PCh|U#t3|mN^@@=q=# zgOuM%J{FIhqie`_;SoUDE6REFttj6Tg3?+-55+0;;D-qrkEo^;dpMewXL?3Oeeyr_ z$ao4rWMR*4!4u;YC;JF+6S5-7lsuHD=tH#7oGXmab|2P&NlEXT!icNp{ z4{+qi2w#_lzgghrI)W^FocK0CPRA;q7j9LlWB7~pvkrLTFV`hr3xDas=r7jue*=Cj z`G1iE|N9*Hmw~5t<2N9IhwZHZKfs5{V<)VluzeC>F1?*VnE`e(`A(uvKe^;2im~Kp zdmdV?vh3$FDA1r>Y(G~s#a^tRGKRm{o}G-(#r8H0dxJb$)wAZ~{h+@L$a1l+%XPSs z;nV$;sr7>1Di(aUe@Ee#9P~c|-X<&Spbh@cMnB+Pr9&e5n;d-h0dEDpHH*G42mJuU z!=A+g&CV&n|I-}w4TR6T*q=;A;4p^kQ7RbTs_YPf5IgGt|Jwz=?M7tqust)NTi{oH zjiD8`M?&&pfmZ~c?U8{0j=&F#z=oZ{0RJ?@a~}HdXMvxRcdlAYZk`Em~Ww*-Bipx-KZB?LZR z#u4l+2gzg(K2zW@$FkcJ;HTtW?5`>q{^EIBlLP;C#^0)J5`N%eA!iftHj&nY2&30y zc>1Xv_@4>>HZd-KQS~JSB?n!xS(GmXpS-b#TAa_@G}=cKi2)K zmtjLl^MV~Tf!%7!(%;G6@8IQ|w>{Jm3ghpwyh{4^RZpnJf!9bun*x-|*$ybJuQYPiwL;gmoJ#}|$nTKw74YcB3RJ>>OKHTAN_IpEU zZ^1pzMKzw9#V)!+HnT;a;&Cls>|9hkKeL40I13c+VfNIhf`jV1NAWCl-#yRi_T0T- z!M!#0o_gmzcMWl6_qBRE!mRJ?w$|!u{q3w=SWja^OG|^i7&epQv+lvA`(?AJ{l10} zI0e_~@KuUvrZw1(Yi6P7V2h`!+~aLZ-D{h^__n%Q-XfcQac!F8EXgnw6sfejVG6Bl z{kWGGH|~n|@OHJKrNa{nQj4H~Lq%H{i13pfBvzjZlZEMuN4lch`E;rMW1sCr-CaR|^aFsWB8>*j>oH zgPt{bcOGoS@atND5lBfOq!=_QLJQudqw&=p9YWvinq!adg5|UfbdNFbFK-gF6Zb9S za_2M&iK!#er**Q?mCc!T`2EY7IFARHP^bKb&JaBzaVxdN(O?Rs&=JfNZ^BzX^KqBA+kfof=LZt(hXLv@?39NvN5Ijuvb$Cgbi zDZEnFvAzX;1q`)wxJIVf4;b2%vesb8U)InDOecP^ApZUJI5oxr+Y7 zkhX!?I$>|gA9)@op*;5$#f(;_3EqGY#dflOCE`tbB($+y`b!+2rVzIwrLVtC)R)kn zqT~sLaT!l7a{Bu698N-81~u*JGariE@iT*bn<*sLV4a#^{GyF z{eK3IbRzjvh{+xS<$Dc*y=eS@i~@aqo2Vz@sw{W67qM zc?my89gD7h>RfOUaZB4P&!zLS{&^IT?FzS(I)9e`zmEKWbZGw3BkM^${yT8ge_3Ci zQy1S&)OgR&LF!x9mv9^^>+3741Zf?IvK`4l)|2_ks7yH7zHJpRvF5063`@wpp+fS)HCn^Pu`evEIcpU Wm4s7}7_0uc)tut0tO{9K<$nSci@@># literal 0 HcmV?d00001 diff --git a/CUDA/examples/more/00_example_template/example.c b/CUDA/examples/more/00_example_template/example.c new file mode 100644 index 0000000..f5ee07e --- /dev/null +++ b/CUDA/examples/more/00_example_template/example.c @@ -0,0 +1,19 @@ +#include "../../../squiggle.h" +#include "../../../squiggle_more.h" +#include +#include + +double sample_model(uint64_t* seed){ + return sample_to(1, 10, seed); +} + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with 0 + + // ... + + free(seed); +} diff --git a/CUDA/examples/more/02_ci_beta/example b/CUDA/examples/more/02_ci_beta/example new file mode 100755 index 0000000000000000000000000000000000000000..27effbb416e17de7459bfd723598acaf3e2243f6 GIT binary patch literal 27368 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 literal 0 HcmV?d00001 diff --git a/CUDA/examples/more/02_ci_beta/example.c b/CUDA/examples/more/02_ci_beta/example.c new file mode 100644 index 0000000..fd9581c --- /dev/null +++ b/CUDA/examples/more/02_ci_beta/example.c @@ -0,0 +1,30 @@ +#include "../../../squiggle.h" +#include "../../../squiggle_more.h" +#include +#include + +// Estimate functions +double sample_beta_3_2(uint64_t* seed) +{ + return sample_beta(3.0, 2.0, seed); +} + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with 0 + + int n_samples = 1 * MILLION; + double* xs = malloc(sizeof(double) * (size_t)n_samples); + for (int i = 0; i < n_samples; i++) { + xs[i] = sample_beta_3_2(seed); + } + + printf("\n# Stats\n"); + array_print_stats(xs, n_samples); + printf("\n# Histogram\n"); + array_print_histogram(xs, n_samples, 23); + + free(seed); +} diff --git a/CUDA/examples/more/03_ci_beta_parallel/example b/CUDA/examples/more/03_ci_beta_parallel/example new file mode 100755 index 0000000000000000000000000000000000000000..73819d5b9c67f2f49bf95f5b2080a719e823a7f9 GIT binary patch literal 27368 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 +#include + +// Estimate functions +double sample_beta_3_2(uint64_t* seed) +{ + return sample_beta(3.0, 2.0, seed); +} + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with 0 + + int n_samples = 1 * MILLION; + double* xs = malloc(sizeof(double) * (size_t)n_samples); + sampler_parallel(sample_beta_3_2, xs, 16, n_samples); + + printf("\n# Stats\n"); + array_print_stats(xs, n_samples); + printf("\n# Histogram\n"); + array_print_histogram(xs, n_samples, 23); + + free(seed); +} diff --git a/CUDA/examples/more/04_nuclear_war/example b/CUDA/examples/more/04_nuclear_war/example new file mode 100755 index 0000000000000000000000000000000000000000..a22a449ad754013dd201f48fb4feca2e7c023844 GIT binary patch literal 27472 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 literal 0 HcmV?d00001 diff --git a/CUDA/examples/more/04_nuclear_war/example.c b/CUDA/examples/more/04_nuclear_war/example.c new file mode 100644 index 0000000..065815c --- /dev/null +++ b/CUDA/examples/more/04_nuclear_war/example.c @@ -0,0 +1,63 @@ +#include "../../../squiggle.h" +#include "../../../squiggle_more.h" +#include +#include +#include + +double probability_of_dying_nuno(uint64_t* seed) +{ + double first_year_russian_nuclear_weapons = 1953; + double current_year = 2022; + double laplace_probability_nuclear_exchange_year = sample_beta(1, current_year - first_year_russian_nuclear_weapons + 1, seed); + double laplace_probability_nuclear_exchange_month = 1 - pow(1 - laplace_probability_nuclear_exchange_year, (1.0 / 12.0)); + + double london_hit_conditional_on_russia_nuclear_weapon_usage = sample_beta(7.67, 69.65, seed); + // I.e., a beta distribution with a range of 0.05 to 0.16 into: https://nunosempere.com/blog/2023/03/15/fit-beta/ + // 0.05 were my estimate and Samotsvety's estimate in March 2022, respectively: + // https://forum.effectivealtruism.org/posts/KRFXjCqqfGQAYirm5/samotsvety-nuclear-risk-forecasts-march-2022#Nu_o_Sempere + double informed_actor_not_able_to_escape = sample_beta(3.26212166586967, 3.26228162008564, seed); + // 0.2 to 0.8, i.e., 20% to 80%, again using the previous tool + double proportion_which_die_if_bomb_drops_in_london = sample_beta(10.00, 2.45, seed); // 60% to 95% + + double probability_of_dying = laplace_probability_nuclear_exchange_month * london_hit_conditional_on_russia_nuclear_weapon_usage * informed_actor_not_able_to_escape * proportion_which_die_if_bomb_drops_in_london; + return probability_of_dying; +} + +double probability_of_dying_eli(uint64_t* seed) +{ + double russia_nato_nuclear_exchange_in_next_month = sample_beta(1.30, 1182.99, seed); // .0001 to .003 + double london_hit_conditional = sample_beta(3.47, 8.97, seed); // 0.1 to 0.5 + double informed_actors_not_able_to_escape = sample_beta(2.73, 5.67, seed); // .1 to .6 + double proportion_which_die_if_bomb_drops_in_london = sample_beta(3.00, 1.46, seed); // 0.3 to 0.95; + + double probability_of_dying = russia_nato_nuclear_exchange_in_next_month * london_hit_conditional * informed_actors_not_able_to_escape * proportion_which_die_if_bomb_drops_in_london; + return probability_of_dying; +} + +double sample_nuclear_model(uint64_t* seed) +{ + double (*samplers[])(uint64_t*) = { probability_of_dying_nuno, probability_of_dying_eli }; + double weights[] = { 0.5, 0.5 }; + return sample_mixture(samplers, weights, 2, seed); +} + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with 0 + + int n = 1 * MILLION; + double* xs = malloc(sizeof(double) * (size_t)n); + for (int i = 0; i < n; i++) { + xs[i] = sample_nuclear_model(seed); + } + + printf("\n# Stats\n"); + array_print_stats(xs, n); + printf("\n# Histogram\n"); + array_print_90_ci_histogram(xs, n, 20); + + free(xs); + free(seed); +} diff --git a/CUDA/examples/more/04_nuclear_war/scratchpad/example b/CUDA/examples/more/04_nuclear_war/scratchpad/example new file mode 100755 index 0000000000000000000000000000000000000000..5ed948d11767b1236309cce9e99ba9067ff95b09 GIT binary patch literal 22271 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 z +#include +#include + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with 0 + double firstYearRussianNuclearWeapons = 1953; + double currentYear = 2023; + + for(int i=0; i<10; i++){ + double laplace_beta = sample_beta(currentYear-firstYearRussianNuclearWeapons + 1, 1, seed); + printf("%f\n", laplace_beta); + } + + free(seed); +} diff --git a/CUDA/examples/more/04_nuclear_war/scratchpad/makefile b/CUDA/examples/more/04_nuclear_war/scratchpad/makefile new file mode 100644 index 0000000..989c057 --- /dev/null +++ b/CUDA/examples/more/04_nuclear_war/scratchpad/makefile @@ -0,0 +1,53 @@ +# Interface: +# make +# make build +# make format +# make run + +# Compiler +CC=gcc +# CC=tcc # <= faster compilation + +# Main file +SRC=example.c ../../../squiggle.c +OUTPUT=example + +## Dependencies +MATH=-lm + +## Flags +DEBUG= #'-g' +STANDARD=-std=c99 +WARNINGS=-Wall +OPTIMIZED=-O3 #-Ofast +# OPENMP=-fopenmp + +## Formatter +STYLE_BLUEPRINT=webkit +FORMATTER=clang-format -i -style=$(STYLE_BLUEPRINT) + +## make build +build: $(SRC) + $(CC) $(OPTIMIZED) $(DEBUG) $(SRC) $(MATH) -o $(OUTPUT) + +format: $(SRC) + $(FORMATTER) $(SRC) + +run: $(SRC) $(OUTPUT) + OMP_NUM_THREADS=1 ./$(OUTPUT) && echo + +time-linux: + @echo "Requires /bin/time, found on GNU/Linux systems" && echo + + @echo "Running 100x and taking avg time $(OUTPUT)" + @t=$$(/usr/bin/time -f "%e" -p bash -c 'for i in {1..100}; do $(OUTPUT); done' 2>&1 >/dev/null | grep real | awk '{print $$2}' ); echo "scale=2; 1000 * $$t / 100" | bc | sed "s|^|Time using 1 thread: |" | sed 's|$$|ms|' && echo + +## Profiling + +profile-linux: + echo "Requires perf, which depends on the kernel version, and might be in linux-tools package or similar" + echo "Must be run as sudo" + $(CC) $(SRC) $(MATH) -o $(OUTPUT) + sudo perf record ./$(OUTPUT) + sudo perf report + rm perf.data diff --git a/CUDA/examples/more/05_burn_10kg_fat/example b/CUDA/examples/more/05_burn_10kg_fat/example new file mode 100755 index 0000000000000000000000000000000000000000..ba9d49b7d15037b002a1c52443588032d1bb9911 GIT binary patch literal 27408 zcmeHwdwkQ!mG4iM4dP)*q>wlXBuXN;hG1h8NN@rd3uO2?5yT`WH5&(6NV0LTEytF4 zq=b?R2wEdbw@pjh-h1ip-OqNrn{C?9ZZ}Q4jcwk95Su2wP?F$49zS6oj+21HOZR)` zA^#+#gniumxqoCnNN48EnKNh3oH=u5e)5lRm%HX=84QX{M&-XLRO^RPGBgRi5s=#DQ6>!>&(Vs6QbK~%E>qeuiq}Y} zSb3S+<7^ZOQ`=PwIZ~lhw3Cqfp!DbmLEnF*ze>?=+g#2k z6;30CBS|RxTZDF`m+MV(njaDUWts<*7`KF?du2*v!?Js)O=`lpia~RDW>FUynckyOZtig%|&O-i?3!mtPP5 z_zuZ~`Xm}k)Lu+6D^va!e29jP-|#Hqvj}%9K0W?JO{D|va+y$FQYt~i8a`dVkOzT;A&U_}tB*CT0G^ z3o6|$o>os|qrWjhfEq#6MjX6CR(DHlLvygs?Onb?@vm+ODs8QvW}ng$3bsL5$mv}{ zb?!P(LnC3m%RQ}%7pwzbrODsqZCRr<@lsn5V{TRIR<$++X`tTK9(P?sv!}7)X)02m zV%$w0jH0g9@8_aUD=Jn<J7lH00sHFVtl&q`a0a!2<2YPGvUhYRL)jrqfCkD zDJ$tiw=|3(&oy7rN51z%bZAr_P0(j6FA92UAH139P0CV1{{u!pTzOKI$2K(NlGhE1 zGUuPg_)~ki&q}*{X)IxpuY39O>@ z>+s`r_(2_>e7Q_=-O#>5{#~YGK|dS_p*mJILx4(1+oYF5^#qOulJKb*WpD7%v!yq!%LH*ikEfx8yO}4>d@hD(&6{%@Oe6Xw+?@^4*ym5 zD-C?5fv+_1e@g?OSZ=$hhEJQ+_MD>+D~h_YBbXKMR>QkYJ6V_U=@%C&%0N8-5`g7) zh3J=4%|PtEcs#z1m1#p7i1j4Ov=I%&Ium8uKnG&KN|b3s8i@TYQKpS(AojgPnKqz- z*t3Z;Z9D_9rxIn_a0X(YM42|?f!Lx%nKqt*m?Kf94QC)$k|@(gGZ4EYQKk)MAT}mZ zrVV@`W=NE2qZx>Od{vH@HW-XQQKpRr<4=@nL&5kHW!gwE{zREJ5R6}zq1`5?U8lnI zi}LdeNZUi@Xi9lwO8J?Taww(Tlv4Jml%Gf`FHR{hNGX@6lxL-sr>B$)Q_A@%Jxo(~7!R(O{cuWVhx7t|GEq zjqG$qcTk<>_Vs9^U|lRJB$9J#c&DjOwKVSoY9UaR@6c*sn*)|5IZj{(EY@)xF72+f z6m$((mgdZ4_$4`Z2FJ`Dbd{bA{X&h-YM-nqS`kbD`FAOQC-Q$Nn`2R2k#pK�IE1 zL=_`Y0o*GTMlb^HCLH%6k@m(FG{;gc>3IAJM~&l&opo$ImYk`G^ej~)C)Du!{gqX& zXwG8=#4h*vHyBq94CCWYJftX}ZbK&{per?+lSQC(FgOn5`vdC86^w}Y3O($U`iRat zN|n*+hY3u)sz&H+V*RWaQLTjTUaW>^ zwNh4%d=MP1w$ECLf)=|Rk83`NxF=^L%7!P5yB^Ey!+Lj zm^z||`rnW7?q`!!w=JVSSiLp@Ec>?WR3h{bVYueMa1QPyJtyYi=tLTE4Mw~Kvs>Nu z#q-g3FySwt{{rYAgLc}j5SXbf?+fSuOXk9|nI<@CJ|1Awk?oBcZO3$2Hb2Wr5(DVc z+!y(j+yvS*Q&M9$t!l!YWZP*iqn_(AOvo55xRIeNFkC>+2)b?HI|)G=Px0=czzUU9k-^=5&9XU?y2Pu&P?#*&wPkbknl=8d^IYHefH;G`*9_@< z9H_K?yva5CwmlxZf-2_6GTZGk(tBdd!MM`zPqC$>|0wwNtxwfI)VYt(L2;dBO3rpW zwyy82N0blU=Kd8*5IBb*286wX+%L?z0J{lx6xw#GLi5BNWp9cSbI#obtxWxlEAkWyXnh7f^`b`&y}b|KKD*WOTr2N0 z=MZSX7!0*<@n-On5ZYzWL({{kf{@j@uQFCsdMw|09$mto5>~)BqZC6))Mm7iNIsOB zm>Prxa*L!5sv~Aat&FQO&daFe`D-^~pztG0dJ^4}a14=Z$!Y{EVoa6YWZC@BT!$<^ z*ar?rF#5tb?qq5~eo5|6kO%&c$dh+s^RSoI*JzmZ*s7(drHQSv+qB<&Lb|8zl9{SW z`&)*vPI!j5z)l5f>Srei&;r9n+a(hg@E)D^0${L3O#utbroTc!$`}DllZ5@N_;GCC zPPRa~y&}Gl@f7w1#25ELFKCoAlCgxnL6+)H?IFa(K(nHC!kIhRJTh5LaJEO2ly=S1 zhr%H9Ypat3i}hfleSd)X4oL?_=@(MpL2W*?5!=87A-AsG$F+lO>>>gl-ST4b`eHS5 z1^x~4GwKKnv&g?8#s^NgxK@sae+%!jK7p~4S7YZ4eMm|1(-6PvoYOX%VmLHyD%x{~ z%>P+)dRP@)w|3J|kAgQQYbi}%r=B;(x5R(r`E`}ytA=1@WI&A!(#plube_mo4HvgT z^_ad6HW$dNgET2>X;Yj{rlxDJHN*e94-Wg za0qQD9fEE;b#fze#)c~KR4D17=#q_#d$UGZ`pbpqC*zThBL@S22k}rbl7tW zy51#p$n5@0^jNybvf+EA1+Gd+w3|k_hBy}VA%uk)A=1`qw35DuM z>n!6KB<&qfOw-qhw{`4Z`1o!ZKAdFrpV7}d@UbV+0UX7m!>dY>qd;4ssVjK9?=_Mn zwsOd?(EwS^F3K^gU9ownr$Y}a;2+3AX=D4@vPG5-7lJF+Kk3i$O~+#ukwcEf6_G2B zDo5l^oZ};(5QB|}En82)8ekcg4QG)dMV>px&ZH-@iM?tV_!50OBfT(8XKAlx13kpz z8r`|Tdl{0!k5zPjL{2o@?ux{<+s-j5zXru1;)(1A1PR6r4UMr@v=2+T7i9FZ=Vv&dXMYCsz_Oasx$>kda={U=%2E2p zYy+?0uR#yg+<4WjLFr<&@EJBVez@b;367->x3u$wySv5@2a@)u^m_Y{Gyjk3Ew&#U z1V3-m^wPY>9%ra?$Cyd&jFqD({S(=XV==CK;8*F!r$D)vwwLF_|93AOtbwX=6vWS}B)LGAp| zX!&JNxYM9Uox{u2&XdC&mS4W1MuK*eBf2WC8ZN03Y-=v>fr&jX!y#Au0+TcPRJ`KC zpDLn_ADbQ&Q$s{~+thY^&x=mJ-xZx!;4D4$%&qcVeY_&P$K;5=IpDC2nKxKbdN$PO zjGV$PRGDgQ#4>rH#%>LD&{0n}TkwG;hhqgp>yH-AXO1eD_rzi-!xcGM(fPj775Ru( zkM=P1;fkDaMb4^`y;=!r2OH$xa15)79^_j#{|*`{IqZt6CgIN_`&948E^pVwZdY{t zg`Po3XB}neR=30A;3}-N+0YR8lGs={R#NQNKapZ1d!mjw+8H_=k?sXidne5oC~jQf z?XKuNft`0s7h2x5avUwD2cyoLOb(0(1vBx1g_|l$KMlQ3T^fn~C{!tqQq8iV9sJih z9Z@x2+7ooHHI*KE?^?uLbXsZ=}89Q`(3{0F;M;jQa^D8?!k5ZU&ch!g(C2 zvsC>V+t?>7OL2KLnSu`TDW?XU2q%AsYt}l;VvVkqKv)2$+%-51ncZ~`OBKSIn&Wkr z$FOZJIS3^7PQmIPVg>Gu)qCi%@F~uTU5On5my_U9^#MHg+hBnH3$R&E9(3ZGHgXn9 zz$9x66MzBjBw%0J}KK#U{HzTx8AvImj^nZW=!Y#W=cl9ij2#o}ub(jGx3t z#5{S>71l^nW zW)h5eNfS!DrLBA3zD?9?d1Zu5oY2 z^UdoU_lMj%u4~+LIM?eRcQKpq8QRT!bUyoxp>ZQ7$GGF{;tcZ*(j~b)cudR251}yP zTSzw5vTi5sa5T*@^D3<9q9a3ItAmX8@6is!WgZK2Pgf^hM``)PSFq)edyK~rw@?0@ z^{++HYve3qET-fc+M18`c7|{j2=PHu)c^Fz5D2PspTMJYEFb8#2CFbyj!}|MCcAR%v2|LlINW(Eiw?dn1N;krjvl}nsl!@l3BZNdVd{=S&f|cAo;pikw_4gALJ$x*5J7{s zqo(kQ%P4`Q4kmF7O^yTh0TOxJpK-Pf08s~mW4MDk4%mnCx{k8*yN$u=s`r4S-4#_z z_gP$>;VuK>`a9C#a#inPM|;)tN@=&nh3g#a^jY|+0aK(cJUG?z-A)AI2#Us*m*AEF zj;d}OjSYm2?BX(x&~wt8h@0UJ3toqfBbchLB9&DiSa}2SJAvv#g+}!JGBk)txzK{VHm5fpcb59>V_(M8DCLzW@MS6QM)>>@c$RdO zm+*j7y9IRf+k=10=M@6c*2+EZk&VaJ-6qd7d@n2MaNt<0eQ=zZUkYhX+{r|zzW|m@ zkdhAV0IDircm@|bF9_iuoJ8VTpSc@D?pBsPWV173ow5!hp0jc zWLTqE+(jo>J%AOu&+%LOZODbA;m=1pED!IGF3M&<>loUvDdxn(c3sT*5KSIH$hJq$C(89LS%xfMY?U1dVklKN_q$s!scKaCJGUxtGF#njt zSH8CCvBHv}IHff*m3nm#v5?X}T zM_CQU0f@&eTbIEv;-Y4xWosdFs`m<%ZUXl4$TG!F4o#Y6?+6K!&7zs(NePhLW z+Y#OcKMRLfdND|MJ8+8V6-#<>)%*AcZ_B0*EL)oBp$aFRI= z7(nwr1j5(jA4{1A;1JtKZ%w$!x7OX69z6>ye!Vz&FZuPNgkNV1gKhOz=uT|)Hg$VA zdy^q{35Q>?9-LS^wCG^?7=6hxCxo2Ix?oe{isn9vKAn+|(YqfxS2W)Npas!8*WDys zG9(6~Z9KE?7CJZM5FrG`Wr;Qq)TQr)PQeUjFf_P*21CL2bT_Khc3g9$_~*Gtn4>+2 z2js6z(mC2N&0(@D&toide@3KwSAGP7_Q97H?AD$KH;i)JJ7^79*aV0QEK7DmjjfuA z2yt@%%P>jBap7G@`07Zf<>7uubl$M?=(=p!%*@z5aQ*ED{gz;I}M=}))sU|!hiw(q;xMb6=AbkZ)e4id+1SCGiyDg}EXVix?=LCfXi9!paUBos#^xaH8FU;h*QU;N)puV2ic z1Y>R(){oy7?Ee#M!{RFbFs@7c7mgbZPb`1bu{3uzoCu8@@{RK$KP3Io`la(X_!odC zw;vY8`ay3sQoEZ=$e&+Uktd;;8*JfUA&q1xz;&=Q@{uDx_BgvZ zq;-J4Ohd7V{?3WUL!qS@7fB_4In2!AtFNy#@RbJsKh^;Ky&k2z?y{+YRkkKi^BP+d z{^B|4Z?m=dTWvni8k;X*tFSHitn}N00o#+IrWRXkpoJA018sg=N%4w$TcFNX=Ly=D zt+54{`)&SaA7LoF#_wsJt&F_O_Gr+9znMfv#h-l!>RUZcLu#2;#`8r2E@W{1!2wbB z3fTXE!c#|Hp|k4J9XAVn@9ckjvVO!Pi$+Si*^60vYc?mpv#e?N)n9*WV8`sDqAB>- z_Ee~$zP{1#ZVI&ei@ZvH-DDfS@JE7==T9n{gc1WvzW08cV$1i9R8IVGvr>3s^Z!r^ z@+Y;4>WQelTi`^aHo{S=XkO`QZSXV)Z7UlBjh>+2XR8ae+Ui2h-e5zZ*@nMA4K}b` zL$fWv%~p`_n@H`}GCe^<4PM(?+hd-_kl(g;Iz)PqWPiM1Er(t6t#u zp)(!g(V!0mIz(x4e!k5cXs&DU`J26d8~&=*-@4M%C`d4~lGlvurksAAlo;2-P}4G) z6O3Y6Lvx$0DbxmI@!RV0SGkY_mICQZibm?_+B{7yjj%#Vy1b!&xt@}=h5K?prf`jo z{fVuI>66sV`k+6__4~k+(op|j$hTOKvo`pP*SSA_fzsd4u4C!!Y+nBD?AH%cIxXz0 zTR=^~iZa1KL2N|n+q~>7<92#c&?zbP__h13#s}!#2Z*$kZ3pA=<;eHHjz2sBR1U@C zKL@OQBOX5jSk@hnR{|FI#N!=+>jCM#5dDC5TGrU!%K%#ds{nVr8IQLBcE1&mZvnI- zmiRf~HUwP<0sC=|xeQo_qwaW|8Fv8A1hl?`egG>0eSqD7s|kNR9{&Mg*?aMLFV*83 zaWW3Z{U=cmSd8Zm`vA-EOrjsK@}qb>4{=d9;AFsBJk47UScV7BI{;g75Vs*3?Z5@< zWwi<37J={b(BRstvL4)q5 z5QTF%u5A>>j?XlFY_G-RwV+eX)_LZ<2Q8yknbs?_Z@GWcJ@z|+W$kMKt1%a>At8~7 zZxEkK;AswIBK#J7mSc_{B&2G#W;x6z>g#{u(}KA?OZa(aYcy-VId6;6VYY3`c9;vo zIZktN)?stOT(iw#&YNSl&M}*)&$sa*e#@vG5}sBm{rKzxE{FP7&9S4nlM!ye0#C;Cm`XFZbVdeW5%_FIE`Kh+};p6&;{=1*w#1ABj-ujIi@G4z$7Dd7yYFVrG3RYHmYZ$S>~eF# z7Mi_Dq^F%w)E=0_LCEns4B`;@yQrWC^`e-n8nV77U&8VKJA{OUCL4ZwE*znJLBC#hx=(f<^9 z)5n63idmg!HaUU+XW%P=_Y*x^Qx$2}l*-3Z)|_rZv9){|d{%=Gz*p%j4P2K7P!yt%NmyC`$%pTWs`vTH4;zsTn&l#K1#Cw zv#ap{m3NSDLXx(2-znkoeo_+6lsq>_)3!!wP_(CY zOG$)R3Vsp7($8@bNlD_ng}_qoBfJ`Kh~Y{0f14;vI{a{ljSt;1)KyWo2?E5-tX|3q zx5CPr==k%Ldcpp`49NGcr7|q0jR>hsz)AsY1#A&;y@1;U+#%pg0(J=4Enu&J{Q}}8 zN-S9gvihbbv&R zM1G9$#VPo^1zzqWL`%tmj{$NP)KY0^U#VpIYxT1Vc;YYjC2B({jE^CWp8p#7bn^cy z1OE3J@CSjXe!K0+Ah9zE;79lnzBiw+io(tpfSL663F-_`+MDdqOD%ZHBq!CTlb@Xx zXtzqSpBpfd2JAwq_H!#ua2ov-G5odm>|lJZwKof5>MYvTQ`X}*L4N~~Wny2K`*1zO zQ{TyHji9%Q4V|5PL9!_W{ZD|mC9_~98~mM3xz_&wH3Oghz*|9Ytxaauoq@iW;jK!o z2vpel9!)>bK<^=Z*0ug*90G?lu16_hc&oBQ1Ul@F0Q?^i`1Rl5aG@2S2Y?#xcAo=)golUn~MqX(#s!Ji7!0Jv&PSK8=2@ z@Y}_;Iwr{4g*@`T$Wui1V}egd0Y`BEr6^v3uS^-&DuM5{ar!la&v$^QepA=)R!J`w z8M`|~o9{EcXsiP-3i^K9n2^}r2H>k1=(`1dt)Sn`TH(%7;Jd{@*klnIig(Pe^&M&iK6>{jquBx-MF_#{$RIGe%GOay(p z_p8nl{H?-|Et4$$tJ!lDJmm7W2HS!m{QZ$v8G8GwJJ{s*()(BGb*8?6yS_27%+u)h z1p}>ZZck{n;>8a`Tzc+~f z<~`zAQ0^{Y=%iQ3Cim!5+|DHn9SbVvCfBex&H{z^FuTiD!9jICqPXX~9-iZHxgVZ4 z@6qxqca>v~tDLy9_qBT4LTv2pZLMWx`nR)kVcqqfrY4VkF>Er$7rh6U-Y=U%?e}?t z;1pP;!V_#a zuk_=+ym;fT=nqdZJxy)yV1Rm*)!qg|q!LNSyd}N0cc|B?rBJA_12>+Vw!w;gvO$Op zMzp%-HMu$-cq1-*H*YeEzlt{*#|;(l<3+EeRQ}rCgvNAl0v=Ks|%0n{HtBW~X-X#_!elCFb zIS-MLm^u=DUMCy9r8&6`f8}yA&h5r~rxPwhXM66TcoDV4(PRpw&=D*W51E_3;O*4( zKI-KDl3qHEDq4#4VrM=c-TW@|W0fc7n*9*NjUQsbP}jKWw-*h~^=|t4g}d4B_xXLa z)Ru)>o89y)4Cq?_R_SC3RSDc9%>+REsa5?h?#g1vPJa)6e-i@_bNp}|7sLzs{(a^ zdD9~QaGJCWh+J4A)B!4$qn~E2kD;JfDg8RmgN1J zgz}zPR5MzcCwLb=bVVxL%X>BnZK%^Haow6g-HV*QeKq1{mhh#N_VT_}Lj7+&h=*(^;crvg z_liT2gnn^Or?!-2J6^&$4H^CT<^8RM@;Q^FPu1UU(O%BKQYI(`+$PqOz+Th;>!_gq zWqWxaETQ~=S!Dav{*R@!m-ogJS`&uBIY|4F{60VifB(a5n{e`eS^obmsr0fe;m2rW z(X~(9BQ79rL-xu`LuJ|i3MxoMsU~^fDE~hm`h688T7Q&eJ2{X4037L0wwL$Xc@Gmc zeuut<8 literal 0 HcmV?d00001 diff --git a/CUDA/examples/more/05_burn_10kg_fat/example.c b/CUDA/examples/more/05_burn_10kg_fat/example.c new file mode 100644 index 0000000..b690ec5 --- /dev/null +++ b/CUDA/examples/more/05_burn_10kg_fat/example.c @@ -0,0 +1,43 @@ +#include "../../../squiggle.h" +#include "../../../squiggle_more.h" +#include +#include +#include + +double sample_minutes_per_day_jumping_rope_needed_to_burn_10kg(uint64_t* seed) +{ + double kcal_jumping_rope_minute = sample_to(15, 20, seed); + double kcal_jumping_rope_hour = kcal_jumping_rope_minute * 60; + + double kcal_in_kg_of_fat = 7700; + double num_kg_of_fat_to_lose = 10; + + double hours_jumping_rope_needed = kcal_in_kg_of_fat * num_kg_of_fat_to_lose / kcal_jumping_rope_hour; + + double days_until_end_of_year = 152; // as of 2023-08-01 + double hours_per_day = hours_jumping_rope_needed / days_until_end_of_year; + double minutes_per_day = hours_per_day * 60; + return minutes_per_day; +} + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with 0 + + int n = 1000 * 1000; + double* xs = malloc(sizeof(double) * (size_t)n); + for (int i = 0; i < n; i++) { + xs[i] = sample_minutes_per_day_jumping_rope_needed_to_burn_10kg(seed); + } + + printf("## How many minutes per day do I have to jump rope to lose 10kg of fat by the end of the year?\n"); + + printf("\n# Stats\n"); + array_print_stats(xs, n); + printf("\n# Histogram\n"); + array_print_histogram(xs, n, 23); + + free(seed); +} diff --git a/CUDA/examples/more/06_nuclear_recovery/example b/CUDA/examples/more/06_nuclear_recovery/example new file mode 100755 index 0000000000000000000000000000000000000000..c5ade095039f073bf4dd7b07e1e3bfb95481b498 GIT binary patch literal 27696 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 +#include +#include + +double yearly_probability_nuclear_collapse(double year, uint64_t* seed) +{ + double successes = 0; + double failures = (year - 1960); + return sample_laplace(successes, failures, seed); + // ^ can change to (successes + 1)/(trials + 2) + // to get a probability, + // rather than sampling from a distribution over probabilities. +} +double yearly_probability_nuclear_collapse_2023(uint64_t* seed) +{ + return yearly_probability_nuclear_collapse(2023, seed); +} + +double yearly_probability_nuclear_collapse_after_recovery(double year, double rebuilding_period_length_years, uint64_t* seed) +{ + // assumption: nuclear + double successes = 1.0; + double failures = (year - rebuilding_period_length_years - 1960 - 1); + return sample_laplace(successes, failures, seed); +} +double yearly_probability_nuclear_collapse_after_recovery_example(uint64_t* seed) +{ + double year = 2070; + double rebuilding_period_length_years = 30; + // So, there was a nuclear collapse in 2040, + // then a recovery period of 30 years + // and it's now 2070 + return yearly_probability_nuclear_collapse_after_recovery(year, rebuilding_period_length_years, seed); +} + +double yearly_probability_nuclear_collapse_after_recovery_antiinductive(uint64_t* seed) +{ + return yearly_probability_nuclear_collapse(2023, seed) / 2; +} + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with 0 + + int n_samples = 1000000; + + // Before a first nuclear collapse + printf("## Before the first nuclear collapse\n"); + double* yearly_probability_nuclear_collapse_2023_samples = malloc(sizeof(double) * (size_t)n_samples); + for (int i = 0; i < n_samples; i++) { + yearly_probability_nuclear_collapse_2023_samples[i] = yearly_probability_nuclear_collapse_2023(seed); + } + ci ci_90_2023 = array_get_90_ci(yearly_probability_nuclear_collapse_2023_samples, n_samples); + printf("90%% confidence interval: [%f, %f]\n", ci_90_2023.low, ci_90_2023.high); + + // After the first nuclear collapse + printf("\n## After the first nuclear collapse\n"); + + double* yearly_probability_nuclear_collapse_after_recovery_samples = malloc(sizeof(double) * (size_t)n_samples); + for (int i = 0; i < n_samples; i++) { + yearly_probability_nuclear_collapse_after_recovery_samples[i] = yearly_probability_nuclear_collapse_after_recovery_example(seed); + } + ci ci_90_2070 = array_get_90_ci(yearly_probability_nuclear_collapse_after_recovery_samples, 1000000); + printf("90%% confidence interval: [%f, %f]\n", ci_90_2070.low, ci_90_2070.high); + + // After the first nuclear collapse (antiinductive) + printf("\n## After the first nuclear collapse (antiinductive)\n"); + double* yearly_probability_nuclear_collapse_after_recovery_antiinductive_samples = malloc(sizeof(double) * (size_t)n_samples); + for (int i = 0; i < n_samples; i++) { + yearly_probability_nuclear_collapse_after_recovery_antiinductive_samples[i] = yearly_probability_nuclear_collapse_after_recovery_antiinductive(seed); + } + ci ci_90_antiinductive = array_get_90_ci(yearly_probability_nuclear_collapse_after_recovery_antiinductive_samples, 1000000); + printf("90%% confidence interval: [%f, %f]\n", ci_90_antiinductive.low, ci_90_antiinductive.high); + + // free seeds + free(yearly_probability_nuclear_collapse_2023_samples); + free(yearly_probability_nuclear_collapse_after_recovery_samples); + free(yearly_probability_nuclear_collapse_after_recovery_antiinductive_samples); + free(seed); +} diff --git a/CUDA/examples/more/07_algebra/example b/CUDA/examples/more/07_algebra/example new file mode 100755 index 0000000000000000000000000000000000000000..6b150916007f0462fe08bf781cb6f928d31b4107 GIT binary patch literal 27328 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 literal 0 HcmV?d00001 diff --git a/CUDA/examples/more/07_algebra/example.c b/CUDA/examples/more/07_algebra/example.c new file mode 100644 index 0000000..65b5cd6 --- /dev/null +++ b/CUDA/examples/more/07_algebra/example.c @@ -0,0 +1,26 @@ +#include "../../../squiggle.h" +#include "../../../squiggle_more.h" +#include +#include +#include + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with 0 + + normal_params n1 = { .mean = 1.0, .std = 3.0 }; + normal_params n2 = { .mean = 2.0, .std = 4.0 }; + normal_params sn = algebra_sum_normals(n1, n2); + printf("The sum of Normal(%f, %f) and Normal(%f, %f) is Normal(%f, %f)\n", + n1.mean, n1.std, n2.mean, n2.std, sn.mean, sn.std); + + lognormal_params ln1 = { .logmean = 1.0, .logstd = 3.0 }; + lognormal_params ln2 = { .logmean = 2.0, .logstd = 4.0 }; + lognormal_params sln = algebra_product_lognormals(ln1, ln2); + printf("The product of Lognormal(%f, %f) and Lognormal(%f, %f) is Lognormal(%f, %f)\n", + ln1.logmean, ln1.logstd, ln2.logmean, ln2.logstd, sln.logmean, sln.logstd); + + free(seed); +} diff --git a/CUDA/examples/more/08_algebra_and_conversion/example b/CUDA/examples/more/08_algebra_and_conversion/example new file mode 100755 index 0000000000000000000000000000000000000000..e676eb369fb7eb86b7a4bb70e164a6abb4a100ee GIT binary patch literal 27328 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 literal 0 HcmV?d00001 diff --git a/CUDA/examples/more/08_algebra_and_conversion/example.c b/CUDA/examples/more/08_algebra_and_conversion/example.c new file mode 100644 index 0000000..3f2a2c7 --- /dev/null +++ b/CUDA/examples/more/08_algebra_and_conversion/example.c @@ -0,0 +1,33 @@ +#include "../../../squiggle.h" +#include "../../../squiggle_more.h" +#include +#include +#include + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with 0 + + // Convert to 90% confidence interval form and back + lognormal_params ln1 = { .logmean = 1.0, .logstd = 3.0 }; + ci ln1_ci = convert_lognormal_params_to_ci(ln1); + printf("The 90%% confidence interval of Lognormal(%f, %f) is [%f, %f]\n", + ln1.logmean, ln1.logstd, + ln1_ci.low, ln1_ci.high); + lognormal_params ln1_params2 = convert_ci_to_lognormal_params(ln1_ci); + printf("The lognormal which has 90%% confidence interval [%f, %f] is Lognormal(%f, %f)\n", + ln1_ci.low, ln1_ci.high, + ln1_params2.logmean, ln1_params2.logstd); + + lognormal_params ln2 = convert_ci_to_lognormal_params((ci) { .low = 1, .high = 10 }); + lognormal_params ln3 = convert_ci_to_lognormal_params((ci) { .low = 5, .high = 50 }); + + lognormal_params sln = algebra_product_lognormals(ln2, ln3); + ci sln_ci = convert_lognormal_params_to_ci(sln); + + printf("Result of some lognormal products: to(%f, %f)\n", sln_ci.low, sln_ci.high); + + free(seed); +} diff --git a/CUDA/examples/more/09_ergonomic_algebra/example b/CUDA/examples/more/09_ergonomic_algebra/example new file mode 100755 index 0000000000000000000000000000000000000000..cfddc7e6d9a2996142275411a6b9520096f53da6 GIT binary patch literal 27328 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 i(L~tuD34y7a4bA6>y?D#5Xn^jsGCz +#include +#include + +#define ln lognormal_params +#define to(...) convert_ci_to_lognormal_params((ci)__VA_ARGS__) +#define from(...) convert_lognormal_params_to_ci((ln)__VA_ARGS__) +#define times(a, b) algebra_product_lognormals(a, b) + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with 0 + + ln a = to({ .low = 1, .high = 10 }); + ln b = to({ .low = 5, .high = 500 }); + ln c = times(a, b); + + printf("Result: to(%f, %f)\n", from(c).low, from(c).high); + printf("One sample from it is: %f\n", sample_lognormal(c.logmean, c.logstd, seed)); + + free(seed); +} diff --git a/CUDA/examples/more/10_twitter_thread_example/example b/CUDA/examples/more/10_twitter_thread_example/example new file mode 100755 index 0000000000000000000000000000000000000000..1f9061de5eaf85818be0a9c4457ea6efc3fc9b92 GIT binary patch literal 27480 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 +#include + +double sample_0(uint64_t* seed) +{ + UNUSED(seed); + return 0; +} + +double sample_1(uint64_t* seed) +{ + UNUSED(seed); + return 1; +} + +double sample_normal_mean_1_std_2(uint64_t* seed) +{ + return sample_normal(1, 2, seed); +} + +double sample_1_to_3(uint64_t* seed) +{ + return sample_to(1, 3, seed); +} + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with 0 + + int n_dists = 4; + double weights[] = { 1, 2, 3, 4 }; + double (*samplers[])(uint64_t*) = { + sample_0, + sample_1, + sample_normal_mean_1_std_2, + sample_1_to_3 + }; + + int n_samples = 10; + for (int i = 0; i < n_samples; i++) { + printf("Sample #%d: %f\n", i, sample_mixture(samplers, weights, n_dists, seed)); + } + + free(seed); +} diff --git a/CUDA/examples/more/11_billion_lognormals_paralell/example b/CUDA/examples/more/11_billion_lognormals_paralell/example new file mode 100755 index 0000000000000000000000000000000000000000..e1eb2f82c8253634dd1bc410c8c78a34f20503a9 GIT binary patch literal 27360 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 literal 0 HcmV?d00001 diff --git a/CUDA/examples/more/11_billion_lognormals_paralell/example.c b/CUDA/examples/more/11_billion_lognormals_paralell/example.c new file mode 100644 index 0000000..4840304 --- /dev/null +++ b/CUDA/examples/more/11_billion_lognormals_paralell/example.c @@ -0,0 +1,30 @@ +#include "../../../squiggle.h" +#include "../../../squiggle_more.h" +#include +#include + +double sample_model(uint64_t * seed) +{ + return sample_lognormal(0, 10, seed); +} +// Estimate functions +int main() +{ + // set randomness seed + // uint64_t* seed = malloc(sizeof(uint64_t)); + // *seed = 1000; // xorshift can't start with 0 + // ^ not necessary, because sampler_parallel takes care of the seed. + + int n_samples = 1000 * 1000 * 1000; + int n_threads = 16; + double* results = malloc((size_t)n_samples * sizeof(double)); + + sampler_parallel(sample_model, results, n_threads, n_samples); + double avg = array_sum(results, n_samples) / n_samples; + printf("Average of 1B lognormal(0,10): %f\n", avg); + + free(results); + + // free(seed); + // ^ not necessary, because sampler_parallel takes care of the seed. +} diff --git a/CUDA/examples/more/12_time_to_botec_parallel/example b/CUDA/examples/more/12_time_to_botec_parallel/example new file mode 100755 index 0000000000000000000000000000000000000000..7cfdd49f47a997bccb9033420f72823e4318bf2d GIT binary patch literal 27520 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 literal 0 HcmV?d00001 diff --git a/CUDA/examples/more/12_time_to_botec_parallel/example.c b/CUDA/examples/more/12_time_to_botec_parallel/example.c new file mode 100644 index 0000000..07d181c --- /dev/null +++ b/CUDA/examples/more/12_time_to_botec_parallel/example.c @@ -0,0 +1,31 @@ +#include "../../../squiggle.h" +#include "../../../squiggle_more.h" +#include +#include + +double sampler_result(uint64_t * seed) +{ + double p_a = 0.8; + double p_b = 0.5; + double p_c = p_a * p_b; + + double sample_0(uint64_t * seed) { UNUSED(seed); return 0; } + double sample_1(uint64_t * seed) { UNUSED(seed); return 1; } + double sample_few(uint64_t * seed) { return sample_to(1, 3, seed); } + double sample_many(uint64_t * seed) { return sample_to(2, 10, seed); } + + int n_dists = 4; + double weights[] = { 1 - p_c, p_c / 2, p_c / 4, p_c / 4 }; + double (*samplers[])(uint64_t*) = { sample_0, sample_1, sample_few, sample_many }; + return sample_mixture(samplers, weights, n_dists, seed); +} + +int main() +{ + + int n_samples = 1000 * 1000, n_threads = 16; + double* results = malloc((size_t)n_samples * sizeof(double)); + sampler_parallel(sampler_result, results, n_threads, n_samples); + printf("Avg: %f\n", array_sum(results, n_samples) / n_samples); + free(results); +} diff --git a/CUDA/examples/more/13_parallelize_min/example b/CUDA/examples/more/13_parallelize_min/example new file mode 100755 index 0000000000000000000000000000000000000000..aba62d99a2c1a79f9cf2ac4ab2d617ed833672b4 GIT binary patch literal 27424 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 QDqp&kQ{0hOAT6o +#include + +int main() +{ + /* Question: can we parallelize this? + A = normal(5,2) + B = min(A) + B * 20 + */ + + /* Option 1: parallelize taking from n samples */ + // Question being asked: what is the distribution of sampling 1000 times and taking the min? + double sample_min_of_n(uint64_t * seed, int n) + { + double min = sample_normal(5, 2, seed); + for (int i = 0; i < (n - 2); i++) { + double sample = sample_normal(5, 2, seed); + if (sample < min) { + min = sample; + } + } + return min; + } + double sample_min_of_1000(uint64_t * seed) + { + return sample_min_of_n(seed, 1000); + } + + int n_samples = 1000000, n_threads = 16; + double* results = malloc((size_t)n_samples * sizeof(double)); + sampler_parallel(sample_min_of_1000, results, n_threads, n_samples); + printf("Mean of the distribution of (taking the min of 1000 samples of a normal(5,2)): %f\n", array_mean(results, n_samples)); + free(results); + + /* Option 2: take the min from n samples cleverly using parallelism */ + // Question being asked: can we take the min of n samples cleverly? + double sample_n_parallel(int n) + { + + int n_threads = 16; + int quotient = n / 16; + int remainder = n % 16; + + uint64_t seed = 1000; + double result_remainder = sample_min_of_n(&seed, remainder); + + double sample_min_of_quotient(uint64_t * seed) + { + return sample_min_of_n(seed, quotient); + } + double* results_quotient = malloc((size_t)quotient * sizeof(double)); + sampler_parallel(sample_min_of_quotient, results_quotient, n_threads, quotient); + + double min = results_quotient[0]; + for (int i = 1; i < quotient; i++) { + if (min > results_quotient[i]) { + min = results_quotient[i]; + } + } + if (min > result_remainder) { + min = result_remainder; + } + free(results_quotient); + return min; + } + printf("Minimum of 1M samples of normal(5,2): %f\n", sample_n_parallel(1000000)); +} diff --git a/CUDA/examples/more/14_check_confidence_interval/example b/CUDA/examples/more/14_check_confidence_interval/example new file mode 100755 index 0000000000000000000000000000000000000000..b890551cf32b16e3837d1b02476db3a9f57f88a8 GIT binary patch literal 27328 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 ZEIcjim4r0iM=JkLJ*T)Tqd-Pd`9Gv53&j8c literal 0 HcmV?d00001 diff --git a/CUDA/examples/more/14_check_confidence_interval/example.c b/CUDA/examples/more/14_check_confidence_interval/example.c new file mode 100644 index 0000000..400b814 --- /dev/null +++ b/CUDA/examples/more/14_check_confidence_interval/example.c @@ -0,0 +1,22 @@ +#include "../../../squiggle.h" +#include "../../../squiggle_more.h" +#include +#include + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with a seed of 0 + + int n = 1000000; + double* xs = malloc(sizeof(double) * (size_t)n); + for (int i = 0; i < n; i++) { + xs[i] = sample_to(10, 100, seed); + } + ci ci_90 = array_get_90_ci(xs, n); + printf("Recovering confidence interval of sample_to(10, 100):\n low: %f, high: %f\n", ci_90.low, ci_90.high); + + free(xs); + free(seed); +} diff --git a/CUDA/examples/more/15_time_to_botec_custom_mixture/example b/CUDA/examples/more/15_time_to_botec_custom_mixture/example new file mode 100755 index 0000000000000000000000000000000000000000..de627d4e907465d7dac0be3e9642db29dd1247a2 GIT binary patch literal 27536 zcmeHw3w)EumG39Z27$385@?(UiIU2VAhxj+NbCd_3uO2l1enAmurbI+mcWf|Ikvz=447|I9=B zB&>wpz4!ip`}^hlA)T2sXU?2CbLPyM`Q+hilF!r zGNnYx!S^l7&B`d`GZ~JTmvMkn{v6Ioh9-eG0#dzPN{j$+;%G%eDIr0sm+sk-%}XRy ztUOQkvM4F?sc?Eer;|{Y$J;C8Zg`jk-WlXOBK$u||+I2%R6)Ou2mROk}*B&0UzdGMWJ-M^>3N>R@`hx18= z(@5cXB$VwfMm^HY)jo2V9}w-O8wZonzl5TBWokqH%DbmcZKx|~sBa3bD_B=@cfsA$ z3R?q(cQO%3E^32pYTm*n3WlYVaB?^)JwfEDe9AQs|Md5-O?dm{(=Y9NqwQyZ@H&6o zD|t|xL_-hN7embQl)eEUqGA0ve4X$agu4-+KHtH{(xDDHO{gsCDMrO>k}y2;4!}rw znm#s8lJxy5awE}u)8N;o!M~OU|F>!Ix1^DOe;WGJY4Fda!B?fh-wwPDpVa3gAV$)| z#WeWeropdDgWr_~KPHVH?gqULpVVgs5F^Rikp^Fx27e$8-U@kcLs{yR0sMGaY*`I2 zk$y(Od}^fWbGPEDs9NBu^R@U^)wc$HEmaHVGz6M_RkbS{e2T}jsxi>yX${u41U(*3 zIwGNOU9-{Fv0?=Y&njQg6I|WmtF7}ig&LK4 zixyORnrmBX8yb8KaRQVGqE_PI6|#DoTk4yFevfzcql#}`eNbs_scouLnnS@>2n#vA zk5ZY(Ut8ZmSnulE7R3wJ0k6{NYxFj+R~mV)HHbd9DE_rA^+D>WcU`T=U*A;QQ2#h( zsZG)E##;2k-{SLeQKuCaDI{_+;5>K5>^Yu03-2tPo=BI*lXn$Pi>Hed$!Rne8O*O_ zz{6z1YZ+NS18MRqqmeTq#c4(^5s5}^_&s3fj^i)51J<*$#6@vadjDEE8Rgs@iU!Ox> zHze|$e+J`E_2oJ%?XGA7Ve!ayl;@N|5#N|;2@hRa= z@Lwdq(7+cO_(B8!uQc$X<>m`&`}-!fBkRZ_MNyyZ3}(c7)%IPc9@b=R`h|sxG8D_Z z2w=HIA^O!+G8BC)7K?3Td0LQ$qJ8l^Ekr}nu6Ujn(4pwB<9S+;hN3@?=V>7tias6B z(*iUU{dzo43(rvWv3Q;qoS|rKJWmVpP;_xTPYcgb)EUpyf-@8?j^}Bi8H(N-&(i`k z6dfPW(*iyeHN^9@&>aVc5ruWYcP7dVfCFcxK<06=Gk*xpiAZ9tU7?`;l9AXn!Ld1`@L5!axp+>TPLZEawI1y9v zZzzqaI40I_xn(2q?hz35>lyv@76OwmtKmVl>&z^*YuKn7_NaZAgA>4DqF`W(_4}D# zWPO^i8)q&+u@bstiP}DMXg-o^_?_T5wPWTvWVHHAv6xl|5%*-}fzGfTb>r<*{pea0 z3VA5M1P$)GLs9&e4?5NGCBJHE+NWI$Cop8O=JbH2-!gUI+9i~GR_3Ns?)%6=l~lZD zE|`1`ObAbKIkD-C9)oWny`r=>j@9X$+SHE$RaZHiEP~6UKLCfs7?Hec$7nU&t#+Nr zQHy(7>eOhNIx(K5Mz8x4aUN1FQ#yw%%d&F73Tl8H;qLZ+1M6wuDRoRYQFISkmNKgM zrhv+yXiWG^_}AR4Xj4ekt%m#5t|%lrz*28PBBZWc7euT3sl5Z}V_9=zj}Bs_C~l4*M;I`-UuwkD}5|_O-R(qi z!|etlw4b2X<%ie?R)WpBaIFTUvdva&0D94s6${MCc#FaLs?_7~DpBj*mfj zGWEC`JzmxY3A#UfJO*Bl`vd6T0sW)XF1r;1GnM6j=Jp7 z4$GFWbCP%my0x!e;6t((v?B~jwcWI~5o3~Rry=ub>`TwmV@?dR(2aS&-g;x$IlSM(5yNFV9! z`Kt8Q2qx+D1)J`JePV(w?Zp62Jo^>u;ffp%*(^=fCOL-M$Zp)Y|molFKoBIs?HGPh~QMpzC z)&tv8?Cn7{d=Ych#^$9-TXvo#w!*6ck!gooyR>rP)D9!i&{wz{xC1nQp=zkR8Z&xD z*0=Jom=r_vnC0ZtavmcDX*|Wdg90;D4n-Pwd#z*2h zZH&he&{W%Vqu+yuuntP2#855EdXbUPI58#mrzkP&pHQwn@G)2950F9a(`cz5Eox}( zZSbzMTP@#g;caHMF@|KT+7Ed(cu8hMxu|*wZ9>SUIkzxYQ~NC6_%51+J;kknFGeYb z5-&|_BjG$KH9j<*i6xR2sLrSrr7~_yJ1*JDtz-3(!!^yaO^u^KBCsHvSE5TFLSi@M7uU1H@J2nR4&qNaj{W%J)7RA!8T zr9r~_RrCm!Zx@@O++Go1$ao494DrQ1&{g=mi8k zy6MIC$4d|t!@og(Mjd8h7Wp^CzQ73=*TT{8Z|%FR%h6ZzYP}G*TOU&Lcw6#Yn&r09 zfWVk?e7|}k=PDo=3W+`;cFvIlgJRu(a5k#_f}!oU_EQ;bzooW!XTWbTPNbwgXw^Usoz{!Y^b2{HlDu{Qc6rOr z?J)#L3xOdVLfa_^p_?w9+=!g9ph`StiaRN~Wc?!ffjW)yGf$qgY<(Yng)Ej$r;!K` zq3CVsu4R)6?J}B!fh|sfX){qhk=CV}k31b8)Ur9={kLzoq)1 z-?EHC^&@`EL1vuc@sYNBpQIDSbS)0DN+<@D>QVD zV*@XdB+)eqzeXKoCA%oasCGr?qMSB8D1d(;2c=CLWYZQ&+FS^(nE#|d=flp2D#8by zODe*boK?>7YfBIjd`JwQJY?B=$^eaCfJV5p z(5rT7*roAQKkXZx?VlRjo^VF0?3elZ0kdH?F5oooA{fy+1n)k+>XM?i?}b5M2)$hq z9z}uM26T=4ZwyDy5AjOB_#CKT8W;!ttL=LX&eD(CZU-aR$2c#@{21neX*IQL%}ICo zyfapnr3{SU242B`1wBx6VpTJTrHj%2>uJ_CzPWp3xwG22+_}Q(k#-(;cUSn~K+^g& zvff6W`48zWx*rP!-*3|J(zr$+VWVq&7hxQOU7w*ww z?*nvol;=Kk{$gpL<*9?vkmXnV41JLaCgdZ(LSFTTZgP9O+BJjP@r2cF=yZpB+#Nne z?dl&D9;yhRSG(RdT7K2n-epiDuF+*`*U3>%%dcKl!$G^r8Ce@s4HwlgmNmEcz~nx+ z;h?)?fyotlELL&;&lQn|v!?sS&=67XHnjuab0hipx+BvZuF_La+$i_e$1B?Rn4GcK zhMbo1bB8NR&x8hC;ZtgRPnl|Lz%;q9+HMVX(pFD5TJV9zhoX+e{G&wqXnQ3cld-md`1oL)fSU>ut4r@k772_i+anJ-$5hAhujg>B>Y); zpXxp9_I6M1bw_SG-!}~Dtl5TMbvrB$uEI)-4RvuZiH(V4CB<(2GbuK_C*q8uo}tqj z?p+YEchPu(;!6v>y%k+2u<}mrM$PNiOr*(lf5dg2$%+0TVwy)hwGjz`xDqjHt2FzMyM^sq~2DsRy70Hp`y>I<+2|_;b8BEAGUZoe3{gwe|r~ ztUZGil)ed6isFn^8cO>@zgNBc(W6&Ik0@~b#wljQJUq$eI`7$rt|W=_WC+bdE~-&E zQVreOChax6k6SF+`UnW<_R*rr`XVMY6{GS!Q)5iY9# z78S$S)t^xTmYo%)$3n+Gw6tZ~VVC2I_ZJ_cW42e+NYHL|p=Afo7oS12;I}k%fj-|I zZa@Hs-sUp>xJozJO>OtMI_hAc9pmg3-o4KD_c2j!>MEc7X@z0e!bsg)Fr_kd;{%8V z`+gnDnltP!JsEnR=0ZuGdRHdvXy{9@Z54D0^NwEDut%wg>c)$&ua39KH`3bh5iP_b zpvpx@CfA3QWbQtT(~ z$yvp;5&j5As#6Z~;4&8yW&H(jlu0MIGhJ8aGXF#`lU)f zL}vy`C0Ns|&O;-A6&lHD14H1YRtDBwsg>X1R}Sg4;&=&+5Z$L}rQ{-;c~DTQR&M4c zBWOj=XAysOqAwGRAYDaxI6MTk>_NY?0+0m-lYYy_oc1eK2VfURxY(VfMHJ_mxX8WK ze+r7Rb?rV({l_^&)iLy+#74xNKkN?giGB-5W{Leai(e4ETz>Hp@-9o<-ZM12HP^eb zn6v$op>4V|QhwQua3)f4Gul}YsoR4ILSkX}c}9c@Jth|OY6nq^rpjAGbFj>x8D_;i z9F9zX8}BHzUxMNhOwu=y5sP?KdxzFW?%$X^%swi@pECOhe@won3=L-e7K2UpF&g?H zz5EmM!an-ZRTx3xv4nkKmu;Q-KHgnH69~KblmVRsbCBD|ZebtqLO;7eowtHp69!-z zW~}3Vl%rQuCCu}IM=J{_YXMNe`~*Uweh@nb@tpuzp)QPzt6`{%&6a! zAq-RnpH2NfNpH3~vVH@Au3lBYhw(o1>iWHvbG@p5|AceB`hFL&@h;J>=e?`5mn8a) zm>m6%v4b;=H%OP|d>sw2{_`GplYOa{wjMdmaNbpz(S?T-UaOOgb_^Gc`EiUr9i4O^ zq3I7_!KOdXF&;wPp8pAJUkjtv@EOEdOvxqM`m_3ckrqWBGtR{4c4Ydm!T&)tw82h} zz4tj290kn)m%R*FthxAZAPa^`m*Bgax`R%smZdWBOlRa#|OS_@1y+*hj z5eQ>hn8dLt1%7S$o-Q+ZSOJxJvd}pj@TE4?Ayag)zYpIjshV*ND2oZ9~%O}(wslwRXL^) z^jeKs7%4}nG-Wpei3xn`gGCTJpmQHo9StHhhZ1J0`JJV^EiRB^Uu06ZJKJ4PD%c-= z5_+wDgMC7VW%ETG_R$DvXy8!SsSMiqx()Cz{5^R9d!$aQ-x7ce_haaeLeArWfj+-w zpjR#J4Iu~!90;RA>k(7?iBFLOi616$6jhD`4geB)>l@fx27vH`;3&>ujsp%L-_}`n zZnrTwUG*MtcDN%-={}3QtG(NRxc=4=a5<{?kh7!eyGm)V#f{?}>+~Ptrv*%rw)WvW zE#K}!5RRZ|LU}Px3E-&w+o*3KY#=>-5JTuW|8VB-j;mR6C2`+qODp^rP(B9@B2q5+Ez;V`{#eXaT4$f|9Nw!b zFD%EGrMws6^S4o2+*w}C15WK;(9P=z{xcs}2t-RO_qd0jJlb}%+|Tf}thm#OZLOBY zm|qNOE}Y3kraQrs2~ymtojMLu=0#B~J4>NS1^ZBvp$N3}epNw@{7VVEL&SXE^NUYZs zbGnma&Tst{4ahJNJg0v$jG`Aa?&Oj`aUjSW`se}q0r5?$zPL_b0LOCrUatT^d>kVfBy zjLwd7BJOuSMA0Jco5@{- zUl(s(RCGCu5{d&5k6E^^gkQu#%~;FU0;E*$CFUqK#w}!A!U7Gg>EDX#Umc@@?3?EudM~9fB)tPp+174B&R+`t5svdHLU~PkC zAdG}0)`1CPzwK<_1wRXiS9&2xXFG6;Xcbd>c(p(6>L7af5=v}It^ zSfX~IyOz!8;nHz(5Qg{qpi?+T)o?)iMZ7L%ei6RV50ax${Bb~XegoaoFYZh7iy#R= z`F;%SQS4-n0|roi0D}b0|POsT)TI!}3g*VupLQ4f-LK$<2lV+eYFmGDE`5kC&uggATG|iP4$um0H^g}J| zeyi*=%EM>N!^8Ml&M#31PU;r`%t@6OpB6E9K?FFhQ zwTWT2OFw=R;REyI@a>QV&KM{B_!`7qIjBX@2sw3Is#AXf)yS!zV|+9p=x94`qW0!? zDRA8QQWT=1@9)mUKsc5Y+|sb-U{7` zrQW7)Z_nIph+f3zSIh?&<_=9d7(RMmeAERYXRs#Nkhmi`*Pu;T_$*q_LCPJ;i(-Ve z?;H_hWSN3PhImJ`Cr`KCK>KEFB7~qgEYbX+E`2j}3T9Bk(BSqXu)#3RN0HirV~!O6 z>^;mJ?Kt@67w}`5xPQKb#xU8HmoOGNZ{b~fk}KZ`c?aN29lN#v1#alxW2uwWt} z3NS6%4mG-V1|r1#!RKf-bDsaJv;Fc|mu1nQGctEnd8929HZvo77hHdbLBAweDh$!> zbdVsHGuqu2Oc})-^~k&1H!&`3cRTQHtRhoMV*M)e6-XStnGfP7h{Dh7pR(){oy7ME}g{u(*o9jO*53=eTk3#PUZSD{>rgBGhllH*o^e3F#B_ zm-gS_?*L8Cc32c^2d!0;;n=6$!qGH~$lXK@1T#C9JpB_HSq-IM8kqe;8vHP~#|C1dcG;-g}Ixx+&^4t9m# zbH*kdX9tHg573q=5sT~v=sd!sl+dXnK^v%^@Rq$(7=CU4bb1~IoGVZ*Oup} zwMIOHvv|T(#-Uw6g~5%R3Y{E3cpryKXKsP3>f)`}3%dSUfB5REF%K*rTegHfuM2*+ zl{N0Z{I7pEv}0Cb;Z*!&+6?&CCf4&W0_+!0C@}?9{L5=|>&wH;; zvE|i`RZe_wi&Ai6%RefPyeX}scrps_5I9k(m2mV_G_9#^sjqDc+Sb$u8ft^SI-5Vx zV)KWZyutcFlMR0d8mwoj`X*amtId&DH<{{fuss;84dM?}>%F!OwufpPLO$Duu^Vg! z1qH~nZ{!yEYMX2}Ao3dgtayR14vpy$4+iT%phJ`v<>lGDfhK=_ov+F3v*E8xeJyKh z8w5!(5a(5L)s)k(k`nz|7;0SUYq16Vww3iwt+vKcYtXjRXIq88j)fey;A%);TsT%o z*IL`y+~7-)uC8CTT2D#Z!nw8&L%80?{?rwEgJwz1tPT3pSYI7@(vxWaGx-(?a#ja_ zc{=9@&(QPpS$_7MnZ@(Z&wAx$dfpfI)hnPTU`3f=pdf~!=W9IgD&zKfVHU&2@%Xj- zjmG=v?twfIT3?C9RwLbf5P$dqxDoJYfW5EAV($Z%^~PeAfJJ?=SSMgVpb5K<%0sc( zO@K9jip5F*djZ{m%In|6Z(4OoQJfM&uUkHww>-0@Z{c9_a>%xA~OweoG018&26flk03cxRvi?tCv6vm$OO z!do^wU?*S=;10YP-VWG{jdCucMcesUY$M=C!0mwjfI9)phGVgPfI9&D0j;0JVh+SO z^x({uJ%-00Pz>v=h8xF?Hj&N z#+pqFvsHXoW|!l8e)eLs39pM3I!ZZ)abB6Atu`a-rM6zfhsK(fAx-oeKKU5;ENW9V z+cJI)Zu7DkeI{@=*ubMGqKD{nf!hFF9;YwL=;QQMMs~IhwlY!~_35Xuo9VLNJE%7& zTd|>D191Bg+R@)YQ~%mC=9!C(;|*iYR;Sr?e|A35q>iJqO%<)F0y{gW0x>hCosAS&Fh_*i`2ODs#=&Z)eOl=WaEY zn{AQIaNSSIx&an zE(IMg5Joa*6E9TUJjzA9T;`gL<0G4jnMr24fzcCj?qFNf^I(OPDnZ$ zvtyv!4&Sl{X?jZV83Zo#WGuFY5Ez%O8TXrWBQ!2gWkRmaq|5eE87s^VOp^FG@Hw9k zU$hi;kAnx*jmu|i&xGQQEk^U|1?FaqG-=Msmiezpzemg^{Lz8c#-JSS( z#XR^vZa;8YTa9z$_QTqr!)+1cbW_%d7F3>HodyrK(X_nMGc4+p|DZ>NcM5(n!k(YuppqVm?-c?|xexPV+z`Vb+5XKU zFX`~Z9@alJ$559=-X;hTm$PyyC)^&(Yog&#QpyGU|7$?ryOzqZhy^={g$1k>utvaU z0XGV`O~4%j?i8?7z+M6S1soI*mngBvDxgikA_2<;tQ4?Dz-9qc<^H_9sYXvR7~fa% zeO7eVUFyd zws!)24m+k(ysn0 z_|%9%jGZ5$=GioStQg0U`upWH_(p}OR3>_`Mod=pGVW++ZZ1H zjh&7o{=+!YvlaM}`uh{$ZHyxM>(`9_dc{U`~!s*utJ`RE3DeS~2@Fff{GCJTE^i~n@ zN;_FD@cnmjVs>_b~L@d_k)VE8F-q%jv9`a z^LLxT=ceF)Aovue=;40|e5Z}`SU`fV==+6{t`zhK7+z#_fX+@x&%JkW zBs=>-@?0AF(Quf|ZwUG=g4eYIzf&lNoduz6GQ$fZ9k?$Iei88FGp_Vwk1+g|^EZ$N zzlrg;D$T+_JSy7$FTmS$a>(Sfj9%svkba;v(tQ7m;BU2YTA!%$mcZBC!V%>He;RmU z`U1nj7;G3xpF0KpVo^%x{UfzIp4nj%3zl(!ex&@|dQ{QnJfI9Fkp}$!hCpqd6ivR8gp@KV z-%j#3RxRvW3nC z6?2kH*p0V9;T~vDxhgoQt_Kv)Jolp6PPb>#+_?{yS9z+Ov)$z$MT*kmYYjC}lkECf zZ)=FDf?Xb4R;Ir!mRInss%>nnmG{&pQ+(F7ymZ}dGPO6<*oqr-o9|L&3S;A|s||vC zV6Bd}RLJUS3bf!RT#QAa(NkLF@z%$$-c8)iTUI77x=p=XH^Fh5WEc#@)quCS{5D^_ zSY6}8)xo$FShPn)jjf(wfLfHr-g-i$5=q9qCS5F?X!XugC|Q__2d|V{VQ6)-LWpci z)Vks(UmXuz+RLsFPDXjzOVeZ=w`E)zj8;jh{AS>|#&nkzCsYP`i;G5LL-!wZjVHQ5 zFTi;pQmzMfs#tELq({Ls8A_!Ag-{c9k`sx%eD7OKrj>h_R!BC4& zscl&0TiH^JE0hCuA+K&wT17PytdYGj*IO{nP;qH;qGh`9SlDoU*aR1LLo@H7XEol~ z2UcOkbuG}i3u`Tkr|yhPM`p~&PKwotxB3uhWoxTYJG+qCqq_<^As5}a%yq!Uz&ysy z(71*=K|-SINc3r)ymYyAavgqCbTZE4!FAbj&!V$OPf*;SEpar!0x9$cE5$qc#?QD^ zo37DLZZGMsY!uP-r2D9aed0E4!F;6;Ge7xK>ts%H@M@bIYP~)z3(dN6I0<$;whomT zZ#KK6@JeCp`bP8>FxbN3YMEj`rD#?Pn*u>!;i{%kAq=k>-eA2BwK7zXJN@hH1j;$P zq99niN@3)yYg<<~zj&;*CU7G46M(u&_SBxO7(Yw)=39tl;i>?# zlxX#NmBOHJ9kR4ifjYoEWub4iSesVYft$>69(eCq`Pvs}g-T68ic}5r@zt zp`B;r-v}R*o(kmj_2s#sgtjDVI%7zFXkTy+XUkIl9in{+Mfe>*e@~Ua7WK37k@e;I zyo5VM0m(?ZllA2}c|CB{q^vK`BPEpQ`ygRYs{S7Xmd?&)eR*yvVTq`RaE(2ZPQo@| z=`3F6<@u(BJ4HQ`pX8MC3$zkJf^;hD%X3f(4+}!szN|0%|9w$^wxE;er4q{b6I7q- zq}Km2aHJE-A0aP)1SI>`KdIyY4=B{vw~2ZZ)}$yrg}w6MQ|fOV&s&pF(n}d+Uc#Lz z_2qf4g!Aq^r`yWE$Ykh zSIPvXfOM{*e^T3j1%=eUtS`@-C6xa!jO3Bp{?U~B@?2U%Q`|5(2WdZ&-#bX)?~|Bq z6HcCA%l|(nm0sp0Jc~LOUH$kuN4OSzp3YsI0HA)ClTI4vR!q0$ESy$DuOeWcy_`yrf9f zmvTyan@k8eUbLUuj;t?^1LCzvR(kYM+72(_-!-Cr`QmmG&~#=b<(K|v3~*9*UXy>< dRC8FFVn4E7NlVjxr20Eoa*7*LDx_qU{{z5-F~0x+ literal 0 HcmV?d00001 diff --git a/CUDA/examples/more/15_time_to_botec_custom_mixture/example.c b/CUDA/examples/more/15_time_to_botec_custom_mixture/example.c new file mode 100644 index 0000000..47577f8 --- /dev/null +++ b/CUDA/examples/more/15_time_to_botec_custom_mixture/example.c @@ -0,0 +1,34 @@ +#include "../../../squiggle.h" +#include "../../../squiggle_more.h" +#include +#include + +double cumsum_p0 = 0.6; +double cumsum_p1 = 0.8; +double cumsum_p2 = 0.9; +double cumsum_p3 = 1.0; + +double sampler_result(uint64_t * seed) +{ + + double p = sample_uniform(0, 1, seed); + if(p< cumsum_p0){ + return 0; + } else if (p < cumsum_p1){ + return 1; + } else if (p < cumsum_p2){ + return sample_to(1,3, seed); + } else { + return sample_to(2, 10, seed); + } +} + +int main() +{ + + int n_samples = 1000 * 1000, n_threads = 16; + double* results = malloc((size_t)n_samples * sizeof(double)); + sampler_parallel(sampler_result, results, n_threads, n_samples); + printf("Avg: %f\n", array_sum(results, n_samples) / n_samples); + free(results); +} diff --git a/CUDA/examples/more/makefile b/CUDA/examples/more/makefile new file mode 100644 index 0000000..6b4b7dc --- /dev/null +++ b/CUDA/examples/more/makefile @@ -0,0 +1,117 @@ +# Interface: +# make all +# make format-all +# make run-all +# make one DIR=06_nuclear_recovery +# make format-one DIR=06_nuclear_recovery +# make run-one DIR=06_nuclear_recovery +# make time-linux-one DIR=06_nuclear_recovery +# make profile-one DIR=06_nuclear_recovery + +# Compiler +CC=gcc +# CC=tcc # <= faster compilation + +# Main file +SRC=example.c +OUTPUT=example + +## Dependencies +SQUIGGLE=../../squiggle.c +SQUIGGLE_MORE=../../squiggle_more.c +MATH=-lm +OPENMP=-fopenmp +DEPS=$(SQUIGGLE) $(SQUIGGLE_MORE) $(MATH) $(OPENMP) + +## Flags +# DEBUG=-fsanitize=address,undefined +# DEBUG=-g +DEBUG= +WARN=-Wall -Wextra -Wdouble-promotion -Wconversion +STANDARD=-std=c99 +WARNINGS=-Wall +OPTIMIZED=-O3 #-Ofast + +## Formatter +STYLE_BLUEPRINT=webkit +FORMATTER=clang-format -i -style=$(STYLE_BLUEPRINT) + +## make all +all: + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) 00_example_template/$(SRC) $(DEPS) -o 00_example_template/$(OUTPUT) + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) 02_ci_beta/$(SRC) $(DEPS) -o 02_ci_beta/$(OUTPUT) + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) 03_ci_beta_parallel/$(SRC) $(DEPS) -o 03_ci_beta_parallel/$(OUTPUT) + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) 04_nuclear_war/$(SRC) $(DEPS) -o 04_nuclear_war/$(OUTPUT) + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) 05_burn_10kg_fat/$(SRC) $(DEPS) -o 05_burn_10kg_fat/$(OUTPUT) + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) 06_nuclear_recovery/$(SRC) $(DEPS) -o 06_nuclear_recovery/$(OUTPUT) + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) 07_algebra/$(SRC) $(DEPS) -o 07_algebra/$(OUTPUT) + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) 08_algebra_and_conversion/$(SRC) $(DEPS) -o 08_algebra_and_conversion/$(OUTPUT) + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) 09_ergonomic_algebra/$(SRC) $(DEPS) -o 09_ergonomic_algebra/$(OUTPUT) + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) 10_twitter_thread_example/$(SRC) $(DEPS) -o 10_twitter_thread_example/$(OUTPUT) + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) 11_billion_lognormals_paralell/$(SRC) $(DEPS) -o 11_billion_lognormals_paralell/$(OUTPUT) + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) 12_time_to_botec_parallel/$(SRC) $(DEPS) -o 12_time_to_botec_parallel/$(OUTPUT) + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) 13_parallelize_min/$(SRC) $(DEPS) -o 13_parallelize_min/$(OUTPUT) + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) 14_check_confidence_interval/$(SRC) $(DEPS) -o 14_check_confidence_interval/$(OUTPUT) + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) 15_time_to_botec_custom_mixture/$(SRC) $(DEPS) -o 15_time_to_botec_custom_mixture/$(OUTPUT) + +format-all: + $(FORMATTER) 00_example_template/$(SRC) + $(FORMATTER) 01_sample_from_cdf/$(SRC) + $(FORMATTER) 02_ci_beta/$(SRC) + $(FORMATTER) 03_ci_beta_parallel/$(SRC) + $(FORMATTER) 04_nuclear_war/$(SRC) + $(FORMATTER) 05_burn_10kg_fat/$(SRC) + $(FORMATTER) 06_nuclear_recovery/$(SRC) + $(FORMATTER) 07_algebra/$(SRC) + $(FORMATTER) 08_algebra_and_conversion/$(SRC) + $(FORMATTER) 09_ergonomic_algebra/$(SRC) + $(FORMATTER) 10_twitter_thread_example/$(SRC) + $(FORMATTER) 11_billion_lognormals_paralell/$(SRC) + $(FORMATTER) 12_time_to_botec_parallel/$(SRC) + $(FORMATTER) 13_parallelize_min/$(SRC) + $(FORMATTER) 14_check_confidence_interval/$(SRC) + +run-all: + 00_example_template/$(OUTPUT) + 01_sample_from_cdf/$(OUTPUT) + 02_ci_beta/$(OUTPUT) + 03_ci_beta_parallel/$(OUTPUT) + 04_nuclear_war/$(OUTPUT) + 05_burn_10kg_fat/$(OUTPUT) + 06_nuclear_recovery/$(OUTPUT) + 07_algebra/$(OUTPUT) + 08_algebra_and_conversion/$(OUTPUT) + 09_ergonomic_algebra/$(OUTPUT) + 10_twitter_thread_example/$(OUTPUT) + 11_billion_lognormals_paralell/$(OUTPUT) + 12_time_to_botec_parallel/$(OUTPUT) + 13_parallelize_min/$(OUTPUT) + 14_check_confidence_interval/$(OUTPUT) + +## make one DIR=06_nuclear_recovery +one: $(DIR)/$(SRC) + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) $(DIR)/$(SRC) $(DEPS) -o $(DIR)/$(OUTPUT) + +## make format-one DIR=06_nuclear_recovery +format-one: $(DIR)/$(SRC) + $(FORMATTER) $(DIR)/$(SRC) + +## make run-one DIR=06_nuclear_recovery +run-one: $(DIR)/$(OUTPUT) + $(DIR)/$(OUTPUT) && echo + +## make time-linux-one DIR=06_nuclear_recovery +time-linux-one: $(DIR)/$(OUTPUT) + @echo "Requires /bin/time, found on GNU/Linux systems" && echo + @echo "Running 100x and taking avg time $(DIR)/$(OUTPUT)" + @t=$$(/usr/bin/time -f "%e" -p bash -c 'for i in {1..100}; do $(DIR)/$(OUTPUT); done' 2>&1 >/dev/null | grep real | awk '{print $$2}' ); echo "scale=2; 1000 * $$t / 100" | bc | sed "s|^|Time: |" | sed 's|$$|ms|' && echo + +## e.g., make profile-linux-one DIR=06_nuclear_recovery +profile-linux-one: + echo "Requires perf, which depends on the kernel version, and might be in linux-tools package or similar" + echo "Must be run as sudo" + $(CC) $(OPTIMIZED) $(DEBUG) $(WARN) $(DIR)/$(SRC) $(DEPS) -o $(DIR)/$(OUTPUT) + # $(CC) $(SRC) $(DEPS) -o $(OUTPUT) + sudo perf record $(DIR)/$(OUTPUT) + sudo perf report + rm perf.data diff --git a/CUDA/makefile b/CUDA/makefile new file mode 100644 index 0000000..5c21cd9 --- /dev/null +++ b/CUDA/makefile @@ -0,0 +1,35 @@ +MAKEFLAGS += --no-print-directory + +## Formatter +STYLE_BLUEPRINT=webkit +FORMATTER=clang-format -i -style=$(STYLE_BLUEPRINT) + +## Time to botec +TTB=./examples/more/12_time_to_botec_parallel/example + +build-examples: + cd examples/core && make all + cd examples/more && make all + +format-examples: + cd examples/core && make format-all + cd examples/more && make format-all + +format: squiggle.c squiggle.h + $(FORMATTER) squiggle.c squiggle.h + $(FORMATTER) squiggle_more.c squiggle_more.h + +lint: + clang-tidy squiggle.c -- -lm + clang-tidy squiggle_more.c -- -lm + +profile: + sudo perf record -g ./examples/more/12_time_to_botec_parallel/example + sudo perf report + rm perf.data + sudo perf stat ./examples/more/12_time_to_botec_parallel/example + +time-linux: + gcc -O3 -Wall -Wextra -Wdouble-promotion -Wconversion examples/more/12_time_to_botec_parallel/example.c squiggle.c squiggle_more.c -lm -fopenmp -o examples/more/12_time_to_botec_parallel/example + @echo "Running 100x and taking avg time: $(TTB)" + @t=$$(/usr/bin/time -f "%e" -p bash -c 'for i in {1..100}; do OMP_PROC_BIND=TRUE $(TTB); done' 2>&1 >/dev/null | grep real | awk '{print $$2}' ); echo "scale=2; 1000 * $$t / 100" | bc | sed "s|^|Time using 16 threads: |" | sed 's|$$|ms|' && echo diff --git a/CUDA/squiggle.c b/CUDA/squiggle.c new file mode 100644 index 0000000..3f2f4d3 --- /dev/null +++ b/CUDA/squiggle.c @@ -0,0 +1,228 @@ +#include +#include +#include +#include + +// Defs +#define PI 3.14159265358979323846 // M_PI in gcc gnu99 +#define NORMAL90CONFIDENCE 1.6448536269514727 +#define UNUSED(x) (void)(x) +// ^ https://stackoverflow.com/questions/3599160/how-can-i-suppress-unused-parameter-warnings-in-c + +// Pseudo Random number generators +static uint64_t xorshift64(uint64_t* seed) +{ + // Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" + // See: + // + // , + // Also some drama: + // , + // + uint64_t x = *seed; + x ^= x << 13; + x ^= x >> 7; + x ^= x << 17; + return *seed = x; + + /* + // if one wanted to generate 32 bit ints, + // from which to generate floats, + // one could do the following: + uint32_t x = *seed; + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + return *seed = x; + */ +} + +// Distribution & sampling functions +// Unit distributions +double sample_unit_uniform(uint64_t* seed) +{ + // samples uniform from [0,1] interval. + return ((double)xorshift64(seed)) / ((double)UINT64_MAX); +} + +double sample_unit_normal(uint64_t* seed) +{ + // // See: + double u1 = sample_unit_uniform(seed); + double u2 = sample_unit_uniform(seed); + double z = sqrt(-2.0 * log(u1)) * sin(2.0 * PI * u2); + return z; +} + +// Composite distributions +double sample_uniform(double start, double end, uint64_t* seed) +{ + return sample_unit_uniform(seed) * (end - start) + start; +} + +double sample_normal(double mean, double sigma, uint64_t* seed) +{ + return (mean + sigma * sample_unit_normal(seed)); +} + +double sample_lognormal(double logmean, double logstd, uint64_t* seed) +{ + return exp(sample_normal(logmean, logstd, seed)); +} + +double sample_normal_from_90_ci(double low, double high, uint64_t* seed) +{ + // Explanation of key idea: + // 1. We know that the 90% confidence interval of the unit normal is + // [-1.6448536269514722, 1.6448536269514722] + // see e.g.: https://stackoverflow.com/questions/20626994/how-to-calculate-the-inverse-of-the-normal-cumulative-distribution-function-in-p + // or https://www.wolframalpha.com/input?i=N%5BInverseCDF%28normal%280%2C1%29%2C+0.05%29%2C%7B%E2%88%9E%2C100%7D%5D + // 2. So if we take a unit normal and multiply it by + // L / 1.6448536269514722, its new 90% confidence interval will be + // [-L, L], i.e., length 2 * L + // 3. Instead, if we want to get a confidence interval of length L, + // we should multiply the unit normal by + // L / (2 * 1.6448536269514722) + // Meaning that its standard deviation should be multiplied by that amount + // see: https://en.wikipedia.org/wiki/Normal_distribution?lang=en#Operations_on_a_single_normal_variable + // 4. So we have learnt that Normal(0, L / (2 * 1.6448536269514722)) + // has a 90% confidence interval of length L + // 5. If we want a 90% confidence interval from high to low, + // we can set mean = (high + low)/2; the midpoint, and L = high-low, + // Normal([high + low]/2, [high - low]/(2 * 1.6448536269514722)) + double mean = (high + low) * 0.5; + double std = (high - low) / (2.0 * NORMAL90CONFIDENCE); + return sample_normal(mean, std, seed); +} + +double sample_to(double low, double high, uint64_t* seed) +{ + // Given a (positive) 90% confidence interval, + // returns a sample from a lognorma with a matching 90% c.i. + // Key idea: If we want a lognormal with 90% confidence interval [a, b] + // we need but get a normal with 90% confidence interval [log(a), log(b)]. + // Then see code for sample_normal_from_90_ci + double loglow = log(low); + double loghigh = log(high); + return exp(sample_normal_from_90_ci(loglow, loghigh, seed)); +} + +double sample_gamma(double alpha, uint64_t* seed) +{ + + // A Simple Method for Generating Gamma Variables, Marsaglia and Wan Tsang, 2001 + // https://dl.acm.org/doi/pdf/10.1145/358407.358414 + // see also the references/ folder + // Note that the Wikipedia page for the gamma distribution includes a scaling parameter + // k or beta + // https://en.wikipedia.org/wiki/Gamma_distribution + // such that gamma_k(alpha, k) = k * gamma(alpha) + // or gamma_beta(alpha, beta) = gamma(alpha) / beta + // So far I have not needed to use this, and thus the second parameter is by default 1. + if (alpha >= 1) { + double d, c, x, v, u; + d = alpha - 1.0 / 3.0; + c = 1.0 / sqrt(9.0 * d); + while (1) { + + do { + x = sample_unit_normal(seed); + v = 1.0 + c * x; + } while (v <= 0.0); + + v = v * v * v; + u = sample_unit_uniform(seed); + if (u < 1.0 - 0.0331 * (x * x * x * x)) { // Condition 1 + // the 0.0331 doesn't inspire much confidence + // however, this isn't the whole story + // by knowing that Condition 1 implies condition 2 + // we realize that this is just a way of making the algorithm faster + // i.e., of not using the logarithms + return d * v; + } + if (log(u) < 0.5 * (x * x) + d * (1.0 - v + log(v))) { // Condition 2 + return d * v; + } + } + } else { + return sample_gamma(1 + alpha, seed) * pow(sample_unit_uniform(seed), 1 / alpha); + // see note in p. 371 of https://dl.acm.org/doi/pdf/10.1145/358407.358414 + } +} + +double sample_beta(double a, double b, uint64_t* seed) +{ + // See: https://en.wikipedia.org/wiki/Gamma_distribution#Related_distributions + double gamma_a = sample_gamma(a, seed); + double gamma_b = sample_gamma(b, seed); + return gamma_a / (gamma_a + gamma_b); +} + +double sample_laplace(double successes, double failures, uint64_t* seed) +{ + // see + return sample_beta(successes + 1, failures + 1, seed); +} + +// Array helpers +double array_sum(double* array, int length) +{ + double sum = 0.0; + for (int i = 0; i < length; i++) { + sum += array[i]; + } + return sum; +} + +void array_cumsum(double* array_to_sum, double* 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]; + } +} + +double array_mean(double* array, int length) +{ + double sum = array_sum(array, length); + return sum / length; +} + +double array_std(double* array, int length) +{ + double mean = array_mean(array, length); + double std = 0.0; + for (int i = 0; i < length; i++) { + std += (array[i] - mean) * (array[i] - mean); + } + std = sqrt(std / length); + return std; +} + +// Mixture function +double sample_mixture(double (*samplers[])(uint64_t*), double* weights, int n_dists, uint64_t* seed) +{ + // Sample from samples with frequency proportional to their weights. + double sum_weights = array_sum(weights, n_dists); + double* cumsummed_normalized_weights = (double*)malloc((size_t)n_dists * sizeof(double)); + 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; + } + + double result; + int result_set_flag = 0; + double p = sample_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/CUDA/squiggle.h b/CUDA/squiggle.h new file mode 100644 index 0000000..100ea68 --- /dev/null +++ b/CUDA/squiggle.h @@ -0,0 +1,37 @@ +#ifndef SQUIGGLE_C_CORE +#define SQUIGGLE_C_CORE + +// uint64_t header +#include + +// Pseudo Random number generator +uint64_t xorshift64(uint64_t* seed); + +// Basic distribution sampling functions +double sample_unit_uniform(uint64_t* seed); +double sample_unit_normal(uint64_t* seed); + +// Composite distribution sampling functions +double sample_uniform(double start, double end, uint64_t* seed); +double sample_normal(double mean, double sigma, uint64_t* seed); +double sample_lognormal(double logmean, double logsigma, uint64_t* seed); +double sample_normal_from_90_ci(double low, double high, uint64_t* seed); +double sample_to(double low, double high, uint64_t* seed); + +double sample_gamma(double alpha, uint64_t* seed); +double sample_beta(double a, double b, uint64_t* seed); +double sample_laplace(double successes, double failures, uint64_t* seed); + +// Array helpers +double array_sum(double* array, int length); +void array_cumsum(double* array_to_sum, double* array_cumsummed, int length); +double array_mean(double* array, int length); +double array_std(double* array, int length); + +// Mixture function +double sample_mixture(double (*samplers[])(uint64_t*), double* weights, int n_dists, uint64_t* seed); + +// Macro to mute "unused variable" warning when -Wall -Wextra is enabled. Useful for nested functions +#define UNUSED(x) (void)(x) + +#endif diff --git a/CUDA/squiggle_more.c b/CUDA/squiggle_more.c new file mode 100644 index 0000000..4441ce2 --- /dev/null +++ b/CUDA/squiggle_more.c @@ -0,0 +1,459 @@ +#include "squiggle.h" +#include +#include +#include +#include +#include +#include +#include +#include // memcpy + +/* Cache optimizations */ +#define CACHE_LINE_SIZE 64 +// getconf LEVEL1_DCACHE_LINESIZE +// +typedef struct seed_cache_box_t { + uint64_t seed; + char padding[CACHE_LINE_SIZE - sizeof(uint64_t)]; + // Cache line size is 64 *bytes*, uint64_t is 64 *bits* (8 bytes). Different units! +} seed_cache_box; +// This avoids "false sharing", i.e., different threads competing for the same cache line +// Dealing with this shaves 4ms from a 12ms process, or a third of runtime +// + +/* Parallel sampler */ +void sampler_parallel(double (*sampler)(uint64_t* seed), double* results, int n_threads, int n_samples) +{ + + // Terms of the division: + // a = b * quotient + reminder + // a = b * (a/b) + (a%b) + // dividend: a + // divisor: b + // quotient = a/b + // reminder = a%b + // "divisor's multiple" := b*(a/b) + + // now, we have n_samples and n_threads + // to make our life easy, each thread will have a number of samples of: a/b (quotient) + // and we'll compute the remainder of samples separately + // to possibly do by Jorge: improve so that the remainder is included in the threads + + int quotient = n_samples / n_threads; + int divisor_multiple = quotient * n_threads; + + // uint64_t** seeds = malloc((size_t)n_threads * sizeof(uint64_t*)); + seed_cache_box* cache_box = (seed_cache_box*)malloc(sizeof(seed_cache_box) * (size_t)n_threads); + // seed_cache_box cache_box[n_threads]; // we could use the C stack. On normal linux machines, it's 8MB ($ ulimit -s). However, it doesn't quite feel right. + srand(1); + for (int i = 0; i < n_threads; i++) { + // Constraints: + // - xorshift can't start with 0 + // - the seeds should be reasonably separated and not correlated + cache_box[i].seed = (uint64_t)rand() * (UINT64_MAX / RAND_MAX); + + // Other initializations tried: + // *seeds[i] = 1 + i; + // *seeds[i] = (i + 0.5)*(UINT64_MAX/n_threads); + // *seeds[i] = (i + 0.5)*(UINT64_MAX/n_threads) + constant * i; + } + + int i; +#pragma omp parallel private(i) + { +#pragma omp for + for (i = 0; i < n_threads; i++) { + // It's possible I don't need the for, and could instead call omp + // in some different way and get the thread number with omp_get_thread_num() + int lower_bound_inclusive = i * quotient; + int upper_bound_not_inclusive = ((i + 1) * quotient); // note the < in the for loop below, + + for (int j = lower_bound_inclusive; j < upper_bound_not_inclusive; j++) { + results[j] = sampler(&(cache_box[i].seed)); + /* + t starts at 0 and ends at T + at t=0, + thread i accesses: results[i*quotient +0], + thread i+1 acccesses: results[(i+1)*quotient +0] + at t=T + thread i accesses: results[(i+1)*quotient -1] + thread i+1 acccesses: results[(i+2)*quotient -1] + The results[j] that are directly adjacent are + results[(i+1)*quotient -1] (accessed by thread i at time T) + results[(i+1)*quotient +0] (accessed by thread i+1 at time 0) + and these are themselves adjacent to + results[(i+1)*quotient -2] (accessed by thread i at time T-1) + results[(i+1)*quotient +1] (accessed by thread i+1 at time 2) + If T is large enough, which it is, two threads won't access the same + cache line at the same time. + Pictorially: + at t=0 ....i.........I......... + at t=T .............i.........I + and the two never overlap + Note that results[j] is a double, a double has 8 bytes (64 bits) + 8 doubles fill a cache line of 64 bytes. + So we specifically won't get problems as long as n_samples/n_threads > 8 + n_threads is normally 16, so n_samples > 128 + Note also that this is only a problem in terms of speed, if n_samples<128 + the results are still computed, it'll just be slower + */ + } + } + } + for (int j = divisor_multiple; j < n_samples; j++) { + results[j] = sampler(&(cache_box[0].seed)); + // we can just reuse a seed, + // this isn't problematic because we;ve now stopped doing multithreading + } + + free(cache_box); +} + +/* Get confidence intervals, given a sampler */ + +typedef struct ci_t { + double low; + double high; +} ci; + +inline static void swp(int i, int j, double xs[]) +{ + double tmp = xs[i]; + xs[i] = xs[j]; + xs[j] = tmp; +} + +static int partition(int low, int high, double xs[], int length) +{ + if (low > high || high >= length) { + printf("Invariant violated for function partition in %s (%d)", __FILE__, __LINE__); + exit(1); + } + // Note: the scratchpad/ folder in commit 578bfa27 has printfs sprinkled throughout + int pivot = low + (int)floor((high - low) / 2); + double pivot_value = xs[pivot]; + swp(pivot, high, xs); + int gt = low; /* This pointer will iterate until finding an element which is greater than the pivot. Then it will move elements that are smaller before it--more specifically, it will move elements to its position and then increment. As a result all elements between gt and i will be greater than the pivot. */ + for (int i = low; i < high; i++) { + if (xs[i] < pivot_value) { + swp(gt, i, xs); + gt++; + } + } + swp(high, gt, xs); + return gt; +} + +static double quickselect(int k, double xs[], int n) +{ + // https://en.wikipedia.org/wiki/Quickselect + + double* ys = malloc((size_t)n * sizeof(double)); + memcpy(ys, xs, (size_t)n * sizeof(double)); + // ^: don't rearrange item order in the original array + + int low = 0; + int high = n - 1; + for (;;) { + if (low == high) { + double result = ys[low]; + free(ys); + return result; + } + int pivot = partition(low, high, ys, n); + if (pivot == k) { + double result = ys[pivot]; + free(ys); + return result; + } else if (k < pivot) { + high = pivot - 1; + } else { + low = pivot + 1; + } + } +} + +ci array_get_ci(ci interval, double* xs, int n) +{ + + int low_k = (int)floor(interval.low * n); + int high_k = (int)ceil(interval.high * n); + ci result = { + .low = quickselect(low_k, xs, n), + .high = quickselect(high_k, xs, n), + }; + return result; +} +ci array_get_90_ci(double xs[], int n) +{ + return array_get_ci((ci) { .low = 0.05, .high = 0.95 }, xs, n); +} + +double array_get_median(double xs[], int n) +{ + int median_k = (int)floor(0.5 * n); + return quickselect(median_k, xs, n); +} + +/* array print: potentially useful for debugging */ +void array_print(double xs[], int n) +{ + printf("["); + for (int i = 0; i < n - 1; i++) { + printf("%f, ", xs[i]); + } + printf("%f", xs[n - 1]); + printf("]\n"); +} + +void array_print_stats(double xs[], int n) +{ + ci ci_90 = array_get_ci((ci) { .low = 0.05, .high = 0.95 }, xs, n); + ci ci_80 = array_get_ci((ci) { .low = 0.1, .high = 0.9 }, xs, n); + ci ci_50 = array_get_ci((ci) { .low = 0.25, .high = 0.75 }, xs, n); + double median = array_get_median(xs, n); + double mean = array_mean(xs, n); + double std = array_std(xs, n); + printf("| Statistic | Value |\n" + "| --- | --- |\n" + "| Mean | %lf |\n" + "| Median | %lf |\n" + "| Std | %lf |\n" + "| 90%% confidence interval | %lf to %lf |\n" + "| 80%% confidence interval | %lf to %lf |\n" + "| 50%% confidence interval | %lf to %lf |\n", + mean, median, std, ci_90.low, ci_90.high, ci_80.low, ci_80.high, ci_50.low, ci_50.high); +} + +void array_print_histogram(double* xs, int n_samples, int n_bins) +{ + // Interface inspired by + if (n_bins <= 1) { + fprintf(stderr, "Number of bins must be greater than 1.\n"); + return; + } else if (n_samples <= 1) { + fprintf(stderr, "Number of samples must be higher than 1.\n"); + return; + } + + int* bins = (int*)calloc((size_t)n_bins, sizeof(int)); + if (bins == NULL) { + fprintf(stderr, "Memory allocation for bins failed.\n"); + return; + } + + // Find the minimum and maximum values from the samples + double min_value = xs[0], max_value = xs[0]; + for (int i = 0; i < n_samples; i++) { + if (xs[i] < min_value) { + min_value = xs[i]; + } + if (xs[i] > max_value) { + max_value = xs[i]; + } + } + + // Avoid division by zero for a single unique value + if (min_value == max_value) { + max_value++; + } + + // Calculate bin width + double bin_width = (max_value - min_value) / n_bins; + + // Fill the bins with sample counts + for (int i = 0; i < n_samples; i++) { + int bin_index = (int)((xs[i] - min_value) / bin_width); + if (bin_index == n_bins) { + bin_index--; // Last bin includes max_value + } + bins[bin_index]++; + } + + // Calculate the scaling factor based on the maximum bin count + int max_bin_count = 0; + for (int i = 0; i < n_bins; i++) { + if (bins[i] > max_bin_count) { + max_bin_count = bins[i]; + } + } + const int MAX_WIDTH = 50; // Adjust this to your terminal width + double scale = max_bin_count > MAX_WIDTH ? (double)MAX_WIDTH / max_bin_count : 1.0; + + // Print the histogram + for (int i = 0; i < n_bins; i++) { + double bin_start = min_value + i * bin_width; + double bin_end = bin_start + bin_width; + + int decimalPlaces = 1; + if ((0 < bin_width) && (bin_width < 1)) { + int magnitude = (int)floor(log10(bin_width)); + decimalPlaces = -magnitude; + decimalPlaces = decimalPlaces > 10 ? 10 : decimalPlaces; + } + printf("[%*.*f, %*.*f", 4 + decimalPlaces, decimalPlaces, bin_start, 4 + decimalPlaces, decimalPlaces, bin_end); + char interval_delimiter = ')'; + if (i == (n_bins - 1)) { + interval_delimiter = ']'; // last bucket is inclusive + } + printf("%c: ", interval_delimiter); + + int marks = (int)(bins[i] * scale); + for (int j = 0; j < marks; j++) { + printf("█"); + } + printf(" %d\n", bins[i]); + } + + // Free the allocated memory for bins + free(bins); +} + +void array_print_90_ci_histogram(double* xs, int n_samples, int n_bins) +{ + // Code duplicated from previous function + // I'll consider simplifying it at some future point + // Possible ideas: + // - having only one function that takes any confidence interval? + // - having a utility function that is called by both functions? + ci ci_90 = array_get_90_ci(xs, n_samples); + + if (n_bins <= 1) { + fprintf(stderr, "Number of bins must be greater than 1.\n"); + return; + } else if (n_samples <= 10) { + fprintf(stderr, "Number of samples must be higher than 10.\n"); + return; + } + + int* bins = (int*)calloc((size_t)n_bins, sizeof(int)); + if (bins == NULL) { + fprintf(stderr, "Memory allocation for bins failed.\n"); + return; + } + + double min_value = ci_90.low, max_value = ci_90.high; + + // Avoid division by zero for a single unique value + if (min_value == max_value) { + max_value++; + } + double bin_width = (max_value - min_value) / n_bins; + + // Fill the bins with sample counts + int below_min = 0, above_max = 0; + for (int i = 0; i < n_samples; i++) { + if (xs[i] < min_value) { + below_min++; + } else if (xs[i] > max_value) { + above_max++; + } else { + int bin_index = (int)((xs[i] - min_value) / bin_width); + if (bin_index == n_bins) { + bin_index--; // Last bin includes max_value + } + bins[bin_index]++; + } + } + + // Calculate the scaling factor based on the maximum bin count + int max_bin_count = 0; + for (int i = 0; i < n_bins; i++) { + if (bins[i] > max_bin_count) { + max_bin_count = bins[i]; + } + } + const int MAX_WIDTH = 40; // Adjust this to your terminal width + double scale = max_bin_count > MAX_WIDTH ? (double)MAX_WIDTH / max_bin_count : 1.0; + + // Print the histogram + int decimalPlaces = 1; + if ((0 < bin_width) && (bin_width < 1)) { + int magnitude = (int)floor(log10(bin_width)); + decimalPlaces = -magnitude; + decimalPlaces = decimalPlaces > 10 ? 10 : decimalPlaces; + } + printf("(%*s, %*.*f): ", 6 + decimalPlaces, "-∞", 4 + decimalPlaces, decimalPlaces, min_value); + int marks_below_min = (int)(below_min * scale); + for (int j = 0; j < marks_below_min; j++) { + printf("█"); + } + printf(" %d\n", below_min); + for (int i = 0; i < n_bins; i++) { + double bin_start = min_value + i * bin_width; + double bin_end = bin_start + bin_width; + + printf("[%*.*f, %*.*f", 4 + decimalPlaces, decimalPlaces, bin_start, 4 + decimalPlaces, decimalPlaces, bin_end); + char interval_delimiter = ')'; + if (i == (n_bins - 1)) { + interval_delimiter = ']'; // last bucket is inclusive + } + printf("%c: ", interval_delimiter); + + int marks = (int)(bins[i] * scale); + for (int j = 0; j < marks; j++) { + printf("█"); + } + printf(" %d\n", bins[i]); + } + printf("(%*.*f, %*s): ", 4 + decimalPlaces, decimalPlaces, max_value, 6 + decimalPlaces, "+∞"); + int marks_above_max = (int)(above_max * scale); + for (int j = 0; j < marks_above_max; j++) { + printf("█"); + } + printf(" %d\n", above_max); + + // Free the allocated memory for bins + free(bins); +} + +/* Algebra manipulations */ + +#define NORMAL90CONFIDENCE 1.6448536269514727 + +typedef struct normal_params_t { + double mean; + double std; +} normal_params; + +normal_params algebra_sum_normals(normal_params a, normal_params b) +{ + normal_params result = { + .mean = a.mean + b.mean, + .std = sqrt((a.std * a.std) + (b.std * b.std)), + }; + return result; +} + +typedef struct lognormal_params_t { + double logmean; + double logstd; +} lognormal_params; + +lognormal_params algebra_product_lognormals(lognormal_params a, lognormal_params b) +{ + lognormal_params result = { + .logmean = a.logmean + b.logmean, + .logstd = sqrt((a.logstd * a.logstd) + (b.logstd * b.logstd)), + }; + return result; +} + +lognormal_params convert_ci_to_lognormal_params(ci x) +{ + double loghigh = log(x.high); + double loglow = log(x.low); + double logmean = (loghigh + loglow) / 2.0; + double logstd = (loghigh - loglow) / (2.0 * NORMAL90CONFIDENCE); + lognormal_params result = { .logmean = logmean, .logstd = logstd }; + return result; +} + +ci convert_lognormal_params_to_ci(lognormal_params y) +{ + double h = y.logstd * NORMAL90CONFIDENCE; + double loghigh = y.logmean + h; + double loglow = y.logmean - h; + ci result = { .low = exp(loglow), .high = exp(loghigh) }; + return result; +} diff --git a/CUDA/squiggle_more.h b/CUDA/squiggle_more.h new file mode 100644 index 0000000..6ff601b --- /dev/null +++ b/CUDA/squiggle_more.h @@ -0,0 +1,42 @@ +#ifndef SQUIGGLE_C_EXTRA +#define SQUIGGLE_C_EXTRA + +/* Parallel sampling */ +void sampler_parallel(double (*sampler)(uint64_t* seed), double* results, int n_threads, int n_samples); + +/* Stats */ +double array_get_median(double xs[], int n); +typedef struct ci_t { + double low; + double high; +} ci; +ci array_get_ci(ci interval, double* xs, int n); +ci array_get_90_ci(double xs[], int n); + +void array_print_stats(double xs[], int n); +void array_print_histogram(double* xs, int n_samples, int n_bins); +void array_print_90_ci_histogram(double* xs, int n, int n_bins); + +/* Algebra manipulations */ + +typedef struct normal_params_t { + double mean; + double std; +} normal_params; +normal_params algebra_sum_normals(normal_params a, normal_params b); + +typedef struct lognormal_params_t { + double logmean; + double logstd; +} lognormal_params; +lognormal_params algebra_product_lognormals(lognormal_params a, lognormal_params b); + +lognormal_params convert_ci_to_lognormal_params(ci x); +ci convert_lognormal_params_to_ci(lognormal_params y); + +/* Utilities */ + +#define THOUSAND 1000 +#define MILLION 1000000 + +#endif diff --git a/CUDA/test/makefile b/CUDA/test/makefile new file mode 100644 index 0000000..af3137a --- /dev/null +++ b/CUDA/test/makefile @@ -0,0 +1,56 @@ +# Interface: +# make +# make build +# make format +# make run + +# Compiler +CC=gcc +# CC=tcc # <= faster compilation + +# Main file +SRC=test.c ../squiggle.c +OUTPUT=test + +## Dependencies +MATH=-lm + +## Flags +DEBUG= #'-g' +STANDARD=-std=c99 +WARNINGS=-Wall +OPTIMIZED=-O3 #-Ofast +# OPENMP=-fopenmp + +## Formatter +STYLE_BLUEPRINT=webkit +FORMATTER=clang-format -i -style=$(STYLE_BLUEPRINT) + +## make build +build: $(SRC) + $(CC) $(OPTIMIZED) $(DEBUG) $(SRC) $(MATH) -o $(OUTPUT) + +format: $(SRC) + $(FORMATTER) $(SRC) + +run: $(SRC) $(OUTPUT) + ./$(OUTPUT) + +verify: $(SRC) $(OUTPUT) + ./$(OUTPUT) | grep "NOT passed" -A 2 --group-separator='' || true + +time-linux: + @echo "Requires /bin/time, found on GNU/Linux systems" && echo + + @echo "Running 100x and taking avg time $(OUTPUT)" + @t=$$(/usr/bin/time -f "%e" -p bash -c 'for i in {1..100}; do $(OUTPUT); done' 2>&1 >/dev/null | grep real | awk '{print $$2}' ); echo "scale=2; 1000 * $$t / 100" | bc | sed "s|^|Time using 1 thread: |" | sed 's|$$|ms|' && echo + +## Profiling + +profile-linux: + echo "Requires perf, which depends on the kernel version, and might be in linux-tools package or similar" + echo "Must be run as sudo" + $(CC) $(SRC) $(MATH) -o $(OUTPUT) + sudo perf record ./$(OUTPUT) + sudo perf report + rm perf.data diff --git a/CUDA/test/test b/CUDA/test/test new file mode 100755 index 0000000000000000000000000000000000000000..495baccf697bb0f4c1781e6ce4b3ec19ca9a4f28 GIT binary patch literal 26288 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 literal 0 HcmV?d00001 diff --git a/CUDA/test/test.c b/CUDA/test/test.c new file mode 100644 index 0000000..cb9fab3 --- /dev/null +++ b/CUDA/test/test.c @@ -0,0 +1,328 @@ +#include "../squiggle.h" +#include +#include +#include +#include + +#define TOLERANCE 5.0 / 1000.0 +#define MAX_NAME_LENGTH 500 + +// Structs + +struct array_expectations { + double* array; + int n; + char* name; + double expected_mean; + double expected_std; + double tolerance; +}; + +void test_array_expectations(struct array_expectations e) +{ + double mean = array_mean(e.array, e.n); + double delta_mean = mean - e.expected_mean; + + double std = array_std(e.array, e.n); + double delta_std = std - e.expected_std; + + if ((fabs(delta_mean) / fabs(mean) > e.tolerance) && (fabs(delta_mean) > e.tolerance)) { + printf("[-] Mean test for %s NOT passed.\n", e.name); + printf("Mean of %s: %f, vs expected mean: %f\n", e.name, mean, e.expected_mean); + printf("delta: %f, relative delta: %f\n", delta_mean, delta_mean / fabs(mean)); + } else { + printf("[x] Mean test for %s PASSED\n", e.name); + } + + if ((fabs(delta_std) / fabs(std) > e.tolerance) && (fabs(delta_std) > e.tolerance)) { + printf("[-] Std test for %s NOT passed.\n", e.name); + printf("Std of %s: %f, vs expected std: %f\n", e.name, std, e.expected_std); + printf("delta: %f, relative delta: %f\n", delta_std, delta_std / fabs(std)); + } else { + printf("[x] Std test for %s PASSED\n", e.name); + } + + printf("\n"); +} + +// Test unit uniform +void test_unit_uniform(uint64_t* seed) +{ + int n = 1000 * 1000; + double* unit_uniform_array = malloc(sizeof(double) * n); + + for (int i = 0; i < n; i++) { + unit_uniform_array[i] = sample_unit_uniform(seed); + } + + struct array_expectations expectations = { + .array = unit_uniform_array, + .n = n, + .name = "unit uniform", + .expected_mean = 0.5, + .expected_std = sqrt(1.0 / 12.0), + .tolerance = TOLERANCE, + }; + + test_array_expectations(expectations); + free(unit_uniform_array); +} + +// Test uniforms +void test_uniform(double start, double end, uint64_t* seed) +{ + int n = 1000 * 1000; + double* uniform_array = malloc(sizeof(double) * n); + + for (int i = 0; i < n; i++) { + uniform_array[i] = sample_uniform(start, end, seed); + } + + char* name = malloc(MAX_NAME_LENGTH * sizeof(char)); + snprintf(name, MAX_NAME_LENGTH, "[%f, %f] uniform", start, end); + struct array_expectations expectations = { + .array = uniform_array, + .n = n, + .name = name, + .expected_mean = (start + end) / 2, + .expected_std = sqrt(1.0 / 12.0) * fabs(end - start), + .tolerance = fabs(end - start) * TOLERANCE, + }; + + test_array_expectations(expectations); + free(name); + free(uniform_array); +} + +// Test unit normal +void test_unit_normal(uint64_t* seed) +{ + int n = 1000 * 1000; + double* unit_normal_array = malloc(sizeof(double) * n); + + for (int i = 0; i < n; i++) { + unit_normal_array[i] = sample_unit_normal(seed); + } + + struct array_expectations expectations = { + .array = unit_normal_array, + .n = n, + .name = "unit normal", + .expected_mean = 0, + .expected_std = 1, + .tolerance = TOLERANCE, + }; + + test_array_expectations(expectations); + free(unit_normal_array); +} + +// Test normal +void test_normal(double mean, double std, uint64_t* seed) +{ + int n = 10 * 1000 * 1000; + double* normal_array = malloc(sizeof(double) * n); + + for (int i = 0; i < n; i++) { + normal_array[i] = sample_normal(mean, std, seed); + } + + char* name = malloc(MAX_NAME_LENGTH * sizeof(char)); + snprintf(name, MAX_NAME_LENGTH, "normal(%f, %f)", mean, std); + struct array_expectations expectations = { + .array = normal_array, + .n = n, + .name = name, + .expected_mean = mean, + .expected_std = std, + .tolerance = TOLERANCE, + }; + + test_array_expectations(expectations); + free(name); + free(normal_array); +} + +// Test lognormal +void test_lognormal(double logmean, double logstd, uint64_t* seed) +{ + int n = 10 * 1000 * 1000; + double* lognormal_array = malloc(sizeof(double) * n); + + for (int i = 0; i < n; i++) { + lognormal_array[i] = sample_lognormal(logmean, logstd, seed); + } + + char* name = malloc(MAX_NAME_LENGTH * sizeof(char)); + snprintf(name, MAX_NAME_LENGTH, "lognormal(%f, %f)", logmean, logstd); + struct array_expectations expectations = { + .array = lognormal_array, + .n = n, + .name = name, + .expected_mean = exp(logmean + pow(logstd, 2) / 2), + .expected_std = sqrt((exp(pow(logstd, 2)) - 1) * exp(2 * logmean + pow(logstd, 2))), + .tolerance = TOLERANCE, + }; + + test_array_expectations(expectations); + free(name); + free(lognormal_array); +} + +// Test lognormal to +void test_to(double low, double high, uint64_t* seed) +{ + int n = 10 * 1000 * 1000; + double* lognormal_array = malloc(sizeof(double) * n); + + for (int i = 0; i < n; i++) { + lognormal_array[i] = sample_to(low, high, seed); + } + + + char* name = malloc(MAX_NAME_LENGTH * sizeof(char)); + snprintf(name, MAX_NAME_LENGTH, "to(%f, %f)", low, high); + + const double NORMAL95CONFIDENCE = 1.6448536269514722; + double loglow = logf(low); + double loghigh = logf(high); + double logmean = (loglow + loghigh) / 2; + double logstd = (loghigh - loglow) / (2.0 * NORMAL95CONFIDENCE); + + struct array_expectations expectations = { + .array = lognormal_array, + .n = n, + .name = name, + .expected_mean = exp(logmean + pow(logstd, 2) / 2), + .expected_std = sqrt((exp(pow(logstd, 2)) - 1) * exp(2 * logmean + pow(logstd, 2))), + .tolerance = TOLERANCE, + }; + + test_array_expectations(expectations); + free(name); + free(lognormal_array); +} + +// Test beta + +void test_beta(double a, double b, uint64_t* seed) +{ + int n = 10 * 1000 * 1000; + double* beta_array = malloc(sizeof(double) * n); + + for (int i = 0; i < n; i++) { + beta_array[i] = sample_beta(a, b, seed); + } + + char* name = malloc(MAX_NAME_LENGTH * sizeof(char)); + snprintf(name, MAX_NAME_LENGTH, "beta(%f, %f)", a, b); + struct array_expectations expectations = { + .array = beta_array, + .n = n, + .name = name, + .expected_mean = a / (a + b), + .expected_std = sqrt((a * b) / (pow(a + b, 2) * (a + b + 1))), + .tolerance = TOLERANCE, + }; + + test_array_expectations(expectations); + free(name); +} + +int main() +{ + // set randomness seed + uint64_t* seed = malloc(sizeof(uint64_t)); + *seed = 1000; // xorshift can't start with a seed of 0 + + printf("Testing unit uniform\n"); + test_unit_uniform(seed); + + printf("Testing small uniforms\n"); + for (int i = 0; i < 100; i++) { + double start = sample_uniform(-10, 10, seed); + double end = sample_uniform(-10, 10, seed); + if (end > start) { + test_uniform(start, end, seed); + } + } + + printf("Testing wide uniforms\n"); + for (int i = 0; i < 100; i++) { + double start = sample_uniform(-1000 * 1000, 1000 * 1000, seed); + double end = sample_uniform(-1000 * 1000, 1000 * 1000, seed); + if (end > start) { + test_uniform(start, end, seed); + } + } + + printf("Testing unit normal\n"); + test_unit_normal(seed); + + printf("Testing small normals\n"); + for (int i = 0; i < 100; i++) { + double mean = sample_uniform(-10, 10, seed); + double std = sample_uniform(0, 10, seed); + if (std > 0) { + test_normal(mean, std, seed); + } + } + + printf("Testing larger normals\n"); + for (int i = 0; i < 100; i++) { + double mean = sample_uniform(-1000 * 1000, 1000 * 1000, seed); + double std = sample_uniform(0, 1000 * 1000, seed); + if (std > 0) { + test_normal(mean, std, seed); + } + } + + printf("Testing smaller lognormals\n"); + for (int i = 0; i < 100; i++) { + double mean = sample_uniform(-1, 1, seed); + double std = sample_uniform(0, 1, seed); + if (std > 0) { + test_lognormal(mean, std, seed); + } + } + + printf("Testing larger lognormals\n"); + for (int i = 0; i < 100; i++) { + double mean = sample_uniform(-1, 5, seed); + double std = sample_uniform(0, 5, seed); + if (std > 0) { + test_lognormal(mean, std, seed); + } + } + + printf("Testing lognormals — sample_to(low, high) syntax\n"); + for (int i = 0; i < 100; i++) { + double low = sample_uniform(0, 1000 * 1000, seed); + double high = sample_uniform(0, 1000 * 1000, seed); + if (low < high) { + test_to(low, high, seed); + } + } + // Bonus example + test_to(10, 10 * 1000, seed); + + printf("Testing beta distribution\n"); + for (int i = 0; i < 100; i++) { + double a = sample_uniform(0, 1000, seed); + double b = sample_uniform(0, 1000, seed); + if ((a > 0) && (b > 0)) { + test_beta(a, b, seed); + } + } + + printf("Testing larger beta distributions\n"); + for (int i = 0; i < 100; i++) { + double a = sample_uniform(0, 1000 * 1000, seed); + double b = sample_uniform(0, 1000 * 1000, seed); + if ((a > 0) && (b > 0)) { + test_beta(a, b, seed); + } + } + + free(seed); +}