From 8f1689ffb9063129bdde05132b73adc04cdfa5b7 Mon Sep 17 00:00:00 2001
From: Boris Stefanovic <owldev@bluewin.ch>
Date: Tue, 7 Jun 2022 15:29:08 +0200
Subject: [PATCH] ADD: cluster structure and beginning of logic

---
 src/cluster.c    | 81 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/cluster.h    | 46 +++++++++++++++++++++++++++
 src/distance.c   |  4 ---
 src/distance.h   |  4 ---
 src/linkedlist.c | 24 +++++++-------
 src/linkedlist.h | 36 ++++++++++-----------
 src/point.c      | 14 ++++-----
 src/point.h      | 15 +++++----
 src/vector.c     | 24 ++++++++++++++
 src/vector.h     | 10 ++++++
 10 files changed, 202 insertions(+), 56 deletions(-)
 create mode 100644 src/cluster.c
 create mode 100644 src/cluster.h

diff --git a/src/cluster.c b/src/cluster.c
new file mode 100644
index 0000000..84e6beb
--- /dev/null
+++ b/src/cluster.c
@@ -0,0 +1,81 @@
+#include "cluster.h"
+#include "vector.h"
+
+
+cluster_int_t* cluster_create_int(vector_int_t* center) {
+	cluster_int_t* cluster = malloc(sizeof(cluster_int_t));
+	if (NULL == cluster) return NULL;
+	cluster->center = center;
+	cluster->points = list_points_create_int();
+}
+
+cluster_fpt_t* cluster_create_fpt(vector_fpt_t* center) {
+	cluster_fpt_t* cluster = malloc(sizeof(cluster_fpt_t));
+	if (NULL == cluster) return NULL;
+	cluster->center = center;
+	cluster->points = list_points_create_fpt();
+}
+
+
+void cluster_destroy_int(cluster_int_t* cluster) {
+	if (NULL == cluster) return;
+	vector_destroy_int(cluster->center);
+	list_points_destroy_int(cluster->points, false);
+	free(cluster);
+}
+
+void cluster_destroy_fpt(cluster_fpt_t* cluster) {
+	if (NULL == cluster) return;
+	vector_destroy_fpt(cluster->center);
+	list_points_destroy_fpt(cluster->points, false);
+	free(cluster);
+}
+
+
+void cluster_add_point_int(cluster_int_t* cluster, point_int_t* point) {
+	//TODO
+	if (NULL == cluster || NULL == point) return;
+	if (NULL == cluster->center) {
+		cluster->center = vector_copy_int(point->vector);
+	} else {
+		vector_int_t* delta = vector_copy_int(point->vector);
+		vector_div_inplace_int(delta, cluster->points->size);
+		vector_add_inplace_int(cluster->center, *delta);
+		vector_destroy_int(delta);
+	}
+}
+
+void cluster_add_point_fpt(cluster_fpt_t* cluster, point_fpt_t* point) {
+	//TODO
+	if (NULL == cluster || NULL == point) return;
+	if (NULL == cluster->center) {
+		cluster->center = vector_copy_fpt(point->vector);
+	} else {
+		vector_fpt_t* delta = vector_copy_fpt(point->vector);
+		vector_div_inplace_fpt(delta, cluster->points->size);
+		vector_add_inplace_fpt(cluster->center, *delta);
+		vector_destroy_fpt(delta);
+	}
+}
+
+
+void cluster_update_center_int(cluster_int_t* cluster) {
+	//TODO
+}
+
+void cluster_update_center_fpt(cluster_fpt_t* cluster) {
+	//TODO
+}
+
+
+void cluster_reset_int(cluster_int_t* cluster) {
+	//TODO
+	list_points_destroy_int(cluster->points, false);
+	cluster->points = list_points_create_int();
+}
+
+void cluster_reset_fpt(cluster_fpt_t* cluster) {
+	//TODO
+	list_points_destroy_fpt(cluster->points, false);
+	cluster->points = list_points_create_fpt();
+}
diff --git a/src/cluster.h b/src/cluster.h
new file mode 100644
index 0000000..963e417
--- /dev/null
+++ b/src/cluster.h
@@ -0,0 +1,46 @@
+#ifndef PROG_KMEANS_CLUSTER_H
+#define PROG_KMEANS_CLUSTER_H
+
+#include <stdlib.h>
+#include "linkedlist.h"
+#include "point.h"
+#include "vector.h"
+
+
+typedef struct cluster_int {
+	vector_int_t* center;
+	list_points_int_t* points;
+} cluster_int_t;
+
+typedef struct cluster_fpt {
+	vector_fpt_t* center;
+	list_points_fpt_t* points;
+} cluster_fpt_t;
+
+
+cluster_int_t* cluster_create_int(vector_int_t* center);
+
+cluster_fpt_t* cluster_create_fpt(vector_fpt_t* center);
+
+
+void cluster_destroy_int(cluster_int_t* center);
+
+void cluster_destroy_fpt(cluster_fpt_t* center);
+
+
+void cluster_add_point_int(cluster_int_t* cluster, point_int_t* point);
+
+void cluster_add_point_fpt(cluster_fpt_t* cluster, point_fpt_t* point);
+
+
+void cluster_update_center_int(cluster_int_t* cluster);
+
+void cluster_update_center_fpt(cluster_fpt_t* cluster);
+
+
+void cluster_reset_int(cluster_int_t* cluster);
+
+void cluster_reset_fpt(cluster_fpt_t* cluster);
+
+
+#endif //PROG_KMEANS_CLUSTER_H
diff --git a/src/distance.c b/src/distance.c
index 1655e2f..b6abfae 100644
--- a/src/distance.c
+++ b/src/distance.c
@@ -1,7 +1,3 @@
-//
-// by Boris Stefanovic on 24/05/22
-//
-
 #include "distance.h"
 #include <math.h>
 #include "common.h"
