// @(#)root/mathcore:$Id$
// Author: L. Moneta Fri Sep 22 15:06:47 2006

/**********************************************************************
 *                                                                    *
 * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
 *                                                                    *
 *                                                                    *
 **********************************************************************/

// Header file for class DistSampler

#ifndef ROOT_Math_DistSampler
#define ROOT_Math_DistSampler

#ifndef ROOT_Math_IFunctionfwd
#include "Math/IFunctionfwd.h"
#endif

#ifndef ROOT_Math_WrappedFunction
#include "Math/WrappedFunction.h"
#endif

#include <vector>
#include <cassert>

class TRandom;

namespace ROOT {

   namespace Fit {

      class DataRange;
      class BinData;
      class UnBinData;
   }

   namespace Math {

      class DistSamplerOptions;

/**
   @defgroup Random Random number generators and generation of random number distributions
   @ingroup Random

   Classes implementing random number generators and classes implementing generation of random numbers
   according to arbitrary distributions
*/

//_______________________________________________________________________________
/**
   Interface class for generic sampling of a distribution,
   i.e. generating random numbers according to arbitrary distributions

   @ingroup Random
*/


class DistSampler {

public:

   /// default constructor
   DistSampler() : fOwnFunc(false), fRange(0), fFunc(0) {}


   /// virtual destructor
   virtual ~DistSampler();



   /// set the parent function distribution to use for sampling (generic case)
   template<class Function>
   void SetFunction(Function & func, unsigned int dim) {
      WrappedMultiFunction<Function &> wf(func, dim);
      fData.resize(dim);
      // need to clone to avoid temporary
      DoSetFunction(wf,true);
   }

   /// set the parent function distribution to use for random sampling (one dim case)
   virtual void SetFunction(const ROOT::Math::IGenFunction & func)  {
      SetFunction<const ROOT::Math::IGenFunction>(func, 1);
   }


   /// set the parent function distribution to use for random sampling (multi-dim case)
   virtual void SetFunction(const ROOT::Math::IMultiGenFunction & func)  {
      DoSetFunction(func,false);
   }

   /// return the dimension of the parent distribution (and the data)
   unsigned int NDim() const { return fData.size(); }


   /**
      initialize the generators with the given algorithm
      Implemented by derived classes who needs it
      (like UnuranSampler)
      If nothing is specified use default algorithm
      from DistSamplerOptions::SetDefaultAlgorithm
   */
   virtual bool Init(const char * =""/* algorithm */) { return true;}

   /**
      initialize the generators with the given option
      which my include the algorithm but also more if
      the method is re-impelmented by derived class
      The default implementation calls the above method
      passing just the algorithm name
   */
   virtual bool Init(const DistSamplerOptions & opt );


   /**
       Set the random engine to be used
       To be implemented by the derived classes who provides
       random sampling
   */
   virtual void SetRandom(TRandom *  ) {}

   /**
       Set the random seed for the TRandom instances used by the sampler
       classes
       To be implemented by the derived classes who provides random sampling
   */
   virtual void SetSeed(unsigned int /*seed*/ ) {}

   /**
      Get the random engine used by the sampler
      To be implemented by the derived classes who needs it
      Returns zero by default
    */
   virtual TRandom * GetRandom() { return 0; }

   /// set range in a given dimension
   void SetRange(double xmin, double xmax, int icoord = 0);

   /// set range for all dimensions
   void SetRange(const double * xmin, const double * xmax);

   /// set range using DataRange class
   void SetRange(const ROOT::Fit::DataRange & range);

   /// set the mode of the distribution (could be useful to some methods)
   /// implemented by derived classes if needed
   virtual void SetMode(double  ) {}

   /// set the normalization area of distribution
   /// implemented by derived classes if needed
   virtual void SetArea(double) {}

   /// get the parent distribution function (must be called after setting the function)
   const ROOT::Math::IMultiGenFunction & ParentPdf() const {
      return *fFunc;
   }


   /**
      sample one event in one dimension
      better implementation could be provided by the derived classes
   */
   virtual double Sample1D() {
      Sample(&fData[0]);
      return fData[0];
   }

   /**
      sample one event and rerturning array x with coordinates
    */
   const double *  Sample() {
      Sample(&fData[0]);
      return &fData.front();
   }

   /**
      sample one event in multi-dimension by filling the given array
      return false if sampling failed
   */
   virtual bool Sample(double * x) = 0;

   /**
      sample one bin given an estimated of the pdf in the bin
      (this can be function value at the center or its integral in the bin
      divided by the bin width)
      By default do not do random sample, just return the function values
      Typically Poisson statistics will be used
    */
   virtual bool SampleBin(double prob, double & value, double * error = 0) {
      value = prob;
      if (error) *error = 0;
      return true;
   }
   /**
      sample a set of bins given a vector of probabilities
      Typically multinomial statistics will be used and the sum of the probabilities
      will be equal to the total number of events to be generated
      For sampling the bins indipendently, SampleBin should be used
    */
   virtual bool SampleBins(unsigned int n, const double * prob, double * values, double * errors  = 0)  {
      std::copy(prob,prob+n, values);
      if (errors) std::fill(errors,errors+n,0);
      return true;
   }


