iMSTK
Interactive Medical Simulation Toolkit
imstkVecDataArray.h
1 /*
2 ** This file is part of the Interactive Medical Simulation Toolkit (iMSTK)
3 ** iMSTK is distributed under the Apache License, Version 2.0.
4 ** See accompanying NOTICE for details.
5 */
6 
7 #pragma once
8 
9 #include "imstkDataArray.h"
10 #include "imstkMath.h"
11 #include "imstkLogger.h"
12 //#include "imstkParallelReduce.h"
13 
14 namespace imstk
15 {
22 template<typename T, int N>
23 class VecDataArray : public DataArray<T>
24 {
25 public:
26  using ScalarType = T;
27  using ValueType = Eigen::Matrix<T, N, 1>;
28  static constexpr int NumComponents = N;
29 
30  class iterator
31  {
32  public:
33  using self_type = iterator;
34  using value_type = ValueType;
35  using iterator_category = std::forward_iterator_tag;
36  using difference_type = std::ptrdiff_t;
37  using pointer = ValueType*;
38  using reference = ValueType&;
39 
40  public:
41  iterator(pointer ptr, pointer end) : ptr_(ptr), end_(end) { }
42 
43  self_type operator++()
44  {
45  self_type i = *this;
46  ptr_++;
47 #ifdef IMSTK_CHECK_ARRAY_RANGE
48  if ((end_ - ptr_) < 0) { throw std::runtime_error("iterator past bounds"); }
49 #endif
50  return i;
51  }
52 
53  self_type operator++(int junk)
54  {
55  ptr_++;
56 #ifdef IMSTK_CHECK_ARRAY_RANGE
57  if ((end_ - ptr_) < 0) { throw std::runtime_error("iterator past bounds"); }
58 #endif
59  return *this;
60  }
61 
62  reference operator*() { return *ptr_; }
63 
64  pointer operator->() { return ptr_; }
65 
66  bool operator==(const self_type& rhs) const { return ptr_ == rhs.ptr_; }
67 
68  bool operator!=(const self_type& rhs) const { return ptr_ != rhs.ptr_; }
69 
70  private:
71  pointer ptr_;
72  pointer end_;
73  };
74 
76  {
77  public:
78  using self_type = const_iterator;
79  using value_type = ValueType;
80  using iterator_category = std::forward_iterator_tag;
81  using difference_type = std::ptrdiff_t;
82  using pointer = ValueType*;
83  using reference = const ValueType&;
84 
85  public:
86  const_iterator(pointer ptr, pointer end) : ptr_(ptr), end_(end) { }
87 
88  self_type operator++()
89  {
90  self_type i = *this;
91  ptr_++;
92 #ifdef IMSTK_CHECK_ARRAY_RANGE
93  if ((end_ - ptr_) < 0) { throw std::runtime_error("iterator past bounds"); }
94 #endif
95  return i;
96  }
97 
98  self_type operator++(int junk) { ptr_++; return *this; }
99 
100  reference operator*() { return *ptr_; }
101 
102  const pointer operator->() { return ptr_; }
103 
104  bool operator==(const self_type& rhs) const { return ptr_ == rhs.ptr_; }
105 
106  bool operator!=(const self_type& rhs) const { return ptr_ != rhs.ptr_; }
107 
108  private:
109  pointer ptr_;
110  pointer end_;
111  };
112 
113 public:
117  VecDataArray() : DataArray<T>(N), m_vecSize(0), m_vecCapacity(1), m_dataCast(reinterpret_cast<ValueType*>(DataArray<T>::m_data)) { }
118 
122  VecDataArray(const int size) : DataArray<T>(size * N), m_vecSize(size), m_vecCapacity(size), m_dataCast(reinterpret_cast<ValueType*>(DataArray<T>::m_data)) { }
123 
127  VecDataArray(std::initializer_list<Eigen::Matrix<T, N, 1>> list) : DataArray<T>(static_cast<int>(list.size() * N)),
128  m_vecSize(static_cast<int>(list.size())),
129  m_vecCapacity(static_cast<int>(list.size())),
130  m_dataCast(reinterpret_cast<ValueType*>(DataArray<T>::m_data))
131  {
132  int j = 0;
133  for (auto i : list)
134  {
135  m_dataCast[j] = i;
136  j++;
137  }
138  }
139 
140  VecDataArray(const VecDataArray& other)
141  {
142  DataArray<T>::m_mapped = other.m_mapped;
143  AbstractDataArray::m_size = other.m_size;
144  AbstractDataArray::m_capacity = other.m_capacity;
145  AbstractDataArray::m_scalarType = other.m_scalarType;
147  {
148  DataArray<T>::m_data = other.m_data;
149  }
150  else
151  {
152  DataArray<T>::m_data = new T[AbstractDataArray::m_capacity];
153  std::copy_n(other.m_data, AbstractDataArray::m_size, DataArray<T>::m_data);
154  }
155  m_vecSize = other.m_vecSize;
156  m_vecCapacity = other.m_vecCapacity;
157  m_dataCast = reinterpret_cast<ValueType*>(DataArray<T>::m_data);
158  }
159 
160  VecDataArray(VecDataArray&& other)
161  {
162  DataArray<T>::m_mapped = other.m_mapped;
163  AbstractDataArray::m_size = other.m_size;
164  AbstractDataArray::m_capacity = other.m_capacity;
165  m_vecSize = other.m_vecSize;
166  m_vecCapacity = other.m_vecCapacity;
167  AbstractDataArray::m_scalarType = other.m_scalarType;
168  DataArray<T>::m_data = other.m_data; // Take the others buffer
169  m_dataCast = other.m_dataCast;
170  other.m_mapped = true;
171  }
172 
173  ~VecDataArray() override = default;
174 
179  template<typename U>
181  {
183  {
184  throw(std::runtime_error("Can't cast a mapped array"));
185  }
186  VecDataArray<U, N> other;
187  other.reserve(size());
188  for (auto item : *this)
189  {
190  other.push_back(item.template cast<U>());
191  }
192  return other;
193  }
194 
195  std::shared_ptr<AbstractDataArray> cast(ScalarTypeId type) override
196  {
197  if (type == AbstractDataArray::m_scalarType)
198  {
199  return std::make_shared<VecDataArray<T, N>>(*this);
200  }
201  switch (type)
202  {
203  TemplateMacro(return (std::make_shared<VecDataArray<IMSTK_TT, N>>(cast<IMSTK_TT>())));
204  default:
205  throw(std::runtime_error("Unknown scalar type"));
206  }
207  }
208 
209 public:
213  inline void resize(const int size) override
214  {
215  // Can't resize a mapped vector
217  {
218  return;
219  }
220 
221  if (size == m_vecCapacity)
222  {
224  m_vecSize = m_vecCapacity;
225  return;
226  }
227 
228  if (size == 0)
229  {
231  m_dataCast = reinterpret_cast<ValueType*>(DataArray<T>::m_data);
232  AbstractDataArray::m_size = m_vecSize = 0;
233  }
234  else
235  {
236  DataArray<T>::resize(size * N);
237  m_dataCast = reinterpret_cast<ValueType*>(DataArray<T>::m_data);
238  m_vecSize = size;
239  m_vecCapacity = DataArray<T>::m_capacity / N;
240  }
241  }
242 
243  inline void fill(const ValueType& val) { std::fill_n(m_dataCast, m_vecSize, val); }
244 
245  inline int size() const { return m_vecSize; }
246 
247  inline void squeeze() override
248  {
250  m_dataCast = reinterpret_cast<ValueType*>(DataArray<T>::m_data);
251  m_vecCapacity = DataArray<T>::m_capacity / N;
252  }
253 
257  inline void push_back(const ValueType& val)
258  {
259  // Can't push back to a mapped vector
261  {
262  return;
263  }
264 
265  const int newVecSize = m_vecSize + 1;
266  if (newVecSize > m_vecCapacity) // If the new size exceeds capacity
267  {
268  VecDataArray::resize(m_vecCapacity * 2); // Conservative/copies values
269  }
270  m_vecSize = newVecSize;
271  AbstractDataArray::m_size = newVecSize * N;
272  m_dataCast[newVecSize - 1] = val;
273  }
274 
275  inline void push_back(const ValueType&& val) // Move
276  {
277  // Can't push back to a mapped vector
279  {
280  return;
281  }
282 
283  const int newVecSize = m_vecSize + 1;
284  if (newVecSize > m_vecCapacity) // If the new size exceeds capacity
285  {
286  VecDataArray::resize(m_vecCapacity * 2); // Conservative/copies values
287  }
288  m_vecSize = newVecSize;
289  AbstractDataArray::m_size = newVecSize * N;
290  m_dataCast[newVecSize - 1] = val;
291  }
292 
296  iterator begin() { return iterator(m_dataCast, m_dataCast + m_vecSize); }
297 
298  const_iterator begin() const { return const_iterator(m_dataCast, m_dataCast + m_vecSize); }
299 
300  iterator end() { return iterator(m_dataCast + m_vecSize, m_dataCast + m_vecSize); }
301 
302  const_iterator end() const { return const_iterator(m_dataCast + m_vecSize, m_dataCast + m_vecSize); }
303 
304  const_iterator cbegin() const { return const_iterator(m_dataCast, m_dataCast + m_vecSize); }
305 
306  const_iterator cend() const { return const_iterator(m_dataCast + m_vecSize, m_dataCast + m_vecSize); }
308 
312  inline void reserve(const int size) override
313  {
315  {
316  return;
317  }
318 
319  if (size < m_vecCapacity) { return; }
320 
321  const int currVecSize = m_vecSize;
322  const int currSize = AbstractDataArray::m_size;
323  this->resize(size); // Resize to desired capacity
324  AbstractDataArray::m_size = currSize;
325  m_vecSize = currVecSize; // Keep current size
326  }
327 
328  inline ValueType* getPointer() { return m_dataCast; }
329 
330  inline ValueType& operator[](const size_t pos)
331  {
332 #ifdef IMSTK_CHECK_ARRAY_RANGE
333  if (pos >= static_cast<size_t>(m_vecSize)) { throw std::out_of_range("Index out of range"); }
334 #endif
335  return m_dataCast[pos];
336  }
337 
338  inline const ValueType& operator[](const size_t pos) const
339  {
340 #ifdef IMSTK_CHECK_ARRAY_RANGE
341  if (pos >= static_cast<size_t>(m_vecSize)) { throw std::out_of_range("Index out of range"); }
342 #endif
343  return m_dataCast[pos];
344  }
345 
350  inline ValueType& at(const size_t pos)
351  {
352 #ifdef IMSTK_CHECK_ARRAY_RANGE
353  if (pos >= static_cast<size_t>(m_vecSize)) { throw std::out_of_range("Index out of range"); }
354 #endif
355  return m_dataCast[pos];
356  }
357 
362  inline const ValueType& at(const size_t pos) const
363  {
364 #ifdef IMSTK_CHECK_ARRAY_RANGE
365  if (pos >= static_cast<size_t>(m_vecSize)) { throw std::out_of_range("Index out of range"); }
366 #endif
367  return m_dataCast[pos];
368  }
369 
370  inline void erase(const int vecPos)
371  {
372  // If array is mapped or pos is not in bounds, don't erase
373  if (DataArray<T>::m_mapped || vecPos >= m_vecSize || vecPos < 0)
374  {
375  return;
376  }
377 
378  // If erasing the only element, clear
379  const int newSize = AbstractDataArray::m_size - N;
380  if (newSize == 0)
381  {
382  this->clear();
383  return;
384  }
385 
386  const int pos = vecPos * N; // Position in type T instead of ValueType
387 
388  if (vecPos != m_vecSize - 1)
389  {
390  std::copy_n(DataArray<T>::m_data + pos + N, AbstractDataArray::m_size - pos - N, DataArray<T>::m_data + pos);
391  }
392 
393  m_vecSize--;
394  AbstractDataArray::m_size -= N;
395  }
396 
400  template<typename U, int M>
401  VecDataArray<T, N>& operator=(std::initializer_list<Eigen::Matrix<U, M, 1>> list)
402  {
403  // If previously mapped, don't delete, just overwrite
405  {
406  delete[] DataArray<T>::m_data;
407  }
408  DataArray<T>::m_data = new T[list.size() * N];
409  m_dataCast = reinterpret_cast<ValueType*>(DataArray<T>::m_data);
410  int j = 0;
411  for (auto i : list)
412  {
413  m_dataCast[j] = i;
414  j++;
415  }
416  m_vecSize = m_vecCapacity = static_cast<int>(list.size());
417  AbstractDataArray::m_size = AbstractDataArray::m_capacity = m_vecSize * N;
418  DataArray<T>::m_mapped = false;
419  return *this;
420  }
421 
422  VecDataArray& operator=(const VecDataArray& other)
423  {
424  // Delegate to the appropriate functions while maintaining state
425  // No need to copy type as it's static and this will only be used
426  // for `=` of equivalent types
427  if (other.m_mapped)
428  {
429  setData(other.m_dataCast, other.size());
430  }
431  else
432  {
434  {
435  DataArray<T>::m_data = nullptr;
438  m_vecCapacity = 0;
439  m_vecSize = 0;
440  DataArray<T>::m_mapped = false;
441  }
442 
443  reserve(other.size());
444  std::copy_n(other.m_data, other.m_size, DataArray<T>::m_data);
445  AbstractDataArray::m_size = other.m_size;
446  m_vecSize = other.m_vecSize;
447  }
448 
449  return *this;
450  }
451 
455  /*inline Vec2d getRange(const int component) const
456  {
457  ParallelUtils::RangeFunctor<DataArray<T, N>> pObj(vec);
458  tbb::parallel_reduce(tbb::blocked_range<size_t>(0, vec.size()), pObj);
459  return pObj.getRange();
460  return Vec2d(0.0, 0.0);
461  }*/
462 
469  inline void setData(ValueType* ptr, const int size)
470  {
472  {
473  delete[] DataArray<T>::m_data;
474  }
475 
476  DataArray<T>::m_mapped = true;
477  DataArray<T>::m_data = reinterpret_cast<T*>(ptr);
478  m_dataCast = ptr;
479  AbstractDataArray::m_size = AbstractDataArray::m_capacity = size * N;
480  m_vecSize = m_vecCapacity = size;
481  }
482 
483  inline int getNumberOfComponents() const override { return N; }
484 
489  std::unique_ptr<VecDataArray<T, N>> clone()
490  {
491  return std::unique_ptr<VecDataArray<T, N>>(cloneImplementation());
492  }
493 
494 private:
495 
496  VecDataArray<T, N>* cloneImplementation()
497  {
498  return new VecDataArray<T, N>(*this);
499  };
500 
501  int m_vecSize;
502  int m_vecCapacity;
503  ValueType* m_dataCast;
504 };
505 } // namespace imstk
ValueType & at(const size_t pos)
VecDataArray(std::initializer_list< Eigen::Matrix< T, N, 1 >> list)
Constructs from intializer list.
VecDataArray(const int size)
Constructs a data array of size.
VecDataArray()
Constructs an empty data array.
VecDataArray< T, N > & operator=(std::initializer_list< Eigen::Matrix< U, M, 1 >> list)
Allow initialization from initializer list, ie: DataArray<int> arr = { 1, 2 }.
virtual void squeeze()
Resize to current size.
Compound Geometry.
void reserve(const int size) override
Allocates extra capacity, for the number of values, conservative reallocate.
void resize(const int size) override
Resize data array to hold exactly size number of values.
void push_back(const ValueType &val)
Append the data array to hold the new value, resizes if neccesary.
iterator begin()
begin(), end() to mirror std::vector
void squeeze() override
Resize to current size.
Simple dynamic array implementation that also supports event posting and viewing/facade.
void resize(const int size) override
Resize data array to hold exactly size number of values.
std::shared_ptr< AbstractDataArray > cast(ScalarTypeId type) override
Cast array to the IMSTK type on the abstract interface.
const ValueType & at(const size_t pos) const
std::unique_ptr< VecDataArray< T, N > > clone()
Polymorphic clone, shadows the declaration in the superclasss but returns own type.
VecDataArray< U, N > cast()
Templated copy the current array with a new internal data type, does not change the number of compone...
void setData(ValueType *ptr, const int size)
Computes the range of a component of the vectors elements.
bool operator==(const Color &color_lhs, const Color &color_rhs)
Comparison operator.
Definition: imstkColor.cpp:310
Color operator*(const Color &color_lhs, const Color &color_rhs)
Multiplication operators.
Definition: imstkColor.cpp:178
int getNumberOfComponents() const override
Returns the number of components.
Simple dynamic array implementation that also supports event posting and viewing/facade.