...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
boost::uniform_smallint
// In header: <boost/random/uniform_smallint.hpp> template<typename IntType = int> class uniform_smallint { public: // types typedef IntType input_type; typedef IntType result_type; // construct/copy/destruct uniform_smallint(IntType = 0, IntType = 9); // public member functions result_type min() const; result_type max() const; void reset(); template<typename Engine> result_type operator()(Engine &); };
The distribution function uniform_smallint models a random distribution . On each invocation, it returns a random integer value uniformly distributed in the set of integer numbers {min, min+1, min+2, ..., max}. It assumes that the desired range (max-min+1) is small compared to the range of the underlying source of random numbers and thus makes no attempt to limit quantization errors.
Let rout=(max-min+1) the desired range of integer numbers, and let rbase be the range of the underlying source of random numbers. Then, for the uniform distribution, the theoretical probability for any number i in the range rout will be pout(i) = 1/rout. Likewise, assume a uniform distribution on rbase for the underlying source of random numbers, i.e. pbase(i) = 1/rbase. Let pout_s(i) denote the random distribution generated by uniform_smallint
. Then the sum over all i in rout of (pout_s(i)/pout(i) - 1)2 shall not exceed rout/rbase2 (rbase mod rout)(rout - rbase mod rout).
The template parameter IntType shall denote an integer-like value type.
Note: The property above is the square sum of the relative differences in probabilities between the desired uniform distribution pout(i) and the generated distribution pout_s(i). The property can be fulfilled with the calculation (base_rng mod rout), as follows: Let r = rbase mod rout. The base distribution on rbase is folded onto the range rout. The numbers i < r have assigned (rbase div rout)+1 numbers of the base distribution, the rest has only (rbase div rout). Therefore, pout_s(i) = ((rbase div rout)+1) / rbase for i < r and pout_s(i) = (rbase div rout)/rbase otherwise. Substituting this in the above sum formula leads to the desired result.
Note: The upper bound for (rbase mod rout) (rout - rbase mod rout) is rout2/4. Regarding the upper bound for the square sum of the relative quantization error of rout3/(4*rbase2), it seems wise to either choose rbase so that rbase > 10*rout2 or ensure that rbase is divisible by rout.