#include "tbb/task_scheduler_init.h"
#include "tbb/parallel_do.h"
#include "tbb/tick_count.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>

using namespace std;
using namespace tbb;

#define N 500000
typedef pair<double *, double *> zakres;

struct Sortowanie {	
	static const int min_rozmiar = 20;
	void operator()(zakres& z, parallel_do_feeder<zakres>& feeder) const {
		int rozmiar = z.second - z.first;
		double m, *i, *j, *k;
		// sortujemy zwykłą metodą jeżeli rozmiar jest za mały
		if (rozmiar <= min_rozmiar) {
			sort(z.first, z.second);
			return;
		}
		// wybieramy z trzech losowych elementów wartość środkową
		i = z.first + rand() % rozmiar;
		j = z.first + rand() % rozmiar;
		k = z.first + rand() % rozmiar;
		m = (*i > *j) ? *i : *j;
		m = (m > *k) ? *k : m;
		i = z.first;
		j = z.second - 1;
		do {
			while (*i < m) ++i;
			while (*j > m) --j;
			if (i <= j) {
				swap(*i, *j);
				++i;
				--j;
			}
		} while (i <= j);
		if (z.first < i) feeder.add(zakres(z.first, i));
		if (z.second > i) feeder.add(zakres(i, z.second));
	}
};

int main(int argc, char* argv[])
{
	double *tablica = new double[N];
	task_scheduler_init init;
	tick_count t0, t1, t2;
	
	srand((unsigned int)time(NULL));
	for (int i = 0; i < N; ++i)
		tablica[i] = (double)rand() / (double)RAND_MAX;
			
	vector<zakres> obszary;
	obszary.push_back(zakres(tablica, tablica + N));

	t0 = tick_count::now();
	Sortowanie s;
	parallel_do(obszary.begin(), obszary.end(), s);
	t1 = tick_count::now();
	
	cout << "Czas: " << (t1 - t0).seconds() << " s" << endl;

	delete[] tablica;

	cin.get();
	return 0;
}

