Main Page   Groups   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Concepts

itkMersenneTwisterRandomVariateGenerator.h

Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Program:   Insight Segmentation & Registration Toolkit
00004   Module:    $RCSfile: itkMersenneTwisterRandomVariateGenerator.h,v $
00005   Language:  C++
00006   Date:      $Date: 2009-08-08 15:25:34 $
00007   Version:   $Revision: 1.9 $
00008 
00009   Copyright (c) Insight Software Consortium. All rights reserved.
00010   See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
00011 
00012      This software is distributed WITHOUT ANY WARRANTY; without even 
00013      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
00014      PURPOSE.  See the above copyright notices for more information.
00015 
00016 =========================================================================*/
00017 #ifndef __itkMersenneTwisterRandomVariateGenerator_h
00018 #define __itkMersenneTwisterRandomVariateGenerator_h
00019 
00020 #if defined(_MSC_VER)
00021 #pragma warning ( disable : 4146 )
00022 #endif
00023 
00024 #include "itkMacro.h"
00025 #include "itkObjectFactory.h"
00026 #include "itkRandomVariateGeneratorBase.h"
00027 #include "itkIntTypes.h"
00028 #include "vcl_ctime.h"
00029 #include "vnl/vnl_math.h"
00030 #include <limits.h>
00031 
00032 
00033 namespace itk {
00034 namespace Statistics {
00035 
00103 class ITKCommon_EXPORT MersenneTwisterRandomVariateGenerator : 
00104     public RandomVariateGeneratorBase
00105 {
00106 public:
00107   
00109   typedef MersenneTwisterRandomVariateGenerator Self;
00110   typedef RandomVariateGeneratorBase            Superclass;
00111   typedef SmartPointer<Self>                    Pointer;
00112   typedef SmartPointer<const Self>              ConstPointer;
00113 
00114   typedef ITK_UINT32 IntegerType;
00115 
00117   itkTypeMacro(MersenneTwisterRandomVariateGenerator, 
00118                RandomVariateGeneratorBase );
00119 
00121   static Pointer New();
00122   static Pointer GetInstance();
00124 
00126   itkStaticConstMacro(StateVectorLength,IntegerType,624);
00127 
00129   // itkStaticConstMacro(SAVE,IntegerType,625);
00130 
00131   
00132   
00133   // Methods to reseed
00134   
00136   void Initialize( const IntegerType oneSeed );
00137 
00139   //void Initialize( IntegerType *const bigSeed, 
00140   //        IntegerType const seedLength = StateVectorLength );  
00141 
00142   /* Initialize with vcl_clock time */ 
00143   void Initialize();  
00144   
00145   // Methods to get various random variates ...
00146   
00148   double GetVariateWithClosedRange();
00149 
00151   double GetVariateWithClosedRange( const double& n );
00152 
00154   double GetVariateWithOpenUpperRange();
00155 
00157   double GetVariateWithOpenUpperRange( const double& n );
00158 
00160   double GetVariateWithOpenRange();
00161 
00163   double GetVariateWithOpenRange( const double& n );
00164 
00166   IntegerType GetIntegerVariate();
00167 
00169   IntegerType GetIntegerVariate( const IntegerType& n );
00170 
00173   double Get53BitVariate();
00174 
00175   /* Access to a normal random number distribution 
00176    * TODO: Compare with vnl_sample_normal */
00177   double GetNormalVariate( const double& mean = 0.0, 
00178       const double& variance = 1.0 );
00179   
00180   /* Access to a uniform random number distribution in the range [a, b)
00181    * TODO: Compare with vnl_sample_uniform */
00182   double GetUniformVariate( const double& a, const double& b );
00183   
00189   virtual double GetVariate();
00190 
00192   double operator()(); 
00193 
00194 
00195   // Re-seeding functions with same behavior as initializers
00196   inline void SetSeed( const IntegerType oneSeed );
00197   inline void SetSeed( IntegerType * bigSeed, const IntegerType seedLength = StateVectorLength );
00198   inline void SetSeed();
00199 
00200   /*
00201   // Saving and loading generator state
00202   void save( IntegerType* saveArray ) const;  // to array of size SAVE
00203   void load( IntegerType *const loadArray );  // from such array
00204   */
00205 
00206 protected:
00207   inline MersenneTwisterRandomVariateGenerator();
00208   virtual ~MersenneTwisterRandomVariateGenerator() {}; 
00209   virtual void PrintSelf(std::ostream& os, Indent indent) const {
00210     Superclass::PrintSelf(os, indent);
00211 
00212     // Print state vector contents
00213     os << indent << "State vector: " << state << std::endl;
00214     os << indent;
00215     register const IntegerType *s = state;
00216     register int i = StateVectorLength;
00217     for(; i--; os << *s++ << "\t" ) {}
00218     os << std::endl;
00219     
00220     //Print next value to be gotten from state
00221     os << indent << "Next value to be gotten from state: " << pNext << std::endl;
00222     
00223     //Number of values left before reload
00224     os << indent << "Values left before next reload: " << left << std::endl;
00225   }
00226 
00227 
00228   // enum { M = 397 };  // period parameter
00229   itkStaticConstMacro ( M, unsigned int, 397 );
00230   
00231   IntegerType state[StateVectorLength];   // internal state
00232   IntegerType *pNext;     // next value to get from state
00233   int left;          // number of values left before reload needed
00234 
00235   /* Reload array with N new values */
00236   void reload();
00237   
00238   IntegerType hiBit( const IntegerType& u ) const { return u & 0x80000000UL; }
00239   IntegerType loBit( const IntegerType& u ) const { return u & 0x00000001UL; }
00240   IntegerType loBits( const IntegerType& u ) const { return u & 0x7fffffffUL; }
00241   IntegerType mixBits( const IntegerType& u, const IntegerType& v ) const
00242     { 
00243     return hiBit(u) | loBits(v); 
00244     }
00245   IntegerType twist( const IntegerType& m, const IntegerType& s0, const IntegerType& s1 ) const
00246     { 
00247     return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfUL); 
00248     }
00249   static IntegerType hash( vcl_time_t t, vcl_clock_t c );
00250   static Pointer m_Instance;
00251 };  // end of class
00252   
00253 // Declare inlined functions.... (must be declared in the header)
00254 // Declare then in order to keep SGI happy
00255 
00256 inline MersenneTwisterRandomVariateGenerator::IntegerType 
00257 MersenneTwisterRandomVariateGenerator::hash( vcl_time_t t, vcl_clock_t c )
00258 {
00259   // Get a IntegerType from t and c
00260   // Better than IntegerType(x) in case x is floating point in [0,1]
00261   // Based on code by Lawrence Kirby: fred at genesis dot demon dot co dot uk 
00262 
00263   static IntegerType differ = 0;  // guarantee time-based seeds will change
00264 
00265   IntegerType h1 = 0;
00266   unsigned char *p = (unsigned char *) &t;
00267   for( size_t i = 0; i < sizeof(t); ++i )
00268     {
00269     h1 *= UCHAR_MAX + 2U;
00270     h1 += p[i];
00271     }
00272   IntegerType h2 = 0;
00273   p = (unsigned char *) &c;
00274   for( size_t j = 0; j < sizeof(c); ++j )
00275     {
00276     h2 *= UCHAR_MAX + 2U;
00277     h2 += p[j];
00278     }
00279   return ( h1 + differ++ ) ^ h2;
00280 }
00281 
00282 
00283 inline void 
00284 MersenneTwisterRandomVariateGenerator::Initialize( const IntegerType seed )
00285 {
00286   // Initialize generator state with seed
00287   // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
00288   // In previous versions, most significant bits (MSBs) of the seed affect
00289   // only MSBs of the state array.  Modified 9 Jan 2002 by Makoto Matsumoto.
00290   register IntegerType *s = state;
00291   register IntegerType *r = state;
00292   register IntegerType i = 1;
00293   *s++ = seed & 0xffffffffUL;
00294   for( i = 1; i < MersenneTwisterRandomVariateGenerator::StateVectorLength; ++i )
00295     {
00296     *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
00297     r++;
00298     }
00299 }
00300 
00301 inline void 
00302 MersenneTwisterRandomVariateGenerator::reload()
00303 {
00304   // Generate N new values in state
00305   // Made clearer and faster by Matthew Bellew 
00306   // matthew dot bellew at home dot com
00307   
00308   // get rid of VS warning
00309   register int index = static_cast< int >(
00310       M-MersenneTwisterRandomVariateGenerator::StateVectorLength);
00311     
00312   register IntegerType *p = state;
00313   register int i;
00314   for( i = MersenneTwisterRandomVariateGenerator::StateVectorLength - M; i--; ++p )
00315     {
00316     *p = twist( p[M], p[0], p[1] );
00317     }
00318   for( i = M; --i; ++p )
00319     {
00320     *p = twist( p[index], p[0], p[1] );
00321     }
00322   *p = twist( p[index], p[0], state[0] );
00323 
00324   left = MersenneTwisterRandomVariateGenerator::StateVectorLength, pNext = state;
00325 }
00326 
00327 #define SVL 624
00328 inline void 
00329 MersenneTwisterRandomVariateGenerator::SetSeed( 
00330   IntegerType * const bigSeed, const IntegerType seedLength )
00331 {
00332   // Seed the generator with an array of IntegerType's
00333   // There are 2^19937-1 possible initial states.  This function allows
00334   // all of those to be accessed by providing at least 19937 bits (with a
00335   // default seed length of StateVectorLength = 624 IntegerType's).  
00336   // Any bits above the lower 32
00337   // in each element are discarded.
00338   // Just call seed() if you want to get array from /dev/urandom
00339   Initialize(19650218UL);
00340   register IntegerType i = 1;
00341   register IntegerType j = 0;
00342   register int k;
00343   if ( StateVectorLength > seedLength )
00344     {
00345     k = StateVectorLength;
00346     }
00347   else
00348     {
00349     k = seedLength;
00350     }
00351   for(; k; --k )
00352     {
00353     state[i] =
00354       state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL );
00355     state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
00356     state[i] &= 0xffffffffUL;
00357     ++i;  ++j;
00358     if( i >= StateVectorLength ) { state[0] = state[StateVectorLength-1];  i = 1; }
00359     if( j >= seedLength ) j = 0;
00360     }
00361   for( k = StateVectorLength - 1; k; --k )
00362     {
00363     state[i] =
00364       state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL );
00365     state[i] -= i;
00366     state[i] &= 0xffffffffUL;
00367     ++i;
00368     if( i >= SVL ) 
00369       { 
00370       state[0] = state[StateVectorLength-1];  i = 1; 
00371       }
00372     }
00373   state[0] = 0x80000000UL;  // MSB is 1, assuring non-zero initial array
00374   reload();
00375 }
00376 
00377 
00378 inline void
00379 MersenneTwisterRandomVariateGenerator::Initialize()
00380 { 
00381   SetSeed(); 
00382 }
00383 
00384 
00385 inline void 
00386 MersenneTwisterRandomVariateGenerator::SetSeed( const IntegerType oneSeed )
00387 {
00388   // Seed the generator with a simple IntegerType
00389   Initialize(oneSeed);
00390   reload();
00391 }
00392 
00393 
00394 inline void 
00395 MersenneTwisterRandomVariateGenerator::SetSeed()
00396 {
00397   // use time() and clock() to generate a unlikely-to-repeat seed.
00398   SetSeed( hash( vcl_time(0), vcl_clock() ) );
00399 }
00400 
00402 inline MersenneTwisterRandomVariateGenerator::IntegerType 
00403 MersenneTwisterRandomVariateGenerator::GetIntegerVariate()
00404 {
00405   if( left == 0 ) reload();
00406   --left;
00408 
00409   register IntegerType s1;
00410   s1 = *pNext++;
00411   s1 ^= (s1 >> 11);
00412   s1 ^= (s1 <<  7) & 0x9d2c5680UL;
00413   s1 ^= (s1 << 15) & 0xefc60000UL;
00414   return ( s1 ^ (s1 >> 18) );
00415 }
00416 
00417 
00418 inline double 
00419 MersenneTwisterRandomVariateGenerator::GetVariateWithClosedRange()
00420 { 
00421   return double(GetIntegerVariate()) * (1.0/4294967295.0); 
00422 }
00423 
00425 inline double 
00426 MersenneTwisterRandomVariateGenerator::GetVariateWithClosedRange( 
00427                                                     const double& n )
00428 { 
00429   return GetVariateWithClosedRange() * n; 
00430 }
00431 
00433 inline double 
00434 MersenneTwisterRandomVariateGenerator::GetVariateWithOpenUpperRange()
00435 { 
00436   return double(GetIntegerVariate()) * (1.0/4294967296.0); 
00437 }
00438 
00440 inline double 
00441 MersenneTwisterRandomVariateGenerator::GetVariateWithOpenUpperRange( 
00442   const double& n )
00443 { 
00444   return GetVariateWithOpenUpperRange() * n; 
00445 }
00446 
00448 inline double 
00449 MersenneTwisterRandomVariateGenerator::GetVariateWithOpenRange()
00450 {
00451   return ( double(GetIntegerVariate()) + 0.5 ) * (1.0/4294967296.0); 
00452 }
00453 
00454 
00456 inline double 
00457 MersenneTwisterRandomVariateGenerator::GetVariateWithOpenRange( 
00458   const double& n )
00459 { 
00460   return GetVariateWithOpenRange() * n; 
00461 }
00462 
00463 
00464 inline MersenneTwisterRandomVariateGenerator::IntegerType 
00465 MersenneTwisterRandomVariateGenerator::GetIntegerVariate( 
00466                                         const IntegerType& n )
00467 {
00468   // Find which bits are used in n
00469   // Optimized by Magnus Jonsson magnus at smartelectronix dot com
00470   IntegerType used = n;
00471   used |= used >> 1;
00472   used |= used >> 2;
00473   used |= used >> 4;
00474   used |= used >> 8;
00475   used |= used >> 16;
00476 
00477   // Draw numbers until one is found in [0,n]
00478   IntegerType i;
00479   do
00480     {
00481     i = GetIntegerVariate() & used;  // toss unused bits to shorten search
00482     }
00483   while( i > n );
00484   
00485   return i;
00486 }
00487 
00488 
00491 inline double 
00492 MersenneTwisterRandomVariateGenerator::Get53BitVariate()  
00493 {
00494   IntegerType a = GetIntegerVariate() >> 5, b = GetIntegerVariate() >> 6;
00495   return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0);  // by Isaku Wada
00496 }
00498 
00499 
00500 /* Access to a normal random number distribution */
00501 // TODO: Compare with vnl_sample_normal
00502 inline double 
00503 MersenneTwisterRandomVariateGenerator::GetNormalVariate( 
00504   const double& mean, const double& variance )
00505 {
00506   // Return a real number from a normal (Gaussian) distribution with given
00507   // mean and variance by Box-Muller method
00508   double r = vcl_sqrt( -2.0 * vcl_log( 1.0-GetVariateWithOpenRange()) * variance);
00509   double phi = 2.0 * vnl_math::pi
00510                           * GetVariateWithOpenUpperRange();
00511   return mean + r * vcl_cos(phi);
00512 }
00513 
00514 
00515 /* Access to a uniform random number distribution */
00516 // TODO: Compare with vnl_sample_uniform
00517 inline double 
00518 MersenneTwisterRandomVariateGenerator::GetUniformVariate( 
00519                             const double& a, const double& b )
00520 {
00521   double u = GetVariateWithOpenUpperRange();
00522   return ((1.0 -u) * a + u * b); 
00523 }
00524 
00525 
00526 inline double 
00527 MersenneTwisterRandomVariateGenerator::GetVariate() 
00528 {
00529   return GetVariateWithClosedRange();
00530 }
00531 
00532 
00533 inline double 
00534 MersenneTwisterRandomVariateGenerator::operator()()
00535 { 
00536   return GetVariate(); 
00537 }  
00538  
00539 
00540 inline 
00541 MersenneTwisterRandomVariateGenerator::MersenneTwisterRandomVariateGenerator()
00542 {
00543   SetSeed ( 121212 );
00544 }
00545   
00546 
00547 /* Change log from MTRand.h */
00548 // Change log:
00549 //
00550 // v0.1 - First release on 15 May 2000
00551 //      - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
00552 //      - Translated from C to C++
00553 //      - Made completely ANSI compliant
00554 //      - Designed convenient interface for initialization, seeding, and
00555 //        obtaining numbers in default or user-defined ranges
00556 //      - Added automatic seeding from /dev/urandom or time() and clock()
00557 //      - Provided functions for saving and loading generator state
00558 //
00559 // v0.2 - Fixed bug which reloaded generator one step too late
00560 //
00561 // v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
00562 //
00563 // v0.4 - Removed trailing newline in saved generator format to be consistent
00564 //        with output format of built-in types
00565 //
00566 // v0.5 - Improved portability by replacing static const int's with enum's and
00567 //        clarifying return values in seed(); suggested by Eric Heimburg
00568 //      - Removed MAXINT constant; use 0xffffffffUL instead
00569 //
00570 // v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
00571 //      - Changed integer [0,n] generator to give better uniformity
00572 //
00573 // v0.7 - Fixed operator precedence ambiguity in reload()
00574 //      - Added access for real numbers in (0,1) and (0,n)
00575 //
00576 // v0.8 - Included time.h header to properly support time_t and clock_t
00577 //
00578 // v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
00579 //      - Allowed for seeding with arrays of any length
00580 //      - Added access for real numbers in [0,1) with 53-bit resolution
00581 //      - Added access for real numbers from normal (Gaussian) distributions
00582 //      - Increased overall speed by optimizing twist()
00583 //      - Doubled speed of integer [0,n] generation
00584 //      - Fixed out-of-range number generation on 64-bit machines
00585 //      - Improved portability by substituting literal constants for long enum's
00586 //      - Changed license from GNU LGPL to BSD
00587 
00588 } // end of namespace Statistics
00589 } // end of namespace itk
00590 
00591 #endif
00592 

Generated at Tue Sep 15 03:57:30 2009 for ITK by doxygen 1.5.8 written by Dimitri van Heesch, © 1997-2000