Setting TF1 parameter broken when declaring with a lambda function


ROOT Version: 6.12/06
Platform: OSX 10.13.4
Compiler: Apple LLVM version 9.1.0 (clang-902.0.39.2)


Dear ROOTers,
I’m trying to construct a TF1 object from a lambda function to be used in a fit. Whenever I try to call TF1::SetParameter or TF1::SetParameters on the resulting TF1 the parameter values are not the ones I put there. Actually some of them seem to be resulting from a invalid memory access.

Here a small example

{
  auto lfun = [&](double *x, double *p) {
    cout << "Inside lambda function" << endl;

    cout << "  passed parameters: ";
    for (int i = 0; i < 5; i++)
      cout << p[i] << " ";
    cout << endl;
    double lambda = p[3];
    double lambda2 = p[4];
    double y = lambda == 0 ? log(x[0] + lambda2)
                          : (pow(x[0] + lambda2, lambda) - 1) / lambda;
    cout << x[0] << " -> " << y << " (" << lambda << "," << lambda2 << ")"
         << endl;
    return p[0] * TMath::Gaus(y, p[1], p[2]);
  };

  cout << "Test lambda function..." << endl;
  double _x[] = {1.};
  double _p[] = {1., 1., 1., 1., 1.};
  cout << lfun(_x, _p) << endl;
  cout << "...seems OK" << endl << endl;

  cout << "Test TF1..." << endl;
  auto bctest = new TF1("bctest", lfun, -1, 3, 1);
  for (int i = 0; i < 5; i++) {
    bctest->SetParameter(i, _p[i]);
    cout << i << " - " << bctest->GetParameter(i) << endl;
  }
  cout << "wrong parameters!" << endl << endl;

  cout << "Try to pass parameter array..." << endl;
  bctest->SetParameters(_p);
  for (int i = 0; i < 5; i++) {
    cout << i << " - " << bctest->GetParameter(i) << endl;
  }
  cout << "wrong parameters!" << endl << endl;

  cout << "Try to pass hardcoded parameters..." << endl;
  bctest->SetParameters(1., 1., 1., 1., 1.);
  for (int i = 0; i < 5; i++) {
    cout << i << " - " << bctest->GetParameter(i) << endl;
  }
  cout << "wrong parameters!" << endl << endl;


  cout << "Calling TF1::Eval()" << endl;
  cout << bctest->Eval(1) << endl;
}

and here’s the output:

root [0]
Processing test_bc.C...
Test lambda function...
Inside lambda function
  passed parameters: 1 1 1 1 1
1 -> 1 (1,1)
1
...seems OK

Test TF1...
0 - 1
1 - 0
2 - 0
3 - 0
4 - 0
wrong parameters!

Try to pass parameter array...
0 - 1
1 - 0
2 - 0
3 - 0
4 - 0
wrong parameters!

Try to pass hardcoded parameters...
0 - 1
1 - 0
2 - 0
3 - 0
4 - 0
wrong parameters!

Calling TF1::Eval()
Inside lambda function
  passed parameters: 1 -1.49458e-154 6.94021e-310 6.94021e-310 6.94021e-310
1 -> 0 (6.94021e-310,6.94021e-310)
0

I’m following closely the example on the Doxygen but I don’t understand what’s going wrong…

Cheers,
Valerio

auto bctest = new TF1("bctest", lfun, -1, 3, 5);

Oh my god I feel so dumb… I misread the constructor!

Thanks!

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