diff --git a/src/distance.h b/src/distance.h
index 166cd54..f046c90 100644
--- a/src/distance.h
+++ b/src/distance.h
@@ -1,7 +1,3 @@
-//
-// by Boris Stefanovic on 24/05/22
-//
-
 #ifndef PROG_KMEANS_DISTANCE_H
 #define PROG_KMEANS_DISTANCE_H
 
diff --git a/src/linkedlist.c b/src/linkedlist.c
index b9c8f83..898c7d3 100644
--- a/src/linkedlist.c
+++ b/src/linkedlist.c
@@ -4,20 +4,20 @@
 #include "point.h"
 
 
-list_points_node_int_t* list_points_create_node_int(vector_int_t* vec) {
+list_points_node_int_t* list_points_node_create_int(vector_int_t* vec) {
 	list_points_node_int_t* node = malloc(sizeof(list_points_node_int_t));
 	if (NULL == node) return NULL;
-	point_int_t* point = point_int_create(vec);
+	point_int_t* point = point_create_int(vec);
 	if (NULL == point) return NULL;
 	node->point = point;
 	node->next = NULL;
 	return node;
 }
 
-list_points_node_fpt_t* list_points_create_node_fpt(vector_fpt_t* vec) {
+list_points_node_fpt_t* list_points_node_create_fpt(vector_fpt_t* vec) {
 	list_points_node_fpt_t* node = malloc(sizeof(list_points_node_fpt_t));
 	if (NULL == node) return NULL;
-	point_fpt_t* point = point_fpt_create(vec);
+	point_fpt_t* point = point_create_fpt(vec);
 	if (NULL == point) return NULL;
 	node->point = point;
 	node->next = NULL;
@@ -25,15 +25,15 @@ list_points_node_fpt_t* list_points_create_node_fpt(vector_fpt_t* vec) {
 }
 
 
-void list_points_destroy_node_int(list_points_node_int_t* node, const bool full) {
+void list_points_node_destroy_int(list_points_node_int_t* node, const bool full) {
 	if (NULL == node) return;
-	if (full) point_int_destroy(node->point);
+	if (full) point_destroy_int(node->point);
 	free(node);
 }
 
-void list_points_destroy_node_fpt(list_points_node_fpt_t* node, const bool full) {
+void list_points_node_destroy_fpt(list_points_node_fpt_t* node, const bool full) {
 	if (NULL == node) return;
-	if (full) point_fpt_destroy(node->point);
+	if (full) point_destroy_fpt(node->point);
 	free(node);
 }
 
@@ -64,7 +64,7 @@ void list_points_destroy_int(list_points_int_t* list, const bool full) {
 	list_points_node_int_t* node;
 	while ((node = list->head) != NULL) {
 		list->head = node->next;
-		list_points_destroy_node_int(node, full);
+		list_points_node_destroy_int(node, full);
 	}
 	free(list);
 }
@@ -74,7 +74,7 @@ void list_points_destroy_fpt(list_points_fpt_t* list, const bool full) {
 	list_points_node_fpt_t* node;
 	while ((node = list->head) != NULL) {
 		list->head = node->next;
-		list_points_destroy_node_fpt(node, full);
+		list_points_node_destroy_fpt(node, full);
 	}
 	free(list);
 }
@@ -82,7 +82,7 @@ void list_points_destroy_fpt(list_points_fpt_t* list, const bool full) {
 
 void list_points_append_int(list_points_int_t* list, vector_int_t* vector) {
 	if (NULL == vector) return;
-	list_points_node_int_t* node = list_points_create_node_int(vector);
+	list_points_node_int_t* node = list_points_node_create_int(vector);
 	if (NULL == list->head) {  // if list is empty
 		list->head = node;
 		list->tail = list->head;
@@ -95,7 +95,7 @@ void list_points_append_int(list_points_int_t* list, vector_int_t* vector) {
 
 void list_points_append_fpt(list_points_fpt_t* list, vector_fpt_t* vector) {
 	if (NULL == vector) return;
-	list_points_node_fpt_t* node = list_points_create_node_fpt(vector);
+	list_points_node_fpt_t* node = list_points_node_create_fpt(vector);
 	if (NULL == list->head) {  // if list is empty
 		list->head = node;
 		list->tail = list->head;
diff --git a/src/linkedlist.h b/src/linkedlist.h
index a269942..adfdeb9 100644
--- a/src/linkedlist.h
+++ b/src/linkedlist.h
@@ -1,7 +1,3 @@
-//
-// by Boris Stefanovic on 31/05/22
-//
-
 #ifndef PROG_KMEANS_LINKEDLIST_H
 #define PROG_KMEANS_LINKEDLIST_H
 
@@ -15,33 +11,33 @@ typedef struct list_points_node_int {
 	struct list_points_node_int* next;
 } list_points_node_int_t;
 
-typedef struct list_points_int {
-	list_points_node_int_t* head;
-	list_points_node_int_t* tail;
-	size_t size;
-} list_points_int_t;
-
-
 typedef struct list_points_node_fpt {
 	point_fpt_t* point;
 	struct list_points_node_fpt* next;
 } list_points_node_fpt_t;
 
-typedef struct list_points_fpt {
-	list_points_node_fpt_t* head;
-	list_points_node_fpt_t* tail;
-	size_t size;
-} list_points_fpt_t;
 
+list_points_node_int_t* list_points_node_create_int(vector_int_t* vec);
 
-list_points_node_int_t* list_points_create_node_int(vector_int_t* vec);
+list_points_node_fpt_t* list_points_node_create_fpt(vector_fpt_t* vec);
 
-list_points_node_fpt_t* list_points_create_node_fpt(vector_fpt_t* vec);
 
+void list_points_node_destroy_int(list_points_node_int_t* node, const bool full);
 
-void list_points_destroy_node_int(list_points_node_int_t* node, const bool full);
+void list_points_node_destroy_fpt(list_points_node_fpt_t* node, const bool full);
 
-void list_points_destroy_node_fpt(list_points_node_fpt_t* node, const bool full);
+
+typedef struct list_points_int {
+	list_points_node_int_t* head;
+	list_points_node_int_t* tail;
+	size_t size;
+} list_points_int_t;
+
+typedef struct list_points_fpt {
+	list_points_node_fpt_t* head;
+	list_points_node_fpt_t* tail;
+	size_t size;
+} list_points_fpt_t;
 
 
 list_points_int_t* list_points_create_int();
diff --git a/src/point.c b/src/point.c
index cb2e30f..3dcb58f 100644
--- a/src/point.c
+++ b/src/point.c
@@ -3,7 +3,7 @@
 #include "vector.h"
 
 
-point_int_t* point_int_create(vector_int_t* vector) {
+point_int_t* point_create_int(vector_int_t* vector) {
 	point_int_t* point = malloc(sizeof(point_int_t));
 	if (NULL == point) return NULL;
 	point->vector = vector;
@@ -11,8 +11,7 @@ point_int_t* point_int_create(vector_int_t* vector) {
 	return point;
 }
 
-
-point_fpt_t* point_fpt_create(vector_fpt_t* vector) {
+point_fpt_t* point_create_fpt(vector_fpt_t* vector) {
 	point_fpt_t* point = malloc(sizeof(point_fpt_t));
 	if (NULL == point) return NULL;
 	point->vector = vector;
@@ -21,15 +20,14 @@ point_fpt_t* point_fpt_create(vector_fpt_t* vector) {
 }
 
 
-void point_int_destroy(point_int_t* cp) {
+void point_destroy_int(point_int_t* cp) {
 	if (NULL == cp) return;
-	vector_int_destroy(cp->vector);
+	vector_destroy_int(cp->vector);
 	free(cp);
 }
 
-
-void point_fpt_destroy(point_fpt_t* cp) {
+void point_destroy_fpt(point_fpt_t* cp) {
 	if (NULL == cp) return;
-	vector_fpt_destroy(cp->vector);
+	vector_destroy_fpt(cp->vector);
 	free(cp);
 }
diff --git a/src/point.h b/src/point.h
index 58694e5..381dabe 100644
--- a/src/point.h
+++ b/src/point.h
@@ -1,5 +1,5 @@
-#ifndef PROG_KMEANS_CLUSTER_H
-#define PROG_KMEANS_CLUSTER_H
+#ifndef PROG_KMEANS_POINT_H
+#define PROG_KMEANS_POINT_H
 
 #include "vector.h"
 
@@ -9,21 +9,20 @@ typedef struct point_int {
 	vector_int_t* cluster;
 } point_int_t;
 
-
 typedef struct point_fpt {
 	vector_fpt_t* vector;
 	vector_fpt_t* cluster;
 } point_fpt_t;
 
 
-point_int_t* point_int_create(vector_int_t* vector);
+point_int_t* point_create_int(vector_int_t* vector);
 
-point_fpt_t* point_fpt_create(vector_fpt_t* vector);
+point_fpt_t* point_create_fpt(vector_fpt_t* vector);
 
 
-void point_int_destroy(point_int_t* cp);
+void point_destroy_int(point_int_t* cp);
 
-void point_fpt_destroy(point_fpt_t* cp);
+void point_destroy_fpt(point_fpt_t* cp);
 
 
-#endif //PROG_KMEANS_CLUSTER_H
+#endif //PROG_KMEANS_POINT_H
diff --git a/src/vector.c b/src/vector.c
index f72d466..b70c9f1 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -87,3 +87,27 @@ void vector_print_to_file_fpt(FILE* file, const vector_fpt_t* v) {
 	for (size_t i = 1; i < v->dim; ++i) fprintf(file, " , %lf", v->data[i]);
 	fprintf(file, "\n");
 }
+
+
+void vector_add_inplace_int(vector_int_t* v, const vector_int_t a) {
+	if (NULL == v) return;
+	const size_t dim = v->dim < a.dim ? v->dim : a.dim;
+	for (size_t i = 0; i < dim; ++i) v->data[i] += a.data[i];
+}
+
+void vector_add_inplace_fpt(vector_fpt_t* v, const vector_fpt_t a) {
+	if (NULL == v) return;
+	const size_t dim = v->dim < a.dim ? v->dim : a.dim;
+	for (size_t i = 0; i < dim; ++i) v->data[i] += a.data[i];
+}
+
+
+void vector_div_inplace_int(vector_int_t* v, const int_t a) {
+	if (NULL == v) return;
+	for (size_t i = 0; i < v->dim; ++i) v->data[i] /= a;
+}
+
+void vector_div_inplace_fpt(vector_fpt_t* v, const fpt_t a) {
+	if (NULL == v) return;
+	for (size_t i = 0; i < v->dim; ++i) v->data[i] /= a;
+}
diff --git a/src/vector.h b/src/vector.h
index 8291ac9..155fb78 100644
--- a/src/vector.h
+++ b/src/vector.h
@@ -44,4 +44,14 @@ void vector_print_to_file_int(FILE* file, const vector_int_t* v);
 void vector_print_to_file_fpt(FILE* file, const vector_fpt_t* v);
 
 
+void vector_add_inplace_int(vector_int_t* v, const vector_int_t a);
+
+void vector_add_inplace_fpt(vector_fpt_t* v, const vector_fpt_t a);
+
+
+void vector_div_inplace_int(vector_int_t* v, const int_t a);
+
+void vector_div_inplace_fpt(vector_fpt_t* v, const fpt_t a);
+
+
 #endif //PROG_KMEANS_VECTOR_H
-- 
GitLab