From 11a18eb6a37c578c8bbcc0f565d7ec9a2921a948 Mon Sep 17 00:00:00 2001
From: Simon Praetorius <simon.praetorius@tu-dresden.de>
Date: Wed, 8 May 2019 14:14:33 +0200
Subject: [PATCH] add test for switchCases

---
 src/amdis/common/SwitchCases.hpp | 96 ++++++++++++++++++++++++++++++++
 test/CMakeLists.txt              |  3 +
 test/SwitchCasesTest.cpp         | 40 +++++++++++++
 3 files changed, 139 insertions(+)
 create mode 100644 test/SwitchCasesTest.cpp

diff --git a/src/amdis/common/SwitchCases.hpp b/src/amdis/common/SwitchCases.hpp
index f17d31b8..55a6c11b 100644
--- a/src/amdis/common/SwitchCases.hpp
+++ b/src/amdis/common/SwitchCases.hpp
@@ -7,6 +7,7 @@
 
 namespace AMDiS
 {
+  // static switching. Iterates over all possible values
   template <class T, T to, T from, class Value, class Then, class Else>
   constexpr decltype(auto) switchCases(const Dune::StaticIntegralRange<T,to,from>& cases, const Value& value,
                                        Then&& thenBranch, Else&& elseBranch)
@@ -15,6 +16,7 @@ namespace AMDiS
     return Dune::Hybrid::switchCases(integer_sequence{}, value, FWD(thenBranch), FWD(elseBranch));
   }
 
+  // dynamic switching. Calls the `thenBranch` or `elseBranch` directly
   template <class T, class Value, class Then, class Else>
   constexpr decltype(auto) switchCases(const Dune::IntegralRange<T>& cases, const Value& value,
                                        Then&& thenBranch, Else&& elseBranch)
@@ -25,6 +27,55 @@ namespace AMDiS
       return elseBranch(value);
   }
 
+  // specialization for the case value in {0}
+  template <class Value, class Then, class Else>
+  constexpr decltype(auto) switchCases(const Dune::StaticIntegralRange<std::size_t,1,0>& cases, const Value& value,
+                                       Then&& thenBranch, Else&& elseBranch)
+  {
+    return std::size_t(value) == std::size_t(0) ? thenBranch(index_t<0>{}) : elseBranch();
+  }
+
+  // specialization for the case value in {0,1}
+  template <class Value, class Then, class Else>
+  constexpr decltype(auto) switchCases(const Dune::StaticIntegralRange<std::size_t,2,0>& cases, const Value& value,
+                                       Then&& thenBranch, Else&& elseBranch)
+  {
+    switch (std::size_t(value)) {
+      case 0u: return thenBranch(index_t<0>{});
+      case 1u: return thenBranch(index_t<1>{});
+      default: return elseBranch();
+    }
+  }
+
+  // specialization for the case value in {0,1,2}
+  template <class Value, class Then, class Else>
+  constexpr decltype(auto) switchCases(const Dune::StaticIntegralRange<std::size_t,3,0>& cases, const Value& value,
+                                       Then&& thenBranch, Else&& elseBranch)
+  {
+    switch (std::size_t(value)) {
+      case 0u: return thenBranch(index_t<0>{});
+      case 1u: return thenBranch(index_t<1>{});
+      case 2u: return thenBranch(index_t<2>{});
+      default: return elseBranch();
+    }
+  }
+
+  // specialization for the case value in {0,1,2,3}
+  template <class Value, class Then, class Else>
+  constexpr decltype(auto) switchCases(const Dune::StaticIntegralRange<std::size_t,4,0>& cases, const Value& value,
+                                       Then&& thenBranch, Else&& elseBranch)
+  {
+    switch (std::size_t(value)) {
+      case 0u: return thenBranch(index_t<0>{});
+      case 1u: return thenBranch(index_t<1>{});
+      case 2u: return thenBranch(index_t<2>{});
+      case 3u: return thenBranch(index_t<3>{});
+      default: return elseBranch();
+    }
+  }
+
+
+  // static switching. Iterates over all possible values
   template<class T, T to, T from, class Value, class Then>
   constexpr void switchCases(const Dune::StaticIntegralRange<T,to,from>& cases, const Value& value, Then&& thenBranch)
   {
@@ -32,6 +83,7 @@ namespace AMDiS
     Dune::Hybrid::switchCases(integer_sequence{}, value, FWD(thenBranch));
   }
 
