6 changed files with 336 additions and 3 deletions
			
			
		@ -1,7 +1,7 @@ | 
				
			|||||
"THE BEER-WARE LICENSE" | 
					"THE BEER-WARE LICENSE" | 
				
			||||
 | 
					
 | 
				
			||||
Copyright (c) 2018 Apostolof, charaldp, tsakonag | 
					Copyright (c) 2019 Apostolof | 
				
			||||
 | 
					
 | 
				
			||||
As long as you retain this notice you can do whatever you want with this stuff. | 
					As long as you retain this notice you can do whatever you want with this stuff. | 
				
			||||
If we meet some day, and you think this stuff is worth it, you can buy us a | 
					If we meet some day, and you think this stuff is worth it, you can buy me a | 
				
			||||
beer in return. | 
					beer in return. | 
				
			||||
 | 
				
			|||||
@ -0,0 +1,38 @@ | 
				
			|||||
 | 
					SHELL := /bin/bash | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# ============================================
 | 
				
			||||
 | 
					# COMMANDS
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					CC = gcc -std=gnu99 | 
				
			||||
 | 
					RM = rm -f | 
				
			||||
 | 
					CFLAGS_DEBUG=-O2 -ggdb3 -Wall -Werror -pedantic -D_FORTIFY_SOURCE=2 -fasynchronous-unwind-tables -grecord-gcc-switches -Werror=implicit-function-declaration -I. | 
				
			||||
 | 
					CFLAGS=-O2 -Wall -Werror -pedantic -I. | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					OBJ=test_sample.o test_sample_functions.o | 
				
			||||
 | 
					DEPS=test_sample_functions.h | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# ==========================================
 | 
				
			||||
 | 
					# TARGETS
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					EXECUTABLES = test_sample.out | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.PHONY: all clean | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					all: $(EXECUTABLES) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# ==========================================
 | 
				
			||||
 | 
					# DEPENDENCIES (HEADERS)
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					%.o: %.c $(DEPS) | 
				
			||||
 | 
						$(CC) -c -o $@ $< $(CFLAGS) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.PRECIOUS: $(EXECUTABLES) $(OBJ) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# ==========================================
 | 
				
			||||
 | 
					# EXECUTABLE (MAIN)
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					$(EXECUTABLES): $(OBJ) | 
				
			||||
 | 
						$(CC) -o $@ $^ $(CFLAGS) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					clean: | 
				
			||||
 | 
						$(RM) *.o *~ $(EXECUTABLES) | 
				
			||||
