1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 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 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 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 383 384 385 386 387 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 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 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 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 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 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789
|
// @(#)root/mathcore:$Id$
// Author: L. Moneta Mon Nov 13 15:58:13 2006
/**********************************************************************
* *
* Copyright (c) 2006 LCG ROOT Math Team, CERN/PH-SFT *
* *
* *
**********************************************************************/
// Heaer file for Functor classes.
// designed is inspired by the Loki Functor
#ifndef ROOT_Math_Functor
#define ROOT_Math_Functor
#include "Math/IFunction.h"
// #ifndef Root_Math_StaticCheck
// #include "Math/StaticCheck.h"
// #endif
#include <memory>
namespace ROOT {
namespace Math {
/**
@defgroup Functor_int Internal Functor Classes
Internal classes for implementing Functor and Functor1D classes
@ingroup GenFunc
*/
/**
FunctorImpl is a base class for the functor
handler implementation class.
It defines the Copy operator used to clone the functor objects
*/
template<class IBaseFunc>
class FunctorImpl : public IBaseFunc {
public:
typedef IBaseFunc BaseFunc;
FunctorImpl() : IBaseFunc() { }
virtual ~FunctorImpl() {}
virtual FunctorImpl* Copy() const = 0;
};
/**
Functor Handler class is responsible for wrapping any other functor and pointer to
free C functions.
It can be created from any function implementing the correct signature
corresponding to the requested type
In the case of one dimension the function evaluation object must implement
double operator() (double x). If it implements a method: double Derivative(double x)
can be used to create a Gradient function type.
In the case of multi-dimension the function evaluation object must implement
double operator()(const double *x). If it implements a method:
double Derivative(const double *x, int icoord)
can be used to create a Gradient function type.
@ingroup Functor_int
*/
template<class ParentFunctor, class Func >
class FunctorHandler : public ParentFunctor::Impl {
typedef typename ParentFunctor::Impl ImplFunc;
typedef typename ImplFunc::BaseFunc BaseFunc;
//typedef typename ParentFunctor::Dim Dim;
public:
// constructor for 1d functions
FunctorHandler(const Func & fun) : fDim(1), fFunc(fun) {}
// constructor for multi-dimensional functions w/0 NDim()
FunctorHandler(unsigned int dim, const Func & fun ) :
fDim(dim),
fFunc(fun)
{}
virtual ~FunctorHandler() {}
// copy of the function handler (use copy-ctor)
ImplFunc * Copy() const {
return new FunctorHandler(*this);
}
// clone of the function handler (use copy-ctor)
BaseFunc * Clone() const {
return Copy();
}
// constructor for multi-dimensional functions
unsigned int NDim() const {
return fDim;
}
private :
inline double DoEval (double x) const {
return fFunc(x);
}
inline double DoEval (const double * x) const {
return fFunc(x);
}
inline double DoDerivative (double x) const {
return fFunc.Derivative(x);
}
inline double DoDerivative (const double * x, unsigned int icoord ) const {
return fFunc.Derivative(x,icoord);
}
unsigned int fDim;
mutable Func fFunc; // should here be a reference and pass a non-const ref in ctor
};
/**
Functor Handler class for gradient functions where both callable objects are provided for the function
evaluation (type Func) and for the gradient (type GradFunc) .
It can be created from any function implementing the correct signature
corresponding to the requested type
In the case of one dimension the function evaluation object and the derivative function object must implement
double operator() (double x).
In the case of multi-dimension the function evaluation object must implement
double operator() (const double * x) and the gradient function object must implement
double operator() (const double * x, int icoord)
@ingroup Functor_int
*/
template<class ParentFunctor, class Func, class GradFunc >
class FunctorGradHandler : public ParentFunctor::Impl {
typedef typename ParentFunctor::Impl ImplFunc;
typedef typename ImplFunc::BaseFunc BaseFunc;
//typedef typename ParentFunctor::Dim Dim;
public:
// constructor for 1d functions
FunctorGradHandler(const Func & fun, const GradFunc & gfun) :
fDim(1),
fFunc(fun),
fGradFunc(gfun)
{}
// constructor for multi-dimensional functions
FunctorGradHandler(unsigned int dim, const Func & fun, const GradFunc & gfun) :
fDim(dim),
fFunc(fun),
fGradFunc( gfun )
{}
virtual ~FunctorGradHandler() {}
// clone of the function handler (use copy-ctor)
ImplFunc * Copy() const { return new FunctorGradHandler(*this); }
// clone of the function handler (use copy-ctor)
BaseFunc * Clone() const { return Copy(); }
// constructor for multi-dimensional functions
unsigned int NDim() const {
return fDim;
}
private :
inline double DoEval (double x) const {
return fFunc(x);
}
inline double DoEval (const double * x) const {
return fFunc(x);
}
inline double DoDerivative (double x) const {
return fGradFunc(x);
}
inline double DoDerivative (const double * x, unsigned int icoord ) const {
return fGradFunc(x, icoord);
}
unsigned int fDim;
mutable Func fFunc;
mutable GradFunc fGradFunc;
};
/**
Functor Handler to Wrap pointers to member functions
The member function type must be (XXX means any name is allowed) :
double XXX ( double x) for 1D functions
and
double XXXX (const double *x) for multi-dimensional functions
@ingroup Functor_int
*/
template <class ParentFunctor, typename PointerToObj,
typename PointerToMemFn>
class MemFunHandler : public ParentFunctor::Impl
{
//typedef typename ParentFunctor::Dim Dim;
typedef typename ParentFunctor::Impl ImplFunc;
typedef typename ImplFunc::BaseFunc BaseFunc;
public:
/// constructor from a pointer to the class and a pointer to the function
MemFunHandler(const PointerToObj& pObj, PointerToMemFn pMemFn)
: fDim(1), fObj(pObj), fMemFn(pMemFn) // should pass pointer by value ??
{}
/// constructor from a pointer to the class and a pointer to the function
MemFunHandler(unsigned int dim, const PointerToObj& pObj, PointerToMemFn pMemFn)
: fDim(dim), fObj(pObj), fMemFn(pMemFn)
{}
virtual ~MemFunHandler() {}
// clone of the function handler (use copy-ctor)
ImplFunc * Copy() const { return new MemFunHandler(*this); }
// clone of the function handler (use copy-ctor)
BaseFunc * Clone() const { return new MemFunHandler(*this); }
// constructor for multi-dimensional functions
unsigned int NDim() const {
return fDim;
}
private :
inline double DoEval (double x) const {
return ((*fObj).*fMemFn)(x);
}
inline double DoEval (const double * x) const {
return ((*fObj).*fMemFn)(x);
}
unsigned int fDim;
mutable PointerToObj fObj;
PointerToMemFn fMemFn;
};
/**
Functor Handler to Wrap pointers to member functions for the evaluation of the function
and the gradient.
The member function type must be (XXX means any name is allowed) :
double XXX ( double x) for 1D function and derivative evaluation
double XXX (const double *x) for multi-dimensional function evaluation and
double XXX (cost double *x, int icoord) for partial derivatives evaluation
@ingroup Functor_int
*/
template <class ParentFunctor, typename PointerToObj,
typename PointerToMemFn, typename PointerToGradMemFn>
class MemGradFunHandler : public ParentFunctor::Impl
{
typedef typename ParentFunctor::Impl ImplFunc;
typedef typename ImplFunc::BaseFunc BaseFunc;
//typedef typename ParentFunctor::Dim Dim;
public:
/// constructor from a pointer to the class and a pointer to the function
MemGradFunHandler(const PointerToObj& pObj, PointerToMemFn pMemFn, PointerToGradMemFn pGradMemFn)
: fDim(1),
fObj(pObj),
fMemFn(pMemFn),
fGradMemFn(pGradMemFn)
{}
/// constructor from a pointer to the class and a pointer to the function
MemGradFunHandler(unsigned int dim,
const PointerToObj& pObj,
PointerToMemFn pMemFn,
PointerToGradMemFn pGradMemFn )
: fDim(dim),
fObj(pObj),
fMemFn(pMemFn),
fGradMemFn(pGradMemFn)
{}
virtual ~MemGradFunHandler() {}
// clone of the function handler (use copy-ctor)
ImplFunc * Copy() const { return new MemGradFunHandler(*this); }
// clone of the function handler (use copy-ctor)
BaseFunc * Clone() const { return new MemGradFunHandler(*this); }
// constructor for multi-dimensional functions
unsigned int NDim() const {
return fDim;
}
private :
inline double DoEval (double x) const {
return ((*fObj).*fMemFn)(x);
}
inline double DoEval (const double * x) const {
return ((*fObj).*fMemFn)(x);
}
inline double DoDerivative (double x) const {
return ((*fObj).*fGradMemFn)(x);
}
inline double DoDerivative (const double * x, unsigned int icoord ) const {
return ((*fObj).*fGradMemFn)(x,icoord);
}
unsigned int fDim;
mutable PointerToObj fObj;
PointerToMemFn fMemFn;
PointerToGradMemFn fGradMemFn;
};
//****************************
// LM 7/2/2014: no needed this : make template ctor of Functor1D and GradFunctor1D not
// available to CINT s
//***************************************
//#if defined(__MAKECINT__) || defined(G__DICTIONARY)
// needed since CINT initialize it with TRootIOCtor
//class TRootIOCtor;
// template<class ParentFunctor>
// class FunctorHandler<ParentFunctor,TRootIOCtor *> : public ParentFunctor::Impl
// {
// public:
// typedef typename ParentFunctor::Impl ImplFunc;
// typedef typename ImplFunc::BaseFunc BaseFunc;
// FunctorHandler(TRootIOCtor *) {}
// // function required by interface
// virtual ~FunctorHandler() {}
// double DoEval (double ) const { return 0; }
// double DoDerivative (double ) const { return 0; }
// ImplFunc * Copy() const { return 0; }
// BaseFunc * Clone() const { return 0; }
// };
// #endif
/**
Documentation for class Functor class.
It is used to wrap in a very simple and convenient way multi-dimensional function objects.
It can wrap all the following types:
<ul>
<li> any C++ callable object implemention double operator()( const double * )
<li> a free C function of type double ()(const double * )
<li> a member function with the correct signature like Foo::Eval(const double * ).
In this case one pass the object pointer and a pointer to the member function (&Foo::Eval)
</ul>
The function dimension is required when constructing the functor.
@ingroup GenFunc
*/
class Functor : public IBaseFunctionMultiDim {
public:
typedef FunctorImpl<IBaseFunctionMultiDim> Impl;
typedef IBaseFunctionMultiDim::BaseFunc ImplBase;
/**
Default constructor
*/
Functor () {}
/**
construct from a pointer to member function (multi-dim type)
*/
template <class PtrObj, typename MemFn>
Functor(const PtrObj& p, MemFn memFn, unsigned int dim )
: fImpl(new MemFunHandler<Functor, PtrObj, MemFn>(dim, p, memFn))
{}
/**
construct from a callable object of multi-dimension
with the right signature (implementing operator()(double *x)
*/
template <typename Func>
Functor( const Func & f, unsigned int dim ) :
fImpl(new FunctorHandler<Functor,Func>(dim,f) )
{}
/**
Destructor (no operations)
*/
virtual ~Functor () {}
/**
Copy constructor for functor based on ROOT::Math::IMultiGenFunction
*/
Functor(const Functor & rhs) :
ImplBase()
{
if (rhs.fImpl)
fImpl = std::unique_ptr<Impl>((rhs.fImpl)->Copy());
}
// need a specialization in order to call base classes and use clone
/**
Assignment operator
*/
Functor & operator = (const Functor & rhs) {
Functor copy(rhs);
fImpl.swap(copy.fImpl);
return *this;
}
// clone of the function handler (use copy-ctor)
ImplBase * Clone() const { return new Functor(*this); }
// for multi-dimensional functions
unsigned int NDim() const { return fImpl->NDim(); }
private :
inline double DoEval (const double * x) const {
return (*fImpl)(x);
}
std::unique_ptr<Impl> fImpl; // pointer to base functor handler
};
/**
Functor1D class for one-dimensional functions.
It is used to wrap in a very simple and convenient way:
<ul>
<li> any C++ callable object implemention double operator()( double )
<li> a free C function of type double ()(double )
<li> a member function with the correct signature like Foo::Eval(double ).
In this case one pass the object pointer and a pointer to the member function (&Foo::Eval)
</ul>
@ingroup GenFunc
*/
class Functor1D : public IBaseFunctionOneDim {
public:
typedef FunctorImpl<IBaseFunctionOneDim> Impl;
typedef IBaseFunctionOneDim::BaseFunc ImplBase;
/**
Default constructor
*/
Functor1D () {}
/**
construct from a callable object with the right signature
implementing operator() (double x)
*/
template <typename Func>
Functor1D(const Func & f) :
fImpl(new FunctorHandler<Functor1D,Func>(f))
{}
/**
construct from a pointer to member function (1D type)
*/
template <class PtrObj, typename MemFn>
Functor1D(const PtrObj& p, MemFn memFn)
: fImpl(new MemFunHandler<Functor1D, PtrObj, MemFn>(p, memFn))
{}
/**
Destructor (no operations)
*/
virtual ~Functor1D () {}
/**
Copy constructor for Functor based on ROOT::Math::IGenFunction
*/
Functor1D(const Functor1D & rhs) :
// strange that this is required eventhough ImplBase is an abstract class
ImplBase()
{
if (rhs.fImpl)
fImpl = std::unique_ptr<Impl>( (rhs.fImpl)->Copy() );
}
/**
Assignment operator
*/
Functor1D & operator = (const Functor1D & rhs) {
Functor1D copy(rhs);
fImpl.swap(copy.fImpl);
return *this;
}
// clone of the function handler (use copy-ctor)
ImplBase * Clone() const { return new Functor1D(*this); }
private :
inline double DoEval (double x) const {
return (*fImpl)(x);
}
std::unique_ptr<Impl> fImpl; // pointer to base functor handler
};
/**
GradFunctor class for Multidimensional gradient functions.
It is used to wrap in a very C++ callable object to make gradient functions.
It can be constructed in three different way:
<ol>
<li> from an object implementing both
double operator()( const double * ) for the function evaluation and
double Derivative(const double *, int icoord) for the partial derivatives
<li>from an object implementing any member function like Foo::XXX(const double *) for the function evaluation
and any member function like Foo::XXX(const double *, int icoord) for the partial derivatives
<li>from an function object implementing
double operator()( const double * ) for the function evaluation and another function object implementing
double operator() (const double *, int icoord) for the partial derivatives
</ol>
The function dimension is required when constructing the functor.
@ingroup GenFunc
*/
class GradFunctor : public IGradientFunctionMultiDim {
public:
typedef FunctorImpl<IGradientFunctionMultiDim> Impl;
typedef IGradientFunctionMultiDim::BaseFunc ImplBase;
/**
Default constructor
*/
GradFunctor () {}
/**
construct from a callable object of multi-dimension
implementing operator()(const double *x) and
Derivative(const double * x,icoord)
*/
template <typename Func>
GradFunctor( const Func & f, unsigned int dim ) :
fImpl(new FunctorHandler<GradFunctor,Func>(dim,f) )
{}
/**
construct from a pointer to member function and member function types for function and derivative evaluations
*/
template <class PtrObj, typename MemFn, typename GradMemFn>
GradFunctor(const PtrObj& p, MemFn memFn, GradMemFn gradFn, unsigned int dim )
: fImpl(new MemGradFunHandler<GradFunctor, PtrObj, MemFn, GradMemFn>(dim, p, memFn, gradFn))
{}
/**
construct for Gradient Functions of multi-dimension
Func gives the function evaluatiion, GradFunc the partial derivatives
The function dimension is required
*/
template <typename Func, typename GradFunc>
GradFunctor(const Func & f, const GradFunc & g, int dim ) :
fImpl(new FunctorGradHandler<GradFunctor,Func,GradFunc>(dim, f, g) )
{ }
/**
Destructor (no operations)
*/
virtual ~GradFunctor () {}
/**
Copy constructor for functor based on ROOT::Math::IMultiGradFunction
*/
GradFunctor(const GradFunctor & rhs) :
ImplBase()
{
if (rhs.fImpl)
fImpl = std::unique_ptr<Impl>(rhs.fImpl->Copy());
}
/**
Assignment operator
*/
GradFunctor & operator = (const GradFunctor & rhs) {
GradFunctor copy(rhs);
fImpl.swap(copy.fImpl);
return *this;
}
// clone of the function handler (use copy-ctor)
ImplBase * Clone() const { return new GradFunctor(*this); }
// for multi-dimensional functions
unsigned int NDim() const { return fImpl->NDim(); }
private :
inline double DoEval (const double * x) const {
return (*fImpl)(x);
}
inline double DoDerivative (const double * x, unsigned int icoord ) const {
return fImpl->Derivative(x,icoord);
}
std::unique_ptr<Impl> fImpl; // pointer to base grad functor handler
};
//_______________________________________________________________________________________________
/**
GradFunctor1D class for one-dimensional gradient functions.
It is used to wrap in a very C++ callable object to make a 1D gradient functions.
It can be constructed in three different way:
<ol>
<li> from an object implementing both
double operator()( double ) for the function evaluation and
double Derivative(double ) for the partial derivatives
<li>from an object implementing any member function like Foo::XXX(double ) for the function evaluation
and any other member function like Foo::YYY(double ) for the derivative.
<li>from an 2 function objects implementing
double operator()( double ) . One object provides the function evaluation, the other the derivative.
</ol>
@ingroup GenFunc
*/
class GradFunctor1D : public IGradientFunctionOneDim {
public:
typedef FunctorImpl<IGradientFunctionOneDim> Impl;
typedef IGradientFunctionOneDim::BaseFunc ImplBase;
/**
Default constructor
*/
GradFunctor1D () {}
/**
construct from an object with the right signature
implementing both operator() (double x) and Derivative(double x)
*/
template <typename Func>
GradFunctor1D(const Func & f) :
fImpl(new FunctorHandler<GradFunctor1D,Func>(f) )
{}
/**
construct from a pointer to class and two pointers to member functions, one for
the function evaluation and the other for the derivative.
The member functions must take a double as argument and return a double
*/
template <class PtrObj, typename MemFn, typename GradMemFn>
GradFunctor1D(const PtrObj& p, MemFn memFn, GradMemFn gradFn)
: fImpl(new MemGradFunHandler<GradFunctor1D, PtrObj, MemFn, GradMemFn>(p, memFn, gradFn))
{}
/**
construct from two 1D function objects
*/
template <typename Func, typename GradFunc>
GradFunctor1D(const Func & f, const GradFunc & g ) :
fImpl(new FunctorGradHandler<GradFunctor1D,Func, GradFunc>(f, g) )
{}
/**
Destructor (no operations)
*/
virtual ~GradFunctor1D () {}
/**
Copy constructor for Functor based on ROOT::Math::IGradFunction
*/
GradFunctor1D(const GradFunctor1D & rhs) :
// strange that this is required eventhough Impl is an abstract class
ImplBase()
{
if (rhs.fImpl)
fImpl = std::unique_ptr<Impl>( rhs.fImpl->Copy() );
}
/**
Assignment operator
*/
GradFunctor1D & operator = (const GradFunctor1D & rhs) {
GradFunctor1D copy(rhs);
fImpl.swap(copy.fImpl);
return *this;
}
// clone of the function handler (use copy-ctor)
ImplBase * Clone() const { return new GradFunctor1D(*this); }
private :
inline double DoEval (double x) const {
return (*fImpl)(x);
}
inline double DoDerivative (double x) const {
return fImpl->Derivative(x);
}
std::unique_ptr<Impl> fImpl; // pointer to base gradient functor handler
};
} // end namespace Math
} // end namespace ROOT
#endif /* ROOT_Math_Functor */
|