+  // dynamic switching. Calls the `thenBranch` directly
   template<class T, class Value, class Then>
   constexpr void switchCases(const Dune::IntegralRange<T>& cases, const Value& value, Then&& thenBranch)
   {
@@ -39,4 +91,48 @@ namespace AMDiS
     thenBranch(value);
   }
 
+  // specialization for the case value in {0}
+  template <class Value, class Then, class Else>
+  constexpr decltype(auto) switchCases(const Dune::StaticIntegralRange<std::size_t,1,0>& cases, const Value& value, Then&& thenBranch)
+  {
+    assert(std::size_t(value) < 1u);
+    return thenBranch(index_t<0>{});
+  }
+
+  // specialization for the case value in {0,1}
+  template <class Value, class Then, class Else>
+  constexpr decltype(auto) switchCases(const Dune::StaticIntegralRange<std::size_t,2,0>& cases, const Value& value, Then&& thenBranch)
+  {
+    assert(std::size_t(value) < 2u);
+    switch (std::size_t(value)) {
+      case 0u: return thenBranch(index_t<0>{});
+      default: return thenBranch(index_t<1>{});
+    }
+  }
+
+  // specialization for the case value in {0,1,2}
+  template <class Value, class Then, class Else>
+  constexpr decltype(auto) switchCases(const Dune::StaticIntegralRange<std::size_t,3,0>& cases, const Value& value, Then&& thenBranch)
+  {
+    assert(std::size_t(value) < 3u);
+    switch (std::size_t(value)) {
+      case 0u: return thenBranch(index_t<0>{});
+      case 1u: return thenBranch(index_t<1>{});
+      default: return thenBranch(index_t<2>{});
+    }
+  }
+
+  // specialization for the case value in {0,1,2,3}
+  template <class Value, class Then, class Else>
+  constexpr decltype(auto) switchCases(const Dune::StaticIntegralRange<std::size_t,4,0>& cases, const Value& value, Then&& thenBranch)
+  {
+    assert(std::size_t(value) < 3u);
+    switch (std::size_t(value)) {
+      case 0u: return thenBranch(index_t<0>{});
+      case 1u: return thenBranch(index_t<1>{});
+      case 2u: return thenBranch(index_t<2>{});
+      default: return thenBranch(index_t<3>{});
+    }
+  }
+
 } // end namespace AMDiS
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 82bc31b7..4841332f 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -64,6 +64,9 @@ dune_add_test(SOURCES RangeTypeTest.cpp
 dune_add_test(SOURCES ResizeTest.cpp
   LINK_LIBRARIES amdis)
 
+dune_add_test(SOURCES SwitchCasesTest.cpp
+  LINK_LIBRARIES amdis)
+
 dune_add_test(SOURCES StringTest.cpp
   LINK_LIBRARIES amdis)
 
diff --git a/test/SwitchCasesTest.cpp b/test/SwitchCasesTest.cpp
new file mode 100644
index 00000000..92394fbb
--- /dev/null
+++ b/test/SwitchCasesTest.cpp
@@ -0,0 +1,40 @@
+#include <amdis/AMDiS.hpp>
+#include <amdis/common/SwitchCases.hpp>
+
+using namespace AMDiS;
+
+template <std::size_t i>
+struct Foo
+{
+  void foo() {}
+};
+
+struct Bar
+{
+  void bar(std::size_t i) {}
+};
+
+template <std::size_t max_i>
+void call_foo(std::size_t i)
+{
+  switchCases(Dune::range(index_t<max_i>{}), i, [](auto _i) { Foo<_i.value>{}.foo(); });
+}
+
+void call_bar(std::size_t i, std::size_t max_i)
+{
+  switchCases(Dune::range(max_i), i, [](auto _i) { Bar{}.bar(_i); });
+}
+
+int main(int argc, char** argv)
+{
+  call_foo<1>(0);
+  call_foo<2>(1);
+  call_foo<3>(2);
+  call_foo<10>(7);
+
+  call_bar(0, 1);
+  call_bar(1, 2);
+  call_bar(2, 3);
+  call_bar(7, 10);
+  return 0;
+}
-- 
GitLab