source: trunk/yat/utility/StrideIterator.h @ 1275

Last change on this file since 1275 was 1275, checked in by Jari Häkkinen, 15 years ago

Updating copyright statements.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.2 KB
Line 
1#ifndef _theplu_yat_utility_stride_iterator_
2#define _theplu_yat_utility_stride_iterator_
3
4// $Id: StrideIterator.h 1275 2008-04-11 06:10:12Z jari $
5
6/*
7  Copyright (C) 2007 Jari Häkkinen, Peter Johansson
8  Copyright (C) 2008 Peter Johansson
9
10  This file is part of the yat library, http://trac.thep.lu.se/yat
11
12  The yat library is free software; you can redistribute it and/or
13  modify it under the terms of the GNU General Public License as
14  published by the Free Software Foundation; either version 2 of the
15  License, or (at your option) any later version.
16
17  The yat library is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  General Public License for more details.
21
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25  02111-1307, USA.
26*/
27
28#include "iterator_traits.h"
29#include "yat_assert.h"
30
31#include <iterator>
32
33namespace theplu {
34namespace yat {
35namespace utility {
36
37  // forward declaration
38  template<typename Iter>
39  class StrideIterator;
40
41  /**
42     Specialization for StrideIterator that calls underlying iterator.
43   */
44  template <typename Iter>
45  struct weighted_iterator_traits<StrideIterator<Iter> > {
46    /**
47       StrideIterator is weighted if underlying iterator is weighted.
48    */
49    typedef typename weighted_iterator_traits<Iter>::type type;
50  };
51
52  /**
53     Specialization for StrideIterator using iterator_traits with base()
54   */
55  template <class Iter>
56  struct iterator_traits<StrideIterator<Iter> > {
57    /**
58       \return data that is *iter
59    */
60    double data(StrideIterator<Iter> iter) const 
61    { return iterator_traits<Iter>().data(iter.base()); }
62
63    /**
64       \return 1.0
65    */
66    double weight(StrideIterator<Iter> iter) const 
67    { return iterator_traits<Iter>().weight(iter.base()); }
68
69  };
70
71  /**
72     @brief Adaptor using a stride on underlying iterator
73
74     Works as underlying iterator except that all arithmetic uses the
75     stride, so e.g., ++StrideIterator returns underlying
76     _iterator+stride
77
78  */
79  template<typename Iter>
80  class StrideIterator 
81    : public std::iterator<typename std::iterator_traits<Iter>::iterator_category, 
82                           typename std::iterator_traits<Iter>::value_type, 
83                           typename std::iterator_traits<Iter>::difference_type, 
84                           typename std::iterator_traits<Iter>::pointer, 
85                           typename std::iterator_traits<Iter>::reference>
86  {
87  public:
88    /// type of underlying iterator
89    typedef Iter iterator_type;
90    /// value type
91    typedef typename std::iterator_traits<Iter>::value_type value_type;
92    /// difference type
93    typedef typename std::iterator_traits<Iter>::difference_type difference_type;
94    /// reference
95    typedef typename std::iterator_traits<Iter>::reference reference;
96    /// pointer
97    typedef typename std::iterator_traits<Iter>::pointer pointer;
98    /// weighted_iterator_tag if iterator is weighted
99    typedef typename yat::utility::weighted_iterator_traits<Iter>::type w_type;
100
101    /**
102       \brief Constructor
103    */
104    explicit StrideIterator(Iter p, difference_type stride=1)
105      : iterator_(p), stride_(stride) {}
106
107   
108    /**
109       Conversion from mutable iterator to const iterator. Only works
110       if underlying iterator is a pointer.
111     */
112    // Peter, this is ugly hack to provide iterator to const_iterator
113    // for our gsl_iterators - solution? use Boost:iterator_adaptor
114    operator StrideIterator<const value_type*>()
115    { return StrideIterator<const value_type*>(base(), stride_); }
116
117    /**
118       \return underlying iterator
119     */
120    inline Iter base(void) const { return iterator_; }
121
122    /**
123       \return stride
124     */
125    inline size_t stride(void) const { return stride_; }
126
127    /**
128       \return element
129     */
130    reference operator*(void) const 
131    { return *iterator_; }
132
133    /**
134       \return pointer
135     */
136    pointer operator->() const { return &(operator*()); }
137
138    /**
139       \return element \a n steps forward
140     */
141    reference operator[](difference_type n) const 
142    { 
143      return iterator_[stride_*n];
144    }
145
146    /**
147       \brief pre-increment
148
149       \return reference to *this
150     */
151    StrideIterator& operator++(void) { iterator_+=stride_; return *this; }
152
153    /**
154       \brief post-increment
155
156       \return copy of iterator prior increment
157     */
158    StrideIterator operator++(int) 
159    { StrideIterator tmp(*this); iterator_+=stride_; return tmp;}
160
161    /**
162       \brief iterate \f$ n \f$ steps forward
163
164       \return reference to resulting iterator
165     */
166    StrideIterator& operator+=(int n) { iterator_+=stride_*n; return *this; }
167
168    /**
169       \brief post-decrement
170
171       \return copy of iterator prior decrement
172     */
173    StrideIterator operator--(int) 
174    { StrideIterator tmp(*this); iterator_-=stride_; return tmp;}
175
176    /**
177       \brief pre-decrement
178
179       \return reference to resulting iterator
180     */
181    StrideIterator& operator--(void) { iterator_-=stride_; return *this; }
182
183    /**
184       \brief iterate \f$ n \f$ steps backwards
185
186       \return reference to resulting iterator
187     */
188    StrideIterator& operator-=(int n) { iterator_-=n*stride_; return *this; }
189
190    /**
191       \brief addition operator
192
193       \return copy of resulting iterator
194     */
195    friend StrideIterator operator+(const StrideIterator& lhs,difference_type n) 
196    { StrideIterator tmp(lhs); tmp+=n; return tmp; }
197
198    /**
199       \brief subtraction operator
200
201       \return copy of resulting iterator
202     */
203    friend StrideIterator operator-(const StrideIterator& lhs, 
204                                    difference_type n) 
205    { StrideIterator tmp(lhs); tmp-=n; return tmp; }
206
207    /**
208       \brief difference operator
209
210       \return distance between \a lhs and \a rhs
211     */
212    friend difference_type operator-(const StrideIterator& lhs, 
213                                     const StrideIterator& rhs) 
214    {
215      yat_assert<std::runtime_error>(lhs.stride_==rhs.stride_, 
216        "StrideIterator::operator- different stride in lhs and rhs.");
217      return static_cast<difference_type>( (lhs.iterator_-rhs.iterator_)/
218                                           lhs.stride_);
219    }
220
221   
222    /**
223       \brief Equality operator
224
225       \return True if \a lhs and \a rhs are pointing to same element
226     */
227    friend bool operator==(const StrideIterator& lhs, const StrideIterator& rhs)
228    { return lhs.iterator_==rhs.iterator_; }
229   
230    /**
231       \brief Non-equality operator
232
233       \return False if \a lhs and \a rhs are pointing to same element
234     */
235    friend bool operator!=(const StrideIterator& lhs, const StrideIterator& rhs)
236    { return lhs.iterator_!=rhs.iterator_; }
237   
238    /**
239       \brief Less operator
240     */
241    friend bool operator<(const StrideIterator& lhs, const StrideIterator& rhs)
242    { return lhs.iterator_<rhs.iterator_; }
243   
244    /**
245       \brief Less equal operator
246     */
247    friend bool operator<=(const StrideIterator& lhs, const StrideIterator& rhs)
248    { return lhs.iterator_<=rhs.iterator_; }
249   
250    /**
251       \brief Larger operator
252     */
253    friend bool operator>(const StrideIterator& lhs, const StrideIterator& rhs)
254    { return lhs.iterator_>rhs.iterator_; }
255   
256    /**
257       \brief Larger equal operator
258     */
259    friend bool operator>=(const StrideIterator& lhs, const StrideIterator& rhs)
260    { return lhs.iterator_>=rhs.iterator_; }
261   
262  private:
263    Iter iterator_;
264    size_t stride_;
265
266    // Using compiler generated copy
267    //StrideIterator(const StrideIterator&);
268    //StrideIterator& operator=(const StrideIterator&);
269  };
270
271
272
273
274
275}}} // of namespace utility, yat, and theplu
276
277#endif
Note: See TracBrowser for help on using the repository browser.