--- /dev/null
+//
+//=======================================================================
+// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
+// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
+//
+// 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)
+//=======================================================================
+//
+//
+// Revision History:
+// 13 June 2001: Changed some names for clarity. (Jeremy Siek)
+// 01 April 2001: Modified to use new <boost/limits.hpp> header. (JMaddock)
+//
+#ifndef BOOST_GRAPH_DETAIL_BUCKET_SORTER_HPP
+#define BOOST_GRAPH_DETAIL_BUCKET_SORTER_HPP
+
+#include <vector>
+#include <cassert>
+#include <boost/limits.hpp>
+
+namespace boost {
+
+ template <class BucketType, class ValueType, class Bucket,
+ class ValueIndexMap>
+ class bucket_sorter {
+ public:
+ typedef BucketType bucket_type;
+ typedef ValueType value_type;
+ typedef typename std::vector<value_type>::size_type size_type;
+
+ bucket_sorter(size_type _length, bucket_type _max_bucket,
+ const Bucket& _bucket = Bucket(),
+ const ValueIndexMap& _id = ValueIndexMap())
+ : head(_max_bucket, invalid_value()),
+ next(_length, invalid_value()),
+ prev(_length, invalid_value()),
+ id_to_value(_length),
+ bucket(_bucket), id(_id) { }
+
+ void remove(const value_type& x) {
+ const size_type i = get(id, x);
+ const size_type& next_node = next[i];
+ const size_type& prev_node = prev[i];
+
+ //check if i is the end of the bucket list
+ if ( next_node != invalid_value() )
+ prev[next_node] = prev_node;
+ //check if i is the begin of the bucket list
+ if ( prev_node != invalid_value() )
+ next[prev_node] = next_node;
+ else //need update head of current bucket list
+ head[ bucket[x] ] = next_node;
+ }
+
+ void push(const value_type& x) {
+ id_to_value[get(id, x)] = x;
+ (*this)[bucket[x]].push(x);
+ }
+
+ void update(const value_type& x) {
+ remove(x);
+ (*this)[bucket[x]].push(x);
+ }
+ // private:
+ // with KCC, the nested stack class is having access problems
+ // despite the friend decl.
+ static size_type invalid_value() {
+ return (std::numeric_limits<size_type>::max)();
+ }
+
+ typedef typename std::vector<size_type>::iterator Iter;
+ typedef typename std::vector<value_type>::iterator IndexValueMap;
+
+ public:
+ friend class stack;
+
+ class stack {
+ public:
+ stack(bucket_type _bucket_id, Iter h, Iter n, Iter p, IndexValueMap v,
+ const ValueIndexMap& _id)
+ : bucket_id(_bucket_id), head(h), next(n), prev(p), value(v), id(_id) {}
+
+ // Avoid using default arg for ValueIndexMap so that the default
+ // constructor of the ValueIndexMap is not required if not used.
+ stack(bucket_type _bucket_id, Iter h, Iter n, Iter p, IndexValueMap v)
+ : bucket_id(_bucket_id), head(h), next(n), prev(p), value(v) {}
+
+ void push(const value_type& x) {
+ const size_type new_head = get(id, x);
+ const size_type current = head[bucket_id];
+ if ( current != invalid_value() )
+ prev[current] = new_head;
+ prev[new_head] = invalid_value();
+ next[new_head] = current;
+ head[bucket_id] = new_head;
+ }
+ void pop() {
+ size_type current = head[bucket_id];
+ size_type next_node = next[current];
+ head[bucket_id] = next_node;
+ if ( next_node != invalid_value() )
+ prev[next_node] = invalid_value();
+ }
+ value_type& top() { return value[ head[bucket_id] ]; }
+ const value_type& top() const { return value[ head[bucket_id] ]; }
+ bool empty() const { return head[bucket_id] == invalid_value(); }
+ private:
+ bucket_type bucket_id;
+ Iter head;
+ Iter next;
+ Iter prev;
+ IndexValueMap value;
+ ValueIndexMap id;
+ };
+
+ stack operator[](const bucket_type& i) {
+ assert(i < head.size());
+ return stack(i, head.begin(), next.begin(), prev.begin(),
+ id_to_value.begin(), id);
+ }
+ protected:
+ std::vector<size_type> head;
+ std::vector<size_type> next;
+ std::vector<size_type> prev;
+ std::vector<value_type> id_to_value;
+ Bucket bucket;
+ ValueIndexMap id;
+ };
+
+}
+
+#endif
--- /dev/null
+// (C) Copyright Jeremy Siek 2004
+// 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_GRAPH_DETAIL_CONTAINER_TRAITS_H
+#define BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H
+
+// Sure would be nice to be able to forward declare these
+// instead of pulling in all the headers. Too bad that
+// is not legal. There ought to be a standard <stlfwd> header. -JGS
+
+#include <boost/next_prior.hpp>
+
+#include <algorithm> // for std::remove
+#include <vector>
+#include <list>
+#include <map>
+#include <set>
+
+#if !defined BOOST_NO_HASH
+# ifdef BOOST_HASH_SET_HEADER
+# include BOOST_HASH_SET_HEADER
+# else
+# include <hash_set>
+# endif
+# ifdef BOOST_HASH_MAP_HEADER
+# include BOOST_HASH_MAP_HEADER
+# else
+# include <hash_map>
+# endif
+#endif
+
+#if !defined BOOST_NO_SLIST
+# ifdef BOOST_SLIST_HEADER
+# include BOOST_SLIST_HEADER
+# else
+# include <slist>
+# endif
+#endif
+
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+// Stay out of the way of concept checking class templates
+# define Container Container_
+# define AssociativeContainer AssociativeContainer_
+#endif
+
+// The content of this file is in 'graph_detail' because otherwise
+// there will be name clashes with
+// sandbox/boost/sequence_algo/container_traits.hpp
+// The 'detail' subnamespace will still cause problems.
+namespace boost { namespace graph_detail {
+
+ //======================================================================
+ // Container Category Tags
+ //
+ // They use virtual inheritance because there are lots of
+ // inheritance diamonds.
+
+ struct container_tag { };
+ struct forward_container_tag : virtual public container_tag { };
+ struct reversible_container_tag : virtual public forward_container_tag { };
+ struct random_access_container_tag
+ : virtual public reversible_container_tag { };
+
+ struct sequence_tag : virtual public forward_container_tag { };
+
+ struct associative_container_tag : virtual public forward_container_tag { };
+
+ struct sorted_associative_container_tag
+ : virtual public associative_container_tag,
+ virtual public reversible_container_tag { };
+
+ struct front_insertion_sequence_tag : virtual public sequence_tag { };
+ struct back_insertion_sequence_tag : virtual public sequence_tag { };
+
+ struct unique_associative_container_tag
+ : virtual public associative_container_tag { };
+ struct multiple_associative_container_tag
+ : virtual public associative_container_tag { };
+ struct simple_associative_container_tag
+ : virtual public associative_container_tag { };
+ struct pair_associative_container_tag
+ : virtual public associative_container_tag { };
+
+
+ //======================================================================
+ // Iterator Stability Tags
+ //
+ // Do mutating operations such as insert/erase/resize invalidate all
+ // outstanding iterators?
+
+ struct stable_tag { };
+ struct unstable_tag { };
+
+ //======================================================================
+ // Container Traits Class and container_category() function
+
+#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ // don't use this unless there is partial specialization
+ template <class Container>
+ struct container_traits {
+ typedef typename Container::category category;
+ typedef typename Container::iterator_stability iterator_stability;
+ };
+#endif
+
+ // Use this as a compile-time assertion that X is stable
+ inline void require_stable(stable_tag) { }
+
+ // std::vector
+ struct vector_tag :
+ virtual public random_access_container_tag,
+ virtual public back_insertion_sequence_tag { };
+
+ template <class T, class Alloc>
+ vector_tag container_category(const std::vector<T,Alloc>&)
+ { return vector_tag(); }
+
+ template <class T, class Alloc>
+ unstable_tag iterator_stability(const std::vector<T,Alloc>&)
+ { return unstable_tag(); }
+
+#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ template <class T, class Alloc>
+ struct container_traits< std::vector<T,Alloc> > {
+ typedef vector_tag category;
+ typedef unstable_tag iterator_stability;
+ };
+#endif
+
+ // std::list
+ struct list_tag :
+ virtual public reversible_container_tag,
+ virtual public back_insertion_sequence_tag
+ // this causes problems for push_dispatch...
+ // virtual public front_insertion_sequence_tag
+ { };
+
+ template <class T, class Alloc>
+ list_tag container_category(const std::list<T,Alloc>&)
+ { return list_tag(); }
+
+ template <class T, class Alloc>
+ stable_tag iterator_stability(const std::list<T,Alloc>&)
+ { return stable_tag(); }
+
+#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ template <class T, class Alloc>
+ struct container_traits< std::list<T,Alloc> > {
+ typedef list_tag category;
+ typedef stable_tag iterator_stability;
+ };
+#endif
+
+
+ // std::slist
+#ifndef BOOST_NO_SLIST
+# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ template <class T, class Alloc>
+ struct container_traits<BOOST_STD_EXTENSION_NAMESPACE::slist<T,Alloc> > {
+ typedef front_insertion_sequence_tag category;
+ typedef stable_tag iterator_stability;
+ };
+#endif
+ template <class T, class Alloc>
+ front_insertion_sequence_tag container_category(
+ const BOOST_STD_EXTENSION_NAMESPACE::slist<T,Alloc>&
+ )
+ { return front_insertion_sequence_tag(); }
+
+ template <class T, class Alloc>
+ stable_tag iterator_stability(
+ const BOOST_STD_EXTENSION_NAMESPACE::slist<T,Alloc>&)
+ { return stable_tag(); }
+#endif
+
+
+ // std::set
+ struct set_tag :
+ virtual public sorted_associative_container_tag,
+ virtual public simple_associative_container_tag,
+ virtual public unique_associative_container_tag
+ { };
+
+ template <class Key, class Cmp, class Alloc>
+ set_tag container_category(const std::set<Key,Cmp,Alloc>&)
+ { return set_tag(); }
+
+ template <class Key, class Cmp, class Alloc>
+ stable_tag iterator_stability(const std::set<Key,Cmp,Alloc>&)
+ { return stable_tag(); }
+
+#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ template <class Key, class Cmp, class Alloc>
+ struct container_traits< std::set<Key,Cmp,Alloc> > {
+ typedef set_tag category;
+ typedef stable_tag iterator_stability;
+ };
+#endif
+
+ // std::multiset
+ struct multiset_tag :
+ virtual public sorted_associative_container_tag,
+ virtual public simple_associative_container_tag,
+ virtual public multiple_associative_container_tag
+ { };
+
+ template <class Key, class Cmp, class Alloc>
+ multiset_tag container_category(const std::multiset<Key,Cmp,Alloc>&)
+ { return multiset_tag(); }
+
+ template <class Key, class Cmp, class Alloc>
+ stable_tag iterator_stability(const std::multiset<Key,Cmp,Alloc>&)
+ { return stable_tag(); }
+
+#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ template <class Key, class Cmp, class Alloc>
+ struct container_traits< std::multiset<Key,Cmp,Alloc> > {
+ typedef multiset_tag category;
+ typedef stable_tag iterator_stability;
+ };
+#endif
+
+ // deque
+
+ // std::map
+ struct map_tag :
+ virtual public sorted_associative_container_tag,
+ virtual public pair_associative_container_tag,
+ virtual public unique_associative_container_tag
+ { };
+
+#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ template <class Key, class T, class Cmp, class Alloc>
+ struct container_traits< std::map<Key,T,Cmp,Alloc> > {
+ typedef map_tag category;
+ typedef stable_tag iterator_stability;
+ };
+#endif
+
+ template <class Key, class T, class Cmp, class Alloc>
+ map_tag container_category(const std::map<Key,T,Cmp,Alloc>&)
+ { return map_tag(); }
+
+ template <class Key, class T, class Cmp, class Alloc>
+ stable_tag iterator_stability(const std::map<Key,T,Cmp,Alloc>&)
+ { return stable_tag(); }
+
+ // std::multimap
+ struct multimap_tag :
+ virtual public sorted_associative_container_tag,
+ virtual public pair_associative_container_tag,
+ virtual public multiple_associative_container_tag
+ { };
+
+#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ template <class Key, class T, class Cmp, class Alloc>
+ struct container_traits< std::multimap<Key,T,Cmp,Alloc> > {
+ typedef multimap_tag category;
+ typedef stable_tag iterator_stability;
+ };
+#endif
+
+ template <class Key, class T, class Cmp, class Alloc>
+ multimap_tag container_category(const std::multimap<Key,T,Cmp,Alloc>&)
+ { return multimap_tag(); }
+
+ template <class Key, class T, class Cmp, class Alloc>
+ stable_tag iterator_stability(const std::multimap<Key,T,Cmp,Alloc>&)
+ { return stable_tag(); }
+
+
+ // hash_set, hash_map
+
+#ifndef BOOST_NO_HASH
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ template <class Key, class Eq, class Hash, class Alloc>
+ struct container_traits< BOOST_STD_EXTENSION_NAMESPACE::hash_set<Key,Eq,Hash,Alloc> > {
+ typedef set_tag category;
+ typedef stable_tag iterator_stability; // is this right?
+ };
+ template <class Key, class T, class Eq, class Hash, class Alloc>
+ struct container_traits< BOOST_STD_EXTENSION_NAMESPACE::hash_map<Key,T,Eq,Hash,Alloc> > {
+ typedef map_tag category;
+ typedef stable_tag iterator_stability; // is this right?
+ };
+#endif
+ template <class Key, class Eq, class Hash, class Alloc>
+ set_tag container_category(const BOOST_STD_EXTENSION_NAMESPACE::hash_set<Key,Eq,Hash,Alloc>&)
+ { return set_tag(); }
+
+ template <class Key, class T, class Eq, class Hash, class Alloc>
+ map_tag container_category(const BOOST_STD_EXTENSION_NAMESPACE::hash_map<Key,T,Eq,Hash,Alloc>&)
+ { return map_tag(); }
+
+ template <class Key, class Eq, class Hash, class Alloc>
+ stable_tag iterator_stability(const BOOST_STD_EXTENSION_NAMESPACE::hash_set<Key,Eq,Hash,Alloc>&)
+ { return stable_tag(); }
+
+ template <class Key, class T, class Eq, class Hash, class Alloc>
+ stable_tag iterator_stability(const BOOST_STD_EXTENSION_NAMESPACE::hash_map<Key,T,Eq,Hash,Alloc>&)
+ { return stable_tag(); }
+#endif
+
+
+
+ //===========================================================================
+ // Generalized Container Functions
+
+
+ // Erase
+ template <class Sequence, class T>
+ void erase_dispatch(Sequence& c, const T& x,
+ sequence_tag)
+ {
+ c.erase(std::remove(c.begin(), c.end(), x), c.end());
+ }
+
+ template <class AssociativeContainer, class T>
+ void erase_dispatch(AssociativeContainer& c, const T& x,
+ associative_container_tag)
+ {
+ c.erase(x);
+ }
+ template <class Container, class T>
+ void erase(Container& c, const T& x)
+ {
+ erase_dispatch(c, x, container_category(c));
+ }
+
+ // Erase If
+ template <class Sequence, class Predicate, class IteratorStability>
+ void erase_if_dispatch(Sequence& c, Predicate p,
+ sequence_tag, IteratorStability)
+ {
+#if 0
+ c.erase(std::remove_if(c.begin(), c.end(), p), c.end());
+#else
+ if (! c.empty())
+ c.erase(std::remove_if(c.begin(), c.end(), p), c.end());
+#endif
+ }
+ template <class AssociativeContainer, class Predicate>
+ void erase_if_dispatch(AssociativeContainer& c, Predicate p,
+ associative_container_tag, stable_tag)
+ {
+ typename AssociativeContainer::iterator i, next;
+ for (i = next = c.begin(); next != c.end(); i = next) {
+ ++next;
+ if (p(*i))
+ c.erase(i);
+ }
+ }
+ template <class AssociativeContainer, class Predicate>
+ void erase_if_dispatch(AssociativeContainer& c, Predicate p,
+ associative_container_tag, unstable_tag)
+ {
+ // This method is really slow, so hopefully we won't have any
+ // associative containers with unstable iterators!
+ // Is there a better way to do this?
+ typename AssociativeContainer::iterator i;
+ typename AssociativeContainer::size_type n = c.size();
+ while (n--)
+ for (i = c.begin(); i != c.end(); ++i)
+ if (p(*i)) {
+ c.erase(i);
+ break;
+ }
+ }
+ template <class Container, class Predicate>
+ void erase_if(Container& c, Predicate p)
+ {
+ erase_if_dispatch(c, p, container_category(c), iterator_stability(c));
+ }
+
+ // Push
+ template <class Container, class T>
+ std::pair<typename Container::iterator, bool>
+ push_dispatch(Container& c, const T& v, back_insertion_sequence_tag)
+ {
+ c.push_back(v);
+ return std::make_pair(boost::prior(c.end()), true);
+ }
+
+ template <class Container, class T>
+ std::pair<typename Container::iterator, bool>
+ push_dispatch(Container& c, const T& v, front_insertion_sequence_tag)
+ {
+ c.push_front(v);
+ return std::make_pair(c.begin(), true);
+ }
+
+ template <class AssociativeContainer, class T>
+ std::pair<typename AssociativeContainer::iterator, bool>
+ push_dispatch(AssociativeContainer& c, const T& v,
+ unique_associative_container_tag)
+ {
+ return c.insert(v);
+ }
+
+ template <class AssociativeContainer, class T>
+ std::pair<typename AssociativeContainer::iterator, bool>
+ push_dispatch(AssociativeContainer& c, const T& v,
+ multiple_associative_container_tag)
+ {
+ return std::make_pair(c.insert(v), true);
+ }
+
+ template <class Container, class T>
+ std::pair<typename Container::iterator,bool>
+ push(Container& c, const T& v)
+ {
+ return push_dispatch(c, v, container_category(c));
+ }
+
+}} // namespace boost::graph_detail
+
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+// Stay out of the way of concept checking class templates
+# undef Container
+# undef AssociativeContainer
+#endif
+
+#endif // BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H
--- /dev/null
+// -*- C++ -*- forwarding header.
+// (C) Copyright Jeremy Siek 2004
+// 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_CSTDDEF_HPP
+#define BOOST_CSTDDEF_HPP
+
+#if defined(__sgi) && !defined(__GNUC__)
+# include <stddef.h>
+#else
+# include <cstddef>
+#endif
+
+#endif
--- /dev/null
+// (C) Copyright Jeremy Siek 2000.
+// 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)
+
+// This header replaces the implementation of ct_if that preceded the
+// introduction of Boost.MPL with a facade that defers to that reviewed and
+// accepted library.
+
+// Author: Ronald Garcia
+// Date: 20 October, 2006
+
+
+#ifndef BOOST_CT_IF_HPP
+#define BOOST_CT_IF_HPP
+
+
+// A stub implementation in terms of Boost.MPL
+
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/and.hpp>
+// true_type and false_type are used by applications of ct_if
+#include <boost/type_traits/integral_constant.hpp>
+
+namespace boost {
+
+ template <class A, class B>
+ struct ct_and : boost::mpl::and_<A,B> {};
+
+ template <class A>
+ struct ct_not : mpl::not_<A> {};
+
+ template <bool cond, class A, class B>
+ struct ct_if : mpl::if_c<cond,A,B> {};
+
+ template <class cond, class A, class B>
+ struct ct_if_t : mpl::if_<cond,A,B> {};
+
+} // namespace boost
+
+#endif // BOOST_CT_IF_HPP
+
--- /dev/null
+// (C) Copyright Jeremy Siek 2004
+// 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_DETAIL_DISJOINT_SETS_HPP
+#define BOOST_DETAIL_DISJOINT_SETS_HPP
+
+namespace boost {
+
+namespace detail {
+
+template <class ParentPA, class Vertex>
+Vertex
+find_representative_with_path_halving(ParentPA p, Vertex v)
+{
+ Vertex parent = get(p, v);
+ Vertex grandparent = get(p, parent);
+ while (parent != grandparent) {
+ put(p, v, grandparent);
+ v = grandparent;
+ parent = get(p, v);
+ grandparent = get(p, parent);
+ }
+ return parent;
+}
+
+template <class ParentPA, class Vertex>
+Vertex
+find_representative_with_full_compression(ParentPA parent, Vertex v)
+{
+ Vertex old = v;
+ Vertex ancestor = get(parent, v);
+ while (ancestor != v) {
+ v = ancestor;
+ ancestor = get(parent, v);
+ }
+ v = get(parent, old);
+ while (ancestor != v) {
+ put(parent, old, ancestor);
+ old = v;
+ v = get(parent, old);
+ }
+ return ancestor;
+}
+
+/* the postcondition of link sets is:
+ component_representative(i) == component_representative(j)
+ */
+template <class ParentPA, class RankPA, class Vertex,
+ class ComponentRepresentative>
+inline void
+link_sets(ParentPA p, RankPA rank, Vertex i, Vertex j,
+ ComponentRepresentative comp_rep)
+{
+ i = comp_rep(p, i);
+ j = comp_rep(p, j);
+ if (i == j) return;
+ if (get(rank, i) > get(rank, j))
+ put(p, j, i);
+ else {
+ put(p, i, j);
+ if (get(rank, i) == get(rank, j))
+ put(rank, j, get(rank, j) + 1);
+ }
+}
+
+// normalize components has the following postcondidition:
+// i >= p[i]
+// that is, the representative is the node with the smallest index in its class
+// as its precondition it it assumes that the node container is compressed
+
+template <class ParentPA, class Vertex>
+inline void
+normalize_node(ParentPA p, Vertex i)
+{
+ if (i > get(p,i) || get(p, get(p,i)) != get(p,i))
+ put(p,i, get(p, get(p,i)));
+ else {
+ put(p, get(p,i), i);
+ put(p, i, i);
+ }
+}
+
+ } // namespace detail
+} // namespace boost
+
+#endif // BOOST_DETAIL_DISJOINT_SETS_HPP
--- /dev/null
+// (C) Copyright Jeremy Siek 1999.
+// 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_INT_ITERATOR_H
+#define BOOST_INT_ITERATOR_H
+
+#include <boost/iterator.hpp>
+#if !defined BOOST_MSVC
+#include <boost/operators.hpp>
+#endif
+#include <iostream>
+//using namespace std;
+
+#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
+namespace boost {
+#endif
+
+// this should use random_access_iterator_helper but I've had
+// VC++ portablility problems with that. -JGS
+template <class IntT>
+class int_iterator
+{
+ typedef int_iterator self;
+public:
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef IntT value_type;
+ typedef IntT& reference;
+ typedef IntT* pointer;
+ typedef std::ptrdiff_t difference_type;
+
+ inline int_iterator() : _i(0) { }
+ inline int_iterator(IntT i) : _i(i) { }
+ inline int_iterator(const self& x) : _i(x._i) { }
+ inline self& operator=(const self& x) { _i = x._i; return *this; }
+ inline IntT operator*() { return _i; }
+ inline IntT operator[](IntT n) { return _i + n; }
+ inline self& operator++() { ++_i; return *this; }
+ inline self operator++(int) { self t = *this; ++_i; return t; }
+ inline self& operator+=(IntT n) { _i += n; return *this; }
+ inline self operator+(IntT n) { self t = *this; t += n; return t; }
+ inline self& operator--() { --_i; return *this; }
+ inline self operator--(int) { self t = *this; --_i; return t; }
+ inline self& operator-=(IntT n) { _i -= n; return *this; }
+ inline IntT operator-(const self& x) const { return _i - x._i; }
+ inline bool operator==(const self& x) const { return _i == x._i; }
+ // vc++ had a problem finding != in random_access_iterator_helper
+ // need to look into this... for now implementing everything here -JGS
+ inline bool operator!=(const self& x) const { return _i != x._i; }
+ inline bool operator<(const self& x) const { return _i < x._i; }
+ inline bool operator<=(const self& x) const { return _i <= x._i; }
+ inline bool operator>(const self& x) const { return _i > x._i; }
+ inline bool operator>=(const self& x) const { return _i >= x._i; }
+protected:
+ IntT _i;
+};
+
+template <class IntT>
+inline int_iterator<IntT>
+operator+(IntT n, int_iterator<IntT> t) { t += n; return t; }
+
+#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
+} /* namespace boost */
+#endif
+
+#ifdef BOOST_NO_OPERATORS_IN_NAMESPACE
+namespace boost {
+ using ::int_iterator;
+}
+#endif
+
+
+#endif /* BOOST_INT_ITERATOR_H */
--- /dev/null
+// (C) Copyright Jeremy Siek 2004
+// 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_DETAIL_PROPERTY_HPP
+#define BOOST_DETAIL_PROPERTY_HPP
+
+#include <utility> // for std::pair
+#include <boost/type_traits/same_traits.hpp> // for is_same
+
+namespace boost {
+
+ namespace detail {
+
+ template <class PropertyTag1, class PropertyTag2>
+ struct same_property {
+ enum { value = is_same<PropertyTag1,PropertyTag2>::value };
+ };
+
+ struct error_property_not_found { };
+
+ template <int TagMatched>
+ struct property_value_dispatch {
+ template <class PropertyTag, class T, class Tag>
+ inline static T& get_value(PropertyTag& p, T*, Tag) {
+ return p.m_value;
+ }
+ template <class PropertyTag, class T, class Tag>
+ inline static const T& const_get_value(const PropertyTag& p, T*, Tag) {
+ return p.m_value;
+ }
+ };
+
+ template <class PropertyList>
+ struct property_value_end {
+ template <class T> struct result { typedef T type; };
+
+ template <class T, class Tag>
+ inline static T& get_value(PropertyList& p, T* t, Tag tag) {
+ typedef typename PropertyList::next_type Next;
+ typedef typename Next::tag_type Next_tag;
+ enum { match = same_property<Next_tag,Tag>::value };
+ return property_value_dispatch<match>
+ ::get_value(static_cast<Next&>(p), t, tag);
+ }
+ template <class T, class Tag>
+ inline static const T& const_get_value(const PropertyList& p, T* t, Tag tag) {
+ typedef typename PropertyList::next_type Next;
+ typedef typename Next::tag_type Next_tag;
+ enum { match = same_property<Next_tag,Tag>::value };
+ return property_value_dispatch<match>
+ ::const_get_value(static_cast<const Next&>(p), t, tag);
+ }
+ };
+ template <>
+ struct property_value_end<no_property> {
+ template <class T> struct result {
+ typedef detail::error_property_not_found type;
+ };
+
+ // Stop the recursion and return error
+ template <class T, class Tag>
+ inline static detail::error_property_not_found&
+ get_value(no_property&, T*, Tag) {
+ static error_property_not_found s_prop_not_found;
+ return s_prop_not_found;
+ }
+ template <class T, class Tag>
+ inline static const detail::error_property_not_found&
+ const_get_value(const no_property&, T*, Tag) {
+ static error_property_not_found s_prop_not_found;
+ return s_prop_not_found;
+ }
+ };
+
+ template <>
+ struct property_value_dispatch<0> {
+ template <class PropertyList, class T, class Tag>
+ inline static typename property_value_end<PropertyList>::template result<T>::type&
+ get_value(PropertyList& p, T* t, Tag tag) {
+ return property_value_end<PropertyList>::get_value(p, t, tag);
+ }
+ template <class PropertyList, class T, class Tag>
+ inline static const typename property_value_end<PropertyList>::template result<T>::type&
+ const_get_value(const PropertyList& p, T* t, Tag tag) {
+ return property_value_end<PropertyList>::const_get_value(p, t, tag);
+ }
+ };
+
+ template <class PropertyList>
+ struct build_property_tag_value_alist
+ {
+ typedef typename PropertyList::next_type NextProperty;
+ typedef typename PropertyList::value_type Value;
+ typedef typename PropertyList::tag_type Tag;
+ typedef typename build_property_tag_value_alist<NextProperty>::type Next;
+ typedef std::pair< std::pair<Tag,Value>, Next> type;
+ };
+ template <>
+ struct build_property_tag_value_alist<no_property>
+ {
+ typedef no_property type;
+ };
+
+#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ template <class TagValueAList, class Tag>
+ struct extract_value {
+ typedef error_property_not_found type;
+ };
+ template <class Value, class Tag1, class Tag2, class Rest>
+ struct extract_value< std::pair<std::pair<Tag1,Value>,Rest>, Tag2> {
+ typedef typename extract_value<Rest,Tag2>::type type;
+ };
+ template <class Value, class Tag, class Rest>
+ struct extract_value< std::pair<std::pair<Tag,Value>,Rest>, Tag> {
+ typedef Value type;
+ };
+#else
+ // VC++ workaround:
+ // The main idea here is to replace partial specialization with
+ // nested template member classes. Of course there is the
+ // further complication that the outer class of the nested
+ // template class cannot itself be a template class.
+ // Hence the need for the ev_selector. -JGS
+
+ struct recursive_extract;
+ struct end_extract;
+
+ template <class TagValueAList>
+ struct ev_selector { typedef recursive_extract type; };
+ template <>
+ struct ev_selector<no_property> { typedef end_extract type; };
+
+ struct recursive_extract {
+ template <class TagValueAList, class Tag1>
+ struct bind_ {
+ typedef typename TagValueAList::first_type AListFirst;
+ typedef typename AListFirst::first_type Tag2;
+ typedef typename AListFirst::second_type Value;
+ enum { match = same_property<Tag1,Tag2>::value };
+ typedef typename TagValueAList::second_type Next;
+ typedef typename ev_selector<Next>::type Extractor;
+ typedef typename boost::ct_if< match, Value,
+ typename Extractor::template bind_<Next,Tag1>::type
+ >::type type;
+ };
+ };
+ struct end_extract {
+ template <class AList, class Tag1>
+ struct bind_ {
+ typedef error_property_not_found type;
+ };
+ };
+#endif //!defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+ } // namespace detail
+} // namespace boost
+
+#endif // BOOST_DETAIL_PROPERTY_HPP
--- /dev/null
+//
+//=======================================================================
+// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
+// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
+//
+// 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_DISJOINT_SETS_HPP
+#define BOOST_DISJOINT_SETS_HPP
+
+#include <vector>
+#include <boost/graph/properties.hpp>
+#include <boost/pending/detail/disjoint_sets.hpp>
+
+namespace boost {
+
+ struct find_with_path_halving {
+ template <class ParentPA, class Vertex>
+ Vertex operator()(ParentPA p, Vertex v) {
+ return detail::find_representative_with_path_halving(p, v);
+ }
+ };
+
+ struct find_with_full_path_compression {
+ template <class ParentPA, class Vertex>
+ Vertex operator()(ParentPA p, Vertex v){
+ return detail::find_representative_with_full_compression(p, v);
+ }
+ };
+
+ // This is a generalized functor to provide disjoint sets operations
+ // with "union by rank" and "path compression". A disjoint-set data
+ // structure maintains a collection S={S1, S2, ..., Sk} of disjoint
+ // sets. Each set is identified by a representative, which is some
+ // member of of the set. Sets are represented by rooted trees. Two
+ // heuristics: "union by rank" and "path compression" are used to
+ // speed up the operations.
+
+ // Disjoint Set requires two vertex properties for internal use. A
+ // RankPA and a ParentPA. The RankPA must map Vertex to some Integral type
+ // (preferably the size_type associated with Vertex). The ParentPA
+ // must map Vertex to Vertex.
+ template <class RankPA, class ParentPA,
+ class FindCompress = find_with_full_path_compression
+ >
+ class disjoint_sets {
+ typedef disjoint_sets self;
+
+ inline disjoint_sets() {}
+ public:
+ inline disjoint_sets(RankPA r, ParentPA p)
+ : rank(r), parent(p) {}
+
+ inline disjoint_sets(const self& c)
+ : rank(c.rank), parent(c.parent) {}
+
+ // Make Set -- Create a singleton set containing vertex x
+ template <class Element>
+ inline void make_set(Element x)
+ {
+ put(parent, x, x);
+ typedef typename property_traits<RankPA>::value_type R;
+ put(rank, x, R());
+ }
+
+ // Link - union the two sets represented by vertex x and y
+ template <class Element>
+ inline void link(Element x, Element y)
+ {
+ detail::link_sets(parent, rank, x, y, rep);
+ }
+
+ // Union-Set - union the two sets containing vertex x and y
+ template <class Element>
+ inline void union_set(Element x, Element y)
+ {
+ link(find_set(x), find_set(y));
+ }
+
+ // Find-Set - returns the Element representative of the set
+ // containing Element x and applies path compression.
+ template <class Element>
+ inline Element find_set(Element x)
+ {
+ return rep(parent, x);
+ }
+
+ template <class ElementIterator>
+ inline std::size_t count_sets(ElementIterator first, ElementIterator last)
+ {
+ std::size_t count = 0;
+ for ( ; first != last; ++first)
+ if (get(parent, *first) == *first)
+ ++count;
+ return count;
+ }
+
+ template <class ElementIterator>
+ inline void normalize_sets(ElementIterator first, ElementIterator last)
+ {
+ for (; first != last; ++first)
+ detail::normalize_node(parent, *first);
+ }
+
+ template <class ElementIterator>
+ inline void compress_sets(ElementIterator first, ElementIterator last)
+ {
+ for (; first != last; ++first)
+ detail::find_representative_with_full_compression(parent, *first);
+ }
+ protected:
+ RankPA rank;
+ ParentPA parent;
+ FindCompress rep;
+ };
+
+
+
+
+ template <class ID = identity_property_map,
+ class InverseID = identity_property_map,
+ class FindCompress = find_with_full_path_compression
+ >
+ class disjoint_sets_with_storage
+ {
+ typedef typename property_traits<ID>::value_type Index;
+ typedef std::vector<Index> ParentContainer;
+ typedef std::vector<unsigned char> RankContainer;
+ public:
+ typedef typename ParentContainer::size_type size_type;
+
+ disjoint_sets_with_storage(size_type n = 0,
+ ID id_ = ID(),
+ InverseID inv = InverseID())
+ : id(id_), id_to_vertex(inv), rank(n, 0), parent(n)
+ {
+ for (Index i = 0; i < n; ++i)
+ parent[i] = i;
+ }
+ // note this is not normally needed
+ template <class Element>
+ inline void
+ make_set(Element x) {
+ parent[x] = x;
+ rank[x] = 0;
+ }
+ template <class Element>
+ inline void
+ link(Element x, Element y)
+ {
+ extend_sets(x,y);
+ detail::link_sets(&parent[0], &rank[0],
+ get(id,x), get(id,y), rep);
+ }
+ template <class Element>
+ inline void
+ union_set(Element x, Element y) {
+ Element rx = find_set(x);
+ Element ry = find_set(y);
+ link(rx, ry);
+ }
+ template <class Element>
+ inline Element find_set(Element x) {
+ return id_to_vertex[rep(&parent[0], get(id,x))];
+ }
+
+ template <class ElementIterator>
+ inline std::size_t count_sets(ElementIterator first, ElementIterator last)
+ {
+ std::size_t count = 0;
+ for ( ; first != last; ++first)
+ if (parent[*first] == *first)
+ ++count;
+ return count;
+ }
+
+ template <class ElementIterator>
+ inline void normalize_sets(ElementIterator first, ElementIterator last)
+ {
+ for (; first != last; ++first)
+ detail::normalize_node(&parent[0], *first);
+ }
+
+ template <class ElementIterator>
+ inline void compress_sets(ElementIterator first, ElementIterator last)
+ {
+ for (; first != last; ++first)
+ detail::find_representative_with_full_compression(&parent[0],
+ *first);
+ }
+
+ const ParentContainer& parents() { return parent; }
+
+ protected:
+
+ template <class Element>
+ inline void
+ extend_sets(Element x, Element y)
+ {
+ Index needed = get(id,x) > get(id,y) ? get(id,x) + 1 : get(id,y) + 1;
+ if (needed > parent.size()) {
+ rank.insert(rank.end(), needed - rank.size(), 0);
+ for (Index k = parent.size(); k < needed; ++k)
+ parent.push_back(k);
+ }
+ }
+
+ ID id;
+ InverseID id_to_vertex;
+ RankContainer rank;
+ ParentContainer parent;
+ FindCompress rep;
+ };
+
+} // namespace boost
+
+#endif // BOOST_DISJOINT_SETS_HPP
--- /dev/null
+// (C) Copyright Jeremiah Willcock 2004
+// 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_FENCED_PRIORITY_QUEUE_HPP
+#define BOOST_FENCED_PRIORITY_QUEUE_HPP
+
+#include <vector>
+#include <queue>
+#include <functional>
+#include <boost/pending/queue.hpp>
+
+// Fenced priority queue
+// Jeremiah Willcock
+
+// This class implements a fenced priority queue. This is similar to
+// a normal priority queue (sorts its members, and only returns the
+// first), except that members cannot be sorted around a "fence" that
+// can be placed into the buffer. This fence is inserted using the
+// fence() member function or (possibly) implicitly by the top() and
+// pop() methods, and is removed automatically when the elements
+// around it are popped.
+
+// The implementation is as follows: Q is an unsorted queue that
+// contains the already-sorted list data, and PQ is a priority queue
+// that contains new elements (since the last fence) that have yet to
+// be sorted. New elements are inserted into PQ, and a fence moves
+// all elements in PQ into the back of Q in sorted order. Elements
+// are then popped from the front of Q, and if that is empty the front
+// of PQ.
+
+namespace boost {
+
+ template<class T, class Compare = std::less<T>, bool implicit_fence = true,
+ class Buffer = boost::queue<T> >
+ class fenced_priority_queue {
+ public:
+ typedef T value_type;
+ typedef typename Buffer::size_type size_type;
+
+ fenced_priority_queue(const Compare _comp = Compare() )
+ : PQ(_comp) {}
+
+ void push(const T& data);
+ void pop(void);
+ T& top(void);
+ const T& top(void) const;
+ size_type size(void) const;
+ bool empty(void) const;
+ void fence(void);
+
+ private:
+ void fence(void) const;
+
+ //let them mutable to allow const version of top and the same
+ //semantics with non-constant version. Rich Lee
+ mutable std::priority_queue<T, std::vector<T>, Compare> PQ;
+ mutable Buffer Q;
+ };
+
+ template<class T, class Compare, bool implicit_fence, class Buffer>
+ inline void
+ fenced_priority_queue<T, Compare, implicit_fence, Buffer>::
+ push(const T &t) {
+ // Push a new element after the last fence. This puts it into the
+ // priority queue to be sorted with all other elements in its
+ // partition.
+ PQ.push(t);
+ }
+
+ template<class T, class Compare, bool implicit_fence, class Buffer>
+ inline void fenced_priority_queue<T, Compare, implicit_fence, Buffer>::
+ pop(void) {
+ // Pop one element from the front of the queue. Removes from the
+ // already-sorted part of the queue if it is non-empty, otherwise
+ // removes from the new-element priority queue. Runs an implicit
+ // "fence" operation if the implicit_fence template argument is
+ // true.
+ if (implicit_fence) fence();
+ if ( !Q.empty() )
+ Q.pop();
+ else
+ PQ.pop();
+ }
+
+ template<class T, class Compare, bool implicit_fence, class Buffer>
+ inline T& fenced_priority_queue<T, Compare, implicit_fence, Buffer>::
+ top(void) {
+ // Get the top element from the queue. This element comes from Q if
+ // possible, otherwise from PQ. Causes an implicit "fence"
+ // operation if the implicit_fence template argument is true.
+ if (implicit_fence) fence();
+ if ( !Q.empty() )
+ return Q.top();
+ else
+ //std::priority_queue only have const version of top. Rich Lee
+ return const_cast<T&>(PQ.top());
+ }
+
+ template<class T, class Compare, bool implicit_fence, class Buffer>
+ inline const T&
+ fenced_priority_queue<T, Compare, implicit_fence, Buffer>::
+ top(void) const {
+ if (implicit_fence) fence();
+ if ( !Q.empty() )
+ return Q.top();
+ else
+ return PQ.top();
+ }
+
+ template<class T, class Compare, bool implicit_fence, class Buffer>
+ inline typename fenced_priority_queue<T, Compare, implicit_fence, Buffer>::size_type
+ fenced_priority_queue<T, Compare, implicit_fence, Buffer>::
+ size(void) const {
+ // Returns the size of the queue (both parts together).
+ return Q.size() + PQ.size();
+ }
+
+ template<class T, class Compare, bool implicit_fence, class Buffer>
+ inline bool
+ fenced_priority_queue<T, Compare, implicit_fence, Buffer>::
+ empty(void) const {
+ // Returns if the queue is empty, i.e. both parts are empty.
+ return Q.empty() && PQ.empty();
+ }
+
+ template<class T, class Compare, bool implicit_fence, class Buffer>
+ inline void
+ fenced_priority_queue<T, Compare, implicit_fence, Buffer>::
+ fence(void) {
+ // Perform a fence operation. Remove elements from PQ in sorted
+ // order and insert them in the back of Q.
+ while ( !PQ.empty() ) {
+ Q.push(PQ.top());
+ PQ.pop();
+ }
+ }
+ template<class T, class Compare, bool implicit_fence, class Buffer>
+ inline void
+ fenced_priority_queue<T, Compare, implicit_fence, Buffer>::
+ fence(void) const {
+ // Perform a fence operation. Remove elements from PQ in sorted
+ // order and insert them in the back of Q.
+ while ( !PQ.empty() ) {
+ Q.push(PQ.top());
+ PQ.pop();
+ }
+ }
+
+}
+#endif /* BOOST_FENCED_PRIORITY_QUEUE_HPP */
--- /dev/null
+// (C) Copyright Jeremy Siek 2004.
+// 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_FIBONACCI_HEAP_HPP
+#define BOOST_FIBONACCI_HEAP_HPP
+
+#if defined(__sgi) && !defined(__GNUC__)
+# include <math.h>
+#else
+# include <cmath>
+#endif
+#include <iosfwd>
+#include <vector>
+#include <functional>
+#include <boost/config.hpp>
+#include <boost/property_map.hpp>
+
+//
+// An adaptation of Knuth's Fibonacci heap implementation
+// in "The Stanford Graph Base", pages 475-482.
+//
+
+namespace boost {
+
+
+template <class T,
+ class Compare = std::less<T>,
+ class ID = identity_property_map>
+class fibonacci_heap
+{
+ typedef typename boost::property_traits<ID>::value_type size_type;
+ typedef T value_type;
+protected:
+ typedef fibonacci_heap self;
+ typedef std::vector<size_type> LinkVec;
+ typedef typename LinkVec::iterator LinkIter;
+public:
+
+ fibonacci_heap(size_type n,
+ const Compare& cmp,
+ const ID& id = identity_property_map())
+ : _key(n), _left(n), _right(n), _p(n), _mark(n), _degree(n),
+ _n(0), _root(n), _id(id), _compare(cmp), _child(n),
+#if defined(BOOST_MSVC) || defined(__ICL) // need a new macro?
+ new_roots(size_type(log(float(n))) + 5) { }
+#else
+ new_roots(size_type(std::log(float(n))) + 5) { }
+#endif
+
+ // 33
+ void push(const T& d) {
+ ++_n;
+ size_type v = get(_id, d);
+ _key[v] = d;
+ _p[v] = nil();
+ _degree[v] = 0;
+ _mark[v] = false;
+ _child[v] = nil();
+ if (_root == nil()) {
+ _root = _left[v] = _right[v] = v;
+ //std::cout << "root added" << std::endl;
+ } else {
+ size_type u = _left[_root];
+ _left[v] = u;
+ _right[v] = _root;
+ _left[_root] = _right[u] = v;
+ if (_compare(d, _key[_root]))
+ _root = v;
+ //std::cout << "non-root node added" << std::endl;
+ }
+ }
+ T& top() { return _key[_root]; }
+ const T& top() const { return _key[_root]; }
+
+ // 38
+ void pop() {
+ --_n;
+ int h = -1;
+ size_type v, w;
+ if (_root != nil()) {
+ if (_degree[_root] == 0) {
+ v = _right[_root];
+ } else {
+ w = _child[_root];
+ v = _right[w];
+ _right[w] = _right[_root];
+ for (w = v; w != _right[_root]; w = _right[w])
+ _p[w] = nil();
+ }
+ while (v != _root) {
+ w = _right[v];
+ add_tree_to_new_roots(v, new_roots.begin(), h);
+ v = w;
+ }
+ rebuild_root_list(new_roots.begin(), h);
+ }
+ }
+ // 39
+ inline void add_tree_to_new_roots(size_type v,
+ LinkIter new_roots,
+ int& h)
+ {
+ int r;
+ size_type u;
+ r = _degree[v];
+ while (1) {
+ if (h < r) {
+ do {
+ ++h;
+ new_roots[h] = (h == r ? v : nil());
+ } while (h < r);
+ break;
+ }
+ if (new_roots[r] == nil()) {
+ new_roots[r] = v;
+ break;
+ }
+ u = new_roots[r];
+ new_roots[r] = nil();
+ if (_compare(_key[u], _key[v])) {
+ _degree[v] = r;
+ _mark[v] = false;
+ std::swap(u, v);
+ }
+ make_child(u, v, r);
+ ++r;
+ }
+ _degree[v] = r;
+ _mark[v] = false;
+ }
+ // 40
+ void make_child(size_type u, size_type v, size_type r) {
+ if (r == 0) {
+ _child[v] = u;
+ _left[u] = u;
+ _right[u] = u;
+ } else {
+ size_type t = _child[v];
+ _right[u] = _right[t];
+ _left[u] = t;
+ _right[t] = u;
+ _left[_right[u]] = u;
+ }
+ _p[u] = v;
+ }
+ // 41
+ inline void rebuild_root_list(LinkIter new_roots, int& h)
+ {
+ size_type u, v, w;
+ if (h < 0)
+ _root = nil();
+ else {
+ T d;
+ u = v = new_roots[h];
+ d = _key[u];
+ _root = u;
+ for (h--; h >= 0; --h)
+ if (new_roots[h] != nil()) {
+ w = new_roots[h];
+ _left[w] = v;
+ _right[v] = w;
+ if (_compare(_key[w], d)) {
+ _root = w;
+ d = _key[w];
+ }
+ v = w;
+ }
+ _right[v] = u;
+ _left[u] = v;
+ }
+ }
+
+ // 34
+ void update(const T& d) {
+ size_type v = get(_id, d);
+ assert(!_compare(_key[v], d));
+ _key[v] = d;
+ size_type p = _p[v];
+ if (p == nil()) {
+ if (_compare(d, _key[_root]))
+ _root = v;
+ } else if (_compare(d, _key[p]))
+ while (1) {
+ size_type r = _degree[p];
+ if (r >= 2)
+ remove_from_family(v, p);
+ insert_into_forest(v, d);
+ size_type pp = _p[p];
+ if (pp == nil()) {
+ --_degree[p];
+ break;
+ }
+ if (_mark[p] == false) {
+ _mark[p] = true;
+ --_degree[p];
+ break;
+ } else
+ --_degree[p];
+ v = p;
+ p = pp;
+ }
+ }
+
+ inline size_type size() const { return _n; }
+ inline bool empty() const { return _n == 0; }
+
+ void print(std::ostream& os) {
+ if (_root != nil()) {
+ size_type i = _root;
+ do {
+ print_recur(i, os);
+ os << std::endl;
+ i = _right[i];
+ } while (i != _root);
+ }
+ }
+
+protected:
+ // 35
+ inline void remove_from_family(size_type v, size_type p) {
+ size_type u = _left[v];
+ size_type w = _right[v];
+ _right[u] = w;
+ _left[w] = u;
+ if (_child[p] == v)
+ _child[p] = w;
+ }
+ // 36
+ inline void insert_into_forest(size_type v, const T& d) {
+ _p[v] = nil();
+ size_type u = _left[_root];
+ _left[v] = u;
+ _right[v] = _root;
+ _left[_root] = _right[u] = v;
+ if (_compare(d, _key[_root]))
+ _root = v;
+ }
+
+ void print_recur(size_type x, std::ostream& os) {
+ if (x != nil()) {
+ os << x;
+ if (_degree[x] > 0) {
+ os << "(";
+ size_type i = _child[x];
+ do {
+ print_recur(i, os); os << " ";
+ i = _right[i];
+ } while (i != _child[x]);
+ os << ")";
+ }
+ }
+ }
+
+ size_type nil() const { return _left.size(); }
+
+ std::vector<T> _key;
+ LinkVec _left, _right, _p;
+ std::vector<bool> _mark;
+ LinkVec _degree;
+ size_type _n, _root;
+ ID _id;
+ Compare _compare;
+ LinkVec _child;
+ LinkVec new_roots;
+};
+
+} // namespace boost
+
+
+#endif // BOOST_FIBONACCI_HEAP_HPP
--- /dev/null
+//
+//=======================================================================
+// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
+// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
+//
+// 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_INDIRECT_CMP_HPP
+#define BOOST_INDIRECT_CMP_HPP
+
+#include <functional>
+#include <boost/config.hpp>
+#include <boost/property_map.hpp>
+
+namespace boost {
+
+ //: indirect_cmp
+ //
+ // could also do this with compose_f_gx_hx, and the member binder...
+ //
+ //!category: functors
+ //!component: type
+ //!tparam: ReadablePropertyMap - a model of ReadablePropertyMap
+ //!definition: functor.h
+ template <class ReadablePropertyMap, class Compare>
+ class indirect_cmp {
+ public:
+ typedef typename boost::property_traits<ReadablePropertyMap>::value_type T;
+ typedef typename boost::property_traits<ReadablePropertyMap>::key_type K;
+ typedef K first_argument_type;
+ typedef K second_argument_type;
+ typedef T result_type;
+ inline indirect_cmp(const ReadablePropertyMap& df, const Compare& c = Compare())
+ : d(df), cmp(c) { }
+
+ template <class A, class B>
+ inline bool
+ operator()(const A& u, const B& v) const {
+ T du = get(d, u), dv = get(d, v);
+ return cmp(du, dv);
+ }
+ protected:
+ ReadablePropertyMap d;
+ Compare cmp;
+ };
+
+ template <typename Compare, typename ReadablePropertyMap>
+ indirect_cmp<ReadablePropertyMap, Compare>
+ make_indirect_cmp(const Compare& cmp, ReadablePropertyMap pmap) {
+ indirect_cmp<ReadablePropertyMap, Compare> p(pmap, cmp);
+ return p;
+ }
+
+ template <class ReadablePropertyMap>
+ class indirect_pmap {
+ public:
+ typedef typename boost::property_traits<ReadablePropertyMap>::value_type T;
+ typedef typename boost::property_traits<ReadablePropertyMap>::key_type K;
+ typedef K argument_type;
+ typedef T result_type;
+ inline indirect_pmap(const ReadablePropertyMap& df)
+ : d(df) { }
+
+ inline bool operator()(const K& u) const {
+ return get(d, u);
+ }
+ protected:
+ ReadablePropertyMap d;
+ };
+
+ template <typename ReadablePropertyMap>
+ indirect_pmap<ReadablePropertyMap>
+ make_indirect_pmap(ReadablePropertyMap pmap) {
+ indirect_pmap<ReadablePropertyMap> f(pmap);
+ return f;
+ }
+
+
+} // namespace boost
+
+
+#endif // GGCL_INDIRECT_CMP_HPP
--- /dev/null
+// -------------------------------------
+// integer_log2.hpp
+//
+// Gives the integer part of the logarithm, in base 2, of a
+// given number. Behavior is undefined if the argument is <= 0.
+//
+//
+// (C) Copyright Gennaro Prota 2003 - 2004.
+//
+// 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)
+//
+// ------------------------------------------------------
+//
+// $Id: integer_log2.hpp 41369 2007-11-25 18:07:19Z bemandawes $
+
+
+#ifndef BOOST_INTEGER_LOG2_HPP_GP_20030301
+#define BOOST_INTEGER_LOG2_HPP_GP_20030301
+
+#include <assert.h>
+#ifdef __BORLANDC__
+#include <climits>
+#endif
+#include "boost/limits.hpp"
+#include "boost/config.hpp"
+
+
+namespace boost {
+ namespace detail {
+
+ template <typename T>
+ int integer_log2_impl(T x, int n) {
+
+ int result = 0;
+
+ while (x != 1) {
+
+ const T t = x >> n;
+ if (t) {
+ result += n;
+ x = t;
+ }
+ n /= 2;
+
+ }
+
+ return result;
+ }
+
+
+
+ // helper to find the maximum power of two
+ // less than p (more involved than necessary,
+ // to avoid PTS)
+ //
+ template <int p, int n>
+ struct max_pow2_less {
+
+ enum { c = 2*n < p };
+
+ BOOST_STATIC_CONSTANT(int, value =
+ c ? (max_pow2_less< c*p, 2*c*n>::value) : n);
+
+ };
+
+ template <>
+ struct max_pow2_less<0, 0> {
+
+ BOOST_STATIC_CONSTANT(int, value = 0);
+ };
+
+ // this template is here just for Borland :(
+ // we could simply rely on numeric_limits but sometimes
+ // Borland tries to use numeric_limits<const T>, because
+ // of its usual const-related problems in argument deduction
+ // - gps
+ template <typename T>
+ struct width {
+
+#ifdef __BORLANDC__
+ BOOST_STATIC_CONSTANT(int, value = sizeof(T) * CHAR_BIT);
+#else
+ BOOST_STATIC_CONSTANT(int, value = (std::numeric_limits<T>::digits));
+#endif
+
+ };
+
+ } // detail
+
+
+ // ---------
+ // integer_log2
+ // ---------------
+ //
+ template <typename T>
+ int integer_log2(T x) {
+
+ assert(x > 0);
+
+ const int n = detail::max_pow2_less<
+ detail::width<T> :: value, 4
+ > :: value;
+
+ return detail::integer_log2_impl(x, n);
+
+ }
+
+
+
+}
+
+
+
+#endif // include guard
--- /dev/null
+// (C) Copyright David Abrahams and Jeremy Siek 2000-2001.
+// 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)
+//
+// Revision History:
+// 04 Jan 2001 Factored counting_iterator stuff into
+// boost/counting_iterator.hpp (David Abrahams)
+
+#ifndef BOOST_INTEGER_RANGE_HPP_
+#define BOOST_INTEGER_RANGE_HPP_
+
+#include <boost/config.hpp>
+#include <boost/iterator/counting_iterator.hpp>
+#include <algorithm>
+
+namespace boost {
+
+//=============================================================================
+// Counting Iterator and Integer Range Class
+
+template <class IntegerType>
+struct integer_range {
+ typedef counting_iterator<IntegerType> iterator;
+
+ typedef iterator const_iterator;
+ typedef IntegerType value_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef IntegerType reference;
+ typedef IntegerType const_reference;
+ typedef const IntegerType* pointer;
+ typedef const IntegerType* const_pointer;
+ typedef IntegerType size_type;
+
+ integer_range(IntegerType start, IntegerType finish)
+ : m_start(start), m_finish(finish) { }
+
+ iterator begin() const { return iterator(m_start); }
+ iterator end() const { return iterator(m_finish); }
+ size_type size() const { return m_finish - m_start; }
+ bool empty() const { return m_finish == m_start; }
+ void swap(integer_range& x) {
+ std::swap(m_start, x.m_start);
+ std::swap(m_finish, x.m_finish);
+ }
+protected:
+ IntegerType m_start, m_finish;
+};
+
+template <class IntegerType>
+inline integer_range<IntegerType>
+make_integer_range(IntegerType first, IntegerType last)
+{
+ return integer_range<IntegerType>(first, last);
+}
+
+} // namespace boost
+
+#endif // BOOST_INTEGER_RANGE_HPP_
--- /dev/null
+//
+//=======================================================================
+// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
+// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
+//
+// 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)
+//=======================================================================
+//
+#if __KCC
+namespace std {
+
+template <class RandomAccessIterator, class Distance>
+bool __is_heap(RandomAccessIterator first, RandomAccessIterator last,
+ Distance*)
+{
+ const Distance n = last - first;
+
+ Distance parent = 0;
+ for (Distance child = 1; child < n; ++child) {
+ if (first[parent] < first[child])
+ return false;
+ if ((child & 1) == 0)
+ ++parent;
+ }
+ return true;
+}
+
+template <class RandomAccessIterator>
+inline bool is_heap(RandomAccessIterator first, RandomAccessIterator last)
+{
+ return __is_heap(first, last, distance_type(first));
+}
+
+
+template <class RandomAccessIterator, class Distance, class StrictWeakOrdering>
+bool __is_heap(RandomAccessIterator first, RandomAccessIterator last,
+ StrictWeakOrdering comp,
+ Distance*)
+{
+ const Distance n = last - first;
+
+ Distance parent = 0;
+ for (Distance child = 1; child < n; ++child) {
+ if (comp(first[parent], first[child]))
+ return false;
+ if ((child & 1) == 0)
+ ++parent;
+ }
+ return true;
+}
+
+template <class RandomAccessIterator, class StrictWeakOrdering>
+inline bool is_heap(RandomAccessIterator first, RandomAccessIterator last,
+ StrictWeakOrdering comp)
+{
+ return __is_heap(first, last, comp, distance_type(first));
+}
+
+}
+#endif
--- /dev/null
+// Copyright David Abrahams 2003.
+// 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)
+
+#include <boost/iterator_adaptors.hpp>
--- /dev/null
+// Copyright David Abrahams and Jeremy Siek 2003.
+// 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_ITERATOR_TESTS_HPP
+# define BOOST_ITERATOR_TESTS_HPP
+
+// This is meant to be the beginnings of a comprehensive, generic
+// test suite for STL concepts such as iterators and containers.
+//
+// Revision History:
+// 28 Apr 2002 Fixed input iterator requirements.
+// For a == b a++ == b++ is no longer required.
+// See 24.1.1/3 for details.
+// (Thomas Witt)
+// 08 Feb 2001 Fixed bidirectional iterator test so that
+// --i is no longer a precondition.
+// (Jeremy Siek)
+// 04 Feb 2001 Added lvalue test, corrected preconditions
+// (David Abrahams)
+
+# include <iterator>
+# include <assert.h>
+# include <boost/type_traits.hpp>
+# include <boost/static_assert.hpp>
+# include <boost/concept_archetype.hpp> // for detail::dummy_constructor
+# include <boost/implicit_cast.hpp>
+# include <boost/type_traits/broken_compiler_spec.hpp>
+
+namespace boost {
+
+ // use this for the value type
+struct dummyT {
+ dummyT() { }
+ dummyT(detail::dummy_constructor) { }
+ dummyT(int x) : m_x(x) { }
+ int foo() const { return m_x; }
+ bool operator==(const dummyT& d) const { return m_x == d.m_x; }
+ int m_x;
+};
+
+}
+
+BOOST_TT_BROKEN_COMPILER_SPEC(boost::dummyT)
+
+namespace boost {
+
+// Tests whether type Iterator satisfies the requirements for a
+// TrivialIterator.
+// Preconditions: i != j, *i == val
+template <class Iterator, class T>
+void trivial_iterator_test(const Iterator i, const Iterator j, T val)
+{
+ Iterator k;
+ assert(i == i);
+ assert(j == j);
+ assert(i != j);
+#ifdef BOOST_NO_STD_ITERATOR_TRAITS
+ T v = *i;
+#else
+ typename std::iterator_traits<Iterator>::value_type v = *i;
+#endif
+ assert(v == val);
+#if 0
+ // hmm, this will give a warning for transform_iterator... perhaps
+ // this should be separated out into a stand-alone test since there
+ // are several situations where it can't be used, like for
+ // integer_range::iterator.
+ assert(v == i->foo());
+#endif
+ k = i;
+ assert(k == k);
+ assert(k == i);
+ assert(k != j);
+ assert(*k == val);
+}
+
+
+// Preconditions: i != j
+template <class Iterator, class T>
+void mutable_trivial_iterator_test(const Iterator i, const Iterator j, T val)
+{
+ *i = val;
+ trivial_iterator_test(i, j, val);
+}
+
+
+// Preconditions: *i == v1, *++i == v2
+template <class Iterator, class T>
+void input_iterator_test(Iterator i, T v1, T v2)
+{
+ Iterator i1(i);
+
+ assert(i == i1);
+ assert(!(i != i1));
+
+ // I can see no generic way to create an input iterator
+ // that is in the domain of== of i and != i.
+ // The following works for istream_iterator but is not
+ // guaranteed to work for arbitrary input iterators.
+ //
+ // Iterator i2;
+ //
+ // assert(i != i2);
+ // assert(!(i == i2));
+
+ assert(*i1 == v1);
+ assert(*i == v1);
+
+ // we cannot test for equivalence of (void)++i & (void)i++
+ // as i is only guaranteed to be single pass.
+ assert(*i++ == v1);
+
+ i1 = i;
+
+ assert(i == i1);
+ assert(!(i != i1));
+
+ assert(*i1 == v2);
+ assert(*i == v2);
+
+ // i is dereferencable, so it must be incrementable.
+ ++i;
+
+ // how to test for operator-> ?
+}
+
+// how to test output iterator?
+
+
+template <bool is_pointer> struct lvalue_test
+{
+ template <class Iterator> static void check(Iterator)
+ {
+# ifndef BOOST_NO_STD_ITERATOR_TRAITS
+ typedef typename std::iterator_traits<Iterator>::reference reference;
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+# else
+ typedef typename Iterator::reference reference;
+ typedef typename Iterator::value_type value_type;
+# endif
+ BOOST_STATIC_ASSERT(boost::is_reference<reference>::value);
+ BOOST_STATIC_ASSERT((boost::is_same<reference,value_type&>::value
+ || boost::is_same<reference,const value_type&>::value
+ ));
+ }
+};
+
+# ifdef BOOST_NO_STD_ITERATOR_TRAITS
+template <> struct lvalue_test<true> {
+ template <class T> static void check(T) {}
+};
+#endif
+
+template <class Iterator, class T>
+void forward_iterator_test(Iterator i, T v1, T v2)
+{
+ input_iterator_test(i, v1, v2);
+
+ Iterator i1 = i, i2 = i;
+
+ assert(i == i1++);
+ assert(i != ++i2);
+
+ trivial_iterator_test(i, i1, v1);
+ trivial_iterator_test(i, i2, v1);
+
+ ++i;
+ assert(i == i1);
+ assert(i == i2);
+ ++i1;
+ ++i2;
+
+ trivial_iterator_test(i, i1, v2);
+ trivial_iterator_test(i, i2, v2);
+
+ // borland doesn't allow non-type template parameters
+# if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)
+ lvalue_test<(boost::is_pointer<Iterator>::value)>::check(i);
+#endif
+}
+
+// Preconditions: *i == v1, *++i == v2
+template <class Iterator, class T>
+void bidirectional_iterator_test(Iterator i, T v1, T v2)
+{
+ forward_iterator_test(i, v1, v2);
+ ++i;
+
+ Iterator i1 = i, i2 = i;
+
+ assert(i == i1--);
+ assert(i != --i2);
+
+ trivial_iterator_test(i, i1, v2);
+ trivial_iterator_test(i, i2, v2);
+
+ --i;
+ assert(i == i1);
+ assert(i == i2);
+ ++i1;
+ ++i2;
+
+ trivial_iterator_test(i, i1, v1);
+ trivial_iterator_test(i, i2, v1);
+}
+
+// mutable_bidirectional_iterator_test
+
+template <class U> struct undefined;
+
+// Preconditions: [i,i+N) is a valid range
+template <class Iterator, class TrueVals>
+void random_access_iterator_test(Iterator i, int N, TrueVals vals)
+{
+ bidirectional_iterator_test(i, vals[0], vals[1]);
+ const Iterator j = i;
+ int c;
+
+ typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
+
+ for (c = 0; c < N-1; ++c) {
+ assert(i == j + c);
+ assert(*i == vals[c]);
+ assert(*i == boost::implicit_cast<value_type>(j[c]));
+ assert(*i == *(j + c));
+ assert(*i == *(c + j));
+ ++i;
+ assert(i > j);
+ assert(i >= j);
+ assert(j <= i);
+ assert(j < i);
+ }
+
+ Iterator k = j + N - 1;
+ for (c = 0; c < N-1; ++c) {
+ assert(i == k - c);
+ assert(*i == vals[N - 1 - c]);
+ assert(*i == boost::implicit_cast<value_type>(j[N - 1 - c]));
+ Iterator q = k - c;
+ assert(*i == *q);
+ assert(i > j);
+ assert(i >= j);
+ assert(j <= i);
+ assert(j < i);
+ --i;
+ }
+}
+
+// Precondition: i != j
+template <class Iterator, class ConstIterator>
+void const_nonconst_iterator_test(Iterator i, ConstIterator j)
+{
+ assert(i != j);
+ assert(j != i);
+
+ ConstIterator k(i);
+ assert(k == i);
+ assert(i == k);
+
+ k = i;
+ assert(k == i);
+ assert(i == k);
+}
+
+} // namespace boost
+
+#endif // BOOST_ITERATOR_TESTS_HPP
--- /dev/null
+// -------------------------------------
+// lowest_bit.hpp
+//
+// Position of the lowest bit 'on'
+//
+// (C) Copyright Gennaro Prota 2003 - 2004.
+//
+// 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)
+//
+// ------------------------------------------------------
+//
+// $Id: lowest_bit.hpp 41369 2007-11-25 18:07:19Z bemandawes $
+
+#ifndef BOOST_LOWEST_BIT_HPP_GP_20030301
+#define BOOST_LOWEST_BIT_HPP_GP_20030301
+
+#include <assert.h>
+#include "boost/pending/integer_log2.hpp"
+
+
+namespace boost {
+
+ template <typename T>
+ int lowest_bit(T x) {
+
+ assert(x >= 1); // PRE
+
+ // clear all bits on except the rightmost one,
+ // then calculate the logarithm base 2
+ //
+ return boost::integer_log2<T>( x - ( x & (x-1) ) );
+
+ }
+
+
+}
+
+
+#endif // include guard
--- /dev/null
+//
+//=======================================================================
+// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
+// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
+//
+// 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_GRAPH_DETAIL_MUTABLE_HEAP_H
+#define BOOST_GRAPH_DETAIL_MUTABLE_HEAP_H
+
+/*
+ There are a few things wrong with this set of functions.
+
+ ExternalData should be removed, it is not part of the core
+ algorithm. It can be handled inside the tree nodes.
+
+ The swap() should be replaced by assignment since its use is causing
+ the number of memory references to double.
+
+ The min_element should be replaced by a fixed length loop
+ (fixed at d for d-heaps).
+
+ The member functions of TreeNode should be changed to global
+ functions.
+
+ These functions will be replaced by those in heap_tree.h
+
+ */
+
+namespace boost {
+
+ template <class TreeNode, class Compare, class ExternalData>
+ inline TreeNode up_heap(TreeNode x, const Compare& comp, ExternalData& edata) {
+ while (x.has_parent() && comp(x, x.parent()))
+ x.swap(x.parent(), edata);
+ return x;
+ }
+
+ template <class TreeNode, class Compare, class ExternalData>
+ inline TreeNode down_heap(TreeNode x, const Compare& comp, ExternalData& edata) {
+ while (x.children().size() > 0) {
+ typename TreeNode::children_type::iterator
+ child_iter = std::min_element(x.children().begin(),
+ x.children().end(),
+ comp);
+ if (comp(*child_iter, x))
+ x.swap(*child_iter, edata);
+ else
+ break;
+ }
+ return x;
+ }
+
+ template <class TreeNode, class Compare, class ExternalData>
+ inline void update_heap(TreeNode x, const Compare& comp, ExternalData& edata) {
+ x = down_heap(x, comp, edata);
+ (void)up_heap(x, comp, edata);
+ }
+
+}
+#endif
--- /dev/null
+//
+//=======================================================================
+// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
+// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
+//
+// 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_MUTABLE_QUEUE_HPP
+#define BOOST_MUTABLE_QUEUE_HPP
+
+#include <vector>
+#include <algorithm>
+#include <functional>
+#include <boost/property_map.hpp>
+#include <boost/pending/mutable_heap.hpp>
+#include <boost/pending/is_heap.hpp>
+#include <boost/graph/detail/array_binary_tree.hpp>
+#include <iterator>
+
+namespace boost {
+
+ // The mutable queue whose elements are indexed
+ //
+ // This adaptor provides a special kind of priority queue that has
+ // and update operation. This allows the ordering of the items to
+ // change. After the ordering criteria for item x changes, one must
+ // call the Q.update(x)
+ //
+ // In order to efficiently find x in the queue, a functor must be
+ // provided to map value_type to a unique ID, which the
+ // mutable_queue will then use to map to the location of the
+ // item. The ID's generated must be between 0 and N, where N is the
+ // value passed to the constructor of mutable_queue
+
+ template <class IndexedType,
+ class RandomAccessContainer = std::vector<IndexedType>,
+ class Comp = std::less<typename RandomAccessContainer::value_type>,
+ class ID = identity_property_map >
+ class mutable_queue {
+ public:
+ typedef IndexedType value_type;
+ typedef typename RandomAccessContainer::size_type size_type;
+ protected:
+ typedef typename RandomAccessContainer::iterator iterator;
+#if !defined BOOST_NO_STD_ITERATOR_TRAITS
+ typedef adstl::array_binary_tree_node<iterator, ID> Node;
+#else
+ typedef adstl::array_binary_tree_node<iterator, value_type, ID> Node;
+#endif
+ typedef adstl::compare_array_node<RandomAccessContainer,Comp> Compare;
+ typedef std::vector<size_type> IndexArray;
+ public:
+ typedef Compare value_compare;
+ typedef ID id_generator;
+
+ mutable_queue(size_type n, const Comp& x, const ID& _id)
+ : index_array(n), comp(x), id(_id) {
+ c.reserve(n);
+ }
+ template <class ForwardIterator>
+ mutable_queue(ForwardIterator first, ForwardIterator last,
+ const Comp& x, const ID& _id)
+ : index_array(std::distance(first, last)), comp(x), id(_id)
+ {
+ while( first != last ) {
+ push(*first);
+ ++first;
+ }
+ }
+
+ bool empty() const { return c.empty(); }
+
+ void pop() {
+ value_type tmp = c.back();
+ c.back() = c.front();
+ c.front() = tmp;
+
+ size_type id_f = get(id, c.back());
+ size_type id_b = get(id, tmp);
+ size_type i = index_array[ id_b ];
+ index_array[ id_b ] = index_array[ id_f ];
+ index_array[ id_f ] = i;
+
+ c.pop_back();
+ Node node(c.begin(), c.end(), c.begin(), id);
+ down_heap(node, comp, index_array);
+ }
+ void push(const IndexedType& x) {
+ c.push_back(x);
+ /*set index-array*/
+ index_array[ get(id, x) ] = c.size()-1;
+ Node node(c.begin(), c.end(), c.end() - 1, id);
+ up_heap(node, comp, index_array);
+ }
+
+ void update(const IndexedType& x) {
+ size_type current_pos = index_array[ get(id, x) ];
+ c[current_pos] = x;
+
+ Node node(c.begin(), c.end(), c.begin()+current_pos, id);
+ update_heap(node, comp, index_array);
+ }
+
+ value_type& front() { return c.front(); }
+ value_type& top() { return c.front(); }
+
+ const value_type& front() const { return c.front(); }
+ const value_type& top() const { return c.front(); }
+
+ size_type size() const { return c.size(); }
+
+ void clear() { c.clear(); }
+
+#if 0
+ // dwa 2003/7/11 - I don't know what compiler is supposed to
+ // be able to compile this, but is_heap is not standard!!
+ bool test() {
+ return std::is_heap(c.begin(), c.end(), Comp());
+ }
+#endif
+
+ protected:
+ IndexArray index_array;
+ Compare comp;
+ RandomAccessContainer c;
+ ID id;
+ };
+
+
+}
+
+#endif // BOOST_MUTABLE_QUEUE_HPP
--- /dev/null
+// (C) Copyright Jeremy Siek 2004
+// 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_PROPERTY_HPP
+#define BOOST_PROPERTY_HPP
+
+#include <boost/pending/ct_if.hpp>
+
+namespace boost {
+
+ struct no_property {
+ typedef no_property tag_type;
+ typedef no_property next_type;
+ typedef no_property value_type;
+ enum { num = 0 };
+ typedef void kind;
+ };
+
+ template <class Tag, class T, class Base = no_property>
+ struct property : public Base {
+ typedef Base next_type;
+ typedef Tag tag_type;
+ typedef T value_type;
+#if BOOST_WORKAROUND (__GNUC__, < 3)
+ property() { }
+#else
+ property() : m_value() { }
+#endif
+ property(const T& v) : m_value(v) { }
+ property(const T& v, const Base& b) : Base(b), m_value(v) { }
+ // copy constructor and assignment operator will be generated by compiler
+
+ T m_value;
+ };
+
+ // The BGL properties specialize property_kind and
+ // property_num, and use enum's for the Property type (see
+ // graph/properties.hpp), but the user may want to use a class
+ // instead with a nested kind type and num. Also, we may want to
+ // switch BGL back to using class types for properties at some point.
+
+ template <class PropertyTag>
+ struct property_kind {
+ typedef typename PropertyTag::kind type;
+ };
+
+ template <class P>
+ struct has_property {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ typedef true_type type;
+ };
+ template <>
+ struct has_property<no_property> {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+ typedef false_type type;
+ };
+
+} // namespace boost
+
+#include <boost/pending/detail/property.hpp>
+
+namespace boost {
+
+ template <class PropertyList, class Tag>
+ struct property_value {
+#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ typedef typename detail::build_property_tag_value_alist<PropertyList>::type AList;
+ typedef typename detail::extract_value<AList,Tag>::type type;
+#else
+ typedef typename detail::build_property_tag_value_alist<PropertyList>::type AList;
+ typedef typename detail::ev_selector<AList>::type Extractor;
+ typedef typename Extractor::template bind_<AList,Tag>::type type;
+#endif
+ };
+
+ template <class Tag1, class Tag2, class T1, class Base>
+ inline typename property_value<property<Tag1,T1,Base>, Tag2>::type&
+ get_property_value(property<Tag1,T1,Base>& p, Tag2 tag2) {
+ BOOST_STATIC_CONSTANT(bool,
+ match = (detail::same_property<Tag1,Tag2>::value));
+ typedef property<Tag1,T1,Base> Prop;
+ typedef typename property_value<Prop, Tag2>::type T2;
+ T2* t2 = 0;
+ typedef detail::property_value_dispatch<match> Dispatcher;
+ return Dispatcher::get_value(p, t2, tag2);
+ }
+ template <class Tag1, class Tag2, class T1, class Base>
+ inline
+ const typename property_value<property<Tag1,T1,Base>, Tag2>::type&
+ get_property_value(const property<Tag1,T1,Base>& p, Tag2 tag2) {
+ BOOST_STATIC_CONSTANT(bool,
+ match = (detail::same_property<Tag1,Tag2>::value));
+ typedef property<Tag1,T1,Base> Prop;
+ typedef typename property_value<Prop, Tag2>::type T2;
+ T2* t2 = 0;
+ typedef detail::property_value_dispatch<match> Dispatcher;
+ return Dispatcher::const_get_value(p, t2, tag2);
+ }
+
+ namespace detail {
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+ template<typename FinalTag, typename FinalType>
+ struct retag_property_list
+ {
+ typedef property<FinalTag, FinalType> type;
+ typedef FinalType retagged;
+ };
+
+ template<typename FinalTag, typename Tag, typename T, typename Base>
+ struct retag_property_list<FinalTag, property<Tag, T, Base> >
+ {
+ private:
+ typedef retag_property_list<FinalTag, Base> next;
+
+ public:
+ typedef property<Tag, T, typename next::type> type;
+ typedef typename next::retagged retagged;
+ };
+
+ template<typename FinalTag>
+ struct retag_property_list<FinalTag, no_property>
+ {
+ typedef no_property type;
+ typedef no_property retagged;
+ };
+#endif
+ }
+} // namesapce boost
+
+#endif /* BOOST_PROPERTY_HPP */
--- /dev/null
+// (C) Copyright Jeremy Siek 2006
+// 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_PROPERTY_SERIALIZE_HPP
+#define BOOST_PROPERTY_SERIALIZE_HPP
+
+#include <boost/pending/property.hpp>
+
+#include <boost/serialization/base_object.hpp>
+#include <boost/serialization/nvp.hpp>
+
+namespace boost {
+ template<class Archive>
+ inline void serialize(Archive&, no_property&, const unsigned int) { }
+
+ template<class Archive, class Tag, class T, class Base>
+ void
+ serialize(Archive& ar, property<Tag, T, Base>& prop,
+ const unsigned int version)
+ {
+ ar & serialization::make_nvp( "property_base" , boost::serialization::base_object<Base>(prop) );
+ ar & serialization::make_nvp( "property_value" , prop.m_value );
+ }
+} // end namespace boost
+
+#endif // BOOST_PROPERTY_SERIALIZE_HPP
--- /dev/null
+// (C) Copyright Jeremy Siek 2004
+// 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_QUEUE_HPP
+#define BOOST_QUEUE_HPP
+
+#include <deque>
+#include <algorithm>
+
+namespace boost {
+
+template <class _Tp,
+ class _Sequence = std::deque<_Tp> >
+class queue;
+
+template <class _Tp, class _Seq>
+inline bool operator==(const queue<_Tp, _Seq>&, const queue<_Tp, _Seq>&);
+
+template <class _Tp, class _Seq>
+inline bool operator<(const queue<_Tp, _Seq>&, const queue<_Tp, _Seq>&);
+
+
+template <class _Tp, class _Sequence>
+class queue {
+
+#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+ template <class _Tp1, class _Seq1>
+ friend bool operator== (const queue<_Tp1, _Seq1>&,
+ const queue<_Tp1, _Seq1>&);
+ template <class _Tp1, class _Seq1>
+ friend bool operator< (const queue<_Tp1, _Seq1>&,
+ const queue<_Tp1, _Seq1>&);
+#endif
+public:
+ typedef typename _Sequence::value_type value_type;
+ typedef typename _Sequence::size_type size_type;
+ typedef _Sequence container_type;
+
+ typedef typename _Sequence::reference reference;
+ typedef typename _Sequence::const_reference const_reference;
+#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+protected:
+#endif
+ _Sequence c;
+public:
+ queue() : c() {}
+ explicit queue(const _Sequence& __c) : c(__c) {}
+
+ bool empty() const { return c.empty(); }
+ size_type size() const { return c.size(); }
+ reference front() { return c.front(); }
+ const_reference front() const { return c.front(); }
+ reference top() { return c.front(); }
+ const_reference top() const { return c.front(); }
+ reference back() { return c.back(); }
+ const_reference back() const { return c.back(); }
+ void push(const value_type& __x) { c.push_back(__x); }
+ void pop() { c.pop_front(); }
+
+ void swap(queue& other)
+ {
+ using std::swap;
+ swap(c, other.c);
+ }
+};
+
+template <class _Tp, class _Sequence>
+bool
+operator==(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y)
+{
+ return __x.c == __y.c;
+}
+
+template <class _Tp, class _Sequence>
+bool
+operator<(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y)
+{
+ return __x.c < __y.c;
+}
+
+template <class _Tp, class _Sequence>
+bool
+operator!=(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y)
+{
+ return !(__x == __y);
+}
+
+template <class _Tp, class _Sequence>
+bool
+operator>(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y)
+{
+ return __y < __x;
+}
+
+template <class _Tp, class _Sequence>
+bool
+operator<=(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y)
+{
+ return !(__y < __x);
+}
+
+template <class _Tp, class _Sequence>
+bool
+operator>=(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y)
+{
+ return !(__x < __y);
+}
+
+template <class _Tp, class _Sequence>
+inline void
+swap(queue<_Tp, _Sequence>& __x, queue<_Tp, _Sequence>& __y)
+{ __x.swap(__y); }
+
+} /* namespace boost */
+
+#endif /* BOOST_QUEUE_HPP */
--- /dev/null
+// Copyright 2004 The Trustees of Indiana University.
+
+// Use, modification and distribution is subject to 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)
+
+// Authors: Douglas Gregor
+// Andrew Lumsdaine
+#ifndef BOOST_RELAXED_HEAP_HEADER
+#define BOOST_RELAXED_HEAP_HEADER
+
+#include <functional>
+#include <boost/property_map.hpp>
+#include <boost/optional.hpp>
+#include <vector>
+#include <climits> // for CHAR_BIT
+#include <boost/none.hpp>
+
+#ifdef BOOST_RELAXED_HEAP_DEBUG
+# include <iostream>
+#endif // BOOST_RELAXED_HEAP_DEBUG
+
+#if defined(BOOST_MSVC)
+# pragma warning(push)
+# pragma warning(disable:4355) // complaint about using 'this' to
+#endif // initialize a member
+
+namespace boost {
+
+template<typename IndexedType,
+ typename Compare = std::less<IndexedType>,
+ typename ID = identity_property_map>
+class relaxed_heap
+{
+ struct group;
+
+ typedef relaxed_heap self_type;
+ typedef std::size_t rank_type;
+
+public:
+ typedef IndexedType value_type;
+ typedef rank_type size_type;
+
+private:
+ /**
+ * The kind of key that a group has. The actual values are discussed
+ * in-depth in the documentation of the @c kind field of the @c group
+ * structure. Note that the order of the enumerators *IS* important
+ * and must not be changed.
+ */
+ enum group_key_kind { smallest_key, stored_key, largest_key };
+
+ struct group {
+ explicit group(group_key_kind kind = largest_key)
+ : kind(kind), parent(this), rank(0) { }
+
+ /** The value associated with this group. This value is only valid
+ * when @c kind!=largest_key (which indicates a deleted
+ * element). Note that the use of boost::optional increases the
+ * memory requirements slightly but does not result in extraneous
+ * memory allocations or deallocations. The optional could be
+ * eliminated when @c value_type is a model of
+ * DefaultConstructible.
+ */
+ ::boost::optional<value_type> value;
+
+ /**
+ * The kind of key stored at this group. This may be @c
+ * smallest_key, which indicates that the key is infinitely small;
+ * @c largest_key, which indicates that the key is infinitely
+ * large; or @c stored_key, which means that the key is unknown,
+ * but its relationship to other keys can be determined via the
+ * comparison function object.
+ */
+ group_key_kind kind;
+
+ /// The parent of this group. Will only be NULL for the dummy root group
+ group* parent;
+
+ /// The rank of this group. Equivalent to the number of children in
+ /// the group.
+ rank_type rank;
+
+ /** The children of this group. For the dummy root group, these are
+ * the roots. This is an array of length log n containing pointers
+ * to the child groups.
+ */
+ group** children;
+ };
+
+ size_type log_base_2(size_type n) // log2 is a macro on some platforms
+ {
+ size_type leading_zeroes = 0;
+ do {
+ size_type next = n << 1;
+ if (n == (next >> 1)) {
+ ++leading_zeroes;
+ n = next;
+ } else {
+ break;
+ }
+ } while (true);
+ return sizeof(size_type) * CHAR_BIT - leading_zeroes - 1;
+ }
+
+public:
+ relaxed_heap(size_type n, const Compare& compare = Compare(),
+ const ID& id = ID())
+ : compare(compare), id(id), root(smallest_key), groups(n),
+ smallest_value(0)
+ {
+ if (n == 0) {
+ root.children = new group*[1];
+ return;
+ }
+
+ log_n = log_base_2(n);
+ if (log_n == 0) log_n = 1;
+ size_type g = n / log_n;
+ if (n % log_n > 0) ++g;
+ size_type log_g = log_base_2(g);
+ size_type r = log_g;
+
+ // Reserve an appropriate amount of space for data structures, so
+ // that we do not need to expand them.
+ index_to_group.resize(g);
+ A.resize(r + 1, 0);
+ root.rank = r + 1;
+ root.children = new group*[(log_g + 1) * (g + 1)];
+ for (rank_type i = 0; i < r+1; ++i) root.children[i] = 0;
+
+ // Build initial heap
+ size_type idx = 0;
+ while (idx < g) {
+ root.children[r] = &index_to_group[idx];
+ idx = build_tree(root, idx, r, log_g + 1);
+ if (idx != g)
+ r = static_cast<size_type>(log_base_2(g-idx));
+ }
+ }
+
+ ~relaxed_heap() { delete [] root.children; }
+
+ void push(const value_type& x)
+ {
+ groups[get(id, x)] = x;
+ update(x);
+ }
+
+ void update(const value_type& x)
+ {
+ group* a = &index_to_group[get(id, x) / log_n];
+ if (!a->value
+ || *a->value == x
+ || compare(x, *a->value)) {
+ if (a != smallest_value) smallest_value = 0;
+ a->kind = stored_key;
+ a->value = x;
+ promote(a);
+ }
+ }
+
+ void remove(const value_type& x)
+ {
+ group* a = &index_to_group[get(id, x) / log_n];
+ assert(groups[get(id, x)] != 0);
+ a->value = x;
+ a->kind = smallest_key;
+ promote(a);
+ smallest_value = a;
+ pop();
+ }
+
+ value_type& top()
+ {
+ find_smallest();
+ assert(smallest_value->value != none);
+ return *smallest_value->value;
+ }
+
+ const value_type& top() const
+ {
+ find_smallest();
+ assert(smallest_value->value != none);
+ return *smallest_value->value;
+ }
+
+ bool empty() const
+ {
+ find_smallest();
+ return !smallest_value || (smallest_value->kind == largest_key);
+ }
+
+ bool contains(const value_type& x) const { return groups[get(id, x)]; }
+
+ void pop()
+ {
+ // Fill in smallest_value. This is the group x.
+ find_smallest();
+ group* x = smallest_value;
+ smallest_value = 0;
+
+ // Make x a leaf, giving it the smallest value within its group
+ rank_type r = x->rank;
+ group* p = x->parent;
+ {
+ assert(x->value != none);
+
+ // Find x's group
+ size_type start = get(id, *x->value) - get(id, *x->value) % log_n;
+ size_type end = start + log_n;
+ if (end > groups.size()) end = groups.size();
+
+ // Remove the smallest value from the group, and find the new
+ // smallest value.
+ groups[get(id, *x->value)].reset();
+ x->value.reset();
+ x->kind = largest_key;
+ for (size_type i = start; i < end; ++i) {
+ if (groups[i] && (!x->value || compare(*groups[i], *x->value))) {
+ x->kind = stored_key;
+ x->value = groups[i];
+ }
+ }
+ }
+ x->rank = 0;
+
+ // Combine prior children of x with x
+ group* y = x;
+ for (size_type c = 0; c < r; ++c) {
+ group* child = x->children[c];
+ if (A[c] == child) A[c] = 0;
+ y = combine(y, child);
+ }
+
+ // If we got back something other than x, let y take x's place
+ if (y != x) {
+ y->parent = p;
+ p->children[r] = y;
+
+ assert(r == y->rank);
+ if (A[y->rank] == x)
+ A[y->rank] = do_compare(y, p)? y : 0;
+ }
+ }
+
+#ifdef BOOST_RELAXED_HEAP_DEBUG
+ /*************************************************************************
+ * Debugging support *
+ *************************************************************************/
+ void dump_tree() { dump_tree(std::cout); }
+ void dump_tree(std::ostream& out) { dump_tree(out, &root); }
+
+ void dump_tree(std::ostream& out, group* p, bool in_progress = false)
+ {
+ if (!in_progress) {
+ out << "digraph heap {\n"
+ << " edge[dir=\"back\"];\n";
+ }
+
+ size_type p_index = 0;
+ if (p != &root) while (&index_to_group[p_index] != p) ++p_index;
+
+ for (size_type i = 0; i < p->rank; ++i) {
+ group* c = p->children[i];
+ if (c) {
+ size_type c_index = 0;
+ if (c != &root) while (&index_to_group[c_index] != c) ++c_index;
+
+ out << " ";
+ if (p == &root) out << 'p'; else out << p_index;
+ out << " -> ";
+ if (c == &root) out << 'p'; else out << c_index;
+ if (A[c->rank] == c) out << " [style=\"dotted\"]";
+ out << ";\n";
+ dump_tree(out, c, true);
+
+ // Emit node information
+ out << " ";
+ if (c == &root) out << 'p'; else out << c_index;
+ out << " [label=\"";
+ if (c == &root) out << 'p'; else out << c_index;
+ out << ":";
+ size_type start = c_index * log_n;
+ size_type end = start + log_n;
+ if (end > groups.size()) end = groups.size();
+ while (start != end) {
+ if (groups[start]) {
+ out << " " << get(id, *groups[start]);
+ if (*groups[start] == *c->value) out << "(*)";
+ }
+ ++start;
+ }
+ out << '"';
+
+ if (do_compare(c, p)) {
+ out << " ";
+ if (c == &root) out << 'p'; else out << c_index;
+ out << ", style=\"filled\", fillcolor=\"gray\"";
+ }
+ out << "];\n";
+ } else {
+ assert(p->parent == p);
+ }
+ }
+ if (!in_progress) out << "}\n";
+ }
+
+ bool valid()
+ {
+ // Check that the ranks in the A array match the ranks of the
+ // groups stored there. Also, the active groups must be the last
+ // child of their parent.
+ for (size_type r = 0; r < A.size(); ++r) {
+ if (A[r] && A[r]->rank != r) return false;
+
+ if (A[r] && A[r]->parent->children[A[r]->parent->rank-1] != A[r])
+ return false;
+ }
+
+ // The root must have no value and a key of -Infinity
+ if (root.kind != smallest_key) return false;
+
+ return valid(&root);
+ }
+
+ bool valid(group* p)
+ {
+ for (size_type i = 0; i < p->rank; ++i) {
+ group* c = p->children[i];
+ if (c) {
+ // Check link structure
+ if (c->parent != p) return false;
+ if (c->rank != i) return false;
+
+ // A bad group must be active
+ if (do_compare(c, p) && A[i] != c) return false;
+
+ // Check recursively
+ if (!valid(c)) return false;
+ } else {
+ // Only the root may
+ if (p != &root) return false;
+ }
+ }
+ return true;
+ }
+
+#endif // BOOST_RELAXED_HEAP_DEBUG
+
+private:
+ size_type
+ build_tree(group& parent, size_type idx, size_type r, size_type max_rank)
+ {
+ group& this_group = index_to_group[idx];
+ this_group.parent = &parent;
+ ++idx;
+
+ this_group.children = root.children + (idx * max_rank);
+ this_group.rank = r;
+ for (size_type i = 0; i < r; ++i) {
+ this_group.children[i] = &index_to_group[idx];
+ idx = build_tree(this_group, idx, i, max_rank);
+ }
+ return idx;
+ }
+
+ void find_smallest() const
+ {
+ group** roots = root.children;
+
+ if (!smallest_value) {
+ std::size_t i;
+ for (i = 0; i < root.rank; ++i) {
+ if (roots[i] &&
+ (!smallest_value || do_compare(roots[i], smallest_value))) {
+ smallest_value = roots[i];
+ }
+ }
+ for (i = 0; i < A.size(); ++i) {
+ if (A[i] && (!smallest_value || do_compare(A[i], smallest_value)))
+ smallest_value = A[i];
+ }
+ }
+ }
+
+ bool do_compare(group* x, group* y) const
+ {
+ return (x->kind < y->kind
+ || (x->kind == y->kind
+ && x->kind == stored_key
+ && compare(*x->value, *y->value)));
+ }
+
+ void promote(group* a)
+ {
+ assert(a != 0);
+ rank_type r = a->rank;
+ group* p = a->parent;
+ assert(p != 0);
+ if (do_compare(a, p)) {
+ // s is the rank + 1 sibling
+ group* s = p->rank > r + 1? p->children[r + 1] : 0;
+
+ // If a is the last child of p
+ if (r == p->rank - 1) {
+ if (!A[r]) A[r] = a;
+ else if (A[r] != a) pair_transform(a);
+ } else {
+ assert(s != 0);
+ if (A[r + 1] == s) active_sibling_transform(a, s);
+ else good_sibling_transform(a, s);
+ }
+ }
+ }
+
+ group* combine(group* a1, group* a2)
+ {
+ assert(a1->rank == a2->rank);
+ if (do_compare(a2, a1)) do_swap(a1, a2);
+ a1->children[a1->rank++] = a2;
+ a2->parent = a1;
+ clean(a1);
+ return a1;
+ }
+
+ void clean(group* q)
+ {
+ if (2 > q->rank) return;
+ group* qp = q->children[q->rank-1];
+ rank_type s = q->rank - 2;
+ group* x = q->children[s];
+ group* xp = qp->children[s];
+ assert(s == x->rank);
+
+ // If x is active, swap x and xp
+ if (A[s] == x) {
+ q->children[s] = xp;
+ xp->parent = q;
+ qp->children[s] = x;
+ x->parent = qp;
+ }
+ }
+
+ void pair_transform(group* a)
+ {
+#if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1
+ std::cerr << "- pair transform\n";
+#endif
+ rank_type r = a->rank;
+
+ // p is a's parent
+ group* p = a->parent;
+ assert(p != 0);
+
+ // g is p's parent (a's grandparent)
+ group* g = p->parent;
+ assert(g != 0);
+
+ // a' <- A(r)
+ assert(A[r] != 0);
+ group* ap = A[r];
+ assert(ap != 0);
+
+ // A(r) <- nil
+ A[r] = 0;
+
+ // let a' have parent p'
+ group* pp = ap->parent;
+ assert(pp != 0);
+
+ // let a' have grandparent g'
+ group* gp = pp->parent;
+ assert(gp != 0);
+
+ // Remove a and a' from their parents
+ assert(ap == pp->children[pp->rank-1]); // Guaranteed because ap is active
+ --pp->rank;
+
+ // Guaranteed by caller
+ assert(a == p->children[p->rank-1]);
+ --p->rank;
+
+ // Note: a, ap, p, pp all have rank r
+ if (do_compare(pp, p)) {
+ do_swap(a, ap);
+ do_swap(p, pp);
+ do_swap(g, gp);
+ }
+
+ // Assuming k(p) <= k(p')
+ // make p' the rank r child of p
+ assert(r == p->rank);
+ p->children[p->rank++] = pp;
+ pp->parent = p;
+
+ // Combine a, ap into a rank r+1 group c
+ group* c = combine(a, ap);
+
+ // make c the rank r+1 child of g'
+ assert(gp->rank > r+1);
+ gp->children[r+1] = c;
+ c->parent = gp;
+
+#if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1
+ std::cerr << "After pair transform...\n";
+ dump_tree();
+#endif
+
+ if (A[r+1] == pp) A[r+1] = c;
+ else promote(c);
+ }
+
+ void active_sibling_transform(group* a, group* s)
+ {
+#if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1
+ std::cerr << "- active sibling transform\n";
+#endif
+ group* p = a->parent;
+ group* g = p->parent;
+
+ // remove a, s from their parents
+ assert(s->parent == p);
+ assert(p->children[p->rank-1] == s);
+ --p->rank;
+ assert(p->children[p->rank-1] == a);
+ --p->rank;
+
+ rank_type r = a->rank;
+ A[r+1] = 0;
+ a = combine(p, a);
+ group* c = combine(a, s);
+
+ // make c the rank r+2 child of g
+ assert(g->children[r+2] == p);
+ g->children[r+2] = c;
+ c->parent = g;
+ if (A[r+2] == p) A[r+2] = c;
+ else promote(c);
+ }
+
+ void good_sibling_transform(group* a, group* s)
+ {
+#if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1
+ std::cerr << "- good sibling transform\n";
+#endif
+ rank_type r = a->rank;
+ group* c = s->children[s->rank-1];
+ assert(c->rank == r);
+ if (A[r] == c) {
+#if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1
+ std::cerr << "- good sibling pair transform\n";
+#endif
+ A[r] = 0;
+ group* p = a->parent;
+
+ // Remove c from its parent
+ --s->rank;
+
+ // Make s the rank r child of p
+ s->parent = p;
+ p->children[r] = s;
+
+ // combine a, c and let the result by the rank r+1 child of p
+ assert(p->rank > r+1);
+ group* x = combine(a, c);
+ x->parent = p;
+ p->children[r+1] = x;
+
+ if (A[r+1] == s) A[r+1] = x;
+ else promote(x);
+
+#if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1
+ dump_tree(std::cerr);
+#endif
+ // pair_transform(a);
+ } else {
+ // Clean operation
+ group* p = a->parent;
+ s->children[r] = a;
+ a->parent = s;
+ p->children[r] = c;
+ c->parent = p;
+
+ promote(a);
+ }
+ }
+
+ static void do_swap(group*& x, group*& y)
+ {
+ group* tmp = x;
+ x = y;
+ y = tmp;
+ }
+
+ /// Function object that compares two values in the heap
+ Compare compare;
+
+ /// Mapping from values to indices in the range [0, n).
+ ID id;
+
+ /** The root group of the queue. This group is special because it will
+ * never store a value, but it acts as a parent to all of the
+ * roots. Thus, its list of children is the list of roots.
+ */
+ group root;
+
+ /** Mapping from the group index of a value to the group associated
+ * with that value. If a value is not in the queue, then the "value"
+ * field will be empty.
+ */
+ std::vector<group> index_to_group;
+
+ /** Flat data structure containing the values in each of the
+ * groups. It will be indexed via the id of the values. The groups
+ * are each log_n long, with the last group potentially being
+ * smaller.
+ */
+ std::vector< ::boost::optional<value_type> > groups;
+
+ /** The list of active groups, indexed by rank. When A[r] is null,
+ * there is no active group of rank r. Otherwise, A[r] is the active
+ * group of rank r.
+ */
+ std::vector<group*> A;
+
+ /** The group containing the smallest value in the queue, which must
+ * be either a root or an active group. If this group is null, then we
+ * will need to search for this group when it is needed.
+ */
+ mutable group* smallest_value;
+
+ /// Cached value log_base_2(n)
+ size_type log_n;
+};
+
+
+} // end namespace boost
+
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
+#endif // BOOST_RELAXED_HEAP_HEADER
--- /dev/null
+// (C) Copyright Jeremy Siek 2004
+// 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_STRINGTOK_HPP
+#define BOOST_STRINGTOK_HPP
+
+/*
+ * stringtok.hpp -- Breaks a string into tokens. This is an example for lib3.
+ *
+ * Template function looks like this:
+ *
+ * template <typename Container>
+ * void stringtok (Container &l,
+ * string const &s,
+ * char const * const ws = " \t\n");
+ *
+ * A nondestructive version of strtok() that handles its own memory and can
+ * be broken up by any character(s). Does all the work at once rather than
+ * in an invocation loop like strtok() requires.
+ *
+ * Container is any type that supports push_back(a_string), although using
+ * list<string> and deque<string> are indicated due to their O(1) push_back.
+ * (I prefer deque<> because op[]/at() is available as well.) The first
+ * parameter references an existing Container.
+ *
+ * s is the string to be tokenized. From the parameter declaration, it can
+ * be seen that s is not affected. Since references-to-const may refer to
+ * temporaries, you could use stringtok(some_container, readline("")) when
+ * using the GNU readline library.
+ *
+ * The final parameter is an array of characters that serve as whitespace.
+ * Whitespace characters default to one or more of tab, space, and newline,
+ * in any combination.
+ *
+ * 'l' need not be empty on entry. On return, 'l' will have the token
+ * strings appended.
+ *
+ *
+ * [Example:
+ * list<string> ls;
+ * stringtok (ls, " this \t is\t\n a test ");
+ * for (list<string>::const_iterator i = ls.begin();
+ * i != ls.end(); ++i)
+ * {
+ * cerr << ':' << (*i) << ":\n";
+ * }
+ *
+ * would print
+ * :this:
+ * :is:
+ * :a:
+ * :test:
+ * -end example]
+ *
+ * pedwards@jaj.com May 1999
+*/
+
+
+#include <string>
+#include <cstring> // for strchr
+
+
+/*****************************************************************
+ * This is the only part of the implementation that I don't like.
+ * It can probably be improved upon by the reader...
+*/
+
+ inline bool
+ isws (char c, char const * const wstr)
+ {
+ using namespace std;
+ return (strchr(wstr,c) != NULL);
+ }
+
+
+namespace boost {
+
+/*****************************************************************
+ * Simplistic and quite Standard, but a bit slow. This should be
+ * templatized on basic_string instead, or on a more generic StringT
+ * that just happens to support ::size_type, .substr(), and so on.
+ * I had hoped that "whitespace" would be a trait, but it isn't, so
+ * the user must supply it. Enh, this lets them break up strings on
+ * different things easier than traits would anyhow.
+*/
+template <typename Container>
+void
+stringtok (Container &l, std::string const &s, char const * const ws = " \t\n")
+{
+ typedef std::string::size_type size_type;
+ const size_type S = s.size();
+ size_type i = 0;
+
+ while (i < S) {
+ // eat leading whitespace
+ while ((i < S) && (isws(s[i],ws))) ++i;
+ if (i == S) return; // nothing left but WS
+
+ // find end of word
+ size_type j = i+1;
+ while ((j < S) && (!isws(s[j],ws))) ++j;
+
+ // add word
+ l.push_back(s.substr(i,j-i));
+
+ // set up for next loop
+ i = j+1;
+ }
+}
+
+
+} // namespace boost
+
+#endif // BOOST_STRINGTOK_HPP