// Copyright Daniel Wallin 2006. Use, modification and distribution is // subject to 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) #include #include #include #include #include #include #include #include #include //#include #include #include // Generators #include #include #include #include #include #include #include using namespace boost::python; namespace mpl = boost::mpl; struct seed_fwd { #define BOOST_PP_LOCAL_MACRO(n) \ template \ R operator()(boost::type, T& self BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(n, A, const& a)) \ { \ return self.seed(BOOST_PP_ENUM_PARAMS(n, a)); \ } #define BOOST_PP_LOCAL_LIMITS (0, 4) #include BOOST_PP_LOCAL_ITERATE() }; /* struct sprng_visitor : def_visitor { typedef mpl::vector4< boost::random::random_tag::stream_number* , boost::random::random_tag::total_streams* , boost::random::random_tag::global_seed* , boost::random::random_tag::parameter* > keywords; template void visit(C& cl) const { typedef typename C::wrapped_type rng; namespace py = boost::parameter::python; cl .def( py::init< keywords , mpl::vector4 >() ) .def("seed", py::function< seed_fwd , keywords , mpl::vector5 >() ); } }; */ template struct variate_generator_class : class_< boost::variate_generator< boost::buffered_uniform_01<>&, Distribution > > { typedef boost::variate_generator< boost::buffered_uniform_01<>&, Distribution > generator; typedef class_ base; variate_generator_class(char const* name) : base(name, init&, Distribution&>()) { converter::registration const* r = converter::registry::query(type_id()); assert(r); object distribution_class(handle<>(r->get_class_object())); dict current(scope().attr("__dict__")); if (!current.has_key("distribution_variate_map")) scope().attr("distribution_variate_map") = dict(); scope().attr("distribution_variate_map")[distribution_class] = *this; this->def("__call__", make_function( boost::apply() , default_call_policies() , mpl::vector2() ) ); } }; template struct distribution_class : class_ { static typename Distribution::result_type call( Distribution& d, boost::buffered_uniform_01<>& rng ) { return d(rng); } template distribution_class(char const* name, Init init) : class_(name, init) { this->def("reset", &Distribution::reset); // this->def("__call__", &call); } }; template struct rng_wrapper : boost::base_from_member , boost::basic_buffered_uniform_01 { typedef boost::base_from_member member_base; typedef boost::basic_buffered_uniform_01 buffered_base; rng_wrapper() : buffered_base(this->member) {} rng_wrapper(rng_wrapper const& other) : member_base(other.member) , buffered_base(this->member) {} #define BOOST_PP_LOCAL_MACRO(n) \ template \ rng_wrapper(BOOST_PP_ENUM_BINARY_PARAMS(n, A, a)) \ : member_base(BOOST_PP_ENUM_PARAMS(n, a)) \ , buffered_base(this->member) \ {} #define BOOST_PP_LOCAL_LIMITS (1, 5) #include BOOST_PP_LOCAL_ITERATE() void seed() { this->member.seed(); this->reset(); } #define BOOST_PP_LOCAL_MACRO(n) \ template \ void seed(BOOST_PP_ENUM_BINARY_PARAMS(n, A, a)) \ { \ this->member.seed(BOOST_PP_ENUM_PARAMS(n, a)); \ this->reset(); \ } #define BOOST_PP_LOCAL_LIMITS (1, 5) #include BOOST_PP_LOCAL_ITERATE() }; template struct buffered_uniform_01_class : class_< rng_wrapper, bases > > { typedef class_< rng_wrapper, bases > > base; buffered_uniform_01_class(char const* name) : base(name) { this->def("seed", (void(rng_wrapper::*)())&rng_wrapper::seed); } }; template R(*unary_function(R(*f)(A0)))(A0) { return f; } boost::multivariate_normal_distribution<>* make_multivariate_normal_distribution(object const& c, object const& m) { Py_ssize_t size = len(m); if (len(c) != size) { PyErr_SetString(PyExc_IndexError, "cholesky matrix must be square with the same size as the mean vector"); } boost::multivariate_normal_distribution<>::matrix_type cholesky(size,size); boost::multivariate_normal_distribution<>::matrix_type::array_type::iterator out( cholesky.data().begin()); for (stl_input_iterator i(c); i != stl_input_iterator(); ++i) { object inner(*i); if (len(inner) != size) { PyErr_SetString(PyExc_IndexError, "cholesky matrix must be square with the same size as the mean vector"); } out = std::copy(stl_input_iterator(inner), stl_input_iterator(), out); } boost::multivariate_normal_distribution<>::vector_type mean(size); std::copy(stl_input_iterator(m), stl_input_iterator(), mean.begin()); return new boost::multivariate_normal_distribution<>(cholesky, mean); } BOOST_PYTHON_MODULE(_boost_random) { typedef boost::buffered_uniform_01 rng; class_, boost::noncopyable>("buffered_generator", no_init) .def("__call__", make_function( boost::apply::result_type>() , default_call_policies() , mpl::vector2::result_type, boost::buffered_generator&>() ) ); class_< boost::buffered_uniform_01<>, bases >, boost::noncopyable >("buffered_uniform_01", no_init); buffered_uniform_01_class("minstd_rand0") .def(init(arg("x0"))) .def( "seed" , (void(rng_wrapper::*)(boost::minstd_rand0::result_type)) &rng_wrapper::seed , arg("x0") ); buffered_uniform_01_class("minstd_rand") .def(init(arg("x0"))) .def( "seed" , (void(rng_wrapper::*)(boost::minstd_rand::result_type)) &rng_wrapper::seed , arg("x0") ); buffered_uniform_01_class("ecuyer1988") .def(init( (arg("x0"), arg("x1")) )) .def( "seed" , (void(rng_wrapper::*)(boost::ecuyer1988::result_type, boost::ecuyer1988::result_type)) &rng_wrapper::seed , (arg("x0"), arg("x1")) ); buffered_uniform_01_class("kreutzer1986") .def(init(arg("s"))) .def( "seed" , (void(rng_wrapper::*)(boost::kreutzer1986::result_type)) &rng_wrapper::seed , arg("s") ); buffered_uniform_01_class("hellekalek1995") .def(init(arg("y0"))) .def( "seed" , (void(rng_wrapper::*)(boost::hellekalek1995::result_type)) &rng_wrapper::seed , arg("y0") ); buffered_uniform_01_class("mt11213b") .def(init(arg("value"))) .def( "seed" , (void(rng_wrapper::*)(boost::mt11213b::result_type)) &rng_wrapper::seed , arg("value") ); buffered_uniform_01_class("mt19937") .def(init(arg("value"))) .def( "seed" , (void(rng_wrapper::*)(boost::mt19937::result_type)) &rng_wrapper::seed , arg("value") ); buffered_uniform_01_class("lagged_fibonacci607") .def(init(arg("value"))) .def( "seed" , (void(rng_wrapper::*)(boost::uint32_t)) &rng_wrapper::seed , arg("value") ); buffered_uniform_01_class("lagged_fibonacci1279") .def(init(arg("value"))) .def( "seed" , (void(rng_wrapper::*)(boost::uint32_t)) &rng_wrapper::seed , arg("value") ); buffered_uniform_01_class("lagged_fibonacci2281") .def(init(arg("value"))) .def( "seed" , (void(rng_wrapper::*)(boost::uint32_t)) &rng_wrapper::seed , arg("value") ); buffered_uniform_01_class("lagged_fibonacci3217") .def(init(arg("value"))) .def( "seed" , (void(rng_wrapper::*)(boost::uint32_t)) &rng_wrapper::seed , arg("value") ); buffered_uniform_01_class("lagged_fibonacci4423") .def(init(arg("value"))) .def( "seed" , (void(rng_wrapper::*)(boost::uint32_t)) &rng_wrapper::seed , arg("value") ); buffered_uniform_01_class("lagged_fibonacci9689") .def(init(arg("value"))) .def( "seed" , (void(rng_wrapper::*)(boost::uint32_t)) &rng_wrapper::seed , arg("value") ); buffered_uniform_01_class("lagged_fibonacci19937") .def(init(arg("value"))) .def( "seed" , (void(rng_wrapper::*)(boost::uint32_t)) &rng_wrapper::seed , arg("value") ); buffered_uniform_01_class("lagged_fibonacci23209") .def(init(arg("value"))) .def( "seed" , (void(rng_wrapper::*)(boost::uint32_t)) &rng_wrapper::seed , arg("value") ); buffered_uniform_01_class("lagged_fibonacci44497") .def(init(arg("value"))) .def( "seed" , (void(rng_wrapper::*)(boost::uint32_t)) &rng_wrapper::seed , arg("value") ); distribution_class >( "uniform_int" , init( (arg("min")=0, arg("max")=9) ) ) .def("max", &boost::uniform_int<>::max) .def("min", &boost::uniform_int<>::min); distribution_class >( "bernoulli_distribution" , init(arg("p")=0.5) ) .def("p", &boost::bernoulli_distribution<>::p); distribution_class >( "geometric_distribution" , init(arg("p")=0.5) ) .def("p", &boost::geometric_distribution<>::p); distribution_class >( "triangle_distribution" , init( (arg("a"), arg("b"), arg("c")) ) ) .def("a", &boost::triangle_distribution<>::a) .def("b", &boost::triangle_distribution<>::b) .def("c", &boost::triangle_distribution<>::c); distribution_class >( "exponential_distribution" , init(arg("lambda_")) ) .def("lambda_", &boost::exponential_distribution<>::lambda); distribution_class >( "normal_distribution" , init( (arg("mean")=0.0, arg("sigma")=1.0) ) ) .def("mean", &boost::normal_distribution<>::mean) .def("sigma", &boost::normal_distribution<>::sigma); distribution_class >( "lognormal_distribution" , init( (arg("mean")=0.0, arg("sigma")=1.0) ) ) .def("mean", &boost::lognormal_distribution<>::mean) .def("sigma", &boost::lognormal_distribution<>::sigma); distribution_class >( "multivariate_normal_distribution" , no_init ) .def("__init__", make_constructor(make_multivariate_normal_distribution)); // .def("mean", &boost::multivariate_normal_distribution<>::mean); // .def("cholesky", &boost::multivariate_normal_distribution<>::cholesky); variate_generator_class >("uniform_int_variate"); variate_generator_class >("bernoulli_distribution_variate"); variate_generator_class >("geometric_distribution_variate"); variate_generator_class >("triangle_distribution_variate"); variate_generator_class >("exponential_distribution_variate"); variate_generator_class >("normal_distribution_variate"); variate_generator_class >("lognormal_distribution_variate"); variate_generator_class >("multivariate_normal_distribution_variate"); /* #define SPRNG_CLASSES \ (cmrg)(lcg)(lcg64)(lfg)(mlfg) //(pmlcg) #define MAKE_PYTHON_CLASS(r, _, rng) \ buffered_uniform_01_class(BOOST_PP_STRINGIZE(rng) "_01") \ .def(sprng_visitor()); BOOST_PP_SEQ_FOR_EACH(MAKE_PYTHON_CLASS, ~, SPRNG_CLASSES) #undef MAKE_PYTHON_CLASS #undef SPRNG_CLASSES typedef mpl::vector3< boost::random::random_tag::stream_number* , boost::random::random_tag::total_streams* , boost::random::random_tag::global_seed* > lcg64_keywords; buffered_uniform_01_class("lcg64_01") .def( boost::parameter::python::init< lcg64_keywords , mpl::vector3 >() ) .def("seed", boost::parameter::python::function< seed_fwd , lcg64_keywords , mpl::vector4 >() );*/ }