36#ifndef VIGRA_COUNTING_ITERATOR_HXX
37#define VIGRA_COUNTING_ITERATOR_HXX
45#include "tinyvector.hxx"
51template <
class T,
bool is_
float=false>
52struct CountingIteratorCompare
55 static bool equal(T left, T right, T )
59 static bool not_equal(T left, T right, T )
63 static bool less(T left, T right, T step)
71 static bool less_equal(T left, T right, T step)
77 static bool greater(T left, T right, T step)
83 static bool greater_equal(T left, T right, T step)
91 static std::ptrdiff_t distance(T from, T to, T step)
93 const double diff = (double(to) - double(from)) /
double(step);
95 ? (std::ptrdiff_t)std::ceil(diff)
96 : (std::ptrdiff_t)std::floor(diff);
101struct CountingIteratorCompare<T, true>
103 typedef std::numeric_limits<T> limit;
107 static bool equal(T left, T right, T step)
109 return std::fabs(right-left) <= 0.5*std::fabs(step);
111 static bool not_equal(T left, T right, T step)
113 return std::fabs(right-left) > 0.5*std::fabs(step);
115 static bool less(T left, T right, T step)
118 ? right - left > 0.5*step
119 : right - left < 0.5*step;
121 static bool less_equal(T left, T right, T step)
124 ? left - right < 0.5*step
125 : left - right > 0.5*step;
127 static bool greater(T left, T right, T step)
130 ? left - right > 0.5*step
131 : left - right < 0.5*step;
133 static bool greater_equal(T left, T right, T step)
136 ? right - left < 0.5*step
137 : right - left > 0.5*step;
141 static std::ptrdiff_t distance(T from, T to, T step)
143 const double diff = (double(to) - double(from)) /
double(step);
145 ? (std::ptrdiff_t)std::ceil(diff*(1.0-2.0*limit::epsilon()))
146 : (std::ptrdiff_t)std::floor(diff*(1.0-2.0*limit::epsilon()));
242template<
class T = std::ptrdiff_t>
246 typedef std::random_access_iterator_tag iterator_category;
247 typedef T value_type;
248 typedef std::ptrdiff_t difference_type;
249 typedef T
const* pointer;
263 vigra_precondition(begin <= end,
264 "CountingIterator(): begin must be less or equal to end.");
272 vigra_precondition(step != 0,
273 "CountingIterator(): step must be non-zero.");
274 vigra_precondition((step > 0 && begin <= end) || (step < 0 && begin >= end),
275 "CountingIterator(): sign mismatch between step and (end-begin).");
281 , step_(-other.step_)
295 T end = begin_ + step_*Compare::distance(begin_, end_, step_);
301 return Compare::greater_equal(begin_, end_, step_);
333 return Compare::distance(other.begin_, begin_, step_);
338 return Compare::less(begin_, other.begin_, step_);
343 return Compare::less_equal(begin_, other.begin_, step_);
348 return Compare::greater(begin_, other.begin_, step_);
353 return Compare::greater_equal(begin_, other.begin_, step_);
358 return Compare::equal(begin_, other.begin_, step_);
363 return Compare::not_equal(begin_, other.begin_, step_);
366 T operator[](std::ptrdiff_t n)
const {
367 return begin_ + n*step_;
370 T operator*()
const {
374 T
const * operator->()
const{
380 typedef detail::CountingIteratorCompare<T, std::is_floating_point<T>::value> Compare;
382 T begin_, end_, step_;
386template <
class T1,
class T2,
class T3>
388range(T1 begin, T2 end, T3 step)
393template <
class T1,
class T2>
394inline CountingIterator<T1>
395range(T1 begin, T2 end)
397 return CountingIterator<T1>(begin, end, 1);
401inline CountingIterator<T>
404 return CountingIterator<T>(0, end, 1);
412struct std::iterator_traits<typename
vigra::CountingIterator<T>>
414 typedef typename vigra::CountingIterator<T>::iterator_category iterator_category;
415 typedef typename vigra::CountingIterator<T>::value_type value_type;
416 typedef typename vigra::CountingIterator<T>::difference_type difference_type;
417 typedef typename vigra::CountingIterator<T>::pointer pointer;
418 typedef typename vigra::CountingIterator<T>::reference reference;
Iterator that counts upwards or downwards with a given step size.
Definition counting_iterator.hxx:244