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