HOPS
HOPS class reference
MHO_NDArrayView.hh
Go to the documentation of this file.
1 #ifndef MHO_NDArrayView_HH__
2 #define MHO_NDArrayView_HH__
3 
4 #include <algorithm>
5 #include <array>
6 #include <cinttypes>
7 #include <cmath>
8 #include <cstdlib>
9 #include <cstring> //for memset
10 #include <stdexcept>
11 #include <string>
12 #include <vector>
13 
15 #include "MHO_Message.hh"
16 #include "MHO_Meta.hh"
17 #include "MHO_NDArrayMath.hh"
18 
19 namespace hops
20 {
21 
32 template< typename XValueType, std::size_t RANK > class MHO_NDArrayView
33 {
34  public:
35  using value_type = XValueType;
36  using index_type = std::array< std::size_t, RANK >;
37  typedef std::integral_constant< std::size_t, RANK > rank;
38 
39  //constructors
40  MHO_NDArrayView(XValueType* ptr, const std::size_t* dim, const std::size_t* strides) { Construct(ptr, dim, strides); };
41 
42  MHO_NDArrayView(const MHO_NDArrayView& obj) { Construct(obj.fDataPtr, &(obj.fDims[0]), &(obj.fStrides[0])); }
43 
44  //destructor
45  virtual ~MHO_NDArrayView(){};
46 
52  MHO_NDArrayView* Clone() { return new MHO_NDArrayView(*this); }
53 
59  void Copy(const MHO_NDArrayView& rhs)
60  {
61  //check the sizes are the same
62  bool ok = true;
63  std::size_t j = 0;
64  for(j = 0; j < RANK; j++)
65  {
66  if(fDims[j] != rhs.fDims[j])
67  {
68  ok = false;
69  break;
70  }
71  }
72  if(ok)
73  {
74  index_type idx;
75  idx.fill(0);
76  for(std::size_t i = 0; i < fSize; i++)
77  {
78  MHO_NDArrayMath::IncrementIndices< RANK >(&(fDims[0]), &(idx[0]));
79  this->ValueAt(idx) = rhs.ValueAt(idx);
80  }
81  }
82  else
83  {
84  msg_error("containers", "array view copy failed due to mismatched sizes on dimension: " << j << "." << eom);
85  }
86  }
87 
93  std::size_t GetRank() const { return RANK; }
94 
100  std::size_t GetSize() const { return fSize; };
101 
107  const std::size_t* GetDimensions() const { return &(fDims[0]); }
108 
114  void GetDimensions(std::size_t* dim) const
115  {
116  for(std::size_t i = 0; i < RANK; i++)
117  {
118  dim[i] = fDims[i];
119  }
120  }
121 
127  index_type GetDimensionArray() const { return fDims; }
128 
135  std::size_t GetDimension(std::size_t idx) const { return fDims[idx]; }
136 
142  const std::size_t* GetStrides() const { return &(fStrides[0]); }
143 
149  void GetStrides(std::size_t* strd) const
150  {
151  for(std::size_t i = 0; i < RANK; i++)
152  {
153  strd[i] = fStrides[i];
154  }
155  }
156 
162  index_type GetStrideArray() const { return fStrides; }
163 
170  std::size_t GetStride(std::size_t idx) const { return fStrides[idx]; }
171 
172 
179  template< typename... XIndexTypeS >
180  typename std::enable_if< (sizeof...(XIndexTypeS) == RANK), XValueType& >::type operator()(XIndexTypeS... idx)
181  {
182  fTmp = {{static_cast< size_t >(idx)...}};
183  return ValueAt(fTmp);
184  }
185 
192  template< typename... XIndexTypeS >
193  typename std::enable_if< (sizeof...(XIndexTypeS) == RANK), const XValueType& >::type
194  operator()(XIndexTypeS... idx) const
195  {
196  fTmp = {{static_cast< size_t >(idx)...}};
197  return ValueAt(fTmp);
198  }
199 
206  template< typename... XIndexTypeS >
207  typename std::enable_if< (sizeof...(XIndexTypeS) == RANK), XValueType& >::type at(XIndexTypeS... idx)
208  {
209  //make sure the indices are valid for the given array dimensions
210  fTmp = {{static_cast< size_t >(idx)...}};
212  {
213  return ValueAt(fTmp);
214  }
215  else
216  {
217  throw std::out_of_range("MHO_NDArrayView::at() indices out of range.");
218  }
219  }
220 
227  template< typename... XIndexTypeS >
228  typename std::enable_if< (sizeof...(XIndexTypeS) == RANK), const XValueType& >::type at(XIndexTypeS... idx) const
229  {
230  //make sure the indices are valid for the given array dimensions
231  fTmp = {{static_cast< size_t >(idx)...}};
233  {
234  return ValueAt(fTmp);
235  }
236  else
237  {
238  throw std::out_of_range("MHO_NDArrayView::at() indices out of range.");
239  }
240  }
241 
242  //assignment operator
244  {
245  if(this != &rhs)
246  {
247  Construct(rhs.fDataPtr, &(rhs.fDims[0]), &(rhs.fStrides[0]));
248  }
249  return *this;
250  }
251 
255  void SetArray(const XValueType& obj)
256  {
257  auto bit = this->begin();
258  auto eit = this->end();
259  for(auto it = bit; it != eit; ++it)
260  {
261  *it = obj;
262  }
263  }
264 
268  void ZeroArray()
269  {
270  auto bit = this->begin();
271  auto eit = this->end();
272  for(auto it = bit; it != eit; ++it)
273  {
274  *it = 0;
275  }
276  }
277 
281  std::size_t GetOffsetForIndices(const std::size_t* index)
282  {
283  return MHO_NDArrayMath::OffsetFromStrideIndex< RANK >(&(fStrides[0]), index);
284  }
285 
289  index_type GetIndicesForOffset(std::size_t offset)
290  {
291  index_type index;
292  MHO_NDArrayMath::RowMajorIndexFromOffset< RANK >(offset, &(fDims[0]), &(index[0]));
293  return index;
294  }
295 
297 
298  //simple in-place compound assignment operators (mult/add/sub)//////////
299 
303  template< typename T >
304  typename std::enable_if< std::is_same< XValueType, T >::value or std::is_integral< T >::value or
305  std::is_floating_point< T >::value,
306  MHO_NDArrayView& >::type inline
307  operator*=(T aScalar)
308  {
309  auto bit = this->begin();
310  auto eit = this->end();
311  for(auto it = bit; it != eit; ++it)
312  {
313  (*it) *= aScalar;
314  }
315  return *this;
316  }
317 
321  template< typename T >
322  typename std::enable_if< std::is_same< XValueType, T >::value or std::is_integral< T >::value or
323  std::is_floating_point< T >::value,
324  MHO_NDArrayView& >::type inline
325  operator+=(T aScalar)
326  {
327  auto bit = this->begin();
328  auto eit = this->end();
329  for(auto it = bit; it != eit; ++it)
330  {
331  (*it) += aScalar;
332  }
333  return *this;
334  }
335 
339  template< typename T >
340  typename std::enable_if< std::is_same< XValueType, T >::value or std::is_integral< T >::value or
341  std::is_floating_point< T >::value,
342  MHO_NDArrayView& >::type inline
343  operator-=(T aScalar)
344  {
345  auto bit = this->begin();
346  auto eit = this->end();
347  for(auto it = bit; it != eit; ++it)
348  {
349  (*it) -= aScalar;
350  }
351  return *this;
352  }
353 
358  {
359  if(!HaveSameNumberOfElements(this, &anArray))
360  {
361  throw std::out_of_range("MHO_NDArrayView::*= size mismatch.");
362  }
363  auto bit1 = this->begin();
364  auto bit2 = anArray.begin();
365  auto it1 = bit1;
366  auto it2 = bit2;
367  for(std::size_t i = 0; i < fSize; i++)
368  {
369  (*it1) *= (*it2);
370  ++it1;
371  ++it2;
372  }
373  return *this;
374  }
375 
380  {
381  if(!HaveSameNumberOfElements(this, &anArray))
382  {
383  throw std::out_of_range("MHO_NDArrayView::+= size mismatch.");
384  }
385  auto bit1 = this->begin();
386  auto bit2 = anArray.begin();
387  auto it1 = bit1;
388  auto it2 = bit2;
389  for(std::size_t i = 0; i < fSize; i++)
390  {
391  (*it1) += (*it2);
392  ++it1;
393  ++it2;
394  }
395  return *this;
396  }
397 
402  {
403  if(!HaveSameNumberOfElements(this, &anArray))
404  {
405  throw std::out_of_range("MHO_NDArrayView::-= size mismatch.");
406  }
407  auto bit1 = this->begin();
408  auto bit2 = anArray.begin();
409  auto it1 = bit1;
410  auto it2 = bit2;
411  for(std::size_t i = 0; i < fSize; i++)
412  {
413  (*it1) -= (*it2);
414  ++it1;
415  ++it2;
416  }
417  return *this;
418  }
419 
420  bool CheckIndexValidity(const index_type& idx) const
421  {
422  return MHO_NDArrayMath::CheckIndexValidity< RANK >(&(fDims[0]), &(idx[0]));
423  }
424 
425  XValueType& ValueAt(const index_type& idx)
426  {
427  return fDataPtr[MHO_NDArrayMath::OffsetFromStrideIndex< RANK >(&(fStrides[0]), &(idx[0]))];
428  }
429 
430  const XValueType& ValueAt(const index_type& idx) const
431  {
432  return fDataPtr[MHO_NDArrayMath::OffsetFromStrideIndex< RANK >(&(fStrides[0]), &(idx[0]))];
433  }
434 
435  protected:
436  XValueType* fDataPtr; //data for an array view is always externally managed
437  index_type fDims; //size of each dimension
438  index_type fStrides; //strides between elements in each dimension
439  uint64_t fSize; //total size of array
440  mutable index_type fTmp; //temp index workspace
441 
442  private:
443  //special constructor for when strides are pre-determined (not from array dimensions)
444  //this is only called with building a 'SliceView'
445  void Construct(XValueType* ptr, const std::size_t* dim, const std::size_t* strides)
446  {
447  //default construction (empty)
448  for(std::size_t i = 0; i < RANK; i++)
449  {
450  fDims[i] = 0;
451  fStrides[i] = 0;
452  }
453  fSize = 0;
454  fDataPtr = nullptr;
455  if(ptr == nullptr || dim == nullptr || strides == nullptr)
456  {
457  msg_error("containers", "cannot construct array slice." << eom);
458  return;
459  }
460 
461  fDataPtr = ptr;
462  //set the dimensions, and the strides directly
463  for(std::size_t i = 0; i < RANK; i++)
464  {
465  fDims[i] = dim[i];
466  fStrides[i] = strides[i];
467  }
468  fSize = MHO_NDArrayMath::TotalArraySize< RANK >(&(fDims[0]));
469  }
470 
471  //the iterator definitions //////////////////////////////////////////////////
472  public:
475 
476  iterator begin() { return iterator(fDataPtr, 0, &(fDims[0]), &(fStrides[0])); }
477 
478  iterator end() { return iterator(fDataPtr, fSize, &(fDims[0]), &(fStrides[0])); }
479 
480  iterator iterator_at(std::size_t offset)
481  {
482  return iterator(fDataPtr, std::min(offset, fSize), &(fDims[0]), &(fStrides[0]));
483  }
484 
485  const_iterator cbegin() const { return const_iterator(fDataPtr, 0, &(fDims[0]), &(fStrides[0])); }
486 
487  const_iterator cend() const { return const_iterator(fDataPtr, fSize, &(fDims[0]), &(fStrides[0])); }
488 
489  const_iterator citerator_at(std::size_t offset) const
490  {
491  return const_iterator(fDataPtr, std::min(offset, fSize), &(fDims[0]), &(fStrides[0]));
492  }
493 };
494 
495 } // namespace hops
496 
497 #endif
#define msg_error(xKEY, xCONTENT)
Definition: MHO_Message.hh:244
template meta-programming helper functions, mostly tuple access/modification
Class MHO_BidirectionalIndexedIterator.
Definition: MHO_BidirectionalIndexedIterator.hh:26
MHO_NDArrayView is a class to represent a view (slice) of a n-dimensional array Thu 13 Aug 2020 02:53...
Definition: MHO_NDArrayView.hh:33
const std::size_t * GetStrides() const
get element strides
Definition: MHO_NDArrayView.hh:142
MHO_NDArrayView & operator*=(const MHO_NDArrayView &anArray)
operator*= in place point-wise multiplication by another array
Definition: MHO_NDArrayView.hh:357
index_type GetIndicesForOffset(std::size_t offset)
invert (memory) offset into array to indexes of the associated element
Definition: MHO_NDArrayView.hh:289
MHO_NDArrayView & operator=(const MHO_NDArrayView &rhs)
Definition: MHO_NDArrayView.hh:243
index_type GetStrideArray() const
Getter for stride array.
Definition: MHO_NDArrayView.hh:162
XValueType * fDataPtr
Definition: MHO_NDArrayView.hh:436
MHO_NDArrayView(XValueType *ptr, const std::size_t *dim, const std::size_t *strides)
Definition: MHO_NDArrayView.hh:40
std::enable_if< std::is_same< XValueType, T >::value or std::is_integral< T >::value or std::is_floating_point< T >::value, MHO_NDArrayView & >::type operator-=(T aScalar)
operator-= in place subtraction by a scalar amount
Definition: MHO_NDArrayView.hh:343
std::enable_if< std::is_same< XValueType, T >::value or std::is_integral< T >::value or std::is_floating_point< T >::value, MHO_NDArrayView & >::type operator*=(T aScalar)
operator*= in place multiplication by a scalar factor
Definition: MHO_NDArrayView.hh:307
index_type fTmp
Definition: MHO_NDArrayView.hh:440
std::enable_if<(sizeof...(XIndexTypeS)==RANK), XValueType & >::type operator()(XIndexTypeS... idx)
access operator, accepts multiple indices (,,...,) but does no bounds checking
Definition: MHO_NDArrayView.hh:180
std::enable_if<(sizeof...(XIndexTypeS)==RANK), const XValueType & >::type at(XIndexTypeS... idx) const
at(): same as const operator(...) but with bounds checking with bounds checking
Definition: MHO_NDArrayView.hh:228
const XValueType & ValueAt(const index_type &idx) const
Definition: MHO_NDArrayView.hh:430
std::enable_if< std::is_same< XValueType, T >::value or std::is_integral< T >::value or std::is_floating_point< T >::value, MHO_NDArrayView & >::type operator+=(T aScalar)
operator+= in place addition by a scalar amount
Definition: MHO_NDArrayView.hh:325
MHO_BidirectionalIndexedIterator< XValueType, RANK > iterator
Definition: MHO_NDArrayView.hh:473
void Copy(const MHO_NDArrayView &rhs)
copy functionality, calling array view must have same shape as rhs
Definition: MHO_NDArrayView.hh:59
MHO_NDArrayView * Clone()
clone functionality - Creates a deep copy of this MHO_NDArrayView object.
Definition: MHO_NDArrayView.hh:52
std::size_t GetOffsetForIndices(const std::size_t *index)
compute (memory) offset into array from a set of indexes
Definition: MHO_NDArrayView.hh:281
iterator begin()
Definition: MHO_NDArrayView.hh:476
void ZeroArray()
set all elements in the array to zero
Definition: MHO_NDArrayView.hh:268
index_type fDims
Definition: MHO_NDArrayView.hh:437
void SetArray(const XValueType &obj)
set all elements in the array to a certain value
Definition: MHO_NDArrayView.hh:255
void GetDimensions(std::size_t *dim) const
get the dimensions/shape of the array
Definition: MHO_NDArrayView.hh:114
const std::size_t * GetDimensions() const
get the dimensions/shape of the array
Definition: MHO_NDArrayView.hh:107
std::array< std::size_t, RANK > index_type
Definition: MHO_NDArrayView.hh:36
std::size_t GetDimension(std::size_t idx) const
Getter for a single dimension dimension.
Definition: MHO_NDArrayView.hh:135
std::enable_if<(sizeof...(XIndexTypeS)==RANK), XValueType & >::type at(XIndexTypeS... idx)
at(): same as operator(...) but with bounds checking with bounds checking
Definition: MHO_NDArrayView.hh:207
bool CheckIndexValidity(const index_type &idx) const
Definition: MHO_NDArrayView.hh:420
iterator end()
Definition: MHO_NDArrayView.hh:478
const_iterator citerator_at(std::size_t offset) const
Definition: MHO_NDArrayView.hh:489
MHO_NDArrayView & operator+=(const MHO_NDArrayView &anArray)
operator+= in place point-wise addition by another array
Definition: MHO_NDArrayView.hh:379
XValueType & ValueAt(const index_type &idx)
Definition: MHO_NDArrayView.hh:425
std::size_t GetStride(std::size_t idx) const
Getter for stride at index.
Definition: MHO_NDArrayView.hh:170
const_iterator cend() const
Definition: MHO_NDArrayView.hh:487
index_type GetDimensionArray() const
get the dimensions/shape of the array as std::array
Definition: MHO_NDArrayView.hh:127
MHO_BidirectionalIndexedIterator< XValueType, RANK > const_iterator
Definition: MHO_NDArrayView.hh:474
XValueType value_type
Definition: MHO_NDArrayView.hh:35
uint64_t fSize
Definition: MHO_NDArrayView.hh:439
iterator iterator_at(std::size_t offset)
Definition: MHO_NDArrayView.hh:480
MHO_NDArrayView & operator-=(const MHO_NDArrayView &anArray)
operator-= in place point-wise subtraction by another array
Definition: MHO_NDArrayView.hh:401
virtual ~MHO_NDArrayView()
Definition: MHO_NDArrayView.hh:45
MHO_NDArrayView(const MHO_NDArrayView &obj)
Definition: MHO_NDArrayView.hh:42
std::enable_if<(sizeof...(XIndexTypeS)==RANK), const XValueType & >::type operator()(XIndexTypeS... idx) const
const reference access operator, accepts multiple indices (,,...,) but does no bounds checking
Definition: MHO_NDArrayView.hh:194
std::size_t GetSize() const
get the total size of the array view
Definition: MHO_NDArrayView.hh:100
void GetStrides(std::size_t *strd) const
Getter for strides array (fills passed array)
Definition: MHO_NDArrayView.hh:149
std::integral_constant< std::size_t, RANK > rank
Definition: MHO_NDArrayView.hh:37
const_iterator cbegin() const
Definition: MHO_NDArrayView.hh:485
index_type fStrides
Definition: MHO_NDArrayView.hh:438
std::size_t GetRank() const
Getter for rank of the array view.
Definition: MHO_NDArrayView.hh:93
#define min(a, b)
Definition: max555.c:9
Definition: MHO_ChannelLabeler.hh:17