#include "tbb/task_scheduler_init.h"
#include "tbb/parallel_for.h"
#include "tbb/tick_count.h"
#include <iostream>
#include <algorithm>

using namespace std;
using namespace tbb;

#define N 500000

template <class T> class sort_range {
	T *poczatek, *koniec;
	size_t min_rozmiar;
public:
	T *begin() const { return poczatek; }
	T *end() const { return koniec;	}
	bool empty() const { return poczatek == koniec;	}
	bool is_divisible() const {	return (size_t)(koniec - poczatek) > min_rozmiar; }

	sort_range(T *poczatek_, T *koniec_, size_t rozmiar_ = 20) :
		poczatek(poczatek_), koniec(koniec_), min_rozmiar(rozmiar_)
	{}
	sort_range(sort_range<T>& r, split) {
		size_t rozmiar = r.end() - r.begin();
		T m, *i, *j, *k;
		i = r.begin() + rand() % rozmiar;
		j = r.begin() + rand() % rozmiar;
		k = r.begin() + rand() % rozmiar;
		m = (*i > *j) ? *i : *j;
		m = (m > *k) ? *k : m;
		i = r.begin();
		j = r.end() - 1;
		do {
			while (*i < m) ++i;
			while (*j > m) --j;
			if (i <= j) {
				swap(*i, *j);
				++i;
				--j;
			}
		} while (i <= j);
		k = r.end();
		if (r.begin() < i)
			r.koniec = i;
		if (k > i) {
			poczatek = i;
			koniec = k;
			min_rozmiar = r.min_rozmiar;
		}
	}
};

struct sort_body {
	void operator()(const sort_range<double>& r) const {
		sort(r.begin(), r.end());
	}
};

int main(int argc, char* argv[])
{
	double *tablica = new double[N];
	task_scheduler_init init;
	tick_count t0, t1;
	
	for (int i = 0; i < N; ++i)
		tablica[i] = (double)rand() / (double)RAND_MAX;
			
	t0 = tick_count::now();
	parallel_for(sort_range<double>(tablica, tablica + N), sort_body(), auto_partitioner());
	t1 = tick_count::now();
	
	cout << "Czas:  " << (t1 - t0).seconds() << " s" << endl;

	delete[] tablica;

	cin.get();
	return 0;
}

