aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--km-rand.c33
-rw-r--r--km-set.c47
-rw-r--r--km.h13
3 files changed, 91 insertions, 2 deletions
diff --git a/km-rand.c b/km-rand.c
index fcc6a74..1410861 100644
--- a/km-rand.c
+++ b/km-rand.c
@@ -12,6 +12,16 @@ km_rand_fill(
return rs->cbs->fill(rs, num_floats, floats);
}
+// fill buffer with N random size_ts
+bool
+km_rand_fill_sizes(
+ km_rand_t * const rs,
+ const size_t num_sizes,
+ size_t * const sizes
+) {
+ return rs->cbs->fill_sizes(rs, num_sizes, sizes);
+}
+
// finalize random source
void
km_rand_fini(
@@ -40,11 +50,30 @@ system_on_fill(
return true;
}
+// fill sizes callback for system random source
+static bool
+system_on_fill_sizes(
+ km_rand_t * const rs,
+ const size_t num_sizes,
+ size_t * const sizes
+) {
+ UNUSED(rs);
+
+ // generate random size_ts
+ for (size_t i = 0; i < num_sizes; i++) {
+ sizes[i] = rand();
+ }
+
+ // return success
+ return true;
+}
+
// system random source callbacks
static const km_rand_cbs_t
SYSTEM_CBS = {
- .fill = system_on_fill,
- .fini = NULL,
+ .fill = system_on_fill,
+ .fill_sizes = system_on_fill_sizes,
+ .fini = NULL,
};
// init system random source (uses system rand())
diff --git a/km-set.c b/km-set.c
index 37a7337..535b46b 100644
--- a/km-set.c
+++ b/km-set.c
@@ -301,3 +301,50 @@ km_set_init_rand_clusters(
// add data, return result
return km_set_push(cs, num_clusters, floats, ints);
}
+
+// init a set with num_clusters clusters of shape num_floats by picking
+// random initial points from the set
+bool
+km_set_init_rand_points(
+ km_set_t * const cs,
+ const km_set_t * const set,
+ const size_t num_clusters,
+ km_rand_t * const rs
+) {
+ const size_t num_floats = set->shape.num_floats,
+ stride = sizeof(float) * num_floats;
+
+ // init cluster shape
+ const km_shape_t shape = {
+ .num_floats = num_floats,
+ .num_ints = 1,
+ };
+
+ // get random row offsets
+ size_t rows[num_clusters];
+ if (!km_rand_fill_sizes(rs, num_clusters, rows)) {
+ // return failure
+ return false;
+ }
+
+ // generate random cluster centers
+ float floats[num_floats * num_clusters];
+ for (size_t i = 0; i < num_clusters; i++) {
+ const size_t row_num = rows[i] % set->num_rows;
+ const float * const row_floats = km_set_get_row(set, row_num);
+ memcpy(floats + i * num_floats, row_floats, stride);
+ }
+
+ // FIXME: should probably be heap-allocated
+ int ints[num_clusters];
+ memset(ints, 0, sizeof(ints));
+
+ // init cluster set
+ if (!km_set_init(cs, &shape, num_clusters)) {
+ // return failure
+ return false;
+ }
+
+ // add data, return result
+ return km_set_push(cs, num_clusters, floats, ints);
+}
diff --git a/km.h b/km.h
index 82bd835..c70e13e 100644
--- a/km.h
+++ b/km.h
@@ -11,6 +11,7 @@ typedef struct km_rand_t_ km_rand_t;
// random number source callbacks
typedef struct {
_Bool (*fill)(km_rand_t * const, const size_t, float * const);
+ _Bool (*fill_sizes)(km_rand_t * const, const size_t, size_t * const);
void (*fini)(km_rand_t * const);
} km_rand_cbs_t;
@@ -23,6 +24,9 @@ struct km_rand_t_ {
// fill buffer with N random floats
_Bool km_rand_fill(km_rand_t * const, const size_t, float * const);
+// fill buffer with N random size_ts
+_Bool km_rand_fill_sizes(km_rand_t * const, const size_t, size_t * const);
+
// finalize random source
void km_rand_fini(km_rand_t * const);
@@ -82,6 +86,15 @@ _Bool km_set_init_rand_clusters(
km_rand_t *
);
+// init a set with num_clusters clusters of random points from the
+// given set
+_Bool km_set_init_rand_points(
+ km_set_t * const,
+ const km_set_t * const,
+ const size_t,
+ km_rand_t *
+);
+
typedef struct {
float d2;
size_t cluster;