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 
204 // Disable use-after-free warning with these two functions as it appears to be
205 // incorrectly triggered in GCC 12.2.
206 #if __GNUC__ == 12 && __GNUC_MINOR__ == 2
207 #pragma GCC diagnostic push
208 #pragma GCC diagnostic ignored "-Wuse-after-free"
209 #endif
211  {
212  if (m_count == nullptr)
213  {
214  return;
215  }
216 
217  *m_count -= 1;
218  if (*m_count == 0)
219  {
220 #ifdef WITH_PYTHON
221  if (*m_pythonInfo == nullptr)
222  {
223  ArrayDestructionPolicy<DataType>::Destroy(m_data, m_capacity);
224  MemoryManager<DataType>::RawDeallocate(m_data, m_capacity);
225  }
226  else
227  {
228  (*m_pythonInfo)->m_callback((*m_pythonInfo)->m_pyObject);
229  delete *m_pythonInfo;
230  }
231 
232  delete m_pythonInfo;
233  m_pythonInfo = nullptr;
234 #else
235 
236  ArrayDestructionPolicy<DataType>::Destroy(m_data, m_capacity);
237  MemoryManager<DataType>::RawDeallocate(m_data, m_capacity);
238 
239 #endif
240 
241  delete m_count; // Clean up the memory used for the reference count.
242  m_count = nullptr;
243  }
244  }
245 
246  /// \brief Creates a reference to rhs.
248  const Array<OneD, const DataType> &rhs)
249  {
250  *m_count -= 1;
251  if (*m_count == 0)
252  {
253 #ifdef WITH_PYTHON
254  if (*m_pythonInfo == nullptr)
255  {
256  ArrayDestructionPolicy<DataType>::Destroy(m_data, m_capacity);
257  MemoryManager<DataType>::RawDeallocate(m_data, m_capacity);
258  }
259  else if ((*rhs.m_pythonInfo) != nullptr &&
260  (*m_pythonInfo)->m_pyObject !=
261  (*rhs.m_pythonInfo)->m_pyObject)
262  {
263  (*m_pythonInfo)->m_callback((*m_pythonInfo)->m_pyObject);
264  delete *m_pythonInfo;
265  }
266 
267  delete m_pythonInfo;
268  m_pythonInfo = nullptr;
269 #else
270 
271  ArrayDestructionPolicy<DataType>::Destroy(m_data, m_capacity);
272  MemoryManager<DataType>::RawDeallocate(m_data, m_capacity);
273 #endif
274  delete m_count; // Clean up the memory used for the reference count.
275  m_count = nullptr;
276  }
277 
278  m_data = rhs.m_data;
279  m_capacity = rhs.m_capacity;
280  m_count = rhs.m_count;
281  *m_count += 1;
282  m_offset = rhs.m_offset;
283  m_size = rhs.m_size;
284 #ifdef WITH_PYTHON
285  m_pythonInfo = rhs.m_pythonInfo;
286 #endif
287  return *this;
288  }
289 #if __GNUC__ == 12 && __GNUC_MINOR__ == 2
290 #pragma GCC diagnostic pop
291 #endif
292 
294  {
295  return m_data + m_offset;
296  }
298  {
299  return m_data + m_offset + m_size;
300  }
301 
303  {
304  ASSERTL1(i < m_size,
305  std::string("Element ") + std::to_string(i) +
306  std::string(" requested in an array of size ") +
307  std::to_string(m_size));
308  return *(m_data + i + m_offset);
309  }
310 
311  /// \brief Returns a c-style pointer to the underlying array.
312  const element *get() const
313  {
314  return m_data + m_offset;
315  }
316 
317  /// \brief Returns a c-style pointer to the underlying array.
318  const element *data() const
319  {
320  return m_data + m_offset;
321  }
322 
323  /// \brief Returns 1.
325  {
326  return 1;
327  }
328 
329  /// \brief Returns the array's size.
330  size_type size() const
331  {
332  return m_size;
333  }
334 
335  /// \brief Returns the array's size.
336  /// Deprecated
337  DEPRECATED(5.1.0, size) size_type num_elements() const
338  {
339  WARNINGL1(false, "member function num_elements() is deprecated, "
340  "use size() instead.");
341  return m_size;
342  }
343 
344  /// \brief Returns the array's capacity.
346  {
347  return m_capacity;
348  }
349 
350  /// \brief Returns the array's offset.
352  {
353  return m_offset;
354  }
355 
356  /// \brief Returns the array's reference counter.
358  {
359  return *m_count;
360  }
361 
362  /// \brief Returns true is this array and rhs overlap.
363  bool Overlaps(const Array<OneD, const DataType> &rhs) const
364  {
365  const element *start = get();
366  const element *end = start + m_size;
367 
368  const element *rhs_start = rhs.get();
369  const element *rhs_end = rhs_start + rhs.size();
370 
371  return (rhs_start >= start && rhs_start <= end) ||
372  (rhs_end >= start && rhs_end <= end);
373  }
374 
375 #ifdef WITH_PYTHON
376  bool IsPythonArray()
377  {
378  return *m_pythonInfo != nullptr;
379  }
380 
381  void ToPythonArray(void *memory_pointer, void (*python_decrement)(void *))
382  {
383  *m_pythonInfo = new PythonInfo();
384  (*m_pythonInfo)->m_callback = python_decrement;
385  (*m_pythonInfo)->m_pyObject = memory_pointer;
386  }
387 #endif
388 
389  /// \brief Creates an array with a specified offset.
390  ///
391  /// The return value will reference the same array as lhs,
392  /// but with an offset.
393  ///
394  /// For example, in the following:
395  /// \code
396  /// Array<OneD, const double> result = anArray + 10;
397  /// \endcode
398  /// result[0] == anArray[10];
399  template <typename T>
401  typename Array<OneD, T>::size_type offset);
402 
403  template <typename T>
405  const Array<OneD, T> &rhs);
406 
407 protected:
408 #ifdef WITH_PYTHON
409  PythonInfo **m_pythonInfo;
410 #endif
411 
414  DataType *m_data;
415 
416  // m_count points to an integer used as a reference count to this array's
417  // data (m_data). Previously, the reference count was stored in the first 4
418  // bytes of the m_data array.
420 
422 
423 private:
424  // struct DestroyArray
425  // {
426  // DestroyArray(unsigned int elements) :
427  // m_elements(elements) {}
428  //
429  // void operator()(DataType* p)
430  // {
431  // ArrayDestructionPolicy<DataType>::Destroy(p,
432  // m_elements); MemoryManager<DataType>::RawDeallocate(p,
433  // m_elements);
434  // }
435  // unsigned int m_elements;
436  // };
437  //
439  {
440  DataType *storage = MemoryManager<DataType>::RawAllocate(size);
441  m_data = storage;
442 
443  // Allocate an integer to hold the reference count. Note 1, all arrays
444  // that share this array's data (ie, point to m_data) will also share
445  // the m_count data. Note 2, previously m_count pointed to "(unsigned
446  // int*)storage".
447  m_count = new size_type();
448  *m_count = 1;
449 #ifdef WITH_PYTHON
450  m_pythonInfo = new PythonInfo *();
451  *m_pythonInfo = nullptr;
452 #endif
453  }
454 
455  template <typename T>
457  size_type offset)
458  {
459  Array<OneD, T> result(rhs);
460  result.m_offset += offset;
461  result.m_size = rhs.m_size - offset;
462  return result;
463  }
464 };
465 
466 /// \brief 2D array with garbage collection and bounds checking.
467 template <typename DataType> class Array<TwoD, const DataType>
468 {
469 public:
470  typedef boost::multi_array_ref<DataType, 2> ArrayType;
471  typedef typename ArrayType::const_reference const_reference;
472  typedef typename ArrayType::reference reference;
473 
474  typedef typename ArrayType::index index;
475  typedef typename ArrayType::const_iterator const_iterator;
476  typedef typename ArrayType::iterator iterator;
477 
478  typedef typename ArrayType::element element;
479  typedef typename ArrayType::size_type size_type;
480 
481 public:
482  Array() : m_data(CreateStorage<DataType>(0, 0))
483  {
484  }
485 
486  /// \brief Constructs a 2 dimensional array. The elements of the array are
487  /// not initialized.
488  Array(size_type dim1Size, size_type dim2Size)
489  : m_data(CreateStorage<DataType>(dim1Size, dim2Size))
490  {
492  m_data->num_elements());
493  }
494 
495  Array(size_type dim1Size, size_type dim2Size, const DataType &initValue)
496  : m_data(CreateStorage<DataType>(dim1Size, dim2Size))
497  {
499  m_data->data(), m_data->num_elements(), initValue);
500  }
501 
502  Array(size_type dim1Size, size_type dim2Size, const DataType *data)
503  : m_data(CreateStorage<DataType>(dim1Size, dim2Size))
504  {
506  m_data->data(), m_data->num_elements(), data);
507  }
508 
509  Array(const Array<TwoD, const DataType> &rhs) : m_data(rhs.m_data)
510  {
511  }
512 
514  const Array<TwoD, const DataType> &rhs)
515  {
516  m_data = rhs.m_data;
517  return *this;
518  }
519 
521  {
522  return m_data->begin();
523  }
525  {
526  return m_data->end();
527  }
529  {
530  return (*m_data)[i];
531  }
532  const element *get() const
533  {
534  return m_data->data();
535  }
536  const element *data() const
537  {
538  return m_data->data();
539  }
541  {
542  return m_data->num_dimensions();
543  }
544  const size_type *shape() const
545  {
546  return m_data->shape();
547  }
548  // m_data is a shared_ptr to a boost::multi_array_ref
549  size_type size() const
550  {
551  return m_data->num_elements();
552  }
553  // deprecated interface
554  DEPRECATED(5.1.0, size) size_type num_elements() const
555  {
556  WARNINGL1(false, "member function num_elements() is deprecated, "
557  "use size() instead.");
558  return m_data->num_elements();
559  }
560 
562  {
563  return m_data->shape()[0];
564  }
566  {
567  return m_data->shape()[1];
568  }
569 
570 protected:
571  std::shared_ptr<ArrayType> m_data;
572 
573 private:
574 };
575 
577 {
579 };
580 
581 /// \brief 1D Array
582 ///
583 /// \ref pageNekArrays
584 ///
585 /// Misc notes.
586 ///
587 /// Through out the 1D Array class you will see things like "using
588 /// BaseType::begin" and "using BaseType::end". This is necessary to bring the
589 /// methods from the ConstArray into scope in Array class. Typically this is
590 /// not necessary, but since we have method names which match those in the base
591 /// class, the base class names are hidden. Therefore, we have to explicitly
592 /// bring them into scope to use them.
593 template <typename DataType>
594 class Array<OneD, DataType> : public Array<OneD, const DataType>
595 {
596 public:
598  typedef typename BaseType::iterator iterator;
599  typedef typename BaseType::reference reference;
600  typedef typename BaseType::size_type size_type;
601  typedef typename BaseType::element element;
602 
603 public:
605  {
606  }
607 
608  explicit Array(size_type dim1Size) : BaseType(dim1Size)
609  {
610  }
611 
612  Array(size_type dim1Size, const DataType &initValue)
613  : BaseType(dim1Size, initValue)
614  {
615  }
616 
617  Array(size_type dim1Size, const DataType *data) : BaseType(dim1Size, data)
618  {
619  }
620 
621  Array(size_type dim1Size, DataType *data, bool WrapArray)
622  : BaseType(dim1Size, data, WrapArray)
623  {
624  }
625 
626  Array(size_type dim1Size, const Array<OneD, DataType> &rhs)
627  : BaseType(dim1Size, rhs)
628  {
629  }
630 
632  : BaseType(dim1Size, rhs.data())
633  {
634  }
635 
637  {
638  }
639 
641  : BaseType(rhs.size(), rhs.data())
642  {
643  }
644 
645 #ifdef WITH_PYTHON
646  Array(size_type dim1Size, DataType *data, void *memory_pointer,
647  void (*python_decrement)(void *))
648  : BaseType(dim1Size, data, memory_pointer, python_decrement)
649  {
650  }
651 
652  void ToPythonArray(void *memory_pointer, void (*python_decrement)(void *))
653  {
654  BaseType::ToPythonArray(memory_pointer, python_decrement);
655  }
656 #endif
657 
659  {
660  BaseType::operator=(rhs);
661  return *this;
662  }
663 
665  const Array<OneD, DataType> &rhs, unsigned int offset)
666  {
667  Array<OneD, DataType> result(rhs);
668  result.m_offset += offset;
669  result.m_size = rhs.m_size - offset;
670  return result;
671  }
672 
674  {
676  }
678  {
679  return this->m_data + this->m_offset;
680  }
681 
682  using BaseType::end;
684  {
685  return this->m_data + this->m_offset + this->m_size;
686  }
687 
688  using BaseType::operator[];
690  {
691  ASSERTL1(static_cast<size_type>(i) < this->size(),
692  std::string("Element ") + std::to_string(i) +
693  std::string(" requested in an array of size ") +
694  std::to_string(this->size()));
695  return (get())[i];
696  }
697 
698  using BaseType::get;
700  {
701  return this->m_data + this->m_offset;
702  }
703 
704  using BaseType::data;
706  {
707  return this->m_data + this->m_offset;
708  }
709 
710  template <typename T1> friend class NekVector;
711 
712  template <typename T1, typename T3> friend class NekMatrix;
713 
714  friend class LinearSystem;
715 
716 protected:
718  : BaseType(rhs)
719  {
720  boost::ignore_unused(a);
721  }
722 
723  void ChangeSize(size_type newSize)
724  {
725  ASSERTL1(newSize <= this->m_capacity,
726  "Can't change an array size to something larger than its "
727  "capacity.");
728  this->m_size = newSize;
729  }
730 
731 private:
732 };
733 
734 /// \brief A 2D array.
735 template <typename DataType>
736 class Array<TwoD, DataType> : public Array<TwoD, const DataType>
737 {
738 public:
740  typedef typename BaseType::iterator iterator;
741  typedef typename BaseType::reference reference;
742  typedef typename BaseType::index index;
743  typedef typename BaseType::size_type size_type;
744  typedef typename BaseType::element element;
745 
746 public:
748  {
749  }
750 
751  Array(size_type dim1Size, size_type dim2Size) : BaseType(dim1Size, dim2Size)
752  {
753  }
754 
755  Array(size_type dim1Size, size_type dim2Size, const DataType &initValue)
756  : BaseType(dim1Size, dim2Size, initValue)
757  {
758  }
759 
760  Array(size_type dim1Size, size_type dim2Size, const DataType *data)
761  : BaseType(dim1Size, dim2Size, data)
762  {
763  }
764 
766  {
767  }
768 
770  {
771  BaseType::operator=(rhs);
772  return *this;
773  }
774 
775  using BaseType::begin;
777  {
778  return this->m_data->begin();
779  }
780 
781  using BaseType::end;
783  {
784  return this->m_data->end();
785  }
786 
787  using BaseType::operator[];
789  {
790  return (*this->m_data)[i];
791  }
792 
793  using BaseType::get;
795  {
796  return this->m_data->data();
797  }
798 
799  using BaseType::data;
801  {
802  return this->m_data->data();
803  }
804 
805 private:
806 };
807 
808 // compare whatever
809 template <typename T>
810 inline bool IsEqualImpl(const T &lhs, const T &rhs, std::false_type)
811 {
812  return lhs == rhs;
813 }
814 
815 // compare floating point value
816 template <typename T>
817 inline bool IsEqualImpl(const T &lhs, const T &rhs, std::true_type)
818 {
819  return LibUtilities::IsRealEqual(lhs, rhs);
820 }
821 
822 template <typename T> inline bool IsEqual(const T &lhs, const T &rhs)
823 {
824  return IsEqualImpl(lhs, rhs, std::is_floating_point<T>());
825 }
826 
827 template <typename T1, typename T2>
828 bool operator==(const Array<OneD, T1> &lhs, const Array<OneD, T2> &rhs)
829 {
830  if (lhs.size() != rhs.size())
831  {
832  return false;
833  }
834 
835  if (lhs.data() == rhs.data())
836  {
837  return true;
838  }
839 
840  typename Array<OneD, T1>::size_type size_value(lhs.size());
841  for (typename Array<OneD, T1>::size_type i = 0; i < size_value; ++i)
842  {
843  if (!IsEqual(lhs[i], rhs[i]))
844  {
845  return false;
846  }
847  }
848 
849  return true;
850 }
851 
852 template <typename T1, typename T2>
853 bool operator!=(const Array<OneD, T1> &lhs, const Array<OneD, T2> &rhs)
854 {
855  return !(lhs == rhs);
856 }
857 
858 template <typename DataType>
860  const Array<OneD, DataType> &lhs,
861  typename Array<OneD, DataType>::size_type offset)
862 {
864 }
865 
866 template <typename DataType>
868  typename Array<OneD, DataType>::size_type offset,
869  const Array<OneD, DataType> &rhs)
870 {
872 }
873 
874 template <typename ConstDataType, typename DataType>
876  Array<OneD, DataType> &dest)
877 {
878  if (dest.size() != source.size())
879  {
880  dest = Array<OneD, DataType>(source.size());
881  }
882 
883  std::copy(source.data(), source.data() + source.size(), dest.data());
884 }
885 
886 template <typename ConstDataType, typename DataType>
888  Array<OneD, DataType> &dest,
890 {
891  if (dest.size() != n)
892  {
893  dest = Array<OneD, DataType>(n);
894  }
895 
896  std::copy(source.data(), source.data() + n, dest.data());
897 }
898 
902 
903 // TODO: Consider removing this declaration
906 
907 // TODO: This declaration will be removed
908 template <class T> using TensorOfArray2D = Array<OneD, Array<OneD, T>>;
909 
910 // Temporary alias for 3D nested array. Please note that the inner arrays
911 // are not const declared. It is therefore suggested to use this alias with
912 // caution.
913 template <class T>
915 // Temporary alias for 4D nested array. Please note that the inner arrays
916 // are not const declared. It is therefore suggested to use this alias with
917 // caution.
918 template <class T>
920 // Temporary alias for 5D nested array. Please note that the inner arrays
921 // are not const declared. It is therefore suggested to use this alias with
922 // caution.
923 template <class T>
926 
927 template <typename T1, typename T2>
928 bool operator==(const Array<TwoD, T1> &lhs, const Array<TwoD, T2> &rhs)
929 {
930  if ((lhs.GetRows() != rhs.GetRows()) ||
931  (lhs.GetColumns() != rhs.GetColumns()))
932  {
933  return false;
934  }
935 
936  if (lhs.data() == rhs.data())
937  {
938  return true;
939  }
940 
941  for (typename Array<OneD, T1>::size_type i = 0; i < lhs.GetRows(); ++i)
942  {
943  for (typename Array<OneD, T1>::size_type j = 0; j < lhs.GetColumns();
944  ++j)
945  {
946  if (!IsEqual(lhs[i][j], rhs[i][j]))
947  {
948  return false;
949  }
950  }
951  }
952 
953  return true;
954 }
955 
956 template <typename T1, typename T2>
957 bool operator!=(const Array<TwoD, T1> &lhs, const Array<TwoD, T2> &rhs)
958 {
959  return !(lhs == rhs);
960 }
961 
962 namespace LibUtilities
963 {
964 static std::vector<NekDouble> NullNekDoubleVector;
965 static std::vector<unsigned int> NullUnsignedIntVector;
966 static std::vector<std::vector<NekDouble>> NullVectorNekDoubleVector = {
968 } // namespace LibUtilities
969 } // namespace Nektar
970 
971 #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(size_type dim1Size, DataType *data, bool WrapArray)
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:2
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)