stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork

This commit is contained in:
2026-02-24 18:38:47 +00:00
parent da8c28aaeb
commit 65cb2619a7
13106 changed files with 2484322 additions and 1804 deletions
@@ -0,0 +1,283 @@
/* boost random/additive_combine.hpp header file
*
* Copyright Jens Maurer 2000-2001
* 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$
*
* Revision history
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_ADDITIVE_COMBINE_HPP
#define BOOST_RANDOM_ADDITIVE_COMBINE_HPP
#include <istream>
#include <iosfwd>
#include <algorithm> // for std::min and std::max
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/detail/seed.hpp>
#include <boost/random/linear_congruential.hpp>
namespace boost {
namespace random {
/**
* An instantiation of class template @c additive_combine_engine models a
* \pseudo_random_number_generator. It combines two multiplicative
* \linear_congruential_engine number generators, i.e. those with @c c = 0.
* It is described in
*
* @blockquote
* "Efficient and Portable Combined Random Number Generators", Pierre L'Ecuyer,
* Communications of the ACM, Vol. 31, No. 6, June 1988, pp. 742-749, 774
* @endblockquote
*
* The template parameters MLCG1 and MLCG2 shall denote two different
* \linear_congruential_engine number generators, each with c = 0. Each
* invocation returns a random number
* X(n) := (MLCG1(n) - MLCG2(n)) mod (m1 - 1),
* where m1 denotes the modulus of MLCG1.
*/
template<class MLCG1, class MLCG2>
class additive_combine_engine
{
public:
typedef MLCG1 first_base;
typedef MLCG2 second_base;
typedef typename MLCG1::result_type result_type;
// Required by old Boost.Random concept
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
/**
* Returns the smallest value that the generator can produce
*/
static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return 1; }
/**
* Returns the largest value that the generator can produce
*/
static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return MLCG1::modulus-1; }
/**
* Constructs an @c additive_combine_engine using the
* default constructors of the two base generators.
*/
additive_combine_engine() : _mlcg1(), _mlcg2() { }
/**
* Constructs an @c additive_combine_engine, using seed as
* the constructor argument for both base generators.
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(additive_combine_engine,
result_type, seed_arg)
{
_mlcg1.seed(seed_arg);
_mlcg2.seed(seed_arg);
}
/**
* Constructs an @c additive_combine_engine, using seq as
* the constructor argument for both base generators.
*
* @xmlwarning
* The semantics of this function are liable to change.
* A @c seed_seq is designed to generate all the seeds
* in one shot, but this seeds the two base engines
* independantly and probably ends up giving the same
* sequence to both.
* @endxmlwarning
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(additive_combine_engine,
SeedSeq, seq)
{
_mlcg1.seed(seq);
_mlcg2.seed(seq);
}
/**
* Constructs an @c additive_combine_engine, using
* @c seed1 and @c seed2 as the constructor argument to
* the first and second base generators, respectively.
*/
additive_combine_engine(typename MLCG1::result_type seed1,
typename MLCG2::result_type seed2)
: _mlcg1(seed1), _mlcg2(seed2) { }
/**
* Contructs an @c additive_combine_engine with
* values from the range defined by the input iterators first
* and last. first will be modified to point to the element
* after the last one used.
*
* Throws: @c std::invalid_argument if the input range is too small.
*
* Exception Safety: Basic
*/
template<class It> additive_combine_engine(It& first, It last)
: _mlcg1(first, last), _mlcg2(first, last) { }
/**
* Seeds an @c additive_combine_engine using the default
* seeds of the two base generators.
*/
void seed()
{
_mlcg1.seed();
_mlcg2.seed();
}
/**
* Seeds an @c additive_combine_engine, using @c seed as the
* seed for both base generators.
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(additive_combine_engine,
result_type, seed_arg)
{
_mlcg1.seed(seed_arg);
_mlcg2.seed(seed_arg);
}
/**
* Seeds an @c additive_combine_engine, using @c seq to
* seed both base generators.
*
* See the warning on the corresponding constructor.
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(additive_combine_engine,
SeedSeq, seq)
{
_mlcg1.seed(seq);
_mlcg2.seed(seq);
}
/**
* Seeds an @c additive_combine generator, using @c seed1 and @c seed2 as
* the seeds to the first and second base generators, respectively.
*/
void seed(typename MLCG1::result_type seed1,
typename MLCG2::result_type seed2)
{
_mlcg1.seed(seed1);
_mlcg2.seed(seed2);
}
/**
* Seeds an @c additive_combine_engine with
* values from the range defined by the input iterators first
* and last. first will be modified to point to the element
* after the last one used.
*
* Throws: @c std::invalid_argument if the input range is too small.
*
* Exception Safety: Basic
*/
template<class It> void seed(It& first, It last)
{
_mlcg1.seed(first, last);
_mlcg2.seed(first, last);
}
/** Returns the next value of the generator. */
result_type operator()() {
result_type val1 = _mlcg1();
result_type val2 = _mlcg2();
if(val2 < val1) return val1 - val2;
else return val1 - val2 + MLCG1::modulus - 1;
}
/** Fills a range with random values */
template<class Iter>
void generate(Iter first, Iter last)
{ detail::generate_from_int(*this, first, last); }
/** Advances the state of the generator by @c z. */
void discard(boost::uintmax_t z)
{
_mlcg1.discard(z);
_mlcg2.discard(z);
}
/**
* Writes the state of an @c additive_combine_engine to a @c
* std::ostream. The textual representation of an @c
* additive_combine_engine is the textual representation of
* the first base generator followed by the textual representation
* of the second base generator.
*/
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, additive_combine_engine, r)
{ os << r._mlcg1 << ' ' << r._mlcg2; return os; }
/**
* Reads the state of an @c additive_combine_engine from a
* @c std::istream.
*/
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, additive_combine_engine, r)
{ is >> r._mlcg1 >> std::ws >> r._mlcg2; return is; }
/**
* Returns: true iff the two @c additive_combine_engines will
* produce the same sequence of values.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(additive_combine_engine, x, y)
{ return x._mlcg1 == y._mlcg1 && x._mlcg2 == y._mlcg2; }
/**
* Returns: true iff the two @c additive_combine_engines will
* produce different sequences of values.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(additive_combine_engine)
private:
MLCG1 _mlcg1;
MLCG2 _mlcg2;
};
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
template<class MLCG1, class MLCG2>
const bool additive_combine_engine<MLCG1, MLCG2>::has_fixed_range;
#endif
/// \cond show_deprecated
/** Provided for backwards compatibility. */
template<class MLCG1, class MLCG2, typename MLCG1::result_type val = 0>
class additive_combine : public additive_combine_engine<MLCG1, MLCG2>
{
typedef additive_combine_engine<MLCG1, MLCG2> base_t;
public:
typedef typename base_t::result_type result_type;
additive_combine() {}
template<class T>
additive_combine(T& arg) : base_t(arg) {}
template<class T>
additive_combine(const T& arg) : base_t(arg) {}
template<class It>
additive_combine(It& first, It last) : base_t(first, last) {}
};
/// \endcond
/**
* The specialization \ecuyer1988 was suggested in
*
* @blockquote
* "Efficient and Portable Combined Random Number Generators", Pierre L'Ecuyer,
* Communications of the ACM, Vol. 31, No. 6, June 1988, pp. 742-749, 774
* @endblockquote
*/
typedef additive_combine_engine<
linear_congruential_engine<uint32_t, 40014, 0, 2147483563>,
linear_congruential_engine<uint32_t, 40692, 0, 2147483399>
> ecuyer1988;
} // namespace random
using random::ecuyer1988;
} // namespace boost
#endif // BOOST_RANDOM_ADDITIVE_COMBINE_HPP
@@ -0,0 +1,197 @@
/* boost random/bernoulli_distribution.hpp header file
*
* Copyright Jens Maurer 2000-2001
* Copyright Steven Watanabe 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$
*
* Revision history
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_BERNOULLI_DISTRIBUTION_HPP
#define BOOST_RANDOM_BERNOULLI_DISTRIBUTION_HPP
#include <iosfwd>
#include <boost/assert.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
namespace boost {
namespace random {
/**
* Instantiations of class template \bernoulli_distribution model a
* \random_distribution. Such a random distribution produces bool values
* distributed with probabilities P(true) = p and P(false) = 1-p. p is
* the parameter of the distribution.
*/
template<class RealType = double>
class bernoulli_distribution
{
public:
// In principle, this could work with both integer and floating-point
// types. Generating floating-point random numbers in the first
// place is probably more expensive, so use integer as input.
typedef int input_type;
typedef bool result_type;
class param_type
{
public:
typedef bernoulli_distribution distribution_type;
/**
* Constructs the parameters of the distribution.
*
* Requires: 0 <= p <= 1
*/
explicit param_type(RealType p_arg = RealType(0.5))
: _p(p_arg)
{
BOOST_ASSERT(_p >= 0);
BOOST_ASSERT(_p <= 1);
}
/** Returns the p parameter of the distribution. */
RealType p() const { return _p; }
/** Writes the parameters to a std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{
os << parm._p;
return os;
}
/** Reads the parameters from a std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{
is >> parm._p;
return is;
}
/** Returns true if the two sets of parameters are equal. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._p == rhs._p; }
/** Returns true if the two sets of parameters are different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
RealType _p;
};
/**
* Constructs a \bernoulli_distribution object.
* p is the parameter of the distribution.
*
* Requires: 0 <= p <= 1
*/
explicit bernoulli_distribution(const RealType& p_arg = RealType(0.5))
: _p(p_arg)
{
BOOST_ASSERT(_p >= 0);
BOOST_ASSERT(_p <= 1);
}
/**
* Constructs \bernoulli_distribution from its parameters
*/
explicit bernoulli_distribution(const param_type& parm)
: _p(parm.p()) {}
// compiler-generated copy ctor and assignment operator are fine
/**
* Returns: The "p" parameter of the distribution.
*/
RealType p() const { return _p; }
/** Returns the smallest value that the distribution can produce. */
bool min BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return false; }
/** Returns the largest value that the distribution can produce. */
bool max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return true; }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(_p); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm) { _p = parm.p(); }
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { }
/**
* Returns: a random variate distributed according to the
* \bernoulli_distribution.
*/
template<class Engine>
bool operator()(Engine& eng) const
{
if(_p == RealType(0))
return false;
else
return RealType(eng() - (eng.min)()) <= _p * RealType((eng.max)()-(eng.min)());
}
/**
* Returns: a random variate distributed according to the
* \bernoulli_distribution with parameters specified by param.
*/
template<class Engine>
bool operator()(Engine& eng, const param_type& parm) const
{
return bernoulli_distribution(parm)(eng);
}
/**
* Writes the parameters of the distribution to a @c std::ostream.
*/
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, bernoulli_distribution, bd)
{
os << bd._p;
return os;
}
/**
* Reads the parameters of the distribution from a @c std::istream.
*/
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, bernoulli_distribution, bd)
{
is >> bd._p;
return is;
}
/**
* Returns true iff the two distributions will produce identical
* sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(bernoulli_distribution, lhs, rhs)
{ return lhs._p == rhs._p; }
/**
* Returns true iff the two distributions will produce different
* sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(bernoulli_distribution)
private:
RealType _p;
};
} // namespace random
using random::bernoulli_distribution;
} // namespace boost
#endif // BOOST_RANDOM_BERNOULLI_DISTRIBUTION_HPP
@@ -0,0 +1,184 @@
/* boost random/beta_distribution.hpp header file
*
* Copyright Steven Watanabe 2014
* 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_BETA_DISTRIBUTION_HPP
#define BOOST_RANDOM_BETA_DISTRIBUTION_HPP
#include <cassert>
#include <istream>
#include <iosfwd>
#include <boost/random/detail/operators.hpp>
#include <boost/random/gamma_distribution.hpp>
namespace boost {
namespace random {
/**
* The beta distribution is a real-valued distribution which produces
* values in the range [0, 1]. It has two parameters, alpha and beta.
*
* It has \f$\displaystyle p(x) = \frac{x^{\alpha-1}(1-x)^{\beta-1}}{B(\alpha, \beta)}\f$.
*/
template<class RealType = double>
class beta_distribution {
public:
typedef RealType result_type;
typedef RealType input_type;
class param_type {
public:
typedef beta_distribution distribution_type;
/**
* Constructs a @c param_type from the "alpha" and "beta" parameters
* of the distribution.
*
* Requires: alpha > 0, beta > 0
*/
explicit param_type(RealType alpha_arg = RealType(1.0),
RealType beta_arg = RealType(1.0))
: _alpha(alpha_arg), _beta(beta_arg)
{
assert(alpha_arg > 0);
assert(beta_arg > 0);
}
/** Returns the "alpha" parameter of the distribtuion. */
RealType alpha() const { return _alpha; }
/** Returns the "beta" parameter of the distribution. */
RealType beta() const { return _beta; }
/** Writes a @c param_type to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{ os << parm._alpha << ' ' << parm._beta; return os; }
/** Reads a @c param_type from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{ is >> parm._alpha >> std::ws >> parm._beta; return is; }
/** Returns true if the two sets of parameters are the same. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._alpha == rhs._alpha && lhs._beta == rhs._beta; }
/** Returns true if the two sets of parameters are the different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
RealType _alpha;
RealType _beta;
};
/**
* Constructs an @c beta_distribution from its "alpha" and "beta" parameters.
*
* Requires: alpha > 0, beta > 0
*/
explicit beta_distribution(RealType alpha_arg = RealType(1.0),
RealType beta_arg = RealType(1.0))
: _alpha(alpha_arg), _beta(beta_arg)
{
assert(alpha_arg > 0);
assert(beta_arg > 0);
}
/** Constructs an @c beta_distribution from its parameters. */
explicit beta_distribution(const param_type& parm)
: _alpha(parm.alpha()), _beta(parm.beta())
{}
/**
* Returns a random variate distributed according to the
* beta distribution.
*/
template<class URNG>
RealType operator()(URNG& urng) const
{
RealType a = gamma_distribution<RealType>(_alpha, RealType(1.0))(urng);
RealType b = gamma_distribution<RealType>(_beta, RealType(1.0))(urng);
return a / (a + b);
}
/**
* Returns a random variate distributed accordint to the beta
* distribution with parameters specified by @c param.
*/
template<class URNG>
RealType operator()(URNG& urng, const param_type& parm) const
{
return beta_distribution(parm)(urng);
}
/** Returns the "alpha" parameter of the distribution. */
RealType alpha() const { return _alpha; }
/** Returns the "beta" parameter of the distribution. */
RealType beta() const { return _beta; }
/** Returns the smallest value that the distribution can produce. */
RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return RealType(0.0); }
/** Returns the largest value that the distribution can produce. */
RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return RealType(1.0); }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(_alpha, _beta); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
_alpha = parm.alpha();
_beta = parm.beta();
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { }
/** Writes an @c beta_distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, beta_distribution, wd)
{
os << wd.param();
return os;
}
/** Reads an @c beta_distribution from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, beta_distribution, wd)
{
param_type parm;
if(is >> parm) {
wd.param(parm);
}
return is;
}
/**
* Returns true if the two instances of @c beta_distribution will
* return identical sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(beta_distribution, lhs, rhs)
{ return lhs._alpha == rhs._alpha && lhs._beta == rhs._beta; }
/**
* Returns true if the two instances of @c beta_distribution will
* return different sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(beta_distribution)
private:
RealType _alpha;
RealType _beta;
};
} // namespace random
} // namespace boost
#endif // BOOST_RANDOM_BETA_DISTRIBUTION_HPP
@@ -0,0 +1,434 @@
/* boost random/binomial_distribution.hpp header file
*
* Copyright Steven Watanabe 2010
* 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_BINOMIAL_DISTRIBUTION_HPP_INCLUDED
#define BOOST_RANDOM_BINOMIAL_DISTRIBUTION_HPP_INCLUDED
#include <boost/config/no_tr1/cmath.hpp>
#include <cstdlib>
#include <iosfwd>
#include <boost/random/detail/config.hpp>
#include <boost/random/uniform_01.hpp>
#include <boost/random/detail/disable_warnings.hpp>
namespace boost {
namespace random {
namespace detail {
template<class RealType>
struct binomial_table {
static const RealType table[10];
};
template<class RealType>
const RealType binomial_table<RealType>::table[10] = {
0.08106146679532726,
0.04134069595540929,
0.02767792568499834,
0.02079067210376509,
0.01664469118982119,
0.01387612882307075,
0.01189670994589177,
0.01041126526197209,
0.009255462182712733,
0.008330563433362871
};
}
/**
* The binomial distribution is an integer valued distribution with
* two parameters, @c t and @c p. The values of the distribution
* are within the range [0,t].
*
* The distribution function is
* \f$\displaystyle P(k) = {t \choose k}p^k(1-p)^{t-k}\f$.
*
* The algorithm used is the BTRD algorithm described in
*
* @blockquote
* "The generation of binomial random variates", Wolfgang Hormann,
* Journal of Statistical Computation and Simulation, Volume 46,
* Issue 1 & 2 April 1993 , pages 101 - 110
* @endblockquote
*/
template<class IntType = int, class RealType = double>
class binomial_distribution {
public:
typedef IntType result_type;
typedef RealType input_type;
class param_type {
public:
typedef binomial_distribution distribution_type;
/**
* Construct a param_type object. @c t and @c p
* are the parameters of the distribution.
*
* Requires: t >=0 && 0 <= p <= 1
*/
explicit param_type(IntType t_arg = 1, RealType p_arg = RealType (0.5))
: _t(t_arg), _p(p_arg)
{}
/** Returns the @c t parameter of the distribution. */
IntType t() const { return _t; }
/** Returns the @c p parameter of the distribution. */
RealType p() const { return _p; }
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
/** Writes the parameters of the distribution to a @c std::ostream. */
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os,
const param_type& parm)
{
os << parm._p << " " << parm._t;
return os;
}
/** Reads the parameters of the distribution from a @c std::istream. */
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is, param_type& parm)
{
is >> parm._p >> std::ws >> parm._t;
return is;
}
#endif
/** Returns true if the parameters have the same values. */
friend bool operator==(const param_type& lhs, const param_type& rhs)
{
return lhs._t == rhs._t && lhs._p == rhs._p;
}
/** Returns true if the parameters have different values. */
friend bool operator!=(const param_type& lhs, const param_type& rhs)
{
return !(lhs == rhs);
}
private:
IntType _t;
RealType _p;
};
/**
* Construct a @c binomial_distribution object. @c t and @c p
* are the parameters of the distribution.
*
* Requires: t >=0 && 0 <= p <= 1
*/
explicit binomial_distribution(IntType t_arg = 1,
RealType p_arg = RealType(0.5))
: _t(t_arg), _p(p_arg)
{
init();
}
/**
* Construct an @c binomial_distribution object from the
* parameters.
*/
explicit binomial_distribution(const param_type& parm)
: _t(parm.t()), _p(parm.p())
{
init();
}
/**
* Returns a random variate distributed according to the
* binomial distribution.
*/
template<class URNG>
IntType operator()(URNG& urng) const
{
if(use_inversion()) {
if(0.5 < _p) {
return _t - invert(_t, 1-_p, urng);
} else {
return invert(_t, _p, urng);
}
} else if(0.5 < _p) {
return _t - generate(urng);
} else {
return generate(urng);
}
}
/**
* Returns a random variate distributed according to the
* binomial distribution with parameters specified by @c param.
*/
template<class URNG>
IntType operator()(URNG& urng, const param_type& parm) const
{
return binomial_distribution(parm)(urng);
}
/** Returns the @c t parameter of the distribution. */
IntType t() const { return _t; }
/** Returns the @c p parameter of the distribution. */
RealType p() const { return _p; }
/** Returns the smallest value that the distribution can produce. */
IntType min BOOST_PREVENT_MACRO_SUBSTITUTION() const { return 0; }
/** Returns the largest value that the distribution can produce. */
IntType max BOOST_PREVENT_MACRO_SUBSTITUTION() const { return _t; }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(_t, _p); }
/** Sets parameters of the distribution. */
void param(const param_type& parm)
{
_t = parm.t();
_p = parm.p();
init();
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { }
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
/** Writes the parameters of the distribution to a @c std::ostream. */
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os,
const binomial_distribution& bd)
{
os << bd.param();
return os;
}
/** Reads the parameters of the distribution from a @c std::istream. */
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is, binomial_distribution& bd)
{
bd.read(is);
return is;
}
#endif
/** Returns true if the two distributions will produce the same
sequence of values, given equal generators. */
friend bool operator==(const binomial_distribution& lhs,
const binomial_distribution& rhs)
{
return lhs._t == rhs._t && lhs._p == rhs._p;
}
/** Returns true if the two distributions could produce different
sequences of values, given equal generators. */
friend bool operator!=(const binomial_distribution& lhs,
const binomial_distribution& rhs)
{
return !(lhs == rhs);
}
private:
/// @cond show_private
template<class CharT, class Traits>
void read(std::basic_istream<CharT, Traits>& is) {
param_type parm;
if(is >> parm) {
param(parm);
}
}
bool use_inversion() const
{
// BTRD is safe when np >= 10
return m < 11;
}
// computes the correction factor for the Stirling approximation
// for log(k!)
static RealType fc(IntType k)
{
if(k < 10) return detail::binomial_table<RealType>::table[k];
else {
RealType ikp1 = RealType(1) / (k + 1);
return (RealType(1)/12
- (RealType(1)/360
- (RealType(1)/1260)*(ikp1*ikp1))*(ikp1*ikp1))*ikp1;
}
}
void init()
{
using std::sqrt;
using std::pow;
RealType p = (0.5 < _p)? (1 - _p) : _p;
IntType t = _t;
m = static_cast<IntType>((t+1)*p);
if(use_inversion()) {
q_n = pow((1 - p), static_cast<RealType>(t));
} else {
btrd.r = p/(1-p);
btrd.nr = (t+1)*btrd.r;
btrd.npq = t*p*(1-p);
RealType sqrt_npq = sqrt(btrd.npq);
btrd.b = 1.15 + 2.53 * sqrt_npq;
btrd.a = -0.0873 + 0.0248*btrd.b + 0.01*p;
btrd.c = t*p + 0.5;
btrd.alpha = (2.83 + 5.1/btrd.b) * sqrt_npq;
btrd.v_r = 0.92 - 4.2/btrd.b;
btrd.u_rv_r = 0.86*btrd.v_r;
}
}
template<class URNG>
result_type generate(URNG& urng) const
{
using std::floor;
using std::abs;
using std::log;
while(true) {
RealType u;
RealType v = uniform_01<RealType>()(urng);
if(v <= btrd.u_rv_r) {
u = v/btrd.v_r - 0.43;
return static_cast<IntType>(floor(
(2*btrd.a/(0.5 - abs(u)) + btrd.b)*u + btrd.c));
}
if(v >= btrd.v_r) {
u = uniform_01<RealType>()(urng) - 0.5;
} else {
u = v/btrd.v_r - 0.93;
u = ((u < 0)? -0.5 : 0.5) - u;
v = uniform_01<RealType>()(urng) * btrd.v_r;
}
RealType us = 0.5 - abs(u);
IntType k = static_cast<IntType>(floor((2*btrd.a/us + btrd.b)*u + btrd.c));
if(k < 0 || k > _t) continue;
v = v*btrd.alpha/(btrd.a/(us*us) + btrd.b);
RealType km = abs(k - m);
if(km <= 15) {
RealType f = 1;
if(m < k) {
IntType i = m;
do {
++i;
f = f*(btrd.nr/i - btrd.r);
} while(i != k);
} else if(m > k) {
IntType i = k;
do {
++i;
v = v*(btrd.nr/i - btrd.r);
} while(i != m);
}
if(v <= f) return k;
else continue;
} else {
// final acceptance/rejection
v = log(v);
RealType rho =
(km/btrd.npq)*(((km/3. + 0.625)*km + 1./6)/btrd.npq + 0.5);
RealType t = -km*km/(2*btrd.npq);
if(v < t - rho) return k;
if(v > t + rho) continue;
IntType nm = _t - m + 1;
RealType h = (m + 0.5)*log((m + 1)/(btrd.r*nm))
+ fc(m) + fc(_t - m);
IntType nk = _t - k + 1;
if(v <= h + (_t+1)*log(static_cast<RealType>(nm)/nk)
+ (k + 0.5)*log(nk*btrd.r/(k+1))
- fc(k)
- fc(_t - k))
{
return k;
} else {
continue;
}
}
}
}
template<class URNG>
IntType invert(IntType t, RealType p, URNG& urng) const
{
RealType q = 1 - p;
RealType s = p / q;
RealType a = (t + 1) * s;
RealType r = q_n;
RealType u = uniform_01<RealType>()(urng);
IntType x = 0;
while(u > r) {
u = u - r;
++x;
RealType r1 = ((a/x) - s) * r;
// If r gets too small then the round-off error
// becomes a problem. At this point, p(i) is
// decreasing exponentially, so if we just call
// it 0, it's close enough. Note that the
// minimum value of q_n is about 1e-7, so we
// may need to be a little careful to make sure that
// we don't terminate the first time through the loop
// for float. (Hence the test that r is decreasing)
if(r1 < std::numeric_limits<RealType>::epsilon() && r1 < r) {
break;
}
r = r1;
}
return x;
}
// parameters
IntType _t;
RealType _p;
// common data
IntType m;
union {
// for btrd
struct {
RealType r;
RealType nr;
RealType npq;
RealType b;
RealType a;
RealType c;
RealType alpha;
RealType v_r;
RealType u_rv_r;
} btrd;
// for inversion
RealType q_n;
};
/// @endcond
};
}
// backwards compatibility
using random::binomial_distribution;
}
#include <boost/random/detail/enable_warnings.hpp>
#endif
@@ -0,0 +1,214 @@
/* boost random/cauchy_distribution.hpp header file
*
* Copyright Jens Maurer 2000-2001
* 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$
*
* Revision history
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_CAUCHY_DISTRIBUTION_HPP
#define BOOST_RANDOM_CAUCHY_DISTRIBUTION_HPP
#include <boost/config/no_tr1/cmath.hpp>
#include <iosfwd>
#include <istream>
#include <boost/limits.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/uniform_01.hpp>
namespace boost {
namespace random {
// Cauchy distribution:
/**
* The cauchy distribution is a continuous distribution with two
* parameters, median and sigma.
*
* It has \f$\displaystyle p(x) = \frac{\sigma}{\pi(\sigma^2 + (x-m)^2)}\f$
*/
template<class RealType = double>
class cauchy_distribution
{
public:
typedef RealType input_type;
typedef RealType result_type;
class param_type
{
public:
typedef cauchy_distribution distribution_type;
/** Constructs the parameters of the cauchy distribution. */
explicit param_type(RealType median_arg = RealType(0.0),
RealType sigma_arg = RealType(1.0))
: _median(median_arg), _sigma(sigma_arg) {}
// backwards compatibility for Boost.Random
/** Returns the median of the distribution. */
RealType median() const { return _median; }
/** Returns the sigma parameter of the distribution. */
RealType sigma() const { return _sigma; }
// The new names in C++0x.
/** Returns the median of the distribution. */
RealType a() const { return _median; }
/** Returns the sigma parameter of the distribution. */
RealType b() const { return _sigma; }
/** Writes the parameters to a std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{
os << parm._median << " " << parm._sigma;
return os;
}
/** Reads the parameters from a std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{
is >> parm._median >> std::ws >> parm._sigma;
return is;
}
/** Returns true if the two sets of parameters are equal. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._median == rhs._median && lhs._sigma == rhs._sigma; }
/** Returns true if the two sets of parameters are different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
RealType _median;
RealType _sigma;
};
/**
* Constructs a \cauchy_distribution with the paramters @c median
* and @c sigma.
*/
explicit cauchy_distribution(RealType median_arg = RealType(0.0),
RealType sigma_arg = RealType(1.0))
: _median(median_arg), _sigma(sigma_arg) { }
/**
* Constructs a \cauchy_distribution from it's parameters.
*/
explicit cauchy_distribution(const param_type& parm)
: _median(parm.median()), _sigma(parm.sigma()) { }
// compiler-generated copy ctor and assignment operator are fine
// backwards compatibility for Boost.Random
/** Returns: the "median" parameter of the distribution */
RealType median() const { return _median; }
/** Returns: the "sigma" parameter of the distribution */
RealType sigma() const { return _sigma; }
// The new names in C++0x
/** Returns: the "median" parameter of the distribution */
RealType a() const { return _median; }
/** Returns: the "sigma" parameter of the distribution */
RealType b() const { return _sigma; }
/** Returns the smallest value that the distribution can produce. */
RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return -(std::numeric_limits<RealType>::infinity)(); }
/** Returns the largest value that the distribution can produce. */
RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return (std::numeric_limits<RealType>::infinity)(); }
param_type param() const { return param_type(_median, _sigma); }
void param(const param_type& parm)
{
_median = parm.median();
_sigma = parm.sigma();
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { }
/**
* Returns: A random variate distributed according to the
* cauchy distribution.
*/
template<class Engine>
result_type operator()(Engine& eng)
{
// Can we have a boost::mathconst please?
const result_type pi = result_type(3.14159265358979323846);
using std::tan;
RealType val = uniform_01<RealType>()(eng)-result_type(0.5);
return _median + _sigma * tan(pi*val);
}
/**
* Returns: A random variate distributed according to the
* cauchy distribution with parameters specified by param.
*/
template<class Engine>
result_type operator()(Engine& eng, const param_type& parm)
{
return cauchy_distribution(parm)(eng);
}
/**
* Writes the distribution to a @c std::ostream.
*/
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, cauchy_distribution, cd)
{
os << cd._median << " " << cd._sigma;
return os;
}
/**
* Reads the distribution from a @c std::istream.
*/
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, cauchy_distribution, cd)
{
is >> cd._median >> std::ws >> cd._sigma;
return is;
}
/**
* Returns true if the two distributions will produce
* identical sequences of values, given equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(cauchy_distribution, lhs, rhs)
{ return lhs._median == rhs._median && lhs._sigma == rhs._sigma; }
/**
* Returns true if the two distributions may produce
* different sequences of values, given equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(cauchy_distribution)
private:
RealType _median;
RealType _sigma;
};
} // namespace random
using random::cauchy_distribution;
} // namespace boost
#endif // BOOST_RANDOM_CAUCHY_DISTRIBUTION_HPP
@@ -0,0 +1,209 @@
/* boost random/chi_squared_distribution.hpp header file
*
* Copyright Steven Watanabe 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_CHI_SQUARED_DISTRIBUTION_HPP_INCLUDED
#define BOOST_RANDOM_CHI_SQUARED_DISTRIBUTION_HPP_INCLUDED
#include <iosfwd>
#include <boost/limits.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/gamma_distribution.hpp>
namespace boost {
namespace random {
/**
* The chi squared distribution is a real valued distribution with
* one parameter, @c n. The distribution produces values > 0.
*
* The distribution function is
* \f$\displaystyle P(x) = \frac{x^{(n/2)-1}e^{-x/2}}{\Gamma(n/2)2^{n/2}}\f$.
*/
template<class RealType = double>
class chi_squared_distribution {
public:
typedef RealType result_type;
typedef RealType input_type;
class param_type {
public:
typedef chi_squared_distribution distribution_type;
/**
* Construct a param_type object. @c n
* is the parameter of the distribution.
*
* Requires: t >=0 && 0 <= p <= 1
*/
explicit param_type(RealType n_arg = RealType(1))
: _n(n_arg)
{}
/** Returns the @c n parameter of the distribution. */
RealType n() const { return _n; }
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
/** Writes the parameters of the distribution to a @c std::ostream. */
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os,
const param_type& parm)
{
os << parm._n;
return os;
}
/** Reads the parameters of the distribution from a @c std::istream. */
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is, param_type& parm)
{
is >> parm._n;
return is;
}
#endif
/** Returns true if the parameters have the same values. */
friend bool operator==(const param_type& lhs, const param_type& rhs)
{
return lhs._n == rhs._n;
}
/** Returns true if the parameters have different values. */
friend bool operator!=(const param_type& lhs, const param_type& rhs)
{
return !(lhs == rhs);
}
private:
RealType _n;
};
/**
* Construct a @c chi_squared_distribution object. @c n
* is the parameter of the distribution.
*
* Requires: t >=0 && 0 <= p <= 1
*/
explicit chi_squared_distribution(RealType n_arg = RealType(1))
: _impl(static_cast<RealType>(n_arg / 2))
{
}
/**
* Construct an @c chi_squared_distribution object from the
* parameters.
*/
explicit chi_squared_distribution(const param_type& parm)
: _impl(static_cast<RealType>(parm.n() / 2))
{
}
/**
* Returns a random variate distributed according to the
* chi squared distribution.
*/
template<class URNG>
RealType operator()(URNG& urng)
{
return 2 * _impl(urng);
}
/**
* Returns a random variate distributed according to the
* chi squared distribution with parameters specified by @c param.
*/
template<class URNG>
RealType operator()(URNG& urng, const param_type& parm) const
{
return chi_squared_distribution(parm)(urng);
}
/** Returns the @c n parameter of the distribution. */
RealType n() const { return 2 * _impl.alpha(); }
/** Returns the smallest value that the distribution can produce. */
RealType min BOOST_PREVENT_MACRO_SUBSTITUTION() const { return 0; }
/** Returns the largest value that the distribution can produce. */
RealType max BOOST_PREVENT_MACRO_SUBSTITUTION() const
{ return (std::numeric_limits<RealType>::infinity)(); }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(n()); }
/** Sets parameters of the distribution. */
void param(const param_type& parm)
{
typedef gamma_distribution<RealType> impl_type;
typename impl_type::param_type impl_parm(static_cast<RealType>(parm.n() / 2));
_impl.param(impl_parm);
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { _impl.reset(); }
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
/** Writes the parameters of the distribution to a @c std::ostream. */
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os,
const chi_squared_distribution& c2d)
{
os << c2d.param();
return os;
}
/** Reads the parameters of the distribution from a @c std::istream. */
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is,
chi_squared_distribution& c2d)
{
c2d.read(is);
return is;
}
#endif
/** Returns true if the two distributions will produce the same
sequence of values, given equal generators. */
friend bool operator==(const chi_squared_distribution& lhs,
const chi_squared_distribution& rhs)
{
return lhs._impl == rhs._impl;
}
/** Returns true if the two distributions could produce different
sequences of values, given equal generators. */
friend bool operator!=(const chi_squared_distribution& lhs,
const chi_squared_distribution& rhs)
{
return !(lhs == rhs);
}
private:
/// @cond show_private
template<class CharT, class Traits>
void read(std::basic_istream<CharT, Traits>& is) {
param_type parm;
if(is >> parm) {
param(parm);
}
}
gamma_distribution<RealType> _impl;
/// @endcond
};
}
}
#endif
@@ -0,0 +1,40 @@
/* boost random auto_link.hpp header file
*
* Copyright Steven Watanabe 2010
* 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)
*
* $Id$
*/
#ifndef BOOST_RANDOM_DETAIL_AUTO_LINK_HPP
#define BOOST_RANDOM_DETAIL_AUTO_LINK_HPP
#include <boost/config.hpp>
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_RANDOM_DYN_LINK)
#if defined(BOOST_RANDOM_SOURCE)
#define BOOST_RANDOM_DECL BOOST_SYMBOL_EXPORT
#else
#define BOOST_RANDOM_DECL BOOST_SYMBOL_IMPORT
#endif
#endif
#ifndef BOOST_RANDOM_DECL
#define BOOST_RANDOM_DECL
#endif
#if !defined(BOOST_RANDOM_NO_LIB) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_RANDOM_SOURCE)
#define BOOST_LIB_NAME boost_random
#if defined(BOOST_RANDOM_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)
#define BOOST_DYN_LINK
#endif
#include <boost/config/auto_link.hpp>
#endif
#endif
@@ -0,0 +1,18 @@
/* boost random/detail/config.hpp header file
*
* Copyright Steven Watanabe 2009
* 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$
*/
#include <boost/config.hpp>
#if (defined(BOOST_NO_OPERATORS_IN_NAMESPACE) || defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)) \
&& !defined(BOOST_MSVC)
#define BOOST_RANDOM_NO_STREAM_OPERATORS
#endif
@@ -0,0 +1,216 @@
/* boost random/detail/const_mod.hpp header file
*
* Copyright Jens Maurer 2000-2001
* 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$
*
* Revision history
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_CONST_MOD_HPP
#define BOOST_RANDOM_CONST_MOD_HPP
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/integer_traits.hpp>
#include <boost/type_traits/make_unsigned.hpp>
#include <boost/random/detail/large_arithmetic.hpp>
#include <boost/random/detail/disable_warnings.hpp>
namespace boost {
namespace random {
template<class IntType, IntType m>
class const_mod
{
public:
static IntType apply(IntType x)
{
if(((unsigned_m() - 1) & unsigned_m()) == 0)
return (unsigned_type(x)) & (unsigned_m() - 1);
else {
IntType suppress_warnings = (m == 0);
BOOST_ASSERT(suppress_warnings == 0);
return x % (m + suppress_warnings);
}
}
static IntType add(IntType x, IntType c)
{
if(((unsigned_m() - 1) & unsigned_m()) == 0)
return (unsigned_type(x) + unsigned_type(c)) & (unsigned_m() - 1);
else if(c == 0)
return x;
else if(x < m - c)
return x + c;
else
return x - (m - c);
}
static IntType mult(IntType a, IntType x)
{
if(((unsigned_m() - 1) & unsigned_m()) == 0)
return unsigned_type(a) * unsigned_type(x) & (unsigned_m() - 1);
else if(a == 0)
return 0;
else if(a == 1)
return x;
else if(m <= traits::const_max/a) // i.e. a*m <= max
return mult_small(a, x);
else if(traits::is_signed && (m%a < m/a))
return mult_schrage(a, x);
else
return mult_general(a, x);
}
static IntType mult_add(IntType a, IntType x, IntType c)
{
if(((unsigned_m() - 1) & unsigned_m()) == 0)
return (unsigned_type(a) * unsigned_type(x) + unsigned_type(c)) & (unsigned_m() - 1);
else if(a == 0)
return c;
else if(m <= (traits::const_max-c)/a) { // i.e. a*m+c <= max
IntType suppress_warnings = (m == 0);
BOOST_ASSERT(suppress_warnings == 0);
return (a*x+c) % (m + suppress_warnings);
} else
return add(mult(a, x), c);
}
static IntType pow(IntType a, boost::uintmax_t exponent)
{
IntType result = 1;
while(exponent != 0) {
if(exponent % 2 == 1) {
result = mult(result, a);
}
a = mult(a, a);
exponent /= 2;
}
return result;
}
static IntType invert(IntType x)
{ return x == 0 ? 0 : (m == 0? invert_euclidian0(x) : invert_euclidian(x)); }
private:
typedef integer_traits<IntType> traits;
typedef typename make_unsigned<IntType>::type unsigned_type;
const_mod(); // don't instantiate
static IntType mult_small(IntType a, IntType x)
{
IntType suppress_warnings = (m == 0);
BOOST_ASSERT(suppress_warnings == 0);
return a*x % (m + suppress_warnings);
}
static IntType mult_schrage(IntType a, IntType value)
{
const IntType q = m / a;
const IntType r = m % a;
BOOST_ASSERT(r < q); // check that overflow cannot happen
return sub(a*(value%q), r*(value/q));
}
static IntType mult_general(IntType a, IntType b)
{
IntType suppress_warnings = (m == 0);
BOOST_ASSERT(suppress_warnings == 0);
IntType modulus = m + suppress_warnings;
BOOST_ASSERT(modulus == m);
if(::boost::uintmax_t(modulus) <=
(::std::numeric_limits< ::boost::uintmax_t>::max)() / modulus)
{
return static_cast<IntType>(boost::uintmax_t(a) * b % modulus);
} else {
return static_cast<IntType>(detail::mulmod(a, b, modulus));
}
}
static IntType sub(IntType a, IntType b)
{
if(a < b)
return m - (b - a);
else
return a - b;
}
static unsigned_type unsigned_m()
{
if(m == 0) {
return unsigned_type((std::numeric_limits<IntType>::max)()) + 1;
} else {
return unsigned_type(m);
}
}
// invert c in the finite field (mod m) (m must be prime)
static IntType invert_euclidian(IntType c)
{
// we are interested in the gcd factor for c, because this is our inverse
BOOST_ASSERT(c > 0);
IntType l1 = 0;
IntType l2 = 1;
IntType n = c;
IntType p = m;
for(;;) {
IntType q = p / n;
l1 += q * l2;
p -= q * n;
if(p == 0)
return l2;
IntType q2 = n / p;
l2 += q2 * l1;
n -= q2 * p;
if(n == 0)
return m - l1;
}
}
// invert c in the finite field (mod m) (c must be relatively prime to m)
static IntType invert_euclidian0(IntType c)
{
// we are interested in the gcd factor for c, because this is our inverse
BOOST_ASSERT(c > 0);
if(c == 1) return 1;
IntType l1 = 0;
IntType l2 = 1;
IntType n = c;
IntType p = m;
IntType max = (std::numeric_limits<IntType>::max)();
IntType q = max / n;
BOOST_ASSERT(max % n != n - 1 && "c must be relatively prime to m.");
l1 += q * l2;
p = max - q * n + 1;
for(;;) {
if(p == 0)
return l2;
IntType q2 = n / p;
l2 += q2 * l1;
n -= q2 * p;
if(n == 0)
return m - l1;
q = p / n;
l1 += q * l2;
p -= q * n;
}
}
};
} // namespace random
} // namespace boost
#include <boost/random/detail/enable_warnings.hpp>
#endif // BOOST_RANDOM_CONST_MOD_HPP
@@ -0,0 +1,29 @@
/* boost random/detail/disable_warnings.hpp header file
*
* Copyright Steven Watanabe 2009
* 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$
*
*/
// No #include guard. This header is intended to be included multiple times.
#include <boost/config.hpp>
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4512)
#pragma warning(disable:4127)
#pragma warning(disable:4724)
#pragma warning(disable:4800) // 'int' : forcing value to bool 'true' or 'false' (performance warning)
#endif
#if defined(BOOST_GCC) && BOOST_GCC >= 40600
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wlogical-op"
#endif
@@ -0,0 +1,22 @@
/* boost random/detail/enable_warnings.hpp header file
*
* Copyright Steven Watanabe 2009
* 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$
*
*/
// No #include guard. This header is intended to be included multiple times.
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
#if defined(BOOST_GCC) && BOOST_GCC >= 40600
#pragma GCC diagnostic pop
#endif
@@ -0,0 +1,36 @@
/* boost random/detail/generator_bits.hpp header file
*
* Copyright Steven Watanabe 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_GENERATOR_BITS_HPP
#define BOOST_RANDOM_DETAIL_GENERATOR_BITS_HPP
#include <boost/limits.hpp>
namespace boost {
namespace random {
namespace detail {
// This is a temporary measure that retains backwards
// compatibility.
template<class URNG>
struct generator_bits {
static std::size_t value() {
return std::numeric_limits<typename URNG::result_type>::digits;
}
};
} // namespace detail
} // namespace random
} // namespace boost
#endif // BOOST_RANDOM_DETAIL_GENERATOR_BITS_HPP
@@ -0,0 +1,40 @@
/* boost random/mersenne_twister.hpp header file
*
* Copyright Jens Maurer 2000-2001
* Copyright Steven Watanabe 2010
* 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_GENERATOR_SEED_SEQ_HPP_INCLUDED
#define BOOST_RANDOM_DETAIL_GENERATOR_SEED_SEQ_HPP_INCLUDED
namespace boost {
namespace random {
namespace detail {
template<class Generator>
class generator_seed_seq {
public:
generator_seed_seq(Generator& g) : gen(&g) {}
template<class It>
void generate(It first, It last) {
for(; first != last; ++first) {
*first = (*gen)();
}
}
private:
Generator* gen;
};
}
}
}
#endif
@@ -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
@@ -0,0 +1,84 @@
/* boost random/detail/integer_log2.hpp header file
*
* Copyright Steven Watanabe 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_INTEGER_LOG2_HPP
#define BOOST_RANDOM_DETAIL_INTEGER_LOG2_HPP
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/pending/integer_log2.hpp>
namespace boost {
namespace random {
namespace detail {
#if !defined(BOOST_NO_CXX11_CONSTEXPR)
#define BOOST_RANDOM_DETAIL_CONSTEXPR constexpr
#elif defined(BOOST_MSVC)
#define BOOST_RANDOM_DETAIL_CONSTEXPR __forceinline
#elif defined(__GNUC__) && __GNUC__ >= 4
#define BOOST_RANDOM_DETAIL_CONSTEXPR inline __attribute__((__const__)) __attribute__((__always_inline__))
#else
#define BOOST_RANDOM_DETAIL_CONSTEXPR inline
#endif
template<int Shift>
struct integer_log2_impl
{
#if defined(BOOST_NO_CXX11_CONSTEXPR)
template<class T>
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);
}
#else
template<class T>
BOOST_RANDOM_DETAIL_CONSTEXPR static int apply2(T t, int accum, int update)
{
return integer_log2_impl<Shift / 2>::apply(t >> update, accum + update);
}
template<class T>
BOOST_RANDOM_DETAIL_CONSTEXPR static int apply(T t, int accum)
{
return apply2(t, accum, ((t >> Shift) != 0) * Shift);
}
#endif
};
template<>
struct integer_log2_impl<1>
{
template<class T>
BOOST_RANDOM_DETAIL_CONSTEXPR static int apply(T t, int accum)
{
return int(t >> 1) + accum;
}
};
template<class T>
BOOST_RANDOM_DETAIL_CONSTEXPR int integer_log2(T t)
{
return integer_log2_impl<
::boost::detail::max_pow2_less<
::std::numeric_limits<T>::digits, 4
>::value
>::apply(t, 0);
}
} // namespace detail
} // namespace random
} // namespace boost
#endif // BOOST_RANDOM_DETAIL_INTEGER_LOG2_HPP
@@ -0,0 +1,45 @@
/* boost random/detail/iterator_mixin.hpp header file
*
* Copyright Jens Maurer 2000-2001
* 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.
*
* Revision history
*/
#ifndef BOOST_ITERATOR_MIXIN_HPP
#define BOOST_ITERATOR_MIXIN_HPP
#include <boost/operators.hpp>
namespace boost {
// must be in boost namespace, otherwise the inline friend trick fails
template<class Generator, class ResultType>
class generator_iterator_mixin_adapter
: incrementable<Generator>, equality_comparable<Generator>
{
public:
typedef std::input_iterator_tag iterator_category;
typedef ResultType value_type;
typedef std::ptrdiff_t difference_type;
typedef const value_type * pointer;
typedef const value_type & reference;
Generator& operator++() { v = cast()(); return cast(); }
const value_type& operator*() const { return v; }
protected:
// instantiate from derived classes only
generator_iterator_mixin_adapter() { }
void iterator_init() { operator++(); }
private:
Generator & cast() { return static_cast<Generator&>(*this); }
value_type v;
};
} // namespace boost
#endif // BOOST_ITERATOR_MIXIN_HPP
@@ -0,0 +1,122 @@
/* boost random/detail/large_arithmetic.hpp header file
*
* Copyright Steven Watanabe 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_LARGE_ARITHMETIC_HPP
#define BOOST_RANDOM_DETAIL_LARGE_ARITHMETIC_HPP
#include <boost/cstdint.hpp>
#include <boost/integer.hpp>
#include <boost/limits.hpp>
#include <boost/random/detail/integer_log2.hpp>
#include <boost/random/detail/disable_warnings.hpp>
namespace boost {
namespace random {
namespace detail {
struct div_t {
boost::uintmax_t quotient;
boost::uintmax_t remainder;
};
inline div_t muldivmod(boost::uintmax_t a, boost::uintmax_t b, boost::uintmax_t m)
{
const int bits =
::std::numeric_limits< ::boost::uintmax_t>::digits / 2;
const ::boost::uintmax_t mask = (::boost::uintmax_t(1) << bits) - 1;
typedef ::boost::uint_t<bits>::fast digit_t;
int shift = std::numeric_limits< ::boost::uintmax_t>::digits - 1
- detail::integer_log2(m);
a <<= shift;
m <<= shift;
digit_t product[4] = { 0, 0, 0, 0 };
digit_t a_[2] = { digit_t(a & mask), digit_t((a >> bits) & mask) };
digit_t b_[2] = { digit_t(b & mask), digit_t((b >> bits) & mask) };
digit_t m_[2] = { digit_t(m & mask), digit_t((m >> bits) & mask) };
// multiply a * b
for(int i = 0; i < 2; ++i) {
digit_t carry = 0;
for(int j = 0; j < 2; ++j) {
::boost::uint64_t temp = ::boost::uintmax_t(a_[i]) * b_[j] +
carry + product[i + j];
product[i + j] = digit_t(temp & mask);
carry = digit_t(temp >> bits);
}
if(carry != 0) {
product[i + 2] += carry;
}
}
digit_t quotient[2];
if(m == 0) {
div_t result = {
((::boost::uintmax_t(product[3]) << bits) | product[2]),
((::boost::uintmax_t(product[1]) << bits) | product[0]) >> shift,
};
return result;
}
// divide product / m
for(int i = 3; i >= 2; --i) {
::boost::uintmax_t temp =
::boost::uintmax_t(product[i]) << bits | product[i - 1];
digit_t q = digit_t((product[i] == m_[1]) ? mask : temp / m_[1]);
::boost::uintmax_t rem =
((temp - ::boost::uintmax_t(q) * m_[1]) << bits) + product[i - 2];
::boost::uintmax_t diff = m_[0] * ::boost::uintmax_t(q);
int error = 0;
if(diff > rem) {
if(diff - rem > m) {
error = 2;
} else {
error = 1;
}
}
q -= error;
rem = rem + error * m - diff;
quotient[i - 2] = q;
product[i] = 0;
product[i-1] = static_cast<digit_t>((rem >> bits) & mask);
product[i-2] = static_cast<digit_t>(rem & mask);
}
div_t result = {
((::boost::uintmax_t(quotient[1]) << bits) | quotient[0]),
((::boost::uintmax_t(product[1]) << bits) | product[0]) >> shift,
};
return result;
}
inline boost::uintmax_t muldiv(boost::uintmax_t a, boost::uintmax_t b, boost::uintmax_t m)
{ return detail::muldivmod(a, b, m).quotient; }
inline boost::uintmax_t mulmod(boost::uintmax_t a, boost::uintmax_t b, boost::uintmax_t m)
{ return detail::muldivmod(a, b, m).remainder; }
} // namespace detail
} // namespace random
} // namespace boost
#include <boost/random/detail/enable_warnings.hpp>
#endif // BOOST_RANDOM_DETAIL_LARGE_ARITHMETIC_HPP
@@ -0,0 +1,84 @@
/* boost random/detail/operators.hpp header file
*
* 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_OPERATORS_HPP
#define BOOST_RANDOM_DETAIL_OPERATORS_HPP
#include <boost/random/detail/config.hpp>
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1310) \
|| BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100))
#define BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, T, t) \
template<class CharT, class Traits> \
friend std::basic_ostream<CharT,Traits>& \
operator<<(std::basic_ostream<CharT,Traits>& os, const T& t) { \
t.print(os, t); \
return os; \
} \
template<class CharT, class Traits> \
static std::basic_ostream<CharT,Traits>& \
print(std::basic_ostream<CharT,Traits>& os, const T& t)
#define BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, T, t) \
template<class CharT, class Traits> \
friend std::basic_istream<CharT,Traits>& \
operator>>(std::basic_istream<CharT,Traits>& is, T& t) { \
t.read(is, t); \
return is; \
} \
template<class CharT, class Traits> \
static std::basic_istream<CharT,Traits>& \
read(std::basic_istream<CharT,Traits>& is, T& t)
#endif
#if defined(__BORLANDC__)
#define BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(T, lhs, rhs) \
bool operator==(const T& rhs) const \
{ return T::is_equal(*this, rhs); } \
static bool is_equal(const T& lhs, const T& rhs)
#define BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(T) \
bool operator!=(const T& rhs) const \
{ return !T::is_equal(*this, rhs); }
#endif
#ifndef BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR
#define BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, T, t) \
template<class CharT, class Traits> \
friend std::basic_ostream<CharT,Traits>& \
operator<<(std::basic_ostream<CharT,Traits>& os, const T& t)
#endif
#ifndef BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR
#define BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, T, t) \
template<class CharT, class Traits> \
friend std::basic_istream<CharT,Traits>& \
operator>>(std::basic_istream<CharT,Traits>& is, T& t)
#endif
#ifndef BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR
#define BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(T, lhs, rhs) \
friend bool operator==(const T& lhs, const T& rhs)
#endif
#ifndef BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR
#define BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(T) \
friend bool operator!=(const T& lhs, const T& rhs) \
{ return !(lhs == rhs); }
#endif
#endif
@@ -0,0 +1,384 @@
/* boost random/detail/polynomial.hpp header file
*
* Copyright Steven Watanabe 2014
* 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_POLYNOMIAL_HPP
#define BOOST_RANDOM_DETAIL_POLYNOMIAL_HPP
#include <cstddef>
#include <limits>
#include <vector>
#include <algorithm>
#include <boost/assert.hpp>
#include <boost/cstdint.hpp>
namespace boost {
namespace random {
namespace detail {
class polynomial_ops {
public:
typedef unsigned long digit_t;
static void add(std::size_t size, const digit_t * lhs,
const digit_t * rhs, digit_t * output)
{
for(std::size_t i = 0; i < size; ++i) {
output[i] = lhs[i] ^ rhs[i];
}
}
static void add_shifted_inplace(std::size_t size, const digit_t * lhs,
digit_t * output, std::size_t shift)
{
if(shift == 0) {
add(size, lhs, output, output);
return;
}
std::size_t bits = std::numeric_limits<digit_t>::digits;
digit_t prev = 0;
for(std::size_t i = 0; i < size; ++i) {
digit_t tmp = lhs[i];
output[i] ^= (tmp << shift) | (prev >> (bits-shift));
prev = tmp;
}
output[size] ^= (prev >> (bits-shift));
}
static void multiply_simple(std::size_t size, const digit_t * lhs,
const digit_t * rhs, digit_t * output)
{
std::size_t bits = std::numeric_limits<digit_t>::digits;
for(std::size_t i = 0; i < 2*size; ++i) {
output[i] = 0;
}
for(std::size_t i = 0; i < size; ++i) {
for(std::size_t j = 0; j < bits; ++j) {
if((lhs[i] & (digit_t(1) << j)) != 0) {
add_shifted_inplace(size, rhs, output + i, j);
}
}
}
}
// memory requirements: (size - cutoff) * 4 + next_smaller
static void multiply_karatsuba(std::size_t size,
const digit_t * lhs, const digit_t * rhs,
digit_t * output)
{
if(size < 64) {
multiply_simple(size, lhs, rhs, output);
return;
}
// split in half
std::size_t cutoff = size/2;
multiply_karatsuba(cutoff, lhs, rhs, output);
multiply_karatsuba(size - cutoff, lhs + cutoff, rhs + cutoff,
output + cutoff*2);
std::vector<digit_t> local1(size - cutoff);
std::vector<digit_t> local2(size - cutoff);
// combine the digits for the inner multiply
add(cutoff, lhs, lhs + cutoff, &local1[0]);
if(size & 1) local1[cutoff] = lhs[size - 1];
add(cutoff, rhs + cutoff, rhs, &local2[0]);
if(size & 1) local2[cutoff] = rhs[size - 1];
std::vector<digit_t> local3((size - cutoff) * 2);
multiply_karatsuba(size - cutoff, &local1[0], &local2[0], &local3[0]);
add(cutoff * 2, output, &local3[0], &local3[0]);
add((size - cutoff) * 2, output + cutoff*2, &local3[0], &local3[0]);
// Finally, add the inner result
add((size - cutoff) * 2, output + cutoff, &local3[0], output + cutoff);
}
static void multiply_add_karatsuba(std::size_t size,
const digit_t * lhs, const digit_t * rhs,
digit_t * output)
{
std::vector<digit_t> buf(size * 2);
multiply_karatsuba(size, lhs, rhs, &buf[0]);
add(size * 2, &buf[0], output, output);
}
static void multiply(const digit_t * lhs, std::size_t lhs_size,
const digit_t * rhs, std::size_t rhs_size,
digit_t * output)
{
std::fill_n(output, lhs_size + rhs_size, digit_t(0));
multiply_add(lhs, lhs_size, rhs, rhs_size, output);
}
static void multiply_add(const digit_t * lhs, std::size_t lhs_size,
const digit_t * rhs, std::size_t rhs_size,
digit_t * output)
{
// split into pieces that can be passed to
// karatsuba multiply.
while(lhs_size != 0) {
if(lhs_size < rhs_size) {
std::swap(lhs, rhs);
std::swap(lhs_size, rhs_size);
}
multiply_add_karatsuba(rhs_size, lhs, rhs, output);
lhs += rhs_size;
lhs_size -= rhs_size;
output += rhs_size;
}
}
static void copy_bits(const digit_t * x, std::size_t low, std::size_t high,
digit_t * out)
{
const std::size_t bits = std::numeric_limits<digit_t>::digits;
std::size_t offset = low/bits;
x += offset;
low -= offset*bits;
high -= offset*bits;
std::size_t n = (high-low)/bits;
if(low == 0) {
for(std::size_t i = 0; i < n; ++i) {
out[i] = x[i];
}
} else {
for(std::size_t i = 0; i < n; ++i) {
out[i] = (x[i] >> low) | (x[i+1] << (bits-low));
}
}
if((high-low)%bits) {
digit_t low_mask = (digit_t(1) << ((high-low)%bits)) - 1;
digit_t result = (x[n] >> low);
if(low != 0 && (n+1)*bits < high) {
result |= (x[n+1] << (bits-low));
}
out[n] = (result & low_mask);
}
}
static void shift_left(digit_t * val, std::size_t size, std::size_t shift)
{
const std::size_t bits = std::numeric_limits<digit_t>::digits;
BOOST_ASSERT(shift > 0);
BOOST_ASSERT(shift < bits);
digit_t prev = 0;
for(std::size_t i = 0; i < size; ++i) {
digit_t tmp = val[i];
val[i] = (prev >> (bits - shift)) | (val[i] << shift);
prev = tmp;
}
}
static digit_t sqr(digit_t val) {
const std::size_t bits = std::numeric_limits<digit_t>::digits;
digit_t mask = (digit_t(1) << bits/2) - 1;
for(std::size_t i = bits; i > 1; i /= 2) {
val = ((val & ~mask) << i/2) | (val & mask);
mask = mask & (mask >> i/4);
mask = mask | (mask << i/2);
}
return val;
}
static void sqr(digit_t * val, std::size_t size)
{
const std::size_t bits = std::numeric_limits<digit_t>::digits;
digit_t mask = (digit_t(1) << bits/2) - 1;
for(std::size_t i = 0; i < size; ++i) {
digit_t x = val[size - i - 1];
val[(size - i - 1) * 2] = sqr(x & mask);
val[(size - i - 1) * 2 + 1] = sqr(x >> bits/2);
}
}
// optimized for the case when the modulus has few bits set.
struct sparse_mod {
sparse_mod(const digit_t * divisor, std::size_t divisor_bits)
{
const std::size_t bits = std::numeric_limits<digit_t>::digits;
_remainder_bits = divisor_bits - 1;
for(std::size_t i = 0; i < divisor_bits; ++i) {
if(divisor[i/bits] & (digit_t(1) << i%bits)) {
_bit_indices.push_back(i);
}
}
BOOST_ASSERT(_bit_indices.back() == divisor_bits - 1);
_bit_indices.pop_back();
if(_bit_indices.empty()) {
_block_bits = divisor_bits;
_lower_bits = 0;
} else {
_block_bits = divisor_bits - _bit_indices.back() - 1;
_lower_bits = _bit_indices.back() + 1;
}
_partial_quotient.resize((_block_bits + bits - 1)/bits);
}
void operator()(digit_t * dividend, std::size_t dividend_bits)
{
const std::size_t bits = std::numeric_limits<digit_t>::digits;
while(dividend_bits > _remainder_bits) {
std::size_t block_start = (std::max)(dividend_bits - _block_bits, _remainder_bits);
std::size_t block_size = (dividend_bits - block_start + bits - 1) / bits;
copy_bits(dividend, block_start, dividend_bits, &_partial_quotient[0]);
for(std::size_t i = 0; i < _bit_indices.size(); ++i) {
std::size_t pos = _bit_indices[i] + block_start - _remainder_bits;
add_shifted_inplace(block_size, &_partial_quotient[0], dividend + pos/bits, pos%bits);
}
add_shifted_inplace(block_size, &_partial_quotient[0], dividend + block_start/bits, block_start%bits);
dividend_bits = block_start;
}
}
std::vector<digit_t> _partial_quotient;
std::size_t _remainder_bits;
std::size_t _block_bits;
std::size_t _lower_bits;
std::vector<std::size_t> _bit_indices;
};
// base should have the same number of bits as mod
// base, and mod should both be able to hold a power
// of 2 >= mod_bits. out needs to be twice as large.
static void mod_pow_x(boost::uintmax_t exponent, const digit_t * mod, std::size_t mod_bits, digit_t * out)
{
const std::size_t bits = std::numeric_limits<digit_t>::digits;
const std::size_t n = (mod_bits + bits - 1) / bits;
const std::size_t highbit = mod_bits - 1;
if(exponent == 0) {
out[0] = 1;
std::fill_n(out + 1, n - 1, digit_t(0));
return;
}
boost::uintmax_t i = std::numeric_limits<boost::uintmax_t>::digits - 1;
while(((boost::uintmax_t(1) << i) & exponent) == 0) {
--i;
}
out[0] = 2;
std::fill_n(out + 1, n - 1, digit_t(0));
sparse_mod m(mod, mod_bits);
while(i--) {
sqr(out, n);
m(out, 2 * mod_bits - 1);
if((boost::uintmax_t(1) << i) & exponent) {
shift_left(out, n, 1);
if(out[highbit / bits] & (digit_t(1) << highbit%bits))
add(n, out, mod, out);
}
}
}
};
class polynomial
{
typedef polynomial_ops::digit_t digit_t;
public:
polynomial() : _size(0) {}
class reference {
public:
reference(digit_t &value, int idx)
: _value(value), _idx(idx) {}
operator bool() const { return (_value & (digit_t(1) << _idx)) != 0; }
reference& operator=(bool b)
{
if(b) {
_value |= (digit_t(1) << _idx);
} else {
_value &= ~(digit_t(1) << _idx);
}
return *this;
}
reference &operator^=(bool b)
{
_value ^= (digit_t(b) << _idx);
return *this;
}
reference &operator=(const reference &other)
{
return *this = static_cast<bool>(other);
}
private:
digit_t &_value;
int _idx;
};
reference operator[](std::size_t i)
{
static const std::size_t bits = std::numeric_limits<digit_t>::digits;
ensure_bit(i);
return reference(_storage[i/bits], i%bits);
}
bool operator[](std::size_t i) const
{
static const std::size_t bits = std::numeric_limits<digit_t>::digits;
if(i < size())
return (_storage[i/bits] & (digit_t(1) << (i%bits))) != 0;
else
return false;
}
std::size_t size() const
{
return _size;
}
void resize(std::size_t n)
{
static const std::size_t bits = std::numeric_limits<digit_t>::digits;
_storage.resize((n + bits - 1)/bits);
// clear the high order bits in case we're shrinking.
if(n%bits) {
_storage.back() &= ((digit_t(1) << (n%bits)) - 1);
}
_size = n;
}
friend polynomial operator*(const polynomial &lhs, const polynomial &rhs);
friend polynomial mod_pow_x(boost::uintmax_t exponent, polynomial mod);
private:
std::vector<polynomial_ops::digit_t> _storage;
std::size_t _size;
void ensure_bit(std::size_t i)
{
if(i >= size()) {
resize(i + 1);
}
}
void normalize()
{
while(size() && (*this)[size() - 1] == 0)
resize(size() - 1);
}
};
inline polynomial operator*(const polynomial &lhs, const polynomial &rhs)
{
polynomial result;
result._storage.resize(lhs._storage.size() + rhs._storage.size());
polynomial_ops::multiply(&lhs._storage[0], lhs._storage.size(),
&rhs._storage[0], rhs._storage.size(),
&result._storage[0]);
result._size = lhs._size + rhs._size;
return result;
}
inline polynomial mod_pow_x(boost::uintmax_t exponent, polynomial mod)
{
polynomial result;
mod.normalize();
std::size_t mod_size = mod.size();
result._storage.resize(mod._storage.size() * 2);
result._size = mod.size() * 2;
polynomial_ops::mod_pow_x(exponent, &mod._storage[0], mod_size, &result._storage[0]);
result.resize(mod.size() - 1);
return result;
}
}
}
}
#endif // BOOST_RANDOM_DETAIL_POLYNOMIAL_HPP
@@ -0,0 +1,67 @@
/* boost random/detail/ptr_helper.hpp header file
*
* Copyright Jens Maurer 2002
* 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_PTR_HELPER_HPP
#define BOOST_RANDOM_DETAIL_PTR_HELPER_HPP
#include <boost/config.hpp>
namespace boost {
namespace random {
namespace detail {
// type_traits could help here, but I don't want to depend on type_traits.
template<class T>
struct ptr_helper
{
typedef T value_type;
typedef T& reference_type;
typedef const T& rvalue_type;
static reference_type ref(T& r) { return r; }
static const T& ref(const T& r) { return r; }
};
template<class T>
struct ptr_helper<T&>
{
typedef T value_type;
typedef T& reference_type;
typedef T& rvalue_type;
static reference_type ref(T& r) { return r; }
static const T& ref(const T& r) { return r; }
};
template<class T>
struct ptr_helper<T*>
{
typedef T value_type;
typedef T& reference_type;
typedef T* rvalue_type;
static reference_type ref(T * p) { return *p; }
static const T& ref(const T * p) { return *p; }
};
} // namespace detail
} // namespace random
} // namespace boost
//
// BOOST_RANDOM_PTR_HELPER_SPEC --
//
// Helper macro for broken compilers defines specializations of
// ptr_helper.
//
# define BOOST_RANDOM_PTR_HELPER_SPEC(T)
#endif // BOOST_RANDOM_DETAIL_PTR_HELPER_HPP
@@ -0,0 +1,115 @@
/* boost random/detail/seed.hpp header file
*
* Copyright Steven Watanabe 2009
* 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_SEED_HPP
#define BOOST_RANDOM_DETAIL_SEED_HPP
#include <boost/config.hpp>
// Sun seems to have trouble with the use of SFINAE for the
// templated constructor. So does Borland.
#if !defined(BOOST_NO_SFINAE) && !defined(__SUNPRO_CC) && !defined(__BORLANDC__)
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/mpl/bool.hpp>
namespace boost {
namespace random {
namespace detail {
template<class T>
struct disable_seed : boost::disable_if<boost::is_arithmetic<T> > {};
template<class Engine, class T>
struct disable_constructor : disable_seed<T> {};
template<class Engine>
struct disable_constructor<Engine, Engine> {};
#define BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(Self, Generator, gen) \
template<class Generator> \
explicit Self(Generator& gen, typename ::boost::random::detail::disable_constructor<Self, Generator>::type* = 0)
#define BOOST_RANDOM_DETAIL_GENERATOR_SEED(Self, Generator, gen) \
template<class Generator> \
void seed(Generator& gen, typename ::boost::random::detail::disable_seed<Generator>::type* = 0)
#define BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(Self, SeedSeq, seq) \
template<class SeedSeq> \
explicit Self(SeedSeq& seq, typename ::boost::random::detail::disable_constructor<Self, SeedSeq>::type* = 0)
#define BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(Self, SeedSeq, seq) \
template<class SeedSeq> \
void seed(SeedSeq& seq, typename ::boost::random::detail::disable_seed<SeedSeq>::type* = 0)
#define BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(Self, T, x) \
explicit Self(const T& x)
#define BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(Self, T, x) \
void seed(const T& x)
}
}
}
#else
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/mpl/bool.hpp>
#define BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(Self, Generator, gen) \
Self(Self& other) { *this = other; } \
Self(const Self& other) { *this = other; } \
template<class Generator> \
explicit Self(Generator& gen) { \
boost_random_constructor_impl(gen, ::boost::is_arithmetic<Generator>());\
} \
template<class Generator> \
void boost_random_constructor_impl(Generator& gen, ::boost::mpl::false_)
#define BOOST_RANDOM_DETAIL_GENERATOR_SEED(Self, Generator, gen) \
template<class Generator> \
void seed(Generator& gen) { \
boost_random_seed_impl(gen, ::boost::is_arithmetic<Generator>());\
}\
template<class Generator>\
void boost_random_seed_impl(Generator& gen, ::boost::mpl::false_)
#define BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(Self, SeedSeq, seq) \
Self(Self& other) { *this = other; } \
Self(const Self& other) { *this = other; } \
template<class SeedSeq> \
explicit Self(SeedSeq& seq) { \
boost_random_constructor_impl(seq, ::boost::is_arithmetic<SeedSeq>());\
} \
template<class SeedSeq> \
void boost_random_constructor_impl(SeedSeq& seq, ::boost::mpl::false_)
#define BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(Self, SeedSeq, seq) \
template<class SeedSeq> \
void seed(SeedSeq& seq) { \
boost_random_seed_impl(seq, ::boost::is_arithmetic<SeedSeq>()); \
} \
template<class SeedSeq> \
void boost_random_seed_impl(SeedSeq& seq, ::boost::mpl::false_)
#define BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(Self, T, x) \
explicit Self(const T& x) { boost_random_constructor_impl(x, ::boost::mpl::true_()); }\
void boost_random_constructor_impl(const T& x, ::boost::mpl::true_)
#define BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(Self, T, x) \
void seed(const T& x) { boost_random_seed_impl(x, ::boost::mpl::true_()); }\
void boost_random_seed_impl(const T& x, ::boost::mpl::true_)
#endif
#endif
@@ -0,0 +1,398 @@
/* boost random/detail/seed.hpp header file
*
* Copyright Steven Watanabe 2009
* 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_SEED_IMPL_HPP
#define BOOST_RANDOM_DETAIL_SEED_IMPL_HPP
#include <stdexcept>
#include <boost/cstdint.hpp>
#include <boost/throw_exception.hpp>
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/integer/integer_mask.hpp>
#include <boost/integer/static_log2.hpp>
#include <boost/random/traits.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/int.hpp>
#include <boost/random/detail/const_mod.hpp>
#include <boost/random/detail/integer_log2.hpp>
#include <boost/random/detail/signed_unsigned_tools.hpp>
#include <boost/random/detail/generator_bits.hpp>
#include <boost/random/detail/disable_warnings.hpp>
namespace boost {
namespace random {
namespace detail {
// finds the seed type of an engine, given its
// result_type. If the result_type is integral
// the seed type is the same. If the result_type
// is floating point, the seed type is uint32_t
template<class T>
struct seed_type
{
typedef typename boost::mpl::if_<boost::is_integral<T>,
T,
boost::uint32_t
>::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(T(arg * arg), n / 2,
n%2 == 0? result : T(result * arg));
}
};
template<>
struct const_pow_impl<0>
{
template<class T>
static T call(T, int, 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::fmod;
typedef typename Engine::result_type RealType;
const int Bits = detail::generator_bits<Engine>::value();
int remaining_bits = 0;
boost::uint_least32_t saved_bits = 0;
RealType multiplier = pow2<RealType>( Bits);
RealType mult32 = RealType(4294967296.0); // 2^32
while(true) {
RealType val = eng() * multiplier;
int available_bits = 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 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(fmod(val, mult32)) & (divisor - 1);
val = val / divisor;
*begin++ = saved_bits | (extra_bits << remaining_bits);
if(begin == end) return;
available_bits -= 32 - remaining_bits;
remaining_bits = 0;
}
// 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(fmod(val, mult32));
val /= mult32;
*begin++ = word;
if(begin == end) return;
}
}
remaining_bits = available_bits;
saved_bits = static_cast<boost::uint_least32_t>(val);
}
}
}
template<class Engine, class Iter>
void generate_from_int(Engine& eng, Iter begin, Iter end)
{
typedef typename Engine::result_type IntType;
typedef typename boost::random::traits::make_unsigned<IntType>::type unsigned_type;
int remaining_bits = 0;
boost::uint_least32_t saved_bits = 0;
unsigned_type range = boost::random::detail::subtract<IntType>()((eng.max)(), (eng.min)());
int bits =
(range == (std::numeric_limits<unsigned_type>::max)()) ?
std::numeric_limits<unsigned_type>::digits :
detail::integer_log2(range + 1);
{
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);
bits = bits - discarded_bits + extra_bits;
}
}
unsigned_type mask = (static_cast<unsigned_type>(2) << (bits - 1)) - 1;
unsigned_type limit = ((range + 1) & ~mask) - 1;
while(true) {
unsigned_type val;
do {
val = boost::random::detail::subtract<IntType>()(eng(), (eng.min)());
} while(limit != range && val > limit);
val &= mask;
int available_bits = 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;
int suppress_warning = (bits >= 32);
BOOST_ASSERT(suppress_warning == 1);
val >>= (32 * suppress_warning);
*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(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);
if(begin == end) return;
available_bits -= 32 - remaining_bits;
remaining_bits = 0;
}
if(bits >= 32) {
for(; available_bits >= 32; available_bits -= 32) {
boost::uint_least32_t word = boost::uint_least32_t(val) & 0xFFFFFFFFu;
int suppress_warning = (bits >= 32);
BOOST_ASSERT(suppress_warning == 1);
val >>= (32 * suppress_warning);
*begin++ = word;
if(begin == end) return;
}
}
remaining_bits = available_bits;
saved_bits = static_cast<boost::uint_least32_t>(val);
}
}
}
template<class Engine, class Iter>
void generate_impl(Engine& eng, Iter first, Iter last, boost::mpl::true_)
{
return detail::generate_from_int(eng, first, last);
}
template<class Engine, class Iter>
void generate_impl(Engine& eng, Iter first, Iter last, boost::mpl::false_)
{
return detail::generate_from_real(eng, first, last);
}
template<class Engine, class Iter>
void generate(Engine& eng, Iter first, Iter last)
{
return detail::generate_impl(eng, first, last, boost::random::traits::is_integral<typename Engine::result_type>());
}
template<class IntType, IntType m, class SeedSeq>
IntType seed_one_int(SeedSeq& seq)
{
static const int log = ::boost::mpl::if_c<(m == 0),
::boost::mpl::int_<(::std::numeric_limits<IntType>::digits)>,
::boost::static_log2<m> >::type::value;
static const int k =
(log + ((~(static_cast<IntType>(2) << (log - 1)) & m)? 32 : 31)) / 32;
::boost::uint_least32_t array[log / 32 + 4];
seq.generate(&array[0], &array[0] + k + 3);
IntType s = 0;
for(int j = 0; j < k; ++j) {
IntType digit = const_mod<IntType, m>::apply(IntType(array[j+3]));
IntType mult = IntType(1) << 32*j;
s = const_mod<IntType, m>::mult_add(mult, digit, s);
}
return s;
}
template<class IntType, IntType m, class Iter>
IntType get_one_int(Iter& first, Iter last)
{
static const int log = ::boost::mpl::if_c<(m == 0),
::boost::mpl::int_<(::std::numeric_limits<IntType>::digits)>,
::boost::static_log2<m> >::type::value;
static const int k =
(log + ((~(static_cast<IntType>(2) << (log - 1)) & m)? 32 : 31)) / 32;
IntType s = 0;
for(int j = 0; j < k; ++j) {
if(first == last) {
boost::throw_exception(::std::invalid_argument("Not enough elements in call to seed."));
}
IntType digit = const_mod<IntType, m>::apply(IntType(*first++));
IntType mult = IntType(1) << 32*j;
s = const_mod<IntType, m>::mult_add(mult, digit, s);
}
return s;
}
// TODO: work in-place whenever possible
template<int w, std::size_t n, class SeedSeq, class UIntType>
void seed_array_int_impl(SeedSeq& seq, UIntType (&x)[n])
{
boost::uint_least32_t storage[((w+31)/32) * n];
seq.generate(&storage[0], &storage[0] + ((w+31)/32) * n);
for(std::size_t j = 0; j < n; j++) {
UIntType val = 0;
for(std::size_t k = 0; k < (w+31)/32; ++k) {
val += static_cast<UIntType>(storage[(w+31)/32*j + k]) << 32*k;
}
x[j] = val & ::boost::low_bits_mask_t<w>::sig_bits;
}
}
template<int w, std::size_t n, class SeedSeq, class IntType>
inline void seed_array_int_impl(SeedSeq& seq, IntType (&x)[n], boost::mpl::true_)
{
BOOST_STATIC_ASSERT_MSG(boost::is_integral<IntType>::value, "Sorry but this routine has not been ported to non built-in integers as it relies on a reinterpret_cast.");
typedef typename boost::make_unsigned<IntType>::type unsigned_array[n];
seed_array_int_impl<w>(seq, reinterpret_cast<unsigned_array&>(x));
}
template<int w, std::size_t n, class SeedSeq, class IntType>
inline void seed_array_int_impl(SeedSeq& seq, IntType (&x)[n], boost::mpl::false_)
{
seed_array_int_impl<w>(seq, x);
}
template<int w, std::size_t n, class SeedSeq, class IntType>
inline void seed_array_int(SeedSeq& seq, IntType (&x)[n])
{
seed_array_int_impl<w>(seq, x, boost::random::traits::is_signed<IntType>());
}
template<int w, std::size_t n, class Iter, class UIntType>
void fill_array_int_impl(Iter& first, Iter last, UIntType (&x)[n])
{
for(std::size_t j = 0; j < n; j++) {
UIntType val = 0;
for(std::size_t k = 0; k < (w+31)/32; ++k) {
if(first == last) {
boost::throw_exception(std::invalid_argument("Not enough elements in call to seed."));
}
val += static_cast<UIntType>(*first++) << 32*k;
}
x[j] = val & ::boost::low_bits_mask_t<w>::sig_bits;
}
}
template<int w, std::size_t n, class Iter, class IntType>
inline void fill_array_int_impl(Iter& first, Iter last, IntType (&x)[n], boost::mpl::true_)
{
BOOST_STATIC_ASSERT_MSG(boost::is_integral<IntType>::value, "Sorry but this routine has not been ported to non built-in integers as it relies on a reinterpret_cast.");
typedef typename boost::make_unsigned<IntType>::type unsigned_array[n];
fill_array_int_impl<w>(first, last, reinterpret_cast<unsigned_array&>(x));
}
template<int w, std::size_t n, class Iter, class IntType>
inline void fill_array_int_impl(Iter& first, Iter last, IntType (&x)[n], boost::mpl::false_)
{
fill_array_int_impl<w>(first, last, x);
}
template<int w, std::size_t n, class Iter, class IntType>
inline void fill_array_int(Iter& first, Iter last, IntType (&x)[n])
{
fill_array_int_impl<w>(first, last, x, boost::random::traits::is_signed<IntType>());
}
template<int w, std::size_t n, class RealType>
void seed_array_real_impl(const boost::uint_least32_t* storage, RealType (&x)[n])
{
boost::uint_least32_t mask = ~((~boost::uint_least32_t(0)) << (w%32));
RealType two32 = 4294967296.0;
const RealType divisor = RealType(1)/detail::pow2<RealType>(w);
unsigned int j;
for(j = 0; j < n; ++j) {
RealType val = RealType(0);
RealType mult = divisor;
for(int k = 0; k < w/32; ++k) {
val += *storage++ * mult;
mult *= two32;
}
if(mask != 0) {
val += (*storage++ & mask) * mult;
}
BOOST_ASSERT(val >= 0);
BOOST_ASSERT(val < 1);
x[j] = val;
}
}
template<int w, std::size_t n, class SeedSeq, class RealType>
void seed_array_real(SeedSeq& seq, RealType (&x)[n])
{
using std::pow;
boost::uint_least32_t storage[((w+31)/32) * n];
seq.generate(&storage[0], &storage[0] + ((w+31)/32) * n);
seed_array_real_impl<w>(storage, x);
}
template<int w, std::size_t n, class Iter, class RealType>
void fill_array_real(Iter& first, Iter last, RealType (&x)[n])
{
boost::uint_least32_t mask = ~((~boost::uint_least32_t(0)) << (w%32));
RealType two32 = 4294967296.0;
const RealType divisor = RealType(1)/detail::pow2<RealType>(w);
unsigned int j;
for(j = 0; j < n; ++j) {
RealType val = RealType(0);
RealType mult = divisor;
for(int k = 0; k < w/32; ++k, ++first) {
if(first == last) boost::throw_exception(std::invalid_argument("Not enough elements in call to seed."));
val += *first * mult;
mult *= two32;
}
if(mask != 0) {
if(first == last) boost::throw_exception(std::invalid_argument("Not enough elements in call to seed."));
val += (*first & mask) * mult;
++first;
}
BOOST_ASSERT(val >= 0);
BOOST_ASSERT(val < 1);
x[j] = val;
}
}
}
}
}
#include <boost/random/detail/enable_warnings.hpp>
#endif
@@ -0,0 +1,89 @@
/* boost random/detail/signed_unsigned_tools.hpp header file
*
* Copyright Jens Maurer 2006
* 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.
*/
#ifndef BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS
#define BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS
#include <boost/limits.hpp>
#include <boost/config.hpp>
#include <boost/random/traits.hpp>
namespace boost {
namespace random {
namespace detail {
/*
* Compute x - y, we know that x >= y, return an unsigned value.
*/
template<class T, bool sgn = std::numeric_limits<T>::is_signed && std::numeric_limits<T>::is_bounded>
struct subtract { };
template<class T>
struct subtract<T, /* signed */ false>
{
typedef T result_type;
result_type operator()(T x, T y) { return x - y; }
};
template<class T>
struct subtract<T, /* signed */ true>
{
typedef typename boost::random::traits::make_unsigned_or_unbounded<T>::type result_type;
result_type operator()(T x, T y)
{
if (y >= 0) // because x >= y, it follows that x >= 0, too
return result_type(x) - result_type(y);
if (x >= 0) // y < 0
// avoid the nasty two's complement case for y == min()
return result_type(x) + result_type(-(y+1)) + 1;
// both x and y are negative: no signed overflow
return result_type(x - y);
}
};
/*
* Compute x + y, x is unsigned, result fits in type of "y".
*/
template<class T1, class T2, bool sgn = (std::numeric_limits<T2>::is_signed && (std::numeric_limits<T1>::digits >= std::numeric_limits<T2>::digits))>
struct add { };
template<class T1, class T2>
struct add<T1, T2, /* signed or else T2 has more digits than T1 so the cast always works - needed when T2 is a multiprecision type and T1 is a native integer */ false>
{
typedef T2 result_type;
result_type operator()(T1 x, T2 y) { return T2(x) + y; }
};
template<class T1, class T2>
struct add<T1, T2, /* signed */ true>
{
typedef T2 result_type;
result_type operator()(T1 x, T2 y)
{
if (y >= 0)
return T2(x) + y;
// y < 0
if (x > T1(-(y+1))) // result >= 0 after subtraction
// avoid the nasty two's complement edge case for y == min()
return T2(x - T1(-(y+1)) - 1);
// abs(x) < abs(y), thus T2 able to represent x
return T2(x) + y;
}
};
} // namespace detail
} // namespace random
} // namespace boost
#endif // BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS
@@ -0,0 +1,76 @@
/* boost random/detail/uniform_int_float.hpp header file
*
* Copyright Jens Maurer 2000-2001
* Copyright Steven Watanabe 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_UNIFORM_INT_FLOAT_HPP
#define BOOST_RANDOM_DETAIL_UNIFORM_INT_FLOAT_HPP
#include <boost/limits.hpp>
#include <boost/config.hpp>
#include <boost/integer.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/generator_bits.hpp>
#include <boost/random/detail/disable_warnings.hpp>
namespace boost {
namespace random {
namespace detail {
template<class URNG>
class uniform_int_float
{
public:
typedef URNG base_type;
typedef typename base_type::result_type base_result;
typedef typename boost::uint_t<
(std::numeric_limits<boost::uintmax_t>::digits <
std::numeric_limits<base_result>::digits)?
std::numeric_limits<boost::uintmax_t>::digits :
std::numeric_limits<base_result>::digits
>::fast result_type;
uniform_int_float(base_type& rng)
: _rng(rng) {}
static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return 0; }
static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{
std::size_t digits = std::numeric_limits<result_type>::digits;
if(detail::generator_bits<URNG>::value() < digits) {
digits = detail::generator_bits<URNG>::value();
}
return (result_type(2) << (digits - 1)) - 1;
}
base_type& base() { return _rng; }
const base_type& base() const { return _rng; }
result_type operator()()
{
base_result range = static_cast<base_result>((max)())+1;
return static_cast<result_type>(_rng() * range);
}
private:
base_type& _rng;
};
} // namespace detail
} // namespace random
} // namespace boost
#include <boost/random/detail/enable_warnings.hpp>
#endif // BOOST_RANDOM_DETAIL_UNIFORM_INT_FLOAT_HPP
@@ -0,0 +1,75 @@
/* boost random/vector_io.hpp header file
*
* Copyright Steven Watanabe 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_VECTOR_IO_HPP
#define BOOST_RANDOM_DETAIL_VECTOR_IO_HPP
#include <vector>
#include <iosfwd>
#include <istream>
namespace boost {
namespace random {
namespace detail {
template<class CharT, class Traits, class T>
void print_vector(std::basic_ostream<CharT, Traits>& os,
const std::vector<T>& vec)
{
typename std::vector<T>::const_iterator
iter = vec.begin(),
end = vec.end();
os << os.widen('[');
if(iter != end) {
os << *iter;
++iter;
for(; iter != end; ++iter)
{
os << os.widen(' ') << *iter;
}
}
os << os.widen(']');
}
template<class CharT, class Traits, class T>
void read_vector(std::basic_istream<CharT, Traits>& is, std::vector<T>& vec)
{
CharT ch;
if(!(is >> ch)) {
return;
}
if(ch != is.widen('[')) {
is.putback(ch);
is.setstate(std::ios_base::failbit);
return;
}
T val;
while(is >> std::ws >> val) {
vec.push_back(val);
}
if(is.fail()) {
is.clear();
if(!(is >> ch)) {
return;
}
if(ch != is.widen(']')) {
is.putback(ch);
is.setstate(std::ios_base::failbit);
}
}
}
}
}
}
#endif // BOOST_RANDOM_DETAIL_VECTOR_IO_HPP
@@ -0,0 +1,241 @@
/* boost random/discard_block.hpp header file
*
* Copyright Jens Maurer 2002
* Copyright Steven Watanabe 2010
* 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$
*
* Revision history
* 2001-03-02 created
*/
#ifndef BOOST_RANDOM_DISCARD_BLOCK_HPP
#define BOOST_RANDOM_DISCARD_BLOCK_HPP
#include <iostream>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/limits.hpp>
#include <boost/static_assert.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/seed.hpp>
#include <boost/random/detail/seed_impl.hpp>
namespace boost {
namespace random {
/**
* The class template \discard_block_engine is a model of
* \pseudo_random_number_generator. It modifies
* another generator by discarding parts of its output.
* Out of every block of @c p results, the first @c r
* will be returned and the rest discarded.
*
* Requires: 0 < p <= r
*/
template<class UniformRandomNumberGenerator, std::size_t p, std::size_t r>
class discard_block_engine
{
typedef typename detail::seed_type<
typename UniformRandomNumberGenerator::result_type>::type seed_type;
public:
typedef UniformRandomNumberGenerator base_type;
typedef typename base_type::result_type result_type;
BOOST_STATIC_CONSTANT(std::size_t, block_size = p);
BOOST_STATIC_CONSTANT(std::size_t, used_block = r);
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
BOOST_STATIC_CONSTANT(std::size_t, total_block = p);
BOOST_STATIC_CONSTANT(std::size_t, returned_block = r);
BOOST_STATIC_ASSERT(total_block >= returned_block);
/** Uses the default seed for the base generator. */
discard_block_engine() : _rng(), _n(0) { }
/** Constructs a new \discard_block_engine with a copy of rng. */
explicit discard_block_engine(const base_type & rng) : _rng(rng), _n(0) { }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
/** Constructs a new \discard_block_engine with rng. */
explicit discard_block_engine(base_type && rng) : _rng(rng), _n(0) { }
#endif
/**
* Creates a new \discard_block_engine and seeds the underlying
* generator with @c value
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(discard_block_engine,
seed_type, value)
{ _rng.seed(value); _n = 0; }
/**
* Creates a new \discard_block_engine and seeds the underlying
* generator with @c seq
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(discard_block_engine, SeedSeq, seq)
{ _rng.seed(seq); _n = 0; }
/**
* Creates a new \discard_block_engine and seeds the underlying
* generator with first and last.
*/
template<class It> discard_block_engine(It& first, It last)
: _rng(first, last), _n(0) { }
/** default seeds the underlying generator. */
void seed() { _rng.seed(); _n = 0; }
/** Seeds the underlying generator with s. */
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(discard_block_engine, seed_type, s)
{ _rng.seed(s); _n = 0; }
/** Seeds the underlying generator with seq. */
BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(discard_block_engine, SeedSeq, seq)
{ _rng.seed(seq); _n = 0; }
/** Seeds the underlying generator with first and last. */
template<class It> void seed(It& first, It last)
{ _rng.seed(first, last); _n = 0; }
/** Returns the underlying engine. */
const base_type& base() const { return _rng; }
/** Returns the next value of the generator. */
result_type operator()()
{
if(_n >= returned_block) {
// discard values of random number generator
// Don't use discard, since we still need to
// be somewhat compatible with TR1.
// _rng.discard(total_block - _n);
for(std::size_t i = 0; i < total_block - _n; ++i) {
_rng();
}
_n = 0;
}
++_n;
return _rng();
}
void discard(boost::uintmax_t z)
{
for(boost::uintmax_t j = 0; j < z; ++j) {
(*this)();
}
}
template<class It>
void generate(It first, It last)
{ detail::generate(*this, first, last); }
/**
* Returns the smallest value that the generator can produce.
* This is the same as the minimum of the underlying generator.
*/
static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return (base_type::min)(); }
/**
* Returns the largest value that the generator can produce.
* This is the same as the maximum of the underlying generator.
*/
static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return (base_type::max)(); }
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
/** Writes a \discard_block_engine to a @c std::ostream. */
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os,
const discard_block_engine& s)
{
os << s._rng << ' ' << s._n;
return os;
}
/** Reads a \discard_block_engine from a @c std::istream. */
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is, discard_block_engine& s)
{
is >> s._rng >> std::ws >> s._n;
return is;
}
#endif
/** Returns true if the two generators will produce identical sequences. */
friend bool operator==(const discard_block_engine& x,
const discard_block_engine& y)
{ return x._rng == y._rng && x._n == y._n; }
/** Returns true if the two generators will produce different sequences. */
friend bool operator!=(const discard_block_engine& x,
const discard_block_engine& y)
{ return !(x == y); }
private:
base_type _rng;
std::size_t _n;
};
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
// A definition is required even for integral static constants
template<class URNG, std::size_t p, std::size_t r>
const bool discard_block_engine<URNG, p, r>::has_fixed_range;
template<class URNG, std::size_t p, std::size_t r>
const std::size_t discard_block_engine<URNG, p, r>::total_block;
template<class URNG, std::size_t p, std::size_t r>
const std::size_t discard_block_engine<URNG, p, r>::returned_block;
template<class URNG, std::size_t p, std::size_t r>
const std::size_t discard_block_engine<URNG, p, r>::block_size;
template<class URNG, std::size_t p, std::size_t r>
const std::size_t discard_block_engine<URNG, p, r>::used_block;
#endif
/// \cond \show_deprecated
template<class URNG, int p, int r>
class discard_block : public discard_block_engine<URNG, p, r>
{
typedef discard_block_engine<URNG, p, r> base_t;
public:
typedef typename base_t::result_type result_type;
discard_block() {}
template<class T>
discard_block(T& arg) : base_t(arg) {}
template<class T>
discard_block(const T& arg) : base_t(arg) {}
template<class It>
discard_block(It& first, It last) : base_t(first, last) {}
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return (this->base().min)(); }
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return (this->base().max)(); }
};
/// \endcond
namespace detail {
template<class Engine>
struct generator_bits;
template<class URNG, std::size_t p, std::size_t r>
struct generator_bits<discard_block_engine<URNG, p, r> > {
static std::size_t value() { return generator_bits<URNG>::value(); }
};
template<class URNG, int p, int r>
struct generator_bits<discard_block<URNG, p, r> > {
static std::size_t value() { return generator_bits<URNG>::value(); }
};
}
} // namespace random
} // namespace boost
#endif // BOOST_RANDOM_DISCARD_BLOCK_HPP
@@ -0,0 +1,636 @@
/* boost random/discrete_distribution.hpp header file
*
* Copyright Steven Watanabe 2009-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_DISCRETE_DISTRIBUTION_HPP_INCLUDED
#define BOOST_RANDOM_DISCRETE_DISTRIBUTION_HPP_INCLUDED
#include <vector>
#include <limits>
#include <numeric>
#include <utility>
#include <iterator>
#include <boost/assert.hpp>
#include <boost/random/uniform_01.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/detail/vector_io.hpp>
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
#include <initializer_list>
#endif
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/random/detail/disable_warnings.hpp>
namespace boost {
namespace random {
namespace detail {
template<class IntType, class WeightType>
struct integer_alias_table {
WeightType get_weight(IntType bin) const {
WeightType result = _average;
if(bin < _excess) ++result;
return result;
}
template<class Iter>
WeightType init_average(Iter begin, Iter end) {
WeightType weight_average = 0;
IntType excess = 0;
IntType n = 0;
// weight_average * n + excess == current partial sum
// This is a bit messy, but it's guaranteed not to overflow
for(Iter iter = begin; iter != end; ++iter) {
++n;
if(*iter < weight_average) {
WeightType diff = weight_average - *iter;
weight_average -= diff / n;
if(diff % n > excess) {
--weight_average;
excess += n - diff % n;
} else {
excess -= diff % n;
}
} else {
WeightType diff = *iter - weight_average;
weight_average += diff / n;
if(diff % n < n - excess) {
excess += diff % n;
} else {
++weight_average;
excess -= n - diff % n;
}
}
}
_alias_table.resize(static_cast<std::size_t>(n));
_average = weight_average;
_excess = excess;
return weight_average;
}
void init_empty()
{
_alias_table.clear();
_alias_table.push_back(std::make_pair(static_cast<WeightType>(1),
static_cast<IntType>(0)));
_average = static_cast<WeightType>(1);
_excess = static_cast<IntType>(0);
}
bool operator==(const integer_alias_table& other) const
{
return _alias_table == other._alias_table &&
_average == other._average && _excess == other._excess;
}
static WeightType normalize(WeightType val, WeightType average)
{
return val;
}
static void normalize(std::vector<WeightType>&) {}
template<class URNG>
WeightType test(URNG &urng) const
{
return uniform_int_distribution<WeightType>(0, _average)(urng);
}
bool accept(IntType result, WeightType val) const
{
return result < _excess || val < _average;
}
static WeightType try_get_sum(const std::vector<WeightType>& weights)
{
WeightType result = static_cast<WeightType>(0);
for(typename std::vector<WeightType>::const_iterator
iter = weights.begin(), end = weights.end();
iter != end; ++iter)
{
if((std::numeric_limits<WeightType>::max)() - result > *iter) {
return static_cast<WeightType>(0);
}
result += *iter;
}
return result;
}
template<class URNG>
static WeightType generate_in_range(URNG &urng, WeightType max)
{
return uniform_int_distribution<WeightType>(
static_cast<WeightType>(0), max-1)(urng);
}
typedef std::vector<std::pair<WeightType, IntType> > alias_table_t;
alias_table_t _alias_table;
WeightType _average;
IntType _excess;
};
template<class IntType, class WeightType>
struct real_alias_table {
WeightType get_weight(IntType) const
{
return WeightType(1.0);
}
template<class Iter>
WeightType init_average(Iter first, Iter last)
{
std::size_t size = std::distance(first, last);
WeightType weight_sum =
std::accumulate(first, last, static_cast<WeightType>(0));
_alias_table.resize(size);
return weight_sum / size;
}
void init_empty()
{
_alias_table.clear();
_alias_table.push_back(std::make_pair(static_cast<WeightType>(1),
static_cast<IntType>(0)));
}
bool operator==(const real_alias_table& other) const
{
return _alias_table == other._alias_table;
}
static WeightType normalize(WeightType val, WeightType average)
{
return val / average;
}
static void normalize(std::vector<WeightType>& weights)
{
WeightType sum =
std::accumulate(weights.begin(), weights.end(),
static_cast<WeightType>(0));
for(typename std::vector<WeightType>::iterator
iter = weights.begin(),
end = weights.end();
iter != end; ++iter)
{
*iter /= sum;
}
}
template<class URNG>
WeightType test(URNG &urng) const
{
return uniform_01<WeightType>()(urng);
}
bool accept(IntType, WeightType) const
{
return true;
}
static WeightType try_get_sum(const std::vector<WeightType>& weights)
{
return static_cast<WeightType>(1);
}
template<class URNG>
static WeightType generate_in_range(URNG &urng, WeightType)
{
return uniform_01<WeightType>()(urng);
}
typedef std::vector<std::pair<WeightType, IntType> > alias_table_t;
alias_table_t _alias_table;
};
template<bool IsIntegral>
struct select_alias_table;
template<>
struct select_alias_table<true> {
template<class IntType, class WeightType>
struct apply {
typedef integer_alias_table<IntType, WeightType> type;
};
};
template<>
struct select_alias_table<false> {
template<class IntType, class WeightType>
struct apply {
typedef real_alias_table<IntType, WeightType> type;
};
};
}
/**
* The class @c discrete_distribution models a \random_distribution.
* It produces integers in the range [0, n) with the probability
* of producing each value is specified by the parameters of the
* distribution.
*/
template<class IntType = int, class WeightType = double>
class discrete_distribution {
public:
typedef WeightType input_type;
typedef IntType result_type;
class param_type {
public:
typedef discrete_distribution distribution_type;
/**
* Constructs a @c param_type object, representing a distribution
* with \f$p(0) = 1\f$ and \f$p(k|k>0) = 0\f$.
*/
param_type() : _probabilities(1, static_cast<WeightType>(1)) {}
/**
* If @c first == @c last, equivalent to the default constructor.
* Otherwise, the values of the range represent weights for the
* possible values of the distribution.
*/
template<class Iter>
param_type(Iter first, Iter last) : _probabilities(first, last)
{
normalize();
}
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
/**
* If wl.size() == 0, equivalent to the default constructor.
* Otherwise, the values of the @c initializer_list represent
* weights for the possible values of the distribution.
*/
param_type(const std::initializer_list<WeightType>& wl)
: _probabilities(wl)
{
normalize();
}
#endif
/**
* If the range is empty, equivalent to the default constructor.
* Otherwise, the elements of the range represent
* weights for the possible values of the distribution.
*/
template<class Range>
explicit param_type(const Range& range)
: _probabilities(boost::begin(range), boost::end(range))
{
normalize();
}
/**
* If nw is zero, equivalent to the default constructor.
* Otherwise, the range of the distribution is [0, nw),
* and the weights are found by calling fw with values
* evenly distributed between \f$\mbox{xmin} + \delta/2\f$ and
* \f$\mbox{xmax} - \delta/2\f$, where
* \f$\delta = (\mbox{xmax} - \mbox{xmin})/\mbox{nw}\f$.
*/
template<class Func>
param_type(std::size_t nw, double xmin, double xmax, Func fw)
{
std::size_t n = (nw == 0) ? 1 : nw;
double delta = (xmax - xmin) / n;
BOOST_ASSERT(delta > 0);
for(std::size_t k = 0; k < n; ++k) {
_probabilities.push_back(fw(xmin + k*delta + delta/2));
}
normalize();
}
/**
* Returns a vector containing the probabilities of each possible
* value of the distribution.
*/
std::vector<WeightType> probabilities() const
{
return _probabilities;
}
/** Writes the parameters to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{
detail::print_vector(os, parm._probabilities);
return os;
}
/** Reads the parameters from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{
std::vector<WeightType> temp;
detail::read_vector(is, temp);
if(is) {
parm._probabilities.swap(temp);
}
return is;
}
/** Returns true if the two sets of parameters are the same. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{
return lhs._probabilities == rhs._probabilities;
}
/** Returns true if the two sets of parameters are different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
/// @cond show_private
friend class discrete_distribution;
explicit param_type(const discrete_distribution& dist)
: _probabilities(dist.probabilities())
{}
void normalize()
{
impl_type::normalize(_probabilities);
}
std::vector<WeightType> _probabilities;
/// @endcond
};
/**
* Creates a new @c discrete_distribution object that has
* \f$p(0) = 1\f$ and \f$p(i|i>0) = 0\f$.
*/
discrete_distribution()
{
_impl.init_empty();
}
/**
* Constructs a discrete_distribution from an iterator range.
* If @c first == @c last, equivalent to the default constructor.
* Otherwise, the values of the range represent weights for the
* possible values of the distribution.
*/
template<class Iter>
discrete_distribution(Iter first, Iter last)
{
init(first, last);
}
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
/**
* Constructs a @c discrete_distribution from a @c std::initializer_list.
* If the @c initializer_list is empty, equivalent to the default
* constructor. Otherwise, the values of the @c initializer_list
* represent weights for the possible values of the distribution.
* For example, given the distribution
*
* @code
* discrete_distribution<> dist{1, 4, 5};
* @endcode
*
* The probability of a 0 is 1/10, the probability of a 1 is 2/5,
* the probability of a 2 is 1/2, and no other values are possible.
*/
discrete_distribution(std::initializer_list<WeightType> wl)
{
init(wl.begin(), wl.end());
}
#endif
/**
* Constructs a discrete_distribution from a Boost.Range range.
* If the range is empty, equivalent to the default constructor.
* Otherwise, the values of the range represent weights for the
* possible values of the distribution.
*/
template<class Range>
explicit discrete_distribution(const Range& range)
{
init(boost::begin(range), boost::end(range));
}
/**
* Constructs a discrete_distribution that approximates a function.
* If nw is zero, equivalent to the default constructor.
* Otherwise, the range of the distribution is [0, nw),
* and the weights are found by calling fw with values
* evenly distributed between \f$\mbox{xmin} + \delta/2\f$ and
* \f$\mbox{xmax} - \delta/2\f$, where
* \f$\delta = (\mbox{xmax} - \mbox{xmin})/\mbox{nw}\f$.
*/
template<class Func>
discrete_distribution(std::size_t nw, double xmin, double xmax, Func fw)
{
std::size_t n = (nw == 0) ? 1 : nw;
double delta = (xmax - xmin) / n;
BOOST_ASSERT(delta > 0);
std::vector<WeightType> weights;
for(std::size_t k = 0; k < n; ++k) {
weights.push_back(fw(xmin + k*delta + delta/2));
}
init(weights.begin(), weights.end());
}
/**
* Constructs a discrete_distribution from its parameters.
*/
explicit discrete_distribution(const param_type& parm)
{
param(parm);
}
/**
* Returns a value distributed according to the parameters of the
* discrete_distribution.
*/
template<class URNG>
IntType operator()(URNG& urng) const
{
BOOST_ASSERT(!_impl._alias_table.empty());
IntType result;
WeightType test;
do {
result = uniform_int_distribution<IntType>((min)(), (max)())(urng);
test = _impl.test(urng);
} while(!_impl.accept(result, test));
if(test < _impl._alias_table[static_cast<std::size_t>(result)].first) {
return result;
} else {
return(_impl._alias_table[static_cast<std::size_t>(result)].second);
}
}
/**
* Returns a value distributed according to the parameters
* specified by param.
*/
template<class URNG>
IntType operator()(URNG& urng, const param_type& parm) const
{
if(WeightType limit = impl_type::try_get_sum(parm._probabilities)) {
WeightType val = impl_type::generate_in_range(urng, limit);
WeightType sum = 0;
std::size_t result = 0;
for(typename std::vector<WeightType>::const_iterator
iter = parm._probabilities.begin(),
end = parm._probabilities.end();
iter != end; ++iter, ++result)
{
sum += *iter;
if(sum > val) {
return result;
}
}
// This shouldn't be reachable, but round-off error
// can prevent any match from being found when val is
// very close to 1.
return static_cast<IntType>(parm._probabilities.size() - 1);
} else {
// WeightType is integral and sum(parm._probabilities)
// would overflow. Just use the easy solution.
return discrete_distribution(parm)(urng);
}
}
/** Returns the smallest value that the distribution can produce. */
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; }
/** Returns the largest value that the distribution can produce. */
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return static_cast<result_type>(_impl._alias_table.size() - 1); }
/**
* Returns a vector containing the probabilities of each
* value of the distribution. For example, given
*
* @code
* discrete_distribution<> dist = { 1, 4, 5 };
* std::vector<double> p = dist.param();
* @endcode
*
* the vector, p will contain {0.1, 0.4, 0.5}.
*
* If @c WeightType is integral, then the weights
* will be returned unchanged.
*/
std::vector<WeightType> probabilities() const
{
std::vector<WeightType> result(_impl._alias_table.size(), static_cast<WeightType>(0));
std::size_t i = 0;
for(typename impl_type::alias_table_t::const_iterator
iter = _impl._alias_table.begin(),
end = _impl._alias_table.end();
iter != end; ++iter, ++i)
{
WeightType val = iter->first;
result[i] += val;
result[static_cast<std::size_t>(iter->second)] += _impl.get_weight(i) - val;
}
impl_type::normalize(result);
return(result);
}
/** Returns the parameters of the distribution. */
param_type param() const
{
return param_type(*this);
}
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
init(parm._probabilities.begin(), parm._probabilities.end());
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() {}
/** Writes a distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, discrete_distribution, dd)
{
os << dd.param();
return os;
}
/** Reads a distribution from a @c std::istream */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, discrete_distribution, dd)
{
param_type parm;
if(is >> parm) {
dd.param(parm);
}
return is;
}
/**
* Returns true if the two distributions will return the
* same sequence of values, when passed equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(discrete_distribution, lhs, rhs)
{
return lhs._impl == rhs._impl;
}
/**
* Returns true if the two distributions may return different
* sequences of values, when passed equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(discrete_distribution)
private:
/// @cond show_private
template<class Iter>
void init(Iter first, Iter last, std::input_iterator_tag)
{
std::vector<WeightType> temp(first, last);
init(temp.begin(), temp.end());
}
template<class Iter>
void init(Iter first, Iter last, std::forward_iterator_tag)
{
std::vector<std::pair<WeightType, IntType> > below_average;
std::vector<std::pair<WeightType, IntType> > above_average;
WeightType weight_average = _impl.init_average(first, last);
WeightType normalized_average = _impl.get_weight(0);
std::size_t i = 0;
for(; first != last; ++first, ++i) {
WeightType val = impl_type::normalize(*first, weight_average);
std::pair<WeightType, IntType> elem(val, static_cast<IntType>(i));
if(val < normalized_average) {
below_average.push_back(elem);
} else {
above_average.push_back(elem);
}
}
typename impl_type::alias_table_t::iterator
b_iter = below_average.begin(),
b_end = below_average.end(),
a_iter = above_average.begin(),
a_end = above_average.end()
;
while(b_iter != b_end && a_iter != a_end) {
_impl._alias_table[static_cast<std::size_t>(b_iter->second)] =
std::make_pair(b_iter->first, a_iter->second);
a_iter->first -= (_impl.get_weight(b_iter->second) - b_iter->first);
if(a_iter->first < normalized_average) {
*b_iter = *a_iter++;
} else {
++b_iter;
}
}
for(; b_iter != b_end; ++b_iter) {
_impl._alias_table[static_cast<std::size_t>(b_iter->second)].first =
_impl.get_weight(b_iter->second);
}
for(; a_iter != a_end; ++a_iter) {
_impl._alias_table[static_cast<std::size_t>(a_iter->second)].first =
_impl.get_weight(a_iter->second);
}
}
template<class Iter>
void init(Iter first, Iter last)
{
if(first == last) {
_impl.init_empty();
} else {
typename std::iterator_traits<Iter>::iterator_category category;
init(first, last, category);
}
}
typedef typename detail::select_alias_table<
(::boost::is_integral<WeightType>::value)
>::template apply<IntType, WeightType>::type impl_type;
impl_type _impl;
/// @endcond
};
}
}
#include <boost/random/detail/enable_warnings.hpp>
#endif
@@ -0,0 +1,386 @@
/* boost random/exponential_distribution.hpp header file
*
* Copyright Jens Maurer 2000-2001
* Copyright Steven Watanabe 2011
* Copyright Jason Rhinelander 2016
* 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$
*
* Revision history
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_EXPONENTIAL_DISTRIBUTION_HPP
#define BOOST_RANDOM_EXPONENTIAL_DISTRIBUTION_HPP
#include <boost/config/no_tr1/cmath.hpp>
#include <iosfwd>
#include <boost/assert.hpp>
#include <boost/limits.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/detail/int_float_pair.hpp>
#include <boost/random/uniform_01.hpp>
namespace boost {
namespace random {
namespace detail {
// tables for the ziggurat algorithm
template<class RealType>
struct exponential_table {
static const RealType table_x[257];
static const RealType table_y[257];
};
template<class RealType>
const RealType exponential_table<RealType>::table_x[257] = {
8.6971174701310497140, 7.6971174701310497140, 6.9410336293772123602, 6.4783784938325698538,
6.1441646657724730491, 5.8821443157953997963, 5.6664101674540337371, 5.4828906275260628694,
5.3230905057543986131, 5.1814872813015010392, 5.0542884899813047117, 4.9387770859012514838,
4.8329397410251125881, 4.7352429966017412526, 4.6444918854200854873, 4.5597370617073515513,
4.4802117465284221949, 4.4052876934735729805, 4.3344436803172730116, 4.2672424802773661873,
4.2033137137351843802, 4.1423408656640511251, 4.0840513104082974638, 4.0282085446479365106,
3.9746060666737884793, 3.9230625001354895926, 3.8734176703995089983, 3.8255294185223367372,
3.7792709924116678992, 3.7345288940397975350, 3.6912010902374189454, 3.6491955157608538478,
3.6084288131289096339, 3.5688252656483374051, 3.5303158891293438633, 3.4928376547740601814,
3.4563328211327607625, 3.4207483572511205323, 3.3860354424603017887, 3.3521490309001100106,
3.3190474709707487166, 3.2866921715990692095, 3.2550473085704501813, 3.2240795652862645207,
3.1937579032122407483, 3.1640533580259734580, 3.1349388580844407393, 3.1063890623398246660,
3.0783802152540905188, 3.0508900166154554479, 3.0238975044556767713, 2.9973829495161306949,
2.9713277599210896472, 2.9457143948950456386, 2.9205262865127406647, 2.8957477686001416838,
2.8713640120155362592, 2.8473609656351888266, 2.8237253024500354905, 2.8004443702507381944,
2.7775061464397572041, 2.7548991965623453650, 2.7326126361947007411, 2.7106360958679293686,
2.6889596887418041593, 2.6675739807732670816, 2.6464699631518093905, 2.6256390267977886123,
2.6050729387408355373, 2.5847638202141406911, 2.5647041263169053687, 2.5448866271118700928,
2.5253043900378279427, 2.5059507635285939648, 2.4868193617402096807, 2.4679040502973649846,
2.4491989329782498908, 2.4306983392644199088, 2.4123968126888708336, 2.3942890999214583288,
2.3763701405361408194, 2.3586350574093374601, 2.3410791477030346875, 2.3236978743901964559,
2.3064868582835798692, 2.2894418705322694265, 2.2725588255531546952, 2.2558337743672190441,
2.2392628983129087111, 2.2228425031110364013, 2.2065690132576635755, 2.1904389667232199235,
2.1744490099377744673, 2.1585958930438856781, 2.1428764653998416425, 2.1272876713173679737,
2.1118265460190418108, 2.0964902118017147637, 2.0812758743932248696, 2.0661808194905755036,
2.0512024094685848641, 2.0363380802487695916, 2.0215853383189260770, 2.0069417578945183144,
1.9924049782135764992, 1.9779727009573602295, 1.9636426877895480401, 1.9494127580071845659,
1.9352807862970511135, 1.9212447005915276767, 1.9073024800183871196, 1.8934521529393077332,
1.8796917950722108462, 1.8660195276928275962, 1.8524335159111751661, 1.8389319670188793980,
1.8255131289035192212, 1.8121752885263901413, 1.7989167704602903934, 1.7857359354841254047,
1.7726311792313049959, 1.7596009308890742369, 1.7466436519460739352, 1.7337578349855711926,
1.7209420025219350428, 1.7081947058780575683, 1.6955145241015377061, 1.6829000629175537544,
1.6703499537164519163, 1.6578628525741725325, 1.6454374393037234057, 1.6330724165359912048,
1.6207665088282577216, 1.6085184617988580769, 1.5963270412864831349, 1.5841910325326886695,
1.5721092393862294810, 1.5600804835278879161, 1.5481036037145133070, 1.5361774550410318943,
1.5243009082192260050, 1.5124728488721167573, 1.5006921768428164936, 1.4889578055167456003,
1.4772686611561334579, 1.4656236822457450411, 1.4540218188487932264, 1.4424620319720121876,
1.4309432929388794104, 1.4194645827699828254, 1.4080248915695353509, 1.3966232179170417110,
1.3852585682631217189, 1.3739299563284902176, 1.3626364025050864742, 1.3513769332583349176,
1.3401505805295045843, 1.3289563811371163220, 1.3177933761763245480, 1.3066606104151739482,
1.2955571316866007210, 1.2844819902750125450, 1.2734342382962410994, 1.2624129290696153434,
1.2514171164808525098, 1.2404458543344064544, 1.2294981956938491599, 1.2185731922087903071,
1.2076698934267612830, 1.1967873460884031665, 1.1859245934042023557, 1.1750806743109117687,
1.1642546227056790397, 1.1534454666557748056, 1.1426522275816728928, 1.1318739194110786733,
1.1211095477013306083, 1.1103581087274114281, 1.0996185885325976575, 1.0888899619385472598,
1.0781711915113727024, 1.0674612264799681530, 1.0567590016025518414, 1.0460634359770445503,
1.0353734317905289496, 1.0246878730026178052, 1.0140056239570971074, 1.0033255279156973717,
0.99264640550727647009, 0.98196705308506317914, 0.97128624098390397896, 0.96060271166866709917,
0.94991517776407659940, 0.93922231995526297952, 0.92852278474721113999, 0.91781518207004493915,
0.90709808271569100600, 0.89637001558989069006, 0.88562946476175228052, 0.87487486629102585352,
0.86410460481100519511, 0.85331700984237406386, 0.84251035181036928333, 0.83168283773427388393,
0.82083260655441252290, 0.80995772405741906620, 0.79905617735548788109, 0.78812586886949324977,
0.77716460975913043936, 0.76617011273543541328, 0.75513998418198289808, 0.74407171550050873971,
0.73296267358436604916, 0.72181009030875689912, 0.71061105090965570413, 0.69936248110323266174,
0.68806113277374858613, 0.67670356802952337911, 0.66528614139267855405, 0.65380497984766565353,
0.64225596042453703448, 0.63063468493349100113, 0.61893645139487678178, 0.60715622162030085137,
0.59528858429150359384, 0.58332771274877027785, 0.57126731653258903915, 0.55910058551154127652,
0.54682012516331112550, 0.53441788123716615385, 0.52188505159213564105, 0.50921198244365495319,
0.49638804551867159754, 0.48340149165346224782, 0.47023927508216945338, 0.45688684093142071279,
0.44332786607355296305, 0.42954394022541129589, 0.41551416960035700100, 0.40121467889627836229,
0.38661797794112021568, 0.37169214532991786118, 0.35639976025839443721, 0.34069648106484979674,
0.32452911701691008547, 0.30783295467493287307, 0.29052795549123115167, 0.27251318547846547924,
0.25365836338591284433, 0.23379048305967553619, 0.21267151063096745264, 0.18995868962243277774,
0.16512762256418831796, 0.13730498094001380420, 0.10483850756582017915, 0.063852163815003480173,
0
};
template<class RealType>
const RealType exponential_table<RealType>::table_y[257] = {
0, 0.00045413435384149675545, 0.00096726928232717452884, 0.0015362997803015723824,
0.0021459677437189061793, 0.0027887987935740759640, 0.0034602647778369039855, 0.0041572951208337952532,
0.0048776559835423925804, 0.0056196422072054831710, 0.0063819059373191794422, 0.0071633531836349841425,
0.0079630774380170392396, 0.0087803149858089752347, 0.0096144136425022094101, 0.010464810181029979488,
0.011331013597834597488, 0.012212592426255380661, 0.013109164931254991070, 0.014020391403181937334,
0.014945968011691148079, 0.015885621839973162490, 0.016839106826039946359, 0.017806200410911360563,
0.018786700744696029497, 0.019780424338009741737, 0.020787204072578117603, 0.021806887504283582125,
0.022839335406385238829, 0.023884420511558170348, 0.024942026419731782971, 0.026012046645134218076,
0.027094383780955798424, 0.028188948763978634421, 0.029295660224637394015, 0.030414443910466605492,
0.031545232172893605499, 0.032687963508959533317, 0.033842582150874329031, 0.035009037697397411067,
0.036187284781931419754, 0.037377282772959360128, 0.038578995503074859626, 0.039792391023374122670,
0.041017441380414820816, 0.042254122413316231413, 0.043502413568888183301, 0.044762297732943280694,
0.046033761076175166762, 0.047316792913181548703, 0.048611385573379494401, 0.049917534282706374944,
0.051235237055126279830, 0.052564494593071689595, 0.053905310196046085104, 0.055257689676697038322,
0.056621641283742874438, 0.057997175631200659098, 0.059384305633420264487, 0.060783046445479636051,
0.062193415408540996150, 0.063615431999807331076, 0.065049117786753755036, 0.066494496385339779043,
0.067951593421936607770, 0.069420436498728751675, 0.070901055162371828426, 0.072393480875708743023,
0.073897746992364746308, 0.075413888734058408453, 0.076941943170480510100, 0.078481949201606426042,
0.080033947542319910023, 0.081597980709237420930, 0.083174093009632380354, 0.084762330532368125386,
0.086362741140756912277, 0.087975374467270219300, 0.089600281910032864534, 0.091237516631040162057,
0.092887133556043546523, 0.094549189376055853718, 0.096223742550432800103, 0.097910853311492199618,
0.099610583670637128826, 0.10132299742595363588, 0.10304816017125771553, 0.10478613930657016928,
0.10653700405000166218, 0.10830082545103379867, 0.11007767640518539026, 0.11186763167005629731,
0.11367076788274431301, 0.11548716357863353664, 0.11731689921155557057, 0.11916005717532768467,
0.12101672182667483729, 0.12288697950954513498, 0.12477091858083096578, 0.12666862943751066518,
0.12858020454522817870, 0.13050573846833078225, 0.13244532790138752023, 0.13439907170221363078,
0.13636707092642885841, 0.13834942886358021406, 0.14034625107486244210, 0.14235764543247220043,
0.14438372216063476473, 0.14642459387834493787, 0.14848037564386679222, 0.15055118500103990354,
0.15263714202744286154, 0.15473836938446807312, 0.15685499236936522013, 0.15898713896931420572,
0.16113493991759203183, 0.16329852875190180795, 0.16547804187493600915, 0.16767361861725019322,
0.16988540130252766513, 0.17211353531532005700, 0.17435816917135348788, 0.17661945459049489581,
0.17889754657247831241, 0.18119260347549629488, 0.18350478709776746150, 0.18583426276219711495,
0.18818119940425430485, 0.19054576966319540013, 0.19292814997677133873, 0.19532852067956322315,
0.19774706610509886464, 0.20018397469191127727, 0.20263943909370901930, 0.20511365629383770880,
0.20760682772422204205, 0.21011915938898825914, 0.21265086199297827522, 0.21520215107537867786,
0.21777324714870053264, 0.22036437584335949720, 0.22297576805812018050, 0.22560766011668406495,
0.22826029393071670664, 0.23093391716962742173, 0.23362878343743333945, 0.23634515245705964715,
0.23908329026244917002, 0.24184346939887722761, 0.24462596913189210901, 0.24743107566532763894,
0.25025908236886230967, 0.25311029001562948171, 0.25598500703041538015, 0.25888354974901621678,
0.26180624268936295243, 0.26475341883506220209, 0.26772541993204481808, 0.27072259679906003167,
0.27374530965280298302, 0.27679392844851734458, 0.27986883323697289920, 0.28297041453878076010,
0.28609907373707684673, 0.28925522348967773308, 0.29243928816189258772, 0.29565170428126120948,
0.29889292101558177099, 0.30216340067569352897, 0.30546361924459023541, 0.30879406693456016794,
0.31215524877417956945, 0.31554768522712893632, 0.31897191284495723773, 0.32242848495608914289,
0.32591797239355619822, 0.32944096426413633091, 0.33299806876180896713, 0.33658991402867758144,
0.34021714906678004560, 0.34388044470450243010, 0.34758049462163698567, 0.35131801643748334681,
0.35509375286678745925, 0.35890847294874976196, 0.36276297335481777335, 0.36665807978151414890,
0.37059464843514599421, 0.37457356761590215193, 0.37859575940958081092, 0.38266218149600982112,
0.38677382908413768115, 0.39093173698479710717, 0.39513698183329015336, 0.39939068447523107877,
0.40369401253053026739, 0.40804818315203238238, 0.41245446599716116772, 0.41691418643300289465,
0.42142872899761659635, 0.42599954114303435739, 0.43062813728845883923, 0.43531610321563659758,
0.44006510084235387501, 0.44487687341454851593, 0.44975325116275498919, 0.45469615747461548049,
0.45970761564213768669, 0.46478975625042618067, 0.46994482528395999841, 0.47517519303737738299,
0.48048336393045423016, 0.48587198734188493564, 0.49134386959403255500, 0.49690198724154955294,
0.50254950184134769289, 0.50828977641064283495, 0.51412639381474855788, 0.52006317736823356823,
0.52610421398361972602, 0.53225388026304326945, 0.53851687200286186590, 0.54489823767243963663,
0.55140341654064131685, 0.55803828226258748140, 0.56480919291240022434, 0.57172304866482579008,
0.57878735860284503057, 0.58601031847726802755, 0.59340090169173341521, 0.60096896636523224742,
0.60872538207962206507, 0.61668218091520762326, 0.62485273870366592605, 0.63325199421436607968,
0.64189671642726607018, 0.65080583341457104881, 0.66000084107899974178, 0.66950631673192477684,
0.67935057226476538741, 0.68956649611707798890, 0.70019265508278816709, 0.71127476080507597882,
0.72286765959357200702, 0.73503809243142351530, 0.74786862198519510742, 0.76146338884989624862,
0.77595685204011559675, 0.79152763697249565519, 0.80842165152300838005, 0.82699329664305033399,
0.84778550062398962096, 0.87170433238120363669, 0.90046992992574643800, 0.93814368086217467916,
1
};
template<class RealType = double>
struct unit_exponential_distribution
{
template<class Engine>
RealType operator()(Engine& eng) {
const double * const table_x = exponential_table<double>::table_x;
const double * const table_y = exponential_table<double>::table_y;
RealType shift(0);
for(;;) {
std::pair<RealType, int> vals = generate_int_float_pair<RealType, 8>(eng);
int i = vals.second;
RealType x = vals.first * RealType(table_x[i]);
if(x < RealType(table_x[i + 1])) return shift + x;
// For i=0 we need to generate from the tail, but because this is an exponential
// distribution, the tail looks exactly like the body, so we can simply repeat with a
// shift:
if (i == 0) shift += RealType(table_x[1]);
else {
RealType y01 = uniform_01<RealType>()(eng);
RealType y = RealType(table_y[i]) + y01 * RealType(table_y[i+1] - table_y[i]);
// All we care about is whether these are < or > 0; these values are equal to
// (lbound) or proportional to (ubound) `y` minus the lower/upper bound.
RealType y_above_ubound = RealType(table_x[i] - table_x[i+1]) * y01 - (RealType(table_x[i]) - x),
y_above_lbound = y - (RealType(table_y[i+1]) + (RealType(table_x[i+1]) - x) * RealType(table_y[i+1]));
if (y_above_ubound < 0 // if above the upper bound reject immediately
&&
(
y_above_lbound < 0 // If below the lower bound accept immediately
||
y < f(x) // Otherwise it's between the bounds and we need a full check
)
) {
return x + shift;
}
}
}
}
static RealType f(RealType x) {
using std::exp;
return exp(-x);
}
};
} // namespace detail
/**
* The exponential distribution is a model of \random_distribution with
* a single parameter lambda.
*
* It has \f$\displaystyle p(x) = \lambda e^{-\lambda x}\f$
*
* The implementation uses the "ziggurat" algorithm, as described in
*
* @blockquote
* "The Ziggurat Method for Generating Random Variables",
* George Marsaglia and Wai Wan Tsang, Journal of Statistical Software
* Volume 5, Number 8 (2000), 1-7.
* @endblockquote
*/
template<class RealType = double>
class exponential_distribution
{
public:
typedef RealType input_type;
typedef RealType result_type;
class param_type
{
public:
typedef exponential_distribution distribution_type;
/**
* Constructs parameters with a given lambda.
*
* Requires: lambda > 0
*/
param_type(RealType lambda_arg = RealType(1.0))
: _lambda(lambda_arg) { BOOST_ASSERT(_lambda > RealType(0)); }
/** Returns the lambda parameter of the distribution. */
RealType lambda() const { return _lambda; }
/** Writes the parameters to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{
os << parm._lambda;
return os;
}
/** Reads the parameters from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{
is >> parm._lambda;
return is;
}
/** Returns true if the two sets of parameters are equal. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._lambda == rhs._lambda; }
/** Returns true if the two sets of parameters are different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
RealType _lambda;
};
/**
* Constructs an exponential_distribution with a given lambda.
*
* Requires: lambda > 0
*/
explicit exponential_distribution(RealType lambda_arg = RealType(1.0))
: _lambda(lambda_arg) { BOOST_ASSERT(_lambda > RealType(0)); }
/**
* Constructs an exponential_distribution from its parameters
*/
explicit exponential_distribution(const param_type& parm)
: _lambda(parm.lambda()) {}
// compiler-generated copy ctor and assignment operator are fine
/** Returns the lambda parameter of the distribution. */
RealType lambda() const { return _lambda; }
/** Returns the smallest value that the distribution can produce. */
RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return RealType(0); }
/** Returns the largest value that the distribution can produce. */
RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return (std::numeric_limits<RealType>::infinity)(); }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(_lambda); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm) { _lambda = parm.lambda(); }
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { }
/**
* Returns a random variate distributed according to the
* exponential distribution.
*/
template<class Engine>
result_type operator()(Engine& eng) const
{
detail::unit_exponential_distribution<RealType> impl;
return impl(eng) / _lambda;
}
/**
* Returns a random variate distributed according to the exponential
* distribution with parameters specified by param.
*/
template<class Engine>
result_type operator()(Engine& eng, const param_type& parm) const
{
return exponential_distribution(parm)(eng);
}
/** Writes the distribution to a std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, exponential_distribution, ed)
{
os << ed._lambda;
return os;
}
/** Reads the distribution from a std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, exponential_distribution, ed)
{
is >> ed._lambda;
return is;
}
/**
* Returns true iff the two distributions will produce identical
* sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(exponential_distribution, lhs, rhs)
{ return lhs._lambda == rhs._lambda; }
/**
* Returns true iff the two distributions will produce different
* sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(exponential_distribution)
private:
result_type _lambda;
};
} // namespace random
using random::exponential_distribution;
} // namespace boost
#endif // BOOST_RANDOM_EXPONENTIAL_DISTRIBUTION_HPP
@@ -0,0 +1,177 @@
/* boost random/extreme_value_distribution.hpp header file
*
* Copyright Steven Watanabe 2010
* 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_EXTREME_VALUE_DISTRIBUTION_HPP
#define BOOST_RANDOM_EXTREME_VALUE_DISTRIBUTION_HPP
#include <boost/config/no_tr1/cmath.hpp>
#include <iosfwd>
#include <istream>
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/uniform_01.hpp>
namespace boost {
namespace random {
/**
* The extreme value distribution is a real valued distribution with two
* parameters a and b.
*
* It has \f$\displaystyle p(x) = \frac{1}{b}e^{\frac{a-x}{b} - e^\frac{a-x}{b}}\f$.
*/
template<class RealType = double>
class extreme_value_distribution {
public:
typedef RealType result_type;
typedef RealType input_type;
class param_type {
public:
typedef extreme_value_distribution distribution_type;
/**
* Constructs a @c param_type from the "a" and "b" parameters
* of the distribution.
*
* Requires: b > 0
*/
explicit param_type(RealType a_arg = 1.0, RealType b_arg = 1.0)
: _a(a_arg), _b(b_arg)
{}
/** Returns the "a" parameter of the distribtuion. */
RealType a() const { return _a; }
/** Returns the "b" parameter of the distribution. */
RealType b() const { return _b; }
/** Writes a @c param_type to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{ os << parm._a << ' ' << parm._b; return os; }
/** Reads a @c param_type from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{ is >> parm._a >> std::ws >> parm._b; return is; }
/** Returns true if the two sets of parameters are the same. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._a == rhs._a && lhs._b == rhs._b; }
/** Returns true if the two sets of parameters are the different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
RealType _a;
RealType _b;
};
/**
* Constructs an @c extreme_value_distribution from its "a" and "b" parameters.
*
* Requires: b > 0
*/
explicit extreme_value_distribution(RealType a_arg = 1.0, RealType b_arg = 1.0)
: _a(a_arg), _b(b_arg)
{}
/** Constructs an @c extreme_value_distribution from its parameters. */
explicit extreme_value_distribution(const param_type& parm)
: _a(parm.a()), _b(parm.b())
{}
/**
* Returns a random variate distributed according to the
* @c extreme_value_distribution.
*/
template<class URNG>
RealType operator()(URNG& urng) const
{
using std::log;
return _a - log(-log(uniform_01<RealType>()(urng))) * _b;
}
/**
* Returns a random variate distributed accordint to the extreme
* value distribution with parameters specified by @c param.
*/
template<class URNG>
RealType operator()(URNG& urng, const param_type& parm) const
{
return extreme_value_distribution(parm)(urng);
}
/** Returns the "a" parameter of the distribution. */
RealType a() const { return _a; }
/** Returns the "b" parameter of the distribution. */
RealType b() const { return _b; }
/** Returns the smallest value that the distribution can produce. */
RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return -std::numeric_limits<RealType>::infinity(); }
/** Returns the largest value that the distribution can produce. */
RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return std::numeric_limits<RealType>::infinity(); }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(_a, _b); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
_a = parm.a();
_b = parm.b();
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { }
/** Writes an @c extreme_value_distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, extreme_value_distribution, wd)
{
os << wd.param();
return os;
}
/** Reads an @c extreme_value_distribution from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, extreme_value_distribution, wd)
{
param_type parm;
if(is >> parm) {
wd.param(parm);
}
return is;
}
/**
* Returns true if the two instances of @c extreme_value_distribution will
* return identical sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(extreme_value_distribution, lhs, rhs)
{ return lhs._a == rhs._a && lhs._b == rhs._b; }
/**
* Returns true if the two instances of @c extreme_value_distribution will
* return different sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(extreme_value_distribution)
private:
RealType _a;
RealType _b;
};
} // namespace random
} // namespace boost
#endif // BOOST_RANDOM_EXTREME_VALUE_DISTRIBUTION_HPP
@@ -0,0 +1,183 @@
/* boost random/fisher_f_distribution.hpp header file
*
* Copyright Steven Watanabe 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_FISHER_F_DISTRIBUTION_HPP
#define BOOST_RANDOM_FISHER_F_DISTRIBUTION_HPP
#include <iosfwd>
#include <istream>
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/chi_squared_distribution.hpp>
namespace boost {
namespace random {
/**
* The Fisher F distribution is a real valued distribution with two
* parameters m and n.
*
* It has \f$\displaystyle p(x) =
* \frac{\Gamma((m+n)/2)}{\Gamma(m/2)\Gamma(n/2)}
* \left(\frac{m}{n}\right)^{m/2}
* x^{(m/2)-1} \left(1+\frac{mx}{n}\right)^{-(m+n)/2}
* \f$.
*/
template<class RealType = double>
class fisher_f_distribution {
public:
typedef RealType result_type;
typedef RealType input_type;
class param_type {
public:
typedef fisher_f_distribution distribution_type;
/**
* Constructs a @c param_type from the "m" and "n" parameters
* of the distribution.
*
* Requires: m > 0 and n > 0
*/
explicit param_type(RealType m_arg = RealType(1.0),
RealType n_arg = RealType(1.0))
: _m(m_arg), _n(n_arg)
{}
/** Returns the "m" parameter of the distribtuion. */
RealType m() const { return _m; }
/** Returns the "n" parameter of the distribution. */
RealType n() const { return _n; }
/** Writes a @c param_type to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{ os << parm._m << ' ' << parm._n; return os; }
/** Reads a @c param_type from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{ is >> parm._m >> std::ws >> parm._n; return is; }
/** Returns true if the two sets of parameters are the same. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._m == rhs._m && lhs._n == rhs._n; }
/** Returns true if the two sets of parameters are the different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
RealType _m;
RealType _n;
};
/**
* Constructs a @c fisher_f_distribution from its "m" and "n" parameters.
*
* Requires: m > 0 and n > 0
*/
explicit fisher_f_distribution(RealType m_arg = RealType(1.0),
RealType n_arg = RealType(1.0))
: _impl_m(m_arg), _impl_n(n_arg)
{}
/** Constructs an @c fisher_f_distribution from its parameters. */
explicit fisher_f_distribution(const param_type& parm)
: _impl_m(parm.m()), _impl_n(parm.n())
{}
/**
* Returns a random variate distributed according to the
* F distribution.
*/
template<class URNG>
RealType operator()(URNG& urng)
{
return (_impl_m(urng) * n()) / (_impl_n(urng) * m());
}
/**
* Returns a random variate distributed according to the
* F distribution with parameters specified by @c param.
*/
template<class URNG>
RealType operator()(URNG& urng, const param_type& parm) const
{
return fisher_f_distribution(parm)(urng);
}
/** Returns the "m" parameter of the distribution. */
RealType m() const { return _impl_m.n(); }
/** Returns the "n" parameter of the distribution. */
RealType n() const { return _impl_n.n(); }
/** Returns the smallest value that the distribution can produce. */
RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; }
/** Returns the largest value that the distribution can produce. */
RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return std::numeric_limits<RealType>::infinity(); }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(m(), n()); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
typedef chi_squared_distribution<RealType> impl_type;
typename impl_type::param_type m_param(parm.m());
_impl_m.param(m_param);
typename impl_type::param_type n_param(parm.n());
_impl_n.param(n_param);
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { }
/** Writes an @c fisher_f_distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, fisher_f_distribution, fd)
{
os << fd.param();
return os;
}
/** Reads an @c fisher_f_distribution from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, fisher_f_distribution, fd)
{
param_type parm;
if(is >> parm) {
fd.param(parm);
}
return is;
}
/**
* Returns true if the two instances of @c fisher_f_distribution will
* return identical sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(fisher_f_distribution, lhs, rhs)
{ return lhs._impl_m == rhs._impl_m && lhs._impl_n == rhs._impl_n; }
/**
* Returns true if the two instances of @c fisher_f_distribution will
* return different sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(fisher_f_distribution)
private:
chi_squared_distribution<RealType> _impl_m;
chi_squared_distribution<RealType> _impl_n;
};
} // namespace random
} // namespace boost
#endif // BOOST_RANDOM_EXTREME_VALUE_DISTRIBUTION_HPP
@@ -0,0 +1,292 @@
/* boost random/gamma_distribution.hpp header file
*
* Copyright Jens Maurer 2002
* Copyright Steven Watanabe 2010
* 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_GAMMA_DISTRIBUTION_HPP
#define BOOST_RANDOM_GAMMA_DISTRIBUTION_HPP
#include <boost/config/no_tr1/cmath.hpp>
#include <istream>
#include <iosfwd>
#include <boost/assert.hpp>
#include <boost/limits.hpp>
#include <boost/static_assert.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/exponential_distribution.hpp>
namespace boost {
namespace random {
// The algorithm is taken from Knuth
/**
* The gamma distribution is a continuous distribution with two
* parameters alpha and beta. It produces values > 0.
*
* It has
* \f$\displaystyle p(x) = x^{\alpha-1}\frac{e^{-x/\beta}}{\beta^\alpha\Gamma(\alpha)}\f$.
*/
template<class RealType = double>
class gamma_distribution
{
public:
typedef RealType input_type;
typedef RealType result_type;
class param_type
{
public:
typedef gamma_distribution distribution_type;
/**
* Constructs a @c param_type object from the "alpha" and "beta"
* parameters.
*
* Requires: alpha > 0 && beta > 0
*/
param_type(const RealType& alpha_arg = RealType(1.0),
const RealType& beta_arg = RealType(1.0))
: _alpha(alpha_arg), _beta(beta_arg)
{
}
/** Returns the "alpha" parameter of the distribution. */
RealType alpha() const { return _alpha; }
/** Returns the "beta" parameter of the distribution. */
RealType beta() const { return _beta; }
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
/** Writes the parameters to a @c std::ostream. */
template<class CharT, class Traits>
friend std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
const param_type& parm)
{
os << parm._alpha << ' ' << parm._beta;
return os;
}
/** Reads the parameters from a @c std::istream. */
template<class CharT, class Traits>
friend std::basic_istream<CharT, Traits>&
operator>>(std::basic_istream<CharT, Traits>& is, param_type& parm)
{
is >> parm._alpha >> std::ws >> parm._beta;
return is;
}
#endif
/** Returns true if the two sets of parameters are the same. */
friend bool operator==(const param_type& lhs, const param_type& rhs)
{
return lhs._alpha == rhs._alpha && lhs._beta == rhs._beta;
}
/** Returns true if the two sets fo parameters are different. */
friend bool operator!=(const param_type& lhs, const param_type& rhs)
{
return !(lhs == rhs);
}
private:
RealType _alpha;
RealType _beta;
};
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
BOOST_STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer);
#endif
/**
* Creates a new gamma_distribution with parameters "alpha" and "beta".
*
* Requires: alpha > 0 && beta > 0
*/
explicit gamma_distribution(const result_type& alpha_arg = result_type(1.0),
const result_type& beta_arg = result_type(1.0))
: _exp(result_type(1)), _alpha(alpha_arg), _beta(beta_arg)
{
BOOST_ASSERT(_alpha > result_type(0));
BOOST_ASSERT(_beta > result_type(0));
init();
}
/** Constructs a @c gamma_distribution from its parameters. */
explicit gamma_distribution(const param_type& parm)
: _exp(result_type(1)), _alpha(parm.alpha()), _beta(parm.beta())
{
init();
}
// compiler-generated copy ctor and assignment operator are fine
/** Returns the "alpha" paramter of the distribution. */
RealType alpha() const { return _alpha; }
/** Returns the "beta" parameter of the distribution. */
RealType beta() const { return _beta; }
/** Returns the smallest value that the distribution can produce. */
RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; }
/* Returns the largest value that the distribution can produce. */
RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return (std::numeric_limits<RealType>::infinity)(); }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(_alpha, _beta); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
_alpha = parm.alpha();
_beta = parm.beta();
init();
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { _exp.reset(); }
/**
* Returns a random variate distributed according to
* the gamma distribution.
*/
template<class Engine>
result_type operator()(Engine& eng)
{
#ifndef BOOST_NO_STDC_NAMESPACE
// allow for Koenig lookup
using std::tan; using std::sqrt; using std::exp; using std::log;
using std::pow;
#endif
if(_alpha == result_type(1)) {
return _exp(eng) * _beta;
} else if(_alpha > result_type(1)) {
// Can we have a boost::mathconst please?
const result_type pi = result_type(3.14159265358979323846);
for(;;) {
result_type y = tan(pi * uniform_01<RealType>()(eng));
result_type x = sqrt(result_type(2)*_alpha-result_type(1))*y
+ _alpha-result_type(1);
if(x <= result_type(0))
continue;
if(uniform_01<RealType>()(eng) >
(result_type(1)+y*y) * exp((_alpha-result_type(1))
*log(x/(_alpha-result_type(1)))
- sqrt(result_type(2)*_alpha
-result_type(1))*y))
continue;
return x * _beta;
}
} else /* alpha < 1.0 */ {
for(;;) {
result_type u = uniform_01<RealType>()(eng);
result_type y = _exp(eng);
result_type x, q;
if(u < _p) {
x = exp(-y/_alpha);
q = _p*exp(-x);
} else {
x = result_type(1)+y;
q = _p + (result_type(1)-_p) * pow(x,_alpha-result_type(1));
}
if(u >= q)
continue;
return x * _beta;
}
}
}
template<class URNG>
RealType operator()(URNG& urng, const param_type& parm) const
{
return gamma_distribution(parm)(urng);
}
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
/** Writes a @c gamma_distribution to a @c std::ostream. */
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os,
const gamma_distribution& gd)
{
os << gd.param();
return os;
}
/** Reads a @c gamma_distribution from a @c std::istream. */
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is, gamma_distribution& gd)
{
gd.read(is);
return is;
}
#endif
/**
* Returns true if the two distributions will produce identical
* sequences of random variates given equal generators.
*/
friend bool operator==(const gamma_distribution& lhs,
const gamma_distribution& rhs)
{
return lhs._alpha == rhs._alpha
&& lhs._beta == rhs._beta
&& lhs._exp == rhs._exp;
}
/**
* Returns true if the two distributions can produce different
* sequences of random variates, given equal generators.
*/
friend bool operator!=(const gamma_distribution& lhs,
const gamma_distribution& rhs)
{
return !(lhs == rhs);
}
private:
/// \cond hide_private_members
template<class CharT, class Traits>
void read(std::basic_istream<CharT, Traits>& is)
{
param_type parm;
if(is >> parm) {
param(parm);
}
}
void init()
{
#ifndef BOOST_NO_STDC_NAMESPACE
// allow for Koenig lookup
using std::exp;
#endif
_p = exp(result_type(1)) / (_alpha + exp(result_type(1)));
}
/// \endcond
exponential_distribution<RealType> _exp;
result_type _alpha;
result_type _beta;
// some data precomputed from the parameters
result_type _p;
};
} // namespace random
using random::gamma_distribution;
} // namespace boost
#endif // BOOST_RANDOM_GAMMA_DISTRIBUTION_HPP
@@ -0,0 +1,96 @@
/* boost random/generate_canonical.hpp header file
*
* Copyright Steven Watanabe 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_GENERATE_CANONICAL_HPP
#define BOOST_RANDOM_GENERATE_CANONICAL_HPP
#include <algorithm>
#include <boost/assert.hpp>
#include <boost/config/no_tr1/cmath.hpp>
#include <boost/limits.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/random/detail/signed_unsigned_tools.hpp>
#include <boost/random/detail/generator_bits.hpp>
namespace boost {
namespace random {
namespace detail {
template<class RealType, std::size_t bits, class URNG>
RealType generate_canonical_impl(URNG& g, boost::mpl::true_ /*is_integral*/)
{
using std::pow;
typedef typename URNG::result_type base_result;
std::size_t digits = std::numeric_limits<RealType>::digits;
RealType R = RealType((g.max)()) - RealType((g.min)()) + 1;
RealType mult = R;
RealType limit =
pow(RealType(2),
RealType((std::min)(static_cast<std::size_t>(bits), digits)));
RealType S = RealType(detail::subtract<base_result>()(g(), (g.min)()));
while(mult < limit) {
RealType inc = RealType(detail::subtract<base_result>()(g(), (g.min)()));
S += inc * mult;
mult *= R;
}
return S / mult;
}
template<class RealType, std::size_t bits, class URNG>
RealType generate_canonical_impl(URNG& g, boost::mpl::false_ /*is_integral*/)
{
using std::pow;
using std::floor;
BOOST_ASSERT((g.min)() == 0);
BOOST_ASSERT((g.max)() == 1);
std::size_t digits = std::numeric_limits<RealType>::digits;
std::size_t engine_bits = detail::generator_bits<URNG>::value();
std::size_t b = (std::min)(bits, digits);
RealType R = pow(RealType(2), RealType(engine_bits));
RealType mult = R;
RealType limit = pow(RealType(2), RealType(b));
RealType S = RealType(g() - (g.min)());
while(mult < limit) {
RealType inc(floor((RealType(g()) - RealType((g.min)())) * R));
S += inc * mult;
mult *= R;
}
return S / mult;
}
}
/**
* Returns a value uniformly distributed in the range [0, 1)
* with at least @c bits random bits.
*/
template<class RealType, std::size_t bits, class URNG>
RealType generate_canonical(URNG& g)
{
RealType result = detail::generate_canonical_impl<RealType, bits>(
g, boost::random::traits::is_integral<typename URNG::result_type>());
BOOST_ASSERT(result >= 0);
BOOST_ASSERT(result <= 1);
if(result == 1) {
result -= std::numeric_limits<RealType>::epsilon() / 2;
BOOST_ASSERT(result != 1);
}
return result;
}
} // namespace random
} // namespace boost
#endif // BOOST_RANDOM_GENERATE_CANONICAL_HPP
@@ -0,0 +1,267 @@
/* boost random/geometric_distribution.hpp header file
*
* Copyright Jens Maurer 2000-2001
* Copyright Steven Watanabe 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$
*
* Revision history
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_GEOMETRIC_DISTRIBUTION_HPP
#define BOOST_RANDOM_GEOMETRIC_DISTRIBUTION_HPP
#include <boost/config/no_tr1/cmath.hpp> // std::log
#include <iosfwd>
#include <ios>
#include <boost/assert.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/uniform_01.hpp>
namespace boost {
namespace random {
/**
* An instantiation of the class template @c geometric_distribution models
* a \random_distribution. The distribution produces positive
* integers which are the number of bernoulli trials
* with probability @c p required to get one that fails.
*
* For the geometric distribution, \f$p(i) = p(1-p)^{i}\f$.
*
* @xmlwarning
* This distribution has been updated to match the C++ standard.
* Its behavior has changed from the original
* boost::geometric_distribution. A backwards compatible
* wrapper is provided in namespace boost.
* @endxmlwarning
*/
template<class IntType = int, class RealType = double>
class geometric_distribution
{
public:
typedef RealType input_type;
typedef IntType result_type;
class param_type
{
public:
typedef geometric_distribution distribution_type;
/** Constructs the parameters with p. */
explicit param_type(RealType p_arg = RealType(0.5))
: _p(p_arg)
{
BOOST_ASSERT(RealType(0) < _p && _p < RealType(1));
}
/** Returns the p parameter of the distribution. */
RealType p() const { return _p; }
/** Writes the parameters to a std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{
os << parm._p;
return os;
}
/** Reads the parameters from a std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{
double p_in;
if(is >> p_in) {
if(p_in > RealType(0) && p_in < RealType(1)) {
parm._p = p_in;
} else {
is.setstate(std::ios_base::failbit);
}
}
return is;
}
/** Returns true if the two sets of parameters are equal. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._p == rhs._p; }
/** Returns true if the two sets of parameters are different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
RealType _p;
};
/**
* Contructs a new geometric_distribution with the paramter @c p.
*
* Requires: 0 < p < 1
*/
explicit geometric_distribution(const RealType& p_arg = RealType(0.5))
: _p(p_arg)
{
BOOST_ASSERT(RealType(0) < _p && _p < RealType(1));
init();
}
/** Constructs a new geometric_distribution from its parameters. */
explicit geometric_distribution(const param_type& parm)
: _p(parm.p())
{
init();
}
// compiler-generated copy ctor and assignment operator are fine
/** Returns: the distribution parameter @c p */
RealType p() const { return _p; }
/** Returns the smallest value that the distribution can produce. */
IntType min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return IntType(0); }
/** Returns the largest value that the distribution can produce. */
IntType max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return (std::numeric_limits<IntType>::max)(); }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(_p); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
_p = parm.p();
init();
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { }
/**
* Returns a random variate distributed according to the
* geometric_distribution.
*/
template<class Engine>
result_type operator()(Engine& eng) const
{
using std::log;
using std::floor;
RealType x = RealType(1) - boost::uniform_01<RealType>()(eng);
return IntType(floor(log(x) / _log_1mp));
}
/**
* Returns a random variate distributed according to the
* geometric distribution with parameters specified by param.
*/
template<class Engine>
result_type operator()(Engine& eng, const param_type& parm) const
{ return geometric_distribution(parm)(eng); }
/** Writes the distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, geometric_distribution, gd)
{
os << gd._p;
return os;
}
/** Reads the distribution from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, geometric_distribution, gd)
{
param_type parm;
if(is >> parm) {
gd.param(parm);
}
return is;
}
/**
* Returns true if the two distributions will produce identical
* sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(geometric_distribution, lhs, rhs)
{ return lhs._p == rhs._p; }
/**
* Returns true if the two distributions may produce different
* sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(geometric_distribution)
private:
/// \cond show_private
void init()
{
using std::log;
_log_1mp = log(1 - _p);
}
RealType _p;
RealType _log_1mp;
/// \endcond
};
} // namespace random
/// \cond show_deprecated
/**
* Provided for backwards compatibility. This class is
* deprecated. It provides the old behavior of geometric_distribution
* with \f$p(i) = (1-p) p^{i-1}\f$.
*/
template<class IntType = int, class RealType = double>
class geometric_distribution
{
public:
typedef RealType input_type;
typedef IntType result_type;
explicit geometric_distribution(RealType p_arg = RealType(0.5))
: _impl(1 - p_arg) {}
RealType p() const { return 1 - _impl.p(); }
void reset() {}
template<class Engine>
IntType operator()(Engine& eng) const { return _impl(eng) + IntType(1); }
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, geometric_distribution, gd)
{
os << gd.p();
return os;
}
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, geometric_distribution, gd)
{
RealType val;
if(is >> val) {
typename impl_type::param_type impl_param(1 - val);
gd._impl.param(impl_param);
}
return is;
}
private:
typedef random::geometric_distribution<IntType, RealType> impl_type;
impl_type _impl;
};
/// \endcond
} // namespace boost
#endif // BOOST_RANDOM_GEOMETRIC_DISTRIBUTION_HPP
@@ -0,0 +1,883 @@
/* boost random/hyperexponential_distribution.hpp header file
*
* Copyright Marco Guazzone 2014
* 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.
*
* Much of the code here taken by boost::math::hyperexponential_distribution.
* To this end, we would like to thank Paul Bristow and John Maddock for their
* valuable feedback.
*
* \author Marco Guazzone (marco.guazzone@gmail.com)
*/
#ifndef BOOST_RANDOM_HYPEREXPONENTIAL_DISTRIBUTION_HPP
#define BOOST_RANDOM_HYPEREXPONENTIAL_DISTRIBUTION_HPP
#include <boost/config.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/detail/vector_io.hpp>
#include <boost/random/discrete_distribution.hpp>
#include <boost/random/exponential_distribution.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/type_traits/has_pre_increment.hpp>
#include <cassert>
#include <cmath>
#include <cstddef>
#include <iterator>
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
# include <initializer_list>
#endif // BOOST_NO_CXX11_HDR_INITIALIZER_LIST
#include <iostream>
#include <limits>
#include <numeric>
#include <vector>
namespace boost { namespace random {
namespace hyperexp_detail {
template <typename T>
std::vector<T>& normalize(std::vector<T>& v)
{
if (v.size() == 0)
{
return v;
}
const T sum = std::accumulate(v.begin(), v.end(), static_cast<T>(0));
T final_sum = 0;
const typename std::vector<T>::iterator end = --v.end();
for (typename std::vector<T>::iterator it = v.begin();
it != end;
++it)
{
*it /= sum;
final_sum += *it;
}
*end = 1-final_sum; // avoids round off errors thus ensuring the probabilities really sum to 1
return v;
}
template <typename RealT>
bool check_probabilities(std::vector<RealT> const& probabilities)
{
const std::size_t n = probabilities.size();
RealT sum = 0;
for (std::size_t i = 0; i < n; ++i)
{
if (probabilities[i] < 0
|| probabilities[i] > 1
|| !(boost::math::isfinite)(probabilities[i]))
{
return false;
}
sum += probabilities[i];
}
//NOTE: the check below seems to fail on some architectures.
// So we commented it.
//// - We try to keep phase probabilities correctly normalized in the distribution constructors
//// - However in practice we have to allow for a very slight divergence from a sum of exactly 1:
////if (std::abs(sum-1) > (std::numeric_limits<RealT>::epsilon()*2))
//// This is from Knuth "The Art of Computer Programming: Vol.2, 3rd Ed", and can be used to
//// check is two numbers are approximately equal
//const RealT one = 1;
//const RealT tol = std::numeric_limits<RealT>::epsilon()*2.0;
//if (std::abs(sum-one) > (std::max(std::abs(sum), std::abs(one))*tol))
//{
// return false;
//}
return true;
}
template <typename RealT>
bool check_rates(std::vector<RealT> const& rates)
{
const std::size_t n = rates.size();
for (std::size_t i = 0; i < n; ++i)
{
if (rates[i] <= 0
|| !(boost::math::isfinite)(rates[i]))
{
return false;
}
}
return true;
}
template <typename RealT>
bool check_params(std::vector<RealT> const& probabilities, std::vector<RealT> const& rates)
{
if (probabilities.size() != rates.size())
{
return false;
}
return check_probabilities(probabilities)
&& check_rates(rates);
}
} // Namespace hyperexp_detail
/**
* The hyperexponential distribution is a real-valued continuous distribution
* with two parameters, the <em>phase probability vector</em> \c probs and the
* <em>rate vector</em> \c rates.
*
* A \f$k\f$-phase hyperexponential distribution is a mixture of \f$k\f$
* exponential distributions.
* For this reason, it is also referred to as <em>mixed exponential
* distribution</em> or <em>parallel \f$k\f$-phase exponential
* distribution</em>.
*
* A \f$k\f$-phase hyperexponential distribution is characterized by two
* parameters, namely a <em>phase probability vector</em> \f$\mathbf{\alpha}=(\alpha_1,\ldots,\alpha_k)\f$ and a <em>rate vector</em> \f$\mathbf{\lambda}=(\lambda_1,\ldots,\lambda_k)\f$.
*
* A \f$k\f$-phase hyperexponential distribution is frequently used in
* <em>queueing theory</em> to model the distribution of the superposition of
* \f$k\f$ independent events, like, for instance, the service time distribution
* of a queueing station with \f$k\f$ servers in parallel where the \f$i\f$-th
* server is chosen with probability \f$\alpha_i\f$ and its service time
* distribution is an exponential distribution with rate \f$\lambda_i\f$
* (Allen,1990; Papadopolous et al.,1993; Trivedi,2002).
*
* For instance, CPUs service-time distribution in a computing system has often
* been observed to possess such a distribution (Rosin,1965).
* Also, the arrival of different types of customer to a single queueing station
* is often modeled as a hyperexponential distribution (Papadopolous et al.,1993).
* Similarly, if a product manufactured in several parallel assemply lines and
* the outputs are merged, the failure density of the overall product is likely
* to be hyperexponential (Trivedi,2002).
*
* Finally, since the hyperexponential distribution exhibits a high Coefficient
* of Variation (CoV), that is a CoV > 1, it is especially suited to fit
* empirical data with large CoV (Feitelson,2014; Wolski et al.,2013) and to
* approximate <em>long-tail probability distributions</em> (Feldmann et al.,1998).
*
* See (Boost,2014) for more information and examples.
*
* A \f$k\f$-phase hyperexponential distribution has a probability density
* function
* \f[
* f(x) = \sum_{i=1}^k \alpha_i \lambda_i e^{-x\lambda_i}
* \f]
* where:
* - \f$k\f$ is the <em>number of phases</em> and also the size of the input
* vector parameters,
* - \f$\mathbf{\alpha}=(\alpha_1,\ldots,\alpha_k)\f$ is the <em>phase probability
* vector</em> parameter, and
* - \f$\mathbf{\lambda}=(\lambda_1,\ldots,\lambda_k)\f$ is the <em>rate vector</em>
* parameter.
* .
*
* Given a \f$k\f$-phase hyperexponential distribution with phase probability
* vector \f$\mathbf{\alpha}\f$ and rate vector \f$\mathbf{\lambda}\f$, the
* random variate generation algorithm consists of the following steps (Tyszer,1999):
* -# Generate a random variable \f$U\f$ uniformly distribution on the interval \f$(0,1)\f$.
* -# Use \f$U\f$ to select the appropriate \f$\lambda_i\f$ (e.g., the
* <em>alias method</em> can possibly be used for this step).
* -# Generate an exponentially distributed random variable \f$X\f$ with rate parameter \f$\lambda_i\f$.
* -# Return \f$X\f$.
* .
*
* References:
* -# A.O. Allen, <em>Probability, Statistics, and Queuing Theory with Computer Science Applications, Second Edition</em>, Academic Press, 1990.
* -# Boost C++ Libraries, <em>Boost.Math / Statistical Distributions: Hyperexponential Distribution</em>, Online: http://www.boost.org/doc/libs/release/libs/math/doc/html/dist.html , 2014.
* -# D.G. Feitelson, <em>Workload Modeling for Computer Systems Performance Evaluation</em>, Cambridge University Press, 2014
* -# A. Feldmann and W. Whitt, <em>Fitting mixtures of exponentials to long-tail distributions to analyze network performance models</em>, Performance Evaluation 31(3-4):245, doi:10.1016/S0166-5316(97)00003-5, 1998.
* -# H.T. Papadopolous, C. Heavey and J. Browne, <em>Queueing Theory in Manufacturing Systems Analysis and Design</em>, Chapman & Hall/CRC, 1993, p. 35.
* -# R.F. Rosin, <em>Determining a computing center environment</em>, Communications of the ACM 8(7):463-468, 1965.
* -# K.S. Trivedi, <em>Probability and Statistics with Reliability, Queueing, and Computer Science Applications</em>, John Wiley & Sons, Inc., 2002.
* -# J. Tyszer, <em>Object-Oriented Computer Simulation of Discrete-Event Systems</em>, Springer, 1999.
* -# Wikipedia, <em>Hyperexponential Distribution</em>, Online: http://en.wikipedia.org/wiki/Hyperexponential_distribution , 2014.
* -# Wolfram Mathematica, <em>Hyperexponential Distribution</em>, Online: http://reference.wolfram.com/language/ref/HyperexponentialDistribution.html , 2014.
* .
*
* \author Marco Guazzone (marco.guazzone@gmail.com)
*/
template<class RealT = double>
class hyperexponential_distribution
{
public: typedef RealT result_type;
public: typedef RealT input_type;
/**
* The parameters of a hyperexponential distribution.
*
* Stores the <em>phase probability vector</em> and the <em>rate vector</em>
* of the hyperexponential distribution.
*
* \author Marco Guazzone (marco.guazzone@gmail.com)
*/
public: class param_type
{
public: typedef hyperexponential_distribution distribution_type;
/**
* Constructs a \c param_type with the default parameters
* of the distribution.
*/
public: param_type()
: probs_(1, 1),
rates_(1, 1)
{
}
/**
* Constructs a \c param_type from the <em>phase probability vector</em>
* and <em>rate vector</em> parameters of the distribution.
*
* The <em>phase probability vector</em> parameter is given by the range
* defined by [\a prob_first, \a prob_last) iterator pair, and the
* <em>rate vector</em> parameter is given by the range defined by
* [\a rate_first, \a rate_last) iterator pair.
*
* \tparam ProbIterT Must meet the requirements of \c InputIterator concept (ISO,2014,sec. 24.2.3 [input.iterators]).
* \tparam RateIterT Must meet the requirements of \c InputIterator concept (ISO,2014,sec. 24.2.3 [input.iterators]).
*
* \param prob_first The iterator to the beginning of the range of non-negative real elements representing the phase probabilities; if elements don't sum to 1, they are normalized.
* \param prob_last The iterator to the ending of the range of non-negative real elements representing the phase probabilities; if elements don't sum to 1, they are normalized.
* \param rate_first The iterator to the beginning of the range of non-negative real elements representing the rates.
* \param rate_last The iterator to the ending of the range of non-negative real elements representing the rates.
*
* References:
* -# ISO, <em>ISO/IEC 14882-2014: Information technology - Programming languages - C++</em>, 2014
* .
*/
public: template <typename ProbIterT, typename RateIterT>
param_type(ProbIterT prob_first, ProbIterT prob_last,
RateIterT rate_first, RateIterT rate_last)
: probs_(prob_first, prob_last),
rates_(rate_first, rate_last)
{
hyperexp_detail::normalize(probs_);
assert( hyperexp_detail::check_params(probs_, rates_) );
}
/**
* Constructs a \c param_type from the <em>phase probability vector</em>
* and <em>rate vector</em> parameters of the distribution.
*
* The <em>phase probability vector</em> parameter is given by the range
* defined by \a prob_range, and the <em>rate vector</em> parameter is
* given by the range defined by \a rate_range.
*
* \tparam ProbRangeT Must meet the requirements of <a href="boost:/libs/range/doc/html/range/concepts.html">Range</a> concept.
* \tparam RateRangeT Must meet the requirements of <a href="boost:/libs/range/doc/html/range/concepts.html">Range</a> concept.
*
* \param prob_range The range of non-negative real elements representing the phase probabilities; if elements don't sum to 1, they are normalized.
* \param rate_range The range of positive real elements representing the rates.
*
* \note
* The final \c disable_if parameter is an implementation detail that
* differentiates between this two argument constructor and the
* iterator-based two argument constructor described below.
*/
// We SFINAE this out of existance if either argument type is
// incrementable as in that case the type is probably an iterator:
public: template <typename ProbRangeT, typename RateRangeT>
param_type(ProbRangeT const& prob_range,
RateRangeT const& rate_range,
typename boost::disable_if_c<boost::has_pre_increment<ProbRangeT>::value || boost::has_pre_increment<RateRangeT>::value>::type* = 0)
: probs_(boost::begin(prob_range), boost::end(prob_range)),
rates_(boost::begin(rate_range), boost::end(rate_range))
{
hyperexp_detail::normalize(probs_);
assert( hyperexp_detail::check_params(probs_, rates_) );
}
/**
* Constructs a \c param_type from the <em>rate vector</em> parameter of
* the distribution and with equal phase probabilities.
*
* The <em>rate vector</em> parameter is given by the range defined by
* [\a rate_first, \a rate_last) iterator pair, and the <em>phase
* probability vector</em> parameter is set to the equal phase
* probabilities (i.e., to a vector of the same length \f$k\f$ of the
* <em>rate vector</em> and with each element set to \f$1.0/k\f$).
*
* \tparam RateIterT Must meet the requirements of \c InputIterator concept (ISO,2014,sec. 24.2.3 [input.iterators]).
* \tparam RateIterT2 Must meet the requirements of \c InputIterator concept (ISO,2014,sec. 24.2.3 [input.iterators]).
*
* \param rate_first The iterator to the beginning of the range of non-negative real elements representing the rates.
* \param rate_last The iterator to the ending of the range of non-negative real elements representing the rates.
*
* \note
* The final \c disable_if parameter is an implementation detail that
* differentiates between this two argument constructor and the
* range-based two argument constructor described above.
*
* References:
* -# ISO, <em>ISO/IEC 14882-2014: Information technology - Programming languages - C++</em>, 2014
* .
*/
// We SFINAE this out of existance if the argument type is
// incrementable as in that case the type is probably an iterator.
public: template <typename RateIterT>
param_type(RateIterT rate_first,
RateIterT rate_last,
typename boost::enable_if_c<boost::has_pre_increment<RateIterT>::value>::type* = 0)
: probs_(std::distance(rate_first, rate_last), 1), // will be normalized below
rates_(rate_first, rate_last)
{
assert(probs_.size() == rates_.size());
}
/**
* Constructs a @c param_type from the "rates" parameters
* of the distribution and with equal phase probabilities.
*
* The <em>rate vector</em> parameter is given by the range defined by
* \a rate_range, and the <em>phase probability vector</em> parameter is
* set to the equal phase probabilities (i.e., to a vector of the same
* length \f$k\f$ of the <em>rate vector</em> and with each element set
* to \f$1.0/k\f$).
*
* \tparam RateRangeT Must meet the requirements of <a href="boost:/libs/range/doc/html/range/concepts.html">Range</a> concept.
*
* \param rate_range The range of positive real elements representing the rates.
*/
public: template <typename RateRangeT>
param_type(RateRangeT const& rate_range)
: probs_(boost::size(rate_range), 1), // Will be normalized below
rates_(boost::begin(rate_range), boost::end(rate_range))
{
hyperexp_detail::normalize(probs_);
assert( hyperexp_detail::check_params(probs_, rates_) );
}
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
/**
* Constructs a \c param_type from the <em>phase probability vector</em>
* and <em>rate vector</em> parameters of the distribution.
*
* The <em>phase probability vector</em> parameter is given by the
* <em>brace-init-list</em> (ISO,2014,sec. 8.5.4 [dcl.init.list])
* defined by \a l1, and the <em>rate vector</em> parameter is given by the
* <em>brace-init-list</em> (ISO,2014,sec. 8.5.4 [dcl.init.list])
* defined by \a l2.
*
* \param l1 The initializer list for inizializing the phase probability vector.
* \param l2 The initializer list for inizializing the rate vector.
*
* References:
* -# ISO, <em>ISO/IEC 14882-2014: Information technology - Programming languages - C++</em>, 2014
* .
*/
public: param_type(std::initializer_list<RealT> l1, std::initializer_list<RealT> l2)
: probs_(l1.begin(), l1.end()),
rates_(l2.begin(), l2.end())
{
hyperexp_detail::normalize(probs_);
assert( hyperexp_detail::check_params(probs_, rates_) );
}
/**
* Constructs a \c param_type from the <em>rate vector</em> parameter
* of the distribution and with equal phase probabilities.
*
* The <em>rate vector</em> parameter is given by the
* <em>brace-init-list</em> (ISO,2014,sec. 8.5.4 [dcl.init.list])
* defined by \a l1, and the <em>phase probability vector</em> parameter is
* set to the equal phase probabilities (i.e., to a vector of the same
* length \f$k\f$ of the <em>rate vector</em> and with each element set
* to \f$1.0/k\f$).
*
* \param l1 The initializer list for inizializing the rate vector.
*
* References:
* -# ISO, <em>ISO/IEC 14882-2014: Information technology - Programming languages - C++</em>, 2014
* .
*/
public: param_type(std::initializer_list<RealT> l1)
: probs_(std::distance(l1.begin(), l1.end()), 1), // Will be normalized below
rates_(l1.begin(), l1.end())
{
hyperexp_detail::normalize(probs_);
assert( hyperexp_detail::check_params(probs_, rates_) );
}
#endif // BOOST_NO_CXX11_HDR_INITIALIZER_LIST
/**
* Gets the <em>phase probability vector</em> parameter of the distribtuion.
*
* \return The <em>phase probability vector</em> parameter of the distribution.
*
* \note
* The returned probabilities are the normalized version of the ones
* passed at construction time.
*/
public: std::vector<RealT> probabilities() const
{
return probs_;
}
/**
* Gets the <em>rate vector</em> parameter of the distribtuion.
*
* \return The <em>rate vector</em> parameter of the distribution.
*/
public: std::vector<RealT> rates() const
{
return rates_;
}
/** Writes a \c param_type to a \c std::ostream. */
public: BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, param)
{
detail::print_vector(os, param.probs_);
os << ' ';
detail::print_vector(os, param.rates_);
return os;
}
/** Reads a \c param_type from a \c std::istream. */
public: BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, param)
{
// NOTE: if \c std::ios_base::exceptions is set, the code below may
// throw in case of a I/O failure.
// To prevent leaving the state of \c param inconsistent:
// - if an exception is thrown, the state of \c param is left
// unchanged (i.e., is the same as the one at the beginning
// of the function's execution), and
// - the state of \c param only after reading the whole input.
std::vector<RealT> probs;
std::vector<RealT> rates;
// Reads probability and rate vectors
detail::read_vector(is, probs);
if (!is)
{
return is;
}
is >> std::ws;
detail::read_vector(is, rates);
if (!is)
{
return is;
}
// Update the state of the param_type object
if (probs.size() > 0)
{
param.probs_.swap(probs);
probs.clear();
}
if (rates.size() > 0)
{
param.rates_.swap(rates);
rates.clear();
}
bool fail = false;
// Adjust vector sizes (if needed)
if (param.probs_.size() != param.rates_.size()
|| param.probs_.size() == 0)
{
fail = true;
const std::size_t np = param.probs_.size();
const std::size_t nr = param.rates_.size();
if (np > nr)
{
param.rates_.resize(np, 1);
}
else if (nr > np)
{
param.probs_.resize(nr, 1);
}
else
{
param.probs_.resize(1, 1);
param.rates_.resize(1, 1);
}
}
// Normalize probabilities
// NOTE: this cannot be done earlier since the probability vector
// can be changed due to size conformance
hyperexp_detail::normalize(param.probs_);
// Set the error state in the underlying stream in case of invalid input
if (fail)
{
// This throws an exception if ios_base::exception(failbit) is enabled
is.setstate(std::ios_base::failbit);
}
//post: vector size conformance
assert(param.probs_.size() == param.rates_.size());
return is;
}
/** Returns true if the two sets of parameters are the same. */
public: BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{
return lhs.probs_ == rhs.probs_
&& lhs.rates_ == rhs.rates_;
}
/** Returns true if the two sets of parameters are the different. */
public: BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private: std::vector<RealT> probs_; ///< The <em>phase probability vector</em> parameter of the distribution
private: std::vector<RealT> rates_; ///< The <em>rate vector</em> parameter of the distribution
}; // param_type
/**
* Constructs a 1-phase \c hyperexponential_distribution (i.e., an
* exponential distribution) with rate 1.
*/
public: hyperexponential_distribution()
: dd_(std::vector<RealT>(1, 1)),
rates_(1, 1)
{
// empty
}
/**
* Constructs a \c hyperexponential_distribution from the <em>phase
* probability vector</em> and <em>rate vector</em> parameters of the
* distribution.
*
* The <em>phase probability vector</em> parameter is given by the range
* defined by [\a prob_first, \a prob_last) iterator pair, and the
* <em>rate vector</em> parameter is given by the range defined by
* [\a rate_first, \a rate_last) iterator pair.
*
* \tparam ProbIterT Must meet the requirements of \c InputIterator concept (ISO,2014,sec. 24.2.3 [input.iterators]).
* \tparam RateIterT Must meet the requirements of \c InputIterator concept (ISO,2014,sec. 24.2.3 [input.iterators]).
*
* \param prob_first The iterator to the beginning of the range of non-negative real elements representing the phase probabilities; if elements don't sum to 1, they are normalized.
* \param prob_last The iterator to the ending of the range of non-negative real elements representing the phase probabilities; if elements don't sum to 1, they are normalized.
* \param rate_first The iterator to the beginning of the range of non-negative real elements representing the rates.
* \param rate_last The iterator to the ending of the range of non-negative real elements representing the rates.
*
* References:
* -# ISO, <em>ISO/IEC 14882-2014: Information technology - Programming languages - C++</em>, 2014
* .
*/
public: template <typename ProbIterT, typename RateIterT>
hyperexponential_distribution(ProbIterT prob_first, ProbIterT prob_last,
RateIterT rate_first, RateIterT rate_last)
: dd_(prob_first, prob_last),
rates_(rate_first, rate_last)
{
assert( hyperexp_detail::check_params(dd_.probabilities(), rates_) );
}
/**
* Constructs a \c hyperexponential_distribution from the <em>phase
* probability vector</em> and <em>rate vector</em> parameters of the
* distribution.
*
* The <em>phase probability vector</em> parameter is given by the range
* defined by \a prob_range, and the <em>rate vector</em> parameter is
* given by the range defined by \a rate_range.
*
* \tparam ProbRangeT Must meet the requirements of <a href="boost:/libs/range/doc/html/range/concepts.html">Range</a> concept.
* \tparam RateRangeT Must meet the requirements of <a href="boost:/libs/range/doc/html/range/concepts.html">Range</a> concept.
*
* \param prob_range The range of non-negative real elements representing the phase probabilities; if elements don't sum to 1, they are normalized.
* \param rate_range The range of positive real elements representing the rates.
*
* \note
* The final \c disable_if parameter is an implementation detail that
* differentiates between this two argument constructor and the
* iterator-based two argument constructor described below.
*/
// We SFINAE this out of existance if either argument type is
// incrementable as in that case the type is probably an iterator:
public: template <typename ProbRangeT, typename RateRangeT>
hyperexponential_distribution(ProbRangeT const& prob_range,
RateRangeT const& rate_range,
typename boost::disable_if_c<boost::has_pre_increment<ProbRangeT>::value || boost::has_pre_increment<RateRangeT>::value>::type* = 0)
: dd_(prob_range),
rates_(boost::begin(rate_range), boost::end(rate_range))
{
assert( hyperexp_detail::check_params(dd_.probabilities(), rates_) );
}
/**
* Constructs a \c hyperexponential_distribution from the <em>rate
* vector</em> parameter of the distribution and with equal phase
* probabilities.
*
* The <em>rate vector</em> parameter is given by the range defined by
* [\a rate_first, \a rate_last) iterator pair, and the <em>phase
* probability vector</em> parameter is set to the equal phase
* probabilities (i.e., to a vector of the same length \f$k\f$ of the
* <em>rate vector</em> and with each element set to \f$1.0/k\f$).
*
* \tparam RateIterT Must meet the requirements of \c InputIterator concept (ISO,2014,sec. 24.2.3 [input.iterators]).
* \tparam RateIterT2 Must meet the requirements of \c InputIterator concept (ISO,2014,sec. 24.2.3 [input.iterators]).
*
* \param rate_first The iterator to the beginning of the range of non-negative real elements representing the rates.
* \param rate_last The iterator to the ending of the range of non-negative real elements representing the rates.
*
* \note
* The final \c disable_if parameter is an implementation detail that
* differentiates between this two argument constructor and the
* range-based two argument constructor described above.
*
* References:
* -# ISO, <em>ISO/IEC 14882-2014: Information technology - Programming languages - C++</em>, 2014
* .
*/
// We SFINAE this out of existance if the argument type is
// incrementable as in that case the type is probably an iterator.
public: template <typename RateIterT>
hyperexponential_distribution(RateIterT rate_first,
RateIterT rate_last,
typename boost::enable_if_c<boost::has_pre_increment<RateIterT>::value>::type* = 0)
: dd_(std::vector<RealT>(std::distance(rate_first, rate_last), 1)),
rates_(rate_first, rate_last)
{
assert( hyperexp_detail::check_params(dd_.probabilities(), rates_) );
}
/**
* Constructs a @c param_type from the "rates" parameters
* of the distribution and with equal phase probabilities.
*
* The <em>rate vector</em> parameter is given by the range defined by
* \a rate_range, and the <em>phase probability vector</em> parameter is
* set to the equal phase probabilities (i.e., to a vector of the same
* length \f$k\f$ of the <em>rate vector</em> and with each element set
* to \f$1.0/k\f$).
*
* \tparam RateRangeT Must meet the requirements of <a href="boost:/libs/range/doc/html/range/concepts.html">Range</a> concept.
*
* \param rate_range The range of positive real elements representing the rates.
*/
public: template <typename RateRangeT>
hyperexponential_distribution(RateRangeT const& rate_range)
: dd_(std::vector<RealT>(boost::size(rate_range), 1)),
rates_(boost::begin(rate_range), boost::end(rate_range))
{
assert( hyperexp_detail::check_params(dd_.probabilities(), rates_) );
}
/**
* Constructs a \c hyperexponential_distribution from its parameters.
*
* \param param The parameters of the distribution.
*/
public: explicit hyperexponential_distribution(param_type const& param)
: dd_(param.probabilities()),
rates_(param.rates())
{
assert( hyperexp_detail::check_params(dd_.probabilities(), rates_) );
}
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
/**
* Constructs a \c hyperexponential_distribution from the <em>phase
* probability vector</em> and <em>rate vector</em> parameters of the
* distribution.
*
* The <em>phase probability vector</em> parameter is given by the
* <em>brace-init-list</em> (ISO,2014,sec. 8.5.4 [dcl.init.list])
* defined by \a l1, and the <em>rate vector</em> parameter is given by the
* <em>brace-init-list</em> (ISO,2014,sec. 8.5.4 [dcl.init.list])
* defined by \a l2.
*
* \param l1 The initializer list for inizializing the phase probability vector.
* \param l2 The initializer list for inizializing the rate vector.
*
* References:
* -# ISO, <em>ISO/IEC 14882-2014: Information technology - Programming languages - C++</em>, 2014
* .
*/
public: hyperexponential_distribution(std::initializer_list<RealT> const& l1, std::initializer_list<RealT> const& l2)
: dd_(l1.begin(), l1.end()),
rates_(l2.begin(), l2.end())
{
assert( hyperexp_detail::check_params(dd_.probabilities(), rates_) );
}
/**
* Constructs a \c hyperexponential_distribution from the <em>rate
* vector</em> parameter of the distribution and with equal phase
* probabilities.
*
* The <em>rate vector</em> parameter is given by the
* <em>brace-init-list</em> (ISO,2014,sec. 8.5.4 [dcl.init.list])
* defined by \a l1, and the <em>phase probability vector</em> parameter is
* set to the equal phase probabilities (i.e., to a vector of the same
* length \f$k\f$ of the <em>rate vector</em> and with each element set
* to \f$1.0/k\f$).
*
* \param l1 The initializer list for inizializing the rate vector.
*
* References:
* -# ISO, <em>ISO/IEC 14882-2014: Information technology - Programming languages - C++</em>, 2014
* .
*/
public: hyperexponential_distribution(std::initializer_list<RealT> const& l1)
: dd_(std::vector<RealT>(std::distance(l1.begin(), l1.end()), 1)),
rates_(l1.begin(), l1.end())
{
assert( hyperexp_detail::check_params(dd_.probabilities(), rates_) );
}
#endif
/**
* Gets a random variate distributed according to the
* hyperexponential distribution.
*
* \tparam URNG Must meet the requirements of \uniform_random_number_generator.
*
* \param urng A uniform random number generator object.
*
* \return A random variate distributed according to the hyperexponential distribution.
*/
public: template<class URNG>\
RealT operator()(URNG& urng) const
{
const int i = dd_(urng);
return boost::random::exponential_distribution<RealT>(rates_[i])(urng);
}
/**
* Gets a random variate distributed according to the hyperexponential
* distribution with parameters specified by \c param.
*
* \tparam URNG Must meet the requirements of \uniform_random_number_generator.
*
* \param urng A uniform random number generator object.
* \param param A distribution parameter object.
*
* \return A random variate distributed according to the hyperexponential distribution.
* distribution with parameters specified by \c param.
*/
public: template<class URNG>
RealT operator()(URNG& urng, const param_type& param) const
{
return hyperexponential_distribution(param)(urng);
}
/** Returns the number of phases of the distribution. */
public: std::size_t num_phases() const
{
return rates_.size();
}
/** Returns the <em>phase probability vector</em> parameter of the distribution. */
public: std::vector<RealT> probabilities() const
{
return dd_.probabilities();
}
/** Returns the <em>rate vector</em> parameter of the distribution. */
public: std::vector<RealT> rates() const
{
return rates_;
}
/** Returns the smallest value that the distribution can produce. */
public: RealT min BOOST_PREVENT_MACRO_SUBSTITUTION () const
{
return 0;
}
/** Returns the largest value that the distribution can produce. */
public: RealT max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{
return std::numeric_limits<RealT>::infinity();
}
/** Returns the parameters of the distribution. */
public: param_type param() const
{
std::vector<RealT> probs = dd_.probabilities();
return param_type(probs.begin(), probs.end(), rates_.begin(), rates_.end());
}
/** Sets the parameters of the distribution. */
public: void param(param_type const& param)
{
dd_.param(typename boost::random::discrete_distribution<int,RealT>::param_type(param.probabilities()));
rates_ = param.rates();
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
public: void reset()
{
// empty
}
/** Writes an @c hyperexponential_distribution to a @c std::ostream. */
public: BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, hyperexponential_distribution, hd)
{
os << hd.param();
return os;
}
/** Reads an @c hyperexponential_distribution from a @c std::istream. */
public: BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, hyperexponential_distribution, hd)
{
param_type param;
if(is >> param)
{
hd.param(param);
}
return is;
}
/**
* Returns true if the two instances of @c hyperexponential_distribution will
* return identical sequences of values given equal generators.
*/
public: BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(hyperexponential_distribution, lhs, rhs)
{
return lhs.dd_ == rhs.dd_
&& lhs.rates_ == rhs.rates_;
}
/**
* Returns true if the two instances of @c hyperexponential_distribution will
* return different sequences of values given equal generators.
*/
public: BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(hyperexponential_distribution)
private: boost::random::discrete_distribution<int,RealT> dd_; ///< The \c discrete_distribution used to sample the phase probability and choose the rate
private: std::vector<RealT> rates_; ///< The <em>rate vector</em> parameter of the distribution
}; // hyperexponential_distribution
}} // namespace boost::random
#endif // BOOST_RANDOM_HYPEREXPONENTIAL_DISTRIBUTION_HPP
@@ -0,0 +1,271 @@
/* boost random/independent_bits.hpp header file
*
* Copyright Steven Watanabe 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_INDEPENDENT_BITS_HPP
#define BOOST_RANDOM_INDEPENDENT_BITS_HPP
#include <istream>
#include <iosfwd>
#include <boost/assert.hpp>
#include <boost/limits.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/integer/integer_mask.hpp>
#include <boost/random/traits.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/integer_log2.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/detail/seed.hpp>
#include <boost/random/detail/seed_impl.hpp>
#include <boost/random/detail/signed_unsigned_tools.hpp>
namespace boost {
namespace random {
/**
* An instantiation of class template @c independent_bits_engine
* model a \pseudo_random_number_generator. It generates random
* numbers distributed between [0, 2^w) by combining one or
* more invocations of the base engine.
*
* Requires: 0 < w <= std::numeric_limits<UIntType>::digits
*/
template<class Engine, std::size_t w, class UIntType>
class independent_bits_engine
{
public:
typedef Engine base_type;
typedef UIntType result_type;
typedef typename Engine::result_type base_result_type;
// Required by old Boost.Random concept
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
/** Returns the smallest value that the generator can produce. */
static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return 0; }
/** Returns the largest value that the generator can produce. */
static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return max_imp(boost::is_integral<UIntType>()); }
/**
* Constructs an @c independent_bits_engine using the
* default constructor of the base generator.
*/
independent_bits_engine() { }
/**
* Constructs an @c independent_bits_engine, using seed as
* the constructor argument for both base generators.
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(independent_bits_engine,
base_result_type, seed_arg)
{
_base.seed(seed_arg);
}
/**
* Constructs an @c independent_bits_engine, using seq as
* the constructor argument for the base generator.
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(independent_bits_engine,
SeedSeq, seq)
{ _base.seed(seq); }
/** Constructs an @c independent_bits_engine by copying @c base. */
independent_bits_engine(const base_type& base_arg) : _base(base_arg) {}
/**
* Contructs an @c independent_bits_engine with
* values from the range defined by the input iterators first
* and last. first will be modified to point to the element
* after the last one used.
*
* Throws: @c std::invalid_argument if the input range is too small.
*
* Exception Safety: Basic
*/
template<class It>
independent_bits_engine(It& first, It last) : _base(first, last) { }
/**
* Seeds an @c independent_bits_engine using the default
* seed of the base generator.
*/
void seed() { _base.seed(); }
/**
* Seeds an @c independent_bits_engine, using @c seed as the
* seed for the base generator.
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(independent_bits_engine,
base_result_type, seed_arg)
{ _base.seed(seed_arg); }
/**
* Seeds an @c independent_bits_engine, using @c seq to
* seed the base generator.
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(independent_bits_engine,
SeedSeq, seq)
{ _base.seed(seq); }
/**
* Seeds an @c independent_bits_engine with
* values from the range defined by the input iterators first
* and last. first will be modified to point to the element
* after the last one used.
*
* Throws: @c std::invalid_argument if the input range is too small.
*
* Exception Safety: Basic
*/
template<class It> void seed(It& first, It last)
{ _base.seed(first, last); }
/** Returns the next value of the generator. */
result_type operator()()
{
// While it may seem wasteful to recalculate this
// every time, both msvc and gcc can propagate
// constants, resolving this at compile time.
base_unsigned range =
detail::subtract<base_result_type>()((_base.max)(), (_base.min)());
std::size_t m =
(range == (std::numeric_limits<base_unsigned>::max)()) ?
std::numeric_limits<base_unsigned>::digits :
detail::integer_log2(range + 1);
std::size_t n = (w + m - 1) / m;
std::size_t w0, n0;
base_unsigned y0, y1;
base_unsigned y0_mask, y1_mask;
calc_params(n, range, w0, n0, y0, y1, y0_mask, y1_mask);
if(base_unsigned(range - y0 + 1) > y0 / n) {
// increment n and try again.
++n;
calc_params(n, range, w0, n0, y0, y1, y0_mask, y1_mask);
}
BOOST_ASSERT(n0*w0 + (n - n0)*(w0 + 1) == w);
result_type S = 0;
for(std::size_t k = 0; k < n0; ++k) {
base_unsigned u;
do {
u = detail::subtract<base_result_type>()(_base(), (_base.min)());
} while(u > base_unsigned(y0 - 1));
S = (S << w0) + (u & y0_mask);
}
for(std::size_t k = 0; k < (n - n0); ++k) {
base_unsigned u;
do {
u = detail::subtract<base_result_type>()(_base(), (_base.min)());
} while(u > base_unsigned(y1 - 1));
S = (S << (w0 + 1)) + (u & y1_mask);
}
return S;
}
/** Fills a range with random values */
template<class Iter>
void generate(Iter first, Iter last)
{ detail::generate_from_int(*this, first, last); }
/** Advances the state of the generator by @c z. */
void discard(boost::uintmax_t z)
{
for(boost::uintmax_t i = 0; i < z; ++i) {
(*this)();
}
}
const base_type& base() const { return _base; }
/**
* Writes the textual representation if the generator to a @c std::ostream.
* The textual representation of the engine is the textual representation
* of the base engine.
*/
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, independent_bits_engine, r)
{
os << r._base;
return os;
}
/**
* Reads the state of an @c independent_bits_engine from a
* @c std::istream.
*/
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, independent_bits_engine, r)
{
is >> r._base;
return is;
}
/**
* Returns: true iff the two @c independent_bits_engines will
* produce the same sequence of values.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(independent_bits_engine, x, y)
{ return x._base == y._base; }
/**
* Returns: true iff the two @c independent_bits_engines will
* produce different sequences of values.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(independent_bits_engine)
private:
/// \cond show_private
typedef typename boost::random::traits::make_unsigned<base_result_type>::type base_unsigned;
static UIntType max_imp(const boost::true_type&)
{
return boost::low_bits_mask_t<w>::sig_bits;
}
static UIntType max_imp(const boost::false_type&)
{
// We have a multiprecision integer type:
BOOST_STATIC_ASSERT(std::numeric_limits<UIntType>::is_specialized);
return w < std::numeric_limits<UIntType>::digits ? UIntType((UIntType(1) << w) - 1) : UIntType((((UIntType(1) << (w - 1)) - 1) << 1) | 1u);
}
void calc_params(
std::size_t n, base_unsigned range,
std::size_t& w0, std::size_t& n0,
base_unsigned& y0, base_unsigned& y1,
base_unsigned& y0_mask, base_unsigned& y1_mask)
{
BOOST_ASSERT(w >= n);
w0 = w/n;
n0 = n - w % n;
y0_mask = (base_unsigned(2) << (w0 - 1)) - 1;
y1_mask = (y0_mask << 1) | 1;
y0 = (range + 1) & ~y0_mask;
y1 = (range + 1) & ~y1_mask;
BOOST_ASSERT(y0 != 0 || base_unsigned(range + 1) == 0);
}
/// \endcond
Engine _base;
};
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
template<class Engine, std::size_t w, class UIntType>
const bool independent_bits_engine<Engine, w, UIntType>::has_fixed_range;
#endif
} // namespace random
} // namespace boost
#endif // BOOST_RANDOM_INDEPENDENT_BITS_HPP
@@ -0,0 +1,267 @@
/* boost random/inversive_congruential.hpp header file
*
* Copyright Jens Maurer 2000-2001
* 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$
*
* Revision history
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_INVERSIVE_CONGRUENTIAL_HPP
#define BOOST_RANDOM_INVERSIVE_CONGRUENTIAL_HPP
#include <iosfwd>
#include <stdexcept>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/integer/static_log2.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/const_mod.hpp>
#include <boost/random/detail/seed.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/detail/seed_impl.hpp>
#include <boost/random/detail/disable_warnings.hpp>
namespace boost {
namespace random {
// Eichenauer and Lehn 1986
/**
* Instantiations of class template @c inversive_congruential_engine model a
* \pseudo_random_number_generator. It uses the inversive congruential
* algorithm (ICG) described in
*
* @blockquote
* "Inversive pseudorandom number generators: concepts, results and links",
* Peter Hellekalek, In: "Proceedings of the 1995 Winter Simulation
* Conference", C. Alexopoulos, K. Kang, W.R. Lilegdon, and D. Goldsman
* (editors), 1995, pp. 255-262. ftp://random.mat.sbg.ac.at/pub/data/wsc95.ps
* @endblockquote
*
* The output sequence is defined by x(n+1) = (a*inv(x(n)) - b) (mod p),
* where x(0), a, b, and the prime number p are parameters of the generator.
* The expression inv(k) denotes the multiplicative inverse of k in the
* field of integer numbers modulo p, with inv(0) := 0.
*
* The template parameter IntType shall denote a signed integral type large
* enough to hold p; a, b, and p are the parameters of the generators. The
* template parameter val is the validation value checked by validation.
*
* @xmlnote
* The implementation currently uses the Euclidian Algorithm to compute
* the multiplicative inverse. Therefore, the inversive generators are about
* 10-20 times slower than the others (see section"performance"). However,
* the paper talks of only 3x slowdown, so the Euclidian Algorithm is probably
* not optimal for calculating the multiplicative inverse.
* @endxmlnote
*/
template<class IntType, IntType a, IntType b, IntType p>
class inversive_congruential_engine
{
public:
typedef IntType result_type;
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
BOOST_STATIC_CONSTANT(result_type, multiplier = a);
BOOST_STATIC_CONSTANT(result_type, increment = b);
BOOST_STATIC_CONSTANT(result_type, modulus = p);
BOOST_STATIC_CONSTANT(IntType, default_seed = 1);
static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return b == 0 ? 1 : 0; }
static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () { return p-1; }
/**
* Constructs an @c inversive_congruential_engine, seeding it with
* the default seed.
*/
inversive_congruential_engine() { seed(); }
/**
* Constructs an @c inversive_congruential_engine, seeding it with @c x0.
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(inversive_congruential_engine,
IntType, x0)
{ seed(x0); }
/**
* Constructs an @c inversive_congruential_engine, seeding it with values
* produced by a call to @c seq.generate().
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(inversive_congruential_engine,
SeedSeq, seq)
{ seed(seq); }
/**
* Constructs an @c inversive_congruential_engine, seeds it
* with values taken from the itrator range [first, last),
* and adjusts first to point to the element after the last one
* used. If there are not enough elements, throws @c std::invalid_argument.
*
* first and last must be input iterators.
*/
template<class It> inversive_congruential_engine(It& first, It last)
{ seed(first, last); }
/**
* Calls seed(default_seed)
*/
void seed() { seed(default_seed); }
/**
* If c mod m is zero and x0 mod m is zero, changes the current value of
* the generator to 1. Otherwise, changes it to x0 mod m. If c is zero,
* distinct seeds in the range [1,m) will leave the generator in distinct
* states. If c is not zero, the range is [0,m).
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(inversive_congruential_engine, IntType, x0)
{
// wrap _x if it doesn't fit in the destination
if(modulus == 0) {
_value = x0;
} else {
_value = x0 % modulus;
}
// handle negative seeds
if(_value <= 0 && _value != 0) {
_value += modulus;
}
// adjust to the correct range
if(increment == 0 && _value == 0) {
_value = 1;
}
BOOST_ASSERT(_value >= (min)());
BOOST_ASSERT(_value <= (max)());
}
/**
* Seeds an @c inversive_congruential_engine using values from a SeedSeq.
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(inversive_congruential_engine, SeedSeq, seq)
{ seed(detail::seed_one_int<IntType, modulus>(seq)); }
/**
* seeds an @c inversive_congruential_engine with values taken
* from the itrator range [first, last) and adjusts @c first to
* point to the element after the last one used. If there are
* not enough elements, throws @c std::invalid_argument.
*
* @c first and @c last must be input iterators.
*/
template<class It> void seed(It& first, It last)
{ seed(detail::get_one_int<IntType, modulus>(first, last)); }
/** Returns the next output of the generator. */
IntType operator()()
{
typedef const_mod<IntType, p> do_mod;
_value = do_mod::mult_add(a, do_mod::invert(_value), b);
return _value;
}
/** Fills a range with random values */
template<class Iter>
void generate(Iter first, Iter last)
{ detail::generate_from_int(*this, first, last); }
/** Advances the state of the generator by @c z. */
void discard(boost::uintmax_t z)
{
for(boost::uintmax_t j = 0; j < z; ++j) {
(*this)();
}
}
/**
* Writes the textual representation of the generator to a @c std::ostream.
*/
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, inversive_congruential_engine, x)
{
os << x._value;
return os;
}
/**
* Reads the textual representation of the generator from a @c std::istream.
*/
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, inversive_congruential_engine, x)
{
is >> x._value;
return is;
}
/**
* Returns true if the two generators will produce identical
* sequences of outputs.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(inversive_congruential_engine, x, y)
{ return x._value == y._value; }
/**
* Returns true if the two generators will produce different
* sequences of outputs.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(inversive_congruential_engine)
private:
IntType _value;
};
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
// A definition is required even for integral static constants
template<class IntType, IntType a, IntType b, IntType p>
const bool inversive_congruential_engine<IntType, a, b, p>::has_fixed_range;
template<class IntType, IntType a, IntType b, IntType p>
const typename inversive_congruential_engine<IntType, a, b, p>::result_type inversive_congruential_engine<IntType, a, b, p>::multiplier;
template<class IntType, IntType a, IntType b, IntType p>
const typename inversive_congruential_engine<IntType, a, b, p>::result_type inversive_congruential_engine<IntType, a, b, p>::increment;
template<class IntType, IntType a, IntType b, IntType p>
const typename inversive_congruential_engine<IntType, a, b, p>::result_type inversive_congruential_engine<IntType, a, b, p>::modulus;
template<class IntType, IntType a, IntType b, IntType p>
const typename inversive_congruential_engine<IntType, a, b, p>::result_type inversive_congruential_engine<IntType, a, b, p>::default_seed;
#endif
/// \cond show_deprecated
// provided for backwards compatibility
template<class IntType, IntType a, IntType b, IntType p, IntType val = 0>
class inversive_congruential : public inversive_congruential_engine<IntType, a, b, p>
{
typedef inversive_congruential_engine<IntType, a, b, p> base_type;
public:
inversive_congruential(IntType x0 = 1) : base_type(x0) {}
template<class It>
inversive_congruential(It& first, It last) : base_type(first, last) {}
};
/// \endcond
/**
* The specialization hellekalek1995 was suggested in
*
* @blockquote
* "Inversive pseudorandom number generators: concepts, results and links",
* Peter Hellekalek, In: "Proceedings of the 1995 Winter Simulation
* Conference", C. Alexopoulos, K. Kang, W.R. Lilegdon, and D. Goldsman
* (editors), 1995, pp. 255-262. ftp://random.mat.sbg.ac.at/pub/data/wsc95.ps
* @endblockquote
*/
typedef inversive_congruential_engine<uint32_t, 9102, 2147483647-36884165,
2147483647> hellekalek1995;
} // namespace random
using random::hellekalek1995;
} // namespace boost
#include <boost/random/detail/enable_warnings.hpp>
#endif // BOOST_RANDOM_INVERSIVE_CONGRUENTIAL_HPP
@@ -0,0 +1,537 @@
/* boost random/lagged_fibonacci.hpp header file
*
* Copyright Jens Maurer 2000-2001
* 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$
*
* Revision history
* 2013-10-14 fixed some warnings with Wshadow (mgaunard)
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_LAGGED_FIBONACCI_HPP
#define BOOST_RANDOM_LAGGED_FIBONACCI_HPP
#include <istream>
#include <iosfwd>
#include <algorithm> // std::max
#include <iterator>
#include <boost/config/no_tr1/cmath.hpp> // std::pow
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/cstdint.hpp>
#include <boost/integer/integer_mask.hpp>
#include <boost/random/linear_congruential.hpp>
#include <boost/random/uniform_01.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/seed.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/detail/generator_seed_seq.hpp>
namespace boost {
namespace random {
/**
* Instantiations of class template \lagged_fibonacci_engine model a
* \pseudo_random_number_generator. It uses a lagged Fibonacci
* algorithm with two lags @c p and @c q:
* x(i) = x(i-p) + x(i-q) (mod 2<sup>w</sup>) with p > q.
*/
template<class UIntType, int w, unsigned int p, unsigned int q>
class lagged_fibonacci_engine
{
public:
typedef UIntType result_type;
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
BOOST_STATIC_CONSTANT(int, word_size = w);
BOOST_STATIC_CONSTANT(unsigned int, long_lag = p);
BOOST_STATIC_CONSTANT(unsigned int, short_lag = q);
BOOST_STATIC_CONSTANT(UIntType, default_seed = 331u);
/** Returns the smallest value that the generator can produce. */
static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return 0; }
/** Returns the largest value that the generator can produce. */
static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return low_bits_mask_t<w>::sig_bits; }
/** Creates a new @c lagged_fibonacci_engine and calls @c seed(). */
lagged_fibonacci_engine() { seed(); }
/** Creates a new @c lagged_fibonacci_engine and calls @c seed(value). */
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(lagged_fibonacci_engine,
UIntType, value)
{ seed(value); }
/** Creates a new @c lagged_fibonacci_engine and calls @c seed(seq). */
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(lagged_fibonacci_engine,
SeedSeq, seq)
{ seed(seq); }
/**
* Creates a new @c lagged_fibonacci_engine and calls @c seed(first, last).
*/
template<class It> lagged_fibonacci_engine(It& first, It last)
{ seed(first, last); }
// compiler-generated copy ctor and assignment operator are fine
/** Calls @c seed(default_seed). */
void seed() { seed(default_seed); }
/**
* Sets the state of the generator to values produced by
* a \minstd_rand0 generator.
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(lagged_fibonacci_engine,
UIntType, value)
{
minstd_rand0 intgen(static_cast<boost::uint32_t>(value));
detail::generator_seed_seq<minstd_rand0> gen(intgen);
seed(gen);
}
/**
* Sets the state of the generator using values produced by seq.
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(lagged_fibonacci_engine, SeedSeq, seq)
{
detail::seed_array_int<w>(seq, x);
i = long_lag;
}
/**
* Sets the state of the generator to values from the iterator
* range [first, last). If there are not enough elements in the
* range [first, last) throws @c std::invalid_argument.
*/
template<class It>
void seed(It& first, It last)
{
detail::fill_array_int<w>(first, last, x);
i = long_lag;
}
/** Returns the next value of the generator. */
result_type operator()()
{
if(i >= long_lag)
fill();
return x[i++];
}
/** Fills a range with random values */
template<class Iter>
void generate(Iter first, Iter last)
{ detail::generate_from_int(*this, first, last); }
/** Advances the state of the generator by @c z. */
void discard(boost::uintmax_t z)
{
for(boost::uintmax_t j = 0; j < z; ++j) {
(*this)();
}
}
/**
* Writes the textual representation of the generator to a @c std::ostream.
*/
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, lagged_fibonacci_engine, f)
{
os << f.i;
for(unsigned int j = 0; j < f.long_lag; ++j)
os << ' ' << f.x[j];
return os;
}
/**
* Reads the textual representation of the generator from a @c std::istream.
*/
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, lagged_fibonacci_engine, f)
{
is >> f.i >> std::ws;
for(unsigned int j = 0; j < f.long_lag; ++j)
is >> f.x[j] >> std::ws;
return is;
}
/**
* Returns true if the two generators will produce identical
* sequences of outputs.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(lagged_fibonacci_engine, x_, y_)
{ return x_.i == y_.i && std::equal(x_.x, x_.x+long_lag, y_.x); }
/**
* Returns true if the two generators will produce different
* sequences of outputs.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(lagged_fibonacci_engine)
private:
/// \cond show_private
void fill();
/// \endcond
unsigned int i;
UIntType x[long_lag];
};
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
// A definition is required even for integral static constants
template<class UIntType, int w, unsigned int p, unsigned int q>
const bool lagged_fibonacci_engine<UIntType, w, p, q>::has_fixed_range;
template<class UIntType, int w, unsigned int p, unsigned int q>
const unsigned int lagged_fibonacci_engine<UIntType, w, p, q>::long_lag;
template<class UIntType, int w, unsigned int p, unsigned int q>
const unsigned int lagged_fibonacci_engine<UIntType, w, p, q>::short_lag;
template<class UIntType, int w, unsigned int p, unsigned int q>
const UIntType lagged_fibonacci_engine<UIntType, w, p, q>::default_seed;
#endif
/// \cond show_private
template<class UIntType, int w, unsigned int p, unsigned int q>
void lagged_fibonacci_engine<UIntType, w, p, q>::fill()
{
// two loops to avoid costly modulo operations
{ // extra scope for MSVC brokenness w.r.t. for scope
for(unsigned int j = 0; j < short_lag; ++j)
x[j] = (x[j] + x[j+(long_lag-short_lag)]) & low_bits_mask_t<w>::sig_bits;
}
for(unsigned int j = short_lag; j < long_lag; ++j)
x[j] = (x[j] + x[j-short_lag]) & low_bits_mask_t<w>::sig_bits;
i = 0;
}
/// \endcond
/// \cond show_deprecated
// provided for backwards compatibility
template<class UIntType, int w, unsigned int p, unsigned int q, UIntType v = 0>
class lagged_fibonacci : public lagged_fibonacci_engine<UIntType, w, p, q>
{
typedef lagged_fibonacci_engine<UIntType, w, p, q> base_type;
public:
lagged_fibonacci() {}
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(lagged_fibonacci, UIntType, val)
{ this->seed(val); }
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(lagged_fibonacci, SeedSeq, seq)
{ this->seed(seq); }
template<class It>
lagged_fibonacci(It& first, It last) : base_type(first, last) {}
};
/// \endcond
// lagged Fibonacci generator for the range [0..1)
// contributed by Matthias Troyer
// for p=55, q=24 originally by G. J. Mitchell and D. P. Moore 1958
/**
* Instantiations of class template @c lagged_fibonacci_01 model a
* \pseudo_random_number_generator. It uses a lagged Fibonacci
* algorithm with two lags @c p and @c q, evaluated in floating-point
* arithmetic: x(i) = x(i-p) + x(i-q) (mod 1) with p > q. See
*
* @blockquote
* "Uniform random number generators for supercomputers", Richard Brent,
* Proc. of Fifth Australian Supercomputer Conference, Melbourne,
* Dec. 1992, pp. 704-706.
* @endblockquote
*
* @xmlnote
* The quality of the generator crucially depends on the choice
* of the parameters. User code should employ one of the sensibly
* parameterized generators such as \lagged_fibonacci607 instead.
* @endxmlnote
*
* The generator requires considerable amounts of memory for the storage
* of its state array. For example, \lagged_fibonacci607 requires about
* 4856 bytes and \lagged_fibonacci44497 requires about 350 KBytes.
*/
template<class RealType, int w, unsigned int p, unsigned int q>
class lagged_fibonacci_01_engine
{
public:
typedef RealType result_type;
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
BOOST_STATIC_CONSTANT(int, word_size = w);
BOOST_STATIC_CONSTANT(unsigned int, long_lag = p);
BOOST_STATIC_CONSTANT(unsigned int, short_lag = q);
BOOST_STATIC_CONSTANT(boost::uint32_t, default_seed = 331u);
/** Constructs a @c lagged_fibonacci_01 generator and calls @c seed(). */
lagged_fibonacci_01_engine() { seed(); }
/** Constructs a @c lagged_fibonacci_01 generator and calls @c seed(value). */
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(lagged_fibonacci_01_engine, uint32_t, value)
{ seed(value); }
/** Constructs a @c lagged_fibonacci_01 generator and calls @c seed(gen). */
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(lagged_fibonacci_01_engine, SeedSeq, seq)
{ seed(seq); }
template<class It> lagged_fibonacci_01_engine(It& first, It last)
{ seed(first, last); }
// compiler-generated copy ctor and assignment operator are fine
/** Calls seed(default_seed). */
void seed() { seed(default_seed); }
/**
* Constructs a \minstd_rand0 generator with the constructor parameter
* value and calls seed with it. Distinct seeds in the range
* [1, 2147483647) will produce generators with different states. Other
* seeds will be equivalent to some seed within this range. See
* \linear_congruential_engine for details.
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(lagged_fibonacci_01_engine, boost::uint32_t, value)
{
minstd_rand0 intgen(value);
detail::generator_seed_seq<minstd_rand0> gen(intgen);
seed(gen);
}
/**
* Seeds this @c lagged_fibonacci_01_engine using values produced by
* @c seq.generate.
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(lagged_fibonacci_01_engine, SeedSeq, seq)
{
detail::seed_array_real<w>(seq, x);
i = long_lag;
}
/**
* Seeds this @c lagged_fibonacci_01_engine using values from the
* iterator range [first, last). If there are not enough elements
* in the range, throws @c std::invalid_argument.
*/
template<class It>
void seed(It& first, It last)
{
detail::fill_array_real<w>(first, last, x);
i = long_lag;
}
/** Returns the smallest value that the generator can produce. */
static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return result_type(0); }
/** Returns the upper bound of the generators outputs. */
static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () { return result_type(1); }
/** Returns the next value of the generator. */
result_type operator()()
{
if(i >= long_lag)
fill();
return x[i++];
}
/** Fills a range with random values */
template<class Iter>
void generate(Iter first, Iter last)
{ return detail::generate_from_real(*this, first, last); }
/** Advances the state of the generator by @c z. */
void discard(boost::uintmax_t z)
{
for(boost::uintmax_t j = 0; j < z; ++j) {
(*this)();
}
}
/**
* Writes the textual representation of the generator to a @c std::ostream.
*/
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, lagged_fibonacci_01_engine, f)
{
// allow for Koenig lookup
using std::pow;
os << f.i;
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.x[j] * f.modulus();
os.flags(oldflags);
return os;
}
/**
* Reads the textual representation of the generator from a @c std::istream.
*/
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, lagged_fibonacci_01_engine, f)
{
is >> f.i;
for(unsigned int j = 0; j < f.long_lag; ++j) {
typename lagged_fibonacci_01_engine::result_type value;
is >> std::ws >> value;
f.x[j] = value / f.modulus();
}
return is;
}
/**
* Returns true if the two generators will produce identical
* sequences of outputs.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(lagged_fibonacci_01_engine, x_, y_)
{ return x_.i == y_.i && std::equal(x_.x, x_.x+long_lag, y_.x); }
/**
* Returns true if the two generators will produce different
* sequences of outputs.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(lagged_fibonacci_01_engine)
private:
/// \cond show_private
void fill();
static RealType modulus()
{
using std::pow;
return pow(RealType(2), word_size);
}
/// \endcond
unsigned int i;
RealType x[long_lag];
};
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
// A definition is required even for integral static constants
template<class RealType, int w, unsigned int p, unsigned int q>
const bool lagged_fibonacci_01_engine<RealType, w, p, q>::has_fixed_range;
template<class RealType, int w, unsigned int p, unsigned int q>
const unsigned int lagged_fibonacci_01_engine<RealType, w, p, q>::long_lag;
template<class RealType, int w, unsigned int p, unsigned int q>
const unsigned int lagged_fibonacci_01_engine<RealType, w, p, q>::short_lag;
template<class RealType, int w, unsigned int p, unsigned int q>
const int lagged_fibonacci_01_engine<RealType,w,p,q>::word_size;
template<class RealType, int w, unsigned int p, unsigned int q>
const boost::uint32_t lagged_fibonacci_01_engine<RealType,w,p,q>::default_seed;
#endif
/// \cond show_private
template<class RealType, int w, unsigned int p, unsigned int q>
void lagged_fibonacci_01_engine<RealType, w, p, q>::fill()
{
// two loops to avoid costly modulo operations
{ // extra scope for MSVC brokenness w.r.t. for scope
for(unsigned int j = 0; j < short_lag; ++j) {
RealType t = x[j] + x[j+(long_lag-short_lag)];
if(t >= RealType(1))
t -= RealType(1);
x[j] = t;
}
}
for(unsigned int j = short_lag; j < long_lag; ++j) {
RealType t = x[j] + x[j-short_lag];
if(t >= RealType(1))
t -= RealType(1);
x[j] = t;
}
i = 0;
}
/// \endcond
/// \cond show_deprecated
// provided for backwards compatibility
template<class RealType, int w, unsigned int p, unsigned int q>
class lagged_fibonacci_01 : public lagged_fibonacci_01_engine<RealType, w, p, q>
{
typedef lagged_fibonacci_01_engine<RealType, w, p, q> base_type;
public:
lagged_fibonacci_01() {}
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(lagged_fibonacci_01, boost::uint32_t, val)
{ this->seed(val); }
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(lagged_fibonacci_01, SeedSeq, seq)
{ this->seed(seq); }
template<class It>
lagged_fibonacci_01(It& first, It last) : base_type(first, last) {}
};
/// \endcond
namespace detail {
template<class Engine>
struct generator_bits;
template<class RealType, int w, unsigned int p, unsigned int q>
struct generator_bits<lagged_fibonacci_01_engine<RealType, w, p, q> >
{
static std::size_t value() { return w; }
};
template<class RealType, int w, unsigned int p, unsigned int q>
struct generator_bits<lagged_fibonacci_01<RealType, w, p, q> >
{
static std::size_t value() { return w; }
};
}
#ifdef BOOST_RANDOM_DOXYGEN
namespace detail {
/**
* The specializations lagged_fibonacci607 ... lagged_fibonacci44497
* use well tested lags.
*
* See
*
* @blockquote
* "On the Periods of Generalized Fibonacci Recurrences", Richard P. Brent
* Computer Sciences Laboratory Australian National University, December 1992
* @endblockquote
*
* The lags used here can be found in
*
* @blockquote
* "Uniform random number generators for supercomputers", Richard Brent,
* Proc. of Fifth Australian Supercomputer Conference, Melbourne,
* Dec. 1992, pp. 704-706.
* @endblockquote
*/
struct lagged_fibonacci_doc {};
}
#endif
/** @copydoc boost::random::detail::lagged_fibonacci_doc */
typedef lagged_fibonacci_01_engine<double, 48, 607, 273> lagged_fibonacci607;
/** @copydoc boost::random::detail::lagged_fibonacci_doc */
typedef lagged_fibonacci_01_engine<double, 48, 1279, 418> lagged_fibonacci1279;
/** @copydoc boost::random::detail::lagged_fibonacci_doc */
typedef lagged_fibonacci_01_engine<double, 48, 2281, 1252> lagged_fibonacci2281;
/** @copydoc boost::random::detail::lagged_fibonacci_doc */
typedef lagged_fibonacci_01_engine<double, 48, 3217, 576> lagged_fibonacci3217;
/** @copydoc boost::random::detail::lagged_fibonacci_doc */
typedef lagged_fibonacci_01_engine<double, 48, 4423, 2098> lagged_fibonacci4423;
/** @copydoc boost::random::detail::lagged_fibonacci_doc */
typedef lagged_fibonacci_01_engine<double, 48, 9689, 5502> lagged_fibonacci9689;
/** @copydoc boost::random::detail::lagged_fibonacci_doc */
typedef lagged_fibonacci_01_engine<double, 48, 19937, 9842> lagged_fibonacci19937;
/** @copydoc boost::random::detail::lagged_fibonacci_doc */
typedef lagged_fibonacci_01_engine<double, 48, 23209, 13470> lagged_fibonacci23209;
/** @copydoc boost::random::detail::lagged_fibonacci_doc */
typedef lagged_fibonacci_01_engine<double, 48, 44497, 21034> lagged_fibonacci44497;
} // namespace random
using random::lagged_fibonacci607;
using random::lagged_fibonacci1279;
using random::lagged_fibonacci2281;
using random::lagged_fibonacci3217;
using random::lagged_fibonacci4423;
using random::lagged_fibonacci9689;
using random::lagged_fibonacci19937;
using random::lagged_fibonacci23209;
using random::lagged_fibonacci44497;
} // namespace boost
#endif // BOOST_RANDOM_LAGGED_FIBONACCI_HPP
@@ -0,0 +1,175 @@
/* boost random/laplace_distribution.hpp header file
*
* Copyright Steven Watanabe 2014
* 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_LAPLACE_DISTRIBUTION_HPP
#define BOOST_RANDOM_LAPLACE_DISTRIBUTION_HPP
#include <cassert>
#include <istream>
#include <iosfwd>
#include <boost/random/detail/operators.hpp>
#include <boost/random/exponential_distribution.hpp>
namespace boost {
namespace random {
/**
* The laplace distribution is a real-valued distribution with
* two parameters, mean and beta.
*
* It has \f$\displaystyle p(x) = \frac{e^-{\frac{|x-\mu|}{\beta}}}{2\beta}\f$.
*/
template<class RealType = double>
class laplace_distribution {
public:
typedef RealType result_type;
typedef RealType input_type;
class param_type {
public:
typedef laplace_distribution distribution_type;
/**
* Constructs a @c param_type from the "mean" and "beta" parameters
* of the distribution.
*/
explicit param_type(RealType mean_arg = RealType(0.0),
RealType beta_arg = RealType(1.0))
: _mean(mean_arg), _beta(beta_arg)
{}
/** Returns the "mean" parameter of the distribtuion. */
RealType mean() const { return _mean; }
/** Returns the "beta" parameter of the distribution. */
RealType beta() const { return _beta; }
/** Writes a @c param_type to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{ os << parm._mean << ' ' << parm._beta; return os; }
/** Reads a @c param_type from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{ is >> parm._mean >> std::ws >> parm._beta; return is; }
/** Returns true if the two sets of parameters are the same. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._mean == rhs._mean && lhs._beta == rhs._beta; }
/** Returns true if the two sets of parameters are the different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
RealType _mean;
RealType _beta;
};
/**
* Constructs an @c laplace_distribution from its "mean" and "beta" parameters.
*/
explicit laplace_distribution(RealType mean_arg = RealType(0.0),
RealType beta_arg = RealType(1.0))
: _mean(mean_arg), _beta(beta_arg)
{}
/** Constructs an @c laplace_distribution from its parameters. */
explicit laplace_distribution(const param_type& parm)
: _mean(parm.mean()), _beta(parm.beta())
{}
/**
* Returns a random variate distributed according to the
* laplace distribution.
*/
template<class URNG>
RealType operator()(URNG& urng) const
{
RealType exponential = exponential_distribution<RealType>()(urng);
if(uniform_01<RealType>()(urng) < 0.5)
exponential = -exponential;
return _mean + _beta * exponential;
}
/**
* Returns a random variate distributed accordint to the laplace
* distribution with parameters specified by @c param.
*/
template<class URNG>
RealType operator()(URNG& urng, const param_type& parm) const
{
return laplace_distribution(parm)(urng);
}
/** Returns the "mean" parameter of the distribution. */
RealType mean() const { return _mean; }
/** Returns the "beta" parameter of the distribution. */
RealType beta() const { return _beta; }
/** Returns the smallest value that the distribution can produce. */
RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return RealType(-std::numeric_limits<RealType>::infinity()); }
/** Returns the largest value that the distribution can produce. */
RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return RealType(std::numeric_limits<RealType>::infinity()); }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(_mean, _beta); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
_mean = parm.mean();
_beta = parm.beta();
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { }
/** Writes an @c laplace_distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, laplace_distribution, wd)
{
os << wd.param();
return os;
}
/** Reads an @c laplace_distribution from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, laplace_distribution, wd)
{
param_type parm;
if(is >> parm) {
wd.param(parm);
}
return is;
}
/**
* Returns true if the two instances of @c laplace_distribution will
* return identical sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(laplace_distribution, lhs, rhs)
{ return lhs._mean == rhs._mean && lhs._beta == rhs._beta; }
/**
* Returns true if the two instances of @c laplace_distribution will
* return different sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(laplace_distribution)
private:
RealType _mean;
RealType _beta;
};
} // namespace random
} // namespace boost
#endif // BOOST_RANDOM_LAPLACE_DISTRIBUTION_HPP
@@ -0,0 +1,466 @@
/* boost random/linear_congruential.hpp header file
*
* Copyright Jens Maurer 2000-2001
* 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$
*
* Revision history
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_LINEAR_CONGRUENTIAL_HPP
#define BOOST_RANDOM_LINEAR_CONGRUENTIAL_HPP
#include <iostream>
#include <stdexcept>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/limits.hpp>
#include <boost/static_assert.hpp>
#include <boost/integer/static_log2.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/const_mod.hpp>
#include <boost/random/detail/seed.hpp>
#include <boost/random/detail/seed_impl.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/random/detail/disable_warnings.hpp>
namespace boost {
namespace random {
/**
* Instantiations of class template linear_congruential_engine model a
* \pseudo_random_number_generator. Linear congruential pseudo-random
* number generators are described in:
*
* @blockquote
* "Mathematical methods in large-scale computing units", D. H. Lehmer,
* Proc. 2nd Symposium on Large-Scale Digital Calculating Machines,
* Harvard University Press, 1951, pp. 141-146
* @endblockquote
*
* Let x(n) denote the sequence of numbers returned by some pseudo-random
* number generator. Then for the linear congruential generator,
* x(n+1) := (a * x(n) + c) mod m. Parameters for the generator are
* x(0), a, c, m. The template parameter IntType shall denote an integral
* type. It must be large enough to hold values a, c, and m. The template
* parameters a and c must be smaller than m.
*
* Note: The quality of the generator crucially depends on the choice of
* the parameters. User code should use one of the sensibly parameterized
* generators such as minstd_rand instead.
*/
template<class IntType, IntType a, IntType c, IntType m>
class linear_congruential_engine
{
public:
typedef IntType result_type;
// Required for old Boost.Random concept
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
BOOST_STATIC_CONSTANT(IntType, multiplier = a);
BOOST_STATIC_CONSTANT(IntType, increment = c);
BOOST_STATIC_CONSTANT(IntType, modulus = m);
BOOST_STATIC_CONSTANT(IntType, default_seed = 1);
BOOST_STATIC_ASSERT(std::numeric_limits<IntType>::is_integer);
BOOST_STATIC_ASSERT(m == 0 || a < m);
BOOST_STATIC_ASSERT(m == 0 || c < m);
/**
* Constructs a @c linear_congruential_engine, using the default seed
*/
linear_congruential_engine() { seed(); }
/**
* Constructs a @c linear_congruential_engine, seeding it with @c x0.
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(linear_congruential_engine,
IntType, x0)
{ seed(x0); }
/**
* Constructs a @c linear_congruential_engine, seeding it with values
* produced by a call to @c seq.generate().
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(linear_congruential_engine,
SeedSeq, seq)
{ seed(seq); }
/**
* Constructs a @c linear_congruential_engine and seeds it
* with values taken from the itrator range [first, last)
* and adjusts first to point to the element after the last one
* used. If there are not enough elements, throws @c std::invalid_argument.
*
* first and last must be input iterators.
*/
template<class It>
linear_congruential_engine(It& first, It last)
{
seed(first, last);
}
// compiler-generated copy constructor and assignment operator are fine
/**
* Calls seed(default_seed)
*/
void seed() { seed(default_seed); }
/**
* If c mod m is zero and x0 mod m is zero, changes the current value of
* the generator to 1. Otherwise, changes it to x0 mod m. If c is zero,
* distinct seeds in the range [1,m) will leave the generator in distinct
* states. If c is not zero, the range is [0,m).
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(linear_congruential_engine, IntType, x0)
{
// wrap _x if it doesn't fit in the destination
if(modulus == 0) {
_x = x0;
} else {
_x = x0 % modulus;
}
// handle negative seeds
if(_x <= 0 && _x != 0) {
_x += modulus;
}
// adjust to the correct range
if(increment == 0 && _x == 0) {
_x = 1;
}
BOOST_ASSERT(_x >= (min)());
BOOST_ASSERT(_x <= (max)());
}
/**
* Seeds a @c linear_congruential_engine using values from a SeedSeq.
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(linear_congruential_engine, SeedSeq, seq)
{ seed(detail::seed_one_int<IntType, m>(seq)); }
/**
* seeds a @c linear_congruential_engine with values taken
* from the itrator range [first, last) and adjusts @c first to
* point to the element after the last one used. If there are
* not enough elements, throws @c std::invalid_argument.
*
* @c first and @c last must be input iterators.
*/
template<class It>
void seed(It& first, It last)
{ seed(detail::get_one_int<IntType, m>(first, last)); }
/**
* Returns the smallest value that the @c linear_congruential_engine
* can produce.
*/
static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return c == 0 ? 1 : 0; }
/**
* Returns the largest value that the @c linear_congruential_engine
* can produce.
*/
static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return modulus-1; }
/** Returns the next value of the @c linear_congruential_engine. */
IntType operator()()
{
_x = const_mod<IntType, m>::mult_add(a, _x, c);
return _x;
}
/** Fills a range with random values */
template<class Iter>
void generate(Iter first, Iter last)
{ detail::generate_from_int(*this, first, last); }
/** Advances the state of the generator by @c z. */
void discard(boost::uintmax_t z)
{
typedef const_mod<IntType, m> mod_type;
IntType b_inv = mod_type::invert(a-1);
IntType b_gcd = mod_type::mult(a-1, b_inv);
if(b_gcd == 1) {
IntType a_z = mod_type::pow(a, z);
_x = mod_type::mult_add(a_z, _x,
mod_type::mult(mod_type::mult(c, b_inv), a_z - 1));
} else {
// compute (a^z - 1)*c % (b_gcd * m) / (b / b_gcd) * inv(b / b_gcd)
// we're storing the intermediate result / b_gcd
IntType a_zm1_over_gcd = 0;
IntType a_km1_over_gcd = (a - 1) / b_gcd;
boost::uintmax_t exponent = z;
while(exponent != 0) {
if(exponent % 2 == 1) {
a_zm1_over_gcd =
mod_type::mult_add(
b_gcd,
mod_type::mult(a_zm1_over_gcd, a_km1_over_gcd),
mod_type::add(a_zm1_over_gcd, a_km1_over_gcd));
}
a_km1_over_gcd = mod_type::mult_add(
b_gcd,
mod_type::mult(a_km1_over_gcd, a_km1_over_gcd),
mod_type::add(a_km1_over_gcd, a_km1_over_gcd));
exponent /= 2;
}
IntType a_z = mod_type::mult_add(b_gcd, a_zm1_over_gcd, 1);
IntType num = mod_type::mult(c, a_zm1_over_gcd);
b_inv = mod_type::invert((a-1)/b_gcd);
_x = mod_type::mult_add(a_z, _x, mod_type::mult(b_inv, num));
}
}
friend bool operator==(const linear_congruential_engine& x,
const linear_congruential_engine& y)
{ return x._x == y._x; }
friend bool operator!=(const linear_congruential_engine& x,
const linear_congruential_engine& y)
{ return !(x == y); }
#if !defined(BOOST_RANDOM_NO_STREAM_OPERATORS)
/** Writes a @c linear_congruential_engine to a @c std::ostream. */
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os,
const linear_congruential_engine& lcg)
{
return os << lcg._x;
}
/** Reads a @c linear_congruential_engine from a @c std::istream. */
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is,
linear_congruential_engine& lcg)
{
lcg.read(is);
return is;
}
#endif
private:
/// \cond show_private
template<class CharT, class Traits>
void read(std::basic_istream<CharT, Traits>& is) {
IntType x;
if(is >> x) {
if(x >= (min)() && x <= (max)()) {
_x = x;
} else {
is.setstate(std::ios_base::failbit);
}
}
}
/// \endcond
IntType _x;
};
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
// A definition is required even for integral static constants
template<class IntType, IntType a, IntType c, IntType m>
const bool linear_congruential_engine<IntType, a, c, m>::has_fixed_range;
template<class IntType, IntType a, IntType c, IntType m>
const IntType linear_congruential_engine<IntType,a,c,m>::multiplier;
template<class IntType, IntType a, IntType c, IntType m>
const IntType linear_congruential_engine<IntType,a,c,m>::increment;
template<class IntType, IntType a, IntType c, IntType m>
const IntType linear_congruential_engine<IntType,a,c,m>::modulus;
template<class IntType, IntType a, IntType c, IntType m>
const IntType linear_congruential_engine<IntType,a,c,m>::default_seed;
#endif
/// \cond show_deprecated
// provided for backwards compatibility
template<class IntType, IntType a, IntType c, IntType m, IntType val = 0>
class linear_congruential : public linear_congruential_engine<IntType, a, c, m>
{
typedef linear_congruential_engine<IntType, a, c, m> base_type;
public:
linear_congruential(IntType x0 = 1) : base_type(x0) {}
template<class It>
linear_congruential(It& first, It last) : base_type(first, last) {}
};
/// \endcond
/**
* The specialization \minstd_rand0 was originally suggested in
*
* @blockquote
* A pseudo-random number generator for the System/360, P.A. Lewis,
* A.S. Goodman, J.M. Miller, IBM Systems Journal, Vol. 8, No. 2,
* 1969, pp. 136-146
* @endblockquote
*
* It is examined more closely together with \minstd_rand in
*
* @blockquote
* "Random Number Generators: Good ones are hard to find",
* Stephen K. Park and Keith W. Miller, Communications of
* the ACM, Vol. 31, No. 10, October 1988, pp. 1192-1201
* @endblockquote
*/
typedef linear_congruential_engine<uint32_t, 16807, 0, 2147483647> minstd_rand0;
/** The specialization \minstd_rand was suggested in
*
* @blockquote
* "Random Number Generators: Good ones are hard to find",
* Stephen K. Park and Keith W. Miller, Communications of
* the ACM, Vol. 31, No. 10, October 1988, pp. 1192-1201
* @endblockquote
*/
typedef linear_congruential_engine<uint32_t, 48271, 0, 2147483647> minstd_rand;
#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T)
/**
* Class @c rand48 models a \pseudo_random_number_generator. It uses
* the linear congruential algorithm with the parameters a = 0x5DEECE66D,
* c = 0xB, m = 2**48. It delivers identical results to the @c lrand48()
* function available on some systems (assuming lcong48 has not been called).
*
* It is only available on systems where @c uint64_t is provided as an
* integral type, so that for example static in-class constants and/or
* enum definitions with large @c uint64_t numbers work.
*/
class rand48
{
public:
typedef boost::uint32_t result_type;
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
/**
* Returns the smallest value that the generator can produce
*/
static uint32_t min BOOST_PREVENT_MACRO_SUBSTITUTION () { return 0; }
/**
* Returns the largest value that the generator can produce
*/
static uint32_t max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return 0x7FFFFFFF; }
/** Seeds the generator with the default seed. */
rand48() : lcf(cnv(static_cast<uint32_t>(1))) {}
/**
* Constructs a \rand48 generator with x(0) := (x0 << 16) | 0x330e.
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(rand48, result_type, x0)
{ seed(x0); }
/**
* Seeds the generator with values produced by @c seq.generate().
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(rand48, SeedSeq, seq)
{ seed(seq); }
/**
* Seeds the generator using values from an iterator range,
* and updates first to point one past the last value consumed.
*/
template<class It> rand48(It& first, It last) : lcf(first, last) { }
// compiler-generated copy ctor and assignment operator are fine
/** Seeds the generator with the default seed. */
void seed() { seed(static_cast<uint32_t>(1)); }
/**
* Changes the current value x(n) of the generator to (x0 << 16) | 0x330e.
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(rand48, result_type, x0)
{ lcf.seed(cnv(x0)); }
/**
* Seeds the generator using values from an iterator range,
* and updates first to point one past the last value consumed.
*/
template<class It> void seed(It& first, It last) { lcf.seed(first,last); }
/**
* Seeds the generator with values produced by @c seq.generate().
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(rand48, SeedSeq, seq)
{ lcf.seed(seq); }
/** Returns the next value of the generator. */
uint32_t operator()() { return static_cast<uint32_t>(lcf() >> 17); }
/** Advances the state of the generator by @c z. */
void discard(boost::uintmax_t z) { lcf.discard(z); }
/** Fills a range with random values */
template<class Iter>
void generate(Iter first, Iter last)
{
for(; first != last; ++first) {
*first = (*this)();
}
}
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
/** Writes a @c rand48 to a @c std::ostream. */
template<class CharT,class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os, const rand48& r)
{ os << r.lcf; return os; }
/** Reads a @c rand48 from a @c std::istream. */
template<class CharT,class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is, rand48& r)
{ is >> r.lcf; return is; }
#endif
/**
* Returns true if the two generators will produce identical
* sequences of values.
*/
friend bool operator==(const rand48& x, const rand48& y)
{ return x.lcf == y.lcf; }
/**
* Returns true if the two generators will produce different
* sequences of values.
*/
friend bool operator!=(const rand48& x, const rand48& y)
{ return !(x == y); }
private:
/// \cond show_private
typedef random::linear_congruential_engine<uint64_t,
// xxxxULL is not portable
uint64_t(0xDEECE66DUL) | (uint64_t(0x5) << 32),
0xB, uint64_t(1)<<48> lcf_t;
lcf_t lcf;
static boost::uint64_t cnv(boost::uint32_t x)
{ return (static_cast<uint64_t>(x) << 16) | 0x330e; }
/// \endcond
};
#endif /* !BOOST_NO_INT64_T && !BOOST_NO_INTEGRAL_INT64_T */
} // namespace random
using random::minstd_rand0;
using random::minstd_rand;
using random::rand48;
} // namespace boost
#include <boost/random/detail/enable_warnings.hpp>
#endif // BOOST_RANDOM_LINEAR_CONGRUENTIAL_HPP
@@ -0,0 +1,217 @@
/* boost random/linear_feedback_shift.hpp header file
*
* Copyright Jens Maurer 2002
* Copyright Steven Watanabe 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_LINEAR_FEEDBACK_SHIFT_HPP
#define BOOST_RANDOM_LINEAR_FEEDBACK_SHIFT_HPP
#include <iosfwd>
#include <stdexcept>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/static_assert.hpp>
#include <boost/integer/integer_mask.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>
namespace boost {
namespace random {
/**
* Instatiations of @c linear_feedback_shift model a
* \pseudo_random_number_generator. It was originally
* proposed in
*
* @blockquote
* "Random numbers generated by linear recurrence modulo two.",
* Tausworthe, R. C.(1965), Mathematics of Computation 19, 201-209.
* @endblockquote
*/
template<class UIntType, int w, int k, int q, int s>
class linear_feedback_shift_engine
{
public:
typedef UIntType result_type;
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
BOOST_STATIC_CONSTANT(int, word_size = w);
BOOST_STATIC_CONSTANT(int, exponent1 = k);
BOOST_STATIC_CONSTANT(int, exponent2 = q);
BOOST_STATIC_CONSTANT(int, step_size = s);
BOOST_STATIC_CONSTANT(UIntType, default_seed = 341);
/** Returns the smallest value that the generator can produce. */
static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return 0; }
/** Returns the largest value that the generator can produce. */
static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return wordmask(); }
BOOST_STATIC_ASSERT(w > 0);
BOOST_STATIC_ASSERT(q > 0);
BOOST_STATIC_ASSERT(k < w);
BOOST_STATIC_ASSERT(0 < 2*q && 2*q < k);
BOOST_STATIC_ASSERT(0 < s && s <= k-q);
/** Constructs a @c linear_feedback_shift_engine, using the default seed. */
linear_feedback_shift_engine() { seed(); }
/** Constructs a @c linear_feedback_shift_engine, seeding it with s0. */
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(linear_feedback_shift_engine,
UIntType, s0)
{ seed(s0); }
/** Constructs a @c linear_feedback_shift_engine, seeding it with seq. */
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(linear_feedback_shift_engine,
SeedSeq, seq)
{ seed(seq); }
/**
* Constructs a @c linear_feedback_shift_engine, seeding it with
* values from the range [first, last).
*/
template<class It> linear_feedback_shift_engine(It& first, It last)
{ seed(first, last); }
/** Seeds a @c linear_feedback_shift_engine with the default seed. */
void seed() { seed(default_seed); }
/** Seeds a @c linear_feedback_shift_engine with @c s0. */
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(linear_feedback_shift_engine,
UIntType, s0)
{
value = s0 & wordmask();
if(value < (1 << (w-k))) {
value += 1 << (w-k);
}
}
/**
* Seeds a @c linear_feedback_shift_engine with values
* produced by @c seq.generate().
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(linear_feedback_shift_engine,
SeedSeq, seq)
{ seed(detail::seed_one_int<UIntType, (UIntType(2) << (w - 1))>(seq)); }
/**
* Seeds a @c linear_feedback_shift_engine with values
* from the range [first, last).
*/
template<class It> void seed(It& first, It last)
{
seed(detail::get_one_int<UIntType, (UIntType(2) << (w - 1))>(first, last));
}
/** Returns the next value of the generator. */
result_type operator()()
{
const UIntType b = (((value << q) ^ value) & wordmask()) >> (k-s);
const UIntType mask = (wordmask() << (w-k)) & wordmask();
value = ((value & mask) << s) ^ b;
return value;
}
/** Fills a range with random values */
template<class Iter>
void generate(Iter first, Iter last)
{ detail::generate_from_int(*this, first, last); }
/** Advances the state of the generator by @c z. */
void discard(boost::uintmax_t z)
{
for(boost::uintmax_t j = 0; j < z; ++j) {
(*this)();
}
}
/**
* Writes the textual representation of the generator to a @c std::ostream.
*/
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, linear_feedback_shift_engine, x)
{
os << x.value;
return os;
}
/**
* Reads the textual representation of the generator from a @c std::istream.
*/
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, linear_feedback_shift_engine, x)
{
is >> x.value;
return is;
}
/**
* Returns true if the two generators will produce identical
* sequences of outputs.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(linear_feedback_shift_engine, x, y)
{ return x.value == y.value; }
/**
* Returns true if the two generators will produce different
* sequences of outputs.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(linear_feedback_shift_engine)
private:
/// \cond show_private
static UIntType wordmask() { return boost::low_bits_mask_t<w>::sig_bits; }
/// \endcond
UIntType value;
};
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
// A definition is required even for integral static constants
template<class UIntType, int w, int k, int q, int s>
const bool linear_feedback_shift_engine<UIntType, w, k, q, s>::has_fixed_range;
template<class UIntType, int w, int k, int q, int s>
const int linear_feedback_shift_engine<UIntType, w, k, q, s>::word_size;
template<class UIntType, int w, int k, int q, int s>
const int linear_feedback_shift_engine<UIntType, w, k, q, s>::exponent1;
template<class UIntType, int w, int k, int q, int s>
const int linear_feedback_shift_engine<UIntType, w, k, q, s>::exponent2;
template<class UIntType, int w, int k, int q, int s>
const int linear_feedback_shift_engine<UIntType, w, k, q, s>::step_size;
template<class UIntType, int w, int k, int q, int s>
const UIntType linear_feedback_shift_engine<UIntType, w, k, q, s>::default_seed;
#endif
/// \cond show_deprecated
/** Provided for backwards compatibility. */
template<class UIntType, int w, int k, int q, int s, UIntType v = 0>
class linear_feedback_shift :
public linear_feedback_shift_engine<UIntType, w, k, q, s>
{
typedef linear_feedback_shift_engine<UIntType, w, k, q, s> base_type;
public:
linear_feedback_shift() {}
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(linear_feedback_shift,
SeedSeq, seq)
{ seed(seq); }
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(linear_feedback_shift,
UIntType, val)
{ seed(val); }
template<class It>
linear_feedback_shift(It& first, It last) : base_type(first, last) {}
};
/// \endcond
} // namespace random
} // namespace boost
#endif // BOOST_RANDOM_LINEAR_FEEDBACK_SHIFT_HPP
@@ -0,0 +1,254 @@
/* boost random/lognormal_distribution.hpp header file
*
* Copyright Jens Maurer 2000-2001
* Copyright Steven Watanabe 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$
*
* Revision history
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_LOGNORMAL_DISTRIBUTION_HPP
#define BOOST_RANDOM_LOGNORMAL_DISTRIBUTION_HPP
#include <boost/config/no_tr1/cmath.hpp> // std::exp, std::sqrt
#include <cassert>
#include <iosfwd>
#include <istream>
#include <boost/limits.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/normal_distribution.hpp>
namespace boost {
namespace random {
/**
* Instantiations of class template lognormal_distribution model a
* \random_distribution. Such a distribution produces random numbers
* with \f$\displaystyle p(x) = \frac{1}{x s \sqrt{2\pi}} e^{\frac{-\left(\log(x)-m\right)^2}{2s^2}}\f$
* for x > 0.
*
* @xmlwarning
* This distribution has been updated to match the C++ standard.
* Its behavior has changed from the original
* boost::lognormal_distribution. A backwards compatible
* version is provided in namespace boost.
* @endxmlwarning
*/
template<class RealType = double>
class lognormal_distribution
{
public:
typedef typename normal_distribution<RealType>::input_type input_type;
typedef RealType result_type;
class param_type
{
public:
typedef lognormal_distribution distribution_type;
/** Constructs the parameters of a lognormal_distribution. */
explicit param_type(RealType m_arg = RealType(0.0),
RealType s_arg = RealType(1.0))
: _m(m_arg), _s(s_arg) {}
/** Returns the "m" parameter of the distribution. */
RealType m() const { return _m; }
/** Returns the "s" parameter of the distribution. */
RealType s() const { return _s; }
/** Writes the parameters to a std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{
os << parm._m << " " << parm._s;
return os;
}
/** Reads the parameters from a std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{
is >> parm._m >> std::ws >> parm._s;
return is;
}
/** Returns true if the two sets of parameters are equal. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._m == rhs._m && lhs._s == rhs._s; }
/** Returns true if the two sets of parameters are different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
RealType _m;
RealType _s;
};
/**
* Constructs a lognormal_distribution. @c m and @c s are the
* parameters of the distribution.
*/
explicit lognormal_distribution(RealType m_arg = RealType(0.0),
RealType s_arg = RealType(1.0))
: _normal(m_arg, s_arg) {}
/**
* Constructs a lognormal_distribution from its parameters.
*/
explicit lognormal_distribution(const param_type& parm)
: _normal(parm.m(), parm.s()) {}
// compiler-generated copy ctor and assignment operator are fine
/** Returns the m parameter of the distribution. */
RealType m() const { return _normal.mean(); }
/** Returns the s parameter of the distribution. */
RealType s() const { return _normal.sigma(); }
/** Returns the smallest value that the distribution can produce. */
RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return RealType(0); }
/** Returns the largest value that the distribution can produce. */
RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return (std::numeric_limits<RealType>::infinity)(); }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(m(), s()); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
typedef normal_distribution<RealType> normal_type;
typename normal_type::param_type normal_param(parm.m(), parm.s());
_normal.param(normal_param);
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { _normal.reset(); }
/**
* Returns a random variate distributed according to the
* lognormal distribution.
*/
template<class Engine>
result_type operator()(Engine& eng)
{
using std::exp;
return exp(_normal(eng));
}
/**
* Returns a random variate distributed according to the
* lognormal distribution with parameters specified by param.
*/
template<class Engine>
result_type operator()(Engine& eng, const param_type& parm)
{ return lognormal_distribution(parm)(eng); }
/** Writes the distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, lognormal_distribution, ld)
{
os << ld._normal;
return os;
}
/** Reads the distribution from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, lognormal_distribution, ld)
{
is >> ld._normal;
return is;
}
/**
* Returns true if the two distributions will produce identical
* sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(lognormal_distribution, lhs, rhs)
{ return lhs._normal == rhs._normal; }
/**
* Returns true if the two distributions may produce different
* sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(lognormal_distribution)
private:
normal_distribution<result_type> _normal;
};
} // namespace random
/// \cond show_deprecated
/**
* Provided for backwards compatibility. This class is
* deprecated. It provides the old behavior of lognormal_distribution with
* \f$\displaystyle p(x) = \frac{1}{x \sigma_N \sqrt{2\pi}} e^{\frac{-\left(\log(x)-\mu_N\right)^2}{2\sigma_N^2}}\f$
* for x > 0, where \f$\displaystyle \mu_N = \log\left(\frac{\mu^2}{\sqrt{\sigma^2 + \mu^2}}\right)\f$ and
* \f$\displaystyle \sigma_N = \sqrt{\log\left(1 + \frac{\sigma^2}{\mu^2}\right)}\f$.
*/
template<class RealType = double>
class lognormal_distribution
{
public:
typedef typename normal_distribution<RealType>::input_type input_type;
typedef RealType result_type;
lognormal_distribution(RealType mean_arg = RealType(1.0),
RealType sigma_arg = RealType(1.0))
: _mean(mean_arg), _sigma(sigma_arg)
{
init();
}
RealType mean() const { return _mean; }
RealType sigma() const { return _sigma; }
void reset() { _normal.reset(); }
template<class Engine>
RealType operator()(Engine& eng)
{
using std::exp;
return exp(_normal(eng) * _nsigma + _nmean);
}
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, lognormal_distribution, ld)
{
os << ld._normal << " " << ld._mean << " " << ld._sigma;
return os;
}
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, lognormal_distribution, ld)
{
is >> ld._normal >> std::ws >> ld._mean >> std::ws >> ld._sigma;
ld.init();
return is;
}
private:
/// \cond show_private
void init()
{
using std::log;
using std::sqrt;
_nmean = log(_mean*_mean/sqrt(_sigma*_sigma + _mean*_mean));
_nsigma = sqrt(log(_sigma*_sigma/_mean/_mean+result_type(1)));
}
RealType _mean;
RealType _sigma;
RealType _nmean;
RealType _nsigma;
normal_distribution<RealType> _normal;
/// \endcond
};
/// \endcond
} // namespace boost
#endif // BOOST_RANDOM_LOGNORMAL_DISTRIBUTION_HPP
@@ -0,0 +1,682 @@
/* boost random/mersenne_twister.hpp header file
*
* Copyright Jens Maurer 2000-2001
* Copyright Steven Watanabe 2010
* 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$
*
* Revision history
* 2013-10-14 fixed some warnings with Wshadow (mgaunard)
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_MERSENNE_TWISTER_HPP
#define BOOST_RANDOM_MERSENNE_TWISTER_HPP
#include <iosfwd>
#include <istream>
#include <stdexcept>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/integer/integer_mask.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/ptr_helper.hpp>
#include <boost/random/detail/seed.hpp>
#include <boost/random/detail/seed_impl.hpp>
#include <boost/random/detail/generator_seed_seq.hpp>
#include <boost/random/detail/polynomial.hpp>
#include <boost/random/detail/disable_warnings.hpp>
namespace boost {
namespace random {
/**
* Instantiations of class template mersenne_twister_engine model a
* \pseudo_random_number_generator. It uses the algorithm described in
*
* @blockquote
* "Mersenne Twister: A 623-dimensionally equidistributed uniform
* pseudo-random number generator", Makoto Matsumoto and Takuji Nishimura,
* ACM Transactions on Modeling and Computer Simulation: Special Issue on
* Uniform Random Number Generation, Vol. 8, No. 1, January 1998, pp. 3-30.
* @endblockquote
*
* @xmlnote
* The boost variant has been implemented from scratch and does not
* derive from or use mt19937.c provided on the above WWW site. However, it
* was verified that both produce identical output.
* @endxmlnote
*
* The seeding from an integer was changed in April 2005 to address a
* <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html">weakness</a>.
*
* The quality of the generator crucially depends on the choice of the
* parameters. User code should employ one of the sensibly parameterized
* generators such as \mt19937 instead.
*
* The generator requires considerable amounts of memory for the storage of
* its state array. For example, \mt11213b requires about 1408 bytes and
* \mt19937 requires about 2496 bytes.
*/
template<class UIntType,
std::size_t w, std::size_t n, std::size_t m, std::size_t r,
UIntType a, std::size_t u, UIntType d, std::size_t s,
UIntType b, std::size_t t,
UIntType c, std::size_t l, UIntType f>
class mersenne_twister_engine
{
public:
typedef UIntType result_type;
BOOST_STATIC_CONSTANT(std::size_t, word_size = w);
BOOST_STATIC_CONSTANT(std::size_t, state_size = n);
BOOST_STATIC_CONSTANT(std::size_t, shift_size = m);
BOOST_STATIC_CONSTANT(std::size_t, mask_bits = r);
BOOST_STATIC_CONSTANT(UIntType, xor_mask = a);
BOOST_STATIC_CONSTANT(std::size_t, tempering_u = u);
BOOST_STATIC_CONSTANT(UIntType, tempering_d = d);
BOOST_STATIC_CONSTANT(std::size_t, tempering_s = s);
BOOST_STATIC_CONSTANT(UIntType, tempering_b = b);
BOOST_STATIC_CONSTANT(std::size_t, tempering_t = t);
BOOST_STATIC_CONSTANT(UIntType, tempering_c = c);
BOOST_STATIC_CONSTANT(std::size_t, tempering_l = l);
BOOST_STATIC_CONSTANT(UIntType, initialization_multiplier = f);
BOOST_STATIC_CONSTANT(UIntType, default_seed = 5489u);
// backwards compatibility
BOOST_STATIC_CONSTANT(UIntType, parameter_a = a);
BOOST_STATIC_CONSTANT(std::size_t, output_u = u);
BOOST_STATIC_CONSTANT(std::size_t, output_s = s);
BOOST_STATIC_CONSTANT(UIntType, output_b = b);
BOOST_STATIC_CONSTANT(std::size_t, output_t = t);
BOOST_STATIC_CONSTANT(UIntType, output_c = c);
BOOST_STATIC_CONSTANT(std::size_t, output_l = l);
// old Boost.Random concept requirements
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
/**
* Constructs a @c mersenne_twister_engine and calls @c seed().
*/
mersenne_twister_engine() { seed(); }
/**
* Constructs a @c mersenne_twister_engine and calls @c seed(value).
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(mersenne_twister_engine,
UIntType, value)
{ seed(value); }
template<class It> mersenne_twister_engine(It& first, It last)
{ seed(first,last); }
/**
* Constructs a mersenne_twister_engine and calls @c seed(gen).
*
* @xmlnote
* The copy constructor will always be preferred over
* the templated constructor.
* @endxmlnote
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(mersenne_twister_engine,
SeedSeq, seq)
{ seed(seq); }
// compiler-generated copy ctor and assignment operator are fine
/** Calls @c seed(default_seed). */
void seed() { seed(default_seed); }
/**
* Sets the state x(0) to v mod 2w. Then, iteratively,
* sets x(i) to
* (i + f * (x(i-1) xor (x(i-1) rshift w-2))) mod 2<sup>w</sup>
* for i = 1 .. n-1. x(n) is the first value to be returned by operator().
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(mersenne_twister_engine, UIntType, value)
{
// New seeding algorithm from
// http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html
// In the previous versions, MSBs of the seed affected only MSBs of the
// state x[].
const UIntType mask = (max)();
x[0] = value & mask;
for (i = 1; i < n; i++) {
// See Knuth "The Art of Computer Programming"
// Vol. 2, 3rd ed., page 106
x[i] = (f * (x[i-1] ^ (x[i-1] >> (w-2))) + i) & mask;
}
normalize_state();
}
/**
* Seeds a mersenne_twister_engine using values produced by seq.generate().
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(mersenne_twister_engine, SeeqSeq, seq)
{
detail::seed_array_int<w>(seq, x);
i = n;
normalize_state();
}
/** Sets the state of the generator using values from an iterator range. */
template<class It>
void seed(It& first, It last)
{
detail::fill_array_int<w>(first, last, x);
i = n;
normalize_state();
}
/** Returns the smallest value that the generator can produce. */
static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return 0; }
/** Returns the largest value that the generator can produce. */
static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return boost::low_bits_mask_t<w>::sig_bits; }
/** Produces the next value of the generator. */
result_type operator()();
/** Fills a range with random values */
template<class Iter>
void generate(Iter first, Iter last)
{ detail::generate_from_int(*this, first, last); }
/**
* Advances the state of the generator by @c z steps. Equivalent to
*
* @code
* for(unsigned long long i = 0; i < z; ++i) {
* gen();
* }
* @endcode
*/
void discard(boost::uintmax_t z)
{
#ifndef BOOST_RANDOM_MERSENNE_TWISTER_DISCARD_THRESHOLD
#define BOOST_RANDOM_MERSENNE_TWISTER_DISCARD_THRESHOLD 10000000
#endif
if(z > BOOST_RANDOM_MERSENNE_TWISTER_DISCARD_THRESHOLD) {
discard_many(z);
} else {
for(boost::uintmax_t j = 0; j < z; ++j) {
(*this)();
}
}
}
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
/** Writes a mersenne_twister_engine to a @c std::ostream */
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os,
const mersenne_twister_engine& mt)
{
mt.print(os);
return os;
}
/** Reads a mersenne_twister_engine from a @c std::istream */
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is,
mersenne_twister_engine& mt)
{
for(std::size_t j = 0; j < mt.state_size; ++j)
is >> mt.x[j] >> std::ws;
// MSVC (up to 7.1) and Borland (up to 5.64) don't handle the template
// value parameter "n" available from the class template scope, so use
// the static constant with the same value
mt.i = mt.state_size;
return is;
}
#endif
/**
* Returns true if the two generators are in the same state,
* and will thus produce identical sequences.
*/
friend bool operator==(const mersenne_twister_engine& x_,
const mersenne_twister_engine& y_)
{
if(x_.i < y_.i) return x_.equal_imp(y_);
else return y_.equal_imp(x_);
}
/**
* Returns true if the two generators are in different states.
*/
friend bool operator!=(const mersenne_twister_engine& x_,
const mersenne_twister_engine& y_)
{ return !(x_ == y_); }
private:
/// \cond show_private
void twist();
/**
* Does the work of operator==. This is in a member function
* for portability. Some compilers, such as msvc 7.1 and
* Sun CC 5.10 can't access template parameters or static
* members of the class from inline friend functions.
*
* requires i <= other.i
*/
bool equal_imp(const mersenne_twister_engine& other) const
{
UIntType back[n];
std::size_t offset = other.i - i;
for(std::size_t j = 0; j + offset < n; ++j)
if(x[j] != other.x[j+offset])
return false;
rewind(&back[n-1], offset);
for(std::size_t j = 0; j < offset; ++j)
if(back[j + n - offset] != other.x[j])
return false;
return true;
}
/**
* Does the work of operator<<. This is in a member function
* for portability.
*/
template<class CharT, class Traits>
void print(std::basic_ostream<CharT, Traits>& os) const
{
UIntType data[n];
for(std::size_t j = 0; j < i; ++j) {
data[j + n - i] = x[j];
}
if(i != n) {
rewind(&data[n - i - 1], n - i);
}
os << data[0];
for(std::size_t j = 1; j < n; ++j) {
os << ' ' << data[j];
}
}
/**
* Copies z elements of the state preceding x[0] into
* the array whose last element is last.
*/
void rewind(UIntType* last, std::size_t z) const
{
const UIntType upper_mask = (~static_cast<UIntType>(0)) << r;
const UIntType lower_mask = ~upper_mask;
UIntType y0 = x[m-1] ^ x[n-1];
if(y0 & (static_cast<UIntType>(1) << (w-1))) {
y0 = ((y0 ^ a) << 1) | 1;
} else {
y0 = y0 << 1;
}
for(std::size_t sz = 0; sz < z; ++sz) {
UIntType y1 =
rewind_find(last, sz, m-1) ^ rewind_find(last, sz, n-1);
if(y1 & (static_cast<UIntType>(1) << (w-1))) {
y1 = ((y1 ^ a) << 1) | 1;
} else {
y1 = y1 << 1;
}
*(last - sz) = (y0 & upper_mask) | (y1 & lower_mask);
y0 = y1;
}
}
/**
* Converts an arbitrary array into a valid generator state.
* First we normalize x[0], so that it contains the same
* value we would get by running the generator forwards
* and then in reverse. (The low order r bits are redundant).
* Then, if the state consists of all zeros, we set the
* high order bit of x[0] to 1. This function only needs to
* be called by seed, since the state transform preserves
* this relationship.
*/
void normalize_state()
{
const UIntType upper_mask = (~static_cast<UIntType>(0)) << r;
const UIntType lower_mask = ~upper_mask;
UIntType y0 = x[m-1] ^ x[n-1];
if(y0 & (static_cast<UIntType>(1) << (w-1))) {
y0 = ((y0 ^ a) << 1) | 1;
} else {
y0 = y0 << 1;
}
x[0] = (x[0] & upper_mask) | (y0 & lower_mask);
// fix up the state if it's all zeroes.
for(std::size_t j = 0; j < n; ++j) {
if(x[j] != 0) return;
}
x[0] = static_cast<UIntType>(1) << (w-1);
}
/**
* Given a pointer to the last element of the rewind array,
* and the current size of the rewind array, finds an element
* relative to the next available slot in the rewind array.
*/
UIntType
rewind_find(UIntType* last, std::size_t size, std::size_t j) const
{
std::size_t index = (j + n - size + n - 1) % n;
if(index < n - size) {
return x[index];
} else {
return *(last - (n - 1 - index));
}
}
/**
* Optimized algorithm for large jumps.
*
* Hiroshi Haramoto, Makoto Matsumoto, and Pierre L'Ecuyer. 2008.
* A Fast Jump Ahead Algorithm for Linear Recurrences in a Polynomial
* Space. In Proceedings of the 5th international conference on
* Sequences and Their Applications (SETA '08).
* DOI=10.1007/978-3-540-85912-3_26
*/
void discard_many(boost::uintmax_t z)
{
// Compute the minimal polynomial, phi(t)
// This depends only on the transition function,
// which is constant. The characteristic
// polynomial is the same as the minimal
// polynomial for a maximum period generator
// (which should be all specializations of
// mersenne_twister.) Even if it weren't,
// the characteristic polynomial is guaranteed
// to be a multiple of the minimal polynomial,
// which is good enough.
detail::polynomial phi = get_characteristic_polynomial();
// calculate g(t) = t^z % phi(t)
detail::polynomial g = mod_pow_x(z, phi);
// h(s_0, t) = \sum_{i=0}^{2k-1}o(s_i)t^{2k-i-1}
detail::polynomial h;
const std::size_t num_bits = w*n - r;
for(std::size_t j = 0; j < num_bits * 2; ++j) {
// Yes, we're advancing the generator state
// here, but it doesn't matter because
// we're going to overwrite it completely
// in reconstruct_state.
if(i >= n) twist();
h[2*num_bits - j - 1] = x[i++] & UIntType(1);
}
// g(t)h(s_0, t)
detail::polynomial gh = g * h;
detail::polynomial result;
for(std::size_t j = 0; j <= num_bits; ++j) {
result[j] = gh[2*num_bits - j - 1];
}
reconstruct_state(result);
}
static detail::polynomial get_characteristic_polynomial()
{
const std::size_t num_bits = w*n - r;
detail::polynomial helper;
helper[num_bits - 1] = 1;
mersenne_twister_engine tmp;
tmp.reconstruct_state(helper);
// Skip the first num_bits elements, since we
// already know what they are.
for(std::size_t j = 0; j < num_bits; ++j) {
if(tmp.i >= n) tmp.twist();
if(j == num_bits - 1)
assert((tmp.x[tmp.i] & 1) == 1);
else
assert((tmp.x[tmp.i] & 1) == 0);
++tmp.i;
}
detail::polynomial phi;
phi[num_bits] = 1;
detail::polynomial next_bits = tmp.as_polynomial(num_bits);
for(std::size_t j = 0; j < num_bits; ++j) {
int val = next_bits[j] ^ phi[num_bits-j-1];
phi[num_bits-j-1] = val;
if(val) {
for(std::size_t k = j + 1; k < num_bits; ++k) {
phi[num_bits-k-1] ^= next_bits[k-j-1];
}
}
}
return phi;
}
detail::polynomial as_polynomial(std::size_t size) {
detail::polynomial result;
for(std::size_t j = 0; j < size; ++j) {
if(i >= n) twist();
result[j] = x[i++] & UIntType(1);
}
return result;
}
void reconstruct_state(const detail::polynomial& p)
{
const UIntType upper_mask = (~static_cast<UIntType>(0)) << r;
const UIntType lower_mask = ~upper_mask;
const std::size_t num_bits = w*n - r;
for(std::size_t j = num_bits - n + 1; j <= num_bits; ++j)
x[j % n] = p[j];
UIntType y0 = 0;
for(std::size_t j = num_bits + 1; j >= n - 1; --j) {
UIntType y1 = x[j % n] ^ x[(j + m) % n];
if(p[j - n + 1])
y1 = (y1 ^ a) << UIntType(1) | UIntType(1);
else
y1 = y1 << UIntType(1);
x[(j + 1) % n] = (y0 & upper_mask) | (y1 & lower_mask);
y0 = y1;
}
i = 0;
}
/// \endcond
// state representation: next output is o(x(i))
// x[0] ... x[k] x[k+1] ... x[n-1] represents
// x(i-k) ... x(i) x(i+1) ... x(i-k+n-1)
UIntType x[n];
std::size_t i;
};
/// \cond show_private
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
// A definition is required even for integral static constants
#define BOOST_RANDOM_MT_DEFINE_CONSTANT(type, name) \
template<class UIntType, std::size_t w, std::size_t n, std::size_t m, \
std::size_t r, UIntType a, std::size_t u, UIntType d, std::size_t s, \
UIntType b, std::size_t t, UIntType c, std::size_t l, UIntType f> \
const type mersenne_twister_engine<UIntType,w,n,m,r,a,u,d,s,b,t,c,l,f>::name
BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, word_size);
BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, state_size);
BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, shift_size);
BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, mask_bits);
BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, xor_mask);
BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, tempering_u);
BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, tempering_d);
BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, tempering_s);
BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, tempering_b);
BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, tempering_t);
BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, tempering_c);
BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, tempering_l);
BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, initialization_multiplier);
BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, default_seed);
BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, parameter_a);
BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, output_u );
BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, output_s);
BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, output_b);
BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, output_t);
BOOST_RANDOM_MT_DEFINE_CONSTANT(UIntType, output_c);
BOOST_RANDOM_MT_DEFINE_CONSTANT(std::size_t, output_l);
BOOST_RANDOM_MT_DEFINE_CONSTANT(bool, has_fixed_range);
#undef BOOST_RANDOM_MT_DEFINE_CONSTANT
#endif
template<class UIntType,
std::size_t w, std::size_t n, std::size_t m, std::size_t r,
UIntType a, std::size_t u, UIntType d, std::size_t s,
UIntType b, std::size_t t,
UIntType c, std::size_t l, UIntType f>
void
mersenne_twister_engine<UIntType,w,n,m,r,a,u,d,s,b,t,c,l,f>::twist()
{
const UIntType upper_mask = (~static_cast<UIntType>(0)) << r;
const UIntType lower_mask = ~upper_mask;
const std::size_t unroll_factor = 6;
const std::size_t unroll_extra1 = (n-m) % unroll_factor;
const std::size_t unroll_extra2 = (m-1) % unroll_factor;
// split loop to avoid costly modulo operations
{ // extra scope for MSVC brokenness w.r.t. for scope
for(std::size_t j = 0; j < n-m-unroll_extra1; j++) {
UIntType y = (x[j] & upper_mask) | (x[j+1] & lower_mask);
x[j] = x[j+m] ^ (y >> 1) ^ ((x[j+1]&1) * a);
}
}
{
for(std::size_t j = n-m-unroll_extra1; j < n-m; j++) {
UIntType y = (x[j] & upper_mask) | (x[j+1] & lower_mask);
x[j] = x[j+m] ^ (y >> 1) ^ ((x[j+1]&1) * a);
}
}
{
for(std::size_t j = n-m; j < n-1-unroll_extra2; j++) {
UIntType y = (x[j] & upper_mask) | (x[j+1] & lower_mask);
x[j] = x[j-(n-m)] ^ (y >> 1) ^ ((x[j+1]&1) * a);
}
}
{
for(std::size_t j = n-1-unroll_extra2; j < n-1; j++) {
UIntType y = (x[j] & upper_mask) | (x[j+1] & lower_mask);
x[j] = x[j-(n-m)] ^ (y >> 1) ^ ((x[j+1]&1) * a);
}
}
// last iteration
UIntType y = (x[n-1] & upper_mask) | (x[0] & lower_mask);
x[n-1] = x[m-1] ^ (y >> 1) ^ ((x[0]&1) * a);
i = 0;
}
/// \endcond
template<class UIntType,
std::size_t w, std::size_t n, std::size_t m, std::size_t r,
UIntType a, std::size_t u, UIntType d, std::size_t s,
UIntType b, std::size_t t,
UIntType c, std::size_t l, UIntType f>
inline typename
mersenne_twister_engine<UIntType,w,n,m,r,a,u,d,s,b,t,c,l,f>::result_type
mersenne_twister_engine<UIntType,w,n,m,r,a,u,d,s,b,t,c,l,f>::operator()()
{
if(i == n)
twist();
// Step 4
UIntType z = x[i];
++i;
z ^= ((z >> u) & d);
z ^= ((z << s) & b);
z ^= ((z << t) & c);
z ^= (z >> l);
return z;
}
/**
* The specializations \mt11213b and \mt19937 are from
*
* @blockquote
* "Mersenne Twister: A 623-dimensionally equidistributed
* uniform pseudo-random number generator", Makoto Matsumoto
* and Takuji Nishimura, ACM Transactions on Modeling and
* Computer Simulation: Special Issue on Uniform Random Number
* Generation, Vol. 8, No. 1, January 1998, pp. 3-30.
* @endblockquote
*/
typedef mersenne_twister_engine<uint32_t,32,351,175,19,0xccab8ee7,
11,0xffffffff,7,0x31b6ab00,15,0xffe50000,17,1812433253> mt11213b;
/**
* The specializations \mt11213b and \mt19937 are from
*
* @blockquote
* "Mersenne Twister: A 623-dimensionally equidistributed
* uniform pseudo-random number generator", Makoto Matsumoto
* and Takuji Nishimura, ACM Transactions on Modeling and
* Computer Simulation: Special Issue on Uniform Random Number
* Generation, Vol. 8, No. 1, January 1998, pp. 3-30.
* @endblockquote
*/
typedef mersenne_twister_engine<uint32_t,32,624,397,31,0x9908b0df,
11,0xffffffff,7,0x9d2c5680,15,0xefc60000,18,1812433253> mt19937;
#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T)
typedef mersenne_twister_engine<uint64_t,64,312,156,31,
UINT64_C(0xb5026f5aa96619e9),29,UINT64_C(0x5555555555555555),17,
UINT64_C(0x71d67fffeda60000),37,UINT64_C(0xfff7eee000000000),43,
UINT64_C(6364136223846793005)> mt19937_64;
#endif
/// \cond show_deprecated
template<class UIntType,
int w, int n, int m, int r,
UIntType a, int u, std::size_t s,
UIntType b, int t,
UIntType c, int l, UIntType v>
class mersenne_twister :
public mersenne_twister_engine<UIntType,
w, n, m, r, a, u, ~(UIntType)0, s, b, t, c, l, 1812433253>
{
typedef mersenne_twister_engine<UIntType,
w, n, m, r, a, u, ~(UIntType)0, s, b, t, c, l, 1812433253> base_type;
public:
mersenne_twister() {}
BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(mersenne_twister, Gen, gen)
{ seed(gen); }
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(mersenne_twister, UIntType, val)
{ seed(val); }
template<class It>
mersenne_twister(It& first, It last) : base_type(first, last) {}
void seed() { base_type::seed(); }
BOOST_RANDOM_DETAIL_GENERATOR_SEED(mersenne_twister, Gen, gen)
{
detail::generator_seed_seq<Gen> seq(gen);
base_type::seed(seq);
}
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(mersenne_twister, UIntType, val)
{ base_type::seed(val); }
template<class It>
void seed(It& first, It last) { base_type::seed(first, last); }
};
/// \endcond
} // namespace random
using random::mt11213b;
using random::mt19937;
using random::mt19937_64;
} // namespace boost
BOOST_RANDOM_PTR_HELPER_SPEC(boost::mt11213b)
BOOST_RANDOM_PTR_HELPER_SPEC(boost::mt19937)
BOOST_RANDOM_PTR_HELPER_SPEC(boost::mt19937_64)
#include <boost/random/detail/enable_warnings.hpp>
#endif // BOOST_RANDOM_MERSENNE_TWISTER_HPP
@@ -0,0 +1,220 @@
/* boost random/negative_binomial_distribution.hpp header file
*
* Copyright Steven Watanabe 2010
* 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_NEGATIVE_BINOMIAL_DISTRIBUTION_HPP_INCLUDED
#define BOOST_RANDOM_NEGATIVE_BINOMIAL_DISTRIBUTION_HPP_INCLUDED
#include <iosfwd>
#include <boost/limits.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/gamma_distribution.hpp>
#include <boost/random/poisson_distribution.hpp>
namespace boost {
namespace random {
/**
* The negative binomial distribution is an integer valued
* distribution with two parameters, @c k and @c p. The
* distribution produces non-negative values.
*
* The distribution function is
* \f$\displaystyle P(i) = {k+i-1\choose i}p^k(1-p)^i\f$.
*
* This implementation uses a gamma-poisson mixture.
*/
template<class IntType = int, class RealType = double>
class negative_binomial_distribution {
public:
typedef IntType result_type;
typedef RealType input_type;
class param_type {
public:
typedef negative_binomial_distribution distribution_type;
/**
* Construct a param_type object. @c k and @c p
* are the parameters of the distribution.
*
* Requires: k >=0 && 0 <= p <= 1
*/
explicit param_type(IntType k_arg = 1, RealType p_arg = RealType (0.5))
: _k(k_arg), _p(p_arg)
{}
/** Returns the @c k parameter of the distribution. */
IntType k() const { return _k; }
/** Returns the @c p parameter of the distribution. */
RealType p() const { return _p; }
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
/** Writes the parameters of the distribution to a @c std::ostream. */
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os,
const param_type& parm)
{
os << parm._p << " " << parm._k;
return os;
}
/** Reads the parameters of the distribution from a @c std::istream. */
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is, param_type& parm)
{
is >> parm._p >> std::ws >> parm._k;
return is;
}
#endif
/** Returns true if the parameters have the same values. */
friend bool operator==(const param_type& lhs, const param_type& rhs)
{
return lhs._k == rhs._k && lhs._p == rhs._p;
}
/** Returns true if the parameters have different values. */
friend bool operator!=(const param_type& lhs, const param_type& rhs)
{
return !(lhs == rhs);
}
private:
IntType _k;
RealType _p;
};
/**
* Construct a @c negative_binomial_distribution object. @c k and @c p
* are the parameters of the distribution.
*
* Requires: k >=0 && 0 <= p <= 1
*/
explicit negative_binomial_distribution(IntType k_arg = 1,
RealType p_arg = RealType(0.5))
: _k(k_arg), _p(p_arg)
{}
/**
* Construct an @c negative_binomial_distribution object from the
* parameters.
*/
explicit negative_binomial_distribution(const param_type& parm)
: _k(parm.k()), _p(parm.p())
{}
/**
* Returns a random variate distributed according to the
* negative binomial distribution.
*/
template<class URNG>
IntType operator()(URNG& urng) const
{
gamma_distribution<RealType> gamma(_k, (1-_p)/_p);
poisson_distribution<IntType, RealType> poisson(gamma(urng));
return poisson(urng);
}
/**
* Returns a random variate distributed according to the negative
* binomial distribution with parameters specified by @c param.
*/
template<class URNG>
IntType operator()(URNG& urng, const param_type& parm) const
{
return negative_binomial_distribution(parm)(urng);
}
/** Returns the @c k parameter of the distribution. */
IntType k() const { return _k; }
/** Returns the @c p parameter of the distribution. */
RealType p() const { return _p; }
/** Returns the smallest value that the distribution can produce. */
IntType min BOOST_PREVENT_MACRO_SUBSTITUTION() const { return 0; }
/** Returns the largest value that the distribution can produce. */
IntType max BOOST_PREVENT_MACRO_SUBSTITUTION() const
{ return (std::numeric_limits<IntType>::max)(); }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(_k, _p); }
/** Sets parameters of the distribution. */
void param(const param_type& parm)
{
_k = parm.k();
_p = parm.p();
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { }
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
/** Writes the parameters of the distribution to a @c std::ostream. */
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os,
const negative_binomial_distribution& bd)
{
os << bd.param();
return os;
}
/** Reads the parameters of the distribution from a @c std::istream. */
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is,
negative_binomial_distribution& bd)
{
bd.read(is);
return is;
}
#endif
/** Returns true if the two distributions will produce the same
sequence of values, given equal generators. */
friend bool operator==(const negative_binomial_distribution& lhs,
const negative_binomial_distribution& rhs)
{
return lhs._k == rhs._k && lhs._p == rhs._p;
}
/** Returns true if the two distributions could produce different
sequences of values, given equal generators. */
friend bool operator!=(const negative_binomial_distribution& lhs,
const negative_binomial_distribution& rhs)
{
return !(lhs == rhs);
}
private:
/// @cond \show_private
template<class CharT, class Traits>
void read(std::basic_istream<CharT, Traits>& is) {
param_type parm;
if(is >> parm) {
param(parm);
}
}
// parameters
IntType _k;
RealType _p;
/// @endcond
};
}
}
#endif
@@ -0,0 +1,221 @@
/* boost random/non_central_chi_squared_distribution.hpp header file
*
* Copyright Thijs van den Berg 2014
*
* 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_NON_CENTRAL_CHI_SQUARED_DISTRIBUTION_HPP
#define BOOST_RANDOM_NON_CENTRAL_CHI_SQUARED_DISTRIBUTION_HPP
#include <boost/config/no_tr1/cmath.hpp>
#include <iosfwd>
#include <istream>
#include <boost/limits.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/uniform_real_distribution.hpp>
#include <boost/random/normal_distribution.hpp>
#include <boost/random/chi_squared_distribution.hpp>
#include <boost/random/poisson_distribution.hpp>
namespace boost {
namespace random {
/**
* The noncentral chi-squared distribution is a real valued distribution with
* two parameter, @c k and @c lambda. The distribution produces values > 0.
*
* This is the distribution of the sum of squares of k Normal distributed
* variates each with variance one and \f$\lambda\f$ the sum of squares of the
* normal means.
*
* The distribution function is
* \f$\displaystyle P(x) = \frac{1}{2} e^{-(x+\lambda)/2} \left( \frac{x}{\lambda} \right)^{k/4-1/2} I_{k/2-1}( \sqrt{\lambda x} )\f$.
* where \f$\displaystyle I_\nu(z)\f$ is a modified Bessel function of the
* first kind.
*
* The algorithm is taken from
*
* @blockquote
* "Monte Carlo Methods in Financial Engineering", Paul Glasserman,
* 2003, XIII, 596 p, Stochastic Modelling and Applied Probability, Vol. 53,
* ISBN 978-0-387-21617-1, p 124, Fig. 3.5.
* @endblockquote
*/
template <typename RealType = double>
class non_central_chi_squared_distribution {
public:
typedef RealType result_type;
typedef RealType input_type;
class param_type {
public:
typedef non_central_chi_squared_distribution distribution_type;
/**
* Constructs the parameters of a non_central_chi_squared_distribution.
* @c k and @c lambda are the parameter of the distribution.
*
* Requires: k > 0 && lambda > 0
*/
explicit
param_type(RealType k_arg = RealType(1), RealType lambda_arg = RealType(1))
: _k(k_arg), _lambda(lambda_arg)
{
BOOST_ASSERT(k_arg > RealType(0));
BOOST_ASSERT(lambda_arg > RealType(0));
}
/** Returns the @c k parameter of the distribution */
RealType k() const { return _k; }
/** Returns the @c lambda parameter of the distribution */
RealType lambda() const { return _lambda; }
/** Writes the parameters of the distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{
os << parm._k << ' ' << parm._lambda;
return os;
}
/** Reads the parameters of the distribution from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{
is >> parm._k >> std::ws >> parm._lambda;
return is;
}
/** Returns true if the parameters have the same values. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._k == rhs._k && lhs._lambda == rhs._lambda; }
/** Returns true if the parameters have different values. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
RealType _k;
RealType _lambda;
};
/**
* Construct a @c non_central_chi_squared_distribution object. @c k and
* @c lambda are the parameter of the distribution.
*
* Requires: k > 0 && lambda > 0
*/
explicit
non_central_chi_squared_distribution(RealType k_arg = RealType(1), RealType lambda_arg = RealType(1))
: _param(k_arg, lambda_arg)
{
BOOST_ASSERT(k_arg > RealType(0));
BOOST_ASSERT(lambda_arg > RealType(0));
}
/**
* Construct a @c non_central_chi_squared_distribution object from the parameter.
*/
explicit
non_central_chi_squared_distribution(const param_type& parm)
: _param( parm )
{ }
/**
* Returns a random variate distributed according to the
* non central chi squared distribution specified by @c param.
*/
template<typename URNG>
RealType operator()(URNG& eng, const param_type& parm) const
{ return non_central_chi_squared_distribution(parm)(eng); }
/**
* Returns a random variate distributed according to the
* non central chi squared distribution.
*/
template<typename URNG>
RealType operator()(URNG& eng)
{
using std::sqrt;
if (_param.k() > 1) {
boost::random::normal_distribution<RealType> n_dist;
boost::random::chi_squared_distribution<RealType> c_dist(_param.k() - RealType(1));
RealType _z = n_dist(eng);
RealType _x = c_dist(eng);
RealType term1 = _z + sqrt(_param.lambda());
return term1*term1 + _x;
}
else {
boost::random::poisson_distribution<> p_dist(_param.lambda()/RealType(2));
boost::random::poisson_distribution<>::result_type _p = p_dist(eng);
boost::random::chi_squared_distribution<RealType> c_dist(_param.k() + RealType(2)*_p);
return c_dist(eng);
}
}
/** Returns the @c k parameter of the distribution. */
RealType k() const { return _param.k(); }
/** Returns the @c lambda parameter of the distribution. */
RealType lambda() const { return _param.lambda(); }
/** Returns the parameters of the distribution. */
param_type param() const { return _param; }
/** Sets parameters of the distribution. */
void param(const param_type& parm) { _param = parm; }
/** Resets the distribution, so that subsequent uses does not depend on values already produced by it.*/
void reset() {}
/** Returns the smallest value that the distribution can produce. */
RealType min BOOST_PREVENT_MACRO_SUBSTITUTION() const
{ return RealType(0); }
/** Returns the largest value that the distribution can produce. */
RealType max BOOST_PREVENT_MACRO_SUBSTITUTION() const
{ return (std::numeric_limits<RealType>::infinity)(); }
/** Writes the parameters of the distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, non_central_chi_squared_distribution, dist)
{
os << dist.param();
return os;
}
/** reads the parameters of the distribution from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, non_central_chi_squared_distribution, dist)
{
param_type parm;
if(is >> parm) {
dist.param(parm);
}
return is;
}
/** Returns true if two distributions have the same parameters and produce
the same sequence of random numbers given equal generators.*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(non_central_chi_squared_distribution, lhs, rhs)
{ return lhs.param() == rhs.param(); }
/** Returns true if two distributions have different parameters and/or can produce
different sequences of random numbers given equal generators.*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(non_central_chi_squared_distribution)
private:
/// @cond show_private
param_type _param;
/// @endcond
};
} // namespace random
} // namespace boost
#endif
@@ -0,0 +1,374 @@
/* boost random/normal_distribution.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$
*
* Revision history
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_NORMAL_DISTRIBUTION_HPP
#define BOOST_RANDOM_NORMAL_DISTRIBUTION_HPP
#include <boost/config/no_tr1/cmath.hpp>
#include <istream>
#include <iosfwd>
#include <boost/assert.hpp>
#include <boost/limits.hpp>
#include <boost/static_assert.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/detail/int_float_pair.hpp>
#include <boost/random/uniform_01.hpp>
#include <boost/random/exponential_distribution.hpp>
namespace boost {
namespace random {
namespace detail {
// tables for the ziggurat algorithm
template<class RealType>
struct normal_table {
static const RealType table_x[129];
static const RealType table_y[129];
};
template<class RealType>
const RealType normal_table<RealType>::table_x[129] = {
3.7130862467403632609, 3.4426198558966521214, 3.2230849845786185446, 3.0832288582142137009,
2.9786962526450169606, 2.8943440070186706210, 2.8231253505459664379, 2.7611693723841538514,
2.7061135731187223371, 2.6564064112581924999, 2.6109722484286132035, 2.5690336259216391328,
2.5300096723854666170, 2.4934545220919507609, 2.4590181774083500943, 2.4264206455302115930,
2.3954342780074673425, 2.3658713701139875435, 2.3375752413355307354, 2.3104136836950021558,
2.2842740596736568056, 2.2590595738653295251, 2.2346863955870569803, 2.2110814088747278106,
2.1881804320720206093, 2.1659267937448407377, 2.1442701823562613518, 2.1231657086697899595,
2.1025731351849988838, 2.0824562379877246441, 2.0627822745039633575, 2.0435215366506694976,
2.0246469733729338782, 2.0061338699589668403, 1.9879595741230607243, 1.9701032608497132242,
1.9525457295488889058, 1.9352692282919002011, 1.9182573008597320303, 1.9014946531003176140,
1.8849670357028692380, 1.8686611409895420085, 1.8525645117230870617, 1.8366654602533840447,
1.8209529965910050740, 1.8054167642140487420, 1.7900469825946189862, 1.7748343955807692457,
1.7597702248942318749, 1.7448461281083765085, 1.7300541605582435350, 1.7153867407081165482,
1.7008366185643009437, 1.6863968467734863258, 1.6720607540918522072, 1.6578219209482075462,
1.6436741568569826489, 1.6296114794646783962, 1.6156280950371329644, 1.6017183802152770587,
1.5878768648844007019, 1.5740982160167497219, 1.5603772223598406870, 1.5467087798535034608,
1.5330878776675560787, 1.5195095847593707806, 1.5059690368565502602, 1.4924614237746154081,
1.4789819769830978546, 1.4655259573357946276, 1.4520886428822164926, 1.4386653166774613138,
1.4252512545068615734, 1.4118417124397602509, 1.3984319141236063517, 1.3850170377251486449,
1.3715922024197322698, 1.3581524543224228739, 1.3446927517457130432, 1.3312079496576765017,
1.3176927832013429910, 1.3041418501204215390, 1.2905495919178731508, 1.2769102735516997175,
1.2632179614460282310, 1.2494664995643337480, 1.2356494832544811749, 1.2217602305309625678,
1.2077917504067576028, 1.1937367078237721994, 1.1795873846544607035, 1.1653356361550469083,
1.1509728421389760651, 1.1364898520030755352, 1.1218769225722540661, 1.1071236475235353980,
1.0922188768965537614, 1.0771506248819376573, 1.0619059636836193998, 1.0464709007525802629,
1.0308302360564555907, 1.0149673952392994716, 0.99886423348064351303, 0.98250080350276038481,
0.96585507938813059489, 0.94890262549791195381, 0.93161619660135381056, 0.91396525100880177644,
0.89591535256623852894, 0.87742742909771569142, 0.85845684317805086354, 0.83895221428120745572,
0.81885390668331772331, 0.79809206062627480454, 0.77658398787614838598, 0.75423066443451007146,
0.73091191062188128150, 0.70647961131360803456, 0.68074791864590421664, 0.65347863871504238702,
0.62435859730908822111, 0.59296294244197797913, 0.55869217837551797140, 0.52065603872514491759,
0.47743783725378787681, 0.42654798630330512490, 0.36287143102841830424, 0.27232086470466385065,
0
};
template<class RealType>
const RealType normal_table<RealType>::table_y[129] = {
0, 0.0026696290839025035092, 0.0055489952208164705392, 0.0086244844129304709682,
0.011839478657982313715, 0.015167298010672042468, 0.018592102737165812650, 0.022103304616111592615,
0.025693291936149616572, 0.029356317440253829618, 0.033087886146505155566, 0.036884388786968774128,
0.040742868074790604632, 0.044660862200872429800, 0.048636295860284051878, 0.052667401903503169793,
0.056752663481538584188, 0.060890770348566375972, 0.065080585213631873753, 0.069321117394180252601,
0.073611501884754893389, 0.077950982514654714188, 0.082338898242957408243, 0.086774671895542968998,
0.091257800827634710201, 0.09578784912257815216, 0.10036444102954554013, 0.10498725541035453978,
0.10965602101581776100, 0.11437051244988827452, 0.11913054670871858767, 0.12393598020398174246,
0.12878670619710396109, 0.13368265258464764118, 0.13862377998585103702, 0.14361008009193299469,
0.14864157424369696566, 0.15371831220958657066, 0.15884037114093507813, 0.16400785468492774791,
0.16922089223892475176, 0.17447963833240232295, 0.17978427212496211424, 0.18513499701071343216,
0.19053204032091372112, 0.19597565311811041399, 0.20146611007620324118, 0.20700370944187380064,
0.21258877307373610060, 0.21822164655637059599, 0.22390269938713388747, 0.22963232523430270355,
0.23541094226572765600, 0.24123899354775131610, 0.24711694751469673582, 0.25304529850976585934,
0.25902456739871074263, 0.26505530225816194029, 0.27113807914102527343, 0.27727350292189771153,
0.28346220822601251779, 0.28970486044581049771, 0.29600215684985583659, 0.30235482778947976274,
0.30876363800925192282, 0.31522938806815752222, 0.32175291587920862031, 0.32833509837615239609,
0.33497685331697116147, 0.34167914123501368412, 0.34844296754987246935, 0.35526938485154714435,
0.36215949537303321162, 0.36911445366827513952, 0.37613546951445442947, 0.38322381105988364587,
0.39038080824138948916, 0.39760785649804255208, 0.40490642081148835099, 0.41227804010702462062,
0.41972433205403823467, 0.42724699830956239880, 0.43484783025466189638, 0.44252871528024661483,
0.45029164368692696086, 0.45813871627287196483, 0.46607215269457097924, 0.47409430069824960453,
0.48220764633483869062, 0.49041482528932163741, 0.49871863547658432422, 0.50712205108130458951,
0.51562823824987205196, 0.52424057267899279809, 0.53296265938998758838, 0.54179835503172412311,
0.55075179312105527738, 0.55982741271069481791, 0.56902999107472161225, 0.57836468112670231279,
0.58783705444182052571, 0.59745315095181228217, 0.60721953663260488551, 0.61714337082656248870,
0.62723248525781456578, 0.63749547734314487428, 0.64794182111855080873, 0.65858200005865368016,
0.66942766735770616891, 0.68049184100641433355, 0.69178914344603585279, 0.70333609902581741633,
0.71515150742047704368, 0.72725691835450587793, 0.73967724368333814856, 0.75244155918570380145,
0.76558417390923599480, 0.77914608594170316563, 0.79317701178385921053, 0.80773829469612111340,
0.82290721139526200050, 0.83878360531064722379, 0.85550060788506428418, 0.87324304892685358879,
0.89228165080230272301, 0.91304364799203805999, 0.93628268170837107547, 0.96359969315576759960,
1
};
template<class RealType = double>
struct unit_normal_distribution
{
template<class Engine>
RealType operator()(Engine& eng) {
const double * const table_x = normal_table<double>::table_x;
const double * const table_y = normal_table<double>::table_y;
for(;;) {
std::pair<RealType, int> vals = generate_int_float_pair<RealType, 8>(eng);
int i = vals.second;
int sign = (i & 1) * 2 - 1;
i = i >> 1;
RealType x = vals.first * RealType(table_x[i]);
if(x < table_x[i + 1]) return x * sign;
if(i == 0) return generate_tail(eng) * sign;
RealType y01 = uniform_01<RealType>()(eng);
RealType y = RealType(table_y[i]) + y01 * RealType(table_y[i + 1] - table_y[i]);
// These store the value y - bound, or something proportional to that difference:
RealType y_above_ubound, y_above_lbound;
// There are three cases to consider:
// - convex regions (where x[i] > x[j] >= 1)
// - concave regions (where 1 <= x[i] < x[j])
// - region containing the inflection point (where x[i] > 1 > x[j])
// For convex (concave), exp^(-x^2/2) is bounded below (above) by the tangent at
// (x[i],y[i]) and is bounded above (below) by the diagonal line from (x[i+1],y[i+1]) to
// (x[i],y[i]).
//
// *If* the inflection point region satisfies slope(x[i+1]) < slope(diagonal), then we
// can treat the inflection region as a convex region: this condition is necessary and
// sufficient to ensure that the curve lies entirely below the diagonal (that, in turn,
// also implies that it will be above the tangent at x[i]).
//
// For the current table size (128), this is satisfied: slope(x[i+1]) = -0.60653 <
// slope(diag) = -0.60649, and so we have only two cases below instead of three.
if (table_x[i] >= 1) { // convex (incl. inflection)
y_above_ubound = RealType(table_x[i] - table_x[i+1]) * y01 - (RealType(table_x[i]) - x);
y_above_lbound = y - (RealType(table_y[i]) + (RealType(table_x[i]) - x) * RealType(table_y[i]) * RealType(table_x[i]));
}
else { // concave
y_above_lbound = RealType(table_x[i] - table_x[i+1]) * y01 - (RealType(table_x[i]) - x);
y_above_ubound = y - (RealType(table_y[i]) + (RealType(table_x[i]) - x) * RealType(table_y[i]) * RealType(table_x[i]));
}
if (y_above_ubound < 0 // if above the upper bound reject immediately
&&
(
y_above_lbound < 0 // If below the lower bound accept immediately
||
y < f(x) // Otherwise it's between the bounds and we need a full check
)
) {
return x * sign;
}
}
}
static RealType f(RealType x) {
using std::exp;
return exp(-(x*x/2));
}
// Generate from the tail using rejection sampling from the exponential(x_1) distribution,
// shifted by x_1. This looks a little different from the usual rejection sampling because it
// transforms the condition by taking the log of both sides, thus avoiding the costly exp() call
// on the RHS, then takes advantage of the fact that -log(unif01) is simply generating an
// exponential (by inverse cdf sampling) by replacing the log(unif01) on the LHS with a
// exponential(1) draw, y.
template<class Engine>
RealType generate_tail(Engine& eng) {
const RealType tail_start = RealType(normal_table<double>::table_x[1]);
boost::random::exponential_distribution<RealType> exp_x(tail_start);
boost::random::exponential_distribution<RealType> exp_y;
for(;;) {
RealType x = exp_x(eng);
RealType y = exp_y(eng);
// If we were doing non-transformed rejection sampling, this condition would be:
// if (unif01 < exp(-.5*x*x)) return x + tail_start;
if(2*y > x*x) return x + tail_start;
}
}
};
} // namespace detail
/**
* Instantiations of class template normal_distribution model a
* \random_distribution. Such a distribution produces random numbers
* @c x distributed with probability density function
* \f$\displaystyle p(x) =
* \frac{1}{\sqrt{2\pi}\sigma} e^{-\frac{(x-\mu)^2}{2\sigma^2}}
* \f$,
* where mean and sigma are the parameters of the distribution.
*
* The implementation uses the "ziggurat" algorithm, as described in
*
* @blockquote
* "The Ziggurat Method for Generating Random Variables",
* George Marsaglia and Wai Wan Tsang, Journal of Statistical Software,
* Volume 5, Number 8 (2000), 1-7.
* @endblockquote
*/
template<class RealType = double>
class normal_distribution
{
public:
typedef RealType input_type;
typedef RealType result_type;
class param_type {
public:
typedef normal_distribution distribution_type;
/**
* Constructs a @c param_type with a given mean and
* standard deviation.
*
* Requires: sigma >= 0
*/
explicit param_type(RealType mean_arg = RealType(0.0),
RealType sigma_arg = RealType(1.0))
: _mean(mean_arg),
_sigma(sigma_arg)
{}
/** Returns the mean of the distribution. */
RealType mean() const { return _mean; }
/** Returns the standand deviation of the distribution. */
RealType sigma() const { return _sigma; }
/** Writes a @c param_type to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{ os << parm._mean << " " << parm._sigma ; return os; }
/** Reads a @c param_type from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{ is >> parm._mean >> std::ws >> parm._sigma; return is; }
/** Returns true if the two sets of parameters are the same. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._mean == rhs._mean && lhs._sigma == rhs._sigma; }
/** Returns true if the two sets of parameters are the different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
RealType _mean;
RealType _sigma;
};
/**
* Constructs a @c normal_distribution object. @c mean and @c sigma are
* the parameters for the distribution.
*
* Requires: sigma >= 0
*/
explicit normal_distribution(const RealType& mean_arg = RealType(0.0),
const RealType& sigma_arg = RealType(1.0))
: _mean(mean_arg), _sigma(sigma_arg)
{
BOOST_ASSERT(_sigma >= RealType(0));
}
/**
* Constructs a @c normal_distribution object from its parameters.
*/
explicit normal_distribution(const param_type& parm)
: _mean(parm.mean()), _sigma(parm.sigma())
{}
/** Returns the mean of the distribution. */
RealType mean() const { return _mean; }
/** Returns the standard deviation of the distribution. */
RealType sigma() const { return _sigma; }
/** Returns the smallest value that the distribution can produce. */
RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return -std::numeric_limits<RealType>::infinity(); }
/** Returns the largest value that the distribution can produce. */
RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return std::numeric_limits<RealType>::infinity(); }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(_mean, _sigma); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
_mean = parm.mean();
_sigma = parm.sigma();
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { }
/** Returns a normal variate. */
template<class Engine>
result_type operator()(Engine& eng)
{
detail::unit_normal_distribution<RealType> impl;
return impl(eng) * _sigma + _mean;
}
/** Returns a normal variate with parameters specified by @c param. */
template<class URNG>
result_type operator()(URNG& urng, const param_type& parm)
{
return normal_distribution(parm)(urng);
}
/** Writes a @c normal_distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, normal_distribution, nd)
{
os << nd._mean << " " << nd._sigma;
return os;
}
/** Reads a @c normal_distribution from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, normal_distribution, nd)
{
is >> std::ws >> nd._mean >> std::ws >> nd._sigma;
return is;
}
/**
* Returns true if the two instances of @c normal_distribution will
* return identical sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(normal_distribution, lhs, rhs)
{
return lhs._mean == rhs._mean && lhs._sigma == rhs._sigma;
}
/**
* Returns true if the two instances of @c normal_distribution will
* return different sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(normal_distribution)
private:
RealType _mean, _sigma;
};
} // namespace random
using random::normal_distribution;
} // namespace boost
#endif // BOOST_RANDOM_NORMAL_DISTRIBUTION_HPP
@@ -0,0 +1,466 @@
/* boost random/piecewise_constant_distribution.hpp header file
*
* Copyright Steven Watanabe 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_PIECEWISE_CONSTANT_DISTRIBUTION_HPP_INCLUDED
#define BOOST_RANDOM_PIECEWISE_CONSTANT_DISTRIBUTION_HPP_INCLUDED
#include <vector>
#include <numeric>
#include <boost/assert.hpp>
#include <boost/random/uniform_real.hpp>
#include <boost/random/discrete_distribution.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/detail/vector_io.hpp>
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
#include <initializer_list>
#endif
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost {
namespace random {
/**
* The class @c piecewise_constant_distribution models a \random_distribution.
*/
template<class RealType = double, class WeightType = double>
class piecewise_constant_distribution {
public:
typedef std::size_t input_type;
typedef RealType result_type;
class param_type {
public:
typedef piecewise_constant_distribution distribution_type;
/**
* Constructs a @c param_type object, representing a distribution
* that produces values uniformly distributed in the range [0, 1).
*/
param_type()
{
_weights.push_back(WeightType(1));
_intervals.push_back(RealType(0));
_intervals.push_back(RealType(1));
}
/**
* Constructs a @c param_type object from two iterator ranges
* containing the interval boundaries and the interval weights.
* If there are less than two boundaries, then this is equivalent to
* the default constructor and creates a single interval, [0, 1).
*
* The values of the interval boundaries must be strictly
* increasing, and the number of weights must be one less than
* the number of interval boundaries. If there are extra
* weights, they are ignored.
*/
template<class IntervalIter, class WeightIter>
param_type(IntervalIter intervals_first, IntervalIter intervals_last,
WeightIter weight_first)
: _intervals(intervals_first, intervals_last)
{
if(_intervals.size() < 2) {
_intervals.clear();
_intervals.push_back(RealType(0));
_intervals.push_back(RealType(1));
_weights.push_back(WeightType(1));
} else {
_weights.reserve(_intervals.size() - 1);
for(std::size_t i = 0; i < _intervals.size() - 1; ++i) {
_weights.push_back(*weight_first++);
}
}
}
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
/**
* Constructs a @c param_type object from an
* initializer_list containing the interval boundaries
* and a unary function specifying the weights. Each
* weight is determined by calling the function at the
* midpoint of the corresponding interval.
*
* If the initializer_list contains less than two elements,
* this is equivalent to the default constructor and the
* distribution will produce values uniformly distributed
* in the range [0, 1).
*/
template<class T, class F>
param_type(const std::initializer_list<T>& il, F f)
: _intervals(il.begin(), il.end())
{
if(_intervals.size() < 2) {
_intervals.clear();
_intervals.push_back(RealType(0));
_intervals.push_back(RealType(1));
_weights.push_back(WeightType(1));
} else {
_weights.reserve(_intervals.size() - 1);
for(std::size_t i = 0; i < _intervals.size() - 1; ++i) {
RealType midpoint = (_intervals[i] + _intervals[i + 1]) / 2;
_weights.push_back(f(midpoint));
}
}
}
#endif
/**
* Constructs a @c param_type object from Boost.Range
* ranges holding the interval boundaries and the weights. If
* there are less than two interval boundaries, this is equivalent
* to the default constructor and the distribution will produce
* values uniformly distributed in the range [0, 1). The
* number of weights must be one less than the number of
* interval boundaries.
*/
template<class IntervalRange, class WeightRange>
param_type(const IntervalRange& intervals_arg,
const WeightRange& weights_arg)
: _intervals(boost::begin(intervals_arg), boost::end(intervals_arg)),
_weights(boost::begin(weights_arg), boost::end(weights_arg))
{
if(_intervals.size() < 2) {
_intervals.clear();
_intervals.push_back(RealType(0));
_intervals.push_back(RealType(1));
_weights.push_back(WeightType(1));
}
}
/**
* Constructs the parameters for a distribution that approximates a
* function. The range of the distribution is [xmin, xmax). This
* range is divided into nw equally sized intervals and the weights
* are found by calling the unary function f on the midpoints of the
* intervals.
*/
template<class F>
param_type(std::size_t nw, RealType xmin, RealType xmax, F f)
{
std::size_t n = (nw == 0) ? 1 : nw;
double delta = (xmax - xmin) / n;
BOOST_ASSERT(delta > 0);
for(std::size_t k = 0; k < n; ++k) {
_weights.push_back(f(xmin + k*delta + delta/2));
_intervals.push_back(xmin + k*delta);
}
_intervals.push_back(xmax);
}
/** Returns a vector containing the interval boundaries. */
std::vector<RealType> intervals() const { return _intervals; }
/**
* Returns a vector containing the probability densities
* over all the intervals of the distribution.
*/
std::vector<RealType> densities() const
{
RealType sum = std::accumulate(_weights.begin(), _weights.end(),
static_cast<RealType>(0));
std::vector<RealType> result;
result.reserve(_weights.size());
for(std::size_t i = 0; i < _weights.size(); ++i) {
RealType width = _intervals[i + 1] - _intervals[i];
result.push_back(_weights[i] / (sum * width));
}
return result;
}
/** Writes the parameters to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{
detail::print_vector(os, parm._intervals);
detail::print_vector(os, parm._weights);
return os;
}
/** Reads the parameters from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{
std::vector<RealType> new_intervals;
std::vector<WeightType> new_weights;
detail::read_vector(is, new_intervals);
detail::read_vector(is, new_weights);
if(is) {
parm._intervals.swap(new_intervals);
parm._weights.swap(new_weights);
}
return is;
}
/** Returns true if the two sets of parameters are the same. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{
return lhs._intervals == rhs._intervals
&& lhs._weights == rhs._weights;
}
/** Returns true if the two sets of parameters are different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
friend class piecewise_constant_distribution;
std::vector<RealType> _intervals;
std::vector<WeightType> _weights;
};
/**
* Creates a new @c piecewise_constant_distribution with
* a single interval, [0, 1).
*/
piecewise_constant_distribution()
{
_intervals.push_back(RealType(0));
_intervals.push_back(RealType(1));
}
/**
* Constructs a piecewise_constant_distribution from two iterator ranges
* containing the interval boundaries and the interval weights.
* If there are less than two boundaries, then this is equivalent to
* the default constructor and creates a single interval, [0, 1).
*
* The values of the interval boundaries must be strictly
* increasing, and the number of weights must be one less than
* the number of interval boundaries. If there are extra
* weights, they are ignored.
*
* For example,
*
* @code
* double intervals[] = { 0.0, 1.0, 4.0 };
* double weights[] = { 1.0, 1.0 };
* piecewise_constant_distribution<> dist(
* &intervals[0], &intervals[0] + 3, &weights[0]);
* @endcode
*
* The distribution has a 50% chance of producing a
* value between 0 and 1 and a 50% chance of producing
* a value between 1 and 4.
*/
template<class IntervalIter, class WeightIter>
piecewise_constant_distribution(IntervalIter first_interval,
IntervalIter last_interval,
WeightIter first_weight)
: _intervals(first_interval, last_interval)
{
if(_intervals.size() < 2) {
_intervals.clear();
_intervals.push_back(RealType(0));
_intervals.push_back(RealType(1));
} else {
std::vector<WeightType> actual_weights;
actual_weights.reserve(_intervals.size() - 1);
for(std::size_t i = 0; i < _intervals.size() - 1; ++i) {
actual_weights.push_back(*first_weight++);
}
typedef discrete_distribution<std::size_t, WeightType> bins_type;
typename bins_type::param_type bins_param(actual_weights);
_bins.param(bins_param);
}
}
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
/**
* Constructs a piecewise_constant_distribution from an
* initializer_list containing the interval boundaries
* and a unary function specifying the weights. Each
* weight is determined by calling the function at the
* midpoint of the corresponding interval.
*
* If the initializer_list contains less than two elements,
* this is equivalent to the default constructor and the
* distribution will produce values uniformly distributed
* in the range [0, 1).
*/
template<class T, class F>
piecewise_constant_distribution(std::initializer_list<T> il, F f)
: _intervals(il.begin(), il.end())
{
if(_intervals.size() < 2) {
_intervals.clear();
_intervals.push_back(RealType(0));
_intervals.push_back(RealType(1));
} else {
std::vector<WeightType> actual_weights;
actual_weights.reserve(_intervals.size() - 1);
for(std::size_t i = 0; i < _intervals.size() - 1; ++i) {
RealType midpoint = (_intervals[i] + _intervals[i + 1]) / 2;
actual_weights.push_back(f(midpoint));
}
typedef discrete_distribution<std::size_t, WeightType> bins_type;
typename bins_type::param_type bins_param(actual_weights);
_bins.param(bins_param);
}
}
#endif
/**
* Constructs a piecewise_constant_distribution from Boost.Range
* ranges holding the interval boundaries and the weights. If
* there are less than two interval boundaries, this is equivalent
* to the default constructor and the distribution will produce
* values uniformly distributed in the range [0, 1). The
* number of weights must be one less than the number of
* interval boundaries.
*/
template<class IntervalsRange, class WeightsRange>
piecewise_constant_distribution(const IntervalsRange& intervals_arg,
const WeightsRange& weights_arg)
: _bins(weights_arg),
_intervals(boost::begin(intervals_arg), boost::end(intervals_arg))
{
if(_intervals.size() < 2) {
_intervals.clear();
_intervals.push_back(RealType(0));
_intervals.push_back(RealType(1));
}
}
/**
* Constructs a piecewise_constant_distribution that approximates a
* function. The range of the distribution is [xmin, xmax). This
* range is divided into nw equally sized intervals and the weights
* are found by calling the unary function f on the midpoints of the
* intervals.
*/
template<class F>
piecewise_constant_distribution(std::size_t nw,
RealType xmin,
RealType xmax,
F f)
: _bins(nw, xmin, xmax, f)
{
if(nw == 0) { nw = 1; }
RealType delta = (xmax - xmin) / nw;
_intervals.reserve(nw + 1);
for(std::size_t i = 0; i < nw; ++i) {
_intervals.push_back(xmin + i * delta);
}
_intervals.push_back(xmax);
}
/**
* Constructs a piecewise_constant_distribution from its parameters.
*/
explicit piecewise_constant_distribution(const param_type& parm)
: _bins(parm._weights),
_intervals(parm._intervals)
{
}
/**
* Returns a value distributed according to the parameters of the
* piecewist_constant_distribution.
*/
template<class URNG>
RealType operator()(URNG& urng) const
{
std::size_t i = _bins(urng);
return uniform_real<RealType>(_intervals[i], _intervals[i+1])(urng);
}
/**
* Returns a value distributed according to the parameters
* specified by param.
*/
template<class URNG>
RealType operator()(URNG& urng, const param_type& parm) const
{
return piecewise_constant_distribution(parm)(urng);
}
/** Returns the smallest value that the distribution can produce. */
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return _intervals.front(); }
/** Returns the largest value that the distribution can produce. */
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return _intervals.back(); }
/**
* Returns a vector containing the probability density
* over each interval.
*/
std::vector<RealType> densities() const
{
std::vector<RealType> result(_bins.probabilities());
for(std::size_t i = 0; i < result.size(); ++i) {
result[i] /= (_intervals[i+1] - _intervals[i]);
}
return(result);
}
/** Returns a vector containing the interval boundaries. */
std::vector<RealType> intervals() const { return _intervals; }
/** Returns the parameters of the distribution. */
param_type param() const
{
return param_type(_intervals, _bins.probabilities());
}
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
std::vector<RealType> new_intervals(parm._intervals);
typedef discrete_distribution<std::size_t, WeightType> bins_type;
typename bins_type::param_type bins_param(parm._weights);
_bins.param(bins_param);
_intervals.swap(new_intervals);
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { _bins.reset(); }
/** Writes a distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(
os, piecewise_constant_distribution, pcd)
{
os << pcd.param();
return os;
}
/** Reads a distribution from a @c std::istream */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(
is, piecewise_constant_distribution, pcd)
{
param_type parm;
if(is >> parm) {
pcd.param(parm);
}
return is;
}
/**
* Returns true if the two distributions will return the
* same sequence of values, when passed equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(
piecewise_constant_distribution, lhs, rhs)
{
return lhs._bins == rhs._bins && lhs._intervals == rhs._intervals;
}
/**
* Returns true if the two distributions may return different
* sequences of values, when passed equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(piecewise_constant_distribution)
private:
discrete_distribution<std::size_t, WeightType> _bins;
std::vector<RealType> _intervals;
};
}
}
#endif
@@ -0,0 +1,531 @@
/* boost random/piecewise_linear_distribution.hpp header file
*
* Copyright Steven Watanabe 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_PIECEWISE_LINEAR_DISTRIBUTION_HPP_INCLUDED
#define BOOST_RANDOM_PIECEWISE_LINEAR_DISTRIBUTION_HPP_INCLUDED
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <boost/assert.hpp>
#include <boost/random/uniform_real.hpp>
#include <boost/random/discrete_distribution.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/detail/vector_io.hpp>
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
#include <initializer_list>
#endif
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
namespace boost {
namespace random {
/**
* The class @c piecewise_linear_distribution models a \random_distribution.
*/
template<class RealType = double>
class piecewise_linear_distribution {
public:
typedef std::size_t input_type;
typedef RealType result_type;
class param_type {
public:
typedef piecewise_linear_distribution distribution_type;
/**
* Constructs a @c param_type object, representing a distribution
* that produces values uniformly distributed in the range [0, 1).
*/
param_type()
{
_weights.push_back(RealType(1));
_weights.push_back(RealType(1));
_intervals.push_back(RealType(0));
_intervals.push_back(RealType(1));
}
/**
* Constructs a @c param_type object from two iterator ranges
* containing the interval boundaries and weights at the boundaries.
* If there are fewer than two boundaries, then this is equivalent to
* the default constructor and the distribution will produce values
* uniformly distributed in the range [0, 1).
*
* The values of the interval boundaries must be strictly
* increasing, and the number of weights must be the same as
* the number of interval boundaries. If there are extra
* weights, they are ignored.
*/
template<class IntervalIter, class WeightIter>
param_type(IntervalIter intervals_first, IntervalIter intervals_last,
WeightIter weight_first)
: _intervals(intervals_first, intervals_last)
{
if(_intervals.size() < 2) {
_intervals.clear();
_weights.push_back(RealType(1));
_weights.push_back(RealType(1));
_intervals.push_back(RealType(0));
_intervals.push_back(RealType(1));
} else {
_weights.reserve(_intervals.size());
for(std::size_t i = 0; i < _intervals.size(); ++i) {
_weights.push_back(*weight_first++);
}
}
}
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
/**
* Constructs a @c param_type object from an initializer_list
* containing the interval boundaries and a unary function
* specifying the weights at the boundaries. Each weight is
* determined by calling the function at the corresponding point.
*
* If the initializer_list contains fewer than two elements,
* this is equivalent to the default constructor and the
* distribution will produce values uniformly distributed
* in the range [0, 1).
*/
template<class T, class F>
param_type(const std::initializer_list<T>& il, F f)
: _intervals(il.begin(), il.end())
{
if(_intervals.size() < 2) {
_intervals.clear();
_weights.push_back(RealType(1));
_weights.push_back(RealType(1));
_intervals.push_back(RealType(0));
_intervals.push_back(RealType(1));
} else {
_weights.reserve(_intervals.size());
for(typename std::vector<RealType>::const_iterator
iter = _intervals.begin(), end = _intervals.end();
iter != end; ++iter)
{
_weights.push_back(f(*iter));
}
}
}
#endif
/**
* Constructs a @c param_type object from Boost.Range ranges holding
* the interval boundaries and the weights at the boundaries. If
* there are fewer than two interval boundaries, this is equivalent
* to the default constructor and the distribution will produce
* values uniformly distributed in the range [0, 1). The
* number of weights must be equal to the number of
* interval boundaries.
*/
template<class IntervalRange, class WeightRange>
param_type(const IntervalRange& intervals_arg,
const WeightRange& weights_arg)
: _intervals(boost::begin(intervals_arg), boost::end(intervals_arg)),
_weights(boost::begin(weights_arg), boost::end(weights_arg))
{
if(_intervals.size() < 2) {
_weights.clear();
_weights.push_back(RealType(1));
_weights.push_back(RealType(1));
_intervals.clear();
_intervals.push_back(RealType(0));
_intervals.push_back(RealType(1));
}
}
/**
* Constructs the parameters for a distribution that approximates a
* function. The range of the distribution is [xmin, xmax). This
* range is divided into nw equally sized intervals and the weights
* are found by calling the unary function f on the boundaries of the
* intervals.
*/
template<class F>
param_type(std::size_t nw, RealType xmin, RealType xmax, F f)
{
std::size_t n = (nw == 0) ? 1 : nw;
double delta = (xmax - xmin) / n;
BOOST_ASSERT(delta > 0);
for(std::size_t k = 0; k < n; ++k) {
_weights.push_back(f(xmin + k*delta));
_intervals.push_back(xmin + k*delta);
}
_weights.push_back(f(xmax));
_intervals.push_back(xmax);
}
/** Returns a vector containing the interval boundaries. */
std::vector<RealType> intervals() const { return _intervals; }
/**
* Returns a vector containing the probability densities
* at all the interval boundaries.
*/
std::vector<RealType> densities() const
{
RealType sum = static_cast<RealType>(0);
for(std::size_t i = 0; i < _intervals.size() - 1; ++i) {
RealType width = _intervals[i + 1] - _intervals[i];
sum += (_weights[i] + _weights[i + 1]) * width / 2;
}
std::vector<RealType> result;
result.reserve(_weights.size());
for(typename std::vector<RealType>::const_iterator
iter = _weights.begin(), end = _weights.end();
iter != end; ++iter)
{
result.push_back(*iter / sum);
}
return result;
}
/** Writes the parameters to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{
detail::print_vector(os, parm._intervals);
detail::print_vector(os, parm._weights);
return os;
}
/** Reads the parameters from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{
std::vector<RealType> new_intervals;
std::vector<RealType> new_weights;
detail::read_vector(is, new_intervals);
detail::read_vector(is, new_weights);
if(is) {
parm._intervals.swap(new_intervals);
parm._weights.swap(new_weights);
}
return is;
}
/** Returns true if the two sets of parameters are the same. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{
return lhs._intervals == rhs._intervals
&& lhs._weights == rhs._weights;
}
/** Returns true if the two sets of parameters are different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
friend class piecewise_linear_distribution;
std::vector<RealType> _intervals;
std::vector<RealType> _weights;
};
/**
* Creates a new @c piecewise_linear_distribution that
* produces values uniformly distributed in the range [0, 1).
*/
piecewise_linear_distribution()
{
default_init();
}
/**
* Constructs a piecewise_linear_distribution from two iterator ranges
* containing the interval boundaries and the weights at the boundaries.
* If there are fewer than two boundaries, then this is equivalent to
* the default constructor and creates a distribution that
* produces values uniformly distributed in the range [0, 1).
*
* The values of the interval boundaries must be strictly
* increasing, and the number of weights must be equal to
* the number of interval boundaries. If there are extra
* weights, they are ignored.
*
* For example,
*
* @code
* double intervals[] = { 0.0, 1.0, 2.0 };
* double weights[] = { 0.0, 1.0, 0.0 };
* piecewise_constant_distribution<> dist(
* &intervals[0], &intervals[0] + 3, &weights[0]);
* @endcode
*
* produces a triangle distribution.
*/
template<class IntervalIter, class WeightIter>
piecewise_linear_distribution(IntervalIter first_interval,
IntervalIter last_interval,
WeightIter first_weight)
: _intervals(first_interval, last_interval)
{
if(_intervals.size() < 2) {
default_init();
} else {
_weights.reserve(_intervals.size());
for(std::size_t i = 0; i < _intervals.size(); ++i) {
_weights.push_back(*first_weight++);
}
init();
}
}
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
/**
* Constructs a piecewise_linear_distribution from an
* initializer_list containing the interval boundaries
* and a unary function specifying the weights. Each
* weight is determined by calling the function at the
* corresponding interval boundary.
*
* If the initializer_list contains fewer than two elements,
* this is equivalent to the default constructor and the
* distribution will produce values uniformly distributed
* in the range [0, 1).
*/
template<class T, class F>
piecewise_linear_distribution(std::initializer_list<T> il, F f)
: _intervals(il.begin(), il.end())
{
if(_intervals.size() < 2) {
default_init();
} else {
_weights.reserve(_intervals.size());
for(typename std::vector<RealType>::const_iterator
iter = _intervals.begin(), end = _intervals.end();
iter != end; ++iter)
{
_weights.push_back(f(*iter));
}
init();
}
}
#endif
/**
* Constructs a piecewise_linear_distribution from Boost.Range
* ranges holding the interval boundaries and the weights. If
* there are fewer than two interval boundaries, this is equivalent
* to the default constructor and the distribution will produce
* values uniformly distributed in the range [0, 1). The
* number of weights must be equal to the number of
* interval boundaries.
*/
template<class IntervalsRange, class WeightsRange>
piecewise_linear_distribution(const IntervalsRange& intervals_arg,
const WeightsRange& weights_arg)
: _intervals(boost::begin(intervals_arg), boost::end(intervals_arg)),
_weights(boost::begin(weights_arg), boost::end(weights_arg))
{
if(_intervals.size() < 2) {
default_init();
} else {
init();
}
}
/**
* Constructs a piecewise_linear_distribution that approximates a
* function. The range of the distribution is [xmin, xmax). This
* range is divided into nw equally sized intervals and the weights
* are found by calling the unary function f on the interval boundaries.
*/
template<class F>
piecewise_linear_distribution(std::size_t nw,
RealType xmin,
RealType xmax,
F f)
{
if(nw == 0) { nw = 1; }
RealType delta = (xmax - xmin) / nw;
_intervals.reserve(nw + 1);
for(std::size_t i = 0; i < nw; ++i) {
RealType x = xmin + i * delta;
_intervals.push_back(x);
_weights.push_back(f(x));
}
_intervals.push_back(xmax);
_weights.push_back(f(xmax));
init();
}
/**
* Constructs a piecewise_linear_distribution from its parameters.
*/
explicit piecewise_linear_distribution(const param_type& parm)
: _intervals(parm._intervals),
_weights(parm._weights)
{
init();
}
/**
* Returns a value distributed according to the parameters of the
* piecewise_linear_distribution.
*/
template<class URNG>
RealType operator()(URNG& urng) const
{
std::size_t i = _bins(urng);
bool is_in_rectangle = (i % 2 == 0);
i = i / 2;
uniform_real<RealType> dist(_intervals[i], _intervals[i+1]);
if(is_in_rectangle) {
return dist(urng);
} else if(_weights[i] < _weights[i+1]) {
return (std::max)(dist(urng), dist(urng));
} else {
return (std::min)(dist(urng), dist(urng));
}
}
/**
* Returns a value distributed according to the parameters
* specified by param.
*/
template<class URNG>
RealType operator()(URNG& urng, const param_type& parm) const
{
return piecewise_linear_distribution(parm)(urng);
}
/** Returns the smallest value that the distribution can produce. */
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return _intervals.front(); }
/** Returns the largest value that the distribution can produce. */
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return _intervals.back(); }
/**
* Returns a vector containing the probability densities
* at the interval boundaries.
*/
std::vector<RealType> densities() const
{
RealType sum = static_cast<RealType>(0);
for(std::size_t i = 0; i < _intervals.size() - 1; ++i) {
RealType width = _intervals[i + 1] - _intervals[i];
sum += (_weights[i] + _weights[i + 1]) * width / 2;
}
std::vector<RealType> result;
result.reserve(_weights.size());
for(typename std::vector<RealType>::const_iterator
iter = _weights.begin(), end = _weights.end();
iter != end; ++iter)
{
result.push_back(*iter / sum);
}
return result;
}
/** Returns a vector containing the interval boundaries. */
std::vector<RealType> intervals() const { return _intervals; }
/** Returns the parameters of the distribution. */
param_type param() const
{
return param_type(_intervals, _weights);
}
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
std::vector<RealType> new_intervals(parm._intervals);
std::vector<RealType> new_weights(parm._weights);
init(new_intervals, new_weights);
_intervals.swap(new_intervals);
_weights.swap(new_weights);
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { _bins.reset(); }
/** Writes a distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(
os, piecewise_linear_distribution, pld)
{
os << pld.param();
return os;
}
/** Reads a distribution from a @c std::istream */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(
is, piecewise_linear_distribution, pld)
{
param_type parm;
if(is >> parm) {
pld.param(parm);
}
return is;
}
/**
* Returns true if the two distributions will return the
* same sequence of values, when passed equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(
piecewise_linear_distribution, lhs, rhs)
{
return lhs._intervals == rhs._intervals && lhs._weights == rhs._weights;
}
/**
* Returns true if the two distributions may return different
* sequences of values, when passed equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(piecewise_linear_distribution)
private:
/// @cond \show_private
void init(const std::vector<RealType>& intervals_arg,
const std::vector<RealType>& weights_arg)
{
using std::abs;
std::vector<RealType> bin_weights;
bin_weights.reserve((intervals_arg.size() - 1) * 2);
for(std::size_t i = 0; i < intervals_arg.size() - 1; ++i) {
RealType width = intervals_arg[i + 1] - intervals_arg[i];
RealType w1 = weights_arg[i];
RealType w2 = weights_arg[i + 1];
bin_weights.push_back((std::min)(w1, w2) * width);
bin_weights.push_back(abs(w1 - w2) * width / 2);
}
typedef discrete_distribution<std::size_t, RealType> bins_type;
typename bins_type::param_type bins_param(bin_weights);
_bins.param(bins_param);
}
void init()
{
init(_intervals, _weights);
}
void default_init()
{
_intervals.clear();
_intervals.push_back(RealType(0));
_intervals.push_back(RealType(1));
_weights.clear();
_weights.push_back(RealType(1));
_weights.push_back(RealType(1));
init();
}
discrete_distribution<std::size_t, RealType> _bins;
std::vector<RealType> _intervals;
std::vector<RealType> _weights;
/// @endcond
};
}
}
#endif
@@ -0,0 +1,360 @@
/* boost random/poisson_distribution.hpp header file
*
* Copyright Jens Maurer 2002
* Copyright Steven Watanabe 2010
* 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_POISSON_DISTRIBUTION_HPP
#define BOOST_RANDOM_POISSON_DISTRIBUTION_HPP
#include <boost/config/no_tr1/cmath.hpp>
#include <cstdlib>
#include <iosfwd>
#include <boost/assert.hpp>
#include <boost/limits.hpp>
#include <boost/random/uniform_01.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/disable_warnings.hpp>
namespace boost {
namespace random {
namespace detail {
template<class RealType>
struct poisson_table {
static RealType value[10];
};
template<class RealType>
RealType poisson_table<RealType>::value[10] = {
0.0,
0.0,
0.69314718055994529,
1.7917594692280550,
3.1780538303479458,
4.7874917427820458,
6.5792512120101012,
8.5251613610654147,
10.604602902745251,
12.801827480081469
};
}
/**
* An instantiation of the class template @c poisson_distribution is a
* model of \random_distribution. The poisson distribution has
* \f$p(i) = \frac{e^{-\lambda}\lambda^i}{i!}\f$
*
* This implementation is based on the PTRD algorithm described
*
* @blockquote
* "The transformed rejection method for generating Poisson random variables",
* Wolfgang Hormann, Insurance: Mathematics and Economics
* Volume 12, Issue 1, February 1993, Pages 39-45
* @endblockquote
*/
template<class IntType = int, class RealType = double>
class poisson_distribution {
public:
typedef IntType result_type;
typedef RealType input_type;
class param_type {
public:
typedef poisson_distribution distribution_type;
/**
* Construct a param_type object with the parameter "mean"
*
* Requires: mean > 0
*/
explicit param_type(RealType mean_arg = RealType(1))
: _mean(mean_arg)
{
BOOST_ASSERT(_mean > 0);
}
/* Returns the "mean" parameter of the distribution. */
RealType mean() const { return _mean; }
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
/** Writes the parameters of the distribution to a @c std::ostream. */
template<class CharT, class Traits>
friend std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
const param_type& parm)
{
os << parm._mean;
return os;
}
/** Reads the parameters of the distribution from a @c std::istream. */
template<class CharT, class Traits>
friend std::basic_istream<CharT, Traits>&
operator>>(std::basic_istream<CharT, Traits>& is, param_type& parm)
{
is >> parm._mean;
return is;
}
#endif
/** Returns true if the parameters have the same values. */
friend bool operator==(const param_type& lhs, const param_type& rhs)
{
return lhs._mean == rhs._mean;
}
/** Returns true if the parameters have different values. */
friend bool operator!=(const param_type& lhs, const param_type& rhs)
{
return !(lhs == rhs);
}
private:
RealType _mean;
};
/**
* Constructs a @c poisson_distribution with the parameter @c mean.
*
* Requires: mean > 0
*/
explicit poisson_distribution(RealType mean_arg = RealType(1))
: _mean(mean_arg)
{
BOOST_ASSERT(_mean > 0);
init();
}
/**
* Construct an @c poisson_distribution object from the
* parameters.
*/
explicit poisson_distribution(const param_type& parm)
: _mean(parm.mean())
{
init();
}
/**
* Returns a random variate distributed according to the
* poisson distribution.
*/
template<class URNG>
IntType operator()(URNG& urng) const
{
if(use_inversion()) {
return invert(urng);
} else {
return generate(urng);
}
}
/**
* Returns a random variate distributed according to the
* poisson distribution with parameters specified by param.
*/
template<class URNG>
IntType operator()(URNG& urng, const param_type& parm) const
{
return poisson_distribution(parm)(urng);
}
/** Returns the "mean" parameter of the distribution. */
RealType mean() const { return _mean; }
/** Returns the smallest value that the distribution can produce. */
IntType min BOOST_PREVENT_MACRO_SUBSTITUTION() const { return 0; }
/** Returns the largest value that the distribution can produce. */
IntType max BOOST_PREVENT_MACRO_SUBSTITUTION() const
{ return (std::numeric_limits<IntType>::max)(); }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(_mean); }
/** Sets parameters of the distribution. */
void param(const param_type& parm)
{
_mean = parm.mean();
init();
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { }
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
/** Writes the parameters of the distribution to a @c std::ostream. */
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os,
const poisson_distribution& pd)
{
os << pd.param();
return os;
}
/** Reads the parameters of the distribution from a @c std::istream. */
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is, poisson_distribution& pd)
{
pd.read(is);
return is;
}
#endif
/** Returns true if the two distributions will produce the same
sequence of values, given equal generators. */
friend bool operator==(const poisson_distribution& lhs,
const poisson_distribution& rhs)
{
return lhs._mean == rhs._mean;
}
/** Returns true if the two distributions could produce different
sequences of values, given equal generators. */
friend bool operator!=(const poisson_distribution& lhs,
const poisson_distribution& rhs)
{
return !(lhs == rhs);
}
private:
/// @cond show_private
template<class CharT, class Traits>
void read(std::basic_istream<CharT, Traits>& is) {
param_type parm;
if(is >> parm) {
param(parm);
}
}
bool use_inversion() const
{
return _mean < 10;
}
static RealType log_factorial(IntType k)
{
BOOST_ASSERT(k >= 0);
BOOST_ASSERT(k < 10);
return detail::poisson_table<RealType>::value[k];
}
void init()
{
using std::sqrt;
using std::exp;
if(use_inversion()) {
_exp_mean = exp(-_mean);
} else {
_ptrd.smu = sqrt(_mean);
_ptrd.b = 0.931 + 2.53 * _ptrd.smu;
_ptrd.a = -0.059 + 0.02483 * _ptrd.b;
_ptrd.inv_alpha = 1.1239 + 1.1328 / (_ptrd.b - 3.4);
_ptrd.v_r = 0.9277 - 3.6224 / (_ptrd.b - 2);
}
}
template<class URNG>
IntType generate(URNG& urng) const
{
using std::floor;
using std::abs;
using std::log;
while(true) {
RealType u;
RealType v = uniform_01<RealType>()(urng);
if(v <= 0.86 * _ptrd.v_r) {
u = v / _ptrd.v_r - 0.43;
return static_cast<IntType>(floor(
(2*_ptrd.a/(0.5-abs(u)) + _ptrd.b)*u + _mean + 0.445));
}
if(v >= _ptrd.v_r) {
u = uniform_01<RealType>()(urng) - 0.5;
} else {
u = v/_ptrd.v_r - 0.93;
u = ((u < 0)? -0.5 : 0.5) - u;
v = uniform_01<RealType>()(urng) * _ptrd.v_r;
}
RealType us = 0.5 - abs(u);
if(us < 0.013 && v > us) {
continue;
}
RealType k = floor((2*_ptrd.a/us + _ptrd.b)*u+_mean+0.445);
v = v*_ptrd.inv_alpha/(_ptrd.a/(us*us) + _ptrd.b);
RealType log_sqrt_2pi = 0.91893853320467267;
if(k >= 10) {
if(log(v*_ptrd.smu) <= (k + 0.5)*log(_mean/k)
- _mean
- log_sqrt_2pi
+ k
- (1/12. - (1/360. - 1/(1260.*k*k))/(k*k))/k) {
return static_cast<IntType>(k);
}
} else if(k >= 0) {
if(log(v) <= k*log(_mean)
- _mean
- log_factorial(static_cast<IntType>(k))) {
return static_cast<IntType>(k);
}
}
}
}
template<class URNG>
IntType invert(URNG& urng) const
{
RealType p = _exp_mean;
IntType x = 0;
RealType u = uniform_01<RealType>()(urng);
while(u > p) {
u = u - p;
++x;
p = _mean * p / x;
}
return x;
}
RealType _mean;
union {
// for ptrd
struct {
RealType v_r;
RealType a;
RealType b;
RealType smu;
RealType inv_alpha;
} _ptrd;
// for inversion
RealType _exp_mean;
};
/// @endcond
};
} // namespace random
using random::poisson_distribution;
} // namespace boost
#include <boost/random/detail/enable_warnings.hpp>
#endif // BOOST_RANDOM_POISSON_DISTRIBUTION_HPP
@@ -0,0 +1,143 @@
/* boost random/random_device.hpp header file
*
* Copyright Jens Maurer 2000
* 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)
*
* $Id$
*
* Revision history
* 2000-02-18 Portability fixes (thanks to Beman Dawes)
*/
// See http://www.boost.org/libs/random for documentation.
#ifndef BOOST_RANDOM_RANDOM_DEVICE_HPP
#define BOOST_RANDOM_RANDOM_DEVICE_HPP
#include <string>
#include <boost/config.hpp>
#include <boost/noncopyable.hpp>
#include <boost/random/detail/auto_link.hpp>
#include <boost/system/config.hpp> // force autolink to find Boost.System
namespace boost {
namespace random {
/**
* Class \random_device models a \nondeterministic_random_number_generator.
* It uses one or more implementation-defined stochastic processes to
* generate a sequence of uniformly distributed non-deterministic random
* numbers. For those environments where a non-deterministic random number
* generator is not available, class random_device must not be implemented. See
*
* @blockquote
* "Randomness Recommendations for Security", D. Eastlake, S. Crocker,
* J. Schiller, Network Working Group, RFC 1750, December 1994
* @endblockquote
*
* for further discussions.
*
* @xmlnote
* Some operating systems abstract the computer hardware enough
* to make it difficult to non-intrusively monitor stochastic processes.
* However, several do provide a special device for exactly this purpose.
* It seems to be impossible to emulate the functionality using Standard
* C++ only, so users should be aware that this class may not be available
* on all platforms.
* @endxmlnote
*
* <b>Implementation Note for Linux</b>
*
* On the Linux operating system, token is interpreted as a filesystem
* path. It is assumed that this path denotes an operating system
* pseudo-device which generates a stream of non-deterministic random
* numbers. The pseudo-device should never signal an error or end-of-file.
* Otherwise, @c std::ios_base::failure is thrown. By default,
* \random_device uses the /dev/urandom pseudo-device to retrieve
* the random numbers. Another option would be to specify the /dev/random
* pseudo-device, which blocks on reads if the entropy pool has no more
* random bits available.
*
* <b>Implementation Note for Windows</b>
*
* On the Windows operating system, token is interpreted as the name
* of a cryptographic service provider. By default \random_device uses
* MS_DEF_PROV.
*
* <b>Performance</b>
*
* The test program <a href="\boost/libs/random/performance/nondet_random_speed.cpp">
* nondet_random_speed.cpp</a> measures the execution times of the
* random_device.hpp implementation of the above algorithms in a tight
* loop. The performance has been evaluated on an
* Intel(R) Core(TM) i7 CPU Q 840 \@ 1.87GHz, 1867 Mhz with
* Visual C++ 2010, Microsoft Windows 7 Professional and with gcc 4.4.5,
* Ubuntu Linux 2.6.35-25-generic.
*
* <table cols="2">
* <tr><th>Platform</th><th>time per invocation [microseconds]</th></tr>
* <tr><td> Windows </td><td>2.9</td></tr>
* <tr><td> Linux </td><td>1.7</td></tr>
* </table>
*
* The measurement error is estimated at +/- 1 usec.
*/
class random_device : private noncopyable
{
public:
typedef unsigned int result_type;
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
/** Returns the smallest value that the \random_device can produce. */
static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return 0; }
/** Returns the largest value that the \random_device can produce. */
static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () { return ~0u; }
/** Constructs a @c random_device, optionally using the default device. */
BOOST_RANDOM_DECL random_device();
/**
* Constructs a @c random_device, optionally using the given token as an
* access specification (for example, a URL) to some implementation-defined
* service for monitoring a stochastic process.
*/
BOOST_RANDOM_DECL explicit random_device(const std::string& token);
BOOST_RANDOM_DECL ~random_device();
/**
* Returns: An entropy estimate for the random numbers returned by
* operator(), in the range min() to log2( max()+1). A deterministic
* random number generator (e.g. a pseudo-random number engine)
* has entropy 0.
*
* Throws: Nothing.
*/
BOOST_RANDOM_DECL double entropy() const;
/** Returns a random value in the range [min, max]. */
BOOST_RANDOM_DECL unsigned int operator()();
/** Fills a range with random 32-bit values. */
template<class Iter>
void generate(Iter begin, Iter end)
{
for(; begin != end; ++begin) {
*begin = (*this)();
}
}
private:
class impl;
impl * pimpl;
};
} // namespace random
using random::random_device;
} // namespace boost
#endif /* BOOST_RANDOM_RANDOM_DEVICE_HPP */
@@ -0,0 +1,73 @@
/* boost random/random_number_generator.hpp header file
*
* Copyright Jens Maurer 2000-2001
* 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$
*
* Revision history
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_RANDOM_NUMBER_GENERATOR_HPP
#define BOOST_RANDOM_RANDOM_NUMBER_GENERATOR_HPP
#include <boost/assert.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/random/detail/disable_warnings.hpp>
namespace boost {
namespace random {
/**
* Instantiations of class template random_number_generator model a
* RandomNumberGenerator (std:25.2.11 [lib.alg.random.shuffle]). On
* each invocation, it returns a uniformly distributed integer in
* the range [0..n).
*
* The template parameter IntType shall denote some integer-like value type.
*/
template<class URNG, class IntType = long>
class random_number_generator
{
public:
typedef URNG base_type;
typedef IntType argument_type;
typedef IntType result_type;
/**
* Constructs a random_number_generator functor with the given
* \uniform_random_number_generator as the underlying source of
* random numbers.
*/
random_number_generator(base_type& rng) : _rng(rng) {}
// compiler-generated copy ctor is fine
// assignment is disallowed because there is a reference member
/**
* Returns a value in the range [0, n)
*/
result_type operator()(argument_type n)
{
BOOST_ASSERT(n > 0);
return uniform_int_distribution<IntType>(0, n-1)(_rng);
}
private:
base_type& _rng;
};
} // namespace random
using random::random_number_generator;
} // namespace boost
#include <boost/random/detail/enable_warnings.hpp>
#endif // BOOST_RANDOM_RANDOM_NUMBER_GENERATOR_HPP
@@ -0,0 +1,99 @@
/* boost random/ranlux.hpp header file
*
* Copyright Jens Maurer 2002
* 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$
*
* Revision history
* 2001-02-18 created
*/
#ifndef BOOST_RANDOM_RANLUX_HPP
#define BOOST_RANDOM_RANLUX_HPP
#include <boost/config.hpp>
#include <boost/random/subtract_with_carry.hpp>
#include <boost/random/discard_block.hpp>
namespace boost {
namespace random {
namespace detail {
/**
* The ranlux family of generators are described in
*
* @blockquote
* "A portable high-quality random number generator for lattice field theory
* calculations", M. Luescher, Computer Physics Communications, 79 (1994)
* pp 100-110.
* @endblockquote
*
* The levels are given in
*
* @blockquote
* "RANLUX: A Fortran implementation of the high-quality
* pseudorandom number generator of Luescher", F. James,
* Computer Physics Communications 79 (1994) 111-114
* @endblockquote
*/
class ranlux_documentation {};
}
typedef subtract_with_carry_engine<uint32_t, 24, 10, 24> ranlux_base;
typedef subtract_with_carry_01_engine<float, 24, 10, 24> ranlux_base_01;
typedef subtract_with_carry_01_engine<double, 48, 10, 24> ranlux64_base_01;
/** @copydoc boost::random::detail::ranlux_documentation */
typedef discard_block_engine<ranlux_base, 223, 24> ranlux3;
/** @copydoc boost::random::detail::ranlux_documentation */
typedef discard_block_engine<ranlux_base, 389, 24> ranlux4;
/** @copydoc boost::random::detail::ranlux_documentation */
typedef discard_block_engine<ranlux_base_01, 223, 24> ranlux3_01;
/** @copydoc boost::random::detail::ranlux_documentation */
typedef discard_block_engine<ranlux_base_01, 389, 24> ranlux4_01;
/** @copydoc boost::random::detail::ranlux_documentation */
typedef discard_block_engine<ranlux64_base_01, 223, 24> ranlux64_3_01;
/** @copydoc boost::random::detail::ranlux_documentation */
typedef discard_block_engine<ranlux64_base_01, 389, 24> ranlux64_4_01;
#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T)
typedef subtract_with_carry_engine<uint64_t, 48, 10, 24> ranlux64_base;
/** @copydoc boost::random::detail::ranlux_documentation */
typedef discard_block_engine<ranlux64_base, 223, 24> ranlux64_3;
/** @copydoc boost::random::detail::ranlux_documentation */
typedef discard_block_engine<ranlux64_base, 389, 24> ranlux64_4;
#endif /* !BOOST_NO_INT64_T && !BOOST_NO_INTEGRAL_INT64_T */
typedef subtract_with_carry_engine<uint32_t, 24, 10, 24> ranlux24_base;
typedef subtract_with_carry_engine<uint64_t, 48, 5, 12> ranlux48_base;
typedef discard_block_engine<ranlux24_base, 223, 23> ranlux24;
#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T)
typedef discard_block_engine<ranlux48_base, 389, 11> ranlux48;
#endif
}
using random::ranlux3;
using random::ranlux4;
using random::ranlux3_01;
using random::ranlux4_01;
using random::ranlux64_3_01;
using random::ranlux64_4_01;
#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T)
using random::ranlux64_3;
using random::ranlux64_4;
#endif
} // namespace boost
#endif // BOOST_RANDOM_LINEAR_CONGRUENTIAL_HPP
@@ -0,0 +1,118 @@
/* boost random/seed_seq.hpp header file
*
* Copyright Steven Watanabe 2010
* 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_SEED_SEQ_HPP
#define BOOST_RANDOM_SEED_SEQ_HPP
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <cstddef>
#include <vector>
#include <algorithm>
#include <iterator>
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
#include <initializer_list>
#endif
namespace boost {
namespace random {
/**
* The class @c seed_seq stores a sequence of 32-bit words
* for seeding a \pseudo_random_number_generator. These
* words will be combined to fill the entire state of the
* generator.
*/
class seed_seq {
public:
typedef boost::uint_least32_t result_type;
/** Initializes a seed_seq to hold an empty sequence. */
seed_seq() {}
#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
/** Initializes the sequence from an initializer_list. */
template<class T>
seed_seq(const std::initializer_list<T>& il) : v(il.begin(), il.end()) {}
#endif
/** Initializes the sequence from an iterator range. */
template<class Iter>
seed_seq(Iter first, Iter last) : v(first, last) {}
/** Initializes the sequence from Boost.Range range. */
template<class Range>
explicit seed_seq(const Range& range)
: v(boost::begin(range), boost::end(range)) {}
/**
* Fills a range with 32-bit values based on the stored sequence.
*
* Requires: Iter must be a Random Access Iterator whose value type
* is an unsigned integral type at least 32 bits wide.
*/
template<class Iter>
void generate(Iter first, Iter last) const
{
typedef typename std::iterator_traits<Iter>::value_type value_type;
std::fill(first, last, static_cast<value_type>(0x8b8b8b8bu));
std::size_t s = v.size();
std::size_t n = last - first;
std::size_t t =
(n >= 623) ? 11 :
(n >= 68) ? 7 :
(n >= 39) ? 5 :
(n >= 7) ? 3 :
(n - 1)/2;
std::size_t p = (n - t) / 2;
std::size_t q = p + t;
std::size_t m = (std::max)(s+1, n);
value_type mask = 0xffffffffu;
for(std::size_t k = 0; k < m; ++k) {
value_type r1 = static_cast<value_type>
(*(first + k%n) ^ *(first + (k+p)%n) ^ *(first + (k+n-1)%n));
r1 = r1 ^ (r1 >> 27);
r1 = (r1 * 1664525u) & mask;
value_type r2 = static_cast<value_type>(r1 +
((k == 0) ? s :
(k <= s) ? k % n + v[k - 1] :
(k % n)));
*(first + (k+p)%n) = (*(first + (k+p)%n) + r1) & mask;
*(first + (k+q)%n) = (*(first + (k+q)%n) + r2) & mask;
*(first + k%n) = r2;
}
for(std::size_t k = m; k < m + n; ++k) {
value_type r3 = static_cast<value_type>
((*(first + k%n) + *(first + (k+p)%n) + *(first + (k+n-1)%n))
& mask);
r3 = r3 ^ (r3 >> 27);
r3 = (r3 * 1566083941u) & mask;
value_type r4 = static_cast<value_type>(r3 - k%m);
*(first + (k+p)%n) ^= r3;
*(first + (k+q)%n) ^= r4;
*(first + k%n) = r4;
}
}
/** Returns the size of the sequence. */
std::size_t size() const { return v.size(); }
/** Writes the stored sequence to iter. */
template<class Iter>
void param(Iter out) { std::copy(v.begin(), v.end(), out); }
private:
std::vector<result_type> v;
};
}
}
#endif
@@ -0,0 +1,269 @@
/* boost random/shuffle_order.hpp header file
*
* Copyright Jens Maurer 2000-2001
* Copyright Steven Watanabe 2010
* 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_SHUFFLE_ORDER_HPP
#define BOOST_RANDOM_SHUFFLE_ORDER_HPP
#include <iostream>
#include <algorithm> // std::copy
#include <cassert>
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/static_assert.hpp>
#include <boost/cstdint.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/detail/seed.hpp>
#include <boost/random/detail/signed_unsigned_tools.hpp>
#include <boost/random/linear_congruential.hpp>
#include <boost/random/detail/disable_warnings.hpp>
namespace boost {
namespace random {
/**
* Instatiations of class template @c shuffle_order_engine model a
* \pseudo_random_number_generator. It mixes the output
* of some (usually \linear_congruential_engine)
* \uniform_random_number_generator to get better statistical properties.
* The algorithm is described in
*
* @blockquote
* "Improving a poor random number generator", Carter Bays
* and S.D. Durham, ACM Transactions on Mathematical Software,
* Vol 2, No. 1, March 1976, pp. 59-64.
* http://doi.acm.org/10.1145/355666.355670
* @endblockquote
*
* The output of the base generator is buffered in an array of
* length k. Every output X(n) has a second role: It gives an
* index into the array where X(n+1) will be retrieved. Used
* array elements are replaced with fresh output from the base
* generator.
*
* Template parameters are the base generator and the array
* length k, which should be around 100.
*/
template<class UniformRandomNumberGenerator, std::size_t k>
class shuffle_order_engine
{
public:
typedef UniformRandomNumberGenerator base_type;
typedef typename base_type::result_type result_type;
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
BOOST_STATIC_CONSTANT(std::size_t, buffer_size = k);
BOOST_STATIC_CONSTANT(std::size_t, table_size = k);
BOOST_STATIC_ASSERT(std::numeric_limits<result_type>::is_integer);
BOOST_STATIC_ASSERT(k > 0);
/**
* Constructs a @c shuffle_order_engine by invoking the
* default constructor of the base generator.
*
* Complexity: Exactly k+1 invocations of the base generator.
*/
shuffle_order_engine() : _rng() { init(); }
/**
* Constructs a @c shuffle_output_engine by invoking the one-argument
* constructor of the base generator with the parameter seed.
*
* Complexity: Exactly k+1 invocations of the base generator.
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(shuffle_order_engine,
result_type, s)
{ _rng.seed(s); init(); }
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(shuffle_order_engine, SeedSeq, seq)
{ _rng.seed(seq); init(); }
/**
* Constructs a @c shuffle_output_engine by using a copy
* of the provided generator.
*
* Precondition: The template argument UniformRandomNumberGenerator
* shall denote a CopyConstructible type.
*
* Complexity: Exactly k+1 invocations of the base generator.
*/
explicit shuffle_order_engine(const base_type & rng) : _rng(rng) { init(); }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
explicit shuffle_order_engine(base_type&& rng) : _rng(rng) { init(); }
#endif
template<class It> shuffle_order_engine(It& first, It last)
: _rng(first, last) { init(); }
void seed() { _rng.seed(); init(); }
/**
* Invokes the one-argument seed method of the base generator
* with the parameter seed and re-initializes the internal buffer array.
*
* Complexity: Exactly k+1 invocations of the base generator.
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(shuffle_order_engine,
result_type, seed_arg)
{ _rng.seed(seed_arg); init(); }
/**
* Invokes the one-argument seed method of the base generator
* with the parameter seq and re-initializes the internal buffer array.
*
* Complexity: Exactly k+1 invocations of the base generator.
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(shuffle_order_engine, SeedSeq, seq)
{ _rng.seed(seq); init(); }
template<class It> void seed(It& first, It last)
{ _rng.seed(first, last); init(); }
const base_type& base() const { return _rng; }
result_type operator()() {
// calculating the range every time may seem wasteful. However, this
// makes the information locally available for the optimizer.
typedef typename boost::random::traits::make_unsigned<result_type>::type base_unsigned;
const base_unsigned brange =
detail::subtract<result_type>()((max)(), (min)());
const base_unsigned off =
detail::subtract<result_type>()(y, (min)());
base_unsigned j;
if(k == 1) {
j = 0;
} else if(brange < (std::numeric_limits<base_unsigned>::max)() / k) {
// try to do it in the native type if we know that it won't
// overflow
j = k * off / (brange + 1);
} else if(brange < (std::numeric_limits<uintmax_t>::max)() / k) {
// Otherwise try to use uint64_t
j = static_cast<base_unsigned>(
static_cast<uintmax_t>(off) * k /
(static_cast<uintmax_t>(brange) + 1));
} else {
boost::uintmax_t divisor =
static_cast<boost::uintmax_t>(brange) + 1;
j = static_cast<base_unsigned>(detail::muldiv(off, k, divisor));
}
// assert(0 <= j && j < k);
y = v[j];
v[j] = _rng();
return y;
}
/** Advances the generator by z steps. */
void discard(boost::uintmax_t z)
{
for(boost::uintmax_t j = 0; j < z; ++j) {
(*this)();
}
}
/** Fills a range with pseudo-random values. */
template<class Iter>
void generate(Iter first, Iter last)
{ detail::generate_from_int(*this, first, last); }
/** Returns the smallest value that the generator can produce. */
static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return (base_type::min)(); }
/** Returns the largest value that the generator can produce. */
static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return (base_type::max)(); }
/** Writes a @c shuffle_order_engine to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, shuffle_order_engine, s)
{
os << s._rng;
for(std::size_t i = 0; i < k; ++i)
os << ' ' << s.v[i];
os << ' ' << s.y;
return os;
}
/** Reads a @c shuffle_order_engine from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, shuffle_order_engine, s)
{
is >> s._rng;
for(std::size_t i = 0; i < k; ++i)
is >> std::ws >> s.v[i];
is >> std::ws >> s.y;
return is;
}
/** Returns true if the two generators will produce identical sequences. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(shuffle_order_engine, x, y)
{ return x._rng == y._rng && x.y == y.y && std::equal(x.v, x.v+k, y.v); }
/** Returns true if the two generators will produce different sequences. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(shuffle_order_engine)
private:
/// \cond show_private
void init()
{
// we cannot use std::generate, because it uses pass-by-value for _rng
for(result_type * p = v; p != v+k; ++p)
*p = _rng();
y = _rng();
}
/// \endcond
base_type _rng;
result_type v[k];
result_type y;
};
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
// A definition is required even for integral static constants
template<class URNG, std::size_t k>
const bool shuffle_order_engine<URNG, k>::has_fixed_range;
template<class URNG, std::size_t k>
const std::size_t shuffle_order_engine<URNG, k>::table_size;
template<class URNG, std::size_t k>
const std::size_t shuffle_order_engine<URNG, k>::buffer_size;
#endif
/**
* According to Harry Erwin (private e-mail), the specialization
* @c kreutzer1986 was suggested in:
*
* @blockquote
* "System Simulation: Programming Styles and Languages (International
* Computer Science Series)", Wolfgang Kreutzer, Addison-Wesley, December 1986.
* @endblockquote
*/
typedef shuffle_order_engine<
linear_congruential_engine<uint32_t, 1366, 150889, 714025>,
97> kreutzer1986;
/**
* The specialization @c knuth_b is specified by the C++ standard.
* It is described in
*
* @blockquote
* "The Art of Computer Programming, Second Edition, Volume 2,
* Seminumerical Algorithms", Donald Knuth, Addison-Wesley, 1981.
* @endblockquote
*/
typedef shuffle_order_engine<minstd_rand0, 256> knuth_b;
} // namespace random
using random::kreutzer1986;
} // namespace boost
#include <boost/random/detail/enable_warnings.hpp>
#endif // BOOST_RANDOM_SHUFFLE_OUTPUT_HPP
@@ -0,0 +1,51 @@
/* boost random/shuffle_output.hpp header file
*
* Copyright Jens Maurer 2000-2001
* 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$
*
* Revision history
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_SHUFFLE_OUTPUT_HPP
#define BOOST_RANDOM_SHUFFLE_OUTPUT_HPP
#include <boost/random/shuffle_order.hpp>
namespace boost {
namespace random {
/// \cond
template<typename URNG, int k,
typename URNG::result_type val = 0>
class shuffle_output : public shuffle_order_engine<URNG, k>
{
typedef shuffle_order_engine<URNG, k> base_t;
public:
typedef typename base_t::result_type result_type;
shuffle_output() {}
template<class T>
explicit shuffle_output(T& arg) : base_t(arg) {}
template<class T>
explicit shuffle_output(const T& arg) : base_t(arg) {}
template<class It>
shuffle_output(It& first, It last) : base_t(first, last) {}
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return (this->base().min)(); }
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return (this->base().max)(); }
};
/// \endcond
}
}
#endif // BOOST_RANDOM_SHUFFLE_OUTPUT_HPP
@@ -0,0 +1,180 @@
/* boost random/student_t_distribution.hpp header file
*
* Copyright Steven Watanabe 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_STUDENT_T_DISTRIBUTION_HPP
#define BOOST_RANDOM_STUDENT_T_DISTRIBUTION_HPP
#include <boost/config/no_tr1/cmath.hpp>
#include <iosfwd>
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/chi_squared_distribution.hpp>
#include <boost/random/normal_distribution.hpp>
namespace boost {
namespace random {
/**
* The Student t distribution is a real valued distribution with one
* parameter n, the number of degrees of freedom.
*
* It has \f$\displaystyle p(x) =
* \frac{1}{\sqrt{n\pi}}
* \frac{\Gamma((n+1)/2)}{\Gamma(n/2)}
* \left(1+\frac{x^2}{n}\right)^{-(n+1)/2}
* \f$.
*/
template<class RealType = double>
class student_t_distribution {
public:
typedef RealType result_type;
typedef RealType input_type;
class param_type {
public:
typedef student_t_distribution distribution_type;
/**
* Constructs a @c param_type with "n" degrees of freedom.
*
* Requires: n > 0
*/
explicit param_type(RealType n_arg = RealType(1.0))
: _n(n_arg)
{}
/** Returns the number of degrees of freedom of the distribution. */
RealType n() const { return _n; }
/** Writes a @c param_type to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{ os << parm._n; return os; }
/** Reads a @c param_type from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{ is >> parm._n; return is; }
/** Returns true if the two sets of parameters are the same. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._n == rhs._n; }
/** Returns true if the two sets of parameters are the different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
RealType _n;
};
/**
* Constructs an @c student_t_distribution with "n" degrees of freedom.
*
* Requires: n > 0
*/
explicit student_t_distribution(RealType n_arg = RealType(1.0))
: _normal(), _chi_squared(n_arg)
{}
/** Constructs an @c student_t_distribution from its parameters. */
explicit student_t_distribution(const param_type& parm)
: _normal(), _chi_squared(parm.n())
{}
/**
* Returns a random variate distributed according to the
* Student t distribution.
*/
template<class URNG>
RealType operator()(URNG& urng)
{
using std::sqrt;
return _normal(urng) / sqrt(_chi_squared(urng) / n());
}
/**
* Returns a random variate distributed accordint to the Student
* t distribution with parameters specified by @c param.
*/
template<class URNG>
RealType operator()(URNG& urng, const param_type& parm) const
{
return student_t_distribution(parm)(urng);
}
/** Returns the number of degrees of freedom. */
RealType n() const { return _chi_squared.n(); }
/** Returns the smallest value that the distribution can produce. */
RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return -std::numeric_limits<RealType>::infinity(); }
/** Returns the largest value that the distribution can produce. */
RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return std::numeric_limits<RealType>::infinity(); }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(n()); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
typedef chi_squared_distribution<RealType> chi_squared_type;
typename chi_squared_type::param_type chi_squared_param(parm.n());
_chi_squared.param(chi_squared_param);
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset()
{
_normal.reset();
_chi_squared.reset();
}
/** Writes a @c student_t_distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, student_t_distribution, td)
{
os << td.param();
return os;
}
/** Reads a @c student_t_distribution from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, student_t_distribution, td)
{
param_type parm;
if(is >> parm) {
td.param(parm);
}
return is;
}
/**
* Returns true if the two instances of @c student_t_distribution will
* return identical sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(student_t_distribution, lhs, rhs)
{ return lhs._normal == rhs._normal && lhs._chi_squared == rhs._chi_squared; }
/**
* Returns true if the two instances of @c student_t_distribution will
* return different sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(student_t_distribution)
private:
normal_distribution<RealType> _normal;
chi_squared_distribution<RealType> _chi_squared;
};
} // namespace random
} // namespace boost
#endif // BOOST_RANDOM_STUDENT_T_DISTRIBUTION_HPP
@@ -0,0 +1,613 @@
/* boost random/subtract_with_carry.hpp header file
*
* Copyright Jens Maurer 2002
* 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$
*
* Revision history
* 2002-03-02 created
*/
#ifndef BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP
#define BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP
#include <boost/config/no_tr1/cmath.hpp> // std::pow
#include <iostream>
#include <algorithm> // std::equal
#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) {
// 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(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);
}
}
// 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
* described in
*
* @blockquote
* "A New Class of Random Number Generators", George
* Marsaglia and Arif Zaman, Annals of Applied Probability,
* Volume 1, Number 3 (1991), 462-480.
* @endblockquote
*/
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);
// Required by the old Boost.Random concepts
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
// Backwards compatibility
BOOST_STATIC_CONSTANT(result_type, modulus = (result_type(1) << w));
BOOST_STATIC_ASSERT(std::numeric_limits<result_type>::is_integer);
/**
* Constructs a new @c subtract_with_carry_engine and seeds
* it with the default seed.
*/
subtract_with_carry_engine() { seed(); }
/**
* Constructs a new @c subtract_with_carry_engine and seeds
* it with @c value.
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry_engine,
IntType, value)
{ seed(value); }
/**
* Constructs a new @c subtract_with_carry_engine and seeds
* it with values produced by @c seq.generate().
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(subtract_with_carry_engine,
SeedSeq, seq)
{ seed(seq); }
/**
* Constructs a new @c subtract_with_carry_engine and seeds
* it with values from a range. first is updated to point
* one past the last value consumed. If there are not
* enough elements in the range to fill the entire state of
* the generator, throws @c std::invalid_argument.
*/
template<class It> subtract_with_carry_engine(It& first, It last)
{ seed(first,last); }
// compiler-generated copy ctor and assignment operator are fine
/** Seeds the generator with the default seed. */
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);
}
/** Seeds the generator with values produced by @c seq.generate(). */
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;
}
/**
* Seeds the generator with values from a range. Updates @c first to
* point one past the last consumed value. If the range does not
* contain enough elements to fill the entire state of the generator,
* throws @c std::invalid_argument.
*/
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;
}
/** Returns the smallest value that the generator can produce. */
static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return 0; }
/** Returns the largest value that the generator can produce. */
static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return boost::low_bits_mask_t<w>::sig_bits; }
/** Returns the next value of the generator. */
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;
}
/** Advances the state of the generator by @c z. */
void discard(boost::uintmax_t z)
{
detail::subtract_with_carry_discard::apply(*this, z);
}
/** Fills a range with random values. */
template<class It>
void generate(It first, It last)
{ detail::generate_from_int(*this, first, last); }
/** Writes a @c subtract_with_carry_engine to a @c std::ostream. */
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;
}
/** Reads a @c subtract_with_carry_engine from a @c std::istream. */
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;
}
/**
* Returns true if the two generators will produce identical
* sequences of values.
*/
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;
}
/**
* Returns true if the two generators will produce different
* sequences of values.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(subtract_with_carry_engine)
private:
/// \cond show_private
// returns x(i-r+index), where index is in 0..r-1
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) {
// 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)
// x[0] ... x[k] x[k+1] ... x[long_lag-1] represents
// x(i-k) ... x(i) x(i+1) ... x(i-k+long_lag-1)
// speed: base: 20-25 nsec
// ranlux_4: 230 nsec, ranlux_7: 430 nsec, ranlux_14: 810 nsec
// This state representation makes operator== and save/restore more
// difficult, because we've already computed "too much" and thus
// have to undo some steps to get at x(i-r) etc.
// state representation: next output (state) is x(i)
// x[0] ... x[k] x[k+1] ... x[long_lag-1] represents
// x(i-k) ... x(i) x(i-long_lag+1) ... x(i-k-1)
// speed: base 28 nsec
// ranlux_4: 370 nsec, ranlux_7: 688 nsec, ranlux_14: 1343 nsec
IntType x[long_lag];
std::size_t k;
IntType carry;
};
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
// A definition is required even for integral static constants
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
// use a floating-point representation to produce values in [0..1)
/**
* Instantiations of \subtract_with_carry_01_engine model a
* \pseudo_random_number_generator. The algorithm is
* described in
*
* @blockquote
* "A New Class of Random Number Generators", George
* Marsaglia and Arif Zaman, Annals of Applied Probability,
* Volume 1, Number 3 (1991), 462-480.
* @endblockquote
*/
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);
/** Creates a new \subtract_with_carry_01_engine using the default seed. */
subtract_with_carry_01_engine() { init_modulus(); seed(); }
/** Creates a new subtract_with_carry_01_engine and seeds it with value. */
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry_01_engine,
boost::uint32_t, value)
{ init_modulus(); seed(value); }
/**
* Creates a new \subtract_with_carry_01_engine and seeds with values
* produced by seq.generate().
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(subtract_with_carry_01_engine,
SeedSeq, seq)
{ init_modulus(); seed(seq); }
/**
* Creates a new \subtract_with_carry_01_engine and seeds it with values
* from a range. Advances first to point one past the last consumed
* value. If the range does not contain enough elements to fill the
* entire state, throws @c std::invalid_argument.
*/
template<class It> subtract_with_carry_01_engine(It& first, It last)
{ init_modulus(); seed(first,last); }
private:
/// \cond show_private
void init_modulus()
{
#ifndef BOOST_NO_STDC_NAMESPACE
// allow for Koenig lookup
using std::pow;
#endif
_modulus = pow(RealType(2), RealType(word_size));
}
/// \endcond
public:
// compiler-generated copy ctor and assignment operator are fine
/** Seeds the generator with the default seed. */
void seed() { seed(default_seed); }
/** Seeds the generator with @c value. */
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);
}
/** Seeds the generator with values produced by @c seq.generate(). */
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;
}
/**
* Seeds the generator with values from a range. Updates first to
* point one past the last consumed element. If there are not
* enough elements in the range to fill the entire state, throws
* @c std::invalid_argument.
*/
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;
}
/** Returns the smallest value that the generator can produce. */
static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return result_type(0); }
/** Returns the largest value that the generator can produce. */
static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
{ return result_type(1); }
/** Returns the next value of the generator. */
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;
}
/** Advances the state of the generator by @c z. */
void discard(boost::uintmax_t z)
{ detail::subtract_with_carry_discard::apply(*this, z); }
/** Fills a range with random values. */
template<class Iter>
void generate(Iter first, Iter last)
{ detail::generate_from_real(*this, first, last); }
/** Writes a \subtract_with_carry_01_engine to a @c std::ostream. */
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;
}
/** Reads a \subtract_with_carry_01_engine from a @c std::istream. */
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;
}
/** Returns true if the two generators will produce identical sequences. */
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;
}
/** Returns true if the two generators will produce different sequences. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(subtract_with_carry_01_engine)
private:
/// \cond show_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;
}
/// \endcond
std::size_t k;
RealType carry;
RealType x[long_lag];
RealType _modulus;
};
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
// A definition is required even for integral static constants
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
/// \cond show_deprecated
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); }
};
/// \endcond
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; }
};
}
} // namespace random
} // namespace boost
#endif // BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP
@@ -0,0 +1,45 @@
/* boost random/taus88.hpp header file
*
* Copyright Jens Maurer 2000-2001
* Copyright Steven Watanabe 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/libs/random for documentation.
*
* $Id$
*
*/
#ifndef BOOST_RANDOM_TAUS88_HPP
#define BOOST_RANDOM_TAUS88_HPP
#include <boost/random/linear_feedback_shift.hpp>
#include <boost/random/xor_combine.hpp>
namespace boost {
namespace random {
/**
* The specialization taus88 was suggested in
*
* @blockquote
* "Maximally Equidistributed Combined Tausworthe Generators",
* Pierre L'Ecuyer, Mathematics of Computation, Volume 65,
* Number 213, January 1996, Pages 203-213
* @endblockquote
*/
typedef xor_combine_engine<
xor_combine_engine<
linear_feedback_shift_engine<uint32_t, 32, 31, 13, 12>, 0,
linear_feedback_shift_engine<uint32_t, 32, 29, 2, 4>, 0>, 0,
linear_feedback_shift_engine<uint32_t, 32, 28, 3, 17>, 0> taus88;
} // namespace random
using random::taus88;
} // namespace boost
#endif // BOOST_RANDOM_TAUS88_HPP
@@ -0,0 +1,107 @@
/* boost random/traits.hpp header file
*
* Copyright John Maddock 2015
* 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.
*
* These traits classes serve two purposes: they are designed to mostly
* work out of the box for multiprecision types (ie number types that are
* C++ class types and not integers or floats from type-traits point of view),
* they are also a potential point of specialization for user-defined
* number types.
*
* $Id$
*/
#ifndef BOOST_RANDOM_TRAITS_HPP
#define BOOST_RANDOM_TRAITS_HPP
#include <boost/type_traits/is_signed.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/make_unsigned.hpp>
#include <boost/mpl/bool.hpp>
#include <limits>
namespace boost {
namespace random {
namespace traits {
// \cond show_private
template <class T, bool intrinsic>
struct make_unsigned_imp
{
typedef typename boost::make_unsigned<T>::type type;
};
template <class T>
struct make_unsigned_imp<T, false>
{
BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_signed == false);
BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_integer == true);
typedef T type;
};
// \endcond
/** \brief Converts the argument type T to an unsigned type.
*
* This trait has a single member `type` which is the unsigned type corresponding to T.
* Note that
* if T is signed, then member `type` *should define a type with one more bit precision than T*. For built-in
* types this trait defaults to `boost::make_unsigned<T>::type`. For user defined types it simply asserts that
* the argument type T is an unsigned integer (using std::numeric_limits).
* User defined specializations may be provided for other cases.
*/
template <class T>
struct make_unsigned
// \cond show_private
: public make_unsigned_imp < T, boost::is_integral<T>::value >
// \endcond
{};
// \cond show_private
template <class T, bool intrinsic>
struct make_unsigned_or_unbounded_imp
{
typedef typename boost::make_unsigned<T>::type type;
};
template <class T>
struct make_unsigned_or_unbounded_imp<T, false>
{
BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
BOOST_STATIC_ASSERT((std::numeric_limits<T>::is_signed == false) || (std::numeric_limits<T>::is_bounded == false));
BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_integer == true);
typedef T type;
};
// \endcond
/** \brief Converts the argument type T to either an unsigned type or an unbounded integer type.
*
* This trait has a single member `type` which is either the unsigned type corresponding to T or an unbounded
* integer type. This trait is used to generate types suitable for the calculation of a range: as a result
* if T is signed, then member `type` *should define a type with one more bit precision than T*. For built-in
* types this trait defaults to `boost::make_unsigned<T>::type`. For user defined types it simply asserts that
* the argument type T is either an unbounded integer, or an unsigned one (using std::numeric_limits).
* User defined specializations may be provided for other cases.
*/
template <class T>
struct make_unsigned_or_unbounded
// \cond show_private
: public make_unsigned_or_unbounded_imp < T, boost::is_integral<T>::value >
// \endcond
{};
/** \brief Traits class that indicates whether type T is an integer
*/
template <class T>
struct is_integral
: public mpl::bool_<boost::is_integral<T>::value || (std::numeric_limits<T>::is_integer)>
{};
/** \brief Traits class that indicates whether type T is a signed integer
*/
template <class T> struct is_signed
: public mpl::bool_ < boost::is_signed<T>::value || (std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed)>
{};
}
}
}
#endif
@@ -0,0 +1,232 @@
/* boost random/triangle_distribution.hpp header file
*
* Copyright Jens Maurer 2000-2001
* Copyright Steven Watanabe 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$
*
* Revision history
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_TRIANGLE_DISTRIBUTION_HPP
#define BOOST_RANDOM_TRIANGLE_DISTRIBUTION_HPP
#include <boost/config/no_tr1/cmath.hpp>
#include <iosfwd>
#include <ios>
#include <istream>
#include <boost/assert.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/uniform_01.hpp>
namespace boost {
namespace random {
/**
* Instantiations of @c triangle_distribution model a \random_distribution.
* A @c triangle_distribution has three parameters, @c a, @c b, and @c c,
* which are the smallest, the most probable and the largest values of
* the distribution respectively.
*/
template<class RealType = double>
class triangle_distribution
{
public:
typedef RealType input_type;
typedef RealType result_type;
class param_type
{
public:
typedef triangle_distribution distribution_type;
/** Constructs the parameters of a @c triangle_distribution. */
explicit param_type(RealType a_arg = RealType(0.0),
RealType b_arg = RealType(0.5),
RealType c_arg = RealType(1.0))
: _a(a_arg), _b(b_arg), _c(c_arg)
{
BOOST_ASSERT(_a <= _b && _b <= _c);
}
/** Returns the minimum value of the distribution. */
RealType a() const { return _a; }
/** Returns the mode of the distribution. */
RealType b() const { return _b; }
/** Returns the maximum value of the distribution. */
RealType c() const { return _c; }
/** Writes the parameters to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{
os << parm._a << " " << parm._b << " " << parm._c;
return os;
}
/** Reads the parameters from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{
double a_in, b_in, c_in;
if(is >> a_in >> std::ws >> b_in >> std::ws >> c_in) {
if(a_in <= b_in && b_in <= c_in) {
parm._a = a_in;
parm._b = b_in;
parm._c = c_in;
} else {
is.setstate(std::ios_base::failbit);
}
}
return is;
}
/** Returns true if the two sets of parameters are equal. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._a == rhs._a && lhs._b == rhs._b && lhs._c == rhs._c; }
/** Returns true if the two sets of parameters are different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
RealType _a;
RealType _b;
RealType _c;
};
/**
* Constructs a @c triangle_distribution with the parameters
* @c a, @c b, and @c c.
*
* Preconditions: a <= b <= c.
*/
explicit triangle_distribution(RealType a_arg = RealType(0.0),
RealType b_arg = RealType(0.5),
RealType c_arg = RealType(1.0))
: _a(a_arg), _b(b_arg), _c(c_arg)
{
BOOST_ASSERT(_a <= _b && _b <= _c);
init();
}
/** Constructs a @c triangle_distribution from its parameters. */
explicit triangle_distribution(const param_type& parm)
: _a(parm.a()), _b(parm.b()), _c(parm.c())
{
init();
}
// compiler-generated copy ctor and assignment operator are fine
/** Returns the @c a parameter of the distribution */
result_type a() const { return _a; }
/** Returns the @c b parameter of the distribution */
result_type b() const { return _b; }
/** Returns the @c c parameter of the distribution */
result_type c() const { return _c; }
/** Returns the smallest value that the distribution can produce. */
RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _a; }
/** Returns the largest value that the distribution can produce. */
RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _c; }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(_a, _b, _c); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
_a = parm.a();
_b = parm.b();
_c = parm.c();
init();
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { }
/**
* Returns a random variate distributed according to the
* triangle distribution.
*/
template<class Engine>
result_type operator()(Engine& eng)
{
using std::sqrt;
result_type u = uniform_01<result_type>()(eng);
if( u <= q1 )
return _a + p1*sqrt(u);
else
return _c - d3*sqrt(d2*u-d1);
}
/**
* Returns a random variate distributed according to the
* triangle distribution with parameters specified by param.
*/
template<class Engine>
result_type operator()(Engine& eng, const param_type& parm)
{ return triangle_distribution(parm)(eng); }
/** Writes the distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, triangle_distribution, td)
{
os << td.param();
return os;
}
/** Reads the distribution from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, triangle_distribution, td)
{
param_type parm;
if(is >> parm) {
td.param(parm);
}
return is;
}
/**
* Returns true if the two distributions will produce identical
* sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(triangle_distribution, lhs, rhs)
{ return lhs._a == rhs._a && lhs._b == rhs._b && lhs._c == rhs._c; }
/**
* Returns true if the two distributions may produce different
* sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(triangle_distribution)
private:
/// \cond show_private
void init()
{
using std::sqrt;
d1 = _b - _a;
d2 = _c - _a;
d3 = sqrt(_c - _b);
q1 = d1 / d2;
p1 = sqrt(d1 * d2);
}
/// \endcond
RealType _a, _b, _c;
RealType d1, d2, d3, q1, p1;
};
} // namespace random
using random::triangle_distribution;
} // namespace boost
#endif // BOOST_RANDOM_TRIANGLE_DISTRIBUTION_HPP
@@ -0,0 +1,257 @@
/* boost random/uniform_01.hpp header file
*
* Copyright Jens Maurer 2000-2001
* 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$
*
* Revision history
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_UNIFORM_01_HPP
#define BOOST_RANDOM_UNIFORM_01_HPP
#include <iostream>
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/static_assert.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/ptr_helper.hpp>
#include <boost/random/detail/disable_warnings.hpp>
namespace boost {
namespace random {
#ifdef BOOST_RANDOM_DOXYGEN
/**
* The distribution function uniform_01 models a \random_distribution.
* On each invocation, it returns a random floating-point value
* uniformly distributed in the range [0..1).
*
* The template parameter RealType shall denote a float-like value type
* with support for binary operators +, -, and /.
*
* Note: The current implementation is buggy, because it may not fill
* all of the mantissa with random bits. I'm unsure how to fill a
* (to-be-invented) @c boost::bigfloat class with random bits efficiently.
* It's probably time for a traits class.
*/
template<class RealType = double>
class uniform_01
{
public:
typedef RealType input_type;
typedef RealType result_type;
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const;
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const;
void reset();
template<class Engine>
result_type operator()(Engine& eng);
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os, const new_uniform_01&)
{
return os;
}
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is, new_uniform_01&)
{
return is;
}
#endif
};
#else
namespace detail {
template<class RealType>
class new_uniform_01
{
public:
typedef RealType input_type;
typedef RealType result_type;
// compiler-generated copy ctor and copy assignment are fine
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return result_type(0); }
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return result_type(1); }
void reset() { }
template<class Engine>
result_type operator()(Engine& eng) {
for (;;) {
typedef typename Engine::result_type base_result;
result_type factor = result_type(1) /
(result_type(base_result((eng.max)()-(eng.min)())) +
result_type(std::numeric_limits<base_result>::is_integer ? 1 : 0));
result_type result = result_type(base_result(eng() - (eng.min)())) * factor;
if (result < result_type(1))
return result;
}
}
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os, const new_uniform_01&)
{
return os;
}
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is, new_uniform_01&)
{
return is;
}
#endif
};
template<class UniformRandomNumberGenerator, class RealType>
class backward_compatible_uniform_01
{
typedef boost::random::detail::ptr_helper<UniformRandomNumberGenerator> traits;
public:
typedef UniformRandomNumberGenerator base_type;
typedef RealType result_type;
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS)
BOOST_STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer);
#endif
explicit backward_compatible_uniform_01(typename traits::rvalue_type rng)
: _rng(rng),
_factor(result_type(1) /
(result_type((base().max)()-(base().min)()) +
result_type(std::numeric_limits<base_result>::is_integer ? 1 : 0)))
{
}
// compiler-generated copy ctor and copy assignment are fine
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return result_type(0); }
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return result_type(1); }
typename traits::value_type& base() { return traits::ref(_rng); }
const typename traits::value_type& base() const { return traits::ref(_rng); }
void reset() { }
result_type operator()() {
for (;;) {
result_type result = result_type(base()() - (base().min)()) * _factor;
if (result < result_type(1))
return result;
}
}
#if !defined(BOOST_NO_OPERATORS_IN_NAMESPACE) && !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os, const backward_compatible_uniform_01& u)
{
os << u._rng;
return os;
}
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is, backward_compatible_uniform_01& u)
{
is >> u._rng;
return is;
}
#endif
private:
typedef typename traits::value_type::result_type base_result;
UniformRandomNumberGenerator _rng;
result_type _factor;
};
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
// A definition is required even for integral static constants
template<class UniformRandomNumberGenerator, class RealType>
const bool backward_compatible_uniform_01<UniformRandomNumberGenerator, RealType>::has_fixed_range;
#endif
template<class UniformRandomNumberGenerator, bool is_number = std::numeric_limits<UniformRandomNumberGenerator>::is_specialized>
struct select_uniform_01
{
template<class RealType>
struct apply
{
typedef backward_compatible_uniform_01<UniformRandomNumberGenerator, RealType> type;
};
};
template<class Num>
struct select_uniform_01<Num, true>
{
template<class RealType>
struct apply
{
typedef new_uniform_01<Num> type;
};
};
}
// Because it is so commonly used: uniform distribution on the real [0..1)
// range. This allows for specializations to avoid a costly int -> float
// conversion plus float multiplication
template<class UniformRandomNumberGenerator = double, class RealType = double>
class uniform_01
: public detail::select_uniform_01<UniformRandomNumberGenerator>::BOOST_NESTED_TEMPLATE apply<RealType>::type
{
typedef typename detail::select_uniform_01<UniformRandomNumberGenerator>::BOOST_NESTED_TEMPLATE apply<RealType>::type impl_type;
typedef boost::random::detail::ptr_helper<UniformRandomNumberGenerator> traits;
public:
uniform_01() {}
explicit uniform_01(typename traits::rvalue_type rng)
: impl_type(rng)
{
}
#if !defined(BOOST_NO_OPERATORS_IN_NAMESPACE) && !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os, const uniform_01& u)
{
os << static_cast<const impl_type&>(u);
return os;
}
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is, uniform_01& u)
{
is >> static_cast<impl_type&>(u);
return is;
}
#endif
};
#endif
} // namespace random
using random::uniform_01;
} // namespace boost
#include <boost/random/detail/enable_warnings.hpp>
#endif // BOOST_RANDOM_UNIFORM_01_HPP
@@ -0,0 +1,99 @@
/* boost random/uniform_int.hpp header file
*
* Copyright Jens Maurer 2000-2001
* 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$
*
* Revision history
* 2001-04-08 added min<max assertion (N. Becker)
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_UNIFORM_INT_HPP
#define BOOST_RANDOM_UNIFORM_INT_HPP
#include <boost/assert.hpp>
#include <boost/random/uniform_int_distribution.hpp>
namespace boost {
/**
* The distribution function uniform_int models a \random_distribution.
* On each invocation, it returns a random integer value uniformly
* distributed in the set of integer numbers {min, min+1, min+2, ..., max}.
*
* The template parameter IntType shall denote an integer-like value type.
*
* This class is deprecated. Please use @c uniform_int_distribution in
* new code.
*/
template<class IntType = int>
class uniform_int : public random::uniform_int_distribution<IntType>
{
typedef random::uniform_int_distribution<IntType> base_type;
public:
class param_type : public base_type::param_type
{
public:
typedef uniform_int distribution_type;
/**
* Constructs the parameters of a uniform_int distribution.
*
* Requires: min <= max
*/
explicit param_type(IntType min_arg = 0, IntType max_arg = 9)
: base_type::param_type(min_arg, max_arg)
{}
};
/**
* Constructs a uniform_int object. @c min and @c max are
* the parameters of the distribution.
*
* Requires: min <= max
*/
explicit uniform_int(IntType min_arg = 0, IntType max_arg = 9)
: base_type(min_arg, max_arg)
{}
/** Constructs a uniform_int distribution from its parameters. */
explicit uniform_int(const param_type& parm)
: base_type(parm)
{}
/** Returns the parameters of the distribution */
param_type param() const { return param_type(this->a(), this->b()); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm) { this->base_type::param(parm); }
// Codergear seems to have trouble with a using declaration here
template<class Engine>
IntType operator()(Engine& eng) const
{
return static_cast<const base_type&>(*this)(eng);
}
template<class Engine>
IntType operator()(Engine& eng, const param_type& parm) const
{
return static_cast<const base_type&>(*this)(eng, parm);
}
template<class Engine>
IntType operator()(Engine& eng, IntType n) const
{
BOOST_ASSERT(n > 0);
return static_cast<const base_type&>(*this)(eng, param_type(0, n - 1));
}
};
} // namespace boost
#endif // BOOST_RANDOM_UNIFORM_INT_HPP
@@ -0,0 +1,419 @@
/* boost random/uniform_int_distribution.hpp header file
*
* Copyright Jens Maurer 2000-2001
* Copyright Steven Watanabe 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$
*
* Revision history
* 2001-04-08 added min<max assertion (N. Becker)
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP
#define BOOST_RANDOM_UNIFORM_INT_DISTRIBUTION_HPP
#include <iosfwd>
#include <ios>
#include <istream>
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/assert.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/detail/uniform_int_float.hpp>
#include <boost/random/detail/signed_unsigned_tools.hpp>
#include <boost/random/traits.hpp>
#include <boost/mpl/bool.hpp>
#ifdef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
#include <boost/mpl/if.hpp>
#endif
namespace boost {
namespace random {
namespace detail {
#ifdef BOOST_MSVC
#pragma warning(push)
// disable division by zero warning, since we can't
// actually divide by zero.
#pragma warning(disable:4723)
#endif
template<class Engine, class T>
T generate_uniform_int(
Engine& eng, T min_value, T max_value,
boost::mpl::true_ /** is_integral<Engine::result_type> */)
{
typedef T result_type;
typedef typename boost::random::traits::make_unsigned_or_unbounded<T>::type range_type;
typedef typename Engine::result_type base_result;
// ranges are always unsigned or unbounded
typedef typename boost::random::traits::make_unsigned_or_unbounded<base_result>::type base_unsigned;
const range_type range = random::detail::subtract<result_type>()(max_value, min_value);
const base_result bmin = (eng.min)();
const base_unsigned brange =
random::detail::subtract<base_result>()((eng.max)(), (eng.min)());
if(range == 0) {
return min_value;
} else if(brange == range) {
// this will probably never happen in real life
// basically nothing to do; just take care we don't overflow / underflow
base_unsigned v = random::detail::subtract<base_result>()(eng(), bmin);
return random::detail::add<base_unsigned, result_type>()(v, min_value);
} else if(brange < range) {
// use rejection method to handle things like 0..3 --> 0..4
for(;;) {
// concatenate several invocations of the base RNG
// take extra care to avoid overflows
// limit == floor((range+1)/(brange+1))
// Therefore limit*(brange+1) <= range+1
range_type limit;
if(range == (std::numeric_limits<range_type>::max)()) {
limit = range/(range_type(brange)+1);
if(range % (range_type(brange)+1) == range_type(brange))
++limit;
} else {
limit = (range+1)/(range_type(brange)+1);
}
// We consider "result" as expressed to base (brange+1):
// For every power of (brange+1), we determine a random factor
range_type result = range_type(0);
range_type mult = range_type(1);
// loop invariants:
// result < mult
// mult <= range
while(mult <= limit) {
// Postcondition: result <= range, thus no overflow
//
// limit*(brange+1)<=range+1 def. of limit (1)
// eng()-bmin<=brange eng() post. (2)
// and mult<=limit. loop condition (3)
// Therefore mult*(eng()-bmin+1)<=range+1 by (1),(2),(3) (4)
// Therefore mult*(eng()-bmin)+mult<=range+1 rearranging (4) (5)
// result<mult loop invariant (6)
// Therefore result+mult*(eng()-bmin)<range+1 by (5), (6) (7)
//
// Postcondition: result < mult*(brange+1)
//
// result<mult loop invariant (1)
// eng()-bmin<=brange eng() post. (2)
// Therefore result+mult*(eng()-bmin) <
// mult+mult*(eng()-bmin) by (1) (3)
// Therefore result+(eng()-bmin)*mult <
// mult+mult*brange by (2), (3) (4)
// Therefore result+(eng()-bmin)*mult <
// mult*(brange+1) by (4)
result += static_cast<range_type>(static_cast<range_type>(random::detail::subtract<base_result>()(eng(), bmin)) * mult);
// equivalent to (mult * (brange+1)) == range+1, but avoids overflow.
if(mult * range_type(brange) == range - mult + 1) {
// The destination range is an integer power of
// the generator's range.
return(result);
}
// Postcondition: mult <= range
//
// limit*(brange+1)<=range+1 def. of limit (1)
// mult<=limit loop condition (2)
// Therefore mult*(brange+1)<=range+1 by (1), (2) (3)
// mult*(brange+1)!=range+1 preceding if (4)
// Therefore mult*(brange+1)<range+1 by (3), (4) (5)
//
// Postcondition: result < mult
//
// See the second postcondition on the change to result.
mult *= range_type(brange)+range_type(1);
}
// loop postcondition: range/mult < brange+1
//
// mult > limit loop condition (1)
// Suppose range/mult >= brange+1 Assumption (2)
// range >= mult*(brange+1) by (2) (3)
// range+1 > mult*(brange+1) by (3) (4)
// range+1 > (limit+1)*(brange+1) by (1), (4) (5)
// (range+1)/(brange+1) > limit+1 by (5) (6)
// limit < floor((range+1)/(brange+1)) by (6) (7)
// limit==floor((range+1)/(brange+1)) def. of limit (8)
// not (2) reductio (9)
//
// loop postcondition: (range/mult)*mult+(mult-1) >= range
//
// (range/mult)*mult + range%mult == range identity (1)
// range%mult < mult def. of % (2)
// (range/mult)*mult+mult > range by (1), (2) (3)
// (range/mult)*mult+(mult-1) >= range by (3) (4)
//
// Note that the maximum value of result at this point is (mult-1),
// so after this final step, we generate numbers that can be
// at least as large as range. We have to really careful to avoid
// overflow in this final addition and in the rejection. Anything
// that overflows is larger than range and can thus be rejected.
// range/mult < brange+1 -> no endless loop
range_type result_increment =
generate_uniform_int(
eng,
static_cast<range_type>(0),
static_cast<range_type>(range/mult),
boost::mpl::true_());
if(std::numeric_limits<range_type>::is_bounded && ((std::numeric_limits<range_type>::max)() / mult < result_increment)) {
// The multiplcation would overflow. Reject immediately.
continue;
}
result_increment *= mult;
// unsigned integers are guaranteed to wrap on overflow.
result += result_increment;
if(result < result_increment) {
// The addition overflowed. Reject.
continue;
}
if(result > range) {
// Too big. Reject.
continue;
}
return random::detail::add<range_type, result_type>()(result, min_value);
}
} else { // brange > range
#ifdef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
typedef typename mpl::if_c<
std::numeric_limits<range_type>::is_specialized && std::numeric_limits<base_unsigned>::is_specialized
&& (std::numeric_limits<range_type>::digits >= std::numeric_limits<base_unsigned>::digits),
range_type, base_unsigned>::type mixed_range_type;
#else
typedef base_unsigned mixed_range_type;
#endif
mixed_range_type bucket_size;
// it's safe to add 1 to range, as long as we cast it first,
// because we know that it is less than brange. However,
// we do need to be careful not to cause overflow by adding 1
// to brange. We use mixed_range_type throughout for mixed
// arithmetic between base_unsigned and range_type - in the case
// that range_type has more bits than base_unsigned it is always
// safe to use range_type for this albeit it may be more effient
// to use base_unsigned. The latter is a narrowing conversion though
// which may be disallowed if range_type is a multiprecision type
// and there are no explicit converison operators.
if(brange == (std::numeric_limits<base_unsigned>::max)()) {
bucket_size = static_cast<mixed_range_type>(brange) / (static_cast<mixed_range_type>(range)+1);
if(static_cast<mixed_range_type>(brange) % (static_cast<mixed_range_type>(range)+1) == static_cast<mixed_range_type>(range)) {
++bucket_size;
}
} else {
bucket_size = static_cast<mixed_range_type>(brange + 1) / (static_cast<mixed_range_type>(range)+1);
}
for(;;) {
mixed_range_type result =
random::detail::subtract<base_result>()(eng(), bmin);
result /= bucket_size;
// result and range are non-negative, and result is possibly larger
// than range, so the cast is safe
if(result <= static_cast<mixed_range_type>(range))
return random::detail::add<mixed_range_type, result_type>()(result, min_value);
}
}
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
template<class Engine, class T>
inline T generate_uniform_int(
Engine& eng, T min_value, T max_value,
boost::mpl::false_ /** is_integral<Engine::result_type> */)
{
uniform_int_float<Engine> wrapper(eng);
return generate_uniform_int(wrapper, min_value, max_value, boost::mpl::true_());
}
template<class Engine, class T>
inline T generate_uniform_int(Engine& eng, T min_value, T max_value)
{
typedef typename Engine::result_type base_result;
return generate_uniform_int(eng, min_value, max_value,
boost::random::traits::is_integral<base_result>());
}
}
/**
* The class template uniform_int_distribution models a \random_distribution.
* On each invocation, it returns a random integer value uniformly
* distributed in the set of integers {min, min+1, min+2, ..., max}.
*
* The template parameter IntType shall denote an integer-like value type.
*/
template<class IntType = int>
class uniform_int_distribution
{
public:
typedef IntType input_type;
typedef IntType result_type;
class param_type
{
public:
typedef uniform_int_distribution distribution_type;
/**
* Constructs the parameters of a uniform_int_distribution.
*
* Requires min <= max
*/
explicit param_type(
IntType min_arg = 0,
IntType max_arg = (std::numeric_limits<IntType>::max)())
: _min(min_arg), _max(max_arg)
{
BOOST_ASSERT(_min <= _max);
}
/** Returns the minimum value of the distribution. */
IntType a() const { return _min; }
/** Returns the maximum value of the distribution. */
IntType b() const { return _max; }
/** Writes the parameters to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{
os << parm._min << " " << parm._max;
return os;
}
/** Reads the parameters from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{
IntType min_in, max_in;
if(is >> min_in >> std::ws >> max_in) {
if(min_in <= max_in) {
parm._min = min_in;
parm._max = max_in;
} else {
is.setstate(std::ios_base::failbit);
}
}
return is;
}
/** Returns true if the two sets of parameters are equal. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._min == rhs._min && lhs._max == rhs._max; }
/** Returns true if the two sets of parameters are different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
IntType _min;
IntType _max;
};
/**
* Constructs a uniform_int_distribution. @c min and @c max are
* the parameters of the distribution.
*
* Requires: min <= max
*/
explicit uniform_int_distribution(
IntType min_arg = 0,
IntType max_arg = (std::numeric_limits<IntType>::max)())
: _min(min_arg), _max(max_arg)
{
BOOST_ASSERT(min_arg <= max_arg);
}
/** Constructs a uniform_int_distribution from its parameters. */
explicit uniform_int_distribution(const param_type& parm)
: _min(parm.a()), _max(parm.b()) {}
/** Returns the minimum value of the distribution */
IntType min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; }
/** Returns the maximum value of the distribution */
IntType max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; }
/** Returns the minimum value of the distribution */
IntType a() const { return _min; }
/** Returns the maximum value of the distribution */
IntType b() const { return _max; }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(_min, _max); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
_min = parm.a();
_max = parm.b();
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { }
/** Returns an integer uniformly distributed in the range [min, max]. */
template<class Engine>
result_type operator()(Engine& eng) const
{ return detail::generate_uniform_int(eng, _min, _max); }
/**
* Returns an integer uniformly distributed in the range
* [param.a(), param.b()].
*/
template<class Engine>
result_type operator()(Engine& eng, const param_type& parm) const
{ return detail::generate_uniform_int(eng, parm.a(), parm.b()); }
/** Writes the distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, uniform_int_distribution, ud)
{
os << ud.param();
return os;
}
/** Reads the distribution from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, uniform_int_distribution, ud)
{
param_type parm;
if(is >> parm) {
ud.param(parm);
}
return is;
}
/**
* Returns true if the two distributions will produce identical sequences
* of values given equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(uniform_int_distribution, lhs, rhs)
{ return lhs._min == rhs._min && lhs._max == rhs._max; }
/**
* Returns true if the two distributions may produce different sequences
* of values given equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(uniform_int_distribution)
private:
IntType _min;
IntType _max;
};
} // namespace random
} // namespace boost
#endif // BOOST_RANDOM_UNIFORM_INT_HPP
@@ -0,0 +1,284 @@
/* boost random/uniform_on_sphere.hpp header file
*
* Copyright Jens Maurer 2000-2001
* Copyright Steven Watanabe 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$
*
* Revision history
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_UNIFORM_ON_SPHERE_HPP
#define BOOST_RANDOM_UNIFORM_ON_SPHERE_HPP
#include <vector>
#include <algorithm> // std::transform
#include <functional> // std::bind2nd, std::divides
#include <boost/assert.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/normal_distribution.hpp>
namespace boost {
namespace random {
/**
* Instantiations of class template uniform_on_sphere model a
* \random_distribution. Such a distribution produces random
* numbers uniformly distributed on the unit sphere of arbitrary
* dimension @c dim. The @c Cont template parameter must be a STL-like
* container type with begin and end operations returning non-const
* ForwardIterators of type @c Cont::iterator.
*/
template<class RealType = double, class Cont = std::vector<RealType> >
class uniform_on_sphere
{
public:
typedef RealType input_type;
typedef Cont result_type;
class param_type
{
public:
typedef uniform_on_sphere distribution_type;
/**
* Constructs the parameters of a uniform_on_sphere
* distribution, given the dimension of the sphere.
*/
explicit param_type(int dim_arg = 2) : _dim(dim_arg)
{
BOOST_ASSERT(_dim >= 0);
}
/** Returns the dimension of the sphere. */
int dim() const { return _dim; }
/** Writes the parameters to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{
os << parm._dim;
return os;
}
/** Reads the parameters from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{
is >> parm._dim;
return is;
}
/** Returns true if the two sets of parameters are equal. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._dim == rhs._dim; }
/** Returns true if the two sets of parameters are different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
int _dim;
};
/**
* Constructs a @c uniform_on_sphere distribution.
* @c dim is the dimension of the sphere.
*
* Requires: dim >= 0
*/
explicit uniform_on_sphere(int dim_arg = 2)
: _container(dim_arg), _dim(dim_arg) { }
/**
* Constructs a @c uniform_on_sphere distribution from its parameters.
*/
explicit uniform_on_sphere(const param_type& parm)
: _container(parm.dim()), _dim(parm.dim()) { }
// compiler-generated copy ctor and assignment operator are fine
/** Returns the dimension of the sphere. */
int dim() const { return _dim; }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(_dim); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
_dim = parm.dim();
_container.resize(_dim);
}
/**
* Returns the smallest value that the distribution can produce.
* Note that this is required to approximate the standard library's
* requirements. The behavior is defined according to lexicographical
* comparison so that for a container type of std::vector,
* dist.min() <= x <= dist.max() where x is any value produced
* by the distribution.
*/
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const
{
result_type result(_dim);
if(_dim != 0) {
result.front() = RealType(-1.0);
}
return result;
}
/**
* Returns the largest value that the distribution can produce.
* Note that this is required to approximate the standard library's
* requirements. The behavior is defined according to lexicographical
* comparison so that for a container type of std::vector,
* dist.min() <= x <= dist.max() where x is any value produced
* by the distribution.
*/
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{
result_type result(_dim);
if(_dim != 0) {
result.front() = RealType(1.0);
}
return result;
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() {}
/**
* Returns a point uniformly distributed over the surface of
* a sphere of dimension dim().
*/
template<class Engine>
const result_type & operator()(Engine& eng)
{
using std::sqrt;
switch(_dim)
{
case 0: break;
case 1:
{
if(uniform_01<RealType>()(eng) < 0.5) {
*_container.begin() = -1;
} else {
*_container.begin() = 1;
}
break;
}
case 2:
{
uniform_01<RealType> uniform;
RealType sqsum;
RealType x, y;
do {
x = uniform(eng) * 2 - 1;
y = uniform(eng) * 2 - 1;
sqsum = x*x + y*y;
} while(sqsum == 0 || sqsum > 1);
RealType mult = 1/sqrt(sqsum);
typename Cont::iterator iter = _container.begin();
*iter = x * mult;
iter++;
*iter = y * mult;
break;
}
case 3:
{
uniform_01<RealType> uniform;
RealType sqsum;
RealType x, y;
do {
x = uniform(eng) * 2 - 1;
y = uniform(eng) * 2 - 1;
sqsum = x*x + y*y;
} while(sqsum > 1);
RealType mult = 2 * sqrt(1 - sqsum);
typename Cont::iterator iter = _container.begin();
*iter = x * mult;
++iter;
*iter = y * mult;
++iter;
*iter = 2 * sqsum - 1;
break;
}
default:
{
detail::unit_normal_distribution<RealType> normal;
RealType sqsum;
do {
sqsum = 0;
for(typename Cont::iterator it = _container.begin();
it != _container.end();
++it) {
RealType val = normal(eng);
*it = val;
sqsum += val * val;
}
} while(sqsum == 0);
// for all i: result[i] /= sqrt(sqsum)
std::transform(_container.begin(), _container.end(), _container.begin(),
std::bind2nd(std::multiplies<RealType>(), 1/sqrt(sqsum)));
}
}
return _container;
}
/**
* Returns a point uniformly distributed over the surface of
* a sphere of dimension param.dim().
*/
template<class Engine>
result_type operator()(Engine& eng, const param_type& parm) const
{
return uniform_on_sphere(parm)(eng);
}
/** Writes the distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, uniform_on_sphere, sd)
{
os << sd._dim;
return os;
}
/** Reads the distribution from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, uniform_on_sphere, sd)
{
is >> sd._dim;
sd._container.resize(sd._dim);
return is;
}
/**
* Returns true if the two distributions will produce identical
* sequences of values, given equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(uniform_on_sphere, lhs, rhs)
{ return lhs._dim == rhs._dim; }
/**
* Returns true if the two distributions may produce different
* sequences of values, given equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(uniform_on_sphere)
private:
result_type _container;
int _dim;
};
} // namespace random
using random::uniform_on_sphere;
} // namespace boost
#endif // BOOST_RANDOM_UNIFORM_ON_SPHERE_HPP
@@ -0,0 +1,82 @@
/* boost random/uniform_real.hpp header file
*
* Copyright Jens Maurer 2000-2001
* 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$
*
* Revision history
* 2001-04-08 added min<max assertion (N. Becker)
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_UNIFORM_REAL_HPP
#define BOOST_RANDOM_UNIFORM_REAL_HPP
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/random/uniform_real_distribution.hpp>
namespace boost {
/**
* The distribution function uniform_real models a random distribution.
* On each invocation, it returns a random floating-point value uniformly
* distributed in the range [min..max).
*
* This class is deprecated. Please use @c uniform_real_distribution in
* new code.
*/
template<class RealType = double>
class uniform_real : public random::uniform_real_distribution<RealType>
{
typedef random::uniform_real_distribution<RealType> base_type;
public:
class param_type : public base_type::param_type
{
public:
typedef uniform_real distribution_type;
/**
* Constructs the parameters of a uniform_real distribution.
*
* Requires: min <= max
*/
explicit param_type(RealType min_arg = RealType(0.0),
RealType max_arg = RealType(1.0))
: base_type::param_type(min_arg, max_arg)
{}
};
/**
* Constructs a uniform_real object. @c min and @c max are the
* parameters of the distribution.
*
* Requires: min <= max
*/
explicit uniform_real(RealType min_arg = RealType(0.0),
RealType max_arg = RealType(1.0))
: base_type(min_arg, max_arg)
{
BOOST_ASSERT(min_arg < max_arg);
}
/** Constructs a uniform_real distribution from its parameters. */
explicit uniform_real(const param_type& parm)
: base_type(parm)
{}
/** Returns the parameters of the distribution */
param_type param() const { return param_type(this->a(), this->b()); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm) { this->base_type::param(parm); }
};
} // namespace boost
#endif // BOOST_RANDOM_UNIFORM_REAL_HPP
@@ -0,0 +1,241 @@
/* boost random/uniform_real_distribution.hpp header file
*
* Copyright Jens Maurer 2000-2001
* Copyright Steven Watanabe 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_UNIFORM_REAL_DISTRIBUTION_HPP
#define BOOST_RANDOM_UNIFORM_REAL_DISTRIBUTION_HPP
#include <iosfwd>
#include <ios>
#include <istream>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/detail/signed_unsigned_tools.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/mpl/bool.hpp>
namespace boost {
namespace random {
namespace detail {
template<class Engine, class T>
T generate_uniform_real(
Engine& eng, T min_value, T max_value,
boost::mpl::false_ /** is_integral<Engine::result_type> */)
{
for(;;) {
typedef T result_type;
result_type numerator = static_cast<T>(eng() - (eng.min)());
result_type divisor = static_cast<T>((eng.max)() - (eng.min)());
BOOST_ASSERT(divisor > 0);
BOOST_ASSERT(numerator >= 0 && numerator <= divisor);
T result = numerator / divisor * (max_value - min_value) + min_value;
if(result < max_value) return result;
}
}
template<class Engine, class T>
T generate_uniform_real(
Engine& eng, T min_value, T max_value,
boost::mpl::true_ /** is_integral<Engine::result_type> */)
{
for(;;) {
typedef T result_type;
typedef typename Engine::result_type base_result;
result_type numerator = static_cast<T>(subtract<base_result>()(eng(), (eng.min)()));
result_type divisor = static_cast<T>(subtract<base_result>()((eng.max)(), (eng.min)())) + 1;
BOOST_ASSERT(divisor > 0);
BOOST_ASSERT(numerator >= 0 && numerator <= divisor);
T result = numerator / divisor * (max_value - min_value) + min_value;
if(result < max_value) return result;
}
}
template<class Engine, class T>
inline T generate_uniform_real(Engine& eng, T min_value, T max_value)
{
if(max_value / 2 - min_value / 2 > (std::numeric_limits<T>::max)() / 2)
return 2 * generate_uniform_real(eng, T(min_value / 2), T(max_value / 2));
typedef typename Engine::result_type base_result;
return generate_uniform_real(eng, min_value, max_value,
boost::is_integral<base_result>());
}
}
/**
* The class template uniform_real_distribution models a \random_distribution.
* On each invocation, it returns a random floating-point value uniformly
* distributed in the range [min..max).
*/
template<class RealType = double>
class uniform_real_distribution
{
public:
typedef RealType input_type;
typedef RealType result_type;
class param_type
{
public:
typedef uniform_real_distribution distribution_type;
/**
* Constructs the parameters of a uniform_real_distribution.
*
* Requires min <= max
*/
explicit param_type(RealType min_arg = RealType(0.0),
RealType max_arg = RealType(1.0))
: _min(min_arg), _max(max_arg)
{
BOOST_ASSERT(_min < _max);
}
/** Returns the minimum value of the distribution. */
RealType a() const { return _min; }
/** Returns the maximum value of the distribution. */
RealType b() const { return _max; }
/** Writes the parameters to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{
os << parm._min << " " << parm._max;
return os;
}
/** Reads the parameters from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{
RealType min_in, max_in;
if(is >> min_in >> std::ws >> max_in) {
if(min_in <= max_in) {
parm._min = min_in;
parm._max = max_in;
} else {
is.setstate(std::ios_base::failbit);
}
}
return is;
}
/** Returns true if the two sets of parameters are equal. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._min == rhs._min && lhs._max == rhs._max; }
/** Returns true if the two sets of parameters are different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
RealType _min;
RealType _max;
};
/**
* Constructs a uniform_real_distribution. @c min and @c max are
* the parameters of the distribution.
*
* Requires: min <= max
*/
explicit uniform_real_distribution(
RealType min_arg = RealType(0.0),
RealType max_arg = RealType(1.0))
: _min(min_arg), _max(max_arg)
{
BOOST_ASSERT(min_arg < max_arg);
}
/** Constructs a uniform_real_distribution from its parameters. */
explicit uniform_real_distribution(const param_type& parm)
: _min(parm.a()), _max(parm.b()) {}
/** Returns the minimum value of the distribution */
RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; }
/** Returns the maximum value of the distribution */
RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; }
/** Returns the minimum value of the distribution */
RealType a() const { return _min; }
/** Returns the maximum value of the distribution */
RealType b() const { return _max; }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(_min, _max); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
_min = parm.a();
_max = parm.b();
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { }
/** Returns a value uniformly distributed in the range [min, max). */
template<class Engine>
result_type operator()(Engine& eng) const
{ return detail::generate_uniform_real(eng, _min, _max); }
/**
* Returns a value uniformly distributed in the range
* [param.a(), param.b()).
*/
template<class Engine>
result_type operator()(Engine& eng, const param_type& parm) const
{ return detail::generate_uniform_real(eng, parm.a(), parm.b()); }
/** Writes the distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, uniform_real_distribution, ud)
{
os << ud.param();
return os;
}
/** Reads the distribution from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, uniform_real_distribution, ud)
{
param_type parm;
if(is >> parm) {
ud.param(parm);
}
return is;
}
/**
* Returns true if the two distributions will produce identical sequences
* of values given equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(uniform_real_distribution, lhs, rhs)
{ return lhs._min == rhs._min && lhs._max == rhs._max; }
/**
* Returns true if the two distributions may produce different sequences
* of values given equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(uniform_real_distribution)
private:
RealType _min;
RealType _max;
};
} // namespace random
} // namespace boost
#endif // BOOST_RANDOM_UNIFORM_INT_HPP
@@ -0,0 +1,307 @@
/* boost random/uniform_smallint.hpp header file
*
* Copyright Jens Maurer 2000-2001
* 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$
*
* Revision history
* 2001-04-08 added min<max assertion (N. Becker)
* 2001-02-18 moved to individual header files
*/
#ifndef BOOST_RANDOM_UNIFORM_SMALLINT_HPP
#define BOOST_RANDOM_UNIFORM_SMALLINT_HPP
#include <istream>
#include <iosfwd>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/detail/signed_unsigned_tools.hpp>
#include <boost/random/uniform_01.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/mpl/bool.hpp>
#ifdef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
#include <boost/mpl/if.hpp>
#endif
namespace boost {
namespace random {
// uniform integer distribution on a small range [min, max]
/**
* The distribution function uniform_smallint models a \random_distribution.
* On each invocation, it returns a random integer value uniformly distributed
* in the set of integer numbers {min, min+1, min+2, ..., max}. It assumes
* that the desired range (max-min+1) is small compared to the range of the
* underlying source of random numbers and thus makes no attempt to limit
* quantization errors.
*
* Let \f$r_{\mathtt{out}} = (\mbox{max}-\mbox{min}+1)\f$ the desired range of
* integer numbers, and
* let \f$r_{\mathtt{base}}\f$ be the range of the underlying source of random
* numbers. Then, for the uniform distribution, the theoretical probability
* for any number i in the range \f$r_{\mathtt{out}}\f$ will be
* \f$\displaystyle p_{\mathtt{out}}(i) = \frac{1}{r_{\mathtt{out}}}\f$.
* Likewise, assume a uniform distribution on \f$r_{\mathtt{base}}\f$ for
* the underlying source of random numbers, i.e.
* \f$\displaystyle p_{\mathtt{base}}(i) = \frac{1}{r_{\mathtt{base}}}\f$.
* Let \f$p_{\mathtt{out\_s}}(i)\f$ denote the random
* distribution generated by @c uniform_smallint. Then the sum over all
* i in \f$r_{\mathtt{out}}\f$ of
* \f$\displaystyle
* \left(\frac{p_{\mathtt{out\_s}}(i)}{p_{\mathtt{out}}(i)} - 1\right)^2\f$
* shall not exceed
* \f$\displaystyle \frac{r_{\mathtt{out}}}{r_{\mathtt{base}}^2}
* (r_{\mathtt{base}} \mbox{ mod } r_{\mathtt{out}})
* (r_{\mathtt{out}} - r_{\mathtt{base}} \mbox{ mod } r_{\mathtt{out}})\f$.
*
* The template parameter IntType shall denote an integer-like value type.
*
* @xmlnote
* The property above is the square sum of the relative differences
* in probabilities between the desired uniform distribution
* \f$p_{\mathtt{out}}(i)\f$ and the generated distribution
* \f$p_{\mathtt{out\_s}}(i)\f$.
* The property can be fulfilled with the calculation
* \f$(\mbox{base\_rng} \mbox{ mod } r_{\mathtt{out}})\f$, as follows:
* Let \f$r = r_{\mathtt{base}} \mbox{ mod } r_{\mathtt{out}}\f$.
* The base distribution on \f$r_{\mathtt{base}}\f$ is folded onto the
* range \f$r_{\mathtt{out}}\f$. The numbers i < r have assigned
* \f$\displaystyle
* \left\lfloor\frac{r_{\mathtt{base}}}{r_{\mathtt{out}}}\right\rfloor+1\f$
* numbers of the base distribution, the rest has only \f$\displaystyle
* \left\lfloor\frac{r_{\mathtt{base}}}{r_{\mathtt{out}}}\right\rfloor\f$.
* Therefore,
* \f$\displaystyle p_{\mathtt{out\_s}}(i) =
* \left(\left\lfloor\frac{r_{\mathtt{base}}}
* {r_{\mathtt{out}}}\right\rfloor+1\right) /
* r_{\mathtt{base}}\f$ for i < r and \f$\displaystyle p_{\mathtt{out\_s}}(i) =
* \left\lfloor\frac{r_{\mathtt{base}}}
* {r_{\mathtt{out}}}\right\rfloor/r_{\mathtt{base}}\f$ otherwise.
* Substituting this in the
* above sum formula leads to the desired result.
* @endxmlnote
*
* Note: The upper bound for
* \f$(r_{\mathtt{base}} \mbox{ mod } r_{\mathtt{out}})
* (r_{\mathtt{out}} - r_{\mathtt{base}} \mbox{ mod } r_{\mathtt{out}})\f$ is
* \f$\displaystyle \frac{r_{\mathtt{out}}^2}{4}\f$. Regarding the upper bound
* for the square sum of the relative quantization error of
* \f$\displaystyle \frac{r_\mathtt{out}^3}{4r_{\mathtt{base}}^2}\f$, it
* seems wise to either choose \f$r_{\mathtt{base}}\f$ so that
* \f$r_{\mathtt{base}} > 10r_{\mathtt{out}}^2\f$ or ensure that
* \f$r_{\mathtt{base}}\f$ is
* divisible by \f$r_{\mathtt{out}}\f$.
*/
template<class IntType = int>
class uniform_smallint
{
public:
typedef IntType input_type;
typedef IntType result_type;
class param_type
{
public:
typedef uniform_smallint distribution_type;
/** constructs the parameters of a @c uniform_smallint distribution. */
param_type(IntType min_arg = 0, IntType max_arg = 9)
: _min(min_arg), _max(max_arg)
{
BOOST_ASSERT(_min <= _max);
}
/** Returns the minimum value. */
IntType a() const { return _min; }
/** Returns the maximum value. */
IntType b() const { return _max; }
/** Writes the parameters to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{
os << parm._min << " " << parm._max;
return os;
}
/** Reads the parameters from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{
is >> parm._min >> std::ws >> parm._max;
return is;
}
/** Returns true if the two sets of parameters are equal. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._min == rhs._min && lhs._max == rhs._max; }
/** Returns true if the two sets of parameters are different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
IntType _min;
IntType _max;
};
/**
* Constructs a @c uniform_smallint. @c min and @c max are the
* lower and upper bounds of the output range, respectively.
*/
explicit uniform_smallint(IntType min_arg = 0, IntType max_arg = 9)
: _min(min_arg), _max(max_arg) {}
/**
* Constructs a @c uniform_smallint from its parameters.
*/
explicit uniform_smallint(const param_type& parm)
: _min(parm.a()), _max(parm.b()) {}
/** Returns the minimum value of the distribution. */
result_type a() const { return _min; }
/** Returns the maximum value of the distribution. */
result_type b() const { return _max; }
/** Returns the minimum value of the distribution. */
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; }
/** Returns the maximum value of the distribution. */
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(_min, _max); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
_min = parm.a();
_max = parm.b();
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { }
/** Returns a value uniformly distributed in the range [min(), max()]. */
template<class Engine>
result_type operator()(Engine& eng) const
{
typedef typename Engine::result_type base_result;
return generate(eng, boost::random::traits::is_integral<base_result>());
}
/** Returns a value uniformly distributed in the range [param.a(), param.b()]. */
template<class Engine>
result_type operator()(Engine& eng, const param_type& parm) const
{ return uniform_smallint(parm)(eng); }
/** Writes the distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, uniform_smallint, ud)
{
os << ud._min << " " << ud._max;
return os;
}
/** Reads the distribution from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, uniform_smallint, ud)
{
is >> ud._min >> std::ws >> ud._max;
return is;
}
/**
* Returns true if the two distributions will produce identical
* sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(uniform_smallint, lhs, rhs)
{ return lhs._min == rhs._min && lhs._max == rhs._max; }
/**
* Returns true if the two distributions may produce different
* sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(uniform_smallint)
private:
// \cond show_private
template<class Engine>
result_type generate(Engine& eng, boost::mpl::true_) const
{
// equivalent to (eng() - eng.min()) % (_max - _min + 1) + _min,
// but guarantees no overflow.
typedef typename Engine::result_type base_result;
typedef typename boost::random::traits::make_unsigned<base_result>::type base_unsigned;
typedef typename boost::random::traits::make_unsigned_or_unbounded<result_type>::type range_type;
#ifdef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
typedef typename mpl::if_c<
std::numeric_limits<range_type>::is_specialized && std::numeric_limits<base_unsigned>::is_specialized
&& (std::numeric_limits<range_type>::digits >= std::numeric_limits<base_unsigned>::digits),
range_type, base_unsigned>::type mixed_range_type;
#else
typedef base_unsigned mixed_range_type;
#endif
range_type range = random::detail::subtract<result_type>()(_max, _min);
base_unsigned base_range =
random::detail::subtract<base_result>()((eng.max)(), (eng.min)());
base_unsigned val =
random::detail::subtract<base_result>()(eng(), (eng.min)());
if(range >= base_range) {
return boost::random::detail::add<range_type, result_type>()(
static_cast<range_type>(val), _min);
} else {
// This involves mixed arithmetic between the base generators range
// type, and the result_type's range type. mixed_range_type is
// normally the same as base_unsigned which is the most efficient
// option, but requires a narrowing explcit cast if result_type
// is a multiprecision type. If no such casts are available then use
// multiprecision arithmetic throughout instead.
mixed_range_type modulus = static_cast<mixed_range_type>(range)+1;
return boost::random::detail::add<range_type, result_type>()(
static_cast<mixed_range_type>(val) % modulus, _min);
}
}
template<class Engine>
result_type generate(Engine& eng, boost::mpl::false_) const
{
typedef typename Engine::result_type base_result;
typedef typename boost::random::traits::make_unsigned<result_type>::type range_type;
range_type range = random::detail::subtract<result_type>()(_max, _min);
base_result val = boost::uniform_01<base_result>()(eng);
// what is the worst that can possibly happen here?
// base_result may not be able to represent all the values in [0, range]
// exactly. If this happens, it will cause round off error and we
// won't be able to produce all the values in the range. We don't
// care about this because the user has already told us not to by
// using uniform_smallint. However, we do need to be careful
// to clamp the result, or floating point rounding can produce
// an out of range result.
range_type offset = static_cast<range_type>(val * (static_cast<base_result>(range) + 1));
if(offset > range) return _max;
return boost::random::detail::add<range_type, result_type>()(offset , _min);
}
// \endcond
result_type _min;
result_type _max;
};
} // namespace random
using random::uniform_smallint;
} // namespace boost
#endif // BOOST_RANDOM_UNIFORM_SMALLINT_HPP
@@ -0,0 +1,122 @@
/* boost random/variate_generator.hpp header file
*
* Copyright Jens Maurer 2002
* Copyright Steven Watanabe 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_RANDOM_GENERATOR_HPP
#define BOOST_RANDOM_RANDOM_GENERATOR_HPP
#include <boost/random/detail/ptr_helper.hpp>
#include <boost/random/detail/disable_warnings.hpp>
namespace boost {
/// \cond hide_private_members
namespace random {
///\endcond
/**
* A random variate generator is used to join a random number
* generator together with a random number distribution.
* Boost.Random provides a vast choice of \generators as well
* as \distributions.
*
* The argument for the template parameter Engine shall be of
* the form U, U&, or U*, where U models a
* \uniform_random_number_generator. Then, the member
* engine_value_type names U (not the pointer or reference to U).
*
* Specializations of @c variate_generator satisfy the
* requirements of CopyConstructible. They also satisfy the
* requirements of Assignable unless the template parameter
* Engine is of the form U&.
*
* The complexity of all functions specified in this section
* is constant. No function described in this section except
* the constructor throws an exception.
*/
template<class Engine, class Distribution>
class variate_generator
{
private:
typedef boost::random::detail::ptr_helper<Engine> helper_type;
public:
typedef typename helper_type::value_type engine_value_type;
typedef Engine engine_type;
typedef Distribution distribution_type;
typedef typename Distribution::result_type result_type;
/**
* Constructs a @c variate_generator object with the associated
* \uniform_random_number_generator eng and the associated
* \random_distribution d.
*
* Throws: If and what the copy constructor of Engine or
* Distribution throws.
*/
variate_generator(Engine e, Distribution d)
: _eng(e), _dist(d) { }
/** Returns: distribution()(engine()) */
result_type operator()() { return _dist(engine()); }
/**
* Returns: distribution()(engine(), value).
*/
template<class T>
result_type operator()(const T& value) { return _dist(engine(), value); }
/**
* Returns: A reference to the associated uniform random number generator.
*/
engine_value_type& engine() { return helper_type::ref(_eng); }
/**
* Returns: A reference to the associated uniform random number generator.
*/
const engine_value_type& engine() const { return helper_type::ref(_eng); }
/** Returns: A reference to the associated \random_distribution. */
distribution_type& distribution() { return _dist; }
/**
* Returns: A reference to the associated random distribution.
*/
const distribution_type& distribution() const { return _dist; }
/**
* Precondition: distribution().min() is well-formed
*
* Returns: distribution().min()
*/
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (distribution().min)(); }
/**
* Precondition: distribution().max() is well-formed
*
* Returns: distribution().max()
*/
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (distribution().max)(); }
private:
Engine _eng;
distribution_type _dist;
};
} // namespace random
using random::variate_generator;
} // namespace boost
#include <boost/random/detail/enable_warnings.hpp>
#endif // BOOST_RANDOM_RANDOM_GENERATOR_HPP
@@ -0,0 +1,177 @@
/* boost random/weibull_distribution.hpp header file
*
* Copyright Steven Watanabe 2010
* 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_WEIBULL_DISTRIBUTION_HPP
#define BOOST_RANDOM_WEIBULL_DISTRIBUTION_HPP
#include <boost/config/no_tr1/cmath.hpp>
#include <iosfwd>
#include <istream>
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/random/detail/operators.hpp>
#include <boost/random/uniform_01.hpp>
namespace boost {
namespace random {
/**
* The Weibull distribution is a real valued distribution with two
* parameters a and b, producing values >= 0.
*
* It has \f$\displaystyle p(x) = \frac{a}{b}\left(\frac{x}{b}\right)^{a-1}e^{-\left(\frac{x}{b}\right)^a}\f$.
*/
template<class RealType = double>
class weibull_distribution {
public:
typedef RealType result_type;
typedef RealType input_type;
class param_type {
public:
typedef weibull_distribution distribution_type;
/**
* Constructs a @c param_type from the "a" and "b" parameters
* of the distribution.
*
* Requires: a > 0 && b > 0
*/
explicit param_type(RealType a_arg = 1.0, RealType b_arg = 1.0)
: _a(a_arg), _b(b_arg)
{}
/** Returns the "a" parameter of the distribtuion. */
RealType a() const { return _a; }
/** Returns the "b" parameter of the distribution. */
RealType b() const { return _b; }
/** Writes a @c param_type to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
{ os << parm._a << ' ' << parm._b; return os; }
/** Reads a @c param_type from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
{ is >> parm._a >> std::ws >> parm._b; return is; }
/** Returns true if the two sets of parameters are the same. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
{ return lhs._a == rhs._a && lhs._b == rhs._b; }
/** Returns true if the two sets of parameters are the different. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
private:
RealType _a;
RealType _b;
};
/**
* Constructs a @c weibull_distribution from its "a" and "b" parameters.
*
* Requires: a > 0 && b > 0
*/
explicit weibull_distribution(RealType a_arg = 1.0, RealType b_arg = 1.0)
: _a(a_arg), _b(b_arg)
{}
/** Constructs a @c weibull_distribution from its parameters. */
explicit weibull_distribution(const param_type& parm)
: _a(parm.a()), _b(parm.b())
{}
/**
* Returns a random variate distributed according to the
* @c weibull_distribution.
*/
template<class URNG>
RealType operator()(URNG& urng) const
{
using std::pow;
using std::log;
return _b*pow(-log(1 - uniform_01<RealType>()(urng)), 1/_a);
}
/**
* Returns a random variate distributed accordint to the Weibull
* distribution with parameters specified by @c param.
*/
template<class URNG>
RealType operator()(URNG& urng, const param_type& parm) const
{
return weibull_distribution(parm)(urng);
}
/** Returns the "a" parameter of the distribution. */
RealType a() const { return _a; }
/** Returns the "b" parameter of the distribution. */
RealType b() const { return _b; }
/** Returns the smallest value that the distribution can produce. */
RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; }
/** Returns the largest value that the distribution can produce. */
RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const
{ return std::numeric_limits<RealType>::infinity(); }
/** Returns the parameters of the distribution. */
param_type param() const { return param_type(_a, _b); }
/** Sets the parameters of the distribution. */
void param(const param_type& parm)
{
_a = parm.a();
_b = parm.b();
}
/**
* Effects: Subsequent uses of the distribution do not depend
* on values produced by any engine prior to invoking reset.
*/
void reset() { }
/** Writes a @c weibull_distribution to a @c std::ostream. */
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, weibull_distribution, wd)
{
os << wd.param();
return os;
}
/** Reads a @c weibull_distribution from a @c std::istream. */
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, weibull_distribution, wd)
{
param_type parm;
if(is >> parm) {
wd.param(parm);
}
return is;
}
/**
* Returns true if the two instances of @c weibull_distribution will
* return identical sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(weibull_distribution, lhs, rhs)
{ return lhs._a == rhs._a && lhs._b == rhs._b; }
/**
* Returns true if the two instances of @c weibull_distribution will
* return different sequences of values given equal generators.
*/
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(weibull_distribution)
private:
RealType _a;
RealType _b;
};
} // namespace random
} // namespace boost
#endif // BOOST_RANDOM_WEIBULL_DISTRIBUTION_HPP
@@ -0,0 +1,208 @@
/* boost random/xor_combine.hpp header file
*
* Copyright Jens Maurer 2002
* 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_XOR_COMBINE_HPP
#define BOOST_RANDOM_XOR_COMBINE_HPP
#include <istream>
#include <iosfwd>
#include <cassert>
#include <algorithm> // for std::min and std::max
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/cstdint.hpp> // uint32_t
#include <boost/random/detail/config.hpp>
#include <boost/random/detail/seed.hpp>
#include <boost/random/detail/seed_impl.hpp>
#include <boost/random/detail/operators.hpp>
namespace boost {
namespace random {
/**
* Instantiations of @c xor_combine_engine model a
* \pseudo_random_number_generator. To produce its output it
* invokes each of the base generators, shifts their results
* and xors them together.
*/
template<class URNG1, int s1, class URNG2, int s2>
class xor_combine_engine
{
public:
typedef URNG1 base1_type;
typedef URNG2 base2_type;
typedef typename base1_type::result_type result_type;
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
BOOST_STATIC_CONSTANT(int, shift1 = s1);
BOOST_STATIC_CONSTANT(int, shift2 = s2);
/**
* Constructors a @c xor_combine_engine by default constructing
* both base generators.
*/
xor_combine_engine() : _rng1(), _rng2() { }
/** Constructs a @c xor_combine by copying two base generators. */
xor_combine_engine(const base1_type & rng1, const base2_type & rng2)
: _rng1(rng1), _rng2(rng2) { }
/**
* Constructs a @c xor_combine_engine, seeding both base generators
* with @c v.
*
* @xmlwarning
* The exact algorithm used by this function may change in the future.
* @endxmlwarning
*/
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(xor_combine_engine,
result_type, v)
{ seed(v); }
/**
* Constructs a @c xor_combine_engine, seeding both base generators
* with values produced by @c seq.
*/
BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(xor_combine_engine,
SeedSeq, seq)
{ seed(seq); }
/**
* Constructs a @c xor_combine_engine, seeding both base generators
* with values from the iterator range [first, last) and changes
* first to point to the element after the last one used. If there
* are not enough elements in the range to seed both generators,
* throws @c std::invalid_argument.
*/
template<class It> xor_combine_engine(It& first, It last)
: _rng1(first, last), _rng2( /* advanced by other call */ first, last) { }
/** Calls @c seed() for both base generators. */
void seed() { _rng1.seed(); _rng2.seed(); }
/** @c seeds both base generators with @c v. */
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(xor_combine_engine, result_type, v)
{ _rng1.seed(v); _rng2.seed(v); }
/** @c seeds both base generators with values produced by @c seq. */
BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(xor_combine_engine, SeedSeq, seq)
{ _rng1.seed(seq); _rng2.seed(seq); }
/**
* seeds both base generators with values from the iterator
* range [first, last) and changes first to point to the element
* after the last one used. If there are not enough elements in
* the range to seed both generators, throws @c std::invalid_argument.
*/
template<class It> void seed(It& first, It last)
{
_rng1.seed(first, last);
_rng2.seed(first, last);
}
/** Returns the first base generator. */
const base1_type& base1() const { return _rng1; }
/** Returns the second base generator. */
const base2_type& base2() const { return _rng2; }
/** Returns the next value of the generator. */
result_type operator()()
{
return (_rng1() << s1) ^ (_rng2() << s2);
}
/** Fills a range with random values */
template<class Iter>
void generate(Iter first, Iter last)
{ detail::generate_from_int(*this, first, last); }
/** Advances the state of the generator by @c z. */
void discard(boost::uintmax_t z)
{
_rng1.discard(z);
_rng2.discard(z);
}
/** Returns the smallest value that the generator can produce. */
static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return (std::min)((URNG1::min)(), (URNG2::min)()); }
/** Returns the largest value that the generator can produce. */
static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () { return (std::max)((URNG1::min)(), (URNG2::max)()); }
/**
* Writes the textual representation of the generator to a @c std::ostream.
*/
BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, xor_combine_engine, s)
{
os << s._rng1 << ' ' << s._rng2;
return os;
}
/**
* Reads the textual representation of the generator from a @c std::istream.
*/
BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, xor_combine_engine, s)
{
is >> s._rng1 >> std::ws >> s._rng2;
return is;
}
/** Returns true if the two generators will produce identical sequences. */
BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(xor_combine_engine, x, y)
{ return x._rng1 == y._rng1 && x._rng2 == y._rng2; }
/** Returns true if the two generators will produce different sequences. */
BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(xor_combine_engine)
private:
base1_type _rng1;
base2_type _rng2;
};
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
// A definition is required even for integral static constants
template<class URNG1, int s1, class URNG2, int s2>
const bool xor_combine_engine<URNG1, s1, URNG2, s2>::has_fixed_range;
template<class URNG1, int s1, class URNG2, int s2>
const int xor_combine_engine<URNG1, s1, URNG2, s2>::shift1;
template<class URNG1, int s1, class URNG2, int s2>
const int xor_combine_engine<URNG1, s1, URNG2, s2>::shift2;
#endif
/// \cond show_private
/** Provided for backwards compatibility. */
template<class URNG1, int s1, class URNG2, int s2,
typename URNG1::result_type v = 0>
class xor_combine : public xor_combine_engine<URNG1, s1, URNG2, s2>
{
typedef xor_combine_engine<URNG1, s1, URNG2, s2> base_type;
public:
typedef typename base_type::result_type result_type;
xor_combine() {}
xor_combine(result_type val) : base_type(val) {}
template<class It>
xor_combine(It& first, It last) : base_type(first, last) {}
xor_combine(const URNG1 & rng1, const URNG2 & rng2)
: base_type(rng1, rng2) { }
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (std::min)((this->base1().min)(), (this->base2().min)()); }
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (std::max)((this->base1().min)(), (this->base2().max)()); }
};
/// \endcond
} // namespace random
} // namespace boost
#endif // BOOST_RANDOM_XOR_COMBINE_HPP