15 #include "../config/config.hpp"
25 #include <type_traits>
34 void Swap(Array<T> &, Array<T> &);
57 static_assert(std::is_trivial<T>::value,
"type T must be trivial");
70 explicit inline Array(
int asize)
71 :
size(asize) { asize > 0 ?
data.New(asize) :
data.Reset(); }
75 :
size(asize) { asize > 0 ?
data.New(asize, mt) :
data.Reset(mt); }
80 inline Array(T *data_,
int asize)
81 {
data.Wrap(data_, asize,
false);
size = asize; }
88 template <
typename CT>
92 template <
typename CT,
int N>
93 explicit inline Array(
const CT (&values)[N]);
102 template <
typename CT>
106 inline operator T *() {
return data; }
109 inline operator const T *()
const {
return data; }
141 inline void SetSize(
int nsize);
144 inline void SetSize(
int nsize,
const T &initval);
166 inline int Append(
const T & el);
169 inline int Append(
const T *els,
int nels);
175 inline int Prepend(
const T &el);
181 inline const T &
Last()
const;
184 inline int Union(
const T & el);
187 inline int Find(
const T &el)
const;
224 void Save(std::ostream &
out,
int fmt = 0)
const;
232 void Load(std::istream &in,
int fmt = 0);
236 void Load(
int new_size, std::istream &in)
251 template<
class Compare>
275 inline void Assign(
const T *);
278 template <
typename U>
284 template <
typename U>
304 const T *
Read(
bool on_dev =
true)
const
331 if ( LHS.Size() != RHS.Size() ) {
return false; }
332 for (
int i=0; i<LHS.Size(); i++)
334 if ( LHS[i] != RHS[i] ) {
return false; }
342 return !( LHS == RHS );
347 template <
typename T>
const T &
AsConst(T &
a) {
return a; }
368 Array2D(
int m,
int n) : array1d(m*n) { M = m; N = n; }
370 void SetSize(
int m,
int n) { array1d.SetSize(m*n); M = m; N = n; }
375 inline const T &
operator()(
int i,
int j)
const;
384 const T *
GetRow(
int i)
const {
return (*
this)[i]; }
400 void Save(std::ostream &os,
int fmt = 0)
const
412 void Load(std::istream &in,
int fmt = 0)
414 if (fmt == 0) { in >> M >> N; array1d.SetSize(M*N); }
419 void Load(
const char *filename,
int fmt = 0);
423 void Load(
int new_size0,
int new_size1, std::istream &in)
427 { copy.M = M; copy.N = N; array1d.Copy(copy.array1d); }
436 { M = master.M; N = master.N; array1d.MakeRef(master.array1d); }
439 inline void DeleteAll() { M = 0; N = 0; array1d.DeleteAll(); }
456 : array1d(n1*n2*n3) { N2 = n2; N3 = n3; }
459 { array1d.SetSize(n1*n2*n3); N2 = n2; N3 = n3; }
461 inline const T &
operator()(
int i,
int j,
int k)
const;
483 int Append(
const T &item);
515 template <
typename cA,
typename cT>
536 b_end_idx = std::min(a->size, a->mask+1);
542 MFEM_ASSERT(!
stop,
"invalid use");
545 if (b_end_idx < array->
size)
549 b_end_idx = std::min(
array->size, (b_end_idx|
array->mask) + 1);
596 iterator
begin() {
return size ? iterator(
this) : iterator(
true); }
597 iterator
end() {
return iterator(); }
600 {
return size ? const_iterator(
this) : const_iterator(
true); }
601 const_iterator
cend()
const {
return const_iterator(); }
611 MFEM_ASSERT(index >= 0 && index <
size,
612 "Out of bounds access: " << index <<
", size = " <<
size);
632 Swap(a.data, b.data);
633 Swap(a.size, b.size);
642 data.UseDevice(src.data.UseDevice());
645 template <
typename T>
template <
typename CT>
650 for (
int i = 0; i <
size; i++) { (*this)[i] = T(src[i]); }
653 template <
typename T>
template <
typename CT,
int N>
656 for (
int i = 0; i <
size; i++) { (*this)[i] = T(values[i]); }
662 const int nsize = std::max(minsize, 2 * data.Capacity());
664 p.CopyFrom(data, size);
665 p.UseDevice(data.UseDevice());
670 template <
typename T>
template <
typename CT>
674 for (
int i = 0; i < size; i++) { (*this)[i] = T(src[i]); }
681 MFEM_ASSERT( nsize>=0,
"Size must be non-negative. It is " << nsize );
682 if (nsize > Capacity())
692 MFEM_ASSERT( nsize>=0,
"Size must be non-negative. It is " << nsize );
695 if (nsize > Capacity())
699 for (
int i = size; i < nsize; i++)
710 MFEM_ASSERT(nsize >= 0,
"invalid new size: " << nsize);
711 if (mt == data.GetMemoryType())
713 if (nsize <= Capacity())
719 const bool use_dev = data.UseDevice();
731 data.UseDevice(use_dev);
737 MFEM_ASSERT( i>=0 && i<size,
738 "Access element " << i <<
" of array, size = " << size );
745 MFEM_ASSERT( i>=0 && i<size,
746 "Access element " << i <<
" of array, size = " << size );
761 const int old_size = size;
763 SetSize(size + nels);
764 for (
int i = 0; i < nels; i++)
766 data[old_size+i] = els[i];
775 for (
int i = size-1; i > 0; i--)
786 MFEM_ASSERT(size > 0,
"Array size is zero: " << size);
793 MFEM_ASSERT(size > 0,
"Array size is zero: " << size);
801 while ((i < size) && (data[i] != el)) { i++; }
812 for (
int i = 0; i < size; i++)
814 if (data[i] == el) {
return i; }
822 const T *begin = data, *end = begin + size;
823 const T* first = std::lower_bound(begin, end, el);
824 if (first == end || !(*first == el)) {
return -1; }
825 return first - begin;
831 for (
int i = 0; i < size; i++)
835 for (i++; i < size; i++)
848 const bool use_dev = data.UseDevice();
852 data.UseDevice(use_dev);
855 template <
typename T>
858 copy.SetSize(Size(), data.GetMemoryType());
859 data.CopyTo(copy.data, Size());
860 copy.data.UseDevice(data.UseDevice());
867 data.Wrap(p, s,
false);
877 data.ClearOwnerFlags();
884 for (
int i = 0; i < sa_size; i++)
886 sa[i] = (*this)[offset+i];
893 for (
int i = 0; i < size; i++)
902 data.CopyFromHost(p, Size());
909 MFEM_ASSERT( i>=0 && i< array1d.Size()/N && j>=0 && j<N,
910 "Array2D: invalid access of element (" << i <<
',' << j
911 <<
") in array of size (" << array1d.Size()/N <<
',' << N
913 return array1d[i*N+j];
919 MFEM_ASSERT( i>=0 && i< array1d.Size()/N && j>=0 && j<N,
920 "Array2D: invalid access of element (" << i <<
',' << j
921 <<
") in array of size (" << array1d.Size()/N <<
',' << N
923 return array1d[i*N+j];
929 MFEM_ASSERT( i>=0 && i< array1d.Size()/N,
930 "Array2D: invalid access of row " << i <<
" in array with "
931 << array1d.Size()/N <<
" rows.");
932 return &array1d[i*N];
938 MFEM_ASSERT( i>=0 && i< array1d.Size()/N,
939 "Array2D: invalid access of row " << i <<
" in array with "
940 << array1d.Size()/N <<
" rows.");
941 return &array1d[i*N];
948 Swap(a.array1d, b.array1d);
956 MFEM_ASSERT(i >= 0 && i < array1d.Size() / N2 / N3 && j >= 0 && j < N2
958 "Array3D: invalid access of element ("
959 << i <<
',' << j <<
',' << k <<
") in array of size ("
960 << array1d.Size() / N2 / N3 <<
',' << N2 <<
',' << N3 <<
").");
961 return array1d[(i*N2+j)*N3+k];
967 MFEM_ASSERT(i >= 0 && i < array1d.Size() / N2 / N3 && j >= 0 && j < N2
969 "Array3D: invalid access of element ("
970 << i <<
',' << j <<
',' << k <<
") in array of size ("
971 << array1d.Size() / N2 / N3 <<
',' << N2 <<
',' << N3 <<
").");
972 return array1d[(i*N2+j)*N3+k];
980 MFEM_VERIFY(!(block_size & mask),
"block_size must be a power of two.");
983 while ((1 << shift) < block_size) { shift++; }
996 for (
int i = 0; i < blocks.Size(); i++)
998 blocks[i] = (T*)
new char[bsize *
sizeof(T)];
1002 for (
int i = 0; i < size; i++)
1004 new (&At(i)) T(other[i]);
1008 template<
typename T>
1012 if (size >= blocks.Size() * bsize)
1014 T* new_block = (T*)
new char[bsize *
sizeof(T)];
1015 blocks.Append(new_block);
1020 template<
typename T>
1023 int index = Alloc();
1024 new (&At(index)) T();
1028 template<
typename T>
1031 int index = Alloc();
1032 new (&At(index)) T(item);
1036 template<
typename T>
1040 std::swap(size, other.
size);
1041 std::swap(shift, other.
shift);
1042 std::swap(mask, other.
mask);
1045 template<
typename T>
1048 return (mask+1)*
sizeof(T)*blocks.Size() + blocks.MemoryUsage();
1051 template<
typename T>
1054 int bsize = size & mask;
1055 for (
int i = blocks.Size(); i != 0; )
1057 T *block = blocks[--i];
1058 for (
int j = bsize; j != 0; )
1062 delete [] (
char*) block;
T * HostReadWrite()
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), false).
int Size() const
Return the logical size of the array.
const_iterator(const BlockArray *a)
void Load(std::istream &in, int fmt=0)
Read an Array from the stream in using format fmt. The format fmt can be:
void Unique()
Removes duplicities from a sorted array. This requires operator== to be defined for T...
Memory< T > & GetMemory()
Return a reference to the Memory object used by the Array.
T * end()
STL-like end. Returns pointer after the last element of the array.
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:
const_iterator cbegin() const
Array(int asize, MemoryType mt)
Creates array of asize elements with a given MemoryType.
const T * begin() const
STL-like begin. Returns const pointer to the first element of the array.
iterator_base< const BlockArray, const T > base
const T * operator()(int i) const
int Capacity() const
Return the current capacity of the BlockArray.
void Load(std::istream &in, int fmt=0)
Read an Array2D from the stream in using format fmt. The format fmt can be:
const T * HostRead() const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), false).
int size
Size of the array.
int Size() const
Return the number of items actually stored.
void Copy(Array ©) const
Create a copy of the internal array to the provided copy.
T * GetData()
Returns the data.
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...
void operator=(const T &a)
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:
bool UseDevice() const
Return the device flag of the Memory object used by the Array.
Array(int asize)
Creates array of asize elements.
void Sort(Compare cmp)
Sorts the array in ascending order using the supplied comparison function object. ...
T Sum()
Return the sum of all the array entries using the '+'' operator for class 'T'.
bool operator==(const iterator &other) const
void MakeRef(const Array2D &master)
Make this Array a reference to 'master'.
void Load(int new_size, std::istream &in)
Set the Array size to new_size and read that many entries from the stream in.
const T & At(int index) const
bool operator==(const const_iterator &other) const
void DeleteFirst(const T &el)
Delete the first entry with value == 'el'.
T & operator[](int index)
Access item of the array.
void SetSize(int n1, int n2, int n3)
T Min() const
Find the minimal element in the array, using the comparison operator < for class T.
void DeleteAll()
Delete the whole array.
int Append(const Array< T > &els)
Append another array to this array, resize if necessary.
void CopyTo(U *dest)
STL-like copyTo dest from begin to end.
void SetSize(int m, int n)
void Copy(Array2D ©) const
bool OwnsData() const
Return true if the data will be deleted by the array.
const T & operator()(int i, int j) const
const T * GetData() const
Returns the data.
int Append(const T &el)
Append element 'el' to array, resize if necessary.
void DeleteAll()
Destroy all items, set size to zero.
void GetSubArray(int offset, int sa_size, Array< T > &sa) const
Copy sub array starting from offset out to the provided sa.
T & operator[](int i)
Reference access to the ith element.
void LoseData()
NULL-ifies the data.
BlockArray & operator=(const BlockArray &)=delete
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
void Reserve(int capacity)
Ensures that the allocated size is at least the given size.
void CopyFrom(const U *src)
Copy from src into this array. Copies enough entries to fill the Capacity size of this array...
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
bool operator!=(const Array< T > &LHS, const Array< T > &RHS)
T * begin()
STL-like begin. Returns pointer to the first element of the array.
void Assign(const T *)
Copy data from a pointer. 'Size()' elements are copied.
void Sort()
Sorts the array in ascending order. This requires operator< to be defined for T.
int FindSorted(const T &el) const
Do bisection search for 'el' in a sorted array; return -1 if not found.
void StealData(T **p)
Changes the ownership of the data.
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...
int Union(const T &el)
Append element when it is not yet in the array, return index.
Dynamic 2D array using row-major layout.
Memory< T > data
Pointer to data.
void Print(std::ostream &out=mfem::out, int width=4)
Prints array to stream with width elements per row.
void Swap(Array< T > &, Array< T > &)
double p(const Vector &x, double t)
bool operator==(const Array< T > &LHS, const Array< T > &RHS)
void GrowSize(int minsize)
int IsSorted()
Return 1 if the array is sorted from lowest to highest. Otherwise return 0.
Array(T *data_, int asize)
Creates array using an existing c-array of asize elements; allocsize is set to -asize to indicate tha...
BlockArray(int block_size=16 *1024)
MemoryType
Memory types supported by MFEM.
int Find(const T &el) const
Return the first index where 'el' is found; return -1 if not found.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
const T * operator[](int i) const
void PartialSum()
Fill the entries of the array with the cumulative sum of the entries.
std::size_t MemoryUsage() const
T * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), on_dev).
void DeleteLast()
Delete the last entry of the array.
const T & operator[](int index) const
void MakeDataOwner() const
Make the Array own the data.
Array(MemoryType mt)
Creates an empty array with a given MemoryType.
T * HostWrite()
Shortcut for mfem::Write(a.GetMemory(), a.Size(), false).
bool operator!=(const iterator &other) const
const_iterator(bool stop)
void CheckIndex(int index) const
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, if on_dev = true, or the mfem::Device's HostMemoryClass, otherwise.
Array()
Creates an empty array.
int index(int i, int j, int nx, int ny)
bool operator!=(const const_iterator &other) const
Class used by MFEM to store pointers to host and/or device memory.
const_iterator & operator++()
T & Last()
Return the last element in the array.
void Print(std::ostream &out=mfem::out, int width=4) const
Prints array to stream with width elements per row.
iterator_base< BlockArray, T > base
T * Write(bool on_dev=true)
Shortcut for mfem::Write(a.GetMemory(), a.Size(), on_dev).
void MakeRef(T *, int)
Make this Array a reference to a pointer.
Array< T > & operator=(const Array< T > &src)
Assignment operator: deep copy from 'src'.
const_iterator cend() const
std::size_t MemoryUsage() const
Returns the number of bytes allocated for the array including any reserve.
const Memory< T > & GetMemory() const
Return a reference to the Memory object used by the Array, const version.
void DeleteAll()
Delete all dynamically allocated memory, resetting all dimensions to zero.
const T & operator()(int i, int j, int k) const
Array3D(int n1, int n2, int n3)
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
const T * end() const
STL-like end. Returns const pointer after the last element of the array.
T & At(int index)
Access item of the array.
const T & AsConst(T &a)
Utility function similar to std::as_const in c++17.
const T * GetRow(int i) const
int Prepend(const T &el)
Prepend an 'el' to the array, resize if necessary.
int Append()
Allocate and construct a new item in the array, return its index.
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...
void Swap(BlockArray< T > &other)
void GetRow(int i, Array< T > &sa) const
Extract a copy of the i-th row into the Array sa.