ExRandom  3.0
u_rand.hpp
Go to the documentation of this file.
1 /**
2  * @file u_rand.hpp
3  * @author Charles Karney <charles.karney@sri.com>
4  * @brief Definition of u_rand
5  *
6  * Copyright (c) Charles Karney (2014-2020) and licensed under the MIT/X11
7  * License. For more information, see http://exrandom.sourceforge.net/
8  */
9 
10 #if !defined(EXRANDOM_U_RAND_HPP)
11 #define EXRANDOM_U_RAND_HPP 1
12 
13 #include <iostream> // for std::ostream, etc.
14 #include <string> // for print routines
15 #include <sstream> // for print routines
16 #include <iomanip> // for print routines
17 #include <algorithm> // for std::swap, std::max
18 #include <utility> // for std::pair
19 #include <vector> // for fraction in u_rand
20 #include <limits> // for conversion to floating point
21 #include <cmath> // for std::ldexp
22 
24 #include <exrandom/i_rand.hpp>
25 
26 #if defined(_MSC_VER)
27 // Squelch warnings about constant conditional expressions and possible loss of
28 // data. (Could suppress these with casts but then we lose the mixed type
29 // special cases offered by mpreal.)
30 # pragma warning (push)
31 # pragma warning (disable: 4127 4244 4267)
32 #endif
33 
34 namespace exrandom {
35 
36 #if !defined(DOXYGEN)
37  // This is a bunch or support utilities to enable u_rand::value to work
38  // across multiple types of floating point numbers. So far it's been tested
39  // with
40  //
41  // float, double, long double
42  // mpfr::mpreal
43  // boost's mpfr_float, mpf_float, cpp_dec_float, and float128
44  //
45  // The issues are
46  // mpreal has a variable precision and rounding style.
47  // cpp_dec_float has a decimal base
48  // for efficiency we avoid explicit casting in mixed mode operations
49  // we want to be able to select between ldexp, scalbn, and pow
50  //
51  // For the right specializations to be defined, this file must be included
52  // *after* the one that defines the floating point type. The checking here
53  // depends on MPREAL_VERSION_STRING for mpfr::mpreal (this appeared in
54  // version 3.5.7, June 3, 2014). It's probable that C++11 template magic
55  // using SFINAE could remove this restrication.
56 
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;
62  }
63 
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;
69  }
70 
71 #if defined(MPREAL_VERSION_STRING)
72  // Specializations for mprf::mpreal
73  template<>
74  inline int real_digits<mpfr::mpreal>()
75  { return std::numeric_limits<mpfr::mpreal>::digits(); }
76 
77  template<>
78  inline std::float_round_style real_round_style<mpfr::mpreal>()
79  { return std::numeric_limits<mpfr::mpreal>::round_style(); }
80 #endif
81 
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);
87  // Alternatives (assuming radix == 2 for scalbn):
88  // using std::pow; return x * pow(RealType(2), n);
89  // using std::scalbn; return scalbn(x, n);
90  }
91 
92 #endif
93 
94  /**
95  * @brief The machinery to handle u-rands, arbitrary precision random
96  * deviates.
97  *
98  * A u_rand is represented in base b as s (n +
99  * &sum;<sub>k=0</sub><sup>K&minus;1</sup> d<sub>k</sub>
100  * b<sup>&minus;k&minus;1</sup> + b<sup>&minus;K</sup>U) where s = &plusmn;1,
101  * n and K are non-negative integers, and d<sub>k</sub> &isin; [0,b).
102  *
103  * @tparam digit_gen the type of digit generator.
104  */
105  template<typename digit_gen> class u_rand {
106  public:
107  /**
108  * The constructor.
109  *
110  * @param D A reference to the digit generator to be used.
111  *
112  * The initial state represents a random deviate uniform in (0,1)
113  */
114  u_rand(digit_gen& D) : _s(1), _n(0U), _D(D) {}
115  /**
116  * Reset to the initial state.
117  *
118  * @return the u_rand itself.
119  *
120  * The returned result allows the idiom x.init().less_than(g, y) to be
121  * used.
122  */
124  _s = 1; _n = 0U; _d.clear();
125  return *this;
126  }
127  /**
128  * Swap two u_rands.
129  *
130  * @param t the u_rand to swap with.
131  *
132  * The digit generator is not part of the swap.
133  */
134  void swap(u_rand& t) {
135  if (this == &t) return;
136  // Don't swap _D, these should be refs to the same object
137  std::swap(_s, t._s); std::swap(_n, t._n); _d.swap(t._d);
138  }
139  /**
140  * @return sign of the u_rand (either +1 or -1).
141  */
142  int sign() const { return _s; }
143  /**
144  * Change the sign of the u_rand.
145  */
146  void negate() { _s = -_s; }
147  /**
148  * @return unsigned integer part of the u_rand.
149  */
150  unsigned integer() const { return _n; }
151  /**
152  * Set the integer part of the u_rand.
153  * @param n the new value of the (unsigned) integer part.
154  */
155  void set_integer(unsigned n) { _n = n; }
156  /**
157  * @return the number of digits in the fraction.
158  */
159  size_t ndigits() const { return _d.size(); }
160  /**
161  * The k'th digit generating it if necessary.
162  *
163  * @tparam Generator the type of g.
164  * @param g the random generator engine used to generate the digit.
165  * @param k which digit of the fraction to return (counting from 0).
166  * @return the value of the digit.
167  */
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));
171  return _d[k];
172  }
173  /**
174  * The k'th digit (which must already have been generated).
175  *
176  * @param k which digit of the fraction to return (counting from 0).
177  * @return the value of the digit.
178  */
179  uint_t rawdigit(size_t k) const { return _d[k]; }
180  /**
181  * A reference to the k'th digit (which must already be generated).
182  *
183  * @param k which digit of the fraction to return (counting from 0).
184  * @return a reference to the k'th digit.
185  */
186  uint_t& rawdigit(size_t k) { return _d[k]; }
187  /**
188  * Test *this &lt; t.
189  *
190  * @tparam Generator the type of g.
191  * @param g the random generator engine used to generate the digit.
192  * @param t the u_rand to compare with.
193  * @return *this &lt; t.
194  */
195  template<typename Generator>
196  bool less_than(Generator& g, u_rand& t) {
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) {
201  uint_t a = digit(g, k), b = t.digit(g, k);
202  if (a != b) return (_s < 0) ^ (a < b);
203  }
204  }
205  /**
206  * Test *this &lt; 1/2.
207  *
208  * @tparam Generator the type of g.
209  * @param g the random generator engine used to generate the digit.
210  * @return *this &lt; 1/2.
211  */
212  template<typename Generator>
213  bool less_than_half(Generator& g) {
214  if (_s < 0) return true;
215  if (_n > 0) return false;
216  return truncatep(g, size_t(0));
217  }
218  /**
219  * Determine how the result should be rounded.
220  *
221  * @tparam Generator the type of g.
222  * @param g the random generator engine used to generate the digit.
223  * @param k which rounding digit.
224  * @return true if the result can be truncated towards zero.
225  *
226  * Look at the kth (and subsequent) digits to determine whether the (k-1)th
227  * digit should retained (i.e., the result rounded towards zero) or
228  * incremented (i.e., the result should rounded away from zero). If k = 0,
229  * then the (k-1)th digit affects the integer part of the result. If base
230  * is even only one digit is tested.
231  */
232  template<typename Generator>
233  bool truncatep(Generator& g, size_t k) {
234  for (;; ++k) {
235  uint_t d = digit(g, k);
236  if (d <= (bm1 - 1U) / 2U) return true;
237  if (d > bm1 / 2U) return false;
238  }
239  }
240  /**
241  * Compare *this with u1/v and u2/v.
242  *
243  * @tparam Generator the type of g.
244  * @param g the random generator engine.
245  * @param u1 the numerator of the first fraction.
246  * @param u2 the numerator of the second fraction.
247  * @param v the denominator of the fractions.
248  * @return -1 if *this &lt; u1/v, +1 if frac(*this) &gt; u2/v, and 0
249  * otherwise.
250  *
251  * This function requires v &gt; 0, u2 &gt; u1.
252  */
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; // u1/v >= 1, so *this < u1/v
260  if (u2 <= 0) return _s; // u2/v <= 0, so *this > u2/v
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);
265  }
266  }
267  /**
268  * Compare *this with a i_rand.
269  *
270  * @tparam Generator the type of g.
271  * @param g the random generator engine.
272  * @param u0 the offset in the numerator.
273  * @param c the multiplier for the i_rand.
274  * @param v the denominator of the fraction.
275  * @param h the i_rand.
276  * @return *this &lt; u/v, where u = u0 + h * c.
277  *
278  * This function requires v &gt; 0, c &gt; 0.
279  */
280  template<typename Generator>
281  bool less_than(Generator& g, long long u0, long long c, long long v,
282  i_rand<digit_gen>& h) {
283  for (;;) {
284  int r = compare(g, u0 + h.min()*c, u0 + h.max()*c, v);
285  if (r < 0) return true;
286  if (r > 0) return false;
287  h.refine(g);
288  }
289  }
290  /**
291  * The lower end of the range as a rational.
292  *
293  * @param k the number of digits to include from the fractional part of the
294  * number.
295  * @return the lower end of the range represented by the u_rand with a
296  * given number of (already generated) digits in the fraction as a
297  * rational (a std::pair of the numerator and denominator).
298  *
299  * The fraction is not in lowest terms. Thus the upper end can be found by
300  * adding 1 to the numerator. Overflow is possible in this routine and no
301  * attempt is made to detect this.
302 
303  * This function requires that base &le; 2<sup>8</sup> (in an attempt to
304  * avoid overflow).
305  */
306  std::pair<long long, long long> rawrational(size_t k) const {
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];
311  den *= base;
312  }
313  if (_s < 0) num = -num - 1LL;
314  return std::pair<long long, long long>(num, den);
315  }
316  /**
317  * The lower end of the range as a rational.
318  *
319  * @return the lower end of the range represented by the u_rand as a
320  * rational (a std::pair of the numerator and denominator).
321  *
322  * The fraction is not in lowest terms. Thus the upper end can be found by
323  * adding 1 to the numerator. Overflow is possible in this routine and no
324  * attempt is made to detect this.
325  *
326  * This function requires that base &le; 2<sup>8</sup> (in an attempt to
327  * avoid overflow).
328  */
329  std::pair<long long, long long> rational() const
330  { return rawrational(ndigits());}
331  /**
332  * The lower end of the range as a rational.
333  *
334  * @tparam Generator the type of g.
335  * @param g the random generator engine.
336  * @param k the number of digits to include from the fractional part of the
337  * number.
338  * @return the lower end of the range represented by the u_rand with a
339  * given number of digits in the fraction as a rational (a std::pair of
340  * the numerator and denominator).
341  *
342  * The fraction is not in lowest terms. Thus the upper end can be found by
343  * adding 1 to the numerator. Overflow is possible in this routine and no
344  * attempt is made to detect this.
345  *
346  * This function requires that base &le; 2<sup>8</sup> (in an attempt to
347  * avoid overflow).
348  */
349  template<typename Generator>
350  std::pair<long long, long long> rational(Generator& g, size_t k) {
351  if (k) digit(g, k - 1);
352  { return rawrational(k); }
353  }
354  /**
355  * The range.
356  *
357  * @tparam RealType the floating point type for the ends of the range.
358  * @return the range represented by the u_rand as a std::pair.
359  *
360  * The calculations of the end points are done using ordinary floating
361  * point arithmetic. The results will be reasonably close to the true end
362  * points.
363  */
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--;) {
370  x = (_d[k] + x) * v;
371  d *= v;
372  }
373  x += _n;
374  return std::pair<RealType, RealType>(_s > 0 ? x : -(x + d),
375  _s > 0 ? (x + d) : -x);
376  }
377  /**
378  * The midpoint of the range.
379  *
380  * @tparam RealType the floating point type for the result.
381  * @return the midpoint of the current range.
382  *
383  * The calculation of the midpoint is done using ordinary floating point
384  * arithmetic. The result will be reasonably close to the true midpoint.
385  */
386  template<typename RealType>
387  RealType midpoint() {
388  auto r = range<RealType>();
389  return (r.first + r.second) / 2;
390  }
391  /**
392  * The midpoint of the range.
393  *
394  * @tparam RealType the floating point type for the result.
395  * @tparam Generator the type of g.
396  * @param g the random generator engine.
397  * @param k make sure there are at least k digits in the fraction.
398  * @return the midpoint of the resulting range.
399  *
400  * The calculation of the midpoint is done using ordinary floating point
401  * arithmetic. The result will be reasonably close to the true midpoint.
402  */
403  template<typename RealType, typename Generator>
404  RealType midpoint(Generator& g, size_t k) {
405  if (k) digit(g, k - 1U);
406  return midpoint<RealType>();
407  }
408 
409  /**
410  * Return the value of the u_rand with specified rounding as a floating
411  * point number of type RealType and, if necessary, creating additional
412  * digits of the number. Also return inexact flag to indicate whether the
413  * rounded result is greater or less than the true result.
414  *
415  * @tparam RealType the floating point type to convert to.
416  * @tparam Generator the type of g.
417  * @param g the random generator engine.
418  * @param rnd the rounding mode; by default this is the rounding mode for
419  * RealType.
420  * @param[out] flag the inexact flag, +1 (resp. -1) if rounded result is
421  * greater (resp. less) than the true result.
422  * @return the value of the u_rand rounded to a RealType.
423  *
424  * This function is only implemented if the base is a power of two for
425  * conventional floating point types (which have radix = 2). If the
426  * floating point radix is not two (e.g., radix = 10), then the base needs
427  * to match the radix and be even. The meaning for the inexact flag is the
428  * same as in the MPFR library.
429  *
430  * Possible values for rnd are
431  * - std::round_indeterminate, taken to mean round away from zero
432  * - std::round_toward_zero
433  * - std::round_to_nearest, this is the default for float, double, etc.
434  * - std::round_toward_infinity
435  * - std::round_toward_neg_infinity
436  *
437  * The conversions have been tested for
438  * - float, double, long double
439  * - mpfr::mpreal
440  * - boost's mpfr_float, mpf_float, cpp_dec_float, and float128
441  * .
442  * RealType needs to support the following operations:
443  * - std::numeric_limits<RealType> must include min(), radix, digits,
444  * min_exponent, max_exponent, has_denorm, round_style
445  * - std::numeric_limits<RealType>::is_integer is false
446  * - basic arithmetic: negation, addition
447  * - ldexp(const RealType&, int) if radix is 2; multiplication otherwise
448  * .
449  * Special treatment is included for
450  * - mpfr::mpreal (std::numeric_limits has digits() and round_style()
451  * instead of digits and round_style)
452  **********************************************************************/
453  template<typename RealType, typename Generator>
454  RealType value(Generator& g, std::float_round_style rnd, int& flag) {
455  // Need to treat rounding explicitly since the missing digits always
456  // imply rounding up.
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;
461  // How many RealType digits fit into a u_rand digit
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");
467  // Check that overflow cannot happen (skip this check if radix is not 2
468  // or 10)
469  static_assert(binary ? std::numeric_limits<RealType>::max_exponent >= 32 :
470  radix == 10U ?
471  std::numeric_limits<RealType>::max_exponent >= 10 : true,
472  "RealType::max_exponent too small");
473  // std::numeric_limits<RealType>::digits isn't defined for mpreals
474  static const int digits = real_digits<RealType>(),
475  // Put a sane lower limit on min_exp. Boost's gmp_float has
476  // min_exponent = -2^63 which doesn't fit into an int.
477  min_exp = std::numeric_limits<RealType>::min_exponent < -(1<<30) ?
478  -(1<<30) : std::numeric_limits<RealType>::min_exponent;
479  // round_dir is rounding direction for magnitude of number:
480  // -1 = down, 0 = nearest, 1 = up
481  flag =
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 :
486  +1; // round_indeterminate taken to mean away from zero
487  int lead; // Position of leading bit (0.5 = position 0)
488  if (_n) {
489  if (binary)
490  lead = highest_bit_idx(_n);
491  else {
492  uint_t n = _n;
493  lead = 0;
494  while (n) {++lead; n /= radix;}
495  }
496  } else {
497  int i = 0;
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 :
502  // To handle denormalized numbers set lead = max(lead, min_exp); if
503  // no denormalized min_exp - 1 marks underflow.
504  std::numeric_limits<RealType>::has_denorm == std::denorm_present ?
505  min_exp : min_exp - 1;
506  }
507  // Position of rounding bit (0.5 = position 0)
508  int trail = lead - (lead >= min_exp ? digits : 0);
509  if (flag == 0) { // Get the rounding bit
510  if (binary)
511  flag = int((trail > 0 ? _n >> (trail - 1) :
512  digit(g, size_t( (-trail)/xbits ))
513  >> (xbits - 1 - (-trail) % xbits)) & 1U);
514  else {
515  if (trail > 0) {
516  uint_t n = _n;
517  for (int t = 1; t < trail; ++t) n /= radix;
518  flag = int((n % radix) / (radix >> 1));
519  } else
520  flag = int(digit(g, size_t(-trail)) / (radix >> 1));
521  }
522  flag = flag == 0 ? -1 : 1;
523  }
524  RealType z(flag > 0 ? 1 : 0);
525  // Result is given by the bits in [trail+1, lead] + rounding, where
526  // rounding = z * 2^trail
527  if (trail >= 0) {
528  if (binary)
529  z = real_ldexp<RealType>(z, trail) + (_n & (~uint_t(0) << trail));
530  else {
531  uint_t n = _n;
532  for (int t = 0; t < trail; ++t) n /= radix;
533  z += n;
534  for (int t = 0; t < trail; ++t) z *= radix;
535  }
536  } else if (lead >= min_exp) {
537  // digit with bit trail+1
538  size_t k = size_t((-trail-1) / xbits);
539  if (binary) {
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;
544  } else {
545  z += digit(g, k);
546  while (k--) z = z / radix + _d[k];
547  z = z / radix + _n;
548  }
549  } else
550  z *= std::numeric_limits<RealType>::min(); // Handle underflow
551  flag *= _s;
552  return _s * z;
553  }
554 
555  /**
556  * Return the value of the u_rand rounded to nearest floating point number
557  * of type RealType and, if necessary, creating additional digits of the
558  * number. Also return inexact flag to indicate whether the rounded result
559  * is greater or less than the true result.
560  *
561  * @tparam RealType the floating point type to convert to.
562  * @tparam Generator the type of g.
563  * @param g the random generator engine.
564  * @param[out] flag the inexact flag, +1 (resp. -1) if rounded result is
565  * greater (resp. less) than the true result.
566  * @return the value of the u_rand rounded to a RealType.
567  *
568  * This function is only implemented if the base is a power of two for
569  * conventional floating point types (which have radix = 2). If the
570  * floating point radix is not two (e.g., radix = 10), then the base needs
571  * to match the radix and be even. The meaning for the inexact flag is the
572  * same as in the MPFR library.
573  **********************************************************************/
574  template<typename RealType, typename Generator>
575  RealType value(Generator& g, int& flag) {
576  return value<RealType, Generator>(g, real_round_style<RealType>(), flag);
577  }
578  /**
579  * Return the value of the u_rand rounded to nearest floating point number
580  * of type RealType and, if necessary, creating additional digits of the
581  * number.
582  *
583  * @tparam RealType the floating point type to convert to.
584  * @tparam Generator the type of g.
585  * @param g the random generator engine.
586  * @return the value of the u_rand rounded to a RealType.
587  *
588  * This function is only implemented if the base is a power of two for
589  * conventional floating point types (which have radix = 2). If the
590  * floating point radix is not two (e.g., radix = 10), then the base needs
591  * to match the radix and be even.
592  **********************************************************************/
593  template<typename RealType, typename Generator>
594  RealType value(Generator& g) {
595  int flag;
596  return value<RealType, Generator>(g, real_round_style<RealType>(), flag);
597  }
598 
599  /**
600  * Print a u_rand in u-rand format.
601  *
602  * @return the printed representation of the current number.
603  *
604  * This prints the number to the existing precision followed by an ellipsis
605  * "&hellip;" to indicate the digits which haven't been generated yet.
606  * This function is only implemented if the base is less than 16 or a power
607  * of 16. The representation uses the base of the u_rand or hexadecimal if
608  * base &gt; 16.
609  */
610  std::string print() const {
611  return bareprint(*this) + "...";
612  }
613  /**
614  * Print a u_rand in rounded fixed point format.
615  *
616  * @tparam Generator the type of g.
617  * @param g the random generator engine.
618  * @param k
619  * @return the printed fixed point representation rounded to k digits.
620  *
621  * This prints the number with k digits in the fraction and (+)
622  * (resp. (&minus;)) to indicate that the true result is further from
623  * (resp. closer to) zero. This function is only implemented if the base
624  * is less than 16 or a power of 16. The representation uses the base of
625  * the u_rand or hexadecimal if base &gt; 16.
626  */
627  template<typename Generator>
628  std::string print_fixed(Generator& g, size_t k) {
629  bool trunc = truncatep(g, k);
630  u_rand x(*this);
631  x._d.resize(k);
632  if (!trunc) {
633  while (k--) {
634  if (x._d[k] < bm1) {
635  ++x._d[k];
636  break;
637  } else
638  x._d[k] = uint_t(0);
639  }
640  if (++k == 0U)
641  ++x._n;
642  }
643  return bareprint(x) + (trunc ? "(+)" : "(-)");
644  }
645  /**
646  * Print a u_rand in u-rand format.
647  *
648  * @param os an output stream.
649  * @param x a u_rand.
650  * @return os.
651  *
652  * This prints the number to the existing precision followed by an ellipsis
653  * "..." to indicate the digits which haven't been generated yet. This
654  * function is only implemented if the base is less than 16 or a power of
655  * 16. The representation uses the base of the u_rand or hexadecimal if
656  * base &gt; 16.
657  **********************************************************************/
658  friend std::ostream& operator<<(std::ostream& os, const u_rand& x)
659  { os << x.print(); return os; }
660 
661  /**
662  * The base of the digit generator.
663  */
664  static const uint_t base = digit_gen::base;
665 
666  private:
667  int _s; // the sign
668  unsigned _n; // the integer part; N.B. _n >= 0
669  std::vector<uint_t> _d; // the digits in the fraction
670  digit_gen& _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) {
675  // Print in the current base, except that use hexadecimal for base > 16.
676  // For that reason if base > 16, we require that it be a power of 16.
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)
682  os << x._n;
683  else {
684  std::ostringstream osint;
685  osint << std::hex;
686  int n = x._n;
687  while (n) {
688  // Avoid silly warnings from the compiler when base == 0
689  osint << n % (base ? base : uint_t(1));
690  n /= base ? base : uint_t(1);
691  }
692  std::string sint = osint.str();
693  std::reverse(sint.begin(), sint.end());
694  os << sint;
695  }
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];
699  return os.str();
700  }
701 
702  };
703 
704 }
705 
706 #if defined(_MSC_VER)
707 # pragma warning (pop)
708 #endif
709 
710 #endif // EXRANDOM_U_RAND_HPP
RealType midpoint()
Definition: u_rand.hpp:387
int max() const
Definition: i_rand.hpp:106
std::string print() const
Definition: u_rand.hpp:610
uint_t digit(Generator &g, size_t k)
Definition: u_rand.hpp:169
std::pair< RealType, RealType > range() const
Definition: u_rand.hpp:364
Definition of digit_arithmetic.
RealType midpoint(Generator &g, size_t k)
Definition: u_rand.hpp:404
static const uint_t base
Definition: u_rand.hpp:664
std::pair< long long, long long > rational(Generator &g, size_t k)
Definition: u_rand.hpp:350
bool less_than(Generator &g, u_rand &t)
Definition: u_rand.hpp:196
int sign() const
Definition: u_rand.hpp:142
bool truncatep(Generator &g, size_t k)
Definition: u_rand.hpp:233
std::pair< long long, long long > rational() const
Definition: u_rand.hpp:329
A class to sample integers [0,m).
Definition: i_rand.hpp:44
size_t ndigits() const
Definition: u_rand.hpp:159
void swap(u_rand &t)
Definition: u_rand.hpp:134
u_rand & init()
Definition: u_rand.hpp:123
std::string print_fixed(Generator &g, size_t k)
Definition: u_rand.hpp:628
uint_t & rawdigit(size_t k)
Definition: u_rand.hpp:186
int min() const
Definition: i_rand.hpp:102
uint_t rawdigit(size_t k) const
Definition: u_rand.hpp:179
The common namespace.
Definition: aux_info.hpp:18
friend std::ostream & operator<<(std::ostream &os, const u_rand &x)
Definition: u_rand.hpp:658
u_rand(digit_gen &D)
Definition: u_rand.hpp:114
RealType value(Generator &g, std::float_round_style rnd, int &flag)
Definition: u_rand.hpp:454
unsigned integer() const
Definition: u_rand.hpp:150
int compare(Generator &g, long long u1, long long u2, long long v)
Definition: u_rand.hpp:254
std::pair< long long, long long > rawrational(size_t k) const
Definition: u_rand.hpp:306
RealType value(Generator &g, int &flag)
Definition: u_rand.hpp:575
void refine(Generator &g)
Definition: i_rand.hpp:204
RealType value(Generator &g)
Definition: u_rand.hpp:594
The machinery to handle u-rands, arbitrary precision random deviates.
Definition: u_rand.hpp:105
void set_integer(unsigned n)
Definition: u_rand.hpp:155
bool less_than_half(Generator &g)
Definition: u_rand.hpp:213
Definition of i_rand.
bool less_than(Generator &g, long long u0, long long c, long long v, i_rand< digit_gen > &h)
Definition: u_rand.hpp:281