30 ClassImp(TUnuranSampler);
32 TUnuranSampler::TUnuranSampler() : ROOT::Math::DistSampler(),
35 fHasMode(false), fHasArea(false),
38 fUnuran(new TUnuran() )
40 fLevel = ROOT::Math::DistSamplerOptions::DefaultPrintLevel();
43 TUnuranSampler::~TUnuranSampler() {
48 bool TUnuranSampler::Init(
const char * algo) {
50 assert (fUnuran != 0 );
52 Error(
"TUnuranSampler::Init",
"Distribution function has not been set ! Need to call SetFunction first.");
56 if (fLevel < 0) fLevel = ROOT::Math::DistSamplerOptions::DefaultPrintLevel();
59 if (method.IsNull() ) {
60 if (NDim() == 1) method = ROOT::Math::DistSamplerOptions::DefaultAlgorithm1D();
61 else method = ROOT::Math::DistSamplerOptions::DefaultAlgorithmND();
69 if (method.First(
"D") == 0) {
70 if (fLevel>1) Info(
"TUnuranSampler::Init",
"Initialize one-dim discrete distribution with method %s",method.Data());
71 ret = DoInitDiscrete1D(method);
74 if (fLevel>1) Info(
"TUnuranSampler::Init",
"Initialize one-dim continuous distribution with method %s",method.Data());
75 ret = DoInit1D(method);
79 if (fLevel>1) Info(
"TUnuranSampler::Init",
"Initialize multi-dim continuous distribution with method %s",method.Data());
80 ret = DoInitND(method);
85 if (ret) Info(
"TUnuranSampler::Init",
"Successfully initailized Unuran with method %s",method.Data() );
86 else Error(
"TUnuranSampler::Init",
"Failed to initailize Unuran with method %s",method.Data() );
93 bool TUnuranSampler::Init(
const ROOT::Math::DistSamplerOptions & opt ) {
95 SetPrintLevel(opt.PrintLevel() );
96 return Init(opt.Algorithm().c_str() );
100 bool TUnuranSampler::DoInit1D(
const char * method) {
105 TUnuranContDist * dist = 0;
107 ROOT::Math::OneDimMultiFunctionAdapter<>
function(ParentPdf() );
108 dist =
new TUnuranContDist(
function,0,
false,
true);
111 dist =
new TUnuranContDist(*fFunc1D);
114 const ROOT::Fit::DataRange & range = PdfRange();
115 if (range.Size(0) > 0) {
117 range.GetRange(0,xmin,xmax);
118 dist->SetDomain(xmin,xmax);
120 if (fHasMode) dist->SetMode(fMode);
121 if (fHasArea) dist->SetPdfArea(fArea);
124 if (method) ret = fUnuran->Init(*dist, method);
125 else ret = fUnuran->Init(*dist);
130 bool TUnuranSampler::DoInitDiscrete1D(
const char * method) {
134 TUnuranDiscrDist * dist = 0;
137 ROOT::Math::OneDimMultiFunctionAdapter<>
function(ParentPdf() );
138 dist =
new TUnuranDiscrDist(
function,
true);
142 dist =
new TUnuranDiscrDist(*fFunc1D,
false);
146 const ROOT::Fit::DataRange & range = PdfRange();
147 if (range.Size(0) > 0) {
149 range.GetRange(0,xmin,xmax);
151 Warning(
"DoInitDiscrete1D",
"range starts from negative values - set minimum to zero");
154 dist->SetDomain(
int(xmin+0.1),
int(xmax+0.1));
156 if (fHasMode) dist->SetMode(
int(fMode+0.1));
157 if (fHasArea) dist->SetProbSum(fArea);
159 bool ret = fUnuran->Init(*dist, method);
165 bool TUnuranSampler::DoInitND(
const char * method) {
167 TUnuranMultiContDist dist(ParentPdf());
169 const ROOT::Fit::DataRange & range = PdfRange();
171 std::vector<double> xmin(range.NDim() );
172 std::vector<double> xmax(range.NDim() );
173 range.GetRange(&xmin[0],&xmax[0]);
174 dist.SetDomain(&xmin.front(),&xmax.front());
182 if (method)
return fUnuran->Init(dist, method);
183 return fUnuran->Init(dist);
186 void TUnuranSampler::SetFunction(TF1 * pdf) {
188 SetFunction<TF1>(*pdf, pdf->GetNdim());
191 void TUnuranSampler::SetRandom(TRandom * r) {
193 fUnuran->SetRandom(r);
196 void TUnuranSampler::SetSeed(
unsigned int seed) {
198 fUnuran->SetSeed(seed);
201 TRandom * TUnuranSampler::GetRandom() {
203 return fUnuran->GetRandom();
206 double TUnuranSampler::Sample1D() {
208 return (fDiscrete) ? (double) fUnuran->SampleDiscr() : fUnuran->Sample();
211 bool TUnuranSampler::Sample(
double * x) {
213 if (!fOneDim)
return fUnuran->SampleMulti(x);
219 bool TUnuranSampler::SampleBin(
double prob,
double & value,
double *error) {
222 TRandom * r = fUnuran->GetRandom();
223 if (!r)
return false;
224 value = r->Poisson(prob);
225 if (error) *error = std::sqrt(value);