/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2010 University of Bonn. All rights reserved. * Please see the LICENSE file or "Copyright notice" in builder.cpp for details. */ /* * RandomNumberGeneratorFactory.cpp * * Created on: Dec 31, 2010 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "CodePatterns/MemDebug.hpp" #include #include "CodePatterns/Singleton_impl.hpp" #include "CodePatterns/Assert.hpp" #include "TemplatePowerSetGenerator.hpp" #include "RandomNumberEngine_Encapsulation.hpp" #include "RandomNumberDistribution_Encapsulation.hpp" #include "RandomNumberGenerator_Encapsulation.hpp" #include #include #include "RandomNumberGeneratorFactory.hpp" #include "RandomNumberGeneratorFactory.def" enum RandomNumberGeneratorFactory::Engine RandomNumberGeneratorFactory::engine = (enum RandomNumberGeneratorFactory::Engine) 0; enum RandomNumberGeneratorFactory::Distribution RandomNumberGeneratorFactory::distribution = (enum RandomNumberGeneratorFactory::Distribution) 0; RandomNumberGeneratorFactory::EngineMap RandomNumberGeneratorFactory::engines; RandomNumberGeneratorFactory::EngineNamesMap RandomNumberGeneratorFactory::engineNames; RandomNumberGeneratorFactory::DistributionMap RandomNumberGeneratorFactory::distributions; RandomNumberGeneratorFactory::DistributionNamesMap RandomNumberGeneratorFactory::distributionNames; RandomNumberGeneratorFactory::EngineTable RandomNumberGeneratorFactory::EnginePrototypeTable; RandomNumberGeneratorFactory::DistributionTable RandomNumberGeneratorFactory::DistributionPrototypeTable; RandomNumberGeneratorFactory::EngineDistributionTable RandomNumberGeneratorFactory::GeneratorPrototypeTable; RandomNumberGeneratorFactory::RandomNumberGeneratorFactory() { // insert all known engines #define BOOST_PP_LOCAL_MACRO(n) seqitems_as_string_enum_map(~, n, engine_seq, engines) #define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_SEQ_SIZE(engine_seq)-1 ) #include BOOST_PP_LOCAL_ITERATE() #define BOOST_PP_LOCAL_MACRO(n) seqitems_as_string_enum_map(~, n, engine_seq_a, engines) #define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_SEQ_SIZE(engine_seq_a)-1 ) #include BOOST_PP_LOCAL_ITERATE() for (EngineMap::const_iterator iter = engines.begin(); iter != engines.end(); ++iter) { engineNames.insert(make_pair(iter->second, iter->first)); } // insert all known distributions #define BOOST_PP_LOCAL_MACRO(n) seqitems_as_string_enum_map(~, n, distribution_seq, distributions) #define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_SEQ_SIZE(distribution_seq)-1 ) #include BOOST_PP_LOCAL_ITERATE() for (DistributionMap::const_iterator iter = distributions.begin(); iter != distributions.end(); ++iter) { distributionNames.insert(make_pair(iter->second, iter->first)); } FillPrototypeTables(); } /** Removes all pointers to instances from a table while free'ing memory. * * I.e. we assume class T to be a map of some key with its values pointers to * some classes that have to be free'd. * * \param _PrototypeTable table to empty */ template void EmptyPrototypeTable(T &_PrototypeTable) { for (typename T::iterator iter = _PrototypeTable.begin(); !_PrototypeTable.empty(); iter = _PrototypeTable.begin()) { delete (iter->second); _PrototypeTable.erase(iter); } _PrototypeTable.clear(); } RandomNumberGeneratorFactory::~RandomNumberGeneratorFactory() { // clear out factories map to allow boost::shared_ptr to do their work (i.e. to release mem) // this is necessary as factories is a object engines.clear(); engineNames.clear(); EmptyPrototypeTable (EnginePrototypeTable); distributions.clear(); distributionNames.clear(); EmptyPrototypeTable (DistributionPrototypeTable); for (EngineDistributionTable::iterator iter = GeneratorPrototypeTable.begin(); !GeneratorPrototypeTable.empty(); iter = GeneratorPrototypeTable.begin()) { EmptyPrototypeTable< std::map > (iter->second); GeneratorPrototypeTable.erase(iter); } GeneratorPrototypeTable.clear(); } void RandomNumberGeneratorFactory::FillPrototypeTables() { // fill EnginePrototypeTable #define BOOST_PP_LOCAL_MACRO(n) seqitems_as_enum_key_map(~, n, engine_seq, EnginePrototypeTable, new RandomNumberEngine_Encapsulation, boost::, ) #define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_SEQ_SIZE(engine_seq)-1 ) #include BOOST_PP_LOCAL_ITERATE() #define BOOST_PP_LOCAL_MACRO(n) seqitems_as_enum_key_map(~, n, engine_seq_a, EnginePrototypeTable, new RandomNumberEngine_Encapsulation, boost::, ) #define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_SEQ_SIZE(engine_seq_a)-1 ) #include BOOST_PP_LOCAL_ITERATE() // fill DistributionPrototypeTable #define BOOST_PP_LOCAL_MACRO(n) seqitems_as_enum_key_map(~, n, distribution_seq, DistributionPrototypeTable, new RandomNumberDistribution_Encapsulation, boost::, <>) #define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_SEQ_SIZE(distribution_seq)-1 ) #include BOOST_PP_LOCAL_ITERATE() // fill GeneratorPrototypeTable #define DoubleElementSequenceElementizer(z,data,elem) ((data)(elem)) #define seqseqiterate(z,n,seq) BOOST_PP_SEQ_FOR_EACH(DoubleElementSequenceElementizer, BOOST_PP_SEQ_ELEM(n,seq), distribution_seq) #define distributionengine_seqseq BOOST_PP_REPEAT( \ BOOST_PP_SEQ_SIZE(engine_seq), seqseqiterate, engine_seq ) #define distributionengine_seqseq_a BOOST_PP_REPEAT( \ BOOST_PP_SEQ_SIZE(engine_seq_a), seqseqiterate, engine_seq_a ) #define suffixseq ()(<>) #define tableseq (*EnginePrototypeTable)(*DistributionPrototypeTable) #define TableItemPrinter(z,n,sequence) \ BOOST_PP_COMMA_IF(n) \ boost:: \ BOOST_PP_SEQ_ELEM(n,sequence) \ BOOST_PP_SEQ_ELEM(n,suffixseq) #define ParamItemPrinter(z,n,sequence) \ BOOST_PP_COMMA_IF(n) \ BOOST_PP_SEQ_ELEM(n,tableseq) \ [ \ BOOST_PP_SEQ_ELEM(n,sequence) \ ] #define BOOST_PP_LOCAL_MACRO(n) seqitems_as_enum_key_multidimmap(~, n, distributionengine_seqseq, GeneratorPrototypeTable, new RandomNumberGenerator_Encapsulation, TableItemPrinter, ParamItemPrinter) #define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_SEQ_SIZE(distributionengine_seqseq)-1 ) #include BOOST_PP_LOCAL_ITERATE() #define BOOST_PP_LOCAL_MACRO(n) seqitems_as_enum_key_multidimmap(~, n, distributionengine_seqseq_a, GeneratorPrototypeTable, new RandomNumberGenerator_Encapsulation, TableItemPrinter, ParamItemPrinter) #define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_SEQ_SIZE(distributionengine_seqseq_a)-1 ) #include BOOST_PP_LOCAL_ITERATE() } RandomNumberGenerator& RandomNumberGeneratorFactory::makeRandomNumberGenerator() const { // Instantiate and return (implicitly creates a copy of the stored prototype) return *GeneratorPrototypeTable[engine][distribution]; } RandomNumberGenerator& RandomNumberGeneratorFactory::makeRandomNumberGenerator(std::string engine_type, std::string distribution_type) const { enum Engine eng_type; enum Distribution dis_type; // Instantiate and return (implicitly creates a copy of the stored prototype) if (!engine_type.empty()) { ASSERT(engines.count(engine_type) != 0, "RandomNumberGeneratorFactory::makeRandomNumberGenerator() - Selected engine "+engine_type+"is not registered."); eng_type = engines[engine_type]; } else eng_type = engine; if (!distribution_type.empty()) { ASSERT(distributions.count(distribution_type) != 0, "RandomNumberGeneratorFactory::makeRandomNumberGenerator() - Selected distribution "+distribution_type+"is not registered."); dis_type = distributions[distribution_type]; } else dis_type = distribution; return *GeneratorPrototypeTable[ eng_type ][ dis_type ]; } void RandomNumberGeneratorFactory::setEngine(std::string engine_type) { ASSERT(engines.count(engine_type) != 0,"Selected engine "+engine_type+"is not registered."); engine = engines[engine_type]; } const std::string &RandomNumberGeneratorFactory::getEngine() const { return engineNames[engine]; } void RandomNumberGeneratorFactory::setDistribution(std::string distribution_type) { ASSERT(distributions.count(distribution_type) != 0 ,"Selected distribution "+distribution_type+"is not registered."); distribution = distributions[distribution_type]; } const std::string &RandomNumberGeneratorFactory::getDistribution() const { return distributionNames[distribution]; } CONSTRUCT_SINGLETON(RandomNumberGeneratorFactory) #include "RandomNumberGeneratorFactory.undef"