From 2593917370fa424ab1db76db1b870066bfee617c Mon Sep 17 00:00:00 2001
From: Rene Milk <rene.milk@wwu.de>
Date: Tue, 31 May 2016 11:47:09 +0200
Subject: [PATCH] [math] clamp now also works for known vector types

---
 dune/xt/common/math.hh      | 15 ++++++++++++++-
 dune/xt/common/test/math.cc | 24 ++++++++++++++++++------
 2 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/dune/xt/common/math.hh b/dune/xt/common/math.hh
index 326c7de24..8d6c87f12 100644
--- a/dune/xt/common/math.hh
+++ b/dune/xt/common/math.hh
@@ -35,6 +35,7 @@
 #include <dune/xt/common/reenable_warnings.hh>
 
 #include <dune/xt/common/type_traits.hh>
+#include <dune/xt/common/vector.hh>
 #include <dune/common/deprecated.hh>
 
 namespace Dune {
@@ -177,11 +178,23 @@ protected:
 
 //! \return var bounded in [min, max]
 template <typename T>
-T clamp(const T var, const T min, const T max)
+typename std::enable_if<!is_vector<T>::value, T>::type clamp(const T var, const T min, const T max)
 {
   return (var < min) ? min : (var > max) ? max : var;
 }
 
+template <typename T>
+typename std::enable_if<is_vector<T>::value, T>::type clamp(const T var, const T min, const T max)
+{
+  auto result     = var;
+  std::size_t idx = 0;
+  for (auto&& element : var) {
+    result[idx] = clamp(element, min[idx], max[idx]);
+    ++idx;
+  }
+  return result;
+}
+
 /**
  * \returns: -1 iff val < 0
  *            0 iff val == 0
diff --git a/dune/xt/common/test/math.cc b/dune/xt/common/test/math.cc
index 15faa261c..38ea35329 100644
--- a/dune/xt/common/test/math.cc
+++ b/dune/xt/common/test/math.cc
@@ -19,27 +19,39 @@
 #include <dune/xt/common/ranges.hh>
 
 using namespace Dune::XT::Common;
+typedef testing::Types<double, int, Dune::FieldVector<double, 3>, std::vector<double>> ClampTestTypes;
 typedef testing::Types<double, int> TestTypes;
 typedef testing::Types<std::complex<double>, double, int> ComplexTestTypes;
 
+template <typename T>
+static typename std::enable_if<is_vector<T>::value, T>::type init_bound(int val)
+{
+  const auto size = VectorAbstraction<T>::has_static_size ? VectorAbstraction<T>::static_size : 3u;
+  return VectorAbstraction<T>::create(size, val);
+}
+template <typename T>
+static typename std::enable_if<!is_vector<T>::value, T>::type init_bound(int val)
+{
+  return T(val);
+}
 template <class T>
 struct ClampTest : public testing::Test
 {
   const T lower;
   const T upper;
   ClampTest()
-    : lower(T(-1))
-    , upper(T(1))
+    : lower(init_bound<T>(-1))
+    , upper(init_bound<T>(1))
   {
   }
 };
 
-TYPED_TEST_CASE(ClampTest, TestTypes);
+TYPED_TEST_CASE(ClampTest, ClampTestTypes);
 TYPED_TEST(ClampTest, All)
 {
-  EXPECT_EQ(clamp(TypeParam(-2), this->lower, this->upper), this->lower);
-  EXPECT_EQ(clamp(TypeParam(2), this->lower, this->upper), this->upper);
-  EXPECT_EQ(clamp(TypeParam(0), this->lower, this->upper), TypeParam(0));
+  EXPECT_EQ(clamp(init_bound<TypeParam>(-2), this->lower, this->upper), this->lower);
+  EXPECT_EQ(clamp(init_bound<TypeParam>(2), this->lower, this->upper), this->upper);
+  EXPECT_EQ(clamp(init_bound<TypeParam>(0), this->lower, this->upper), init_bound<TypeParam>(0));
 }
 
 template <class T>
-- 
GitLab