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 
31 template< typename XValueType, std::size_t RANK > class MHO_NDArrayView
32 {
33  public:
34  using value_type = XValueType;
35  using index_type = std::array< std::size_t, RANK >;
36  typedef std::integral_constant< std::size_t, RANK > rank;
37 
38  //constructors
39  MHO_NDArrayView(XValueType* ptr, const std::size_t* dim, const std::size_t* strides) { Construct(ptr, dim, strides); };
40 
41  MHO_NDArrayView(const MHO_NDArrayView& obj) { Construct(obj.fDataPtr, &(obj.fDims[0]), &(obj.fStrides[0])); }
42 
43  //destructor
44  virtual ~MHO_NDArrayView(){};
45 
51  MHO_NDArrayView* Clone() { return new MHO_NDArrayView(*this); }
52 
58  void Copy(const MHO_NDArrayView& rhs)
59  {
60  //check the sizes are the same
61  bool ok = true;
62  std::size_t j = 0;
63  for(j = 0; j < RANK; j++)
64  {
65  if(fDims[j] != rhs.fDims[j])
66  {
67  ok = false;
68  break;
69  }
70  }
71  if(ok)
72  {
73  index_type idx;
74  idx.fill(0);
75  for(std::size_t i = 0; i < fSize; i++)
76  {
77  MHO_NDArrayMath::IncrementIndices< RANK >(&(fDims[0]), &(idx[0]));
78  this->ValueAt(idx) = rhs.ValueAt(idx);
79  }
80  }
81  else
82  {
83  msg_error("containers", "array view copy failed due to mismatched sizes on dimension: " << j << "." << eom);
84  }
85  }
86 
92  std::size_t GetRank() const { return RANK; }
93 
99  std::size_t GetSize() const { return fSize; };
100 
106  const std::size_t* GetDimensions() const { return &(fDims[0]); }
107 
113  void GetDimensions(std::size_t* dim) const
114  {
115  for(std::size_t i = 0; i < RANK; i++)
116  {
117  dim[i] = fDims[i];
118  }
119  }
120 
126  index_type GetDimensionArray() const { return fDims; }
127 
134  std::size_t GetDimension(std::size_t idx) const { return fDims[idx]; }
135 
141  const std::size_t* GetStrides() const { return &(fStrides[0]); }
142 
148  void GetStrides(std::size_t* strd) const
149  {
150  for(std::size_t i = 0; i < RANK; i++)
151  {
152  strd[i] = fStrides[i];
153  }
154  }
155 
161  index_type GetStrideArray() const { return fStrides; }
162 
169  std::size_t GetStride(std::size_t idx) const { return fStrides[idx]; }
170 
177  template< typename... XIndexTypeS >
178  typename std::enable_if< (sizeof...(XIndexTypeS) == RANK), XValueType& >::type operator()(XIndexTypeS... idx)
179  {
180  fTmp = {{static_cast< size_t >(idx)...}};
181  return ValueAt(fTmp);
182  }
183 
190  template< typename... XIndexTypeS >
191  typename std::enable_if< (sizeof...(XIndexTypeS) == RANK), const XValueType& >::type
192  operator()(XIndexTypeS... idx) const
193  {
194  fTmp = {{static_cast< size_t >(idx)...}};
195  return ValueAt(fTmp);
196  }
197 
204  template< typename... XIndexTypeS >
205  typename std::enable_if< (sizeof...(XIndexTypeS) == RANK), XValueType& >::type at(XIndexTypeS... idx)
206  {
207  //make sure the indices are valid for the given array dimensions
208  fTmp = {{static_cast< size_t >(idx)...}};
210  {
211  return ValueAt(fTmp);
212  }
213  else
214  {
215  throw std::out_of_range("MHO_NDArrayView::at() indices out of range.");
216  }
217  }
218 
225  template< typename... XIndexTypeS >
226  typename std::enable_if< (sizeof...(XIndexTypeS) == RANK), const XValueType& >::type at(XIndexTypeS... idx) const
227  {
228  //make sure the indices are valid for the given array dimensions
229  fTmp = {{static_cast< size_t >(idx)...}};
231  {
232  return ValueAt(fTmp);
233  }
234  else
235  {
236  throw std::out_of_range("MHO_NDArrayView::at() indices out of range.");
237  }
238  }
239 
240  //assignment operator
242  {
243  if(this != &rhs)
244  {
245  Construct(rhs.fDataPtr, &(rhs.fDims[0]), &(rhs.fStrides[0]));
246  }
247  return *this;
248  }
249 
253  void SetArray(const XValueType& obj)
254  {
255  auto bit = this->begin();
256  auto eit = this->end();
257  for(auto it = bit; it != eit; ++it)
258  {
259  *it = obj;
260  }
261  }
262 
266  void ZeroArray()
267  {
268  auto bit = this->begin();
269  auto eit = this->end();
270  for(auto it = bit; it != eit; ++it)
271  {
272  *it = 0;
273  }
274  }
275 
279  std::size_t GetOffsetForIndices(const std::size_t* index)
280  {
281  return MHO_NDArrayMath::OffsetFromStrideIndex< RANK >(&(fStrides[0]), index);
282  }
283 
287  index_type GetIndicesForOffset(std::size_t offset)
288  {
289  index_type index;
290  MHO_NDArrayMath::RowMajorIndexFromOffset< RANK >(offset, &(fDims[0]), &(index[0]));
291  return index;
292  }
293 
295 
296  //simple in-place compound assignment operators (mult/add/sub)//////////
297 
301  template< typename T >
302  typename std::enable_if< std::is_same< XValueType, T >::value or std::is_integral< T >::value or
303  std::is_floating_point< T >::value,
304  MHO_NDArrayView& >::type inline
305  operator*=(T aScalar)
306  {
307  auto bit = this->begin();
308  auto eit = this->end();
309  for(auto it = bit; it != eit; ++it)
310  {
311  (*it) *= aScalar;
312  }
313  return *this;
314  }
315 
319  template< typename T >
320  typename std::enable_if< std::is_same< XValueType, T >::value or std::is_integral< T >::value or
321  std::is_floating_point< T >::value,
322  MHO_NDArrayView& >::type inline
323  operator+=(T aScalar)
324  {
325  auto bit = this->begin();
326  auto eit = this->end();
327  for(auto it = bit; it != eit; ++it)
328  {
329  (*it) += aScalar;
330  }
331  return *this;
332  }
333 
337  template< typename T >
338  typename std::enable_if< std::is_same< XValueType, T >::value or std::is_integral< T >::value or
339  std::is_floating_point< T >::value,
340  MHO_NDArrayView& >::type inline
341  operator-=(T aScalar)
342  {
343  auto bit = this->begin();
344  auto eit = this->end();
345  for(auto it = bit; it != eit; ++it)
346  {
347  (*it) -= aScalar;
348  }
349  return *this;
350  }
351 
356  {
357  if(!HaveSameNumberOfElements(this, &anArray))
358  {
359  throw std::out_of_range("MHO_NDArrayView::*= size mismatch.");
360  }
361  auto bit1 = this->begin();
362  auto bit2 = anArray.cbegin();
363  auto it1 = bit1;
364  auto it2 = bit2;
365  for(std::size_t i = 0; i < fSize; i++)
366  {
367  (*it1) *= (*it2);
368  ++it1;
369  ++it2;
370  }
371  return *this;
372  }
373 
378  {
379  if(!HaveSameNumberOfElements(this, &anArray))
380  {
381  throw std::out_of_range("MHO_NDArrayView::+= size mismatch.");
382  }
383  auto bit1 = this->begin();
384  auto bit2 = anArray.cbegin();
385  auto it1 = bit1;
386  auto it2 = bit2;
387  for(std::size_t i = 0; i < fSize; i++)
388  {
389  (*it1) += (*it2);
390  ++it1;
391  ++it2;
392  }
393  return *this;
394  }
395 
400  {
401  if(!HaveSameNumberOfElements(this, &anArray))
402  {
403  throw std::out_of_range("MHO_NDArrayView::-= size mismatch.");
404  }
405  auto bit1 = this->begin();
406  auto bit2 = anArray.cbegin();
407  auto it1 = bit1;
408  auto it2 = bit2;
409  for(std::size_t i = 0; i < fSize; i++)
410  {
411  (*it1) -= (*it2);
412  ++it1;
413  ++it2;
414  }
415  return *this;
416  }
417 
418  bool CheckIndexValidity(const index_type& idx) const
419  {
420  return MHO_NDArrayMath::CheckIndexValidity< RANK >(&(fDims[0]), &(idx[0]));
421  }
422 
423  XValueType& ValueAt(const index_type& idx)
424  {
425  return fDataPtr[MHO_NDArrayMath::OffsetFromStrideIndex< RANK >(&(fStrides[0]), &(idx[0]))];
426  }
427 
428  const XValueType& ValueAt(const index_type& idx) const
429  {
430  return fDataPtr[MHO_NDArrayMath::OffsetFromStrideIndex< RANK >(&(fStrides[0]), &(idx[0]))];
431  }
432 
433  protected:
434  XValueType* fDataPtr; //data for an array view is always externally managed
435  index_type fDims; //size of each dimension
436  index_type fStrides; //strides between elements in each dimension
437  uint64_t fSize; //total size of array
438  mutable index_type fTmp; //temp index workspace
439 
440  private:
441  //special constructor for when strides are pre-determined (not from array dimensions)
442  //this is only called with building a 'SliceView'
443  void Construct(XValueType* ptr, const std::size_t* dim, const std::size_t* strides)
444  {
445  //default construction (empty)
446  for(std::size_t i = 0; i < RANK; i++)
447  {
448  fDims[i] = 0;
449  fStrides[i] = 0;
450  }
451  fSize = 0;
452  fDataPtr = nullptr;
453  if(ptr == nullptr || dim == nullptr || strides == nullptr)
454  {
455  msg_error("containers", "cannot construct array slice." << eom);
456  return;
457  }
458 
459  fDataPtr = ptr;
460  //set the dimensions, and the strides directly
461  for(std::size_t i = 0; i < RANK; i++)
462  {
463  fDims[i] = dim[i];
464  fStrides[i] = strides[i];
465  }
466  fSize = MHO_NDArrayMath::TotalArraySize< RANK >(&(fDims[0]));
467  }
468 
469  //the iterator definitions //////////////////////////////////////////////////
470  public:
473 
474  iterator begin() { return iterator(fDataPtr, 0, &(fDims[0]), &(fStrides[0])); }
475 
476  iterator end() { return iterator(fDataPtr, fSize, &(fDims[0]), &(fStrides[0])); }
477 
478  iterator iterator_at(std::size_t offset)
479  {
480  return iterator(fDataPtr, std::min(offset, fSize), &(fDims[0]), &(fStrides[0]));
481  }
482 
483  const_iterator cbegin() const { return const_iterator(fDataPtr, 0, &(fDims[0]), &(fStrides[0])); }
484 
485  const_iterator cend() const { return const_iterator(fDataPtr, fSize, &(fDims[0]), &(fStrides[0])); }
486 
487  const_iterator citerator_at(std::size_t offset) const
488  {
489  return const_iterator(fDataPtr, std::min(offset, fSize), &(fDims[0]), &(fStrides[0]));
490  }
491 };
492 
493 } // namespace hops
494 
495 #endif
#define msg_error(xKEY, xCONTENT)
Definition: MHO_Message.hh:238
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:32
const std::size_t * GetStrides() const
get element strides
Definition: MHO_NDArrayView.hh:141
MHO_NDArrayView & operator*=(const MHO_NDArrayView &anArray)
operator*= in place point-wise multiplication by another array
Definition: MHO_NDArrayView.hh:355
index_type GetIndicesForOffset(std::size_t offset)
invert (memory) offset into array to indexes of the associated element
Definition: MHO_NDArrayView.hh:287
MHO_NDArrayView & operator=(const MHO_NDArrayView &rhs)
Definition: MHO_NDArrayView.hh:241
index_type GetStrideArray() const
Getter for stride array.
Definition: MHO_NDArrayView.hh:161
XValueType * fDataPtr
Definition: MHO_NDArrayView.hh:434
MHO_NDArrayView(XValueType *ptr, const std::size_t *dim, const std::size_t *strides)
Definition: MHO_NDArrayView.hh:39
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:341
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:305
index_type fTmp
Definition: MHO_NDArrayView.hh:438
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:178
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:226
const XValueType & ValueAt(const index_type &idx) const
Definition: MHO_NDArrayView.hh:428
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:323
MHO_BidirectionalIndexedIterator< XValueType, RANK > iterator
Definition: MHO_NDArrayView.hh:471
void Copy(const MHO_NDArrayView &rhs)
copy functionality, calling array view must have same shape as rhs
Definition: MHO_NDArrayView.hh:58
MHO_NDArrayView * Clone()
clone functionality - Creates a deep copy of this MHO_NDArrayView object.
Definition: MHO_NDArrayView.hh:51
std::size_t GetOffsetForIndices(const std::size_t *index)
compute (memory) offset into array from a set of indexes
Definition: MHO_NDArrayView.hh:279
iterator begin()
Definition: MHO_NDArrayView.hh:474
void ZeroArray()
set all elements in the array to zero
Definition: MHO_NDArrayView.hh:266
index_type fDims
Definition: MHO_NDArrayView.hh:435
void SetArray(const XValueType &obj)
set all elements in the array to a certain value
Definition: MHO_NDArrayView.hh:253
void GetDimensions(std::size_t *dim) const
get the dimensions/shape of the array
Definition: MHO_NDArrayView.hh:113
const std::size_t * GetDimensions() const
get the dimensions/shape of the array
Definition: MHO_NDArrayView.hh:106
std::array< std::size_t, RANK > index_type
Definition: MHO_NDArrayView.hh:35
std::size_t GetDimension(std::size_t idx) const
Getter for a single dimension dimension.
Definition: MHO_NDArrayView.hh:134
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:205
bool CheckIndexValidity(const index_type &idx) const
Definition: MHO_NDArrayView.hh:418
iterator end()
Definition: MHO_NDArrayView.hh:476
const_iterator citerator_at(std::size_t offset) const
Definition: MHO_NDArrayView.hh:487
MHO_NDArrayView & operator+=(const MHO_NDArrayView &anArray)
operator+= in place point-wise addition by another array
Definition: MHO_NDArrayView.hh:377
XValueType & ValueAt(const index_type &idx)
Definition: MHO_NDArrayView.hh:423
std::size_t GetStride(std::size_t idx) const
Getter for stride at index.
Definition: MHO_NDArrayView.hh:169
const_iterator cend() const
Definition: MHO_NDArrayView.hh:485
index_type GetDimensionArray() const
get the dimensions/shape of the array as std::array
Definition: MHO_NDArrayView.hh:126
MHO_BidirectionalIndexedIterator< XValueType, RANK > const_iterator
Definition: MHO_NDArrayView.hh:472
XValueType value_type
Definition: MHO_NDArrayView.hh:34
uint64_t fSize
Definition: MHO_NDArrayView.hh:437
iterator iterator_at(std::size_t offset)
Definition: MHO_NDArrayView.hh:478
MHO_NDArrayView & operator-=(const MHO_NDArrayView &anArray)
operator-= in place point-wise subtraction by another array
Definition: MHO_NDArrayView.hh:399
virtual ~MHO_NDArrayView()
Definition: MHO_NDArrayView.hh:44
MHO_NDArrayView(const MHO_NDArrayView &obj)
Definition: MHO_NDArrayView.hh:41
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:192
std::size_t GetSize() const
get the total size of the array view
Definition: MHO_NDArrayView.hh:99
void GetStrides(std::size_t *strd) const
Getter for strides array (fills passed array)
Definition: MHO_NDArrayView.hh:148
std::integral_constant< std::size_t, RANK > rank
Definition: MHO_NDArrayView.hh:36
const_iterator cbegin() const
Definition: MHO_NDArrayView.hh:483
index_type fStrides
Definition: MHO_NDArrayView.hh:436
std::size_t GetRank() const
Getter for rank of the array view.
Definition: MHO_NDArrayView.hh:92
#define min(a, b)
Definition: max555.c:9
Definition: MHO_AdhocFlagging.hh:18