function.h 21.3 KB
Newer Older
1 2
#pragma once

3 4
#include <functional>
#include <string>
5
#include <fstream>
6

7
#include "common.h"
8
#include "args.h"
9
#include "params.h"
10
#include "data.h"
11

Laurent Belcour's avatar
Laurent Belcour committed
12
/*! \brief A representation of an analytical function.
13
 *  \ingroup core
Laurent Belcour's avatar
Laurent Belcour committed
14
 *
15
 *  \details
16
 *  function are functors with a domain of definition specified by a vector 
Laurent Belcour's avatar
Laurent Belcour committed
17
 *  interval \f$[\vec{min} .. \vec{max}]\f$ where \f$\vec{min}\f$ and 
18 19 20 21
 *  \f$\vec{max}\f$ have the size of the input domain.
 *
 *  Any function used by the fitting algorithm should overload publicly this
 *  interface.
Laurent Belcour's avatar
Laurent Belcour committed
22
 */
23
class function : public parametrized
24 25 26
{
	public: // methods

27 28
		/* INTERFACE */

29
		// Overload the function operator
30
		virtual vec operator()(const vec& x) const = 0 ;
Laurent Belcour's avatar
Laurent Belcour committed
31
		virtual vec value(const vec& x) const = 0 ;
32

33
		//! Load function specific files
34
		virtual void load(std::istream& in) = 0 ;
35

36 37 38 39 40
		//! \brief Provide a first rough fit of the function. 
		//!
		//! \details
		//! Can be used to set the diffuse component of the function for
		//! example.
41
		virtual void bootstrap(const data* d, const arguments& args) {}
42

43
		//! Provide the dimension of the input space of the function
44
		virtual int dimX() const { return _nX ; }
45
		//! Provide the dimension of the output space of the function
46 47
		virtual int dimY() const { return _nY ; }

48
		//! Set the dimension of the input space of the function
49
		virtual void setDimX(int nX) { _nX = nX ; }
50
		//! Set the dimension of the output space of the function
51 52 53 54 55
		virtual void setDimY(int nY) { _nY = nY ; }

		// Acces to the domain of definition of the function
		virtual void setMin(const vec& min) 
		{
56
#ifdef DEBUG
57
			assert(min.size() == _nX) ;
58
#endif
59
			_min = min ; 
60 61 62
		}
		virtual void setMax(const vec& max) 
		{
63
#ifdef DEBUG
64
			assert(max.size() == _nX) ;
65
#endif
66 67 68 69
			_max = max ; 
		}
		virtual vec getMin() const { return _min ; }
		virtual vec getMax() const { return _max ; }
70

71

72
		/* EXPORT FUNCTIONS */
73

74 75 76 77 78
		//! \brief Save the current function to a specific file type, args can 
		//! be used to differenciate the type of export.
		//!
		//! \see rational_function.cpp for an example
		virtual void save(const std::string& filename, const arguments& args) const;
79

80 81 82 83
		//! \brief save the header of the output function file. The header should
		//! store general information about the fit such as the command line used
		//! the dimension of the fit. L2 and L_inf distance could be added here.
		virtual void save_header(std::ostream& out, const arguments& args) const ;
84

85 86 87 88
		//! \brief save function specific data. This has no use for ALTA export
		//! but allows to factorize the code in the C++ or matlab export by
		//! defining function calls that are common to all the plugins.
		virtual void save_body(std::ostream& out, const arguments& args) const ;
89

90 91 92 93
		//! \brief save object specific information. For an ALTA export the
		//! coefficients will be exported. For a C++ or matlab export, the call
		//! to the associated function will be done.
		virtual void save_call(std::ostream& out, const arguments& args) const ;
94 95


96
		/* METRIC FUNCTIONS */
97 98 99 100 101 102

		//! \brief L2 norm to data.
		double L2_distance(const data* d) const ;

		//! \brief Linf norm to data.
		double Linf_distance(const data* d) const ;
103

104

105
	protected: // data
106

107
		// Dimension of the function & domain of definition.
108
		int _nX, _nY ;
109
		vec _min, _max ;
110 111
};

112
/*! \brief Non-linear function interface
113
 *  \ingroup core
114
 *
115
 * \details
116 117 118 119 120
 * Provide a way to obtain the dérivative of the function with respect to its
 * parameters. If the function \f$f(\vec{x})\f$ is defined for a vector of
 * parameters \f$\vec{a}\f$, the resulting vector is \f$df_i = {df \over 
 * da_i}\f$. 
 *
121
 * \note It is not necessary to have an analytical formulation
122 123
 * of the derivative and a numerical evaluation of it can be provided.
 */
