Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r70005 - trunk/boost/random/detail
From: steven_at_[hidden]
Date: 2011-03-15 17:03:48


Author: steven_watanabe
Date: 2011-03-15 17:03:46 EDT (Tue, 15 Mar 2011)
New Revision: 70005
URL: http://svn.boost.org/trac/boost/changeset/70005

Log:
Try to help the compiler see through all the constants.
Text files modified:
   trunk/boost/random/detail/integer_log2.hpp | 15 ++++-
   trunk/boost/random/detail/seed_impl.hpp | 98 +++++++++++++++++++++++++++++++--------
   2 files changed, 89 insertions(+), 24 deletions(-)

Modified: trunk/boost/random/detail/integer_log2.hpp
==============================================================================
--- trunk/boost/random/detail/integer_log2.hpp (original)
+++ trunk/boost/random/detail/integer_log2.hpp 2011-03-15 17:03:46 EDT (Tue, 15 Mar 2011)
@@ -14,6 +14,7 @@
 #ifndef BOOST_RANDOM_DETAIL_INTEGER_LOG2_HPP
 #define BOOST_RANDOM_DETAIL_INTEGER_LOG2_HPP
 
+#include <boost/config.hpp>
 #include <boost/limits.hpp>
 #include <boost/pending/integer_log2.hpp>
 
