#include <stdio.h>
#include <stdlib.h>

#include "gradient.h"

#define EPSILON  0.000001
#define MAX_ITER 100000

/**
 * Fonction � �tudier
 * * [1 + (x1 + x2 + 1)2 . (19 - 14x1 + 3x12 - 14x2 + 6x1x2 + 3x22)].[30 + (2x1 - 3x2)2 . (18 - 32x1 + 12x12 + 48x2 - 36x1x2 + 27x22)]
 * Domaine de recherche :
 * * -2 < xj < 2 ; j := [1,2]
 * * 4 minima locaux
 * * 1 minimum global :
 *      (x1,x2)* = (0,-1);
 *      GP((x1,x2)*) = 3;
 */
double* GP(const double x[], const size_t dimension)
{
    static double result[1] = {0};

    if( dimension != 2 ){
        perror("Wrong dimension for 'GP' function");
        return NULL; // Fonction de R^3 vers R
    }

    result[0] = (
               1
               + pow(
                   x[0]
                   + x[1]
                   + 1
                   ,2)
               *
               (
                   19
                   - 14 * x[0]
                   + 3 * pow(x[0],2)
                   - 14 * x[1]
                   + 6 * x[0] * x[1] +
                   3 * pow(x[0],2)
               )
           ) *
           (
               30
               + pow(
                   2 * x[0]
                   - 3 * x[1]
                   ,2)
               *
               (
                   18
                   - 32 * x[0]
                   + 12 * pow(x[0],2)
                   + 48 * x[1]
                   - 36 * x[0] * x[1]
                   + 27 * pow(x[1],2)
               )
           );

    return result;
}

double* ES(const double x[], const size_t dimension)
{
    static double result[1] = {0};

    if( dimension != 3 ){
        perror("Wrong dimension for 'ES' function");
        return NULL; // Fonction de R^3 vers R
    }

    result[0] = x[0]*x[0] + x[1]*x[1] + x[2]*x[2];

    return result;
}

int main()
{
    int choix = 1;
    float x0[3] = {2,1,2}, pas = 0.1;

    // Init the random seed
    srand (time (NULL));

    printf("\nVecteur initial x : ");
    /*
     * saisir le vecteur en donnant chaque composante s�par�e par une virgule.
     * e.g : 5.0,3.0,4.0
     */
//    scanf("%f,%f,%f",&x0[0],&x0[1],&x0[2]);
    printVector(x0,3);
    printf("\nFunction value for x : %f",ES(x0));

    printf("\nChoix de la m�thode :");
    printf("\n1 - Gradient � pas fixe");
    printf("\n2 - Gradient � pas optimal");
    printf("\n3 - Benchmark\n");

//    scanf("%d",&choix);
    printf("%d\n",choix);

    switch(choix)
    {
    case 1 :
        printf("\nPas : ");
        /*
         * saisir un pas assez faible, pour que le prochain point soit dans le voisinage du premier vecteur.
         * e.g : 0.1
         */
        scanf("%f",&pas);
        printf("%f\n",pas);

/*
        resolveByGradientPasFixe(x0,pas,EPSILON,MAX_ITER);
*/
        break;
    case 2 :
        resolveGradientOptimal(x0,EPSILON,MAX_ITER);
        break;
    case 3 :
        printf("\nPas : ");
        /*
         * saisir un pas assez faible, pour que le prochain point soit dans le voisinage du premier vecteur.
         * e.g : 0.1
         */
//            scanf("%f",&pas);
        printf("%f\n",pas);

        printf("\nGRADIENT PAS FIXE :");
/*
        resolveByGradientPasFixe(x0,pas,EPSILON,MAX_ITER);
*/
        printf("\n\nGRADIENT PAS OPTIMAL :");
        resolveGradientOptimal(x0,EPSILON,MAX_ITER);
        break;
    }

    return EXIT_SUCCESS;
}
