diff --git a/extent.cpp b/extent.cpp index e635ec6e..770de12b 100644 --- a/extent.cpp +++ b/extent.cpp @@ -23,7 +23,6 @@ #include using util::extent; -using util::extent_range; /////////////////////////////////////////////////////////////////////////////// @@ -86,91 +85,6 @@ extent::empty (void) const } -/////////////////////////////////////////////////////////////////////////////// -template -extent_range::extent_range (extent _target): - m_target (_target) -{ ; } - - -//----------------------------------------------------------------------------- -template -typename extent_range::iterator -extent_range::begin (void) const -{ - return { m_target, util::point (0) }; -} - - -//----------------------------------------------------------------------------- -template -typename extent_range::iterator -extent_range::end (void) const -{ - util::point cursor (0); - cursor[S-1] = m_target[S-1]; - - return { m_target, cursor }; -} - - -/////////////////////////////////////////////////////////////////////////////// -template -extent_range::iterator::iterator (extent _target, util::point _cursor): - m_cursor (_cursor), - m_target (_target) -{ - static_assert (std::is_integral::value, "range stepping size is ill-defined for non-integral types"); -} - - -//----------------------------------------------------------------------------- -template -util::point -extent_range::iterator::operator* (void) const -{ - return m_cursor; -} - - -//----------------------------------------------------------------------------- -template -typename extent_range::iterator& -extent_range::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 -bool -extent_range::iterator::operator== (const iterator &rhs) const -{ - return m_cursor == rhs.m_cursor; -} - - -//----------------------------------------------------------------------------- -template -bool -extent_range::iterator::operator!= (const iterator &rhs) const -{ - return m_cursor != rhs.m_cursor; -} - - /////////////////////////////////////////////////////////////////////////////// namespace util::debug { template @@ -196,11 +110,6 @@ INSTANTIATE_S_T(1,T) \ INSTANTIATE_S_T(2,T) \ INSTANTIATE_S_T(3,T) -#define INSTANTIATE_INT(T) \ -template struct util::extent_range<1,T>; \ -template struct util::extent_range<2,T>; \ -template struct util::extent_range<3,T>; - INSTANTIATE( int16_t) INSTANTIATE( int32_t) INSTANTIATE( int64_t) @@ -211,11 +120,3 @@ INSTANTIATE(uint64_t) INSTANTIATE(float) INSTANTIATE(double) - -INSTANTIATE_INT( int16_t) -INSTANTIATE_INT( int32_t) -INSTANTIATE_INT( int64_t) - -INSTANTIATE_INT(uint16_t) -INSTANTIATE_INT(uint32_t) -INSTANTIATE_INT(uint64_t) diff --git a/extent.hpp b/extent.hpp index 4f154755..811aa31e 100644 --- a/extent.hpp +++ b/extent.hpp @@ -106,49 +106,65 @@ namespace util { { return extent { 0 }; } - }; - template - struct extent_range { - public: - struct iterator : public std::iterator< - std::forward_iterator_tag, - ::util::point, - size_t - > { + + /////////////////////////////////////////////////////////////////////// + class iterator { public: - iterator (::util::extent, ::util::point); + using iterator_category = std::forward_iterator_tag; + using value_type = point; + using difference_type = size_t; + using pointer = value_type*; + using reference = value_type&; - point operator* () const; - iterator& operator++ (void); - bool operator!= (const iterator &rhs) const; - bool operator== (const iterator &rhs) const; + iterator (point _cursor, extent _target): + m_cursor (_cursor), + m_target (_target) + { ; } + + + point operator* () { return m_cursor; } + point operator* () const { return m_cursor; } + + 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]++; + } + + return *this; + } + + + bool operator!= (const iterator &rhs) const { return m_cursor != rhs.m_cursor; } + bool operator== (const iterator &rhs) const { return m_cursor == rhs.m_cursor; } private: point m_cursor; extent m_target; }; - explicit extent_range (extent target); - iterator begin (void) const; - iterator end (void) const; + auto step (void) const + { + point last {0}; + last[S-1] = this->data[S-1]; - private: - extent m_target; + return util::view { + iterator {point {0}, *this}, + iterator {last, *this} + }; + } }; - /////////////////////////////////////////////////////////////////////////// - template - extent_range - make_range (extent e) - { - return extent_range {e}; - } - - /////////////////////////////////////////////////////////////////////////// // convenience typedefs template using extent2 = extent<2,T>; @@ -168,16 +184,6 @@ namespace util { typedef extent3 extent3u; typedef extent3 extent3f; - - - //------------------------------------------------------------------------- - template using extent_range2 = extent_range<2,T>; - template using extent_range3 = extent_range<3,T>; - - - using extent_range2u = extent_range2; - using extent_range2i = extent_range2; - using extent_range3u = extent_range2; } diff --git a/region.hpp b/region.hpp index 3818ed63..bca04b78 100644 --- a/region.hpp +++ b/region.hpp @@ -140,6 +140,59 @@ namespace util { static constexpr region zero (void) { return { point_t {0}, extent_t {0} }; } + + class iterator { + public: + using iterator_category = std::forward_iterator_tag; + using difference_type = std::size_t; + using value_type = point_t; + using pointer = value_type*; + using reference = value_type&; + + iterator (point_t _lo, point_t _hi): + cursor (_lo), + lo (_lo), + hi (_hi) + { ; } + + + const point_t& operator* (void) const& { return cursor; } + + iterator& + operator++ (void) + { + cursor[0] += 1; + + for (size_t s = 0; s < S-1; ++s) { + if (cursor[s] <= hi[s]) + return *this; + + cursor[s] = lo[s]; + cursor[s+1]++; + } + + return *this; + } + + bool operator== (const iterator &rhs) const { return cursor == rhs.cursor; } + bool operator!= (const iterator &rhs) const { return cursor != rhs.cursor; } + + private: + point_t cursor, lo, hi; + }; + + auto step (void) const + { + point_t last = p; + last[S-1] = (p + e)[S-1] + 1; + + return util::view { + iterator { p, p + e }, + iterator { last, p + e } + }; + }; + + void sanity (void) const; }; @@ -157,96 +210,17 @@ namespace util { /////////////////////////////////////////////////////////////////////////// - /// construct a point iterator across a given region, generating each - /// valid point in row-major sequence. - /// - /// this is only defined for integral types as it's not clear how to - /// handle floats; it's _super_ unlikely anyone actually wants to visit - /// every single floating point value for a region (and if so they can - /// damn well code that monstrosity themselves). - template < - typename T, - std::size_t S, - typename = std::enable_if_t< - std::is_integral_v, void - > - > - auto - make_range (region r) - { - using region_t = region; - using point_t = typename region_t::point_t; - using vector_t = util::vector; - - // this range object is mostly a wrapper around the existing - // extent_range object with a constant offset. it's not going to be as - // performant, but when we discover this is an issue we can do write a - // better version of this object & iterator. - class region_range { - public: - class iterator : public std::iterator { - public: - iterator (typename extent_range::iterator _inner, vector_t _offset): - m_inner (_inner), - m_offset (_offset) - { ; } - - - point_t operator* (void) const { return *m_inner + m_offset; } - - iterator& - operator++ (void) - { - ++m_inner; - return *this; - } - - - bool operator== (const iterator &rhs) const - { - assert (m_offset == rhs.m_offset); - return m_inner == rhs.m_inner; - } - - - bool operator!= (const iterator &rhs) const - { return !(*this == rhs); } - - - private: - typename extent_range::iterator m_inner; - vector_t m_offset; - }; - - region_range (region_t _r): - m_range { _r.e + T{1} }, - m_offset { _r.p.template as () } - { ; } - - iterator begin (void) const { return { m_range.begin (), m_offset }; } - iterator end (void) const { return { m_range.end (), m_offset }; } - - iterator cbegin (void) const { return begin (); } - iterator cend (void) const { return end (); } - - private: - const extent_range m_range; - const vector_t m_offset; - }; - - - return region_range { r }; - }; - - template using region2 = region<2,T>; template using region3 = region<3,T>; + using region2u = region2; using region2i = region2; using region2f = region2; using region2d = region2; + + /////////////////////////////////////////////////////////////////////////// template std::ostream& operator<< (std::ostream&, const util::region&); } diff --git a/test/extent.cpp b/test/extent.cpp index 624d897e..1857b4bf 100644 --- a/test/extent.cpp +++ b/test/extent.cpp @@ -17,16 +17,21 @@ main (void) static constexpr 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; + bool success = true; - for (auto p: util::extent_range2u ({3, 3})) - success += EXPECTED[offset++] == p ? 1 : 0; + for (auto p: util::extent2u {3,2}.step ()) { + if (offset >= std::size (EXPECTED)) { + success = false; + break; + } - tap.expect_eq (success, std::size (EXPECTED), "extent_range2u iteration"); + success = success && util::all (EXPECTED[offset++] == p); + } + + tap.expect (success, "extent_range2u iteration"); } return tap.status (); diff --git a/test/region.cpp b/test/region.cpp index dceb0ceb..f63bda4e 100644 --- a/test/region.cpp +++ b/test/region.cpp @@ -85,18 +85,16 @@ main (int, char **) { const util::region2i REGION { util::point2i { -1, 1 }, - util::point2i { 1, 3 } + util::point2i { 1, 2 } }; const util::point2i EXPECTED[] = { { -1, 1 }, { 0, 1 }, { 1, 1 }, { -1, 2 }, { 0, 2 }, { 1, 2 }, - { -1, 3 }, { 0, 3 }, { 1, 3 }, }; std::vector values; - auto sequence = util::make_range (REGION); - std::copy (std::cbegin (sequence), std::cend (sequence), std::back_inserter (values)); + std::copy (std::cbegin (REGION.step ()), std::cend (REGION.step ()), std::back_inserter (values)); bool success = values.size () == std::size (EXPECTED) && std::equal (std::cbegin (values), std::cend (values), @@ -104,8 +102,5 @@ main (int, char **) tap.expect (success, "make_range(region2i)"); }; - //CHECK (region<2,intmax_t> (0, 0, 10, 10).includes (point2d (0.4, 0.01))); - //CHECK (region<2,intmax_t> (0, 0, 10, 10).contains (point2d (0.4, 0.01))); - return tap.status (); }