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

Last change on this file since 1293 was 1293, checked in by Peter, 13 years ago

adding missing include

  • 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 1293 2008-05-12 00:04:12Z peter $
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#include <stdexcept>
33
34namespace theplu {
35namespace yat {
36namespace utility {
37
38  // forward declaration
39  template<typename Iter>
40  class StrideIterator;
41
42  /**
43     Specialization for StrideIterator that calls underlying iterator.
44   */
45  template <typename Iter>
46  struct weighted_iterator_traits<StrideIterator<Iter> > {
47    /**
48       StrideIterator is weighted if underlying iterator is weighted.
49    */
50    typedef typename weighted_iterator_traits<Iter>::type type;
51  };
52
53  /**
54     Specialization for StrideIterator using iterator_traits with base()
55   */
56  template <class Iter>
57  struct iterator_traits<StrideIterator<Iter> > {
58    /**
59       \return data that is *iter
60    */
61    double data(StrideIterator<Iter> iter) const 
62    { return iterator_traits<Iter>().data(iter.base()); }
63
64    /**
65       \return 1.0
66    */
67    double weight(StrideIterator<Iter> iter) const 
68    { return iterator_traits<Iter>().weight(iter.base()); }
69
70  };
71
72  /**
73     @brief Adaptor using a stride on underlying iterator
74
75     Works as underlying iterator except that all arithmetic uses the
76     stride, so e.g., ++StrideIterator returns underlying
77     _iterator+stride
78
79  */
80  template<typename Iter>
81  class StrideIterator 
82    : public std::iterator<typename std::iterator_traits<Iter>::iterator_category, 
83                           typename std::iterator_traits<Iter>::value_type, 
84                           typename std::iterator_traits<Iter>::difference_type, 
85                           typename std::iterator_traits<Iter>::pointer, 
86                           typename std::iterator_traits<Iter>::reference>
87  {
88  public:
89    /// type of underlying iterator
90    typedef Iter iterator_type;
91    /// value type
92    typedef typename std::iterator_traits<Iter>::value_type value_type;
93    /// difference type
94    typedef typename std::iterator_traits<Iter>::difference_type difference_type;
95    /// reference
96    typedef typename std::iterator_traits<Iter>::reference reference;
97    /// pointer
98    typedef typename std::iterator_traits<Iter>::pointer pointer;
99    /// weighted_iterator_tag if iterator is weighted
100    typedef typename yat::utility::weighted_iterator_traits<Iter>::type w_type;
101
102    /**
103       \brief Constructor
104    */
105    explicit StrideIterator(Iter p, difference_type stride=1)
106      : iterator_(p), stride_(stride) {}
107
108   
109    /**
110       Conversion from mutable iterator to const iterator. Only works
111       if underlying iterator is a pointer.
112     */
113    // Peter, this is ugly hack to provide iterator to const_iterator
114    // for our gsl_iterators - solution? use Boost:iterator_adaptor
115    operator StrideIterator<const value_type*>()
116    { return StrideIterator<const value_type*>(base(), stride_); }
117
118    /**
119       \return underlying iterator
120     */
121    inline Iter base(void) const { return iterator_; }
122
123    /**
124       \return stride
125     */
126    inline size_t stride(void) const { return stride_; }
127
128    /**
129       \return element
130     */
131    reference operator*(void) const 
132    { return *iterator_; }
133
134    /**
135       \return pointer
136     */
137    pointer operator->() const { return &(operator*()); }
138
139    /**
140       \return element \a n steps forward
141     */
142    reference operator[](difference_type n) const 
143    { 
144      return iterator_[stride_*n];
145    }
146
147    /**
148       \brief pre-increment
149
150       \return reference to *this
151     */
152    StrideIterator& operator++(void) { iterator_+=stride_; return *this; }
153
154    /**
155       \brief post-increment
156
157       \return copy of iterator prior increment
158     */
159    StrideIterator operator++(int) 
160    { StrideIterator tmp(*this); iterator_+=stride_; return tmp;}
161
162    /**
163       \brief iterate \f$ n \f$ steps forward
164
165       \return reference to resulting iterator
166     */
167    StrideIterator& operator+=(int n) { iterator_+=stride_*n; return *this; }
168
169    /**
170       \brief post-decrement
171
172       \return copy of iterator prior decrement
173     */
174    StrideIterator operator--(int) 
175    { StrideIterator tmp(*this); iterator_-=stride_; return tmp;}
176
177    /**
178       \brief pre-decrement
179
180       \return reference to resulting iterator
181     */
182    StrideIterator& operator--(void) { iterator_-=stride_; return *this; }
183
184    /**
185       \brief iterate \f$ n \f$ steps backwards
186
187       \return reference to resulting iterator
188     */
189    StrideIterator& operator-=(int n) { iterator_-=n*stride_; return *this; }
190
191    /**
192       \brief addition operator
193
194       \return copy of resulting iterator
195     */
196    friend StrideIterator operator+(const StrideIterator& lhs,difference_type n) 
197    { StrideIterator tmp(lhs); tmp+=n; return tmp; }
198
199    /**
200       \brief subtraction operator
201
202       \return copy of resulting iterator
203     */
204    friend StrideIterator operator-(const StrideIterator& lhs, 
205                                    difference_type n) 
206    { StrideIterator tmp(lhs); tmp-=n; return tmp; }
207
208    /**
209       \brief difference operator
210
211       \return distance between \a lhs and \a rhs
212     */
213    friend difference_type operator-(const StrideIterator& lhs, 
214                                     const StrideIterator& rhs) 
215    {
216      yat_assert<std::runtime_error>(lhs.stride_==rhs.stride_, 
217        "StrideIterator::operator- different stride in lhs and rhs.");
218      return static_cast<difference_type>( (lhs.iterator_-rhs.iterator_)/
219                                           lhs.stride_);
220    }
221
222   
223    /**
224       \brief Equality operator
225
226       \return True if \a lhs and \a rhs are pointing to same element
227     */
228    friend bool operator==(const StrideIterator& lhs, const StrideIterator& rhs)
229    { return lhs.iterator_==rhs.iterator_; }
230   
231    /**
232       \brief Non-equality operator
233
234       \return False if \a lhs and \a rhs are pointing to same element
235     */
236    friend bool operator!=(const StrideIterator& lhs, const StrideIterator& rhs)
237    { return lhs.iterator_!=rhs.iterator_; }
238   
239    /**
240       \brief Less operator
241     */
242    friend bool operator<(const StrideIterator& lhs, const StrideIterator& rhs)
243    { return lhs.iterator_<rhs.iterator_; }
244   
245    /**
246       \brief Less equal operator
247     */
248    friend bool operator<=(const StrideIterator& lhs, const StrideIterator& rhs)
249    { return lhs.iterator_<=rhs.iterator_; }
250   
251    /**
252       \brief Larger operator
253     */
254    friend bool operator>(const StrideIterator& lhs, const StrideIterator& rhs)
255    { return lhs.iterator_>rhs.iterator_; }
256   
257    /**
258       \brief Larger equal operator
259     */
260    friend bool operator>=(const StrideIterator& lhs, const StrideIterator& rhs)
261    { return lhs.iterator_>=rhs.iterator_; }
262   
263  private:
264    Iter iterator_;
265    size_t stride_;
266
267    // Using compiler generated copy
268    //StrideIterator(const StrideIterator&);
269    //StrideIterator& operator=(const StrideIterator&);
270  };
271
272
273
274
275
276}}} // of namespace utility, yat, and theplu
277
278#endif
Note: See TracBrowser for help on using the repository browser.