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;