1 #ifndef teca_variant_array_h
2 #define teca_variant_array_h
11 #include <type_traits>
15 #include "teca_common.h"
16 #include "teca_binary_stream.h"
17 #include "teca_variant_array_fwd.h"
18 #include "teca_bad_cast.h"
23 std::integral_constant<bool,
24 std::is_arithmetic<T>::value>
30 std::integral_constant<bool,
31 !std::is_arithmetic<T>::value>
52 { this->copy(other);
return *
this; }
56 { this->swap(other);
return *
this; }
60 virtual p_teca_variant_array new_instance()
const = 0;
61 virtual p_teca_variant_array new_instance(
size_t n)
const = 0;
65 virtual p_teca_variant_array new_copy()
const = 0;
66 virtual p_teca_variant_array new_copy(
size_t start,
size_t end)
const = 0;
70 {
return this->equal(other); }
73 virtual std::string get_class_name()
const = 0;
76 virtual void initialize() = 0;
81 void get(
unsigned long i, T &val)
const
82 { this->get_dispatch<T>(i, val); }
85 void get(std::vector<T> &vals)
const
86 { this->get_dispatch<T>(vals); }
89 void get(
size_t start,
size_t end, T *vals)
const
90 { this->get_dispatch<T>(start, end, vals); }
95 void set(
const std::vector<T> &vals)
96 { this->set_dispatch<T>(vals); }
99 void set(
unsigned long i,
const T &val)
100 { this->set_dispatch<T>(i, val); }
103 void set(
size_t start,
size_t end,
const T *vals)
104 { this->set_dispatch<T>(start, end, vals); }
109 void append(
const T &val)
110 { this->append_dispatch(val); }
113 void append(
const std::vector<T> &vals)
114 { this->append_dispatch(vals); }
117 virtual unsigned long size()
const noexcept = 0;
120 virtual void resize(
unsigned long i) = 0;
124 virtual void reserve(
unsigned long i) = 0;
127 virtual void clear() noexcept = 0;
135 void copy(
const const_p_teca_variant_array &other)
136 { this->copy(*other.get()); }
139 void append(
const const_p_teca_variant_array &other)
140 { this->append(*other.get()); }
146 void swap(
const p_teca_variant_array &other)
147 { this->swap(*other.get()); }
151 bool equal(
const const_p_teca_variant_array &other)
const
152 {
return this->equal(*other.get()); }
158 virtual int to_stream(std::ostream &s)
const = 0;
159 virtual int from_stream(std::ostream &s) = 0;
162 virtual unsigned int type_code()
const noexcept = 0;
170 void append_dispatch(
const std::vector<T> &vals,
174 void append_dispatch(
const std::vector<T> &vals,
178 void append_dispatch(
const T &val,
182 void append_dispatch(
const T &val,
186 void set_dispatch(
const std::vector<T> &vals,
190 void set_dispatch(
const std::vector<T> &vals,
194 void set_dispatch(
unsigned long i,
const T &val,
198 void set_dispatch(
unsigned long i,
const T &val,
202 void set_dispatch(
size_t start,
size_t end,
const T *vals,
206 void set_dispatch(
size_t start,
size_t end,
const T *vals,
210 void get_dispatch(std::vector<T> &vals,
214 void get_dispatch(std::vector<T> &vals,
218 void get_dispatch(
unsigned long i, T &val,
222 void get_dispatch(
unsigned long i, T &val,
226 void get_dispatch(
size_t start,
size_t end, T *vals,
230 void get_dispatch(
size_t start,
size_t end, T *vals,
240 : std::integral_constant<bool,
241 std::is_arithmetic<T>::value ||
242 std::is_same<T, std::string>::value>
248 : std::integral_constant<bool,
249 (std::is_pointer<T>::value ||
250 std::is_same<T, p_teca_variant_array>::value) &&
251 !pack_array<T>::value>
257 : std::integral_constant<bool,
258 !pack_array<T>::value &&
259 !std::is_pointer<T>::value &&
260 !pack_object_ptr<T>::value>
278 p_teca_variant_array new_copy()
const override;
279 p_teca_variant_array new_copy(
size_t start,
size_t end)
const override;
280 p_teca_variant_array new_instance()
const override;
281 p_teca_variant_array new_instance(
size_t n)
const override;
284 std::string get_class_name()
const override;
287 void initialize()
override;
304 T &get(
unsigned long i)
305 {
return m_data[i]; }
307 const T &get(
unsigned long i)
const
308 {
return m_data[i]; }
312 void get(
unsigned long i, U &val)
const;
317 void get(
size_t start,
size_t end, U *vals)
const;
321 void get(std::vector<U> &val)
const;
324 T *get(){
return &m_data[0]; }
325 const T *get()
const {
return &m_data[0]; }
329 void set(
unsigned long i,
const U &val);
334 void set(
size_t start,
size_t end,
const U *vals);
339 void set(
const std::vector<U> &val);
343 void append(
const std::vector<U> &val);
347 void append(
const U &val);
350 virtual unsigned long size()
const noexcept
override;
353 virtual void resize(
unsigned long n)
override;
354 void resize(
unsigned long n,
const T &val);
357 virtual void reserve(
unsigned long n)
override;
360 virtual void clear() noexcept
override;
381 this->to_binary<T>(s);
387 this->from_binary<T>(s);
391 int to_stream(std::ostream &s)
const override
393 this->to_ascii<T>(s);
397 int from_stream(std::ostream &s)
override
399 this->from_ascii<T>(s);
432 template <
typename U = T>
437 template <
typename U = T>
442 template <
typename U = T>
447 template <
typename U = T>
452 template <
typename U = T>
457 template <
typename U = T>
462 template <
typename U = T>
463 void to_ascii(std::ostream &s,
467 template <
typename U = T>
468 void from_ascii(std::ostream &s,
472 template <
typename U = T>
473 void to_ascii(std::ostream &s,
477 template <
typename U = T>
478 void from_ascii(std::ostream &s,
482 template <
typename U = T>
483 void to_ascii(std::ostream &s,
487 template <
typename U = T>
488 void from_ascii(std::ostream &s,
492 unsigned int type_code()
const noexcept
override;
494 std::vector<T> m_data;
501 #pragma GCC diagnostic ignored "-Wunknown-pragmas"
502 #pragma GCC diagnostic ignored "-Wunused-local-typedefs"
509 #define TEMPLATE_DISPATCH_CASE(tt, nt, p, body) \
510 if (dynamic_cast<tt<nt>*>(p)) \
523 #define NESTED_TEMPLATE_DISPATCH_CASE(tt, nt, p, i, body) \
524 if (dynamic_cast<tt<nt>*>(p)) \
526 using TT##i = tt<nt>; \
534 #define TEMPLATE_DISPATCH_FP(t, p, body) \
535 TEMPLATE_DISPATCH_CASE(t, float, p, body) \
536 else TEMPLATE_DISPATCH_CASE(t, double, p, body)
541 #define TEMPLATE_DISPATCH_SI(t, p, body) \
542 TEMPLATE_DISPATCH_CASE(t, long long, p, body) \
543 else TEMPLATE_DISPATCH_CASE(t, long, p, body) \
544 else TEMPLATE_DISPATCH_CASE(t, int, p, body) \
545 else TEMPLATE_DISPATCH_CASE(t, short int, p, body) \
546 else TEMPLATE_DISPATCH_CASE(t, char, p, body)
551 #define TEMPLATE_DISPATCH_FP_SI(t, p, body) \
552 TEMPLATE_DISPATCH_CASE(t, float, p, body) \
553 else TEMPLATE_DISPATCH_CASE(t, double, p, body) \
554 else TEMPLATE_DISPATCH_SI(t, p, body)
559 #define TEMPLATE_DISPATCH_I(t, p, body) \
560 TEMPLATE_DISPATCH_CASE(t, long long, p, body) \
561 else TEMPLATE_DISPATCH_CASE(t, unsigned long long, p, body) \
562 else TEMPLATE_DISPATCH_CASE(t, long, p, body) \
563 else TEMPLATE_DISPATCH_CASE(t, int, p, body) \
564 else TEMPLATE_DISPATCH_CASE(t, unsigned int, p, body) \
565 else TEMPLATE_DISPATCH_CASE(t, unsigned long, p, body) \
566 else TEMPLATE_DISPATCH_CASE(t, short int, p, body) \
567 else TEMPLATE_DISPATCH_CASE(t, short unsigned int, p, body) \
568 else TEMPLATE_DISPATCH_CASE(t, char, p, body) \
569 else TEMPLATE_DISPATCH_CASE(t, unsigned char, p, body)
576 #define TEMPLATE_DISPATCH(t, p, body) \
577 TEMPLATE_DISPATCH_FP(t, p, body) \
578 else TEMPLATE_DISPATCH_I(t, p, body)
583 #define NESTED_TEMPLATE_DISPATCH_FP(t, p, i, body) \
584 NESTED_TEMPLATE_DISPATCH_CASE(t, float, p, i, body) \
585 else NESTED_TEMPLATE_DISPATCH_CASE(t, double, p, i, body)
590 #define NESTED_TEMPLATE_DISPATCH_I(t, p, i, body) \
591 NESTED_TEMPLATE_DISPATCH_CASE(t, long long, p, i, body) \
592 else NESTED_TEMPLATE_DISPATCH_CASE(t, unsigned long long, p, i, body) \
593 else NESTED_TEMPLATE_DISPATCH_CASE(t, long, p, i, body) \
594 else NESTED_TEMPLATE_DISPATCH_CASE(t, int, p, i, body) \
595 else NESTED_TEMPLATE_DISPATCH_CASE(t, unsigned int, p, i, body) \
596 else NESTED_TEMPLATE_DISPATCH_CASE(t, unsigned long, p, i, body) \
597 else NESTED_TEMPLATE_DISPATCH_CASE(t, short int, p, i, body) \
598 else NESTED_TEMPLATE_DISPATCH_CASE(t, short unsigned int, p, i, body) \
599 else NESTED_TEMPLATE_DISPATCH_CASE(t, char, p, i, body) \
600 else NESTED_TEMPLATE_DISPATCH_CASE(t, unsigned char, p, i, body)
608 #define NESTED_TEMPLATE_DISPATCH(t, p, i, body) \
609 NESTED_TEMPLATE_DISPATCH_FP(t, p, i, body) \
610 else NESTED_TEMPLATE_DISPATCH_I(t, p, i, body)
615 void teca_variant_array::get_dispatch(std::vector<T> &vals,
619 TT *this_t =
static_cast<TT*
>(
this);
623 throw std::bad_cast();
628 void teca_variant_array::get_dispatch(std::vector<T> &vals,
632 TT *this_t =
static_cast<TT*
>(
this);
636 throw std::bad_cast();
641 void teca_variant_array::get_dispatch(
unsigned long i, T &val,
645 TT *this_t =
static_cast<TT*
>(
this);
649 throw std::bad_cast();
654 void teca_variant_array::get_dispatch(
unsigned long i, T &val,
658 TT *this_t =
static_cast<TT*
>(
this);
662 throw std::bad_cast();
667 void teca_variant_array::get_dispatch(
size_t start,
size_t end, T *vals,
671 TT *this_t =
static_cast<TT*
>(
this);
672 this_t->get(start, end, vals);
675 throw std::bad_cast();
680 void teca_variant_array::get_dispatch(
size_t start,
size_t end, T *vals,
684 TT *this_t =
static_cast<TT*
>(
this);
685 this_t->get(start, end, vals);
688 throw std::bad_cast();
693 void teca_variant_array::set_dispatch(
const std::vector<T> &vals,
697 TT *this_t =
static_cast<TT*
>(
this);
701 throw std::bad_cast();
706 void teca_variant_array::set_dispatch(
const std::vector<T> &vals,
710 TT *this_t =
static_cast<TT*
>(
this);
714 throw std::bad_cast();
719 void teca_variant_array::set_dispatch(
unsigned long i,
const T &val,
723 TT *this_t =
static_cast<TT*
>(
this);
727 throw std::bad_cast();
732 void teca_variant_array::set_dispatch(
unsigned long i,
const T &val,
736 TT *this_t =
static_cast<TT*
>(
this);
740 throw std::bad_cast();
745 void teca_variant_array::set_dispatch(
size_t start,
size_t end,
const T *vals,
749 TT *this_t =
static_cast<TT*
>(
this);
750 this_t->set(start, end, vals);
753 throw std::bad_cast();
758 void teca_variant_array::set_dispatch(
size_t start,
size_t end,
const T *vals,
762 TT *this_t =
static_cast<TT*
>(
this);
763 this_t->set(start, end, vals);
766 throw std::bad_cast();
771 void teca_variant_array::append_dispatch(
const std::vector<T> &vals,
775 TT *this_t =
static_cast<TT*
>(
this);
776 this_t->append(vals);
779 throw std::bad_cast();
784 void teca_variant_array::append_dispatch(
const std::vector<T> &vals,
788 TT *this_t =
static_cast<TT*
>(
this);
789 this_t->append(vals);
792 throw std::bad_cast();
797 void teca_variant_array::append_dispatch(
const T &val,
801 TT *this_t =
static_cast<TT*
>(
this);
805 throw std::bad_cast();
810 void teca_variant_array::append_dispatch(
const T &val,
814 TT *this_t =
static_cast<TT*
>(
this);
818 throw std::bad_cast();
842 size_t start,
size_t end)
const
845 this->get(start, end, c->get());
868 m_data.assign(other.m_data.begin(), other.m_data.end());
879 m_data.assign(other.m_data.begin(), other.m_data.end());
887 : m_data(std::move(other.m_data))
895 m_data = std::move(other.m_data);
903 const char *element_name =
typeid(T).name();
904 size_t element_size =
sizeof(T);
905 std::ostringstream oss;
906 oss <<
"teca_variant_array_impl<" << element_name
907 << element_size <<
">";
915 m_data.assign(m_data.size(), T());
931 for (
size_t i = start, ii = 0; i <= end; ++i, ++ii)
932 vals[ii] = m_data[i];
940 val.assign(m_data.begin(), m_data.end());
956 for (
size_t i = start, ii = 0; i <= end; ++i, ++ii)
957 m_data[i] = vals[ii];
965 size_t n = val.size();
967 for (
size_t i = 0; i < n; ++i)
968 m_data[i] =
static_cast<T
>(val[i]);
976 std::copy(val.begin(), val.end(), std::back_inserter(m_data));
984 m_data.push_back(val);
990 {
return m_data.size(); }
1000 template<
typename T>
1003 m_data.resize(n, val);
1007 template<
typename T>
1014 template<
typename T>
1021 template<
typename T>
1025 TT *other_t =
static_cast<TT*
>(&other);
1029 throw teca_bad_cast(safe_class_name(&other), safe_class_name(
this));
1033 template<
typename T>
1037 TT *other_t =
static_cast<TT*
>(&other);
1039 other_t->m_data.begin(),
1040 other_t->m_data.end(),
1041 std::back_inserter(this->m_data));
1044 throw teca_bad_cast(safe_class_name(&other), safe_class_name(
this));
1048 template<
typename T>
1052 TT *other_t =
dynamic_cast<TT*
>(&other);
1055 this->m_data.swap(other_t->m_data);
1058 throw teca_bad_cast(safe_class_name(&other), safe_class_name(
this));
1062 template<
typename T>
1066 const TT *other_t =
dynamic_cast<const TT*
>(&other);
1069 return this->m_data == other_t->m_data;
1071 throw teca_bad_cast(safe_class_name(&other), safe_class_name(
this));
1076 template<
typename T>
1077 template <
typename U>
1082 s.pack(this->m_data);
1086 template<
typename T>
1087 template <
typename U>
1092 s.unpack(this->m_data);
1096 template<
typename T>
1097 template <
typename U>
1102 unsigned long long n = this->size();
1104 for (
unsigned long long i=0; i<n; ++i)
1105 this->m_data[i].to_stream(s);
1109 template<
typename T>
1110 template <
typename U>
1115 unsigned long long n;
1118 for (
unsigned long long i=0; i<n; ++i)
1119 this->m_data[i].from_stream(s);
1123 template<
typename T>
1124 template <
typename U>
1129 unsigned long long n = this->size();
1131 for (
unsigned long long i=0; i<n; ++i)
1132 this->m_data[i]->to_stream(s);
1136 template<
typename T>
1137 template <
typename U>
1142 unsigned long long n;
1145 for (
unsigned long long i=0; i<n; ++i)
1146 this->m_data[i]->from_stream(s);
1149 #define STR_DELIM(_a, _b) \
1150 (std::is_same<T, std::string>::value ? _a : _b)
1153 template<
typename T>
1154 template <
typename U>
1159 size_t n = this->m_data.size();
1162 s << STR_DELIM(
"\"",
"")
1163 << this->m_data[0] << STR_DELIM(
"\"",
"");
1164 for (
size_t i = 1; i < n; ++i)
1166 s << STR_DELIM(
", \"",
", ")
1167 << this->m_data[i] << STR_DELIM(
"\"",
"");
1173 template<
typename T>
1174 template <
typename U>
1183 template<
typename T>
1184 template <
typename U>
1189 size_t n = this->m_data.size();
1193 this->m_data[0].to_stream(s);
1195 for (
size_t i = 1; i < n; ++i)
1198 this->m_data[i].to_stream(s);
1205 template<
typename T>
1206 template <
typename U>
1215 template<
typename T>
1216 template <
typename U>
1221 size_t n = this->m_data.size();
1225 this->m_data[0]->to_stream(s);
1227 for (
size_t i = 1; i < n; ++i)
1230 this->m_data[i]->to_stream(s);
1237 template<
typename T>
1238 template <
typename U>
1246 template <
typename T>
1249 template <
unsigned int I>
1252 template <
unsigned int I>
1255 #define TECA_VARIANT_ARRAY_TT_SPEC(T, v) \
1257 struct teca_variant_array_code<T> \
1259 static constexpr unsigned int get() \
1263 struct teca_variant_array_new<v> \
1265 static p_teca_variant_array_impl<T> New() \
1266 { return teca_variant_array_impl<T>::New(); } \
1269 struct teca_variant_array_type<v> \
1273 static constexpr const char *name() \
1277 #define TECA_VARIANT_ARRAY_FACTORY_NEW(_v) \
1279 return teca_variant_array_new<_v>::New();
1281 #include "teca_metadata.h"
1284 TECA_VARIANT_ARRAY_TT_SPEC(
char, 1)
1285 TECA_VARIANT_ARRAY_TT_SPEC(
unsigned char, 2)
1286 TECA_VARIANT_ARRAY_TT_SPEC(
int, 3)
1287 TECA_VARIANT_ARRAY_TT_SPEC(
unsigned int, 4)
1288 TECA_VARIANT_ARRAY_TT_SPEC(
short int, 5)
1289 TECA_VARIANT_ARRAY_TT_SPEC(
short unsigned int, 6)
1290 TECA_VARIANT_ARRAY_TT_SPEC(
long, 7)
1291 TECA_VARIANT_ARRAY_TT_SPEC(
unsigned long, 8)
1292 TECA_VARIANT_ARRAY_TT_SPEC(
long long, 9)
1293 TECA_VARIANT_ARRAY_TT_SPEC(
unsigned long long, 10)
1294 TECA_VARIANT_ARRAY_TT_SPEC(
float, 11)
1295 TECA_VARIANT_ARRAY_TT_SPEC(
double, 12)
1296 TECA_VARIANT_ARRAY_TT_SPEC(std::
string, 13)
1298 TECA_VARIANT_ARRAY_TT_SPEC(p_teca_variant_array, 15)
1302 static p_teca_variant_array New(
unsigned int type_code)
1306 TECA_VARIANT_ARRAY_FACTORY_NEW(1)
1307 TECA_VARIANT_ARRAY_FACTORY_NEW(2)
1308 TECA_VARIANT_ARRAY_FACTORY_NEW(3)
1309 TECA_VARIANT_ARRAY_FACTORY_NEW(4)
1310 TECA_VARIANT_ARRAY_FACTORY_NEW(5)
1311 TECA_VARIANT_ARRAY_FACTORY_NEW(6)
1312 TECA_VARIANT_ARRAY_FACTORY_NEW(7)
1313 TECA_VARIANT_ARRAY_FACTORY_NEW(8)
1314 TECA_VARIANT_ARRAY_FACTORY_NEW(9)
1315 TECA_VARIANT_ARRAY_FACTORY_NEW(10)
1316 TECA_VARIANT_ARRAY_FACTORY_NEW(11)
1317 TECA_VARIANT_ARRAY_FACTORY_NEW(12)
1318 TECA_VARIANT_ARRAY_FACTORY_NEW(13)
1319 TECA_VARIANT_ARRAY_FACTORY_NEW(14)
1320 TECA_VARIANT_ARRAY_FACTORY_NEW(15)
1323 <<
"Failed to create from "
1330 #define CODE_DISPATCH_CASE(_v, _c, _code) \
1333 using NT = teca_variant_array_type<_c>::type; \
1334 using TT = teca_variant_array_impl<NT>; \
1338 #define CODE_DISPATCH_I(_v, _code) \
1339 CODE_DISPATCH_CASE(_v, 1, _code) \
1340 else CODE_DISPATCH_CASE(_v, 2, _code) \
1341 else CODE_DISPATCH_CASE(_v, 3, _code) \
1342 else CODE_DISPATCH_CASE(_v, 4, _code) \
1343 else CODE_DISPATCH_CASE(_v, 5, _code) \
1344 else CODE_DISPATCH_CASE(_v, 6, _code) \
1345 else CODE_DISPATCH_CASE(_v, 7, _code) \
1346 else CODE_DISPATCH_CASE(_v, 8, _code) \
1347 else CODE_DISPATCH_CASE(_v, 9, _code) \
1348 else CODE_DISPATCH_CASE(_v, 10, _code)
1350 #define CODE_DISPATCH_FP(_v, _code) \
1351 CODE_DISPATCH_CASE(_v, 11, _code) \
1352 else CODE_DISPATCH_CASE(_v, 12, _code)
1354 #define CODE_DISPATCH_CLASS(_v, _code) \
1355 CODE_DISPATCH_CASE(_v, 13, _code) \
1356 else CODE_DISPATCH_CASE(_v, 14, _code) \
1357 else CODE_DISPATCH_CASE(_v, 15, _code)
1359 #define CODE_DISPATCH(_v, _code) \
1360 CODE_DISPATCH_I(_v, _code) \
1361 else CODE_DISPATCH_FP(_v, _code)
1365 template<
typename T>
1372 template <
typename num_t>
1373 num_t min(
const const_p_teca_variant_array_impl<num_t> &a)
1375 num_t mn = std::numeric_limits<num_t>::max();
1378 const NT *pa = std::dynamic_pointer_cast<TT>(a)->get();
1379 size_t n = a->size();
1380 for (
size_t i = 0; i < n; ++i)
1381 mn = mn > pa[i] ? pa[i] : mn;
1387 template <
typename num_t>
1388 num_t min(
const p_teca_variant_array_impl<num_t> &a)
1390 return min(const_p_teca_variant_array_impl<num_t>(a));
1394 template <
typename num_t>
1395 num_t max(
const const_p_teca_variant_array_impl<num_t> &a)
1397 num_t mx = std::numeric_limits<num_t>::lowest();
1400 const NT *pa = std::dynamic_pointer_cast<TT>(a)->get();
1401 size_t n = a->size();
1402 for (
size_t i = 0; i < n; ++i)
1403 mx = mx < pa[i] ? pa[i] : mx;
1409 template <
typename num_t>
1410 num_t max(
const p_teca_variant_array_impl<num_t> &a)
1412 return max(const_p_teca_variant_array_impl<num_t>(a));