openPMD-api
Datatype.hpp
1 /* Copyright 2017-2020 Fabian Koller and Franz Poeschel
2  *
3  * This file is part of openPMD-api.
4  *
5  * openPMD-api is free software: you can redistribute it and/or modify
6  * it under the terms of of either the GNU General Public License or
7  * the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * openPMD-api is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License and the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * and the GNU Lesser General Public License along with openPMD-api.
19  * If not, see <http://www.gnu.org/licenses/>.
20  */
21 #pragma once
22 
23 #include <array>
24 #include <cstdint>
25 #include <iosfwd>
26 #include <memory>
27 #include <type_traits>
28 #include <vector>
29 #include <tuple>
30 #include <climits>
31 #include <map>
32 #include <string>
33 
34 namespace openPMD
35 {
38 enum class Datatype : int
39 {
40  CHAR = 0, UCHAR, // SCHAR,
41  SHORT, INT, LONG, LONGLONG,
42  USHORT, UINT, ULONG, ULONGLONG,
43  FLOAT, DOUBLE, LONG_DOUBLE,
44  STRING,
45  VEC_CHAR,
46  VEC_SHORT,
47  VEC_INT,
48  VEC_LONG,
49  VEC_LONGLONG,
50  VEC_UCHAR,
51  VEC_USHORT,
52  VEC_UINT,
53  VEC_ULONG,
54  VEC_ULONGLONG,
55  VEC_FLOAT,
56  VEC_DOUBLE,
57  VEC_LONG_DOUBLE,
58  VEC_STRING,
59  ARR_DBL_7,
60 
61  BOOL,
62 
63  DATATYPE = 1000,
64 
65  UNDEFINED
66 }; // Datatype
67 
73 extern std::vector< Datatype > openPMD_Datatypes;
74 
84 template<
85  typename T,
86  typename U
87 >
88 struct decay_equiv :
89  std::is_same<
90  typename std::remove_pointer<
91  typename std::remove_cv<
92  typename std::decay<
93  typename std::remove_all_extents< T >::type
94  >::type
95  >::type
96  >::type,
97  typename std::remove_pointer<
98  typename std::remove_cv<
99  typename std::decay<
100  typename std::remove_all_extents< U >::type
101  >::type
102  >::type
103  >::type
104  >::type
105 { };
106 
107 #if __cplusplus >= 201402L
108 template<
109  typename T,
110  typename U
111 >
112 constexpr bool decay_equiv_v = decay_equiv< T, U >::value;
113 #endif
114 
115 template< typename T >
116 inline
117 #if __cplusplus >= 201402L
118 constexpr
119 #endif
120 Datatype
121 determineDatatype()
122 {
123  using DT = Datatype;
124  if( decay_equiv< T, char >::value ){ return DT::CHAR; }
125  else if( decay_equiv< T, unsigned char >::value ){ return DT::UCHAR; }
126  else if( decay_equiv< T, short >::value ){ return DT::SHORT; }
127  else if( decay_equiv< T, int >::value ){ return DT::INT; }
128  else if( decay_equiv< T, long >::value ){ return DT::LONG; }
129  else if( decay_equiv< T, long long >::value ){ return DT::LONGLONG; }
130  else if( decay_equiv< T, unsigned short >::value ){ return DT::USHORT; }
131  else if( decay_equiv< T, unsigned int >::value ){ return DT::UINT; }
132  else if( decay_equiv< T, unsigned long >::value ){ return DT::ULONG; }
133  else if( decay_equiv< T, unsigned long long >::value ){ return DT::ULONGLONG; }
134  else if( decay_equiv< T, float >::value ){ return DT::FLOAT; }
135  else if( decay_equiv< T, double >::value ){ return DT::DOUBLE; }
136  else if( decay_equiv< T, long double >::value ){ return DT::LONG_DOUBLE; }
137  else if( decay_equiv< T, std::string >::value ){ return DT::STRING; }
138  else if( decay_equiv< T, std::vector< char > >::value ){ return DT::VEC_CHAR; }
139  else if( decay_equiv< T, std::vector< short > >::value ){ return DT::VEC_SHORT; }
140  else if( decay_equiv< T, std::vector< int > >::value ){ return DT::VEC_INT; }
141  else if( decay_equiv< T, std::vector< long > >::value ){ return DT::VEC_LONG; }
142  else if( decay_equiv< T, std::vector< long long > >::value ){ return DT::VEC_LONGLONG; }
143  else if( decay_equiv< T, std::vector< unsigned char > >::value ){ return DT::VEC_UCHAR; }
144  else if( decay_equiv< T, std::vector< unsigned short > >::value ){ return DT::VEC_USHORT; }
145  else if( decay_equiv< T, std::vector< unsigned int > >::value ){ return DT::VEC_UINT; }
146  else if( decay_equiv< T, std::vector< unsigned long > >::value ){ return DT::VEC_ULONG; }
147  else if( decay_equiv< T, std::vector< unsigned long long > >::value ){ return DT::VEC_ULONGLONG; }
148  else if( decay_equiv< T, std::vector< float > >::value ){ return DT::VEC_FLOAT; }
149  else if( decay_equiv< T, std::vector< double > >::value ){ return DT::VEC_DOUBLE; }
150  else if( decay_equiv< T, std::vector< long double > >::value ){ return DT::VEC_LONG_DOUBLE; }
151  else if( decay_equiv< T, std::vector< std::string > >::value ){ return DT::VEC_STRING; }
152  else if( decay_equiv< T, std::array< double, 7 > >::value ){ return DT::ARR_DBL_7; }
153  else if( decay_equiv< T, bool >::value ){ return DT::BOOL; }
154  else return Datatype::UNDEFINED;
155 }
156 
157 template< typename T >
158 inline
159 #if __cplusplus >= 201402L
160 constexpr
161 #endif
162 Datatype
163 determineDatatype(std::shared_ptr< T >)
164 {
165  using DT = Datatype;
166  if( decay_equiv< T, char >::value ){ return DT::CHAR; }
167  else if( decay_equiv< T, unsigned char >::value ){ return DT::UCHAR; }
168  else if( decay_equiv< T, short >::value ){ return DT::SHORT; }
169  else if( decay_equiv< T, int >::value ){ return DT::INT; }
170  else if( decay_equiv< T, long >::value ){ return DT::LONG; }
171  else if( decay_equiv< T, long long >::value ){ return DT::LONGLONG; }
172  else if( decay_equiv< T, unsigned short >::value ){ return DT::USHORT; }
173  else if( decay_equiv< T, unsigned int >::value ){ return DT::UINT; }
174  else if( decay_equiv< T, unsigned long >::value ){ return DT::ULONG; }
175  else if( decay_equiv< T, unsigned long long >::value ){ return DT::ULONGLONG; }
176  else if( decay_equiv< T, float >::value ){ return DT::FLOAT; }
177  else if( decay_equiv< T, double >::value ){ return DT::DOUBLE; }
178  else if( decay_equiv< T, long double >::value ){ return DT::LONG_DOUBLE; }
179  else if( decay_equiv< T, std::string >::value ){ return DT::STRING; }
180  else if( decay_equiv< T, std::vector< char > >::value ){ return DT::VEC_CHAR; }
181  else if( decay_equiv< T, std::vector< short > >::value ){ return DT::VEC_SHORT; }
182  else if( decay_equiv< T, std::vector< int > >::value ){ return DT::VEC_INT; }
183  else if( decay_equiv< T, std::vector< long > >::value ){ return DT::VEC_LONG; }
184  else if( decay_equiv< T, std::vector< long long > >::value ){ return DT::VEC_LONGLONG; }
185  else if( decay_equiv< T, std::vector< unsigned char > >::value ){ return DT::VEC_UCHAR; }
186  else if( decay_equiv< T, std::vector< unsigned short > >::value ){ return DT::VEC_USHORT; }
187  else if( decay_equiv< T, std::vector< unsigned int > >::value ){ return DT::VEC_UINT; }
188  else if( decay_equiv< T, std::vector< unsigned long > >::value ){ return DT::VEC_ULONG; }
189  else if( decay_equiv< T, std::vector< unsigned long long > >::value ){ return DT::VEC_ULONGLONG; }
190  else if( decay_equiv< T, std::vector< float > >::value ){ return DT::VEC_FLOAT; }
191  else if( decay_equiv< T, std::vector< double > >::value ){ return DT::VEC_DOUBLE; }
192  else if( decay_equiv< T, std::vector< long double > >::value ){ return DT::VEC_LONG_DOUBLE; }
193  else if( decay_equiv< T, std::vector< std::string > >::value ){ return DT::VEC_STRING; }
194  else if( decay_equiv< T, std::array< double, 7 > >::value ){ return DT::ARR_DBL_7; }
195  else if( decay_equiv< T, bool >::value ){ return DT::BOOL; }
196  else return DT::UNDEFINED;
197 }
198 
204 inline size_t
206 {
207  using DT = Datatype;
208  switch( d )
209  {
210  case DT::CHAR:
211  case DT::VEC_CHAR:
212  case DT::STRING:
213  case DT::VEC_STRING:
214  return sizeof(char);
215  case DT::UCHAR:
216  case DT::VEC_UCHAR:
217  return sizeof(unsigned char);
218  // case DT::SCHAR:
219  // case DT::VEC_SCHAR:
220  // return sizeof(signed char);
221  // break;
222  case DT::SHORT:
223  case DT::VEC_SHORT:
224  return sizeof(short);
225  case DT::INT:
226  case DT::VEC_INT:
227  return sizeof(int);
228  case DT::LONG:
229  case DT::VEC_LONG:
230  return sizeof(long);
231  case DT::LONGLONG:
232  case DT::VEC_LONGLONG:
233  return sizeof(long long);
234  case DT::USHORT:
235  case DT::VEC_USHORT:
236  return sizeof(unsigned short);
237  case DT::UINT:
238  case DT::VEC_UINT:
239  return sizeof(unsigned int);
240  case DT::ULONG:
241  case DT::VEC_ULONG:
242  return sizeof(unsigned long);
243  case DT::ULONGLONG:
244  case DT::VEC_ULONGLONG:
245  return sizeof(unsigned long long);
246  case DT::FLOAT:
247  case DT::VEC_FLOAT:
248  return sizeof(float);
249  case DT::DOUBLE:
250  case DT::VEC_DOUBLE:
251  case DT::ARR_DBL_7:
252  return sizeof(double);
253  case DT::LONG_DOUBLE:
254  case DT::VEC_LONG_DOUBLE:
255  return sizeof(long double);
256  case DT::BOOL:
257  return sizeof(bool);
258  case DT::DATATYPE:
259  case DT::UNDEFINED:
260  default:
261  throw std::runtime_error("toBytes: Invalid datatype!");
262  }
263 }
264 
270 inline size_t
272 {
273  return toBytes( d ) * CHAR_BIT;
274 }
275 
281 inline bool
283 {
284  using DT = Datatype;
285 
286  switch( d )
287  {
288  case DT::VEC_CHAR:
289  case DT::VEC_SHORT:
290  case DT::VEC_INT:
291  case DT::VEC_LONG:
292  case DT::VEC_LONGLONG:
293  case DT::VEC_UCHAR:
294  case DT::VEC_USHORT:
295  case DT::VEC_UINT:
296  case DT::VEC_ULONG:
297  case DT::VEC_ULONGLONG:
298  case DT::VEC_FLOAT:
299  case DT::VEC_DOUBLE:
300  case DT::VEC_LONG_DOUBLE:
301  case DT::VEC_STRING:
302  return true;
303  default:
304  return false;
305  }
306 }
307 
315 inline bool
317 {
318  using DT = Datatype;
319 
320  switch( d )
321  {
322  case DT::FLOAT:
323  case DT::VEC_FLOAT:
324  case DT::DOUBLE:
325  case DT::VEC_DOUBLE:
326  case DT::LONG_DOUBLE:
327  case DT::VEC_LONG_DOUBLE:
328  return true;
329  default:
330  return false;
331  }
332 }
333 
341 template< typename T >
342 inline bool
344 {
345  Datatype dtype = determineDatatype< T >();
346 
347  return isFloatingPoint( dtype );
348 }
349 
358 inline std::tuple< bool, bool >
360 {
361  using DT = Datatype;
362 
363  switch( d )
364  {
365  case DT::SHORT:
366  case DT::VEC_SHORT:
367  case DT::INT:
368  case DT::VEC_INT:
369  case DT::LONG:
370  case DT::VEC_LONG:
371  case DT::LONGLONG:
372  case DT::VEC_LONGLONG:
373  return std::make_tuple( true, true );
374  case DT::USHORT:
375  case DT::VEC_USHORT:
376  case DT::UINT:
377  case DT::VEC_UINT:
378  case DT::ULONG:
379  case DT::VEC_ULONG:
380  case DT::ULONGLONG:
381  case DT::VEC_ULONGLONG:
382  return std::make_tuple( true, false );
383  default:
384  return std::make_tuple( false, false );
385  }
386 }
387 
396 template< typename T >
397 inline std::tuple< bool, bool >
399 {
400  Datatype dtype = determineDatatype< T >();
401 
402  return isInteger( dtype );
403 }
404 
411 template< typename T_FP >
412 inline bool
414 {
415  // template
416  bool tt_is_fp = isFloatingPoint< T_FP >();
417 
418  // Datatype
419  bool dt_is_fp = isFloatingPoint( d );
420 
421  if(
422  tt_is_fp &&
423  dt_is_fp &&
424  toBits( d ) == toBits( determineDatatype< T_FP >() )
425  )
426  return true;
427  else
428  return false;
429 }
430 
437 template< typename T_Int >
438 inline bool
440 {
441  // template
442  bool tt_is_int, tt_is_sig;
443  std::tie(tt_is_int, tt_is_sig) = isInteger< T_Int >();
444 
445  // Datatype
446  bool dt_is_int, dt_is_sig;
447  std::tie(dt_is_int, dt_is_sig) = isInteger( d );
448 
449  if(
450  tt_is_int &&
451  dt_is_int &&
452  tt_is_sig == dt_is_sig &&
453  toBits( d ) == toBits( determineDatatype< T_Int >() )
454  )
455  return true;
456  else
457  return false;
458 }
459 
466 inline bool
468 {
469  // exact same type
470  if( static_cast<int>(d) == static_cast<int>(e) )
471  return true;
472 
473  bool d_is_vec = isVector( d );
474  bool e_is_vec = isVector( e );
475 
476  // same int
477  bool d_is_int, d_is_sig;
478  std::tie(d_is_int, d_is_sig) = isInteger( d );
479  bool e_is_int, e_is_sig;
480  std::tie(e_is_int, e_is_sig) = isInteger( e );
481  if(
482  d_is_int &&
483  e_is_int &&
484  d_is_vec == e_is_vec &&
485  d_is_sig == e_is_sig &&
486  toBits( d ) == toBits( e )
487  )
488  return true;
489 
490  // same float
491  bool d_is_fp = isFloatingPoint( d );
492  bool e_is_fp = isFloatingPoint( e );
493 
494  if(
495  d_is_fp &&
496  e_is_fp &&
497  d_is_vec == e_is_vec &&
498  toBits( d ) == toBits( e )
499  )
500  return true;
501 
502  return false;
503 }
504 
505 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
506 #define OPENPMD_TEMPLATE_OPERATOR operator
507 #else
508 #define OPENPMD_TEMPLATE_OPERATOR template operator
509 #endif
510 
528 template < typename ReturnType = void, typename Action, typename... Args >
529 ReturnType switchType( Datatype dt, Action action, Args &&... args )
530 {
531  switch ( dt )
532  {
533  case Datatype::CHAR:
534  return action.OPENPMD_TEMPLATE_OPERATOR( )< char >(
535  std::forward< Args >( args )... );
536  case Datatype::UCHAR:
537  return action.OPENPMD_TEMPLATE_OPERATOR( )< unsigned char >(
538  std::forward< Args >( args )... );
539  case Datatype::SHORT:
540  return action.OPENPMD_TEMPLATE_OPERATOR( )< short >(
541  std::forward< Args >( args )... );
542  case Datatype::INT:
543  return action.OPENPMD_TEMPLATE_OPERATOR( )< int >(
544  std::forward< Args >( args )... );
545  case Datatype::LONG:
546  return action.OPENPMD_TEMPLATE_OPERATOR( )< long >(
547  std::forward< Args >( args )... );
548  case Datatype::LONGLONG:
549  return action.OPENPMD_TEMPLATE_OPERATOR( )< long long >(
550  std::forward< Args >( args )... );
551  case Datatype::USHORT:
552  return action.OPENPMD_TEMPLATE_OPERATOR( )< unsigned short >(
553  std::forward< Args >( args )... );
554  case Datatype::UINT:
555  return action.OPENPMD_TEMPLATE_OPERATOR( )< unsigned int >(
556  std::forward< Args >( args )... );
557  case Datatype::ULONG:
558  return action.OPENPMD_TEMPLATE_OPERATOR( )< unsigned long >(
559  std::forward< Args >( args )... );
560  case Datatype::ULONGLONG:
561  return action.OPENPMD_TEMPLATE_OPERATOR( )< unsigned long long >(
562  std::forward< Args >( args )... );
563  case Datatype::FLOAT:
564  return action.OPENPMD_TEMPLATE_OPERATOR( )< float >(
565  std::forward< Args >( args )... );
566  case Datatype::DOUBLE:
567  return action.OPENPMD_TEMPLATE_OPERATOR( )< double >(
568  std::forward< Args >( args )... );
569  case Datatype::LONG_DOUBLE:
570  return action.OPENPMD_TEMPLATE_OPERATOR( )< long double >(
571  std::forward< Args >( args )... );
572  case Datatype::STRING:
573  return action.OPENPMD_TEMPLATE_OPERATOR( )< std::string >(
574  std::forward< Args >( args )... );
575  case Datatype::VEC_CHAR:
576  return action.OPENPMD_TEMPLATE_OPERATOR( )< std::vector< char > >(
577  std::forward< Args >( args )... );
578  case Datatype::VEC_SHORT:
579  return action.OPENPMD_TEMPLATE_OPERATOR( )< std::vector< short > >(
580  std::forward< Args >( args )... );
581  case Datatype::VEC_INT:
582  return action.OPENPMD_TEMPLATE_OPERATOR( )< std::vector< int > >(
583  std::forward< Args >( args )... );
584  case Datatype::VEC_LONG:
585  return action.OPENPMD_TEMPLATE_OPERATOR( )< std::vector< long > >(
586  std::forward< Args >( args )... );
587  case Datatype::VEC_LONGLONG:
588  return action.OPENPMD_TEMPLATE_OPERATOR( )< std::vector< long long > >(
589  std::forward< Args >( args )... );
590  case Datatype::VEC_UCHAR:
591  return action
592  .OPENPMD_TEMPLATE_OPERATOR( )< std::vector< unsigned char > >(
593  std::forward< Args >( args )... );
594  case Datatype::VEC_USHORT:
595  return action
596  .OPENPMD_TEMPLATE_OPERATOR( )< std::vector< unsigned short > >(
597  std::forward< Args >( args )... );
598  case Datatype::VEC_UINT:
599  return action
600  .OPENPMD_TEMPLATE_OPERATOR( )< std::vector< unsigned int > >(
601  std::forward< Args >( args )... );
602  case Datatype::VEC_ULONG:
603  return action
604  .OPENPMD_TEMPLATE_OPERATOR( )< std::vector< unsigned long > >(
605  std::forward< Args >( args )... );
606  case Datatype::VEC_ULONGLONG:
607  return action
608  .OPENPMD_TEMPLATE_OPERATOR( )< std::vector< unsigned long long > >(
609  std::forward< Args >( args )... );
610  case Datatype::VEC_FLOAT:
611  return action.OPENPMD_TEMPLATE_OPERATOR( )< std::vector< float > >(
612  std::forward< Args >( args )... );
613  case Datatype::VEC_DOUBLE:
614  return action.OPENPMD_TEMPLATE_OPERATOR( )< std::vector< double > >(
615  std::forward< Args >( args )... );
616  case Datatype::VEC_LONG_DOUBLE:
617  return action
618  .OPENPMD_TEMPLATE_OPERATOR( )< std::vector< long double > >(
619  std::forward< Args >( args )... );
620  case Datatype::VEC_STRING:
621  return action
622  .OPENPMD_TEMPLATE_OPERATOR( )< std::vector< std::string > >(
623  std::forward< Args >( args )... );
624  case Datatype::ARR_DBL_7:
625  return action.OPENPMD_TEMPLATE_OPERATOR( )< std::array< double, 7 > >(
626  std::forward< Args >( args )... );
627  case Datatype::BOOL:
628  return action.OPENPMD_TEMPLATE_OPERATOR( )< bool >(
629  std::forward< Args >( args )... );
630  case Datatype::DATATYPE:
631  return action.OPENPMD_TEMPLATE_OPERATOR( )< 1000 >(
632  std::forward< Args >( args )... );
633  case Datatype::UNDEFINED:
634  return action.OPENPMD_TEMPLATE_OPERATOR( )< 0 >(
635  std::forward< Args >( args )... );
636  default:
637  throw std::runtime_error(
638  "Internal error: Encountered unknown datatype (switchType) ->" +
639  std::to_string( static_cast< int >( dt ) ) );
640  }
641 }
642 
643 #undef OPENPMD_TEMPLATE_OPERATOR
644 
645 namespace detail {
646  template<typename T>
648  Datatype m_dt = determineDatatype<T>();
649  };
650 
651  template<typename T>
652  struct BasicDatatypeHelper<std::vector<T>> {
653  Datatype m_dt = BasicDatatypeHelper<T>{}.m_dt;
654  };
655 
656  template<typename T, long n>
657  struct BasicDatatypeHelper<std::array<T, n>> {
658  Datatype m_dt = BasicDatatypeHelper<T>{}.m_dt;
659  };
660 
661  struct BasicDatatype {
662  template <typename T>
663  Datatype operator()();
664 
665  template <int n>
666  Datatype operator()();
667  };
668 }
669 
676 
677 Datatype toVectorType(Datatype dt);
678 
679 std::string datatypeToString( Datatype dt );
680 
681 Datatype stringToDatatype( std::string s );
682 
683 std::string datatypeToString( Datatype dt );
684 
685 Datatype stringToDatatype( std::string s );
686 
687 void
688 warnWrongDtype(std::string const& key,
689  Datatype store,
690  Datatype request);
691 
692 std::ostream&
693 operator<<(std::ostream&, openPMD::Datatype const&);
694 
695 } // namespace openPMD
696 
697 #if !defined(_MSC_VER)
698 
710 inline bool
711 operator==( openPMD::Datatype d, openPMD::Datatype e )
712 {
713  return openPMD::isSame(d, e);
714 }
715 
716 inline bool
717 operator!=( openPMD::Datatype d, openPMD::Datatype e )
718 {
719  return !(d == e);
720 }
723 #endif
bool isVector(Datatype d)
Compare if a Datatype is a vector type.
Definition: Datatype.hpp:282
std::vector< Datatype > openPMD_Datatypes
All openPMD datatypes defined in Datatype, listed in order in a vector.
Definition: Datatype.cpp:303
bool isSameFloatingPoint(Datatype d)
Compare if a Datatype is equivalent to a floating point type.
Definition: Datatype.hpp:413
bool isSameInteger(Datatype d)
Compare if a Datatype is equivalent to an integer type.
Definition: Datatype.hpp:439
STL namespace.
std::tuple< bool, bool > isInteger(Datatype d)
Compare if a Datatype is an integer type.
Definition: Datatype.hpp:359
Fundamental equivalence check for two given types T and U.
Definition: Datatype.hpp:88
Datatype
Concrete datatype of an object available at runtime.
Definition: Datatype.hpp:38
Definition: Container.cpp:51
size_t toBits(Datatype d)
Return number of bits representing a Datatype.
Definition: Datatype.hpp:271
Definition: Datatype.hpp:647
ReturnType switchType(Datatype dt, Action action, Args &&... args)
Generalizes switching over an openPMD datatype.
Definition: Datatype.hpp:529
Public definitions of openPMD-api.
Definition: Date.cpp:28
Datatype basicDatatype(Datatype dt)
basicDatatype Strip openPMD Datatype of std::vector, std::array et.
Definition: Datatype.cpp:339
size_t toBytes(Datatype d)
Return number of bytes representing a Datatype.
Definition: Datatype.hpp:205
Definition: Datatype.hpp:661
bool isFloatingPoint(Datatype d)
Compare if a Datatype is a floating point type.
Definition: Datatype.hpp:316
bool isSame(openPMD::Datatype const d, openPMD::Datatype const e)
Comparison for two Datatypes.
Definition: Datatype.hpp:467