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

Generated at Tue Aug 30 16:45:18 2005 for ITK by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2000