Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description:
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
36 #ifndef NEKTAR_LIB_UTILITIES_BASIC_UTILS_SHARED_ARRAY_HPP
37 #define NEKTAR_LIB_UTILITIES_BASIC_UTILS_SHARED_ARRAY_HPP
38 
45 
46 #include <boost/multi_array.hpp>
47 #include <boost/shared_ptr.hpp>
48 
49 namespace Nektar
50 {
51  class LinearSystem;
52 
53  // Forward declaration for a ConstArray constructor.
54  template<typename Dim, typename DataType>
55  class Array;
56 
57  /// \brief 1D Array of constant elements with garbage collection and bounds checking.
58  template<typename DataType>
59  class Array<OneD, const DataType>
60  {
61  public:
62  typedef DataType* ArrayType;
63  typedef const DataType& const_reference;
64  typedef DataType& reference;
65 
66  typedef const DataType* const_iterator;
67  typedef DataType* iterator;
68 
69  typedef DataType element;
70  typedef unsigned int size_type;
71 
72 
73  public:
74  /// \brief Creates an empty array.
75  Array() :
76  m_size(0),
77  m_capacity(0),
78  m_data(0),
79  m_count(0),
80  m_offset(0)
81  {
82  CreateStorage(m_capacity);
83  }
84 
85  /// \brief Creates an array of size dim1Size.
86  ///
87  /// If DataType is a fundamental type (double, int, etc.), then the allocated array is
88  /// uninitialized. If it is any other type, each element is initialized with DataType's default
89  /// constructor.
90  explicit Array(unsigned int dim1Size) :
91  m_size(dim1Size),
92  m_capacity(dim1Size),
93  m_data(0),
94  m_count(0),
95  m_offset(0)
96  {
97  CreateStorage(m_capacity);
98  ArrayInitializationPolicy<DataType>::Initialize(m_data + 1, m_capacity);
99  }
100 
101  /// \brief Creates a 1D array with each element
102  /// initialized to an initial value.
103  /// \param dim1Size The array's size.
104  /// \param initValue Each element's initial value.
105  ///
106  /// If DataType is a fundamental type (double, int, etc.),
107  /// then the initial value is copied directly into each
108  /// element. Otherwise, the DataType's copy constructor
109  /// is used to initialize each element.
110  Array(unsigned int dim1Size, const DataType& initValue) :
111  m_size(dim1Size),
112  m_capacity(dim1Size),
113  m_data(0),
114  m_count(0),
115  m_offset(0)
116  {
117  CreateStorage(m_capacity);
118  ArrayInitializationPolicy<DataType>::Initialize(m_data + 1, m_capacity, initValue);
119  }
120 
121  /// \brief Creates a 1D array a copies data into it.
122  /// \param dim1Size the array's size.
123  /// \param data The data to copy.
124  ///
125  /// If DataType is a fundamental type (double, int, etc.), then data is copied
126  /// directly into the underlying storage. Otherwise, the DataType's copy constructor
127  /// is used to copy each element.
128  Array(unsigned int dim1Size, const DataType* data) :
129  m_size(dim1Size),
130  m_capacity(dim1Size),
131  m_data(0),
132  m_count(0),
133  m_offset(0)
134  {
135  CreateStorage(m_capacity);
136  ArrayInitializationPolicy<DataType>::Initialize(m_data + 1, m_capacity, data);
137  }
138 
139  /// \brief Creates a 1D array that references rhs.
140  /// \param dim1Size The size of the array. This is useful
141  /// when you want this array to reference
142  /// a subset of the elements in rhs.
143  /// \param rhs Array to reference.
144  /// This constructor creates an array that references rhs.
145  /// Any changes to rhs will be reflected in this array.
146  /// The memory for the array will only be deallocated when
147  /// both rhs and this array have gone out of scope.
148  Array(unsigned int dim1Size, const Array<OneD, const DataType>& rhs) :
149  m_size(dim1Size),
150  m_capacity(rhs.m_capacity),
151  m_data(rhs.m_data),
152  m_count(rhs.m_count),
153  m_offset(rhs.m_offset)
154  {
155  *m_count += 1;
156  ASSERTL0(m_size <= rhs.num_elements(), "Requested size is larger than input array size.");
157  }
158 
159  /// \brief Creates a reference to rhs.
160  Array(const Array<OneD, const DataType>& rhs) :
161  m_size(rhs.m_size),
162  m_capacity(rhs.m_capacity),
163  m_data(rhs.m_data),
164  m_count(rhs.m_count),
165  m_offset(rhs.m_offset)
166  {
167  *m_count += 1;
168  }
169 
170  ~Array()
171  {
172  if( m_count == 0 )
173  {
174  return;
175  }
176 
177  *m_count -= 1;
178  if( *m_count == 0 )
179  {
180  ArrayDestructionPolicy<DataType>::Destroy(m_data+1, m_capacity);
181  MemoryManager<DataType>::RawDeallocate(m_data, m_capacity+1);
182  }
183  }
184 
185  /// \brief Creates a reference to rhs.
187  {
188  *m_count -= 1;
189  if( *m_count == 0 )
190  {
191  ArrayDestructionPolicy<DataType>::Destroy(m_data+1, m_capacity);
192  MemoryManager<DataType>::RawDeallocate(m_data, m_capacity+1);
193  }
194 
195  m_data = rhs.m_data;
196  m_capacity = rhs.m_capacity;
197  m_count = rhs.m_count;
198  *m_count += 1;
199  m_offset = rhs.m_offset;
200  m_size = rhs.m_size;
201  return *this;
202  }
203 
204  const_iterator begin() const { return m_data + m_offset + 1; }
205  const_iterator end() const { return m_data + m_offset + m_size + 1; }
206 
207  const_reference operator[](unsigned int i) const
208  {
209  ASSERTL1(static_cast<size_type>(i) < m_size, (std::string("Element ") +
210  boost::lexical_cast<std::string>(i) + std::string(" requested in an array of size ") +
211  boost::lexical_cast<std::string>(m_size)));
212  return *(m_data + i + m_offset + 1);
213  }
214 
215  /// \brief Returns a c-style pointer to the underlying array.
216  const element* get() const { return m_data+m_offset+1; }
217 
218  /// \brief Returns a c-style pointer to the underlying array.
219  const element* data() const { return m_data+m_offset+1; }
220 
221  /// \brief Returns 1.
222  size_type num_dimensions() const { return 1; }
223 
224  /// \brief Returns the array's size.
225  size_type num_elements() const { return m_size; }
226 
227  size_type capacity() const { return m_capacity; }
228 
229  /// \brief Returns the array's offset.
230  unsigned int GetOffset() const { return m_offset; }
231 
232  /// \brief Returns true is this array and rhs overlap.
233  bool Overlaps(const Array<OneD, const DataType>& rhs) const
234  {
235  const element* start = get();
236  const element* end = start + m_size;
237 
238  const element* rhs_start = rhs.get();
239  const element* rhs_end = rhs_start + rhs.num_elements();
240 
241  return (rhs_start >= start && rhs_start <= end) ||
242  (rhs_end >= start && rhs_end <= end);
243  }
244 
245  template<typename T1, typename T2>
246  friend bool operator==(const Array<OneD, T1>&, const Array<OneD, T2>&);
247  LIB_UTILITIES_EXPORT friend bool operator==(const Array<OneD, NekDouble>&, const Array<OneD, NekDouble>&);
248  LIB_UTILITIES_EXPORT friend bool IsEqual(const Array<OneD, const NekDouble>&,const Array<OneD, const NekDouble>&,NekDouble);
249 
250  /// \brief Creates an array with a specified offset.
251  ///
252  /// The return value will reference the same array as lhs,
253  /// but with an offset.
254  ///
255  /// For example, in the following:
256  /// \code
257  /// Array<OneD, const double> result = anArray + 10;
258  /// \endcode
259  /// result[0] == anArray[10];
260  template<typename T>
261  friend Array<OneD, T> operator+(const Array<OneD, T>& lhs, unsigned int offset);
262 
263  template<typename T>
264  friend Array<OneD, T> operator+(unsigned int offset, const Array<OneD, T>& rhs);
265 
266  protected:
267  unsigned int m_size;
268  unsigned int m_capacity;
269  //boost::shared_ptr<DataType> m_data;
270  //NekPtr<DataType> m_data;
271  DataType* m_data;
272  unsigned int* m_count;
273  unsigned int m_offset;
274 
275 
276  private:
277  // struct DestroyArray
278  // {
279  // DestroyArray(unsigned int elements) :
280  // m_elements(elements) {}
281  //
282  // void operator()(DataType* p)
283  // {
284  // ArrayDestructionPolicy<DataType>::Destroy(p, m_elements);
285  // MemoryManager<DataType>::RawDeallocate(p, m_elements);
286  // }
287  // unsigned int m_elements;
288  // };
289  //
290  // boost::shared_ptr<DataType>
291  // NekPtr<DataType>
292  void
293  CreateStorage(unsigned int size)
294  {
295  DataType* storage = MemoryManager<DataType>::RawAllocate(size+1);
296  m_data = storage;
297  m_count = (unsigned int*)storage;
298  *m_count = 1;
299  //return NekPtr<DataType>(storage, size);
300  //return boost::shared_ptr<DataType>(storage,
301  //boost::bind(DeleteStorage<DataType>, storage, size) );
302  // DestroyArray(size), MemoryManager<DataType>() );
303  }
304 
305  template<typename T>
306  static Array<OneD, T> CreateWithOffset(const Array<OneD, T>& rhs, unsigned int offset)
307  {
308  Array<OneD, T> result(rhs);
309  result.m_offset += offset;
310  result.m_size = rhs.m_size - offset;
311  return result;
312  }
313 
314  };
315 
316 
317  /// \brief 2D array with garbage collection and bounds checking.
318  template<typename DataType>
319  class Array<TwoD, const DataType>
320  {
321  public:
322  typedef boost::multi_array_ref<DataType, 2> ArrayType;
323  typedef typename ArrayType::const_reference const_reference;
324  typedef typename ArrayType::reference reference;
325 
326  typedef typename ArrayType::index index;
327  typedef typename ArrayType::const_iterator const_iterator;
328  typedef typename ArrayType::iterator iterator;
329 
330  typedef typename ArrayType::element element;
331  typedef typename ArrayType::size_type size_type;
332 
333 
334 
335  public:
336  Array() :
337  m_data(CreateStorage<DataType>(0, 0))
338  {
339  }
340 
341  /// \brief Constructs a 3 dimensional array. The elements of the array are not initialized.
342  Array(unsigned int dim1Size, unsigned int dim2Size) :
343  m_data(CreateStorage<DataType>(dim1Size, dim2Size))
344  {
345  ArrayInitializationPolicy<DataType>::Initialize(m_data->data(), m_data->num_elements());
346  }
347 
348  Array(unsigned int dim1Size, unsigned int dim2Size, const DataType& initValue) :
349  m_data(CreateStorage<DataType>(dim1Size, dim2Size))
350  {
351  ArrayInitializationPolicy<DataType>::Initialize(m_data->data(), m_data->num_elements(), initValue);
352  }
353 
354  Array(unsigned int dim1Size, unsigned int dim2Size, const DataType* data) :
355  m_data(CreateStorage<DataType>(dim1Size, dim2Size))
356  {
357  ArrayInitializationPolicy<DataType>::Initialize(m_data->data(), m_data->num_elements(), data);
358  }
359 
360  Array(const Array<TwoD, const DataType>& rhs) :
361  m_data(rhs.m_data)
362  {
363  }
364 
366  {
367  m_data = rhs.m_data;
368  return *this;
369  }
370 
371  template<typename T>
372  friend bool operator==(const Array<TwoD, T>&, const Array<TwoD, T>&);
373  LIB_UTILITIES_EXPORT friend bool operator==(const Array<TwoD, NekDouble>&, const Array<TwoD, NekDouble>&);
374  LIB_UTILITIES_EXPORT friend bool IsEqual(const Array<TwoD, const NekDouble>&,const Array<TwoD, const NekDouble>&,NekDouble);
375 
376  const_iterator begin() const { return m_data->begin(); }
377  const_iterator end() const { return m_data->end(); }
378  const_reference operator[](index i) const { return (*m_data)[i]; }
379  const element* get() const { return m_data->data(); }
380  const element* data() const { return m_data->data(); }
381  size_type num_dimensions() const { return m_data->num_dimensions(); }
382  const size_type* shape() const { return m_data->shape(); }
383  size_type num_elements() const { return m_data->num_elements(); }
384 
385  size_type GetRows() const { return m_data->shape()[0]; }
386  size_type GetColumns() const { return m_data->shape()[1]; }
387 
388  protected:
389  boost::shared_ptr<ArrayType> m_data;
390 
391  private:
392 
393  };
394 
395  /// \brief 3D array with garbage collection and bounds checking.
396  template<typename DataType>
397  class Array<ThreeD, const DataType>
398  {
399  public:
400  typedef boost::multi_array_ref<DataType, 3> ArrayType;
401  typedef typename ArrayType::const_reference const_reference;
402  typedef typename ArrayType::reference reference;
403 
404  typedef typename ArrayType::index index;
405  typedef typename ArrayType::const_iterator const_iterator;
406  typedef typename ArrayType::iterator iterator;
407 
408  typedef typename ArrayType::element element;
409  typedef typename ArrayType::size_type size_type;
410 
411 
412 
413  public:
414  Array() :
415  m_data(CreateStorage<DataType>(0, 0, 0))
416  {
417  }
418 
419  /// \brief Constructs a 3 dimensional array. The elements of the array are not initialized.
420  Array(unsigned int dim1Size, unsigned int dim2Size, unsigned int dim3Size) :
421  m_data(CreateStorage<DataType>(dim1Size, dim2Size, dim3Size))
422  {
423  ArrayInitializationPolicy<DataType>::Initialize(m_data->data(), m_data->num_elements());
424  }
425 
426  Array(unsigned int dim1Size, unsigned int dim2Size, unsigned int dim3Size, const DataType& initValue) :
427  m_data(CreateStorage<DataType>(dim1Size, dim2Size, dim3Size))
428  {
429  ArrayInitializationPolicy<DataType>::Initialize(m_data->data(), m_data->num_elements(), initValue);
430  }
431 
432  Array(const Array<ThreeD, const DataType>& rhs) :
433  m_data(rhs.m_data)
434  {
435  }
436 
438  {
439  m_data = rhs.m_data;
440  return *this;
441  }
442 
443  const_iterator begin() const { return m_data->begin(); }
444  const_iterator end() const { return m_data->end(); }
445  const_reference operator[](index i) const { return (*m_data)[i]; }
446  const element* get() const { return m_data->data(); }
447  const element* data() const { return m_data->data(); }
448  size_type num_dimensions() const { return m_data->num_dimensions(); }
449  const size_type* shape() const { return m_data->shape(); }
450  size_type num_elements() const { return m_data->num_elements(); }
451 
452  protected:
453  boost::shared_ptr<ArrayType> m_data;
454 
455  private:
456 
457  };
458 
459 
461  {
463  };
464 
465  /// \brief 1D Array
466  ///
467  /// \ref pageNekArrays
468  ///
469  /// Misc notes.
470  ///
471  /// Throught the 1D Array class you will see things like "using BaseType::begin" and
472  /// "using BaseType::end". This is necessary to bring the methods from the ConstArray
473  /// into scope in Array class. Typically this is not necessary, but since we have
474  /// method names which match those in the base class, the base class names are hidden.
475  /// Therefore, we have to explicitly bring them into scope to use them.
476  template<typename DataType>
477  class Array<OneD, DataType> : public Array<OneD, const DataType>
478  {
479  public:
481  typedef typename BaseType::iterator iterator;
482  typedef typename BaseType::reference reference;
483  typedef typename BaseType::size_type size_type;
484  typedef typename BaseType::element element;
485 
486  public:
487  Array() :
488  BaseType()
489  {
490  }
491 
492  explicit Array(unsigned int dim1Size) :
493  BaseType(dim1Size)
494  {
495  }
496 
497  Array(unsigned int dim1Size, const DataType& initValue) :
498  BaseType(dim1Size, initValue)
499  {
500  }
501 
502  Array(unsigned int dim1Size, const DataType* data) :
503  BaseType(dim1Size, data)
504  {
505  }
506 
507  Array(unsigned int dim1Size, const Array<OneD, DataType>& rhs) :
508  BaseType(dim1Size, rhs)
509  {
510  }
511 
512  Array(unsigned int dim1Size, const Array<OneD, const DataType>& rhs) :
513  BaseType(dim1Size, rhs.data())
514  {
515  }
516 
517  Array(const Array<OneD, DataType>& rhs) :
518  BaseType(rhs)
519  {
520  }
521 
522  Array(const Array<OneD, const DataType>& rhs) :
523  BaseType(rhs.num_elements(), rhs.data())
524  {
525  }
526 
528  {
529  BaseType::operator=(rhs);
530  return *this;
531  }
532 
533  static Array<OneD, DataType> CreateWithOffset(const Array<OneD, DataType>& rhs, unsigned int offset)
534  {
535  Array<OneD, DataType> result(rhs);
536  result.m_offset += offset;
537  result.m_size = rhs.m_size - offset;
538  return result;
539  }
540 
541  using BaseType::begin;
542  iterator begin() { return this->m_data + 1 +this->m_offset; }
543 
544  using BaseType::end;
545  iterator end() { return this->m_data + 1 + this->m_offset + this->m_size; }
546 
547  using BaseType::operator[];
548  reference operator[](unsigned int i)
549  {
550  ASSERTL1(static_cast<size_type>(i) < this->num_elements(), (std::string("Element ") +
551  boost::lexical_cast<std::string>(i) + std::string(" requested in an array of size ") +
552  boost::lexical_cast<std::string>(this->num_elements())));
553  return (get())[i];
554  }
555 
556 
557  using BaseType::get;
558  element* get() { return this->m_data + 1 +this->m_offset; }
559 
560  using BaseType::data;
561  element* data() { return this->m_data + 1 +this->m_offset; }
562 
563  template<typename T1>
564  friend class NekVector;
565 
566  template<typename T1, typename T3>
567  friend class NekMatrix;
568 
569  friend class LinearSystem;
570 
571  protected:
573  BaseType(rhs)
574  {
575  }
576 
577  void ChangeSize(unsigned int newSize)
578  {
579  ASSERTL1(newSize <= this->m_capacity, "Can't change an array size to something larger than its capacity.");
580  this->m_size = newSize;
581  }
582 
583  private:
584 
585  };
586 
587  /// \brief A 2D array.
588  template<typename DataType>
589  class Array<TwoD, DataType> : public Array<TwoD, const DataType>
590  {
591  public:
593  typedef typename BaseType::iterator iterator;
594  typedef typename BaseType::reference reference;
595  typedef typename BaseType::index index;
596  typedef typename BaseType::size_type size_type;
597  typedef typename BaseType::element element;
598 
599  public:
600  Array() :
601  BaseType()
602  {
603  }
604 
605  Array(unsigned int dim1Size, unsigned int dim2Size) :
606  BaseType(dim1Size, dim2Size)
607  {
608  }
609 
610  Array(unsigned int dim1Size, unsigned int dim2Size, const DataType& initValue) :
611  BaseType(dim1Size, dim2Size, initValue)
612  {
613  }
614 
615  Array(unsigned int dim1Size, unsigned int dim2Size, const DataType* data) :
616  BaseType(dim1Size, dim2Size, data)
617  {
618  }
619 
620  Array(const Array<TwoD, DataType>& rhs) :
621  BaseType(rhs)
622  {
623  }
624 
626  {
627  BaseType::operator=(rhs);
628  return *this;
629  }
630 
631  using BaseType::begin;
632  iterator begin() { return this->m_data->begin(); }
633 
634  using BaseType::end;
635  iterator end() { return this->m_data->end(); }
636 
637  using BaseType::operator[];
638  reference operator[](index i) { return (*this->m_data)[i]; }
639 
640  using BaseType::get;
641  element* get() { return this->m_data->data(); }
642 
643  using BaseType::data;
644  element* data() { return this->m_data->data(); }
645 
646  private:
647 
648  };
649 
650  /// \brief A 3D array.
651  template<typename DataType>
652  class Array<ThreeD, DataType> : public Array<ThreeD, const DataType>
653  {
654  public:
656  typedef typename BaseType::iterator iterator;
657  typedef typename BaseType::reference reference;
658  typedef typename BaseType::index index;
659  typedef typename BaseType::size_type size_type;
660  typedef typename BaseType::element element;
661 
662  public:
663  Array() :
664  BaseType()
665  {
666  }
667 
668  Array(unsigned int dim1Size, unsigned int dim2Size, unsigned int dim3Size) :
669  BaseType(dim1Size, dim2Size, dim3Size)
670  {
671  }
672 
673  Array(unsigned int dim1Size, unsigned int dim2Size, unsigned int dim3Size, const DataType& initValue) :
674  BaseType(dim1Size, dim2Size, dim3Size, initValue)
675  {
676  }
677 
678  Array(const Array<ThreeD, DataType>& rhs) :
679  BaseType(rhs)
680  {
681  }
682 
684  {
685  BaseType::operator=(rhs);
686  return *this;
687  }
688 
689  using BaseType::begin;
690  iterator begin() { return this->m_data->begin(); }
691 
692  using BaseType::end;
693  iterator end() { return this->m_data->end(); }
694 
695  using BaseType::operator[];
696  reference operator[](index i) { return (*this->m_data)[i]; }
697 
698  using BaseType::get;
699  element* get() { return this->m_data->data(); }
700 
701  using BaseType::data;
702  element* data() { return this->m_data->data(); }
703 
704  private:
705 
706  };
707 
708  LIB_UTILITIES_EXPORT bool IsEqual(const Array<OneD, const NekDouble>& lhs,
709  const Array<OneD, const NekDouble>& rhs,
711  LIB_UTILITIES_EXPORT bool operator==(const Array<OneD, NekDouble>& lhs, const Array<OneD, NekDouble>& rhs);
712 
713  template<typename T1, typename T2>
714  bool operator==(const Array<OneD, T1>& lhs, const Array<OneD, T2>& rhs)
715  {
716  if( lhs.num_elements() != rhs.num_elements() )
717  {
718  return false;
719  }
720 
721  if( lhs.data() == rhs.data() )
722  {
723  return true;
724  }
725 
726  for(unsigned int i = 0; i < lhs.num_elements(); ++i)
727  {
728  if( lhs[i] != rhs[i] )
729  {
730  return false;
731  }
732  }
733 
734  return true;
735  }
736 
737  template<typename T1, typename T2>
738  bool operator!=(const Array<OneD, T1>& lhs, const Array<OneD, T2>& rhs)
739  {
740  return !(lhs == rhs);
741  }
742 
743  template<typename DataType>
745  {
747  }
748 
749  template<typename DataType>
750  Array<OneD, DataType> operator+(unsigned int offset, const Array<OneD, DataType>& rhs)
751  {
753  }
754 
755 // template<typename DataType>
756 // Array<OneD, DataType> operator+(const Array<OneD, DataType>& lhs, unsigned int offset)
757 // {
758 // return Array<OneD, DataType>::CreateWithOffset(lhs, offset);
759 // }
760 
761  template<typename ConstDataType, typename DataType>
762  void CopyArray(const Array<OneD, ConstDataType>& source, Array<OneD, DataType>& dest)
763  {
764  if( dest.num_elements() != source.num_elements() )
765  {
766  dest = Array<OneD, DataType>(source.num_elements());
767  }
768 
769  std::copy(source.data(), source.data() + source.num_elements(), dest.data());
770  }
771 
772  template<typename ConstDataType, typename DataType>
773  void CopyArrayN(const Array<OneD, ConstDataType>& source, Array<OneD, DataType>& dest, unsigned int n)
774  {
775  if( dest.num_elements() != n )
776  {
777  dest = Array<OneD, DataType>(n);
778  }
779 
780  std::copy(source.data(), source.data() + n, dest.data());
781  }
782 
783  static Array<OneD, int> NullInt1DArray;
784  static Array<OneD, NekDouble> NullNekDouble1DArray;
785  static Array<OneD, Array<OneD, NekDouble> > NullNekDoubleArrayofArray;
786 
787  LIB_UTILITIES_EXPORT bool IsEqual(const Array<TwoD, const NekDouble>& lhs,
788  const Array<TwoD, const NekDouble>& rhs,
790  LIB_UTILITIES_EXPORT bool operator==(const Array<TwoD, NekDouble>& lhs, const Array<TwoD, NekDouble>& rhs) ;
791 
792  template<typename DataType>
794  {
795  return *lhs.m_data == *rhs.m_data;
796  }
797 
798  template<typename DataType>
800  {
801  return !(lhs == rhs);
802  }
803 
804 
805 }
806 
807 #endif //NEKTAR_LIB_UTILITIES_BASIC_UTILS_SHARED_ARRAY_HPP