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>
54  class Array;
55 
56  /// \brief 1D Array of constant elements with garbage collection and bounds checking.
57  template<typename DataType>
58  class Array<OneD, const DataType>
59  {
60 #ifdef WITH_PYTHON
61  struct PythonInfo {
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 
78  public:
79  /// \brief Creates an empty array.
80  Array() :
81 #ifdef WITH_PYTHON
82  m_pythonInfo(nullptr),
83 #endif
84  m_size( 0 ),
85  m_capacity( 0 ),
86  m_data( nullptr ),
87  m_count( nullptr ),
88  m_offset( 0 )
89  {
90  CreateStorage(m_capacity);
91  }
92 
93  /// \brief Creates an array of size dim1Size.
94  ///
95  /// If DataType is a fundamental type (double, int, etc.), then the allocated array is
96  /// uninitialized. If it is any other type, each element is initialized with DataType's default
97  /// constructor.
98  explicit Array(size_type dim1Size) :
99 #ifdef WITH_PYTHON
100  m_pythonInfo(nullptr),
101 #endif
102  m_size( dim1Size ),
103  m_capacity( dim1Size ),
104  m_data( nullptr ),
105  m_count( nullptr ),
106  m_offset( 0 )
107  {
108  CreateStorage(m_capacity);
110  }
111 
112  /// \brief Creates a 1D array with each element
113  /// initialized to an initial value.
114  /// \param dim1Size The array's size.
115  /// \param initValue Each element's initial value.
116  ///
117  /// If DataType is a fundamental type (double, int, etc.),
118  /// then the initial value is copied directly into each
119  /// element. Otherwise, the DataType's copy constructor
120  /// is used to initialize each element.
121  Array(size_type dim1Size, const DataType& initValue) :
122 #ifdef WITH_PYTHON
123  m_pythonInfo(nullptr),
124 #endif
125  m_size( dim1Size ),
126  m_capacity( dim1Size ),
127  m_data( nullptr ),
128  m_count( nullptr ),
129  m_offset( 0 )
130  {
131  CreateStorage(m_capacity);
132  ArrayInitializationPolicy<DataType>::Initialize( m_data, m_capacity, initValue );
133  }
134 
135  /// \brief Creates a 1D array a copies data into it.
136  /// \param dim1Size the array's size.
137  /// \param data The data to copy.
138  ///
139  /// If DataType is a fundamental type (double, int, etc.), then data is copied
140  /// directly into the underlying storage. Otherwise, the DataType's copy constructor
141  /// is used to copy each element.
142  Array(size_type dim1Size, const DataType* data) :
143 #ifdef WITH_PYTHON
144  m_pythonInfo(nullptr),
145 #endif
146  m_size( dim1Size ),
147  m_capacity( dim1Size ),
148  m_data( nullptr ),
149  m_count( nullptr ),
150  m_offset( 0 )
151  {
152  CreateStorage(m_capacity);
153  ArrayInitializationPolicy<DataType>::Initialize( m_data, m_capacity, data );
154  }
155 
156  /// \brief Creates a 1D array that references rhs.
157  /// \param dim1Size The size of the array. This is useful
158  /// when you want this array to reference
159  /// a subset of the elements in rhs.
160  /// \param rhs Array to reference.
161  /// This constructor creates an array that references rhs.
162  /// Any changes to rhs will be reflected in this array.
163  /// The memory for the array will only be deallocated when
164  /// both rhs and this array have gone out of scope.
166 #ifdef WITH_PYTHON
167  m_pythonInfo(rhs.m_pythonInfo),
168 #endif
169  m_size(dim1Size),
170  m_capacity(rhs.m_capacity),
171  m_data(rhs.m_data),
172  m_count(rhs.m_count),
173  m_offset(rhs.m_offset)
174  {
175  *m_count += 1;
176  ASSERTL0(m_size <= rhs.size(), "Requested size is \
177  larger than input array size.");
178  }
179 
180 #ifdef WITH_PYTHON
181  /// \brief Creates a 1D array a copies data into it.
182  /// \param dim1Size the array's size.
183  /// \param data The data to reference.
184  /// \param memory_pointer Pointer to the memory address of the array
185  /// \param python_decrement Pointer to decrementer
186  Array(size_type dim1Size, DataType* data, void* memory_pointer,
187  void (*python_decrement)(void *)) :
188  m_size( dim1Size ),
189  m_capacity( dim1Size ),
190  m_data( data ),
191  m_count( nullptr ),
192  m_offset( 0 )
193  {
194  m_count = new size_type();
195  *m_count = 1;
196 
197  m_pythonInfo = new PythonInfo *();
198  *m_pythonInfo = new PythonInfo();
199  (*m_pythonInfo)->m_callback = python_decrement;
200  (*m_pythonInfo)->m_pyObject = memory_pointer;
201  }
202 #endif
203 
204  /// \brief Creates a reference to rhs.
206 #ifdef WITH_PYTHON
207  m_pythonInfo(rhs.m_pythonInfo),
208 #endif
209  m_size(rhs.m_size),
210  m_capacity(rhs.m_capacity),
211  m_data(rhs.m_data),
212  m_count(rhs.m_count),
213  m_offset(rhs.m_offset)
214  {
215  *m_count += 1;
216  }
217 
219  {
220  if( m_count == nullptr )
221  {
222  return;
223  }
224 
225  *m_count -= 1;
226  if( *m_count == 0 )
227  {
228 #ifdef WITH_PYTHON
229  if (*m_pythonInfo == nullptr)
230  {
231  ArrayDestructionPolicy<DataType>::Destroy( m_data, m_capacity );
232  MemoryManager<DataType>::RawDeallocate( m_data, m_capacity );
233  }
234  else
235  {
236  (*m_pythonInfo)->m_callback((*m_pythonInfo)->m_pyObject);
237  delete *m_pythonInfo;
238  }
239 
240  delete m_pythonInfo;
241 
242 #else
243 
244  ArrayDestructionPolicy<DataType>::Destroy( m_data, m_capacity );
245  MemoryManager<DataType>::RawDeallocate( m_data, m_capacity );
246 
247 #endif
248 
249  delete m_count; // Clean up the memory used for the reference count.
250  }
251  }
252 
253  /// \brief Creates a reference to rhs.
255  {
256  *m_count -= 1;
257  if( *m_count == 0 )
258  {
259 #ifdef WITH_PYTHON
260  if (*m_pythonInfo == nullptr)
261  {
262  ArrayDestructionPolicy<DataType>::Destroy( m_data, m_capacity );
263  MemoryManager<DataType>::RawDeallocate( m_data, m_capacity );
264  }
265  else if ((*rhs.m_pythonInfo) != nullptr && (*m_pythonInfo)->m_pyObject != (*rhs.m_pythonInfo)->m_pyObject)
266  {
267  (*m_pythonInfo)->m_callback((*m_pythonInfo)->m_pyObject);
268  delete *m_pythonInfo;
269  }
270 
271  delete m_pythonInfo;
272 #else
273 
274  ArrayDestructionPolicy<DataType>::Destroy( m_data, m_capacity );
275  MemoryManager<DataType>::RawDeallocate( m_data, m_capacity );
276 #endif
277  delete m_count; // Clean up the memory used for the reference count.
278  }
279 
280  m_data = rhs.m_data;
281  m_capacity = rhs.m_capacity;
282  m_count = rhs.m_count;
283  *m_count += 1;
284  m_offset = rhs.m_offset;
285  m_size = rhs.m_size;
286 #ifdef WITH_PYTHON
287  m_pythonInfo = rhs.m_pythonInfo;
288 #endif
289  return *this;
290  }
291 
292  const_iterator begin() const { return m_data + m_offset; }
293  const_iterator end() const { return m_data + m_offset + m_size; }
294 
296  {
297  ASSERTL1(i < m_size,
298  std::string("Element ") + std::to_string(i) +
299  std::string(" requested in an array of size ") +
300  std::to_string(m_size));
301  return *( m_data + i + m_offset );
302  }
303 
304  /// \brief Returns a c-style pointer to the underlying array.
305  const element* get() const { return m_data + m_offset; }
306 
307  /// \brief Returns a c-style pointer to the underlying array.
308  const element* data() const { return m_data + m_offset; }
309 
310  /// \brief Returns 1.
311  size_type num_dimensions() const { return 1; }
312 
313  /// \brief Returns the array's size.
314  size_type size() const { return m_size; }
315 
316  /// \brief Returns the array's size.
317  /// Deprecated
318  DEPRECATED(5.1.0, size) size_type num_elements() const
319  {
320  WARNINGL1(false,
321  "member function num_elements() is deprecated, "
322  "use size() instead.");
323  return m_size;
324  }
325 
326  /// \brief Returns the array's capacity.
327  size_type capacity() const { return m_capacity; }
328 
329  /// \brief Returns the array's offset.
330  size_type GetOffset() const { return m_offset; }
331 
332  /// \brief Returns the array's reference counter.
333  size_type GetCount() const { return *m_count; }
334 
335  /// \brief Returns true is this array and rhs overlap.
336  bool Overlaps(const Array<OneD, const DataType>& rhs) const
337  {
338  const element* start = get();
339  const element* end = start + m_size;
340 
341  const element* rhs_start = rhs.get();
342  const element* rhs_end = rhs_start + rhs.size();
343 
344  return (rhs_start >= start && rhs_start <= end) ||
345  (rhs_end >= start && rhs_end <= end);
346  }
347 
348 #ifdef WITH_PYTHON
349  bool IsPythonArray()
350  {
351  return *m_pythonInfo != nullptr;
352  }
353 
354  void ToPythonArray(void* memory_pointer, void (*python_decrement)(void *))
355  {
356  *m_pythonInfo = new PythonInfo();
357  (*m_pythonInfo)->m_callback = python_decrement;
358  (*m_pythonInfo)->m_pyObject = memory_pointer;
359  }
360 #endif
361 
362  /// \brief Creates an array with a specified offset.
363  ///
364  /// The return value will reference the same array as lhs,
365  /// but with an offset.
366  ///
367  /// For example, in the following:
368  /// \code
369  /// Array<OneD, const double> result = anArray + 10;
370  /// \endcode
371  /// result[0] == anArray[10];
372  template<typename T>
374  typename Array<OneD, T>::size_type offset);
375 
376  template<typename T>
378  const Array<OneD, T>& rhs);
379 
380  protected:
381 
382 #ifdef WITH_PYTHON
383  PythonInfo **m_pythonInfo;
384 #endif
385 
388  DataType* m_data;
389 
390  // m_count points to an integer used as a reference count to this array's data (m_data).
391  // Previously, the reference count was stored in the first 4 bytes of the m_data array.
393 
395 
396  private:
397  // struct DestroyArray
398  // {
399  // DestroyArray(unsigned int elements) :
400  // m_elements(elements) {}
401  //
402  // void operator()(DataType* p)
403  // {
404  // ArrayDestructionPolicy<DataType>::Destroy(p, m_elements);
405  // MemoryManager<DataType>::RawDeallocate(p, m_elements);
406  // }
407  // unsigned int m_elements;
408  // };
409  //
410  void
412  {
413  DataType* storage = MemoryManager<DataType>::RawAllocate( size );
414  m_data = storage;
415 
416  // Allocate an integer to hold the reference count. Note 1, all arrays that share this array's
417  // data (ie, point to m_data) will also share the m_count data. Note 2, previously m_count
418  // pointed to "(unsigned int*)storage".
419  m_count = new size_type();
420  *m_count = 1;
421 #ifdef WITH_PYTHON
422  m_pythonInfo = new PythonInfo*();
423  *m_pythonInfo = nullptr;
424 #endif
425  }
426 
427  template<typename T>
429  {
430  Array<OneD, T> result(rhs);
431  result.m_offset += offset;
432  result.m_size = rhs.m_size - offset;
433  return result;
434  }
435 
436  };
437 
438 
439  /// \brief 2D array with garbage collection and bounds checking.
440  template<typename DataType>
441  class Array<TwoD, const DataType>
442  {
443  public:
444  typedef boost::multi_array_ref<DataType, 2> ArrayType;
445  typedef typename ArrayType::const_reference const_reference;
446  typedef typename ArrayType::reference reference;
447 
448  typedef typename ArrayType::index index;
449  typedef typename ArrayType::const_iterator const_iterator;
450  typedef typename ArrayType::iterator iterator;
451 
452  typedef typename ArrayType::element element;
453  typedef typename ArrayType::size_type size_type;
454 
455 
456  public:
457  Array() :
458  m_data(CreateStorage<DataType>(0, 0))
459  {
460  }
461 
462  /// \brief Constructs a 2 dimensional array. The elements of the array are not initialized.
463  Array(size_type dim1Size, size_type dim2Size) :
464  m_data(CreateStorage<DataType>(dim1Size, dim2Size))
465  {
467  m_data->num_elements());
468  }
469 
470  Array(size_type dim1Size, size_type dim2Size, const DataType& initValue) :
471  m_data(CreateStorage<DataType>(dim1Size, dim2Size))
472  {
474  m_data->num_elements(), initValue);
475  }
476 
477  Array(size_type dim1Size, size_type dim2Size, const DataType* data) :
478  m_data(CreateStorage<DataType>(dim1Size, dim2Size))
479  {
481  m_data->num_elements(), data);
482  }
483 
485  m_data(rhs.m_data)
486  {
487  }
488 
490  const DataType>& rhs)
491  {
492  m_data = rhs.m_data;
493  return *this;
494  }
495 
496  const_iterator begin() const { return m_data->begin(); }
497  const_iterator end() const { return m_data->end(); }
498  const_reference operator[](index i) const { return (*m_data)[i]; }
499  const element* get() const { return m_data->data(); }
500  const element* data() const { return m_data->data(); }
501  size_type num_dimensions() const { return m_data->num_dimensions(); }
502  const size_type* shape() const { return m_data->shape(); }
503  // m_data is a shared_ptr to a boost::multi_array_ref
504  size_type size() const { return m_data->num_elements(); }
505  // deprecated interface
506  DEPRECATED(5.1.0, size) size_type num_elements() const
507  {
508  WARNINGL1(false,
509  "member function num_elements() is deprecated, "
510  "use size() instead.");
511  return m_data->num_elements();
512  }
513 
514  size_type GetRows() const { return m_data->shape()[0]; }
515  size_type GetColumns() const { return m_data->shape()[1]; }
516 
517  protected:
518  std::shared_ptr<ArrayType> m_data;
519 
520  private:
521 
522  };
523 
525  {
527  };
528 
529  /// \brief 1D Array
530  ///
531  /// \ref pageNekArrays
532  ///
533  /// Misc notes.
534  ///
535  /// Through out the 1D Array class you will see things like "using BaseType::begin" and
536  /// "using BaseType::end". This is necessary to bring the methods from the ConstArray
537  /// into scope in Array class. Typically this is not necessary, but since we have
538  /// method names which match those in the base class, the base class names are hidden.
539  /// Therefore, we have to explicitly bring them into scope to use them.
540  template<typename DataType>
541  class Array<OneD, DataType> : public Array<OneD, const DataType>
542  {
543  public:
545  typedef typename BaseType::iterator iterator;
546  typedef typename BaseType::reference reference;
547  typedef typename BaseType::size_type size_type;
548  typedef typename BaseType::element element;
549 
550  public:
551  Array() :
552  BaseType()
553  {
554  }
555 
556  explicit Array(size_type dim1Size) :
557  BaseType(dim1Size)
558  {
559  }
560 
561  Array(size_type dim1Size, const DataType& initValue) :
562  BaseType(dim1Size, initValue)
563  {
564  }
565 
566  Array(size_type dim1Size, const DataType* data) :
567  BaseType(dim1Size, data)
568  {
569  }
570 
571  Array(size_type dim1Size, const Array<OneD, DataType>& rhs) :
572  BaseType(dim1Size, rhs)
573  {
574  }
575 
577  BaseType(dim1Size, rhs.data())
578  {
579  }
580 
582  BaseType(rhs)
583  {
584  }
585 
587  BaseType(rhs.size(), rhs.data())
588  {
589  }
590 
591 #ifdef WITH_PYTHON
592  Array(size_type dim1Size, DataType* data, void* memory_pointer, void (*python_decrement)(void *)) :
593  BaseType(dim1Size, data, memory_pointer, python_decrement)
594  {
595  }
596 
597  void ToPythonArray(void* memory_pointer, void (*python_decrement)(void *))
598  {
599  BaseType::ToPythonArray(memory_pointer, python_decrement);
600  }
601 #endif
602 
604  {
605  BaseType::operator=(rhs);
606  return *this;
607  }
608 
609  static Array<OneD, DataType> CreateWithOffset(const Array<OneD, DataType>& rhs, unsigned int offset)
610  {
611  Array<OneD, DataType> result(rhs);
612  result.m_offset += offset;
613  result.m_size = rhs.m_size - offset;
614  return result;
615  }
616 
619  iterator begin() { return this->m_data + this->m_offset; }
620 
621  using BaseType::end;
622  iterator end() { return this->m_data + this->m_offset + this->m_size; }
623 
624  using BaseType::operator[];
626  {
627  ASSERTL1(static_cast<size_type>(i) < this->size(),
628  std::string("Element ") + std::to_string(i) +
629  std::string(" requested in an array of size ") +
630  std::to_string(this->size()));
631  return (get())[i];
632  }
633 
634 
635  using BaseType::get;
636  element* get() { return this->m_data + this->m_offset; }
637 
638  using BaseType::data;
639  element* data() { return this->m_data + this->m_offset; }
640 
641  template<typename T1>
642  friend class NekVector;
643 
644  template<typename T1, typename T3>
645  friend class NekMatrix;
646 
647  friend class LinearSystem;
648 
649  protected:
651  BaseType(rhs)
652  {
653  boost::ignore_unused(a);
654  }
655 
656  void ChangeSize(size_type newSize)
657  {
658  ASSERTL1(newSize <= this->m_capacity, "Can't change an array size to something larger than its capacity.");
659  this->m_size = newSize;
660  }
661 
662  private:
663 
664  };
665 
666  /// \brief A 2D array.
667  template<typename DataType>
668  class Array<TwoD, DataType> : public Array<TwoD, const DataType>
669  {
670  public:
672  typedef typename BaseType::iterator iterator;
673  typedef typename BaseType::reference reference;
674  typedef typename BaseType::index index;
675  typedef typename BaseType::size_type size_type;
676  typedef typename BaseType::element element;
677 
678  public:
679  Array() :
680  BaseType()
681  {
682  }
683 
684  Array(size_type dim1Size, size_type dim2Size) :
685  BaseType(dim1Size, dim2Size)
686  {
687  }
688 
689  Array(size_type dim1Size, size_type dim2Size, const DataType& initValue) :
690  BaseType(dim1Size, dim2Size, initValue)
691  {
692  }
693 
694  Array(size_type dim1Size, size_type dim2Size, const DataType* data) :
695  BaseType(dim1Size, dim2Size, data)
696  {
697  }
698 
700  BaseType(rhs)
701  {
702  }
703 
705  {
706  BaseType::operator=(rhs);
707  return *this;
708  }
709 
710  using BaseType::begin;
711  iterator begin() { return this->m_data->begin(); }
712 
713  using BaseType::end;
714  iterator end() { return this->m_data->end(); }
715 
716  using BaseType::operator[];
717  reference operator[](index i) { return (*this->m_data)[i]; }
718 
719  using BaseType::get;
720  element* get() { return this->m_data->data(); }
721 
722  using BaseType::data;
723  element* data() { return this->m_data->data(); }
724 
725  private:
726 
727  };
728 
729  // compare whatever
730  template<typename T>
731  inline bool IsEqualImpl(const T& lhs, const T& rhs, std::false_type)
732  {
733  return lhs == rhs;
734  }
735 
736  // compare floating point value
737  template<typename T>
738  inline bool IsEqualImpl(const T& lhs, const T& rhs, std::true_type)
739  {
740  return LibUtilities::IsRealEqual(lhs, rhs);
741  }
742 
743  template<typename T>
744  inline bool IsEqual(const T& lhs, const T& rhs)
745  {
746  return IsEqualImpl(lhs, rhs, std::is_floating_point<T>());
747  }
748 
749  template<typename T1, typename T2>
750  bool operator==(const Array<OneD, T1>& lhs,
751  const Array<OneD, T2>& rhs)
752  {
753  if (lhs.size() != rhs.size())
754  {
755  return false;
756  }
757 
758  if (lhs.data() == rhs.data())
759  {
760  return true;
761  }
762 
763  typename Array<OneD, T1>::size_type size_value(lhs.size());
764  for (typename Array<OneD, T1>::size_type i = 0; i < size_value; ++i)
765  {
766  if (!IsEqual(lhs[i], rhs[i]))
767  {
768  return false;
769  }
770  }
771 
772  return true;
773  }
774 
775  template<typename T1, typename T2>
776  bool operator!=(const Array<OneD, T1>& lhs,
777  const Array<OneD, T2>& rhs)
778  {
779  return !(lhs == rhs);
780  }
781 
782  template<typename DataType>
784  typename Array<OneD, DataType>::size_type offset)
785  {
787  }
788 
789  template<typename DataType>
791  const Array<OneD, DataType>& rhs)
792  {
794  }
795 
796  template<typename ConstDataType, typename DataType>
798  {
799  if( dest.size() != source.size() )
800  {
801  dest = Array<OneD, DataType>(source.size());
802  }
803 
804  std::copy(source.data(), source.data() + source.size(), dest.data());
805  }
806 
807  template<typename ConstDataType, typename DataType>
809  DataType>& dest, typename Array<OneD, DataType>::size_type n)
810  {
811  if( dest.size() != n )
812  {
813  dest = Array<OneD, DataType>(n);
814  }
815 
816  std::copy(source.data(), source.data() + n, dest.data());
817  }
818 
822 
823  // TODO: Consider removing this declaration
824  static Array<OneD,
825  Array<OneD,
827  >
829 
830  // TODO: This declaration will be removed
831  template<class T>
833 
834  // Temporary alias for 3D nested array. Please note that the inner arrays
835  // are not const declared. It is therefore suggested to use this alias with
836  // caution.
837  template<class T>
839  Array<OneD,
840  Array<OneD,
842  >
843  >;
844  // Temporary alias for 4D nested array. Please note that the inner arrays
845  // are not const declared. It is therefore suggested to use this alias with
846  // caution.
847  template<class T>
849  Array<OneD,
850  Array<OneD,
851  Array<OneD,
853  >
854  >
855  >;
856  // Temporary alias for 5D nested array. Please note that the inner arrays
857  // are not const declared. It is therefore suggested to use this alias with
858  // caution.
859  template<class T>
861  Array<OneD,
862  Array<OneD,
863  Array<OneD,
864  Array<OneD,
866  >
867  >
868  >
869  >;
870 
871  template<typename T1, typename T2>
872  bool operator==(const Array<TwoD, T1>& lhs,
873  const Array<TwoD, T2>& rhs)
874  {
875  if ( (lhs.GetRows() != rhs.GetRows()) ||
876  (lhs.GetColumns() != rhs.GetColumns()) )
877  {
878  return false;
879  }
880 
881  if ( lhs.data() == rhs.data() )
882  {
883  return true;
884  }
885 
886  for (typename Array<OneD, T1>::size_type i = 0; i < lhs.GetRows(); ++i)
887  {
888  for (typename Array<OneD, T1>::size_type j = 0;
889  j < lhs.GetColumns(); ++j)
890  {
891  if (!IsEqual(lhs[i][j], rhs[i][j]))
892  {
893  return false;
894  }
895  }
896  }
897 
898  return true;
899  }
900 
901  template<typename T1, typename T2>
902  bool operator!=(const Array<TwoD, T1>& lhs,
903  const Array<TwoD, T2>& rhs)
904  {
905  return !(lhs == rhs);
906  }
907 
908  namespace LibUtilities
909  {
910  static std::vector<NekDouble> NullNekDoubleVector;
911  static std::vector<unsigned int> NullUnsignedIntVector;
912  static std::vector<std::vector<NekDouble> > NullVectorNekDoubleVector
913  = { NullNekDoubleVector };
914  }
915 }
916 
917 #endif //NEKTAR_LIB_UTILITIES_BASIC_UTILS_SHARED_ARRAY_HPP
#define WARNINGL1(condition, msg)
Definition: ErrorUtil.hpp:251
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:250
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:59
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:80
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:98
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)