Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #if !defined(RANDOMNUMBER_HPP)
00012 #define RANDOMNUMBER_HPP "$Id: RandomNumber.hpp 6723 2010-01-11 14:20:10Z ckarney $"
00013
00014 #include <vector>
00015 #include <iomanip>
00016 #include <limits>
00017 #include <cmath>
00018
00019 #if !defined(STATIC_ASSERT)
00020
00021
00022
00023 #define STATIC_ASSERT(cond,reason) { enum{ STATIC_ASSERT_ENUM = 1/int(cond) }; }
00024 #endif
00025
00026 namespace RandomLib {
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 template<int bits = 1> class RandomNumber {
00045 public:
00046
00047
00048
00049 RandomNumber(int n = 0) : _n(n) {};
00050
00051
00052
00053 int Integer() const { return _n; }
00054
00055
00056
00057 template<class Random> unsigned Digit(Random& r, unsigned k) {
00058 ExpandTo(r, k + 1);
00059 return _f[k];
00060 }
00061
00062
00063
00064 unsigned RawDigit(unsigned k) const {
00065 return _f.at(k);
00066 }
00067
00068
00069
00070 void AddInteger(int k) { _n += k; }
00071
00072
00073
00074 void SetInteger(int k) { _n = k; }
00075
00076
00077
00078 void Init(int n = 0) {
00079 STATIC_ASSERT(bits > 0 && bits <= w && (bits < 4 || bits % 4 == 0),
00080 "RandomNumber: unsupported value for bits");
00081 _n = n;
00082 _f.clear();
00083 }
00084
00085
00086
00087 template<class Random> bool LessThan(Random& r, RandomNumber& t) {
00088 if (this == &t)
00089 return false;
00090 if (_n < t._n)
00091 return true;
00092 else if (_n > t._n)
00093 return false;
00094 for (size_t k = 0; ; ++k) {
00095
00096 const unsigned x = Digit(r,k);
00097 const unsigned y = t.Digit(r,k);
00098 if (x == y)
00099 continue;
00100 return x < y;
00101 }
00102 }
00103
00104
00105
00106 void Negate() {
00107 const unsigned mask = bits == w ? ~0U : ~(~0U << (bits < w ? bits : 0));
00108 for (size_t k = 0; k < Size(); ++k)
00109 _f[k] = ~_f[k] & mask;
00110
00111 _n = - _n - 1;
00112 }
00113
00114
00115
00116 size_t Size() const {
00117 return _f.size();
00118 }
00119
00120
00121
00122
00123
00124
00125
00126 template<typename RealType, typename Random> RealType Fraction(Random& r) {
00127 STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer,
00128 "RandomNumber::Fraction: invalid real type RealType");
00129 const int d = std::numeric_limits<RealType>::digits;
00130 const int k = (d + bits - 1)/bits;
00131 const int kg = (d + bits)/bits;
00132 RealType y = 0;
00133 if (Digit(r, kg - 1) & (1U << (kg * bits - d - 1)))
00134
00135 y += std::pow(RealType(2), -d);
00136 const RealType fact = std::pow(RealType(2), -bits);
00137 RealType mult = RealType(1);
00138 for (size_t i = 0; i < k; ++i) {
00139 mult *= fact;
00140 y += mult * RealType(i < k - 1 ? RawDigit(i) :
00141 RawDigit(i) & (~0U << (k * bits - d)));
00142 }
00143 return y;
00144 }
00145
00146
00147
00148
00149
00150 template<typename RealType, class Random> RealType Value(Random& r) {
00151
00152
00153
00154
00155 STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer,
00156 "RandomNumber::Value: invalid real type RealType");
00157 const int digits = std::numeric_limits<RealType>::digits,
00158 min_exp = std::numeric_limits<RealType>::min_exponent;
00159 const bool negative = Integer() < 0;
00160 if (negative)
00161 Negate();
00162 unsigned n = Integer();
00163 int lead;
00164 if (n)
00165 lead = highest_bit_idx(n);
00166 else {
00167 int i = 0;
00168 while ( Digit(r, i) == 0 && i < (-min_exp)/bits )
00169 ++i;
00170 lead = highest_bit_idx(RawDigit(i)) - (i + 1) * bits;
00171
00172 lead = lead > min_exp ? lead : min_exp;
00173 }
00174 int trail = lead - digits;
00175 RealType y;
00176 if (trail > 0) {
00177 y = RealType(n & (~0U << trail));
00178 if (n & (1U << (trail - 1)))
00179 y += std::pow(RealType(2), trail);
00180 } else {
00181 y = RealType(n);
00182 int k = (-trail)/bits;
00183 if (Digit(r, k) & (1U << ((k + 1) * bits + trail - 1)))
00184 y += std::pow(RealType(2), trail);
00185
00186 k = (-trail - 1 + bits)/bits - 1;
00187 const RealType fact = std::pow(RealType(2), -bits);
00188 RealType mult = RealType(1);
00189 for (int i = 0; i <= k; ++i) {
00190 mult *= fact;
00191 y += mult * RealType(i < k ? RawDigit(i) :
00192 RawDigit(i) & (~0U << ((k + 1) * bits + trail)));
00193 }
00194 }
00195 if (negative) {
00196 Negate();
00197 y *= -1;
00198 }
00199 return y;
00200 }
00201
00202
00203
00204
00205
00206 std::pair<double, double> Range() const {
00207 double y = Integer();
00208 const double fact = std::pow(double(2), -bits);
00209 double mult = double(1);
00210 for (size_t i = 0; i < Size(); ++i) {
00211 mult *= fact;
00212 y += mult * RawDigit(i);
00213 }
00214 return std::pair<double, double>(y, y + mult);
00215 }
00216
00217 private:
00218
00219
00220
00221 int _n;
00222
00223
00224
00225 std::vector<unsigned> _f;
00226
00227
00228
00229 template<class Random> void ExpandTo(Random& r, size_t k) {
00230 size_t l = _f.size();
00231 if (k <= l)
00232 return;
00233 _f.resize(k);
00234 for (size_t i = l; i < k; ++i)
00235 _f[i] = r.template Integer<bits>();
00236 }
00237
00238
00239
00240
00241 static int highest_bit_idx(unsigned x) {
00242 if (x == 0) return 0;
00243 int r = 1;
00244 if (x & 0xffff0000U) { x >>= 16; r += 16; }
00245 if (x & 0x0000ff00U) { x >>= 8; r += 8; }
00246 if (x & 0x000000f0U) { x >>= 4; r += 4; }
00247 if (x & 0x0000000cU) { x >>= 2; r += 2; }
00248 if (x & 0x00000002U) { r += 1; }
00249 return r;
00250 }
00251
00252
00253
00254 static const int w = std::numeric_limits<unsigned>::digits;
00255 };
00256
00257
00258
00259
00260
00261
00262
00263
00264 template<int bits> inline
00265 std::ostream& operator<<(std::ostream& os, const RandomNumber<bits>& n) {
00266 const std::ios::fmtflags oldflags = os.flags();
00267 RandomNumber<bits> t = n;
00268 unsigned i;
00269 if (t.Integer() < 0) {
00270 os << "-";
00271 t.Negate();
00272 }
00273 i = unsigned(t.Integer());
00274 os << std::hex << std::setfill('0');
00275 if (i == 0)
00276 os << "0";
00277 else {
00278 bool first = true;
00279 const int w = std::numeric_limits<unsigned>::digits;
00280 const unsigned mask = bits == w ? ~0U : ~(~0U << (bits < w ? bits : 0));
00281 for (int s = ((w + bits - 1)/bits) * bits - bits; s >= 0; s -= bits) {
00282 unsigned d = mask & (i >> s);
00283 if (d || !first) {
00284 if (first) {
00285 os << d;
00286 first = false;
00287 }
00288 else
00289 os << std::setw((bits+3)/4) << d;
00290 }
00291 }
00292 }
00293 os << ".";
00294 size_t s = t.Size();
00295 for (size_t i = 0; i < s; ++i)
00296 os << std::setw((bits+3)/4) << t.RawDigit(i);
00297 os << "..." << std::setfill(' ');
00298 os.flags(oldflags);
00299 return os;
00300 }
00301 }
00302 #endif // RANDOMNUMBER_HPP