124 125 126 127
class nonlinear_function: public function
{
	public: // methods

128 129 130
		//! Number of parameters to this non-linear function
		virtual int nbParameters() const = 0;

131
		//! Get the vector of parameters for the function
132
		virtual vec parameters() const = 0;
133 134

		//! Update the vector of parameters for the function
135 136
		virtual void setParameters(const vec& p) = 0;

137 138 139 140 141 142 143 144 145 146
		//! \brief get the maximum value for all the parameters in a vector
		//! format. The maximum vector and the parameter vector have the same
		//! indexing.
		virtual vec getParametersMax() const;

		//! \brief get the minimum value for all the parameters in a vector
		//! format. The minimum vector and the parameter vector have the same
		//! indexing.
		virtual vec getParametersMin() const;

147 148 149 150
		//! \brief Obtain the derivatives of the function with respect to the 
		//! parameters. 
		//
		// The x input of this function is the position in the input space and 
151 152
		// has size dimX(), the resulting vector has the size of the parameters
		// times the size of the output domain.
153 154 155
		//
		// The result vector should be orderer as res[i + dimY()*j], output
		// dimension first, then parameters.
156
		virtual vec parametersJacobian(const vec& x) const = 0;
157 158 159 160 161 162 163 164 165 166 167 168 169 170

		//! \brief default non_linear import. Parse the parameters in order.
		virtual void load(std::istream& in)
		{
			// Parse line until the next comment
			while(in.peek() != '#')
			{
				char line[256];
				in.getline(line, 256);
			}

			// Checking for the comment line #FUNC nonlinear_function_phong
			std::string token;
			in >> token;
171 172 173 174 175 176 177
			if(token.compare("#FUNC") != 0) 
			{ 
				std::cerr << "<<ERROR>> parsing the stream. The #FUNC is not the next line defined." << std::endl; 
#ifdef DEBUG
				std::cout << "<<DEBUG>> got: \"" << token << "\"" << std::endl;
#endif
			}
178 179

			in >> token;
180
			if(token.compare("nonlinear_function") != 0)
181 182
			{
				std::cerr << "<<ERROR>> parsing the stream. A function name is defined." << std::endl;
183
				std::cerr << "<<ERROR>> did you forget to specify the plugin used to export?" << std::endl;
184 185 186 187 188 189 190 191 192 193 194 195 196 197
			}

			int nb_params = nbParameters();
			vec p(nb_params);
			for(int i=0; i<nb_params; ++i)
			{
				in >> token >> p[i];
			}

			setParameters(p);
		}

		//! \brief default non_linear export. It will dump the parameters in order
		//! but won't assign names for the function nor parameters.
198
		virtual void save_call(std::ostream& out, const arguments& args) const
199 200 201 202 203 204 205 206 207 208 209 210 211 212
		{
			if(!args.is_defined("export"))
			{
				// Dump a #FUNC nonlinear
				out << "#FUNC nonlinear_function" << std::endl;

				// Dump the parameters in order
				vec p = parameters();
				for(int i=0; i<p.size(); ++i)
				{
					out << "param_" << i+1 << "\t" << p[i] << std::endl;
				}
				out << std::endl;
			}
213

214
			function::save_call(out, args);
215
		}
216
};
217

Laurent Belcour's avatar
Laurent Belcour committed
218

