MFEM  v4.1.0
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
array.hpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2020, Lawrence Livermore National Security, LLC. Produced
2 // at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3 // LICENSE and NOTICE for details. LLNL-CODE-806117.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability visit https://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the BSD-3 license. We welcome feedback and contributions, see file
10 // CONTRIBUTING.md for details.
11 
12 #ifndef MFEM_ARRAY
13 #define MFEM_ARRAY
14 
15 #include "../config/config.hpp"
16 #include "mem_manager.hpp"
17 #include "device.hpp"
18 #include "error.hpp"
19 #include "globals.hpp"
20 
21 #include <iostream>
22 #include <cstdlib>
23 #include <cstring>
24 #include <algorithm>
25 
26 namespace mfem
27 {
28 
29 template <class T>
30 class Array;
31 
32 template <class T>
33 void Swap(Array<T> &, Array<T> &);
34 
35 /**
36  Abstract data type Array.
37 
38  Array<T> is an automatically increasing array containing elements of the
39  generic type T. The allocated size may be larger then the logical size
40  of the array.
41  The elements can be accessed by the [] operator, the range is 0 to size-1.
42 */
43 template <class T>
44 class Array
45 {
46 protected:
47  /// Pointer to data
49  /// Size of the array
50  int size;
51 
52  inline void GrowSize(int minsize);
53 
54 public:
55  friend void Swap<T>(Array<T> &, Array<T> &);
56 
57  /// Creates an empty array
58  inline Array() : size(0) { data.Reset(); }
59 
60  /// Creates an empty array with a given MemoryType
61  inline Array(MemoryType mt) : size(0) { data.Reset(mt); }
62 
63  /// Creates array of asize elements
64  explicit inline Array(int asize)
65  : size(asize) { asize > 0 ? data.New(asize) : data.Reset(); }
66 
67  /** Creates array using an existing c-array of asize elements;
68  allocsize is set to -asize to indicate that the data will not
69  be deleted. */
70  inline Array(T *_data, int asize)
71  { data.Wrap(_data, asize, false); size = asize; }
72 
73  /// Copy constructor: deep copy
74  /** This method supports source arrays using any MemoryType. */
75  inline Array(const Array &src);
76 
77  /// Copy constructor (deep copy) from an Array of convertable type
78  template <typename CT>
79  inline Array(const Array<CT> &src);
80 
81  /// Destructor
82  inline ~Array() { data.Delete(); }
83 
84  /// Assignment operator: deep copy
85  Array<T> &operator=(const Array<T> &src) { src.Copy(*this); return *this; }
86 
87  /// Assignment operator (deep copy) from an Array of convertable type
88  template <typename CT>
89  inline Array &operator=(const Array<CT> &src);
90 
91  /// Return the data as 'T *'
92  inline operator T *() { return data; }
93 
94  /// Return the data as 'const T *'
95  inline operator const T *() const { return data; }
96 
97  /// Returns the data
98  inline T *GetData() { return data; }
99  /// Returns the data
100  inline const T *GetData() const { return data; }
101 
102  /// Return a reference to the Memory object used by the Array.
103  Memory<T> &GetMemory() { return data; }
104 
105  /// Return a reference to the Memory object used by the Array, const version.
106  const Memory<T> &GetMemory() const { return data; }
107 
108  /// Return the device flag of the Memory object used by the Array
109  bool UseDevice() const { return data.UseDevice(); }
110 
111  /// Return true if the data will be deleted by the array
112  inline bool OwnsData() const { return data.OwnsHostPtr(); }
113 
114  /// Changes the ownership of the data
115  inline void StealData(T **p) { *p = data; data.Reset(); size = 0; }
116 
117  /// NULL-ifies the data
118  inline void LoseData() { data.Reset(); size = 0; }
119 
120  /// Make the Array own the data
121  void MakeDataOwner() const { data.SetHostPtrOwner(true); }
122 
123  /// Logical size of the array
124  inline int Size() const { return size; }
125 
126  /// Change logical size of the array, keep existing entries
127  inline void SetSize(int nsize);
128 
129  /// Same as SetSize(int) plus initialize new entries with 'initval'
130  inline void SetSize(int nsize, const T &initval);
131 
132  /** @brief Resize the array to size @a nsize using MemoryType @a mt. Note
133  that unlike the other versions of SetSize(), the current content of the
134  array is not preserved. */
135  inline void SetSize(int nsize, MemoryType mt);
136 
137  /** Maximum number of entries the array can store without allocating more
138  memory. */
139  inline int Capacity() const { return data.Capacity(); }
140 
141  /// Ensures that the allocated size is at least the given size.
142  inline void Reserve(int capacity)
143  { if (capacity > Capacity()) { GrowSize(capacity); } }
144 
145  /// Access element
146  inline T & operator[](int i);
147 
148  /// Access const element
149  inline const T &operator[](int i) const;
150 
151  /// Append element to array, resize if necessary
152  inline int Append(const T & el);
153 
154  /// Append another array to this array, resize if necessary
155  inline int Append(const T *els, int nels);
156 
157  /// Append another array to this array, resize if necessary
158  inline int Append(const Array<T> &els) { return Append(els, els.Size()); }
159 
160  /// Prepend an element to the array, resize if necessary
161  inline int Prepend(const T &el);
162 
163  /// Return the last element in the array
164  inline T &Last();
165  inline const T &Last() const;
166 
167  /// Append element when it is not yet in the array, return index
168  inline int Union(const T & el);
169 
170  /// Return the first index where 'el' is found; return -1 if not found
171  inline int Find(const T &el) const;
172 
173  /// Do bisection search for 'el' in a sorted array; return -1 if not found.
174  inline int FindSorted(const T &el) const;
175 
176  /// Delete the last entry
177  inline void DeleteLast() { if (size > 0) { size--; } }
178 
179  /// Delete the first 'el' entry
180  inline void DeleteFirst(const T &el);
181 
182  /// Delete whole array
183  inline void DeleteAll();
184 
185  /// Create a copy of the current array
186  inline void Copy(Array &copy) const;
187 
188  /// Make this Array a reference to a pointer
189  inline void MakeRef(T *, int);
190 
191  /// Make this Array a reference to 'master'
192  inline void MakeRef(const Array &master);
193 
194  inline void GetSubArray(int offset, int sa_size, Array<T> &sa) const;
195 
196  /// Prints array to stream with width elements per row
197  void Print(std::ostream &out = mfem::out, int width = 4) const;
198 
199  /** @brief Save the Array to the stream @a out using the format @a fmt.
200  The format @a fmt can be:
201 
202  0 - write the size followed by all entries
203  1 - write only the entries
204  */
205  void Save(std::ostream &out, int fmt = 0) const;
206 
207  /** @brief Read an Array from the stream @a in using format @a fmt.
208  The format @a fmt can be:
209 
210  0 - read the size then the entries
211  1 - read Size() entries
212  */
213  void Load(std::istream &in, int fmt = 0);
214 
215  /** @brief Set the Array size to @a new_size and read that many entries from
216  the stream @a in. */
217  void Load(int new_size, std::istream &in)
218  { SetSize(new_size); Load(in, 1); }
219 
220  /** @brief Find the maximal element in the array, using the comparison
221  operator `<` for class T. */
222  T Max() const;
223 
224  /** @brief Find the minimal element in the array, using the comparison
225  operator `<` for class T. */
226  T Min() const;
227 
228  /// Sorts the array. This requires operator< to be defined for T.
229  void Sort() { std::sort((T*)data, data + size); }
230 
231  /// Sorts the array using the supplied comparison function object.
232  template<class Compare>
233  void Sort(Compare cmp) { std::sort((T*)data, data + size, cmp); }
234 
235  /** Removes duplicities from a sorted array. This requires operator== to be
236  defined for T. */
237  void Unique()
238  {
239  T* end = std::unique((T*)data, data + size);
240  SetSize(end - data);
241  }
242 
243  /// return true if the array is sorted.
244  int IsSorted();
245 
246  /// Partial Sum
247  void PartialSum();
248 
249  /// Sum all entries
250  T Sum();
251 
252  inline void operator=(const T &a);
253 
254  /// Copy data from a pointer. Size() elements are copied.
255  inline void Assign(const T *);
256 
257  template <typename U>
258  inline void CopyTo(U *dest) { std::copy(begin(), end(), dest); }
259 
260  template <typename U>
261  inline void CopyFrom(const U *src)
262  { std::memcpy(begin(), src, MemoryUsage()); }
263 
264  // STL-like begin/end
265  inline T* begin() { return data; }
266  inline T* end() { return data + size; }
267  inline const T* begin() const { return data; }
268  inline const T* end() const { return data + size; }
269 
270  long MemoryUsage() const { return Capacity() * sizeof(T); }
271 
272  /// Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
273  const T *Read(bool on_dev = true) const
274  { return mfem::Read(data, size, on_dev); }
275 
276  /// Shortcut for mfem::Read(a.GetMemory(), a.Size(), false).
277  const T *HostRead() const
278  { return mfem::Read(data, size, false); }
279 
280  /// Shortcut for mfem::Write(a.GetMemory(), a.Size(), on_dev).
281  T *Write(bool on_dev = true)
282  { return mfem::Write(data, size, on_dev); }
283 
284  /// Shortcut for mfem::Write(a.GetMemory(), a.Size(), false).
286  { return mfem::Write(data, size, false); }
287 
288  /// Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), on_dev).
289  T *ReadWrite(bool on_dev = true)
290  { return mfem::ReadWrite(data, size, on_dev); }
291 
292  /// Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), false).
294  { return mfem::ReadWrite(data, size, false); }
295 };
296 
297 template <class T>
298 inline bool operator==(const Array<T> &LHS, const Array<T> &RHS)
299 {
300  if ( LHS.Size() != RHS.Size() ) { return false; }
301  for (int i=0; i<LHS.Size(); i++)
302  {
303  if ( LHS[i] != RHS[i] ) { return false; }
304  }
305  return true;
306 }
307 
308 template <class T>
309 inline bool operator!=(const Array<T> &LHS, const Array<T> &RHS)
310 {
311  return !( LHS == RHS );
312 }
313 
314 
315 template <class T>
316 class Array2D;
317 
318 template <class T>
319 void Swap(Array2D<T> &, Array2D<T> &);
320 
321 /// Dynamic 2D array using row-major layout
322 template <class T>
323 class Array2D
324 {
325 private:
326  friend void Swap<T>(Array2D<T> &, Array2D<T> &);
327 
328  Array<T> array1d;
329  int M, N; // number of rows and columns
330 
331 public:
332  Array2D() { M = N = 0; }
333  Array2D(int m, int n) : array1d(m*n) { M = m; N = n; }
334 
335  void SetSize(int m, int n) { array1d.SetSize(m*n); M = m; N = n; }
336 
337  int NumRows() const { return M; }
338  int NumCols() const { return N; }
339 
340  inline const T &operator()(int i, int j) const;
341  inline T &operator()(int i, int j);
342 
343  inline const T *operator[](int i) const;
344  inline T *operator[](int i);
345 
346  const T *operator()(int i) const { return (*this)[i]; }
347  T *operator()(int i) { return (*this)[i]; }
348 
349  const T *GetRow(int i) const { return (*this)[i]; }
350  T *GetRow(int i) { return (*this)[i]; }
351 
352  /// Extract a copy of the @a i-th row into the Array @a sa.
353  void GetRow(int i, Array<T> &sa) const
354  {
355  sa.SetSize(N);
356  sa.Assign(GetRow(i));
357  }
358 
359  /** @brief Save the Array2D to the stream @a out using the format @a fmt.
360  The format @a fmt can be:
361 
362  0 - write the number of rows and columns, followed by all entries
363  1 - write only the entries, using row-major layout
364  */
365  void Save(std::ostream &out, int fmt = 0) const
366  {
367  if (fmt == 0) { out << NumRows() << ' ' << NumCols() << '\n'; }
368  array1d.Save(out, 1);
369  }
370 
371  /** @brief Read an Array2D from the stream @a in using format @a fmt.
372  The format @a fmt can be:
373 
374  0 - read the number of rows and columns, then the entries
375  1 - read NumRows() x NumCols() entries, using row-major layout
376  */
377  void Load(std::istream &in, int fmt = 0)
378  {
379  if (fmt == 0) { in >> M >> N; array1d.SetSize(M*N); }
380  array1d.Load(in, 1);
381  }
382 
383  /// Read an Array2D from a file
384  void Load(const char *filename, int fmt = 0);
385 
386  /** @brief Set the Array2D dimensions to @a new_size0 x @a new_size1 and read
387  that many entries from the stream @a in. */
388  void Load(int new_size0,int new_size1, std::istream &in)
389  { SetSize(new_size0,new_size1); Load(in, 1); }
390 
391  void Copy(Array2D &copy) const
392  { copy.M = M; copy.N = N; array1d.Copy(copy.array1d); }
393 
394  inline void operator=(const T &a)
395  { array1d = a; }
396 
397  /// Make this Array a reference to 'master'
398  inline void MakeRef(const Array2D &master)
399  { M = master.M; N = master.N; array1d.MakeRef(master.array1d); }
400 
401  /// Delete all dynamically allocated memory, resetting all dimensions to zero.
402  inline void DeleteAll() { M = 0; N = 0; array1d.DeleteAll(); }
403 
404  /// Prints array to stream with width elements per row
405  void Print(std::ostream &out = mfem::out, int width = 4);
406 };
407 
408 
409 template <class T>
410 class Array3D
411 {
412 private:
413  Array<T> array1d;
414  int N2, N3;
415 
416 public:
417  Array3D() { N2 = N3 = 0; }
418  Array3D(int n1, int n2, int n3)
419  : array1d(n1*n2*n3) { N2 = n2; N3 = n3; }
420 
421  void SetSize(int n1, int n2, int n3)
422  { array1d.SetSize(n1*n2*n3); N2 = n2; N3 = n3; }
423 
424  inline const T &operator()(int i, int j, int k) const;
425  inline T &operator()(int i, int j, int k);
426 };
427 
428 
429 /** A container for items of type T. Dynamically grows as items are added.
430  * Each item is accessible by its index. Items are allocated in larger chunks
431  * (blocks), so the 'Append' method is very fast on average.
432  */
433 template<typename T>
435 {
436 public:
437  BlockArray(int block_size = 16*1024);
438  BlockArray(const BlockArray<T> &other); // deep copy
440 
441  /// Allocate and construct a new item in the array, return its index.
442  int Append();
443 
444  /// Allocate and copy-construct a new item in the array, return its index.
445  int Append(const T &item);
446 
447  /// Access item of the array.
448  inline T& At(int index)
449  {
450  CheckIndex(index);
451  return blocks[index >> shift][index & mask];
452  }
453  inline const T& At(int index) const
454  {
455  CheckIndex(index);
456  return blocks[index >> shift][index & mask];
457  }
458 
459  /// Access item of the array.
460  inline T& operator[](int index) { return At(index); }
461  inline const T& operator[](int index) const { return At(index); }
462 
463  /// Return the number of items actually stored.
464  int Size() const { return size; }
465 
466  /// Return the current capacity of the BlockArray.
467  int Capacity() const { return blocks.Size()*(mask+1); }
468 
469  /// Destroy all items, set size to zero.
470  void DeleteAll() { Destroy(); blocks.DeleteAll(); size = 0; }
471 
472  void Swap(BlockArray<T> &other);
473 
474  long MemoryUsage() const;
475 
476 protected:
477  template <typename cA, typename cT>
479  {
480  public:
481  cT& operator*() const { return *ptr; }
482  cT* operator->() const { return ptr; }
483 
484  bool good() const { return !stop; }
485  int index() const { return (ptr - ref); }
486 
487  protected:
488  cA *array;
489  cT *ptr, *b_end, *ref;
491  bool stop;
492 
494  iterator_base(bool stop) : stop(stop) { }
496  : array(a), ptr(a->blocks[0]), ref(ptr), stop(false)
497  {
498  b_end_idx = std::min(a->size, a->mask+1);
499  b_end = ptr + b_end_idx;
500  }
501 
502  void next()
503  {
504  MFEM_ASSERT(!stop, "invalid use");
505  if (++ptr == b_end)
506  {
507  if (b_end_idx < array->size)
508  {
509  ptr = &array->At(b_end_idx);
510  ref = ptr - b_end_idx;
511  b_end_idx = std::min(array->size, (b_end_idx|array->mask) + 1);
512  b_end = &array->At(b_end_idx-1) + 1;
513  }
514  else
515  {
516  MFEM_ASSERT(b_end_idx == array->size, "invalid use");
517  stop = true;
518  }
519  }
520  }
521  };
522 
523 public:
524  class iterator : public iterator_base<BlockArray, T>
525  {
526  protected:
527  friend class BlockArray;
529 
530  iterator() { }
531  iterator(bool stop) : base(stop) { }
533 
534  public:
535  iterator &operator++() { base::next(); return *this; }
536 
537  bool operator==(const iterator &other) const { return base::stop; }
538  bool operator!=(const iterator &other) const { return !base::stop; }
539  };
540 
541  class const_iterator : public iterator_base<const BlockArray, const T>
542  {
543  protected:
544  friend class BlockArray;
546 
548  const_iterator(bool stop) : base(stop) { }
549  const_iterator(const BlockArray *a) : base(a) { }
550 
551  public:
552  const_iterator &operator++() { base::next(); return *this; }
553 
554  bool operator==(const const_iterator &other) const { return base::stop; }
555  bool operator!=(const const_iterator &other) const { return !base::stop; }
556  };
557 
558  iterator begin() { return size ? iterator(this) : iterator(true); }
559  iterator end() { return iterator(); }
560 
561  const_iterator cbegin() const
562  { return size ? const_iterator(this) : const_iterator(true); }
563  const_iterator cend() const { return const_iterator(); }
564 
565 protected:
567  int size, shift, mask;
568 
569  int Alloc();
570 
571  inline void CheckIndex(int index) const
572  {
573  MFEM_ASSERT(index >= 0 && index < size,
574  "Out of bounds access: " << index << ", size = " << size);
575  }
576 
577  void Destroy();
578 };
579 
580 
581 /// inlines ///
582 
583 template <class T>
584 inline void Swap(T &a, T &b)
585 {
586  T c = a;
587  a = b;
588  b = c;
589 }
590 
591 template <class T>
592 inline void Swap(Array<T> &a, Array<T> &b)
593 {
594  Swap(a.data, b.data);
595  Swap(a.size, b.size);
596 }
597 
598 template <class T>
599 inline Array<T>::Array(const Array &src)
600  : size(src.Size())
601 {
602  size > 0 ? data.New(size, src.data.GetMemoryType()) : data.Reset();
603  data.CopyFrom(src.data, size);
604  data.UseDevice(src.data.UseDevice());
605 }
606 
607 template <typename T> template <typename CT>
608 inline Array<T>::Array(const Array<CT> &src)
609  : size(src.Size())
610 {
611  size > 0 ? data.New(size) : data.Reset();
612  for (int i = 0; i < size; i++) { (*this)[i] = T(src[i]); }
613 }
614 
615 template <class T>
616 inline void Array<T>::GrowSize(int minsize)
617 {
618  const int nsize = std::max(minsize, 2 * data.Capacity());
619  Memory<T> p(nsize, data.GetMemoryType());
620  p.CopyFrom(data, size);
621  p.UseDevice(data.UseDevice());
622  data.Delete();
623  data = p;
624 }
625 
626 template <typename T> template <typename CT>
628 {
629  SetSize(src.Size());
630  for (int i = 0; i < size; i++) { (*this)[i] = T(src[i]); }
631  return *this;
632 }
633 
634 template <class T>
635 inline void Array<T>::SetSize(int nsize)
636 {
637  MFEM_ASSERT( nsize>=0, "Size must be non-negative. It is " << nsize );
638  if (nsize > Capacity())
639  {
640  GrowSize(nsize);
641  }
642  size = nsize;
643 }
644 
645 template <class T>
646 inline void Array<T>::SetSize(int nsize, const T &initval)
647 {
648  MFEM_ASSERT( nsize>=0, "Size must be non-negative. It is " << nsize );
649  if (nsize > size)
650  {
651  if (nsize > Capacity())
652  {
653  GrowSize(nsize);
654  }
655  for (int i = size; i < nsize; i++)
656  {
657  data[i] = initval;
658  }
659  }
660  size = nsize;
661 }
662 
663 template <class T>
664 inline void Array<T>::SetSize(int nsize, MemoryType mt)
665 {
666  MFEM_ASSERT(nsize >= 0, "invalid new size: " << nsize);
667  if (mt == data.GetMemoryType())
668  {
669  if (nsize <= Capacity())
670  {
671  size = nsize;
672  return;
673  }
674  }
675  const bool use_dev = data.UseDevice();
676  data.Delete();
677  if (nsize > 0)
678  {
679  data.New(nsize, mt);
680  size = nsize;
681  }
682  else
683  {
684  data.Reset();
685  size = 0;
686  }
687  data.UseDevice(use_dev);
688 }
689 
690 template <class T>
691 inline T &Array<T>::operator[](int i)
692 {
693  MFEM_ASSERT( i>=0 && i<size,
694  "Access element " << i << " of array, size = " << size );
695  return data[i];
696 }
697 
698 template <class T>
699 inline const T &Array<T>::operator[](int i) const
700 {
701  MFEM_ASSERT( i>=0 && i<size,
702  "Access element " << i << " of array, size = " << size );
703  return data[i];
704 }
705 
706 template <class T>
707 inline int Array<T>::Append(const T &el)
708 {
709  SetSize(size+1);
710  data[size-1] = el;
711  return size;
712 }
713 
714 template <class T>
715 inline int Array<T>::Append(const T *els, int nels)
716 {
717  const int old_size = size;
718 
719  SetSize(size + nels);
720  for (int i = 0; i < nels; i++)
721  {
722  data[old_size+i] = els[i];
723  }
724  return size;
725 }
726 
727 template <class T>
728 inline int Array<T>::Prepend(const T &el)
729 {
730  SetSize(size+1);
731  for (int i = size-1; i > 0; i--)
732  {
733  data[i] = data[i-1];
734  }
735  data[0] = el;
736  return size;
737 }
738 
739 template <class T>
740 inline T &Array<T>::Last()
741 {
742  MFEM_ASSERT(size > 0, "Array size is zero: " << size);
743  return data[size-1];
744 }
745 
746 template <class T>
747 inline const T &Array<T>::Last() const
748 {
749  MFEM_ASSERT(size > 0, "Array size is zero: " << size);
750  return data[size-1];
751 }
752 
753 template <class T>
754 inline int Array<T>::Union(const T &el)
755 {
756  int i = 0;
757  while ((i < size) && (data[i] != el)) { i++; }
758  if (i == size)
759  {
760  Append(el);
761  }
762  return i;
763 }
764 
765 template <class T>
766 inline int Array<T>::Find(const T &el) const
767 {
768  for (int i = 0; i < size; i++)
769  {
770  if (data[i] == el) { return i; }
771  }
772  return -1;
773 }
774 
775 template <class T>
776 inline int Array<T>::FindSorted(const T &el) const
777 {
778  const T *begin = data, *end = begin + size;
779  const T* first = std::lower_bound(begin, end, el);
780  if (first == end || !(*first == el)) { return -1; }
781  return first - begin;
782 }
783 
784 template <class T>
785 inline void Array<T>::DeleteFirst(const T &el)
786 {
787  for (int i = 0; i < size; i++)
788  {
789  if (data[i] == el)
790  {
791  for (i++; i < size; i++)
792  {
793  data[i-1] = data[i];
794  }
795  size--;
796  return;
797  }
798  }
799 }
800 
801 template <class T>
802 inline void Array<T>::DeleteAll()
803 {
804  const bool use_dev = data.UseDevice();
805  data.Delete();
806  data.Reset();
807  size = 0;
808  data.UseDevice(use_dev);
809 }
810 
811 template <typename T>
812 inline void Array<T>::Copy(Array &copy) const
813 {
814  copy.SetSize(Size(), data.GetMemoryType());
815  data.CopyTo(copy.data, Size());
816  copy.data.UseDevice(data.UseDevice());
817 }
818 
819 template <class T>
820 inline void Array<T>::MakeRef(T *p, int s)
821 {
822  data.Delete();
823  data.Wrap(p, s, false);
824  size = s;
825 }
826 
827 template <class T>
828 inline void Array<T>::MakeRef(const Array &master)
829 {
830  data.Delete();
831  data = master.data; // note: copies the device flag
832  size = master.size;
833  data.ClearOwnerFlags();
834 }
835 
836 template <class T>
837 inline void Array<T>::GetSubArray(int offset, int sa_size, Array<T> &sa) const
838 {
839  sa.SetSize(sa_size);
840  for (int i = 0; i < sa_size; i++)
841  {
842  sa[i] = (*this)[offset+i];
843  }
844 }
845 
846 template <class T>
847 inline void Array<T>::operator=(const T &a)
848 {
849  for (int i = 0; i < size; i++)
850  {
851  data[i] = a;
852  }
853 }
854 
855 template <class T>
856 inline void Array<T>::Assign(const T *p)
857 {
858  data.CopyFromHost(p, Size());
859 }
860 
861 
862 template <class T>
863 inline const T &Array2D<T>::operator()(int i, int j) const
864 {
865  MFEM_ASSERT( i>=0 && i< array1d.Size()/N && j>=0 && j<N,
866  "Array2D: invalid access of element (" << i << ',' << j
867  << ") in array of size (" << array1d.Size()/N << ',' << N
868  << ")." );
869  return array1d[i*N+j];
870 }
871 
872 template <class T>
873 inline T &Array2D<T>::operator()(int i, int j)
874 {
875  MFEM_ASSERT( i>=0 && i< array1d.Size()/N && j>=0 && j<N,
876  "Array2D: invalid access of element (" << i << ',' << j
877  << ") in array of size (" << array1d.Size()/N << ',' << N
878  << ")." );
879  return array1d[i*N+j];
880 }
881 
882 template <class T>
883 inline const T *Array2D<T>::operator[](int i) const
884 {
885  MFEM_ASSERT( i>=0 && i< array1d.Size()/N,
886  "Array2D: invalid access of row " << i << " in array with "
887  << array1d.Size()/N << " rows.");
888  return &array1d[i*N];
889 }
890 
891 template <class T>
892 inline T *Array2D<T>::operator[](int i)
893 {
894  MFEM_ASSERT( i>=0 && i< array1d.Size()/N,
895  "Array2D: invalid access of row " << i << " in array with "
896  << array1d.Size()/N << " rows.");
897  return &array1d[i*N];
898 }
899 
900 
901 template <class T>
902 inline void Swap(Array2D<T> &a, Array2D<T> &b)
903 {
904  Swap(a.array1d, b.array1d);
905  Swap(a.N, b.N);
906 }
907 
908 
909 template <class T>
910 inline const T &Array3D<T>::operator()(int i, int j, int k) const
911 {
912  MFEM_ASSERT(i >= 0 && i < array1d.Size() / N2 / N3 && j >= 0 && j < N2
913  && k >= 0 && k < N3,
914  "Array3D: invalid access of element ("
915  << i << ',' << j << ',' << k << ") in array of size ("
916  << array1d.Size() / N2 / N3 << ',' << N2 << ',' << N3 << ").");
917  return array1d[(i*N2+j)*N3+k];
918 }
919 
920 template <class T>
921 inline T &Array3D<T>::operator()(int i, int j, int k)
922 {
923  MFEM_ASSERT(i >= 0 && i < array1d.Size() / N2 / N3 && j >= 0 && j < N2
924  && k >= 0 && k < N3,
925  "Array3D: invalid access of element ("
926  << i << ',' << j << ',' << k << ") in array of size ("
927  << array1d.Size() / N2 / N3 << ',' << N2 << ',' << N3 << ").");
928  return array1d[(i*N2+j)*N3+k];
929 }
930 
931 
932 template<typename T>
934 {
935  mask = block_size-1;
936  MFEM_VERIFY(!(block_size & mask), "block_size must be a power of two.");
937 
938  size = shift = 0;
939  while ((1 << shift) < block_size) { shift++; }
940 }
941 
942 template<typename T>
944 {
945  blocks.SetSize(other.blocks.Size());
946 
947  size = other.size;
948  shift = other.shift;
949  mask = other.mask;
950 
951  int bsize = mask+1;
952  for (int i = 0; i < blocks.Size(); i++)
953  {
954  blocks[i] = (T*) new char[bsize * sizeof(T)];
955  }
956 
957  // copy all items
958  for (int i = 0; i < size; i++)
959  {
960  new (&At(i)) T(other[i]);
961  }
962 }
963 
964 template<typename T>
966 {
967  int bsize = mask+1;
968  if (size >= blocks.Size() * bsize)
969  {
970  T* new_block = (T*) new char[bsize * sizeof(T)];
971  blocks.Append(new_block);
972  }
973  return size++;
974 }
975 
976 template<typename T>
978 {
979  int index = Alloc();
980  new (&At(index)) T();
981  return index;
982 }
983 
984 template<typename T>
985 int BlockArray<T>::Append(const T &item)
986 {
987  int index = Alloc();
988  new (&At(index)) T(item);
989  return index;
990 }
991 
992 template<typename T>
994 {
995  mfem::Swap(blocks, other.blocks);
996  std::swap(size, other.size);
997  std::swap(shift, other.shift);
998  std::swap(mask, other.mask);
999 }
1000 
1001 template<typename T>
1003 {
1004  return blocks.Size()*(mask+1)*sizeof(T) +
1005  blocks.MemoryUsage();
1006 }
1007 
1008 template<typename T>
1010 {
1011  int bsize = size & mask;
1012  for (int i = blocks.Size(); i != 0; )
1013  {
1014  T *block = blocks[--i];
1015  for (int j = bsize; j != 0; )
1016  {
1017  block[--j].~T();
1018  }
1019  delete [] (char*) block;
1020  bsize = mask+1;
1021  }
1022 }
1023 
1024 } // namespace mfem
1025 
1026 #endif
T * HostReadWrite()
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), false).
Definition: array.hpp:293
int Size() const
Logical size of the array.
Definition: array.hpp:124
const_iterator(const BlockArray *a)
Definition: array.hpp:549
void Load(std::istream &in, int fmt=0)
Read an Array from the stream in using format fmt. The format fmt can be:
Definition: array.cpp:53
Array(T *_data, int asize)
Definition: array.hpp:70
void Unique()
Definition: array.hpp:237
Memory< T > & GetMemory()
Return a reference to the Memory object used by the Array.
Definition: array.hpp:103
int NumCols() const
Definition: array.hpp:338
T * end()
Definition: array.hpp:266
const_iterator cbegin() const
Definition: array.hpp:561
const T * begin() const
Definition: array.hpp:267
iterator_base< const BlockArray, const T > base
Definition: array.hpp:545
const T * operator()(int i) const
Definition: array.hpp:346
T * GetRow(int i)
Definition: array.hpp:350
int Capacity() const
Return the current capacity of the BlockArray.
Definition: array.hpp:467
void Load(std::istream &in, int fmt=0)
Read an Array2D from the stream in using format fmt. The format fmt can be:
Definition: array.hpp:377
const T * HostRead() const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), false).
Definition: array.hpp:277
int size
Size of the array.
Definition: array.hpp:50
int Size() const
Return the number of items actually stored.
Definition: array.hpp:464
void Save(std::ostream &out, int fmt=0) const
Save the Array2D to the stream out using the format fmt. The format fmt can be:
Definition: array.hpp:365
void Copy(Array &copy) const
Create a copy of the current array.
Definition: array.hpp:812
T * GetData()
Returns the data.
Definition: array.hpp:98
T * operator()(int i)
Definition: array.hpp:347
T * Write(Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for write access to mem with the mfem::Device&#39;s DeviceMemoryClass, if on_dev = true...
Definition: device.hpp:312
void operator=(const T &a)
Definition: array.hpp:394
void Save(std::ostream &out, int fmt=0) const
Save the Array to the stream out using the format fmt. The format fmt can be:
Definition: array.cpp:40
bool UseDevice() const
Return the device flag of the Memory object used by the Array.
Definition: array.hpp:109
Array(int asize)
Creates array of asize elements.
Definition: array.hpp:64
void Sort(Compare cmp)
Sorts the array using the supplied comparison function object.
Definition: array.hpp:233
T Sum()
Sum all entries.
Definition: array.cpp:115
bool operator==(const iterator &other) const
Definition: array.hpp:537
void MakeRef(const Array2D &master)
Make this Array a reference to &#39;master&#39;.
Definition: array.hpp:398
void CopyFrom(const Memory &src, int size)
Copy size entries from src to *this.
iterator & operator++()
Definition: array.hpp:535
void Load(int new_size, std::istream &in)
Set the Array size to new_size and read that many entries from the stream in.
Definition: array.hpp:217
const T & At(int index) const
Definition: array.hpp:453
bool operator==(const const_iterator &other) const
Definition: array.hpp:554
void DeleteFirst(const T &el)
Delete the first &#39;el&#39; entry.
Definition: array.hpp:785
T & operator[](int index)
Access item of the array.
Definition: array.hpp:460
void SetSize(int n1, int n2, int n3)
Definition: array.hpp:421
T Min() const
Find the minimal element in the array, using the comparison operator &lt; for class T.
Definition: array.cpp:85
iterator(BlockArray *a)
Definition: array.hpp:532
void DeleteAll()
Delete whole array.
Definition: array.hpp:802
int Append(const Array< T > &els)
Append another array to this array, resize if necessary.
Definition: array.hpp:158
void CopyTo(U *dest)
Definition: array.hpp:258
iterator begin()
Definition: array.hpp:558
~Array()
Destructor.
Definition: array.hpp:82
void SetSize(int m, int n)
Definition: array.hpp:335
void Copy(Array2D &copy) const
Definition: array.hpp:391
bool OwnsData() const
Return true if the data will be deleted by the array.
Definition: array.hpp:112
const T & operator()(int i, int j) const
Definition: array.hpp:863
const T * GetData() const
Returns the data.
Definition: array.hpp:100
int Append(const T &el)
Append element to array, resize if necessary.
Definition: array.hpp:707
void DeleteAll()
Destroy all items, set size to zero.
Definition: array.hpp:470
void GetSubArray(int offset, int sa_size, Array< T > &sa) const
Definition: array.hpp:837
T & operator[](int i)
Access element.
Definition: array.hpp:691
double b
Definition: lissajous.cpp:42
void LoseData()
NULL-ifies the data.
Definition: array.hpp:118
T Max() const
Find the maximal element in the array, using the comparison operator &lt; for class T.
Definition: array.cpp:68
long MemoryUsage() const
Definition: array.hpp:1002
void Reserve(int capacity)
Ensures that the allocated size is at least the given size.
Definition: array.hpp:142
void CopyFrom(const U *src)
Definition: array.hpp:261
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
Definition: array.hpp:273
bool operator!=(const Array< T > &LHS, const Array< T > &RHS)
Definition: array.hpp:309
T * begin()
Definition: array.hpp:265
void Assign(const T *)
Copy data from a pointer. Size() elements are copied.
Definition: array.hpp:856
long MemoryUsage() const
Definition: array.hpp:270
void Sort()
Sorts the array. This requires operator&lt; to be defined for T.
Definition: array.hpp:229
int FindSorted(const T &el) const
Do bisection search for &#39;el&#39; in a sorted array; return -1 if not found.
Definition: array.hpp:776
void StealData(T **p)
Changes the ownership of the data.
Definition: array.hpp:115
const T * Read(const Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for read access to mem with the mfem::Device&#39;s DeviceMemoryClass, if on_dev = true...
Definition: device.hpp:295
int Union(const T &el)
Append element when it is not yet in the array, return index.
Definition: array.hpp:754
Dynamic 2D array using row-major layout.
Definition: array.hpp:316
Memory< T > data
Pointer to data.
Definition: array.hpp:48
void Destroy()
Definition: array.hpp:1009
void Print(std::ostream &out=mfem::out, int width=4)
Prints array to stream with width elements per row.
Definition: array.cpp:155
void Swap(Array< T > &, Array< T > &)
Definition: array.hpp:592
bool operator==(const Array< T > &LHS, const Array< T > &RHS)
Definition: array.hpp:298
void GrowSize(int minsize)
Definition: array.hpp:616
int IsSorted()
return true if the array is sorted.
Definition: array.cpp:127
BlockArray(int block_size=16 *1024)
Definition: array.hpp:933
MemoryType
Memory types supported by MFEM.
Definition: mem_manager.hpp:27
int Find(const T &el) const
Return the first index where &#39;el&#39; is found; return -1 if not found.
Definition: array.hpp:766
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
Definition: array.hpp:635
const T * operator[](int i) const
Definition: array.hpp:883
void PartialSum()
Partial Sum.
Definition: array.cpp:103
T * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), on_dev).
Definition: array.hpp:289
void DeleteLast()
Delete the last entry.
Definition: array.hpp:177
const T & operator[](int index) const
Definition: array.hpp:461
void MakeDataOwner() const
Make the Array own the data.
Definition: array.hpp:121
Array2D(int m, int n)
Definition: array.hpp:333
Array(MemoryType mt)
Creates an empty array with a given MemoryType.
Definition: array.hpp:61
T * HostWrite()
Shortcut for mfem::Write(a.GetMemory(), a.Size(), false).
Definition: array.hpp:285
double a
Definition: lissajous.cpp:41
bool operator!=(const iterator &other) const
Definition: array.hpp:538
void CheckIndex(int index) const
Definition: array.hpp:571
T * ReadWrite(Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for read+write access to mem with the mfem::Device&#39;s DeviceMemoryClass, if on_dev = true, or the mfem::Device&#39;s HostMemoryClass, otherwise.
Definition: device.hpp:329
Array()
Creates an empty array.
Definition: array.hpp:58
Array< T * > blocks
Definition: array.hpp:566
int Capacity() const
Definition: array.hpp:139
int index(int i, int j, int nx, int ny)
Definition: life.cpp:241
bool operator!=(const const_iterator &other) const
Definition: array.hpp:555
Class used by MFEM to store pointers to host and/or device memory.
const_iterator & operator++()
Definition: array.hpp:552
T & Last()
Return the last element in the array.
Definition: array.hpp:740
void Print(std::ostream &out=mfem::out, int width=4) const
Prints array to stream with width elements per row.
Definition: array.cpp:23
iterator_base< BlockArray, T > base
Definition: array.hpp:528
T * Write(bool on_dev=true)
Shortcut for mfem::Write(a.GetMemory(), a.Size(), on_dev).
Definition: array.hpp:281
void MakeRef(T *, int)
Make this Array a reference to a pointer.
Definition: array.hpp:820
iterator end()
Definition: array.hpp:559
Array< T > & operator=(const Array< T > &src)
Assignment operator: deep copy.
Definition: array.hpp:85
const_iterator cend() const
Definition: array.hpp:563
const Memory< T > & GetMemory() const
Return a reference to the Memory object used by the Array, const version.
Definition: array.hpp:106
void DeleteAll()
Delete all dynamically allocated memory, resetting all dimensions to zero.
Definition: array.hpp:402
const T & operator()(int i, int j, int k) const
Definition: array.hpp:910
Array3D(int n1, int n2, int n3)
Definition: array.hpp:418
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition: globals.hpp:66
const T * end() const
Definition: array.hpp:268
T & At(int index)
Access item of the array.
Definition: array.hpp:448
const T * GetRow(int i) const
Definition: array.hpp:349
int NumRows() const
Definition: array.hpp:337
int Prepend(const T &el)
Prepend an element to the array, resize if necessary.
Definition: array.hpp:728
int Append()
Allocate and construct a new item in the array, return its index.
Definition: array.hpp:977
void Load(int new_size0, int new_size1, std::istream &in)
Set the Array2D dimensions to new_size0 x new_size1 and read that many entries from the stream in...
Definition: array.hpp:388
void Swap(BlockArray< T > &other)
Definition: array.hpp:993
void GetRow(int i, Array< T > &sa) const
Extract a copy of the i-th row into the Array sa.
Definition: array.hpp:353