#include "real.h"
#include "simplex.h"
#include <stdlib.h>
#include <stdio.h>
#include "real.h"

int downhill_simplex(
	real(*fun)(real*),
	real** simplex, int d,
	real simplex_size_goal){

int hi,lo;

real* centroid=(real*)calloc(d,sizeof(real));
real* fun_values=(real*)calloc(d+1,sizeof(real));
real* point=(real*)calloc(d,sizeof(real));

simplex_initiate(fun,simplex,fun_values,d,&hi,&lo,centroid);

while(size(simplex,d)>simplex_size_goal){
	reflection(simplex[hi],centroid,d,point);
	real f_re=fun(point);
	if(f_re<fun_values[lo]){
		expansion(simplex[hi],centroid,d,point);
		for(int i=0;i<d;i++) simplex[hi][i]=point[i];
		fun_values[hi]=fun(point);
		simplex_update(simplex,fun_values,d,&hi,&lo,centroid);

fprintf(stderr,
"expansion  :  simplex_size=%#9.3g\t f_high=%#9.3g\n",
size(simplex,d),fun_values[hi]);

		}
	else if(f_re<fun_values[hi]){
		for(int i=0;i<d;i++) simplex[hi][i]=point[i];
		fun_values[hi]=f_re;
		simplex_update(simplex,fun_values,d,&hi,&lo,centroid);

fprintf(stderr,
"reflection :  simplex_size=%#9.3g\t f_high=%#9.3g\n",
size(simplex,d),fun_values[hi]);

		}
	else{
		contraction(simplex[hi],centroid,d,point);
		real f_co=fun(point);
		if(f_co<fun_values[hi]){
			for(int i=0;i<d;i++) simplex[hi][i]=point[i];
			fun_values[hi]=f_co;
			simplex_update(simplex,fun_values,d,&hi,&lo,centroid);

fprintf(stderr,
"contraction:  simplex_size=%#9.3g\t f_high=%#9.3g\n",
size(simplex,d),fun_values[hi]);

			}
		else{
			reduction(simplex,d,lo);
			simplex_initiate(fun,simplex,fun_values,d,&hi,&lo,centroid);

fprintf(stderr,
"reduction :  simplex_size=%#9.3g\t f_high=%#9.3g\n",
size(simplex,d),fun_values[hi]);

			}
		}
	}// end while
	return 0;
}
