From f152063f510160ce98f96d94cce87665a02c9224 Mon Sep 17 00:00:00 2001 From: bramas <berenger.bramas@inria.fr> Date: Wed, 9 Jul 2014 17:08:04 +0200 Subject: [PATCH] Create new functions to work with template very easily --- Src/Utils/FTemplate.hpp | 132 ++++++++++++++++++++++++++++ Tests/Utils/testTemplateExample.cpp | 65 ++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 Src/Utils/FTemplate.hpp create mode 100644 Tests/Utils/testTemplateExample.cpp diff --git a/Src/Utils/FTemplate.hpp b/Src/Utils/FTemplate.hpp new file mode 100644 index 000000000..3f9842f87 --- /dev/null +++ b/Src/Utils/FTemplate.hpp @@ -0,0 +1,132 @@ +// =================================================================================== +// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner +// olivier.coulaud@inria.fr, berenger.bramas@inria.fr +// This software is a computer program whose purpose is to compute the FMM. +// +// This software is governed by the CeCILL-C and LGPL licenses and +// abiding by the rules of distribution of free software. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public and CeCILL-C Licenses for more details. +// "http://www.cecill.info". +// "http://www.gnu.org/licenses". +// =================================================================================== +#ifndef FTEMPLATE_HPP +#define FTEMPLATE_HPP + +/////////////////////////////////////////////////////////////////////////////////////// +/// This file provide useful method to work with template. +/// It provide solution in order to build several methods +/// and run them accordingly to a given condition. +/// We recommand to look at the testTemplateExample.cpp in order +/// to see the usage. +/////////////////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////////////// +/// FForAll : Compile all and exec all +/////////////////////////////////////////////////////////////////////////////////////// + +#include <functional> + +namespace FForAll{ + +template <class IterType, const IterType CurrentIter, const IterType iterTo, const IterType IterStep, + class Func, bool IsNotOver, typename... Args> +struct Evaluator{ + static void Run(Args... args){ + Func::template For<CurrentIter>(args...); + Evaluator<IterType, CurrentIter+IterStep, iterTo, IterStep, Func, (CurrentIter+IterStep < iterTo), Args...>::Run(args...); + } +}; + +template <class IterType, const IterType CurrentIter, const IterType iterTo, const IterType IterStep, + class Func, typename... Args> +struct Evaluator< IterType, CurrentIter, iterTo, IterStep, Func, false, Args...>{ + static void Run(Args... args){ + } +}; + +template <class IterType, const IterType IterFrom, const IterType iterTo, const IterType IterStep, + class Func, typename... Args> +void For(Args... args){ + Evaluator<IterType, IterFrom, iterTo, IterStep, Func, (IterFrom<iterTo), Args...>::Run(args...); +} + +} + + +/////////////////////////////////////////////////////////////////////////////////////// +/// FRunIf : Compile all and exec only one (if the template variable is equal to +/// the first variable) +/////////////////////////////////////////////////////////////////////////////////////// + +#include <iostream> + +namespace FRunIf{ + +template <class IterType, const IterType CurrentIter, const IterType iterTo, const IterType IterStep, + class Func, bool IsNotOver, typename... Args> +struct Evaluator{ + static void Run(IterType value, Args... args){ + if(CurrentIter == value){ + Func::template Run<CurrentIter>(args...); + } + else{ + Evaluator<IterType, CurrentIter+IterStep, iterTo, IterStep, Func, (CurrentIter+IterStep < iterTo), Args...>::Run(value, args...); + } + } +}; + +template <class IterType, const IterType CurrentIter, const IterType iterTo, const IterType IterStep, + class Func, typename... Args> +struct Evaluator< IterType, CurrentIter, iterTo, IterStep, Func, false, Args...>{ + static void Run(IterType value, Args... args){ + std::cout << __FUNCTION__ << " no matching value found\n"; + } +}; + +template <class IterType, const IterType IterFrom, const IterType iterTo, const IterType IterStep, + class Func, typename... Args> +void Run(IterType value, Args... args){ + Evaluator<IterType, IterFrom, iterTo, IterStep, Func, (IterFrom<iterTo), Args...>::Run(value, args...); +} + +} + + +/////////////////////////////////////////////////////////////////////////////////////// +/// FRunIfFunctional : Compile all and exec only those whose respect a condition +/////////////////////////////////////////////////////////////////////////////////////// + +namespace FRunIfFunctional{ + +template <class IterType, const IterType CurrentIter, const IterType iterTo, const IterType IterStep, + class Func, bool IsNotOver, typename... Args> +struct Evaluator{ + static void Run(std::function<bool(IterType)> test, Args... args){ + if(test(CurrentIter)){ + Func::template Run<CurrentIter>(args...); + } + Evaluator<IterType, CurrentIter+IterStep, iterTo, IterStep, Func, (CurrentIter+IterStep < iterTo), Args...>::Run(test, args...); + } +}; + +template <class IterType, const IterType CurrentIter, const IterType iterTo, const IterType IterStep, + class Func, typename... Args> +struct Evaluator< IterType, CurrentIter, iterTo, IterStep, Func, false, Args...>{ + static void Run(std::function<bool(IterType)> test, Args... args){ + } +}; + +template <class IterType, const IterType IterFrom, const IterType iterTo, const IterType IterStep, + class Func, typename... Args> +void Run(std::function<bool(IterType)> test, Args... args){ + Evaluator<IterType, IterFrom, iterTo, IterStep, Func, (IterFrom<iterTo), Args...>::Run(test, args...); +} + +} + +#endif // FTEMPLATE_HPP diff --git a/Tests/Utils/testTemplateExample.cpp b/Tests/Utils/testTemplateExample.cpp new file mode 100644 index 000000000..bd838b26c --- /dev/null +++ b/Tests/Utils/testTemplateExample.cpp @@ -0,0 +1,65 @@ +// =================================================================================== +// Copyright ScalFmm 2011 INRIA, Olivier Coulaud, Bérenger Bramas, Matthias Messner +// olivier.coulaud@inria.fr, berenger.bramas@inria.fr +// This software is a computer program whose purpose is to compute the FMM. +// +// This software is governed by the CeCILL-C and LGPL licenses and +// abiding by the rules of distribution of free software. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public and CeCILL-C Licenses for more details. +// "http://www.cecill.info". +// "http://www.gnu.org/licenses". +// =================================================================================== + + +/** This file gives an example of the template helper usage. + * + **/ + +#include "../../Src/Utils/FTemplate.hpp" + +#include <iostream> + +struct RunContainer{ + template <const int P> + static void For(double mydouble, int myint){ + std::cout << "For >> P = " << P << " mydouble " << mydouble << " myint " << myint << "\n"; + } + + template <const int P> + static void Run(double mydouble, int myint){ + std::cout << "Run >> P = " << P << " mydouble " << mydouble << " myint " << myint << "\n"; + } + + template <const int P> + static void Run(){ + std::cout << "Run without param >> P = " << P << "\n"; + } +}; + + +// Compile with g++ -std=c++11 main.cpp -o test.exe +int main(){ + // This will call the For method (maybe several times) + FForAll::For<int, 0, 20, 1, RunContainer>(45.4, 55); + + // This will call the Run method + FRunIf::Run<int, 0, 20, 1, RunContainer>(3, 45.4, 55); + + // Should not run, because 21 is out of the compiled interval + FRunIf::Run<int, 0, 20, 1, RunContainer>(21, 45.4, 55); + + // Call the Run method with no param + FRunIf::Run<int, 0, 20, 1, RunContainer>(18); + + // Call the Run method with no param for odd P + FRunIfFunctional::Run<int, 0, 20, 1, RunContainer>([&](int p){ return p&1;}); + + // Call the Run method with params for even P + FRunIfFunctional::Run<int, 0, 20, 1, RunContainer>([&](int p){ return !(p&1);}, 45.4, 55); + + return 0; +} -- GitLab