00001 #ifndef Impala_Util_NewRandom_h
00002 #define Impala_Util_NewRandom_h
00003
00004 #include <ctime>
00005 #include <cstdlib>
00006 #include <set>
00007
00008 #include "Basis/ILog.h"
00009 #include "Basis/NativeTypes.h"
00010
00011 namespace Impala
00012 {
00013 namespace Util
00014 {
00015
00028 class Random
00029 {
00030 public:
00031 static Random&
00032 GetGlobal()
00033 {
00034 static Random globalInstance;
00035 return globalInstance;
00036 }
00037
00038
00039 Random()
00040 {
00041 SetSeed(1);
00042 }
00043
00044 ~Random()
00045 {
00046 }
00047
00048 void
00049 SetSeed(long seed)
00050 {
00051 mSeed = (seed ^ 0x5DEECE66DLL) & ((1LL << 48) - 1);
00052 }
00053
00054 void
00055 RandomizeSeed()
00056 {
00057 SetSeed(time(0));
00058 }
00059
00061 int
00062 GetRandMax()
00063 {
00064 return (1LL << cRandomIntBits) -1;
00065 }
00066
00068 int
00069 GetInt()
00070 {
00071 return Next(cRandomIntBits);
00072 }
00073
00075 int
00076 GetInt(int upperBound)
00077 {
00078 if(upperBound < 0)
00079 {
00080 ILOG_ERROR("upperbound must be positive");
00081 return 0;
00082 }
00083 if(upperBound > GetRandMax())
00084 ILOG_WARNING(upperBound <<" upperBound > rand max "<< GetRandMax());
00085
00086
00087
00088
00089 if(!((upperBound -1) & upperBound))
00090 return (int)((upperBound * (UInt64)Next(31)) >> 31);
00091
00092
00093
00094 int bits, val;
00095 do {
00096 bits = Next(31);
00097 val = bits % upperBound;
00098 } while(bits - val + (upperBound-1) < 0);
00099
00100 return val;
00101 }
00102
00105 double
00106 GetDouble()
00107 {
00108 return (((UInt64)Next(26) << 27) + Next(27)) / (double)(1LL << 53);
00109
00110 }
00111
00113 std::set<int>
00114 RandomUniqueNumbers(int count, int upperBound)
00115 {
00116 std::set<int> set;
00117 if(count > upperBound)
00118 {
00119 ILOG_ERROR("count > upperBound:"<< count <<" "<< upperBound);
00120 for(int i=0 ; i<count ; ++i)
00121 set.insert(i);
00122 return set;
00123 }
00124 if(count >= GetRandMax())
00125 {
00126 ILOG_ERROR("count >= GetRandMax:"<< count <<" "<< GetRandMax());
00127 for(int i=0 ; i<count ; ++i)
00128 set.insert(i);
00129 return set;
00130 }
00131 while(set.size() < count)
00132 {
00133 int draw = GetInt(upperBound);
00134 if(set.find(draw) == set.end())
00135 set.insert(draw);
00136 }
00137 return set;
00138 }
00139
00141 int
00142 operator() (int upperBound)
00143 {
00144 return GetInt(upperBound);
00145 }
00146
00147 private:
00148 Int64 mSeed;
00149 static const int cRandomIntBits = 31;
00150 ILOG_CLASS;
00151
00152 Int64
00153 Next(int bits)
00154 {
00155 mSeed = (mSeed * 0x5DEECE66DLL + 0xBL) & ((1LL << 48) - 1);
00156 return (mSeed >> (48 - bits));
00157 }
00158 };
00159
00160 ILOG_CLASS_INIT(Random, Impala.Util);
00161
00162
00163 }
00164 }
00165
00166 #endif