219
class compound_function: public nonlinear_function
Laurent Belcour's avatar
Laurent Belcour committed
220 221
{
	public: // methods
222

Laurent Belcour's avatar
Laurent Belcour committed
223 224 225 226 227 228 229 230
		// Overload the function operator
		virtual vec operator()(const vec& x) const
		{
			return value(x);
		}
		virtual vec value(const vec& x) const
		{
			vec res(_nY);
231 232
			res = vec::Zero(_nY);
			for(unsigned int i=0; i<fs.size(); ++i)
Laurent Belcour's avatar
Laurent Belcour committed
233
			{
234 235 236 237 238 239 240 241 242 243
				if(fs[i]->input_parametrization() != input_parametrization())
				{
					vec temp_x(fs[i]->dimX());
					params::convert(&x[0], input_parametrization(), fs[i]->input_parametrization(), &temp_x[0]);
					res = res + fs[i]->value(temp_x);
				}
				else
				{
					res = res + fs[i]->value(x);
				}
Laurent Belcour's avatar
Laurent Belcour committed
244 245 246 247
			}
			return res;
		}

248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
		//! Provide a vector like interface
		virtual void push_back(nonlinear_function* f)
		{
			fs.push_back(f);

			// Update the input param
			if(input_parametrization() == params::UNKNOWN_INPUT)
			{
				setParametrization(f->input_parametrization());
			}
			
			// Update the output param
			if(output_parametrization() == params::UNKNOWN_OUTPUT)
			{
				setParametrization(f->output_parametrization());
			}
			else if(output_parametrization() != f->output_parametrization())
			{
				std::cerr << "Creating a compound function with different output dimensions, this is not allowed" << std::endl;
				throw;
			}
		}

		//! \brief Access to the i-th function of the compound
		nonlinear_function* operator[](int i) const
		{
#ifdef DEBUG
			assert(i >= 0 && i < fs.size());
#endif
			return fs[i];
		}

		//! \brief Access to the number of elements in the compound object.
		unsigned int size() const
		{
			return fs.size();
		}

Laurent Belcour's avatar
Laurent Belcour committed
286
		//! Load function specific files
287
		virtual void load(std::istream& in)
Laurent Belcour's avatar
Laurent Belcour committed
288
		{
289
			for(unsigned int i=0; i<fs.size(); ++i)
Laurent Belcour's avatar
Laurent Belcour committed
290
			{
291
				fs[i]->load(in);
Laurent Belcour's avatar
Laurent Belcour committed
292 293
			}
		}
294

Laurent Belcour's avatar
Laurent Belcour committed
295 296 297
		//! \brief Provide a first rough fit of the function. 
		virtual void bootstrap(const ::data* d, const arguments& args) 
		{
298
			for(unsigned int i=0; i<fs.size(); ++i)
Laurent Belcour's avatar
Laurent Belcour committed
299
			{
300
				fs[i]->bootstrap(d, args);
Laurent Belcour's avatar
Laurent Belcour committed
301 302
			}
		}
303

Laurent Belcour's avatar
Laurent Belcour committed
304 305 306
		//! Set the dimension of the input space of the function
		virtual void setDimX(int nX) 
		{
307
			function::setDimX(nX);
308
			for(unsigned int i=0; i<fs.size(); ++i)
Laurent Belcour's avatar
Laurent Belcour committed
309
			{
310
				fs[i]->setDimX(nX);
Laurent Belcour's avatar
Laurent Belcour committed
311 312 313 314 315
			}
		}
		//! Set the dimension of the output space of the function
		virtual void setDimY(int nY)
		{
316
			function::setDimY(nY);
317
			for(unsigned int i=0; i<fs.size(); ++i)
Laurent Belcour's avatar
Laurent Belcour committed
318
			{
319
				fs[i]->setDimY(nY);
Laurent Belcour's avatar
Laurent Belcour committed
320 321 322 323 324 325
			}
		}

		// Acces to the domain of definition of the function
		virtual void setMin(const vec& min) 
		{
326
			function::setMin(min);
327
			for(unsigned int i=0; i<fs.size(); ++i)
Laurent Belcour's avatar
Laurent Belcour committed
328
			{
329
				fs[i]->setMin(min);
Laurent Belcour's avatar
Laurent Belcour committed
330 331 332 333
			}
		}
		virtual void setMax(const vec& max) 
		{
334
			function::setMax(max);
335
			for(unsigned int i=0; i<fs.size(); ++i)
Laurent Belcour's avatar
Laurent Belcour committed
336
			{
337
				fs[i]->setMax(max);
Laurent Belcour's avatar
Laurent Belcour committed
338 339 340 341 342 343 344
			}
		}

		//! Number of parameters to this non-linear function
		virtual int nbParameters() const
		{
			int nb_params = 0;
345
			for(unsigned int i=0; i<fs.size(); ++i)
Laurent Belcour's avatar
Laurent Belcour committed
346
			{
347
				nb_params += fs[i]->nbParameters();
Laurent Belcour's avatar
Laurent Belcour committed
348
			}
349
			return nb_params;
Laurent Belcour's avatar
Laurent Belcour committed
350 351 352 353 354 355 356
		}

		//! Get the vector of parameters for the function
		virtual vec parameters() const
		{
			vec params(nbParameters());
			int current_i = 0;
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
			for(unsigned int f=0; f<fs.size(); ++f)
			{
				int f_size = fs[f]->nbParameters();

				// Handle when there is no parameters to include
				if(f_size > 0)
				{
					vec f_params = fs[f]->parameters();
					for(int i=0; i<f_size; ++i)
					{
						params[i + current_i] = f_params[i];
					}

					current_i += f_size;
				}
			}

			return params;
		}
		
		//! Get the vector of min parameters for the function
		virtual vec getParametersMin() const
		{
			vec params(nbParameters());
			int current_i = 0;
			for(unsigned int f=0; f<fs.size(); ++f)
Laurent Belcour's avatar
Laurent Belcour committed
383
			{
384
				int f_size = fs[f]->nbParameters();
385 386 387

				// Handle when there is no parameters to include
				if(f_size > 0)
Laurent Belcour's avatar
Laurent Belcour committed
388
				{
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
					vec f_params = fs[f]->getParametersMin();
					for(int i=0; i<f_size; ++i)
					{
						params[i + current_i] = f_params[i];
					}

					current_i += f_size;
				}
			}

			return params;
		}
		
		//! Get the vector of min parameters for the function
		virtual vec getParametersMax() const
		{
			vec params(nbParameters());
			int current_i = 0;
			for(unsigned int f=0; f<fs.size(); ++f)
			{
				int f_size = fs[f]->nbParameters();

				// Handle when there is no parameters to include
				if(f_size > 0)
				{
					vec f_params = fs[f]->getParametersMax();
415 416 417 418
					for(int i=0; i<f_size; ++i)
					{
						params[i + current_i] = f_params[i];
					}
Laurent Belcour's avatar
Laurent Belcour committed
419

420 421
					current_i += f_size;
				}
Laurent Belcour's avatar
Laurent Belcour committed
422 423 424 425 426 427 428 429 430
			}

			return params;
		}

		//! Update the vector of parameters for the function
		virtual void setParameters(const vec& p) 
		{
			int current_i = 0;
431
			for(unsigned int f=0; f<fs.size(); ++f)
Laurent Belcour's avatar
Laurent Belcour committed
432
			{
433
				int f_size = fs[f]->nbParameters();
434 435 436

				// Handle when there is no parameters to include
				if(f_size > 0)
Laurent Belcour's avatar
Laurent Belcour committed
437
				{
438 439 440 441 442
					vec f_params(f_size);
					for(int i=0; i<f_params.size(); ++i)
					{
						f_params[i] = p[i + current_i];
					}
Laurent Belcour's avatar
Laurent Belcour committed
443

444
					fs[f]->setParameters(f_params);
445 446
					current_i += f_size;
				}
Laurent Belcour's avatar
Laurent Belcour committed
447 448 449 450 451 452 453 454 455 456 457 458 459 460
			}
		}

		//! \brief Obtain the derivatives of the function with respect to the 
		//! parameters. 
		//
		// The x input of this function is the position in the input space and 
		// has size dimX(), the resulting vector has the size of the parameters
		// times the size of the output domain.
		//
		// The result vector should be orderer as res[i + dimY()*j], output
		// dimension first, then parameters.
		virtual vec parametersJacobian(const vec& x) const
		{
461
			int nb_params = nbParameters();
Laurent Belcour's avatar
Laurent Belcour committed
462
			vec jac(nb_params*_nY);
463
			jac = vec::Zero(nb_params*_nY);
Laurent Belcour's avatar
Laurent Belcour committed
464 465 466 467

			int start_i = 0;

			// Export the sub-Jacobian for each function
468
			for(unsigned int f=0; f<fs.size(); ++f)
Laurent Belcour's avatar
Laurent Belcour committed
469
			{
470
				nonlinear_function* func = fs[f];
Laurent Belcour's avatar
Laurent Belcour committed
471 472
				int nb_f_params = func->nbParameters(); 

473 474
				// Only export Jacobian if there are non-linear parameters
				if(nb_f_params > 0)
Laurent Belcour's avatar
Laurent Belcour committed
475
				{
476 477 478 479

					vec func_jac = func->parametersJacobian(x);

					for(int i=0; i<nb_f_params; ++i)
Laurent Belcour's avatar
Laurent Belcour committed
480
					{
481 482 483 484
						for(int y=0; y<_nY; ++y)
						{
							jac[y + _nY*(i+start_i)] = func_jac[y + _nY*i];
						}
Laurent Belcour's avatar
Laurent Belcour committed
485 486 487 488
					}
				}

				start_i += nb_f_params;
489
			}
490

491
			return jac;
Laurent Belcour's avatar
Laurent Belcour committed
492
		}
493

Laurent Belcour's avatar
Laurent Belcour committed
494 495 496 497 498
		//! \brief can set the input parametrization of a non-parametrized
		//! object. Print an error if it is already defined.
		virtual void setParametrization(params::input new_param)
		{
			parametrized::setParametrization(new_param);
499
			for(unsigned int i=0; i<fs.size(); ++i)
Laurent Belcour's avatar
Laurent Belcour committed
500
			{
501
				fs[i]->setParametrization(new_param);
Laurent Belcour's avatar
Laurent Belcour committed
502 503
			}
		}
504

Laurent Belcour's avatar
Laurent Belcour committed
505 506 507 508 509 510
		//! \brief can set the output parametrization of a non-parametrized
		//! function. Throw an exception if it tries to erase a previously
		//! defined one.
		virtual void setParametrization(params::output new_param)
		{
			parametrized::setParametrization(new_param);
511
			for(unsigned int i=0; i<fs.size(); ++i)
Laurent Belcour's avatar
Laurent Belcour committed
512
			{
513
				fs[i]->setParametrization(new_param);
Laurent Belcour's avatar
Laurent Belcour committed
514 515 516
			}
		}

517 518 519
		//! \brief save function specific data. This has no use for ALTA export
		//! but allows to factorize the code in the C++ or matlab export by
		//! defining function calls that are common to all the plugins.
520
		virtual void save_body(std::ostream& out, const arguments& args) const
521
		{
522
			for(unsigned int i=0; i<fs.size(); ++i)
523
			{
524
				fs[i]->save_body(out, args);
525 526 527 528 529 530 531 532 533
				out << std::endl;
			}

			function::save_body(out, args);
		}

		//! \brief save object specific information. For an ALTA export the
		//! coefficients will be exported. For a C++ or matlab export, the call
		//! to the associated function will be done.
534
		virtual void save_call(std::ostream& out, const arguments& args) const
535 536
		{
			bool is_cpp    = args["export"] == "C++";
537
			bool is_shader = args["export"] == "shader" || args["export"] == "explorer";
538 539 540 541 542 543 544 545
			bool is_matlab = args["export"] == "matlab";

			// This part is export specific. For ALTA, the coefficients are just
			// dumped as is with a #FUNC {plugin_name} header.
			//
			// For C++ export, the function call should be done before hand and
			// the line should look like:
			//   res += call_i(x);
546
			for(unsigned int i=0; i<fs.size(); ++i)
547
			{
548
				if(i != 0 && (is_cpp || is_matlab || is_shader))
549
				{
550
					out << "\tres += ";
551 552
				}

553
				fs[i]->save_call(out, args);
554 555 556 557 558 559 560 561 562 563

				if(is_cpp || is_matlab || is_shader)
				{
					out << ";" << std::endl;
				}
			}

			function::save_call(out, args);
		}

564 565 566
	protected:
		std::vector<nonlinear_function*> fs;

Laurent Belcour's avatar
Laurent Belcour committed
567 568
};

