Commit 1d8da6ae authored by david's avatar david
Browse files

Ajout des fichiers C du TP1

parents
CC= gcc
CXXFLAGS= -Wall -ansi --pedantic
CPP_O_FILE = arraylist.o analyzer.o main.o
LIB = -lm
all: $(CPP_O_FILE)
$(CC) $(CXXFLAGS) -o arraylist_analysis $(CPP_O_FILE) $(LIB)
clean:
rm -rf *.o
rm -rf *~
rm -rf arraylist_analysis
#include"analyzer.h"
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
analyzer_t * analyzer_create(){
analyzer_t * res = (analyzer_t *) malloc( sizeof(analyzer_t) );
res->capacity = 4;
res->cost = (double *) malloc( sizeof(double) * res->capacity );
res->cumulative_cost = (double *) malloc( sizeof(double) * res->capacity );
res->cumulative_square = 0.;
res->size = 0;
return res;
}
void analyzer_destroy(analyzer_t * a){
if( a != NULL ){
free( a->cost );
free( a->cumulative_cost );
free( a );
}
}
void analyzer_append(analyzer_t * a, double x){
if( a!=NULL ){
if( a->size >= (a->capacity * 3)/4 ){
a->capacity *= 2;
a->cost = (double *) realloc(a->cost, sizeof(double) * a->capacity*2);
a->cumulative_cost = (double *) realloc(a->cumulative_cost, sizeof(double) * a->capacity*2);
}
a->cost[a->size] = x;
a->cumulative_cost[a->size] = (a->size) ? a->cumulative_cost[a->size-1]+x : x;
a->cumulative_square += x*x;
a->size++;
}
}
double get_total_cost(analyzer_t * a){
return (a->size) ? a->cumulative_cost[a->size-1] : -1;
}
double get_amortized_cost(analyzer_t * a, size_t pos){
if(pos >= 0 && pos < a->size)
return (pos)? a->cumulative_cost[pos]/pos : a->cumulative_cost[pos];
return -1;
}
double get_average_cost(analyzer_t * a){
if(a->size)
return a->cumulative_cost[a->size - 1]/a->size;
return -1;
}
double get_variance(analyzer_t * a){
double mean, mean_square;
if(a->size){
mean = get_average_cost(a);
mean_square = mean * mean;
return a->cumulative_square - mean_square;
}
return -1;
}
double get_standard_deviation(analyzer_t * a){
if(a->size)
return sqrt(get_variance(a));
return -1;
}
void save_values(analyzer_t * a, char * path){
FILE * f;
int i;
if( (f = fopen(path, "w")) != NULL ){
for (i = 0; i < a->size; ++i){
fprintf(f,"%d %lf %lf\n", i, a->cost[i], get_amortized_cost(a, i));
}
}else{
fprintf(stderr, "Could not save values in file %s", path);
}
}
void plot_values(analyzer_t * a){
int i;
for (i = 0; i < a->size; ++i){
printf("%d %lf %lf\n", i, a->cost[i], get_amortized_cost(a, i));
}
}
#ifndef __ANALYZER_H__
#define __ANALYZER_H__
#include <stddef.h>
/**
Structure utilisée pour faire des statistiques élémentaires
sur une séquence d'opérations.
*/
typedef struct analyzer_s{
// Coût de chaque opération. Peut représenter du temps ou une autre mesure.
double * cost;
// Coût cumulatif. La case i contient la somme des coûts des i premières opérations.
// Permet de calculer le coût amorti d'une opération.
double * cumulative_cost;
// Carré du coût cumulatif. Sert à calculer la variance. On ne garde que la dernière valeur.
double cumulative_square;
// Capacité de stockage des tableaux
size_t capacity;
// Nombre d'éléments dans chaque tableaux.
size_t size;
} analyzer_t;
/**
Fonction d'initialisation d'une analyse.
Complexité en temps/espace, pire et meilleur cas : O(1)
@return Un pointeur sur une structure analyzer_t nouvellement allouée.
*/
analyzer_t * analyzer_create();
/**
Fonction de libération de la mémoire occupée par une analyse.
Complexité en temps/espace, pire et meilleur cas : O(1)
@param a est un pointeur vers l'espace mémoire que la fonction va libérer.
*/
void analyzer_destroy(analyzer_t * a);
/**
Ajoute un coût, une valeur à l'analyse.
Complexité en temps/espace, pire cas : O(size)
Complexité en temps/espace, meilleur cas : O(1)
Complexité amortie : O(1)
@param a est l'analyse à laquelle on souhaite ajouter une valeur.
@param cost est la valeur que l'on souhaite ajouter.
*/
void analyzer_append(analyzer_t * a, double cost);
/**
Renvoie la somme des coûts enregistrés dans cette analyse.
Complexité en temps/espace, pire cas : O(1)
@param a est une analyse.
@returns la somme des coûts enregistrés dans cette analyse.
*/
double get_total_cost(analyzer_t * a);
/**
Renvoie le coût amorti d'une opération.
Complexité en temps/espace, pire cas : O(1)
@param a est une analyse.
@param pos est l'indice de l'opération pour laquelle on veut connaître le coût amorti.
@returns le coût amorti d'une opération.
*/
double get_amortized_cost(analyzer_t * a, size_t pos);
/**
Renvoie la moyenne des coûts de toutes les opérations enregistrées dans l'analyse.
Complexité en temps/espace, pire cas : O(1)
@param a est une analyse.
@returns la moyenne des coûts de toutes les opérations enregistrées dans l'analyse.
*/
double get_average_cost(analyzer_t * a);
/**
Renvoie la variance des coûts de toutes les opérations enregistrées dans l'analyse.
Complexité en temps/espace, pire cas : O(1)
@param a est une analyse.
@returns la variance des coûts de toutes les opérations enregistrées dans l'analyse.
*/
double get_variance(analyzer_t * a);
/**
Renvoie l'écart-type des coûts de toutes les opérations enregistrées dans l'analyse.
Complexité en temps/espace, pire cas : O(1)
@param a est une analyse.
@returns l'écart-type des coûts de toutes les opérations enregistrées dans l'analyse.
*/
double get_standard_deviation(analyzer_t * a);
/**
Sauvegarde la liste des coûts et des coûts amortis dans un fichier.
Complexité en temps, meilleur/pire cas : O(size)
@param a est l'analyse que l'on souhaite sauvegarder.
@param path est le chemin du fichier dans lequel la sauvegarde est faite.
*/
void save_values(analyzer_t * a, char * path);
/**
Affiche la liste des coûts et des coûts amortis sur la sortie standard.
Complexité en temps, meilleur/pire cas : O(size)
@param a est l'analyse que l'on souhaite sauvegarder.
*/
void plot_values(analyzer_t * a);
#endif
#include "arraylist.h"
#include<stdio.h>
#include<stdlib.h>
arraylist_t * arraylist_create(){
arraylist_t * res = (arraylist_t *) malloc( sizeof(arraylist_t) );
res->data = (int *) malloc( sizeof(int) * 4 );
res->capacity = 4;
res->size = 0;
return res;
}
void arraylist_destroy(arraylist_t * a){
if( a != NULL ){
if( a->data != NULL )
free( a->data );
free( a );
}
}
char arraylist_append(arraylist_t * a, int x){
char memory_allocation = FALSE;
if( a!=NULL ){
if( arraylist_enlarging_capacity(a) ){
memory_allocation = TRUE;
a->capacity *= 2;
a->data = (int *) realloc(a->data, sizeof(int) * a->capacity);
}
a->data[a->size++] = x;
}
return memory_allocation;
}
char arraylist_pop_back(arraylist_t * a){
char memory_reduction = FALSE;
if( a!=NULL && a->size>0 ){
if( arraylist_reducing_capacity(a) ){
memory_reduction = TRUE;
a->capacity /= 2;
a->data = (int *) realloc(a->data, sizeof(int) * a->capacity);
}
a->size--;
}
return memory_reduction;
}
int arraylist_get(arraylist_t * a, int pos){
if( a != NULL && pos >0 && pos < a->size ){
return a->data[pos];
}
printf("Wrong parameter pos=%d or NULL list", pos);
return -1;
}
size_t arraylist_get_size(arraylist_t * a){
return ( a!=NULL) ? a->size : -1;
}
char arraylist_enlarging_capacity(arraylist_t * a){
return ( a->size >= (a->capacity * 3)/4 )? TRUE: FALSE;
}
char arraylist_reducing_capacity(arraylist_t * a){
return ( a->size <= a->capacity/4 && a->size >4 )? TRUE: FALSE;
}
#ifndef __ARRAYLIST_H
#define __ARRAYLIST_H
#define FALSE 0
#define TRUE 1
#include <stddef.h>
/**
Tableau dynamique d'entiers.
*/
typedef struct arraylist_s{
// Pointeur vers la zone de mémoire où les entiers seront stockées.
int * data;
// Taille réelle, ou capacité de stockage, du tableau.
size_t capacity;
// Nombre d'éléments stockés dans le tableau.
size_t size;
} arraylist_t;
/**
Fonction d'initialisation d'un tableau dynamique.
Complexité en temps/espace, pire et meilleur cas : O(1)
@return Un pointeur sur un tableau dynamique nouvellement alloué.
*/
arraylist_t * arraylist_create();
/**
Fonction de libération de la mémoire occupée par un tableau dynamique.
Complexité en temps/espace, pire et meilleur cas : O(1)
@param a est un pointeur vers l'espace mémoire que la fonction va libérer.
*/
void arraylist_destroy(arraylist_t * a);
/**
Ajoute une valeur dans le tableau.
Complexité en temps/espace, pire cas : O(size)
Complexité en temps/espace, meilleur cas : O(1)
Complexité amortie : O(1)
@param a est le tableau auquel on souhaite ajouter une valeur.
@param x est la valeur que l'on souhaite ajouter.
@returns VRAI si le tableau a été agrandit, FAUX sinon
*/
char arraylist_append(arraylist_t * a, int x);
/**
Supprime la dernière valeur du tableau.
Complexité en temps, pire cas : O(size)
Complexité en temps, meilleur cas : O(1)
Complexité amortie : O(1)
@param a est le tableau auquel on souhaite ajouter une valeur.
@returns VRAI si le tableau a été réduit, FAUX sinon
*/
char arraylist_pop_back(arraylist_t * a);
/**
Renvoie la valeur située à la position donnée par l'utilisateur.
Complexité en temps/espace, pire cas : O(1)
@param a est un pointeur vers un tableau.
@param pos est la l'indice de la case on l'utilisateur veut connaître la valeur.
@returns la valeur située à la position donnée par l'utilisateur.
*/
int arraylist_get(arraylist_t * a, int pos);
/**
Renvoie le nombre d'éléments stockés dans le tableau.
Complexité en temps/espace, pire cas : O(1)
@param a est un pointeur vers un tableau.
@returns le nombre d'éléments stockés dans le tableau.
*/
size_t arraylist_get_size(arraylist_t * a);
/**
Cette fonction détermine la règle selon laquelle un espace mémoire plus grand sera alloué ou non.
@param a est un pointeur vers un tableau.
@returns VRAI si le tableau doit être agrandi, FAUX sinon.
*/
char arraylist_enlarging_capacity(arraylist_t * a);
/**
Cette fonction détermine la règle selon laquelle un espace mémoire plus petit sera alloué ou non.
@param a est un pointeur vers un tableau.
@returns VRAI si le tableau doit être réduit, FAUX sinon.
*/
char arraylist_reducing_capacity(arraylist_t * a);
#endif
#include<stdio.h>
#include <time.h>
#include<stdlib.h>
#include "arraylist.h"
#include "analyzer.h"
int main(int argc, char ** argv){
int i;
// Tableau dynamique.
arraylist_t * a = arraylist_create();
// Analyse du temps pris par les opérations.
analyzer_t * time_analysis = analyzer_create();
// Analyse du nombre de copies faites par les opérations.
analyzer_t * copy_analysis = analyzer_create();
struct timespec before, after;
// utilisé comme booléen pour savoir si une allocation a été effectuée.
char memory_allocation;
for(i = 0; i < 1000000 ; i++){
// Ajout d'un élément et mesure du temps pris par l'opération.
timespec_get(&before, TIME_UTC);
memory_allocation = arraylist_append(a, i);
timespec_get(&after, TIME_UTC);
// Enregistrement du temps pris par l'opération
analyzer_append(time_analysis, after.tv_nsec - before.tv_nsec);
// Enregistrement du nombre de copies efféctuées par l'opération.
// S'il y a eu réallocation de mémoire, il a fallu recopier tout le tableau.
analyzer_append(copy_analysis, (memory_allocation)? i:1 );
}
// Affichage de quelques statistiques sur l'expérience.
fprintf(stderr, "Total cost: %lf\n", get_total_cost(time_analysis));
fprintf(stderr, "Average cost: %lf\n", get_average_cost(time_analysis));
fprintf(stderr, "Variance: %lf\n", get_variance(time_analysis));
fprintf(stderr, "Standard deviation: %lf\n", get_standard_deviation(time_analysis));
// Sauvegarde les données de l'expérience: temps et nombre de copies effectuées par opération.
save_values(time_analysis, "../dynamic_array_time_c.plot");
save_values(copy_analysis, "../dynamic_array_copy_c.plot");
// Nettoyage de la mémoire avant la sortie du programme
arraylist_destroy(a);
analyzer_destroy(time_analysis);
analyzer_destroy(copy_analysis);
return EXIT_SUCCESS;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment