From 562973be86f0597ef313d4b07580c0ea18c24e96 Mon Sep 17 00:00:00 2001 From: Simon Praetorius <simon.praetorius@tu-dresden.de> Date: Sun, 17 Mar 2019 11:06:34 +0100 Subject: [PATCH] make some operations constexpr and add missing inline --- src/amdis/operations/Arithmetic.hpp | 36 ++++++------- src/amdis/operations/CMath.hpp | 2 +- test/CMakeLists.txt | 3 ++ test/OperationsTest.cpp | 82 +++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 19 deletions(-) create mode 100644 test/OperationsTest.cpp diff --git a/src/amdis/operations/Arithmetic.hpp b/src/amdis/operations/Arithmetic.hpp index 31d7c7a8..f3580e77 100644 --- a/src/amdis/operations/Arithmetic.hpp +++ b/src/amdis/operations/Arithmetic.hpp @@ -43,13 +43,13 @@ namespace AMDiS #endif template <class... Int> - int order(Plus, Int... orders) + constexpr int order(Plus, Int... orders) { return Math::max(int(orders)...); } template <std::size_t I> - auto partial(Plus, index_t<I>) + constexpr auto partial(Plus, index_t<I>) { static_assert((I < 2), "Derivatives of `Plus` only defined for the binary case."); return One{}; @@ -66,17 +66,17 @@ namespace AMDiS return lhs - rhs; } - friend int order(Minus, int lhs, int rhs) + friend constexpr int order(Minus, int lhs, int rhs) { return Math::max(lhs, rhs); } - friend auto partial(Minus, index_t<0>) + friend constexpr auto partial(Minus, index_t<0>) { return One{}; } - friend auto partial(Minus, index_t<1>) + friend constexpr auto partial(Minus, index_t<1>) { return StaticConstant<int,-1>{}; } @@ -134,15 +134,15 @@ namespace AMDiS template <class... Int> - int order(Multiplies, Int... orders) + constexpr int order(Multiplies, Int... orders) { - return Plus{}(int(orders)...); + return Math::sum(int(orders)...); } // only for binary * // d_0 (x * y) = y, d_1 (x * y) = x template <std::size_t I> - auto partial(Multiplies, index_t<I>) + constexpr auto partial(Multiplies, index_t<I>) { static_assert((I < 2), "Derivatives of `Multiplies` only defined for the binary case."); return Arg<1-I>{}; @@ -160,13 +160,13 @@ namespace AMDiS } // d_0 f(x,y) = 1 / y - friend auto partial(Divides, index_t<0>) + friend constexpr auto partial(Divides, index_t<0>) { return compose(Divides{}, One{}, Arg<1>{}); } // d_1 f(x,y) = (y - x)/y^2 - friend auto partial(Divides, index_t<1>); + friend constexpr auto partial(Divides, index_t<1>); }; // ------------------------------------------------------------------------- @@ -180,12 +180,12 @@ namespace AMDiS return -x; } - friend int order(Negate, int d) + friend constexpr int order(Negate, int d) { return d; } - friend auto partial(Negate, index_t<0>) + friend constexpr auto partial(Negate, index_t<0>) { return StaticConstant<int,-1>{}; } @@ -238,12 +238,12 @@ namespace AMDiS return Math::pow<p>(x); } - friend int order(PowImpl, int d) + friend constexpr int order(PowImpl, int d) { return p*d; } - friend auto partial(PowImpl, index_t<0>) + friend constexpr auto partial(PowImpl, index_t<0>) { return compose(Multiplies{}, StaticConstant<int,p>{}, Pow<p-1>{}); } @@ -278,7 +278,7 @@ namespace AMDiS #endif // d_1 f(x,y) = (y - x)/y^2 - auto partial(Divides, index_t<1>) + inline constexpr auto partial(Divides, index_t<1>) { return compose(Divides{}, compose(Minus{}, Arg<1>{}, Arg<0>{}), compose(Pow<2>{}, Arg<1>{})); @@ -287,7 +287,7 @@ namespace AMDiS /// Functor that represents x^p, \see \ref Pow struct Pow_ { - Pow_(int p) + constexpr Pow_(int p) : p_(p) {} @@ -297,12 +297,12 @@ namespace AMDiS return std::pow(x, p_); } - friend int order(Pow_ P, int d) + friend constexpr int order(Pow_ P, int d) { return P.p_ * d; } - friend auto partial(Pow_ P, index_t<0>) + friend constexpr auto partial(Pow_ P, index_t<0>) { return compose(Multiplies{}, Constant<int>{P.p_}, Pow_{P.p_-1}); } diff --git a/src/amdis/operations/CMath.hpp b/src/amdis/operations/CMath.hpp index c90d5416..e865582f 100644 --- a/src/amdis/operations/CMath.hpp +++ b/src/amdis/operations/CMath.hpp @@ -52,7 +52,7 @@ namespace AMDiS return (x > T{0} ? T{1} : T{-1}); } - constexpr friend auto partial(Signum, index_t<0>) + friend constexpr auto partial(Signum, index_t<0>) { return Zero{}; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ead7e40c..b08e5078 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -43,6 +43,9 @@ dune_add_test(SOURCES MultiTypeVectorTest.cpp dune_add_test(SOURCES MultiTypeMatrixTest.cpp LINK_LIBRARIES amdis) +dune_add_test(SOURCES OperationsTest.cpp + LINK_LIBRARIES amdis) + dune_add_test(SOURCES OperatorsTest.cpp LINK_LIBRARIES amdis) diff --git a/test/OperationsTest.cpp b/test/OperationsTest.cpp new file mode 100644 index 00000000..dfea8c33 --- /dev/null +++ b/test/OperationsTest.cpp @@ -0,0 +1,82 @@ +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: + +#include <iostream> + +#include <amdis/AMDiS.hpp> +#include <amdis/Operations.hpp> +#include "Tests.hpp" + +using namespace AMDiS; + +int main(int argc, char** argv) +{ + AMDiS::init(argc, argv); + + constexpr Operation::StaticConstant<int,0> op0a; + constexpr Operation::Zero op0b; + AMDIS_TEST_EQ(order(op0a,4,2,6,3,4), 0); + AMDIS_TEST_EQ(order(op0b,4,2,6,3,4), 0); + + constexpr int zero = op0a(1,2,3,4,5); + AMDIS_TEST_EQ(zero, 0); + + constexpr Operation::StaticConstant<int,1> op1a; + constexpr Operation::One op1b; + AMDIS_TEST_EQ(order(op1a,4,2,6,3,4), 0); + AMDIS_TEST_EQ(order(op1b,4,2,6,3,4), 0); + + constexpr int one = op1a(1,2,3,4,5); + AMDIS_TEST_EQ(one, 1); + + constexpr auto op1a_0 = partial(op1a, index_t<0>{}); + AMDIS_TEST((std::is_same<decltype(op1a_0), decltype(op0a)>::value)); + + constexpr Operation::Id op2; + AMDIS_TEST_EQ(op2(7), 7); + AMDIS_TEST_EQ(order(op2,7), 7); + + constexpr Operation::Constant<int> op3(42); + AMDIS_TEST_EQ(op3(1,2,3,4,5), 42); + AMDIS_TEST_EQ(order(op3,4,2,6,3,4), 0); + + constexpr Operation::Arg<0> op4a; + constexpr Operation::Arg<1> op4b; + AMDIS_TEST_EQ(op4a(1,2,3,4,5), 1); + AMDIS_TEST_EQ(op4b(1,2,3,4,5), 2); + AMDIS_TEST_EQ(order(op4a,4,2,6,3,4), 4); + AMDIS_TEST_EQ(order(op4b,4,2,6,3,4), 2); + + constexpr Operation::Plus op5; + constexpr auto erg5 = op5(7,8); + constexpr int order5 = order(op5,2,3); + AMDIS_TEST_EQ(erg5, 15); + AMDIS_TEST_EQ(order5, 3); + + constexpr Operation::Minus op6; + constexpr auto erg6 = op6(15,8); + constexpr int order6 = order(op6,2,3); + AMDIS_TEST_EQ(erg6, 7); + AMDIS_TEST_EQ(order6, 3); + + constexpr Operation::Multiplies op7; + constexpr auto erg7 = op7(2,4); + constexpr int order7 = order(op7,2,3); + AMDIS_TEST_EQ(erg7, 8); + AMDIS_TEST_EQ(order7, 5); + + constexpr auto op7_0 = partial(op7, index_t<0>{}); + constexpr auto op7_1 = partial(op7, index_t<1>{}); + constexpr auto erg7_0 = op7_0(2,4); + constexpr auto erg7_1 = op7_1(2,4); + AMDIS_TEST_EQ(erg7_0, 4); + AMDIS_TEST_EQ(erg7_1, 2); + + constexpr Operation::Divides op8; + constexpr auto erg8 = op8(16,8); + AMDIS_TEST_EQ(erg8, 2); + // constexpr int order8 = order(op8,2,3); // no order() for divides + + AMDiS::finalize(); + return report_errors(); +} -- GitLab