diff --git a/dune/solvers/common/CMakeLists.txt b/dune/solvers/common/CMakeLists.txt index 7451cd6c92cd13fbfe11d3dbeb659f67e9a1ac4a..07d57c75c91f5c3382fa099d29099f2b56d4d8cd 100644 --- a/dune/solvers/common/CMakeLists.txt +++ b/dune/solvers/common/CMakeLists.txt @@ -1,4 +1,5 @@ install(FILES + algorithm.hh arithmetic.hh boxconstraint.hh canignore.hh diff --git a/dune/solvers/common/algorithm.hh b/dune/solvers/common/algorithm.hh new file mode 100644 index 0000000000000000000000000000000000000000..c5155fa776ef6caee49e3068543cadf35a1ffe5d --- /dev/null +++ b/dune/solvers/common/algorithm.hh @@ -0,0 +1,117 @@ +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_SOLVERS_COMMON_ALGORITHM_HH +#define DUNE_SOLVERS_COMMON_ALGORITHM_HH + + + +namespace Dune { +namespace Solvers { + + +namespace Imp { + +template<class ST, ST begin, ST end> +struct StaticForLoop +{ + template<class F, class...Args> + static void apply(F&& f, Args&&... args) + { + f(std::integral_constant<ST, begin>(), std::forward<Args>(args)...); + StaticForLoop<ST, begin+1, end>::apply(std::forward<F>(f), std::forward<Args>(args)...); + } +}; + +template<class ST, ST end> +struct StaticForLoop<ST, end, end> +{ + template<class F, class...Args> + static void apply(F&& f, Args&&...) + {} +}; + +// Check if T is an integral constant +template<class T> +struct IsIntegralConstant +{ + static const bool value = false; +}; + +template<class T, T t> +struct IsIntegralConstant<std::integral_constant<T, t>> +{ + static const bool value = true; +}; + +} //end namespace Imp + + + +/** + * \brief Hybrid for loop over integral range + * + * \tparam Index Raw type of used indices + * \tparam Begin Type of begin index + * \tparam End Type of end index + * \tparam F Type of functor containing the loop body + * \tparam Args Types of further arguments to the loop body + * + * \param begin Initial index + * \param end One past last index + * \param f Functor to call in each loop instance + * \param args Additional arguments to be passed to the functor + * + * This is a hybrid for loop that can work on statically and dynamically + * sized containers. The functor is called with index as first argument + * and all additional arguments. + * + * This is the static-size overload which is selected if begin and + * end are both static indices, i.e., integral constants. The loop + * body is called with std::integral_constant<Index,i> where i + * is the static index. + */ +template<class Index, class Begin, class End, class F, class... Args, + std::enable_if_t<Imp::IsIntegralConstant<Begin>::value and Imp::IsIntegralConstant<End>::value, int> = 0> +void integralRangeFor(Begin&& begin, End&& end, F&& f, Args&&... args) +{ + static const Index begin_t = begin; + static const Index end_t = end; + Imp::StaticForLoop<Index, begin_t, end_t>::apply(std::forward<F>(f), std::forward<Args>(args)...); +} + +/** + * \brief Hybrid for loop over integral range + * + * \tparam Index Raw type of used indices + * \tparam Begin Type of begin index + * \tparam End Type of end index + * \tparam F Type of functor containing the loop body + * \tparam Args Types of further arguments to the loop body + * + * \param begin Initial index + * \param end One past last index + * \param f Functor to call in each loop instance + * \param args Additional arguments to be passed to the functor + * + * This is a hybrid for loop that can work on statically and dynamically + * sized containers. The functor is called with index as first argument + * and all additional arguments. + * + * This is the dynamic-size overload which is selected if either begin or + * end is a dynamic index, i.e., not an integral constant. The loop + * body is called with indices of type Index. + */ +template<class Index, class Begin, class End, class F, class... Args, + std::enable_if_t<not(Imp::IsIntegralConstant<Begin>::value and Imp::IsIntegralConstant<End>::value), int> = 0> +void integralRangeFor(Begin&& begin, End&& end, F&& f, Args&&... args) +{ + for(Index i=begin; i != end; ++i) + f(i, std::forward<Args>(args)...); +} + + +} // namespace Solvers +} // namespace Dune + + +#endif// DUNE_SOLVERS_COMMON_FORLOOP_HH