diff --git a/dune/solvers/common/CMakeLists.txt b/dune/solvers/common/CMakeLists.txt index 4af29f62113514bb2e2cd9c7195d113d8c5b5c86..fdeb182c3fbf132796d97137d65c9cec5447fe87 100644 --- a/dune/solvers/common/CMakeLists.txt +++ b/dune/solvers/common/CMakeLists.txt @@ -1,5 +1,4 @@ install(FILES - algorithm.hh arithmetic.hh boxconstraint.hh canignore.hh diff --git a/dune/solvers/common/algorithm.hh b/dune/solvers/common/algorithm.hh deleted file mode 100644 index 94f36b6e500eb854544eccf4f7f496c5cb7c7e05..0000000000000000000000000000000000000000 --- a/dune/solvers/common/algorithm.hh +++ /dev/null @@ -1,326 +0,0 @@ -// -*- 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 - -#include <dune/common/indices.hh> - -#include <dune/common/typeutilities.hh> -#include <dune/common/typetraits.hh> - - -#include <dune/istl/multitypeblockvector.hh> - -namespace Dune { -namespace Solvers { - -// Implementation of integralRangeFor -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&&...) - {} -}; - -// Overload for static ranges -template<class Index, class Begin, class End, class F, class... Args, - std::enable_if_t<IsIntegralConstant<Begin>::value and IsIntegralConstant<End>::value, int> = 0> -void integralRangeFor(Begin&& begin, End&& end, F&& f, Args&&... args) -{ - static const Index begin_t = std::decay_t<Begin>::value; - static const Index end_t = std::decay_t<End>::value; - StaticForLoop<Index, begin_t, end_t>::apply(std::forward<F>(f), std::forward<Args>(args)...); -} - -// Overload for dynamic ranges -template<class Index, class Begin, class End, class F, class... Args, - std::enable_if_t<not(IsIntegralConstant<Begin>::value and 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)...); -} - -} - -/** - * \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. If begin and end are both of type - * std::integral_constant<*,*> than the loop is static with indices - * of the form std::integral_constant<Index, *>, otherwise the loop - * is dynamic with indices type Index. - */ -template<class Index, class Begin, class End, class F, class... Args> -void integralRangeFor(Begin&& begin, End&& end, F&& f, Args&&... args) -{ - Imp::integralRangeFor<Index>(std::forward<Begin>(begin), std::forward<End>(end), std::forward<F>(f), std::forward<Args>(args)...); -} - - - -// Implementation of hybridEquals -namespace Imp { - -// Compute t1==t2 either statically or dynamically -template<class T1, class T2> -constexpr auto hybridEquals(const T1& t1, const T2& t2, PriorityTag<1>) -> decltype(T1::value, T2::value, std::integral_constant<bool,T1::value == T2::value>()) -{ return {}; } - -template<class T1, class T2> -constexpr auto hybridEquals(const T1& t1, const T2& t2, PriorityTag<0>) -{ - return t1==t2; -} - -} //end namespace Imp - -/** - * \brief Hybrid equality comparison - * - * If both types have a static member value, the result of comparing - * these is returned as std::integral_constant<bool, *>. Otherwise - * the result of a runtime comparison of t1 and t2 is directly returned. - */ -template<class T1, class T2> -constexpr auto hybridEquals(const T1& t1, const T2& t2) -{ - return Imp::hybridEquals(t1, t2, PriorityTag<1>()); -} - - - -// Implementation of hybridIf -namespace Imp { - -template<class IfFunc, class ElseFunc> -constexpr void hybridIf(std::true_type, IfFunc&& ifFunc, ElseFunc&& elseFunc) -{ - ifFunc([](auto&& x) { return std::forward<decltype(x)>(x);}); -} - -template<class IfFunc, class ElseFunc> -constexpr void hybridIf(std::false_type, IfFunc&& ifFunc, ElseFunc&& elseFunc) -{ - elseFunc([](auto&& x) { return std::forward<decltype(x)>(x);}); -} - -template<class IfFunc, class ElseFunc> -constexpr void hybridIf(const bool& condition, IfFunc&& ifFunc, ElseFunc&& elseFunc) -{ - if (condition) - ifFunc([](auto&& x) { return std::forward<decltype(x)>(x);}); - else - elseFunc([](auto&& x) { return std::forward<decltype(x)>(x);}); -} - -} //end namespace Imp - -/** - * \brief Hybrid if - * - * This will call either ifFunc or elseFunc depending - * on the condition. In any case a single argument - * will be passed to the called function. This will always - * be the indentity function. Passing an expression through - * this function will lead to lazy evaluation. This way both - * 'branches' can contain expressions that are only valid - * within this branch if the condition is a std::integral_constant<bool,*>. - * - * In order to do this, the passed functors must have a single - * argument of type auto. - */ -template<class Condition, class IfFunc, class ElseFunc> -constexpr void hybridIf(const Condition& condition, IfFunc&& ifFunc, ElseFunc&& elseFunc) -{ - Imp::hybridIf(condition, std::forward<IfFunc>(ifFunc), std::forward<ElseFunc>(elseFunc)); -} - -/** - * \brief Hybrid if - * - * This provides a hybridIf with empty else clause. - */ -template<class Condition, class IfFunc> -constexpr void hybridIf(const Condition& condition, IfFunc&& ifFunc) -{ - hybridIf(condition, std::forward<IfFunc>(ifFunc), [](auto&& i) {}); -} - - - -// Everything in the next namespace block is just used to implement StaticSize, HasStaticSize, hybridSize -namespace Imp { - -// As a last resort try if there's a static constexpr size() -template<class T> -constexpr auto staticSize(const T*, const PriorityTag<0>&) - -> decltype(std::integral_constant<std::size_t,T::size()>()) -{ - return {}; -} - -// Try if tuple_size is implemented for class -template<class T> -constexpr auto staticSize(const T*, const PriorityTag<2>&) - -> decltype(std::integral_constant<std::size_t,std::tuple_size<T>::value>()) -{ - return {}; -} - -// Try if tuple_size is implemented for class -template<class T, int i> -constexpr auto staticSize(const Dune::FieldVector<T, i>*, const PriorityTag<3>&) - -> decltype(std::integral_constant<std::size_t,i>()) -{ - return {}; -} - -template<class T> -constexpr std::false_type hasStaticSize(const T* t, const PriorityTag<0>& p) -{ - return {}; -} - -template<class T> -constexpr auto hasStaticSize(const T* t, const PriorityTag<1>& p) - -> decltype(staticSize(t ,PriorityTag<42>()), std::true_type()) -{ - return {}; -} - -} - - - -/** - * \brief Check if type is a statically sized container - * - * \ingroup Utility - * - * Derives from std::true_type or std::false_type - */ -template<class T> -struct HasStaticSize : - public decltype(Imp::hasStaticSize((typename std::decay<T>::type*)(nullptr), PriorityTag<42>())) -{}; - - - -/** - * \brief Obtain size of statically sized container - * - * \ingroup Utility - * - * Derives from std::integral_constant<std::size_t, size> - */ -template<class T> -struct StaticSize : - public decltype(Imp::staticSize((typename std::decay<T>::type*)(nullptr), PriorityTag<42>())) -{}; - - - -/** - * \brief Hybrid size query - * - * \tparam T Type of container whose size is queried - * - * \param t Container whose size is queried - * - * This function is hybrid in the sense that it returns a statically - * encoded size, i.e., an integral_constant if possible and the - * dynamic result of the t.size() method otherwise. - * - * This is the static-size overload which returns the size i - * as std::integral_constant<std::size_t, i>. - */ -template<class T, - std::enable_if_t<HasStaticSize<T>::value, int> = 0> -constexpr auto hybridSize(const T& t) -{ - return Imp::staticSize((T*)(nullptr), PriorityTag<42>()); -} - -/** - * \brief Hybrid size query - * - * \tparam T Type of container whose size is queried - * - * \param t Container whose size is queried - * - * This function is hybrid in the sense that it returns a statically - * encoded size, i.e., an integral_constant if possible and the - * dynamic result of the *.size() method otherwise. - * - * This is the dynamic-size overload which returns the result - * of t.size(). - */ -template<class T, - std::enable_if_t<not HasStaticSize<T>::value, int> = 0> -constexpr auto hybridSize(const T& t) -{ - return t.size(); -} - - - -/** - * \brief Hybrid for loop over sparse range - */ -template<class... T, class F> -void sparseRangeFor(const Dune::MultiTypeBlockVector<T...>& range, F&& f) -{ - integralRangeFor<std::size_t>(Indices::_0, hybridSize(range), [&](auto&& i) { - f(range[i], i); - }); -} - - - -/** - * \brief Hybrid for loop over sparse range - */ -template<class Range, class F> -void sparseRangeFor(Range&& range, F&& f) -{ - auto it = range.begin(); - auto end = range.end(); - for(; it!=end; ++it) - f(*it, it.index()); -} - - - -} // namespace Solvers -} // namespace Dune - - -#endif // DUNE_SOLVERS_COMMON_ALGORITHM_HH