TPIE

2362a60
packed_array.h
Go to the documentation of this file.
1 // -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*-
2 // vi:set ts=4 sts=4 sw=4 noet :
3 // Copyright 2008, The TPIE development team
4 //
5 // This file is part of TPIE.
6 //
7 // TPIE is free software: you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License as published by the
9 // Free Software Foundation, either version 3 of the License, or (at your
10 // option) any later version.
11 //
12 // TPIE is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 // License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with TPIE. If not, see <http://www.gnu.org/licenses/>
19 #ifndef __TPIE_PACKED_ARRAY_H__
20 #define __TPIE_PACKED_ARRAY_H__
21 
22 #include <tpie/config.h>
23 #include <tpie/util.h>
24 #include <iterator>
25 #include <cassert>
26 
31 
32 namespace tpie {
33 
40 template <typename CT, bool forward, typename RT>
42 private:
43  CT & self() {return *reinterpret_cast<CT*>(this);}
44  template <typename, bool, typename> friend class packed_array_iter_facade;
45 
46 public:
47  const CT & self() const {return *reinterpret_cast<const CT*>(this);}
48 
49  typedef ptrdiff_t difference_type;
50  typedef std::random_access_iterator_tag iterator_category;
51  template <typename TT>
52  bool operator==(const TT & o) const {return (self()-o) == 0;}
53  template <typename TT>
54  bool operator!=(const TT & o) const {return (self()-o) != 0;}
55  CT & operator++() {self().index() += forward?1:-1; return self();}
56  CT operator++(int) {CT x=self(); ++self(); return x;}
57  CT & operator--() {self().index() += forward?-1:1; return self();}
58  CT operator--(int) {CT x=self(); --self(); return x;}
59  bool operator<(const CT & o) const {return (self()-o) < 0;}
60  bool operator>(const CT & o) const {return (self()-o) > 0;}
61  bool operator<=(const CT & o) const {return (self()-o) <= 0;}
62  bool operator>=(const CT & o) const {return (self()-o) >= 0;}
63  ptrdiff_t operator-(const CT & o) const {return forward ? (self().index() - o.index()) : (o.index() - self().index());}
64  CT operator+(difference_type n) const {CT x=self(); return x += n;}
65  CT operator-(difference_type n) const {CT x=self(); return x -= n;}
66  CT & operator+=(difference_type n) {self().index() += (forward?n:-n); return self();}
67  CT & operator-=(difference_type n) {self().index() += (forward?n:-n); return self();}
68  RT operator[](difference_type n) {return *(self() + n);}
69 };
70 
71 template <typename CT, bool f, typename RT>
72 CT operator+(ptrdiff_t n, const packed_array_iter_facade<CT, f, RT> & i) {
73  CT tmp(i.self());
74  tmp += n;
75  return tmp;
76 }
77 
88 template <typename T, int B>
89 class packed_array: public linear_memory_base<packed_array<T, B> >{
90 public:
91  typedef size_t storage_type;
92 private:
93  // TODO is this necessary?
94  static_assert(sizeof(storage_type) * 8 % B == 0, "Bad storrage");
95 
99  static size_t perword() {
100  return sizeof(storage_type) * 8 / B;
101  }
102 
106  static size_t high(size_t index) {
107  return index/perword();
108  }
109 
113  static size_t low(size_t index) {
114  return B*(index%perword());
115  }
116 
120  static size_t words(size_t m) {
121  return (perword()-1+m)/perword();
122  }
123 
127  static storage_type mask() {
128  return (1 << B)-1;
129  }
130 
131  template <bool forward>
132  class const_iter_base;
133 
134  template <bool forward>
135  class iter_base;
136 
142  class iter_return_type {
143  private:
144  iter_return_type(storage_type * e, size_t i): elms(e), index(i) {}
145  storage_type * elms;
146  size_t index;
147  public:
148  template <typename, int> friend class packed_array;
149  operator T() const {return static_cast<T>((elms[high(index)] >> low(index))&mask());}
150  iter_return_type & operator=(const T b) {
151  storage_type * p = elms+high(index);
152  size_t i = low(index);
153  *p = (*p & ~(mask()<<i)) | ((b & mask()) << i);
154  return *this;
155  }
156  };
157 
163  template <bool forward>
164  class iter_base: public packed_array_iter_facade<iter_base<forward>, forward, iter_return_type> {
165  private:
166  iter_return_type elm;
167 
168  friend class const_iter_base<forward>;
169  friend class packed_array;
170  template <typename, bool, typename> friend class packed_array_iter_facade;
171  iter_base(storage_type * elms, size_t index): elm(elms, index) {};
172 
173  size_t & index() {return elm.index;}
174  const size_t & index() const {return elm.index;}
175  public:
176  typedef iter_return_type value_type;
177  typedef iter_return_type & reference;
178  typedef iter_return_type * pointer;
179 
180  iter_return_type & operator*() {return elm;}
181  iter_return_type * operator->() {return &elm;}
182  iter_base & operator=(const iter_base & o) {elm.index = o.elm.index; elm.elms=o.elm.elms; return *this;}
183  iter_base(iter_base const &o): elm(o.elm) {};
184  };
185 
186  typedef T vssucks;
192  template <bool forward>
193  class const_iter_base: public packed_array_iter_facade<const_iter_base<forward>, forward, vssucks> {
194  private:
195  const storage_type * elms;
196  size_t idx;
197 
198  friend class packed_array;
199  friend class boost::iterator_core_access;
200  template <typename, bool, typename> friend class packed_array_iter_facade;
201  const_iter_base(const storage_type * e, size_t i): elms(e), idx(i) {}
202 
203  size_t & index() {return idx;}
204  const size_t & index() const {return idx;}
205  public:
206  typedef vssucks value_type;
207  typedef vssucks reference;
208  typedef vssucks * pointer;
209 
210  const_iter_base & operator=(const const_iter_base & o) {idx = o.idx; elms=o.elms; return *this;}
211  vssucks operator*() const {return static_cast<T>(elms[high(idx)] >> low(idx) & mask());}
212  const_iter_base(const_iter_base const& o): elms(o.elms), idx(o.idx) {}
213  const_iter_base(iter_base<forward> const& o): elms(o.elm.elms), idx(o.elm.index) {}
214  };
215 
216 
222  struct return_type{
223  private:
224  storage_type * p;
225  size_t i;
226  return_type(storage_type * p_, size_t i_): p(p_), i(i_) {}
227  friend class packed_array;
228  public:
229  operator T() const {return static_cast<T>((*p >> i) & mask());}
230  return_type & operator=(const T b) {
231  *p = (*p & ~(mask()<<i)) | ((static_cast<const storage_type>(b) & mask()) << i);
232  return *this;
233  }
234  return_type & operator=(const return_type & t){
235  *this = (T) t;
236  return *this;
237  }
238  };
239 
240  storage_type * m_elements;
241  size_t m_size;
242 public:
246  typedef T value_type;
247 
251  typedef const_iter_base<true> const_iterator;
252 
256  typedef const_iter_base<false> const_reverse_iterator;
257 
261  typedef iter_base<true> iterator;
262 
266  typedef iter_base<false> reverse_iterator;
267 
272  static double memory_coefficient(){
273  return B/8.0;
274  }
275 
280  static double memory_overhead() {
281  return (double)sizeof(packed_array)+(double)sizeof(storage_type);
282  }
283 
290  packed_array(size_t s=0): m_elements(nullptr), m_size(0) {resize(s);}
291 
298  packed_array(size_t s, T value): m_elements(nullptr), m_size(0) {resize(s,value);}
299 
304  packed_array(const packed_array & a): m_elements(nullptr), m_size(0) {*this=a;}
305 
310  packed_array(packed_array && a): m_elements(a.m_elements), m_size(a.m_size) {
311  a.m_elements = nullptr;
312  a.m_size = 0;
313  }
314 
319 
328  resize(a.m_size);
329  for(size_t i=0;i<words(m_size);++i)
330  m_elements[i] = a.m_elements[i];
331  return *this;
332  }
333 
339  resize(0);
340  std::swap(m_elements, a.m_elements);
341  std::swap(m_size, a.m_size);
342  return *this;
343  }
344 
345 
353  void resize(size_t s) {
354  if (s == m_size) return;
355  tpie_delete_array(m_elements, words(m_size));
356  m_size = s;
357  m_elements = m_size?tpie_new_array<storage_type>(words(m_size)):nullptr;
358  }
359 
365  void fill(T value) {
366  storage_type x=0;
367  for (size_t i=0; i < perword(); ++i)
368  x = (x << B) + ((storage_type)value & mask());
369  for (size_t i=0; i < words(m_size); ++i)
370  m_elements[i] = x;
371  }
372 
373 
382  void resize(size_t s, T value) {
383  resize(s);
384  fill(value);
385  }
386 
392  size_t size() const {return m_size;}
393 
399  bool empty() const {return m_size ==0;}
400 
407  T operator[](size_t t)const {
408  assert(t < m_size);
409  return static_cast<T>((m_elements[high(t)] >> low(t))&mask());
410  }
411 
418  return_type operator[](size_t t) {
419  assert(t < m_size);
420  return return_type(m_elements+high(t), low(t));
421  }
422 
429  iterator find(size_type i) {return iterator(m_elements,i);}
430 
437  const_iterator find(size_type i) const {return const_iterator(m_elements,i);}
438 
444  iterator begin() {return iterator(m_elements,0);}
445 
451  const_iterator begin() const {return const_iterator(m_elements,0);}
452 
458  iterator end() {return iterator(m_elements,m_size);}
459 
465  const_iterator end() const {return const_iterator(m_elements,m_size);}
466 
467  //We use m_elements -1 as basic for the reverse operators
468  //To make sure that the index of rend is positive
469  reverse_iterator rbegin() {return reverse_iterator(m_elements-1, perword()+m_size-1);}
470  const_reverse_iterator rbegin() const {return const_reverse_iterator(m_elements-1, perword()+m_size-1);}
471  reverse_iterator rend() {return reverse_iterator(m_elements-1, perword()-1);}
472  const_reverse_iterator rend() const {return const_reverse_iterator(m_elements-1, perword()-1);}
473 
477  void swap(packed_array & o) {
478  std::swap(m_elements, o.m_elements);
479  std::swap(m_size, o.m_size);
480  }
481 };
482 
483 } //namespace tpie
484 
485 namespace std {
486 template <typename T, int B>
488  a.swap(b);
489 }
490 } //namespace std
491 #endif //__TPIE_PACKED_ARRAY_H__
const_iterator find(size_type i) const
Return a const iterator to the i'th element of the array.
Definition: packed_array.h:437
const_iterator begin() const
Return a const iterator to the beginning of the array.
Definition: packed_array.h:451
iter_base< true > iterator
Iterator over an array.
Definition: packed_array.h:261
const_iter_base< true > const_iterator
Iterator over a const array.
Definition: packed_array.h:251
Base class of data structures with linear memory usage.
Definition: util.h:73
iterator find(size_type i)
Return an iterator to the i'th element of the array.
Definition: packed_array.h:429
void resize(size_t s, T value)
Change the size of the array.
Definition: packed_array.h:382
T value_type
Type of values containd in the array.
Definition: packed_array.h:246
static double memory_overhead()
Return the memory overhead of the structure.
Definition: packed_array.h:280
const_iter_base< false > const_reverse_iterator
Reverse iterator over a const array.
Definition: packed_array.h:256
An array storring elements of type T using B bits to to store a element.
Definition: packed_array.h:89
iterator begin()
Return an iterator to the beginning of the array.
Definition: packed_array.h:444
const_iterator end() const
Return a const iterator to the end of the array.
Definition: packed_array.h:465
~packed_array()
Free up all memory used by the array.
Definition: packed_array.h:318
void resize(size_t s)
Change the size of the array.
Definition: packed_array.h:353
void swap(packed_array &o)
Swap two arrays.
Definition: packed_array.h:477
bool empty() const
Check if the array is empty.
Definition: packed_array.h:399
void fill(T value)
Fill the entier array with the given value.
Definition: packed_array.h:365
packed_array(size_t s, T value)
Construct array of given size.
Definition: packed_array.h:298
packed_array(const packed_array &a)
Construct a copy of another array.
Definition: packed_array.h:304
static double memory_coefficient()
Return the memory coefficient of the structure.
Definition: packed_array.h:272
Miscellaneous utility functions.
packed_array & operator=(const packed_array &a)
Copy elements from another array into this.
Definition: packed_array.h:327
size_t size() const
Return the size of the array.
Definition: packed_array.h:392
return_type operator[](size_t t)
Return a object behaving like a reference to an array entry.
Definition: packed_array.h:418
packed_array & operator=(packed_array &&a)
Move another array.
Definition: packed_array.h:338
iterator end()
Return an iterator to the end of the array.
Definition: packed_array.h:458
T operator[](size_t t) const
Return an array entry.
Definition: packed_array.h:407
iter_base< false > reverse_iterator
Reverse iterator over an array.
Definition: packed_array.h:266
packed_array(size_t s=0)
Construct array of given size.
Definition: packed_array.h:290
Base class for the iterators.
Definition: packed_array.h:41
packed_array(packed_array &&a)
Move another aray into me.
Definition: packed_array.h:310
void tpie_delete_array(T *a, size_t size)
Delete an array allocated with tpie_new_array.
Definition: memory.h:319