diff --git a/src/common/aka_array_printer.hh b/src/common/aka_array_printer.hh index e0949fb8b..f66bb7040 100644 --- a/src/common/aka_array_printer.hh +++ b/src/common/aka_array_printer.hh @@ -1,101 +1,101 @@ /** * @file aka_array_printer.hh * * @author Nicolas Richart * * @date creation mer jun 19 2019 * * @brief A Documented file. * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_array.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_ARRAY_PRINTER_HH__ #define __AKANTU_AKA_ARRAY_PRINTER_HH__ namespace akantu { /* -------------------------------------------------------------------------- */ template class ArrayPrinter { public: ArrayPrinter(const container & cont) : cont(cont) {} void printself(std::ostream & stream, int indent = 0) const { std::string space(indent, AKANTU_INDENT); stream << space << "{"; for (UInt i = 0; i < this->cont.size(); ++i) { stream << this->cont[i]; if (i != this->cont.size() - 1) stream << ", "; } - stream << "}" << std::endl; + stream << "}"; } private: const container & cont; }; /* -------------------------------------------------------------------------- */ template class ArrayPrinter> { public: ArrayPrinter(const Array & cont) : cont(cont) {} void printself(std::ostream & stream, int indent = 0) const { std::string space(indent, AKANTU_INDENT); stream << space << "{"; for (UInt i = 0; i < this->cont.size(); ++i) { stream << "{"; for (UInt j = 0; j < this->cont.getNbComponent(); ++j) { stream << this->cont(i, j); if (j != this->cont.getNbComponent() - 1) stream << ", "; } stream << "}"; if (i != this->cont.size() - 1) stream << ", "; } - stream << "}" << std::endl; + stream << "}"; } private: const Array & cont; }; template decltype(auto) make_printer(const container & array) { return ArrayPrinter(array); } /* -------------------------------------------------------------------------- */ template inline std::ostream & operator<<(std::ostream & stream, const ArrayPrinter & _this) { _this.printself(stream); return stream; } } // namespace akantu #endif /* __AKANTU_AKA_ARRAY_PRINTER_HH__ */ diff --git a/src/common/aka_compatibilty_with_cpp_standard.hh b/src/common/aka_compatibilty_with_cpp_standard.hh index 3afb2ecad..2bcd70e4c 100644 --- a/src/common/aka_compatibilty_with_cpp_standard.hh +++ b/src/common/aka_compatibilty_with_cpp_standard.hh @@ -1,156 +1,173 @@ /** * @file aka_compatibilty_with_cpp_standard.hh * * @author Nicolas Richart * * @date creation: Fri Jun 18 2010 * @date last modification: Wed Jan 10 2018 * * @brief The content of this file is taken from the possible implementations * on * http://en.cppreference.com * * @section LICENSE * * Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_static_if.hh" /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_COMPATIBILTY_WITH_CPP_STANDARD_HH__ #define __AKANTU_AKA_COMPATIBILTY_WITH_CPP_STANDARD_HH__ namespace aka { // Part taken from C++14 #if __cplusplus < 201402L template using enable_if_t = typename enable_if::type; #else template using enable_if_t = std::enable_if_t; #endif // Part taken from C++17 #if __cplusplus < 201703L // bool_constant template using bool_constant = std::integral_constant; namespace { template constexpr bool bool_constant_v = bool_constant::value; } /* -------------------------------------------------------------------------- */ // conjunction template struct conjunction : std::true_type {}; template struct conjunction : B1 {}; template struct conjunction : std::conditional_t, B1> {}; // disjunction template struct disjunction : std::false_type {}; template struct disjunction : B1 {}; template struct disjunction : std::conditional_t> {}; /* -------------------------------------------------------------------------- */ // negations template struct negation : bool_constant {}; /* -------------------------------------------------------------------------- */ namespace detail { template struct is_reference_wrapper : std::false_type {}; template struct is_reference_wrapper> : std::true_type {}; // template // constexpr bool is_reference_wrapper_v = is_reference_wrapper::value; // template // decltype(auto) INVOKE(Type T::*f, T1 && t1, Args &&... args) { // static_assert(std::is_member_function_pointer{} and // std::is_base_of>{}, // "Does not know what to do with this types"); // return (std::forward(t1).*f)(std::forward(args)...); // } template decltype(auto) INVOKE(Type T::*f, T1 && t1, Args &&... args) { static_if(std::is_member_function_pointer{}) .then_([&](auto && f) { static_if(std::is_base_of>{}) .then_([&](auto && f) { return (std::forward(t1).*f)(std::forward(args)...); }) .elseif(is_reference_wrapper>{})([&](auto && f) { return (t1.get().*f)(std::forward(args)...); }) .else_([&](auto && f) { return ((*std::forward(t1)).* f)(std::forward(args)...); })(std::forward(f)); }) .else_([&](auto && f) { static_assert(std::is_member_object_pointer::value, "f is not a member object"); static_assert(sizeof...(args) == 0, "f takes arguments"); static_if(std::is_base_of>{}) .then_([&](auto && f) { return std::forward(t1).*f; }) .elseif(std::is_base_of>{})( [&](auto && f) { return t1.get().*f; }) .else_([&](auto && f) { return (*std::forward(t1)).*f; })( std::forward(f)); })(std::forward(f)); } template decltype(auto) INVOKE(F && f, Args &&... args) { return std::forward(f)(std::forward(args)...); } } // namespace detail template decltype(auto) invoke(F && f, Args &&... args) { return detail::INVOKE(std::forward(f), std::forward(args)...); } namespace detail { template constexpr decltype(auto) apply_impl(F && f, Tuple && t, std::index_sequence) { return invoke(std::forward(f), std::get(std::forward(t))...); } } // namespace detail +/* -------------------------------------------------------------------------- */ template constexpr decltype(auto) apply(F && f, Tuple && t) { return detail::apply_impl( std::forward(f), std::forward(t), std::make_index_sequence>::value>{}); } +/* -------------------------------------------------------------------------- */ + +template +typename std::iterator_traits::difference_type +count_if(InputIt first, InputIt last, UnaryPredicate p) { + typename std::iterator_traits::difference_type ret = 0; + for (; first != last; ++first) { + if (p(*first)) { + ret++; + } + } + return ret; +} +#else +using apply = std::apply; +using count_if = std::count_if; #endif } // namespace aka #endif /* __AKANTU_AKA_COMPATIBILTY_WITH_CPP_STANDARD_HH__ */ diff --git a/src/common/aka_error.hh b/src/common/aka_error.hh index 9dc9e316f..b889408a5 100644 --- a/src/common/aka_error.hh +++ b/src/common/aka_error.hh @@ -1,384 +1,389 @@ /** * @file aka_error.hh * * @author Nicolas Richart * * @date creation: Mon Jun 14 2010 * @date last modification: Tue Feb 20 2018 * * @brief error management and internal exceptions * * @section LICENSE * * Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include #include #include #include /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ERROR_HH__ #define __AKANTU_ERROR_HH__ namespace akantu { /* -------------------------------------------------------------------------- */ enum DebugLevel { dbl0 = 0, dblError = 0, dblAssert = 0, dbl1 = 1, dblException = 1, dblCritical = 1, dbl2 = 2, dblMajor = 2, dbl3 = 3, dblCall = 3, dblSecondary = 3, dblHead = 3, dbl4 = 4, dblWarning = 4, dbl5 = 5, dblInfo = 5, dbl6 = 6, dblIn = 6, dblOut = 6, dbl7 = 7, dbl8 = 8, dblTrace = 8, dbl9 = 9, dblAccessory = 9, dbl10 = 10, dblDebug = 42, dbl100 = 100, dblDump = 100, dblTest = 1337 }; /* -------------------------------------------------------------------------- */ #define AKANTU_LOCATION \ "(" << __func__ << "(): " << __FILE__ << ":" << __LINE__ << ")" /* -------------------------------------------------------------------------- */ namespace debug { void setDebugLevel(const DebugLevel & level); const DebugLevel & getDebugLevel(); void initSignalHandler(); std::string demangle(const char * symbol); template std::string demangle() { return demangle(typeid(T).name()); } - std::string exec(const std::string & cmd); + + template std::string demangle(const T & t) { + return demangle(typeid(t).name()); + } + +std::string exec(const std::string & cmd); void printBacktrace(int sig); void exit(int status) __attribute__((noreturn)); /* ------------------------------------------------------------------------ */ /// exception class that can be thrown by akantu class Exception : public std::exception { /* ---------------------------------------------------------------------- */ /* Constructors/Destructors */ /* ---------------------------------------------------------------------- */ protected: explicit Exception(std::string info = "") : _info(std::move(info)), _file("") {} public: //! full constructor Exception(std::string info, std::string file, unsigned int line) : _info(std::move(info)), _file(std::move(file)), _line(line) {} //! destructor ~Exception() noexcept override = default; /* ---------------------------------------------------------------------- */ /* Methods */ /* ---------------------------------------------------------------------- */ public: const char * what() const noexcept override { return _info.c_str(); } virtual const std::string info() const noexcept { std::stringstream stream; stream << debug::demangle(typeid(*this).name()) << " : " << _info << " [" << _file << ":" << _line << "]"; return stream.str(); } public: void setInfo(const std::string & info) { _info = info; } void setFile(const std::string & file) { _file = file; } void setLine(unsigned int line) { _line = line; } void setModule(const std::string & module) { _module = module; } /* ---------------------------------------------------------------------- */ /* Class Members */ /* ---------------------------------------------------------------------- */ protected: /// exception description and additionals std::string _info; private: /// file it is thrown from std::string _file; /// line it is thrown from unsigned int _line{0}; /// module in which exception was raised std::string _module{"core"}; }; class CriticalError : public Exception {}; class AssertException : public Exception {}; class NotImplementedException : public Exception {}; /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const Exception & _this) { stream << _this.what(); return stream; } /* -------------------------------------------------------------------------- */ class Debugger { public: Debugger(); virtual ~Debugger(); Debugger(const Debugger &) = default; Debugger & operator=(const Debugger &) = default; void exit(int status) __attribute__((noreturn)); void throwException(const std::string & info, const std::string & file, unsigned int line, bool, const std::string &, const std::string & module) const noexcept(false) __attribute__((noreturn)); /*----------------------------------------------------------------------- */ template void throwCustomException(const Except & ex, const std::string & info, const std::string & file, unsigned int line, const std::string & module) const noexcept(false) __attribute__((noreturn)); /*----------------------------------------------------------------------- */ template void throwCustomException(const Except & ex, const std::string & file, unsigned int line, const std::string & module) const noexcept(false) __attribute__((noreturn)); void printMessage(const std::string & prefix, const DebugLevel & level, const std::string & info, const std::string & module) const; void setOutStream(std::ostream & out) { cout = &out; } std::ostream & getOutStream() { return *cout; } public: void setParallelContext(int rank, int size); void setDebugLevel(const DebugLevel & level); const DebugLevel & getDebugLevel() const; void setLogFile(const std::string & filename); std::ostream & getOutputStream(); inline bool testLevel(const DebugLevel & level, const std::string & module = "core") const { auto level_reached = (this->level >= (level)); auto correct_module = (level <= dblCritical) or (modules_to_debug.size() == 0) or (modules_to_debug.find(module) != modules_to_debug.end()); return level_reached and correct_module; } void printBacktrace(bool on_off) { this->print_backtrace = on_off; } bool printBacktrace() { return this->print_backtrace; } void addModuleToDebug(const std::string & id) { modules_to_debug.insert(id); } void removeModuleToDebug(const std::string & id) { auto it = modules_to_debug.find(id); if (it != modules_to_debug.end()) modules_to_debug.erase(it); } void listModules() { for (auto & module_ : modules_to_debug) { (*cout) << module_ << std::endl; } } private: std::string parallel_context; std::ostream * cout; bool file_open; DebugLevel level; bool print_backtrace; std::set modules_to_debug; }; extern Debugger debugger; } // namespace debug /* -------------------------------------------------------------------------- */ #define AKANTU_STRINGIZE_(str) #str #define AKANTU_STRINGIZE(str) AKANTU_STRINGIZE_(str) /* -------------------------------------------------------------------------- */ #define AKANTU_DEBUG_MODULE AKANTU_STRINGIZE(AKANTU_MODULE) /* -------------------------------------------------------------------------- */ #define AKANTU_STRINGSTREAM_IN(_str, _sstr) \ ; \ do { \ std::stringstream _dbg_s_info; \ _dbg_s_info << _sstr; \ _str = _dbg_s_info.str(); \ } while (false) /* -------------------------------------------------------------------------- */ #define AKANTU_EXCEPTION(info) AKANTU_EXCEPTION_(info, false) #define AKANTU_SILENT_EXCEPTION(info) AKANTU_EXCEPTION_(info, true) #define AKANTU_EXCEPTION_(info, silent) \ do { \ std::stringstream _dbg_str; \ _dbg_str << info; \ std::stringstream _dbg_loc; \ _dbg_loc << AKANTU_LOCATION; \ ::akantu::debug::debugger.throwException(_dbg_str.str(), __FILE__, \ __LINE__, silent, _dbg_loc.str(), \ AKANTU_DEBUG_MODULE); \ } while (false) #define AKANTU_CUSTOM_EXCEPTION_INFO(ex, info) \ do { \ std::stringstream _dbg_str; \ _dbg_str << info; \ ::akantu::debug::debugger.throwCustomException( \ ex, _dbg_str.str(), __FILE__, __LINE__, AKANTU_DEBUG_MODULE); \ } while (false) #define AKANTU_CUSTOM_EXCEPTION(ex) \ do { \ ::akantu::debug::debugger.throwCustomException(ex, __FILE__, __LINE__, \ AKANTU_DEBUG_MODULE); \ } while (false) /* -------------------------------------------------------------------------- */ #ifdef AKANTU_NDEBUG #define AKANTU_DEBUG_TEST(level) (false) #define AKANTU_DEBUG_LEVEL_IS_TEST() \ (::akantu::debug::debugger.testLevel(dblTest, AKANTU_DEBUG_MODULE)) #define AKANTU_DEBUG(level, info) #define AKANTU_DEBUG_(pref, level, info) #define AKANTU_DEBUG_IN() #define AKANTU_DEBUG_OUT() #define AKANTU_DEBUG_INFO(info) #define AKANTU_DEBUG_WARNING(info) #define AKANTU_DEBUG_TRACE(info) #define AKANTU_DEBUG_ASSERT(test, info) #define AKANTU_ERROR(info) \ AKANTU_CUSTOM_EXCEPTION_INFO(::akantu::debug::CriticalError(), info) /* -------------------------------------------------------------------------- */ #else #define AKANTU_DEBUG(level, info) AKANTU_DEBUG_(" ", level, info) #define AKANTU_DEBUG_(pref, level, info) \ do { \ std::string _dbg_str; \ AKANTU_STRINGSTREAM_IN(_dbg_str, info << " " << AKANTU_LOCATION); \ ::akantu::debug::debugger.printMessage(pref, level, _dbg_str, \ AKANTU_DEBUG_MODULE); \ } while (false) #define AKANTU_DEBUG_TEST(level) \ (::akantu::debug::debugger.testLevel(level, AKANTU_DEBUG_MODULE)) #define AKANTU_DEBUG_LEVEL_IS_TEST() \ (::akantu::debug::debugger.testLevel(dblTest)) #define AKANTU_DEBUG_IN() \ AKANTU_DEBUG_("==>", ::akantu::dblIn, __func__ << "()") #define AKANTU_DEBUG_OUT() \ AKANTU_DEBUG_("<==", ::akantu::dblOut, __func__ << "()") #define AKANTU_DEBUG_INFO(info) AKANTU_DEBUG_("---", ::akantu::dblInfo, info) #define AKANTU_DEBUG_WARNING(info) \ AKANTU_DEBUG_("/!\\", ::akantu::dblWarning, info) #define AKANTU_DEBUG_TRACE(info) AKANTU_DEBUG_(">>>", ::akantu::dblTrace, info) #define AKANTU_DEBUG_ASSERT(test, info) \ do { \ if (not(test)) \ AKANTU_CUSTOM_EXCEPTION_INFO(::akantu::debug::AssertException(), \ "assert [" << #test << "] " << info); \ } while (false) #define AKANTU_ERROR(info) \ do { \ AKANTU_DEBUG_("!!! ", ::akantu::dblError, info); \ AKANTU_CUSTOM_EXCEPTION_INFO(::akantu::debug::CriticalError(), info); \ } while (false) #endif // AKANTU_NDEBUG #define AKANTU_TO_IMPLEMENT() \ AKANTU_CUSTOM_EXCEPTION_INFO(::akantu::debug::NotImplementedException(), \ __func__ << " : not implemented yet !") /* -------------------------------------------------------------------------- */ namespace debug { /* ------------------------------------------------------------------------ */ template void Debugger::throwCustomException(const Except & ex, const std::string & info, const std::string & file, unsigned int line, const std::string & module) const noexcept(false) { auto & nc_ex = const_cast(ex); nc_ex.setInfo(info); nc_ex.setFile(file); nc_ex.setLine(line); nc_ex.setModule(module); throw ex; } /* ------------------------------------------------------------------------ */ template void Debugger::throwCustomException(const Except & ex, const std::string & file, unsigned int line, const std::string & module) const noexcept(false) { auto & nc_ex = const_cast(ex); nc_ex.setFile(file); nc_ex.setLine(line); nc_ex.setModule(module); throw ex; } } // namespace debug } // namespace akantu #endif /* __AKANTU_ERROR_HH__ */ diff --git a/src/common/aka_random_generator.hh b/src/common/aka_random_generator.hh index 3d22a4777..41bdf1afc 100644 --- a/src/common/aka_random_generator.hh +++ b/src/common/aka_random_generator.hh @@ -1,271 +1,267 @@ /** * @file aka_random_generator.hh * * @author Nicolas Richart * * @date creation: Thu Feb 21 2013 * @date last modification: Wed Nov 08 2017 * * @brief generic random generator * * @section LICENSE * * Copyright (©) 2014-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_array.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_RANDOM_GENERATOR_HH__ #define __AKANTU_AKA_RANDOM_GENERATOR_HH__ namespace akantu { /* -------------------------------------------------------------------------- */ /* List of available distributions */ /* -------------------------------------------------------------------------- */ // clang-format off #define AKANTU_RANDOM_DISTRIBUTION_TYPES \ ((uniform , std::uniform_real_distribution )) \ ((exponential , std::exponential_distribution )) \ ((gamma , std::gamma_distribution )) \ ((weibull , std::weibull_distribution )) \ ((extreme_value, std::extreme_value_distribution)) \ ((normal , std::normal_distribution )) \ ((lognormal , std::lognormal_distribution )) \ ((chi_squared , std::chi_squared_distribution )) \ ((cauchy , std::cauchy_distribution )) \ ((fisher_f , std::fisher_f_distribution )) \ ((student_t , std::student_t_distribution )) // clang-format on #define AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX(elem) BOOST_PP_CAT(_rdt_, elem) #define AKANTU_RANDOM_DISTRIBUTION_PREFIX(s, data, elem) \ AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX(BOOST_PP_TUPLE_ELEM(2, 0, elem)) enum RandomDistributionType { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(AKANTU_RANDOM_DISTRIBUTION_PREFIX, _, AKANTU_RANDOM_DISTRIBUTION_TYPES)), _rdt_not_defined }; /* -------------------------------------------------------------------------- */ /* Generator */ /* -------------------------------------------------------------------------- */ template class RandomGenerator { /* ------------------------------------------------------------------------ */ +private: + static long int _seed; + static std::default_random_engine generator; + /* ------------------------------------------------------------------------ */ public: inline T operator()() { return generator(); } /// function to print the contain of the class - virtual void printself(std::ostream & stream, int) const { + void printself(std::ostream & stream, int) const { stream << "RandGenerator [seed=" << _seed << "]"; } /* ------------------------------------------------------------------------ */ public: static void seed(long int s) { _seed = s; generator.seed(_seed); } static long int seed() { return _seed; } static constexpr T min() { return generator.min(); } static constexpr T max() { return generator.max(); } - - /* ------------------------------------------------------------------------ */ -private: - static long int _seed; - static std::default_random_engine generator; }; -// template -// long int RandomGenerator::_seed = 0; - /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #undef AKANTU_RANDOM_DISTRIBUTION_PREFIX #define AKANTU_RANDOM_DISTRIBUTION_TYPE_PRINT_CASE(r, data, elem) \ case AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX( \ BOOST_PP_TUPLE_ELEM(2, 0, elem)): { \ stream << BOOST_PP_STRINGIZE(AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX( \ BOOST_PP_TUPLE_ELEM(2, 0, elem))); \ break; \ } inline std::ostream & operator<<(std::ostream & stream, RandomDistributionType type) { switch (type) { BOOST_PP_SEQ_FOR_EACH(AKANTU_RANDOM_DISTRIBUTION_TYPE_PRINT_CASE, _, AKANTU_RANDOM_DISTRIBUTION_TYPES) default: stream << UInt(type) << " not a RandomDistributionType"; break; } return stream; } #undef AKANTU_RANDOM_DISTRIBUTION_TYPE_PRINT_CASE /* -------------------------------------------------------------------------- */ /* Some Helper */ /* -------------------------------------------------------------------------- */ template class RandomDistributionTypeHelper { enum { value = _rdt_not_defined }; }; /* -------------------------------------------------------------------------- */ #define AKANTU_RANDOM_DISTRIBUTION_TYPE_GET_TYPE(r, data, elem) \ template \ struct RandomDistributionTypeHelper> { \ enum { \ value = AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX( \ BOOST_PP_TUPLE_ELEM(2, 0, elem)) \ }; \ \ static void printself(std::ostream & stream) { \ stream << BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, elem)); \ } \ }; BOOST_PP_SEQ_FOR_EACH(AKANTU_RANDOM_DISTRIBUTION_TYPE_GET_TYPE, _, AKANTU_RANDOM_DISTRIBUTION_TYPES) #undef AKANTU_RANDOM_DISTRIBUTION_TYPE_GET_TYPE /* -------------------------------------------------------------------------- */ template class RandomDistribution { public: virtual ~RandomDistribution() = default; virtual T operator()(RandomGenerator & gen) = 0; virtual std::unique_ptr> make_unique() const = 0; virtual void printself(std::ostream & stream, int = 0) const = 0; }; template class RandomDistributionProxy : public RandomDistribution { public: explicit RandomDistributionProxy(Distribution dist) : distribution(std::move(dist)) {} T operator()(RandomGenerator & gen) override { return distribution(gen); } std::unique_ptr> make_unique() const override { return std::make_unique>( distribution); } void printself(std::ostream & stream, int = 0) const override { RandomDistributionTypeHelper::printself(stream); stream << " [ " << distribution << " ]"; } private: Distribution distribution; }; /* -------------------------------------------------------------------------- */ /* RandomParameter */ /* -------------------------------------------------------------------------- */ template class RandomParameter { public: template explicit RandomParameter(T base_value, Distribution dist) : base_value(base_value), type(RandomDistributionType( RandomDistributionTypeHelper::value)), distribution_proxy( std::make_unique>( std::move(dist))) {} explicit RandomParameter(T base_value) : base_value(base_value), type(RandomDistributionType( RandomDistributionTypeHelper< T, std::uniform_real_distribution>::value)), distribution_proxy( std::make_unique< RandomDistributionProxy>>( std::uniform_real_distribution(0., 0.))) {} RandomParameter(const RandomParameter & other) : base_value(other.base_value), type(other.type), distribution_proxy(other.distribution_proxy->make_unique()) {} RandomParameter & operator=(const RandomParameter & other) { distribution_proxy = other.distribution_proxy->make_unique(); base_value = other.base_value; type = other.type; return *this; } virtual ~RandomParameter() = default; inline void setBaseValue(const T & value) { this->base_value = value; } inline T getBaseValue() const { return this->base_value; } template