Nektar++
SharedArray.hpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File SharedArray.hpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Scientific Computing and Imaging Institute,
10 // University of Utah (USA) and Department of Aeronautics, Imperial
11 // College London (UK).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description:
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #ifndef NEKTAR_LIB_UTILITIES_BASIC_UTILS_SHARED_ARRAY_HPP
36 #define NEKTAR_LIB_UTILITIES_BASIC_UTILS_SHARED_ARRAY_HPP
37 
44 
45 #include <boost/core/ignore_unused.hpp>
46 #include <boost/multi_array.hpp>
47 
48 namespace Nektar
49 {
50 class LinearSystem;
51 
52 // Forward declaration for a ConstArray constructor.
53 template <typename Dim, typename DataType> class Array;
54 
55 /// \brief 1D Array of constant elements with garbage collection and bounds
56 /// checking.
57 template <typename DataType> class Array<OneD, const DataType>
58 {
59 #ifdef WITH_PYTHON
60  struct PythonInfo
61  {
62  void *m_pyObject; // Underlying PyObject pointer
63  void (*m_callback)(void *); // Callback
64  };
65 #endif
66 public:
67  typedef DataType *ArrayType;
68  typedef const DataType &const_reference;
69  typedef DataType &reference;
70 
71  typedef const DataType *const_iterator;
72  typedef DataType *iterator;
73 
74  typedef DataType element;
75  typedef size_t size_type;
76 
77 public:
78  /// \brief Creates an empty array.
80  :
81 #ifdef WITH_PYTHON
82  m_pythonInfo(nullptr),
83 #endif
84  m_size(0), m_capacity(0), m_data(nullptr), m_count(nullptr),
85  m_offset(0)
86  {
87  CreateStorage(m_capacity);
88  }
89 
90  /// \brief Creates an array of size dim1Size.
91  ///
92  /// If DataType is a fundamental type (double, int, etc.), then the
93  /// allocated array is uninitialized. If it is any other type, each element
94  /// is initialized with DataType's default constructor.
95  explicit Array(size_type dim1Size)
96  :
97 #ifdef WITH_PYTHON
98  m_pythonInfo(nullptr),
99 #endif
100  m_size(dim1Size), m_capacity(dim1Size), m_data(nullptr),
101  m_count(nullptr), m_offset(0)
102  {
103  CreateStorage(m_capacity);
105  }
106 
107  /// \brief Creates a 1D array with each element
108  /// initialized to an initial value.
109  /// \param dim1Size The array's size.
110  /// \param initValue Each element's initial value.
111  ///
112  /// If DataType is a fundamental type (double, int, etc.),
113  /// then the initial value is copied directly into each
114  /// element. Otherwise, the DataType's copy constructor
115  /// is used to initialize each element.
116  Array(size_type dim1Size, const DataType &initValue)
117  :
118 #ifdef WITH_PYTHON
119  m_pythonInfo(nullptr),
120 #endif
121  m_size(dim1Size), m_capacity(dim1Size), m_data(nullptr),
122  m_count(nullptr), m_offset(0)
123  {
124  CreateStorage(m_capacity);
126  initValue);
127  }
128 
129  /// \brief Creates a 1D array a copies data into it.
130  /// \param dim1Size the array's size.
131  /// \param data The data to copy.
132  ///
133  /// If DataType is a fundamental type (double, int, etc.), then data is
134  /// copied directly into the underlying storage. Otherwise, the DataType's
135  /// copy constructor is used to copy each element.
136  Array(size_type dim1Size, const DataType *data)
137  :
138 #ifdef WITH_PYTHON
139  m_pythonInfo(nullptr),
140 #endif
141  m_size(dim1Size), m_capacity(dim1Size), m_data(nullptr),
142  m_count(nullptr), m_offset(0)
143  {
144  CreateStorage(m_capacity);
146  data);
147  }
148 
149  /// \brief Creates a 1D array that references rhs.
150  /// \param dim1Size The size of the array. This is useful
151  /// when you want this array to reference
152  /// a subset of the elements in rhs.
153  /// \param rhs Array to reference.
154  /// This constructor creates an array that references rhs.
155  /// Any changes to rhs will be reflected in this array.
156  /// The memory for the array will only be deallocated when
157  /// both rhs and this array have gone out of scope.
159  :
160 #ifdef WITH_PYTHON
161  m_pythonInfo(rhs.m_pythonInfo),
162 #endif
163  m_size(dim1Size), m_capacity(rhs.m_capacity), m_data(rhs.m_data),
164  m_count(rhs.m_count), m_offset(rhs.m_offset)
165  {
166  *m_count += 1;
167  ASSERTL0(m_size <= rhs.size(), "Requested size is \
168  larger than input array size.");
169  }
170 
171 #ifdef WITH_PYTHON
172  /// \brief Creates a 1D array a copies data into it.
173  /// \param dim1Size the array's size.
174  /// \param data The data to reference.
175  /// \param memory_pointer Pointer to the memory address of the array
176  /// \param python_decrement Pointer to decrementer
177  Array(size_type dim1Size, DataType *data, void *memory_pointer,
178  void (*python_decrement)(void *))
179  : m_size(dim1Size), m_capacity(dim1Size), m_data(data),
180  m_count(nullptr), m_offset(0)
181  {
182  m_count = new size_type();
183  *m_count = 1;
184 
185  m_pythonInfo = new PythonInfo *();
186  *m_pythonInfo = new PythonInfo();
187  (*m_pythonInfo)->m_callback = python_decrement;
188  (*m_pythonInfo)->m_pyObject = memory_pointer;
189  }
190 #endif
191 
192  /// \brief Creates a reference to rhs.
194  :
195 #ifdef WITH_PYTHON
196  m_pythonInfo(rhs.m_pythonInfo),
197 #endif
198  m_size(rhs.m_size), m_capacity(rhs.m_capacity), m_data(rhs.m_data),
199  m_count(rhs.m_count), m_offset(rhs.m_offset)
200  {
201  *m_count += 1;
202  }
203 
205  {
206  if (m_count == nullptr)
207  {
208  return;
209  }
210 
211  *m_count -= 1;
212  if (*m_count == 0)
213  {
214 #ifdef WITH_PYTHON
215  if (*m_pythonInfo == nullptr)
216  {
217  ArrayDestructionPolicy<DataType>::Destroy(m_data, m_capacity);
218  MemoryManager<DataType>::RawDeallocate(m_data, m_capacity);
219  }
220  else
221  {
222  (*m_pythonInfo)->m_callback((*m_pythonInfo)->m_pyObject);
223  delete *m_pythonInfo;
224  }
225 
226  delete m_pythonInfo;
227 
228 #else
229 
230  ArrayDestructionPolicy<DataType>::Destroy(m_data, m_capacity);
231  MemoryManager<DataType>::RawDeallocate(m_data, m_capacity);
232 
233 #endif
234 
235  delete m_count; // Clean up the memory used for the reference count.
236  }
237  }
238 
239  /// \brief Creates a reference to rhs.
241  const Array<OneD, const DataType> &rhs)
242  {
243  *m_count -= 1;
244  if (*m_count == 0)
245  {
246 #ifdef WITH_PYTHON
247  if (*m_pythonInfo == nullptr)
248  {
249  ArrayDestructionPolicy<DataType>::Destroy(m_data, m_capacity);
250  MemoryManager<DataType>::RawDeallocate(m_data, m_capacity);
251  }
252  else if ((*rhs.m_pythonInfo) != nullptr &&
253  (*m_pythonInfo)->m_pyObject !=
254  (*rhs.m_pythonInfo)->m_pyObject)
255  {
256  (*m_pythonInfo)->m_callback((*m_pythonInfo)->m_pyObject);
257  delete *m_pythonInfo;
258  }
259 
260  delete m_pythonInfo;
261 #else
262 
263  ArrayDestructionPolicy<DataType>::Destroy(m_data, m_capacity);
264  MemoryManager<DataType>::RawDeallocate(m_data, m_capacity);
265 #endif
266  delete m_count; // Clean up the memory used for the reference count.
267  }
268 
269  m_data = rhs.m_data;
270  m_capacity = rhs.m_capacity;
271  m_count = rhs.m_count;
272  *m_count += 1;
273  m_offset = rhs.m_offset;
274  m_size = rhs.m_size;
275 #ifdef WITH_PYTHON
276  m_pythonInfo = rhs.m_pythonInfo;
277 #endif
278  return *this;
279  }
280 
282  {
283  return m_data + m_offset;
284  }
286  {
287  return m_data + m_offset + m_size;
288  }
289 
291  {
292  ASSERTL1(i < m_size,
293  std::string("Element ") + std::to_string(i) +
294  std::string(" requested in an array of size ") +
295  std::to_string(m_size));
296  return *(m_data + i + m_offset);
297  }
298 
299  /// \brief Returns a c-style pointer to the underlying array.
300  const element *get() const
301  {
302  return m_data + m_offset;
303  }
304 
305  /// \brief Returns a c-style pointer to the underlying array.
306  const element *data() const
307  {
308  return m_data + m_offset;
309  }
310 
311  /// \brief Returns 1.
313  {
314  return 1;
315  }
316 
317  /// \brief Returns the array's size.
318  size_type size() const
319  {
320  return m_size;
321  }
322 
323  /// \brief Returns the array's size.
324  /// Deprecated
325  DEPRECATED(5.1.0, size) size_type num_elements() const
326  {
327  WARNINGL1(false, "member function num_elements() is deprecated, "
328  "use size() instead.");
329  return m_size;
330  }
331 
332  /// \brief Returns the array's capacity.
334  {
335  return m_capacity;
336  }
337 
338  /// \brief Returns the array's offset.
340  {
341  return m_offset;
342  }
343 
344  /// \brief Returns the array's reference counter.
346  {
347  return *m_count;
348  }
349 
350  /// \brief Returns true is this array and rhs overlap.
351  bool Overlaps(const Array<OneD, const DataType> &rhs) const
352  {
353  const element *start = get();
354  const element *end = start + m_size;
355 
356  const element *rhs_start = rhs.get();
357  const element *rhs_end = rhs_start + rhs.size();
358 
359  return (rhs_start >= start && rhs_start <= end) ||
360  (rhs_end >= start && rhs_end <= end);
361  }
362 
363 #ifdef WITH_PYTHON
364  bool IsPythonArray()
365  {
366  return *m_pythonInfo != nullptr;
367  }
368 
369  void ToPythonArray(void *memory_pointer, void (*python_decrement)(void *))
370  {
371  *m_pythonInfo = new PythonInfo();
372  (*m_pythonInfo)->m_callback = python_decrement;
373  (*m_pythonInfo)->m_pyObject = memory_pointer;
374  }
375 #endif
376 
377  /// \brief Creates an array with a specified offset.
378  ///
379  /// The return value will reference the same array as lhs,
380  /// but with an offset.
381  ///
382  /// For example, in the following:
383  /// \code
384  /// Array<OneD, const double> result = anArray + 10;
385  /// \endcode
386  /// result[0] == anArray[10];
387  template <typename T>
389  typename Array<OneD, T>::size_type offset);
390 
391  template <typename T>
393  const Array<OneD, T> &rhs);
394 
395 protected:
396 #ifdef WITH_PYTHON
397  PythonInfo **m_pythonInfo;
398 #endif
399 
402  DataType *m_data;
403 
404  // m_count points to an integer used as a reference count to this array's
405  // data (m_data). Previously, the reference count was stored in the first 4
406  // bytes of the m_data array.
408 
410 
411 private:
412  // struct DestroyArray
413  // {
414  // DestroyArray(unsigned int elements) :
415  // m_elements(elements) {}
416  //
417  // void operator()(DataType* p)
418  // {
419  // ArrayDestructionPolicy<DataType>::Destroy(p,
420  // m_elements); MemoryManager<DataType>::RawDeallocate(p,
421  // m_elements);
422  // }
423  // unsigned int m_elements;
424  // };
425  //
427  {
428  DataType *storage = MemoryManager<DataType>::RawAllocate(size);
429  m_data = storage;
430 
431  // Allocate an integer to hold the reference count. Note 1, all arrays
432  // that share this array's data (ie, point to m_data) will also share
433  // the m_count data. Note 2, previously m_count pointed to "(unsigned
434  // int*)storage".
435  m_count = new size_type();
436  *m_count = 1;
437 #ifdef WITH_PYTHON
438  m_pythonInfo = new PythonInfo *();
439  *m_pythonInfo = nullptr;
440 #endif
441  }
442 
443  template <typename T>
445  size_type offset)
446  {
447  Array<OneD, T> result(rhs);
448  result.m_offset += offset;
449  result.m_size = rhs.m_size - offset;
450  return result;
451  }
452 };
453 
454 /// \brief 2D array with garbage collection and bounds checking.
455 template <typename DataType> class Array<TwoD, const DataType>
456 {
457 public:
458  typedef boost::multi_array_ref<DataType, 2> ArrayType;
459  typedef typename ArrayType::const_reference const_reference;
460  typedef typename ArrayType::reference reference;
461 
462  typedef typename ArrayType::index index;
463  typedef typename ArrayType::const_iterator const_iterator;
464  typedef typename ArrayType::iterator iterator;
465 
466  typedef typename ArrayType::element element;
467  typedef typename ArrayType::size_type size_type;
468 
469 public:
470  Array() : m_data(CreateStorage<DataType>(0, 0))
471  {
472  }
473 
474  /// \brief Constructs a 2 dimensional array. The elements of the array are
475  /// not initialized.
476  Array(size_type dim1Size, size_type dim2Size)
477  : m_data(CreateStorage<DataType>(dim1Size, dim2Size))
478  {
480  m_data->num_elements());
481  }
482 
483  Array(size_type dim1Size, size_type dim2Size, const DataType &initValue)
484  : m_data(CreateStorage<DataType>(dim1Size, dim2Size))
485  {
487  m_data->data(), m_data->num_elements(), initValue);
488  }
489 
490  Array(size_type dim1Size, size_type dim2Size, const DataType *data)
491  : m_data(CreateStorage<DataType>(dim1Size, dim2Size))
492  {
494  m_data->data(), m_data->num_elements(), data);
495  }
496 
497  Array(const Array<TwoD, const DataType> &rhs) : m_data(rhs.m_data)
498  {
499  }
500 
502  const Array<TwoD, const DataType> &rhs)
503  {
504  m_data = rhs.m_data;
505  return *this;
506  }
507 
509  {
510  return m_data->begin();
511  }
513  {
514  return m_data->end();
515  }
517  {
518  return (*m_data)[i];
519  }
520  const element *get() const
521  {
522  return m_data->data();
523  }
524  const element *data() const
525  {
526  return m_data->data();
527  }
529  {
530  return m_data->num_dimensions();
531  }
532  const size_type *shape() const
533  {
534  return m_data->shape();
535  }
536  // m_data is a shared_ptr to a boost::multi_array_ref
537  size_type size() const
538  {
539  return m_data->num_elements();
540  }
541  // deprecated interface
542  DEPRECATED(5.1.0, size) size_type num_elements() const
543  {
544  WARNINGL1(false, "member function num_elements() is deprecated, "
545  "use size() instead.");
546  return m_data->num_elements();
547  }
548 
550  {
551  return m_data->shape()[0];
552  }
554  {
555  return m_data->shape()[1];
556  }
557 
558 protected:
559  std::shared_ptr<ArrayType> m_data;
560 
561 private:
562 };
563 
565 {
567 };
568 
569 /// \brief 1D Array
570 ///
571 /// \ref pageNekArrays
572 ///
573 /// Misc notes.
574 ///
575 /// Through out the 1D Array class you will see things like "using
576 /// BaseType::begin" and "using BaseType::end". This is necessary to bring the
577 /// methods from the ConstArray into scope in Array class. Typically this is
578 /// not necessary, but since we have method names which match those in the base
579 /// class, the base class names are hidden. Therefore, we have to explicitly
580 /// bring them into scope to use them.
581 template <typename DataType>
582 class Array<OneD, DataType> : public Array<OneD, const DataType>
583 {
584 public:
586  typedef typename BaseType::iterator iterator;
587  typedef typename BaseType::reference reference;
588  typedef typename BaseType::size_type size_type;
589  typedef typename BaseType::element element;
590 
591 public:
593  {
594  }
595 
596  explicit Array(size_type dim1Size) : BaseType(dim1Size)
597  {
598  }
599 
600  Array(size_type dim1Size, const DataType &initValue)
601  : BaseType(dim1Size, initValue)
602  {
603  }
604 
605  Array(size_type dim1Size, const DataType *data) : BaseType(dim1Size, data)
606  {
607  }
608 
609  Array(size_type dim1Size, const Array<OneD, DataType> &rhs)
610  : BaseType(dim1Size, rhs)
611  {
612  }
613 
615  : BaseType(dim1Size, rhs.data())
616  {
617  }
618 
620  {
621  }
622 
624  : BaseType(rhs.size(), rhs.data())
625  {
626  }
627 
628 #ifdef WITH_PYTHON
629  Array(size_type dim1Size, DataType *data, void *memory_pointer,
630  void (*python_decrement)(void *))
631  : BaseType(dim1Size, data, memory_pointer, python_decrement)
632  {
633  }
634 
635  void ToPythonArray(void *memory_pointer, void (*python_decrement)(void *))
636  {
637  BaseType::ToPythonArray(memory_pointer, python_decrement);
638  }
639 #endif
640 
642  {
643  BaseType::operator=(rhs);
644  return *this;
645  }
646 
648  const Array<OneD, DataType> &rhs, unsigned int offset)
649  {
650  Array<OneD, DataType> result(rhs);
651  result.m_offset += offset;
652  result.m_size = rhs.m_size - offset;
653  return result;
654  }
655 
657  {
659  }
661  {
662  return this->m_data + this->m_offset;
663  }
664 
665  using BaseType::end;
667  {
668  return this->m_data + this->m_offset + this->m_size;
669  }
670 
671  using BaseType::operator[];
673  {
674  ASSERTL1(static_cast<size_type>(i) < this->size(),
675  std::string("Element ") + std::to_string(i) +
676  std::string(" requested in an array of size ") +
677  std::to_string(this->size()));
678  return (get())[i];
679  }
680 
681  using BaseType::get;
683  {
684  return this->m_data + this->m_offset;
685  }
686 
687  using BaseType::data;
689  {
690  return this->m_data + this->m_offset;
691  }
692 
693  template <typename T1> friend class NekVector;
694 
695  template <typename T1, typename T3> friend class NekMatrix;
696 
697  friend class LinearSystem;
698 
699 protected:
701  : BaseType(rhs)
702  {
703  boost::ignore_unused(a);
704  }
705 
706  void ChangeSize(size_type newSize)
707  {
708  ASSERTL1(newSize <= this->m_capacity,
709  "Can't change an array size to something larger than its "
710  "capacity.");
711  this->m_size = newSize;
712  }
713 
714 private:
715 };
716 
717 /// \brief A 2D array.
718 template <typename DataType>
719 class Array<TwoD, DataType> : public Array<TwoD, const DataType>
720 {
721 public:
723  typedef typename BaseType::iterator iterator;
724  typedef typename BaseType::reference reference;
725  typedef typename BaseType::index index;
726  typedef typename BaseType::size_type size_type;
727  typedef typename BaseType::element element;
728 
729 public:
731  {
732  }
733 
734  Array(size_type dim1Size, size_type dim2Size) : BaseType(dim1Size, dim2Size)
735  {
736  }
737 
738  Array(size_type dim1Size, size_type dim2Size, const DataType &initValue)
739  : BaseType(dim1Size, dim2Size, initValue)
740  {
741  }
742 
743  Array(size_type dim1Size, size_type dim2Size, const DataType *data)
744  : BaseType(dim1Size, dim2Size, data)
745  {
746  }
747 
749  {
750  }
751 
753  {
754  BaseType::operator=(rhs);
755  return *this;
756  }
757 
758  using BaseType::begin;
760  {
761  return this->m_data->begin();
762  }
763 
764  using BaseType::end;
766  {
767  return this->m_data->end();
768  }
769 
770  using BaseType::operator[];
772  {
773  return (*this->m_data)[i];
774  }
775 
776  using BaseType::get;
778  {
779  return this->m_data->data();
780  }
781 
782  using BaseType::data;
784  {
785  return this->m_data->data();
786  }
787 
788 private:
789 };
790 
791 // compare whatever
792 template <typename T>
793 inline bool IsEqualImpl(const T &lhs, const T &rhs, std::false_type)
794 {
795  return lhs == rhs;
796 }
797 
798 // compare floating point value
799 template <typename T>
800 inline bool IsEqualImpl(const T &lhs, const T &rhs, std::true_type)
801 {
802  return LibUtilities::IsRealEqual(lhs, rhs);
803 }
804 
805 template <typename T> inline bool IsEqual(const T &lhs, const T &rhs)
806 {
807  return IsEqualImpl(lhs, rhs, std::is_floating_point<T>());
808 }
809 
810 template <typename T1, typename T2>
811 bool operator==(const Array<OneD, T1> &lhs, const Array<OneD, T2> &rhs)
812 {
813  if (lhs.size() != rhs.size())
814  {
815  return false;
816  }
817 
818  if (lhs.data() == rhs.data())
819  {
820  return true;
821  }
822 
823  typename Array<OneD, T1>::size_type size_value(lhs.size());
824  for (typename Array<OneD, T1>::size_type i = 0; i < size_value; ++i)
825  {
826  if (!IsEqual(lhs[i], rhs[i]))
827  {
828  return false;
829  }
830  }
831 
832  return true;
833 }
834 
835 template <typename T1, typename T2>
836 bool operator!=(const Array<OneD, T1> &lhs, const Array<OneD, T2> &rhs)
837 {
838  return !(lhs == rhs);
839 }
840 
841 template <typename DataType>
843  const Array<OneD, DataType> &lhs,
844  typename Array<OneD, DataType>::size_type offset)
845 {
847 }
848 
849 template <typename DataType>
851  typename Array<OneD, DataType>::size_type offset,
852  const Array<OneD, DataType> &rhs)
853 {
855 }
856 
857 template <typename ConstDataType, typename DataType>
859  Array<OneD, DataType> &dest)
860 {
861  if (dest.size() != source.size())
862  {
863  dest = Array<OneD, DataType>(source.size());
864  }
865 
866  std::copy(source.data(), source.data() + source.size(), dest.data());
867 }
868 
869 template <typename ConstDataType, typename DataType>
871  Array<OneD, DataType> &dest,
873 {
874  if (dest.size() != n)
875  {
876  dest = Array<OneD, DataType>(n);
877  }
878 
879  std::copy(source.data(), source.data() + n, dest.data());
880 }
881 
885 
886 // TODO: Consider removing this declaration
889 
890 // TODO: This declaration will be removed
891 template <class T> using TensorOfArray2D = Array<OneD, Array<OneD, T>>;
892 
893 // Temporary alias for 3D nested array. Please note that the inner arrays
894 // are not const declared. It is therefore suggested to use this alias with
895 // caution.
896 template <class T>
898 // Temporary alias for 4D nested array. Please note that the inner arrays
899 // are not const declared. It is therefore suggested to use this alias with
900 // caution.
901 template <class T>
903 // Temporary alias for 5D nested array. Please note that the inner arrays
904 // are not const declared. It is therefore suggested to use this alias with
905 // caution.
906 template <class T>
909 
910 template <typename T1, typename T2>
911 bool operator==(const Array<TwoD, T1> &lhs, const Array<TwoD, T2> &rhs)
912 {
913  if ((lhs.GetRows() != rhs.GetRows()) ||
914  (lhs.GetColumns() != rhs.GetColumns()))
915  {
916  return false;
917  }
918 
919  if (lhs.data() == rhs.data())
920  {
921  return true;
922  }
923 
924  for (typename Array<OneD, T1>::size_type i = 0; i < lhs.GetRows(); ++i)
925  {
926  for (typename Array<OneD, T1>::size_type j = 0; j < lhs.GetColumns();
927  ++j)
928  {
929  if (!IsEqual(lhs[i][j], rhs[i][j]))
930  {
931  return false;
932  }
933  }
934  }
935 
936  return true;
937 }
938 
939 template <typename T1, typename T2>
940 bool operator!=(const Array<TwoD, T1> &lhs, const Array<TwoD, T2> &rhs)
941 {
942  return !(lhs == rhs);
943 }
944 
945 namespace LibUtilities
946 {
947 static std::vector<NekDouble> NullNekDoubleVector;
948 static std::vector<unsigned int> NullUnsignedIntVector;
949 static std::vector<std::vector<NekDouble>> NullVectorNekDoubleVector = {
951 } // namespace LibUtilities
952 } // namespace Nektar
953 
954 #endif // NEKTAR_LIB_UTILITIES_BASIC_UTILS_SHARED_ARRAY_HPP
#define WARNINGL1(condition, msg)
Definition: ErrorUtil.hpp:250
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:249
reference operator[](size_type i)
Array(size_type dim1Size, const Array< OneD, DataType > &rhs)
BaseType::reference reference
Array< OneD, const DataType >::const_iterator begin() const
Array(size_type dim1Size, const DataType *data)
Array(const Array< OneD, const DataType > &rhs)
Array(const Array< OneD, const DataType > &rhs, AllowWrappingOfConstArrays a)
static Array< OneD, DataType > CreateWithOffset(const Array< OneD, DataType > &rhs, unsigned int offset)
BaseType::size_type size_type
Array(const Array< OneD, DataType > &rhs)
Array< OneD, const DataType > BaseType
Array(size_type dim1Size, const DataType &initValue)
Array(size_type dim1Size, const Array< OneD, const DataType > &rhs)
Array< OneD, DataType > & operator=(const Array< OneD, DataType > &rhs)
void ChangeSize(size_type newSize)
1D Array of constant elements with garbage collection and bounds checking.
Definition: SharedArray.hpp:58
friend Array< OneD, T > operator+(const Array< OneD, T > &lhs, typename Array< OneD, T >::size_type offset)
Creates an array with a specified offset.
Array< OneD, const DataType > & operator=(const Array< OneD, const DataType > &rhs)
Creates a reference to rhs.
const element * data() const
Returns a c-style pointer to the underlying array.
static Array< OneD, T > CreateWithOffset(const Array< OneD, T > &rhs, size_type offset)
Array(size_type dim1Size, const Array< OneD, const DataType > &rhs)
Creates a 1D array that references rhs.
friend Array< OneD, T > operator+(typename Array< OneD, T >::size_type offset, const Array< OneD, T > &rhs)
size_type GetCount() const
Returns the array's reference counter.
Array(size_type dim1Size, const DataType *data)
Creates a 1D array a copies data into it.
Array()
Creates an empty array.
Definition: SharedArray.hpp:79
bool Overlaps(const Array< OneD, const DataType > &rhs) const
Returns true is this array and rhs overlap.
Array(size_type dim1Size)
Creates an array of size dim1Size.
Definition: SharedArray.hpp:95
const_reference operator[](size_type i) const
const element * get() const
Returns a c-style pointer to the underlying array.
size_type capacity() const
Returns the array's capacity.
Array(const Array< OneD, const DataType > &rhs)
Creates a reference to rhs.
size_type size() const
Returns the array's size.
size_type num_dimensions() const
Returns 1.
DEPRECATED(5.1.0, size) size_type num_elements() const
Returns the array's size. Deprecated.
size_type GetOffset() const
Returns the array's offset.
Array(size_type dim1Size, const DataType &initValue)
Creates a 1D array with each element initialized to an initial value.
Array(const Array< TwoD, DataType > &rhs)
Array(size_type dim1Size, size_type dim2Size, const DataType *data)
BaseType::reference reference
Array< TwoD, DataType > & operator=(const Array< TwoD, DataType > &rhs)
Array(size_type dim1Size, size_type dim2Size)
Array(size_type dim1Size, size_type dim2Size, const DataType &initValue)
BaseType::size_type size_type
Array< TwoD, const DataType > BaseType
2D array with garbage collection and bounds checking.
Array(size_type dim1Size, size_type dim2Size, const DataType &initValue)
Array(size_type dim1Size, size_type dim2Size, const DataType *data)
Array< TwoD, const DataType > & operator=(const Array< TwoD, const DataType > &rhs)
ArrayType::const_reference const_reference
Array(size_type dim1Size, size_type dim2Size)
Constructs a 2 dimensional array. The elements of the array are not initialized.
std::shared_ptr< ArrayType > m_data
ArrayType::const_iterator const_iterator
boost::multi_array_ref< DataType, 2 > ArrayType
Array(const Array< TwoD, const DataType > &rhs)
DEPRECATED(5.1.0, size) size_type num_elements() const
const size_type * shape() const
const_reference operator[](index i) const
static void RawDeallocate(DataType *array, size_t NumberOfElements)
Deallocates memory allocated from RawAllocate.
static DataType * RawAllocate(size_t NumberOfElements)
Allocates a chunk of raw, uninitialized memory, capable of holding NumberOfElements objects.
def copy(self)
Definition: pycml.py:2663
static std::vector< unsigned int > NullUnsignedIntVector
static std::vector< std::vector< NekDouble > > NullVectorNekDoubleVector
static std::vector< NekDouble > NullNekDoubleVector
bool IsRealEqual(T1 &&lhs, T2 &&rhs, const unsigned int factor=NekConstants::kNekFloatCompFact)
compare reals of same type with relative tolerance
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1
std::shared_ptr< boost::multi_array_ref< DataType, Dim::Value > > CreateStorage(const ExtentListType &extent)
bool operator==(const Array< OneD, T1 > &lhs, const Array< OneD, T2 > &rhs)
AllowWrappingOfConstArrays
@ eVECTOR_WRAPPER
static Array< OneD, int > NullInt1DArray
Array< OneD, DataType > operator+(const Array< OneD, DataType > &lhs, typename Array< OneD, DataType >::size_type offset)
static Array< OneD, Array< OneD, NekDouble > > NullNekDoubleArrayOfArray
bool IsEqual(const T &lhs, const T &rhs)
static Array< OneD, Array< OneD, Array< OneD, NekDouble > > > NullNekDoubleTensorOfArray3D
bool IsEqualImpl(const T &lhs, const T &rhs, std::false_type)
void CopyArrayN(const Array< OneD, ConstDataType > &source, Array< OneD, DataType > &dest, typename Array< OneD, DataType >::size_type n)
static Array< OneD, NekDouble > NullNekDouble1DArray
bool operator!=(const Array< OneD, T1 > &lhs, const Array< OneD, T2 > &rhs)
void CopyArray(const Array< OneD, ConstDataType > &source, Array< OneD, DataType > &dest)