Skip to content
Snippets Groups Projects
main.c 3.48 KiB
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "distance.h"
#include "io.h"
#include "kmeans.h"
#include "linkedlist.h"
#include "vector.h"


enum DistanceFunctionType {
	EUCLID = 0, MANHATTAN = 1, CHEBYSHEV = 2
};

enum DataType {
	FLOAT = 0, INT = 1
};


fpt_t (* const DIST_FUNC_INT[])(const vector_int_t*, const vector_int_t*) = {
		distance_euclid_int,
		distance_manhattan_int,
		distance_chebyshev_int};

fpt_t (* const DIST_FUNC_FPT[])(const vector_fpt_t*, const vector_fpt_t*) = {
		distance_euclid_fpt,
		distance_manhattan_fpt,
		distance_chebyshev_fpt};


void help(const char* callname) {
	fprintf(stderr,
			"\nUSAGE:    %s  -i INPUT_FILE  -o OUTPUT_FILE  -d [euclid,manhattan,chebyshev]  -t [fpt,int]\n",
			callname);
}


void parse_args(int argc, char** argv, char** ipath, char** opath, enum DistanceFunctionType* df, enum DataType* type) {
	int opt;
	while ((opt = getopt(argc, argv, "i:o:d:t:h")) != -1) {
		switch (opt) {
			case 'h':
				help(argv[0]);
				exit(EXIT_FAILURE);
			case 'i':
				*ipath = optarg;
				break;
			case 'o':
				*opath = optarg;
				break;
			case 'd':
				if (strcmp(optarg, "euclid") == 0) *df = EUCLID;
				else if (strcmp(optarg, "manhattan") == 0) *df = MANHATTAN;
				else if (strcmp(optarg, "chebyshev") == 0) *df = CHEBYSHEV;
				break;
			case 't':
				if (strcmp(optarg, "fpt") == 0) *type = FLOAT;
				else if (strcmp(optarg, "int") == 0) *type = INT;
				break;
			case '?':
				fprintf(stderr, "UNKNOWN OPTION :  %c", opt);
				break;
			default:
				// https://www.gnu.org/software/libc/manual/html_node/Example-of-Getopt.html
				abort();
		}
	}
}


int main_int(const char* ipath, const char* opath, const enum DistanceFunctionType dist_func_type) {
	//TODO
	return EXIT_FAILURE;
}

int main_fpt(const char* ipath, const char* opath, const enum DistanceFunctionType dist_func_type) {
	// READ
	FILE* ifile = ipath != NULL ? fopen(ipath, "r") : stdin;
	const size_t dim = io_read_int(ifile);
	const size_t nb_clusters = io_read_int(ifile);
	if (0 == dim) {
		printf("DIMENSION MUST BE STRICTLY POSITIVE !\n");
		fclose(ifile);
		return EXIT_FAILURE;
	}
	if (0 == nb_clusters) {
		printf("NUMBER OF CLUSTERS MUST BE STRICTLY POSITIVE !\n");
		fclose(ifile);
		return EXIT_FAILURE;
	}
	list_points_fpt_t* list = io_get_vector_list_fpt(ifile, dim);
	fclose(ifile);
	ifile = NULL;
	const size_t point_count = list->size;
	vector_fpt_t** points = list_points_to_array_fpt(list);
	list_points_destroy_fpt(list, false);
	list = NULL;
	// ALGORITHM
	printf("INIT: ...   ");
	cluster_fpt_t** clusters = kmeans_init_clusters_fpt((const vector_fpt_t**) points, point_count, nb_clusters);
	printf("DONE\n");
	printf("STARTING KMEANS ALGORITHM: ...\n");
	kmeans_fpt(points, point_count, clusters, nb_clusters, DIST_FUNC_FPT[dist_func_type]);
	printf("KMEANS DONE !\n");
	// WRITE
	FILE* ofile = opath != NULL ? fopen(opath, "w") : stdout;
	fprintf(ofile, "%lud\n%lud\n", dim, nb_clusters);
	io_write_clusters_to_file_fpt(ofile, clusters, nb_clusters);
	fclose(ofile);
	return EXIT_SUCCESS;
}


int main(int argc, char** argv) {
	// init defaults
	char (* ipath) = NULL, (* opath) = NULL;
	enum DistanceFunctionType disttype = EUCLID;
	enum DataType datatype = FLOAT;
	// parse args
	parse_args(argc, argv, &ipath, &opath, &disttype, &datatype);
	switch (datatype) {
		case FLOAT:
			printf("FLOAT\n");
			return main_fpt(ipath, opath, disttype);
		case INT:
			printf("INT\n");
			return main_int(ipath, opath, disttype);
		default:
			abort();
	}
}