Hello,
I am having a lot of issues creating TTrees with hi-precision quantities like the ones provided by gmp.h and mpfr.h.
So, long story short, using doubles resulted in errors in my calculations, so I had to create hi-precision objects (type mpfr_t) using the mpfr.h library. The computations are then carried out successfully, but then I am unable to create a TTree with mpfr_t objects.
I admit that I have a lot of confusion on the topic. I wrote a short program trying to accomplish what I’m trying to do:
# include <iostream>
# include "TRandom3.h"
# include "TFile.h"
# include "TTree.h"
# include <gmp.h> // hi-precision library
# include <mpfr.h>
using namespace std;
void GenerateMPFR(mpfr_t *in);
void test_mpfr(){
mpfr_t testvar;
mpfr_init(testvar);
TFile *fout = new TFile("output.root","recreate");
TTree *tout = new TTree("tout","Tree out");
tout->Branch("branch_mpfr", &testvar);
for(int i=0;i<10;++i){
GenerateMPFR(&testvar);
tout->Fill();
}
tout->Write();
fout->Close();
mpfr_clear(testvar);
mpfr_free_cache();
}
void GenerateMPFR(mpfr_t *in){
TRandom3 *r = new TRandom3(0);
mpfr_set_d(*in, r->Uniform(), MPFR_RNDN);
}
#ifndef __CINT__
int main(int argc, char **argv) {
if ( argc == 1 ) {
std::cout << "\n==========> test_mpfr <=============" << std::endl;
test_mpfr();
}
else {
cout << "Usage:" << endl;
cout << "./test_mpfr.cc.exe" << endl;
return 0;
}
std::cout << "==> Application finished." << std::endl;
return 0;
}
#endif /* __CINT __ */
The program gets successfully compiled with the following call to the compiler:
g++ -std=c++11 test_mpfr.cc -o test_mpfr.cc.exe `root-config --libs --cflags` -lMinuit -lmpfr -lgmp -lgmpxx
But when I run the program, I get the following message:
Error in <TTree::Branch>: The pointer specified for branch_mpfr is not of a class or type known to ROOT
And here’s when I start to be confused. Reading online I learned that I have to create a dictionary telling ROOT what to do with the object that I’m trying to pass as branch element. The first thing that I tried to do, then, was to create the shared objects for gmp.h and mpfr.h with:
root[0] .L /path-to-library/gmp.h+
root[1] .L /path-to-library/mpfr.h+
obtaining “.so files", ".d files”, and “*_ACLiC_dict_rdict.pcm” (naively, I’d say that these last files are the dictionary for the library). I would then load these files into my program with the lines:
gSystem->Load("gmp_h.so");
gSystem->Load("mpfr_h.so");
but this doesn’t solve my problem.
Further research showed me that I might have to use a LinkDef.h file, but I am totally clueless on what #pragma code to add, how to implement it, if to #include it in my code, if converting it to a .so file and loading it with gSystem->Load, I even found a reference to roocling to create an additional *.cxx file, but again, I don’t know what to do with the resulting file.
Please help. I’m not asking to straight solve my problem, but at least to point me to some useful resource that I can use to solve my issue.
Thank you.
ROOT Version: 6.12/06
Platform: Linux Mint 18.3
Compiler: g++ 5.4.0