include/orderlist.hpp
author Dmitriy Morozov <morozov@cs.duke.edu>
Sat, 16 Dec 2006 15:34:46 -0500
changeset 4 c1be260ad990
parent 0 d95020656286
child 5 ee9052408c40
permissions -rw-r--r--
Split OrderList into OrderList and ConsistencyList. Made efficient insertions possible.

/* Implementations */

template<class T>
void 
OrderList<T>::
swap(iterator i, iterator j)
{
	typename Parent::iterator i_base = i.get_base();
	typename Parent::iterator j_base = j.get_base();
	std::swap(i_base->tag, j_base->tag);

	// Exchange the actual elements in the list --- so that iterators behave as expected
	typename Parent::iterator after_j = boost::next(j_base);	
	Parent::splice(i_base, *this, j_base);
	Parent::splice(after_j, *this, i_base);
}

template<class T>
typename OrderList<T>::iterator 
OrderList<T>::
push_back(const_reference x)
{
	if (empty()) 
		Parent::push_back(NodeType(x, 0));
	else
		Parent::push_back(NodeType(x, last().get_base()->tag + 1));
	
	return last();
}

template<class T>
typename OrderList<T>::iterator 
OrderList<T>::
insert(iterator p, const_reference x)
{
	typename Parent::iterator p_base = p.get_base();
	OrderType tag = (p_base++)->tag + 1;
	typename Parent::iterator new_base = Parent::insert(p_base, NodeType(x, tag));

	if (p_base->tag != tag)
		return iterator(new_base);

	// Find non-overflowing region
	unsigned int num_elements = 1, maximum = 1, lower = tag, upper = tag, level = 0;
	float inv_density = 1;
	typename Parent::iterator prev = p_base, next = p_base;
	--(--prev); ++next; 		// move prev back twice to skip over the newly inserted element

	do
	{
		lower &= ~(1 << level);
		upper |= (1 << level);
		maximum <<= 1; inv_density *= density_threshold;
		++level;

		while (prev != Parent::end() && prev->tag >= lower) { --prev; ++num_elements; }
		while (next != Parent::end() && next->tag <= upper) { ++next; ++num_elements; }
	} while (inv_density * num_elements >= maximum);
	++num_elements;			// for the extra element inserted

	Dout(dc::orderlist, num_elements << ", " << lower << ", " << upper);
	Dout(dc::orderlist, "prev is at the end: " << (prev == Parent::end()));
	Dout(dc::orderlist, "next is at the end: " << (next == Parent::end()));
	
	// Reorder
	AssertMsg((upper - lower + 1)/num_elements > 0, "Spacing between new tags must be non-zero");
	for (int i = 0; i < num_elements; ++i)
	{
		(++prev)->tag = lower + i*((upper - lower + 1)/num_elements);
		Dout(dc::orderlist, prev->tag);
		AssertMsg(prev->tag != 0 || prev == Parent::begin(), "Cannot assign 0 tag except at the beginning of OrderList");
	}

	AssertMsg(++prev == next, "prev + num_elements != next in OrderList::insert()");

	return iterator(new_base);
}

template<class T>
void
OrderList<T>::
show_elements() const
{
	for (const_iterator cur = begin(); cur != end(); ++cur)
		std::cout << *(cur.get_base()) << std::endl;
	std::cout << std::endl;
}

/* OrderComparison */
template<class T>
int 
OrderList<T>::OrderComparison::
compare(ComparableType a, ComparableType b) const
{
	if (a.get_base()->tag == b.get_base()->tag)			return 0;
	if (a.get_base()->tag < b.get_base()->tag)			return -1;
	return 1;
}