#include <iostream>
#include <tbb/parallel_reduce.h>
#include <tbb/parallel_for.h>
#include <tbb/blocked_range.h>
#include <tbb/task_scheduler_init.h>

#define N 10

using namespace std;
using namespace tbb;

void func_for( int *x )
{
	*x = -(*x);
}

int func_red( int *x )
{
	return *x;
}

class Task {
	private:
		int *local_a;

	public:
		int sum;

		Task( int _a[] ) : local_a( _a ), sum( 0 ) {}

		// parallel_for
		void operator( )( const blocked_range<long> &r ) const {
			for ( long i=r.begin(); i!=r.end( ); ++i ) {
				func_for( &local_a[i] );
			}
		}

		// parallel_reduce
		Task( Task &subtask, split )
		{
			local_a = subtask.local_a;
			sum = 0;
		}

		void operator()( const blocked_range<int> &r ) {
			for ( int i=r.begin(); i!=r.end( ); ++i ) {
				sum += func_red( &local_a[i] );
			}
		}

		void join( const Task &subtask )
		{
			sum += subtask.sum;
		}
};

void par_for_neg(int x, int y, int *a)
{
	Task task(a);

	parallel_for(blocked_range<long>(x,y,2), task);

	return;
}

int par_reduce_sum(int x, int y, int *a)
{
	Task task(a);

	parallel_reduce(blocked_range<int>(x,y,N/10), task);

	return task.sum;
}

int main()
{
	task_scheduler_init init(2);

	int a[N];

	for ( int i=0; i<N; i++ ) {
		a[i] = (int) i;
	}

	cout << endl << "Total (par_red): " << par_reduce_sum(0,N,a) << endl;

	cout << endl << "Total (par_for): reset values to their negative " << endl;
	par_for_neg(0,N,a);

	cout << endl << "Total (par_red): " << par_reduce_sum(0,N,a) << endl;

	return 0;
}

