Commit c0d7303e authored by Edwin Carlinet's avatar Edwin Carlinet
Browse files

Fix ndimage to use new style iterators.

*  mln/core/concept/image.hpp,
*  mln/core/concept/object.hpp,
*  mln/core/domain/box.hpp,
*  mln/core/domain/box_iter.hpp,
*  mln/core/image/internal/nested_loop_iterator.hpp,
*  mln/core/image/ndimage.hpp,
*  mln/core/image/ndimage_iter.hpp,
*  mln/core/image/ndimage_pixel.hpp,
*  mln/core/image/ndimage_pixel_iterator.hpp,
*  mln/core/image_base.hpp,
*  mln/core/iterator/iterator_base.hpp,
*  tests/bench_iterator.cpp: New style iterator.
parent a5667890
......@@ -97,28 +97,28 @@ namespace mln {
(void) ptr3;
(void) ptr4;
typedef typename boost::range_iterator<value_range>::type value_iterator;
typedef typename boost::range_iterator<const_value_range>::type const_value_iterator;
typedef typename boost::range_iterator<pixel_range>::type pixel_iterator;
typedef typename boost::range_iterator<const_pixel_range>::type const_pixel_iterator;
typedef typename value_range::iterator value_iterator;
typedef typename const_value_range::iterator const_value_iterator;
typedef typename pixel_range::iterator pixel_iterator;
typedef typename const_pixel_range::iterator const_pixel_iterator;
check(std::is_convertible<typename std::iterator_traits<value_iterator>::value_type, value_type> ());
check(std::is_convertible<typename value_iterator::value_type, value_type> ());
// "Iterator's value type is expected to be the image value type.");
check(std::is_same<typename std::iterator_traits<value_iterator>::reference, reference> ());
check(std::is_same<typename value_iterator::reference, reference> ());
// "Iterator's reference is expected to be the image reference");
check(std::is_convertible<typename std::iterator_traits<const_value_iterator>::value_type, value_type> ());
check(std::is_convertible<typename const_value_iterator::value_type, value_type> ());
// "Iterator's value type is expected to be the image value type");
check(std::is_same<typename std::iterator_traits<const_value_iterator>::reference, const_reference> ());
check(std::is_same<typename const_value_iterator::reference, const_reference> ());
// "Iterator's reference type is expected to be the image const reference");
//check(std::is_const<typename std::remove_reference<const_reference>::type > ());
check(std::is_convertible<typename std::iterator_traits<pixel_iterator>::reference, pixel_type> ());
check(std::is_same<typename std::iterator_traits<pixel_iterator>::value_type, pixel_type> ());
check(std::is_convertible<typename pixel_iterator::reference, pixel_type> ());
check(std::is_same<typename pixel_iterator::value_type, pixel_type> ());
// "Pixel Iterator's value type is expected to be the image pixel type");
check(std::is_convertible<typename std::iterator_traits<const_pixel_iterator>::reference, const_pixel_type> ());
check(std::is_same<typename std::iterator_traits<const_pixel_iterator>::value_type, const_pixel_type> ());
check(std::is_convertible<typename const_pixel_iterator::reference, const_pixel_type> ());
check(std::is_same<typename const_pixel_iterator::value_type, const_pixel_type> ());
// "Pixel Iterator's value type is expected to be the image const pixel type");
check(std::is_same<typename pixel_type::image_type, I> ());
......
......@@ -61,6 +61,7 @@ namespace mln {
template <typename E>
struct Object
{
typedef E exact_type;
protected:
Object (const Object&) = default;
......@@ -78,6 +79,18 @@ namespace mln {
Object_ () = default;
};
template <typename E>
struct exact_type
{
typedef typename E::exact_type type;
};
template <typename E>
struct exact_type<const E>
{
typedef const typename E::exact_type type;
};
} // end of namespace mln
......
......@@ -2,7 +2,8 @@
# define MLN_BOX_HH
# include <mln/core/point.hpp>
# include <mln/core/iterator/fast_reverse_iterator.hpp>
# include <mln/core/image/internal/nested_loop_iterator.hpp>
//# include <mln/core/iterator/fast_reverse_iterator.hpp>
# include <mln/core/domain/box_iter.hpp>
namespace mln
......@@ -19,10 +20,17 @@ namespace mln
{
typedef point<T, dim> point_type;
typedef box_iter<T, dim> iterator;
typedef iterator const_iterator;
typedef mln::fast_reverse_iterator<iterator> reverse_iterator;
typedef reverse_iterator const_reverse_iterator;
typedef internal::nested_loop_iterator<
internal::domain_point_visitor_forward< point<T, dim> >,
internal::no_op_value_visitor,
internal::point_structure<T, dim>,
internal::deref_return_point_policy> iterator;
typedef internal::nested_loop_iterator<
internal::domain_point_visitor_backward< point<T, dim> >,
internal::no_op_value_visitor,
internal::point_structure<T, dim>,
internal::deref_return_point_policy> reverse_iterator;
bool has(const point_type& p) const
{
......@@ -34,36 +42,19 @@ namespace mln
return pmax - pmin;
}
iterator begin() const
{
//return iterator(*this, pmin);
return iterator( internal::point_structure<T, dim> (pmin),
internal::make_point_visitor(pmin, pmax),
internal::no_op_value_visitor ());
}
iterator end() const
{
internal::point_structure<T, dim> ps(pmin);
ps.point_[0] = pmax[0];
return iterator( ps, internal::make_point_visitor(pmin, pmax),
internal::no_op_value_visitor ());
//return iterator(*this, pend );
}
reverse_iterator rbegin() const
iterator iter() const
{
//point_type pend = pmax - (short)1;
return reverse_iterator(end());
return iterator( internal::point_structure<T, dim> (),
internal::make_point_visitor_forward(pmin, pmax),
internal::no_op_value_visitor ());
}
reverse_iterator rend() const
reverse_iterator riter() const
{
//point_type pbeg = pmax - (short)1;
//pbeg[0] = pmin[0] - 1;
return reverse_iterator(begin());
return iterator( internal::point_structure<T, dim> (),
internal::make_point_visitor_backward(pmin, pmax),
internal::no_op_value_visitor ());
}
......
......@@ -18,15 +18,17 @@ namespace mln
{
typedef mln::point<T, dim> point_type;
point_structure();
point_structure() {}
point_structure(const mln::point<T, dim>& p) : point_ (p) {}
const mln::point<T, dim>& point() const { return point_; }
mln::point<T, dim>& get_point() { return point_; }
void get_value() { }
mln::point<T, dim>& get_point() { return point_; }
const mln::point<T, dim>& get_point() const { return point_; }
void get_value() const { }
bool equal(const point_structure& other) const { return point_ == other.point_; }
mln::point<T, dim> point_;
......@@ -34,184 +36,6 @@ namespace mln
}
template <typename T, unsigned dim>
using box_iter = internal::nested_loop_iterator<
internal::domain_point_visitor< point<T, dim> >,
internal::no_op_value_visitor,
internal::point_structure<T, dim>,
internal::deref_return_point_policy>;
/*
template <typename T, unsigned dim>
struct box_iter :
public boost::iterator_facade< box_iter<T, dim>, const typename box<T, dim>::point_type,
boost::bidirectional_traversal_tag, const typename box<T, dim>::point_type&>
{
typedef typename box<T, dim>::point_type point_type;
box_iter() {}
// box_iter(const box_rev_iter<T, dim>& it) :
// box_ (it.box_),
// point_ (it.point_)
// {
// }
box_iter(const box<T, dim>& box, point_type p) :
box_ (box),
point_ (p)
{
}
public:
friend class boost::iterator_core_access;
template <typename, unsigned> friend struct box_rev_iter;
inline
void increment()
{
for (int i = dim-1; ;--i)
{
point_[i] += 1;
if (point_[i] < box_.pmax[i] || i == 0)
break;
point_[i] = box_.pmin[i];
}
}
inline
void decrement()
{
for (int i = dim-1; ;--i)
{
point_[i] -= 1;
if (point_[i] >= box_.pmin[i] || i == 0)
break;
point_[i] = box_.pmax[i] - 1;
}
}
template <typename U>
bool equal(const box_iter<U, dim>& other) const
{
return this->point_ == other.point_;
}
const point_type& dereference() const
{
return point_;
}
box<short, dim> box_; // Domain iteration (do faster than reference)
point_type point_; // Site location
};
template <typename T, unsigned dim>
struct box_rev_iter :
public boost::iterator_facade< box_rev_iter<T, dim>, const typename box<T, dim>::point_type,
boost::bidirectional_traversal_tag, const typename box<T, dim>::point_type&>
{
typedef typename box<T, dim>::point_type point_type;
box_rev_iter() {}
box_rev_iter(const box_iter<T, dim>& it) :
box_ (it.box_),
point_ (it.point_)
{
}
box_rev_iter(const box<T, dim>& box, point_type p) :
box_ (box),
point_ (p)
{
}
public:
friend class boost::iterator_core_access;
template <typename, unsigned> friend struct box_iter;
inline
void decrement()
{
for (int i = dim-1; ;--i)
{
point_[i] += 1;
if (point_[i] < box_.pmax[i] || i == 0)
break;
point_[i] = box_.pmin[i];
}
}
inline
void increment()
{
for (int i = dim-1; ;--i)
{
point_[i] -= 1;
if (point_[i] >= box_.pmin[i] || i == 0)
break;
point_[i] = box_.pmax[i] - 1;
}
}
template <typename U>
bool equal(const box_rev_iter<U, dim>& other) const
{
return this->point_ == other.point_;
}
const point_type& dereference() const
{
return point_;
}
box<short, dim> box_; // Domain iteration (do faster than reference)
point_type point_; // Site location
};
*/
}
// Specialization of the boost::reverse_iterator
// Because increment and decrement have constant complexity but quite
// expensive compared to stl iterator.
namespace boost
{
template <>
template <typename T, unsigned dim>
struct reverse_iterator< mln::box_iter<T, dim> > :
mln::fast_reverse_iterator< mln::box_iter<T, dim> >
{
private:
typedef mln::box_iter<T, dim> base_it;
typedef mln::fast_reverse_iterator<base_it> base;
public:
reverse_iterator() = default;
reverse_iterator(const reverse_iterator&) = default;
reverse_iterator(const base_it& it) : base(it) {}
};
// template <>
// template <typename T, unsigned dim>
// struct reverse_iterator< mln::box_rev_iter<T, dim> > : mln::box_iter<T, dim>
// {
// private:
// typedef mln::box_iter<T, dim> base;
// public:
// reverse_iterator() = default;
// reverse_iterator(const reverse_iterator&) = default;
// reverse_iterator(mln::box_rev_iter<T, dim> it) : base(--it) {}
// };
}
......
......@@ -4,7 +4,7 @@
# include <type_traits>
# include <utility>
# include <boost/iterator/iterator_facade.hpp>
# include <mln/core/iterator/iterator_base.hpp>
# include <boost/any.hpp>
namespace mln
......@@ -34,6 +34,9 @@ namespace mln
template <typename S>
auto get_point(S& v) -> decltype(v.get_point()) { return v.get_point(); }
template <typename S>
auto get_point(const S& v) const -> decltype(v.get_point()) { return v.get_point(); }
template <typename S>
typename get_value_helper<S>::type
get_value(S& v) {
......@@ -86,13 +89,17 @@ namespace mln
/// * `PVis::next<n>(P&)`
/// * `PVis::finished<n>(P&)`
/// \{
template <typename Point> struct origin_point_visitor;
template <typename Point> struct domain_point_visitor;
template <typename Point> struct strided_domain_point_visitor;
template <typename P> origin_point_visitor<P> make_point_visitor(const P& pmax);
template <typename P> domain_point_visitor<P> make_point_visitor(const P& pmin, const P& pmax);
template <typename P> strided_domain_point_visitor<P> make_point_visitor(const P& pmin, const P& pmax, const P& strides);
template <typename Point> struct origin_point_visitor_forward;
template <typename Point> struct origin_point_visitor_backward;
template <typename Point> struct domain_point_visitor_forward;
template <typename Point> struct domain_point_visitor_backward;
//template <typename Point> struct strided_domain_point_visitor;
template <typename P> origin_point_visitor_forward<P> make_point_visitor_forward(const P& pmax);
template <typename P> origin_point_visitor_backward<P> make_point_visitor_backward(const P& pmax);
template <typename P> domain_point_visitor_forward<P> make_point_visitor_forward(const P& pmin, const P& pmax);
template <typename P> domain_point_visitor_backward<P> make_point_visitor_backward(const P& pmin, const P& pmax);
//template <typename P> strided_domain_point_visitor<P> make_point_visitor(const P& pmin, const P& pmax, const P& strides);
/// \}
......@@ -106,9 +113,8 @@ namespace mln
/// * `VVis::next<n>(VVis::arg)`
/// The type of `s.get_value()` must be convertible to `VVis::arg`
/// \{
template <typename V, size_t dim, bool forward> struct strided_pointer_value_visitor;
template <size_t dim, bool forward> struct strided_pointer_value_visitor;
struct no_op_value_visitor;
/// \}
......@@ -185,10 +191,10 @@ namespace mln
origin_point_visitor_backward() : pmax_ () {}
origin_point_visitor_backward(const P& pmax) : pmax_ (pmax) {}
void initialize(P& point) const { point = (P){0,}; point[0] = pmax_[0]; }
void initialize(P& point) const { point = pmax_; point -= 1; }
template <size_t n> void init(P& point) const { point[n] = pmax_[n] - 1; }
template <size_t n> void next(P& point) const { --point[n]; }
template <size_t n> bool finished(P& point) const { return point[n] < 0; }
template <size_t n> bool finished(const P& point) const { return point[n] < 0; }
private:
P pmax_;
......@@ -203,7 +209,7 @@ namespace mln
domain_point_visitor_backward(): pmin_ (), pmax_ () {}
domain_point_visitor_backward(const P& pmin, const P& pmax) : pmin_ (pmin), pmax_ (pmax) {}
void initialize(P& point) const { point = pmin_; point[0] = pmax_[0]; }
void initialize(P& point) const { point = pmax_; point -= 1; }
template <size_t n> void init(P& point) const { point[n] = pmax_[n] - 1; }
template <size_t n> void next(P& point) const { --point[n]; }
template <size_t n> bool finished(P& point) const { return point[n] < pmin_[n]; }
......@@ -265,34 +271,24 @@ namespace mln
// Value visitor
template <typename V, size_t dim, bool forward>
template <size_t dim, bool forward>
struct strided_pointer_value_visitor
{
typedef char* ptr_t;
typedef char* byte_ptr_t;
enum { ndim = dim };
strided_pointer_value_visitor()
{
}
strided_pointer_value_visitor(ptr_t start, const size_t* strides)
strided_pointer_value_visitor(byte_ptr_t start, const size_t* strides)
: start_ (start)
{
std::copy(strides, strides + ndim, strides_.begin());
}
// Conversion non-const -> const
template <typename U>
strided_pointer_value_visitor(const strided_pointer_value_visitor<U, dim, forward>& other,
typename std::enable_if< std::is_convertible<U*, V*>::value >* dummy = NULL) :
start_ (other.start_),
strides_ (other.strides_),
stack_ (other.stack_)
{
}
void
initialize(ptr_t& ptr)
initialize(byte_ptr_t& ptr)
{
ptr = start_;
stack_.fill(start_);
......@@ -301,7 +297,7 @@ namespace mln
template <size_t n>
typename std::enable_if<(n < ndim-1)>::type
init (ptr_t& )
init (byte_ptr_t& )
{
static_assert(n > 0, "");
stack_[n] = stack_[n-1];
......@@ -309,51 +305,46 @@ namespace mln
template <size_t n>
typename std::enable_if<(n == ndim-1)>::type
init(ptr_t& ptr)
init(byte_ptr_t& ptr)
{
static_assert(n > 0, "");
ptr = stack_[n] = stack_[n-1];
}
private:
char* start_;
std::array<size_t, ndim> strides_;
std::array<char*, ndim> stack_;
};
template <typename V, size_t dim>
template <size_t n>
typename std::enable_if<(n < dim-1)>::type
strided_pointer_value_visitor<V, dim, false>::next (ptr_t&)
typename std::enable_if<(!forward and n < dim-1)>::type
next (char* &)
{
stack_[n] -= strides_[n];
}
template <typename V, size_t dim>
template <size_t n>
typename std::enable_if<(n < dim-1)>::type
strided_pointer_value_visitor<V, dim, true>::next (ptr_t&)
typename std::enable_if<(forward and n < dim-1)>::type
next (char* &)
{
stack_[n] += strides_[n];
}
template <typename V, size_t dim>
template <size_t n>
typename std::enable_if<(n == dim-1)>::type
strided_pointer_value_visitor<V, dim, false>::next (ptr_t& ptr)
typename std::enable_if<(!forward and n == dim-1)>::type
next (char*& ptr)
{
ptr = (stack_[n] -= strides_[n]);
}
template <typename V, size_t dim>
template <size_t n>
typename std::enable_if<(n == dim-1)>::type
strided_pointer_value_visitor<V, dim, true>::next (ptr_t& ptr)
typename std::enable_if<(forward and n == dim-1)>::type
next (char*& ptr)
{
ptr = (stack_[n] += strides_[n]);
}
private:
char* start_;
std::array<size_t, ndim> strides_;
std::array<char*, ndim> stack_;
};
struct no_op_value_visitor
{
......@@ -387,8 +378,8 @@ namespace mln
void init()
{
p_.initialize();
v_.initialize()
p_.initialize(get_point(s_));
v_.initialize(get_value(s_));
}
void next()
......@@ -396,9 +387,9 @@ namespace mln
this->next_<ndim-1>();
}
void finished() const
bool finished() const
{
return p_.finished();
return p_.template finished<0>(get_point(s_));
}
reference
......@@ -426,7 +417,7 @@ namespace mln
v_.template next<n>(get_value(s_));
return;
}
this->next<n-1>();
this->next_<n-1>();
p_.template init<n>(get_point(s_));
v_.template init<n>(get_value(s_));
}
......
......@@ -10,10 +10,7 @@
# include <mln/core/image_traits.hpp>
# include <mln/core/image_category.hpp>
# include <boost/range/iterator_range.hpp>
# include <mln/core/image/ndimage_iter.hpp>
# include <mln/core/image/ndimage_pixel_iterator.hpp>
namespace mln
{
......@@ -136,32 +133,28 @@ namespace mln
const_reference at (difference_type n) const;
// As an IterableImage
typedef ndimage_iter<this_type, T> value_iterator;
typedef ndimage_iter<const this_type, const T> const_value_iterator;
typedef boost::reverse_iterator<value_iterator> reverse_value_iterator;
typedef boost::reverse_iterator<const_value_iterator> const_reverse_value_iterator;
typedef ndimage_pixel_iterator<T, dim, E> pixel_iterator;
typedef ndimage_pixel_iterator<const T, dim, const E> const_pixel_iterator;
typedef boost::reverse_iterator<pixel_iterator> reverse_pixel_iterator;
typedef boost::reverse_iterator<const_pixel_iterator> const_reverse_pixel_iterator;
typedef ndimage_value_range<this_type, T> value_range;
typedef ndimage_value_range<const this_type, const T> const_value_range;
typedef typename value_range::iterator value_iterator;
typedef typename value_range::reverse_iterator reverse_value_iterator;
typedef typename const_value_range::iterator const_value_iterator;
typedef typename const_value_range::reverse_iterator const_reverse_value_iterator;
typedef ndimage_pixel_range<this_type, T> pixel_range;
typedef ndimage_pixel_range<const this_type, const T> const_pixel_range;
typedef typename pixel_range::iterator pixel_iterator;
typedef typename pixel_range::reverse_iterator reverse_pixel_iterator;