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