iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ArrayImpl.H
Go to the documentation of this file.
1 /*! @file
2  @author
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 
35 
36 
39 
40 #include <boost/mpl/bool.hpp>
41 #include <boost/lexical_cast.hpp>
42 
43 // ######################################################################
44 #ifdef NRT_ARRAY_DEEPCOPY_THROWS
45 
46 template <class T> inline
47 nrt::exception::ArrayDeepCopyException<T>::ArrayDeepCopyException(nrt::Array<T> const * arr) throw()
48  try : nrt::exception::Exception("Error ArrayDeepCopyException, and further error while constructing the exception"),
49  whatstring("deepCopy() occured for array at " + boost::lexical_cast<std::string>(arr))
50 { whatptr = whatstring.c_str(); } catch (...) { }
51 
52 template <class T> inline
53 nrt::exception::ArrayDeepCopyException<T>::~ArrayDeepCopyException() throw()
54 { }
55 
56 #endif // NRT_ARRAY_DEEPCOPY_THROWS
57 
58 // ######################################################################
59 template <class T>
60 nrt::Array<T>::Array() : itsMemory( std::make_shared<Memory>() )
61 { }
62 
63 // ######################################################################
64 template <class T>
65 nrt::Array<T>::Array(size_t size) : itsMemory( std::make_shared<Memory>(size) )
66 { }
67 
68 template <class T>
69 nrt::Array<T>::Array(T const * data, size_t size) : itsMemory( std::make_shared<Memory>(data, size) )
70 { }
71 
72 // ######################################################################
73 template <class T>
74 nrt::Array<T>::Array(size_t size, T fillvalue) : itsMemory( std::make_shared<Memory>(size, fillvalue) )
75 { }
76 
77 // ######################################################################
78 template <class T>
80  : itsMemory(a.itsMemory)
81 { }
82 
83 // ######################################################################
84 template <class T>
86  : itsMemory(std::move(a.itsMemory))
87 { }
88 
89 // ######################################################################
90 template <class T>
92 { }
93 
94 // ######################################################################
95 template <class T>
97 {
98  itsMemory = a.itsMemory;
99  return *this;
100 }
101 
102 // ######################################################################
103 template <class T>
105 {
106  itsMemory = std::move(a.itsMemory);
107  return *this;
108 }
109 
110 // ######################################################################
111 template <class T>
113 { return (itsMemory.get() == a.itsMemory.get()); }
114 
115 // ######################################################################
116 template <class T>
117 size_t nrt::Array<T>::size() const
118 { return itsMemory->size; }
119 
120 // ######################################################################
121 template <class T>
122 T const & nrt::Array<T>::at(size_t index) const
123 {
124  if (index >= itsMemory->size)
125  throw std::range_error("Index [" + boost::lexical_cast<std::string>(index) + "] out of range");
126  return itsMemory->itsData[index];
127 }
128 
129 // ######################################################################
130 template <class T>
131 T const & nrt::Array<T>::operator[](size_t index) const
132 { return at(index); }
133 
134 // ######################################################################
135 template <class T>
136 T & nrt::Array<T>::operator[](size_t index)
137 {
138  if (index >= itsMemory->size)
139  throw std::range_error("Index [" + boost::lexical_cast<std::string>(index) + "] out of range");
140  return begin()[index];
141 }
142 
143 // ######################################################################
144 template <class T>
146 { return itsMemory->itsData; }
147 
148 // ######################################################################
149 template <class T>
151 { return itsMemory->itsData; }
152 
153 // ######################################################################
154 template <class T>
156 { return itsMemory->itsData + itsMemory->size; }
157 
158 // ######################################################################
159 template <class T>
161 { return itsMemory->itsData + itsMemory->size; }
162 
163 // ######################################################################
164 template <class T>
166 {
167  deepCopy();
168  return itsMemory->itsData;
169 }
170 
171 // ######################################################################
172 template <class T>
174 {
175  return begin()+itsMemory->size;
176 }
177 
178 // ######################################################################
179 template <class T>
181 {
182  if (itsMemory.unique()) return;
183 
184  itsMemory = std::make_shared<Memory>(*itsMemory);
185 
186 #ifdef NRT_ARRAY_DEEPCOPY_THROWS
187  throw nrt::exception::ArrayDeepCopyException<T>(this);
188 #endif
189 }
190 
191 // ######################################################################
192 // Memory
193 // ######################################################################
194 //! A reference counted storage class for an array of data
195 /*! This class is the core of the nrt::Array class - users should never need to
196  use it explicitely. */
197 template <class T>
199 {
200  public:
201  //! Construct an empty Memory
202  Memory();
203 
204  //! Create a Memory of the given size.
205  Memory(size_t size);
206 
207  //! Create a Memory of the given size, and fill it with the given value
208  template <class Scalar>
209  Memory(size_t size, Scalar const & value,
210  typename std::enable_if<std::is_arithmetic<Scalar>::value>::type * = 0);
211 
212  //! Create a Memory of the given size, and fill it with the given value
213  Memory(size_t size, T const & value);
214 
215  //! Create a Memory by copying the given data
216  Memory(T const * data, size_t size);
217 
218  //! Create a Memory as a deep copy of another memory
219  Memory(typename nrt::Array<T>::Memory const & m);
220 
221  //! Delete the Memory
222  ~Memory();
223 
224  //! The size of the internal data storage
225  size_t size;
226 
227  //! A pointer to the internal data storage
228  T * itsData;
229 
230  private:
231  //! Create a Memory of the given size
232  void ConstructMemory(size_t size, /*isTrivial = */ boost::mpl::bool_<true> );
233  void ConstructMemory(size_t size, /*isTrivial = */ boost::mpl::bool_<false> );
234 
235  //! Create a Memory of the given size, filled with the given value
236  void ConstructMemory(size_t size, T const & value, /*isTrivial = */ boost::mpl::bool_<true> );
237  void ConstructMemory(size_t size, T const & value, /*isTrivial = */ boost::mpl::bool_<false> );
238 
239  //! Create a Memory as a deep copy of another Memory
240  void ConstructMemory(typename nrt::Array<T>::Memory const & m, /*isTrivial = */ boost::mpl::bool_<true> );
241  void ConstructMemory(typename nrt::Array<T>::Memory const & m, /*isTrivial = */ boost::mpl::bool_<false> );
242 
243  //! Create a Memory as a deep copy of a raw array
244  void ConstructMemory(T const * data, /*isTrivial = */ boost::mpl::bool_<true> );
245  void ConstructMemory(T const * data, /*isTrivial = */ boost::mpl::bool_<false> );
246 
247  //! Delete the Memory and all associated data
248  void DeleteMemory(/*isTrivial = */ boost::mpl::bool_<true> );
249  void DeleteMemory(/*isTrivial = */ boost::mpl::bool_<false> );
250 
251  //! Save to a cereal archive
252  template <class Archive> void SaveMemory(Archive & ar, /*isTrivial = */ boost::mpl::bool_<true> ) const;
253  template <class Archive> void SaveMemory(Archive & ar, /*isTrivial = */ boost::mpl::bool_<false> ) const;
254 
255  //! Load from a cereal archive
256  template <class Archive> void LoadMemory(Archive & ar, /*isTrivial = */ boost::mpl::bool_<true> );
257  template <class Archive> void LoadMemory(Archive & ar, /*isTrivial = */ boost::mpl::bool_<false> );
258 
259  static const boost::mpl::bool_<std::is_pod<T>::value || std::is_base_of<nrt::trivial_type, T>::value > isTrivial;
260 
261  //! Serialization: save
262  friend class cereal::access;
263  template <class Archive>
264  void save( Archive & ar ) const
265  { SaveMemory(ar, isTrivial); }
266 
267  //! Serialization: load
268  template <class Archive>
269  void load( Archive & ar )
270  { LoadMemory(ar, isTrivial); }
271 };
272 
273 // ######################################################################
274 template <class T>
276  size(0),
277  itsData(NULL)
278 { }
279 
280 // ######################################################################
281 template <class T>
283  size(size)
284 { ConstructMemory(size, isTrivial); }
285 
286 // ######################################################################
287 template <class T>
288 nrt::Array<T>::Memory::Memory(size_t size, T const & value) :
289  size(size)
290 { ConstructMemory(size, value, isTrivial); }
291 
292 // ######################################################################
293 template <class T>
294 nrt::Array<T>::Memory::Memory(T const * data, size_t size) :
295  size(size)
296 { ConstructMemory(data, isTrivial); }
297 
298 // ######################################################################
299 template <class T>
301  size(m.size)
302 { ConstructMemory(m, isTrivial); }
303 
304 // ######################################################################
305 template <class T>
307 { DeleteMemory(isTrivial); }
308 
309 // ######################################################################
310 template <class T>
311 void nrt::Array<T>::Memory::ConstructMemory( size_t size, /*isTrivial = */ boost::mpl::bool_<true> )
312 {
313  itsData = static_cast<T*>(nrt::allocate(size * sizeof(T)));
314 }
315 
316 // ######################################################################
317 template <class T>
318 void nrt::Array<T>::Memory::ConstructMemory( size_t size, /*isTrivial = */ boost::mpl::bool_<false> )
319 {
320  itsData = new T[size];
321 }
322 
323 // ######################################################################
324 template <class T>
325 void nrt::Array<T>::Memory::ConstructMemory( size_t size, T const & value, /*isTrivial = */ boost::mpl::bool_<true> )
326 {
327  itsData = static_cast<T*>(nrt::allocate(size * sizeof(T)));
328  std::fill_n(itsData, size, value);
329 }
330 
331 // ######################################################################
332 template <class T>
333 void nrt::Array<T>::Memory::ConstructMemory( size_t size, T const & value, /*isTrivial = */ boost::mpl::bool_<false> )
334 {
335  itsData = new T[size];
336  std::fill_n(itsData, size, value);
337 }
338 
339 // ######################################################################
340 template <class T>
341 void nrt::Array<T>::Memory::ConstructMemory(nrt::Array<T>::Memory const & m, /*isTrivial = */ boost::mpl::bool_<true> )
342 {
343  itsData = static_cast<T*>(nrt::allocate(size * sizeof(T)));
344  memcpy(itsData, m.itsData, size * sizeof(T));
345 }
346 
347 // ######################################################################
348 template <class T>
349 void nrt::Array<T>::Memory::ConstructMemory(nrt::Array<T>::Memory const & m, /*isTrivial = */ boost::mpl::bool_<false> )
350 {
351  itsData = new T[size];
352  std::copy(m.itsData, m.itsData+m.size, itsData);
353 }
354 
355 // ######################################################################
356 template <class T>
357 void nrt::Array<T>::Memory::ConstructMemory(T const * data, /*isTrivial = */ boost::mpl::bool_<true> )
358 {
359  itsData = static_cast<T *>(nrt::allocate(size * sizeof(T)));
360  memcpy(itsData, data, size * sizeof(T));
361 }
362 
363 // ######################################################################
364 template <class T>
365 void nrt::Array<T>::Memory::ConstructMemory(T const * data, /*isTrivial = */ boost::mpl::bool_<false> )
366 {
367  itsData = new T[size];
368  std::copy(data, data + size, itsData);
369 }
370 
371 // ######################################################################
372 template <class T>
373 void nrt::Array<T>::Memory::DeleteMemory(/*isTrivial = */ boost::mpl::bool_<true> )
374 {
375  nrt::deallocate(itsData);
376 }
377 
378 // ######################################################################
379 template <class T>
380 void nrt::Array<T>::Memory::DeleteMemory(/*isTrivial = */ boost::mpl::bool_<false> )
381 {
382  delete [] itsData;
383 }
384 
385 // ######################################################################
386 template <class T> template <class Archive>
387 void nrt::Array<T>::Memory::SaveMemory(Archive & ar, /*isTrivial = */ boost::mpl::bool_<true> ) const
388 {
389  ar( size );
390  ar(cereal::binary_data(itsData, size * sizeof(T)));
391 }
392 
393 // ######################################################################
394 template <class T> template <class Archive>
395 void nrt::Array<T>::Memory::SaveMemory(Archive & ar, /*isTrivial = */ boost::mpl::bool_<false> ) const
396 {
397  ar( size );
398  T const * ptr = itsData;
399  for (size_t i = 0; i < size; ++i, ++ptr) ar(*ptr);
400 }
401 
402 // ######################################################################
403 template <class T> template <class Archive>
404 void nrt::Array<T>::Memory::LoadMemory(Archive & ar, /*isTrivial = */ boost::mpl::bool_<true> )
405 {
406  ar( size );
407 
408  ConstructMemory(size, isTrivial);
409  ar(cereal::binary_data(itsData, size * sizeof(T)));
410 }
411 
412 // ######################################################################
413 template <class T> template <class Archive>
414 void nrt::Array<T>::Memory::LoadMemory(Archive & ar, /*isTrivial = */ boost::mpl::bool_<false> )
415 {
416  ar( size );
417 
418  // We can allocate the memory raw since we are going to de-serialize the elements into it:
419  itsData = static_cast<T *>(nrt::allocate(size * sizeof(T)));
420 
421  T * ptr = itsData;
422  for (size_t i = 0; i < size; ++i, ++ptr) ar(*ptr);
423 }