Lambda with capture list as a TF1 parameter

ROOT Version: 6.22/08
Platform: Ubuntu 20.04 under WSL2
Compiler: gcc 9.3.0


Warning : issue is a non-priority (I suppose that I know how to solve it, but in a somewhat unpleasant way)

I tried to pass lambda with some capture list into TF1, but it didn’t work for me no matter how I try.

Following fails due to compilation error saying that TF1 cannot be constructed this way

    Double_t par1 = 0, par2 = 2;
	auto fit_lamb = [=](Double_t* x) {return par1 + x[0] * par2; };
	TF1* fit = new TF1("fit", fit_lamb, 0, 6, 2);

Following

Double_t par1 = 0, par2 = 2;
	auto fit_lamb = [=](Double_t* x) {return par1 + x[0] * par2; };
	TF1* fit = new TF1("fit", "fit_lamb(x)", 0, 6);

fails at the execution time

input_line_12:2:66: error: use of undeclared identifier 'fit_lamb'
Double_t TFormula____id10424473659609012643(Double_t *x){ return fit_lamb(x[0]) ; }
                                                                 ^
input_line_13:2:66: error: use of undeclared identifier 'fit_lamb'
Double_t TFormula____id10424473659609012643(Double_t *x){ return fit_lamb(x[0]) ; }
                                                                 ^
Error in <prepareMethod>: Can't compile function TFormula____id10424473659609012643 prototype with arguments Double_t*
Error in <TFormula::InputFormulaIntoCling>: Error compiling formula expression in Cling
Error in <TFormula::ProcessFormula>: Formula "fit_lamb(x)" is invalid !
...

An obvious solution is to pass whole capture list as a parameter list, but I find this solution not so elegant. What is the intended way of solving this issue?

Thanks in advance for any help.

{
  static double par1 = 0., par2 = 2.;
  auto f1_lamb = [](const double *x, const double *) {return par1 + x[0] * par2;};
  TF1 *f1 = new TF1("f1", f1_lamb, 0., 6., 0);
  f1->Print();
  new TCanvas(); f1->Draw();
  auto f2_lamb = [](const double *x, const double *p) {return p[0] + x[0] * p[1];};
  TF1 *f2 = new TF1("f2", f2_lamb, 0., 6., 2);
  f2->Print();
  f2->SetParameters(par1, par2);
  new TCanvas(); f2->Draw();
}

While first solution seems like not a big mess, I’d like to avoid a static keyword (I’m going to reuse that function). Second solution I recognize as the one I suggested.

Thanks for providing options, but it seems like right now there is no full support of lambdas (and, I suppose, std::function) in TF1? Will it be added later on?

{{
  double par1 = 0., par2 = 2.;
  auto fit_lamb = [=](const double *x, const double *) {return par1 + x[0] * par2;};
  TF1 *fit = new TF1("fit", fit_lamb, 0., 6., 0);
  fit->Print();
  new TCanvas(); fit->Draw();
}}

Hm, interesting. That works and thats exactly what I asked about. Thanks a lot!

Hi,
We have full support of lambda, std::function and any C++ callable object for building a TF1. You just need to provide the correct signature: double operator() (double *, double *)

Lorenzo

I see now. That is actually a relief, thanks.

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