Laurent Belcour's avatar
Laurent Belcour committed
569 570 571 572 573
/*! \brief A Fresnel interface
 *  \ingroup core
 */
class fresnel : public nonlinear_function
{
574
	public: // methods
Laurent Belcour's avatar
Laurent Belcour committed
575

576 577
		// Overload the function operator
		virtual vec operator()(const vec& x) const
Laurent Belcour's avatar
Laurent Belcour committed
578
		{
579
			return value(x);
Laurent Belcour's avatar
Laurent Belcour committed
580
		}
581
		virtual vec value(const vec& x) const
Laurent Belcour's avatar
Laurent Belcour committed
582
		{
583
			vec fres = fresnelValue(x);
584 585 586
			vec func = f->value(x);

			return product(fres, func);
Laurent Belcour's avatar
Laurent Belcour committed
587 588
		}

589
		//! Load function specific files
590
		virtual void load(std::istream& in)
591 592
		{
			if(f != NULL)
Laurent Belcour's avatar
Laurent Belcour committed
593
			{
594
				f->load(in);
Laurent Belcour's avatar
Laurent Belcour committed
595 596 597 598 599
			}
			else
			{
				std::cout << "<<ERROR>> trying to load a Fresnel object with no base class" << std::endl;
			}
600
		}
601

Laurent Belcour's avatar
Laurent Belcour committed
602 603 604 605 606 607
		//! \brief Provide a first rough fit of the function. 
		virtual void bootstrap(const data* d, const arguments& args) 
		{
			fresnelBootstrap(d, args);
			f->bootstrap(d, args);
		}
608

609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
		//! Set the dimension of the input space of the function
		virtual void setDimX(int nX) 
		{
			function::setDimX(nX);
			f->setDimX(nX);
		}
		//! Set the dimension of the output space of the function
		virtual void setDimY(int nY)
		{
			function::setDimY(nY);
			f->setDimY(nY);
		}

