#pragma once
#include "Tests.h"


class LCG : public TestCase {
private:
	size_t randomNumbers;
	size_t threadCount;
	std::vector<float> randomBuffer;
	std::vector<float> seedBuffer;
	std::string kernel_name;
	cl::Buffer clHistoBuffer;
	std::vector<int> histoBuffer;
	size_t bucketNum;
public:
	LCG(size_t _randomNumbers, size_t _threadCount, size_t _bucketNum);
	void collect_results(cl::CommandQueue* queue);
	void gpu_compute(cl::Context* context, cl::CommandQueue* queue, cl::Program* program, cl::Event* Event);
	void cpu_compute();
	bool validate_results();
	std::string description();
};

class LFG : public TestCase {
private:
	size_t randomNumbers;
	size_t threadCount;
	std::vector<float> randomBuffer;
	std::vector<float> seedBuffer;
	std::string kernel_name;
	size_t randomStateSize;
	cl::Buffer clHistoBuffer;
	size_t bucketNum;
	std::vector<int> histoBuffer;
public:
	LFG(size_t _randomNumbers, size_t _threadCount, size_t _randomStateSize, size_t _bucketNum);
	void collect_results(cl::CommandQueue* queue);
	void gpu_compute(cl::Context* context, cl::CommandQueue* queue, cl::Program* program, cl::Event* Event);
	void cpu_compute();
	bool validate_results();
	std::string description();
};

class CTG : public TestCase {
private:
	size_t randomNumbers;
	size_t threadCount;
	std::vector<float> randomBuffer;
	std::vector<float> seedBuffer;
	std::string kernel_name;
	cl::Buffer clHistoBuffer;
	size_t bucketNum;
	std::vector<int> histoBuffer;
public:
	CTG(size_t _randomNumbers, size_t _threadCount, size_t _bucketNum);
	void collect_results(cl::CommandQueue* queue);
	void gpu_compute(cl::Context* context, cl::CommandQueue* queue, cl::Program* program, cl::Event* Event);
	void cpu_compute();
	bool validate_results();
	std::string description();
};

class Hybrid : public TestCase {
private:
	size_t randomNumbers;
	size_t threadCount;
	std::vector<float> randomBuffer;
	std::vector<float> seedBuffer;
	std::string kernel_name;
	cl::Buffer clHistoBuffer;
	size_t bucketNum;
	std::vector<int> histoBuffer;
public:
	Hybrid(size_t _randomNumbers, size_t _threadCount, size_t _bucketNum);
	void collect_results(cl::CommandQueue* queue);
	void gpu_compute(cl::Context* context, cl::CommandQueue* queue, cl::Program* program, cl::Event* Event);
	void cpu_compute();
	bool validate_results();
	std::string description();
};

class Halton : public TestCase {
private:
	size_t randomNumbers;
	size_t threadCount;
	size_t base;
	std::vector<float> randomBuffer;
	std::string kernel_name;
	cl::Buffer clHistoBuffer;
	size_t bucketNum;
	std::vector<int> histoBuffer;
public:
	Halton(size_t _randomNumbers, size_t _threadCount, size_t _base, size_t _bucketNum);
	void collect_results(cl::CommandQueue* queue);
	void gpu_compute(cl::Context* context, cl::CommandQueue* queue, cl::Program* program, cl::Event* Event);
	void cpu_compute();
	bool validate_results();
	std::string description();
};