pseudoRandom.cpp

Go to the documentation of this file.
00001 
00015 #include <dlrCommon/exception.h>
00016 #include <dlrLinearAlgebra/clapack.h>
00017 #include <dlrPortability/timeUtilities.h>
00018 #include <dlrRandom/pseudoRandom.h>
00019 
00020 namespace dlr {
00021 
00022   namespace random {
00023 
00024     // The default constructor initializes the random number generator
00025     // with a seed derived from the system clock.
00026     PseudoRandom::
00027     PseudoRandom()
00028     {
00029 
00030       // Note that time resolution is not critical here.  The only
00031       // impact of low resolution is that two PseudorRandom instances
00032       // created at nearly the same time may wind up on the same
00033       // sequence.  If you're worried about that, you can use the
00034       // getCurrentSeed() member function to make sure it hasn't
00035       // happened.
00036       double currentTime = dlr::portability::getCurrentTime();
00037       Int32 seconds = static_cast<Int32>(currentTime);
00038       Int32 uSeconds = static_cast<Int32>(1000000.0 * (currentTime - seconds));
00039     
00040       // All seeds must be in the range [0, 4096).
00041       Int32 seed0 = static_cast<Int32>(seconds & 0x00000fff);
00042       Int32 seed1 = static_cast<Int32>((seconds & 0x00fff000) >> 12);
00043       Int32 seed2 = static_cast<Int32>((uSeconds & 0x00000fff));
00044       Int32 seed3 = static_cast<Int32>((uSeconds & 0x00fff000) >> 12);
00045 
00046       // seed3 must be odd.
00047       if(seed3 % 2 == 0) {
00048         seed3 -= 1;
00049       }
00050 
00051       // All seeds must be >= zero.
00052       if(seed3 < 0) {
00053         seed3 = -seed3;
00054       }
00055 
00056       // try {
00057       this->setLapackSeed(seed0, seed1, seed2, seed3);
00058       // } catch(const ValueException&) {
00059       // This won't happen because we've chosen the seed values wisely.
00060       // }
00061     }
00062 
00063 
00064     // This constructor sets the seed of the random number generator.
00065     PseudoRandom::
00066     PseudoRandom(Int64 seed)
00067     {
00068       this->setCurrentSeed(seed);
00069     }
00070 
00071   
00072     // This member function returns a double drawn from a Gaussian
00073     // distribution with the specified mean and standard deviation.
00074     double
00075     PseudoRandom::
00076     gaussian(double mu, double sigma)
00077     {
00078       double returnValue = this->normal();
00079       return (returnValue * sigma) + mu;
00080     }
00081 
00082 
00083     // This member function returns the current state of the random
00084     // number generator.
00085     Int64
00086     PseudoRandom::
00087     getCurrentSeed()
00088     {
00089       Int64 seed = 0;
00090       seed += static_cast<Int64>(m_seed[0]) << 35;
00091       seed += static_cast<Int64>(m_seed[1]) << 23;
00092       seed += static_cast<Int64>(m_seed[2]) << 11;
00093       seed += static_cast<Int64>((m_seed[3] & 0x0ffe) >> 1);
00094       return seed;
00095     }
00096   
00097 
00098     // This member function returns a double drawn from a Gaussian
00099     // distribution with equal to 0.0 and and standard deviation equal to
00100     // 1.0.
00101     double
00102     PseudoRandom::
00103     normal()
00104     {
00105       Int32 idist = 3;   // Tells lapack we want a normal distribution.
00106       double returnValue;   // The nuber we'll return.
00107       Int32 size = 1;    // Only one value needed.
00108 
00109       // Call the lapack routine
00110       dlarnv_(&idist, m_seed, &size, &returnValue);
00111 
00112       return returnValue;
00113     }
00114 
00115 
00116     //This member function sets the seed for the random number
00117     // generator.
00118     void
00119     PseudoRandom::
00120     setCurrentSeed(Int64 seed)
00121     {
00122       // All seeds must be in the range [0,4096).
00123       Int32 seed0 = static_cast<Int32>((seed & 0x00007ff800000000LL) >> 35);
00124       Int32 seed1 = static_cast<Int32>((seed & 0x00000007ff800000LL) >> 23);
00125       Int32 seed2 = static_cast<Int32>((seed & 0x00000000007ff800LL) >> 11);
00126     
00127       // Seed3 must be odd, 
00128       Int32 seed3 = static_cast<Int32>(((seed & 0x00000000000007ffLL) << 1) + 1);
00129 
00130       // try {
00131       this->setLapackSeed(seed0, seed1, seed2, seed3);
00132       // } catch(const ValueException&) {
00133       // This won't happen because we've chosen the seed values wisely.
00134       // }
00135     }
00136 
00137   
00138     // This member function returns a double, x, drawn from a uniform
00139     // distribution.
00140     double
00141     PseudoRandom::
00142     uniform(double lowerBound, double upperBound)
00143     {
00144       Int32 idist = 1;   // Tells lapack we want uniform [0,1)
00145       double returnValue;   // The number we'll return
00146       Int32 size = 1;    // Only one value needed.
00147 
00148       // Call the lapack routine
00149       dlarnv_(&idist, m_seed, &size, &returnValue);
00150 
00151       double range = upperBound - lowerBound;
00152       returnValue = returnValue * range + lowerBound;
00153       return returnValue;
00154     }
00155 
00156 
00157     // This member function returns a integer, x, drawn from a uniform
00158     // distribution.
00159     int
00160     PseudoRandom::
00161     uniformInt(int lowerBound, int upperBound)
00162     {
00163       return static_cast<int>(
00164         this->uniform(static_cast<double>(lowerBound),
00165                       static_cast<double>(upperBound)));
00166     }
00167 
00168     void
00169     PseudoRandom::
00170     setLapackSeed(Int32 seed0, Int32 seed1, Int32 seed2, Int32 seed3)
00171     {
00172       if(seed3 % 2 == 0) {
00173         DLR_THROW(ValueException,
00174                   "PseudoRandom::setLapackSeed(Int32, Int32, Int32, Int32)",
00175                   "Seed 3 must be odd.");
00176       }
00177       if(seed0 >= 4096 || seed1 >= 4096 || seed2 >= 4096 || seed3 >= 4096
00178          || seed0 < 0 || seed1 < 0 || seed2 < 0 || seed3 < 0 ) {
00179         DLR_THROW(ValueException,
00180                   "PseudoRandom::PseudoRandom(Int32, Int32, Int32, Int32)",
00181                   "All seeds must be >= 0 and < 4096.");
00182       }
00183       m_seed[0] = seed0;
00184       m_seed[1] = seed1;
00185       m_seed[2] = seed2;
00186       m_seed[3] = seed3;
00187     }
00188 
00189     
00190   } // namespace random
00191     
00192 } // namespace dlr

Generated on Mon Jul 9 20:34:03 2007 for dlrLibs Utility Libraries by  doxygen 1.5.2