Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Random-Ranrotb.cpp

Go to the documentation of this file.
00001 /************************* RANROTB.CPP ****************** AgF 1999-03-03 *
00002 *  Random Number generator 'RANROT' type B                               *
00003 *                                                                        *
00004 *  This is a lagged-Fibonacci type of random number generator with       *
00005 *  rotation of bits.  The algorithm is:                                  *
00006 *  X[n] = ((X[n-j] rotl r1) + (X[n-k] rotl r2)) modulo 2^b               *
00007 *                                                                        *
00008 *  The last k values of X are stored in a circular buffer named          *
00009 *  randbuffer.                                                           *
00010 *  The code includes a self-test facility which will detect any          *
00011 *  repetition of previous states.                                        *
00012 *  The function uses a fast method for conversion to floating point.     *
00013 *  This method relies on floating point numbers being stored in the      *
00014 *  standard 64-bit IEEE format.                                          *
00015 *                                                                        *
00016 *  The theory of the RANROT type of generators and the reason for the    *
00017 *  self-test are described at www.agner.org/random                       *
00018 *                                                                        *
00019 *************************************************************************/
00020 
00021 #include "headers.h"
00022 #include "randomc.h"
00023 #ifndef __BORLANDC__    
00024 // If your system doesn't have a rotate function for 32 bits integers,
00025 // then define it thus:
00026 //unsigned long _lrotl (unsigned long x, int r) {
00027 //  return (x << r) | (x >> (sizeof(x)*8-r));}
00028 #endif  
00029 
00030 TRanrotBGenerator::TRanrotBGenerator() {
00031     RandomInit(time(NULL));
00032 }
00033 
00034 
00035 // constructor:
00036 TRanrotBGenerator::TRanrotBGenerator(long int seed) {
00037   RandomInit(seed);
00038 }
00039 
00040 
00041 // returns a random number between 0 and 1:
00042 double TRanrotBGenerator::Random() {
00043     Guard guard(&m_mutex);
00044     unsigned long x;
00045     // generate next random number
00046     x = randbuffer[p1] = _lrotl(randbuffer[p2], R1) + _lrotl(randbuffer[p1], R2);
00047     // rotate list pointers
00048     if (--p1 < 0) p1 = KK - 1;
00049     if (--p2 < 0) p2 = KK - 1;
00050 #ifdef SELF_TEST
00051     // perform self-test
00052     if (randbuffer[p1] == randbufcopy[0] &&
00053         memcmp(randbuffer, randbufcopy+KK-p1, KK*sizeof(uint32)) == 0) {
00054         // self-test failed
00055         if ((p2 + KK - p1) % KK != JJ) {
00056             // note: the way of printing error messages depends on system
00057             // In Windows you may use FatalAppExit
00058             printf("Random number generator not initialized");
00059         }
00060         else {
00061             printf("Random number generator returned to initial state");
00062         }
00063         exit(1);
00064     }
00065 #endif
00066     // fast conversion to float:
00067     union {
00068         double randp1;
00069         unsigned long randbits[2];
00070     };
00071     randbits[0] = x << 20;
00072     randbits[1] = (x >> 12) | 0x3FF00000;
00073     return randp1 - 1.0;
00074 }
00075 
00076 
00077 // returns integer random number in desired interval:
00078 int TRanrotBGenerator::IRandom(int min, int max) {
00079     Guard guard(&m_mutex);
00080     int iinterval = max - min + 1;
00081     if (iinterval <= 0) {
00082         return 0x80000000; // error
00083     }
00084     int i = iinterval * Random(); // truncate
00085     if (i >= iinterval) {
00086         i = iinterval-1;
00087     }
00088     return (min + i);
00089 }
00090   
00091 
00092 void TRanrotBGenerator::RandomInit(long int seed) {
00093     Guard guard(&m_mutex);
00094     // this function initializes the random number generator.
00095     int i;
00096     unsigned long s = seed;
00097     
00098     // make random numbers and put them into the buffer
00099     for (i=0; i<KK; i++) {
00100         s = s * 2891336453 + 1;
00101         randbuffer[i] = s;
00102     }
00103     
00104     // check that the right data formats are used by compiler:
00105     union {
00106         double randp1;
00107         unsigned long randbits[2];
00108     };
00109     randp1 = 1.5;
00110     assert(randbits[1]==0x3FF80000); // check that IEEE double precision float format used
00111     
00112     // initialize pointers to circular buffer
00113     p1 = 0;  p2 = JJ;
00114 #ifdef SELF_TEST
00115     // store state for self-test
00116     memcpy (randbufcopy, randbuffer, KK*sizeof(uint32));
00117     memcpy (randbufcopy+KK, randbuffer, KK*sizeof(uint32));
00118 #endif
00119     // randomize some more
00120     for (i=0; i<9; i++) {
00121         Random();
00122     }
00123 }
00124 

Generated at Thu Jul 11 13:31:51 2002 for Peekabooty by doxygen1.2.9 written by Dimitri van Heesch, © 1997-2001