summaryrefslogtreecommitdiff
path: root/boost/random/detail/int_float_pair.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/random/detail/int_float_pair.hpp')
-rw-r--r--boost/random/detail/int_float_pair.hpp121
1 files changed, 121 insertions, 0 deletions
diff --git a/boost/random/detail/int_float_pair.hpp b/boost/random/detail/int_float_pair.hpp
new file mode 100644
index 0000000000..de253a0ecb
--- /dev/null
+++ b/boost/random/detail/int_float_pair.hpp
@@ -0,0 +1,121 @@
+/* boost random/detail/int_float_pair.hpp header file
+ *
+ * Copyright Jens Maurer 2000-2001
+ * Copyright Steven Watanabe 2010-2011
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org for most recent version including documentation.
+ *
+ * $Id$
+ *
+ */
+
+#ifndef BOOST_RANDOM_DETAIL_INT_FLOAT_PAIR_HPP
+#define BOOST_RANDOM_DETAIL_INT_FLOAT_PAIR_HPP
+
+#include <utility>
+#include <boost/integer.hpp>
+#include <boost/integer/integer_mask.hpp>
+#include <boost/type_traits/make_unsigned.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/random/uniform_01.hpp>
+#include <boost/random/uniform_int_distribution.hpp>
+#include <boost/random/detail/signed_unsigned_tools.hpp>
+#include <boost/random/detail/integer_log2.hpp>
+#include <boost/mpl/bool.hpp>
+
+namespace boost {
+namespace random {
+namespace detail {
+
+template<class Engine>
+inline typename boost::make_unsigned<typename Engine::result_type>::type
+generate_one_digit(Engine& eng, std::size_t bits)
+{
+ typedef typename Engine::result_type base_result;
+ typedef typename boost::make_unsigned<base_result>::type base_unsigned;
+
+ base_unsigned range =
+ detail::subtract<base_result>()((eng.max)(), (eng.min)());
+ base_unsigned y0_mask = (base_unsigned(2) << (bits - 1)) - 1;
+ base_unsigned y0 = (range + 1) & ~y0_mask;
+ base_unsigned u;
+ do {
+ u = detail::subtract<base_result>()(eng(), (eng.min)());
+ } while(y0 != 0 && u > base_unsigned(y0 - 1));
+ return u & y0_mask;
+}
+
+template<class RealType, std::size_t w, class Engine>
+std::pair<RealType, int> generate_int_float_pair(Engine& eng, boost::mpl::true_)
+{
+ typedef typename Engine::result_type base_result;
+ typedef typename boost::make_unsigned<base_result>::type base_unsigned;
+
+ base_unsigned range =
+ detail::subtract<base_result>()((eng.max)(), (eng.min)());
+
+ std::size_t m =
+ (range == (std::numeric_limits<base_unsigned>::max)()) ?
+ std::numeric_limits<base_unsigned>::digits :
+ detail::integer_log2(range + 1);
+
+ int bucket = 0;
+ // process as many full digits as possible into the int part
+ for(std::size_t i = 0; i < w/m; ++i) {
+ base_unsigned u = generate_one_digit(eng, m);
+ bucket = (bucket << m) | u;
+ }
+ RealType r;
+
+ const std::size_t digits = std::numeric_limits<RealType>::digits;
+ {
+ base_unsigned u = generate_one_digit(eng, m);
+ base_unsigned mask = (base_unsigned(1) << (w%m)) - 1;
+ bucket = (bucket << (w%m)) | (mask & u);
+ const RealType mult = RealType(1)/RealType(base_unsigned(1) << (m - w%m));
+ // zero out unused bits
+ if (m - w%m > digits) {
+ u &= ~(base_unsigned(1) << (m - digits));
+ }
+ r = RealType(u >> (w%m)) * mult;
+ }
+ for(std::size_t i = m - w%m; i + m < digits; ++i) {
+ base_unsigned u = generate_one_digit(eng, m);
+ r += u;
+ r *= RealType(0.5)/RealType(base_unsigned(1) << (m - 1));
+ }
+ if (m - w%m < digits)
+ {
+ const std::size_t remaining = (digits - m + w%m) % m;
+ base_unsigned u = generate_one_digit(eng, m);
+ r += u & ((base_unsigned(2) << (remaining - 1)) - 1);
+ const RealType mult = RealType(0.5)/RealType(base_unsigned(1) << (remaining - 1));
+ r *= mult;
+ }
+ return std::make_pair(r, bucket);
+}
+
+template<class RealType, std::size_t w, class Engine>
+inline std::pair<RealType, int> generate_int_float_pair(Engine& eng, boost::mpl::false_)
+{
+ int bucket = uniform_int_distribution<>(0, (1 << w) - 1)(eng);
+ RealType r = uniform_01<RealType>()(eng);
+ return std::make_pair(r, bucket);
+}
+
+template<class RealType, std::size_t w, class Engine>
+inline std::pair<RealType, int> generate_int_float_pair(Engine& eng)
+{
+ typedef typename Engine::result_type base_result;
+ return generate_int_float_pair<RealType, w>(eng,
+ boost::is_integral<base_result>());
+}
+
+} // namespace detail
+} // namespace random
+} // namespace boost
+
+#endif // BOOST_RANDOM_DETAIL_INT_FLOAT_PAIR_HPP