Chaste  Release::2017.1
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 
45 namespace boost
46 {
47 namespace 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