BEM++  2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
_3d_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 // _3dArray
27 
28 template <typename T>
29 inline _3dArray<T>::_3dArray()
30 {
31  init_empty();
32 }
33 
34 template <typename T>
35 inline _3dArray<T>::_3dArray(size_t extent0, size_t extent1, size_t extent2)
36 {
37  init_memory(extent0, extent1, extent2);
38 }
39 
40 template <typename T>
41 inline _3dArray<T>::_3dArray(size_t extent0, size_t extent1, size_t extent2, T* data, bool strict)
42 {
43 #ifdef FIBER_CHECK_ARRAY_BOUNDS
44  check_extents(extent0, extent1, extent2);
45 #endif
46  m_extents[0] = extent0;
47  m_extents[1] = extent1;
48  m_extents[2] = extent2;
49  m_storage = data;
50  m_owns = false;
51  m_strict = strict;
52 }
53 
54 template <typename T>
55 inline _3dArray<T>::_3dArray(const _3dArray& other)
56 {
57  if (!other.is_empty()) {
58  init_memory(other.m_extents[0], other.m_extents[1], other.m_extents[2]);
59  std::copy(other.begin(), other.end(), m_storage);
60  } else
61  init_empty();
62 }
63 
64 template <typename T>
65 inline _3dArray<T>& _3dArray<T>::operator=(const _3dArray& rhs)
66 {
67  if (&rhs != this) {
68  set_size(rhs.m_extents[0], rhs.m_extents[1], rhs.m_extents[2]);
69  std::copy(rhs.begin(), rhs.end(), m_storage);
70  }
71  return *this;
72 }
73 
74 template <typename T>
75 inline _3dArray<T>::~_3dArray()
76 {
77  free_memory();
78 }
79 
80 template <typename T>
81 inline void _3dArray<T>::init_memory(size_t extent0, size_t extent1, size_t extent2)
82 {
83 #ifdef FIBER_CHECK_ARRAY_BOUNDS
84  check_extents(extent0, extent1, extent2);
85 #endif
86  m_storage = new T[extent0 * extent1 * extent2];
87  m_owns = true;
88  m_strict = false;
89  m_extents[0] = extent0;
90  m_extents[1] = extent1;
91  m_extents[2] = extent2;
92 }
93 
94 template <typename T>
95 inline void _3dArray<T>::init_empty()
96 {
97  m_extents[0] = 0;
98  m_extents[1] = 0;
99  m_extents[2] = 0;
100  m_storage = 0;
101  m_owns = false;
102  m_strict = false;
103 }
104 
105 template <typename T>
106 inline void _3dArray<T>::free_memory()
107 {
108  if (m_owns && m_storage)
109  delete[] m_storage;
110  m_owns = false;
111  m_storage = 0;
112 }
113 
114 template <typename T>
115 inline T& _3dArray<T>::operator()(size_t index0, size_t index1, size_t index2)
116 {
117 #ifdef FIBER_CHECK_ARRAY_BOUNDS
118  check_indices(index0, index1, index2);
119 #endif
120  return m_storage[
121  index0 +
122  m_extents[0] * index1 +
123  m_extents[0] * m_extents[1] * index2];
124 }
125 
126 template <typename T>
127 inline const T& _3dArray<T>::operator()(size_t index0, size_t index1, size_t index2) const
128 {
129 #ifdef FIBER_CHECK_ARRAY_BOUNDS
130  check_indices(index0, index1, index2);
131 #endif
132  return m_storage[
133  index0 +
134  m_extents[0] * index1 +
135  m_extents[0] * m_extents[1] * index2];
136 }
137 
138 template <typename T>
139 inline size_t _3dArray<T>::extent(size_t dimension) const
140 {
141 #ifdef FIBER_CHECK_ARRAY_BOUNDS
142  check_dimension(dimension);
143 #endif
144  return m_extents[dimension];
145 }
146 
147 template <typename T>
148 inline _3dArray<T>& _3dArray<T>::operator+=(const _3dArray<T>& other){
149  if ((this->extent(0)!= other.extent(0))||
150  (this->extent(1)!= other.extent(1))||
151  (this->extent(2)!= other.extent(2)))
152  std::runtime_error("_3dArray<T> operator+=: Array sizes don't agree.");
153  for (size_t i=0;i<this->extent(2);++i)
154  for (size_t j=0;j<this->extent(1);++j)
155  for (size_t k=0;k<this->extent(0);++k)
156  (*this)(k,j,i)+=other(k,j,i);
157  return *this;
158 
159 }
160 
161 template <typename T>
162 inline _3dArray<T>& _3dArray<T>::operator*=(const T& other) {
163  for (size_t i=0;i<this->extent(2);++i)
164  for (size_t j=0;j<this->extent(1);++j)
165  for (size_t k=0;k<this->extent(0);++k)
166  (*this)(k,j,i)*=other;
167  return *this;
168 }
169 
170 
171 
172 template <typename T>
173 inline void _3dArray<T>::set_size(size_t extent0, size_t extent1, size_t extent2)
174 {
175  if (extent0 * extent1 * extent2 ==
176  m_extents[0] * m_extents[1] * m_extents[2]) {
177  m_extents[0] = extent0;
178  m_extents[1] = extent1;
179  m_extents[2] = extent2;
180  }
181  else {
182  if (m_strict)
183  throw std::runtime_error("_3dArray::set_size(): Changing the total "
184  "number of elements stored in an array "
185  "created in the strict mode is not allowed");
186  if (m_owns) {
187  delete[] m_storage;
188  m_storage = 0;
189  }
190  if (extent0 * extent1 * extent2 != 0)
191  init_memory(extent0, extent1, extent2);
192  else
193  init_empty();
194  }
195 }
196 
197 template <typename T>
198 inline bool _3dArray<T>::is_empty() const
199 {
200  return m_extents[0] * m_extents[1] * m_extents[2] == 0;
201 }
202 
203 template <typename T>
204 inline typename _3dArray<T>::iterator _3dArray<T>::begin()
205 {
206  return m_storage;
207 }
208 
209 template <typename T>
210 inline typename _3dArray<T>::const_iterator _3dArray<T>::begin() const
211 {
212  return m_storage;
213 }
214 
215 template <typename T>
216 inline typename _3dArray<T>::iterator _3dArray<T>::end()
217 {
218  return m_storage + m_extents[0] * m_extents[1] * m_extents[2];
219 }
220 
221 template <typename T>
222 inline typename _3dArray<T>::const_iterator _3dArray<T>::end() const
223 {
224  return m_storage + m_extents[0] * m_extents[1] * m_extents[2];
225 }
226 
227 #ifdef FIBER_CHECK_ARRAY_BOUNDS
228 template <typename T>
229 inline void _3dArray<T>::check_dimension(size_t dimension) const
230 {
231  if (2 < dimension)
232  throw std::invalid_argument("Invalid dimension");
233 }
234 
235 template <typename T>
236 inline void _3dArray<T>::check_extents(size_t extent0, size_t extent1, size_t extent2) const
237 {
238 }
239 
240 template <typename T>
241 inline void _3dArray<T>::check_indices(size_t index0, size_t index1, size_t index2) const
242 {
243  if (m_extents[0] <= index0 ||
244  m_extents[1] <= index1 ||
245  m_extents[2] <= index2)
246  throw std::out_of_range("Invalid index");
247 }
248 #endif // FIBER_CHECK_ARRAY_BOUNDS
249 
250 // _2dSliceOf3dArray
251 
252 template <typename T>
253 inline _2dSliceOf3dArray<T>::_2dSliceOf3dArray(_3dArray<T>& array, size_t index2) :
254  m_array(array), m_index2(index2)
255 {}
256 
257 template <typename T>
259  return *this;
260 }
261 
262 template <typename T>
263 inline const T& _2dSliceOf3dArray<T>::operator()(size_t index0, size_t index1) const {
264  return m_array(index0, index1, m_index2);
265 }
266 
267 template <typename T>
268 inline T& _2dSliceOf3dArray<T>::operator()(size_t index0, size_t index1) {
269  return m_array(index0, index1, m_index2);
270 }
271 
272 template <typename T>
273 inline size_t _2dSliceOf3dArray<T>::extent(size_t dimension) const {
274  check_dimension(dimension);
275  return m_array.extent(dimension);
276 }
277 
278 template <typename T>
279 inline void _2dSliceOf3dArray<T>::check_dimension(size_t dimension) const {
280 #ifdef FIBER_CHECK_ARRAY_BOUNDS
281  if (1 < dimension)
282  throw std::invalid_argument("Invalid dimension");
283 #endif
284 }
285 
286 // _2dSliceOfConst3dArray
287 
288 template <typename T>
289 inline _2dSliceOfConst3dArray<T>::_2dSliceOfConst3dArray(
290  const _3dArray<T>& array, size_t index2) :
291  m_array(array), m_index2(index2)
292 {}
293 
294 template <typename T>
295 inline const T& _2dSliceOfConst3dArray<T>::operator()(size_t index0, size_t index1) const {
296  return m_array(index0, index1, m_index2);
297 }
298 
299 template <typename T>
300 inline size_t _2dSliceOfConst3dArray<T>::extent(size_t dimension) const {
301  check_dimension(dimension);
302  return m_array.extent(dimension);
303 }
304 
305 template <typename T>
306 inline void _2dSliceOfConst3dArray<T>::check_dimension(size_t dimension) const {
307 #ifdef FIBER_CHECK_ARRAY_BOUNDS
308  if (1 < dimension)
309  throw std::invalid_argument("Invalid dimension");
310 #endif
311 }
312 
313 // _1dSliceOf3dArray
314 
315 template <typename T>
317  _3dArray<T>& array, size_t index1, size_t index2) :
318  m_array(array), m_index1(index1), m_index2(index2)
319 {}
320 
321 template <typename T>
323  return *this;
324 }
325 
326 template <typename T>
327 inline const T& _1dSliceOf3dArray<T>::operator()(size_t index0) const {
328  return m_array(index0, m_index1, m_index2);
329 }
330 
331 template <typename T>
332 inline T& _1dSliceOf3dArray<T>::operator()(size_t index0) {
333  return m_array(index0, m_index1, m_index2);
334 }
335 
336 template <typename T>
337 inline size_t _1dSliceOf3dArray<T>::extent(size_t dimension) const {
338  check_dimension(dimension);
339  return m_array.extent(dimension);
340 }
341 
342 template <typename T>
343 inline void _1dSliceOf3dArray<T>::check_dimension(size_t dimension) const {
344 #ifdef FIBER_CHECK_ARRAY_BOUNDS
345  if (0 < dimension)
346  throw std::invalid_argument("Invalid dimension");
347 #endif
348 }
349 
350 // _1dSliceOfConst3dArray
351 
352 template <typename T>
353 inline _1dSliceOfConst3dArray<T>::_1dSliceOfConst3dArray(
354  const _3dArray<T>& array, size_t index1, size_t index2) :
355  m_array(array), m_index1(index1), m_index2(index2)
356 {}
357 
358 template <typename T>
359 inline const T& _1dSliceOfConst3dArray<T>::operator()(size_t index0) const {
360  return m_array(index0, m_index1, m_index2);
361 }
362 
363 template <typename T>
364 inline size_t _1dSliceOfConst3dArray<T>::extent(size_t dimension) const {
365  check_dimension(dimension);
366  return m_array.extent(dimension);
367 }
368 
369 template <typename T>
370 inline void _1dSliceOfConst3dArray<T>::check_dimension(size_t dimension) const {
371 #ifdef FIBER_CHECK_ARRAY_BOUNDS
372  if (0 < dimension)
373  throw std::invalid_argument("Invalid dimension");
374 #endif
375 }
376 
377 } // namespace Fiber
_1dSliceOf3dArray(_3dArray< T > &array, size_t index1, size_t index2)
Construct a slice consisting of the elements array(:,index1,index2)
Definition: _3d_array_imp.hpp:316
Lightweight encapsulation of a 2D slice of a 3D array.
Definition: _3d_array.hpp:107
_1dSliceOf3dArray & self()
Returns a reference to self.
Definition: _3d_array_imp.hpp:322
Lightweight encapsulation of a 1D slice of a 3D array.
Definition: _3d_array.hpp:155
_2dSliceOf3dArray & self()
Returns a reference to self.
Definition: _3d_array_imp.hpp:258
Simple implementation of a 3D Fortran-ordered array.
Definition: _3d_array.hpp:48