From 5b84b71647aa3576c7a79fbb8b6572ee12426bd7 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Mon, 15 Oct 2018 18:23:25 +0200
Subject: [PATCH] Implement a cast mechanism that minimize number of word
 subdivision

If T is a given type. It is decomposed into small pieces of integer words to
define messages.

For instance, if T size is Byte then it will be decomposed into one int8 (no
decomposition just a reinterpret_cast). If T is 2Bytes -> int16, and so on.

It sizeof(T) is not exactly 1,2,4 or 8, then the cast (sub)type will be the one
whose size is the greatest (exact) divisor of the size of T. The
CastArray<InitialType, CastType> will ensure data size consistency when
transferring arrays.
---
 src/utils/Messenger.hpp | 70 +++++++++++++++++++----------------------
 1 file changed, 32 insertions(+), 38 deletions(-)

diff --git a/src/utils/Messenger.hpp b/src/utils/Messenger.hpp
index bb8b58d52..f1c74ffb8 100644
--- a/src/utils/Messenger.hpp
+++ b/src/utils/Messenger.hpp
@@ -37,47 +37,47 @@ class Messenger
         return MPI_Datatype();
       }
     }
-#endif PASTIS_HAS_MPI
+#endif // PASTIS_HAS_MPI
 
-    struct CompositeType {}; // composite type
 
-    template <typename data_type,
-              int size = sizeof(data_type)>
-    struct data_cast
-    {
-      using type = CompositeType;
-    };
+   private:
+    template <typename T,
+              typename Allowed = void>
+    struct split_cast {};
 
-    template <typename data_type>
-    struct data_cast<data_type,1>
-    {
-      using type = int8_t;
-      static_assert(sizeof(data_type) == sizeof(type));
+    template <typename T>
+    struct split_cast<T,std::enable_if_t<not(sizeof(T) % sizeof(int64_t))>> {
+      using type = int64_t;
+      static_assert(not(sizeof(T) % sizeof(int64_t)));
     };
 
-    template <typename data_type>
-    struct data_cast<data_type,2>
-    {
-      using type = int16_t;
-      static_assert(sizeof(data_type) == sizeof(type));
+    template <typename T>
+    struct split_cast<T,std::enable_if_t<not(sizeof(T) % sizeof(int32_t))
+                                         and(sizeof(T) % sizeof(int64_t))>> {
+      using type = int32_t;
+      static_assert(not(sizeof(T) % sizeof(int32_t)));
     };
 
-    template <typename data_type>
-    struct data_cast<data_type,4>
-    {
-      using type = int32_t;
-      static_assert(sizeof(data_type) == sizeof(type));
+    template <typename T>
+    struct split_cast<T,std::enable_if_t<not(sizeof(T) % sizeof(int16_t))
+                                         and(sizeof(T) % sizeof(int32_t))
+                                         and(sizeof(T) % sizeof(int64_t))>> {
+      using type = int16_t;
+      static_assert(not(sizeof(T) % sizeof(int16_t)));
     };
 
-    template <typename data_type>
-    struct data_cast<data_type,8>
-    {
-      using type = int64_t;
-      static_assert(sizeof(data_type) == sizeof(type));
+    template <typename T>
+    struct split_cast<T,std::enable_if_t<not(sizeof(T) % sizeof(int8_t))
+                                         and(sizeof(T) % sizeof(int16_t))
+                                         and(sizeof(T) % sizeof(int32_t))
+                                         and(sizeof(T) % sizeof(int64_t))>> {
+      using type = int8_t;
+      static_assert(not(sizeof(T) % sizeof(int8_t)));
     };
 
-    template <typename data_type>
-    using data_cast_t = typename data_cast<data_type>::type;
+   public:
+    template <typename T>
+    using split_cast_t = typename split_cast<T>::type;
   };
 
   static Messenger* m_instance;
@@ -246,14 +246,8 @@ class Messenger
     if constexpr(std::is_arithmetic_v<DataType>) {
       _exchange(sent_array_list, recv_array_list);
     } else if constexpr(std::is_trivial_v<DataType>) {
-      using CastType = Helper::data_cast_t<DataType>;
-
-      if constexpr(std::is_same_v<CastType, Helper::CompositeType>) {
-        static_assert(not std::is_same_v<CastType, Helper::CompositeType>,
-                      "treatment of composite type is not yet implemented!");
-      } else {
-        this->_exchange_through_cast<SendDataType, CastType>(sent_array_list, recv_array_list);
-      }
+      using CastType = Helper::split_cast_t<DataType>;
+      _exchange_through_cast<SendDataType, CastType>(sent_array_list, recv_array_list);
     } else {
       static_assert(std::is_trivial_v<RecvDataType>,
                     "unexpected non trivial type of data");
-- 
GitLab