diff --git a/cmake/modules/AddVcFlags.cmake b/cmake/modules/AddVcFlags.cmake new file mode 100644 index 0000000000000000000000000000000000000000..bcb3e7b181980060be84146010f00071f9f92bde --- /dev/null +++ b/cmake/modules/AddVcFlags.cmake @@ -0,0 +1,28 @@ +# Defines the functions to use VC +# +# .. cmake_function:: add_dune_vc_flags +# +# .. cmake_param:: targets +# :positional: +# :single: +# :required: +# +# A list of targets to use VC with. +# + +function(add_dune_vc_flags _targets) + if(Vc_FOUND) + foreach(_target ${_targets}) + target_link_libraries(${_target} ${Vc_LIBRARIES}) + target_compile_options(${_target} PUBLIC ${Vc_ALL_FLAGS}) + target_include_directories(${_target} SYSTEM PUBLIC ${Vc_INCLUDE_DIR}) + endforeach(_target ${_targets}) + endif(Vc_FOUND) +endfunction(add_dune_vc_flags) + +if(Vc_FOUND) + dune_register_package_flags(COMPILE_OPTIONS "${Vc_ALL_FLAGS}" + LIBRARIES "${Vc_LIBRARIES}" + INCLUDE_DIRS "${Vc_INCLUDE_DIR}") +endif(Vc_FOUND) +set(HAVE_VC ${Vc_FOUND}) diff --git a/cmake/modules/DuneCommonMacros.cmake b/cmake/modules/DuneCommonMacros.cmake index b5a04bef1d803b277fd0730574734e0f86539b55..242fe0bb73be541c210590d20d0ae8088d4dabc1 100644 --- a/cmake/modules/DuneCommonMacros.cmake +++ b/cmake/modules/DuneCommonMacros.cmake @@ -26,3 +26,7 @@ include(AddGMPFlags) find_package(Inkscape) include(UseInkscape) include(FindMProtect) + +# try to find the Vc library +find_package(Vc) +include(AddVcFlags) diff --git a/config.h.cmake b/config.h.cmake index 55398195206002476c55b5e42a07a2c02b342366..6558f21331141f74e45581d74575e6a7e1242655 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -45,6 +45,9 @@ to facilitate activating and deactivating GMP using compile flags. */ #cmakedefine HAVE_GMP ENABLE_GMP +/* Define to 1 if you have the Vc library. */ +#cmakedefine HAVE_VC 1 + /* Define to 1 if you have the symbol mprotect. */ #cmakedefine HAVE_MPROTECT 1 diff --git a/doc/doxygen/modules.txt b/doc/doxygen/modules.txt index af03ad2802d323682313a23551d0f28aededf2b0..75d10ad63c474a652f5e8f9fb593778f0c4bd591 100644 --- a/doc/doxygen/modules.txt +++ b/doc/doxygen/modules.txt @@ -21,6 +21,15 @@ @ingroup Utilities */ +/** + @defgroup RangeUtilities Range Utilities + @brief Utilities for reduction like operations on ranges + + All these reduction operations work for appropriate ranges and scalar values + + @ingroup Utilities +*/ + /** @defgroup StringUtilities String Utilities @brief Utility functions for std::string diff --git a/dune/common/conditional.hh b/dune/common/conditional.hh new file mode 100644 index 0000000000000000000000000000000000000000..e4590f6845569ae969b41ef3cc63d395f6ca8cff --- /dev/null +++ b/dune/common/conditional.hh @@ -0,0 +1,33 @@ +#ifndef DUNE_COMMON_CONDITIONAL_HH +#define DUNE_COMMON_CONDITIONAL_HH + +namespace Dune +{ + + /** \brief conditional evaluate + + sometimes call immediate if, evaluates to + + \code + if (b) + return v1; + else + return v2; + \endcode + + In contrast to if-then-else the cond function can also be + evaluated for vector valued SIMD data types, see simd.hh. + + \param b boolean value + \param v1 value of b==true + \param v2 value of b==false + */ + template<typename T1, typename T2> + const T1 cond(bool b, const T1 & v1, const T2 & v2) + { + return (b ? v1 : v2); + } + +} // end namespace Dune + +#endif // DUNE_COMMON_CONDITIONAL_HH diff --git a/dune/common/rangeutilities.hh b/dune/common/rangeutilities.hh new file mode 100644 index 0000000000000000000000000000000000000000..09b44d266e2581f974a7a118118ffa17af902712 --- /dev/null +++ b/dune/common/rangeutilities.hh @@ -0,0 +1,114 @@ +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_COMMON_RANGE_UTILITIES_HH +#define DUNE_COMMON_RANGE_UTILITIES_HH + +#include <dune/common/typetraits.hh> +#include <utility> +#include <type_traits> +#include <bitset> + +/** + * \file + * \brief Utilities for reduction like operations on ranges + * \author Christian Engwer + */ + +/** + * @addtogroup RangeUtilities + * @{ + */ + +namespace Dune +{ + /** + \brief compute the maximum value over a range + + overloads for scalar values, and ranges exist + */ + template <typename T, + typename std::enable_if<is_range<T>::value, int>::type = 0> + typename T::value_type + max_value(const T & v) { + using std::max; + typename T::value_type m; + for (const auto & e : v) + m = max(e,m); + return m; + }; + + template <typename T, + typename std::enable_if<!is_range<T>::value, int>::type = 0> + const T & max_value(const T & v) { return v; }; + + /** + \brief compute the minimum value over a range + + overloads for scalar values, and ranges exist + */ + template <typename T, + typename std::enable_if<is_range<T>::value, int>::type = 0> + typename T::value_type + min_value(const T & v) { + using std::min; + typename T::value_type m; + for (const auto & e : v) + m = min(e,m); + return m; + }; + + template <typename T, + typename std::enable_if<!is_range<T>::value, int>::type = 0> + T & min_value(const T & v) { return v; }; + + /** + \brief similar to std::bitset<N>::any() return true, if any entries is true + + overloads for scalar values, ranges, and std::bitset<N> exist + */ + template <typename T, + typename std::enable_if<is_range<T>::value, int>::type = 0> + bool any_true(const T & v) { + bool b = false; + for (const auto & e : v) + b = b or bool(e); + return b; + }; + + template <typename T, + typename std::enable_if<!is_range<T>::value, int>::type = 0> + bool any_true(const T & v) { return v; }; + + template<std::size_t N> + bool any_true(const std::bitset<N> & b) + { + return b.any(); + } + + /** + \brief similar to std::bitset<N>::all() return true, if any entries is true + + overloads for scalar values, ranges, and std::bitset<N> exist + */ + template <typename T, + typename std::enable_if<is_range<T>::value, int>::type = 0> + bool all_true(const T & v) { + bool b = true; + for (const auto & e : v) + b = b and bool(e); + return b; + }; + + template <typename T, + typename std::enable_if<!is_range<T>::value, int>::type = 0> + bool all_true(const T & v) { return v; }; + + template<std::size_t N> + bool all_true(const std::bitset<N> & b) + { + return b.all(); + } + +} + +#endif // DUNE_COMMON_RANGE_UTILITIES_HH diff --git a/dune/common/simd.hh b/dune/common/simd.hh new file mode 100644 index 0000000000000000000000000000000000000000..139bad937d8c44b7daeefdc50bbb624c2bd22005 --- /dev/null +++ b/dune/common/simd.hh @@ -0,0 +1,79 @@ +#ifndef DUNE_COMMON_SIMD_HH +#define DUNE_COMMON_SIMD_HH + +#include <dune/common/rangeutilities.hh> +#include <dune/common/conditional.hh> +#if HAVE_VC +#include <Vc/Vc> + +namespace Dune +{ + + template<typename T, typename A> + Vc::Vector<T,A> cond(const Vc::Mask<T,A> & b, + const Vc::Vector<T,A> & v1, + const Vc::Vector<T,A> & v2) + { + return std::move(Vc::iif(b, v1, v2)); + } + + template<typename T, std::size_t N, typename V, std::size_t M> + Vc::SimdArray<T,N,V,M> cond(const typename Vc::SimdArray<T,N,V,M>::mask_type & b, + const Vc::SimdArray<T,N,V,M> & v1, + const Vc::SimdArray<T,N,V,M> & v2) + { + return std::move(Vc::iif(b, v1, v2)); + } + + template<typename T, typename A> + T max_value(const Vc::Vector<T,A> & v) + { + return v.max(); + } + + template<typename T, std::size_t N, typename V, std::size_t M> + double max_value(const Vc::SimdArray<T,N,V,M> & v) + { + return v.max(); + } + + template<typename T, typename A> + T min_value(const Vc::Vector<T,A> & v) + { + return v.min(); + } + + template<typename T, std::size_t N, typename V, std::size_t M> + double min_value(const Vc::SimdArray<T,N,V,M> & v) + { + return v.min(); + } + + template<typename T, typename A> + bool any_true(const Vc::Mask<T,A> & v) + { + return Vc::any_of(v); + } + + template<typename T, std::size_t N, typename V, std::size_t M> + bool any_true(const Vc::SimdMaskArray<T,N,V,M> & v) + { + return Vc::any_of(v); + } + + template<typename T, typename A> + bool all_true(const Vc::Mask<T,A> & v) + { + return Vc::all_of(v); + } + + template<typename T, std::size_t N, typename V, std::size_t M> + bool all_true(const Vc::SimdMaskArray<T,N,V,M> & v) + { + return Vc::all_of(v); + } + +} // end namespace Dune +#endif // HAVE_VC + +#endif // DUNE_COMMON_SIMD_HH diff --git a/dune/common/typetraits.hh b/dune/common/typetraits.hh index a2ff86c39f6e0db935f314468a7612a0da6ea3b9..63752ae4a9029197ac9d609d0a202dcc011afac0 100644 --- a/dune/common/typetraits.hh +++ b/dune/common/typetraits.hh @@ -395,6 +395,25 @@ namespace Dune #endif // defined(DOXYGEN) or HAVE_IS_INDEXABLE_SUPPORT + /** + typetrait to check that a class has begin() and end() members + */ + // default version, gets picked if SFINAE fails + template<typename T, typename = void, typename = void> + struct is_range + : public std::false_type + {}; + +#ifndef DOXYGEN + // version for types with begin() and end() + template<typename T> + struct is_range<T, + decltype(Std::declval<T>().begin()), + decltype(Std::declval<T>().end())> + : public std::true_type + {}; +#endif + namespace detail { ///