BEM++  2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
_2d_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 _2dArray<T>::_2dArray()
28 {
29  m_storage = 0;
30  m_owns = false;
31  m_extents[0] = 0;
32  m_extents[1] = 0;
33 }
34 
35 template <typename T>
36 inline _2dArray<T>::_2dArray(size_t extent0, size_t extent1)
37 {
38  init_memory(extent0, extent1);
39 }
40 
41 template <typename T>
42 inline _2dArray<T>::_2dArray(size_t extent0, size_t extent1, T* data)
43 {
44 #ifdef FIBER_CHECK_ARRAY_BOUNDS
45  check_extents(extent0, extent1);
46 #endif
47  m_storage = data;
48  m_owns = false;
49  m_extents[0] = extent0;
50  m_extents[1] = extent1;
51 }
52 
53 template <typename T>
54 inline _2dArray<T>::_2dArray(const _2dArray& other)
55 {
56  init_memory(other.m_extents[0], other.m_extents[1]);
57  std::copy(other.begin(), other.end(), m_storage);
58 }
59 
60 template <typename T>
61 inline _2dArray<T>& _2dArray<T>::operator=(const _2dArray& rhs)
62 {
63  if (&rhs != this) {
64  set_size(rhs.m_extents[0], rhs.m_extents[1]);
65  std::copy(rhs.begin(), rhs.end(), m_storage);
66  }
67  return *this;
68 }
69 
70 template <typename T>
71 inline _2dArray<T>::~_2dArray()
72 {
73  free_memory();
74 }
75 
76 template <typename T>
77 inline void _2dArray<T>::init_memory(size_t extent0, size_t extent1)
78 {
79 #ifdef FIBER_CHECK_ARRAY_BOUNDS
80  check_extents(extent0, extent1);
81 #endif
82  m_storage = new T[extent0 * extent1];
83  m_owns = true;
84  m_extents[0] = extent0;
85  m_extents[1] = extent1;
86 }
87 
88 template <typename T>
89 inline void _2dArray<T>::free_memory()
90 {
91  if (m_owns && m_storage)
92  delete[] m_storage;
93  m_owns = false;
94  m_storage = 0;
95 }
96 
97 template <typename T>
98 inline T& _2dArray<T>::operator()(size_t index0, size_t index1)
99 {
100 #ifdef FIBER_CHECK_ARRAY_BOUNDS
101  check_indices(index0, index1);
102 #endif
103  return m_storage[index0 + m_extents[0] * index1];
104 }
105 
106 template <typename T>
107 inline const T& _2dArray<T>::operator()(size_t index0, size_t index1) const
108 {
109 #ifdef FIBER_CHECK_ARRAY_BOUNDS
110  check_indices(index0, index1);
111 #endif
112  return m_storage[index0 + m_extents[0] * index1];
113 }
114 
115 template <typename T>
116 inline size_t _2dArray<T>::extent(size_t dimension) const
117 {
118 #ifdef FIBER_CHECK_ARRAY_BOUNDS
119  check_dimension(dimension);
120 #endif
121  return m_extents[dimension];
122 }
123 
124 template <typename T>
125 inline void _2dArray<T>::set_size(size_t extent0, size_t extent1)
126 {
127 #ifdef FIBER_CHECK_ARRAY_BOUNDS
128  check_extents(extent0, extent1);
129 #endif
130  if (extent0 * extent1 == m_extents[0] * m_extents[1]) {
131  m_extents[0] = extent0;
132  m_extents[1] = extent1;
133  }
134  else {
135  free_memory();
136  init_memory(extent0, extent1);
137  }
138 }
139 
140 template <typename T>
141 inline _2dArray<T>& _2dArray<T>::operator+=(const _2dArray<T>& other){
142  if ((this->extent(0)!= other.extent(0))||
143  (this->extent(1)!= other.extent(1)))
144  std::runtime_error("_2dArray<T> operator+=: Array sizes don't agree.");
145  for (size_t i=0;i<this->extent(1);++i)
146  for (size_t j=0;j<this->extent(0);++j)
147  (*this)(j,i)+=other(j,i);
148  return *this;
149 
150 }
151 
152 template <typename T>
153 inline _2dArray<T>& _2dArray<T>::operator*=(const T& other) {
154  for (size_t i=0;i<this->extent(1);++i)
155  for (size_t j=0;j<this->extent(0);++j)
156  (*this)(j,i)*=other;
157  return *this;
158 }
159 
160 
161 template <typename T>
162 inline typename _2dArray<T>::iterator _2dArray<T>::begin()
163 {
164  return m_storage;
165 }
166 
167 template <typename T>
168 inline typename _2dArray<T>::const_iterator _2dArray<T>::begin() const
169 {
170  return m_storage;
171 }
172 
173 template <typename T>
174 inline typename _2dArray<T>::iterator _2dArray<T>::end()
175 {
176  return m_storage + m_extents[0] * m_extents[1];
177 }
178 
179 template <typename T>
180 inline typename _2dArray<T>::const_iterator _2dArray<T>::end() const
181 {
182  return m_storage + m_extents[0] * m_extents[1];
183 }
184 
185 #ifdef FIBER_CHECK_ARRAY_BOUNDS
186 template <typename T>
187 inline void _2dArray<T>::check_dimension(size_t dimension) const
188 {
189  if (1 < dimension)
190  throw std::invalid_argument("Invalid dimension");
191 }
192 
193 template <typename T>
194 inline void _2dArray<T>::check_extents(size_t extent0, size_t extent1) const
195 {
196 }
197 
198 template <typename T>
199 inline void _2dArray<T>::check_indices(size_t index0, size_t index1) const
200 {
201  if (m_extents[0] <= index0 ||
202  m_extents[1] <= index1)
203  throw std::out_of_range("Invalid index");
204 }
205 #endif // FIBER_CHECK_ARRAY_BOUNDS
206 
207 // _1dSliceOf2dArray
208 
209 template <typename T>
211  _2dArray<T>& array, size_t index1) :
212  m_array(array), m_index1(index1)
213 {}
214 
215 template <typename T>
217  return *this;
218 }
219 
220 template <typename T>
221 inline const T& _1dSliceOf2dArray<T>::operator()(size_t index0) const {
222  return m_array(index0, m_index1);
223 }
224 
225 template <typename T>
226 inline T& _1dSliceOf2dArray<T>::operator()(size_t index0) {
227  return m_array(index0, m_index1);
228 }
229 
230 template <typename T>
231 inline size_t _1dSliceOf2dArray<T>::extent(size_t dimension) const {
232  check_dimension(dimension);
233  return m_array.extent(dimension);
234 }
235 
236 template <typename T>
237 inline void _1dSliceOf2dArray<T>::check_dimension(size_t dimension) const {
238 #ifdef FIBER_CHECK_ARRAY_BOUNDS
239  if (0 < dimension)
240  throw std::invalid_argument("Invalid dimension");
241 #endif
242 }
243 
244 // _1dSliceOfConst2dArray
245 
246 template <typename T>
247 inline _1dSliceOfConst2dArray<T>::_1dSliceOfConst2dArray(
248  const _2dArray<T>& array, size_t index1) :
249  m_array(array), m_index1(index1)
250 {}
251 
252 template <typename T>
253 inline const T& _1dSliceOfConst2dArray<T>::operator()(size_t index0) const {
254  return m_array(index0, m_index1);
255 }
256 
257 template <typename T>
258 inline size_t _1dSliceOfConst2dArray<T>::extent(size_t dimension) const {
259  check_dimension(dimension);
260  return m_array.extent(dimension);
261 }
262 
263 template <typename T>
264 inline void _1dSliceOfConst2dArray<T>::check_dimension(size_t dimension) const {
265 #ifdef FIBER_CHECK_ARRAY_BOUNDS
266  if (0 < dimension)
267  throw std::invalid_argument("Invalid dimension");
268 #endif
269 }
270 
271 } // namespace Fiber
_1dSliceOf2dArray & self()
Returns a reference to self.
Definition: _2d_array_imp.hpp:216
Lightweight encapsulation of a 1D slice of a 2D array.
Definition: _2d_array.hpp:89
_1dSliceOf2dArray(_2dArray< T > &array, size_t index1)
Construct a slice consisting of the elements array(:,index1)
Definition: _2d_array_imp.hpp:210
Simple implementation of a 2D Fortran-ordered array.
Definition: _2d_array.hpp:41