00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef _RANDOM_H
00022 #define _RANDOM_H
00023
00024 #include <vector>
00025 #include <time.h>
00026 #include <math.h>
00027
00028 #include "constants.h"
00029
00030 #if GCC_VERSION >= 40300
00031
00032 #include <tr1/unordered_set>
00033 using namespace std::tr1;
00034 #else
00035 #include <ext/hash_map>
00036 using namespace __gnu_cxx;
00037 #define unordered_set hash_set;
00038 #define unordered_map hash_map;
00039 #endif
00040
00041 using namespace std;
00042
00043 #include "global.h"
00044 #include "Mersennetwister.h"
00045
00046
00047
00048 #ifdef __GNUC__
00049 #if __GNUC__ < 3
00050 namespace Sgi { using ::hash_map; };
00051 #else
00052 #if __GNUC_MINOR__ == 0
00053 namespace Sgi = std;
00054 #else
00055 namespace Sgi = ::__gnu_cxx;
00056 #endif
00057 #endif
00058 #else // ... there are other compilers, right?
00059 namespace Sgi = std;
00060 #endif
00061
00062 #if (GCC_VERSION < 40300)
00063
00064 namespace __gnu_cxx
00065 {
00066 template <> struct hash< double >
00067 {
00068
00069
00070
00071 size_t operator()(const double& num) const { return static_cast< size_t >(num); }
00072 };
00073 }
00074 #endif // GCC_VERSION
00075
00076
00077
00078
00079 template <class MyNT> class MyRand : public MTRand
00080 {
00081 public:
00082 MyRand()
00083 : MTRand()
00084 {}
00085 virtual ~MyRand()
00086 {}
00087
00088 MyNT operator()();
00089 MyNT operator()(MyNT num);
00090 MyNT operator()(MyNT low, MyNT high);
00091 };
00092
00093 template <> int MyRand< int >::operator()();
00094 template <> int MyRand< int >::operator()(int num);
00095 template <> int MyRand< int >::operator()(int low, int high);
00096 template <> double MyRand< double >::operator()();
00097 template <> double MyRand< double >::operator()(double num);
00098 template <> double MyRand< double >::operator()(double low, double high);
00099
00100 enum MyUniqueRandomStatus {MyUniqueRandomStatus_OK, MyUniqueRandomStatus_NONE};
00101
00102
00103
00104
00105 template < class MyNT > class MyUniqueRandom
00106 {
00107 public:
00108
00109
00110
00111
00112 MyUniqueRandom(MyNT l, MyNT h)
00113 : low(l), high(h), generator(), unique()
00114 {
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 virtual ~MyUniqueRandom()
00132 {}
00133
00134
00135 void reset()
00136 {
00137
00138 unique.clear();
00139 }
00140
00141
00142
00143
00144
00145
00146
00147 MyUniqueRandomStatus generate(MyNT& num)
00148 {
00149 if (allGenerated(unique.size()))
00150 {
00151 cerr << "ERROR! All unique random numbers between " << low << " and " << high
00152 << " have been generated." << endl;
00153 return(MyUniqueRandomStatus_NONE);
00154 }
00155
00156 while (true)
00157 {
00158 num = generator(low, high);
00159 if (unique.end() == unique.find(num))
00160 {
00161 unique.insert(num);
00162 return(MyUniqueRandomStatus_OK);
00163 }
00164 }
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 MyUniqueRandomStatus generate(
00177 MyNT& num,
00178 #if GCC_VERSION >= 40300
00179 const unordered_set< MyNT, hash< MyNT > >& numsToAvoid)
00180 #else
00181 const hash_set< MyNT, hash< MyNT > >& numsToAvoid)
00182 #endif
00183 {
00184 if (allGenerated(unique.size() + numsToAvoid.size()))
00185 {
00186 cerr << "ERROR! All unique random numbers between " << low << " and " << high
00187 << " have been generated." << endl;
00188 return(MyUniqueRandomStatus_NONE);
00189 }
00190
00191 while (true)
00192 {
00193 num = generator(low, high);
00194 if ((unique.end() == unique.find(num)) &&
00195 (numsToAvoid.end() == numsToAvoid.find(num)))
00196 {
00197 unique.insert(num);
00198 return(MyUniqueRandomStatus_OK);
00199 }
00200 }
00201 }
00202
00203
00204
00205
00206 MyUniqueRandomStatus generate(
00207 int count,
00208 #if GCC_VERSION >= 40300
00209 const unordered_set< MyNT, hash< MyNT > >& numsToAvoid,
00210 #else
00211 const hash_set< MyNT, hash< MyNT > >& numsToAvoid,
00212 #endif
00213 vector< MyNT >& nums)
00214 {
00215 if (!canGenerate(count + numsToAvoid.size()))
00216 {
00217 cerr << "ERROR! MyUniqueRandom::generate(): cannot generate " <<
00218 count + numsToAvoid.size() << " unique random numbers between "
00219 << low << " and " << high << "." << endl;
00220 return(MyUniqueRandomStatus_NONE);
00221 }
00222
00223
00224
00225 #if GCC_VERSION >= 40300
00226 static unordered_set< MyNT, hash< MyNT > > localUnique;
00227 #else
00228 static hash_set< MyNT, hash< MyNT > > localUnique;
00229 #endif
00230 MyNT num;
00231 while (0 < count)
00232 {
00233 num = generator(low, high);
00234
00235
00236
00237 if ((localUnique.end() == localUnique.find(num)) &&
00238 (numsToAvoid.end() == numsToAvoid.find(num)))
00239 {
00240 localUnique.insert(num);
00241 nums[--count] = num;
00242 }
00243 }
00244 localUnique.clear();
00245 return(MyUniqueRandomStatus_OK);
00246 }
00247
00248
00249
00250
00251
00252
00253 MyUniqueRandomStatus generate(
00254 int count,
00255 const vector< int >& numsToUse,
00256 #if GCC_VERSION >= 40300
00257 const unordered_set< MyNT, hash< MyNT > >& numsToAvoid,
00258 #else
00259 const hash_set< MyNT, hash< MyNT > >& numsToAvoid,
00260 #endif
00261 vector< MyNT >& nums)
00262 {
00263
00264 if (!canGenerate(0, numsToUse.size() - 1,
00265 count + numsToAvoid.size()))
00266 {
00267 cerr << "ERROR! MyUniqueRandom::generate(): cannot generate " <<
00268 count + numsToAvoid.size() << " unique random numbers between "
00269 << 0 << " and " << numsToUse.size() - 1 << "." << endl;
00270 return(MyUniqueRandomStatus_NONE);
00271 }
00272
00273
00274
00275 #if GCC_VERSION >= 40300
00276 static unordered_set< MyNT, hash< MyNT > > localUnique;
00277 #else
00278 static hash_set< MyNT, hash< MyNT > > localUnique;
00279 #endif
00280 MyNT num, randomNum;
00281 while (0 < count)
00282 {
00283
00284 randomNum = generator(0, numsToUse.size() - 1);
00285 num = numsToUse[randomNum];
00286
00287
00288
00289
00290
00291 if ((localUnique.empty() ||
00292 (localUnique.end() == localUnique.find(num))) &&
00293 (numsToAvoid.empty() ||
00294 (numsToAvoid.end() == numsToAvoid.find(num))))
00295 {
00296 localUnique.insert(num);
00297 nums[--count] = num;
00298 }
00299 }
00300 localUnique.clear();
00301 return(MyUniqueRandomStatus_OK);
00302 }
00303
00304 private:
00305 int numPossibleUnique() const;
00306 bool allGenerated(int num) const;
00307 bool canGenerate(int num) const;
00308
00309 bool canGenerate(int newlow, int newhigh, int num) const;
00310
00311 private:
00312 MyNT low;
00313 MyNT high;
00314 MyRand< MyNT > generator;
00315 #if GCC_VERSION >= 40300
00316 unordered_set< MyNT > unique;
00317 #else
00318 hash_set< MyNT > unique;
00319 #endif
00320 };
00321
00322
00323
00324 #endif // _RANDOM_H