   /**
      generate a un-binned data sets (fill the given data set)
      if dataset has already data append to it
   */
   virtual bool Generate(unsigned int nevt, ROOT::Fit::UnBinData & data);


   /**
      generate a bin data set .
      A range must have been set before (otherwise inf is returned)
      and the bins are equidinstant in the previously defined range
      bin center values must be present in given data set
      If the sampler is implemented by a random one, the entries
      will be binned according to the Poisson distribution
      It is assumed the distribution is normalized, otherwise the nevt must be scaled
      accordingly. The expected value/bin nexp  = f(x_i) * binArea/ nevt
      Extend control if use a fixed (i.e. multinomial statistics) or floating total number of events
   */
   virtual bool Generate(unsigned int nevt, const  int * nbins, ROOT::Fit::BinData & data, bool extend = true);
   /**
      same as before but passing the range in case of 1 dim data
    */
   bool Generate(unsigned int nevt, int nbins, double xmin, double xmax, ROOT::Fit::BinData & data, bool extend = true) {
      SetRange(xmin,xmax);
      int nbs[1]; nbs[0] = nbins;
      return Generate(nevt, nbs, data, extend);
   }


protected:

   // internal method to set the function
   virtual void DoSetFunction(const ROOT::Math::IMultiGenFunction & func, bool copy);
   // check if generator have been initialized correctly and one can start generating
   bool IsInitialized() ;
   /// return the data range of the Pdf . Must be called after setting the function
   const ROOT::Fit::DataRange & PdfRange() const {
      assert(fRange);
      return *fRange;
   }




private:

   // private methods

   bool fOwnFunc;                         // flag to indicate if the function is owned
   mutable std::vector<double> fData;     // internal array used to cached the sample data
   ROOT::Fit::DataRange    *   fRange;    // data range
   const ROOT::Math::IMultiGenFunction * fFunc; // internal function (ND)


};

   } // end namespace Math

} // end namespace ROOT


