From c9e4667a826c0f4bdc588c3a92c44df6dbc72fa0 Mon Sep 17 00:00:00 2001 From: Matthias Troyer Date: Thu, 22 Jun 2006 08:06:56 +0000 Subject: [PATCH] *** empty log message *** [SVN r3012] --- build/Jamfile.v2 | 53 +++++++++++-------- include/boost/random/parallel/keyword.hpp | 6 ++- include/boost/random/parallel/lcg64.hpp | 39 +++++++++++--- include/boost/random/parallel/mpi.hpp | 32 ++++++----- include/boost/random/parallel/seed.hpp | 16 ++++-- .../random/sprng/detail/implementation.hpp | 32 ++++++++++- python/random.cpp | 2 +- test/Jamfile.v2 | 39 ++++++++++++++ test/buffered_generator_test.cpp | 2 +- test/buffered_uniform_01_test.cpp | 2 +- test/lcg64_test.cpp | 6 +-- test/mpi_test.cpp | 15 ++---- test/parameter_test.cpp | 2 +- test/sprng_parameter_test.cpp | 17 +++++- 14 files changed, 196 insertions(+), 67 deletions(-) create mode 100755 test/Jamfile.v2 diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 8109ea4..dfcfdf0 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -4,40 +4,49 @@ # License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) +import os ; -if [ modules.peek : SPRNG_ROOT ] -{ -project boost/random/sprng - : source-location $(SPRNG_ROOT)/SRC - : requirements $(SPRNG_ROOT)/SRC - : default-build release - ; +sprng = [ os.environ SPRNG_ROOT ] ; -SOURCES = lcg64/lcg64 +project boost/random + : requirements ../../.. $(BOOST_ROOT) + : source-location ../src + ; + +SOURCES_SPRNG = + lcg64/lcg64 lcg/lcg cmrg/cmrg mlfg/mlfg lfg/lfg - pmlcg/pmlcg memory primes_32 primes_64 store checkid ; - -lib boost_random_sprng - : $(SPRNG_ROOT)/SRC/lcg64/lcg64 - $(SPRNG_ROOT)/SRC/lcg/lcg.c - $(SPRNG_ROOT)/SRC/cmrg/cmrg - $(SPRNG_ROOT)/SRC/mlfg/mlfg - $(SPRNG_ROOT)/SRC/lfg/lfg - $(SPRNG_ROOT)/SRC/pmlcg/pmlcg - $(SPRNG_ROOT)/SRC/memory - $(SPRNG_ROOT)/SRC/primes_32 - $(SPRNG_ROOT)/SRC/primes_64 - $(SPRNG_ROOT)/SRC/store - $(SPRNG_ROOT)/SRC/checkid +SOURCES_RANDOM = + primelist_64.cpp + get_prime.cpp ; + +lib boost_random + : ../src/$(SOURCES_RANDOM) + : $(BOOST_ROOT) + : debug release + ; + + +if $(sprng) { +lib boost_random_sprng + : $(sprng)/SRC/$(SOURCES_SPRNG).c + : $(sprng)/SRC static + : debug release + ; +} +else +{ + ECHO Set the SPRNG_ROOT environment variable to point to the SPRNG sources + ECHO if you want to build the SPRNG parallel randum number generators. ; } diff --git a/include/boost/random/parallel/keyword.hpp b/include/boost/random/parallel/keyword.hpp index 6dd7281..da3ea75 100644 --- a/include/boost/random/parallel/keyword.hpp +++ b/include/boost/random/parallel/keyword.hpp @@ -14,6 +14,10 @@ #ifndef BOOST_RANDOM_PARALLEL_KEYWORD_HPP #define BOOST_RANDOM_PARALLEL_KEYWORD_HPP +#ifndef BOOST_RANDOM_MAXARITY +#define BOOST_RANDOM_MAXARITY 5 +#endif + namespace boost { namespace random { using mpl::placeholders::_; @@ -24,7 +28,7 @@ namespace boost { namespace random { typedef parameter::parameters< parameter::optional > , parameter::optional > - , parameter::optional > + , parameter::optional > parallel_seed_params; } } // namespace boost::random diff --git a/include/boost/random/parallel/lcg64.hpp b/include/boost/random/parallel/lcg64.hpp index 1272daf..e83a041 100644 --- a/include/boost/random/parallel/lcg64.hpp +++ b/include/boost/random/parallel/lcg64.hpp @@ -63,12 +63,39 @@ public: seed(BOOST_PP_ENUM_PARAMS(n,x) ); \ } -BOOST_PP_REPEAT_FROM_TO(1, 4, BOOST_LCG64_GENERATOR,~) +BOOST_PP_REPEAT_FROM_TO(1, BOOST_RANDOM_MAXARITY, BOOST_LCG64_GENERATOR,~) #undef BOOST_LCG64_GENERATOR - // forwarding seed functions - BOOST_PARAMETER_MEMFUN(void,seed,1,4,parallel_seed_params) +// forward seeding functions to named versions +#define BOOST_LCG64_SEED(z, n, unused) \ + template \ + void seed(BOOST_PP_ENUM_BINARY_PARAMS(n,T,const& x)) \ + { \ + seed_named(BOOST_PP_ENUM_PARAMS(n,x) ); \ + } + +BOOST_PP_REPEAT_FROM_TO(1, BOOST_RANDOM_MAXARITY, BOOST_LCG64_SEED,~) + +#undef BOOST_LCG64_SEED_IT + +// forward seeding functions with iterator buffers to named versions +#define BOOST_LCG64_SEED_IT(z, n, unused) \ + template \ + void seed(It& first, It const& last, BOOST_PP_ENUM_BINARY_PARAMS(n,T,const& x)) \ + { \ + if(first == last) \ + throw std::invalid_argument("boost::sprng::parallel::lcg64::seed"); \ + seed(global_seed=*first++,BOOST_PP_ENUM_PARAMS(n,x) ); \ + } + +BOOST_PP_REPEAT_FROM_TO(1, BOOST_RANDOM_MAXARITY, BOOST_LCG64_SEED_IT,~) + +#undef BOOST_LCG64_SEED_IT + + + // forwarding named seeding functions + BOOST_PARAMETER_MEMFUN(void,seed_named,1,BOOST_RANDOM_MAXARITY,parallel_seed_params) { seed_implementation(p[stream_number|0u], p[total_streams|1u], p[global_seed|0]); } @@ -205,11 +232,11 @@ const uint64_t lcg64::max_streams; // the three tested versions, validation still missing typedef random::parallel::lcg64 lcg64; + uint64_t( 481823773Ul)+(uint64_t(3380683238Ul)<<32)> lcg64a; typedef random::parallel::lcg64 lcg64a; + uint64_t(3274024413Ul)+(uint64_t(3475904802Ul)<<32)> lcg64b; typedef random::parallel::lcg64 lcg64b; + uint64_t( 950651229Ul)+(uint64_t(3996309981Ul)<<32)> lcg64c; } // namespace boost diff --git a/include/boost/random/parallel/mpi.hpp b/include/boost/random/parallel/mpi.hpp index d8f924b..94bfaa4 100644 --- a/include/boost/random/parallel/mpi.hpp +++ b/include/boost/random/parallel/mpi.hpp @@ -20,22 +20,19 @@ namespace boost { namespace random { namespace parallel { void seed( PRNG& prng , boost::parallel::mpi::communicator const& c - , unsigned int seed=0u ) { - prng.seed(global_seed=seed, stream_number=c.rank(), total_streams=c.size()); + seed(prng, c.rank(), c.size()); } - template - void broadcast_seed( + template + void seed( PRNG& prng , boost::parallel::mpi::communicator const& c - , int root - , unsigned int seed=0u + , SeedType const& s ) { - boost::parallel::mpi::broadcast(c,seed,root); - prng.seed(global_seed=seed, stream_number=c.rank(), total_streams=c.size()); + seed(prng, c.rank(), c.size(), s); } template @@ -46,9 +43,19 @@ namespace boost { namespace random { namespace parallel { , Iterator const& last ) { - if(first == last) - throw_exception(std::invalid_argument("parallel_seed")); - seed(prng, c, *first++); + seed(prng, c.rank(), c.size(), first, last); + } + + template + void broadcast_seed( + PRNG& prng + , boost::parallel::mpi::communicator const& c + , int root + , SeedType s + ) + { + boost::parallel::mpi::broadcast(c,s,root); + seed(prng, c.rank(), c.size(), s); } template @@ -61,7 +68,7 @@ namespace boost { namespace random { namespace parallel { ) { // read a seed value only if I'm the root rank - int seed=0; + typename std::iterator_traits::value_type seed; if (c.rank()==root) { if(first == last) throw_exception(std::invalid_argument("parallel_seed")); @@ -70,7 +77,6 @@ namespace boost { namespace random { namespace parallel { broadcast_seed(prng, c, root, seed); } - } } } // namespace boost::random::parallel #endif // BOOST_RANDOM_PARALLEL_MPI_HPP diff --git a/include/boost/random/parallel/seed.hpp b/include/boost/random/parallel/seed.hpp index f91ed72..ac29fff 100644 --- a/include/boost/random/parallel/seed.hpp +++ b/include/boost/random/parallel/seed.hpp @@ -21,10 +21,20 @@ namespace boost { namespace random { namespace parallel { PRNG& prng , unsigned int num , unsigned int total - , unsigned int seed=0u ) { - prng.seed(global_seed=seed, stream_number=num, total_streams=total); + prng.seed(stream_number=num, total_streams=total); + } + + template + void seed( + PRNG& prng + , unsigned int num + , unsigned int total + , SeedType const& s + ) + { + prng.seed(global_seed=s, stream_number=num, total_streams=total); } template @@ -38,7 +48,7 @@ namespace boost { namespace random { namespace parallel { { if(first == last) throw_exception(std::invalid_argument("parallel_seed")); - seed(prng, num, total, *first++); + prng.seed(first,last,stream_number=num, total_streams=total); } diff --git a/include/boost/random/sprng/detail/implementation.hpp b/include/boost/random/sprng/detail/implementation.hpp index 3b3476c..f9dbad4 100644 --- a/include/boost/random/sprng/detail/implementation.hpp +++ b/include/boost/random/sprng/detail/implementation.hpp @@ -87,10 +87,38 @@ public: seed(BOOST_PP_ENUM_PARAMS(n,x) ); \ } -BOOST_PP_REPEAT_FROM_TO(1, 5, BOOST_RANDOM_SPRNG_CONSTRUCTOR,~) +BOOST_PP_REPEAT_FROM_TO(1, BOOST_RANDOM_MAXARITY, BOOST_RANDOM_SPRNG_CONSTRUCTOR,~) #undef BOOST_RANDOM_SPRNG_CONSTRUCTOR +#undef BOOST_LCG64_GENERATOR + +// forward seeding functions to named versions +#define BOOST_RANDOM_SPRNG_SEED(z, n, unused) \ + template \ + void seed(BOOST_PP_ENUM_BINARY_PARAMS(n,T,const& x)) \ + { \ + seed_named(BOOST_PP_ENUM_PARAMS(n,x) ); \ + } + +BOOST_PP_REPEAT_FROM_TO(1, BOOST_RANDOM_MAXARITY, BOOST_RANDOM_SPRNG_SEED,~) + +#undef BOOST_RANDOM_SPRNG_SEED + +// forward seeding functions with iterator buffers to named versions +#define BOOST_RANDOM_SPRNG_SEED_IT(z, n, unused) \ + template \ + void seed(It& first, It const& last, BOOST_PP_ENUM_BINARY_PARAMS(n,T,const& x)) \ + { \ + if(first == last) \ + throw std::invalid_argument("SPRNG seeding invalid argument"); \ + seed(global_seed=*first++,BOOST_PP_ENUM_PARAMS(n,x) ); \ + } + +BOOST_PP_REPEAT_FROM_TO(1, BOOST_RANDOM_MAXARITY, BOOST_RANDOM_SPRNG_SEED_IT,~) + +#undef BOOST_RANDOM_SPRNG_SEED_IT + BOOST_SPRNG_GENERATOR const& operator=(BOOST_SPRNG_GENERATOR const& rhs) { free(); @@ -127,7 +155,7 @@ BOOST_PP_REPEAT_FROM_TO(1, 5, BOOST_RANDOM_SPRNG_CONSTRUCTOR,~) } // forwarding seed functions - BOOST_PARAMETER_MEMFUN(void,seed,1,4,sprng_seed_params) + BOOST_PARAMETER_MEMFUN(void,seed_named,1,BOOST_RANDOM_MAXARITY,sprng_seed_params) { seed_implementation( p[stream_number|0u] diff --git a/python/random.cpp b/python/random.cpp index 1223c36..6d03a94 100755 --- a/python/random.cpp +++ b/python/random.cpp @@ -245,7 +245,7 @@ BOOST_PYTHON_MODULE(_boost_random) , boost::random::random_tag::global_seed* > lcg64_keywords; - buffered_uniform_01_class("lcg64_01") + buffered_uniform_01_class("lcg64_01") .def( boost::parameter::python::init< lcg64_keywords diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 new file mode 100755 index 0000000..c2fc7ad --- /dev/null +++ b/test/Jamfile.v2 @@ -0,0 +1,39 @@ +# (C) Copyright 2006: Eric Niebler +# 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) + +# bring in rules for testing +import testing ; +import os ; + +sprng = [ os.environ SPRNG_ROOT ] ; + + +project + : requirements + ../build//boost_random + static + ../../.. + ; + +test-suite "random_parallel" + : + [ run lcg64_test.cpp ] + [ run parameter_test.cpp ] + [ run buffered_generator_test.cpp ] + [ run buffered_uniform_01_test.cpp ] + [ run random_test.cpp ] + ; + +if $(sprng) { +project + : requirements + ../build//boost_random_sprng + static + ../../.. + ; + test-suite random_sprng + : [ run sprng_test.cpp ] + [ run sprng_parameter_test.cpp ] + ; +} diff --git a/test/buffered_generator_test.cpp b/test/buffered_generator_test.cpp index ad641d4..f69bbfe 100644 --- a/test/buffered_generator_test.cpp +++ b/test/buffered_generator_test.cpp @@ -70,7 +70,7 @@ void test(const std::string & name, const PRNG &) void test_all() { test("minstd_rand", boost::minstd_rand()); - test("lcg64", boost::lcg64()); + test("lcg64a", boost::lcg64a()); } diff --git a/test/buffered_uniform_01_test.cpp b/test/buffered_uniform_01_test.cpp index d37e0a5..c96fc7c 100644 --- a/test/buffered_uniform_01_test.cpp +++ b/test/buffered_uniform_01_test.cpp @@ -70,7 +70,7 @@ void test(const std::string & name, const PRNG &) void test_all() { test("minstd_rand", boost::minstd_rand()); - test("lcg64", boost::lcg64()); + test("lcg64a", boost::lcg64a()); } diff --git a/test/lcg64_test.cpp b/test/lcg64_test.cpp index 15fe74b..e3ee8dd 100644 --- a/test/lcg64_test.cpp +++ b/test/lcg64_test.cpp @@ -58,9 +58,9 @@ void validate(const std::string & name, const PRNG &) void validate_all() { using namespace boost; - validate("lcg64", boost::lcg64()); validate("lcg64a", boost::lcg64a()); validate("lcg64b", boost::lcg64b()); + validate("lcg64c", boost::lcg64c()); } @@ -281,9 +281,9 @@ void instantiate_urng(const std::string & s, const URNG &, const ResultType &) void instantiate_all() { using namespace boost; - instantiate_urng("lcg64", lcg64(),uint64_t(0)); instantiate_urng("lcg64a", lcg64a(),uint64_t(0)); instantiate_urng("lcg64b", lcg64b(),uint64_t(0)); + instantiate_urng("lcg64c", lcg64c(),uint64_t(0)); } @@ -304,9 +304,9 @@ template class boost::normal_distribution; \ template class boost::uniform_on_sphere; \ template class boost::lognormal_distribution; -INSTANT(boost::lcg64) INSTANT(boost::lcg64a) INSTANT(boost::lcg64b) +INSTANT(boost::lcg64c) #undef INSTANT #endif diff --git a/test/mpi_test.cpp b/test/mpi_test.cpp index 85f34b3..8c0898c 100644 --- a/test/mpi_test.cpp +++ b/test/mpi_test.cpp @@ -55,23 +55,14 @@ void test(const std::string & name, const PRNG &) rng3(); typename PRNG::result_type val3 = rng3(); - PRNG rng4; - std::vector buffer(1,0); - std::vector::iterator it=buffer.begin(); - parallel::broadcast_seed(rng4,comm,0,it,buffer.end()); - for(int i = 0; i < 10000; i++) - rng4(); - typename PRNG::result_type val4 = rng4(); - - - bool result = (val==val2) && (val == val3) && (val==val4); - std::cout << val << " " << val2 << " " << val3 << " " << val4 << std::endl; + bool result = (val==val2) && (val == val3); + std::cout << val << " " << val2 << " " << val3 << std::endl; BOOST_CHECK(result); } void test_all() { - test("lcg64", boost::lcg64()); + test("lcg64a", boost::lcg64a()); } diff --git a/test/parameter_test.cpp b/test/parameter_test.cpp index 29cc6d5..17e7b56 100644 --- a/test/parameter_test.cpp +++ b/test/parameter_test.cpp @@ -68,7 +68,7 @@ void test(const std::string & name, const PRNG &) void test_all() { - test("lcg64", boost::lcg64()); + test("lcg64a", boost::lcg64a()); } diff --git a/test/sprng_parameter_test.cpp b/test/sprng_parameter_test.cpp index 3e49bc3..7537a49 100644 --- a/test/sprng_parameter_test.cpp +++ b/test/sprng_parameter_test.cpp @@ -51,8 +51,23 @@ void test(const std::string & name, const PRNG &) for(int i = 0; i < 9999; i++) rng4(); typename PRNG::result_type val4 = rng4(); + + PRNG rng5; + parallel::seed(rng5,1,2,0); + for(int i = 0; i < 10000; i++) + rng4(); + typename PRNG::result_type val5 = rng5(); - bool result = (val==val2) && (val != val3) && (val3==val4); + PRNG rng6; + std::vector buffer(1,0); + std::vector::iterator it=buffer.begin(); + parallel::seed(rng6,1,2,it,buffer.end()); + for(int i = 0; i < 10000; i++) + rng6(); + typename PRNG::result_type val6 = rng6(); + + bool result = (val==val2) && (val != val3) && (val3==val4) && + (val4==val5) && (val5==val6) ; std::cout << val << " " << val2 << " " << val3 << " " << val4 << std::endl; BOOST_CHECK(result); }