ITK  4.2.0
Insight Segmentation and Registration Toolkit
itkMersenneTwisterRandomVariateGenerator.h
Go to the documentation of this file.
1 /*=========================================================================
2  *
3  * Copyright Insight Software Consortium
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef __itkMersenneTwisterRandomVariateGenerator_h
19 #define __itkMersenneTwisterRandomVariateGenerator_h
20 
21 #include "itkMacro.h"
22 #include "itkObjectFactory.h"
24 #include "itkIntTypes.h"
25 #include "vcl_ctime.h"
26 #include "vnl/vnl_math.h"
27 #include <limits.h>
28 
29 namespace itk
30 {
31 namespace Statistics
32 {
107 {
108 public:
109 
115 
117 
121 
125  static Pointer New();
126 
132  static Pointer GetInstance();
133 
135  itkStaticConstMacro(StateVectorLength, IntegerType, 624);
136 
138  void Initialize(const IntegerType oneSeed);
139 
140  /* Initialize with vcl_clock time */
141  void Initialize();
142 
144  double GetVariateWithClosedRange();
145 
147  double GetVariateWithClosedRange(const double & n);
148 
150  double GetVariateWithOpenUpperRange();
151 
153  double GetVariateWithOpenUpperRange(const double & n);
154 
156  double GetVariateWithOpenRange();
157 
159  double GetVariateWithOpenRange(const double & n);
160 
162  IntegerType GetIntegerVariate();
163 
165  IntegerType GetIntegerVariate(const IntegerType & n);
166 
169  double Get53BitVariate();
170 
171  /* Access to a normal random number distribution
172  * TODO: Compare with vnl_sample_normal */
173  double GetNormalVariate(const double & mean = 0.0,
174  const double & variance = 1.0);
175 
176  /* Access to a uniform random number distribution in the range [a, b)
177  * TODO: Compare with vnl_sample_uniform */
178  double GetUniformVariate(const double & a, const double & b);
179 
185  virtual double GetVariate();
186 
188  double operator()();
189 
190  // Re-seeding functions with same behavior as initializers
191  inline void SetSeed(const IntegerType oneSeed);
192  // inline void SetSeed(IntegerType *bigSeed, const IntegerType seedLength = StateVectorLength);
193  inline void SetSeed();
194  // Return the current seed
195  IntegerType GetSeed() { return this->m_Seed; };
196 
197  /*
198  // Saving and loading generator state
199  void save( IntegerType* saveArray ) const; // to array of size SAVE
200  void load( IntegerType *const loadArray ); // from such array
201  */
202 protected:
205  virtual void PrintSelf(std::ostream & os, Indent indent) const
206  {
207  Superclass::PrintSelf(os, indent);
208 
209  // Print state vector contents
210  os << indent << "State vector: " << state << std::endl;
211  os << indent;
212  register const IntegerType *s = state;
213  register int i = StateVectorLength;
214  for (; i--; os << *s++ << "\t" ) {}
215  os << std::endl;
216 
217  //Print next value to be gotten from state
218  os << indent << "Next value to be gotten from state: " << pNext << std::endl;
219 
220  //Number of values left before reload
221  os << indent << "Values left before next reload: " << left << std::endl;
222  }
223 
224  // period parameter
225  itkStaticConstMacro (M, unsigned int, 397);
226 
227  IntegerType state[StateVectorLength]; // internal state
228  IntegerType *pNext; // next value to get from state
229  int left; // number of values left before reload
230  // needed
231  IntegerType m_Seed; // Seed value
232 
233  /* Reload array with N new values */
234  void reload();
235 
236  IntegerType hiBit(const IntegerType & u) const { return u & 0x80000000UL; }
237  IntegerType loBit(const IntegerType & u) const { return u & 0x00000001UL; }
238  IntegerType loBits(const IntegerType & u) const { return u & 0x7fffffffUL; }
239  IntegerType mixBits(const IntegerType & u, const IntegerType & v) const
240  {
241  return hiBit(u) | loBits(v);
242  }
243 
244  IntegerType twist(const IntegerType & m, const IntegerType & s0, const IntegerType & s1) const
245  {
246  return m ^ ( mixBits(s0, s1) >> 1 ) ^ ( -loBit(s1) & 0x9908b0dfUL );
247  }
248 
249  static IntegerType hash(vcl_time_t t, vcl_clock_t c);
250 
252 }; // end of class
253 
254 // Declare inlined functions.... (must be declared in the header)
255 
258 {
259  // Get a IntegerType from t and c
260  // Better than IntegerType(x) in case x is floating point in [0,1]
261  // Based on code by Lawrence Kirby: fred at genesis dot demon dot co dot uk
262 
263  static IntegerType differ = 0; // guarantee time-based seeds will change
264 
265  IntegerType h1 = 0;
266  unsigned char *p = (unsigned char *)&t;
267 
268  const unsigned int sizeOfT = static_cast< unsigned int >( sizeof(t) );
269  for ( unsigned int i = 0; i < sizeOfT; ++i )
270  {
271  h1 *= UCHAR_MAX + 2U;
272  h1 += p[i];
273  }
274  IntegerType h2 = 0;
275  p = (unsigned char *)&c;
276 
277  const unsigned int sizeOfC = static_cast< unsigned int >( sizeof(c) );
278  for ( unsigned int j = 0; j < sizeOfC; ++j )
279  {
280  h2 *= UCHAR_MAX + 2U;
281  h2 += p[j];
282  }
283  return ( h1 + differ++ ) ^ h2;
284 }
285 
286 inline void
288 {
289  this->m_Seed = seed;
290  // Initialize generator state with seed
291  // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
292  // In previous versions, most significant bits (MSBs) of the seed affect
293  // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
294  register IntegerType *s = state;
295  register IntegerType *r = state;
296  register IntegerType i = 1;
297 
298  *s++ = seed & 0xffffffffUL;
300  {
301  *s++ = ( 1812433253UL * ( *r ^ ( *r >> 30 ) ) + i ) & 0xffffffffUL;
302  r++;
303  }
304 }
305 
306 inline void
308 {
309  // Generate N new values in state
310  // Made clearer and faster by Matthew Bellew
311  // matthew dot bellew at home dot com
312 
313  // get rid of VS warning
314  register int index = static_cast< int >(
316 
317  register IntegerType *p = state;
318  register int i;
319 
321  {
322  *p = twist(p[M], p[0], p[1]);
323  }
324  for ( i = M; --i; ++p )
325  {
326  *p = twist(p[index], p[0], p[1]);
327  }
328  *p = twist(p[index], p[0], state[0]);
329 
331 }
332 
333  /*
334 #define SVL 624
335 inline void
336 MersenneTwisterRandomVariateGenerator::SetSeed(
337  IntegerType *const bigSeed, const IntegerType seedLength)
338 {
339  // Seed the generator with an array of IntegerType's
340  // There are 2^19937-1 possible initial states. This function allows
341  // all of those to be accessed by providing at least 19937 bits (with a
342  // default seed length of StateVectorLength = 624 IntegerType's).
343  // Any bits above the lower 32
344  // in each element are discarded.
345  // Just call seed() if you want to get array from /dev/urandom
346  Initialize(19650218UL);
347  register IntegerType i = 1;
348  register IntegerType j = 0;
349  register int k;
350  if ( StateVectorLength > seedLength )
351  {
352  k = StateVectorLength;
353  }
354  else
355  {
356  k = seedLength;
357  }
358  for (; k; --k )
359  {
360  state[i] =
361  state[i] ^ ( ( state[i - 1] ^ ( state[i - 1] >> 30 ) ) * 1664525UL );
362  state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
363  state[i] &= 0xffffffffUL;
364  ++i; ++j;
365  if ( i >= StateVectorLength ) { state[0] = state[StateVectorLength - 1]; i = 1; }
366  if ( j >= seedLength ) { j = 0; }
367  }
368  for ( k = StateVectorLength - 1; k; --k )
369  {
370  state[i] =
371  state[i] ^ ( ( state[i - 1] ^ ( state[i - 1] >> 30 ) ) * 1566083941UL );
372  state[i] -= i;
373  state[i] &= 0xffffffffUL;
374  ++i;
375  if ( i >= SVL )
376  {
377  state[0] = state[StateVectorLength - 1]; i = 1;
378  }
379  }
380  state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array
381  reload();
382 }
383  */
384 
385 inline void
387 {
388  SetSeed();
389 }
390 
391 inline void
393 {
394  // Seed the generator with a simple IntegerType
395  Initialize(oneSeed);
396  reload();
397 }
398 
399 inline void
401 {
402  // use time() and clock() to generate a unlikely-to-repeat seed.
403  SetSeed( hash( vcl_time(0), vcl_clock() ) );
404 }
405 
409 {
410  if ( left == 0 ) { reload(); }
411  --left;
413 
414  register IntegerType s1;
415  s1 = *pNext++;
416  s1 ^= ( s1 >> 11 );
417  s1 ^= ( s1 << 7 ) & 0x9d2c5680UL;
418  s1 ^= ( s1 << 15 ) & 0xefc60000UL;
419  return ( s1 ^ ( s1 >> 18 ) );
420 }
421 
422 inline double
424 {
425  return double( GetIntegerVariate() ) * ( 1.0 / 4294967295.0 );
426 }
427 
429 inline double
431  const double & n)
432 {
433  return GetVariateWithClosedRange() * n;
434 }
435 
437 inline double
439 {
440  return double( GetIntegerVariate() ) * ( 1.0 / 4294967296.0 );
441 }
442 
444 inline double
446  const double & n)
447 {
448  return GetVariateWithOpenUpperRange() * n;
449 }
450 
452 inline double
454 {
455  return ( double( GetIntegerVariate() ) + 0.5 ) * ( 1.0 / 4294967296.0 );
456 }
457 
459 inline double
461  const double & n)
462 {
463  return GetVariateWithOpenRange() * n;
464 }
465 
468  const IntegerType & n)
469 {
470  // Find which bits are used in n
471  // Optimized by Magnus Jonsson magnus at smartelectronix dot com
472  IntegerType used = n;
473 
474  used |= used >> 1;
475  used |= used >> 2;
476  used |= used >> 4;
477  used |= used >> 8;
478  used |= used >> 16;
479 
480  // Draw numbers until one is found in [0,n]
481  IntegerType i;
482  do
483  {
484  i = GetIntegerVariate() & used; // toss unused bits to shorten search
485  }
486  while ( i > n );
487 
488  return i;
489 }
490 
493 inline double
495 {
496  IntegerType a = GetIntegerVariate() >> 5, b = GetIntegerVariate() >> 6;
497 
498  return ( a * 67108864.0 + b ) * ( 1.0 / 9007199254740992.0 ); // by Isaku
499  // Wada
500 }
501 
502 /* Access to a normal random number distribution */
503 // TODO: Compare with vnl_sample_normal
504 inline double
506  const double & mean, const double & variance)
507 {
508  // Return a real number from a normal (Gaussian) distribution with given
509  // mean and variance by Box-Muller method
510  double r = vcl_sqrt(-2.0 * vcl_log( 1.0 - GetVariateWithOpenRange() ) * variance);
511  double phi = 2.0 * vnl_math::pi
513 
514  return mean + r *vcl_cos(phi);
515 }
516 
517 /* Access to a uniform random number distribution */
518 // TODO: Compare with vnl_sample_uniform
519 inline double
521  const double & a, const double & b)
522 {
523  double u = GetVariateWithOpenUpperRange();
524 
525  return ( ( 1.0 - u ) * a + u * b );
526 }
527 
528 inline double
530 {
531  return GetVariateWithClosedRange();
532 }
533 
534 inline double
536 {
537  return GetVariate();
538 }
539 
540 inline
542 {
543  SetSeed (121212);
544 }
545 
546 /* Change log from MTRand.h */
547 // Change log:
548 //
549 // v0.1 - First release on 15 May 2000
550 // - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
551 // - Translated from C to C++
552 // - Made completely ANSI compliant
553 // - Designed convenient interface for initialization, seeding, and
554 // obtaining numbers in default or user-defined ranges
555 // - Added automatic seeding from /dev/urandom or time() and clock()
556 // - Provided functions for saving and loading generator state
557 //
558 // v0.2 - Fixed bug which reloaded generator one step too late
559 //
560 // v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
561 //
562 // v0.4 - Removed trailing newline in saved generator format to be consistent
563 // with output format of built-in types
564 //
565 // v0.5 - Improved portability by replacing static const int's with enum's and
566 // clarifying return values in seed(); suggested by Eric Heimburg
567 // - Removed MAXINT constant; use 0xffffffffUL instead
568 //
569 // v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
570 // - Changed integer [0,n] generator to give better uniformity
571 //
572 // v0.7 - Fixed operator precedence ambiguity in reload()
573 // - Added access for real numbers in (0,1) and (0,n)
574 //
575 // v0.8 - Included time.h header to properly support time_t and clock_t
576 //
577 // v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
578 // - Allowed for seeding with arrays of any length
579 // - Added access for real numbers in [0,1) with 53-bit resolution
580 // - Added access for real numbers from normal (Gaussian) distributions
581 // - Increased overall speed by optimizing twist()
582 // - Doubled speed of integer [0,n] generation
583 // - Fixed out-of-range number generation on 64-bit machines
584 // - Improved portability by substituting literal constants for long enum's
585 // - Changed license from GNU LGPL to BSD
586 } // end of namespace Statistics
587 } // end of namespace itk
588 
589 #endif
590