/******************************************************************************************
> [KAZOE]                                                                                 <
> Initial Sofware by [Yannick Verdie, Florent Lafarge], Copyright (C) Inria (GEOMETRICA)  <
> All Rights Reserved, 2012, [Version 1.0].                                               <
******************************************************************************************/
#ifndef GPU_OTHER
#define GPU_OTHER

#include<math.h>
#include <stdio.h>
#include <string.h>

#include "cuda.h"
#include "curand.h"
#include "curand_kernel.h"	
#include "cuda_runtime_api.h"


#include "GPU_common_header.h"
#include "GPU_Macro_Definition.h"

  //use by road, ellipse and tree3D
__device__ __inline__ bool evaluateGreen (const float sigma , const float t ,const float jacobian ,const float randValue )
{
		return ( randValue < ( expf( -sigma / t )* jacobian ));
};

 


class Basic_result
{
public:
	bool* dev_available_spot;

	//----------- global arrays -----------------------------------------
	unsigned int* dev_index_available_spots;//size nb_Cells
	int* dev_index_not_available_spots;//-> use for death, -1 if nothing
	//-------------------------------------------------------------------		
};



class Ellipse_result : public Basic_result
{
public:
	//----------- array of values for each object i--------------------
	float* dev_x;		//ie (dev_x[i] is the centerX of the object i)
	float* dev_y;
	float* dev_angle;
	float* dev_axis0;
	float* dev_axis1;
									
};


 __host__ __device__ __inline__ float getMesure(const float m1,const float m2,const float s1,const float s2,const float resInter,const bhatt_Parameter *param)
{

	//FOR Ellipse !!!!!!!!!!!!

	float sigma_birth;

	sigma_birth = 100.f*((m1-m2)*(m1-m2)/(4.f*(s1+s2))
		-0.5f*logf((2.f*sqrtf(s1*s2))/(s1+s2)));
	float d0 = param->Bhatt_Threshold;


	if ( 
		ELLIPSE_WRONG_DATA_CONTRAST(m1,m2) || ELLIPSE_WRONG_DATA_BOUND(m1,m2,s1,s2)
		) //put 1 in dataterm
		return param->Intersections_Alpha + param->Bhatt_Alpha;
	else
		if (sigma_birth <= d0)
			return  param->Bhatt_Alpha*(1.f-sigma_birth / d0 ) + param->Intersections_Alpha*resInter;
		else
			return param->Bhatt_Alpha*(exp((d0-sigma_birth)/(d0)) - 1.f) + param->Intersections_Alpha*resInter;	 
}









 __global__
void Birth_on_Grid_RJMCMC_bhat_nonHo(const int* val,const int w,const int h,const float *dev_rando, const int size_cell,const int offsetw,const int offseth,const int border, const unsigned int  nb_Cells, //input
				   Ellipse_result *result_Ellipses, unsigned int* dev_minArea, unsigned int* dev_nbObjectsAtPixel_i,unsigned int* dev_nbObjectsAtCell_i, 																							//output
				   const unsigned int* dev_array_quadtree_x,const unsigned int* dev_array_quadtree_y,const unsigned int* dev_array_quadtree_w, const unsigned int* dev_array_quadtree_h, const unsigned int nb_thread_total, const unsigned int offset,
				    const float temperature, bhatt_Parameter *param, const unsigned int nb_Objects_found);

 //1 read of gmem
 __global__
void Birth_on_Grid_RJMCMC_bhat_nonHo(const int* val,const int w,const int h,const float *dev_rando, const int size_cell,const int offsetw,const int offseth,const int border, const unsigned int  nb_Cells, //input
				   Ellipse_result *result_Ellipses, unsigned int* dev_minArea, unsigned int* dev_nbObjectsAtPixel_i,unsigned int* dev_nbObjectsAtCell_i, 																							//output
				   const unsigned int* index_grid,const unsigned int size_cell_qt, const unsigned int nb_thread_total, const unsigned int offset, const float ratio_birth_death,
				    const float temperature, bhatt_Parameter *param, const unsigned int nb_Objects_found);

 __global__
void Birth_on_Grid_RJMCMC_bhat(const int* val,const int w,const int h,const float *dev_rando,const int nb_cell_w,const int nb_cell_h,const int size_cell,const int offsetw,const int offseth,const int border, const unsigned int  nb_Cells, //input
				   Ellipse_result *result_Ellipses, unsigned int* dev_minArea, unsigned int* dev_nbObjectsAtPixel_i,unsigned int* dev_nbObjectsAtCell_i,																						//output
				    const float temperature, bhatt_Parameter *param, const unsigned int nb_Objects_found)	;																							//const 

 __global__
void Birth_on_Grid_RJMCMC_bayesian(const int* val,const int w,const int h,const float *dev_rando,const int nb_cell_w,const int nb_cell_h,const int size_cell,const int offsetw,const int offseth,const int border, const unsigned int  nb_Cells, //input
				   Ellipse_result *result_Ellipses, unsigned int* dev_minArea, unsigned int* dev_nbObjectsAtPixel_i,unsigned int* dev_nbObjectsAtCell_i, 																							//output
				    const float temperature, bayesian_Parameter *param, const unsigned int nb_Objects_found)	;	


 __global__
void Death_on_Grid_RJMCMC_bhat(const int* val, const int w,const int h,const float *dev_rando,const int nb_cell_w,const int nb_cell_h,const int size_cell,const int offsetw,const int offseth,const int border,//input
							  Ellipse_result *result_Ellipses, unsigned int* dev_minArea, unsigned int* dev_nbObjectsAtPixel_i,unsigned int* dev_nbObjectsAtCell_i, const float ratio_birth_death,								//output
							   const float temperature, bhatt_Parameter *param, const unsigned int nb_Objects_found, const unsigned int nb_Cells);

 __global__
void Death_on_Grid_RJMCMC(const int* val, const int w,const int h,const float *dev_rando,const int nb_cell_w,const int nb_cell_h,const int size_cell,const int offsetw,const int offseth,const int border,//input
							  Ellipse_result *result_Ellipses, unsigned int* dev_minArea, unsigned int* dev_nbObjectsAtPixel_i, unsigned int* dev_nbObjectsAtCell_i, 									//output
							  const float temperature, bayesian_Parameter *dev_param,const unsigned int nb_Objects_found, const unsigned int nb_Cells);											//const 




 __global__
void EnlargeShrink_on_Grid(const int* val, const int w,const int h,const float *dev_rando,const int nb_cell_w,const int nb_cell_h,const int size_cell,const int offsetw,const int offseth,const int border,//input
							  Ellipse_result *result_Ellipses, unsigned int* dev_minArea, unsigned int* dev_nbObjectsAtPixel_i,unsigned int* dev_nbObjectsAtCell_i, 								//output
							   const float temperature, bayesian_Parameter *param, const unsigned int nb_Objects_found, const unsigned int nb_Cells);

 __global__
void Rotate_on_Grid_bhat(const int* val, const int w,const int h,const float *dev_rando,const int nb_cell_w,const int nb_cell_h,const int size_cell,const int offsetw,const int offseth,const int border,//input
							  Ellipse_result *result_Ellipses, unsigned int* dev_minArea, unsigned int* dev_nbObjectsAtPixel_i,unsigned int* dev_nbObjectsAtCell_i, 								//output
							   const float temperature, bhatt_Parameter *param, const unsigned int nb_Objects_found, const unsigned int nb_Cells)	;


  __global__
 void Rotate_on_Grid(const int* val, const int w,const int h,const float *dev_rando,const int nb_cell_w,const int nb_cell_h,const int size_cell,const int offsetw,const int offseth,const int border,//input
							  Ellipse_result *result_Ellipses, unsigned int* dev_minArea, unsigned int* dev_nbObjectsAtPixel_i,unsigned int* dev_nbObjectsAtCell_i, 								//output
							   const float temperature, bayesian_Parameter *param, const unsigned int nb_Objects_found, const unsigned int nb_Cells)	;

 __global__
void Translate_on_Grid_bhat(const int* val, const int w,const int h,const float *dev_rando,const int nb_cell_w,const int nb_cell_h,const int size_cell,const int offsetw,const int offseth,const int border,//input
							  Ellipse_result *result_Ellipses, unsigned int* dev_minArea, unsigned int* dev_nbObjectsAtPixel_i,unsigned int* dev_nbObjectsAtCell_i, 								//output
							   const float temperature, bhatt_Parameter *param, const unsigned int nb_Objects_found, const unsigned int nb_Cells);

 __global__
void Translate_on_Grid(const int* val, const int w,const int h,const float *dev_rando,const int nb_cell_w,const int nb_cell_h,const int size_cell,const int offsetw,const int offseth,const int border,//input
							  Ellipse_result *result_Ellipses, unsigned int* dev_minArea, unsigned int* dev_nbObjectsAtPixel_i, unsigned int* dev_nbObjectsAtCell_i, 									//output
							  const float temperature, bayesian_Parameter *dev_param,const unsigned int nb_Objects_found, const unsigned int nb_Cells);

  __global__
 void EnlargeShrink_on_Grid_bhat(const int* val, const int w,const int h,const float *dev_rando,const int nb_cell_w,const int nb_cell_h,const int size_cell,const int offsetw,const int offseth,const int border,//input
							  Ellipse_result *result_Ellipses, unsigned int* dev_minArea, unsigned int* dev_nbObjectsAtPixel_i,unsigned int* dev_nbObjectsAtCell_i, 								//output
							   const float temperature, bhatt_Parameter *param, const unsigned int nb_Objects_found, const unsigned int nb_Cells);

  __global__
 void EnlargeShrink_on_Grid(const int* val, const int w,const int h,const float *dev_rando,const int nb_cell_w,const int nb_cell_h,const int size_cell,const int offsetw,const int offseth,const int border,//input
							  Ellipse_result *result_Ellipses, unsigned int* dev_minArea, unsigned int* dev_nbObjectsAtPixel_i,unsigned int* dev_nbObjectsAtCell_i, 								//output
							   const float temperature, bayesian_Parameter *param, const unsigned int nb_Objects_found, const unsigned int nb_Cells);




 





#endif

