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
   {
     ///