@ -0,0 +1,43 @@ | 
				
			|||||
 | 
					#include "test_sample_functions.h" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					int main(int argc, char **argv) { | 
				
			||||
 | 
						Parameters parameters; | 
				
			||||
 | 
						parseArguments(argc, argv, ¶meters); | 
				
			||||
 | 
						//parameters.numberOfSamples = (parameters.time + parameters.delta - 1) / parameters.delta;
 | 
				
			||||
 | 
						parameters.numberOfSamples = 1 + ((parameters.time - 1) / parameters.delta); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						// Initialize a matrix to store the sample values
 | 
				
			||||
 | 
						double **samplesMatrix = (double **) malloc(parameters.numberOfSamples * sizeof(double *)); | 
				
			||||
 | 
						for (int i=0; i<parameters.numberOfSamples; ++i) { | 
				
			||||
 | 
							samplesMatrix[i] = (double *) malloc(3 * sizeof(double)); | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						// Saves information about the experiment to the output file
 | 
				
			||||
 | 
						{ | 
				
			||||
 | 
							FILE *outputFile; | 
				
			||||
 | 
							outputFile = fopen(parameters.outputFilename, "w"); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							if (outputFile == NULL) { | 
				
			||||
 | 
								printf("Error while opening the output file.\n"); | 
				
			||||
 | 
								exit(EXIT_FAILURE); | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							fprintf(outputFile, "Sampling experiment will run for %f seconds\n"\ | 
				
			||||
 | 
								"Sampling period is set to %f seconds.\n"\ | 
				
			||||
 | 
								"Number of samples should be %d.\n\n", | 
				
			||||
 | 
								parameters.time, parameters.delta, parameters.numberOfSamples); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							fclose(outputFile); | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						printf(ANSI_COLOR_BLUE "\n----- STARTING EXPERIMENT -----\n" ANSI_COLOR_RESET); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						testSampling(&samplesMatrix, parameters); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						printf(ANSI_COLOR_YELLOW "\n----- WRITING RESULTS TO OUTPUT FILE -----\n" ANSI_COLOR_RESET); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						// Saves results to the output file
 | 
				
			||||
 | 
						saveSamplesToFile(parameters.outputFilename, samplesMatrix, parameters.numberOfSamples); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						printf(ANSI_COLOR_GREEN "\n----- DONE -----\n" ANSI_COLOR_RESET); | 
				
			||||
 | 
					} | 
				
			||||
@ -0,0 +1,187 @@ | 
				
			|||||
 | 
					/* ===== INCLUDES ===== */ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#include "test_sample_functions.h" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/* ===== CONSTANTS ===== */ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					const char *ARGUMENT_TIME = "-t"; | 
				
			||||
 | 
					const char *ARGUMENT_DELTA = "-d"; | 
				
			||||
 | 
					const char *ARGUMENT_OUTPUT_FILENAME = "-o"; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					char *DEFAULT_OUTPUT_FILENAME = "sample_test_output"; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/* ===== STRUCTURES ===== */ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					struct timeval startwtime, endwtime; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/* ===== OTHER ===== */ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					volatile sig_atomic_t sample_flag = false; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/* ===== FUNCTIONS ===== */ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/*
 | 
				
			||||
 | 
					 * testSampling implements the sampling experiment. Three different ways of sampling are | 
				
			||||
 | 
					 * implemented. On the first one sleep is used. On the second sleep is used and the sleep times are | 
				
			||||
 | 
					 * corrected based on the previous error. On the third alarms are used. | 
				
			||||
 | 
					*/ | 
				
			||||
 | 
					void testSampling(double ***samplesMatrix, Parameters parameters) { | 
				
			||||
 | 
						printf(ANSI_COLOR_CYAN "\n----- RUNNING FIRST EXPERIMENT -----\n" ANSI_COLOR_RESET); | 
				
			||||
 | 
						for (int i = 0; i < parameters.numberOfSamples; ++i) { | 
				
			||||
 | 
							gettimeofday (&startwtime, NULL); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							usleep(parameters.delta * 1000000); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							gettimeofday (&endwtime, NULL); | 
				
			||||
 | 
							(*samplesMatrix)[i][0] = (double)((endwtime.tv_usec - startwtime.tv_usec)/1.0e6 + | 
				
			||||
 | 
								endwtime.tv_sec - startwtime.tv_sec); | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						printf(ANSI_COLOR_CYAN "\n----- RUNNING SECOND EXPERIMENT -----\n" ANSI_COLOR_RESET); | 
				
			||||
 | 
						double totalError = 0; | 
				
			||||
 | 
						for (int i = 0; i < parameters.numberOfSamples; ++i) { | 
				
			||||
 | 
							gettimeofday (&startwtime, NULL); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							usleep((parameters.delta - (totalError / (i + 1))) * 1000000); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							gettimeofday (&endwtime, NULL); | 
				
			||||
 | 
							(*samplesMatrix)[i][1] = (double)((endwtime.tv_usec - startwtime.tv_usec)/1.0e6 + | 
				
			||||
 | 
								endwtime.tv_sec - startwtime.tv_sec); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							totalError += (*samplesMatrix)[i][1] - parameters.delta; | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						printf(ANSI_COLOR_CYAN "\n----- RUNNING THIRD EXPERIMENT -----\n" ANSI_COLOR_RESET); | 
				
			||||
 | 
						signal(SIGALRM, handle_alarm); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						struct itimerval new; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						new.it_interval.tv_usec = (int) ((parameters.delta - ((int) parameters.delta)) * 1000000); | 
				
			||||
 | 
						new.it_interval.tv_sec = ((int) parameters.delta); | 
				
			||||
 | 
						new.it_value.tv_usec = (int) ((parameters.delta - ((int) parameters.delta)) * 1000000); | 
				
			||||
 | 
						new.it_value.tv_sec = ((int) parameters.delta); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						if (setitimer (ITIMER_REAL, &new, NULL) == -1) { | 
				
			||||
 | 
							perror("setitimer"); | 
				
			||||
 | 
							exit(EXIT_FAILURE); | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						gettimeofday (&startwtime, NULL); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						int i = 0 ; | 
				
			||||
 | 
						while(i < parameters.numberOfSamples) { | 
				
			||||
 | 
							if (sample_flag) { | 
				
			||||
 | 
								sample_flag = false; | 
				
			||||
 | 
								gettimeofday (&endwtime, NULL); | 
				
			||||
 | 
								(*samplesMatrix)[i][2] = (double)((endwtime.tv_usec - startwtime.tv_usec)/1.0e6 + | 
				
			||||
 | 
									endwtime.tv_sec - startwtime.tv_sec); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
								++i; | 
				
			||||
 | 
								gettimeofday (&startwtime, NULL); | 
				
			||||
 | 
							} | 
				
			||||
 | 
						} | 
				
			||||
 | 
						//alarm(0); Is this needed?
 | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					void handle_alarm(int sig) { | 
				
			||||
 | 
						sample_flag = true; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					// ==================== PROGRAM INPUT AND OUTPUT UTILS ====================
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/*
 | 
				
			||||
 | 
					 * parseArguments parses the command line arguments given by the user. | 
				
			||||
 | 
					*/ | 
				
			||||
 | 
					void parseArguments(int argumentCount, char **argumentVector, Parameters *parameters) { | 
				
			||||
 | 
						if (argumentCount > 7) { | 
				
			||||
 | 
							validUsage(argumentVector[0]); | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						(*parameters).time = 7200; | 
				
			||||
 | 
						(*parameters).delta = 0.1; | 
				
			||||
 | 
						(*parameters).outputFilename = DEFAULT_OUTPUT_FILENAME; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						char *endPointer; | 
				
			||||
 | 
						int argumentIndex = 1; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						while (argumentIndex < argumentCount) { | 
				
			||||
 | 
							if (!strcmp(argumentVector[argumentIndex], ARGUMENT_TIME)) { | 
				
			||||
 | 
								argumentIndex = checkIncrement(argumentIndex, argumentCount, argumentVector[0]); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
								double timeInput = strtod(argumentVector[argumentIndex], &endPointer); | 
				
			||||
 | 
								if ((timeInput <= 0) && endPointer) { | 
				
			||||
 | 
									printf("Invalid time argument\n"); | 
				
			||||
 | 
									exit(EXIT_FAILURE); | 
				
			||||
 | 
								} | 
				
			||||
 | 
								(*parameters).time = timeInput; | 
				
			||||
 | 
							} else if (!strcmp(argumentVector[argumentIndex], ARGUMENT_DELTA)) { | 
				
			||||
 | 
								argumentIndex = checkIncrement(argumentIndex, argumentCount, argumentVector[0]); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
								double deltaInput = strtod(argumentVector[argumentIndex], &endPointer); | 
				
			||||
 | 
								if ((deltaInput <= 0) && endPointer) { | 
				
			||||
 | 
									printf("Invalid time argument\n"); | 
				
			||||
 | 
									exit(EXIT_FAILURE); | 
				
			||||
 | 
								} | 
				
			||||
 | 
								(*parameters).delta = deltaInput; | 
				
			||||
 | 
							} else if (!strcmp(argumentVector[argumentIndex], ARGUMENT_OUTPUT_FILENAME)) { | 
				
			||||
 | 
								argumentIndex = checkIncrement(argumentIndex, argumentCount, argumentVector[0]); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
								if (fopen(argumentVector[argumentIndex], "w") == NULL) { | 
				
			||||
 | 
									printf("Invalid output filename. Reverting to default.\n"); | 
				
			||||
 | 
									continue; | 
				
			||||
 | 
								} | 
				
			||||
 | 
								(*parameters).outputFilename = argumentVector[argumentIndex]; | 
				
			||||
 | 
							} else { | 
				
			||||
 | 
								validUsage(argumentVector[0]); | 
				
			||||
 | 
								exit(EXIT_FAILURE); | 
				
			||||
 | 
							} | 
				
			||||
 | 
							++argumentIndex; | 
				
			||||
 | 
						} | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/*
 | 
				
			||||
 | 
					 * validUsage outputs a message to the console that informs the user of the | 
				
			||||
 | 
					 * correct (valid) way to use the program. | 
				
			||||
 | 
					*/ | 
				
			||||
 | 
					void validUsage(char *programName) { | 
				
			||||
 | 
						printf("%s [-t time] [-d delta] [-o output]" \ | 
				
			||||
 | 
							"\n-t time" \ | 
				
			||||
 | 
							"\n\ttotal duration of the sampling in seconds" \ | 
				
			||||
 | 
							"\n-d delta" \ | 
				
			||||
 | 
							"\n\tsampling period in seconds" \ | 
				
			||||
 | 
							"\n-o output" \ | 
				
			||||
 | 
							"\n\tfilename and path for the output" \ | 
				
			||||
 | 
							"\n", programName); | 
				
			||||
 | 
						exit(EXIT_FAILURE); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/*
 | 
				
			||||
 | 
					 * checkIncrement is a helper function for parseArguments function. | 
				
			||||
 | 
					*/ | 
				
			||||
 | 
					int checkIncrement(int previousIndex, int maxIndex, char *programName) { | 
				
			||||
 | 
						if (previousIndex == maxIndex) { | 
				
			||||
 | 
							validUsage(programName); | 
				
			||||
 | 
							exit(EXIT_FAILURE); | 
				
			||||
 | 
						} | 
				
			||||
 | 
						return ++previousIndex; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					void saveSamplesToFile(char *filename, double **samplesMatrix, int matrixRows) { | 
				
			||||
 | 
						FILE *outputFile; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						outputFile = fopen(filename, "a"); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						if (outputFile == NULL) { | 
				
			||||
 | 
							printf("Error while opening the output file.\n"); | 
				
			||||
 | 
							return; | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						// Saves the samples matrix
 | 
				
			||||
 | 
						for (int i=0; i<matrixRows; ++i) { | 
				
			||||
 | 
							fprintf(outputFile, "%.10g\t%.10g\t%.10g\n", | 
				
			||||
 | 
								samplesMatrix[i][0], samplesMatrix[i][1], samplesMatrix[i][2]); | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						fclose(outputFile); | 
				
			||||
 | 
					} | 
				
			||||
@ -0,0 +1,65 @@ | 
				
			|||||
 | 
					#ifndef TEST_SAMPLE_FUNCTIONS_H	/* Include guard */ | 
				
			||||
 | 
					#define TEST_SAMPLE_FUNCTIONS_H | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/* ===== INCLUDES ===== */ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#include <sys/time.h> | 
				
			||||
 | 
					#include <stdio.h> | 
				
			||||
 | 
					#include <stdlib.h> | 
				
			||||
 | 
					#include <string.h> | 
				
			||||
 | 
					#include <unistd.h> | 
				
			||||
 | 
					#include <signal.h> | 
				
			||||
 | 
					#include <stdbool.h> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/* ===== DEFINITIONS ===== */ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					//Colors used for better console output formating.
 | 
				
			||||
 | 
					#define ANSI_COLOR_RED     "\x1B[31m" | 
				
			||||
 | 
					#define ANSI_COLOR_GREEN   "\x1B[32m" | 
				
			||||
 | 
					#define ANSI_COLOR_YELLOW  "\x1B[33m" | 
				
			||||
 | 
					#define ANSI_COLOR_BLUE    "\x1B[34m" | 
				
			||||
 | 
					#define ANSI_COLOR_CYAN    "\x1B[36m" | 
				
			||||
 | 
					#define ANSI_COLOR_RESET   "\x1B[0m" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/* ===== CONSTANTS DEFINITION ===== */ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					// Constant strings that store the command line options available.
 | 
				
			||||
 | 
					extern const char *ARGUMENT_TIME; | 
				
			||||
 | 
					extern const char *ARGUMENT_DELTA; | 
				
			||||
 | 
					extern const char *ARGUMENT_OUTPUT_FILENAME; | 
				
			||||
 | 
					// Default filename used for the output.
 | 
				
			||||
 | 
					extern char *DEFAULT_OUTPUT_FILENAME; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/* ===== STRUCTURES ===== */ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					// Structures used in gettimeofday
 | 
				
			||||
 | 
					extern struct timeval startwtime, endwtime; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					// A data structure to conveniently hold the algorithm's parameters.
 | 
				
			||||
 | 
					typedef struct parameters { | 
				
			||||
 | 
						double time, delta; | 
				
			||||
 | 
						char *outputFilename; | 
				
			||||
 | 
						int numberOfSamples; | 
				
			||||
 | 
					} Parameters; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/* ===== FUNCTION DEFINITIONS ===== */ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					// Function that implements the sampling experiment.
 | 
				
			||||
 | 
					void testSampling(double ***samplesMatrix, Parameters parameters); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					void handle_alarm(int sig); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					// Function validUsage outputs the correct way to use the program with command line arguments.
 | 
				
			||||
 | 
					void validUsage(char *programName); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					// Function checkIncrement is a helper function used in parseArguments (see bellow).
 | 
				
			||||
 | 
					int checkIncrement(int previousIndex, int maxIndex, char *programName); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					// Function parseArguments parses command line arguments.
 | 
				
			||||
 | 
					void parseArguments(int argumentCount, char **argumentVector, Parameters *parameters); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					// Function saveSamplesToFile appends the sample matrix "samplesMatrix" to the file with the
 | 
				
			||||
 | 
					// filename supplied in the arguments.
 | 
				
			||||
 | 
					void saveSamplesToFile(char *filename, double **samplesMatrix, int matrixRows); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#endif	// TEST_SAMPLE_FUNCTIONS_H
 | 
				
			||||
					Loading…
					
					
				
		Reference in new issue