#ifndef BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP
#define BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP
#include <boost/config/no_tr1/cmath.hpp>
#include <iostream>
#include <algorithm>
#include <stdexcept>
#include <boost/config.hpp>
#include <boost/limits.hpp>
#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>
#include <boost/random/detail/operators.hpp>
#include <boost/random/detail/seed_impl.hpp>
#include <boost/random/detail/generator_seed_seq.hpp>
#include <boost/random/linear_congruential.hpp>
namespace boost {
namespace random {
namespace detail {
struct subtract_with_carry_discard
{
template<class Engine>
static void apply(Engine& eng, boost::uintmax_t 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) {
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) {
for(std::size_t 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);
}
}
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;
}
};
}
template<class IntType, std::size_t w, std::size_t s, std::size_t r>
class subtract_with_carry_engine
{
public:
typedef IntType result_type;
BOOST_STATIC_CONSTANT(std::size_t, word_size = w);
BOOST_STATIC_CONSTANT(std::size_t, long_lag = r);
BOOST_STATIC_CONSTANT(std::size_t, short_lag = s);
BOOST_STATIC_CONSTANT(uint32_t, default_seed = 19780503u);
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
BOOST_STATIC_CONSTANT(result_type, modulus = (result_type(1) << w));
BOOST_STATIC_ASSERT(std::numeric_limits<result_type>::is_integer);
subtract_with_carry_engine() { seed(); }
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry_engine,
IntType, value)
{ seed(value); }
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(subtract_with_carry_engine,
SeedSeq, seq)
{ seed(seq); }
template<class It> subtract_with_carry_engine(It& first, It last)
{ seed(first,last); }
void seed() { seed(default_seed); }
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry_engine,
IntType, value)
{
typedef linear_congruential_engine<uint32_t,40014,0,2147483563> gen_t;
gen_t intgen(static_cast<boost::uint32_t>(value == 0 ? default_seed : value));
detail::generator_seed_seq<gen_t> gen(intgen);
seed(gen);
}
BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(subtract_with_carry, SeedSeq, seq)
{
detail::seed_array_int<w>(seq, x);
carry = (x[long_lag-1] == 0);
k = 0;
}
template<class It>
void seed(It& first, It last)
{
detail::fill_array_int<w>(first, last, x);
carry = (x[long_lag-1] == 0);
k = 0;
}
static BOOST_CONSTEXPR result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return 0; }
static BOOST_CONSTEXPR result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return boost::low_bits_mask_t<w>::sig_bits; }
result_type operator()()
{
std::size_t short_index =
(k < short_lag)?
(k + long_lag - short_lag) :
(k - short_lag);
carry = do_update(k, short_index, carry);
IntType result = x[k];
++k;
if(k >= long_lag)
k = 0;
return result;
}
void discard(boost::uintmax_t z)
{
detail::subtract_with_carry_discard::apply(*this, z);
}
template<class It>
void generate(It first, It last)
{ detail::generate_from_int(*this, first, last); }
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, subtract_with_carry_engine, f)
{
for(unsigned int j = 0; j < f.long_lag; ++j)
os << f.compute(j) << ' ';
os << f.carry;
return os;
}
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, subtract_with_carry_engine, f)
{
for(unsigned int j = 0; j < f.long_lag; ++j)
is >> f.x[j] >> std::ws;
is >> f.carry;
f.k = 0;
return is;
}
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(subtract_with_carry_engine, x_, y)
{
for(unsigned int j = 0; j < r; ++j)
if(x_.compute(j) != y.compute(j))
return false;
return true;
}
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(subtract_with_carry_engine)
private:
IntType compute(unsigned int index) const
{
return x[(k+index) % long_lag];
}
friend struct detail::subtract_with_carry_discard;
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) {
delta = x[short_index] - temp;
carry_ = 0;
} else {
delta = modulus - temp + x[short_index];
carry_ = 1;
}
x[current] = delta;
return carry_;
}
IntType x[long_lag];
std::size_t k;
IntType carry;
};
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
template<class IntType, std::size_t w, std::size_t s, std::size_t r>
const bool subtract_with_carry_engine<IntType, w, s, r>::has_fixed_range;
template<class IntType, std::size_t w, std::size_t s, std::size_t r>
const IntType subtract_with_carry_engine<IntType, w, s, r>::modulus;
template<class IntType, std::size_t w, std::size_t s, std::size_t r>
const std::size_t subtract_with_carry_engine<IntType, w, s, r>::word_size;
template<class IntType, std::size_t w, std::size_t s, std::size_t r>
const std::size_t subtract_with_carry_engine<IntType, w, s, r>::long_lag;
template<class IntType, std::size_t w, std::size_t s, std::size_t r>
const std::size_t subtract_with_carry_engine<IntType, w, s, r>::short_lag;
template<class IntType, std::size_t w, std::size_t s, std::size_t r>
const uint32_t subtract_with_carry_engine<IntType, w, s, r>::default_seed;
#endif
template<class RealType, std::size_t w, std::size_t s, std::size_t r>
class subtract_with_carry_01_engine
{
public:
typedef RealType result_type;
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
BOOST_STATIC_CONSTANT(std::size_t, word_size = w);
BOOST_STATIC_CONSTANT(std::size_t, long_lag = r);
BOOST_STATIC_CONSTANT(std::size_t, short_lag = s);
BOOST_STATIC_CONSTANT(boost::uint32_t, default_seed = 19780503u);
BOOST_STATIC_ASSERT(!std::numeric_limits<result_type>::is_integer);
subtract_with_carry_01_engine() { init_modulus(); seed(); }
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry_01_engine,
boost::uint32_t, value)
{ init_modulus(); seed(value); }
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(subtract_with_carry_01_engine,
SeedSeq, seq)
{ init_modulus(); seed(seq); }
template<class It> subtract_with_carry_01_engine(It& first, It last)
{ init_modulus(); seed(first,last); }
private:
void init_modulus()
{
#ifndef BOOST_NO_STDC_NAMESPACE
using std::pow;
#endif
_modulus = pow(RealType(2), RealType(word_size));
}
public:
void seed() { seed(default_seed); }
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry_01_engine,
boost::uint32_t, value)
{
typedef linear_congruential_engine<uint32_t, 40014, 0, 2147483563> gen_t;
gen_t intgen(value == 0 ? default_seed : value);
detail::generator_seed_seq<gen_t> gen(intgen);
seed(gen);
}
BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(subtract_with_carry_01_engine,
SeedSeq, seq)
{
detail::seed_array_real<w>(seq, x);
carry = (x[long_lag-1] ? result_type(0) : result_type(1 / _modulus));
k = 0;
}
template<class It>
void seed(It& first, It last)
{
detail::fill_array_real<w>(first, last, x);
carry = (x[long_lag-1] ? result_type(0) : result_type(1 / _modulus));
k = 0;
}
static BOOST_CONSTEXPR result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return result_type(0); }
static BOOST_CONSTEXPR result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return result_type(1); }
result_type operator()()
{
std::size_t short_index =
(k < short_lag) ?
(k + long_lag - short_lag) :
(k - short_lag);
carry = do_update(k, short_index, carry);
RealType result = x[k];
++k;
if(k >= long_lag)
k = 0;
return result;
}
void discard(boost::uintmax_t z)
{ detail::subtract_with_carry_discard::apply(*this, z); }
template<class Iter>
void generate(Iter first, Iter last)
{ detail::generate_from_real(*this, first, last); }
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, subtract_with_carry_01_engine, f)
{
std::ios_base::fmtflags oldflags =
os.flags(os.dec | os.fixed | os.left);
for(unsigned int j = 0; j < f.long_lag; ++j)
os << (f.compute(j) * f._modulus) << ' ';
os << (f.carry * f._modulus);
os.flags(oldflags);
return os;
}
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, subtract_with_carry_01_engine, f)
{
RealType value;
for(unsigned int j = 0; j < long_lag; ++j) {
is >> value >> std::ws;
f.x[j] = value / f._modulus;
}
is >> value;
f.carry = value / f._modulus;
f.k = 0;
return is;
}
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(subtract_with_carry_01_engine, x_, y)
{
for(unsigned int j = 0; j < r; ++j)
if(x_.compute(j) != y.compute(j))
return false;
return true;
}
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(subtract_with_carry_01_engine)
private:
RealType compute(unsigned int index) const
{
return x[(k+index) % long_lag];
}
friend struct detail::subtract_with_carry_discard;
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_;
}
std::size_t k;
RealType carry;
RealType x[long_lag];
RealType _modulus;
};
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
template<class RealType, std::size_t w, std::size_t s, std::size_t r>
const bool subtract_with_carry_01_engine<RealType, w, s, r>::has_fixed_range;
template<class RealType, std::size_t w, std::size_t s, std::size_t r>
const std::size_t subtract_with_carry_01_engine<RealType, w, s, r>::word_size;
template<class RealType, std::size_t w, std::size_t s, std::size_t r>
const std::size_t subtract_with_carry_01_engine<RealType, w, s, r>::long_lag;
template<class RealType, std::size_t w, std::size_t s, std::size_t r>
const std::size_t subtract_with_carry_01_engine<RealType, w, s, r>::short_lag;
template<class RealType, std::size_t w, std::size_t s, std::size_t r>
const uint32_t subtract_with_carry_01_engine<RealType, w, s, r>::default_seed;
#endif
template<class IntType, IntType m, unsigned s, unsigned r, IntType v>
class subtract_with_carry :
public subtract_with_carry_engine<IntType,
boost::static_log2<m>::value, s, r>
{
typedef subtract_with_carry_engine<IntType,
boost::static_log2<m>::value, s, r> base_type;
public:
subtract_with_carry() {}
BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(subtract_with_carry, Gen, gen)
{ seed(gen); }
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry,
IntType, val)
{ seed(val); }
template<class It>
subtract_with_carry(It& first, It last) : base_type(first, last) {}
void seed() { base_type::seed(); }
BOOST_RANDOM_DETAIL_GENERATOR_SEED(subtract_with_carry, Gen, gen)
{
detail::generator_seed_seq<Gen> seq(gen);
base_type::seed(seq);
}
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry, IntType, val)
{ base_type::seed(val); }
template<class It>
void seed(It& first, It last) { base_type::seed(first, last); }
};
template<class RealType, int w, unsigned s, unsigned r, int v = 0>
class subtract_with_carry_01 :
public subtract_with_carry_01_engine<RealType, w, s, r>
{
typedef subtract_with_carry_01_engine<RealType, w, s, r> base_type;
public:
subtract_with_carry_01() {}
BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(subtract_with_carry_01, Gen, gen)
{ seed(gen); }
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry_01,
uint32_t, val)
{ seed(val); }
template<class It>
subtract_with_carry_01(It& first, It last) : base_type(first, last) {}
void seed() { base_type::seed(); }
BOOST_RANDOM_DETAIL_GENERATOR_SEED(subtract_with_carry_01, Gen, gen)
{
detail::generator_seed_seq<Gen> seq(gen);
base_type::seed(seq);
}
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry_01, uint32_t, val)
{ base_type::seed(val); }
template<class It>
void seed(It& first, It last) { base_type::seed(first, last); }
};
namespace detail {
template<class Engine>
struct generator_bits;
template<class RealType, std::size_t w, std::size_t s, std::size_t r>
struct generator_bits<subtract_with_carry_01_engine<RealType, w, s, r> > {
static std::size_t value() { return w; }
};
template<class RealType, int w, unsigned s, unsigned r, int v>
struct generator_bits<subtract_with_carry_01<RealType, w, s, r, v> > {
static std::size_t value() { return w; }
};
}
} }
#endif