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(); }
76 inline Array(T *data_,
int asize)
77 {
data.Wrap(data_, asize,
false);
size = asize; }
84 template <
typename CT>
88 template <
typename CT,
int N>
89 explicit inline Array(
const CT (&values)[N]);
98 template <
typename CT>
102 inline operator T *() {
return data; }
105 inline operator const T *()
const {
return data; }
137 inline void SetSize(
int nsize);
140 inline void SetSize(
int nsize,
const T &initval);
162 inline int Append(
const T & el);
165 inline int Append(
const T *els,
int nels);
171 inline int Prepend(
const T &el);
177 inline const T &
Last()
const;
180 inline int Union(
const T & el);
183 inline int Find(
const T &el)
const;
220 void Save(std::ostream &
out,
int fmt = 0)
const;
228 void Load(std::istream &in,
int fmt = 0);
232 void Load(
int new_size, std::istream &in)
247 template<
class Compare>
271 inline void Assign(
const T *);
274 template <
typename U>
280 template <
typename U>
300 const T *
Read(
bool on_dev =
true)
const
327 if ( LHS.Size() != RHS.Size() ) {
return false; }
328 for (
int i=0; i<LHS.Size(); i++)
330 if ( LHS[i] != RHS[i] ) {
return false; }
338 return !( LHS == RHS );
343 template <
typename T>
const T &
AsConst(T &
a) {
return a; }
364 Array2D(
int m,
int n) : array1d(m*n) { M = m; N = n; }
366 void SetSize(
int m,
int n) { array1d.SetSize(m*n); M = m; N = n; }
371 inline const T &
operator()(
int i,
int j)
const;
380 const T *
GetRow(
int i)
const {
return (*
this)[i]; }
396 void Save(std::ostream &
out,
int fmt = 0)
const
399 array1d.Save(out, 1);
408 void Load(std::istream &in,
int fmt = 0)
410 if (fmt == 0) { in >> M >> N; array1d.SetSize(M*N); }
415 void Load(
const char *filename,
int fmt = 0);
419 void Load(
int new_size0,
int new_size1, std::istream &in)
423 { copy.M = M; copy.N = N; array1d.Copy(copy.array1d); }
432 { M = master.M; N = master.N; array1d.MakeRef(master.array1d); }
435 inline void DeleteAll() { M = 0; N = 0; array1d.DeleteAll(); }
452 : array1d(n1*n2*n3) { N2 = n2; N3 = n3; }
455 { array1d.SetSize(n1*n2*n3); N2 = n2; N3 = n3; }
457 inline const T &
operator()(
int i,
int j,
int k)
const;
478 int Append(
const T &item);
510 template <
typename cA,
typename cT>
531 b_end_idx = std::min(a->size, a->mask+1);
537 MFEM_ASSERT(!
stop,
"invalid use");
540 if (b_end_idx < array->
size)
544 b_end_idx = std::min(
array->size, (b_end_idx|
array->mask) + 1);
591 iterator
begin() {
return size ? iterator(
this) : iterator(
true); }
592 iterator
end() {
return iterator(); }
595 {
return size ? const_iterator(
this) : const_iterator(
true); }
596 const_iterator
cend()
const {
return const_iterator(); }
606 MFEM_ASSERT(index >= 0 && index <
size,
607 "Out of bounds access: " << index <<
", size = " <<
size);
627 Swap(a.data, b.data);
628 Swap(a.size, b.size);
637 data.UseDevice(src.data.UseDevice());
640 template <
typename T>
template <
typename CT>
645 for (
int i = 0; i <
size; i++) { (*this)[i] = T(src[i]); }
648 template <
typename T>
template <
typename CT,
int N>
651 for (
int i = 0; i <
size; i++) { (*this)[i] = T(values[i]); }
657 const int nsize = std::max(minsize, 2 * data.Capacity());
659 p.CopyFrom(data, size);
660 p.UseDevice(data.UseDevice());
665 template <
typename T>
template <
typename CT>
669 for (
int i = 0; i < size; i++) { (*this)[i] = T(src[i]); }
676 MFEM_ASSERT( nsize>=0,
"Size must be non-negative. It is " << nsize );
677 if (nsize > Capacity())
687 MFEM_ASSERT( nsize>=0,
"Size must be non-negative. It is " << nsize );
690 if (nsize > Capacity())
694 for (
int i = size; i < nsize; i++)
705 MFEM_ASSERT(nsize >= 0,
"invalid new size: " << nsize);
706 if (mt == data.GetMemoryType())
708 if (nsize <= Capacity())
714 const bool use_dev = data.UseDevice();
726 data.UseDevice(use_dev);
732 MFEM_ASSERT( i>=0 && i<size,
733 "Access element " << i <<
" of array, size = " << size );
740 MFEM_ASSERT( i>=0 && i<size,
741 "Access element " << i <<
" of array, size = " << size );
756 const int old_size = size;
758 SetSize(size + nels);
759 for (
int i = 0; i < nels; i++)
761 data[old_size+i] = els[i];
770 for (
int i = size-1; i > 0; i--)
781 MFEM_ASSERT(size > 0,
"Array size is zero: " << size);
788 MFEM_ASSERT(size > 0,
"Array size is zero: " << size);
796 while ((i < size) && (data[i] != el)) { i++; }
807 for (
int i = 0; i < size; i++)
809 if (data[i] == el) {
return i; }
817 const T *begin = data, *end = begin + size;
818 const T* first = std::lower_bound(begin, end, el);
819 if (first == end || !(*first == el)) {
return -1; }
820 return first - begin;
826 for (
int i = 0; i < size; i++)
830 for (i++; i < size; i++)
843 const bool use_dev = data.UseDevice();
847 data.UseDevice(use_dev);
850 template <
typename T>
853 copy.SetSize(Size(), data.GetMemoryType());
854 data.CopyTo(copy.data, Size());
855 copy.data.UseDevice(data.UseDevice());
862 data.Wrap(p, s,
false);
872 data.ClearOwnerFlags();
879 for (
int i = 0; i < sa_size; i++)
881 sa[i] = (*this)[offset+i];
888 for (
int i = 0; i < size; i++)
897 data.CopyFromHost(p, Size());
904 MFEM_ASSERT( i>=0 && i< array1d.Size()/N && j>=0 && j<N,
905 "Array2D: invalid access of element (" << i <<
',' << j
906 <<
") in array of size (" << array1d.Size()/N <<
',' << N
908 return array1d[i*N+j];
914 MFEM_ASSERT( i>=0 && i< array1d.Size()/N && j>=0 && j<N,
915 "Array2D: invalid access of element (" << i <<
',' << j
916 <<
") in array of size (" << array1d.Size()/N <<
',' << N
918 return array1d[i*N+j];
924 MFEM_ASSERT( i>=0 && i< array1d.Size()/N,
925 "Array2D: invalid access of row " << i <<
" in array with "
926 << array1d.Size()/N <<
" rows.");
927 return &array1d[i*N];
933 MFEM_ASSERT( i>=0 && i< array1d.Size()/N,
934 "Array2D: invalid access of row " << i <<
" in array with "
935 << array1d.Size()/N <<
" rows.");
936 return &array1d[i*N];
943 Swap(a.array1d, b.array1d);
951 MFEM_ASSERT(i >= 0 && i < array1d.Size() / N2 / N3 && j >= 0 && j < N2
953 "Array3D: invalid access of element ("
954 << i <<
',' << j <<
',' << k <<
") in array of size ("
955 << array1d.Size() / N2 / N3 <<
',' << N2 <<
',' << N3 <<
").");
956 return array1d[(i*N2+j)*N3+k];
962 MFEM_ASSERT(i >= 0 && i < array1d.Size() / N2 / N3 && j >= 0 && j < N2
964 "Array3D: invalid access of element ("
965 << i <<
',' << j <<
',' << k <<
") in array of size ("
966 << array1d.Size() / N2 / N3 <<
',' << N2 <<
',' << N3 <<
").");
967 return array1d[(i*N2+j)*N3+k];
975 MFEM_VERIFY(!(block_size & mask),
"block_size must be a power of two.");
978 while ((1 << shift) < block_size) { shift++; }
991 for (
int i = 0; i < blocks.Size(); i++)
993 blocks[i] = (T*)
new char[bsize *
sizeof(T)];
997 for (
int i = 0; i < size; i++)
999 new (&At(i)) T(other[i]);
1003 template<
typename T>
1007 if (size >= blocks.Size() * bsize)
1009 T* new_block = (T*)
new char[bsize *
sizeof(T)];
1010 blocks.Append(new_block);
1015 template<
typename T>
1018 int index = Alloc();
1019 new (&At(index)) T();
1023 template<
typename T>
1026 int index = Alloc();
1027 new (&At(index)) T(item);
1031 template<
typename T>
1035 std::swap(size, other.
size);
1036 std::swap(shift, other.
shift);
1037 std::swap(mask, other.
mask);
1040 template<
typename T>
1043 return blocks.Size()*(mask+1)*
sizeof(T) +
1044 blocks.MemoryUsage();
1047 template<
typename T>
1050 int bsize = size & mask;
1051 for (
int i = blocks.Size(); i != 0; )
1053 T *block = blocks[--i];
1054 for (
int j = bsize; j != 0; )
1058 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.
const_iterator cbegin() const
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 Save(std::ostream &out, int fmt=0) const
Save the Array2D to the stream out using the format fmt. The format fmt can be:
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.
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.
long MemoryUsage() const
Returns the number of bytes allocated for the array including any reserve.
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.
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
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.