Using a member function in a functor


ROOT Version: 6.08/02
Platform: Linux CentOS 7
Compiler: ROOT interpreter


I am trying to minimize a user defined function. Looking at some online documentation, I found several examples which use a Functor as input to the minimization system.

According to the Functor documentation, the Functor can wrap β€œ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)”.

With this in mind I created the following minimization class:

class DiffFunctor {
public:

  DiffFunctor() {
    fMin = 0;
    fMax = 1024;
    fShift = 0;
    fTemp = 0;
    fWF = 0;
  }

  void SetTemplate(Double_t* t) { fTemp = t; }
  void SetWaveform(Double_t* w) { fWF = w; }

  void SetBinMin(Int_t m) { fMin = m; }
  void SetBinMax(Int_t m) { fMax = m; }
  void SetBinShift(Int_t m) { fShift = m; }
  void SetScale(Double_t s) { fScale = s; }

  void DoMinimize() {
    ROOT::Math::Functor fun(&DiffFunctor::Eval,1);
    ROOT::Math::Minimizer* min = ROOT::Math::Factory::CreateMinimizer("Minuit2","");
    min->SetMaxFunctionCalls(1000000); // for Minuit/Minuit2
    min->SetMaxIterations(10000);  // for GSL 
    min->SetTolerance(0.001);
    min->SetPrintLevel(1);
    min->SetFunction(fun);
    min->SetVariable(0,"scale",fScale,0.01);
    min->Minimize();
  }

private:

  Double_t Eval(const double* p) {
    Double_t tot = 0.;
    for (int i=fMin; i<fMax; i++) {
      Double_t d = fWF[i]-p[0]*fTemp[i-fShift];
      tot += d*d;
    }
    return tot;
  }

  Int_t fMin,fMax,fShift;
  Double_t fScale;
  Double_t* fTemp;
  Double_t* fWF;

};

but when I use it, the interpreter fails with the following messages:

Processing FitMacro.C...
In file included from input_line_12:18:
In file included from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.08.02-be67f/x86_64-centos7-gcc62-opt/etc/../etc/dictpch/allHeaders.h:603:
/cvmfs/sft.cern.ch/lcg/releases/ROOT/6.08.02-be67f/x86_64-centos7-gcc62-opt/etc/../include/Math/Functor.h:122:14: error: called object type 'double (DiffFunctor::*)(const double *)' is not a function or function pointer
      return fFunc(x);
             ^~~~~
/cvmfs/sft.cern.ch/lcg/releases/ROOT/6.08.02-be67f/x86_64-centos7-gcc62-opt/etc/../include/Math/Functor.h:92:4: note: in instantiation of member function 'ROOT::Math::FunctorHandler<ROOT::Math::Functor, double (DiffFunctor::*)(const double *)>::DoEval' requested here
   FunctorHandler(unsigned int dim, const Func & fun ) :
   ^
/cvmfs/sft.cern.ch/lcg/releases/ROOT/6.08.02-be67f/x86_64-centos7-gcc62-opt/etc/../include/Math/Functor.h:424:17: note: in instantiation of member function 'ROOT::Math::FunctorHandler<ROOT::Math::Functor, double (DiffFunctor::*)(const double *)>::FunctorHandler' requested here
      fImpl(new FunctorHandler<Functor,Func>(dim,f) )
                ^
/home/leonardi/sviluppo/padme-fw.newpadmereco/PadmeReco3/FitMacro.C:21:25: note: in instantiation of function template specialization 'ROOT::Math::Functor::Functor<double (DiffFunctor::*)(const double *)>' requested here
    ROOT::Math::Functor fun(&DiffFunctor::Eval,1);
                        ^
IncrementalExecutor::executeFunction: symbol '_ZN5TMath3RMSIdEEdxPKT_PKd' unresolved while linking [cling interface function]!
You are probably missing the definition of double TMath::RMS<double>(long long, double const*, double const*)
Maybe you need to load the corresponding shared library?
IncrementalExecutor::executeFunction: symbol '_ZNK4ROOT4Math14FunctorHandlerINS0_7FunctorEM11DiffFunctorFdPKdEE6DoEvalES5_' unresolved while linking [cling interface function]!
You are probably missing the definition of ROOT::Math::FunctorHandler<ROOT::Math::Functor, double (DiffFunctor::*)(double const*)>::DoEval(double const*) const
Maybe you need to load the corresponding shared library?
IncrementalExecutor::executeFunction: symbol '_ZSt8_DestroyIPddEvT_S1_RSaIT0_E' unresolved while linking [cling interface function]!
You are probably missing the definition of void std::_Destroy<double*, double>(double*, double*, std::allocator<double>&)
Maybe you need to load the corresponding shared library?

What am I doing wrong?

1 Like

Hi,

When constructing a Functor from a member function pointer you need to provide the pointer to the object on which you will call the member function, i.e. using this signature:

ROOT::Math::Functor fun(this, &DiffFunctor::Eval,1);

Lorenzo

Thanks for the clarification. Now everything works and I understood the meaning of the phrase β€œIn this case one pass the object pointer and a pointer to the member function (&Foo::Eval)”.

I think the authors should add to the documentation an example with the correct syntax to create functors this way.

1 Like

Thank you for the feedback. I agree, we should add this example code in the Functor class documentation (ROOT: ROOT::Math::Functor Class Reference) as we have for example for the TF1 class (see ROOT: TF1 Class Reference).

Best regards

Lorenzo