00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 #include "RooFit.h"
00031 
00032 #include "RooQuasiRandomGenerator.h"
00033 #include "RooQuasiRandomGenerator.h"
00034 #include "RooMsgService.h"
00035 #include "TMath.h"
00036 
00037 #include "Riostream.h"
00038 #include <assert.h>
00039 
00040 ClassImp(RooQuasiRandomGenerator)
00041   ;
00042 
00043 
00044 
00045 
00046 RooQuasiRandomGenerator::RooQuasiRandomGenerator() 
00047 {
00048   
00049   
00050   
00051   if(!_coefsCalculated) {
00052     calculateCoefs(MaxDimension);
00053     _coefsCalculated= kTRUE;
00054   }
00055   
00056   _nextq= new Int_t[MaxDimension];
00057   reset();
00058 }
00059 
00060 
00061 
00062 RooQuasiRandomGenerator::~RooQuasiRandomGenerator() 
00063 {
00064   
00065 
00066   delete[] _nextq;
00067 }
00068 
00069 
00070 
00071 void RooQuasiRandomGenerator::reset() 
00072 {
00073   
00074 
00075   _sequenceCount= 0;
00076   for(Int_t dim= 0; dim < MaxDimension; dim++) _nextq[dim]= 0;
00077 }
00078 
00079 
00080 
00081 Bool_t RooQuasiRandomGenerator::generate(UInt_t dimension, Double_t vector[]) 
00082 {
00083   
00084   
00085   
00086   
00087   static const Double_t recip = 1.0/(double)(1U << NBits); 
00088 
00089   UInt_t dim;
00090   for(dim=0; dim < dimension; dim++) {
00091     vector[dim] = _nextq[dim] * recip;
00092   }
00093 
00094   
00095 
00096 
00097 
00098   Int_t r(0),c(_sequenceCount);
00099   while(1) {
00100     if((c % 2) == 1) {
00101       ++r;
00102       c /= 2;
00103     }
00104     else break;
00105   }
00106   if(r >= NBits) {
00107     oocoutE((TObject*)0,Integration) << "RooQuasiRandomGenerator::generate: internal error!" << endl;
00108     return kFALSE;
00109   }
00110 
00111   
00112   for(dim=0; dim<dimension; dim++) {
00113     _nextq[dim] ^= _cj[r][dim];
00114   }
00115   _sequenceCount++;
00116 
00117   return kTRUE;
00118 }
00119 
00120 
00121 
00122 void RooQuasiRandomGenerator::calculateCoefs(UInt_t dimension) 
00123 {
00124   
00125 
00126   int ci[NBits][NBits];
00127   int v[NBits+MaxDegree+1];
00128   int r;
00129   unsigned int i_dim;
00130 
00131   for(i_dim=0; i_dim<dimension; i_dim++) {
00132 
00133     const int poly_index = i_dim + 1;
00134     int j, k;
00135 
00136     
00137 
00138 
00139 
00140     int u = 0;
00141 
00142     
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150     int pb[MaxDegree+1];
00151     int px[MaxDegree+1];
00152     int px_degree = _polyDegree[poly_index];
00153     int pb_degree = 0;
00154 
00155     for(k=0; k<=px_degree; k++) {
00156       px[k] = _primitivePoly[poly_index][k];
00157       pb[k] = 0;
00158     }
00159     pb[0] = 1;
00160 
00161     for(j=0; j<NBits; j++) {
00162 
00163       
00164 
00165 
00166       if(u == 0) calculateV(px, px_degree, pb, &pb_degree, v, NBits+MaxDegree);
00167 
00168       
00169 
00170 
00171 
00172 
00173 
00174       for(r=0; r<NBits; r++) {
00175         ci[r][j] = v[r+u];
00176       }
00177 
00178       
00179       ++u;
00180       if(u == px_degree) u = 0;
00181     }
00182 
00183     
00184 
00185 
00186 
00187     for(r=0; r<NBits; r++) {
00188       int term = 0;
00189       for(j=0; j<NBits; j++) {
00190         term = 2*term + ci[r][j];
00191       }
00192       _cj[r][i_dim] = term;
00193     }
00194 
00195   }
00196 }
00197 
00198 
00199 
00200 void RooQuasiRandomGenerator::calculateV(const int px[], int px_degree,
00201                                          int pb[], int * pb_degree, int v[], int maxv) 
00202 {
00203   
00204   
00205   const int nonzero_element = 1;    
00206   const int arbitrary_element = 1;  
00207 
00208   
00209 
00210 
00211 
00212   int ph[MaxDegree+1];
00213   
00214   int bigm = *pb_degree;      
00215   int m;                      
00216   int r, k, kj;
00217 
00218   for(k=0; k<=MaxDegree; k++) {
00219     ph[k] = pb[k];
00220   }
00221 
00222   
00223 
00224 
00225 
00226    polyMultiply(px, px_degree, pb, *pb_degree, pb, pb_degree);
00227    m = *pb_degree;
00228 
00229   
00230 
00231 
00232 
00233 
00234   
00235 
00236 
00237 
00238 
00239 
00240   kj = bigm;
00241 
00242   
00243 
00244 
00245   for(r=0; r<kj; r++) {
00246     v[r] = 0;
00247   }
00248   v[kj] = 1;
00249 
00250 
00251   if(kj >= bigm) {
00252     for(r=kj+1; r<m; r++) {
00253       v[r] = arbitrary_element;
00254     }
00255   }
00256   else {
00257     
00258 
00259     int term = sub(0, ph[kj]);
00260 
00261     for(r=kj+1; r<bigm; r++) {
00262       v[r] = arbitrary_element;
00263 
00264       
00265 
00266 
00267       term = sub(term, mul(ph[r], v[r]));
00268     }
00269 
00270     
00271     v[bigm] = add(nonzero_element, term);
00272 
00273     for(r=bigm+1; r<m; r++) {
00274       v[r] = arbitrary_element;
00275     }
00276   }
00277 
00278   
00279 
00280 
00281   for(r=0; r<=maxv-m; r++) {
00282     int term = 0;
00283     for(k=0; k<m; k++) {
00284       term = sub(term, mul(pb[k], v[r+k]));
00285     }
00286     v[r+m] = term;
00287   }
00288 }
00289 
00290 
00291 
00292 void RooQuasiRandomGenerator::polyMultiply(const int pa[], int pa_degree, const int pb[],
00293                                            int pb_degree, int pc[], int  * pc_degree) 
00294 {
00295   
00296 
00297   int j, k;
00298   int pt[MaxDegree+1];
00299   int pt_degree = pa_degree + pb_degree;
00300 
00301   for(k=0; k<=pt_degree; k++) {
00302     int term = 0;
00303     for(j=0; j<=k; j++) {
00304       const int conv_term = mul(pa[k-j], pb[j]);
00305       term = add(term, conv_term);
00306     }
00307     pt[k] = term;
00308   }
00309 
00310   for(k=0; k<=pt_degree; k++) {
00311     pc[k] = pt[k];
00312   }
00313   for(k=pt_degree+1; k<=MaxDegree; k++) {
00314     pc[k] = 0;
00315   }
00316 
00317   *pc_degree = pt_degree;
00318 }
00319 
00320 
00321 
00322 Int_t RooQuasiRandomGenerator::_cj[RooQuasiRandomGenerator::NBits]
00323 [RooQuasiRandomGenerator::MaxDimension];
00324 
00325 
00326 
00327 
00328 const Int_t RooQuasiRandomGenerator::_primitivePoly[RooQuasiRandomGenerator::MaxDimension+1]
00329 
00330 
00331 [RooQuasiRandomGenerator::MaxPrimitiveDegree+1] =
00332 {
00333   { 1, 0, 0, 0, 0, 0 },  
00334   { 0, 1, 0, 0, 0, 0 },  
00335   { 1, 1, 0, 0, 0, 0 },  
00336   { 1, 1, 1, 0, 0, 0 },  
00337   { 1, 1, 0, 1, 0, 0 },  
00338   { 1, 0, 1, 1, 0, 0 },  
00339   { 1, 1, 0, 0, 1, 0 },  
00340   { 1, 0, 0, 1, 1, 0 },  
00341   { 1, 1, 1, 1, 1, 0 },  
00342   { 1, 0, 1, 0, 0, 1 },  
00343   { 1, 0, 0, 1, 0, 1 },  
00344   { 1, 1, 1, 1, 0, 1 },  
00345   { 1, 1, 1, 0, 1, 1 }   
00346 };
00347 
00348 
00349 
00350 
00351 const Int_t RooQuasiRandomGenerator::_polyDegree[RooQuasiRandomGenerator::MaxDimension+1] =
00352 {
00353   0, 1, 1, 2, 3, 3, 4, 4, 4, 5, 5, 5, 5
00354 };
00355 
00356 Bool_t RooQuasiRandomGenerator::_coefsCalculated= kFALSE;