vector.hpp
Go to the documentation of this file.
1 /*!
2  * \brief Implements the dense vector class for the cpu
3  *
4  * \author O. Krause
5  * \date 2016
6  *
7  *
8  * \par Copyright 1995-2015 Shark Development Team
9  *
10  * <BR><HR>
11  * This file is part of Shark.
12  * <http://image.diku.dk/shark/>
13  *
14  * Shark is free software: you can redistribute it and/or modify
15  * it under the terms of the GNU Lesser General Public License as published
16  * by the Free Software Foundation, either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * Shark is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * along with Shark. If not, see <http://www.gnu.org/licenses/>.
26  *
27  */
28 #ifndef REMORA_CPU_VECTOR_HPP
29 #define REMORA_CPU_VECTOR_HPP
30 
31 //INCLUDED BY ../vector.hpp!
32 
33 #include "../detail/vector_proxy_classes.hpp"
34 #include <initializer_list>
35 #include <vector>
36 #include <boost/serialization/vector.hpp>
37 #include <boost/serialization/nvp.hpp>
38 #include <boost/serialization/collection_size_type.hpp>
39 #include <boost/serialization/array.hpp>
40 
41 namespace remora{
42 template<class T>
43 class vector<T,cpu_tag>: public vector_container<vector<T, cpu_tag>, cpu_tag > {
44 
45  typedef vector<T> self_type;
46  typedef std::vector<typename std::conditional<std::is_same<T,bool>::value,char,T>::type > array_type;
47 public:
48  typedef typename array_type::value_type value_type;
49  typedef typename array_type::const_reference const_reference;
50  typedef typename array_type::reference reference;
51  typedef typename array_type::size_type size_type;
52 
53  typedef vector_reference<self_type const> const_closure_type;
54  typedef vector_reference<self_type> closure_type;
55  typedef dense_vector_storage<value_type, continuous_dense_tag> storage_type;
56  typedef dense_vector_storage<value_type const, continuous_dense_tag> const_storage_type;
57  typedef elementwise<dense_tag> evaluation_category;
58 
59  // Construction and destruction
60 
61  /// \brief Constructor of a vector
62  /// By default it is empty, i.e. \c size()==0.
63  vector() = default;
64 
65  /// \brief Constructor of a vector with a predefined size
66  /// By default, its elements are initialized to 0.
67  /// \param size initial size of the vector
68  explicit vector(size_type size):m_storage(size) {}
69 
70  /// \brief Constructor of a vector with a predefined size and a unique initial value
71  /// \param size of the vector
72  /// \param init value to assign to each element of the vector
73  vector(size_type size, const value_type& init):m_storage(size, init) {}
74 
75  /// \brief Copy-constructor of a vector
76  /// \param v is the vector to be duplicated
77  vector(vector const& v) = default;
78 
79  /// \brief Move-constructor of a vector
80  /// \param v is the vector to be moved
81  //~ vector(vector && v) = default; //vc++ can not default this. true story
82  vector(vector && v): m_storage(std::move(v.m_storage)){}
83 
84  vector(std::initializer_list<T> list) : m_storage(list.begin(),list.end()){}
85 
86  /// \brief Constructs the vector from a predefined range
87  template<class Iter>
88  vector(Iter begin, Iter end):m_storage(begin,end){}
89 
90  /// \brief Copy-constructor of a vector from a vector_expression
91  /// \param e the vector_expression whose values will be duplicated into the vector
92  template<class E>
93  vector(vector_expression<E, cpu_tag> const& e):m_storage(e().size()) {
94  assign(*this, e);
95  }
96 
97  // -------------------
98  // Assignment operators
99  // -------------------
100 
101  /// \brief Assign a full vector (\e RHS-vector) to the current vector (\e LHS-vector)
102  /// Assign a full vector (\e RHS-vector) to the current vector (\e LHS-vector). This method does not create any temporary.
103  /// \param v is the source vector container
104  /// \return a reference to a vector (i.e. the destination vector)
105  vector& operator = (vector const& v) = default;
106 
107  /// \brief Move-Assign a full vector (\e RHS-vector) to the current vector (\e LHS-vector)
108  /// \param v is the source vector container
109  /// \return a reference to a vector (i.e. the destination vector)
110  //~ vector& operator = (vector && v) = default; //vc++ can not default this. true story
111  vector& operator = (vector && v){
112  m_storage = std::move(v.m_storage);
113  return *this;
114  }
115 
116  /// \brief Assign a full vector (\e RHS-vector) to the current vector (\e LHS-vector)
117  /// Assign a full vector (\e RHS-vector) to the current vector (\e LHS-vector). This method does not create any temporary.
118  /// \param v is the source vector container
119  /// \return a reference to a vector (i.e. the destination vector)
120  template<class C> // Container assignment without temporary
121  vector& operator = (vector_container<C, cpu_tag> const& v) {
122  resize(v().size());
123  return assign(*this, v);
124  }
125 
126  /// \brief Assign the result of a vector_expression to the vector
127  /// Assign the result of a vector_expression to the vector.
128  /// \param e is a const reference to the vector_expression
129  /// \return a reference to the resulting vector
130  template<class E>
131  vector& operator = (vector_expression<E, cpu_tag> const& e) {
132  self_type temporary(e);
133  swap(*this,temporary);
134  return *this;
135  }
136 
137  // ---------
138  // Storage interface
139  // ---------
140 
141  /// \brief Return the size of the vector.
142  size_type size() const {
143  return m_storage.size();
144  }
145 
146  ///\brief Returns the underlying storage structure for low level access
147  storage_type raw_storage(){
148  return {m_storage.data(),1};
149  }
150 
151  ///\brief Returns the underlying storage structure for low level access
152  const_storage_type raw_storage() const{
153  return {m_storage.data(),1};
154  }
155  typename device_traits<cpu_tag>::queue_type& queue(){
156  return device_traits<cpu_tag>::default_queue();
157  }
158 
159  // ---------
160  // High level interface
161  // ---------
162 
163  /// \brief Return the maximum size of the data container.
164  /// Return the upper bound (maximum size) on the data container. Depending on the container, it can be bigger than the current size of the vector.
165  size_type max_size() const {
166  return m_storage.max_size();
167  }
168 
169  /// \brief Return true if the vector is empty (\c size==0)
170  /// \return \c true if empty, \c false otherwise
171  bool empty() const {
172  return m_storage.empty();
173  }
174 
175  /// \brief Resize the vector
176  /// \param size new size of the vector
177  void resize(size_type size) {
178  m_storage.resize(size);
179  }
180 
181  // --------------
182  // Element access
183  // --------------
184 
185  /// \brief Return a const reference to the element \f$i\f$
186  /// Return a const reference to the element \f$i\f$. With some compilers, this notation will be faster than \c operator[]
187  /// \param i index of the element
188  const_reference operator()(size_type i) const {
189  REMORA_RANGE_CHECK(i < size());
190  return m_storage[i];
191  }
192 
193  /// \brief Return a reference to the element \f$i\f$
194  /// Return a reference to the element \f$i\f$. With some compilers, this notation will be faster than \c operator[]
195  /// \param i index of the element
196  reference operator()(size_type i) {
197  REMORA_RANGE_CHECK(i < size());
198  return m_storage[i];
199  }
200 
201  /// \brief Return a const reference to the element \f$i\f$
202  /// \param i index of the element
203  const_reference operator [](size_type i) const {
204  REMORA_RANGE_CHECK(i < size());
205  return m_storage[i];
206  }
207 
208  /// \brief Return a reference to the element \f$i\f$
209  /// \param i index of the element
210  reference operator [](size_type i) {
211  REMORA_RANGE_CHECK(i < size());
212  return m_storage[i];
213  }
214 
215  ///\brief Returns the first element of the vector
216  reference front(){
217  return m_storage[0];
218  }
219  ///\brief Returns the first element of the vector
220  const_reference front()const{
221  return m_storage[0];
222  }
223  ///\brief Returns the last element of the vector
224  reference back(){
225  return m_storage[size()-1];
226  }
227  ///\brief Returns the last element of the vector
228  const_reference back()const{
229  return m_storage[size()-1];
230  }
231 
232  ///\brief resizes the vector by appending a new element to the end. this invalidates storage
233  void push_back(value_type const& element){
234  m_storage.push_back(element);
235  }
236 
237  /// \brief Clear the vector, i.e. set all values to the \c zero value.
238  void clear() {
239  std::fill(m_storage.begin(), m_storage.end(), value_type/*zero*/());
240  }
241 
242  // Iterator types
243  typedef iterators::dense_storage_iterator<value_type> iterator;
244  typedef iterators::dense_storage_iterator<value_type const> const_iterator;
245 
246  /// \brief return an iterator on the first element of the vector
247  const_iterator cbegin() const {
248  return const_iterator(m_storage.data(),0);
249  }
250 
251  /// \brief return an iterator after the last element of the vector
252  const_iterator cend() const {
253  return const_iterator(m_storage.data()+size(),size());
254  }
255 
256  /// \brief return an iterator on the first element of the vector
257  const_iterator begin() const {
258  return cbegin();
259  }
260 
261  /// \brief return an iterator after the last element of the vector
262  const_iterator end() const {
263  return cend();
264  }
265 
266  /// \brief Return an iterator on the first element of the vector
267  iterator begin(){
268  return iterator(m_storage.data(),0);
269  }
270 
271  /// \brief Return an iterator at the end of the vector
272  iterator end(){
273  return iterator(m_storage.data()+size(),size());
274  }
275 
276  /////////////////sparse interface///////////////////////////////
277  iterator set_element(iterator pos, size_type index, value_type value) {
278  REMORA_SIZE_CHECK(pos.index() == index);
279  (*this)(index) = value;
280 
281  return pos;
282  }
283 
284  iterator clear_element(iterator pos) {
285  REMORA_SIZE_CHECK(pos != end());
286  v(pos.index()) = value_type();
287 
288  //return new iterator to the next element
289  return pos+1;
290  }
291 
292  iterator clear_range(iterator start, iterator end) {
293  REMORA_RANGE_CHECK(start <= end);
294  std::fill(start,end,value_type());
295  return end;
296  }
297 
298  void reserve(size_type) {}
299 
300  /// \brief Swap the content of two vectors
301  /// \param v1 is the first vector. It takes values from v2
302  /// \param v2 is the second vector It takes values from v1
303  friend void swap(vector& v1, vector& v2) {
304  v1.m_storage.swap(v2.m_storage);
305  }
306  // -------------
307  // Serialization
308  // -------------
309 
310  /// Serialize a vector into and archive as defined in Boost
311  /// \param ar Archive object. Can be a flat file, an XML file or any other stream
312  /// \param file_version Optional file version (not yet used)
313  template<class Archive>
314  void serialize(Archive &ar, const unsigned int file_version) {
315  boost::serialization::collection_size_type count(size());
316  ar & count;
317  if(!Archive::is_saving::value){
318  resize(count);
319  }
320  if (!empty())
321  ar & boost::serialization::make_array(m_storage.data(),size());
322  (void) file_version;//prevent warning
323  }
324 
325 private:
326  array_type m_storage;
327 };
328 
329 }
330 
331 #endif