TECA
The Toolkit for Extreme Climate Analysis
teca_variant_array_impl.h
Go to the documentation of this file.
1 #ifndef teca_variant_array_impl_h
2 #define teca_variant_array_impl_h
3 
4 /// @file
5 
6 #if defined(__CUDACC__)
7 #pragma nv_diag_suppress = partial_override
8 #endif
9 
10 #include "teca_config.h"
11 #include "teca_variant_array.h"
12 #include "teca_common.h"
13 #include "teca_binary_stream.h"
14 #include "teca_bad_cast.h"
15 #include "teca_shared_object.h"
16 
17 #include <hamr_buffer.h>
18 
19 #include <vector>
20 #include <string>
21 #include <sstream>
22 #include <exception>
23 #include <typeinfo>
24 #include <iterator>
25 #include <algorithm>
26 #include <type_traits>
27 #include <typeinfo>
28 #include <utility>
29 #include <limits>
30 
31 #if defined(TECA_HAS_CUDA)
32 #include <thrust/device_ptr.h>
33 #include <thrust/functional.h>
34 #include <thrust/reduce.h>
35 #endif
36 
37 class teca_metadata;
38 
39 TECA_SHARED_OBJECT_TEMPLATE_FORWARD_DECL(teca_variant_array_impl)
40 
41 #ifndef SWIG
43 using p_teca_string_array = std::shared_ptr<teca_variant_array_impl<std::string>>;
44 using const_p_teca_string_array = std::shared_ptr<const teca_variant_array_impl<std::string>>;
45 
47 using p_teca_float_array = std::shared_ptr<teca_variant_array_impl<float>>;
48 using const_p_teca_float_array = std::shared_ptr<const teca_variant_array_impl<float>>;
49 
51 using p_teca_double_array = std::shared_ptr<teca_variant_array_impl<double>>;
52 using const_p_teca_double_array = std::shared_ptr<const teca_variant_array_impl<double>>;
53 
55 using p_teca_char_array = std::shared_ptr<teca_variant_array_impl<char>>;
56 using const_p_teca_char_array = std::shared_ptr<const teca_variant_array_impl<char>>;
57 
59 using p_teca_unsigned_char_array = std::shared_ptr<teca_variant_array_impl<unsigned char>>;
60 using const_p_teca_unsigned_char_array = std::shared_ptr<const teca_variant_array_impl<unsigned char>>;
61 
63 using p_teca_short_array = std::shared_ptr<teca_variant_array_impl<short>>;
64 using const_p_teca_short_array = std::shared_ptr<const teca_variant_array_impl<short>>;
65 
67 using p_teca_unsigned_short_array = std::shared_ptr<teca_variant_array_impl<unsigned short>>;
68 using const_p_teca_unsigned_short_array = std::shared_ptr<const teca_variant_array_impl<unsigned short>>;
69 
71 using p_teca_int_array = std::shared_ptr<teca_variant_array_impl<int>>;
72 using const_p_teca_int_array = std::shared_ptr<const teca_variant_array_impl<int>>;
73 
75 using p_teca_unsigned_int_array = std::shared_ptr<teca_variant_array_impl<unsigned int>>;
76 using const_p_teca_unsigned_int_array = std::shared_ptr<const teca_variant_array_impl<unsigned int>>;
77 
79 using p_teca_long_array = std::shared_ptr<teca_variant_array_impl<long>>;
80 using const_p_teca_long_array = std::shared_ptr<const teca_variant_array_impl<long>>;
81 
83 using p_teca_unsigned_long_array = std::shared_ptr<teca_variant_array_impl<unsigned long>>;
84 using const_p_teca_unsigned_long_array = std::shared_ptr<const teca_variant_array_impl<unsigned long>>;
85 
87 using p_teca_long_long_array = std::shared_ptr<teca_variant_array_impl<long long>>;
88 using const_p_teca_long_long_array = std::shared_ptr<const teca_variant_array_impl<long long>>;
89 
91 using p_teca_unsigned_long_long_array = std::shared_ptr<teca_variant_array_impl<unsigned long long>>;
92 using const_p_teca_unsigned_long_long_array = std::shared_ptr<const teca_variant_array_impl<unsigned long long>>;
93 
95 using p_teca_size_t_array = std::shared_ptr<teca_variant_array_impl<size_t>>;
96 using const_p_teca_size_t_array = std::shared_ptr<const teca_variant_array_impl<size_t>>;
97 #endif
98 
99 
100 /** convert from a pointer to a non-const type to a pointer to a const type.
101  * this is used to help with template deduction, which occurs before implicit
102  * conversions are considered.
103  */
104 template <typename T>
106 {
108 }
109 
110 
111 /// @cond
112 /// A tag for dispatching operations on POD data
113 template <typename T>
114 struct pod_dispatch :
115  std::integral_constant<bool,
116  std::is_arithmetic<T>::value>
117 {};
118 
119 /// A tag for disp[atching operations on classes
120 template <typename T>
121 struct object_dispatch :
122  std::integral_constant<bool,
123  !std::is_arithmetic<T>::value>
124 {};
125 /// @endcond
126 
127 /** Executes the code in body if p is a tt<nt>
128  * @param tt derived container
129  * @param nt contained type
130  * @param p base class pointer
131  * @param body the code to execute if the type matches
132  *
133  * The following aliases are provided to know the type within the code to execute.
134  *
135  * using TT = tt<nt>;
136  * using NT = nt;
137  *
138  */
139 #define TEMPLATE_DISPATCH_CASE(tt, nt, p, body) \
140  if (dynamic_cast<tt<nt>*>(p)) \
141  { \
142  using TT = tt<nt>; \
143  using NT = nt; \
144  body \
145  }
146 
147 /** Executes the code in body if p is a tt<nt> an idnetifier disambiguates type
148  * aliases when nested
149  *
150  * @param tt derived container
151  * @param nt contained type
152  * @param p base class pointer
153  * @param i identifier
154  * @param body the code to execute if the type matches
155  *
156  * The following aliases are provided to know the type within the code to execute.
157  *
158  * using TT##i = tt<nt>;
159  * using NT##i = nt;
160  *
161  */
162 #define NESTED_TEMPLATE_DISPATCH_CASE(tt, nt, p, i, body) \
163  if (dynamic_cast<tt<nt>*>(p)) \
164  { \
165  using TT##i = tt<nt>; \
166  using NT##i = nt; \
167  body \
168  }
169 
170 /// Executes the code in body if p is a t<nt> where nt is a floating point type
171 #define TEMPLATE_DISPATCH_FP(t, p, body) \
172  TEMPLATE_DISPATCH_CASE(t, float, p, body) \
173  else TEMPLATE_DISPATCH_CASE(t, double, p, body)
174 
175 /// Executes the code in body if p is a t<nt> where nt is a signed inetegral type
176 #define TEMPLATE_DISPATCH_SI(t, p, body) \
177  TEMPLATE_DISPATCH_CASE(t, long long, p, body) \
178  else TEMPLATE_DISPATCH_CASE(t, long, p, body) \
179  else TEMPLATE_DISPATCH_CASE(t, int, p, body) \
180  else TEMPLATE_DISPATCH_CASE(t, short int, p, body) \
181  else TEMPLATE_DISPATCH_CASE(t, char, p, body)
182 
183 /// Executes the code in body if p is a t<nt> where nt is either a signed integral or floating point type
184 #define TEMPLATE_DISPATCH_FP_SI(t, p, body) \
185  TEMPLATE_DISPATCH_CASE(t, float, p, body) \
186  else TEMPLATE_DISPATCH_CASE(t, double, p, body) \
187  else TEMPLATE_DISPATCH_SI(t, p, body)
188 
189 /// Executes the code in body if p is a t<nt> where nt is an integral type
190 #define TEMPLATE_DISPATCH_I(t, p, body) \
191  TEMPLATE_DISPATCH_CASE(t, long long, p, body) \
192  else TEMPLATE_DISPATCH_CASE(t, unsigned long long, p, body) \
193  else TEMPLATE_DISPATCH_CASE(t, long, p, body) \
194  else TEMPLATE_DISPATCH_CASE(t, int, p, body) \
195  else TEMPLATE_DISPATCH_CASE(t, unsigned int, p, body) \
196  else TEMPLATE_DISPATCH_CASE(t, unsigned long, p, body) \
197  else TEMPLATE_DISPATCH_CASE(t, short int, p, body) \
198  else TEMPLATE_DISPATCH_CASE(t, short unsigned int, p, body) \
199  else TEMPLATE_DISPATCH_CASE(t, char, p, body) \
200  else TEMPLATE_DISPATCH_CASE(t, unsigned char, p, body)
201 
202 /** A macro for accessing the typed contents of a teca_variant_array
203  * @param t container type
204  * @param p pointer to an instance to match on
205  * @param body code to execute on match
206  *
207  * See #TEMPLATE_DISPATCH_CASE for details.
208  */
209 #define TEMPLATE_DISPATCH(t, p, body) \
210  TEMPLATE_DISPATCH_FP(t, p, body) \
211  else TEMPLATE_DISPATCH_I(t, p, body)
212 
213 /** A macro for accessing the typed contents of a teca_variant_array
214  * @param t container type
215  * @param p pointer to an instance to match on
216  * @param body code to execute on match
217  *
218  * See #TEMPLATE_DISPATCH_CASE for details.
219  */
220 #define TEMPLATE_DISPATCH_OBJ(t, p, body) \
221  TEMPLATE_DISPATCH_CASE(t, std::string, p, body) \
222  else TEMPLATE_DISPATCH_CASE(t, teca_metadata, p, body)
223 
224 /** A macro for accessing the typed contents of a teca_variant_array
225  * @param t container type
226  * @param p pointer to an instance to match on
227  * @param body code to execute on match
228  *
229  * See #TEMPLATE_DISPATCH_CASE for details.
230  */
231 #define TEMPLATE_DISPATCH_PTR(t, p, body) \
232  TEMPLATE_DISPATCH_CASE(t, const_p_teca_variant_array, p, body) \
233  else TEMPLATE_DISPATCH_CASE(t, p_teca_variant_array, p, body)
234 
235 /** A macro for accessing the floating point typed contents of a teca_variant_array
236  * @param t container type
237  * @param p pointer to an instance to match on
238  * @param i an indentifier to use with type aliases
239  * @param body code to execute on match
240  *
241  * See #NESTED_TEMPLATE_DISPATCH_CASE for details.
242  */
243 #define NESTED_TEMPLATE_DISPATCH_FP(t, p, i, body) \
244  NESTED_TEMPLATE_DISPATCH_CASE(t, float, p, i, body) \
245  else NESTED_TEMPLATE_DISPATCH_CASE(t, double, p, i, body)
246 
247 /** A macro for accessing the inetgral typed contents of a teca_variant_array
248  * @param t container type
249  * @param p pointer to an instance to match on
250  * @param i an indentifier to use with type aliases
251  * @param body code to execute on match
252  *
253  * See #NESTED_TEMPLATE_DISPATCH_CASE for details.
254  */
255 #define NESTED_TEMPLATE_DISPATCH_I(t, p, i, body) \
256  NESTED_TEMPLATE_DISPATCH_CASE(t, long long, p, i, body) \
257  else NESTED_TEMPLATE_DISPATCH_CASE(t, unsigned long long, p, i, body) \
258  else NESTED_TEMPLATE_DISPATCH_CASE(t, long, p, i, body) \
259  else NESTED_TEMPLATE_DISPATCH_CASE(t, int, p, i, body) \
260  else NESTED_TEMPLATE_DISPATCH_CASE(t, unsigned int, p, i, body) \
261  else NESTED_TEMPLATE_DISPATCH_CASE(t, unsigned long, p, i, body) \
262  else NESTED_TEMPLATE_DISPATCH_CASE(t, short int, p, i, body) \
263  else NESTED_TEMPLATE_DISPATCH_CASE(t, short unsigned int, p, i, body) \
264  else NESTED_TEMPLATE_DISPATCH_CASE(t, char, p, i, body) \
265  else NESTED_TEMPLATE_DISPATCH_CASE(t, unsigned char, p, i, body)
266 
267 /** \def NESTED_TEMPLATE_DISPATCH(t, p, i, body)
268  * A macro for accessing the typed contents of a teca_variant_array
269  * @param t container type
270  * @param p pointer to an instance to match on
271  * @param i an indentifier to use with type aliases
272  * @param body code to execute on match
273  *
274  * See #NESTED_TEMPLATE_DISPATCH_CASE for details.
275  */
276 #define NESTED_TEMPLATE_DISPATCH(t, p, i, body) \
277  NESTED_TEMPLATE_DISPATCH_FP(t, p, i, body) \
278  else NESTED_TEMPLATE_DISPATCH_I(t, p, i, body)
279 
280 /// @cond
281 // tag for contiguous arrays, and objects that have
282 // overrides in teca_binary_stream
283 template<typename T>
284 struct pack_array
285  : std::integral_constant<bool,
286  std::is_arithmetic<T>::value ||
287  std::is_same<T, std::string>::value>
288 {};
289 
290 // tag for arrays of pointers of other objects
291 template<typename T>
292 struct pack_object_ptr
293  : std::integral_constant<bool,
294  (std::is_pointer<T>::value ||
295  std::is_same<T, p_teca_variant_array>::value) &&
296  !pack_array<T>::value>
297 {};
298 
299 // tag for arrays of other objects
300 template<typename T>
301 struct pack_object
302  : std::integral_constant<bool,
303  !pack_array<T>::value &&
304  !std::is_pointer<T>::value &&
305  !pack_object_ptr<T>::value>
306 {};
307 /// @endcond
308 
309 
310 /** @brief
311  * The concrete implementation of our type agnostic container for contiguous
312  * arrays.
313  */
314 template<typename T>
316 {
317 public:
318  /** @name Array constructors
319  * Constructs a new instance containing the templated type.
320  */
321  ///@{
322  /** Allocate an array. The default value of alloc sets the array up for
323  * use on the CPU using C++ new to allocate memory to hold the contents.
324  */
325  static std::shared_ptr<teca_variant_array_impl<T>>
326  New() { return New(allocator::malloc); }
327 
328  /** Allocate an array. The default value of alloc sets the array up for
329  * use on the CPU using C++ new to allocate memory to hold the contents.
330  */
331  static std::shared_ptr<teca_variant_array_impl<T>>
332  New(allocator alloc);
333 
334  /** Allocates an array with space for n elements. The default value of
335  * alloc sets the array up for use on the CPU using C++ new to allocate
336  * memory to hold the contents.
337  */
338  static std::shared_ptr<teca_variant_array_impl<T>>
339  New(size_t n) { return New(n, allocator::malloc); }
340 
341  /** Allocates an array with space for n elements. The default value of
342  * alloc sets the array up for use on the CPU using C++ new to allocate
343  * memory to hold the contents.
344  */
345  static std::shared_ptr<teca_variant_array_impl<T>>
346  New(size_t n, allocator alloc);
347 
348  /** Allocate an array with space for n elements initialized with v. The default
349  * value of alloc sets the array up for use on the CPU using C++ new to
350  * allocate memory to hold the contents.
351  */
352  template <typename U>
353  static std::shared_ptr<teca_variant_array_impl<T>>
354  New(size_t n, const U &v) { return New(n, v, allocator::malloc); }
355 
356  /** Allocate an array with space for n elements initialized with v. The default
357  * value of alloc sets the array up for use on the CPU using C++ new to
358  * allocate memory to hold the contents.
359  */
360  template <typename U>
361  static std::shared_ptr<teca_variant_array_impl<T>>
362  New(size_t n, const U &v, allocator alloc);
363 
364  /** Allocate an array with space for n elements initialized with v. The default
365  * value of alloc sets the array up for use on the CPU using C++ new to
366  * allocate memory to hold the contents.
367  */
368  template <typename U>
369  static std::shared_ptr<teca_variant_array_impl<T>>
370  New(size_t n, const U *v) { return New(n, v, allocator::malloc); }
371 
372  /** Allocate an array with space for n elements initialized with v. The default
373  * value of alloc sets the array up for use on the CPU using C++ new to
374  * allocate memory to hold the contents.
375  */
376  template <typename U>
377  static std::shared_ptr<teca_variant_array_impl<T>>
378  New(size_t n, const U *v, allocator alloc);
379 
380  /** construct by directly providing the buffer contents. This can be used
381  * for zero-copy transfer of data. One must also name the allocator type
382  * and device owning the data. In addition for new allocations the
383  * allocator type and owner are used internally to know how to
384  * automatically move data during inter technology transfers.
385  *
386  * @param[in] alloc an ::allocator indicating the technology backing the
387  * pointer
388  * @param[in] size the number of elements in the array pointed to by ptr
389  * @param[in] owner the device owning the memory, -1 for CPU. if the
390  * allocator is a GPU allocator and -1 is passed the
391  * driver API is used to determine the device that
392  * allocated the memory.
393  * @param[in] ptr a pointer to the data
394  * @param[in] df a function `void df(void*ptr)` used to delete the data
395  * when this instance is finished using it.
396  */
397  template <typename delete_func_t>
398  static std::shared_ptr<teca_variant_array_impl<T>>
399  New(size_t n, T *ptr, allocator alloc, int owner, delete_func_t df);
400 
401  /// Returns a new instance initialized with a deep copy of this one.
402  p_teca_variant_array new_copy(allocator alloc = allocator::malloc) const override;
403 
404  /** virtual copy construct. return a newly allocated object, initialized
405  * copy from a subset of this.
406  */
407  p_teca_variant_array new_copy(size_t src_start, size_t n_elem, allocator alloc) const override;
408 
409  /// Returns a new instance of the same type.
410  p_teca_variant_array new_instance(allocator alloc) const override;
411 
412  /// Returns a new instance of the same type sized to hold n elements.
413  p_teca_variant_array new_instance(size_t n, allocator alloc) const override;
414  ///@}
415 
416  virtual ~teca_variant_array_impl() noexcept;
417 
418  /// @copydoc teca_variant_array::set_allocator(allocator)
419  int set_allocator(allocator alloc) override;
420 
421  /// Returns the name of the class in a human readable form
422  std::string get_class_name() const override;
423 
424  /// Initialize all elements with T()
425  void initialize() override
426  {
427  TECA_ERROR("Not implemented")
428  }
429 
430  // silence some warning from nvcc
435 
436  /** @name get
437  * Copy the content of this array. The desitination must be large enough to
438  * hold the results. These calls could throw teca_bad_cast if the passed
439  * in type is not castable to the internal type.
440  */
441  ///@{
442  /// get a single value
443  template<typename U>
444  void get(size_t i, U &val) const
445  {
446  this->get(i, &val, 0, 1);
447  }
448 
449  /// get a single value
450  T get(size_t i) const
451  {
452  T val = T();
453  this->get(i, &val, 0, 1);
454  return val;
455  }
456 
457  /// get a vector of values
458  template<typename U>
459  void get(std::vector<U> &dest) const
460  {
461  size_t n_elem = this->size();
462  dest.resize(n_elem);
463  this->get(0, dest.data(), 0, n_elem);
464  }
465 
466  /// get a range of values
467  template<typename U>
468  void get(size_t src_start, U *dest, size_t dest_start, size_t n_elem) const
469  {
470  assert(this->size() >= (src_start + n_elem));
471  this->get_dispatch(src_start, dest, dest_start, n_elem);
472  }
473 
474  /// get the contents into the other array.
475  void get(const p_teca_variant_array &dest) const override
476  {
477  this->get(0, dest, 0, this->size());
478  }
479 
480  /** get a subset of the contents into a subset of the other array
481  *
482  * @param[in] dest_start the first location to assign to
483  * @param[in] src the array to copy values from
484  * @param[in] src_start the first location to copy from
485  * @param[in] n_elem the number of elements to copy
486  */
487  void get(size_t src_start, const p_teca_variant_array &dest,
488  size_t dest_start, size_t n_elem) const override
489  {
490  assert(this->size() >= (src_start + n_elem));
491  this->get_dispatch<T>(src_start, dest, dest_start, n_elem);
492  }
493 
494  /// get the contents into the other array.
495  template <typename U>
496  void get(const p_teca_variant_array_impl<U> &dest) const
497  {
498  this->get(0, dest, 0, this->size());
499  }
500 
501  /** get a subset of the contents into a subset of the other array
502  *
503  * @param[in] dest_start the first location to assign to
504  * @param[in] src the array to copy values from
505  * @param[in] src_start the first location to copy from
506  * @param[in] n_elem the number of elements to copy
507  */
508  template <typename U>
509  void get(size_t src_start, const p_teca_variant_array_impl<U> &dest,
510  size_t dest_start, size_t n_elem) const
511  {
512  assert(this->size() >= (src_start + n_elem));
513  this->get_dispatch<T>(src_start, dest, dest_start, n_elem);
514  }
515  ///@}
516 
517  /** @name set
518  * Assign values to this array. This array must already be large enough to
519  * hold the result. If automatic resizing is desired use copy instead.
520  * These calls could throw teca_bad_cast if the passed in type is not
521  * castable to the internal type.
522  */
523  ///@{
524  /// set a single value
525  template<typename U>
526  void set(size_t i, const U &val)
527  {
528  this->set(i, &val, 0, 1);
529  }
530 
531  /// set from a vector of values
532  template<typename U>
533  void set(const std::vector<U> &src)
534  {
535  this->set(0, src.data(), 0, src.size());
536  }
537 
538  /** set from a subset of the other array
539  *
540  * @param[in] dest_start the first location to assign to
541  * @param[in] src the array to copy values from
542  * @param[in] src_start the first location to copy from
543  * @param[in] n_elem the number of elements to copy
544  */
545  template<typename U>
546  void set(size_t dest_start, const U *src, size_t src_start, size_t n_elem)
547  {
548  assert(this->size() >= (dest_start + n_elem));
549  this->set_dispatch(dest_start, src, src_start, n_elem);
550  }
551 
552  /// Set from the other array
553  void set(const const_p_teca_variant_array &src) override
554  {
555  this->set(0, src, 0, src->size());
556  }
557 
558  /** Set a subset of this array from a subset of the other array.
559  *
560  * @param[in] dest_start the first location to assign to
561  * @param[in] src the array to copy values from
562  * @param[in] src_start the first location to copy from
563  * @param[in] n_elem the number of elements to copy
564  */
565  void set(size_t dest_start, const const_p_teca_variant_array &src,
566  size_t src_start, size_t n_elem) override
567  {
568  assert(this->size() >= (dest_start + n_elem));
569  this->set_dispatch(dest_start, src, src_start, n_elem);
570  }
571 
572  /// Set from the other array
573  template <typename U>
575  {
576  this->set(0, src, 0, src->size());
577  }
578 
579  /** Set a subset of this array from a subset of the other array.
580  *
581  * @param[in] dest_start the first location to assign to
582  * @param[in] src the array to copy values from
583  * @param[in] src_start the first location to copy from
584  * @param[in] n_elem the number of elements to copy
585  */
586  template <typename U>
587  void set(size_t dest_start, const const_p_teca_variant_array_impl<U> &src,
588  size_t src_start, size_t n_elem)
589  {
590  assert(this->size() >= (dest_start + n_elem));
591  this->set_dispatch(dest_start, src, src_start, n_elem);
592  }
593  ///@}
594 
595  /** @name assign
596  * assign the contents of the passed array to this array. This array will be
597  * resized to hold the results. These calls could throw teca_bad_cast if
598  * the passed in type is not castable to the internal type.
599  */
600  ///@{
601  /// assign the contents from a vector of values
602  template<typename U>
603  void assign(const std::vector<U> &src)
604  {
605  this->assign(src.data(), 0, src.size());
606  }
607 
608  /// assign a subset from the other array
609  template<typename U>
610  void assign(const U *src, size_t src_start, size_t n_elem)
611  {
612  this->assign_dispatch(src, src_start, n_elem);
613  }
614 
615  /// assign the contents from the other array.
616  void assign(const const_p_teca_variant_array &src) override
617  {
618  this->assign(src, 0, src->size());
619  }
620 
621  /// assign a subset of the other array
623  size_t src_start, size_t n_elem) override
624  {
625  this->assign_dispatch(src, src_start, n_elem);
626  }
627 
628  /// assign the contents from the other array.
629  template <typename U>
631  {
632  this->assign(src, 0, src->size());
633  }
634 
635  /// assign the contents from the other array.
636  template <typename U>
638  {
639  // forward to the const implementation
640  this->assign(const_p_teca_variant_array_impl<U>(src), 0, src->size());
641  }
642 
643  /// assign a subset of the other array
644  template <typename U>
646  size_t src_start, size_t n_elem)
647  {
648  this->assign_dispatch(src, src_start, n_elem);
649  }
650 
651  /// copy the contents from the other array.
652  template <typename U>
654  {
655  this->assign(src, 0, src->size());
656  }
657 
658  /// copy a subset of the other array
659  template <typename U>
661  size_t src_start, size_t n_elem)
662  {
663  this->assign_dispatch(src, src_start, n_elem);
664  }
665  ///@}
666 
667  /** @name append
668  * Append data at the back of the array. These calls could throw
669  * teca_bad_cast if the passed in type is not castable to the internal
670  * type.
671  */
672  ///@{
673  /// append a single value
674  template<typename U>
675  void append(const U &val)
676  {
677  this->append(&val, 0, 1);
678  }
679 
680  /// append a vector of values
681  template<typename U>
682  void append(const std::vector<U> &vals)
683  {
684  this->append(vals.data(), 0, vals.size());
685  }
686 
687  /// append a range of values
688  template<typename U>
689  void append(const U *src, size_t src_start, size_t n_elem)
690  {
691  this->append_dispatch(src, src_start, n_elem);
692  }
693 
694  // Append the contents from the other array
695  void append(const const_p_teca_variant_array &src) override
696  {
697  this->append(src, 0, src->size());
698  }
699 
700  // Append a subset of the contents from the other array
701  void append(const const_p_teca_variant_array &src,
702  size_t src_start, size_t n_elem) override
703  {
704  this->append_dispatch(src, src_start, n_elem);
705  }
706 
707  // Append the contents from the other array
708  template <typename U>
710  {
711  this->append(src, 0, src->size());
712  }
713 
714  // Append the contents from the other array
715  template <typename U>
716  void append(const p_teca_variant_array_impl<U> &src)
717  {
718  // forward to const implementation
719  this->append(const_p_teca_variant_array_impl<U>(src), 0, src->size());
720  }
721 
722  // Append a subset of the contents from the other array
723  template <typename U>
725  size_t src_start, size_t n_elem)
726  {
727  this->append_dispatch(src, src_start, n_elem);
728  }
729  ///@}
730 
731 #if !defined(SWIG)
732  /** @name get_accessible
733  * get's a pointer to the raw data that is accessible on the named
734  * accelerator device or technology.
735  */
736  ///@{
737  /// Get a pointer to the data
738  std::shared_ptr<T> get_cpu_accessible()
739  { return m_data.get_cpu_accessible(); }
740 
741  const std::shared_ptr<const T> get_cpu_accessible() const
742  { return m_data.get_cpu_accessible(); }
743 
744  std::shared_ptr<T> get_cuda_accessible()
745  { return m_data.get_cuda_accessible(); }
746 
747  const std::shared_ptr<const T> get_cuda_accessible() const
748  { return m_data.get_cuda_accessible(); }
749  ///@}
750 #endif
751 
752  /// returns true if the data is accessible from CUDA codes
753  int cuda_accessible() const { return m_data.cuda_accessible(); }
754 
755  /// returns true if the data is accessible from codes running on the CPU
756  int cpu_accessible() const { return m_data.cpu_accessible(); }
757 
758  /// Get the current size of the data
759  unsigned long size() const noexcept override;
760 
761  /// Resize the data
762  void resize(unsigned long n) override;
763  void resize(unsigned long n, const T &val);
764 
765  /// Reserve space
766  void reserve(unsigned long n) override;
767 
768  /// Clear the data
769  void clear() noexcept override;
770 
771  /// virtual swap
772  void swap(const p_teca_variant_array &other) override;
773 
774  /// virtual equivalence test
775  bool equal(const const_p_teca_variant_array &other) const override;
776 
777  /// Serialize to the stream
778  int to_stream(teca_binary_stream &s) const override
779  {
780  this->to_binary<T>(s);
781  return 0;
782  }
783 
784  /// Deserialize from the stream
786  {
787  this->from_binary<T>(s);
788  return 0;
789  }
790 
791  /// Serialize to the stream
792  int to_stream(std::ostream &s) const override
793  {
794  this->to_ascii<T>(s);
795  return 0;
796  }
797 
798  /// Deserialize from the stream
799  int from_stream(std::ostream &s) override
800  {
801  this->from_ascii<T>(s);
802  return 0;
803  }
804 
805  /// Print the contents of the buffer for debugging
806  template <typename U = T>
807  void debug_print(typename std::enable_if< std::is_arithmetic<U>::value >::type* = 0) const
808  { m_data.print(); }
809 
810  /// Print the contents of the buffer for debugging
811  template <typename U = T>
812  void debug_print(typename std::enable_if<!std::is_arithmetic<U>::value>::type* = 0) const
813  {
814  TECA_WARNING("Failed to print the buffer for T=" << typeid(T).name() << sizeof(T))
815  }
816 
817  teca_variant_array::allocator get_allocator() const
818  {
819  return teca_variant_array::allocator(m_data.get_allocator());
820  }
821 
822 #if defined(SWIG)
823 protected:
824 #else
825 public:
826 #endif
827  // NOTE: constructors are public to enable std::make_shared. DO NOT USE.
828 
829  /// default construct (the object is unusable)
831 
832  /// construct with a specific allocator
833  teca_variant_array_impl(allocator alloc) :
834  m_data(alloc) {}
835 
836  /// construct with preallocated size
837  teca_variant_array_impl(allocator alloc, size_t n_elem) :
838  m_data(alloc, n_elem) {}
839 
840  /// construct with preallocated size and initialized to a specific value
841  teca_variant_array_impl(allocator alloc, size_t n_elem, const T &val) :
842  m_data(alloc, n_elem, val) {}
843 
844  /// construct with preallocated size and initialized to a specific value
845  template <typename U>
846  teca_variant_array_impl(allocator alloc, size_t n_elem, const U *vals) :
847  m_data(alloc, n_elem, vals) {}
848 
849  /// copy construct from an instance of different type
850  template<typename U>
851  teca_variant_array_impl(allocator alloc,
852  const const_p_teca_variant_array_impl<U> &other) :
853  m_data(alloc, other->m_data) {}
854 
855  /// zero-copy construct by setting buffer contents directly
856  template <typename delete_func_t>
857  teca_variant_array_impl(allocator alloc, size_t size, int owner,
858  T *ptr, delete_func_t df) : m_data(alloc, size, owner, ptr, df) {}
859 
860 private:
861  /// get from objects.
862  template <typename U = T>
863  void get_dispatch(size_t src_start,
864  const p_teca_variant_array_impl<U> &dest, size_t dest_start, size_t n_elem,
865  typename std::enable_if<object_dispatch<U>::value, U>::type* = 0) const;
866 
867  /// get from POD types
868  template <typename U = T>
869  void get_dispatch(size_t src_start,
870  const p_teca_variant_array_impl<U> &dest, size_t dest_start, size_t n_elem,
871  typename std::enable_if<pod_dispatch<U>::value, U>::type* = 0) const;
872 
873  /// set from objects.
874  template <typename U = T>
875  void set_dispatch(size_t dest_start,
876  const const_p_teca_variant_array_impl<U> &src, size_t src_start, size_t n_elem,
877  typename std::enable_if<object_dispatch<U>::value, U>::type* = 0);
878 
879  /// set from POD types
880  template <typename U = T>
881  void set_dispatch(size_t dest_start,
882  const const_p_teca_variant_array_impl<U> &src, size_t src_start, size_t n_elem,
883  typename std::enable_if<pod_dispatch<U>::value, U>::type* = 0);
884 
885  /// copy from objects.
886  template <typename U = T>
887  void assign_dispatch(const const_p_teca_variant_array_impl<U> &src,
888  size_t src_start, size_t n_elem,
889  typename std::enable_if<object_dispatch<U>::value, U>::type* = 0);
890 
891  /// copy from POD types
892  template <typename U = T>
893  void assign_dispatch(const const_p_teca_variant_array_impl<U> &src,
894  size_t src_start, size_t n_elem,
895  typename std::enable_if<pod_dispatch<U>::value, U>::type* = 0);
896 
897  /// append from objects.
898  template <typename U = T>
899  void append_dispatch(const const_p_teca_variant_array_impl<U> &src,
900  size_t src_start, size_t n_elem,
901  typename std::enable_if<object_dispatch<U>::value, U>::type* = 0);
902 
903  /// append from POD types
904  template <typename U = T>
905  void append_dispatch(const const_p_teca_variant_array_impl<U> &src,
906  size_t src_start, size_t n_elem,
907  typename std::enable_if<pod_dispatch<U>::value, U>::type* = 0);
908 
909  /// get from objects.
910  template <typename U = T>
911  void get_dispatch(size_t src_start,
912  const p_teca_variant_array &dest, size_t dest_start, size_t n_elem,
913  typename std::enable_if<object_dispatch<U>::value, U>::type* = 0) const;
914 
915  /// get from POD types
916  template <typename U = T>
917  void get_dispatch(size_t src_start,
918  const p_teca_variant_array &dest, size_t dest_start, size_t n_elem,
919  typename std::enable_if<pod_dispatch<U>::value, U>::type* = 0) const;
920 
921  /// set from objects.
922  template <typename U = T>
923  void set_dispatch(size_t dest_start,
924  const const_p_teca_variant_array &src, size_t src_start, size_t n_elem,
925  typename std::enable_if<object_dispatch<U>::value, U>::type* = 0);
926 
927  /// set from POD types
928  template <typename U = T>
929  void set_dispatch(size_t dest_start,
930  const const_p_teca_variant_array &src, size_t src_start, size_t n_elem,
931  typename std::enable_if<pod_dispatch<U>::value, U>::type* = 0);
932 
933  /// copy from objects.
934  template <typename U = T>
935  void assign_dispatch(const const_p_teca_variant_array &src,
936  size_t src_start, size_t n_elem,
937  typename std::enable_if<object_dispatch<U>::value, U>::type* = 0);
938 
939  /// copy from POD types
940  template <typename U = T>
941  void assign_dispatch(const const_p_teca_variant_array &src,
942  size_t src_start, size_t n_elem,
943  typename std::enable_if<pod_dispatch<U>::value, U>::type* = 0);
944 
945  /// append from objects.
946  template <typename U = T>
947  void append_dispatch(const const_p_teca_variant_array &src,
948  size_t src_start, size_t n_elem,
949  typename std::enable_if<object_dispatch<U>::value, U>::type* = 0);
950 
951  /// append from POD types
952  template <typename U = T>
953  void append_dispatch(const const_p_teca_variant_array &src,
954  size_t src_start, size_t n_elem,
955  typename std::enable_if<pod_dispatch<U>::value, U>::type* = 0);
956 
957  /// get from objects.
958  template <typename U = T>
959  void get_dispatch(size_t src_start,
960  U *dest, size_t dest_start, size_t n_elem,
961  typename std::enable_if<object_dispatch<U>::value, U>::type* = 0) const;
962 
963  /// get from POD types
964  template <typename U = T>
965  void get_dispatch(size_t src_start,
966  U *dest, size_t dest_start, size_t n_elem,
967  typename std::enable_if<pod_dispatch<U>::value, U>::type* = 0) const;
968 
969  /// set from objects.
970  template <typename U = T>
971  void set_dispatch(size_t dest_start,
972  const U *src, size_t src_start, size_t n_elem,
973  typename std::enable_if<object_dispatch<U>::value, U>::type* = 0);
974 
975  /// set from POD types
976  template <typename U = T>
977  void set_dispatch(size_t dest_start,
978  const U *src, size_t src_start, size_t n_elem,
979  typename std::enable_if<pod_dispatch<U>::value, U>::type* = 0);
980 
981  /// copy from objects.
982  template <typename U = T>
983  void assign_dispatch(const U *src,
984  size_t src_start, size_t n_elem,
985  typename std::enable_if<object_dispatch<U>::value, U>::type* = 0);
986 
987  /// copy from POD types
988  template <typename U = T>
989  void assign_dispatch(const U *src,
990  size_t src_start, size_t n_elem,
991  typename std::enable_if<pod_dispatch<U>::value, U>::type* = 0);
992 
993  /// append from objects.
994  template <typename U = T>
995  void append_dispatch(const U *src,
996  size_t src_start, size_t n_elem,
997  typename std::enable_if<object_dispatch<U>::value, U>::type* = 0);
998 
999  /// append from POD types
1000  template <typename U = T>
1001  void append_dispatch(const U *src,
1002  size_t src_start, size_t n_elem,
1003  typename std::enable_if<pod_dispatch<U>::value, U>::type* = 0);
1004 
1005 
1006  // tag dispatch c style array, and types that have overrides in
1007  // binary stream
1008  template <typename U = T>
1009  void to_binary(teca_binary_stream &s,
1010  typename std::enable_if<pack_array<U>::value, U>::type* = 0)
1011  const;
1012 
1013  template <typename U = T>
1014  void from_binary(teca_binary_stream &s,
1015  typename std::enable_if<pack_array<U>::value, U>::type* = 0);
1016 
1017  // tag dispatch array of other objects
1018  template <typename U = T>
1019  void to_binary(teca_binary_stream &s,
1020  typename std::enable_if<pack_object<U>::value, U>::type* = 0)
1021  const;
1022 
1023  template <typename U = T>
1024  void from_binary(teca_binary_stream &s,
1025  typename std::enable_if<pack_object<U>::value, U>::type* = 0);
1026 
1027  // tag dispatch array of pointer to other objects
1028  template <typename U = T>
1029  void to_binary(teca_binary_stream &s,
1030  typename std::enable_if<pack_object_ptr<U>::value, U>::type* = 0)
1031  const;
1032 
1033  template <typename U = T>
1034  void from_binary(teca_binary_stream &s,
1035  typename std::enable_if<pack_object_ptr<U>::value, U>::type* = 0);
1036 
1037  // ostream
1038  template <typename U = T>
1039  void to_ascii(std::ostream &s,
1040  typename std::enable_if<pack_array<U>::value, U>::type* = 0)
1041  const;
1042 
1043  template <typename U = T>
1044  void from_ascii(std::ostream &s,
1045  typename std::enable_if<pack_array<U>::value, U>::type* = 0);
1046 
1047  // tag dispatch array of other objects
1048  template <typename U = T>
1049  void to_ascii(std::ostream &s,
1050  typename std::enable_if<pack_object<U>::value, U>::type* = 0)
1051  const;
1052 
1053  template <typename U = T>
1054  void from_ascii(std::ostream &s,
1055  typename std::enable_if<pack_object<U>::value, U>::type* = 0);
1056 
1057  // tag dispatch array of pointer to other objects
1058  template <typename U = T>
1059  void to_ascii(std::ostream &s,
1060  typename std::enable_if<pack_object_ptr<U>::value, U>::type* = 0)
1061  const;
1062 
1063  template <typename U = T>
1064  void from_ascii(std::ostream &s,
1065  typename std::enable_if<pack_object_ptr<U>::value, U>::type* = 0);
1066 
1067  /// returns a code used to identify the contained type during serialization
1068  unsigned int type_code() const noexcept override;
1069 
1070  /// gets a shared pointer to this
1071  p_teca_variant_array_impl<T> shared_from_this()
1072  {
1073  return std::static_pointer_cast
1075  (teca_variant_array::shared_from_this());
1076  }
1077 
1078  /// gets a const shared pointer to this
1079  const_p_teca_variant_array_impl<T> shared_from_this() const
1080  {
1081  return std::static_pointer_cast
1083  (teca_variant_array::shared_from_this());
1084  }
1085 
1086 private:
1087  hamr::buffer<T> m_data;
1088 
1089  friend class teca_variant_array;
1090  template<typename U> friend class teca_variant_array_impl;
1091 };
1092 
1093 
1094 
1095 
1096 #pragma GCC diagnostic ignored "-Wunknown-pragmas"
1097 #pragma GCC diagnostic ignored "-Wunused-local-typedefs"
1098 
1099 // --------------------------------------------------------------------------
1100 template<typename T>
1101 void teca_variant_array::get(unsigned long i, T &val) const
1102 {
1103  this->get_dispatch(i, val);
1104 }
1105 
1106 // --------------------------------------------------------------------------
1107 template<typename T>
1108 T teca_variant_array::get(unsigned long i) const
1109 {
1110  T val = T();
1111  this->get_dispatch(i, val);
1112  return val;
1113 }
1114 
1115 // --------------------------------------------------------------------------
1116 template<typename T>
1117 void teca_variant_array::get(std::vector<T> &vals) const
1118 {
1119  this->get_dispatch(vals);
1120 }
1121 
1122 // --------------------------------------------------------------------------
1123 template<typename T>
1124 void teca_variant_array::get(size_t src_start, T *dest, size_t dest_start, size_t n_elem) const
1125 {
1126  this->get_dispatch(src_start, dest, dest_start, n_elem);
1127 }
1128 
1129 // --------------------------------------------------------------------------
1130 template<typename T>
1131 void teca_variant_array::set(unsigned long i, const T &val)
1132 {
1133  this->set_dispatch(i, val);
1134 }
1135 
1136 // --------------------------------------------------------------------------
1137 template<typename T>
1138 void teca_variant_array::set(const std::vector<T> &src)
1139 {
1140  this->set_dispatch(src);
1141 }
1142 
1143 // --------------------------------------------------------------------------
1144 template<typename T>
1145 void teca_variant_array::set(size_t dest_start, const T *src, size_t src_start, size_t n_elem)
1146 {
1147  this->set_dispatch(dest_start, src, src_start, n_elem);
1148 }
1149 
1150 // --------------------------------------------------------------------------
1151 template<typename T>
1152 void teca_variant_array::assign(const std::vector<T> &src)
1153 {
1154  this->assign_dispatch(src);
1155 }
1156 
1157 // --------------------------------------------------------------------------
1158 template<typename T>
1159 void teca_variant_array::assign(const T *src, size_t src_start, size_t n_elem)
1160 {
1161  this->assign(src, src_start, n_elem);
1162 }
1163 
1164 // --------------------------------------------------------------------------
1165 template<typename T>
1166 void teca_variant_array::append(const T &val)
1167 {
1168  this->append_dispatch(val);
1169 }
1170 
1171 // --------------------------------------------------------------------------
1172 template<typename T>
1173 void teca_variant_array::append(const std::vector<T> &src)
1174 {
1175  this->append_dispatch(src);
1176 }
1177 
1178 // --------------------------------------------------------------------------
1179 template<typename T>
1180 void teca_variant_array::append(const T *src, size_t src_start, size_t n_elem)
1181 {
1182  this->append_dispatch(src, src_start, n_elem);
1183 }
1184 
1185 // --------------------------------------------------------------------------
1186 template<typename T>
1187 void teca_variant_array::get_dispatch(unsigned long i, T &val,
1188  typename std::enable_if<object_dispatch<T>::value, T>::type*) const
1189 {
1190  // only apply when types match
1191  const teca_variant_array_impl<T> *ptthis =
1192  dynamic_cast<const teca_variant_array_impl<T>*>(this);
1193 
1194  if (ptthis)
1195  {
1196  // safe. the types match
1197  ptthis->get(i, val);
1198  return;
1199  }
1200 
1201  // types do not match
1202  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1203  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1204  << " failed")
1205 }
1206 
1207 // --------------------------------------------------------------------------
1208 template<typename T>
1209 void teca_variant_array::get_dispatch(unsigned long i, T &val,
1210  typename std::enable_if<pod_dispatch<T>::value, T>::type*) const
1211 {
1212  // apply on POD types
1214  this,
1215  TT *ptthis = dynamic_cast<TT*>(this);
1216  ptthis->get(i, val);
1217  return;
1218  )
1219 
1220  // unssuported type
1221  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1222  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1223  << " failed")
1224 }
1225 
1226 // --------------------------------------------------------------------------
1227 template<typename T>
1228 void teca_variant_array::get_dispatch(std::vector<T> &vals,
1229  typename std::enable_if<object_dispatch<T>::value, T>::type*) const
1230 {
1231  // only apply when types match
1232  const teca_variant_array_impl<T> *ptthis =
1233  dynamic_cast<const teca_variant_array_impl<T>*>(this);
1234 
1235  if (ptthis)
1236  {
1237  // safe. the types match
1238  ptthis->get(vals);
1239  return;
1240  }
1241 
1242  // types do not match
1243  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1244  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1245  << " failed")
1246 }
1247 
1248 // --------------------------------------------------------------------------
1249 template<typename T>
1250 void teca_variant_array::get_dispatch(std::vector<T> &vals,
1251  typename std::enable_if<pod_dispatch<T>::value, T>::type*) const
1252 {
1253  // apply on POD types
1255  this,
1256  TT *ptthis = dynamic_cast<TT*>(this);
1257  ptthis->get(vals);
1258  return;
1259  )
1260 
1261  // unssuported type
1262  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1263  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1264  << " failed")
1265 }
1266 
1267 // --------------------------------------------------------------------------
1268 template<typename T>
1269 void teca_variant_array::get_dispatch(size_t src_start, T *dest, size_t dest_start, size_t n_elem,
1270  typename std::enable_if<object_dispatch<T>::value, T>::type*) const
1271 {
1272  // only apply when types match
1273  const teca_variant_array_impl<T> *ptthis =
1274  dynamic_cast<const teca_variant_array_impl<T>*>(this);
1275 
1276  if (ptthis)
1277  {
1278  // safe. the types match
1279  ptthis->get(src_start, dest, dest_start, n_elem);
1280  return;
1281  }
1282 
1283  // types do not match
1284  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1285  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1286  << " failed")
1287 }
1288 
1289 // --------------------------------------------------------------------------
1290 template<typename T>
1291 void teca_variant_array::get_dispatch(size_t src_start, T *dest, size_t dest_start, size_t n_elem,
1292  typename std::enable_if<pod_dispatch<T>::value, T>::type*) const
1293 {
1294  // apply on POD types
1296  this,
1297  TT *ptthis = dynamic_cast<TT*>(this);
1298  ptthis->get(src_start, dest, dest_start, n_elem);
1299  return;
1300  )
1301 
1302  // unssuported type
1303  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1304  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1305  << " failed")
1306 }
1307 
1308 // --------------------------------------------------------------------------
1309 template<typename T>
1310 void teca_variant_array::set_dispatch(unsigned long i, const T &val,
1311  typename std::enable_if<object_dispatch<T>::value, T>::type*)
1312 {
1313  // only apply when types match
1314  teca_variant_array_impl<T> *ptthis =
1315  dynamic_cast<teca_variant_array_impl<T>*>(this);
1316 
1317  if (ptthis)
1318  {
1319  // safe. the types match
1320  ptthis->set(i, val);
1321  return;
1322  }
1323 
1324  // types do not match
1325  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1326  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1327  << " failed")
1328 }
1329 
1330 // --------------------------------------------------------------------------
1331 template<typename T>
1332 void teca_variant_array::set_dispatch(unsigned long i, const T &val,
1333  typename std::enable_if<pod_dispatch<T>::value, T>::type*)
1334 {
1335  // apply on POD types
1337  this,
1338  TT *ptthis = dynamic_cast<TT*>(this);
1339  ptthis->set(i, val);
1340  return;
1341  )
1342 
1343  // unssuported type
1344  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1345  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1346  << " failed")
1347 }
1348 
1349 // --------------------------------------------------------------------------
1350 template<typename T>
1351 void teca_variant_array::set_dispatch(const std::vector<T> &src,
1352  typename std::enable_if<object_dispatch<T>::value, T>::type*)
1353 {
1354  // only apply when types match
1355  teca_variant_array_impl<T> *ptthis =
1356  dynamic_cast<teca_variant_array_impl<T>*>(this);
1357 
1358  if (ptthis)
1359  {
1360  // safe. the types match
1361  ptthis->set(src);
1362  return;
1363  }
1364 
1365  // types do not match
1366  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1367  << typeid(T).name() <<sizeof(T) << " to " << this->get_class_name()
1368  << " failed")
1369 }
1370 
1371 // --------------------------------------------------------------------------
1372 template<typename T>
1373 void teca_variant_array::set_dispatch(const std::vector<T> &src,
1374  typename std::enable_if<pod_dispatch<T>::value, T>::type*)
1375 {
1376  // apply on POD types
1378  this,
1379  TT *ptthis = dynamic_cast<TT*>(this);
1380  ptthis->set(src);
1381  return;
1382  )
1383 
1384  // unssuported type
1385  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1386  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1387  << " failed")
1388 }
1389 
1390 // --------------------------------------------------------------------------
1391 template<typename T>
1392 void teca_variant_array::set_dispatch(size_t dest_start,
1393  const T *src, size_t src_start, size_t n_elem,
1394  typename std::enable_if<object_dispatch<T>::value, T>::type*)
1395 {
1396  // only apply when types match
1397  teca_variant_array_impl<T> *ptthis =
1398  dynamic_cast<teca_variant_array_impl<T>*>(this);
1399 
1400  if (ptthis)
1401  {
1402  // safe. the types match
1403  ptthis->set(dest_start, src, src_start, n_elem);
1404  return;
1405  }
1406 
1407  // types do not match
1408  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1409  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1410  << " failed")
1411 }
1412 
1413 // --------------------------------------------------------------------------
1414 template<typename T>
1415 void teca_variant_array::set_dispatch(size_t dest_start,
1416  const T *src, size_t src_start, size_t n_elem,
1417  typename std::enable_if<pod_dispatch<T>::value, T>::type*)
1418 {
1419  // apply on POD types
1421  this,
1422  TT *ptthis = dynamic_cast<TT*>(this);
1423  ptthis->set(dest_start, src, src_start, n_elem);
1424  return;
1425  )
1426 
1427  // unssuported type
1428  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1429  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1430  << " failed")
1431 }
1432 
1433 // --------------------------------------------------------------------------
1434 template<typename T>
1435 void teca_variant_array::assign_dispatch(const std::vector<T> &src,
1436  typename std::enable_if<object_dispatch<T>::value, T>::type*)
1437 {
1438  // only apply when types match
1439  teca_variant_array_impl<T> *ptthis =
1440  dynamic_cast<teca_variant_array_impl<T>*>(this);
1441 
1442  if (ptthis)
1443  {
1444  // safe. the types match
1445  ptthis->assign(src);
1446  return;
1447  }
1448 
1449  // types do not match
1450  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1451  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1452  << " failed")
1453 }
1454 
1455 // --------------------------------------------------------------------------
1456 template<typename T>
1457 void teca_variant_array::assign_dispatch(const std::vector<T> &src,
1458  typename std::enable_if<pod_dispatch<T>::value, T>::type*)
1459 {
1460  // apply on POD types
1462  this,
1463  TT *ptthis = dynamic_cast<TT*>(this);
1464  ptthis->assign(src);
1465  return;
1466  )
1467 
1468  // unssuported type
1469  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1470  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1471  << " failed")
1472 }
1473 
1474 // --------------------------------------------------------------------------
1475 template<typename T>
1476 void teca_variant_array::assign_dispatch(const T *src, size_t src_start,
1477  size_t n_elem, typename std::enable_if<object_dispatch<T>::value, T>::type*)
1478 {
1479  // only apply when types match
1480  teca_variant_array_impl<T> *ptthis =
1481  dynamic_cast<teca_variant_array_impl<T>*>(this);
1482 
1483  if (ptthis)
1484  {
1485  // safe. the types match
1486  ptthis->assign(src, src_start, n_elem);
1487  return;
1488  }
1489 
1490  // types do not match
1491  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1492  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1493  << " failed")
1494 }
1495 
1496 // --------------------------------------------------------------------------
1497 template<typename T>
1498 void teca_variant_array::assign_dispatch(const T *src, size_t src_start, size_t n_elem,
1499  typename std::enable_if<pod_dispatch<T>::value, T>::type*)
1500 {
1501  // apply on POD types
1503  this,
1504  TT *ptthis = dynamic_cast<TT*>(this);
1505  ptthis->assign(src, src_start, n_elem);
1506  return;
1507  )
1508 
1509  // unssuported type
1510  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1511  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1512  << " failed")
1513 }
1514 
1515 // --------------------------------------------------------------------------
1516 template<typename T>
1517 void teca_variant_array::append_dispatch(const T &val,
1518  typename std::enable_if<object_dispatch<T>::value, T>::type*)
1519 {
1520  // only apply when types match
1521  teca_variant_array_impl<T> *ptthis =
1522  dynamic_cast<teca_variant_array_impl<T>*>(this);
1523 
1524  if (ptthis)
1525  {
1526  // safe. the types match
1527  ptthis->append(val);
1528  return;
1529  }
1530 
1531  // types do not match
1532  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1533  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1534  << " failed")
1535 }
1536 
1537 // --------------------------------------------------------------------------
1538 template<typename T>
1539 void teca_variant_array::append_dispatch(const T &val,
1540  typename std::enable_if<pod_dispatch<T>::value, T>::type*)
1541 {
1542  // apply on POD types
1544  this,
1545  TT *ptthis = dynamic_cast<TT*>(this);
1546  ptthis->append(val);
1547  return;
1548  )
1549 
1550  // unssuported type
1551  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1552  << typeid(T).name() <<sizeof(T) << " to " << this->get_class_name()
1553  << " failed")
1554 }
1555 
1556 // --------------------------------------------------------------------------
1557 template<typename T>
1558 void teca_variant_array::append_dispatch(const std::vector<T> &src,
1559  typename std::enable_if<object_dispatch<T>::value, T>::type*)
1560 {
1561  // only apply when types match
1562  teca_variant_array_impl<T> *ptthis =
1563  dynamic_cast<teca_variant_array_impl<T>*>(this);
1564 
1565  if (ptthis)
1566  {
1567  // safe. the types match
1568  ptthis->append(src);
1569  return;
1570  }
1571 
1572  // types do not match
1573  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1574  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1575  << " failed")
1576 }
1577 
1578 // --------------------------------------------------------------------------
1579 template<typename T>
1580 void teca_variant_array::append_dispatch(const std::vector<T> &src,
1581  typename std::enable_if<pod_dispatch<T>::value, T>::type*)
1582 {
1583  // apply on POD types
1585  this,
1586  TT *ptthis = dynamic_cast<TT*>(this);
1587  ptthis->append(src);
1588  return;
1589  )
1590 
1591  // unssuported type
1592  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1593  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1594  << " failed")
1595 }
1596 
1597 // --------------------------------------------------------------------------
1598 template<typename T>
1599 void teca_variant_array::append_dispatch(const T *src, size_t src_start, size_t n_elem,
1600  typename std::enable_if<object_dispatch<T>::value, T>::type*)
1601 {
1602  // only apply when types match
1603  teca_variant_array_impl<T> *ptthis =
1604  dynamic_cast<teca_variant_array_impl<T>*>(this);
1605 
1606  if (ptthis)
1607  {
1608  // safe. the types match
1609  ptthis->append(src, src_start, n_elem);
1610  return;
1611  }
1612 
1613  // types do not match
1614  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1615  << typeid(T).name() << sizeof(T) << " to " << this->get_class_name()
1616  << " failed")
1617 }
1618 
1619 // --------------------------------------------------------------------------
1620 template<typename T>
1621 void teca_variant_array::append_dispatch(const T *src, size_t src_start, size_t n_elem,
1622  typename std::enable_if<pod_dispatch<T>::value, T>::type*)
1623 {
1624  // apply on POD types
1626  this,
1627  TT *ptthis = dynamic_cast<TT*>(this);
1628  ptthis->append(src, src_start, n_elem);
1629  return;
1630  )
1631 
1632  // unssuported type
1633  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1634  << typeid(T).name() <<sizeof(T) << " to " << this->get_class_name()
1635  << " failed")
1636 }
1637 
1638 
1639 
1640 
1641 // --------------------------------------------------------------------------
1642 template<typename T>
1644 {
1645  this->clear();
1646 }
1647 
1648 // --------------------------------------------------------------------------
1649 template<typename T>
1651 {
1652  return std::make_shared<teca_variant_array_impl<T>>(alloc);
1653 }
1654 
1655 // --------------------------------------------------------------------------
1656 template<typename T>
1658 {
1659  return std::make_shared<teca_variant_array_impl<T>>(alloc, n);
1660 }
1661 
1662 // --------------------------------------------------------------------------
1663 template<typename T>
1664 template<typename U>
1666  const U &v, allocator alloc)
1667 {
1668  return std::make_shared<teca_variant_array_impl<T>>(alloc, n, v);
1669 }
1670 
1671 // --------------------------------------------------------------------------
1672 template<typename T>
1673 template<typename U>
1675  const U *v, allocator alloc)
1676 {
1677  return std::make_shared<teca_variant_array_impl<T>>(alloc, n, v);
1678 }
1679 
1680 // --------------------------------------------------------------------------
1681 template<typename T>
1682 template <typename delete_func_t>
1684  T *ptr, allocator alloc, int owner, delete_func_t df)
1685 {
1686  return std::make_shared<teca_variant_array_impl<T>>
1687  (alloc, n, owner, ptr, df);
1688 }
1689 
1690 // --------------------------------------------------------------------------
1691 template<typename T>
1693 {
1694  if (alloc == allocator::same)
1695  alloc = static_cast<allocator>(m_data.get_allocator());
1696 
1697  return std::make_shared<teca_variant_array_impl<T>>
1698  (alloc, this->shared_from_this());
1699 }
1700 
1701 // --------------------------------------------------------------------------
1702 template<typename T>
1704  size_t n_elem, allocator alloc) const
1705 {
1706  if (alloc == allocator::same)
1707  alloc = static_cast<allocator>(m_data.get_allocator());
1708 
1710  std::make_shared<teca_variant_array_impl<T>>
1711  (alloc, n_elem);
1712 
1713  this->get(src_start, dest, 0, n_elem);
1714 
1715  return dest;
1716 }
1717 
1718 // --------------------------------------------------------------------------
1719 template<typename T>
1721 {
1722  if (alloc == allocator::same)
1723  alloc = static_cast<allocator>(m_data.get_allocator());
1724 
1725  return std::make_shared<teca_variant_array_impl<T>>(alloc);
1726 }
1727 
1728 // --------------------------------------------------------------------------
1729 template<typename T>
1731  allocator alloc) const
1732 {
1733  if (alloc == allocator::same)
1734  alloc = static_cast<allocator>(m_data.get_allocator());
1735 
1736  return std::make_shared<teca_variant_array_impl<T>>(alloc, n);
1737 }
1738 
1739 // --------------------------------------------------------------------------
1740 template<typename T>
1742 {
1743  // if the allocator is already in use do nothing
1744  if (this->m_data.get_allocator() == alloc)
1745  return 0;
1746 
1747  // move the data using the specified allocator
1748  hamr::buffer<T> tmp(alloc, m_data);
1749  m_data = std::move(tmp);
1750 
1751  return 0;
1752 }
1753 
1754 // --------------------------------------------------------------------------
1755 template<typename T>
1757 {
1758  p_teca_variant_array_impl<T> pt_other =
1759  std::dynamic_pointer_cast<teca_variant_array_impl<T>>(other);
1760 
1761  if (pt_other)
1762  {
1763  m_data.swap(pt_other->m_data);
1764  }
1765 
1766  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1767  << other->get_class_name() << sizeof(T) << " to " << this->get_class_name()
1768  << " failed")
1769 }
1770 
1771 // --------------------------------------------------------------------------
1772 template<typename T>
1774 {
1775  const char *element_name = typeid(T).name();
1776  size_t element_size = sizeof(T);
1777  std::ostringstream oss;
1778  oss << "teca_variant_array_impl<" << element_name
1779  << element_size << ">";
1780  return oss.str();
1781 }
1782 
1783 // --------------------------------------------------------------------------
1784 template<typename T>
1785 unsigned long teca_variant_array_impl<T>::size() const noexcept
1786 {
1787  return m_data.size();
1788 }
1789 
1790 // --------------------------------------------------------------------------
1791 template<typename T>
1793 {
1794  m_data.resize(n);
1795 }
1796 
1797 // --------------------------------------------------------------------------
1798 template<typename T>
1799 void teca_variant_array_impl<T>::resize(unsigned long n, const T &val)
1800 {
1801  m_data.resize(n, val);
1802 }
1803 
1804 // --------------------------------------------------------------------------
1805 template<typename T>
1807 {
1808  m_data.reserve(n);
1809 }
1810 
1811 // --------------------------------------------------------------------------
1812 template<typename T>
1814 {
1815  m_data.free();
1816 }
1817 
1818 // --------------------------------------------------------------------------
1819 template <typename T>
1820 template <typename U>
1821 void teca_variant_array_impl<T>::get_dispatch(size_t src_start,
1822  const p_teca_variant_array_impl<U> &dest, size_t dest_start, size_t n_elem,
1823  typename std::enable_if<object_dispatch<U>::value, U>::type*) const
1824 {
1825  // only act on arrays of the same type
1827  std::dynamic_pointer_cast<teca_variant_array_impl<T>>(dest);
1828 
1829  if (tp_dest)
1830  {
1831  m_data.get(src_start, tp_dest->m_data, dest_start, n_elem);
1832  return;
1833  }
1834 
1835  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1836  << dest->get_class_name() << " to " << this->get_class_name()
1837  << " failed")
1838 }
1839 
1840 // --------------------------------------------------------------------------
1841 template <typename T>
1842 template <typename U>
1843 void teca_variant_array_impl<T>::get_dispatch(size_t src_start,
1844  const p_teca_variant_array_impl<U> &dest, size_t dest_start, size_t n_elem,
1845  typename std::enable_if<pod_dispatch<U>::value, U>::type*) const
1846 {
1847  assert(dest->size() >= dest_start + n_elem);
1848  assert(this->size() >= src_start + n_elem);
1849  m_data.get(src_start, dest->m_data, dest_start, n_elem);
1850 }
1851 
1852 // --------------------------------------------------------------------------
1853 template <typename T>
1854 template <typename U>
1855 void teca_variant_array_impl<T>::set_dispatch(size_t dest_start,
1856  const const_p_teca_variant_array_impl<U> &src, size_t src_start, size_t n_elem,
1857  typename std::enable_if<object_dispatch<U>::value, U>::type*)
1858 {
1859  // only act on arrays of the same type
1861  std::dynamic_pointer_cast<const teca_variant_array_impl<T>>(src);
1862 
1863  if (tp_src)
1864  {
1865  m_data.set(dest_start, tp_src->m_data, src_start, n_elem);
1866 
1867  return;
1868  }
1869 
1870  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1871  << src->get_class_name() << " to " << this->get_class_name()
1872  << " failed")
1873 }
1874 
1875 // --------------------------------------------------------------------------
1876 template <typename T>
1877 template <typename U>
1878 void teca_variant_array_impl<T>::set_dispatch(size_t dest_start,
1879  const const_p_teca_variant_array_impl<U> &src, size_t src_start, size_t n_elem,
1880  typename std::enable_if<pod_dispatch<U>::value, U>::type*)
1881 {
1882  m_data.set(dest_start, src->m_data, src_start, n_elem);
1883 }
1884 
1885 // --------------------------------------------------------------------------
1886 template <typename T>
1887 template <typename U>
1889  const const_p_teca_variant_array_impl<U> &src, size_t src_start, size_t n_elem,
1890  typename std::enable_if<object_dispatch<U>::value, U>::type*)
1891 {
1892  // only act on arrays of the same type
1894  std::dynamic_pointer_cast<const teca_variant_array_impl<T>>(src);
1895 
1896  if (tp_src)
1897  {
1898  m_data.assign(tp_src->m_data, src_start, n_elem);
1899  return;
1900  }
1901 
1902  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1903  << src->get_class_name() << " to " << this->get_class_name()
1904  << " failed")
1905 }
1906 
1907 // --------------------------------------------------------------------------
1908 template <typename T>
1909 template <typename U>
1911  const const_p_teca_variant_array_impl<U> &src, size_t src_start, size_t n_elem,
1912  typename std::enable_if<pod_dispatch<U>::value, U>::type*)
1913 {
1914  m_data.assign(src->m_data, src_start, n_elem);
1915 }
1916 
1917 // --------------------------------------------------------------------------
1918 template <typename T>
1919 template <typename U>
1921  const const_p_teca_variant_array_impl<U> &src, size_t src_start, size_t n_elem,
1922  typename std::enable_if<object_dispatch<U>::value, U>::type*)
1923 {
1924  // only act on arrays of the same type
1926  std::dynamic_pointer_cast<const teca_variant_array_impl<T>>(src);
1927 
1928  if (tp_src)
1929  {
1930  m_data.append(tp_src->m_data, src_start, n_elem);
1931  return;
1932  }
1933 
1934  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1935  << src->get_class_name() << " to " << this->get_class_name()
1936  << " failed")
1937 }
1938 
1939 // --------------------------------------------------------------------------
1940 template <typename T>
1941 template <typename U>
1943  const const_p_teca_variant_array_impl<U> &src, size_t src_start, size_t n_elem,
1944  typename std::enable_if<pod_dispatch<U>::value, U>::type*)
1945 {
1946  m_data.append(src->m_data, src_start, n_elem);
1947 }
1948 
1949 // --------------------------------------------------------------------------
1950 template <typename T>
1951 template <typename U>
1952 void teca_variant_array_impl<T>::get_dispatch(size_t src_start,
1953  const p_teca_variant_array &dest, size_t dest_start, size_t n_elem,
1954  typename std::enable_if<object_dispatch<U>::value, U>::type*) const
1955 {
1956  // only act on arrays of the same type
1958  std::dynamic_pointer_cast<teca_variant_array_impl<T>>(dest);
1959 
1960  if (tp_dest)
1961  {
1962  this->get_dispatch(src_start, tp_dest, dest_start, n_elem);
1963  return;
1964  }
1965 
1966  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1967  << dest->get_class_name() << " to " << this->get_class_name()
1968  << " failed")
1969 }
1970 
1971 // --------------------------------------------------------------------------
1972 template <typename T>
1973 template <typename U>
1974 void teca_variant_array_impl<T>::get_dispatch(size_t src_start,
1975  const p_teca_variant_array &dest, size_t dest_start, size_t n_elem,
1976  typename std::enable_if<pod_dispatch<U>::value, U>::type*) const
1977 {
1979  dest.get(),
1980  std::shared_ptr<TT> tp_dest = std::static_pointer_cast<TT>(dest);
1981  this->get_dispatch(src_start, tp_dest, dest_start, n_elem);
1982  return;
1983  )
1984 
1985  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
1986  << dest->get_class_name() << " to " << this->get_class_name()
1987  << " failed")
1988 }
1989 
1990 // --------------------------------------------------------------------------
1991 template <typename T>
1992 template <typename U>
1993 void teca_variant_array_impl<T>::set_dispatch(size_t dest_start,
1994  const const_p_teca_variant_array &src, size_t src_start, size_t n_elem,
1995  typename std::enable_if<object_dispatch<U>::value, U>::type*)
1996 {
1997  // only act on arrays of the same type
1999  std::dynamic_pointer_cast<const teca_variant_array_impl<T>>(src);
2000 
2001  if (tp_src)
2002  {
2003  this->set_dispatch(dest_start, tp_src, src_start, n_elem);
2004  return;
2005  }
2006 
2007  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
2008  << src->get_class_name() << " to " << this->get_class_name()
2009  << " failed")
2010 }
2011 
2012 // --------------------------------------------------------------------------
2013 template <typename T>
2014 template <typename U>
2015 void teca_variant_array_impl<T>::set_dispatch(size_t dest_start,
2016  const const_p_teca_variant_array &src, size_t src_start, size_t n_elem,
2017  typename std::enable_if<pod_dispatch<U>::value, U>::type*)
2018 {
2020  src.get(),
2022  std::static_pointer_cast<const teca_variant_array_impl<NT>>(src);
2023  //std::shared_ptr<TT> tp_src = std::static_pointer_cast<TT>(src);
2024  this->set_dispatch(dest_start, tp_src, src_start, n_elem);
2025  return;
2026  )
2027 
2028  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
2029  << src->get_class_name() << " to " << this->get_class_name()
2030  << " failed")
2031 }
2032 
2033 // --------------------------------------------------------------------------
2034 template <typename T>
2035 template <typename U>
2037  const const_p_teca_variant_array &src, size_t src_start, size_t n_elem,
2038  typename std::enable_if<object_dispatch<U>::value, U>::type*)
2039 {
2040  // only act on arrays of the same type
2042  std::dynamic_pointer_cast<const teca_variant_array_impl<T>>(src);
2043 
2044  if (tp_src)
2045  {
2046  this->assign_dispatch(tp_src, src_start, n_elem);
2047  return;
2048  }
2049 
2050  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
2051  << src->get_class_name() << " to " << this->get_class_name()
2052  << " failed")
2053 }
2054 
2055 // --------------------------------------------------------------------------
2056 template <typename T>
2057 template <typename U>
2059  const const_p_teca_variant_array &src, size_t src_start, size_t n_elem,
2060  typename std::enable_if<pod_dispatch<U>::value, U>::type*)
2061 {
2063  src.get(),
2064  std::shared_ptr<TT> tp_src = std::static_pointer_cast<TT>(src);
2065  this->assign_dispatch(tp_src, src_start, n_elem);
2066  return;
2067  )
2068 
2069  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
2070  << src->get_class_name() << " to " << this->get_class_name()
2071  << " failed")
2072 }
2073 
2074 // --------------------------------------------------------------------------
2075 template <typename T>
2076 template <typename U>
2078  const const_p_teca_variant_array &src, size_t src_start, size_t n_elem,
2079  typename std::enable_if<object_dispatch<U>::value, U>::type*)
2080 {
2081  // only act on arrays of the same type
2083  std::dynamic_pointer_cast<const teca_variant_array_impl<T>>(src);
2084 
2085  if (tp_src)
2086  {
2087  this->append_dispatch(tp_src, src_start, n_elem);
2088  return;
2089  }
2090 
2091  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
2092  << src->get_class_name() << " to " << this->get_class_name()
2093  << " failed")
2094 }
2095 
2096 // --------------------------------------------------------------------------
2097 template <typename T>
2098 template <typename U>
2100  const const_p_teca_variant_array &src, size_t src_start, size_t n_elem,
2101  typename std::enable_if<pod_dispatch<U>::value, U>::type*)
2102 {
2104  src.get(),
2105  std::shared_ptr<TT> tp_src = std::static_pointer_cast<TT>(src);
2106  this->append_dispatch(tp_src, src_start, n_elem);
2107  return;
2108  )
2109 
2110  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
2111  << src->get_class_name() << " to " << this->get_class_name()
2112  << " failed")
2113 }
2114 
2115 // --------------------------------------------------------------------------
2116 template <typename T>
2117 template <typename U>
2118 void teca_variant_array_impl<T>::get_dispatch(size_t src_start,
2119  U *dest, size_t dest_start, size_t n_elem,
2120  typename std::enable_if<object_dispatch<U>::value, U>::type*) const
2121 {
2122  // only act on arrays of the same type
2123  const teca_variant_array_impl<U> *thisu =
2124  dynamic_cast<const teca_variant_array_impl<U>*>(this);
2125 
2126  if (thisu)
2127  {
2128  thisu->m_data.get(src_start, dest, dest_start, n_elem);
2129  return;
2130  }
2131 
2132  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
2133  << safe_class_name(this) << " to " << safe_pointer_name(dest)
2134  << " failed")
2135 }
2136 
2137 // --------------------------------------------------------------------------
2138 template <typename T>
2139 template <typename U>
2140 void teca_variant_array_impl<T>::get_dispatch(size_t src_start,
2141  U *dest, size_t dest_start, size_t n_elem,
2142  typename std::enable_if<pod_dispatch<U>::value, U>::type*) const
2143 {
2144  m_data.get(src_start, dest, dest_start, n_elem);
2145 }
2146 
2147 // --------------------------------------------------------------------------
2148 template <typename T>
2149 template <typename U>
2150 void teca_variant_array_impl<T>::set_dispatch(size_t dest_start,
2151  const U *src, size_t src_start, size_t n_elem,
2152  typename std::enable_if<object_dispatch<U>::value, U>::type*)
2153 {
2154  // only act on arrays of the same type
2156  dynamic_cast<teca_variant_array_impl<U>*>(this);
2157 
2158  if (thisu)
2159  {
2160  thisu->m_data.set(dest_start, src, src_start, n_elem);
2161  return;
2162  }
2163 
2164  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
2165  << safe_class_name(this) << " to " << safe_pointer_name(src)
2166  << " failed")
2167 }
2168 
2169 // --------------------------------------------------------------------------
2170 template <typename T>
2171 template <typename U>
2172 void teca_variant_array_impl<T>::set_dispatch(size_t dest_start,
2173  const U *src, size_t src_start, size_t n_elem,
2174  typename std::enable_if<pod_dispatch<U>::value, U>::type*)
2175 {
2176  m_data.set(dest_start, src, src_start, n_elem);
2177 }
2178 
2179 // --------------------------------------------------------------------------
2180 template <typename T>
2181 template <typename U>
2183  const U *src, size_t src_start, size_t n_elem,
2184  typename std::enable_if<object_dispatch<U>::value, U>::type*)
2185 {
2186  // only act on arrays of the same type
2188  dynamic_cast<teca_variant_array_impl<U>*>(this);
2189 
2190  if (thisu)
2191  {
2192  thisu->m_data.assign(src, src_start, n_elem);
2193  return;
2194  }
2195 
2196  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
2197  << safe_class_name(this) << " to " << safe_pointer_name(src)
2198  << " failed")
2199 }
2200 
2201 // --------------------------------------------------------------------------
2202 template <typename T>
2203 template <typename U>
2205  const U *src, size_t src_start, size_t n_elem,
2206  typename std::enable_if<pod_dispatch<U>::value, U>::type*)
2207 {
2208  m_data.assign(src, src_start, n_elem);
2209 }
2210 
2211 // --------------------------------------------------------------------------
2212 template <typename T>
2213 template <typename U>
2215  const U *src, size_t src_start, size_t n_elem,
2216  typename std::enable_if<object_dispatch<U>::value, U>::type*)
2217 {
2218  // only act on arrays of the same type
2220  dynamic_cast<teca_variant_array_impl<U>*>(this);
2221 
2222  if (thisu)
2223  {
2224  thisu->m_data.append(src, src_start, n_elem);
2225  return;
2226  }
2227 
2228  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
2229  << safe_class_name(this) << " to " << safe_pointer_name(src)
2230  << " failed")
2231 }
2232 
2233 // --------------------------------------------------------------------------
2234 template <typename T>
2235 template <typename U>
2237  const U *src, size_t src_start, size_t n_elem,
2238  typename std::enable_if<pod_dispatch<U>::value, U>::type*)
2239 {
2240  m_data.append(src, src_start, n_elem);
2241 }
2242 
2243 
2244 
2245 
2246 // --------------------------------------------------------------------------
2247 template<typename T>
2249 {
2250  using NT = T;
2251  using TT = teca_variant_array_impl<T>;
2252  const TT *other_t = dynamic_cast<const TT*>(other.get());
2253  if (other_t)
2254  {
2255  size_t n_elem = this->size();
2256 
2257  if (n_elem != other_t->size())
2258  return false;
2259 
2260  auto spthis = this->get_cpu_accessible();
2261  const NT *pthis = spthis.get();
2262 
2263  auto spother = other_t->get_cpu_accessible();
2264  const NT *pother = spother.get();
2265 
2266  for (size_t i = 0; i < n_elem; ++i)
2267  {
2268  if (pthis[i] != pother[i])
2269  return false;
2270  }
2271 
2272  return true;
2273  }
2274  TECA_FATAL_ERROR("Operation on incompatible types. The cast from "
2275  << safe_class_name(other.get()) << " to " << safe_class_name(this)
2276  << " failed")
2277  return false;
2278 }
2279 
2280 // --------------------------------------------------------------------------
2281 template<typename T>
2282  template <typename U>
2284  typename std::enable_if<pack_array<U>::value, U>::type*) const
2285 {
2286  // pack the size
2287  unsigned long long n_elem = this->size();
2288  s.pack(n_elem);
2289 
2290  // pack the data from the CPU
2291  std::shared_ptr<const T> pdata = this->get_cpu_accessible();
2292  s.pack(pdata.get(), n_elem);
2293 }
2294 
2295 // --------------------------------------------------------------------------
2296 template<typename T>
2297  template <typename U>
2299  typename std::enable_if<pack_array<U>::value, U>::type*)
2300 {
2301  // unpack the size
2302  unsigned long long n_elem = 0;
2303  s.unpack(n_elem);
2304 
2305  // allocate a buffer
2306  hamr::buffer<T> tmp(allocator::malloc, n_elem);
2307  std::shared_ptr<T> sptmp = tmp.get_cpu_accessible();
2308 
2309  // unpack the elements into the buffer
2310  s.unpack(sptmp.get(), n_elem);
2311 
2312  // update the array
2313  m_data = std::move(tmp);
2314 }
2315 
2316 // --------------------------------------------------------------------------
2317 template<typename T>
2318  template <typename U>
2320  typename std::enable_if<pack_object<U>::value, U>::type*) const
2321 {
2322  // pack the size
2323  unsigned long long n_elem = this->size();
2324  s.pack(n_elem);
2325 
2326  // pack the data from the CPU
2327  std::shared_ptr<const T> data = this->get_cpu_accessible();
2328  const T *pdata = data.get();
2329  for (unsigned long long i = 0; i < n_elem; ++i)
2330  {
2331  pdata[i].to_stream(s);
2332  }
2333 }
2334 
2335 // --------------------------------------------------------------------------
2336 template<typename T>
2337  template <typename U>
2339  teca_binary_stream &s,
2340  typename std::enable_if<pack_object<U>::value, U>::type*)
2341 {
2342  // unpack the size
2343  unsigned long long n_elem = 0;
2344  s.unpack(n_elem);
2345 
2346  // always unpack the data to the CPU
2347  std::vector<T> tmp(n_elem);
2348  for (unsigned long long i = 0; i < n_elem; ++i)
2349  {
2350  tmp[i].from_stream(s);
2351  }
2352 
2353  // copy to the active device
2354  m_data.assign(tmp.data(), 0, n_elem);
2355 }
2356 
2357 // --------------------------------------------------------------------------
2358 template<typename T>
2359  template <typename U>
2361  teca_binary_stream &s,
2362  typename std::enable_if<pack_object_ptr<U>::value, U>::type*) const
2363 {
2364  // pack the size
2365  unsigned long long n_elem = this->size();
2366  s.pack(n_elem);
2367 
2368  // pack the data from the CPU
2369  std::shared_ptr<const T> data = this->get_cpu_accessible();
2370  const T *pdata = data.get();
2371  for (unsigned long long i = 0; i < n_elem; ++i)
2372  {
2373  pdata[i]->to_stream(s);
2374  }
2375 }
2376 
2377 // --------------------------------------------------------------------------
2378 template<typename T>
2379  template <typename U>
2381  teca_binary_stream &s,
2382  typename std::enable_if<pack_object_ptr<U>::value, U>::type*)
2383 {
2384  // unpack the size
2385  unsigned long long n_elem = 0;
2386  s.unpack(n_elem);
2387 
2388  // unpack to the CPU
2389  std::vector<T> tmp(n_elem);
2390  for (unsigned long long i=0; i < n_elem; ++i)
2391  {
2392  tmp[i]->from_stream(s);
2393  }
2394 
2395  // copy to the active device
2396  m_data.assign(tmp.data(), 0, n_elem);
2397 }
2398 
2399 #define STR_DELIM(_a, _b) \
2400  (std::is_same<T, std::string>::value ? _a : _b)
2401 
2402 // --------------------------------------------------------------------------
2403 template<typename T>
2404  template <typename U>
2406  std::ostream &s,
2407  typename std::enable_if<pack_array<U>::value, U>::type*) const
2408 {
2409  size_t n_elem = this->size();
2410  if (n_elem)
2411  {
2412  // serialize from the CPU
2413  std::shared_ptr<const T> data = this->get_cpu_accessible();
2414  const T *pdata = data.get();
2415 
2416  s << STR_DELIM("\"", "") << pdata[0] << STR_DELIM("\"", "");
2417 
2418  for (size_t i = 1; i < n_elem; ++i)
2419  {
2420  s << STR_DELIM(", \"", ", ") << pdata[i] << STR_DELIM("\"", "");
2421  }
2422  }
2423 }
2424 
2425 // --------------------------------------------------------------------------
2426 template<typename T>
2427  template <typename U>
2429  std::ostream &,
2430  typename std::enable_if<pack_array<U>::value, U>::type*)
2431 {
2432  // TODO
2433 }
2434 
2435 // --------------------------------------------------------------------------
2436 template<typename T>
2437  template <typename U>
2439  std::ostream &s,
2440  typename std::enable_if<pack_object<U>::value, U>::type*) const
2441 {
2442  size_t n_elem = this->m_data.size();
2443  if (n_elem)
2444  {
2445  // serialize from the CPU
2446  std::shared_ptr<const T> data = this->get_cpu_accessible();
2447  const T *pdata = data.get();
2448 
2449  s << "{";
2450  pdata[0].to_stream(s);
2451  s << "}";
2452  for (size_t i = 1; i < n_elem; ++i)
2453  {
2454  s << ", {";
2455  pdata[i].to_stream(s);
2456  s << "}";
2457  }
2458  }
2459 }
2460 
2461 // --------------------------------------------------------------------------
2462 template<typename T>
2463  template <typename U>
2465  std::ostream &,
2466  typename std::enable_if<pack_object<U>::value, U>::type*)
2467 {
2468  // TODO
2469 }
2470 
2471 // --------------------------------------------------------------------------
2472 template<typename T>
2473  template <typename U>
2475  std::ostream &s,
2476  typename std::enable_if<pack_object_ptr<U>::value, U>::type*) const
2477 {
2478  size_t n_elem = this->m_data.size();
2479  if (n_elem)
2480  {
2481  // serialize from the CPU
2482  std::shared_ptr<const T> data = this->get_cpu_accessible();
2483  const T *pdata = data.get();
2484 
2485  s << "{";
2486  pdata[0]->to_stream(s);
2487  s << "}";
2488  for (size_t i = 1; i < n_elem; ++i)
2489  {
2490  s << ", {";
2491  pdata[i]->to_stream(s);
2492  s << "}";
2493  }
2494  }
2495 }
2496 
2497 // --------------------------------------------------------------------------
2498 template<typename T>
2499  template <typename U>
2501  std::ostream &,
2502  typename std::enable_if<pack_object_ptr<U>::value, U>::type*)
2503 {
2504  // TODO
2505 }
2506 
2507 /// @cond
2508 template <typename T>
2509 struct TECA_EXPORT teca_variant_array_code {};
2510 
2511 template <unsigned int I>
2512 struct TECA_EXPORT teca_variant_array_new {};
2513 
2514 template <unsigned int I>
2515 struct TECA_EXPORT teca_variant_array_type {};
2516 
2517 #define TECA_VARIANT_ARRAY_TT_SPEC(T, v) \
2518 template <> \
2519 struct teca_variant_array_code<T> \
2520 { \
2521  static constexpr unsigned int get() \
2522  { return v; } \
2523 }; \
2524 template <> \
2525 struct teca_variant_array_new<v> \
2526 { \
2527  using allocator = teca_variant_array::allocator; \
2528  \
2529  static p_teca_variant_array_impl<T> New(allocator alloc) \
2530  { return teca_variant_array_impl<T>::New(alloc); } \
2531 }; \
2532 template <> \
2533 struct teca_variant_array_type<v> \
2534 { \
2535  using type = T; \
2536  \
2537  static constexpr const char *name() \
2538  { return #T; } \
2539 };
2540 
2541 #define TECA_VARIANT_ARRAY_FACTORY_NEW(_v) \
2542  case _v: \
2543  return teca_variant_array_new<_v>::New(alloc);
2544 
2545 #include "teca_metadata.h"
2546 class teca_metadata;
2547 
2548 TECA_VARIANT_ARRAY_TT_SPEC(char, 1)
2549 TECA_VARIANT_ARRAY_TT_SPEC(unsigned char, 2)
2550 TECA_VARIANT_ARRAY_TT_SPEC(int, 3)
2551 TECA_VARIANT_ARRAY_TT_SPEC(unsigned int, 4)
2552 TECA_VARIANT_ARRAY_TT_SPEC(short int, 5)
2553 TECA_VARIANT_ARRAY_TT_SPEC(short unsigned int, 6)
2554 TECA_VARIANT_ARRAY_TT_SPEC(long, 7)
2555 TECA_VARIANT_ARRAY_TT_SPEC(unsigned long, 8)
2556 TECA_VARIANT_ARRAY_TT_SPEC(long long, 9)
2557 TECA_VARIANT_ARRAY_TT_SPEC(unsigned long long, 10)
2558 TECA_VARIANT_ARRAY_TT_SPEC(float, 11)
2559 TECA_VARIANT_ARRAY_TT_SPEC(double, 12)
2560 TECA_VARIANT_ARRAY_TT_SPEC(std::string, 13)
2561 TECA_VARIANT_ARRAY_TT_SPEC(teca_metadata, 14)
2562 TECA_VARIANT_ARRAY_TT_SPEC(p_teca_variant_array, 15)
2563 /// @endcond
2564 
2565 /** @brief Creates an instance of teca_variant_array_impl<T> where T is
2566  * determined from the type code.
2567  */
2569 {
2570  using allocator = teca_variant_array::allocator;
2571 
2572  /** Construct a new variant array.
2573  * @param[in] type_code the type of array to construct
2574  * @param[in] alloc the allocator to use
2575  * @returns a new variant array or a nullptr if the type_code was invalid.
2576  */
2577  static p_teca_variant_array New(unsigned int type_code,
2578  allocator alloc = allocator::malloc)
2579  {
2580  switch (type_code)
2581  {
2582  TECA_VARIANT_ARRAY_FACTORY_NEW(1)
2583  TECA_VARIANT_ARRAY_FACTORY_NEW(2)
2584  TECA_VARIANT_ARRAY_FACTORY_NEW(3)
2585  TECA_VARIANT_ARRAY_FACTORY_NEW(4)
2586  TECA_VARIANT_ARRAY_FACTORY_NEW(5)
2587  TECA_VARIANT_ARRAY_FACTORY_NEW(6)
2588  TECA_VARIANT_ARRAY_FACTORY_NEW(7)
2589  TECA_VARIANT_ARRAY_FACTORY_NEW(8)
2590  TECA_VARIANT_ARRAY_FACTORY_NEW(9)
2591  TECA_VARIANT_ARRAY_FACTORY_NEW(10)
2592  TECA_VARIANT_ARRAY_FACTORY_NEW(11)
2593  TECA_VARIANT_ARRAY_FACTORY_NEW(12)
2594  TECA_VARIANT_ARRAY_FACTORY_NEW(13)
2595  TECA_VARIANT_ARRAY_FACTORY_NEW(14)
2596  TECA_VARIANT_ARRAY_FACTORY_NEW(15)
2597  default:
2598  TECA_ERROR("Failed to create a teca_variant_array,"
2599  " unknown code " << type_code)
2600  }
2601  return nullptr;
2602  }
2603 };
2604 
2605 /// @cond
2606 #define CODE_DISPATCH_CASE(_v, _c, _code) \
2607  if (_v == _c) \
2608  { \
2609  using NT = teca_variant_array_type<_c>::type; \
2610  using TT = teca_variant_array_impl<NT>; \
2611  _code \
2612  }
2613 
2614 #define CODE_DISPATCH_I(_v, _code) \
2615  CODE_DISPATCH_CASE(_v, 1, _code) \
2616  else CODE_DISPATCH_CASE(_v, 2, _code) \
2617  else CODE_DISPATCH_CASE(_v, 3, _code) \
2618  else CODE_DISPATCH_CASE(_v, 4, _code) \
2619  else CODE_DISPATCH_CASE(_v, 5, _code) \
2620  else CODE_DISPATCH_CASE(_v, 6, _code) \
2621  else CODE_DISPATCH_CASE(_v, 7, _code) \
2622  else CODE_DISPATCH_CASE(_v, 8, _code) \
2623  else CODE_DISPATCH_CASE(_v, 9, _code) \
2624  else CODE_DISPATCH_CASE(_v, 10, _code)
2625 
2626 #define CODE_DISPATCH_FP(_v, _code) \
2627  CODE_DISPATCH_CASE(_v, 11, _code) \
2628  else CODE_DISPATCH_CASE(_v, 12, _code)
2629 
2630 #define CODE_DISPATCH_CLASS(_v, _code) \
2631  CODE_DISPATCH_CASE(_v, 13, _code) \
2632  else CODE_DISPATCH_CASE(_v, 14, _code) \
2633  else CODE_DISPATCH_CASE(_v, 15, _code)
2634 
2635 #define CODE_DISPATCH(_v, _code) \
2636  CODE_DISPATCH_I(_v, _code) \
2637  else CODE_DISPATCH_FP(_v, _code)
2638 
2639 /// @endcond
2640 
2641 // --------------------------------------------------------------------------
2642 template <typename T>
2643 unsigned int teca_variant_array_impl<T>::type_code() const noexcept
2644 {
2645  return teca_variant_array_code<T>::get();
2646 }
2647 
2648 // **************************************************************************
2649 template <typename T>
2651 T min(const const_p_teca_variant_array_impl<T> &a)
2652 {
2653  size_t n_elem = a->size();
2654  T mn = std::numeric_limits<T>::max();
2655 #if defined(TECA_HAS_CUDA)
2656  if (a->cuda_accessible())
2657  {
2658  std::shared_ptr<const T> data = a->get_cuda_accessible();
2659  thrust::device_ptr<const T> pdata(data.get());
2660  mn = thrust::reduce(pdata, pdata + n_elem, mn, thrust::minimum<T>());
2661  }
2662  else
2663  {
2664 #endif
2665  std::shared_ptr<const T> data = a->get_cuda_accessible();
2666  const T *pdata = data.get();
2667  for (size_t i = 0; i < n_elem; ++i)
2668  mn = mn > pdata[i] ? pdata[i] : mn;
2669 #if defined(TECA_HAS_CUDA)
2670  }
2671 #endif
2672  return mn;
2673 }
2674 
2675 // **************************************************************************
2676 template <typename T>
2678 T min(const p_teca_variant_array_impl<T> &a)
2679 {
2680  return min(const_p_teca_variant_array_impl<T>(a));
2681 }
2682 
2683 // **************************************************************************
2684 template <typename T>
2686 T max(const const_p_teca_variant_array_impl<T> &a)
2687 {
2688  size_t n_elem = a->size();
2689  T mx = std::numeric_limits<T>::lowest();
2690 #if defined(TECA_HAS_CUDA)
2691  if (a->cuda_accessible())
2692  {
2693  std::shared_ptr<const T> data = a->get_cuda_accessible();
2694  thrust::device_ptr<const T> pdata(data.get());
2695  mx = thrust::reduce(pdata, pdata + n_elem, mx, thrust::maximum<T>());
2696  }
2697  else
2698  {
2699 #endif
2700  std::shared_ptr<const T> data = a->get_cuda_accessible();
2701  const T *pdata = data.get();
2702  for (size_t i = 0; i < n_elem; ++i)
2703  mx = mx < pdata[i] ? pdata[i] : mx;
2704 #if defined(TECA_HAS_CUDA)
2705  }
2706 #endif
2707  return mx;
2708 }
2709 
2710 // **************************************************************************
2711 template <typename T>
2713 T max(const p_teca_variant_array_impl<T> &a)
2714 {
2715  return max(const_p_teca_variant_array_impl<T>(a));
2716 }
2717 
2718 #if defined(__CUDACC__)
2719 #pragma nv_diag_default = partial_override
2720 #endif
2721 #endif
teca_variant_array_impl::from_stream
int from_stream(std::ostream &s) override
Deserialize from the stream.
Definition: teca_variant_array_impl.h:799
teca_variant_array.h
teca_variant_array_impl::clear
void clear() noexcept override
Clear the data.
Definition: teca_variant_array_impl.h:1813
teca_binary_stream
Serialize objects into a binary stream.
Definition: teca_binary_stream.h:16
teca_variant_array_impl::get
void get(size_t i, U &val) const
Definition: teca_variant_array_impl.h:444
teca_variant_array_impl::equal
bool equal(const const_p_teca_variant_array &other) const override
virtual equivalence test
Definition: teca_variant_array_impl.h:2248
teca_metadata
A generic container for meta data in the form of name=value pairs.
Definition: teca_metadata.h:21
teca_variant_array_impl::set
void set(size_t dest_start, const const_p_teca_variant_array_impl< U > &src, size_t src_start, size_t n_elem)
Definition: teca_variant_array_impl.h:587
teca_variant_array_impl::assign
void assign(const const_p_teca_variant_array_impl< U > &src)
assign the contents from the other array.
Definition: teca_variant_array_impl.h:630
teca_variant_array_impl::set
void set(size_t i, const U &val)
Definition: teca_variant_array_impl.h:526
teca_variant_array_impl::teca_variant_array_impl
teca_variant_array_impl(allocator alloc, size_t size, int owner, T *ptr, delete_func_t df)
zero-copy construct by setting buffer contents directly
Definition: teca_variant_array_impl.h:857
teca_variant_array_impl::from_stream
int from_stream(teca_binary_stream &s) override
Deserialize from the stream.
Definition: teca_variant_array_impl.h:785
teca_variant_array_impl::debug_print
void debug_print(typename std::enable_if< std::is_arithmetic< U >::value >::type *=0) const
Print the contents of the buffer for debugging.
Definition: teca_variant_array_impl.h:807
teca_variant_array
A type erasure for array based data.
Definition: teca_variant_array.h:42
teca_variant_array_impl::append
void append(const std::vector< U > &vals)
append a vector of values
Definition: teca_variant_array_impl.h:682
const_p_teca_variant_array_impl
std::shared_ptr< const teca_variant_array_impl< T > > const_p_teca_variant_array_impl
Definition: teca_variant_array_impl.h:39
teca_variant_array::assign
virtual void assign(const const_p_teca_variant_array &src)=0
teca_variant_array_impl::swap
void swap(const p_teca_variant_array &other) override
virtual swap
Definition: teca_variant_array_impl.h:1756
teca_variant_array_impl::teca_variant_array_impl
teca_variant_array_impl(allocator alloc, size_t n_elem, const T &val)
construct with preallocated size and initialized to a specific value
Definition: teca_variant_array_impl.h:841
teca_variant_array_impl
The concrete implementation of our type agnostic container for contiguous arrays.
Definition: teca_variant_array_impl.h:39
teca_variant_array_impl::set
void set(size_t dest_start, const const_p_teca_variant_array &src, size_t src_start, size_t n_elem) override
Definition: teca_variant_array_impl.h:565
teca_variant_array_impl::reserve
void reserve(unsigned long n) override
Reserve space.
Definition: teca_variant_array_impl.h:1806
teca_variant_array_impl::get
void get(const p_teca_variant_array_impl< U > &dest) const
get the contents into the other array.
Definition: teca_variant_array_impl.h:496
teca_variant_array_impl::get
void get(size_t src_start, const p_teca_variant_array_impl< U > &dest, size_t dest_start, size_t n_elem) const
Definition: teca_variant_array_impl.h:509
TECA_FATAL_ERROR
#define TECA_FATAL_ERROR(_msg)
Definition: teca_common.h:138
teca_variant_array_impl::assign
void assign(const p_teca_variant_array_impl< U > &src)
assign the contents from the other array.
Definition: teca_variant_array_impl.h:637
teca_variant_array_impl::debug_print
void debug_print(typename std::enable_if<!std::is_arithmetic< U >::value >::type *=0) const
Print the contents of the buffer for debugging.
Definition: teca_variant_array_impl.h:812
teca_variant_array_impl::get
void get(const p_teca_variant_array &dest) const override
get the contents into the other array.
Definition: teca_variant_array_impl.h:475
teca_variant_array_impl::set
void set(const const_p_teca_variant_array &src) override
Set from the other array.
Definition: teca_variant_array_impl.h:553
object_dispatch
Definition: teca_variant_array.h:25
teca_variant_array_impl::append
void append(const U &val)
Definition: teca_variant_array_impl.h:675
teca_variant_array::get
virtual void get(const p_teca_variant_array &dest) const =0
teca_variant_array::size
virtual unsigned long size() const noexcept=0
get the number of elements in the array
teca_variant_array_impl::cuda_accessible
int cuda_accessible() const
returns true if the data is accessible from CUDA codes
Definition: teca_variant_array_impl.h:753
teca_variant_array_impl::New
static std::shared_ptr< teca_variant_array_impl< T > > New(size_t n, const U &v)
Definition: teca_variant_array_impl.h:354
teca_variant_array_impl::assign
void assign(const const_p_teca_variant_array &src, size_t src_start, size_t n_elem) override
assign a subset of the other array
Definition: teca_variant_array_impl.h:622
teca_variant_array_impl::teca_variant_array_impl
teca_variant_array_impl()
default construct (the object is unusable)
Definition: teca_variant_array_impl.h:830
teca_variant_array::allocator
hamr::buffer_allocator allocator
allocator types
Definition: teca_variant_array.h:46
teca_variant_array_impl::get
T get(size_t i) const
get a single value
Definition: teca_variant_array_impl.h:450
teca_variant_array::get_class_name
virtual std::string get_class_name() const =0
return the name of the class in a human readable form
teca_variant_array_impl::size
unsigned long size() const noexcept override
Get the current size of the data.
Definition: teca_variant_array_impl.h:1785
teca_coordinate_util::equal
bool equal(T a, T b, T relTol=equal_tt< T >::relTol(), T absTol=equal_tt< T >::absTol(), typename std::enable_if< std::is_floating_point< T >::value >::type *=0)
Definition: teca_coordinate_util.h:70
teca_common.h
teca_variant_array_impl::set
void set(const std::vector< U > &src)
set from a vector of values
Definition: teca_variant_array_impl.h:533
const_p_teca_variant_array
std::shared_ptr< const teca_variant_array > const_p_teca_variant_array
Definition: teca_variant_array.h:27
teca_variant_array_impl::assign
void assign(const std::vector< U > &src)
Definition: teca_variant_array_impl.h:603
teca_variant_array_impl::get_cpu_accessible
std::shared_ptr< T > get_cpu_accessible()
Definition: teca_variant_array_impl.h:738
teca_variant_array::new_instance
p_teca_variant_array new_instance() const
Definition: teca_variant_array.h:62
pod_dispatch
Definition: teca_variant_array.h:24
teca_variant_array::append
virtual void append(const const_p_teca_variant_array &src)=0
teca_variant_array_impl::new_instance
p_teca_variant_array new_instance(allocator alloc) const override
Returns a new instance of the same type.
Definition: teca_variant_array_impl.h:1720
teca_variant_array_impl::get
void get(size_t src_start, U *dest, size_t dest_start, size_t n_elem) const
get a range of values
Definition: teca_variant_array_impl.h:468
teca_variant_array_impl::new_copy
p_teca_variant_array new_copy(allocator alloc=allocator::malloc) const override
Returns a new instance initialized with a deep copy of this one.
Definition: teca_variant_array_impl.h:1692
teca_variant_array_impl::teca_variant_array_impl
teca_variant_array_impl(allocator alloc)
construct with a specific allocator
Definition: teca_variant_array_impl.h:833
teca_variant_array_impl::get_class_name
std::string get_class_name() const override
Returns the name of the class in a human readable form.
Definition: teca_variant_array_impl.h:1773
teca_variant_array_factory::New
static p_teca_variant_array New(unsigned int type_code, allocator alloc=allocator::malloc)
Definition: teca_variant_array_impl.h:2577
teca_variant_array::type_code
virtual unsigned int type_code() const noexcept=0
a code for the contained data type used for serialization
teca_variant_array_impl::set_allocator
int set_allocator(allocator alloc) override
Definition: teca_variant_array_impl.h:1741
teca_variant_array_impl::New
static std::shared_ptr< teca_variant_array_impl< T > > New(size_t n)
Definition: teca_variant_array_impl.h:339
teca_variant_array_impl::assign
void assign(const const_p_teca_variant_array_impl< U > &src, size_t src_start, size_t n_elem)
assign a subset of the other array
Definition: teca_variant_array_impl.h:645
teca_shared_object.h
teca_variant_array_impl::cpu_accessible
int cpu_accessible() const
returns true if the data is accessible from codes running on the CPU
Definition: teca_variant_array_impl.h:756
teca_variant_array_impl::resize
void resize(unsigned long n) override
Resize the data.
Definition: teca_variant_array_impl.h:1792
teca_variant_array_impl::teca_variant_array_impl
teca_variant_array_impl(allocator alloc, size_t n_elem, const U *vals)
construct with preallocated size and initialized to a specific value
Definition: teca_variant_array_impl.h:846
teca_variant_array::new_copy
p_teca_variant_array new_copy() const
Definition: teca_variant_array.h:101
teca_variant_array_impl::set
void set(const const_p_teca_variant_array_impl< U > &src)
Set from the other array.
Definition: teca_variant_array_impl.h:574
p_teca_variant_array
std::shared_ptr< teca_variant_array > p_teca_variant_array
Definition: teca_variant_array.h:27
teca_variant_array_impl::get
void get(size_t src_start, const p_teca_variant_array &dest, size_t dest_start, size_t n_elem) const override
Definition: teca_variant_array_impl.h:487
teca_variant_array::set
virtual void set(const const_p_teca_variant_array &src)=0
teca_variant_array_impl::get
void get(std::vector< U > &dest) const
get a vector of values
Definition: teca_variant_array_impl.h:459
teca_variant_array_impl::teca_variant_array_impl
teca_variant_array_impl(allocator alloc, size_t n_elem)
construct with preallocated size
Definition: teca_variant_array_impl.h:837
teca_variant_array_impl::assign
void assign(const const_p_teca_variant_array &src) override
assign the contents from the other array.
Definition: teca_variant_array_impl.h:616
teca_variant_array_impl::teca_variant_array_impl
teca_variant_array_impl(allocator alloc, const const_p_teca_variant_array_impl< U > &other)
copy construct from an instance of different type
Definition: teca_variant_array_impl.h:851
teca_variant_array_factory
Creates an instance of teca_variant_array_impl<T> where T is determined from the type code.
Definition: teca_variant_array_impl.h:2568
TECA_WARNING
#define TECA_WARNING(_msg)
Constructs a warning message and sends it to the stderr stream.
Definition: teca_common.h:149
teca_error::TECA_EXPORT
p_teca_error_handler error_handler TECA_EXPORT
The global error handler instance.
p_teca_variant_array_impl
std::shared_ptr< teca_variant_array_impl< T > > p_teca_variant_array_impl
Definition: teca_variant_array_impl.h:39
teca_variant_array_impl::to_stream
int to_stream(std::ostream &s) const override
Serialize to the stream.
Definition: teca_variant_array_impl.h:792
teca_variant_array_impl::append
void append(const U *src, size_t src_start, size_t n_elem)
append a range of values
Definition: teca_variant_array_impl.h:689
const_ptr
const_p_teca_variant_array_impl< T > const_ptr(const p_teca_variant_array_impl< T > &v)
Definition: teca_variant_array_impl.h:105
teca_variant_array_impl::assign
void assign(const U *src, size_t src_start, size_t n_elem)
assign a subset from the other array
Definition: teca_variant_array_impl.h:610
TECA_ERROR
#define TECA_ERROR(_msg)
Constructs an error message and sends it to the stderr stream.
Definition: teca_common.h:146
teca_variant_array_impl::copy
void copy(const const_p_teca_variant_array_impl< U > &src, size_t src_start, size_t n_elem)
copy a subset of the other array
Definition: teca_variant_array_impl.h:660
teca_variant_array_impl::New
static std::shared_ptr< teca_variant_array_impl< T > > New(size_t n, const U *v)
Definition: teca_variant_array_impl.h:370
TEMPLATE_DISPATCH
#define TEMPLATE_DISPATCH(t, p, body)
Definition: teca_variant_array_impl.h:209
teca_variant_array_impl::set
void set(size_t dest_start, const U *src, size_t src_start, size_t n_elem)
Definition: teca_variant_array_impl.h:546
teca_variant_array_impl::New
static std::shared_ptr< teca_variant_array_impl< T > > New()
Definition: teca_variant_array_impl.h:326
teca_variant_array_impl::copy
void copy(const const_p_teca_variant_array_impl< U > &src)
copy the contents from the other array.
Definition: teca_variant_array_impl.h:653