GraphLab: Distributed Graph-Parallel API  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
empty.hpp
1 /**
2  * Copyright (c) 2009 Carnegie Mellon University.
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an "AS
13  * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14  * express or implied. See the License for the specific language
15  * governing permissions and limitations under the License.
16  *
17  * For more about this software visit:
18  *
19  * http://www.graphlab.ml.cmu.edu
20  *
21  */
22 
23 
24 #ifndef GRAPHLAB_UTIL_EMPTY_HPP
25 #define GRAPHLAB_UTIL_EMPTY_HPP
26 #include <vector>
27 #include <algorithm>
28 #include <stdexcept>
29 #include <graphlab/serialization/iarchive.hpp>
30 #include <graphlab/serialization/oarchive.hpp>
31 namespace graphlab {
32 
33 struct empty {
34  void save(oarchive&) const { }
35  void load(iarchive&) { }
36  empty& operator+=(const empty&) { return *this; }
37 };
38 
39 } // namespace graphlab;
40 
41 
42 namespace std {
43 
44 template <>
45 class vector<graphlab::empty, allocator<graphlab::empty> > {
46  public:
47  size_t len;
48  graphlab::empty e;
49 
50  public:
51  struct iterator {
52  typedef int difference_type;
53  typedef graphlab::empty value_type;
54  typedef graphlab::empty* pointer;
55  typedef graphlab::empty& reference;
56  typedef const graphlab::empty& const_reference;
57  typedef random_access_iterator_tag iterator_category;
58 
59  graphlab::empty e;
60  size_t i; const size_t* len;
61  iterator(): i(0),len(NULL) { }
62  iterator(size_t i, const size_t* len): i(i), len(len) { }
63  bool operator==(const iterator& iter) const {
64  return i == iter.i;
65  }
66  bool operator!=(const iterator& iter) const {
67  return !((*this) == iter);
68  }
69  iterator operator++() {
70  i += (i < *len);
71  return *this;
72  }
73  reference operator*() {
74  return e;
75  }
76  const_reference operator*() const {
77  return e;
78  }
79  iterator operator++(int) {
80  iterator old = (*this);
81  i += (i < *len);
82  return old;
83  }
84  iterator operator--() {
85  i -= (i > 0);
86  return *this;
87  }
88  iterator operator--(int) {
89  iterator old = (*this);
90  i -= (i > 0);
91  return old;
92  }
93  iterator operator+=(int n) {
94  i += n;
95  if (n > 0 && i > (*len)) i = (*len); // overflow
96  else if (n < 0 && i > (*len)) i = 0; // underflow
97  return *this;
98  }
99  iterator operator-=(int n) {
100  i += -n;
101  return *this;
102  }
103  iterator operator+(int n) const {
104  iterator tmp = (*this);
105  tmp += n;
106  return tmp;
107  }
108  iterator operator-(int n) const {
109  iterator tmp = (*this);
110  tmp -= n;
111  return tmp;
112  }
113 
114  int operator-(iterator n) const {
115  return i - n.i;
116  }
117 
118  bool operator<(iterator other) const {
119  return i < other.i;
120  }
121  bool operator<=(iterator other) const {
122  return i <= other.i;
123  }
124  bool operator>(iterator other) const {
125  return i > other.i;
126  }
127  bool operator>=(iterator other) const {
128  return i >= other.i;
129  }
130  };
131 
132  typedef iterator const_iterator;
133  typedef iterator reverse_iterator;
134  typedef iterator const_reverse_iterator;
135  typedef graphlab::empty& reference;
136  typedef const graphlab::empty& const_reference;
137  typedef allocator<graphlab::empty> allocator_type;
138 
139  // default constructor
140  explicit vector(const allocator_type& a = allocator_type()):len(0) { }
141  // construct from value
142  explicit vector(size_t n, const graphlab::empty& val = graphlab::empty(),
143  const allocator_type& a = allocator_type()):len(n) { }
144  // construct from iterator
145  template <typename InputIterator>
146  vector(InputIterator first, InputIterator last,
147  const allocator_type& a = allocator_type()): len(std::distance(first, last)) { }
148  // copy constructor
149  vector(const vector<graphlab::empty, allocator_type>& v): len(v.len) { };
150 
151  iterator begin() {
152  return iterator(0, &len);
153  }
154  iterator end() {
155  return iterator(len, &len);
156  }
157  const_iterator begin() const {
158  return const_iterator(0, &len);
159  }
160  const_iterator end() const {
161  return const_iterator(len, &len);
162  }
163 
164  reverse_iterator rbegin() {
165  return iterator(0, &len);
166  }
167  reverse_iterator rend() {
168  return iterator(len, &len);
169  }
170  const_reverse_iterator rbegin() const {
171  return const_iterator(0, &len);
172  }
173  const_reverse_iterator rend() const {
174  return const_iterator(len, &len);
175  }
176 
177  size_t size() const {
178  return len;
179  }
180 
181  size_t capacity() const {
182  return len;
183  }
184 
185  bool empty() const {
186  return len == 0;
187  }
188 
189  void resize(size_t s, const graphlab::empty& e = graphlab::empty()) { len = s; }
190 
191  void reserve(size_t s) {}
192 
193  reference operator[](int i) {
194  return e;
195  }
196 
197  const_reference operator[](int i) const {
198  return e;
199  }
200 
201  reference at(int i) {
202  if (i < 0 || (size_t)i >= len) throw std::out_of_range("vector index out of range");
203  else return e;
204  }
205 
206  const_reference at(int i) const {
207  if (i < 0 || (size_t)i >= len) throw std::out_of_range("vector index out of range");
208  else return e;
209  }
210 
211  template <typename InputIterator>
212  void assign(InputIterator first, InputIterator last) {
213  len = std::distance(first, last);
214  }
215 
216 
217  void assign(size_t n, const graphlab::empty&) {
218  len = n;
219  }
220 
221  void push_back(const graphlab::empty&) {
222  ++len;
223  }
224 
225  void pop_back(const graphlab::empty&) {
226  --len;
227  }
228 
229  void insert(iterator, const graphlab::empty&) {
230  ++len;
231  }
232 
233 
234  void insert(iterator, size_t n, const graphlab::empty&) {
235  len += n;
236  }
237 
238 
239  template <typename InputIterator>
240  void insert(iterator, InputIterator first, InputIterator last) {
241  len += std::distance(first, last);
242  }
243 
244  void erase(iterator) {
245  --len;
246  }
247 
248  void erase(iterator first, iterator last) {
249  len -= (last - first);
250  }
251 
252  void swap(vector<graphlab::empty, allocator_type> &v) {
253  std::swap(len, v.len);
254  }
255 
256  void clear() {
257  len = 0;
258  }
259 
260  allocator_type get_allocator() const {
261  return allocator_type();
262  }
263 };
264 
265 } // namespace std
266 
267 // serialization of the empty vector is a problem since it will
268 // preferentially dispatch to the general vector serialize implementation
269 // instead of the one built into vector<empty>. Using the out of place
270 // save/load will fix this
271 
272 BEGIN_OUT_OF_PLACE_SAVE(arc, std::vector<graphlab::empty>, tval)
273  arc<< tval.len;
274 END_OUT_OF_PLACE_SAVE()
275 
276 BEGIN_OUT_OF_PLACE_LOAD(arc, std::vector<graphlab::empty>, tval)
277  arc >> tval.len;
278 END_OUT_OF_PLACE_LOAD()
279 
280 
281 #endif