aboutsummaryrefslogtreecommitdiff
path: root/src/random.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/random.c')
-rw-r--r--src/random.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/random.c b/src/random.c
index 0112ebd..482e102 100644
--- a/src/random.c
+++ b/src/random.c
@@ -16,6 +16,10 @@
#include "random.h"
#include <math.h>
+#include <gsl/gsl_rng.h>
+#include <gsl/gsl_randist.h>
+
+static gsl_rng *r;
double randn(void)
{
@@ -44,3 +48,39 @@ void rand_sphere(double *dir)
dir[1] = sin(theta)*sin(phi);
dir[2] = cos(theta);
}
+
+/* Randomly choose `k` elements from array `src` with `n` elements with
+ * probabilities proportional to `w`. The elements are sampled without
+ * replacement and placed into the `dest` array. */
+void ran_choose_weighted(int *dest, double *w, size_t k, int *src, size_t n)
+{
+ int i, j;
+ gsl_ran_discrete_t *g;
+ size_t index, result;
+ int duplicate;
+
+ if (!r)
+ r = gsl_rng_alloc(gsl_rng_default);
+
+ g = gsl_ran_discrete_preproc(n, w);
+
+ i = 0;
+ while (i < k) {
+ index = gsl_ran_discrete(r, g);
+
+ result = src[index];
+
+ duplicate = 0;
+ for (j = 0; j < i; j++) {
+ if (result == dest[j]) {
+ duplicate = 1;
+ break;
+ }
+ }
+
+ if (!duplicate) dest[i++] = result;
+ }
+
+ gsl_ran_discrete_free(g);
+}
+