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