aboutsummaryrefslogtreecommitdiff
path: root/src/km-init.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/km-init.c')
-rw-r--r--src/km-init.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/src/km-init.c b/src/km-init.c
new file mode 100644
index 0000000..280ea81
--- /dev/null
+++ b/src/km-init.c
@@ -0,0 +1,85 @@
+#include <stdbool.h> // bool
+#include <stddef.h> // size_t
+#include <string.h> // strcmp()
+#include "util.h"
+#include "km.h"
+
+typedef bool (*km_init_fn_t)(
+ km_set_t *,
+ const size_t,
+ const km_set_t *,
+ km_rand_t *
+);
+
+bool km_init_rand(km_set_t *, const size_t, const km_set_t *, km_rand_t *);
+bool km_init_forgy(km_set_t *, const size_t, const km_set_t *, km_rand_t *);
+bool km_init_kmeans(km_set_t *, const size_t, const km_set_t *, km_rand_t *);
+
+static const struct {
+ const km_init_type_t type;
+ const char * const name;
+ const km_init_fn_t init;
+} TYPES[] = {{
+ .name = "rand",
+ .type = KM_INIT_TYPE_RAND,
+ .init = km_init_rand,
+}, {
+ .name = "forgy",
+ .type = KM_INIT_TYPE_FORGY,
+ .init = km_init_forgy,
+}, {
+ .name = "kmeans",
+ .type = KM_INIT_TYPE_KMEANS,
+ .init = km_init_kmeans,
+}};
+
+#define NUM_TYPES (sizeof(TYPES) / sizeof(TYPES[0]))
+
+km_init_type_t
+km_init_get_type(
+ const char * const s
+) {
+ // find init method
+ for (size_t i = 0; i < NUM_TYPES; i++) {
+ if (!strcmp(s, TYPES[i].name)) {
+ // return type
+ return TYPES[i].type;
+ }
+ }
+
+ // return failure
+ return KM_INIT_TYPE_LAST;
+}
+
+static km_init_fn_t
+get_init_func(
+ const km_init_type_t type
+) {
+ // find init method
+ for (size_t i = 0; i < NUM_TYPES; i++) {
+ if (type == TYPES[i].type) {
+ // return init func
+ return TYPES[i].init;
+ }
+ }
+
+ // return failure
+ return NULL;
+}
+
+bool
+km_init(
+ km_set_t * const cs,
+ const km_init_type_t init_type,
+ const size_t num_clusters,
+ const km_set_t * const set,
+ km_rand_t * const rs
+) {
+ km_init_fn_t init_fn = get_init_func(init_type);
+ if (!init_fn) {
+ die("unknown cluster init method");
+ }
+
+ // call init, return result
+ return init_fn(cs, num_clusters, set, rs);
+}