/* -*- mia-c++  -*-
 *
 * This file is part of MIA - a toolbox for medical image analysis 
 * Copyright (c) Leipzig, Madrid 1999-2017 Gert Wollny
 *
 * MIA is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with MIA; if not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <mia/core/parallelcxx11.hh>
#include <mia/internal/autotest.hh>
using namespace mia;
using namespace std; 

BOOST_AUTO_TEST_CASE (test_preduce)
{
	int identity_value = 0;
	C1DParallelRange range(0, 200, 10);

	vector<int> input(200);
	for (int i = 0; i < 200; ++i)
		input[i] = i;

	auto p_func = [&input](const C1DParallelRange& range, int in_value) {
		for (auto i= range.begin(); i != range.end(); ++i) {
			in_value += input[i]; 
		}
		return in_value; 
	};

	auto r_func = [](int a, int b){return a+b;}; 
	
	int result = preduce(range, identity_value, p_func, r_func); 
	
	BOOST_CHECK_EQUAL(result, 100*199); 
	
}

BOOST_AUTO_TEST_CASE (test_preduce_vector_result)
{
	vector<int> identity_value(2, 0);
	C1DParallelRange range(0, 200, 10);

	vector<int> input(200);
	for (int i = 0; i < 200; ++i)
		input[i] = i;

	auto p_func = [&input](const C1DParallelRange& range, vector<int> in_value) -> vector<int>{
		for (auto i= range.begin(); i != range.end(); ++i) {
			in_value[0] += input[i];
			in_value[1] += 2 * input[i]; 
		}
		return in_value; 
	};

	auto r_func = [](const vector<int>& a, const vector<int>& b) -> vector<int>{
		vector<int> out(a);
		transform(out.begin(), out.end(), b.begin(), out.begin(), [](int ia, int ib){return ia + ib;}); 
		return out;
	}; 
	
	auto  result = preduce(range, identity_value, p_func, r_func);
	
	BOOST_CHECK_EQUAL(result.size(), 2u); 
	BOOST_CHECK_EQUAL(result[0], 100*199);
	BOOST_CHECK_EQUAL(result[1], 2 * 100*199); 
	
}


BOOST_AUTO_TEST_CASE (test_pfor)
{

	C1DParallelRange range(0, 200, 10);

	vector<int> input(200);
	for (int i = 0; i < 200; ++i)
		input[i] = i;

	auto p_func = [&input](const C1DParallelRange& range) {
		for (auto i= range.begin(); i != range.end(); ++i) {
			input[i] *= 2; 
		}
	};


	pfor(range, p_func); 
	
	for (int i = 0; i < 200; ++i) {
		BOOST_CHECK_EQUAL(input[i], 2*i); 
	}
}
