stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork
This commit is contained in:
@@ -0,0 +1,245 @@
|
||||
// boost heap: heap node helper classes
|
||||
//
|
||||
// Copyright (C) 2010 Tim Blechmann
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HEAP_DETAIL_HEAP_COMPARISON_HPP
|
||||
#define BOOST_HEAP_DETAIL_HEAP_COMPARISON_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/concept/assert.hpp>
|
||||
#include <boost/heap/heap_concepts.hpp>
|
||||
|
||||
#ifdef BOOST_HEAP_SANITYCHECKS
|
||||
#define BOOST_HEAP_ASSERT BOOST_ASSERT
|
||||
#else
|
||||
#define BOOST_HEAP_ASSERT(expression)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace heap {
|
||||
namespace detail {
|
||||
|
||||
template <typename Heap1, typename Heap2>
|
||||
bool value_equality(Heap1 const & lhs, Heap2 const & rhs,
|
||||
typename Heap1::value_type lval, typename Heap2::value_type rval)
|
||||
{
|
||||
typename Heap1::value_compare const & cmp = lhs.value_comp();
|
||||
bool ret = !(cmp(lval, rval)) && !(cmp(rval, lval));
|
||||
|
||||
// if this assertion is triggered, the value_compare objects of lhs and rhs return different values
|
||||
BOOST_ASSERT((ret == (!(rhs.value_comp()(lval, rval)) && !(rhs.value_comp()(rval, lval)))));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename Heap1, typename Heap2>
|
||||
bool value_compare(Heap1 const & lhs, Heap2 const & rhs,
|
||||
typename Heap1::value_type lval, typename Heap2::value_type rval)
|
||||
{
|
||||
typename Heap1::value_compare const & cmp = lhs.value_comp();
|
||||
bool ret = cmp(lval, rval);
|
||||
|
||||
// if this assertion is triggered, the value_compare objects of lhs and rhs return different values
|
||||
BOOST_ASSERT((ret == rhs.value_comp()(lval, rval)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct heap_equivalence_copy
|
||||
{
|
||||
template <typename Heap1, typename Heap2>
|
||||
bool operator()(Heap1 const & lhs, Heap2 const & rhs)
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap1>));
|
||||
BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap2>));
|
||||
|
||||
// if this assertion is triggered, the value_compare types are incompatible
|
||||
BOOST_STATIC_ASSERT((boost::is_same<typename Heap1::value_compare, typename Heap2::value_compare>::value));
|
||||
|
||||
if (Heap1::constant_time_size && Heap2::constant_time_size)
|
||||
if (lhs.size() != rhs.size())
|
||||
return false;
|
||||
|
||||
if (lhs.empty() && rhs.empty())
|
||||
return true;
|
||||
|
||||
Heap1 lhs_copy(lhs);
|
||||
Heap2 rhs_copy(rhs);
|
||||
|
||||
while (true) {
|
||||
if (!value_equality(lhs_copy, rhs_copy, lhs_copy.top(), rhs_copy.top()))
|
||||
return false;
|
||||
|
||||
lhs_copy.pop();
|
||||
rhs_copy.pop();
|
||||
|
||||
if (lhs_copy.empty() && rhs_copy.empty())
|
||||
return true;
|
||||
|
||||
if (lhs_copy.empty())
|
||||
return false;
|
||||
|
||||
if (rhs_copy.empty())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct heap_equivalence_iteration
|
||||
{
|
||||
template <typename Heap1, typename Heap2>
|
||||
bool operator()(Heap1 const & lhs, Heap2 const & rhs)
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap1>));
|
||||
BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap2>));
|
||||
|
||||
// if this assertion is triggered, the value_compare types are incompatible
|
||||
BOOST_STATIC_ASSERT((boost::is_same<typename Heap1::value_compare, typename Heap2::value_compare>::value));
|
||||
|
||||
if (Heap1::constant_time_size && Heap2::constant_time_size)
|
||||
if (lhs.size() != rhs.size())
|
||||
return false;
|
||||
|
||||
if (lhs.empty() && rhs.empty())
|
||||
return true;
|
||||
|
||||
typename Heap1::ordered_iterator it1 = lhs.ordered_begin();
|
||||
typename Heap1::ordered_iterator it1_end = lhs.ordered_end();
|
||||
typename Heap1::ordered_iterator it2 = rhs.ordered_begin();
|
||||
typename Heap1::ordered_iterator it2_end = rhs.ordered_end();
|
||||
while (true) {
|
||||
if (!value_equality(lhs, rhs, *it1, *it2))
|
||||
return false;
|
||||
|
||||
++it1;
|
||||
++it2;
|
||||
|
||||
if (it1 == it1_end && it2 == it2_end)
|
||||
return true;
|
||||
|
||||
if (it1 == it1_end || it2 == it2_end)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Heap1,
|
||||
typename Heap2
|
||||
>
|
||||
bool heap_equality(Heap1 const & lhs, Heap2 const & rhs)
|
||||
{
|
||||
const bool use_ordered_iterators = Heap1::has_ordered_iterators && Heap2::has_ordered_iterators;
|
||||
|
||||
typedef typename boost::mpl::if_c<use_ordered_iterators,
|
||||
heap_equivalence_iteration,
|
||||
heap_equivalence_copy
|
||||
>::type equivalence_check;
|
||||
|
||||
equivalence_check eq_check;
|
||||
return eq_check(lhs, rhs);
|
||||
}
|
||||
|
||||
|
||||
struct heap_compare_iteration
|
||||
{
|
||||
template <typename Heap1,
|
||||
typename Heap2
|
||||
>
|
||||
bool operator()(Heap1 const & lhs, Heap2 const & rhs)
|
||||
{
|
||||
typename Heap1::size_type left_size = lhs.size();
|
||||
typename Heap2::size_type right_size = rhs.size();
|
||||
if (left_size < right_size)
|
||||
return true;
|
||||
|
||||
if (left_size > right_size)
|
||||
return false;
|
||||
|
||||
typename Heap1::ordered_iterator it1 = lhs.ordered_begin();
|
||||
typename Heap1::ordered_iterator it1_end = lhs.ordered_end();
|
||||
typename Heap1::ordered_iterator it2 = rhs.ordered_begin();
|
||||
typename Heap1::ordered_iterator it2_end = rhs.ordered_end();
|
||||
while (true) {
|
||||
if (value_compare(lhs, rhs, *it1, *it2))
|
||||
return true;
|
||||
|
||||
if (value_compare(lhs, rhs, *it2, *it1))
|
||||
return false;
|
||||
|
||||
++it1;
|
||||
++it2;
|
||||
|
||||
if (it1 == it1_end && it2 == it2_end)
|
||||
return true;
|
||||
|
||||
if (it1 == it1_end || it2 == it2_end)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct heap_compare_copy
|
||||
{
|
||||
template <typename Heap1,
|
||||
typename Heap2
|
||||
>
|
||||
bool operator()(Heap1 const & lhs, Heap2 const & rhs)
|
||||
{
|
||||
typename Heap1::size_type left_size = lhs.size();
|
||||
typename Heap2::size_type right_size = rhs.size();
|
||||
if (left_size < right_size)
|
||||
return true;
|
||||
|
||||
if (left_size > right_size)
|
||||
return false;
|
||||
|
||||
Heap1 lhs_copy(lhs);
|
||||
Heap2 rhs_copy(rhs);
|
||||
|
||||
while (true) {
|
||||
if (value_compare(lhs_copy, rhs_copy, lhs_copy.top(), rhs_copy.top()))
|
||||
return true;
|
||||
|
||||
if (value_compare(lhs_copy, rhs_copy, rhs_copy.top(), lhs_copy.top()))
|
||||
return false;
|
||||
|
||||
lhs_copy.pop();
|
||||
rhs_copy.pop();
|
||||
|
||||
if (lhs_copy.empty() && rhs_copy.empty())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Heap1,
|
||||
typename Heap2
|
||||
>
|
||||
bool heap_compare(Heap1 const & lhs, Heap2 const & rhs)
|
||||
{
|
||||
const bool use_ordered_iterators = Heap1::has_ordered_iterators && Heap2::has_ordered_iterators;
|
||||
|
||||
typedef typename boost::mpl::if_c<use_ordered_iterators,
|
||||
heap_compare_iteration,
|
||||
heap_compare_copy
|
||||
>::type compare_check;
|
||||
|
||||
compare_check check_object;
|
||||
return check_object(lhs, rhs);
|
||||
}
|
||||
|
||||
|
||||
} /* namespace detail */
|
||||
} /* namespace heap */
|
||||
} /* namespace boost */
|
||||
|
||||
|
||||
#undef BOOST_HEAP_ASSERT
|
||||
|
||||
#endif // BOOST_HEAP_DETAIL_HEAP_COMPARISON_HPP
|
||||
@@ -0,0 +1,367 @@
|
||||
// boost heap: heap node helper classes
|
||||
//
|
||||
// Copyright (C) 2010 Tim Blechmann
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HEAP_DETAIL_HEAP_NODE_HPP
|
||||
#define BOOST_HEAP_DETAIL_HEAP_NODE_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
#ifdef BOOST_HEAP_SANITYCHECKS
|
||||
#define BOOST_HEAP_ASSERT BOOST_ASSERT
|
||||
#else
|
||||
#define BOOST_HEAP_ASSERT(expression)
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace heap {
|
||||
namespace detail {
|
||||
|
||||
namespace bi = boost::intrusive;
|
||||
namespace mpl = boost::mpl;
|
||||
|
||||
template <bool auto_unlink = false>
|
||||
struct heap_node_base:
|
||||
bi::list_base_hook<typename mpl::if_c<auto_unlink,
|
||||
bi::link_mode<bi::auto_unlink>,
|
||||
bi::link_mode<bi::safe_link>
|
||||
>::type
|
||||
>
|
||||
{};
|
||||
|
||||
typedef bi::list<heap_node_base<false> > heap_node_list;
|
||||
|
||||
struct nop_disposer
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(T * n)
|
||||
{
|
||||
BOOST_HEAP_ASSERT(false);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Node, typename HeapBase>
|
||||
bool is_heap(const Node * n, typename HeapBase::value_compare const & cmp)
|
||||
{
|
||||
for (typename Node::const_child_iterator it = n->children.begin(); it != n->children.end(); ++it) {
|
||||
Node const & this_node = static_cast<Node const &>(*it);
|
||||
const Node * child = static_cast<const Node*>(&this_node);
|
||||
|
||||
if (cmp(HeapBase::get_value(n->value), HeapBase::get_value(child->value)) ||
|
||||
!is_heap<Node, HeapBase>(child, cmp))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Node>
|
||||
std::size_t count_nodes(const Node * n);
|
||||
|
||||
template <typename Node, typename List>
|
||||
std::size_t count_list_nodes(List const & node_list)
|
||||
{
|
||||
std::size_t ret = 0;
|
||||
|
||||
for (typename List::const_iterator it = node_list.begin(); it != node_list.end(); ++it) {
|
||||
const Node * child = static_cast<const Node*>(&*it);
|
||||
ret += count_nodes<Node>(child);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename Node>
|
||||
std::size_t count_nodes(const Node * n)
|
||||
{
|
||||
return 1 + count_list_nodes<Node, typename Node::child_list>(n->children);
|
||||
}
|
||||
|
||||
|
||||
/* node cloner
|
||||
*
|
||||
* Requires `Clone Constructor':
|
||||
* template <typename Alloc>
|
||||
* Node::Node(Node const &, Alloc &)
|
||||
*
|
||||
* template <typename Alloc>
|
||||
* Node::Node(Node const &, Alloc &, Node * parent)
|
||||
*
|
||||
* */
|
||||
template <typename Node,
|
||||
typename NodeBase,
|
||||
typename Alloc>
|
||||
struct node_cloner
|
||||
{
|
||||
node_cloner(Alloc & allocator):
|
||||
allocator(allocator)
|
||||
{}
|
||||
|
||||
Node * operator() (NodeBase const & node)
|
||||
{
|
||||
Node * ret = allocator.allocate(1);
|
||||
new (ret) Node(static_cast<Node const &>(node), allocator);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Node * operator() (NodeBase const & node, Node * parent)
|
||||
{
|
||||
Node * ret = allocator.allocate(1);
|
||||
new (ret) Node(static_cast<Node const &>(node), allocator, parent);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
Alloc & allocator;
|
||||
};
|
||||
|
||||
/* node disposer
|
||||
*
|
||||
* Requirements:
|
||||
* Node::clear_subtree(Alloc &) clears the subtree via allocator
|
||||
*
|
||||
* */
|
||||
template <typename Node,
|
||||
typename NodeBase,
|
||||
typename Alloc>
|
||||
struct node_disposer
|
||||
{
|
||||
typedef typename Alloc::pointer node_pointer;
|
||||
|
||||
node_disposer(Alloc & alloc):
|
||||
alloc_(alloc)
|
||||
{}
|
||||
|
||||
void operator()(NodeBase * base)
|
||||
{
|
||||
node_pointer n = static_cast<node_pointer>(base);
|
||||
n->clear_subtree(alloc_);
|
||||
alloc_.destroy(n);
|
||||
alloc_.deallocate(n, 1);
|
||||
}
|
||||
|
||||
Alloc & alloc_;
|
||||
};
|
||||
|
||||
|
||||
template <typename ValueType,
|
||||
bool constant_time_child_size = true
|
||||
>
|
||||
struct heap_node:
|
||||
heap_node_base<!constant_time_child_size>
|
||||
{
|
||||
typedef heap_node_base<!constant_time_child_size> node_base;
|
||||
|
||||
public:
|
||||
typedef ValueType value_type;
|
||||
|
||||
typedef bi::list<node_base,
|
||||
bi::constant_time_size<constant_time_child_size> > child_list;
|
||||
|
||||
typedef typename child_list::iterator child_iterator;
|
||||
typedef typename child_list::const_iterator const_child_iterator;
|
||||
typedef typename child_list::size_type size_type;
|
||||
|
||||
heap_node(ValueType const & v):
|
||||
value(v)
|
||||
{}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class... Args>
|
||||
heap_node(Args&&... args):
|
||||
value(std::forward<Args>(args)...)
|
||||
{}
|
||||
#endif
|
||||
|
||||
/* protected: */
|
||||
heap_node(heap_node const & rhs):
|
||||
value(rhs.value)
|
||||
{
|
||||
/* we don't copy the child list, but clone it later */
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
template <typename Alloc>
|
||||
heap_node (heap_node const & rhs, Alloc & allocator):
|
||||
value(rhs.value)
|
||||
{
|
||||
children.clone_from(rhs.children, node_cloner<heap_node, node_base, Alloc>(allocator), nop_disposer());
|
||||
}
|
||||
|
||||
size_type child_count(void) const
|
||||
{
|
||||
BOOST_STATIC_ASSERT(constant_time_child_size);
|
||||
return children.size();
|
||||
}
|
||||
|
||||
void add_child(heap_node * n)
|
||||
{
|
||||
children.push_back(*n);
|
||||
}
|
||||
|
||||
template <typename Alloc>
|
||||
void clear_subtree(Alloc & alloc)
|
||||
{
|
||||
children.clear_and_dispose(node_disposer<heap_node, node_base, Alloc>(alloc));
|
||||
}
|
||||
|
||||
void swap_children(heap_node * rhs)
|
||||
{
|
||||
children.swap(rhs->children);
|
||||
}
|
||||
|
||||
ValueType value;
|
||||
child_list children;
|
||||
};
|
||||
|
||||
template <typename value_type>
|
||||
struct parent_pointing_heap_node:
|
||||
heap_node<value_type>
|
||||
{
|
||||
typedef heap_node<value_type> super_t;
|
||||
|
||||
parent_pointing_heap_node(value_type const & v):
|
||||
super_t(v), parent(NULL)
|
||||
{}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class... Args>
|
||||
parent_pointing_heap_node(Args&&... args):
|
||||
super_t(std::forward<Args>(args)...), parent(NULL)
|
||||
{}
|
||||
#endif
|
||||
|
||||
template <typename Alloc>
|
||||
struct node_cloner
|
||||
{
|
||||
node_cloner(Alloc & allocator, parent_pointing_heap_node * parent):
|
||||
allocator(allocator), parent_(parent)
|
||||
{}
|
||||
|
||||
parent_pointing_heap_node * operator() (typename super_t::node_base const & node)
|
||||
{
|
||||
parent_pointing_heap_node * ret = allocator.allocate(1);
|
||||
new (ret) parent_pointing_heap_node(static_cast<parent_pointing_heap_node const &>(node), allocator, parent_);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
Alloc & allocator;
|
||||
parent_pointing_heap_node * parent_;
|
||||
};
|
||||
|
||||
template <typename Alloc>
|
||||
parent_pointing_heap_node (parent_pointing_heap_node const & rhs, Alloc & allocator, parent_pointing_heap_node * parent):
|
||||
super_t(static_cast<super_t const &>(rhs)), parent(parent)
|
||||
{
|
||||
super_t::children.clone_from(rhs.children, node_cloner<Alloc>(allocator, this), nop_disposer());
|
||||
}
|
||||
|
||||
void update_children(void)
|
||||
{
|
||||
typedef heap_node_list::iterator node_list_iterator;
|
||||
for (node_list_iterator it = super_t::children.begin(); it != super_t::children.end(); ++it) {
|
||||
parent_pointing_heap_node * child = static_cast<parent_pointing_heap_node*>(&*it);
|
||||
child->parent = this;
|
||||
}
|
||||
}
|
||||
|
||||
void remove_from_parent(void)
|
||||
{
|
||||
BOOST_HEAP_ASSERT(parent);
|
||||
parent->children.erase(heap_node_list::s_iterator_to(*this));
|
||||
parent = NULL;
|
||||
}
|
||||
|
||||
void add_child(parent_pointing_heap_node * n)
|
||||
{
|
||||
BOOST_HEAP_ASSERT(n->parent == NULL);
|
||||
n->parent = this;
|
||||
super_t::add_child(n);
|
||||
}
|
||||
|
||||
parent_pointing_heap_node * get_parent(void)
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
const parent_pointing_heap_node * get_parent(void) const
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
parent_pointing_heap_node * parent;
|
||||
};
|
||||
|
||||
|
||||
template <typename value_type>
|
||||
struct marked_heap_node:
|
||||
parent_pointing_heap_node<value_type>
|
||||
{
|
||||
typedef parent_pointing_heap_node<value_type> super_t;
|
||||
|
||||
marked_heap_node(value_type const & v):
|
||||
super_t(v), mark(false)
|
||||
{}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class... Args>
|
||||
marked_heap_node(Args&&... args):
|
||||
super_t(std::forward<Args>(args)...), mark(false)
|
||||
{}
|
||||
#endif
|
||||
|
||||
marked_heap_node * get_parent(void)
|
||||
{
|
||||
return static_cast<marked_heap_node*>(super_t::parent);
|
||||
}
|
||||
|
||||
const marked_heap_node * get_parent(void) const
|
||||
{
|
||||
return static_cast<marked_heap_node*>(super_t::parent);
|
||||
}
|
||||
|
||||
bool mark;
|
||||
};
|
||||
|
||||
|
||||
template <typename Node>
|
||||
struct cmp_by_degree
|
||||
{
|
||||
template <typename NodeBase>
|
||||
bool operator()(NodeBase const & left,
|
||||
NodeBase const & right)
|
||||
{
|
||||
return static_cast<const Node*>(&left)->child_count() < static_cast<const Node*>(&right)->child_count();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename List, typename Node, typename Cmp>
|
||||
Node * find_max_child(List const & list, Cmp const & cmp)
|
||||
{
|
||||
BOOST_HEAP_ASSERT(!list.empty());
|
||||
|
||||
const Node * ret = static_cast<const Node *> (&list.front());
|
||||
for (typename List::const_iterator it = list.begin(); it != list.end(); ++it) {
|
||||
const Node * current = static_cast<const Node *> (&*it);
|
||||
|
||||
if (cmp(ret->value, current->value))
|
||||
ret = current;
|
||||
}
|
||||
|
||||
return const_cast<Node*>(ret);
|
||||
}
|
||||
|
||||
} /* namespace detail */
|
||||
} /* namespace heap */
|
||||
} /* namespace boost */
|
||||
|
||||
#undef BOOST_HEAP_ASSERT
|
||||
#endif /* BOOST_HEAP_DETAIL_HEAP_NODE_HPP */
|
||||
@@ -0,0 +1,64 @@
|
||||
// boost heap: integer log2
|
||||
//
|
||||
// Copyright (C) 2010 Tim Blechmann
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HEAP_DETAIL_ILOG2_HPP
|
||||
#define BOOST_HEAP_DETAIL_ILOG2_HPP
|
||||
|
||||
#include <string> // std::size_t
|
||||
|
||||
namespace boost {
|
||||
namespace heap {
|
||||
namespace detail {
|
||||
|
||||
template <typename IntType>
|
||||
struct log2
|
||||
{
|
||||
IntType operator()(IntType value)
|
||||
{
|
||||
IntType l = 0;
|
||||
while( (value >> l) > 1 )
|
||||
++l;
|
||||
return l;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef __GNUC__
|
||||
template<>
|
||||
struct log2<unsigned int>
|
||||
{
|
||||
unsigned int operator()(unsigned int value)
|
||||
{
|
||||
return sizeof(unsigned int)*8 - __builtin_clz(value - 1);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct log2<unsigned long>
|
||||
{
|
||||
unsigned long operator()(unsigned long value)
|
||||
{
|
||||
return sizeof(unsigned long)*8 - __builtin_clzl(value - 1);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} /* namespace detail */
|
||||
|
||||
|
||||
template <typename IntType>
|
||||
IntType log2(IntType value)
|
||||
{
|
||||
detail::log2<IntType> fn;
|
||||
return fn(value);
|
||||
}
|
||||
|
||||
} /* namespace heap */
|
||||
} /* namespace boost */
|
||||
|
||||
#endif /* BOOST_HEAP_DETAIL_ILOG2_HPP */
|
||||
@@ -0,0 +1,524 @@
|
||||
// boost heap
|
||||
//
|
||||
// Copyright (C) 2010 Tim Blechmann
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HEAP_DETAIL_MUTABLE_HEAP_HPP
|
||||
#define BOOST_HEAP_DETAIL_MUTABLE_HEAP_HPP
|
||||
|
||||
/*! \file
|
||||
* INTERNAL ONLY
|
||||
*/
|
||||
|
||||
#include <list>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/heap/detail/ordered_adaptor_iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace heap {
|
||||
namespace detail {
|
||||
|
||||
/* wrapper for a mutable heap container adaptors
|
||||
*
|
||||
* this wrapper introduces an additional indirection. the heap is not constructed from objects,
|
||||
* but instead from std::list iterators. this way, the mutability is achieved
|
||||
*
|
||||
*/
|
||||
template <typename PriorityQueueType>
|
||||
class priority_queue_mutable_wrapper
|
||||
{
|
||||
public:
|
||||
typedef typename PriorityQueueType::value_type value_type;
|
||||
typedef typename PriorityQueueType::size_type size_type;
|
||||
typedef typename PriorityQueueType::value_compare value_compare;
|
||||
typedef typename PriorityQueueType::allocator_type allocator_type;
|
||||
|
||||
typedef typename PriorityQueueType::reference reference;
|
||||
typedef typename PriorityQueueType::const_reference const_reference;
|
||||
typedef typename PriorityQueueType::pointer pointer;
|
||||
typedef typename PriorityQueueType::const_pointer const_pointer;
|
||||
static const bool is_stable = PriorityQueueType::is_stable;
|
||||
|
||||
private:
|
||||
typedef std::pair<value_type, size_type> node_type;
|
||||
|
||||
typedef std::list<node_type, typename allocator_type::template rebind<node_type>::other> object_list;
|
||||
|
||||
typedef typename object_list::iterator list_iterator;
|
||||
typedef typename object_list::const_iterator const_list_iterator;
|
||||
|
||||
template <typename Heap1, typename Heap2>
|
||||
friend struct heap_merge_emulate;
|
||||
|
||||
typedef typename PriorityQueueType::super_t::stability_counter_type stability_counter_type;
|
||||
|
||||
stability_counter_type get_stability_count(void) const
|
||||
{
|
||||
return q_.get_stability_count();
|
||||
}
|
||||
|
||||
void set_stability_count(stability_counter_type new_count)
|
||||
{
|
||||
q_.set_stability_count(new_count);
|
||||
}
|
||||
|
||||
struct index_updater
|
||||
{
|
||||
template <typename It>
|
||||
static void run(It & it, size_type new_index)
|
||||
{
|
||||
q_type::get_value(it)->second = new_index;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
struct handle_type
|
||||
{
|
||||
value_type & operator*() const
|
||||
{
|
||||
return iterator->first;
|
||||
}
|
||||
|
||||
handle_type (void)
|
||||
{}
|
||||
|
||||
handle_type(handle_type const & rhs):
|
||||
iterator(rhs.iterator)
|
||||
{}
|
||||
|
||||
bool operator==(handle_type const & rhs) const
|
||||
{
|
||||
return iterator == rhs.iterator;
|
||||
}
|
||||
|
||||
bool operator!=(handle_type const & rhs) const
|
||||
{
|
||||
return iterator != rhs.iterator;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit handle_type(list_iterator const & it):
|
||||
iterator(it)
|
||||
{}
|
||||
|
||||
list_iterator iterator;
|
||||
|
||||
friend class priority_queue_mutable_wrapper;
|
||||
};
|
||||
|
||||
private:
|
||||
struct indirect_cmp:
|
||||
public value_compare
|
||||
{
|
||||
indirect_cmp(value_compare const & cmp = value_compare()):
|
||||
value_compare(cmp)
|
||||
{}
|
||||
|
||||
bool operator()(const_list_iterator const & lhs, const_list_iterator const & rhs) const
|
||||
{
|
||||
return value_compare::operator()(lhs->first, rhs->first);
|
||||
}
|
||||
};
|
||||
|
||||
typedef typename PriorityQueueType::template rebind<list_iterator,
|
||||
indirect_cmp,
|
||||
allocator_type, index_updater >::other q_type;
|
||||
|
||||
protected:
|
||||
q_type q_;
|
||||
object_list objects;
|
||||
|
||||
protected:
|
||||
priority_queue_mutable_wrapper(value_compare const & cmp = value_compare()):
|
||||
q_(cmp)
|
||||
{}
|
||||
|
||||
priority_queue_mutable_wrapper(priority_queue_mutable_wrapper const & rhs):
|
||||
q_(rhs.q_), objects(rhs.objects)
|
||||
{
|
||||
for (typename object_list::iterator it = objects.begin(); it != objects.end(); ++it)
|
||||
q_.push(it);
|
||||
}
|
||||
|
||||
priority_queue_mutable_wrapper & operator=(priority_queue_mutable_wrapper const & rhs)
|
||||
{
|
||||
q_ = rhs.q_;
|
||||
objects = rhs.objects;
|
||||
q_.clear();
|
||||
for (typename object_list::iterator it = objects.begin(); it != objects.end(); ++it)
|
||||
q_.push(it);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
priority_queue_mutable_wrapper (priority_queue_mutable_wrapper && rhs):
|
||||
q_(std::move(rhs.q_))
|
||||
{
|
||||
/// FIXME: msvc seems to invalidate iterators when moving std::list
|
||||
std::swap(objects, rhs.objects);
|
||||
}
|
||||
|
||||
priority_queue_mutable_wrapper & operator=(priority_queue_mutable_wrapper && rhs)
|
||||
{
|
||||
q_ = std::move(rhs.q_);
|
||||
objects.clear();
|
||||
std::swap(objects, rhs.objects);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
public:
|
||||
template <typename iterator_type>
|
||||
class iterator_base:
|
||||
public boost::iterator_adaptor<iterator_base<iterator_type>,
|
||||
iterator_type,
|
||||
value_type const,
|
||||
boost::bidirectional_traversal_tag>
|
||||
{
|
||||
typedef boost::iterator_adaptor<iterator_base<iterator_type>,
|
||||
iterator_type,
|
||||
value_type const,
|
||||
boost::bidirectional_traversal_tag> super_t;
|
||||
|
||||
friend class boost::iterator_core_access;
|
||||
friend class priority_queue_mutable_wrapper;
|
||||
|
||||
iterator_base(void):
|
||||
super_t(0)
|
||||
{}
|
||||
|
||||
template <typename T>
|
||||
explicit iterator_base(T const & it):
|
||||
super_t(it)
|
||||
{}
|
||||
|
||||
value_type const & dereference() const
|
||||
{
|
||||
return super_t::base()->first;
|
||||
}
|
||||
|
||||
iterator_type get_list_iterator() const
|
||||
{
|
||||
return super_t::base_reference();
|
||||
}
|
||||
};
|
||||
|
||||
typedef iterator_base<list_iterator> iterator;
|
||||
typedef iterator_base<const_list_iterator> const_iterator;
|
||||
|
||||
typedef typename object_list::difference_type difference_type;
|
||||
|
||||
class ordered_iterator:
|
||||
public boost::iterator_adaptor<ordered_iterator,
|
||||
const_list_iterator,
|
||||
value_type const,
|
||||
boost::forward_traversal_tag
|
||||
>,
|
||||
q_type::ordered_iterator_dispatcher
|
||||
{
|
||||
typedef boost::iterator_adaptor<ordered_iterator,
|
||||
const_list_iterator,
|
||||
value_type const,
|
||||
boost::forward_traversal_tag
|
||||
> adaptor_type;
|
||||
|
||||
typedef const_list_iterator iterator;
|
||||
typedef typename q_type::ordered_iterator_dispatcher ordered_iterator_dispatcher;
|
||||
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
public:
|
||||
ordered_iterator(void):
|
||||
adaptor_type(0), unvisited_nodes(indirect_cmp()), q_(NULL)
|
||||
{}
|
||||
|
||||
ordered_iterator(const priority_queue_mutable_wrapper * q, indirect_cmp const & cmp):
|
||||
adaptor_type(0), unvisited_nodes(cmp), q_(q)
|
||||
{}
|
||||
|
||||
ordered_iterator(const_list_iterator it, const priority_queue_mutable_wrapper * q, indirect_cmp const & cmp):
|
||||
adaptor_type(it), unvisited_nodes(cmp), q_(q)
|
||||
{
|
||||
if (it != q->objects.end())
|
||||
discover_nodes(it);
|
||||
}
|
||||
|
||||
bool operator!=(ordered_iterator const & rhs) const
|
||||
{
|
||||
return adaptor_type::base() != rhs.base();
|
||||
}
|
||||
|
||||
bool operator==(ordered_iterator const & rhs) const
|
||||
{
|
||||
return !operator!=(rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
void increment(void)
|
||||
{
|
||||
if (unvisited_nodes.empty())
|
||||
adaptor_type::base_reference() = q_->objects.end();
|
||||
else {
|
||||
iterator next = unvisited_nodes.top();
|
||||
unvisited_nodes.pop();
|
||||
discover_nodes(next);
|
||||
adaptor_type::base_reference() = next;
|
||||
}
|
||||
}
|
||||
|
||||
value_type const & dereference() const
|
||||
{
|
||||
return adaptor_type::base()->first;
|
||||
}
|
||||
|
||||
void discover_nodes(iterator current)
|
||||
{
|
||||
size_type current_index = current->second;
|
||||
const q_type * q = &(q_->q_);
|
||||
|
||||
if (ordered_iterator_dispatcher::is_leaf(q, current_index))
|
||||
return;
|
||||
|
||||
std::pair<size_type, size_type> child_range = ordered_iterator_dispatcher::get_child_nodes(q, current_index);
|
||||
|
||||
for (size_type i = child_range.first; i <= child_range.second; ++i) {
|
||||
typename q_type::internal_type const & internal_value_at_index = ordered_iterator_dispatcher::get_internal_value(q, i);
|
||||
typename q_type::value_type const & value_at_index = q_->q_.get_value(internal_value_at_index);
|
||||
|
||||
unvisited_nodes.push(value_at_index);
|
||||
}
|
||||
}
|
||||
|
||||
std::priority_queue<iterator,
|
||||
std::vector<iterator, typename allocator_type::template rebind<iterator>::other >,
|
||||
indirect_cmp
|
||||
> unvisited_nodes;
|
||||
const priority_queue_mutable_wrapper * q_;
|
||||
};
|
||||
|
||||
bool empty(void) const
|
||||
{
|
||||
return q_.empty();
|
||||
}
|
||||
|
||||
size_type size(void) const
|
||||
{
|
||||
return q_.size();
|
||||
}
|
||||
|
||||
size_type max_size(void) const
|
||||
{
|
||||
return objects.max_size();
|
||||
}
|
||||
|
||||
void clear(void)
|
||||
{
|
||||
q_.clear();
|
||||
objects.clear();
|
||||
}
|
||||
|
||||
allocator_type get_allocator(void) const
|
||||
{
|
||||
return q_.get_allocator();
|
||||
}
|
||||
|
||||
void swap(priority_queue_mutable_wrapper & rhs)
|
||||
{
|
||||
objects.swap(rhs.objects);
|
||||
q_.swap(rhs.q_);
|
||||
}
|
||||
|
||||
const_reference top(void) const
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
return q_.top()->first;
|
||||
}
|
||||
|
||||
handle_type push(value_type const & v)
|
||||
{
|
||||
objects.push_front(std::make_pair(v, 0));
|
||||
list_iterator ret = objects.begin();
|
||||
q_.push(ret);
|
||||
return handle_type(ret);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class... Args>
|
||||
handle_type emplace(Args&&... args)
|
||||
{
|
||||
objects.push_front(std::make_pair(std::forward<Args>(args)..., 0));
|
||||
list_iterator ret = objects.begin();
|
||||
q_.push(ret);
|
||||
return handle_type(ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
void pop(void)
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
list_iterator q_top = q_.top();
|
||||
q_.pop();
|
||||
objects.erase(q_top);
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
|
||||
*
|
||||
* \b Complexity: Logarithmic.
|
||||
*
|
||||
* */
|
||||
void update(handle_type handle, const_reference v)
|
||||
{
|
||||
list_iterator it = handle.iterator;
|
||||
value_type const & current_value = it->first;
|
||||
value_compare const & cmp = q_.value_comp();
|
||||
if (cmp(v, current_value))
|
||||
decrease(handle, v);
|
||||
else
|
||||
increase(handle, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
|
||||
*
|
||||
* \b Complexity: Logarithmic.
|
||||
*
|
||||
* \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
|
||||
* */
|
||||
void update(handle_type handle)
|
||||
{
|
||||
list_iterator it = handle.iterator;
|
||||
size_type index = it->second;
|
||||
q_.update(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
|
||||
*
|
||||
* \b Complexity: Logarithmic.
|
||||
*
|
||||
* \b Note: The new value is expected to be greater than the current one
|
||||
* */
|
||||
void increase(handle_type handle, const_reference v)
|
||||
{
|
||||
BOOST_ASSERT(!value_compare()(v, handle.iterator->first));
|
||||
handle.iterator->first = v;
|
||||
increase(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
|
||||
*
|
||||
* \b Complexity: Logarithmic.
|
||||
*
|
||||
* \b Note: The new value is expected to be greater than the current one. If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
|
||||
* */
|
||||
void increase(handle_type handle)
|
||||
{
|
||||
list_iterator it = handle.iterator;
|
||||
size_type index = it->second;
|
||||
q_.increase(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
|
||||
*
|
||||
* \b Complexity: Logarithmic.
|
||||
*
|
||||
* \b Note: The new value is expected to be less than the current one
|
||||
* */
|
||||
void decrease(handle_type handle, const_reference v)
|
||||
{
|
||||
BOOST_ASSERT(!value_compare()(handle.iterator->first, v));
|
||||
handle.iterator->first = v;
|
||||
decrease(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
|
||||
*
|
||||
* \b Complexity: Logarithmic.
|
||||
*
|
||||
* \b Note: The new value is expected to be less than the current one. If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
|
||||
* */
|
||||
void decrease(handle_type handle)
|
||||
{
|
||||
list_iterator it = handle.iterator;
|
||||
size_type index = it->second;
|
||||
q_.decrease(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* \b Effects: Removes the element handled by \c handle from the priority_queue.
|
||||
*
|
||||
* \b Complexity: Logarithmic.
|
||||
* */
|
||||
void erase(handle_type handle)
|
||||
{
|
||||
list_iterator it = handle.iterator;
|
||||
size_type index = it->second;
|
||||
q_.erase(index);
|
||||
objects.erase(it);
|
||||
}
|
||||
|
||||
const_iterator begin(void) const
|
||||
{
|
||||
return const_iterator(objects.begin());
|
||||
}
|
||||
|
||||
const_iterator end(void) const
|
||||
{
|
||||
return const_iterator(objects.end());
|
||||
}
|
||||
|
||||
iterator begin(void)
|
||||
{
|
||||
return iterator(objects.begin());
|
||||
}
|
||||
|
||||
iterator end(void)
|
||||
{
|
||||
return iterator(objects.end());
|
||||
}
|
||||
|
||||
ordered_iterator ordered_begin(void) const
|
||||
{
|
||||
if (!empty())
|
||||
return ordered_iterator(q_.top(), this, indirect_cmp(q_.value_comp()));
|
||||
else
|
||||
return ordered_end();
|
||||
}
|
||||
|
||||
ordered_iterator ordered_end(void) const
|
||||
{
|
||||
return ordered_iterator(objects.end(), this, indirect_cmp(q_.value_comp()));
|
||||
}
|
||||
|
||||
static handle_type s_handle_from_iterator(iterator const & it)
|
||||
{
|
||||
return handle_type(it.get_list_iterator());
|
||||
}
|
||||
|
||||
value_compare const & value_comp(void) const
|
||||
{
|
||||
return q_.value_comp();
|
||||
}
|
||||
|
||||
void reserve (size_type element_count)
|
||||
{
|
||||
q_.reserve(element_count);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} /* namespace detail */
|
||||
} /* namespace heap */
|
||||
} /* namespace boost */
|
||||
|
||||
#endif /* BOOST_HEAP_DETAIL_MUTABLE_HEAP_HPP */
|
||||
@@ -0,0 +1,146 @@
|
||||
// boost heap: ordered iterator helper classes for container adaptors
|
||||
//
|
||||
// Copyright (C) 2011 Tim Blechmann
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HEAP_DETAIL_ORDERED_ADAPTOR_ITERATOR_HPP
|
||||
#define BOOST_HEAP_DETAIL_ORDERED_ADAPTOR_ITERATOR_HPP
|
||||
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/heap/detail/tree_iterator.hpp>
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/concept_check.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace heap {
|
||||
namespace detail {
|
||||
|
||||
/* ordered iterator helper classes for container adaptors
|
||||
*
|
||||
* Requirements for Dispatcher:
|
||||
*
|
||||
* * static size_type max_index(const ContainerType * heap); // return maximum index
|
||||
* * static bool is_leaf(const ContainerType * heap, size_type index); // return if index denotes a leaf
|
||||
* * static std::pair<size_type, size_type> get_child_nodes(const ContainerType * heap, size_type index); // get index range of child nodes
|
||||
* * static internal_type const & get_internal_value(const ContainerType * heap, size_type index); // get internal value at index
|
||||
* * static value_type const & get_value(internal_type const & arg) const; // get value_type from internal_type
|
||||
*
|
||||
* */
|
||||
template <typename ValueType,
|
||||
typename InternalType,
|
||||
typename ContainerType,
|
||||
typename Alloc,
|
||||
typename ValueCompare,
|
||||
typename Dispatcher
|
||||
>
|
||||
class ordered_adaptor_iterator:
|
||||
public boost::iterator_facade<ordered_adaptor_iterator<ValueType,
|
||||
InternalType,
|
||||
ContainerType,
|
||||
Alloc,
|
||||
ValueCompare,
|
||||
Dispatcher>,
|
||||
ValueType,
|
||||
boost::forward_traversal_tag
|
||||
>,
|
||||
Dispatcher
|
||||
{
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
struct compare_by_heap_value:
|
||||
ValueCompare
|
||||
{
|
||||
const ContainerType * container;
|
||||
|
||||
compare_by_heap_value (const ContainerType * container, ValueCompare const & cmp):
|
||||
ValueCompare(cmp), container(container)
|
||||
{}
|
||||
|
||||
bool operator()(size_t lhs, size_t rhs)
|
||||
{
|
||||
BOOST_ASSERT(lhs <= Dispatcher::max_index(container));
|
||||
BOOST_ASSERT(rhs <= Dispatcher::max_index(container));
|
||||
return ValueCompare::operator()(Dispatcher::get_internal_value(container, lhs),
|
||||
Dispatcher::get_internal_value(container, rhs));
|
||||
}
|
||||
};
|
||||
|
||||
const ContainerType * container;
|
||||
size_t current_index; // current index: special value -1 denotes `end' iterator
|
||||
|
||||
public:
|
||||
ordered_adaptor_iterator(void):
|
||||
container(NULL), current_index((std::numeric_limits<size_t>::max)()),
|
||||
unvisited_nodes(compare_by_heap_value(NULL, ValueCompare()))
|
||||
{}
|
||||
|
||||
ordered_adaptor_iterator(const ContainerType * container, ValueCompare const & cmp):
|
||||
container(container), current_index(container->size()),
|
||||
unvisited_nodes(compare_by_heap_value(container, ValueCompare()))
|
||||
{}
|
||||
|
||||
ordered_adaptor_iterator(size_t initial_index, const ContainerType * container, ValueCompare const & cmp):
|
||||
container(container), current_index(initial_index),
|
||||
unvisited_nodes(compare_by_heap_value(container, cmp))
|
||||
{
|
||||
discover_nodes(initial_index);
|
||||
}
|
||||
|
||||
private:
|
||||
bool equal (ordered_adaptor_iterator const & rhs) const
|
||||
{
|
||||
if (current_index != rhs.current_index)
|
||||
return false;
|
||||
|
||||
if (container != rhs.container) // less likely than first check
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void increment(void)
|
||||
{
|
||||
if (unvisited_nodes.empty())
|
||||
current_index = Dispatcher::max_index(container) + 1;
|
||||
else {
|
||||
current_index = unvisited_nodes.top();
|
||||
unvisited_nodes.pop();
|
||||
discover_nodes(current_index);
|
||||
}
|
||||
}
|
||||
|
||||
ValueType const & dereference() const
|
||||
{
|
||||
BOOST_ASSERT(current_index <= Dispatcher::max_index(container));
|
||||
return Dispatcher::get_value(Dispatcher::get_internal_value(container, current_index));
|
||||
}
|
||||
|
||||
void discover_nodes(size_t index)
|
||||
{
|
||||
if (Dispatcher::is_leaf(container, index))
|
||||
return;
|
||||
|
||||
std::pair<size_t, size_t> child_range = Dispatcher::get_child_nodes(container, index);
|
||||
|
||||
for (size_t i = child_range.first; i <= child_range.second; ++i)
|
||||
unvisited_nodes.push(i);
|
||||
}
|
||||
|
||||
std::priority_queue<size_t,
|
||||
std::vector<size_t, typename Alloc::template rebind<size_t>::other >,
|
||||
compare_by_heap_value
|
||||
> unvisited_nodes;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace detail */
|
||||
} /* namespace heap */
|
||||
} /* namespace boost */
|
||||
|
||||
#endif /* BOOST_HEAP_DETAIL_ORDERED_ADAPTOR_ITERATOR_HPP */
|
||||
@@ -0,0 +1,582 @@
|
||||
// boost heap: helper classes for stable priority queues
|
||||
//
|
||||
// Copyright (C) 2010 Tim Blechmann
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HEAP_DETAIL_STABLE_HEAP_HPP
|
||||
#define BOOST_HEAP_DETAIL_STABLE_HEAP_HPP
|
||||
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
|
||||
#include <boost/heap/policies.hpp>
|
||||
#include <boost/heap/heap_merge.hpp>
|
||||
|
||||
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
|
||||
#include <boost/type_traits/is_nothrow_move_assignable.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace heap {
|
||||
namespace detail {
|
||||
|
||||
template<bool ConstantSize, class SizeType>
|
||||
struct size_holder
|
||||
{
|
||||
static const bool constant_time_size = ConstantSize;
|
||||
typedef SizeType size_type;
|
||||
|
||||
size_holder(void) BOOST_NOEXCEPT:
|
||||
size_(0)
|
||||
{}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
size_holder(size_holder && rhs) BOOST_NOEXCEPT:
|
||||
size_(rhs.size_)
|
||||
{
|
||||
rhs.size_ = 0;
|
||||
}
|
||||
|
||||
size_holder(size_holder const & rhs) BOOST_NOEXCEPT:
|
||||
size_(rhs.size_)
|
||||
{}
|
||||
|
||||
size_holder & operator=(size_holder && rhs) BOOST_NOEXCEPT
|
||||
{
|
||||
size_ = rhs.size_;
|
||||
rhs.size_ = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
size_holder & operator=(size_holder const & rhs) BOOST_NOEXCEPT
|
||||
{
|
||||
size_ = rhs.size_;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
SizeType get_size() const BOOST_NOEXCEPT
|
||||
{ return size_; }
|
||||
|
||||
void set_size(SizeType size) BOOST_NOEXCEPT
|
||||
{ size_ = size; }
|
||||
|
||||
void decrement() BOOST_NOEXCEPT
|
||||
{ --size_; }
|
||||
|
||||
void increment() BOOST_NOEXCEPT
|
||||
{ ++size_; }
|
||||
|
||||
void add(SizeType value) BOOST_NOEXCEPT
|
||||
{ size_ += value; }
|
||||
|
||||
void sub(SizeType value) BOOST_NOEXCEPT
|
||||
{ size_ -= value; }
|
||||
|
||||
void swap(size_holder & rhs) BOOST_NOEXCEPT
|
||||
{ std::swap(size_, rhs.size_); }
|
||||
|
||||
SizeType size_;
|
||||
};
|
||||
|
||||
template<class SizeType>
|
||||
struct size_holder<false, SizeType>
|
||||
{
|
||||
static const bool constant_time_size = false;
|
||||
typedef SizeType size_type;
|
||||
|
||||
size_holder(void) BOOST_NOEXCEPT
|
||||
{}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
size_holder(size_holder && rhs) BOOST_NOEXCEPT
|
||||
{}
|
||||
|
||||
size_holder(size_holder const & rhs) BOOST_NOEXCEPT
|
||||
{}
|
||||
|
||||
size_holder & operator=(size_holder && rhs) BOOST_NOEXCEPT
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
size_holder & operator=(size_holder const & rhs) BOOST_NOEXCEPT
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_type get_size() const BOOST_NOEXCEPT
|
||||
{ return 0; }
|
||||
|
||||
void set_size(size_type) BOOST_NOEXCEPT
|
||||
{}
|
||||
|
||||
void decrement() BOOST_NOEXCEPT
|
||||
{}
|
||||
|
||||
void increment() BOOST_NOEXCEPT
|
||||
{}
|
||||
|
||||
void add(SizeType /*value*/) BOOST_NOEXCEPT
|
||||
{}
|
||||
|
||||
void sub(SizeType /*value*/) BOOST_NOEXCEPT
|
||||
{}
|
||||
|
||||
void swap(size_holder & /*rhs*/) BOOST_NOEXCEPT
|
||||
{}
|
||||
};
|
||||
|
||||
// note: MSVC does not implement lookup correctly, we therefore have to place the Cmp object as member inside the
|
||||
// struct. of course, this prevents EBO and significantly reduces the readability of this code
|
||||
template <typename T,
|
||||
typename Cmp,
|
||||
bool constant_time_size,
|
||||
typename StabilityCounterType = boost::uintmax_t,
|
||||
bool stable = false
|
||||
>
|
||||
struct heap_base:
|
||||
#ifndef BOOST_MSVC
|
||||
Cmp,
|
||||
#endif
|
||||
size_holder<constant_time_size, size_t>
|
||||
{
|
||||
typedef StabilityCounterType stability_counter_type;
|
||||
typedef T value_type;
|
||||
typedef T internal_type;
|
||||
typedef size_holder<constant_time_size, size_t> size_holder_type;
|
||||
typedef Cmp value_compare;
|
||||
typedef Cmp internal_compare;
|
||||
static const bool is_stable = stable;
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
Cmp cmp_;
|
||||
#endif
|
||||
|
||||
heap_base (Cmp const & cmp = Cmp()):
|
||||
#ifndef BOOST_MSVC
|
||||
Cmp(cmp)
|
||||
#else
|
||||
cmp_(cmp)
|
||||
#endif
|
||||
{}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
heap_base(heap_base && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<Cmp>::value):
|
||||
#ifndef BOOST_MSVC
|
||||
Cmp(std::move(static_cast<Cmp&>(rhs))),
|
||||
#else
|
||||
cmp_(std::move(rhs.cmp_)),
|
||||
#endif
|
||||
size_holder_type(std::move(static_cast<size_holder_type&>(rhs)))
|
||||
{}
|
||||
|
||||
heap_base(heap_base const & rhs):
|
||||
#ifndef BOOST_MSVC
|
||||
Cmp(static_cast<Cmp const &>(rhs)),
|
||||
#else
|
||||
cmp_(rhs.value_comp()),
|
||||
#endif
|
||||
size_holder_type(static_cast<size_holder_type const &>(rhs))
|
||||
{}
|
||||
|
||||
heap_base & operator=(heap_base && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_assignable<Cmp>::value)
|
||||
{
|
||||
value_comp_ref().operator=(std::move(rhs.value_comp_ref()));
|
||||
size_holder_type::operator=(std::move(static_cast<size_holder_type&>(rhs)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
heap_base & operator=(heap_base const & rhs)
|
||||
{
|
||||
value_comp_ref().operator=(rhs.value_comp());
|
||||
size_holder_type::operator=(static_cast<size_holder_type const &>(rhs));
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool operator()(internal_type const & lhs, internal_type const & rhs) const
|
||||
{
|
||||
return value_comp().operator()(lhs, rhs);
|
||||
}
|
||||
|
||||
internal_type make_node(T const & val)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
T && make_node(T && val)
|
||||
{
|
||||
return std::forward<T>(val);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class... Args>
|
||||
internal_type make_node(Args && ... val)
|
||||
{
|
||||
return internal_type(std::forward<Args>(val)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
static T & get_value(internal_type & val) BOOST_NOEXCEPT
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
static T const & get_value(internal_type const & val) BOOST_NOEXCEPT
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
Cmp const & value_comp(void) const BOOST_NOEXCEPT
|
||||
{
|
||||
#ifndef BOOST_MSVC
|
||||
return *this;
|
||||
#else
|
||||
return cmp_;
|
||||
#endif
|
||||
}
|
||||
|
||||
Cmp const & get_internal_cmp(void) const BOOST_NOEXCEPT
|
||||
{
|
||||
return value_comp();
|
||||
}
|
||||
|
||||
void swap(heap_base & rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<Cmp>::value && boost::is_nothrow_move_assignable<Cmp>::value)
|
||||
{
|
||||
std::swap(value_comp_ref(), rhs.value_comp_ref());
|
||||
size_holder<constant_time_size, size_t>::swap(rhs);
|
||||
}
|
||||
|
||||
stability_counter_type get_stability_count(void) const BOOST_NOEXCEPT
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_stability_count(stability_counter_type) BOOST_NOEXCEPT
|
||||
{}
|
||||
|
||||
template <typename Heap1, typename Heap2>
|
||||
friend struct heap_merge_emulate;
|
||||
|
||||
private:
|
||||
Cmp & value_comp_ref(void)
|
||||
{
|
||||
#ifndef BOOST_MSVC
|
||||
return *this;
|
||||
#else
|
||||
return cmp_;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename T,
|
||||
typename Cmp,
|
||||
bool constant_time_size,
|
||||
typename StabilityCounterType
|
||||
>
|
||||
struct heap_base<T, Cmp, constant_time_size, StabilityCounterType, true>:
|
||||
#ifndef BOOST_MSVC
|
||||
Cmp,
|
||||
#endif
|
||||
size_holder<constant_time_size, size_t>
|
||||
{
|
||||
typedef StabilityCounterType stability_counter_type;
|
||||
typedef T value_type;
|
||||
|
||||
struct internal_type
|
||||
{
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class ...Args>
|
||||
internal_type(stability_counter_type cnt, Args && ... args):
|
||||
first(std::forward<Args>(args)...), second(cnt)
|
||||
{}
|
||||
#endif
|
||||
|
||||
internal_type(stability_counter_type const & cnt, T const & value):
|
||||
first(value), second(cnt)
|
||||
{}
|
||||
|
||||
T first;
|
||||
stability_counter_type second;
|
||||
};
|
||||
|
||||
typedef size_holder<constant_time_size, size_t> size_holder_type;
|
||||
typedef Cmp value_compare;
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
Cmp cmp_;
|
||||
#endif
|
||||
|
||||
heap_base (Cmp const & cmp = Cmp()):
|
||||
#ifndef BOOST_MSVC
|
||||
Cmp(cmp),
|
||||
#else
|
||||
cmp_(cmp),
|
||||
#endif
|
||||
counter_(0)
|
||||
{}
|
||||
|
||||
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
heap_base(heap_base && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<Cmp>::value):
|
||||
#ifndef BOOST_MSVC
|
||||
Cmp(std::move(static_cast<Cmp&>(rhs))),
|
||||
#else
|
||||
cmp_(std::move(rhs.cmp_)),
|
||||
#endif
|
||||
size_holder_type(std::move(static_cast<size_holder_type&>(rhs))), counter_(rhs.counter_)
|
||||
{
|
||||
rhs.counter_ = 0;
|
||||
}
|
||||
|
||||
heap_base(heap_base const & rhs):
|
||||
#ifndef BOOST_MSVC
|
||||
Cmp(static_cast<Cmp const&>(rhs)),
|
||||
#else
|
||||
cmp_(rhs.value_comp()),
|
||||
#endif
|
||||
size_holder_type(static_cast<size_holder_type const &>(rhs)), counter_(rhs.counter_)
|
||||
{}
|
||||
|
||||
heap_base & operator=(heap_base && rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_assignable<Cmp>::value)
|
||||
{
|
||||
value_comp_ref().operator=(std::move(rhs.value_comp_ref()));
|
||||
size_holder_type::operator=(std::move(static_cast<size_holder_type&>(rhs)));
|
||||
|
||||
counter_ = rhs.counter_;
|
||||
rhs.counter_ = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
heap_base & operator=(heap_base const & rhs)
|
||||
{
|
||||
value_comp_ref().operator=(rhs.value_comp());
|
||||
size_holder_type::operator=(static_cast<size_holder_type const &>(rhs));
|
||||
|
||||
counter_ = rhs.counter_;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool operator()(internal_type const & lhs, internal_type const & rhs) const
|
||||
{
|
||||
return get_internal_cmp()(lhs, rhs);
|
||||
}
|
||||
|
||||
bool operator()(T const & lhs, T const & rhs) const
|
||||
{
|
||||
return value_comp()(lhs, rhs);
|
||||
}
|
||||
|
||||
internal_type make_node(T const & val)
|
||||
{
|
||||
stability_counter_type count = ++counter_;
|
||||
if (counter_ == (std::numeric_limits<stability_counter_type>::max)())
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("boost::heap counter overflow"));
|
||||
return internal_type(count, val);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template <class... Args>
|
||||
internal_type make_node(Args&&... args)
|
||||
{
|
||||
stability_counter_type count = ++counter_;
|
||||
if (counter_ == (std::numeric_limits<stability_counter_type>::max)())
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("boost::heap counter overflow"));
|
||||
return internal_type (count, std::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
|
||||
static T & get_value(internal_type & val) BOOST_NOEXCEPT
|
||||
{
|
||||
return val.first;
|
||||
}
|
||||
|
||||
static T const & get_value(internal_type const & val) BOOST_NOEXCEPT
|
||||
{
|
||||
return val.first;
|
||||
}
|
||||
|
||||
Cmp const & value_comp(void) const BOOST_NOEXCEPT
|
||||
{
|
||||
#ifndef BOOST_MSVC
|
||||
return *this;
|
||||
#else
|
||||
return cmp_;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct internal_compare:
|
||||
Cmp
|
||||
{
|
||||
internal_compare(Cmp const & cmp = Cmp()):
|
||||
Cmp(cmp)
|
||||
{}
|
||||
|
||||
bool operator()(internal_type const & lhs, internal_type const & rhs) const
|
||||
{
|
||||
if (Cmp::operator()(lhs.first, rhs.first))
|
||||
return true;
|
||||
|
||||
if (Cmp::operator()(rhs.first, lhs.first))
|
||||
return false;
|
||||
|
||||
return lhs.second > rhs.second;
|
||||
}
|
||||
};
|
||||
|
||||
internal_compare get_internal_cmp(void) const
|
||||
{
|
||||
return internal_compare(value_comp());
|
||||
}
|
||||
|
||||
void swap(heap_base & rhs) BOOST_NOEXCEPT_IF(boost::is_nothrow_move_constructible<Cmp>::value && boost::is_nothrow_move_assignable<Cmp>::value)
|
||||
{
|
||||
#ifndef BOOST_MSVC
|
||||
std::swap(static_cast<Cmp&>(*this), static_cast<Cmp&>(rhs));
|
||||
#else
|
||||
std::swap(cmp_, rhs.cmp_);
|
||||
#endif
|
||||
std::swap(counter_, rhs.counter_);
|
||||
size_holder<constant_time_size, size_t>::swap(rhs);
|
||||
}
|
||||
|
||||
stability_counter_type get_stability_count(void) const
|
||||
{
|
||||
return counter_;
|
||||
}
|
||||
|
||||
void set_stability_count(stability_counter_type new_count)
|
||||
{
|
||||
counter_ = new_count;
|
||||
}
|
||||
|
||||
template <typename Heap1, typename Heap2>
|
||||
friend struct heap_merge_emulate;
|
||||
|
||||
private:
|
||||
Cmp & value_comp_ref(void) BOOST_NOEXCEPT
|
||||
{
|
||||
#ifndef BOOST_MSVC
|
||||
return *this;
|
||||
#else
|
||||
return cmp_;
|
||||
#endif
|
||||
}
|
||||
|
||||
stability_counter_type counter_;
|
||||
};
|
||||
|
||||
template <typename node_pointer,
|
||||
typename extractor,
|
||||
typename reference
|
||||
>
|
||||
struct node_handle
|
||||
{
|
||||
explicit node_handle(node_pointer n = 0):
|
||||
node_(n)
|
||||
{}
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
return extractor::get_value(node_->value);
|
||||
}
|
||||
|
||||
bool operator==(node_handle const & rhs) const
|
||||
{
|
||||
return node_ == rhs.node_;
|
||||
}
|
||||
|
||||
bool operator!=(node_handle const & rhs) const
|
||||
{
|
||||
return node_ != rhs.node_;
|
||||
}
|
||||
|
||||
node_pointer node_;
|
||||
};
|
||||
|
||||
template <typename value_type,
|
||||
typename internal_type,
|
||||
typename extractor
|
||||
>
|
||||
struct value_extractor
|
||||
{
|
||||
value_type const & operator()(internal_type const & data) const
|
||||
{
|
||||
return extractor::get_value(data);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T,
|
||||
typename ContainerIterator,
|
||||
typename Extractor>
|
||||
class stable_heap_iterator:
|
||||
public boost::iterator_adaptor<stable_heap_iterator<T, ContainerIterator, Extractor>,
|
||||
ContainerIterator,
|
||||
T const,
|
||||
boost::random_access_traversal_tag>
|
||||
{
|
||||
typedef boost::iterator_adaptor<stable_heap_iterator,
|
||||
ContainerIterator,
|
||||
T const,
|
||||
boost::random_access_traversal_tag> super_t;
|
||||
|
||||
public:
|
||||
stable_heap_iterator(void):
|
||||
super_t(0)
|
||||
{}
|
||||
|
||||
explicit stable_heap_iterator(ContainerIterator const & it):
|
||||
super_t(it)
|
||||
{}
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
T const & dereference() const
|
||||
{
|
||||
return Extractor::get_value(*super_t::base());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Parspec, bool constant_time_size>
|
||||
struct make_heap_base
|
||||
{
|
||||
typedef typename parameter::binding<Parspec, tag::compare, std::less<T> >::type compare_argument;
|
||||
typedef typename parameter::binding<Parspec, tag::allocator, std::allocator<T> >::type allocator_argument;
|
||||
typedef typename parameter::binding<Parspec, tag::stability_counter_type, boost::uintmax_t >::type stability_counter_type;
|
||||
|
||||
static const bool is_stable = extract_stable<Parspec>::value;
|
||||
|
||||
typedef heap_base<T, compare_argument, constant_time_size, stability_counter_type, is_stable> type;
|
||||
};
|
||||
|
||||
|
||||
template <typename Alloc>
|
||||
struct extract_allocator_types
|
||||
{
|
||||
typedef typename Alloc::size_type size_type;
|
||||
typedef typename Alloc::difference_type difference_type;
|
||||
typedef typename Alloc::reference reference;
|
||||
typedef typename Alloc::const_reference const_reference;
|
||||
typedef typename Alloc::pointer pointer;
|
||||
typedef typename Alloc::const_pointer const_pointer;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace detail */
|
||||
} /* namespace heap */
|
||||
} /* namespace boost */
|
||||
|
||||
#endif /* BOOST_HEAP_DETAIL_STABLE_HEAP_HPP */
|
||||
@@ -0,0 +1,377 @@
|
||||
// boost heap: node tree iterator helper classes
|
||||
//
|
||||
// Copyright (C) 2010 Tim Blechmann
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_HEAP_DETAIL_TREE_ITERATOR_HPP
|
||||
#define BOOST_HEAP_DETAIL_TREE_ITERATOR_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <queue>
|
||||
|
||||
namespace boost {
|
||||
namespace heap {
|
||||
namespace detail {
|
||||
|
||||
|
||||
template<typename type>
|
||||
struct identity
|
||||
{
|
||||
type& operator()(type& x) const BOOST_NOEXCEPT
|
||||
{ return x; }
|
||||
|
||||
const type& operator()(const type& x) const BOOST_NOEXCEPT
|
||||
{ return x; }
|
||||
};
|
||||
|
||||
template<typename Node>
|
||||
struct dereferencer
|
||||
{
|
||||
template <typename Iterator>
|
||||
Node * operator()(Iterator const & it)
|
||||
{
|
||||
return static_cast<Node *>(*it);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Node>
|
||||
struct pointer_to_reference
|
||||
{
|
||||
template <typename Iterator>
|
||||
const Node * operator()(Iterator const & it)
|
||||
{
|
||||
return static_cast<const Node *>(&*it);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename HandleType,
|
||||
typename Alloc,
|
||||
typename ValueCompare
|
||||
>
|
||||
struct unordered_tree_iterator_storage
|
||||
{
|
||||
unordered_tree_iterator_storage(ValueCompare const & cmp)
|
||||
{}
|
||||
|
||||
void push(HandleType h)
|
||||
{
|
||||
data_.push_back(h);
|
||||
}
|
||||
|
||||
HandleType const & top(void)
|
||||
{
|
||||
return data_.back();
|
||||
}
|
||||
|
||||
void pop(void)
|
||||
{
|
||||
data_.pop_back();
|
||||
}
|
||||
|
||||
bool empty(void) const
|
||||
{
|
||||
return data_.empty();
|
||||
}
|
||||
|
||||
std::vector<HandleType, typename Alloc::template rebind<HandleType>::other > data_;
|
||||
};
|
||||
|
||||
template <typename ValueType,
|
||||
typename HandleType,
|
||||
typename Alloc,
|
||||
typename ValueCompare,
|
||||
typename ValueExtractor
|
||||
>
|
||||
struct ordered_tree_iterator_storage:
|
||||
ValueExtractor
|
||||
{
|
||||
struct compare_values_by_handle:
|
||||
ValueExtractor,
|
||||
ValueCompare
|
||||
{
|
||||
compare_values_by_handle(ValueCompare const & cmp):
|
||||
ValueCompare(cmp)
|
||||
{}
|
||||
|
||||
bool operator()(HandleType const & lhs, HandleType const & rhs) const
|
||||
{
|
||||
ValueType const & lhs_value = ValueExtractor::operator()(lhs->value);
|
||||
ValueType const & rhs_value = ValueExtractor::operator()(rhs->value);
|
||||
return ValueCompare::operator()(lhs_value, rhs_value);
|
||||
}
|
||||
};
|
||||
|
||||
ordered_tree_iterator_storage(ValueCompare const & cmp):
|
||||
data_(compare_values_by_handle(cmp))
|
||||
{}
|
||||
|
||||
void push(HandleType h)
|
||||
{
|
||||
data_.push(h);
|
||||
}
|
||||
|
||||
void pop(void)
|
||||
{
|
||||
data_.pop();
|
||||
}
|
||||
|
||||
HandleType const & top(void)
|
||||
{
|
||||
return data_.top();
|
||||
}
|
||||
|
||||
bool empty(void) const BOOST_NOEXCEPT
|
||||
{
|
||||
return data_.empty();
|
||||
}
|
||||
|
||||
std::priority_queue<HandleType,
|
||||
std::vector<HandleType, typename Alloc::template rebind<HandleType>::other>,
|
||||
compare_values_by_handle> data_;
|
||||
};
|
||||
|
||||
|
||||
/* tree iterator helper class
|
||||
*
|
||||
* Requirements:
|
||||
* Node provides child_iterator
|
||||
* ValueExtractor can convert Node->value to ValueType
|
||||
*
|
||||
* */
|
||||
template <typename Node,
|
||||
typename ValueType,
|
||||
typename Alloc = std::allocator<Node>,
|
||||
typename ValueExtractor = identity<typename Node::value_type>,
|
||||
typename PointerExtractor = dereferencer<Node>,
|
||||
bool check_null_pointer = false,
|
||||
bool ordered_iterator = false,
|
||||
typename ValueCompare = std::less<ValueType>
|
||||
>
|
||||
class tree_iterator:
|
||||
public boost::iterator_adaptor<tree_iterator<Node,
|
||||
ValueType,
|
||||
Alloc,
|
||||
ValueExtractor,
|
||||
PointerExtractor,
|
||||
check_null_pointer,
|
||||
ordered_iterator,
|
||||
ValueCompare
|
||||
>,
|
||||
const Node *,
|
||||
ValueType,
|
||||
boost::forward_traversal_tag
|
||||
>,
|
||||
ValueExtractor,
|
||||
PointerExtractor
|
||||
{
|
||||
typedef boost::iterator_adaptor<tree_iterator<Node,
|
||||
ValueType,
|
||||
Alloc,
|
||||
ValueExtractor,
|
||||
PointerExtractor,
|
||||
check_null_pointer,
|
||||
ordered_iterator,
|
||||
ValueCompare
|
||||
>,
|
||||
const Node *,
|
||||
ValueType,
|
||||
boost::forward_traversal_tag
|
||||
> adaptor_type;
|
||||
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
typedef typename boost::mpl::if_c< ordered_iterator,
|
||||
ordered_tree_iterator_storage<ValueType, const Node*, Alloc, ValueCompare, ValueExtractor>,
|
||||
unordered_tree_iterator_storage<const Node*, Alloc, ValueCompare>
|
||||
>::type
|
||||
unvisited_node_container;
|
||||
|
||||
public:
|
||||
tree_iterator(void):
|
||||
adaptor_type(0), unvisited_nodes(ValueCompare())
|
||||
{}
|
||||
|
||||
tree_iterator(ValueCompare const & cmp):
|
||||
adaptor_type(0), unvisited_nodes(cmp)
|
||||
{}
|
||||
|
||||
tree_iterator(const Node * it, ValueCompare const & cmp):
|
||||
adaptor_type(it), unvisited_nodes(cmp)
|
||||
{
|
||||
if (it)
|
||||
discover_nodes(it);
|
||||
}
|
||||
|
||||
/* fills the iterator from a list of possible top nodes */
|
||||
template <typename NodePointerIterator>
|
||||
tree_iterator(NodePointerIterator begin, NodePointerIterator end, const Node * top_node, ValueCompare const & cmp):
|
||||
adaptor_type(0), unvisited_nodes(cmp)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(ordered_iterator);
|
||||
if (begin == end)
|
||||
return;
|
||||
|
||||
adaptor_type::base_reference() = top_node;
|
||||
discover_nodes(top_node);
|
||||
|
||||
for (NodePointerIterator it = begin; it != end; ++it) {
|
||||
const Node * current_node = static_cast<const Node*>(&*it);
|
||||
if (current_node != top_node)
|
||||
unvisited_nodes.push(current_node);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator!=(tree_iterator const & rhs) const
|
||||
{
|
||||
return adaptor_type::base() != rhs.base();
|
||||
}
|
||||
|
||||
bool operator==(tree_iterator const & rhs) const
|
||||
{
|
||||
return !operator!=(rhs);
|
||||
}
|
||||
|
||||
const Node * get_node() const
|
||||
{
|
||||
return adaptor_type::base_reference();
|
||||
}
|
||||
|
||||
private:
|
||||
void increment(void)
|
||||
{
|
||||
if (unvisited_nodes.empty())
|
||||
adaptor_type::base_reference() = 0;
|
||||
else {
|
||||
const Node * next = unvisited_nodes.top();
|
||||
unvisited_nodes.pop();
|
||||
discover_nodes(next);
|
||||
adaptor_type::base_reference() = next;
|
||||
}
|
||||
}
|
||||
|
||||
ValueType const & dereference() const
|
||||
{
|
||||
return ValueExtractor::operator()(adaptor_type::base_reference()->value);
|
||||
}
|
||||
|
||||
void discover_nodes(const Node * n)
|
||||
{
|
||||
for (typename Node::const_child_iterator it = n->children.begin(); it != n->children.end(); ++it) {
|
||||
const Node * n = PointerExtractor::operator()(it);
|
||||
if (check_null_pointer && n == NULL)
|
||||
continue;
|
||||
unvisited_nodes.push(n);
|
||||
}
|
||||
}
|
||||
|
||||
unvisited_node_container unvisited_nodes;
|
||||
};
|
||||
|
||||
template <typename Node, typename NodeList>
|
||||
struct list_iterator_converter
|
||||
{
|
||||
typename NodeList::const_iterator operator()(const Node * node)
|
||||
{
|
||||
return NodeList::s_iterator_to(*node);
|
||||
}
|
||||
|
||||
Node * operator()(typename NodeList::const_iterator it)
|
||||
{
|
||||
return const_cast<Node*>(static_cast<const Node*>(&*it));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Node,
|
||||
typename NodeIterator,
|
||||
typename ValueType,
|
||||
typename ValueExtractor = identity<typename Node::value_type>,
|
||||
typename IteratorCoverter = identity<NodeIterator>
|
||||
>
|
||||
class recursive_tree_iterator:
|
||||
public boost::iterator_adaptor<recursive_tree_iterator<Node,
|
||||
NodeIterator,
|
||||
ValueType,
|
||||
ValueExtractor,
|
||||
IteratorCoverter
|
||||
>,
|
||||
NodeIterator,
|
||||
ValueType const,
|
||||
boost::bidirectional_traversal_tag>,
|
||||
ValueExtractor, IteratorCoverter
|
||||
{
|
||||
typedef boost::iterator_adaptor<recursive_tree_iterator<Node,
|
||||
NodeIterator,
|
||||
ValueType,
|
||||
ValueExtractor,
|
||||
IteratorCoverter
|
||||
>,
|
||||
NodeIterator,
|
||||
ValueType const,
|
||||
boost::bidirectional_traversal_tag> adaptor_type;
|
||||
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
|
||||
public:
|
||||
recursive_tree_iterator(void):
|
||||
adaptor_type(0)
|
||||
{}
|
||||
|
||||
explicit recursive_tree_iterator(NodeIterator const & it):
|
||||
adaptor_type(it)
|
||||
{}
|
||||
|
||||
void increment(void)
|
||||
{
|
||||
NodeIterator next = adaptor_type::base_reference();
|
||||
|
||||
const Node * n = get_node(next);
|
||||
if (n->children.empty()) {
|
||||
const Node * parent = get_node(next)->get_parent();
|
||||
|
||||
++next;
|
||||
|
||||
while (true) {
|
||||
if (parent == NULL || next != parent->children.end())
|
||||
break;
|
||||
|
||||
next = IteratorCoverter::operator()(parent);
|
||||
parent = get_node(next)->get_parent();
|
||||
++next;
|
||||
}
|
||||
} else
|
||||
next = n->children.begin();
|
||||
|
||||
adaptor_type::base_reference() = next;
|
||||
return;
|
||||
}
|
||||
|
||||
ValueType const & dereference() const
|
||||
{
|
||||
return ValueExtractor::operator()(get_node(adaptor_type::base_reference())->value);
|
||||
}
|
||||
|
||||
static const Node * get_node(NodeIterator const & it)
|
||||
{
|
||||
return static_cast<const Node *>(&*it);
|
||||
}
|
||||
|
||||
const Node * get_node() const
|
||||
{
|
||||
return get_node(adaptor_type::base_reference());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} /* namespace detail */
|
||||
} /* namespace heap */
|
||||
} /* namespace boost */
|
||||
|
||||
#endif /* BOOST_HEAP_DETAIL_TREE_ITERATOR_HPP */
|
||||
Reference in New Issue
Block a user