31#ifndef BOOST_165_RANDOM_DETAIL_INT_FLOAT_PAIR_HPP
32#define BOOST_165_RANDOM_DETAIL_INT_FLOAT_PAIR_HPP
34#include <boost/integer.hpp>
35#include <boost/integer/integer_mask.hpp>
36#include <boost/mpl/bool.hpp>
37#include <boost/random/detail/integer_log2.hpp>
38#include <boost/random/detail/signed_unsigned_tools.hpp>
39#include <boost/random/uniform_01.hpp>
40#include <boost/random/uniform_int_distribution.hpp>
41#include <boost/type_traits/is_integral.hpp>
42#include <boost/type_traits/make_unsigned.hpp>
52 template <
class Engine>
53 inline typename boost::make_unsigned<typename Engine::result_type>::type
54 generate_one_digit_v165(Engine& eng, std::size_t bits)
56 typedef typename Engine::result_type base_result;
57 typedef typename boost::make_unsigned<base_result>::type base_unsigned;
59 base_unsigned range = detail::subtract<base_result>()((eng.max)(), (eng.min)());
60 base_unsigned y0_mask = (base_unsigned(2) << (bits - 1)) - 1;
61 base_unsigned y0 = (range + 1) & ~y0_mask;
65 u = detail::subtract<base_result>()(eng(), (eng.min)());
66 }
while (y0 != 0 && u > base_unsigned(y0 - 1));
70 template <
class RealType, std::
size_t w,
class Engine>
71 std::pair<RealType, int> generate_int_float_pair_v165(Engine& eng, boost::mpl::true_)
73 typedef typename Engine::result_type base_result;
74 typedef typename boost::make_unsigned<base_result>::type base_unsigned;
76 base_unsigned range = detail::subtract<base_result>()((eng.max)(), (eng.min)());
78 std::size_t m = (range == (std::numeric_limits<base_unsigned>::max)()) ? std::numeric_limits<base_unsigned>::digits : detail::integer_log2(range + 1);
82 for (std::size_t i = 0; i < w / m; ++i)
84 base_unsigned u = generate_one_digit_v165(eng, m);
85 bucket = (bucket << m) | u;
89 const std::size_t digits = std::numeric_limits<RealType>::digits;
91 base_unsigned u = generate_one_digit_v165(eng, m);
92 base_unsigned mask = (base_unsigned(1) << (w % m)) - 1;
93 bucket = (bucket << (w % m)) | (mask & u);
94 const RealType mult = RealType(1) / RealType(base_unsigned(1) << (m - w % m));
96 if (m - w % m > digits)
98 u &= ~(base_unsigned(1) << (m - digits));
100 r = RealType(u >> (w % m)) * mult;
102 for (std::size_t i = m - w % m; i + m < digits; ++i)
104 base_unsigned u = generate_one_digit_v165(eng, m);
106 r *= RealType(0.5) / RealType(base_unsigned(1) << (m - 1));
108 if (m - w % m < digits)
110 const std::size_t remaining = (digits - m + w % m) % m;
111 base_unsigned u = generate_one_digit_v165(eng, m);
112 r += u & ((base_unsigned(2) << (remaining - 1)) - 1);
113 const RealType mult = RealType(0.5) / RealType(base_unsigned(1) << (remaining - 1));
116 return std::make_pair(r, bucket);
119 template <
class RealType, std::
size_t w,
class Engine>
120 inline std::pair<RealType, int> generate_int_float_pair_v165(Engine& eng, boost::mpl::false_)
122 int bucket = uniform_int_distribution<>(0, (1 << w) - 1)(eng);
123 RealType r = uniform_01<RealType>()(eng);
124 return std::make_pair(r, bucket);
127 template <
class RealType, std::
size_t w,
class Engine>
128 inline std::pair<RealType, int> generate_int_float_pair_v165(Engine& eng)
130 typedef typename Engine::result_type base_result;
131 return generate_int_float_pair_v165<RealType, w>(eng,
132 boost::is_integral<base_result>());