Give more arguments to a function

Hello everybody.
I encounter some problem with my minimization algorithm.
For this I need a function to minimize that I set like this:

double pm_function (const double *v)
{
    ...
    TH1F * spectrum = new() TF1(...) ;
    spectrum->Fill( data(v[0,1,2,3]) ) ;
    TCanvas C(...) ;
    C.dc() ;
    Spectrum->Draw("HIST") ;
    C.SaveAs("Spectrum.png") ;
     ...
     ...
    int std_dev = Spectrum ->GetStdDev(1) ;
return std_dev ;
}

then in main() function : 

ROOT::Math::Minimizer* MinmizeFunction ; 
MinmizeFunction = ROOT::Math::Factory::CreateMinimizer("Minuit2", "Simplex") ;
ROOT::Math::Functor PMFun(&pm_function,var_nbr) ; //encapsulate function in root
MinmizeFunction->SetFunction(PMFun) ; // begin minimization

I would like to know if there is a way to give more arguments to the function pm_function (). For example pm_function (const double * v, double * initial_data, int i, Tcanvas * C);
Because I would not load my data at each iteration of the minimization function which is a black box of ROOT. I could use it to increment my image backup C.SaveAs (“Spectrum” + to_string (i) + “.png”);
If so, how to encapsulate the method under root?

Any idea ?
best regard.

Thanks for answering @dvotaw.
I wrote the function pm_function ().
But I can not put more argument here because to encapsulate the function under ROOT :: Math :: Functor it takes a certain standard. Even if I could, I do not call this function anywhere. I just pass its object to ROOT :: Math :: Functor PMFun (& pm_function, var_nbr); Without arguments.
I tried something like that.
Double pm_function (const double * v, int i);
And I got errors

In file included from Minimization.C:10:0:
(...)/root6_inst/include/root/Math/Functor.h: In instantiation of ‘double ROOT::Math::FunctorHandler<ParentFunctor, Func>::DoEval(const double*) const [with ParentFunctor = ROOT::Math::Functor; Func = double (*)(const double*, int)]’:
Minimization.C:177:1:   required from here
(...)/root6_inst/include/root/Math/Functor.h:120:21: error: too few arguments to function
       return fFunc(x);
                     ^
Makefile:33 : la recette pour la cible « Minimization.o » a échouée
make: *** [Minimization.o] Erreur 1

TL;DR:
make pm_function a functor class.

Hi, to keep the signature as it is, but give your functor more state (more information), you have to make pm_function a class the defines operator()(double* b, int i) (or a lambda).

You can pass the extra arguments that you want pm_function to have to the constructor of the class (or in the capture list of the lambda) and the pass the class/lambda to ROOT::Math::Functor. It will not care that it is not a simple function, as long as it can call yourObject(v,i) on it.

1 Like

Thank you very much for your reply @eguiraud .
I do not understand very well what you are talking about is you may be using an advanced c ++ technique that I do not use yet. A clearer example will be appreciated. ?

I tried something like this:

class pmfunction{
public:
        double pm_function (const double *v)
        {
            ....
        }
        TH1F* spectrum = new ...
       ....
};

int main() function

         ....
 	pmfunction pmfun ;
	ROOT::Math::Functor PMFun(&pmfun.pm_function, nbr_of_variable) ;
        ...

but I had this error

Minimization.C: In function ‘int main(int, char**)’:
Minimization.C:157:35: error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function.  Say ‘&pmfunction::pm_function’ [-fpermissive]
  ROOT::Math::Functor PMFun(&pmfun.pm_function, N) ;
                                   ^~~~~~~~~~~
In file included from Minimization.C:10:0:
/home/orly/Documents/root6/root6-build/include/Math/Functor.h: In instantiation of ‘double ROOT::Math::FunctorHandler<ParentFunctor, Func>::DoEval(const double*) const [with ParentFunctor = ROOT::Math::Functor; Func = double (pmfunction::*)(const double*)]’:
Minimization.C:199:1:   required from here
/home/orly/Documents/root6/root6-build/include/Math/Functor.h:120:21: error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘((const ROOT::Math::FunctorHandler<ROOT::Math::Functor, double (pmfunction::*)(const double*)>*)this)->ROOT::Math::FunctorHandler<ROOT::Math::Functor, double (pmfunction::*)(const double*)>::fFunc (...)’, e.g. ‘(... ->* ((const ROOT::Math::FunctorHandler<ROOT::Math::Functor, double (pmfunction::*)(const double*)>*)this)->ROOT::Math::FunctorHandler<ROOT::Math::Functor, double (pmfunction::*)(const double*)>::fFunc) (...)’
       return fFunc(x);
                     ^
Makefile:33 : la recette pour la cible « Minimization.o » a échouée
make: *** [Minimization.o] Erreur 1

Thanks

Hi,
I would suggest you read up about c++11 lambdas, there are lots of good tutorials on the internet and I would argue they are the single most useful feature introduced by c++11.

Coming to your example, you are almost there. I think you understood what I meant when I said you should encapsulate the pm_function in a class, so you can leave its signature unchanged but you can let it access more variables (i.e. more “state”) in the form of the class’ data members.

The ingredient missing is that we need to let your pmfunction class act like a function. We want to allow ROOT::Math::Functor to call your pmfunction class just as if it was a function. The way you do it is by defining what happens when you use brackets () after an instance of your class. More concretely, we need to define pmfunction::operator() to act like pm_function:

class pmfunction {
public:
  double operator()(const double *v)
  {
     ...
  }
};

Now you can use an instance of pmfunction as if it was a function:

pmfunction f;
double *v = new double;
f(v); // this calls pmfunction::operator()

Finally, note that you cannot in general declare variables in the body of a class like you are doing with TH1F* spectrum. Usually member variables are initialized by the class constructor. Again, there are many c++ intro tutorials that you can find if you are not sure what I mean. Also note that it is good design to define member variables as private, so that only class instances can access them.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.