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