Chaste Commit::1fd4e48e3990e67db148bc1bc4cf6991a0049d0c
Boost165IntFloatPair.hpp
Go to the documentation of this file.
1
17/* boost random/detail/int_float_pair.hpp header file
18 *
19 * Copyright Jens Maurer 2000-2001
20 * Copyright Steven Watanabe 2010-2011
21 * Distributed under the Boost Software License, Version 1.0. (See
22 * accompanying file LICENSE_1_0.txt or copy at
23 * http://www.boost.org/LICENSE_1_0.txt)
24 *
25 * See http://www.boost.org for most recent version including documentation.
26 *
27 * $Id$
28 *
29 */
30
31#ifndef BOOST_165_RANDOM_DETAIL_INT_FLOAT_PAIR_HPP
32#define BOOST_165_RANDOM_DETAIL_INT_FLOAT_PAIR_HPP
33
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>
43#include <utility>
44
45namespace boost
46{
47namespace random
48{
49 namespace detail
50 {
51
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)
55 {
56 typedef typename Engine::result_type base_result;
57 typedef typename boost::make_unsigned<base_result>::type base_unsigned;
58
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;
62 base_unsigned u;
63 do
64 {
65 u = detail::subtract<base_result>()(eng(), (eng.min)());
66 } while (y0 != 0 && u > base_unsigned(y0 - 1));
67 return u & y0_mask;
68 }
69
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_)
72 {
73 typedef typename Engine::result_type base_result;
74 typedef typename boost::make_unsigned<base_result>::type base_unsigned;
75
76 base_unsigned range = detail::subtract<base_result>()((eng.max)(), (eng.min)());
77
78 std::size_t m = (range == (std::numeric_limits<base_unsigned>::max)()) ? std::numeric_limits<base_unsigned>::digits : detail::integer_log2(range + 1);
79
80 int bucket = 0;
81 // process as many full digits as possible into the int part
82 for (std::size_t i = 0; i < w / m; ++i)
83 {
84 base_unsigned u = generate_one_digit_v165(eng, m);
85 bucket = (bucket << m) | u;
86 }
87 RealType r;
88
89 const std::size_t digits = std::numeric_limits<RealType>::digits;
90 {
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));
95 // zero out unused bits
96 if (m - w % m > digits)
97 {
98 u &= ~(base_unsigned(1) << (m - digits));
99 }
100 r = RealType(u >> (w % m)) * mult;
101 }
102 for (std::size_t i = m - w % m; i + m < digits; ++i)
103 {
104 base_unsigned u = generate_one_digit_v165(eng, m);
105 r += u;
106 r *= RealType(0.5) / RealType(base_unsigned(1) << (m - 1));
107 }
108 if (m - w % m < digits)
109 {
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));
114 r *= mult;
115 }
116 return std::make_pair(r, bucket);
117 }
118
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_)
121 {
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);
125 }
126
127 template <class RealType, std::size_t w, class Engine>
128 inline std::pair<RealType, int> generate_int_float_pair_v165(Engine& eng)
129 {
130 typedef typename Engine::result_type base_result;
131 return generate_int_float_pair_v165<RealType, w>(eng,
132 boost::is_integral<base_result>());
133 }
134
135 } // namespace detail
136} // namespace random
137} // namespace boost
138
139#endif // BOOST_165_RANDOM_DETAIL_INT_FLOAT_PAIR_HPP