|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r69969 - trunk/boost/random
From: steven_at_[hidden]
Date: 2011-03-13 22:46:16
Author: steven_watanabe
Date: 2011-03-13 22:46:15 EDT (Sun, 13 Mar 2011)
New Revision: 69969
URL: http://svn.boost.org/trac/boost/changeset/69969
Log:
Some optimizations for ranlux.
Text files modified:
trunk/boost/random/discard_block.hpp | 3
trunk/boost/random/subtract_with_carry.hpp | 132 +++++++++++++++++++++++++++++----------
2 files changed, 97 insertions(+), 38 deletions(-)
Modified: trunk/boost/random/discard_block.hpp
==============================================================================
--- trunk/boost/random/discard_block.hpp (original)
+++ trunk/boost/random/discard_block.hpp 2011-03-13 22:46:15 EDT (Sun, 13 Mar 2011)
@@ -105,8 +105,7 @@
{
if(_n >= returned_block) {
// discard values of random number generator
- for( ; _n < total_block; ++_n)
- _rng();
+ _rng.discard(total_block - _n);
_n = 0;
}
++_n;
Modified: trunk/boost/random/subtract_with_carry.hpp
==============================================================================
--- trunk/boost/random/subtract_with_carry.hpp (original)
+++ trunk/boost/random/subtract_with_carry.hpp 2011-03-13 22:46:15 EDT (Sun, 13 Mar 2011)
@@ -25,6 +25,7 @@
#include <boost/cstdint.hpp>
#include <boost/static_assert.hpp>
#include <boost/integer/static_log2.hpp>
+#include <boost/integer/integer_mask.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/seed.hpp>
@@ -37,6 +38,58 @@
namespace boost {
namespace random {
+namespace detail {
+
+template<class Engine, class UIntType>
+void subtract_with_carry_discard(Engine& eng, UIntType z) {
+ typedef typename Engine::result_type IntType;
+ const std::size_t short_lag = Engine::short_lag;
+ const std::size_t long_lag = Engine::long_lag;
+ std::size_t k = eng.k;
+ IntType carry = eng.carry;
+ if(k != 0) {
+ // increment k until it becomes 0.
+ if(k < short_lag) {
+ std::size_t limit = (short_lag - k) < z? short_lag : (k + static_cast<std::size_t>(z));
+ for(std::size_t j = k; j < limit; ++j) {
+ carry = eng.do_update(j, j + long_lag - short_lag, carry);
+ }
+ }
+ std::size_t limit = (long_lag - k) < z? long_lag : (k + static_cast<std::size_t>(z));
+ std::size_t start = (k < short_lag ? short_lag : k);
+ for(std::size_t j = start; j < limit; ++j) {
+ carry = eng.do_update(j, j - short_lag, carry);
+ }
+ }
+
+ k = ((z % long_lag) + k) % long_lag;
+
+ if(k < z) {
+ // main loop: update full blocks from k = 0 to long_lag
+ for(int i = 0; i < (z - k) / long_lag; ++i) {
+ for(std::size_t j = 0; j < short_lag; ++j) {
+ carry = eng.do_update(j, j + long_lag - short_lag, carry);
+ }
+ for(std::size_t j = short_lag; j < long_lag; ++j) {
+ carry = eng.do_update(j, j - short_lag, carry);
+ }
+ }
+
+ // Update the last partial block
+ std::size_t limit = short_lag < k? short_lag : k;
+ for(std::size_t j = 0; j < limit; ++j) {
+ carry = eng.do_update(j, j + long_lag - short_lag, carry);
+ }
+ for(std::size_t j = short_lag; j < k; ++j) {
+ carry = eng.do_update(j, j - short_lag, carry);
+ }
+ }
+ eng.carry = carry;
+ eng.k = k;
+}
+
+}
+
/**
* Instantiations of @c subtract_with_carry_engine model a
* \pseudo_random_number_generator. The algorithm is
@@ -134,13 +187,7 @@
{ return 0; }
/** Returns the largest value that the generator can produce. */
static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
- {
- // avoid "left shift count >= width of type" warning
- result_type res = 0;
- for(std::size_t j = 0; j < w; ++j)
- res |= (static_cast<result_type>(1) << j);
- return res;
- }
+ { return boost::low_bits_mask_t<w>::sig_bits; }
/** Returns the next value of the generator. */
result_type operator()()
@@ -149,30 +196,19 @@
(k < short_lag)?
(k + long_lag - short_lag) :
(k - short_lag);
- IntType delta;
- if (x[short_index] >= x[k] + carry) {
- // x(n) >= 0
- delta = x[short_index] - (x[k] + carry);
- carry = 0;
- } else {
- // x(n) < 0
- delta = modulus - x[k] - carry + x[short_index];
- carry = 1;
- }
- x[k] = delta;
+ carry = do_update(k, short_index, carry);
+ IntType result = x[k];
++k;
if(k >= long_lag)
k = 0;
- return delta;
+ return result;
}
#ifndef BOOST_NO_LONG_LONG
/** Advances the state of the generator by @c z. */
void discard(boost::ulong_long_type z)
{
- for(boost::ulong_long_type j = 0; j < z; ++j) {
- (*this)();
- }
+ detail::subtract_with_carry_discard(*this, z);
}
#endif
@@ -225,6 +261,25 @@
{
return x[(k+index) % long_lag];
}
+
+ friend void detail::subtract_with_carry_discard<>(subtract_with_carry_engine&, boost::ulong_long_type);
+
+ IntType do_update(std::size_t current, std::size_t short_index, IntType carry)
+ {
+ IntType delta;
+ IntType temp = x[current] + carry;
+ if (x[short_index] >= temp) {
+ // x(n) >= 0
+ delta = x[short_index] - temp;
+ carry = 0;
+ } else {
+ // x(n) < 0
+ delta = modulus - temp + x[short_index];
+ carry = 1;
+ }
+ x[current] = delta;
+ return carry;
+ }
/// \endcond
// state representation; next output (state) is x(i)
@@ -385,28 +440,18 @@
(k < short_lag) ?
(k + long_lag - short_lag) :
(k - short_lag);
- RealType delta = x[short_index] - x[k] - carry;
- if(delta < 0) {
- delta += RealType(1);
- carry = RealType(1)/_modulus;
- } else {
- carry = 0;
- }
- x[k] = delta;
+ carry = do_update(k, short_index, carry);
+ RealType result = x[k];
++k;
if(k >= long_lag)
k = 0;
- return delta;
+ return result;
}
#ifndef BOOST_NO_LONG_LONG
/** Advances the state of the generator by @c z. */
void discard(boost::ulong_long_type z)
- {
- for(boost::ulong_long_type j = 0; j < z; ++j) {
- (*this)();
- }
- }
+ { detail::subtract_with_carry_discard(*this, z); }
#endif
/** Fills a range with random values. */
@@ -458,6 +503,21 @@
{
return x[(k+index) % long_lag];
}
+
+ friend void detail::subtract_with_carry_discard<>(subtract_with_carry_01_engine&, boost::ulong_long_type);
+
+ RealType do_update(std::size_t current, std::size_t short_index, RealType carry)
+ {
+ RealType delta = x[short_index] - x[current] - carry;
+ if(delta < 0) {
+ delta += RealType(1);
+ carry = RealType(1)/_modulus;
+ } else {
+ carry = 0;
+ }
+ x[current] = delta;
+ return carry;
+ }
/// \endcond
std::size_t k;
RealType carry;
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