#ifndef _UTILITY_H
#define _UTILITY_H

#include<vector>
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<time.h>
#include<string.h>
#include<ctype.h>
#include<cuda_runtime.h>
#include<string>
#include<fstream>
#include<list>
#include<Windows.h>
#include<process.h>
using namespace std;

typedef long long int64;
typedef unsigned long long uint64;
const int LengthLongType = 64;
const int NumOfGenotype = 3;
/*const int NumOfTable1 = 4;
const int NumOfTable2 = 8;
const int NumOfTable3 = 16;
const int NumOfTable4 = 32;
const int NumOfTable5 = 64;
const int NumOfTable = 1;
*/
const int NumOfCell = 9;


static unsigned char wordbits[65536];

#define MarginalDistrSNP_Y_DimensionX 4
#define MarginalDistrSNP_Y_DimensionY 3

#define THREAD_NUM 256
#define BLOCK_NUM 128

static int popcount(uint64 i)
{
	return(wordbits[i & 0xFFFF] + wordbits[(i >> 16) & 0xFFFF] + wordbits[(i >> 32) & 0xFFFF] + wordbits[i >> 48]);
}

int bitCount(uint64 i);

double Abs(double a);

void CalculateMarginalDistr(uint64 **genoY_G, int nsnps, int nsamples, int* nY_G, int* pMarginalDistrSNP, int* pMarginalDistrSNP_Y);

int GBOOST2(char* filelistname, char* outputfileprefix, int numofCov, float testThreshold);





class DeviceProperties{
public:
	DeviceProperties();
	~DeviceProperties();
	int getDeviceCount();
	cudaDeviceProp getDeviceProp(int i);
	void printDevProp(int i);
private:
	cudaDeviceProp* devPropArray;
	int devCount;
};

class para_data{
public:
	uint64* genoCtrl_F;
	uint64* genoCtrl_M;
	uint64* genoCase_F;
	uint64* genoCase_M;
	int* nlongintCase_Gender;
	int nsnps;
	int nsamples;
	int* pMarginalDistrSNP;
	int* pMarginalDistrSNP_Y;
	int* GenoJointDistr;
	vector<pair<int, int>>*inputPairs;
	vector<pair<int, int>>*outputPairs;
	vector<double>*outputMeasure;

};


extern "C" void cuda_GetInteractionPairs(uint64** genoY_G, int nsnps, int nsamples, int numOfCov, int* nlongintY_G, int* nY_G, int* pMarginalDistrSNP, int* pMarginalDistrSNP_Y,
	const unsigned char* wordbits, int wordBitCount, vector<int>&interactionPairs, vector<double>&interactionMeasure, double thresholdRecord);


#endif