mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-19 06:01:57 +00:00
Merge branch 'master' of https://github.com/yandex/ClickHouse into CLICKHOUSE-2720
This commit is contained in:
commit
b32445ca8b
@ -27,16 +27,16 @@ endif ()
|
||||
cmake_policy (SET CMP0014 OLD) # Ignore warning about CMakeLists.txt in each directory
|
||||
cmake_policy (SET CMP0012 NEW) # Don't dereference TRUE and FALSE
|
||||
|
||||
find_program (CCACHE_FOUND ccache)
|
||||
if (CCACHE_FOUND AND NOT CMAKE_CXX_COMPILER_LAUNCHER MATCHES "ccache" AND NOT CMAKE_CXX_COMPILER MATCHES "ccache")
|
||||
set_property (GLOBAL PROPERTY RULE_LAUNCH_COMPILE "ccache")
|
||||
set_property (GLOBAL PROPERTY RULE_LAUNCH_LINK "ccache")
|
||||
endif ()
|
||||
# Write compile_commands.json
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
|
||||
|
||||
include (cmake/find_ccache.cmake)
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "None")
|
||||
message (STATUS "CMAKE_BUILD_TYPE is not set, set to default = RELWITHDEBINFO")
|
||||
set (CMAKE_BUILD_TYPE "RELWITHDEBINFO")
|
||||
endif ()
|
||||
string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UC)
|
||||
message (STATUS "CMAKE_BUILD_TYPE: " ${CMAKE_BUILD_TYPE} )
|
||||
|
||||
# ASan - build type with address sanitizer
|
||||
@ -86,18 +86,25 @@ else ()
|
||||
set (CXX11_ABI_FLAGS "")
|
||||
endif ()
|
||||
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} ${CXX11_ABI_FLAGS}")
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} ${CXX11_ABI_FLAGS}")
|
||||
|
||||
option (PIPE "-pipe compiler option [less /tmp usage, more ram usage]" ON)
|
||||
if (PIPE)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} -pipe")
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} -pipe")
|
||||
endif ()
|
||||
|
||||
include (cmake/test_cpu.cmake)
|
||||
|
||||
option (ARCHNATIVE "Enable -march=native compiler flag" OFF)
|
||||
if (ARCHNATIVE)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} -march=native")
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} -march=native")
|
||||
endif ()
|
||||
|
||||
option (USE_LIBCXX "Use libc++ and libc++abi instead of libstdc++ (only make sense on Linux with Clang)" OFF)
|
||||
if (USE_LIBCXX)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} -pthread") # NOTE: Why this is not the default and why this is needed only with libc++?
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_LIBCPP_DEBUG=1") # More checks in debug build.
|
||||
endif ()
|
||||
|
||||
set (CMAKE_BUILD_COLOR_MAKEFILE ON)
|
||||
@ -112,11 +119,16 @@ set (CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3")
|
||||
set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -g3 -ggdb3 -fno-inline")
|
||||
|
||||
if (NOT APPLE AND NOT (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_SYSTEM MATCHES "FreeBSD"))
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++")
|
||||
endif ()
|
||||
|
||||
if (NOT APPLE)
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GLIBC_COMPATIBILITY_LINK_FLAGS} ${CXX11_ABI_FLAGS}")
|
||||
|
||||
if (USE_LIBCXX AND (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
|
||||
link_libraries (-Wl,-Bstatic -stdlib=libc++ c++ c++abi -Wl,-Bdynamic)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
include (cmake/test_compiler.cmake)
|
||||
@ -145,6 +157,18 @@ set (CMAKE_C_FLAGS_MSAN "${CMAKE_C_FLAGS_MSAN} ${SAN_FLAGS}
|
||||
set (CMAKE_CXX_FLAGS_TSAN "${CMAKE_CXX_FLAGS_TSAN} ${SAN_FLAGS} -fsanitize=thread")
|
||||
set (CMAKE_C_FLAGS_TSAN "${CMAKE_C_FLAGS_TSAN} ${SAN_FLAGS} -fsanitize=thread")
|
||||
|
||||
# Using "include-what-you-use" tool.
|
||||
option (USE_INCLUDE_WHAT_YOU_USE "Use 'include-what-you-use' tool" OFF)
|
||||
if (USE_INCLUDE_WHAT_YOU_USE)
|
||||
find_program(IWYU_PATH NAMES include-what-you-use iwyu)
|
||||
if (NOT IWYU_PATH)
|
||||
message(FATAL_ERROR "Could not find the program include-what-you-use")
|
||||
endif()
|
||||
if (${CMAKE_VERSION} VERSION_LESS "3.3.0")
|
||||
message(FATAL_ERROR "include-what-you-use requires CMake version at least 3.3.")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
# Flags for test coverage
|
||||
if (TEST_COVERAGE)
|
||||
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage -DIS_DEBUG")
|
||||
@ -173,7 +197,7 @@ if (UNBUNDLED OR NOT (CMAKE_SYSTEM MATCHES "Linux" OR APPLE) OR ARCH_32)
|
||||
option (NO_WERROR "Disable -Werror compiler option" ON)
|
||||
endif ()
|
||||
|
||||
message (STATUS "Building for: ${CMAKE_SYSTEM} ${CMAKE_SYSTEM_PROCESSOR} ${CMAKE_LIBRARY_ARCHITECTURE} ; USE_STATIC_LIBRARIES=${USE_STATIC_LIBRARIES} MAKE_STATIC_LIBRARIES=${MAKE_STATIC_LIBRARIES} UNBUNDLED=${UNBUNDLED} CCACHE=${CCACHE_FOUND}")
|
||||
message (STATUS "Building for: ${CMAKE_SYSTEM} ${CMAKE_SYSTEM_PROCESSOR} ${CMAKE_LIBRARY_ARCHITECTURE} ; USE_STATIC_LIBRARIES=${USE_STATIC_LIBRARIES} MAKE_STATIC_LIBRARIES=${MAKE_STATIC_LIBRARIES} UNBUNDLED=${UNBUNDLED} CCACHE=${CCACHE_FOUND} ${CCACHE_VERSION}")
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
@ -211,8 +235,8 @@ include (libs/libmysqlxx/cmake/find_mysqlclient.cmake)
|
||||
include (libs/libdaemon/cmake/find_unwind.cmake)
|
||||
|
||||
|
||||
set (FULL_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE}}")
|
||||
set (FULL_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}}")
|
||||
set (FULL_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE_UC}}")
|
||||
set (FULL_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UC}}")
|
||||
message (STATUS "C_FLAGS = ${FULL_C_FLAGS}")
|
||||
message (STATUS "CXX_FLAGS = ${FULL_CXX_FLAGS}")
|
||||
message (STATUS "LINK_FLAGS = ${CMAKE_EXE_LINKER_FLAGS}")
|
||||
|
14
cmake/find_ccache.cmake
Normal file
14
cmake/find_ccache.cmake
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
find_program (CCACHE_FOUND ccache)
|
||||
if (CCACHE_FOUND AND NOT CMAKE_CXX_COMPILER_LAUNCHER MATCHES "ccache" AND NOT CMAKE_CXX_COMPILER MATCHES "ccache")
|
||||
execute_process(COMMAND ${CCACHE_FOUND} "-V" OUTPUT_VARIABLE CCACHE_VERSION)
|
||||
string(REGEX REPLACE "ccache version ([0-9\\.]+).*" "\\1" CCACHE_VERSION ${CCACHE_VERSION} )
|
||||
|
||||
if (CCACHE_VERSION VERSION_GREATER "3.2.0" OR NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
#message(STATUS "Using ${CCACHE_FOUND} ${CCACHE_VERSION}")
|
||||
set_property (GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_FOUND})
|
||||
set_property (GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_FOUND})
|
||||
else ()
|
||||
message(STATUS "Not using ${CCACHE_FOUND} ${CCACHE_VERSION} bug: https://bugzilla.samba.org/show_bug.cgi?id=8118")
|
||||
endif ()
|
||||
endif ()
|
@ -4,3 +4,4 @@ set(CITYHASH_CONTRIB_INCLUDE_DIR ${ClickHouse_SOURCE_DIR}/contrib/libcityhash/in
|
||||
set(COMMON_INCLUDE_DIR ${ClickHouse_SOURCE_DIR}/libs/libcommon/include ${ClickHouse_BINARY_DIR}/libs/libcommon/include)
|
||||
set(DBMS_INCLUDE_DIR ${ClickHouse_SOURCE_DIR}/dbms/src ${ClickHouse_BINARY_DIR}/dbms/src)
|
||||
set(DOUBLE_CONVERSION_CONTRIB_INCLUDE_DIR ${ClickHouse_SOURCE_DIR}/contrib/libdouble-conversion)
|
||||
set(PCG_RANDOM_INCLUDE_DIR ${ClickHouse_SOURCE_DIR}/contrib/libpcg-random/include)
|
||||
|
@ -1,91 +0,0 @@
|
||||
/* boost random.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/libs/random for documentation.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Revision history
|
||||
* 2000-02-18 portability fixes (thanks to Beman Dawes)
|
||||
* 2000-02-21 shuffle_output, inversive_congruential_schrage,
|
||||
* generator_iterator, uniform_smallint
|
||||
* 2000-02-23 generic modulus arithmetic helper, removed *_schrage classes,
|
||||
* implemented Streamable and EqualityComparable concepts for
|
||||
* generators, added Bernoulli distribution and Box-Muller
|
||||
* transform
|
||||
* 2000-03-01 cauchy, lognormal, triangle distributions; fixed
|
||||
* uniform_smallint; renamed gaussian to normal distribution
|
||||
* 2000-03-05 implemented iterator syntax for distribution functions
|
||||
* 2000-04-21 removed some optimizations for better BCC/MSVC compatibility
|
||||
* 2000-05-10 adapted to BCC and MSVC
|
||||
* 2000-06-13 incorporated review results
|
||||
* 2000-07-06 moved basic templates from namespace detail to random
|
||||
* 2000-09-23 warning removals and int64 fixes (Ed Brey)
|
||||
* 2000-09-24 added lagged_fibonacci generator (Matthias Troyer)
|
||||
* 2001-02-18 moved to individual header files
|
||||
*/
|
||||
|
||||
#ifndef BOOST_RANDOM_HPP
|
||||
#define BOOST_RANDOM_HPP
|
||||
|
||||
// generators
|
||||
#include <boost/random/additive_combine.hpp>
|
||||
#include <boost/random/discard_block.hpp>
|
||||
#include <boost/random/independent_bits.hpp>
|
||||
#include <boost/random/inversive_congruential.hpp>
|
||||
#include <boost/random/lagged_fibonacci.hpp>
|
||||
#include <boost/random/linear_congruential.hpp>
|
||||
#include <boost/random/linear_feedback_shift.hpp>
|
||||
#include <boost/random/mersenne_twister.hpp>
|
||||
#include <boost/random/ranlux.hpp>
|
||||
#include <boost/random/shuffle_order.hpp>
|
||||
#include <boost/random/shuffle_output.hpp>
|
||||
#include <boost/random/subtract_with_carry.hpp>
|
||||
#include <boost/random/taus88.hpp>
|
||||
#include <boost/random/xor_combine.hpp>
|
||||
|
||||
// misc
|
||||
#include <boost/random/generate_canonical.hpp>
|
||||
#include <boost/random/seed_seq.hpp>
|
||||
#include <boost/random/random_number_generator.hpp>
|
||||
#include <boost/random/variate_generator.hpp>
|
||||
|
||||
// distributions
|
||||
#include <boost/random/bernoulli_distribution.hpp>
|
||||
#include <boost/random/beta_distribution.hpp>
|
||||
#include <boost/random/binomial_distribution.hpp>
|
||||
#include <boost/random/cauchy_distribution.hpp>
|
||||
#include <boost/random/chi_squared_distribution.hpp>
|
||||
#include <boost/random/discrete_distribution.hpp>
|
||||
#include <boost/random/exponential_distribution.hpp>
|
||||
#include <boost/random/extreme_value_distribution.hpp>
|
||||
#include <boost/random/fisher_f_distribution.hpp>
|
||||
#include <boost/random/gamma_distribution.hpp>
|
||||
#include <boost/random/geometric_distribution.hpp>
|
||||
#include <boost/random/hyperexponential_distribution.hpp>
|
||||
#include <boost/random/laplace_distribution.hpp>
|
||||
#include <boost/random/lognormal_distribution.hpp>
|
||||
#include <boost/random/negative_binomial_distribution.hpp>
|
||||
#include <boost/random/non_central_chi_squared_distribution.hpp>
|
||||
#include <boost/random/normal_distribution.hpp>
|
||||
#include <boost/random/piecewise_constant_distribution.hpp>
|
||||
#include <boost/random/piecewise_linear_distribution.hpp>
|
||||
#include <boost/random/poisson_distribution.hpp>
|
||||
#include <boost/random/student_t_distribution.hpp>
|
||||
#include <boost/random/triangle_distribution.hpp>
|
||||
#include <boost/random/uniform_01.hpp>
|
||||
#include <boost/random/uniform_int.hpp>
|
||||
#include <boost/random/uniform_int_distribution.hpp>
|
||||
#include <boost/random/uniform_on_sphere.hpp>
|
||||
#include <boost/random/uniform_real.hpp>
|
||||
#include <boost/random/uniform_real_distribution.hpp>
|
||||
#include <boost/random/uniform_smallint.hpp>
|
||||
#include <boost/random/weibull_distribution.hpp>
|
||||
|
||||
#include <boost/random/generate_canonical.hpp>
|
||||
|
||||
#endif // BOOST_RANDOM_HPP
|
@ -1,283 +0,0 @@
|
||||
/* 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
|
@ -1,197 +0,0 @@
|
||||
/* 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
|
@ -1,184 +0,0 @@
|
||||
/* 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
|
@ -1,434 +0,0 @@
|
||||
/* 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
|
@ -1,214 +0,0 @@
|
||||
/* 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
|
@ -1,209 +0,0 @@
|
||||
/* 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
|
@ -1,40 +0,0 @@
|
||||
/* 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
|
@ -1,18 +0,0 @@
|
||||
/* 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
|
@ -1,216 +0,0 @@
|
||||
/* 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
|
@ -1,29 +0,0 @@
|
||||
/* 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
|
@ -1,22 +0,0 @@
|
||||
/* 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
|
@ -1,36 +0,0 @@
|
||||
/* 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
|
@ -1,40 +0,0 @@
|
||||
/* 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
|
@ -1,121 +0,0 @@
|
||||
/* 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
|
@ -1,84 +0,0 @@
|
||||
/* 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
|
@ -1,45 +0,0 @@
|
||||
/* 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
|
@ -1,122 +0,0 @@
|
||||
/* 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
|
@ -1,84 +0,0 @@
|
||||
/* 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
|
@ -1,384 +0,0 @@
|
||||
/* 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
|
@ -1,67 +0,0 @@
|
||||
/* 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
|
@ -1,115 +0,0 @@
|
||||
/* 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
|
@ -1,398 +0,0 @@
|
||||
/* 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
|
@ -1,89 +0,0 @@
|
||||
/* 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
|
||||
|
@ -1,76 +0,0 @@
|
||||
/* 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
|
@ -1,75 +0,0 @@
|
||||
/* 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
|
@ -1,241 +0,0 @@
|
||||
/* 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
|
@ -1,636 +0,0 @@
|
||||
/* 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
|
@ -1,386 +0,0 @@
|
||||
/* 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
|
@ -1,177 +0,0 @@
|
||||
/* 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
|
@ -1,183 +0,0 @@
|
||||
/* 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
|
@ -1,292 +0,0 @@
|
||||
/* 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
|
@ -1,96 +0,0 @@
|
||||
/* 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
|
@ -1,267 +0,0 @@
|
||||
/* 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
|
@ -1,883 +0,0 @@
|
||||
/* 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
|
@ -1,271 +0,0 @@
|
||||
/* 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
|
@ -1,267 +0,0 @@
|
||||
/* 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
|
@ -1,537 +0,0 @@
|
||||
/* 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
|
@ -1,175 +0,0 @@
|
||||
/* 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
|
@ -1,466 +0,0 @@
|
||||
/* 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
|
@ -1,217 +0,0 @@
|
||||
/* 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
|
@ -1,254 +0,0 @@
|
||||
/* 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
|
@ -1,682 +0,0 @@
|
||||
/* 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
|
@ -1,220 +0,0 @@
|
||||
/* 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
|
@ -1,221 +0,0 @@
|
||||
/* 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
|
@ -1,374 +0,0 @@
|
||||
/* 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
|
@ -1,466 +0,0 @@
|
||||
/* 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
|
@ -1,531 +0,0 @@
|
||||
/* 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
|
@ -1,360 +0,0 @@
|
||||
/* 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
|
@ -1,143 +0,0 @@
|
||||
/* 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 */
|
@ -1,73 +0,0 @@
|
||||
/* 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
|
@ -1,99 +0,0 @@
|
||||
/* 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
|
@ -1,118 +0,0 @@
|
||||
/* 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
|
@ -1,269 +0,0 @@
|
||||
/* 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
|
@ -1,51 +0,0 @@
|
||||
/* 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
|
@ -1,180 +0,0 @@
|
||||
/* 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
|
@ -1,613 +0,0 @@
|
||||
/* 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
|
@ -1,45 +0,0 @@
|
||||
/* 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
|
@ -1,107 +0,0 @@
|
||||
/* 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
|
@ -1,232 +0,0 @@
|
||||
/* 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
|
@ -1,257 +0,0 @@
|
||||
/* 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
|
@ -1,99 +0,0 @@
|
||||
/* 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
|
@ -1,419 +0,0 @@
|
||||
/* 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
|
@ -1,284 +0,0 @@
|
||||
/* 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
|
@ -1,82 +0,0 @@
|
||||
/* 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
|
@ -1,241 +0,0 @@
|
||||
/* 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
|
@ -1,307 +0,0 @@
|
||||
/* 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
|
@ -1,122 +0,0 @@
|
||||
/* 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
|
@ -1,177 +0,0 @@
|
||||
/* 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
|
@ -1,208 +0,0 @@
|
||||
/* 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
|
201
contrib/libpcg-random/LICENSE-APACHE.txt
Normal file
201
contrib/libpcg-random/LICENSE-APACHE.txt
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
2
contrib/libpcg-random/README
Normal file
2
contrib/libpcg-random/README
Normal file
@ -0,0 +1,2 @@
|
||||
https://github.com/imneme/pcg-cpp
|
||||
0ca2e8ea6ba212bdfbc6219c2313c45917e34b8d
|
52
contrib/libpcg-random/README.md
Normal file
52
contrib/libpcg-random/README.md
Normal file
@ -0,0 +1,52 @@
|
||||
# PCG Random Number Generation, C++ Edition
|
||||
|
||||
[PCG-Random website]: http://www.pcg-random.org
|
||||
|
||||
This code provides an implementation of the PCG family of random number
|
||||
generators, which are fast, statistically excellent, and offer a number of
|
||||
useful features.
|
||||
|
||||
Full details can be found at the [PCG-Random website]. This version
|
||||
of the code provides many family members -- if you just want one
|
||||
simple generator, you may prefer the minimal C version of the library.
|
||||
|
||||
There are two kinds of generator, normal generators and extended generators.
|
||||
Extended generators provide *k* dimensional equidistribution and can perform
|
||||
party tricks, but generally speaking most people only need the normal
|
||||
generators.
|
||||
|
||||
There are two ways to access the generators, using a convenience typedef
|
||||
or by using the underlying templates directly (similar to C++11's `std::mt19937` typedef vs its `std::mersenne_twister_engine` template). For most users, the convenience typedef is what you want, and probably you're fine with `pcg32` for 32-bit numbers. If you want 64-bit numbers, either use `pcg64` (or, if you're on a 32-bit system, making 64 bits from two calls to `pcg32_k2` may be faster).
|
||||
|
||||
## Documentation and Examples
|
||||
|
||||
Visit [PCG-Random website] for information on how to use this library, or look
|
||||
at the sample code in the `sample` directory -- hopefully it should be fairly
|
||||
self explanatory.
|
||||
|
||||
## Building
|
||||
|
||||
The code is written in C++11, as an include-only library (i.e., there is
|
||||
nothing you need to build). There are some provided demo programs and tests
|
||||
however. On a Unix-style system (e.g., Linux, Mac OS X) you should be able
|
||||
to just type
|
||||
|
||||
make
|
||||
|
||||
To build the demo programs.
|
||||
|
||||
## Testing
|
||||
|
||||
Run
|
||||
|
||||
make test
|
||||
|
||||
## Directory Structure
|
||||
|
||||
The directories are arranged as follows:
|
||||
|
||||
* `include` -- contains `pcg_random.hpp` and supporting include files
|
||||
* `test-high` -- test code for the high-level API where the functions have
|
||||
shorter, less scary-looking names.
|
||||
* `sample` -- sample code, some similar to the code in `test-high` but more
|
||||
human readable, some other examples too
|
618
contrib/libpcg-random/include/pcg_extras.hpp
Normal file
618
contrib/libpcg-random/include/pcg_extras.hpp
Normal file
@ -0,0 +1,618 @@
|
||||
/*
|
||||
* PCG Random Number Generation for C++
|
||||
*
|
||||
* Copyright 2014-2017 Melissa O'Neill <oneill@pcg-random.org>,
|
||||
* and the PCG Project contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (provided in
|
||||
* LICENSE-APACHE.txt and at http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* or under the MIT license (provided in LICENSE-MIT.txt and at
|
||||
* http://opensource.org/licenses/MIT), at your option. This file may not
|
||||
* be copied, modified, or distributed except according to those terms.
|
||||
*
|
||||
* Distributed on an "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, either
|
||||
* express or implied. See your chosen license for details.
|
||||
*
|
||||
* For additional information about the PCG random number generation scheme,
|
||||
* visit http://www.pcg-random.org/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file provides support code that is useful for random-number generation
|
||||
* but not specific to the PCG generation scheme, including:
|
||||
* - 128-bit int support for platforms where it isn't available natively
|
||||
* - bit twiddling operations
|
||||
* - I/O of 128-bit and 8-bit integers
|
||||
* - Handling the evilness of SeedSeq
|
||||
* - Support for efficiently producing random numbers less than a given
|
||||
* bound
|
||||
*/
|
||||
|
||||
#ifndef PCG_EXTRAS_HPP_INCLUDED
|
||||
#define PCG_EXTRAS_HPP_INCLUDED 1
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
#include <iostream>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <locale>
|
||||
#include <iterator>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#include <cxxabi.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Abstractions for compiler-specific directives
|
||||
*/
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define PCG_NOINLINE __attribute__((noinline))
|
||||
#else
|
||||
#define PCG_NOINLINE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some members of the PCG library use 128-bit math. When compiling on 64-bit
|
||||
* platforms, both GCC and Clang provide 128-bit integer types that are ideal
|
||||
* for the job.
|
||||
*
|
||||
* On 32-bit platforms (or with other compilers), we fall back to a C++
|
||||
* class that provides 128-bit unsigned integers instead. It may seem
|
||||
* like we're reinventing the wheel here, because libraries already exist
|
||||
* that support large integers, but most existing libraries provide a very
|
||||
* generic multiprecision code, but here we're operating at a fixed size.
|
||||
* Also, most other libraries are fairly heavyweight. So we use a direct
|
||||
* implementation. Sadly, it's much slower than hand-coded assembly or
|
||||
* direct CPU support.
|
||||
*
|
||||
*/
|
||||
#if __SIZEOF_INT128__
|
||||
namespace pcg_extras {
|
||||
typedef __uint128_t pcg128_t;
|
||||
}
|
||||
#define PCG_128BIT_CONSTANT(high,low) \
|
||||
((pcg128_t(high) << 64) + low)
|
||||
#else
|
||||
#include "pcg_uint128.hpp"
|
||||
namespace pcg_extras {
|
||||
typedef pcg_extras::uint_x4<uint32_t,uint64_t> pcg128_t;
|
||||
}
|
||||
#define PCG_128BIT_CONSTANT(high,low) \
|
||||
pcg128_t(high,low)
|
||||
#define PCG_EMULATED_128BIT_MATH 1
|
||||
#endif
|
||||
|
||||
|
||||
namespace pcg_extras {
|
||||
|
||||
/*
|
||||
* We often need to represent a "number of bits". When used normally, these
|
||||
* numbers are never greater than 128, so an unsigned char is plenty.
|
||||
* If you're using a nonstandard generator of a larger size, you can set
|
||||
* PCG_BITCOUNT_T to have it define it as a larger size. (Some compilers
|
||||
* might produce faster code if you set it to an unsigned int.)
|
||||
*/
|
||||
|
||||
#ifndef PCG_BITCOUNT_T
|
||||
typedef uint8_t bitcount_t;
|
||||
#else
|
||||
typedef PCG_BITCOUNT_T bitcount_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* C++ requires us to be able to serialize RNG state by printing or reading
|
||||
* it from a stream. Because we use 128-bit ints, we also need to be able
|
||||
* ot print them, so here is code to do so.
|
||||
*
|
||||
* This code provides enough functionality to print 128-bit ints in decimal
|
||||
* and zero-padded in hex. It's not a full-featured implementation.
|
||||
*/
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::basic_ostream<CharT,Traits>&
|
||||
operator<<(std::basic_ostream<CharT,Traits>& out, pcg128_t value)
|
||||
{
|
||||
auto desired_base = out.flags() & out.basefield;
|
||||
bool want_hex = desired_base == out.hex;
|
||||
|
||||
if (want_hex) {
|
||||
uint64_t highpart = uint64_t(value >> 64);
|
||||
uint64_t lowpart = uint64_t(value);
|
||||
auto desired_width = out.width();
|
||||
if (desired_width > 16) {
|
||||
out.width(desired_width - 16);
|
||||
}
|
||||
if (highpart != 0 || desired_width > 16)
|
||||
out << highpart;
|
||||
CharT oldfill = '\0';
|
||||
if (highpart != 0) {
|
||||
out.width(16);
|
||||
oldfill = out.fill('0');
|
||||
}
|
||||
auto oldflags = out.setf(decltype(desired_base){}, out.showbase);
|
||||
out << lowpart;
|
||||
out.setf(oldflags);
|
||||
if (highpart != 0) {
|
||||
out.fill(oldfill);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
constexpr size_t MAX_CHARS_128BIT = 40;
|
||||
|
||||
char buffer[MAX_CHARS_128BIT];
|
||||
char* pos = buffer+sizeof(buffer);
|
||||
*(--pos) = '\0';
|
||||
constexpr auto BASE = pcg128_t(10ULL);
|
||||
do {
|
||||
auto div = value / BASE;
|
||||
auto mod = uint32_t(value - (div * BASE));
|
||||
*(--pos) = '0' + char(mod);
|
||||
value = div;
|
||||
} while(value != pcg128_t(0ULL));
|
||||
return out << pos;
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::basic_istream<CharT,Traits>&
|
||||
operator>>(std::basic_istream<CharT,Traits>& in, pcg128_t& value)
|
||||
{
|
||||
typename std::basic_istream<CharT,Traits>::sentry s(in);
|
||||
|
||||
if (!s)
|
||||
return in;
|
||||
|
||||
constexpr auto BASE = pcg128_t(10ULL);
|
||||
pcg128_t current(0ULL);
|
||||
bool did_nothing = true;
|
||||
bool overflow = false;
|
||||
for(;;) {
|
||||
CharT wide_ch = in.get();
|
||||
if (!in.good())
|
||||
break;
|
||||
auto ch = in.narrow(wide_ch, '\0');
|
||||
if (ch < '0' || ch > '9') {
|
||||
in.unget();
|
||||
break;
|
||||
}
|
||||
did_nothing = false;
|
||||
pcg128_t digit(uint32_t(ch - '0'));
|
||||
pcg128_t timesbase = current*BASE;
|
||||
overflow = overflow || timesbase < current;
|
||||
current = timesbase + digit;
|
||||
overflow = overflow || current < digit;
|
||||
}
|
||||
|
||||
if (did_nothing || overflow) {
|
||||
in.setstate(std::ios::failbit);
|
||||
if (overflow)
|
||||
current = ~pcg128_t(0ULL);
|
||||
}
|
||||
|
||||
value = current;
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
/*
|
||||
* Likewise, if people use tiny rngs, we'll be serializing uint8_t.
|
||||
* If we just used the provided IO operators, they'd read/write chars,
|
||||
* not ints, so we need to define our own. We *can* redefine this operator
|
||||
* here because we're in our own namespace.
|
||||
*/
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::basic_ostream<CharT,Traits>&
|
||||
operator<<(std::basic_ostream<CharT,Traits>&out, uint8_t value)
|
||||
{
|
||||
return out << uint32_t(value);
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::basic_istream<CharT,Traits>&
|
||||
operator>>(std::basic_istream<CharT,Traits>& in, uint8_t& target)
|
||||
{
|
||||
uint32_t value = 0xdecea5edU;
|
||||
in >> value;
|
||||
if (!in && value == 0xdecea5edU)
|
||||
return in;
|
||||
if (value > uint8_t(~0)) {
|
||||
in.setstate(std::ios::failbit);
|
||||
value = ~0U;
|
||||
}
|
||||
target = uint8_t(value);
|
||||
return in;
|
||||
}
|
||||
|
||||
/* Unfortunately, the above functions don't get found in preference to the
|
||||
* built in ones, so we create some more specific overloads that will.
|
||||
* Ugh.
|
||||
*/
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, uint8_t value)
|
||||
{
|
||||
return pcg_extras::operator<< <char>(out, value);
|
||||
}
|
||||
|
||||
inline std::istream& operator>>(std::istream& in, uint8_t& value)
|
||||
{
|
||||
return pcg_extras::operator>> <char>(in, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Useful bitwise operations.
|
||||
*/
|
||||
|
||||
/*
|
||||
* XorShifts are invertable, but they are someting of a pain to invert.
|
||||
* This function backs them out. It's used by the whacky "inside out"
|
||||
* generator defined later.
|
||||
*/
|
||||
|
||||
template <typename itype>
|
||||
inline itype unxorshift(itype x, bitcount_t bits, bitcount_t shift)
|
||||
{
|
||||
if (2*shift >= bits) {
|
||||
return x ^ (x >> shift);
|
||||
}
|
||||
itype lowmask1 = (itype(1U) << (bits - shift*2)) - 1;
|
||||
itype highmask1 = ~lowmask1;
|
||||
itype top1 = x;
|
||||
itype bottom1 = x & lowmask1;
|
||||
top1 ^= top1 >> shift;
|
||||
top1 &= highmask1;
|
||||
x = top1 | bottom1;
|
||||
itype lowmask2 = (itype(1U) << (bits - shift)) - 1;
|
||||
itype bottom2 = x & lowmask2;
|
||||
bottom2 = unxorshift(bottom2, bits - shift, shift);
|
||||
bottom2 &= lowmask1;
|
||||
return top1 | bottom2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotate left and right.
|
||||
*
|
||||
* In ideal world, compilers would spot idiomatic rotate code and convert it
|
||||
* to a rotate instruction. Of course, opinions vary on what the correct
|
||||
* idiom is and how to spot it. For clang, sometimes it generates better
|
||||
* (but still crappy) code if you define PCG_USE_ZEROCHECK_ROTATE_IDIOM.
|
||||
*/
|
||||
|
||||
template <typename itype>
|
||||
inline itype rotl(itype value, bitcount_t rot)
|
||||
{
|
||||
constexpr bitcount_t bits = sizeof(itype) * 8;
|
||||
constexpr bitcount_t mask = bits - 1;
|
||||
#if PCG_USE_ZEROCHECK_ROTATE_IDIOM
|
||||
return rot ? (value << rot) | (value >> (bits - rot)) : value;
|
||||
#else
|
||||
return (value << rot) | (value >> ((- rot) & mask));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename itype>
|
||||
inline itype rotr(itype value, bitcount_t rot)
|
||||
{
|
||||
constexpr bitcount_t bits = sizeof(itype) * 8;
|
||||
constexpr bitcount_t mask = bits - 1;
|
||||
#if PCG_USE_ZEROCHECK_ROTATE_IDIOM
|
||||
return rot ? (value >> rot) | (value << (bits - rot)) : value;
|
||||
#else
|
||||
return (value >> rot) | (value << ((- rot) & mask));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Unfortunately, both Clang and GCC sometimes perform poorly when it comes
|
||||
* to properly recognizing idiomatic rotate code, so for we also provide
|
||||
* assembler directives (enabled with PCG_USE_INLINE_ASM). Boo, hiss.
|
||||
* (I hope that these compilers get better so that this code can die.)
|
||||
*
|
||||
* These overloads will be preferred over the general template code above.
|
||||
*/
|
||||
#if PCG_USE_INLINE_ASM && __GNUC__ && (__x86_64__ || __i386__)
|
||||
|
||||
inline uint8_t rotr(uint8_t value, bitcount_t rot)
|
||||
{
|
||||
asm ("rorb %%cl, %0" : "=r" (value) : "0" (value), "c" (rot));
|
||||
return value;
|
||||
}
|
||||
|
||||
inline uint16_t rotr(uint16_t value, bitcount_t rot)
|
||||
{
|
||||
asm ("rorw %%cl, %0" : "=r" (value) : "0" (value), "c" (rot));
|
||||
return value;
|
||||
}
|
||||
|
||||
inline uint32_t rotr(uint32_t value, bitcount_t rot)
|
||||
{
|
||||
asm ("rorl %%cl, %0" : "=r" (value) : "0" (value), "c" (rot));
|
||||
return value;
|
||||
}
|
||||
|
||||
#if __x86_64__
|
||||
inline uint64_t rotr(uint64_t value, bitcount_t rot)
|
||||
{
|
||||
asm ("rorq %%cl, %0" : "=r" (value) : "0" (value), "c" (rot));
|
||||
return value;
|
||||
}
|
||||
#endif // __x86_64__
|
||||
|
||||
#endif // PCG_USE_INLINE_ASM
|
||||
|
||||
|
||||
/*
|
||||
* The C++ SeedSeq concept (modelled by seed_seq) can fill an array of
|
||||
* 32-bit integers with seed data, but sometimes we want to produce
|
||||
* larger or smaller integers.
|
||||
*
|
||||
* The following code handles this annoyance.
|
||||
*
|
||||
* uneven_copy will copy an array of 32-bit ints to an array of larger or
|
||||
* smaller ints (actually, the code is general it only needing forward
|
||||
* iterators). The copy is identical to the one that would be performed if
|
||||
* we just did memcpy on a standard little-endian machine, but works
|
||||
* regardless of the endian of the machine (or the weirdness of the ints
|
||||
* involved).
|
||||
*
|
||||
* generate_to initializes an array of integers using a SeedSeq
|
||||
* object. It is given the size as a static constant at compile time and
|
||||
* tries to avoid memory allocation. If we're filling in 32-bit constants
|
||||
* we just do it directly. If we need a separate buffer and it's small,
|
||||
* we allocate it on the stack. Otherwise, we fall back to heap allocation.
|
||||
* Ugh.
|
||||
*
|
||||
* generate_one produces a single value of some integral type using a
|
||||
* SeedSeq object.
|
||||
*/
|
||||
|
||||
/* uneven_copy helper, case where destination ints are less than 32 bit. */
|
||||
|
||||
template<class SrcIter, class DestIter>
|
||||
SrcIter uneven_copy_impl(
|
||||
SrcIter src_first, DestIter dest_first, DestIter dest_last,
|
||||
std::true_type)
|
||||
{
|
||||
typedef typename std::iterator_traits<SrcIter>::value_type src_t;
|
||||
typedef typename std::iterator_traits<DestIter>::value_type dest_t;
|
||||
|
||||
constexpr bitcount_t SRC_SIZE = sizeof(src_t);
|
||||
constexpr bitcount_t DEST_SIZE = sizeof(dest_t);
|
||||
constexpr bitcount_t DEST_BITS = DEST_SIZE * 8;
|
||||
constexpr bitcount_t SCALE = SRC_SIZE / DEST_SIZE;
|
||||
|
||||
size_t count = 0;
|
||||
src_t value = 0;
|
||||
|
||||
while (dest_first != dest_last) {
|
||||
if ((count++ % SCALE) == 0)
|
||||
value = *src_first++; // Get more bits
|
||||
else
|
||||
value >>= DEST_BITS; // Move down bits
|
||||
|
||||
*dest_first++ = dest_t(value); // Truncates, ignores high bits.
|
||||
}
|
||||
return src_first;
|
||||
}
|
||||
|
||||
/* uneven_copy helper, case where destination ints are more than 32 bit. */
|
||||
|
||||
template<class SrcIter, class DestIter>
|
||||
SrcIter uneven_copy_impl(
|
||||
SrcIter src_first, DestIter dest_first, DestIter dest_last,
|
||||
std::false_type)
|
||||
{
|
||||
typedef typename std::iterator_traits<SrcIter>::value_type src_t;
|
||||
typedef typename std::iterator_traits<DestIter>::value_type dest_t;
|
||||
|
||||
constexpr auto SRC_SIZE = sizeof(src_t);
|
||||
constexpr auto SRC_BITS = SRC_SIZE * 8;
|
||||
constexpr auto DEST_SIZE = sizeof(dest_t);
|
||||
constexpr auto SCALE = (DEST_SIZE+SRC_SIZE-1) / SRC_SIZE;
|
||||
|
||||
while (dest_first != dest_last) {
|
||||
dest_t value(0UL);
|
||||
unsigned int shift = 0;
|
||||
|
||||
for (size_t i = 0; i < SCALE; ++i) {
|
||||
value |= dest_t(*src_first++) << shift;
|
||||
shift += SRC_BITS;
|
||||
}
|
||||
|
||||
*dest_first++ = value;
|
||||
}
|
||||
return src_first;
|
||||
}
|
||||
|
||||
/* uneven_copy, call the right code for larger vs. smaller */
|
||||
|
||||
template<class SrcIter, class DestIter>
|
||||
inline SrcIter uneven_copy(SrcIter src_first,
|
||||
DestIter dest_first, DestIter dest_last)
|
||||
{
|
||||
typedef typename std::iterator_traits<SrcIter>::value_type src_t;
|
||||
typedef typename std::iterator_traits<DestIter>::value_type dest_t;
|
||||
|
||||
constexpr bool DEST_IS_SMALLER = sizeof(dest_t) < sizeof(src_t);
|
||||
|
||||
return uneven_copy_impl(src_first, dest_first, dest_last,
|
||||
std::integral_constant<bool, DEST_IS_SMALLER>{});
|
||||
}
|
||||
|
||||
/* generate_to, fill in a fixed-size array of integral type using a SeedSeq
|
||||
* (actually works for any random-access iterator)
|
||||
*/
|
||||
|
||||
template <size_t size, typename SeedSeq, typename DestIter>
|
||||
inline void generate_to_impl(SeedSeq&& generator, DestIter dest,
|
||||
std::true_type)
|
||||
{
|
||||
generator.generate(dest, dest+size);
|
||||
}
|
||||
|
||||
template <size_t size, typename SeedSeq, typename DestIter>
|
||||
void generate_to_impl(SeedSeq&& generator, DestIter dest,
|
||||
std::false_type)
|
||||
{
|
||||
typedef typename std::iterator_traits<DestIter>::value_type dest_t;
|
||||
constexpr auto DEST_SIZE = sizeof(dest_t);
|
||||
constexpr auto GEN_SIZE = sizeof(uint32_t);
|
||||
|
||||
constexpr bool GEN_IS_SMALLER = GEN_SIZE < DEST_SIZE;
|
||||
constexpr size_t FROM_ELEMS =
|
||||
GEN_IS_SMALLER
|
||||
? size * ((DEST_SIZE+GEN_SIZE-1) / GEN_SIZE)
|
||||
: (size + (GEN_SIZE / DEST_SIZE) - 1)
|
||||
/ ((GEN_SIZE / DEST_SIZE) + GEN_IS_SMALLER);
|
||||
// this odd code ^^^^^^^^^^^^^^^^^ is work-around for
|
||||
// a bug: http://llvm.org/bugs/show_bug.cgi?id=21287
|
||||
|
||||
if (FROM_ELEMS <= 1024) {
|
||||
uint32_t buffer[FROM_ELEMS];
|
||||
generator.generate(buffer, buffer+FROM_ELEMS);
|
||||
uneven_copy(buffer, dest, dest+size);
|
||||
} else {
|
||||
uint32_t* buffer = static_cast<uint32_t*>(malloc(GEN_SIZE * FROM_ELEMS));
|
||||
generator.generate(buffer, buffer+FROM_ELEMS);
|
||||
uneven_copy(buffer, dest, dest+size);
|
||||
free(static_cast<void*>(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t size, typename SeedSeq, typename DestIter>
|
||||
inline void generate_to(SeedSeq&& generator, DestIter dest)
|
||||
{
|
||||
typedef typename std::iterator_traits<DestIter>::value_type dest_t;
|
||||
constexpr bool IS_32BIT = sizeof(dest_t) == sizeof(uint32_t);
|
||||
|
||||
generate_to_impl<size>(std::forward<SeedSeq>(generator), dest,
|
||||
std::integral_constant<bool, IS_32BIT>{});
|
||||
}
|
||||
|
||||
/* generate_one, produce a value of integral type using a SeedSeq
|
||||
* (optionally, we can have it produce more than one and pick which one
|
||||
* we want)
|
||||
*/
|
||||
|
||||
template <typename UInt, size_t i = 0UL, size_t N = i+1UL, typename SeedSeq>
|
||||
inline UInt generate_one(SeedSeq&& generator)
|
||||
{
|
||||
UInt result[N];
|
||||
generate_to<N>(std::forward<SeedSeq>(generator), result);
|
||||
return result[i];
|
||||
}
|
||||
|
||||
template <typename RngType>
|
||||
auto bounded_rand(RngType& rng, typename RngType::result_type upper_bound)
|
||||
-> typename RngType::result_type
|
||||
{
|
||||
typedef typename RngType::result_type rtype;
|
||||
rtype threshold = (RngType::max() - RngType::min() + rtype(1) - upper_bound)
|
||||
% upper_bound;
|
||||
for (;;) {
|
||||
rtype r = rng() - RngType::min();
|
||||
if (r >= threshold)
|
||||
return r % upper_bound;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iter, typename RandType>
|
||||
void shuffle(Iter from, Iter to, RandType&& rng)
|
||||
{
|
||||
typedef typename std::iterator_traits<Iter>::difference_type delta_t;
|
||||
typedef typename std::remove_reference<RandType>::type::result_type result_t;
|
||||
auto count = to - from;
|
||||
while (count > 1) {
|
||||
delta_t chosen = delta_t(bounded_rand(rng, result_t(count)));
|
||||
--count;
|
||||
--to;
|
||||
using std::swap;
|
||||
swap(*(from + chosen), *to);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Although std::seed_seq is useful, it isn't everything. Often we want to
|
||||
* initialize a random-number generator some other way, such as from a random
|
||||
* device.
|
||||
*
|
||||
* Technically, it does not meet the requirements of a SeedSequence because
|
||||
* it lacks some of the rarely-used member functions (some of which would
|
||||
* be impossible to provide). However the C++ standard is quite specific
|
||||
* that actual engines only called the generate method, so it ought not to be
|
||||
* a problem in practice.
|
||||
*/
|
||||
|
||||
template <typename RngType>
|
||||
class seed_seq_from {
|
||||
private:
|
||||
RngType rng_;
|
||||
|
||||
typedef uint_least32_t result_type;
|
||||
|
||||
public:
|
||||
template<typename... Args>
|
||||
seed_seq_from(Args&&... args) :
|
||||
rng_(std::forward<Args>(args)...)
|
||||
{
|
||||
// Nothing (else) to do...
|
||||
}
|
||||
|
||||
template<typename Iter>
|
||||
void generate(Iter start, Iter finish)
|
||||
{
|
||||
for (auto i = start; i != finish; ++i)
|
||||
*i = result_type(rng_());
|
||||
}
|
||||
|
||||
constexpr size_t size() const
|
||||
{
|
||||
return (sizeof(typename RngType::result_type) > sizeof(result_type)
|
||||
&& RngType::max() > ~size_t(0UL))
|
||||
? ~size_t(0UL)
|
||||
: size_t(RngType::max());
|
||||
}
|
||||
};
|
||||
|
||||
// Sometimes, when debugging or testing, it's handy to be able print the name
|
||||
// of a (in human-readable form). This code allows the idiom:
|
||||
//
|
||||
// cout << printable_typename<my_foo_type_t>()
|
||||
//
|
||||
// to print out my_foo_type_t (or its concrete type if it is a synonym)
|
||||
|
||||
#if __cpp_rtti || __GXX_RTTI
|
||||
|
||||
template <typename T>
|
||||
struct printable_typename {};
|
||||
|
||||
template <typename T>
|
||||
std::ostream& operator<<(std::ostream& out, printable_typename<T>) {
|
||||
const char *implementation_typename = typeid(T).name();
|
||||
#ifdef __GNUC__
|
||||
int status;
|
||||
char* pretty_name =
|
||||
abi::__cxa_demangle(implementation_typename, NULL, NULL, &status);
|
||||
if (status == 0)
|
||||
out << pretty_name;
|
||||
free(static_cast<void*>(pretty_name));
|
||||
if (status == 0)
|
||||
return out;
|
||||
#endif
|
||||
out << implementation_typename;
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif // __cpp_rtti || __GXX_RTTI
|
||||
|
||||
} // namespace pcg_extras
|
||||
|
||||
#endif // PCG_EXTRAS_HPP_INCLUDED
|
1771
contrib/libpcg-random/include/pcg_random.hpp
Normal file
1771
contrib/libpcg-random/include/pcg_random.hpp
Normal file
File diff suppressed because it is too large
Load Diff
748
contrib/libpcg-random/include/pcg_uint128.hpp
Normal file
748
contrib/libpcg-random/include/pcg_uint128.hpp
Normal file
@ -0,0 +1,748 @@
|
||||
/*
|
||||
* PCG Random Number Generation for C++
|
||||
*
|
||||
* Copyright 2014-2017 Melissa O'Neill <oneill@pcg-random.org>,
|
||||
* and the PCG Project contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (provided in
|
||||
* LICENSE-APACHE.txt and at http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* or under the MIT license (provided in LICENSE-MIT.txt and at
|
||||
* http://opensource.org/licenses/MIT), at your option. This file may not
|
||||
* be copied, modified, or distributed except according to those terms.
|
||||
*
|
||||
* Distributed on an "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, either
|
||||
* express or implied. See your chosen license for details.
|
||||
*
|
||||
* For additional information about the PCG random number generation scheme,
|
||||
* visit http://www.pcg-random.org/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code provides a a C++ class that can provide 128-bit (or higher)
|
||||
* integers. To produce 2K-bit integers, it uses two K-bit integers,
|
||||
* placed in a union that allowes the code to also see them as four K/2 bit
|
||||
* integers (and access them either directly name, or by index).
|
||||
*
|
||||
* It may seem like we're reinventing the wheel here, because several
|
||||
* libraries already exist that support large integers, but most existing
|
||||
* libraries provide a very generic multiprecision code, but here we're
|
||||
* operating at a fixed size. Also, most other libraries are fairly
|
||||
* heavyweight. So we use a direct implementation. Sadly, it's much slower
|
||||
* than hand-coded assembly or direct CPU support.
|
||||
*/
|
||||
|
||||
#ifndef PCG_UINT128_HPP_INCLUDED
|
||||
#define PCG_UINT128_HPP_INCLUDED 1
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <utility>
|
||||
#include <initializer_list>
|
||||
#include <type_traits>
|
||||
|
||||
/*
|
||||
* We want to lay the type out the same way that a native type would be laid
|
||||
* out, which means we must know the machine's endian, at compile time.
|
||||
* This ugliness attempts to do so.
|
||||
*/
|
||||
|
||||
#ifndef PCG_LITTLE_ENDIAN
|
||||
#if defined(__BYTE_ORDER__)
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define PCG_LITTLE_ENDIAN 1
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define PCG_LITTLE_ENDIAN 0
|
||||
#else
|
||||
#error __BYTE_ORDER__ does not match a standard endian, pick a side
|
||||
#endif
|
||||
#elif __LITTLE_ENDIAN__ || _LITTLE_ENDIAN
|
||||
#define PCG_LITTLE_ENDIAN 1
|
||||
#elif __BIG_ENDIAN__ || _BIG_ENDIAN
|
||||
#define PCG_LITTLE_ENDIAN 0
|
||||
#elif __x86_64 || __x86_64__ || _M_X64 || __i386 || __i386__ || _M_IX86
|
||||
#define PCG_LITTLE_ENDIAN 1
|
||||
#elif __powerpc__ || __POWERPC__ || __ppc__ || __PPC__ \
|
||||
|| __m68k__ || __mc68000__
|
||||
#define PCG_LITTLE_ENDIAN 0
|
||||
#else
|
||||
#error Unable to determine target endianness
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace pcg_extras {
|
||||
|
||||
// Recent versions of GCC have intrinsics we can use to quickly calculate
|
||||
// the number of leading and trailing zeros in a number. If possible, we
|
||||
// use them, otherwise we fall back to old-fashioned bit twiddling to figure
|
||||
// them out.
|
||||
|
||||
#ifndef PCG_BITCOUNT_T
|
||||
typedef uint8_t bitcount_t;
|
||||
#else
|
||||
typedef PCG_BITCOUNT_T bitcount_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Provide some useful helper functions
|
||||
* * flog2 floor(log2(x))
|
||||
* * trailingzeros number of trailing zero bits
|
||||
*/
|
||||
|
||||
#ifdef __GNUC__ // Any GNU-compatible compiler supporting C++11 has
|
||||
// some useful intrinsics we can use.
|
||||
|
||||
inline bitcount_t flog2(uint32_t v)
|
||||
{
|
||||
return 31 - __builtin_clz(v);
|
||||
}
|
||||
|
||||
inline bitcount_t trailingzeros(uint32_t v)
|
||||
{
|
||||
return __builtin_ctz(v);
|
||||
}
|
||||
|
||||
inline bitcount_t flog2(uint64_t v)
|
||||
{
|
||||
#if UINT64_MAX == ULONG_MAX
|
||||
return 63 - __builtin_clzl(v);
|
||||
#elif UINT64_MAX == ULLONG_MAX
|
||||
return 63 - __builtin_clzll(v);
|
||||
#else
|
||||
#error Cannot find a function for uint64_t
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bitcount_t trailingzeros(uint64_t v)
|
||||
{
|
||||
#if UINT64_MAX == ULONG_MAX
|
||||
return __builtin_ctzl(v);
|
||||
#elif UINT64_MAX == ULLONG_MAX
|
||||
return __builtin_ctzll(v);
|
||||
#else
|
||||
#error Cannot find a function for uint64_t
|
||||
#endif
|
||||
}
|
||||
|
||||
#else // Otherwise, we fall back to bit twiddling
|
||||
// implementations
|
||||
|
||||
inline bitcount_t flog2(uint32_t v)
|
||||
{
|
||||
// Based on code by Eric Cole and Mark Dickinson, which appears at
|
||||
// https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
|
||||
|
||||
static const uint8_t multiplyDeBruijnBitPos[32] = {
|
||||
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
|
||||
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
|
||||
};
|
||||
|
||||
v |= v >> 1; // first round down to one less than a power of 2
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
|
||||
return multiplyDeBruijnBitPos[(uint32_t)(v * 0x07C4ACDDU) >> 27];
|
||||
}
|
||||
|
||||
inline bitcount_t trailingzeros(uint32_t v)
|
||||
{
|
||||
static const uint8_t multiplyDeBruijnBitPos[32] = {
|
||||
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
|
||||
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
|
||||
};
|
||||
|
||||
return multiplyDeBruijnBitPos[((uint32_t)((v & -v) * 0x077CB531U)) >> 27];
|
||||
}
|
||||
|
||||
inline bitcount_t flog2(uint64_t v)
|
||||
{
|
||||
uint32_t high = v >> 32;
|
||||
uint32_t low = uint32_t(v);
|
||||
|
||||
return high ? 32+flog2(high) : flog2(low);
|
||||
}
|
||||
|
||||
inline bitcount_t trailingzeros(uint64_t v)
|
||||
{
|
||||
uint32_t high = v >> 32;
|
||||
uint32_t low = uint32_t(v);
|
||||
|
||||
return low ? trailingzeros(low) : trailingzeros(high)+32;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template <typename UInt>
|
||||
inline bitcount_t clog2(UInt v)
|
||||
{
|
||||
return flog2(v) + ((v & (-v)) != v);
|
||||
}
|
||||
|
||||
template <typename UInt>
|
||||
inline UInt addwithcarry(UInt x, UInt y, bool carryin, bool* carryout)
|
||||
{
|
||||
UInt half_result = y + carryin;
|
||||
UInt result = x + half_result;
|
||||
*carryout = (half_result < y) || (result < x);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename UInt>
|
||||
inline UInt subwithcarry(UInt x, UInt y, bool carryin, bool* carryout)
|
||||
{
|
||||
UInt half_result = y + carryin;
|
||||
UInt result = x - half_result;
|
||||
*carryout = (half_result < y) || (result > x);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
class uint_x4 {
|
||||
// private:
|
||||
public:
|
||||
union {
|
||||
#if PCG_LITTLE_ENDIAN
|
||||
struct {
|
||||
UInt v0, v1, v2, v3;
|
||||
} w;
|
||||
struct {
|
||||
UIntX2 v01, v23;
|
||||
} d;
|
||||
#else
|
||||
struct {
|
||||
UInt v3, v2, v1, v0;
|
||||
} w;
|
||||
struct {
|
||||
UIntX2 v23, v01;
|
||||
} d;
|
||||
#endif
|
||||
// For the array access versions, the code that uses the array
|
||||
// must handle endian itself. Yuck.
|
||||
UInt wa[4];
|
||||
UIntX2 da[2];
|
||||
};
|
||||
|
||||
public:
|
||||
uint_x4() = default;
|
||||
|
||||
constexpr uint_x4(UInt v3, UInt v2, UInt v1, UInt v0)
|
||||
#if PCG_LITTLE_ENDIAN
|
||||
: w{v0, v1, v2, v3}
|
||||
#else
|
||||
: w{v3, v2, v1, v0}
|
||||
#endif
|
||||
{
|
||||
// Nothing (else) to do
|
||||
}
|
||||
|
||||
constexpr uint_x4(UIntX2 v23, UIntX2 v01)
|
||||
#if PCG_LITTLE_ENDIAN
|
||||
: d{v01,v23}
|
||||
#else
|
||||
: d{v23,v01}
|
||||
#endif
|
||||
{
|
||||
// Nothing (else) to do
|
||||
}
|
||||
|
||||
template<class Integral,
|
||||
typename std::enable_if<(std::is_integral<Integral>::value
|
||||
&& sizeof(Integral) <= sizeof(UIntX2))
|
||||
>::type* = nullptr>
|
||||
constexpr uint_x4(Integral v01)
|
||||
#if PCG_LITTLE_ENDIAN
|
||||
: d{UIntX2(v01),0UL}
|
||||
#else
|
||||
: d{0UL,UIntX2(v01)}
|
||||
#endif
|
||||
{
|
||||
// Nothing (else) to do
|
||||
}
|
||||
|
||||
explicit constexpr operator uint64_t() const
|
||||
{
|
||||
return d.v01;
|
||||
}
|
||||
|
||||
explicit constexpr operator uint32_t() const
|
||||
{
|
||||
return w.v0;
|
||||
}
|
||||
|
||||
explicit constexpr operator int() const
|
||||
{
|
||||
return w.v0;
|
||||
}
|
||||
|
||||
explicit constexpr operator uint16_t() const
|
||||
{
|
||||
return w.v0;
|
||||
}
|
||||
|
||||
explicit constexpr operator uint8_t() const
|
||||
{
|
||||
return w.v0;
|
||||
}
|
||||
|
||||
typedef typename std::conditional<std::is_same<uint64_t,
|
||||
unsigned long>::value,
|
||||
unsigned long long,
|
||||
unsigned long>::type
|
||||
uint_missing_t;
|
||||
|
||||
explicit constexpr operator uint_missing_t() const
|
||||
{
|
||||
return d.v01;
|
||||
}
|
||||
|
||||
explicit constexpr operator bool() const
|
||||
{
|
||||
return d.v01 || d.v23;
|
||||
}
|
||||
|
||||
template<typename U, typename V>
|
||||
friend uint_x4<U,V> operator*(const uint_x4<U,V>&, const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend std::pair< uint_x4<U,V>,uint_x4<U,V> >
|
||||
divmod(const uint_x4<U,V>&, const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend uint_x4<U,V> operator+(const uint_x4<U,V>&, const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend uint_x4<U,V> operator-(const uint_x4<U,V>&, const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend uint_x4<U,V> operator<<(const uint_x4<U,V>&, const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend uint_x4<U,V> operator>>(const uint_x4<U,V>&, const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend uint_x4<U,V> operator&(const uint_x4<U,V>&, const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend uint_x4<U,V> operator|(const uint_x4<U,V>&, const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend uint_x4<U,V> operator^(const uint_x4<U,V>&, const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend bool operator==(const uint_x4<U,V>&, const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend bool operator!=(const uint_x4<U,V>&, const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend bool operator<(const uint_x4<U,V>&, const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend bool operator<=(const uint_x4<U,V>&, const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend bool operator>(const uint_x4<U,V>&, const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend bool operator>=(const uint_x4<U,V>&, const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend uint_x4<U,V> operator~(const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend uint_x4<U,V> operator-(const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend bitcount_t flog2(const uint_x4<U,V>&);
|
||||
|
||||
template<typename U, typename V>
|
||||
friend bitcount_t trailingzeros(const uint_x4<U,V>&);
|
||||
|
||||
uint_x4& operator*=(const uint_x4& rhs)
|
||||
{
|
||||
uint_x4 result = *this * rhs;
|
||||
return *this = result;
|
||||
}
|
||||
|
||||
uint_x4& operator/=(const uint_x4& rhs)
|
||||
{
|
||||
uint_x4 result = *this / rhs;
|
||||
return *this = result;
|
||||
}
|
||||
|
||||
uint_x4& operator%=(const uint_x4& rhs)
|
||||
{
|
||||
uint_x4 result = *this % rhs;
|
||||
return *this = result;
|
||||
}
|
||||
|
||||
uint_x4& operator+=(const uint_x4& rhs)
|
||||
{
|
||||
uint_x4 result = *this + rhs;
|
||||
return *this = result;
|
||||
}
|
||||
|
||||
uint_x4& operator-=(const uint_x4& rhs)
|
||||
{
|
||||
uint_x4 result = *this - rhs;
|
||||
return *this = result;
|
||||
}
|
||||
|
||||
uint_x4& operator&=(const uint_x4& rhs)
|
||||
{
|
||||
uint_x4 result = *this & rhs;
|
||||
return *this = result;
|
||||
}
|
||||
|
||||
uint_x4& operator|=(const uint_x4& rhs)
|
||||
{
|
||||
uint_x4 result = *this | rhs;
|
||||
return *this = result;
|
||||
}
|
||||
|
||||
uint_x4& operator^=(const uint_x4& rhs)
|
||||
{
|
||||
uint_x4 result = *this ^ rhs;
|
||||
return *this = result;
|
||||
}
|
||||
|
||||
uint_x4& operator>>=(bitcount_t shift)
|
||||
{
|
||||
uint_x4 result = *this >> shift;
|
||||
return *this = result;
|
||||
}
|
||||
|
||||
uint_x4& operator<<=(bitcount_t shift)
|
||||
{
|
||||
uint_x4 result = *this << shift;
|
||||
return *this = result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename U, typename V>
|
||||
bitcount_t flog2(const uint_x4<U,V>& v)
|
||||
{
|
||||
#if PCG_LITTLE_ENDIAN
|
||||
for (uint8_t i = 4; i !=0; /* dec in loop */) {
|
||||
--i;
|
||||
#else
|
||||
for (uint8_t i = 0; i < 4; ++i) {
|
||||
#endif
|
||||
if (v.wa[i] == 0)
|
||||
continue;
|
||||
return flog2(v.wa[i]) + (sizeof(U)*CHAR_BIT)*i;
|
||||
}
|
||||
abort();
|
||||
}
|
||||
|
||||
template<typename U, typename V>
|
||||
bitcount_t trailingzeros(const uint_x4<U,V>& v)
|
||||
{
|
||||
#if PCG_LITTLE_ENDIAN
|
||||
for (uint8_t i = 0; i < 4; ++i) {
|
||||
#else
|
||||
for (uint8_t i = 4; i !=0; /* dec in loop */) {
|
||||
--i;
|
||||
#endif
|
||||
if (v.wa[i] != 0)
|
||||
return trailingzeros(v.wa[i]) + (sizeof(U)*CHAR_BIT)*i;
|
||||
}
|
||||
return (sizeof(U)*CHAR_BIT)*4;
|
||||
}
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
std::pair< uint_x4<UInt,UIntX2>, uint_x4<UInt,UIntX2> >
|
||||
divmod(const uint_x4<UInt,UIntX2>& orig_dividend,
|
||||
const uint_x4<UInt,UIntX2>& divisor)
|
||||
{
|
||||
// If the dividend is less than the divisor, the answer is always zero.
|
||||
// This takes care of boundary cases like 0/x (which would otherwise be
|
||||
// problematic because we can't take the log of zero. (The boundary case
|
||||
// of division by zero is undefined.)
|
||||
if (orig_dividend < divisor)
|
||||
return { uint_x4<UInt,UIntX2>(0UL), orig_dividend };
|
||||
|
||||
auto dividend = orig_dividend;
|
||||
|
||||
auto log2_divisor = flog2(divisor);
|
||||
auto log2_dividend = flog2(dividend);
|
||||
// assert(log2_dividend >= log2_divisor);
|
||||
bitcount_t logdiff = log2_dividend - log2_divisor;
|
||||
|
||||
constexpr uint_x4<UInt,UIntX2> ONE(1UL);
|
||||
if (logdiff == 0)
|
||||
return { ONE, dividend - divisor };
|
||||
|
||||
// Now we change the log difference to
|
||||
// floor(log2(divisor)) - ceil(log2(dividend))
|
||||
// to ensure that we *underestimate* the result.
|
||||
logdiff -= 1;
|
||||
|
||||
uint_x4<UInt,UIntX2> quotient(0UL);
|
||||
|
||||
auto qfactor = ONE << logdiff;
|
||||
auto factor = divisor << logdiff;
|
||||
|
||||
do {
|
||||
dividend -= factor;
|
||||
quotient += qfactor;
|
||||
while (dividend < factor) {
|
||||
factor >>= 1;
|
||||
qfactor >>= 1;
|
||||
}
|
||||
} while (dividend >= divisor);
|
||||
|
||||
return { quotient, dividend };
|
||||
}
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
uint_x4<UInt,UIntX2> operator/(const uint_x4<UInt,UIntX2>& dividend,
|
||||
const uint_x4<UInt,UIntX2>& divisor)
|
||||
{
|
||||
return divmod(dividend, divisor).first;
|
||||
}
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
uint_x4<UInt,UIntX2> operator%(const uint_x4<UInt,UIntX2>& dividend,
|
||||
const uint_x4<UInt,UIntX2>& divisor)
|
||||
{
|
||||
return divmod(dividend, divisor).second;
|
||||
}
|
||||
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
uint_x4<UInt,UIntX2> operator*(const uint_x4<UInt,UIntX2>& a,
|
||||
const uint_x4<UInt,UIntX2>& b)
|
||||
{
|
||||
uint_x4<UInt,UIntX2> r = {0U, 0U, 0U, 0U};
|
||||
bool carryin = false;
|
||||
bool carryout;
|
||||
UIntX2 a0b0 = UIntX2(a.w.v0) * UIntX2(b.w.v0);
|
||||
r.w.v0 = UInt(a0b0);
|
||||
r.w.v1 = UInt(a0b0 >> 32);
|
||||
|
||||
UIntX2 a1b0 = UIntX2(a.w.v1) * UIntX2(b.w.v0);
|
||||
r.w.v2 = UInt(a1b0 >> 32);
|
||||
r.w.v1 = addwithcarry(r.w.v1, UInt(a1b0), carryin, &carryout);
|
||||
carryin = carryout;
|
||||
r.w.v2 = addwithcarry(r.w.v2, UInt(0U), carryin, &carryout);
|
||||
carryin = carryout;
|
||||
r.w.v3 = addwithcarry(r.w.v3, UInt(0U), carryin, &carryout);
|
||||
|
||||
UIntX2 a0b1 = UIntX2(a.w.v0) * UIntX2(b.w.v1);
|
||||
carryin = false;
|
||||
r.w.v2 = addwithcarry(r.w.v2, UInt(a0b1 >> 32), carryin, &carryout);
|
||||
carryin = carryout;
|
||||
r.w.v3 = addwithcarry(r.w.v3, UInt(0U), carryin, &carryout);
|
||||
|
||||
carryin = false;
|
||||
r.w.v1 = addwithcarry(r.w.v1, UInt(a0b1), carryin, &carryout);
|
||||
carryin = carryout;
|
||||
r.w.v2 = addwithcarry(r.w.v2, UInt(0U), carryin, &carryout);
|
||||
carryin = carryout;
|
||||
r.w.v3 = addwithcarry(r.w.v3, UInt(0U), carryin, &carryout);
|
||||
|
||||
UIntX2 a1b1 = UIntX2(a.w.v1) * UIntX2(b.w.v1);
|
||||
carryin = false;
|
||||
r.w.v2 = addwithcarry(r.w.v2, UInt(a1b1), carryin, &carryout);
|
||||
carryin = carryout;
|
||||
r.w.v3 = addwithcarry(r.w.v3, UInt(a1b1 >> 32), carryin, &carryout);
|
||||
|
||||
r.d.v23 += a.d.v01 * b.d.v23 + a.d.v23 * b.d.v01;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
uint_x4<UInt,UIntX2> operator+(const uint_x4<UInt,UIntX2>& a,
|
||||
const uint_x4<UInt,UIntX2>& b)
|
||||
{
|
||||
uint_x4<UInt,UIntX2> r = {0U, 0U, 0U, 0U};
|
||||
|
||||
bool carryin = false;
|
||||
bool carryout;
|
||||
r.w.v0 = addwithcarry(a.w.v0, b.w.v0, carryin, &carryout);
|
||||
carryin = carryout;
|
||||
r.w.v1 = addwithcarry(a.w.v1, b.w.v1, carryin, &carryout);
|
||||
carryin = carryout;
|
||||
r.w.v2 = addwithcarry(a.w.v2, b.w.v2, carryin, &carryout);
|
||||
carryin = carryout;
|
||||
r.w.v3 = addwithcarry(a.w.v3, b.w.v3, carryin, &carryout);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
uint_x4<UInt,UIntX2> operator-(const uint_x4<UInt,UIntX2>& a,
|
||||
const uint_x4<UInt,UIntX2>& b)
|
||||
{
|
||||
uint_x4<UInt,UIntX2> r = {0U, 0U, 0U, 0U};
|
||||
|
||||
bool carryin = false;
|
||||
bool carryout;
|
||||
r.w.v0 = subwithcarry(a.w.v0, b.w.v0, carryin, &carryout);
|
||||
carryin = carryout;
|
||||
r.w.v1 = subwithcarry(a.w.v1, b.w.v1, carryin, &carryout);
|
||||
carryin = carryout;
|
||||
r.w.v2 = subwithcarry(a.w.v2, b.w.v2, carryin, &carryout);
|
||||
carryin = carryout;
|
||||
r.w.v3 = subwithcarry(a.w.v3, b.w.v3, carryin, &carryout);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
uint_x4<UInt,UIntX2> operator&(const uint_x4<UInt,UIntX2>& a,
|
||||
const uint_x4<UInt,UIntX2>& b)
|
||||
{
|
||||
return uint_x4<UInt,UIntX2>(a.d.v23 & b.d.v23, a.d.v01 & b.d.v01);
|
||||
}
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
uint_x4<UInt,UIntX2> operator|(const uint_x4<UInt,UIntX2>& a,
|
||||
const uint_x4<UInt,UIntX2>& b)
|
||||
{
|
||||
return uint_x4<UInt,UIntX2>(a.d.v23 | b.d.v23, a.d.v01 | b.d.v01);
|
||||
}
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
uint_x4<UInt,UIntX2> operator^(const uint_x4<UInt,UIntX2>& a,
|
||||
const uint_x4<UInt,UIntX2>& b)
|
||||
{
|
||||
return uint_x4<UInt,UIntX2>(a.d.v23 ^ b.d.v23, a.d.v01 ^ b.d.v01);
|
||||
}
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
uint_x4<UInt,UIntX2> operator~(const uint_x4<UInt,UIntX2>& v)
|
||||
{
|
||||
return uint_x4<UInt,UIntX2>(~v.d.v23, ~v.d.v01);
|
||||
}
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
uint_x4<UInt,UIntX2> operator-(const uint_x4<UInt,UIntX2>& v)
|
||||
{
|
||||
return uint_x4<UInt,UIntX2>(0UL,0UL) - v;
|
||||
}
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
bool operator==(const uint_x4<UInt,UIntX2>& a, const uint_x4<UInt,UIntX2>& b)
|
||||
{
|
||||
return (a.d.v01 == b.d.v01) && (a.d.v23 == b.d.v23);
|
||||
}
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
bool operator!=(const uint_x4<UInt,UIntX2>& a, const uint_x4<UInt,UIntX2>& b)
|
||||
{
|
||||
return !operator==(a,b);
|
||||
}
|
||||
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
bool operator<(const uint_x4<UInt,UIntX2>& a, const uint_x4<UInt,UIntX2>& b)
|
||||
{
|
||||
return (a.d.v23 < b.d.v23)
|
||||
|| ((a.d.v23 == b.d.v23) && (a.d.v01 < b.d.v01));
|
||||
}
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
bool operator>(const uint_x4<UInt,UIntX2>& a, const uint_x4<UInt,UIntX2>& b)
|
||||
{
|
||||
return operator<(b,a);
|
||||
}
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
bool operator<=(const uint_x4<UInt,UIntX2>& a, const uint_x4<UInt,UIntX2>& b)
|
||||
{
|
||||
return !(operator<(b,a));
|
||||
}
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
bool operator>=(const uint_x4<UInt,UIntX2>& a, const uint_x4<UInt,UIntX2>& b)
|
||||
{
|
||||
return !(operator<(a,b));
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
uint_x4<UInt,UIntX2> operator<<(const uint_x4<UInt,UIntX2>& v,
|
||||
const bitcount_t shift)
|
||||
{
|
||||
uint_x4<UInt,UIntX2> r = {0U, 0U, 0U, 0U};
|
||||
const bitcount_t bits = sizeof(UInt) * CHAR_BIT;
|
||||
const bitcount_t bitmask = bits - 1;
|
||||
const bitcount_t shiftdiv = shift / bits;
|
||||
const bitcount_t shiftmod = shift & bitmask;
|
||||
|
||||
if (shiftmod) {
|
||||
UInt carryover = 0;
|
||||
#if PCG_LITTLE_ENDIAN
|
||||
for (uint8_t out = shiftdiv, in = 0; out < 4; ++out, ++in) {
|
||||
#else
|
||||
for (uint8_t out = 4-shiftdiv, in = 4; out != 0; /* dec in loop */) {
|
||||
--out, --in;
|
||||
#endif
|
||||
r.wa[out] = (v.wa[in] << shiftmod) | carryover;
|
||||
carryover = (v.wa[in] >> (bits - shiftmod));
|
||||
}
|
||||
} else {
|
||||
#if PCG_LITTLE_ENDIAN
|
||||
for (uint8_t out = shiftdiv, in = 0; out < 4; ++out, ++in) {
|
||||
#else
|
||||
for (uint8_t out = 4-shiftdiv, in = 4; out != 0; /* dec in loop */) {
|
||||
--out, --in;
|
||||
#endif
|
||||
r.wa[out] = v.wa[in];
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
template <typename UInt, typename UIntX2>
|
||||
uint_x4<UInt,UIntX2> operator>>(const uint_x4<UInt,UIntX2>& v,
|
||||
const bitcount_t shift)
|
||||
{
|
||||
uint_x4<UInt,UIntX2> r = {0U, 0U, 0U, 0U};
|
||||
const bitcount_t bits = sizeof(UInt) * CHAR_BIT;
|
||||
const bitcount_t bitmask = bits - 1;
|
||||
const bitcount_t shiftdiv = shift / bits;
|
||||
const bitcount_t shiftmod = shift & bitmask;
|
||||
|
||||
if (shiftmod) {
|
||||
UInt carryover = 0;
|
||||
#if PCG_LITTLE_ENDIAN
|
||||
for (uint8_t out = 4-shiftdiv, in = 4; out != 0; /* dec in loop */) {
|
||||
--out, --in;
|
||||
#else
|
||||
for (uint8_t out = shiftdiv, in = 0; out < 4; ++out, ++in) {
|
||||
#endif
|
||||
r.wa[out] = (v.wa[in] >> shiftmod) | carryover;
|
||||
carryover = (v.wa[in] << (bits - shiftmod));
|
||||
}
|
||||
} else {
|
||||
#if PCG_LITTLE_ENDIAN
|
||||
for (uint8_t out = 4-shiftdiv, in = 4; out != 0; /* dec in loop */) {
|
||||
--out, --in;
|
||||
#else
|
||||
for (uint8_t out = shiftdiv, in = 0; out < 4; ++out, ++in) {
|
||||
#endif
|
||||
r.wa[out] = v.wa[in];
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
} // namespace pcg_extras
|
||||
|
||||
#endif // PCG_UINT128_HPP_INCLUDED
|
@ -34,7 +34,7 @@ class Foundation_API TraverseBase
|
||||
{
|
||||
public:
|
||||
typedef std::stack<DirectoryIterator> Stack;
|
||||
typedef std::pointer_to_unary_function<const Stack&, UInt16> DepthFunPtr;
|
||||
typedef std::function<UInt16(const Stack&)> DepthFunPtr;
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -45,6 +45,7 @@
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <atomic>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@ -381,7 +382,7 @@ public:
|
||||
|
||||
private:
|
||||
int _fd;
|
||||
bool _stopped;
|
||||
std::atomic<bool> _stopped;
|
||||
};
|
||||
|
||||
|
||||
@ -464,7 +465,7 @@ public:
|
||||
private:
|
||||
int _queueFD;
|
||||
int _dirFD;
|
||||
bool _stopped;
|
||||
std::atomic<bool> _stopped;
|
||||
};
|
||||
|
||||
|
||||
|
@ -79,7 +79,7 @@ inline std::string Element::name() const
|
||||
class ElementComparator
|
||||
{
|
||||
public:
|
||||
bool operator()(const Element::Ptr& s1, const Element::Ptr& s2)
|
||||
bool operator()(const Element::Ptr& s1, const Element::Ptr& s2) const
|
||||
{
|
||||
return s1->name() < s2->name();
|
||||
}
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include "Poco/Net/HTTPServerParams.h"
|
||||
#include "Poco/Mutex.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Net {
|
||||
@ -56,7 +58,7 @@ protected:
|
||||
private:
|
||||
HTTPServerParams::Ptr _pParams;
|
||||
HTTPRequestHandlerFactory::Ptr _pFactory;
|
||||
bool _stopped;
|
||||
std::atomic<bool> _stopped;
|
||||
Poco::FastMutex _mutex;
|
||||
};
|
||||
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include "Poco/Thread.h"
|
||||
#include "Poco/ThreadPool.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Net {
|
||||
@ -184,7 +186,7 @@ private:
|
||||
ServerSocket _socket;
|
||||
TCPServerDispatcher* _pDispatcher;
|
||||
Poco::Thread _thread;
|
||||
bool _stopped;
|
||||
std::atomic<bool> _stopped;
|
||||
};
|
||||
|
||||
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "Poco/ThreadPool.h"
|
||||
#include "Poco/Mutex.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Net {
|
||||
@ -109,7 +111,7 @@ private:
|
||||
int _currentConnections;
|
||||
int _maxConcurrentConnections;
|
||||
int _refusedConnections;
|
||||
bool _stopped;
|
||||
std::atomic<bool> _stopped;
|
||||
Poco::NotificationQueue _queue;
|
||||
TCPServerConnectionFactory::Ptr _pConnectionFactory;
|
||||
Poco::ThreadPool& _threadPool;
|
||||
|
@ -80,9 +80,9 @@ extern "C" {
|
||||
* bitStream encoding API (write forward)
|
||||
********************************************/
|
||||
/* bitStream can mix input from multiple sources.
|
||||
* A critical property of these streams is that they encode and decode in **reverse** direction.
|
||||
* So the first bit sequence you add will be the last to be read, like a LIFO stack.
|
||||
*/
|
||||
* A critical property of these streams is that they encode and decode in **reverse** direction.
|
||||
* So the first bit sequence you add will be the last to be read, like a LIFO stack.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
size_t bitContainer;
|
||||
@ -203,7 +203,7 @@ static const unsigned BIT_mask[] = { 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F,
|
||||
/*! BIT_initCStream() :
|
||||
* `dstCapacity` must be > sizeof(size_t)
|
||||
* @return : 0 if success,
|
||||
otherwise an error code (can be tested using ERR_isError() ) */
|
||||
* otherwise an error code (can be tested using ERR_isError()) */
|
||||
MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
|
||||
void* startPtr, size_t dstCapacity)
|
||||
{
|
||||
@ -217,8 +217,8 @@ MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
|
||||
}
|
||||
|
||||
/*! BIT_addBits() :
|
||||
can add up to 26 bits into `bitC`.
|
||||
Does not check for register overflow ! */
|
||||
* can add up to 26 bits into `bitC`.
|
||||
* Note : does not check for register overflow ! */
|
||||
MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC,
|
||||
size_t value, unsigned nbBits)
|
||||
{
|
||||
@ -268,7 +268,7 @@ MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
|
||||
|
||||
/*! BIT_closeCStream() :
|
||||
* @return : size of CStream, in bytes,
|
||||
or 0 if it could not fit into dstBuffer */
|
||||
* or 0 if it could not fit into dstBuffer */
|
||||
MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
|
||||
{
|
||||
BIT_addBitsFast(bitC, 1, 1); /* endMark */
|
||||
@ -279,14 +279,14 @@ MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
|
||||
|
||||
|
||||
/*-********************************************************
|
||||
* bitStream decoding
|
||||
* bitStream decoding
|
||||
**********************************************************/
|
||||
/*! BIT_initDStream() :
|
||||
* Initialize a BIT_DStream_t.
|
||||
* `bitD` : a pointer to an already allocated BIT_DStream_t structure.
|
||||
* `srcSize` must be the *exact* size of the bitStream, in bytes.
|
||||
* @return : size of stream (== srcSize) or an errorCode if a problem is detected
|
||||
*/
|
||||
* Initialize a BIT_DStream_t.
|
||||
* `bitD` : a pointer to an already allocated BIT_DStream_t structure.
|
||||
* `srcSize` must be the *exact* size of the bitStream, in bytes.
|
||||
* @return : size of stream (== srcSize), or an errorCode if a problem is detected
|
||||
*/
|
||||
MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
|
||||
{
|
||||
if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
|
||||
@ -305,29 +305,30 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si
|
||||
bitD->bitContainer = *(const BYTE*)(bitD->start);
|
||||
switch(srcSize)
|
||||
{
|
||||
case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);
|
||||
/* fall-through */
|
||||
case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);
|
||||
/* fall-through */
|
||||
|
||||
case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
|
||||
/* fall-through */
|
||||
case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
|
||||
/* fall-through */
|
||||
|
||||
case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
|
||||
/* fall-through */
|
||||
case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
|
||||
/* fall-through */
|
||||
|
||||
case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24;
|
||||
/* fall-through */
|
||||
case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24;
|
||||
/* fall-through */
|
||||
|
||||
case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16;
|
||||
/* fall-through */
|
||||
case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16;
|
||||
/* fall-through */
|
||||
|
||||
case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8;
|
||||
/* fall-through */
|
||||
case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8;
|
||||
/* fall-through */
|
||||
|
||||
default: break;
|
||||
default: break;
|
||||
}
|
||||
{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
|
||||
bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
|
||||
if (lastByte == 0) return ERROR(corruption_detected); /* endMark not present */
|
||||
}
|
||||
{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
|
||||
bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
|
||||
if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
|
||||
bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;
|
||||
}
|
||||
|
||||
@ -363,9 +364,8 @@ MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
|
||||
* local register is not modified.
|
||||
* On 32-bits, maxNbBits==24.
|
||||
* On 64-bits, maxNbBits==56.
|
||||
* @return : value extracted
|
||||
*/
|
||||
MEM_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
|
||||
* @return : value extracted */
|
||||
MEM_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
|
||||
{
|
||||
#if defined(__BMI__) && defined(__GNUC__) /* experimental; fails if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8 */
|
||||
return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits);
|
||||
@ -392,8 +392,7 @@ MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
|
||||
/*! BIT_readBits() :
|
||||
* Read (consume) next n bits from local register and update.
|
||||
* Pay attention to not read more than nbBits contained into local register.
|
||||
* @return : extracted value.
|
||||
*/
|
||||
* @return : extracted value. */
|
||||
MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)
|
||||
{
|
||||
size_t const value = BIT_lookBits(bitD, nbBits);
|
||||
@ -402,7 +401,7 @@ MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)
|
||||
}
|
||||
|
||||
/*! BIT_readBitsFast() :
|
||||
* unsafe version; only works only if nbBits >= 1 */
|
||||
* unsafe version; only works only if nbBits >= 1 */
|
||||
MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
|
||||
{
|
||||
size_t const value = BIT_lookBitsFast(bitD, nbBits);
|
||||
@ -412,10 +411,10 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)
|
||||
}
|
||||
|
||||
/*! BIT_reloadDStream() :
|
||||
* Refill `bitD` from buffer previously set in BIT_initDStream() .
|
||||
* This function is safe, it guarantees it will not read beyond src buffer.
|
||||
* @return : status of `BIT_DStream_t` internal register.
|
||||
if status == BIT_DStream_unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */
|
||||
* Refill `bitD` from buffer previously set in BIT_initDStream() .
|
||||
* This function is safe, it guarantees it will not read beyond src buffer.
|
||||
* @return : status of `BIT_DStream_t` internal register.
|
||||
* when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */
|
||||
MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
|
||||
{
|
||||
if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* overflow detected, like end of stream */
|
||||
@ -446,8 +445,8 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
|
||||
}
|
||||
|
||||
/*! BIT_endOfDStream() :
|
||||
* @return Tells if DStream has exactly reached its end (all bits consumed).
|
||||
*/
|
||||
* @return : 1 if DStream has _exactly_ reached its end (all bits consumed).
|
||||
*/
|
||||
MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
|
||||
{
|
||||
return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));
|
||||
|
85
contrib/libzstd/include/zstd/common/compiler.h
Normal file
85
contrib/libzstd/include/zstd/common/compiler.h
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
*/
|
||||
|
||||
#ifndef ZSTD_COMPILER_H
|
||||
#define ZSTD_COMPILER_H
|
||||
|
||||
/*-*******************************************************
|
||||
* Compiler specifics
|
||||
*********************************************************/
|
||||
/* force inlining */
|
||||
#if defined (__GNUC__) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
|
||||
# define INLINE_KEYWORD inline
|
||||
#else
|
||||
# define INLINE_KEYWORD
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define FORCE_INLINE_ATTR __attribute__((always_inline))
|
||||
#elif defined(_MSC_VER)
|
||||
# define FORCE_INLINE_ATTR __forceinline
|
||||
#else
|
||||
# define FORCE_INLINE_ATTR
|
||||
#endif
|
||||
|
||||
/**
|
||||
* FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant
|
||||
* parameters. They must be inlined for the compiler to elimininate the constant
|
||||
* branches.
|
||||
*/
|
||||
#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR
|
||||
/**
|
||||
* HINT_INLINE is used to help the compiler generate better code. It is *not*
|
||||
* used for "templates", so it can be tweaked based on the compilers
|
||||
* performance.
|
||||
*
|
||||
* gcc-4.8 and gcc-4.9 have been shown to benefit from leaving off the
|
||||
* always_inline attribute.
|
||||
*
|
||||
* clang up to 5.0.0 (trunk) benefit tremendously from the always_inline
|
||||
* attribute.
|
||||
*/
|
||||
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5
|
||||
# define HINT_INLINE static INLINE_KEYWORD
|
||||
#else
|
||||
# define HINT_INLINE static INLINE_KEYWORD FORCE_INLINE_ATTR
|
||||
#endif
|
||||
|
||||
/* force no inlining */
|
||||
#ifdef _MSC_VER
|
||||
# define FORCE_NOINLINE static __declspec(noinline)
|
||||
#else
|
||||
# ifdef __GNUC__
|
||||
# define FORCE_NOINLINE static __attribute__((__noinline__))
|
||||
# else
|
||||
# define FORCE_NOINLINE static
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* prefetch */
|
||||
#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) /* _mm_prefetch() is not defined outside of x86/x64 */
|
||||
# include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */
|
||||
# define PREFETCH(ptr) _mm_prefetch((const char*)ptr, _MM_HINT_T0)
|
||||
#elif defined(__GNUC__)
|
||||
# define PREFETCH(ptr) __builtin_prefetch(ptr, 0, 0)
|
||||
#else
|
||||
# define PREFETCH(ptr) /* disabled */
|
||||
#endif
|
||||
|
||||
/* disable warnings */
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
# include <intrin.h> /* For Visual 2005 */
|
||||
# pragma warning(disable : 4100) /* disable: C4100: unreferenced formal parameter */
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */
|
||||
# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
|
||||
# pragma warning(disable : 4324) /* disable: C4324: padded structure */
|
||||
#endif
|
||||
|
||||
#endif /* ZSTD_COMPILER_H */
|
@ -1,10 +1,10 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
*/
|
||||
|
||||
/* The purpose of this file is to have a single list of error strings embedded in binary */
|
||||
@ -20,19 +20,17 @@ const char* ERR_getErrorString(ERR_enum code)
|
||||
case PREFIX(GENERIC): return "Error (generic)";
|
||||
case PREFIX(prefix_unknown): return "Unknown frame descriptor";
|
||||
case PREFIX(version_unsupported): return "Version not supported";
|
||||
case PREFIX(parameter_unknown): return "Unknown parameter type";
|
||||
case PREFIX(frameParameter_unsupported): return "Unsupported frame parameter";
|
||||
case PREFIX(frameParameter_unsupportedBy32bits): return "Frame parameter unsupported in 32-bits mode";
|
||||
case PREFIX(frameParameter_windowTooLarge): return "Frame requires too much memory for decoding";
|
||||
case PREFIX(compressionParameter_unsupported): return "Compression parameter is not supported";
|
||||
case PREFIX(compressionParameter_outOfBound): return "Compression parameter is out of bound";
|
||||
case PREFIX(corruption_detected): return "Corrupted block detected";
|
||||
case PREFIX(checksum_wrong): return "Restored data doesn't match checksum";
|
||||
case PREFIX(parameter_unsupported): return "Unsupported parameter";
|
||||
case PREFIX(parameter_outOfBound): return "Parameter is out of bound";
|
||||
case PREFIX(init_missing): return "Context should be init first";
|
||||
case PREFIX(memory_allocation): return "Allocation error : not enough memory";
|
||||
case PREFIX(stage_wrong): return "Operation not authorized at current processing stage";
|
||||
case PREFIX(dstSize_tooSmall): return "Destination buffer is too small";
|
||||
case PREFIX(srcSize_wrong): return "Src size is incorrect";
|
||||
case PREFIX(corruption_detected): return "Corrupted block detected";
|
||||
case PREFIX(checksum_wrong): return "Restored data doesn't match checksum";
|
||||
case PREFIX(tableLog_tooLarge): return "tableLog requires too much memory : unsupported";
|
||||
case PREFIX(maxSymbolValue_tooLarge): return "Unsupported max Symbol Value : too large";
|
||||
case PREFIX(maxSymbolValue_tooSmall): return "Specified maxSymbolValue is too small";
|
||||
|
@ -1,10 +1,10 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
*/
|
||||
|
||||
/* Note : this module is expected to remain private, do not expose it */
|
||||
|
@ -31,13 +31,14 @@
|
||||
You can contact the author at :
|
||||
- Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
****************************************************************** */
|
||||
#ifndef FSE_H
|
||||
#define FSE_H
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef FSE_H
|
||||
#define FSE_H
|
||||
|
||||
|
||||
/*-*****************************************
|
||||
* Dependencies
|
||||
@ -297,8 +298,10 @@ FSE_decompress_usingDTable() result will tell how many bytes were regenerated (<
|
||||
If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small)
|
||||
*/
|
||||
|
||||
#endif /* FSE_H */
|
||||
|
||||
#ifdef FSE_STATIC_LINKING_ONLY
|
||||
#if defined(FSE_STATIC_LINKING_ONLY) && !defined(FSE_H_FSE_STATIC_LINKING_ONLY)
|
||||
#define FSE_H_FSE_STATIC_LINKING_ONLY
|
||||
|
||||
/* *** Dependency *** */
|
||||
#include "bitstream.h"
|
||||
@ -381,6 +384,11 @@ size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue);
|
||||
size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, FSE_DTable* workSpace, unsigned maxLog);
|
||||
/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DTABLE_SIZE_U32(maxLog)` */
|
||||
|
||||
typedef enum {
|
||||
FSE_repeat_none, /**< Cannot use the previous table */
|
||||
FSE_repeat_check, /**< Can use the previous table but it must be checked */
|
||||
FSE_repeat_valid /**< Can use the previous table and it is asumed to be valid */
|
||||
} FSE_repeat;
|
||||
|
||||
/* *****************************************
|
||||
* FSE symbol compression API
|
||||
@ -694,5 +702,3 @@ MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FSE_H */
|
||||
|
@ -33,35 +33,16 @@
|
||||
****************************************************************** */
|
||||
|
||||
|
||||
/* **************************************************************
|
||||
* Compiler specifics
|
||||
****************************************************************/
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
# define FORCE_INLINE static __forceinline
|
||||
# include <intrin.h> /* For Visual 2005 */
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
# pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */
|
||||
#else
|
||||
# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
|
||||
# ifdef __GNUC__
|
||||
# define FORCE_INLINE static inline __attribute__((always_inline))
|
||||
# else
|
||||
# define FORCE_INLINE static inline
|
||||
# endif
|
||||
# else
|
||||
# define FORCE_INLINE static
|
||||
# endif /* __STDC_VERSION__ */
|
||||
#endif
|
||||
|
||||
|
||||
/* **************************************************************
|
||||
* Includes
|
||||
****************************************************************/
|
||||
#include <stdlib.h> /* malloc, free, qsort */
|
||||
#include <string.h> /* memcpy, memset */
|
||||
#include "bitstream.h"
|
||||
#include "compiler.h"
|
||||
#define FSE_STATIC_LINKING_ONLY
|
||||
#include "fse.h"
|
||||
#include "error_private.h"
|
||||
|
||||
|
||||
/* **************************************************************
|
||||
@ -216,7 +197,7 @@ size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)
|
||||
return 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE size_t FSE_decompress_usingDTable_generic(
|
||||
FORCE_INLINE_TEMPLATE size_t FSE_decompress_usingDTable_generic(
|
||||
void* dst, size_t maxDstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const FSE_DTable* dt, const unsigned fast)
|
||||
|
@ -31,13 +31,13 @@
|
||||
You can contact the author at :
|
||||
- Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
****************************************************************** */
|
||||
#ifndef HUF_H_298734234
|
||||
#define HUF_H_298734234
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef HUF_H_298734234
|
||||
#define HUF_H_298734234
|
||||
|
||||
/* *** Dependencies *** */
|
||||
#include <stddef.h> /* size_t */
|
||||
@ -124,6 +124,7 @@ HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity, const
|
||||
#define HUF_DECOMPRESS_WORKSPACE_SIZE (2 << 10)
|
||||
#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32))
|
||||
|
||||
#endif /* HUF_H_298734234 */
|
||||
|
||||
/* ******************************************************************
|
||||
* WARNING !!
|
||||
@ -132,7 +133,8 @@ HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity, const
|
||||
* because they are not guaranteed to remain stable in the future.
|
||||
* Only consider them in association with static linking.
|
||||
*******************************************************************/
|
||||
#ifdef HUF_STATIC_LINKING_ONLY
|
||||
#if defined(HUF_STATIC_LINKING_ONLY) && !defined(HUF_H_HUF_STATIC_LINKING_ONLY)
|
||||
#define HUF_H_HUF_STATIC_LINKING_ONLY
|
||||
|
||||
/* *** Dependencies *** */
|
||||
#include "mem.h" /* U32 */
|
||||
@ -295,9 +297,6 @@ size_t HUF_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* c
|
||||
|
||||
#endif /* HUF_STATIC_LINKING_ONLY */
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HUF_H_298734234 */
|
||||
|
@ -1,10 +1,10 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
*/
|
||||
|
||||
#ifndef MEM_H_MODULE
|
||||
@ -110,7 +110,7 @@ Only use if no other choice to achieve best performance on target platform */
|
||||
MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }
|
||||
MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }
|
||||
MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }
|
||||
MEM_STATIC U64 MEM_readST(const void* memPtr) { return *(const size_t*) memPtr; }
|
||||
MEM_STATIC size_t MEM_readST(const void* memPtr) { return *(const size_t*) memPtr; }
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
|
||||
MEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }
|
||||
@ -131,7 +131,7 @@ MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; }
|
||||
MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
|
||||
MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
|
||||
MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
|
||||
MEM_STATIC U64 MEM_readST(const void* ptr) { return ((const unalign*)ptr)->st; }
|
||||
MEM_STATIC size_t MEM_readST(const void* ptr) { return ((const unalign*)ptr)->st; }
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
|
||||
MEM_STATIC void MEM_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; }
|
||||
|
@ -1,10 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2016-present, Facebook, Inc.
|
||||
/*
|
||||
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
*/
|
||||
|
||||
|
||||
@ -39,6 +39,12 @@ struct POOL_ctx_s {
|
||||
size_t queueHead;
|
||||
size_t queueTail;
|
||||
size_t queueSize;
|
||||
|
||||
/* The number of threads working on jobs */
|
||||
size_t numThreadsBusy;
|
||||
/* Indicates if the queue is empty */
|
||||
int queueEmpty;
|
||||
|
||||
/* The mutex protects the queue */
|
||||
pthread_mutex_t queueMutex;
|
||||
/* Condition variable for pushers to wait on when the queue is full */
|
||||
@ -60,30 +66,41 @@ static void* POOL_thread(void* opaque) {
|
||||
for (;;) {
|
||||
/* Lock the mutex and wait for a non-empty queue or until shutdown */
|
||||
pthread_mutex_lock(&ctx->queueMutex);
|
||||
while (ctx->queueHead == ctx->queueTail && !ctx->shutdown) {
|
||||
|
||||
while (ctx->queueEmpty && !ctx->shutdown) {
|
||||
pthread_cond_wait(&ctx->queuePopCond, &ctx->queueMutex);
|
||||
}
|
||||
/* empty => shutting down: so stop */
|
||||
if (ctx->queueHead == ctx->queueTail) {
|
||||
if (ctx->queueEmpty) {
|
||||
pthread_mutex_unlock(&ctx->queueMutex);
|
||||
return opaque;
|
||||
}
|
||||
/* Pop a job off the queue */
|
||||
{ POOL_job const job = ctx->queue[ctx->queueHead];
|
||||
ctx->queueHead = (ctx->queueHead + 1) % ctx->queueSize;
|
||||
ctx->numThreadsBusy++;
|
||||
ctx->queueEmpty = ctx->queueHead == ctx->queueTail;
|
||||
/* Unlock the mutex, signal a pusher, and run the job */
|
||||
pthread_mutex_unlock(&ctx->queueMutex);
|
||||
pthread_cond_signal(&ctx->queuePushCond);
|
||||
|
||||
job.function(job.opaque);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the intended queue size was 0, signal after finishing job */
|
||||
if (ctx->queueSize == 1) {
|
||||
pthread_mutex_lock(&ctx->queueMutex);
|
||||
ctx->numThreadsBusy--;
|
||||
pthread_mutex_unlock(&ctx->queueMutex);
|
||||
pthread_cond_signal(&ctx->queuePushCond);
|
||||
} }
|
||||
} /* for (;;) */
|
||||
/* Unreachable */
|
||||
}
|
||||
|
||||
POOL_ctx *POOL_create(size_t numThreads, size_t queueSize) {
|
||||
POOL_ctx *ctx;
|
||||
/* Check the parameters */
|
||||
if (!numThreads || !queueSize) { return NULL; }
|
||||
if (!numThreads) { return NULL; }
|
||||
/* Allocate the context and zero initialize */
|
||||
ctx = (POOL_ctx *)calloc(1, sizeof(POOL_ctx));
|
||||
if (!ctx) { return NULL; }
|
||||
@ -92,15 +109,17 @@ POOL_ctx *POOL_create(size_t numThreads, size_t queueSize) {
|
||||
* and full queues.
|
||||
*/
|
||||
ctx->queueSize = queueSize + 1;
|
||||
ctx->queue = (POOL_job *)malloc(ctx->queueSize * sizeof(POOL_job));
|
||||
ctx->queue = (POOL_job*) malloc(ctx->queueSize * sizeof(POOL_job));
|
||||
ctx->queueHead = 0;
|
||||
ctx->queueTail = 0;
|
||||
pthread_mutex_init(&ctx->queueMutex, NULL);
|
||||
pthread_cond_init(&ctx->queuePushCond, NULL);
|
||||
pthread_cond_init(&ctx->queuePopCond, NULL);
|
||||
ctx->numThreadsBusy = 0;
|
||||
ctx->queueEmpty = 1;
|
||||
(void)pthread_mutex_init(&ctx->queueMutex, NULL);
|
||||
(void)pthread_cond_init(&ctx->queuePushCond, NULL);
|
||||
(void)pthread_cond_init(&ctx->queuePopCond, NULL);
|
||||
ctx->shutdown = 0;
|
||||
/* Allocate space for the thread handles */
|
||||
ctx->threads = (pthread_t *)malloc(numThreads * sizeof(pthread_t));
|
||||
ctx->threads = (pthread_t*)malloc(numThreads * sizeof(pthread_t));
|
||||
ctx->numThreads = 0;
|
||||
/* Check for errors */
|
||||
if (!ctx->threads || !ctx->queue) { POOL_free(ctx); return NULL; }
|
||||
@ -153,22 +172,37 @@ size_t POOL_sizeof(POOL_ctx *ctx) {
|
||||
+ ctx->numThreads * sizeof(pthread_t);
|
||||
}
|
||||
|
||||
void POOL_add(void *ctxVoid, POOL_function function, void *opaque) {
|
||||
POOL_ctx *ctx = (POOL_ctx *)ctxVoid;
|
||||
/**
|
||||
* Returns 1 if the queue is full and 0 otherwise.
|
||||
*
|
||||
* If the queueSize is 1 (the pool was created with an intended queueSize of 0),
|
||||
* then a queue is empty if there is a thread free and no job is waiting.
|
||||
*/
|
||||
static int isQueueFull(POOL_ctx const* ctx) {
|
||||
if (ctx->queueSize > 1) {
|
||||
return ctx->queueHead == ((ctx->queueTail + 1) % ctx->queueSize);
|
||||
} else {
|
||||
return ctx->numThreadsBusy == ctx->numThreads ||
|
||||
!ctx->queueEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
void POOL_add(void* ctxVoid, POOL_function function, void *opaque) {
|
||||
POOL_ctx* const ctx = (POOL_ctx*)ctxVoid;
|
||||
if (!ctx) { return; }
|
||||
|
||||
pthread_mutex_lock(&ctx->queueMutex);
|
||||
{ POOL_job const job = {function, opaque};
|
||||
|
||||
/* Wait until there is space in the queue for the new job */
|
||||
size_t newTail = (ctx->queueTail + 1) % ctx->queueSize;
|
||||
while (ctx->queueHead == newTail && !ctx->shutdown) {
|
||||
while (isQueueFull(ctx) && !ctx->shutdown) {
|
||||
pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);
|
||||
newTail = (ctx->queueTail + 1) % ctx->queueSize;
|
||||
}
|
||||
/* The queue is still going => there is space */
|
||||
if (!ctx->shutdown) {
|
||||
ctx->queueEmpty = 0;
|
||||
ctx->queue[ctx->queueTail] = job;
|
||||
ctx->queueTail = newTail;
|
||||
ctx->queueTail = (ctx->queueTail + 1) % ctx->queueSize;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&ctx->queueMutex);
|
||||
@ -183,22 +217,22 @@ struct POOL_ctx_s {
|
||||
int data;
|
||||
};
|
||||
|
||||
POOL_ctx *POOL_create(size_t numThreads, size_t queueSize) {
|
||||
POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
|
||||
(void)numThreads;
|
||||
(void)queueSize;
|
||||
return (POOL_ctx *)malloc(sizeof(POOL_ctx));
|
||||
return (POOL_ctx*)malloc(sizeof(POOL_ctx));
|
||||
}
|
||||
|
||||
void POOL_free(POOL_ctx *ctx) {
|
||||
if (ctx) free(ctx);
|
||||
void POOL_free(POOL_ctx* ctx) {
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
void POOL_add(void *ctx, POOL_function function, void *opaque) {
|
||||
void POOL_add(void* ctx, POOL_function function, void* opaque) {
|
||||
(void)ctx;
|
||||
function(opaque);
|
||||
}
|
||||
|
||||
size_t POOL_sizeof(POOL_ctx *ctx) {
|
||||
size_t POOL_sizeof(POOL_ctx* ctx) {
|
||||
if (ctx==NULL) return 0; /* supports sizeof NULL */
|
||||
return sizeof(*ctx);
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2016-present, Facebook, Inc.
|
||||
/*
|
||||
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
*/
|
||||
|
||||
#ifndef POOL_H
|
||||
#define POOL_H
|
||||
|
||||
@ -19,11 +20,10 @@ extern "C" {
|
||||
typedef struct POOL_ctx_s POOL_ctx;
|
||||
|
||||
/*! POOL_create() :
|
||||
Create a thread pool with at most `numThreads` threads.
|
||||
`numThreads` must be at least 1.
|
||||
The maximum number of queued jobs before blocking is `queueSize`.
|
||||
`queueSize` must be at least 1.
|
||||
@return : The POOL_ctx pointer on success else NULL.
|
||||
* Create a thread pool with at most `numThreads` threads.
|
||||
* `numThreads` must be at least 1.
|
||||
* The maximum number of queued jobs before blocking is `queueSize`.
|
||||
* @return : POOL_ctx pointer on success, else NULL.
|
||||
*/
|
||||
POOL_ctx *POOL_create(size_t numThreads, size_t queueSize);
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/**
|
||||
* Copyright (c) 2016 Tino Reichardt
|
||||
* All rights reserved.
|
||||
@ -42,14 +41,14 @@ extern "C" {
|
||||
|
||||
/* mutex */
|
||||
#define pthread_mutex_t CRITICAL_SECTION
|
||||
#define pthread_mutex_init(a,b) InitializeCriticalSection((a))
|
||||
#define pthread_mutex_init(a,b) (InitializeCriticalSection((a)), 0)
|
||||
#define pthread_mutex_destroy(a) DeleteCriticalSection((a))
|
||||
#define pthread_mutex_lock(a) EnterCriticalSection((a))
|
||||
#define pthread_mutex_unlock(a) LeaveCriticalSection((a))
|
||||
|
||||
/* condition variable */
|
||||
#define pthread_cond_t CONDITION_VARIABLE
|
||||
#define pthread_cond_init(a, b) InitializeConditionVariable((a))
|
||||
#define pthread_cond_init(a, b) (InitializeConditionVariable((a)), 0)
|
||||
#define pthread_cond_destroy(a) /* No delete */
|
||||
#define pthread_cond_wait(a, b) SleepConditionVariableCS((a), (b), INFINITE)
|
||||
#define pthread_cond_signal(a) WakeConditionVariable((a))
|
||||
@ -80,14 +79,14 @@ int _pthread_join(pthread_t* thread, void** value_ptr);
|
||||
#else /* ZSTD_MULTITHREAD not defined */
|
||||
/* No multithreading support */
|
||||
|
||||
#define pthread_mutex_t int /* #define rather than typedef, as sometimes pthread support is implicit, resulting in duplicated symbols */
|
||||
#define pthread_mutex_init(a,b)
|
||||
#define pthread_mutex_t int /* #define rather than typedef, because sometimes pthread support is implicit, resulting in duplicated symbols */
|
||||
#define pthread_mutex_init(a,b) ((void)a, 0)
|
||||
#define pthread_mutex_destroy(a)
|
||||
#define pthread_mutex_lock(a)
|
||||
#define pthread_mutex_unlock(a)
|
||||
|
||||
#define pthread_cond_t int
|
||||
#define pthread_cond_init(a,b)
|
||||
#define pthread_cond_init(a,b) ((void)a, 0)
|
||||
#define pthread_cond_destroy(a)
|
||||
#define pthread_cond_wait(a,b)
|
||||
#define pthread_cond_signal(a)
|
||||
|
@ -113,19 +113,25 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcp
|
||||
/* *************************************
|
||||
* Compiler Specific Options
|
||||
***************************************/
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
# define FORCE_INLINE static __forceinline
|
||||
#if defined (__GNUC__) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
|
||||
# define INLINE_KEYWORD inline
|
||||
#else
|
||||
# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
|
||||
# ifdef __GNUC__
|
||||
# define FORCE_INLINE static inline __attribute__((always_inline))
|
||||
# else
|
||||
# define FORCE_INLINE static inline
|
||||
# endif
|
||||
# else
|
||||
# define FORCE_INLINE static
|
||||
# endif /* __STDC_VERSION__ */
|
||||
# define INLINE_KEYWORD
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define FORCE_INLINE_ATTR __attribute__((always_inline))
|
||||
#elif defined(_MSC_VER)
|
||||
# define FORCE_INLINE_ATTR __forceinline
|
||||
#else
|
||||
# define FORCE_INLINE_ATTR
|
||||
#endif
|
||||
|
||||
#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
#endif
|
||||
|
||||
|
||||
@ -248,7 +254,7 @@ typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
|
||||
*****************************/
|
||||
typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
|
||||
|
||||
FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
FORCE_INLINE_TEMPLATE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
if (align==XXH_unaligned)
|
||||
return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));
|
||||
@ -256,7 +262,7 @@ FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_a
|
||||
return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr);
|
||||
}
|
||||
|
||||
FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian)
|
||||
FORCE_INLINE_TEMPLATE U32 XXH_readLE32(const void* ptr, XXH_endianess endian)
|
||||
{
|
||||
return XXH_readLE32_align(ptr, endian, XXH_unaligned);
|
||||
}
|
||||
@ -266,7 +272,7 @@ static U32 XXH_readBE32(const void* ptr)
|
||||
return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr);
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
FORCE_INLINE_TEMPLATE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
if (align==XXH_unaligned)
|
||||
return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));
|
||||
@ -274,7 +280,7 @@ FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_a
|
||||
return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr);
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian)
|
||||
FORCE_INLINE_TEMPLATE U64 XXH_readLE64(const void* ptr, XXH_endianess endian)
|
||||
{
|
||||
return XXH_readLE64_align(ptr, endian, XXH_unaligned);
|
||||
}
|
||||
@ -335,7 +341,7 @@ static U32 XXH32_round(U32 seed, U32 input)
|
||||
return seed;
|
||||
}
|
||||
|
||||
FORCE_INLINE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)
|
||||
FORCE_INLINE_TEMPLATE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* bEnd = p + len;
|
||||
@ -435,7 +441,7 @@ static U64 XXH64_mergeRound(U64 acc, U64 val)
|
||||
return acc;
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)
|
||||
FORCE_INLINE_TEMPLATE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
@ -584,7 +590,7 @@ XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE XXH_errorcode XXH32_update_endian (XXH32_state_t* state, const void* input, size_t len, XXH_endianess endian)
|
||||
FORCE_INLINE_TEMPLATE XXH_errorcode XXH32_update_endian (XXH32_state_t* state, const void* input, size_t len, XXH_endianess endian)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
@ -654,7 +660,7 @@ XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void*
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE U32 XXH32_digest_endian (const XXH32_state_t* state, XXH_endianess endian)
|
||||
FORCE_INLINE_TEMPLATE U32 XXH32_digest_endian (const XXH32_state_t* state, XXH_endianess endian)
|
||||
{
|
||||
const BYTE * p = (const BYTE*)state->mem32;
|
||||
const BYTE* const bEnd = (const BYTE*)(state->mem32) + state->memsize;
|
||||
@ -704,7 +710,7 @@ XXH_PUBLIC_API unsigned int XXH32_digest (const XXH32_state_t* state_in)
|
||||
|
||||
/* **** XXH64 **** */
|
||||
|
||||
FORCE_INLINE XXH_errorcode XXH64_update_endian (XXH64_state_t* state, const void* input, size_t len, XXH_endianess endian)
|
||||
FORCE_INLINE_TEMPLATE XXH_errorcode XXH64_update_endian (XXH64_state_t* state, const void* input, size_t len, XXH_endianess endian)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
@ -771,7 +777,7 @@ XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void*
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE U64 XXH64_digest_endian (const XXH64_state_t* state, XXH_endianess endian)
|
||||
FORCE_INLINE_TEMPLATE U64 XXH64_digest_endian (const XXH64_state_t* state, XXH_endianess endian)
|
||||
{
|
||||
const BYTE * p = (const BYTE*)state->mem64;
|
||||
const BYTE* const bEnd = (const BYTE*)state->mem64 + state->memsize;
|
||||
|
@ -1,10 +1,10 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
*/
|
||||
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
*/
|
||||
|
||||
#ifndef ZSTD_ERRORS_H_398273423
|
||||
@ -37,43 +37,41 @@ extern "C" {
|
||||
/*-****************************************
|
||||
* error codes list
|
||||
* note : this API is still considered unstable
|
||||
* it should not be used with a dynamic library
|
||||
* and shall not be used with a dynamic library.
|
||||
* only static linking is allowed
|
||||
******************************************/
|
||||
typedef enum {
|
||||
ZSTD_error_no_error,
|
||||
ZSTD_error_GENERIC,
|
||||
ZSTD_error_prefix_unknown,
|
||||
ZSTD_error_version_unsupported,
|
||||
ZSTD_error_parameter_unknown,
|
||||
ZSTD_error_frameParameter_unsupported,
|
||||
ZSTD_error_frameParameter_unsupportedBy32bits,
|
||||
ZSTD_error_frameParameter_windowTooLarge,
|
||||
ZSTD_error_compressionParameter_unsupported,
|
||||
ZSTD_error_compressionParameter_outOfBound,
|
||||
ZSTD_error_init_missing,
|
||||
ZSTD_error_memory_allocation,
|
||||
ZSTD_error_stage_wrong,
|
||||
ZSTD_error_dstSize_tooSmall,
|
||||
ZSTD_error_srcSize_wrong,
|
||||
ZSTD_error_corruption_detected,
|
||||
ZSTD_error_checksum_wrong,
|
||||
ZSTD_error_tableLog_tooLarge,
|
||||
ZSTD_error_maxSymbolValue_tooLarge,
|
||||
ZSTD_error_maxSymbolValue_tooSmall,
|
||||
ZSTD_error_dictionary_corrupted,
|
||||
ZSTD_error_dictionary_wrong,
|
||||
ZSTD_error_dictionaryCreation_failed,
|
||||
ZSTD_error_frameIndex_tooLarge,
|
||||
ZSTD_error_seekableIO,
|
||||
ZSTD_error_maxCode
|
||||
ZSTD_error_no_error = 0,
|
||||
ZSTD_error_GENERIC = 1,
|
||||
ZSTD_error_prefix_unknown = 10,
|
||||
ZSTD_error_version_unsupported = 12,
|
||||
ZSTD_error_frameParameter_unsupported = 14,
|
||||
ZSTD_error_frameParameter_windowTooLarge = 16,
|
||||
ZSTD_error_corruption_detected = 20,
|
||||
ZSTD_error_checksum_wrong = 22,
|
||||
ZSTD_error_dictionary_corrupted = 30,
|
||||
ZSTD_error_dictionary_wrong = 32,
|
||||
ZSTD_error_dictionaryCreation_failed = 34,
|
||||
ZSTD_error_parameter_unsupported = 40,
|
||||
ZSTD_error_parameter_outOfBound = 42,
|
||||
ZSTD_error_tableLog_tooLarge = 44,
|
||||
ZSTD_error_maxSymbolValue_tooLarge = 46,
|
||||
ZSTD_error_maxSymbolValue_tooSmall = 48,
|
||||
ZSTD_error_stage_wrong = 60,
|
||||
ZSTD_error_init_missing = 62,
|
||||
ZSTD_error_memory_allocation = 64,
|
||||
ZSTD_error_dstSize_tooSmall = 70,
|
||||
ZSTD_error_srcSize_wrong = 72,
|
||||
ZSTD_error_frameIndex_tooLarge = 100,
|
||||
ZSTD_error_seekableIO = 102,
|
||||
ZSTD_error_maxCode = 120 /* never EVER use this value directly, it may change in future versions! Use ZSTD_isError() instead */
|
||||
} ZSTD_ErrorCode;
|
||||
|
||||
/*! ZSTD_getErrorCode() :
|
||||
convert a `size_t` function result into a `ZSTD_ErrorCode` enum type,
|
||||
which can be used to compare with enum list published above */
|
||||
ZSTDERRORLIB_API ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult);
|
||||
ZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code);
|
||||
ZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code); /**< Same as ZSTD_getErrorName, but using a `ZSTD_ErrorCode` enum argument */
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
|
@ -1,55 +1,28 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||
* in the COPYING file in the root directory of this source tree).
|
||||
*/
|
||||
|
||||
#ifndef ZSTD_CCOMMON_H_MODULE
|
||||
#define ZSTD_CCOMMON_H_MODULE
|
||||
|
||||
/*-*******************************************************
|
||||
* Compiler specifics
|
||||
*********************************************************/
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
# define FORCE_INLINE static __forceinline
|
||||
# include <intrin.h> /* For Visual 2005 */
|
||||
# pragma warning(disable : 4100) /* disable: C4100: unreferenced formal parameter */
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */
|
||||
# pragma warning(disable : 4324) /* disable: C4324: padded structure */
|
||||
#else
|
||||
# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
|
||||
# ifdef __GNUC__
|
||||
# define FORCE_INLINE static inline __attribute__((always_inline))
|
||||
# else
|
||||
# define FORCE_INLINE static inline
|
||||
# endif
|
||||
# else
|
||||
# define FORCE_INLINE static
|
||||
# endif /* __STDC_VERSION__ */
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define FORCE_NOINLINE static __declspec(noinline)
|
||||
#else
|
||||
# ifdef __GNUC__
|
||||
# define FORCE_NOINLINE static __attribute__((__noinline__))
|
||||
# else
|
||||
# define FORCE_NOINLINE static
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Dependencies
|
||||
***************************************/
|
||||
#include "compiler.h"
|
||||
#include "mem.h"
|
||||
#include "error_private.h"
|
||||
#define ZSTD_STATIC_LINKING_ONLY
|
||||
#include "zstd.h"
|
||||
#define FSE_STATIC_LINKING_ONLY
|
||||
#include "fse.h"
|
||||
#define HUF_STATIC_LINKING_ONLY
|
||||
#include "huf.h"
|
||||
#ifndef XXH_STATIC_LINKING_ONLY
|
||||
# define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
|
||||
#endif
|
||||
@ -211,20 +184,6 @@ MEM_STATIC void ZSTD_wildcopy_e(void* dst, const void* src, void* dstEnd) /* s
|
||||
*********************************************/
|
||||
typedef struct ZSTD_stats_s ZSTD_stats_t;
|
||||
|
||||
typedef struct {
|
||||
U32 off;
|
||||
U32 len;
|
||||
} ZSTD_match_t;
|
||||
|
||||
typedef struct {
|
||||
U32 price;
|
||||
U32 off;
|
||||
U32 mlen;
|
||||
U32 litlen;
|
||||
U32 rep[ZSTD_REP_NUM];
|
||||
} ZSTD_optimal_t;
|
||||
|
||||
|
||||
typedef struct seqDef_s {
|
||||
U32 offset;
|
||||
U16 litLength;
|
||||
@ -242,13 +201,31 @@ typedef struct {
|
||||
BYTE* ofCode;
|
||||
U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */
|
||||
U32 longLengthPos;
|
||||
/* opt */
|
||||
ZSTD_optimal_t* priceTable;
|
||||
ZSTD_match_t* matchTable;
|
||||
U32* matchLengthFreq;
|
||||
U32* litLengthFreq;
|
||||
U32 rep[ZSTD_REP_NUM];
|
||||
U32 repToConfirm[ZSTD_REP_NUM];
|
||||
} seqStore_t;
|
||||
|
||||
typedef struct {
|
||||
U32 off;
|
||||
U32 len;
|
||||
} ZSTD_match_t;
|
||||
|
||||
typedef struct {
|
||||
U32 price;
|
||||
U32 off;
|
||||
U32 mlen;
|
||||
U32 litlen;
|
||||
U32 rep[ZSTD_REP_NUM];
|
||||
} ZSTD_optimal_t;
|
||||
|
||||
typedef struct {
|
||||
U32* litFreq;
|
||||
U32* litLengthFreq;
|
||||
U32* matchLengthFreq;
|
||||
U32* offCodeFreq;
|
||||
ZSTD_match_t* matchTable;
|
||||
ZSTD_optimal_t* priceTable;
|
||||
|
||||
U32 matchLengthSum;
|
||||
U32 matchSum;
|
||||
U32 litLengthSum;
|
||||
@ -264,7 +241,19 @@ typedef struct {
|
||||
U32 cachedPrice;
|
||||
U32 cachedLitLength;
|
||||
const BYTE* cachedLiterals;
|
||||
} seqStore_t;
|
||||
} optState_t;
|
||||
|
||||
typedef struct {
|
||||
U32 hufCTable[HUF_CTABLE_SIZE_U32(255)];
|
||||
FSE_CTable offcodeCTable[FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];
|
||||
FSE_CTable matchlengthCTable[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];
|
||||
FSE_CTable litlengthCTable[FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];
|
||||
U32 workspace[HUF_WORKSPACE_SIZE_U32];
|
||||
HUF_repeat hufCTable_repeatMode;
|
||||
FSE_repeat offcode_repeatMode;
|
||||
FSE_repeat matchlength_repeatMode;
|
||||
FSE_repeat litlength_repeatMode;
|
||||
} ZSTD_entropyCTables_t;
|
||||
|
||||
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx);
|
||||
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr);
|
||||
@ -331,4 +320,16 @@ size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
||||
ZSTD_parameters ZSTD_getParamsFromCDict(const ZSTD_CDict* cdict);
|
||||
|
||||
|
||||
typedef struct {
|
||||
blockType_e blockType;
|
||||
U32 lastBlock;
|
||||
U32 origSize;
|
||||
} blockProperties_t;
|
||||
|
||||
/*! ZSTD_getcBlockSize() :
|
||||
* Provides the size of compressed block from block header `src` */
|
||||
size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
|
||||
blockProperties_t* bpPtr);
|
||||
|
||||
|
||||
#endif /* ZSTD_CCOMMON_H_MODULE */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user