Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooQuasiRandomGenerator.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16
17/**
18\file RooQuasiRandomGenerator.cxx
19\class RooQuasiRandomGenerator
20\ingroup Roofitcore
21
22This class generates the quasi-random (aka "low discrepancy")
23sequence for dimensions up to 12 using the Niederreiter base 2
24algorithm described in Bratley, Fox, Niederreiter, ACM Trans.
25Model. Comp. Sim. 2, 195 (1992). This implementation was adapted
26from the 0.9 beta release of the GNU scientific library.
27Quasi-random number sequences are useful for improving the
28convergence of a Monte Carlo integration.
29**/
30
32#include "RooMsgService.h"
33
34#include <iostream>
35#include <cassert>
36
37using std::endl;
38
39
40
41////////////////////////////////////////////////////////////////////////////////
42/// Perform one-time initialization of our static coefficient array if necessary
43/// and initialize our workspace.
44
46{
47 if(!_coefsCalculated) {
49 _coefsCalculated= true;
50 }
51 // allocate workspace memory
53 reset();
54}
55
56
57////////////////////////////////////////////////////////////////////////////////
58/// Destructor
59
64
65
66////////////////////////////////////////////////////////////////////////////////
67/// Reset the workspace to its initial state.
68
70{
72 for(Int_t dim= 0; dim < MaxDimension; dim++) _nextq[dim]= 0;
73}
74
75
76////////////////////////////////////////////////////////////////////////////////
77/// Generate the next number in the sequence for the specified dimension.
78/// The maximum dimension supported is 12.
79
80bool RooQuasiRandomGenerator::generate(UInt_t dimension, double vector[])
81{
82 /* Load the result from the saved state. */
83 static const double recip = 1.0/(double)(1U << NBits); /* 2^(-nbits) */
84
85 UInt_t dim;
86 for(dim=0; dim < dimension; dim++) {
87 vector[dim] = _nextq[dim] * recip;
88 }
89
90 /* Find the position of the least-significant zero in sequence_count.
91 * This is the bit that changes in the Gray-code representation as
92 * the count is advanced.
93 */
94 Int_t r(0);
96 while(true) {
97 if((c % 2) == 1) {
98 ++r;
99 c /= 2;
100 }
101 else break;
102 }
103 if(r >= NBits) {
104 oocoutE(nullptr,Integration) << "RooQuasiRandomGenerator::generate: internal error!" << std::endl;
105 return false;
106 }
107
108 /* Calculate the next state. */
109 for(dim=0; dim<dimension; dim++) {
110 _nextq[dim] ^= _cj[r][dim];
111 }
113
114 return true;
115}
116
117
118////////////////////////////////////////////////////////////////////////////////
119/// Calculate the coefficients for the given number of dimensions
120
122{
123 int ci[NBits][NBits];
124 int v[NBits+MaxDegree+1];
125 int r;
126 unsigned int i_dim;
127
128 for(i_dim=0; i_dim<dimension; i_dim++) {
129
130 const int poly_index = i_dim + 1;
131 int j;
132 int k;
133
134 /* Niederreiter (page 56, after equation (7), defines two
135 * variables Q and U. We do not need Q explicitly, but we
136 * do need U.
137 */
138 int u = 0;
139
140 /* For each dimension, we need to calculate powers of an
141 * appropriate irreducible polynomial, see Niederreiter
142 * page 65, just below equation (19).
143 * Copy the appropriate irreducible polynomial into PX,
144 * and its degree into E. Set polynomial B = PX ** 0 = 1.
145 * M is the degree of B. Subsequently B will hold higher
146 * powers of PX.
147 */
148 int pb[MaxDegree+1];
149 int px[MaxDegree+1];
151 int pb_degree = 0;
152
153 for(k=0; k<=px_degree; k++) {
154 px[k] = _primitivePoly[poly_index][k];
155 pb[k] = 0;
156 }
157 pb[0] = 1;
158
159 for(j=0; j<NBits; j++) {
160
161 /* If U = 0, we need to set B to the next power of PX
162 * and recalculate V.
163 */
164 if(u == 0) calculateV(px, px_degree, pb, &pb_degree, v, NBits+MaxDegree);
165
166 /* Now C is obtained from V. Niederreiter
167 * obtains A from V (page 65, near the bottom), and then gets
168 * C from A (page 56, equation (7)). However this can be done
169 * in one step. Here CI(J,R) corresponds to
170 * Niederreiter's C(I,J,R).
171 */
172 for(r=0; r<NBits; r++) {
173 ci[r][j] = v[r+u];
174 }
175
176 /* Advance Niederreiter's state variables. */
177 ++u;
178 if(u == px_degree) u = 0;
179 }
180
181 /* The array CI now holds the values of C(I,J,R) for this value
182 * of I. We pack them into array CJ so that CJ(I,R) holds all
183 * the values of C(I,J,R) for J from 1 to NBITS.
184 */
185 for(r=0; r<NBits; r++) {
186 int term = 0;
187 for(j=0; j<NBits; j++) {
188 term = 2*term + ci[r][j];
189 }
190 _cj[r][i_dim] = term;
191 }
192
193 }
194}
195
196
197////////////////////////////////////////////////////////////////////////////////
198/// Internal function
199
201 int pb[], int * pb_degree, int v[], int maxv)
202{
203 const int nonzero_element = 1; /* nonzero element of Z_2 */
204 const int arbitrary_element = 1; /* arbitrary element of Z_2 */
205
206 /* The polynomial ph is px**(J-1), which is the value of B on arrival.
207 * In section 3.3, the values of Hi are defined with a minus sign:
208 * don't forget this if you use them later !
209 */
210 int ph[MaxDegree+1];
211 /* int ph_degree = *pb_degree; */
212 int bigm = *pb_degree; /* m from section 3.3 */
213 int m; /* m from section 2.3 */
214 int r;
215 int k;
216 int kj;
217
218 for(k=0; k<=MaxDegree; k++) {
219 ph[k] = pb[k];
220 }
221
222 /* Now multiply B by PX so B becomes PX**J.
223 * In section 2.3, the values of Bi are defined with a minus sign :
224 * don't forget this if you use them later !
225 */
227 m = *pb_degree;
228
229 /* Now choose a value of Kj as defined in section 3.3.
230 * We must have 0 <= Kj < E*J = M.
231 * The limit condition on Kj does not seem very relevant
232 * in this program.
233 */
234 /* Quoting from BFN: "Our program currently sets each K_q
235 * equal to eq. This has the effect of setting all unrestricted
236 * values of v to 1."
237 * Actually, it sets them to the arbitrary chosen value.
238 * Whatever.
239 */
240 kj = bigm;
241
242 /* Now choose values of V in accordance with
243 * the conditions in section 3.3.
244 */
245 for(r=0; r<kj; r++) {
246 v[r] = 0;
247 }
248 v[kj] = 1;
249
250
251 if(kj >= bigm) {
252 for(r=kj+1; r<m; r++) {
254 }
255 }
256 else {
257 /* This block is never reached. */
258
259 int term = sub(0, ph[kj]);
260
261 for(r=kj+1; r<bigm; r++) {
263
264 /* Check the condition of section 3.3,
265 * remembering that the H's have the opposite sign. [????????]
266 */
267 term = sub(term, mul(ph[r], v[r]));
268 }
269
270 /* Now v[bigm] != term. */
272
273 for(r=bigm+1; r<m; r++) {
275 }
276 }
277
278 /* Calculate the remaining V's using the recursion of section 2.3,
279 * remembering that the B's have the opposite sign.
280 */
281 for(r=0; r<=maxv-m; r++) {
282 int term = 0;
283 for(k=0; k<m; k++) {
284 term = sub(term, mul(pb[k], v[r+k]));
285 }
286 v[r+m] = term;
287 }
288}
289
290
291////////////////////////////////////////////////////////////////////////////////
292/// Internal function
293
294void RooQuasiRandomGenerator::polyMultiply(const int pa[], int pa_degree, const int pb[],
295 int pb_degree, int pc[], int * pc_degree)
296{
297 int j;
298 int k;
299 int pt[MaxDegree+1];
301
302 for(k=0; k<=pt_degree; k++) {
303 int term = 0;
304 for(j=0; j<=k; j++) {
305 const int conv_term = mul(pa[k-j], pb[j]);
307 }
308 pt[k] = term;
309 }
310
311 for(k=0; k<=pt_degree; k++) {
312 pc[k] = pt[k];
313 }
314 for(k=pt_degree+1; k<=MaxDegree; k++) {
315 pc[k] = 0;
316 }
317
319}
320
321
322////////////////////////////////////////////////////////////////////////////////
323
326
327/* primitive polynomials in binary encoding */
328
329////////////////////////////////////////////////////////////////////////////////
330
332
333////////////////////////////////////////////////////////////////////////////////
334
336{
337 { 1, 0, 0, 0, 0, 0 }, /* 1 */
338 { 0, 1, 0, 0, 0, 0 }, /* x */
339 { 1, 1, 0, 0, 0, 0 }, /* 1 + x */
340 { 1, 1, 1, 0, 0, 0 }, /* 1 + x + x^2 */
341 { 1, 1, 0, 1, 0, 0 }, /* 1 + x + x^3 */
342 { 1, 0, 1, 1, 0, 0 }, /* 1 + x^2 + x^3 */
343 { 1, 1, 0, 0, 1, 0 }, /* 1 + x + x^4 */
344 { 1, 0, 0, 1, 1, 0 }, /* 1 + x^3 + x^4 */
345 { 1, 1, 1, 1, 1, 0 }, /* 1 + x + x^2 + x^3 + x^4 */
346 { 1, 0, 1, 0, 0, 1 }, /* 1 + x^2 + x^5 */
347 { 1, 0, 0, 1, 0, 1 }, /* 1 + x^3 + x^5 */
348 { 1, 1, 1, 1, 0, 1 }, /* 1 + x + x^2 + x^3 + x^5 */
349 { 1, 1, 1, 0, 1, 1 } /* 1 + x + x^2 + x^4 + x^5 */
350};
351
352/* degrees of primitive polynomials */
353
354////////////////////////////////////////////////////////////////////////////////
355
357{
358 0, 1, 1, 2, 3, 3, 4, 4, 4, 5, 5, 5, 5
359};
360
#define c(i)
Definition RSha256.hxx:101
#define oocoutE(o, a)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
void polyMultiply(const int pa[], int pa_degree, const int pb[], int pb_degree, int pc[], int *pc_degree)
Internal function.
RooQuasiRandomGenerator()
Perform one-time initialization of our static coefficient array if necessary and initialize our works...
void calculateV(const int px[], int px_degree, int pb[], int *pb_degree, int v[], int maxv)
Internal function.
Int_t mul(Int_t x, Int_t y) const
void reset()
Reset the workspace to its initial state.
void calculateCoefs(UInt_t dimension)
Calculate the coefficients for the given number of dimensions.
static Int_t _cj[NBits][MaxDimension]
virtual ~RooQuasiRandomGenerator()
Destructor.
static const Int_t _polyDegree[MaxDimension+1]
static const Int_t _primitivePoly[MaxDimension+1][MaxPrimitiveDegree+1]
bool generate(UInt_t dimension, double vector[])
Generate the next number in the sequence for the specified dimension.
Int_t add(Int_t x, Int_t y) const
Int_t sub(Int_t x, Int_t y) const
TPaveText * pt
TMarker m
Definition textangle.C:8