00001 #ifndef UTIL_RANDOM_H
00002 #define UTIL_RANDOM_H
00003
00004 #include <cstdlib>
00005 #include <limits>
00006
00007 namespace util
00008 {
00034 void rand_init(unsigned int);
00035
00046 void rand_init();
00047
00048
00053 template<typename T> inline T rand();
00054
00055
00061 template<typename T> inline T rand_excl(T bottom, T top);
00062
00063
00069 template<typename T> inline T rand_excl(T top);
00070
00071
00077 template<typename T> inline T rand_incl(T bottom, T top);
00078
00079
00085 template<typename T> inline T rand_incl(T top);
00086
00087
00098 template<typename T> inline T wide_rand();
00099
00105 template<typename T> inline T wide_rand_excl(T top);
00106
00112 template<typename T> inline T wide_rand_excl(T bottom, T top);
00113
00119 template<typename T> inline T wide_rand_incl(T top);
00120
00126 template<typename T> inline T wide_rand_incl(T bottom, T top);
00127
00128
00130 namespace internal
00131 {
00133 int rand_int();
00134
00136 template<typename T, bool is_integer_type> struct random_scaler;
00137
00139 template<typename T> struct random_scaler<T, true>
00140 {
00141 static T rnd_excl(T value, T range) { return value % range; }
00142 static T rnd_incl(T value, T range) { return value % (range + 1); }
00143 };
00144
00146 template<typename T> struct random_scaler<T, false>
00147 {
00148 static T rnd_excl(T value, T range)
00149 {
00150
00151 return range * value / (T(RAND_MAX) + 1);
00152 }
00153 static T rnd_incl(T value, T range) { return range * value / RAND_MAX; }
00154 };
00155
00157 template<typename T, size_t remaining_ints> struct wide_random_collector
00158 {
00159 static T generate()
00160 {
00161 T one_int = util::rand<T>() << (8 * sizeof(int));
00162 return one_int | wide_random_collector<T, remaining_ints-1>::generate();
00163 }
00164 };
00166 template<typename T> struct wide_random_collector<T, 1>
00167 {
00168 static T generate() { return util::rand<T>(); }
00169 };
00170
00171 }
00172
00173
00174 template<typename T> inline T rand()
00175 {
00176 return T(util::internal::rand_int());
00177 }
00178
00179 template<typename T> inline T rand_excl(T top)
00180 {
00181 typedef internal::random_scaler<T, std::numeric_limits<T>::is_integer> scaler;
00182 return scaler::rnd_excl(util::rand<T>(), top);
00183 }
00184
00185 template<typename T> inline T rand_excl(T bottom, T top)
00186 {
00187 return bottom + rand_excl(top - bottom);
00188 }
00189
00190 template<typename T> inline T rand_incl(T top)
00191 {
00192 typedef internal::random_scaler<T, std::numeric_limits<T>::is_integer> scaler;
00193 return scaler::rnd_incl(util::rand<T>(), top);
00194 }
00195
00196 template<typename T> inline T rand_incl(T bottom, T top)
00197 {
00198 return bottom + rand_incl(top - bottom);
00199 }
00200
00201 template<typename T> inline T wide_rand()
00202 {
00203 return internal::wide_random_collector<T, sizeof(T)/sizeof(int)>::generate();
00204 }
00205
00206 template<typename T> inline T wide_rand_excl(T top)
00207 {
00208 typedef internal::random_scaler<T, std::numeric_limits<T>::is_integer> scaler;
00209 return scaler::rnd_excl(util::wide_rand<T>(), top);
00210 }
00211
00212 template<typename T> inline T wide_rand_excl(T bottom, T top)
00213 {
00214 return bottom + wide_rand_excl(top - bottom);
00215 }
00216
00217 template<typename T> inline T wide_rand_incl(T top)
00218 {
00219 typedef internal::random_scaler<T, std::numeric_limits<T>::is_integer> scaler;
00220 return scaler::rnd_incl(util::wide_rand<T>(), top);
00221 }
00222
00223 template<typename T> inline T wide_rand_incl(T bottom, T top)
00224 {
00225 return bottom + wide_rand_incl(top - bottom);
00226 }
00227 }
00228
00229 #endif