10 #if !defined(EXRANDOM_U_RAND_HPP) 11 #define EXRANDOM_U_RAND_HPP 1 30 # pragma warning (push) 31 # pragma warning (disable: 4127 4244 4267) 57 template<
typename RealType>
58 inline int real_digits() {
59 static_assert(!std::numeric_limits<RealType>::is_integer,
60 "invalid real type RealType");
61 return std::numeric_limits<RealType>::digits;
64 template<
typename RealType>
65 inline std::float_round_style real_round_style() {
66 static_assert(!std::numeric_limits<RealType>::is_integer,
67 "invalid real type RealType");
68 return std::numeric_limits<RealType>::round_style;
71 #if defined(MPREAL_VERSION_STRING) 74 inline int real_digits<mpfr::mpreal>()
75 {
return std::numeric_limits<mpfr::mpreal>::digits(); }
78 inline std::float_round_style real_round_style<mpfr::mpreal>()
79 {
return std::numeric_limits<mpfr::mpreal>::round_style(); }
82 template<
typename RealType>
83 inline RealType real_ldexp(
const RealType& x,
int n) {
84 static_assert(!std::numeric_limits<RealType>::is_integer,
85 "invalid real type RealType");
86 using std::ldexp;
return ldexp(x, n);
105 template<
typename digit_gen>
class u_rand {
114 u_rand(digit_gen& D) : _s(1), _n(0U), _D(D) {}
124 _s = 1; _n = 0U; _d.clear();
135 if (
this == &t)
return;
137 std::swap(_s, t._s); std::swap(_n, t._n); _d.swap(t._d);
142 int sign()
const {
return _s; }
168 template<
typename Generator>
169 uint_t
digit(Generator& g,
size_t k) {
170 for (
size_t i =
ndigits(); i <= k; ++i) _d.push_back(_D(g));
195 template<
typename Generator>
197 if (
this == &t)
return false;
198 if (_s != t._s)
return _s < t._s;
199 if (_n != t._n)
return (_s < 0) ^ (_n < t._n);
200 for (
size_t k = 0;; ++k) {
202 if (a != b)
return (_s < 0) ^ (a < b);
212 template<
typename Generator>
214 if (_s < 0)
return true;
215 if (_n > 0)
return false;
232 template<
typename Generator>
235 uint_t d =
digit(g, k);
236 if (d <= (bm1 - 1U) / 2U)
return true;
237 if (d > bm1 / 2U)
return false;
253 template<
typename Generator>
254 int compare(Generator& g,
long long u1,
long long u2,
long long v) {
255 static const long long lbase =
base;
256 u1 = (std::max)(0LL, _s * u1 - (
long long)(_n) * v);
257 u2 = (std::min)( v , _s * u2 - (
long long)(_n) * v);
258 for (
size_t k = 0;; ++k) {
259 if (u1 >= v)
return -_s;
260 if (u2 <= 0)
return _s;
261 if (u1 <= 0 && u2 >= v)
return 0;
262 long long d =
digit(g, k);
263 u1 = (std::max)(0LL, u1 * lbase - d * v);
264 u2 = (std::min)( v , u2 * lbase - d * v);
280 template<
typename Generator>
281 bool less_than(Generator& g,
long long u0,
long long c,
long long v,
285 if (r < 0)
return true;
286 if (r > 0)
return false;
307 static_assert(bm1 <= 0xffUL,
"base must not be larger than 256");
308 long long num = _n, den = 1LL;
309 for (
size_t j = 0; j < k; ++j) {
310 num =
base * num + _d[j];
313 if (_s < 0) num = -num - 1LL;
314 return std::pair<long long, long long>(num, den);
349 template<
typename Generator>
350 std::pair<long long, long long>
rational(Generator& g,
size_t k) {
351 if (k)
digit(g, k - 1);
364 template<
typename RealType> std::pair<RealType, RealType>
range()
const {
365 static_assert(!std::numeric_limits<RealType>::is_integer,
366 "invalid real type RealType");
367 RealType x = 0, d = 1,
368 v = digit_gen::template invrealbase<RealType>();
369 for (
size_t k = _d.size(); k--;) {
374 return std::pair<RealType, RealType>(_s > 0 ? x : -(x + d),
375 _s > 0 ? (x + d) : -x);
386 template<
typename RealType>
388 auto r = range<RealType>();
389 return (r.first + r.second) / 2;
403 template<
typename RealType,
typename Generator>
405 if (k)
digit(g, k - 1U);
406 return midpoint<RealType>();
453 template<
typename RealType,
typename Generator>
454 RealType
value(Generator& g, std::float_round_style rnd,
int& flag) {
457 static_assert(!std::numeric_limits<RealType>::is_integer,
458 "invalid real type RealType");
459 static const uint_t radix = std::numeric_limits<RealType>::radix;
460 static const bool binary = radix == 2U;
462 static const int xbits = binary ? bits : 1;
463 static_assert((binary && power_of_two) ||
464 (radix ==
base && (
base & 1U) == 0U),
465 "require RealType::radix = 2 and base a power of two " 466 "or RealType::radix = base = even");
469 static_assert(binary ? std::numeric_limits<RealType>::max_exponent >= 32 :
471 std::numeric_limits<RealType>::max_exponent >= 10 :
true,
472 "RealType::max_exponent too small");
474 static const int digits = real_digits<RealType>(),
477 min_exp = std::numeric_limits<RealType>::min_exponent < -(1<<30) ?
478 -(1<<30) : std::numeric_limits<RealType>::min_exponent;
482 rnd == std::round_to_nearest ? 0 :
483 rnd == std::round_toward_zero ? -1 :
484 rnd == std::round_toward_infinity ? _s :
485 rnd == std::round_toward_neg_infinity ? -_s :
490 lead = highest_bit_idx(_n);
494 while (n) {++lead; n /= radix;}
498 while (
digit(g,
size_t(i)) == 0 && i < (-min_exp)/xbits ) ++i;
499 lead = binary ? highest_bit_idx(_d[i]) : _d[i] ? 1 : 0;
500 lead -= (i + 1) * xbits;
501 lead = lead >= min_exp ? lead :
504 std::numeric_limits<RealType>::has_denorm == std::denorm_present ?
505 min_exp : min_exp - 1;
508 int trail = lead - (lead >= min_exp ? digits : 0);
511 flag = int((trail > 0 ? _n >> (trail - 1) :
512 digit(g,
size_t( (-trail)/xbits ))
513 >> (xbits - 1 - (-trail) % xbits)) & 1U);
517 for (
int t = 1; t < trail; ++t) n /= radix;
518 flag = int((n % radix) / (radix >> 1));
520 flag = int(
digit(g,
size_t(-trail)) / (radix >> 1));
522 flag = flag == 0 ? -1 : 1;
524 RealType z(flag > 0 ? 1 : 0);
529 z = real_ldexp<RealType>(z, trail) + (_n & (~uint_t(0) << trail));
532 for (
int t = 0; t < trail; ++t) n /= radix;
534 for (
int t = 0; t < trail; ++t) z *= radix;
536 }
else if (lead >= min_exp) {
538 size_t k = size_t((-trail-1) / xbits);
540 z = real_ldexp<RealType>(z,
int(k + 1) * xbits + trail) +
541 (
digit(g, k) & (~uint_t(0) << ((k + 1) * xbits + trail)));
542 while (k--) z = real_ldexp<RealType>(z, -xbits) + _d[k];
543 z = real_ldexp<RealType>(z, -xbits) + _n;
546 while (k--) z = z / radix + _d[k];
550 z *= std::numeric_limits<RealType>::min();
574 template<
typename RealType,
typename Generator>
575 RealType
value(Generator& g,
int& flag) {
576 return value<RealType, Generator>(g, real_round_style<RealType>(), flag);
593 template<
typename RealType,
typename Generator>
596 return value<RealType, Generator>(g, real_round_style<RealType>(), flag);
611 return bareprint(*
this) +
"...";
627 template<
typename Generator>
643 return bareprint(x) + (trunc ?
"(+)" :
"(-)");
659 { os << x.
print();
return os; }
664 static const uint_t
base = digit_gen::base;
669 std::vector<uint_t> _d;
671 static const uint_t bm1 = digit_gen::max_value;
672 static const int bits = digit_gen::bits;
673 static const bool power_of_two = digit_gen::power_of_two;
674 static std::string bareprint(
const u_rand& x) {
677 static_assert(bm1 < 15U || (power_of_two && (bits % 4 == 0)),
678 "Output requires base < 16 or base = a power of 16");
679 std::ostringstream os;
680 os << (x._s < 0 ?
'-' :
'+') << std::setfill(
'0') << std::hex;
681 if (x._n == 0 || bits >= 4)
684 std::ostringstream osint;
689 osint << n % (
base ?
base : uint_t(1));
692 std::string sint = osint.str();
693 std::reverse(sint.begin(), sint.end());
696 if (x._d.size()) os <<
'.';
697 for (
size_t k = 0; k < x._d.size(); ++k)
698 os << std::setw((bits+3)/4) << x._d[k];
706 #if defined(_MSC_VER) 707 # pragma warning (pop) 710 #endif // EXRANDOM_U_RAND_HPP
std::string print() const
uint_t digit(Generator &g, size_t k)
std::pair< RealType, RealType > range() const
Definition of digit_arithmetic.
RealType midpoint(Generator &g, size_t k)
std::pair< long long, long long > rational(Generator &g, size_t k)
bool less_than(Generator &g, u_rand &t)
bool truncatep(Generator &g, size_t k)
std::pair< long long, long long > rational() const
A class to sample integers [0,m).
std::string print_fixed(Generator &g, size_t k)
uint_t & rawdigit(size_t k)
uint_t rawdigit(size_t k) const
friend std::ostream & operator<<(std::ostream &os, const u_rand &x)
RealType value(Generator &g, std::float_round_style rnd, int &flag)
int compare(Generator &g, long long u1, long long u2, long long v)
std::pair< long long, long long > rawrational(size_t k) const
RealType value(Generator &g, int &flag)
void refine(Generator &g)
RealType value(Generator &g)
The machinery to handle u-rands, arbitrary precision random deviates.
void set_integer(unsigned n)
bool less_than_half(Generator &g)
bool less_than(Generator &g, long long u0, long long c, long long v, i_rand< digit_gen > &h)