@@ -21,11 +22,19 @@
 namespace random {
 namespace detail {
 
+#if !defined(BOOST_NO_CONSTEXPR)
+#define BOOST_RANDOM_DETAIL_CONSTEXPR constexpr
+#elif defined(BOOST_MSVC)
+#define BOOST_RANDOM_DETAIL_CONSTEXPR __forceinline
+#elif defined(__GNUC__)
+#define BOOST_RANDOM_DETAIL_CONSTEXPR __attribute__((const)) __attribute__((always_inline))
+#endif
+
 template<int Shift>
 struct integer_log2_impl
 {
     template<class T>
- static int apply(T t, int accum)
+ BOOST_RANDOM_DETAIL_CONSTEXPR static int apply(T t, int accum)
     {
         int update = ((t >> Shift) != 0) * Shift;
         return integer_log2_impl<Shift / 2>::apply(t >> update, accum + update);
@@ -36,14 +45,14 @@
 struct integer_log2_impl<1>
 {
     template<class T>
- static int apply(T t, int accum)
+ BOOST_RANDOM_DETAIL_CONSTEXPR static int apply(T t, int accum)
     {
         return int(t >> 1) + accum;
     }
 };
 
 template<class T>
-inline int integer_log2(T t)
+BOOST_RANDOM_DETAIL_CONSTEXPR int integer_log2(T t)
 {
     return integer_log2_impl<
         ::boost::detail::max_pow2_less<

Modified: trunk/boost/random/detail/seed_impl.hpp
==============================================================================
--- trunk/boost/random/detail/seed_impl.hpp (original)
+++ trunk/boost/random/detail/seed_impl.hpp 2011-03-15 17:03:46 EDT (Tue, 15 Mar 2011)
@@ -45,36 +45,80 @@
>::type type;
 };
 
+template<int N>
+struct const_pow_impl
+{
+ template<class T>
+ static T call(T arg, int n, T result)
+ {
+ return const_pow_impl<N / 2>::call(arg * arg, n / 2,
+ n%2 == 0? result : result * arg);
+ }
+};
+
+template<>
+struct const_pow_impl<0>
+{
+ template<class T>
+ static T call(T arg, int n, T result)
+ {
+ return result;
+ }
+};
+
+// requires N is an upper bound on n
+template<int N, class T>
+inline T const_pow(T arg, int n) { return const_pow_impl<N>::call(arg, n, T(1)); }
+
+template<class T>
+inline T pow2(int n)
+{
+ typedef unsigned int_type;
+ const int max_bits = std::numeric_limits<int_type>::digits;
+ T multiplier = T(int_type(1) << (max_bits - 1)) * 2;
+ return (int_type(1) << (n % max_bits)) *
+ const_pow<std::numeric_limits<T>::digits / max_bits>(multiplier, n / max_bits);
+}
+
 template<class Engine, class Iter>
 void generate_from_real(Engine& eng, Iter begin, Iter end)
 {
- using std::ldexp;
     typedef typename Engine::result_type RealType;
     const int Bits = Engine::precision();
     int remaining_bits = 0;
     boost::uint_least32_t saved_bits = 0;
- RealType multiplier = ldexp(RealType(1), Bits);
- RealType mult32 = 4294967296.0; // 2^32
+ RealType multiplier = pow2<RealType>( Bits);
+ RealType mult32 = RealType(4294967296.0); // 2^32
     while(true) {
         RealType val = eng() * multiplier;
         int available_bits = Bits;
- if(available_bits < 32 - remaining_bits) {
+ // Make sure the compiler can optimize this out
+ // if it isn't possible.
+ if(Bits < 32 && available_bits < 32 - remaining_bits) {
             saved_bits |= boost::uint_least32_t(val) << remaining_bits;
             remaining_bits += Bits;
         } else {
- if(remaining_bits != 0) {
- boost::uint_least32_t extra_bits = boost::uint_least32_t(val) & ((boost::uint_least32_t(1) << (32 - remaining_bits)) - 1);
- val = ldexp(val, -(32 - remaining_bits));
+ // If Bits < 32, then remaining_bits != 0, since
+ // if remaining_bits == 0, available_bits < 32 - 0,
+ // and we won't get here to begin with.
+ if(Bits < 32 || remaining_bits != 0) {
+ boost::uint_least32_t divisor =
+ (boost::uint_least32_t(1) << (32 - remaining_bits));
+ boost::uint_least32_t extra_bits = boost::uint_least32_t(val) & (divisor - 1);
+ val = val / divisor;
                 *begin++ = saved_bits | (extra_bits << remaining_bits);
                 if(begin == end) return;
                 available_bits -= 32 - remaining_bits;
                 remaining_bits = 0;
             }
- for(; available_bits >= 32; available_bits -= 32) {
- boost::uint_least32_t word = boost::uint_least32_t(val);
- val /= mult32;
- *begin++ = word;
- if(begin == end) return;
+ // If Bits < 32 we should never enter this loop
+ if(Bits >= 32) {
+ for(; available_bits >= 32; available_bits -= 32) {
+ boost::uint_least32_t word = boost::uint_least32_t(val);
+ val /= mult32;
+ *begin++ = word;
+ if(begin == end) return;
+ }
             }
             remaining_bits = available_bits;
             saved_bits = static_cast<boost::uint_least32_t>(val);
@@ -97,7 +141,7 @@
             detail::integer_log2(range + 1);
 
     {
- int discarded_bits = detail::integer_log2(static_cast<unsigned_type>(bits));
+ int discarded_bits = detail::integer_log2(bits);
         unsigned_type excess = (range + 1) >> (bits - discarded_bits);
         if(excess != 0) {
             int extra_bits = detail::integer_log2((excess - 1) ^ excess);
@@ -112,14 +156,24 @@
         unsigned_type val;
         do {
             val = boost::random::detail::subtract<IntType>()(eng(), (eng.min)());
- } while(val > limit);
+ } while(limit != range && val > limit);
         val &= mask;
         int available_bits = bits;
- if(available_bits < 32 - remaining_bits) {
+ if(available_bits == 32) {
+ *begin++ = static_cast<boost::uint_least32_t>(val) & 0xFFFFFFFFu;
+ if(begin == end) return;
+ } else if(available_bits % 32 == 0) {
+ for(int i = 0; i < available_bits / 32; ++i) {
+ boost::uint_least32_t word = boost::uint_least32_t(val) & 0xFFFFFFFFu;
+ val >>= 32;
+ *begin++ = word;
+ if(begin == end) return;
+ }
+ } else if(bits < 32 && available_bits < 32 - remaining_bits) {
             saved_bits |= boost::uint_least32_t(val) << remaining_bits;
             remaining_bits += bits;
         } else {
- if(remaining_bits != 0) {
+ if(bits < 32 || remaining_bits != 0) {
                 boost::uint_least32_t extra_bits = boost::uint_least32_t(val) & ((boost::uint_least32_t(1) << (32 - remaining_bits)) - 1);
                 val >>= 32 - remaining_bits;
                 *begin++ = saved_bits | (extra_bits << remaining_bits);
@@ -127,11 +181,13 @@
                 available_bits -= 32 - remaining_bits;
                 remaining_bits = 0;
             }
- for(; available_bits >= 32; available_bits -= 32) {
- boost::uint_least32_t word = boost::uint_least32_t(val);
- val >>= 32;
- *begin++ = word;
- if(begin == end) return;
+ if(bits >= 32) {
+ for(; available_bits >= 32; available_bits -= 32) {
+ boost::uint_least32_t word = boost::uint_least32_t(val) & 0xFFFFFFFFu;
+ val >>= 32;
+ *begin++ = word;
+ if(begin == end) return;
+ }
             }
             remaining_bits = available_bits;
             saved_bits = static_cast<boost::uint_least32_t>(val);


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk