BEM++  2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
_4d_array_imp.hpp
1 // Copyright (C) 2011-2012 by the BEM++ Authors
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 // THE SOFTWARE.
20 
21 #include <stdexcept>
22 
23 namespace Fiber
24 {
25 
26 template <typename T>
27 inline _4dArray<T>::_4dArray()
28 {
29  m_extents[0] = 0;
30  m_extents[1] = 0;
31  m_extents[2] = 0;
32  m_extents[3] = 0;
33  m_storage = 0;
34  m_owns = false;
35 }
36 
37 template <typename T>
38 inline _4dArray<T>::_4dArray(size_t extent0, size_t extent1, size_t extent2, size_t extent3)
39 {
40  init_memory(extent0, extent1, extent2, extent3);
41 }
42 
43 template <typename T>
44 inline _4dArray<T>::_4dArray(size_t extent0, size_t extent1, size_t extent2, size_t extent3, T* data)
45 {
46 #ifdef FIBER_CHECK_ARRAY_BOUNDS
47  check_extents(extent0, extent1, extent2, extent3);
48 #endif
49  m_extents[0] = extent0;
50  m_extents[1] = extent1;
51  m_extents[2] = extent2;
52  m_extents[3] = extent3;
53  m_storage = data;
54  m_owns = false;
55 }
56 
57 template <typename T>
58 inline _4dArray<T>::_4dArray(const _4dArray& other)
59 {
60  init_memory(other.m_extents[0], other.m_extents[1],
61  other.m_extents[2], other.m_extents[3]);
62  std::copy(other.begin(), other.end(), m_storage);
63 }
64 
65 template <typename T>
66 inline _4dArray<T>& _4dArray<T>::operator=(const _4dArray& rhs)
67 {
68  if (&rhs != this) {
69  set_size(rhs.m_extents[0], rhs.m_extents[1],
70  rhs.m_extents[2], rhs.m_extents[3]);
71  std::copy(rhs.begin(), rhs.end(), m_storage);
72  }
73  return *this;
74 }
75 
76 template <typename T>
77 inline _4dArray<T>::~_4dArray()
78 {
79  free_memory();
80 }
81 
82 template <typename T>
83 inline void _4dArray<T>::init_memory(size_t extent0, size_t extent1,
84  size_t extent2, size_t extent3)
85 {
86 #ifdef FIBER_CHECK_ARRAY_BOUNDS
87  check_extents(extent0, extent1, extent2, extent3);
88 #endif
89  m_storage = new T[extent0 * extent1 * extent2 * extent3];
90  m_owns = true;
91  m_extents[0] = extent0;
92  m_extents[1] = extent1;
93  m_extents[2] = extent2;
94  m_extents[3] = extent3;
95 }
96 
97 template <typename T>
98 inline void _4dArray<T>::free_memory()
99 {
100  if (m_owns && m_storage)
101  delete[] m_storage;
102  m_owns = false;
103  m_storage = 0;
104 }
105 
106 
107 template <typename T>
108 inline _4dArray<T>& _4dArray<T>::operator+=(const _4dArray<T>& other){
109  if ((this->extent(0)!= other.extent(0))||
110  (this->extent(1)!= other.extent(1))||
111  (this->extent(2)!= other.extent(2))||
112  (this->extent(3)!= other.extent(3)))
113  std::runtime_error("_4dArray<T> operator+=: Array sizes don't agree.");
114  for (size_t i=0;i<this->extent(3);++i)
115  for (size_t j=0;j<this->extent(2);++j)
116  for (size_t k=0;k<this->extent(1);++k)
117  for (size_t l=0;l<this->extent(0);++l)
118  (*this)(l,k,j,i)+=other(l,k,j,i);
119  return *this;
120 
121 }
122 
123 template <typename T>
124 inline _4dArray<T>& _4dArray<T>::operator*=(const T& other) {
125  for (size_t i=0;i<this->extent(3);++i)
126  for (size_t j=0;j<this->extent(2);++j)
127  for (size_t k=0;k<this->extent(1);++k)
128  for (size_t l=0;l<this->extent(0);++l)
129  (*this)(l,k,j,i)*=other;
130  return *this;
131 }
132 
133 
134 template <typename T>
135 inline T& _4dArray<T>::operator()(size_t index0, size_t index1, size_t index2, size_t index3)
136 {
137 #ifdef FIBER_CHECK_ARRAY_BOUNDS
138  check_indices(index0, index1, index2, index3);
139 #endif
140  return m_storage[
141  index0 +
142  m_extents[0] * index1 +
143  m_extents[0] * m_extents[1] * index2 +
144  m_extents[0] * m_extents[1] * m_extents[2] * index3];
145 }
146 
147 template <typename T>
148 inline const T& _4dArray<T>::operator()(size_t index0, size_t index1, size_t index2, size_t index3) const
149 {
150 #ifdef FIBER_CHECK_ARRAY_BOUNDS
151  check_indices(index0, index1, index2, index3);
152 #endif
153  return m_storage[
154  index0 +
155  m_extents[0] * index1 +
156  m_extents[0] * m_extents[1] * index2 +
157  m_extents[0] * m_extents[1] * m_extents[2] * index3];
158 }
159 
160 template <typename T>
161 inline size_t _4dArray<T>::extent(size_t dimension) const
162 {
163 #ifdef FIBER_CHECK_ARRAY_BOUNDS
164  check_dimension(dimension);
165 #endif
166  return m_extents[dimension];
167 }
168 
169 template <typename T>
170 inline void _4dArray<T>::set_size(size_t extent0, size_t extent1, size_t extent2, size_t extent3)
171 {
172 #ifdef FIBER_CHECK_ARRAY_BOUNDS
173  check_extents(extent0, extent1, extent2, extent3);
174 #endif
175  if (extent0 * extent1 * extent2 * extent3 ==
176  m_extents[0] * m_extents[1] * m_extents[2] * m_extents[3]) {
177  m_extents[0] = extent0;
178  m_extents[1] = extent1;
179  m_extents[2] = extent2;
180  m_extents[3] = extent3;
181  }
182  else {
183  if (m_owns && m_storage) {
184  delete[] m_storage;
185  m_storage = 0;
186  }
187  m_extents[0] = extent0;
188  m_extents[1] = extent1;
189  m_extents[2] = extent2;
190  m_extents[3] = extent3;
191  m_storage = new T[extent0 * extent1 * extent2 * extent3];
192  m_owns = true;
193  }
194 }
195 
196 template <typename T>
197 inline typename _4dArray<T>::iterator _4dArray<T>::begin()
198 {
199  return m_storage;
200 }
201 
202 template <typename T>
203 inline typename _4dArray<T>::const_iterator _4dArray<T>::begin() const
204 {
205  return m_storage;
206 }
207 
208 template <typename T>
209 inline typename _4dArray<T>::iterator _4dArray<T>::end()
210 {
211  return m_storage + m_extents[0] * m_extents[1] * m_extents[2] * m_extents[3];
212 }
213 
214 template <typename T>
215 inline typename _4dArray<T>::const_iterator _4dArray<T>::end() const
216 {
217  return m_storage + m_extents[0] * m_extents[1] * m_extents[2] * m_extents[3];
218 }
219 
220 #ifdef FIBER_CHECK_ARRAY_BOUNDS
221 template <typename T>
222 inline void _4dArray<T>::check_dimension(size_t dimension) const
223 {
224  if (3 < dimension)
225  throw std::invalid_argument("Invalid dimension");
226 }
227 
228 template <typename T>
229 inline void _4dArray<T>::check_extents(size_t extent0, size_t extent1, size_t extent2, size_t extent3) const
230 {
231 }
232 
233 template <typename T>
234 inline void _4dArray<T>::check_indices(size_t index0, size_t index1, size_t index2, size_t index3) const
235 {
236  if (m_extents[0] <= index0 ||
237  m_extents[1] <= index1 ||
238  m_extents[2] <= index2 ||
239  m_extents[3] <= index3)
240  throw std::out_of_range("Invalid index");
241 }
242 #endif // FIBER_CHECK_ARRAY_BOUNDS
243 
244 // _3dSliceOf4dArray
245 
246 template <typename T>
247 inline _3dSliceOf4dArray<T>::_3dSliceOf4dArray(_4dArray<T>& array, size_t index3) :
248  m_array(array), m_index3(index3)
249 {}
250 
251 template <typename T>
253  return *this;
254 }
255 
256 template <typename T>
257 inline const T& _3dSliceOf4dArray<T>::operator()(size_t index0, size_t index1, size_t index2) const {
258  return m_array(index0, index1, index2, m_index3);
259 }
260 
261 template <typename T>
262 inline T& _3dSliceOf4dArray<T>::operator()(size_t index0, size_t index1, size_t index2) {
263  return m_array(index0, index1, index2, m_index3);
264 }
265 
266 template <typename T>
267 inline size_t _3dSliceOf4dArray<T>::extent(size_t dimension) const {
268  check_dimension(dimension);
269  return m_array.extent(dimension);
270 }
271 
272 template <typename T>
273 inline void _3dSliceOf4dArray<T>::check_dimension(size_t dimension) const {
274 #ifdef FIBER_CHECK_ARRAY_BOUNDS
275  if (2 < dimension)
276  throw std::invalid_argument("Invalid dimension");
277 #endif
278 }
279 
280 // _3dSliceOfConst4dArray
281 
282 template <typename T>
283 inline _3dSliceOfConst4dArray<T>::_3dSliceOfConst4dArray(
284  const _4dArray<T>& array, size_t index3) :
285  m_array(array), m_index3(index3)
286 {}
287 
288 template <typename T>
289 inline const T& _3dSliceOfConst4dArray<T>::operator()(size_t index0, size_t index1, size_t index2) const {
290  return m_array(index0, index1, index2, m_index3);
291 }
292 
293 template <typename T>
294 inline size_t _3dSliceOfConst4dArray<T>::extent(size_t dimension) const {
295  check_dimension(dimension);
296  return m_array.extent(dimension);
297 }
298 
299 template <typename T>
300 inline void _3dSliceOfConst4dArray<T>::check_dimension(size_t dimension) const {
301 #ifdef FIBER_CHECK_ARRAY_BOUNDS
302  if (2 < dimension)
303  throw std::invalid_argument("Invalid dimension");
304 #endif
305 }
306 
307 // _2dSliceOf4dArray
308 
309 template <typename T>
310 inline _2dSliceOf4dArray<T>::_2dSliceOf4dArray(_4dArray<T>& array, size_t index2, size_t index3) :
311  m_array(array), m_index2(index2), m_index3(index3)
312 {}
313 
314 template <typename T>
316  return *this;
317 }
318 
319 template <typename T>
320 inline const T& _2dSliceOf4dArray<T>::operator()(size_t index0, size_t index1) const {
321  return m_array(index0, index1, m_index2, m_index3);
322 }
323 
324 template <typename T>
325 inline T& _2dSliceOf4dArray<T>::operator()(size_t index0, size_t index1) {
326  return m_array(index0, index1, m_index2, m_index3);
327 }
328 
329 template <typename T>
330 inline size_t _2dSliceOf4dArray<T>::extent(size_t dimension) const {
331  check_dimension(dimension);
332  return m_array.extent(dimension);
333 }
334 
335 template <typename T>
336 inline void _2dSliceOf4dArray<T>::check_dimension(size_t dimension) const {
337 #ifdef FIBER_CHECK_ARRAY_BOUNDS
338  if (1 < dimension)
339  throw std::invalid_argument("Invalid dimension");
340 #endif
341 }
342 
343 // _2dSliceOfConst4dArray
344 
345 template <typename T>
346 inline _2dSliceOfConst4dArray<T>::_2dSliceOfConst4dArray(
347  const _4dArray<T>& array, size_t index2, size_t index3) :
348  m_array(array), m_index2(index2), m_index3(index3)
349 {}
350 
351 template <typename T>
352 inline const T& _2dSliceOfConst4dArray<T>::operator()(size_t index0, size_t index1) const {
353  return m_array(index0, index1, m_index2, m_index3);
354 }
355 
356 template <typename T>
357 inline size_t _2dSliceOfConst4dArray<T>::extent(size_t dimension) const {
358  check_dimension(dimension);
359  return m_array.extent(dimension);
360 }
361 
362 template <typename T>
363 inline void _2dSliceOfConst4dArray<T>::check_dimension(size_t dimension) const {
364 #ifdef FIBER_CHECK_ARRAY_BOUNDS
365  if (1 < dimension)
366  throw std::invalid_argument("Invalid dimension");
367 #endif
368 }
369 
370 // _1dSliceOf4dArray
371 
372 template <typename T>
374  _4dArray<T>& array, size_t index1, size_t index2, size_t index3) :
375  m_array(array), m_index1(index1), m_index2(index2), m_index3(index3)
376 {}
377 
378 template <typename T>
380  return *this;
381 }
382 
383 template <typename T>
384 inline const T& _1dSliceOf4dArray<T>::operator()(size_t index0) const {
385  return m_array(index0, m_index1, m_index2, m_index3);
386 }
387 
388 template <typename T>
389 inline T& _1dSliceOf4dArray<T>::operator()(size_t index0) {
390  return m_array(index0, m_index1, m_index2, m_index3);
391 }
392 
393 template <typename T>
394 inline size_t _1dSliceOf4dArray<T>::extent(size_t dimension) const {
395  check_dimension(dimension);
396  return m_array.extent(dimension);
397 }
398 
399 template <typename T>
400 inline void _1dSliceOf4dArray<T>::check_dimension(size_t dimension) const {
401 #ifdef FIBER_CHECK_ARRAY_BOUNDS
402  if (0 < dimension)
403  throw std::invalid_argument("Invalid dimension");
404 #endif
405 }
406 
407 // _1dSliceOfConst4dArray
408 
409 template <typename T>
410 inline _1dSliceOfConst4dArray<T>::_1dSliceOfConst4dArray(
411  const _4dArray<T>& array, size_t index1, size_t index2, size_t index3) :
412  m_array(array), m_index1(index1), m_index2(index2), m_index3(index3)
413 {}
414 
415 template <typename T>
416 inline const T& _1dSliceOfConst4dArray<T>::operator()(size_t index0) const {
417  return m_array(index0, m_index1, m_index2, m_index3);
418 }
419 
420 template <typename T>
421 inline size_t _1dSliceOfConst4dArray<T>::extent(size_t dimension) const {
422  check_dimension(dimension);
423  return m_array.extent(dimension);
424 }
425 
426 template <typename T>
427 inline void _1dSliceOfConst4dArray<T>::check_dimension(size_t dimension) const {
428 #ifdef FIBER_CHECK_ARRAY_BOUNDS
429  if (0 < dimension)
430  throw std::invalid_argument("Invalid dimension");
431 #endif
432 }
433 
434 } // namespace Fiber
_2dSliceOf4dArray & self()
Returns a reference to self.
Definition: _4d_array_imp.hpp:315
Simple implementation of a 4D Fortran-ordered array.
Definition: _4d_array.hpp:50
_1dSliceOf4dArray(_4dArray< T > &array, size_t index1, size_t index2, size_t index3)
Construct a slice consisting of the elements array(:,index1,index2,index3)
Definition: _4d_array_imp.hpp:373
_3dSliceOf4dArray & self()
Returns a reference to self.
Definition: _4d_array_imp.hpp:252
Lightweight encapsulation of a 3D slice of a 4D array.
Definition: _4d_array.hpp:99
Lightweight encapsulation of a 2D slice of a 4d array.
Definition: _4d_array.hpp:147
_1dSliceOf4dArray & self()
Returns a reference to self.
Definition: _4d_array_imp.hpp:379
Lightweight encapsulation of a 1D slice of a 4d array.
Definition: _4d_array.hpp:195