		// Acces to the domain of definition of the function
		virtual void setMin(const vec& min) 
		{
			function::setMin(min);
			f->setMin(min);
		}
		virtual void setMax(const vec& max) 
		{
			function::setMax(max);
			f->setMax(max);
		}
633

Laurent Belcour's avatar
Laurent Belcour committed
634 635 636 637 638 639 640 641 642 643 644 645
		//! Number of parameters to this non-linear function
		virtual int nbParameters() const
		{
			return f->nbParameters() + nbFresnelParameters();
		}

		//! Get the vector of parameters for the function
		virtual vec parameters() const
		{
			int nb_func_params = f->nbParameters();
			int nb_fres_params = nbFresnelParameters();
			int nb_params = nb_func_params + nb_fres_params;
646

Laurent Belcour's avatar
Laurent Belcour committed
647
			vec params(nb_params);
648

Laurent Belcour's avatar
Laurent Belcour committed
649 650 651 652 653
			vec func_params = f->parameters();
			for(int i=0; i<nb_func_params; ++i)
			{
				params[i] = func_params[i];
			}
654

Laurent Belcour's avatar
Laurent Belcour committed
655
			vec fres_params = getFresnelParameters();
656
			for(int i=0; i<nb_fres_params; ++i)
Laurent Belcour's avatar
Laurent Belcour committed
657
			{
658
				params[i+nb_func_params] = fres_params[i];
Laurent Belcour's avatar
Laurent Belcour committed
659
			}
660

Laurent Belcour's avatar
Laurent Belcour committed
661 662
			return params;
		}
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710
		
