Stxxl  1.3.2
mng/adaptor.h
1 /***************************************************************************
2  * include/stxxl/bits/mng/adaptor.h
3  *
4  * Part of the STXXL. See http://stxxl.sourceforge.net
5  *
6  * Copyright (C) 2002-2003 Roman Dementiev <[email protected]>
7  * Copyright (C) 2007 Johannes Singler <[email protected]>
8  * Copyright (C) 2009-2010 Andreas Beckmann <[email protected]>
9  *
10  * Distributed under the Boost Software License, Version 1.0.
11  * (See accompanying file LICENSE_1_0.txt or copy at
12  * http://www.boost.org/LICENSE_1_0.txt)
13  **************************************************************************/
14 
15 #ifndef STXXL_MNG_ADAPTOR_HEADER
16 #define STXXL_MNG_ADAPTOR_HEADER
17 
18 #include <iterator>
19 
20 #include <stxxl/bits/common/types.h>
21 
22 
23 __STXXL_BEGIN_NAMESPACE
24 
28 
29 
30 template <unsigned_type modulo>
31 class blocked_index
32 {
33  unsigned_type pos;
34  unsigned_type block;
35  unsigned_type offset;
36 
38 
39  void set(unsigned_type pos)
40  {
41  this->pos = pos;
42  block = pos / modulo;
43  offset = pos % modulo;
44  }
45 
46 public:
47  blocked_index()
48  {
49  set(0);
50  }
51 
52  blocked_index(unsigned_type pos)
53  {
54  set(pos);
55  }
56 
57  blocked_index(unsigned_type block, unsigned_type offset)
58  {
59  this->block = block;
60  this->offset = offset;
61  pos = block * modulo + offset;
62  }
63 
64  void operator = (unsigned_type pos)
65  {
66  set(pos);
67  }
68 
69  //pre-increment operator
70  blocked_index & operator ++ ()
71  {
72  ++pos;
73  ++offset;
74  if (offset == modulo)
75  {
76  offset = 0;
77  ++block;
78  }
79  return *this;
80  }
81 
82  //post-increment operator
83  blocked_index operator ++ (int)
84  {
85  blocked_index former(*this);
86  operator ++ ();
87  return former;
88  }
89 
90  //pre-increment operator
91  blocked_index & operator -- ()
92  {
93  --pos;
94  if (offset == 0)
95  {
96  offset = modulo;
97  --block;
98  }
99  --offset;
100  return *this;
101  }
102 
103  //post-increment operator
104  blocked_index operator -- (int)
105  {
106  blocked_index former(*this);
107  operator -- ();
108  return former;
109  }
110 
111  blocked_index & operator += (unsigned_type addend)
112  {
113  set(pos + addend);
114  return *this;
115  }
116 
117  blocked_index & operator >>= (unsigned_type shift)
118  {
119  set(pos >> shift);
120  return *this;
121  }
122 
123  operator unsigned_type () const
124  {
125  return pos;
126  }
127 
128  const unsigned_type & get_block() const
129  {
130  return block;
131  }
132 
133  const unsigned_type & get_offset() const
134  {
135  return offset;
136  }
137 };
138 
139 #define STXXL_ADAPTOR_ARITHMETICS(pos) \
140  bool operator == (const _Self & a) const \
141  { \
142  return (a.pos == pos); \
143  } \
144  bool operator != (const _Self & a) const \
145  { \
146  return (a.pos != pos); \
147  } \
148  bool operator < (const _Self & a) const \
149  { \
150  return (pos < a.pos); \
151  } \
152  bool operator > (const _Self & a) const \
153  { \
154  return (pos > a.pos); \
155  } \
156  bool operator <= (const _Self & a) const \
157  { \
158  return (pos <= a.pos); \
159  } \
160  bool operator >= (const _Self & a) const \
161  { \
162  return (pos >= a.pos); \
163  } \
164  _Self operator + (pos_type off) const \
165  { \
166  return _Self(array, pos + off); \
167  } \
168  _Self operator - (pos_type off) const \
169  { \
170  return _Self(array, pos - off); \
171  } \
172  _Self & operator ++ () \
173  { \
174  pos++; \
175  return *this; \
176  } \
177  _Self operator ++ (int) \
178  { \
179  _Self tmp = *this; \
180  pos++; \
181  return tmp; \
182  } \
183  _Self & operator -- () \
184  { \
185  pos--; \
186  return *this; \
187  } \
188  _Self operator -- (int) \
189  { \
190  _Self tmp = *this; \
191  pos--; \
192  return tmp; \
193  } \
194  pos_type operator - (const _Self & a) const \
195  { \
196  return pos - a.pos; \
197  } \
198  _Self & operator -= (pos_type off) \
199  { \
200  pos -= off; \
201  return *this; \
202  } \
203  _Self & operator += (pos_type off) \
204  { \
205  pos += off; \
206  return *this; \
207  }
208 
209 template <class one_dim_array_type, class data_type, class pos_type>
210 struct TwoToOneDimArrayAdaptorBase
211  : public std::iterator<std::random_access_iterator_tag, data_type, unsigned_type>
212 {
213  one_dim_array_type * array;
214  pos_type pos;
215  typedef pos_type _pos_type;
216  typedef TwoToOneDimArrayAdaptorBase<one_dim_array_type,
217  data_type, pos_type> _Self;
218 
219 
220  TwoToOneDimArrayAdaptorBase()
221  { }
222 
223  TwoToOneDimArrayAdaptorBase(one_dim_array_type * a, pos_type p)
224  : array(a), pos(p)
225  { }
226  TwoToOneDimArrayAdaptorBase(const TwoToOneDimArrayAdaptorBase & a)
227  : array(a.array), pos(a.pos)
228  { }
229 
230  STXXL_ADAPTOR_ARITHMETICS(pos)
231 };
232 
233 
235 
236 #define BLOCK_ADAPTOR_OPERATORS(two_to_one_dim_array_adaptor_base) \
237  \
238  template <unsigned _blk_sz, typename _run_type, class __pos_type> \
239  inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & operator ++ ( \
240  two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a) \
241  { \
242  a.pos++; \
243  return a; \
244  } \
245  \
246  template <unsigned _blk_sz, typename _run_type, class __pos_type> \
247  inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> operator ++ ( \
248  two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a, int) \
249  { \
250  two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> tmp = a; \
251  a.pos++; \
252  return tmp; \
253  } \
254  \
255  template <unsigned _blk_sz, typename _run_type, class __pos_type> \
256  inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & operator -- ( \
257  two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a) \
258  { \
259  a.pos--; \
260  return a; \
261  } \
262  \
263  template <unsigned _blk_sz, typename _run_type, class __pos_type> \
264  inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> operator -- ( \
265  two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a, int) \
266  { \
267  two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> tmp = a; \
268  a.pos--; \
269  return tmp; \
270  } \
271  \
272  template <unsigned _blk_sz, typename _run_type, class __pos_type> \
273  inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & operator -= ( \
274  two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a, \
275  typename two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type>::_pos_type off) \
276  { \
277  a.pos -= off; \
278  return a; \
279  } \
280  \
281  template <unsigned _blk_sz, typename _run_type, class __pos_type> \
282  inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & operator += ( \
283  two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a, \
284  typename two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type>::_pos_type off) \
285  { \
286  a.pos += off; \
287  return a; \
288  } \
289  \
290  template <unsigned _blk_sz, typename _run_type, class __pos_type> \
291  inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> operator + ( \
292  const two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a, \
293  typename two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type>::_pos_type off) \
294  { \
295  return two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type>(a.array, a.pos + off); \
296  } \
297  \
298  template <unsigned _blk_sz, typename _run_type, class __pos_type> \
299  inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> operator + ( \
300  typename two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type>::_pos_type off, \
301  const two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a) \
302  { \
303  return two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type>(a.array, a.pos + off); \
304  } \
305  \
306  template <unsigned _blk_sz, typename _run_type, class __pos_type> \
307  inline two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> operator - ( \
308  const two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type> & a, \
309  typename two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type>::_pos_type off) \
310  { \
311  return two_to_one_dim_array_adaptor_base<_blk_sz, _run_type, __pos_type>(a.array, a.pos - off); \
312  }
313 
314 
315 #if 0
316 template <class one_dim_array_type, class data_type,
318  unsigned dim_size, class pos_type = blocked_index<dim_size> >
319 struct TwoToOneDimArrayRowAdaptor :
320  public TwoToOneDimArrayAdaptorBase<one_dim_array_type, data_type, pos_type>
321 {
322  typedef TwoToOneDimArrayRowAdaptor<one_dim_array_type,
323  data_type, dim_size, pos_type> _Self;
324 
325  typedef TwoToOneDimArrayAdaptorBase<one_dim_array_type,
326  data_type, pos_type> _Parent;
327  using _Parent::array;
328  using _Parent::pos;
329 
330  TwoToOneDimArrayRowAdaptor()
331  { }
332  TwoToOneDimArrayRowAdaptor(one_dim_array_type * a, pos_type p)
333  : TwoToOneDimArrayAdaptorBase<one_dim_array_type, data_type, pos_type>(a, p)
334  { }
335  TwoToOneDimArrayRowAdaptor(const TwoToOneDimArrayRowAdaptor & a)
336  : TwoToOneDimArrayAdaptorBase<one_dim_array_type, data_type, pos_type>(a)
337  { }
338 
339  data_type & operator * ()
340  {
341  return array[(pos).get_block()][(pos).get_offset()];
342  }
343 
344  data_type * operator -> () const
345  {
346  return &(array[(pos).get_block()][(pos).get_offset()]);
347  }
348 
349  data_type & operator [] (pos_type n)
350  {
351  n += pos;
352  return array[(n) / dim_size][(n) % dim_size];
353  }
354 
355  const data_type & operator [] (pos_type n) const
356  {
357  n += pos;
358  return array[(n) / dim_size][(n) % dim_size];
359  }
360  STXXL_ADAPTOR_ARITHMETICS(pos)
361 };
362 
363 template <class one_dim_array_type, class data_type,
364  unsigned dim_size, class pos_type = blocked_index<dim_size> >
365 struct TwoToOneDimArrayColumnAdaptor
366  : public TwoToOneDimArrayAdaptorBase<one_dim_array_type, data_type, pos_type>
367 {
368  typedef TwoToOneDimArrayColumnAdaptor<one_dim_array_type,
369  data_type, dim_size, pos_type> _Self;
370 
371  using TwoToOneDimArrayAdaptorBase<one_dim_array_type, data_type, pos_type>::pos;
372  using TwoToOneDimArrayAdaptorBase<one_dim_array_type, data_type, pos_type>::array;
373 
374  TwoToOneDimArrayColumnAdaptor(one_dim_array_type * a, pos_type p)
375  : TwoToOneDimArrayAdaptorBase<one_dim_array_type, data_type, pos_type>(a, p)
376  { }
377  TwoToOneDimArrayColumnAdaptor(const _Self & a)
378  : TwoToOneDimArrayAdaptorBase<one_dim_array_type, data_type, pos_type>(a)
379  { }
380 
381  data_type & operator * ()
382  {
383  return array[(pos).get_offset()][(pos).get_block()];
384  }
385 
386  data_type * operator -> () const
387  {
388  return &(array[(pos).get_offset()][(pos).get_block()]);
389  }
390 
391  const data_type & operator [] (pos_type n) const
392  {
393  n += pos;
394  return array[(n) % dim_size][(n) / dim_size];
395  }
396 
397  data_type & operator [] (pos_type n)
398  {
399  n += pos;
400  return array[(n) % dim_size][(n) / dim_size];
401  }
402  STXXL_ADAPTOR_ARITHMETICS(pos)
403 };
404 #endif
405 
406 
407 template <typename array_type, typename value_type, unsigned_type modulo>
408 class ArrayOfSequencesIterator : public std::iterator<std::random_access_iterator_tag, value_type, unsigned_type>
409 {
410  unsigned_type pos;
411  unsigned_type offset;
412  array_type * arrays;
413  array_type * base;
414  value_type * base_element;
415 
417 
418  void set(unsigned_type pos)
419  {
420  this->pos = pos;
421  offset = pos % modulo;
422  base = arrays + pos / modulo;
423  base_element = base->elem;
424  }
425 
426 public:
427  ArrayOfSequencesIterator()
428  {
429  this->arrays = NULL;
430  set(0);
431  }
432 
433  ArrayOfSequencesIterator(array_type * arrays)
434  {
435  this->arrays = arrays;
436  set(0);
437  }
438 
439  ArrayOfSequencesIterator(array_type * arrays, unsigned_type pos)
440  {
441  this->arrays = arrays;
442  set(pos);
443  }
444 
445  void operator = (unsigned_type pos)
446  {
447  set(pos);
448  }
449 
450  //pre-increment operator
451  ArrayOfSequencesIterator & operator ++ ()
452  {
453  ++pos;
454  ++offset;
455  if (offset == modulo)
456  {
457  offset = 0;
458  ++base;
459  base_element = base->elem;
460  }
461  return *this;
462  }
463 
464  //post-increment operator
465  ArrayOfSequencesIterator operator ++ (int)
466  {
467  ArrayOfSequencesIterator former(*this);
468  operator ++ ();
469  return former;
470  }
471 
472  //pre-increment operator
473  ArrayOfSequencesIterator & operator -- ()
474  {
475  --pos;
476  if (offset == 0)
477  {
478  offset = modulo;
479  --base;
480  base_element = base->elem;
481  }
482  --offset;
483  return *this;
484  }
485 
486  //post-increment operator
487  ArrayOfSequencesIterator operator -- (int)
488  {
489  ArrayOfSequencesIterator former(*this);
490  operator -- ();
491  return former;
492  }
493 
494  ArrayOfSequencesIterator & operator += (unsigned_type addend)
495  {
496  set(pos + addend);
497  return *this;
498  }
499 
500  ArrayOfSequencesIterator & operator -= (unsigned_type addend)
501  {
502  set(pos - addend);
503  return *this;
504  }
505 
506  ArrayOfSequencesIterator operator + (unsigned_type addend) const
507  {
508  return ArrayOfSequencesIterator(arrays, pos + addend);
509  }
510 
511  ArrayOfSequencesIterator operator - (unsigned_type subtrahend) const
512  {
513  return ArrayOfSequencesIterator(arrays, pos - subtrahend);
514  }
515 
516  unsigned_type operator - (const ArrayOfSequencesIterator & subtrahend) const
517  {
518  return pos - subtrahend.pos;
519  }
520 
521  bool operator == (const ArrayOfSequencesIterator & aoai) const
522  {
523  return pos == aoai.pos;
524  }
525 
526  bool operator != (const ArrayOfSequencesIterator & aoai) const
527  {
528  return pos != aoai.pos;
529  }
530 
531  bool operator < (const ArrayOfSequencesIterator & aoai) const
532  {
533  return pos < aoai.pos;
534  }
535 
536  bool operator <= (const ArrayOfSequencesIterator & aoai) const
537  {
538  return pos <= aoai.pos;
539  }
540 
541  bool operator > (const ArrayOfSequencesIterator & aoai) const
542  {
543  return pos > aoai.pos;
544  }
545 
546  bool operator >= (const ArrayOfSequencesIterator & aoai) const
547  {
548  return pos >= aoai.pos;
549  }
550 
551  const value_type & operator * () const
552  {
553  return base_element[offset];
554  }
555 
556  value_type & operator * ()
557  {
558  return base_element[offset];
559  }
560 
561  const value_type & operator -> () const
562  {
563  return &(base_element[offset]);
564  }
565 
566  value_type & operator -> ()
567  {
568  return &(base_element[offset]);
569  }
570 
571  const value_type & operator [] (unsigned_type index) const
572  {
573  return arrays[index / modulo][index % modulo];
574  }
575 
576  value_type & operator [] (unsigned_type index)
577  {
578  return arrays[index / modulo][index % modulo];
579  }
580 };
581 
582 namespace helper
583 {
584  template <typename BlockType, bool can_use_trivial_pointer>
585  class element_iterator_generator
586  { };
587 
588  // default case for blocks with fillers or other data: use ArrayOfSequenceIterator
589  template <typename BlockType>
590  class element_iterator_generator<BlockType, false>
591  {
592  typedef BlockType block_type;
593  typedef typename block_type::value_type value_type;
594 
595  public:
596  typedef ArrayOfSequencesIterator<block_type, value_type, block_type::size> iterator;
597 
598  iterator operator () (block_type * blocks, unsigned_type offset) const
599  {
600  return iterator(blocks, offset);
601  }
602  };
603 
604  // special case for completely filled blocks: use trivial pointers
605  template <typename BlockType>
606  class element_iterator_generator<BlockType, true>
607  {
608  typedef BlockType block_type;
609  typedef typename block_type::value_type value_type;
610 
611  public:
612  typedef value_type * iterator;
613 
614  iterator operator () (block_type * blocks, unsigned_type offset) const
615  {
616  return blocks[0].elem + offset;
617  }
618  };
619 }
620 
621 template <typename BlockType>
622 struct element_iterator_traits
623 {
624  typedef typename helper::element_iterator_generator<BlockType, BlockType::has_only_data>::iterator element_iterator;
625 };
626 
627 template <typename BlockType>
628 inline
629 typename element_iterator_traits<BlockType>::element_iterator
630 make_element_iterator(BlockType * blocks, unsigned_type offset)
631 {
632  helper::element_iterator_generator<BlockType, BlockType::has_only_data> iter_gen;
633  return iter_gen(blocks, offset);
634 }
635 
637 
638 __STXXL_END_NAMESPACE
639 
640 #endif // !STXXL_MNG_ADAPTOR_HEADER
641 // vim: et:ts=4:sw=4