Using TF1 in compiled code with my own function -- what am I doing wrong?

ROOT Version: 6.26/06
Platform: MacOS 12.6.7
Compiler: g++

I am trying to make a graph of a function. This simple implementation below does not work. The function chi2_p2bm clearly exists, because I can calculate a value and print it out via the cout. But the TF1 does not recognize it. I am very confused because this looks exactly like many of the examples in the TF1 documentation.

Here is the compiler line:
% g++ -std=c++11 testgraph.cpp -o testgraph root-config --cflags --glibs

Here is the output:
% ./testgraph
0.0225
0.0256
0.0289
0.0324
input_line_8:2:65: error: use of undeclared identifier ‘chi2_p2bm’
Double_t TFormula____id4664759779193443662(Double_t *x){ return chi2_p2bm(x[0]) ; }
^
input_line_9:2:65: error: use of undeclared identifier ‘chi2_p2bm’
Double_t TFormula____id4664759779193443662(Double_t x){ return chi2_p2bm(x[0]) ; }
^
Error in : Can’t compile function TFormula____id4664759779193443662 prototype with arguments Double_t

Error in < TFormula::InputFormulaIntoCling >: Error compiling formula expression in Cling
Error in < TFormula::ProcessFormula >: Formula “chi2_p2bm(x)” is invalid !
%

Here is the code:

#include <TObject.h>
#include <TROOT.h>
#include <TClass.h>
#include <TError.h>
#include <TMath.h>
#include <TH1.h>
#include <TH2.h>
#include <TH3.h>
#include <TF1.h>
#include <TGraphErrors.h>
#include <TCanvas.h>
#include <TMinuit.h>
#include <TStyle.h>
#include <TPaveText.h>
#include <TPaveLabel.h>
#include <TLegend.h>
#include <TMatrixD.h>
#include <TFormula.h>

using namespace std;

double chi2_p2bm(double x) {
return pow(x,2);
}

int main()
{

cout << chi2_p2bm(.15) << endl;
cout << chi2_p2bm(.16) << endl;
cout << chi2_p2bm(.17) << endl;
cout << chi2_p2bm(.18) << endl;

TCanvas *c1 = new TCanvas("c1", "",1900,1100);

// c1->Divide(5,1);
// c1->cd(1);

TF1 *fp2bm = new TF1("fp2bm","chi2_p2bm(x)",0.1,0.3);

// fp2bm->Draw();

// c1->Print(“chi2.pdf”);
}

I think these functions cannot be compiled, see the TF1 doc. You can use the types 4-6 on that page, e.g.

/*
  g++ testgraph.cpp -o testgraph `root-config --cflags --glibs`
*/

#include <TObject.h>
#include <TROOT.h>
#include <TClass.h>
#include <TError.h>
#include <TMath.h>
#include <TH1.h>
#include <TH2.h>
#include <TH3.h>
#include <TF1.h>
#include <TGraphErrors.h>
#include <TCanvas.h>
#include <TMinuit.h>
#include <TStyle.h>
#include <TPaveText.h>
#include <TPaveLabel.h>
#include <TLegend.h>
#include <TMatrixD.h>
#include <TFormula.h>

using namespace std;

Double_t chi2_p2bm(Double_t *x, Double_t *par) {
   return pow(x[0],2);
}

int main() {
/*
  double myx[1]={.15};
  cout << chi2_p2bm(myx,myx) << endl;
*/
  TCanvas *c1 = new TCanvas("c1", "",1900,1100);
  c1->Divide(2,1);

  c1->cd(1);
  TF1 *fp2bm = new TF1("fp2bm", chi2_p2bm, 0.1, 0.3, 0);
  fp2bm->Draw();

  // or with Lambda:
  c1->cd(2);
  TF1 *fp2bmL = new TF1("fp2bmL",[&](double*x, double *p){ return pow(x[0],2); }, 0.1, 0.3, 0);
  fp2bmL->Draw();

  c1->SaveAs("chi2.pdf");
}

Helllo @sfpate !
I guess you should use a different TF1 constructor, for example

double chi2_p2bm(double *x, double *par)
{
    return pow(x[0]);
}
...
TF1 *fp2bm = new TF1("fp2bm", chi2_p2bm, 0.1, 0.3, 0);

Here the last argument 0 to the constructor is number of parameters of function, which is actually zero.

Edit: I just realized that the post above gives a more detailed explanation, so mine is just a duplicate. I apologize for my haste and inattention.

Also, it might be useful to take a look at this post about the use of new statement in modern C++:
https://root-forum.cern.ch/t/how-to-properly-delete-ttree-and-tgraph-and-renew-them/55351/2?u=ako_b

Dear @dastudillo and @Ako_b

Thank you for your quick responses. I chose to use the parametrized function with no parameters.

Steve

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