		//! Get the vector of min parameters for the function
		virtual vec getParametersMax() const
		{
			int nb_func_params = f->nbParameters();
			int nb_fres_params = nbFresnelParameters();
			int nb_params = nb_func_params + nb_fres_params;

			vec params(nb_params);

			vec func_params = f->getParametersMax();
			for(int i=0; i<nb_func_params; ++i)
			{
				params[i] = func_params[i];
			}

			vec fres_params = getFresnelParametersMax();
			for(int i=0; i<nb_fres_params; ++i)
			{
				params[i+nb_func_params] = fres_params[i];
			}

			return params;
		}
		
		//! Get the vector of min parameters for the function
		virtual vec getParametersMin() const
		{
			int nb_func_params = f->nbParameters();
			int nb_fres_params = nbFresnelParameters();
			int nb_params = nb_func_params + nb_fres_params;

			vec params(nb_params);

			vec func_params = f->getParametersMin();
			for(int i=0; i<nb_func_params; ++i)
			{
				params[i] = func_params[i];
			}

			vec fres_params = getFresnelParametersMin();
			for(int i=0; i<nb_fres_params; ++i)
			{
				params[i+nb_func_params] = fres_params[i];
			}

			return params;
		}
Laurent Belcour's avatar
Laurent Belcour committed
711 712

		//! Update the vector of parameters for the function
713 714 715 716 717 718 719 720 721 722 723
		virtual void setParameters(const vec& p)
		{
			int nb_func_params = f->nbParameters();
			int nb_fres_params = nbFresnelParameters();

			vec func_params(nb_func_params);
			for(int i=0; i<nb_func_params; ++i)
			{
				func_params[i] = p[i];
			}
			f->setParameters(func_params);
724

725 726 727 728 729 730 731
			vec fres_params(nb_fres_params);
			for(int i=0; i<nb_fres_params; ++i)
			{
				fres_params[i] = p[i+nb_func_params];
			}
			setFresnelParameters(fres_params);
		}
Laurent Belcour's avatar
Laurent Belcour committed
732 733 734

