TPIE

v1.1rc1-6-g0c97303
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 <boost/static_assert.hpp>
24 
29 
30 namespace tpie {
31 
38 template <typename CT, bool forward, typename RT>
40 private:
41  CT & self() {return *reinterpret_cast<CT*>(this);}
42  template <typename, bool, typename> friend class packed_array_iter_facade;
43 
44 public:
45  const CT & self() const {return *reinterpret_cast<const CT*>(this);}
46 
47  typedef ptrdiff_t difference_type;
48  typedef std::random_access_iterator_tag iterator_category;
49  template <typename TT>
50  inline bool operator==(const TT & o) const {return (self()-o) == 0;}
51  template <typename TT>
52  inline bool operator!=(const TT & o) const {return (self()-o) != 0;}
53  inline CT & operator++() {self().index() += forward?1:-1; return self();}
54  inline CT operator++(int) {CT x=self(); ++self(); return x;}
55  inline CT & operator--() {self().index() += forward?-1:1; return self();}
56  inline CT operator--(int) {CT x=self(); --self(); return x;}
57  inline bool operator<(const CT & o) const {return (self()-o) < 0;}
58  inline bool operator>(const CT & o) const {return (self()-o) > 0;}
59  inline bool operator<=(const CT & o) const {return (self()-o) <= 0;}
60  inline bool operator>=(const CT & o) const {return (self()-o) >= 0;}
61  inline ptrdiff_t operator-(const CT & o) const {return forward ? (self().index() - o.index()) : (o.index() - self().index());}
62  inline CT operator+(difference_type n) const {CT x=self(); return x += n;}
63  inline CT operator-(difference_type n) const {CT x=self(); return x -= n;}
64  inline CT & operator+=(difference_type n) {self().index() += (forward?n:-n); return self();}
65  inline CT & operator-=(difference_type n) {self().index() += (forward?n:-n); return self();}
66  inline RT operator[](difference_type n) {return *(self() + n);}
67 };
68 
69 template <typename CT, bool f, typename RT>
70 CT operator+(ptrdiff_t n, const packed_array_iter_facade<CT, f, RT> & i) {
71  CT tmp(i.self());
72  tmp += n;
73  return tmp;
74 }
75 
86 template <typename T, int B>
87 class packed_array: public linear_memory_base<packed_array<T, B> >{
88 public:
89  typedef size_t storage_type;
90 private:
91  // TODO is this necessary?
92  BOOST_STATIC_ASSERT(sizeof(storage_type) * 8 % B == 0);
93 
97  static inline size_t perword() {
98  return sizeof(storage_type) * 8 / B;
99  }
100 
104  static inline size_t high(size_t index) {
105  return index/perword();
106  }
107 
111  static inline size_t low(size_t index) {
112  return B*(index%perword());
113  }
114 
118  static inline size_t words(size_t m) {
119  return (perword()-1+m)/perword();
120  }
121 
125  static inline storage_type mask() {
126  return (1 << B)-1;
127  }
128 
129  template <bool forward>
130  class const_iter_base;
131 
132  template <bool forward>
133  class iter_base;
134 
140  class iter_return_type {
141  private:
142  iter_return_type(storage_type * e, size_t i): elms(e), index(i) {}
143  storage_type * elms;
144  size_t index;
145  public:
146  template <bool> friend class packed_array::iter_base;
147  template <bool> friend class packed_array::const_iter_base;
148  operator T() const {return static_cast<T>((elms[high(index)] >> low(index))&mask());}
149  inline iter_return_type & operator=(const T b) {
150  storage_type * p = elms+high(index);
151  size_t i = low(index);
152  *p = (*p & ~(mask()<<i)) | ((b & mask()) << i);
153  return *this;
154  }
155  };
156 
162  template <bool forward>
163  class iter_base: public packed_array_iter_facade<iter_base<forward>, forward, iter_return_type> {
164  private:
165  iter_return_type elm;
166 
167  friend class const_iter_base<forward>;
168  friend class packed_array;
169  template <typename, bool, typename> friend class packed_array_iter_facade;
170  iter_base(storage_type * elms, size_t index): elm(elms, index) {};
171 
172  inline size_t & index() {return elm.index;}
173  inline const size_t & index() const {return elm.index;}
174  public:
175  typedef iter_return_type value_type;
176  typedef iter_return_type & reference;
177  typedef iter_return_type * pointer;
178 
179  iter_return_type & operator*() {return elm;}
180  iter_return_type * operator->() {return &elm;}
181  iter_base & operator=(const iter_base & o) {elm.index = o.elm.index; elm.elms=o.elm.elms; return *this;}
182  iter_base(iter_base const &o): elm(o.elm) {};
183  };
184 
185  typedef T vssucks;
191  template <bool forward>
192  class const_iter_base: public packed_array_iter_facade<const_iter_base<forward>, forward, vssucks> {
193  private:
194  const storage_type * elms;
195  size_t idx;
196 
197  friend class packed_array;
198  friend class boost::iterator_core_access;
199  template <typename, bool, typename> friend class packed_array_iter_facade;
200  const_iter_base(const storage_type * e, size_t i): elms(e), idx(i) {}
201 
202  inline size_t & index() {return idx;}
203  inline const size_t & index() const {return idx;}
204  public:
205  typedef vssucks value_type;
206  typedef vssucks reference;
207  typedef vssucks * pointer;
208 
209  const_iter_base & operator=(const const_iter_base & o) {idx = o.idx; elms=o.elms; return *this;}
210  vssucks operator*() const {return static_cast<T>(elms[high(idx)] >> low(idx) & mask());}
211  const_iter_base(const_iter_base const& o): elms(o.elms), idx(o.idx) {}
212  const_iter_base(iter_base<forward> const& o): elms(o.elm.elms), idx(o.elm.index) {}
213  };
214 
215 
221  struct return_type{
222  private:
223  storage_type * p;
224  size_t i;
225  return_type(storage_type * p_, size_t i_): p(p_), i(i_) {}
226  friend class packed_array;
227  public:
228  inline operator T() const {return static_cast<T>((*p >> i) & mask());}
229  inline return_type & operator=(const T b) {
230  *p = (*p & ~(mask()<<i)) | ((static_cast<const storage_type>(b) & mask()) << i);
231  return *this;
232  }
233  inline return_type & operator=(const return_type & t){
234  *this = (T) t;
235  return *this;
236  }
237  };
238 
239  storage_type * m_elements;
240  size_t m_size;
241 public:
245  typedef T value_type;
246 
250  typedef const_iter_base<true> const_iterator;
251 
255  typedef const_iter_base<false> const_reverse_iterator;
256 
260  typedef iter_base<true> iterator;
261 
265  typedef iter_base<false> reverse_iterator;
266 
271  inline static double memory_coefficient(){
272  return B/8.0;
273  }
274 
279  static double memory_overhead() {
280  return (double)sizeof(packed_array)+(double)sizeof(storage_type);
281  }
282 
289  packed_array(size_t s=0): m_elements(0), m_size(0) {resize(s);}
290 
297  packed_array(size_t s, T value): m_elements(0), m_size(0) {resize(s,value);}
298 
303  packed_array(const packed_array & a): m_elements(0), m_size(0) {*this=a;}
304 
309 
318  resize(a.m_size);
319  for(size_t i=0;i<words(m_size);++i)
320  m_elements[i] = a.m_elements[i];
321  return *this;
322  }
323 
331  void resize(size_t s) {
332  if (s == m_size) return;
333  tpie_delete_array(m_elements, words(m_size));
334  m_size = s;
335  m_elements = m_size?tpie_new_array<storage_type>(words(m_size)):0;
336  }
337 
346  void resize(size_t s, T value) {
347  resize(s);
348  storage_type x=0;
349  for (size_t i=0; i < perword(); ++i)
350  x = (x << B) + ((storage_type)value & mask());
351  for (size_t i=0; i < words(m_size); ++i)
352  m_elements[i] = x;
353  }
354 
360  inline size_t size() const {return m_size;}
361 
367  inline bool empty() const {return m_size ==0;}
368 
375  inline T operator[](size_t t)const {
376  assert(t < m_size);
377  return static_cast<T>((m_elements[high(t)] >> low(t))&mask());
378  }
379 
386  inline return_type operator[](size_t t) {
387  assert(t < m_size);
388  return return_type(m_elements+high(t), low(t));
389  }
390 
397  inline iterator find(size_type i) {return iterator(m_elements,i);}
398 
405  inline const_iterator find(size_type i) const {return const_iterator(m_elements,i);}
406 
412  inline iterator begin() {return iterator(m_elements,0);}
413 
419  inline const_iterator begin() const {return const_iterator(m_elements,0);}
420 
426  inline iterator end() {return iterator(m_elements,m_size);}
427 
433  inline const_iterator end() const {return const_iterator(m_elements,m_size);}
434 
435  //We use m_elements -1 as basic for the reverse operators
436  //To make sure that the index of rend is positive
437  inline reverse_iterator rbegin() {return reverse_iterator(m_elements-1, perword()+m_size-1);}
438  inline const_reverse_iterator rbegin() const {return const_reverse_iterator(m_elements-1, perword()+m_size-1);}
439  inline reverse_iterator rend() {return reverse_iterator(m_elements-1, perword()-1);}
440  inline const_reverse_iterator rend() const {return const_reverse_iterator(m_elements-1, perword()-1);}
441 };
442 
443 }
444 #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:405
const_iterator begin() const
Return a const iterator to the beginning of the array.
Definition: packed_array.h:419
iter_base< true > iterator
Iterator over an array.
Definition: packed_array.h:260
const_iter_base< true > const_iterator
Iterator over a const array.
Definition: packed_array.h:250
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:397
void resize(size_t s, T value)
Change the size of the array.
Definition: packed_array.h:346
T value_type
Type of values containd in the array.
Definition: packed_array.h:245
static double memory_overhead()
Return the memory overhead of the structure.
Definition: packed_array.h:279
const_iter_base< false > const_reverse_iterator
Reverse iterator over a const array.
Definition: packed_array.h:255
An array storring elements of type T using B bits to to store a element.
Definition: packed_array.h:87
iterator begin()
Return an iterator to the beginning of the array.
Definition: packed_array.h:412
const_iterator end() const
Return a const iterator to the end of the array.
Definition: packed_array.h:433
~packed_array()
Free up all memory used by the array.
Definition: packed_array.h:308
void resize(size_t s)
Change the size of the array.
Definition: packed_array.h:331
bool empty() const
Check if the array is empty.
Definition: packed_array.h:367
packed_array(size_t s, T value)
Construct array of given size.
Definition: packed_array.h:297
packed_array(const packed_array &a)
Construct a copy of another array.
Definition: packed_array.h:303
static double memory_coefficient()
Return the memory coefficient of the structure.
Definition: packed_array.h:271
packed_array & operator=(const packed_array &a)
Copy elements from another array into this.
Definition: packed_array.h:317
size_t size() const
Return the size of the array.
Definition: packed_array.h:360
return_type operator[](size_t t)
Return a object behaving like a reference to an array entry.
Definition: packed_array.h:386
iterator end()
Return an iterator to the end of the array.
Definition: packed_array.h:426
T operator[](size_t t) const
Return an array entry.
Definition: packed_array.h:375
iter_base< false > reverse_iterator
Reverse iterator over an array.
Definition: packed_array.h:265
packed_array(size_t s=0)
Construct array of given size.
Definition: packed_array.h:289
Base class for the iterators.
Definition: packed_array.h:39
void tpie_delete_array(T *a, size_t size)
Delete an array allocated with tpie_new_array.
Definition: memory.h:398