extent: add range-for adapter for extent points

This commit is contained in:
Danny Robson 2015-09-29 17:32:11 +10:00
parent 543da8f15e
commit 464c703ffd
3 changed files with 147 additions and 1 deletions

View File

@ -22,6 +22,7 @@
#include <cmath>
using util::extent;
using util::extent_range;
///////////////////////////////////////////////////////////////////////////////
@ -119,11 +120,97 @@ const extent<S,T> extent<S,T>::MIN { 0 };
//-----------------------------------------------------------------------------
template <size_t S, typename T>
const extent<S,T> extent<S,T>::MAX {
const extent<S,T> extent<S,T>::MAX
{
std::numeric_limits<T>::max ()
};
///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T>
extent_range<S,T>::extent_range (extent<S,T> _target):
m_target (_target)
{ ; }
//-----------------------------------------------------------------------------
template <size_t S, typename T>
typename extent_range<S,T>::iterator
extent_range<S,T>::begin (void) const
{
return iterator (m_target, util::point<S,T> (0));
}
//-----------------------------------------------------------------------------
template <size_t S, typename T>
typename extent_range<S,T>::iterator
extent_range<S,T>::end (void) const
{
util::point<S,T> cursor (0);
cursor[S-1] = m_target[S-1];
return iterator (m_target, cursor);
}
///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T>
extent_range<S,T>::iterator::iterator (extent<S,T> _target, util::point<S,T> _cursor):
m_cursor (_cursor),
m_target (_target)
{
static_assert (std::is_integral<T>::value, "range stepping size is ill-defined for non-integral types");
}
//-----------------------------------------------------------------------------
template <size_t S, typename T>
util::point<S,T>
extent_range<S,T>::iterator::operator* (void) const
{
return m_cursor;
}
//-----------------------------------------------------------------------------
template <size_t S, typename T>
typename extent_range<S,T>::iterator&
extent_range<S,T>::iterator::operator++ (void)
{
++m_cursor[0];
for (size_t i = 0; i < S - 1; ++i) {
if (m_cursor[i] != m_target[i])
break;
m_cursor[i] = 0;
m_cursor[i+1]++;
continue;
}
return *this;
}
//-----------------------------------------------------------------------------
template <size_t S, typename T>
bool
extent_range<S,T>::iterator::operator== (const iterator &rhs) const
{
return m_cursor == rhs.m_cursor;
}
//-----------------------------------------------------------------------------
template <size_t S, typename T>
bool
extent_range<S,T>::iterator::operator!= (const iterator &rhs) const
{
return m_cursor != rhs.m_cursor;
}
///////////////////////////////////////////////////////////////////////////////
namespace debug {
template <size_t S, typename T>
@ -173,4 +260,11 @@ namespace util {
INSTANTIATE(uint64_t)
INSTANTIATE(float)
INSTANTIATE(double)
template struct extent_range<2,uint16_t>;
template struct extent_range<3,uint16_t>;
template struct extent_range<2,uint32_t>;
template struct extent_range<3,uint32_t>;
template struct extent_range<2,uint64_t>;
template struct extent_range<3,uint64_t>;
}

View File

@ -56,6 +56,33 @@ namespace util {
static const extent MIN;
};
template <size_t S, typename T>
struct extent_range {
public:
struct iterator : public std::iterator<std::forward_iterator_tag, point<S,T>, size_t> {
public:
iterator (extent<S,T>, util::point<S,T>);
point<S,T> operator* () const;
iterator& operator++ (void);
bool operator!= (const iterator &rhs) const;
bool operator== (const iterator &rhs) const;
private:
point<S,T> m_cursor;
extent<S,T> m_target;
};
extent_range (extent<S,T> target);
iterator begin (void) const;
iterator end (void) const;
private:
extent<S,T> m_target;
};
// convenience typedefs
template <typename T> using extent2 = extent<2,T>;
template <typename T> using extent3 = extent<3,T>;
@ -68,6 +95,14 @@ namespace util {
typedef extent3<size_t> extent3u;
typedef extent3<float> extent3f;
template <typename T> using extent_range2 = extent_range<2,T>;
template <typename T> using extent_range3 = extent_range<3,T>;
using extent_range2u = extent_range2<typename extent2u::value_type>;
using extent_range2i = extent_range2<typename extent2i::value_type>;
using extent_range3u = extent_range2<typename extent3u::value_type>;
template <size_t S, typename T>
std::ostream& operator<< (std::ostream&, util::extent<S,T>);
}

View File

@ -1,5 +1,6 @@
#include "extent.hpp"
#include "tap.hpp"
#include "types.hpp"
int
main (void)
@ -12,5 +13,21 @@ main (void)
tap.expect_eq (lo, hi.contracted (2), "extent scalar contraction by value");
}
{
static const util::point2u EXPECTED[] = {
{ 0, 0 }, { 1, 0 }, { 2, 0 },
{ 0, 1 }, { 1, 1 }, { 2, 1 },
{ 0, 2 }, { 1, 2 }, { 2, 2 },
};
size_t offset = 0;
unsigned success = 0;
for (auto p: util::extent_range2u ({3, 3}))
success += EXPECTED[offset++] == p ? 1 : 0;
tap.expect (success == elems (EXPECTED), "extent_range2u iteration");
}
return tap.status ();
}