diff --git a/Makefile b/Makefile
index 3efc662b2e08a39c01dbd52176476d8bc410f1d9..5163eacc27ae859cb7955749ed7766e89ea56f85 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ HDR := $(wildcard ${SRC_DIR}/*.h)
 BUILD_DIR := ${BUILD_ROOT}/prod
 TARGET := ${BUILD_DIR}/main
 CFLAGS := -std=c11 -Wall -Wextra -pedantic
-LDEXTRA :=
+LDEXTRA := -lm
 LDFLAGS := ${CFLAGS} ${LDEXTRA}
 OBJ := $(patsubst ${SRC_DIR}/%.c,${BUILD_DIR}/%.o,${SRC})
 
@@ -27,13 +27,13 @@ all: ${TARGET} ${TARGET_DEBUG}
 ${TARGET}: ${OBJ}
 	${CC} ${LDFLAGS} -o $@ $^
 
-${OBJ}: ${BUILD_DIR}/%.o: %.c ${HDR} ${BUILD_DIR}
+${OBJ}: ${BUILD_DIR}/%.o: ${SRC_DIR}/%.c ${HDR} ${BUILD_DIR}
 	${CC} ${CFLAGS} -c -o $@ $<
 
 ${DEBUG_TARGET}: ${DEBUG_OBJ}
 	${CC} ${DEBUG_LDFLAGS} -o $@ $^
 
-${DEBUG_OBJ}: ${DEBUG_BUILD_DIR}/%.o: %.c ${HDR} ${DEBUG_BUILD_DIR}
+${DEBUG_OBJ}: ${DEBUG_BUILD_DIR}/%.o: ${SRC_DIR}/%.c ${HDR} ${DEBUG_BUILD_DIR}
 	${CC} ${DEBUG_CFLAGS} -c -o $@ $<
 
 
diff --git a/src/common.h b/src/common.h
new file mode 100644
index 0000000000000000000000000000000000000000..e2fddef821d2ad35b1dcecfe986f04553fb47ec4
--- /dev/null
+++ b/src/common.h
@@ -0,0 +1,15 @@
+//
+// by Boris Stefanovic on 24/05/22
+//
+
+#ifndef PROG_KMEANS_COMMON_H
+#define PROG_KMEANS_COMMON_H
+
+#include <stdint.h>
+
+
+typedef int64_t int_t;
+typedef double fp_t;
+
+
+#endif //PROG_KMEANS_COMMON_H
diff --git a/src/distance.c b/src/distance.c
new file mode 100644
index 0000000000000000000000000000000000000000..79c24d282a4ee2b3b26cce7928959c8415e8dde9
--- /dev/null
+++ b/src/distance.c
@@ -0,0 +1,43 @@
+//
+// by Boris Stefanovic on 24/05/22
+//
+
+#include "distance.h"
+#include <math.h>
+#include "common.h"
+
+#define ERROR -1.0
+
+
+double distance_euclid_int(const vector_int_t* p1, const vector_int_t* p2) {
+	if (p1->dim != p2->dim)return ERROR;
+	int_t acc = 0;
+	for (size_t i = 0; i < p1->dim; ++i) {
+		int_t diff = p2->data[i] - p1->data[i];
+		int_t item = diff * diff;
+		acc += item;
+	}
+	return sqrt((double) acc);
+}
+
+inline int_t
+
+abs_diff(const int_t a1, const int_t a2) {
+	int_t diff = a2 - a1;
+	return diff >= 0 ? diff : -diff;
+}
+
+double distance_manhattan_int(const vector_int_t* p1, const vector_int_t* p2) {
+	if (p1->dim != p2->dim)return ERROR;
+	int_t acc = 0;
+	for (size_t i = 0; i < p1->dim; ++i) {
+		int_t diff = p2->data[i] - p1->data[i];
+		int_t item = diff >= 0 ? diff : -diff;
+		acc += item;
+	}
+	return (double) acc;
+}
+
+double distance_chebyshev_int(const vector_int_t* p1, const vector_int_t* p2) {
+	return ERROR;
+}
diff --git a/src/distance.h b/src/distance.h
new file mode 100644
index 0000000000000000000000000000000000000000..47f86eac375cc2d45a7a9b354a2a04b0953b6d3d
--- /dev/null
+++ b/src/distance.h
@@ -0,0 +1,25 @@
+//
+// by Boris Stefanovic on 24/05/22
+//
+
+#ifndef PROG_KMEANS_DISTANCE_H
+#define PROG_KMEANS_DISTANCE_H
+
+#include "vector.h"
+
+/*
+ * Although many distance return types may be left as integers,
+ * when passing function pointers to the k-means routine,
+ * a fixed signature will be expected.
+ * Therefore, we convert all distance return types to double.
+ */
+
+
+double distance_euclid_int(const vector_int_t* p1, const vector_int_t* p2);
+
+double distance_manhattan_int(const vector_int_t* p1, const vector_int_t* p2);
+
+double distance_chebyshev_int(const vector_int_t* p1, const vector_int_t* p2);
+
+
+#endif //PROG_KMEANS_DISTANCE_H
diff --git a/src/vector.c b/src/vector.c
index 41ce2975d078148b47ede58e802ac818efbf2021..d30b3ef765c94d6df15aafe2101ce57d1eea55ac 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -1,15 +1,15 @@
 //
 // Created by Boris Stefanovic on 24/05/22.
 //
-#include "vector.h"
 
+#include "vector.h"
 #include <stdlib.h>
 
 
-vector_int_t* vector_int_create(const size_t dim, const int* data) {
+vector_int_t* vector_int_create(const size_t dim, const int_t* data) {
 	vector_int_t* v;
 	if ((v = malloc(dim * sizeof(int))) == NULL) return NULL;
 	v->dim = dim;
-	for (int i = 0; i < dim; ++i) v->data[i] = data[i];
+	for (size_t i = 0; i < dim; ++i) v->data[i] = data[i];
 	return v;
 }
diff --git a/src/vector.h b/src/vector.h
index a9bfb94239b61b5f0af8eb3e23e82752aeaaca9e..2cdd4ad0dc2900b8039bceca7cdc6ed11e77b315 100644
--- a/src/vector.h
+++ b/src/vector.h
@@ -4,15 +4,22 @@
 #ifndef PROG_KMEANS_VECTOR_H
 #define PROG_KMEANS_VECTOR_H
 
+/*
+ * We can justify the implementation of vectors for multiple types to ease
+ * application to several scenarios without the need for casting,
+ * e.g. scientific measurements (floating point) and image data (integer).
+ */
+
 #include <stdlib.h>
+#include "common.h"
 
 
-typedef struct _vector_int {
+typedef struct vector_int_t_ {
 	size_t dim;
-	int* data;
+	int_t* data;
 } vector_int_t;
 
-vector_int_t* vector_int_create(const size_t dim, const int* data);
+vector_int_t* vector_int_create(const size_t dim, const int_t* data);
 
 
 #endif //PROG_KMEANS_VECTOR_H