Skip to content
Snippets Groups Projects
Commit 2471d05f authored by Carsten Gräser's avatar Carsten Gräser
Browse files

Remove algorithm.hh

Fixes #13.

* sparseRangeFor() is properly implemented in dune-matrix-vector
* the rest was moved to dune-common long time ago
parent a119a452
No related branches found
No related tags found
No related merge requests found
Pipeline #
install(FILES
algorithm.hh
arithmetic.hh
boxconstraint.hh
canignore.hh
......
// -*- 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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment