Removed segmented iterator machinery

This commit is contained in:
Ion Gaztañaga
2026-06-04 22:38:57 +02:00
parent 1319a775a0
commit 6765a2a489
2 changed files with 3 additions and 867 deletions
+3 -527
View File
@@ -80,20 +80,9 @@
#include <emmintrin.h>
#endif
#if !defined(BOOST_CONTAINER_NEST_NO_PDEP)
# if defined(__BMI2__)
# define BOOST_CONTAINER_NEST_HAS_PDEP
# elif defined(BOOST_MSVC) && defined(__AVX2__) && (defined(_M_X64) || defined(_M_IX86))
# define BOOST_CONTAINER_NEST_HAS_PDEP
# endif
#endif
#if defined(BOOST_CONTAINER_NEST_HAS_PDEP)
# if defined(BOOST_MSVC)
# include <intrin.h>
# else
# include <immintrin.h>
# endif
//_BitScanForward64 / _BitScanReverse64 used by the bit helpers below.
#if defined(BOOST_MSVC) && (defined(_M_X64) || defined(_M_ARM64))
# include <intrin.h>
#endif
#ifdef __has_builtin
@@ -233,11 +222,6 @@ std::pair< nest_iterator<ValuePointer, StoreDataInBlock, Prefetch>, F >
, nest_iterator<ValuePointer, StoreDataInBlock, Prefetch>
, F);
struct segmented_iterator_tag;
template<class Iterator>
struct segmented_iterator_traits;
namespace nest_detail {
//////////////////////////////////////////////
@@ -292,84 +276,6 @@ BOOST_CONTAINER_FORCEINLINE int unchecked_countl_zero(boost::uint64_t x)
#endif
}
// nth_set_bit: returns the bit-position of the nth set bit (0-indexed) in mask.
// Precondition: popcount(mask) > n >= 0.
//
// Two implementations selected at compile time:
// 1. BMI2 pdep + countr_zero (BOOST_CONTAINER_NEST_HAS_PDEP)
// 2. Binary search using popcount (default fallback)
//
// The default fallback halves the 64-bit mask with popcount at each step
// (branching variant). Define BOOST_CONTAINER_NEST_NTH_BIT_BRANCHLESS to
// select a branchless arithmetic variant of the same algorithm.
#if defined(BOOST_CONTAINER_NEST_HAS_PDEP)
BOOST_CONTAINER_FORCEINLINE int nth_set_bit(boost::uint64_t mask, int n)
{
return unchecked_countr_zero(_pdep_u64(boost::uint64_t(1) << n, mask));
}
#elif defined(BOOST_CONTAINER_NEST_NTH_BIT_BRANCHLESS)
inline int nth_set_bit(boost::uint64_t mask, int n)
{
int pos = 0;
int c;
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x00000000FFFFFFFFu)));
{ const int s = (n >= c); pos += s * 32; mask >>= unsigned(s * 32); n -= s * c; }
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x000000000000FFFFu)));
{ const int s = (n >= c); pos += s * 16; mask >>= unsigned(s * 16); n -= s * c; }
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x00000000000000FFu)));
{ const int s = (n >= c); pos += s * 8; mask >>= unsigned(s * 8); n -= s * c; }
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x000000000000000Fu)));
{ const int s = (n >= c); pos += s * 4; mask >>= unsigned(s * 4); n -= s * c; }
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x0000000000000003u)));
{ const int s = (n >= c); pos += s * 2; mask >>= unsigned(s * 2); n -= s * c; }
{ const int s = (n > 0); pos += s; mask >>= unsigned(s); }
return pos + unchecked_countr_zero(mask);
}
#else
inline int nth_set_bit(boost::uint64_t mask, int n)
{
int pos = 0;
int c;
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x00000000FFFFFFFFu)));
if (n >= c) { pos += 32; mask >>= 32; n -= c; }
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x000000000000FFFFu)));
if (n >= c) { pos += 16; mask >>= 16; n -= c; }
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x00000000000000FFu)));
if (n >= c) { pos += 8; mask >>= 8; n -= c; }
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x000000000000000Fu)));
if (n >= c) { pos += 4; mask >>= 4; n -= c; }
c = boost::core::popcount(boost::uint64_t(mask & boost::uint64_t(0x0000000000000003u)));
if (n >= c) { pos += 2; mask >>= 2; n -= c; }
if (n > 0) { pos += 1; mask >>= 1; }
return pos + unchecked_countr_zero(mask);
}
#endif
//////////////////////////////////////////////
//
@@ -872,7 +778,6 @@ public:
private:
template<class, bool, bool> friend class nest_iterator;
template<class, class, class> friend class boost::container::nest;
template<class> friend struct ::boost::container::segmented_iterator_traits;
template<class VP, bool SDIB, bool Pf, class FF>
friend std::pair< nest_iterator<VP, SDIB, Pf>, FF >
for_each_while
@@ -909,370 +814,6 @@ private:
int n;
};
//////////////////////////////////////////////
//
// nest_local_iterator
//
//////////////////////////////////////////////
#define NEST_LOCAL_ITERATOR_FULL
#if defined(NEST_LOCAL_ITERATOR_FULL)
template<class ValuePointer, bool StoreDataInBlock>
class nest_local_iterator
{
typedef typename boost::intrusive::pointer_traits<ValuePointer>::element_type element_type;
typedef typename nest_detail::pointer_rebind<ValuePointer, void>::type void_pointer;
typedef nest_detail::block_base<void_pointer> block_base_type;
typedef typename nest_detail::pointer_rebind<ValuePointer,
typename dtl::remove_const<element_type>::type>::type nonconst_pointer;
typedef nest_detail::block<nonconst_pointer, StoreDataInBlock> block_type;
typedef typename block_base_type::mask_type mask_type;
BOOST_STATIC_CONSTEXPR std::size_t N = block_base_type::N;
BOOST_STATIC_CONSTEXPR mask_type full = block_base_type::full;
BOOST_STATIC_CONSTEXPR mask_type full_l = (full << 1);
public:
typedef typename dtl::remove_const<element_type>::type value_type;
typedef typename boost::intrusive::pointer_traits<ValuePointer>::difference_type difference_type;
typedef ValuePointer pointer;
typedef element_type& reference;
typedef std::random_access_iterator_tag iterator_category;
typedef typename nest_detail::pointer_rebind<ValuePointer, block_base_type>::type block_base_pointer;
nest_local_iterator() BOOST_NOEXCEPT
: pbb(), n(0)
{}
nest_local_iterator(block_base_pointer pbb_, int n_) BOOST_NOEXCEPT
: pbb(pbb_), n(n_)
{}
BOOST_CONTAINER_FORCEINLINE reference operator*() const BOOST_NOEXCEPT
{ return static_cast<block_type&>(*pbb).data()[n]; }
BOOST_CONTAINER_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT
{ return static_cast<block_type&>(*pbb).data() + n; }
BOOST_CONTAINER_FORCEINLINE nest_local_iterator& operator++() BOOST_NOEXCEPT
{
BOOST_CONTAINER_ASSUME(n != (int)N);
const mask_type m = pbb->mask & (full_l << n);
n = m ? nest_detail::first_in_mask(m) : (int)N;
return *this;
}
BOOST_CONTAINER_FORCEINLINE nest_local_iterator operator++(int) BOOST_NOEXCEPT
{ nest_local_iterator tmp(*this); ++*this; return tmp; }
BOOST_CONTAINER_FORCEINLINE nest_local_iterator& operator--() BOOST_NOEXCEPT
{
BOOST_CONTAINER_ASSUME(n != 0);
const mask_type m = pbb->mask & (full >> (int(N) - n));
n = nest_detail::last_in_mask(m);
return *this;
}
BOOST_CONTAINER_FORCEINLINE nest_local_iterator operator--(int) BOOST_NOEXCEPT
{ nest_local_iterator tmp(*this); --*this; return tmp; }
// random-access: advance by k occupied slots
BOOST_CONTAINER_FORCEINLINE nest_local_iterator& operator+=(difference_type k) BOOST_NOEXCEPT
{
const mask_type m = pbb->mask;
const mask_type lo = (n == int(N)) ? full : ((mask_type(1) << n) - 1);
const int idx = (int)boost::core::popcount(m & lo);
const int target = idx + (int)k;
const int total = (int)boost::core::popcount(m);
BOOST_CONTAINER_ASSUME(target >= 0 && target <= total);
n = (target >= total) ? (int)N : nest_detail::nth_set_bit(m, target);
return *this;
}
BOOST_CONTAINER_FORCEINLINE nest_local_iterator& operator-=(difference_type k) BOOST_NOEXCEPT
{ return *this += (-k); }
BOOST_CONTAINER_FORCEINLINE
friend nest_local_iterator operator+(nest_local_iterator it, difference_type k) BOOST_NOEXCEPT
{ it += k; return it; }
BOOST_CONTAINER_FORCEINLINE
friend nest_local_iterator operator+(difference_type k, nest_local_iterator it) BOOST_NOEXCEPT
{ it += k; return it; }
BOOST_CONTAINER_FORCEINLINE
friend nest_local_iterator operator-(nest_local_iterator it, difference_type k) BOOST_NOEXCEPT
{ it -= k; return it; }
BOOST_CONTAINER_FORCEINLINE reference operator[](difference_type k) const BOOST_NOEXCEPT
{ return *(*this + k); }
// equality
BOOST_CONTAINER_FORCEINLINE
friend bool operator==(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
{ return x.n == y.n; }
BOOST_CONTAINER_FORCEINLINE
friend bool operator!=(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
{ return x.n != y.n; }
// ordering
BOOST_CONTAINER_FORCEINLINE
friend bool operator<(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
{ return x.n < y.n; }
BOOST_CONTAINER_FORCEINLINE
friend bool operator>(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
{ return x.n > y.n; }
BOOST_CONTAINER_FORCEINLINE
friend bool operator<=(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
{ return x.n <= y.n; }
BOOST_CONTAINER_FORCEINLINE
friend bool operator>=(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
{ return x.n >= y.n; }
// distance
BOOST_CONTAINER_FORCEINLINE
friend difference_type operator-(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
{
BOOST_CONTAINER_ASSUME(x.pbb == y.pbb);
#if 0 //Supporting negative difference would require additional checks
const mask_type m = x.pbb->mask;
const mask_type lo_x = (x.n == int(N)) ? full : ((mask_type(1) << x.n) - 1);
const mask_type lo_y = (y.n == int(N)) ? full : ((mask_type(1) << y.n) - 1);
return difference_type(boost::core::popcount(m & lo_x))
- difference_type(boost::core::popcount(m & lo_y));
#endif
const mask_type lo_x = (x.n == int(N)) ? full : ((mask_type(1) << x.n) - 1);
const mask_type lo_y = (y.n == int(N)) ? full : ((mask_type(1) << y.n) - 1);
const mask_type m = x.pbb->mask;
return boost::core::popcount(m & lo_x & (~lo_y));
}
BOOST_CONTAINER_FORCEINLINE block_base_pointer get_block() const BOOST_NOEXCEPT { return pbb; }
BOOST_CONTAINER_FORCEINLINE int get_slot() const BOOST_NOEXCEPT { return n; }
private:
block_base_pointer pbb;
int n;
};
#else
template<class ValuePointer, bool StoreDataInBlock>
class nest_local_iterator
{
typedef typename boost::intrusive::pointer_traits<ValuePointer>::element_type element_type;
typedef typename nest_detail::pointer_rebind<ValuePointer, void>::type void_pointer;
typedef nest_detail::block_base<void_pointer> block_base_type;
typedef typename nest_detail::pointer_rebind<ValuePointer,
typename dtl::remove_const<element_type>::type>::type nonconst_pointer;
typedef nest_detail::block<nonconst_pointer, StoreDataInBlock> block_type;
typedef typename block_base_type::mask_type mask_type;
BOOST_STATIC_CONSTEXPR std::size_t N = block_base_type::N;
BOOST_STATIC_CONSTEXPR mask_type full = block_base_type::full;
BOOST_STATIC_CONSTEXPR mask_type full_l = (full << 1);
public:
typedef typename dtl::remove_const<element_type>::type value_type;
typedef typename boost::intrusive::pointer_traits<ValuePointer>::difference_type difference_type;
typedef ValuePointer pointer;
typedef element_type& reference;
typedef std::random_access_iterator_tag iterator_category;
typedef typename nest_detail::pointer_rebind<ValuePointer, block_base_type>::type block_base_pointer;
nest_local_iterator() BOOST_NOEXCEPT
: pos()
{}
nest_local_iterator(block_base_pointer pbb_, int n_) BOOST_NOEXCEPT
: pos(static_cast<block_type&>(*pbb_).data()+n_), n(n_), mask(pbb_->mask)
{}
BOOST_CONTAINER_FORCEINLINE reference operator*() const BOOST_NOEXCEPT
{ return *pos; }
BOOST_CONTAINER_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT
{ return pos; }
BOOST_CONTAINER_FORCEINLINE nest_local_iterator& operator++() BOOST_NOEXCEPT
{
BOOST_CONTAINER_ASSUME(n != (int)N);
const mask_type m = mask & (full_l << n);
const int old_n = n;
n = m ? nest_detail::first_in_mask(m) : (int)N;
pos += (n - old_n);
return *this;
}
BOOST_CONTAINER_FORCEINLINE nest_local_iterator operator++(int) BOOST_NOEXCEPT
{ nest_local_iterator tmp(*this); ++*this; return tmp; }
BOOST_CONTAINER_FORCEINLINE nest_local_iterator& operator--() BOOST_NOEXCEPT
{
BOOST_CONTAINER_ASSUME(n != 0);
const mask_type m = mask & (full >> (N - n));
const int old_n = n;
n = nest_detail::last_in_mask(m);
pos -= (old_n - n);
return *this;
}
BOOST_CONTAINER_FORCEINLINE nest_local_iterator operator--(int) BOOST_NOEXCEPT
{ nest_local_iterator tmp(*this); --*this; return tmp; }
// random-access: advance by k occupied slots
BOOST_CONTAINER_FORCEINLINE nest_local_iterator& operator+=(difference_type k) BOOST_NOEXCEPT
{
const mask_type m = mask;
const mask_type lo = (n == int(N)) ? full : ((mask_type(1) << n) - 1);
const int idx = (int)boost::core::popcount(m & lo);
const int target = idx + (int)k;
const int total = (int)boost::core::popcount(m);
BOOST_CONTAINER_ASSUME(target >= 0 && target <= total);
const int old_n = n;
n = (target >= total) ? (int)N : nest_detail::nth_set_bit(m, target);
pos += (n - old_n);
return *this;
}
BOOST_CONTAINER_FORCEINLINE nest_local_iterator& operator-=(difference_type k) BOOST_NOEXCEPT
{ return *this += (-k); }
BOOST_CONTAINER_FORCEINLINE
friend nest_local_iterator operator+(nest_local_iterator it, difference_type k) BOOST_NOEXCEPT
{ it += k; return it; }
BOOST_CONTAINER_FORCEINLINE
friend nest_local_iterator operator+(difference_type k, nest_local_iterator it) BOOST_NOEXCEPT
{ it += k; return it; }
BOOST_CONTAINER_FORCEINLINE
friend nest_local_iterator operator-(nest_local_iterator it, difference_type k) BOOST_NOEXCEPT
{ it -= k; return it; }
BOOST_CONTAINER_FORCEINLINE reference operator[](difference_type k) const BOOST_NOEXCEPT
{ return *(*this + k); }
// equality
BOOST_CONTAINER_FORCEINLINE
friend bool operator==(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
{ return x.n == y.n; }
BOOST_CONTAINER_FORCEINLINE
friend bool operator!=(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
{ return x.n != y.n; }
// ordering
BOOST_CONTAINER_FORCEINLINE
friend bool operator<(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
{ return x.n < y.n; }
BOOST_CONTAINER_FORCEINLINE
friend bool operator>(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
{ return x.n > y.n; }
BOOST_CONTAINER_FORCEINLINE
friend bool operator<=(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
{ return x.n <= y.n; }
BOOST_CONTAINER_FORCEINLINE
friend bool operator>=(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
{ return x.n >= y.n; }
// distance
BOOST_CONTAINER_FORCEINLINE
friend difference_type operator-(const nest_local_iterator& x, const nest_local_iterator& y) BOOST_NOEXCEPT
{
BOOST_CONTAINER_ASSUME(x.mask == y.mask);
#if 0
const mask_type m = x.mask;
const mask_type lo_x = (x.n == int(N)) ? full : ((mask_type(1) << x.n) - 1);
const mask_type lo_y = (y.n == int(N)) ? full : ((mask_type(1) << y.n) - 1);
return difference_type(boost::core::popcount(m & lo_x))
- difference_type(boost::core::popcount(m & lo_y));
#endif
BOOST_CONTAINER_ASSUME(x.n >= y.n); // Undefined behavior otherwise
const mask_type m = x.mask;
const mask_type lo_x = (x.n == int(N)) ? full : ((mask_type(1) << x.n) - 1);
const mask_type lo_y = (y.n == int(N)) ? full : ((mask_type(1) << y.n) - 1);
return boost::core::popcount(m & lo_x & (~lo_y));
}
//BOOST_CONTAINER_FORCEINLINE block_base_pointer get_block() const BOOST_NOEXCEPT { return pbb; }
BOOST_CONTAINER_FORCEINLINE int get_slot() const BOOST_NOEXCEPT { return n; }
private:
pointer pos;
int n;
mask_type mask;
};
#endif //defined(NEST_LOCAL_ITERATOR_FULL)
//////////////////////////////////////////////
//
// nest_segment_iterator
//
//////////////////////////////////////////////
template<class ValuePointer>
class nest_segment_iterator
{
typedef typename nest_detail::pointer_rebind<ValuePointer, void>::type void_pointer;
typedef nest_detail::block_base<void_pointer> block_base_type;
public:
typedef void value_type;
typedef std::ptrdiff_t difference_type;
typedef void pointer;
typedef void reference;
typedef std::bidirectional_iterator_tag iterator_category;
typedef typename nest_detail::pointer_rebind<ValuePointer, block_base_type>::type block_base_pointer;
nest_segment_iterator() BOOST_NOEXCEPT
: pbb()
{}
explicit nest_segment_iterator(block_base_pointer pbb_) BOOST_NOEXCEPT
: pbb(pbb_)
{}
BOOST_CONTAINER_FORCEINLINE nest_segment_iterator& operator++() BOOST_NOEXCEPT
{ pbb = pbb->next; return *this; }
BOOST_CONTAINER_FORCEINLINE nest_segment_iterator operator++(int) BOOST_NOEXCEPT
{ nest_segment_iterator tmp(*this); ++*this; return tmp; }
BOOST_CONTAINER_FORCEINLINE nest_segment_iterator& operator--() BOOST_NOEXCEPT
{ pbb = pbb->prev; return *this; }
BOOST_CONTAINER_FORCEINLINE nest_segment_iterator operator--(int) BOOST_NOEXCEPT
{ nest_segment_iterator tmp(*this); --*this; return tmp; }
BOOST_CONTAINER_FORCEINLINE friend bool operator==(
const nest_segment_iterator& x, const nest_segment_iterator& y) BOOST_NOEXCEPT
{ return x.pbb == y.pbb; }
BOOST_CONTAINER_FORCEINLINE friend bool operator!=(
const nest_segment_iterator& x, const nest_segment_iterator& y) BOOST_NOEXCEPT
{ return !(x == y); }
BOOST_CONTAINER_FORCEINLINE block_base_pointer get_block() const BOOST_NOEXCEPT { return pbb; }
private:
block_base_pointer pbb;
};
namespace nest_detail {
//////////////////////////////////////////////
@@ -1565,71 +1106,6 @@ struct ref_predicate_adaptor
} // namespace nest_detail
////////////////////////////////////////////////////////////////////////////
//
// Specialization of segmented_iterator_traits for nest::iterator
//
////////////////////////////////////////////////////////////////////////////
template<class ValuePointer, bool StoreDataInBlock, bool Prefetch>
struct segmented_iterator_traits
< nest_iterator<ValuePointer, StoreDataInBlock, Prefetch> >
{
typedef segmented_iterator_tag is_segmented_iterator;
typedef nest_iterator<ValuePointer, StoreDataInBlock, Prefetch> nest_iterator_type;
typedef nest_local_iterator<ValuePointer, StoreDataInBlock> local_iterator;
typedef nest_segment_iterator<ValuePointer> segment_iterator;
private:
typedef typename boost::intrusive::pointer_traits
<ValuePointer>::element_type element_type;
typedef typename dtl::remove_const<element_type>::type value_type;
typedef typename nest_detail::pointer_rebind<ValuePointer, void>::type void_pointer;
typedef nest_detail::block_base<void_pointer> block_base_type;
typedef typename nest_detail::pointer_rebind
<ValuePointer, value_type>::type nonconst_pointer;
typedef nest_detail::block<nonconst_pointer, StoreDataInBlock> block_type;
typedef typename block_base_type::mask_type mask_type;
BOOST_STATIC_CONSTEXPR std::size_t N = block_base_type::N;
public:
BOOST_CONTAINER_FORCEINLINE static segment_iterator segment(const nest_iterator_type &it)
{ return segment_iterator(it.pbb); }
BOOST_CONTAINER_FORCEINLINE static local_iterator local(const nest_iterator_type &it)
{ return local_iterator(it.pbb, it.n); }
BOOST_CONTAINER_FORCEINLINE static nest_iterator_type compose(segment_iterator s, const local_iterator& l)
{
int n = l.get_slot();
if (BOOST_UNLIKELY(n == N)) {
++s;
n = 0;
}
return nest_iterator_type(s.get_block(), n);
}
BOOST_CONTAINER_FORCEINLINE static local_iterator begin(const segment_iterator &s)
{
typedef typename segment_iterator::block_base_pointer block_base_pointer;
block_base_pointer const bp = s.get_block();
const mask_type m = bp->mask;
const int n = nest_detail::first_in_mask(m);
//Prefetch the eact line the
//returned local_iterator will dereference first instead of the
//unconditional slot-0 line.
BOOST_CONTAINER_NEST_PREFETCH_BLOCK_NTH(bp, n);
return local_iterator(bp, n);
}
BOOST_CONTAINER_FORCEINLINE static local_iterator end(const segment_iterator &s)
{ return local_iterator(s.get_block(), int(N)); }
};
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template<class Options>
-340
View File
@@ -717,344 +717,6 @@ void test_initializer_list_operations()
}
#endif
void test_segment_iterator_operations()
{
typedef nest<int> nest_t;
typedef nest_t::iterator iterator;
typedef segmented_iterator_traits<iterator> traits;
typedef traits::segment_iterator segment_iterator;
typedef traits::local_iterator local_iterator;
nest_t h;
for (int i = 0; i < 200; ++i)
h.insert(i);
segment_iterator seg_begin = traits::segment(h.begin());
segment_iterator seg_end = traits::segment(h.end());
// Default construction compiles
{
segment_iterator s;
(void)s;
}
// segment() + equality / inequality
{
segment_iterator s1 = traits::segment(h.begin());
segment_iterator s2 = traits::segment(h.begin());
BOOST_TEST(s1 == s2);
BOOST_TEST(!(s1 != s2));
BOOST_TEST(s1 != seg_end);
BOOST_TEST(!(s1 == seg_end));
}
// Pre-increment returns reference to self and advances
{
segment_iterator s = seg_begin;
segment_iterator& ref = ++s;
BOOST_TEST(&ref == &s);
BOOST_TEST(s != seg_begin);
BOOST_TEST(s != seg_end);
}
// Post-increment returns old value and advances
{
segment_iterator s = seg_begin;
segment_iterator old = s++;
BOOST_TEST(old == seg_begin);
segment_iterator expected = seg_begin;
++expected;
BOOST_TEST(s == expected);
}
// Pre-decrement returns reference to self and retreats
{
segment_iterator s = seg_begin;
++s;
segment_iterator& ref = --s;
BOOST_TEST(&ref == &s);
BOOST_TEST(s == seg_begin);
}
// Post-decrement returns old value and retreats
{
segment_iterator second = seg_begin;
++second;
segment_iterator old = second--;
BOOST_TEST(second == seg_begin);
segment_iterator expected = seg_begin;
++expected;
BOOST_TEST(old == expected);
}
// Increment then decrement is identity
{
segment_iterator s = seg_begin;
++s; ++s;
--s; --s;
BOOST_TEST(s == seg_begin);
}
// Count segments (200 elements, 64 per block => at least 4 segments)
{
int num_segments = 0;
for (segment_iterator s = seg_begin; s != seg_end; ++s)
++num_segments;
BOOST_TEST(num_segments >= 4);
}
// Full segmented traversal yields all elements
{
int count = 0;
segment_iterator s = seg_begin;
local_iterator loc = traits::local(h.begin());
while (s != seg_end) {
local_iterator loc_end = traits::end(s);
for (; loc != loc_end; ++loc)
++count;
++s;
if (s != seg_end)
loc = traits::begin(s);
}
BOOST_TEST_EQ(count, 200);
}
// Reverse traversal over segments
{
int fwd_count = 0;
for (segment_iterator s = seg_begin; s != seg_end; ++s)
++fwd_count;
segment_iterator s = seg_end;
int rev_count = 0;
while (s != seg_begin) {
--s;
++rev_count;
}
BOOST_TEST_EQ(fwd_count, rev_count);
}
}
void test_local_iterator_operations()
{
typedef nest<int> nest_t;
typedef nest_t::iterator iterator;
typedef segmented_iterator_traits<iterator> traits;
typedef traits::segment_iterator segment_iterator;
typedef traits::local_iterator local_iterator;
// ---- Dense case (no gaps in bitmask) ----
nest_t h;
for (int i = 0; i < 200; ++i)
h.insert(i);
segment_iterator seg = traits::segment(h.begin());
// Default construction compiles
{
local_iterator l;
(void)l;
}
// begin() / end() of a segment
{
local_iterator b = traits::begin(seg);
local_iterator e = traits::end(seg);
BOOST_TEST(b != e);
}
// operator* dereference
{
local_iterator b = traits::begin(seg);
int val = *b;
(void)val;
}
// operator-> returns valid pointer
{
local_iterator b = traits::begin(seg);
BOOST_TEST(b.operator->() != 0);
BOOST_TEST_EQ(*b.operator->(), *b);
}
// Equality / inequality
{
local_iterator b1 = traits::begin(seg);
local_iterator b2 = traits::begin(seg);
local_iterator e = traits::end(seg);
BOOST_TEST(b1 == b2);
BOOST_TEST(!(b1 != b2));
BOOST_TEST(b1 != e);
BOOST_TEST(!(b1 == e));
}
// Pre-increment returns reference to self and advances
{
local_iterator b = traits::begin(seg);
local_iterator orig = b;
local_iterator& ref = ++b;
BOOST_TEST(&ref == &b);
BOOST_TEST(b != orig);
}
// Post-increment returns old value
{
local_iterator b = traits::begin(seg);
local_iterator old = b++;
BOOST_TEST(old == traits::begin(seg));
local_iterator expected = traits::begin(seg);
++expected;
BOOST_TEST(b == expected);
}
// Pre-decrement returns reference to self and retreats
{
local_iterator b = traits::begin(seg);
local_iterator second = b;
++second;
local_iterator& ref = --second;
BOOST_TEST(&ref == &second);
BOOST_TEST(second == b);
}
// Post-decrement returns old value
{
local_iterator b = traits::begin(seg);
local_iterator second = b;
++second;
local_iterator old = second--;
BOOST_TEST(second == b);
local_iterator expected = b;
++expected;
BOOST_TEST(old == expected);
}
// Increment then decrement is identity
{
local_iterator b = traits::begin(seg);
++b; ++b; ++b;
--b; --b; --b;
BOOST_TEST(b == traits::begin(seg));
}
// operator- (distance) on a dense (fully packed) block
{
local_iterator b = traits::begin(seg);
local_iterator e = traits::end(seg);
int count = 0;
for (local_iterator tmp = b; tmp != e; ++tmp)
++count;
BOOST_TEST_EQ(e - b, count);
BOOST_TEST_EQ(b - b, 0);
BOOST_TEST_EQ(e - e, 0);
local_iterator second = b;
++second;
BOOST_TEST_EQ(second - b, 1);
}
// operator- at intermediate positions
{
local_iterator b = traits::begin(seg);
local_iterator it = b;
for (int i = 0; i < 5; ++i) ++it;
BOOST_TEST_EQ(it - b, 5);
}
// compose() round-trip: compose(segment(it), local(it)) == it
{
iterator it = h.begin();
segment_iterator s = traits::segment(it);
local_iterator l = traits::local(it);
iterator composed = traits::compose(s, l);
BOOST_TEST(composed == it);
BOOST_TEST_EQ(*composed, *it);
}
// compose() round-trip after advancing the nest iterator
{
iterator it = h.begin();
++it; ++it; ++it;
segment_iterator s = traits::segment(it);
local_iterator l = traits::local(it);
iterator composed = traits::compose(s, l);
BOOST_TEST(composed == it);
BOOST_TEST_EQ(*composed, *it);
}
// local() gives an iterator that dereferences to the same value
{
iterator it = h.begin();
local_iterator l = traits::local(it);
BOOST_TEST_EQ(*l, *it);
}
// begin(seg) matches local(compose(seg, begin(seg)))
{
local_iterator b = traits::begin(seg);
iterator it = traits::compose(seg, b);
local_iterator l = traits::local(it);
BOOST_TEST(l == b);
}
// ---- Sparse case (gaps in bitmask after erasures) ----
{
nest_t h2;
for (int i = 0; i < 128; ++i)
h2.insert(i);
int remaining = 128;
int erase_idx = 0;
for (iterator it = h2.begin(); it != h2.end(); ) {
if (erase_idx % 3 == 0) {
it = h2.erase(it);
--remaining;
} else {
++it;
}
++erase_idx;
}
BOOST_TEST_EQ(h2.size(), (nest_t::size_type)remaining);
segment_iterator s = traits::segment(h2.begin());
segment_iterator s_end = traits::segment(h2.end());
int total_count = 0;
local_iterator loc = traits::local(h2.begin());
while (s != s_end) {
local_iterator lb = traits::begin(s);
local_iterator le = traits::end(s);
int seg_count = 0;
for (local_iterator tmp = lb; tmp != le; ++tmp)
++seg_count;
// operator- must match the manual count
BOOST_TEST_EQ(le - lb, seg_count);
BOOST_TEST_EQ(lb - lb, 0);
// Intermediate distances
if (seg_count >= 4) {
local_iterator mid = lb;
++mid; ++mid; ++mid;
BOOST_TEST_EQ(mid - lb, 3);
BOOST_TEST_EQ(le - mid, seg_count - 3);
}
for (; loc != le; ++loc)
++total_count;
++s;
if (s != s_end)
loc = traits::begin(s);
}
BOOST_TEST_EQ(total_count, remaining);
}
}
int main()
{
test_default_construction();
@@ -1106,7 +768,5 @@ int main()
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
test_initializer_list_operations();
#endif
test_segment_iterator_operations();
test_local_iterator_operations();
return boost::report_errors();
}