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