#endif /* ROOT_Math_DistSampler */
 DistSampler.h:1
 DistSampler.h:2
 DistSampler.h:3
 DistSampler.h:4
 DistSampler.h:5
 DistSampler.h:6
 DistSampler.h:7
 DistSampler.h:8
 DistSampler.h:9
 DistSampler.h:10
 DistSampler.h:11
 DistSampler.h:12
 DistSampler.h:13
 DistSampler.h:14
 DistSampler.h:15
 DistSampler.h:16
 DistSampler.h:17
 DistSampler.h:18
 DistSampler.h:19
 DistSampler.h:20
 DistSampler.h:21
 DistSampler.h:22
 DistSampler.h:23
 DistSampler.h:24
 DistSampler.h:25
 DistSampler.h:26
 DistSampler.h:27
 DistSampler.h:28
 DistSampler.h:29
 DistSampler.h:30
 DistSampler.h:31
 DistSampler.h:32
 DistSampler.h:33
 DistSampler.h:34
 DistSampler.h:35
 DistSampler.h:36
 DistSampler.h:37
 DistSampler.h:38
 DistSampler.h:39
 DistSampler.h:40
 DistSampler.h:41
 DistSampler.h:42
 DistSampler.h:43
 DistSampler.h:44
 DistSampler.h:45
 DistSampler.h:46
 DistSampler.h:47
 DistSampler.h:48
 DistSampler.h:49
 DistSampler.h:50
 DistSampler.h:51
 DistSampler.h:52
 DistSampler.h:53
 DistSampler.h:54
 DistSampler.h:55
 DistSampler.h:56
 DistSampler.h:57
 DistSampler.h:58
 DistSampler.h:59
 DistSampler.h:60
 DistSampler.h:61
 DistSampler.h:62
 DistSampler.h:63
 DistSampler.h:64
 DistSampler.h:65
 DistSampler.h:66
 DistSampler.h:67
 DistSampler.h:68
 DistSampler.h:69
 DistSampler.h:70
 DistSampler.h:71
 DistSampler.h:72
 DistSampler.h:73
 DistSampler.h:74
 DistSampler.h:75
 DistSampler.h:76
 DistSampler.h:77
 DistSampler.h:78
 DistSampler.h:79
 DistSampler.h:80
 DistSampler.h:81
 DistSampler.h:82
 DistSampler.h:83
 DistSampler.h:84
 DistSampler.h:85
 DistSampler.h:86
 DistSampler.h:87
 DistSampler.h:88
 DistSampler.h:89
 DistSampler.h:90
 DistSampler.h:91
 DistSampler.h:92
 DistSampler.h:93
 DistSampler.h:94
 DistSampler.h:95
 DistSampler.h:96
 DistSampler.h:97
 DistSampler.h:98
 DistSampler.h:99
 DistSampler.h:100
 DistSampler.h:101
 DistSampler.h:102
 DistSampler.h:103
 DistSampler.h:104
 DistSampler.h:105
 DistSampler.h:106
 DistSampler.h:107
 DistSampler.h:108
 DistSampler.h:109
 DistSampler.h:110
 DistSampler.h:111
 DistSampler.h:112
 DistSampler.h:113
 DistSampler.h:114
 DistSampler.h:115
 DistSampler.h:116
 DistSampler.h:117
 DistSampler.h:118
 DistSampler.h:119
 DistSampler.h:120
 DistSampler.h:121
 DistSampler.h:122
 DistSampler.h:123
 DistSampler.h:124
 DistSampler.h:125
 DistSampler.h:126
 DistSampler.h:127
 DistSampler.h:128
 DistSampler.h:129
 DistSampler.h:130
 DistSampler.h:131
 DistSampler.h:132
 DistSampler.h:133
 DistSampler.h:134
 DistSampler.h:135
 DistSampler.h:136
 DistSampler.h:137
 DistSampler.h:138
 DistSampler.h:139
 DistSampler.h:140
 DistSampler.h:141
 DistSampler.h:142
 DistSampler.h:143
 DistSampler.h:144
 DistSampler.h:145
 DistSampler.h:146
 DistSampler.h:147
 DistSampler.h:148
 DistSampler.h:149
 DistSampler.h:150
 DistSampler.h:151
 DistSampler.h:152
 DistSampler.h:153
 DistSampler.h:154
 DistSampler.h:155
 DistSampler.h:156
 DistSampler.h:157
 DistSampler.h:158
 DistSampler.h:159
 DistSampler.h:160
 DistSampler.h:161
 DistSampler.h:162
 DistSampler.h:163
 DistSampler.h:164
 DistSampler.h:165
 DistSampler.h:166
 DistSampler.h:167
 DistSampler.h:168
 DistSampler.h:169
 DistSampler.h:170
 DistSampler.h:171
 DistSampler.h:172
 DistSampler.h:173
 DistSampler.h:174
 DistSampler.h:175
 DistSampler.h:176
 DistSampler.h:177
 DistSampler.h:178
 DistSampler.h:179
 DistSampler.h:180
 DistSampler.h:181
 DistSampler.h:182
 DistSampler.h:183
 DistSampler.h:184
 DistSampler.h:185
 DistSampler.h:186
 DistSampler.h:187
 DistSampler.h:188
 DistSampler.h:189
 DistSampler.h:190
 DistSampler.h:191
 DistSampler.h:192
 DistSampler.h:193
 DistSampler.h:194
 DistSampler.h:195
 DistSampler.h:196
 DistSampler.h:197
 DistSampler.h:198
 DistSampler.h:199
 DistSampler.h:200
 DistSampler.h:201
 DistSampler.h:202
 DistSampler.h:203
 DistSampler.h:204
 DistSampler.h:205
 DistSampler.h:206
 DistSampler.h:207
 DistSampler.h:208
 DistSampler.h:209
 DistSampler.h:210
 DistSampler.h:211
 DistSampler.h:212
 DistSampler.h:213
 DistSampler.h:214
 DistSampler.h:215
 DistSampler.h:216
 DistSampler.h:217
 DistSampler.h:218
 DistSampler.h:219
 DistSampler.h:220
 DistSampler.h:221
 DistSampler.h:222
 DistSampler.h:223
 DistSampler.h:224
 DistSampler.h:225
 DistSampler.h:226
 DistSampler.h:227
 DistSampler.h:228
 DistSampler.h:229
 DistSampler.h:230
 DistSampler.h:231
 DistSampler.h:232
 DistSampler.h:233
 DistSampler.h:234
 DistSampler.h:235
 DistSampler.h:236
 DistSampler.h:237
 DistSampler.h:238
 DistSampler.h:239
 DistSampler.h:240
 DistSampler.h:241
 DistSampler.h:242
 DistSampler.h:243
 DistSampler.h:244
 DistSampler.h:245
 DistSampler.h:246
 DistSampler.h:247
 DistSampler.h:248
 DistSampler.h:249
 DistSampler.h:250
 DistSampler.h:251
 DistSampler.h:252
 DistSampler.h:253
 DistSampler.h:254
 DistSampler.h:255
 DistSampler.h:256
 DistSampler.h:257
 DistSampler.h:258
 DistSampler.h:259
 DistSampler.h:260
 DistSampler.h:261
 DistSampler.h:262
 DistSampler.h:263
 DistSampler.h:264
 DistSampler.h:265
 DistSampler.h:266
 DistSampler.h:267
 DistSampler.h:268