// 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 // Generators #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::tag::stream_number* , boost::random::tag::total_streams* , boost::random::tag::global_seed* , boost::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 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) {} #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); } }; BOOST_PYTHON_MODULE(_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); #define RNG_CLASSES \ (minstd_rand0)(minstd_rand) \ (rand48) \ (ecuyer1988) \ (kreutzer1986) \ (hellekalek1995) \ (mt11213b)(mt19937) \ (lagged_fibonacci607)(lagged_fibonacci1279)(lagged_fibonacci2281) \ (lagged_fibonacci3217)(lagged_fibonacci4423)(lagged_fibonacci9689) \ (lagged_fibonacci19937)(lagged_fibonacci23209)(lagged_fibonacci44497) #define MAKE_PYTHON_CLASS(r, _, rng) \ buffered_uniform_01_class(BOOST_PP_STRINGIZE(rng) "_01"); BOOST_PP_SEQ_FOR_EACH(MAKE_PYTHON_CLASS, ~, RNG_CLASSES) #undef MAKE_PYTHON_CLASS #undef RNG_CLASSES class_ >("uniform_int", init >()); class_ >("bernoulli_distribution", init >()); class_ >("geometric_distribution", init >()); class_ >("triangle_distribution", init >()); class_ >("exponential_distribution", init >()); class_ >("normal_distribution", init >()); class_ >("lognormal_distribution", init >()); 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"); #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 }