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