#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/**
la structure pour définir un vecteur de Rn
*/
typedef struct {
	double * pvecteur;
	int dimension;
} SVecteurRn;

typedef SVecteurRn * PVecteurRn;

/**
La fonction pour allouer un vecteur de Rn
*/
PVecteurRn allouerVecteurRn(int dimension);

/**
La fonction pour faire une copie d'un vecteur de Rn
*/
PVecteurRn copierVecteurRn(PVecteurRn pvect);

/**
La fonction pour afficher un vecteur de Rn
*/
void affVecteurRn(PVecteurRn pvect);

/**
La fonction pour liberer un vecteur de Rn
*/
void libererVecteurRn(PVecteurRn pvect);

/**
La fonction pour calculer le produit scalaire de deux vecteurs de Rn
*/
double produitScalaireRn(PVecteurRn pvect1, PVecteurRn pvect2);

/**
La fonction pour calculer la norme d'un vecteur
*/
double norme(PVecteurRn pvect);

/**
La fonction pour calculer le carré de la norme d'un vecteur
*/
double normeCarree(PVecteurRn pvect);

/**
La fonction pour additionner deux vecteurs de Rn
*/
PVecteurRn addVecteurRn(PVecteurRn pvect1, PVecteurRn pvect2);


/**
La fonction pour soustraire deux vecteurs de Rn
*/
PVecteurRn difVecteurRn(PVecteurRn pvect1, PVecteurRn pvect2);

/**
La fonction pour multiplier un vecteur de Rn par un scalaire
*/
PVecteurRn mulScalVecteurRn(double coeff,PVecteurRn pvect1);

/**
la structure pour définir un Matrice de Rn
*/
typedef struct {
	double ** pmatrice;
	int dimension;
} SMatriceRn;

typedef SMatriceRn * PMatriceRn;

/**
La fonction pour allouer un Matrice de Rn
*/
PMatriceRn allouerMatriceRn(int dimension);

/**
La fonction pour allouer une Matrice Identité de Rn @ Laurent
*/
PMatriceRn allouerMatriceIdentiteRn(int dimension);

/**
La fonction pour faire une copie d'un Matrice de Rn
*/
PMatriceRn copierMatriceRn(PMatriceRn pvect);

/**
La fonction pour additionner deux matrices de Rn
*/
PMatriceRn addMatriceRn(PMatriceRn pmat1, PMatriceRn pmat2);

/**
La fonction pour multiplier deux matrices de Rn
*/
PMatriceRn mulMatricesRn(PMatriceRn pmat1, PMatriceRn pmat2);

/**
La fonction pour multiplier un scalaire et une matrice.
*/
PMatriceRn mulScalMatriceRn(double coeff,PMatriceRn pmat);

/**
La fonction pour afficher un Matrice de Rn
*/
void affMatriceRn(PMatriceRn pvect);

/**
La fonction pour calculer le produit d'une matrice par un vecteur
*/
PVecteurRn produitMatriceVecteurRn(PMatriceRn pmat, PVecteurRn pvect);

/**
La fonction pour calculer du produit matriciel tu .  v dans Rn
*/
PMatriceRn produitVecteursRn(PVecteurRn pvect1, PVecteurRn pvect2);

/**
La fonction pour liberer un Matrice de Rn
*/
void libererMatriceRn(PMatriceRn pvect);

/**
L'algorithme de gradient à pas fixe
*/
PVecteurRn gradientPasFixe(PVecteurRn px0, double pas, double epsilon, int nbMaxIterations);

/**
L'algorithme de gradient à pas optimal avec la règle d'Armijo
*/
PVecteurRn gradientPasOptimal(PVecteurRn px0, double pas, double epsilon, int nbMaxIterations);

/**
* Calcul du pas Armijo @ Laurent
*/
double pasArmijo(PVecteurRn px, PVecteurRn pdirectionDescente, double pas);

/**
*L'algorithme de quasi Newton @ Laurent
*/
PVecteurRn quasiNewton(PVecteurRn x0, int dimension, double pasArmijoInit, double epsilon, int maxIter);

/**
La fonction à optimiser
*/
double J(PVecteurRn px);

/**
Le gradient de la fonction à optimiser s'il est connu
*/
PVecteurRn gradientJ(PVecteurRn px);


