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
00025
00026 PseudoRandom::
00027 PseudoRandom()
00028 {
00029
00030
00031
00032
00033
00034
00035
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
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
00047 if(seed3 % 2 == 0) {
00048 seed3 -= 1;
00049 }
00050
00051
00052 if(seed3 < 0) {
00053 seed3 = -seed3;
00054 }
00055
00056
00057 this->setLapackSeed(seed0, seed1, seed2, seed3);
00058
00059
00060
00061 }
00062
00063
00064
00065 PseudoRandom::
00066 PseudoRandom(Int64 seed)
00067 {
00068 this->setCurrentSeed(seed);
00069 }
00070
00071
00072
00073
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
00084
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
00099
00100
00101 double
00102 PseudoRandom::
00103 normal()
00104 {
00105 Int32 idist = 3;
00106 double returnValue;
00107 Int32 size = 1;
00108
00109
00110 dlarnv_(&idist, m_seed, &size, &returnValue);
00111
00112 return returnValue;
00113 }
00114
00115
00116
00117
00118 void
00119 PseudoRandom::
00120 setCurrentSeed(Int64 seed)
00121 {
00122
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
00128 Int32 seed3 = static_cast<Int32>(((seed & 0x00000000000007ffLL) << 1) + 1);
00129
00130
00131 this->setLapackSeed(seed0, seed1, seed2, seed3);
00132
00133
00134
00135 }
00136
00137
00138
00139
00140 double
00141 PseudoRandom::
00142 uniform(double lowerBound, double upperBound)
00143 {
00144 Int32 idist = 1;
00145 double returnValue;
00146 Int32 size = 1;
00147
00148
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
00158
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 }
00191
00192 }