		//! \brief Obtain the derivatives of the function with respect to the 
		//! parameters.
735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758
		virtual vec parametersJacobian(const vec& x) const
		{
			int nb_func_params = f->nbParameters();
			int nb_fres_params = nbFresnelParameters();
			int nb_params = nb_func_params + nb_fres_params;

			vec func_jacobian = f->parametersJacobian(x);
			vec fres_jacobian = getFresnelParametersJacobian(x);

			vec func_value = f->value(x);
			vec fres_value = fresnelValue(x);

			// F = fresnel; f = function
			// d(F * f)(x) /dp = F(x) df(x) /dp + f(x) dF(x) / dp
			vec jac(nb_params*_nY);
			for(int y=0; y<_nY; ++y)
			{
				for(int i=0; i<nb_func_params; ++i)
				{
					jac[y + _nY*i] = func_jacobian[y + _nY*i] * fres_value[y];
				}

				for(int i=0; i<nb_fres_params; ++i)
				{
759
					jac[y + _nY*(i+nb_func_params)] = fres_jacobian[y + _nY*i] * func_value[y];
760 761 762 763 764
				}
			}

			return jac;
		}
Laurent Belcour's avatar
Laurent Belcour committed
765

766 767 768 769 770
		//! \brief set the value for the base function
		void setBase(nonlinear_function* fin)
		{
			f = fin;
		}
771

772 773 774 775 776
		//! \brief provide the input parametrization of the object.
		virtual params::input input_parametrization() const
		{
			return f->input_parametrization();
		}
777

778 779 780 781 782
		//! \brief provide the outout parametrization of the object.
		virtual params::output output_parametrization() const
		{
			return f->output_parametrization();
		}
783

784 785 786 787 788 789 790
		//! \brief can set the input parametrization of a non-parametrized
		//! object. Print an error if it is already defined.
		virtual void setParametrization(params::input new_param)
		{
			function::setParametrization(new_param);
			f->setParametrization(new_param);
		}
791

792 793 794 795 796 797 798 799
		//! \brief can set the output parametrization of a non-parametrized
		//! function. Throw an exception if it tries to erase a previously
		//! defined one.
		virtual void setParametrization(params::output new_param)
		{
			function::setParametrization(new_param);
			f->setParametrization(new_param);
		}
800 801

	protected: // methods
Laurent Belcour's avatar
Laurent Belcour committed
802

803 804
		//! \brief the interface for the Fresnel code
		virtual vec fresnelValue(const vec& x) const  = 0;
Laurent Belcour's avatar
Laurent Belcour committed
805 806 807 808 809 810 811

		//! Number of parameters to this non-linear function
		virtual int nbFresnelParameters() const = 0;

		//! Get the vector of parameters for the function
		virtual vec getFresnelParameters() const = 0;

812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833
		//! Get the vector of min parameters for the function
		virtual vec getFresnelParametersMin() const
		{
			vec m(nbFresnelParameters());
			for(int i=0; i<nbFresnelParameters(); ++i)
			{
				m[i] = -std::numeric_limits<double>::max();
			}
			return m;
		}

		//! Get the vector of min parameters for the function
		virtual vec getFresnelParametersMax() const
		{
			vec M(nbFresnelParameters());
			for(int i=0; i<nbFresnelParameters(); ++i)
			{
				M[i] = std::numeric_limits<double>::max();
			}
			return M;
		}

Laurent Belcour's avatar
Laurent Belcour committed
834 835 836 837 838 839 840
		//! Update the vector of parameters for the function
		virtual void setFresnelParameters(const vec& p) = 0;

		//! \brief Obtain the derivatives of the function with respect to the 
		//! parameters.
		virtual vec getFresnelParametersJacobian(const vec& x) const = 0;		

Laurent Belcour's avatar
Laurent Belcour committed
841 842 843
		//! \brief Boostrap the function by defining the diffuse term
		virtual void fresnelBootstrap(const data* d, const arguments& args) = 0;

844
	protected: //data
Laurent Belcour's avatar
Laurent Belcour committed
845

846 847
		//! the base object
		nonlinear_function* f;
Laurent Belcour's avatar
Laurent Belcour committed
848
};