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

Generated at Wed May 24 23:40:07 2006 for ITK by doxygen 1.3.5 written by Dimitri van Heesch, © 1997-2000