/* -*- 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/3d/transformmock.hh>

#include <mia/internal/plugintester.hh>
#include <mia/3d/splinepenalty/divcurl.hh>
#include <mia/3d/interpolator.hh>

using namespace divcurl_splinepenalty; 
NS_MIA_USE
namespace bfs=::boost::filesystem;

/*
  The proper evaluation of the penalty and its gradient 
  is done in test_ppmatrix.cc. Here we only test the proper 
  initialization and transfer of data. 
*/

BOOST_AUTO_TEST_CASE( test_divcurl_cost_w2_d1_c1 ) 
{
	C3DBounds size(10,10,10); 
	C3DFVector range(32,32,32); 
	auto kernel = produce_spline_kernel("bspline:d=3"); 
	
	auto plugin = BOOST_TEST_create_from_plugin<C3DDivcurlSplinePenaltyPlugin>("divcurl:weight=2.0"); 
	
	plugin->initialize(size, range, kernel);

	C3DPPDivcurlMatrix test_matrix(size, range, *kernel, 1.0, 1.0); 
	
	C3DFVectorfield coefficients(size); 
	
	BOOST_CHECK_EQUAL(plugin->value(coefficients), 0.0); 
	
	coefficients(5,5,5) = C3DFVector(2,3,4); 

	BOOST_CHECK_EQUAL(plugin->value(coefficients), 2 * (test_matrix * coefficients));
	
	CDoubleVector plug_gradient(size.product() * 3); 
	CDoubleVector test_gradient(size.product() * 3); 

	BOOST_CHECK_EQUAL(plugin->value_and_gradient(coefficients, plug_gradient), 
			  2 * test_matrix.evaluate(coefficients,test_gradient)); 

	for (auto ipg = plug_gradient.begin(), itg = test_gradient.begin(); 
	     ipg != plug_gradient.end(); ++ipg, ++itg)
		BOOST_CHECK_CLOSE(*ipg, -2.0 * *itg, 0.1); 

	
}

