1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
     100
     101
     102
     103
     104
     105
     106
     107
     108
     109
     110
     111
     112
     113
     114
     115
     116
     117
     118
     119
#ifndef HPC_MPI_FUNDAMENTAL_H
#define HPC_MPI_FUNDAMENTAL_H 1

#include <mpi.h>
#include <complex>

namespace hpc { namespace mpi {

template<typename T> struct fundamental_type {
   static constexpr bool defined = false;
};

template<>
struct fundamental_type<char> {
   static constexpr bool defined = true;
   MPI_Datatype get() const { return MPI_CHAR; }
};
template<>
struct fundamental_type<signed char> {
   static constexpr bool defined = true;
   MPI_Datatype get() const { return MPI_SIGNED_CHAR; }
};
template<>
struct fundamental_type<unsigned char> {
   static constexpr bool defined = true;
   MPI_Datatype get() const { return MPI_UNSIGNED_CHAR; }
};
template<>
struct fundamental_type<short> {
   static constexpr bool defined = true;
   MPI_Datatype get() const { return MPI_SHORT; }
};
template<>
struct fundamental_type<unsigned short> {
   static constexpr bool defined = true;
   MPI_Datatype get() const { return MPI_UNSIGNED_SHORT; }
};
template<>
struct fundamental_type<int> {
   static constexpr bool defined = true;
   MPI_Datatype get() const { return MPI_INT; }
};
template<>
struct fundamental_type<unsigned> {
   static constexpr bool defined = true;
   MPI_Datatype get() const { return MPI_UNSIGNED; }
};
template<>
struct fundamental_type<long> {
   static constexpr bool defined = true;
   MPI_Datatype get() const { return MPI_LONG; }
};
template<>
struct fundamental_type<unsigned long> {
   static constexpr bool defined = true;
   MPI_Datatype get() const { return MPI_UNSIGNED_LONG; }
};
template<>
struct fundamental_type<long long> {
   static constexpr bool defined = true;
   MPI_Datatype get() const { return MPI_LONG_LONG; }
};
template<>
struct fundamental_type<unsigned long long> {
   static constexpr bool defined = true;
   MPI_Datatype get() const { return MPI_UNSIGNED_LONG_LONG; }
};
template<>
struct fundamental_type<float> {
   static constexpr bool defined = true;
   MPI_Datatype get() const { return MPI_FLOAT; }
};
template<>
struct fundamental_type<double> {
   static constexpr bool defined = true;
   MPI_Datatype get() const { return MPI_DOUBLE; }
};
template<>
struct fundamental_type<long double> {
   static constexpr bool defined = true;
   MPI_Datatype get() const { return MPI_LONG_DOUBLE; }
};

/* the following types are not supported by older
   MPI implementations; hence we make it dependent
   on the corresponding preprocessor symbols */
#ifdef MPI_CXX_FLOAT_COMPLEX
template<>
struct fundamental_type<std::complex<float>> {
   static constexpr bool defined = true;
   MPI_Datatype get() const { return MPI_CXX_FLOAT_COMPLEX; }
};
#endif
#ifdef MPI_CXX_DOUBLE_COMPLEX
template<>
struct fundamental_type<std::complex<double>> {
   static constexpr bool defined = true;
   MPI_Datatype get() const { return MPI_CXX_DOUBLE_COMPLEX; }
};
#endif
#ifdef MPI_CXX_LONG_DOUBLE_COMPLEX
template<>
struct fundamental_type<std::complex<long double>> {
   static constexpr bool defined = true;
   MPI_Datatype get() const { return MPI_CXX_LONG_DOUBLE_COMPLEX; }
};
#endif

template<typename T>
typename std::enable_if<
   fundamental_type<T>::defined,
   MPI_Datatype>::type
get_type(const T& value) {
   return fundamental_type<T>().get();
}

} } // namespaces mpi, hpc

#endif