MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
array.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, 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#include <type_traits>
26#include <initializer_list>
27
28namespace mfem
29{
30
31template <class T>
32class Array;
33
34template <class T>
35void Swap(Array<T> &, Array<T> &);
36
37/**
38 Abstract data type Array.
39
40 Array<T> is an automatically increasing array containing elements of the
41 generic type T, which must be a trivial type, see `std::is_trivial`. The
42 allocated size may be larger then the logical size of the array. The elements
43 can be accessed by the [] operator, the range is 0 to size-1.
44*/
45template <class T>
46class Array
47{
48protected:
49 /// Pointer to data
51 /// Size of the array
52 int size;
53
54 inline void GrowSize(int minsize);
55
56 static_assert(std::is_trivial<T>::value, "type T must be trivial");
57
58public:
59 friend void Swap<T>(Array<T> &, Array<T> &);
60
61 /// Creates an empty array
62 inline Array() : size(0) { }
63
64 /// Creates an empty array with a given MemoryType
65 inline Array(MemoryType mt) : data(mt), size(0) { }
66
67 /// Creates array of @a asize elements
68 explicit inline Array(int asize)
69 : size(asize) { if (asize > 0) { data.New(asize); } }
70
71 /// Creates array of @a asize elements with a given MemoryType
72 inline Array(int asize, MemoryType mt)
73 : data(mt), size(asize) { if (asize > 0) { data.New(asize, mt); } }
74
75 /** @brief Creates array using an externally allocated host pointer @a data_
76 to @a asize elements. If @a own_data is true, the array takes ownership
77 of the pointer.
78
79 When @a own_data is true, the pointer @a data_ must be allocated with
80 MemoryType given by MemoryManager::GetHostMemoryType(). */
81 inline Array(T *data_, int asize, bool own_data = false)
82 { data.Wrap(data_, asize, own_data); size = asize; }
83
84 /// Copy constructor: deep copy from @a src
85 /** This method supports source arrays using any MemoryType. */
86 inline Array(const Array &src);
87
88 /// Copy constructor (deep copy) from 'src', an Array of convertible type.
89 template <typename CT>
90 inline Array(const Array<CT> &src);
91
92 /// Construct an Array from a C-style array of static length
93 template <typename CT, int N>
94 explicit inline Array(const CT (&values)[N]);
95
96 /// Construct an Array from a braced initializer list of convertible type
97 template <typename CT, typename std::enable_if<
98 std::is_convertible<CT,T>::value,bool>::type = true>
99 explicit inline Array(std::initializer_list<CT> values);
100
101 /// Move constructor ("steals" data from 'src')
102 inline Array(Array<T> &&src) : Array() { Swap(src, *this); }
103
104 /// Destructor
105 inline ~Array() { data.Delete(); }
106
107 /// Assignment operator: deep copy from 'src'.
108 Array<T> &operator=(const Array<T> &src) { src.Copy(*this); return *this; }
109
110 /// Assignment operator (deep copy) from @a src, an Array of convertible type.
111 template <typename CT>
112 inline Array &operator=(const Array<CT> &src);
113
114 /// Return the data as 'T *'
115 inline operator T *() { return data; }
116
117 /// Return the data as 'const T *'
118 inline operator const T *() const { return data; }
119
120 /// Returns the data
121 inline T *GetData() { return data; }
122 /// Returns the data
123 inline const T *GetData() const { return data; }
124
125 /// Return a reference to the Memory object used by the Array.
126 Memory<T> &GetMemory() { return data; }
127
128 /// Return a reference to the Memory object used by the Array, const version.
129 const Memory<T> &GetMemory() const { return data; }
130
131 /// Return the device flag of the Memory object used by the Array
132 bool UseDevice() const { return data.UseDevice(); }
133
134 /// Return true if the data will be deleted by the Array
135 inline bool OwnsData() const { return data.OwnsHostPtr(); }
136
137 /// Changes the ownership of the data
138 inline void StealData(T **p) { *p = data; data.Reset(); size = 0; }
139
140 /// NULL-ifies the data
141 inline void LoseData() { data.Reset(); size = 0; }
142
143 /// Make the Array own the data
144 void MakeDataOwner() const { data.SetHostPtrOwner(true); }
145
146 /// Return the logical size of the array.
147 inline int Size() const { return size; }
148
149 /// Change the logical size of the array, keep existing entries.
150 inline void SetSize(int nsize);
151
152 /// Same as SetSize(int) plus initialize new entries with 'initval'.
153 inline void SetSize(int nsize, const T &initval);
154
155 /** @brief Resize the array to size @a nsize using MemoryType @a mt. Note
156 that unlike the other versions of SetSize(), the current content of the
157 array is not preserved. */
158 inline void SetSize(int nsize, MemoryType mt);
159
160 /** Maximum number of entries the array can store without allocating more
161 memory. */
162 inline int Capacity() const { return data.Capacity(); }
163
164 /// Ensures that the allocated size is at least the given size.
165 inline void Reserve(int capacity)
166 { if (capacity > Capacity()) { GrowSize(capacity); } }
167
168 /// Reference access to the ith element.
169 inline T & operator[](int i);
170
171 /// Const reference access to the ith element.
172 inline const T &operator[](int i) const;
173
174 /// Append element 'el' to array, resize if necessary.
175 inline int Append(const T & el);
176
177 /// Append another array to this array, resize if necessary.
178 inline int Append(const T *els, int nels);
179
180 /// Append another array to this array, resize if necessary.
181 inline int Append(const Array<T> &els) { return Append(els, els.Size()); }
182
183 /// Prepend an 'el' to the array, resize if necessary.
184 inline int Prepend(const T &el);
185
186 /// Return the last element in the array.
187 inline T &Last();
188
189 /// Return the last element in the array.
190 inline const T &Last() const;
191
192 /// Append element when it is not yet in the array, return index.
193 inline int Union(const T & el);
194
195 /// Return the first index where 'el' is found; return -1 if not found.
196 inline int Find(const T &el) const;
197
198 /// Do bisection search for 'el' in a sorted array; return -1 if not found.
199 inline int FindSorted(const T &el) const;
200
201 /// Delete the last entry of the array.
202 inline void DeleteLast() { if (size > 0) { size--; } }
203
204 /// Delete the first entry with value == 'el'.
205 inline void DeleteFirst(const T &el);
206
207 /// Delete the whole array.
208 inline void DeleteAll();
209
210 /// Reduces the capacity of the array to exactly match the current size.
211 inline void ShrinkToFit();
212
213 /// Create a copy of the internal array to the provided @a copy.
214 inline void Copy(Array &copy) const;
215
216 /// Make this Array a reference to a pointer.
217 /** When @a own_data is true, the pointer @a data_ must be allocated with
218 MemoryType given by MemoryManager::GetHostMemoryType(). */
219 inline void MakeRef(T *data_, int size_, bool own_data = false);
220
221 /// Make this Array a reference to a pointer.
222 /** When @a own_data is true, the pointer @a data_ must be allocated with
223 MemoryType given by @a mt. */
224 inline void MakeRef(T *data_, int size, MemoryType mt, bool own_data);
225
226 /// Make this Array a reference to 'master'.
227 inline void MakeRef(const Array &master);
228
229 /**
230 * @brief Permute the array using the provided indices. Sorts the indices
231 * variable in the process, thereby destroying the permutation. The rvalue
232 * reference is to be used when this destruction is allowed, whilst the const
233 * reference preserves at the cost of duplication.
234 *
235 * @param indices The indices of the ordering. data[i] = data[indices[i]].
236 */
237 template <typename I>
238 inline void Permute(I &&indices);
239 template <typename I>
240 inline void Permute(const I &indices) { Permute(I(indices)); }
241
242 /// Copy sub array starting from @a offset out to the provided @a sa.
243 inline void GetSubArray(int offset, int sa_size, Array<T> &sa) const;
244
245 /// Prints array to stream with width elements per row.
246 void Print(std::ostream &out = mfem::out, int width = 4) const;
247
248 /** @brief Save the Array to the stream @a out using the format @a fmt.
249 The format @a fmt can be:
250
251 0 - write the size followed by all entries
252 1 - write only the entries
253 */
254 void Save(std::ostream &out, int fmt = 0) const;
255
256 /** @brief Read an Array from the stream @a in using format @a fmt.
257 The format @a fmt can be:
258
259 0 - read the size then the entries
260 1 - read Size() entries
261 */
262 void Load(std::istream &in, int fmt = 0);
263
264 /** @brief Set the Array size to @a new_size and read that many entries from
265 the stream @a in. */
266 void Load(int new_size, std::istream &in)
267 { SetSize(new_size); Load(in, 1); }
268
269 /** @brief Find the maximal element in the array, using the comparison
270 operator `<` for class T. */
271 T Max() const;
272
273 /** @brief Find the minimal element in the array, using the comparison
274 operator `<` for class T. */
275 T Min() const;
276
277 /// Sorts the array in ascending order. This requires operator< to be defined for T.
278 void Sort() { std::sort((T*)data, data + size); }
279
280 /// Sorts the array in ascending order using the supplied comparison function object.
281 template<class Compare>
282 void Sort(Compare cmp) { std::sort((T*)data, data + size, cmp); }
283
284 /** @brief Removes duplicities from a sorted array. This requires
285 operator== to be defined for T. */
286 void Unique()
287 {
288 T* end = std::unique((T*)data, data + size);
289 SetSize((int)(end - data));
290 }
291
292 /// Return 1 if the array is sorted from lowest to highest. Otherwise return 0.
293 int IsSorted() const;
294
295 /// Does the Array have Size zero.
296 bool IsEmpty() const { return Size() == 0; }
297
298 /// Fill the entries of the array with the cumulative sum of the entries.
299 void PartialSum();
300
301 /// Return the sum of all the array entries using the '+'' operator for class 'T'.
302 T Sum() const;
303
304 /// Set all entries of the array to the provided constant.
305 inline void operator=(const T &a);
306
307 /// Copy data from a pointer. 'Size()' elements are copied.
308 inline void Assign(const T *);
309
310 /// STL-like copyTo @a dest from begin to end.
311 template <typename U>
312 inline void CopyTo(U *dest) { std::copy(begin(), end(), dest); }
313
314 /** @brief Copy from @a src into this array. Copies enough entries to
315 fill the Capacity size of this array. Careful this does not update
316 the Size to match this Capacity after this.*/
317 template <typename U>
318 inline void CopyFrom(const U *src)
319 { std::memcpy(begin(), src, MemoryUsage()); }
320
321 /// STL-like begin. Returns pointer to the first element of the array.
322 inline T* begin() { return data; }
323
324 /// STL-like end. Returns pointer after the last element of the array.
325 inline T* end() { return data + size; }
326
327 /// STL-like begin. Returns const pointer to the first element of the array.
328 inline const T* begin() const { return data; }
329
330 /// STL-like end. Returns const pointer after the last element of the array.
331 inline const T* end() const { return data + size; }
332
333 /// Returns the number of bytes allocated for the array including any reserve.
334 std::size_t MemoryUsage() const { return Capacity() * sizeof(T); }
335
336 /// Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
337 const T *Read(bool on_dev = true) const
338 { return mfem::Read(data, size, on_dev); }
339
340 /// Shortcut for mfem::Read(a.GetMemory(), a.Size(), false).
341 const T *HostRead() const
342 { return mfem::Read(data, size, false); }
343
344 /// Shortcut for mfem::Write(a.GetMemory(), a.Size(), on_dev).
345 T *Write(bool on_dev = true)
346 { return mfem::Write(data, size, on_dev); }
347
348 /// Shortcut for mfem::Write(a.GetMemory(), a.Size(), false).
350 { return mfem::Write(data, size, false); }
351
352 /// Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), on_dev).
353 T *ReadWrite(bool on_dev = true)
354 { return mfem::ReadWrite(data, size, on_dev); }
355
356 /// Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), false).
358 { return mfem::ReadWrite(data, size, false); }
359};
360
361template <class T>
362inline bool operator==(const Array<T> &LHS, const Array<T> &RHS)
363{
364 if ( LHS.Size() != RHS.Size() ) { return false; }
365 for (int i=0; i<LHS.Size(); i++)
366 {
367 if ( LHS[i] != RHS[i] ) { return false; }
368 }
369 return true;
370}
371
372template <class T>
373inline bool operator!=(const Array<T> &LHS, const Array<T> &RHS)
374{
375 return !( LHS == RHS );
376}
377
378
379/// Utility function similar to std::as_const in c++17.
380template <typename T> const T &AsConst(const T &a) { return a; }
381
382
383template <class T>
384class Array2D;
385
386template <class T>
387void Swap(Array2D<T> &, Array2D<T> &);
388
389/// Dynamic 2D array using row-major layout
390template <class T>
392{
393private:
394 friend void Swap<T>(Array2D<T> &, Array2D<T> &);
395
396 Array<T> array1d;
397 int M, N; // number of rows and columns
398
399public:
400 Array2D() { M = N = 0; }
401 Array2D(int m, int n) : array1d(m*n) { M = m; N = n; }
402
403 Array2D(const Array2D &) = default;
404
405 void SetSize(int m, int n) { array1d.SetSize(m*n); M = m; N = n; }
406
407 int NumRows() const { return M; }
408 int NumCols() const { return N; }
409
410 inline const T &operator()(int i, int j) const;
411 inline T &operator()(int i, int j);
412
413 inline const T *operator[](int i) const;
414 inline T *operator[](int i);
415
416 const T *operator()(int i) const { return (*this)[i]; }
417 T *operator()(int i) { return (*this)[i]; }
418
419 const T *GetRow(int i) const { return (*this)[i]; }
420 T *GetRow(int i) { return (*this)[i]; }
421
422 /// Extract a copy of the @a i-th row into the Array @a sa.
423 void GetRow(int i, Array<T> &sa) const
424 {
425 sa.SetSize(N);
426 sa.Assign(GetRow(i));
427 }
428
429 /** @brief Save the Array2D to the stream @a out using the format @a fmt.
430 The format @a fmt can be:
431
432 0 - write the number of rows and columns, followed by all entries
433 1 - write only the entries, using row-major layout
434 */
435 void Save(std::ostream &os, int fmt = 0) const
436 {
437 if (fmt == 0) { os << NumRows() << ' ' << NumCols() << '\n'; }
438 array1d.Save(os, 1);
439 }
440
441 /** @brief Read an Array2D from the stream @a in using format @a fmt.
442 The format @a fmt can be:
443
444 0 - read the number of rows and columns, then the entries
445 1 - read NumRows() x NumCols() entries, using row-major layout
446 */
447 void Load(std::istream &in, int fmt = 0)
448 {
449 if (fmt == 0) { in >> M >> N; array1d.SetSize(M*N); }
450 array1d.Load(in, 1);
451 }
452
453 /// Read an Array2D from a file
454 void Load(const char *filename, int fmt = 0);
455
456 /** @brief Set the Array2D dimensions to @a new_size0 x @a new_size1 and read
457 that many entries from the stream @a in. */
458 void Load(int new_size0,int new_size1, std::istream &in)
459 { SetSize(new_size0,new_size1); Load(in, 1); }
460
461 void Copy(Array2D &copy) const
462 { copy.M = M; copy.N = N; array1d.Copy(copy.array1d); }
463
464 inline void operator=(const T &a)
465 { array1d = a; }
466
467 inline Array2D& operator=(const Array2D &a) = default;
468
469 /// Make this Array a reference to 'master'
470 inline void MakeRef(const Array2D &master)
471 { M = master.M; N = master.N; array1d.MakeRef(master.array1d); }
472
473 /// Delete all dynamically allocated memory, resetting all dimensions to zero.
474 inline void DeleteAll() { M = 0; N = 0; array1d.DeleteAll(); }
475
476 /// Prints array to stream with width elements per row
477 void Print(std::ostream &out = mfem::out, int width = 4);
478};
479
480
481template <class T>
483{
484private:
485 Array<T> array1d;
486 int N2, N3;
487
488public:
489 Array3D() { N2 = N3 = 0; }
490 Array3D(int n1, int n2, int n3)
491 : array1d(n1*n2*n3) { N2 = n2; N3 = n3; }
492
493 void SetSize(int n1, int n2, int n3)
494 { array1d.SetSize(n1*n2*n3); N2 = n2; N3 = n3; }
495
496 inline const T &operator()(int i, int j, int k) const;
497 inline T &operator()(int i, int j, int k);
498
499 inline void operator=(const T &a)
500 { array1d = a; }
501};
502
503
504/** A container for items of type T. Dynamically grows as items are added.
505 * Each item is accessible by its index. Items are allocated in larger chunks
506 * (blocks), so the 'Append' method is very fast on average.
507 */
508template<typename T>
510{
511public:
512 BlockArray(int block_size = 16*1024);
513 BlockArray(const BlockArray<T> &other); // deep copy
514 BlockArray& operator=(const BlockArray&) = delete; // not supported
515 BlockArray(BlockArray<T> &&other) = default;
516 BlockArray& operator=(BlockArray<T> &&other) = default;
518
519 /// Allocate and construct a new item in the array, return its index.
520 int Append();
521
522 /// Allocate and copy-construct a new item in the array, return its index.
523 int Append(const T &item);
524
525 /// Access item of the array.
526 inline T& At(int index)
527 {
529 return blocks[index >> shift][index & mask];
530 }
531 inline const T& At(int index) const
532 {
534 return blocks[index >> shift][index & mask];
535 }
536
537 /// Access item of the array.
538 inline T& operator[](int index) { return At(index); }
539 inline const T& operator[](int index) const { return At(index); }
540
541 /// Return the number of items actually stored.
542 int Size() const { return size; }
543
544 /// Return the current capacity of the BlockArray.
545 int Capacity() const { return blocks.Size()*(mask+1); }
546
547 /// Destroy all items, set size to zero.
548 void DeleteAll() { Destroy(); blocks.DeleteAll(); size = 0; }
549
550 void Swap(BlockArray<T> &other);
551
552 std::size_t MemoryUsage() const;
553
554protected:
555 template <typename cA, typename cT>
557 {
558 public:
559 cT& operator*() const { return *ptr; }
560 cT* operator->() const { return ptr; }
561
562 bool good() const { return !stop; }
563 int index() const { return (ptr - ref); }
564
565 protected:
566 cA *array;
567 cT *ptr, *b_end, *ref;
569 bool stop;
570
574 : array(a), ptr(a->blocks[0]), ref(ptr), stop(false)
575 {
576 b_end_idx = std::min(a->size, a->mask+1);
577 b_end = ptr + b_end_idx;
578 }
579
580 void next()
581 {
582 MFEM_ASSERT(!stop, "invalid use");
583 if (++ptr == b_end)
584 {
586 {
587 ptr = &array->At(b_end_idx);
588 ref = ptr - b_end_idx;
589 b_end_idx = std::min(array->size, (b_end_idx|array->mask) + 1);
590 b_end = &array->At(b_end_idx-1) + 1;
591 }
592 else
593 {
594 MFEM_ASSERT(b_end_idx == array->size, "invalid use");
595 stop = true;
596 }
597 }
598 }
599 };
600
601public:
602 class iterator : public iterator_base<BlockArray, T>
603 {
604 protected:
605 friend class BlockArray;
607
609 iterator(bool stop) : base(stop) { }
611
612 public:
613 iterator &operator++() { base::next(); return *this; }
614
615 bool operator==(const iterator &other) const { return base::stop; }
616 bool operator!=(const iterator &other) const { return !base::stop; }
617 };
618
619 class const_iterator : public iterator_base<const BlockArray, const T>
620 {
621 protected:
622 friend class BlockArray;
624
628
629 public:
630 const_iterator &operator++() { base::next(); return *this; }
631
632 bool operator==(const const_iterator &other) const { return base::stop; }
633 bool operator!=(const const_iterator &other) const { return !base::stop; }
634 };
635
636 iterator begin() { return size ? iterator(this) : iterator(true); }
637 iterator end() { return iterator(); }
638 const_iterator begin() const { return cbegin(); }
639 const_iterator end() const { return cend(); }
640
642 { return size ? const_iterator(this) : const_iterator(true); }
643 const_iterator cend() const { return const_iterator(); }
644
645protected:
648
649 int Alloc();
650
651 inline void CheckIndex(int index) const
652 {
653 MFEM_ASSERT(index >= 0 && index < size,
654 "Out of bounds access: " << index << ", size = " << size);
655 }
656
657 void Destroy();
658};
659
660
661/// inlines ///
662
663template <class T>
664inline void Swap(T &a, T &b)
665{
666 T c = a;
667 a = b;
668 b = c;
669}
670
671template <class T>
672inline void Swap(Array<T> &a, Array<T> &b)
673{
674 Swap(a.data, b.data);
675 Swap(a.size, b.size);
676}
677
678template <class T>
679inline Array<T>::Array(const Array &src)
680 : size(src.Size())
681{
682 size > 0 ? data.New(size, src.data.GetMemoryType()) : data.Reset();
683 data.CopyFrom(src.data, size);
684 data.UseDevice(src.data.UseDevice());
685}
686
687template <typename T> template <typename CT>
688inline Array<T>::Array(const Array<CT> &src)
689 : size(src.Size())
690{
691 size > 0 ? data.New(size) : data.Reset();
692 for (int i = 0; i < size; i++) { (*this)[i] = T(src[i]); }
693}
694
695template <typename T>
696template <typename CT, typename std::enable_if<
697 std::is_convertible<CT,T>::value,bool>::type>
698inline Array<T>::Array(std::initializer_list<CT> values) : Array(values.size())
699{
700 std::copy(values.begin(), values.end(), begin());
701}
702
703template <typename T> template <typename CT, int N>
704inline Array<T>::Array(const CT (&values)[N]) : Array(N)
705{
706 std::copy(values, values + N, begin());
707}
708
709template <class T>
710inline void Array<T>::GrowSize(int minsize)
711{
712 const int nsize = std::max(minsize, 2 * data.Capacity());
713 Memory<T> p(nsize, data.GetMemoryType());
714 p.CopyFrom(data, size);
715 p.UseDevice(data.UseDevice());
716 data.Delete();
717 data = p;
718}
719
720template <typename T>
722{
723 if (Capacity() == size) { return; }
724 Memory<T> p(size, data.GetMemoryType());
725 p.CopyFrom(data, size);
726 p.UseDevice(data.UseDevice());
727 data.Delete();
728 data = p;
729}
730
731template <typename T>
732template <typename I>
733inline void Array<T>::Permute(I &&indices)
734{
735 for (int i = 0; i < size; i++)
736 {
737 auto current = i;
738 while (i != indices[current])
739 {
740 auto next = indices[current];
741 std::swap(data[current], data[next]);
742 indices[current] = current;
743 current = next;
744 }
745 indices[current] = current;
746 }
747}
748
749template <typename T> template <typename CT>
751{
752 SetSize(src.Size());
753 for (int i = 0; i < size; i++) { (*this)[i] = T(src[i]); }
754 return *this;
755}
756
757template <class T>
758inline void Array<T>::SetSize(int nsize)
759{
760 MFEM_ASSERT( nsize>=0, "Size must be non-negative. It is " << nsize );
761 if (nsize > Capacity())
762 {
763 GrowSize(nsize);
764 }
765 size = nsize;
766}
767
768template <class T>
769inline void Array<T>::SetSize(int nsize, const T &initval)
770{
771 MFEM_ASSERT( nsize>=0, "Size must be non-negative. It is " << nsize );
772 if (nsize > size)
773 {
774 if (nsize > Capacity())
775 {
776 GrowSize(nsize);
777 }
778 for (int i = size; i < nsize; i++)
779 {
780 data[i] = initval;
781 }
782 }
783 size = nsize;
784}
785
786template <class T>
787inline void Array<T>::SetSize(int nsize, MemoryType mt)
788{
789 MFEM_ASSERT(nsize >= 0, "invalid new size: " << nsize);
790 if (mt == data.GetMemoryType())
791 {
792 if (nsize <= Capacity())
793 {
794 size = nsize;
795 return;
796 }
797 }
798 const bool use_dev = data.UseDevice();
799 data.Delete();
800 if (nsize > 0)
801 {
802 data.New(nsize, mt);
803 size = nsize;
804 }
805 else
806 {
807 data.Reset();
808 size = 0;
809 }
810 data.UseDevice(use_dev);
811}
812
813template <class T>
814inline T &Array<T>::operator[](int i)
815{
816 MFEM_ASSERT( i>=0 && i<size,
817 "Access element " << i << " of array, size = " << size );
818 return data[i];
819}
820
821template <class T>
822inline const T &Array<T>::operator[](int i) const
823{
824 MFEM_ASSERT( i>=0 && i<size,
825 "Access element " << i << " of array, size = " << size );
826 return data[i];
827}
828
829template <class T>
830inline int Array<T>::Append(const T &el)
831{
832 SetSize(size+1);
833 data[size-1] = el;
834 return size;
835}
836
837template <class T>
838inline int Array<T>::Append(const T *els, int nels)
839{
840 const int old_size = size;
841
842 SetSize(size + nels);
843 for (int i = 0; i < nels; i++)
844 {
845 data[old_size+i] = els[i];
846 }
847 return size;
848}
849
850template <class T>
851inline int Array<T>::Prepend(const T &el)
852{
853 SetSize(size+1);
854 for (int i = size-1; i > 0; i--)
855 {
856 data[i] = data[i-1];
857 }
858 data[0] = el;
859 return size;
860}
861
862template <class T>
863inline T &Array<T>::Last()
864{
865 MFEM_ASSERT(size > 0, "Array size is zero: " << size);
866 return data[size-1];
867}
868
869template <class T>
870inline const T &Array<T>::Last() const
871{
872 MFEM_ASSERT(size > 0, "Array size is zero: " << size);
873 return data[size-1];
874}
875
876template <class T>
877inline int Array<T>::Union(const T &el)
878{
879 int i = 0;
880 while ((i < size) && (data[i] != el)) { i++; }
881 if (i == size)
882 {
883 Append(el);
884 }
885 return i;
886}
887
888template <class T>
889inline int Array<T>::Find(const T &el) const
890{
891 for (int i = 0; i < size; i++)
892 {
893 if (data[i] == el) { return i; }
894 }
895 return -1;
896}
897
898template <class T>
899inline int Array<T>::FindSorted(const T &el) const
900{
901 const T *begin = data, *end = begin + size;
902 const T* first = std::lower_bound(begin, end, el);
903 if (first == end || !(*first == el)) { return -1; }
904 return (int)(first - begin);
905}
906
907template <class T>
908inline void Array<T>::DeleteFirst(const T &el)
909{
910 for (int i = 0; i < size; i++)
911 {
912 if (data[i] == el)
913 {
914 for (i++; i < size; i++)
915 {
916 data[i-1] = data[i];
917 }
918 size--;
919 return;
920 }
921 }
922}
923
924template <class T>
926{
927 const bool use_dev = data.UseDevice();
928 data.Delete();
929 data.Reset();
930 size = 0;
931 data.UseDevice(use_dev);
932}
933
934template <typename T>
935inline void Array<T>::Copy(Array &copy) const
936{
937 copy.SetSize(Size(), data.GetMemoryType());
938 data.CopyTo(copy.data, Size());
939 copy.data.UseDevice(data.UseDevice());
940}
941
942template <class T>
943inline void Array<T>::MakeRef(T *data_, int size_, bool own_data)
944{
945 data.Delete();
946 data.Wrap(data_, size_, own_data);
947 size = size_;
948}
949
950template <class T>
951inline void Array<T>::MakeRef(T *data_, int size_, MemoryType mt, bool own_data)
952{
953 data.Delete();
954 data.Wrap(data_, size_, mt, own_data);
955 size = size_;
956}
957
958template <class T>
959inline void Array<T>::MakeRef(const Array &master)
960{
961 data.Delete();
962 size = master.size;
963 data.MakeAlias(master.GetMemory(), 0, size);
964}
965
966template <class T>
967inline void Array<T>::GetSubArray(int offset, int sa_size, Array<T> &sa) const
968{
969 sa.SetSize(sa_size);
970 for (int i = 0; i < sa_size; i++)
971 {
972 sa[i] = (*this)[offset+i];
973 }
974}
975
976template <class T>
977inline void Array<T>::operator=(const T &a)
978{
979 for (int i = 0; i < size; i++)
980 {
981 data[i] = a;
982 }
983}
984
985template <class T>
986inline void Array<T>::Assign(const T *p)
987{
988 data.CopyFromHost(p, Size());
989}
990
991
992template <class T>
993inline const T &Array2D<T>::operator()(int i, int j) const
994{
995 MFEM_ASSERT( i>=0 && i< array1d.Size()/N && j>=0 && j<N,
996 "Array2D: invalid access of element (" << i << ',' << j
997 << ") in array of size (" << array1d.Size()/N << ',' << N
998 << ")." );
999 return array1d[i*N+j];
1000}
1001
1002template <class T>
1003inline T &Array2D<T>::operator()(int i, int j)
1004{
1005 MFEM_ASSERT( i>=0 && i< array1d.Size()/N && j>=0 && j<N,
1006 "Array2D: invalid access of element (" << i << ',' << j
1007 << ") in array of size (" << array1d.Size()/N << ',' << N
1008 << ")." );
1009 return array1d[i*N+j];
1010}
1011
1012template <class T>
1013inline const T *Array2D<T>::operator[](int i) const
1014{
1015 MFEM_ASSERT( i>=0 && i< array1d.Size()/N,
1016 "Array2D: invalid access of row " << i << " in array with "
1017 << array1d.Size()/N << " rows.");
1018 return &array1d[i*N];
1019}
1020
1021template <class T>
1023{
1024 MFEM_ASSERT( i>=0 && i< array1d.Size()/N,
1025 "Array2D: invalid access of row " << i << " in array with "
1026 << array1d.Size()/N << " rows.");
1027 return &array1d[i*N];
1028}
1029
1030
1031template <class T>
1033{
1034 Swap(a.array1d, b.array1d);
1035 Swap(a.N, b.N);
1036}
1037
1038
1039template <class T>
1040inline const T &Array3D<T>::operator()(int i, int j, int k) const
1041{
1042 MFEM_ASSERT(i >= 0 && i < array1d.Size() / N2 / N3 && j >= 0 && j < N2
1043 && k >= 0 && k < N3,
1044 "Array3D: invalid access of element ("
1045 << i << ',' << j << ',' << k << ") in array of size ("
1046 << array1d.Size() / N2 / N3 << ',' << N2 << ',' << N3 << ").");
1047 return array1d[(i*N2+j)*N3+k];
1048}
1049
1050template <class T>
1051inline T &Array3D<T>::operator()(int i, int j, int k)
1052{
1053 MFEM_ASSERT(i >= 0 && i < array1d.Size() / N2 / N3 && j >= 0 && j < N2
1054 && k >= 0 && k < N3,
1055 "Array3D: invalid access of element ("
1056 << i << ',' << j << ',' << k << ") in array of size ("
1057 << array1d.Size() / N2 / N3 << ',' << N2 << ',' << N3 << ").");
1058 return array1d[(i*N2+j)*N3+k];
1059}
1060
1061
1062template<typename T>
1064{
1065 mask = block_size-1;
1066 MFEM_VERIFY(!(block_size & mask), "block_size must be a power of two.");
1067
1068 size = shift = 0;
1069 while ((1 << shift) < block_size) { shift++; }
1070}
1071
1072template<typename T>
1074{
1075 blocks.SetSize(other.blocks.Size());
1076
1077 size = other.size;
1078 shift = other.shift;
1079 mask = other.mask;
1080
1081 int bsize = mask+1;
1082 for (int i = 0; i < blocks.Size(); i++)
1083 {
1084 blocks[i] = (T*) new char[bsize * sizeof(T)];
1085 }
1086
1087 // copy all items
1088 for (int i = 0; i < size; i++)
1089 {
1090 new (&At(i)) T(other[i]);
1091 }
1092}
1093
1094template<typename T>
1096{
1097 int bsize = mask+1;
1098 if (size >= blocks.Size() * bsize)
1099 {
1100 T* new_block = (T*) new char[bsize * sizeof(T)];
1101 blocks.Append(new_block);
1102 }
1103 return size++;
1104}
1105
1106template<typename T>
1108{
1109 int index = Alloc();
1110 new (&At(index)) T();
1111 return index;
1112}
1113
1114template<typename T>
1115int BlockArray<T>::Append(const T &item)
1116{
1117 int index = Alloc();
1118 new (&At(index)) T(item);
1119 return index;
1120}
1121
1122template<typename T>
1124{
1125 mfem::Swap(blocks, other.blocks);
1126 std::swap(size, other.size);
1127 std::swap(shift, other.shift);
1128 std::swap(mask, other.mask);
1129}
1130
1131template<typename T>
1133{
1134 return (mask+1)*sizeof(T)*blocks.Size() + blocks.MemoryUsage();
1135}
1136
1137template<typename T>
1139{
1140 int bsize = size & mask;
1141 for (int i = blocks.Size(); i != 0; )
1142 {
1143 T *block = blocks[--i];
1144 for (int j = bsize; j != 0; )
1145 {
1146 block[--j].~T();
1147 }
1148 delete [] (char*) block;
1149 bsize = mask+1;
1150 }
1151}
1152
1153} // namespace mfem
1154
1155#endif
Dynamic 2D array using row-major layout.
Definition array.hpp:392
void DeleteAll()
Delete all dynamically allocated memory, resetting all dimensions to zero.
Definition array.hpp:474
const T * operator[](int i) const
Definition array.hpp:1013
int NumCols() const
Definition array.hpp:408
Array2D(int m, int n)
Definition array.hpp:401
friend void Swap(Array2D< T > &, Array2D< T > &)
Definition array.hpp:1032
T * operator[](int i)
Definition array.hpp:1022
void Copy(Array2D &copy) const
Definition array.hpp:461
Array2D(const Array2D &)=default
void Save(std::ostream &os, int fmt=0) const
Save the Array2D to the stream out using the format fmt. The format fmt can be:
Definition array.hpp:435
const T & operator()(int i, int j) const
Definition array.hpp:993
const T * GetRow(int i) const
Definition array.hpp:419
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:447
T & operator()(int i, int j)
Definition array.hpp:1003
T * operator()(int i)
Definition array.hpp:417
T * GetRow(int i)
Definition array.hpp:420
int NumRows() const
Definition array.hpp:407
void Print(std::ostream &out=mfem::out, int width=4)
Prints array to stream with width elements per row.
Definition array.cpp:155
void operator=(const T &a)
Definition array.hpp:464
void GetRow(int i, Array< T > &sa) const
Extract a copy of the i-th row into the Array sa.
Definition array.hpp:423
const T * operator()(int i) const
Definition array.hpp:416
Array2D & operator=(const Array2D &a)=default
void MakeRef(const Array2D &master)
Make this Array a reference to 'master'.
Definition array.hpp:470
void SetSize(int m, int n)
Definition array.hpp:405
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:458
const T & operator()(int i, int j, int k) const
Definition array.hpp:1040
Array3D(int n1, int n2, int n3)
Definition array.hpp:490
void SetSize(int n1, int n2, int n3)
Definition array.hpp:493
void operator=(const T &a)
Definition array.hpp:499
T & operator()(int i, int j, int k)
Definition array.hpp:1051
Memory< T > & GetMemory()
Return a reference to the Memory object used by the Array.
Definition array.hpp:126
Array(std::initializer_list< CT > values)
Construct an Array from a braced initializer list of convertible type.
Definition array.hpp:698
const T & Last() const
Return the last element in the array.
Definition array.hpp:870
void Sort(Compare cmp)
Sorts the array in ascending order using the supplied comparison function object.
Definition array.hpp:282
void DeleteFirst(const T &el)
Delete the first entry with value == 'el'.
Definition array.hpp:908
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Definition array.cpp:68
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
int FindSorted(const T &el) const
Do bisection search for 'el' in a sorted array; return -1 if not found.
Definition array.hpp:899
const T * HostRead() const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), false).
Definition array.hpp:341
void MakeRef(const Array &master)
Make this Array a reference to 'master'.
Definition array.hpp:959
friend void Swap(Array< T > &, Array< T > &)
Definition array.hpp:672
void GetSubArray(int offset, int sa_size, Array< T > &sa) const
Copy sub array starting from offset out to the provided sa.
Definition array.hpp:967
int size
Size of the array.
Definition array.hpp:52
int Union(const T &el)
Append element when it is not yet in the array, return index.
Definition array.hpp:877
void Sort()
Sorts the array in ascending order. This requires operator< to be defined for T.
Definition array.hpp:278
T & operator[](int i)
Reference access to the ith element.
Definition array.hpp:814
void MakeDataOwner() const
Make the Array own the data.
Definition array.hpp:144
void Assign(const T *)
Copy data from a pointer. 'Size()' elements are copied.
Definition array.hpp:986
void CopyFrom(const U *src)
Copy from src into this array. Copies enough entries to fill the Capacity size of this array....
Definition array.hpp:318
Array< T > & operator=(const Array< T > &src)
Assignment operator: deep copy from 'src'.
Definition array.hpp:108
T * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), on_dev).
Definition array.hpp:353
void Reserve(int capacity)
Ensures that the allocated size is at least the given size.
Definition array.hpp:165
void StealData(T **p)
Changes the ownership of the data.
Definition array.hpp:138
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:758
int Prepend(const T &el)
Prepend an 'el' to the array, resize if necessary.
Definition array.hpp:851
bool IsEmpty() const
Does the Array have Size zero.
Definition array.hpp:296
T Min() const
Find the minimal element in the array, using the comparison operator < for class T.
Definition array.cpp:85
void LoseData()
NULL-ifies the data.
Definition array.hpp:141
int Size() const
Return the logical size of the array.
Definition array.hpp:147
const T * begin() const
STL-like begin. Returns const pointer to the first element of the array.
Definition array.hpp:328
void PartialSum()
Fill the entries of the array with the cumulative sum of the entries.
Definition array.cpp:103
Memory< T > data
Pointer to data.
Definition array.hpp:50
bool UseDevice() const
Return the device flag of the Memory object used by the Array.
Definition array.hpp:132
const T * end() const
STL-like end. Returns const pointer after the last element of the array.
Definition array.hpp:331
void operator=(const T &a)
Set all entries of the array to the provided constant.
Definition array.hpp:977
Array(MemoryType mt)
Creates an empty array with a given MemoryType.
Definition array.hpp:65
int Append(const T *els, int nels)
Append another array to this array, resize if necessary.
Definition array.hpp:838
int IsSorted() const
Return 1 if the array is sorted from lowest to highest. Otherwise return 0.
Definition array.cpp:127
int Append(const Array< T > &els)
Append another array to this array, resize if necessary.
Definition array.hpp:181
void MakeRef(T *data_, int size_, bool own_data=false)
Make this Array a reference to a pointer.
Definition array.hpp:943
Array(int asize, MemoryType mt)
Creates array of asize elements with a given MemoryType.
Definition array.hpp:72
Array(const Array< CT > &src)
Copy constructor (deep copy) from 'src', an Array of convertible type.
Definition array.hpp:688
void DeleteAll()
Delete the whole array.
Definition array.hpp:925
T * Write(bool on_dev=true)
Shortcut for mfem::Write(a.GetMemory(), a.Size(), on_dev).
Definition array.hpp:345
int Find(const T &el) const
Return the first index where 'el' is found; return -1 if not found.
Definition array.hpp:889
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:830
T * GetData()
Returns the data.
Definition array.hpp:121
const T * GetData() const
Returns the data.
Definition array.hpp:123
const Memory< T > & GetMemory() const
Return a reference to the Memory object used by the Array, const version.
Definition array.hpp:129
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
void Copy(Array &copy) const
Create a copy of the internal array to the provided copy.
Definition array.hpp:935
Array(Array< T > &&src)
Move constructor ("steals" data from 'src')
Definition array.hpp:102
Array(const Array &src)
Copy constructor: deep copy from src.
Definition array.hpp:679
void Permute(const I &indices)
Definition array.hpp:240
bool OwnsData() const
Return true if the data will be deleted by the Array.
Definition array.hpp:135
void Unique()
Removes duplicities from a sorted array. This requires operator== to be defined for T.
Definition array.hpp:286
void Permute(I &&indices)
Permute the array using the provided indices. Sorts the indices variable in the process,...
Definition array.hpp:733
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
Definition array.hpp:337
T * HostReadWrite()
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), false).
Definition array.hpp:357
void ShrinkToFit()
Reduces the capacity of the array to exactly match the current size.
Definition array.hpp:721
T * end()
STL-like end. Returns pointer after the last element of the array.
Definition array.hpp:325
~Array()
Destructor.
Definition array.hpp:105
Array()
Creates an empty array.
Definition array.hpp:62
Array(T *data_, int asize, bool own_data=false)
Creates array using an externally allocated host pointer data_ to asize elements. If own_data is true...
Definition array.hpp:81
T * begin()
STL-like begin. Returns pointer to the first element of the array.
Definition array.hpp:322
void Print(std::ostream &out=mfem::out, int width=4) const
Prints array to stream with width elements per row.
Definition array.cpp:23
const T & operator[](int i) const
Const reference access to the ith element.
Definition array.hpp:822
Array & operator=(const Array< CT > &src)
Assignment operator (deep copy) from src, an Array of convertible type.
std::size_t MemoryUsage() const
Returns the number of bytes allocated for the array including any reserve.
Definition array.hpp:334
Array(const CT(&values)[N])
Construct an Array from a C-style array of static length.
Definition array.hpp:704
int Capacity() const
Definition array.hpp:162
void MakeRef(T *data_, int size, MemoryType mt, bool own_data)
Make this Array a reference to a pointer.
Definition array.hpp:951
Array(int asize)
Creates array of asize elements.
Definition array.hpp:68
void CopyTo(U *dest)
STL-like copyTo dest from begin to end.
Definition array.hpp:312
void SetSize(int nsize, MemoryType mt)
Resize the array to size nsize using MemoryType mt. Note that unlike the other versions of SetSize(),...
Definition array.hpp:787
void GrowSize(int minsize)
Definition array.hpp:710
T Sum() const
Return the sum of all the array entries using the '+'' operator for class 'T'.
Definition array.cpp:115
void DeleteLast()
Delete the last entry of the array.
Definition array.hpp:202
void SetSize(int nsize, const T &initval)
Same as SetSize(int) plus initialize new entries with 'initval'.
Definition array.hpp:769
T * HostWrite()
Shortcut for mfem::Write(a.GetMemory(), a.Size(), false).
Definition array.hpp:349
T & Last()
Return the last element in the array.
Definition array.hpp:863
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:266
const_iterator(const BlockArray *a)
Definition array.hpp:627
const_iterator & operator++()
Definition array.hpp:630
iterator_base< const BlockArray, const T > base
Definition array.hpp:623
bool operator!=(const const_iterator &other) const
Definition array.hpp:633
bool operator==(const const_iterator &other) const
Definition array.hpp:632
bool operator==(const iterator &other) const
Definition array.hpp:615
iterator(BlockArray *a)
Definition array.hpp:610
iterator & operator++()
Definition array.hpp:613
bool operator!=(const iterator &other) const
Definition array.hpp:616
iterator_base< BlockArray, T > base
Definition array.hpp:606
void DeleteAll()
Destroy all items, set size to zero.
Definition array.hpp:548
Array< T * > blocks
Definition array.hpp:646
BlockArray(const BlockArray< T > &other)
Definition array.hpp:1073
const T & At(int index) const
Definition array.hpp:531
int Capacity() const
Return the current capacity of the BlockArray.
Definition array.hpp:545
iterator begin()
Definition array.hpp:636
std::size_t MemoryUsage() const
Definition array.hpp:1132
const_iterator cend() const
Definition array.hpp:643
BlockArray & operator=(const BlockArray &)=delete
T & At(int index)
Access item of the array.
Definition array.hpp:526
const T & operator[](int index) const
Definition array.hpp:539
void CheckIndex(int index) const
Definition array.hpp:651
void Swap(BlockArray< T > &other)
Definition array.hpp:1123
iterator end()
Definition array.hpp:637
int Append()
Allocate and construct a new item in the array, return its index.
Definition array.hpp:1107
const_iterator cbegin() const
Definition array.hpp:641
BlockArray & operator=(BlockArray< T > &&other)=default
const_iterator begin() const
Definition array.hpp:638
const_iterator end() const
Definition array.hpp:639
T & operator[](int index)
Access item of the array.
Definition array.hpp:538
int Append(const T &item)
Allocate and copy-construct a new item in the array, return its index.
Definition array.hpp:1115
int Size() const
Return the number of items actually stored.
Definition array.hpp:542
BlockArray(BlockArray< T > &&other)=default
BlockArray(int block_size=16 *1024)
Definition array.hpp:1063
Class used by MFEM to store pointers to host and/or device memory.
int Capacity() const
Return the size of the allocated memory.
void CopyFromHost(const T *src, int size)
Copy size entries from the host pointer src to *this.
void MakeAlias(const Memory &base, int offset, int size)
Create a memory object that points inside the memory object base.
bool UseDevice() const
Read the internal device flag.
MemoryType GetMemoryType() const
Return a MemoryType that is currently valid. If both the host and the device pointers are currently v...
void Reset()
Reset the memory to be empty, ensuring that Delete() will be a no-op.
void Wrap(T *ptr, int size, bool own)
Wrap an externally allocated host pointer, ptr with the current host memory type returned by MemoryMa...
void Delete()
Delete the owned pointers and reset the Memory object.
void CopyTo(Memory &dest, int size) const
Copy size entries from *this to dest.
void New(int size)
Allocate host memory for size entries with the current host memory type returned by MemoryManager::Ge...
int index(int i, int j, int nx, int ny)
Definition life.cpp:236
real_t b
Definition lissajous.cpp:42
real_t a
Definition lissajous.cpp:41
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's DeviceMemoryClass, if on_dev = true,...
Definition device.hpp:341
void Swap(Array< T > &, Array< T > &)
Definition array.hpp:672
T * Write(Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for write access to mem with the mfem::Device's DeviceMemoryClass, if on_dev = true,...
Definition device.hpp:358
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
bool operator!=(const Array< T > &LHS, const Array< T > &RHS)
Definition array.hpp:373
T * ReadWrite(Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for read+write access to mem with the mfem::Device's DeviceMemoryClass,...
Definition device.hpp:375
bool operator==(const Array< T > &LHS, const Array< T > &RHS)
Definition array.hpp:362
const T & AsConst(const T &a)
Utility function similar to std::as_const in c++17.
Definition array.hpp:380
MemoryType
Memory types supported by MFEM.
real_t p(const Vector &x, real_t t)