LibraryLink Utilities  3.0.1
Modern C++ wrapper over LibraryLink and WSTP
Utilities.hpp
Go to the documentation of this file.
1 
9 #ifndef LLU_UTILITIES_HPP
10 #define LLU_UTILITIES_HPP
11 
12 #include <complex>
13 #include <cstdint>
14 #include <type_traits>
15 #include <utility>
16 #include <variant>
17 
18 #include "LLU/LibraryData.h"
19 
20 namespace LLU {
21 
26  template<typename T>
27  using remove_cv_ref = std::remove_cv_t<std::remove_reference_t<T>>;
28 
34  template<typename A, typename B>
35  using disable_if_same_or_derived = typename std::enable_if_t<!std::is_same<A, B>::value && !std::is_base_of<A, remove_cv_ref<B>>::value>;
36 
42  template<typename A, typename B>
43  using enable_if_same_or_derived = typename std::enable_if_t<std::is_same<A, B>::value || std::is_base_of<A, remove_cv_ref<B>>::value>;
44 
49  template<typename Iterator>
51 
56  template<typename Container>
57  using enable_if_integral_elements = typename std::enable_if_t<std::is_integral<typename std::remove_reference_t<Container>::value_type>::value>;
58 
59  template<typename Container, typename = std::void_t<>>
60  struct has_value_type : std::false_type {};
61 
62  template<typename Container>
63  struct has_value_type<Container, std::void_t<typename Container::value_type>> : std::true_type {};
64 
65  template<typename Container, typename T>
66  struct has_matching_type : std::is_same<typename Container::value_type, T> {};
67 
68  template<typename Container, typename = std::void_t<>>
69  struct has_size : std::false_type {};
70 
71  template<typename Container>
72  struct has_size<Container, std::void_t<decltype(std::declval<Container>().size())>> : std::true_type {};
73 
75  template<typename Container>
76  inline constexpr bool has_size_v = has_size<Container>::value;
77 
78  template<typename Container, typename = std::void_t<>>
79  struct is_iterable : std::false_type {};
80 
81  template<typename Container>
82  struct is_iterable<Container, std::void_t<decltype(*std::begin(std::declval<Container>())), decltype(std::end(std::declval<Container>()))>>
83  : std::true_type {};
84 
86  template<typename Container, typename T>
88  std::conjunction<std::is_class<Container>, has_value_type<Container>, is_iterable<Container>, has_matching_type<Container, T>>::value;
89 
98  template<typename VariantType, typename T, std::size_t index = 0>
99  constexpr std::size_t variant_index() {
100  // NOLINTNEXTLINE(bugprone-branch-clone): for some reason this did not work when first two branches were combined into one
101  if constexpr (index >= std::variant_size_v<VariantType>) {
102  return index;
103  } else if (std::is_same_v<std::variant_alternative_t<index, VariantType>, T>) {
104  return index;
105  } else {
106  return variant_index<VariantType, T, index + 1>();
107  }
108  }
109 
114  template<typename... Ts>
115  void Unused(Ts&&... /* args */) {}
116 
121  template<typename T>
122  struct dependent_false : std::false_type {};
123 
128  template<typename T>
130 
132  template<numericarray_data_t>
133  struct [[maybe_unused]] NumericArrayFromEnum;
134 
136  template<>
137  struct NumericArrayFromEnum<MNumericArray_Type_Bit8> {
138  using type = std::int8_t;
139  static constexpr const char* typeName = "Integer8";
140  };
141  template<>
142  struct NumericArrayFromEnum<MNumericArray_Type_UBit8> {
143  using type = std::uint8_t;
144  static constexpr const char* typeName = "UnsignedInteger8";
145  };
146  template<>
147  struct NumericArrayFromEnum<MNumericArray_Type_Bit16> {
148  using type = std::int16_t;
149  static constexpr const char* typeName = "Integer16";
150  };
151  template<>
152  struct NumericArrayFromEnum<MNumericArray_Type_UBit16> {
153  using type = std::uint16_t;
154  static constexpr const char* typeName = "UnsignedInteger16";
155  };
156  template<>
157  struct NumericArrayFromEnum<MNumericArray_Type_Bit32> {
158  using type = std::int32_t;
159  static constexpr const char* typeName = "Integer32";
160  };
161  template<>
162  struct NumericArrayFromEnum<MNumericArray_Type_UBit32> {
163  using type = std::uint32_t;
164  static constexpr const char* typeName = "UnsignedInteger32";
165  };
166  template<>
167  struct NumericArrayFromEnum<MNumericArray_Type_Bit64> {
168  using type = std::int64_t;
169  static constexpr const char* typeName = "Integer64";
170  };
171  template<>
172  struct NumericArrayFromEnum<MNumericArray_Type_UBit64> {
173  using type = std::uint64_t;
174  static constexpr const char* typeName = "UnsignedInteger64";
175  };
176  template<>
177  struct NumericArrayFromEnum<MNumericArray_Type_Real32> {
178  using type = float;
179  static constexpr const char* typeName = "Real32";
180  };
181  template<>
182  struct NumericArrayFromEnum<MNumericArray_Type_Real64> {
183  using type = double;
184  static constexpr const char* typeName = "Real64";
185  };
186  template<>
187  struct NumericArrayFromEnum<MNumericArray_Type_Complex_Real32> {
188  using type = std::complex<float>;
189  static constexpr const char* typeName = "ComplexReal32";
190  };
191  template<>
192  struct NumericArrayFromEnum<MNumericArray_Type_Complex_Real64> {
193  using type = std::complex<double>;
194  static constexpr const char* typeName = "ComplexReal64";
195  };
197 
199  template<numericarray_data_t rat>
201 
203  namespace NA {
207  enum class ConversionMethod {
208  Check = MNumericArray_Convert_Check,
209  ClipCheck = MNumericArray_Convert_Clip_Check,
210  Coerce = MNumericArray_Convert_Coerce,
211  ClipCoerce = MNumericArray_Convert_Clip_Coerce,
212  Round = MNumericArray_Convert_Round,
213  ClipRound = MNumericArray_Convert_Clip_Round,
214  Scale = MNumericArray_Convert_Scale,
215  ClipScale = MNumericArray_Convert_Clip_Scale,
216  };
217 
223  inline std::string typeToString(numericarray_data_t t) {
224  switch (t) {
225  case MNumericArray_Type_Undef: return "Undefined";
226  case MNumericArray_Type_Bit8: return NumericArrayFromEnum<MNumericArray_Type_Bit8>::typeName;
227  case MNumericArray_Type_UBit8: return NumericArrayFromEnum<MNumericArray_Type_UBit8>::typeName;
228  case MNumericArray_Type_Bit16: return NumericArrayFromEnum<MNumericArray_Type_Bit16>::typeName;
229  case MNumericArray_Type_UBit16: return NumericArrayFromEnum<MNumericArray_Type_UBit16>::typeName;
230  case MNumericArray_Type_Bit32: return NumericArrayFromEnum<MNumericArray_Type_Bit32>::typeName;
231  case MNumericArray_Type_UBit32: return NumericArrayFromEnum<MNumericArray_Type_UBit32>::typeName;
232  case MNumericArray_Type_Bit64: return NumericArrayFromEnum<MNumericArray_Type_Bit64>::typeName;
233  case MNumericArray_Type_UBit64: return NumericArrayFromEnum<MNumericArray_Type_UBit64>::typeName;
234  case MNumericArray_Type_Real32: return NumericArrayFromEnum<MNumericArray_Type_Real32>::typeName;
235  case MNumericArray_Type_Real64: return NumericArrayFromEnum<MNumericArray_Type_Real64>::typeName;
236  case MNumericArray_Type_Complex_Real32: return NumericArrayFromEnum<MNumericArray_Type_Complex_Real32>::typeName;
237  case MNumericArray_Type_Complex_Real64: return NumericArrayFromEnum<MNumericArray_Type_Complex_Real64>::typeName;
238  default:
239  // In V12.2 MNumericArray_Type_Real16 and MNumericArray_Type_Complex_Real16 have been introduced but they are not supported in the Kernel.
240  // We add a default case to avoid compiler warnings.
241  return "Undefined";
242  }
243  return "Undefined";
244  }
245  } // namespace NA
246 
248  template<typename T>
249  inline constexpr imagedata_t ImageType = MImage_Type_Undef;
251  template<>
252  inline constexpr imagedata_t ImageType<int8_t> = MImage_Type_Bit;
253  template<>
254  inline constexpr imagedata_t ImageType<uint8_t> = MImage_Type_Bit8;
255  template<>
256  inline constexpr imagedata_t ImageType<uint16_t> = MImage_Type_Bit16;
257  template<>
258  inline constexpr imagedata_t ImageType<float> = MImage_Type_Real32;
259  template<>
260  inline constexpr imagedata_t ImageType<double> = MImage_Type_Real;
262 
264  template<typename T>
265  inline constexpr numericarray_data_t NumericArrayType = MNumericArray_Type_Undef;
267  template<>
268  inline constexpr numericarray_data_t NumericArrayType<int8_t> = MNumericArray_Type_Bit8;
269  template<>
270  inline constexpr numericarray_data_t NumericArrayType<uint8_t> = MNumericArray_Type_UBit8;
271  template<>
272  inline constexpr numericarray_data_t NumericArrayType<int16_t> = MNumericArray_Type_Bit16;
273  template<>
274  inline constexpr numericarray_data_t NumericArrayType<uint16_t> = MNumericArray_Type_UBit16;
275  template<>
276  inline constexpr numericarray_data_t NumericArrayType<int32_t> = MNumericArray_Type_Bit32;
277  template<>
278  inline constexpr numericarray_data_t NumericArrayType<uint32_t> = MNumericArray_Type_UBit32;
279  template<>
280  inline constexpr numericarray_data_t NumericArrayType<int64_t> = MNumericArray_Type_Bit64;
281  template<>
282  inline constexpr numericarray_data_t NumericArrayType<uint64_t> = MNumericArray_Type_UBit64;
283  template<>
284  inline constexpr numericarray_data_t NumericArrayType<float> = MNumericArray_Type_Real32;
285  template<>
286  inline constexpr numericarray_data_t NumericArrayType<double> = MNumericArray_Type_Real64;
287  template<>
288  inline constexpr numericarray_data_t NumericArrayType<std::complex<float>> = MNumericArray_Type_Complex_Real32;
289  template<>
290  inline constexpr numericarray_data_t NumericArrayType<std::complex<double>> = MNumericArray_Type_Complex_Real64;
292 
294  template<typename T>
295  inline constexpr mint TensorType = MType_Undef;
297  template<>
298  inline constexpr mint TensorType<mint> = MType_Integer;
299  template<>
300  inline constexpr mint TensorType<double> = MType_Real;
301  template<>
302  inline constexpr mint TensorType<std::complex<double>> = MType_Complex;
304 
305 } /* namespace LLU */
306 
307 #endif // LLU_UTILITIES_HPP
LLU::is_iterable_container_with_matching_type_v
constexpr bool is_iterable_container_with_matching_type_v
A type trait to check whether type Container is a class type with a member type alias value_type equa...
Definition: Utilities.hpp:87
LLU::variant_index
constexpr std::size_t variant_index()
Get index of given type in the variant.
Definition: Utilities.hpp:99
LLU::remove_cv_ref
std::remove_cv_t< std::remove_reference_t< T > > remove_cv_ref
Utility type that strips any given type from reference and cv qualifiers.
Definition: Utilities.hpp:27
LLU
Main namespace of LibraryLink Utilities.
Definition: Queue.h:13
LLU::TensorType
constexpr mint TensorType
Utility structure that matches a C++ type with a corresponding MTensor data type.
Definition: Utilities.hpp:295
LibraryData.h
LLU::NumericArrayTypeFromEnum
typename NumericArrayFromEnum< rat >::type NumericArrayTypeFromEnum
Simple type alias to easily extract type from NumericArrayFromEnum.
Definition: Utilities.hpp:200
LLU::NA::typeToString
std::string typeToString(numericarray_data_t t)
Get name of the given MNumericArray type, e.g.
Definition: Utilities.hpp:223
LLU::NA::ConversionMethod
ConversionMethod
Possible methods of handling out-of-range data when converting a NumericArray to different type.
Definition: Utilities.hpp:207
LLU::enable_if_input_iterator
enable_if_same_or_derived< std::input_iterator_tag, typename std::iterator_traits< Iterator >::iterator_category > enable_if_input_iterator
Utility type that checks if given type can be treated as input iterator.
Definition: Utilities.hpp:50
LLU::disable_if_same_or_derived
typename std::enable_if_t<!std::is_same< A, B >::value &&!std::is_base_of< A, remove_cv_ref< B > >::value > disable_if_same_or_derived
Utility type that is valid only if B is not A and not a subclass of A.
Definition: Utilities.hpp:35
LLU::dependent_false_v
constexpr bool dependent_false_v
Compile-time boolean constant false that "depends" on a template parameter.
Definition: Utilities.hpp:129
LLU::Unused
void Unused(Ts &&...)
Dummy function called on otherwise unused parameters to eliminate compiler warnings.
Definition: Utilities.hpp:115
LLU::ImageType
constexpr imagedata_t ImageType
Utility variable template that matches a C++ type with a corresponding MImage data type.
Definition: Utilities.hpp:249
LLU::NumericArrayFromEnum
Utility structure that matches an MNumericArray data type with corresponding C++ type.
Definition: Utilities.hpp:133
LLU::enable_if_same_or_derived
typename std::enable_if_t< std::is_same< A, B >::value||std::is_base_of< A, remove_cv_ref< B > >::value > enable_if_same_or_derived
Utility type that is valid only if B is A or a subclass of A.
Definition: Utilities.hpp:43
LLU::has_size_v
constexpr bool has_size_v
A type trait to check whether type Container has a member function size()
Definition: Utilities.hpp:76
LLU::enable_if_integral_elements
typename std::enable_if_t< std::is_integral< typename std::remove_reference_t< Container >::value_type >::value > enable_if_integral_elements
Utility type that checks if given container type has elements that are integers (and therefore can be...
Definition: Utilities.hpp:57
LLU::NumericArrayType
constexpr numericarray_data_t NumericArrayType
Utility structure that matches a C++ type with a corresponding MNumericArray data type.
Definition: Utilities.hpp:265
LLU::dependent_false
Get a type that inherits from false_type and ignores the template parameter completely.
Definition: Utilities.hpp:122