QMCPACK
OhmmsArray.h
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
8 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
9 //
10 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
11 //////////////////////////////////////////////////////////////////////////////////////
12 
13 
14 #ifndef OHMMS_PETE_ARRAY_H
15 #define OHMMS_PETE_ARRAY_H
16 
17 /** A D-dimensional Array class based on PETE
18  *
19  */
20 #include <array>
21 #include <type_traits>
22 #include "OhmmsVector.h"
23 
24 template<class T, unsigned D, typename ALLOC = std::allocator<T>>
25 class Array
26 {
27 public:
28  using Type_t = T;
31 
32  //default constructor
33  Array() { Length.fill(0); }
34 
35  //copy constructor
36  Array(const Array& rhs)
37  {
38  resize(rhs.shape());
39  std::copy(rhs.begin(), rhs.end(), X.begin());
40  }
41 
42  template<typename SIZET = size_t, typename = std::is_integral<SIZET>>
43  Array(const std::array<SIZET, D>& dims)
44  {
45  resize(dims);
46  }
47 
48  /// Provides specialized constructors with signature (size_1, ... , size_D) for array dimension D
49  template<typename... Args>
50  Array(Args... sizes)
51  {
52  resize(sizes...);
53  }
54 
55  inline unsigned dim() const { return D; }
56  inline const std::array<size_t, D>& shape() const { return Length; }
57  inline size_t size() const { return X.size(); }
58  inline size_t size(int i) const { return Length[i]; }
59 
60  Container_t& storage() { return X; }
61 
62  /// Resize the container. For performance consideration, previous data may or may not get kept.
63  /// Please avoid relying on previous data after resizing.
64  template<typename SIZET = size_t, typename = std::is_integral<SIZET>>
65  void resize(const std::array<SIZET, D>& dims)
66  {
67  for (int i = 0; i < dims.size(); i++)
68  Length[i] = dims[i];
70  }
71 
72  /// Provides specialized resize(size_1, ... , size_D) functions for the array D
73  template<typename... Args>
74  void resize(Args... sizes)
75  {
76  static_assert(sizeof...(Args) == D, "resize arguments must match dimensionality of Array");
77  resize({static_cast<std::size_t>(std::forward<Args>(sizes))...});
78  }
79 
80  inline typename Container_t::iterator begin() { return X.begin(); }
81  inline typename Container_t::iterator end() { return X.end(); }
82  inline typename Container_t::const_iterator begin() const { return X.begin(); }
83  inline typename Container_t::const_iterator end() const { return X.end(); }
84 
85  ///@{
86  /// access the container data pointer
87  inline Type_t* data() { return X.data(); }
88  inline const Type_t* data() const { return X.data(); }
89  template<typename Allocator = ALLOC, typename = qmcplusplus::IsDualSpace<Allocator>>
90  inline Type_t* device_data()
91  {
92  return X.device_data();
93  }
94  template<typename Allocator = ALLOC, typename = qmcplusplus::IsDualSpace<Allocator>>
95  inline const Type_t* device_data() const
96  {
97  return X.device_data();
98  }
99  ///@}
100 
101  ///@{
102  /// access the data pointer at {index_1, ..., index_D}
103  template<typename SIZET = size_t, typename = std::is_integral<SIZET>>
104  Type_t* data_at(const std::array<SIZET, D>& indices)
105  {
106  return X.data() + compute_offset(indices);
107  }
108  template<typename SIZET = size_t, typename = std::is_integral<SIZET>>
109  const Type_t* data_at(const std::array<SIZET, D>& indices) const
110  {
111  return X.data() + compute_offset(indices);
112  }
113  template<typename SIZET = size_t,
114  typename = std::is_integral<SIZET>,
115  typename Allocator = ALLOC,
117  Type_t* device_data_at(const std::array<SIZET, D>& indices)
118  {
119  return X.device_data() + compute_offset(indices);
120  }
121  template<typename SIZET = size_t,
122  typename = std::is_integral<SIZET>,
123  typename Allocator = ALLOC,
125  const Type_t* device_data_at(const std::array<SIZET, D>& indices) const
126  {
127  return X.device_data() + compute_offset(indices);
128  }
129 
130  template<typename... Args>
131  Type_t* data_at(Args... indices)
132  {
133  static_assert(sizeof...(Args) == D, "data arguments must match dimensionality of Array");
134  return data_at({static_cast<std::size_t>(std::forward<Args>(indices))...});
135  }
136  template<typename... Args>
137  const Type_t* data_at(Args... indices) const
138  {
139  static_assert(sizeof...(Args) == D, "data arguments must match dimensionality of Array");
140  return data_at({static_cast<std::size_t>(std::forward<Args>(indices))...});
141  }
142  template<typename... Args, typename Allocator = ALLOC, typename = qmcplusplus::IsDualSpace<Allocator>>
143  Type_t* device_data_at(Args... indices)
144  {
145  static_assert(sizeof...(Args) == D, "device_data arguments must match dimensionality of Array");
146  return device_data_at({static_cast<std::size_t>(std::forward<Args>(indices))...});
147  }
148  template<typename... Args, typename Allocator = ALLOC, typename = qmcplusplus::IsDualSpace<Allocator>>
149  const Type_t* device_data_at(Args... indices) const
150  {
151  static_assert(sizeof...(Args) == D, "device_data arguments must match dimensionality of Array");
152  return device_data_at({static_cast<std::size_t>(std::forward<Args>(indices))...});
153  }
154  ///@}
155 
156  inline const Type_t* first_address() const { return X.data(); }
157 
158  inline const Type_t* last_address() const { return X.data() + X.size(); }
159 
160  inline Type_t* first_address() { return X.data(); }
161 
162  inline Type_t* last_address() { return X.data() + X.size(); }
163 
164  This_t& operator=(const T& rhs)
165  {
166  std::fill(X.begin(), X.end(), rhs);
167  return *this;
168  }
169 
170  This_t& operator=(const Array& rhs)
171  {
172  if (&rhs != this)
173  {
174  resize(rhs.shape());
175  std::copy(rhs.begin(), rhs.end(), X.begin());
176  }
177  return *this;
178  }
179 
180  template<typename TT, typename ALLOC2>
182  {
183  resize(rhs.shape());
184  std::copy(rhs.begin(), rhs.end(), X.begin());
185  return *this;
186  }
187 
188  ///@{
189  /// access the element at {index_1, ..., index_D}
190  template<typename SIZET = size_t, typename = std::is_integral<SIZET>>
191  Type_t& operator()(const std::array<SIZET, D>& indices)
192  {
193  return X[compute_offset(indices)];
194  }
195  template<typename SIZET = size_t, typename = std::is_integral<SIZET>>
196  const Type_t& operator()(const std::array<SIZET, D>& indices) const
197  {
198  return X[compute_offset(indices)];
199  }
200  template<typename... Args>
201  Type_t& operator()(Args... indices)
202  {
203  static_assert(sizeof...(Args) == D, "operator() arguments must match dimensionality of Array");
204  return operator()({static_cast<std::size_t>(std::forward<Args>(indices))...});
205  }
206  template<typename... Args>
207  const Type_t& operator()(Args... indices) const
208  {
209  static_assert(sizeof...(Args) == D, "operator() arguments must match dimensionality of Array");
210  return operator()({static_cast<std::size_t>(std::forward<Args>(indices))...});
211  }
212  ///@}
213 
214  inline Type_t sum() const
215  {
216  Type_t s = 0;
217  for (int i = 0; i < X.size(); ++i)
218  s += X[i];
219  return s;
220  }
221 
222  // Abstract Dual Space Transfers
223  template<typename Allocator = ALLOC, typename = qmcplusplus::IsDualSpace<Allocator>>
224  void updateTo(size_t size = 0, std::ptrdiff_t offset = 0)
225  {
226  X.updateTo(size, offset);
227  }
228  template<typename Allocator = ALLOC, typename = qmcplusplus::IsDualSpace<Allocator>>
229  void updateFrom(size_t size = 0, std::ptrdiff_t offset = 0)
230  {
231  X.updateFrom(size, offset);
232  }
233 
234 private:
235  std::array<size_t, D> Length;
237  /// compute the full size of dims
238  size_t full_size(const std::array<size_t, D>& dims) const
239  {
240  size_t total = dims[0];
241  for (int i = 1; i < dims.size(); i++)
242  total *= dims[i];
243  return total;
244  }
245 
246  template<typename SIZET = size_t, typename = std::is_integral<SIZET>>
247  SIZET compute_offset(const std::array<SIZET, D>& indices) const
248  {
249  SIZET offset = indices[0];
250  for (int i = 1; i < indices.size(); i++)
251  offset = offset * Length[i] + indices[i];
252  return offset;
253  }
254 };
255 
256 template<class T, unsigned D, class Alloc>
258 {
260  "operator== requires host accessible Vector.");
261  if (lhs.size() == rhs.size())
262  {
263  for (int i = 0; i < rhs.size(); i++)
264  if (lhs(i) != rhs(i))
265  return false;
266  return true;
267  }
268  else
269  return false;
270 }
271 
272 template<class T, unsigned D, class Alloc>
274 {
276  "operator== requires host accessible Vector.");
277  return !(lhs == rhs);
278 }
279 #endif //OHMMS_PETE_ARRAY_H
const Type_t * data_at(const std::array< SIZET, D > &indices) const
Definition: OhmmsArray.h:109
void resize(size_type n, Type_t val=Type_t())
Resize the container.
Definition: OhmmsVector.h:166
std::array< size_t, D > Length
Definition: OhmmsArray.h:235
const Type_t * device_data_at(Args... indices) const
Definition: OhmmsArray.h:149
Array()
Definition: OhmmsArray.h:33
Array(const Array &rhs)
Definition: OhmmsArray.h:36
Type_t * device_data_at(Args... indices)
Definition: OhmmsArray.h:143
Container_t::const_iterator end() const
Definition: OhmmsArray.h:83
Type_t * device_data()
Definition: OhmmsArray.h:90
Type_t & operator()(Args... indices)
Definition: OhmmsArray.h:201
This_t & operator=(const Array< TT, D, ALLOC2 > &rhs)
Definition: OhmmsArray.h:181
Type_t * data_at(const std::array< SIZET, D > &indices)
Definition: OhmmsArray.h:104
Type_t * data()
Definition: OhmmsArray.h:87
pointer device_data()
Return the device_ptr matching X if this is a vector attached or owning dual space memory...
Definition: OhmmsVector.h:245
void updateFrom(size_type size=0, std::ptrdiff_t offset=0)
Definition: OhmmsVector.h:272
bool operator!=(const Array< T, D, Alloc > &lhs, const Array< T, D, Alloc > &rhs)
Definition: OhmmsArray.h:273
void resize(const std::array< SIZET, D > &dims)
Resize the container.
Definition: OhmmsArray.h:65
const Type_t * last_address() const
Definition: OhmmsArray.h:158
bool operator==(const Array< T, D, Alloc > &lhs, const Array< T, D, Alloc > &rhs)
Definition: OhmmsArray.h:257
void copy(const Array< T1, 3 > &src, Array< T2, 3 > &dest)
Definition: Blitz.h:639
This_t & operator=(const Array &rhs)
Definition: OhmmsArray.h:170
const Type_t * device_data_at(const std::array< SIZET, D > &indices) const
Definition: OhmmsArray.h:125
Container_t & storage()
Definition: OhmmsArray.h:60
size_t full_size(const std::array< size_t, D > &dims) const
compute the full size of dims
Definition: OhmmsArray.h:238
size_type size() const
return the current size
Definition: OhmmsVector.h:162
const Type_t & operator()(const std::array< SIZET, D > &indices) const
Definition: OhmmsArray.h:196
Type_t * device_data_at(const std::array< SIZET, D > &indices)
Definition: OhmmsArray.h:117
Type_t & operator()(const std::array< SIZET, D > &indices)
Definition: OhmmsArray.h:191
size_t size() const
Definition: OhmmsArray.h:57
void resize(Args... sizes)
Provides specialized resize(size_1, ... , size_D) functions for the array D.
Definition: OhmmsArray.h:74
Type_t * last_address()
Definition: OhmmsArray.h:162
template class analogous to std::allocator_traits.
void updateFrom(size_t size=0, std::ptrdiff_t offset=0)
Definition: OhmmsArray.h:229
SIZET compute_offset(const std::array< SIZET, D > &indices) const
Definition: OhmmsArray.h:247
Array(Args... sizes)
Provides specialized constructors with signature (size_1, ... , size_D) for array dimension D...
Definition: OhmmsArray.h:50
Type_t sum() const
Definition: OhmmsArray.h:214
const Type_t & operator()(Args... indices) const
Definition: OhmmsArray.h:207
Declaraton of Vector<T,Alloc> Manage memory through Alloc directly and allow referencing an existing ...
const Type_t * data_at(Args... indices) const
Definition: OhmmsArray.h:137
void updateTo(size_t size=0, std::ptrdiff_t offset=0)
Definition: OhmmsArray.h:224
const Type_t * device_data() const
Definition: OhmmsArray.h:95
Type_t * data_at(Args... indices)
Definition: OhmmsArray.h:131
Container_t::iterator begin()
Definition: OhmmsArray.h:80
std::enable_if_t< qmc_allocator_traits< Allocator >::is_dual_space > IsDualSpace
const Type_t * data() const
Definition: OhmmsArray.h:88
std::vector< int > dims
unsigned dim() const
Definition: OhmmsArray.h:55
Array(const std::array< SIZET, D > &dims)
Definition: OhmmsArray.h:43
Container_t X
Definition: OhmmsArray.h:236
void updateTo(size_type size=0, std::ptrdiff_t offset=0)
Definition: OhmmsVector.h:263
const Type_t * first_address() const
Definition: OhmmsArray.h:156
A D-dimensional Array class based on PETE.
Definition: OhmmsArray.h:25
Type_t * first_address()
Definition: OhmmsArray.h:160
const std::array< size_t, D > & shape() const
Definition: OhmmsArray.h:56
Container_t::const_iterator begin() const
Definition: OhmmsArray.h:82
This_t & operator=(const T &rhs)
Definition: OhmmsArray.h:164
size_t size(int i) const
Definition: OhmmsArray.h:58
Container_t::iterator end()
Definition: OhmmsArray.h:81