/*************************************/
/* Auteur : Rémi Synave */
/* Date de création : 01/03/07 */
/* Date de modification : 15/03/15 */
/* Version : 0.4 */
/*************************************/
/***************************************************************************/
/* This file is part of a2ri. */
/* */
/* a2ri is free software: you can redistribute it and/or modify it */
/* under the terms of the GNU Lesser General Public License as published */
/* by the Free Software Foundation, either version 3 of the License, or */
/* (at your option) any later version. */
/* */
/* a2ri is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU Lesser General Public License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public */
/* License along with a2ri. */
/* If not, see . */
/***************************************************************************/
#include "util.h"
/********** INTERMEDIATE TYPES AND FUNCTIONS **********/
/* Les fonctions intermédiaires sont préfixées de IF */
/* et les types intermédiaires de IT */
int
IFlist_int_etape_tri_rapide (
int *t,
int min,
int max,
int type)
{
int temp = t[max];
while (max > min)
{
if (type == ASC)
{
while (max > min && t[min] <= temp)
min++;
}
else
{
while (max > min && t[min] > temp)
min++;
}
if (max > min)
{
t[max] = t[min];
max--;
if (type == ASC)
{
while (max > min && t[max] >= temp)
max--;
}
else
{
while (max > min && t[max] < temp)
max--;
}
if (max > min)
{
t[min] = t[max];
min++;
}
}
}
t[max] = temp;
return (max);
}
void
IFlist_int_tri_rapide (
int *t,
int deb,
int fin,
int type)
{
int mil;
if (deb < fin)
{
mil = IFlist_int_etape_tri_rapide (t, deb, fin, type);
if (mil - deb > fin - mil)
{
IFlist_int_tri_rapide (t, mil + 1, fin, type);
IFlist_int_tri_rapide (t, deb, mil - 1, type);
}
else
{
IFlist_int_tri_rapide (t, deb, mil - 1, type);
IFlist_int_tri_rapide (t, mil + 1, fin, type);
}
}
}
int
IFlist_double_etape_tri_rapide (
double *t,
int min,
int max,
int type)
{
double temp = t[max];
while (max > min)
{
if (type == ASC)
{
while (max > min && t[min] <= temp)
min++;
}
else
{
while (max > min && t[min] > temp)
min++;
}
if (max > min)
{
t[max] = t[min];
max--;
if (type == ASC)
{
while (max > min && t[max] >= temp)
max--;
}
else
{
while (max > min && t[max] < temp)
max--;
}
if (max > min)
{
t[min] = t[max];
min++;
}
}
}
t[max] = temp;
return (max);
}
void
IFlist_double_tri_rapide (
double *t,
int deb,
int fin,
int type)
{
int mil;
if (deb < fin)
{
mil = IFlist_double_etape_tri_rapide (t, deb, fin, type);
if (mil - deb > fin - mil)
{
IFlist_double_tri_rapide (t, mil + 1, fin, type);
IFlist_double_tri_rapide (t, deb, mil - 1, type);
}
else
{
IFlist_double_tri_rapide (t, deb, mil - 1, type);
IFlist_double_tri_rapide (t, mil + 1, fin, type);
}
}
}
/********** MAIN FUNCTIONS **********/
/**
Affiche un message d'erreur et stoppe le programme si la condition n'est pas satisfaite
@param cond condition à satisfaire
@param str message d'erreur à afficher dans le cas contraire
@return aucun
**/
void
a2ri_erreur_critique_si (
int cond,
const char * const str)
{
if (cond)
{
a2ri_printf_debug ("%s\n", str);
exit (EXIT_FAILURE);
}
}
/**
Renvoie un entier compris entre min et max
@param min valeur minimale
@param max valeur maximale
@return un entier
**/
int
rand_int (
int min,
int max)
{
return ((((int) rand ()) % (max - min + 1)) + min);
}
/**
Retourne la position de la valeur tosearch, -1 sinon
@param list tableau d'entier
@param size taille du tableau
@param tosearch entier à chercher
@return position de la première occurence, -1 s'il n'apparait pas dans le tableau
*/
int
list_int_contains (
const int * const list,
int size,
int tosearch)
{
int i;
for (i = 0; i < size; i++)
if (list[i] == tosearch)
return i;
return -1;
}
/**
Retourne la position de la valeur tosearch, -1 sinon
@param list tableau de réels
@param size taille du tableau
@param tosearch réel à chercher
@return position de la première occurence, -1 s'il n'apparait pas dans le tableau
*/
int
list_double_contains (
const double * const list,
int size,
double tosearch)
{
int i;
for (i = 0; i < size; i++)
if (list[i] == tosearch)
return i;
return -1;
}
/**
Clone la liste
@param list la liste à cloner
@param size taille de la liste
@param list_clone liste clonée
@return 1 si la liste est bien clonée, 0 sinon
**/
int
list_int_clone (
const int * const list,
int size,
int **list_clone)
{
(*list_clone) = (int *) malloc (size * sizeof (int));
a2ri_erreur_critique_si (*list_clone == NULL,
"erreur allocation memoire pour list_clone\nlist_int_clone");
if ((*list_clone) == NULL)
return 0;
for (int i = 0; i < size; i++)
(*list_clone)[i] = list[i];
return 1;
}
/**
Clone la liste
@param list la liste à cloner
@param size taille de la liste
@param list_clone liste clonée
@return 1 si la liste est bien clonée, 0 sinon
**/
int
list_double_clone (
const double * const list,
int size,
double **list_clone)
{
(*list_clone) = (double *) malloc (size * sizeof (double));
a2ri_erreur_critique_si (*list_clone == NULL,
"erreur allocation memoire pour list_clone\nlist_double_clone");
if ((*list_clone) == NULL)
return 0;
for (int i = 0; i < size; i++)
(*list_clone)[i] = list[i];
return 1;
}
/**
calcul de l'intersection de deux liste d'entier
@param list1 premiere liste d'entier
@param size1 taille de la premiere liste
@param list2 seconde liste d'entier
@param size2 taille de la seconde liste
@param list_inter liste d'entier représentatnt l'intersection de list1 et list2
@param size_list_inter taille de la liste d'intersection
@return aucun
*/
void
list_int_intersection (
const int * const list1,
int size1,
const int * const list2,
int size2,
int **list_inter,
int *size_list_inter)
{
*list_inter = NULL;
*size_list_inter = 0;
for (int i = 0; i < size1; i++)
{
if (list_int_contains (list2, size2, list1[i]) != -1)
list_int_add (list_inter,
size_list_inter,
list1[i],
WITHOUT_REDUNDANCE);
}
}
/**
Ajoute l'entier toadd en fin de liste
@param list pointeur sur le premier élément du tableau
@param size pointeur sur la taille du tableau
@param toadd entier à ajouter
@param add_type WITH_REDUNDANCE ou WITHOUT_REDUNDANCE
avec redondance : ajout simple
sans redondance : ajout si la valeur n'apparait pas dans la liste
@return 1 si succès, 0 sinon
*/
int
list_int_add (
int **list,
int *size,
int toadd,
int add_type)
{
if (add_type == WITHOUT_REDUNDANCE)
if (list_int_contains (*list, *size, toadd) != -1)
return 0;
int *newlist = (int *) malloc (((*size) + 1) * sizeof (int));
a2ri_erreur_critique_si (newlist == NULL,
"erreur allocation memoire pour newlist\nlist_int_add");
int i;
for (i = 0; i < *size; i++)
newlist[i] = (*list)[i];
newlist[*size] = toadd;
free (*list);
(*list) = newlist;
*size = (*size) + 1;
return 1;
}
/**
Ajoute le réel toadd en fin de liste
@param list pointeur sur le premier élément du tableau
@param size pointeur sur la taille du tableau
@param toadd réel à ajouter
@param add_type WITH_REDUNDANCE ou WITHOUT_REDUNDANCE
avec redondance : ajout simple
sans redondance : ajout si la valeur n'apparait pas dans la liste
@return 1 si succès, 0 sinon
*/
int
list_double_add (
double **list,
int *size,
double toadd,
int add_type)
{
if (add_type == WITHOUT_REDUNDANCE)
if (list_double_contains (*list, *size, toadd) != -1)
return 0;
double *newlist = (double *) malloc (((*size) + 1) * sizeof (double));
a2ri_erreur_critique_si (newlist == NULL,
"erreur allocation memoire pour newlist\nlist_double_add");
int i;
for (i = 0; i < *size; i++)
newlist[i] = (*list)[i];
newlist[*size] = toadd;
free (*list);
(*list) = newlist;
*size = (*size) + 1;
return 1;
}
/**
Enlève la valeur à la position index
@param list pointeur sur le premier élément du tableau
@param size pointeur sur la taille du tableau
@param index position de l'entier à supprimer
@return 1 si succès, 0 sinon (cas où index>=size)
*/
int
list_int_remove (
int **list,
int *size,
int index)
{
int *temp;
if (index >= *size)
return 0;
if(*size==1)
{
free(*list);
*size=0;
*list=NULL;
return 1;
}
for (int i = index; i < (*size) - 1; i++)
(*list)[i] = (*list)[i + 1];
temp = (int *) realloc (*list, ((*size) - 1) * sizeof (int));
a2ri_erreur_critique_si (temp == NULL && *size != 0,
"erreur allocation memoire pour temp\nlist_int_remove");
*list=temp;
*size = (*size) - 1;
a2ri_erreur_critique_si (*list == NULL && *size != 0,
"erreur allocation memoire pour list\nlist_int_remove");
return 1;
}
/**
Enlève la valeur à la position index
@param list pointeur sur le premier élément du tableau
@param size pointeur sur la taille du tableau
@param index position du réel à supprimer
@return 1 si succès, 0 sinon (cas où index>=size)
*/
int
list_double_remove (
double **list,
int *size,
int index)
{
double *temp;
if (index >= *size)
return 0;
if(*size==1)
{
free(*list);
*size=0;
*list=NULL;
return 1;
}
for (int i = index; i < (*size) - 1; i++)
(*list)[i] = (*list)[i + 1];
temp = (double *) realloc (*list, ((*size) - 1) * sizeof (double));
a2ri_erreur_critique_si (temp == NULL && *size != 0,
"erreur allocation memoire pour temp\nlist_double_remove");
*list=temp;
*size = (*size) - 1;
a2ri_erreur_critique_si (*list == NULL && *size != 0,
"erreur allocation memoire pour list\nlist_double_remove");
return 1;
}
/**
Mélange la liste d'entier
@param list tableau d'entier
@param size taille du tableau
@return aucun
*/
void
list_int_mix (
int *list,
int size)
{
int *list_clone = NULL,
size_clone;
list_int_clone (list, size, &list_clone);
size_clone = size;
for (int i = 0; i < size; i++)
{
int index = rand_int (0, size_clone - 1);
list[i] = list_clone[index];
list_int_remove (&list_clone, &size_clone, index);
}
}
/**
Mélange la liste de réel
@param list tableau de réel
@param size taille du tableau
@return aucun
*/
void
list_double_mix (
double *list,
int size)
{
double *list_clone = NULL;
int size_clone;
list_double_clone (list, size, &list_clone);
size_clone = size;
for (int i = 0; i < size; i++)
{
int index = rand_int (0, size_clone - 1);
list[i] = list_clone[index];
list_double_remove (&list_clone, &size_clone, index);
}
}
/**
Affichage de la liste d'entier
@param list tableau d'entier
@param size taille du tableau
@return aucun
*/
void
list_int_display (
const int * const list,
int size)
{
int i;
if (size == 0)
return;
printf ("liste :\n%d", list[0]);
for (i = 1; i < size; i++)
printf (" - %d", list[i]);
printf ("\n");
}
/**
Affichage de la liste de réel
@param list tableau de réel
@param size taille du tableau
@return aucun
*/
void
list_double_display (
const double * const list,
int size)
{
int i;
if (size == 0)
return;
printf ("liste :\n%lf", list[0]);
for (i = 1; i < size; i++)
printf (" - %lf", list[i]);
printf ("\n");
}
/**
Inverse la liste d'entier
@param list tableau d'entier
@param size taille du tableau
@return aucun
*/
void
list_int_reverse (
int *list,
int size)
{
int *listechang = (int *) malloc (size * sizeof (int));
a2ri_erreur_critique_si (listechang == NULL,
"erreur allocation memoire pour list\nlist_int_reverse");
int i;
for (i = 0; i < size; i++)
listechang[i] = list[i];
for (i = 0; i < size; i++)
list[i] = listechang[size - 1 - i];
free (listechang);
}
/**
Inverse la liste de réel
@param list tableau de réel
@param size taille du tableau
@return aucun
*/
void
list_double_reverse (
double *list,
int size)
{
double *listechang = (double *) malloc (size * sizeof (double));
a2ri_erreur_critique_si (listechang == NULL,
"erreur allocation memoire pour list\nlist_double_reverse");
int i;
for (i = 0; i < size; i++)
listechang[i] = list[i];
for (i = 0; i < size; i++)
list[i] = listechang[size - 1 - i];
free (listechang);
}
/**
Décale la liste d'entier à droite de "shift" position(s)
@param list tableau d'entier
@param size taille du tableau
@param shift nombre de décalage à droite
@return aucun
*/
void
list_int_shift_right (
int *list,
int size,
int shift)
{
int *listechang = (int *) malloc (size * sizeof (int));
a2ri_erreur_critique_si (listechang == NULL,
"erreur allocation memoire pour list\nlist_int_shift_right");
int i;
for (i = 0; i < size; i++)
listechang[i] = list[i];
for (i = 0; i < size; i++)
list[i] = listechang[(i - shift + size) % size];
free (listechang);
}
/**
Décale la liste d'entier à gauche de "shift" position(s)
@param list tableau d'entier
@param size taille du tableau
@param shift nombre de décalage à gauche
@return aucun
*/
void
list_int_shift_left (
int *list,
int size,
int shift)
{
int *listechang = (int *) malloc (size * sizeof (int));
a2ri_erreur_critique_si (listechang == NULL,
"erreur allocation memoire pour list\nlist_int_shift_left");
int i;
for (i = 0; i < size; i++)
listechang[i] = list[i];
for (i = 0; i < size; i++)
list[i] = listechang[(i + shift) % size];
free (listechang);
}
/**
Décale la liste de réel à droite de "shift" position(s)
@param list tableau de réel
@param size taille du tableau
@param shift nombre de décalage à droite
@return aucun
*/
void
list_double_shift_right (
double *list,
int size,
int shift)
{
double *listechang = (double *) malloc (size * sizeof (double));
a2ri_erreur_critique_si (listechang == NULL,
"erreur allocation memoire pour list\nlist_double_shift_right");
int i;
for (i = 0; i < size; i++)
listechang[i] = list[i];
for (i = 0; i < size; i++)
list[i] = listechang[(i - shift + size) % size];
free (listechang);
}
/**
Décale la liste de réel à gauche de "shift" position(s)
@param list tableau de réel
@param size taille du tableau
@param shift nombre de décalage à gauche
@return aucun
*/
void
list_double_shift_left (
double *list,
int size,
int shift)
{
double *listechang = (double *) malloc (size * sizeof (double));
a2ri_erreur_critique_si (listechang == NULL,
"erreur allocation memoire pour list\nlist_double_shift_left");
int i;
for (i = 0; i < size; i++)
listechang[i] = list[i];
for (i = 0; i < size; i++)
list[i] = listechang[(i + shift) % size];
free (listechang);
}
/**
Trouve le plus petit entier de la liste
@param list tableau d'entier
@param size taille du tableau
@return le plus petit entier
*/
int
list_int_min (
const int * const list,
int size)
{
int min = list[0];
for (int i = 1; i < size; i++)
if (list[i] < min)
min = list[i];
return min;
}
/**
Trouve le plus grand entier de la liste
@param list tableau d'entier
@param size taille du tableau
@return le plus grand entier
*/
int
list_int_max (
const int * const list,
int size)
{
int max = list[0];
for (int i = 1; i < size; i++)
if (list[i] > max)
max = list[i];
return max;
}
/**
Trouve le plus petit réel de la liste
@param list tableau de réel
@param size taille du tableau
@return le plus petit réel
*/
double
list_double_min (
const double * const list,
int size)
{
double min = list[0];
for (int i = 1; i < size; i++)
if (list[i] < min)
min = list[i];
return min;
}
/**
Trouve le plus grand réel de la liste
@param list tableau de réel
@param size taille du tableau
@return le plus grand réel
*/
double
list_double_max (
const double * const list,
int size)
{
double max = list[0];
for (int i = 1; i < size; i++)
if (list[i] > max)
max = list[i];
return max;
}
/**
Calcul de la moyenne d'une liste d'entier
@param list tableau d'entier
@param size taille du tableau
@return moyenne de la liste
*/
double
list_int_average (
const int * const list,
int size)
{
int somme = 0;
for (int i = 0; i < size; i++)
somme += list[i];
return (somme * 1.0) / (size * 1.0);
}
/**
Calcul de la variance d'une liste d'entier
@param list tableau d'entier
@param size taille du tableau
@return variance de la liste
*/
double
list_int_variance (
const int * const list,
int size)
{
double moyenne = list_int_average (list, size),
somme = 0;
for (int i = 0; i < size; i++)
somme += (list[i] - moyenne) * (list[i] - moyenne);
return somme / (size * 1.0);
}
/**
Calcul de la moyenne d'une liste de réel
@param list tableau de réel
@param size taille du tableau
@return moyenne de la liste
*/
double
list_double_average (
const double * const list,
int size)
{
double somme = 0;
for (int i = 0; i < size; i++)
somme += list[i];
return somme / (size * 1.0);
}
/**
Calcul de la variance d'une liste de réel
@param list tableau de réel
@param size taille du tableau
@return variance de la liste
*/
double
list_double_variance (
const double * const list,
int size)
{
double moyenne = list_double_average (list, size);
double somme = 0;
for (int i = 0; i < size; i++)
somme += (list[i] - moyenne) * (list[i] - moyenne);
return somme / (size * 1.0);
}
/**
Tri de la liste d'entier
@param list tableau d'entier
@param size taille du tableau
@param type ASC ou DESC : ordre croissant ou décroissant
@return aucun
*/
void
list_int_sort (
int *list,
int size,
int type)
{
IFlist_int_tri_rapide (list, 0, size - 1, type);
}
/**
Tri de la liste de réel
@param list tableau de réel
@param size taille du tableau
@param type ASC ou DESC : ordre croissant ou décroissant
@return aucun
*/
void
list_double_sort (
double *list,
int size,
int type)
{
IFlist_double_tri_rapide (list, 0, size - 1, type);
}
/**
Initialisation à zéro d'un temps
@param t pointeur vers un objet temps
@return aucun
*/
void
a2ri_time_init (
a2ri_time * t)
{
t->tv_sec = 0;
t->tv_usec = 0;
}
/**
Acquisition de l'heure actuelle
@param t pointeur vers un objet temps
@return aucun
*/
a2ri_time
a2ri_get_time (
)
{
a2ri_time retour;
gettimeofday (&retour, NULL);
return retour;
}
/**
Conversion d'un temps en double
@param deb le temps inférieur
@param fin le temps supérieur
@return la conversion en double
*/
double
a2ri_time_interval_to_double (
a2ri_time deb,
a2ri_time fin)
{
return ((fin.tv_sec - deb.tv_sec) * 1.0) +
((fin.tv_usec - deb.tv_usec) / 1000000.0);
}
/**
Affichage du temps séparant les deux variables en secondes
@param debut borne de début
@param fin borne de fin
@return aucun
*/
void
a2ri_display_interval_time (
const char * const str,
a2ri_time deb,
a2ri_time fin)
{
printf ("%s%lf\n",
str,
((fin.tv_sec - deb.tv_sec) * 1.0) +
((fin.tv_usec - deb.tv_usec) / 1000000.0));
}