twister.h
Go to the documentation of this file.
1 /* $Id$ */
2 // Author: John Wu <John.Wu at ACM.org>
3 // Copyright (c) 2000-2016 the Regents of the University of California
4 #ifndef IBIS_TWISTER_H
5 #define IBIS_TWISTER_H
6 
19 #include <time.h> // time_t time
20 #include <limits.h> // DBL_MIN, ULONG_MAX
21 #include <float.h> // DBL_MIN
22 #include <math.h> // sqrt, log, exp, pow
23 
24 #include <vector> // std::vector<double> used by discrateZip1
25 
26 namespace ibis {
27  class uniformRandomNumber; // the abstract base class
28  class MersenneTwister; // concrete uniform random number generator
29  class discretePoisson; // discrete Poisson
30  class discretePoisson1; // the spcial case for exp(-x)
31  class discreteZipf; // discrete Zipf 1/x^a (a > 0)
32  class discreteZipf1; // 1/x
33  class discreteZipf2; // 1/x^2
34  class randomGaussian; // continuous Gaussian
35  class randomPoisson; // continuous Posson
36  class randomZipf; // continuous Zipf
37 };
38 
41 public:
42  virtual double operator()() = 0;
43 };
44 
48 public:
54  unsigned seed;
55 #if defined(FASTBIT_USE_DEV_URANDOM)
56  FILE* fptr = fopen("/dev/urandom", "rb");
57  if (fptr != 0) {
58  int ierr = fread(&seed, sizeof(seed), 1, fptr);
59  if (ierr < 1 || seed == 0)
60  seed = time(0);
61  }
62  else {
63 #if defined(CLOCK_MONOTONIC) && !defined(__CYGWIN__)
64  struct timespec tb;
65  if (0 == clock_gettime(CLOCK_MONOTONIC, &tb))
66  seed = (tb.tv_sec ^ tb.tv_nsec);
67  else
68  seed = time(0);
69 #else
70  seed = time(0);
71 #endif
72  }
73 #else
74 #if defined(CLOCK_MONOTONIC) && !defined(__CYGWIN__)
75  struct timespec tb;
76  if (0 == clock_gettime(CLOCK_MONOTONIC, &tb))
77  seed = (tb.tv_sec ^ tb.tv_nsec);
78  else
79  seed = time(0);
80 #else
81  seed = time(0);
82 #endif
83 #endif
84  setSeed(seed);
85  }
87  explicit MersenneTwister(unsigned seed) {setSeed(seed);}
88 
90  virtual double operator()() {return nextDouble();}
92  int nextInt() {return next();}
93  long nextLong() {return next();}
94  float nextFloat() {return 2.3283064365386962890625e-10*next();}
95  double nextDouble() {return 2.3283064365386962890625e-10*next();}
97  unsigned next(unsigned r) {return static_cast<unsigned>(r*nextDouble());}
98 
100  void setSeed(unsigned seed) {
101  for (int i=0; i<624; i++) {
102  mt[i] = seed & 0xffff0000;
103  seed = 69069 * seed + 1;
104  mt[i] |= (seed & 0xffff0000) >> 16;
105  seed = 69069 * seed + 1;
106  }
107  mti = 624;
108  }
109 
111  unsigned next() {
112  unsigned y;
113  if (mti >= 624) { /* generate 624 words at one time */
114  static unsigned mag01[2]={0x0, 0x9908b0df};
115  int kk;
116 
117  for (kk=0; kk<227; kk++) {
118  y = (mt[kk]&0x80000000)|(mt[kk+1]&0x7fffffff);
119  mt[kk] = mt[kk+397] ^ (y >> 1) ^ mag01[y & 0x1];
120  }
121  for (; kk<623; kk++) {
122  y = (mt[kk]&0x80000000)|(mt[kk+1]&0x7fffffff);
123  mt[kk] = mt[kk-227] ^ (y >> 1) ^ mag01[y & 0x1];
124  }
125  y = (mt[623]&0x80000000)|(mt[0]&0x7fffffff);
126  mt[623] = mt[396] ^ (y >> 1) ^ mag01[y & 0x1];
127  mti = 0;
128  }
129 
130  y = mt[mti++];
131  y ^= (y >> 11);
132  y ^= (y << 7) & 0x9d2c5680;
133  y ^= (y << 15) & 0xefc60000;
134  y ^= (y >> 18);
135 
136  return y;
137  }
138 
139 private:
140  // all data members are private
141  int mti;
142  unsigned mt[624]; /* the array for the state vector */
143 }; // class MersenneTwister
144 
145 // ********** the following random number generators need a uniformation
146 // ********** random number generator as the input
147 
150 public:
152  randomPoisson(uniformRandomNumber& ur) : urand(ur) {}
153  double operator()() {return next();}
154  double next() {return -log(urand());}
155 
156 private:
157  uniformRandomNumber& urand;
158 }; // ibis::randomPoisson
159 
164 public:
167  : urand(ur), has_extra(false), extra(0.0) {}
169  double operator()() {return next();}
171  double next() {
172  if (has_extra) { /* has extra value from the previous run */
173  has_extra = false;
174  return extra;
175  }
176  else { /* Box-Mueller transformation */
177  double v1, v2, r, fac;
178  do {
179  v1 = 2.0 * urand() - 1.0;
180  v2 = 2.0 * urand() - 1.0;
181  r = v1 * v1 + v2 * v2;
182  } while (r >= 1.0 || r <= 0.0);
183  fac = sqrt((-2.0 * log(r))/r);
184  has_extra = false;
185  extra = v2 * fac;
186  v1 *= fac;
187  return v1;
188  }
189  }
190 
191 private:
192  uniformRandomNumber& urand;
193  bool has_extra;
194  double extra;
195 }; // ibis::randomGaussian
196 
200 public:
202  randomZipf(uniformRandomNumber& ur, double a=1) : urand(ur), alpha(a-1) {}
204  double operator()() {return next();}
206  double next() {
207  if (alpha > 0.0)
208  return (exp(-log(1 - urand())/(alpha)) - 1);
209  else
210  return (1.0 / (1.0 - urand()) - 1.0);
211  }
212 
213 private:
214  uniformRandomNumber& urand;
215  const double alpha; // Zipf exponent - 1
216 }; // ibis::randomZipf
217 
221 public:
223  const double lam=1.0, long m=0)
224  : min0(m), lambda(lam), urand(ur) {init();}
225 
226  long operator()() {return next();}
227  long next() {
228  long k;
229  double u, x;
230  while (true) {
231  u = ym * (urand)();
232  x = - lambda * log(u * laminv);
233  k = static_cast<long>(x + 0.5);
234  if (k <= k0 && k-x <= xm)
235  return k;
236  else if (u >= -exp(laminv*k+laminv2)*lambda-exp(laminv*k))
237  return k;
238  }
239  } // next integer random number
240 
241 private:
242  // private member variables
243  long min0, k0;
244  double lambda, laminv, laminv2, xm, ym;
245  uniformRandomNumber& urand;
246 
247  // private functions
248  void init() { // check input parameters and initialize three constants
249  if (! (lambda > DBL_MIN))
250  lambda = 1.0;
251  laminv = -1.0 / lambda;
252  laminv2 = 0.5*laminv;
253  k0 = static_cast<long>(1.0+min0+1.0/(1.0-exp(laminv)));
254  ym = -exp((min0+0.5)*laminv)*lambda - exp(min0*laminv);
255  xm = min0 - log(ym*laminv);
256  }
257 }; // class discretePoisson
258 
261 public:
263  : urand(ur) {init();}
264 
265  long operator()() {return next();}
266  long next() {
267  long k;
268  double u, x;
269  while (true) {
270  u = ym * (urand)();
271  x = - log(-u);
272  k = static_cast<long>(x + 0.5);
273  if (k <= k0 && k-x <= xm)
274  return k;
275  else if (u >= -exp(-static_cast<double>(k)-0.5) -
276  exp(-static_cast<double>(k)))
277  return k;
278  }
279  } // next integer random number
280 
281 private:
282  // private member variables
283  double xm, ym;
284  long k0;
285  uniformRandomNumber& urand;
286 
287  // private functions
288  void init() { // check input parameters and initialize three constants
289  k0 = static_cast<long>(1.0+1.0/(1.0-exp(-1.0)));
290  ym = - exp(-0.5) - 1.0;
291  xm = - log(-ym);
292  }
293 }; // class discretePoisson1
294 
300 public:
301  discreteZipf(ibis::uniformRandomNumber& ur, double a=2.0,
302  unsigned long imax = ULONG_MAX)
303  : urand(ur), max0(imax), alpha(a) {init();}
304 
306  unsigned long operator()() {return next();}
307  unsigned long next() {
308  if (alpha > 1.0) { // rejection-inversion
309  while (true) {
310  double ur = (urand)();
311  ur = hxm + ur * hx0;
312  double x = Hinv(ur);
313  unsigned long k = static_cast<unsigned long>(0.5+x);
314  if (k - x <= ss)
315  return k;
316  else if (ur >= H(0.5+k) - exp(-log(k+1.0)*alpha))
317  return k;
318  }
319  }
320  else { // simple rejection
321  unsigned long k = ((long) (urand() * max0)) % max0;
322  double freq = pow((1.0+k), -alpha);
323  while (urand() >= freq) {
324  k = ((long) (urand() * max0)) % max0;
325  freq = pow((1.0+k), -alpha);
326  }
327  return k;
328  }
329  } // next
330 
331 private:
332  // private member variables
333  uniformRandomNumber& urand;
334  long unsigned max0;
335  double alpha, alpha1, alphainv, hx0, hxm, ss;
336 
337  // private member function
338  double H(double x) {return (exp(alpha1*log(1.0+x)) * alphainv);}
339  double Hinv(double x) {return exp(alphainv*log(alpha1*x)) - 1.0;}
340  void init() {
341  // enforce the condition that alpha >= 0 and max0 > 1
342  if (max0 <= 1)
343  max0 = 100;
344  if (! (alpha >= 0.0))
345  alpha = 1.0;
346  if (alpha > 1.0) {
347  // the rejection-inversion algorithm of W. Hormann and
348  // G. Derflinger
349  alpha1 = 1.0 - alpha;
350  alphainv = 1.0 / alpha1;
351  hxm = H(max0 + 0.5);
352  hx0 = H(0.5) - 1.0 - hxm;
353  ss = 1 - Hinv(H(1.5)-exp(-alpha*log(2.0)));
354  }
355  else { // use a simple rejection scheme
356  alpha1 = 0.0;
357  alphainv = 0.0;
358  hxm = 0.0;
359  hx0 = 0.0;
360  ss = 0.0;
361  }
362  }
363 }; // Zipf distribution
364 
368 public:
370  unsigned long imax = ULONG_MAX) :
371  max0(imax), urand(ur) {init();}
372 
374  unsigned long operator()() {return next();}
375  unsigned long next() {
376  while (true) {
377  double ur = (urand)();
378  ur = hxm + ur * hx0;
379  double x = Hinv(ur);
380  unsigned long k = static_cast<unsigned long>(0.5+x);
381  if (k - x <= ss)
382  return k;
383  else if (ur >= H(0.5+k) - 1.0/((1.0+x)*(1.0+x)))
384  return k;
385  }
386  } // next
387 
388 private:
389  // private member variables
390  double hx0, hxm, ss;
391  long unsigned max0;
392  uniformRandomNumber& urand;
393 
394  // private member function
395  double H(double x) {return -1.0 / (1.0 + x);}
396  double Hinv(double x) {return (- 1.0 / x) - 1.0;}
397  void init() {
398  hxm = H(max0+0.5);
399  hx0 = - 5.0/3.0 - hxm;
400  ss = 1 - Hinv(H(1.5)-0.25);
401  }
402 }; // Zipf2 distribution
403 
409 public:
410  discreteZipf1(ibis::uniformRandomNumber& ur, unsigned long imax = 100) :
411  card(imax+1), cpd(imax+1), urand(ur) {init();}
412 
414  unsigned long operator()() {return next();}
415  unsigned long next() {
416  double ur = (urand)();
417  if (ur <= cpd[0]) return 0;
418  // return the minimal i such that cdf[i] >= ur
419  unsigned long i, j, k;
420  i = 0;
421  j = card-1;
422  k = (i + j) / 2;
423  while (i < k) {
424  if (cpd[k] > ur)
425  j = k;
426  else if (cpd[k] < ur)
427  i = k;
428  else
429  return k;
430  k = (i + j) / 2;
431  }
432  if (cpd[i] >= ur)
433  return i;
434  else
435  return j;
436  } // next
437 
438 private:
439  // private member variables
440  const unsigned long card;
441  std::vector<double> cpd; // cumulative probability distribution
442  uniformRandomNumber& urand;
443 
444  // private member function
445  void init() { // generates the cpd
446  const unsigned n = cpd.size();
447  if (n < 2 || n > 1024*1024 || card != n)
448  throw "imax must be in [2, 1000000]";
449 
450  cpd[0] = 1.0;
451  for (unsigned i = 1; i < n; ++i)
452  cpd[i] = cpd[i-1] + 1.0 / (1.0 + i);
453  double ss = 1.0 / cpd.back();
454  for (unsigned i = 0; i < n; ++i)
455  cpd[i] *= ss;
456  } // init
457 }; // Zipf1 distribution
458 #endif // IBIS_TWISTER_H
Continuous Gaussian distribution.
Definition: twister.h:163
Mersenne Twister.
Definition: twister.h:47
Specialized version of the Poisson distribution exp(-x).
Definition: twister.h:260
double operator()()
Operator that returns the next random numbers.
Definition: twister.h:169
A specialized version of the Zipf distribution f(x) = 1/(1+x)^2.
Definition: twister.h:367
MersenneTwister()
Constructor.
Definition: twister.h:53
randomPoisson(uniformRandomNumber &ur)
Constructor. Must be supplied with a uniform random number generator.
Definition: twister.h:152
MersenneTwister(unsigned seed)
Constructor. Uses a user specified integer as seed.
Definition: twister.h:87
The current implementation of FastBit is code named IBIS; most data structures and functions are in t...
Definition: bord.h:16
Continuous Poisson distribution.
Definition: twister.h:149
randomZipf(uniformRandomNumber &ur, double a=1)
Constructor. Must be supplied with a uniform random number generator.
Definition: twister.h:202
unsigned long operator()()
Return a discrete random number in the range of [0, imax].
Definition: twister.h:306
Continuous Zipf distribution.
Definition: twister.h:199
randomGaussian(uniformRandomNumber &ur)
Constructor. Must be supplied with a uniform random number generator.
Definition: twister.h:166
Discrete random number with Poisson distribution exp(-x/lambda).
Definition: twister.h:220
unsigned next(unsigned r)
Return integers in the range of [0, r)
Definition: twister.h:97
unsigned next()
Generate the next random integer in the range of 0-(2^{32}-1).
Definition: twister.h:111
double operator()()
Operator that returns the next random number.
Definition: twister.h:204
unsigned long operator()()
Return a discrete random number in the range of [0, imax].
Definition: twister.h:374
int nextInt()
Next integer.
Definition: twister.h:92
virtual double operator()()
Return a floating-point value in the range of [0, 1).
Definition: twister.h:90
double next()
Next random number.
Definition: twister.h:206
double next()
Next random number.
Definition: twister.h:171
Discrete Zipf distribution.
Definition: twister.h:299
void setSeed(unsigned seed)
Initializing the array with a seed.
Definition: twister.h:100
unsigned long operator()()
Return a discrete random number in the range of [0, imax].
Definition: twister.h:414
A functor to generate uniform random number in the range [0, 1).
Definition: twister.h:40
A specialized case of the Zipf distribution f(x) = 1/(1+x).
Definition: twister.h:408

Make It A Bit Faster
Contact us
Disclaimers
FastBit source code
FastBit mailing list archive