TBTK
Array.h
Go to the documentation of this file.
1 /* Copyright 2017 Kristofer Bj√∂rnson
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
23 #ifndef COM_DAFER45_TBTK_ARRAY
24 #define COM_DAFER45_TBTK_ARRAY
25 
26 #include "TBTK/Index.h"
27 #include "TBTK/TBTKMacros.h"
28 
29 #include <vector>
30 
31 namespace TBTK{
32 
33 template<typename DataType>
34 class Array{
35 public:
37  Array();
38 
40  Array(const std::vector<unsigned int> &ranges);
41 
43  Array(const std::vector<unsigned int> &ranges, const DataType &fillValue);
44 
46  Array(const Array &array);
47 
49  Array(Array &&array);
50 
52  ~Array();
53 
55  Array& operator=(const Array &rhs);
56 
58  Array& operator=(Array &&rhs);
59 
61  DataType& operator[](const std::initializer_list<unsigned int> &index);
62 
64  const DataType& operator[](
65  const std::initializer_list<unsigned int> &index
66  ) const;
67 
71  DataType& operator[](unsigned int n);
72 
76  const DataType& operator[](unsigned int n) const;
77 
79  Array operator+(const Array &rhs) const;
80 
82  Array operator-(const Array &rhs) const;
83 
85  Array operator*(const DataType &rhs) const;
86 
88  friend Array operator*(const DataType &lhs, const Array &rhs){
89  Array<DataType> result(rhs.ranges);
90  for(unsigned int n = 0; n < rhs.size; n++)
91  result.data[n] = lhs*rhs.data[n];
92 
93  return result;
94  }
95 
97  Array operator/(const DataType &rhs) const;
98 
100  Array<DataType> getSlice(const std::vector<int> &index) const;
101 
103  const std::vector<unsigned int>& getRanges() const;
104 private:
106  DataType *data;
107 
109  unsigned int size;
110 
112  std::vector<unsigned int> ranges;
113 
115  void fillSlice(
116  Array &array,
117  const std::vector<int> &index,
118  unsigned int subindex,
119  unsigned int offsetSlice,
120  unsigned int offsetOriginal
121  ) const;
122 
124  void assertCompatibleRanges(
125  const Array &array,
126  std::string functionName
127  ) const;
128 };
129 
130 template<typename DataType>
132  size = 0;
133  data = nullptr;
134 }
135 
136 template<typename DataType>
137 Array<DataType>::Array(const std::vector<unsigned int> &ranges){
138  this->ranges = ranges;
139  size = 1;
140  for(unsigned int n = 0; n < ranges.size(); n++){
141  TBTKAssert(
142  ranges[n] > 0,
143  "Array::Array()",
144  "Invalid ranges.",
145  "'ranges' must only contain positive numbers."
146  );
147  size *= ranges[n];
148  }
149 
150  data = new DataType[size];
151 }
152 
153 template<typename DataType>
155  const std::vector<unsigned int> &ranges,
156  const DataType &fillValue
157 ){
158  this->ranges = ranges;
159  size = 1;
160  for(unsigned int n = 0; n < ranges.size(); n++){
161  TBTKAssert(
162  ranges[n] > 0,
163  "Array::Array()",
164  "Invalid ranges.",
165  "'ranges' must only contain positive numbers."
166  );
167  size *= ranges[n];
168  }
169 
170  data = new DataType[size];
171 
172  for(unsigned int n = 0; n < size; n++)
173  data[n] = fillValue;
174 }
175 
176 template<typename DataType>
178  ranges = array.ranges;
179  size = array.size;
180  if(size != 0){
181  data = new DataType[size];
182  for(unsigned int n = 0; n < size; n++)
183  data[n] = array.data[n];
184  }
185  else{
186  data = nullptr;
187  }
188 }
189 
190 template<typename DataType>
192  ranges = std::move(array.ranges);
193  size = std::move(array.size);
194  data = array.data;
195  array.data = nullptr;
196 }
197 
198 template<typename DataType>
200  if(data != nullptr)
201  delete [] data;
202 }
203 
204 template<typename DataType>
206  if(this != &rhs){
207  ranges = rhs.ranges;
208  size = rhs.size;
209  if(data != nullptr)
210  delete [] data;
211  if(size != 0){
212  data = new DataType[size];
213  for(unsigned int n = 0; n < size; n++)
214  data[n] = rhs.data[n];
215  }
216  else{
217  data = nullptr;
218  }
219  }
220 
221  return *this;
222 }
223 
224 template<typename DataType>
226  if(this != &rhs){
227  ranges = std::move(rhs.ranges);
228  size = std::move(rhs.size);
229  if(data != nullptr)
230  delete [] data;
231  data = rhs.data;
232  rhs.data = nullptr;
233  }
234 
235  return *this;
236 }
237 
238 template<typename DataType>
240  const std::initializer_list<unsigned int> &index
241 ){
242  unsigned int idx = 0;
243  for(unsigned int n = 0; n < index.size(); n++){
244  if(n != 0)
245  idx *= ranges[n];
246  idx += *(index.begin() + n);
247  }
248 
249  return data[idx];
250 }
251 
252 template<typename DataType>
253 inline const DataType& Array<DataType>::operator[](
254  const std::initializer_list<unsigned int> &index
255 ) const{
256  unsigned int idx = 0;
257  for(unsigned int n = 0; n < index.size(); n++){
258  if(n != 0)
259  idx *= ranges[n];
260  idx += *(index.begin() + n);
261  }
262 
263  return data[idx];
264 }
265 
266 template<typename DataType>
267 inline DataType& Array<DataType>::operator[](unsigned int n){
268  return data[n];
269 }
270 
271 template<typename DataType>
272 inline const DataType& Array<DataType>::operator[](unsigned int n) const{
273  return data[n];
274 }
275 
276 template<typename DataType>
278  const Array<DataType> &rhs
279 ) const{
280  assertCompatibleRanges(rhs, "operator+()");
281 
282  Array<DataType> result(ranges);
283  for(unsigned int n = 0; n < size; n++)
284  result.data[n] = data[n] + rhs.data[n];
285 
286  return result;
287 }
288 
289 template<typename DataType>
291  const Array<DataType> &rhs
292 ) const{
293  assertCompatibleRanges(rhs, "operator+()");
294 
295  Array<DataType> result(ranges);
296  for(unsigned int n = 0; n < size; n++)
297  result.data[n] = data[n] - rhs.data[n];
298 
299  return result;
300 }
301 
302 template<typename DataType>
304  const DataType &rhs
305 ) const{
306  Array<DataType> result(ranges);
307  for(unsigned int n = 0; n < size; n++)
308  result.data[n] = data[n]*rhs;
309 
310  return result;
311 }
312 
313 template<typename DataType>
315  const DataType &rhs
316 ) const{
317  Array<DataType> result(ranges);
318  for(unsigned int n = 0; n < size; n++)
319  result.data[n] = data[n]/rhs;
320 
321  return result;
322 }
323 
324 template<typename DataType>
325 Array<DataType> Array<DataType>::getSlice(const std::vector<int> &index) const{
326  TBTKAssert(
327  ranges.size() == index.size(),
328  "Array::getSlice()",
329  "Incompatible ranges.",
330  "'index' must have the same number of dimensions as 'ranges'."
331  );
332 
333  std::vector<unsigned int> newRanges;
334  for(unsigned int n = 0; n < ranges.size(); n++){
335  TBTKAssert(
336  index[n] < (int)ranges[n],
337  "Array::getSlice()",
338  "'index' out of range.",
339  ""
340  );
341  if(index[n] < 0){
342  TBTKAssert(
343  index[n] == IDX_ALL,
344  "Array::getSlice()",
345  "Invalid symbol.",
346  "'index' can only contain positive numbers or"
347  << " 'IDX_ALL'."
348  );
349  newRanges.push_back(ranges[n]);
350  }
351  }
352 
353  Array array(newRanges);
354 
355  fillSlice(array, index, 0, 0, 0);
356 
357  return array;
358 }
359 
360 template<typename DataType>
362  Array &array,
363  const std::vector<int> &index,
364  unsigned int subindex,
365  unsigned int offsetSlice,
366  unsigned int offsetOriginal
367 ) const{
368  if(subindex == index.size()-1){
369  if(index[subindex] == IDX_ALL){
370  for(unsigned int n = 0; n < ranges[subindex]; n++){
371  array.data[offsetSlice*ranges[subindex] + n]
372  = data[
373  offsetOriginal*ranges[subindex]
374  + n
375  ];
376  }
377  }
378  else{
379  array.data[offsetSlice] = data[
380  offsetOriginal*ranges[subindex]
381  + index[subindex]
382  ];
383  }
384  }
385  else{
386  if(index[subindex] == IDX_ALL){
387  for(unsigned int n = 0; n < ranges[subindex]; n++){
388  fillSlice(
389  array,
390  index,
391  subindex+1,
392  offsetSlice*ranges[subindex] + n,
393  offsetOriginal*ranges[subindex] + n
394  );
395  }
396  }
397  else{
398  fillSlice(
399  array,
400  index,
401  subindex+1,
402  offsetSlice,
403  offsetOriginal*ranges[subindex]
404  + index[subindex]
405  );
406  }
407  }
408 }
409 
410 template<typename DataType>
411 inline const std::vector<unsigned int>& Array<DataType>::getRanges() const{
412  return ranges;
413 }
414 
415 template<typename DataType>
417  const Array<DataType> &array,
418  std::string functionName
419 ) const{
420  TBTKAssert(
421  ranges.size() == array.ranges.size(),
422  "Array::" + functionName,
423  "Incompatible ranges.",
424  "Left and right hand sides must have the same number of"
425  << " dimensions."
426  );
427  for(unsigned int n = 0; n < ranges.size(); n++){
428  TBTKAssert(
429  ranges[n] == array.ranges[n],
430  "Array::" + functionName,
431  "Incompatible ranges.",
432  "Left and right hand sides must have the same ranges."
433  );
434  }
435 }
436 
437 }; //End of namesapce TBTK
438 
439 #endif
Array operator*(const DataType &rhs) const
Definition: Array.h:303
Array operator-(const Array &rhs) const
Definition: Array.h:290
Flexible physical index.
Array< DataType > getSlice(const std::vector< int > &index) const
Definition: Array.h:325
Array operator+(const Array &rhs) const
Definition: Array.h:277
Precompiler macros.
Array()
Definition: Array.h:131
friend Array operator*(const DataType &lhs, const Array &rhs)
Definition: Array.h:88
Definition: Array.h:34
DataType & operator[](const std::initializer_list< unsigned int > &index)
Definition: Array.h:239
Definition: ModelFactory.h:35
~Array()
Definition: Array.h:199
const std::vector< unsigned int > & getRanges() const
Definition: Array.h:411
Array & operator=(const Array &rhs)
Definition: Array.h:205
Array operator/(const DataType &rhs) const
Definition: Array.h:314